OpenCores
URL https://opencores.org/ocsvn/riscv_vhdl/riscv_vhdl/trunk

Subversion Repositories riscv_vhdl

[/] [riscv_vhdl/] [trunk/] [debugger/] [src/] [libdbg64g/] [services/] [elfloader/] [elfreader.cpp] - Blame information for rev 2

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 sergeykhbr
/**
2
 * @file
3
 * @copyright  Copyright 2016 GNSS Sensor Ltd. All right reserved.
4
 * @author     Sergey Khabarov - sergeykhbr@gmail.com
5
 * @brief      elf-file loader class implementation.
6
 */
7
 
8
#include "elfreader.h"
9
#include <iostream>
10
 
11
namespace debugger {
12
 
13
/** Class registration in the Core */
14
REGISTER_CLASS(ElfReaderService)
15
 
16
ElfReaderService::ElfReaderService(const char *name) : IService(name) {
17
    registerInterface(static_cast<IElfReader *>(this));
18
    image_ = NULL;
19
    sectionNames_ = NULL;
20
    symbolList_.make_list(0);
21
    loadSectionList_.make_list(0);
22
}
23
 
24
ElfReaderService::~ElfReaderService() {
25
    if (image_) {
26
        delete image_;
27
    }
28
}
29
 
30
void ElfReaderService::postinitService() {
31
}
32
 
33
int ElfReaderService::readFile(const char *filename) {
34
    FILE *fp = fopen(filename, "rb");
35
    if (!fp) {
36
        RISCV_error("File '%s' not found", filename);
37
        return -1;
38
    }
39
    fseek(fp, 0, SEEK_END);
40
    int sz = ftell(fp);
41
    rewind(fp);
42
 
43
    if (image_) {
44
        delete image_;
45
        sectionNames_ = NULL;
46
    }
47
    image_ = new uint8_t[sz];
48
    fread(image_, 1, sz, fp);
49
 
50
    if (readElfHeader() != 0) {
51
        fclose(fp);
52
        return 0;
53
    }
54
 
55
    if (!header_->e_shoff) {
56
        fclose(fp);
57
        return 0;
58
    }
59
 
60
    /** Init names */
61
    SectionHeaderType *sh;
62
    sh_tbl_ =
63
        reinterpret_cast<SectionHeaderType *>(&image_[header_->e_shoff]);
64
    for (int i = 0; i < header_->e_shnum; i++) {
65
        sh = &sh_tbl_[i];
66
        if (sh->sh_type == SHT_STRTAB) {
67
            processStringTable(sh);
68
        }
69
    }
70
 
71
    /** Direct loading via tap interface: */
72
    int bytes_loaded = loadSections();
73
    RISCV_info("Loaded: %d B", bytes_loaded);
74
 
75
    if (header_->e_phoff) {
76
        //readProgramHeader();
77
    }
78
 
79
    fclose(fp);
80
    return 0;
81
}
82
 
83
int ElfReaderService::readElfHeader() {
84
    header_ = reinterpret_cast<ElfHeaderType *>(image_);
85
    for (int i = 0; i < 4; i++) {
86
        if (header_->e_ident[i] != MAGIC_BYTES[i]) {
87
            RISCV_error("File format is not ELF", NULL);
88
            return -1;
89
        }
90
    }
91
    return 0;
92
}
93
 
94
int ElfReaderService::loadSections() {
95
    SectionHeaderType *sh;
96
    uint64_t total_bytes = 0;
97
    AttributeType tsymb;
98
 
99
    for (int i = 0; i < header_->e_shnum; i++) {
100
        sh = &sh_tbl_[i];
101
 
102
        if (sh->sh_size == 0) {
103
            continue;
104
        }
105
 
106
        if (sectionNames_ && (sh->sh_flags & SHF_ALLOC)) {
107
            RISCV_info("Reading '%s' section", &sectionNames_[sh->sh_name]);
108
        }
109
 
110
        if (sh->sh_type == SHT_PROGBITS && (sh->sh_flags & SHF_ALLOC) != 0) {
111
            /**
112
             * @brief   Instructions or other processor's information
113
             * @details This section holds information defined by the program,
114
             *          whose format and meaning are determined solely by the
115
             *          program.
116
             */
117
            AttributeType loadsec;
118
            loadsec.make_list(LoadSh_Total);
119
            if (sectionNames_) {
120
                loadsec[LoadSh_name].make_string(&sectionNames_[sh->sh_name]);
121
            } else {
122
                loadsec[LoadSh_name].make_string("unknown");
123
            }
124
            loadsec[LoadSh_addr].make_uint64(sh->sh_addr);
125
            loadsec[LoadSh_size].make_uint64(sh->sh_size);
126
            loadsec[LoadSh_data].make_data(static_cast<unsigned>(sh->sh_size),
127
                                           &image_[sh->sh_offset]);
128
            loadSectionList_.add_to_list(&loadsec);
129
            total_bytes += sh->sh_size;
130
        } else if (sh->sh_type == SHT_NOBITS
131
                    && (sh->sh_flags & SHF_ALLOC) != 0) {
132
            /**
133
             * @brief   Initialized data
134
             * @details A section of this type occupies no space in  the file
135
             *          but otherwise resembles SHT_PROGBITS.  Although this
136
             *          section contains no bytes, the sh_offset member
137
             *          contains the conceptual file offset.
138
             */
139
            AttributeType loadsec;
140
            loadsec.make_list(LoadSh_Total);
141
            if (sectionNames_) {
142
                loadsec[LoadSh_name].make_string(&sectionNames_[sh->sh_name]);
143
            } else {
144
                loadsec[LoadSh_name].make_string("unknown");
145
            }
146
            loadsec[LoadSh_addr].make_uint64(sh->sh_addr);
147
            loadsec[LoadSh_size].make_uint64(sh->sh_size);
148
            loadsec[LoadSh_data].make_data(static_cast<unsigned>(sh->sh_size));
149
            memset(loadsec[LoadSh_data].data(),
150
                        0, static_cast<size_t>(sh->sh_size));
151
            loadSectionList_.add_to_list(&loadsec);
152
            total_bytes += sh->sh_size;
153
        } else if (sh->sh_type == SHT_SYMTAB || sh->sh_type == SHT_DYNSYM) {
154
            processDebugSymbol(sh);
155
        }
156
    }
157
    symbolList_.sort(LoadSh_name);
158
    symbolListSortByAddr_ = symbolList_;
159
    symbolListSortByAddr_.sort(LoadSh_addr);
160
    return static_cast<int>(total_bytes);
161
}
162
 
163
void ElfReaderService::processStringTable(SectionHeaderType *sh) {
164
    if (sectionNames_ == NULL) {
165
        sectionNames_ = reinterpret_cast<char *>(&image_[sh->sh_offset]);
166
        if (strcmp(sectionNames_ + sh->sh_name, ".shstrtab") != 0) {
167
            /** This section holds section names. */
168
            printf("err: undefined .shstrtab section\n");
169
            sectionNames_ = NULL;
170
        }
171
    } else if (strcmp(sectionNames_ + sh->sh_name, ".strtab") == 0) {
172
        /**
173
         * This section holds strings, most commonly the strings that
174
         * represent the names associated with symbol table entries.
175
         * If the file has a loadable segment that includes the symbol
176
         * string table, the section's attributes will include the
177
         * SHF_ALLOC bit; otherwise, that bit will be turned off.
178
         */
179
        symbolNames_ = reinterpret_cast<char *>(&image_[sh->sh_offset]);
180
    } else {
181
        RISCV_error("Unsupported string section %s",
182
                            sectionNames_ + sh->sh_name);
183
    }
184
}
185
 
186
void ElfReaderService::processDebugSymbol(SectionHeaderType *sh) {
187
    uint64_t symbol_off = 0;
188
    SymbolTableType *st;
189
    AttributeType tsymb;
190
    uint8_t st_type;
191
    const char *symb_name;
192
    //const char *file_name = 0;
193
 
194
    if (!symbolNames_) {
195
        return;
196
    }
197
 
198
    while (symbol_off < sh->sh_size) {
199
        st = reinterpret_cast<SymbolTableType *>
200
                    (&image_[sh->sh_offset + symbol_off]);
201
        symb_name = &symbolNames_[st->st_name];
202
 
203
        if (sh->sh_entsize) {
204
            // section with elements of fixed size
205
            symbol_off += sh->sh_entsize;
206
        } else if (st->st_size) {
207
            symbol_off += st->st_size;
208
        } else {
209
            symbol_off += sizeof(SymbolTableType);
210
        }
211
 
212
        st_type = st->st_info & 0xF;
213
        if ((st_type == STT_OBJECT || st_type == STT_FUNC) && st->st_value) {
214
            tsymb.make_list(Symbol_Total);
215
            tsymb[Symbol_Name].make_string(symb_name);
216
            tsymb[Symbol_Addr].make_uint64(st->st_value);
217
            tsymb[Symbol_Size].make_uint64(st->st_size);
218
            if (st_type == STT_FUNC) {
219
                tsymb[Symbol_Type].make_uint64(SYMBOL_TYPE_FUNCTION);
220
            } else {
221
                tsymb[Symbol_Type].make_uint64(SYMBOL_TYPE_DATA);
222
            }
223
            symbolList_.add_to_list(&tsymb);
224
        } else if (st_type == STT_FILE) {
225
            //file_name = symb_name;
226
        }
227
    }
228
}
229
 
230
void ElfReaderService::addressToSymbol(uint64_t addr, AttributeType *info) {
231
    uint64_t sadr, send;
232
    int sz = static_cast<int>(symbolListSortByAddr_.size());
233
 
234
    info->make_list(2);
235
    (*info)[0u].make_string("");
236
    (*info)[1].make_uint64(0);
237
    if (sz == 0) {
238
        return;
239
    }
240
    sadr = symbolListSortByAddr_[0u][Symbol_Addr].to_uint64();
241
    if (addr < sadr) {
242
        return;
243
    }
244
 
245
    bool search = true;
246
    int dist, pos = sz / 2;
247
    dist = pos;
248
    while (search) {
249
        AttributeType &symb = symbolListSortByAddr_[pos];
250
        sadr = symb[Symbol_Addr].to_uint64();
251
        send = sadr + symb[Symbol_Size].to_uint64();
252
        if (sadr <= addr && addr < send) {
253
            (*info)[0u] = symb[Symbol_Name];
254
            (*info)[1].make_uint64(addr - sadr);
255
            return;
256
        }
257
 
258
        if (addr < sadr) {
259
            if (dist == 0 || pos == 0) {
260
                search = false;
261
            } else if (dist == 1) {
262
                dist = 0;
263
                pos--;
264
            } else {
265
                int incr = dist / 2;
266
                pos -= incr;
267
                dist = (dist / 2) + (dist & 0x1);
268
                if (pos < 0) {
269
                    pos = 0;
270
                }
271
            }
272
        } else {
273
            if (dist == 0 || pos == (sz - 1)) {
274
                search = false;
275
            } else if (dist == 1) {
276
                dist = 0;
277
                pos++;
278
            } else {
279
                int incr = dist / 2;
280
                pos += incr;
281
                dist = (dist / 2) + (dist & 0x1);
282
                if (pos >= sz) {
283
                    pos = sz - 1;
284
                }
285
            }
286
        }
287
    }
288
}
289
 
290
}  // namespace debugger

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.