summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2015-08-07 23:01:33 +0000
committerDimitry Andric <dim@FreeBSD.org>2015-08-07 23:01:33 +0000
commitee8648bdac07986a0f1ec897b02ec82a2f144d46 (patch)
tree52d1861acda1205241ee35a94aa63129c604d469 /tools
parent1a82d4c088707c791c792f6822f611b47a12bdfe (diff)
Notes
Diffstat (limited to 'tools')
-rw-r--r--tools/dsymutil/DebugMap.cpp4
-rw-r--r--tools/dsymutil/MachODebugMapParser.cpp16
-rw-r--r--tools/llc/llc.cpp39
-rw-r--r--tools/llvm-ar/llvm-ar.cpp101
-rw-r--r--tools/llvm-cxxdump/llvm-cxxdump.cpp5
-rw-r--r--tools/llvm-jitlistener/CMakeLists.txt6
-rw-r--r--tools/llvm-nm/llvm-nm.cpp104
-rw-r--r--tools/llvm-objdump/COFFDump.cpp4
-rw-r--r--tools/llvm-objdump/MachODump.cpp50
-rw-r--r--tools/llvm-objdump/llvm-objdump.cpp132
-rw-r--r--tools/llvm-objdump/llvm-objdump.h3
-rw-r--r--tools/llvm-readobj/ARMWinEHPrinter.cpp20
-rw-r--r--tools/llvm-readobj/COFFDumper.cpp29
-rw-r--r--tools/llvm-readobj/ELFDumper.cpp250
-rw-r--r--tools/llvm-readobj/ObjDumper.h1
-rw-r--r--tools/llvm-readobj/StreamWriter.h4
-rw-r--r--tools/llvm-readobj/Win64EHDumper.cpp4
-rw-r--r--tools/llvm-readobj/llvm-readobj.cpp10
-rw-r--r--tools/llvm-rtdyld/llvm-rtdyld.cpp77
-rw-r--r--tools/llvm-shlib/CMakeLists.txt2
-rw-r--r--tools/llvm-stress/llvm-stress.cpp95
-rw-r--r--tools/llvm-symbolizer/LLVMSymbolize.cpp6
-rw-r--r--tools/obj2yaml/elf2yaml.cpp20
-rw-r--r--tools/opt/opt.cpp1
-rw-r--r--tools/yaml2obj/yaml2elf.cpp28
25 files changed, 671 insertions, 340 deletions
diff --git a/tools/dsymutil/DebugMap.cpp b/tools/dsymutil/DebugMap.cpp
index cc7c0dc778b3a..e5cc87b3f3181 100644
--- a/tools/dsymutil/DebugMap.cpp
+++ b/tools/dsymutil/DebugMap.cpp
@@ -216,9 +216,7 @@ MappingTraits<dsymutil::DebugMapObject>::YamlDMO::denormalize(IO &IO) {
// during the test, we can't hardcode the symbols addresses, so
// look them up here and rewrite them.
for (const auto &Sym : ErrOrObjectFile->symbols()) {
- uint64_t Address;
- if (Sym.getAddress(Address))
- continue;
+ uint64_t Address = Sym.getValue();
ErrorOr<StringRef> Name = Sym.getName();
if (!Name)
continue;
diff --git a/tools/dsymutil/MachODebugMapParser.cpp b/tools/dsymutil/MachODebugMapParser.cpp
index c58545aec999e..6c9fa9b513251 100644
--- a/tools/dsymutil/MachODebugMapParser.cpp
+++ b/tools/dsymutil/MachODebugMapParser.cpp
@@ -160,8 +160,6 @@ void MachODebugMapParser::handleStabSymbolTableEntry(uint32_t StringIndex,
// symbol table to find its address as it might not be in the
// debug map (for common symbols).
Value = getMainBinarySymbolAddress(Name);
- if (Value == UnknownAddress)
- return;
break;
case MachO::N_FUN:
// Functions are scopes in STABS. They have an end marker that
@@ -197,10 +195,7 @@ void MachODebugMapParser::loadCurrentObjectFileSymbols() {
CurrentObjectAddresses.clear();
for (auto Sym : CurrentObjectHolder.Get().symbols()) {
-
- uint64_t Addr;
- if (Sym.getAddress(Addr) || Addr == UnknownAddress)
- continue;
+ uint64_t Addr = Sym.getValue();
ErrorOr<StringRef> Name = Sym.getName();
if (!Name)
continue;
@@ -214,7 +209,7 @@ void MachODebugMapParser::loadCurrentObjectFileSymbols() {
uint64_t MachODebugMapParser::getMainBinarySymbolAddress(StringRef Name) {
auto Sym = MainBinarySymbolAddresses.find(Name);
if (Sym == MainBinarySymbolAddresses.end())
- return UnknownAddress;
+ return 0;
return Sym->second;
}
@@ -228,15 +223,14 @@ void MachODebugMapParser::loadMainBinarySymbols() {
// Skip undefined and STAB entries.
if ((Type & SymbolRef::ST_Debug) || (Type & SymbolRef::ST_Unknown))
continue;
- uint64_t Addr;
// The only symbols of interest are the global variables. These
// are the only ones that need to be queried because the address
// of common data won't be described in the debug map. All other
// addresses should be fetched for the debug map.
- if (Sym.getAddress(Addr) || Addr == UnknownAddress ||
- !(Sym.getFlags() & SymbolRef::SF_Global) || Sym.getSection(Section) ||
- Section->isText())
+ if (!(Sym.getFlags() & SymbolRef::SF_Global) || Sym.getSection(Section) ||
+ Section == MainBinary.section_end() || Section->isText())
continue;
+ uint64_t Addr = Sym.getValue();
ErrorOr<StringRef> NameOrErr = Sym.getName();
if (!NameOrErr)
continue;
diff --git a/tools/llc/llc.cpp b/tools/llc/llc.cpp
index 88e7371609927..e33cd795d3ae2 100644
--- a/tools/llc/llc.cpp
+++ b/tools/llc/llc.cpp
@@ -333,29 +333,44 @@ static int compileModule(char **argv, LLVMContext &Context) {
OS = BOS.get();
}
+ AnalysisID StartBeforeID = nullptr;
AnalysisID StartAfterID = nullptr;
AnalysisID StopAfterID = nullptr;
const PassRegistry *PR = PassRegistry::getPassRegistry();
- if (!StartAfter.empty()) {
- const PassInfo *PI = PR->getPassInfo(StartAfter);
- if (!PI) {
- errs() << argv[0] << ": start-after pass is not registered.\n";
+ if (!RunPass.empty()) {
+ if (!StartAfter.empty() || !StopAfter.empty()) {
+ errs() << argv[0] << ": start-after and/or stop-after passes are "
+ "redundant when run-pass is specified.\n";
return 1;
}
- StartAfterID = PI->getTypeInfo();
- }
- if (!StopAfter.empty()) {
- const PassInfo *PI = PR->getPassInfo(StopAfter);
+ const PassInfo *PI = PR->getPassInfo(RunPass);
if (!PI) {
- errs() << argv[0] << ": stop-after pass is not registered.\n";
+ errs() << argv[0] << ": run-pass pass is not registered.\n";
return 1;
}
- StopAfterID = PI->getTypeInfo();
+ StopAfterID = StartBeforeID = PI->getTypeInfo();
+ } else {
+ if (!StartAfter.empty()) {
+ const PassInfo *PI = PR->getPassInfo(StartAfter);
+ if (!PI) {
+ errs() << argv[0] << ": start-after pass is not registered.\n";
+ return 1;
+ }
+ StartAfterID = PI->getTypeInfo();
+ }
+ if (!StopAfter.empty()) {
+ const PassInfo *PI = PR->getPassInfo(StopAfter);
+ if (!PI) {
+ errs() << argv[0] << ": stop-after pass is not registered.\n";
+ return 1;
+ }
+ StopAfterID = PI->getTypeInfo();
+ }
}
// Ask the target to add backend passes as necessary.
- if (Target->addPassesToEmitFile(PM, *OS, FileType, NoVerify, StartAfterID,
- StopAfterID, MIR.get())) {
+ if (Target->addPassesToEmitFile(PM, *OS, FileType, NoVerify, StartBeforeID,
+ StartAfterID, StopAfterID, MIR.get())) {
errs() << argv[0] << ": target does not support generation of this"
<< " file type!\n";
return 1;
diff --git a/tools/llvm-ar/llvm-ar.cpp b/tools/llvm-ar/llvm-ar.cpp
index 0fd2df4f5aa92..2c9668c63b8cc 100644
--- a/tools/llvm-ar/llvm-ar.cpp
+++ b/tools/llvm-ar/llvm-ar.cpp
@@ -13,6 +13,7 @@
//===----------------------------------------------------------------------===//
#include "llvm/ADT/StringSwitch.h"
+#include "llvm/ADT/Triple.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/LibDriver/LibDriver.h"
@@ -70,6 +71,16 @@ static cl::list<std::string>
static cl::opt<bool> MRI("M", cl::desc(""));
+namespace {
+enum Format { Default, GNU, BSD };
+}
+
+static cl::opt<Format>
+ FormatOpt("format", cl::desc("Archive format to create"),
+ cl::values(clEnumValN(Default, "defalut", "default"),
+ clEnumValN(GNU, "gnu", "gnu"),
+ clEnumValN(BSD, "bsd", "bsd"), clEnumValEnd));
+
std::string Options;
// Provide additional help output explaining the operations and modifiers of
@@ -118,6 +129,7 @@ static bool OriginalDates = false; ///< 'o' modifier
static bool OnlyUpdate = false; ///< 'u' modifier
static bool Verbose = false; ///< 'v' modifier
static bool Symtab = true; ///< 's' modifier
+static bool Deterministic = true; ///< 'D' and 'U' modifiers
// Relative Positional Argument (for insert/move). This variable holds
// the name of the archive member to which the 'a', 'b' or 'i' modifier
@@ -234,6 +246,12 @@ static ArchiveOperation parseCommandLine() {
AddBefore = true;
NumPositional++;
break;
+ case 'D':
+ Deterministic = true;
+ break;
+ case 'U':
+ Deterministic = false;
+ break;
default:
cl::PrintHelpMessage();
}
@@ -277,11 +295,13 @@ static ArchiveOperation parseCommandLine() {
// Implements the 'p' operation. This function traverses the archive
// looking for members that match the path list.
-static void doPrint(StringRef Name, object::Archive::child_iterator I) {
+static void doPrint(StringRef Name, const object::Archive::Child &C) {
if (Verbose)
outs() << "Printing " << Name << "\n";
- StringRef Data = I->getBuffer();
+ ErrorOr<StringRef> DataOrErr = C.getBuffer();
+ failIfError(DataOrErr.getError());
+ StringRef Data = *DataOrErr;
outs().write(Data.data(), Data.size());
}
@@ -306,16 +326,16 @@ static void printMode(unsigned mode) {
// the file names of each of the members. However, if verbose mode is requested
// ('v' modifier) then the file type, permission mode, user, group, size, and
// modification time are also printed.
-static void doDisplayTable(StringRef Name, object::Archive::child_iterator I) {
+static void doDisplayTable(StringRef Name, const object::Archive::Child &C) {
if (Verbose) {
- sys::fs::perms Mode = I->getAccessMode();
+ sys::fs::perms Mode = C.getAccessMode();
printMode((Mode >> 6) & 007);
printMode((Mode >> 3) & 007);
printMode(Mode & 007);
- outs() << ' ' << I->getUID();
- outs() << '/' << I->getGID();
- outs() << ' ' << format("%6llu", I->getSize());
- outs() << ' ' << I->getLastModified().str();
+ outs() << ' ' << C.getUID();
+ outs() << '/' << C.getGID();
+ outs() << ' ' << format("%6llu", C.getSize());
+ outs() << ' ' << C.getLastModified().str();
outs() << ' ';
}
outs() << Name << "\n";
@@ -323,9 +343,9 @@ static void doDisplayTable(StringRef Name, object::Archive::child_iterator I) {
// Implement the 'x' operation. This function extracts files back to the file
// system.
-static void doExtract(StringRef Name, object::Archive::child_iterator I) {
+static void doExtract(StringRef Name, const object::Archive::Child &C) {
// Retain the original mode.
- sys::fs::perms Mode = I->getAccessMode();
+ sys::fs::perms Mode = C.getAccessMode();
SmallString<128> Storage = Name;
int FD;
@@ -337,7 +357,7 @@ static void doExtract(StringRef Name, object::Archive::child_iterator I) {
raw_fd_ostream file(FD, false);
// Get the data and its length
- StringRef Data = I->getBuffer();
+ StringRef Data = *C.getBuffer();
// Write the data.
file.write(Data.data(), Data.size());
@@ -347,7 +367,7 @@ static void doExtract(StringRef Name, object::Archive::child_iterator I) {
// now.
if (OriginalDates)
failIfError(
- sys::fs::setLastModificationAndAccessTime(FD, I->getLastModified()));
+ sys::fs::setLastModificationAndAccessTime(FD, C.getLastModified()));
if (close(FD))
fail("Could not close the file");
@@ -373,31 +393,43 @@ static bool shouldCreateArchive(ArchiveOperation Op) {
static void performReadOperation(ArchiveOperation Operation,
object::Archive *OldArchive) {
- for (object::Archive::child_iterator I = OldArchive->child_begin(),
- E = OldArchive->child_end();
- I != E; ++I) {
- ErrorOr<StringRef> NameOrErr = I->getName();
+ if (Operation == Extract && OldArchive->isThin()) {
+ errs() << "extracting from a thin archive is not supported\n";
+ std::exit(1);
+ }
+
+ bool Filter = !Members.empty();
+ for (const object::Archive::Child &C : OldArchive->children()) {
+ ErrorOr<StringRef> NameOrErr = C.getName();
failIfError(NameOrErr.getError());
StringRef Name = NameOrErr.get();
- if (!Members.empty() &&
- std::find(Members.begin(), Members.end(), Name) == Members.end())
- continue;
+ if (Filter) {
+ auto I = std::find(Members.begin(), Members.end(), Name);
+ if (I == Members.end())
+ continue;
+ Members.erase(I);
+ }
switch (Operation) {
default:
llvm_unreachable("Not a read operation");
case Print:
- doPrint(Name, I);
+ doPrint(Name, C);
break;
case DisplayTable:
- doDisplayTable(Name, I);
+ doDisplayTable(Name, C);
break;
case Extract:
- doExtract(Name, I);
+ doExtract(Name, C);
break;
}
}
+ if (Members.empty())
+ return;
+ for (StringRef Name : Members)
+ errs() << Name << " was not found\n";
+ std::exit(1);
}
template <typename T>
@@ -525,7 +557,8 @@ computeNewArchiveMembers(ArchiveOperation Operation,
assert(unsigned(InsertPos) <= Ret.size());
Ret.insert(Ret.begin() + InsertPos, Moved.begin(), Moved.end());
- Ret.insert(Ret.begin() + InsertPos, Members.size(), NewArchiveIterator());
+ Ret.insert(Ret.begin() + InsertPos, Members.size(),
+ NewArchiveIterator("", ""));
int Pos = InsertPos;
for (auto &Member : Members) {
StringRef Name = sys::path::filename(Member);
@@ -539,15 +572,33 @@ computeNewArchiveMembers(ArchiveOperation Operation,
static void
performWriteOperation(ArchiveOperation Operation, object::Archive *OldArchive,
std::vector<NewArchiveIterator> *NewMembersP) {
+ object::Archive::Kind Kind;
+ switch (FormatOpt) {
+ case Default: {
+ Triple T(sys::getProcessTriple());
+ if (T.isOSDarwin())
+ Kind = object::Archive::K_BSD;
+ else
+ Kind = object::Archive::K_GNU;
+ break;
+ }
+ case GNU:
+ Kind = object::Archive::K_GNU;
+ break;
+ case BSD:
+ Kind = object::Archive::K_BSD;
+ break;
+ }
if (NewMembersP) {
std::pair<StringRef, std::error_code> Result =
- writeArchive(ArchiveName, *NewMembersP, Symtab);
+ writeArchive(ArchiveName, *NewMembersP, Symtab, Kind, Deterministic);
failIfError(Result.second, Result.first);
return;
}
std::vector<NewArchiveIterator> NewMembers =
computeNewArchiveMembers(Operation, OldArchive);
- auto Result = writeArchive(ArchiveName, NewMembers, Symtab);
+ auto Result =
+ writeArchive(ArchiveName, NewMembers, Symtab, Kind, Deterministic);
failIfError(Result.second, Result.first);
}
diff --git a/tools/llvm-cxxdump/llvm-cxxdump.cpp b/tools/llvm-cxxdump/llvm-cxxdump.cpp
index c627a662a9625..4e06be9e78b96 100644
--- a/tools/llvm-cxxdump/llvm-cxxdump.cpp
+++ b/tools/llvm-cxxdump/llvm-cxxdump.cpp
@@ -207,9 +207,10 @@ static void dumpCXXData(const ObjectFile *Obj) {
StringRef SecContents;
if (error(Sec.getContents(SecContents)))
return;
- uint64_t SymAddress;
- if (error(Sym.getAddress(SymAddress)))
+ ErrorOr<uint64_t> SymAddressOrErr = Sym.getAddress();
+ if (error(SymAddressOrErr.getError()))
return;
+ uint64_t SymAddress = *SymAddressOrErr;
uint64_t SecAddress = Sec.getAddress();
uint64_t SecSize = Sec.getSize();
uint64_t SymOffset = SymAddress - SecAddress;
diff --git a/tools/llvm-jitlistener/CMakeLists.txt b/tools/llvm-jitlistener/CMakeLists.txt
index 68a4303acef0f..61f8420a7ae59 100644
--- a/tools/llvm-jitlistener/CMakeLists.txt
+++ b/tools/llvm-jitlistener/CMakeLists.txt
@@ -6,7 +6,7 @@ include_directories( ${LLVM_INTEL_JITEVENTS_INCDIR} )
set(LLVM_LINK_COMPONENTS
asmparser
bitreader
- debuginfo
+ DebugInfoDWARF
inteljitevents
interpreter
irreader
@@ -14,6 +14,10 @@ set(LLVM_LINK_COMPONENTS
nativecodegen
object
selectiondag
+ Support
+ ExecutionEngine
+ RuntimeDyld
+ Core
)
add_llvm_tool(llvm-jitlistener
diff --git a/tools/llvm-nm/llvm-nm.cpp b/tools/llvm-nm/llvm-nm.cpp
index c88f373345647..e7ee3124ed731 100644
--- a/tools/llvm-nm/llvm-nm.cpp
+++ b/tools/llvm-nm/llvm-nm.cpp
@@ -180,67 +180,25 @@ struct NMSymbol {
uint64_t Size;
char TypeChar;
StringRef Name;
- DataRefImpl Symb;
+ BasicSymbolRef Sym;
};
}
static bool compareSymbolAddress(const NMSymbol &A, const NMSymbol &B) {
- if (!ReverseSort) {
- if (A.Address < B.Address)
- return true;
- if (A.Address == B.Address && A.Name < B.Name)
- return true;
- if (A.Address == B.Address && A.Name == B.Name && A.Size < B.Size)
- return true;
- return false;
- }
-
- if (A.Address > B.Address)
- return true;
- if (A.Address == B.Address && A.Name > B.Name)
- return true;
- if (A.Address == B.Address && A.Name == B.Name && A.Size > B.Size)
- return true;
- return false;
+ bool ADefined = !(A.Sym.getFlags() & SymbolRef::SF_Undefined);
+ bool BDefined = !(B.Sym.getFlags() & SymbolRef::SF_Undefined);
+ return std::make_tuple(ADefined, A.Address, A.Name, A.Size) <
+ std::make_tuple(BDefined, B.Address, B.Name, B.Size);
}
static bool compareSymbolSize(const NMSymbol &A, const NMSymbol &B) {
- if (!ReverseSort) {
- if (A.Size < B.Size)
- return true;
- if (A.Size == B.Size && A.Name < B.Name)
- return true;
- if (A.Size == B.Size && A.Name == B.Name && A.Address < B.Address)
- return true;
- return false;
- }
-
- if (A.Size > B.Size)
- return true;
- if (A.Size == B.Size && A.Name > B.Name)
- return true;
- if (A.Size == B.Size && A.Name == B.Name && A.Address > B.Address)
- return true;
- return false;
+ return std::make_tuple(A.Size, A.Name, A.Address) <
+ std::make_tuple(B.Size, B.Name, B.Address);
}
static bool compareSymbolName(const NMSymbol &A, const NMSymbol &B) {
- if (!ReverseSort) {
- if (A.Name < B.Name)
- return true;
- if (A.Name == B.Name && A.Size < B.Size)
- return true;
- if (A.Name == B.Name && A.Size == B.Size && A.Address < B.Address)
- return true;
- return false;
- }
- if (A.Name > B.Name)
- return true;
- if (A.Name == B.Name && A.Size > B.Size)
- return true;
- if (A.Name == B.Name && A.Size == B.Size && A.Address > B.Address)
- return true;
- return false;
+ return std::make_tuple(A.Name, A.Size, A.Address) <
+ std::make_tuple(B.Name, B.Size, B.Address);
}
static char isSymbolList64Bit(SymbolicFile &Obj) {
@@ -274,11 +232,12 @@ static void darwinPrintSymbol(MachOObjectFile *MachO, SymbolListT::iterator I,
uint16_t NDesc;
uint32_t NStrx;
uint64_t NValue;
+ DataRefImpl SymDRI = I->Sym.getRawDataRefImpl();
if (MachO->is64Bit()) {
H_64 = MachO->MachOObjectFile::getHeader64();
Filetype = H_64.filetype;
Flags = H_64.flags;
- STE_64 = MachO->getSymbol64TableEntry(I->Symb);
+ STE_64 = MachO->getSymbol64TableEntry(SymDRI);
NType = STE_64.n_type;
NSect = STE_64.n_sect;
NDesc = STE_64.n_desc;
@@ -288,7 +247,7 @@ static void darwinPrintSymbol(MachOObjectFile *MachO, SymbolListT::iterator I,
H = MachO->MachOObjectFile::getHeader();
Filetype = H.filetype;
Flags = H.flags;
- STE = MachO->getSymbolTableEntry(I->Symb);
+ STE = MachO->getSymbolTableEntry(SymDRI);
NType = STE.n_type;
NSect = STE.n_sect;
NDesc = STE.n_desc;
@@ -356,7 +315,7 @@ static void darwinPrintSymbol(MachOObjectFile *MachO, SymbolListT::iterator I,
break;
case MachO::N_SECT: {
section_iterator Sec = MachO->section_end();
- MachO->getSymbolSection(I->Symb, Sec);
+ MachO->getSymbolSection(I->Sym.getRawDataRefImpl(), Sec);
DataRefImpl Ref = Sec->getRawDataRefImpl();
StringRef SectionName;
MachO->getSectionName(Ref, SectionName);
@@ -415,7 +374,7 @@ static void darwinPrintSymbol(MachOObjectFile *MachO, SymbolListT::iterator I,
if ((NType & MachO::N_TYPE) == MachO::N_INDR) {
outs() << I->Name << " (for ";
StringRef IndirectName;
- if (MachO->getIndirectName(I->Symb, IndirectName))
+ if (MachO->getIndirectName(I->Sym.getRawDataRefImpl(), IndirectName))
outs() << "?)";
else
outs() << IndirectName << ")";
@@ -498,13 +457,14 @@ static void darwinPrintStab(MachOObjectFile *MachO, SymbolListT::iterator I) {
uint8_t NType;
uint8_t NSect;
uint16_t NDesc;
+ DataRefImpl SymDRI = I->Sym.getRawDataRefImpl();
if (MachO->is64Bit()) {
- STE_64 = MachO->getSymbol64TableEntry(I->Symb);
+ STE_64 = MachO->getSymbol64TableEntry(SymDRI);
NType = STE_64.n_type;
NSect = STE_64.n_sect;
NDesc = STE_64.n_desc;
} else {
- STE = MachO->getSymbolTableEntry(I->Symb);
+ STE = MachO->getSymbolTableEntry(SymDRI);
NType = STE.n_type;
NSect = STE.n_sect;
NDesc = STE.n_desc;
@@ -526,12 +486,17 @@ static void sortAndPrintSymbolList(SymbolicFile &Obj, bool printName,
std::string ArchiveName,
std::string ArchitectureName) {
if (!NoSort) {
+ std::function<bool(const NMSymbol &, const NMSymbol &)> Cmp;
if (NumericSort)
- std::sort(SymbolList.begin(), SymbolList.end(), compareSymbolAddress);
+ Cmp = compareSymbolAddress;
else if (SizeSort)
- std::sort(SymbolList.begin(), SymbolList.end(), compareSymbolSize);
+ Cmp = compareSymbolSize;
else
- std::sort(SymbolList.begin(), SymbolList.end(), compareSymbolName);
+ Cmp = compareSymbolName;
+
+ if (ReverseSort)
+ Cmp = [=](const NMSymbol &A, const NMSymbol &B) { return Cmp(B, A); };
+ std::sort(SymbolList.begin(), SymbolList.end(), Cmp);
}
if (!PrintFileName) {
@@ -557,9 +522,11 @@ static void sortAndPrintSymbolList(SymbolicFile &Obj, bool printName,
for (SymbolListT::iterator I = SymbolList.begin(), E = SymbolList.end();
I != E; ++I) {
- if ((I->TypeChar != 'U') && UndefinedOnly)
+ uint32_t SymFlags = I->Sym.getFlags();
+ bool Undefined = SymFlags & SymbolRef::SF_Undefined;
+ if (!Undefined && UndefinedOnly)
continue;
- if ((I->TypeChar == 'U') && DefinedOnly)
+ if (Undefined && DefinedOnly)
continue;
if (SizeSort && !PrintAddress)
continue;
@@ -578,12 +545,12 @@ static void sortAndPrintSymbolList(SymbolicFile &Obj, bool printName,
char SymbolAddrStr[18] = "";
char SymbolSizeStr[18] = "";
- if (OutputFormat == sysv || I->Address == UnknownAddress)
+ if (OutputFormat == sysv || I->TypeChar == 'U')
strcpy(SymbolAddrStr, printBlanks);
if (OutputFormat == sysv)
strcpy(SymbolSizeStr, printBlanks);
- if (I->Address != UnknownAddress)
+ if (I->TypeChar != 'U')
format(printFormat, I->Address)
.print(SymbolAddrStr, sizeof(SymbolAddrStr));
format(printFormat, I->Size).print(SymbolSizeStr, sizeof(SymbolSizeStr));
@@ -895,20 +862,23 @@ static void dumpSymbolNamesFromObject(SymbolicFile &Obj, bool printName,
continue;
NMSymbol S;
S.Size = 0;
- S.Address = UnknownAddress;
+ S.Address = 0;
if (PrintSize) {
if (isa<ELFObjectFileBase>(&Obj))
S.Size = ELFSymbolRef(Sym).getSize();
}
if (PrintAddress && isa<ObjectFile>(Obj)) {
- if (error(SymbolRef(Sym).getAddress(S.Address)))
+ SymbolRef SymRef(Sym);
+ ErrorOr<uint64_t> AddressOrErr = SymRef.getAddress();
+ if (error(AddressOrErr.getError()))
break;
+ S.Address = *AddressOrErr;
}
S.TypeChar = getNMTypeChar(Obj, Sym);
if (error(Sym.printName(OS)))
break;
OS << '\0';
- S.Symb = Sym.getRawDataRefImpl();
+ S.Sym = Sym;
SymbolList.push_back(S);
}
diff --git a/tools/llvm-objdump/COFFDump.cpp b/tools/llvm-objdump/COFFDump.cpp
index 58bdddfa9918e..8b94a50ea28b5 100644
--- a/tools/llvm-objdump/COFFDump.cpp
+++ b/tools/llvm-objdump/COFFDump.cpp
@@ -161,8 +161,10 @@ static std::error_code
resolveSectionAndAddress(const COFFObjectFile *Obj, const SymbolRef &Sym,
const coff_section *&ResolvedSection,
uint64_t &ResolvedAddr) {
- if (std::error_code EC = Sym.getAddress(ResolvedAddr))
+ ErrorOr<uint64_t> ResolvedAddrOrErr = Sym.getAddress();
+ if (std::error_code EC = ResolvedAddrOrErr.getError())
return EC;
+ ResolvedAddr = *ResolvedAddrOrErr;
section_iterator iter(Obj->section_begin());
if (std::error_code EC = Sym.getSection(iter))
return EC;
diff --git a/tools/llvm-objdump/MachODump.cpp b/tools/llvm-objdump/MachODump.cpp
index 5263c33bf2dcc..04c72f4856c89 100644
--- a/tools/llvm-objdump/MachODump.cpp
+++ b/tools/llvm-objdump/MachODump.cpp
@@ -102,9 +102,6 @@ cl::list<std::string>
cl::desc("Prints the specified segment,section for "
"Mach-O objects (requires -macho)"));
-cl::opt<bool> llvm::Raw("raw",
- cl::desc("Have -section dump the raw binary contents"));
-
cl::opt<bool>
llvm::InfoPlist("info-plist",
cl::desc("Print the info plist section as strings for "
@@ -178,18 +175,8 @@ static const Target *GetTarget(const MachOObjectFile *MachOObj,
struct SymbolSorter {
bool operator()(const SymbolRef &A, const SymbolRef &B) {
- SymbolRef::Type AType = A.getType();
- SymbolRef::Type BType = B.getType();
-
- uint64_t AAddr, BAddr;
- if (AType != SymbolRef::ST_Function)
- AAddr = 0;
- else
- A.getAddress(AAddr);
- if (BType != SymbolRef::ST_Function)
- BAddr = 0;
- else
- B.getAddress(BAddr);
+ uint64_t AAddr = (A.getType() != SymbolRef::ST_Function) ? 0 : A.getValue();
+ uint64_t BAddr = (B.getType() != SymbolRef::ST_Function) ? 0 : B.getValue();
return AAddr < BAddr;
}
};
@@ -592,8 +579,7 @@ static void CreateSymbolAddressMap(MachOObjectFile *O,
SymbolRef::Type ST = Symbol.getType();
if (ST == SymbolRef::ST_Function || ST == SymbolRef::ST_Data ||
ST == SymbolRef::ST_Other) {
- uint64_t Address;
- Symbol.getAddress(Address);
+ uint64_t Address = Symbol.getValue();
ErrorOr<StringRef> SymNameOrErr = Symbol.getName();
if (std::error_code EC = SymNameOrErr.getError())
report_fatal_error(EC.message());
@@ -1057,11 +1043,6 @@ static void DumpSectionContents(StringRef Filename, MachOObjectFile *O,
uint32_t sect_size = BytesStr.size();
uint64_t sect_addr = Section.getAddress();
- if (Raw) {
- outs().write(BytesStr.data(), BytesStr.size());
- continue;
- }
-
outs() << "Contents of (" << SegName << "," << SectName
<< ") section\n";
@@ -1190,8 +1171,7 @@ static void ProcessMachO(StringRef Filename, MachOObjectFile *MachOOF,
// UniversalHeaders or ArchiveHeaders.
if (Disassemble || PrivateHeaders || ExportsTrie || Rebase || Bind ||
LazyBind || WeakBind || IndirectSymbols || DataInCode || LinkOptHints ||
- DylibsUsed || DylibId || ObjcMetaData ||
- (DumpSections.size() != 0 && !Raw)) {
+ DylibsUsed || DylibId || ObjcMetaData || (DumpSections.size() != 0)) {
outs() << Filename;
if (!ArchiveMemberName.empty())
outs() << '(' << ArchiveMemberName << ')';
@@ -2424,7 +2404,7 @@ static const char *get_pointer_32(uint32_t Address, uint32_t &offset,
// symbol is passed, look up that address in the info's AddrMap.
static const char *get_symbol_64(uint32_t sect_offset, SectionRef S,
DisassembleInfo *info, uint64_t &n_value,
- uint64_t ReferenceValue = UnknownAddress) {
+ uint64_t ReferenceValue = 0) {
n_value = 0;
if (!info->verbose)
return nullptr;
@@ -2456,9 +2436,7 @@ static const char *get_symbol_64(uint32_t sect_offset, SectionRef S,
// and return its name.
const char *SymbolName = nullptr;
if (reloc_found && isExtern) {
- Symbol.getAddress(n_value);
- if (n_value == UnknownAddress)
- n_value = 0;
+ n_value = Symbol.getValue();
ErrorOr<StringRef> NameOrError = Symbol.getName();
if (std::error_code EC = NameOrError.getError())
report_fatal_error(EC.message());
@@ -2480,8 +2458,7 @@ static const char *get_symbol_64(uint32_t sect_offset, SectionRef S,
// We did not find an external relocation entry so look up the ReferenceValue
// as an address of a symbol and if found return that symbol's name.
- if (ReferenceValue != UnknownAddress)
- SymbolName = GuessSymbolName(ReferenceValue, info->AddrMap);
+ SymbolName = GuessSymbolName(ReferenceValue, info->AddrMap);
return SymbolName;
}
@@ -5640,7 +5617,7 @@ static const char *GuessLiteralPointer(uint64_t ReferenceValue,
if (info->O->getAnyRelocationPCRel(RE)) {
unsigned Type = info->O->getAnyRelocationType(RE);
if (Type == MachO::X86_64_RELOC_SIGNED) {
- Symbol.getAddress(ReferenceValue);
+ ReferenceValue = Symbol.getValue();
}
}
}
@@ -6131,8 +6108,7 @@ static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF,
SymbolRef::Type ST = Symbol.getType();
if (ST == SymbolRef::ST_Function || ST == SymbolRef::ST_Data ||
ST == SymbolRef::ST_Other) {
- uint64_t Address;
- Symbol.getAddress(Address);
+ uint64_t Address = Symbol.getValue();
ErrorOr<StringRef> SymNameOrErr = Symbol.getName();
if (std::error_code EC = SymNameOrErr.getError())
report_fatal_error(EC.message());
@@ -6194,9 +6170,8 @@ static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF,
continue;
// Start at the address of the symbol relative to the section's address.
- uint64_t Start = 0;
+ uint64_t Start = Symbols[SymIdx].getValue();
uint64_t SectionAddress = Sections[SectIdx].getAddress();
- Symbols[SymIdx].getAddress(Start);
Start -= SectionAddress;
// Stop disassembling either at the beginning of the next symbol or at
@@ -6209,7 +6184,7 @@ static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF,
if (NextSymType == SymbolRef::ST_Function) {
containsNextSym =
Sections[SectIdx].containsSymbol(Symbols[NextSymIdx]);
- Symbols[NextSymIdx].getAddress(NextSym);
+ NextSym = Symbols[NextSymIdx].getValue();
NextSym -= SectionAddress;
break;
}
@@ -6815,8 +6790,7 @@ void llvm::printMachOUnwindInfo(const MachOObjectFile *Obj) {
if (Section == Obj->section_end())
continue;
- uint64_t Addr;
- SymRef.getAddress(Addr);
+ uint64_t Addr = SymRef.getValue();
Symbols.insert(std::make_pair(Addr, SymRef));
}
diff --git a/tools/llvm-objdump/llvm-objdump.cpp b/tools/llvm-objdump/llvm-objdump.cpp
index 7869818546098..275eb9c6a454e 100644
--- a/tools/llvm-objdump/llvm-objdump.cpp
+++ b/tools/llvm-objdump/llvm-objdump.cpp
@@ -96,6 +96,10 @@ llvm::LazyBind("lazy-bind", cl::desc("Display mach-o lazy binding info"));
cl::opt<bool>
llvm::WeakBind("weak-bind", cl::desc("Display mach-o weak binding info"));
+cl::opt<bool>
+llvm::RawClangAST("raw-clang-ast",
+ cl::desc("Dump the raw binary contents of the clang AST section"));
+
static cl::opt<bool>
MachOOpt("macho", cl::desc("Use MachO specific object file parser"));
static cl::alias
@@ -212,9 +216,7 @@ static const Target *getTarget(const ObjectFile *Obj = nullptr) {
}
bool llvm::RelocAddressLess(RelocationRef a, RelocationRef b) {
- uint64_t a_addr = a.getOffset();
- uint64_t b_addr = b.getOffset();
- return a_addr < b_addr;
+ return a.getOffset() < b.getOffset();
}
namespace {
@@ -455,13 +457,12 @@ static void printRelocationTargetName(const MachOObjectFile *O,
for (const SymbolRef &Symbol : O->symbols()) {
std::error_code ec;
- uint64_t Addr;
- ErrorOr<StringRef> Name = Symbol.getName();
-
- if ((ec = Symbol.getAddress(Addr)))
+ ErrorOr<uint64_t> Addr = Symbol.getAddress();
+ if ((ec = Addr.getError()))
report_fatal_error(ec.message());
- if (Addr != Val)
+ if (*Addr != Val)
continue;
+ ErrorOr<StringRef> Name = Symbol.getName();
if (std::error_code EC = Name.getError())
report_fatal_error(EC.message());
fmt << *Name;
@@ -811,6 +812,30 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {
SectionRelocMap[*Sec2].push_back(Section);
}
+ // Create a mapping from virtual address to symbol name. This is used to
+ // pretty print the target of a call.
+ std::vector<std::pair<uint64_t, StringRef>> AllSymbols;
+ if (MIA) {
+ for (const SymbolRef &Symbol : Obj->symbols()) {
+ if (Symbol.getType() != SymbolRef::ST_Function)
+ continue;
+
+ ErrorOr<uint64_t> AddressOrErr = Symbol.getAddress();
+ if (error(AddressOrErr.getError()))
+ break;
+ uint64_t Address = *AddressOrErr;
+
+ ErrorOr<StringRef> Name = Symbol.getName();
+ if (error(Name.getError()))
+ break;
+ if (Name->empty())
+ continue;
+ AllSymbols.push_back(std::make_pair(Address, *Name));
+ }
+
+ array_pod_sort(AllSymbols.begin(), AllSymbols.end());
+ }
+
for (const SectionRef &Section : Obj->sections()) {
if (!Section.isText() || Section.isVirtual())
continue;
@@ -824,11 +849,10 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {
std::vector<std::pair<uint64_t, StringRef>> Symbols;
for (const SymbolRef &Symbol : Obj->symbols()) {
if (Section.containsSymbol(Symbol)) {
- uint64_t Address;
- if (error(Symbol.getAddress(Address)))
+ ErrorOr<uint64_t> AddressOrErr = Symbol.getAddress();
+ if (error(AddressOrErr.getError()))
break;
- if (Address == UnknownAddress)
- continue;
+ uint64_t Address = *AddressOrErr;
Address -= SectionAddr;
if (Address >= SectSize)
continue;
@@ -916,6 +940,29 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {
SectionAddr + Index, outs(), "", *STI);
outs() << CommentStream.str();
Comments.clear();
+ if (MIA && (MIA->isCall(Inst) || MIA->isUnconditionalBranch(Inst) ||
+ MIA->isConditionalBranch(Inst))) {
+ uint64_t Target;
+ if (MIA->evaluateBranch(Inst, SectionAddr + Index, Size, Target)) {
+ auto TargetSym = std::upper_bound(
+ AllSymbols.begin(), AllSymbols.end(), Target,
+ [](uint64_t LHS, const std::pair<uint64_t, StringRef> &RHS) {
+ return LHS < RHS.first;
+ });
+ if (TargetSym != AllSymbols.begin())
+ --TargetSym;
+ else
+ TargetSym = AllSymbols.end();
+
+ if (TargetSym != AllSymbols.end()) {
+ outs() << " <" << TargetSym->second;
+ uint64_t Disp = Target - TargetSym->first;
+ if (Disp)
+ outs() << '+' << utohexstr(Disp);
+ outs() << '>';
+ }
+ }
+ }
outs() << "\n";
} else {
errs() << ToolName << ": warning: invalid instruction encoding\n";
@@ -1113,12 +1160,13 @@ void llvm::PrintSymbolTable(const ObjectFile *o) {
return;
}
for (const SymbolRef &Symbol : o->symbols()) {
- uint64_t Address;
+ ErrorOr<uint64_t> AddressOrError = Symbol.getAddress();
+ if (error(AddressOrError.getError()))
+ continue;
+ uint64_t Address = *AddressOrError;
SymbolRef::Type Type = Symbol.getType();
uint32_t Flags = Symbol.getFlags();
section_iterator Section = o->section_end();
- if (error(Symbol.getAddress(Address)))
- continue;
if (error(Symbol.getSection(Section)))
continue;
StringRef Name;
@@ -1137,11 +1185,6 @@ void llvm::PrintSymbolTable(const ObjectFile *o) {
bool Common = Flags & SymbolRef::SF_Common;
bool Hidden = Flags & SymbolRef::SF_Hidden;
- if (Common)
- Address = Symbol.getCommonSize();
-
- if (Address == UnknownAddress)
- Address = 0;
char GlobLoc = ' ';
if (Type != SymbolRef::ST_Unknown)
GlobLoc = Global ? 'g' : 'l';
@@ -1269,6 +1312,43 @@ void llvm::printWeakBindTable(const ObjectFile *o) {
}
}
+/// Dump the raw contents of the __clangast section so the output can be piped
+/// into llvm-bcanalyzer.
+void llvm::printRawClangAST(const ObjectFile *Obj) {
+ if (outs().is_displayed()) {
+ errs() << "The -raw-clang-ast option will dump the raw binary contents of "
+ "the clang ast section.\n"
+ "Please redirect the output to a file or another program such as "
+ "llvm-bcanalyzer.\n";
+ return;
+ }
+
+ StringRef ClangASTSectionName("__clangast");
+ if (isa<COFFObjectFile>(Obj)) {
+ ClangASTSectionName = "clangast";
+ }
+
+ Optional<object::SectionRef> ClangASTSection;
+ for (auto Sec : Obj->sections()) {
+ StringRef Name;
+ Sec.getName(Name);
+ if (Name == ClangASTSectionName) {
+ ClangASTSection = Sec;
+ break;
+ }
+ }
+ if (!ClangASTSection)
+ return;
+
+ StringRef ClangASTContents;
+ if (error(ClangASTSection.getValue().getContents(ClangASTContents))) {
+ errs() << "Could not read the " << ClangASTSectionName << " section!\n";
+ return;
+ }
+
+ outs().write(ClangASTContents.data(), ClangASTContents.size());
+}
+
static void printFaultMaps(const ObjectFile *Obj) {
const char *FaultMapSectionName = nullptr;
@@ -1323,9 +1403,12 @@ static void printPrivateFileHeader(const ObjectFile *o) {
}
static void DumpObject(const ObjectFile *o) {
- outs() << '\n';
- outs() << o->getFileName()
- << ":\tfile format " << o->getFileFormatName() << "\n\n";
+ // Avoid other output when using a raw option.
+ if (!RawClangAST) {
+ outs() << '\n';
+ outs() << o->getFileName()
+ << ":\tfile format " << o->getFileFormatName() << "\n\n";
+ }
if (Disassemble)
DisassembleObject(o, Relocations);
@@ -1351,6 +1434,8 @@ static void DumpObject(const ObjectFile *o) {
printLazyBindTable(o);
if (WeakBind)
printWeakBindTable(o);
+ if (RawClangAST)
+ printRawClangAST(o);
if (PrintFaultMaps)
printFaultMaps(o);
}
@@ -1441,6 +1526,7 @@ int main(int argc, char **argv) {
&& !Bind
&& !LazyBind
&& !WeakBind
+ && !RawClangAST
&& !(UniversalHeaders && MachOOpt)
&& !(ArchiveHeaders && MachOOpt)
&& !(IndirectSymbols && MachOOpt)
diff --git a/tools/llvm-objdump/llvm-objdump.h b/tools/llvm-objdump/llvm-objdump.h
index b4d34f4033bcf..eb10d8344f711 100644
--- a/tools/llvm-objdump/llvm-objdump.h
+++ b/tools/llvm-objdump/llvm-objdump.h
@@ -26,7 +26,6 @@ extern cl::opt<std::string> ArchName;
extern cl::opt<std::string> MCPU;
extern cl::list<std::string> MAttrs;
extern cl::list<std::string> DumpSections;
-extern cl::opt<bool> Raw;
extern cl::opt<bool> Disassemble;
extern cl::opt<bool> NoShowRawInsn;
extern cl::opt<bool> PrivateHeaders;
@@ -35,6 +34,7 @@ extern cl::opt<bool> Rebase;
extern cl::opt<bool> Bind;
extern cl::opt<bool> LazyBind;
extern cl::opt<bool> WeakBind;
+extern cl::opt<bool> RawClangAST;
extern cl::opt<bool> UniversalHeaders;
extern cl::opt<bool> ArchiveHeaders;
extern cl::opt<bool> IndirectSymbols;
@@ -72,6 +72,7 @@ void printRebaseTable(const object::ObjectFile *o);
void printBindTable(const object::ObjectFile *o);
void printLazyBindTable(const object::ObjectFile *o);
void printWeakBindTable(const object::ObjectFile *o);
+void printRawClangAST(const object::ObjectFile *o);
void PrintRelocations(const object::ObjectFile *o);
void PrintSectionHeaders(const object::ObjectFile *o);
void PrintSectionContents(const object::ObjectFile *o);
diff --git a/tools/llvm-readobj/ARMWinEHPrinter.cpp b/tools/llvm-readobj/ARMWinEHPrinter.cpp
index a1ea79f3688ea..bf5ff8e1d0310 100644
--- a/tools/llvm-readobj/ARMWinEHPrinter.cpp
+++ b/tools/llvm-readobj/ARMWinEHPrinter.cpp
@@ -201,10 +201,10 @@ ErrorOr<object::SymbolRef> Decoder::getSymbol(const COFFObjectFile &COFF,
if (FunctionOnly && Symbol.getType() != SymbolRef::ST_Function)
continue;
- uint64_t Address;
- if (std::error_code EC = Symbol.getAddress(Address))
+ ErrorOr<uint64_t> Address = Symbol.getAddress();
+ if (std::error_code EC = Address.getError())
return EC;
- if (Address == VA)
+ if (*Address == VA)
return Symbol;
}
return readobj_error::unknown_symbol;
@@ -605,7 +605,10 @@ bool Decoder::dumpUnpackedEntry(const COFFObjectFile &COFF,
if (std::error_code EC = FunctionNameOrErr.getError())
report_fatal_error(EC.message());
FunctionName = *FunctionNameOrErr;
- Function->getAddress(FunctionAddress);
+ ErrorOr<uint64_t> FunctionAddressOrErr = Function->getAddress();
+ if (std::error_code EC = FunctionAddressOrErr.getError())
+ report_fatal_error(EC.message());
+ FunctionAddress = *FunctionAddressOrErr;
} else {
const pe32_header *PEHeader;
if (COFF.getPE32Header(PEHeader))
@@ -620,8 +623,10 @@ bool Decoder::dumpUnpackedEntry(const COFFObjectFile &COFF,
if (std::error_code EC = Name.getError())
report_fatal_error(EC.message());
- uint64_t Address;
- XDataRecord->getAddress(Address);
+ ErrorOr<uint64_t> AddressOrErr = XDataRecord->getAddress();
+ if (std::error_code EC = AddressOrErr.getError())
+ report_fatal_error(EC.message());
+ uint64_t Address = *AddressOrErr;
SW.printString("ExceptionRecord", formatSymbol(*Name, Address));
@@ -666,7 +671,8 @@ bool Decoder::dumpPackedEntry(const object::COFFObjectFile &COFF,
if (std::error_code EC = FunctionNameOrErr.getError())
report_fatal_error(EC.message());
FunctionName = *FunctionNameOrErr;
- Function->getAddress(FunctionAddress);
+ ErrorOr<uint64_t> FunctionAddressOrErr = Function->getAddress();
+ FunctionAddress = *FunctionAddressOrErr;
} else {
const pe32_header *PEHeader;
if (COFF.getPE32Header(PEHeader))
diff --git a/tools/llvm-readobj/COFFDumper.cpp b/tools/llvm-readobj/COFFDumper.cpp
index f5effe2924419..cf897d7cb4840 100644
--- a/tools/llvm-readobj/COFFDumper.cpp
+++ b/tools/llvm-readobj/COFFDumper.cpp
@@ -48,7 +48,6 @@ public:
COFFDumper(const llvm::object::COFFObjectFile *Obj, StreamWriter& Writer)
: ObjDumper(Writer)
, Obj(Obj) {
- cacheRelocations();
}
void printFileHeaders() override;
@@ -92,6 +91,7 @@ private:
typedef DenseMap<const coff_section*, std::vector<RelocationRef> > RelocMapTy;
const llvm::object::COFFObjectFile *Obj;
+ bool RelocCached = false;
RelocMapTy RelocMap;
StringRef CVFileIndexToStringOffsetTable;
StringRef CVStringTable;
@@ -119,6 +119,7 @@ std::error_code createCOFFDumper(const object::ObjectFile *Obj,
// symbol used for the relocation at the offset.
std::error_code COFFDumper::resolveSymbol(const coff_section *Section,
uint64_t Offset, SymbolRef &Sym) {
+ cacheRelocations();
const auto &Relocations = RelocMap[Section];
for (const auto &Relocation : Relocations) {
uint64_t RelocationOffset = Relocation.getOffset();
@@ -339,6 +340,10 @@ static std::error_code getSymbolAuxData(const COFFObjectFile *Obj,
}
void COFFDumper::cacheRelocations() {
+ if (RelocCached)
+ return;
+ RelocCached = true;
+
for (const SectionRef &S : Obj->sections()) {
const coff_section *Section = Obj->getCOFFSection(S);
@@ -580,7 +585,11 @@ void COFFDumper::printCodeViewDebugInfo(const SectionRef &Section) {
W.printString("FunctionName", Name);
DataExtractor DE(FunctionLineTables[Name], true, 4);
- uint32_t Offset = 8; // Skip relocations.
+ uint32_t Offset = 6; // Skip relocations.
+ uint16_t Flags = DE.getU16(&Offset);
+ W.printHex("Flags", Flags);
+ bool HasColumnInformation =
+ Flags & COFF::DEBUG_LINE_TABLES_HAVE_COLUMN_RECORDS;
uint32_t FunctionSize = DE.getU32(&Offset);
W.printHex("CodeSize", FunctionSize);
while (DE.isValidOffset(Offset)) {
@@ -588,9 +597,12 @@ void COFFDumper::printCodeViewDebugInfo(const SectionRef &Section) {
// in the line table. The filename string is accessed using double
// indirection to the string table subsection using the index subsection.
uint32_t OffsetInIndex = DE.getU32(&Offset),
- SegmentLength = DE.getU32(&Offset),
+ SegmentLength = DE.getU32(&Offset),
FullSegmentSize = DE.getU32(&Offset);
- if (FullSegmentSize != 12 + 8 * SegmentLength) {
+
+ if (FullSegmentSize !=
+ 12 + 8 * SegmentLength +
+ (HasColumnInformation ? 4 * SegmentLength : 0)) {
error(object_error::parse_failed);
return;
}
@@ -631,6 +643,15 @@ void COFFDumper::printCodeViewDebugInfo(const SectionRef &Section) {
format("+0x%X", PC).snprint(Buffer, 32);
W.printNumber(Buffer, LineNumber);
}
+ if (HasColumnInformation) {
+ for (unsigned J = 0; J != SegmentLength && DE.isValidOffset(Offset);
+ ++J) {
+ uint16_t ColStart = DE.getU16(&Offset);
+ W.printNumber("ColStart", ColStart);
+ uint16_t ColEnd = DE.getU16(&Offset);
+ W.printNumber("ColEnd", ColEnd);
+ }
+ }
}
}
}
diff --git a/tools/llvm-readobj/ELFDumper.cpp b/tools/llvm-readobj/ELFDumper.cpp
index a4b25efeb9ba1..1cdf5529c0809 100644
--- a/tools/llvm-readobj/ELFDumper.cpp
+++ b/tools/llvm-readobj/ELFDumper.cpp
@@ -56,6 +56,7 @@ public:
void printDynamicTable() override;
void printNeededLibraries() override;
void printProgramHeaders() override;
+ void printHashTable() override;
void printAttributes() override;
void printMipsPLTGOT() override;
@@ -1119,6 +1120,18 @@ void ELFDumper<ELFT>::printProgramHeaders() {
}
}
+template <typename ELFT>
+void ELFDumper<ELFT>::printHashTable() {
+ DictScope D(W, "HashTable");
+ auto HT = Obj->getHashTable();
+ if (!HT)
+ return;
+ W.printNumber("Num Buckets", HT->nbucket);
+ W.printNumber("Num Chains", HT->nchain);
+ W.printList("Buckets", HT->buckets());
+ W.printList("Chains", HT->chains());
+}
+
template <class ELFT>
void ELFDumper<ELFT>::printAttributes() {
W.startLine() << "Attributes not implemented.\n";
@@ -1162,9 +1175,10 @@ public:
typedef typename ObjectFile::Elf_Shdr Elf_Shdr;
typedef typename ObjectFile::Elf_Sym Elf_Sym;
- MipsGOTParser(const ObjectFile *Obj, StreamWriter &W) : Obj(Obj), W(W) {}
+ MipsGOTParser(const ObjectFile *Obj, StreamWriter &W);
- void parseGOT(const Elf_Shdr &GOTShdr);
+ void parseGOT();
+ void parsePLT();
private:
typedef typename ObjectFile::Elf_Addr GOTEntry;
@@ -1173,35 +1187,79 @@ private:
const ObjectFile *Obj;
StreamWriter &W;
+ llvm::Optional<uint64_t> DtPltGot;
+ llvm::Optional<uint64_t> DtLocalGotNum;
+ llvm::Optional<uint64_t> DtGotSym;
+ llvm::Optional<uint64_t> DtMipsPltGot;
+ llvm::Optional<uint64_t> DtJmpRel;
std::size_t getGOTTotal(ArrayRef<uint8_t> GOT) const;
GOTIter makeGOTIter(ArrayRef<uint8_t> GOT, std::size_t EntryNum);
- bool getGOTTags(uint64_t &LocalGotNum, uint64_t &GotSym);
void printGotEntry(uint64_t GotAddr, GOTIter BeginIt, GOTIter It);
void printGlobalGotEntry(uint64_t GotAddr, GOTIter BeginIt, GOTIter It,
const Elf_Sym *Sym, bool IsDynamic);
+ void printPLTEntry(uint64_t PLTAddr, GOTIter BeginIt, GOTIter It,
+ StringRef Purpose);
+ void printPLTEntry(uint64_t PLTAddr, GOTIter BeginIt, GOTIter It,
+ const Elf_Sym *Sym);
};
}
template <class ELFT>
-void MipsGOTParser<ELFT>::parseGOT(const Elf_Shdr &GOTShdr) {
+MipsGOTParser<ELFT>::MipsGOTParser(const ObjectFile *Obj, StreamWriter &W)
+ : Obj(Obj), W(W) {
+ for (const auto &Entry : Obj->dynamic_table()) {
+ switch (Entry.getTag()) {
+ case ELF::DT_PLTGOT:
+ DtPltGot = Entry.getVal();
+ break;
+ case ELF::DT_MIPS_LOCAL_GOTNO:
+ DtLocalGotNum = Entry.getVal();
+ break;
+ case ELF::DT_MIPS_GOTSYM:
+ DtGotSym = Entry.getVal();
+ break;
+ case ELF::DT_MIPS_PLTGOT:
+ DtMipsPltGot = Entry.getVal();
+ break;
+ case ELF::DT_JMPREL:
+ DtJmpRel = Entry.getVal();
+ break;
+ }
+ }
+}
+
+template <class ELFT> void MipsGOTParser<ELFT>::parseGOT() {
// See "Global Offset Table" in Chapter 5 in the following document
// for detailed GOT description.
// ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
+ if (!DtPltGot) {
+ W.startLine() << "Cannot find PLTGOT dynamic table tag.\n";
+ return;
+ }
+ if (!DtLocalGotNum) {
+ W.startLine() << "Cannot find MIPS_LOCAL_GOTNO dynamic table tag.\n";
+ return;
+ }
+ if (!DtGotSym) {
+ W.startLine() << "Cannot find MIPS_GOTSYM dynamic table tag.\n";
+ return;
+ }
- ErrorOr<ArrayRef<uint8_t>> GOT = Obj->getSectionContents(&GOTShdr);
- if (!GOT) {
- W.startLine() << "The .got section is empty.\n";
+ const Elf_Shdr *GOTShdr = findSectionByAddress(Obj, *DtPltGot);
+ if (!GOTShdr) {
+ W.startLine() << "There is no .got section in the file.\n";
return;
}
- uint64_t DtLocalGotNum;
- uint64_t DtGotSym;
- if (!getGOTTags(DtLocalGotNum, DtGotSym))
+ ErrorOr<ArrayRef<uint8_t>> GOT = Obj->getSectionContents(GOTShdr);
+ if (!GOT) {
+ W.startLine() << "The .got section is empty.\n";
return;
+ }
- if (DtLocalGotNum > getGOTTotal(*GOT)) {
+ if (*DtLocalGotNum > getGOTTotal(*GOT)) {
W.startLine() << "MIPS_LOCAL_GOTNO exceeds a number of GOT entries.\n";
return;
}
@@ -1210,37 +1268,37 @@ void MipsGOTParser<ELFT>::parseGOT(const Elf_Shdr &GOTShdr) {
const Elf_Sym *DynSymEnd = Obj->dynamic_symbol_end();
std::size_t DynSymTotal = std::size_t(std::distance(DynSymBegin, DynSymEnd));
- if (DtGotSym > DynSymTotal) {
+ if (*DtGotSym > DynSymTotal) {
W.startLine() << "MIPS_GOTSYM exceeds a number of dynamic symbols.\n";
return;
}
- std::size_t GlobalGotNum = DynSymTotal - DtGotSym;
+ std::size_t GlobalGotNum = DynSymTotal - *DtGotSym;
- if (DtLocalGotNum + GlobalGotNum > getGOTTotal(*GOT)) {
+ if (*DtLocalGotNum + GlobalGotNum > getGOTTotal(*GOT)) {
W.startLine() << "Number of global GOT entries exceeds the size of GOT.\n";
return;
}
GOTIter GotBegin = makeGOTIter(*GOT, 0);
- GOTIter GotLocalEnd = makeGOTIter(*GOT, DtLocalGotNum);
+ GOTIter GotLocalEnd = makeGOTIter(*GOT, *DtLocalGotNum);
GOTIter It = GotBegin;
DictScope GS(W, "Primary GOT");
- W.printHex("Canonical gp value", GOTShdr.sh_addr + 0x7ff0);
+ W.printHex("Canonical gp value", GOTShdr->sh_addr + 0x7ff0);
{
ListScope RS(W, "Reserved entries");
{
DictScope D(W, "Entry");
- printGotEntry(GOTShdr.sh_addr, GotBegin, It++);
+ printGotEntry(GOTShdr->sh_addr, GotBegin, It++);
W.printString("Purpose", StringRef("Lazy resolver"));
}
if (It != GotLocalEnd && (*It >> (sizeof(GOTEntry) * 8 - 1)) != 0) {
DictScope D(W, "Entry");
- printGotEntry(GOTShdr.sh_addr, GotBegin, It++);
+ printGotEntry(GOTShdr->sh_addr, GotBegin, It++);
W.printString("Purpose", StringRef("Module pointer (GNU extension)"));
}
}
@@ -1248,24 +1306,88 @@ void MipsGOTParser<ELFT>::parseGOT(const Elf_Shdr &GOTShdr) {
ListScope LS(W, "Local entries");
for (; It != GotLocalEnd; ++It) {
DictScope D(W, "Entry");
- printGotEntry(GOTShdr.sh_addr, GotBegin, It);
+ printGotEntry(GOTShdr->sh_addr, GotBegin, It);
}
}
{
ListScope GS(W, "Global entries");
- GOTIter GotGlobalEnd = makeGOTIter(*GOT, DtLocalGotNum + GlobalGotNum);
- const Elf_Sym *GotDynSym = DynSymBegin + DtGotSym;
+ GOTIter GotGlobalEnd = makeGOTIter(*GOT, *DtLocalGotNum + GlobalGotNum);
+ const Elf_Sym *GotDynSym = DynSymBegin + *DtGotSym;
for (; It != GotGlobalEnd; ++It) {
DictScope D(W, "Entry");
- printGlobalGotEntry(GOTShdr.sh_addr, GotBegin, It, GotDynSym++, true);
+ printGlobalGotEntry(GOTShdr->sh_addr, GotBegin, It, GotDynSym++, true);
}
}
- std::size_t SpecGotNum = getGOTTotal(*GOT) - DtLocalGotNum - GlobalGotNum;
+ std::size_t SpecGotNum = getGOTTotal(*GOT) - *DtLocalGotNum - GlobalGotNum;
W.printNumber("Number of TLS and multi-GOT entries", uint64_t(SpecGotNum));
}
+template <class ELFT> void MipsGOTParser<ELFT>::parsePLT() {
+ if (!DtMipsPltGot) {
+ W.startLine() << "Cannot find MIPS_PLTGOT dynamic table tag.\n";
+ return;
+ }
+ if (!DtJmpRel) {
+ W.startLine() << "Cannot find JMPREL dynamic table tag.\n";
+ return;
+ }
+
+ const Elf_Shdr *PLTShdr = findSectionByAddress(Obj, *DtMipsPltGot);
+ if (!PLTShdr) {
+ W.startLine() << "There is no .got.plt section in the file.\n";
+ return;
+ }
+ ErrorOr<ArrayRef<uint8_t>> PLT = Obj->getSectionContents(PLTShdr);
+ if (!PLT) {
+ W.startLine() << "The .got.plt section is empty.\n";
+ return;
+ }
+
+ const Elf_Shdr *PLTRelShdr = findSectionByAddress(Obj, *DtJmpRel);
+ if (!PLTShdr) {
+ W.startLine() << "There is no .rel.plt section in the file.\n";
+ return;
+ }
+
+ GOTIter PLTBegin = makeGOTIter(*PLT, 0);
+ GOTIter PLTEnd = makeGOTIter(*PLT, getGOTTotal(*PLT));
+ GOTIter It = PLTBegin;
+
+ DictScope GS(W, "PLT GOT");
+ {
+ ListScope RS(W, "Reserved entries");
+ printPLTEntry(PLTShdr->sh_addr, PLTBegin, It++, "PLT lazy resolver");
+ if (It != PLTEnd)
+ printPLTEntry(PLTShdr->sh_addr, PLTBegin, It++, "Module pointer");
+ }
+ {
+ ListScope GS(W, "Entries");
+
+ switch (PLTRelShdr->sh_type) {
+ case ELF::SHT_REL:
+ for (typename ObjectFile::Elf_Rel_Iter RI = Obj->rel_begin(PLTRelShdr),
+ RE = Obj->rel_end(PLTRelShdr);
+ RI != RE && It != PLTEnd; ++RI, ++It) {
+ const Elf_Sym *Sym =
+ Obj->getRelocationSymbol(&*PLTRelShdr, &*RI).second;
+ printPLTEntry(PLTShdr->sh_addr, PLTBegin, It, Sym);
+ }
+ break;
+ case ELF::SHT_RELA:
+ for (typename ObjectFile::Elf_Rela_Iter RI = Obj->rela_begin(PLTRelShdr),
+ RE = Obj->rela_end(PLTRelShdr);
+ RI != RE && It != PLTEnd; ++RI, ++It) {
+ const Elf_Sym *Sym =
+ Obj->getRelocationSymbol(&*PLTRelShdr, &*RI).second;
+ printPLTEntry(PLTShdr->sh_addr, PLTBegin, It, Sym);
+ }
+ break;
+ }
+ }
+}
+
template <class ELFT>
std::size_t MipsGOTParser<ELFT>::getGOTTotal(ArrayRef<uint8_t> GOT) const {
return GOT.size() / sizeof(GOTEntry);
@@ -1279,36 +1401,6 @@ MipsGOTParser<ELFT>::makeGOTIter(ArrayRef<uint8_t> GOT, std::size_t EntryNum) {
}
template <class ELFT>
-bool MipsGOTParser<ELFT>::getGOTTags(uint64_t &LocalGotNum, uint64_t &GotSym) {
- bool FoundLocalGotNum = false;
- bool FoundGotSym = false;
- for (const auto &Entry : Obj->dynamic_table()) {
- switch (Entry.getTag()) {
- case ELF::DT_MIPS_LOCAL_GOTNO:
- LocalGotNum = Entry.getVal();
- FoundLocalGotNum = true;
- break;
- case ELF::DT_MIPS_GOTSYM:
- GotSym = Entry.getVal();
- FoundGotSym = true;
- break;
- }
- }
-
- if (!FoundLocalGotNum) {
- W.startLine() << "Cannot find MIPS_LOCAL_GOTNO dynamic table tag.\n";
- return false;
- }
-
- if (!FoundGotSym) {
- W.startLine() << "Cannot find MIPS_GOTSYM dynamic table tag.\n";
- return false;
- }
-
- return true;
-}
-
-template <class ELFT>
void MipsGOTParser<ELFT>::printGotEntry(uint64_t GotAddr, GOTIter BeginIt,
GOTIter It) {
int64_t Offset = std::distance(BeginIt, It) * sizeof(GOTEntry);
@@ -1335,32 +1427,44 @@ void MipsGOTParser<ELFT>::printGlobalGotEntry(uint64_t GotAddr, GOTIter BeginIt,
W.printNumber("Name", FullSymbolName, Sym->st_name);
}
-template <class ELFT> void ELFDumper<ELFT>::printMipsPLTGOT() {
- if (Obj->getHeader()->e_machine != EM_MIPS) {
- W.startLine() << "MIPS PLT GOT is available for MIPS targets only.\n";
- return;
- }
+template <class ELFT>
+void MipsGOTParser<ELFT>::printPLTEntry(uint64_t PLTAddr, GOTIter BeginIt,
+ GOTIter It, StringRef Purpose) {
+ DictScope D(W, "Entry");
+ int64_t Offset = std::distance(BeginIt, It) * sizeof(GOTEntry);
+ W.printHex("Address", PLTAddr + Offset);
+ W.printHex("Initial", *It);
+ W.printString("Purpose", Purpose);
+}
- llvm::Optional<uint64_t> DtPltGot;
- for (const auto &Entry : Obj->dynamic_table()) {
- if (Entry.getTag() == ELF::DT_PLTGOT) {
- DtPltGot = Entry.getVal();
- break;
- }
- }
+template <class ELFT>
+void MipsGOTParser<ELFT>::printPLTEntry(uint64_t PLTAddr, GOTIter BeginIt,
+ GOTIter It, const Elf_Sym *Sym) {
+ DictScope D(W, "Entry");
+ int64_t Offset = std::distance(BeginIt, It) * sizeof(GOTEntry);
+ W.printHex("Address", PLTAddr + Offset);
+ W.printHex("Initial", *It);
+ W.printHex("Value", Sym->st_value);
+ W.printEnum("Type", Sym->getType(), makeArrayRef(ElfSymbolTypes));
- if (!DtPltGot) {
- W.startLine() << "Cannot find PLTGOT dynamic table tag.\n";
- return;
- }
+ unsigned SectionIndex = 0;
+ StringRef SectionName;
+ getSectionNameIndex(*Obj, Sym, SectionName, SectionIndex);
+ W.printHex("Section", SectionName, SectionIndex);
- const Elf_Shdr *GotShdr = findSectionByAddress(Obj, *DtPltGot);
- if (!GotShdr) {
- W.startLine() << "There is no .got section in the file.\n";
+ std::string FullSymbolName = getFullSymbolName(*Obj, Sym, true);
+ W.printNumber("Name", FullSymbolName, Sym->st_name);
+}
+
+template <class ELFT> void ELFDumper<ELFT>::printMipsPLTGOT() {
+ if (Obj->getHeader()->e_machine != EM_MIPS) {
+ W.startLine() << "MIPS PLT GOT is available for MIPS targets only.\n";
return;
}
- MipsGOTParser<ELFT>(Obj, W).parseGOT(*GotShdr);
+ MipsGOTParser<ELFT> GOTParser(Obj, W);
+ GOTParser.parseGOT();
+ GOTParser.parsePLT();
}
static const EnumEntry<unsigned> ElfMipsISAExtType[] = {
diff --git a/tools/llvm-readobj/ObjDumper.h b/tools/llvm-readobj/ObjDumper.h
index 27e15b256cc57..5ecf0ec3d6fa0 100644
--- a/tools/llvm-readobj/ObjDumper.h
+++ b/tools/llvm-readobj/ObjDumper.h
@@ -37,6 +37,7 @@ public:
virtual void printDynamicTable() { }
virtual void printNeededLibraries() { }
virtual void printProgramHeaders() { }
+ virtual void printHashTable() { }
// Only implemented for ARM ELF at this time.
virtual void printAttributes() { }
diff --git a/tools/llvm-readobj/StreamWriter.h b/tools/llvm-readobj/StreamWriter.h
index 245588ba06006..f3cc57ef940e7 100644
--- a/tools/llvm-readobj/StreamWriter.h
+++ b/tools/llvm-readobj/StreamWriter.h
@@ -181,8 +181,8 @@ public:
startLine() << Label << ": " << (Value ? "Yes" : "No") << '\n';
}
- template <typename T_>
- void printList(StringRef Label, const SmallVectorImpl<T_> &List) {
+ template <typename T>
+ void printList(StringRef Label, const T &List) {
startLine() << Label << ": [";
bool Comma = false;
for (const auto &Item : List) {
diff --git a/tools/llvm-readobj/Win64EHDumper.cpp b/tools/llvm-readobj/Win64EHDumper.cpp
index 5a8af4135bd75..f57eea20e2d9c 100644
--- a/tools/llvm-readobj/Win64EHDumper.cpp
+++ b/tools/llvm-readobj/Win64EHDumper.cpp
@@ -144,8 +144,10 @@ static std::error_code resolveRelocation(const Dumper::Context &Ctx,
Ctx.ResolveSymbol(Section, Offset, Symbol, Ctx.UserData))
return EC;
- if (std::error_code EC = Symbol.getAddress(ResolvedAddress))
+ ErrorOr<uint64_t> ResolvedAddressOrErr = Symbol.getAddress();
+ if (std::error_code EC = ResolvedAddressOrErr.getError())
return EC;
+ ResolvedAddress = *ResolvedAddressOrErr;
section_iterator SI = Ctx.COFF.section_begin();
if (std::error_code EC = Symbol.getSection(SI))
diff --git a/tools/llvm-readobj/llvm-readobj.cpp b/tools/llvm-readobj/llvm-readobj.cpp
index c5bccf9796094..12afacb0a858e 100644
--- a/tools/llvm-readobj/llvm-readobj.cpp
+++ b/tools/llvm-readobj/llvm-readobj.cpp
@@ -127,6 +127,10 @@ namespace opts {
cl::opt<bool> ProgramHeaders("program-headers",
cl::desc("Display ELF program headers"));
+ // -hash-table
+ cl::opt<bool> HashTable("hash-table",
+ cl::desc("Display ELF hash table"));
+
// -expand-relocs
cl::opt<bool> ExpandRelocs("expand-relocs",
cl::desc("Expand each shown relocation to multiple lines"));
@@ -199,9 +203,7 @@ bool error(std::error_code EC) {
}
bool relocAddressLess(RelocationRef a, RelocationRef b) {
- uint64_t a_addr = a.getOffset();
- uint64_t b_addr = b.getOffset();
- return a_addr < b_addr;
+ return a.getOffset() < b.getOffset();
}
} // namespace llvm
@@ -302,6 +304,8 @@ static void dumpObject(const ObjectFile *Obj) {
Dumper->printNeededLibraries();
if (opts::ProgramHeaders)
Dumper->printProgramHeaders();
+ if (opts::HashTable)
+ Dumper->printHashTable();
if (Obj->getArch() == llvm::Triple::arm && Obj->isELF())
if (opts::ARMAttributes)
Dumper->printAttributes();
diff --git a/tools/llvm-rtdyld/llvm-rtdyld.cpp b/tools/llvm-rtdyld/llvm-rtdyld.cpp
index 98c6f5c4399cd..86f66f89b1595 100644
--- a/tools/llvm-rtdyld/llvm-rtdyld.cpp
+++ b/tools/llvm-rtdyld/llvm-rtdyld.cpp
@@ -115,8 +115,17 @@ TargetSectionSep("target-section-sep",
static cl::list<std::string>
SpecificSectionMappings("map-section",
- cl::desc("Map a section to a specific address."),
- cl::ZeroOrMore);
+ cl::desc("For -verify only: Map a section to a "
+ "specific address."),
+ cl::ZeroOrMore,
+ cl::Hidden);
+
+static cl::list<std::string>
+DummySymbolMappings("dummy-extern",
+ cl::desc("For -verify only: Inject a symbol into the extern "
+ "symbol table."),
+ cl::ZeroOrMore,
+ cl::Hidden);
/* *** */
@@ -147,10 +156,25 @@ public:
// relocations) will get to the data cache but not to the instruction cache.
virtual void invalidateInstructionCache();
+ void addDummySymbol(const std::string &Name, uint64_t Addr) {
+ DummyExterns[Name] = Addr;
+ }
+
+ RuntimeDyld::SymbolInfo findSymbol(const std::string &Name) override {
+ auto I = DummyExterns.find(Name);
+
+ if (I != DummyExterns.end())
+ return RuntimeDyld::SymbolInfo(I->second, JITSymbolFlags::Exported);
+
+ return RTDyldMemoryManager::findSymbol(Name);
+ }
+
void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr,
size_t Size) override {}
void deregisterEHFrames(uint8_t *Addr, uint64_t LoadAddr,
size_t Size) override {}
+private:
+ std::map<std::string, uint64_t> DummyExterns;
};
uint8_t *TrivialMemoryManager::allocateCodeSection(uintptr_t Size,
@@ -269,9 +293,10 @@ static int printLineInfoForInput(bool LoadObjects, bool UseDebugObj) {
ErrorOr<StringRef> Name = Sym.getName();
if (!Name)
continue;
- uint64_t Addr;
- if (Sym.getAddress(Addr))
+ ErrorOr<uint64_t> AddrOrErr = Sym.getAddress();
+ if (!AddrOrErr)
continue;
+ uint64_t Addr = *AddrOrErr;
uint64_t Size = P.second;
// If we're not using the debug object, compute the address of the
@@ -400,7 +425,7 @@ applySpecificSectionMappings(RuntimeDyldChecker &Checker) {
for (StringRef Mapping : SpecificSectionMappings) {
size_t EqualsIdx = Mapping.find_first_of("=");
- StringRef SectionIDStr = Mapping.substr(0, EqualsIdx);
+ std::string SectionIDStr = Mapping.substr(0, EqualsIdx);
size_t ComaIdx = Mapping.find_first_of(",");
if (ComaIdx == StringRef::npos) {
@@ -409,8 +434,8 @@ applySpecificSectionMappings(RuntimeDyldChecker &Checker) {
exit(1);
}
- StringRef FileName = SectionIDStr.substr(0, ComaIdx);
- StringRef SectionName = SectionIDStr.substr(ComaIdx + 1);
+ std::string FileName = SectionIDStr.substr(0, ComaIdx);
+ std::string SectionName = SectionIDStr.substr(ComaIdx + 1);
uint64_t OldAddrInt;
std::string ErrorMsg;
@@ -424,11 +449,11 @@ applySpecificSectionMappings(RuntimeDyldChecker &Checker) {
void* OldAddr = reinterpret_cast<void*>(static_cast<uintptr_t>(OldAddrInt));
- StringRef NewAddrStr = Mapping.substr(EqualsIdx + 1);
+ std::string NewAddrStr = Mapping.substr(EqualsIdx + 1);
uint64_t NewAddr;
- if (NewAddrStr.getAsInteger(0, NewAddr)) {
- errs() << "Invalid section address in mapping: " << Mapping << "\n";
+ if (StringRef(NewAddrStr).getAsInteger(0, NewAddr)) {
+ errs() << "Invalid section address in mapping '" << Mapping << "'.\n";
exit(1);
}
@@ -450,9 +475,9 @@ applySpecificSectionMappings(RuntimeDyldChecker &Checker) {
// Defaults to zero. Set to something big
// (e.g. 1 << 32) to stress-test stubs, GOTs, etc.
//
-static void remapSections(const llvm::Triple &TargetTriple,
- const TrivialMemoryManager &MemMgr,
- RuntimeDyldChecker &Checker) {
+static void remapSectionsAndSymbols(const llvm::Triple &TargetTriple,
+ TrivialMemoryManager &MemMgr,
+ RuntimeDyldChecker &Checker) {
// Set up a work list (section addr/size pairs).
typedef std::list<std::pair<void*, uint64_t>> WorklistT;
@@ -515,6 +540,27 @@ static void remapSections(const llvm::Triple &TargetTriple,
Checker.getRTDyld().mapSectionAddress(CurEntry.first, NextSectionAddr);
}
+ // Add dummy symbols to the memory manager.
+ for (const auto &Mapping : DummySymbolMappings) {
+ size_t EqualsIdx = Mapping.find_first_of("=");
+
+ if (EqualsIdx == StringRef::npos) {
+ errs() << "Invalid dummy symbol specification '" << Mapping
+ << "'. Should be '<symbol name>=<addr>'\n";
+ exit(1);
+ }
+
+ std::string Symbol = Mapping.substr(0, EqualsIdx);
+ std::string AddrStr = Mapping.substr(EqualsIdx + 1);
+
+ uint64_t Addr;
+ if (StringRef(AddrStr).getAsInteger(0, Addr)) {
+ errs() << "Invalid symbol mapping '" << Mapping << "'.\n";
+ exit(1);
+ }
+
+ MemMgr.addDummySymbol(Symbol, Addr);
+ }
}
// Load and link the objects specified on the command line, but do not execute
@@ -603,8 +649,9 @@ static int linkAndVerify() {
}
}
- // Re-map the section addresses into the phony target address space.
- remapSections(TheTriple, MemMgr, Checker);
+ // Re-map the section addresses into the phony target address space and add
+ // dummy symbols.
+ remapSectionsAndSymbols(TheTriple, MemMgr, Checker);
// Resolve all the relocations we can.
Dyld.resolveRelocations();
diff --git a/tools/llvm-shlib/CMakeLists.txt b/tools/llvm-shlib/CMakeLists.txt
index bc1b658ba7264..54d71d3f63200 100644
--- a/tools/llvm-shlib/CMakeLists.txt
+++ b/tools/llvm-shlib/CMakeLists.txt
@@ -15,6 +15,8 @@ if(NOT DEFINED LLVM_DYLIB_COMPONENTS)
BitWriter
CodeGen
Core
+ DebugInfoDWARF
+ DebugInfoPDB
ExecutionEngine
IPA
IPO
diff --git a/tools/llvm-stress/llvm-stress.cpp b/tools/llvm-stress/llvm-stress.cpp
index 727d03f9d6ea4..6a1a248a05725 100644
--- a/tools/llvm-stress/llvm-stress.cpp
+++ b/tools/llvm-stress/llvm-stress.cpp
@@ -31,7 +31,8 @@
#include <set>
#include <sstream>
#include <vector>
-using namespace llvm;
+
+namespace llvm {
static cl::opt<unsigned> SeedCL("seed",
cl::desc("Seed used for randomness"), cl::init(0));
@@ -42,16 +43,39 @@ static cl::opt<std::string>
OutputFilename("o", cl::desc("Override output filename"),
cl::value_desc("filename"));
-static cl::opt<bool> GenHalfFloat("generate-half-float",
- cl::desc("Generate half-length floating-point values"), cl::init(false));
-static cl::opt<bool> GenX86FP80("generate-x86-fp80",
- cl::desc("Generate 80-bit X86 floating-point values"), cl::init(false));
-static cl::opt<bool> GenFP128("generate-fp128",
- cl::desc("Generate 128-bit floating-point values"), cl::init(false));
-static cl::opt<bool> GenPPCFP128("generate-ppc-fp128",
- cl::desc("Generate 128-bit PPC floating-point values"), cl::init(false));
-static cl::opt<bool> GenX86MMX("generate-x86-mmx",
- cl::desc("Generate X86 MMX floating-point values"), cl::init(false));
+namespace cl {
+template <> class parser<Type*> final : public basic_parser<Type*> {
+public:
+ parser(Option &O) : basic_parser(O) {}
+
+ // Parse options as IR types. Return true on error.
+ bool parse(Option &O, StringRef, StringRef Arg, Type *&Value) {
+ auto &Context = getGlobalContext();
+ if (Arg == "half") Value = Type::getHalfTy(Context);
+ else if (Arg == "fp128") Value = Type::getFP128Ty(Context);
+ else if (Arg == "x86_fp80") Value = Type::getX86_FP80Ty(Context);
+ else if (Arg == "ppc_fp128") Value = Type::getPPC_FP128Ty(Context);
+ else if (Arg == "x86_mmx") Value = Type::getX86_MMXTy(Context);
+ else if (Arg.startswith("i")) {
+ unsigned N = 0;
+ Arg.drop_front().getAsInteger(10, N);
+ if (N > 0)
+ Value = Type::getIntNTy(Context, N);
+ }
+
+ if (!Value)
+ return O.error("Invalid IR scalar type: '" + Arg + "'!");
+ return false;
+ }
+
+ const char *getValueName() const override { return "IR scalar type"; }
+};
+}
+
+
+static cl::list<Type*> AdditionalScalarTypes("types", cl::CommaSeparated,
+ cl::desc("Additional IR scalar types "
+ "(always includes i1, i8, i16, i32, i64, float and double)"));
namespace {
/// A utility class to provide a pseudo-random number generator which is
@@ -243,35 +267,22 @@ protected:
/// Pick a random scalar type.
Type *pickScalarType() {
- Type *t = nullptr;
- do {
- switch (Ran->Rand() % 30) {
- case 0: t = Type::getInt1Ty(Context); break;
- case 1: t = Type::getInt8Ty(Context); break;
- case 2: t = Type::getInt16Ty(Context); break;
- case 3: case 4:
- case 5: t = Type::getFloatTy(Context); break;
- case 6: case 7:
- case 8: t = Type::getDoubleTy(Context); break;
- case 9: case 10:
- case 11: t = Type::getInt32Ty(Context); break;
- case 12: case 13:
- case 14: t = Type::getInt64Ty(Context); break;
- case 15: case 16:
- case 17: if (GenHalfFloat) t = Type::getHalfTy(Context); break;
- case 18: case 19:
- case 20: if (GenX86FP80) t = Type::getX86_FP80Ty(Context); break;
- case 21: case 22:
- case 23: if (GenFP128) t = Type::getFP128Ty(Context); break;
- case 24: case 25:
- case 26: if (GenPPCFP128) t = Type::getPPC_FP128Ty(Context); break;
- case 27: case 28:
- case 29: if (GenX86MMX) t = Type::getX86_MMXTy(Context); break;
- default: llvm_unreachable("Invalid scalar value");
- }
- } while (t == nullptr);
+ static std::vector<Type*> ScalarTypes;
+ if (ScalarTypes.empty()) {
+ ScalarTypes.assign({
+ Type::getInt1Ty(Context),
+ Type::getInt8Ty(Context),
+ Type::getInt16Ty(Context),
+ Type::getInt32Ty(Context),
+ Type::getInt64Ty(Context),
+ Type::getFloatTy(Context),
+ Type::getDoubleTy(Context)
+ });
+ ScalarTypes.insert(ScalarTypes.end(),
+ AdditionalScalarTypes.begin(), AdditionalScalarTypes.end());
+ }
- return t;
+ return ScalarTypes[Ran->Rand() % ScalarTypes.size()];
}
/// Basic block to populate
@@ -665,9 +676,13 @@ static void IntroduceControlFlow(Function *F, Random &R) {
}
}
+}
+
int main(int argc, char **argv) {
+ using namespace llvm;
+
// Init LLVM, call llvm_shutdown() on exit, parse args, etc.
- llvm::PrettyStackTraceProgram X(argc, argv);
+ PrettyStackTraceProgram X(argc, argv);
cl::ParseCommandLineOptions(argc, argv, "llvm codegen stress-tester\n");
llvm_shutdown_obj Y;
diff --git a/tools/llvm-symbolizer/LLVMSymbolize.cpp b/tools/llvm-symbolizer/LLVMSymbolize.cpp
index ec3fe4868db33..c57c219b11d23 100644
--- a/tools/llvm-symbolizer/LLVMSymbolize.cpp
+++ b/tools/llvm-symbolizer/LLVMSymbolize.cpp
@@ -84,10 +84,10 @@ void ModuleInfo::addSymbol(const SymbolRef &Symbol, uint64_t SymbolSize,
SymbolRef::Type SymbolType = Symbol.getType();
if (SymbolType != SymbolRef::ST_Function && SymbolType != SymbolRef::ST_Data)
return;
- uint64_t SymbolAddress;
- if (error(Symbol.getAddress(SymbolAddress)) ||
- SymbolAddress == UnknownAddress)
+ ErrorOr<uint64_t> SymbolAddressOrErr = Symbol.getAddress();
+ if (error(SymbolAddressOrErr.getError()))
return;
+ uint64_t SymbolAddress = *SymbolAddressOrErr;
if (OpdExtractor) {
// For big-endian PowerPC64 ELF, symbols in the .opd section refer to
// function descriptors. The first word of the descriptor is a pointer to
diff --git a/tools/obj2yaml/elf2yaml.cpp b/tools/obj2yaml/elf2yaml.cpp
index 9afcedef63982..f117a10d38222 100644
--- a/tools/obj2yaml/elf2yaml.cpp
+++ b/tools/obj2yaml/elf2yaml.cpp
@@ -40,6 +40,7 @@ class ELFDumper {
ErrorOr<ELFYAML::RelocationSection *> dumpRelaSection(const Elf_Shdr *Shdr);
ErrorOr<ELFYAML::RawContentSection *>
dumpContentSection(const Elf_Shdr *Shdr);
+ ErrorOr<ELFYAML::NoBitsSection *> dumpNoBitsSection(const Elf_Shdr *Shdr);
ErrorOr<ELFYAML::Group *> dumpGroup(const Elf_Shdr *Shdr);
ErrorOr<ELFYAML::MipsABIFlags *> dumpMipsABIFlags(const Elf_Shdr *Shdr);
@@ -104,6 +105,13 @@ ErrorOr<ELFYAML::Object *> ELFDumper<ELFT>::dump() {
Y->Sections.push_back(std::unique_ptr<ELFYAML::Section>(G.get()));
break;
}
+ case ELF::SHT_NOBITS: {
+ ErrorOr<ELFYAML::NoBitsSection *> S = dumpNoBitsSection(&Sec);
+ if (std::error_code EC = S.getError())
+ return EC;
+ Y->Sections.push_back(std::unique_ptr<ELFYAML::Section>(S.get()));
+ break;
+ }
default: {
ErrorOr<ELFYAML::RawContentSection *> S = dumpContentSection(&Sec);
if (std::error_code EC = S.getError())
@@ -305,6 +313,18 @@ ELFDumper<ELFT>::dumpContentSection(const Elf_Shdr *Shdr) {
}
template <class ELFT>
+ErrorOr<ELFYAML::NoBitsSection *>
+ELFDumper<ELFT>::dumpNoBitsSection(const Elf_Shdr *Shdr) {
+ auto S = make_unique<ELFYAML::NoBitsSection>();
+
+ if (std::error_code EC = dumpCommonSection(Shdr, *S))
+ return EC;
+ S->Size = Shdr->sh_size;
+
+ return S.release();
+}
+
+template <class ELFT>
ErrorOr<ELFYAML::Group *> ELFDumper<ELFT>::dumpGroup(const Elf_Shdr *Shdr) {
auto S = make_unique<ELFYAML::Group>();
diff --git a/tools/opt/opt.cpp b/tools/opt/opt.cpp
index 55426e7b27435..0db60d1444099 100644
--- a/tools/opt/opt.cpp
+++ b/tools/opt/opt.cpp
@@ -324,6 +324,7 @@ int main(int argc, char **argv) {
initializeRewriteSymbolsPass(Registry);
initializeWinEHPreparePass(Registry);
initializeDwarfEHPreparePass(Registry);
+ initializeSjLjEHPreparePass(Registry);
#ifdef LINK_POLLY_INTO_TOOLS
polly::initializePollyPasses(Registry);
diff --git a/tools/yaml2obj/yaml2elf.cpp b/tools/yaml2obj/yaml2elf.cpp
index 772b5b918ecab..a247f48c053dc 100644
--- a/tools/yaml2obj/yaml2elf.cpp
+++ b/tools/yaml2obj/yaml2elf.cpp
@@ -35,6 +35,8 @@ class ContiguousBlobAccumulator {
/// \returns The new offset.
uint64_t padToAlignment(unsigned Align) {
+ if (Align == 0)
+ Align = 1;
uint64_t CurrentOffset = InitialOffset + OS.tell();
uint64_t AlignedOffset = RoundUpToAlignment(CurrentOffset, Align);
for (; CurrentOffset != AlignedOffset; ++CurrentOffset)
@@ -46,7 +48,7 @@ public:
ContiguousBlobAccumulator(uint64_t InitialOffset_)
: InitialOffset(InitialOffset_), Buf(), OS(Buf) {}
template <class Integer>
- raw_ostream &getOSAndAlignedOffset(Integer &Offset, unsigned Align = 16) {
+ raw_ostream &getOSAndAlignedOffset(Integer &Offset, unsigned Align) {
Offset = padToAlignment(Align);
return OS;
}
@@ -241,6 +243,12 @@ bool ELFState<ELFT>::initSectionHeaders(std::vector<Elf_Shdr> &SHeaders,
} else if (auto S = dyn_cast<ELFYAML::MipsABIFlags>(Sec.get())) {
if (!writeSectionContent(SHeader, *S, CBA))
return false;
+ } else if (auto S = dyn_cast<ELFYAML::NoBitsSection>(Sec.get())) {
+ SHeader.sh_entsize = 0;
+ SHeader.sh_size = S->Size;
+ // SHT_NOBITS section does not have content
+ // so just to setup the section offset.
+ CBA.getOSAndAlignedOffset(SHeader.sh_offset, SHeader.sh_addralign);
} else
llvm_unreachable("Unknown section type");
@@ -259,6 +267,7 @@ void ELFState<ELFT>::initSymtabSectionHeader(Elf_Shdr &SHeader,
// One greater than symbol table index of the last local symbol.
SHeader.sh_info = Doc.Symbols.Local.size() + 1;
SHeader.sh_entsize = sizeof(Elf_Sym);
+ SHeader.sh_addralign = 8;
std::vector<Elf_Sym> Syms;
{
@@ -281,8 +290,9 @@ void ELFState<ELFT>::initSymtabSectionHeader(Elf_Shdr &SHeader,
addSymbols(Doc.Symbols.Global, Syms, ELF::STB_GLOBAL);
addSymbols(Doc.Symbols.Weak, Syms, ELF::STB_WEAK);
- writeArrayData(CBA.getOSAndAlignedOffset(SHeader.sh_offset),
- makeArrayRef(Syms));
+ writeArrayData(
+ CBA.getOSAndAlignedOffset(SHeader.sh_offset, SHeader.sh_addralign),
+ makeArrayRef(Syms));
SHeader.sh_size = arrayDataSize(makeArrayRef(Syms));
}
@@ -293,7 +303,8 @@ void ELFState<ELFT>::initStrtabSectionHeader(Elf_Shdr &SHeader, StringRef Name,
zero(SHeader);
SHeader.sh_name = DotShStrtab.getOffset(Name);
SHeader.sh_type = ELF::SHT_STRTAB;
- CBA.getOSAndAlignedOffset(SHeader.sh_offset) << STB.data();
+ CBA.getOSAndAlignedOffset(SHeader.sh_offset, SHeader.sh_addralign)
+ << STB.data();
SHeader.sh_size = STB.data().size();
SHeader.sh_addralign = 1;
}
@@ -331,7 +342,8 @@ ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader,
ContiguousBlobAccumulator &CBA) {
assert(Section.Size >= Section.Content.binary_size() &&
"Section size and section content are inconsistent");
- raw_ostream &OS = CBA.getOSAndAlignedOffset(SHeader.sh_offset);
+ raw_ostream &OS =
+ CBA.getOSAndAlignedOffset(SHeader.sh_offset, SHeader.sh_addralign);
Section.Content.writeAsBinary(OS);
for (auto i = Section.Content.binary_size(); i < Section.Size; ++i)
OS.write(0);
@@ -358,7 +370,7 @@ ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader,
SHeader.sh_entsize = IsRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel);
SHeader.sh_size = SHeader.sh_entsize * Section.Relocations.size();
- auto &OS = CBA.getOSAndAlignedOffset(SHeader.sh_offset);
+ auto &OS = CBA.getOSAndAlignedOffset(SHeader.sh_offset, SHeader.sh_addralign);
for (const auto &Rel : Section.Relocations) {
unsigned SymIdx = 0;
@@ -396,7 +408,7 @@ bool ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader,
SHeader.sh_entsize = sizeof(Elf_Word);
SHeader.sh_size = SHeader.sh_entsize * Section.Members.size();
- auto &OS = CBA.getOSAndAlignedOffset(SHeader.sh_offset);
+ auto &OS = CBA.getOSAndAlignedOffset(SHeader.sh_offset, SHeader.sh_addralign);
for (auto member : Section.Members) {
Elf_Word SIdx;
@@ -427,7 +439,7 @@ bool ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader,
SHeader.sh_entsize = sizeof(Flags);
SHeader.sh_size = SHeader.sh_entsize;
- auto &OS = CBA.getOSAndAlignedOffset(SHeader.sh_offset);
+ auto &OS = CBA.getOSAndAlignedOffset(SHeader.sh_offset, SHeader.sh_addralign);
Flags.version = Section.Version;
Flags.isa_level = Section.ISALevel;
Flags.isa_rev = Section.ISARevision;