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:
parent
71ad3679dc
commit
1583b1cd53
4 changed files with 361 additions and 4 deletions
|
@ -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
169
utils/sbinfo/elf.c
Normal 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
140
utils/sbinfo/elf.h
Normal 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);
|
|
@ -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)
|
||||
|
|
Loading…
Reference in a new issue