summaryrefslogtreecommitdiffstats
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
all: $(TGT)
-$(TGT): sbinfo.c crc.c crypto.h aes128.c sha1.c
- $(CC) -g -std=c99 -o $(TGT) -W -Wall sbinfo.c aes128.c crc.c sha1.c
+$(TGT): sbinfo.c crc.c crypto.h aes128.c sha1.c elf.c
+ $(CC) -g -std=c99 -o $(TGT) -W -Wall sbinfo.c aes128.c crc.c sha1.c elf.c
clean:
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 @@
+#include "elf.h"
+
+void elf_init(struct elf_params_t *params)
+{
+ params->has_start_addr = false;
+ params->start_addr = 0;
+ params->first_section = NULL;
+ params->last_section = NULL;
+}
+
+extern void *xmalloc(size_t s);
+
+static struct elf_section_t *elf_add_section(struct elf_params_t *params)
+{
+ struct elf_section_t *sec = xmalloc(sizeof(struct elf_section_t));
+ if(params->first_section == NULL)
+ params->first_section = params->last_section = sec;
+ else
+ {
+ params->last_section->next = sec;
+ params->last_section = sec;
+ }
+ sec->next = NULL;
+
+ return sec;
+}
+
+void elf_add_load_section(struct elf_params_t *params,
+ uint32_t load_addr, uint32_t size, const void *section)
+{
+ struct elf_section_t *sec = elf_add_section(params);
+
+ sec->type = EST_LOAD;
+ sec->addr = load_addr;
+ sec->size = size;
+ sec->section = xmalloc(size);
+ memcpy(sec->section, section, size);
+}
+
+void elf_add_fill_section(struct elf_params_t *params,
+ uint32_t fill_addr, uint32_t size, uint32_t pattern)
+{
+ if(pattern != 0x00)
+ {
+ printf("oops, non-zero filling, ignore fill section\n");
+ return;
+ }
+
+ struct elf_section_t *sec = elf_add_section(params);
+
+ sec->type = EST_FILL;
+ sec->addr = fill_addr;
+ sec->size = size;
+ sec->pattern = pattern;
+}
+
+void elf_output(struct elf_params_t *params, elf_write_fn_t write, void *user)
+{
+ Elf32_Ehdr ehdr;
+ uint32_t phoff = sizeof(Elf32_Ehdr);
+ uint32_t phentsize = sizeof(Elf32_Phdr);
+ uint32_t phnum = 0;
+ uint32_t shstrndx = SHN_UNDEF;
+ struct elf_section_t *sec = params->first_section;
+ uint32_t offset = 0;
+ Elf32_Phdr phdr;
+
+ while(sec)
+ {
+ if(sec->type == EST_LOAD)
+ {
+ sec->offset = offset;
+ offset += sec->size;
+ }
+
+ phnum++;
+ sec = sec->next;
+ }
+
+ memset(&ehdr, 0, EI_NIDENT);
+ ehdr.e_ident[EI_MAG0] = ELFMAG0;
+ ehdr.e_ident[EI_MAG1] = ELFMAG1;
+ ehdr.e_ident[EI_MAG2] = ELFMAG2;
+ ehdr.e_ident[EI_MAG3] = ELFMAG3;
+ ehdr.e_ident[EI_CLASS] = ELFCLASS32;
+ ehdr.e_ident[EI_DATA] = ELFDATA2LSB;
+ ehdr.e_ident[EI_VERSION] = EV_CURRENT;
+ ehdr.e_ident[EI_OSABI] = ELFOSABI_NONE;
+ ehdr.e_ident[EI_ABIVERSION] = 0;
+ ehdr.e_type = ET_EXEC;
+ ehdr.e_machine = EM_ARM;
+ ehdr.e_version = EV_CURRENT;
+ ehdr.e_entry = params->start_addr;
+ ehdr.e_phoff = phoff;
+ ehdr.e_shoff = 0;
+ ehdr.e_flags = 0;
+ if(params->has_start_addr)
+ ehdr.e_flags |= EF_ARM_HASENTRY;
+ ehdr.e_ehsize = sizeof ehdr;
+ ehdr.e_phentsize = phentsize;
+ ehdr.e_phnum = phnum;
+ ehdr.e_shentsize = 0;
+ ehdr.e_shnum = 0;
+ ehdr.e_shstrndx = shstrndx;
+
+ write(user, 0, &ehdr, sizeof ehdr);
+
+ sec = params->first_section;
+ offset = phoff;
+ while(sec)
+ {
+ sec->offset += phoff + phnum * phentsize;
+
+ phdr.p_type = PT_LOAD;
+ if(sec->type == EST_LOAD)
+ phdr.p_offset = sec->offset;
+ else
+ phdr.p_offset = 0;
+ phdr.p_paddr = sec->addr;
+ phdr.p_vaddr = phdr.p_paddr; /* assume identity map ? */
+ phdr.p_memsz = sec->size;
+ if(sec->type == EST_LOAD)
+ phdr.p_filesz = phdr.p_memsz;
+ else
+ phdr.p_filesz = 0;
+ phdr.p_flags = PF_X | PF_W | PF_R;
+ phdr.p_align = 0;
+
+ write(user, offset, &phdr, sizeof phdr);
+
+ offset += sizeof(Elf32_Phdr);
+ sec = sec->next;
+ }
+
+ sec = params->first_section;
+ while(sec)
+ {
+ if(sec->type == EST_LOAD)
+ write(user, sec->offset, sec->section, sec->size);
+ sec = sec->next;
+ }
+}
+
+bool elf_is_empty(struct elf_params_t *params)
+{
+ return params->first_section == NULL;
+}
+
+void elf_set_start_addr(struct elf_params_t *params, uint32_t addr)
+{
+ params->has_start_addr = true;
+ params->start_addr = addr;
+}
+
+void elf_release(struct elf_params_t *params)
+{
+ struct elf_section_t *sec, *next_sec;
+ sec = params->first_section;
+ while(sec)
+ {
+ next_sec = sec->next;
+ if(sec->type == EST_LOAD)
+ free(sec->section);
+ free(sec);
+ sec = next_sec;
+ }
+ params->first_section = NULL;
+ params->last_section = NULL;
+}
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 @@
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+/**
+ * Definitions
+ * taken from elf.h linux header
+ * based on ELF specification
+ * based on ARM ELF specification
+ */
+typedef uint16_t Elf32_Half;
+
+typedef uint32_t Elf32_Word;
+typedef int32_t Elf32_Sword;
+typedef uint32_t Elf32_Addr;
+typedef uint32_t Elf32_Off;
+typedef uint16_t Elf32_Section;
+
+#define EI_NIDENT 16
+
+typedef struct
+{
+ unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */
+ Elf32_Half e_type; /* Object file type */
+ Elf32_Half e_machine; /* Architecture */
+ Elf32_Word e_version; /* Object file version */
+ Elf32_Addr e_entry; /* Entry point virtual address */
+ Elf32_Off e_phoff; /* Program header table file offset */
+ Elf32_Off e_shoff; /* Section header table file offset */
+ Elf32_Word e_flags; /* Processor-specific flags */
+ Elf32_Half e_ehsize; /* ELF header size in bytes */
+ Elf32_Half e_phentsize; /* Program header table entry size */
+ Elf32_Half e_phnum; /* Program header table entry count */
+ Elf32_Half e_shentsize; /* Section header table entry size */
+ Elf32_Half e_shnum; /* Section header table entry count */
+ Elf32_Half e_shstrndx; /* Section header string table index */
+}Elf32_Ehdr;
+
+#define EI_MAG0 0 /* File identification byte 0 index */
+#define ELFMAG0 0x7f /* Magic number byte 0 */
+
+#define EI_MAG1 1 /* File identification byte 1 index */
+#define ELFMAG1 'E' /* Magic number byte 1 */
+
+#define EI_MAG2 2 /* File identification byte 2 index */
+#define ELFMAG2 'L' /* Magic number byte 2 */
+
+#define EI_MAG3 3 /* File identification byte 3 index */
+#define ELFMAG3 'F' /* Magic number byte 3 */
+
+#define EI_CLASS 4 /* File class byte index */
+#define ELFCLASS32 1 /* 32-bit objects */
+
+#define EI_DATA 5 /* Data encoding byte index */
+#define ELFDATA2LSB 1 /* 2's complement, little endian */
+
+#define EI_VERSION 6 /* File version byte index, Value must be EV_CURRENT */
+
+#define EI_OSABI 7 /* OS ABI identification */
+#define ELFOSABI_NONE 0 /* UNIX System V ABI */
+#define ELFOSABI_ARM_AEABI 64 /* ARM EABI */
+#define ELFOSABI_ARM 97 /* ARM */
+
+#define EI_ABIVERSION 8 /* ABI version */
+
+#define EI_PAD 9 /* Byte index of padding bytes */
+
+#define ET_EXEC 2 /* Executable file */
+
+#define EM_ARM 40 /* ARM */
+
+#define EV_CURRENT 1 /* Current version */
+
+#define EF_ARM_HASENTRY 0x0
+
+#define SHN_UNDEF 0 /* Undefined section */
+
+typedef struct
+{
+ Elf32_Word p_type; /* Segment type */
+ Elf32_Off p_offset; /* Segment file offset */
+ Elf32_Addr p_vaddr; /* Segment virtual address */
+ Elf32_Addr p_paddr; /* Segment physical address */
+ Elf32_Word p_filesz; /* Segment size in file */
+ Elf32_Word p_memsz; /* Segment size in memory */
+ Elf32_Word p_flags; /* Segment flags */
+ Elf32_Word p_align; /* Segment alignment */
+}Elf32_Phdr;
+
+#define PT_LOAD 1 /* Loadable program segment */
+
+#define PF_X (1 << 0) /* Segment is executable */
+#define PF_W (1 << 1) /* Segment is writable */
+#define PF_R (1 << 2) /* Segment is readable */
+
+/**
+ * API
+ */
+enum elf_section_type_t
+{
+ EST_LOAD,
+ EST_FILL
+};
+
+struct elf_section_t
+{
+ uint32_t addr;
+ uint32_t size;
+ enum elf_section_type_t type;
+ /* <union> */
+ void *section;
+ uint32_t pattern;
+ /* </union> */
+ struct elf_section_t *next;
+ /* Internal to elf_output */
+ uint32_t offset;
+};
+
+struct elf_params_t
+{
+ bool has_start_addr;
+ uint32_t start_addr;
+ struct elf_section_t *first_section;
+ struct elf_section_t *last_section;
+};
+
+typedef void (*elf_write_fn_t)(void *user, uint32_t addr, const void *buf, size_t count);
+
+void elf_init(struct elf_params_t *params);
+void elf_add_load_section(struct elf_params_t *params,
+ uint32_t load_addr, uint32_t size, const void *section);
+void elf_add_fill_section(struct elf_params_t *params,
+ uint32_t fill_addr, uint32_t size, uint32_t pattern);
+void elf_output(struct elf_params_t *params, elf_write_fn_t write, void *user);
+bool elf_is_empty(struct elf_params_t *params);
+void elf_set_start_addr(struct elf_params_t *params, uint32_t addr);
+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 @@
#include <string.h>
#include <ctype.h>
#include <time.h>
+
#include "crypto.h"
+#include "elf.h"
#if 1 /* ANSI colors */
@@ -117,7 +119,7 @@ struct sb_instruction_call_t
uint32_t arg;
} __attribute__((packed));
-static void *xmalloc(size_t s) /* malloc helper */
+void *xmalloc(size_t s) /* malloc helper, used in elf.c */
{
void * r = malloc(s);
if(!r) bugp("malloc");
@@ -259,9 +261,31 @@ static uint8_t instruction_checksum(struct sb_instruction_header_t *hdr)
return sum;
}
+static void elf_write(void *user, uint32_t addr, const void *buf, size_t count)
+{
+ FILE *f = user;
+ fseek(f, addr, SEEK_SET);
+ fwrite(buf, count, 1, f);
+}
+
+static void extract_elf_section(struct elf_params_t *elf, int count, const char *prefix)
+{
+ char *filename = xmalloc(strlen(prefix) + 32);
+ sprintf(filename, "%s.%d.elf", prefix, count);
+ printf("write %s\n", filename);
+
+ FILE *fd = fopen(filename, "wb");
+ free(filename);
+
+ if(fd == NULL)
+ return ;
+ elf_output(elf, elf_write, fd);
+ fclose(fd);
+}
+
static void extract_section(int data_sec, char name[5], byte *buf, int size, const char *indent)
{
- char filename[PREFIX_SIZE + 16];
+ char filename[PREFIX_SIZE + 32];
snprintf(filename, sizeof filename, "%s%s.bin", out_prefix, name);
FILE *fd = fopen(filename, "wb");
if (fd != NULL) {
@@ -270,6 +294,13 @@ static void extract_section(int data_sec, char name[5], byte *buf, int size, con
}
if(data_sec)
return;
+
+ snprintf(filename, sizeof filename, "%s%s", out_prefix, name);
+
+ /* elf construction */
+ struct elf_params_t elf;
+ elf_init(&elf);
+ int elf_count = 0;
/* Pretty print the content */
int pos = 0;
while(pos < size)
@@ -306,6 +337,10 @@ static void extract_section(int data_sec, char name[5], byte *buf, int size, con
else
printf(" Failed (crc=0x%08x)\n", computed_crc);
+ /* elf construction */
+ elf_add_load_section(&elf, load->addr, load->len,
+ &buf[pos + sizeof(struct sb_instruction_load_t)]);
+
pos += load->len + sizeof(struct sb_instruction_load_t);
// unsure about rounding
pos = ROUND_UP(pos, 16);
@@ -326,6 +361,9 @@ static void extract_section(int data_sec, char name[5], byte *buf, int size, con
printf("pattern=0x%08x\n", fill->pattern);
color(OFF);
+ /* elf construction */
+ elf_add_fill_section(&elf, fill->addr, fill->len, fill->pattern);
+
pos += sizeof(struct sb_instruction_fill_t);
// fixme: useless as pos is a multiple of 16 and fill struct is 4-bytes wide ?
pos = ROUND_UP(pos, 16);
@@ -348,6 +386,12 @@ static void extract_section(int data_sec, char name[5], byte *buf, int size, con
printf("arg=0x%08x\n", call->arg);
color(OFF);
+ /* elf construction */
+ elf_set_start_addr(&elf, call->addr);
+ extract_elf_section(&elf, elf_count++, filename);
+ elf_release(&elf);
+ elf_init(&elf);
+
pos += sizeof(struct sb_instruction_call_t);
// fixme: useless as pos is a multiple of 16 and call struct is 4-bytes wide ?
pos = ROUND_UP(pos, 16);
@@ -359,6 +403,10 @@ static void extract_section(int data_sec, char name[5], byte *buf, int size, con
break;
}
}
+
+ if(elf_is_empty(&elf))
+ extract_elf_section(&elf, elf_count++, filename);
+ elf_release(&elf);
}
static void extract(unsigned long filesize)