summaryrefslogtreecommitdiff
path: root/tools/relocate-rela.c
diff options
context:
space:
mode:
authorMichal Simek <michal.simek@amd.com>2022-06-24 14:15:00 +0200
committerMichal Simek <michal.simek@amd.com>2022-06-24 14:15:00 +0200
commit30fb8d29cd3e7a682dfb89f40c4702c0a4029615 (patch)
treeaf8e4eb1ce8489198403f858243e637d3ae2e112 /tools/relocate-rela.c
parenta1405d9cfedb1228289e617258de3fc0d7facecd (diff)
downloadu-boot-30fb8d29cd3e7a682dfb89f40c4702c0a4029615.tar.gz
tools: relocate-rela: Add support for elf32 decoding
Add support for 32bit ELF format which is used by Microblaze. Also check that code runs only for Microblaze. Function finds information about rela.dyn and dynsym which will be used later for relocation. Signed-off-by: Michal Simek <michal.simek@amd.com> Link: https://lore.kernel.org/r/7491cc72fe04cbd48db014f1492ce463e91dfb42.1655299267.git.michal.simek@amd.com
Diffstat (limited to 'tools/relocate-rela.c')
-rw-r--r--tools/relocate-rela.c141
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) {