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

Subversion Repositories riscv_vhdl

[/] [riscv_vhdl/] [trunk/] [examples/] [elf2raw64/] [src/] [elfreader.cpp] - Blame information for rev 5

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 5 sergeykhbr
#include "elfreader.h"
2
#include <fstream>
3
#include <cstring>
4
 
5
ElfReader::ElfReader(const char *file_name)
6
{
7
    src_img.arr = NULL;
8
    pSectionNames = NULL;
9
 
10
    std::ifstream *pisElf = new std::ifstream(file_name, std::ios::binary);
11
    iElfFileSize = 0;
12
    if (pisElf->is_open()) {
13
        pisElf->seekg(0, std::ios::end);
14
        iElfFileSize = (int)pisElf->tellg();
15
        if(iElfFileSize) {
16
            elf_img = new uint8_t[iElfFileSize];
17
            pisElf->seekg(0, std::ios::beg);
18
            pisElf->read((char *)elf_img, iElfFileSize);
19
        }
20
        pisElf->close();
21
    }
22
    delete pisElf;
23
 
24
    if (isOpened()) {
25
        readElfHeader();
26
        if (Elf32_Ehdr->e_shoff) {
27
            readSections();
28
            createRawImage();
29
            //attachSymbolsToRawImage();
30
        }
31
        if (Elf32_Ehdr->e_phoff) {
32
            readProgramHeader();
33
        }
34
 
35
    }
36
}
37
 
38
ElfReader::~ElfReader()
39
{
40
    if (iElfFileSize) delete [] elf_img;
41
    if (src_img.arr) delete [] src_img.arr;
42
}
43
 
44
//****************************************************************************
45
void ElfReader::SwapBytes(Elf32_Half& v)
46
{
47
    if (Elf32_Ehdr->e_ident[EI_DATA] == ELFDATA2MSB) {
48
          v = ((v>>8)&0xff) | ((v&0xFF)<<8);
49
    }
50
}
51
 
52
//****************************************************************************
53
void ElfReader::SwapBytes(Elf32_Word& v)
54
{
55
    if (Elf32_Ehdr->e_ident[EI_DATA] == ELFDATA2MSB) {
56
        v = ((v>>24)&0xff) | ((v>>8)&0xff00) | ((v<<8)&0xff0000) | ((v&0xFF)<<24);
57
    }
58
}
59
 
60
//****************************************************************************
61
void ElfReader::SwapBytes(uint64_t& v)
62
{
63
    if (Elf32_Ehdr->e_ident[EI_DATA] == ELFDATA2MSB) {
64
        v = ((v>>24)&0xff) | ((v>>8)&0xff00) | ((v<<8)&0xff0000) | ((v&0xFF)<<24);
65
    }
66
}
67
 
68
//****************************************************************************
69
uint32_t ElfReader::read32(uint32_t off) {
70
    uint32_t word;
71
    if(Elf32_Ehdr->e_ident[EI_DATA] == ELFDATA2MSB)  {
72
        word = uint32_t(elf_img[off+0])<<24;
73
        word |= uint32_t(elf_img[off+1])<<16;
74
        word |= uint32_t(elf_img[off+2])<<8;
75
        word |= uint32_t(elf_img[off+3])<<0;
76
    } else {
77
        word = uint32_t(elf_img[off+3])<<24;
78
        word |= uint32_t(elf_img[off+2])<<16;
79
        word |= uint32_t(elf_img[off+1])<<8;
80
        word |= uint32_t(elf_img[off+0])<<0;
81
    }
82
    return word;
83
}
84
 
85
//****************************************************************************
86
void ElfReader::readElfHeader()
87
{
88
    Elf32_Ehdr = (ElfHeaderType *)elf_img;
89
 
90
    for (int i=0; i<4; i++) {
91
        if(Elf32_Ehdr->e_ident[i] != MAGIC_BYTES[i]) {
92
            printf("err: wrong file format\n");
93
            return;
94
        }
95
    }
96
 
97
    SwapBytes(Elf32_Ehdr->e_type);
98
    SwapBytes(Elf32_Ehdr->e_machine);
99
    SwapBytes(Elf32_Ehdr->e_entry);
100
    SwapBytes(Elf32_Ehdr->e_phoff);
101
    SwapBytes(Elf32_Ehdr->e_shoff);
102
    SwapBytes(Elf32_Ehdr->e_flags);
103
    SwapBytes(Elf32_Ehdr->e_ehsize);
104
    SwapBytes(Elf32_Ehdr->e_phentsize);
105
    SwapBytes(Elf32_Ehdr->e_phnum);
106
    SwapBytes(Elf32_Ehdr->e_shentsize);
107
    SwapBytes(Elf32_Ehdr->e_shnum);
108
    SwapBytes(Elf32_Ehdr->e_shstrndx);
109
}
110
 
111
 
112
//****************************************************************************
113
void ElfReader::readSections()
114
{
115
    SectionHeaderType *sh;
116
    SymbolTableType *st;
117
    // Compute relative Base Address
118
    uiRawImageBytes = static_cast<uint32_t>(Elf32_Ehdr->e_entry);
119
 
120
    uint32_t symbol_off;
121
    uint64_t section_off = Elf32_Ehdr->e_shoff;
122
 
123
    for(int i=0; i<Elf32_Ehdr->e_shnum; i++) {
124
        sh = (SectionHeaderType *)&elf_img[section_off];
125
 
126
        SwapBytes(sh->sh_name);//Index in a header section table (gives name of section)
127
        SwapBytes(sh->sh_type);
128
        SwapBytes(sh->sh_flags);
129
        SwapBytes(sh->sh_addr);
130
        SwapBytes(sh->sh_offset);
131
        SwapBytes(sh->sh_size);
132
        SwapBytes(sh->sh_link);
133
        SwapBytes(sh->sh_info);
134
        SwapBytes(sh->sh_addralign);
135
        SwapBytes(sh->sh_entsize);
136
 
137
        switch (sh->sh_type) {
138
        // string names:
139
        case SHT_STRTAB:
140
            if (pSectionNames == NULL) {
141
                pSectionNames = (char *)&elf_img[sh->sh_offset];
142
                if (strcmp(pSectionNames+sh->sh_name, ".shstrtab") != 0) {
143
                    printf("err: undefined .shstrtab section\n");
144
                    pSectionNames = NULL;
145
                }
146
            } else if (strcmp(pSectionNames+sh->sh_name, ".strtab") == 0) {
147
                pSymbolName  = (char *)&elf_img[sh->sh_offset];
148
            } else {
149
                printf("err: unsupported string section %s\n",
150
                        pSectionNames+sh->sh_name);
151
            }
152
            break;
153
 
154
        case SHT_PROGBITS:  // instructions or other processor's information
155
        case SHT_NOBITS:    // initialized data
156
            if (sh->sh_flags & SHF_ALLOC) {
157
                if ((sh->sh_addr + sh->sh_size) > uiRawImageBytes)
158
                    uiRawImageBytes =
159
                        static_cast<uint32_t>(sh->sh_addr + sh->sh_size);
160
            }
161
            break;
162
 
163
        // Debug symbols:
164
        case SHT_SYMTAB:
165
        case SHT_DYNSYM:
166
            symbol_off = 0;
167
            while (symbol_off < sh->sh_size) {
168
                st = (SymbolTableType *)&elf_img[sh->sh_offset+symbol_off];
169
                SwapBytes(st->st_name);
170
                SwapBytes(st->st_value);
171
                SwapBytes(st->st_size);
172
                SwapBytes(st->st_shndx);
173
 
174
                // section with elements of fixed size
175
                if (sh->sh_entsize) {
176
                    symbol_off += static_cast<uint32_t>(sh->sh_entsize);
177
                } else if (st->st_size) {
178
                    symbol_off += static_cast<uint32_t>(st->st_size);
179
                } else {
180
                    symbol_off += sizeof(SymbolTableType);
181
                }
182
 
183
                debug_symbols.push_back(*st);
184
            }
185
            break;
186
        default:;
187
        }
188
 
189
        section.push_back(*sh);
190
        section_off += sizeof(SectionHeaderType);
191
    }
192
 
193
    uiRawImageBytes -= static_cast<uint32_t>(Elf32_Ehdr->e_entry);
194
}
195
 
196
//****************************************************************************
197
void ElfReader::createRawImage()
198
{
199
    src_img.entry = static_cast<uint32_t>(Elf32_Ehdr->e_entry);
200
    src_img.iSizeWords = (uiRawImageBytes+3)/4;
201
    src_img.arr = new SrcElement[src_img.iSizeWords];
202
    memset(src_img.arr, 0, src_img.iSizeWords*sizeof(SrcElement));
203
 
204
    // print Program defined section:
205
    uint32_t adr;
206
    uint32_t word;
207
    SectionHeaderType *sh;
208
    for (unsigned i = 0; i < section.size(); i++) {
209
 
210
        sh = &section[i];
211
 
212
        if (sh->sh_size == 0) continue;
213
        if ((sh->sh_flags & SHF_ALLOC) == 0) continue;
214
 
215
        adr = static_cast<uint32_t>((sh->sh_addr - src_img.entry) / 4);
216
        if ((adr + sh->sh_size/4) > src_img.iSizeWords) {
217
            printf("err: section address %08x is out of range "
218
                   "of the allocated image\n", adr);
219
            continue;
220
        }
221
 
222
        src_img.arr[adr].pSectionName =
223
            reinterpret_cast<uint8_t *>(pSectionNames + sh->sh_name);
224
        if ((sh->sh_type == SHT_PROGBITS) || (sh->sh_type == SHT_NOBITS)) {
225
 
226
            for (uint32_t n = 0; n < sh->sh_size; n += 4) {
227
                if (sh->sh_type == SHT_PROGBITS) {
228
                    word = read32(static_cast<uint32_t>(sh->sh_offset + n));
229
                } else if(sh->sh_type == SHT_NOBITS) {
230
                    word = 0;
231
                }
232
 
233
                src_img.arr[adr++].val = word;
234
            }
235
        }
236
    }
237
}
238
 
239
void ElfReader::readProgramHeader() {
240
    ProgramHeaderType *pr;
241
    uint64_t pr_offset = Elf32_Ehdr->e_phoff;
242
 
243
    for (uint32_t i = 0; i < Elf32_Ehdr->e_phnum; i++) {
244
        pr = (ProgramHeaderType *)&elf_img[pr_offset];
245
        SwapBytes(pr->p_type);
246
        SwapBytes(pr->p_offset);
247
        SwapBytes(pr->p_vaddr);
248
        SwapBytes(pr->p_paddr);
249
        SwapBytes(pr->p_filesz);
250
        SwapBytes(pr->p_memsz);
251
        SwapBytes(pr->p_flags);
252
        SwapBytes(pr->p_align);
253
 
254
        program.push_back(*pr);
255
    }
256
}
257
 
258
 
259
//****************************************************************************
260
void ElfReader::attachSymbolsToRawImage() {
261
    SymbolTableType *st;
262
    uint64_t offset;
263
    for (uint32_t i = 0; i < debug_symbols.size(); i++) {
264
        st = &debug_symbols[i];
265
        offset = (st->st_value - src_img.entry)/4;  // TODO: byte access
266
 
267
        if (offset > src_img.iSizeWords) {
268
            printf("err: Symbol has address %08x out of image range\n",
269
                static_cast<uint32_t>(offset));
270
            continue;
271
        }
272
 
273
        switch(ELF32_ST_TYPE(st->st_info)) {
274
        case STT_OBJECT:
275
            src_img.arr[offset].pDataName =
276
                reinterpret_cast<uint8_t *>(pSymbolName + st->st_name);
277
            break;
278
        case STT_FUNC:
279
            src_img.arr[offset].pFuncName =
280
                reinterpret_cast<uint8_t *>(pSymbolName + st->st_name);
281
            break;
282
        case STT_FILE:
283
            src_img.arr[offset].pFileName =
284
            reinterpret_cast<uint8_t *>(pSymbolName + st->st_name);
285
            break;
286
        default:;
287
        }
288
    }
289
}
290
 
291
//****************************************************************************
292
void ElfReader::writeRawImage(const char *file_name, uint32_t fixed_size)
293
{
294
    SrcElement *e;
295
    std::ofstream osraw(file_name, std::ios::binary);
296
    if (!osraw.is_open()) {
297
        printf("err: can't create output file %s\n", file_name);
298
        return;
299
    }
300
    if (fixed_size && fixed_size < 4*src_img.iSizeWords) {
301
        printf("Warning: defined size %d is less than actual size %d\n",
302
            fixed_size, 4*src_img.iSizeWords);
303
    }
304
 
305
    char ss;
306
    for (uint32_t i = 0; i < src_img.iSizeWords; i++) {
307
        e = &src_img.arr[i];
308
 
309
        for (int n=0; n<4; n++) {
310
            ss = (char)(e->val >> (24-8*n));
311
            osraw.write(&ss, 1);
312
        }
313
    }
314
 
315
    if (fixed_size) {
316
        uint32_t fix_word = (fixed_size+3)/4;
317
        for (uint32_t i = src_img.iSizeWords; i < fix_word; i++) {
318
            uint32_t fix_zero = 0;
319
            osraw.write((char *)&fix_zero, 4);
320
        }
321
    }
322
 
323
#if 0
324
    // Warning! Bug in BOOT ROM was fixed when MBR was added, but incorrect
325
    //          could be output like "coping section ffff"
326
    if ((src_img.iSizeWords&0x1ff) == 0) {
327
        uint32 fix_zero = 0;
328
        osraw.write((char *)&fix_zero, 4);
329
    }
330
#endif
331
    osraw.flush();
332
 
333
    printf("Image %d Bytes was generated\n",
334
        fixed_size ? fixed_size :uiRawImageBytes);
335
}
336
 
337
//****************************************************************************
338
void ElfReader::writeRomHexArray(const char *file_name, uint64_t base_addr,
339
                                 uint32_t bytes_per_line,
340
                                 uint32_t fixed_size) {
341
    if (base_addr == ~0) {
342
        base_addr = src_img.entry;
343
    }
344
 
345
    if (fixed_size && fixed_size < (4*src_img.iSizeWords + src_img.entry - base_addr)) {
346
        printf("Warning: defined size %d is less than actual size %d\n",
347
            fixed_size, 4*src_img.iSizeWords);
348
    }
349
 
350
    // generate *.rom array
351
    char chRomFile[64];
352
    std::string rom_file_name(file_name);
353
    std::ofstream osRom(rom_file_name.c_str(), std::ios::out);
354
 
355
    uint32_t bytes_total, lines_total;
356
    if (fixed_size == 0) {
357
        bytes_total = src_img.iSizeWords;
358
    } else {
359
        bytes_total = fixed_size;
360
    }
361
    lines_total = (bytes_total + (bytes_per_line - 1)) / bytes_per_line;
362
    uint32_t words_per_line = bytes_per_line / 4;
363
 
364
    int idx = (int)((int64_t)base_addr - (int64_t)src_img.entry) / 4;
365
    for (uint32_t i = 0; i < lines_total; i++) {
366
        idx += (words_per_line);
367
        for (uint32_t n = 0; n < words_per_line; n++) {
368
            idx--;
369
            if (idx >= 0 && idx < static_cast<int>(src_img.iSizeWords)) {
370
                sprintf(chRomFile,"%08X", src_img.arr[idx].val);
371
            } else {
372
                sprintf(chRomFile,"%08X", 0);
373
            }
374
            osRom << chRomFile;
375
        }
376
        idx += (words_per_line);
377
        osRom << "\n";
378
    }
379
 
380
 
381
    osRom.close();
382
 
383
    printf("HexRom was generated: %dx%d lines\n", lines_total, 8*bytes_per_line);
384
}

powered by: WebSVN 2.1.0

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