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
This commit is contained in:
Amaury Pouly 2010-12-01 16:17:11 +00:00
parent 71ad3679dc
commit 1583b1cd53
4 changed files with 361 additions and 4 deletions

View file

@ -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)

169
utils/sbinfo/elf.c Normal file
View file

@ -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;
}

140
utils/sbinfo/elf.h Normal file
View file

@ -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);

View file

@ -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)