[RFC PATCH 51/73] x86/tools/relocs: Append relocations into input file

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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





[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux