diff options
Diffstat (limited to 'lib/Object/ELFObjectFile.cpp')
| -rw-r--r-- | lib/Object/ELFObjectFile.cpp | 214 | 
1 files changed, 133 insertions, 81 deletions
diff --git a/lib/Object/ELFObjectFile.cpp b/lib/Object/ELFObjectFile.cpp index d2a2726ce739..e2ff4dfc0384 100644 --- a/lib/Object/ELFObjectFile.cpp +++ b/lib/Object/ELFObjectFile.cpp @@ -222,22 +222,24 @@ class ELFObjectFile : public ObjectFile {    const char     *getString(const Elf_Shdr *section, uint32_t offset) const;  protected: -  virtual SymbolRef getSymbolNext(DataRefImpl Symb) const; -  virtual StringRef getSymbolName(DataRefImpl Symb) const; -  virtual uint64_t  getSymbolAddress(DataRefImpl Symb) const; -  virtual uint64_t  getSymbolSize(DataRefImpl Symb) const; -  virtual char      getSymbolNMTypeChar(DataRefImpl Symb) const; -  virtual bool      isSymbolInternal(DataRefImpl Symb) const; - -  virtual SectionRef getSectionNext(DataRefImpl Sec) const; -  virtual StringRef  getSectionName(DataRefImpl Sec) const; -  virtual uint64_t   getSectionAddress(DataRefImpl Sec) const; -  virtual uint64_t   getSectionSize(DataRefImpl Sec) const; -  virtual StringRef  getSectionContents(DataRefImpl Sec) const; -  virtual bool       isSectionText(DataRefImpl Sec) const; +  virtual error_code getSymbolNext(DataRefImpl Symb, SymbolRef &Res) const; +  virtual error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const; +  virtual error_code getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const; +  virtual error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const; +  virtual error_code getSymbolNMTypeChar(DataRefImpl Symb, char &Res) const; +  virtual error_code isSymbolInternal(DataRefImpl Symb, bool &Res) const; + +  virtual error_code getSectionNext(DataRefImpl Sec, SectionRef &Res) const; +  virtual error_code getSectionName(DataRefImpl Sec, StringRef &Res) const; +  virtual error_code getSectionAddress(DataRefImpl Sec, uint64_t &Res) const; +  virtual error_code getSectionSize(DataRefImpl Sec, uint64_t &Res) const; +  virtual error_code getSectionContents(DataRefImpl Sec, StringRef &Res) const; +  virtual error_code isSectionText(DataRefImpl Sec, bool &Res) const; +  virtual error_code sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb, +                                           bool &Result) const;  public: -  ELFObjectFile(MemoryBuffer *Object); +  ELFObjectFile(MemoryBuffer *Object, error_code &ec);    virtual symbol_iterator begin_symbols() const;    virtual symbol_iterator end_symbols() const;    virtual section_iterator begin_sections() const; @@ -259,9 +261,9 @@ void ELFObjectFile<target_endianness, is64Bits>    //        an error object around.    if (!(  symb          && SymbolTableSection -        && symb >= (const Elf_Sym*)(base +        && symb >= (const Elf_Sym*)(base()                     + SymbolTableSection->sh_offset) -        && symb <  (const Elf_Sym*)(base +        && symb <  (const Elf_Sym*)(base()                     + SymbolTableSection->sh_offset                     + SymbolTableSection->sh_size)))      // FIXME: Proper error handling. @@ -269,8 +271,9 @@ void ELFObjectFile<target_endianness, is64Bits>  }  template<support::endianness target_endianness, bool is64Bits> -SymbolRef ELFObjectFile<target_endianness, is64Bits> -                       ::getSymbolNext(DataRefImpl Symb) const { +error_code ELFObjectFile<target_endianness, is64Bits> +                        ::getSymbolNext(DataRefImpl Symb, +                                        SymbolRef &Result) const {    validateSymbol(Symb);    const Elf_Shdr *SymbolTableSection = SymbolTableSections[Symb.d.b]; @@ -287,63 +290,80 @@ SymbolRef ELFObjectFile<target_endianness, is64Bits>      }    } -  return SymbolRef(Symb, this); +  Result = SymbolRef(Symb, this); +  return object_error::success;  }  template<support::endianness target_endianness, bool is64Bits> -StringRef ELFObjectFile<target_endianness, is64Bits> -                       ::getSymbolName(DataRefImpl Symb) const { +error_code ELFObjectFile<target_endianness, is64Bits> +                        ::getSymbolName(DataRefImpl Symb, +                                        StringRef &Result) const {    validateSymbol(Symb);    const Elf_Sym  *symb = getSymbol(Symb);    if (symb->st_name == 0) {      const Elf_Shdr *section = getSection(symb->st_shndx);      if (!section) -      return ""; -    return getString(dot_shstrtab_sec, section->sh_name); +      Result = ""; +    else +      Result = getString(dot_shstrtab_sec, section->sh_name); +    return object_error::success;    }    // Use the default symbol table name section. -  return getString(dot_strtab_sec, symb->st_name); +  Result = getString(dot_strtab_sec, symb->st_name); +  return object_error::success;  }  template<support::endianness target_endianness, bool is64Bits> -uint64_t ELFObjectFile<target_endianness, is64Bits> -                      ::getSymbolAddress(DataRefImpl Symb) const { +error_code ELFObjectFile<target_endianness, is64Bits> +                        ::getSymbolAddress(DataRefImpl Symb, +                                           uint64_t &Result) const {    validateSymbol(Symb);    const Elf_Sym  *symb = getSymbol(Symb);    const Elf_Shdr *Section;    switch (symb->st_shndx) {    case ELF::SHN_COMMON:     // Undefined symbols have no address yet. -  case ELF::SHN_UNDEF: return UnknownAddressOrSize; -  case ELF::SHN_ABS: return symb->st_value; +  case ELF::SHN_UNDEF: +    Result = UnknownAddressOrSize; +    return object_error::success; +  case ELF::SHN_ABS: +    Result = symb->st_value; +    return object_error::success;    default: Section = getSection(symb->st_shndx);    }    switch (symb->getType()) { -  case ELF::STT_SECTION: return Section ? Section->sh_addr -                                        : UnknownAddressOrSize; +  case ELF::STT_SECTION: +    Result = Section ? Section->sh_addr : UnknownAddressOrSize; +    return object_error::success;    case ELF::STT_FUNC:    case ELF::STT_OBJECT:    case ELF::STT_NOTYPE: -    return symb->st_value; -  default: return UnknownAddressOrSize; +    Result = symb->st_value; +    return object_error::success; +  default: +    Result = UnknownAddressOrSize; +    return object_error::success;    }  }  template<support::endianness target_endianness, bool is64Bits> -uint64_t ELFObjectFile<target_endianness, is64Bits> -                      ::getSymbolSize(DataRefImpl Symb) const { +error_code ELFObjectFile<target_endianness, is64Bits> +                        ::getSymbolSize(DataRefImpl Symb, +                                        uint64_t &Result) const {    validateSymbol(Symb);    const Elf_Sym  *symb = getSymbol(Symb);    if (symb->st_size == 0) -    return UnknownAddressOrSize; -  return symb->st_size; +    Result = UnknownAddressOrSize; +  Result = symb->st_size; +  return object_error::success;  }  template<support::endianness target_endianness, bool is64Bits> -char ELFObjectFile<target_endianness, is64Bits> -                  ::getSymbolNMTypeChar(DataRefImpl Symb) const { +error_code ELFObjectFile<target_endianness, is64Bits> +                        ::getSymbolNMTypeChar(DataRefImpl Symb, +                                              char &Result) const {    validateSymbol(Symb);    const Elf_Sym  *symb = getSymbol(Symb);    const Elf_Shdr *Section = getSection(symb->st_shndx); @@ -390,89 +410,120 @@ char ELFObjectFile<target_endianness, is64Bits>          ret = 'W';    } -  if (ret == '?' && symb->getType() == ELF::STT_SECTION) -    return StringSwitch<char>(getSymbolName(Symb)) +  if (ret == '?' && symb->getType() == ELF::STT_SECTION) { +    StringRef name; +    if (error_code ec = getSymbolName(Symb, name)) +      return ec; +    Result = StringSwitch<char>(name)        .StartsWith(".debug", 'N')        .StartsWith(".note", 'n'); +    return object_error::success; +  } -  return ret; +  Result = ret; +  return object_error::success;  }  template<support::endianness target_endianness, bool is64Bits> -bool ELFObjectFile<target_endianness, is64Bits> -                  ::isSymbolInternal(DataRefImpl Symb) const { +error_code ELFObjectFile<target_endianness, is64Bits> +                        ::isSymbolInternal(DataRefImpl Symb, +                                           bool &Result) const {    validateSymbol(Symb);    const Elf_Sym  *symb = getSymbol(Symb);    if (  symb->getType() == ELF::STT_FILE       || symb->getType() == ELF::STT_SECTION) -    return true; -  return false; +    Result = true; +  Result = false; +  return object_error::success;  }  template<support::endianness target_endianness, bool is64Bits> -SectionRef ELFObjectFile<target_endianness, is64Bits> -                        ::getSectionNext(DataRefImpl Sec) const { +error_code ELFObjectFile<target_endianness, is64Bits> +                        ::getSectionNext(DataRefImpl Sec, SectionRef &Result) const {    const uint8_t *sec = reinterpret_cast<const uint8_t *>(Sec.p);    sec += Header->e_shentsize;    Sec.p = reinterpret_cast<intptr_t>(sec); -  return SectionRef(Sec, this); +  Result = SectionRef(Sec, this); +  return object_error::success;  }  template<support::endianness target_endianness, bool is64Bits> -StringRef ELFObjectFile<target_endianness, is64Bits> -                       ::getSectionName(DataRefImpl Sec) const { +error_code ELFObjectFile<target_endianness, is64Bits> +                        ::getSectionName(DataRefImpl Sec, +                                         StringRef &Result) const {    const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); -  return StringRef(getString(dot_shstrtab_sec, sec->sh_name)); +  Result = StringRef(getString(dot_shstrtab_sec, sec->sh_name)); +  return object_error::success;  }  template<support::endianness target_endianness, bool is64Bits> -uint64_t ELFObjectFile<target_endianness, is64Bits> -                      ::getSectionAddress(DataRefImpl Sec) const { +error_code ELFObjectFile<target_endianness, is64Bits> +                        ::getSectionAddress(DataRefImpl Sec, +                                            uint64_t &Result) const {    const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); -  return sec->sh_addr; +  Result = sec->sh_addr; +  return object_error::success;  }  template<support::endianness target_endianness, bool is64Bits> -uint64_t ELFObjectFile<target_endianness, is64Bits> -                      ::getSectionSize(DataRefImpl Sec) const { +error_code ELFObjectFile<target_endianness, is64Bits> +                        ::getSectionSize(DataRefImpl Sec, +                                         uint64_t &Result) const {    const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); -  return sec->sh_size; +  Result = sec->sh_size; +  return object_error::success;  }  template<support::endianness target_endianness, bool is64Bits> -StringRef ELFObjectFile<target_endianness, is64Bits> -                       ::getSectionContents(DataRefImpl Sec) const { +error_code ELFObjectFile<target_endianness, is64Bits> +                        ::getSectionContents(DataRefImpl Sec, +                                             StringRef &Result) const {    const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p); -  const char *start = (char*)base + sec->sh_offset; -  return StringRef(start, sec->sh_size); +  const char *start = (const char*)base() + sec->sh_offset; +  Result = StringRef(start, sec->sh_size); +  return object_error::success;  }  template<support::endianness target_endianness, bool is64Bits> -bool ELFObjectFile<target_endianness, is64Bits> -                  ::isSectionText(DataRefImpl Sec) const { +error_code ELFObjectFile<target_endianness, is64Bits> +                        ::isSectionText(DataRefImpl Sec, +                                        bool &Result) const {    const Elf_Shdr *sec = reinterpret_cast<const Elf_Shdr *>(Sec.p);    if (sec->sh_flags & ELF::SHF_EXECINSTR) -    return true; -  return false; +    Result = true; +  else +    Result = false; +  return object_error::success; +} + +template<support::endianness target_endianness, bool is64Bits> +error_code ELFObjectFile<target_endianness, is64Bits> +                          ::sectionContainsSymbol(DataRefImpl Sec, +                                                  DataRefImpl Symb, +                                                  bool &Result) const { +  // FIXME: Unimplemented. +  Result = false; +  return object_error::success;  }  template<support::endianness target_endianness, bool is64Bits> -ELFObjectFile<target_endianness, is64Bits>::ELFObjectFile(MemoryBuffer *Object) -  : ObjectFile(Object) +ELFObjectFile<target_endianness, is64Bits>::ELFObjectFile(MemoryBuffer *Object +                                                          , error_code &ec) +  : ObjectFile(Binary::isELF, Object, ec)    , SectionHeaderTable(0)    , dot_shstrtab_sec(0)    , dot_strtab_sec(0) { -  Header = reinterpret_cast<const Elf_Ehdr *>(base); +  Header = reinterpret_cast<const Elf_Ehdr *>(base());    if (Header->e_shoff == 0)      return;    SectionHeaderTable = -    reinterpret_cast<const Elf_Shdr *>(base + Header->e_shoff); +    reinterpret_cast<const Elf_Shdr *>(base() + Header->e_shoff);    uint32_t SectionTableSize = Header->e_shnum * Header->e_shentsize;    if (!(  (const uint8_t *)SectionHeaderTable + SectionTableSize -         <= base + MapFile->getBufferSize())) +         <= base() + Data->getBufferSize()))      // FIXME: Proper error handling.      report_fatal_error("Section table goes past end of file!"); @@ -491,7 +542,7 @@ ELFObjectFile<target_endianness, is64Bits>::ELFObjectFile(MemoryBuffer *Object)    dot_shstrtab_sec = getSection(Header->e_shstrndx);    if (dot_shstrtab_sec) {      // Verify that the last byte in the string table in a null. -    if (((const char*)base + dot_shstrtab_sec->sh_offset) +    if (((const char*)base() + dot_shstrtab_sec->sh_offset)          [dot_shstrtab_sec->sh_size - 1] != 0)        // FIXME: Proper error handling.        report_fatal_error("String table must end with a null terminator!"); @@ -509,7 +560,7 @@ ELFObjectFile<target_endianness, is64Bits>::ELFObjectFile(MemoryBuffer *Object)            // FIXME: Proper error handling.            report_fatal_error("Already found section named .strtab!");          dot_strtab_sec = sh; -        const char *dot_strtab = (const char*)base + sh->sh_offset; +        const char *dot_strtab = (const char*)base() + sh->sh_offset;            if (dot_strtab[sh->sh_size - 1] != 0)              // FIXME: Proper error handling.              report_fatal_error("String table must end with a null terminator!"); @@ -548,7 +599,7 @@ ObjectFile::section_iterator ELFObjectFile<target_endianness, is64Bits>                                            ::begin_sections() const {    DataRefImpl ret;    memset(&ret, 0, sizeof(DataRefImpl)); -  ret.p = reinterpret_cast<intptr_t>(base + Header->e_shoff); +  ret.p = reinterpret_cast<intptr_t>(base() + Header->e_shoff);    return section_iterator(SectionRef(ret, this));  } @@ -557,7 +608,7 @@ ObjectFile::section_iterator ELFObjectFile<target_endianness, is64Bits>                                            ::end_sections() const {    DataRefImpl ret;    memset(&ret, 0, sizeof(DataRefImpl)); -  ret.p = reinterpret_cast<intptr_t>(base +  ret.p = reinterpret_cast<intptr_t>(base()                                       + Header->e_shoff                                       + (Header->e_shentsize * Header->e_shnum));    return section_iterator(SectionRef(ret, this)); @@ -613,7 +664,7 @@ const typename ELFObjectFile<target_endianness, is64Bits>::Elf_Sym *  ELFObjectFile<target_endianness, is64Bits>::getSymbol(DataRefImpl Symb) const {    const Elf_Shdr *sec = SymbolTableSections[Symb.d.b];    return reinterpret_cast<const Elf_Sym *>( -           base +           base()             + sec->sh_offset             + (Symb.d.a * sec->sh_entsize));  } @@ -656,8 +707,8 @@ const char *ELFObjectFile<target_endianness, is64Bits>    assert(section && section->sh_type == ELF::SHT_STRTAB && "Invalid section!");    if (offset >= section->sh_size)      // FIXME: Proper error handling. -    report_fatal_error("Sybol name offset outside of string table!"); -  return (const char *)base + section->sh_offset + offset; +    report_fatal_error("Symbol name offset outside of string table!"); +  return (const char *)base() + section->sh_offset + offset;  }  // EI_CLASS, EI_DATA. @@ -673,14 +724,15 @@ namespace llvm {    ObjectFile *ObjectFile::createELFObjectFile(MemoryBuffer *Object) {      std::pair<unsigned char, unsigned char> Ident = getElfArchType(Object); +    error_code ec;      if (Ident.first == ELF::ELFCLASS32 && Ident.second == ELF::ELFDATA2LSB) -      return new ELFObjectFile<support::little, false>(Object); +      return new ELFObjectFile<support::little, false>(Object, ec);      else if (Ident.first == ELF::ELFCLASS32 && Ident.second == ELF::ELFDATA2MSB) -      return new ELFObjectFile<support::big, false>(Object); +      return new ELFObjectFile<support::big, false>(Object, ec);      else if (Ident.first == ELF::ELFCLASS64 && Ident.second == ELF::ELFDATA2LSB) -      return new ELFObjectFile<support::little, true>(Object); +      return new ELFObjectFile<support::little, true>(Object, ec);      else if (Ident.first == ELF::ELFCLASS64 && Ident.second == ELF::ELFDATA2MSB) -      return new ELFObjectFile<support::big, true>(Object); +      return new ELFObjectFile<support::big, true>(Object, ec);      // FIXME: Proper error handling.      report_fatal_error("Not an ELF object file!");    }  | 
