<div dir="ltr">Reverted in r317371.<br><div><br></div><div>Peter</div></div><div class="gmail_extra"><br><div class="gmail_quote">On Fri, Nov 3, 2017 at 1:48 PM, Peter Collingbourne <span dir="ltr"><<a href="mailto:peter@pcc.me.uk" target="_blank">peter@pcc.me.uk</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">Thanks. Just from looking at the code that reads input sections I see that a number of those functions appear to be hot, so that would probably explain it. It's probably not worth trying to segregate these functions based on whether they are performance critical or not (or at least I don't have time to do it right now), so I'll revert my change.<div><div><br></div><div>Peter</div></div></div><div class="gmail_extra"><div><div class="h5"><br><div class="gmail_quote">On Fri, Nov 3, 2017 at 1:36 PM, Rafael Espíndola <span dir="ltr"><<a href="mailto:rafael.espindola@gmail.com" target="_blank">rafael.espindola@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">This seems to have caused a performance regression when linking chrome.<br>
<br>
This test is fairly noisy, but the effect seems persistent on later changes.<br>
<br>
Cheers,<br>
Rafael<br>
<br>
<br>
On 31 October 2017 at 15:49, Peter Collingbourne via llvm-commits<br>
<div class="m_5539637813713696148HOEnZb"><div class="m_5539637813713696148h5"><<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a>> wrote:<br>
> Author: pcc<br>
> Date: Tue Oct 31 15:49:23 2017<br>
> New Revision: 317046<br>
><br>
> URL: <a href="http://llvm.org/viewvc/llvm-project?rev=317046&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject?rev=317046&view=rev</a><br>
> Log:<br>
> Object: Move some code from ELF.h into ELF.cpp.<br>
><br>
> Differential Revision: <a href="https://reviews.llvm.org/D39271" rel="noreferrer" target="_blank">https://reviews.llvm.org/D3927<wbr>1</a><br>
><br>
> Modified:<br>
>     llvm/trunk/include/llvm/Objec<wbr>t/ELF.h<br>
>     llvm/trunk/lib/Object/ELF.cpp<br>
><br>
> Modified: llvm/trunk/include/llvm/Object<wbr>/ELF.h<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Object/ELF.h?rev=317046&r1=317045&r2=317046&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/include/llvm/<wbr>Object/ELF.h?rev=317046&r1=<wbr>317045&r2=317046&view=diff</a><br>
> ==============================<wbr>==============================<wbr>==================<br>
> --- llvm/trunk/include/llvm/Object<wbr>/ELF.h (original)<br>
> +++ llvm/trunk/include/llvm/Object<wbr>/ELF.h Tue Oct 31 15:49:23 2017<br>
> @@ -205,46 +205,6 @@ getExtendedSymbolTableIndex(co<wbr>nst typena<br>
>  }<br>
><br>
>  template <class ELFT><br>
> -Expected<uint32_t><br>
> -ELFFile<ELFT>::getSectionInde<wbr>x(const Elf_Sym *Sym, Elf_Sym_Range Syms,<br>
> -                               ArrayRef<Elf_Word> ShndxTable) const {<br>
> -  uint32_t Index = Sym->st_shndx;<br>
> -  if (Index == ELF::SHN_XINDEX) {<br>
> -    auto ErrorOrIndex = getExtendedSymbolTableIndex<EL<wbr>FT>(<br>
> -        Sym, Syms.begin(), ShndxTable);<br>
> -    if (!ErrorOrIndex)<br>
> -      return ErrorOrIndex.takeError();<br>
> -    return *ErrorOrIndex;<br>
> -  }<br>
> -  if (Index == ELF::SHN_UNDEF || Index >= ELF::SHN_LORESERVE)<br>
> -    return 0;<br>
> -  return Index;<br>
> -}<br>
> -<br>
> -template <class ELFT><br>
> -Expected<const typename ELFT::Shdr *><br>
> -ELFFile<ELFT>::getSection(con<wbr>st Elf_Sym *Sym, const Elf_Shdr *SymTab,<br>
> -                          ArrayRef<Elf_Word> ShndxTable) const {<br>
> -  auto SymsOrErr = symbols(SymTab);<br>
> -  if (!SymsOrErr)<br>
> -    return SymsOrErr.takeError();<br>
> -  return getSection(Sym, *SymsOrErr, ShndxTable);<br>
> -}<br>
> -<br>
> -template <class ELFT><br>
> -Expected<const typename ELFT::Shdr *><br>
> -ELFFile<ELFT>::getSection(con<wbr>st Elf_Sym *Sym, Elf_Sym_Range Symbols,<br>
> -                          ArrayRef<Elf_Word> ShndxTable) const {<br>
> -  auto IndexOrErr = getSectionIndex(Sym, Symbols, ShndxTable);<br>
> -  if (!IndexOrErr)<br>
> -    return IndexOrErr.takeError();<br>
> -  uint32_t Index = *IndexOrErr;<br>
> -  if (Index == 0)<br>
> -    return nullptr;<br>
> -  return getSection(Index);<br>
> -}<br>
> -<br>
> -template <class ELFT><br>
>  inline Expected<const typename ELFT::Sym *><br>
>  getSymbol(typename ELFT::SymRange Symbols, uint32_t Index) {<br>
>    if (Index >= Symbols.size())<br>
> @@ -253,15 +213,6 @@ getSymbol(typename ELFT::SymRange Symbol<br>
>  }<br>
><br>
>  template <class ELFT><br>
> -Expected<const typename ELFT::Sym *><br>
> -ELFFile<ELFT>::getSymbol(cons<wbr>t Elf_Shdr *Sec, uint32_t Index) const {<br>
> -  auto SymtabOrErr = symbols(Sec);<br>
> -  if (!SymtabOrErr)<br>
> -    return SymtabOrErr.takeError();<br>
> -  return object::getSymbol<ELFT>(*Symta<wbr>bOrErr, Index);<br>
> -}<br>
> -<br>
> -template <class ELFT><br>
>  template <typename T><br>
>  Expected<ArrayRef<T>><br>
>  ELFFile<ELFT>::getSectionConte<wbr>ntsAsArray(const Elf_Shdr *Sec) const {<br>
> @@ -282,119 +233,6 @@ ELFFile<ELFT>::getSectionConte<wbr>ntsAsArray<br>
>  }<br>
><br>
>  template <class ELFT><br>
> -Expected<ArrayRef<uint8_t>><br>
> -ELFFile<ELFT>::getSectionCont<wbr>ents(const Elf_Shdr *Sec) const {<br>
> -  return getSectionContentsAsArray<uint<wbr>8_t>(Sec);<br>
> -}<br>
> -<br>
> -template <class ELFT><br>
> -StringRef ELFFile<ELFT>::getRelocationTy<wbr>peName(uint32_t Type) const {<br>
> -  return getELFRelocationTypeName(getHe<wbr>ader()->e_machine, Type);<br>
> -}<br>
> -<br>
> -template <class ELFT><br>
> -void ELFFile<ELFT>::getRelocationTy<wbr>peName(uint32_t Type,<br>
> -                                          SmallVectorImpl<char> &Result) const {<br>
> -  if (!isMipsELF64()) {<br>
> -    StringRef Name = getRelocationTypeName(Type);<br>
> -    Result.append(Name.begin(), Name.end());<br>
> -  } else {<br>
> -    // The Mips N64 ABI allows up to three operations to be specified per<br>
> -    // relocation record. Unfortunately there's no easy way to test for the<br>
> -    // presence of N64 ELFs as they have no special flag that identifies them<br>
> -    // as being N64. We can safely assume at the moment that all Mips<br>
> -    // ELFCLASS64 ELFs are N64. New Mips64 ABIs should provide enough<br>
> -    // information to disambiguate between old vs new ABIs.<br>
> -    uint8_t Type1 = (Type >> 0) & 0xFF;<br>
> -    uint8_t Type2 = (Type >> 8) & 0xFF;<br>
> -    uint8_t Type3 = (Type >> 16) & 0xFF;<br>
> -<br>
> -    // Concat all three relocation type names.<br>
> -    StringRef Name = getRelocationTypeName(Type1);<br>
> -    Result.append(Name.begin(), Name.end());<br>
> -<br>
> -    Name = getRelocationTypeName(Type2);<br>
> -    Result.append(1, '/');<br>
> -    Result.append(Name.begin(), Name.end());<br>
> -<br>
> -    Name = getRelocationTypeName(Type3);<br>
> -    Result.append(1, '/');<br>
> -    Result.append(Name.begin(), Name.end());<br>
> -  }<br>
> -}<br>
> -<br>
> -template <class ELFT><br>
> -Expected<const typename ELFT::Sym *><br>
> -ELFFile<ELFT>::getRelocationS<wbr>ymbol(const Elf_Rel *Rel,<br>
> -                                   const Elf_Shdr *SymTab) const {<br>
> -  uint32_t Index = Rel->getSymbol(isMips64EL());<br>
> -  if (Index == 0)<br>
> -    return nullptr;<br>
> -  return getEntry<Elf_Sym>(SymTab, Index);<br>
> -}<br>
> -<br>
> -template <class ELFT><br>
> -Expected<StringRef><br>
> -ELFFile<ELFT>::getSectionStri<wbr>ngTable(Elf_Shdr_Range Sections) const {<br>
> -  uint32_t Index = getHeader()->e_shstrndx;<br>
> -  if (Index == ELF::SHN_XINDEX)<br>
> -    Index = Sections[0].sh_link;<br>
> -<br>
> -  if (!Index) // no section string table.<br>
> -    return "";<br>
> -  if (Index >= Sections.size())<br>
> -    return createError("invalid section index");<br>
> -  return getStringTable(&Sections[Index<wbr>]);<br>
> -}<br>
> -<br>
> -template <class ELFT> ELFFile<ELFT>::ELFFile(StringR<wbr>ef Object) : Buf(Object) {}<br>
> -<br>
> -template <class ELFT><br>
> -Expected<ELFFile<ELFT>> ELFFile<ELFT>::create(StringRe<wbr>f Object) {<br>
> -  if (sizeof(Elf_Ehdr) > Object.size())<br>
> -    return createError("Invalid buffer");<br>
> -  return ELFFile(Object);<br>
> -}<br>
> -<br>
> -template <class ELFT><br>
> -Expected<typename ELFT::ShdrRange> ELFFile<ELFT>::sections() const {<br>
> -  const uintX_t SectionTableOffset = getHeader()->e_shoff;<br>
> -  if (SectionTableOffset == 0)<br>
> -    return ArrayRef<Elf_Shdr>();<br>
> -<br>
> -  if (getHeader()->e_shentsize != sizeof(Elf_Shdr))<br>
> -    return createError(<br>
> -        "invalid section header entry size (e_shentsize) in ELF header");<br>
> -<br>
> -  const uint64_t FileSize = Buf.size();<br>
> -<br>
> -  if (SectionTableOffset + sizeof(Elf_Shdr) > FileSize)<br>
> -    return createError("section header table goes past the end of the file");<br>
> -<br>
> -  // Invalid address alignment of section headers<br>
> -  if (SectionTableOffset & (alignof(Elf_Shdr) - 1))<br>
> -    return createError("invalid alignment of section headers");<br>
> -<br>
> -  const Elf_Shdr *First =<br>
> -      reinterpret_cast<const Elf_Shdr *>(base() + SectionTableOffset);<br>
> -<br>
> -  uintX_t NumSections = getHeader()->e_shnum;<br>
> -  if (NumSections == 0)<br>
> -    NumSections = First->sh_size;<br>
> -<br>
> -  if (NumSections > UINT64_MAX / sizeof(Elf_Shdr))<br>
> -    return createError("section table goes past the end of file");<br>
> -<br>
> -  const uint64_t SectionTableSize = NumSections * sizeof(Elf_Shdr);<br>
> -<br>
> -  // Section table goes past end of file!<br>
> -  if (SectionTableOffset + SectionTableSize > FileSize)<br>
> -    return createError("section table goes past the end of file");<br>
> -<br>
> -  return makeArrayRef(First, NumSections);<br>
> -}<br>
> -<br>
> -template <class ELFT><br>
>  template <typename T><br>
>  Expected<const T *> ELFFile<ELFT>::getEntry(uint32<wbr>_t Section,<br>
>                                              uint32_t Entry) const {<br>
> @@ -416,107 +254,6 @@ Expected<const T *> ELFFile<ELFT>::getEn<br>
>    return reinterpret_cast<const T *>(base() + Pos);<br>
>  }<br>
><br>
> -template <class ELFT><br>
> -Expected<const typename ELFT::Shdr *><br>
> -ELFFile<ELFT>::getSection(uin<wbr>t32_t Index) const {<br>
> -  auto TableOrErr = sections();<br>
> -  if (!TableOrErr)<br>
> -    return TableOrErr.takeError();<br>
> -  return object::getSection<ELFT>(*Tabl<wbr>eOrErr, Index);<br>
> -}<br>
> -<br>
> -template <class ELFT><br>
> -Expected<StringRef><br>
> -ELFFile<ELFT>::getStringTable<wbr>(const Elf_Shdr *Section) const {<br>
> -  if (Section->sh_type != ELF::SHT_STRTAB)<br>
> -    return createError("invalid sh_type for string table, expected SHT_STRTAB");<br>
> -  auto V = getSectionContentsAsArray<char<wbr>>(Section);<br>
> -  if (!V)<br>
> -    return V.takeError();<br>
> -  ArrayRef<char> Data = *V;<br>
> -  if (Data.empty())<br>
> -    return createError("empty string table");<br>
> -  if (Data.back() != '\0')<br>
> -    return createError("string table non-null terminated");<br>
> -  return StringRef(Data.begin(), Data.size());<br>
> -}<br>
> -<br>
> -template <class ELFT><br>
> -Expected<ArrayRef<typename ELFT::Word>><br>
> -ELFFile<ELFT>::getSHNDXTable(<wbr>const Elf_Shdr &Section) const {<br>
> -  auto SectionsOrErr = sections();<br>
> -  if (!SectionsOrErr)<br>
> -    return SectionsOrErr.takeError();<br>
> -  return getSHNDXTable(Section, *SectionsOrErr);<br>
> -}<br>
> -<br>
> -template <class ELFT><br>
> -Expected<ArrayRef<typename ELFT::Word>><br>
> -ELFFile<ELFT>::getSHNDXTable(<wbr>const Elf_Shdr &Section,<br>
> -                             Elf_Shdr_Range Sections) const {<br>
> -  assert(Section.sh_type == ELF::SHT_SYMTAB_SHNDX);<br>
> -  auto VOrErr = getSectionContentsAsArray<Elf_<wbr>Word>(&Section);<br>
> -  if (!VOrErr)<br>
> -    return VOrErr.takeError();<br>
> -  ArrayRef<Elf_Word> V = *VOrErr;<br>
> -  auto SymTableOrErr = object::getSection<ELFT>(Secti<wbr>ons, Section.sh_link);<br>
> -  if (!SymTableOrErr)<br>
> -    return SymTableOrErr.takeError();<br>
> -  const Elf_Shdr &SymTable = **SymTableOrErr;<br>
> -  if (SymTable.sh_type != ELF::SHT_SYMTAB &&<br>
> -      SymTable.sh_type != ELF::SHT_DYNSYM)<br>
> -    return createError("invalid sh_type");<br>
> -  if (V.size() != (SymTable.sh_size / sizeof(Elf_Sym)))<br>
> -    return createError("invalid section contents size");<br>
> -  return V;<br>
> -}<br>
> -<br>
> -template <class ELFT><br>
> -Expected<StringRef><br>
> -ELFFile<ELFT>::getStringTable<wbr>ForSymtab(const Elf_Shdr &Sec) const {<br>
> -  auto SectionsOrErr = sections();<br>
> -  if (!SectionsOrErr)<br>
> -    return SectionsOrErr.takeError();<br>
> -  return getStringTableForSymtab(Sec, *SectionsOrErr);<br>
> -}<br>
> -<br>
> -template <class ELFT><br>
> -Expected<StringRef><br>
> -ELFFile<ELFT>::getStringTable<wbr>ForSymtab(const Elf_Shdr &Sec,<br>
> -                                       Elf_Shdr_Range Sections) const {<br>
> -<br>
> -  if (Sec.sh_type != ELF::SHT_SYMTAB && Sec.sh_type != ELF::SHT_DYNSYM)<br>
> -    return createError(<br>
> -        "invalid sh_type for symbol table, expected SHT_SYMTAB or SHT_DYNSYM");<br>
> -  auto SectionOrErr = object::getSection<ELFT>(Secti<wbr>ons, Sec.sh_link);<br>
> -  if (!SectionOrErr)<br>
> -    return SectionOrErr.takeError();<br>
> -  return getStringTable(*SectionOrErr);<br>
> -}<br>
> -<br>
> -template <class ELFT><br>
> -Expected<StringRef><br>
> -ELFFile<ELFT>::getSectionName<wbr>(const Elf_Shdr *Section) const {<br>
> -  auto SectionsOrErr = sections();<br>
> -  if (!SectionsOrErr)<br>
> -    return SectionsOrErr.takeError();<br>
> -  auto Table = getSectionStringTable(*Section<wbr>sOrErr);<br>
> -  if (!Table)<br>
> -    return Table.takeError();<br>
> -  return getSectionName(Section, *Table);<br>
> -}<br>
> -<br>
> -template <class ELFT><br>
> -Expected<StringRef> ELFFile<ELFT>::getSectionName(<wbr>const Elf_Shdr *Section,<br>
> -                                                  StringRef DotShstrtab) const {<br>
> -  uint32_t Offset = Section->sh_name;<br>
> -  if (Offset == 0)<br>
> -    return StringRef();<br>
> -  if (Offset >= DotShstrtab.size())<br>
> -    return createError("invalid string offset");<br>
> -  return StringRef(DotShstrtab.data() + Offset);<br>
> -}<br>
> -<br>
>  /// This function returns the hash value for a symbol in the .dynsym section<br>
>  /// Name of the API remains consistent as specified in the libelf<br>
>  /// REF : <a href="http://www.sco.com/developers/gabi/latest/ch5.dynamic.html#hash" rel="noreferrer" target="_blank">http://www.sco.com/developers/<wbr>gabi/latest/ch5.dynamic.html#h<wbr>ash</a><br>
><br>
> Modified: llvm/trunk/lib/Object/ELF.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Object/ELF.cpp?rev=317046&r1=317045&r2=317046&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/llvm/trunk/lib/Object/EL<wbr>F.cpp?rev=317046&r1=317045&r2=<wbr>317046&view=diff</a><br>
> ==============================<wbr>==============================<wbr>==================<br>
> --- llvm/trunk/lib/Object/ELF.cpp (original)<br>
> +++ llvm/trunk/lib/Object/ELF.cpp Tue Oct 31 15:49:23 2017<br>
> @@ -215,6 +215,269 @@ StringRef llvm::object::getELFSectionTyp<br>
>  }<br>
><br>
>  template <class ELFT><br>
> +Expected<uint32_t><br>
> +ELFFile<ELFT>::getSectionInde<wbr>x(const Elf_Sym *Sym, Elf_Sym_Range Syms,<br>
> +                               ArrayRef<Elf_Word> ShndxTable) const {<br>
> +  uint32_t Index = Sym->st_shndx;<br>
> +  if (Index == ELF::SHN_XINDEX) {<br>
> +    auto ErrorOrIndex = getExtendedSymbolTableIndex<EL<wbr>FT>(<br>
> +        Sym, Syms.begin(), ShndxTable);<br>
> +    if (!ErrorOrIndex)<br>
> +      return ErrorOrIndex.takeError();<br>
> +    return *ErrorOrIndex;<br>
> +  }<br>
> +  if (Index == ELF::SHN_UNDEF || Index >= ELF::SHN_LORESERVE)<br>
> +    return 0;<br>
> +  return Index;<br>
> +}<br>
> +<br>
> +template <class ELFT><br>
> +Expected<const typename ELFT::Shdr *><br>
> +ELFFile<ELFT>::getSection(con<wbr>st Elf_Sym *Sym, const Elf_Shdr *SymTab,<br>
> +                          ArrayRef<Elf_Word> ShndxTable) const {<br>
> +  auto SymsOrErr = symbols(SymTab);<br>
> +  if (!SymsOrErr)<br>
> +    return SymsOrErr.takeError();<br>
> +  return getSection(Sym, *SymsOrErr, ShndxTable);<br>
> +}<br>
> +<br>
> +template <class ELFT><br>
> +Expected<const typename ELFT::Shdr *><br>
> +ELFFile<ELFT>::getSection(con<wbr>st Elf_Sym *Sym, Elf_Sym_Range Symbols,<br>
> +                          ArrayRef<Elf_Word> ShndxTable) const {<br>
> +  auto IndexOrErr = getSectionIndex(Sym, Symbols, ShndxTable);<br>
> +  if (!IndexOrErr)<br>
> +    return IndexOrErr.takeError();<br>
> +  uint32_t Index = *IndexOrErr;<br>
> +  if (Index == 0)<br>
> +    return nullptr;<br>
> +  return getSection(Index);<br>
> +}<br>
> +<br>
> +template <class ELFT><br>
> +Expected<const typename ELFT::Sym *><br>
> +ELFFile<ELFT>::getSymbol(cons<wbr>t Elf_Shdr *Sec, uint32_t Index) const {<br>
> +  auto SymtabOrErr = symbols(Sec);<br>
> +  if (!SymtabOrErr)<br>
> +    return SymtabOrErr.takeError();<br>
> +  return object::getSymbol<ELFT>(*Symta<wbr>bOrErr, Index);<br>
> +}<br>
> +<br>
> +template <class ELFT><br>
> +Expected<ArrayRef<uint8_t>><br>
> +ELFFile<ELFT>::getSectionCont<wbr>ents(const Elf_Shdr *Sec) const {<br>
> +  return getSectionContentsAsArray<uint<wbr>8_t>(Sec);<br>
> +}<br>
> +<br>
> +template <class ELFT><br>
> +StringRef ELFFile<ELFT>::getRelocationTy<wbr>peName(uint32_t Type) const {<br>
> +  return getELFRelocationTypeName(getHe<wbr>ader()->e_machine, Type);<br>
> +}<br>
> +<br>
> +template <class ELFT><br>
> +void ELFFile<ELFT>::getRelocationTy<wbr>peName(uint32_t Type,<br>
> +                                          SmallVectorImpl<char> &Result) const {<br>
> +  if (!isMipsELF64()) {<br>
> +    StringRef Name = getRelocationTypeName(Type);<br>
> +    Result.append(Name.begin(), Name.end());<br>
> +  } else {<br>
> +    // The Mips N64 ABI allows up to three operations to be specified per<br>
> +    // relocation record. Unfortunately there's no easy way to test for the<br>
> +    // presence of N64 ELFs as they have no special flag that identifies them<br>
> +    // as being N64. We can safely assume at the moment that all Mips<br>
> +    // ELFCLASS64 ELFs are N64. New Mips64 ABIs should provide enough<br>
> +    // information to disambiguate between old vs new ABIs.<br>
> +    uint8_t Type1 = (Type >> 0) & 0xFF;<br>
> +    uint8_t Type2 = (Type >> 8) & 0xFF;<br>
> +    uint8_t Type3 = (Type >> 16) & 0xFF;<br>
> +<br>
> +    // Concat all three relocation type names.<br>
> +    StringRef Name = getRelocationTypeName(Type1);<br>
> +    Result.append(Name.begin(), Name.end());<br>
> +<br>
> +    Name = getRelocationTypeName(Type2);<br>
> +    Result.append(1, '/');<br>
> +    Result.append(Name.begin(), Name.end());<br>
> +<br>
> +    Name = getRelocationTypeName(Type3);<br>
> +    Result.append(1, '/');<br>
> +    Result.append(Name.begin(), Name.end());<br>
> +  }<br>
> +}<br>
> +<br>
> +template <class ELFT><br>
> +Expected<const typename ELFT::Sym *><br>
> +ELFFile<ELFT>::getRelocationS<wbr>ymbol(const Elf_Rel *Rel,<br>
> +                                   const Elf_Shdr *SymTab) const {<br>
> +  uint32_t Index = Rel->getSymbol(isMips64EL());<br>
> +  if (Index == 0)<br>
> +    return nullptr;<br>
> +  return getEntry<Elf_Sym>(SymTab, Index);<br>
> +}<br>
> +<br>
> +template <class ELFT><br>
> +Expected<StringRef><br>
> +ELFFile<ELFT>::getSectionStri<wbr>ngTable(Elf_Shdr_Range Sections) const {<br>
> +  uint32_t Index = getHeader()->e_shstrndx;<br>
> +  if (Index == ELF::SHN_XINDEX)<br>
> +    Index = Sections[0].sh_link;<br>
> +<br>
> +  if (!Index) // no section string table.<br>
> +    return "";<br>
> +  if (Index >= Sections.size())<br>
> +    return createError("invalid section index");<br>
> +  return getStringTable(&Sections[Index<wbr>]);<br>
> +}<br>
> +<br>
> +template <class ELFT> ELFFile<ELFT>::ELFFile(StringR<wbr>ef Object) : Buf(Object) {}<br>
> +<br>
> +template <class ELFT><br>
> +Expected<ELFFile<ELFT>> ELFFile<ELFT>::create(StringRe<wbr>f Object) {<br>
> +  if (sizeof(Elf_Ehdr) > Object.size())<br>
> +    return createError("Invalid buffer");<br>
> +  return ELFFile(Object);<br>
> +}<br>
> +<br>
> +template <class ELFT><br>
> +Expected<typename ELFT::ShdrRange> ELFFile<ELFT>::sections() const {<br>
> +  const uintX_t SectionTableOffset = getHeader()->e_shoff;<br>
> +  if (SectionTableOffset == 0)<br>
> +    return ArrayRef<Elf_Shdr>();<br>
> +<br>
> +  if (getHeader()->e_shentsize != sizeof(Elf_Shdr))<br>
> +    return createError(<br>
> +        "invalid section header entry size (e_shentsize) in ELF header");<br>
> +<br>
> +  const uint64_t FileSize = Buf.size();<br>
> +<br>
> +  if (SectionTableOffset + sizeof(Elf_Shdr) > FileSize)<br>
> +    return createError("section header table goes past the end of the file");<br>
> +<br>
> +  // Invalid address alignment of section headers<br>
> +  if (SectionTableOffset & (alignof(Elf_Shdr) - 1))<br>
> +    return createError("invalid alignment of section headers");<br>
> +<br>
> +  const Elf_Shdr *First =<br>
> +      reinterpret_cast<const Elf_Shdr *>(base() + SectionTableOffset);<br>
> +<br>
> +  uintX_t NumSections = getHeader()->e_shnum;<br>
> +  if (NumSections == 0)<br>
> +    NumSections = First->sh_size;<br>
> +<br>
> +  if (NumSections > UINT64_MAX / sizeof(Elf_Shdr))<br>
> +    return createError("section table goes past the end of file");<br>
> +<br>
> +  const uint64_t SectionTableSize = NumSections * sizeof(Elf_Shdr);<br>
> +<br>
> +  // Section table goes past end of file!<br>
> +  if (SectionTableOffset + SectionTableSize > FileSize)<br>
> +    return createError("section table goes past the end of file");<br>
> +<br>
> +  return makeArrayRef(First, NumSections);<br>
> +}<br>
> +<br>
> +template <class ELFT><br>
> +Expected<const typename ELFT::Shdr *><br>
> +ELFFile<ELFT>::getSection(uin<wbr>t32_t Index) const {<br>
> +  auto TableOrErr = sections();<br>
> +  if (!TableOrErr)<br>
> +    return TableOrErr.takeError();<br>
> +  return object::getSection<ELFT>(*Tabl<wbr>eOrErr, Index);<br>
> +}<br>
> +<br>
> +template <class ELFT><br>
> +Expected<StringRef><br>
> +ELFFile<ELFT>::getStringTable<wbr>(const Elf_Shdr *Section) const {<br>
> +  if (Section->sh_type != ELF::SHT_STRTAB)<br>
> +    return createError("invalid sh_type for string table, expected SHT_STRTAB");<br>
> +  auto V = getSectionContentsAsArray<char<wbr>>(Section);<br>
> +  if (!V)<br>
> +    return V.takeError();<br>
> +  ArrayRef<char> Data = *V;<br>
> +  if (Data.empty())<br>
> +    return createError("empty string table");<br>
> +  if (Data.back() != '\0')<br>
> +    return createError("string table non-null terminated");<br>
> +  return StringRef(Data.begin(), Data.size());<br>
> +}<br>
> +<br>
> +template <class ELFT><br>
> +Expected<ArrayRef<typename ELFT::Word>><br>
> +ELFFile<ELFT>::getSHNDXTable(<wbr>const Elf_Shdr &Section) const {<br>
> +  auto SectionsOrErr = sections();<br>
> +  if (!SectionsOrErr)<br>
> +    return SectionsOrErr.takeError();<br>
> +  return getSHNDXTable(Section, *SectionsOrErr);<br>
> +}<br>
> +<br>
> +template <class ELFT><br>
> +Expected<ArrayRef<typename ELFT::Word>><br>
> +ELFFile<ELFT>::getSHNDXTable(<wbr>const Elf_Shdr &Section,<br>
> +                             Elf_Shdr_Range Sections) const {<br>
> +  assert(Section.sh_type == ELF::SHT_SYMTAB_SHNDX);<br>
> +  auto VOrErr = getSectionContentsAsArray<Elf_<wbr>Word>(&Section);<br>
> +  if (!VOrErr)<br>
> +    return VOrErr.takeError();<br>
> +  ArrayRef<Elf_Word> V = *VOrErr;<br>
> +  auto SymTableOrErr = object::getSection<ELFT>(Secti<wbr>ons, Section.sh_link);<br>
> +  if (!SymTableOrErr)<br>
> +    return SymTableOrErr.takeError();<br>
> +  const Elf_Shdr &SymTable = **SymTableOrErr;<br>
> +  if (SymTable.sh_type != ELF::SHT_SYMTAB &&<br>
> +      SymTable.sh_type != ELF::SHT_DYNSYM)<br>
> +    return createError("invalid sh_type");<br>
> +  if (V.size() != (SymTable.sh_size / sizeof(Elf_Sym)))<br>
> +    return createError("invalid section contents size");<br>
> +  return V;<br>
> +}<br>
> +<br>
> +template <class ELFT><br>
> +Expected<StringRef><br>
> +ELFFile<ELFT>::getStringTable<wbr>ForSymtab(const Elf_Shdr &Sec) const {<br>
> +  auto SectionsOrErr = sections();<br>
> +  if (!SectionsOrErr)<br>
> +    return SectionsOrErr.takeError();<br>
> +  return getStringTableForSymtab(Sec, *SectionsOrErr);<br>
> +}<br>
> +<br>
> +template <class ELFT><br>
> +Expected<StringRef><br>
> +ELFFile<ELFT>::getStringTable<wbr>ForSymtab(const Elf_Shdr &Sec,<br>
> +                                       Elf_Shdr_Range Sections) const {<br>
> +<br>
> +  if (Sec.sh_type != ELF::SHT_SYMTAB && Sec.sh_type != ELF::SHT_DYNSYM)<br>
> +    return createError(<br>
> +        "invalid sh_type for symbol table, expected SHT_SYMTAB or SHT_DYNSYM");<br>
> +  auto SectionOrErr = object::getSection<ELFT>(Secti<wbr>ons, Sec.sh_link);<br>
> +  if (!SectionOrErr)<br>
> +    return SectionOrErr.takeError();<br>
> +  return getStringTable(*SectionOrErr);<br>
> +}<br>
> +<br>
> +template <class ELFT><br>
> +Expected<StringRef><br>
> +ELFFile<ELFT>::getSectionName<wbr>(const Elf_Shdr *Section) const {<br>
> +  auto SectionsOrErr = sections();<br>
> +  if (!SectionsOrErr)<br>
> +    return SectionsOrErr.takeError();<br>
> +  auto Table = getSectionStringTable(*Section<wbr>sOrErr);<br>
> +  if (!Table)<br>
> +    return Table.takeError();<br>
> +  return getSectionName(Section, *Table);<br>
> +}<br>
> +<br>
> +template <class ELFT><br>
> +Expected<StringRef> ELFFile<ELFT>::getSectionName(<wbr>const Elf_Shdr *Section,<br>
> +                                                  StringRef DotShstrtab) const {<br>
> +  uint32_t Offset = Section->sh_name;<br>
> +  if (Offset == 0)<br>
> +    return StringRef();<br>
> +  if (Offset >= DotShstrtab.size())<br>
> +    return createError("invalid string offset");<br>
> +  return StringRef(DotShstrtab.data() + Offset);<br>
> +}<br>
> +<br>
> +template <class ELFT><br>
>  Expected<std::vector<typename ELFT::Rela>><br>
>  ELFFile<ELFT>::android_relas(c<wbr>onst Elf_Shdr *Sec) const {<br>
>    // This function reads relocations in Android's packed relocation format,<br>
><br>
><br>
> ______________________________<wbr>_________________<br>
> llvm-commits mailing list<br>
> <a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a><br>
> <a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/<wbr>mailman/listinfo/llvm-commits</a><br>
</div></div></blockquote></div><br><br clear="all"><div><br></div></div></div><span class="HOEnZb"><font color="#888888">-- <br><div class="m_5539637813713696148gmail_signature" data-smartmail="gmail_signature"><div dir="ltr">-- <div>Peter</div></div></div>
</font></span></div>
</blockquote></div><br><br clear="all"><div><br></div>-- <br><div class="gmail_signature" data-smartmail="gmail_signature"><div dir="ltr">-- <div>Peter</div></div></div>
</div>