diff options
-rw-r--r-- | tools/relocate-rela.c | 141 |
1 files changed, 139 insertions, 2 deletions
diff --git a/tools/relocate-rela.c b/tools/relocate-rela.c index 2f7f1796a0..7c2a441a8e 100644 --- a/tools/relocate-rela.c +++ b/tools/relocate-rela.c @@ -22,7 +22,7 @@ static int ei_class; -static uint64_t rela_start, rela_end, text_base; +static uint64_t rela_start, rela_end, text_base, dyn_start; static const bool debug_en; @@ -184,6 +184,142 @@ static int decode_elf64(FILE *felf, char **argv) return 0; } +static int decode_elf32(FILE *felf, char **argv) +{ + size_t size; + Elf32_Ehdr header; + uint64_t section_header_base, section_header_size, sh_offset, sh_size; + Elf32_Shdr *sh_table; /* Elf symbol table */ + int ret, i, machine; + char *sh_str; + + debug("32bit version\n"); + + /* Make sure we are at start */ + rewind(felf); + + size = fread(&header, 1, sizeof(header), felf); + if (size != sizeof(header)) { + fclose(felf); + return 25; + } + + machine = header.e_machine; + debug("Machine %d\n", machine); + + if (machine != EM_MICROBLAZE) { + fprintf(stderr, "%s: Not supported machine type\n", argv[0]); + return 30; + } + + text_base = header.e_entry; + section_header_base = header.e_shoff; + + debug("Section header base %x\n", section_header_base); + + section_header_size = header.e_shentsize * header.e_shnum; + + debug("Section header size %d\n", section_header_size); + + sh_table = malloc(section_header_size); + if (!sh_table) { + fprintf(stderr, "%s: Cannot allocate space for section header\n", + argv[0]); + fclose(felf); + return 26; + } + + ret = fseek(felf, section_header_base, SEEK_SET); + if (ret) { + fprintf(stderr, "%s: Can't set pointer to section header: %x/%lx\n", + argv[0], ret, section_header_base); + free(sh_table); + fclose(felf); + return 26; + } + + size = fread(sh_table, 1, section_header_size, felf); + if (size != section_header_size) { + fprintf(stderr, "%s: Can't read section header: %lx/%lx\n", + argv[0], size, section_header_size); + free(sh_table); + fclose(felf); + return 27; + } + + sh_size = sh_table[header.e_shstrndx].sh_size; + debug("e_shstrndx %x, sh_size %lx\n", header.e_shstrndx, sh_size); + + sh_str = malloc(sh_size); + if (!sh_str) { + fprintf(stderr, "malloc failed\n"); + free(sh_table); + fclose(felf); + return 28; + } + + /* + * Specifies the byte offset from the beginning of the file + * to the first byte in the section. + */ + sh_offset = sh_table[header.e_shstrndx].sh_offset; + + debug("sh_offset %x\n", header.e_shnum); + + ret = fseek(felf, sh_offset, SEEK_SET); + if (ret) { + fprintf(stderr, "Setting up sh_offset failed\n"); + free(sh_str); + free(sh_table); + fclose(felf); + return 29; + } + + size = fread(sh_str, 1, sh_size, felf); + if (size != sh_size) { + fprintf(stderr, "%s: Can't read section: %lx/%lx\n", + argv[0], size, sh_size); + free(sh_str); + free(sh_table); + fclose(felf); + return 30; + } + + for (i = 0; i < header.e_shnum; i++) { + debug("%s\n", sh_str + sh_table[i].sh_name); + if (!strcmp(".rela.dyn", (sh_str + sh_table[i].sh_name))) { + debug("Found section\t\".rela_dyn\"\n"); + debug(" at addr\t0x%08x\n", (unsigned int)sh_table[i].sh_addr); + debug(" at offset\t0x%08x\n", (unsigned int)sh_table[i].sh_offset); + debug(" of size\t0x%08x\n", (unsigned int)sh_table[i].sh_size); + rela_start = sh_table[i].sh_addr; + rela_end = rela_start + sh_table[i].sh_size; + } + if (!strcmp(".dynsym", (sh_str + sh_table[i].sh_name))) { + debug("Found section\t\".dynsym\"\n"); + debug(" at addr\t0x%08x\n", (unsigned int)sh_table[i].sh_addr); + debug(" at offset\t0x%08x\n", (unsigned int)sh_table[i].sh_offset); + debug(" of size\t0x%08x\n", (unsigned int)sh_table[i].sh_size); + dyn_start = sh_table[i].sh_addr; + } + } + + /* Clean up */ + free(sh_str); + free(sh_table); + fclose(felf); + + debug("text_base\t0x%08lx\n", text_base); + debug("rela_start\t0x%08lx\n", rela_start); + debug("rela_end\t0x%08lx\n", rela_end); + debug("dyn_start\t0x%08lx\n", dyn_start); + + if (!rela_start) + return 1; + + return 0; +} + static int decode_elf(char **argv) { FILE *felf; @@ -218,7 +354,7 @@ static int decode_elf(char **argv) if (ei_class == 2) return decode_elf64(felf, argv); - return 1; + return decode_elf32(felf, argv); } static int rela_elf64(char **argv, FILE *f) @@ -310,6 +446,7 @@ int main(int argc, char **argv) rela_start -= text_base; rela_end -= text_base; + dyn_start -= text_base; f = fopen(argv[1], "r+b"); if (!f) { |