[PATCH] D26133: [ELF] Allow relative relocations to absolute symbols in PIC

Roland McGrath via llvm-commits llvm-commits at lists.llvm.org
Fri Mar 3 16:45:12 PST 2017


I think I've read all the discussion on this, and IMHO it has been
fundamentally misguided and gone down multiple tangential ratholes.  I hope
I can introduce some clarity here.  My intent is to reduce the controversy,
so apologies in advance if anything I say here raises someone's ire.

The ELF "specification" is not a formal standards document and it's a
mistake to read it as if it were one.  It was never written to be
interpreted precisely as a formal standard is.  It's never had real
multi-party review.  It's not the outcome of any standards process.
Despite being labelled a "specification", it's really just a general
overview of ELF linking, and documentation for the file format's layouts
and bit values.  You just can't read its individual clauses in isolation
and extrapolate to explain everything.  The document leaves a great deal
unsaid, and what it does say needs to be interpreted in the appropriate
context.

SHN_ABS means "absolute" in the context of the static link.  It's absolute
in the sense that it is not relative to a section.  ELF symbols do not
provide any notion of a runtime absolute address.  The wording describing
SHN_ABS is talking about its meaning in an input ET_REL file at static link
time.  It's wrong to extrapolate this to any more general context.

After the static link, i.e. in any ET_EXEC or ET_DYN object, there is only
one kind of symbol value: The st_value field is a statically "absolute"
address that must be adjusted at runtime by the object's runtime load bias.

In the runtime view, ELF sections are not a concept that exists, and
neither is SHN_ABS.  The dynamic linker does not do anything with the
st_shndx field in symbol table entries, except to notice the single special
value SHN_UNDEF (zero) as identifying an undefined symbol.  Once the
dynamic linker has chosen a particular symbol table entry in a particular
object to resolve a relocation, it ignores st_shndx entirely; it simply
takes the st_value from the symbol table entry and adds the object's
runtime load bias.  If you have a dynamic relocation that refers to a
SHN_ABS symbol with st_value 0, then it resolves to the runtime load bias
of the object defining that symbol (plus 0), not to absolute 0.

The runtime load bias is the difference between static addresses in the ELF
format's fields and their runtime counterparts.  It's usually calculated as
the difference between the first PT_LOAD segment's (p_vaddr & -p_align) and
the runtime address where that segment was actually loaded.  In ET_EXEC
objects, this difference is zero by definition.  In ET_DYN objects, it's
most common to have a PT_LOAD with (p_vaddr & -p_align) == 0, and so the
runtime load bias is often (imprecisely) referred to as the "load address".
But ELF symbol tables and other headers don't have any actual notion of
"load address" per se, and thus don't have any notion of "image-relative"
per se.

When I'm creating an ET_DYN object, I know what addresses I'm giving its
PT_LOAD segments.  When I create a file with its first (p_vaddr & -p_align)
at zero, then I know that st_value of 0 refers to the same address in
memory where the first segment is loaded.  Hence, when I say "_BASE = 0;"
at static link time, I know that _BASE refers to the beginning of the
image, even though there is no general-purpose notion of "image-relative".

This all being the case, any kind of relocation referring to any symbol
that is defined in the static link as STB_LOCAL or STV_HIDDEN (or that
otherwise becomes STB_LOCAL as part of the static link) should be relaxed,
regardless of other details about the symbol.  Any such PC-relative
relocation is relaxed away entirely to needing no dynamic relocation.
Any such absolute-address relocation is relaxed to R_*_RELATIVE.

A PC-relative relocation to an undefined, STB_GLOBAL, or STB_WEAK symbol
would indeed require a dynamic relocation entry, and thus is illegal on
machines where no PC-relative reloc type is valid for dynamic relocs; and,
when applied to a non-writable section, is a TEXTREL and thus is illegal on
machines or linker modes where TEXTREL is never allowed (such as always on
x86-64; under -z text on any machine; or always in LLD, where -z notext is
not supported at all).

It's true that assemblers' treatment of local symbols with literal (or
computed) integer values is inconsistent with what SHN_ABS symbols in an
ELF symbol table mean in general.  The fact is, assembler labels and
symbols are not ELF symbols.  They are an assembler notion that the
assembler defines, and then the assembler emits an ELF symbol table that is
derived from a subset of these assembler entities.  The assembler has a
traditional notion of when it does or doesn't need to generate a reloc,
which includes not generating relocs for locally-defined assembler symbols
with literal integer values.  That's a messy result of the historical
evolution of assemblers and object file formats, but it's not a bug
anywhere.

IMHO it would be a mistake to introduce any kinds of symbol definition or
expression value into the linker script language that are not directly
representable as ELF symbols.  Whatever you can define in the linker
script, you should also be able to define (once you've computed the value,
which might depend on what linking will do) in an input ET_REL file and
have the same result.  Fortunately, no such thing is actually required for
the case we're discussing, because SHN_ABS symbols already have the
semantics this case needs.


Thanks,
Roland
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20170303/67661ce5/attachment.html>


More information about the llvm-commits mailing list