[llvm-dev] Proposal: arbitrary relocations in constant global initializers

Peter Collingbourne via llvm-dev
Fri, 07 Oct 2016 20:22:58 -0000

On Fri, Oct 7, 2016 at 12:20 PM, Evgenii Stepanov <eugeni.stepanov at
gmail.com
> wrote:

> I've tried implementing some of the alternatives mentioned in this
> thread, and so far I like this syntax the most:
>
> i32 reloc (29, void ()* @f, 3925868544)
> ; 29 = 0x1d = R_ARM_JUMP24
> ; 3925868544 = 0xea000000
>
> Note the zeroes in the relocated data instead of 0xfffffe in the
> original proposal. This is aligned with the way LLVM emits relocations
> in the backend, and avoids encoding the addend in a
> relocation-specific way in the IR.


I am confused by this statement. If the zeros aren't what appear in the
object file, it seems rather relocation specific to me.


> Instead, the addend can be
> specified in the second argument with the regular IR expressions, like
> the following:
>
> @w = internal global [3 x i32]
>    [i32 reloc (29, void ()* @f, 3925868544),
>     i32 reloc (29, [3 x i32]* @w, 3925868544),
>     i32 reloc (29, i32* getelementptr (i32, i32* bitcast ([3 x i32]*
> @w to i32*), i32 1), 3925868544)
> ], align 4



we also get relocations for elements 1 and 2 of @w optimized out for

free. If the "addend" (i.e. the third arg of reloc) was specified as

0xeafffffe, the backend would have had to decode this value first.


I think it may be ok to allow non-global constants as the second operand
(the utility of this feature being the ability to freely RAUW a global
without worrying about reloc constants).

This doesn't necessarily need to act as an alternative means of specifying
an addend, though. Instead, the backend could synthesise local symbols to
act as relocation targets. For example, your example would conceptually
translate to:

@w = internal global [3 x i32]
   [i32 reloc (29, void ()* @f, 3925868544),
    i32 reloc (29, [3 x i32]* @w, 3925868544),
    i32 reloc (29, i32* @dummy, i32 1), 3925868544)

@dummy = internal alias i32* getelementptr (i32, i32* bitcast ([3 x i32]*
@w to i32*), i32 1)

This way, you save yourself from needing to worry about manipulating
addends in the backend, the linker will take care of it for you.

On the other hand, it is possible for a constant expression in the
IR
> to be lowered to something that is not a valid relocation target, and
> it is hard to detect this problem at the IR level.
>

Right, this is of course a problem we already have for aliasees and
constant initializers.


> Also, separating the addend from the section data allows the backend
> to choose between .rel and .rela representations.
>

Do you have an example of a rela relocation which uses both r_addend and
the underlying value in the object file?

Peter


> On Wed, Aug 26, 2015 at 3:29 PM, Peter Collingbourne via llvm-dev
> <llvm-dev at lists.llvm.org> wrote:
> > On Wed, Aug 26, 2015 at 03:53:33PM -0400, Rafael Espíndola wrote:
> >> > I'm not sure if this would be sufficient. The
R_ARM_JUMP24 relocation
> >> > on ARM has specific semantics to implement ARM/Thumb
interworking; see
> >> > http://infocenter.arm.com/help/topic/com.arm.doc.ihi0044e/
> IHI0044E_aaelf.pdf
> >> > Note that R_ARM_CALL has the same operation but different
semantics.
> >> > I suppose that we could try looking at the addend to decide
which
> relocation
> >> > to use, but this would mean adding more complexity to the
assembler
> (along
> >> > with any pattern matching that would need to be done). It
seems
> simpler,
> >> > both conceptually and in the implementation, for the client
to
> directly say
> >> > what it wants in the object file.
> >> >
> >> > There's also the point that if @foo is defined outside
the current
> linkage
> >> > unit, or refers to a Thumb function, the above expression in
a
> constant
> >> > initializer would refer to the function's PLT entry or a
shim, but in
> a
> >> > function it would refer to the function's actual address,
so the
> evaluation
> >> > of this expression would depend on whether it was constant
folded.
> (Although
> >> > on the other hand we might just declare that by using such a
constant
> in a
> >> > global initializer that may be constant folded the client is
> asserting that
> >> > it doesn't care which address is used.)
> >>
> >> I am pretty sure there is use for some target specific
expressions, my
> >> concerns are
> >> * Using a target specific expression when it could be represented
in a
> >> target independent way (possibly a bit more verbose).
> >
> > Well I don't think there's a target independent way to write
an
> R_ARM_JUMP24
> > relocation, as there's no way to represent the PLT entry or
interworking
> > shim in IR.
> >
> >> * Using the raw relocation values, instead of something like
> >> thumb_addr_delta. With this the semantics of each constant
expression
> >> are still documented in the language reference.
> >
> > I guess there are two ways we can go here:
> >
> > 1) expose the raw relocation values
> > 2) introduce new specific ConstantExpr subtypes for the
target-specific
> things we need
> >
> > In this case I think we should do one or the other, I don't really
think
> it's
> > worth adding a half measure of flexibility (e.g. providing a way to
> specify
> > the addend of a R_ARM_JUMP24 when it will pretty much always be the
> same).
> >
> > I like option 1 because it's more general purpose and ultimately
less of
> an
> > impedance mismatch between what the client wants and what appears in
the
> > object file, and we can solve the documentation problem with reference
to
> > the object file format documentation, but it would require our
> documentation
> > to depend on sometimes poorly documented object file formats.
> >
> > Option 2 could look something like this (produces the same bytes as
"b
> > some_label" in every object format when targeting ARM, or
"b.w
> some_label"
> > when targeting Thumb):
> >
> > i32 arm_b (void ()* @some_label)
> >
> > and that would be easy to document on its own. The downside is that
it's
> > pretty specific to my use case, but maybe that's ok.
> >
> > 2 seems like it would be less implementation work, and doesn't
require
> any
> > changes to the assembly format (and ultimately could be upgraded to 1
> later
> > if needed), so maybe it's best to start with that.
> >
> >> >> Why do you need to be able to avoid them showing up in
function
> >> >> bodies? It would be unusual but valid to pass the above
value as an
> >> >> argument to a function.
> >> >
> >> > This was part of the proposal mainly for the constant folding
reasons
> mentioned
> >> > above, but if we did go with a reloc expression we'd need
to encode
> the
> >> > original constant address in the reloc for PC-relative
expressions,
> which
> >> > wouldn't be necessary if we disallow it.
> >>
> >> Seems better to make it explicit IMHO.
> >
> > Okay, but if we do introduce a new constant kind, there doesn't
seem to
> be
> > much point in teaching the backend to lower it in a function, other
than
> > for completeness. If we can avoid having to do that, that seems
> preferable.
> >
> >> BTW, about the assembly change: Please check what the binutils
guys
> >> think of it. We do have extensions, but it is nice to at least let
> >> them know so that we don't end up with two independent
solutions in
> >> the future.
> >
> > Yes if I ultimately go with 1.
> >
> > Thanks,
> > --
> > Peter
> > _______________________________________________
> > LLVM Developers mailing list
> > llvm-dev at lists.llvm.org
> > http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
>



--
--
Peter
-------------- next part --------------
An HTML attachment was scrubbed...
URL:
<http://lists.llvm.org/pipermail/llvm-dev/attachments/20161007/8d7e88ac/attachment-0001.html>