From: Hou Wenlong <houwenlong.hwl@xxxxxxxxxxxx> Add a command line option to append relocations into a reserved section named ".data.reloc" section of the input file. This is the same as the implementation in MIPS. Signed-off-by: Hou Wenlong <houwenlong.hwl@xxxxxxxxxxxx> Signed-off-by: Lai Jiangshan <jiangshan.ljs@xxxxxxxxxxxx> --- arch/x86/tools/relocs.c | 62 +++++++++++++++++++++++++++------- arch/x86/tools/relocs.h | 1 + arch/x86/tools/relocs_common.c | 11 ++++-- 3 files changed, 60 insertions(+), 14 deletions(-) diff --git a/arch/x86/tools/relocs.c b/arch/x86/tools/relocs.c index 743e5e44338b..97e0243b9abb 100644 --- a/arch/x86/tools/relocs.c +++ b/arch/x86/tools/relocs.c @@ -912,6 +912,17 @@ static int is_percpu_sym(ElfW(Sym) *sym, const char *symname) strncmp(symname, "init_per_cpu_", 13); } +static struct section *sec_lookup(const char *name) +{ + int i; + + for (i = 0; i < shnum; i++) { + if (!strcmp(sec_name(i), name)) + return &secs[i]; + } + + return NULL; +} static int do_reloc64(struct section *sec, Elf_Rel *rel, ElfW(Sym) *sym, const char *symname) @@ -1164,12 +1175,13 @@ static int write32_as_text(uint32_t v, FILE *f) return fprintf(f, "\t.long 0x%08"PRIx32"\n", v) > 0 ? 0 : -1; } -static void emit_relocs(void) +static void emit_relocs(FILE *f) { int i; int (*write_reloc)(uint32_t, FILE *) = write32; int (*do_reloc)(struct section *sec, Elf_Rel *rel, Elf_Sym *sym, const char *symname); + FILE *outf = stdout; #if ELF_BITS == 64 if (!opts.use_real_mode) @@ -1208,37 +1220,63 @@ static void emit_relocs(void) write_reloc = write32_as_text; } +#if ELF_BITS == 64 + if (opts.keep_relocs) { + struct section *sec_reloc; + uint32_t size_needed; + unsigned long offset; + + sec_reloc = sec_lookup(".data.reloc"); + if (!sec_reloc) + die("Could not find relocation data section\n"); + + size_needed = (3 + relocs64.count + relocs32neg.count + + relocs32.count) * sizeof(uint32_t); + if (size_needed > sec_reloc->shdr.sh_size) + die("Relocations overflow available space!\n" \ + "Please adjust CONFIG_RELOCATION_TABLE_SIZE" \ + "to at least 0x%08x\n", (size_needed + 0x1000) & ~0xFFF); + + offset = sec_reloc->shdr.sh_offset + sec_reloc->shdr.sh_size - + size_needed; + if (fseek(f, offset, SEEK_SET) < 0) + die("Seek to %ld failed: %s\n", offset, strerror(errno)); + + outf = f; + } +#endif + if (opts.use_real_mode) { - write_reloc(relocs16.count, stdout); + write_reloc(relocs16.count, outf); for (i = 0; i < relocs16.count; i++) - write_reloc(relocs16.offset[i], stdout); + write_reloc(relocs16.offset[i], outf); - write_reloc(relocs32.count, stdout); + write_reloc(relocs32.count, outf); for (i = 0; i < relocs32.count; i++) - write_reloc(relocs32.offset[i], stdout); + write_reloc(relocs32.offset[i], outf); } else { #if ELF_BITS == 64 /* Print a stop */ - write_reloc(0, stdout); + write_reloc(0, outf); /* Now print each relocation */ for (i = 0; i < relocs64.count; i++) - write_reloc(relocs64.offset[i], stdout); + write_reloc(relocs64.offset[i], outf); /* Print a stop */ - write_reloc(0, stdout); + write_reloc(0, outf); /* Now print each inverse 32-bit relocation */ for (i = 0; i < relocs32neg.count; i++) - write_reloc(relocs32neg.offset[i], stdout); + write_reloc(relocs32neg.offset[i], outf); #endif /* Print a stop */ - write_reloc(0, stdout); + write_reloc(0, outf); /* Now print each relocation */ for (i = 0; i < relocs32.count; i++) - write_reloc(relocs32.offset[i], stdout); + write_reloc(relocs32.offset[i], outf); } } @@ -1294,5 +1332,5 @@ void process(FILE *fp) print_reloc_info(); return; } - emit_relocs(); + emit_relocs(fp); } diff --git a/arch/x86/tools/relocs.h b/arch/x86/tools/relocs.h index 1cb0e235ad73..20f729e4579f 100644 --- a/arch/x86/tools/relocs.h +++ b/arch/x86/tools/relocs.h @@ -37,6 +37,7 @@ struct opts { bool show_absolute_syms; bool show_absolute_relocs; bool show_reloc_info; + bool keep_relocs; }; extern struct opts opts; diff --git a/arch/x86/tools/relocs_common.c b/arch/x86/tools/relocs_common.c index 17d69baee0c3..87d94d9e4b97 100644 --- a/arch/x86/tools/relocs_common.c +++ b/arch/x86/tools/relocs_common.c @@ -14,7 +14,7 @@ void die(char *fmt, ...) static void usage(void) { - die("relocs [--abs-syms|--abs-relocs|--reloc-info|--text|--realmode]" \ + die("relocs [--abs-syms|--abs-relocs|--reloc-info|--text|--realmode|--keep]" \ " vmlinux\n"); } @@ -49,6 +49,10 @@ int main(int argc, char **argv) opts.use_real_mode = true; continue; } + if (strcmp(arg, "--keep") == 0) { + opts.keep_relocs = true; + continue; + } } else if (!fname) { fname = arg; @@ -59,7 +63,10 @@ int main(int argc, char **argv) if (!fname) { usage(); } - fp = fopen(fname, "r"); + if (opts.keep_relocs) + fp = fopen(fname, "r+"); + else + fp = fopen(fname, "r"); if (!fp) { die("Cannot open %s: %s\n", fname, strerror(errno)); } -- 2.19.1.6.gb485710b