sbtools: make code aware of elf section names

Change-Id: I7ab657959e38d2fcb2c7e6d9858facfb83101423
This commit is contained in:
Amaury Pouly 2013-07-30 17:12:56 +02:00
parent da8ebcec2f
commit 76446dda45
3 changed files with 39 additions and 23 deletions

View file

@ -18,9 +18,11 @@
* KIND, either express or implied. * KIND, either express or implied.
* *
****************************************************************************/ ****************************************************************************/
#define _POSIX_C_SOURCE 200809L /* for strdup */
#include "elf.h" #include "elf.h"
#include "misc.h" #include "misc.h"
#include <stdarg.h> #include <stdarg.h>
#include <string.h>
/** /**
* Definitions * Definitions
@ -190,10 +192,11 @@ static struct elf_segment_t *elf_add_segment(struct elf_params_t *params)
} }
void elf_add_load_section(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) uint32_t load_addr, uint32_t size, const void *section, const char *name)
{ {
struct elf_section_t *sec = elf_add_section(params); struct elf_section_t *sec = elf_add_section(params);
sec->name = strdup(name);
sec->type = EST_LOAD; sec->type = EST_LOAD;
sec->addr = load_addr; sec->addr = load_addr;
sec->size = size; sec->size = size;
@ -202,7 +205,7 @@ void elf_add_load_section(struct elf_params_t *params,
} }
void elf_add_fill_section(struct elf_params_t *params, void elf_add_fill_section(struct elf_params_t *params,
uint32_t fill_addr, uint32_t size, uint32_t pattern) uint32_t fill_addr, uint32_t size, uint32_t pattern, const char *name)
{ {
if(pattern != 0x00) if(pattern != 0x00)
{ {
@ -212,6 +215,7 @@ void elf_add_fill_section(struct elf_params_t *params,
struct elf_section_t *sec = elf_add_section(params); struct elf_section_t *sec = elf_add_section(params);
sec->name = strdup(name);
sec->type = EST_FILL; sec->type = EST_FILL;
sec->addr = fill_addr; sec->addr = fill_addr;
sec->size = size; sec->size = size;
@ -282,6 +286,7 @@ void elf_simplify(struct elf_params_t *params)
memcpy(data + cur_sec->size, sections[i].section, sections[i].size); memcpy(data + cur_sec->size, sections[i].section, sections[i].size);
free(cur_sec->section); free(cur_sec->section);
free(sections[i].section); free(sections[i].section);
free(sections[i].name);
cur_sec->section = data; cur_sec->section = data;
cur_sec->size += sections[i].size; cur_sec->size += sections[i].size;
sections[i].size = 0; // will be ignored by rebuilding (see below) sections[i].size = 0; // will be ignored by rebuilding (see below)
@ -426,12 +431,19 @@ void elf_write_file(struct elf_params_t *params, elf_write_fn_t write,
write(user, 0, &ehdr, sizeof ehdr); write(user, 0, &ehdr, sizeof ehdr);
/* allocate enough size to hold any combinaison of .text/.bss in the string table: /* allocate enough size for the string table:
* - one empty name ("\0") * - one empty name ("\0")
* - at most N names of the form ".textXXXX\0" or ".bssXXXX\0" * - one name ".shstrtab\0"
* - one name ".shstrtab\0" */ * - all section names with zeroes */
char *strtbl_content = malloc(1 + strlen(".shstrtab") + 1 + size_t strtbl_size = 1+ strlen(".shstrtab") + 1;
phnum * (strlen(".textXXXX") + 1)); sec = params->first_section;
while(sec)
{
strtbl_size += strlen(sec->name) + 1;
sec = sec->next;
}
char *strtbl_content = malloc(strtbl_size);
strtbl_content[0] = '\0'; strtbl_content[0] = '\0';
strcpy(&strtbl_content[1], ".shstrtab"); strcpy(&strtbl_content[1], ".shstrtab");
@ -487,21 +499,14 @@ void elf_write_file(struct elf_params_t *params, elf_write_fn_t write,
offset += sizeof(Elf32_Shdr); offset += sizeof(Elf32_Shdr);
} }
uint32_t text_idx = 0;
uint32_t bss_idx = 0;
while(sec) while(sec)
{ {
shdr.sh_name = strtbl_index; shdr.sh_name = strtbl_index;
strtbl_index += 1 + sprintf(&strtbl_content[strtbl_index], "%s", sec->name);
if(sec->type == EST_LOAD) if(sec->type == EST_LOAD)
{
strtbl_index += 1 + sprintf(&strtbl_content[strtbl_index], ".text%d", text_idx++);
shdr.sh_type = SHT_PROGBITS; shdr.sh_type = SHT_PROGBITS;
}
else else
{
strtbl_index += 1 + sprintf(&strtbl_content[strtbl_index], ".bss%d", bss_idx++);
shdr.sh_type = SHT_NOBITS; shdr.sh_type = SHT_NOBITS;
}
shdr.sh_flags = SHF_ALLOC | SHF_EXECINSTR; shdr.sh_flags = SHF_ALLOC | SHF_EXECINSTR;
shdr.sh_addr = sec->addr; shdr.sh_addr = sec->addr;
shdr.sh_offset = sec->offset; shdr.sh_offset = sec->offset;
@ -610,7 +615,7 @@ bool elf_read_file(struct elf_params_t *params, elf_read_fn_t read,
void *data = xmalloc(shdr.sh_size); void *data = xmalloc(shdr.sh_size);
if(!read(user, shdr.sh_offset, data, shdr.sh_size)) if(!read(user, shdr.sh_offset, data, shdr.sh_size))
error_printf("error read self section data\n"); error_printf("error read self section data\n");
elf_add_load_section(params, shdr.sh_addr, shdr.sh_size, data); elf_add_load_section(params, shdr.sh_addr, shdr.sh_size, data, &strtab[shdr.sh_name]);
free(data); free(data);
if(strtab) if(strtab)
@ -618,7 +623,7 @@ bool elf_read_file(struct elf_params_t *params, elf_read_fn_t read,
} }
else if(shdr.sh_type == SHT_NOBITS && shdr.sh_flags & SHF_ALLOC) else if(shdr.sh_type == SHT_NOBITS && shdr.sh_flags & SHF_ALLOC)
{ {
elf_add_fill_section(params, shdr.sh_addr, shdr.sh_size, 0); elf_add_fill_section(params, shdr.sh_addr, shdr.sh_size, 0, &strtab[shdr.sh_name]);
if(strtab) if(strtab)
printf(user, false, "create fill segment for %s\n", &strtab[shdr.sh_name]); printf(user, false, "create fill segment for %s\n", &strtab[shdr.sh_name]);
} }
@ -713,6 +718,7 @@ void elf_release(struct elf_params_t *params)
struct elf_section_t *next_sec = sec->next; struct elf_section_t *next_sec = sec->next;
if(sec->type == EST_LOAD) if(sec->type == EST_LOAD)
free(sec->section); free(sec->section);
free(sec->name);
free(sec); free(sec);
sec = next_sec; sec = next_sec;
} }

View file

@ -39,6 +39,7 @@ enum elf_section_type_t
struct elf_section_t struct elf_section_t
{ {
char *name;
uint32_t addr; /* virtual address */ uint32_t addr; /* virtual address */
uint32_t size; /* virtual size */ uint32_t size; /* virtual size */
enum elf_section_type_t type; enum elf_section_type_t type;
@ -77,9 +78,9 @@ typedef void (*elf_printf_fn_t)(void *user, bool error, const char *fmt, ...);
void elf_init(struct elf_params_t *params); void elf_init(struct elf_params_t *params);
void elf_add_load_section(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); uint32_t load_addr, uint32_t size, const void *section, const char *name);
void elf_add_fill_section(struct elf_params_t *params, void elf_add_fill_section(struct elf_params_t *params,
uint32_t fill_addr, uint32_t size, uint32_t pattern); uint32_t fill_addr, uint32_t size, uint32_t pattern, const char *name);
uint32_t elf_translate_virtual_address(struct elf_params_t *params, uint32_t addr); uint32_t elf_translate_virtual_address(struct elf_params_t *params, uint32_t addr);
void elf_translate_addresses(struct elf_params_t *params); void elf_translate_addresses(struct elf_params_t *params);
void elf_simplify(struct elf_params_t *params); void elf_simplify(struct elf_params_t *params);

View file

@ -107,16 +107,20 @@ static void extract_sb_section(struct sb_section_t *sec)
struct elf_params_t elf; struct elf_params_t elf;
elf_init(&elf); elf_init(&elf);
int bss_idx = 0, text_idx = 0;
char secname[32];
for(int i = 0; i < sec->nr_insts; i++) for(int i = 0; i < sec->nr_insts; i++)
{ {
struct sb_inst_t *inst = &sec->insts[i]; struct sb_inst_t *inst = &sec->insts[i];
switch(inst->inst) switch(inst->inst)
{ {
case SB_INST_LOAD: case SB_INST_LOAD:
elf_add_load_section(&elf, inst->addr, inst->size, inst->data); sprintf(secname, ".text%d", text_idx++);
elf_add_load_section(&elf, inst->addr, inst->size, inst->data, secname);
break; break;
case SB_INST_FILL: case SB_INST_FILL:
elf_add_fill_section(&elf, inst->addr, inst->size, inst->pattern); sprintf(secname, ".bss%d", bss_idx++);
elf_add_fill_section(&elf, inst->addr, inst->size, inst->pattern, secname);
break; break;
case SB_INST_CALL: case SB_INST_CALL:
case SB_INST_JUMP: case SB_INST_JUMP:
@ -124,6 +128,7 @@ static void extract_sb_section(struct sb_section_t *sec)
extract_elf_section(&elf, elf_count++, sec->identifier); extract_elf_section(&elf, elf_count++, sec->identifier);
elf_release(&elf); elf_release(&elf);
elf_init(&elf); elf_init(&elf);
bss_idx = text_idx = 0;
break; break;
default: default:
/* ignore mode and nop */ /* ignore mode and nop */
@ -166,16 +171,20 @@ static void extract_sb1_file(struct sb1_file_t *file)
struct elf_params_t elf; struct elf_params_t elf;
elf_init(&elf); elf_init(&elf);
int bss_idx = 0, text_idx = 0;
char secname[32];
for(int i = 0; i < file->nr_insts; i++) for(int i = 0; i < file->nr_insts; i++)
{ {
struct sb1_inst_t *inst = &file->insts[i]; struct sb1_inst_t *inst = &file->insts[i];
switch(inst->cmd) switch(inst->cmd)
{ {
case SB1_INST_LOAD: case SB1_INST_LOAD:
elf_add_load_section(&elf, inst->addr, inst->size, inst->data); sprintf(secname, ".text%d", text_idx++);
elf_add_load_section(&elf, inst->addr, inst->size, inst->data, secname);
break; break;
case SB1_INST_FILL: case SB1_INST_FILL:
elf_add_fill_section(&elf, inst->addr, inst->size, inst->pattern); sprintf(secname, ".bss%d", bss_idx++);
elf_add_fill_section(&elf, inst->addr, inst->size, inst->pattern, secname);
break; break;
case SB1_INST_CALL: case SB1_INST_CALL:
case SB1_INST_JUMP: case SB1_INST_JUMP: