[PATCH] D28612: [ELF] - Added support for --emit-relocs.
George Rimar via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Mon Jan 16 06:20:55 PST 2017
grimar added a comment.
So after little investigation about how linux kerner works with this featue I found next:
1. It links the real mode loader, and produces binary file realmode.bin using objcopy and realmode.relocs file with relocations using /x86/tools/relocs tool:
(http://git.kernel.org/cgit/linux/kernel/git/tip/tip.git/tree/arch/x86/realmode/rm/Makefile?id=f2604c141a00c00b92b7fd2f9d2455517fdd6c15#n43)
$(obj)/realmode.bin: $(obj)/realmode.elf
$(call if_changed,objcopy)
quiet_cmd_relocs = RELOCS $@
cmd_relocs = arch/x86/tools/relocs --realmode $< > $@
$(obj)/realmode.relocs: $(obj)/realmode.elf FORCE
$(call if_changed,relocs)
2. /x86/tools/relocs --realmode do next:
(https://github.com/torvalds/linux/blob/5924bbecd0267d87c24110cbe2041b5075173a25/arch/x86/tools/relocs.c#L1012)
write_reloc(relocs16.count, stdout);
for (i = 0; i < relocs16.count; i++)
write_reloc(relocs16.offset[i], stdout);
write_reloc(relocs32.count, stdout);
for (i = 0; i < relocs32.count; i++)
write_reloc(relocs32.offset[i], stdout);
So its output is a custom binary that has amount the relocations and relocations itself following.
Also it do some relocations sorting sorting before that code.
3. Then https://github.com/torvalds/linux/blob/master/arch/x86/realmode/rmpiggy.S packs the
result realmode.bin and realmode.relocs into single file, into .init.data section.
Also it creates symbol real_mode_relocs:
GLOBAL(real_mode_blob)
.incbin "arch/x86/realmode/rm/realmode.bin"
END(real_mode_blob)
GLOBAL(real_mode_blob_end);
GLOBAL(real_mode_relocs)
.incbin "arch/x86/realmode/rm/realmode.relocs"
END(real_mode_relocs)
4. After that all init.c uses the all data from above to perform self-relocations:
(https://github.com/torvalds/linux/blob/5924bbecd0267d87c24110cbe2041b5075173a25/arch/x86/realmode/init.c#L69)
/* 32-bit linear relocations. */
count = *rel++;
while (count--) {
u32 *ptr = (u32 *) (base + *rel++);
*ptr += phys_base;
}
I think we should just support that feature.
It is specific, but not huge itself + looks stoned in linux kernel atm.
It is easier to support it than to force users to create workarounds. What do you think ?
https://reviews.llvm.org/D28612
More information about the llvm-commits
mailing list