summaryrefslogtreecommitdiff
path: root/utils/sbtools/elf.c
diff options
context:
space:
mode:
authorAmaury Pouly <pamaury@rockbox.org>2011-04-17 15:49:58 +0000
committerAmaury Pouly <pamaury@rockbox.org>2011-04-17 15:49:58 +0000
commitc4cb4cca47091978be0c557bcc0b2fbdca7c3b61 (patch)
tree8442635026d4c2d38b22c630be96a415c95d3dd6 /utils/sbtools/elf.c
parent204a2e920acd94090e5be12b009fc71ddee8fabc (diff)
downloadrockbox-c4cb4cca47091978be0c557bcc0b2fbdca7c3b61.tar.gz
rockbox-c4cb4cca47091978be0c557bcc0b2fbdca7c3b61.zip
sbtools: move internal elf definition to elf.c, implement elf reading
sbtoelf: generate a correct section name for undef and string table sections elftosb: static'ify functions, add cmd file to sb file conversion git-svn-id: svn://svn.rockbox.org/rockbox/trunk@29738 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'utils/sbtools/elf.c')
-rw-r--r--utils/sbtools/elf.c240
1 files changed, 235 insertions, 5 deletions
diff --git a/utils/sbtools/elf.c b/utils/sbtools/elf.c
index f146bcc111..4b95025d8f 100644
--- a/utils/sbtools/elf.c
+++ b/utils/sbtools/elf.c
@@ -1,5 +1,135 @@
1#include "elf.h" 1#include "elf.h"
2 2
3/**
4 * Definitions
5 * taken from elf.h linux header
6 * based on ELF specification
7 * based on ARM ELF specification
8 */
9typedef uint16_t Elf32_Half;
10
11typedef uint32_t Elf32_Word;
12typedef int32_t Elf32_Sword;
13typedef uint32_t Elf32_Addr;
14typedef uint32_t Elf32_Off;
15typedef uint16_t Elf32_Section;
16
17#define EI_NIDENT 16
18
19typedef struct
20{
21 unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */
22 Elf32_Half e_type; /* Object file type */
23 Elf32_Half e_machine; /* Architecture */
24 Elf32_Word e_version; /* Object file version */
25 Elf32_Addr e_entry; /* Entry point virtual address */
26 Elf32_Off e_phoff; /* Program header table file offset */
27 Elf32_Off e_shoff; /* Section header table file offset */
28 Elf32_Word e_flags; /* Processor-specific flags */
29 Elf32_Half e_ehsize; /* ELF header size in bytes */
30 Elf32_Half e_phentsize; /* Program header table entry size */
31 Elf32_Half e_phnum; /* Program header table entry count */
32 Elf32_Half e_shentsize; /* Section header table entry size */
33 Elf32_Half e_shnum; /* Section header table entry count */
34 Elf32_Half e_shstrndx; /* Section header string table index */
35}Elf32_Ehdr;
36
37#define EI_MAG0 0 /* File identification byte 0 index */
38#define ELFMAG0 0x7f /* Magic number byte 0 */
39
40#define EI_MAG1 1 /* File identification byte 1 index */
41#define ELFMAG1 'E' /* Magic number byte 1 */
42
43#define EI_MAG2 2 /* File identification byte 2 index */
44#define ELFMAG2 'L' /* Magic number byte 2 */
45
46#define EI_MAG3 3 /* File identification byte 3 index */
47#define ELFMAG3 'F' /* Magic number byte 3 */
48
49#define EI_CLASS 4 /* File class byte index */
50#define ELFCLASS32 1 /* 32-bit objects */
51
52#define EI_DATA 5 /* Data encoding byte index */
53#define ELFDATA2LSB 1 /* 2's complement, little endian */
54
55#define EI_VERSION 6 /* File version byte index, Value must be EV_CURRENT */
56
57#define EI_OSABI 7 /* OS ABI identification */
58#define ELFOSABI_NONE 0 /* UNIX System V ABI */
59#define ELFOSABI_ARM_AEABI 64 /* ARM EABI */
60#define ELFOSABI_ARM 97 /* ARM */
61
62#define EI_ABIVERSION 8 /* ABI version */
63
64#define EI_PAD 9 /* Byte index of padding bytes */
65
66#define ET_EXEC 2 /* Executable file */
67
68#define EM_ARM 40 /* ARM */
69
70#define EV_CURRENT 1 /* Current version */
71
72#define EF_ARM_HASENTRY 0x00000002
73
74#define SHN_UNDEF 0 /* Undefined section */
75
76typedef struct
77{
78 Elf32_Word sh_name; /* Section name (string tbl index) */
79 Elf32_Word sh_type; /* Section type */
80 Elf32_Word sh_flags; /* Section flags */
81 Elf32_Addr sh_addr; /* Section virtual addr at execution */
82 Elf32_Off sh_offset; /* Section file offset */
83 Elf32_Word sh_size; /* Section size in bytes */
84 Elf32_Word sh_link; /* Link to another section */
85 Elf32_Word sh_info; /* Additional section information */
86 Elf32_Word sh_addralign; /* Section alignment */
87 Elf32_Word sh_entsize; /* Entry size if section holds table */
88}Elf32_Shdr;
89
90#define SHT_NULL 0 /* Section header table entry unused */
91#define SHT_PROGBITS 1 /* Program data */
92#define SHT_SYMTAB 2 /* Symbol table */
93#define SHT_STRTAB 3 /* String table */
94#define SHT_RELA 4 /* Relocation entries with addends */
95#define SHT_HASH 5 /* Symbol hash table */
96#define SHT_DYNAMIC 6 /* Dynamic linking information */
97#define SHT_NOTE 7 /* Notes */
98#define SHT_NOBITS 8 /* Program space with no data (bss) */
99#define SHT_REL 9 /* Relocation entries, no addends */
100#define SHT_SHLIB 10 /* Reserved */
101#define SHT_DYNSYM 11 /* Dynamic linker symbol table */
102#define SHT_INIT_ARRAY 14 /* Array of constructors */
103#define SHT_FINI_ARRAY 15 /* Array of destructors */
104#define SHT_PREINIT_ARRAY 16 /* Array of pre-constructors */
105#define SHT_GROUP 17 /* Section group */
106#define SHT_SYMTAB_SHNDX 18 /* Extended section indeces */
107#define SHT_NUM 19 /* Number of defined types. */
108
109#define SHF_WRITE (1 << 0) /* Writable */
110#define SHF_ALLOC (1 << 1) /* Occupies memory during execution */
111#define SHF_EXECINSTR (1 << 2) /* Executable */
112#define SHF_MERGE (1 << 4) /* Might be merged */
113#define SHF_STRINGS (1 << 5) /* Contains nul-terminated strings */
114
115typedef struct
116{
117 Elf32_Word p_type; /* Segment type */
118 Elf32_Off p_offset; /* Segment file offset */
119 Elf32_Addr p_vaddr; /* Segment virtual address */
120 Elf32_Addr p_paddr; /* Segment physical address */
121 Elf32_Word p_filesz; /* Segment size in file */
122 Elf32_Word p_memsz; /* Segment size in memory */
123 Elf32_Word p_flags; /* Segment flags */
124 Elf32_Word p_align; /* Segment alignment */
125}Elf32_Phdr;
126
127#define PT_LOAD 1 /* Loadable program segment */
128
129#define PF_X (1 << 0) /* Segment is executable */
130#define PF_W (1 << 1) /* Segment is writable */
131#define PF_R (1 << 2) /* Segment is readable */
132
3void elf_init(struct elf_params_t *params) 133void elf_init(struct elf_params_t *params)
4{ 134{
5 params->has_start_addr = false; 135 params->has_start_addr = false;
@@ -54,7 +184,7 @@ void elf_add_fill_section(struct elf_params_t *params,
54 sec->pattern = pattern; 184 sec->pattern = pattern;
55} 185}
56 186
57void elf_output(struct elf_params_t *params, elf_write_fn_t write, void *user) 187void elf_write_file(struct elf_params_t *params, elf_write_fn_t write, void *user)
58{ 188{
59 Elf32_Ehdr ehdr; 189 Elf32_Ehdr ehdr;
60 uint32_t phnum = 0; 190 uint32_t phnum = 0;
@@ -64,9 +194,11 @@ void elf_output(struct elf_params_t *params, elf_write_fn_t write, void *user)
64 Elf32_Shdr shdr; 194 Elf32_Shdr shdr;
65 memset(&ehdr, 0, EI_NIDENT); 195 memset(&ehdr, 0, EI_NIDENT);
66 196
67 uint32_t bss_strtbl = 0; 197 uint32_t bss_strtbl = 1;
68 uint32_t text_strtbl = bss_strtbl + strlen(".bss") + 1; 198 uint32_t text_strtbl = bss_strtbl + strlen(".bss") + 1;
69 uint32_t strtbl_size = text_strtbl + strlen(".text") + 1; 199 uint32_t shstrtab_strtbl = text_strtbl + strlen(".text") + 1;
200 uint32_t strtbl_size = shstrtab_strtbl + strlen(".shstrtab") + 1;
201
70 202
71 while(sec) 203 while(sec)
72 { 204 {
@@ -182,7 +314,7 @@ void elf_output(struct elf_params_t *params, elf_write_fn_t write, void *user)
182 } 314 }
183 315
184 { 316 {
185 shdr.sh_name = bss_strtbl; 317 shdr.sh_name = shstrtab_strtbl;
186 shdr.sh_type = SHT_STRTAB; 318 shdr.sh_type = SHT_STRTAB;
187 shdr.sh_flags = 0; 319 shdr.sh_flags = 0;
188 shdr.sh_addr = 0; 320 shdr.sh_addr = 0;
@@ -206,7 +338,86 @@ void elf_output(struct elf_params_t *params, elf_write_fn_t write, void *user)
206 sec = sec->next; 338 sec = sec->next;
207 } 339 }
208 340
209 write(user, strtbl_offset + data_offset, ".bss\0.text\0", strtbl_size); 341 write(user, strtbl_offset + data_offset, "\0.bss\0.text\0.shstrtab\0", strtbl_size);
342}
343
344bool elf_read_file(struct elf_params_t *params, elf_read_fn_t read,
345 elf_printf_fn_t printf, void *user)
346{
347 #define error_printf(...) ({printf(user, true, __VA_ARGS__); return false;})
348 /* read header */
349 Elf32_Ehdr ehdr;
350 if(!read(user, 0, &ehdr, sizeof(ehdr)))
351 {
352 printf(user, true, "error reading elf header\n");
353 return false;
354 }
355 /* basic checks */
356 if(ehdr.e_ident[EI_MAG0] != ELFMAG0 || ehdr.e_ident[EI_MAG1] != ELFMAG1 ||
357 ehdr.e_ident[EI_MAG2] != ELFMAG2 || ehdr.e_ident[EI_MAG3] != ELFMAG3)
358 error_printf("invalid elf header\n");
359 if(ehdr.e_ident[EI_CLASS] != ELFCLASS32)
360 error_printf("invalid elf class: must be a 32-bit object\n");
361 if(ehdr.e_ident[EI_DATA] != ELFDATA2LSB)
362 error_printf("invalid elf data encoding: must be 32-bit lsb\n");
363 if(ehdr.e_ident[EI_VERSION] != EV_CURRENT)
364 error_printf("invalid elf version");
365 if(ehdr.e_type != ET_EXEC)
366 error_printf("invalid elf file: must be an executable file\n");
367 if(ehdr.e_machine != EM_ARM)
368 error_printf("invalid elf file: must target an arm machine\n");
369 if(ehdr.e_ehsize != sizeof(ehdr))
370 error_printf("invalid elf file: size header mismatch\n");
371 if(ehdr.e_phentsize != sizeof(Elf32_Phdr))
372 error_printf("invalid elf file: program header size mismatch\n");
373 if(ehdr.e_shentsize != sizeof(Elf32_Shdr))
374 error_printf("invalid elf file: section header size mismatch\n");
375 if(ehdr.e_flags & EF_ARM_HASENTRY)
376 elf_set_start_addr(params, ehdr.e_entry);
377
378 char *strtab = NULL;
379 {
380 Elf32_Shdr shstrtab;
381 if(read(user, ehdr.e_shoff + ehdr.e_shstrndx * ehdr.e_shentsize,
382 &shstrtab, sizeof(shstrtab)))
383 {
384 strtab = xmalloc(shstrtab.sh_size);
385 if(!read(user, shstrtab.sh_offset, strtab, shstrtab.sh_size))
386 {
387 free(strtab);
388 strtab = NULL;
389 }
390 }
391 }
392 /* run through sections */
393 printf(user, false, "ELF file:\n");
394 for(int i = 1; i< ehdr.e_shnum; i++)
395 {
396 uint32_t off = ehdr.e_shoff + i * ehdr.e_shentsize;
397 Elf32_Shdr shdr;
398 memset(&shdr, 0, sizeof(shdr));
399 if(!read(user, off, &shdr, sizeof(shdr)))
400 error_printf("error reading elf section header");
401
402 if(shdr.sh_type == SHT_PROGBITS && shdr.sh_flags & SHF_ALLOC)
403 {
404 void *data = xmalloc(shdr.sh_size);
405 if(!read(user, shdr.sh_offset, data, shdr.sh_size))
406 error_printf("error read self section data");
407 elf_add_load_section(params, shdr.sh_addr, shdr.sh_size, data);
408
409 printf(user, false, "create load segment for %s\n", &strtab[shdr.sh_name]);
410 }
411 else if(shdr.sh_type == SHT_NOBITS && shdr.sh_flags & SHF_ALLOC)
412 {
413 elf_add_fill_section(params, shdr.sh_addr, shdr.sh_size, 0);
414 printf(user, false, "create fill segment for %s\n", &strtab[shdr.sh_name]);
415 }
416 else
417 printf(user, false, "filter out %s\n", &strtab[shdr.sh_name], shdr.sh_type);
418
419 }
420 return true;
210} 421}
211 422
212bool elf_is_empty(struct elf_params_t *params) 423bool elf_is_empty(struct elf_params_t *params)
@@ -220,6 +431,25 @@ void elf_set_start_addr(struct elf_params_t *params, uint32_t addr)
220 params->start_addr = addr; 431 params->start_addr = addr;
221} 432}
222 433
434bool elf_get_start_addr(struct elf_params_t *params, uint32_t *addr)
435{
436 if(params->has_start_addr && addr != NULL)
437 *addr = params->start_addr;
438 return params->has_start_addr;
439}
440
441int elf_get_nr_sections(struct elf_params_t *params)
442{
443 int nr = 0;
444 struct elf_section_t *sec = params->first_section;
445 while(sec)
446 {
447 nr++;
448 sec = sec->next;
449 }
450 return nr;
451}
452
223void elf_release(struct elf_params_t *params) 453void elf_release(struct elf_params_t *params)
224{ 454{
225 struct elf_section_t *sec, *next_sec; 455 struct elf_section_t *sec, *next_sec;