[PATCH] [ARM] Use AT() in the linker script to create correct program headers
Jason Gunthorpe
jgunthorpe at obsidianresearch.com
Mon Oct 1 12:06:39 EDT 2012
On Mon, Oct 01, 2012 at 04:39:53PM +0100, Dave Martin wrote:
> > Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
> > LOAD 0x008000 0xc0008000 0x00008000 0x372244 0x3a4310 RWE 0x8000
>
> Not related directly to your patch, but I wonder why we don't we see
> separate r-x and rw- segments?
I think this is because the sections are not aligned when the
protections change, and the sections are not sorted by protection
type.
[ 1] .head.text PROGBITS c0008000 008000 0001c0 00 AX 0 0 32
[ 2] .text PROGBITS c00081c0 0081c0 1dc880 00 AX 0 0 32
[ 3] .rodata PROGBITS c01e5000 1e5000 060a80 00 A 0 0 32
[ 4] __bug_table PROGBITS c0245a80 245a80 002a78 00 A 0 0 1
[ 5] .pci_fixup PROGBITS c02484f8 2484f8 000090 00 A 0 0 4
[ 6] __param PROGBITS c0248588 248588 000280 00 A 0 0 4
[ 7] __modver PROGBITS c0248808 248808 0007f8 00 A 0 0 4
[ 8] .init.text PROGBITS c0249000 249000 01af20 00 AX 0 0 32
[ 9] .exit.text PROGBITS c0263f20 263f20 000c0c 00 AX 0 0 4
[10] .init.proc.info PROGBITS c0264b2c 264b2c 00009c 00 AX 0 0 1
[11] .init.arch.info PROGBITS c0264bc8 264bc8 000044 00 A 0 0 4
[12] .init.tagtable PROGBITS c0264c0c 264c0c 000040 00 A 0 0 4
[13] .init.data PROGBITS c0264c60 264c60 0f481c 00 WA 0 0 32
[14] .data PROGBITS c035a000 35a000 020220 00 WA 0 0 32
[15] .notes NOTE c037a220 37a220 000024 00 AX 0 0 4
[16] .bss NOBITS c037a260 37a244 0320b0 00 WA 0 0 32
[17] .comment PROGBITS 00000000 37a244 000021 01 MS 0 0 1
> > +/* If we have a known, fixed physical load address then set LOAD_OFFSET
> > + and generate an ELF that has the physical load address in the program
> > + headers. */
> > +#ifndef CONFIG_ARM_PATCH_PHYS_VIRT
> > +#define LOAD_OFFSET (PAGE_OFFSET - PHYS_OFFSET)
> > +#endif
> > +
>
> What happens if CONFIG_ARM_PATCH_PHYS_VIRT=y? This will be used
> increasingly, especially for multiplatform kernels.
Then LOAD_OFFSET is unset and include/asm-generic/vmlinux.lds.h does:
#ifndef LOAD_OFFSET
#define LOAD_OFFSET 0
#endif
Which is exactly the same case we have today. LOAD_OFFSET is not a
name I invented, it is the standard kernel name for the functionality.
> If the kernel is intended to be loadable at a physical address which is
> not statically known, no ELF loader that does not ignore the ELF
> phdr
In this case you can't really use a standard ELF loader to load the
kernel so, LOAD_OFFSET = 0 is fine. My case is using an ELF loader,
and I have set options for a static physical load address.
> > OUTPUT_ARCH(arm)
> > -ENTRY(stext)
> > +ENTRY(phys_start)
>
> This is debatable. In fact, stext has the property that its virtual
> (runtime) and load addresses are the same.
This is what other arches using LOAD_OFFSET do (eg see ia64), and is
sensible. ENTRY is *only* used by the ELF loader and specifies where
the loader should jump. It must be a physical address since the loader
only works with physical addresse. I don't understand your comment
that .stext has the same load and virtual address, that is clearly not
true for the ELF images my build is producing:
c0008000 T _text
c0008000 T stext
The physical address of that symbol is 0x8000.
> To represent this correctly in the linker scripts, the
> position-independent head.S code should be split out into a separate
> section to which LOAD_OFFSET is not applied.
I'm not sure, the linker script should use addresses that are correct
during runtime, and if the PIC code does not care about its PC then it
is fine to keep it at the virtual address to minimize confusion once
the MMU is on.
> Setting vaddr and paddr to PAGE_OFFSET (as we do now) and having the
> loader choose the appropriate board-specific place to load the kernel
> image makes this irrelevant, if I've understood the situation correctly.
Yes, if you use more loader stages then the load headers are ignored.
Our boot loaders on our boards boot straight ELF vmlinux.gz so they
need correct load headers.
Jason
More information about the linux-arm-kernel
mailing list