[llvm-dev] [cfe-dev] LLD option to not apply relocations

Fāng-ruì Sòng via llvm-dev llvm-dev at lists.llvm.org
Fri Nov 16 14:15:43 PST 2018


https://reviews.llvm.org/D54651
On Fri, Nov 16, 2018 at 1:49 PM Fāng-ruì Sòng <maskray at google.com> wrote:
>
> Move it to llvm-dev :)
>
> A way to debug relocation overflow issues will be helpful, but to that
> end we can probably reuse the existing option --noinhibit-exec.
>
>   // --noinhibit-exec merely changes errorOrWarn to use warn instead
>   static inline void errorOrWarn(const Twine &Msg) {
>     if (!Config->NoinhibitExec)
>       error(Msg);
>     else
>       warn(Msg);
>   }
>
> However, these relocation overflows still inhibit the produce of an
> executable. It should be improved.
>
> % rm -f t; ld.bfd --noinhibit-exec --entry=func --gc-sections t.o -o t; ls t
> t.o: In function `func':
> (.text.func+0x3): relocation truncated to fit: R_X86_64_32S against
> symbol `func' defined in .text.func section in t.o
> t*
>
> % rm -f t; ld.lld --noinhibit-exec --entry=func --gc-sections t.o -o t; ls t
> ld.lld: error: t.o:(function func): relocation R_X86_64_32S out of
> range: -281474974609408 is not in [-2147483648, 2147483647]
> ls: cannot access 't': No such file or directory
> On Thu, Aug 30, 2018 at 9:32 AM Tim Hutt via cfe-dev
> <cfe-dev at lists.llvm.org> wrote:
> >
> > Hi,
> >
> > We have added an option to LLD to not apply relocations when writing out an ELF section and I wonder if you would accept it upstream. Why would we want that I hear you ask?
> >
> > Suppose we have a weird microcontroller with a 16-bit memory space. Naturally its relocations will be 16 bits (or less). If you try to link a file that is more than 65536 bytes you might get relocations that point beyond 65536 and cannot fit inside a 16-bit relocation. This means that when the section is written out it will give a relocation error and linking will fail. So far so reasonable. But what if your program *almost* fits in 65536 bytes? Wouldn't it be nice to get a binary out that is 65667 bytes (or whatever) even if it is broken. Then you can at least inspect it, e.g. with Bloaty McBloatface to see where you can save memory.
> >
> > That's where this option helps. It basically just ignores relocations when writing them out so you always get a (broken) binary even if relocations would have prevented it. The patch is really small (see below). Would you guys be willing to accept this, or if not can you suggest an alternative? Things I have tried / people have suggested:
> >
> > * Use -Map instead. Unfortunately the map file is written after relocations are resolved so this does not work.
> > * Use --relocatable. This does work, but it doesn't give the same file that you would get if linking had succeeded without it. In particular you can't use it with --gc-sections, which could make a huge difference if you have -ffunction-sections.
> > * Just pass all your .o files to Bloaty instead of the final binary. Unfortunately this suffers from the same problem - it doesn't account for --gc-sections or other things the linker might do.
> >
> > This works nicely for us. What do you think?
> >
> > Cheers,
> >
> > Tim
> >
> > ---
> >  ELF/Config.h         | 1 +
> >  ELF/Driver.cpp       | 1 +
> >  ELF/InputSection.cpp | 5 ++++-
> >  ELF/Options.td       | 3 +++
> >  4 files changed, 9 insertions(+), 1 deletion(-)
> >
> > diff --git a/ELF/Config.h b/ELF/Config.h
> > index f58931a84..3d2a99720 100644
> > --- a/ELF/Config.h
> > +++ b/ELF/Config.h
> > @@ -136,6 +136,7 @@ struct Configuration {
> >    bool ICF;
> >    bool IgnoreDataAddressEquality;
> >    bool IgnoreFunctionAddressEquality;
> > +  bool IgnoreRelocations;
> >    bool LTODebugPassManager;
> >    bool LTONewPassManager;
> >    bool MergeArmExidx;
> > diff --git a/ELF/Driver.cpp b/ELF/Driver.cpp
> > index bcf4eebb4..b83e06a46 100644
> > --- a/ELF/Driver.cpp
> > +++ b/ELF/Driver.cpp
> > @@ -705,6 +705,7 @@ void LinkerDriver::readConfigs(opt::InputArgList &Args) {
> >        Args.hasArg(OPT_ignore_data_address_equality);
> >    Config->IgnoreFunctionAddressEquality =
> >        Args.hasArg(OPT_ignore_function_address_equality);
> > +  Config->IgnoreRelocations = Args.hasArg(OPT_ignore_relocations);
> >    Config->Init = Args.getLastArgValue(OPT_init, "_init");
> >    Config->LTOAAPipeline = Args.getLastArgValue(OPT_lto_aa_pipeline);
> >    Config->LTODebugPassManager = Args.hasArg(OPT_lto_debug_pass_manager);
> > diff --git a/ELF/InputSection.cpp b/ELF/InputSection.cpp
> > index 77a50b657..4413b2355 100644
> > --- a/ELF/InputSection.cpp
> > +++ b/ELF/InputSection.cpp
> > @@ -795,7 +795,10 @@ template <class ELFT> void InputSection::writeTo(uint8_t *Buf) {
> >    // and then apply relocations.
> >    memcpy(Buf + OutSecOff, Data.data(), Data.size());
> >    uint8_t *BufEnd = Buf + OutSecOff + Data.size();
> > -  relocate<ELFT>(Buf, BufEnd);
> > +
> > +  if (!Config->IgnoreRelocations) {
> > +    relocate<ELFT>(Buf, BufEnd);
> > +  }
> >  }
> >
> >  void InputSection::replace(InputSection *Other) {
> > diff --git a/ELF/Options.td b/ELF/Options.td
> > index 582f70b0e..1ecbca3db 100644
> > --- a/ELF/Options.td
> > +++ b/ELF/Options.td
> > @@ -185,6 +185,9 @@ def ignore_function_address_equality: F<"ignore-function-address-equality">,
> >  def ignore_data_address_equality: F<"ignore-data-address-equality">,
> >    HelpText<"lld can break the address equality of data">;
> >
> > +def ignore_relocations: F<"ignore-relocations">,
> > +  HelpText<"don't resolve relocations when writing sections">;
> > +
> >  defm image_base : Eq<"image-base">, HelpText<"Set the base address">;
> >
> >  defm init: Eq<"init">, HelpText<"Specify an initializer function">,
> > --
> >
> > _______________________________________________
> > cfe-dev mailing list
> > cfe-dev at lists.llvm.org
> > http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
>
>
>
> --
> 宋方睿



-- 
宋方睿


More information about the llvm-dev mailing list