ELFObjectFileBase(unsigned int Type, MemoryBufferRef Source);
public:
- virtual std::error_code getRelocationAddend(DataRefImpl Rel,
- int64_t &Res) const = 0;
+ virtual ErrorOr<int64_t> getRelocationAddend(DataRefImpl Rel) const = 0;
+
+ // FIXME: This is a bit of a hack. Every caller should know if it expecting
+ // and addend or not.
+ virtual bool hasRelocationAddend(DataRefImpl Rel) const = 0;
+
virtual std::pair<symbol_iterator, symbol_iterator>
getELFDynamicSymbolIterators() const = 0;
- virtual std::error_code getSymbolVersion(SymbolRef Symb, StringRef &Version,
- bool &IsDefault) const = 0;
-
virtual uint64_t getSectionFlags(SectionRef Sec) const = 0;
virtual uint32_t getSectionType(SectionRef Sec) const = 0;
+ virtual uint64_t getSymbolSize(SymbolRef Symb) const = 0;
+
static inline bool classof(const Binary *v) { return v->isELF(); }
};
typedef typename ELFFile<ELFT>::Elf_Shdr_Iter Elf_Shdr_Iter;
typedef typename ELFFile<ELFT>::Elf_Dyn_Iter Elf_Dyn_Iter;
+ uint64_t getSymbolSize(SymbolRef Symb) const override;
+
protected:
ELFFile<ELFT> EF;
StringRef &Res) const override;
std::error_code getSymbolAddress(DataRefImpl Symb,
uint64_t &Res) const override;
- std::error_code getSymbolAlignment(DataRefImpl Symb,
- uint32_t &Res) const override;
- std::error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const override;
+ uint64_t getSymbolValue(DataRefImpl Symb) const override;
+ uint32_t getSymbolAlignment(DataRefImpl Symb) const override;
+ uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override;
uint32_t getSymbolFlags(DataRefImpl Symb) const override;
std::error_code getSymbolOther(DataRefImpl Symb, uint8_t &Res) const override;
std::error_code getSymbolType(DataRefImpl Symb,
SymbolRef::Type &Res) const override;
+ section_iterator getSymbolSection(const Elf_Sym *Symb) const;
std::error_code getSymbolSection(DataRefImpl Symb,
section_iterator &Res) const override;
std::error_code
getRelocationTypeName(DataRefImpl Rel,
SmallVectorImpl<char> &Result) const override;
- std::error_code
- getRelocationValueString(DataRefImpl Rel,
- SmallVectorImpl<char> &Result) const override;
uint64_t getROffset(DataRefImpl Rel) const;
StringRef getRelocationTypeName(uint32_t Type) const;
// visibility is either DEFAULT or PROTECTED. All other symbols are not
// exported.
if ((Binding == ELF::STB_GLOBAL || Binding == ELF::STB_WEAK) &&
- (Visibility == ELF::STV_DEFAULT && Visibility == ELF::STV_PROTECTED))
+ (Visibility == ELF::STV_DEFAULT || Visibility == ELF::STV_PROTECTED))
return true;
return false;
section_iterator section_begin() const override;
section_iterator section_end() const override;
- std::error_code getRelocationAddend(DataRefImpl Rel,
- int64_t &Res) const override;
- std::error_code getSymbolVersion(SymbolRef Symb, StringRef &Version,
- bool &IsDefault) const override;
+ ErrorOr<int64_t> getRelocationAddend(DataRefImpl Rel) const override;
+ bool hasRelocationAddend(DataRefImpl Rel) const override;
uint64_t getSectionFlags(SectionRef Sec) const override;
uint32_t getSectionType(SectionRef Sec) const override;
std::error_code getPlatformFlags(unsigned &Result) const override {
Result = EF.getHeader()->e_flags;
- return object_error::success;
+ return std::error_code();
}
const ELFFile<ELFT> *getELFFile() const { return &EF; }
bool isRelocatableObject() const override;
};
-// Use an alignment of 2 for the typedefs since that is the worst case for
-// ELF files in archives.
-typedef ELFObjectFile<ELFType<support::little, 2, false> > ELF32LEObjectFile;
-typedef ELFObjectFile<ELFType<support::little, 2, true> > ELF64LEObjectFile;
-typedef ELFObjectFile<ELFType<support::big, 2, false> > ELF32BEObjectFile;
-typedef ELFObjectFile<ELFType<support::big, 2, true> > ELF64BEObjectFile;
+typedef ELFObjectFile<ELFType<support::little, false>> ELF32LEObjectFile;
+typedef ELFObjectFile<ELFType<support::little, true>> ELF64LEObjectFile;
+typedef ELFObjectFile<ELFType<support::big, false>> ELF32BEObjectFile;
+typedef ELFObjectFile<ELFType<support::big, true>> ELF64BEObjectFile;
template <class ELFT>
void ELFObjectFile<ELFT>::moveSymbolNext(DataRefImpl &Symb) const {
if (!Name)
return Name.getError();
Result = *Name;
- return object_error::success;
-}
-
-template <class ELFT>
-std::error_code ELFObjectFile<ELFT>::getSymbolVersion(SymbolRef SymRef,
- StringRef &Version,
- bool &IsDefault) const {
- DataRefImpl Symb = SymRef.getRawDataRefImpl();
- const Elf_Sym *symb = getSymbol(Symb);
- ErrorOr<StringRef> Ver =
- EF.getSymbolVersion(EF.getSection(Symb.d.b), symb, IsDefault);
- if (!Ver)
- return Ver.getError();
- Version = *Ver;
- return object_error::success;
+ return std::error_code();
}
template <class ELFT>
}
template <class ELFT>
-std::error_code ELFObjectFile<ELFT>::getSymbolAddress(DataRefImpl Symb,
- uint64_t &Result) const {
+uint64_t ELFObjectFile<ELFT>::getSymbolValue(DataRefImpl Symb) const {
const Elf_Sym *ESym = getSymbol(Symb);
- switch (EF.getSymbolTableIndex(ESym)) {
+ switch (ESym->st_shndx) {
case ELF::SHN_COMMON:
case ELF::SHN_UNDEF:
- Result = UnknownAddressOrSize;
- return object_error::success;
+ return UnknownAddress;
case ELF::SHN_ABS:
- Result = ESym->st_value;
- return object_error::success;
- default:
- break;
+ return ESym->st_value;
}
const Elf_Ehdr *Header = EF.getHeader();
- Result = ESym->st_value;
+ uint64_t Ret = ESym->st_value;
// Clear the ARM/Thumb or microMIPS indicator flag.
if ((Header->e_machine == ELF::EM_ARM || Header->e_machine == ELF::EM_MIPS) &&
ESym->getType() == ELF::STT_FUNC)
- Result &= ~1;
+ Ret &= ~1;
+
+ return Ret;
+}
+
+template <class ELFT>
+std::error_code ELFObjectFile<ELFT>::getSymbolAddress(DataRefImpl Symb,
+ uint64_t &Result) const {
+ Result = getSymbolValue(Symb);
+ const Elf_Sym *ESym = getSymbol(Symb);
+ switch (ESym->st_shndx) {
+ case ELF::SHN_COMMON:
+ case ELF::SHN_UNDEF:
+ case ELF::SHN_ABS:
+ return std::error_code();
+ }
+
+ const Elf_Ehdr *Header = EF.getHeader();
- if (Header->e_type == ELF::ET_REL)
- Result += EF.getSection(ESym)->sh_addr;
+ if (Header->e_type == ELF::ET_REL) {
+ const typename ELFFile<ELFT>::Elf_Shdr * Section = EF.getSection(ESym);
+ if (Section != nullptr)
+ Result += Section->sh_addr;
+ }
- return object_error::success;
+ return std::error_code();
}
template <class ELFT>
-std::error_code ELFObjectFile<ELFT>::getSymbolAlignment(DataRefImpl Symb,
- uint32_t &Res) const {
+uint32_t ELFObjectFile<ELFT>::getSymbolAlignment(DataRefImpl Symb) const {
Elf_Sym_Iter Sym = toELFSymIter(Symb);
if (Sym->st_shndx == ELF::SHN_COMMON)
- Res = Sym->st_value;
- else
- Res = 0;
- return object_error::success;
+ return Sym->st_value;
+ return 0;
}
template <class ELFT>
-std::error_code ELFObjectFile<ELFT>::getSymbolSize(DataRefImpl Symb,
- uint64_t &Result) const {
- Result = toELFSymIter(Symb)->st_size;
- return object_error::success;
+uint64_t ELFObjectFile<ELFT>::getSymbolSize(SymbolRef Symb) const {
+ return toELFSymIter(Symb.getRawDataRefImpl())->st_size;
+}
+
+template <class ELFT>
+uint64_t ELFObjectFile<ELFT>::getCommonSymbolSizeImpl(DataRefImpl Symb) const {
+ return toELFSymIter(Symb)->st_size;
}
template <class ELFT>
std::error_code ELFObjectFile<ELFT>::getSymbolOther(DataRefImpl Symb,
uint8_t &Result) const {
Result = toELFSymIter(Symb)->st_other;
- return object_error::success;
+ return std::error_code();
}
template <class ELFT>
Result = SymbolRef::ST_Other;
break;
}
- return object_error::success;
+ return std::error_code();
}
template <class ELFT>
EIter == EF.begin_symbols() || EIter == EF.begin_dynamic_symbols())
Result |= SymbolRef::SF_FormatSpecific;
- if (EF.getSymbolTableIndex(ESym) == ELF::SHN_UNDEF)
+ if (ESym->st_shndx == ELF::SHN_UNDEF)
Result |= SymbolRef::SF_Undefined;
- if (ESym->getType() == ELF::STT_COMMON ||
- EF.getSymbolTableIndex(ESym) == ELF::SHN_COMMON)
+ if (ESym->getType() == ELF::STT_COMMON || ESym->st_shndx == ELF::SHN_COMMON)
Result |= SymbolRef::SF_Common;
if (isExportedToOtherDSO(ESym))
Result |= SymbolRef::SF_Exported;
+ if (ESym->getVisibility() == ELF::STV_HIDDEN)
+ Result |= SymbolRef::SF_Hidden;
+
return Result;
}
template <class ELFT>
-std::error_code
-ELFObjectFile<ELFT>::getSymbolSection(DataRefImpl Symb,
- section_iterator &Res) const {
- const Elf_Sym *ESym = getSymbol(Symb);
+section_iterator
+ELFObjectFile<ELFT>::getSymbolSection(const Elf_Sym *ESym) const {
const Elf_Shdr *ESec = EF.getSection(ESym);
if (!ESec)
- Res = section_end();
+ return section_end();
else {
DataRefImpl Sec;
Sec.p = reinterpret_cast<intptr_t>(ESec);
- Res = section_iterator(SectionRef(Sec, this));
+ return section_iterator(SectionRef(Sec, this));
}
- return object_error::success;
+}
+
+template <class ELFT>
+std::error_code
+ELFObjectFile<ELFT>::getSymbolSection(DataRefImpl Symb,
+ section_iterator &Res) const {
+ Res = getSymbolSection(getSymbol(Symb));
+ return std::error_code();
}
template <class ELFT>
if (!Name)
return Name.getError();
Result = *Name;
- return object_error::success;
+ return std::error_code();
}
template <class ELFT>
StringRef &Result) const {
Elf_Shdr_Iter EShdr = toELFShdrIter(Sec);
Result = StringRef((const char *)base() + EShdr->sh_offset, EShdr->sh_size);
- return object_error::success;
+ return std::error_code();
}
template <class ELFT>
Result = ROffset;
}
- return object_error::success;
+ return std::error_code();
}
template <class ELFT>
assert(EF.getHeader()->e_type == ELF::ET_REL &&
"Only relocatable object files have relocation offsets");
Result = getROffset(Rel);
- return object_error::success;
+ return std::error_code();
}
template <class ELFT>
break;
}
}
- return object_error::success;
+ return std::error_code();
}
template <class ELFT>
}
EF.getRelocationTypeName(type, Result);
- return object_error::success;
+ return std::error_code();
}
template <class ELFT>
-std::error_code
-ELFObjectFile<ELFT>::getRelocationAddend(DataRefImpl Rel,
- int64_t &Result) const {
- const Elf_Shdr *sec = getRelSection(Rel);
- switch (sec->sh_type) {
- default:
- report_fatal_error("Invalid section type in Rel!");
- case ELF::SHT_REL: {
- Result = 0;
- return object_error::success;
- }
- case ELF::SHT_RELA: {
- Result = getRela(Rel)->r_addend;
- return object_error::success;
- }
- }
+ErrorOr<int64_t>
+ELFObjectFile<ELFT>::getRelocationAddend(DataRefImpl Rel) const {
+ if (getRelSection(Rel)->sh_type != ELF::SHT_RELA)
+ return object_error::parse_failed;
+ return (int64_t)getRela(Rel)->r_addend;
}
template <class ELFT>
-std::error_code ELFObjectFile<ELFT>::getRelocationValueString(
- DataRefImpl Rel, SmallVectorImpl<char> &Result) const {
- const Elf_Shdr *sec = getRelSection(Rel);
- uint8_t type;
- StringRef res;
- int64_t addend = 0;
- uint16_t symbol_index = 0;
- switch (sec->sh_type) {
- default:
- return object_error::parse_failed;
- case ELF::SHT_REL: {
- type = getRel(Rel)->getType(EF.isMips64EL());
- symbol_index = getRel(Rel)->getSymbol(EF.isMips64EL());
- // TODO: Read implicit addend from section data.
- break;
- }
- case ELF::SHT_RELA: {
- type = getRela(Rel)->getType(EF.isMips64EL());
- symbol_index = getRela(Rel)->getSymbol(EF.isMips64EL());
- addend = getRela(Rel)->r_addend;
- break;
- }
- }
- const Elf_Sym *symb =
- EF.template getEntry<Elf_Sym>(sec->sh_link, symbol_index);
- ErrorOr<StringRef> SymName =
- EF.getSymbolName(EF.getSection(sec->sh_link), symb);
- if (!SymName)
- return SymName.getError();
- switch (EF.getHeader()->e_machine) {
- case ELF::EM_X86_64:
- switch (type) {
- case ELF::R_X86_64_PC8:
- case ELF::R_X86_64_PC16:
- case ELF::R_X86_64_PC32: {
- std::string fmtbuf;
- raw_string_ostream fmt(fmtbuf);
- fmt << *SymName << (addend < 0 ? "" : "+") << addend << "-P";
- fmt.flush();
- Result.append(fmtbuf.begin(), fmtbuf.end());
- } break;
- case ELF::R_X86_64_8:
- case ELF::R_X86_64_16:
- case ELF::R_X86_64_32:
- case ELF::R_X86_64_32S:
- case ELF::R_X86_64_64: {
- std::string fmtbuf;
- raw_string_ostream fmt(fmtbuf);
- fmt << *SymName << (addend < 0 ? "" : "+") << addend;
- fmt.flush();
- Result.append(fmtbuf.begin(), fmtbuf.end());
- } break;
- default:
- res = "Unknown";
- }
- break;
- case ELF::EM_AARCH64: {
- std::string fmtbuf;
- raw_string_ostream fmt(fmtbuf);
- fmt << *SymName;
- if (addend != 0)
- fmt << (addend < 0 ? "" : "+") << addend;
- fmt.flush();
- Result.append(fmtbuf.begin(), fmtbuf.end());
- break;
- }
- case ELF::EM_386:
- case ELF::EM_ARM:
- case ELF::EM_HEXAGON:
- case ELF::EM_MIPS:
- res = *SymName;
- break;
- default:
- res = "Unknown";
- }
- if (Result.empty())
- Result.append(res.begin(), res.end());
- return object_error::success;
+bool ELFObjectFile<ELFT>::hasRelocationAddend(DataRefImpl Rel) const {
+ return getRelSection(Rel)->sh_type == ELF::SHT_RELA;
}
template <class ELFT>
case ELF::EM_SPARC:
case ELF::EM_SPARC32PLUS:
- return Triple::sparc;
+ return IsLittleEndian ? Triple::sparcel : Triple::sparc;
case ELF::EM_SPARCV9:
return Triple::sparcv9;
return EF.getHeader()->e_type == ELF::ET_REL;
}
-inline std::error_code getELFRelocationAddend(const RelocationRef R,
- int64_t &Addend) {
- const ObjectFile *Obj = R.getObjectFile();
- DataRefImpl DRI = R.getRawDataRefImpl();
- return cast<ELFObjectFileBase>(Obj)->getRelocationAddend(DRI, Addend);
-}
-
inline std::pair<symbol_iterator, symbol_iterator>
getELFDynamicSymbolIterators(const SymbolicFile *Obj) {
return cast<ELFObjectFileBase>(Obj)->getELFDynamicSymbolIterators();
}
-inline std::error_code GetELFSymbolVersion(const ObjectFile *Obj,
- const SymbolRef &Sym,
- StringRef &Version,
- bool &IsDefault) {
- return cast<ELFObjectFileBase>(Obj)
- ->getSymbolVersion(Sym, Version, IsDefault);
-}
}
}