[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