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 4

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 4 sergeykhbr
/*
2
 *  Copyright 2018 Sergey Khabarov, sergeykhbr@gmail.com
3
 *
4
 *  Licensed under the Apache License, Version 2.0 (the "License");
5
 *  you may not use this file except in compliance with the License.
6
 *  You may obtain a copy of the License at
7
 *
8
 *      http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 *  Unless required by applicable law or agreed to in writing, software
11
 *  distributed under the License is distributed on an "AS IS" BASIS,
12
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 *  See the License for the specific language governing permissions and
14
 *  limitations under the License.
15
 */
16
 
17
#include "elfreader.h"
18
#include <iostream>
19
 
20
namespace debugger {
21
 
22
/** Class registration in the Core */
23
REGISTER_CLASS(ElfReaderService)
24
 
25
ElfReaderService::ElfReaderService(const char *name) : IService(name) {
26
    registerInterface(static_cast<IElfReader *>(this));
27
    registerAttribute("SourceProc", &sourceProc_);
28
    image_ = NULL;
29
    sectionNames_ = NULL;
30
    symbolList_.make_list(0);
31
    loadSectionList_.make_list(0);
32
    sourceProc_.make_string("");
33
    isrc_ = 0;
34
}
35
 
36
ElfReaderService::~ElfReaderService() {
37
    if (image_) {
38
        delete image_;
39
    }
40
}
41
 
42
void ElfReaderService::postinitService() {
43
    isrc_ = static_cast<ISourceCode *>(
44
       RISCV_get_service_iface(sourceProc_.to_string(),
45
                               IFACE_SOURCE_CODE));
46
    if (!isrc_) {
47
        RISCV_error("SourceCode interface '%s' not found",
48
                    sourceProc_.to_string());
49
    }
50
}
51
 
52
int ElfReaderService::readFile(const char *filename) {
53
    FILE *fp = fopen(filename, "rb");
54
    if (!fp) {
55
        RISCV_error("File '%s' not found", filename);
56
        return -1;
57
    }
58
    fseek(fp, 0, SEEK_END);
59
    int sz = ftell(fp);
60
    rewind(fp);
61
 
62
    if (image_) {
63
        delete image_;
64
        sectionNames_ = NULL;
65
        sourceProc_.make_list(0);
66
        symbolList_.make_list(0);
67
        loadSectionList_.make_list(0);
68
    }
69
    image_ = new uint8_t[sz];
70
    fread(image_, 1, sz, fp);
71
 
72
    if (readElfHeader() != 0) {
73
        fclose(fp);
74
        return 0;
75
    }
76
 
77
    symbolNames_ = 0;
78
    if (!header_->get_shoff()) {
79
        fclose(fp);
80
        return 0;
81
    }
82
 
83
    sh_tbl_ = new SectionHeaderType *[header_->get_shnum()];
84
 
85
    /** Search .shstrtab section */
86
    uint8_t *psh = &image_[header_->get_shoff()];
87
    for (int i = 0; i < header_->get_shnum(); i++) {
88
        sh_tbl_[i] = new SectionHeaderType(psh, header_);
89
 
90
        sectionNames_ = reinterpret_cast<char *>(&image_[sh_tbl_[i]->get_offset()]);
91
        if (sh_tbl_[i]->get_type() == SHT_STRTAB &&
92
            strcmp(sectionNames_ + sh_tbl_[i]->get_name(), ".shstrtab") != 0) {
93
            sectionNames_ = NULL;
94
        }
95
 
96
        if (header_->isElf32()) {
97
            psh += sizeof(Elf32_Shdr);
98
        } else {
99
            psh += sizeof(Elf64_Shdr);
100
        }
101
    }
102
    if (!sectionNames_) {
103
        printf("err: section .shstrtab not found.\n");
104
    }
105
 
106
    /** Search ".strtab" section with Debug symbols */
107
    SectionHeaderType *sh;
108
    for (int i = 0; i < header_->get_shnum(); i++) {
109
        sh = sh_tbl_[i];
110
        if (sectionNames_ == NULL || sh->get_type() != SHT_STRTAB) {
111
            continue;
112
        }
113
        if (strcmp(sectionNames_ + sh->get_name(), ".strtab")) {
114
            continue;
115
        }
116
        /**
117
            * This section holds strings, most commonly the strings that
118
            * represent the names associated with symbol table entries.
119
            * If the file has a loadable segment that includes the symbol
120
            * string table, the section's attributes will include the
121
            * SHF_ALLOC bit; otherwise, that bit will be turned off.
122
            */
123
        symbolNames_ = reinterpret_cast<char *>(&image_[sh->get_offset()]);
124
    }
125
    if (!symbolNames_) {
126
        printf("err: section .strtab not found. No debug symbols.\n");
127
    }
128
 
129
    /** Direct loading via tap interface: */
130
    int bytes_loaded = loadSections();
131
    RISCV_info("Loaded: %d B", bytes_loaded);
132
 
133
    if (header_->get_phoff()) {
134
        //readProgramHeader();
135
    }
136
 
137
    fclose(fp);
138
    return 0;
139
}
140
 
141
int ElfReaderService::readElfHeader() {
142
    header_ = new ElfHeaderType(image_);
143
    if (header_->isElf()) {
144
        return 0;
145
    }
146
    RISCV_error("File format is not ELF", NULL);
147
    return -1;
148
}
149
 
150
int ElfReaderService::loadSections() {
151
    SectionHeaderType *sh;
152
    uint64_t total_bytes = 0;
153
    AttributeType tsymb;
154
 
155
    for (int i = 0; i < header_->get_shnum(); i++) {
156
        sh = sh_tbl_[i];
157
 
158
        if (sh->get_size() == 0) {
159
            continue;
160
        }
161
 
162
        if (sectionNames_ && (sh->get_flags() & SHF_ALLOC)) {
163
            RISCV_info("Reading '%s' section", &sectionNames_[sh->get_name()]);
164
        }
165
 
166
        if (sh->get_type() == SHT_PROGBITS && (sh->get_flags() & SHF_ALLOC) != 0) {
167
            /**
168
             * @brief   Instructions or other processor's information
169
             * @details This section holds information defined by the program,
170
             *          whose format and meaning are determined solely by the
171
             *          program.
172
             */
173
            AttributeType loadsec;
174
            loadsec.make_list(LoadSh_Total);
175
            if (sectionNames_) {
176
                loadsec[LoadSh_name].make_string(&sectionNames_[sh->get_name()]);
177
            } else {
178
                loadsec[LoadSh_name].make_string("unknown");
179
            }
180
            loadsec[LoadSh_addr].make_uint64(sh->get_addr());
181
            loadsec[LoadSh_size].make_uint64(sh->get_size());
182
            loadsec[LoadSh_data].make_data(static_cast<unsigned>(sh->get_size()),
183
                                           &image_[sh->get_offset()]);
184
            loadSectionList_.add_to_list(&loadsec);
185
            total_bytes += sh->get_size();
186
        } else if (sh->get_type() == SHT_NOBITS
187
                    && (sh->get_flags() & SHF_ALLOC) != 0) {
188
            /**
189
             * @brief   Initialized data
190
             * @details A section of this type occupies no space in  the file
191
             *          but otherwise resembles SHT_PROGBITS.  Although this
192
             *          section contains no bytes, the sh_offset member
193
             *          contains the conceptual file offset.
194
             */
195
            AttributeType loadsec;
196
            loadsec.make_list(LoadSh_Total);
197
            if (sectionNames_) {
198
                loadsec[LoadSh_name].make_string(&sectionNames_[sh->get_name()]);
199
            } else {
200
                loadsec[LoadSh_name].make_string("unknown");
201
            }
202
            loadsec[LoadSh_addr].make_uint64(sh->get_addr());
203
            loadsec[LoadSh_size].make_uint64(sh->get_size());
204
            loadsec[LoadSh_data].make_data(static_cast<unsigned>(sh->get_size()));
205
            memset(loadsec[LoadSh_data].data(),
206
                        0, static_cast<size_t>(sh->get_size()));
207
            loadSectionList_.add_to_list(&loadsec);
208
            total_bytes += sh->get_size();
209
        } else if (sh->get_type() == SHT_SYMTAB || sh->get_type() == SHT_DYNSYM) {
210
            processDebugSymbol(sh);
211
        }
212
    }
213
    symbolList_.sort(LoadSh_name);
214
    if (isrc_) {
215
        isrc_->addSymbols(&symbolList_);
216
    }
217
    return static_cast<int>(total_bytes);
218
}
219
 
220
void ElfReaderService::processDebugSymbol(SectionHeaderType *sh) {
221
    uint64_t symbol_off = 0;
222
    SymbolTableType *st;
223
    AttributeType tsymb;
224
    uint8_t st_type;
225
    const char *symb_name;
226
    //const char *file_name = 0;
227
 
228
    if (!symbolNames_) {
229
        return;
230
    }
231
 
232
    while (symbol_off < sh->get_size()) {
233
        st = new SymbolTableType(&image_[sh->get_offset() + symbol_off],
234
                                header_);
235
 
236
        symb_name = &symbolNames_[st->get_name()];
237
 
238
        st_type = st->get_info() & 0xF;
239
        if ((st_type == STT_OBJECT || st_type == STT_FUNC) && st->get_value()) {
240
            tsymb.make_list(Symbol_Total);
241
            tsymb[Symbol_Name].make_string(symb_name);
242
            tsymb[Symbol_Addr].make_uint64(st->get_value());
243
            tsymb[Symbol_Size].make_uint64(st->get_size());
244
            if (st_type == STT_FUNC) {
245
                tsymb[Symbol_Type].make_uint64(SYMBOL_TYPE_FUNCTION);
246
            } else {
247
                tsymb[Symbol_Type].make_uint64(SYMBOL_TYPE_DATA);
248
            }
249
            symbolList_.add_to_list(&tsymb);
250
        } else if (st_type == STT_FILE) {
251
            //file_name = symb_name;
252
        }
253
 
254
        if (sh->get_entsize()) {
255
            // section with elements of fixed size
256
            symbol_off += sh->get_entsize();
257
        } else if (st->get_size()) {
258
            symbol_off += st->get_size();
259
        } else {
260
            if (header_->isElf32()) {
261
                symbol_off += sizeof(Elf32_Sym);
262
            } else {
263
                symbol_off += sizeof(Elf64_Sym);
264
            }
265
        }
266
        delete st;
267
    }
268
}
269
 
270
}  // namespace debugger

powered by: WebSVN 2.1.0

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