summaryrefslogtreecommitdiff
path: root/lib/Object
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2019-01-19 10:01:25 +0000
committerDimitry Andric <dim@FreeBSD.org>2019-01-19 10:01:25 +0000
commitd8e91e46262bc44006913e6796843909f1ac7bcd (patch)
tree7d0c143d9b38190e0fa0180805389da22cd834c5 /lib/Object
parentb7eb8e35e481a74962664b63dfb09483b200209a (diff)
Notes
Diffstat (limited to 'lib/Object')
-rw-r--r--lib/Object/ArchiveWriter.cpp188
-rw-r--r--lib/Object/Binary.cpp3
-rw-r--r--lib/Object/COFFObjectFile.cpp72
-rw-r--r--lib/Object/ELF.cpp26
-rw-r--r--lib/Object/ELFObjectFile.cpp67
-rw-r--r--lib/Object/Error.cpp1
-rw-r--r--lib/Object/MachOObjectFile.cpp8
-rw-r--r--lib/Object/ModuleSymbolTable.cpp1
-rw-r--r--lib/Object/Object.cpp8
-rw-r--r--lib/Object/ObjectFile.cpp8
-rw-r--r--lib/Object/WasmObjectFile.cpp310
-rw-r--r--lib/Object/WindowsResource.cpp7
12 files changed, 550 insertions, 149 deletions
diff --git a/lib/Object/ArchiveWriter.cpp b/lib/Object/ArchiveWriter.cpp
index ea17b2220a0b..da93602cbb28 100644
--- a/lib/Object/ArchiveWriter.cpp
+++ b/lib/Object/ArchiveWriter.cpp
@@ -27,6 +27,8 @@
#include "llvm/Support/ToolOutputFile.h"
#include "llvm/Support/raw_ostream.h"
+#include <map>
+
#if !defined(_MSC_VER) && !defined(__MINGW32__)
#include <unistd.h>
#else
@@ -119,6 +121,11 @@ static void printWithSpacePadding(raw_ostream &OS, T Data, unsigned Size) {
OS.indent(Size - SizeSoFar);
}
+static bool isDarwin(object::Archive::Kind Kind) {
+ return Kind == object::Archive::K_DARWIN ||
+ Kind == object::Archive::K_DARWIN64;
+}
+
static bool isBSDLike(object::Archive::Kind Kind) {
switch (Kind) {
case object::Archive::K_GNU:
@@ -126,8 +133,8 @@ static bool isBSDLike(object::Archive::Kind Kind) {
return false;
case object::Archive::K_BSD:
case object::Archive::K_DARWIN:
- return true;
case object::Archive::K_DARWIN64:
+ return true;
case object::Archive::K_COFF:
break;
}
@@ -243,20 +250,33 @@ static void addToStringTable(raw_ostream &Out, StringRef ArcName,
static void printMemberHeader(raw_ostream &Out, uint64_t Pos,
raw_ostream &StringTable,
+ StringMap<uint64_t> &MemberNames,
object::Archive::Kind Kind, bool Thin,
StringRef ArcName, const NewArchiveMember &M,
+ sys::TimePoint<std::chrono::seconds> ModTime,
unsigned Size) {
+
if (isBSDLike(Kind))
- return printBSDMemberHeader(Out, Pos, M.MemberName, M.ModTime, M.UID, M.GID,
+ return printBSDMemberHeader(Out, Pos, M.MemberName, ModTime, M.UID, M.GID,
M.Perms, Size);
if (!useStringTable(Thin, M.MemberName))
- return printGNUSmallMemberHeader(Out, M.MemberName, M.ModTime, M.UID, M.GID,
+ return printGNUSmallMemberHeader(Out, M.MemberName, ModTime, M.UID, M.GID,
M.Perms, Size);
Out << '/';
- uint64_t NamePos = StringTable.tell();
- addToStringTable(StringTable, ArcName, M, Thin);
+ uint64_t NamePos;
+ if (Thin) {
+ NamePos = StringTable.tell();
+ addToStringTable(StringTable, ArcName, M, Thin);
+ } else {
+ auto Insertion = MemberNames.insert({M.MemberName, uint64_t(0)});
+ if (Insertion.second) {
+ Insertion.first->second = StringTable.tell();
+ addToStringTable(StringTable, ArcName, M, Thin);
+ }
+ NamePos = Insertion.first->second;
+ }
printWithSpacePadding(Out, NamePos, 15);
- printRestOfMemberHeader(Out, M.ModTime, M.UID, M.GID, M.Perms, Size);
+ printRestOfMemberHeader(Out, ModTime, M.UID, M.GID, M.Perms, Size);
}
namespace {
@@ -310,7 +330,9 @@ static void printNBits(raw_ostream &Out, object::Archive::Kind Kind,
static void writeSymbolTable(raw_ostream &Out, object::Archive::Kind Kind,
bool Deterministic, ArrayRef<MemberData> Members,
StringRef StringTable) {
- if (StringTable.empty())
+ // We don't write a symbol table on an archive with no members -- except on
+ // Darwin, where the linker will abort unless the archive has a symbol table.
+ if (StringTable.empty() && !isDarwin(Kind))
return;
unsigned NumSyms = 0;
@@ -318,15 +340,15 @@ static void writeSymbolTable(raw_ostream &Out, object::Archive::Kind Kind,
NumSyms += M.Symbols.size();
unsigned Size = 0;
- Size += is64BitKind(Kind) ? 8 : 4; // Number of entries
+ unsigned OffsetSize = is64BitKind(Kind) ? sizeof(uint64_t) : sizeof(uint32_t);
+
+ Size += OffsetSize; // Number of entries
if (isBSDLike(Kind))
- Size += NumSyms * 8; // Table
- else if (is64BitKind(Kind))
- Size += NumSyms * 8; // Table
+ Size += NumSyms * OffsetSize * 2; // Table
else
- Size += NumSyms * 4; // Table
+ Size += NumSyms * OffsetSize; // Table
if (isBSDLike(Kind))
- Size += 4; // byte count
+ Size += OffsetSize; // 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
@@ -336,25 +358,26 @@ static void writeSymbolTable(raw_ostream &Out, object::Archive::Kind Kind,
unsigned Pad = OffsetToAlignment(Size, Alignment);
Size += Pad;
- 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);
+ if (isBSDLike(Kind)) {
+ const char *Name = is64BitKind(Kind) ? "__.SYMDEF_64" : "__.SYMDEF";
+ printBSDMemberHeader(Out, Out.tell(), Name, now(Deterministic), 0, 0, 0,
+ Size);
+ } else {
+ const char *Name = is64BitKind(Kind) ? "/SYM64" : "";
+ printGNUSmallMemberHeader(Out, Name, now(Deterministic), 0, 0, 0, Size);
+ }
uint64_t Pos = Out.tell() + Size;
if (isBSDLike(Kind))
- print<uint32_t>(Out, Kind, NumSyms * 8);
+ printNBits(Out, Kind, NumSyms * 2 * OffsetSize);
else
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, StringOffset);
printNBits(Out, Kind, Pos); // member offset
}
Pos += M.Header.size() + M.Data.size() + M.Padding.size();
@@ -362,7 +385,7 @@ static void writeSymbolTable(raw_ostream &Out, object::Archive::Kind Kind,
if (isBSDLike(Kind))
// byte count of the string table
- print<uint32_t>(Out, Kind, StringTable.size());
+ printNBits(Out, Kind, StringTable.size());
Out << StringTable;
while (Pad--)
@@ -372,20 +395,32 @@ static void writeSymbolTable(raw_ostream &Out, object::Archive::Kind Kind,
static Expected<std::vector<unsigned>>
getSymbols(MemoryBufferRef Buf, raw_ostream &SymNames, bool &HasObject) {
std::vector<unsigned> Ret;
- LLVMContext Context;
- 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;
+ // In the scenario when LLVMContext is populated SymbolicFile will contain a
+ // reference to it, thus SymbolicFile should be destroyed first.
+ LLVMContext Context;
+ std::unique_ptr<object::SymbolicFile> Obj;
+ if (identify_magic(Buf.getBuffer()) == file_magic::bitcode) {
+ auto ObjOrErr = object::SymbolicFile::createSymbolicFile(
+ Buf, file_magic::bitcode, &Context);
+ if (!ObjOrErr) {
+ // FIXME: check only for "not an object file" errors.
+ consumeError(ObjOrErr.takeError());
+ return Ret;
+ }
+ Obj = std::move(*ObjOrErr);
+ } else {
+ auto ObjOrErr = object::SymbolicFile::createSymbolicFile(Buf);
+ if (!ObjOrErr) {
+ // FIXME: check only for "not an object file" errors.
+ consumeError(ObjOrErr.takeError());
+ return Ret;
+ }
+ Obj = std::move(*ObjOrErr);
}
HasObject = true;
- object::SymbolicFile &Obj = *ObjOrErr.get();
- for (const object::BasicSymbolRef &S : Obj.symbols()) {
+ for (const object::BasicSymbolRef &S : Obj->symbols()) {
if (!isArchiveSymbol(S))
continue;
Ret.push_back(SymNames.tell());
@@ -399,7 +434,7 @@ getSymbols(MemoryBufferRef Buf, raw_ostream &SymNames, bool &HasObject) {
static Expected<std::vector<MemberData>>
computeMemberData(raw_ostream &StringTable, raw_ostream &SymNames,
object::Archive::Kind Kind, bool Thin, StringRef ArcName,
- ArrayRef<NewArchiveMember> NewMembers) {
+ bool Deterministic, ArrayRef<NewArchiveMember> NewMembers) {
static char PaddingData[8] = {'\n', '\n', '\n', '\n', '\n', '\n', '\n', '\n'};
// This ignores the symbol table, but we only need the value mod 8 and the
@@ -408,6 +443,62 @@ computeMemberData(raw_ostream &StringTable, raw_ostream &SymNames,
std::vector<MemberData> Ret;
bool HasObject = false;
+
+ // Deduplicate long member names in the string table and reuse earlier name
+ // offsets. This especially saves space for COFF Import libraries where all
+ // members have the same name.
+ StringMap<uint64_t> MemberNames;
+
+ // UniqueTimestamps is a special case to improve debugging on Darwin:
+ //
+ // The Darwin linker does not link debug info into the final
+ // binary. Instead, it emits entries of type N_OSO in in the output
+ // binary's symbol table, containing references to the linked-in
+ // object files. Using that reference, the debugger can read the
+ // debug data directly from the object files. Alternatively, an
+ // invocation of 'dsymutil' will link the debug data from the object
+ // files into a dSYM bundle, which can be loaded by the debugger,
+ // instead of the object files.
+ //
+ // For an object file, the N_OSO entries contain the absolute path
+ // path to the file, and the file's timestamp. For an object
+ // included in an archive, the path is formatted like
+ // "/absolute/path/to/archive.a(member.o)", and the timestamp is the
+ // archive member's timestamp, rather than the archive's timestamp.
+ //
+ // However, this doesn't always uniquely identify an object within
+ // an archive -- an archive file can have multiple entries with the
+ // same filename. (This will happen commonly if the original object
+ // files started in different directories.) The only way they get
+ // distinguished, then, is via the timestamp. But this process is
+ // unable to find the correct object file in the archive when there
+ // are two files of the same name and timestamp.
+ //
+ // Additionally, timestamp==0 is treated specially, and causes the
+ // timestamp to be ignored as a match criteria.
+ //
+ // That will "usually" work out okay when creating an archive not in
+ // deterministic timestamp mode, because the objects will probably
+ // have been created at different timestamps.
+ //
+ // To ameliorate this problem, in deterministic archive mode (which
+ // is the default), on Darwin we will emit a unique non-zero
+ // timestamp for each entry with a duplicated name. This is still
+ // deterministic: the only thing affecting that timestamp is the
+ // order of the files in the resultant archive.
+ //
+ // See also the functions that handle the lookup:
+ // in lldb: ObjectContainerBSDArchive::Archive::FindObject()
+ // in llvm/tools/dsymutil: BinaryHolder::GetArchiveMemberBuffers().
+ bool UniqueTimestamps = Deterministic && isDarwin(Kind);
+ std::map<StringRef, unsigned> FilenameCount;
+ if (UniqueTimestamps) {
+ for (const NewArchiveMember &M : NewMembers)
+ FilenameCount[M.MemberName]++;
+ for (auto &Entry : FilenameCount)
+ Entry.second = Entry.second > 1 ? 1 : 0;
+ }
+
for (const NewArchiveMember &M : NewMembers) {
std::string Header;
raw_string_ostream Out(Header);
@@ -419,14 +510,19 @@ computeMemberData(raw_ostream &StringTable, raw_ostream &SymNames,
// 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.
- unsigned MemberPadding = Kind == object::Archive::K_DARWIN
- ? OffsetToAlignment(Data.size(), 8)
- : 0;
+ unsigned MemberPadding =
+ isDarwin(Kind) ? 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);
+ sys::TimePoint<std::chrono::seconds> ModTime;
+ if (UniqueTimestamps)
+ // Increment timestamp for each file of a given name.
+ ModTime = sys::toTimePoint(FilenameCount[M.MemberName]++);
+ else
+ ModTime = M.ModTime;
+ printMemberHeader(Out, Pos, StringTable, MemberNames, Kind, Thin, ArcName,
+ M, ModTime, Buf.getBufferSize() + MemberPadding);
Out.flush();
Expected<std::vector<unsigned>> Symbols =
@@ -457,8 +553,8 @@ Error llvm::writeArchive(StringRef ArcName,
SmallString<0> StringTableBuf;
raw_svector_ostream StringTable(StringTableBuf);
- Expected<std::vector<MemberData>> DataOrErr =
- computeMemberData(StringTable, SymNames, Kind, Thin, ArcName, NewMembers);
+ Expected<std::vector<MemberData>> DataOrErr = computeMemberData(
+ StringTable, SymNames, Kind, Thin, ArcName, Deterministic, NewMembers);
if (Error E = DataOrErr.takeError())
return E;
std::vector<MemberData> &Data = *DataOrErr;
@@ -470,7 +566,7 @@ Error llvm::writeArchive(StringRef ArcName,
if (WriteSymtab) {
uint64_t MaxOffset = 0;
uint64_t LastOffset = MaxOffset;
- for (const auto& M : Data) {
+ 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.
@@ -494,8 +590,12 @@ Error llvm::writeArchive(StringRef ArcName,
// 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;
+ if (LastOffset >= (1ULL << Sym64Threshold)) {
+ if (Kind == object::Archive::K_DARWIN)
+ Kind = object::Archive::K_DARWIN64;
+ else
+ Kind = object::Archive::K_GNU64;
+ }
}
Expected<sys::fs::TempFile> Temp =
diff --git a/lib/Object/Binary.cpp b/lib/Object/Binary.cpp
index d7c25921ec36..fe41987f5c27 100644
--- a/lib/Object/Binary.cpp
+++ b/lib/Object/Binary.cpp
@@ -88,7 +88,8 @@ Expected<std::unique_ptr<Binary>> object::createBinary(MemoryBufferRef Buffer,
Expected<OwningBinary<Binary>> object::createBinary(StringRef Path) {
ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr =
- MemoryBuffer::getFileOrSTDIN(Path);
+ MemoryBuffer::getFileOrSTDIN(Path, /*FileSize=*/-1,
+ /*RequiresNullTerminator=*/false);
if (std::error_code EC = FileOrErr.getError())
return errorCodeToError(EC);
std::unique_ptr<MemoryBuffer> &Buffer = FileOrErr.get();
diff --git a/lib/Object/COFFObjectFile.cpp b/lib/Object/COFFObjectFile.cpp
index 85b1913cb23b..fc1deeba339a 100644
--- a/lib/Object/COFFObjectFile.cpp
+++ b/lib/Object/COFFObjectFile.cpp
@@ -616,6 +616,8 @@ std::error_code COFFObjectFile::initBaseRelocPtr() {
IntPtr);
BaseRelocEnd = reinterpret_cast<coff_base_reloc_block_header *>(
IntPtr + DataEntry->Size);
+ // FIXME: Verify the section containing BaseRelocHeader has at least
+ // DataEntry->Size bytes after DataEntry->RelativeVirtualAddress.
return std::error_code();
}
@@ -637,10 +639,10 @@ std::error_code COFFObjectFile::initDebugDirectoryPtr() {
if (std::error_code EC = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr))
return EC;
DebugDirectoryBegin = reinterpret_cast<const debug_directory *>(IntPtr);
- if (std::error_code EC = getRvaPtr(
- DataEntry->RelativeVirtualAddress + DataEntry->Size, IntPtr))
- return EC;
- DebugDirectoryEnd = reinterpret_cast<const debug_directory *>(IntPtr);
+ DebugDirectoryEnd = reinterpret_cast<const debug_directory *>(
+ IntPtr + DataEntry->Size);
+ // FIXME: Verify the section containing DebugDirectoryBegin has at least
+ // DataEntry->Size bytes after DataEntry->RelativeVirtualAddress.
return std::error_code();
}
@@ -936,6 +938,18 @@ iterator_range<base_reloc_iterator> COFFObjectFile::base_relocs() const {
return make_range(base_reloc_begin(), base_reloc_end());
}
+std::error_code
+COFFObjectFile::getCOFFHeader(const coff_file_header *&Res) const {
+ Res = COFFHeader;
+ return std::error_code();
+}
+
+std::error_code
+COFFObjectFile::getCOFFBigObjHeader(const coff_bigobj_file_header *&Res) const {
+ Res = COFFBigObjHeader;
+ return std::error_code();
+}
+
std::error_code COFFObjectFile::getPE32Header(const pe32_header *&Res) const {
Res = PE32Header;
return std::error_code();
@@ -1051,6 +1065,16 @@ COFFObjectFile::getSymbolAuxData(COFFSymbolRef Symbol) const {
return makeArrayRef(Aux, Symbol.getNumberOfAuxSymbols() * SymbolSize);
}
+uint32_t COFFObjectFile::getSymbolIndex(COFFSymbolRef Symbol) const {
+ uintptr_t Offset =
+ reinterpret_cast<uintptr_t>(Symbol.getRawPtr()) - getSymbolTable();
+ assert(Offset % getSymbolTableEntrySize() == 0 &&
+ "Symbol did not point to the beginning of a symbol");
+ size_t Index = Offset / getSymbolTableEntrySize();
+ assert(Index < getNumberOfSymbols());
+ return Index;
+}
+
std::error_code COFFObjectFile::getSectionName(const coff_section *Sec,
StringRef &Res) const {
StringRef Name;
@@ -1176,16 +1200,12 @@ COFFObjectFile::getRelocations(const coff_section *Sec) const {
#define LLVM_COFF_SWITCH_RELOC_TYPE_NAME(reloc_type) \
case COFF::reloc_type: \
- Res = #reloc_type; \
- break;
+ return #reloc_type;
-void COFFObjectFile::getRelocationTypeName(
- DataRefImpl Rel, SmallVectorImpl<char> &Result) const {
- const coff_relocation *Reloc = toRel(Rel);
- StringRef Res;
+StringRef COFFObjectFile::getRelocationTypeName(uint16_t Type) const {
switch (getMachine()) {
case COFF::IMAGE_FILE_MACHINE_AMD64:
- switch (Reloc->Type) {
+ switch (Type) {
LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ABSOLUTE);
LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR64);
LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32);
@@ -1204,11 +1224,11 @@ void COFFObjectFile::getRelocationTypeName(
LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_PAIR);
LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SSPAN32);
default:
- Res = "Unknown";
+ return "Unknown";
}
break;
case COFF::IMAGE_FILE_MACHINE_ARMNT:
- switch (Reloc->Type) {
+ switch (Type) {
LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ABSOLUTE);
LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32);
LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32NB);
@@ -1225,11 +1245,11 @@ void COFFObjectFile::getRelocationTypeName(
LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24T);
LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX23T);
default:
- Res = "Unknown";
+ return "Unknown";
}
break;
case COFF::IMAGE_FILE_MACHINE_ARM64:
- switch (Reloc->Type) {
+ switch (Type) {
LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ABSOLUTE);
LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR32);
LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR32NB);
@@ -1248,11 +1268,11 @@ void COFFObjectFile::getRelocationTypeName(
LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH19);
LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_BRANCH14);
default:
- Res = "Unknown";
+ return "Unknown";
}
break;
case COFF::IMAGE_FILE_MACHINE_I386:
- switch (Reloc->Type) {
+ switch (Type) {
LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_ABSOLUTE);
LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR16);
LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL16);
@@ -1265,21 +1285,33 @@ void COFFObjectFile::getRelocationTypeName(
LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL7);
LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL32);
default:
- Res = "Unknown";
+ return "Unknown";
}
break;
default:
- Res = "Unknown";
+ return "Unknown";
}
- Result.append(Res.begin(), Res.end());
}
#undef LLVM_COFF_SWITCH_RELOC_TYPE_NAME
+void COFFObjectFile::getRelocationTypeName(
+ DataRefImpl Rel, SmallVectorImpl<char> &Result) const {
+ const coff_relocation *Reloc = toRel(Rel);
+ StringRef Res = getRelocationTypeName(Reloc->Type);
+ Result.append(Res.begin(), Res.end());
+}
+
bool COFFObjectFile::isRelocatableObject() const {
return !DataDirectory;
}
+StringRef COFFObjectFile::mapDebugSectionName(StringRef Name) const {
+ return StringSwitch<StringRef>(Name)
+ .Case("eh_fram", "eh_frame")
+ .Default(Name);
+}
+
bool ImportDirectoryEntryRef::
operator==(const ImportDirectoryEntryRef &Other) const {
return ImportTable == Other.ImportTable && Index == Other.Index;
diff --git a/lib/Object/ELF.cpp b/lib/Object/ELF.cpp
index 2eefb7ef13a3..cf8313f88f93 100644
--- a/lib/Object/ELF.cpp
+++ b/lib/Object/ELF.cpp
@@ -139,6 +139,13 @@ StringRef llvm::object::getELFRelocationTypeName(uint32_t Machine,
break;
}
break;
+ case ELF::EM_MSP430:
+ switch (Type) {
+#include "llvm/BinaryFormat/ELFRelocs/MSP430.def"
+ default:
+ break;
+ }
+ break;
default:
break;
}
@@ -147,7 +154,7 @@ StringRef llvm::object::getELFRelocationTypeName(uint32_t Machine,
#undef ELF_RELOC
-uint32_t llvm::object::getELFRelrRelocationType(uint32_t Machine) {
+uint32_t llvm::object::getELFRelativeRelocationType(uint32_t Machine) {
switch (Machine) {
case ELF::EM_X86_64:
return ELF::R_X86_64_RELATIVE;
@@ -293,7 +300,7 @@ ELFFile<ELFT>::decode_relrs(Elf_Relr_Range relrs) const {
Elf_Rela Rela;
Rela.r_info = 0;
Rela.r_addend = 0;
- Rela.setType(getRelrRelocationType(), false);
+ Rela.setType(getRelativeRelocationType(), false);
std::vector<Elf_Rela> Relocs;
// Word type: uint32_t for Elf32, and uint64_t for Elf64.
@@ -393,20 +400,17 @@ ELFFile<ELFT>::android_relas(const Elf_Shdr *Sec) const {
if (GroupedByAddend && GroupHasAddend)
Addend += ReadSLEB();
+ if (!GroupHasAddend)
+ Addend = 0;
+
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;
- }
-
+ if (GroupHasAddend && !GroupedByAddend)
+ Addend += ReadSLEB();
+ R.r_addend = Addend;
Relocs.push_back(R);
if (ErrStr)
diff --git a/lib/Object/ELFObjectFile.cpp b/lib/Object/ELFObjectFile.cpp
index e806c8f28b15..9fb3a55ac7b1 100644
--- a/lib/Object/ELFObjectFile.cpp
+++ b/lib/Object/ELFObjectFile.cpp
@@ -14,6 +14,7 @@
#include "llvm/Object/ELFObjectFile.h"
#include "llvm/ADT/Triple.h"
#include "llvm/BinaryFormat/ELF.h"
+#include "llvm/MC/MCInstrAnalysis.h"
#include "llvm/MC/SubtargetFeature.h"
#include "llvm/Object/ELF.h"
#include "llvm/Object/ELFTypes.h"
@@ -23,6 +24,7 @@
#include "llvm/Support/Endian.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MathExtras.h"
+#include "llvm/Support/TargetRegistry.h"
#include <algorithm>
#include <cstddef>
#include <cstdint>
@@ -327,3 +329,68 @@ void ELFObjectFileBase::setARMSubArch(Triple &TheTriple) const {
TheTriple.setArchName(Triple);
}
+
+std::vector<std::pair<DataRefImpl, uint64_t>>
+ELFObjectFileBase::getPltAddresses() const {
+ std::string Err;
+ const auto Triple = makeTriple();
+ const auto *T = TargetRegistry::lookupTarget(Triple.str(), Err);
+ if (!T)
+ return {};
+ uint64_t JumpSlotReloc = 0;
+ switch (Triple.getArch()) {
+ case Triple::x86:
+ JumpSlotReloc = ELF::R_386_JUMP_SLOT;
+ break;
+ case Triple::x86_64:
+ JumpSlotReloc = ELF::R_X86_64_JUMP_SLOT;
+ break;
+ case Triple::aarch64:
+ JumpSlotReloc = ELF::R_AARCH64_JUMP_SLOT;
+ break;
+ default:
+ return {};
+ }
+ std::unique_ptr<const MCInstrInfo> MII(T->createMCInstrInfo());
+ std::unique_ptr<const MCInstrAnalysis> MIA(
+ T->createMCInstrAnalysis(MII.get()));
+ if (!MIA)
+ return {};
+ Optional<SectionRef> Plt = None, RelaPlt = None, GotPlt = None;
+ for (const SectionRef &Section : sections()) {
+ StringRef Name;
+ if (Section.getName(Name))
+ continue;
+ if (Name == ".plt")
+ Plt = Section;
+ else if (Name == ".rela.plt" || Name == ".rel.plt")
+ RelaPlt = Section;
+ else if (Name == ".got.plt")
+ GotPlt = Section;
+ }
+ if (!Plt || !RelaPlt || !GotPlt)
+ return {};
+ StringRef PltContents;
+ if (Plt->getContents(PltContents))
+ return {};
+ ArrayRef<uint8_t> PltBytes((const uint8_t *)PltContents.data(),
+ Plt->getSize());
+ auto PltEntries = MIA->findPltEntries(Plt->getAddress(), PltBytes,
+ GotPlt->getAddress(), Triple);
+ // Build a map from GOT entry virtual address to PLT entry virtual address.
+ DenseMap<uint64_t, uint64_t> GotToPlt;
+ for (const auto &Entry : PltEntries)
+ GotToPlt.insert(std::make_pair(Entry.second, Entry.first));
+ // Find the relocations in the dynamic relocation table that point to
+ // locations in the GOT for which we know the corresponding PLT entry.
+ std::vector<std::pair<DataRefImpl, uint64_t>> Result;
+ for (const auto &Relocation : RelaPlt->relocations()) {
+ if (Relocation.getType() != JumpSlotReloc)
+ continue;
+ auto PltEntryIter = GotToPlt.find(Relocation.getOffset());
+ if (PltEntryIter != GotToPlt.end())
+ Result.push_back(std::make_pair(
+ Relocation.getSymbol()->getRawDataRefImpl(), PltEntryIter->second));
+ }
+ return Result;
+}
diff --git a/lib/Object/Error.cpp b/lib/Object/Error.cpp
index 7d43a84f3e0e..6fa23e06c409 100644
--- a/lib/Object/Error.cpp
+++ b/lib/Object/Error.cpp
@@ -57,6 +57,7 @@ std::string _object_error_category::message(int EV) const {
"defined.");
}
+void BinaryError::anchor() {}
char BinaryError::ID = 0;
char GenericBinaryError::ID = 0;
diff --git a/lib/Object/MachOObjectFile.cpp b/lib/Object/MachOObjectFile.cpp
index e422903f2805..ce4d1cf92e20 100644
--- a/lib/Object/MachOObjectFile.cpp
+++ b/lib/Object/MachOObjectFile.cpp
@@ -1592,8 +1592,8 @@ MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian,
"command extends past the end of the symbol table");
return;
}
- if (Dysymtab.nextdefsym != 0 && Dysymtab.ilocalsym > Symtab.nsyms) {
- Err = malformedError("nextdefsym in LC_DYSYMTAB load command "
+ if (Dysymtab.nextdefsym != 0 && Dysymtab.iextdefsym > Symtab.nsyms) {
+ Err = malformedError("iextdefsym in LC_DYSYMTAB load command "
"extends past the end of the symbol table");
return;
}
@@ -1606,7 +1606,7 @@ MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian,
return;
}
if (Dysymtab.nundefsym != 0 && Dysymtab.iundefsym > Symtab.nsyms) {
- Err = malformedError("nundefsym in LC_DYSYMTAB load command "
+ Err = malformedError("iundefsym in LC_DYSYMTAB load command "
"extends past the end of the symbol table");
return;
}
@@ -2438,7 +2438,7 @@ basic_symbol_iterator MachOObjectFile::symbol_end() const {
return basic_symbol_iterator(SymbolRef(DRI, this));
}
-basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const {
+symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const {
MachO::symtab_command Symtab = getSymtabLoadCommand();
if (!SymtabLoadCmd || Index >= Symtab.nsyms)
report_fatal_error("Requested symbol index is out of range.");
diff --git a/lib/Object/ModuleSymbolTable.cpp b/lib/Object/ModuleSymbolTable.cpp
index b353ef3c835b..33ce7d8109fb 100644
--- a/lib/Object/ModuleSymbolTable.cpp
+++ b/lib/Object/ModuleSymbolTable.cpp
@@ -100,6 +100,7 @@ initializeRecordStreamer(const Module &M,
MCObjectFileInfo MOFI;
MCContext MCCtx(MAI.get(), MRI.get(), &MOFI);
MOFI.InitMCObjectFileInfo(TT, /*PIC*/ false, MCCtx);
+ MOFI.setSDKVersion(M.getSDKVersion());
RecordStreamer Streamer(MCCtx, M);
T->createNullTargetStreamer(Streamer);
diff --git a/lib/Object/Object.cpp b/lib/Object/Object.cpp
index 5fd823e0117e..f5de2e1d5ce2 100644
--- a/lib/Object/Object.cpp
+++ b/lib/Object/Object.cpp
@@ -105,7 +105,7 @@ void LLVMMoveToContainingSection(LLVMSectionIteratorRef Sect,
if (!SecOrErr) {
std::string Buf;
raw_string_ostream OS(Buf);
- logAllUnhandledErrors(SecOrErr.takeError(), OS, "");
+ logAllUnhandledErrors(SecOrErr.takeError(), OS);
OS.flush();
report_fatal_error(Buf);
}
@@ -187,7 +187,7 @@ const char *LLVMGetSymbolName(LLVMSymbolIteratorRef SI) {
if (!Ret) {
std::string Buf;
raw_string_ostream OS(Buf);
- logAllUnhandledErrors(Ret.takeError(), OS, "");
+ logAllUnhandledErrors(Ret.takeError(), OS);
OS.flush();
report_fatal_error(Buf);
}
@@ -199,7 +199,7 @@ uint64_t LLVMGetSymbolAddress(LLVMSymbolIteratorRef SI) {
if (!Ret) {
std::string Buf;
raw_string_ostream OS(Buf);
- logAllUnhandledErrors(Ret.takeError(), OS, "");
+ logAllUnhandledErrors(Ret.takeError(), OS);
OS.flush();
report_fatal_error(Buf);
}
@@ -229,7 +229,7 @@ const char *LLVMGetRelocationTypeName(LLVMRelocationIteratorRef RI) {
SmallVector<char, 0> ret;
(*unwrap(RI))->getTypeName(ret);
char *str = static_cast<char*>(safe_malloc(ret.size()));
- std::copy(ret.begin(), ret.end(), str);
+ llvm::copy(ret, str);
return str;
}
diff --git a/lib/Object/ObjectFile.cpp b/lib/Object/ObjectFile.cpp
index db0ff220c4d8..cf63b89adc12 100644
--- a/lib/Object/ObjectFile.cpp
+++ b/lib/Object/ObjectFile.cpp
@@ -77,6 +77,14 @@ bool ObjectFile::isSectionBitcode(DataRefImpl Sec) const {
bool ObjectFile::isSectionStripped(DataRefImpl Sec) const { return false; }
+bool ObjectFile::isBerkeleyText(DataRefImpl Sec) const {
+ return isSectionText(Sec);
+}
+
+bool ObjectFile::isBerkeleyData(DataRefImpl Sec) const {
+ return isSectionData(Sec);
+}
+
section_iterator ObjectFile::getRelocatedSection(DataRefImpl Sec) const {
return section_iterator(SectionRef(Sec, this));
}
diff --git a/lib/Object/WasmObjectFile.cpp b/lib/Object/WasmObjectFile.cpp
index 4d4c887b2d97..d84cb48c9fbd 100644
--- a/lib/Object/WasmObjectFile.cpp
+++ b/lib/Object/WasmObjectFile.cpp
@@ -24,6 +24,7 @@
#include "llvm/Support/Error.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/LEB128.h"
+#include "llvm/Support/ScopedPrinter.h"
#include <algorithm>
#include <cassert>
#include <cstdint>
@@ -37,8 +38,8 @@ using namespace object;
void WasmSymbol::print(raw_ostream &Out) const {
Out << "Name=" << Info.Name
- << ", Kind=" << toString(wasm::WasmSymbolType(Info.Kind))
- << ", Flags=" << Info.Flags;
+ << ", Kind=" << toString(wasm::WasmSymbolType(Info.Kind))
+ << ", Flags=" << Info.Flags;
if (!isTypeData()) {
Out << ", ElemIndex=" << Info.ElementIndex;
} else if (isDefined()) {
@@ -62,9 +63,9 @@ ObjectFile::createWasmObjectFile(MemoryBufferRef Buffer) {
return std::move(ObjectFile);
}
-#define VARINT7_MAX ((1<<7)-1)
-#define VARINT7_MIN (-(1<<7))
-#define VARUINT7_MAX (1<<7)
+#define VARINT7_MAX ((1 << 7) - 1)
+#define VARINT7_MIN (-(1 << 7))
+#define VARUINT7_MAX (1 << 7)
#define VARUINT1_MAX (1)
static uint8_t readUint8(WasmObjectFile::ReadContext &Ctx) {
@@ -82,6 +83,8 @@ static uint32_t readUint32(WasmObjectFile::ReadContext &Ctx) {
}
static int32_t readFloat32(WasmObjectFile::ReadContext &Ctx) {
+ if (Ctx.Ptr + 4 > Ctx.End)
+ report_fatal_error("EOF while reading float64");
int32_t Result = 0;
memcpy(&Result, Ctx.Ptr, sizeof(Result));
Ctx.Ptr += sizeof(Result);
@@ -89,6 +92,8 @@ static int32_t readFloat32(WasmObjectFile::ReadContext &Ctx) {
}
static int64_t readFloat64(WasmObjectFile::ReadContext &Ctx) {
+ if (Ctx.Ptr + 8 > Ctx.End)
+ report_fatal_error("EOF while reading float64");
int64_t Result = 0;
memcpy(&Result, Ctx.Ptr, sizeof(Result));
Ctx.Ptr += sizeof(Result);
@@ -97,7 +102,7 @@ static int64_t readFloat64(WasmObjectFile::ReadContext &Ctx) {
static uint64_t readULEB128(WasmObjectFile::ReadContext &Ctx) {
unsigned Count;
- const char* Error = nullptr;
+ const char *Error = nullptr;
uint64_t Result = decodeULEB128(Ctx.Ptr, &Count, Ctx.End, &Error);
if (Error)
report_fatal_error(Error);
@@ -117,7 +122,7 @@ static StringRef readString(WasmObjectFile::ReadContext &Ctx) {
static int64_t readLEB128(WasmObjectFile::ReadContext &Ctx) {
unsigned Count;
- const char* Error = nullptr;
+ const char *Error = nullptr;
uint64_t Result = decodeSLEB128(Ctx.Ptr, &Count, Ctx.End, &Error);
if (Error)
report_fatal_error(Error);
@@ -171,7 +176,7 @@ static Error readInitExpr(wasm::WasmInitExpr &Expr,
case wasm::WASM_OPCODE_F64_CONST:
Expr.Value.Float64 = readFloat64(Ctx);
break;
- case wasm::WASM_OPCODE_GET_GLOBAL:
+ case wasm::WASM_OPCODE_GLOBAL_GET:
Expr.Value.Global = readULEB128(Ctx);
break;
default:
@@ -189,7 +194,7 @@ static Error readInitExpr(wasm::WasmInitExpr &Expr,
static wasm::WasmLimits readLimits(WasmObjectFile::ReadContext &Ctx) {
wasm::WasmLimits Result;
- Result.Flags = readVaruint1(Ctx);
+ Result.Flags = readVaruint32(Ctx);
Result.Initial = readVaruint32(Ctx);
if (Result.Flags & wasm::WASM_LIMITS_FLAG_HAS_MAX)
Result.Maximum = readVaruint32(Ctx);
@@ -203,8 +208,8 @@ static wasm::WasmTable readTable(WasmObjectFile::ReadContext &Ctx) {
return Table;
}
-static Error readSection(WasmSection &Section,
- WasmObjectFile::ReadContext &Ctx) {
+static Error readSection(WasmSection &Section, WasmObjectFile::ReadContext &Ctx,
+ WasmSectionOrderChecker &Checker) {
Section.Offset = Ctx.Ptr - Ctx.Start;
Section.Type = readUint8(Ctx);
LLVM_DEBUG(dbgs() << "readSection type=" << Section.Type << "\n");
@@ -216,10 +221,24 @@ static Error readSection(WasmSection &Section,
return make_error<StringError>("Section too large",
object_error::parse_failed);
if (Section.Type == wasm::WASM_SEC_CUSTOM) {
- const uint8_t *NameStart = Ctx.Ptr;
- Section.Name = readString(Ctx);
- Size -= Ctx.Ptr - NameStart;
+ WasmObjectFile::ReadContext SectionCtx;
+ SectionCtx.Start = Ctx.Ptr;
+ SectionCtx.Ptr = Ctx.Ptr;
+ SectionCtx.End = Ctx.Ptr + Size;
+
+ Section.Name = readString(SectionCtx);
+
+ uint32_t SectionNameSize = SectionCtx.Ptr - SectionCtx.Start;
+ Ctx.Ptr += SectionNameSize;
+ Size -= SectionNameSize;
+ }
+
+ if (!Checker.isValidSectionOrder(Section.Type, Section.Name)) {
+ return make_error<StringError>("Out of order section type: " +
+ llvm::to_string(Section.Type),
+ object_error::parse_failed);
}
+
Section.Content = ArrayRef<uint8_t>(Ctx.Ptr, Size);
Ctx.Ptr += Size;
return Error::success();
@@ -230,8 +249,8 @@ WasmObjectFile::WasmObjectFile(MemoryBufferRef Buffer, Error &Err)
ErrorAsOutParameter ErrAsOutParam(&Err);
Header.Magic = getData().substr(0, 4);
if (Header.Magic != StringRef("\0asm", 4)) {
- Err = make_error<StringError>("Bad magic number",
- object_error::parse_failed);
+ Err =
+ make_error<StringError>("Bad magic number", object_error::parse_failed);
return;
}
@@ -254,8 +273,9 @@ WasmObjectFile::WasmObjectFile(MemoryBufferRef Buffer, Error &Err)
}
WasmSection Sec;
+ WasmSectionOrderChecker Checker;
while (Ctx.Ptr < Ctx.End) {
- if ((Err = readSection(Sec, Ctx)))
+ if ((Err = readSection(Sec, Ctx, Checker)))
return;
if ((Err = parseSection(Sec)))
return;
@@ -284,6 +304,8 @@ Error WasmObjectFile::parseSection(WasmSection &Sec) {
return parseMemorySection(Ctx);
case wasm::WASM_SEC_GLOBAL:
return parseGlobalSection(Ctx);
+ case wasm::WASM_SEC_EVENT:
+ return parseEventSection(Ctx);
case wasm::WASM_SEC_EXPORT:
return parseExportSection(Ctx);
case wasm::WASM_SEC_START:
@@ -300,6 +322,22 @@ Error WasmObjectFile::parseSection(WasmSection &Sec) {
}
}
+Error WasmObjectFile::parseDylinkSection(ReadContext &Ctx) {
+ // See https://github.com/WebAssembly/tool-conventions/blob/master/DynamicLinking.md
+ DylinkInfo.MemorySize = readVaruint32(Ctx);
+ DylinkInfo.MemoryAlignment = readVaruint32(Ctx);
+ DylinkInfo.TableSize = readVaruint32(Ctx);
+ DylinkInfo.TableAlignment = readVaruint32(Ctx);
+ uint32_t Count = readVaruint32(Ctx);
+ while (Count--) {
+ DylinkInfo.Needed.push_back(readString(Ctx));
+ }
+ if (Ctx.Ptr != Ctx.End)
+ return make_error<GenericBinaryError>("dylink section ended prematurely",
+ object_error::parse_failed);
+ return Error::success();
+}
+
Error WasmObjectFile::parseNameSection(ReadContext &Ctx) {
llvm::DenseSet<uint64_t> Seen;
if (Functions.size() != FunctionTypes.size()) {
@@ -336,8 +374,8 @@ Error WasmObjectFile::parseNameSection(ReadContext &Ctx) {
break;
}
if (Ctx.Ptr != SubSectionEnd)
- return make_error<GenericBinaryError>("Name sub-section ended prematurely",
- object_error::parse_failed);
+ return make_error<GenericBinaryError>(
+ "Name sub-section ended prematurely", object_error::parse_failed);
}
if (Ctx.Ptr != Ctx.End)
@@ -350,7 +388,8 @@ Error WasmObjectFile::parseLinkingSection(ReadContext &Ctx) {
HasLinkingSection = true;
if (Functions.size() != FunctionTypes.size()) {
return make_error<GenericBinaryError>(
- "Linking data must come after code section", object_error::parse_failed);
+ "Linking data must come after code section",
+ object_error::parse_failed);
}
LinkingData.Version = readVaruint32(Ctx);
@@ -427,19 +466,24 @@ Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) {
std::vector<wasm::WasmImport *> ImportedGlobals;
std::vector<wasm::WasmImport *> ImportedFunctions;
+ std::vector<wasm::WasmImport *> ImportedEvents;
ImportedGlobals.reserve(Imports.size());
ImportedFunctions.reserve(Imports.size());
+ ImportedEvents.reserve(Imports.size());
for (auto &I : Imports) {
if (I.Kind == wasm::WASM_EXTERNAL_FUNCTION)
ImportedFunctions.emplace_back(&I);
else if (I.Kind == wasm::WASM_EXTERNAL_GLOBAL)
ImportedGlobals.emplace_back(&I);
+ else if (I.Kind == wasm::WASM_EXTERNAL_EVENT)
+ ImportedEvents.emplace_back(&I);
}
while (Count--) {
wasm::WasmSymbolInfo Info;
- const wasm::WasmSignature *FunctionType = nullptr;
+ const wasm::WasmSignature *Signature = nullptr;
const wasm::WasmGlobalType *GlobalType = nullptr;
+ const wasm::WasmEventType *EventType = nullptr;
Info.Kind = readUint8(Ctx);
Info.Flags = readVaruint32(Ctx);
@@ -455,13 +499,13 @@ Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) {
if (IsDefined) {
Info.Name = readString(Ctx);
unsigned FuncIndex = Info.ElementIndex - NumImportedFunctions;
- FunctionType = &Signatures[FunctionTypes[FuncIndex]];
+ Signature = &Signatures[FunctionTypes[FuncIndex]];
wasm::WasmFunction &Function = Functions[FuncIndex];
if (Function.SymbolName.empty())
Function.SymbolName = Info.Name;
} else {
wasm::WasmImport &Import = *ImportedFunctions[Info.ElementIndex];
- FunctionType = &Signatures[Import.SigIndex];
+ Signature = &Signatures[Import.SigIndex];
Info.Name = Import.Field;
Info.Module = Import.Module;
}
@@ -473,9 +517,8 @@ Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) {
IsDefined != isDefinedGlobalIndex(Info.ElementIndex))
return make_error<GenericBinaryError>("invalid global symbol index",
object_error::parse_failed);
- if (!IsDefined &&
- (Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) ==
- wasm::WASM_SYMBOL_BINDING_WEAK)
+ if (!IsDefined && (Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) ==
+ wasm::WASM_SYMBOL_BINDING_WEAK)
return make_error<GenericBinaryError>("undefined weak global symbol",
object_error::parse_failed);
if (IsDefined) {
@@ -521,6 +564,34 @@ Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) {
break;
}
+ case wasm::WASM_SYMBOL_TYPE_EVENT: {
+ Info.ElementIndex = readVaruint32(Ctx);
+ if (!isValidEventIndex(Info.ElementIndex) ||
+ IsDefined != isDefinedEventIndex(Info.ElementIndex))
+ return make_error<GenericBinaryError>("invalid event symbol index",
+ object_error::parse_failed);
+ if (!IsDefined && (Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) ==
+ wasm::WASM_SYMBOL_BINDING_WEAK)
+ return make_error<GenericBinaryError>("undefined weak global symbol",
+ object_error::parse_failed);
+ if (IsDefined) {
+ Info.Name = readString(Ctx);
+ unsigned EventIndex = Info.ElementIndex - NumImportedEvents;
+ wasm::WasmEvent &Event = Events[EventIndex];
+ Signature = &Signatures[Event.Type.SigIndex];
+ EventType = &Event.Type;
+ if (Event.SymbolName.empty())
+ Event.SymbolName = Info.Name;
+
+ } else {
+ wasm::WasmImport &Import = *ImportedEvents[Info.ElementIndex];
+ EventType = &Import.Event;
+ Signature = &Signatures[EventType->SigIndex];
+ Info.Name = Import.Field;
+ }
+ break;
+ }
+
default:
return make_error<GenericBinaryError>("Invalid symbol type",
object_error::parse_failed);
@@ -533,8 +604,8 @@ Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) {
Twine(Info.Name),
object_error::parse_failed);
LinkingData.SymbolTable.emplace_back(Info);
- Symbols.emplace_back(LinkingData.SymbolTable.back(), FunctionType,
- GlobalType);
+ Symbols.emplace_back(LinkingData.SymbolTable.back(), GlobalType, EventType,
+ Signature);
LLVM_DEBUG(dbgs() << "Adding symbol: " << Symbols.back() << "\n");
}
@@ -547,7 +618,8 @@ Error WasmObjectFile::parseLinkingSectionComdat(ReadContext &Ctx) {
for (unsigned ComdatIndex = 0; ComdatIndex < ComdatCount; ++ComdatIndex) {
StringRef Name = readString(Ctx);
if (Name.empty() || !ComdatSet.insert(Name).second)
- return make_error<GenericBinaryError>("Bad/duplicate COMDAT name " + Twine(Name),
+ return make_error<GenericBinaryError>("Bad/duplicate COMDAT name " +
+ Twine(Name),
object_error::parse_failed);
LinkingData.Comdats.emplace_back(Name);
uint32_t Flags = readVaruint32(Ctx);
@@ -565,8 +637,8 @@ Error WasmObjectFile::parseLinkingSectionComdat(ReadContext &Ctx) {
object_error::parse_failed);
case wasm::WASM_COMDAT_DATA:
if (Index >= DataSegments.size())
- return make_error<GenericBinaryError>("COMDAT data index out of range",
- object_error::parse_failed);
+ return make_error<GenericBinaryError>(
+ "COMDAT data index out of range", object_error::parse_failed);
if (DataSegments[Index].Data.Comdat != UINT32_MAX)
return make_error<GenericBinaryError>("Data segment in two COMDATs",
object_error::parse_failed);
@@ -574,8 +646,8 @@ Error WasmObjectFile::parseLinkingSectionComdat(ReadContext &Ctx) {
break;
case wasm::WASM_COMDAT_FUNCTION:
if (!isDefinedFunctionIndex(Index))
- return make_error<GenericBinaryError>("COMDAT function index out of range",
- object_error::parse_failed);
+ return make_error<GenericBinaryError>(
+ "COMDAT function index out of range", object_error::parse_failed);
if (getDefinedFunction(Index).Comdat != UINT32_MAX)
return make_error<GenericBinaryError>("Function in two COMDATs",
object_error::parse_failed);
@@ -592,13 +664,18 @@ Error WasmObjectFile::parseRelocSection(StringRef Name, ReadContext &Ctx) {
if (SectionIndex >= Sections.size())
return make_error<GenericBinaryError>("Invalid section index",
object_error::parse_failed);
- WasmSection& Section = Sections[SectionIndex];
+ WasmSection &Section = Sections[SectionIndex];
uint32_t RelocCount = readVaruint32(Ctx);
uint32_t EndOffset = Section.Content.size();
+ uint32_t PreviousOffset = 0;
while (RelocCount--) {
wasm::WasmRelocation Reloc = {};
Reloc.Type = readVaruint32(Ctx);
Reloc.Offset = readVaruint32(Ctx);
+ if (Reloc.Offset < PreviousOffset)
+ return make_error<GenericBinaryError>("Relocations not in offset order",
+ object_error::parse_failed);
+ PreviousOffset = Reloc.Offset;
Reloc.Index = readVaruint32(Ctx);
switch (Reloc.Type) {
case wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB:
@@ -618,6 +695,11 @@ Error WasmObjectFile::parseRelocSection(StringRef Name, ReadContext &Ctx) {
return make_error<GenericBinaryError>("Bad relocation global index",
object_error::parse_failed);
break;
+ case wasm::R_WEBASSEMBLY_EVENT_INDEX_LEB:
+ if (!isValidEventSymbol(Reloc.Index))
+ return make_error<GenericBinaryError>("Bad relocation event index",
+ object_error::parse_failed);
+ break;
case wasm::R_WEBASSEMBLY_MEMORY_ADDR_LEB:
case wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB:
case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32:
@@ -666,7 +748,10 @@ Error WasmObjectFile::parseRelocSection(StringRef Name, ReadContext &Ctx) {
}
Error WasmObjectFile::parseCustomSection(WasmSection &Sec, ReadContext &Ctx) {
- if (Sec.Name == "name") {
+ if (Sec.Name == "dylink") {
+ if (Error Err = parseDylinkSection(Ctx))
+ return Err;
+ } else if (Sec.Name == "name") {
if (Error Err = parseNameSection(Ctx))
return Err;
} else if (Sec.Name == "linking") {
@@ -684,17 +769,16 @@ Error WasmObjectFile::parseTypeSection(ReadContext &Ctx) {
Signatures.reserve(Count);
while (Count--) {
wasm::WasmSignature Sig;
- Sig.ReturnType = wasm::WASM_TYPE_NORESULT;
uint8_t Form = readUint8(Ctx);
if (Form != wasm::WASM_TYPE_FUNC) {
return make_error<GenericBinaryError>("Invalid signature type",
object_error::parse_failed);
}
uint32_t ParamCount = readVaruint32(Ctx);
- Sig.ParamTypes.reserve(ParamCount);
+ Sig.Params.reserve(ParamCount);
while (ParamCount--) {
uint32_t ParamType = readUint8(Ctx);
- Sig.ParamTypes.push_back(ParamType);
+ Sig.Params.push_back(wasm::ValType(ParamType));
}
uint32_t ReturnCount = readVaruint32(Ctx);
if (ReturnCount) {
@@ -702,9 +786,9 @@ Error WasmObjectFile::parseTypeSection(ReadContext &Ctx) {
return make_error<GenericBinaryError>(
"Multiple return types not supported", object_error::parse_failed);
}
- Sig.ReturnType = readUint8(Ctx);
+ Sig.Returns.push_back(wasm::ValType(readUint8(Ctx)));
}
- Signatures.push_back(Sig);
+ Signatures.push_back(std::move(Sig));
}
if (Ctx.Ptr != Ctx.End)
return make_error<GenericBinaryError>("Type section ended prematurely",
@@ -735,13 +819,18 @@ Error WasmObjectFile::parseImportSection(ReadContext &Ctx) {
break;
case wasm::WASM_EXTERNAL_TABLE:
Im.Table = readTable(Ctx);
- if (Im.Table.ElemType != wasm::WASM_TYPE_ANYFUNC)
+ if (Im.Table.ElemType != wasm::WASM_TYPE_FUNCREF)
return make_error<GenericBinaryError>("Invalid table element type",
object_error::parse_failed);
break;
+ case wasm::WASM_EXTERNAL_EVENT:
+ NumImportedEvents++;
+ Im.Event.Attribute = readVarint32(Ctx);
+ Im.Event.SigIndex = readVarint32(Ctx);
+ break;
default:
- return make_error<GenericBinaryError>(
- "Unexpected import kind", object_error::parse_failed);
+ return make_error<GenericBinaryError>("Unexpected import kind",
+ object_error::parse_failed);
}
Imports.push_back(Im);
}
@@ -773,7 +862,7 @@ Error WasmObjectFile::parseTableSection(ReadContext &Ctx) {
Tables.reserve(Count);
while (Count--) {
Tables.push_back(readTable(Ctx));
- if (Tables.back().ElemType != wasm::WASM_TYPE_ANYFUNC) {
+ if (Tables.back().ElemType != wasm::WASM_TYPE_FUNCREF) {
return make_error<GenericBinaryError>("Invalid table element type",
object_error::parse_failed);
}
@@ -815,6 +904,24 @@ Error WasmObjectFile::parseGlobalSection(ReadContext &Ctx) {
return Error::success();
}
+Error WasmObjectFile::parseEventSection(ReadContext &Ctx) {
+ EventSection = Sections.size();
+ uint32_t Count = readVarint32(Ctx);
+ Events.reserve(Count);
+ while (Count--) {
+ wasm::WasmEvent Event;
+ Event.Index = NumImportedEvents + Events.size();
+ Event.Type.Attribute = readVaruint32(Ctx);
+ Event.Type.SigIndex = readVarint32(Ctx);
+ Events.push_back(Event);
+ }
+
+ if (Ctx.Ptr != Ctx.End)
+ return make_error<GenericBinaryError>("Event section ended prematurely",
+ object_error::parse_failed);
+ return Error::success();
+}
+
Error WasmObjectFile::parseExportSection(ReadContext &Ctx) {
uint32_t Count = readVaruint32(Ctx);
Exports.reserve(Count);
@@ -834,12 +941,17 @@ Error WasmObjectFile::parseExportSection(ReadContext &Ctx) {
return make_error<GenericBinaryError>("Invalid global export",
object_error::parse_failed);
break;
+ case wasm::WASM_EXTERNAL_EVENT:
+ if (!isValidEventIndex(Ex.Index))
+ return make_error<GenericBinaryError>("Invalid event export",
+ object_error::parse_failed);
+ break;
case wasm::WASM_EXTERNAL_MEMORY:
case wasm::WASM_EXTERNAL_TABLE:
break;
default:
- return make_error<GenericBinaryError>(
- "Unexpected export kind", object_error::parse_failed);
+ return make_error<GenericBinaryError>("Unexpected export kind",
+ object_error::parse_failed);
}
Exports.push_back(Ex);
}
@@ -865,6 +977,14 @@ bool WasmObjectFile::isDefinedGlobalIndex(uint32_t Index) const {
return Index >= NumImportedGlobals && isValidGlobalIndex(Index);
}
+bool WasmObjectFile::isValidEventIndex(uint32_t Index) const {
+ return Index < NumImportedEvents + Events.size();
+}
+
+bool WasmObjectFile::isDefinedEventIndex(uint32_t Index) const {
+ return Index >= NumImportedEvents && isValidEventIndex(Index);
+}
+
bool WasmObjectFile::isValidFunctionSymbol(uint32_t Index) const {
return Index < Symbols.size() && Symbols[Index].isTypeFunction();
}
@@ -873,6 +993,10 @@ bool WasmObjectFile::isValidGlobalSymbol(uint32_t Index) const {
return Index < Symbols.size() && Symbols[Index].isTypeGlobal();
}
+bool WasmObjectFile::isValidEventSymbol(uint32_t Index) const {
+ return Index < Symbols.size() && Symbols[Index].isTypeEvent();
+}
+
bool WasmObjectFile::isValidDataSymbol(uint32_t Index) const {
return Index < Symbols.size() && Symbols[Index].isTypeData();
}
@@ -891,6 +1015,11 @@ wasm::WasmGlobal &WasmObjectFile::getDefinedGlobal(uint32_t Index) {
return Globals[Index - NumImportedGlobals];
}
+wasm::WasmEvent &WasmObjectFile::getDefinedEvent(uint32_t Index) {
+ assert(isDefinedEventIndex(Index));
+ return Events[Index - NumImportedEvents];
+}
+
Error WasmObjectFile::parseStartSection(ReadContext &Ctx) {
StartFunction = readVaruint32(Ctx);
if (!isValidFunctionIndex(StartFunction))
@@ -1050,10 +1179,11 @@ Expected<uint64_t> WasmObjectFile::getSymbolAddress(DataRefImpl Symb) const {
return getSymbolValue(Symb);
}
-uint64_t WasmObjectFile::getWasmSymbolValue(const WasmSymbol& Sym) const {
+uint64_t WasmObjectFile::getWasmSymbolValue(const WasmSymbol &Sym) const {
switch (Sym.Info.Kind) {
case wasm::WASM_SYMBOL_TYPE_FUNCTION:
case wasm::WASM_SYMBOL_TYPE_GLOBAL:
+ case wasm::WASM_SYMBOL_TYPE_EVENT:
return Sym.Info.ElementIndex;
case wasm::WASM_SYMBOL_TYPE_DATA: {
// The value of a data symbol is the segment offset, plus the symbol
@@ -1096,6 +1226,8 @@ WasmObjectFile::getSymbolType(DataRefImpl Symb) const {
return SymbolRef::ST_Data;
case wasm::WASM_SYMBOL_TYPE_SECTION:
return SymbolRef::ST_Debug;
+ case wasm::WASM_SYMBOL_TYPE_EVENT:
+ return SymbolRef::ST_Other;
}
llvm_unreachable("Unknown WasmSymbol::SymbolType");
@@ -1104,7 +1236,7 @@ WasmObjectFile::getSymbolType(DataRefImpl Symb) const {
Expected<section_iterator>
WasmObjectFile::getSymbolSection(DataRefImpl Symb) const {
- const WasmSymbol& Sym = getWasmSymbol(Symb);
+ const WasmSymbol &Sym = getWasmSymbol(Symb);
if (Sym.isUndefined())
return section_end();
@@ -1119,10 +1251,12 @@ WasmObjectFile::getSymbolSection(DataRefImpl Symb) const {
case wasm::WASM_SYMBOL_TYPE_DATA:
Ref.d.a = DataSection;
break;
- case wasm::WASM_SYMBOL_TYPE_SECTION: {
+ case wasm::WASM_SYMBOL_TYPE_SECTION:
Ref.d.a = Sym.Info.ElementIndex;
break;
- }
+ case wasm::WASM_SYMBOL_TYPE_EVENT:
+ Ref.d.a = EventSection;
+ break;
default:
llvm_unreachable("Unknown WasmSymbol::SymbolType");
}
@@ -1145,6 +1279,7 @@ std::error_code WasmObjectFile::getSectionName(DataRefImpl Sec,
ECase(TABLE);
ECase(MEMORY);
ECase(GLOBAL);
+ ECase(EVENT);
ECase(EXPORT);
ECase(START);
ECase(ELEM);
@@ -1218,9 +1353,7 @@ relocation_iterator WasmObjectFile::section_rel_end(DataRefImpl Ref) const {
return relocation_iterator(RelocationRef(RelocRef, this));
}
-void WasmObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
- Rel.d.b++;
-}
+void WasmObjectFile::moveRelocationNext(DataRefImpl &Rel) const { Rel.d.b++; }
uint64_t WasmObjectFile::getRelocationOffset(DataRefImpl Ref) const {
const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
@@ -1244,12 +1377,12 @@ uint64_t WasmObjectFile::getRelocationType(DataRefImpl Ref) const {
void WasmObjectFile::getRelocationTypeName(
DataRefImpl Ref, SmallVectorImpl<char> &Result) const {
- const wasm::WasmRelocation& Rel = getWasmRelocation(Ref);
+ const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
StringRef Res = "Unknown";
-#define WASM_RELOC(name, value) \
- case wasm::name: \
- Res = #name; \
+#define WASM_RELOC(name, value) \
+ case wasm::name: \
+ Res = #name; \
break;
switch (Rel.Type) {
@@ -1283,9 +1416,9 @@ SubtargetFeatures WasmObjectFile::getFeatures() const {
return SubtargetFeatures();
}
-bool WasmObjectFile::isRelocatableObject() const {
- return HasLinkingSection;
-}
+bool WasmObjectFile::isRelocatableObject() const { return HasLinkingSection; }
+
+bool WasmObjectFile::isSharedObject() const { return HasDylinkSection; }
const WasmSection &WasmObjectFile::getWasmSection(DataRefImpl Ref) const {
assert(Ref.d.a < Sections.size());
@@ -1305,7 +1438,62 @@ WasmObjectFile::getWasmRelocation(const RelocationRef &Ref) const {
const wasm::WasmRelocation &
WasmObjectFile::getWasmRelocation(DataRefImpl Ref) const {
assert(Ref.d.a < Sections.size());
- const WasmSection& Sec = Sections[Ref.d.a];
+ const WasmSection &Sec = Sections[Ref.d.a];
assert(Ref.d.b < Sec.Relocations.size());
return Sec.Relocations[Ref.d.b];
}
+
+int WasmSectionOrderChecker::getSectionOrder(unsigned ID,
+ StringRef CustomSectionName) {
+ switch (ID) {
+ case wasm::WASM_SEC_CUSTOM:
+ return StringSwitch<unsigned>(CustomSectionName)
+ .Case("dylink", WASM_SEC_ORDER_DYLINK)
+ .Case("linking", WASM_SEC_ORDER_LINKING)
+ .StartsWith("reloc.", WASM_SEC_ORDER_RELOC)
+ .Case("name", WASM_SEC_ORDER_NAME)
+ .Case("producers", WASM_SEC_ORDER_PRODUCERS)
+ .Default(-1);
+ case wasm::WASM_SEC_TYPE:
+ return WASM_SEC_ORDER_TYPE;
+ case wasm::WASM_SEC_IMPORT:
+ return WASM_SEC_ORDER_IMPORT;
+ case wasm::WASM_SEC_FUNCTION:
+ return WASM_SEC_ORDER_FUNCTION;
+ case wasm::WASM_SEC_TABLE:
+ return WASM_SEC_ORDER_TABLE;
+ case wasm::WASM_SEC_MEMORY:
+ return WASM_SEC_ORDER_MEMORY;
+ case wasm::WASM_SEC_GLOBAL:
+ return WASM_SEC_ORDER_GLOBAL;
+ case wasm::WASM_SEC_EXPORT:
+ return WASM_SEC_ORDER_EXPORT;
+ case wasm::WASM_SEC_START:
+ return WASM_SEC_ORDER_START;
+ case wasm::WASM_SEC_ELEM:
+ return WASM_SEC_ORDER_ELEM;
+ case wasm::WASM_SEC_CODE:
+ return WASM_SEC_ORDER_CODE;
+ case wasm::WASM_SEC_DATA:
+ return WASM_SEC_ORDER_DATA;
+ case wasm::WASM_SEC_DATACOUNT:
+ return WASM_SEC_ORDER_DATACOUNT;
+ case wasm::WASM_SEC_EVENT:
+ return WASM_SEC_ORDER_EVENT;
+ default:
+ llvm_unreachable("invalid section");
+ }
+}
+
+bool WasmSectionOrderChecker::isValidSectionOrder(unsigned ID,
+ StringRef CustomSectionName) {
+ int Order = getSectionOrder(ID, CustomSectionName);
+ if (Order == -1) // Skip unknown sections
+ return true;
+ // There can be multiple "reloc." sections. Otherwise there shouldn't be any
+ // duplicate section orders.
+ bool IsValid = (LastOrder == Order && Order == WASM_SEC_ORDER_RELOC) ||
+ LastOrder < Order;
+ LastOrder = Order;
+ return IsValid;
+}
diff --git a/lib/Object/WindowsResource.cpp b/lib/Object/WindowsResource.cpp
index 1b7282f13db0..65413dd8bea1 100644
--- a/lib/Object/WindowsResource.cpp
+++ b/lib/Object/WindowsResource.cpp
@@ -259,7 +259,7 @@ WindowsResourceParser::TreeNode::addChild(ArrayRef<UTF16> NameRef,
std::vector<UTF16> EndianCorrectedName;
if (sys::IsBigEndianHost) {
EndianCorrectedName.resize(NameRef.size() + 1);
- std::copy(NameRef.begin(), NameRef.end(), EndianCorrectedName.begin() + 1);
+ llvm::copy(NameRef, EndianCorrectedName.begin() + 1);
EndianCorrectedName[0] = UNI_UTF16_BYTE_ORDER_MARK_SWAPPED;
CorrectedName = makeArrayRef(EndianCorrectedName);
} else
@@ -501,8 +501,7 @@ void WindowsResourceCOFFWriter::writeFirstSection() {
void WindowsResourceCOFFWriter::writeSecondSection() {
// Now write the .rsrc$02 section.
for (auto const &RawDataEntry : Data) {
- std::copy(RawDataEntry.begin(), RawDataEntry.end(),
- BufferStart + CurrentOffset);
+ llvm::copy(RawDataEntry, BufferStart + CurrentOffset);
CurrentOffset += alignTo(RawDataEntry.size(), sizeof(uint64_t));
}
@@ -672,7 +671,7 @@ void WindowsResourceCOFFWriter::writeDirectoryStringTable() {
support::endian::write16le(BufferStart + CurrentOffset, Length);
CurrentOffset += sizeof(uint16_t);
auto *Start = reinterpret_cast<UTF16 *>(BufferStart + CurrentOffset);
- std::copy(String.begin(), String.end(), Start);
+ llvm::copy(String, Start);
CurrentOffset += Length * sizeof(UTF16);
TotalStringTableSize += Length * sizeof(UTF16) + sizeof(uint16_t);
}