summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAmaury Pouly <pamaury@rockbox.org>2010-12-01 16:17:11 +0000
committerAmaury Pouly <pamaury@rockbox.org>2010-12-01 16:17:11 +0000
commit1583b1cd53282efda61ab00da64e627667d9cda9 (patch)
tree6b6f45eb38196da379b49be0ba129071e0a64f12
parent71ad3679dcb48e946fb3740276d0fc12842148db (diff)
downloadrockbox-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/Makefile4
-rw-r--r--utils/sbinfo/elf.c169
-rw-r--r--utils/sbinfo/elf.h140
-rw-r--r--utils/sbinfo/sbinfo.c52
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
3all: $(TGT) 3all: $(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
8clean: 8clean:
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
3void 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
11extern void *xmalloc(size_t s);
12
13static 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
28void 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
40void 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
57void 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
144bool elf_is_empty(struct elf_params_t *params)
145{
146 return params->first_section == NULL;
147}
148
149void 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
155void 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 */
14typedef uint16_t Elf32_Half;
15
16typedef uint32_t Elf32_Word;
17typedef int32_t Elf32_Sword;
18typedef uint32_t Elf32_Addr;
19typedef uint32_t Elf32_Off;
20typedef uint16_t Elf32_Section;
21
22#define EI_NIDENT 16
23
24typedef 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
81typedef 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 */
102enum elf_section_type_t
103{
104 EST_LOAD,
105 EST_FILL
106};
107
108struct 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
122struct 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
130typedef void (*elf_write_fn_t)(void *user, uint32_t addr, const void *buf, size_t count);
131
132void elf_init(struct elf_params_t *params);
133void elf_add_load_section(struct elf_params_t *params,
134 uint32_t load_addr, uint32_t size, const void *section);
135void elf_add_fill_section(struct elf_params_t *params,
136 uint32_t fill_addr, uint32_t size, uint32_t pattern);
137void elf_output(struct elf_params_t *params, elf_write_fn_t write, void *user);
138bool elf_is_empty(struct elf_params_t *params);
139void elf_set_start_addr(struct elf_params_t *params, uint32_t addr);
140void 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
120static void *xmalloc(size_t s) /* malloc helper */ 122void *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
264static 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
271static 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
262static void extract_section(int data_sec, char name[5], byte *buf, int size, const char *indent) 286static 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
364static void extract(unsigned long filesize) 412static void extract(unsigned long filesize)