diff options
author | Amaury Pouly <pamaury@rockbox.org> | 2010-12-01 16:17:11 +0000 |
---|---|---|
committer | Amaury Pouly <pamaury@rockbox.org> | 2010-12-01 16:17:11 +0000 |
commit | 1583b1cd53282efda61ab00da64e627667d9cda9 (patch) | |
tree | 6b6f45eb38196da379b49be0ba129071e0a64f12 | |
parent | 71ad3679dcb48e946fb3740276d0fc12842148db (diff) | |
download | rockbox-1583b1cd53282efda61ab00da64e627667d9cda9.tar.gz rockbox-1583b1cd53282efda61ab00da64e627667d9cda9.zip |
sbinfo: first try at creating an elf file out of the .sb mess
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@28717 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r-- | utils/sbinfo/Makefile | 4 | ||||
-rw-r--r-- | utils/sbinfo/elf.c | 169 | ||||
-rw-r--r-- | utils/sbinfo/elf.h | 140 | ||||
-rw-r--r-- | utils/sbinfo/sbinfo.c | 52 |
4 files changed, 361 insertions, 4 deletions
diff --git a/utils/sbinfo/Makefile b/utils/sbinfo/Makefile index 8b2cd2649d..9427eaf875 100644 --- a/utils/sbinfo/Makefile +++ b/utils/sbinfo/Makefile | |||
@@ -2,8 +2,8 @@ TGT = sbinfo | |||
2 | 2 | ||
3 | all: $(TGT) | 3 | all: $(TGT) |
4 | 4 | ||
5 | $(TGT): sbinfo.c crc.c crypto.h aes128.c sha1.c | 5 | $(TGT): sbinfo.c crc.c crypto.h aes128.c sha1.c elf.c |
6 | $(CC) -g -std=c99 -o $(TGT) -W -Wall sbinfo.c aes128.c crc.c sha1.c | 6 | $(CC) -g -std=c99 -o $(TGT) -W -Wall sbinfo.c aes128.c crc.c sha1.c elf.c |
7 | 7 | ||
8 | clean: | 8 | clean: |
9 | rm -fr $(TGT) | 9 | rm -fr $(TGT) |
diff --git a/utils/sbinfo/elf.c b/utils/sbinfo/elf.c new file mode 100644 index 0000000000..0fe6792e1d --- /dev/null +++ b/utils/sbinfo/elf.c | |||
@@ -0,0 +1,169 @@ | |||
1 | #include "elf.h" | ||
2 | |||
3 | void elf_init(struct elf_params_t *params) | ||
4 | { | ||
5 | params->has_start_addr = false; | ||
6 | params->start_addr = 0; | ||
7 | params->first_section = NULL; | ||
8 | params->last_section = NULL; | ||
9 | } | ||
10 | |||
11 | extern void *xmalloc(size_t s); | ||
12 | |||
13 | static struct elf_section_t *elf_add_section(struct elf_params_t *params) | ||
14 | { | ||
15 | struct elf_section_t *sec = xmalloc(sizeof(struct elf_section_t)); | ||
16 | if(params->first_section == NULL) | ||
17 | params->first_section = params->last_section = sec; | ||
18 | else | ||
19 | { | ||
20 | params->last_section->next = sec; | ||
21 | params->last_section = sec; | ||
22 | } | ||
23 | sec->next = NULL; | ||
24 | |||
25 | return sec; | ||
26 | } | ||
27 | |||
28 | void elf_add_load_section(struct elf_params_t *params, | ||
29 | uint32_t load_addr, uint32_t size, const void *section) | ||
30 | { | ||
31 | struct elf_section_t *sec = elf_add_section(params); | ||
32 | |||
33 | sec->type = EST_LOAD; | ||
34 | sec->addr = load_addr; | ||
35 | sec->size = size; | ||
36 | sec->section = xmalloc(size); | ||
37 | memcpy(sec->section, section, size); | ||
38 | } | ||
39 | |||
40 | void elf_add_fill_section(struct elf_params_t *params, | ||
41 | uint32_t fill_addr, uint32_t size, uint32_t pattern) | ||
42 | { | ||
43 | if(pattern != 0x00) | ||
44 | { | ||
45 | printf("oops, non-zero filling, ignore fill section\n"); | ||
46 | return; | ||
47 | } | ||
48 | |||
49 | struct elf_section_t *sec = elf_add_section(params); | ||
50 | |||
51 | sec->type = EST_FILL; | ||
52 | sec->addr = fill_addr; | ||
53 | sec->size = size; | ||
54 | sec->pattern = pattern; | ||
55 | } | ||
56 | |||
57 | void elf_output(struct elf_params_t *params, elf_write_fn_t write, void *user) | ||
58 | { | ||
59 | Elf32_Ehdr ehdr; | ||
60 | uint32_t phoff = sizeof(Elf32_Ehdr); | ||
61 | uint32_t phentsize = sizeof(Elf32_Phdr); | ||
62 | uint32_t phnum = 0; | ||
63 | uint32_t shstrndx = SHN_UNDEF; | ||
64 | struct elf_section_t *sec = params->first_section; | ||
65 | uint32_t offset = 0; | ||
66 | Elf32_Phdr phdr; | ||
67 | |||
68 | while(sec) | ||
69 | { | ||
70 | if(sec->type == EST_LOAD) | ||
71 | { | ||
72 | sec->offset = offset; | ||
73 | offset += sec->size; | ||
74 | } | ||
75 | |||
76 | phnum++; | ||
77 | sec = sec->next; | ||
78 | } | ||
79 | |||
80 | memset(&ehdr, 0, EI_NIDENT); | ||
81 | ehdr.e_ident[EI_MAG0] = ELFMAG0; | ||
82 | ehdr.e_ident[EI_MAG1] = ELFMAG1; | ||
83 | ehdr.e_ident[EI_MAG2] = ELFMAG2; | ||
84 | ehdr.e_ident[EI_MAG3] = ELFMAG3; | ||
85 | ehdr.e_ident[EI_CLASS] = ELFCLASS32; | ||
86 | ehdr.e_ident[EI_DATA] = ELFDATA2LSB; | ||
87 | ehdr.e_ident[EI_VERSION] = EV_CURRENT; | ||
88 | ehdr.e_ident[EI_OSABI] = ELFOSABI_NONE; | ||
89 | ehdr.e_ident[EI_ABIVERSION] = 0; | ||
90 | ehdr.e_type = ET_EXEC; | ||
91 | ehdr.e_machine = EM_ARM; | ||
92 | ehdr.e_version = EV_CURRENT; | ||
93 | ehdr.e_entry = params->start_addr; | ||
94 | ehdr.e_phoff = phoff; | ||
95 | ehdr.e_shoff = 0; | ||
96 | ehdr.e_flags = 0; | ||
97 | if(params->has_start_addr) | ||
98 | ehdr.e_flags |= EF_ARM_HASENTRY; | ||
99 | ehdr.e_ehsize = sizeof ehdr; | ||
100 | ehdr.e_phentsize = phentsize; | ||
101 | ehdr.e_phnum = phnum; | ||
102 | ehdr.e_shentsize = 0; | ||
103 | ehdr.e_shnum = 0; | ||
104 | ehdr.e_shstrndx = shstrndx; | ||
105 | |||
106 | write(user, 0, &ehdr, sizeof ehdr); | ||
107 | |||
108 | sec = params->first_section; | ||
109 | offset = phoff; | ||
110 | while(sec) | ||
111 | { | ||
112 | sec->offset += phoff + phnum * phentsize; | ||
113 | |||
114 | phdr.p_type = PT_LOAD; | ||
115 | if(sec->type == EST_LOAD) | ||
116 | phdr.p_offset = sec->offset; | ||
117 | else | ||
118 | phdr.p_offset = 0; | ||
119 | phdr.p_paddr = sec->addr; | ||
120 | phdr.p_vaddr = phdr.p_paddr; /* assume identity map ? */ | ||
121 | phdr.p_memsz = sec->size; | ||
122 | if(sec->type == EST_LOAD) | ||
123 | phdr.p_filesz = phdr.p_memsz; | ||
124 | else | ||
125 | phdr.p_filesz = 0; | ||
126 | phdr.p_flags = PF_X | PF_W | PF_R; | ||
127 | phdr.p_align = 0; | ||
128 | |||
129 | write(user, offset, &phdr, sizeof phdr); | ||
130 | |||
131 | offset += sizeof(Elf32_Phdr); | ||
132 | sec = sec->next; | ||
133 | } | ||
134 | |||
135 | sec = params->first_section; | ||
136 | while(sec) | ||
137 | { | ||
138 | if(sec->type == EST_LOAD) | ||
139 | write(user, sec->offset, sec->section, sec->size); | ||
140 | sec = sec->next; | ||
141 | } | ||
142 | } | ||
143 | |||
144 | bool elf_is_empty(struct elf_params_t *params) | ||
145 | { | ||
146 | return params->first_section == NULL; | ||
147 | } | ||
148 | |||
149 | void elf_set_start_addr(struct elf_params_t *params, uint32_t addr) | ||
150 | { | ||
151 | params->has_start_addr = true; | ||
152 | params->start_addr = addr; | ||
153 | } | ||
154 | |||
155 | void elf_release(struct elf_params_t *params) | ||
156 | { | ||
157 | struct elf_section_t *sec, *next_sec; | ||
158 | sec = params->first_section; | ||
159 | while(sec) | ||
160 | { | ||
161 | next_sec = sec->next; | ||
162 | if(sec->type == EST_LOAD) | ||
163 | free(sec->section); | ||
164 | free(sec); | ||
165 | sec = next_sec; | ||
166 | } | ||
167 | params->first_section = NULL; | ||
168 | params->last_section = NULL; | ||
169 | } | ||
diff --git a/utils/sbinfo/elf.h b/utils/sbinfo/elf.h new file mode 100644 index 0000000000..6835178289 --- /dev/null +++ b/utils/sbinfo/elf.h | |||
@@ -0,0 +1,140 @@ | |||
1 | #include <stdio.h> | ||
2 | #include <stdint.h> | ||
3 | #include <string.h> | ||
4 | #include <stdbool.h> | ||
5 | #include <stdlib.h> | ||
6 | #include <unistd.h> | ||
7 | |||
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 0x0 | ||
78 | |||
79 | #define SHN_UNDEF 0 /* Undefined section */ | ||
80 | |||
81 | typedef struct | ||
82 | { | ||
83 | Elf32_Word p_type; /* Segment type */ | ||
84 | Elf32_Off p_offset; /* Segment file offset */ | ||
85 | Elf32_Addr p_vaddr; /* Segment virtual address */ | ||
86 | Elf32_Addr p_paddr; /* Segment physical address */ | ||
87 | Elf32_Word p_filesz; /* Segment size in file */ | ||
88 | Elf32_Word p_memsz; /* Segment size in memory */ | ||
89 | Elf32_Word p_flags; /* Segment flags */ | ||
90 | Elf32_Word p_align; /* Segment alignment */ | ||
91 | }Elf32_Phdr; | ||
92 | |||
93 | #define PT_LOAD 1 /* Loadable program segment */ | ||
94 | |||
95 | #define PF_X (1 << 0) /* Segment is executable */ | ||
96 | #define PF_W (1 << 1) /* Segment is writable */ | ||
97 | #define PF_R (1 << 2) /* Segment is readable */ | ||
98 | |||
99 | /** | ||
100 | * API | ||
101 | */ | ||
102 | enum elf_section_type_t | ||
103 | { | ||
104 | EST_LOAD, | ||
105 | EST_FILL | ||
106 | }; | ||
107 | |||
108 | struct elf_section_t | ||
109 | { | ||
110 | uint32_t addr; | ||
111 | uint32_t size; | ||
112 | enum elf_section_type_t type; | ||
113 | /* <union> */ | ||
114 | void *section; | ||
115 | uint32_t pattern; | ||
116 | /* </union> */ | ||
117 | struct elf_section_t *next; | ||
118 | /* Internal to elf_output */ | ||
119 | uint32_t offset; | ||
120 | }; | ||
121 | |||
122 | struct elf_params_t | ||
123 | { | ||
124 | bool has_start_addr; | ||
125 | uint32_t start_addr; | ||
126 | struct elf_section_t *first_section; | ||
127 | struct elf_section_t *last_section; | ||
128 | }; | ||
129 | |||
130 | typedef void (*elf_write_fn_t)(void *user, uint32_t addr, const void *buf, size_t count); | ||
131 | |||
132 | void elf_init(struct elf_params_t *params); | ||
133 | void elf_add_load_section(struct elf_params_t *params, | ||
134 | uint32_t load_addr, uint32_t size, const void *section); | ||
135 | void elf_add_fill_section(struct elf_params_t *params, | ||
136 | uint32_t fill_addr, uint32_t size, uint32_t pattern); | ||
137 | void elf_output(struct elf_params_t *params, elf_write_fn_t write, void *user); | ||
138 | bool elf_is_empty(struct elf_params_t *params); | ||
139 | void elf_set_start_addr(struct elf_params_t *params, uint32_t addr); | ||
140 | void elf_release(struct elf_params_t *params); | ||
diff --git a/utils/sbinfo/sbinfo.c b/utils/sbinfo/sbinfo.c index 74b5a0b7be..361764310f 100644 --- a/utils/sbinfo/sbinfo.c +++ b/utils/sbinfo/sbinfo.c | |||
@@ -38,7 +38,9 @@ | |||
38 | #include <string.h> | 38 | #include <string.h> |
39 | #include <ctype.h> | 39 | #include <ctype.h> |
40 | #include <time.h> | 40 | #include <time.h> |
41 | |||
41 | #include "crypto.h" | 42 | #include "crypto.h" |
43 | #include "elf.h" | ||
42 | 44 | ||
43 | #if 1 /* ANSI colors */ | 45 | #if 1 /* ANSI colors */ |
44 | 46 | ||
@@ -117,7 +119,7 @@ struct sb_instruction_call_t | |||
117 | uint32_t arg; | 119 | uint32_t arg; |
118 | } __attribute__((packed)); | 120 | } __attribute__((packed)); |
119 | 121 | ||
120 | static void *xmalloc(size_t s) /* malloc helper */ | 122 | void *xmalloc(size_t s) /* malloc helper, used in elf.c */ |
121 | { | 123 | { |
122 | void * r = malloc(s); | 124 | void * r = malloc(s); |
123 | if(!r) bugp("malloc"); | 125 | if(!r) bugp("malloc"); |
@@ -259,9 +261,31 @@ static uint8_t instruction_checksum(struct sb_instruction_header_t *hdr) | |||
259 | return sum; | 261 | return sum; |
260 | } | 262 | } |
261 | 263 | ||
264 | static void elf_write(void *user, uint32_t addr, const void *buf, size_t count) | ||
265 | { | ||
266 | FILE *f = user; | ||
267 | fseek(f, addr, SEEK_SET); | ||
268 | fwrite(buf, count, 1, f); | ||
269 | } | ||
270 | |||
271 | static void extract_elf_section(struct elf_params_t *elf, int count, const char *prefix) | ||
272 | { | ||
273 | char *filename = xmalloc(strlen(prefix) + 32); | ||
274 | sprintf(filename, "%s.%d.elf", prefix, count); | ||
275 | printf("write %s\n", filename); | ||
276 | |||
277 | FILE *fd = fopen(filename, "wb"); | ||
278 | free(filename); | ||
279 | |||
280 | if(fd == NULL) | ||
281 | return ; | ||
282 | elf_output(elf, elf_write, fd); | ||
283 | fclose(fd); | ||
284 | } | ||
285 | |||
262 | static void extract_section(int data_sec, char name[5], byte *buf, int size, const char *indent) | 286 | static void extract_section(int data_sec, char name[5], byte *buf, int size, const char *indent) |
263 | { | 287 | { |
264 | char filename[PREFIX_SIZE + 16]; | 288 | char filename[PREFIX_SIZE + 32]; |
265 | snprintf(filename, sizeof filename, "%s%s.bin", out_prefix, name); | 289 | snprintf(filename, sizeof filename, "%s%s.bin", out_prefix, name); |
266 | FILE *fd = fopen(filename, "wb"); | 290 | FILE *fd = fopen(filename, "wb"); |
267 | if (fd != NULL) { | 291 | if (fd != NULL) { |
@@ -270,6 +294,13 @@ static void extract_section(int data_sec, char name[5], byte *buf, int size, con | |||
270 | } | 294 | } |
271 | if(data_sec) | 295 | if(data_sec) |
272 | return; | 296 | return; |
297 | |||
298 | snprintf(filename, sizeof filename, "%s%s", out_prefix, name); | ||
299 | |||
300 | /* elf construction */ | ||
301 | struct elf_params_t elf; | ||
302 | elf_init(&elf); | ||
303 | int elf_count = 0; | ||
273 | /* Pretty print the content */ | 304 | /* Pretty print the content */ |
274 | int pos = 0; | 305 | int pos = 0; |
275 | while(pos < size) | 306 | while(pos < size) |
@@ -306,6 +337,10 @@ static void extract_section(int data_sec, char name[5], byte *buf, int size, con | |||
306 | else | 337 | else |
307 | printf(" Failed (crc=0x%08x)\n", computed_crc); | 338 | printf(" Failed (crc=0x%08x)\n", computed_crc); |
308 | 339 | ||
340 | /* elf construction */ | ||
341 | elf_add_load_section(&elf, load->addr, load->len, | ||
342 | &buf[pos + sizeof(struct sb_instruction_load_t)]); | ||
343 | |||
309 | pos += load->len + sizeof(struct sb_instruction_load_t); | 344 | pos += load->len + sizeof(struct sb_instruction_load_t); |
310 | // unsure about rounding | 345 | // unsure about rounding |
311 | pos = ROUND_UP(pos, 16); | 346 | pos = ROUND_UP(pos, 16); |
@@ -326,6 +361,9 @@ static void extract_section(int data_sec, char name[5], byte *buf, int size, con | |||
326 | printf("pattern=0x%08x\n", fill->pattern); | 361 | printf("pattern=0x%08x\n", fill->pattern); |
327 | color(OFF); | 362 | color(OFF); |
328 | 363 | ||
364 | /* elf construction */ | ||
365 | elf_add_fill_section(&elf, fill->addr, fill->len, fill->pattern); | ||
366 | |||
329 | pos += sizeof(struct sb_instruction_fill_t); | 367 | pos += sizeof(struct sb_instruction_fill_t); |
330 | // fixme: useless as pos is a multiple of 16 and fill struct is 4-bytes wide ? | 368 | // fixme: useless as pos is a multiple of 16 and fill struct is 4-bytes wide ? |
331 | pos = ROUND_UP(pos, 16); | 369 | pos = ROUND_UP(pos, 16); |
@@ -348,6 +386,12 @@ static void extract_section(int data_sec, char name[5], byte *buf, int size, con | |||
348 | printf("arg=0x%08x\n", call->arg); | 386 | printf("arg=0x%08x\n", call->arg); |
349 | color(OFF); | 387 | color(OFF); |
350 | 388 | ||
389 | /* elf construction */ | ||
390 | elf_set_start_addr(&elf, call->addr); | ||
391 | extract_elf_section(&elf, elf_count++, filename); | ||
392 | elf_release(&elf); | ||
393 | elf_init(&elf); | ||
394 | |||
351 | pos += sizeof(struct sb_instruction_call_t); | 395 | pos += sizeof(struct sb_instruction_call_t); |
352 | // fixme: useless as pos is a multiple of 16 and call struct is 4-bytes wide ? | 396 | // fixme: useless as pos is a multiple of 16 and call struct is 4-bytes wide ? |
353 | pos = ROUND_UP(pos, 16); | 397 | pos = ROUND_UP(pos, 16); |
@@ -359,6 +403,10 @@ static void extract_section(int data_sec, char name[5], byte *buf, int size, con | |||
359 | break; | 403 | break; |
360 | } | 404 | } |
361 | } | 405 | } |
406 | |||
407 | if(elf_is_empty(&elf)) | ||
408 | extract_elf_section(&elf, elf_count++, filename); | ||
409 | elf_release(&elf); | ||
362 | } | 410 | } |
363 | 411 | ||
364 | static void extract(unsigned long filesize) | 412 | static void extract(unsigned long filesize) |