aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/llvm/lib/Object
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2024-07-27 23:34:35 +0000
committerDimitry Andric <dim@FreeBSD.org>2024-10-23 18:26:01 +0000
commit0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583 (patch)
tree6cf5ab1f05330c6773b1f3f64799d56a9c7a1faa /contrib/llvm-project/llvm/lib/Object
parent6b9f7133aba44189d9625c352bc2c2a59baf18ef (diff)
parentac9a064cb179f3425b310fa2847f8764ac970a4d (diff)
Diffstat (limited to 'contrib/llvm-project/llvm/lib/Object')
-rw-r--r--contrib/llvm-project/llvm/lib/Object/Archive.cpp23
-rw-r--r--contrib/llvm-project/llvm/lib/Object/ArchiveWriter.cpp206
-rw-r--r--contrib/llvm-project/llvm/lib/Object/COFFImportFile.cpp214
-rw-r--r--contrib/llvm-project/llvm/lib/Object/COFFModuleDefinition.cpp21
-rw-r--r--contrib/llvm-project/llvm/lib/Object/COFFObjectFile.cpp48
-rw-r--r--contrib/llvm-project/llvm/lib/Object/DXContainer.cpp26
-rw-r--r--contrib/llvm-project/llvm/lib/Object/ELF.cpp196
-rw-r--r--contrib/llvm-project/llvm/lib/Object/ELFObjectFile.cpp112
-rw-r--r--contrib/llvm-project/llvm/lib/Object/GOFFObjectFile.cpp176
-rw-r--r--contrib/llvm-project/llvm/lib/Object/IRSymtab.cpp22
-rw-r--r--contrib/llvm-project/llvm/lib/Object/MachOObjectFile.cpp62
-rw-r--r--contrib/llvm-project/llvm/lib/Object/ModuleSymbolTable.cpp14
-rw-r--r--contrib/llvm-project/llvm/lib/Object/OffloadBinary.cpp11
-rw-r--r--contrib/llvm-project/llvm/lib/Object/SymbolSize.cpp7
-rw-r--r--contrib/llvm-project/llvm/lib/Object/TapiFile.cpp8
-rw-r--r--contrib/llvm-project/llvm/lib/Object/TapiUniversal.cpp6
-rw-r--r--contrib/llvm-project/llvm/lib/Object/WasmObjectFile.cpp328
-rw-r--r--contrib/llvm-project/llvm/lib/Object/WindowsResource.cpp17
-rw-r--r--contrib/llvm-project/llvm/lib/Object/XCOFFObjectFile.cpp16
19 files changed, 1142 insertions, 371 deletions
diff --git a/contrib/llvm-project/llvm/lib/Object/Archive.cpp b/contrib/llvm-project/llvm/lib/Object/Archive.cpp
index e447e5b23316..e798bbdd16f1 100644
--- a/contrib/llvm-project/llvm/lib/Object/Archive.cpp
+++ b/contrib/llvm-project/llvm/lib/Object/Archive.cpp
@@ -269,11 +269,11 @@ Expected<StringRef> ArchiveMemberHeader::getName(uint64_t Size) const {
return Name;
// System libraries from the Windows SDK for Windows 11 contain this symbol.
// It looks like a CFG guard: we just skip it for now.
- if (Name.equals("/<XFGHASHMAP>/"))
+ if (Name == "/<XFGHASHMAP>/")
return Name;
// Some libraries (e.g., arm64rt.lib) from the Windows WDK
// (version 10.0.22000.0) contain this undocumented special member.
- if (Name.equals("/<ECSYMBOLS>/"))
+ if (Name == "/<ECSYMBOLS>/")
return Name;
// It's a long name.
// Get the string table offset.
@@ -969,12 +969,19 @@ Archive::Archive(MemoryBufferRef Source, Error &Err)
Err = Error::success();
}
-object::Archive::Kind Archive::getDefaultKindForHost() {
- Triple HostTriple(sys::getProcessTriple());
- return HostTriple.isOSDarwin()
- ? object::Archive::K_DARWIN
- : (HostTriple.isOSAIX() ? object::Archive::K_AIXBIG
- : object::Archive::K_GNU);
+object::Archive::Kind Archive::getDefaultKindForTriple(Triple &T) {
+ if (T.isOSDarwin())
+ return object::Archive::K_DARWIN;
+ if (T.isOSAIX())
+ return object::Archive::K_AIXBIG;
+ if (T.isOSWindows())
+ return object::Archive::K_COFF;
+ return object::Archive::K_GNU;
+}
+
+object::Archive::Kind Archive::getDefaultKind() {
+ Triple HostTriple(sys::getDefaultTargetTriple());
+ return getDefaultKindForTriple(HostTriple);
}
Archive::child_iterator Archive::child_begin(Error &Err,
diff --git a/contrib/llvm-project/llvm/lib/Object/ArchiveWriter.cpp b/contrib/llvm-project/llvm/lib/Object/ArchiveWriter.cpp
index 1a7ed2db5439..114045561366 100644
--- a/contrib/llvm-project/llvm/lib/Object/ArchiveWriter.cpp
+++ b/contrib/llvm-project/llvm/lib/Object/ArchiveWriter.cpp
@@ -48,7 +48,7 @@ using namespace llvm;
using namespace llvm::object;
struct SymMap {
- bool UseECMap;
+ bool UseECMap = false;
std::map<std::string, uint16_t> Map;
std::map<std::string, uint16_t> ECMap;
};
@@ -62,12 +62,16 @@ object::Archive::Kind NewArchiveMember::detectKindFromObject() const {
Expected<std::unique_ptr<object::ObjectFile>> OptionalObject =
object::ObjectFile::createObjectFile(MemBufferRef);
- if (OptionalObject)
- return isa<object::MachOObjectFile>(**OptionalObject)
- ? object::Archive::K_DARWIN
- : (isa<object::XCOFFObjectFile>(**OptionalObject)
- ? object::Archive::K_AIXBIG
- : object::Archive::K_GNU);
+ if (OptionalObject) {
+ if (isa<object::MachOObjectFile>(**OptionalObject))
+ return object::Archive::K_DARWIN;
+ if (isa<object::XCOFFObjectFile>(**OptionalObject))
+ return object::Archive::K_AIXBIG;
+ if (isa<object::COFFObjectFile>(**OptionalObject) ||
+ isa<object::COFFImportFile>(**OptionalObject))
+ return object::Archive::K_COFF;
+ return object::Archive::K_GNU;
+ }
// Squelch the error in case we had a non-object file.
consumeError(OptionalObject.takeError());
@@ -80,17 +84,14 @@ object::Archive::Kind NewArchiveMember::detectKindFromObject() const {
MemBufferRef, file_magic::bitcode, &Context)) {
auto &IRObject = cast<object::IRObjectFile>(**ObjOrErr);
auto TargetTriple = Triple(IRObject.getTargetTriple());
- return TargetTriple.isOSDarwin()
- ? object::Archive::K_DARWIN
- : (TargetTriple.isOSAIX() ? object::Archive::K_AIXBIG
- : object::Archive::K_GNU);
+ return object::Archive::getDefaultKindForTriple(TargetTriple);
} else {
// Squelch the error in case this was not a SymbolicFile.
consumeError(ObjOrErr.takeError());
}
}
- return object::Archive::getDefaultKindForHost();
+ return object::Archive::getDefaultKind();
}
Expected<NewArchiveMember>
@@ -481,7 +482,8 @@ static uint64_t computeHeadersSize(object::Archive::Kind Kind,
}
static Expected<std::unique_ptr<SymbolicFile>>
-getSymbolicFile(MemoryBufferRef Buf, LLVMContext &Context) {
+getSymbolicFile(MemoryBufferRef Buf, LLVMContext &Context,
+ object::Archive::Kind Kind, function_ref<void(Error)> Warn) {
const file_magic Type = identify_magic(Buf.getBuffer());
// Don't attempt to read non-symbolic file types.
if (!object::SymbolicFile::isSymbolicFile(Type, &Context))
@@ -489,8 +491,36 @@ getSymbolicFile(MemoryBufferRef Buf, LLVMContext &Context) {
if (Type == file_magic::bitcode) {
auto ObjOrErr = object::SymbolicFile::createSymbolicFile(
Buf, file_magic::bitcode, &Context);
- if (!ObjOrErr)
- return ObjOrErr.takeError();
+ // An error reading a bitcode file most likely indicates that the file
+ // was created by a compiler from the future. Normally we don't try to
+ // implement forwards compatibility for bitcode files, but when creating an
+ // archive we can implement best-effort forwards compatibility by treating
+ // the file as a blob and not creating symbol index entries for it. lld and
+ // mold ignore the archive symbol index, so provided that you use one of
+ // these linkers, LTO will work as long as lld or the gold plugin is newer
+ // than the compiler. We only ignore errors if the archive format is one
+ // that is supported by a linker that is known to ignore the index,
+ // otherwise there's no chance of this working so we may as well error out.
+ // We print a warning on read failure so that users of linkers that rely on
+ // the symbol index can diagnose the issue.
+ //
+ // This is the same behavior as GNU ar when the linker plugin returns an
+ // error when reading the input file. If the bitcode file is actually
+ // malformed, it will be diagnosed at link time.
+ if (!ObjOrErr) {
+ switch (Kind) {
+ case object::Archive::K_BSD:
+ case object::Archive::K_GNU:
+ case object::Archive::K_GNU64:
+ Warn(ObjOrErr.takeError());
+ return nullptr;
+ case object::Archive::K_AIXBIG:
+ case object::Archive::K_COFF:
+ case object::Archive::K_DARWIN:
+ case object::Archive::K_DARWIN64:
+ return ObjOrErr.takeError();
+ }
+ }
return std::move(*ObjOrErr);
} else {
auto ObjOrErr = object::SymbolicFile::createSymbolicFile(Buf);
@@ -677,6 +707,25 @@ static bool isECObject(object::SymbolicFile &Obj) {
return false;
}
+static bool isAnyArm64COFF(object::SymbolicFile &Obj) {
+ if (Obj.isCOFF())
+ return COFF::isAnyArm64(cast<COFFObjectFile>(&Obj)->getMachine());
+
+ if (Obj.isCOFFImportFile())
+ return COFF::isAnyArm64(cast<COFFImportFile>(&Obj)->getMachine());
+
+ if (Obj.isIR()) {
+ Expected<std::string> TripleStr =
+ getBitcodeTargetTriple(Obj.getMemoryBufferRef());
+ if (!TripleStr)
+ return false;
+ Triple T(*TripleStr);
+ return T.isOSWindows() && T.getArch() == Triple::aarch64;
+ }
+
+ return false;
+}
+
bool isImportDescriptor(StringRef Name) {
return Name.starts_with(ImportDescriptorPrefix) ||
Name == StringRef{NullImportDescriptorSymbolName} ||
@@ -730,7 +779,8 @@ static Expected<std::vector<MemberData>>
computeMemberData(raw_ostream &StringTable, raw_ostream &SymNames,
object::Archive::Kind Kind, bool Thin, bool Deterministic,
SymtabWritingMode NeedSymbols, SymMap *SymMap,
- LLVMContext &Context, ArrayRef<NewArchiveMember> NewMembers) {
+ LLVMContext &Context, ArrayRef<NewArchiveMember> NewMembers,
+ std::optional<bool> IsEC, function_ref<void(Error)> Warn) {
static char PaddingData[8] = {'\n', '\n', '\n', '\n', '\n', '\n', '\n', '\n'};
uint64_t MemHeadPadSize = 0;
uint64_t Pos =
@@ -794,23 +844,57 @@ computeMemberData(raw_ostream &StringTable, raw_ostream &SymNames,
Entry.second = Entry.second > 1 ? 1 : 0;
}
+ std::vector<std::unique_ptr<SymbolicFile>> SymFiles;
+
+ if (NeedSymbols != SymtabWritingMode::NoSymtab || isAIXBigArchive(Kind)) {
+ for (const NewArchiveMember &M : NewMembers) {
+ Expected<std::unique_ptr<SymbolicFile>> SymFileOrErr = getSymbolicFile(
+ M.Buf->getMemBufferRef(), Context, Kind, [&](Error Err) {
+ Warn(createFileError(M.MemberName, std::move(Err)));
+ });
+ if (!SymFileOrErr)
+ return createFileError(M.MemberName, SymFileOrErr.takeError());
+ SymFiles.push_back(std::move(*SymFileOrErr));
+ }
+ }
+
+ if (SymMap) {
+ if (IsEC) {
+ SymMap->UseECMap = *IsEC;
+ } else {
+ // When IsEC is not specified by the caller, use it when we have both
+ // any ARM64 object (ARM64 or ARM64EC) and any EC object (ARM64EC or
+ // AMD64). This may be a single ARM64EC object, but may also be separate
+ // ARM64 and AMD64 objects.
+ bool HaveArm64 = false, HaveEC = false;
+ for (std::unique_ptr<SymbolicFile> &SymFile : SymFiles) {
+ if (!SymFile)
+ continue;
+ if (!HaveArm64)
+ HaveArm64 = isAnyArm64COFF(*SymFile);
+ if (!HaveEC)
+ HaveEC = isECObject(*SymFile);
+ if (HaveArm64 && HaveEC) {
+ SymMap->UseECMap = true;
+ break;
+ }
+ }
+ }
+ }
+
// The big archive format needs to know the offset of the previous member
// header.
uint64_t PrevOffset = 0;
uint64_t NextMemHeadPadSize = 0;
- std::unique_ptr<SymbolicFile> CurSymFile;
- std::unique_ptr<SymbolicFile> NextSymFile;
- uint16_t Index = 0;
- for (auto M = NewMembers.begin(); M < NewMembers.end(); ++M) {
+ for (uint32_t Index = 0; Index < NewMembers.size(); ++Index) {
+ const NewArchiveMember *M = &NewMembers[Index];
std::string Header;
raw_string_ostream Out(Header);
MemoryBufferRef Buf = M->Buf->getMemBufferRef();
StringRef Data = Thin ? "" : Buf.getBuffer();
- Index++;
-
// 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
@@ -836,29 +920,9 @@ computeMemberData(raw_ostream &StringTable, raw_ostream &SymNames,
std::move(StringMsg), object::object_error::parse_failed);
}
- if (NeedSymbols != SymtabWritingMode::NoSymtab || isAIXBigArchive(Kind)) {
- auto SetNextSymFile = [&NextSymFile,
- &Context](MemoryBufferRef Buf,
- StringRef MemberName) -> Error {
- Expected<std::unique_ptr<SymbolicFile>> SymFileOrErr =
- getSymbolicFile(Buf, Context);
- if (!SymFileOrErr)
- return createFileError(MemberName, SymFileOrErr.takeError());
- NextSymFile = std::move(*SymFileOrErr);
- return Error::success();
- };
-
- if (M == NewMembers.begin())
- if (Error Err = SetNextSymFile(Buf, M->MemberName))
- return std::move(Err);
-
- CurSymFile = std::move(NextSymFile);
-
- if ((M + 1) != NewMembers.end())
- if (Error Err = SetNextSymFile((M + 1)->Buf->getMemBufferRef(),
- (M + 1)->MemberName))
- return std::move(Err);
- }
+ std::unique_ptr<SymbolicFile> CurSymFile;
+ if (!SymFiles.empty())
+ CurSymFile = std::move(SymFiles[Index]);
// In the big archive file format, we need to calculate and include the next
// member offset and previous member offset in the file member header.
@@ -879,13 +943,13 @@ computeMemberData(raw_ostream &StringTable, raw_ostream &SymNames,
// If there is another member file after this, we need to calculate the
// padding before the header.
- if ((M + 1) != NewMembers.end()) {
- uint64_t OffsetToNextMemData = NextOffset +
- sizeof(object::BigArMemHdrType) +
- alignTo((M + 1)->MemberName.size(), 2);
+ if (Index + 1 != SymFiles.size()) {
+ uint64_t OffsetToNextMemData =
+ NextOffset + sizeof(object::BigArMemHdrType) +
+ alignTo(NewMembers[Index + 1].MemberName.size(), 2);
NextMemHeadPadSize =
alignToPowerOf2(OffsetToNextMemData,
- getMemberAlignment(NextSymFile.get())) -
+ getMemberAlignment(SymFiles[Index + 1].get())) -
OffsetToNextMemData;
NextOffset += NextMemHeadPadSize;
}
@@ -901,7 +965,7 @@ computeMemberData(raw_ostream &StringTable, raw_ostream &SymNames,
std::vector<unsigned> Symbols;
if (NeedSymbols != SymtabWritingMode::NoSymtab) {
Expected<std::vector<unsigned>> SymbolsOrErr =
- getSymbols(CurSymFile.get(), Index, SymNames, SymMap);
+ getSymbols(CurSymFile.get(), Index + 1, SymNames, SymMap);
if (!SymbolsOrErr)
return createFileError(M->MemberName, SymbolsOrErr.takeError());
Symbols = std::move(*SymbolsOrErr);
@@ -937,7 +1001,7 @@ Expected<std::string> computeArchiveRelativePath(StringRef From, StringRef To) {
ErrorOr<SmallString<128>> PathToOrErr = canonicalizePath(To);
ErrorOr<SmallString<128>> DirFromOrErr = canonicalizePath(From);
if (!PathToOrErr || !DirFromOrErr)
- return errorCodeToError(std::error_code(errno, std::generic_category()));
+ return errorCodeToError(errnoAsErrorCode());
const SmallString<128> &PathTo = *PathToOrErr;
const SmallString<128> &DirFrom = sys::path::parent_path(*DirFromOrErr);
@@ -964,11 +1028,12 @@ Expected<std::string> computeArchiveRelativePath(StringRef From, StringRef To) {
return std::string(Relative);
}
-static Error writeArchiveToStream(raw_ostream &Out,
- ArrayRef<NewArchiveMember> NewMembers,
- SymtabWritingMode WriteSymtab,
- object::Archive::Kind Kind,
- bool Deterministic, bool Thin, bool IsEC) {
+Error writeArchiveToStream(raw_ostream &Out,
+ ArrayRef<NewArchiveMember> NewMembers,
+ SymtabWritingMode WriteSymtab,
+ object::Archive::Kind Kind, bool Deterministic,
+ bool Thin, std::optional<bool> IsEC,
+ function_ref<void(Error)> Warn) {
assert((!Thin || !isBSDLike(Kind)) && "Only the gnu format has a thin mode");
SmallString<0> SymNamesBuf;
@@ -976,20 +1041,21 @@ static Error writeArchiveToStream(raw_ostream &Out,
SmallString<0> StringTableBuf;
raw_svector_ostream StringTable(StringTableBuf);
SymMap SymMap;
+ bool ShouldWriteSymtab = WriteSymtab != SymtabWritingMode::NoSymtab;
// COFF symbol map uses 16-bit indexes, so we can't use it if there are too
- // many members.
- if (isCOFFArchive(Kind) && NewMembers.size() > 0xfffe)
+ // many members. COFF format also requires symbol table presence, so use
+ // GNU format when NoSymtab is requested.
+ if (isCOFFArchive(Kind) && (NewMembers.size() > 0xfffe || !ShouldWriteSymtab))
Kind = object::Archive::K_GNU;
// In the scenario when LLVMContext is populated SymbolicFile will contain a
// reference to it, thus SymbolicFile should be destroyed first.
LLVMContext Context;
- SymMap.UseECMap = IsEC;
Expected<std::vector<MemberData>> DataOrErr = computeMemberData(
StringTable, SymNames, Kind, Thin, Deterministic, WriteSymtab,
- isCOFFArchive(Kind) ? &SymMap : nullptr, Context, NewMembers);
+ isCOFFArchive(Kind) ? &SymMap : nullptr, Context, NewMembers, IsEC, Warn);
if (Error E = DataOrErr.takeError())
return E;
std::vector<MemberData> &Data = *DataOrErr;
@@ -1008,7 +1074,6 @@ static Error writeArchiveToStream(raw_ostream &Out,
uint64_t LastMemberHeaderOffset = 0;
uint64_t NumSyms = 0;
uint64_t NumSyms32 = 0; // Store symbol number of 32-bit member files.
- bool ShouldWriteSymtab = WriteSymtab != SymtabWritingMode::NoSymtab;
for (const auto &M : Data) {
// Record the start of the member's offset
@@ -1233,10 +1298,15 @@ static Error writeArchiveToStream(raw_ostream &Out,
return Error::success();
}
+void warnToStderr(Error Err) {
+ llvm::logAllUnhandledErrors(std::move(Err), llvm::errs(), "warning: ");
+}
+
Error writeArchive(StringRef ArcName, ArrayRef<NewArchiveMember> NewMembers,
SymtabWritingMode WriteSymtab, object::Archive::Kind Kind,
bool Deterministic, bool Thin,
- std::unique_ptr<MemoryBuffer> OldArchiveBuf, bool IsEC) {
+ std::unique_ptr<MemoryBuffer> OldArchiveBuf,
+ std::optional<bool> IsEC, function_ref<void(Error)> Warn) {
Expected<sys::fs::TempFile> Temp =
sys::fs::TempFile::create(ArcName + ".temp-archive-%%%%%%%.a");
if (!Temp)
@@ -1244,7 +1314,7 @@ Error writeArchive(StringRef ArcName, ArrayRef<NewArchiveMember> NewMembers,
raw_fd_ostream Out(Temp->FD, false);
if (Error E = writeArchiveToStream(Out, NewMembers, WriteSymtab, Kind,
- Deterministic, Thin, IsEC)) {
+ Deterministic, Thin, IsEC, Warn)) {
if (Error DiscardError = Temp->discard())
return joinErrors(std::move(E), std::move(DiscardError));
return E;
@@ -1268,12 +1338,14 @@ Error writeArchive(StringRef ArcName, ArrayRef<NewArchiveMember> NewMembers,
Expected<std::unique_ptr<MemoryBuffer>>
writeArchiveToBuffer(ArrayRef<NewArchiveMember> NewMembers,
SymtabWritingMode WriteSymtab, object::Archive::Kind Kind,
- bool Deterministic, bool Thin) {
+ bool Deterministic, bool Thin,
+ function_ref<void(Error)> Warn) {
SmallVector<char, 0> ArchiveBufferVector;
raw_svector_ostream ArchiveStream(ArchiveBufferVector);
- if (Error E = writeArchiveToStream(ArchiveStream, NewMembers, WriteSymtab,
- Kind, Deterministic, Thin, false))
+ if (Error E =
+ writeArchiveToStream(ArchiveStream, NewMembers, WriteSymtab, Kind,
+ Deterministic, Thin, std::nullopt, Warn))
return std::move(E);
return std::make_unique<SmallVectorMemoryBuffer>(
diff --git a/contrib/llvm-project/llvm/lib/Object/COFFImportFile.cpp b/contrib/llvm-project/llvm/lib/Object/COFFImportFile.cpp
index d3b5cf2d9f7b..e67b02405a3a 100644
--- a/contrib/llvm-project/llvm/lib/Object/COFFImportFile.cpp
+++ b/contrib/llvm-project/llvm/lib/Object/COFFImportFile.cpp
@@ -12,6 +12,8 @@
#include "llvm/Object/COFFImportFile.h"
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Object/Archive.h"
#include "llvm/Object/ArchiveWriter.h"
@@ -52,18 +54,12 @@ StringRef COFFImportFile::getFileFormatName() const {
}
}
-StringRef COFFImportFile::getExportName() const {
- const coff_import_header *hdr = getCOFFImportHeader();
- StringRef name = Data.getBuffer().substr(sizeof(*hdr)).split('\0').first;
-
+static StringRef applyNameType(ImportNameType Type, StringRef name) {
auto ltrim1 = [](StringRef s, StringRef chars) {
return !s.empty() && chars.contains(s[0]) ? s.substr(1) : s;
};
- switch (hdr->getNameType()) {
- case IMPORT_ORDINAL:
- name = "";
- break;
+ switch (Type) {
case IMPORT_NAME_NOPREFIX:
name = ltrim1(name, "?@_");
break;
@@ -71,6 +67,24 @@ StringRef COFFImportFile::getExportName() const {
name = ltrim1(name, "?@_");
name = name.substr(0, name.find('@'));
break;
+ default:
+ break;
+ }
+ return name;
+}
+
+StringRef COFFImportFile::getExportName() const {
+ const coff_import_header *hdr = getCOFFImportHeader();
+ StringRef name = Data.getBuffer().substr(sizeof(*hdr)).split('\0').first;
+
+ switch (hdr->getNameType()) {
+ case IMPORT_ORDINAL:
+ name = "";
+ break;
+ case IMPORT_NAME_NOPREFIX:
+ case IMPORT_NAME_UNDECORATE:
+ name = applyNameType(static_cast<ImportNameType>(hdr->getNameType()), name);
+ break;
case IMPORT_NAME_EXPORTAS: {
// Skip DLL name
name = Data.getBuffer().substr(sizeof(*hdr) + name.size() + 1);
@@ -84,6 +98,27 @@ StringRef COFFImportFile::getExportName() const {
return name;
}
+Error COFFImportFile::printSymbolName(raw_ostream &OS, DataRefImpl Symb) const {
+ switch (Symb.p) {
+ case ImpSymbol:
+ OS << "__imp_";
+ break;
+ case ECAuxSymbol:
+ OS << "__imp_aux_";
+ break;
+ }
+ const char *Name = Data.getBufferStart() + sizeof(coff_import_header);
+ if (Symb.p != ECThunkSymbol && COFF::isArm64EC(getMachine())) {
+ if (std::optional<std::string> DemangledName =
+ getArm64ECDemangledFunctionName(Name)) {
+ OS << StringRef(*DemangledName);
+ return Error::success();
+ }
+ }
+ OS << StringRef(Name);
+ return Error::success();
+}
+
static uint16_t getImgRelRelocation(MachineTypes Machine) {
switch (Machine) {
default:
@@ -623,10 +658,14 @@ NewArchiveMember ObjectFactory::createWeakExternal(StringRef Sym,
Error writeImportLibrary(StringRef ImportName, StringRef Path,
ArrayRef<COFFShortExport> Exports,
- MachineTypes Machine, bool MinGW) {
+ MachineTypes Machine, bool MinGW,
+ ArrayRef<COFFShortExport> NativeExports) {
- MachineTypes NativeMachine =
- isArm64EC(Machine) ? IMAGE_FILE_MACHINE_ARM64 : Machine;
+ MachineTypes NativeMachine = Machine;
+ if (isArm64EC(Machine)) {
+ NativeMachine = IMAGE_FILE_MACHINE_ARM64;
+ Machine = IMAGE_FILE_MACHINE_ARM64EC;
+ }
std::vector<NewArchiveMember> Members;
ObjectFactory OF(llvm::sys::path::filename(ImportName), NativeMachine);
@@ -640,66 +679,117 @@ Error writeImportLibrary(StringRef ImportName, StringRef Path,
std::vector<uint8_t> NullThunk;
Members.push_back(OF.createNullThunk(NullThunk));
- for (const COFFShortExport &E : Exports) {
- if (E.Private)
- continue;
-
- ImportType ImportType = IMPORT_CODE;
- if (E.Data)
- ImportType = IMPORT_DATA;
- if (E.Constant)
- ImportType = IMPORT_CONST;
-
- StringRef SymbolName = E.SymbolName.empty() ? E.Name : E.SymbolName;
- std::string Name;
-
- if (E.ExtName.empty()) {
- Name = std::string(SymbolName);
- } else {
- Expected<std::string> ReplacedName =
- replace(SymbolName, E.Name, E.ExtName);
- if (!ReplacedName)
- return ReplacedName.takeError();
- Name.swap(*ReplacedName);
- }
-
- if (!E.AliasTarget.empty() && Name != E.AliasTarget) {
- Members.push_back(
- OF.createWeakExternal(E.AliasTarget, Name, false, Machine));
- Members.push_back(
- OF.createWeakExternal(E.AliasTarget, Name, true, Machine));
- continue;
- }
+ auto addExports = [&](ArrayRef<COFFShortExport> Exp,
+ MachineTypes M) -> Error {
+ StringMap<std::string> RegularImports;
+ struct Deferred {
+ std::string Name;
+ ImportType ImpType;
+ const COFFShortExport *Export;
+ };
+ SmallVector<Deferred, 0> Renames;
+ for (const COFFShortExport &E : Exp) {
+ if (E.Private)
+ continue;
+
+ ImportType ImportType = IMPORT_CODE;
+ if (E.Data)
+ ImportType = IMPORT_DATA;
+ if (E.Constant)
+ ImportType = IMPORT_CONST;
+
+ StringRef SymbolName = E.SymbolName.empty() ? E.Name : E.SymbolName;
+ std::string Name;
+
+ if (E.ExtName.empty()) {
+ Name = std::string(SymbolName);
+ } else {
+ Expected<std::string> ReplacedName =
+ replace(SymbolName, E.Name, E.ExtName);
+ if (!ReplacedName)
+ return ReplacedName.takeError();
+ Name.swap(*ReplacedName);
+ }
- ImportNameType NameType;
- std::string ExportName;
- if (E.Noname) {
- NameType = IMPORT_ORDINAL;
- } else {
- NameType = getNameType(SymbolName, E.Name, Machine, MinGW);
- }
+ ImportNameType NameType;
+ std::string ExportName;
+ if (E.Noname) {
+ NameType = IMPORT_ORDINAL;
+ } else if (!E.ExportAs.empty()) {
+ NameType = IMPORT_NAME_EXPORTAS;
+ ExportName = E.ExportAs;
+ } else if (!E.ImportName.empty()) {
+ // If we need to import from a specific ImportName, we may need to use
+ // a weak alias (which needs another import to point at). But if we can
+ // express ImportName based on the symbol name and a specific NameType,
+ // prefer that over an alias.
+ if (Machine == IMAGE_FILE_MACHINE_I386 &&
+ applyNameType(IMPORT_NAME_UNDECORATE, Name) == E.ImportName)
+ NameType = IMPORT_NAME_UNDECORATE;
+ else if (Machine == IMAGE_FILE_MACHINE_I386 &&
+ applyNameType(IMPORT_NAME_NOPREFIX, Name) == E.ImportName)
+ NameType = IMPORT_NAME_NOPREFIX;
+ else if (isArm64EC(M)) {
+ NameType = IMPORT_NAME_EXPORTAS;
+ ExportName = E.ImportName;
+ } else if (Name == E.ImportName)
+ NameType = IMPORT_NAME;
+ else {
+ Deferred D;
+ D.Name = Name;
+ D.ImpType = ImportType;
+ D.Export = &E;
+ Renames.push_back(D);
+ continue;
+ }
+ } else {
+ NameType = getNameType(SymbolName, E.Name, M, MinGW);
+ }
- // On ARM64EC, use EXPORTAS to import demangled name for mangled symbols.
- if (ImportType == IMPORT_CODE && isArm64EC(Machine)) {
- if (std::optional<std::string> MangledName =
- getArm64ECMangledFunctionName(Name)) {
- if (ExportName.empty()) {
+ // On ARM64EC, use EXPORTAS to import demangled name for mangled symbols.
+ if (ImportType == IMPORT_CODE && isArm64EC(M)) {
+ if (std::optional<std::string> MangledName =
+ getArm64ECMangledFunctionName(Name)) {
+ if (!E.Noname && ExportName.empty()) {
+ NameType = IMPORT_NAME_EXPORTAS;
+ ExportName.swap(Name);
+ }
+ Name = std::move(*MangledName);
+ } else if (!E.Noname && ExportName.empty()) {
NameType = IMPORT_NAME_EXPORTAS;
- ExportName.swap(Name);
+ ExportName = std::move(*getArm64ECDemangledFunctionName(Name));
}
- Name = std::move(*MangledName);
- } else if (ExportName.empty()) {
- NameType = IMPORT_NAME_EXPORTAS;
- ExportName = std::move(*getArm64ECDemangledFunctionName(Name));
+ }
+
+ RegularImports[applyNameType(NameType, Name)] = Name;
+ Members.push_back(OF.createShortImport(Name, E.Ordinal, ImportType,
+ NameType, ExportName, M));
+ }
+ for (const auto &D : Renames) {
+ auto It = RegularImports.find(D.Export->ImportName);
+ if (It != RegularImports.end()) {
+ // We have a regular import entry for a symbol with the name we
+ // want to reference; produce an alias pointing at that.
+ StringRef Symbol = It->second;
+ if (D.ImpType == IMPORT_CODE)
+ Members.push_back(OF.createWeakExternal(Symbol, D.Name, false, M));
+ Members.push_back(OF.createWeakExternal(Symbol, D.Name, true, M));
+ } else {
+ Members.push_back(OF.createShortImport(D.Name, D.Export->Ordinal,
+ D.ImpType, IMPORT_NAME_EXPORTAS,
+ D.Export->ImportName, M));
}
}
+ return Error::success();
+ };
- Members.push_back(OF.createShortImport(Name, E.Ordinal, ImportType,
- NameType, ExportName, Machine));
- }
+ if (Error e = addExports(Exports, Machine))
+ return e;
+ if (Error e = addExports(NativeExports, NativeMachine))
+ return e;
return writeArchive(Path, Members, SymtabWritingMode::NormalSymtab,
- MinGW ? object::Archive::K_GNU : object::Archive::K_COFF,
+ object::Archive::K_COFF,
/*Deterministic*/ true, /*Thin*/ false,
/*OldArchiveBuf*/ nullptr, isArm64EC(Machine));
}
diff --git a/contrib/llvm-project/llvm/lib/Object/COFFModuleDefinition.cpp b/contrib/llvm-project/llvm/lib/Object/COFFModuleDefinition.cpp
index 648f01f823d0..82c18539658e 100644
--- a/contrib/llvm-project/llvm/lib/Object/COFFModuleDefinition.cpp
+++ b/contrib/llvm-project/llvm/lib/Object/COFFModuleDefinition.cpp
@@ -39,6 +39,7 @@ enum Kind {
KwConstant,
KwData,
KwExports,
+ KwExportAs,
KwHeapsize,
KwLibrary,
KwName,
@@ -97,10 +98,8 @@ public:
}
case '=':
Buf = Buf.drop_front();
- if (Buf.starts_with("=")) {
- Buf = Buf.drop_front();
+ if (Buf.consume_front("="))
return Token(EqualEqual, "==");
- }
return Token(Equal, "=");
case ',':
Buf = Buf.drop_front();
@@ -118,6 +117,7 @@ public:
.Case("CONSTANT", KwConstant)
.Case("DATA", KwData)
.Case("EXPORTS", KwExports)
+ .Case("EXPORTAS", KwExportAs)
.Case("HEAPSIZE", KwHeapsize)
.Case("LIBRARY", KwLibrary)
.Case("NAME", KwName)
@@ -281,12 +281,19 @@ private:
}
if (Tok.K == EqualEqual) {
read();
- E.AliasTarget = std::string(Tok.Value);
- if (AddUnderscores && !isDecorated(E.AliasTarget, MingwDef))
- E.AliasTarget = std::string("_").append(E.AliasTarget);
+ E.ImportName = std::string(Tok.Value);
continue;
}
- unget();
+ // EXPORTAS must be at the end of export definition
+ if (Tok.K == KwExportAs) {
+ read();
+ if (Tok.K == Eof)
+ return createError(
+ "unexpected end of file, EXPORTAS identifier expected");
+ E.ExportAs = std::string(Tok.Value);
+ } else {
+ unget();
+ }
Info.Exports.push_back(E);
return Error::success();
}
diff --git a/contrib/llvm-project/llvm/lib/Object/COFFObjectFile.cpp b/contrib/llvm-project/llvm/lib/Object/COFFObjectFile.cpp
index 8700912614db..5a85b8e00c63 100644
--- a/contrib/llvm-project/llvm/lib/Object/COFFObjectFile.cpp
+++ b/contrib/llvm-project/llvm/lib/Object/COFFObjectFile.cpp
@@ -14,18 +14,17 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/ADT/iterator_range.h"
-#include "llvm/BinaryFormat/COFF.h"
#include "llvm/Object/Binary.h"
#include "llvm/Object/COFF.h"
#include "llvm/Object/Error.h"
#include "llvm/Object/ObjectFile.h"
+#include "llvm/Object/WindowsMachineFlag.h"
#include "llvm/Support/BinaryStreamReader.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/MemoryBufferRef.h"
-#include "llvm/TargetParser/Triple.h"
#include <algorithm>
#include <cassert>
#include <cinttypes>
@@ -295,7 +294,7 @@ COFFObjectFile::getSectionContents(DataRefImpl Ref) const {
const coff_section *Sec = toSec(Ref);
ArrayRef<uint8_t> Res;
if (Error E = getSectionContents(Sec, Res))
- return std::move(E);
+ return E;
return Res;
}
@@ -808,7 +807,7 @@ Expected<std::unique_ptr<COFFObjectFile>>
COFFObjectFile::create(MemoryBufferRef Object) {
std::unique_ptr<COFFObjectFile> Obj(new COFFObjectFile(std::move(Object)));
if (Error E = Obj->initialize())
- return std::move(E);
+ return E;
return std::move(Obj);
}
@@ -1072,20 +1071,7 @@ StringRef COFFObjectFile::getFileFormatName() const {
}
Triple::ArchType COFFObjectFile::getArch() const {
- switch (getMachine()) {
- case COFF::IMAGE_FILE_MACHINE_I386:
- return Triple::x86;
- case COFF::IMAGE_FILE_MACHINE_AMD64:
- return Triple::x86_64;
- case COFF::IMAGE_FILE_MACHINE_ARMNT:
- return Triple::thumb;
- case COFF::IMAGE_FILE_MACHINE_ARM64:
- case COFF::IMAGE_FILE_MACHINE_ARM64EC:
- case COFF::IMAGE_FILE_MACHINE_ARM64X:
- return Triple::aarch64;
- default:
- return Triple::UnknownArch;
- }
+ return getMachineArchType(getMachine());
}
Expected<uint64_t> COFFObjectFile::getStartAddress() const {
@@ -1320,8 +1306,8 @@ COFFObjectFile::getRelocations(const coff_section *Sec) const {
return #reloc_type;
StringRef COFFObjectFile::getRelocationTypeName(uint16_t Type) const {
- switch (getMachine()) {
- case COFF::IMAGE_FILE_MACHINE_AMD64:
+ switch (getArch()) {
+ case Triple::x86_64:
switch (Type) {
LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ABSOLUTE);
LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR64);
@@ -1344,7 +1330,7 @@ StringRef COFFObjectFile::getRelocationTypeName(uint16_t Type) const {
return "Unknown";
}
break;
- case COFF::IMAGE_FILE_MACHINE_ARMNT:
+ case Triple::thumb:
switch (Type) {
LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ABSOLUTE);
LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32);
@@ -1367,9 +1353,7 @@ StringRef COFFObjectFile::getRelocationTypeName(uint16_t Type) const {
return "Unknown";
}
break;
- case COFF::IMAGE_FILE_MACHINE_ARM64:
- case COFF::IMAGE_FILE_MACHINE_ARM64EC:
- case COFF::IMAGE_FILE_MACHINE_ARM64X:
+ case Triple::aarch64:
switch (Type) {
LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ABSOLUTE);
LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM64_ADDR32);
@@ -1393,7 +1377,7 @@ StringRef COFFObjectFile::getRelocationTypeName(uint16_t Type) const {
return "Unknown";
}
break;
- case COFF::IMAGE_FILE_MACHINE_I386:
+ case Triple::x86:
switch (Type) {
LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_ABSOLUTE);
LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR16);
@@ -1941,19 +1925,17 @@ ResourceSectionRef::getContents(const coff_resource_data_entry &Entry) {
// the expected type.
const coff_relocation &R = **RelocsForOffset.first;
uint16_t RVAReloc;
- switch (Obj->getMachine()) {
- case COFF::IMAGE_FILE_MACHINE_I386:
+ switch (Obj->getArch()) {
+ case Triple::x86:
RVAReloc = COFF::IMAGE_REL_I386_DIR32NB;
break;
- case COFF::IMAGE_FILE_MACHINE_AMD64:
+ case Triple::x86_64:
RVAReloc = COFF::IMAGE_REL_AMD64_ADDR32NB;
break;
- case COFF::IMAGE_FILE_MACHINE_ARMNT:
+ case Triple::thumb:
RVAReloc = COFF::IMAGE_REL_ARM_ADDR32NB;
break;
- case COFF::IMAGE_FILE_MACHINE_ARM64:
- case COFF::IMAGE_FILE_MACHINE_ARM64EC:
- case COFF::IMAGE_FILE_MACHINE_ARM64X:
+ case Triple::aarch64:
RVAReloc = COFF::IMAGE_REL_ARM64_ADDR32NB;
break;
default:
@@ -1977,7 +1959,7 @@ ResourceSectionRef::getContents(const coff_resource_data_entry &Entry) {
uint64_t Offset = Entry.DataRVA + Sym->getValue();
ArrayRef<uint8_t> Contents;
if (Error E = Obj->getSectionContents(*Section, Contents))
- return std::move(E);
+ return E;
if (Offset + Entry.DataSize > Contents.size())
return createStringError(object_error::parse_failed,
"data outside of section");
diff --git a/contrib/llvm-project/llvm/lib/Object/DXContainer.cpp b/contrib/llvm-project/llvm/lib/Object/DXContainer.cpp
index 4aabe9cea3e5..3b1a6203a1f8 100644
--- a/contrib/llvm-project/llvm/lib/Object/DXContainer.cpp
+++ b/contrib/llvm-project/llvm/lib/Object/DXContainer.cpp
@@ -72,13 +72,13 @@ Error DXContainer::parseDXILHeader(StringRef Part) {
return Error::success();
}
-Error DXContainer::parseShaderFlags(StringRef Part) {
- if (ShaderFlags)
+Error DXContainer::parseShaderFeatureFlags(StringRef Part) {
+ if (ShaderFeatureFlags)
return parseFailed("More than one SFI0 part is present in the file");
uint64_t FlagValue = 0;
if (Error Err = readInteger(Part, Part.begin(), FlagValue))
return Err;
- ShaderFlags = FlagValue;
+ ShaderFeatureFlags = FlagValue;
return Error::success();
}
@@ -168,7 +168,7 @@ Error DXContainer::parsePartOffsets() {
return Err;
break;
case dxbc::PartType::SFI0:
- if (Error Err = parseShaderFlags(PartData))
+ if (Error Err = parseShaderFeatureFlags(PartData))
return Err;
break;
case dxbc::PartType::HASH:
@@ -247,7 +247,14 @@ Error DirectX::PSVRuntimeInfo::parse(uint16_t ShaderKind) {
const uint32_t PSVVersion = getVersion();
// Detect the PSVVersion by looking at the size field.
- if (PSVVersion == 2) {
+ if (PSVVersion == 3) {
+ v3::RuntimeInfo Info;
+ if (Error Err = readStruct(PSVInfoData, Current, Info))
+ return Err;
+ if (sys::IsBigEndianHost)
+ Info.swapBytes(ShaderStage);
+ BasicInfo = Info;
+ } else if (PSVVersion == 2) {
v2::RuntimeInfo Info;
if (Error Err = readStruct(PSVInfoData, Current, Info))
return Err;
@@ -341,7 +348,8 @@ Error DirectX::PSVRuntimeInfo::parse(uint16_t ShaderKind) {
SigOutputElements.Stride = SigPatchOrPrimElements.Stride =
SigInputElements.Stride;
- if (Data.end() - Current < ElementCount * SigInputElements.Stride)
+ if (Data.end() - Current <
+ (ptrdiff_t)(ElementCount * SigInputElements.Stride))
return parseFailed(
"Signature elements extend beyond the size of the part");
@@ -424,6 +432,8 @@ Error DirectX::PSVRuntimeInfo::parse(uint16_t ShaderKind) {
}
uint8_t DirectX::PSVRuntimeInfo::getSigInputCount() const {
+ if (const auto *P = std::get_if<dxbc::PSV::v3::RuntimeInfo>(&BasicInfo))
+ return P->SigInputElements;
if (const auto *P = std::get_if<dxbc::PSV::v2::RuntimeInfo>(&BasicInfo))
return P->SigInputElements;
if (const auto *P = std::get_if<dxbc::PSV::v1::RuntimeInfo>(&BasicInfo))
@@ -432,6 +442,8 @@ uint8_t DirectX::PSVRuntimeInfo::getSigInputCount() const {
}
uint8_t DirectX::PSVRuntimeInfo::getSigOutputCount() const {
+ if (const auto *P = std::get_if<dxbc::PSV::v3::RuntimeInfo>(&BasicInfo))
+ return P->SigOutputElements;
if (const auto *P = std::get_if<dxbc::PSV::v2::RuntimeInfo>(&BasicInfo))
return P->SigOutputElements;
if (const auto *P = std::get_if<dxbc::PSV::v1::RuntimeInfo>(&BasicInfo))
@@ -440,6 +452,8 @@ uint8_t DirectX::PSVRuntimeInfo::getSigOutputCount() const {
}
uint8_t DirectX::PSVRuntimeInfo::getSigPatchOrPrimCount() const {
+ if (const auto *P = std::get_if<dxbc::PSV::v3::RuntimeInfo>(&BasicInfo))
+ return P->SigPatchOrPrimElements;
if (const auto *P = std::get_if<dxbc::PSV::v2::RuntimeInfo>(&BasicInfo))
return P->SigPatchOrPrimElements;
if (const auto *P = std::get_if<dxbc::PSV::v1::RuntimeInfo>(&BasicInfo))
diff --git a/contrib/llvm-project/llvm/lib/Object/ELF.cpp b/contrib/llvm-project/llvm/lib/Object/ELF.cpp
index f24395b02043..e47a40b8715d 100644
--- a/contrib/llvm-project/llvm/lib/Object/ELF.cpp
+++ b/contrib/llvm-project/llvm/lib/Object/ELF.cpp
@@ -251,7 +251,10 @@ StringRef llvm::object::getELFSectionTypeName(uint32_t Machine, unsigned Type) {
}
break;
case ELF::EM_HEXAGON:
- switch (Type) { STRINGIFY_ENUM_CASE(ELF, SHT_HEX_ORDERED); }
+ switch (Type) {
+ STRINGIFY_ENUM_CASE(ELF, SHT_HEX_ORDERED);
+ STRINGIFY_ENUM_CASE(ELF, SHT_HEXAGON_ATTRIBUTES);
+ }
break;
case ELF::EM_X86_64:
switch (Type) { STRINGIFY_ENUM_CASE(ELF, SHT_X86_64_UNWIND); }
@@ -300,6 +303,7 @@ StringRef llvm::object::getELFSectionTypeName(uint32_t Machine, unsigned Type) {
STRINGIFY_ENUM_CASE(ELF, SHT_GROUP);
STRINGIFY_ENUM_CASE(ELF, SHT_SYMTAB_SHNDX);
STRINGIFY_ENUM_CASE(ELF, SHT_RELR);
+ STRINGIFY_ENUM_CASE(ELF, SHT_CREL);
STRINGIFY_ENUM_CASE(ELF, SHT_ANDROID_REL);
STRINGIFY_ENUM_CASE(ELF, SHT_ANDROID_RELA);
STRINGIFY_ENUM_CASE(ELF, SHT_ANDROID_RELR);
@@ -390,6 +394,58 @@ ELFFile<ELFT>::decode_relrs(Elf_Relr_Range relrs) const {
}
template <class ELFT>
+Expected<uint64_t>
+ELFFile<ELFT>::getCrelHeader(ArrayRef<uint8_t> Content) const {
+ DataExtractor Data(Content, isLE(), sizeof(typename ELFT::Addr));
+ Error Err = Error::success();
+ uint64_t Hdr = 0;
+ Hdr = Data.getULEB128(&Hdr, &Err);
+ if (Err)
+ return Err;
+ return Hdr;
+}
+
+template <class ELFT>
+Expected<typename ELFFile<ELFT>::RelsOrRelas>
+ELFFile<ELFT>::decodeCrel(ArrayRef<uint8_t> Content) const {
+ std::vector<Elf_Rel> Rels;
+ std::vector<Elf_Rela> Relas;
+ size_t I = 0;
+ bool HasAddend;
+ Error Err = object::decodeCrel<ELFT::Is64Bits>(
+ Content,
+ [&](uint64_t Count, bool HasA) {
+ HasAddend = HasA;
+ if (HasAddend)
+ Relas.resize(Count);
+ else
+ Rels.resize(Count);
+ },
+ [&](Elf_Crel Crel) {
+ if (HasAddend) {
+ Relas[I].r_offset = Crel.r_offset;
+ Relas[I].setSymbolAndType(Crel.r_symidx, Crel.r_type, false);
+ Relas[I++].r_addend = Crel.r_addend;
+ } else {
+ Rels[I].r_offset = Crel.r_offset;
+ Rels[I++].setSymbolAndType(Crel.r_symidx, Crel.r_type, false);
+ }
+ });
+ if (Err)
+ return std::move(Err);
+ return std::make_pair(std::move(Rels), std::move(Relas));
+}
+
+template <class ELFT>
+Expected<typename ELFFile<ELFT>::RelsOrRelas>
+ELFFile<ELFT>::crels(const Elf_Shdr &Sec) const {
+ Expected<ArrayRef<uint8_t>> ContentsOrErr = getSectionContents(Sec);
+ if (!ContentsOrErr)
+ return ContentsOrErr.takeError();
+ return decodeCrel(*ContentsOrErr);
+}
+
+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,
@@ -557,7 +613,11 @@ Expected<typename ELFT::DynRange> ELFFile<ELFT>::dynamicEntries() const {
for (const Elf_Phdr &Phdr : *ProgramHeadersOrError) {
if (Phdr.p_type == ELF::PT_DYNAMIC) {
- Dyn = ArrayRef(reinterpret_cast<const Elf_Dyn *>(base() + Phdr.p_offset),
+ const uint8_t *DynOffset = base() + Phdr.p_offset;
+ if (DynOffset > end())
+ return createError(
+ "dynamic section offset past file size: corrupted ELF");
+ Dyn = ArrayRef(reinterpret_cast<const Elf_Dyn *>(DynOffset),
Phdr.p_filesz / sizeof(Elf_Dyn));
break;
}
@@ -693,6 +753,17 @@ decodeBBAddrMapImpl(const ELFFile<ELFT> &EF,
for (typename ELFFile<ELFT>::Elf_Rela Rela : *Relas)
FunctionOffsetTranslations[Rela.r_offset] = Rela.r_addend;
}
+ auto GetAddressForRelocation =
+ [&](unsigned RelocationOffsetInSection) -> Expected<unsigned> {
+ auto FOTIterator =
+ FunctionOffsetTranslations.find(RelocationOffsetInSection);
+ if (FOTIterator == FunctionOffsetTranslations.end()) {
+ return createError("failed to get relocation data for offset: " +
+ Twine::utohexstr(RelocationOffsetInSection) +
+ " in section " + describe(EF, Sec));
+ }
+ return FOTIterator->second;
+ };
Expected<ArrayRef<uint8_t>> ContentsOrErr = EF.getSectionContents(Sec);
if (!ContentsOrErr)
return ContentsOrErr.takeError();
@@ -704,9 +775,26 @@ decodeBBAddrMapImpl(const ELFFile<ELFT> &EF,
Error ULEBSizeErr = Error::success();
Error MetadataDecodeErr = Error::success();
+ // Helper lampda to extract the (possiblly relocatable) address stored at Cur.
+ auto ExtractAddress = [&]() -> Expected<typename ELFFile<ELFT>::uintX_t> {
+ uint64_t RelocationOffsetInSection = Cur.tell();
+ auto Address =
+ static_cast<typename ELFFile<ELFT>::uintX_t>(Data.getAddress(Cur));
+ if (!Cur)
+ return Cur.takeError();
+ if (!IsRelocatable)
+ return Address;
+ assert(Address == 0);
+ Expected<unsigned> AddressOrErr =
+ GetAddressForRelocation(RelocationOffsetInSection);
+ if (!AddressOrErr)
+ return AddressOrErr.takeError();
+ return *AddressOrErr;
+ };
+
uint8_t Version = 0;
uint8_t Feature = 0;
- PGOAnalysisMap::Features FeatEnable{};
+ BBAddrMap::Features FeatEnable{};
while (!ULEBSizeErr && !MetadataDecodeErr && Cur &&
Cur.tell() < Content.size()) {
if (Sec.sh_type == ELF::SHT_LLVM_BB_ADDR_MAP) {
@@ -719,11 +807,10 @@ decodeBBAddrMapImpl(const ELFFile<ELFT> &EF,
Feature = Data.getU8(Cur); // Feature byte
if (!Cur)
break;
- auto FeatEnableOrErr = PGOAnalysisMap::Features::decode(Feature);
+ auto FeatEnableOrErr = BBAddrMap::Features::decode(Feature);
if (!FeatEnableOrErr)
return FeatEnableOrErr.takeError();
- FeatEnable =
- FeatEnableOrErr ? *FeatEnableOrErr : PGOAnalysisMap::Features{};
+ FeatEnable = *FeatEnableOrErr;
if (Feature != 0 && Version < 2 && Cur)
return createError(
"version should be >= 2 for SHT_LLVM_BB_ADDR_MAP when "
@@ -731,50 +818,65 @@ decodeBBAddrMapImpl(const ELFFile<ELFT> &EF,
Twine(static_cast<int>(Version)) +
" feature = " + Twine(static_cast<int>(Feature)));
}
- uint64_t SectionOffset = Cur.tell();
- auto Address =
- static_cast<typename ELFFile<ELFT>::uintX_t>(Data.getAddress(Cur));
- if (!Cur)
- return Cur.takeError();
- if (IsRelocatable) {
- assert(Address == 0);
- auto FOTIterator = FunctionOffsetTranslations.find(SectionOffset);
- if (FOTIterator == FunctionOffsetTranslations.end()) {
- return createError("failed to get relocation data for offset: " +
- Twine::utohexstr(SectionOffset) + " in section " +
- describe(EF, Sec));
- }
- Address = FOTIterator->second;
- }
- uint32_t NumBlocks = readULEB128As<uint32_t>(Data, Cur, ULEBSizeErr);
-
+ uint32_t NumBlocksInBBRange = 0;
+ uint32_t NumBBRanges = 1;
+ typename ELFFile<ELFT>::uintX_t RangeBaseAddress = 0;
std::vector<BBAddrMap::BBEntry> BBEntries;
- uint32_t PrevBBEndOffset = 0;
- for (uint32_t BlockIndex = 0;
- !MetadataDecodeErr && !ULEBSizeErr && Cur && (BlockIndex < NumBlocks);
- ++BlockIndex) {
- uint32_t ID = Version >= 2
- ? readULEB128As<uint32_t>(Data, Cur, ULEBSizeErr)
- : BlockIndex;
- uint32_t Offset = readULEB128As<uint32_t>(Data, Cur, ULEBSizeErr);
- uint32_t Size = readULEB128As<uint32_t>(Data, Cur, ULEBSizeErr);
- uint32_t MD = readULEB128As<uint32_t>(Data, Cur, ULEBSizeErr);
- if (Version >= 1) {
- // Offset is calculated relative to the end of the previous BB.
- Offset += PrevBBEndOffset;
- PrevBBEndOffset = Offset + Size;
- }
- Expected<BBAddrMap::BBEntry::Metadata> MetadataOrErr =
- BBAddrMap::BBEntry::Metadata::decode(MD);
- if (!MetadataOrErr) {
- MetadataDecodeErr = MetadataOrErr.takeError();
+ if (FeatEnable.MultiBBRange) {
+ NumBBRanges = readULEB128As<uint32_t>(Data, Cur, ULEBSizeErr);
+ if (!Cur || ULEBSizeErr)
break;
+ if (!NumBBRanges)
+ return createError("invalid zero number of BB ranges at offset " +
+ Twine::utohexstr(Cur.tell()) + " in " +
+ describe(EF, Sec));
+ } else {
+ auto AddressOrErr = ExtractAddress();
+ if (!AddressOrErr)
+ return AddressOrErr.takeError();
+ RangeBaseAddress = *AddressOrErr;
+ NumBlocksInBBRange = readULEB128As<uint32_t>(Data, Cur, ULEBSizeErr);
+ }
+ std::vector<BBAddrMap::BBRangeEntry> BBRangeEntries;
+ uint32_t TotalNumBlocks = 0;
+ for (uint32_t BBRangeIndex = 0; BBRangeIndex < NumBBRanges;
+ ++BBRangeIndex) {
+ uint32_t PrevBBEndOffset = 0;
+ if (FeatEnable.MultiBBRange) {
+ auto AddressOrErr = ExtractAddress();
+ if (!AddressOrErr)
+ return AddressOrErr.takeError();
+ RangeBaseAddress = *AddressOrErr;
+ NumBlocksInBBRange = readULEB128As<uint32_t>(Data, Cur, ULEBSizeErr);
+ }
+ for (uint32_t BlockIndex = 0; !MetadataDecodeErr && !ULEBSizeErr && Cur &&
+ (BlockIndex < NumBlocksInBBRange);
+ ++BlockIndex) {
+ uint32_t ID = Version >= 2
+ ? readULEB128As<uint32_t>(Data, Cur, ULEBSizeErr)
+ : BlockIndex;
+ uint32_t Offset = readULEB128As<uint32_t>(Data, Cur, ULEBSizeErr);
+ uint32_t Size = readULEB128As<uint32_t>(Data, Cur, ULEBSizeErr);
+ uint32_t MD = readULEB128As<uint32_t>(Data, Cur, ULEBSizeErr);
+ if (Version >= 1) {
+ // Offset is calculated relative to the end of the previous BB.
+ Offset += PrevBBEndOffset;
+ PrevBBEndOffset = Offset + Size;
+ }
+ Expected<BBAddrMap::BBEntry::Metadata> MetadataOrErr =
+ BBAddrMap::BBEntry::Metadata::decode(MD);
+ if (!MetadataOrErr) {
+ MetadataDecodeErr = MetadataOrErr.takeError();
+ break;
+ }
+ BBEntries.push_back({ID, Offset, Size, *MetadataOrErr});
}
- BBEntries.push_back({ID, Offset, Size, *MetadataOrErr});
+ TotalNumBlocks += BBEntries.size();
+ BBRangeEntries.push_back({RangeBaseAddress, std::move(BBEntries)});
}
- FunctionEntries.emplace_back(Address, std::move(BBEntries));
+ FunctionEntries.push_back({std::move(BBRangeEntries)});
- if (PGOAnalyses || FeatEnable.anyEnabled()) {
+ if (PGOAnalyses || FeatEnable.hasPGOAnalysis()) {
// Function entry count
uint64_t FuncEntryCount =
FeatEnable.FuncEntryCount
@@ -783,8 +885,8 @@ decodeBBAddrMapImpl(const ELFFile<ELFT> &EF,
std::vector<PGOAnalysisMap::PGOBBEntry> PGOBBEntries;
for (uint32_t BlockIndex = 0;
- (FeatEnable.BBFreq || FeatEnable.BrProb) && !MetadataDecodeErr &&
- !ULEBSizeErr && Cur && (BlockIndex < NumBlocks);
+ FeatEnable.hasPGOAnalysisBBData() && !MetadataDecodeErr &&
+ !ULEBSizeErr && Cur && (BlockIndex < TotalNumBlocks);
++BlockIndex) {
// Block frequency
uint64_t BBF = FeatEnable.BBFreq
diff --git a/contrib/llvm-project/llvm/lib/Object/ELFObjectFile.cpp b/contrib/llvm-project/llvm/lib/Object/ELFObjectFile.cpp
index 28b96c341e3f..53c3de06d118 100644
--- a/contrib/llvm-project/llvm/lib/Object/ELFObjectFile.cpp
+++ b/contrib/llvm-project/llvm/lib/Object/ELFObjectFile.cpp
@@ -20,10 +20,11 @@
#include "llvm/Support/ARMAttributeParser.h"
#include "llvm/Support/ARMBuildAttributes.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/HexagonAttributeParser.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/RISCVAttributeParser.h"
#include "llvm/Support/RISCVAttributes.h"
-#include "llvm/Support/RISCVISAInfo.h"
+#include "llvm/TargetParser/RISCVISAInfo.h"
#include "llvm/TargetParser/SubtargetFeature.h"
#include "llvm/TargetParser/Triple.h"
#include <algorithm>
@@ -287,12 +288,87 @@ SubtargetFeatures ELFObjectFileBase::getARMFeatures() const {
return Features;
}
+static std::optional<std::string> hexagonAttrToFeatureString(unsigned Attr) {
+ switch (Attr) {
+ case 5:
+ return "v5";
+ case 55:
+ return "v55";
+ case 60:
+ return "v60";
+ case 62:
+ return "v62";
+ case 65:
+ return "v65";
+ case 67:
+ return "v67";
+ case 68:
+ return "v68";
+ case 69:
+ return "v69";
+ case 71:
+ return "v71";
+ case 73:
+ return "v73";
+ default:
+ return {};
+ }
+}
+
+SubtargetFeatures ELFObjectFileBase::getHexagonFeatures() const {
+ SubtargetFeatures Features;
+ HexagonAttributeParser Parser;
+ if (Error E = getBuildAttributes(Parser)) {
+ // Return no attributes if none can be read.
+ // This behavior is important for backwards compatibility.
+ consumeError(std::move(E));
+ return Features;
+ }
+ std::optional<unsigned> Attr;
+
+ if ((Attr = Parser.getAttributeValue(HexagonAttrs::ARCH))) {
+ if (std::optional<std::string> FeatureString =
+ hexagonAttrToFeatureString(*Attr))
+ Features.AddFeature(*FeatureString);
+ }
+
+ if ((Attr = Parser.getAttributeValue(HexagonAttrs::HVXARCH))) {
+ std::optional<std::string> FeatureString =
+ hexagonAttrToFeatureString(*Attr);
+ // There is no corresponding hvx arch for v5 and v55.
+ if (FeatureString && *Attr >= 60)
+ Features.AddFeature("hvx" + *FeatureString);
+ }
+
+ if ((Attr = Parser.getAttributeValue(HexagonAttrs::HVXIEEEFP)))
+ if (*Attr)
+ Features.AddFeature("hvx-ieee-fp");
+
+ if ((Attr = Parser.getAttributeValue(HexagonAttrs::HVXQFLOAT)))
+ if (*Attr)
+ Features.AddFeature("hvx-qfloat");
+
+ if ((Attr = Parser.getAttributeValue(HexagonAttrs::ZREG)))
+ if (*Attr)
+ Features.AddFeature("zreg");
+
+ if ((Attr = Parser.getAttributeValue(HexagonAttrs::AUDIO)))
+ if (*Attr)
+ Features.AddFeature("audio");
+
+ if ((Attr = Parser.getAttributeValue(HexagonAttrs::CABAC)))
+ if (*Attr)
+ Features.AddFeature("cabac");
+
+ return Features;
+}
+
Expected<SubtargetFeatures> ELFObjectFileBase::getRISCVFeatures() const {
SubtargetFeatures Features;
unsigned PlatformFlags = getPlatformFlags();
if (PlatformFlags & ELF::EF_RISCV_RVC) {
- Features.AddFeature("c");
+ Features.AddFeature("zca");
}
RISCVAttributeParser Attributes;
@@ -349,6 +425,8 @@ Expected<SubtargetFeatures> ELFObjectFileBase::getFeatures() const {
return getRISCVFeatures();
case ELF::EM_LOONGARCH:
return getLoongArchFeatures();
+ case ELF::EM_HEXAGON:
+ return getHexagonFeatures();
default:
return SubtargetFeatures();
}
@@ -508,12 +586,26 @@ StringRef ELFObjectFileBase::getAMDGPUCPUName() const {
return "gfx1150";
case ELF::EF_AMDGPU_MACH_AMDGCN_GFX1151:
return "gfx1151";
+ case ELF::EF_AMDGPU_MACH_AMDGCN_GFX1152:
+ return "gfx1152";
// AMDGCN GFX12.
case ELF::EF_AMDGPU_MACH_AMDGCN_GFX1200:
return "gfx1200";
case ELF::EF_AMDGPU_MACH_AMDGCN_GFX1201:
return "gfx1201";
+
+ // Generic AMDGCN targets
+ case ELF::EF_AMDGPU_MACH_AMDGCN_GFX9_GENERIC:
+ return "gfx9-generic";
+ case ELF::EF_AMDGPU_MACH_AMDGCN_GFX10_1_GENERIC:
+ return "gfx10-1-generic";
+ case ELF::EF_AMDGPU_MACH_AMDGCN_GFX10_3_GENERIC:
+ return "gfx10-3-generic";
+ case ELF::EF_AMDGPU_MACH_AMDGCN_GFX11_GENERIC:
+ return "gfx11-generic";
+ case ELF::EF_AMDGPU_MACH_AMDGCN_GFX12_GENERIC:
+ return "gfx12-generic";
default:
llvm_unreachable("Unknown EF_AMDGPU_MACH value");
}
@@ -805,7 +897,10 @@ Expected<std::vector<BBAddrMap>> static readBBAddrMapImpl(
return createError("unable to get the linked-to section for " +
describe(EF, Sec) + ": " +
toString(TextSecOrErr.takeError()));
- if (*TextSectionIndex != std::distance(Sections.begin(), *TextSecOrErr))
+ assert(*TextSecOrErr >= Sections.begin() &&
+ "Text section pointer outside of bounds");
+ if (*TextSectionIndex !=
+ (unsigned)std::distance(Sections.begin(), *TextSecOrErr))
return false;
return true;
};
@@ -918,3 +1013,14 @@ Expected<std::vector<BBAddrMap>> ELFObjectFileBase::readBBAddrMap(
return readBBAddrMapImpl(cast<ELF64BEObjectFile>(this)->getELFFile(),
TextSectionIndex, PGOAnalyses);
}
+
+StringRef ELFObjectFileBase::getCrelDecodeProblem(SectionRef Sec) const {
+ auto Data = Sec.getRawDataRefImpl();
+ if (const auto *Obj = dyn_cast<ELF32LEObjectFile>(this))
+ return Obj->getCrelDecodeProblem(Data);
+ if (const auto *Obj = dyn_cast<ELF32BEObjectFile>(this))
+ return Obj->getCrelDecodeProblem(Data);
+ if (const auto *Obj = dyn_cast<ELF64LEObjectFile>(this))
+ return Obj->getCrelDecodeProblem(Data);
+ return cast<ELF64BEObjectFile>(this)->getCrelDecodeProblem(Data);
+}
diff --git a/contrib/llvm-project/llvm/lib/Object/GOFFObjectFile.cpp b/contrib/llvm-project/llvm/lib/Object/GOFFObjectFile.cpp
index 76a13559ebfe..3b8704f28fdb 100644
--- a/contrib/llvm-project/llvm/lib/Object/GOFFObjectFile.cpp
+++ b/contrib/llvm-project/llvm/lib/Object/GOFFObjectFile.cpp
@@ -104,16 +104,13 @@ GOFFObjectFile::GOFFObjectFile(MemoryBufferRef Object, Error &Err)
PrevContinuationBits = I[1] & 0x03;
continue;
}
-
-#ifndef NDEBUG
- for (size_t J = 0; J < GOFF::RecordLength; ++J) {
+ LLVM_DEBUG(for (size_t J = 0; J < GOFF::RecordLength; ++J) {
const uint8_t *P = I + J;
if (J % 8 == 0)
dbgs() << " ";
-
dbgs() << format("%02hhX", *P);
- }
-#endif
+ });
+
switch (RecordType) {
case GOFF::RT_ESD: {
// Save ESD record.
@@ -168,6 +165,11 @@ GOFFObjectFile::GOFFObjectFile(MemoryBufferRef Object, Error &Err)
LLVM_DEBUG(dbgs() << " -- ESD " << EsdId << "\n");
break;
}
+ case GOFF::RT_TXT:
+ // Save TXT records.
+ TextPtrs.emplace_back(I);
+ LLVM_DEBUG(dbgs() << " -- TXT\n");
+ break;
case GOFF::RT_END:
LLVM_DEBUG(dbgs() << " -- END (GOFF record type) unhandled\n");
break;
@@ -364,6 +366,13 @@ GOFFObjectFile::getSymbolSection(DataRefImpl Symb) const {
std::to_string(SymEdId));
}
+uint64_t GOFFObjectFile::getSymbolSize(DataRefImpl Symb) const {
+ const uint8_t *Record = getSymbolEsdRecord(Symb);
+ uint32_t Length;
+ ESDRecord::getLength(Record, Length);
+ return Length;
+}
+
const uint8_t *GOFFObjectFile::getSectionEdEsdRecord(DataRefImpl &Sec) const {
SectionEntryImpl EsdIds = SectionList[Sec.d.a];
const uint8_t *EsdRecord = EsdPtrs[EsdIds.d.a];
@@ -394,6 +403,154 @@ GOFFObjectFile::getSectionPrEsdRecord(uint32_t SectionIndex) const {
return EsdRecord;
}
+uint32_t GOFFObjectFile::getSectionDefEsdId(DataRefImpl &Sec) const {
+ const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec);
+ uint32_t Length;
+ ESDRecord::getLength(EsdRecord, Length);
+ if (Length == 0) {
+ const uint8_t *PrEsdRecord = getSectionPrEsdRecord(Sec);
+ if (PrEsdRecord)
+ EsdRecord = PrEsdRecord;
+ }
+
+ uint32_t DefEsdId;
+ ESDRecord::getEsdId(EsdRecord, DefEsdId);
+ LLVM_DEBUG(dbgs() << "Got def EsdId: " << DefEsdId << '\n');
+ return DefEsdId;
+}
+
+void GOFFObjectFile::moveSectionNext(DataRefImpl &Sec) const {
+ Sec.d.a++;
+ if ((Sec.d.a) >= SectionList.size())
+ Sec.d.a = 0;
+}
+
+Expected<StringRef> GOFFObjectFile::getSectionName(DataRefImpl Sec) const {
+ DataRefImpl EdSym;
+ SectionEntryImpl EsdIds = SectionList[Sec.d.a];
+ EdSym.d.a = EsdIds.d.a;
+ Expected<StringRef> Name = getSymbolName(EdSym);
+ if (Name) {
+ StringRef Res = *Name;
+ LLVM_DEBUG(dbgs() << "Got section: " << Res << '\n');
+ LLVM_DEBUG(dbgs() << "Final section name: " << Res << '\n');
+ Name = Res;
+ }
+ return Name;
+}
+
+uint64_t GOFFObjectFile::getSectionAddress(DataRefImpl Sec) const {
+ uint32_t Offset;
+ const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec);
+ ESDRecord::getOffset(EsdRecord, Offset);
+ return Offset;
+}
+
+uint64_t GOFFObjectFile::getSectionSize(DataRefImpl Sec) const {
+ uint32_t Length;
+ uint32_t DefEsdId = getSectionDefEsdId(Sec);
+ const uint8_t *EsdRecord = EsdPtrs[DefEsdId];
+ ESDRecord::getLength(EsdRecord, Length);
+ LLVM_DEBUG(dbgs() << "Got section size: " << Length << '\n');
+ return static_cast<uint64_t>(Length);
+}
+
+// Unravel TXT records and expand fill characters to produce
+// a contiguous sequence of bytes.
+Expected<ArrayRef<uint8_t>>
+GOFFObjectFile::getSectionContents(DataRefImpl Sec) const {
+ if (SectionDataCache.count(Sec.d.a)) {
+ auto &Buf = SectionDataCache[Sec.d.a];
+ return ArrayRef<uint8_t>(Buf);
+ }
+ uint64_t SectionSize = getSectionSize(Sec);
+ uint32_t DefEsdId = getSectionDefEsdId(Sec);
+
+ const uint8_t *EdEsdRecord = getSectionEdEsdRecord(Sec);
+ bool FillBytePresent;
+ ESDRecord::getFillBytePresent(EdEsdRecord, FillBytePresent);
+ uint8_t FillByte = '\0';
+ if (FillBytePresent)
+ ESDRecord::getFillByteValue(EdEsdRecord, FillByte);
+
+ // Initialize section with fill byte.
+ SmallVector<uint8_t> Data(SectionSize, FillByte);
+
+ // Replace section with content from text records.
+ for (const uint8_t *TxtRecordInt : TextPtrs) {
+ const uint8_t *TxtRecordPtr = TxtRecordInt;
+ uint32_t TxtEsdId;
+ TXTRecord::getElementEsdId(TxtRecordPtr, TxtEsdId);
+ LLVM_DEBUG(dbgs() << "Got txt EsdId: " << TxtEsdId << '\n');
+
+ if (TxtEsdId != DefEsdId)
+ continue;
+
+ uint32_t TxtDataOffset;
+ TXTRecord::getOffset(TxtRecordPtr, TxtDataOffset);
+
+ uint16_t TxtDataSize;
+ TXTRecord::getDataLength(TxtRecordPtr, TxtDataSize);
+
+ LLVM_DEBUG(dbgs() << "Record offset " << TxtDataOffset << ", data size "
+ << TxtDataSize << "\n");
+
+ SmallString<256> CompleteData;
+ CompleteData.reserve(TxtDataSize);
+ if (Error Err = TXTRecord::getData(TxtRecordPtr, CompleteData))
+ return std::move(Err);
+ assert(CompleteData.size() == TxtDataSize && "Wrong length of data");
+ std::copy(CompleteData.data(), CompleteData.data() + TxtDataSize,
+ Data.begin() + TxtDataOffset);
+ }
+ SectionDataCache[Sec.d.a] = Data;
+ return ArrayRef<uint8_t>(SectionDataCache[Sec.d.a]);
+}
+
+uint64_t GOFFObjectFile::getSectionAlignment(DataRefImpl Sec) const {
+ const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec);
+ GOFF::ESDAlignment Pow2Alignment;
+ ESDRecord::getAlignment(EsdRecord, Pow2Alignment);
+ return 1ULL << static_cast<uint64_t>(Pow2Alignment);
+}
+
+bool GOFFObjectFile::isSectionText(DataRefImpl Sec) const {
+ const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec);
+ GOFF::ESDExecutable Executable;
+ ESDRecord::getExecutable(EsdRecord, Executable);
+ return Executable == GOFF::ESD_EXE_CODE;
+}
+
+bool GOFFObjectFile::isSectionData(DataRefImpl Sec) const {
+ const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec);
+ GOFF::ESDExecutable Executable;
+ ESDRecord::getExecutable(EsdRecord, Executable);
+ return Executable == GOFF::ESD_EXE_DATA;
+}
+
+bool GOFFObjectFile::isSectionNoLoad(DataRefImpl Sec) const {
+ const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec);
+ GOFF::ESDLoadingBehavior LoadingBehavior;
+ ESDRecord::getLoadingBehavior(EsdRecord, LoadingBehavior);
+ return LoadingBehavior == GOFF::ESD_LB_NoLoad;
+}
+
+bool GOFFObjectFile::isSectionReadOnlyData(DataRefImpl Sec) const {
+ if (!isSectionData(Sec))
+ return false;
+
+ const uint8_t *EsdRecord = getSectionEdEsdRecord(Sec);
+ GOFF::ESDLoadingBehavior LoadingBehavior;
+ ESDRecord::getLoadingBehavior(EsdRecord, LoadingBehavior);
+ return LoadingBehavior == GOFF::ESD_LB_Initial;
+}
+
+bool GOFFObjectFile::isSectionZeroInit(DataRefImpl Sec) const {
+ // GOFF uses fill characters and fill characters are applied
+ // on getSectionContents() - so we say false to zero init.
+ return false;
+}
+
section_iterator GOFFObjectFile::section_begin() const {
DataRefImpl Sec;
moveSectionNext(Sec);
@@ -476,6 +633,13 @@ Error ESDRecord::getData(const uint8_t *Record,
return getContinuousData(Record, DataSize, 72, CompleteData);
}
+Error TXTRecord::getData(const uint8_t *Record,
+ SmallString<256> &CompleteData) {
+ uint16_t Length;
+ getDataLength(Record, Length);
+ return getContinuousData(Record, Length, 24, CompleteData);
+}
+
Error ENDRecord::getData(const uint8_t *Record,
SmallString<256> &CompleteData) {
uint16_t Length = getNameLength(Record);
diff --git a/contrib/llvm-project/llvm/lib/Object/IRSymtab.cpp b/contrib/llvm-project/llvm/lib/Object/IRSymtab.cpp
index 18fc2e4d4a37..2a2b235461a5 100644
--- a/contrib/llvm-project/llvm/lib/Object/IRSymtab.cpp
+++ b/contrib/llvm-project/llvm/lib/Object/IRSymtab.cpp
@@ -22,6 +22,7 @@
#include "llvm/IR/Mangler.h"
#include "llvm/IR/Metadata.h"
#include "llvm/IR/Module.h"
+#include "llvm/IR/RuntimeLibcalls.h"
#include "llvm/MC/StringTableBuilder.h"
#include "llvm/Object/ModuleSymbolTable.h"
#include "llvm/Object/SymbolicFile.h"
@@ -46,9 +47,6 @@ static cl::opt<bool> DisableBitcodeVersionUpgrade(
cl::desc("Disable automatic bitcode upgrade for version mismatch"));
static const char *PreservedSymbols[] = {
-#define HANDLE_LIBCALL(code, name) name,
-#include "llvm/IR/RuntimeLibcalls.def"
-#undef HANDLE_LIBCALL
// There are global variables, so put it here instead of in
// RuntimeLibcalls.def.
// TODO: Are there similar such variables?
@@ -215,9 +213,16 @@ Expected<int> Builder::getComdatIndex(const Comdat *C, const Module *M) {
return P.first->second;
}
-static DenseSet<StringRef> buildPreservedSymbolsSet() {
- return DenseSet<StringRef>(std::begin(PreservedSymbols),
- std::end(PreservedSymbols));
+static DenseSet<StringRef> buildPreservedSymbolsSet(const Triple &TT) {
+ DenseSet<StringRef> PreservedSymbolSet(std::begin(PreservedSymbols),
+ std::end(PreservedSymbols));
+
+ RTLIB::RuntimeLibcallsInfo Libcalls(TT);
+ for (const char *Name : Libcalls.getLibcallNames()) {
+ if (Name)
+ PreservedSymbolSet.insert(Name);
+ }
+ return PreservedSymbolSet;
}
Error Builder::addSymbol(const ModuleSymbolTable &Msymtab,
@@ -276,7 +281,8 @@ Error Builder::addSymbol(const ModuleSymbolTable &Msymtab,
setStr(Sym.IRName, GV->getName());
static const DenseSet<StringRef> PreservedSymbolsSet =
- buildPreservedSymbolsSet();
+ buildPreservedSymbolsSet(
+ llvm::Triple(GV->getParent()->getTargetTriple()));
bool IsPreservedSymbol = PreservedSymbolsSet.contains(GV->getName());
if (Used.count(GV) || IsPreservedSymbol)
@@ -295,7 +301,7 @@ Error Builder::addSymbol(const ModuleSymbolTable &Msymtab,
return make_error<StringError>("Only variables can have common linkage!",
inconvertibleErrorCode());
Uncommon().CommonSize =
- GV->getParent()->getDataLayout().getTypeAllocSize(GV->getValueType());
+ GV->getDataLayout().getTypeAllocSize(GV->getValueType());
Uncommon().CommonAlign = GVar->getAlign() ? GVar->getAlign()->value() : 0;
}
diff --git a/contrib/llvm-project/llvm/lib/Object/MachOObjectFile.cpp b/contrib/llvm-project/llvm/lib/Object/MachOObjectFile.cpp
index 1cfd0a069463..812b2c00ba69 100644
--- a/contrib/llvm-project/llvm/lib/Object/MachOObjectFile.cpp
+++ b/contrib/llvm-project/llvm/lib/Object/MachOObjectFile.cpp
@@ -399,7 +399,7 @@ static Error parseSegmentLoadCommand(
return malformedError("load command " + Twine(LoadCommandIndex) +
" filesize field in " + CmdName +
" greater than vmsize field");
- IsPageZeroSegment |= StringRef("__PAGEZERO").equals(S.segname);
+ IsPageZeroSegment |= StringRef("__PAGEZERO") == S.segname;
} else
return SegOrErr.takeError();
@@ -3104,7 +3104,7 @@ void ExportEntry::pushNode(uint64_t offset) {
}
}
}
- if(ExportStart + ExportInfoSize != State.Current) {
+ if (ExportStart + ExportInfoSize < State.Current) {
*E = malformedError(
"inconsistent export info size: 0x" +
Twine::utohexstr(ExportInfoSize) + " where actual size was: 0x" +
@@ -3256,13 +3256,13 @@ MachOAbstractFixupEntry::MachOAbstractFixupEntry(Error *E,
for (const auto &Command : O->load_commands()) {
if (Command.C.cmd == MachO::LC_SEGMENT) {
MachO::segment_command SLC = O->getSegmentLoadCommand(Command);
- if (StringRef(SLC.segname) == StringRef("__TEXT")) {
+ if (StringRef(SLC.segname) == "__TEXT") {
TextAddress = SLC.vmaddr;
break;
}
} else if (Command.C.cmd == MachO::LC_SEGMENT_64) {
MachO::segment_command_64 SLC_64 = O->getSegment64LoadCommand(Command);
- if (StringRef(SLC_64.segname) == StringRef("__TEXT")) {
+ if (StringRef(SLC_64.segname) == "__TEXT") {
TextAddress = SLC_64.vmaddr;
break;
}
@@ -3501,21 +3501,23 @@ void MachORebaseEntry::moveNext() {
--RemainingLoopCount;
return;
}
- // REBASE_OPCODE_DONE is only used for padding if we are not aligned to
- // pointer size. Therefore it is possible to reach the end without ever having
- // seen REBASE_OPCODE_DONE.
- if (Ptr == Opcodes.end()) {
- Done = true;
- return;
- }
+
bool More = true;
while (More) {
+ // REBASE_OPCODE_DONE is only used for padding if we are not aligned to
+ // pointer size. Therefore it is possible to reach the end without ever
+ // having seen REBASE_OPCODE_DONE.
+ if (Ptr == Opcodes.end()) {
+ Done = true;
+ return;
+ }
+
// Parse next opcode and set up next loop.
const uint8_t *OpcodeStart = Ptr;
uint8_t Byte = *Ptr++;
uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK;
uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK;
- uint32_t Count, Skip;
+ uint64_t Count, Skip;
const char *error = nullptr;
switch (Opcode) {
case MachO::REBASE_OPCODE_DONE:
@@ -3838,15 +3840,17 @@ void MachOBindEntry::moveNext() {
--RemainingLoopCount;
return;
}
- // BIND_OPCODE_DONE is only used for padding if we are not aligned to
- // pointer size. Therefore it is possible to reach the end without ever having
- // seen BIND_OPCODE_DONE.
- if (Ptr == Opcodes.end()) {
- Done = true;
- return;
- }
+
bool More = true;
while (More) {
+ // BIND_OPCODE_DONE is only used for padding if we are not aligned to
+ // pointer size. Therefore it is possible to reach the end without ever
+ // having seen BIND_OPCODE_DONE.
+ if (Ptr == Opcodes.end()) {
+ Done = true;
+ return;
+ }
+
// Parse next opcode and set up next loop.
const uint8_t *OpcodeStart = Ptr;
uint8_t Byte = *Ptr++;
@@ -3854,7 +3858,7 @@ void MachOBindEntry::moveNext() {
uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK;
int8_t SignExtended;
const uint8_t *SymStart;
- uint32_t Count, Skip;
+ uint64_t Count, Skip;
const char *error = nullptr;
switch (Opcode) {
case MachO::BIND_OPCODE_DONE:
@@ -4364,7 +4368,7 @@ BindRebaseSegInfo::BindRebaseSegInfo(const object::MachOObjectFile *Obj) {
Info.Size = Section.getSize();
Info.SegmentName =
Obj->getSectionFinalSegmentName(Section.getRawDataRefImpl());
- if (!Info.SegmentName.equals(CurSegName)) {
+ if (Info.SegmentName != CurSegName) {
++CurSegIndex;
CurSegName = Info.SegmentName;
CurSegAddress = Info.Address;
@@ -4384,18 +4388,18 @@ BindRebaseSegInfo::BindRebaseSegInfo(const object::MachOObjectFile *Obj) {
// that fully contains a pointer at that location. Multiple fixups in a bind
// (such as with the BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB opcode) can
// be tested via the Count and Skip parameters.
-const char * BindRebaseSegInfo::checkSegAndOffsets(int32_t SegIndex,
- uint64_t SegOffset,
- uint8_t PointerSize,
- uint32_t Count,
- uint32_t Skip) {
+const char *BindRebaseSegInfo::checkSegAndOffsets(int32_t SegIndex,
+ uint64_t SegOffset,
+ uint8_t PointerSize,
+ uint64_t Count,
+ uint64_t Skip) {
if (SegIndex == -1)
return "missing preceding *_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB";
if (SegIndex >= MaxSegIndex)
return "bad segIndex (too large)";
- for (uint32_t i = 0; i < Count; ++i) {
- uint32_t Start = SegOffset + i * (PointerSize + Skip);
- uint32_t End = Start + PointerSize;
+ for (uint64_t i = 0; i < Count; ++i) {
+ uint64_t Start = SegOffset + i * (PointerSize + Skip);
+ uint64_t End = Start + PointerSize;
bool Found = false;
for (const SectionInfo &SI : Sections) {
if (SI.SegmentIndex != SegIndex)
diff --git a/contrib/llvm-project/llvm/lib/Object/ModuleSymbolTable.cpp b/contrib/llvm-project/llvm/lib/Object/ModuleSymbolTable.cpp
index 07f76688fa43..d8f520ad02c2 100644
--- a/contrib/llvm-project/llvm/lib/Object/ModuleSymbolTable.cpp
+++ b/contrib/llvm-project/llvm/lib/Object/ModuleSymbolTable.cpp
@@ -175,6 +175,20 @@ void ModuleSymbolTable::CollectAsmSymbols(
AsmSymbol(Key, BasicSymbolRef::Flags(Res));
}
});
+
+ // In ELF, object code generated for x86-32 and some code models of x86-64 may
+ // reference the special symbol _GLOBAL_OFFSET_TABLE_ that is not used in the
+ // IR. Record it like inline asm symbols.
+ Triple TT(M.getTargetTriple());
+ if (!TT.isOSBinFormatELF() || !TT.isX86())
+ return;
+ auto CM = M.getCodeModel();
+ if (TT.getArch() == Triple::x86 || CM == CodeModel::Medium ||
+ CM == CodeModel::Large) {
+ AsmSymbol("_GLOBAL_OFFSET_TABLE_",
+ BasicSymbolRef::Flags(BasicSymbolRef::SF_Undefined |
+ BasicSymbolRef::SF_Global));
+ }
}
void ModuleSymbolTable::CollectAsmSymvers(
diff --git a/contrib/llvm-project/llvm/lib/Object/OffloadBinary.cpp b/contrib/llvm-project/llvm/lib/Object/OffloadBinary.cpp
index bfc35e41fe65..89dc12551494 100644
--- a/contrib/llvm-project/llvm/lib/Object/OffloadBinary.cpp
+++ b/contrib/llvm-project/llvm/lib/Object/OffloadBinary.cpp
@@ -83,7 +83,7 @@ Error extractFromObject(const ObjectFile &Obj,
if (!NameOrErr)
return NameOrErr.takeError();
- if (!NameOrErr->equals(".llvm.offloading"))
+ if (!NameOrErr->starts_with(".llvm.offloading"))
continue;
}
@@ -189,7 +189,10 @@ OffloadBinary::create(MemoryBufferRef Buf) {
return errorCodeToError(object_error::parse_failed);
if (TheHeader->Size > Buf.getBufferSize() ||
- TheHeader->EntryOffset > TheHeader->Size - sizeof(Entry) ||
+ TheHeader->Size < sizeof(Entry) || TheHeader->Size < sizeof(Header))
+ return errorCodeToError(object_error::unexpected_eof);
+
+ if (TheHeader->EntryOffset > TheHeader->Size - sizeof(Entry) ||
TheHeader->EntrySize > TheHeader->Size - sizeof(Header))
return errorCodeToError(object_error::unexpected_eof);
@@ -355,6 +358,10 @@ bool object::areTargetsCompatible(const OffloadFile::TargetID &LHS,
if (LHS.first != RHS.first)
return false;
+ // If the architecture is "all" we assume it is always compatible.
+ if (LHS.second == "generic" || RHS.second == "generic")
+ return true;
+
// Only The AMDGPU target requires additional checks.
llvm::Triple T(LHS.first);
if (!T.isAMDGPU())
diff --git a/contrib/llvm-project/llvm/lib/Object/SymbolSize.cpp b/contrib/llvm-project/llvm/lib/Object/SymbolSize.cpp
index cb20feffb710..635cd8373afb 100644
--- a/contrib/llvm-project/llvm/lib/Object/SymbolSize.cpp
+++ b/contrib/llvm-project/llvm/lib/Object/SymbolSize.cpp
@@ -65,6 +65,13 @@ llvm::object::computeSymbolSizes(const ObjectFile &O) {
return Ret;
}
+ if (const auto *E = dyn_cast<WasmObjectFile>(&O)) {
+ for (SymbolRef Sym : E->symbols()) {
+ Ret.push_back({Sym, E->getSymbolSize(Sym)});
+ }
+ return Ret;
+ }
+
// Collect sorted symbol addresses. Include dummy addresses for the end
// of each section.
std::vector<SymEntry> Addresses;
diff --git a/contrib/llvm-project/llvm/lib/Object/TapiFile.cpp b/contrib/llvm-project/llvm/lib/Object/TapiFile.cpp
index fcf61541941e..4eaacc48e7ce 100644
--- a/contrib/llvm-project/llvm/lib/Object/TapiFile.cpp
+++ b/contrib/llvm-project/llvm/lib/Object/TapiFile.cpp
@@ -56,11 +56,11 @@ TapiFile::TapiFile(MemoryBufferRef Source, const InterfaceFile &Interface,
continue;
switch (Symbol->getKind()) {
- case SymbolKind::GlobalSymbol:
+ case EncodeKind::GlobalSymbol:
Symbols.emplace_back(StringRef(), Symbol->getName(), getFlags(Symbol),
::getType(Symbol));
break;
- case SymbolKind::ObjectiveCClass:
+ case EncodeKind::ObjectiveCClass:
if (Interface.getPlatforms().count(PLATFORM_MACOS) && Arch == AK_i386) {
Symbols.emplace_back(ObjC1ClassNamePrefix, Symbol->getName(),
getFlags(Symbol), ::getType(Symbol));
@@ -71,11 +71,11 @@ TapiFile::TapiFile(MemoryBufferRef Source, const InterfaceFile &Interface,
getFlags(Symbol), ::getType(Symbol));
}
break;
- case SymbolKind::ObjectiveCClassEHType:
+ case EncodeKind::ObjectiveCClassEHType:
Symbols.emplace_back(ObjC2EHTypePrefix, Symbol->getName(),
getFlags(Symbol), ::getType(Symbol));
break;
- case SymbolKind::ObjectiveCInstanceVariable:
+ case EncodeKind::ObjectiveCInstanceVariable:
Symbols.emplace_back(ObjC2IVarPrefix, Symbol->getName(), getFlags(Symbol),
::getType(Symbol));
break;
diff --git a/contrib/llvm-project/llvm/lib/Object/TapiUniversal.cpp b/contrib/llvm-project/llvm/lib/Object/TapiUniversal.cpp
index bf96b57f0321..4db5841a8f34 100644
--- a/contrib/llvm-project/llvm/lib/Object/TapiUniversal.cpp
+++ b/contrib/llvm-project/llvm/lib/Object/TapiUniversal.cpp
@@ -47,9 +47,9 @@ TapiUniversal::~TapiUniversal() = default;
Expected<std::unique_ptr<TapiFile>>
TapiUniversal::ObjectForArch::getAsObjectFile() const {
- return std::unique_ptr<TapiFile>(new TapiFile(Parent->getMemoryBufferRef(),
- *Parent->ParsedFile,
- Parent->Libraries[Index].Arch));
+ return std::make_unique<TapiFile>(Parent->getMemoryBufferRef(),
+ *Parent->ParsedFile,
+ Parent->Libraries[Index].Arch);
}
Expected<std::unique_ptr<TapiUniversal>>
diff --git a/contrib/llvm-project/llvm/lib/Object/WasmObjectFile.cpp b/contrib/llvm-project/llvm/lib/Object/WasmObjectFile.cpp
index b9a8e970216b..f244099d664d 100644
--- a/contrib/llvm-project/llvm/lib/Object/WasmObjectFile.cpp
+++ b/contrib/llvm-project/llvm/lib/Object/WasmObjectFile.cpp
@@ -21,6 +21,7 @@
#include "llvm/Support/Endian.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/Format.h"
#include "llvm/Support/LEB128.h"
#include "llvm/Support/ScopedPrinter.h"
#include "llvm/TargetParser/SubtargetFeature.h"
@@ -29,6 +30,7 @@
#include <cassert>
#include <cstdint>
#include <cstring>
+#include <limits>
#define DEBUG_TYPE "wasm-object"
@@ -173,6 +175,27 @@ static uint8_t readOpcode(WasmObjectFile::ReadContext &Ctx) {
return readUint8(Ctx);
}
+static wasm::ValType parseValType(WasmObjectFile::ReadContext &Ctx,
+ uint32_t Code) {
+ // only directly encoded FUNCREF/EXTERNREF/EXNREF are supported
+ // (not ref null func, ref null extern, or ref null exn)
+ switch (Code) {
+ case wasm::WASM_TYPE_I32:
+ case wasm::WASM_TYPE_I64:
+ case wasm::WASM_TYPE_F32:
+ case wasm::WASM_TYPE_F64:
+ case wasm::WASM_TYPE_V128:
+ case wasm::WASM_TYPE_FUNCREF:
+ case wasm::WASM_TYPE_EXTERNREF:
+ case wasm::WASM_TYPE_EXNREF:
+ return wasm::ValType(Code);
+ }
+ if (Code == wasm::WASM_TYPE_NULLABLE || Code == wasm::WASM_TYPE_NONNULLABLE) {
+ /* Discard HeapType */ readVarint64(Ctx);
+ }
+ return wasm::ValType(wasm::ValType::OTHERREF);
+}
+
static Error readInitExpr(wasm::WasmInitExpr &Expr,
WasmObjectFile::ReadContext &Ctx) {
auto Start = Ctx.Ptr;
@@ -196,11 +219,7 @@ static Error readInitExpr(wasm::WasmInitExpr &Expr,
Expr.Inst.Value.Global = readULEB128(Ctx);
break;
case wasm::WASM_OPCODE_REF_NULL: {
- wasm::ValType Ty = static_cast<wasm::ValType>(readULEB128(Ctx));
- if (Ty != wasm::ValType::EXTERNREF) {
- return make_error<GenericBinaryError>("invalid type for ref.null",
- object_error::parse_failed);
- }
+ /* Discard type */ parseValType(Ctx, readVaruint32(Ctx));
break;
}
default:
@@ -221,10 +240,15 @@ static Error readInitExpr(wasm::WasmInitExpr &Expr,
case wasm::WASM_OPCODE_I32_CONST:
case wasm::WASM_OPCODE_GLOBAL_GET:
case wasm::WASM_OPCODE_REF_NULL:
+ case wasm::WASM_OPCODE_REF_FUNC:
case wasm::WASM_OPCODE_I64_CONST:
+ readULEB128(Ctx);
+ break;
case wasm::WASM_OPCODE_F32_CONST:
+ readFloat32(Ctx);
+ break;
case wasm::WASM_OPCODE_F64_CONST:
- readULEB128(Ctx);
+ readFloat64(Ctx);
break;
case wasm::WASM_OPCODE_I32_ADD:
case wasm::WASM_OPCODE_I32_SUB:
@@ -233,6 +257,23 @@ static Error readInitExpr(wasm::WasmInitExpr &Expr,
case wasm::WASM_OPCODE_I64_SUB:
case wasm::WASM_OPCODE_I64_MUL:
break;
+ case wasm::WASM_OPCODE_GC_PREFIX:
+ break;
+ // The GC opcodes are in a separate (prefixed space). This flat switch
+ // structure works as long as there is no overlap between the GC and
+ // general opcodes used in init exprs.
+ case wasm::WASM_OPCODE_STRUCT_NEW:
+ case wasm::WASM_OPCODE_STRUCT_NEW_DEFAULT:
+ case wasm::WASM_OPCODE_ARRAY_NEW:
+ case wasm::WASM_OPCODE_ARRAY_NEW_DEFAULT:
+ readULEB128(Ctx); // heap type index
+ break;
+ case wasm::WASM_OPCODE_ARRAY_NEW_FIXED:
+ readULEB128(Ctx); // heap type index
+ readULEB128(Ctx); // array size
+ break;
+ case wasm::WASM_OPCODE_REF_I31:
+ break;
case wasm::WASM_OPCODE_END:
Expr.Body = ArrayRef<uint8_t>(Start, Ctx.Ptr - Start);
return Error::success();
@@ -258,7 +299,8 @@ static wasm::WasmLimits readLimits(WasmObjectFile::ReadContext &Ctx) {
static wasm::WasmTableType readTableType(WasmObjectFile::ReadContext &Ctx) {
wasm::WasmTableType TableType;
- TableType.ElemType = wasm::ValType(readVaruint32(Ctx));
+ auto ElemType = parseValType(Ctx, readVaruint32(Ctx));
+ TableType.ElemType = ElemType;
TableType.Limits = readLimits(Ctx);
return TableType;
}
@@ -467,10 +509,20 @@ Error WasmObjectFile::parseNameSection(ReadContext &Ctx) {
llvm::DenseSet<uint64_t> SeenGlobals;
llvm::DenseSet<uint64_t> SeenSegments;
+ // If we have linking section (symbol table) or if we are parsing a DSO
+ // then we don't use the name section for symbol information.
+ bool PopulateSymbolTable = !HasLinkingSection && !HasDylinkSection;
+
+ // If we are using the name section for symbol information then it will
+ // supersede any symbols created by the export section.
+ if (PopulateSymbolTable)
+ Symbols.clear();
+
while (Ctx.Ptr < Ctx.End) {
uint8_t Type = readUint8(Ctx);
uint32_t Size = readVaruint32(Ctx);
const uint8_t *SubSectionEnd = Ctx.Ptr + Size;
+
switch (Type) {
case wasm::WASM_NAMES_FUNCTION:
case wasm::WASM_NAMES_GLOBAL:
@@ -480,6 +532,16 @@ Error WasmObjectFile::parseNameSection(ReadContext &Ctx) {
uint32_t Index = readVaruint32(Ctx);
StringRef Name = readString(Ctx);
wasm::NameType nameType = wasm::NameType::FUNCTION;
+ wasm::WasmSymbolInfo Info{Name,
+ /*Kind */ wasm::WASM_SYMBOL_TYPE_FUNCTION,
+ /* Flags */ 0,
+ /* ImportModule */ std::nullopt,
+ /* ImportName */ std::nullopt,
+ /* ExportName */ std::nullopt,
+ {/* ElementIndex */ Index}};
+ const wasm::WasmSignature *Signature = nullptr;
+ const wasm::WasmGlobalType *GlobalType = nullptr;
+ const wasm::WasmTableType *TableType = nullptr;
if (Type == wasm::WASM_NAMES_FUNCTION) {
if (!SeenFunctions.insert(Index).second)
return make_error<GenericBinaryError>(
@@ -488,26 +550,50 @@ Error WasmObjectFile::parseNameSection(ReadContext &Ctx) {
return make_error<GenericBinaryError>("invalid function name entry",
object_error::parse_failed);
- if (isDefinedFunctionIndex(Index))
- getDefinedFunction(Index).DebugName = Name;
+ if (isDefinedFunctionIndex(Index)) {
+ wasm::WasmFunction &F = getDefinedFunction(Index);
+ F.DebugName = Name;
+ Signature = &Signatures[F.SigIndex];
+ if (F.ExportName) {
+ Info.ExportName = F.ExportName;
+ Info.Flags |= wasm::WASM_SYMBOL_BINDING_GLOBAL;
+ } else {
+ Info.Flags |= wasm::WASM_SYMBOL_BINDING_LOCAL;
+ }
+ } else {
+ Info.Flags |= wasm::WASM_SYMBOL_UNDEFINED;
+ }
} else if (Type == wasm::WASM_NAMES_GLOBAL) {
- nameType = wasm::NameType::GLOBAL;
if (!SeenGlobals.insert(Index).second)
return make_error<GenericBinaryError>("global named more than once",
object_error::parse_failed);
if (!isValidGlobalIndex(Index) || Name.empty())
return make_error<GenericBinaryError>("invalid global name entry",
object_error::parse_failed);
+ nameType = wasm::NameType::GLOBAL;
+ Info.Kind = wasm::WASM_SYMBOL_TYPE_GLOBAL;
+ if (isDefinedGlobalIndex(Index)) {
+ GlobalType = &getDefinedGlobal(Index).Type;
+ } else {
+ Info.Flags |= wasm::WASM_SYMBOL_UNDEFINED;
+ }
} else {
- nameType = wasm::NameType::DATA_SEGMENT;
if (!SeenSegments.insert(Index).second)
return make_error<GenericBinaryError>(
"segment named more than once", object_error::parse_failed);
if (Index > DataSegments.size())
return make_error<GenericBinaryError>("invalid data segment name entry",
object_error::parse_failed);
+ nameType = wasm::NameType::DATA_SEGMENT;
+ Info.Kind = wasm::WASM_SYMBOL_TYPE_DATA;
+ Info.Flags |= wasm::WASM_SYMBOL_BINDING_LOCAL;
+ assert(Index < DataSegments.size());
+ Info.DataRef = wasm::WasmDataReference{
+ Index, 0, DataSegments[Index].Data.Content.size()};
}
DebugNames.push_back(wasm::WasmDebugName{nameType, Index, Name});
+ if (PopulateSymbolTable)
+ Symbols.emplace_back(Info, GlobalType, TableType, Signature);
}
break;
}
@@ -601,9 +687,7 @@ Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) {
uint32_t Count = readVaruint32(Ctx);
// Clear out any symbol information that was derived from the exports
// section.
- LinkingData.SymbolTable.clear();
Symbols.clear();
- LinkingData.SymbolTable.reserve(Count);
Symbols.reserve(Count);
StringSet<> SymbolNames;
@@ -803,9 +887,7 @@ Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) {
return make_error<GenericBinaryError>("duplicate symbol name " +
Twine(Info.Name),
object_error::parse_failed);
- LinkingData.SymbolTable.emplace_back(Info);
- Symbols.emplace_back(LinkingData.SymbolTable.back(), GlobalType, TableType,
- Signature);
+ Symbols.emplace_back(Info, GlobalType, TableType, Signature);
LLVM_DEBUG(dbgs() << "Adding symbol: " << Symbols.back() << "\n");
}
@@ -956,6 +1038,13 @@ Error WasmObjectFile::parseRelocSection(StringRef Name, ReadContext &Ctx) {
if (Reloc.Offset < PreviousOffset)
return make_error<GenericBinaryError>("relocations not in offset order",
object_error::parse_failed);
+
+ auto badReloc = [&](StringRef msg) {
+ return make_error<GenericBinaryError>(
+ msg + ": " + Twine(Symbols[Reloc.Index].Info.Name),
+ object_error::parse_failed);
+ };
+
PreviousOffset = Reloc.Offset;
Reloc.Index = readVaruint32(Ctx);
switch (type) {
@@ -968,18 +1057,15 @@ Error WasmObjectFile::parseRelocSection(StringRef Name, ReadContext &Ctx) {
case wasm::R_WASM_TABLE_INDEX_REL_SLEB:
case wasm::R_WASM_TABLE_INDEX_REL_SLEB64:
if (!isValidFunctionSymbol(Reloc.Index))
- return make_error<GenericBinaryError>(
- "invalid relocation function index", object_error::parse_failed);
+ return badReloc("invalid function relocation");
break;
case wasm::R_WASM_TABLE_NUMBER_LEB:
if (!isValidTableSymbol(Reloc.Index))
- return make_error<GenericBinaryError>("invalid relocation table index",
- object_error::parse_failed);
+ return badReloc("invalid table relocation");
break;
case wasm::R_WASM_TYPE_INDEX_LEB:
if (Reloc.Index >= Signatures.size())
- return make_error<GenericBinaryError>("invalid relocation type index",
- object_error::parse_failed);
+ return badReloc("invalid relocation type index");
break;
case wasm::R_WASM_GLOBAL_INDEX_LEB:
// R_WASM_GLOBAL_INDEX_LEB are can be used against function and data
@@ -987,18 +1073,15 @@ Error WasmObjectFile::parseRelocSection(StringRef Name, ReadContext &Ctx) {
if (!isValidGlobalSymbol(Reloc.Index) &&
!isValidDataSymbol(Reloc.Index) &&
!isValidFunctionSymbol(Reloc.Index))
- return make_error<GenericBinaryError>("invalid relocation global index",
- object_error::parse_failed);
+ return badReloc("invalid global relocation");
break;
case wasm::R_WASM_GLOBAL_INDEX_I32:
if (!isValidGlobalSymbol(Reloc.Index))
- return make_error<GenericBinaryError>("invalid relocation global index",
- object_error::parse_failed);
+ return badReloc("invalid global relocation");
break;
case wasm::R_WASM_TAG_INDEX_LEB:
if (!isValidTagSymbol(Reloc.Index))
- return make_error<GenericBinaryError>("invalid relocation tag index",
- object_error::parse_failed);
+ return badReloc("invalid tag relocation");
break;
case wasm::R_WASM_MEMORY_ADDR_LEB:
case wasm::R_WASM_MEMORY_ADDR_SLEB:
@@ -1007,8 +1090,7 @@ Error WasmObjectFile::parseRelocSection(StringRef Name, ReadContext &Ctx) {
case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB:
case wasm::R_WASM_MEMORY_ADDR_LOCREL_I32:
if (!isValidDataSymbol(Reloc.Index))
- return make_error<GenericBinaryError>("invalid relocation data index",
- object_error::parse_failed);
+ return badReloc("invalid data relocation");
Reloc.Addend = readVarint32(Ctx);
break;
case wasm::R_WASM_MEMORY_ADDR_LEB64:
@@ -1017,26 +1099,22 @@ Error WasmObjectFile::parseRelocSection(StringRef Name, ReadContext &Ctx) {
case wasm::R_WASM_MEMORY_ADDR_REL_SLEB64:
case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB64:
if (!isValidDataSymbol(Reloc.Index))
- return make_error<GenericBinaryError>("invalid relocation data index",
- object_error::parse_failed);
+ return badReloc("invalid data relocation");
Reloc.Addend = readVarint64(Ctx);
break;
case wasm::R_WASM_FUNCTION_OFFSET_I32:
if (!isValidFunctionSymbol(Reloc.Index))
- return make_error<GenericBinaryError>(
- "invalid relocation function index", object_error::parse_failed);
+ return badReloc("invalid function relocation");
Reloc.Addend = readVarint32(Ctx);
break;
case wasm::R_WASM_FUNCTION_OFFSET_I64:
if (!isValidFunctionSymbol(Reloc.Index))
- return make_error<GenericBinaryError>(
- "invalid relocation function index", object_error::parse_failed);
+ return badReloc("invalid function relocation");
Reloc.Addend = readVarint64(Ctx);
break;
case wasm::R_WASM_SECTION_OFFSET_I32:
if (!isValidSectionSymbol(Reloc.Index))
- return make_error<GenericBinaryError>(
- "invalid relocation section index", object_error::parse_failed);
+ return badReloc("invalid section relocation");
Reloc.Addend = readVarint32(Ctx);
break;
default:
@@ -1104,26 +1182,75 @@ Error WasmObjectFile::parseCustomSection(WasmSection &Sec, ReadContext &Ctx) {
}
Error WasmObjectFile::parseTypeSection(ReadContext &Ctx) {
+ auto parseFieldDef = [&]() {
+ uint32_t TypeCode = readVaruint32((Ctx));
+ /* Discard StorageType */ parseValType(Ctx, TypeCode);
+ /* Discard Mutability */ readVaruint32(Ctx);
+ };
+
uint32_t Count = readVaruint32(Ctx);
Signatures.reserve(Count);
while (Count--) {
wasm::WasmSignature Sig;
uint8_t Form = readUint8(Ctx);
+ if (Form == wasm::WASM_TYPE_REC) {
+ // Rec groups expand the type index space (beyond what was declared at
+ // the top of the section, and also consume one element in that space.
+ uint32_t RecSize = readVaruint32(Ctx);
+ if (RecSize == 0)
+ return make_error<GenericBinaryError>("Rec group size cannot be 0",
+ object_error::parse_failed);
+ Signatures.reserve(Signatures.size() + RecSize);
+ Count += RecSize;
+ Sig.Kind = wasm::WasmSignature::Placeholder;
+ Signatures.push_back(std::move(Sig));
+ HasUnmodeledTypes = true;
+ continue;
+ }
if (Form != wasm::WASM_TYPE_FUNC) {
- return make_error<GenericBinaryError>("invalid signature type",
- object_error::parse_failed);
+ // Currently LLVM only models function types, and not other composite
+ // types. Here we parse the type declarations just enough to skip past
+ // them in the binary.
+ if (Form == wasm::WASM_TYPE_SUB || Form == wasm::WASM_TYPE_SUB_FINAL) {
+ uint32_t Supers = readVaruint32(Ctx);
+ if (Supers > 0) {
+ if (Supers != 1)
+ return make_error<GenericBinaryError>(
+ "Invalid number of supertypes", object_error::parse_failed);
+ /* Discard SuperIndex */ readVaruint32(Ctx);
+ }
+ Form = readVaruint32(Ctx);
+ }
+ if (Form == wasm::WASM_TYPE_STRUCT) {
+ uint32_t FieldCount = readVaruint32(Ctx);
+ while (FieldCount--) {
+ parseFieldDef();
+ }
+ } else if (Form == wasm::WASM_TYPE_ARRAY) {
+ parseFieldDef();
+ } else {
+ return make_error<GenericBinaryError>("bad form",
+ object_error::parse_failed);
+ }
+ Sig.Kind = wasm::WasmSignature::Placeholder;
+ Signatures.push_back(std::move(Sig));
+ HasUnmodeledTypes = true;
+ continue;
}
+
uint32_t ParamCount = readVaruint32(Ctx);
Sig.Params.reserve(ParamCount);
while (ParamCount--) {
uint32_t ParamType = readUint8(Ctx);
- Sig.Params.push_back(wasm::ValType(ParamType));
+ Sig.Params.push_back(parseValType(Ctx, ParamType));
+ continue;
}
uint32_t ReturnCount = readVaruint32(Ctx);
while (ReturnCount--) {
uint32_t ReturnType = readUint8(Ctx);
- Sig.Returns.push_back(wasm::ValType(ReturnType));
+ Sig.Returns.push_back(parseValType(Ctx, ReturnType));
}
+
Signatures.push_back(std::move(Sig));
}
if (Ctx.Ptr != Ctx.End)
@@ -1164,7 +1291,9 @@ Error WasmObjectFile::parseImportSection(ReadContext &Ctx) {
NumImportedTables++;
auto ElemType = Im.Table.ElemType;
if (ElemType != wasm::ValType::FUNCREF &&
- ElemType != wasm::ValType::EXTERNREF)
+ ElemType != wasm::ValType::EXTERNREF &&
+ ElemType != wasm::ValType::EXNREF &&
+ ElemType != wasm::ValType::OTHERREF)
return make_error<GenericBinaryError>("invalid table element type",
object_error::parse_failed);
break;
@@ -1221,7 +1350,9 @@ Error WasmObjectFile::parseTableSection(ReadContext &Ctx) {
Tables.push_back(T);
auto ElemType = Tables.back().Type.ElemType;
if (ElemType != wasm::ValType::FUNCREF &&
- ElemType != wasm::ValType::EXTERNREF) {
+ ElemType != wasm::ValType::EXTERNREF &&
+ ElemType != wasm::ValType::EXNREF &&
+ ElemType != wasm::ValType::OTHERREF) {
return make_error<GenericBinaryError>("invalid table element type",
object_error::parse_failed);
}
@@ -1263,6 +1394,7 @@ Error WasmObjectFile::parseTagSection(ReadContext &Ctx) {
wasm::WasmTag Tag;
Tag.Index = NumImportedTags + Tags.size();
Tag.SigIndex = Type;
+ Signatures[Type].Kind = wasm::WasmSignature::Tag;
Tags.push_back(Tag);
}
@@ -1274,15 +1406,20 @@ Error WasmObjectFile::parseTagSection(ReadContext &Ctx) {
Error WasmObjectFile::parseGlobalSection(ReadContext &Ctx) {
GlobalSection = Sections.size();
+ const uint8_t *SectionStart = Ctx.Ptr;
uint32_t Count = readVaruint32(Ctx);
Globals.reserve(Count);
while (Count--) {
wasm::WasmGlobal Global;
Global.Index = NumImportedGlobals + Globals.size();
- Global.Type.Type = readUint8(Ctx);
+ const uint8_t *GlobalStart = Ctx.Ptr;
+ Global.Offset = static_cast<uint32_t>(GlobalStart - SectionStart);
+ auto GlobalOpcode = readVaruint32(Ctx);
+ Global.Type.Type = (uint8_t)parseValType(Ctx, GlobalOpcode);
Global.Type.Mutable = readVaruint1(Ctx);
if (Error Err = readInitExpr(Global.InitExpr, Ctx))
return Err;
+ Global.Size = static_cast<uint32_t>(Ctx.Ptr - GlobalStart);
Globals.push_back(Global);
}
if (Ctx.Ptr != Ctx.End)
@@ -1294,7 +1431,6 @@ Error WasmObjectFile::parseGlobalSection(ReadContext &Ctx) {
Error WasmObjectFile::parseExportSection(ReadContext &Ctx) {
uint32_t Count = readVaruint32(Ctx);
Exports.reserve(Count);
- LinkingData.SymbolTable.reserve(Count);
Symbols.reserve(Count);
for (uint32_t I = 0; I < Count; I++) {
wasm::WasmExport Ex;
@@ -1359,9 +1495,7 @@ Error WasmObjectFile::parseExportSection(ReadContext &Ctx) {
}
Exports.push_back(Ex);
if (Ex.Kind != wasm::WASM_EXTERNAL_MEMORY) {
- LinkingData.SymbolTable.emplace_back(Info);
- Symbols.emplace_back(LinkingData.SymbolTable.back(), GlobalType,
- TableType, Signature);
+ Symbols.emplace_back(Info, GlobalType, TableType, Signature);
LLVM_DEBUG(dbgs() << "Adding symbol: " << Symbols.back() << "\n");
}
}
@@ -1438,7 +1572,7 @@ WasmObjectFile::getDefinedFunction(uint32_t Index) const {
return Functions[Index - NumImportedFunctions];
}
-wasm::WasmGlobal &WasmObjectFile::getDefinedGlobal(uint32_t Index) {
+const wasm::WasmGlobal &WasmObjectFile::getDefinedGlobal(uint32_t Index) const {
assert(isDefinedGlobalIndex(Index));
return Globals[Index - NumImportedGlobals];
}
@@ -1516,15 +1650,28 @@ Error WasmObjectFile::parseElemSection(ReadContext &Ctx) {
return make_error<GenericBinaryError>(
"Unsupported flags for element segment", object_error::parse_failed);
- if (Segment.Flags & wasm::WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER)
+ bool IsPassive = (Segment.Flags & wasm::WASM_ELEM_SEGMENT_IS_PASSIVE) != 0;
+ bool IsDeclarative =
+ IsPassive && (Segment.Flags & wasm::WASM_ELEM_SEGMENT_IS_DECLARATIVE);
+ bool HasTableNumber =
+ !IsPassive &&
+ (Segment.Flags & wasm::WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER);
+ bool HasInitExprs =
+ (Segment.Flags & wasm::WASM_ELEM_SEGMENT_HAS_INIT_EXPRS);
+ bool HasElemKind =
+ (Segment.Flags & wasm::WASM_ELEM_SEGMENT_MASK_HAS_ELEM_KIND) &&
+ !HasInitExprs;
+
+ if (HasTableNumber)
Segment.TableNumber = readVaruint32(Ctx);
else
Segment.TableNumber = 0;
+
if (!isValidTableNumber(Segment.TableNumber))
return make_error<GenericBinaryError>("invalid TableNumber",
object_error::parse_failed);
- if (Segment.Flags & wasm::WASM_ELEM_SEGMENT_IS_PASSIVE) {
+ if (IsPassive || IsDeclarative) {
Segment.Offset.Extended = false;
Segment.Offset.Inst.Opcode = wasm::WASM_OPCODE_I32_CONST;
Segment.Offset.Inst.Value.Int32 = 0;
@@ -1533,33 +1680,42 @@ Error WasmObjectFile::parseElemSection(ReadContext &Ctx) {
return Err;
}
- if (Segment.Flags & wasm::WASM_ELEM_SEGMENT_MASK_HAS_ELEM_KIND) {
+ if (HasElemKind) {
auto ElemKind = readVaruint32(Ctx);
if (Segment.Flags & wasm::WASM_ELEM_SEGMENT_HAS_INIT_EXPRS) {
- Segment.ElemKind = wasm::ValType(ElemKind);
+ Segment.ElemKind = parseValType(Ctx, ElemKind);
if (Segment.ElemKind != wasm::ValType::FUNCREF &&
- Segment.ElemKind != wasm::ValType::EXTERNREF) {
- return make_error<GenericBinaryError>("invalid reference type",
+ Segment.ElemKind != wasm::ValType::EXTERNREF &&
+ Segment.ElemKind != wasm::ValType::EXNREF &&
+ Segment.ElemKind != wasm::ValType::OTHERREF) {
+ return make_error<GenericBinaryError>("invalid elem type",
object_error::parse_failed);
}
} else {
if (ElemKind != 0)
- return make_error<GenericBinaryError>("invalid elemtype",
+ return make_error<GenericBinaryError>("invalid elem type",
object_error::parse_failed);
Segment.ElemKind = wasm::ValType::FUNCREF;
}
+ } else if (HasInitExprs) {
+ auto ElemType = parseValType(Ctx, readVaruint32(Ctx));
+ Segment.ElemKind = ElemType;
} else {
Segment.ElemKind = wasm::ValType::FUNCREF;
}
- if (Segment.Flags & wasm::WASM_ELEM_SEGMENT_HAS_INIT_EXPRS)
- return make_error<GenericBinaryError>(
- "elem segment init expressions not yet implemented",
- object_error::parse_failed);
-
uint32_t NumElems = readVaruint32(Ctx);
- while (NumElems--) {
- Segment.Functions.push_back(readVaruint32(Ctx));
+
+ if (HasInitExprs) {
+ while (NumElems--) {
+ wasm::WasmInitExpr Expr;
+ if (Error Err = readInitExpr(Expr, Ctx))
+ return Err;
+ }
+ } else {
+ while (NumElems--) {
+ Segment.Functions.push_back(readVaruint32(Ctx));
+ }
}
ElemSegments.push_back(Segment);
}
@@ -1668,18 +1824,22 @@ Expected<StringRef> WasmObjectFile::getSymbolName(DataRefImpl Symb) const {
Expected<uint64_t> WasmObjectFile::getSymbolAddress(DataRefImpl Symb) const {
auto &Sym = getWasmSymbol(Symb);
+ if (!Sym.isDefined())
+ return 0;
+ Expected<section_iterator> Sec = getSymbolSection(Symb);
+ if (!Sec)
+ return Sec.takeError();
+ uint32_t SectionAddress = getSectionAddress(Sec.get()->getRawDataRefImpl());
if (Sym.Info.Kind == wasm::WASM_SYMBOL_TYPE_FUNCTION &&
isDefinedFunctionIndex(Sym.Info.ElementIndex)) {
- // For object files, use the section offset. The linker relies on this.
- // For linked files, use the file offset. This behavior matches the way
- // browsers print stack traces and is useful for binary size analysis.
- // (see https://webassembly.github.io/spec/web-api/index.html#conventions)
- uint32_t Adjustment = isRelocatableObject() || isSharedObject()
- ? 0
- : Sections[CodeSection].Offset;
return getDefinedFunction(Sym.Info.ElementIndex).CodeSectionOffset +
- Adjustment;
+ SectionAddress;
}
+ if (Sym.Info.Kind == wasm::WASM_SYMBOL_TYPE_GLOBAL &&
+ isDefinedGlobalIndex(Sym.Info.ElementIndex)) {
+ return getDefinedGlobal(Sym.Info.ElementIndex).Offset + SectionAddress;
+ }
+
return getSymbolValue(Symb);
}
@@ -1785,6 +1945,22 @@ uint32_t WasmObjectFile::getSymbolSectionIdImpl(const WasmSymbol &Sym) const {
}
}
+uint32_t WasmObjectFile::getSymbolSize(SymbolRef Symb) const {
+ const WasmSymbol &Sym = getWasmSymbol(Symb);
+ if (!Sym.isDefined())
+ return 0;
+ if (Sym.isTypeGlobal())
+ return getDefinedGlobal(Sym.Info.ElementIndex).Size;
+ if (Sym.isTypeData())
+ return Sym.Info.DataRef.Size;
+ if (Sym.isTypeFunction())
+ return functions()[Sym.Info.ElementIndex - getNumImportedFunctions()].Size;
+ // Currently symbol size is only tracked for data segments and functions. In
+ // principle we could also track size (e.g. binary size) for tables, globals
+ // and element segments etc too.
+ return 0;
+}
+
void WasmObjectFile::moveSectionNext(DataRefImpl &Sec) const { Sec.d.a++; }
Expected<StringRef> WasmObjectFile::getSectionName(DataRefImpl Sec) const {
@@ -1796,7 +1972,13 @@ Expected<StringRef> WasmObjectFile::getSectionName(DataRefImpl Sec) const {
return wasm::sectionTypeToString(S.Type);
}
-uint64_t WasmObjectFile::getSectionAddress(DataRefImpl Sec) const { return 0; }
+uint64_t WasmObjectFile::getSectionAddress(DataRefImpl Sec) const {
+ // For object files, use 0 for section addresses, and section offsets for
+ // symbol addresses. For linked files, use file offsets.
+ // See also getSymbolAddress.
+ return isRelocatableObject() || isSharedObject() ? 0
+ : Sections[Sec.d.a].Offset;
+}
uint64_t WasmObjectFile::getSectionIndex(DataRefImpl Sec) const {
return Sec.d.a;
diff --git a/contrib/llvm-project/llvm/lib/Object/WindowsResource.cpp b/contrib/llvm-project/llvm/lib/Object/WindowsResource.cpp
index 61ca49e290da..306e8ec54206 100644
--- a/contrib/llvm-project/llvm/lib/Object/WindowsResource.cpp
+++ b/contrib/llvm-project/llvm/lib/Object/WindowsResource.cpp
@@ -12,6 +12,7 @@
#include "llvm/Object/WindowsResource.h"
#include "llvm/Object/COFF.h"
+#include "llvm/Object/WindowsMachineFlag.h"
#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/ScopedPrinter.h"
@@ -79,7 +80,7 @@ Expected<ResourceEntryRef>
ResourceEntryRef::create(BinaryStreamRef BSR, const WindowsResource *Owner) {
auto Ref = ResourceEntryRef(BSR, Owner);
if (auto E = Ref.loadNext())
- return std::move(E);
+ return E;
return Ref;
}
@@ -978,19 +979,17 @@ void WindowsResourceCOFFWriter::writeFirstSectionRelocations() {
reinterpret_cast<coff_relocation *>(BufferStart + CurrentOffset);
Reloc->VirtualAddress = RelocationAddresses[i];
Reloc->SymbolTableIndex = NextSymbolIndex++;
- switch (MachineType) {
- case COFF::IMAGE_FILE_MACHINE_ARMNT:
+ switch (getMachineArchType(MachineType)) {
+ case Triple::thumb:
Reloc->Type = COFF::IMAGE_REL_ARM_ADDR32NB;
break;
- case COFF::IMAGE_FILE_MACHINE_AMD64:
+ case Triple::x86_64:
Reloc->Type = COFF::IMAGE_REL_AMD64_ADDR32NB;
break;
- case COFF::IMAGE_FILE_MACHINE_I386:
+ case Triple::x86:
Reloc->Type = COFF::IMAGE_REL_I386_DIR32NB;
break;
- case COFF::IMAGE_FILE_MACHINE_ARM64:
- case COFF::IMAGE_FILE_MACHINE_ARM64EC:
- case COFF::IMAGE_FILE_MACHINE_ARM64X:
+ case Triple::aarch64:
Reloc->Type = COFF::IMAGE_REL_ARM64_ADDR32NB;
break;
default:
@@ -1007,7 +1006,7 @@ writeWindowsResourceCOFF(COFF::MachineTypes MachineType,
Error E = Error::success();
WindowsResourceCOFFWriter Writer(MachineType, Parser, E);
if (E)
- return std::move(E);
+ return E;
return Writer.write(TimeDateStamp);
}
diff --git a/contrib/llvm-project/llvm/lib/Object/XCOFFObjectFile.cpp b/contrib/llvm-project/llvm/lib/Object/XCOFFObjectFile.cpp
index 3fbd51887831..6efb8759d13f 100644
--- a/contrib/llvm-project/llvm/lib/Object/XCOFFObjectFile.cpp
+++ b/contrib/llvm-project/llvm/lib/Object/XCOFFObjectFile.cpp
@@ -65,6 +65,12 @@ template <typename T> uint16_t XCOFFSectionHeader<T>::getSectionType() const {
}
template <typename T>
+uint32_t XCOFFSectionHeader<T>::getSectionSubtype() const {
+ const T &DerivedXCOFFSectionHeader = static_cast<const T &>(*this);
+ return DerivedXCOFFSectionHeader.Flags & ~SectionFlagsTypeMask;
+}
+
+template <typename T>
bool XCOFFSectionHeader<T>::isReservedSectionType() const {
return getSectionType() & SectionFlagsReservedMask;
}
@@ -731,9 +737,11 @@ bool XCOFFObjectFile::isRelocatableObject() const {
}
Expected<uint64_t> XCOFFObjectFile::getStartAddress() const {
- // TODO FIXME Should get from auxiliary_header->o_entry when support for the
- // auxiliary_header is added.
- return 0;
+ if (AuxiliaryHeader == nullptr)
+ return 0;
+
+ return is64Bit() ? auxiliaryHeader64()->getEntryPointAddr()
+ : auxiliaryHeader32()->getEntryPointAddr();
}
StringRef XCOFFObjectFile::mapDebugSectionName(StringRef Name) const {
@@ -1361,7 +1369,7 @@ Expected<StringRef> XCOFFSymbolRef::getName() const {
return getObject()->getStringTableEntry(getSymbol64()->Offset);
}
-// Explictly instantiate template classes.
+// Explicitly instantiate template classes.
template struct XCOFFSectionHeader<XCOFFSectionHeader32>;
template struct XCOFFSectionHeader<XCOFFSectionHeader64>;