diff options
-rw-r--r-- | utils/sbtools/elf.c | 240 | ||||
-rw-r--r-- | utils/sbtools/elf.h | 141 | ||||
-rw-r--r-- | utils/sbtools/elftosb.c | 215 | ||||
-rw-r--r-- | utils/sbtools/sbtoelf.c | 2 |
4 files changed, 449 insertions, 149 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 | */ | ||
9 | typedef uint16_t Elf32_Half; | ||
10 | |||
11 | typedef uint32_t Elf32_Word; | ||
12 | typedef int32_t Elf32_Sword; | ||
13 | typedef uint32_t Elf32_Addr; | ||
14 | typedef uint32_t Elf32_Off; | ||
15 | typedef uint16_t Elf32_Section; | ||
16 | |||
17 | #define EI_NIDENT 16 | ||
18 | |||
19 | typedef 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 | |||
76 | typedef 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 | |||
115 | typedef 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 | |||
3 | void elf_init(struct elf_params_t *params) | 133 | void 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 | ||
57 | void elf_output(struct elf_params_t *params, elf_write_fn_t write, void *user) | 187 | void 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 | |||
344 | bool 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 | ||
212 | bool elf_is_empty(struct elf_params_t *params) | 423 | bool 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 | ||
434 | bool 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 | |||
441 | int 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 | |||
223 | void elf_release(struct elf_params_t *params) | 453 | void 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; |
diff --git a/utils/sbtools/elf.h b/utils/sbtools/elf.h index d2bf210c5c..b145bfffc5 100644 --- a/utils/sbtools/elf.h +++ b/utils/sbtools/elf.h | |||
@@ -6,136 +6,6 @@ | |||
6 | #include <unistd.h> | 6 | #include <unistd.h> |
7 | 7 | ||
8 | /** | 8 | /** |
9 | * Definitions | ||
10 | * taken from elf.h linux header | ||
11 | * based on ELF specification | ||
12 | * based on ARM ELF specification | ||
13 | */ | ||
14 | typedef uint16_t Elf32_Half; | ||
15 | |||
16 | typedef uint32_t Elf32_Word; | ||
17 | typedef int32_t Elf32_Sword; | ||
18 | typedef uint32_t Elf32_Addr; | ||
19 | typedef uint32_t Elf32_Off; | ||
20 | typedef uint16_t Elf32_Section; | ||
21 | |||
22 | #define EI_NIDENT 16 | ||
23 | |||
24 | typedef struct | ||
25 | { | ||
26 | unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */ | ||
27 | Elf32_Half e_type; /* Object file type */ | ||
28 | Elf32_Half e_machine; /* Architecture */ | ||
29 | Elf32_Word e_version; /* Object file version */ | ||
30 | Elf32_Addr e_entry; /* Entry point virtual address */ | ||
31 | Elf32_Off e_phoff; /* Program header table file offset */ | ||
32 | Elf32_Off e_shoff; /* Section header table file offset */ | ||
33 | Elf32_Word e_flags; /* Processor-specific flags */ | ||
34 | Elf32_Half e_ehsize; /* ELF header size in bytes */ | ||
35 | Elf32_Half e_phentsize; /* Program header table entry size */ | ||
36 | Elf32_Half e_phnum; /* Program header table entry count */ | ||
37 | Elf32_Half e_shentsize; /* Section header table entry size */ | ||
38 | Elf32_Half e_shnum; /* Section header table entry count */ | ||
39 | Elf32_Half e_shstrndx; /* Section header string table index */ | ||
40 | }Elf32_Ehdr; | ||
41 | |||
42 | #define EI_MAG0 0 /* File identification byte 0 index */ | ||
43 | #define ELFMAG0 0x7f /* Magic number byte 0 */ | ||
44 | |||
45 | #define EI_MAG1 1 /* File identification byte 1 index */ | ||
46 | #define ELFMAG1 'E' /* Magic number byte 1 */ | ||
47 | |||
48 | #define EI_MAG2 2 /* File identification byte 2 index */ | ||
49 | #define ELFMAG2 'L' /* Magic number byte 2 */ | ||
50 | |||
51 | #define EI_MAG3 3 /* File identification byte 3 index */ | ||
52 | #define ELFMAG3 'F' /* Magic number byte 3 */ | ||
53 | |||
54 | #define EI_CLASS 4 /* File class byte index */ | ||
55 | #define ELFCLASS32 1 /* 32-bit objects */ | ||
56 | |||
57 | #define EI_DATA 5 /* Data encoding byte index */ | ||
58 | #define ELFDATA2LSB 1 /* 2's complement, little endian */ | ||
59 | |||
60 | #define EI_VERSION 6 /* File version byte index, Value must be EV_CURRENT */ | ||
61 | |||
62 | #define EI_OSABI 7 /* OS ABI identification */ | ||
63 | #define ELFOSABI_NONE 0 /* UNIX System V ABI */ | ||
64 | #define ELFOSABI_ARM_AEABI 64 /* ARM EABI */ | ||
65 | #define ELFOSABI_ARM 97 /* ARM */ | ||
66 | |||
67 | #define EI_ABIVERSION 8 /* ABI version */ | ||
68 | |||
69 | #define EI_PAD 9 /* Byte index of padding bytes */ | ||
70 | |||
71 | #define ET_EXEC 2 /* Executable file */ | ||
72 | |||
73 | #define EM_ARM 40 /* ARM */ | ||
74 | |||
75 | #define EV_CURRENT 1 /* Current version */ | ||
76 | |||
77 | #define EF_ARM_HASENTRY 0x00000002 | ||
78 | |||
79 | #define SHN_UNDEF 0 /* Undefined section */ | ||
80 | |||
81 | typedef struct | ||
82 | { | ||
83 | Elf32_Word sh_name; /* Section name (string tbl index) */ | ||
84 | Elf32_Word sh_type; /* Section type */ | ||
85 | Elf32_Word sh_flags; /* Section flags */ | ||
86 | Elf32_Addr sh_addr; /* Section virtual addr at execution */ | ||
87 | Elf32_Off sh_offset; /* Section file offset */ | ||
88 | Elf32_Word sh_size; /* Section size in bytes */ | ||
89 | Elf32_Word sh_link; /* Link to another section */ | ||
90 | Elf32_Word sh_info; /* Additional section information */ | ||
91 | Elf32_Word sh_addralign; /* Section alignment */ | ||
92 | Elf32_Word sh_entsize; /* Entry size if section holds table */ | ||
93 | }Elf32_Shdr; | ||
94 | |||
95 | #define SHT_NULL 0 /* Section header table entry unused */ | ||
96 | #define SHT_PROGBITS 1 /* Program data */ | ||
97 | #define SHT_SYMTAB 2 /* Symbol table */ | ||
98 | #define SHT_STRTAB 3 /* String table */ | ||
99 | #define SHT_RELA 4 /* Relocation entries with addends */ | ||
100 | #define SHT_HASH 5 /* Symbol hash table */ | ||
101 | #define SHT_DYNAMIC 6 /* Dynamic linking information */ | ||
102 | #define SHT_NOTE 7 /* Notes */ | ||
103 | #define SHT_NOBITS 8 /* Program space with no data (bss) */ | ||
104 | #define SHT_REL 9 /* Relocation entries, no addends */ | ||
105 | #define SHT_SHLIB 10 /* Reserved */ | ||
106 | #define SHT_DYNSYM 11 /* Dynamic linker symbol table */ | ||
107 | #define SHT_INIT_ARRAY 14 /* Array of constructors */ | ||
108 | #define SHT_FINI_ARRAY 15 /* Array of destructors */ | ||
109 | #define SHT_PREINIT_ARRAY 16 /* Array of pre-constructors */ | ||
110 | #define SHT_GROUP 17 /* Section group */ | ||
111 | #define SHT_SYMTAB_SHNDX 18 /* Extended section indeces */ | ||
112 | #define SHT_NUM 19 /* Number of defined types. */ | ||
113 | |||
114 | #define SHF_WRITE (1 << 0) /* Writable */ | ||
115 | #define SHF_ALLOC (1 << 1) /* Occupies memory during execution */ | ||
116 | #define SHF_EXECINSTR (1 << 2) /* Executable */ | ||
117 | #define SHF_MERGE (1 << 4) /* Might be merged */ | ||
118 | #define SHF_STRINGS (1 << 5) /* Contains nul-terminated strings */ | ||
119 | |||
120 | typedef struct | ||
121 | { | ||
122 | Elf32_Word p_type; /* Segment type */ | ||
123 | Elf32_Off p_offset; /* Segment file offset */ | ||
124 | Elf32_Addr p_vaddr; /* Segment virtual address */ | ||
125 | Elf32_Addr p_paddr; /* Segment physical address */ | ||
126 | Elf32_Word p_filesz; /* Segment size in file */ | ||
127 | Elf32_Word p_memsz; /* Segment size in memory */ | ||
128 | Elf32_Word p_flags; /* Segment flags */ | ||
129 | Elf32_Word p_align; /* Segment alignment */ | ||
130 | }Elf32_Phdr; | ||
131 | |||
132 | #define PT_LOAD 1 /* Loadable program segment */ | ||
133 | |||
134 | #define PF_X (1 << 0) /* Segment is executable */ | ||
135 | #define PF_W (1 << 1) /* Segment is writable */ | ||
136 | #define PF_R (1 << 2) /* Segment is readable */ | ||
137 | |||
138 | /** | ||
139 | * API | 9 | * API |
140 | */ | 10 | */ |
141 | enum elf_section_type_t | 11 | enum elf_section_type_t |
@@ -154,7 +24,7 @@ struct elf_section_t | |||
154 | uint32_t pattern; | 24 | uint32_t pattern; |
155 | /* </union> */ | 25 | /* </union> */ |
156 | struct elf_section_t *next; | 26 | struct elf_section_t *next; |
157 | /* Internal to elf_output */ | 27 | /* Internal to elf_write_file */ |
158 | uint32_t offset; | 28 | uint32_t offset; |
159 | }; | 29 | }; |
160 | 30 | ||
@@ -166,14 +36,21 @@ struct elf_params_t | |||
166 | struct elf_section_t *last_section; | 36 | struct elf_section_t *last_section; |
167 | }; | 37 | }; |
168 | 38 | ||
39 | typedef bool (*elf_read_fn_t)(void *user, uint32_t addr, void *buf, size_t count); | ||
40 | /* write function manages it's own error state */ | ||
169 | typedef void (*elf_write_fn_t)(void *user, uint32_t addr, const void *buf, size_t count); | 41 | typedef void (*elf_write_fn_t)(void *user, uint32_t addr, const void *buf, size_t count); |
42 | typedef void (*elf_printf_fn_t)(void *user, bool error, const char *fmt, ...); | ||
170 | 43 | ||
171 | void elf_init(struct elf_params_t *params); | 44 | void elf_init(struct elf_params_t *params); |
172 | void elf_add_load_section(struct elf_params_t *params, | 45 | void elf_add_load_section(struct elf_params_t *params, |
173 | uint32_t load_addr, uint32_t size, const void *section); | 46 | uint32_t load_addr, uint32_t size, const void *section); |
174 | void elf_add_fill_section(struct elf_params_t *params, | 47 | void elf_add_fill_section(struct elf_params_t *params, |
175 | uint32_t fill_addr, uint32_t size, uint32_t pattern); | 48 | uint32_t fill_addr, uint32_t size, uint32_t pattern); |
176 | void elf_output(struct elf_params_t *params, elf_write_fn_t write, void *user); | 49 | void elf_write_file(struct elf_params_t *params, elf_write_fn_t write, void *user); |
50 | bool elf_read_file(struct elf_params_t *params, elf_read_fn_t read, elf_printf_fn_t printf, | ||
51 | void *user); | ||
177 | bool elf_is_empty(struct elf_params_t *params); | 52 | bool elf_is_empty(struct elf_params_t *params); |
178 | void elf_set_start_addr(struct elf_params_t *params, uint32_t addr); | 53 | void elf_set_start_addr(struct elf_params_t *params, uint32_t addr); |
54 | bool elf_get_start_addr(struct elf_params_t *params, uint32_t *addr); | ||
55 | int elf_get_nr_sections(struct elf_params_t *params); | ||
179 | void elf_release(struct elf_params_t *params); | 56 | void elf_release(struct elf_params_t *params); |
diff --git a/utils/sbtools/elftosb.c b/utils/sbtools/elftosb.c index 73768dd9a3..c4887ab47a 100644 --- a/utils/sbtools/elftosb.c +++ b/utils/sbtools/elftosb.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <string.h> | 31 | #include <string.h> |
32 | #include <ctype.h> | 32 | #include <ctype.h> |
33 | #include <time.h> | 33 | #include <time.h> |
34 | #include <stdarg.h> | ||
34 | 35 | ||
35 | #include "crypto.h" | 36 | #include "crypto.h" |
36 | #include "elf.h" | 37 | #include "elf.h" |
@@ -39,6 +40,12 @@ | |||
39 | #define bug(...) do { fprintf(stderr,"ERROR: "__VA_ARGS__); exit(1); } while(0) | 40 | #define bug(...) do { fprintf(stderr,"ERROR: "__VA_ARGS__); exit(1); } while(0) |
40 | #define bugp(a) do { perror("ERROR: "a); exit(1); } while(0) | 41 | #define bugp(a) do { perror("ERROR: "a); exit(1); } while(0) |
41 | 42 | ||
43 | bool g_debug = false; | ||
44 | |||
45 | /** | ||
46 | * Misc | ||
47 | */ | ||
48 | |||
42 | void *xmalloc(size_t s) /* malloc helper, used in elf.c */ | 49 | void *xmalloc(size_t s) /* malloc helper, used in elf.c */ |
43 | { | 50 | { |
44 | void * r = malloc(s); | 51 | void * r = malloc(s); |
@@ -67,6 +74,10 @@ static int convxdigit(char digit, byte *val) | |||
67 | return 1; | 74 | return 1; |
68 | } | 75 | } |
69 | 76 | ||
77 | /** | ||
78 | * Key file parsing | ||
79 | */ | ||
80 | |||
70 | typedef byte (*key_array_t)[16]; | 81 | typedef byte (*key_array_t)[16]; |
71 | 82 | ||
72 | static key_array_t read_keys(const char *key_file, int *num_keys) | 83 | static key_array_t read_keys(const char *key_file, int *num_keys) |
@@ -117,11 +128,18 @@ static key_array_t read_keys(const char *key_file, int *num_keys) | |||
117 | return keys; | 128 | return keys; |
118 | } | 129 | } |
119 | 130 | ||
131 | /** | ||
132 | * Command file parsing | ||
133 | */ | ||
134 | |||
120 | struct cmd_source_t | 135 | struct cmd_source_t |
121 | { | 136 | { |
122 | char *identifier; | 137 | char *identifier; |
123 | char *filename; | 138 | char *filename; |
124 | struct cmd_source_t *next; | 139 | struct cmd_source_t *next; |
140 | /* for later use */ | ||
141 | bool elf_loaded; | ||
142 | struct elf_params_t elf; | ||
125 | }; | 143 | }; |
126 | 144 | ||
127 | enum cmd_inst_type_t | 145 | enum cmd_inst_type_t |
@@ -142,6 +160,7 @@ struct cmd_section_t | |||
142 | { | 160 | { |
143 | uint32_t identifier; | 161 | uint32_t identifier; |
144 | struct cmd_inst_t *inst_list; | 162 | struct cmd_inst_t *inst_list; |
163 | struct cmd_section_t *next; | ||
145 | }; | 164 | }; |
146 | 165 | ||
147 | struct cmd_file_t | 166 | struct cmd_file_t |
@@ -171,7 +190,7 @@ struct lexem_t | |||
171 | uint32_t num; | 190 | uint32_t num; |
172 | }; | 191 | }; |
173 | 192 | ||
174 | void __parse_string(char **ptr, char *end, void *user, void (*emit_fn)(void *user, char c)) | 193 | static void __parse_string(char **ptr, char *end, void *user, void (*emit_fn)(void *user, char c)) |
175 | { | 194 | { |
176 | while(*ptr != end) | 195 | while(*ptr != end) |
177 | { | 196 | { |
@@ -196,19 +215,19 @@ void __parse_string(char **ptr, char *end, void *user, void (*emit_fn)(void *use | |||
196 | (*ptr)++; | 215 | (*ptr)++; |
197 | } | 216 | } |
198 | 217 | ||
199 | void __parse_string_emit(void *user, char c) | 218 | static void __parse_string_emit(void *user, char c) |
200 | { | 219 | { |
201 | char **pstr = (char **)user; | 220 | char **pstr = (char **)user; |
202 | *(*pstr)++ = c; | 221 | *(*pstr)++ = c; |
203 | } | 222 | } |
204 | 223 | ||
205 | void __parse_string_count(void *user, char c) | 224 | static void __parse_string_count(void *user, char c) |
206 | { | 225 | { |
207 | (void) c; | 226 | (void) c; |
208 | (*(int *)user)++; | 227 | (*(int *)user)++; |
209 | } | 228 | } |
210 | 229 | ||
211 | void parse_string(char **ptr, char *end, struct lexem_t *lexem) | 230 | static void parse_string(char **ptr, char *end, struct lexem_t *lexem) |
212 | { | 231 | { |
213 | /* skip " */ | 232 | /* skip " */ |
214 | (*ptr)++; | 233 | (*ptr)++; |
@@ -224,7 +243,7 @@ void parse_string(char **ptr, char *end, struct lexem_t *lexem) | |||
224 | __parse_string(ptr, end, (void *)&pstr, __parse_string_emit); | 243 | __parse_string(ptr, end, (void *)&pstr, __parse_string_emit); |
225 | } | 244 | } |
226 | 245 | ||
227 | void parse_number(char **ptr, char *end, struct lexem_t *lexem) | 246 | static void parse_number(char **ptr, char *end, struct lexem_t *lexem) |
228 | { | 247 | { |
229 | int base = 10; | 248 | int base = 10; |
230 | if(**ptr == '0' && (*ptr) + 1 != end && (*ptr)[1] == 'x') | 249 | if(**ptr == '0' && (*ptr) + 1 != end && (*ptr)[1] == 'x') |
@@ -247,7 +266,7 @@ void parse_number(char **ptr, char *end, struct lexem_t *lexem) | |||
247 | } | 266 | } |
248 | } | 267 | } |
249 | 268 | ||
250 | void parse_identifier(char **ptr, char *end, struct lexem_t *lexem) | 269 | static void parse_identifier(char **ptr, char *end, struct lexem_t *lexem) |
251 | { | 270 | { |
252 | /* remember position */ | 271 | /* remember position */ |
253 | char *old = *ptr; | 272 | char *old = *ptr; |
@@ -260,7 +279,7 @@ void parse_identifier(char **ptr, char *end, struct lexem_t *lexem) | |||
260 | memcpy(lexem->str, old, len); | 279 | memcpy(lexem->str, old, len); |
261 | } | 280 | } |
262 | 281 | ||
263 | void next_lexem(char **ptr, char *end, struct lexem_t *lexem) | 282 | static void next_lexem(char **ptr, char *end, struct lexem_t *lexem) |
264 | { | 283 | { |
265 | #define ret_simple(t, advance) ({(*ptr) += advance; lexem->type = t; return;}) | 284 | #define ret_simple(t, advance) ({(*ptr) += advance; lexem->type = t; return;}) |
266 | while(true) | 285 | while(true) |
@@ -294,7 +313,7 @@ void next_lexem(char **ptr, char *end, struct lexem_t *lexem) | |||
294 | #undef ret_simple | 313 | #undef ret_simple |
295 | } | 314 | } |
296 | 315 | ||
297 | void log_lexem(struct lexem_t *lexem) | 316 | static void log_lexem(struct lexem_t *lexem) |
298 | { | 317 | { |
299 | switch(lexem->type) | 318 | switch(lexem->type) |
300 | { | 319 | { |
@@ -312,19 +331,19 @@ void log_lexem(struct lexem_t *lexem) | |||
312 | } | 331 | } |
313 | } | 332 | } |
314 | 333 | ||
315 | char *find_source_by_id(struct cmd_file_t *cmd_file, const char *id) | 334 | static struct cmd_source_t *find_source_by_id(struct cmd_file_t *cmd_file, const char *id) |
316 | { | 335 | { |
317 | struct cmd_source_t *src = cmd_file->source_list; | 336 | struct cmd_source_t *src = cmd_file->source_list; |
318 | while(src) | 337 | while(src) |
319 | { | 338 | { |
320 | if(strcmp(src->identifier, id) == 0) | 339 | if(strcmp(src->identifier, id) == 0) |
321 | return src->filename; | 340 | return src; |
322 | src = src->next; | 341 | src = src->next; |
323 | } | 342 | } |
324 | return NULL; | 343 | return NULL; |
325 | } | 344 | } |
326 | 345 | ||
327 | struct cmd_file_t *read_command_file(const char *file) | 346 | static struct cmd_file_t *read_command_file(const char *file) |
328 | { | 347 | { |
329 | int size; | 348 | int size; |
330 | struct stat st; | 349 | struct stat st; |
@@ -380,6 +399,7 @@ struct cmd_file_t *read_command_file(const char *file) | |||
380 | } | 399 | } |
381 | 400 | ||
382 | /* sections */ | 401 | /* sections */ |
402 | struct cmd_section_t *end_sec = NULL; | ||
383 | while(true) | 403 | while(true) |
384 | { | 404 | { |
385 | struct cmd_section_t *sec = xmalloc(sizeof(struct cmd_section_t)); | 405 | struct cmd_section_t *sec = xmalloc(sizeof(struct cmd_section_t)); |
@@ -442,12 +462,184 @@ struct cmd_file_t *read_command_file(const char *file) | |||
442 | end_list = inst; | 462 | end_list = inst; |
443 | } | 463 | } |
444 | } | 464 | } |
465 | |||
466 | if(end_sec == NULL) | ||
467 | { | ||
468 | cmd_file->section_list = sec; | ||
469 | end_sec = sec; | ||
470 | } | ||
471 | else | ||
472 | { | ||
473 | end_sec->next = sec; | ||
474 | end_sec = sec; | ||
475 | } | ||
445 | } | 476 | } |
446 | #undef next | 477 | #undef next |
447 | 478 | ||
448 | return cmd_file; | 479 | return cmd_file; |
449 | } | 480 | } |
450 | 481 | ||
482 | /** | ||
483 | * command file to sb conversion | ||
484 | */ | ||
485 | |||
486 | struct sb_inst_t | ||
487 | { | ||
488 | uint8_t inst; /* SB_INST_* */ | ||
489 | uint32_t size; | ||
490 | // <union> | ||
491 | void *data; | ||
492 | uint32_t pattern; | ||
493 | uint32_t addr; | ||
494 | // </union> | ||
495 | }; | ||
496 | |||
497 | struct sb_section_t | ||
498 | { | ||
499 | uint32_t identifier; | ||
500 | int nr_insts; | ||
501 | struct sb_inst_t *insts; | ||
502 | }; | ||
503 | |||
504 | struct sb_file_t | ||
505 | { | ||
506 | int nr_sections; | ||
507 | struct sb_section_t *sections; | ||
508 | }; | ||
509 | |||
510 | static bool elf_read(void *user, uint32_t addr, void *buf, size_t count) | ||
511 | { | ||
512 | if(lseek(*(int *)user, addr, SEEK_SET) == (off_t)-1) | ||
513 | return false; | ||
514 | return read(*(int *)user, buf, count) == (ssize_t)count; | ||
515 | } | ||
516 | |||
517 | static void elf_printf(void *user, bool error, const char *fmt, ...) | ||
518 | { | ||
519 | if(!g_debug && !error) | ||
520 | return; | ||
521 | (void) user; | ||
522 | va_list args; | ||
523 | va_start(args, fmt); | ||
524 | vprintf(fmt, args); | ||
525 | va_end(args); | ||
526 | } | ||
527 | |||
528 | static void load_elf_by_id(struct cmd_file_t *cmd_file, const char *id) | ||
529 | { | ||
530 | struct cmd_source_t *src = find_source_by_id(cmd_file, id); | ||
531 | if(src == NULL) | ||
532 | bug("undefined reference to source '%s'\n", id); | ||
533 | /* avoid reloading */ | ||
534 | if(src->elf_loaded) | ||
535 | return; | ||
536 | int fd = open(src->filename, O_RDONLY); | ||
537 | if(fd < 0) | ||
538 | bug("cannot open '%s' (id '%s')\n", src->filename, id); | ||
539 | elf_init(&src->elf); | ||
540 | src->elf_loaded = elf_read_file(&src->elf, elf_read, elf_printf, &fd); | ||
541 | close(fd); | ||
542 | if(!src->elf_loaded) | ||
543 | bug("error loading elf file '%s' (id '%s')\n", src->filename, id); | ||
544 | } | ||
545 | |||
546 | static struct sb_file_t *apply_cmd_file(struct cmd_file_t *cmd_file) | ||
547 | { | ||
548 | struct sb_file_t *sb = xmalloc(sizeof(struct sb_file_t)); | ||
549 | memset(sb, 0, sizeof(struct sb_file_t)); | ||
550 | /* count sections */ | ||
551 | struct cmd_section_t *csec = cmd_file->section_list; | ||
552 | while(csec) | ||
553 | { | ||
554 | sb->nr_sections++; | ||
555 | csec = csec->next; | ||
556 | } | ||
557 | |||
558 | sb->sections = xmalloc(sb->nr_sections * sizeof(struct sb_section_t)); | ||
559 | memset(sb->sections, 0, sb->nr_sections * sizeof(struct sb_section_t)); | ||
560 | /* flatten sections */ | ||
561 | csec = cmd_file->section_list; | ||
562 | for(int i = 0; i < sb->nr_sections; i++, csec = csec->next) | ||
563 | { | ||
564 | struct sb_section_t *sec = &sb->sections[i]; | ||
565 | sec->identifier = csec->identifier; | ||
566 | /* count instructions */ | ||
567 | struct cmd_inst_t *cinst = csec->inst_list; | ||
568 | while(cinst) | ||
569 | { | ||
570 | load_elf_by_id(cmd_file, cinst->identifier); | ||
571 | struct elf_params_t *elf = &find_source_by_id(cmd_file, cinst->identifier)->elf; | ||
572 | |||
573 | if(cinst->type == CMD_LOAD) | ||
574 | sec->nr_insts += elf_get_nr_sections(elf); | ||
575 | else if(cinst->type == CMD_JUMP || cinst->type == CMD_LOAD) | ||
576 | { | ||
577 | if(!elf_get_start_addr(elf, NULL)) | ||
578 | bug("cannot jump/call '%s' because it has no starting point !", cinst->identifier); | ||
579 | sec->nr_insts++; | ||
580 | } | ||
581 | |||
582 | cinst = cinst->next; | ||
583 | } | ||
584 | |||
585 | sec->insts = xmalloc(sec->nr_insts * sizeof(struct sb_inst_t)); | ||
586 | memset(sec->insts, 0, sec->nr_insts * sizeof(struct sb_inst_t)); | ||
587 | /* flatten */ | ||
588 | int idx = 0; | ||
589 | cinst = csec->inst_list; | ||
590 | while(cinst) | ||
591 | { | ||
592 | struct elf_params_t *elf = &find_source_by_id(cmd_file, cinst->identifier)->elf; | ||
593 | |||
594 | if(cinst->type == CMD_LOAD) | ||
595 | { | ||
596 | struct elf_section_t *esec = elf->first_section; | ||
597 | while(esec) | ||
598 | { | ||
599 | if(esec->type == EST_LOAD) | ||
600 | { | ||
601 | sec->insts[idx].inst = SB_INST_LOAD; | ||
602 | sec->insts[idx].addr = esec->addr; | ||
603 | sec->insts[idx].size = esec->size; | ||
604 | sec->insts[idx++].data = esec->section; | ||
605 | if(g_debug) | ||
606 | printf("LOAD | addr=0x%08x | len=0x%08x | crc=0x%08x\n", | ||
607 | esec->addr, esec->size, 0); | ||
608 | } | ||
609 | else if(esec->type == EST_FILL) | ||
610 | { | ||
611 | sec->insts[idx].inst = SB_INST_FILL; | ||
612 | sec->insts[idx].addr = esec->addr; | ||
613 | sec->insts[idx].size = esec->size; | ||
614 | sec->insts[idx++].pattern = esec->pattern; | ||
615 | if(g_debug) | ||
616 | printf("FILL | addr=0x%08x | len=0x%08x | pattern=0x%08x\n", | ||
617 | esec->addr, esec->size, esec->pattern); | ||
618 | } | ||
619 | esec = esec->next; | ||
620 | } | ||
621 | } | ||
622 | else if(cinst->type == CMD_JUMP || cinst->type == CMD_LOAD) | ||
623 | { | ||
624 | sec->insts[idx].inst = (cinst->type == CMD_JUMP) ? SB_INST_JUMP : SB_INST_CALL; | ||
625 | sec->insts[idx++].addr = elf->start_addr; | ||
626 | if(g_debug) | ||
627 | printf("%s | addr=0x%08x | arg=0x%08x\n", | ||
628 | (cinst->type == CMD_JUMP) ? "JUMP" : "CALL", | ||
629 | elf->start_addr, 0); | ||
630 | } | ||
631 | |||
632 | cinst = cinst->next; | ||
633 | } | ||
634 | } | ||
635 | |||
636 | return sb; | ||
637 | } | ||
638 | |||
639 | /** | ||
640 | * Sb file production | ||
641 | */ | ||
642 | |||
451 | #define ROUND_UP(val, round) ((((val) + (round) - 1) / (round)) * (round)) | 643 | #define ROUND_UP(val, round) ((((val) + (round) - 1) / (round)) * (round)) |
452 | 644 | ||
453 | static uint8_t instruction_checksum(struct sb_instruction_header_t *hdr) | 645 | static uint8_t instruction_checksum(struct sb_instruction_header_t *hdr) |
@@ -467,6 +659,7 @@ int main(int argc, const char **argv) | |||
467 | int nr_keys; | 659 | int nr_keys; |
468 | key_array_t key_array = read_keys(argv[2], &nr_keys); | 660 | key_array_t key_array = read_keys(argv[2], &nr_keys); |
469 | struct cmd_file_t *cmd_file = read_command_file(argv[1]); | 661 | struct cmd_file_t *cmd_file = read_command_file(argv[1]); |
662 | struct sb_file_t *sb_file = apply_cmd_file(cmd_file); | ||
470 | 663 | ||
471 | return 0; | 664 | return 0; |
472 | } | 665 | } |
diff --git a/utils/sbtools/sbtoelf.c b/utils/sbtools/sbtoelf.c index 3eb168ddd1..3a3d9a7bb7 100644 --- a/utils/sbtools/sbtoelf.c +++ b/utils/sbtools/sbtoelf.c | |||
@@ -183,7 +183,7 @@ static void extract_elf_section(struct elf_params_t *elf, int count, const char | |||
183 | 183 | ||
184 | if(fd == NULL) | 184 | if(fd == NULL) |
185 | return ; | 185 | return ; |
186 | elf_output(elf, elf_write, fd); | 186 | elf_write_file(elf, elf_write, fd); |
187 | fclose(fd); | 187 | fclose(fd); |
188 | } | 188 | } |
189 | 189 | ||