[llvm-commits] ELFReader.cpp update - Add support for References.

Michael Spencer bigcheesegs at gmail.com
Fri Sep 14 15:15:20 PDT 2012


On Fri, Sep 14, 2012 at 2:15 PM, Sid Manning <sidneym at codeaurora.org> wrote:
>
> Update to ReaderELF.cpp, ELF.h and test directory.
>
> -- Adds a testcase to check relocations are emitted.  Looks like
> TestingHelpers will need to to be updated in the near future for the many
> relocation types elf will likely support.
> -- Addresses style issues.
> -- Adds doxygen comments to Atoms classes and elaborates on some routines.
> -- Changes DefinedAtom's declaration of ELFReference to a reference.
> -- Some loops changed to c++11 style.
> -- findAtom uses DenseMap::lookup instead of looping.
> -- Uses the iterator added to ELF.h to step through the SHT_REL/RELA
> sections.  Thanks, Michael Spencer for the iterator in ELF.h.
>
> Thanks,
>
>
>
> --
> Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by
> The Linux Foundation

> Index: include/llvm/Object/ELF.h
> ===================================================================
> --- include/llvm/Object/ELF.h	(revision 163925)
> +++ include/llvm/Object/ELF.h	(working copy)

> +
> +private:
>    // Records for each version index the corresponding Verdef or Vernaux entry.
>    // This is filled the first time LoadVersionMap() is called.
>    class VersionMapEntry : public PointerIntPair<const void*, 1> {
> @@ -597,6 +650,27 @@
>    virtual dyn_iterator begin_dynamic_table() const;
>    virtual dyn_iterator end_dynamic_table() const;
>
> +  typedef ELFRelocationIterator<const Elf_Rela *> Elf_Rela_Iter;
> +  typedef ELFRelocationIterator<const Elf_Rel *> Elf_Rel_Iter;

These shouldn't have the const and *. ELFRelocationIterator already adds them.
With them opeartor * actually returns const RelocT * const &. This is why you
needed the reinterpret_casts in the other code.

> +
> +  virtual Elf_Rela_Iter beginELFRela(const Elf_Shdr *sec) const {
> +    return Elf_Rela_Iter(sec, (const char *)(base() + sec->sh_offset));
> +  };
> +
> +  virtual Elf_Rela_Iter endELFRela(const Elf_Shdr *sec) const {
> +    return Elf_Rela_Iter(sec, (const char *)
> +                         (base() + sec->sh_offset + sec->sh_size));
> +  };
> +

> Index: lib/ReaderWriter/ELF/ReaderELF.cpp
> ===================================================================
> --- lib/ReaderWriter/ELF/ReaderELF.cpp	(revision 163928)
> +++ lib/ReaderWriter/ELF/ReaderELF.cpp	(working copy)
> @@ -14,8 +14,10 @@
>
>  #include "lld/ReaderWriter/ReaderELF.h"
>  #include "lld/Core/File.h"
> +#include "lld/Core/Reference.h"
>
>  #include "llvm/ADT/ArrayRef.h"
> +#include "llvm/ADT/SmallString.h"
>  #include "llvm/ADT/StringRef.h"
>  #include "llvm/Object/ELF.h"
>  #include "llvm/Object/ObjectFile.h"
> @@ -39,38 +41,120 @@
>
>  namespace { // anonymous
>
> -// This atom class corresponds to absolute symbol
> +
> +///
> +/// Relocation References: Defined Atoms may contain
> +/// references that will need to be patched before
> +/// the executable is written.
> +///

This should match the style used elsewhere. No extra /// at the top and bottom
and it should have a \brief, which in this case would be all the text that is
currently there.

> +template <llvm::support::endianness target_endianness, bool is64Bits>
> +class ELFReference : public Reference {
> +
> +  typedef llvm::object::Elf_Rel_Impl
> +                        <target_endianness, is64Bits, false> Elf_Rel;
> +  typedef llvm::object::Elf_Rel_Impl
> +                        <target_endianness, is64Bits, true> Elf_Rela;
> +public:
> +
> +  ELFReference(const Elf_Rela *R, uint64_t O, const Atom *T)
> +    : _target(T)
> +    , _targetSymbolIndex(R->getSymbol())
> +    , _offsetInAtom(O)
> +    , _addend(R->r_addend)
> +    , _kind(R->getType()) {}
> +
> +  ELFReference(const Elf_Rel *R, uint64_t O, const Atom *T)
> +    : _target(T)
> +    , _targetSymbolIndex(R->getSymbol())
> +    , _offsetInAtom(O)
> +    , _addend(0)
> +    , _kind(R->getType()) {}
> +
> +
> +  virtual uint64_t offsetInAtom() const {
> +    return _offsetInAtom;
> +  }
> +
> +  virtual Kind kind() const {
> +    return _kind;
> +  }
> +
> +  virtual void setKind(Kind K) {
> +    _kind = K;
> +  }
> +
> +  virtual const Atom *target() const {
> +    return _target;
> +  }
> +
> +///
> +/// targetSymbolIndex: This is the symbol table index that contains
> +/// the target reference.
> +///

Comment style.

> +  virtual uint64_t targetSymbolIndex() const {
> +    return _targetSymbolIndex;
> +  }

This shouldn't be virtual.

> +
> +  virtual Addend addend() const {
> +    return _addend;
> +  }
> +
> +  virtual void setAddend(Addend A) {
> +    _addend = A;
> +  }
> +
> +  virtual void setTarget(const Atom *newAtom) {
> +    _target = newAtom;
> +  }

All of these virtual functions should be marked as final.

> +private:
> +  const Atom  *_target;
> +  uint64_t     _targetSymbolIndex;
> +  uint64_t     _offsetInAtom;
> +  Addend       _addend;
> +  Kind         _kind;
> +};
> +
> +
> +///
> +/// ELFAbsoluteAtom: These atoms store symbols that are fixed to a particular
> +/// address.  This atom has no content its address will be used by the
> +/// Writer to fixup references that point to it.
> +///

Comment style.

> +template<llvm::support::endianness target_endianness, bool is64Bits>
>  class ELFAbsoluteAtom: public AbsoluteAtom {
>
>  public:
>    ELFAbsoluteAtom(const File &F,
>                    llvm::StringRef N,
>                    uint64_t V)
> -    : OwningFile(F)
> -    , Name(N)
> -    , Value(V)
> +    : _owningFile(F)
> +    , _name(N)
> +    , _value(V)
>    {}
>
>    virtual const class File &file() const {
> -    return OwningFile;
> +    return _owningFile;
>    }
>
>    virtual llvm::StringRef name() const {
> -    return Name;
> +    return _name;
>    }
>
>    virtual uint64_t value() const {
> -    return Value;
> +    return _value;
>    }
>
>  private:
> -  const File &OwningFile;
> -  llvm::StringRef Name;
> -  uint64_t Value;
> +  const File &_owningFile;
> +  llvm::StringRef _name;
> +  uint64_t _value;
>  };

>
> -    std::map< const Elf_Shdr *, std::vector<const Elf_Sym *>> SectionSymbols;
> +    std::map< const Elf_Shdr *, std::vector<const Elf_Sym *>> sectionSymbols;
>
> -    llvm::object::symbol_iterator it(Obj->begin_symbols());
> -    llvm::object::symbol_iterator ie(Obj->end_symbols());
> +//  Handle: SHT_REL and SHT_RELA sections:
> +//  Increment over the sections, when REL/RELA section types are
> +//  found add the contents to the RelocationReferences map.
>
> +    llvm::object::section_iterator sit(_objFile->begin_sections());
> +    llvm::object::section_iterator sie(_objFile->end_sections());
> +    for (; sit != sie; sit.increment(EC)) {
> +      if (EC)
> +        return;
> +
> +      const Elf_Shdr *section = _objFile->getElfSection(sit);
> +
> +      if (section->sh_type == llvm::ELF::SHT_RELA) {
> +        llvm::StringRef sectionName;
> +        if ((EC = _objFile->getSectionName(section, sectionName)))
> +          return;
> +        // Get rid of the leading .rela so Atoms can use their own section
> +        // name to find the relocs.
> +        sectionName = sectionName.drop_front(5);
> +
> +        auto rai(_objFile->beginELFRela(section));
> +        auto rae(_objFile->endELFRela(section));
> +
> +        auto &Ref = _relocationAddendRefences[sectionName];
> +        for (; rai != rae; rai++) {
> +          Ref.push_back(reinterpret_cast<const Elf_Rela *>(&*rai));

This cast is incorrect and should be removed. See my comments from ELF.h.

> +        }
> +      }
> +
> +      if (section->sh_type == llvm::ELF::SHT_REL) {
> +        llvm::StringRef sectionName;
> +        if ((EC = _objFile->getSectionName(section, sectionName)))
> +          return;
> +        // Get rid of the leading .rel so Atoms can use their own section
> +        // name to find the relocs.
> +        sectionName = sectionName.drop_front(4);
> +
> +        auto ri(_objFile->beginELFRel(section));
> +        auto re(_objFile->endELFRel(section));
> +
> +        auto &Ref = _relocationReferences[sectionName];
> +        for (; ri != re; ri++) {
> +          Ref.push_back(reinterpret_cast<const Elf_Rel *>(&*ri));

Same as above.

> +        }
> +      }
> +    }
> +
> +
> +//  Increment over all the symbols collecting atoms and symbol
> +//  names for later use.
> +
> +    llvm::object::symbol_iterator it(_objFile->begin_symbols());
> +    llvm::object::symbol_iterator ie(_objFile->end_symbols());
> +

- Michael Spencer



More information about the llvm-commits mailing list