aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm/lib/Object
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2017-12-20 14:16:56 +0000
committerDimitry Andric <dim@FreeBSD.org>2017-12-20 14:16:56 +0000
commit2cab237b5dbfe1b3e9c7aa7a3c02d2b98fcf7462 (patch)
tree524fe828571f81358bba62fdb6d04c6e5e96a2a4 /contrib/llvm/lib/Object
parent6c7828a2807ea5e50c79ca42dbedf2b589ce63b2 (diff)
parent044eb2f6afba375a914ac9d8024f8f5142bb912e (diff)
Merge llvm trunk r321017 to contrib/llvm.
Notes
Notes: svn path=/projects/clang600-import/; revision=327023
Diffstat (limited to 'contrib/llvm/lib/Object')
-rw-r--r--contrib/llvm/lib/Object/Archive.cpp18
-rw-r--r--contrib/llvm/lib/Object/ArchiveWriter.cpp479
-rw-r--r--contrib/llvm/lib/Object/COFFImportFile.cpp30
-rw-r--r--contrib/llvm/lib/Object/COFFModuleDefinition.cpp37
-rw-r--r--contrib/llvm/lib/Object/COFFObjectFile.cpp38
-rw-r--r--contrib/llvm/lib/Object/ELF.cpp100
-rw-r--r--contrib/llvm/lib/Object/ELFObjectFile.cpp37
-rw-r--r--contrib/llvm/lib/Object/IRObjectFile.cpp32
-rw-r--r--contrib/llvm/lib/Object/IRSymtab.cpp58
-rw-r--r--contrib/llvm/lib/Object/MachOObjectFile.cpp588
-rw-r--r--contrib/llvm/lib/Object/ModuleSymbolTable.cpp2
-rw-r--r--contrib/llvm/lib/Object/ObjectFile.cpp31
-rw-r--r--contrib/llvm/lib/Object/SymbolicFile.cpp6
-rw-r--r--contrib/llvm/lib/Object/WasmObjectFile.cpp202
-rw-r--r--contrib/llvm/lib/Object/WindowsResource.cpp59
15 files changed, 1123 insertions, 594 deletions
diff --git a/contrib/llvm/lib/Object/Archive.cpp b/contrib/llvm/lib/Object/Archive.cpp
index 977cccc11dcd..b17eefd220b8 100644
--- a/contrib/llvm/lib/Object/Archive.cpp
+++ b/contrib/llvm/lib/Object/Archive.cpp
@@ -179,7 +179,7 @@ Expected<StringRef> ArchiveMemberHeader::getName(uint64_t Size) const {
// GNU long file names end with a "/\n".
if (Parent->kind() == Archive::K_GNU ||
- Parent->kind() == Archive::K_MIPS64) {
+ Parent->kind() == Archive::K_GNU64) {
StringRef::size_type End = StringRef(addr).find('\n');
return StringRef(addr, End - 1);
}
@@ -338,7 +338,7 @@ Archive::Child::Child(const Archive *Parent, const char *Start, Error *Err)
ErrorAsOutParameter ErrAsOutParam(Err);
- // If there was an error in the construction of the Header
+ // If there was an error in the construction of the Header
// then just return with the error now set.
if (*Err)
return;
@@ -698,7 +698,7 @@ Archive::Archive(MemoryBufferRef Source, Error &Err)
}
if (Name == "//") {
- Format = has64SymTable ? K_MIPS64 : K_GNU;
+ Format = has64SymTable ? K_GNU64 : K_GNU;
// The string table is never an external member, but we still
// must check any Expected<> return value.
Expected<StringRef> BufOrErr = C->getBuffer();
@@ -715,7 +715,7 @@ Archive::Archive(MemoryBufferRef Source, Error &Err)
}
if (Name[0] != '/') {
- Format = has64SymTable ? K_MIPS64 : K_GNU;
+ Format = has64SymTable ? K_GNU64 : K_GNU;
setFirstRegular(*C);
Err = Error::success();
return;
@@ -797,14 +797,14 @@ StringRef Archive::Symbol::getName() const {
Expected<Archive::Child> Archive::Symbol::getMember() const {
const char *Buf = Parent->getSymbolTable().begin();
const char *Offsets = Buf;
- if (Parent->kind() == K_MIPS64 || Parent->kind() == K_DARWIN64)
+ if (Parent->kind() == K_GNU64 || Parent->kind() == K_DARWIN64)
Offsets += sizeof(uint64_t);
else
Offsets += sizeof(uint32_t);
- uint32_t Offset = 0;
+ uint64_t Offset = 0;
if (Parent->kind() == K_GNU) {
Offset = read32be(Offsets + SymbolIndex * 4);
- } else if (Parent->kind() == K_MIPS64) {
+ } else if (Parent->kind() == K_GNU64) {
Offset = read64be(Offsets + SymbolIndex * 8);
} else if (Parent->kind() == K_BSD) {
// The SymbolIndex is an index into the ranlib structs that start at
@@ -902,7 +902,7 @@ Archive::symbol_iterator Archive::symbol_begin() const {
uint32_t symbol_count = 0;
symbol_count = read32be(buf);
buf += sizeof(uint32_t) + (symbol_count * (sizeof(uint32_t)));
- } else if (kind() == K_MIPS64) {
+ } else if (kind() == K_GNU64) {
uint64_t symbol_count = read64be(buf);
buf += sizeof(uint64_t) + (symbol_count * (sizeof(uint64_t)));
} else if (kind() == K_BSD) {
@@ -959,7 +959,7 @@ uint32_t Archive::getNumberOfSymbols() const {
const char *buf = getSymbolTable().begin();
if (kind() == K_GNU)
return read32be(buf);
- if (kind() == K_MIPS64)
+ if (kind() == K_GNU64)
return read64be(buf);
if (kind() == K_BSD)
return read32le(buf) / 8;
diff --git a/contrib/llvm/lib/Object/ArchiveWriter.cpp b/contrib/llvm/lib/Object/ArchiveWriter.cpp
index b052c76d1fed..b3b812daae2e 100644
--- a/contrib/llvm/lib/Object/ArchiveWriter.cpp
+++ b/contrib/llvm/lib/Object/ArchiveWriter.cpp
@@ -35,6 +35,15 @@
using namespace llvm;
+// The SYM64 format is used when an archive's member offsets are larger than
+// 32-bits can hold. The need for this shift in format is detected by
+// writeArchive. To test this we need to generate a file with a member that has
+// an offset larger than 32-bits but this demands a very slow test. To speed
+// the test up we use this flag to pretend like the cutoff happens before
+// 32-bits and instead happens at some much smaller value.
+static cl::opt<int> Sym64Threshold("sym64-threshold", cl::Hidden,
+ cl::init(32));
+
NewArchiveMember::NewArchiveMember(MemoryBufferRef BufRef)
: Buf(MemoryBuffer::getMemBuffer(BufRef, false)),
MemberName(BufRef.getBufferIdentifier()) {}
@@ -111,29 +120,22 @@ Expected<NewArchiveMember> NewArchiveMember::getFile(StringRef FileName,
}
template <typename T>
-static void printWithSpacePadding(raw_fd_ostream &OS, T Data, unsigned Size,
- bool MayTruncate = false) {
+static void printWithSpacePadding(raw_ostream &OS, T Data, unsigned Size) {
uint64_t OldPos = OS.tell();
OS << Data;
unsigned SizeSoFar = OS.tell() - OldPos;
- if (Size > SizeSoFar) {
- OS.indent(Size - SizeSoFar);
- } else if (Size < SizeSoFar) {
- assert(MayTruncate && "Data doesn't fit in Size");
- // Some of the data this is used for (like UID) can be larger than the
- // space available in the archive format. Truncate in that case.
- OS.seek(OldPos + Size);
- }
+ assert(SizeSoFar <= Size && "Data doesn't fit in Size");
+ OS.indent(Size - SizeSoFar);
}
static bool isBSDLike(object::Archive::Kind Kind) {
switch (Kind) {
case object::Archive::K_GNU:
+ case object::Archive::K_GNU64:
return false;
case object::Archive::K_BSD:
case object::Archive::K_DARWIN:
return true;
- case object::Archive::K_MIPS64:
case object::Archive::K_DARWIN64:
case object::Archive::K_COFF:
break;
@@ -141,8 +143,8 @@ static bool isBSDLike(object::Archive::Kind Kind) {
llvm_unreachable("not supported for writting");
}
-static void print32(raw_ostream &Out, object::Archive::Kind Kind,
- uint32_t Val) {
+template <class T>
+static void print(raw_ostream &Out, object::Archive::Kind Kind, T Val) {
if (isBSDLike(Kind))
support::endian::Writer<support::little>(Out).write(Val);
else
@@ -150,18 +152,22 @@ static void print32(raw_ostream &Out, object::Archive::Kind Kind,
}
static void printRestOfMemberHeader(
- raw_fd_ostream &Out, const sys::TimePoint<std::chrono::seconds> &ModTime,
+ raw_ostream &Out, const sys::TimePoint<std::chrono::seconds> &ModTime,
unsigned UID, unsigned GID, unsigned Perms, unsigned Size) {
printWithSpacePadding(Out, sys::toTimeT(ModTime), 12);
- printWithSpacePadding(Out, UID, 6, true);
- printWithSpacePadding(Out, GID, 6, true);
+
+ // The format has only 6 chars for uid and gid. Truncate if the provided
+ // values don't fit.
+ printWithSpacePadding(Out, UID % 1000000, 6);
+ printWithSpacePadding(Out, GID % 1000000, 6);
+
printWithSpacePadding(Out, format("%o", Perms), 8);
printWithSpacePadding(Out, Size, 10);
Out << "`\n";
}
static void
-printGNUSmallMemberHeader(raw_fd_ostream &Out, StringRef Name,
+printGNUSmallMemberHeader(raw_ostream &Out, StringRef Name,
const sys::TimePoint<std::chrono::seconds> &ModTime,
unsigned UID, unsigned GID, unsigned Perms,
unsigned Size) {
@@ -170,11 +176,11 @@ printGNUSmallMemberHeader(raw_fd_ostream &Out, StringRef Name,
}
static void
-printBSDMemberHeader(raw_fd_ostream &Out, StringRef Name,
+printBSDMemberHeader(raw_ostream &Out, uint64_t Pos, StringRef Name,
const sys::TimePoint<std::chrono::seconds> &ModTime,
unsigned UID, unsigned GID, unsigned Perms,
unsigned Size) {
- uint64_t PosAfterHeader = Out.tell() + 60 + Name.size();
+ uint64_t PosAfterHeader = Pos + 60 + Name.size();
// Pad so that even 64 bit object files are aligned.
unsigned Pad = OffsetToAlignment(PosAfterHeader, 8);
unsigned NameWithPadding = Name.size() + Pad;
@@ -182,7 +188,6 @@ printBSDMemberHeader(raw_fd_ostream &Out, StringRef Name,
printRestOfMemberHeader(Out, ModTime, UID, GID, Perms,
NameWithPadding + Size);
Out << Name;
- assert(PosAfterHeader == Out.tell());
while (Pad--)
Out.write(uint8_t(0));
}
@@ -191,21 +196,6 @@ static bool useStringTable(bool Thin, StringRef Name) {
return Thin || Name.size() >= 16 || Name.contains('/');
}
-static void
-printMemberHeader(raw_fd_ostream &Out, object::Archive::Kind Kind, bool Thin,
- StringRef Name,
- std::vector<unsigned>::iterator &StringMapIndexIter,
- const sys::TimePoint<std::chrono::seconds> &ModTime,
- unsigned UID, unsigned GID, unsigned Perms, unsigned Size) {
- if (isBSDLike(Kind))
- return printBSDMemberHeader(Out, Name, ModTime, UID, GID, Perms, Size);
- if (!useStringTable(Thin, Name))
- return printGNUSmallMemberHeader(Out, Name, ModTime, UID, GID, Perms, Size);
- Out << '/';
- printWithSpacePadding(Out, *StringMapIndexIter++, 15);
- printRestOfMemberHeader(Out, ModTime, UID, GID, Perms, Size);
-}
-
// Compute the relative path from From to To.
static std::string computeRelativePath(StringRef From, StringRef To) {
if (sys::path::is_absolute(From) || sys::path::is_absolute(To))
@@ -235,41 +225,70 @@ static std::string computeRelativePath(StringRef From, StringRef To) {
return Relative.str();
}
-static void writeStringTable(raw_fd_ostream &Out, StringRef ArcName,
- ArrayRef<NewArchiveMember> Members,
- std::vector<unsigned> &StringMapIndexes,
- bool Thin) {
- unsigned StartOffset = 0;
- for (const NewArchiveMember &M : Members) {
- StringRef Path = M.Buf->getBufferIdentifier();
- StringRef Name = M.MemberName;
- if (!useStringTable(Thin, Name))
- continue;
- if (StartOffset == 0) {
- printWithSpacePadding(Out, "//", 58);
- Out << "`\n";
- StartOffset = Out.tell();
- }
- StringMapIndexes.push_back(Out.tell() - StartOffset);
+static bool is64BitKind(object::Archive::Kind Kind) {
+ switch (Kind) {
+ case object::Archive::K_GNU:
+ case object::Archive::K_BSD:
+ case object::Archive::K_DARWIN:
+ case object::Archive::K_COFF:
+ return false;
+ case object::Archive::K_DARWIN64:
+ case object::Archive::K_GNU64:
+ return true;
+ }
+ llvm_unreachable("not supported for writting");
+}
- if (Thin) {
- if (M.IsNew)
- Out << computeRelativePath(ArcName, Path);
- else
- Out << M.Buf->getBufferIdentifier();
- } else
- Out << Name;
+static void addToStringTable(raw_ostream &Out, StringRef ArcName,
+ const NewArchiveMember &M, bool Thin) {
+ StringRef ID = M.Buf->getBufferIdentifier();
+ if (Thin) {
+ if (M.IsNew)
+ Out << computeRelativePath(ArcName, ID);
+ else
+ Out << ID;
+ } else
+ Out << M.MemberName;
+ Out << "/\n";
+}
- Out << "/\n";
- }
- if (StartOffset == 0)
- return;
- if (Out.tell() % 2)
- Out << '\n';
- int Pos = Out.tell();
- Out.seek(StartOffset - 12);
- printWithSpacePadding(Out, Pos - StartOffset, 10);
- Out.seek(Pos);
+static void printMemberHeader(raw_ostream &Out, uint64_t Pos,
+ raw_ostream &StringTable,
+ object::Archive::Kind Kind, bool Thin,
+ StringRef ArcName, const NewArchiveMember &M,
+ unsigned Size) {
+ if (isBSDLike(Kind))
+ return printBSDMemberHeader(Out, Pos, M.MemberName, M.ModTime, M.UID, M.GID,
+ M.Perms, Size);
+ if (!useStringTable(Thin, M.MemberName))
+ return printGNUSmallMemberHeader(Out, M.MemberName, M.ModTime, M.UID, M.GID,
+ M.Perms, Size);
+ Out << '/';
+ uint64_t NamePos = StringTable.tell();
+ addToStringTable(StringTable, ArcName, M, Thin);
+ printWithSpacePadding(Out, NamePos, 15);
+ printRestOfMemberHeader(Out, M.ModTime, M.UID, M.GID, M.Perms, Size);
+}
+
+namespace {
+struct MemberData {
+ std::vector<unsigned> Symbols;
+ std::string Header;
+ StringRef Data;
+ StringRef Padding;
+};
+} // namespace
+
+static MemberData computeStringTable(StringRef Names) {
+ unsigned Size = Names.size();
+ unsigned Pad = OffsetToAlignment(Size, 2);
+ std::string Header;
+ raw_string_ostream Out(Header);
+ printWithSpacePadding(Out, "//", 48);
+ printWithSpacePadding(Out, Size + Pad, 10);
+ Out << "`\n";
+ Out.flush();
+ return {{}, std::move(Header), Names, Pad ? "\n" : ""};
}
static sys::TimePoint<std::chrono::seconds> now(bool Deterministic) {
@@ -280,177 +299,222 @@ static sys::TimePoint<std::chrono::seconds> now(bool Deterministic) {
return sys::TimePoint<seconds>();
}
-// Returns the offset of the first reference to a member offset.
-static ErrorOr<unsigned>
-writeSymbolTable(raw_fd_ostream &Out, object::Archive::Kind Kind,
- ArrayRef<NewArchiveMember> Members,
- std::vector<unsigned> &MemberOffsetRefs, bool Deterministic) {
- unsigned HeaderStartOffset = 0;
- unsigned BodyStartOffset = 0;
- SmallString<128> NameBuf;
- raw_svector_ostream NameOS(NameBuf);
- LLVMContext Context;
- for (unsigned MemberNum = 0, N = Members.size(); MemberNum < N; ++MemberNum) {
- MemoryBufferRef MemberBuffer = Members[MemberNum].Buf->getMemBufferRef();
- Expected<std::unique_ptr<object::SymbolicFile>> ObjOrErr =
- object::SymbolicFile::createSymbolicFile(
- MemberBuffer, llvm::file_magic::unknown, &Context);
- if (!ObjOrErr) {
- // FIXME: check only for "not an object file" errors.
- consumeError(ObjOrErr.takeError());
- continue;
- }
- object::SymbolicFile &Obj = *ObjOrErr.get();
+static bool isArchiveSymbol(const object::BasicSymbolRef &S) {
+ uint32_t Symflags = S.getFlags();
+ if (Symflags & object::SymbolRef::SF_FormatSpecific)
+ return false;
+ if (!(Symflags & object::SymbolRef::SF_Global))
+ return false;
+ if (Symflags & object::SymbolRef::SF_Undefined &&
+ !(Symflags & object::SymbolRef::SF_Indirect))
+ return false;
+ return true;
+}
- if (!HeaderStartOffset) {
- HeaderStartOffset = Out.tell();
- if (isBSDLike(Kind))
- printBSDMemberHeader(Out, "__.SYMDEF", now(Deterministic), 0, 0, 0, 0);
- else
- printGNUSmallMemberHeader(Out, "", now(Deterministic), 0, 0, 0, 0);
- BodyStartOffset = Out.tell();
- print32(Out, Kind, 0); // number of entries or bytes
- }
+static void printNBits(raw_ostream &Out, object::Archive::Kind Kind,
+ uint64_t Val) {
+ if (is64BitKind(Kind))
+ print<uint64_t>(Out, Kind, Val);
+ else
+ print<uint32_t>(Out, Kind, Val);
+}
- for (const object::BasicSymbolRef &S : Obj.symbols()) {
- uint32_t Symflags = S.getFlags();
- if (Symflags & object::SymbolRef::SF_FormatSpecific)
- continue;
- if (!(Symflags & object::SymbolRef::SF_Global))
- continue;
- if (Symflags & object::SymbolRef::SF_Undefined &&
- !(Symflags & object::SymbolRef::SF_Indirect))
- continue;
-
- unsigned NameOffset = NameOS.tell();
- if (auto EC = S.printName(NameOS))
- return EC;
- NameOS << '\0';
- MemberOffsetRefs.push_back(MemberNum);
- if (isBSDLike(Kind))
- print32(Out, Kind, NameOffset);
- print32(Out, Kind, 0); // member offset
- }
- }
+static void writeSymbolTable(raw_ostream &Out, object::Archive::Kind Kind,
+ bool Deterministic, ArrayRef<MemberData> Members,
+ StringRef StringTable) {
+ if (StringTable.empty())
+ return;
- if (HeaderStartOffset == 0)
- return 0;
+ unsigned NumSyms = 0;
+ for (const MemberData &M : Members)
+ NumSyms += M.Symbols.size();
- // ld64 prefers the cctools type archive which pads its string table to a
- // boundary of sizeof(int32_t).
+ unsigned Size = 0;
+ Size += is64BitKind(Kind) ? 8 : 4; // Number of entries
if (isBSDLike(Kind))
- for (unsigned P = OffsetToAlignment(NameOS.tell(), sizeof(int32_t)); P--;)
- NameOS << '\0';
-
- StringRef StringTable = NameOS.str();
+ Size += NumSyms * 8; // Table
+ else if (is64BitKind(Kind))
+ Size += NumSyms * 8; // Table
+ else
+ Size += NumSyms * 4; // Table
if (isBSDLike(Kind))
- print32(Out, Kind, StringTable.size()); // byte count of the string table
- Out << StringTable;
- // If there are no symbols, emit an empty symbol table, to satisfy Solaris
- // tools, older versions of which expect a symbol table in a non-empty
- // archive, regardless of whether there are any symbols in it.
- if (StringTable.size() == 0)
- print32(Out, Kind, 0);
+ Size += 4; // byte count
+ Size += StringTable.size();
+ // ld64 expects the members to be 8-byte aligned for 64-bit content and at
+ // least 4-byte aligned for 32-bit content. Opt for the larger encoding
+ // uniformly.
+ // We do this for all bsd formats because it simplifies aligning members.
+ unsigned Alignment = isBSDLike(Kind) ? 8 : 2;
+ unsigned Pad = OffsetToAlignment(Size, Alignment);
+ Size += Pad;
- // ld64 requires the next member header to start at an offset that is
- // 4 bytes aligned.
- unsigned Pad = OffsetToAlignment(Out.tell(), 4);
- while (Pad--)
- Out.write(uint8_t(0));
+ if (isBSDLike(Kind))
+ printBSDMemberHeader(Out, Out.tell(), "__.SYMDEF", now(Deterministic), 0, 0,
+ 0, Size);
+ else if (is64BitKind(Kind))
+ printGNUSmallMemberHeader(Out, "/SYM64", now(Deterministic), 0, 0, 0, Size);
+ else
+ printGNUSmallMemberHeader(Out, "", now(Deterministic), 0, 0, 0, Size);
- // Patch up the size of the symbol table now that we know how big it is.
- unsigned Pos = Out.tell();
- const unsigned MemberHeaderSize = 60;
- Out.seek(HeaderStartOffset + 48); // offset of the size field.
- printWithSpacePadding(Out, Pos - MemberHeaderSize - HeaderStartOffset, 10);
+ uint64_t Pos = Out.tell() + Size;
- // Patch up the number of symbols.
- Out.seek(BodyStartOffset);
- unsigned NumSyms = MemberOffsetRefs.size();
if (isBSDLike(Kind))
- print32(Out, Kind, NumSyms * 8);
+ print<uint32_t>(Out, Kind, NumSyms * 8);
else
- print32(Out, Kind, NumSyms);
+ printNBits(Out, Kind, NumSyms);
+
+ for (const MemberData &M : Members) {
+ for (unsigned StringOffset : M.Symbols) {
+ if (isBSDLike(Kind))
+ print<uint32_t>(Out, Kind, StringOffset);
+ printNBits(Out, Kind, Pos); // member offset
+ }
+ Pos += M.Header.size() + M.Data.size() + M.Padding.size();
+ }
+
+ if (isBSDLike(Kind))
+ // byte count of the string table
+ print<uint32_t>(Out, Kind, StringTable.size());
+ Out << StringTable;
- Out.seek(Pos);
- return BodyStartOffset + 4;
+ while (Pad--)
+ Out.write(uint8_t(0));
}
-std::pair<StringRef, std::error_code>
-llvm::writeArchive(StringRef ArcName,
- std::vector<NewArchiveMember> &NewMembers,
- bool WriteSymtab, object::Archive::Kind Kind,
- bool Deterministic, bool Thin,
- std::unique_ptr<MemoryBuffer> OldArchiveBuf) {
- assert((!Thin || !isBSDLike(Kind)) && "Only the gnu format has a thin mode");
- SmallString<128> TmpArchive;
- int TmpArchiveFD;
- if (auto EC = sys::fs::createUniqueFile(ArcName + ".temp-archive-%%%%%%%.a",
- TmpArchiveFD, TmpArchive))
- return std::make_pair(ArcName, EC);
-
- tool_output_file Output(TmpArchive, TmpArchiveFD);
- raw_fd_ostream &Out = Output.os();
- if (Thin)
- Out << "!<thin>\n";
- else
- Out << "!<arch>\n";
+static Expected<std::vector<unsigned>>
+getSymbols(MemoryBufferRef Buf, raw_ostream &SymNames, bool &HasObject) {
+ std::vector<unsigned> Ret;
+ LLVMContext Context;
- std::vector<unsigned> MemberOffsetRefs;
+ Expected<std::unique_ptr<object::SymbolicFile>> ObjOrErr =
+ object::SymbolicFile::createSymbolicFile(Buf, llvm::file_magic::unknown,
+ &Context);
+ if (!ObjOrErr) {
+ // FIXME: check only for "not an object file" errors.
+ consumeError(ObjOrErr.takeError());
+ return Ret;
+ }
- unsigned MemberReferenceOffset = 0;
- if (WriteSymtab) {
- ErrorOr<unsigned> MemberReferenceOffsetOrErr = writeSymbolTable(
- Out, Kind, NewMembers, MemberOffsetRefs, Deterministic);
- if (auto EC = MemberReferenceOffsetOrErr.getError())
- return std::make_pair(ArcName, EC);
- MemberReferenceOffset = MemberReferenceOffsetOrErr.get();
+ HasObject = true;
+ object::SymbolicFile &Obj = *ObjOrErr.get();
+ for (const object::BasicSymbolRef &S : Obj.symbols()) {
+ if (!isArchiveSymbol(S))
+ continue;
+ Ret.push_back(SymNames.tell());
+ if (auto EC = S.printName(SymNames))
+ return errorCodeToError(EC);
+ SymNames << '\0';
}
+ return Ret;
+}
+
+static Expected<std::vector<MemberData>>
+computeMemberData(raw_ostream &StringTable, raw_ostream &SymNames,
+ object::Archive::Kind Kind, bool Thin, StringRef ArcName,
+ ArrayRef<NewArchiveMember> NewMembers) {
+ static char PaddingData[8] = {'\n', '\n', '\n', '\n', '\n', '\n', '\n', '\n'};
- std::vector<unsigned> StringMapIndexes;
- if (!isBSDLike(Kind))
- writeStringTable(Out, ArcName, NewMembers, StringMapIndexes, Thin);
+ // This ignores the symbol table, but we only need the value mod 8 and the
+ // symbol table is aligned to be a multiple of 8 bytes
+ uint64_t Pos = 0;
- std::vector<unsigned>::iterator StringMapIndexIter = StringMapIndexes.begin();
- std::vector<unsigned> MemberOffset;
+ std::vector<MemberData> Ret;
+ bool HasObject = false;
for (const NewArchiveMember &M : NewMembers) {
- MemoryBufferRef File = M.Buf->getMemBufferRef();
- unsigned Padding = 0;
+ std::string Header;
+ raw_string_ostream Out(Header);
- unsigned Pos = Out.tell();
- MemberOffset.push_back(Pos);
+ MemoryBufferRef Buf = M.Buf->getMemBufferRef();
+ StringRef Data = Thin ? "" : Buf.getBuffer();
// ld64 expects the members to be 8-byte aligned for 64-bit content and at
// least 4-byte aligned for 32-bit content. Opt for the larger encoding
// uniformly. This matches the behaviour with cctools and ensures that ld64
// is happy with archives that we generate.
- if (Kind == object::Archive::K_DARWIN)
- Padding = OffsetToAlignment(M.Buf->getBufferSize(), 8);
+ unsigned MemberPadding = Kind == object::Archive::K_DARWIN
+ ? OffsetToAlignment(Data.size(), 8)
+ : 0;
+ unsigned TailPadding = OffsetToAlignment(Data.size() + MemberPadding, 2);
+ StringRef Padding = StringRef(PaddingData, MemberPadding + TailPadding);
+
+ printMemberHeader(Out, Pos, StringTable, Kind, Thin, ArcName, M,
+ Buf.getBufferSize() + MemberPadding);
+ Out.flush();
+
+ Expected<std::vector<unsigned>> Symbols =
+ getSymbols(Buf, SymNames, HasObject);
+ if (auto E = Symbols.takeError())
+ return std::move(E);
+
+ Pos += Header.size() + Data.size() + Padding.size();
+ Ret.push_back({std::move(*Symbols), std::move(Header), Data, Padding});
+ }
+ // If there are no symbols, emit an empty symbol table, to satisfy Solaris
+ // tools, older versions of which expect a symbol table in a non-empty
+ // archive, regardless of whether there are any symbols in it.
+ if (HasObject && SymNames.tell() == 0)
+ SymNames << '\0' << '\0' << '\0';
+ return Ret;
+}
- printMemberHeader(Out, Kind, Thin, M.MemberName, StringMapIndexIter,
- M.ModTime, M.UID, M.GID, M.Perms,
- M.Buf->getBufferSize() + Padding);
+Error llvm::writeArchive(StringRef ArcName,
+ ArrayRef<NewArchiveMember> NewMembers,
+ bool WriteSymtab, object::Archive::Kind Kind,
+ bool Deterministic, bool Thin,
+ std::unique_ptr<MemoryBuffer> OldArchiveBuf) {
+ assert((!Thin || !isBSDLike(Kind)) && "Only the gnu format has a thin mode");
- if (!Thin)
- Out << File.getBuffer();
+ SmallString<0> SymNamesBuf;
+ raw_svector_ostream SymNames(SymNamesBuf);
+ SmallString<0> StringTableBuf;
+ raw_svector_ostream StringTable(StringTableBuf);
- while (Padding--)
- Out << '\n';
- if (Out.tell() % 2)
- Out << '\n';
- }
+ Expected<std::vector<MemberData>> DataOrErr =
+ computeMemberData(StringTable, SymNames, Kind, Thin, ArcName, NewMembers);
+ if (Error E = DataOrErr.takeError())
+ return E;
+ std::vector<MemberData> &Data = *DataOrErr;
- if (MemberReferenceOffset) {
- Out.seek(MemberReferenceOffset);
- for (unsigned MemberNum : MemberOffsetRefs) {
- if (isBSDLike(Kind))
- Out.seek(Out.tell() + 4); // skip over the string offset
- print32(Out, Kind, MemberOffset[MemberNum]);
+ if (!StringTableBuf.empty())
+ Data.insert(Data.begin(), computeStringTable(StringTableBuf));
+
+ // We would like to detect if we need to switch to a 64-bit symbol table.
+ if (WriteSymtab) {
+ uint64_t MaxOffset = 0;
+ uint64_t LastOffset = MaxOffset;
+ for (const auto& M : Data) {
+ // Record the start of the member's offset
+ LastOffset = MaxOffset;
+ // Account for the size of each part associated with the member.
+ MaxOffset += M.Header.size() + M.Data.size() + M.Padding.size();
+ // We assume 32-bit symbols to see if 32-bit symbols are possible or not.
+ MaxOffset += M.Symbols.size() * 4;
}
+ // If LastOffset isn't going to fit in a 32-bit varible we need to switch
+ // to 64-bit. Note that the file can be larger than 4GB as long as the last
+ // member starts before the 4GB offset.
+ if (LastOffset >= (1ULL << Sym64Threshold))
+ Kind = object::Archive::K_GNU64;
}
- Output.keep();
- Out.close();
+ Expected<sys::fs::TempFile> Temp =
+ sys::fs::TempFile::create(ArcName + ".temp-archive-%%%%%%%.a");
+ if (!Temp)
+ return Temp.takeError();
+
+ raw_fd_ostream Out(Temp->FD, false);
+ if (Thin)
+ Out << "!<thin>\n";
+ else
+ Out << "!<arch>\n";
+
+ if (WriteSymtab)
+ writeSymbolTable(Out, Kind, Deterministic, Data, SymNamesBuf);
+
+ for (const MemberData &M : Data)
+ Out << M.Header << M.Data << M.Padding;
+
+ Out.flush();
// At this point, we no longer need whatever backing memory
// was used to generate the NewMembers. On Windows, this buffer
@@ -464,6 +528,5 @@ llvm::writeArchive(StringRef ArcName,
// closed before we attempt to rename.
OldArchiveBuf.reset();
- sys::fs::rename(TmpArchive, ArcName);
- return std::make_pair("", std::error_code());
+ return Temp->keep(ArcName);
}
diff --git a/contrib/llvm/lib/Object/COFFImportFile.cpp b/contrib/llvm/lib/Object/COFFImportFile.cpp
index ff039463d08c..93631f1ad811 100644
--- a/contrib/llvm/lib/Object/COFFImportFile.cpp
+++ b/contrib/llvm/lib/Object/COFFImportFile.cpp
@@ -20,8 +20,6 @@
#include "llvm/Support/Path.h"
#include <cstdint>
-#include <map>
-#include <set>
#include <string>
#include <vector>
@@ -36,6 +34,7 @@ static bool is32bit(MachineTypes Machine) {
switch (Machine) {
default:
llvm_unreachable("unsupported machine");
+ case IMAGE_FILE_MACHINE_ARM64:
case IMAGE_FILE_MACHINE_AMD64:
return false;
case IMAGE_FILE_MACHINE_ARMNT:
@@ -52,6 +51,8 @@ static uint16_t getImgRelRelocation(MachineTypes Machine) {
return IMAGE_REL_AMD64_ADDR32NB;
case IMAGE_FILE_MACHINE_ARMNT:
return IMAGE_REL_ARM_ADDR32NB;
+ case IMAGE_FILE_MACHINE_ARM64:
+ return IMAGE_REL_ARM64_ADDR32NB;
case IMAGE_FILE_MACHINE_I386:
return IMAGE_REL_I386_DIR32NB;
}
@@ -187,7 +188,7 @@ ObjectFactory::createImportDescriptor(std::vector<uint8_t> &Buffer) {
(ImportName.size() + 1)),
u32(NumberOfSymbols),
u16(0),
- u16(is32bit(Machine) ? IMAGE_FILE_32BIT_MACHINE : 0),
+ u16(is32bit(Machine) ? IMAGE_FILE_32BIT_MACHINE : C_Invalid),
};
append(Buffer, Header);
@@ -323,7 +324,7 @@ ObjectFactory::createNullImportDescriptor(std::vector<uint8_t> &Buffer) {
sizeof(coff_import_directory_table_entry)),
u32(NumberOfSymbols),
u16(0),
- u16(is32bit(Machine) ? IMAGE_FILE_32BIT_MACHINE : 0),
+ u16(is32bit(Machine) ? IMAGE_FILE_32BIT_MACHINE : C_Invalid),
};
append(Buffer, Header);
@@ -386,7 +387,7 @@ NewArchiveMember ObjectFactory::createNullThunk(std::vector<uint8_t> &Buffer) {
VASize),
u32(NumberOfSymbols),
u16(0),
- u16(is32bit(Machine) ? IMAGE_FILE_32BIT_MACHINE : 0),
+ u16(is32bit(Machine) ? IMAGE_FILE_32BIT_MACHINE : C_Invalid),
};
append(Buffer, Header);
@@ -555,9 +556,9 @@ NewArchiveMember ObjectFactory::createWeakExternal(StringRef Sym,
return {MemoryBufferRef(StringRef(Buf, Buffer.size()), ImportName)};
}
-std::error_code writeImportLibrary(StringRef ImportName, StringRef Path,
- ArrayRef<COFFShortExport> Exports,
- MachineTypes Machine, bool MakeWeakAliases) {
+Error writeImportLibrary(StringRef ImportName, StringRef Path,
+ ArrayRef<COFFShortExport> Exports,
+ MachineTypes Machine, bool MakeWeakAliases) {
std::vector<NewArchiveMember> Members;
ObjectFactory OF(llvm::sys::path::filename(ImportName), Machine);
@@ -593,19 +594,16 @@ std::error_code writeImportLibrary(StringRef ImportName, StringRef Path,
? SymbolName
: replace(SymbolName, E.Name, E.ExtName);
- if (!Name) {
- return errorToErrorCode(Name.takeError());
- }
+ if (!Name)
+ return Name.takeError();
Members.push_back(
OF.createShortImport(*Name, E.Ordinal, ImportType, NameType));
}
- std::pair<StringRef, std::error_code> Result =
- writeArchive(Path, Members, /*WriteSymtab*/ true, object::Archive::K_GNU,
- /*Deterministic*/ true, /*Thin*/ false);
-
- return Result.second;
+ return writeArchive(Path, Members, /*WriteSymtab*/ true,
+ object::Archive::K_GNU,
+ /*Deterministic*/ true, /*Thin*/ false);
}
} // namespace object
diff --git a/contrib/llvm/lib/Object/COFFModuleDefinition.cpp b/contrib/llvm/lib/Object/COFFModuleDefinition.cpp
index 510eac8b239b..a571354648d6 100644
--- a/contrib/llvm/lib/Object/COFFModuleDefinition.cpp
+++ b/contrib/llvm/lib/Object/COFFModuleDefinition.cpp
@@ -57,9 +57,27 @@ struct Token {
};
static bool isDecorated(StringRef Sym, bool MingwDef) {
- // mingw does not prepend "_".
- return (!MingwDef && Sym.startswith("_")) || Sym.startswith("@") ||
- Sym.startswith("?");
+ // In def files, the symbols can either be listed decorated or undecorated.
+ //
+ // - For cdecl symbols, only the undecorated form is allowed.
+ // - For fastcall and vectorcall symbols, both fully decorated or
+ // undecorated forms can be present.
+ // - For stdcall symbols in non-MinGW environments, the decorated form is
+ // fully decorated with leading underscore and trailing stack argument
+ // size - like "_Func@0".
+ // - In MinGW def files, a decorated stdcall symbol does not include the
+ // leading underscore though, like "Func@0".
+
+ // This function controls whether a leading underscore should be added to
+ // the given symbol name or not. For MinGW, treat a stdcall symbol name such
+ // as "Func@0" as undecorated, i.e. a leading underscore must be added.
+ // For non-MinGW, look for '@' in the whole string and consider "_Func@0"
+ // as decorated, i.e. don't add any more leading underscores.
+ // We can't check for a leading underscore here, since function names
+ // themselves can start with an underscore, while a second one still needs
+ // to be added.
+ return Sym.startswith("@") || Sym.contains("@@") || Sym.startswith("?") ||
+ (!MingwDef && Sym.contains('@'));
}
static Error createError(const Twine &Err) {
@@ -99,7 +117,7 @@ public:
return Token(Identifier, S);
}
default: {
- size_t End = Buf.find_first_of("=,\r\n \t\v");
+ size_t End = Buf.find_first_of("=,;\r\n \t\v");
StringRef Word = Buf.substr(0, End);
Kind K = llvm::StringSwitch<Kind>(Word)
.Case("BASE", KwBase)
@@ -232,13 +250,18 @@ private:
for (;;) {
read();
if (Tok.K == Identifier && Tok.Value[0] == '@') {
- if (Tok.Value.drop_front().getAsInteger(10, E.Ordinal)) {
- // Not an ordinal modifier at all, but the next export (fastcall
- // decorated) - complete the current one.
+ if (Tok.Value == "@") {
+ // "foo @ 10"
+ read();
+ Tok.Value.getAsInteger(10, E.Ordinal);
+ } else if (Tok.Value.drop_front().getAsInteger(10, E.Ordinal)) {
+ // "foo \n @bar" - Not an ordinal modifier at all, but the next
+ // export (fastcall decorated) - complete the current one.
unget();
Info.Exports.push_back(E);
return Error::success();
}
+ // "foo @10"
read();
if (Tok.K == KwNoname) {
E.Noname = true;
diff --git a/contrib/llvm/lib/Object/COFFObjectFile.cpp b/contrib/llvm/lib/Object/COFFObjectFile.cpp
index 0a2053477caf..b544fa5c1470 100644
--- a/contrib/llvm/lib/Object/COFFObjectFile.cpp
+++ b/contrib/llvm/lib/Object/COFFObjectFile.cpp
@@ -52,16 +52,6 @@ static bool checkSize(MemoryBufferRef M, std::error_code &EC, uint64_t Size) {
return true;
}
-static std::error_code checkOffset(MemoryBufferRef M, uintptr_t Addr,
- const uint64_t Size) {
- if (Addr + Size < Addr || Addr + Size < Size ||
- Addr + Size > uintptr_t(M.getBufferEnd()) ||
- Addr < uintptr_t(M.getBufferStart())) {
- return object_error::unexpected_eof;
- }
- return std::error_code();
-}
-
// Sets Obj unless any bytes in [addr, addr + size) fall outsize of m.
// Returns unexpected_eof if error.
template <typename T>
@@ -69,7 +59,7 @@ static std::error_code getObject(const T *&Obj, MemoryBufferRef M,
const void *Ptr,
const uint64_t Size = sizeof(T)) {
uintptr_t Addr = uintptr_t(Ptr);
- if (std::error_code EC = checkOffset(M, Addr, Size))
+ if (std::error_code EC = Binary::checkOffset(M, Addr, Size))
return EC;
Obj = reinterpret_cast<const T *>(Addr);
return std::error_code();
@@ -383,7 +373,8 @@ getFirstReloc(const coff_section *Sec, MemoryBufferRef M, const uint8_t *Base) {
// relocations.
begin++;
}
- if (checkOffset(M, uintptr_t(begin), sizeof(coff_relocation) * NumRelocs))
+ if (Binary::checkOffset(M, uintptr_t(begin),
+ sizeof(coff_relocation) * NumRelocs))
return nullptr;
return begin;
}
@@ -904,7 +895,7 @@ StringRef COFFObjectFile::getFileFormatName() const {
}
}
-unsigned COFFObjectFile::getArch() const {
+Triple::ArchType COFFObjectFile::getArch() const {
switch (getMachine()) {
case COFF::IMAGE_FILE_MACHINE_I386:
return Triple::x86;
@@ -1599,12 +1590,12 @@ std::error_code ImportedSymbolRef::getOrdinal(uint16_t &Result) const {
return std::error_code();
}
-ErrorOr<std::unique_ptr<COFFObjectFile>>
+Expected<std::unique_ptr<COFFObjectFile>>
ObjectFile::createCOFFObjectFile(MemoryBufferRef Object) {
std::error_code EC;
std::unique_ptr<COFFObjectFile> Ret(new COFFObjectFile(Object, EC));
if (EC)
- return EC;
+ return errorCodeToError(EC);
return std::move(Ret);
}
@@ -1642,11 +1633,12 @@ std::error_code BaseRelocRef::getRVA(uint32_t &Result) const {
return std::error_code();
}
-#define RETURN_IF_ERROR(X) \
- if (auto EC = errorToErrorCode(X)) \
- return EC;
+#define RETURN_IF_ERROR(E) \
+ if (E) \
+ return E;
-ErrorOr<ArrayRef<UTF16>> ResourceSectionRef::getDirStringAtOffset(uint32_t Offset) {
+Expected<ArrayRef<UTF16>>
+ResourceSectionRef::getDirStringAtOffset(uint32_t Offset) {
BinaryStreamReader Reader = BinaryStreamReader(BBS);
Reader.setOffset(Offset);
uint16_t Length;
@@ -1656,12 +1648,12 @@ ErrorOr<ArrayRef<UTF16>> ResourceSectionRef::getDirStringAtOffset(uint32_t Offse
return RawDirString;
}
-ErrorOr<ArrayRef<UTF16>>
+Expected<ArrayRef<UTF16>>
ResourceSectionRef::getEntryNameString(const coff_resource_dir_entry &Entry) {
return getDirStringAtOffset(Entry.Identifier.getNameOffset());
}
-ErrorOr<const coff_resource_dir_table &>
+Expected<const coff_resource_dir_table &>
ResourceSectionRef::getTableAtOffset(uint32_t Offset) {
const coff_resource_dir_table *Table = nullptr;
@@ -1672,11 +1664,11 @@ ResourceSectionRef::getTableAtOffset(uint32_t Offset) {
return *Table;
}
-ErrorOr<const coff_resource_dir_table &>
+Expected<const coff_resource_dir_table &>
ResourceSectionRef::getEntrySubDir(const coff_resource_dir_entry &Entry) {
return getTableAtOffset(Entry.Offset.value());
}
-ErrorOr<const coff_resource_dir_table &> ResourceSectionRef::getBaseTable() {
+Expected<const coff_resource_dir_table &> ResourceSectionRef::getBaseTable() {
return getTableAtOffset(0);
}
diff --git a/contrib/llvm/lib/Object/ELF.cpp b/contrib/llvm/lib/Object/ELF.cpp
index 448fb1bd6b56..c72a1258c1ee 100644
--- a/contrib/llvm/lib/Object/ELF.cpp
+++ b/contrib/llvm/lib/Object/ELF.cpp
@@ -9,6 +9,7 @@
#include "llvm/Object/ELF.h"
#include "llvm/BinaryFormat/ELF.h"
+#include "llvm/Support/LEB128.h"
using namespace llvm;
using namespace object;
@@ -58,6 +59,14 @@ StringRef llvm::object::getELFRelocationTypeName(uint32_t Machine,
break;
}
break;
+ case ELF::EM_ARC_COMPACT:
+ case ELF::EM_ARC_COMPACT2:
+ switch (Type) {
+#include "llvm/BinaryFormat/ELFRelocs/ARC.def"
+ default:
+ break;
+ }
+ break;
case ELF::EM_AVR:
switch (Type) {
#include "llvm/BinaryFormat/ELFRelocs/AVR.def"
@@ -192,6 +201,8 @@ StringRef llvm::object::getELFSectionTypeName(uint32_t Machine, unsigned Type) {
STRINGIFY_ENUM_CASE(ELF, SHT_PREINIT_ARRAY);
STRINGIFY_ENUM_CASE(ELF, SHT_GROUP);
STRINGIFY_ENUM_CASE(ELF, SHT_SYMTAB_SHNDX);
+ STRINGIFY_ENUM_CASE(ELF, SHT_ANDROID_REL);
+ STRINGIFY_ENUM_CASE(ELF, SHT_ANDROID_RELA);
STRINGIFY_ENUM_CASE(ELF, SHT_LLVM_ODRTAB);
STRINGIFY_ENUM_CASE(ELF, SHT_GNU_ATTRIBUTES);
STRINGIFY_ENUM_CASE(ELF, SHT_GNU_HASH);
@@ -202,3 +213,92 @@ StringRef llvm::object::getELFSectionTypeName(uint32_t Machine, unsigned Type) {
return "Unknown";
}
}
+
+template <class ELFT>
+Expected<std::vector<typename ELFT::Rela>>
+ELFFile<ELFT>::android_relas(const Elf_Shdr *Sec) const {
+ // This function reads relocations in Android's packed relocation format,
+ // which is based on SLEB128 and delta encoding.
+ Expected<ArrayRef<uint8_t>> ContentsOrErr = getSectionContents(Sec);
+ if (!ContentsOrErr)
+ return ContentsOrErr.takeError();
+ const uint8_t *Cur = ContentsOrErr->begin();
+ const uint8_t *End = ContentsOrErr->end();
+ if (ContentsOrErr->size() < 4 || Cur[0] != 'A' || Cur[1] != 'P' ||
+ Cur[2] != 'S' || Cur[3] != '2')
+ return createError("invalid packed relocation header");
+ Cur += 4;
+
+ const char *ErrStr = nullptr;
+ auto ReadSLEB = [&]() -> int64_t {
+ if (ErrStr)
+ return 0;
+ unsigned Len;
+ int64_t Result = decodeSLEB128(Cur, &Len, End, &ErrStr);
+ Cur += Len;
+ return Result;
+ };
+
+ uint64_t NumRelocs = ReadSLEB();
+ uint64_t Offset = ReadSLEB();
+ uint64_t Addend = 0;
+
+ if (ErrStr)
+ return createError(ErrStr);
+
+ std::vector<Elf_Rela> Relocs;
+ Relocs.reserve(NumRelocs);
+ while (NumRelocs) {
+ uint64_t NumRelocsInGroup = ReadSLEB();
+ if (NumRelocsInGroup > NumRelocs)
+ return createError("relocation group unexpectedly large");
+ NumRelocs -= NumRelocsInGroup;
+
+ uint64_t GroupFlags = ReadSLEB();
+ bool GroupedByInfo = GroupFlags & ELF::RELOCATION_GROUPED_BY_INFO_FLAG;
+ bool GroupedByOffsetDelta = GroupFlags & ELF::RELOCATION_GROUPED_BY_OFFSET_DELTA_FLAG;
+ bool GroupedByAddend = GroupFlags & ELF::RELOCATION_GROUPED_BY_ADDEND_FLAG;
+ bool GroupHasAddend = GroupFlags & ELF::RELOCATION_GROUP_HAS_ADDEND_FLAG;
+
+ uint64_t GroupOffsetDelta;
+ if (GroupedByOffsetDelta)
+ GroupOffsetDelta = ReadSLEB();
+
+ uint64_t GroupRInfo;
+ if (GroupedByInfo)
+ GroupRInfo = ReadSLEB();
+
+ if (GroupedByAddend && GroupHasAddend)
+ Addend += ReadSLEB();
+
+ for (uint64_t I = 0; I != NumRelocsInGroup; ++I) {
+ Elf_Rela R;
+ Offset += GroupedByOffsetDelta ? GroupOffsetDelta : ReadSLEB();
+ R.r_offset = Offset;
+ R.r_info = GroupedByInfo ? GroupRInfo : ReadSLEB();
+
+ if (GroupHasAddend) {
+ if (!GroupedByAddend)
+ Addend += ReadSLEB();
+ R.r_addend = Addend;
+ } else {
+ R.r_addend = 0;
+ }
+
+ Relocs.push_back(R);
+
+ if (ErrStr)
+ return createError(ErrStr);
+ }
+
+ if (ErrStr)
+ return createError(ErrStr);
+ }
+
+ return Relocs;
+}
+
+template class llvm::object::ELFFile<ELF32LE>;
+template class llvm::object::ELFFile<ELF32BE>;
+template class llvm::object::ELFFile<ELF64LE>;
+template class llvm::object::ELFFile<ELF64BE>;
diff --git a/contrib/llvm/lib/Object/ELFObjectFile.cpp b/contrib/llvm/lib/Object/ELFObjectFile.cpp
index fa136d782b5a..0aad1c89a2d8 100644
--- a/contrib/llvm/lib/Object/ELFObjectFile.cpp
+++ b/contrib/llvm/lib/Object/ELFObjectFile.cpp
@@ -37,7 +37,16 @@ using namespace object;
ELFObjectFileBase::ELFObjectFileBase(unsigned int Type, MemoryBufferRef Source)
: ObjectFile(Type, Source) {}
-ErrorOr<std::unique_ptr<ObjectFile>>
+template <class ELFT>
+static Expected<std::unique_ptr<ELFObjectFile<ELFT>>>
+createPtr(MemoryBufferRef Object) {
+ auto Ret = ELFObjectFile<ELFT>::create(Object);
+ if (Error E = Ret.takeError())
+ return std::move(E);
+ return make_unique<ELFObjectFile<ELFT>>(std::move(*Ret));
+}
+
+Expected<std::unique_ptr<ObjectFile>>
ObjectFile::createELFObjectFile(MemoryBufferRef Obj) {
std::pair<unsigned char, unsigned char> Ident =
getElfArchType(Obj.getBuffer());
@@ -45,31 +54,24 @@ ObjectFile::createELFObjectFile(MemoryBufferRef Obj) {
1ULL << countTrailingZeros(uintptr_t(Obj.getBufferStart()));
if (MaxAlignment < 2)
- return object_error::parse_failed;
+ return createError("Insufficient alignment");
- std::error_code EC;
- std::unique_ptr<ObjectFile> R;
if (Ident.first == ELF::ELFCLASS32) {
if (Ident.second == ELF::ELFDATA2LSB)
- R.reset(new ELFObjectFile<ELFType<support::little, false>>(Obj, EC));
+ return createPtr<ELF32LE>(Obj);
else if (Ident.second == ELF::ELFDATA2MSB)
- R.reset(new ELFObjectFile<ELFType<support::big, false>>(Obj, EC));
+ return createPtr<ELF32BE>(Obj);
else
- return object_error::parse_failed;
+ return createError("Invalid ELF data");
} else if (Ident.first == ELF::ELFCLASS64) {
if (Ident.second == ELF::ELFDATA2LSB)
- R.reset(new ELFObjectFile<ELFType<support::little, true>>(Obj, EC));
+ return createPtr<ELF64LE>(Obj);
else if (Ident.second == ELF::ELFDATA2MSB)
- R.reset(new ELFObjectFile<ELFType<support::big, true>>(Obj, EC));
+ return createPtr<ELF64BE>(Obj);
else
- return object_error::parse_failed;
- } else {
- return object_error::parse_failed;
+ return createError("Invalid ELF data");
}
-
- if (EC)
- return EC;
- return std::move(R);
+ return createError("Invalid ELF class");
}
SubtargetFeatures ELFObjectFileBase::getMIPSFeatures() const {
@@ -260,8 +262,7 @@ void ELFObjectFileBase::setARMSubArch(Triple &TheTriple) const {
std::string Triple;
// Default to ARM, but use the triple if it's been set.
- if (TheTriple.getArch() == Triple::thumb ||
- TheTriple.getArch() == Triple::thumbeb)
+ if (TheTriple.isThumb())
Triple = "thumb";
else
Triple = "arm";
diff --git a/contrib/llvm/lib/Object/IRObjectFile.cpp b/contrib/llvm/lib/Object/IRObjectFile.cpp
index e7807b038335..1ecb26d60bce 100644
--- a/contrib/llvm/lib/Object/IRObjectFile.cpp
+++ b/contrib/llvm/lib/Object/IRObjectFile.cpp
@@ -12,7 +12,6 @@
//===----------------------------------------------------------------------===//
#include "llvm/Object/IRObjectFile.h"
-#include "RecordStreamer.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/BinaryFormat/Magic.h"
#include "llvm/Bitcode/BitcodeReader.h"
@@ -20,17 +19,8 @@
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Mangler.h"
#include "llvm/IR/Module.h"
-#include "llvm/MC/MCAsmInfo.h"
-#include "llvm/MC/MCContext.h"
-#include "llvm/MC/MCInstrInfo.h"
-#include "llvm/MC/MCObjectFileInfo.h"
-#include "llvm/MC/MCParser/MCAsmParser.h"
-#include "llvm/MC/MCParser/MCTargetAsmParser.h"
-#include "llvm/MC/MCRegisterInfo.h"
-#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
@@ -82,20 +72,22 @@ StringRef IRObjectFile::getTargetTriple() const {
return Mods[0]->getTargetTriple();
}
-ErrorOr<MemoryBufferRef> IRObjectFile::findBitcodeInObject(const ObjectFile &Obj) {
+Expected<MemoryBufferRef>
+IRObjectFile::findBitcodeInObject(const ObjectFile &Obj) {
for (const SectionRef &Sec : Obj.sections()) {
if (Sec.isBitcode()) {
StringRef SecContents;
if (std::error_code EC = Sec.getContents(SecContents))
- return EC;
+ return errorCodeToError(EC);
return MemoryBufferRef(SecContents, Obj.getFileName());
}
}
- return object_error::bitcode_section_not_found;
+ return errorCodeToError(object_error::bitcode_section_not_found);
}
-ErrorOr<MemoryBufferRef> IRObjectFile::findBitcodeInMemBuffer(MemoryBufferRef Object) {
+Expected<MemoryBufferRef>
+IRObjectFile::findBitcodeInMemBuffer(MemoryBufferRef Object) {
file_magic Type = identify_magic(Object.getBuffer());
switch (Type) {
case file_magic::bitcode:
@@ -106,19 +98,19 @@ ErrorOr<MemoryBufferRef> IRObjectFile::findBitcodeInMemBuffer(MemoryBufferRef Ob
Expected<std::unique_ptr<ObjectFile>> ObjFile =
ObjectFile::createObjectFile(Object, Type);
if (!ObjFile)
- return errorToErrorCode(ObjFile.takeError());
+ return ObjFile.takeError();
return findBitcodeInObject(*ObjFile->get());
}
default:
- return object_error::invalid_file_type;
+ return errorCodeToError(object_error::invalid_file_type);
}
}
Expected<std::unique_ptr<IRObjectFile>>
IRObjectFile::create(MemoryBufferRef Object, LLVMContext &Context) {
- ErrorOr<MemoryBufferRef> BCOrErr = findBitcodeInMemBuffer(Object);
+ Expected<MemoryBufferRef> BCOrErr = findBitcodeInMemBuffer(Object);
if (!BCOrErr)
- return errorCodeToError(BCOrErr.getError());
+ return BCOrErr.takeError();
Expected<std::vector<BitcodeModule>> BMsOrErr =
getBitcodeModuleList(*BCOrErr);
@@ -142,10 +134,10 @@ IRObjectFile::create(MemoryBufferRef Object, LLVMContext &Context) {
Expected<IRSymtabFile> object::readIRSymtab(MemoryBufferRef MBRef) {
IRSymtabFile F;
- ErrorOr<MemoryBufferRef> BCOrErr =
+ Expected<MemoryBufferRef> BCOrErr =
IRObjectFile::findBitcodeInMemBuffer(MBRef);
if (!BCOrErr)
- return errorCodeToError(BCOrErr.getError());
+ return BCOrErr.takeError();
Expected<BitcodeFileContents> BFCOrErr = getBitcodeFileContents(*BCOrErr);
if (!BFCOrErr)
diff --git a/contrib/llvm/lib/Object/IRSymtab.cpp b/contrib/llvm/lib/Object/IRSymtab.cpp
index 7a6424a76a98..2d8d3f7c0878 100644
--- a/contrib/llvm/lib/Object/IRSymtab.cpp
+++ b/contrib/llvm/lib/Object/IRSymtab.cpp
@@ -72,7 +72,7 @@ struct Builder {
BumpPtrAllocator &Alloc)
: Symtab(Symtab), StrtabBuilder(StrtabBuilder), Saver(Alloc) {}
- DenseMap<const Comdat *, unsigned> ComdatMap;
+ DenseMap<const Comdat *, int> ComdatMap;
Mangler Mang;
Triple TT;
@@ -97,6 +97,8 @@ struct Builder {
reinterpret_cast<const char *>(Objs.data() + Objs.size()));
}
+ Expected<int> getComdatIndex(const Comdat *C, const Module *M);
+
Error addModule(Module *M);
Error addSymbol(const ModuleSymbolTable &Msymtab,
const SmallPtrSet<GlobalValue *, 8> &Used,
@@ -140,6 +142,35 @@ Error Builder::addModule(Module *M) {
return Error::success();
}
+Expected<int> Builder::getComdatIndex(const Comdat *C, const Module *M) {
+ auto P = ComdatMap.insert(std::make_pair(C, Comdats.size()));
+ if (P.second) {
+ std::string Name;
+ if (TT.isOSBinFormatCOFF()) {
+ const GlobalValue *GV = M->getNamedValue(C->getName());
+ if (!GV)
+ return make_error<StringError>("Could not find leader",
+ inconvertibleErrorCode());
+ // Internal leaders do not affect symbol resolution, therefore they do not
+ // appear in the symbol table.
+ if (GV->hasLocalLinkage()) {
+ P.first->second = -1;
+ return -1;
+ }
+ llvm::raw_string_ostream OS(Name);
+ Mang.getNameWithPrefix(OS, GV, false);
+ } else {
+ Name = C->getName();
+ }
+
+ storage::Comdat Comdat;
+ setStr(Comdat.Name, Saver.save(Name));
+ Comdats.push_back(Comdat);
+ }
+
+ return P.first->second;
+}
+
Error Builder::addSymbol(const ModuleSymbolTable &Msymtab,
const SmallPtrSet<GlobalValue *, 8> &Used,
ModuleSymbolTable::Symbol Msym) {
@@ -156,6 +187,7 @@ Error Builder::addSymbol(const ModuleSymbolTable &Msymtab,
Unc = &Uncommons.back();
*Unc = {};
setStr(Unc->COFFWeakExternFallbackName, "");
+ setStr(Unc->SectionName, "");
return *Unc;
};
@@ -215,14 +247,10 @@ Error Builder::addSymbol(const ModuleSymbolTable &Msymtab,
return make_error<StringError>("Unable to determine comdat of alias!",
inconvertibleErrorCode());
if (const Comdat *C = Base->getComdat()) {
- auto P = ComdatMap.insert(std::make_pair(C, Comdats.size()));
- Sym.ComdatIndex = P.first->second;
-
- if (P.second) {
- storage::Comdat Comdat;
- setStr(Comdat.Name, C->getName());
- Comdats.push_back(Comdat);
- }
+ Expected<int> ComdatIndexOrErr = getComdatIndex(C, GV->getParent());
+ if (!ComdatIndexOrErr)
+ return ComdatIndexOrErr.takeError();
+ Sym.ComdatIndex = *ComdatIndexOrErr;
}
if (TT.isOSBinFormatCOFF()) {
@@ -230,16 +258,22 @@ Error Builder::addSymbol(const ModuleSymbolTable &Msymtab,
if ((Flags & object::BasicSymbolRef::SF_Weak) &&
(Flags & object::BasicSymbolRef::SF_Indirect)) {
+ auto *Fallback = dyn_cast<GlobalValue>(
+ cast<GlobalAlias>(GV)->getAliasee()->stripPointerCasts());
+ if (!Fallback)
+ return make_error<StringError>("Invalid weak external",
+ inconvertibleErrorCode());
std::string FallbackName;
raw_string_ostream OS(FallbackName);
- Msymtab.printSymbolName(
- OS, cast<GlobalValue>(
- cast<GlobalAlias>(GV)->getAliasee()->stripPointerCasts()));
+ Msymtab.printSymbolName(OS, Fallback);
OS.flush();
setStr(Uncommon().COFFWeakExternFallbackName, Saver.save(FallbackName));
}
}
+ if (!Base->getSection().empty())
+ setStr(Uncommon().SectionName, Saver.save(Base->getSection()));
+
return Error::success();
}
diff --git a/contrib/llvm/lib/Object/MachOObjectFile.cpp b/contrib/llvm/lib/Object/MachOObjectFile.cpp
index 2e4da9f15aa1..2e3415618e5f 100644
--- a/contrib/llvm/lib/Object/MachOObjectFile.cpp
+++ b/contrib/llvm/lib/Object/MachOObjectFile.cpp
@@ -16,7 +16,6 @@
#include "llvm/ADT/None.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/ADT/Triple.h"
@@ -59,10 +58,9 @@ namespace {
} // end anonymous namespace
-static Error
-malformedError(Twine Msg) {
- std::string StringMsg = "truncated or malformed object (" + Msg.str() + ")";
- return make_error<GenericBinaryError>(std::move(StringMsg),
+static Error malformedError(const Twine &Msg) {
+ return make_error<GenericBinaryError>("truncated or malformed object (" +
+ Msg + ")",
object_error::parse_failed);
}
@@ -185,6 +183,9 @@ static Expected<MachOObjectFile::LoadCommandInfo>
getLoadCommandInfo(const MachOObjectFile &Obj, const char *Ptr,
uint32_t LoadCommandIndex) {
if (auto CmdOrErr = getStructOrErr<MachO::load_command>(Obj, Ptr)) {
+ if (CmdOrErr->cmdsize + Ptr > Obj.getData().end())
+ return malformedError("load command " + Twine(LoadCommandIndex) +
+ " extends past end of file");
if (CmdOrErr->cmdsize < 8)
return malformedError("load command " + Twine(LoadCommandIndex) +
" with size less than 8 bytes");
@@ -476,8 +477,8 @@ static Error checkDysymtabCommand(const MachOObjectFile &Obj,
"the file");
if (Error Err = checkOverlappingElement(Elements, Dysymtab.tocoff,
Dysymtab.ntoc * sizeof(struct
- MachO::dylib_table_of_contents),
- "table of contents"))
+ MachO::dylib_table_of_contents),
+ "table of contents"))
return Err;
if (Dysymtab.modtaboff > FileSize)
return malformedError("modtaboff field of LC_DYSYMTAB command " +
@@ -502,7 +503,7 @@ static Error checkDysymtabCommand(const MachOObjectFile &Obj,
"past the end of the file");
if (Error Err = checkOverlappingElement(Elements, Dysymtab.modtaboff,
Dysymtab.nmodtab * sizeof_modtab,
- "module table"))
+ "module table"))
return Err;
if (Dysymtab.extrefsymoff > FileSize)
return malformedError("extrefsymoff field of LC_DYSYMTAB command " +
@@ -518,8 +519,8 @@ static Error checkDysymtabCommand(const MachOObjectFile &Obj,
"past the end of the file");
if (Error Err = checkOverlappingElement(Elements, Dysymtab.extrefsymoff,
Dysymtab.nextrefsyms *
- sizeof(MachO::dylib_reference),
- "reference table"))
+ sizeof(MachO::dylib_reference),
+ "reference table"))
return Err;
if (Dysymtab.indirectsymoff > FileSize)
return malformedError("indirectsymoff field of LC_DYSYMTAB command " +
@@ -536,7 +537,7 @@ static Error checkDysymtabCommand(const MachOObjectFile &Obj,
if (Error Err = checkOverlappingElement(Elements, Dysymtab.indirectsymoff,
Dysymtab.nindirectsyms *
sizeof(uint32_t),
- "indirect table"))
+ "indirect table"))
return Err;
if (Dysymtab.extreloff > FileSize)
return malformedError("extreloff field of LC_DYSYMTAB command " +
@@ -552,8 +553,8 @@ static Error checkDysymtabCommand(const MachOObjectFile &Obj,
"the file");
if (Error Err = checkOverlappingElement(Elements, Dysymtab.extreloff,
Dysymtab.nextrel *
- sizeof(MachO::relocation_info),
- "external relocation table"))
+ sizeof(MachO::relocation_info),
+ "external relocation table"))
return Err;
if (Dysymtab.locreloff > FileSize)
return malformedError("locreloff field of LC_DYSYMTAB command " +
@@ -569,8 +570,8 @@ static Error checkDysymtabCommand(const MachOObjectFile &Obj,
"the file");
if (Error Err = checkOverlappingElement(Elements, Dysymtab.locreloff,
Dysymtab.nlocrel *
- sizeof(MachO::relocation_info),
- "local relocation table"))
+ sizeof(MachO::relocation_info),
+ "local relocation table"))
return Err;
*DysymtabLoadCmd = Load.Ptr;
return Error::success();
@@ -802,7 +803,7 @@ static Error checkNoteCommand(const MachOObjectFile &Obj,
uint32_t LoadCommandIndex,
std::list<MachOElement> &Elements) {
if (Load.C.cmdsize != sizeof(MachO::note_command))
- return malformedError("load command " + Twine(LoadCommandIndex) +
+ return malformedError("load command " + Twine(LoadCommandIndex) +
" LC_NOTE has incorrect cmdsize");
MachO::note_command Nt = getStruct<MachO::note_command>(Obj, Load.Ptr);
uint64_t FileSize = Obj.getData().size();
@@ -1114,7 +1115,7 @@ static Error checkTwoLevelHintsCommand(const MachOObjectFile &Obj,
Twine(LoadCommandIndex) + " extends past the end of "
"the file");
uint64_t BigSize = Hints.nhints;
- BigSize *= Hints.nhints * sizeof(MachO::twolevel_hint);
+ BigSize *= sizeof(MachO::twolevel_hint);
BigSize += Hints.offset;
if (BigSize > FileSize)
return malformedError("offset field plus nhints times sizeof(struct "
@@ -1927,6 +1928,12 @@ bool MachOObjectFile::isSectionBitcode(DataRefImpl Sec) const {
return false;
}
+bool MachOObjectFile::isSectionStripped(DataRefImpl Sec) const {
+ if (is64Bit())
+ return getSection64(Sec).offset == 0;
+ return getSection(Sec).offset == 0;
+}
+
relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const {
DataRefImpl Ret;
Ret.d.a = Sec.d.a;
@@ -1953,6 +1960,7 @@ MachOObjectFile::section_rel_end(DataRefImpl Sec) const {
relocation_iterator MachOObjectFile::extrel_begin() const {
DataRefImpl Ret;
+ // for DYSYMTAB symbols, Ret.d.a == 0 for external relocations
Ret.d.a = 0; // Would normally be a section index.
Ret.d.b = 0; // Index into the external relocations
return relocation_iterator(RelocationRef(Ret, this));
@@ -1961,11 +1969,29 @@ relocation_iterator MachOObjectFile::extrel_begin() const {
relocation_iterator MachOObjectFile::extrel_end() const {
MachO::dysymtab_command DysymtabLoadCmd = getDysymtabLoadCommand();
DataRefImpl Ret;
+ // for DYSYMTAB symbols, Ret.d.a == 0 for external relocations
Ret.d.a = 0; // Would normally be a section index.
Ret.d.b = DysymtabLoadCmd.nextrel; // Index into the external relocations
return relocation_iterator(RelocationRef(Ret, this));
}
+relocation_iterator MachOObjectFile::locrel_begin() const {
+ DataRefImpl Ret;
+ // for DYSYMTAB symbols, Ret.d.a == 1 for local relocations
+ Ret.d.a = 1; // Would normally be a section index.
+ Ret.d.b = 0; // Index into the local relocations
+ return relocation_iterator(RelocationRef(Ret, this));
+}
+
+relocation_iterator MachOObjectFile::locrel_end() const {
+ MachO::dysymtab_command DysymtabLoadCmd = getDysymtabLoadCommand();
+ DataRefImpl Ret;
+ // for DYSYMTAB symbols, Ret.d.a == 1 for local relocations
+ Ret.d.a = 1; // Would normally be a section index.
+ Ret.d.b = DysymtabLoadCmd.nlocrel; // Index into the local relocations
+ return relocation_iterator(RelocationRef(Ret, this));
+}
+
void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
++Rel.d.b;
}
@@ -2566,7 +2592,7 @@ bool MachOObjectFile::isValidArch(StringRef ArchFlag) {
.Default(false);
}
-unsigned MachOObjectFile::getArch() const {
+Triple::ArchType MachOObjectFile::getArch() const {
return getArch(getCPUType(*this));
}
@@ -2607,10 +2633,14 @@ dice_iterator MachOObjectFile::end_dices() const {
return dice_iterator(DiceRef(DRI, this));
}
-ExportEntry::ExportEntry(ArrayRef<uint8_t> T) : Trie(T) {}
+ExportEntry::ExportEntry(Error *E, const MachOObjectFile *O,
+ ArrayRef<uint8_t> T) : E(E), O(O), Trie(T) {}
void ExportEntry::moveToFirst() {
+ ErrorAsOutParameter ErrAsOutParam(E);
pushNode(0);
+ if (*E)
+ return;
pushDownUntilBottom();
}
@@ -2637,14 +2667,12 @@ bool ExportEntry::operator==(const ExportEntry &Other) const {
return true;
}
-uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr) {
+uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr, const char **error) {
unsigned Count;
- uint64_t Result = decodeULEB128(Ptr, &Count);
+ uint64_t Result = decodeULEB128(Ptr, &Count, Trie.end(), error);
Ptr += Count;
- if (Ptr > Trie.end()) {
+ if (Ptr > Trie.end())
Ptr = Trie.end();
- Malformed = true;
- }
return Result;
}
@@ -2679,24 +2707,134 @@ ExportEntry::NodeState::NodeState(const uint8_t *Ptr)
: Start(Ptr), Current(Ptr) {}
void ExportEntry::pushNode(uint64_t offset) {
+ ErrorAsOutParameter ErrAsOutParam(E);
const uint8_t *Ptr = Trie.begin() + offset;
NodeState State(Ptr);
- uint64_t ExportInfoSize = readULEB128(State.Current);
+ const char *error;
+ uint64_t ExportInfoSize = readULEB128(State.Current, &error);
+ if (error) {
+ *E = malformedError("export info size " + Twine(error) +
+ " in export trie data at node: 0x" +
+ Twine::utohexstr(offset));
+ moveToEnd();
+ return;
+ }
State.IsExportNode = (ExportInfoSize != 0);
const uint8_t* Children = State.Current + ExportInfoSize;
+ if (Children > Trie.end()) {
+ *E = malformedError(
+ "export info size: 0x" + Twine::utohexstr(ExportInfoSize) +
+ " in export trie data at node: 0x" + Twine::utohexstr(offset) +
+ " too big and extends past end of trie data");
+ moveToEnd();
+ return;
+ }
if (State.IsExportNode) {
- State.Flags = readULEB128(State.Current);
+ const uint8_t *ExportStart = State.Current;
+ State.Flags = readULEB128(State.Current, &error);
+ if (error) {
+ *E = malformedError("flags " + Twine(error) +
+ " in export trie data at node: 0x" +
+ Twine::utohexstr(offset));
+ moveToEnd();
+ return;
+ }
+ uint64_t Kind = State.Flags & MachO::EXPORT_SYMBOL_FLAGS_KIND_MASK;
+ if (State.Flags != 0 &&
+ (Kind != MachO::EXPORT_SYMBOL_FLAGS_KIND_REGULAR &&
+ Kind != MachO::EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE &&
+ Kind != MachO::EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL)) {
+ *E = malformedError(
+ "unsupported exported symbol kind: " + Twine((int)Kind) +
+ " in flags: 0x" + Twine::utohexstr(State.Flags) +
+ " in export trie data at node: 0x" + Twine::utohexstr(offset));
+ moveToEnd();
+ return;
+ }
if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) {
State.Address = 0;
- State.Other = readULEB128(State.Current); // dylib ordinal
+ State.Other = readULEB128(State.Current, &error); // dylib ordinal
+ if (error) {
+ *E = malformedError("dylib ordinal of re-export " + Twine(error) +
+ " in export trie data at node: 0x" +
+ Twine::utohexstr(offset));
+ moveToEnd();
+ return;
+ }
+ if (O != nullptr) {
+ if (State.Other > O->getLibraryCount()) {
+ *E = malformedError(
+ "bad library ordinal: " + Twine((int)State.Other) + " (max " +
+ Twine((int)O->getLibraryCount()) +
+ ") in export trie data at node: 0x" + Twine::utohexstr(offset));
+ moveToEnd();
+ return;
+ }
+ }
State.ImportName = reinterpret_cast<const char*>(State.Current);
+ if (*State.ImportName == '\0') {
+ State.Current++;
+ } else {
+ const uint8_t *End = State.Current + 1;
+ if (End >= Trie.end()) {
+ *E = malformedError("import name of re-export in export trie data at "
+ "node: 0x" +
+ Twine::utohexstr(offset) +
+ " starts past end of trie data");
+ moveToEnd();
+ return;
+ }
+ while(*End != '\0' && End < Trie.end())
+ End++;
+ if (*End != '\0') {
+ *E = malformedError("import name of re-export in export trie data at "
+ "node: 0x" +
+ Twine::utohexstr(offset) +
+ " extends past end of trie data");
+ moveToEnd();
+ return;
+ }
+ State.Current = End + 1;
+ }
} else {
- State.Address = readULEB128(State.Current);
- if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER)
- State.Other = readULEB128(State.Current);
+ State.Address = readULEB128(State.Current, &error);
+ if (error) {
+ *E = malformedError("address " + Twine(error) +
+ " in export trie data at node: 0x" +
+ Twine::utohexstr(offset));
+ moveToEnd();
+ return;
+ }
+ if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER) {
+ State.Other = readULEB128(State.Current, &error);
+ if (error) {
+ *E = malformedError("resolver of stub and resolver " + Twine(error) +
+ " in export trie data at node: 0x" +
+ Twine::utohexstr(offset));
+ moveToEnd();
+ return;
+ }
+ }
+ }
+ if(ExportStart + ExportInfoSize != State.Current) {
+ *E = malformedError(
+ "inconsistant export info size: 0x" +
+ Twine::utohexstr(ExportInfoSize) + " where actual size was: 0x" +
+ Twine::utohexstr(State.Current - ExportStart) +
+ " in export trie data at node: 0x" + Twine::utohexstr(offset));
+ moveToEnd();
+ return;
}
}
State.ChildCount = *Children;
+ if (State.ChildCount != 0 && Children + 1 >= Trie.end()) {
+ *E = malformedError("byte for count of childern in export trie data at "
+ "node: 0x" +
+ Twine::utohexstr(offset) +
+ " extends past end of trie data");
+ moveToEnd();
+ return;
+ }
State.Current = Children + 1;
State.NextChildIndex = 0;
State.ParentStringLength = CumulativeString.size();
@@ -2704,21 +2842,53 @@ void ExportEntry::pushNode(uint64_t offset) {
}
void ExportEntry::pushDownUntilBottom() {
+ ErrorAsOutParameter ErrAsOutParam(E);
+ const char *error;
while (Stack.back().NextChildIndex < Stack.back().ChildCount) {
NodeState &Top = Stack.back();
CumulativeString.resize(Top.ParentStringLength);
- for (;*Top.Current != 0; Top.Current++) {
+ for (;*Top.Current != 0 && Top.Current < Trie.end(); Top.Current++) {
char C = *Top.Current;
CumulativeString.push_back(C);
}
+ if (Top.Current >= Trie.end()) {
+ *E = malformedError("edge sub-string in export trie data at node: 0x" +
+ Twine::utohexstr(Top.Start - Trie.begin()) +
+ " for child #" + Twine((int)Top.NextChildIndex) +
+ " extends past end of trie data");
+ moveToEnd();
+ return;
+ }
Top.Current += 1;
- uint64_t childNodeIndex = readULEB128(Top.Current);
+ uint64_t childNodeIndex = readULEB128(Top.Current, &error);
+ if (error) {
+ *E = malformedError("child node offset " + Twine(error) +
+ " in export trie data at node: 0x" +
+ Twine::utohexstr(Top.Start - Trie.begin()));
+ moveToEnd();
+ return;
+ }
+ for (const NodeState &node : nodes()) {
+ if (node.Start == Trie.begin() + childNodeIndex){
+ *E = malformedError("loop in childern in export trie data at node: 0x" +
+ Twine::utohexstr(Top.Start - Trie.begin()) +
+ " back to node: 0x" +
+ Twine::utohexstr(childNodeIndex));
+ moveToEnd();
+ return;
+ }
+ }
Top.NextChildIndex += 1;
pushNode(childNodeIndex);
+ if (*E)
+ return;
}
if (!Stack.back().IsExportNode) {
- Malformed = true;
+ *E = malformedError("node is not an export node in export trie data at "
+ "node: 0x" +
+ Twine::utohexstr(Stack.back().Start - Trie.begin()));
moveToEnd();
+ return;
}
}
@@ -2738,8 +2908,11 @@ void ExportEntry::pushDownUntilBottom() {
// stack ivar. If there is no more ways down, it pops up one and tries to go
// down a sibling path until a childless node is reached.
void ExportEntry::moveNext() {
- if (Stack.empty() || !Stack.back().IsExportNode) {
- Malformed = true;
+ assert(!Stack.empty() && "ExportEntry::moveNext() with empty node stack");
+ if (!Stack.back().IsExportNode) {
+ *E = malformedError("node is not an export node in export trie data at "
+ "node: 0x" +
+ Twine::utohexstr(Stack.back().Start - Trie.begin()));
moveToEnd();
return;
}
@@ -2764,21 +2937,22 @@ void ExportEntry::moveNext() {
}
iterator_range<export_iterator>
-MachOObjectFile::exports(ArrayRef<uint8_t> Trie) {
- ExportEntry Start(Trie);
+MachOObjectFile::exports(Error &E, ArrayRef<uint8_t> Trie,
+ const MachOObjectFile *O) {
+ ExportEntry Start(&E, O, Trie);
if (Trie.empty())
Start.moveToEnd();
else
Start.moveToFirst();
- ExportEntry Finish(Trie);
+ ExportEntry Finish(&E, O, Trie);
Finish.moveToEnd();
return make_range(export_iterator(Start), export_iterator(Finish));
}
-iterator_range<export_iterator> MachOObjectFile::exports() const {
- return exports(getDyldInfoExportsTrie());
+iterator_range<export_iterator> MachOObjectFile::exports(Error &Err) const {
+ return exports(Err, getDyldInfoExportsTrie(), this);
}
MachORebaseEntry::MachORebaseEntry(Error *E, const MachOObjectFile *O,
@@ -2831,11 +3005,11 @@ void MachORebaseEntry::moveNext() {
case MachO::REBASE_OPCODE_SET_TYPE_IMM:
RebaseType = ImmValue;
if (RebaseType > MachO::REBASE_TYPE_TEXT_PCREL32) {
- *E = malformedError("for REBASE_OPCODE_SET_TYPE_IMM bad bind type: " +
- Twine((int)RebaseType) + " for opcode at: 0x" +
- utohexstr(OpcodeStart - Opcodes.begin()));
- moveToEnd();
- return;
+ *E = malformedError("for REBASE_OPCODE_SET_TYPE_IMM bad bind type: " +
+ Twine((int)RebaseType) + " for opcode at: 0x" +
+ Twine::utohexstr(OpcodeStart - Opcodes.begin()));
+ moveToEnd();
+ return;
}
DEBUG_WITH_TYPE(
"mach-o-rebase",
@@ -2847,8 +3021,8 @@ void MachORebaseEntry::moveNext() {
SegmentOffset = readULEB128(&error);
if (error) {
*E = malformedError("for REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
- Twine(error) + " for opcode at: 0x" +
- utohexstr(OpcodeStart - Opcodes.begin()));
+ Twine(error) + " for opcode at: 0x" +
+ Twine::utohexstr(OpcodeStart - Opcodes.begin()));
moveToEnd();
return;
}
@@ -2856,8 +3030,8 @@ void MachORebaseEntry::moveNext() {
true);
if (error) {
*E = malformedError("for REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
- Twine(error) + " for opcode at: 0x" +
- utohexstr(OpcodeStart - Opcodes.begin()));
+ Twine(error) + " for opcode at: 0x" +
+ Twine::utohexstr(OpcodeStart - Opcodes.begin()));
moveToEnd();
return;
}
@@ -2871,18 +3045,18 @@ void MachORebaseEntry::moveNext() {
case MachO::REBASE_OPCODE_ADD_ADDR_ULEB:
SegmentOffset += readULEB128(&error);
if (error) {
- *E = malformedError("for REBASE_OPCODE_ADD_ADDR_ULEB " +
- Twine(error) + " for opcode at: 0x" +
- utohexstr(OpcodeStart - Opcodes.begin()));
+ *E = malformedError("for REBASE_OPCODE_ADD_ADDR_ULEB " + Twine(error) +
+ " for opcode at: 0x" +
+ Twine::utohexstr(OpcodeStart - Opcodes.begin()));
moveToEnd();
return;
}
error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset,
true);
if (error) {
- *E = malformedError("for REBASE_OPCODE_ADD_ADDR_ULEB " +
- Twine(error) + " for opcode at: 0x" +
- utohexstr(OpcodeStart - Opcodes.begin()));
+ *E = malformedError("for REBASE_OPCODE_ADD_ADDR_ULEB " + Twine(error) +
+ " for opcode at: 0x" +
+ Twine::utohexstr(OpcodeStart - Opcodes.begin()));
moveToEnd();
return;
}
@@ -2896,8 +3070,8 @@ void MachORebaseEntry::moveNext() {
true);
if (error) {
*E = malformedError("for REBASE_OPCODE_ADD_ADDR_IMM_SCALED " +
- Twine(error) + " for opcode at: 0x" +
- utohexstr(OpcodeStart - Opcodes.begin()));
+ Twine(error) + " for opcode at: 0x" +
+ Twine::utohexstr(OpcodeStart - Opcodes.begin()));
moveToEnd();
return;
}
@@ -2905,10 +3079,11 @@ void MachORebaseEntry::moveNext() {
error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset,
false);
if (error) {
- *E = malformedError("for REBASE_OPCODE_ADD_ADDR_IMM_SCALED "
- " (after adding immediate times the pointer size) " +
- Twine(error) + " for opcode at: 0x" +
- utohexstr(OpcodeStart - Opcodes.begin()));
+ *E =
+ malformedError("for REBASE_OPCODE_ADD_ADDR_IMM_SCALED "
+ " (after adding immediate times the pointer size) " +
+ Twine(error) + " for opcode at: 0x" +
+ Twine::utohexstr(OpcodeStart - Opcodes.begin()));
moveToEnd();
return;
}
@@ -2922,8 +3097,8 @@ void MachORebaseEntry::moveNext() {
true);
if (error) {
*E = malformedError("for REBASE_OPCODE_DO_REBASE_IMM_TIMES " +
- Twine(error) + " for opcode at: 0x" +
- utohexstr(OpcodeStart - Opcodes.begin()));
+ Twine(error) + " for opcode at: 0x" +
+ Twine::utohexstr(OpcodeStart - Opcodes.begin()));
moveToEnd();
return;
}
@@ -2937,11 +3112,11 @@ void MachORebaseEntry::moveNext() {
error = O->RebaseEntryCheckCountAndSkip(Count, Skip, PointerSize,
SegmentIndex, SegmentOffset);
if (error) {
- *E = malformedError("for REBASE_OPCODE_DO_REBASE_IMM_TIMES "
- + Twine(error) + " for opcode at: 0x" +
- utohexstr(OpcodeStart - Opcodes.begin()));
+ *E = malformedError("for REBASE_OPCODE_DO_REBASE_IMM_TIMES " +
+ Twine(error) + " for opcode at: 0x" +
+ Twine::utohexstr(OpcodeStart - Opcodes.begin()));
moveToEnd();
- return;
+ return;
}
DEBUG_WITH_TYPE(
"mach-o-rebase",
@@ -2956,8 +3131,8 @@ void MachORebaseEntry::moveNext() {
true);
if (error) {
*E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES " +
- Twine(error) + " for opcode at: 0x" +
- utohexstr(OpcodeStart - Opcodes.begin()));
+ Twine(error) + " for opcode at: 0x" +
+ Twine::utohexstr(OpcodeStart - Opcodes.begin()));
moveToEnd();
return;
}
@@ -2966,8 +3141,8 @@ void MachORebaseEntry::moveNext() {
Count = readULEB128(&error);
if (error) {
*E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES " +
- Twine(error) + " for opcode at: 0x" +
- utohexstr(OpcodeStart - Opcodes.begin()));
+ Twine(error) + " for opcode at: 0x" +
+ Twine::utohexstr(OpcodeStart - Opcodes.begin()));
moveToEnd();
return;
}
@@ -2978,11 +3153,11 @@ void MachORebaseEntry::moveNext() {
error = O->RebaseEntryCheckCountAndSkip(Count, Skip, PointerSize,
SegmentIndex, SegmentOffset);
if (error) {
- *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES "
- + Twine(error) + " for opcode at: 0x" +
- utohexstr(OpcodeStart - Opcodes.begin()));
+ *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES " +
+ Twine(error) + " for opcode at: 0x" +
+ Twine::utohexstr(OpcodeStart - Opcodes.begin()));
moveToEnd();
- return;
+ return;
}
DEBUG_WITH_TYPE(
"mach-o-rebase",
@@ -2997,16 +3172,16 @@ void MachORebaseEntry::moveNext() {
true);
if (error) {
*E = malformedError("for REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB " +
- Twine(error) + " for opcode at: 0x" +
- utohexstr(OpcodeStart - Opcodes.begin()));
+ Twine(error) + " for opcode at: 0x" +
+ Twine::utohexstr(OpcodeStart - Opcodes.begin()));
moveToEnd();
return;
}
Skip = readULEB128(&error);
if (error) {
*E = malformedError("for REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB " +
- Twine(error) + " for opcode at: 0x" +
- utohexstr(OpcodeStart - Opcodes.begin()));
+ Twine(error) + " for opcode at: 0x" +
+ Twine::utohexstr(OpcodeStart - Opcodes.begin()));
moveToEnd();
return;
}
@@ -3016,11 +3191,11 @@ void MachORebaseEntry::moveNext() {
error = O->RebaseEntryCheckCountAndSkip(Count, Skip, PointerSize,
SegmentIndex, SegmentOffset);
if (error) {
- *E = malformedError("for REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB "
- + Twine(error) + " for opcode at: 0x" +
- utohexstr(OpcodeStart - Opcodes.begin()));
+ *E = malformedError("for REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB " +
+ Twine(error) + " for opcode at: 0x" +
+ Twine::utohexstr(OpcodeStart - Opcodes.begin()));
moveToEnd();
- return;
+ return;
}
DEBUG_WITH_TYPE(
"mach-o-rebase",
@@ -3035,16 +3210,18 @@ void MachORebaseEntry::moveNext() {
true);
if (error) {
*E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"
- "ULEB " + Twine(error) + " for opcode at: 0x" +
- utohexstr(OpcodeStart - Opcodes.begin()));
+ "ULEB " +
+ Twine(error) + " for opcode at: 0x" +
+ Twine::utohexstr(OpcodeStart - Opcodes.begin()));
moveToEnd();
return;
}
Count = readULEB128(&error);
if (error) {
*E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"
- "ULEB " + Twine(error) + " for opcode at: 0x" +
- utohexstr(OpcodeStart - Opcodes.begin()));
+ "ULEB " +
+ Twine(error) + " for opcode at: 0x" +
+ Twine::utohexstr(OpcodeStart - Opcodes.begin()));
moveToEnd();
return;
}
@@ -3055,8 +3232,9 @@ void MachORebaseEntry::moveNext() {
Skip = readULEB128(&error);
if (error) {
*E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"
- "ULEB " + Twine(error) + " for opcode at: 0x" +
- utohexstr(OpcodeStart - Opcodes.begin()));
+ "ULEB " +
+ Twine(error) + " for opcode at: 0x" +
+ Twine::utohexstr(OpcodeStart - Opcodes.begin()));
moveToEnd();
return;
}
@@ -3066,10 +3244,11 @@ void MachORebaseEntry::moveNext() {
SegmentIndex, SegmentOffset);
if (error) {
*E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"
- "ULEB " + Twine(error) + " for opcode at: 0x" +
- utohexstr(OpcodeStart - Opcodes.begin()));
+ "ULEB " +
+ Twine(error) + " for opcode at: 0x" +
+ Twine::utohexstr(OpcodeStart - Opcodes.begin()));
moveToEnd();
- return;
+ return;
}
DEBUG_WITH_TYPE(
"mach-o-rebase",
@@ -3081,8 +3260,8 @@ void MachORebaseEntry::moveNext() {
return;
default:
*E = malformedError("bad rebase info (bad opcode value 0x" +
- utohexstr(Opcode) + " for opcode at: 0x" +
- utohexstr(OpcodeStart - Opcodes.begin()));
+ Twine::utohexstr(Opcode) + " for opcode at: 0x" +
+ Twine::utohexstr(OpcodeStart - Opcodes.begin()));
moveToEnd();
return;
}
@@ -3224,8 +3403,8 @@ void MachOBindEntry::moveNext() {
case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
if (TableKind == Kind::Weak) {
*E = malformedError("BIND_OPCODE_SET_DYLIB_ORDINAL_IMM not allowed in "
- "weak bind table for opcode at: 0x" +
- utohexstr(OpcodeStart - Opcodes.begin()));
+ "weak bind table for opcode at: 0x" +
+ Twine::utohexstr(OpcodeStart - Opcodes.begin()));
moveToEnd();
return;
}
@@ -3233,9 +3412,11 @@ void MachOBindEntry::moveNext() {
LibraryOrdinalSet = true;
if (ImmValue > O->getLibraryCount()) {
*E = malformedError("for BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB bad "
- "library ordinal: " + Twine((int)ImmValue) + " (max " +
- Twine((int)O->getLibraryCount()) + ") for opcode at: 0x" +
- utohexstr(OpcodeStart - Opcodes.begin()));
+ "library ordinal: " +
+ Twine((int)ImmValue) + " (max " +
+ Twine((int)O->getLibraryCount()) +
+ ") for opcode at: 0x" +
+ Twine::utohexstr(OpcodeStart - Opcodes.begin()));
moveToEnd();
return;
}
@@ -3247,8 +3428,8 @@ void MachOBindEntry::moveNext() {
case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
if (TableKind == Kind::Weak) {
*E = malformedError("BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB not allowed in "
- "weak bind table for opcode at: 0x" +
- utohexstr(OpcodeStart - Opcodes.begin()));
+ "weak bind table for opcode at: 0x" +
+ Twine::utohexstr(OpcodeStart - Opcodes.begin()));
moveToEnd();
return;
}
@@ -3256,16 +3437,18 @@ void MachOBindEntry::moveNext() {
LibraryOrdinalSet = true;
if (error) {
*E = malformedError("for BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB " +
- Twine(error) + " for opcode at: 0x" +
- utohexstr(OpcodeStart - Opcodes.begin()));
+ Twine(error) + " for opcode at: 0x" +
+ Twine::utohexstr(OpcodeStart - Opcodes.begin()));
moveToEnd();
return;
}
if (Ordinal > (int)O->getLibraryCount()) {
*E = malformedError("for BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB bad "
- "library ordinal: " + Twine((int)Ordinal) + " (max " +
- Twine((int)O->getLibraryCount()) + ") for opcode at: 0x" +
- utohexstr(OpcodeStart - Opcodes.begin()));
+ "library ordinal: " +
+ Twine((int)Ordinal) + " (max " +
+ Twine((int)O->getLibraryCount()) +
+ ") for opcode at: 0x" +
+ Twine::utohexstr(OpcodeStart - Opcodes.begin()));
moveToEnd();
return;
}
@@ -3277,8 +3460,8 @@ void MachOBindEntry::moveNext() {
case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
if (TableKind == Kind::Weak) {
*E = malformedError("BIND_OPCODE_SET_DYLIB_SPECIAL_IMM not allowed in "
- "weak bind table for opcode at: 0x" +
- utohexstr(OpcodeStart - Opcodes.begin()));
+ "weak bind table for opcode at: 0x" +
+ Twine::utohexstr(OpcodeStart - Opcodes.begin()));
moveToEnd();
return;
}
@@ -3287,8 +3470,9 @@ void MachOBindEntry::moveNext() {
Ordinal = SignExtended;
if (Ordinal < MachO::BIND_SPECIAL_DYLIB_FLAT_LOOKUP) {
*E = malformedError("for BIND_OPCODE_SET_DYLIB_SPECIAL_IMM unknown "
- "special ordinal: " + Twine((int)Ordinal) + " for opcode at: "
- "0x" + utohexstr(OpcodeStart - Opcodes.begin()));
+ "special ordinal: " +
+ Twine((int)Ordinal) + " for opcode at: 0x" +
+ Twine::utohexstr(OpcodeStart - Opcodes.begin()));
moveToEnd();
return;
}
@@ -3307,11 +3491,12 @@ void MachOBindEntry::moveNext() {
++Ptr;
}
if (Ptr == Opcodes.end()) {
- *E = malformedError("for BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM "
- "symbol name extends past opcodes for opcode at: 0x" +
- utohexstr(OpcodeStart - Opcodes.begin()));
- moveToEnd();
- return;
+ *E = malformedError(
+ "for BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM "
+ "symbol name extends past opcodes for opcode at: 0x" +
+ Twine::utohexstr(OpcodeStart - Opcodes.begin()));
+ moveToEnd();
+ return;
}
SymbolName = StringRef(reinterpret_cast<const char*>(SymStart),
Ptr-SymStart);
@@ -3328,11 +3513,11 @@ void MachOBindEntry::moveNext() {
case MachO::BIND_OPCODE_SET_TYPE_IMM:
BindType = ImmValue;
if (ImmValue > MachO::BIND_TYPE_TEXT_PCREL32) {
- *E = malformedError("for BIND_OPCODE_SET_TYPE_IMM bad bind type: " +
- Twine((int)ImmValue) + " for opcode at: 0x" +
- utohexstr(OpcodeStart - Opcodes.begin()));
- moveToEnd();
- return;
+ *E = malformedError("for BIND_OPCODE_SET_TYPE_IMM bad bind type: " +
+ Twine((int)ImmValue) + " for opcode at: 0x" +
+ Twine::utohexstr(OpcodeStart - Opcodes.begin()));
+ moveToEnd();
+ return;
}
DEBUG_WITH_TYPE(
"mach-o-bind",
@@ -3342,9 +3527,9 @@ void MachOBindEntry::moveNext() {
case MachO::BIND_OPCODE_SET_ADDEND_SLEB:
Addend = readSLEB128(&error);
if (error) {
- *E = malformedError("for BIND_OPCODE_SET_ADDEND_SLEB " +
- Twine(error) + " for opcode at: 0x" +
- utohexstr(OpcodeStart - Opcodes.begin()));
+ *E = malformedError("for BIND_OPCODE_SET_ADDEND_SLEB " + Twine(error) +
+ " for opcode at: 0x" +
+ Twine::utohexstr(OpcodeStart - Opcodes.begin()));
moveToEnd();
return;
}
@@ -3358,16 +3543,16 @@ void MachOBindEntry::moveNext() {
SegmentOffset = readULEB128(&error);
if (error) {
*E = malformedError("for BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
- Twine(error) + " for opcode at: 0x" +
- utohexstr(OpcodeStart - Opcodes.begin()));
+ Twine(error) + " for opcode at: 0x" +
+ Twine::utohexstr(OpcodeStart - Opcodes.begin()));
moveToEnd();
return;
}
error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, true);
if (error) {
*E = malformedError("for BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
- Twine(error) + " for opcode at: 0x" +
- utohexstr(OpcodeStart - Opcodes.begin()));
+ Twine(error) + " for opcode at: 0x" +
+ Twine::utohexstr(OpcodeStart - Opcodes.begin()));
moveToEnd();
return;
}
@@ -3381,17 +3566,17 @@ void MachOBindEntry::moveNext() {
case MachO::BIND_OPCODE_ADD_ADDR_ULEB:
SegmentOffset += readULEB128(&error);
if (error) {
- *E = malformedError("for BIND_OPCODE_ADD_ADDR_ULEB " +
- Twine(error) + " for opcode at: 0x" +
- utohexstr(OpcodeStart - Opcodes.begin()));
+ *E = malformedError("for BIND_OPCODE_ADD_ADDR_ULEB " + Twine(error) +
+ " for opcode at: 0x" +
+ Twine::utohexstr(OpcodeStart - Opcodes.begin()));
moveToEnd();
return;
}
error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, true);
if (error) {
- *E = malformedError("for BIND_OPCODE_ADD_ADDR_ULEB " +
- Twine(error) + " for opcode at: 0x" +
- utohexstr(OpcodeStart - Opcodes.begin()));
+ *E = malformedError("for BIND_OPCODE_ADD_ADDR_ULEB " + Twine(error) +
+ " for opcode at: 0x" +
+ Twine::utohexstr(OpcodeStart - Opcodes.begin()));
moveToEnd();
return;
}
@@ -3406,21 +3591,24 @@ void MachOBindEntry::moveNext() {
error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, true);
if (error) {
*E = malformedError("for BIND_OPCODE_DO_BIND " + Twine(error) +
- " for opcode at: 0x" + utohexstr(OpcodeStart - Opcodes.begin()));
+ " for opcode at: 0x" +
+ Twine::utohexstr(OpcodeStart - Opcodes.begin()));
moveToEnd();
return;
}
if (SymbolName == StringRef()) {
- *E = malformedError("for BIND_OPCODE_DO_BIND missing preceding "
- "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for opcode at: 0x" +
- utohexstr(OpcodeStart - Opcodes.begin()));
+ *E = malformedError(
+ "for BIND_OPCODE_DO_BIND missing preceding "
+ "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for opcode at: 0x" +
+ Twine::utohexstr(OpcodeStart - Opcodes.begin()));
moveToEnd();
return;
}
if (!LibraryOrdinalSet && TableKind != Kind::Weak) {
- *E = malformedError("for BIND_OPCODE_DO_BIND missing preceding "
- "BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode at: 0x" +
- utohexstr(OpcodeStart - Opcodes.begin()));
+ *E =
+ malformedError("for BIND_OPCODE_DO_BIND missing preceding "
+ "BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode at: 0x" +
+ Twine::utohexstr(OpcodeStart - Opcodes.begin()));
moveToEnd();
return;
}
@@ -3432,38 +3620,41 @@ void MachOBindEntry::moveNext() {
case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
if (TableKind == Kind::Lazy) {
*E = malformedError("BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB not allowed in "
- "lazy bind table for opcode at: 0x" +
- utohexstr(OpcodeStart - Opcodes.begin()));
+ "lazy bind table for opcode at: 0x" +
+ Twine::utohexstr(OpcodeStart - Opcodes.begin()));
moveToEnd();
return;
}
error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, true);
if (error) {
*E = malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB " +
- Twine(error) + " for opcode at: 0x" +
- utohexstr(OpcodeStart - Opcodes.begin()));
+ Twine(error) + " for opcode at: 0x" +
+ Twine::utohexstr(OpcodeStart - Opcodes.begin()));
moveToEnd();
return;
}
if (SymbolName == StringRef()) {
- *E = malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB missing "
- "preceding BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for opcode "
- "at: 0x" + utohexstr(OpcodeStart - Opcodes.begin()));
+ *E = malformedError(
+ "for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB missing "
+ "preceding BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for opcode "
+ "at: 0x" +
+ Twine::utohexstr(OpcodeStart - Opcodes.begin()));
moveToEnd();
return;
}
if (!LibraryOrdinalSet && TableKind != Kind::Weak) {
- *E = malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB missing "
- "preceding BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode at: 0x" +
- utohexstr(OpcodeStart - Opcodes.begin()));
+ *E = malformedError(
+ "for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB missing "
+ "preceding BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode at: 0x" +
+ Twine::utohexstr(OpcodeStart - Opcodes.begin()));
moveToEnd();
return;
}
AdvanceAmount = readULEB128(&error) + PointerSize;
if (error) {
*E = malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB " +
- Twine(error) + " for opcode at: 0x" +
- utohexstr(OpcodeStart - Opcodes.begin()));
+ Twine(error) + " for opcode at: 0x" +
+ Twine::utohexstr(OpcodeStart - Opcodes.begin()));
moveToEnd();
return;
}
@@ -3474,8 +3665,9 @@ void MachOBindEntry::moveNext() {
AdvanceAmount, false);
if (error) {
*E = malformedError("for BIND_OPCODE_ADD_ADDR_ULEB (after adding "
- "ULEB) " + Twine(error) + " for opcode at: 0x" +
- utohexstr(OpcodeStart - Opcodes.begin()));
+ "ULEB) " +
+ Twine(error) + " for opcode at: 0x" +
+ Twine::utohexstr(OpcodeStart - Opcodes.begin()));
moveToEnd();
return;
}
@@ -3491,30 +3683,34 @@ void MachOBindEntry::moveNext() {
case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
if (TableKind == Kind::Lazy) {
*E = malformedError("BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED not "
- "allowed in lazy bind table for opcode at: 0x" +
- utohexstr(OpcodeStart - Opcodes.begin()));
+ "allowed in lazy bind table for opcode at: 0x" +
+ Twine::utohexstr(OpcodeStart - Opcodes.begin()));
moveToEnd();
return;
}
error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, true);
if (error) {
*E = malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED " +
- Twine(error) + " for opcode at: 0x" +
- utohexstr(OpcodeStart - Opcodes.begin()));
+ Twine(error) + " for opcode at: 0x" +
+ Twine::utohexstr(OpcodeStart - Opcodes.begin()));
moveToEnd();
return;
}
if (SymbolName == StringRef()) {
- *E = malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED "
- "missing preceding BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for "
- "opcode at: 0x" + utohexstr(OpcodeStart - Opcodes.begin()));
+ *E = malformedError(
+ "for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED "
+ "missing preceding BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for "
+ "opcode at: 0x" +
+ Twine::utohexstr(OpcodeStart - Opcodes.begin()));
moveToEnd();
return;
}
if (!LibraryOrdinalSet && TableKind != Kind::Weak) {
- *E = malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED "
- "missing preceding BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode "
- "at: 0x" + utohexstr(OpcodeStart - Opcodes.begin()));
+ *E = malformedError(
+ "for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED "
+ "missing preceding BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode "
+ "at: 0x" +
+ Twine::utohexstr(OpcodeStart - Opcodes.begin()));
moveToEnd();
return;
}
@@ -3523,10 +3719,11 @@ void MachOBindEntry::moveNext() {
error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset +
AdvanceAmount, false);
if (error) {
- *E = malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED "
- " (after adding immediate times the pointer size) " +
- Twine(error) + " for opcode at: 0x" +
- utohexstr(OpcodeStart - Opcodes.begin()));
+ *E =
+ malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED "
+ " (after adding immediate times the pointer size) " +
+ Twine(error) + " for opcode at: 0x" +
+ Twine::utohexstr(OpcodeStart - Opcodes.begin()));
moveToEnd();
return;
}
@@ -3538,8 +3735,8 @@ void MachOBindEntry::moveNext() {
case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
if (TableKind == Kind::Lazy) {
*E = malformedError("BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB not "
- "allowed in lazy bind table for opcode at: 0x" +
- utohexstr(OpcodeStart - Opcodes.begin()));
+ "allowed in lazy bind table for opcode at: 0x" +
+ Twine::utohexstr(OpcodeStart - Opcodes.begin()));
moveToEnd();
return;
}
@@ -3550,8 +3747,9 @@ void MachOBindEntry::moveNext() {
RemainingLoopCount = 0;
if (error) {
*E = malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
- " (count value) " + Twine(error) + " for opcode at"
- ": 0x" + utohexstr(OpcodeStart - Opcodes.begin()));
+ " (count value) " +
+ Twine(error) + " for opcode at: 0x" +
+ Twine::utohexstr(OpcodeStart - Opcodes.begin()));
moveToEnd();
return;
}
@@ -3559,41 +3757,48 @@ void MachOBindEntry::moveNext() {
AdvanceAmount = Skip + PointerSize;
if (error) {
*E = malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
- " (skip value) " + Twine(error) + " for opcode at"
- ": 0x" + utohexstr(OpcodeStart - Opcodes.begin()));
+ " (skip value) " +
+ Twine(error) + " for opcode at: 0x" +
+ Twine::utohexstr(OpcodeStart - Opcodes.begin()));
moveToEnd();
return;
}
error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, true);
if (error) {
- *E = malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
- + Twine(error) + " for opcode at: 0x" +
- utohexstr(OpcodeStart - Opcodes.begin()));
+ *E =
+ malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB " +
+ Twine(error) + " for opcode at: 0x" +
+ Twine::utohexstr(OpcodeStart - Opcodes.begin()));
moveToEnd();
return;
}
if (SymbolName == StringRef()) {
- *E = malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
- "missing preceding BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for "
- "opcode at: 0x" + utohexstr(OpcodeStart - Opcodes.begin()));
+ *E = malformedError(
+ "for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
+ "missing preceding BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for "
+ "opcode at: 0x" +
+ Twine::utohexstr(OpcodeStart - Opcodes.begin()));
moveToEnd();
return;
}
if (!LibraryOrdinalSet && TableKind != Kind::Weak) {
- *E = malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
- "missing preceding BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode "
- "at: 0x" + utohexstr(OpcodeStart - Opcodes.begin()));
+ *E = malformedError(
+ "for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
+ "missing preceding BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode "
+ "at: 0x" +
+ Twine::utohexstr(OpcodeStart - Opcodes.begin()));
moveToEnd();
return;
}
error = O->BindEntryCheckCountAndSkip(Count, Skip, PointerSize,
SegmentIndex, SegmentOffset);
if (error) {
- *E = malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
- + Twine(error) + " for opcode at: 0x" +
- utohexstr(OpcodeStart - Opcodes.begin()));
+ *E =
+ malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB " +
+ Twine(error) + " for opcode at: 0x" +
+ Twine::utohexstr(OpcodeStart - Opcodes.begin()));
moveToEnd();
- return;
+ return;
}
DEBUG_WITH_TYPE(
"mach-o-bind",
@@ -3605,8 +3810,8 @@ void MachOBindEntry::moveNext() {
return;
default:
*E = malformedError("bad bind info (bad opcode value 0x" +
- utohexstr(Opcode) + " for opcode at: 0x" +
- utohexstr(OpcodeStart - Opcodes.begin()));
+ Twine::utohexstr(Opcode) + " for opcode at: 0x" +
+ Twine::utohexstr(OpcodeStart - Opcodes.begin()));
moveToEnd();
return;
}
@@ -4115,7 +4320,10 @@ MachOObjectFile::getRelocation(DataRefImpl Rel) const {
}
} else {
MachO::dysymtab_command DysymtabLoadCmd = getDysymtabLoadCommand();
- Offset = DysymtabLoadCmd.extreloff; // Offset to the external relocations
+ if (Rel.d.a == 0)
+ Offset = DysymtabLoadCmd.extreloff; // Offset to the external relocations
+ else
+ Offset = DysymtabLoadCmd.locreloff; // Offset to the local relocations
}
auto P = reinterpret_cast<const MachO::any_relocation_info *>(
diff --git a/contrib/llvm/lib/Object/ModuleSymbolTable.cpp b/contrib/llvm/lib/Object/ModuleSymbolTable.cpp
index f2e7a218c13a..64446525b916 100644
--- a/contrib/llvm/lib/Object/ModuleSymbolTable.cpp
+++ b/contrib/llvm/lib/Object/ModuleSymbolTable.cpp
@@ -175,7 +175,7 @@ void ModuleSymbolTable::CollectAsmSymbols(
MCObjectFileInfo MOFI;
MCContext MCCtx(MAI.get(), MRI.get(), &MOFI);
- MOFI.InitMCObjectFileInfo(TT, /*PIC*/ false, CodeModel::Default, MCCtx);
+ MOFI.InitMCObjectFileInfo(TT, /*PIC*/ false, MCCtx);
RecordStreamer Streamer(MCCtx);
T->createNullTargetStreamer(Streamer);
diff --git a/contrib/llvm/lib/Object/ObjectFile.cpp b/contrib/llvm/lib/Object/ObjectFile.cpp
index 8377dd0d73fa..652a2b2497ef 100644
--- a/contrib/llvm/lib/Object/ObjectFile.cpp
+++ b/contrib/llvm/lib/Object/ObjectFile.cpp
@@ -75,10 +75,37 @@ bool ObjectFile::isSectionBitcode(DataRefImpl Sec) const {
return false;
}
+bool ObjectFile::isSectionStripped(DataRefImpl Sec) const { return false; }
+
section_iterator ObjectFile::getRelocatedSection(DataRefImpl Sec) const {
return section_iterator(SectionRef(Sec, this));
}
+Triple ObjectFile::makeTriple() const {
+ Triple TheTriple;
+ auto Arch = getArch();
+ TheTriple.setArch(Triple::ArchType(Arch));
+
+ // For ARM targets, try to use the build attributes to build determine
+ // the build target. Target features are also added, but later during
+ // disassembly.
+ if (Arch == Triple::arm || Arch == Triple::armeb)
+ setARMSubArch(TheTriple);
+
+ // TheTriple defaults to ELF, and COFF doesn't have an environment:
+ // the best we can do here is indicate that it is mach-o.
+ if (isMachO())
+ TheTriple.setObjectFormat(Triple::MachO);
+
+ if (isCOFF()) {
+ const auto COFFObj = dyn_cast<COFFObjectFile>(this);
+ if (COFFObj->getArch() == Triple::thumb)
+ TheTriple.setTriple("thumbv7-windows");
+ }
+
+ return TheTriple;
+}
+
Expected<std::unique_ptr<ObjectFile>>
ObjectFile::createObjectFile(MemoryBufferRef Object, file_magic Type) {
StringRef Data = Object.getBuffer();
@@ -98,7 +125,7 @@ ObjectFile::createObjectFile(MemoryBufferRef Object, file_magic Type) {
case file_magic::elf_executable:
case file_magic::elf_shared_object:
case file_magic::elf_core:
- return errorOrToExpected(createELFObjectFile(Object));
+ return createELFObjectFile(Object);
case file_magic::macho_object:
case file_magic::macho_executable:
case file_magic::macho_fixed_virtual_memory_shared_lib:
@@ -114,7 +141,7 @@ ObjectFile::createObjectFile(MemoryBufferRef Object, file_magic Type) {
case file_magic::coff_object:
case file_magic::coff_import_library:
case file_magic::pecoff_executable:
- return errorOrToExpected(createCOFFObjectFile(Object));
+ return createCOFFObjectFile(Object);
case file_magic::wasm_object:
return createWasmObjectFile(Object);
}
diff --git a/contrib/llvm/lib/Object/SymbolicFile.cpp b/contrib/llvm/lib/Object/SymbolicFile.cpp
index 1042d29d2350..2e7f2cc0d1d9 100644
--- a/contrib/llvm/lib/Object/SymbolicFile.cpp
+++ b/contrib/llvm/lib/Object/SymbolicFile.cpp
@@ -80,10 +80,12 @@ SymbolicFile::createSymbolicFile(MemoryBufferRef Object, file_magic Type,
if (!Obj || !Context)
return std::move(Obj);
- ErrorOr<MemoryBufferRef> BCData =
+ Expected<MemoryBufferRef> BCData =
IRObjectFile::findBitcodeInObject(*Obj->get());
- if (!BCData)
+ if (!BCData) {
+ consumeError(BCData.takeError());
return std::move(Obj);
+ }
return IRObjectFile::create(
MemoryBufferRef(BCData->getBuffer(), Object.getBufferIdentifier()),
diff --git a/contrib/llvm/lib/Object/WasmObjectFile.cpp b/contrib/llvm/lib/Object/WasmObjectFile.cpp
index 7f80bf0b83a0..7a0c05ed8a15 100644
--- a/contrib/llvm/lib/Object/WasmObjectFile.cpp
+++ b/contrib/llvm/lib/Object/WasmObjectFile.cpp
@@ -178,14 +178,16 @@ static wasm::WasmTable readTable(const uint8_t *&Ptr) {
}
static Error readSection(WasmSection &Section, const uint8_t *&Ptr,
- const uint8_t *Start) {
- // TODO(sbc): Avoid reading past EOF in the case of malformed files.
+ const uint8_t *Start, const uint8_t *Eof) {
Section.Offset = Ptr - Start;
Section.Type = readVaruint7(Ptr);
uint32_t Size = readVaruint32(Ptr);
if (Size == 0)
return make_error<StringError>("Zero length section",
object_error::parse_failed);
+ if (Ptr + Size > Eof)
+ return make_error<StringError>("Section too large",
+ object_error::parse_failed);
Section.Content = ArrayRef<uint8_t>(Ptr, Size);
Ptr += Size;
return Error::success();
@@ -193,7 +195,6 @@ static Error readSection(WasmSection &Section, const uint8_t *&Ptr,
WasmObjectFile::WasmObjectFile(MemoryBufferRef Buffer, Error &Err)
: ObjectFile(Binary::ID_Wasm, Buffer) {
- LinkingData.DataAlignment = 0;
LinkingData.DataSize = 0;
ErrorAsOutParameter ErrAsOutParam(&Err);
@@ -203,7 +204,16 @@ WasmObjectFile::WasmObjectFile(MemoryBufferRef Buffer, Error &Err)
object_error::parse_failed);
return;
}
+
+ const uint8_t *Eof = getPtr(getData().size());
const uint8_t *Ptr = getPtr(4);
+
+ if (Ptr + 4 > Eof) {
+ Err = make_error<StringError>("Missing version number",
+ object_error::parse_failed);
+ return;
+ }
+
Header.Version = readUint32(Ptr);
if (Header.Version != wasm::WasmVersion) {
Err = make_error<StringError>("Bad version number",
@@ -211,10 +221,9 @@ WasmObjectFile::WasmObjectFile(MemoryBufferRef Buffer, Error &Err)
return;
}
- const uint8_t *Eof = getPtr(getData().size());
WasmSection Sec;
while (Ptr < Eof) {
- if ((Err = readSection(Sec, Ptr, getPtr(0))))
+ if ((Err = readSection(Sec, Ptr, getPtr(0), Eof)))
return;
if ((Err = parseSection(Sec)))
return;
@@ -292,9 +301,61 @@ Error WasmObjectFile::parseNameSection(const uint8_t *Ptr, const uint8_t *End) {
return Error::success();
}
+void WasmObjectFile::populateSymbolTable() {
+ // Add imports to symbol table
+ size_t ImportIndex = 0;
+ size_t GlobalIndex = 0;
+ size_t FunctionIndex = 0;
+ for (const wasm::WasmImport& Import : Imports) {
+ switch (Import.Kind) {
+ case wasm::WASM_EXTERNAL_GLOBAL:
+ assert(Import.Global.Type == wasm::WASM_TYPE_I32);
+ SymbolMap.try_emplace(Import.Field, Symbols.size());
+ Symbols.emplace_back(Import.Field, WasmSymbol::SymbolType::GLOBAL_IMPORT,
+ ImportSection, GlobalIndex++, ImportIndex);
+ DEBUG(dbgs() << "Adding import: " << Symbols.back()
+ << " sym index:" << Symbols.size() << "\n");
+ break;
+ case wasm::WASM_EXTERNAL_FUNCTION:
+ SymbolMap.try_emplace(Import.Field, Symbols.size());
+ Symbols.emplace_back(Import.Field,
+ WasmSymbol::SymbolType::FUNCTION_IMPORT,
+ ImportSection, FunctionIndex++, ImportIndex);
+ DEBUG(dbgs() << "Adding import: " << Symbols.back()
+ << " sym index:" << Symbols.size() << "\n");
+ break;
+ default:
+ break;
+ }
+ ImportIndex++;
+ }
+
+ // Add exports to symbol table
+ for (const wasm::WasmExport& Export : Exports) {
+ if (Export.Kind == wasm::WASM_EXTERNAL_FUNCTION ||
+ Export.Kind == wasm::WASM_EXTERNAL_GLOBAL) {
+ WasmSymbol::SymbolType ExportType =
+ Export.Kind == wasm::WASM_EXTERNAL_FUNCTION
+ ? WasmSymbol::SymbolType::FUNCTION_EXPORT
+ : WasmSymbol::SymbolType::GLOBAL_EXPORT;
+ SymbolMap.try_emplace(Export.Name, Symbols.size());
+ Symbols.emplace_back(Export.Name, ExportType,
+ ExportSection, Export.Index);
+ DEBUG(dbgs() << "Adding export: " << Symbols.back()
+ << " sym index:" << Symbols.size() << "\n");
+ }
+ }
+}
+
Error WasmObjectFile::parseLinkingSection(const uint8_t *Ptr,
const uint8_t *End) {
HasLinkingSection = true;
+
+ // Only populate the symbol table with imports and exports if the object
+ // has a linking section (i.e. its a relocatable object file). Otherwise
+ // the global might not represent symbols at all.
+ populateSymbolTable();
+
while (Ptr < End) {
uint8_t Type = readVarint7(Ptr);
uint32_t Size = readVaruint32(Ptr);
@@ -317,7 +378,7 @@ Error WasmObjectFile::parseLinkingSection(const uint8_t *Ptr,
Symbols[SymIndex].Flags = Flags;
DEBUG(dbgs() << "Set symbol flags index:"
<< SymIndex << " name:"
- << Symbols[SymIndex].Name << " exptected:"
+ << Symbols[SymIndex].Name << " expected:"
<< Symbol << " flags: " << Flags << "\n");
}
break;
@@ -325,10 +386,33 @@ Error WasmObjectFile::parseLinkingSection(const uint8_t *Ptr,
case wasm::WASM_DATA_SIZE:
LinkingData.DataSize = readVaruint32(Ptr);
break;
- case wasm::WASM_DATA_ALIGNMENT:
- LinkingData.DataAlignment = readVaruint32(Ptr);
+ case wasm::WASM_SEGMENT_INFO: {
+ uint32_t Count = readVaruint32(Ptr);
+ if (Count > DataSegments.size())
+ return make_error<GenericBinaryError>("Too many segment names",
+ object_error::parse_failed);
+ for (uint32_t i = 0; i < Count; i++) {
+ DataSegments[i].Data.Name = readString(Ptr);
+ DataSegments[i].Data.Alignment = readVaruint32(Ptr);
+ DataSegments[i].Data.Flags = readVaruint32(Ptr);
+ }
+ break;
+ }
+ case wasm::WASM_INIT_FUNCS: {
+ uint32_t Count = readVaruint32(Ptr);
+ LinkingData.InitFunctions.reserve(Count);
+ for (uint32_t i = 0; i < Count; i++) {
+ wasm::WasmInitFunc Init;
+ Init.Priority = readVaruint32(Ptr);
+ Init.FunctionIndex = readVaruint32(Ptr);
+ if (!isValidFunctionIndex(Init.FunctionIndex))
+ return make_error<GenericBinaryError>("Invalid function index: " +
+ Twine(Init.FunctionIndex),
+ object_error::parse_failed);
+ LinkingData.InitFunctions.emplace_back(Init);
+ }
break;
- case wasm::WASM_STACK_POINTER:
+ }
default:
Ptr += Size;
break;
@@ -387,9 +471,9 @@ Error WasmObjectFile::parseRelocSection(StringRef Name, const uint8_t *Ptr,
case wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB:
case wasm::R_WEBASSEMBLY_GLOBAL_INDEX_LEB:
break;
- case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_LEB:
- case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_SLEB:
- case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_I32:
+ case wasm::R_WEBASSEMBLY_MEMORY_ADDR_LEB:
+ case wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB:
+ case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32:
Reloc.Addend = readVarint32(Ptr);
break;
default:
@@ -455,6 +539,7 @@ Error WasmObjectFile::parseTypeSection(const uint8_t *Ptr, const uint8_t *End) {
}
Error WasmObjectFile::parseImportSection(const uint8_t *Ptr, const uint8_t *End) {
+ ImportSection = Sections.size();
uint32_t Count = readVaruint32(Ptr);
Imports.reserve(Count);
for (uint32_t i = 0; i < Count; i++) {
@@ -464,31 +549,22 @@ Error WasmObjectFile::parseImportSection(const uint8_t *Ptr, const uint8_t *End)
Im.Kind = readUint8(Ptr);
switch (Im.Kind) {
case wasm::WASM_EXTERNAL_FUNCTION:
+ NumImportedFunctions++;
Im.SigIndex = readVaruint32(Ptr);
- SymbolMap.try_emplace(Im.Field, Symbols.size());
- Symbols.emplace_back(Im.Field, WasmSymbol::SymbolType::FUNCTION_IMPORT,
- Sections.size(), i);
- DEBUG(dbgs() << "Adding import: " << Symbols.back()
- << " sym index:" << Symbols.size() << "\n");
break;
case wasm::WASM_EXTERNAL_GLOBAL:
+ NumImportedGlobals++;
Im.Global.Type = readVarint7(Ptr);
Im.Global.Mutable = readVaruint1(Ptr);
- SymbolMap.try_emplace(Im.Field, Symbols.size());
- Symbols.emplace_back(Im.Field, WasmSymbol::SymbolType::GLOBAL_IMPORT,
- Sections.size(), i);
- DEBUG(dbgs() << "Adding import: " << Symbols.back()
- << " sym index:" << Symbols.size() << "\n");
break;
case wasm::WASM_EXTERNAL_MEMORY:
Im.Memory = readLimits(Ptr);
break;
case wasm::WASM_EXTERNAL_TABLE:
Im.Table = readTable(Ptr);
- if (Im.Table.ElemType != wasm::WASM_TYPE_ANYFUNC) {
+ if (Im.Table.ElemType != wasm::WASM_TYPE_ANYFUNC)
return make_error<GenericBinaryError>("Invalid table element type",
object_error::parse_failed);
- }
break;
default:
return make_error<GenericBinaryError>(
@@ -560,6 +636,7 @@ Error WasmObjectFile::parseGlobalSection(const uint8_t *Ptr, const uint8_t *End)
}
Error WasmObjectFile::parseExportSection(const uint8_t *Ptr, const uint8_t *End) {
+ ExportSection = Sections.size();
uint32_t Count = readVaruint32(Ptr);
Exports.reserve(Count);
for (uint32_t i = 0; i < Count; i++) {
@@ -567,17 +644,18 @@ Error WasmObjectFile::parseExportSection(const uint8_t *Ptr, const uint8_t *End)
Ex.Name = readString(Ptr);
Ex.Kind = readUint8(Ptr);
Ex.Index = readVaruint32(Ptr);
- WasmSymbol::SymbolType ExportType;
- bool MakeSymbol = false;
switch (Ex.Kind) {
case wasm::WASM_EXTERNAL_FUNCTION:
- ExportType = WasmSymbol::SymbolType::FUNCTION_EXPORT;
- MakeSymbol = true;
+ if (Ex.Index >= FunctionTypes.size() + NumImportedFunctions)
+ return make_error<GenericBinaryError>("Invalid function export",
+ object_error::parse_failed);
break;
- case wasm::WASM_EXTERNAL_GLOBAL:
- ExportType = WasmSymbol::SymbolType::GLOBAL_EXPORT;
- MakeSymbol = true;
+ case wasm::WASM_EXTERNAL_GLOBAL: {
+ if (Ex.Index >= Globals.size() + NumImportedGlobals)
+ return make_error<GenericBinaryError>("Invalid global export",
+ object_error::parse_failed);
break;
+ }
case wasm::WASM_EXTERNAL_MEMORY:
case wasm::WASM_EXTERNAL_TABLE:
break;
@@ -585,20 +663,6 @@ Error WasmObjectFile::parseExportSection(const uint8_t *Ptr, const uint8_t *End)
return make_error<GenericBinaryError>(
"Unexpected export kind", object_error::parse_failed);
}
- if (MakeSymbol) {
- auto Pair = SymbolMap.try_emplace(Ex.Name, Symbols.size());
- if (Pair.second) {
- Symbols.emplace_back(Ex.Name, ExportType,
- Sections.size(), i);
- DEBUG(dbgs() << "Adding export: " << Symbols.back()
- << " sym index:" << Symbols.size() << "\n");
- } else {
- uint32_t SymIndex = Pair.first->second;
- Symbols[SymIndex] = WasmSymbol(Ex.Name, ExportType, Sections.size(), i);
- DEBUG(dbgs() << "Replacing existing symbol: " << Symbols[SymIndex]
- << " sym index:" << SymIndex << "\n");
- }
- }
Exports.push_back(Ex);
}
if (Ptr != End)
@@ -607,27 +671,34 @@ Error WasmObjectFile::parseExportSection(const uint8_t *Ptr, const uint8_t *End)
return Error::success();
}
+bool WasmObjectFile::isValidFunctionIndex(uint32_t Index) const {
+ return Index < FunctionTypes.size() + NumImportedFunctions;
+}
+
Error WasmObjectFile::parseStartSection(const uint8_t *Ptr, const uint8_t *End) {
StartFunction = readVaruint32(Ptr);
- if (StartFunction >= FunctionTypes.size())
+ if (!isValidFunctionIndex(StartFunction))
return make_error<GenericBinaryError>("Invalid start function",
object_error::parse_failed);
return Error::success();
}
Error WasmObjectFile::parseCodeSection(const uint8_t *Ptr, const uint8_t *End) {
+ const uint8_t *CodeSectionStart = Ptr;
uint32_t FunctionCount = readVaruint32(Ptr);
if (FunctionCount != FunctionTypes.size()) {
return make_error<GenericBinaryError>("Invalid function count",
object_error::parse_failed);
}
- CodeSection = ArrayRef<uint8_t>(Ptr, End - Ptr);
-
while (FunctionCount--) {
wasm::WasmFunction Function;
- uint32_t FunctionSize = readVaruint32(Ptr);
- const uint8_t *FunctionEnd = Ptr + FunctionSize;
+ const uint8_t *FunctionStart = Ptr;
+ uint32_t Size = readVaruint32(Ptr);
+ const uint8_t *FunctionEnd = Ptr + Size;
+
+ Function.CodeSectionOffset = FunctionStart - CodeSectionStart;
+ Function.Size = FunctionEnd - FunctionStart;
uint32_t NumLocalDecls = readVaruint32(Ptr);
Function.Locals.reserve(NumLocalDecls);
@@ -685,6 +756,8 @@ Error WasmObjectFile::parseDataSection(const uint8_t *Ptr, const uint8_t *End) {
return Err;
uint32_t Size = readVaruint32(Ptr);
Segment.Data.Content = ArrayRef<uint8_t>(Ptr, Size);
+ Segment.Data.Alignment = 0;
+ Segment.Data.Flags = 0;
Segment.SectionOffset = Ptr - Start;
Ptr += Size;
DataSegments.push_back(Segment);
@@ -710,15 +783,19 @@ uint32_t WasmObjectFile::getSymbolFlags(DataRefImpl Symb) const {
const WasmSymbol &Sym = getWasmSymbol(Symb);
DEBUG(dbgs() << "getSymbolFlags: ptr=" << &Sym << " " << Sym << "\n");
- if (Sym.Flags & wasm::WASM_SYMBOL_FLAG_WEAK)
+ if (Sym.isWeak())
Result |= SymbolRef::SF_Weak;
+ if (!Sym.isLocal())
+ Result |= SymbolRef::SF_Global;
+ if (Sym.isHidden())
+ Result |= SymbolRef::SF_Hidden;
switch (Sym.Type) {
case WasmSymbol::SymbolType::FUNCTION_IMPORT:
Result |= SymbolRef::SF_Undefined | SymbolRef::SF_Executable;
break;
case WasmSymbol::SymbolType::FUNCTION_EXPORT:
- Result |= SymbolRef::SF_Global | SymbolRef::SF_Executable;
+ Result |= SymbolRef::SF_Executable;
break;
case WasmSymbol::SymbolType::DEBUG_FUNCTION_NAME:
Result |= SymbolRef::SF_Executable;
@@ -728,7 +805,6 @@ uint32_t WasmObjectFile::getSymbolFlags(DataRefImpl Symb) const {
Result |= SymbolRef::SF_Undefined;
break;
case WasmSymbol::SymbolType::GLOBAL_EXPORT:
- Result |= SymbolRef::SF_Global;
break;
}
@@ -763,21 +839,29 @@ Expected<uint64_t> WasmObjectFile::getSymbolAddress(DataRefImpl Symb) const {
return getSymbolValue(Symb);
}
-uint64_t WasmObjectFile::getSymbolValueImpl(DataRefImpl Symb) const {
- const WasmSymbol& Sym = getWasmSymbol(Symb);
+uint64_t WasmObjectFile::getWasmSymbolValue(const WasmSymbol& Sym) const {
switch (Sym.Type) {
case WasmSymbol::SymbolType::FUNCTION_IMPORT:
case WasmSymbol::SymbolType::GLOBAL_IMPORT:
- return 0;
case WasmSymbol::SymbolType::FUNCTION_EXPORT:
- case WasmSymbol::SymbolType::GLOBAL_EXPORT:
- return Exports[Sym.ElementIndex].Index;
case WasmSymbol::SymbolType::DEBUG_FUNCTION_NAME:
return Sym.ElementIndex;
+ case WasmSymbol::SymbolType::GLOBAL_EXPORT: {
+ uint32_t GlobalIndex = Sym.ElementIndex - NumImportedGlobals;
+ assert(GlobalIndex < Globals.size());
+ const wasm::WasmGlobal& Global = Globals[GlobalIndex];
+ // WasmSymbols correspond only to I32_CONST globals
+ assert(Global.InitExpr.Opcode == wasm::WASM_OPCODE_I32_CONST);
+ return Global.InitExpr.Value.Int32;
+ }
}
llvm_unreachable("invalid symbol type");
}
+uint64_t WasmObjectFile::getSymbolValueImpl(DataRefImpl Symb) const {
+ return getWasmSymbolValue(getWasmSymbol(Symb));
+}
+
uint32_t WasmObjectFile::getSymbolAlignment(DataRefImpl Symb) const {
llvm_unreachable("not yet implemented");
return 0;
@@ -957,7 +1041,7 @@ uint8_t WasmObjectFile::getBytesInAddress() const { return 4; }
StringRef WasmObjectFile::getFileFormatName() const { return "WASM"; }
-unsigned WasmObjectFile::getArch() const { return Triple::wasm32; }
+Triple::ArchType WasmObjectFile::getArch() const { return Triple::wasm32; }
SubtargetFeatures WasmObjectFile::getFeatures() const {
return SubtargetFeatures();
diff --git a/contrib/llvm/lib/Object/WindowsResource.cpp b/contrib/llvm/lib/Object/WindowsResource.cpp
index 246eee5ddb31..9ca584a4a1ae 100644
--- a/contrib/llvm/lib/Object/WindowsResource.cpp
+++ b/contrib/llvm/lib/Object/WindowsResource.cpp
@@ -17,7 +17,6 @@
#include "llvm/Support/MathExtras.h"
#include <ctime>
#include <queue>
-#include <sstream>
#include <system_error>
using namespace llvm;
@@ -57,19 +56,22 @@ WindowsResource::createWindowsResource(MemoryBufferRef Source) {
}
Expected<ResourceEntryRef> WindowsResource::getHeadEntry() {
- Error Err = Error::success();
- auto Ref = ResourceEntryRef(BinaryStreamRef(BBS), this, Err);
- if (Err)
- return std::move(Err);
- return Ref;
+ if (BBS.getLength() < sizeof(WinResHeaderPrefix) + sizeof(WinResHeaderSuffix))
+ return make_error<EmptyResError>(".res contains no entries",
+ object_error::unexpected_eof);
+ return ResourceEntryRef::create(BinaryStreamRef(BBS), this);
}
ResourceEntryRef::ResourceEntryRef(BinaryStreamRef Ref,
- const WindowsResource *Owner, Error &Err)
- : Reader(Ref), OwningRes(Owner) {
- if (loadNext())
- Err = make_error<GenericBinaryError>("Could not read first entry.\n",
- object_error::unexpected_eof);
+ const WindowsResource *Owner)
+ : Reader(Ref) {}
+
+Expected<ResourceEntryRef>
+ResourceEntryRef::create(BinaryStreamRef BSR, const WindowsResource *Owner) {
+ auto Ref = ResourceEntryRef(BSR, Owner);
+ if (auto E = Ref.loadNext())
+ return std::move(E);
+ return Ref;
}
Error ResourceEntryRef::moveNext(bool &End) {
@@ -127,8 +129,20 @@ WindowsResourceParser::WindowsResourceParser() : Root(false) {}
Error WindowsResourceParser::parse(WindowsResource *WR) {
auto EntryOrErr = WR->getHeadEntry();
- if (!EntryOrErr)
- return EntryOrErr.takeError();
+ if (!EntryOrErr) {
+ auto E = EntryOrErr.takeError();
+ if (E.isA<EmptyResError>()) {
+ // Check if the .res file contains no entries. In this case we don't have
+ // to throw an error but can rather just return without parsing anything.
+ // This applies for files which have a valid PE header magic and the
+ // mandatory empty null resource entry. Files which do not fit this
+ // criteria would have already been filtered out by
+ // WindowsResource::createWindowsResource().
+ consumeError(std::move(E));
+ return Error::success();
+ }
+ return E;
+ }
ResourceEntryRef Entry = EntryOrErr.get();
bool End = false;
@@ -426,19 +440,7 @@ std::unique_ptr<MemoryBuffer> WindowsResourceCOFFWriter::write() {
void WindowsResourceCOFFWriter::writeCOFFHeader() {
// Write the COFF header.
auto *Header = reinterpret_cast<coff_file_header *>(BufferStart);
- switch (MachineType) {
- case COFF::IMAGE_FILE_MACHINE_ARMNT:
- Header->Machine = COFF::IMAGE_FILE_MACHINE_ARMNT;
- break;
- case COFF::IMAGE_FILE_MACHINE_AMD64:
- Header->Machine = COFF::IMAGE_FILE_MACHINE_AMD64;
- break;
- case COFF::IMAGE_FILE_MACHINE_I386:
- Header->Machine = COFF::IMAGE_FILE_MACHINE_I386;
- break;
- default:
- Header->Machine = COFF::IMAGE_FILE_MACHINE_UNKNOWN;
- }
+ Header->Machine = MachineType;
Header->NumberOfSections = 2;
Header->TimeDateStamp = getTime();
Header->PointerToSymbolTable = SymbolTableOffset;
@@ -699,8 +701,11 @@ void WindowsResourceCOFFWriter::writeFirstSectionRelocations() {
case COFF::IMAGE_FILE_MACHINE_I386:
Reloc->Type = COFF::IMAGE_REL_I386_DIR32NB;
break;
+ case COFF::IMAGE_FILE_MACHINE_ARM64:
+ Reloc->Type = COFF::IMAGE_REL_ARM64_ADDR32NB;
+ break;
default:
- Reloc->Type = 0;
+ llvm_unreachable("unknown machine type");
}
CurrentOffset += sizeof(coff_relocation);
}