sbinfo: fix a few typos (thanks to Kane Xie), correct coding style, now generate segments along with program sections to make elf files appear more valid (this allows to rebuild an .sb file using elftosb2)
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@29510 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
708f5508ad
commit
f85c04469e
3 changed files with 129 additions and 43 deletions
|
@ -57,13 +57,16 @@ void elf_add_fill_section(struct elf_params_t *params,
|
|||
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;
|
||||
Elf32_Shdr shdr;
|
||||
memset(&ehdr, 0, EI_NIDENT);
|
||||
|
||||
uint32_t bss_strtbl = 0;
|
||||
uint32_t text_strtbl = bss_strtbl + strlen(".bss") + 1;
|
||||
uint32_t strtbl_size = text_strtbl + strlen(".text") + 1;
|
||||
|
||||
while(sec)
|
||||
{
|
||||
|
@ -77,7 +80,8 @@ void elf_output(struct elf_params_t *params, elf_write_fn_t write, void *user)
|
|||
sec = sec->next;
|
||||
}
|
||||
|
||||
memset(&ehdr, 0, EI_NIDENT);
|
||||
uint32_t strtbl_offset = offset;
|
||||
|
||||
ehdr.e_ident[EI_MAG0] = ELFMAG0;
|
||||
ehdr.e_ident[EI_MAG1] = ELFMAG1;
|
||||
ehdr.e_ident[EI_MAG2] = ELFMAG2;
|
||||
|
@ -91,25 +95,28 @@ void elf_output(struct elf_params_t *params, elf_write_fn_t write, void *user)
|
|||
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_phentsize = sizeof phdr;
|
||||
ehdr.e_phnum = phnum;
|
||||
ehdr.e_shentsize = 0;
|
||||
ehdr.e_shnum = 0;
|
||||
ehdr.e_shstrndx = shstrndx;
|
||||
ehdr.e_shentsize = sizeof shdr;
|
||||
ehdr.e_shnum = phnum + 1;
|
||||
ehdr.e_shstrndx = ehdr.e_shnum - 1;
|
||||
ehdr.e_phoff = ehdr.e_ehsize;
|
||||
ehdr.e_shoff = ehdr.e_ehsize + ehdr.e_phnum * ehdr.e_phentsize;
|
||||
|
||||
write(user, 0, &ehdr, sizeof ehdr);
|
||||
|
||||
uint32_t data_offset = ehdr.e_ehsize + ehdr.e_phnum * ehdr.e_phentsize +
|
||||
ehdr.e_shnum * ehdr.e_shentsize;
|
||||
|
||||
sec = params->first_section;
|
||||
offset = phoff;
|
||||
offset = ehdr.e_phoff;
|
||||
while(sec)
|
||||
{
|
||||
sec->offset += phoff + phnum * phentsize;
|
||||
sec->offset += data_offset;
|
||||
|
||||
phdr.p_type = PT_LOAD;
|
||||
if(sec->type == EST_LOAD)
|
||||
|
@ -132,6 +139,47 @@ void elf_output(struct elf_params_t *params, elf_write_fn_t write, void *user)
|
|||
sec = sec->next;
|
||||
}
|
||||
|
||||
sec = params->first_section;
|
||||
offset = ehdr.e_shoff;
|
||||
while(sec)
|
||||
{
|
||||
shdr.sh_name = text_strtbl;
|
||||
if(sec->type == EST_LOAD)
|
||||
shdr.sh_type = SHT_PROGBITS;
|
||||
else
|
||||
shdr.sh_type = SHT_NOBITS;
|
||||
shdr.sh_flags = SHF_ALLOC | SHF_EXECINSTR;
|
||||
shdr.sh_addr = sec->addr;
|
||||
shdr.sh_offset = sec->offset;
|
||||
shdr.sh_size = sec->size;
|
||||
shdr.sh_link = SHN_UNDEF;
|
||||
shdr.sh_info = 0;
|
||||
shdr.sh_addralign = 1;
|
||||
shdr.sh_entsize = 0;
|
||||
|
||||
write(user, offset, &shdr, sizeof shdr);
|
||||
|
||||
offset += sizeof(Elf32_Shdr);
|
||||
sec = sec->next;
|
||||
}
|
||||
|
||||
{
|
||||
shdr.sh_name = bss_strtbl;
|
||||
shdr.sh_type = SHT_STRTAB;
|
||||
shdr.sh_flags = 0;
|
||||
shdr.sh_addr = 0;
|
||||
shdr.sh_offset = strtbl_offset + data_offset;
|
||||
shdr.sh_size = strtbl_size;
|
||||
shdr.sh_link = SHN_UNDEF;
|
||||
shdr.sh_info = 0;
|
||||
shdr.sh_addralign = 1;
|
||||
shdr.sh_entsize = 0;
|
||||
|
||||
write(user, offset, &shdr, sizeof shdr);
|
||||
|
||||
offset += sizeof(Elf32_Shdr);
|
||||
}
|
||||
|
||||
sec = params->first_section;
|
||||
while(sec)
|
||||
{
|
||||
|
@ -139,6 +187,8 @@ void elf_output(struct elf_params_t *params, elf_write_fn_t write, void *user)
|
|||
write(user, sec->offset, sec->section, sec->size);
|
||||
sec = sec->next;
|
||||
}
|
||||
|
||||
write(user, strtbl_offset + data_offset, ".bss\0.text\0", strtbl_size);
|
||||
}
|
||||
|
||||
bool elf_is_empty(struct elf_params_t *params)
|
||||
|
|
|
@ -78,6 +78,45 @@ typedef struct
|
|||
|
||||
#define SHN_UNDEF 0 /* Undefined section */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Elf32_Word sh_name; /* Section name (string tbl index) */
|
||||
Elf32_Word sh_type; /* Section type */
|
||||
Elf32_Word sh_flags; /* Section flags */
|
||||
Elf32_Addr sh_addr; /* Section virtual addr at execution */
|
||||
Elf32_Off sh_offset; /* Section file offset */
|
||||
Elf32_Word sh_size; /* Section size in bytes */
|
||||
Elf32_Word sh_link; /* Link to another section */
|
||||
Elf32_Word sh_info; /* Additional section information */
|
||||
Elf32_Word sh_addralign; /* Section alignment */
|
||||
Elf32_Word sh_entsize; /* Entry size if section holds table */
|
||||
}Elf32_Shdr;
|
||||
|
||||
#define SHT_NULL 0 /* Section header table entry unused */
|
||||
#define SHT_PROGBITS 1 /* Program data */
|
||||
#define SHT_SYMTAB 2 /* Symbol table */
|
||||
#define SHT_STRTAB 3 /* String table */
|
||||
#define SHT_RELA 4 /* Relocation entries with addends */
|
||||
#define SHT_HASH 5 /* Symbol hash table */
|
||||
#define SHT_DYNAMIC 6 /* Dynamic linking information */
|
||||
#define SHT_NOTE 7 /* Notes */
|
||||
#define SHT_NOBITS 8 /* Program space with no data (bss) */
|
||||
#define SHT_REL 9 /* Relocation entries, no addends */
|
||||
#define SHT_SHLIB 10 /* Reserved */
|
||||
#define SHT_DYNSYM 11 /* Dynamic linker symbol table */
|
||||
#define SHT_INIT_ARRAY 14 /* Array of constructors */
|
||||
#define SHT_FINI_ARRAY 15 /* Array of destructors */
|
||||
#define SHT_PREINIT_ARRAY 16 /* Array of pre-constructors */
|
||||
#define SHT_GROUP 17 /* Section group */
|
||||
#define SHT_SYMTAB_SHNDX 18 /* Extended section indeces */
|
||||
#define SHT_NUM 19 /* Number of defined types. */
|
||||
|
||||
#define SHF_WRITE (1 << 0) /* Writable */
|
||||
#define SHF_ALLOC (1 << 1) /* Occupies memory during execution */
|
||||
#define SHF_EXECINSTR (1 << 2) /* Executable */
|
||||
#define SHF_MERGE (1 << 4) /* Might be merged */
|
||||
#define SHF_STRINGS (1 << 5) /* Contains nul-terminated strings */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Elf32_Word p_type; /* Segment type */
|
||||
|
|
|
@ -63,8 +63,8 @@ char BLUE[] = { 0x1b, 0x5b, 0x31, 0x3b, '3', '4', 0x6d, '\0' };
|
|||
|
||||
/* byte swapping */
|
||||
#define get32le(a) ((uint32_t) \
|
||||
( buf[a+3] << 24 | buf[a+2] << 16 | buf[a+1] << 8 | buf[a] ))
|
||||
#define get16le(a) ((uint16_t)( buf[a+1] << 8 | buf[a] ))
|
||||
( g_buf[a+3] << 24 | g_buf[a+2] << 16 | g_buf[a+1] << 8 | g_buf[a] ))
|
||||
#define get16le(a) ((uint16_t)( g_buf[a+1] << 8 | g_buf[a] ))
|
||||
|
||||
/* all blocks are sized as a multiple of 0x1ff */
|
||||
#define PAD_TO_BOUNDARY(x) (((x) + 0x1ff) & ~0x1ff)
|
||||
|
@ -74,8 +74,8 @@ char BLUE[] = { 0x1b, 0x5b, 0x31, 0x3b, '3', '4', 0x6d, '\0' };
|
|||
|
||||
/* globals */
|
||||
|
||||
size_t sz; /* file size */
|
||||
uint8_t *buf; /* file content */
|
||||
size_t g_sz; /* file size */
|
||||
uint8_t *g_buf; /* file content */
|
||||
#define PREFIX_SIZE 128
|
||||
char out_prefix[PREFIX_SIZE];
|
||||
const char *key_file;
|
||||
|
@ -129,25 +129,23 @@ void *xmalloc(size_t s) /* malloc helper, used in elf.c */
|
|||
static char getchr(int offset)
|
||||
{
|
||||
char c;
|
||||
c = buf[offset];
|
||||
c = g_buf[offset];
|
||||
return isprint(c) ? c : '_';
|
||||
}
|
||||
|
||||
static void getstrle(char string[], int offset)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < 4; i++) {
|
||||
for (i = 0; i < 4; i++)
|
||||
string[i] = getchr(offset + 3 - i);
|
||||
}
|
||||
string[4] = 0;
|
||||
}
|
||||
|
||||
static void getstrbe(char string[], int offset)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < 4; i++) {
|
||||
for (i = 0; i < 4; i++)
|
||||
string[i] = getchr(offset + i);
|
||||
}
|
||||
string[4] = 0;
|
||||
}
|
||||
|
||||
|
@ -155,9 +153,8 @@ static void printhex(int offset, int len)
|
|||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
printf("%02X ", buf[offset + i]);
|
||||
}
|
||||
for (i = 0; i < len; i++)
|
||||
printf("%02X ", g_buf[offset + i]);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
|
@ -222,7 +219,7 @@ static key_array_t read_keys(int num_keys)
|
|||
bugp("key file stat() failed");
|
||||
size = st.st_size;
|
||||
char *buf = xmalloc(size);
|
||||
if(read(fd,buf,sz)!=(ssize_t)size)
|
||||
if(read(fd, buf, size) != (ssize_t)size)
|
||||
bugp("reading key file");
|
||||
close(fd);
|
||||
|
||||
|
@ -417,13 +414,13 @@ static void extract(unsigned long filesize)
|
|||
printf("Basic info:\n");
|
||||
color(GREEN);
|
||||
printf("\tHeader SHA-1: ");
|
||||
byte *hdr_sha1 = &buf[0];
|
||||
byte *hdr_sha1 = &g_buf[0];
|
||||
color(YELLOW);
|
||||
print_sha1(hdr_sha1);
|
||||
/* Check SHA1 sum */
|
||||
byte computed_sha1[20];
|
||||
sha_1_init(&sha_1_params);
|
||||
sha_1_update(&sha_1_params, &buf[0x14], 0x4C);
|
||||
sha_1_update(&sha_1_params, &g_buf[0x14], 0x4C);
|
||||
sha_1_finish(&sha_1_params);
|
||||
sha_1_output(&sha_1_params, computed_sha1);
|
||||
color(RED);
|
||||
|
@ -480,7 +477,7 @@ static void extract(unsigned long filesize)
|
|||
if(num_enc > 0)
|
||||
{
|
||||
keys = read_keys(num_enc);
|
||||
color(BLUE),
|
||||
color(BLUE);
|
||||
printf("Encryption data\n");
|
||||
for(int i = 0; i < num_enc; i++)
|
||||
{
|
||||
|
@ -492,14 +489,14 @@ static void extract(unsigned long filesize)
|
|||
printf("\t\tCBC-MAC of headers: ");
|
||||
/* copy the cbc mac */
|
||||
byte hdr_cbc_mac[16];
|
||||
memcpy(hdr_cbc_mac, &buf[0x60 + 16 * num_chunks + 32 * i], 16);
|
||||
memcpy(hdr_cbc_mac, &g_buf[0x60 + 16 * num_chunks + 32 * i], 16);
|
||||
color(YELLOW);
|
||||
print_key(hdr_cbc_mac);
|
||||
/* check it */
|
||||
byte computed_cbc_mac[16];
|
||||
byte zero[16];
|
||||
memset(zero, 0, 16);
|
||||
cbc_mac(buf, NULL, 6 + num_chunks, keys[i], zero, &computed_cbc_mac, 1);
|
||||
cbc_mac(g_buf, NULL, 6 + num_chunks, keys[i], zero, &computed_cbc_mac, 1);
|
||||
color(RED);
|
||||
if(memcmp(hdr_cbc_mac, computed_cbc_mac, 16) == 0)
|
||||
printf(" Ok\n");
|
||||
|
@ -509,7 +506,7 @@ static void extract(unsigned long filesize)
|
|||
|
||||
printf("\t\tEncrypted key : ");
|
||||
byte (*encrypted_key)[16];
|
||||
encrypted_key = (key_array_t)&buf[0x60 + 16 * num_chunks + 32 * i + 16];
|
||||
encrypted_key = (key_array_t)&g_buf[0x60 + 16 * num_chunks + 32 * i + 16];
|
||||
color(YELLOW);
|
||||
print_key(*encrypted_key);
|
||||
printf("\n");
|
||||
|
@ -517,7 +514,7 @@ static void extract(unsigned long filesize)
|
|||
/* decrypt */
|
||||
byte decrypted_key[16];
|
||||
byte iv[16];
|
||||
memcpy(iv, buf, 16); /* uses the first 16-bytes of SHA-1 sig as IV */
|
||||
memcpy(iv, g_buf, 16); /* uses the first 16-bytes of SHA-1 sig as IV */
|
||||
cbc_mac(*encrypted_key, decrypted_key, 1, keys[i], iv, NULL, 0);
|
||||
printf("\t\tDecrypted key : ");
|
||||
color(YELLOW);
|
||||
|
@ -571,9 +568,9 @@ static void extract(unsigned long filesize)
|
|||
/* save it */
|
||||
byte *sec = xmalloc(size);
|
||||
if(encrypted)
|
||||
cbc_mac(buf + pos, sec, size / 16, real_key, buf, NULL, 0);
|
||||
cbc_mac(g_buf + pos, sec, size / 16, real_key, g_buf, NULL, 0);
|
||||
else
|
||||
memcpy(sec, buf + pos, size);
|
||||
memcpy(sec, g_buf + pos, size);
|
||||
|
||||
extract_section(data_sec, name, sec, size, "\t\t\t");
|
||||
free(sec);
|
||||
|
@ -590,16 +587,16 @@ static void extract(unsigned long filesize)
|
|||
printf("\t\t");
|
||||
printhex(filesize - 16, 16);
|
||||
/* decrypt it */
|
||||
byte *encrypted_block = &buf[filesize - 32];
|
||||
byte *encrypted_block = &g_buf[filesize - 32];
|
||||
byte decrypted_block[32];
|
||||
cbc_mac(encrypted_block, decrypted_block, 2, real_key, buf, NULL, 0);
|
||||
cbc_mac(encrypted_block, decrypted_block, 2, real_key, g_buf, NULL, 0);
|
||||
color(GREEN);
|
||||
printf("\tDecrypted SHA-1:\n\t\t");
|
||||
color(YELLOW);
|
||||
print_sha1(decrypted_block);
|
||||
/* check it */
|
||||
sha_1_init(&sha_1_params);
|
||||
sha_1_update(&sha_1_params, buf, filesize - 32);
|
||||
sha_1_update(&sha_1_params, g_buf, filesize - 32);
|
||||
sha_1_finish(&sha_1_params);
|
||||
sha_1_output(&sha_1_params, computed_sha1);
|
||||
color(RED);
|
||||
|
@ -621,17 +618,17 @@ int main(int argc, const char **argv)
|
|||
else
|
||||
strcpy(out_prefix, "");
|
||||
|
||||
if( (fd = open(argv[1],O_RDONLY)) == -1 )
|
||||
if( (fd = open(argv[1], O_RDONLY)) == -1 )
|
||||
bugp("opening firmware failed");
|
||||
|
||||
key_file = argv[2];
|
||||
|
||||
if(fstat(fd,&st) == -1)
|
||||
if(fstat(fd, &st) == -1)
|
||||
bugp("firmware stat() failed");
|
||||
sz = st.st_size;
|
||||
g_sz = st.st_size;
|
||||
|
||||
buf=xmalloc(sz);
|
||||
if(read(fd,buf,sz)!=(ssize_t)sz) /* load the whole file into memory */
|
||||
g_buf = xmalloc(g_sz);
|
||||
if(read(fd, g_buf, g_sz) != (ssize_t)g_sz) /* load the whole file into memory */
|
||||
bugp("reading firmware");
|
||||
|
||||
close(fd);
|
||||
|
@ -641,6 +638,6 @@ int main(int argc, const char **argv)
|
|||
|
||||
color(OFF);
|
||||
|
||||
free(buf);
|
||||
free(g_buf);
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue