diff options
Diffstat (limited to 'contrib/llvm-project/llvm/lib/Object')
13 files changed, 710 insertions, 181 deletions
diff --git a/contrib/llvm-project/llvm/lib/Object/Archive.cpp b/contrib/llvm-project/llvm/lib/Object/Archive.cpp index 6ff896cf347e..5492692445e7 100644 --- a/contrib/llvm-project/llvm/lib/Object/Archive.cpp +++ b/contrib/llvm-project/llvm/lib/Object/Archive.cpp @@ -418,7 +418,7 @@ Expected<bool> Archive::Child::isThinMember() const { if (!NameOrErr) return NameOrErr.takeError(); StringRef Name = NameOrErr.get(); - return Parent->IsThin && Name != "/" && Name != "//"; + return Parent->IsThin && Name != "/" && Name != "//" && Name != "/SYM64/"; } Expected<std::string> Archive::Child::getFullName() const { diff --git a/contrib/llvm-project/llvm/lib/Object/COFFModuleDefinition.cpp b/contrib/llvm-project/llvm/lib/Object/COFFModuleDefinition.cpp index 8f29f7a658fd..55ddd3baca2b 100644 --- a/contrib/llvm-project/llvm/lib/Object/COFFModuleDefinition.cpp +++ b/contrib/llvm-project/llvm/lib/Object/COFFModuleDefinition.cpp @@ -80,11 +80,6 @@ static bool isDecorated(StringRef Sym, bool MingwDef) { (!MingwDef && Sym.contains('@')); } -static Error createError(const Twine &Err) { - return make_error<StringError>(StringRef(Err.str()), - object_error::parse_failed); -} - class Lexer { public: Lexer(StringRef S) : Buf(S) {} diff --git a/contrib/llvm-project/llvm/lib/Object/ELF.cpp b/contrib/llvm-project/llvm/lib/Object/ELF.cpp index ca2ed4449120..84181ae5e501 100644 --- a/contrib/llvm-project/llvm/lib/Object/ELF.cpp +++ b/contrib/llvm-project/llvm/lib/Object/ELF.cpp @@ -246,6 +246,9 @@ StringRef llvm::object::getELFSectionTypeName(uint32_t Machine, unsigned Type) { STRINGIFY_ENUM_CASE(ELF, SHT_MIPS_ABIFLAGS); } break; + case ELF::EM_MSP430: + switch (Type) { STRINGIFY_ENUM_CASE(ELF, SHT_MSP430_ATTRIBUTES); } + break; case ELF::EM_RISCV: switch (Type) { STRINGIFY_ENUM_CASE(ELF, SHT_RISCV_ATTRIBUTES); } break; @@ -333,40 +336,26 @@ ELFFile<ELFT>::decode_relrs(Elf_Relr_Range relrs) const { std::vector<Elf_Rel> Relocs; // Word type: uint32_t for Elf32, and uint64_t for Elf64. - typedef typename ELFT::uint Word; - - // Word size in number of bytes. - const size_t WordSize = sizeof(Word); + using Addr = typename ELFT::uint; - // Number of bits used for the relocation offsets bitmap. - // These many relative relocations can be encoded in a single entry. - const size_t NBits = 8*WordSize - 1; - - Word Base = 0; - for (const Elf_Relr &R : relrs) { - Word Entry = R; - if ((Entry&1) == 0) { + Addr Base = 0; + for (Elf_Relr R : relrs) { + typename ELFT::uint Entry = R; + if ((Entry & 1) == 0) { // Even entry: encodes the offset for next relocation. Rel.r_offset = Entry; Relocs.push_back(Rel); // Set base offset for subsequent bitmap entries. - Base = Entry + WordSize; - continue; - } - - // Odd entry: encodes bitmap for relocations starting at base. - Word Offset = Base; - while (Entry != 0) { - Entry >>= 1; - if ((Entry&1) != 0) { - Rel.r_offset = Offset; - Relocs.push_back(Rel); - } - Offset += WordSize; + Base = Entry + sizeof(Addr); + } else { + // Odd entry: encodes bitmap for relocations starting at base. + for (Addr Offset = Base; (Entry >>= 1) != 0; Offset += sizeof(Addr)) + if ((Entry & 1) != 0) { + Rel.r_offset = Offset; + Relocs.push_back(Rel); + } + Base += (CHAR_BIT * sizeof(Entry) - 1) * sizeof(Addr); } - - // Advance base offset by NBits words. - Base += NBits * WordSize; } return Relocs; @@ -474,6 +463,14 @@ std::string ELFFile<ELFT>::getDynamicTagAsString(unsigned Arch, } break; + case ELF::EM_PPC: + switch (Type) { +#define PPC_DYNAMIC_TAG(name, value) DYNAMIC_STRINGIFY_ENUM(name, value) +#include "llvm/BinaryFormat/DynamicTags.def" +#undef PPC_DYNAMIC_TAG + } + break; + case ELF::EM_PPC64: switch (Type) { #define PPC64_DYNAMIC_TAG(name, value) DYNAMIC_STRINGIFY_ENUM(name, value) @@ -481,6 +478,14 @@ std::string ELFFile<ELFT>::getDynamicTagAsString(unsigned Arch, #undef PPC64_DYNAMIC_TAG } break; + + case ELF::EM_RISCV: + switch (Type) { +#define RISCV_DYNAMIC_TAG(name, value) DYNAMIC_STRINGIFY_ENUM(name, value) +#include "llvm/BinaryFormat/DynamicTags.def" +#undef RISCV_DYNAMIC_TAG + } + break; } #undef DYNAMIC_TAG switch (Type) { @@ -488,7 +493,9 @@ std::string ELFFile<ELFT>::getDynamicTagAsString(unsigned Arch, #define AARCH64_DYNAMIC_TAG(name, value) #define MIPS_DYNAMIC_TAG(name, value) #define HEXAGON_DYNAMIC_TAG(name, value) +#define PPC_DYNAMIC_TAG(name, value) #define PPC64_DYNAMIC_TAG(name, value) +#define RISCV_DYNAMIC_TAG(name, value) // Also ignore marker tags such as DT_HIOS (maps to DT_VERNEEDNUM), etc. #define DYNAMIC_TAG_MARKER(name, value) #define DYNAMIC_TAG(name, value) case value: return #name; @@ -497,7 +504,9 @@ std::string ELFFile<ELFT>::getDynamicTagAsString(unsigned Arch, #undef AARCH64_DYNAMIC_TAG #undef MIPS_DYNAMIC_TAG #undef HEXAGON_DYNAMIC_TAG +#undef PPC_DYNAMIC_TAG #undef PPC64_DYNAMIC_TAG +#undef RISCV_DYNAMIC_TAG #undef DYNAMIC_TAG_MARKER #undef DYNAMIC_STRINGIFY_ENUM default: @@ -613,14 +622,14 @@ ELFFile<ELFT>::toMappedAddr(uint64_t VAddr, WarningHandler WarnHandler) const { } template <class ELFT> -Expected<std::vector<typename ELFT::BBAddrMap>> +Expected<std::vector<BBAddrMap>> ELFFile<ELFT>::decodeBBAddrMap(const Elf_Shdr &Sec) const { Expected<ArrayRef<uint8_t>> ContentsOrErr = getSectionContents(Sec); if (!ContentsOrErr) return ContentsOrErr.takeError(); ArrayRef<uint8_t> Content = *ContentsOrErr; DataExtractor Data(Content, isLE(), ELFT::Is64Bits ? 8 : 4); - std::vector<Elf_BBAddrMap> FunctionEntries; + std::vector<BBAddrMap> FunctionEntries; DataExtractor::Cursor Cur(0); Error ULEBSizeErr = Error::success(); @@ -647,7 +656,7 @@ ELFFile<ELFT>::decodeBBAddrMap(const Elf_Shdr &Sec) const { while (!ULEBSizeErr && Cur && Cur.tell() < Content.size()) { uintX_t Address = static_cast<uintX_t>(Data.getAddress(Cur)); uint32_t NumBlocks = ReadULEB128AsUInt32(); - std::vector<typename Elf_BBAddrMap::BBEntry> BBEntries; + std::vector<BBAddrMap::BBEntry> BBEntries; for (uint32_t BlockID = 0; !ULEBSizeErr && Cur && (BlockID < NumBlocks); ++BlockID) { uint32_t Offset = ReadULEB128AsUInt32(); diff --git a/contrib/llvm-project/llvm/lib/Object/ELFObjectFile.cpp b/contrib/llvm-project/llvm/lib/Object/ELFObjectFile.cpp index 6613d79ab3d0..50035d6c7523 100644 --- a/contrib/llvm-project/llvm/lib/Object/ELFObjectFile.cpp +++ b/contrib/llvm-project/llvm/lib/Object/ELFObjectFile.cpp @@ -15,6 +15,7 @@ #include "llvm/BinaryFormat/ELF.h" #include "llvm/MC/MCInstrAnalysis.h" #include "llvm/MC/SubtargetFeature.h" +#include "llvm/MC/TargetRegistry.h" #include "llvm/Object/ELF.h" #include "llvm/Object/ELFTypes.h" #include "llvm/Object/Error.h" @@ -25,7 +26,6 @@ #include "llvm/Support/MathExtras.h" #include "llvm/Support/RISCVAttributeParser.h" #include "llvm/Support/RISCVAttributes.h" -#include "llvm/Support/TargetRegistry.h" #include <algorithm> #include <cstddef> #include <cstdint> @@ -538,9 +538,16 @@ void ELFObjectFileBase::setARMSubArch(Triple &TheTriple) const { case ARMBuildAttrs::v6K: Triple += "v6k"; break; - case ARMBuildAttrs::v7: - Triple += "v7"; + case ARMBuildAttrs::v7: { + Optional<unsigned> ArchProfileAttr = + Attributes.getAttributeValue(ARMBuildAttrs::CPU_arch_profile); + if (ArchProfileAttr.hasValue() && + ArchProfileAttr.getValue() == ARMBuildAttrs::MicroControllerProfile) + Triple += "v7m"; + else + Triple += "v7"; break; + } case ARMBuildAttrs::v6_M: Triple += "v6m"; break; @@ -647,3 +654,72 @@ ELFObjectFileBase::getPltAddresses() const { } return Result; } + +template <class ELFT> +static Expected<std::vector<VersionEntry>> +readDynsymVersionsImpl(const ELFFile<ELFT> &EF, + ELFObjectFileBase::elf_symbol_iterator_range Symbols) { + using Elf_Shdr = typename ELFT::Shdr; + const Elf_Shdr *VerSec = nullptr; + const Elf_Shdr *VerNeedSec = nullptr; + const Elf_Shdr *VerDefSec = nullptr; + // The user should ensure sections() can't fail here. + for (const Elf_Shdr &Sec : cantFail(EF.sections())) { + if (Sec.sh_type == ELF::SHT_GNU_versym) + VerSec = &Sec; + else if (Sec.sh_type == ELF::SHT_GNU_verdef) + VerDefSec = &Sec; + else if (Sec.sh_type == ELF::SHT_GNU_verneed) + VerNeedSec = &Sec; + } + if (!VerSec) + return std::vector<VersionEntry>(); + + Expected<SmallVector<Optional<VersionEntry>, 0>> MapOrErr = + EF.loadVersionMap(VerNeedSec, VerDefSec); + if (!MapOrErr) + return MapOrErr.takeError(); + + std::vector<VersionEntry> Ret; + size_t I = 0; + for (auto It = Symbols.begin(), E = Symbols.end(); It != E; ++It) { + ++I; + Expected<const typename ELFT::Versym *> VerEntryOrErr = + EF.template getEntry<typename ELFT::Versym>(*VerSec, I); + if (!VerEntryOrErr) + return createError("unable to read an entry with index " + Twine(I) + + " from " + describe(EF, *VerSec) + ": " + + toString(VerEntryOrErr.takeError())); + + Expected<uint32_t> FlagsOrErr = It->getFlags(); + if (!FlagsOrErr) + return createError("unable to read flags for symbol with index " + + Twine(I) + ": " + toString(FlagsOrErr.takeError())); + + bool IsDefault; + Expected<StringRef> VerOrErr = EF.getSymbolVersionByIndex( + (*VerEntryOrErr)->vs_index, IsDefault, *MapOrErr, + (*FlagsOrErr) & SymbolRef::SF_Undefined); + if (!VerOrErr) + return createError("unable to get a version for entry " + Twine(I) + + " of " + describe(EF, *VerSec) + ": " + + toString(VerOrErr.takeError())); + + Ret.push_back({(*VerOrErr).str(), IsDefault}); + } + + return Ret; +} + +Expected<std::vector<VersionEntry>> +ELFObjectFileBase::readDynsymVersions() const { + elf_symbol_iterator_range Symbols = getDynamicSymbolIterators(); + if (const auto *Obj = dyn_cast<ELF32LEObjectFile>(this)) + return readDynsymVersionsImpl(Obj->getELFFile(), Symbols); + if (const auto *Obj = dyn_cast<ELF32BEObjectFile>(this)) + return readDynsymVersionsImpl(Obj->getELFFile(), Symbols); + if (const auto *Obj = dyn_cast<ELF64LEObjectFile>(this)) + return readDynsymVersionsImpl(Obj->getELFFile(), Symbols); + return readDynsymVersionsImpl(cast<ELF64BEObjectFile>(this)->getELFFile(), + Symbols); +} diff --git a/contrib/llvm-project/llvm/lib/Object/IRObjectFile.cpp b/contrib/llvm-project/llvm/lib/Object/IRObjectFile.cpp index befba5d57127..c653262791cc 100644 --- a/contrib/llvm-project/llvm/lib/Object/IRObjectFile.cpp +++ b/contrib/llvm-project/llvm/lib/Object/IRObjectFile.cpp @@ -18,9 +18,9 @@ #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Mangler.h" #include "llvm/IR/Module.h" +#include "llvm/MC/TargetRegistry.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/TargetRegistry.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; using namespace object; diff --git a/contrib/llvm-project/llvm/lib/Object/IRSymtab.cpp b/contrib/llvm-project/llvm/lib/Object/IRSymtab.cpp index 746b00867157..093ae1bbc267 100644 --- a/contrib/llvm-project/llvm/lib/Object/IRSymtab.cpp +++ b/contrib/llvm-project/llvm/lib/Object/IRSymtab.cpp @@ -41,10 +41,15 @@ using namespace llvm; using namespace irsymtab; -static const char *LibcallRoutineNames[] = { +static const char *PreservedSymbols[] = { #define HANDLE_LIBCALL(code, name) name, #include "llvm/IR/RuntimeLibcalls.def" #undef HANDLE_LIBCALL + // There are global variables, so put it here instead of in + // RuntimeLibcalls.def. + // TODO: Are there similar such variables? + "__ssp_canary_word", + "__stack_chk_guard", }; namespace { @@ -261,9 +266,9 @@ Error Builder::addSymbol(const ModuleSymbolTable &Msymtab, setStr(Sym.IRName, GV->getName()); - bool IsBuiltinFunc = llvm::is_contained(LibcallRoutineNames, GV->getName()); + bool IsPreservedSymbol = llvm::is_contained(PreservedSymbols, GV->getName()); - if (Used.count(GV) || IsBuiltinFunc) + if (Used.count(GV) || IsPreservedSymbol) Sym.Flags |= 1 << storage::Symbol::FB_used; if (GV->isThreadLocal()) Sym.Flags |= 1 << storage::Symbol::FB_tls; @@ -283,11 +288,15 @@ Error Builder::addSymbol(const ModuleSymbolTable &Msymtab, Uncommon().CommonAlign = GVar->getAlignment(); } - const GlobalObject *Base = GV->getBaseObject(); - if (!Base) - return make_error<StringError>("Unable to determine comdat of alias!", - inconvertibleErrorCode()); - if (const Comdat *C = Base->getComdat()) { + const GlobalObject *GO = GV->getAliaseeObject(); + if (!GO) { + if (isa<GlobalIFunc>(GV)) + GO = cast<GlobalIFunc>(GV)->getResolverFunction(); + if (!GO) + return make_error<StringError>("Unable to determine comdat of alias!", + inconvertibleErrorCode()); + } + if (const Comdat *C = GO->getComdat()) { Expected<int> ComdatIndexOrErr = getComdatIndex(C, GV->getParent()); if (!ComdatIndexOrErr) return ComdatIndexOrErr.takeError(); @@ -312,8 +321,8 @@ Error Builder::addSymbol(const ModuleSymbolTable &Msymtab, } } - if (!Base->getSection().empty()) - setStr(Uncommon().SectionName, Saver.save(Base->getSection())); + if (!GO->getSection().empty()) + setStr(Uncommon().SectionName, Saver.save(GO->getSection())); return Error::success(); } diff --git a/contrib/llvm-project/llvm/lib/Object/MachOObjectFile.cpp b/contrib/llvm-project/llvm/lib/Object/MachOObjectFile.cpp index 177314a9a790..7501661591f0 100644 --- a/contrib/llvm-project/llvm/lib/Object/MachOObjectFile.cpp +++ b/contrib/llvm-project/llvm/lib/Object/MachOObjectFile.cpp @@ -246,8 +246,8 @@ static Error checkOverlappingElement(std::list<MachOElement> &Elements, if (Size == 0) return Error::success(); - for (auto it=Elements.begin() ; it != Elements.end(); ++it) { - auto E = *it; + for (auto it = Elements.begin(); it != Elements.end(); ++it) { + const auto &E = *it; if ((Offset >= E.Offset && Offset < E.Offset + E.Size) || (Offset + Size > E.Offset && Offset + Size < E.Offset + E.Size) || (Offset <= E.Offset && Offset + Size >= E.Offset + E.Size)) @@ -258,7 +258,7 @@ static Error checkOverlappingElement(std::list<MachOElement> &Elements, auto nt = it; nt++; if (nt != Elements.end()) { - auto N = *nt; + const auto &N = *nt; if (Offset + Size <= N.Offset) { Elements.insert(nt, {Offset, Size, Name}); return Error::success(); @@ -2048,6 +2048,46 @@ bool MachOObjectFile::isDebugSection(DataRefImpl Sec) const { SectionName == "__swift_ast"; } +namespace { +template <typename LoadCommandType> +ArrayRef<uint8_t> getSegmentContents(const MachOObjectFile &Obj, + MachOObjectFile::LoadCommandInfo LoadCmd, + StringRef SegmentName) { + auto SegmentOrErr = getStructOrErr<LoadCommandType>(Obj, LoadCmd.Ptr); + if (!SegmentOrErr) { + consumeError(SegmentOrErr.takeError()); + return {}; + } + auto &Segment = SegmentOrErr.get(); + if (StringRef(Segment.segname, 16).startswith(SegmentName)) + return arrayRefFromStringRef(Obj.getData().slice( + Segment.fileoff, Segment.fileoff + Segment.filesize)); + return {}; +} +} // namespace + +ArrayRef<uint8_t> +MachOObjectFile::getSegmentContents(StringRef SegmentName) const { + for (auto LoadCmd : load_commands()) { + ArrayRef<uint8_t> Contents; + switch (LoadCmd.C.cmd) { + case MachO::LC_SEGMENT: + Contents = ::getSegmentContents<MachO::segment_command>(*this, LoadCmd, + SegmentName); + break; + case MachO::LC_SEGMENT_64: + Contents = ::getSegmentContents<MachO::segment_command_64>(*this, LoadCmd, + SegmentName); + break; + default: + continue; + } + if (!Contents.empty()) + return Contents; + } + return {}; +} + unsigned MachOObjectFile::getSectionID(SectionRef Sec) const { return Sec.getRawDataRefImpl().d.a; } diff --git a/contrib/llvm-project/llvm/lib/Object/ModuleSymbolTable.cpp b/contrib/llvm-project/llvm/lib/Object/ModuleSymbolTable.cpp index 9a79de77af16..954d1f09f4e9 100644 --- a/contrib/llvm-project/llvm/lib/Object/ModuleSymbolTable.cpp +++ b/contrib/llvm-project/llvm/lib/Object/ModuleSymbolTable.cpp @@ -36,6 +36,7 @@ #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/MC/MCSymbol.h" #include "llvm/MC/MCTargetOptions.h" +#include "llvm/MC/TargetRegistry.h" #include "llvm/Object/SymbolicFile.h" #include "llvm/Support/Casting.h" #include "llvm/Support/CodeGen.h" @@ -43,7 +44,6 @@ #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/SMLoc.h" #include "llvm/Support/SourceMgr.h" -#include "llvm/Support/TargetRegistry.h" #include "llvm/Support/raw_ostream.h" #include <algorithm> #include <cassert> @@ -204,8 +204,9 @@ uint32_t ModuleSymbolTable::getSymbolFlags(Symbol S) const { if (GVar->isConstant()) Res |= BasicSymbolRef::SF_Const; } - if (dyn_cast_or_null<Function>(GV->getBaseObject())) - Res |= BasicSymbolRef::SF_Executable; + if (const GlobalObject *GO = GV->getAliaseeObject()) + if (isa<Function>(GO) || isa<GlobalIFunc>(GO)) + Res |= BasicSymbolRef::SF_Executable; if (isa<GlobalAlias>(GV)) Res |= BasicSymbolRef::SF_Indirect; if (GV->hasPrivateLinkage()) diff --git a/contrib/llvm-project/llvm/lib/Object/Object.cpp b/contrib/llvm-project/llvm/lib/Object/Object.cpp index b486e9f5c9a8..0659cf6a2d41 100644 --- a/contrib/llvm-project/llvm/lib/Object/Object.cpp +++ b/contrib/llvm-project/llvm/lib/Object/Object.cpp @@ -222,8 +222,7 @@ void LLVMMoveToContainingSection(LLVMSectionIteratorRef Sect, std::string Buf; raw_string_ostream OS(Buf); logAllUnhandledErrors(SecOrErr.takeError(), OS); - OS.flush(); - report_fatal_error(Buf); + report_fatal_error(Twine(OS.str())); } *unwrap(Sect) = *SecOrErr; } @@ -304,8 +303,7 @@ const char *LLVMGetSymbolName(LLVMSymbolIteratorRef SI) { std::string Buf; raw_string_ostream OS(Buf); logAllUnhandledErrors(Ret.takeError(), OS); - OS.flush(); - report_fatal_error(Buf); + report_fatal_error(Twine(OS.str())); } return Ret->data(); } @@ -316,8 +314,7 @@ uint64_t LLVMGetSymbolAddress(LLVMSymbolIteratorRef SI) { std::string Buf; raw_string_ostream OS(Buf); logAllUnhandledErrors(Ret.takeError(), OS); - OS.flush(); - report_fatal_error(Buf); + report_fatal_error(Twine(OS.str())); } return *Ret; } diff --git a/contrib/llvm-project/llvm/lib/Object/ObjectFile.cpp b/contrib/llvm-project/llvm/lib/Object/ObjectFile.cpp index 5c894439ff67..6fd02f3b9592 100644 --- a/contrib/llvm-project/llvm/lib/Object/ObjectFile.cpp +++ b/contrib/llvm-project/llvm/lib/Object/ObjectFile.cpp @@ -55,14 +55,15 @@ bool SectionRef::containsSymbol(SymbolRef S) const { } Expected<uint64_t> ObjectFile::getSymbolValue(DataRefImpl Ref) const { - if (Expected<uint32_t> FlagsOrErr = getSymbolFlags(Ref)) { - if (*FlagsOrErr & SymbolRef::SF_Undefined) - return 0; - if (*FlagsOrErr & SymbolRef::SF_Common) - return getCommonSymbolSize(Ref); - } else + uint32_t Flags; + if (Error E = getSymbolFlags(Ref).moveInto(Flags)) // TODO: Test this error. - return FlagsOrErr.takeError(); + return std::move(E); + + if (Flags & SymbolRef::SF_Undefined) + return 0; + if (Flags & SymbolRef::SF_Common) + return getCommonSymbolSize(Ref); return getSymbolValueImpl(Ref); } diff --git a/contrib/llvm-project/llvm/lib/Object/RelocationResolver.cpp b/contrib/llvm-project/llvm/lib/Object/RelocationResolver.cpp index ab98a2dd2ac1..00a45e2c5d4e 100644 --- a/contrib/llvm-project/llvm/lib/Object/RelocationResolver.cpp +++ b/contrib/llvm-project/llvm/lib/Object/RelocationResolver.cpp @@ -18,7 +18,7 @@ namespace object { static int64_t getELFAddend(RelocationRef R) { Expected<int64_t> AddendOrErr = ELFRelocationRef(R).getAddend(); handleAllErrors(AddendOrErr.takeError(), [](const ErrorInfoBase &EI) { - report_fatal_error(EI.message()); + report_fatal_error(Twine(EI.message())); }); return *AddendOrErr; } diff --git a/contrib/llvm-project/llvm/lib/Object/WasmObjectFile.cpp b/contrib/llvm-project/llvm/lib/Object/WasmObjectFile.cpp index a08c648358c0..6a19b159f3d5 100644 --- a/contrib/llvm-project/llvm/lib/Object/WasmObjectFile.cpp +++ b/contrib/llvm-project/llvm/lib/Object/WasmObjectFile.cpp @@ -286,9 +286,9 @@ WasmObjectFile::WasmObjectFile(MemoryBufferRef Buffer, Error &Err) return; } - WasmSection Sec; WasmSectionOrderChecker Checker; while (Ctx.Ptr < Ctx.End) { + WasmSection Sec; if ((Err = readSection(Sec, Ctx, Checker))) return; if ((Err = parseSection(Sec))) @@ -339,7 +339,8 @@ Error WasmObjectFile::parseSection(WasmSection &Sec) { } Error WasmObjectFile::parseDylinkSection(ReadContext &Ctx) { - // See https://github.com/WebAssembly/tool-conventions/blob/master/DynamicLinking.md + // Legacy "dylink" section support. + // See parseDylink0Section for the current "dylink.0" section parsing. HasDylinkSection = true; DylinkInfo.MemorySize = readVaruint32(Ctx); DylinkInfo.MemoryAlignment = readVaruint32(Ctx); @@ -349,17 +350,77 @@ Error WasmObjectFile::parseDylinkSection(ReadContext &Ctx) { while (Count--) { DylinkInfo.Needed.push_back(readString(Ctx)); } + if (Ctx.Ptr != Ctx.End) return make_error<GenericBinaryError>("dylink section ended prematurely", object_error::parse_failed); return Error::success(); } +Error WasmObjectFile::parseDylink0Section(ReadContext &Ctx) { + // See + // https://github.com/WebAssembly/tool-conventions/blob/main/DynamicLinking.md + HasDylinkSection = true; + + const uint8_t *OrigEnd = Ctx.End; + while (Ctx.Ptr < OrigEnd) { + Ctx.End = OrigEnd; + uint8_t Type = readUint8(Ctx); + uint32_t Size = readVaruint32(Ctx); + LLVM_DEBUG(dbgs() << "readSubsection type=" << int(Type) << " size=" << Size + << "\n"); + Ctx.End = Ctx.Ptr + Size; + uint32_t Count; + switch (Type) { + case wasm::WASM_DYLINK_MEM_INFO: + DylinkInfo.MemorySize = readVaruint32(Ctx); + DylinkInfo.MemoryAlignment = readVaruint32(Ctx); + DylinkInfo.TableSize = readVaruint32(Ctx); + DylinkInfo.TableAlignment = readVaruint32(Ctx); + break; + case wasm::WASM_DYLINK_NEEDED: + Count = readVaruint32(Ctx); + while (Count--) { + DylinkInfo.Needed.push_back(readString(Ctx)); + } + break; + case wasm::WASM_DYLINK_EXPORT_INFO: { + uint32_t Count = readVaruint32(Ctx); + while (Count--) { + DylinkInfo.ExportInfo.push_back({readString(Ctx), readVaruint32(Ctx)}); + } + break; + } + case wasm::WASM_DYLINK_IMPORT_INFO: { + uint32_t Count = readVaruint32(Ctx); + while (Count--) { + DylinkInfo.ImportInfo.push_back( + {readString(Ctx), readString(Ctx), readVaruint32(Ctx)}); + } + break; + } + default: + LLVM_DEBUG(dbgs() << "unknown dylink.0 sub-section: " << Type << "\n"); + Ctx.Ptr += Size; + break; + } + if (Ctx.Ptr != Ctx.End) { + return make_error<GenericBinaryError>( + "dylink.0 sub-section ended prematurely", object_error::parse_failed); + } + } + + if (Ctx.Ptr != Ctx.End) + return make_error<GenericBinaryError>("dylink.0 section ended prematurely", + object_error::parse_failed); + return Error::success(); +} + Error WasmObjectFile::parseNameSection(ReadContext &Ctx) { llvm::DenseSet<uint64_t> SeenFunctions; llvm::DenseSet<uint64_t> SeenGlobals; llvm::DenseSet<uint64_t> SeenSegments; - if (FunctionTypes.size() && !SeenCodeSection) { + if (Functions.size() && !SeenCodeSection) { return make_error<GenericBinaryError>("names must come after code section", object_error::parse_failed); } @@ -427,7 +488,7 @@ Error WasmObjectFile::parseNameSection(ReadContext &Ctx) { Error WasmObjectFile::parseLinkingSection(ReadContext &Ctx) { HasLinkingSection = true; - if (FunctionTypes.size() && !SeenCodeSection) { + if (Functions.size() && !SeenCodeSection) { return make_error<GenericBinaryError>( "linking data must come after code section", object_error::parse_failed); @@ -529,7 +590,6 @@ Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) { const wasm::WasmSignature *Signature = nullptr; const wasm::WasmGlobalType *GlobalType = nullptr; const wasm::WasmTableType *TableType = nullptr; - const wasm::WasmTagType *TagType = nullptr; Info.Kind = readUint8(Ctx); Info.Flags = readVaruint32(Ctx); @@ -545,8 +605,8 @@ Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) { if (IsDefined) { Info.Name = readString(Ctx); unsigned FuncIndex = Info.ElementIndex - NumImportedFunctions; - Signature = &Signatures[FunctionTypes[FuncIndex]]; wasm::WasmFunction &Function = Functions[FuncIndex]; + Signature = &Signatures[Function.SigIndex]; if (Function.SymbolName.empty()) Function.SymbolName = Info.Name; } else { @@ -674,8 +734,7 @@ Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) { Info.Name = readString(Ctx); unsigned TagIndex = Info.ElementIndex - NumImportedTags; wasm::WasmTag &Tag = Tags[TagIndex]; - Signature = &Signatures[Tag.Type.SigIndex]; - TagType = &Tag.Type; + Signature = &Signatures[Tag.SigIndex]; if (Tag.SymbolName.empty()) Tag.SymbolName = Info.Name; @@ -687,8 +746,7 @@ Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) { } else { Info.Name = Import.Field; } - TagType = &Import.Tag; - Signature = &Signatures[TagType->SigIndex]; + Signature = &Signatures[Import.SigIndex]; if (!Import.Module.empty()) { Info.ImportModule = Import.Module; } @@ -710,7 +768,7 @@ Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) { object_error::parse_failed); LinkingData.SymbolTable.emplace_back(Info); Symbols.emplace_back(LinkingData.SymbolTable.back(), GlobalType, TableType, - TagType, Signature); + Signature); LLVM_DEBUG(dbgs() << "Adding symbol: " << Symbols.back() << "\n"); } @@ -984,6 +1042,9 @@ Error WasmObjectFile::parseCustomSection(WasmSection &Sec, ReadContext &Ctx) { if (Sec.Name == "dylink") { if (Error Err = parseDylinkSection(Ctx)) return Err; + } else if (Sec.Name == "dylink.0") { + if (Error Err = parseDylink0Section(Ctx)) + return Err; } else if (Sec.Name == "name") { if (Error Err = parseNameSection(Ctx)) return Err; @@ -1034,6 +1095,7 @@ Error WasmObjectFile::parseTypeSection(ReadContext &Ctx) { Error WasmObjectFile::parseImportSection(ReadContext &Ctx) { uint32_t Count = readVaruint32(Ctx); + uint32_t NumTypes = Signatures.size(); Imports.reserve(Count); for (uint32_t I = 0; I < Count; I++) { wasm::WasmImport Im; @@ -1044,6 +1106,9 @@ Error WasmObjectFile::parseImportSection(ReadContext &Ctx) { case wasm::WASM_EXTERNAL_FUNCTION: NumImportedFunctions++; Im.SigIndex = readVaruint32(Ctx); + if (Im.SigIndex >= NumTypes) + return make_error<GenericBinaryError>("invalid function type", + object_error::parse_failed); break; case wasm::WASM_EXTERNAL_GLOBAL: NumImportedGlobals++; @@ -1067,8 +1132,13 @@ Error WasmObjectFile::parseImportSection(ReadContext &Ctx) { } case wasm::WASM_EXTERNAL_TAG: NumImportedTags++; - Im.Tag.Attribute = readUint8(Ctx); - Im.Tag.SigIndex = readVarint32(Ctx); + if (readUint8(Ctx) != 0) // Reserved 'attribute' field + return make_error<GenericBinaryError>("invalid attribute", + object_error::parse_failed); + Im.SigIndex = readVaruint32(Ctx); + if (Im.SigIndex >= NumTypes) + return make_error<GenericBinaryError>("invalid tag type", + object_error::parse_failed); break; default: return make_error<GenericBinaryError>("unexpected import kind", @@ -1084,15 +1154,16 @@ Error WasmObjectFile::parseImportSection(ReadContext &Ctx) { Error WasmObjectFile::parseFunctionSection(ReadContext &Ctx) { uint32_t Count = readVaruint32(Ctx); - FunctionTypes.reserve(Count); - Functions.resize(Count); + Functions.reserve(Count); uint32_t NumTypes = Signatures.size(); while (Count--) { uint32_t Type = readVaruint32(Ctx); if (Type >= NumTypes) return make_error<GenericBinaryError>("invalid function type", object_error::parse_failed); - FunctionTypes.push_back(Type); + wasm::WasmFunction F; + F.SigIndex = Type; + Functions.push_back(F); } if (Ctx.Ptr != Ctx.End) return make_error<GenericBinaryError>("function section ended prematurely", @@ -1141,11 +1212,18 @@ Error WasmObjectFile::parseTagSection(ReadContext &Ctx) { TagSection = Sections.size(); uint32_t Count = readVaruint32(Ctx); Tags.reserve(Count); + uint32_t NumTypes = Signatures.size(); while (Count--) { + if (readUint8(Ctx) != 0) // Reserved 'attribute' field + return make_error<GenericBinaryError>("invalid attribute", + object_error::parse_failed); + uint32_t Type = readVaruint32(Ctx); + if (Type >= NumTypes) + return make_error<GenericBinaryError>("invalid tag type", + object_error::parse_failed); wasm::WasmTag Tag; Tag.Index = NumImportedTags + Tags.size(); - Tag.Type.Attribute = readUint8(Ctx); - Tag.Type.SigIndex = readVaruint32(Ctx); + Tag.SigIndex = Type; Tags.push_back(Tag); } @@ -1216,7 +1294,7 @@ Error WasmObjectFile::parseExportSection(ReadContext &Ctx) { } bool WasmObjectFile::isValidFunctionIndex(uint32_t Index) const { - return Index < NumImportedFunctions + FunctionTypes.size(); + return Index < NumImportedFunctions + Functions.size(); } bool WasmObjectFile::isDefinedFunctionIndex(uint32_t Index) const { @@ -1304,7 +1382,7 @@ Error WasmObjectFile::parseCodeSection(ReadContext &Ctx) { SeenCodeSection = true; CodeSection = Sections.size(); uint32_t FunctionCount = readVaruint32(Ctx); - if (FunctionCount != FunctionTypes.size()) { + if (FunctionCount != Functions.size()) { return make_error<GenericBinaryError>("invalid function count", object_error::parse_failed); } @@ -1793,6 +1871,7 @@ int WasmSectionOrderChecker::getSectionOrder(unsigned ID, case wasm::WASM_SEC_CUSTOM: return StringSwitch<unsigned>(CustomSectionName) .Case("dylink", WASM_SEC_ORDER_DYLINK) + .Case("dylink.0", WASM_SEC_ORDER_DYLINK) .Case("linking", WASM_SEC_ORDER_LINKING) .StartsWith("reloc.", WASM_SEC_ORDER_RELOC) .Case("name", WASM_SEC_ORDER_NAME) diff --git a/contrib/llvm-project/llvm/lib/Object/XCOFFObjectFile.cpp b/contrib/llvm-project/llvm/lib/Object/XCOFFObjectFile.cpp index 53447d0c97b2..9b0a5efacba7 100644 --- a/contrib/llvm-project/llvm/lib/Object/XCOFFObjectFile.cpp +++ b/contrib/llvm-project/llvm/lib/Object/XCOFFObjectFile.cpp @@ -69,15 +69,18 @@ bool XCOFFSectionHeader<T>::isReservedSectionType() const { return getSectionType() & SectionFlagsReservedMask; } -bool XCOFFRelocation32::isRelocationSigned() const { +template <typename AddressType> +bool XCOFFRelocation<AddressType>::isRelocationSigned() const { return Info & XR_SIGN_INDICATOR_MASK; } -bool XCOFFRelocation32::isFixupIndicated() const { +template <typename AddressType> +bool XCOFFRelocation<AddressType>::isFixupIndicated() const { return Info & XR_FIXUP_INDICATOR_MASK; } -uint8_t XCOFFRelocation32::getRelocatedLength() const { +template <typename AddressType> +uint8_t XCOFFRelocation<AddressType>::getRelocatedLength() const { // The relocation encodes the bit length being relocated minus 1. Add back // the 1 to get the actual length being relocated. return (Info & XR_BIASED_LENGTH_MASK) + 1; @@ -146,6 +149,20 @@ const XCOFFFileHeader64 *XCOFFObjectFile::fileHeader64() const { return static_cast<const XCOFFFileHeader64 *>(FileHeader); } +const XCOFFAuxiliaryHeader32 *XCOFFObjectFile::auxiliaryHeader32() const { + assert(!is64Bit() && "32-bit interface called on 64-bit object file."); + return static_cast<const XCOFFAuxiliaryHeader32 *>(AuxiliaryHeader); +} + +const XCOFFAuxiliaryHeader64 *XCOFFObjectFile::auxiliaryHeader64() const { + assert(is64Bit() && "64-bit interface called on a 32-bit object file."); + return static_cast<const XCOFFAuxiliaryHeader64 *>(AuxiliaryHeader); +} + +template <typename T> const T *XCOFFObjectFile::sectionHeaderTable() const { + return static_cast<const T *>(SectionHeaderTable); +} + const XCOFFSectionHeader32 * XCOFFObjectFile::sectionHeaderTable32() const { assert(!is64Bit() && "32-bit interface called on 64-bit object file."); @@ -183,12 +200,16 @@ XCOFFObjectFile::getStringTableEntry(uint32_t Offset) const { if (StringTable.Data != nullptr && StringTable.Size > Offset) return (StringTable.Data + Offset); - return make_error<GenericBinaryError>("Bad offset for string table entry", - object_error::parse_failed); + return createError("entry with offset 0x" + Twine::utohexstr(Offset) + + " in a string table with size 0x" + + Twine::utohexstr(StringTable.Size) + " is invalid"); } StringRef XCOFFObjectFile::getStringTable() const { - return StringRef(StringTable.Data, StringTable.Size); + // If the size is less than or equal to 4, then the string table contains no + // string data. + return StringRef(StringTable.Data, + StringTable.Size <= 4 ? 0 : StringTable.Size); } Expected<StringRef> @@ -210,15 +231,85 @@ uint64_t XCOFFObjectFile::getSymbolValueImpl(DataRefImpl Symb) const { return toSymbolRef(Symb).getValue(); } +uint32_t XCOFFObjectFile::getSymbolAlignment(DataRefImpl Symb) const { + uint64_t Result = 0; + XCOFFSymbolRef XCOFFSym = toSymbolRef(Symb); + if (XCOFFSym.isCsectSymbol()) { + Expected<XCOFFCsectAuxRef> CsectAuxRefOrError = + XCOFFSym.getXCOFFCsectAuxRef(); + if (!CsectAuxRefOrError) + // TODO: report the error up the stack. + consumeError(CsectAuxRefOrError.takeError()); + else + Result = 1ULL << CsectAuxRefOrError.get().getAlignmentLog2(); + } + return Result; +} + uint64_t XCOFFObjectFile::getCommonSymbolSizeImpl(DataRefImpl Symb) const { uint64_t Result = 0; - llvm_unreachable("Not yet implemented!"); + XCOFFSymbolRef XCOFFSym = toSymbolRef(Symb); + if (XCOFFSym.isCsectSymbol()) { + Expected<XCOFFCsectAuxRef> CsectAuxRefOrError = + XCOFFSym.getXCOFFCsectAuxRef(); + if (!CsectAuxRefOrError) + // TODO: report the error up the stack. + consumeError(CsectAuxRefOrError.takeError()); + else { + XCOFFCsectAuxRef CsectAuxRef = CsectAuxRefOrError.get(); + assert(CsectAuxRef.getSymbolType() == XCOFF::XTY_CM); + Result = CsectAuxRef.getSectionOrLength(); + } + } return Result; } Expected<SymbolRef::Type> XCOFFObjectFile::getSymbolType(DataRefImpl Symb) const { - // TODO: Return the correct symbol type. + XCOFFSymbolRef XCOFFSym = toSymbolRef(Symb); + + if (XCOFFSym.isFunction()) + return SymbolRef::ST_Function; + + if (XCOFF::C_FILE == XCOFFSym.getStorageClass()) + return SymbolRef::ST_File; + + int16_t SecNum = XCOFFSym.getSectionNumber(); + if (SecNum <= 0) + return SymbolRef::ST_Other; + + Expected<DataRefImpl> SecDRIOrErr = + getSectionByNum(XCOFFSym.getSectionNumber()); + + if (!SecDRIOrErr) + return SecDRIOrErr.takeError(); + + DataRefImpl SecDRI = SecDRIOrErr.get(); + + Expected<StringRef> SymNameOrError = XCOFFSym.getName(); + if (SymNameOrError) { + // The "TOC" symbol is treated as SymbolRef::ST_Other. + if (SymNameOrError.get() == "TOC") + return SymbolRef::ST_Other; + + // The symbol for a section name is treated as SymbolRef::ST_Other. + StringRef SecName; + if (is64Bit()) + SecName = XCOFFObjectFile::toSection64(SecDRIOrErr.get())->getName(); + else + SecName = XCOFFObjectFile::toSection32(SecDRIOrErr.get())->getName(); + + if (SecName == SymNameOrError.get()) + return SymbolRef::ST_Other; + } else + return SymNameOrError.takeError(); + + if (isSectionData(SecDRI) || isSectionBSS(SecDRI)) + return SymbolRef::ST_Data; + + if (isDebugSection(SecDRI)) + return SymbolRef::ST_Debug; + return SymbolRef::ST_Other; } @@ -285,8 +376,12 @@ XCOFFObjectFile::getSectionContents(DataRefImpl Sec) const { const uint8_t * ContentStart = base() + OffsetToRaw; uint64_t SectionSize = getSectionSize(Sec); - if (checkOffset(Data, reinterpret_cast<uintptr_t>(ContentStart), SectionSize)) - return make_error<BinaryError>(); + if (Error E = Binary::checkOffset( + Data, reinterpret_cast<uintptr_t>(ContentStart), SectionSize)) + return createError( + toString(std::move(E)) + ": section data with offset 0x" + + Twine::utohexstr(OffsetToRaw) + " and size 0x" + + Twine::utohexstr(SectionSize) + " goes past the end of the file"); return makeArrayRef(ContentStart,SectionSize); } @@ -297,6 +392,43 @@ uint64_t XCOFFObjectFile::getSectionAlignment(DataRefImpl Sec) const { return Result; } +Expected<uintptr_t> XCOFFObjectFile::getLoaderSectionAddress() const { + uint64_t OffsetToLoaderSection = 0; + uint64_t SizeOfLoaderSection = 0; + + if (is64Bit()) { + for (const auto &Sec64 : sections64()) + if (Sec64.getSectionType() == XCOFF::STYP_LOADER) { + OffsetToLoaderSection = Sec64.FileOffsetToRawData; + SizeOfLoaderSection = Sec64.SectionSize; + break; + } + } else { + for (const auto &Sec32 : sections32()) + if (Sec32.getSectionType() == XCOFF::STYP_LOADER) { + OffsetToLoaderSection = Sec32.FileOffsetToRawData; + SizeOfLoaderSection = Sec32.SectionSize; + break; + } + } + + // No loader section is not an error. + if (!SizeOfLoaderSection) + return 0; + + uintptr_t LoderSectionStart = + reinterpret_cast<uintptr_t>(base() + OffsetToLoaderSection); + if (Error E = + Binary::checkOffset(Data, LoderSectionStart, SizeOfLoaderSection)) + return createError(toString(std::move(E)) + + ": loader section with offset 0x" + + Twine::utohexstr(OffsetToLoaderSection) + + " and size 0x" + Twine::utohexstr(SizeOfLoaderSection) + + " goes past the end of the file"); + + return LoderSectionStart; +} + bool XCOFFObjectFile::isSectionCompressed(DataRefImpl Sec) const { return false; } @@ -326,61 +458,112 @@ bool XCOFFObjectFile::isSectionVirtual(DataRefImpl Sec) const { } relocation_iterator XCOFFObjectFile::section_rel_begin(DataRefImpl Sec) const { - if (is64Bit()) - report_fatal_error("64-bit support not implemented yet"); - const XCOFFSectionHeader32 *SectionEntPtr = toSection32(Sec); - auto RelocationsOrErr = relocations(*SectionEntPtr); - if (Error E = RelocationsOrErr.takeError()) - return relocation_iterator(RelocationRef()); DataRefImpl Ret; - Ret.p = reinterpret_cast<uintptr_t>(&*RelocationsOrErr.get().begin()); + if (is64Bit()) { + const XCOFFSectionHeader64 *SectionEntPtr = toSection64(Sec); + auto RelocationsOrErr = + relocations<XCOFFSectionHeader64, XCOFFRelocation64>(*SectionEntPtr); + if (Error E = RelocationsOrErr.takeError()) { + // TODO: report the error up the stack. + consumeError(std::move(E)); + return relocation_iterator(RelocationRef()); + } + Ret.p = reinterpret_cast<uintptr_t>(&*RelocationsOrErr.get().begin()); + } else { + const XCOFFSectionHeader32 *SectionEntPtr = toSection32(Sec); + auto RelocationsOrErr = + relocations<XCOFFSectionHeader32, XCOFFRelocation32>(*SectionEntPtr); + if (Error E = RelocationsOrErr.takeError()) { + // TODO: report the error up the stack. + consumeError(std::move(E)); + return relocation_iterator(RelocationRef()); + } + Ret.p = reinterpret_cast<uintptr_t>(&*RelocationsOrErr.get().begin()); + } return relocation_iterator(RelocationRef(Ret, this)); } relocation_iterator XCOFFObjectFile::section_rel_end(DataRefImpl Sec) const { - if (is64Bit()) - report_fatal_error("64-bit support not implemented yet"); - const XCOFFSectionHeader32 *SectionEntPtr = toSection32(Sec); - auto RelocationsOrErr = relocations(*SectionEntPtr); - if (Error E = RelocationsOrErr.takeError()) - return relocation_iterator(RelocationRef()); DataRefImpl Ret; - Ret.p = reinterpret_cast<uintptr_t>(&*RelocationsOrErr.get().end()); + if (is64Bit()) { + const XCOFFSectionHeader64 *SectionEntPtr = toSection64(Sec); + auto RelocationsOrErr = + relocations<XCOFFSectionHeader64, XCOFFRelocation64>(*SectionEntPtr); + if (Error E = RelocationsOrErr.takeError()) { + // TODO: report the error up the stack. + consumeError(std::move(E)); + return relocation_iterator(RelocationRef()); + } + Ret.p = reinterpret_cast<uintptr_t>(&*RelocationsOrErr.get().end()); + } else { + const XCOFFSectionHeader32 *SectionEntPtr = toSection32(Sec); + auto RelocationsOrErr = + relocations<XCOFFSectionHeader32, XCOFFRelocation32>(*SectionEntPtr); + if (Error E = RelocationsOrErr.takeError()) { + // TODO: report the error up the stack. + consumeError(std::move(E)); + return relocation_iterator(RelocationRef()); + } + Ret.p = reinterpret_cast<uintptr_t>(&*RelocationsOrErr.get().end()); + } return relocation_iterator(RelocationRef(Ret, this)); } void XCOFFObjectFile::moveRelocationNext(DataRefImpl &Rel) const { - Rel.p = reinterpret_cast<uintptr_t>(viewAs<XCOFFRelocation32>(Rel.p) + 1); + if (is64Bit()) + Rel.p = reinterpret_cast<uintptr_t>(viewAs<XCOFFRelocation64>(Rel.p) + 1); + else + Rel.p = reinterpret_cast<uintptr_t>(viewAs<XCOFFRelocation32>(Rel.p) + 1); } uint64_t XCOFFObjectFile::getRelocationOffset(DataRefImpl Rel) const { - if (is64Bit()) - report_fatal_error("64-bit support not implemented yet"); - const XCOFFRelocation32 *Reloc = viewAs<XCOFFRelocation32>(Rel.p); - const XCOFFSectionHeader32 *Sec32 = sectionHeaderTable32(); - const uint32_t RelocAddress = Reloc->VirtualAddress; - const uint16_t NumberOfSections = getNumberOfSections(); - for (uint16_t i = 0; i < NumberOfSections; ++i) { - // Find which section this relocation is belonging to, and get the - // relocation offset relative to the start of the section. - if (Sec32->VirtualAddress <= RelocAddress && - RelocAddress < Sec32->VirtualAddress + Sec32->SectionSize) { - return RelocAddress - Sec32->VirtualAddress; + if (is64Bit()) { + const XCOFFRelocation64 *Reloc = viewAs<XCOFFRelocation64>(Rel.p); + const XCOFFSectionHeader64 *Sec64 = sectionHeaderTable64(); + const uint64_t RelocAddress = Reloc->VirtualAddress; + const uint16_t NumberOfSections = getNumberOfSections(); + for (uint16_t I = 0; I < NumberOfSections; ++I) { + // Find which section this relocation belongs to, and get the + // relocation offset relative to the start of the section. + if (Sec64->VirtualAddress <= RelocAddress && + RelocAddress < Sec64->VirtualAddress + Sec64->SectionSize) { + return RelocAddress - Sec64->VirtualAddress; + } + ++Sec64; + } + } else { + const XCOFFRelocation32 *Reloc = viewAs<XCOFFRelocation32>(Rel.p); + const XCOFFSectionHeader32 *Sec32 = sectionHeaderTable32(); + const uint32_t RelocAddress = Reloc->VirtualAddress; + const uint16_t NumberOfSections = getNumberOfSections(); + for (uint16_t I = 0; I < NumberOfSections; ++I) { + // Find which section this relocation belongs to, and get the + // relocation offset relative to the start of the section. + if (Sec32->VirtualAddress <= RelocAddress && + RelocAddress < Sec32->VirtualAddress + Sec32->SectionSize) { + return RelocAddress - Sec32->VirtualAddress; + } + ++Sec32; } - ++Sec32; } return InvalidRelocOffset; } symbol_iterator XCOFFObjectFile::getRelocationSymbol(DataRefImpl Rel) const { - if (is64Bit()) - report_fatal_error("64-bit support not implemented yet"); - const XCOFFRelocation32 *Reloc = viewAs<XCOFFRelocation32>(Rel.p); - const uint32_t Index = Reloc->SymbolIndex; - - if (Index >= getLogicalNumberOfSymbolTableEntries32()) - return symbol_end(); - + uint32_t Index; + if (is64Bit()) { + const XCOFFRelocation64 *Reloc = viewAs<XCOFFRelocation64>(Rel.p); + Index = Reloc->SymbolIndex; + + if (Index >= getNumberOfSymbolTableEntries64()) + return symbol_end(); + } else { + const XCOFFRelocation32 *Reloc = viewAs<XCOFFRelocation32>(Rel.p); + Index = Reloc->SymbolIndex; + + if (Index >= getLogicalNumberOfSymbolTableEntries32()) + return symbol_end(); + } DataRefImpl SymDRI; SymDRI.p = getSymbolEntryAddressByIndex(Index); return symbol_iterator(SymbolRef(SymDRI, this)); @@ -388,22 +571,50 @@ symbol_iterator XCOFFObjectFile::getRelocationSymbol(DataRefImpl Rel) const { uint64_t XCOFFObjectFile::getRelocationType(DataRefImpl Rel) const { if (is64Bit()) - report_fatal_error("64-bit support not implemented yet"); + return viewAs<XCOFFRelocation64>(Rel.p)->Type; return viewAs<XCOFFRelocation32>(Rel.p)->Type; } void XCOFFObjectFile::getRelocationTypeName( DataRefImpl Rel, SmallVectorImpl<char> &Result) const { - if (is64Bit()) - report_fatal_error("64-bit support not implemented yet"); - const XCOFFRelocation32 *Reloc = viewAs<XCOFFRelocation32>(Rel.p); - StringRef Res = XCOFF::getRelocationTypeString(Reloc->Type); + StringRef Res; + if (is64Bit()) { + const XCOFFRelocation64 *Reloc = viewAs<XCOFFRelocation64>(Rel.p); + Res = XCOFF::getRelocationTypeString(Reloc->Type); + } else { + const XCOFFRelocation32 *Reloc = viewAs<XCOFFRelocation32>(Rel.p); + Res = XCOFF::getRelocationTypeString(Reloc->Type); + } Result.append(Res.begin(), Res.end()); } Expected<uint32_t> XCOFFObjectFile::getSymbolFlags(DataRefImpl Symb) const { - uint32_t Result = 0; - // TODO: Return correct symbol flags. + XCOFFSymbolRef XCOFFSym = toSymbolRef(Symb); + uint32_t Result = SymbolRef::SF_None; + + if (XCOFFSym.getSectionNumber() == XCOFF::N_ABS) + Result |= SymbolRef::SF_Absolute; + + XCOFF::StorageClass SC = XCOFFSym.getStorageClass(); + if (XCOFF::C_EXT == SC || XCOFF::C_WEAKEXT == SC) + Result |= SymbolRef::SF_Global; + + if (XCOFF::C_WEAKEXT == SC) + Result |= SymbolRef::SF_Weak; + + if (XCOFFSym.isCsectSymbol()) { + Expected<XCOFFCsectAuxRef> CsectAuxEntOrErr = + XCOFFSym.getXCOFFCsectAuxRef(); + if (CsectAuxEntOrErr) { + if (CsectAuxEntOrErr.get().getSymbolType() == XCOFF::XTY_CM) + Result |= SymbolRef::SF_Common; + } else + return CsectAuxEntOrErr.takeError(); + } + + if (XCOFFSym.getSectionNumber() == XCOFF::N_UNDEF) + Result |= SymbolRef::SF_Undefined; + return Result; } @@ -494,7 +705,9 @@ uint16_t XCOFFObjectFile::getMagic() const { Expected<DataRefImpl> XCOFFObjectFile::getSectionByNum(int16_t Num) const { if (Num <= 0 || Num > getNumberOfSections()) - return errorCodeToError(object_error::invalid_section_index); + return createStringError(object_error::invalid_section_index, + "the section index (" + Twine(Num) + + ") is invalid"); DataRefImpl DRI; DRI.p = getWithOffset(getSectionHeaderTableAddress(), @@ -602,6 +815,25 @@ uint32_t XCOFFObjectFile::getSymbolIndex(uintptr_t SymbolEntPtr) const { XCOFF::SymbolTableEntrySize; } +uint64_t XCOFFObjectFile::getSymbolSize(DataRefImpl Symb) const { + uint64_t Result = 0; + XCOFFSymbolRef XCOFFSym = toSymbolRef(Symb); + if (XCOFFSym.isCsectSymbol()) { + Expected<XCOFFCsectAuxRef> CsectAuxRefOrError = + XCOFFSym.getXCOFFCsectAuxRef(); + if (!CsectAuxRefOrError) + // TODO: report the error up the stack. + consumeError(CsectAuxRefOrError.takeError()); + else { + XCOFFCsectAuxRef CsectAuxRef = CsectAuxRefOrError.get(); + uint8_t SymType = CsectAuxRef.getSymbolType(); + if (SymType == XCOFF::XTY_SD || SymType == XCOFF::XTY_CM) + Result = CsectAuxRef.getSectionOrLength(); + } + } + return Result; +} + uintptr_t XCOFFObjectFile::getSymbolEntryAddressByIndex(uint32_t Index) const { return getAdvancedSymbolEntryAddress( reinterpret_cast<uintptr_t>(getPointerToSymbolTable()), Index); @@ -612,7 +844,9 @@ XCOFFObjectFile::getSymbolNameByIndex(uint32_t Index) const { const uint32_t NumberOfSymTableEntries = getNumberOfSymbolTableEntries(); if (Index >= NumberOfSymTableEntries) - return errorCodeToError(object_error::invalid_symbol_index); + return createError("symbol index " + Twine(Index) + + " exceeds symbol count " + + Twine(NumberOfSymTableEntries)); DataRefImpl SymDRI; SymDRI.p = getSymbolEntryAddressByIndex(Index); @@ -658,13 +892,16 @@ ArrayRef<XCOFFSectionHeader32> XCOFFObjectFile::sections32() const { // section header contains the actual count of relocation entries in the s_paddr // field. STYP_OVRFLO headers contain the section index of their corresponding // sections as their raw "NumberOfRelocations" field value. -Expected<uint32_t> XCOFFObjectFile::getLogicalNumberOfRelocationEntries( - const XCOFFSectionHeader32 &Sec) const { - - uint16_t SectionIndex = &Sec - sectionHeaderTable32() + 1; +template <typename T> +Expected<uint32_t> XCOFFObjectFile::getNumberOfRelocationEntries( + const XCOFFSectionHeader<T> &Sec) const { + const T &Section = static_cast<const T &>(Sec); + if (is64Bit()) + return Section.NumberOfRelocations; - if (Sec.NumberOfRelocations < XCOFF::RelocOverflow) - return Sec.NumberOfRelocations; + uint16_t SectionIndex = &Section - sectionHeaderTable<T>() + 1; + if (Section.NumberOfRelocations < XCOFF::RelocOverflow) + return Section.NumberOfRelocations; for (const auto &Sec : sections32()) { if (Sec.Flags == XCOFF::STYP_OVRFLO && Sec.NumberOfRelocations == SectionIndex) @@ -673,27 +910,31 @@ Expected<uint32_t> XCOFFObjectFile::getLogicalNumberOfRelocationEntries( return errorCodeToError(object_error::parse_failed); } -Expected<ArrayRef<XCOFFRelocation32>> -XCOFFObjectFile::relocations(const XCOFFSectionHeader32 &Sec) const { +template <typename Shdr, typename Reloc> +Expected<ArrayRef<Reloc>> XCOFFObjectFile::relocations(const Shdr &Sec) const { uintptr_t RelocAddr = getWithOffset(reinterpret_cast<uintptr_t>(FileHeader), Sec.FileOffsetToRelocationInfo); - auto NumRelocEntriesOrErr = getLogicalNumberOfRelocationEntries(Sec); + auto NumRelocEntriesOrErr = getNumberOfRelocationEntries(Sec); if (Error E = NumRelocEntriesOrErr.takeError()) return std::move(E); uint32_t NumRelocEntries = NumRelocEntriesOrErr.get(); - - static_assert( - sizeof(XCOFFRelocation32) == XCOFF::RelocationSerializationSize32, ""); + static_assert((sizeof(Reloc) == XCOFF::RelocationSerializationSize64 || + sizeof(Reloc) == XCOFF::RelocationSerializationSize32), + "Relocation structure is incorrect"); auto RelocationOrErr = - getObject<XCOFFRelocation32>(Data, reinterpret_cast<void *>(RelocAddr), - NumRelocEntries * sizeof(XCOFFRelocation32)); - if (Error E = RelocationOrErr.takeError()) - return std::move(E); + getObject<Reloc>(Data, reinterpret_cast<void *>(RelocAddr), + NumRelocEntries * sizeof(Reloc)); + if (!RelocationOrErr) + return createError( + toString(RelocationOrErr.takeError()) + ": relocations with offset 0x" + + Twine::utohexstr(Sec.FileOffsetToRelocationInfo) + " and size 0x" + + Twine::utohexstr(NumRelocEntries * sizeof(Reloc)) + + " go past the end of the file"); - const XCOFFRelocation32 *StartReloc = RelocationOrErr.get(); + const Reloc *StartReloc = RelocationOrErr.get(); - return ArrayRef<XCOFFRelocation32>(StartReloc, StartReloc + NumRelocEntries); + return ArrayRef<Reloc>(StartReloc, StartReloc + NumRelocEntries); } Expected<XCOFFStringTable> @@ -716,8 +957,12 @@ XCOFFObjectFile::parseStringTable(const XCOFFObjectFile *Obj, uint64_t Offset) { auto StringTableOrErr = getObject<char>(Obj->Data, Obj->base() + Offset, Size); - if (Error E = StringTableOrErr.takeError()) - return std::move(E); + if (!StringTableOrErr) + return createError(toString(StringTableOrErr.takeError()) + + ": string table with offset 0x" + + Twine::utohexstr(Offset) + " and size 0x" + + Twine::utohexstr(Size) + + " goes past the end of the file"); const char *StringTablePtr = StringTableOrErr.get(); if (StringTablePtr[Size - 1] != '\0') @@ -726,6 +971,54 @@ XCOFFObjectFile::parseStringTable(const XCOFFObjectFile *Obj, uint64_t Offset) { return XCOFFStringTable{Size, StringTablePtr}; } +// This function returns the import file table. Each entry in the import file +// table consists of: "path_name\0base_name\0archive_member_name\0". +Expected<StringRef> XCOFFObjectFile::getImportFileTable() const { + Expected<uintptr_t> LoaderSectionAddrOrError = getLoaderSectionAddress(); + if (!LoaderSectionAddrOrError) + return LoaderSectionAddrOrError.takeError(); + + uintptr_t LoaderSectionAddr = LoaderSectionAddrOrError.get(); + if (!LoaderSectionAddr) + return StringRef(); + + uint64_t OffsetToImportFileTable = 0; + uint64_t LengthOfImportFileTable = 0; + if (is64Bit()) { + const LoaderSectionHeader64 *LoaderSec64 = + viewAs<LoaderSectionHeader64>(LoaderSectionAddr); + OffsetToImportFileTable = LoaderSec64->OffsetToImpid; + LengthOfImportFileTable = LoaderSec64->LengthOfImpidStrTbl; + } else { + const LoaderSectionHeader32 *LoaderSec32 = + viewAs<LoaderSectionHeader32>(LoaderSectionAddr); + OffsetToImportFileTable = LoaderSec32->OffsetToImpid; + LengthOfImportFileTable = LoaderSec32->LengthOfImpidStrTbl; + } + + auto ImportTableOrErr = getObject<char>( + Data, + reinterpret_cast<void *>(LoaderSectionAddr + OffsetToImportFileTable), + LengthOfImportFileTable); + if (!ImportTableOrErr) + return createError( + toString(ImportTableOrErr.takeError()) + + ": import file table with offset 0x" + + Twine::utohexstr(LoaderSectionAddr + OffsetToImportFileTable) + + " and size 0x" + Twine::utohexstr(LengthOfImportFileTable) + + " goes past the end of the file"); + + const char *ImportTablePtr = ImportTableOrErr.get(); + if (ImportTablePtr[LengthOfImportFileTable - 1] != '\0') + return createError( + ": import file name table with offset 0x" + + Twine::utohexstr(LoaderSectionAddr + OffsetToImportFileTable) + + " and size 0x" + Twine::utohexstr(LengthOfImportFileTable) + + " must end with a null terminator"); + + return StringRef(ImportTablePtr, LengthOfImportFileTable); +} + Expected<std::unique_ptr<XCOFFObjectFile>> XCOFFObjectFile::create(unsigned Type, MemoryBufferRef MBR) { // Can't use std::make_unique because of the private constructor. @@ -744,17 +1037,30 @@ XCOFFObjectFile::create(unsigned Type, MemoryBufferRef MBR) { Obj->FileHeader = FileHeaderOrErr.get(); CurOffset += Obj->getFileHeaderSize(); - // TODO FIXME we don't have support for an optional header yet, so just skip - // past it. + + if (Obj->getOptionalHeaderSize()) { + auto AuxiliaryHeaderOrErr = + getObject<void>(Data, Base + CurOffset, Obj->getOptionalHeaderSize()); + if (Error E = AuxiliaryHeaderOrErr.takeError()) + return std::move(E); + Obj->AuxiliaryHeader = AuxiliaryHeaderOrErr.get(); + } + CurOffset += Obj->getOptionalHeaderSize(); // Parse the section header table if it is present. if (Obj->getNumberOfSections()) { - auto SecHeadersOrErr = getObject<void>(Data, Base + CurOffset, - Obj->getNumberOfSections() * - Obj->getSectionHeaderSize()); - if (Error E = SecHeadersOrErr.takeError()) - return std::move(E); + uint64_t SectionHeadersSize = + Obj->getNumberOfSections() * Obj->getSectionHeaderSize(); + auto SecHeadersOrErr = + getObject<void>(Data, Base + CurOffset, SectionHeadersSize); + if (!SecHeadersOrErr) + return createError(toString(SecHeadersOrErr.takeError()) + + ": section headers with offset 0x" + + Twine::utohexstr(CurOffset) + " and size 0x" + + Twine::utohexstr(SectionHeadersSize) + + " go past the end of the file"); + Obj->SectionHeaderTable = SecHeadersOrErr.get(); } @@ -773,8 +1079,12 @@ XCOFFObjectFile::create(unsigned Type, MemoryBufferRef MBR) { NumberOfSymbolTableEntries; auto SymTableOrErr = getObject<void *>(Data, Base + CurOffset, SymbolTableSize); - if (Error E = SymTableOrErr.takeError()) - return std::move(E); + if (!SymTableOrErr) + return createError( + toString(SymTableOrErr.takeError()) + ": symbol table with offset 0x" + + Twine::utohexstr(CurOffset) + " and size 0x" + + Twine::utohexstr(SymbolTableSize) + " goes past the end of the file"); + Obj->SymbolTblPtr = SymTableOrErr.get(); CurOffset += SymbolTableSize; @@ -844,10 +1154,10 @@ Expected<XCOFFCsectAuxRef> XCOFFSymbolRef::getXCOFFCsectAuxRef() const { if (auto Err = NameOrErr.takeError()) return std::move(Err); + uint32_t SymbolIdx = OwningObjectPtr->getSymbolIndex(getEntryAddress()); if (!NumberOfAuxEntries) { - return createStringError(object_error::parse_failed, - "csect symbol \"" + *NameOrErr + - "\" contains no auxiliary entry"); + return createError("csect symbol \"" + *NameOrErr + "\" with index " + + Twine(SymbolIdx) + " contains no auxiliary entry"); } if (!OwningObjectPtr->is64Bit()) { @@ -872,9 +1182,9 @@ Expected<XCOFFCsectAuxRef> XCOFFSymbolRef::getXCOFFCsectAuxRef() const { } } - return createStringError( - object_error::parse_failed, - "a csect auxiliary entry is not found for symbol \"" + *NameOrErr + "\""); + return createError( + "a csect auxiliary entry has not been found for symbol \"" + *NameOrErr + + "\" with index " + Twine(SymbolIdx)); } Expected<StringRef> XCOFFSymbolRef::getName() const { @@ -897,6 +1207,18 @@ Expected<StringRef> XCOFFSymbolRef::getName() const { template struct XCOFFSectionHeader<XCOFFSectionHeader32>; template struct XCOFFSectionHeader<XCOFFSectionHeader64>; +template struct XCOFFRelocation<llvm::support::ubig32_t>; +template struct XCOFFRelocation<llvm::support::ubig64_t>; + +template llvm::Expected<llvm::ArrayRef<llvm::object::XCOFFRelocation64>> +llvm::object::XCOFFObjectFile::relocations<llvm::object::XCOFFSectionHeader64, + llvm::object::XCOFFRelocation64>( + llvm::object::XCOFFSectionHeader64 const &) const; +template llvm::Expected<llvm::ArrayRef<llvm::object::XCOFFRelocation32>> +llvm::object::XCOFFObjectFile::relocations<llvm::object::XCOFFSectionHeader32, + llvm::object::XCOFFRelocation32>( + llvm::object::XCOFFSectionHeader32 const &) const; + bool doesXCOFFTracebackTableBegin(ArrayRef<uint8_t> Bytes) { if (Bytes.size() < 4) return false; |