Hi Vivek,
Thanks for your review!
On 7/6/06, Vivek Goyal <[EMAIL PROTECTED]> wrote:
On Fri, Jun 30, 2006 at 05:45:58PM +0900, Magnus Damm wrote:
> Here comes a working snapshot of some relocation code that I've been
> hacking on lately. I've only tested the code in qemu-system-i386, but
> x86_64 and other architectures may work too.
[snip]
Looks like we are relocating everything including absolute symbols. As long
as absolute symbols are representing address, its fine (like __bss_start)
but if they happen to represent a value which is not supposed to change
due to loading of vmlinux at a different address, it will be an issue.
Yes, all symbols should be relocated by my patch. That may of course
be wrong, but in my mind symbols were only used to represent code or
data that is present at a certain address. So when the base address is
changed all symbols should be adjusted as well.
I understand that it is possible to create a symbol that points to a
fixed address say mapping some hardware resource, but is that a
strategy currently used by Linux?
Probably we can skip relocating absolute symbols but then we shall have to
make sure none of the absolute symbols is representing a information which
is variable like section start addresss.
Or maybe it would make sense to only adjust relocations that are using
symbols which are part of certain types of sections.
Eric had posted a patch in the past which made some the absolute symbols
section relative.
http://marc.theaimsgroup.com/?l=linux-kernel&m=112266670613361&w=2
Nice.
I actually came across that patch a while ago, but I'm not sure how
much it will help with my current "relocate all symbols" strategy. If
we treat absolute symbols differently from relative then I'm sure the
patch will help.
[..]
> --- 0003/Makefile
> +++ work/Makefile 2006-06-30 12:57:25.000000000 +0900
> @@ -573,7 +573,7 @@ vmlinux-lds := arch/$(ARCH)/kernel/vmli
> # May be overridden by arch/$(ARCH)/Makefile
> quiet_cmd_vmlinux__ ?= LD $@
> cmd_vmlinux__ ?= $(LD) $(LDFLAGS) $(LDFLAGS_vmlinux) -o $@ \
> - -T $(vmlinux-lds) $(vmlinux-init) \
> + --emit-reloc -T $(vmlinux-lds) $(vmlinux-init) \
Should this be --emit-reloc or --emit-relocs
Oh, it should be --emit-relocs. Sorry about that.
Ok. So here we are trying to relocate an executable by retaining reloc
information.
FYI, In the past Eric had posted a working prototype where
he was compiling the kernel as a shared library (-shared) which was
compiled for physical address 1MB and relocating it if was loaded
at different address. He was doing relocation at kernel run time.
I've seen a similar approach (maybe it is the same code, I don't know)
used by a former colleague of mine (Jan Kratochvil, CC:ed). If you are
interested then you can have look at the details in
minik-patch-2.6.12-2.1 present in the mkdump-2.1 release. Have a look
at http://mkdump.sourceforge.net/ for more information.
Not sure which approach is better but got a question. By definition, are
executable files supposed to be relocatable? Or we are just trying to
do some hack by treating an R_386_32 type relocation as R_386_RELATIVE
effectively.
If they are supposed to be relocatable? No idea. I mean - my patch is
just asking the linker to keep the relocation information in the
files, right? Then if some external tool (like kexec) is using the
information to relocate the file, how bad can that be?
Isn't the difference between R_386_32 and R_386_RELATIVE that the
latter is a PC-relative addressing mode? The addressing mode and the
relocation type is setup by the compiler I think, and it is only up to
me to follow it to make sure the address is calculated correctly...
Thinking aloud, How about compiling the kernel as shared library and then
performing the relocations in user space at load time instead of runtime.
I must confess that I know too little about the exact differences
between a shared library and a binary with relocation information to
say anything wise. Why is vmlinux an executable?
[snip]
The assumption that gloabl variable will come before local fails on
my machine and build fails.
Eek. I did expect it to fail sooner or later, but not this early. =)
Why don't you provide references to local symbols from a fixed global
symbol like _stext. (Eric did it in the past)
I thought of doing that, but then I the idea of relocating sections to
different memory segments came to my mind. So maybe a good solution
would be to use the start address of the segment containing the symbol
instead.
I put following code to progress through the build.
for (i = 0; i < table_cnt; i++) {
- printf("\tPTR\t%#llx\n", table[i].addr);
+ if ((toupper(table[i].sym[0]) != 'A') &&
+ (table[i].addr - _stext > 0)) {
+ printf("\tPTR\t_stext + %#llx\n",
+ table[i].addr - _stext);
+ } else {
+ printf("\tPTR\t%#llx\n", table[i].addr);
+ }
I will have a look at this later on today. Thanks for the suggestion.
I am still trying to make this patch set work on my machine.
I've attached a newer version of the kernel patch. The kallsyms
utility is probably unchanged, but a CONFIG_RELOCATABLE variable has
been introduced together with some modpost changes.
The patch builds both on i386 and x86_64. I am however unable to
relocate the kernel using my patched kexec tool on x86_64 right now.
Thanks,
/ magnus
--- 0002/Makefile
+++ work/Makefile 2006-07-03 15:57:14.000000000 +0900
@@ -483,6 +483,12 @@ ifdef CONFIG_DEBUG_INFO
CFLAGS += -g
endif
+ifdef CONFIG_RELOCATABLE
+RELOCFLAGS := --emit-relocs
+else
+RELOCFLAGS :=
+endif
+
include $(srctree)/arch/$(ARCH)/Makefile
# arch Makefile may override CC so keep this after arch Makefile is included
@@ -573,7 +579,7 @@ vmlinux-lds := arch/$(ARCH)/kernel/vmli
# May be overridden by arch/$(ARCH)/Makefile
quiet_cmd_vmlinux__ ?= LD $@
cmd_vmlinux__ ?= $(LD) $(LDFLAGS) $(LDFLAGS_vmlinux) -o $@ \
- -T $(vmlinux-lds) $(vmlinux-init) \
+ $(RELOCFLAGS) -T $(vmlinux-lds) $(vmlinux-init) \
--start-group $(vmlinux-main) --end-group \
$(filter-out $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) FORCE ,$^)
@@ -702,6 +708,9 @@ endif # ifdef CONFIG_KALLSYMS
# vmlinux image - including updated kernel symbols
vmlinux: $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) $(kallsyms.o) FORCE
$(call if_changed_rule,vmlinux__)
+ifdef CONFIG_RELOCATABLE
+ $(Q)$(MAKE) -rR -f $(srctree)/scripts/Makefile.modpost __modpost_kernel
+endif
$(Q)rm -f .old_version
# The actual objects are generated when descending,
--- 0002/lib/Kconfig.debug
+++ work/lib/Kconfig.debug 2006-07-03 15:57:14.000000000 +0900
@@ -196,6 +196,16 @@ config UNWIND_INFO
If you don't debug the kernel, you can say N, but we may not be able
to solve problems without frame unwind information or frame pointers.
+config RELOCATABLE
+ bool "Compile the kernel with relocation information"
+ help
+ If you say Y here the resulting kernel image will be slightly larger.
+ The main reason behind including relocation information in the kernel
+ is to allow the boot loader to adjust the physical address where the
+ kernel is loaded. Another nice side effect of including relocation
+ information is that the modpost utility can be used to locate section
+ mismatches that otherwise only are detected on modules.
+
config FORCED_INLINING
bool "Force gcc to inline functions marked 'inline'"
depends on DEBUG_KERNEL
--- 0001/scripts/Makefile
+++ work/scripts/Makefile 2006-07-03 15:57:14.000000000 +0900
@@ -16,7 +16,7 @@ hostprogs-$(CONFIG_IKCONFIG) += bin2
always := $(hostprogs-y)
subdir-$(CONFIG_MODVERSIONS) += genksyms
-subdir-$(CONFIG_MODULES) += mod
+subdir-y += mod
# Let clean descend into subdirs
-subdir- += basic kconfig package
+subdir- += basic kconfig package mod
--- 0002/scripts/Makefile.modpost
+++ work/scripts/Makefile.modpost 2006-07-03 15:57:14.000000000 +0900
@@ -61,7 +61,11 @@ quiet_cmd_modpost = MODPOST
$(filter-out FORCE,$^)
PHONY += __modpost
-__modpost: $(wildcard vmlinux) $(modules:.ko=.o) FORCE
+__modpost: $(modules:.ko=.o) FORCE
+ $(call cmd,modpost)
+
+PHONY += __modpost_kernel
+__modpost_kernel: $(wildcard vmlinux) FORCE
$(call cmd,modpost)
# Declare generated files as targets for modpost
--- 0002/scripts/kallsyms.c
+++ work/scripts/kallsyms.c 2006-07-03 15:57:14.000000000 +0900
@@ -37,6 +37,7 @@
struct sym_entry {
unsigned long long addr;
unsigned int len;
+ unsigned char *orig_sym;
unsigned char *sym;
};
@@ -131,6 +132,7 @@ static int read_symbol(FILE *in, struct
}
strcpy((char *)s->sym + 1, str);
s->sym[0] = stype;
+ s->orig_sym = strdup(s->sym);
return 0;
}
@@ -266,8 +268,25 @@ static void write_src(void)
printf(".data\n");
output_label("kallsyms_addresses");
+ k = -1;
+
for (i = 0; i < table_cnt; i++) {
- printf("\tPTR\t%#llx\n", table[i].addr);
+ if (isupper(table[i].orig_sym[0])) {
+ k = i;
+ }
+ if (k == -1) {
+ fprintf(stderr, "kallsyms failure: "
+ "local variable present before global\n");
+ exit(EXIT_FAILURE);
+ }
+
+ printf("\tPTR\t%s",table[k].orig_sym + 1);
+ if (table[i].addr - table[k].addr) {
+ printf(" + %#llx /* %s */",
+ table[i].addr - table[k].addr,
+ table[i].orig_sym + 1);
+ }
+ printf("\n");
}
printf("\n");
_______________________________________________
fastboot mailing list
[email protected]
https://lists.osdl.org/mailman/listinfo/fastboot