summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/tools
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/tools')
-rw-r--r--contrib/llvm/tools/bugpoint/BugDriver.cpp26
-rw-r--r--contrib/llvm/tools/bugpoint/CrashDebugger.cpp91
-rw-r--r--contrib/llvm/tools/bugpoint/ExtractFunction.cpp6
-rw-r--r--contrib/llvm/tools/bugpoint/Miscompilation.cpp17
-rw-r--r--contrib/llvm/tools/bugpoint/OptimizerDriver.cpp11
-rw-r--r--contrib/llvm/tools/bugpoint/ToolRunner.h2
-rw-r--r--contrib/llvm/tools/bugpoint/bugpoint.cpp8
-rw-r--r--contrib/llvm/tools/llc/llc.cpp68
-rw-r--r--contrib/llvm/tools/lli/OrcLazyJIT.cpp148
-rw-r--r--contrib/llvm/tools/lli/OrcLazyJIT.h164
-rw-r--r--contrib/llvm/tools/lli/RemoteMemoryManager.cpp1
-rw-r--r--contrib/llvm/tools/lli/RemoteMemoryManager.h2
-rw-r--r--contrib/llvm/tools/lli/RemoteTargetExternal.h2
-rw-r--r--contrib/llvm/tools/lli/lli.cpp56
-rw-r--r--contrib/llvm/tools/llvm-ar/llvm-ar.cpp2
-rw-r--r--contrib/llvm/tools/llvm-as/llvm-as.cpp17
-rw-r--r--contrib/llvm/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp39
-rw-r--r--contrib/llvm/tools/llvm-cov/CodeCoverage.cpp73
-rw-r--r--contrib/llvm/tools/llvm-cov/CoverageReport.cpp40
-rw-r--r--contrib/llvm/tools/llvm-cov/CoverageReport.h11
-rw-r--r--contrib/llvm/tools/llvm-cov/CoverageSummary.cpp64
-rw-r--r--contrib/llvm/tools/llvm-cov/CoverageSummary.h45
-rw-r--r--contrib/llvm/tools/llvm-cov/CoverageSummaryInfo.cpp25
-rw-r--r--contrib/llvm/tools/llvm-cov/CoverageSummaryInfo.h53
-rw-r--r--contrib/llvm/tools/llvm-cov/RenderingSupport.h2
-rw-r--r--contrib/llvm/tools/llvm-cov/SourceCoverageView.cpp46
-rw-r--r--contrib/llvm/tools/llvm-cov/SourceCoverageView.h7
-rw-r--r--contrib/llvm/tools/llvm-cov/gcov.cpp9
-rw-r--r--contrib/llvm/tools/llvm-cov/llvm-cov.cpp34
-rw-r--r--contrib/llvm/tools/llvm-cxxdump/Error.cpp43
-rw-r--r--contrib/llvm/tools/llvm-cxxdump/Error.h39
-rw-r--r--contrib/llvm/tools/llvm-cxxdump/llvm-cxxdump.cpp569
-rw-r--r--contrib/llvm/tools/llvm-cxxdump/llvm-cxxdump.h23
-rw-r--r--contrib/llvm/tools/llvm-dis/llvm-dis.cpp54
-rw-r--r--contrib/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp113
-rw-r--r--contrib/llvm/tools/llvm-extract/llvm-extract.cpp20
-rw-r--r--contrib/llvm/tools/llvm-link/llvm-link.cpp70
-rw-r--r--contrib/llvm/tools/llvm-lto/llvm-lto.cpp292
-rw-r--r--contrib/llvm/tools/llvm-mc/llvm-mc.cpp32
-rw-r--r--contrib/llvm/tools/llvm-nm/llvm-nm.cpp132
-rw-r--r--contrib/llvm/tools/llvm-objdump/MachODump.cpp4542
-rw-r--r--contrib/llvm/tools/llvm-objdump/llvm-objdump.cpp97
-rw-r--r--contrib/llvm/tools/llvm-objdump/llvm-objdump.h24
-rw-r--r--contrib/llvm/tools/llvm-pdbdump/BuiltinDumper.cpp87
-rw-r--r--contrib/llvm/tools/llvm-pdbdump/BuiltinDumper.h30
-rw-r--r--contrib/llvm/tools/llvm-pdbdump/ClassDefinitionDumper.cpp190
-rw-r--r--contrib/llvm/tools/llvm-pdbdump/ClassDefinitionDumper.h62
-rw-r--r--contrib/llvm/tools/llvm-pdbdump/CompilandDumper.cpp140
-rw-r--r--contrib/llvm/tools/llvm-pdbdump/CompilandDumper.h39
-rw-r--r--contrib/llvm/tools/llvm-pdbdump/EnumDumper.cpp52
-rw-r--r--contrib/llvm/tools/llvm-pdbdump/EnumDumper.h30
-rw-r--r--contrib/llvm/tools/llvm-pdbdump/ExternalSymbolDumper.cpp40
-rw-r--r--contrib/llvm/tools/llvm-pdbdump/ExternalSymbolDumper.h32
-rw-r--r--contrib/llvm/tools/llvm-pdbdump/FunctionDumper.cpp254
-rw-r--r--contrib/llvm/tools/llvm-pdbdump/FunctionDumper.h42
-rw-r--r--contrib/llvm/tools/llvm-pdbdump/LinePrinter.cpp124
-rw-r--r--contrib/llvm/tools/llvm-pdbdump/LinePrinter.h89
-rw-r--r--contrib/llvm/tools/llvm-pdbdump/TypeDumper.cpp97
-rw-r--r--contrib/llvm/tools/llvm-pdbdump/TypeDumper.h34
-rw-r--r--contrib/llvm/tools/llvm-pdbdump/TypedefDumper.cpp79
-rw-r--r--contrib/llvm/tools/llvm-pdbdump/TypedefDumper.h37
-rw-r--r--contrib/llvm/tools/llvm-pdbdump/VariableDumper.cpp170
-rw-r--r--contrib/llvm/tools/llvm-pdbdump/VariableDumper.h41
-rw-r--r--contrib/llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp284
-rw-r--r--contrib/llvm/tools/llvm-pdbdump/llvm-pdbdump.h32
-rw-r--r--contrib/llvm/tools/llvm-profdata/llvm-profdata.cpp25
-rw-r--r--contrib/llvm/tools/llvm-readobj/COFFDumper.cpp34
-rw-r--r--contrib/llvm/tools/llvm-readobj/ELFDumper.cpp190
-rw-r--r--contrib/llvm/tools/llvm-readobj/MachODumper.cpp25
-rw-r--r--contrib/llvm/tools/llvm-readobj/ObjDumper.h1
-rw-r--r--contrib/llvm/tools/llvm-readobj/StreamWriter.h14
-rw-r--r--contrib/llvm/tools/llvm-readobj/llvm-readobj.cpp36
-rw-r--r--contrib/llvm/tools/llvm-readobj/llvm-readobj.h3
-rw-r--r--contrib/llvm/tools/llvm-rtdyld/llvm-rtdyld.cpp90
-rw-r--r--contrib/llvm/tools/llvm-stress/llvm-stress.cpp5
-rw-r--r--contrib/llvm/tools/llvm-symbolizer/LLVMSymbolize.cpp36
-rw-r--r--contrib/llvm/tools/llvm-symbolizer/LLVMSymbolize.h15
-rw-r--r--contrib/llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp19
-rw-r--r--contrib/llvm/tools/opt/BreakpointPrinter.cpp28
-rw-r--r--contrib/llvm/tools/opt/NewPMDriver.cpp27
-rw-r--r--contrib/llvm/tools/opt/NewPMDriver.h8
-rw-r--r--contrib/llvm/tools/opt/PassRegistry.def65
-rw-r--r--contrib/llvm/tools/opt/Passes.cpp397
-rw-r--r--contrib/llvm/tools/opt/Passes.h78
-rw-r--r--contrib/llvm/tools/opt/opt.cpp139
85 files changed, 8778 insertions, 1561 deletions
diff --git a/contrib/llvm/tools/bugpoint/BugDriver.cpp b/contrib/llvm/tools/bugpoint/BugDriver.cpp
index b8be17e..43f4c29 100644
--- a/contrib/llvm/tools/bugpoint/BugDriver.cpp
+++ b/contrib/llvm/tools/bugpoint/BugDriver.cpp
@@ -16,6 +16,7 @@
#include "BugDriver.h"
#include "ToolRunner.h"
#include "llvm/IR/Module.h"
+#include "llvm/IR/Verifier.h"
#include "llvm/IRReader/IRReader.h"
#include "llvm/Linker/Linker.h"
#include "llvm/Pass.h"
@@ -86,23 +87,28 @@ std::unique_ptr<Module> llvm::parseInputFile(StringRef Filename,
LLVMContext &Ctxt) {
SMDiagnostic Err;
std::unique_ptr<Module> Result = parseIRFile(Filename, Err, Ctxt);
- if (!Result)
+ if (!Result) {
Err.print("bugpoint", errs());
+ return Result;
+ }
+
+ if (verifyModule(*Result, &errs())) {
+ errs() << "bugpoint: " << Filename << ": error: input module is broken!\n";
+ return std::unique_ptr<Module>();
+ }
// If we don't have an override triple, use the first one to configure
// bugpoint, or use the host triple if none provided.
- if (Result) {
- if (TargetTriple.getTriple().empty()) {
- Triple TheTriple(Result->getTargetTriple());
+ if (TargetTriple.getTriple().empty()) {
+ Triple TheTriple(Result->getTargetTriple());
- if (TheTriple.getTriple().empty())
- TheTriple.setTriple(sys::getDefaultTargetTriple());
+ if (TheTriple.getTriple().empty())
+ TheTriple.setTriple(sys::getDefaultTargetTriple());
- TargetTriple.setTriple(TheTriple.getTriple());
- }
-
- Result->setTargetTriple(TargetTriple.getTriple()); // override the triple
+ TargetTriple.setTriple(TheTriple.getTriple());
}
+
+ Result->setTargetTriple(TargetTriple.getTriple()); // override the triple
return Result;
}
diff --git a/contrib/llvm/tools/bugpoint/CrashDebugger.cpp b/contrib/llvm/tools/bugpoint/CrashDebugger.cpp
index bac948a..6f41d30 100644
--- a/contrib/llvm/tools/bugpoint/CrashDebugger.cpp
+++ b/contrib/llvm/tools/bugpoint/CrashDebugger.cpp
@@ -19,11 +19,11 @@
#include "llvm/IR/Constants.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Instructions.h"
+#include "llvm/IR/LegacyPassManager.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/ValueSymbolTable.h"
#include "llvm/IR/Verifier.h"
#include "llvm/Pass.h"
-#include "llvm/PassManager.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/FileUtilities.h"
#include "llvm/Transforms/Scalar.h"
@@ -40,6 +40,15 @@ namespace {
NoGlobalRM ("disable-global-remove",
cl::desc("Do not remove global variables"),
cl::init(false));
+
+ cl::opt<bool>
+ ReplaceFuncsWithNull("replace-funcs-with-null",
+ cl::desc("When stubbing functions, replace all uses will null"),
+ cl::init(false));
+ cl::opt<bool>
+ DontReducePassList("disable-pass-list-reduction",
+ cl::desc("Skip pass list reduction steps"),
+ cl::init(false));
}
namespace llvm {
@@ -194,6 +203,29 @@ namespace {
};
}
+static void RemoveFunctionReferences(Module *M, const char* Name) {
+ auto *UsedVar = M->getGlobalVariable(Name, true);
+ if (!UsedVar || !UsedVar->hasInitializer()) return;
+ if (isa<ConstantAggregateZero>(UsedVar->getInitializer())) {
+ assert(UsedVar->use_empty());
+ UsedVar->eraseFromParent();
+ return;
+ }
+ auto *OldUsedVal = cast<ConstantArray>(UsedVar->getInitializer());
+ std::vector<Constant*> Used;
+ for(Value *V : OldUsedVal->operand_values()) {
+ Constant *Op = cast<Constant>(V->stripPointerCasts());
+ if(!Op->isNullValue()) {
+ Used.push_back(cast<Constant>(V));
+ }
+ }
+ auto *NewValElemTy = OldUsedVal->getType()->getElementType();
+ auto *NewValTy = ArrayType::get(NewValElemTy, Used.size());
+ auto *NewUsedVal = ConstantArray::get(NewValTy, Used);
+ UsedVar->mutateType(NewUsedVal->getType()->getPointerTo());
+ UsedVar->setInitializer(NewUsedVal);
+}
+
bool ReduceCrashingFunctions::TestFuncs(std::vector<Function*> &Funcs) {
// If main isn't present, claim there is no problem.
if (KeepMain && std::find(Funcs.begin(), Funcs.end(),
@@ -218,13 +250,53 @@ bool ReduceCrashingFunctions::TestFuncs(std::vector<Function*> &Funcs) {
outs() << "Checking for crash with only these functions: ";
PrintFunctionList(Funcs);
outs() << ": ";
+ if (!ReplaceFuncsWithNull) {
+ // Loop over and delete any functions which we aren't supposed to be playing
+ // with...
+ for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I)
+ if (!I->isDeclaration() && !Functions.count(I))
+ DeleteFunctionBody(I);
+ } else {
+ std::vector<GlobalValue*> ToRemove;
+ // First, remove aliases to functions we're about to purge.
+ for (GlobalAlias &Alias : M->aliases()) {
+ Constant *Root = Alias.getAliasee()->stripPointerCasts();
+ Function *F = dyn_cast<Function>(Root);
+ if (F) {
+ if (Functions.count(F))
+ // We're keeping this function.
+ continue;
+ } else if (Root->isNullValue()) {
+ // This referenced a globalalias that we've already replaced,
+ // so we still need to replace this alias.
+ } else if (!F) {
+ // Not a function, therefore not something we mess with.
+ continue;
+ }
- // Loop over and delete any functions which we aren't supposed to be playing
- // with...
- for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I)
- if (!I->isDeclaration() && !Functions.count(I))
- DeleteFunctionBody(I);
+ PointerType *Ty = cast<PointerType>(Alias.getType());
+ Constant *Replacement = ConstantPointerNull::get(Ty);
+ Alias.replaceAllUsesWith(Replacement);
+ ToRemove.push_back(&Alias);
+ }
+
+ for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I) {
+ if (!I->isDeclaration() && !Functions.count(I)) {
+ PointerType *Ty = cast<PointerType>(I->getType());
+ Constant *Replacement = ConstantPointerNull::get(Ty);
+ I->replaceAllUsesWith(Replacement);
+ ToRemove.push_back(I);
+ }
+ }
+ for (auto *F : ToRemove) {
+ F->eraseFromParent();
+ }
+
+ // Finally, remove any null members from any global intrinsic.
+ RemoveFunctionReferences(M, "llvm.used");
+ RemoveFunctionReferences(M, "llvm.compiler.used");
+ }
// Try running the hacked up program...
if (TestFn(BD, M)) {
BD.setNewProgram(M); // It crashed, keep the trimmed version...
@@ -296,7 +368,7 @@ bool ReduceCrashingBlocks::TestBlocks(std::vector<const BasicBlock*> &BBs) {
(*SI)->removePredecessor(BB);
TerminatorInst *BBTerm = BB->getTerminator();
-
+
if (!BB->getTerminator()->getType()->isVoidTy())
BBTerm->replaceAllUsesWith(Constant::getNullValue(BBTerm->getType()));
@@ -407,9 +479,8 @@ bool ReduceCrashingInstructions::TestInsts(std::vector<const Instruction*>
}
// Verify that this is still valid.
- PassManager Passes;
+ legacy::PassManager Passes;
Passes.add(createVerifierPass());
- Passes.add(createDebugInfoVerifierPass());
Passes.run(*M);
// Try running on the hacked up program...
@@ -630,7 +701,7 @@ bool BugDriver::debugOptimizerCrash(const std::string &ID) {
std::string Error;
// Reduce the list of passes which causes the optimizer to crash...
- if (!BugpointIsInterrupted)
+ if (!BugpointIsInterrupted && !DontReducePassList)
ReducePassList(*this).reduceList(PassesToRun, Error);
assert(Error.empty());
diff --git a/contrib/llvm/tools/bugpoint/ExtractFunction.cpp b/contrib/llvm/tools/bugpoint/ExtractFunction.cpp
index 34fe53c..238cbbc 100644
--- a/contrib/llvm/tools/bugpoint/ExtractFunction.cpp
+++ b/contrib/llvm/tools/bugpoint/ExtractFunction.cpp
@@ -17,10 +17,10 @@
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/LegacyPassManager.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Verifier.h"
#include "llvm/Pass.h"
-#include "llvm/PassManager.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/FileUtilities.h"
@@ -195,9 +195,9 @@ static Constant *GetTorInit(std::vector<std::pair<Function*, int> > &TorList) {
assert(!TorList.empty() && "Don't create empty tor list!");
std::vector<Constant*> ArrayElts;
Type *Int32Ty = Type::getInt32Ty(TorList[0].first->getContext());
-
+
StructType *STy =
- StructType::get(Int32Ty, TorList[0].first->getType(), NULL);
+ StructType::get(Int32Ty, TorList[0].first->getType(), nullptr);
for (unsigned i = 0, e = TorList.size(); i != e; ++i) {
Constant *Elts[] = {
ConstantInt::get(Int32Ty, TorList[i].second),
diff --git a/contrib/llvm/tools/bugpoint/Miscompilation.cpp b/contrib/llvm/tools/bugpoint/Miscompilation.cpp
index 8cb4583..53631d2 100644
--- a/contrib/llvm/tools/bugpoint/Miscompilation.cpp
+++ b/contrib/llvm/tools/bugpoint/Miscompilation.cpp
@@ -852,7 +852,8 @@ static void CleanupAndPrepareModules(BugDriver &BD, Module *&Test,
// GetElementPtr *funcName, ulong 0, ulong 0
std::vector<Constant*> GEPargs(2,
Constant::getNullValue(Type::getInt32Ty(F->getContext())));
- Value *GEP = ConstantExpr::getGetElementPtr(funcName, GEPargs);
+ Value *GEP = ConstantExpr::getGetElementPtr(InitArray->getType(),
+ funcName, GEPargs);
std::vector<Value*> ResolverArgs;
ResolverArgs.push_back(GEP);
@@ -975,7 +976,7 @@ static bool TestCodeGenerator(BugDriver &BD, Module *Test, Module *Safe,
}
if (BD.writeProgramToFile(SafeModuleBC.str(), SafeModuleFD, Safe)) {
- errs() << "Error writing bitcode to `" << SafeModuleBC.str()
+ errs() << "Error writing bitcode to `" << SafeModuleBC
<< "'\nExiting.";
exit(1);
}
@@ -1050,7 +1051,7 @@ bool BugDriver::debugCodeGenerator(std::string *Error) {
}
if (writeProgramToFile(TestModuleBC.str(), TestModuleFD, ToCodeGen)) {
- errs() << "Error writing bitcode to `" << TestModuleBC.str()
+ errs() << "Error writing bitcode to `" << TestModuleBC
<< "'\nExiting.";
exit(1);
}
@@ -1068,7 +1069,7 @@ bool BugDriver::debugCodeGenerator(std::string *Error) {
}
if (writeProgramToFile(SafeModuleBC.str(), SafeModuleFD, ToNotCodeGen)) {
- errs() << "Error writing bitcode to `" << SafeModuleBC.str()
+ errs() << "Error writing bitcode to `" << SafeModuleBC
<< "'\nExiting.";
exit(1);
}
@@ -1079,17 +1080,17 @@ bool BugDriver::debugCodeGenerator(std::string *Error) {
outs() << "You can reproduce the problem with the command line: \n";
if (isExecutingJIT()) {
- outs() << " lli -load " << SharedObject << " " << TestModuleBC.str();
+ outs() << " lli -load " << SharedObject << " " << TestModuleBC;
} else {
- outs() << " llc " << TestModuleBC.str() << " -o " << TestModuleBC.str()
+ outs() << " llc " << TestModuleBC << " -o " << TestModuleBC
<< ".s\n";
outs() << " gcc " << SharedObject << " " << TestModuleBC.str()
- << ".s -o " << TestModuleBC.str() << ".exe";
+ << ".s -o " << TestModuleBC << ".exe";
#if defined (HAVE_LINK_R)
outs() << " -Wl,-R.";
#endif
outs() << "\n";
- outs() << " " << TestModuleBC.str() << ".exe";
+ outs() << " " << TestModuleBC << ".exe";
}
for (unsigned i = 0, e = InputArgv.size(); i != e; ++i)
outs() << " " << InputArgv[i];
diff --git a/contrib/llvm/tools/bugpoint/OptimizerDriver.cpp b/contrib/llvm/tools/bugpoint/OptimizerDriver.cpp
index f197cc5..344e7b5 100644
--- a/contrib/llvm/tools/bugpoint/OptimizerDriver.cpp
+++ b/contrib/llvm/tools/bugpoint/OptimizerDriver.cpp
@@ -18,9 +18,9 @@
#include "BugDriver.h"
#include "llvm/Bitcode/ReaderWriter.h"
#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/LegacyPassManager.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Verifier.h"
-#include "llvm/PassManager.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/FileUtilities.h"
@@ -42,6 +42,11 @@ namespace llvm {
extern cl::opt<std::string> OutputPrefix;
}
+static cl::opt<bool> PreserveBitcodeUseListOrder(
+ "preserve-bc-uselistorder",
+ cl::desc("Preserve use-list order when writing LLVM bitcode."),
+ cl::init(true), cl::Hidden);
+
namespace {
// ChildOutput - This option captures the name of the child output file that
// is set up by the parent bugpoint process
@@ -55,7 +60,7 @@ namespace {
/// file. If an error occurs, true is returned.
///
static bool writeProgramToFileAux(tool_output_file &Out, const Module *M) {
- WriteBitcodeToFile(M, Out.os());
+ WriteBitcodeToFile(M, Out.os(), PreserveBitcodeUseListOrder);
Out.os().close();
if (!Out.os().has_error()) {
Out.keep();
@@ -151,7 +156,7 @@ bool BugDriver::runPasses(Module *Program,
tool_output_file InFile(InputFilename, InputFD);
- WriteBitcodeToFile(Program, InFile.os());
+ WriteBitcodeToFile(Program, InFile.os(), PreserveBitcodeUseListOrder);
InFile.os().close();
if (InFile.os().has_error()) {
errs() << "Error writing bitcode file: " << InputFilename << "\n";
diff --git a/contrib/llvm/tools/bugpoint/ToolRunner.h b/contrib/llvm/tools/bugpoint/ToolRunner.h
index 454724a..5d67a94 100644
--- a/contrib/llvm/tools/bugpoint/ToolRunner.h
+++ b/contrib/llvm/tools/bugpoint/ToolRunner.h
@@ -165,7 +165,7 @@ public:
ToolArgs.clear();
if (Args) ToolArgs = *Args;
}
- ~LLC() { delete gcc; }
+ ~LLC() override { delete gcc; }
/// compileProgram - Compile the specified program from bitcode to executable
/// code. This does not produce any output, it is only used when debugging
diff --git a/contrib/llvm/tools/bugpoint/bugpoint.cpp b/contrib/llvm/tools/bugpoint/bugpoint.cpp
index d0bade5..af6d9fc 100644
--- a/contrib/llvm/tools/bugpoint/bugpoint.cpp
+++ b/contrib/llvm/tools/bugpoint/bugpoint.cpp
@@ -16,10 +16,10 @@
#include "BugDriver.h"
#include "ToolRunner.h"
#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/LegacyPassManager.h"
#include "llvm/IR/LegacyPassNameParser.h"
#include "llvm/LinkAllIR.h"
#include "llvm/LinkAllPasses.h"
-#include "llvm/PassManager.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/PluginLoader.h"
@@ -50,7 +50,7 @@ TimeoutValue("timeout", cl::init(300), cl::value_desc("seconds"),
static cl::opt<int>
MemoryLimit("mlimit", cl::init(-1), cl::value_desc("MBytes"),
cl::desc("Maximum amount of memory to use. 0 disables check."
- " Defaults to 300MB (800MB under valgrind)."));
+ " Defaults to 400MB (800MB under valgrind)."));
static cl::opt<bool>
UseValgrind("enable-valgrind",
@@ -92,7 +92,7 @@ static void BugpointInterruptFunction() {
// Hack to capture a pass list.
namespace {
- class AddToDriver : public FunctionPassManager {
+ class AddToDriver : public legacy::FunctionPassManager {
BugDriver &D;
public:
AddToDriver(BugDriver &_D) : FunctionPassManager(nullptr), D(_D) {}
@@ -158,7 +158,7 @@ int main(int argc, char **argv) {
if (sys::RunningOnValgrind() || UseValgrind)
MemoryLimit = 800;
else
- MemoryLimit = 300;
+ MemoryLimit = 400;
}
BugDriver D(argv[0], FindBugs, TimeoutValue, MemoryLimit,
diff --git a/contrib/llvm/tools/llc/llc.cpp b/contrib/llvm/tools/llc/llc.cpp
index 35f965b..0977418 100644
--- a/contrib/llvm/tools/llc/llc.cpp
+++ b/contrib/llvm/tools/llc/llc.cpp
@@ -14,18 +14,21 @@
//===----------------------------------------------------------------------===//
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/Triple.h"
+#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/CodeGen/CommandFlags.h"
#include "llvm/CodeGen/LinkAllAsmWriterComponents.h"
#include "llvm/CodeGen/LinkAllCodegenComponents.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/IRPrintingPasses.h"
#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/LegacyPassManager.h"
#include "llvm/IR/Module.h"
+#include "llvm/IR/Verifier.h"
#include "llvm/IRReader/IRReader.h"
#include "llvm/MC/SubtargetFeature.h"
#include "llvm/Pass.h"
-#include "llvm/PassManager.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/FileSystem.h"
@@ -39,7 +42,6 @@
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/ToolOutputFile.h"
-#include "llvm/Target/TargetLibraryInfo.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetSubtargetInfo.h"
#include <memory>
@@ -210,12 +212,6 @@ static int compileModule(char **argv, LLVMContext &Context) {
bool SkipModule = MCPU == "help" ||
(!MAttrs.empty() && MAttrs.front() == "help");
- // If user asked for the 'native' CPU, autodetect here. If autodection fails,
- // this will set the CPU to an empty string which tells the target to
- // pick a basic default.
- if (MCPU == "native")
- MCPU = sys::getHostCPUName();
-
// If user just wants to list available options, skip module loading
if (!SkipModule) {
M = parseIRFile(InputFilename, Err, Context);
@@ -224,6 +220,14 @@ static int compileModule(char **argv, LLVMContext &Context) {
return 1;
}
+ // Verify module immediately to catch problems before doInitialization() is
+ // called on any passes.
+ if (!NoVerify && verifyModule(*M, &errs())) {
+ errs() << argv[0] << ": " << InputFilename
+ << ": error: input module is broken!\n";
+ return 1;
+ }
+
// If we are supposed to override the target triple, do so now.
if (!TargetTriple.empty())
M->setTargetTriple(Triple::normalize(TargetTriple));
@@ -244,14 +248,7 @@ static int compileModule(char **argv, LLVMContext &Context) {
return 1;
}
- // Package up features to be passed to target/subtarget
- std::string FeaturesStr;
- if (MAttrs.size()) {
- SubtargetFeatures Features;
- for (unsigned i = 0; i != MAttrs.size(); ++i)
- Features.AddFeature(MAttrs[i]);
- FeaturesStr = Features.getString();
- }
+ std::string CPUStr = getCPUStr(), FeaturesStr = getFeaturesStr();
CodeGenOpt::Level OLvl = CodeGenOpt::Default;
switch (OptLevel) {
@@ -272,8 +269,9 @@ static int compileModule(char **argv, LLVMContext &Context) {
Options.MCOptions.AsmVerbose = AsmVerbose;
std::unique_ptr<TargetMachine> Target(
- TheTarget->createTargetMachine(TheTriple.getTriple(), MCPU, FeaturesStr,
+ TheTarget->createTargetMachine(TheTriple.getTriple(), CPUStr, FeaturesStr,
Options, RelocModel, CMModel, OLvl));
+
assert(Target && "Could not allocate target machine!");
// If we don't have a module then just exit now. We do this down
@@ -283,9 +281,8 @@ static int compileModule(char **argv, LLVMContext &Context) {
return 0;
assert(M && "Should have exited if we didn't have a module!");
-
- if (GenerateSoftFloatCalls)
- FloatABIForCalls = FloatABI::Soft;
+ if (FloatABIForCalls != FloatABI::Default)
+ Options.FloatABIType = FloatABIForCalls;
// Figure out where we are going to send the output.
std::unique_ptr<tool_output_file> Out =
@@ -293,18 +290,23 @@ static int compileModule(char **argv, LLVMContext &Context) {
if (!Out) return 1;
// Build up all of the passes that we want to do to the module.
- PassManager PM;
+ legacy::PassManager PM;
// Add an appropriate TargetLibraryInfo pass for the module's triple.
- TargetLibraryInfo *TLI = new TargetLibraryInfo(TheTriple);
+ TargetLibraryInfoImpl TLII(Triple(M->getTargetTriple()));
+
+ // The -disable-simplify-libcalls flag actually disables all builtin optzns.
if (DisableSimplifyLibCalls)
- TLI->disableAllFunctions();
- PM.add(TLI);
+ TLII.disableAllFunctions();
+ PM.add(new TargetLibraryInfoWrapperPass(TLII));
// Add the target data from the target machine, if it exists, or the module.
- if (const DataLayout *DL = Target->getSubtargetImpl()->getDataLayout())
- M->setDataLayout(DL);
- PM.add(new DataLayoutPass());
+ if (const DataLayout *DL = Target->getDataLayout())
+ M->setDataLayout(*DL);
+
+ // Override function attributes based on CPUStr, FeaturesStr, and command line
+ // flags.
+ setFunctionAttributes(CPUStr, FeaturesStr, *M);
if (RelaxAll.getNumOccurrences() > 0 &&
FileType != TargetMachine::CGFT_ObjectFile)
@@ -312,7 +314,13 @@ static int compileModule(char **argv, LLVMContext &Context) {
<< ": warning: ignoring -mc-relax-all because filetype != obj";
{
- formatted_raw_ostream FOS(Out->os());
+ raw_pwrite_stream *OS = &Out->os();
+ std::unique_ptr<buffer_ostream> BOS;
+ if (FileType != TargetMachine::CGFT_AssemblyFile &&
+ !Out->os().supportsSeeking()) {
+ BOS = make_unique<buffer_ostream>(*OS);
+ OS = BOS.get();
+ }
AnalysisID StartAfterID = nullptr;
AnalysisID StopAfterID = nullptr;
@@ -335,8 +343,8 @@ static int compileModule(char **argv, LLVMContext &Context) {
}
// Ask the target to add backend passes as necessary.
- if (Target->addPassesToEmitFile(PM, FOS, FileType, NoVerify,
- StartAfterID, StopAfterID)) {
+ if (Target->addPassesToEmitFile(PM, *OS, FileType, NoVerify, StartAfterID,
+ StopAfterID)) {
errs() << argv[0] << ": target does not support generation of this"
<< " file type!\n";
return 1;
diff --git a/contrib/llvm/tools/lli/OrcLazyJIT.cpp b/contrib/llvm/tools/lli/OrcLazyJIT.cpp
new file mode 100644
index 0000000..bda5d6d
--- /dev/null
+++ b/contrib/llvm/tools/lli/OrcLazyJIT.cpp
@@ -0,0 +1,148 @@
+//===------ OrcLazyJIT.cpp - Basic Orc-based JIT for lazy execution -------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "OrcLazyJIT.h"
+#include "llvm/ExecutionEngine/Orc/OrcTargetSupport.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/DynamicLibrary.h"
+#include <cstdio>
+#include <system_error>
+
+using namespace llvm;
+
+namespace {
+
+ enum class DumpKind { NoDump, DumpFuncsToStdOut, DumpModsToStdErr,
+ DumpModsToDisk };
+
+ cl::opt<DumpKind> OrcDumpKind("orc-lazy-debug",
+ cl::desc("Debug dumping for the orc-lazy JIT."),
+ cl::init(DumpKind::NoDump),
+ cl::values(
+ clEnumValN(DumpKind::NoDump, "no-dump",
+ "Don't dump anything."),
+ clEnumValN(DumpKind::DumpFuncsToStdOut,
+ "funcs-to-stdout",
+ "Dump function names to stdout."),
+ clEnumValN(DumpKind::DumpModsToStdErr,
+ "mods-to-stderr",
+ "Dump modules to stderr."),
+ clEnumValN(DumpKind::DumpModsToDisk,
+ "mods-to-disk",
+ "Dump modules to the current "
+ "working directory. (WARNING: "
+ "will overwrite existing files)."),
+ clEnumValEnd));
+}
+
+OrcLazyJIT::CallbackManagerBuilder
+OrcLazyJIT::createCallbackManagerBuilder(Triple T) {
+ switch (T.getArch()) {
+ default: return nullptr;
+
+ case Triple::x86_64: {
+ typedef orc::JITCompileCallbackManager<IRDumpLayerT,
+ orc::OrcX86_64> CCMgrT;
+ return [](IRDumpLayerT &IRDumpLayer, RuntimeDyld::MemoryManager &MemMgr,
+ LLVMContext &Context) {
+ return llvm::make_unique<CCMgrT>(IRDumpLayer, MemMgr, Context, 0,
+ 64);
+ };
+ }
+ }
+}
+
+OrcLazyJIT::TransformFtor OrcLazyJIT::createDebugDumper() {
+
+ switch (OrcDumpKind) {
+ case DumpKind::NoDump:
+ return [](std::unique_ptr<Module> M) { return M; };
+
+ case DumpKind::DumpFuncsToStdOut:
+ return [](std::unique_ptr<Module> M) {
+ printf("[ ");
+
+ for (const auto &F : *M) {
+ if (F.isDeclaration())
+ continue;
+
+ if (F.hasName()) {
+ std::string Name(F.getName());
+ printf("%s ", Name.c_str());
+ } else
+ printf("<anon> ");
+ }
+
+ printf("]\n");
+ return M;
+ };
+
+ case DumpKind::DumpModsToStdErr:
+ return [](std::unique_ptr<Module> M) {
+ dbgs() << "----- Module Start -----\n" << *M
+ << "----- Module End -----\n";
+
+ return M;
+ };
+
+ case DumpKind::DumpModsToDisk:
+ return [](std::unique_ptr<Module> M) {
+ std::error_code EC;
+ raw_fd_ostream Out(M->getModuleIdentifier() + ".ll", EC,
+ sys::fs::F_Text);
+ if (EC) {
+ errs() << "Couldn't open " << M->getModuleIdentifier()
+ << " for dumping.\nError:" << EC.message() << "\n";
+ exit(1);
+ }
+ Out << *M;
+ return M;
+ };
+ }
+ llvm_unreachable("Unknown DumpKind");
+}
+
+int llvm::runOrcLazyJIT(std::unique_ptr<Module> M, int ArgC, char* ArgV[]) {
+ // Add the program's symbols into the JIT's search space.
+ if (sys::DynamicLibrary::LoadLibraryPermanently(nullptr)) {
+ errs() << "Error loading program symbols.\n";
+ return 1;
+ }
+
+ // Grab a target machine and try to build a factory function for the
+ // target-specific Orc callback manager.
+ auto TM = std::unique_ptr<TargetMachine>(EngineBuilder().selectTarget());
+ auto &Context = getGlobalContext();
+ auto CallbackMgrBuilder =
+ OrcLazyJIT::createCallbackManagerBuilder(Triple(TM->getTargetTriple()));
+
+ // If we couldn't build the factory function then there must not be a callback
+ // manager for this target. Bail out.
+ if (!CallbackMgrBuilder) {
+ errs() << "No callback manager available for target '"
+ << TM->getTargetTriple() << "'.\n";
+ return 1;
+ }
+
+ // Everything looks good. Build the JIT.
+ OrcLazyJIT J(std::move(TM), Context, CallbackMgrBuilder);
+
+ // Add the module, look up main and run it.
+ auto MainHandle = J.addModule(std::move(M));
+ auto MainSym = J.findSymbolIn(MainHandle, "main");
+
+ if (!MainSym) {
+ errs() << "Could not find main function.\n";
+ return 1;
+ }
+
+ typedef int (*MainFnPtr)(int, char*[]);
+ auto Main = OrcLazyJIT::fromTargetAddress<MainFnPtr>(MainSym.getAddress());
+ return Main(ArgC, ArgV);
+}
diff --git a/contrib/llvm/tools/lli/OrcLazyJIT.h b/contrib/llvm/tools/lli/OrcLazyJIT.h
new file mode 100644
index 0000000..bff2eca
--- /dev/null
+++ b/contrib/llvm/tools/lli/OrcLazyJIT.h
@@ -0,0 +1,164 @@
+//===--- OrcLazyJIT.h - Basic Orc-based JIT for lazy execution --*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Simple Orc-based JIT. Uses the compile-on-demand layer to break up and
+// lazily compile modules.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLI_ORCLAZYJIT_H
+#define LLVM_TOOLS_LLI_ORCLAZYJIT_H
+
+#include "llvm/ADT/Triple.h"
+#include "llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h"
+#include "llvm/ExecutionEngine/Orc/CompileUtils.h"
+#include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
+#include "llvm/ExecutionEngine/Orc/IRCompileLayer.h"
+#include "llvm/ExecutionEngine/Orc/IRTransformLayer.h"
+#include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h"
+#include "llvm/ExecutionEngine/RTDyldMemoryManager.h"
+#include "llvm/IR/LLVMContext.h"
+
+namespace llvm {
+
+class OrcLazyJIT {
+public:
+
+ typedef orc::JITCompileCallbackManagerBase CompileCallbackMgr;
+ typedef orc::ObjectLinkingLayer<> ObjLayerT;
+ typedef orc::IRCompileLayer<ObjLayerT> CompileLayerT;
+ typedef std::function<std::unique_ptr<Module>(std::unique_ptr<Module>)>
+ TransformFtor;
+ typedef orc::IRTransformLayer<CompileLayerT, TransformFtor> IRDumpLayerT;
+ typedef orc::CompileOnDemandLayer<IRDumpLayerT, CompileCallbackMgr> CODLayerT;
+ typedef CODLayerT::ModuleSetHandleT ModuleHandleT;
+
+ typedef std::function<
+ std::unique_ptr<CompileCallbackMgr>(IRDumpLayerT&,
+ RuntimeDyld::MemoryManager&,
+ LLVMContext&)>
+ CallbackManagerBuilder;
+
+ static CallbackManagerBuilder createCallbackManagerBuilder(Triple T);
+
+ OrcLazyJIT(std::unique_ptr<TargetMachine> TM, LLVMContext &Context,
+ CallbackManagerBuilder &BuildCallbackMgr)
+ : TM(std::move(TM)),
+ Mang(this->TM->getDataLayout()),
+ ObjectLayer(),
+ CompileLayer(ObjectLayer, orc::SimpleCompiler(*this->TM)),
+ IRDumpLayer(CompileLayer, createDebugDumper()),
+ CCMgr(BuildCallbackMgr(IRDumpLayer, CCMgrMemMgr, Context)),
+ CODLayer(IRDumpLayer, *CCMgr),
+ CXXRuntimeOverrides([this](const std::string &S) { return mangle(S); }) {}
+
+ ~OrcLazyJIT() {
+ // Run any destructors registered with __cxa_atexit.
+ CXXRuntimeOverrides.runDestructors();
+ // Run any IR destructors.
+ for (auto &DtorRunner : IRStaticDestructorRunners)
+ DtorRunner.runViaLayer(CODLayer);
+ }
+
+ template <typename PtrTy>
+ static PtrTy fromTargetAddress(orc::TargetAddress Addr) {
+ return reinterpret_cast<PtrTy>(static_cast<uintptr_t>(Addr));
+ }
+
+ ModuleHandleT addModule(std::unique_ptr<Module> M) {
+ // Attach a data-layout if one isn't already present.
+ if (M->getDataLayout().isDefault())
+ M->setDataLayout(*TM->getDataLayout());
+
+ // Record the static constructors and destructors. We have to do this before
+ // we hand over ownership of the module to the JIT.
+ std::vector<std::string> CtorNames, DtorNames;
+ for (auto Ctor : orc::getConstructors(*M))
+ CtorNames.push_back(mangle(Ctor.Func->getName()));
+ for (auto Dtor : orc::getDestructors(*M))
+ DtorNames.push_back(mangle(Dtor.Func->getName()));
+
+ // Symbol resolution order:
+ // 1) Search the JIT symbols.
+ // 2) Check for C++ runtime overrides.
+ // 3) Search the host process (LLI)'s symbol table.
+ auto Resolver =
+ orc::createLambdaResolver(
+ [this](const std::string &Name) {
+
+ if (auto Sym = CODLayer.findSymbol(Name, true))
+ return RuntimeDyld::SymbolInfo(Sym.getAddress(), Sym.getFlags());
+
+ if (auto Sym = CXXRuntimeOverrides.searchOverrides(Name))
+ return Sym;
+
+ if (auto Addr = RTDyldMemoryManager::getSymbolAddressInProcess(Name))
+ return RuntimeDyld::SymbolInfo(Addr, JITSymbolFlags::Exported);
+
+ return RuntimeDyld::SymbolInfo(nullptr);
+ },
+ [](const std::string &Name) { return RuntimeDyld::SymbolInfo(nullptr); }
+ );
+
+ // Add the module to the JIT.
+ std::vector<std::unique_ptr<Module>> S;
+ S.push_back(std::move(M));
+ auto H = CODLayer.addModuleSet(std::move(S), nullptr, std::move(Resolver));
+
+ // Run the static constructors, and save the static destructor runner for
+ // execution when the JIT is torn down.
+ orc::CtorDtorRunner<CODLayerT> CtorRunner(std::move(CtorNames), H);
+ CtorRunner.runViaLayer(CODLayer);
+
+ IRStaticDestructorRunners.push_back(
+ orc::CtorDtorRunner<CODLayerT>(std::move(DtorNames), H));
+
+ return H;
+ }
+
+ orc::JITSymbol findSymbol(const std::string &Name) {
+ return CODLayer.findSymbol(mangle(Name), true);
+ }
+
+ orc::JITSymbol findSymbolIn(ModuleHandleT H, const std::string &Name) {
+ return CODLayer.findSymbolIn(H, mangle(Name), true);
+ }
+
+private:
+
+ std::string mangle(const std::string &Name) {
+ std::string MangledName;
+ {
+ raw_string_ostream MangledNameStream(MangledName);
+ Mang.getNameWithPrefix(MangledNameStream, Name);
+ }
+ return MangledName;
+ }
+
+ static TransformFtor createDebugDumper();
+
+ std::unique_ptr<TargetMachine> TM;
+ Mangler Mang;
+ SectionMemoryManager CCMgrMemMgr;
+
+ ObjLayerT ObjectLayer;
+ CompileLayerT CompileLayer;
+ IRDumpLayerT IRDumpLayer;
+ std::unique_ptr<CompileCallbackMgr> CCMgr;
+ CODLayerT CODLayer;
+
+ orc::LocalCXXRuntimeOverrides CXXRuntimeOverrides;
+ std::vector<orc::CtorDtorRunner<CODLayerT>> IRStaticDestructorRunners;
+};
+
+int runOrcLazyJIT(std::unique_ptr<Module> M, int ArgC, char* ArgV[]);
+
+} // end namespace llvm
+
+#endif
diff --git a/contrib/llvm/tools/lli/RemoteMemoryManager.cpp b/contrib/llvm/tools/lli/RemoteMemoryManager.cpp
index 47da8fb..0a16210 100644
--- a/contrib/llvm/tools/lli/RemoteMemoryManager.cpp
+++ b/contrib/llvm/tools/lli/RemoteMemoryManager.cpp
@@ -16,6 +16,7 @@
#include "llvm/ExecutionEngine/ExecutionEngine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Format.h"
+#include "llvm/Support/raw_ostream.h"
using namespace llvm;
diff --git a/contrib/llvm/tools/lli/RemoteMemoryManager.h b/contrib/llvm/tools/lli/RemoteMemoryManager.h
index 895bcda..5733fa5 100644
--- a/contrib/llvm/tools/lli/RemoteMemoryManager.h
+++ b/contrib/llvm/tools/lli/RemoteMemoryManager.h
@@ -64,7 +64,7 @@ private:
public:
RemoteMemoryManager() : Target(nullptr) {}
- virtual ~RemoteMemoryManager();
+ ~RemoteMemoryManager() override;
uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment,
unsigned SectionID,
diff --git a/contrib/llvm/tools/lli/RemoteTargetExternal.h b/contrib/llvm/tools/lli/RemoteTargetExternal.h
index bb621f5..afe8570 100644
--- a/contrib/llvm/tools/lli/RemoteTargetExternal.h
+++ b/contrib/llvm/tools/lli/RemoteTargetExternal.h
@@ -106,7 +106,7 @@ public:
void stop() override;
RemoteTargetExternal(std::string &Name) : RemoteTarget(), ChildName(Name) {}
- virtual ~RemoteTargetExternal() {}
+ ~RemoteTargetExternal() override {}
private:
std::string ChildName;
diff --git a/contrib/llvm/tools/lli/lli.cpp b/contrib/llvm/tools/lli/lli.cpp
index 730911b..6916d16 100644
--- a/contrib/llvm/tools/lli/lli.cpp
+++ b/contrib/llvm/tools/lli/lli.cpp
@@ -14,6 +14,7 @@
//===----------------------------------------------------------------------===//
#include "llvm/IR/LLVMContext.h"
+#include "OrcLazyJIT.h"
#include "RemoteMemoryManager.h"
#include "RemoteTarget.h"
#include "RemoteTargetExternal.h"
@@ -25,6 +26,7 @@
#include "llvm/ExecutionEngine/JITEventListener.h"
#include "llvm/ExecutionEngine/MCJIT.h"
#include "llvm/ExecutionEngine/ObjectCache.h"
+#include "llvm/ExecutionEngine/OrcMCJITReplacement.h"
#include "llvm/ExecutionEngine/SectionMemoryManager.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/Module.h"
@@ -41,6 +43,7 @@
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/Memory.h"
#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Path.h"
#include "llvm/Support/PluginLoader.h"
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/Process.h"
@@ -64,6 +67,9 @@ using namespace llvm;
#define DEBUG_TYPE "lli"
namespace {
+
+ enum class JITKind { MCJIT, OrcMCJITReplacement, OrcLazy };
+
cl::opt<std::string>
InputFile(cl::desc("<input bitcode>"), cl::Positional, cl::init("-"));
@@ -74,6 +80,20 @@ namespace {
cl::desc("Force interpretation: disable JIT"),
cl::init(false));
+ cl::opt<JITKind> UseJITKind("jit-kind",
+ cl::desc("Choose underlying JIT kind."),
+ cl::init(JITKind::MCJIT),
+ cl::values(
+ clEnumValN(JITKind::MCJIT, "mcjit",
+ "MCJIT"),
+ clEnumValN(JITKind::OrcMCJITReplacement,
+ "orc-mcjit",
+ "Orc-based MCJIT replacement"),
+ clEnumValN(JITKind::OrcLazy,
+ "orc-lazy",
+ "Orc-based lazy JIT."),
+ clEnumValEnd));
+
// The MCJIT supports building for a target address space separate from
// the JIT compilation process. Use a forked process and a copying
// memory manager with IPC to execute using this functionality.
@@ -215,23 +235,6 @@ namespace {
clEnumValN(FloatABI::Hard, "hard",
"Hard float ABI (uses FP registers)"),
clEnumValEnd));
- cl::opt<bool>
-// In debug builds, make this default to true.
-#ifdef NDEBUG
-#define EMIT_DEBUG false
-#else
-#define EMIT_DEBUG true
-#endif
- EmitJitDebugInfo("jit-emit-debug",
- cl::desc("Emit debug information to debugger"),
- cl::init(EMIT_DEBUG));
-#undef EMIT_DEBUG
-
- static cl::opt<bool>
- EmitJitDebugInfoToDisk("jit-emit-debug-to-disk",
- cl::Hidden,
- cl::desc("Emit debug info objfiles to disk"),
- cl::init(false));
}
//===----------------------------------------------------------------------===//
@@ -251,7 +254,7 @@ public:
this->CacheDir[this->CacheDir.size() - 1] != '/')
this->CacheDir += '/';
}
- virtual ~LLIObjectCache() {}
+ ~LLIObjectCache() override {}
void notifyObjectCompiled(const Module *M, MemoryBufferRef Obj) override {
const std::string ModuleID = M->getModuleIdentifier();
@@ -395,6 +398,9 @@ int main(int argc, char **argv, char * const *envp) {
return 1;
}
+ if (UseJITKind == JITKind::OrcLazy)
+ return runOrcLazyJIT(std::move(Owner), argc, argv);
+
if (EnableCacheManager) {
std::string CacheName("file:");
CacheName.append(InputFile);
@@ -421,6 +427,7 @@ int main(int argc, char **argv, char * const *envp) {
builder.setEngineKind(ForceInterpreter
? EngineKind::Interpreter
: EngineKind::JIT);
+ builder.setUseOrcMCJITReplacement(UseJITKind == JITKind::OrcMCJITReplacement);
// If we are supposed to override the target triple, do so now.
if (!TargetTriple.empty())
@@ -458,17 +465,8 @@ int main(int argc, char **argv, char * const *envp) {
builder.setOptLevel(OLvl);
TargetOptions Options;
- Options.UseSoftFloat = GenerateSoftFloatCalls;
if (FloatABIForCalls != FloatABI::Default)
Options.FloatABIType = FloatABIForCalls;
- if (GenerateSoftFloatCalls)
- FloatABIForCalls = FloatABI::Soft;
-
- // Remote target execution doesn't handle EH or debug registration.
- if (!RemoteMCJIT) {
- Options.JITEmitDebugInfo = EmitJitDebugInfo;
- Options.JITEmitDebugInfoToDisk = EmitJitDebugInfoToDisk;
- }
builder.setTargetOptions(Options);
@@ -556,7 +554,7 @@ int main(int argc, char **argv, char * const *envp) {
// If the user specifically requested an argv[0] to pass into the program,
// do it now.
if (!FakeArgv0.empty()) {
- InputFile = FakeArgv0;
+ InputFile = static_cast<std::string>(FakeArgv0);
} else {
// Otherwise, if there is a .bc suffix on the executable strip it off, it
// might confuse the program.
@@ -588,7 +586,7 @@ int main(int argc, char **argv, char * const *envp) {
// function later on to make an explicit call, so get the function now.
Constant *Exit = Mod->getOrInsertFunction("exit", Type::getVoidTy(Context),
Type::getInt32Ty(Context),
- NULL);
+ nullptr);
// Run static constructors.
if (!ForceInterpreter) {
diff --git a/contrib/llvm/tools/llvm-ar/llvm-ar.cpp b/contrib/llvm/tools/llvm-ar/llvm-ar.cpp
index f72762a..f813465 100644
--- a/contrib/llvm/tools/llvm-ar/llvm-ar.cpp
+++ b/contrib/llvm/tools/llvm-ar/llvm-ar.cpp
@@ -24,6 +24,7 @@
#include "llvm/Support/LineIterator.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Path.h"
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/Signals.h"
#include "llvm/Support/TargetSelect.h"
@@ -92,7 +93,6 @@ static cl::extrahelp MoreHelp(
" [a] - put file(s) after [relpos]\n"
" [b] - put file(s) before [relpos] (same as [i])\n"
" [i] - put file(s) before [relpos] (same as [b])\n"
- " [N] - use instance [count] of name\n"
" [o] - preserve original dates\n"
" [s] - create an archive index (cf. ranlib)\n"
" [S] - do not build a symbol table\n"
diff --git a/contrib/llvm/tools/llvm-as/llvm-as.cpp b/contrib/llvm/tools/llvm-as/llvm-as.cpp
index 5ccf505..4455d24 100644
--- a/contrib/llvm/tools/llvm-as/llvm-as.cpp
+++ b/contrib/llvm/tools/llvm-as/llvm-as.cpp
@@ -51,20 +51,19 @@ static cl::opt<bool>
DisableVerify("disable-verify", cl::Hidden,
cl::desc("Do not run verifier on input LLVM (dangerous!)"));
+static cl::opt<bool> PreserveBitcodeUseListOrder(
+ "preserve-bc-uselistorder",
+ cl::desc("Preserve use-list order when writing LLVM bitcode."),
+ cl::init(true), cl::Hidden);
+
static void WriteOutputFile(const Module *M) {
// Infer the output filename if needed.
if (OutputFilename.empty()) {
if (InputFilename == "-") {
OutputFilename = "-";
} else {
- std::string IFN = InputFilename;
- int Len = IFN.length();
- if (IFN[Len-3] == '.' && IFN[Len-2] == 'l' && IFN[Len-1] == 'l') {
- // Source ends in .ll
- OutputFilename = std::string(IFN.begin(), IFN.end()-3);
- } else {
- OutputFilename = IFN; // Append a .bc to it
- }
+ StringRef IFN = InputFilename;
+ OutputFilename = (IFN.endswith(".ll") ? IFN.drop_back(3) : IFN).str();
OutputFilename += ".bc";
}
}
@@ -78,7 +77,7 @@ static void WriteOutputFile(const Module *M) {
}
if (Force || !CheckBitcodeOutputToConsole(Out->os(), true))
- WriteBitcodeToFile(M, Out->os());
+ WriteBitcodeToFile(M, Out->os(), PreserveBitcodeUseListOrder);
// Declare success.
Out->keep();
diff --git a/contrib/llvm/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp b/contrib/llvm/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp
index 396e030..58b02be 100644
--- a/contrib/llvm/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp
+++ b/contrib/llvm/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp
@@ -66,6 +66,10 @@ static cl::opt<std::string>
BlockInfoFilename("block-info",
cl::desc("Use the BLOCK_INFO from the given file"));
+static cl::opt<bool>
+ ShowBinaryBlobs("show-binary-blobs",
+ cl::desc("Print binary blobs using hex escapes"));
+
namespace {
/// CurStreamTypeType - A type for CurStreamType
@@ -222,8 +226,10 @@ static const char *GetCodeName(unsigned CodeID, unsigned BlockID,
case bitc::FUNC_CODE_INST_BINOP: return "INST_BINOP";
case bitc::FUNC_CODE_INST_CAST: return "INST_CAST";
- case bitc::FUNC_CODE_INST_GEP: return "INST_GEP";
- case bitc::FUNC_CODE_INST_INBOUNDS_GEP: return "INST_INBOUNDS_GEP";
+ case bitc::FUNC_CODE_INST_GEP_OLD:
+ return "INST_GEP_OLD";
+ case bitc::FUNC_CODE_INST_INBOUNDS_GEP_OLD:
+ return "INST_INBOUNDS_GEP_OLD";
case bitc::FUNC_CODE_INST_SELECT: return "INST_SELECT";
case bitc::FUNC_CODE_INST_EXTRACTELT: return "INST_EXTRACTELT";
case bitc::FUNC_CODE_INST_INSERTELT: return "INST_INSERTELT";
@@ -248,6 +254,8 @@ static const char *GetCodeName(unsigned CodeID, unsigned BlockID,
case bitc::FUNC_CODE_DEBUG_LOC_AGAIN: return "DEBUG_LOC_AGAIN";
case bitc::FUNC_CODE_INST_CALL: return "INST_CALL";
case bitc::FUNC_CODE_DEBUG_LOC: return "DEBUG_LOC";
+ case bitc::FUNC_CODE_INST_GEP:
+ return "INST_GEP";
}
case bitc::VALUE_SYMTAB_BLOCK_ID:
switch (CodeID) {
@@ -456,17 +464,22 @@ static bool ParseBlock(BitstreamCursor &Stream, unsigned BlockID,
if (Blob.data()) {
outs() << " blob data = ";
- bool BlobIsPrintable = true;
- for (unsigned i = 0, e = Blob.size(); i != e; ++i)
- if (!isprint(static_cast<unsigned char>(Blob[i]))) {
- BlobIsPrintable = false;
- break;
- }
-
- if (BlobIsPrintable)
- outs() << "'" << Blob << "'";
- else
- outs() << "unprintable, " << Blob.size() << " bytes.";
+ if (ShowBinaryBlobs) {
+ outs() << "'";
+ outs().write_escaped(Blob, /*hex=*/true) << "'";
+ } else {
+ bool BlobIsPrintable = true;
+ for (unsigned i = 0, e = Blob.size(); i != e; ++i)
+ if (!isprint(static_cast<unsigned char>(Blob[i]))) {
+ BlobIsPrintable = false;
+ break;
+ }
+
+ if (BlobIsPrintable)
+ outs() << "'" << Blob << "'";
+ else
+ outs() << "unprintable, " << Blob.size() << " bytes.";
+ }
}
outs() << "\n";
diff --git a/contrib/llvm/tools/llvm-cov/CodeCoverage.cpp b/contrib/llvm/tools/llvm-cov/CodeCoverage.cpp
index 7cee4d4..f85f3b1 100644
--- a/contrib/llvm/tools/llvm-cov/CodeCoverage.cpp
+++ b/contrib/llvm/tools/llvm-cov/CodeCoverage.cpp
@@ -16,13 +16,12 @@
#include "RenderingSupport.h"
#include "CoverageFilters.h"
#include "CoverageReport.h"
-#include "CoverageSummary.h"
#include "CoverageViewOptions.h"
#include "SourceCoverageView.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Triple.h"
#include "llvm/ProfileData/CoverageMapping.h"
-#include "llvm/ProfileData/CoverageMappingReader.h"
#include "llvm/ProfileData/InstrProfReader.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/FileSystem.h"
@@ -30,6 +29,7 @@
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/PrettyStackTrace.h"
+#include "llvm/Support/Process.h"
#include "llvm/Support/Signals.h"
#include <functional>
#include <system_error>
@@ -89,6 +89,7 @@ public:
LoadedSourceFiles;
bool CompareFilenamesOnly;
StringMap<std::string> RemappedFilenames;
+ llvm::Triple::ArchType CoverageArch;
};
}
@@ -194,8 +195,22 @@ CodeCoverageTool::createSourceFileView(StringRef SourceFile,
return View;
}
+static bool modifiedTimeGT(StringRef LHS, StringRef RHS) {
+ sys::fs::file_status Status;
+ if (sys::fs::status(LHS, Status))
+ return false;
+ auto LHSTime = Status.getLastModificationTime();
+ if (sys::fs::status(RHS, Status))
+ return false;
+ auto RHSTime = Status.getLastModificationTime();
+ return LHSTime > RHSTime;
+}
+
std::unique_ptr<CoverageMapping> CodeCoverageTool::load() {
- auto CoverageOrErr = CoverageMapping::load(ObjectFilename, PGOFilename);
+ if (modifiedTimeGT(ObjectFilename, PGOFilename))
+ errs() << "warning: profile data may be out of date - object is newer\n";
+ auto CoverageOrErr = CoverageMapping::load(ObjectFilename, PGOFilename,
+ CoverageArch);
if (std::error_code EC = CoverageOrErr.getError()) {
colored_ostream(errs(), raw_ostream::RED)
<< "error: Failed to load coverage: " << EC.message();
@@ -244,6 +259,9 @@ int CodeCoverageTool::run(Command Cmd, int argc, const char **argv) {
cl::desc(
"File with the profile data obtained after an instrumented run"));
+ cl::opt<std::string> Arch(
+ "arch", cl::desc("architecture of the coverage mapping binary"));
+
cl::opt<bool> DebugDump("dump", cl::Optional,
cl::desc("Show internal debug dump"));
@@ -289,11 +307,19 @@ int CodeCoverageTool::run(Command Cmd, int argc, const char **argv) {
"greater than the given threshold"),
cl::cat(FilteringCategory));
+ cl::opt<cl::boolOrDefault> UseColor(
+ "use-color", cl::desc("Emit colored output (default=autodetect)"),
+ cl::init(cl::BOU_UNSET));
+
auto commandLineParser = [&, this](int argc, const char **argv) -> int {
cl::ParseCommandLineOptions(argc, argv, "LLVM code coverage tool\n");
ViewOpts.Debug = DebugDump;
CompareFilenamesOnly = FilenameEquivalence;
+ ViewOpts.Colors = UseColor == cl::BOU_UNSET
+ ? sys::Process::StandardOutHasColors()
+ : UseColor == cl::BOU_TRUE;
+
// Create the function filters
if (!NameFilters.empty() || !NameRegexFilters.empty()) {
auto NameFilterer = new CoverageFilters;
@@ -324,12 +350,23 @@ int CodeCoverageTool::run(Command Cmd, int argc, const char **argv) {
Filters.push_back(std::unique_ptr<CoverageFilter>(StatFilterer));
}
- for (const auto &File : InputSourceFiles) {
- SmallString<128> Path(File);
- if (std::error_code EC = sys::fs::make_absolute(Path)) {
- errs() << "error: " << File << ": " << EC.message();
+ if (Arch.empty())
+ CoverageArch = llvm::Triple::ArchType::UnknownArch;
+ else {
+ CoverageArch = Triple(Arch).getArch();
+ if (CoverageArch == llvm::Triple::ArchType::UnknownArch) {
+ errs() << "error: Unknown architecture: " << Arch << "\n";
return 1;
}
+ }
+
+ for (const auto &File : InputSourceFiles) {
+ SmallString<128> Path(File);
+ if (!CompareFilenamesOnly)
+ if (std::error_code EC = sys::fs::make_absolute(Path)) {
+ errs() << "error: " << File << ": " << EC.message();
+ return 1;
+ }
SourceFiles.push_back(Path.str());
}
return 0;
@@ -373,15 +410,10 @@ int CodeCoverageTool::show(int argc, const char **argv,
cl::desc("Show function instantiations"),
cl::cat(ViewCategory));
- cl::opt<bool> NoColors("no-colors", cl::Optional,
- cl::desc("Don't show text colors"), cl::init(false),
- cl::cat(ViewCategory));
-
auto Err = commandLineParser(argc, argv);
if (Err)
return Err;
- ViewOpts.Colors = !NoColors;
ViewOpts.ShowLineNumbers = true;
ViewOpts.ShowLineStats = ShowLineExecutionCounts.getNumOccurrences() != 0 ||
!ShowRegions || ShowBestLineRegionsCounts;
@@ -447,28 +479,19 @@ int CodeCoverageTool::show(int argc, const char **argv,
int CodeCoverageTool::report(int argc, const char **argv,
CommandLineParserType commandLineParser) {
- cl::opt<bool> NoColors("no-colors", cl::Optional,
- cl::desc("Don't show text colors"), cl::init(false));
-
auto Err = commandLineParser(argc, argv);
if (Err)
return Err;
- ViewOpts.Colors = !NoColors;
-
auto Coverage = load();
if (!Coverage)
return 1;
- CoverageSummary Summarizer;
- Summarizer.createSummaries(*Coverage);
- CoverageReport Report(ViewOpts, Summarizer);
- if (SourceFiles.empty() && Filters.empty()) {
+ CoverageReport Report(ViewOpts, std::move(Coverage));
+ if (SourceFiles.empty())
Report.renderFileReports(llvm::outs());
- return 0;
- }
-
- Report.renderFunctionReports(llvm::outs());
+ else
+ Report.renderFunctionReports(SourceFiles, llvm::outs());
return 0;
}
diff --git a/contrib/llvm/tools/llvm-cov/CoverageReport.cpp b/contrib/llvm/tools/llvm-cov/CoverageReport.cpp
index 6ae6ba5..497c2f8 100644
--- a/contrib/llvm/tools/llvm-cov/CoverageReport.cpp
+++ b/contrib/llvm/tools/llvm-cov/CoverageReport.cpp
@@ -12,7 +12,6 @@
//===----------------------------------------------------------------------===//
#include "CoverageReport.h"
-#include "CoverageSummary.h"
#include "RenderingSupport.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Format.h"
@@ -156,14 +155,15 @@ void CoverageReport::render(const FunctionCoverageSummary &Function,
OS << "\n";
}
-void CoverageReport::renderFunctionReports(raw_ostream &OS) {
+void CoverageReport::renderFunctionReports(ArrayRef<std::string> Files,
+ raw_ostream &OS) {
bool isFirst = true;
- for (const auto &File : Summary.getFileSummaries()) {
+ for (StringRef Filename : Files) {
if (isFirst)
isFirst = false;
else
OS << "\n";
- OS << "File '" << File.Name << "':\n";
+ OS << "File '" << Filename << "':\n";
OS << column("Name", FunctionReportColumns[0])
<< column("Regions", FunctionReportColumns[1], Column::RightAlignment)
<< column("Miss", FunctionReportColumns[2], Column::RightAlignment)
@@ -174,13 +174,19 @@ void CoverageReport::renderFunctionReports(raw_ostream &OS) {
OS << "\n";
renderDivider(FunctionReportColumns, OS);
OS << "\n";
- for (const auto &Function : File.FunctionSummaries)
+ FunctionCoverageSummary Totals("TOTAL");
+ for (const auto &F : Coverage->getCoveredFunctions(Filename)) {
+ FunctionCoverageSummary Function = FunctionCoverageSummary::get(F);
+ ++Totals.ExecutionCount;
+ Totals.RegionCoverage += Function.RegionCoverage;
+ Totals.LineCoverage += Function.LineCoverage;
render(Function, OS);
- renderDivider(FunctionReportColumns, OS);
- OS << "\n";
- render(FunctionCoverageSummary("TOTAL", /*ExecutionCount=*/0,
- File.RegionCoverage, File.LineCoverage),
- OS);
+ }
+ if (Totals.ExecutionCount) {
+ renderDivider(FunctionReportColumns, OS);
+ OS << "\n";
+ render(Totals, OS);
+ }
}
}
@@ -194,9 +200,17 @@ void CoverageReport::renderFileReports(raw_ostream &OS) {
<< "\n";
renderDivider(FileReportColumns, OS);
OS << "\n";
- for (const auto &File : Summary.getFileSummaries())
- render(File, OS);
+ FileCoverageSummary Totals("TOTAL");
+ for (StringRef Filename : Coverage->getUniqueSourceFiles()) {
+ FileCoverageSummary Summary(Filename);
+ for (const auto &F : Coverage->getCoveredFunctions(Filename)) {
+ FunctionCoverageSummary Function = FunctionCoverageSummary::get(F);
+ Summary.addFunction(Function);
+ Totals.addFunction(Function);
+ }
+ render(Summary, OS);
+ }
renderDivider(FileReportColumns, OS);
OS << "\n";
- render(Summary.getCombinedFileSummaries(), OS);
+ render(Totals, OS);
}
diff --git a/contrib/llvm/tools/llvm-cov/CoverageReport.h b/contrib/llvm/tools/llvm-cov/CoverageReport.h
index d186117..7ec3df9 100644
--- a/contrib/llvm/tools/llvm-cov/CoverageReport.h
+++ b/contrib/llvm/tools/llvm-cov/CoverageReport.h
@@ -14,7 +14,7 @@
#ifndef LLVM_COV_COVERAGEREPORT_H
#define LLVM_COV_COVERAGEREPORT_H
-#include "CoverageSummary.h"
+#include "CoverageSummaryInfo.h"
#include "CoverageViewOptions.h"
namespace llvm {
@@ -22,16 +22,17 @@ namespace llvm {
/// \brief Displays the code coverage report.
class CoverageReport {
const CoverageViewOptions &Options;
- CoverageSummary &Summary;
+ std::unique_ptr<coverage::CoverageMapping> Coverage;
void render(const FileCoverageSummary &File, raw_ostream &OS);
void render(const FunctionCoverageSummary &Function, raw_ostream &OS);
public:
- CoverageReport(const CoverageViewOptions &Options, CoverageSummary &Summary)
- : Options(Options), Summary(Summary) {}
+ CoverageReport(const CoverageViewOptions &Options,
+ std::unique_ptr<coverage::CoverageMapping> Coverage)
+ : Options(Options), Coverage(std::move(Coverage)) {}
- void renderFunctionReports(raw_ostream &OS);
+ void renderFunctionReports(ArrayRef<std::string> Files, raw_ostream &OS);
void renderFileReports(raw_ostream &OS);
};
diff --git a/contrib/llvm/tools/llvm-cov/CoverageSummary.cpp b/contrib/llvm/tools/llvm-cov/CoverageSummary.cpp
deleted file mode 100644
index 059c8c8..0000000
--- a/contrib/llvm/tools/llvm-cov/CoverageSummary.cpp
+++ /dev/null
@@ -1,64 +0,0 @@
-//===- CoverageSummary.cpp - Code coverage summary ------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This class implements data management and rendering for the code coverage
-// summaries of all files and functions.
-//
-//===----------------------------------------------------------------------===//
-
-#include "CoverageSummary.h"
-#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/Format.h"
-
-using namespace llvm;
-
-unsigned CoverageSummary::getFileID(StringRef Filename) {
- for (unsigned I = 0, E = Filenames.size(); I < E; ++I) {
- if (sys::fs::equivalent(Filenames[I], Filename))
- return I;
- }
- Filenames.push_back(Filename);
- return Filenames.size() - 1;
-}
-
-void
-CoverageSummary::createSummaries(const coverage::CoverageMapping &Coverage) {
- for (StringRef Filename : Coverage.getUniqueSourceFiles()) {
- size_t PrevSize = FunctionSummaries.size();
- for (const auto &F : Coverage.getCoveredFunctions(Filename))
- FunctionSummaries.push_back(FunctionCoverageSummary::get(F));
- size_t Count = FunctionSummaries.size() - PrevSize;
- if (Count == 0)
- continue;
- FileSummaries.push_back(FileCoverageSummary::get(
- Filename, makeArrayRef(FunctionSummaries.data() + PrevSize, Count)));
- }
-}
-
-FileCoverageSummary CoverageSummary::getCombinedFileSummaries() {
- size_t NumRegions = 0, CoveredRegions = 0;
- size_t NumLines = 0, NonCodeLines = 0, CoveredLines = 0;
- size_t NumFunctionsExecuted = 0, NumFunctions = 0;
- for (const auto &File : FileSummaries) {
- NumRegions += File.RegionCoverage.NumRegions;
- CoveredRegions += File.RegionCoverage.Covered;
-
- NumLines += File.LineCoverage.NumLines;
- NonCodeLines += File.LineCoverage.NonCodeLines;
- CoveredLines += File.LineCoverage.Covered;
-
- NumFunctionsExecuted += File.FunctionCoverage.Executed;
- NumFunctions += File.FunctionCoverage.NumFunctions;
- }
- return FileCoverageSummary(
- "TOTAL", RegionCoverageInfo(CoveredRegions, NumRegions),
- LineCoverageInfo(CoveredLines, NonCodeLines, NumLines),
- FunctionCoverageInfo(NumFunctionsExecuted, NumFunctions),
- None);
-}
diff --git a/contrib/llvm/tools/llvm-cov/CoverageSummary.h b/contrib/llvm/tools/llvm-cov/CoverageSummary.h
deleted file mode 100644
index 9dbebde..0000000
--- a/contrib/llvm/tools/llvm-cov/CoverageSummary.h
+++ /dev/null
@@ -1,45 +0,0 @@
-//===- CoverageSummary.h - Code coverage summary --------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This class implements data management and rendering for the code coverage
-// summaries of all files and functions.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_COV_COVERAGESUMMARY_H
-#define LLVM_COV_COVERAGESUMMARY_H
-
-#include "CoverageSummaryInfo.h"
-#include <vector>
-
-namespace llvm {
-
-/// \brief Manager for the function and file code coverage summaries.
-class CoverageSummary {
- std::vector<StringRef> Filenames;
- std::vector<FunctionCoverageSummary> FunctionSummaries;
- std::vector<std::pair<unsigned, unsigned>> FunctionSummariesFileIDs;
- std::vector<FileCoverageSummary> FileSummaries;
-
- unsigned getFileID(StringRef Filename);
-
-public:
- void createSummaries(const coverage::CoverageMapping &Coverage);
-
- ArrayRef<FileCoverageSummary> getFileSummaries() { return FileSummaries; }
-
- FileCoverageSummary getCombinedFileSummaries();
-
- void render(const FunctionCoverageSummary &Summary, raw_ostream &OS);
-
- void render(raw_ostream &OS);
-};
-}
-
-#endif // LLVM_COV_COVERAGESUMMARY_H
diff --git a/contrib/llvm/tools/llvm-cov/CoverageSummaryInfo.cpp b/contrib/llvm/tools/llvm-cov/CoverageSummaryInfo.cpp
index dd78ace..de89750 100644
--- a/contrib/llvm/tools/llvm-cov/CoverageSummaryInfo.cpp
+++ b/contrib/llvm/tools/llvm-cov/CoverageSummaryInfo.cpp
@@ -69,28 +69,3 @@ FunctionCoverageSummary::get(const coverage::FunctionRecord &Function) {
RegionCoverageInfo(CoveredRegions, NumCodeRegions),
LineCoverageInfo(CoveredLines, 0, NumLines));
}
-
-FileCoverageSummary
-FileCoverageSummary::get(StringRef Name,
- ArrayRef<FunctionCoverageSummary> FunctionSummaries) {
- size_t NumRegions = 0, CoveredRegions = 0;
- size_t NumLines = 0, NonCodeLines = 0, CoveredLines = 0;
- size_t NumFunctionsExecuted = 0;
- for (const auto &Func : FunctionSummaries) {
- CoveredRegions += Func.RegionCoverage.Covered;
- NumRegions += Func.RegionCoverage.NumRegions;
-
- CoveredLines += Func.LineCoverage.Covered;
- NonCodeLines += Func.LineCoverage.NonCodeLines;
- NumLines += Func.LineCoverage.NumLines;
-
- if (Func.ExecutionCount != 0)
- ++NumFunctionsExecuted;
- }
-
- return FileCoverageSummary(
- Name, RegionCoverageInfo(CoveredRegions, NumRegions),
- LineCoverageInfo(CoveredLines, NonCodeLines, NumLines),
- FunctionCoverageInfo(NumFunctionsExecuted, FunctionSummaries.size()),
- FunctionSummaries);
-}
diff --git a/contrib/llvm/tools/llvm-cov/CoverageSummaryInfo.h b/contrib/llvm/tools/llvm-cov/CoverageSummaryInfo.h
index 0036032..c393b00 100644
--- a/contrib/llvm/tools/llvm-cov/CoverageSummaryInfo.h
+++ b/contrib/llvm/tools/llvm-cov/CoverageSummaryInfo.h
@@ -31,10 +31,19 @@ struct RegionCoverageInfo {
/// \brief The total number of regions in a function/file.
size_t NumRegions;
+ RegionCoverageInfo() : Covered(0), NotCovered(0), NumRegions(0) {}
+
RegionCoverageInfo(size_t Covered, size_t NumRegions)
: Covered(Covered), NotCovered(NumRegions - Covered),
NumRegions(NumRegions) {}
+ RegionCoverageInfo &operator+=(const RegionCoverageInfo &RHS) {
+ Covered += RHS.Covered;
+ NotCovered += RHS.NotCovered;
+ NumRegions += RHS.NumRegions;
+ return *this;
+ }
+
bool isFullyCovered() const { return Covered == NumRegions; }
double getPercentCovered() const {
@@ -56,10 +65,21 @@ struct LineCoverageInfo {
/// \brief The total number of lines in a function/file.
size_t NumLines;
+ LineCoverageInfo()
+ : Covered(0), NotCovered(0), NonCodeLines(0), NumLines(0) {}
+
LineCoverageInfo(size_t Covered, size_t NumNonCodeLines, size_t NumLines)
: Covered(Covered), NotCovered(NumLines - NumNonCodeLines - Covered),
NonCodeLines(NumNonCodeLines), NumLines(NumLines) {}
+ LineCoverageInfo &operator+=(const LineCoverageInfo &RHS) {
+ Covered += RHS.Covered;
+ NotCovered += RHS.NotCovered;
+ NonCodeLines += RHS.NonCodeLines;
+ NumLines += RHS.NumLines;
+ return *this;
+ }
+
bool isFullyCovered() const { return Covered == (NumLines - NonCodeLines); }
double getPercentCovered() const {
@@ -75,9 +95,17 @@ struct FunctionCoverageInfo {
/// \brief The total number of functions in this file.
size_t NumFunctions;
+ FunctionCoverageInfo() : Executed(0), NumFunctions(0) {}
+
FunctionCoverageInfo(size_t Executed, size_t NumFunctions)
: Executed(Executed), NumFunctions(NumFunctions) {}
+ void addFunction(bool Covered) {
+ if (Covered)
+ ++Executed;
+ ++NumFunctions;
+ }
+
bool isFullyCovered() const { return Executed == NumFunctions; }
double getPercentCovered() const {
@@ -92,6 +120,8 @@ struct FunctionCoverageSummary {
RegionCoverageInfo RegionCoverage;
LineCoverageInfo LineCoverage;
+ FunctionCoverageSummary(StringRef Name) : Name(Name), ExecutionCount(0) {}
+
FunctionCoverageSummary(StringRef Name, uint64_t ExecutionCount,
const RegionCoverageInfo &RegionCoverage,
const LineCoverageInfo &LineCoverage)
@@ -111,21 +141,14 @@ struct FileCoverageSummary {
RegionCoverageInfo RegionCoverage;
LineCoverageInfo LineCoverage;
FunctionCoverageInfo FunctionCoverage;
- /// \brief The summary of every function
- /// in this file.
- ArrayRef<FunctionCoverageSummary> FunctionSummaries;
-
- FileCoverageSummary(StringRef Name, const RegionCoverageInfo &RegionCoverage,
- const LineCoverageInfo &LineCoverage,
- const FunctionCoverageInfo &FunctionCoverage,
- ArrayRef<FunctionCoverageSummary> FunctionSummaries)
- : Name(Name), RegionCoverage(RegionCoverage), LineCoverage(LineCoverage),
- FunctionCoverage(FunctionCoverage),
- FunctionSummaries(FunctionSummaries) {}
-
- /// \brief Compute the code coverage summary for a file.
- static FileCoverageSummary
- get(StringRef Name, ArrayRef<FunctionCoverageSummary> FunctionSummaries);
+
+ FileCoverageSummary(StringRef Name) : Name(Name) {}
+
+ void addFunction(const FunctionCoverageSummary &Function) {
+ RegionCoverage += Function.RegionCoverage;
+ LineCoverage += Function.LineCoverage;
+ FunctionCoverage.addFunction(/*Covered=*/Function.ExecutionCount > 0);
+ }
};
} // namespace llvm
diff --git a/contrib/llvm/tools/llvm-cov/RenderingSupport.h b/contrib/llvm/tools/llvm-cov/RenderingSupport.h
index 0271329..3ef155d 100644
--- a/contrib/llvm/tools/llvm-cov/RenderingSupport.h
+++ b/contrib/llvm/tools/llvm-cov/RenderingSupport.h
@@ -18,7 +18,7 @@ namespace llvm {
/// \brief A helper class that resets the output stream's color if needed
/// when destroyed.
class ColoredRawOstream {
- ColoredRawOstream(const ColoredRawOstream &OS) LLVM_DELETED_FUNCTION;
+ ColoredRawOstream(const ColoredRawOstream &OS) = delete;
public:
raw_ostream &OS;
diff --git a/contrib/llvm/tools/llvm-cov/SourceCoverageView.cpp b/contrib/llvm/tools/llvm-cov/SourceCoverageView.cpp
index 015099c..58c8a67 100644
--- a/contrib/llvm/tools/llvm-cov/SourceCoverageView.cpp
+++ b/contrib/llvm/tools/llvm-cov/SourceCoverageView.cpp
@@ -14,6 +14,7 @@
#include "SourceCoverageView.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/LineIterator.h"
using namespace llvm;
@@ -77,6 +78,22 @@ void SourceCoverageView::renderViewDivider(unsigned Level, unsigned Length,
OS << "-";
}
+/// Format a count using engineering notation with 3 significant digits.
+static std::string formatCount(uint64_t N) {
+ std::string Number = utostr(N);
+ int Len = Number.size();
+ if (Len <= 3)
+ return Number;
+ int IntLen = Len % 3 == 0 ? 3 : Len % 3;
+ std::string Result(Number.data(), IntLen);
+ if (IntLen != 3) {
+ Result.push_back('.');
+ Result += Number.substr(IntLen, 3 - IntLen);
+ }
+ Result.push_back(" kMGTPEZY"[(Len - 1) / 3]);
+ return Result;
+}
+
void
SourceCoverageView::renderLineCoverageColumn(raw_ostream &OS,
const LineCoverageInfo &Line) {
@@ -84,17 +101,11 @@ SourceCoverageView::renderLineCoverageColumn(raw_ostream &OS,
OS.indent(LineCoverageColumnWidth) << '|';
return;
}
- SmallString<32> Buffer;
- raw_svector_ostream BufferOS(Buffer);
- BufferOS << Line.ExecutionCount;
- auto Str = BufferOS.str();
- // Trim
- Str = Str.substr(0, std::min(Str.size(), (size_t)LineCoverageColumnWidth));
- // Align to the right
- OS.indent(LineCoverageColumnWidth - Str.size());
+ std::string C = formatCount(Line.ExecutionCount);
+ OS.indent(LineCoverageColumnWidth - C.size());
colored_ostream(OS, raw_ostream::MAGENTA,
Line.hasMultipleRegions() && Options.Colors)
- << Str;
+ << C;
OS << '|';
}
@@ -111,9 +122,6 @@ void SourceCoverageView::renderLineNumberColumn(raw_ostream &OS,
void SourceCoverageView::renderRegionMarkers(
raw_ostream &OS, ArrayRef<const coverage::CoverageSegment *> Segments) {
- SmallString<32> Buffer;
- raw_svector_ostream BufferOS(Buffer);
-
unsigned PrevColumn = 1;
for (const auto *S : Segments) {
if (!S->IsRegionEntry)
@@ -122,20 +130,16 @@ void SourceCoverageView::renderRegionMarkers(
if (S->Col > PrevColumn)
OS.indent(S->Col - PrevColumn);
PrevColumn = S->Col + 1;
- BufferOS << S->Count;
- StringRef Str = BufferOS.str();
- // Trim the execution count
- Str = Str.substr(0, std::min(Str.size(), (size_t)7));
- PrevColumn += Str.size();
- OS << '^' << Str;
- Buffer.clear();
+ std::string C = formatCount(S->Count);
+ PrevColumn += C.size();
+ OS << '^' << C;
}
OS << "\n";
if (Options.Debug)
for (const auto *S : Segments)
- errs() << "Marker at " << S->Line << ":" << S->Col << " = " << S->Count
- << (S->IsRegionEntry ? "\n" : " (pop)\n");
+ errs() << "Marker at " << S->Line << ":" << S->Col << " = "
+ << formatCount(S->Count) << (S->IsRegionEntry ? "\n" : " (pop)\n");
}
void SourceCoverageView::render(raw_ostream &OS, bool WholeFile,
diff --git a/contrib/llvm/tools/llvm-cov/SourceCoverageView.h b/contrib/llvm/tools/llvm-cov/SourceCoverageView.h
index d92a748..9e6fe5f 100644
--- a/contrib/llvm/tools/llvm-cov/SourceCoverageView.h
+++ b/contrib/llvm/tools/llvm-cov/SourceCoverageView.h
@@ -90,15 +90,14 @@ private:
bool hasMultipleRegions() const { return RegionCount > 1; }
void addRegionStartCount(uint64_t Count) {
- Mapped = true;
- ExecutionCount = Count;
+ // The max of all region starts is the most interesting value.
+ addRegionCount(RegionCount ? std::max(ExecutionCount, Count) : Count);
++RegionCount;
}
void addRegionCount(uint64_t Count) {
Mapped = true;
- if (!RegionCount)
- ExecutionCount = Count;
+ ExecutionCount = Count;
}
};
diff --git a/contrib/llvm/tools/llvm-cov/gcov.cpp b/contrib/llvm/tools/llvm-cov/gcov.cpp
index 12011ce..4377a50 100644
--- a/contrib/llvm/tools/llvm-cov/gcov.cpp
+++ b/contrib/llvm/tools/llvm-cov/gcov.cpp
@@ -23,9 +23,10 @@
#include <system_error>
using namespace llvm;
-void reportCoverage(StringRef SourceFile, StringRef ObjectDir,
- const std::string &InputGCNO, const std::string &InputGCDA,
- bool DumpGCOV, const GCOVOptions &Options) {
+static void reportCoverage(StringRef SourceFile, StringRef ObjectDir,
+ const std::string &InputGCNO,
+ const std::string &InputGCDA, bool DumpGCOV,
+ const GCOVOptions &Options) {
SmallString<128> CoverageFileStem(ObjectDir);
if (CoverageFileStem.empty()) {
// If no directory was specified with -o, look next to the source file.
@@ -80,7 +81,7 @@ void reportCoverage(StringRef SourceFile, StringRef ObjectDir,
FileInfo FI(Options);
GF.collectLineCounts(FI);
- FI.print(SourceFile, GCNO, GCDA);
+ FI.print(llvm::outs(), SourceFile, GCNO, GCDA);
}
int gcovMain(int argc, const char *argv[]) {
diff --git a/contrib/llvm/tools/llvm-cov/llvm-cov.cpp b/contrib/llvm/tools/llvm-cov/llvm-cov.cpp
index 86ec26d..bf66f58 100644
--- a/contrib/llvm/tools/llvm-cov/llvm-cov.cpp
+++ b/contrib/llvm/tools/llvm-cov/llvm-cov.cpp
@@ -14,6 +14,7 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/Path.h"
+#include "llvm/Support/Process.h"
#include "llvm/Support/raw_ostream.h"
#include <string>
@@ -32,9 +33,13 @@ int convertForTestingMain(int argc, const char *argv[]);
int gcovMain(int argc, const char *argv[]);
/// \brief Top level help.
-int helpMain(int argc, const char *argv[]) {
- errs() << "OVERVIEW: LLVM code coverage tool\n\n"
- << "USAGE: llvm-cov {gcov|report|show}\n";
+static int helpMain(int argc, const char *argv[]) {
+ errs() << "Usage: llvm-cov {gcov|report|show} [OPTION]...\n\n"
+ << "Shows code coverage information.\n\n"
+ << "Subcommands:\n"
+ << " gcov: Work with the gcov format.\n"
+ << " show: Annotate source files using instrprof style coverage.\n"
+ << " report: Summarize instrprof style coverage information.\n";
return 0;
}
@@ -61,18 +66,13 @@ int main(int argc, const char **argv) {
}
}
- // Give a warning and fall back to gcov
- errs().changeColor(raw_ostream::RED);
- errs() << "warning:";
- // Assume that argv[1] wasn't a command when it stats with a '-' or is a
- // filename (i.e. contains a '.')
- if (argc > 1 && !StringRef(argv[1]).startswith("-") &&
- StringRef(argv[1]).find(".") == StringRef::npos)
- errs() << " Unrecognized command '" << argv[1] << "'.";
- errs() << " Using the gcov compatible mode "
- "(this behaviour may be dropped in the future).";
- errs().resetColor();
- errs() << "\n";
-
- return gcovMain(argc, argv);
+ if (argc > 1) {
+ if (sys::Process::StandardErrHasColors())
+ errs().changeColor(raw_ostream::RED);
+ errs() << "Unrecognized command: " << argv[1] << ".\n\n";
+ if (sys::Process::StandardErrHasColors())
+ errs().resetColor();
+ }
+ helpMain(argc, argv);
+ return 1;
}
diff --git a/contrib/llvm/tools/llvm-cxxdump/Error.cpp b/contrib/llvm/tools/llvm-cxxdump/Error.cpp
new file mode 100644
index 0000000..16fed96
--- /dev/null
+++ b/contrib/llvm/tools/llvm-cxxdump/Error.cpp
@@ -0,0 +1,43 @@
+//===- Error.cxx - system_error extensions for llvm-cxxdump -----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This defines a new error_category for the llvm-cxxdump tool.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Error.h"
+#include "llvm/Support/ErrorHandling.h"
+
+using namespace llvm;
+
+namespace {
+class cxxdump_error_category : public std::error_category {
+public:
+ const char *name() const LLVM_NOEXCEPT override { return "llvm.cxxdump"; }
+ std::string message(int ev) const override {
+ switch (static_cast<cxxdump_error>(ev)) {
+ case cxxdump_error::success:
+ return "Success";
+ case cxxdump_error::file_not_found:
+ return "No such file.";
+ case cxxdump_error::unrecognized_file_format:
+ return "Unrecognized file type.";
+ }
+ llvm_unreachable(
+ "An enumerator of cxxdump_error does not have a message defined.");
+ }
+};
+} // namespace
+
+namespace llvm {
+const std::error_category &cxxdump_category() {
+ static cxxdump_error_category o;
+ return o;
+}
+} // namespace llvm
diff --git a/contrib/llvm/tools/llvm-cxxdump/Error.h b/contrib/llvm/tools/llvm-cxxdump/Error.h
new file mode 100644
index 0000000..7caf6d6
--- /dev/null
+++ b/contrib/llvm/tools/llvm-cxxdump/Error.h
@@ -0,0 +1,39 @@
+//===- Error.h - system_error extensions for llvm-cxxdump -------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This declares a new error_category for the llvm-cxxdump tool.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVM_CXXDUMP_ERROR_H
+#define LLVM_TOOLS_LLVM_CXXDUMP_ERROR_H
+
+#include <system_error>
+
+namespace llvm {
+const std::error_category &cxxdump_category();
+
+enum class cxxdump_error {
+ success = 0,
+ file_not_found,
+ unrecognized_file_format,
+};
+
+inline std::error_code make_error_code(cxxdump_error e) {
+ return std::error_code(static_cast<int>(e), cxxdump_category());
+}
+
+} // namespace llvm
+
+namespace std {
+template <>
+struct is_error_code_enum<llvm::cxxdump_error> : std::true_type {};
+}
+
+#endif
diff --git a/contrib/llvm/tools/llvm-cxxdump/llvm-cxxdump.cpp b/contrib/llvm/tools/llvm-cxxdump/llvm-cxxdump.cpp
new file mode 100644
index 0000000..447d55a
--- /dev/null
+++ b/contrib/llvm/tools/llvm-cxxdump/llvm-cxxdump.cpp
@@ -0,0 +1,569 @@
+//===- llvm-cxxdump.cpp - Dump C++ data in an Object File -------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Dumps C++ data resident in object files and archives.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm-cxxdump.h"
+#include "Error.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/Object/Archive.h"
+#include "llvm/Object/ObjectFile.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/PrettyStackTrace.h"
+#include "llvm/Support/Signals.h"
+#include "llvm/Support/TargetRegistry.h"
+#include "llvm/Support/TargetSelect.h"
+#include "llvm/Support/raw_ostream.h"
+#include <map>
+#include <string>
+#include <system_error>
+
+using namespace llvm;
+using namespace llvm::object;
+using namespace llvm::support;
+
+namespace opts {
+cl::list<std::string> InputFilenames(cl::Positional,
+ cl::desc("<input object files>"),
+ cl::ZeroOrMore);
+} // namespace opts
+
+static int ReturnValue = EXIT_SUCCESS;
+
+namespace llvm {
+
+static bool error(std::error_code EC) {
+ if (!EC)
+ return false;
+
+ ReturnValue = EXIT_FAILURE;
+ outs() << "\nError reading file: " << EC.message() << ".\n";
+ outs().flush();
+ return true;
+}
+
+} // namespace llvm
+
+static void reportError(StringRef Input, StringRef Message) {
+ if (Input == "-")
+ Input = "<stdin>";
+
+ errs() << Input << ": " << Message << "\n";
+ errs().flush();
+ ReturnValue = EXIT_FAILURE;
+}
+
+static void reportError(StringRef Input, std::error_code EC) {
+ reportError(Input, EC.message());
+}
+
+static SmallVectorImpl<SectionRef> &getRelocSections(const ObjectFile *Obj,
+ const SectionRef &Sec) {
+ static bool MappingDone = false;
+ static std::map<SectionRef, SmallVector<SectionRef, 1>> SectionRelocMap;
+ if (!MappingDone) {
+ for (const SectionRef &Section : Obj->sections()) {
+ section_iterator Sec2 = Section.getRelocatedSection();
+ if (Sec2 != Obj->section_end())
+ SectionRelocMap[*Sec2].push_back(Section);
+ }
+ MappingDone = true;
+ }
+ return SectionRelocMap[Sec];
+}
+
+static bool collectRelocatedSymbols(const ObjectFile *Obj,
+ const SectionRef &Sec, uint64_t SecAddress,
+ uint64_t SymAddress, uint64_t SymSize,
+ StringRef *I, StringRef *E) {
+ uint64_t SymOffset = SymAddress - SecAddress;
+ uint64_t SymEnd = SymOffset + SymSize;
+ for (const SectionRef &SR : getRelocSections(Obj, Sec)) {
+ for (const object::RelocationRef &Reloc : SR.relocations()) {
+ if (I == E)
+ break;
+ const object::symbol_iterator RelocSymI = Reloc.getSymbol();
+ if (RelocSymI == Obj->symbol_end())
+ continue;
+ StringRef RelocSymName;
+ if (error(RelocSymI->getName(RelocSymName)))
+ return true;
+ uint64_t Offset;
+ if (error(Reloc.getOffset(Offset)))
+ return true;
+ if (Offset >= SymOffset && Offset < SymEnd) {
+ *I = RelocSymName;
+ ++I;
+ }
+ }
+ }
+ return false;
+}
+
+static bool collectRelocationOffsets(
+ const ObjectFile *Obj, const SectionRef &Sec, uint64_t SecAddress,
+ uint64_t SymAddress, uint64_t SymSize, StringRef SymName,
+ std::map<std::pair<StringRef, uint64_t>, StringRef> &Collection) {
+ uint64_t SymOffset = SymAddress - SecAddress;
+ uint64_t SymEnd = SymOffset + SymSize;
+ for (const SectionRef &SR : getRelocSections(Obj, Sec)) {
+ for (const object::RelocationRef &Reloc : SR.relocations()) {
+ const object::symbol_iterator RelocSymI = Reloc.getSymbol();
+ if (RelocSymI == Obj->symbol_end())
+ continue;
+ StringRef RelocSymName;
+ if (error(RelocSymI->getName(RelocSymName)))
+ return true;
+ uint64_t Offset;
+ if (error(Reloc.getOffset(Offset)))
+ return true;
+ if (Offset >= SymOffset && Offset < SymEnd)
+ Collection[std::make_pair(SymName, Offset - SymOffset)] = RelocSymName;
+ }
+ }
+ return false;
+}
+
+static void dumpCXXData(const ObjectFile *Obj) {
+ struct CompleteObjectLocator {
+ StringRef Symbols[2];
+ ArrayRef<little32_t> Data;
+ };
+ struct ClassHierarchyDescriptor {
+ StringRef Symbols[1];
+ ArrayRef<little32_t> Data;
+ };
+ struct BaseClassDescriptor {
+ StringRef Symbols[2];
+ ArrayRef<little32_t> Data;
+ };
+ struct TypeDescriptor {
+ StringRef Symbols[1];
+ uint64_t AlwaysZero;
+ StringRef MangledName;
+ };
+ struct ThrowInfo {
+ uint32_t Flags;
+ };
+ struct CatchableTypeArray {
+ uint32_t NumEntries;
+ };
+ struct CatchableType {
+ uint32_t Flags;
+ uint32_t NonVirtualBaseAdjustmentOffset;
+ int32_t VirtualBasePointerOffset;
+ uint32_t VirtualBaseAdjustmentOffset;
+ uint32_t Size;
+ StringRef Symbols[2];
+ };
+ std::map<std::pair<StringRef, uint64_t>, StringRef> VFTableEntries;
+ std::map<std::pair<StringRef, uint64_t>, StringRef> TIEntries;
+ std::map<std::pair<StringRef, uint64_t>, StringRef> CTAEntries;
+ std::map<StringRef, ArrayRef<little32_t>> VBTables;
+ std::map<StringRef, CompleteObjectLocator> COLs;
+ std::map<StringRef, ClassHierarchyDescriptor> CHDs;
+ std::map<std::pair<StringRef, uint64_t>, StringRef> BCAEntries;
+ std::map<StringRef, BaseClassDescriptor> BCDs;
+ std::map<StringRef, TypeDescriptor> TDs;
+ std::map<StringRef, ThrowInfo> TIs;
+ std::map<StringRef, CatchableTypeArray> CTAs;
+ std::map<StringRef, CatchableType> CTs;
+
+ std::map<std::pair<StringRef, uint64_t>, StringRef> VTableSymEntries;
+ std::map<std::pair<StringRef, uint64_t>, int64_t> VTableDataEntries;
+ std::map<std::pair<StringRef, uint64_t>, StringRef> VTTEntries;
+ std::map<StringRef, StringRef> TINames;
+
+ uint8_t BytesInAddress = Obj->getBytesInAddress();
+
+ for (const object::SymbolRef &Sym : Obj->symbols()) {
+ StringRef SymName;
+ if (error(Sym.getName(SymName)))
+ return;
+ object::section_iterator SecI(Obj->section_begin());
+ if (error(Sym.getSection(SecI)))
+ return;
+ // Skip external symbols.
+ if (SecI == Obj->section_end())
+ continue;
+ const SectionRef &Sec = *SecI;
+ // Skip virtual or BSS sections.
+ if (Sec.isBSS() || Sec.isVirtual())
+ continue;
+ StringRef SecContents;
+ if (error(Sec.getContents(SecContents)))
+ return;
+ uint64_t SymAddress, SymSize;
+ if (error(Sym.getAddress(SymAddress)) || error(Sym.getSize(SymSize)))
+ return;
+ uint64_t SecAddress = Sec.getAddress();
+ uint64_t SecSize = Sec.getSize();
+ uint64_t SymOffset = SymAddress - SecAddress;
+ StringRef SymContents = SecContents.substr(SymOffset, SymSize);
+
+ // VFTables in the MS-ABI start with '??_7' and are contained within their
+ // own COMDAT section. We then determine the contents of the VFTable by
+ // looking at each relocation in the section.
+ if (SymName.startswith("??_7")) {
+ // Each relocation either names a virtual method or a thunk. We note the
+ // offset into the section and the symbol used for the relocation.
+ collectRelocationOffsets(Obj, Sec, SecAddress, SecAddress, SecSize,
+ SymName, VFTableEntries);
+ }
+ // VBTables in the MS-ABI start with '??_8' and are filled with 32-bit
+ // offsets of virtual bases.
+ else if (SymName.startswith("??_8")) {
+ ArrayRef<little32_t> VBTableData(
+ reinterpret_cast<const little32_t *>(SymContents.data()),
+ SymContents.size() / sizeof(little32_t));
+ VBTables[SymName] = VBTableData;
+ }
+ // Complete object locators in the MS-ABI start with '??_R4'
+ else if (SymName.startswith("??_R4")) {
+ CompleteObjectLocator COL;
+ COL.Data = ArrayRef<little32_t>(
+ reinterpret_cast<const little32_t *>(SymContents.data()), 3);
+ StringRef *I = std::begin(COL.Symbols), *E = std::end(COL.Symbols);
+ if (collectRelocatedSymbols(Obj, Sec, SecAddress, SymAddress, SymSize, I,
+ E))
+ return;
+ COLs[SymName] = COL;
+ }
+ // Class hierarchy descriptors in the MS-ABI start with '??_R3'
+ else if (SymName.startswith("??_R3")) {
+ ClassHierarchyDescriptor CHD;
+ CHD.Data = ArrayRef<little32_t>(
+ reinterpret_cast<const little32_t *>(SymContents.data()), 3);
+ StringRef *I = std::begin(CHD.Symbols), *E = std::end(CHD.Symbols);
+ if (collectRelocatedSymbols(Obj, Sec, SecAddress, SymAddress, SymSize, I,
+ E))
+ return;
+ CHDs[SymName] = CHD;
+ }
+ // Class hierarchy descriptors in the MS-ABI start with '??_R2'
+ else if (SymName.startswith("??_R2")) {
+ // Each relocation names a base class descriptor. We note the offset into
+ // the section and the symbol used for the relocation.
+ collectRelocationOffsets(Obj, Sec, SecAddress, SymAddress, SymSize,
+ SymName, BCAEntries);
+ }
+ // Base class descriptors in the MS-ABI start with '??_R1'
+ else if (SymName.startswith("??_R1")) {
+ BaseClassDescriptor BCD;
+ BCD.Data = ArrayRef<little32_t>(
+ reinterpret_cast<const little32_t *>(SymContents.data()) + 1, 5);
+ StringRef *I = std::begin(BCD.Symbols), *E = std::end(BCD.Symbols);
+ if (collectRelocatedSymbols(Obj, Sec, SecAddress, SymAddress, SymSize, I,
+ E))
+ return;
+ BCDs[SymName] = BCD;
+ }
+ // Type descriptors in the MS-ABI start with '??_R0'
+ else if (SymName.startswith("??_R0")) {
+ const char *DataPtr = SymContents.drop_front(BytesInAddress).data();
+ TypeDescriptor TD;
+ if (BytesInAddress == 8)
+ TD.AlwaysZero = *reinterpret_cast<const little64_t *>(DataPtr);
+ else
+ TD.AlwaysZero = *reinterpret_cast<const little32_t *>(DataPtr);
+ TD.MangledName = SymContents.drop_front(BytesInAddress * 2);
+ StringRef *I = std::begin(TD.Symbols), *E = std::end(TD.Symbols);
+ if (collectRelocatedSymbols(Obj, Sec, SecAddress, SymAddress, SymSize, I,
+ E))
+ return;
+ TDs[SymName] = TD;
+ }
+ // Throw descriptors in the MS-ABI start with '_TI'
+ else if (SymName.startswith("_TI") || SymName.startswith("__TI")) {
+ ThrowInfo TI;
+ TI.Flags = *reinterpret_cast<const little32_t *>(SymContents.data());
+ collectRelocationOffsets(Obj, Sec, SecAddress, SymAddress, SymSize,
+ SymName, TIEntries);
+ TIs[SymName] = TI;
+ }
+ // Catchable type arrays in the MS-ABI start with _CTA or __CTA.
+ else if (SymName.startswith("_CTA") || SymName.startswith("__CTA")) {
+ CatchableTypeArray CTA;
+ CTA.NumEntries =
+ *reinterpret_cast<const little32_t *>(SymContents.data());
+ collectRelocationOffsets(Obj, Sec, SecAddress, SymAddress, SymSize,
+ SymName, CTAEntries);
+ CTAs[SymName] = CTA;
+ }
+ // Catchable types in the MS-ABI start with _CT or __CT.
+ else if (SymName.startswith("_CT") || SymName.startswith("__CT")) {
+ const little32_t *DataPtr =
+ reinterpret_cast<const little32_t *>(SymContents.data());
+ CatchableType CT;
+ CT.Flags = DataPtr[0];
+ CT.NonVirtualBaseAdjustmentOffset = DataPtr[2];
+ CT.VirtualBasePointerOffset = DataPtr[3];
+ CT.VirtualBaseAdjustmentOffset = DataPtr[4];
+ CT.Size = DataPtr[5];
+ StringRef *I = std::begin(CT.Symbols), *E = std::end(CT.Symbols);
+ if (collectRelocatedSymbols(Obj, Sec, SecAddress, SymAddress, SymSize, I,
+ E))
+ return;
+ CTs[SymName] = CT;
+ }
+ // Construction vtables in the Itanium ABI start with '_ZTT' or '__ZTT'.
+ else if (SymName.startswith("_ZTT") || SymName.startswith("__ZTT")) {
+ collectRelocationOffsets(Obj, Sec, SecAddress, SymAddress, SymSize,
+ SymName, VTTEntries);
+ }
+ // Typeinfo names in the Itanium ABI start with '_ZTS' or '__ZTS'.
+ else if (SymName.startswith("_ZTS") || SymName.startswith("__ZTS")) {
+ TINames[SymName] = SymContents.slice(0, SymContents.find('\0'));
+ }
+ // Vtables in the Itanium ABI start with '_ZTV' or '__ZTV'.
+ else if (SymName.startswith("_ZTV") || SymName.startswith("__ZTV")) {
+ collectRelocationOffsets(Obj, Sec, SecAddress, SymAddress, SymSize,
+ SymName, VTableSymEntries);
+ for (uint64_t SymOffI = 0; SymOffI < SymSize; SymOffI += BytesInAddress) {
+ auto Key = std::make_pair(SymName, SymOffI);
+ if (VTableSymEntries.count(Key))
+ continue;
+ const char *DataPtr =
+ SymContents.substr(SymOffI, BytesInAddress).data();
+ int64_t VData;
+ if (BytesInAddress == 8)
+ VData = *reinterpret_cast<const little64_t *>(DataPtr);
+ else
+ VData = *reinterpret_cast<const little32_t *>(DataPtr);
+ VTableDataEntries[Key] = VData;
+ }
+ }
+ // Typeinfo structures in the Itanium ABI start with '_ZTI' or '__ZTI'.
+ else if (SymName.startswith("_ZTI") || SymName.startswith("__ZTI")) {
+ // FIXME: Do something with these!
+ }
+ }
+ for (const auto &VFTableEntry : VFTableEntries) {
+ StringRef VFTableName = VFTableEntry.first.first;
+ uint64_t Offset = VFTableEntry.first.second;
+ StringRef SymName = VFTableEntry.second;
+ outs() << VFTableName << '[' << Offset << "]: " << SymName << '\n';
+ }
+ for (const auto &VBTable : VBTables) {
+ StringRef VBTableName = VBTable.first;
+ uint32_t Idx = 0;
+ for (little32_t Offset : VBTable.second) {
+ outs() << VBTableName << '[' << Idx << "]: " << Offset << '\n';
+ Idx += sizeof(Offset);
+ }
+ }
+ for (const auto &COLPair : COLs) {
+ StringRef COLName = COLPair.first;
+ const CompleteObjectLocator &COL = COLPair.second;
+ outs() << COLName << "[IsImageRelative]: " << COL.Data[0] << '\n';
+ outs() << COLName << "[OffsetToTop]: " << COL.Data[1] << '\n';
+ outs() << COLName << "[VFPtrOffset]: " << COL.Data[2] << '\n';
+ outs() << COLName << "[TypeDescriptor]: " << COL.Symbols[0] << '\n';
+ outs() << COLName << "[ClassHierarchyDescriptor]: " << COL.Symbols[1]
+ << '\n';
+ }
+ for (const auto &CHDPair : CHDs) {
+ StringRef CHDName = CHDPair.first;
+ const ClassHierarchyDescriptor &CHD = CHDPair.second;
+ outs() << CHDName << "[AlwaysZero]: " << CHD.Data[0] << '\n';
+ outs() << CHDName << "[Flags]: " << CHD.Data[1] << '\n';
+ outs() << CHDName << "[NumClasses]: " << CHD.Data[2] << '\n';
+ outs() << CHDName << "[BaseClassArray]: " << CHD.Symbols[0] << '\n';
+ }
+ for (const auto &BCAEntry : BCAEntries) {
+ StringRef BCAName = BCAEntry.first.first;
+ uint64_t Offset = BCAEntry.first.second;
+ StringRef SymName = BCAEntry.second;
+ outs() << BCAName << '[' << Offset << "]: " << SymName << '\n';
+ }
+ for (const auto &BCDPair : BCDs) {
+ StringRef BCDName = BCDPair.first;
+ const BaseClassDescriptor &BCD = BCDPair.second;
+ outs() << BCDName << "[TypeDescriptor]: " << BCD.Symbols[0] << '\n';
+ outs() << BCDName << "[NumBases]: " << BCD.Data[0] << '\n';
+ outs() << BCDName << "[OffsetInVBase]: " << BCD.Data[1] << '\n';
+ outs() << BCDName << "[VBPtrOffset]: " << BCD.Data[2] << '\n';
+ outs() << BCDName << "[OffsetInVBTable]: " << BCD.Data[3] << '\n';
+ outs() << BCDName << "[Flags]: " << BCD.Data[4] << '\n';
+ outs() << BCDName << "[ClassHierarchyDescriptor]: " << BCD.Symbols[1]
+ << '\n';
+ }
+ for (const auto &TDPair : TDs) {
+ StringRef TDName = TDPair.first;
+ const TypeDescriptor &TD = TDPair.second;
+ outs() << TDName << "[VFPtr]: " << TD.Symbols[0] << '\n';
+ outs() << TDName << "[AlwaysZero]: " << TD.AlwaysZero << '\n';
+ outs() << TDName << "[MangledName]: ";
+ outs().write_escaped(TD.MangledName.rtrim(StringRef("\0", 1)),
+ /*UseHexEscapes=*/true)
+ << '\n';
+ }
+ for (const auto &TIPair : TIs) {
+ StringRef TIName = TIPair.first;
+ const ThrowInfo &TI = TIPair.second;
+ auto dumpThrowInfoFlag = [&](const char *Name, uint32_t Flag) {
+ outs() << TIName << "[Flags." << Name
+ << "]: " << (TI.Flags & Flag ? "true" : "false") << '\n';
+ };
+ auto dumpThrowInfoSymbol = [&](const char *Name, int Offset) {
+ outs() << TIName << '[' << Name << "]: ";
+ auto Entry = TIEntries.find(std::make_pair(TIName, Offset));
+ outs() << (Entry == TIEntries.end() ? "null" : Entry->second) << '\n';
+ };
+ outs() << TIName << "[Flags]: " << TI.Flags << '\n';
+ dumpThrowInfoFlag("Const", 1);
+ dumpThrowInfoFlag("Volatile", 2);
+ dumpThrowInfoSymbol("CleanupFn", 4);
+ dumpThrowInfoSymbol("ForwardCompat", 8);
+ dumpThrowInfoSymbol("CatchableTypeArray", 12);
+ }
+ for (const auto &CTAPair : CTAs) {
+ StringRef CTAName = CTAPair.first;
+ const CatchableTypeArray &CTA = CTAPair.second;
+
+ outs() << CTAName << "[NumEntries]: " << CTA.NumEntries << '\n';
+
+ unsigned Idx = 0;
+ for (auto I = CTAEntries.lower_bound(std::make_pair(CTAName, 0)),
+ E = CTAEntries.upper_bound(std::make_pair(CTAName, UINT64_MAX));
+ I != E; ++I)
+ outs() << CTAName << '[' << Idx++ << "]: " << I->second << '\n';
+ }
+ for (const auto &CTPair : CTs) {
+ StringRef CTName = CTPair.first;
+ const CatchableType &CT = CTPair.second;
+ auto dumpCatchableTypeFlag = [&](const char *Name, uint32_t Flag) {
+ outs() << CTName << "[Flags." << Name
+ << "]: " << (CT.Flags & Flag ? "true" : "false") << '\n';
+ };
+ outs() << CTName << "[Flags]: " << CT.Flags << '\n';
+ dumpCatchableTypeFlag("ScalarType", 1);
+ dumpCatchableTypeFlag("VirtualInheritance", 4);
+ outs() << CTName << "[TypeDescriptor]: " << CT.Symbols[0] << '\n';
+ outs() << CTName << "[NonVirtualBaseAdjustmentOffset]: "
+ << CT.NonVirtualBaseAdjustmentOffset << '\n';
+ outs() << CTName
+ << "[VirtualBasePointerOffset]: " << CT.VirtualBasePointerOffset
+ << '\n';
+ outs() << CTName << "[VirtualBaseAdjustmentOffset]: "
+ << CT.VirtualBaseAdjustmentOffset << '\n';
+ outs() << CTName << "[Size]: " << CT.Size << '\n';
+ outs() << CTName
+ << "[CopyCtor]: " << (CT.Symbols[1].empty() ? "null" : CT.Symbols[1])
+ << '\n';
+ }
+ for (const auto &VTTPair : VTTEntries) {
+ StringRef VTTName = VTTPair.first.first;
+ uint64_t VTTOffset = VTTPair.first.second;
+ StringRef VTTEntry = VTTPair.second;
+ outs() << VTTName << '[' << VTTOffset << "]: " << VTTEntry << '\n';
+ }
+ for (const auto &TIPair : TINames) {
+ StringRef TIName = TIPair.first;
+ outs() << TIName << ": " << TIPair.second << '\n';
+ }
+ auto VTableSymI = VTableSymEntries.begin();
+ auto VTableSymE = VTableSymEntries.end();
+ auto VTableDataI = VTableDataEntries.begin();
+ auto VTableDataE = VTableDataEntries.end();
+ for (;;) {
+ bool SymDone = VTableSymI == VTableSymE;
+ bool DataDone = VTableDataI == VTableDataE;
+ if (SymDone && DataDone)
+ break;
+ if (!SymDone && (DataDone || VTableSymI->first < VTableDataI->first)) {
+ StringRef VTableName = VTableSymI->first.first;
+ uint64_t Offset = VTableSymI->first.second;
+ StringRef VTableEntry = VTableSymI->second;
+ outs() << VTableName << '[' << Offset << "]: ";
+ outs() << VTableEntry;
+ outs() << '\n';
+ ++VTableSymI;
+ continue;
+ }
+ if (!DataDone && (SymDone || VTableDataI->first < VTableSymI->first)) {
+ StringRef VTableName = VTableDataI->first.first;
+ uint64_t Offset = VTableDataI->first.second;
+ int64_t VTableEntry = VTableDataI->second;
+ outs() << VTableName << '[' << Offset << "]: ";
+ outs() << VTableEntry;
+ outs() << '\n';
+ ++VTableDataI;
+ continue;
+ }
+ }
+}
+
+static void dumpArchive(const Archive *Arc) {
+ for (const Archive::Child &ArcC : Arc->children()) {
+ ErrorOr<std::unique_ptr<Binary>> ChildOrErr = ArcC.getAsBinary();
+ if (std::error_code EC = ChildOrErr.getError()) {
+ // Ignore non-object files.
+ if (EC != object_error::invalid_file_type)
+ reportError(Arc->getFileName(), EC.message());
+ continue;
+ }
+
+ if (ObjectFile *Obj = dyn_cast<ObjectFile>(&*ChildOrErr.get()))
+ dumpCXXData(Obj);
+ else
+ reportError(Arc->getFileName(), cxxdump_error::unrecognized_file_format);
+ }
+}
+
+static void dumpInput(StringRef File) {
+ // If file isn't stdin, check that it exists.
+ if (File != "-" && !sys::fs::exists(File)) {
+ reportError(File, cxxdump_error::file_not_found);
+ return;
+ }
+
+ // Attempt to open the binary.
+ ErrorOr<OwningBinary<Binary>> BinaryOrErr = createBinary(File);
+ if (std::error_code EC = BinaryOrErr.getError()) {
+ reportError(File, EC);
+ return;
+ }
+ Binary &Binary = *BinaryOrErr.get().getBinary();
+
+ if (Archive *Arc = dyn_cast<Archive>(&Binary))
+ dumpArchive(Arc);
+ else if (ObjectFile *Obj = dyn_cast<ObjectFile>(&Binary))
+ dumpCXXData(Obj);
+ else
+ reportError(File, cxxdump_error::unrecognized_file_format);
+}
+
+int main(int argc, const char *argv[]) {
+ sys::PrintStackTraceOnErrorSignal();
+ PrettyStackTraceProgram X(argc, argv);
+ llvm_shutdown_obj Y;
+
+ // Initialize targets.
+ llvm::InitializeAllTargetInfos();
+
+ // Register the target printer for --version.
+ cl::AddExtraVersionPrinter(TargetRegistry::printRegisteredTargetsForVersion);
+
+ cl::ParseCommandLineOptions(argc, argv, "LLVM C++ ABI Data Dumper\n");
+
+ // Default to stdin if no filename is specified.
+ if (opts::InputFilenames.size() == 0)
+ opts::InputFilenames.push_back("-");
+
+ std::for_each(opts::InputFilenames.begin(), opts::InputFilenames.end(),
+ dumpInput);
+
+ return ReturnValue;
+}
diff --git a/contrib/llvm/tools/llvm-cxxdump/llvm-cxxdump.h b/contrib/llvm/tools/llvm-cxxdump/llvm-cxxdump.h
new file mode 100644
index 0000000..daa05cb
--- /dev/null
+++ b/contrib/llvm/tools/llvm-cxxdump/llvm-cxxdump.h
@@ -0,0 +1,23 @@
+//===-- llvm-cxxdump.h ------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVM_CXXDUMP_LLVM_CXXDUMP_H
+#define LLVM_TOOLS_LLVM_CXXDUMP_LLVM_CXXDUMP_H
+
+#include "llvm/Support/CommandLine.h"
+#include <string>
+
+namespace opts {
+extern llvm::cl::list<std::string> InputFilenames;
+} // namespace opts
+
+#define LLVM_CXXDUMP_ENUM_ENT(ns, enum) \
+ { #enum, ns::enum }
+
+#endif
diff --git a/contrib/llvm/tools/llvm-dis/llvm-dis.cpp b/contrib/llvm/tools/llvm-dis/llvm-dis.cpp
index 1349ecc..26f14b9 100644
--- a/contrib/llvm/tools/llvm-dis/llvm-dis.cpp
+++ b/contrib/llvm/tools/llvm-dis/llvm-dis.cpp
@@ -54,16 +54,18 @@ static cl::opt<bool>
ShowAnnotations("show-annotations",
cl::desc("Add informational comments to the .ll file"));
+static cl::opt<bool> PreserveAssemblyUseListOrder(
+ "preserve-ll-uselistorder",
+ cl::desc("Preserve use-list order when writing LLVM assembly."),
+ cl::init(false), cl::Hidden);
+
namespace {
static void printDebugLoc(const DebugLoc &DL, formatted_raw_ostream &OS) {
OS << DL.getLine() << ":" << DL.getCol();
- if (MDNode *N = DL.getInlinedAt(getGlobalContext())) {
- DebugLoc IDL = DebugLoc::getFromDILocation(N);
- if (!IDL.isUnknown()) {
- OS << "@";
- printDebugLoc(IDL,OS);
- }
+ if (DILocation *IDL = DL.getInlinedAt()) {
+ OS << "@";
+ printDebugLoc(IDL, OS);
}
}
class CommentWriter : public AssemblyAnnotationWriter {
@@ -78,11 +80,11 @@ public:
if (!V.getType()->isVoidTy()) {
OS.PadToColumn(50);
Padded = true;
- OS << "; [#uses=" << V.getNumUses() << " type=" << *V.getType() << "]"; // Output # uses and type
+ // Output # uses and type
+ OS << "; [#uses=" << V.getNumUses() << " type=" << *V.getType() << "]";
}
if (const Instruction *I = dyn_cast<Instruction>(&V)) {
- const DebugLoc &DL = I->getDebugLoc();
- if (!DL.isUnknown()) {
+ if (const DebugLoc &DL = I->getDebugLoc()) {
if (!Padded) {
OS.PadToColumn(50);
Padded = true;
@@ -93,20 +95,18 @@ public:
OS << "]";
}
if (const DbgDeclareInst *DDI = dyn_cast<DbgDeclareInst>(I)) {
- DIVariable Var(DDI->getVariable());
if (!Padded) {
OS.PadToColumn(50);
OS << ";";
}
- OS << " [debug variable = " << Var.getName() << "]";
+ OS << " [debug variable = " << DDI->getVariable()->getName() << "]";
}
else if (const DbgValueInst *DVI = dyn_cast<DbgValueInst>(I)) {
- DIVariable Var(DVI->getVariable());
if (!Padded) {
OS.PadToColumn(50);
OS << ";";
}
- OS << " [debug variable = " << Var.getName() << "]";
+ OS << " [debug variable = " << DVI->getVariable()->getName() << "]";
}
}
}
@@ -115,14 +115,21 @@ public:
} // end anon namespace
static void diagnosticHandler(const DiagnosticInfo &DI, void *Context) {
- assert(DI.getSeverity() == DS_Error && "Only expecting errors");
-
raw_ostream &OS = errs();
OS << (char *)Context << ": ";
+ switch (DI.getSeverity()) {
+ case DS_Error: OS << "error: "; break;
+ case DS_Warning: OS << "warning: "; break;
+ case DS_Remark: OS << "remark: "; break;
+ case DS_Note: OS << "note: "; break;
+ }
+
DiagnosticPrinterRawOStream DP(OS);
DI.print(DP);
OS << '\n';
- exit(1);
+
+ if (DI.getSeverity() == DS_Error)
+ exit(1);
}
int main(int argc, char **argv) {
@@ -152,6 +159,9 @@ int main(int argc, char **argv) {
getStreamedBitcodeModule(DisplayFilename, Streamer, Context);
M = std::move(*MOrErr);
M->materializeAllPermanently();
+ } else {
+ errs() << argv[0] << ": " << ErrorMessage << '\n';
+ return 1;
}
// Just use stdout. We won't actually print anything on it.
@@ -162,13 +172,9 @@ int main(int argc, char **argv) {
if (InputFilename == "-") {
OutputFilename = "-";
} else {
- const std::string &IFN = InputFilename;
- int Len = IFN.length();
- // If the source ends in .bc, strip it off.
- if (IFN[Len-3] == '.' && IFN[Len-2] == 'b' && IFN[Len-1] == 'c')
- OutputFilename = std::string(IFN.begin(), IFN.end()-3)+".ll";
- else
- OutputFilename = IFN+".ll";
+ StringRef IFN = InputFilename;
+ OutputFilename = (IFN.endswith(".bc") ? IFN.drop_back(3) : IFN).str();
+ OutputFilename += ".ll";
}
}
@@ -186,7 +192,7 @@ int main(int argc, char **argv) {
// All that llvm-dis does is write the assembly to a file.
if (!DontPrint)
- M->print(Out->os(), Annotator.get());
+ M->print(Out->os(), Annotator.get(), PreserveAssemblyUseListOrder);
// Declare success.
Out->keep();
diff --git a/contrib/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp b/contrib/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp
new file mode 100644
index 0000000..c1cb021
--- /dev/null
+++ b/contrib/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp
@@ -0,0 +1,113 @@
+//===-- llvm-dwarfdump.cpp - Debug info dumping utility for llvm ----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This program is a utility that works like "dwarfdump".
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/DebugInfo/DIContext.h"
+#include "llvm/DebugInfo/DWARF/DWARFContext.h"
+#include "llvm/Object/ObjectFile.h"
+#include "llvm/Object/RelocVisitor.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/PrettyStackTrace.h"
+#include "llvm/Support/Signals.h"
+#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
+#include <cstring>
+#include <list>
+#include <string>
+#include <system_error>
+
+using namespace llvm;
+using namespace object;
+
+static cl::list<std::string>
+InputFilenames(cl::Positional, cl::desc("<input object files>"),
+ cl::ZeroOrMore);
+
+static cl::opt<DIDumpType>
+DumpType("debug-dump", cl::init(DIDT_All),
+ cl::desc("Dump of debug sections:"),
+ cl::values(
+ clEnumValN(DIDT_All, "all", "Dump all debug sections"),
+ clEnumValN(DIDT_Abbrev, "abbrev", ".debug_abbrev"),
+ clEnumValN(DIDT_AbbrevDwo, "abbrev.dwo", ".debug_abbrev.dwo"),
+ clEnumValN(DIDT_AppleNames, "apple_names", ".apple_names"),
+ clEnumValN(DIDT_AppleTypes, "apple_types", ".apple_types"),
+ clEnumValN(DIDT_AppleNamespaces, "apple_namespaces", ".apple_namespaces"),
+ clEnumValN(DIDT_AppleObjC, "apple_objc", ".apple_objc"),
+ clEnumValN(DIDT_Aranges, "aranges", ".debug_aranges"),
+ clEnumValN(DIDT_Info, "info", ".debug_info"),
+ clEnumValN(DIDT_InfoDwo, "info.dwo", ".debug_info.dwo"),
+ clEnumValN(DIDT_Types, "types", ".debug_types"),
+ clEnumValN(DIDT_TypesDwo, "types.dwo", ".debug_types.dwo"),
+ clEnumValN(DIDT_Line, "line", ".debug_line"),
+ clEnumValN(DIDT_LineDwo, "line.dwo", ".debug_line.dwo"),
+ clEnumValN(DIDT_Loc, "loc", ".debug_loc"),
+ clEnumValN(DIDT_LocDwo, "loc.dwo", ".debug_loc.dwo"),
+ clEnumValN(DIDT_Frames, "frames", ".debug_frame"),
+ clEnumValN(DIDT_Ranges, "ranges", ".debug_ranges"),
+ clEnumValN(DIDT_Pubnames, "pubnames", ".debug_pubnames"),
+ clEnumValN(DIDT_Pubtypes, "pubtypes", ".debug_pubtypes"),
+ clEnumValN(DIDT_GnuPubnames, "gnu_pubnames", ".debug_gnu_pubnames"),
+ clEnumValN(DIDT_GnuPubtypes, "gnu_pubtypes", ".debug_gnu_pubtypes"),
+ clEnumValN(DIDT_Str, "str", ".debug_str"),
+ clEnumValN(DIDT_StrDwo, "str.dwo", ".debug_str.dwo"),
+ clEnumValN(DIDT_StrOffsetsDwo, "str_offsets.dwo", ".debug_str_offsets.dwo"),
+ clEnumValEnd));
+
+static void DumpInput(StringRef Filename) {
+ ErrorOr<std::unique_ptr<MemoryBuffer>> BuffOrErr =
+ MemoryBuffer::getFileOrSTDIN(Filename);
+
+ if (std::error_code EC = BuffOrErr.getError()) {
+ errs() << Filename << ": " << EC.message() << "\n";
+ return;
+ }
+ std::unique_ptr<MemoryBuffer> Buff = std::move(BuffOrErr.get());
+
+ ErrorOr<std::unique_ptr<ObjectFile>> ObjOrErr =
+ ObjectFile::createObjectFile(Buff->getMemBufferRef());
+ if (std::error_code EC = ObjOrErr.getError()) {
+ errs() << Filename << ": " << EC.message() << '\n';
+ return;
+ }
+ ObjectFile &Obj = *ObjOrErr.get();
+
+ std::unique_ptr<DIContext> DICtx(new DWARFContextInMemory(Obj));
+
+ outs() << Filename
+ << ":\tfile format " << Obj.getFileFormatName() << "\n\n";
+ // Dump the complete DWARF structure.
+ DICtx->dump(outs(), DumpType);
+}
+
+int main(int argc, char **argv) {
+ // Print a stack trace if we signal out.
+ sys::PrintStackTraceOnErrorSignal();
+ PrettyStackTraceProgram X(argc, argv);
+ llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
+
+ cl::ParseCommandLineOptions(argc, argv, "llvm dwarf dumper\n");
+
+ // Defaults to a.out if no filenames specified.
+ if (InputFilenames.size() == 0)
+ InputFilenames.push_back("a.out");
+
+ std::for_each(InputFilenames.begin(), InputFilenames.end(), DumpInput);
+
+ return 0;
+}
diff --git a/contrib/llvm/tools/llvm-extract/llvm-extract.cpp b/contrib/llvm/tools/llvm-extract/llvm-extract.cpp
index 53b2f0d..936496c 100644
--- a/contrib/llvm/tools/llvm-extract/llvm-extract.cpp
+++ b/contrib/llvm/tools/llvm-extract/llvm-extract.cpp
@@ -20,7 +20,7 @@
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/IRReader/IRReader.h"
-#include "llvm/PassManager.h"
+#include "llvm/IR/LegacyPassManager.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/ManagedStatic.h"
@@ -90,6 +90,16 @@ static cl::opt<bool>
OutputAssembly("S",
cl::desc("Write output as LLVM assembly"), cl::Hidden);
+static cl::opt<bool> PreserveBitcodeUseListOrder(
+ "preserve-bc-uselistorder",
+ cl::desc("Preserve use-list order when writing LLVM bitcode."),
+ cl::init(true), cl::Hidden);
+
+static cl::opt<bool> PreserveAssemblyUseListOrder(
+ "preserve-ll-uselistorder",
+ cl::desc("Preserve use-list order when writing LLVM assembly."),
+ cl::init(false), cl::Hidden);
+
int main(int argc, char **argv) {
// Print a stack trace if we signal out.
sys::PrintStackTraceOnErrorSignal();
@@ -246,8 +256,7 @@ int main(int argc, char **argv) {
// In addition to deleting all other functions, we also want to spiff it
// up a little bit. Do this now.
- PassManager Passes;
- Passes.add(new DataLayoutPass()); // Use correct DataLayout
+ legacy::PassManager Passes;
std::vector<GlobalValue*> Gvs(GVs.begin(), GVs.end());
@@ -265,9 +274,10 @@ int main(int argc, char **argv) {
}
if (OutputAssembly)
- Passes.add(createPrintModulePass(Out.os()));
+ Passes.add(
+ createPrintModulePass(Out.os(), "", PreserveAssemblyUseListOrder));
else if (Force || !CheckBitcodeOutputToConsole(Out.os(), true))
- Passes.add(createBitcodeWriterPass(Out.os()));
+ Passes.add(createBitcodeWriterPass(Out.os(), PreserveBitcodeUseListOrder));
Passes.run(*M.get());
diff --git a/contrib/llvm/tools/llvm-link/llvm-link.cpp b/contrib/llvm/tools/llvm-link/llvm-link.cpp
index 828b9bb..369f347 100644
--- a/contrib/llvm/tools/llvm-link/llvm-link.cpp
+++ b/contrib/llvm/tools/llvm-link/llvm-link.cpp
@@ -13,7 +13,9 @@
//===----------------------------------------------------------------------===//
#include "llvm/Linker/Linker.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/Bitcode/ReaderWriter.h"
+#include "llvm/IR/AutoUpgrade.h"
#include "llvm/IR/DiagnosticInfo.h"
#include "llvm/IR/DiagnosticPrinter.h"
#include "llvm/IR/LLVMContext.h"
@@ -36,6 +38,11 @@ static cl::list<std::string>
InputFilenames(cl::Positional, cl::OneOrMore,
cl::desc("<input bitcode files>"));
+static cl::list<std::string> OverridingInputs(
+ "override", cl::ZeroOrMore, cl::value_desc("filename"),
+ cl::desc(
+ "input bitcode file which can override previously defined symbol(s)"));
+
static cl::opt<std::string>
OutputFilename("o", cl::desc("Override output filename"), cl::init("-"),
cl::value_desc("filename"));
@@ -57,6 +64,16 @@ static cl::opt<bool>
SuppressWarnings("suppress-warnings", cl::desc("Suppress all linking warnings"),
cl::init(false));
+static cl::opt<bool> PreserveBitcodeUseListOrder(
+ "preserve-bc-uselistorder",
+ cl::desc("Preserve use-list order when writing LLVM bitcode."),
+ cl::init(true), cl::Hidden);
+
+static cl::opt<bool> PreserveAssemblyUseListOrder(
+ "preserve-ll-uselistorder",
+ cl::desc("Preserve use-list order when writing LLVM assembly."),
+ cl::init(false), cl::Hidden);
+
// Read the specified bitcode file in and return it. This routine searches the
// link path for the specified file to try to find it...
//
@@ -68,6 +85,9 @@ loadFile(const char *argv0, const std::string &FN, LLVMContext &Context) {
if (!Result)
Err.print(argv0, errs());
+ Result->materializeMetadata();
+ UpgradeDebugInfo(*Result);
+
return Result;
}
@@ -92,6 +112,31 @@ static void diagnosticHandler(const DiagnosticInfo &DI) {
errs() << '\n';
}
+static bool linkFiles(const char *argv0, LLVMContext &Context, Linker &L,
+ const cl::list<std::string> &Files,
+ bool OverrideDuplicateSymbols) {
+ for (const auto &File : Files) {
+ std::unique_ptr<Module> M = loadFile(argv0, File, Context);
+ if (!M.get()) {
+ errs() << argv0 << ": error loading file '" << File << "'\n";
+ return false;
+ }
+
+ if (verifyModule(*M, &errs())) {
+ errs() << argv0 << ": " << File << ": error: input module is broken!\n";
+ return false;
+ }
+
+ if (Verbose)
+ errs() << "Linking in '" << File << "'\n";
+
+ if (L.linkInModule(M.get(), OverrideDuplicateSymbols))
+ return false;
+ }
+
+ return true;
+}
+
int main(int argc, char **argv) {
// Print a stack trace if we signal out.
sys::PrintStackTraceOnErrorSignal();
@@ -104,18 +149,13 @@ int main(int argc, char **argv) {
auto Composite = make_unique<Module>("llvm-link", Context);
Linker L(Composite.get(), diagnosticHandler);
- for (unsigned i = 0; i < InputFilenames.size(); ++i) {
- std::unique_ptr<Module> M = loadFile(argv[0], InputFilenames[i], Context);
- if (!M.get()) {
- errs() << argv[0] << ": error loading file '" <<InputFilenames[i]<< "'\n";
- return 1;
- }
-
- if (Verbose) errs() << "Linking in '" << InputFilenames[i] << "'\n";
+ // First add all the regular input files
+ if (!linkFiles(argv[0], Context, L, InputFilenames, false))
+ return 1;
- if (L.linkInModule(M.get()))
- return 1;
- }
+ // Next the -override ones.
+ if (!linkFiles(argv[0], Context, L, OverridingInputs, true))
+ return 1;
if (DumpAsm) errs() << "Here's the assembly:\n" << *Composite;
@@ -126,16 +166,16 @@ int main(int argc, char **argv) {
return 1;
}
- if (verifyModule(*Composite)) {
- errs() << argv[0] << ": linked module is broken!\n";
+ if (verifyModule(*Composite, &errs())) {
+ errs() << argv[0] << ": error: linked module is broken!\n";
return 1;
}
if (Verbose) errs() << "Writing bitcode...\n";
if (OutputAssembly) {
- Out.os() << *Composite;
+ Composite->print(Out.os(), nullptr, PreserveAssemblyUseListOrder);
} else if (Force || !CheckBitcodeOutputToConsole(Out.os(), true))
- WriteBitcodeToFile(Composite.get(), Out.os());
+ WriteBitcodeToFile(Composite.get(), Out.os(), PreserveBitcodeUseListOrder);
// Declare success.
Out.keep();
diff --git a/contrib/llvm/tools/llvm-lto/llvm-lto.cpp b/contrib/llvm/tools/llvm-lto/llvm-lto.cpp
new file mode 100644
index 0000000..9cd6587
--- /dev/null
+++ b/contrib/llvm/tools/llvm-lto/llvm-lto.cpp
@@ -0,0 +1,292 @@
+//===-- llvm-lto: a simple command-line program to link modules with LTO --===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This program takes in a list of bitcode files, links them, performs link-time
+// optimization, and outputs an object file.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/StringSet.h"
+#include "llvm/CodeGen/CommandFlags.h"
+#include "llvm/LTO/LTOCodeGenerator.h"
+#include "llvm/LTO/LTOModule.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/PrettyStackTrace.h"
+#include "llvm/Support/Signals.h"
+#include "llvm/Support/TargetSelect.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace llvm;
+
+static cl::opt<char>
+OptLevel("O",
+ cl::desc("Optimization level. [-O0, -O1, -O2, or -O3] "
+ "(default = '-O2')"),
+ cl::Prefix,
+ cl::ZeroOrMore,
+ cl::init('2'));
+
+static cl::opt<bool>
+DisableInline("disable-inlining", cl::init(false),
+ cl::desc("Do not run the inliner pass"));
+
+static cl::opt<bool>
+DisableGVNLoadPRE("disable-gvn-loadpre", cl::init(false),
+ cl::desc("Do not run the GVN load PRE pass"));
+
+static cl::opt<bool>
+DisableLTOVectorization("disable-lto-vectorization", cl::init(false),
+ cl::desc("Do not run loop or slp vectorization during LTO"));
+
+static cl::opt<bool>
+UseDiagnosticHandler("use-diagnostic-handler", cl::init(false),
+ cl::desc("Use a diagnostic handler to test the handler interface"));
+
+static cl::list<std::string>
+InputFilenames(cl::Positional, cl::OneOrMore,
+ cl::desc("<input bitcode files>"));
+
+static cl::opt<std::string>
+OutputFilename("o", cl::init(""),
+ cl::desc("Override output filename"),
+ cl::value_desc("filename"));
+
+static cl::list<std::string>
+ExportedSymbols("exported-symbol",
+ cl::desc("Symbol to export from the resulting object file"),
+ cl::ZeroOrMore);
+
+static cl::list<std::string>
+DSOSymbols("dso-symbol",
+ cl::desc("Symbol to put in the symtab in the resulting dso"),
+ cl::ZeroOrMore);
+
+static cl::opt<bool> ListSymbolsOnly(
+ "list-symbols-only", cl::init(false),
+ cl::desc("Instead of running LTO, list the symbols in each IR file"));
+
+static cl::opt<bool> SetMergedModule(
+ "set-merged-module", cl::init(false),
+ cl::desc("Use the first input module as the merged module"));
+
+namespace {
+struct ModuleInfo {
+ std::vector<bool> CanBeHidden;
+};
+}
+
+static void handleDiagnostics(lto_codegen_diagnostic_severity_t Severity,
+ const char *Msg, void *) {
+ switch (Severity) {
+ case LTO_DS_NOTE:
+ errs() << "note: ";
+ break;
+ case LTO_DS_REMARK:
+ errs() << "remark: ";
+ break;
+ case LTO_DS_ERROR:
+ errs() << "error: ";
+ break;
+ case LTO_DS_WARNING:
+ errs() << "warning: ";
+ break;
+ }
+ errs() << Msg << "\n";
+}
+
+static std::unique_ptr<LTOModule>
+getLocalLTOModule(StringRef Path, std::unique_ptr<MemoryBuffer> &Buffer,
+ const TargetOptions &Options, std::string &Error) {
+ ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr =
+ MemoryBuffer::getFile(Path);
+ if (std::error_code EC = BufferOrErr.getError()) {
+ Error = EC.message();
+ return nullptr;
+ }
+ Buffer = std::move(BufferOrErr.get());
+ return std::unique_ptr<LTOModule>(LTOModule::createInLocalContext(
+ Buffer->getBufferStart(), Buffer->getBufferSize(), Options, Error, Path));
+}
+
+/// \brief List symbols in each IR file.
+///
+/// The main point here is to provide lit-testable coverage for the LTOModule
+/// functionality that's exposed by the C API to list symbols. Moreover, this
+/// provides testing coverage for modules that have been created in their own
+/// contexts.
+static int listSymbols(StringRef Command, const TargetOptions &Options) {
+ for (auto &Filename : InputFilenames) {
+ std::string Error;
+ std::unique_ptr<MemoryBuffer> Buffer;
+ std::unique_ptr<LTOModule> Module =
+ getLocalLTOModule(Filename, Buffer, Options, Error);
+ if (!Module) {
+ errs() << Command << ": error loading file '" << Filename
+ << "': " << Error << "\n";
+ return 1;
+ }
+
+ // List the symbols.
+ outs() << Filename << ":\n";
+ for (int I = 0, E = Module->getSymbolCount(); I != E; ++I)
+ outs() << Module->getSymbolName(I) << "\n";
+ }
+ return 0;
+}
+
+int main(int argc, char **argv) {
+ // Print a stack trace if we signal out.
+ sys::PrintStackTraceOnErrorSignal();
+ PrettyStackTraceProgram X(argc, argv);
+
+ llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
+ cl::ParseCommandLineOptions(argc, argv, "llvm LTO linker\n");
+
+ if (OptLevel < '0' || OptLevel > '3') {
+ errs() << argv[0] << ": optimization level must be between 0 and 3\n";
+ return 1;
+ }
+
+ // Initialize the configured targets.
+ InitializeAllTargets();
+ InitializeAllTargetMCs();
+ InitializeAllAsmPrinters();
+ InitializeAllAsmParsers();
+
+ // set up the TargetOptions for the machine
+ TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
+
+ if (ListSymbolsOnly)
+ return listSymbols(argv[0], Options);
+
+ unsigned BaseArg = 0;
+
+ LTOCodeGenerator CodeGen;
+
+ if (UseDiagnosticHandler)
+ CodeGen.setDiagnosticHandler(handleDiagnostics, nullptr);
+
+ switch (RelocModel) {
+ case Reloc::Static:
+ CodeGen.setCodePICModel(LTO_CODEGEN_PIC_MODEL_STATIC);
+ break;
+ case Reloc::PIC_:
+ CodeGen.setCodePICModel(LTO_CODEGEN_PIC_MODEL_DYNAMIC);
+ break;
+ case Reloc::DynamicNoPIC:
+ CodeGen.setCodePICModel(LTO_CODEGEN_PIC_MODEL_DYNAMIC_NO_PIC);
+ break;
+ default:
+ CodeGen.setCodePICModel(LTO_CODEGEN_PIC_MODEL_DEFAULT);
+ }
+
+ CodeGen.setDebugInfo(LTO_DEBUG_MODEL_DWARF);
+ CodeGen.setTargetOptions(Options);
+
+ llvm::StringSet<llvm::MallocAllocator> DSOSymbolsSet;
+ for (unsigned i = 0; i < DSOSymbols.size(); ++i)
+ DSOSymbolsSet.insert(DSOSymbols[i]);
+
+ std::vector<std::string> KeptDSOSyms;
+
+ for (unsigned i = BaseArg; i < InputFilenames.size(); ++i) {
+ std::string error;
+ std::unique_ptr<LTOModule> Module(
+ LTOModule::createFromFile(InputFilenames[i].c_str(), Options, error));
+ if (!error.empty()) {
+ errs() << argv[0] << ": error loading file '" << InputFilenames[i]
+ << "': " << error << "\n";
+ return 1;
+ }
+
+ LTOModule *LTOMod = Module.get();
+
+ // We use the first input module as the destination module when
+ // SetMergedModule is true.
+ if (SetMergedModule && i == BaseArg) {
+ // Transfer ownership to the code generator.
+ CodeGen.setModule(Module.release());
+ } else if (!CodeGen.addModule(Module.get()))
+ return 1;
+
+ unsigned NumSyms = LTOMod->getSymbolCount();
+ for (unsigned I = 0; I < NumSyms; ++I) {
+ StringRef Name = LTOMod->getSymbolName(I);
+ if (!DSOSymbolsSet.count(Name))
+ continue;
+ lto_symbol_attributes Attrs = LTOMod->getSymbolAttributes(I);
+ unsigned Scope = Attrs & LTO_SYMBOL_SCOPE_MASK;
+ if (Scope != LTO_SYMBOL_SCOPE_DEFAULT_CAN_BE_HIDDEN)
+ KeptDSOSyms.push_back(Name);
+ }
+ }
+
+ // Add all the exported symbols to the table of symbols to preserve.
+ for (unsigned i = 0; i < ExportedSymbols.size(); ++i)
+ CodeGen.addMustPreserveSymbol(ExportedSymbols[i].c_str());
+
+ // Add all the dso symbols to the table of symbols to expose.
+ for (unsigned i = 0; i < KeptDSOSyms.size(); ++i)
+ CodeGen.addMustPreserveSymbol(KeptDSOSyms[i].c_str());
+
+ // Set cpu and attrs strings for the default target/subtarget.
+ CodeGen.setCpu(MCPU.c_str());
+
+ CodeGen.setOptLevel(OptLevel - '0');
+
+ std::string attrs;
+ for (unsigned i = 0; i < MAttrs.size(); ++i) {
+ if (i > 0)
+ attrs.append(",");
+ attrs.append(MAttrs[i]);
+ }
+
+ if (!attrs.empty())
+ CodeGen.setAttr(attrs.c_str());
+
+ if (!OutputFilename.empty()) {
+ size_t len = 0;
+ std::string ErrorInfo;
+ const void *Code =
+ CodeGen.compile(&len, DisableInline, DisableGVNLoadPRE,
+ DisableLTOVectorization, ErrorInfo);
+ if (!Code) {
+ errs() << argv[0]
+ << ": error compiling the code: " << ErrorInfo << "\n";
+ return 1;
+ }
+
+ std::error_code EC;
+ raw_fd_ostream FileStream(OutputFilename, EC, sys::fs::F_None);
+ if (EC) {
+ errs() << argv[0] << ": error opening the file '" << OutputFilename
+ << "': " << EC.message() << "\n";
+ return 1;
+ }
+
+ FileStream.write(reinterpret_cast<const char *>(Code), len);
+ } else {
+ std::string ErrorInfo;
+ const char *OutputName = nullptr;
+ if (!CodeGen.compile_to_file(&OutputName, DisableInline,
+ DisableGVNLoadPRE, DisableLTOVectorization,
+ ErrorInfo)) {
+ errs() << argv[0]
+ << ": error compiling the code: " << ErrorInfo
+ << "\n";
+ return 1;
+ }
+
+ outs() << "Wrote native object file '" << OutputName << "'\n";
+ }
+
+ return 0;
+}
diff --git a/contrib/llvm/tools/llvm-mc/llvm-mc.cpp b/contrib/llvm/tools/llvm-mc/llvm-mc.cpp
index 78fe9b7..6a8b493 100644
--- a/contrib/llvm/tools/llvm-mc/llvm-mc.cpp
+++ b/contrib/llvm/tools/llvm-mc/llvm-mc.cpp
@@ -357,6 +357,7 @@ int main(int argc, char **argv) {
cl::ParseCommandLineOptions(argc, argv, "llvm machine code playground\n");
MCTargetOptions MCOptions = InitMCTargetOptionsFromFlags();
TripleName = Triple::normalize(TripleName);
+ Triple TheTriple(TripleName);
setDwarfDebugFlags(argc, argv);
setDwarfDebugProducer();
@@ -438,7 +439,8 @@ int main(int argc, char **argv) {
if (!Out)
return 1;
- formatted_raw_ostream FOS(Out->os());
+ std::unique_ptr<buffer_ostream> BOS;
+ raw_pwrite_stream *OS = &Out->os();
std::unique_ptr<MCStreamer> Str;
std::unique_ptr<MCInstrInfo> MCII(TheTarget->createMCInstrInfo());
@@ -447,8 +449,8 @@ int main(int argc, char **argv) {
MCInstPrinter *IP = nullptr;
if (FileType == OFT_AssemblyFile) {
- IP =
- TheTarget->createMCInstPrinter(OutputAsmVariant, *MAI, *MCII, *MRI, *STI);
+ IP = TheTarget->createMCInstPrinter(Triple(TripleName), OutputAsmVariant,
+ *MAI, *MCII, *MRI);
// Set the display preference for hex vs. decimal immediates.
IP->setPrintImmHex(PrintImmHex);
@@ -457,21 +459,29 @@ int main(int argc, char **argv) {
MCCodeEmitter *CE = nullptr;
MCAsmBackend *MAB = nullptr;
if (ShowEncoding) {
- CE = TheTarget->createMCCodeEmitter(*MCII, *MRI, *STI, Ctx);
+ CE = TheTarget->createMCCodeEmitter(*MCII, *MRI, Ctx);
MAB = TheTarget->createMCAsmBackend(*MRI, TripleName, MCPU);
}
- Str.reset(TheTarget->createAsmStreamer(Ctx, FOS, /*asmverbose*/ true,
- /*useDwarfDirectory*/ true, IP, CE,
- MAB, ShowInst));
+ auto FOut = llvm::make_unique<formatted_raw_ostream>(*OS);
+ Str.reset(TheTarget->createAsmStreamer(
+ Ctx, std::move(FOut), /*asmverbose*/ true,
+ /*useDwarfDirectory*/ true, IP, CE, MAB, ShowInst));
} else if (FileType == OFT_Null) {
- Str.reset(createNullStreamer(Ctx));
+ Str.reset(TheTarget->createNullStreamer(Ctx));
} else {
assert(FileType == OFT_ObjectFile && "Invalid file type!");
- MCCodeEmitter *CE = TheTarget->createMCCodeEmitter(*MCII, *MRI, *STI, Ctx);
+
+ if (!Out->os().supportsSeeking()) {
+ BOS = make_unique<buffer_ostream>(Out->os());
+ OS = BOS.get();
+ }
+
+ MCCodeEmitter *CE = TheTarget->createMCCodeEmitter(*MCII, *MRI, Ctx);
MCAsmBackend *MAB = TheTarget->createMCAsmBackend(*MRI, TripleName, MCPU);
- Str.reset(TheTarget->createMCObjectStreamer(TripleName, Ctx, *MAB, FOS, CE,
- *STI, RelaxAll));
+ Str.reset(TheTarget->createMCObjectStreamer(TheTriple, Ctx, *MAB, *OS, CE,
+ *STI, RelaxAll,
+ /*DWARFMustBeAtTheEnd*/ false));
if (NoExecStack)
Str->InitSections(true);
}
diff --git a/contrib/llvm/tools/llvm-nm/llvm-nm.cpp b/contrib/llvm/tools/llvm-nm/llvm-nm.cpp
index f911c72..f3197bb 100644
--- a/contrib/llvm/tools/llvm-nm/llvm-nm.cpp
+++ b/contrib/llvm/tools/llvm-nm/llvm-nm.cpp
@@ -188,85 +188,77 @@ static bool compareSymbolAddress(const NMSymbol &A, const NMSymbol &B) {
if (!ReverseSort) {
if (A.Address < B.Address)
return true;
- else if (A.Address == B.Address && A.Name < B.Name)
+ if (A.Address == B.Address && A.Name < B.Name)
return true;
- else if (A.Address == B.Address && A.Name == B.Name && A.Size < B.Size)
+ if (A.Address == B.Address && A.Name == B.Name && A.Size < B.Size)
return true;
- else
- return false;
- } else {
- if (A.Address > B.Address)
- return true;
- else if (A.Address == B.Address && A.Name > B.Name)
- return true;
- else if (A.Address == B.Address && A.Name == B.Name && A.Size > B.Size)
- return true;
- else
- return false;
+ 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;
}
static bool compareSymbolSize(const NMSymbol &A, const NMSymbol &B) {
if (!ReverseSort) {
if (A.Size < B.Size)
return true;
- else if (A.Size == B.Size && A.Name < B.Name)
- return true;
- else if (A.Size == B.Size && A.Name == B.Name && A.Address < B.Address)
- return true;
- else
- return false;
- } else {
- if (A.Size > B.Size)
+ if (A.Size == B.Size && A.Name < B.Name)
return true;
- else if (A.Size == B.Size && A.Name > B.Name)
+ if (A.Size == B.Size && A.Name == B.Name && A.Address < B.Address)
return true;
- else if (A.Size == B.Size && A.Name == B.Name && A.Address > B.Address)
- return true;
- else
- return false;
+ 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;
}
static bool compareSymbolName(const NMSymbol &A, const NMSymbol &B) {
if (!ReverseSort) {
if (A.Name < B.Name)
return true;
- else if (A.Name == B.Name && A.Size < B.Size)
- return true;
- else if (A.Name == B.Name && A.Size == B.Size && A.Address < B.Address)
- return true;
- else
- return false;
- } else {
- if (A.Name > B.Name)
+ if (A.Name == B.Name && A.Size < B.Size)
return true;
- else if (A.Name == B.Name && A.Size > B.Size)
+ if (A.Name == B.Name && A.Size == B.Size && A.Address < B.Address)
return true;
- else if (A.Name == B.Name && A.Size == B.Size && A.Address > B.Address)
- return true;
- else
- return false;
+ 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;
}
static char isSymbolList64Bit(SymbolicFile &Obj) {
if (isa<IRObjectFile>(Obj))
return false;
- else if (isa<COFFObjectFile>(Obj))
+ if (isa<COFFObjectFile>(Obj))
return false;
- else if (MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(&Obj))
+ if (MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(&Obj))
return MachO->is64Bit();
- else if (isa<ELF32LEObjectFile>(Obj))
+ if (isa<ELF32LEObjectFile>(Obj))
return false;
- else if (isa<ELF64LEObjectFile>(Obj))
+ if (isa<ELF64LEObjectFile>(Obj))
return true;
- else if (isa<ELF32BEObjectFile>(Obj))
+ if (isa<ELF32BEObjectFile>(Obj))
return false;
- else if (isa<ELF64BEObjectFile>(Obj))
+ if (isa<ELF64BEObjectFile>(Obj))
return true;
- else
- return false;
+ return false;
}
static StringRef CurrentFilename;
@@ -940,7 +932,7 @@ static void dumpSymbolNamesFromObject(SymbolicFile &Obj, bool printName,
NMSymbol S;
S.Size = UnknownAddressOrSize;
S.Address = UnknownAddressOrSize;
- if ((PrintSize || SizeSort) && isa<ObjectFile>(Obj)) {
+ if (PrintSize && isa<ELFObjectFileBase>(Obj)) {
symbol_iterator SymI = I;
if (error(SymI->getSize(S.Size)))
break;
@@ -973,30 +965,26 @@ static void dumpSymbolNamesFromObject(SymbolicFile &Obj, bool printName,
// architectures was specificed. If not then an error is generated and this
// routine returns false. Else it returns true.
static bool checkMachOAndArchFlags(SymbolicFile *O, std::string &Filename) {
- if (isa<MachOObjectFile>(O) && !ArchAll && ArchFlags.size() != 0) {
- MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(O);
- bool ArchFound = false;
- MachO::mach_header H;
- MachO::mach_header_64 H_64;
- Triple T;
- if (MachO->is64Bit()) {
- H_64 = MachO->MachOObjectFile::getHeader64();
- T = MachOObjectFile::getArch(H_64.cputype, H_64.cpusubtype);
- } else {
- H = MachO->MachOObjectFile::getHeader();
- T = MachOObjectFile::getArch(H.cputype, H.cpusubtype);
- }
- unsigned i;
- for (i = 0; i < ArchFlags.size(); ++i) {
- if (ArchFlags[i] == T.getArchName())
- ArchFound = true;
- break;
- }
- if (!ArchFound) {
- error(ArchFlags[i],
- "file: " + Filename + " does not contain architecture");
- return false;
- }
+ MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(O);
+
+ if (!MachO || ArchAll || ArchFlags.size() == 0)
+ return true;
+
+ MachO::mach_header H;
+ MachO::mach_header_64 H_64;
+ Triple T;
+ if (MachO->is64Bit()) {
+ H_64 = MachO->MachOObjectFile::getHeader64();
+ T = MachOObjectFile::getArch(H_64.cputype, H_64.cpusubtype);
+ } else {
+ H = MachO->MachOObjectFile::getHeader();
+ T = MachOObjectFile::getArch(H.cputype, H.cpusubtype);
+ }
+ if (std::none_of(
+ ArchFlags.begin(), ArchFlags.end(),
+ [&](const std::string &Name) { return Name == T.getArchName(); })) {
+ error("No architecture specified", Filename);
+ return false;
}
return true;
}
diff --git a/contrib/llvm/tools/llvm-objdump/MachODump.cpp b/contrib/llvm/tools/llvm-objdump/MachODump.cpp
index 03fad5f..84212c9 100644
--- a/contrib/llvm/tools/llvm-objdump/MachODump.cpp
+++ b/contrib/llvm/tools/llvm-objdump/MachODump.cpp
@@ -18,6 +18,7 @@
#include "llvm/ADT/Triple.h"
#include "llvm/Config/config.h"
#include "llvm/DebugInfo/DIContext.h"
+#include "llvm/DebugInfo/DWARF/DWARFContext.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCDisassembler.h"
@@ -36,6 +37,7 @@
#include "llvm/Support/Format.h"
#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/GraphWriter.h"
+#include "llvm/Support/LEB128.h"
#include "llvm/Support/MachO.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/TargetRegistry.h"
@@ -62,13 +64,83 @@ static cl::opt<std::string> DSYMFile("dsym",
static cl::opt<bool> FullLeadingAddr("full-leading-addr",
cl::desc("Print full leading address"));
+static cl::opt<bool> NoLeadingAddr("no-leading-addr",
+ cl::desc("Print no leading address"));
+
static cl::opt<bool>
PrintImmHex("print-imm-hex",
cl::desc("Use hex format for immediate values"));
+cl::opt<bool> llvm::UniversalHeaders("universal-headers",
+ cl::desc("Print Mach-O universal headers "
+ "(requires -macho)"));
+
+cl::opt<bool>
+ llvm::ArchiveHeaders("archive-headers",
+ cl::desc("Print archive headers for Mach-O archives "
+ "(requires -macho)"));
+
+cl::opt<bool>
+ ArchiveMemberOffsets("archive-member-offsets",
+ cl::desc("Print the offset to each archive member for "
+ "Mach-O archives (requires -macho and "
+ "-archive-headers)"));
+
+cl::opt<bool>
+ llvm::IndirectSymbols("indirect-symbols",
+ cl::desc("Print indirect symbol table for Mach-O "
+ "objects (requires -macho)"));
+
+cl::opt<bool>
+ llvm::DataInCode("data-in-code",
+ cl::desc("Print the data in code table for Mach-O objects "
+ "(requires -macho)"));
+
+cl::opt<bool>
+ llvm::LinkOptHints("link-opt-hints",
+ cl::desc("Print the linker optimization hints for "
+ "Mach-O objects (requires -macho)"));
+
+cl::list<std::string>
+ llvm::DumpSections("section",
+ 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 "
+ "Mach-O objects (requires -macho)"));
+
+cl::opt<bool>
+ llvm::DylibsUsed("dylibs-used",
+ cl::desc("Print the shared libraries used for linked "
+ "Mach-O files (requires -macho)"));
+
+cl::opt<bool>
+ llvm::DylibId("dylib-id",
+ cl::desc("Print the shared library's id for the dylib Mach-O "
+ "file (requires -macho)"));
+
+cl::opt<bool>
+ llvm::NonVerbose("non-verbose",
+ cl::desc("Print the info for Mach-O objects in "
+ "non-verbose or numeric form (requires -macho)"));
+
cl::opt<bool>
- llvm::UniversalHeaders("universal-headers",
- cl::desc("Print Mach-O universal headers"));
+ llvm::ObjcMetaData("objc-meta-data",
+ cl::desc("Print the Objective-C runtime meta data for "
+ "Mach-O files (requires -macho)"));
+
+cl::opt<std::string> llvm::DisSymName(
+ "dis-symname",
+ cl::desc("disassemble just this symbol's instructions (requires -macho"));
+
+static cl::opt<bool> NoSymbolicOperands(
+ "no-symbolic-operands",
+ cl::desc("do not symbolic operands when disassembling (requires -macho)"));
static cl::list<std::string>
ArchFlags("arch", cl::desc("architecture(s) from a Mach-O file to dump"),
@@ -147,7 +219,7 @@ static bool compareDiceTableEntries(const DiceTableEntry &i,
return j.first >= i.first && j.first < i.first + Length;
}
-static uint64_t DumpDataInCode(const char *bytes, uint64_t Length,
+static uint64_t DumpDataInCode(const uint8_t *bytes, uint64_t Length,
unsigned short Kind) {
uint32_t Value, Size = 1;
@@ -156,19 +228,19 @@ static uint64_t DumpDataInCode(const char *bytes, uint64_t Length,
case MachO::DICE_KIND_DATA:
if (Length >= 4) {
if (!NoShowRawInsn)
- DumpBytes(StringRef(bytes, 4));
+ DumpBytes(ArrayRef<uint8_t>(bytes, 4));
Value = bytes[3] << 24 | bytes[2] << 16 | bytes[1] << 8 | bytes[0];
outs() << "\t.long " << Value;
Size = 4;
} else if (Length >= 2) {
if (!NoShowRawInsn)
- DumpBytes(StringRef(bytes, 2));
+ DumpBytes(ArrayRef<uint8_t>(bytes, 2));
Value = bytes[1] << 8 | bytes[0];
outs() << "\t.short " << Value;
Size = 2;
} else {
if (!NoShowRawInsn)
- DumpBytes(StringRef(bytes, 2));
+ DumpBytes(ArrayRef<uint8_t>(bytes, 2));
Value = bytes[0];
outs() << "\t.byte " << Value;
Size = 1;
@@ -180,14 +252,14 @@ static uint64_t DumpDataInCode(const char *bytes, uint64_t Length,
break;
case MachO::DICE_KIND_JUMP_TABLE8:
if (!NoShowRawInsn)
- DumpBytes(StringRef(bytes, 1));
+ DumpBytes(ArrayRef<uint8_t>(bytes, 1));
Value = bytes[0];
outs() << "\t.byte " << format("%3u", Value) << "\t@ KIND_JUMP_TABLE8\n";
Size = 1;
break;
case MachO::DICE_KIND_JUMP_TABLE16:
if (!NoShowRawInsn)
- DumpBytes(StringRef(bytes, 2));
+ DumpBytes(ArrayRef<uint8_t>(bytes, 2));
Value = bytes[1] << 8 | bytes[0];
outs() << "\t.short " << format("%5u", Value & 0xffff)
<< "\t@ KIND_JUMP_TABLE16\n";
@@ -196,7 +268,7 @@ static uint64_t DumpDataInCode(const char *bytes, uint64_t Length,
case MachO::DICE_KIND_JUMP_TABLE32:
case MachO::DICE_KIND_ABS_JUMP_TABLE32:
if (!NoShowRawInsn)
- DumpBytes(StringRef(bytes, 4));
+ DumpBytes(ArrayRef<uint8_t>(bytes, 4));
Value = bytes[3] << 24 | bytes[2] << 16 | bytes[1] << 8 | bytes[0];
outs() << "\t.long " << Value;
if (Kind == MachO::DICE_KIND_JUMP_TABLE32)
@@ -255,6 +327,842 @@ static void getSectionsAndSymbols(const MachO::mach_header Header,
}
}
+static void PrintIndirectSymbolTable(MachOObjectFile *O, bool verbose,
+ uint32_t n, uint32_t count,
+ uint32_t stride, uint64_t addr) {
+ MachO::dysymtab_command Dysymtab = O->getDysymtabLoadCommand();
+ uint32_t nindirectsyms = Dysymtab.nindirectsyms;
+ if (n > nindirectsyms)
+ outs() << " (entries start past the end of the indirect symbol "
+ "table) (reserved1 field greater than the table size)";
+ else if (n + count > nindirectsyms)
+ outs() << " (entries extends past the end of the indirect symbol "
+ "table)";
+ outs() << "\n";
+ uint32_t cputype = O->getHeader().cputype;
+ if (cputype & MachO::CPU_ARCH_ABI64)
+ outs() << "address index";
+ else
+ outs() << "address index";
+ if (verbose)
+ outs() << " name\n";
+ else
+ outs() << "\n";
+ for (uint32_t j = 0; j < count && n + j < nindirectsyms; j++) {
+ if (cputype & MachO::CPU_ARCH_ABI64)
+ outs() << format("0x%016" PRIx64, addr + j * stride) << " ";
+ else
+ outs() << format("0x%08" PRIx32, addr + j * stride) << " ";
+ MachO::dysymtab_command Dysymtab = O->getDysymtabLoadCommand();
+ uint32_t indirect_symbol = O->getIndirectSymbolTableEntry(Dysymtab, n + j);
+ if (indirect_symbol == MachO::INDIRECT_SYMBOL_LOCAL) {
+ outs() << "LOCAL\n";
+ continue;
+ }
+ if (indirect_symbol ==
+ (MachO::INDIRECT_SYMBOL_LOCAL | MachO::INDIRECT_SYMBOL_ABS)) {
+ outs() << "LOCAL ABSOLUTE\n";
+ continue;
+ }
+ if (indirect_symbol == MachO::INDIRECT_SYMBOL_ABS) {
+ outs() << "ABSOLUTE\n";
+ continue;
+ }
+ outs() << format("%5u ", indirect_symbol);
+ if (verbose) {
+ MachO::symtab_command Symtab = O->getSymtabLoadCommand();
+ if (indirect_symbol < Symtab.nsyms) {
+ symbol_iterator Sym = O->getSymbolByIndex(indirect_symbol);
+ SymbolRef Symbol = *Sym;
+ StringRef SymName;
+ Symbol.getName(SymName);
+ outs() << SymName;
+ } else {
+ outs() << "?";
+ }
+ }
+ outs() << "\n";
+ }
+}
+
+static void PrintIndirectSymbols(MachOObjectFile *O, bool verbose) {
+ uint32_t LoadCommandCount = O->getHeader().ncmds;
+ MachOObjectFile::LoadCommandInfo Load = O->getFirstLoadCommandInfo();
+ for (unsigned I = 0;; ++I) {
+ if (Load.C.cmd == MachO::LC_SEGMENT_64) {
+ MachO::segment_command_64 Seg = O->getSegment64LoadCommand(Load);
+ for (unsigned J = 0; J < Seg.nsects; ++J) {
+ MachO::section_64 Sec = O->getSection64(Load, J);
+ uint32_t section_type = Sec.flags & MachO::SECTION_TYPE;
+ if (section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS ||
+ section_type == MachO::S_LAZY_SYMBOL_POINTERS ||
+ section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS ||
+ section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS ||
+ section_type == MachO::S_SYMBOL_STUBS) {
+ uint32_t stride;
+ if (section_type == MachO::S_SYMBOL_STUBS)
+ stride = Sec.reserved2;
+ else
+ stride = 8;
+ if (stride == 0) {
+ outs() << "Can't print indirect symbols for (" << Sec.segname << ","
+ << Sec.sectname << ") "
+ << "(size of stubs in reserved2 field is zero)\n";
+ continue;
+ }
+ uint32_t count = Sec.size / stride;
+ outs() << "Indirect symbols for (" << Sec.segname << ","
+ << Sec.sectname << ") " << count << " entries";
+ uint32_t n = Sec.reserved1;
+ PrintIndirectSymbolTable(O, verbose, n, count, stride, Sec.addr);
+ }
+ }
+ } else if (Load.C.cmd == MachO::LC_SEGMENT) {
+ MachO::segment_command Seg = O->getSegmentLoadCommand(Load);
+ for (unsigned J = 0; J < Seg.nsects; ++J) {
+ MachO::section Sec = O->getSection(Load, J);
+ uint32_t section_type = Sec.flags & MachO::SECTION_TYPE;
+ if (section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS ||
+ section_type == MachO::S_LAZY_SYMBOL_POINTERS ||
+ section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS ||
+ section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS ||
+ section_type == MachO::S_SYMBOL_STUBS) {
+ uint32_t stride;
+ if (section_type == MachO::S_SYMBOL_STUBS)
+ stride = Sec.reserved2;
+ else
+ stride = 4;
+ if (stride == 0) {
+ outs() << "Can't print indirect symbols for (" << Sec.segname << ","
+ << Sec.sectname << ") "
+ << "(size of stubs in reserved2 field is zero)\n";
+ continue;
+ }
+ uint32_t count = Sec.size / stride;
+ outs() << "Indirect symbols for (" << Sec.segname << ","
+ << Sec.sectname << ") " << count << " entries";
+ uint32_t n = Sec.reserved1;
+ PrintIndirectSymbolTable(O, verbose, n, count, stride, Sec.addr);
+ }
+ }
+ }
+ if (I == LoadCommandCount - 1)
+ break;
+ else
+ Load = O->getNextLoadCommandInfo(Load);
+ }
+}
+
+static void PrintDataInCodeTable(MachOObjectFile *O, bool verbose) {
+ MachO::linkedit_data_command DIC = O->getDataInCodeLoadCommand();
+ uint32_t nentries = DIC.datasize / sizeof(struct MachO::data_in_code_entry);
+ outs() << "Data in code table (" << nentries << " entries)\n";
+ outs() << "offset length kind\n";
+ for (dice_iterator DI = O->begin_dices(), DE = O->end_dices(); DI != DE;
+ ++DI) {
+ uint32_t Offset;
+ DI->getOffset(Offset);
+ outs() << format("0x%08" PRIx32, Offset) << " ";
+ uint16_t Length;
+ DI->getLength(Length);
+ outs() << format("%6u", Length) << " ";
+ uint16_t Kind;
+ DI->getKind(Kind);
+ if (verbose) {
+ switch (Kind) {
+ case MachO::DICE_KIND_DATA:
+ outs() << "DATA";
+ break;
+ case MachO::DICE_KIND_JUMP_TABLE8:
+ outs() << "JUMP_TABLE8";
+ break;
+ case MachO::DICE_KIND_JUMP_TABLE16:
+ outs() << "JUMP_TABLE16";
+ break;
+ case MachO::DICE_KIND_JUMP_TABLE32:
+ outs() << "JUMP_TABLE32";
+ break;
+ case MachO::DICE_KIND_ABS_JUMP_TABLE32:
+ outs() << "ABS_JUMP_TABLE32";
+ break;
+ default:
+ outs() << format("0x%04" PRIx32, Kind);
+ break;
+ }
+ } else
+ outs() << format("0x%04" PRIx32, Kind);
+ outs() << "\n";
+ }
+}
+
+static void PrintLinkOptHints(MachOObjectFile *O) {
+ MachO::linkedit_data_command LohLC = O->getLinkOptHintsLoadCommand();
+ const char *loh = O->getData().substr(LohLC.dataoff, 1).data();
+ uint32_t nloh = LohLC.datasize;
+ outs() << "Linker optimiztion hints (" << nloh << " total bytes)\n";
+ for (uint32_t i = 0; i < nloh;) {
+ unsigned n;
+ uint64_t identifier = decodeULEB128((const uint8_t *)(loh + i), &n);
+ i += n;
+ outs() << " identifier " << identifier << " ";
+ if (i >= nloh)
+ return;
+ switch (identifier) {
+ case 1:
+ outs() << "AdrpAdrp\n";
+ break;
+ case 2:
+ outs() << "AdrpLdr\n";
+ break;
+ case 3:
+ outs() << "AdrpAddLdr\n";
+ break;
+ case 4:
+ outs() << "AdrpLdrGotLdr\n";
+ break;
+ case 5:
+ outs() << "AdrpAddStr\n";
+ break;
+ case 6:
+ outs() << "AdrpLdrGotStr\n";
+ break;
+ case 7:
+ outs() << "AdrpAdd\n";
+ break;
+ case 8:
+ outs() << "AdrpLdrGot\n";
+ break;
+ default:
+ outs() << "Unknown identifier value\n";
+ break;
+ }
+ uint64_t narguments = decodeULEB128((const uint8_t *)(loh + i), &n);
+ i += n;
+ outs() << " narguments " << narguments << "\n";
+ if (i >= nloh)
+ return;
+
+ for (uint32_t j = 0; j < narguments; j++) {
+ uint64_t value = decodeULEB128((const uint8_t *)(loh + i), &n);
+ i += n;
+ outs() << "\tvalue " << format("0x%" PRIx64, value) << "\n";
+ if (i >= nloh)
+ return;
+ }
+ }
+}
+
+static void PrintDylibs(MachOObjectFile *O, bool JustId) {
+ uint32_t LoadCommandCount = O->getHeader().ncmds;
+ MachOObjectFile::LoadCommandInfo Load = O->getFirstLoadCommandInfo();
+ for (unsigned I = 0;; ++I) {
+ if ((JustId && Load.C.cmd == MachO::LC_ID_DYLIB) ||
+ (!JustId && (Load.C.cmd == MachO::LC_ID_DYLIB ||
+ Load.C.cmd == MachO::LC_LOAD_DYLIB ||
+ Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB ||
+ Load.C.cmd == MachO::LC_REEXPORT_DYLIB ||
+ Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB ||
+ Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB))) {
+ MachO::dylib_command dl = O->getDylibIDLoadCommand(Load);
+ if (dl.dylib.name < dl.cmdsize) {
+ const char *p = (const char *)(Load.Ptr) + dl.dylib.name;
+ if (JustId)
+ outs() << p << "\n";
+ else {
+ outs() << "\t" << p;
+ outs() << " (compatibility version "
+ << ((dl.dylib.compatibility_version >> 16) & 0xffff) << "."
+ << ((dl.dylib.compatibility_version >> 8) & 0xff) << "."
+ << (dl.dylib.compatibility_version & 0xff) << ",";
+ outs() << " current version "
+ << ((dl.dylib.current_version >> 16) & 0xffff) << "."
+ << ((dl.dylib.current_version >> 8) & 0xff) << "."
+ << (dl.dylib.current_version & 0xff) << ")\n";
+ }
+ } else {
+ outs() << "\tBad offset (" << dl.dylib.name << ") for name of ";
+ if (Load.C.cmd == MachO::LC_ID_DYLIB)
+ outs() << "LC_ID_DYLIB ";
+ else if (Load.C.cmd == MachO::LC_LOAD_DYLIB)
+ outs() << "LC_LOAD_DYLIB ";
+ else if (Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB)
+ outs() << "LC_LOAD_WEAK_DYLIB ";
+ else if (Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB)
+ outs() << "LC_LAZY_LOAD_DYLIB ";
+ else if (Load.C.cmd == MachO::LC_REEXPORT_DYLIB)
+ outs() << "LC_REEXPORT_DYLIB ";
+ else if (Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB)
+ outs() << "LC_LOAD_UPWARD_DYLIB ";
+ else
+ outs() << "LC_??? ";
+ outs() << "command " << I << "\n";
+ }
+ }
+ if (I == LoadCommandCount - 1)
+ break;
+ else
+ Load = O->getNextLoadCommandInfo(Load);
+ }
+}
+
+typedef DenseMap<uint64_t, StringRef> SymbolAddressMap;
+
+static void CreateSymbolAddressMap(MachOObjectFile *O,
+ SymbolAddressMap *AddrMap) {
+ // Create a map of symbol addresses to symbol names.
+ for (const SymbolRef &Symbol : O->symbols()) {
+ SymbolRef::Type ST;
+ Symbol.getType(ST);
+ if (ST == SymbolRef::ST_Function || ST == SymbolRef::ST_Data ||
+ ST == SymbolRef::ST_Other) {
+ uint64_t Address;
+ Symbol.getAddress(Address);
+ StringRef SymName;
+ Symbol.getName(SymName);
+ if (!SymName.startswith(".objc"))
+ (*AddrMap)[Address] = SymName;
+ }
+ }
+}
+
+// GuessSymbolName is passed the address of what might be a symbol and a
+// pointer to the SymbolAddressMap. It returns the name of a symbol
+// with that address or nullptr if no symbol is found with that address.
+static const char *GuessSymbolName(uint64_t value, SymbolAddressMap *AddrMap) {
+ const char *SymbolName = nullptr;
+ // A DenseMap can't lookup up some values.
+ if (value != 0xffffffffffffffffULL && value != 0xfffffffffffffffeULL) {
+ StringRef name = AddrMap->lookup(value);
+ if (!name.empty())
+ SymbolName = name.data();
+ }
+ return SymbolName;
+}
+
+static void DumpCstringChar(const char c) {
+ char p[2];
+ p[0] = c;
+ p[1] = '\0';
+ outs().write_escaped(p);
+}
+
+static void DumpCstringSection(MachOObjectFile *O, const char *sect,
+ uint32_t sect_size, uint64_t sect_addr,
+ bool print_addresses) {
+ for (uint32_t i = 0; i < sect_size; i++) {
+ if (print_addresses) {
+ if (O->is64Bit())
+ outs() << format("%016" PRIx64, sect_addr + i) << " ";
+ else
+ outs() << format("%08" PRIx64, sect_addr + i) << " ";
+ }
+ for (; i < sect_size && sect[i] != '\0'; i++)
+ DumpCstringChar(sect[i]);
+ if (i < sect_size && sect[i] == '\0')
+ outs() << "\n";
+ }
+}
+
+static void DumpLiteral4(uint32_t l, float f) {
+ outs() << format("0x%08" PRIx32, l);
+ if ((l & 0x7f800000) != 0x7f800000)
+ outs() << format(" (%.16e)\n", f);
+ else {
+ if (l == 0x7f800000)
+ outs() << " (+Infinity)\n";
+ else if (l == 0xff800000)
+ outs() << " (-Infinity)\n";
+ else if ((l & 0x00400000) == 0x00400000)
+ outs() << " (non-signaling Not-a-Number)\n";
+ else
+ outs() << " (signaling Not-a-Number)\n";
+ }
+}
+
+static void DumpLiteral4Section(MachOObjectFile *O, const char *sect,
+ uint32_t sect_size, uint64_t sect_addr,
+ bool print_addresses) {
+ for (uint32_t i = 0; i < sect_size; i += sizeof(float)) {
+ if (print_addresses) {
+ if (O->is64Bit())
+ outs() << format("%016" PRIx64, sect_addr + i) << " ";
+ else
+ outs() << format("%08" PRIx64, sect_addr + i) << " ";
+ }
+ float f;
+ memcpy(&f, sect + i, sizeof(float));
+ if (O->isLittleEndian() != sys::IsLittleEndianHost)
+ sys::swapByteOrder(f);
+ uint32_t l;
+ memcpy(&l, sect + i, sizeof(uint32_t));
+ if (O->isLittleEndian() != sys::IsLittleEndianHost)
+ sys::swapByteOrder(l);
+ DumpLiteral4(l, f);
+ }
+}
+
+static void DumpLiteral8(MachOObjectFile *O, uint32_t l0, uint32_t l1,
+ double d) {
+ outs() << format("0x%08" PRIx32, l0) << " " << format("0x%08" PRIx32, l1);
+ uint32_t Hi, Lo;
+ if (O->isLittleEndian()) {
+ Hi = l1;
+ Lo = l0;
+ } else {
+ Hi = l0;
+ Lo = l1;
+ }
+ // Hi is the high word, so this is equivalent to if(isfinite(d))
+ if ((Hi & 0x7ff00000) != 0x7ff00000)
+ outs() << format(" (%.16e)\n", d);
+ else {
+ if (Hi == 0x7ff00000 && Lo == 0)
+ outs() << " (+Infinity)\n";
+ else if (Hi == 0xfff00000 && Lo == 0)
+ outs() << " (-Infinity)\n";
+ else if ((Hi & 0x00080000) == 0x00080000)
+ outs() << " (non-signaling Not-a-Number)\n";
+ else
+ outs() << " (signaling Not-a-Number)\n";
+ }
+}
+
+static void DumpLiteral8Section(MachOObjectFile *O, const char *sect,
+ uint32_t sect_size, uint64_t sect_addr,
+ bool print_addresses) {
+ for (uint32_t i = 0; i < sect_size; i += sizeof(double)) {
+ if (print_addresses) {
+ if (O->is64Bit())
+ outs() << format("%016" PRIx64, sect_addr + i) << " ";
+ else
+ outs() << format("%08" PRIx64, sect_addr + i) << " ";
+ }
+ double d;
+ memcpy(&d, sect + i, sizeof(double));
+ if (O->isLittleEndian() != sys::IsLittleEndianHost)
+ sys::swapByteOrder(d);
+ uint32_t l0, l1;
+ memcpy(&l0, sect + i, sizeof(uint32_t));
+ memcpy(&l1, sect + i + sizeof(uint32_t), sizeof(uint32_t));
+ if (O->isLittleEndian() != sys::IsLittleEndianHost) {
+ sys::swapByteOrder(l0);
+ sys::swapByteOrder(l1);
+ }
+ DumpLiteral8(O, l0, l1, d);
+ }
+}
+
+static void DumpLiteral16(uint32_t l0, uint32_t l1, uint32_t l2, uint32_t l3) {
+ outs() << format("0x%08" PRIx32, l0) << " ";
+ outs() << format("0x%08" PRIx32, l1) << " ";
+ outs() << format("0x%08" PRIx32, l2) << " ";
+ outs() << format("0x%08" PRIx32, l3) << "\n";
+}
+
+static void DumpLiteral16Section(MachOObjectFile *O, const char *sect,
+ uint32_t sect_size, uint64_t sect_addr,
+ bool print_addresses) {
+ for (uint32_t i = 0; i < sect_size; i += 16) {
+ if (print_addresses) {
+ if (O->is64Bit())
+ outs() << format("%016" PRIx64, sect_addr + i) << " ";
+ else
+ outs() << format("%08" PRIx64, sect_addr + i) << " ";
+ }
+ uint32_t l0, l1, l2, l3;
+ memcpy(&l0, sect + i, sizeof(uint32_t));
+ memcpy(&l1, sect + i + sizeof(uint32_t), sizeof(uint32_t));
+ memcpy(&l2, sect + i + 2 * sizeof(uint32_t), sizeof(uint32_t));
+ memcpy(&l3, sect + i + 3 * sizeof(uint32_t), sizeof(uint32_t));
+ if (O->isLittleEndian() != sys::IsLittleEndianHost) {
+ sys::swapByteOrder(l0);
+ sys::swapByteOrder(l1);
+ sys::swapByteOrder(l2);
+ sys::swapByteOrder(l3);
+ }
+ DumpLiteral16(l0, l1, l2, l3);
+ }
+}
+
+static void DumpLiteralPointerSection(MachOObjectFile *O,
+ const SectionRef &Section,
+ const char *sect, uint32_t sect_size,
+ uint64_t sect_addr,
+ bool print_addresses) {
+ // Collect the literal sections in this Mach-O file.
+ std::vector<SectionRef> LiteralSections;
+ for (const SectionRef &Section : O->sections()) {
+ DataRefImpl Ref = Section.getRawDataRefImpl();
+ uint32_t section_type;
+ if (O->is64Bit()) {
+ const MachO::section_64 Sec = O->getSection64(Ref);
+ section_type = Sec.flags & MachO::SECTION_TYPE;
+ } else {
+ const MachO::section Sec = O->getSection(Ref);
+ section_type = Sec.flags & MachO::SECTION_TYPE;
+ }
+ if (section_type == MachO::S_CSTRING_LITERALS ||
+ section_type == MachO::S_4BYTE_LITERALS ||
+ section_type == MachO::S_8BYTE_LITERALS ||
+ section_type == MachO::S_16BYTE_LITERALS)
+ LiteralSections.push_back(Section);
+ }
+
+ // Set the size of the literal pointer.
+ uint32_t lp_size = O->is64Bit() ? 8 : 4;
+
+ // Collect the external relocation symbols for the the literal pointers.
+ std::vector<std::pair<uint64_t, SymbolRef>> Relocs;
+ for (const RelocationRef &Reloc : Section.relocations()) {
+ DataRefImpl Rel;
+ MachO::any_relocation_info RE;
+ bool isExtern = false;
+ Rel = Reloc.getRawDataRefImpl();
+ RE = O->getRelocation(Rel);
+ isExtern = O->getPlainRelocationExternal(RE);
+ if (isExtern) {
+ uint64_t RelocOffset;
+ Reloc.getOffset(RelocOffset);
+ symbol_iterator RelocSym = Reloc.getSymbol();
+ Relocs.push_back(std::make_pair(RelocOffset, *RelocSym));
+ }
+ }
+ array_pod_sort(Relocs.begin(), Relocs.end());
+
+ // Dump each literal pointer.
+ for (uint32_t i = 0; i < sect_size; i += lp_size) {
+ if (print_addresses) {
+ if (O->is64Bit())
+ outs() << format("%016" PRIx64, sect_addr + i) << " ";
+ else
+ outs() << format("%08" PRIx64, sect_addr + i) << " ";
+ }
+ uint64_t lp;
+ if (O->is64Bit()) {
+ memcpy(&lp, sect + i, sizeof(uint64_t));
+ if (O->isLittleEndian() != sys::IsLittleEndianHost)
+ sys::swapByteOrder(lp);
+ } else {
+ uint32_t li;
+ memcpy(&li, sect + i, sizeof(uint32_t));
+ if (O->isLittleEndian() != sys::IsLittleEndianHost)
+ sys::swapByteOrder(li);
+ lp = li;
+ }
+
+ // First look for an external relocation entry for this literal pointer.
+ auto Reloc = std::find_if(
+ Relocs.begin(), Relocs.end(),
+ [&](const std::pair<uint64_t, SymbolRef> &P) { return P.first == i; });
+ if (Reloc != Relocs.end()) {
+ symbol_iterator RelocSym = Reloc->second;
+ StringRef SymName;
+ RelocSym->getName(SymName);
+ outs() << "external relocation entry for symbol:" << SymName << "\n";
+ continue;
+ }
+
+ // For local references see what the section the literal pointer points to.
+ auto Sect = std::find_if(LiteralSections.begin(), LiteralSections.end(),
+ [&](const SectionRef &R) {
+ return lp >= R.getAddress() &&
+ lp < R.getAddress() + R.getSize();
+ });
+ if (Sect == LiteralSections.end()) {
+ outs() << format("0x%" PRIx64, lp) << " (not in a literal section)\n";
+ continue;
+ }
+
+ uint64_t SectAddress = Sect->getAddress();
+ uint64_t SectSize = Sect->getSize();
+
+ StringRef SectName;
+ Sect->getName(SectName);
+ DataRefImpl Ref = Sect->getRawDataRefImpl();
+ StringRef SegmentName = O->getSectionFinalSegmentName(Ref);
+ outs() << SegmentName << ":" << SectName << ":";
+
+ uint32_t section_type;
+ if (O->is64Bit()) {
+ const MachO::section_64 Sec = O->getSection64(Ref);
+ section_type = Sec.flags & MachO::SECTION_TYPE;
+ } else {
+ const MachO::section Sec = O->getSection(Ref);
+ section_type = Sec.flags & MachO::SECTION_TYPE;
+ }
+
+ StringRef BytesStr;
+ Sect->getContents(BytesStr);
+ const char *Contents = reinterpret_cast<const char *>(BytesStr.data());
+
+ switch (section_type) {
+ case MachO::S_CSTRING_LITERALS:
+ for (uint64_t i = lp - SectAddress; i < SectSize && Contents[i] != '\0';
+ i++) {
+ DumpCstringChar(Contents[i]);
+ }
+ outs() << "\n";
+ break;
+ case MachO::S_4BYTE_LITERALS:
+ float f;
+ memcpy(&f, Contents + (lp - SectAddress), sizeof(float));
+ uint32_t l;
+ memcpy(&l, Contents + (lp - SectAddress), sizeof(uint32_t));
+ if (O->isLittleEndian() != sys::IsLittleEndianHost) {
+ sys::swapByteOrder(f);
+ sys::swapByteOrder(l);
+ }
+ DumpLiteral4(l, f);
+ break;
+ case MachO::S_8BYTE_LITERALS: {
+ double d;
+ memcpy(&d, Contents + (lp - SectAddress), sizeof(double));
+ uint32_t l0, l1;
+ memcpy(&l0, Contents + (lp - SectAddress), sizeof(uint32_t));
+ memcpy(&l1, Contents + (lp - SectAddress) + sizeof(uint32_t),
+ sizeof(uint32_t));
+ if (O->isLittleEndian() != sys::IsLittleEndianHost) {
+ sys::swapByteOrder(f);
+ sys::swapByteOrder(l0);
+ sys::swapByteOrder(l1);
+ }
+ DumpLiteral8(O, l0, l1, d);
+ break;
+ }
+ case MachO::S_16BYTE_LITERALS: {
+ uint32_t l0, l1, l2, l3;
+ memcpy(&l0, Contents + (lp - SectAddress), sizeof(uint32_t));
+ memcpy(&l1, Contents + (lp - SectAddress) + sizeof(uint32_t),
+ sizeof(uint32_t));
+ memcpy(&l2, Contents + (lp - SectAddress) + 2 * sizeof(uint32_t),
+ sizeof(uint32_t));
+ memcpy(&l3, Contents + (lp - SectAddress) + 3 * sizeof(uint32_t),
+ sizeof(uint32_t));
+ if (O->isLittleEndian() != sys::IsLittleEndianHost) {
+ sys::swapByteOrder(l0);
+ sys::swapByteOrder(l1);
+ sys::swapByteOrder(l2);
+ sys::swapByteOrder(l3);
+ }
+ DumpLiteral16(l0, l1, l2, l3);
+ break;
+ }
+ }
+ }
+}
+
+static void DumpInitTermPointerSection(MachOObjectFile *O, const char *sect,
+ uint32_t sect_size, uint64_t sect_addr,
+ SymbolAddressMap *AddrMap,
+ bool verbose) {
+ uint32_t stride;
+ if (O->is64Bit())
+ stride = sizeof(uint64_t);
+ else
+ stride = sizeof(uint32_t);
+ for (uint32_t i = 0; i < sect_size; i += stride) {
+ const char *SymbolName = nullptr;
+ if (O->is64Bit()) {
+ outs() << format("0x%016" PRIx64, sect_addr + i * stride) << " ";
+ uint64_t pointer_value;
+ memcpy(&pointer_value, sect + i, stride);
+ if (O->isLittleEndian() != sys::IsLittleEndianHost)
+ sys::swapByteOrder(pointer_value);
+ outs() << format("0x%016" PRIx64, pointer_value);
+ if (verbose)
+ SymbolName = GuessSymbolName(pointer_value, AddrMap);
+ } else {
+ outs() << format("0x%08" PRIx64, sect_addr + i * stride) << " ";
+ uint32_t pointer_value;
+ memcpy(&pointer_value, sect + i, stride);
+ if (O->isLittleEndian() != sys::IsLittleEndianHost)
+ sys::swapByteOrder(pointer_value);
+ outs() << format("0x%08" PRIx32, pointer_value);
+ if (verbose)
+ SymbolName = GuessSymbolName(pointer_value, AddrMap);
+ }
+ if (SymbolName)
+ outs() << " " << SymbolName;
+ outs() << "\n";
+ }
+}
+
+static void DumpRawSectionContents(MachOObjectFile *O, const char *sect,
+ uint32_t size, uint64_t addr) {
+ uint32_t cputype = O->getHeader().cputype;
+ if (cputype == MachO::CPU_TYPE_I386 || cputype == MachO::CPU_TYPE_X86_64) {
+ uint32_t j;
+ for (uint32_t i = 0; i < size; i += j, addr += j) {
+ if (O->is64Bit())
+ outs() << format("%016" PRIx64, addr) << "\t";
+ else
+ outs() << format("%08" PRIx64, addr) << "\t";
+ for (j = 0; j < 16 && i + j < size; j++) {
+ uint8_t byte_word = *(sect + i + j);
+ outs() << format("%02" PRIx32, (uint32_t)byte_word) << " ";
+ }
+ outs() << "\n";
+ }
+ } else {
+ uint32_t j;
+ for (uint32_t i = 0; i < size; i += j, addr += j) {
+ if (O->is64Bit())
+ outs() << format("%016" PRIx64, addr) << "\t";
+ else
+ outs() << format("%08" PRIx64, sect) << "\t";
+ for (j = 0; j < 4 * sizeof(int32_t) && i + j < size;
+ j += sizeof(int32_t)) {
+ if (i + j + sizeof(int32_t) < size) {
+ uint32_t long_word;
+ memcpy(&long_word, sect + i + j, sizeof(int32_t));
+ if (O->isLittleEndian() != sys::IsLittleEndianHost)
+ sys::swapByteOrder(long_word);
+ outs() << format("%08" PRIx32, long_word) << " ";
+ } else {
+ for (uint32_t k = 0; i + j + k < size; k++) {
+ uint8_t byte_word = *(sect + i + j);
+ outs() << format("%02" PRIx32, (uint32_t)byte_word) << " ";
+ }
+ }
+ }
+ outs() << "\n";
+ }
+ }
+}
+
+static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF,
+ StringRef DisSegName, StringRef DisSectName);
+static void DumpProtocolSection(MachOObjectFile *O, const char *sect,
+ uint32_t size, uint32_t addr);
+
+static void DumpSectionContents(StringRef Filename, MachOObjectFile *O,
+ bool verbose) {
+ SymbolAddressMap AddrMap;
+ if (verbose)
+ CreateSymbolAddressMap(O, &AddrMap);
+
+ for (unsigned i = 0; i < DumpSections.size(); ++i) {
+ StringRef DumpSection = DumpSections[i];
+ std::pair<StringRef, StringRef> DumpSegSectName;
+ DumpSegSectName = DumpSection.split(',');
+ StringRef DumpSegName, DumpSectName;
+ if (DumpSegSectName.second.size()) {
+ DumpSegName = DumpSegSectName.first;
+ DumpSectName = DumpSegSectName.second;
+ } else {
+ DumpSegName = "";
+ DumpSectName = DumpSegSectName.first;
+ }
+ for (const SectionRef &Section : O->sections()) {
+ StringRef SectName;
+ Section.getName(SectName);
+ DataRefImpl Ref = Section.getRawDataRefImpl();
+ StringRef SegName = O->getSectionFinalSegmentName(Ref);
+ if ((DumpSegName.empty() || SegName == DumpSegName) &&
+ (SectName == DumpSectName)) {
+
+ uint32_t section_flags;
+ if (O->is64Bit()) {
+ const MachO::section_64 Sec = O->getSection64(Ref);
+ section_flags = Sec.flags;
+
+ } else {
+ const MachO::section Sec = O->getSection(Ref);
+ section_flags = Sec.flags;
+ }
+ uint32_t section_type = section_flags & MachO::SECTION_TYPE;
+
+ StringRef BytesStr;
+ Section.getContents(BytesStr);
+ const char *sect = reinterpret_cast<const char *>(BytesStr.data());
+ 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";
+
+ if (verbose) {
+ if ((section_flags & MachO::S_ATTR_PURE_INSTRUCTIONS) ||
+ (section_flags & MachO::S_ATTR_SOME_INSTRUCTIONS)) {
+ DisassembleMachO(Filename, O, SegName, SectName);
+ continue;
+ }
+ if (SegName == "__TEXT" && SectName == "__info_plist") {
+ outs() << sect;
+ continue;
+ }
+ if (SegName == "__OBJC" && SectName == "__protocol") {
+ DumpProtocolSection(O, sect, sect_size, sect_addr);
+ continue;
+ }
+ switch (section_type) {
+ case MachO::S_REGULAR:
+ DumpRawSectionContents(O, sect, sect_size, sect_addr);
+ break;
+ case MachO::S_ZEROFILL:
+ outs() << "zerofill section and has no contents in the file\n";
+ break;
+ case MachO::S_CSTRING_LITERALS:
+ DumpCstringSection(O, sect, sect_size, sect_addr, !NoLeadingAddr);
+ break;
+ case MachO::S_4BYTE_LITERALS:
+ DumpLiteral4Section(O, sect, sect_size, sect_addr, !NoLeadingAddr);
+ break;
+ case MachO::S_8BYTE_LITERALS:
+ DumpLiteral8Section(O, sect, sect_size, sect_addr, !NoLeadingAddr);
+ break;
+ case MachO::S_16BYTE_LITERALS:
+ DumpLiteral16Section(O, sect, sect_size, sect_addr, !NoLeadingAddr);
+ break;
+ case MachO::S_LITERAL_POINTERS:
+ DumpLiteralPointerSection(O, Section, sect, sect_size, sect_addr,
+ !NoLeadingAddr);
+ break;
+ case MachO::S_MOD_INIT_FUNC_POINTERS:
+ case MachO::S_MOD_TERM_FUNC_POINTERS:
+ DumpInitTermPointerSection(O, sect, sect_size, sect_addr, &AddrMap,
+ verbose);
+ break;
+ default:
+ outs() << "Unknown section type ("
+ << format("0x%08" PRIx32, section_type) << ")\n";
+ DumpRawSectionContents(O, sect, sect_size, sect_addr);
+ break;
+ }
+ } else {
+ if (section_type == MachO::S_ZEROFILL)
+ outs() << "zerofill section and has no contents in the file\n";
+ else
+ DumpRawSectionContents(O, sect, sect_size, sect_addr);
+ }
+ }
+ }
+ }
+}
+
+static void DumpInfoPlistSectionContents(StringRef Filename,
+ MachOObjectFile *O) {
+ for (const SectionRef &Section : O->sections()) {
+ StringRef SectName;
+ Section.getName(SectName);
+ DataRefImpl Ref = Section.getRawDataRefImpl();
+ StringRef SegName = O->getSectionFinalSegmentName(Ref);
+ if (SegName == "__TEXT" && SectName == "__info_plist") {
+ outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
+ StringRef BytesStr;
+ Section.getContents(BytesStr);
+ const char *sect = reinterpret_cast<const char *>(BytesStr.data());
+ outs() << sect;
+ return;
+ }
+ }
+}
+
// checkMachOAndArchFlags() checks to see if the ObjectFile is a Mach-O file
// and if it is and there is a list of architecture flags is specified then
// check to make sure this Mach-O file is one of those architectures or all
@@ -289,7 +1197,7 @@ static bool checkMachOAndArchFlags(ObjectFile *O, StringRef Filename) {
return true;
}
-static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF);
+static void printObjcMetaData(MachOObjectFile *O, bool verbose);
// ProcessMachO() is passed a single opened Mach-O file, which may be an
// archive member and or in a slice of a universal file. It prints the
@@ -300,9 +1208,11 @@ static void ProcessMachO(StringRef Filename, MachOObjectFile *MachOOF,
StringRef ArchitectureName = StringRef()) {
// If we are doing some processing here on the Mach-O file print the header
// info. And don't print it otherwise like in the case of printing the
- // UniversalHeaders.
+ // UniversalHeaders or ArchiveHeaders.
if (Disassemble || PrivateHeaders || ExportsTrie || Rebase || Bind ||
- LazyBind || WeakBind) {
+ LazyBind || WeakBind || IndirectSymbols || DataInCode || LinkOptHints ||
+ DylibsUsed || DylibId || ObjcMetaData ||
+ (DumpSections.size() != 0 && !Raw)) {
outs() << Filename;
if (!ArchiveMemberName.empty())
outs() << '(' << ArchiveMemberName << ')';
@@ -312,23 +1222,35 @@ static void ProcessMachO(StringRef Filename, MachOObjectFile *MachOOF,
}
if (Disassemble)
- DisassembleMachO(Filename, MachOOF);
- // TODO: These should/could be printed in Darwin's otool(1) or nm(1) style
- // for -macho. Or just used a new option that maps to the otool(1)
- // option like -r, -l, etc. Or just the normal llvm-objdump option
- // but now for this slice so that the -arch options can be used.
- // if (Relocations)
- // PrintRelocations(MachOOF);
- // if (SectionHeaders)
- // PrintSectionHeaders(MachOOF);
- // if (SectionContents)
- // PrintSectionContents(MachOOF);
- // if (SymbolTable)
- // PrintSymbolTable(MachOOF);
- // if (UnwindInfo)
- // PrintUnwindInfo(MachOOF);
+ DisassembleMachO(Filename, MachOOF, "__TEXT", "__text");
+ if (IndirectSymbols)
+ PrintIndirectSymbols(MachOOF, !NonVerbose);
+ if (DataInCode)
+ PrintDataInCodeTable(MachOOF, !NonVerbose);
+ if (LinkOptHints)
+ PrintLinkOptHints(MachOOF);
+ if (Relocations)
+ PrintRelocations(MachOOF);
+ if (SectionHeaders)
+ PrintSectionHeaders(MachOOF);
+ if (SectionContents)
+ PrintSectionContents(MachOOF);
+ if (DumpSections.size() != 0)
+ DumpSectionContents(Filename, MachOOF, !NonVerbose);
+ if (InfoPlist)
+ DumpInfoPlistSectionContents(Filename, MachOOF);
+ if (DylibsUsed)
+ PrintDylibs(MachOOF, false);
+ if (DylibId)
+ PrintDylibs(MachOOF, true);
+ if (SymbolTable)
+ PrintSymbolTable(MachOOF);
+ if (UnwindInfo)
+ printMachOUnwindInfo(MachOOF);
if (PrivateHeaders)
printMachOFileHeader(MachOOF);
+ if (ObjcMetaData)
+ printObjcMetaData(MachOOF, !NonVerbose);
if (ExportsTrie)
printExportsTrie(MachOOF);
if (Rebase)
@@ -514,6 +1436,106 @@ static void printMachOUniversalHeaders(const object::MachOUniversalBinary *UB,
}
}
+static void printArchiveChild(Archive::Child &C, bool verbose,
+ bool print_offset) {
+ if (print_offset)
+ outs() << C.getChildOffset() << "\t";
+ sys::fs::perms Mode = C.getAccessMode();
+ if (verbose) {
+ // FIXME: this first dash, "-", is for (Mode & S_IFMT) == S_IFREG.
+ // But there is nothing in sys::fs::perms for S_IFMT or S_IFREG.
+ outs() << "-";
+ if (Mode & sys::fs::owner_read)
+ outs() << "r";
+ else
+ outs() << "-";
+ if (Mode & sys::fs::owner_write)
+ outs() << "w";
+ else
+ outs() << "-";
+ if (Mode & sys::fs::owner_exe)
+ outs() << "x";
+ else
+ outs() << "-";
+ if (Mode & sys::fs::group_read)
+ outs() << "r";
+ else
+ outs() << "-";
+ if (Mode & sys::fs::group_write)
+ outs() << "w";
+ else
+ outs() << "-";
+ if (Mode & sys::fs::group_exe)
+ outs() << "x";
+ else
+ outs() << "-";
+ if (Mode & sys::fs::others_read)
+ outs() << "r";
+ else
+ outs() << "-";
+ if (Mode & sys::fs::others_write)
+ outs() << "w";
+ else
+ outs() << "-";
+ if (Mode & sys::fs::others_exe)
+ outs() << "x";
+ else
+ outs() << "-";
+ } else {
+ outs() << format("0%o ", Mode);
+ }
+
+ unsigned UID = C.getUID();
+ outs() << format("%3d/", UID);
+ unsigned GID = C.getGID();
+ outs() << format("%-3d ", GID);
+ uint64_t Size = C.getRawSize();
+ outs() << format("%5" PRId64, Size) << " ";
+
+ StringRef RawLastModified = C.getRawLastModified();
+ if (verbose) {
+ unsigned Seconds;
+ if (RawLastModified.getAsInteger(10, Seconds))
+ outs() << "(date: \"%s\" contains non-decimal chars) " << RawLastModified;
+ else {
+ // Since cime(3) returns a 26 character string of the form:
+ // "Sun Sep 16 01:03:52 1973\n\0"
+ // just print 24 characters.
+ time_t t = Seconds;
+ outs() << format("%.24s ", ctime(&t));
+ }
+ } else {
+ outs() << RawLastModified << " ";
+ }
+
+ if (verbose) {
+ ErrorOr<StringRef> NameOrErr = C.getName();
+ if (NameOrErr.getError()) {
+ StringRef RawName = C.getRawName();
+ outs() << RawName << "\n";
+ } else {
+ StringRef Name = NameOrErr.get();
+ outs() << Name << "\n";
+ }
+ } else {
+ StringRef RawName = C.getRawName();
+ outs() << RawName << "\n";
+ }
+}
+
+static void printArchiveHeaders(Archive *A, bool verbose, bool print_offset) {
+ if (A->hasSymbolTable()) {
+ Archive::child_iterator S = A->getSymbolTableChild();
+ Archive::Child C = *S;
+ printArchiveChild(C, verbose, print_offset);
+ }
+ for (Archive::child_iterator I = A->child_begin(), E = A->child_end(); I != E;
+ ++I) {
+ Archive::Child C = *I;
+ printArchiveChild(C, verbose, print_offset);
+ }
+}
+
// ParseInputMachO() parses the named Mach-O file in Filename and handles the
// -arch flags selecting just those slices as specified by them and also parses
// archive files. Then for each individual Mach-O file ProcessMachO() is
@@ -542,6 +1564,8 @@ void llvm::ParseInputMachO(StringRef Filename) {
if (Archive *A = dyn_cast<Archive>(&Bin)) {
outs() << "Archive : " << Filename << "\n";
+ if (ArchiveHeaders)
+ printArchiveHeaders(A, !NonVerbose, ArchiveMemberOffsets);
for (Archive::child_iterator I = A->child_begin(), E = A->child_end();
I != E; ++I) {
ErrorOr<std::unique_ptr<Binary>> ChildOrErr = I->getAsBinary();
@@ -557,7 +1581,7 @@ void llvm::ParseInputMachO(StringRef Filename) {
}
if (UniversalHeaders) {
if (MachOUniversalBinary *UB = dyn_cast<MachOUniversalBinary>(&Bin))
- printMachOUniversalHeaders(UB, true);
+ printMachOUniversalHeaders(UB, !NonVerbose);
}
if (MachOUniversalBinary *UB = dyn_cast<MachOUniversalBinary>(&Bin)) {
// If we have a list of architecture flags specified dump only those.
@@ -587,6 +1611,8 @@ void llvm::ParseInputMachO(StringRef Filename) {
if (!ArchitectureName.empty())
outs() << " (architecture " << ArchitectureName << ")";
outs() << "\n";
+ if (ArchiveHeaders)
+ printArchiveHeaders(A.get(), !NonVerbose, ArchiveMemberOffsets);
for (Archive::child_iterator AI = A->child_begin(),
AE = A->child_end();
AI != AE; ++AI) {
@@ -627,6 +1653,8 @@ void llvm::ParseInputMachO(StringRef Filename) {
I->getAsArchive()) {
std::unique_ptr<Archive> &A = *AOrErr;
outs() << "Archive : " << Filename << "\n";
+ if (ArchiveHeaders)
+ printArchiveHeaders(A.get(), !NonVerbose, ArchiveMemberOffsets);
for (Archive::child_iterator AI = A->child_begin(),
AE = A->child_end();
AI != AE; ++AI) {
@@ -662,6 +1690,8 @@ void llvm::ParseInputMachO(StringRef Filename) {
if (!ArchitectureName.empty())
outs() << " (architecture " << ArchitectureName << ")";
outs() << "\n";
+ if (ArchiveHeaders)
+ printArchiveHeaders(A.get(), !NonVerbose, ArchiveMemberOffsets);
for (Archive::child_iterator AI = A->child_begin(), AE = A->child_end();
AI != AE; ++AI) {
ErrorOr<std::unique_ptr<Binary>> ChildOrErr = AI->getAsBinary();
@@ -691,7 +1721,6 @@ void llvm::ParseInputMachO(StringRef Filename) {
<< "Unrecognized file type.\n";
}
-typedef DenseMap<uint64_t, StringRef> SymbolAddressMap;
typedef std::pair<uint64_t, const char *> BindInfoEntry;
typedef std::vector<BindInfoEntry> BindTable;
typedef BindTable::iterator bind_table_iterator;
@@ -712,21 +1741,6 @@ struct DisassembleInfo {
BindTable *bindtable;
};
-// GuessSymbolName is passed the address of what might be a symbol and a
-// pointer to the DisassembleInfo struct. It returns the name of a symbol
-// with that address or nullptr if no symbol is found with that address.
-static const char *GuessSymbolName(uint64_t value,
- struct DisassembleInfo *info) {
- const char *SymbolName = nullptr;
- // A DenseMap can't lookup up some values.
- if (value != 0xffffffffffffffffULL && value != 0xfffffffffffffffeULL) {
- StringRef name = info->AddrMap->lookup(value);
- if (!name.empty())
- SymbolName = name.data();
- }
- return SymbolName;
-}
-
// SymbolizerGetOpInfo() is the operand information call back function.
// This is called to get the symbolic information for operand(s) of an
// instruction when it is being done. This routine does this from
@@ -742,8 +1756,8 @@ static const char *GuessSymbolName(uint64_t value,
// names and addends of the symbolic expression to add for the operand. The
// value of TagType is currently 1 (for the LLVMOpInfo1 struct). If symbolic
// information is returned then this function returns 1 else it returns 0.
-int SymbolizerGetOpInfo(void *DisInfo, uint64_t Pc, uint64_t Offset,
- uint64_t Size, int TagType, void *TagBuf) {
+static int SymbolizerGetOpInfo(void *DisInfo, uint64_t Pc, uint64_t Offset,
+ uint64_t Size, int TagType, void *TagBuf) {
struct DisassembleInfo *info = (struct DisassembleInfo *)DisInfo;
struct LLVMOpInfo1 *op_info = (struct LLVMOpInfo1 *)TagBuf;
uint64_t value = op_info->Value;
@@ -755,7 +1769,7 @@ int SymbolizerGetOpInfo(void *DisInfo, uint64_t Pc, uint64_t Offset,
// If the TagType is not the value 1 which it code knows about or if no
// verbose symbolic information is wanted then just return 0, indicating no
// information is being returned.
- if (TagType != 1 || info->verbose == false)
+ if (TagType != 1 || !info->verbose)
return 0;
unsigned int Arch = info->O->getArch();
@@ -817,8 +1831,8 @@ int SymbolizerGetOpInfo(void *DisInfo, uint64_t Pc, uint64_t Offset,
}
if (reloc_found && (r_type == MachO::GENERIC_RELOC_SECTDIFF ||
r_type == MachO::GENERIC_RELOC_LOCAL_SECTDIFF)) {
- const char *add = GuessSymbolName(r_value, info);
- const char *sub = GuessSymbolName(pair_r_value, info);
+ const char *add = GuessSymbolName(r_value, info->AddrMap);
+ const char *sub = GuessSymbolName(pair_r_value, info->AddrMap);
uint32_t offset = value - (r_value - pair_r_value);
op_info->AddSymbol.Present = 1;
if (add != nullptr)
@@ -838,7 +1852,8 @@ int SymbolizerGetOpInfo(void *DisInfo, uint64_t Pc, uint64_t Offset,
// (if any) for an entry that matches this segment offset.
// uint32_t seg_offset = (Pc + Offset);
return 0;
- } else if (Arch == Triple::x86_64) {
+ }
+ if (Arch == Triple::x86_64) {
if (Size != 1 && Size != 2 && Size != 4 && Size != 0)
return 0;
// First search the section's relocation entries (if any) for an entry
@@ -904,89 +1919,77 @@ int SymbolizerGetOpInfo(void *DisInfo, uint64_t Pc, uint64_t Offset,
// (if any) for an entry that matches this segment offset.
// uint64_t seg_offset = (Pc + Offset);
return 0;
- } else if (Arch == Triple::arm) {
+ }
+ if (Arch == Triple::arm) {
if (Offset != 0 || (Size != 4 && Size != 2))
return 0;
// First search the section's relocation entries (if any) for an entry
// for this section offset.
uint32_t sect_addr = info->S.getAddress();
uint32_t sect_offset = (Pc + Offset) - sect_addr;
- bool reloc_found = false;
DataRefImpl Rel;
MachO::any_relocation_info RE;
bool isExtern = false;
SymbolRef Symbol;
bool r_scattered = false;
uint32_t r_value, pair_r_value, r_type, r_length, other_half;
- for (const RelocationRef &Reloc : info->S.relocations()) {
- uint64_t RelocOffset;
- Reloc.getOffset(RelocOffset);
- if (RelocOffset == sect_offset) {
- Rel = Reloc.getRawDataRefImpl();
- RE = info->O->getRelocation(Rel);
- r_length = info->O->getAnyRelocationLength(RE);
- r_scattered = info->O->isRelocationScattered(RE);
- if (r_scattered) {
- r_value = info->O->getScatteredRelocationValue(RE);
- r_type = info->O->getScatteredRelocationType(RE);
- } else {
- r_type = info->O->getAnyRelocationType(RE);
- isExtern = info->O->getPlainRelocationExternal(RE);
- if (isExtern) {
- symbol_iterator RelocSym = Reloc.getSymbol();
- Symbol = *RelocSym;
- }
- }
- if (r_type == MachO::ARM_RELOC_HALF ||
- r_type == MachO::ARM_RELOC_SECTDIFF ||
- r_type == MachO::ARM_RELOC_LOCAL_SECTDIFF ||
- r_type == MachO::ARM_RELOC_HALF_SECTDIFF) {
- DataRefImpl RelNext = Rel;
- info->O->moveRelocationNext(RelNext);
- MachO::any_relocation_info RENext;
- RENext = info->O->getRelocation(RelNext);
- other_half = info->O->getAnyRelocationAddress(RENext) & 0xffff;
- if (info->O->isRelocationScattered(RENext))
- pair_r_value = info->O->getScatteredRelocationValue(RENext);
- }
- reloc_found = true;
- break;
+ auto Reloc =
+ std::find_if(info->S.relocations().begin(), info->S.relocations().end(),
+ [&](const RelocationRef &Reloc) {
+ uint64_t RelocOffset;
+ Reloc.getOffset(RelocOffset);
+ return RelocOffset == sect_offset;
+ });
+
+ if (Reloc == info->S.relocations().end())
+ return 0;
+
+ Rel = Reloc->getRawDataRefImpl();
+ RE = info->O->getRelocation(Rel);
+ r_length = info->O->getAnyRelocationLength(RE);
+ r_scattered = info->O->isRelocationScattered(RE);
+ if (r_scattered) {
+ r_value = info->O->getScatteredRelocationValue(RE);
+ r_type = info->O->getScatteredRelocationType(RE);
+ } else {
+ r_type = info->O->getAnyRelocationType(RE);
+ isExtern = info->O->getPlainRelocationExternal(RE);
+ if (isExtern) {
+ symbol_iterator RelocSym = Reloc->getSymbol();
+ Symbol = *RelocSym;
}
}
- if (reloc_found && isExtern) {
+ if (r_type == MachO::ARM_RELOC_HALF ||
+ r_type == MachO::ARM_RELOC_SECTDIFF ||
+ r_type == MachO::ARM_RELOC_LOCAL_SECTDIFF ||
+ r_type == MachO::ARM_RELOC_HALF_SECTDIFF) {
+ DataRefImpl RelNext = Rel;
+ info->O->moveRelocationNext(RelNext);
+ MachO::any_relocation_info RENext;
+ RENext = info->O->getRelocation(RelNext);
+ other_half = info->O->getAnyRelocationAddress(RENext) & 0xffff;
+ if (info->O->isRelocationScattered(RENext))
+ pair_r_value = info->O->getScatteredRelocationValue(RENext);
+ }
+
+ if (isExtern) {
StringRef SymName;
Symbol.getName(SymName);
const char *name = SymName.data();
op_info->AddSymbol.Present = 1;
op_info->AddSymbol.Name = name;
- if (value != 0) {
- switch (r_type) {
- case MachO::ARM_RELOC_HALF:
- if ((r_length & 0x1) == 1) {
- op_info->Value = value << 16 | other_half;
- op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_HI16;
- } else {
- op_info->Value = other_half << 16 | value;
- op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_LO16;
- }
- break;
- default:
- break;
- }
- } else {
- switch (r_type) {
- case MachO::ARM_RELOC_HALF:
- if ((r_length & 0x1) == 1) {
- op_info->Value = value << 16 | other_half;
- op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_HI16;
- } else {
- op_info->Value = other_half << 16 | value;
- op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_LO16;
- }
- break;
- default:
- break;
+ switch (r_type) {
+ case MachO::ARM_RELOC_HALF:
+ if ((r_length & 0x1) == 1) {
+ op_info->Value = value << 16 | other_half;
+ op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_HI16;
+ } else {
+ op_info->Value = other_half << 16 | value;
+ op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_LO16;
}
+ break;
+ default:
+ break;
}
return 1;
}
@@ -994,33 +1997,31 @@ int SymbolizerGetOpInfo(void *DisInfo, uint64_t Pc, uint64_t Offset,
// return 0 so the code in tryAddingSymbolicOperand() can use the
// SymbolLookUp call back with the branch target address to look up the
// symbol and possiblity add an annotation for a symbol stub.
- if (reloc_found && isExtern == 0 && (r_type == MachO::ARM_RELOC_BR24 ||
- r_type == MachO::ARM_THUMB_RELOC_BR22))
+ if (isExtern == 0 && (r_type == MachO::ARM_RELOC_BR24 ||
+ r_type == MachO::ARM_THUMB_RELOC_BR22))
return 0;
uint32_t offset = 0;
- if (reloc_found) {
- if (r_type == MachO::ARM_RELOC_HALF ||
- r_type == MachO::ARM_RELOC_HALF_SECTDIFF) {
- if ((r_length & 0x1) == 1)
- value = value << 16 | other_half;
- else
- value = other_half << 16 | value;
- }
- if (r_scattered && (r_type != MachO::ARM_RELOC_HALF &&
- r_type != MachO::ARM_RELOC_HALF_SECTDIFF)) {
- offset = value - r_value;
- value = r_value;
- }
+ if (r_type == MachO::ARM_RELOC_HALF ||
+ r_type == MachO::ARM_RELOC_HALF_SECTDIFF) {
+ if ((r_length & 0x1) == 1)
+ value = value << 16 | other_half;
+ else
+ value = other_half << 16 | value;
+ }
+ if (r_scattered && (r_type != MachO::ARM_RELOC_HALF &&
+ r_type != MachO::ARM_RELOC_HALF_SECTDIFF)) {
+ offset = value - r_value;
+ value = r_value;
}
- if (reloc_found && r_type == MachO::ARM_RELOC_HALF_SECTDIFF) {
+ if (r_type == MachO::ARM_RELOC_HALF_SECTDIFF) {
if ((r_length & 0x1) == 1)
op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_HI16;
else
op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_LO16;
- const char *add = GuessSymbolName(r_value, info);
- const char *sub = GuessSymbolName(pair_r_value, info);
+ const char *add = GuessSymbolName(r_value, info->AddrMap);
+ const char *sub = GuessSymbolName(pair_r_value, info->AddrMap);
int32_t offset = value - (r_value - pair_r_value);
op_info->AddSymbol.Present = 1;
if (add != nullptr)
@@ -1036,115 +2037,101 @@ int SymbolizerGetOpInfo(void *DisInfo, uint64_t Pc, uint64_t Offset,
return 1;
}
- if (reloc_found == false)
- return 0;
-
op_info->AddSymbol.Present = 1;
op_info->Value = offset;
- if (reloc_found) {
- if (r_type == MachO::ARM_RELOC_HALF) {
- if ((r_length & 0x1) == 1)
- op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_HI16;
- else
- op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_LO16;
- }
+ if (r_type == MachO::ARM_RELOC_HALF) {
+ if ((r_length & 0x1) == 1)
+ op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_HI16;
+ else
+ op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_LO16;
}
- const char *add = GuessSymbolName(value, info);
+ const char *add = GuessSymbolName(value, info->AddrMap);
if (add != nullptr) {
op_info->AddSymbol.Name = add;
return 1;
}
op_info->AddSymbol.Value = value;
return 1;
- } else if (Arch == Triple::aarch64) {
+ }
+ if (Arch == Triple::aarch64) {
if (Offset != 0 || Size != 4)
return 0;
// First search the section's relocation entries (if any) for an entry
// for this section offset.
uint64_t sect_addr = info->S.getAddress();
uint64_t sect_offset = (Pc + Offset) - sect_addr;
- bool reloc_found = false;
- DataRefImpl Rel;
- MachO::any_relocation_info RE;
- bool isExtern = false;
- SymbolRef Symbol;
- uint32_t r_type = 0;
- for (const RelocationRef &Reloc : info->S.relocations()) {
- uint64_t RelocOffset;
- Reloc.getOffset(RelocOffset);
- if (RelocOffset == sect_offset) {
- Rel = Reloc.getRawDataRefImpl();
- RE = info->O->getRelocation(Rel);
- r_type = info->O->getAnyRelocationType(RE);
- if (r_type == MachO::ARM64_RELOC_ADDEND) {
- DataRefImpl RelNext = Rel;
- info->O->moveRelocationNext(RelNext);
- MachO::any_relocation_info RENext = info->O->getRelocation(RelNext);
- if (value == 0) {
- value = info->O->getPlainRelocationSymbolNum(RENext);
- op_info->Value = value;
- }
- }
- // NOTE: Scattered relocations don't exist on arm64.
- isExtern = info->O->getPlainRelocationExternal(RE);
- if (isExtern) {
- symbol_iterator RelocSym = Reloc.getSymbol();
- Symbol = *RelocSym;
- }
- reloc_found = true;
- break;
+ auto Reloc =
+ std::find_if(info->S.relocations().begin(), info->S.relocations().end(),
+ [&](const RelocationRef &Reloc) {
+ uint64_t RelocOffset;
+ Reloc.getOffset(RelocOffset);
+ return RelocOffset == sect_offset;
+ });
+
+ if (Reloc == info->S.relocations().end())
+ return 0;
+
+ DataRefImpl Rel = Reloc->getRawDataRefImpl();
+ MachO::any_relocation_info RE = info->O->getRelocation(Rel);
+ uint32_t r_type = info->O->getAnyRelocationType(RE);
+ if (r_type == MachO::ARM64_RELOC_ADDEND) {
+ DataRefImpl RelNext = Rel;
+ info->O->moveRelocationNext(RelNext);
+ MachO::any_relocation_info RENext = info->O->getRelocation(RelNext);
+ if (value == 0) {
+ value = info->O->getPlainRelocationSymbolNum(RENext);
+ op_info->Value = value;
}
}
- if (reloc_found && isExtern) {
- StringRef SymName;
- Symbol.getName(SymName);
- const char *name = SymName.data();
- op_info->AddSymbol.Present = 1;
- op_info->AddSymbol.Name = name;
+ // NOTE: Scattered relocations don't exist on arm64.
+ if (!info->O->getPlainRelocationExternal(RE))
+ return 0;
+ StringRef SymName;
+ Reloc->getSymbol()->getName(SymName);
+ const char *name = SymName.data();
+ op_info->AddSymbol.Present = 1;
+ op_info->AddSymbol.Name = name;
- switch (r_type) {
- case MachO::ARM64_RELOC_PAGE21:
- /* @page */
- op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_PAGE;
- break;
- case MachO::ARM64_RELOC_PAGEOFF12:
- /* @pageoff */
- op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_PAGEOFF;
- break;
- case MachO::ARM64_RELOC_GOT_LOAD_PAGE21:
- /* @gotpage */
- op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_GOTPAGE;
- break;
- case MachO::ARM64_RELOC_GOT_LOAD_PAGEOFF12:
- /* @gotpageoff */
- op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_GOTPAGEOFF;
- break;
- case MachO::ARM64_RELOC_TLVP_LOAD_PAGE21:
- /* @tvlppage is not implemented in llvm-mc */
- op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_TLVP;
- break;
- case MachO::ARM64_RELOC_TLVP_LOAD_PAGEOFF12:
- /* @tvlppageoff is not implemented in llvm-mc */
- op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_TLVOFF;
- break;
- default:
- case MachO::ARM64_RELOC_BRANCH26:
- op_info->VariantKind = LLVMDisassembler_VariantKind_None;
- break;
- }
- return 1;
+ switch (r_type) {
+ case MachO::ARM64_RELOC_PAGE21:
+ /* @page */
+ op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_PAGE;
+ break;
+ case MachO::ARM64_RELOC_PAGEOFF12:
+ /* @pageoff */
+ op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_PAGEOFF;
+ break;
+ case MachO::ARM64_RELOC_GOT_LOAD_PAGE21:
+ /* @gotpage */
+ op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_GOTPAGE;
+ break;
+ case MachO::ARM64_RELOC_GOT_LOAD_PAGEOFF12:
+ /* @gotpageoff */
+ op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_GOTPAGEOFF;
+ break;
+ case MachO::ARM64_RELOC_TLVP_LOAD_PAGE21:
+ /* @tvlppage is not implemented in llvm-mc */
+ op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_TLVP;
+ break;
+ case MachO::ARM64_RELOC_TLVP_LOAD_PAGEOFF12:
+ /* @tvlppageoff is not implemented in llvm-mc */
+ op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_TLVOFF;
+ break;
+ default:
+ case MachO::ARM64_RELOC_BRANCH26:
+ op_info->VariantKind = LLVMDisassembler_VariantKind_None;
+ break;
}
- return 0;
- } else {
- return 0;
+ return 1;
}
+ return 0;
}
// GuessCstringPointer is passed the address of what might be a pointer to a
// literal string in a cstring section. If that address is in a cstring section
// it returns a pointer to that string. Else it returns nullptr.
-const char *GuessCstringPointer(uint64_t ReferenceValue,
- struct DisassembleInfo *info) {
+static const char *GuessCstringPointer(uint64_t ReferenceValue,
+ struct DisassembleInfo *info) {
uint32_t LoadCommandCount = info->O->getHeader().ncmds;
MachOObjectFile::LoadCommandInfo Load = info->O->getFirstLoadCommandInfo();
for (unsigned I = 0;; ++I) {
@@ -1429,14 +2416,24 @@ static uint64_t GuessPointerPointer(uint64_t ReferenceValue,
// offset into the section, number of bytes left in the section past the offset
// and which section is was being referenced. If the Address is not in a
// section nullptr is returned.
-const char *get_pointer_64(uint64_t Address, uint32_t &offset, uint32_t &left,
- SectionRef &S, DisassembleInfo *info) {
+static const char *get_pointer_64(uint64_t Address, uint32_t &offset,
+ uint32_t &left, SectionRef &S,
+ DisassembleInfo *info,
+ bool objc_only = false) {
offset = 0;
left = 0;
S = SectionRef();
for (unsigned SectIdx = 0; SectIdx != info->Sections->size(); SectIdx++) {
uint64_t SectAddress = ((*(info->Sections))[SectIdx]).getAddress();
uint64_t SectSize = ((*(info->Sections))[SectIdx]).getSize();
+ if (objc_only) {
+ StringRef SectName;
+ ((*(info->Sections))[SectIdx]).getName(SectName);
+ DataRefImpl Ref = ((*(info->Sections))[SectIdx]).getRawDataRefImpl();
+ StringRef SegName = info->O->getSectionFinalSegmentName(Ref);
+ if (SegName != "__OBJC" && SectName != "__cstring")
+ continue;
+ }
if (Address >= SectAddress && Address < SectAddress + SectSize) {
S = (*(info->Sections))[SectIdx];
offset = Address - SectAddress;
@@ -1449,13 +2446,24 @@ const char *get_pointer_64(uint64_t Address, uint32_t &offset, uint32_t &left,
return nullptr;
}
+static const char *get_pointer_32(uint32_t Address, uint32_t &offset,
+ uint32_t &left, SectionRef &S,
+ DisassembleInfo *info,
+ bool objc_only = false) {
+ return get_pointer_64(Address, offset, left, S, info, objc_only);
+}
+
// get_symbol_64() returns the name of a symbol (or nullptr) and the address of
// the symbol indirectly through n_value. Based on the relocation information
// for the specified section offset in the specified section reference.
-const char *get_symbol_64(uint32_t sect_offset, SectionRef S,
- DisassembleInfo *info, uint64_t &n_value) {
+// If no relocation information is found and a non-zero ReferenceValue for the
+// 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 = UnknownAddressOrSize) {
n_value = 0;
- if (info->verbose == false)
+ if (!info->verbose)
return nullptr;
// See if there is an external relocation entry at the sect_offset.
@@ -1487,6 +2495,8 @@ const char *get_symbol_64(uint32_t sect_offset, SectionRef S,
const char *SymbolName = nullptr;
if (reloc_found && isExtern) {
Symbol.getAddress(n_value);
+ if (n_value == UnknownAddressOrSize)
+ n_value = 0;
StringRef name;
Symbol.getName(name);
if (!name.empty()) {
@@ -1504,17 +2514,21 @@ const char *get_symbol_64(uint32_t sect_offset, SectionRef S,
//
// NOTE: need add passing the database_offset to this routine.
- // TODO: 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.
- //
- // NOTE: need add passing the ReferenceValue to this routine. Then that code
- // would simply be this:
- // SymbolName = GuessSymbolName(ReferenceValue, info);
+ // 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 != UnknownAddressOrSize)
+ SymbolName = GuessSymbolName(ReferenceValue, info->AddrMap);
return SymbolName;
}
+static const char *get_symbol_32(uint32_t sect_offset, SectionRef S,
+ DisassembleInfo *info,
+ uint32_t ReferenceValue) {
+ uint64_t n_value64;
+ return get_symbol_64(sect_offset, S, info, n_value64, ReferenceValue);
+}
+
// These are structs in the Objective-C meta data and read to produce the
// comments for disassembly. While these are part of the ABI they are no
// public defintions. So the are here not in include/llvm/Support/MachO.h .
@@ -1536,6 +2550,14 @@ struct class64_t {
uint64_t data; // class_ro64_t * (64-bit pointer)
};
+struct class32_t {
+ uint32_t isa; /* class32_t * (32-bit pointer) */
+ uint32_t superclass; /* class32_t * (32-bit pointer) */
+ uint32_t cache; /* Cache (32-bit pointer) */
+ uint32_t vtable; /* IMP * (32-bit pointer) */
+ uint32_t data; /* class_ro32_t * (32-bit pointer) */
+};
+
struct class_ro64_t {
uint32_t flags;
uint32_t instanceStart;
@@ -1550,6 +2572,276 @@ struct class_ro64_t {
uint64_t baseProperties; // const struct objc_property_list (64-bit pointer)
};
+struct class_ro32_t {
+ uint32_t flags;
+ uint32_t instanceStart;
+ uint32_t instanceSize;
+ uint32_t ivarLayout; /* const uint8_t * (32-bit pointer) */
+ uint32_t name; /* const char * (32-bit pointer) */
+ uint32_t baseMethods; /* const method_list_t * (32-bit pointer) */
+ uint32_t baseProtocols; /* const protocol_list_t * (32-bit pointer) */
+ uint32_t ivars; /* const ivar_list_t * (32-bit pointer) */
+ uint32_t weakIvarLayout; /* const uint8_t * (32-bit pointer) */
+ uint32_t baseProperties; /* const struct objc_property_list *
+ (32-bit pointer) */
+};
+
+/* Values for class_ro{64,32}_t->flags */
+#define RO_META (1 << 0)
+#define RO_ROOT (1 << 1)
+#define RO_HAS_CXX_STRUCTORS (1 << 2)
+
+struct method_list64_t {
+ uint32_t entsize;
+ uint32_t count;
+ /* struct method64_t first; These structures follow inline */
+};
+
+struct method_list32_t {
+ uint32_t entsize;
+ uint32_t count;
+ /* struct method32_t first; These structures follow inline */
+};
+
+struct method64_t {
+ uint64_t name; /* SEL (64-bit pointer) */
+ uint64_t types; /* const char * (64-bit pointer) */
+ uint64_t imp; /* IMP (64-bit pointer) */
+};
+
+struct method32_t {
+ uint32_t name; /* SEL (32-bit pointer) */
+ uint32_t types; /* const char * (32-bit pointer) */
+ uint32_t imp; /* IMP (32-bit pointer) */
+};
+
+struct protocol_list64_t {
+ uint64_t count; /* uintptr_t (a 64-bit value) */
+ /* struct protocol64_t * list[0]; These pointers follow inline */
+};
+
+struct protocol_list32_t {
+ uint32_t count; /* uintptr_t (a 32-bit value) */
+ /* struct protocol32_t * list[0]; These pointers follow inline */
+};
+
+struct protocol64_t {
+ uint64_t isa; /* id * (64-bit pointer) */
+ uint64_t name; /* const char * (64-bit pointer) */
+ uint64_t protocols; /* struct protocol_list64_t *
+ (64-bit pointer) */
+ uint64_t instanceMethods; /* method_list_t * (64-bit pointer) */
+ uint64_t classMethods; /* method_list_t * (64-bit pointer) */
+ uint64_t optionalInstanceMethods; /* method_list_t * (64-bit pointer) */
+ uint64_t optionalClassMethods; /* method_list_t * (64-bit pointer) */
+ uint64_t instanceProperties; /* struct objc_property_list *
+ (64-bit pointer) */
+};
+
+struct protocol32_t {
+ uint32_t isa; /* id * (32-bit pointer) */
+ uint32_t name; /* const char * (32-bit pointer) */
+ uint32_t protocols; /* struct protocol_list_t *
+ (32-bit pointer) */
+ uint32_t instanceMethods; /* method_list_t * (32-bit pointer) */
+ uint32_t classMethods; /* method_list_t * (32-bit pointer) */
+ uint32_t optionalInstanceMethods; /* method_list_t * (32-bit pointer) */
+ uint32_t optionalClassMethods; /* method_list_t * (32-bit pointer) */
+ uint32_t instanceProperties; /* struct objc_property_list *
+ (32-bit pointer) */
+};
+
+struct ivar_list64_t {
+ uint32_t entsize;
+ uint32_t count;
+ /* struct ivar64_t first; These structures follow inline */
+};
+
+struct ivar_list32_t {
+ uint32_t entsize;
+ uint32_t count;
+ /* struct ivar32_t first; These structures follow inline */
+};
+
+struct ivar64_t {
+ uint64_t offset; /* uintptr_t * (64-bit pointer) */
+ uint64_t name; /* const char * (64-bit pointer) */
+ uint64_t type; /* const char * (64-bit pointer) */
+ uint32_t alignment;
+ uint32_t size;
+};
+
+struct ivar32_t {
+ uint32_t offset; /* uintptr_t * (32-bit pointer) */
+ uint32_t name; /* const char * (32-bit pointer) */
+ uint32_t type; /* const char * (32-bit pointer) */
+ uint32_t alignment;
+ uint32_t size;
+};
+
+struct objc_property_list64 {
+ uint32_t entsize;
+ uint32_t count;
+ /* struct objc_property64 first; These structures follow inline */
+};
+
+struct objc_property_list32 {
+ uint32_t entsize;
+ uint32_t count;
+ /* struct objc_property32 first; These structures follow inline */
+};
+
+struct objc_property64 {
+ uint64_t name; /* const char * (64-bit pointer) */
+ uint64_t attributes; /* const char * (64-bit pointer) */
+};
+
+struct objc_property32 {
+ uint32_t name; /* const char * (32-bit pointer) */
+ uint32_t attributes; /* const char * (32-bit pointer) */
+};
+
+struct category64_t {
+ uint64_t name; /* const char * (64-bit pointer) */
+ uint64_t cls; /* struct class_t * (64-bit pointer) */
+ uint64_t instanceMethods; /* struct method_list_t * (64-bit pointer) */
+ uint64_t classMethods; /* struct method_list_t * (64-bit pointer) */
+ uint64_t protocols; /* struct protocol_list_t * (64-bit pointer) */
+ uint64_t instanceProperties; /* struct objc_property_list *
+ (64-bit pointer) */
+};
+
+struct category32_t {
+ uint32_t name; /* const char * (32-bit pointer) */
+ uint32_t cls; /* struct class_t * (32-bit pointer) */
+ uint32_t instanceMethods; /* struct method_list_t * (32-bit pointer) */
+ uint32_t classMethods; /* struct method_list_t * (32-bit pointer) */
+ uint32_t protocols; /* struct protocol_list_t * (32-bit pointer) */
+ uint32_t instanceProperties; /* struct objc_property_list *
+ (32-bit pointer) */
+};
+
+struct objc_image_info64 {
+ uint32_t version;
+ uint32_t flags;
+};
+struct objc_image_info32 {
+ uint32_t version;
+ uint32_t flags;
+};
+struct imageInfo_t {
+ uint32_t version;
+ uint32_t flags;
+};
+/* masks for objc_image_info.flags */
+#define OBJC_IMAGE_IS_REPLACEMENT (1 << 0)
+#define OBJC_IMAGE_SUPPORTS_GC (1 << 1)
+
+struct message_ref64 {
+ uint64_t imp; /* IMP (64-bit pointer) */
+ uint64_t sel; /* SEL (64-bit pointer) */
+};
+
+struct message_ref32 {
+ uint32_t imp; /* IMP (32-bit pointer) */
+ uint32_t sel; /* SEL (32-bit pointer) */
+};
+
+// Objective-C 1 (32-bit only) meta data structs.
+
+struct objc_module_t {
+ uint32_t version;
+ uint32_t size;
+ uint32_t name; /* char * (32-bit pointer) */
+ uint32_t symtab; /* struct objc_symtab * (32-bit pointer) */
+};
+
+struct objc_symtab_t {
+ uint32_t sel_ref_cnt;
+ uint32_t refs; /* SEL * (32-bit pointer) */
+ uint16_t cls_def_cnt;
+ uint16_t cat_def_cnt;
+ // uint32_t defs[1]; /* void * (32-bit pointer) variable size */
+};
+
+struct objc_class_t {
+ uint32_t isa; /* struct objc_class * (32-bit pointer) */
+ uint32_t super_class; /* struct objc_class * (32-bit pointer) */
+ uint32_t name; /* const char * (32-bit pointer) */
+ int32_t version;
+ int32_t info;
+ int32_t instance_size;
+ uint32_t ivars; /* struct objc_ivar_list * (32-bit pointer) */
+ uint32_t methodLists; /* struct objc_method_list ** (32-bit pointer) */
+ uint32_t cache; /* struct objc_cache * (32-bit pointer) */
+ uint32_t protocols; /* struct objc_protocol_list * (32-bit pointer) */
+};
+
+#define CLS_GETINFO(cls, infomask) ((cls)->info & (infomask))
+// class is not a metaclass
+#define CLS_CLASS 0x1
+// class is a metaclass
+#define CLS_META 0x2
+
+struct objc_category_t {
+ uint32_t category_name; /* char * (32-bit pointer) */
+ uint32_t class_name; /* char * (32-bit pointer) */
+ uint32_t instance_methods; /* struct objc_method_list * (32-bit pointer) */
+ uint32_t class_methods; /* struct objc_method_list * (32-bit pointer) */
+ uint32_t protocols; /* struct objc_protocol_list * (32-bit ptr) */
+};
+
+struct objc_ivar_t {
+ uint32_t ivar_name; /* char * (32-bit pointer) */
+ uint32_t ivar_type; /* char * (32-bit pointer) */
+ int32_t ivar_offset;
+};
+
+struct objc_ivar_list_t {
+ int32_t ivar_count;
+ // struct objc_ivar_t ivar_list[1]; /* variable length structure */
+};
+
+struct objc_method_list_t {
+ uint32_t obsolete; /* struct objc_method_list * (32-bit pointer) */
+ int32_t method_count;
+ // struct objc_method_t method_list[1]; /* variable length structure */
+};
+
+struct objc_method_t {
+ uint32_t method_name; /* SEL, aka struct objc_selector * (32-bit pointer) */
+ uint32_t method_types; /* char * (32-bit pointer) */
+ uint32_t method_imp; /* IMP, aka function pointer, (*IMP)(id, SEL, ...)
+ (32-bit pointer) */
+};
+
+struct objc_protocol_list_t {
+ uint32_t next; /* struct objc_protocol_list * (32-bit pointer) */
+ int32_t count;
+ // uint32_t list[1]; /* Protocol *, aka struct objc_protocol_t *
+ // (32-bit pointer) */
+};
+
+struct objc_protocol_t {
+ uint32_t isa; /* struct objc_class * (32-bit pointer) */
+ uint32_t protocol_name; /* char * (32-bit pointer) */
+ uint32_t protocol_list; /* struct objc_protocol_list * (32-bit pointer) */
+ uint32_t instance_methods; /* struct objc_method_description_list *
+ (32-bit pointer) */
+ uint32_t class_methods; /* struct objc_method_description_list *
+ (32-bit pointer) */
+};
+
+struct objc_method_description_list_t {
+ int32_t count;
+ // struct objc_method_description_t list[1];
+};
+
+struct objc_method_description_t {
+ uint32_t name; /* SEL, aka struct objc_selector * (32-bit pointer) */
+ uint32_t types; /* char * (32-bit pointer) */
+};
+
inline void swapStruct(struct cfstring64_t &cfs) {
sys::swapByteOrder(cfs.isa);
sys::swapByteOrder(cfs.flags);
@@ -1565,6 +2857,14 @@ inline void swapStruct(struct class64_t &c) {
sys::swapByteOrder(c.data);
}
+inline void swapStruct(struct class32_t &c) {
+ sys::swapByteOrder(c.isa);
+ sys::swapByteOrder(c.superclass);
+ sys::swapByteOrder(c.cache);
+ sys::swapByteOrder(c.vtable);
+ sys::swapByteOrder(c.data);
+}
+
inline void swapStruct(struct class_ro64_t &cro) {
sys::swapByteOrder(cro.flags);
sys::swapByteOrder(cro.instanceStart);
@@ -1579,6 +2879,238 @@ inline void swapStruct(struct class_ro64_t &cro) {
sys::swapByteOrder(cro.baseProperties);
}
+inline void swapStruct(struct class_ro32_t &cro) {
+ sys::swapByteOrder(cro.flags);
+ sys::swapByteOrder(cro.instanceStart);
+ sys::swapByteOrder(cro.instanceSize);
+ sys::swapByteOrder(cro.ivarLayout);
+ sys::swapByteOrder(cro.name);
+ sys::swapByteOrder(cro.baseMethods);
+ sys::swapByteOrder(cro.baseProtocols);
+ sys::swapByteOrder(cro.ivars);
+ sys::swapByteOrder(cro.weakIvarLayout);
+ sys::swapByteOrder(cro.baseProperties);
+}
+
+inline void swapStruct(struct method_list64_t &ml) {
+ sys::swapByteOrder(ml.entsize);
+ sys::swapByteOrder(ml.count);
+}
+
+inline void swapStruct(struct method_list32_t &ml) {
+ sys::swapByteOrder(ml.entsize);
+ sys::swapByteOrder(ml.count);
+}
+
+inline void swapStruct(struct method64_t &m) {
+ sys::swapByteOrder(m.name);
+ sys::swapByteOrder(m.types);
+ sys::swapByteOrder(m.imp);
+}
+
+inline void swapStruct(struct method32_t &m) {
+ sys::swapByteOrder(m.name);
+ sys::swapByteOrder(m.types);
+ sys::swapByteOrder(m.imp);
+}
+
+inline void swapStruct(struct protocol_list64_t &pl) {
+ sys::swapByteOrder(pl.count);
+}
+
+inline void swapStruct(struct protocol_list32_t &pl) {
+ sys::swapByteOrder(pl.count);
+}
+
+inline void swapStruct(struct protocol64_t &p) {
+ sys::swapByteOrder(p.isa);
+ sys::swapByteOrder(p.name);
+ sys::swapByteOrder(p.protocols);
+ sys::swapByteOrder(p.instanceMethods);
+ sys::swapByteOrder(p.classMethods);
+ sys::swapByteOrder(p.optionalInstanceMethods);
+ sys::swapByteOrder(p.optionalClassMethods);
+ sys::swapByteOrder(p.instanceProperties);
+}
+
+inline void swapStruct(struct protocol32_t &p) {
+ sys::swapByteOrder(p.isa);
+ sys::swapByteOrder(p.name);
+ sys::swapByteOrder(p.protocols);
+ sys::swapByteOrder(p.instanceMethods);
+ sys::swapByteOrder(p.classMethods);
+ sys::swapByteOrder(p.optionalInstanceMethods);
+ sys::swapByteOrder(p.optionalClassMethods);
+ sys::swapByteOrder(p.instanceProperties);
+}
+
+inline void swapStruct(struct ivar_list64_t &il) {
+ sys::swapByteOrder(il.entsize);
+ sys::swapByteOrder(il.count);
+}
+
+inline void swapStruct(struct ivar_list32_t &il) {
+ sys::swapByteOrder(il.entsize);
+ sys::swapByteOrder(il.count);
+}
+
+inline void swapStruct(struct ivar64_t &i) {
+ sys::swapByteOrder(i.offset);
+ sys::swapByteOrder(i.name);
+ sys::swapByteOrder(i.type);
+ sys::swapByteOrder(i.alignment);
+ sys::swapByteOrder(i.size);
+}
+
+inline void swapStruct(struct ivar32_t &i) {
+ sys::swapByteOrder(i.offset);
+ sys::swapByteOrder(i.name);
+ sys::swapByteOrder(i.type);
+ sys::swapByteOrder(i.alignment);
+ sys::swapByteOrder(i.size);
+}
+
+inline void swapStruct(struct objc_property_list64 &pl) {
+ sys::swapByteOrder(pl.entsize);
+ sys::swapByteOrder(pl.count);
+}
+
+inline void swapStruct(struct objc_property_list32 &pl) {
+ sys::swapByteOrder(pl.entsize);
+ sys::swapByteOrder(pl.count);
+}
+
+inline void swapStruct(struct objc_property64 &op) {
+ sys::swapByteOrder(op.name);
+ sys::swapByteOrder(op.attributes);
+}
+
+inline void swapStruct(struct objc_property32 &op) {
+ sys::swapByteOrder(op.name);
+ sys::swapByteOrder(op.attributes);
+}
+
+inline void swapStruct(struct category64_t &c) {
+ sys::swapByteOrder(c.name);
+ sys::swapByteOrder(c.cls);
+ sys::swapByteOrder(c.instanceMethods);
+ sys::swapByteOrder(c.classMethods);
+ sys::swapByteOrder(c.protocols);
+ sys::swapByteOrder(c.instanceProperties);
+}
+
+inline void swapStruct(struct category32_t &c) {
+ sys::swapByteOrder(c.name);
+ sys::swapByteOrder(c.cls);
+ sys::swapByteOrder(c.instanceMethods);
+ sys::swapByteOrder(c.classMethods);
+ sys::swapByteOrder(c.protocols);
+ sys::swapByteOrder(c.instanceProperties);
+}
+
+inline void swapStruct(struct objc_image_info64 &o) {
+ sys::swapByteOrder(o.version);
+ sys::swapByteOrder(o.flags);
+}
+
+inline void swapStruct(struct objc_image_info32 &o) {
+ sys::swapByteOrder(o.version);
+ sys::swapByteOrder(o.flags);
+}
+
+inline void swapStruct(struct imageInfo_t &o) {
+ sys::swapByteOrder(o.version);
+ sys::swapByteOrder(o.flags);
+}
+
+inline void swapStruct(struct message_ref64 &mr) {
+ sys::swapByteOrder(mr.imp);
+ sys::swapByteOrder(mr.sel);
+}
+
+inline void swapStruct(struct message_ref32 &mr) {
+ sys::swapByteOrder(mr.imp);
+ sys::swapByteOrder(mr.sel);
+}
+
+inline void swapStruct(struct objc_module_t &module) {
+ sys::swapByteOrder(module.version);
+ sys::swapByteOrder(module.size);
+ sys::swapByteOrder(module.name);
+ sys::swapByteOrder(module.symtab);
+}
+
+inline void swapStruct(struct objc_symtab_t &symtab) {
+ sys::swapByteOrder(symtab.sel_ref_cnt);
+ sys::swapByteOrder(symtab.refs);
+ sys::swapByteOrder(symtab.cls_def_cnt);
+ sys::swapByteOrder(symtab.cat_def_cnt);
+}
+
+inline void swapStruct(struct objc_class_t &objc_class) {
+ sys::swapByteOrder(objc_class.isa);
+ sys::swapByteOrder(objc_class.super_class);
+ sys::swapByteOrder(objc_class.name);
+ sys::swapByteOrder(objc_class.version);
+ sys::swapByteOrder(objc_class.info);
+ sys::swapByteOrder(objc_class.instance_size);
+ sys::swapByteOrder(objc_class.ivars);
+ sys::swapByteOrder(objc_class.methodLists);
+ sys::swapByteOrder(objc_class.cache);
+ sys::swapByteOrder(objc_class.protocols);
+}
+
+inline void swapStruct(struct objc_category_t &objc_category) {
+ sys::swapByteOrder(objc_category.category_name);
+ sys::swapByteOrder(objc_category.class_name);
+ sys::swapByteOrder(objc_category.instance_methods);
+ sys::swapByteOrder(objc_category.class_methods);
+ sys::swapByteOrder(objc_category.protocols);
+}
+
+inline void swapStruct(struct objc_ivar_list_t &objc_ivar_list) {
+ sys::swapByteOrder(objc_ivar_list.ivar_count);
+}
+
+inline void swapStruct(struct objc_ivar_t &objc_ivar) {
+ sys::swapByteOrder(objc_ivar.ivar_name);
+ sys::swapByteOrder(objc_ivar.ivar_type);
+ sys::swapByteOrder(objc_ivar.ivar_offset);
+}
+
+inline void swapStruct(struct objc_method_list_t &method_list) {
+ sys::swapByteOrder(method_list.obsolete);
+ sys::swapByteOrder(method_list.method_count);
+}
+
+inline void swapStruct(struct objc_method_t &method) {
+ sys::swapByteOrder(method.method_name);
+ sys::swapByteOrder(method.method_types);
+ sys::swapByteOrder(method.method_imp);
+}
+
+inline void swapStruct(struct objc_protocol_list_t &protocol_list) {
+ sys::swapByteOrder(protocol_list.next);
+ sys::swapByteOrder(protocol_list.count);
+}
+
+inline void swapStruct(struct objc_protocol_t &protocol) {
+ sys::swapByteOrder(protocol.isa);
+ sys::swapByteOrder(protocol.protocol_name);
+ sys::swapByteOrder(protocol.protocol_list);
+ sys::swapByteOrder(protocol.instance_methods);
+ sys::swapByteOrder(protocol.class_methods);
+}
+
+inline void swapStruct(struct objc_method_description_list_t &mdl) {
+ sys::swapByteOrder(mdl.count);
+}
+
+inline void swapStruct(struct objc_method_description_t &md) {
+ sys::swapByteOrder(md.name);
+ sys::swapByteOrder(md.types);
+}
+
static const char *get_dyld_bind_info_symbolname(uint64_t ReferenceValue,
struct DisassembleInfo *info);
@@ -1587,9 +3119,9 @@ static const char *get_dyld_bind_info_symbolname(uint64_t ReferenceValue,
// address of the pointer, so when the pointer is zero as it can be in an .o
// file, that is used to look for an external relocation entry with a symbol
// name.
-const char *get_objc2_64bit_class_name(uint64_t pointer_value,
- uint64_t ReferenceValue,
- struct DisassembleInfo *info) {
+static const char *get_objc2_64bit_class_name(uint64_t pointer_value,
+ uint64_t ReferenceValue,
+ struct DisassembleInfo *info) {
const char *r;
uint32_t offset, left;
SectionRef S;
@@ -1638,8 +3170,8 @@ const char *get_objc2_64bit_class_name(uint64_t pointer_value,
// get_objc2_64bit_cfstring_name is used for disassembly and is passed a
// pointer to a cfstring and returns its name or nullptr.
-const char *get_objc2_64bit_cfstring_name(uint64_t ReferenceValue,
- struct DisassembleInfo *info) {
+static const char *get_objc2_64bit_cfstring_name(uint64_t ReferenceValue,
+ struct DisassembleInfo *info) {
const char *r, *name;
uint32_t offset, left;
SectionRef S;
@@ -1672,8 +3204,8 @@ const char *get_objc2_64bit_cfstring_name(uint64_t ReferenceValue,
// who's symbol's n_value is the real pointer to the selector name. If that is
// the case the real pointer to the selector name is returned else 0 is
// returned
-uint64_t get_objc2_64bit_selref(uint64_t ReferenceValue,
- struct DisassembleInfo *info) {
+static uint64_t get_objc2_64bit_selref(uint64_t ReferenceValue,
+ struct DisassembleInfo *info) {
uint32_t offset, left;
SectionRef S;
@@ -1687,6 +3219,2411 @@ uint64_t get_objc2_64bit_selref(uint64_t ReferenceValue,
return n_value;
}
+static const SectionRef get_section(MachOObjectFile *O, const char *segname,
+ const char *sectname) {
+ for (const SectionRef &Section : O->sections()) {
+ StringRef SectName;
+ Section.getName(SectName);
+ DataRefImpl Ref = Section.getRawDataRefImpl();
+ StringRef SegName = O->getSectionFinalSegmentName(Ref);
+ if (SegName == segname && SectName == sectname)
+ return Section;
+ }
+ return SectionRef();
+}
+
+static void
+walk_pointer_list_64(const char *listname, const SectionRef S,
+ MachOObjectFile *O, struct DisassembleInfo *info,
+ void (*func)(uint64_t, struct DisassembleInfo *info)) {
+ if (S == SectionRef())
+ return;
+
+ StringRef SectName;
+ S.getName(SectName);
+ DataRefImpl Ref = S.getRawDataRefImpl();
+ StringRef SegName = O->getSectionFinalSegmentName(Ref);
+ outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
+
+ StringRef BytesStr;
+ S.getContents(BytesStr);
+ const char *Contents = reinterpret_cast<const char *>(BytesStr.data());
+
+ for (uint32_t i = 0; i < S.getSize(); i += sizeof(uint64_t)) {
+ uint32_t left = S.getSize() - i;
+ uint32_t size = left < sizeof(uint64_t) ? left : sizeof(uint64_t);
+ uint64_t p = 0;
+ memcpy(&p, Contents + i, size);
+ if (i + sizeof(uint64_t) > S.getSize())
+ outs() << listname << " list pointer extends past end of (" << SegName
+ << "," << SectName << ") section\n";
+ outs() << format("%016" PRIx64, S.getAddress() + i) << " ";
+
+ if (O->isLittleEndian() != sys::IsLittleEndianHost)
+ sys::swapByteOrder(p);
+
+ uint64_t n_value = 0;
+ const char *name = get_symbol_64(i, S, info, n_value, p);
+ if (name == nullptr)
+ name = get_dyld_bind_info_symbolname(S.getAddress() + i, info);
+
+ if (n_value != 0) {
+ outs() << format("0x%" PRIx64, n_value);
+ if (p != 0)
+ outs() << " + " << format("0x%" PRIx64, p);
+ } else
+ outs() << format("0x%" PRIx64, p);
+ if (name != nullptr)
+ outs() << " " << name;
+ outs() << "\n";
+
+ p += n_value;
+ if (func)
+ func(p, info);
+ }
+}
+
+static void
+walk_pointer_list_32(const char *listname, const SectionRef S,
+ MachOObjectFile *O, struct DisassembleInfo *info,
+ void (*func)(uint32_t, struct DisassembleInfo *info)) {
+ if (S == SectionRef())
+ return;
+
+ StringRef SectName;
+ S.getName(SectName);
+ DataRefImpl Ref = S.getRawDataRefImpl();
+ StringRef SegName = O->getSectionFinalSegmentName(Ref);
+ outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
+
+ StringRef BytesStr;
+ S.getContents(BytesStr);
+ const char *Contents = reinterpret_cast<const char *>(BytesStr.data());
+
+ for (uint32_t i = 0; i < S.getSize(); i += sizeof(uint32_t)) {
+ uint32_t left = S.getSize() - i;
+ uint32_t size = left < sizeof(uint32_t) ? left : sizeof(uint32_t);
+ uint32_t p = 0;
+ memcpy(&p, Contents + i, size);
+ if (i + sizeof(uint32_t) > S.getSize())
+ outs() << listname << " list pointer extends past end of (" << SegName
+ << "," << SectName << ") section\n";
+ uint32_t Address = S.getAddress() + i;
+ outs() << format("%08" PRIx32, Address) << " ";
+
+ if (O->isLittleEndian() != sys::IsLittleEndianHost)
+ sys::swapByteOrder(p);
+ outs() << format("0x%" PRIx32, p);
+
+ const char *name = get_symbol_32(i, S, info, p);
+ if (name != nullptr)
+ outs() << " " << name;
+ outs() << "\n";
+
+ if (func)
+ func(p, info);
+ }
+}
+
+static void print_layout_map(const char *layout_map, uint32_t left) {
+ outs() << " layout map: ";
+ do {
+ outs() << format("0x%02" PRIx32, (*layout_map) & 0xff) << " ";
+ left--;
+ layout_map++;
+ } while (*layout_map != '\0' && left != 0);
+ outs() << "\n";
+}
+
+static void print_layout_map64(uint64_t p, struct DisassembleInfo *info) {
+ uint32_t offset, left;
+ SectionRef S;
+ const char *layout_map;
+
+ if (p == 0)
+ return;
+ layout_map = get_pointer_64(p, offset, left, S, info);
+ print_layout_map(layout_map, left);
+}
+
+static void print_layout_map32(uint32_t p, struct DisassembleInfo *info) {
+ uint32_t offset, left;
+ SectionRef S;
+ const char *layout_map;
+
+ if (p == 0)
+ return;
+ layout_map = get_pointer_32(p, offset, left, S, info);
+ print_layout_map(layout_map, left);
+}
+
+static void print_method_list64_t(uint64_t p, struct DisassembleInfo *info,
+ const char *indent) {
+ struct method_list64_t ml;
+ struct method64_t m;
+ const char *r;
+ uint32_t offset, xoffset, left, i;
+ SectionRef S, xS;
+ const char *name, *sym_name;
+ uint64_t n_value;
+
+ r = get_pointer_64(p, offset, left, S, info);
+ if (r == nullptr)
+ return;
+ memset(&ml, '\0', sizeof(struct method_list64_t));
+ if (left < sizeof(struct method_list64_t)) {
+ memcpy(&ml, r, left);
+ outs() << " (method_list_t entends past the end of the section)\n";
+ } else
+ memcpy(&ml, r, sizeof(struct method_list64_t));
+ if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
+ swapStruct(ml);
+ outs() << indent << "\t\t entsize " << ml.entsize << "\n";
+ outs() << indent << "\t\t count " << ml.count << "\n";
+
+ p += sizeof(struct method_list64_t);
+ offset += sizeof(struct method_list64_t);
+ for (i = 0; i < ml.count; i++) {
+ r = get_pointer_64(p, offset, left, S, info);
+ if (r == nullptr)
+ return;
+ memset(&m, '\0', sizeof(struct method64_t));
+ if (left < sizeof(struct method64_t)) {
+ memcpy(&ml, r, left);
+ outs() << indent << " (method_t entends past the end of the section)\n";
+ } else
+ memcpy(&m, r, sizeof(struct method64_t));
+ if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
+ swapStruct(m);
+
+ outs() << indent << "\t\t name ";
+ sym_name = get_symbol_64(offset + offsetof(struct method64_t, name), S,
+ info, n_value, m.name);
+ if (n_value != 0) {
+ if (info->verbose && sym_name != nullptr)
+ outs() << sym_name;
+ else
+ outs() << format("0x%" PRIx64, n_value);
+ if (m.name != 0)
+ outs() << " + " << format("0x%" PRIx64, m.name);
+ } else
+ outs() << format("0x%" PRIx64, m.name);
+ name = get_pointer_64(m.name + n_value, xoffset, left, xS, info);
+ if (name != nullptr)
+ outs() << format(" %.*s", left, name);
+ outs() << "\n";
+
+ outs() << indent << "\t\t types ";
+ sym_name = get_symbol_64(offset + offsetof(struct method64_t, types), S,
+ info, n_value, m.types);
+ if (n_value != 0) {
+ if (info->verbose && sym_name != nullptr)
+ outs() << sym_name;
+ else
+ outs() << format("0x%" PRIx64, n_value);
+ if (m.types != 0)
+ outs() << " + " << format("0x%" PRIx64, m.types);
+ } else
+ outs() << format("0x%" PRIx64, m.types);
+ name = get_pointer_64(m.types + n_value, xoffset, left, xS, info);
+ if (name != nullptr)
+ outs() << format(" %.*s", left, name);
+ outs() << "\n";
+
+ outs() << indent << "\t\t imp ";
+ name = get_symbol_64(offset + offsetof(struct method64_t, imp), S, info,
+ n_value, m.imp);
+ if (info->verbose && name == nullptr) {
+ if (n_value != 0) {
+ outs() << format("0x%" PRIx64, n_value) << " ";
+ if (m.imp != 0)
+ outs() << "+ " << format("0x%" PRIx64, m.imp) << " ";
+ } else
+ outs() << format("0x%" PRIx64, m.imp) << " ";
+ }
+ if (name != nullptr)
+ outs() << name;
+ outs() << "\n";
+
+ p += sizeof(struct method64_t);
+ offset += sizeof(struct method64_t);
+ }
+}
+
+static void print_method_list32_t(uint64_t p, struct DisassembleInfo *info,
+ const char *indent) {
+ struct method_list32_t ml;
+ struct method32_t m;
+ const char *r, *name;
+ uint32_t offset, xoffset, left, i;
+ SectionRef S, xS;
+
+ r = get_pointer_32(p, offset, left, S, info);
+ if (r == nullptr)
+ return;
+ memset(&ml, '\0', sizeof(struct method_list32_t));
+ if (left < sizeof(struct method_list32_t)) {
+ memcpy(&ml, r, left);
+ outs() << " (method_list_t entends past the end of the section)\n";
+ } else
+ memcpy(&ml, r, sizeof(struct method_list32_t));
+ if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
+ swapStruct(ml);
+ outs() << indent << "\t\t entsize " << ml.entsize << "\n";
+ outs() << indent << "\t\t count " << ml.count << "\n";
+
+ p += sizeof(struct method_list32_t);
+ offset += sizeof(struct method_list32_t);
+ for (i = 0; i < ml.count; i++) {
+ r = get_pointer_32(p, offset, left, S, info);
+ if (r == nullptr)
+ return;
+ memset(&m, '\0', sizeof(struct method32_t));
+ if (left < sizeof(struct method32_t)) {
+ memcpy(&ml, r, left);
+ outs() << indent << " (method_t entends past the end of the section)\n";
+ } else
+ memcpy(&m, r, sizeof(struct method32_t));
+ if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
+ swapStruct(m);
+
+ outs() << indent << "\t\t name " << format("0x%" PRIx32, m.name);
+ name = get_pointer_32(m.name, xoffset, left, xS, info);
+ if (name != nullptr)
+ outs() << format(" %.*s", left, name);
+ outs() << "\n";
+
+ outs() << indent << "\t\t types " << format("0x%" PRIx32, m.types);
+ name = get_pointer_32(m.types, xoffset, left, xS, info);
+ if (name != nullptr)
+ outs() << format(" %.*s", left, name);
+ outs() << "\n";
+
+ outs() << indent << "\t\t imp " << format("0x%" PRIx32, m.imp);
+ name = get_symbol_32(offset + offsetof(struct method32_t, imp), S, info,
+ m.imp);
+ if (name != nullptr)
+ outs() << " " << name;
+ outs() << "\n";
+
+ p += sizeof(struct method32_t);
+ offset += sizeof(struct method32_t);
+ }
+}
+
+static bool print_method_list(uint32_t p, struct DisassembleInfo *info) {
+ uint32_t offset, left, xleft;
+ SectionRef S;
+ struct objc_method_list_t method_list;
+ struct objc_method_t method;
+ const char *r, *methods, *name, *SymbolName;
+ int32_t i;
+
+ r = get_pointer_32(p, offset, left, S, info, true);
+ if (r == nullptr)
+ return true;
+
+ outs() << "\n";
+ if (left > sizeof(struct objc_method_list_t)) {
+ memcpy(&method_list, r, sizeof(struct objc_method_list_t));
+ } else {
+ outs() << "\t\t objc_method_list extends past end of the section\n";
+ memset(&method_list, '\0', sizeof(struct objc_method_list_t));
+ memcpy(&method_list, r, left);
+ }
+ if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
+ swapStruct(method_list);
+
+ outs() << "\t\t obsolete "
+ << format("0x%08" PRIx32, method_list.obsolete) << "\n";
+ outs() << "\t\t method_count " << method_list.method_count << "\n";
+
+ methods = r + sizeof(struct objc_method_list_t);
+ for (i = 0; i < method_list.method_count; i++) {
+ if ((i + 1) * sizeof(struct objc_method_t) > left) {
+ outs() << "\t\t remaining method's extend past the of the section\n";
+ break;
+ }
+ memcpy(&method, methods + i * sizeof(struct objc_method_t),
+ sizeof(struct objc_method_t));
+ if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
+ swapStruct(method);
+
+ outs() << "\t\t method_name "
+ << format("0x%08" PRIx32, method.method_name);
+ if (info->verbose) {
+ name = get_pointer_32(method.method_name, offset, xleft, S, info, true);
+ if (name != nullptr)
+ outs() << format(" %.*s", xleft, name);
+ else
+ outs() << " (not in an __OBJC section)";
+ }
+ outs() << "\n";
+
+ outs() << "\t\t method_types "
+ << format("0x%08" PRIx32, method.method_types);
+ if (info->verbose) {
+ name = get_pointer_32(method.method_types, offset, xleft, S, info, true);
+ if (name != nullptr)
+ outs() << format(" %.*s", xleft, name);
+ else
+ outs() << " (not in an __OBJC section)";
+ }
+ outs() << "\n";
+
+ outs() << "\t\t method_imp "
+ << format("0x%08" PRIx32, method.method_imp) << " ";
+ if (info->verbose) {
+ SymbolName = GuessSymbolName(method.method_imp, info->AddrMap);
+ if (SymbolName != nullptr)
+ outs() << SymbolName;
+ }
+ outs() << "\n";
+ }
+ return false;
+}
+
+static void print_protocol_list64_t(uint64_t p, struct DisassembleInfo *info) {
+ struct protocol_list64_t pl;
+ uint64_t q, n_value;
+ struct protocol64_t pc;
+ const char *r;
+ uint32_t offset, xoffset, left, i;
+ SectionRef S, xS;
+ const char *name, *sym_name;
+
+ r = get_pointer_64(p, offset, left, S, info);
+ if (r == nullptr)
+ return;
+ memset(&pl, '\0', sizeof(struct protocol_list64_t));
+ if (left < sizeof(struct protocol_list64_t)) {
+ memcpy(&pl, r, left);
+ outs() << " (protocol_list_t entends past the end of the section)\n";
+ } else
+ memcpy(&pl, r, sizeof(struct protocol_list64_t));
+ if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
+ swapStruct(pl);
+ outs() << " count " << pl.count << "\n";
+
+ p += sizeof(struct protocol_list64_t);
+ offset += sizeof(struct protocol_list64_t);
+ for (i = 0; i < pl.count; i++) {
+ r = get_pointer_64(p, offset, left, S, info);
+ if (r == nullptr)
+ return;
+ q = 0;
+ if (left < sizeof(uint64_t)) {
+ memcpy(&q, r, left);
+ outs() << " (protocol_t * entends past the end of the section)\n";
+ } else
+ memcpy(&q, r, sizeof(uint64_t));
+ if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
+ sys::swapByteOrder(q);
+
+ outs() << "\t\t list[" << i << "] ";
+ sym_name = get_symbol_64(offset, S, info, n_value, q);
+ if (n_value != 0) {
+ if (info->verbose && sym_name != nullptr)
+ outs() << sym_name;
+ else
+ outs() << format("0x%" PRIx64, n_value);
+ if (q != 0)
+ outs() << " + " << format("0x%" PRIx64, q);
+ } else
+ outs() << format("0x%" PRIx64, q);
+ outs() << " (struct protocol_t *)\n";
+
+ r = get_pointer_64(q + n_value, offset, left, S, info);
+ if (r == nullptr)
+ return;
+ memset(&pc, '\0', sizeof(struct protocol64_t));
+ if (left < sizeof(struct protocol64_t)) {
+ memcpy(&pc, r, left);
+ outs() << " (protocol_t entends past the end of the section)\n";
+ } else
+ memcpy(&pc, r, sizeof(struct protocol64_t));
+ if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
+ swapStruct(pc);
+
+ outs() << "\t\t\t isa " << format("0x%" PRIx64, pc.isa) << "\n";
+
+ outs() << "\t\t\t name ";
+ sym_name = get_symbol_64(offset + offsetof(struct protocol64_t, name), S,
+ info, n_value, pc.name);
+ if (n_value != 0) {
+ if (info->verbose && sym_name != nullptr)
+ outs() << sym_name;
+ else
+ outs() << format("0x%" PRIx64, n_value);
+ if (pc.name != 0)
+ outs() << " + " << format("0x%" PRIx64, pc.name);
+ } else
+ outs() << format("0x%" PRIx64, pc.name);
+ name = get_pointer_64(pc.name + n_value, xoffset, left, xS, info);
+ if (name != nullptr)
+ outs() << format(" %.*s", left, name);
+ outs() << "\n";
+
+ outs() << "\t\t\tprotocols " << format("0x%" PRIx64, pc.protocols) << "\n";
+
+ outs() << "\t\t instanceMethods ";
+ sym_name =
+ get_symbol_64(offset + offsetof(struct protocol64_t, instanceMethods),
+ S, info, n_value, pc.instanceMethods);
+ if (n_value != 0) {
+ if (info->verbose && sym_name != nullptr)
+ outs() << sym_name;
+ else
+ outs() << format("0x%" PRIx64, n_value);
+ if (pc.instanceMethods != 0)
+ outs() << " + " << format("0x%" PRIx64, pc.instanceMethods);
+ } else
+ outs() << format("0x%" PRIx64, pc.instanceMethods);
+ outs() << " (struct method_list_t *)\n";
+ if (pc.instanceMethods + n_value != 0)
+ print_method_list64_t(pc.instanceMethods + n_value, info, "\t");
+
+ outs() << "\t\t classMethods ";
+ sym_name =
+ get_symbol_64(offset + offsetof(struct protocol64_t, classMethods), S,
+ info, n_value, pc.classMethods);
+ if (n_value != 0) {
+ if (info->verbose && sym_name != nullptr)
+ outs() << sym_name;
+ else
+ outs() << format("0x%" PRIx64, n_value);
+ if (pc.classMethods != 0)
+ outs() << " + " << format("0x%" PRIx64, pc.classMethods);
+ } else
+ outs() << format("0x%" PRIx64, pc.classMethods);
+ outs() << " (struct method_list_t *)\n";
+ if (pc.classMethods + n_value != 0)
+ print_method_list64_t(pc.classMethods + n_value, info, "\t");
+
+ outs() << "\t optionalInstanceMethods "
+ << format("0x%" PRIx64, pc.optionalInstanceMethods) << "\n";
+ outs() << "\t optionalClassMethods "
+ << format("0x%" PRIx64, pc.optionalClassMethods) << "\n";
+ outs() << "\t instanceProperties "
+ << format("0x%" PRIx64, pc.instanceProperties) << "\n";
+
+ p += sizeof(uint64_t);
+ offset += sizeof(uint64_t);
+ }
+}
+
+static void print_protocol_list32_t(uint32_t p, struct DisassembleInfo *info) {
+ struct protocol_list32_t pl;
+ uint32_t q;
+ struct protocol32_t pc;
+ const char *r;
+ uint32_t offset, xoffset, left, i;
+ SectionRef S, xS;
+ const char *name;
+
+ r = get_pointer_32(p, offset, left, S, info);
+ if (r == nullptr)
+ return;
+ memset(&pl, '\0', sizeof(struct protocol_list32_t));
+ if (left < sizeof(struct protocol_list32_t)) {
+ memcpy(&pl, r, left);
+ outs() << " (protocol_list_t entends past the end of the section)\n";
+ } else
+ memcpy(&pl, r, sizeof(struct protocol_list32_t));
+ if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
+ swapStruct(pl);
+ outs() << " count " << pl.count << "\n";
+
+ p += sizeof(struct protocol_list32_t);
+ offset += sizeof(struct protocol_list32_t);
+ for (i = 0; i < pl.count; i++) {
+ r = get_pointer_32(p, offset, left, S, info);
+ if (r == nullptr)
+ return;
+ q = 0;
+ if (left < sizeof(uint32_t)) {
+ memcpy(&q, r, left);
+ outs() << " (protocol_t * entends past the end of the section)\n";
+ } else
+ memcpy(&q, r, sizeof(uint32_t));
+ if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
+ sys::swapByteOrder(q);
+ outs() << "\t\t list[" << i << "] " << format("0x%" PRIx32, q)
+ << " (struct protocol_t *)\n";
+ r = get_pointer_32(q, offset, left, S, info);
+ if (r == nullptr)
+ return;
+ memset(&pc, '\0', sizeof(struct protocol32_t));
+ if (left < sizeof(struct protocol32_t)) {
+ memcpy(&pc, r, left);
+ outs() << " (protocol_t entends past the end of the section)\n";
+ } else
+ memcpy(&pc, r, sizeof(struct protocol32_t));
+ if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
+ swapStruct(pc);
+ outs() << "\t\t\t isa " << format("0x%" PRIx32, pc.isa) << "\n";
+ outs() << "\t\t\t name " << format("0x%" PRIx32, pc.name);
+ name = get_pointer_32(pc.name, xoffset, left, xS, info);
+ if (name != nullptr)
+ outs() << format(" %.*s", left, name);
+ outs() << "\n";
+ outs() << "\t\t\tprotocols " << format("0x%" PRIx32, pc.protocols) << "\n";
+ outs() << "\t\t instanceMethods "
+ << format("0x%" PRIx32, pc.instanceMethods)
+ << " (struct method_list_t *)\n";
+ if (pc.instanceMethods != 0)
+ print_method_list32_t(pc.instanceMethods, info, "\t");
+ outs() << "\t\t classMethods " << format("0x%" PRIx32, pc.classMethods)
+ << " (struct method_list_t *)\n";
+ if (pc.classMethods != 0)
+ print_method_list32_t(pc.classMethods, info, "\t");
+ outs() << "\t optionalInstanceMethods "
+ << format("0x%" PRIx32, pc.optionalInstanceMethods) << "\n";
+ outs() << "\t optionalClassMethods "
+ << format("0x%" PRIx32, pc.optionalClassMethods) << "\n";
+ outs() << "\t instanceProperties "
+ << format("0x%" PRIx32, pc.instanceProperties) << "\n";
+ p += sizeof(uint32_t);
+ offset += sizeof(uint32_t);
+ }
+}
+
+static void print_indent(uint32_t indent) {
+ for (uint32_t i = 0; i < indent;) {
+ if (indent - i >= 8) {
+ outs() << "\t";
+ i += 8;
+ } else {
+ for (uint32_t j = i; j < indent; j++)
+ outs() << " ";
+ return;
+ }
+ }
+}
+
+static bool print_method_description_list(uint32_t p, uint32_t indent,
+ struct DisassembleInfo *info) {
+ uint32_t offset, left, xleft;
+ SectionRef S;
+ struct objc_method_description_list_t mdl;
+ struct objc_method_description_t md;
+ const char *r, *list, *name;
+ int32_t i;
+
+ r = get_pointer_32(p, offset, left, S, info, true);
+ if (r == nullptr)
+ return true;
+
+ outs() << "\n";
+ if (left > sizeof(struct objc_method_description_list_t)) {
+ memcpy(&mdl, r, sizeof(struct objc_method_description_list_t));
+ } else {
+ print_indent(indent);
+ outs() << " objc_method_description_list extends past end of the section\n";
+ memset(&mdl, '\0', sizeof(struct objc_method_description_list_t));
+ memcpy(&mdl, r, left);
+ }
+ if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
+ swapStruct(mdl);
+
+ print_indent(indent);
+ outs() << " count " << mdl.count << "\n";
+
+ list = r + sizeof(struct objc_method_description_list_t);
+ for (i = 0; i < mdl.count; i++) {
+ if ((i + 1) * sizeof(struct objc_method_description_t) > left) {
+ print_indent(indent);
+ outs() << " remaining list entries extend past the of the section\n";
+ break;
+ }
+ print_indent(indent);
+ outs() << " list[" << i << "]\n";
+ memcpy(&md, list + i * sizeof(struct objc_method_description_t),
+ sizeof(struct objc_method_description_t));
+ if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
+ swapStruct(md);
+
+ print_indent(indent);
+ outs() << " name " << format("0x%08" PRIx32, md.name);
+ if (info->verbose) {
+ name = get_pointer_32(md.name, offset, xleft, S, info, true);
+ if (name != nullptr)
+ outs() << format(" %.*s", xleft, name);
+ else
+ outs() << " (not in an __OBJC section)";
+ }
+ outs() << "\n";
+
+ print_indent(indent);
+ outs() << " types " << format("0x%08" PRIx32, md.types);
+ if (info->verbose) {
+ name = get_pointer_32(md.types, offset, xleft, S, info, true);
+ if (name != nullptr)
+ outs() << format(" %.*s", xleft, name);
+ else
+ outs() << " (not in an __OBJC section)";
+ }
+ outs() << "\n";
+ }
+ return false;
+}
+
+static bool print_protocol_list(uint32_t p, uint32_t indent,
+ struct DisassembleInfo *info);
+
+static bool print_protocol(uint32_t p, uint32_t indent,
+ struct DisassembleInfo *info) {
+ uint32_t offset, left;
+ SectionRef S;
+ struct objc_protocol_t protocol;
+ const char *r, *name;
+
+ r = get_pointer_32(p, offset, left, S, info, true);
+ if (r == nullptr)
+ return true;
+
+ outs() << "\n";
+ if (left >= sizeof(struct objc_protocol_t)) {
+ memcpy(&protocol, r, sizeof(struct objc_protocol_t));
+ } else {
+ print_indent(indent);
+ outs() << " Protocol extends past end of the section\n";
+ memset(&protocol, '\0', sizeof(struct objc_protocol_t));
+ memcpy(&protocol, r, left);
+ }
+ if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
+ swapStruct(protocol);
+
+ print_indent(indent);
+ outs() << " isa " << format("0x%08" PRIx32, protocol.isa)
+ << "\n";
+
+ print_indent(indent);
+ outs() << " protocol_name "
+ << format("0x%08" PRIx32, protocol.protocol_name);
+ if (info->verbose) {
+ name = get_pointer_32(protocol.protocol_name, offset, left, S, info, true);
+ if (name != nullptr)
+ outs() << format(" %.*s", left, name);
+ else
+ outs() << " (not in an __OBJC section)";
+ }
+ outs() << "\n";
+
+ print_indent(indent);
+ outs() << " protocol_list "
+ << format("0x%08" PRIx32, protocol.protocol_list);
+ if (print_protocol_list(protocol.protocol_list, indent + 4, info))
+ outs() << " (not in an __OBJC section)\n";
+
+ print_indent(indent);
+ outs() << " instance_methods "
+ << format("0x%08" PRIx32, protocol.instance_methods);
+ if (print_method_description_list(protocol.instance_methods, indent, info))
+ outs() << " (not in an __OBJC section)\n";
+
+ print_indent(indent);
+ outs() << " class_methods "
+ << format("0x%08" PRIx32, protocol.class_methods);
+ if (print_method_description_list(protocol.class_methods, indent, info))
+ outs() << " (not in an __OBJC section)\n";
+
+ return false;
+}
+
+static bool print_protocol_list(uint32_t p, uint32_t indent,
+ struct DisassembleInfo *info) {
+ uint32_t offset, left, l;
+ SectionRef S;
+ struct objc_protocol_list_t protocol_list;
+ const char *r, *list;
+ int32_t i;
+
+ r = get_pointer_32(p, offset, left, S, info, true);
+ if (r == nullptr)
+ return true;
+
+ outs() << "\n";
+ if (left > sizeof(struct objc_protocol_list_t)) {
+ memcpy(&protocol_list, r, sizeof(struct objc_protocol_list_t));
+ } else {
+ outs() << "\t\t objc_protocol_list_t extends past end of the section\n";
+ memset(&protocol_list, '\0', sizeof(struct objc_protocol_list_t));
+ memcpy(&protocol_list, r, left);
+ }
+ if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
+ swapStruct(protocol_list);
+
+ print_indent(indent);
+ outs() << " next " << format("0x%08" PRIx32, protocol_list.next)
+ << "\n";
+ print_indent(indent);
+ outs() << " count " << protocol_list.count << "\n";
+
+ list = r + sizeof(struct objc_protocol_list_t);
+ for (i = 0; i < protocol_list.count; i++) {
+ if ((i + 1) * sizeof(uint32_t) > left) {
+ outs() << "\t\t remaining list entries extend past the of the section\n";
+ break;
+ }
+ memcpy(&l, list + i * sizeof(uint32_t), sizeof(uint32_t));
+ if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
+ sys::swapByteOrder(l);
+
+ print_indent(indent);
+ outs() << " list[" << i << "] " << format("0x%08" PRIx32, l);
+ if (print_protocol(l, indent, info))
+ outs() << "(not in an __OBJC section)\n";
+ }
+ return false;
+}
+
+static void print_ivar_list64_t(uint64_t p, struct DisassembleInfo *info) {
+ struct ivar_list64_t il;
+ struct ivar64_t i;
+ const char *r;
+ uint32_t offset, xoffset, left, j;
+ SectionRef S, xS;
+ const char *name, *sym_name, *ivar_offset_p;
+ uint64_t ivar_offset, n_value;
+
+ r = get_pointer_64(p, offset, left, S, info);
+ if (r == nullptr)
+ return;
+ memset(&il, '\0', sizeof(struct ivar_list64_t));
+ if (left < sizeof(struct ivar_list64_t)) {
+ memcpy(&il, r, left);
+ outs() << " (ivar_list_t entends past the end of the section)\n";
+ } else
+ memcpy(&il, r, sizeof(struct ivar_list64_t));
+ if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
+ swapStruct(il);
+ outs() << " entsize " << il.entsize << "\n";
+ outs() << " count " << il.count << "\n";
+
+ p += sizeof(struct ivar_list64_t);
+ offset += sizeof(struct ivar_list64_t);
+ for (j = 0; j < il.count; j++) {
+ r = get_pointer_64(p, offset, left, S, info);
+ if (r == nullptr)
+ return;
+ memset(&i, '\0', sizeof(struct ivar64_t));
+ if (left < sizeof(struct ivar64_t)) {
+ memcpy(&i, r, left);
+ outs() << " (ivar_t entends past the end of the section)\n";
+ } else
+ memcpy(&i, r, sizeof(struct ivar64_t));
+ if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
+ swapStruct(i);
+
+ outs() << "\t\t\t offset ";
+ sym_name = get_symbol_64(offset + offsetof(struct ivar64_t, offset), S,
+ info, n_value, i.offset);
+ if (n_value != 0) {
+ if (info->verbose && sym_name != nullptr)
+ outs() << sym_name;
+ else
+ outs() << format("0x%" PRIx64, n_value);
+ if (i.offset != 0)
+ outs() << " + " << format("0x%" PRIx64, i.offset);
+ } else
+ outs() << format("0x%" PRIx64, i.offset);
+ ivar_offset_p = get_pointer_64(i.offset + n_value, xoffset, left, xS, info);
+ if (ivar_offset_p != nullptr && left >= sizeof(*ivar_offset_p)) {
+ memcpy(&ivar_offset, ivar_offset_p, sizeof(ivar_offset));
+ if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
+ sys::swapByteOrder(ivar_offset);
+ outs() << " " << ivar_offset << "\n";
+ } else
+ outs() << "\n";
+
+ outs() << "\t\t\t name ";
+ sym_name = get_symbol_64(offset + offsetof(struct ivar64_t, name), S, info,
+ n_value, i.name);
+ if (n_value != 0) {
+ if (info->verbose && sym_name != nullptr)
+ outs() << sym_name;
+ else
+ outs() << format("0x%" PRIx64, n_value);
+ if (i.name != 0)
+ outs() << " + " << format("0x%" PRIx64, i.name);
+ } else
+ outs() << format("0x%" PRIx64, i.name);
+ name = get_pointer_64(i.name + n_value, xoffset, left, xS, info);
+ if (name != nullptr)
+ outs() << format(" %.*s", left, name);
+ outs() << "\n";
+
+ outs() << "\t\t\t type ";
+ sym_name = get_symbol_64(offset + offsetof(struct ivar64_t, type), S, info,
+ n_value, i.name);
+ name = get_pointer_64(i.type + n_value, xoffset, left, xS, info);
+ if (n_value != 0) {
+ if (info->verbose && sym_name != nullptr)
+ outs() << sym_name;
+ else
+ outs() << format("0x%" PRIx64, n_value);
+ if (i.type != 0)
+ outs() << " + " << format("0x%" PRIx64, i.type);
+ } else
+ outs() << format("0x%" PRIx64, i.type);
+ if (name != nullptr)
+ outs() << format(" %.*s", left, name);
+ outs() << "\n";
+
+ outs() << "\t\t\talignment " << i.alignment << "\n";
+ outs() << "\t\t\t size " << i.size << "\n";
+
+ p += sizeof(struct ivar64_t);
+ offset += sizeof(struct ivar64_t);
+ }
+}
+
+static void print_ivar_list32_t(uint32_t p, struct DisassembleInfo *info) {
+ struct ivar_list32_t il;
+ struct ivar32_t i;
+ const char *r;
+ uint32_t offset, xoffset, left, j;
+ SectionRef S, xS;
+ const char *name, *ivar_offset_p;
+ uint32_t ivar_offset;
+
+ r = get_pointer_32(p, offset, left, S, info);
+ if (r == nullptr)
+ return;
+ memset(&il, '\0', sizeof(struct ivar_list32_t));
+ if (left < sizeof(struct ivar_list32_t)) {
+ memcpy(&il, r, left);
+ outs() << " (ivar_list_t entends past the end of the section)\n";
+ } else
+ memcpy(&il, r, sizeof(struct ivar_list32_t));
+ if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
+ swapStruct(il);
+ outs() << " entsize " << il.entsize << "\n";
+ outs() << " count " << il.count << "\n";
+
+ p += sizeof(struct ivar_list32_t);
+ offset += sizeof(struct ivar_list32_t);
+ for (j = 0; j < il.count; j++) {
+ r = get_pointer_32(p, offset, left, S, info);
+ if (r == nullptr)
+ return;
+ memset(&i, '\0', sizeof(struct ivar32_t));
+ if (left < sizeof(struct ivar32_t)) {
+ memcpy(&i, r, left);
+ outs() << " (ivar_t entends past the end of the section)\n";
+ } else
+ memcpy(&i, r, sizeof(struct ivar32_t));
+ if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
+ swapStruct(i);
+
+ outs() << "\t\t\t offset " << format("0x%" PRIx32, i.offset);
+ ivar_offset_p = get_pointer_32(i.offset, xoffset, left, xS, info);
+ if (ivar_offset_p != nullptr && left >= sizeof(*ivar_offset_p)) {
+ memcpy(&ivar_offset, ivar_offset_p, sizeof(ivar_offset));
+ if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
+ sys::swapByteOrder(ivar_offset);
+ outs() << " " << ivar_offset << "\n";
+ } else
+ outs() << "\n";
+
+ outs() << "\t\t\t name " << format("0x%" PRIx32, i.name);
+ name = get_pointer_32(i.name, xoffset, left, xS, info);
+ if (name != nullptr)
+ outs() << format(" %.*s", left, name);
+ outs() << "\n";
+
+ outs() << "\t\t\t type " << format("0x%" PRIx32, i.type);
+ name = get_pointer_32(i.type, xoffset, left, xS, info);
+ if (name != nullptr)
+ outs() << format(" %.*s", left, name);
+ outs() << "\n";
+
+ outs() << "\t\t\talignment " << i.alignment << "\n";
+ outs() << "\t\t\t size " << i.size << "\n";
+
+ p += sizeof(struct ivar32_t);
+ offset += sizeof(struct ivar32_t);
+ }
+}
+
+static void print_objc_property_list64(uint64_t p,
+ struct DisassembleInfo *info) {
+ struct objc_property_list64 opl;
+ struct objc_property64 op;
+ const char *r;
+ uint32_t offset, xoffset, left, j;
+ SectionRef S, xS;
+ const char *name, *sym_name;
+ uint64_t n_value;
+
+ r = get_pointer_64(p, offset, left, S, info);
+ if (r == nullptr)
+ return;
+ memset(&opl, '\0', sizeof(struct objc_property_list64));
+ if (left < sizeof(struct objc_property_list64)) {
+ memcpy(&opl, r, left);
+ outs() << " (objc_property_list entends past the end of the section)\n";
+ } else
+ memcpy(&opl, r, sizeof(struct objc_property_list64));
+ if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
+ swapStruct(opl);
+ outs() << " entsize " << opl.entsize << "\n";
+ outs() << " count " << opl.count << "\n";
+
+ p += sizeof(struct objc_property_list64);
+ offset += sizeof(struct objc_property_list64);
+ for (j = 0; j < opl.count; j++) {
+ r = get_pointer_64(p, offset, left, S, info);
+ if (r == nullptr)
+ return;
+ memset(&op, '\0', sizeof(struct objc_property64));
+ if (left < sizeof(struct objc_property64)) {
+ memcpy(&op, r, left);
+ outs() << " (objc_property entends past the end of the section)\n";
+ } else
+ memcpy(&op, r, sizeof(struct objc_property64));
+ if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
+ swapStruct(op);
+
+ outs() << "\t\t\t name ";
+ sym_name = get_symbol_64(offset + offsetof(struct objc_property64, name), S,
+ info, n_value, op.name);
+ if (n_value != 0) {
+ if (info->verbose && sym_name != nullptr)
+ outs() << sym_name;
+ else
+ outs() << format("0x%" PRIx64, n_value);
+ if (op.name != 0)
+ outs() << " + " << format("0x%" PRIx64, op.name);
+ } else
+ outs() << format("0x%" PRIx64, op.name);
+ name = get_pointer_64(op.name + n_value, xoffset, left, xS, info);
+ if (name != nullptr)
+ outs() << format(" %.*s", left, name);
+ outs() << "\n";
+
+ outs() << "\t\t\tattributes ";
+ sym_name =
+ get_symbol_64(offset + offsetof(struct objc_property64, attributes), S,
+ info, n_value, op.attributes);
+ if (n_value != 0) {
+ if (info->verbose && sym_name != nullptr)
+ outs() << sym_name;
+ else
+ outs() << format("0x%" PRIx64, n_value);
+ if (op.attributes != 0)
+ outs() << " + " << format("0x%" PRIx64, op.attributes);
+ } else
+ outs() << format("0x%" PRIx64, op.attributes);
+ name = get_pointer_64(op.attributes + n_value, xoffset, left, xS, info);
+ if (name != nullptr)
+ outs() << format(" %.*s", left, name);
+ outs() << "\n";
+
+ p += sizeof(struct objc_property64);
+ offset += sizeof(struct objc_property64);
+ }
+}
+
+static void print_objc_property_list32(uint32_t p,
+ struct DisassembleInfo *info) {
+ struct objc_property_list32 opl;
+ struct objc_property32 op;
+ const char *r;
+ uint32_t offset, xoffset, left, j;
+ SectionRef S, xS;
+ const char *name;
+
+ r = get_pointer_32(p, offset, left, S, info);
+ if (r == nullptr)
+ return;
+ memset(&opl, '\0', sizeof(struct objc_property_list32));
+ if (left < sizeof(struct objc_property_list32)) {
+ memcpy(&opl, r, left);
+ outs() << " (objc_property_list entends past the end of the section)\n";
+ } else
+ memcpy(&opl, r, sizeof(struct objc_property_list32));
+ if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
+ swapStruct(opl);
+ outs() << " entsize " << opl.entsize << "\n";
+ outs() << " count " << opl.count << "\n";
+
+ p += sizeof(struct objc_property_list32);
+ offset += sizeof(struct objc_property_list32);
+ for (j = 0; j < opl.count; j++) {
+ r = get_pointer_32(p, offset, left, S, info);
+ if (r == nullptr)
+ return;
+ memset(&op, '\0', sizeof(struct objc_property32));
+ if (left < sizeof(struct objc_property32)) {
+ memcpy(&op, r, left);
+ outs() << " (objc_property entends past the end of the section)\n";
+ } else
+ memcpy(&op, r, sizeof(struct objc_property32));
+ if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
+ swapStruct(op);
+
+ outs() << "\t\t\t name " << format("0x%" PRIx32, op.name);
+ name = get_pointer_32(op.name, xoffset, left, xS, info);
+ if (name != nullptr)
+ outs() << format(" %.*s", left, name);
+ outs() << "\n";
+
+ outs() << "\t\t\tattributes " << format("0x%" PRIx32, op.attributes);
+ name = get_pointer_32(op.attributes, xoffset, left, xS, info);
+ if (name != nullptr)
+ outs() << format(" %.*s", left, name);
+ outs() << "\n";
+
+ p += sizeof(struct objc_property32);
+ offset += sizeof(struct objc_property32);
+ }
+}
+
+static void print_class_ro64_t(uint64_t p, struct DisassembleInfo *info,
+ bool &is_meta_class) {
+ struct class_ro64_t cro;
+ const char *r;
+ uint32_t offset, xoffset, left;
+ SectionRef S, xS;
+ const char *name, *sym_name;
+ uint64_t n_value;
+
+ r = get_pointer_64(p, offset, left, S, info);
+ if (r == nullptr || left < sizeof(struct class_ro64_t))
+ return;
+ memset(&cro, '\0', sizeof(struct class_ro64_t));
+ if (left < sizeof(struct class_ro64_t)) {
+ memcpy(&cro, r, left);
+ outs() << " (class_ro_t entends past the end of the section)\n";
+ } else
+ memcpy(&cro, r, sizeof(struct class_ro64_t));
+ if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
+ swapStruct(cro);
+ outs() << " flags " << format("0x%" PRIx32, cro.flags);
+ if (cro.flags & RO_META)
+ outs() << " RO_META";
+ if (cro.flags & RO_ROOT)
+ outs() << " RO_ROOT";
+ if (cro.flags & RO_HAS_CXX_STRUCTORS)
+ outs() << " RO_HAS_CXX_STRUCTORS";
+ outs() << "\n";
+ outs() << " instanceStart " << cro.instanceStart << "\n";
+ outs() << " instanceSize " << cro.instanceSize << "\n";
+ outs() << " reserved " << format("0x%" PRIx32, cro.reserved)
+ << "\n";
+ outs() << " ivarLayout " << format("0x%" PRIx64, cro.ivarLayout)
+ << "\n";
+ print_layout_map64(cro.ivarLayout, info);
+
+ outs() << " name ";
+ sym_name = get_symbol_64(offset + offsetof(struct class_ro64_t, name), S,
+ info, n_value, cro.name);
+ if (n_value != 0) {
+ if (info->verbose && sym_name != nullptr)
+ outs() << sym_name;
+ else
+ outs() << format("0x%" PRIx64, n_value);
+ if (cro.name != 0)
+ outs() << " + " << format("0x%" PRIx64, cro.name);
+ } else
+ outs() << format("0x%" PRIx64, cro.name);
+ name = get_pointer_64(cro.name + n_value, xoffset, left, xS, info);
+ if (name != nullptr)
+ outs() << format(" %.*s", left, name);
+ outs() << "\n";
+
+ outs() << " baseMethods ";
+ sym_name = get_symbol_64(offset + offsetof(struct class_ro64_t, baseMethods),
+ S, info, n_value, cro.baseMethods);
+ if (n_value != 0) {
+ if (info->verbose && sym_name != nullptr)
+ outs() << sym_name;
+ else
+ outs() << format("0x%" PRIx64, n_value);
+ if (cro.baseMethods != 0)
+ outs() << " + " << format("0x%" PRIx64, cro.baseMethods);
+ } else
+ outs() << format("0x%" PRIx64, cro.baseMethods);
+ outs() << " (struct method_list_t *)\n";
+ if (cro.baseMethods + n_value != 0)
+ print_method_list64_t(cro.baseMethods + n_value, info, "");
+
+ outs() << " baseProtocols ";
+ sym_name =
+ get_symbol_64(offset + offsetof(struct class_ro64_t, baseProtocols), S,
+ info, n_value, cro.baseProtocols);
+ if (n_value != 0) {
+ if (info->verbose && sym_name != nullptr)
+ outs() << sym_name;
+ else
+ outs() << format("0x%" PRIx64, n_value);
+ if (cro.baseProtocols != 0)
+ outs() << " + " << format("0x%" PRIx64, cro.baseProtocols);
+ } else
+ outs() << format("0x%" PRIx64, cro.baseProtocols);
+ outs() << "\n";
+ if (cro.baseProtocols + n_value != 0)
+ print_protocol_list64_t(cro.baseProtocols + n_value, info);
+
+ outs() << " ivars ";
+ sym_name = get_symbol_64(offset + offsetof(struct class_ro64_t, ivars), S,
+ info, n_value, cro.ivars);
+ if (n_value != 0) {
+ if (info->verbose && sym_name != nullptr)
+ outs() << sym_name;
+ else
+ outs() << format("0x%" PRIx64, n_value);
+ if (cro.ivars != 0)
+ outs() << " + " << format("0x%" PRIx64, cro.ivars);
+ } else
+ outs() << format("0x%" PRIx64, cro.ivars);
+ outs() << "\n";
+ if (cro.ivars + n_value != 0)
+ print_ivar_list64_t(cro.ivars + n_value, info);
+
+ outs() << " weakIvarLayout ";
+ sym_name =
+ get_symbol_64(offset + offsetof(struct class_ro64_t, weakIvarLayout), S,
+ info, n_value, cro.weakIvarLayout);
+ if (n_value != 0) {
+ if (info->verbose && sym_name != nullptr)
+ outs() << sym_name;
+ else
+ outs() << format("0x%" PRIx64, n_value);
+ if (cro.weakIvarLayout != 0)
+ outs() << " + " << format("0x%" PRIx64, cro.weakIvarLayout);
+ } else
+ outs() << format("0x%" PRIx64, cro.weakIvarLayout);
+ outs() << "\n";
+ print_layout_map64(cro.weakIvarLayout + n_value, info);
+
+ outs() << " baseProperties ";
+ sym_name =
+ get_symbol_64(offset + offsetof(struct class_ro64_t, baseProperties), S,
+ info, n_value, cro.baseProperties);
+ if (n_value != 0) {
+ if (info->verbose && sym_name != nullptr)
+ outs() << sym_name;
+ else
+ outs() << format("0x%" PRIx64, n_value);
+ if (cro.baseProperties != 0)
+ outs() << " + " << format("0x%" PRIx64, cro.baseProperties);
+ } else
+ outs() << format("0x%" PRIx64, cro.baseProperties);
+ outs() << "\n";
+ if (cro.baseProperties + n_value != 0)
+ print_objc_property_list64(cro.baseProperties + n_value, info);
+
+ is_meta_class = (cro.flags & RO_META) ? true : false;
+}
+
+static void print_class_ro32_t(uint32_t p, struct DisassembleInfo *info,
+ bool &is_meta_class) {
+ struct class_ro32_t cro;
+ const char *r;
+ uint32_t offset, xoffset, left;
+ SectionRef S, xS;
+ const char *name;
+
+ r = get_pointer_32(p, offset, left, S, info);
+ if (r == nullptr)
+ return;
+ memset(&cro, '\0', sizeof(struct class_ro32_t));
+ if (left < sizeof(struct class_ro32_t)) {
+ memcpy(&cro, r, left);
+ outs() << " (class_ro_t entends past the end of the section)\n";
+ } else
+ memcpy(&cro, r, sizeof(struct class_ro32_t));
+ if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
+ swapStruct(cro);
+ outs() << " flags " << format("0x%" PRIx32, cro.flags);
+ if (cro.flags & RO_META)
+ outs() << " RO_META";
+ if (cro.flags & RO_ROOT)
+ outs() << " RO_ROOT";
+ if (cro.flags & RO_HAS_CXX_STRUCTORS)
+ outs() << " RO_HAS_CXX_STRUCTORS";
+ outs() << "\n";
+ outs() << " instanceStart " << cro.instanceStart << "\n";
+ outs() << " instanceSize " << cro.instanceSize << "\n";
+ outs() << " ivarLayout " << format("0x%" PRIx32, cro.ivarLayout)
+ << "\n";
+ print_layout_map32(cro.ivarLayout, info);
+
+ outs() << " name " << format("0x%" PRIx32, cro.name);
+ name = get_pointer_32(cro.name, xoffset, left, xS, info);
+ if (name != nullptr)
+ outs() << format(" %.*s", left, name);
+ outs() << "\n";
+
+ outs() << " baseMethods "
+ << format("0x%" PRIx32, cro.baseMethods)
+ << " (struct method_list_t *)\n";
+ if (cro.baseMethods != 0)
+ print_method_list32_t(cro.baseMethods, info, "");
+
+ outs() << " baseProtocols "
+ << format("0x%" PRIx32, cro.baseProtocols) << "\n";
+ if (cro.baseProtocols != 0)
+ print_protocol_list32_t(cro.baseProtocols, info);
+ outs() << " ivars " << format("0x%" PRIx32, cro.ivars)
+ << "\n";
+ if (cro.ivars != 0)
+ print_ivar_list32_t(cro.ivars, info);
+ outs() << " weakIvarLayout "
+ << format("0x%" PRIx32, cro.weakIvarLayout) << "\n";
+ print_layout_map32(cro.weakIvarLayout, info);
+ outs() << " baseProperties "
+ << format("0x%" PRIx32, cro.baseProperties) << "\n";
+ if (cro.baseProperties != 0)
+ print_objc_property_list32(cro.baseProperties, info);
+ is_meta_class = (cro.flags & RO_META) ? true : false;
+}
+
+static void print_class64_t(uint64_t p, struct DisassembleInfo *info) {
+ struct class64_t c;
+ const char *r;
+ uint32_t offset, left;
+ SectionRef S;
+ const char *name;
+ uint64_t isa_n_value, n_value;
+
+ r = get_pointer_64(p, offset, left, S, info);
+ if (r == nullptr || left < sizeof(struct class64_t))
+ return;
+ memset(&c, '\0', sizeof(struct class64_t));
+ if (left < sizeof(struct class64_t)) {
+ memcpy(&c, r, left);
+ outs() << " (class_t entends past the end of the section)\n";
+ } else
+ memcpy(&c, r, sizeof(struct class64_t));
+ if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
+ swapStruct(c);
+
+ outs() << " isa " << format("0x%" PRIx64, c.isa);
+ name = get_symbol_64(offset + offsetof(struct class64_t, isa), S, info,
+ isa_n_value, c.isa);
+ if (name != nullptr)
+ outs() << " " << name;
+ outs() << "\n";
+
+ outs() << " superclass " << format("0x%" PRIx64, c.superclass);
+ name = get_symbol_64(offset + offsetof(struct class64_t, superclass), S, info,
+ n_value, c.superclass);
+ if (name != nullptr)
+ outs() << " " << name;
+ outs() << "\n";
+
+ outs() << " cache " << format("0x%" PRIx64, c.cache);
+ name = get_symbol_64(offset + offsetof(struct class64_t, cache), S, info,
+ n_value, c.cache);
+ if (name != nullptr)
+ outs() << " " << name;
+ outs() << "\n";
+
+ outs() << " vtable " << format("0x%" PRIx64, c.vtable);
+ name = get_symbol_64(offset + offsetof(struct class64_t, vtable), S, info,
+ n_value, c.vtable);
+ if (name != nullptr)
+ outs() << " " << name;
+ outs() << "\n";
+
+ name = get_symbol_64(offset + offsetof(struct class64_t, data), S, info,
+ n_value, c.data);
+ outs() << " data ";
+ if (n_value != 0) {
+ if (info->verbose && name != nullptr)
+ outs() << name;
+ else
+ outs() << format("0x%" PRIx64, n_value);
+ if (c.data != 0)
+ outs() << " + " << format("0x%" PRIx64, c.data);
+ } else
+ outs() << format("0x%" PRIx64, c.data);
+ outs() << " (struct class_ro_t *)";
+
+ // This is a Swift class if some of the low bits of the pointer are set.
+ if ((c.data + n_value) & 0x7)
+ outs() << " Swift class";
+ outs() << "\n";
+ bool is_meta_class;
+ print_class_ro64_t((c.data + n_value) & ~0x7, info, is_meta_class);
+
+ if (is_meta_class == false) {
+ outs() << "Meta Class\n";
+ print_class64_t(c.isa + isa_n_value, info);
+ }
+}
+
+static void print_class32_t(uint32_t p, struct DisassembleInfo *info) {
+ struct class32_t c;
+ const char *r;
+ uint32_t offset, left;
+ SectionRef S;
+ const char *name;
+
+ r = get_pointer_32(p, offset, left, S, info);
+ if (r == nullptr)
+ return;
+ memset(&c, '\0', sizeof(struct class32_t));
+ if (left < sizeof(struct class32_t)) {
+ memcpy(&c, r, left);
+ outs() << " (class_t entends past the end of the section)\n";
+ } else
+ memcpy(&c, r, sizeof(struct class32_t));
+ if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
+ swapStruct(c);
+
+ outs() << " isa " << format("0x%" PRIx32, c.isa);
+ name =
+ get_symbol_32(offset + offsetof(struct class32_t, isa), S, info, c.isa);
+ if (name != nullptr)
+ outs() << " " << name;
+ outs() << "\n";
+
+ outs() << " superclass " << format("0x%" PRIx32, c.superclass);
+ name = get_symbol_32(offset + offsetof(struct class32_t, superclass), S, info,
+ c.superclass);
+ if (name != nullptr)
+ outs() << " " << name;
+ outs() << "\n";
+
+ outs() << " cache " << format("0x%" PRIx32, c.cache);
+ name = get_symbol_32(offset + offsetof(struct class32_t, cache), S, info,
+ c.cache);
+ if (name != nullptr)
+ outs() << " " << name;
+ outs() << "\n";
+
+ outs() << " vtable " << format("0x%" PRIx32, c.vtable);
+ name = get_symbol_32(offset + offsetof(struct class32_t, vtable), S, info,
+ c.vtable);
+ if (name != nullptr)
+ outs() << " " << name;
+ outs() << "\n";
+
+ name =
+ get_symbol_32(offset + offsetof(struct class32_t, data), S, info, c.data);
+ outs() << " data " << format("0x%" PRIx32, c.data)
+ << " (struct class_ro_t *)";
+
+ // This is a Swift class if some of the low bits of the pointer are set.
+ if (c.data & 0x3)
+ outs() << " Swift class";
+ outs() << "\n";
+ bool is_meta_class;
+ print_class_ro32_t(c.data & ~0x3, info, is_meta_class);
+
+ if (is_meta_class == false) {
+ outs() << "Meta Class\n";
+ print_class32_t(c.isa, info);
+ }
+}
+
+static void print_objc_class_t(struct objc_class_t *objc_class,
+ struct DisassembleInfo *info) {
+ uint32_t offset, left, xleft;
+ const char *name, *p, *ivar_list;
+ SectionRef S;
+ int32_t i;
+ struct objc_ivar_list_t objc_ivar_list;
+ struct objc_ivar_t ivar;
+
+ outs() << "\t\t isa " << format("0x%08" PRIx32, objc_class->isa);
+ if (info->verbose && CLS_GETINFO(objc_class, CLS_META)) {
+ name = get_pointer_32(objc_class->isa, offset, left, S, info, true);
+ if (name != nullptr)
+ outs() << format(" %.*s", left, name);
+ else
+ outs() << " (not in an __OBJC section)";
+ }
+ outs() << "\n";
+
+ outs() << "\t super_class "
+ << format("0x%08" PRIx32, objc_class->super_class);
+ if (info->verbose) {
+ name = get_pointer_32(objc_class->super_class, offset, left, S, info, true);
+ if (name != nullptr)
+ outs() << format(" %.*s", left, name);
+ else
+ outs() << " (not in an __OBJC section)";
+ }
+ outs() << "\n";
+
+ outs() << "\t\t name " << format("0x%08" PRIx32, objc_class->name);
+ if (info->verbose) {
+ name = get_pointer_32(objc_class->name, offset, left, S, info, true);
+ if (name != nullptr)
+ outs() << format(" %.*s", left, name);
+ else
+ outs() << " (not in an __OBJC section)";
+ }
+ outs() << "\n";
+
+ outs() << "\t\t version " << format("0x%08" PRIx32, objc_class->version)
+ << "\n";
+
+ outs() << "\t\t info " << format("0x%08" PRIx32, objc_class->info);
+ if (info->verbose) {
+ if (CLS_GETINFO(objc_class, CLS_CLASS))
+ outs() << " CLS_CLASS";
+ else if (CLS_GETINFO(objc_class, CLS_META))
+ outs() << " CLS_META";
+ }
+ outs() << "\n";
+
+ outs() << "\t instance_size "
+ << format("0x%08" PRIx32, objc_class->instance_size) << "\n";
+
+ p = get_pointer_32(objc_class->ivars, offset, left, S, info, true);
+ outs() << "\t\t ivars " << format("0x%08" PRIx32, objc_class->ivars);
+ if (p != nullptr) {
+ if (left > sizeof(struct objc_ivar_list_t)) {
+ outs() << "\n";
+ memcpy(&objc_ivar_list, p, sizeof(struct objc_ivar_list_t));
+ } else {
+ outs() << " (entends past the end of the section)\n";
+ memset(&objc_ivar_list, '\0', sizeof(struct objc_ivar_list_t));
+ memcpy(&objc_ivar_list, p, left);
+ }
+ if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
+ swapStruct(objc_ivar_list);
+ outs() << "\t\t ivar_count " << objc_ivar_list.ivar_count << "\n";
+ ivar_list = p + sizeof(struct objc_ivar_list_t);
+ for (i = 0; i < objc_ivar_list.ivar_count; i++) {
+ if ((i + 1) * sizeof(struct objc_ivar_t) > left) {
+ outs() << "\t\t remaining ivar's extend past the of the section\n";
+ break;
+ }
+ memcpy(&ivar, ivar_list + i * sizeof(struct objc_ivar_t),
+ sizeof(struct objc_ivar_t));
+ if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
+ swapStruct(ivar);
+
+ outs() << "\t\t\tivar_name " << format("0x%08" PRIx32, ivar.ivar_name);
+ if (info->verbose) {
+ name = get_pointer_32(ivar.ivar_name, offset, xleft, S, info, true);
+ if (name != nullptr)
+ outs() << format(" %.*s", xleft, name);
+ else
+ outs() << " (not in an __OBJC section)";
+ }
+ outs() << "\n";
+
+ outs() << "\t\t\tivar_type " << format("0x%08" PRIx32, ivar.ivar_type);
+ if (info->verbose) {
+ name = get_pointer_32(ivar.ivar_type, offset, xleft, S, info, true);
+ if (name != nullptr)
+ outs() << format(" %.*s", xleft, name);
+ else
+ outs() << " (not in an __OBJC section)";
+ }
+ outs() << "\n";
+
+ outs() << "\t\t ivar_offset "
+ << format("0x%08" PRIx32, ivar.ivar_offset) << "\n";
+ }
+ } else {
+ outs() << " (not in an __OBJC section)\n";
+ }
+
+ outs() << "\t\t methods " << format("0x%08" PRIx32, objc_class->methodLists);
+ if (print_method_list(objc_class->methodLists, info))
+ outs() << " (not in an __OBJC section)\n";
+
+ outs() << "\t\t cache " << format("0x%08" PRIx32, objc_class->cache)
+ << "\n";
+
+ outs() << "\t\tprotocols " << format("0x%08" PRIx32, objc_class->protocols);
+ if (print_protocol_list(objc_class->protocols, 16, info))
+ outs() << " (not in an __OBJC section)\n";
+}
+
+static void print_objc_objc_category_t(struct objc_category_t *objc_category,
+ struct DisassembleInfo *info) {
+ uint32_t offset, left;
+ const char *name;
+ SectionRef S;
+
+ outs() << "\t category name "
+ << format("0x%08" PRIx32, objc_category->category_name);
+ if (info->verbose) {
+ name = get_pointer_32(objc_category->category_name, offset, left, S, info,
+ true);
+ if (name != nullptr)
+ outs() << format(" %.*s", left, name);
+ else
+ outs() << " (not in an __OBJC section)";
+ }
+ outs() << "\n";
+
+ outs() << "\t\t class name "
+ << format("0x%08" PRIx32, objc_category->class_name);
+ if (info->verbose) {
+ name =
+ get_pointer_32(objc_category->class_name, offset, left, S, info, true);
+ if (name != nullptr)
+ outs() << format(" %.*s", left, name);
+ else
+ outs() << " (not in an __OBJC section)";
+ }
+ outs() << "\n";
+
+ outs() << "\t instance methods "
+ << format("0x%08" PRIx32, objc_category->instance_methods);
+ if (print_method_list(objc_category->instance_methods, info))
+ outs() << " (not in an __OBJC section)\n";
+
+ outs() << "\t class methods "
+ << format("0x%08" PRIx32, objc_category->class_methods);
+ if (print_method_list(objc_category->class_methods, info))
+ outs() << " (not in an __OBJC section)\n";
+}
+
+static void print_category64_t(uint64_t p, struct DisassembleInfo *info) {
+ struct category64_t c;
+ const char *r;
+ uint32_t offset, xoffset, left;
+ SectionRef S, xS;
+ const char *name, *sym_name;
+ uint64_t n_value;
+
+ r = get_pointer_64(p, offset, left, S, info);
+ if (r == nullptr)
+ return;
+ memset(&c, '\0', sizeof(struct category64_t));
+ if (left < sizeof(struct category64_t)) {
+ memcpy(&c, r, left);
+ outs() << " (category_t entends past the end of the section)\n";
+ } else
+ memcpy(&c, r, sizeof(struct category64_t));
+ if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
+ swapStruct(c);
+
+ outs() << " name ";
+ sym_name = get_symbol_64(offset + offsetof(struct category64_t, name), S,
+ info, n_value, c.name);
+ if (n_value != 0) {
+ if (info->verbose && sym_name != nullptr)
+ outs() << sym_name;
+ else
+ outs() << format("0x%" PRIx64, n_value);
+ if (c.name != 0)
+ outs() << " + " << format("0x%" PRIx64, c.name);
+ } else
+ outs() << format("0x%" PRIx64, c.name);
+ name = get_pointer_64(c.name + n_value, xoffset, left, xS, info);
+ if (name != nullptr)
+ outs() << format(" %.*s", left, name);
+ outs() << "\n";
+
+ outs() << " cls ";
+ sym_name = get_symbol_64(offset + offsetof(struct category64_t, cls), S, info,
+ n_value, c.cls);
+ if (n_value != 0) {
+ if (info->verbose && sym_name != nullptr)
+ outs() << sym_name;
+ else
+ outs() << format("0x%" PRIx64, n_value);
+ if (c.cls != 0)
+ outs() << " + " << format("0x%" PRIx64, c.cls);
+ } else
+ outs() << format("0x%" PRIx64, c.cls);
+ outs() << "\n";
+ if (c.cls + n_value != 0)
+ print_class64_t(c.cls + n_value, info);
+
+ outs() << " instanceMethods ";
+ sym_name =
+ get_symbol_64(offset + offsetof(struct category64_t, instanceMethods), S,
+ info, n_value, c.instanceMethods);
+ if (n_value != 0) {
+ if (info->verbose && sym_name != nullptr)
+ outs() << sym_name;
+ else
+ outs() << format("0x%" PRIx64, n_value);
+ if (c.instanceMethods != 0)
+ outs() << " + " << format("0x%" PRIx64, c.instanceMethods);
+ } else
+ outs() << format("0x%" PRIx64, c.instanceMethods);
+ outs() << "\n";
+ if (c.instanceMethods + n_value != 0)
+ print_method_list64_t(c.instanceMethods + n_value, info, "");
+
+ outs() << " classMethods ";
+ sym_name = get_symbol_64(offset + offsetof(struct category64_t, classMethods),
+ S, info, n_value, c.classMethods);
+ if (n_value != 0) {
+ if (info->verbose && sym_name != nullptr)
+ outs() << sym_name;
+ else
+ outs() << format("0x%" PRIx64, n_value);
+ if (c.classMethods != 0)
+ outs() << " + " << format("0x%" PRIx64, c.classMethods);
+ } else
+ outs() << format("0x%" PRIx64, c.classMethods);
+ outs() << "\n";
+ if (c.classMethods + n_value != 0)
+ print_method_list64_t(c.classMethods + n_value, info, "");
+
+ outs() << " protocols ";
+ sym_name = get_symbol_64(offset + offsetof(struct category64_t, protocols), S,
+ info, n_value, c.protocols);
+ if (n_value != 0) {
+ if (info->verbose && sym_name != nullptr)
+ outs() << sym_name;
+ else
+ outs() << format("0x%" PRIx64, n_value);
+ if (c.protocols != 0)
+ outs() << " + " << format("0x%" PRIx64, c.protocols);
+ } else
+ outs() << format("0x%" PRIx64, c.protocols);
+ outs() << "\n";
+ if (c.protocols + n_value != 0)
+ print_protocol_list64_t(c.protocols + n_value, info);
+
+ outs() << "instanceProperties ";
+ sym_name =
+ get_symbol_64(offset + offsetof(struct category64_t, instanceProperties),
+ S, info, n_value, c.instanceProperties);
+ if (n_value != 0) {
+ if (info->verbose && sym_name != nullptr)
+ outs() << sym_name;
+ else
+ outs() << format("0x%" PRIx64, n_value);
+ if (c.instanceProperties != 0)
+ outs() << " + " << format("0x%" PRIx64, c.instanceProperties);
+ } else
+ outs() << format("0x%" PRIx64, c.instanceProperties);
+ outs() << "\n";
+ if (c.instanceProperties + n_value != 0)
+ print_objc_property_list64(c.instanceProperties + n_value, info);
+}
+
+static void print_category32_t(uint32_t p, struct DisassembleInfo *info) {
+ struct category32_t c;
+ const char *r;
+ uint32_t offset, left;
+ SectionRef S, xS;
+ const char *name;
+
+ r = get_pointer_32(p, offset, left, S, info);
+ if (r == nullptr)
+ return;
+ memset(&c, '\0', sizeof(struct category32_t));
+ if (left < sizeof(struct category32_t)) {
+ memcpy(&c, r, left);
+ outs() << " (category_t entends past the end of the section)\n";
+ } else
+ memcpy(&c, r, sizeof(struct category32_t));
+ if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
+ swapStruct(c);
+
+ outs() << " name " << format("0x%" PRIx32, c.name);
+ name = get_symbol_32(offset + offsetof(struct category32_t, name), S, info,
+ c.name);
+ if (name != NULL)
+ outs() << " " << name;
+ outs() << "\n";
+
+ outs() << " cls " << format("0x%" PRIx32, c.cls) << "\n";
+ if (c.cls != 0)
+ print_class32_t(c.cls, info);
+ outs() << " instanceMethods " << format("0x%" PRIx32, c.instanceMethods)
+ << "\n";
+ if (c.instanceMethods != 0)
+ print_method_list32_t(c.instanceMethods, info, "");
+ outs() << " classMethods " << format("0x%" PRIx32, c.classMethods)
+ << "\n";
+ if (c.classMethods != 0)
+ print_method_list32_t(c.classMethods, info, "");
+ outs() << " protocols " << format("0x%" PRIx32, c.protocols) << "\n";
+ if (c.protocols != 0)
+ print_protocol_list32_t(c.protocols, info);
+ outs() << "instanceProperties " << format("0x%" PRIx32, c.instanceProperties)
+ << "\n";
+ if (c.instanceProperties != 0)
+ print_objc_property_list32(c.instanceProperties, info);
+}
+
+static void print_message_refs64(SectionRef S, struct DisassembleInfo *info) {
+ uint32_t i, left, offset, xoffset;
+ uint64_t p, n_value;
+ struct message_ref64 mr;
+ const char *name, *sym_name;
+ const char *r;
+ SectionRef xS;
+
+ if (S == SectionRef())
+ return;
+
+ StringRef SectName;
+ S.getName(SectName);
+ DataRefImpl Ref = S.getRawDataRefImpl();
+ StringRef SegName = info->O->getSectionFinalSegmentName(Ref);
+ outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
+ offset = 0;
+ for (i = 0; i < S.getSize(); i += sizeof(struct message_ref64)) {
+ p = S.getAddress() + i;
+ r = get_pointer_64(p, offset, left, S, info);
+ if (r == nullptr)
+ return;
+ memset(&mr, '\0', sizeof(struct message_ref64));
+ if (left < sizeof(struct message_ref64)) {
+ memcpy(&mr, r, left);
+ outs() << " (message_ref entends past the end of the section)\n";
+ } else
+ memcpy(&mr, r, sizeof(struct message_ref64));
+ if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
+ swapStruct(mr);
+
+ outs() << " imp ";
+ name = get_symbol_64(offset + offsetof(struct message_ref64, imp), S, info,
+ n_value, mr.imp);
+ if (n_value != 0) {
+ outs() << format("0x%" PRIx64, n_value) << " ";
+ if (mr.imp != 0)
+ outs() << "+ " << format("0x%" PRIx64, mr.imp) << " ";
+ } else
+ outs() << format("0x%" PRIx64, mr.imp) << " ";
+ if (name != nullptr)
+ outs() << " " << name;
+ outs() << "\n";
+
+ outs() << " sel ";
+ sym_name = get_symbol_64(offset + offsetof(struct message_ref64, sel), S,
+ info, n_value, mr.sel);
+ if (n_value != 0) {
+ if (info->verbose && sym_name != nullptr)
+ outs() << sym_name;
+ else
+ outs() << format("0x%" PRIx64, n_value);
+ if (mr.sel != 0)
+ outs() << " + " << format("0x%" PRIx64, mr.sel);
+ } else
+ outs() << format("0x%" PRIx64, mr.sel);
+ name = get_pointer_64(mr.sel + n_value, xoffset, left, xS, info);
+ if (name != nullptr)
+ outs() << format(" %.*s", left, name);
+ outs() << "\n";
+
+ offset += sizeof(struct message_ref64);
+ }
+}
+
+static void print_message_refs32(SectionRef S, struct DisassembleInfo *info) {
+ uint32_t i, left, offset, xoffset, p;
+ struct message_ref32 mr;
+ const char *name, *r;
+ SectionRef xS;
+
+ if (S == SectionRef())
+ return;
+
+ StringRef SectName;
+ S.getName(SectName);
+ DataRefImpl Ref = S.getRawDataRefImpl();
+ StringRef SegName = info->O->getSectionFinalSegmentName(Ref);
+ outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
+ offset = 0;
+ for (i = 0; i < S.getSize(); i += sizeof(struct message_ref64)) {
+ p = S.getAddress() + i;
+ r = get_pointer_32(p, offset, left, S, info);
+ if (r == nullptr)
+ return;
+ memset(&mr, '\0', sizeof(struct message_ref32));
+ if (left < sizeof(struct message_ref32)) {
+ memcpy(&mr, r, left);
+ outs() << " (message_ref entends past the end of the section)\n";
+ } else
+ memcpy(&mr, r, sizeof(struct message_ref32));
+ if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
+ swapStruct(mr);
+
+ outs() << " imp " << format("0x%" PRIx32, mr.imp);
+ name = get_symbol_32(offset + offsetof(struct message_ref32, imp), S, info,
+ mr.imp);
+ if (name != nullptr)
+ outs() << " " << name;
+ outs() << "\n";
+
+ outs() << " sel " << format("0x%" PRIx32, mr.sel);
+ name = get_pointer_32(mr.sel, xoffset, left, xS, info);
+ if (name != nullptr)
+ outs() << " " << name;
+ outs() << "\n";
+
+ offset += sizeof(struct message_ref32);
+ }
+}
+
+static void print_image_info64(SectionRef S, struct DisassembleInfo *info) {
+ uint32_t left, offset, swift_version;
+ uint64_t p;
+ struct objc_image_info64 o;
+ const char *r;
+
+ StringRef SectName;
+ S.getName(SectName);
+ DataRefImpl Ref = S.getRawDataRefImpl();
+ StringRef SegName = info->O->getSectionFinalSegmentName(Ref);
+ outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
+ p = S.getAddress();
+ r = get_pointer_64(p, offset, left, S, info);
+ if (r == nullptr)
+ return;
+ memset(&o, '\0', sizeof(struct objc_image_info64));
+ if (left < sizeof(struct objc_image_info64)) {
+ memcpy(&o, r, left);
+ outs() << " (objc_image_info entends past the end of the section)\n";
+ } else
+ memcpy(&o, r, sizeof(struct objc_image_info64));
+ if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
+ swapStruct(o);
+ outs() << " version " << o.version << "\n";
+ outs() << " flags " << format("0x%" PRIx32, o.flags);
+ if (o.flags & OBJC_IMAGE_IS_REPLACEMENT)
+ outs() << " OBJC_IMAGE_IS_REPLACEMENT";
+ if (o.flags & OBJC_IMAGE_SUPPORTS_GC)
+ outs() << " OBJC_IMAGE_SUPPORTS_GC";
+ swift_version = (o.flags >> 8) & 0xff;
+ if (swift_version != 0) {
+ if (swift_version == 1)
+ outs() << " Swift 1.0";
+ else if (swift_version == 2)
+ outs() << " Swift 1.1";
+ else
+ outs() << " unknown future Swift version (" << swift_version << ")";
+ }
+ outs() << "\n";
+}
+
+static void print_image_info32(SectionRef S, struct DisassembleInfo *info) {
+ uint32_t left, offset, swift_version, p;
+ struct objc_image_info32 o;
+ const char *r;
+
+ StringRef SectName;
+ S.getName(SectName);
+ DataRefImpl Ref = S.getRawDataRefImpl();
+ StringRef SegName = info->O->getSectionFinalSegmentName(Ref);
+ outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
+ p = S.getAddress();
+ r = get_pointer_32(p, offset, left, S, info);
+ if (r == nullptr)
+ return;
+ memset(&o, '\0', sizeof(struct objc_image_info32));
+ if (left < sizeof(struct objc_image_info32)) {
+ memcpy(&o, r, left);
+ outs() << " (objc_image_info entends past the end of the section)\n";
+ } else
+ memcpy(&o, r, sizeof(struct objc_image_info32));
+ if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
+ swapStruct(o);
+ outs() << " version " << o.version << "\n";
+ outs() << " flags " << format("0x%" PRIx32, o.flags);
+ if (o.flags & OBJC_IMAGE_IS_REPLACEMENT)
+ outs() << " OBJC_IMAGE_IS_REPLACEMENT";
+ if (o.flags & OBJC_IMAGE_SUPPORTS_GC)
+ outs() << " OBJC_IMAGE_SUPPORTS_GC";
+ swift_version = (o.flags >> 8) & 0xff;
+ if (swift_version != 0) {
+ if (swift_version == 1)
+ outs() << " Swift 1.0";
+ else if (swift_version == 2)
+ outs() << " Swift 1.1";
+ else
+ outs() << " unknown future Swift version (" << swift_version << ")";
+ }
+ outs() << "\n";
+}
+
+static void print_image_info(SectionRef S, struct DisassembleInfo *info) {
+ uint32_t left, offset, p;
+ struct imageInfo_t o;
+ const char *r;
+
+ StringRef SectName;
+ S.getName(SectName);
+ DataRefImpl Ref = S.getRawDataRefImpl();
+ StringRef SegName = info->O->getSectionFinalSegmentName(Ref);
+ outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
+ p = S.getAddress();
+ r = get_pointer_32(p, offset, left, S, info);
+ if (r == nullptr)
+ return;
+ memset(&o, '\0', sizeof(struct imageInfo_t));
+ if (left < sizeof(struct imageInfo_t)) {
+ memcpy(&o, r, left);
+ outs() << " (imageInfo entends past the end of the section)\n";
+ } else
+ memcpy(&o, r, sizeof(struct imageInfo_t));
+ if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
+ swapStruct(o);
+ outs() << " version " << o.version << "\n";
+ outs() << " flags " << format("0x%" PRIx32, o.flags);
+ if (o.flags & 0x1)
+ outs() << " F&C";
+ if (o.flags & 0x2)
+ outs() << " GC";
+ if (o.flags & 0x4)
+ outs() << " GC-only";
+ else
+ outs() << " RR";
+ outs() << "\n";
+}
+
+static void printObjc2_64bit_MetaData(MachOObjectFile *O, bool verbose) {
+ SymbolAddressMap AddrMap;
+ if (verbose)
+ CreateSymbolAddressMap(O, &AddrMap);
+
+ std::vector<SectionRef> Sections;
+ for (const SectionRef &Section : O->sections()) {
+ StringRef SectName;
+ Section.getName(SectName);
+ Sections.push_back(Section);
+ }
+
+ struct DisassembleInfo info;
+ // Set up the block of info used by the Symbolizer call backs.
+ info.verbose = verbose;
+ info.O = O;
+ info.AddrMap = &AddrMap;
+ info.Sections = &Sections;
+ info.class_name = nullptr;
+ info.selector_name = nullptr;
+ info.method = nullptr;
+ info.demangled_name = nullptr;
+ info.bindtable = nullptr;
+ info.adrp_addr = 0;
+ info.adrp_inst = 0;
+
+ const SectionRef CL = get_section(O, "__OBJC2", "__class_list");
+ if (CL != SectionRef()) {
+ info.S = CL;
+ walk_pointer_list_64("class", CL, O, &info, print_class64_t);
+ } else {
+ const SectionRef CL = get_section(O, "__DATA", "__objc_classlist");
+ info.S = CL;
+ walk_pointer_list_64("class", CL, O, &info, print_class64_t);
+ }
+
+ const SectionRef CR = get_section(O, "__OBJC2", "__class_refs");
+ if (CR != SectionRef()) {
+ info.S = CR;
+ walk_pointer_list_64("class refs", CR, O, &info, nullptr);
+ } else {
+ const SectionRef CR = get_section(O, "__DATA", "__objc_classrefs");
+ info.S = CR;
+ walk_pointer_list_64("class refs", CR, O, &info, nullptr);
+ }
+
+ const SectionRef SR = get_section(O, "__OBJC2", "__super_refs");
+ if (SR != SectionRef()) {
+ info.S = SR;
+ walk_pointer_list_64("super refs", SR, O, &info, nullptr);
+ } else {
+ const SectionRef SR = get_section(O, "__DATA", "__objc_superrefs");
+ info.S = SR;
+ walk_pointer_list_64("super refs", SR, O, &info, nullptr);
+ }
+
+ const SectionRef CA = get_section(O, "__OBJC2", "__category_list");
+ if (CA != SectionRef()) {
+ info.S = CA;
+ walk_pointer_list_64("category", CA, O, &info, print_category64_t);
+ } else {
+ const SectionRef CA = get_section(O, "__DATA", "__objc_catlist");
+ info.S = CA;
+ walk_pointer_list_64("category", CA, O, &info, print_category64_t);
+ }
+
+ const SectionRef PL = get_section(O, "__OBJC2", "__protocol_list");
+ if (PL != SectionRef()) {
+ info.S = PL;
+ walk_pointer_list_64("protocol", PL, O, &info, nullptr);
+ } else {
+ const SectionRef PL = get_section(O, "__DATA", "__objc_protolist");
+ info.S = PL;
+ walk_pointer_list_64("protocol", PL, O, &info, nullptr);
+ }
+
+ const SectionRef MR = get_section(O, "__OBJC2", "__message_refs");
+ if (MR != SectionRef()) {
+ info.S = MR;
+ print_message_refs64(MR, &info);
+ } else {
+ const SectionRef MR = get_section(O, "__DATA", "__objc_msgrefs");
+ info.S = MR;
+ print_message_refs64(MR, &info);
+ }
+
+ const SectionRef II = get_section(O, "__OBJC2", "__image_info");
+ if (II != SectionRef()) {
+ info.S = II;
+ print_image_info64(II, &info);
+ } else {
+ const SectionRef II = get_section(O, "__DATA", "__objc_imageinfo");
+ info.S = II;
+ print_image_info64(II, &info);
+ }
+
+ if (info.bindtable != nullptr)
+ delete info.bindtable;
+}
+
+static void printObjc2_32bit_MetaData(MachOObjectFile *O, bool verbose) {
+ SymbolAddressMap AddrMap;
+ if (verbose)
+ CreateSymbolAddressMap(O, &AddrMap);
+
+ std::vector<SectionRef> Sections;
+ for (const SectionRef &Section : O->sections()) {
+ StringRef SectName;
+ Section.getName(SectName);
+ Sections.push_back(Section);
+ }
+
+ struct DisassembleInfo info;
+ // Set up the block of info used by the Symbolizer call backs.
+ info.verbose = verbose;
+ info.O = O;
+ info.AddrMap = &AddrMap;
+ info.Sections = &Sections;
+ info.class_name = nullptr;
+ info.selector_name = nullptr;
+ info.method = nullptr;
+ info.demangled_name = nullptr;
+ info.bindtable = nullptr;
+ info.adrp_addr = 0;
+ info.adrp_inst = 0;
+
+ const SectionRef CL = get_section(O, "__OBJC2", "__class_list");
+ if (CL != SectionRef()) {
+ info.S = CL;
+ walk_pointer_list_32("class", CL, O, &info, print_class32_t);
+ } else {
+ const SectionRef CL = get_section(O, "__DATA", "__objc_classlist");
+ info.S = CL;
+ walk_pointer_list_32("class", CL, O, &info, print_class32_t);
+ }
+
+ const SectionRef CR = get_section(O, "__OBJC2", "__class_refs");
+ if (CR != SectionRef()) {
+ info.S = CR;
+ walk_pointer_list_32("class refs", CR, O, &info, nullptr);
+ } else {
+ const SectionRef CR = get_section(O, "__DATA", "__objc_classrefs");
+ info.S = CR;
+ walk_pointer_list_32("class refs", CR, O, &info, nullptr);
+ }
+
+ const SectionRef SR = get_section(O, "__OBJC2", "__super_refs");
+ if (SR != SectionRef()) {
+ info.S = SR;
+ walk_pointer_list_32("super refs", SR, O, &info, nullptr);
+ } else {
+ const SectionRef SR = get_section(O, "__DATA", "__objc_superrefs");
+ info.S = SR;
+ walk_pointer_list_32("super refs", SR, O, &info, nullptr);
+ }
+
+ const SectionRef CA = get_section(O, "__OBJC2", "__category_list");
+ if (CA != SectionRef()) {
+ info.S = CA;
+ walk_pointer_list_32("category", CA, O, &info, print_category32_t);
+ } else {
+ const SectionRef CA = get_section(O, "__DATA", "__objc_catlist");
+ info.S = CA;
+ walk_pointer_list_32("category", CA, O, &info, print_category32_t);
+ }
+
+ const SectionRef PL = get_section(O, "__OBJC2", "__protocol_list");
+ if (PL != SectionRef()) {
+ info.S = PL;
+ walk_pointer_list_32("protocol", PL, O, &info, nullptr);
+ } else {
+ const SectionRef PL = get_section(O, "__DATA", "__objc_protolist");
+ info.S = PL;
+ walk_pointer_list_32("protocol", PL, O, &info, nullptr);
+ }
+
+ const SectionRef MR = get_section(O, "__OBJC2", "__message_refs");
+ if (MR != SectionRef()) {
+ info.S = MR;
+ print_message_refs32(MR, &info);
+ } else {
+ const SectionRef MR = get_section(O, "__DATA", "__objc_msgrefs");
+ info.S = MR;
+ print_message_refs32(MR, &info);
+ }
+
+ const SectionRef II = get_section(O, "__OBJC2", "__image_info");
+ if (II != SectionRef()) {
+ info.S = II;
+ print_image_info32(II, &info);
+ } else {
+ const SectionRef II = get_section(O, "__DATA", "__objc_imageinfo");
+ info.S = II;
+ print_image_info32(II, &info);
+ }
+}
+
+static bool printObjc1_32bit_MetaData(MachOObjectFile *O, bool verbose) {
+ uint32_t i, j, p, offset, xoffset, left, defs_left, def;
+ const char *r, *name, *defs;
+ struct objc_module_t module;
+ SectionRef S, xS;
+ struct objc_symtab_t symtab;
+ struct objc_class_t objc_class;
+ struct objc_category_t objc_category;
+
+ outs() << "Objective-C segment\n";
+ S = get_section(O, "__OBJC", "__module_info");
+ if (S == SectionRef())
+ return false;
+
+ SymbolAddressMap AddrMap;
+ if (verbose)
+ CreateSymbolAddressMap(O, &AddrMap);
+
+ std::vector<SectionRef> Sections;
+ for (const SectionRef &Section : O->sections()) {
+ StringRef SectName;
+ Section.getName(SectName);
+ Sections.push_back(Section);
+ }
+
+ struct DisassembleInfo info;
+ // Set up the block of info used by the Symbolizer call backs.
+ info.verbose = verbose;
+ info.O = O;
+ info.AddrMap = &AddrMap;
+ info.Sections = &Sections;
+ info.class_name = nullptr;
+ info.selector_name = nullptr;
+ info.method = nullptr;
+ info.demangled_name = nullptr;
+ info.bindtable = nullptr;
+ info.adrp_addr = 0;
+ info.adrp_inst = 0;
+
+ for (i = 0; i < S.getSize(); i += sizeof(struct objc_module_t)) {
+ p = S.getAddress() + i;
+ r = get_pointer_32(p, offset, left, S, &info, true);
+ if (r == nullptr)
+ return true;
+ memset(&module, '\0', sizeof(struct objc_module_t));
+ if (left < sizeof(struct objc_module_t)) {
+ memcpy(&module, r, left);
+ outs() << " (module extends past end of __module_info section)\n";
+ } else
+ memcpy(&module, r, sizeof(struct objc_module_t));
+ if (O->isLittleEndian() != sys::IsLittleEndianHost)
+ swapStruct(module);
+
+ outs() << "Module " << format("0x%" PRIx32, p) << "\n";
+ outs() << " version " << module.version << "\n";
+ outs() << " size " << module.size << "\n";
+ outs() << " name ";
+ name = get_pointer_32(module.name, xoffset, left, xS, &info, true);
+ if (name != nullptr)
+ outs() << format("%.*s", left, name);
+ else
+ outs() << format("0x%08" PRIx32, module.name)
+ << "(not in an __OBJC section)";
+ outs() << "\n";
+
+ r = get_pointer_32(module.symtab, xoffset, left, xS, &info, true);
+ if (module.symtab == 0 || r == nullptr) {
+ outs() << " symtab " << format("0x%08" PRIx32, module.symtab)
+ << " (not in an __OBJC section)\n";
+ continue;
+ }
+ outs() << " symtab " << format("0x%08" PRIx32, module.symtab) << "\n";
+ memset(&symtab, '\0', sizeof(struct objc_symtab_t));
+ defs_left = 0;
+ defs = nullptr;
+ if (left < sizeof(struct objc_symtab_t)) {
+ memcpy(&symtab, r, left);
+ outs() << "\tsymtab extends past end of an __OBJC section)\n";
+ } else {
+ memcpy(&symtab, r, sizeof(struct objc_symtab_t));
+ if (left > sizeof(struct objc_symtab_t)) {
+ defs_left = left - sizeof(struct objc_symtab_t);
+ defs = r + sizeof(struct objc_symtab_t);
+ }
+ }
+ if (O->isLittleEndian() != sys::IsLittleEndianHost)
+ swapStruct(symtab);
+
+ outs() << "\tsel_ref_cnt " << symtab.sel_ref_cnt << "\n";
+ r = get_pointer_32(symtab.refs, xoffset, left, xS, &info, true);
+ outs() << "\trefs " << format("0x%08" PRIx32, symtab.refs);
+ if (r == nullptr)
+ outs() << " (not in an __OBJC section)";
+ outs() << "\n";
+ outs() << "\tcls_def_cnt " << symtab.cls_def_cnt << "\n";
+ outs() << "\tcat_def_cnt " << symtab.cat_def_cnt << "\n";
+ if (symtab.cls_def_cnt > 0)
+ outs() << "\tClass Definitions\n";
+ for (j = 0; j < symtab.cls_def_cnt; j++) {
+ if ((j + 1) * sizeof(uint32_t) > defs_left) {
+ outs() << "\t(remaining class defs entries entends past the end of the "
+ << "section)\n";
+ break;
+ }
+ memcpy(&def, defs + j * sizeof(uint32_t), sizeof(uint32_t));
+ if (O->isLittleEndian() != sys::IsLittleEndianHost)
+ sys::swapByteOrder(def);
+
+ r = get_pointer_32(def, xoffset, left, xS, &info, true);
+ outs() << "\tdefs[" << j << "] " << format("0x%08" PRIx32, def);
+ if (r != nullptr) {
+ if (left > sizeof(struct objc_class_t)) {
+ outs() << "\n";
+ memcpy(&objc_class, r, sizeof(struct objc_class_t));
+ } else {
+ outs() << " (entends past the end of the section)\n";
+ memset(&objc_class, '\0', sizeof(struct objc_class_t));
+ memcpy(&objc_class, r, left);
+ }
+ if (O->isLittleEndian() != sys::IsLittleEndianHost)
+ swapStruct(objc_class);
+ print_objc_class_t(&objc_class, &info);
+ } else {
+ outs() << "(not in an __OBJC section)\n";
+ }
+
+ if (CLS_GETINFO(&objc_class, CLS_CLASS)) {
+ outs() << "\tMeta Class";
+ r = get_pointer_32(objc_class.isa, xoffset, left, xS, &info, true);
+ if (r != nullptr) {
+ if (left > sizeof(struct objc_class_t)) {
+ outs() << "\n";
+ memcpy(&objc_class, r, sizeof(struct objc_class_t));
+ } else {
+ outs() << " (entends past the end of the section)\n";
+ memset(&objc_class, '\0', sizeof(struct objc_class_t));
+ memcpy(&objc_class, r, left);
+ }
+ if (O->isLittleEndian() != sys::IsLittleEndianHost)
+ swapStruct(objc_class);
+ print_objc_class_t(&objc_class, &info);
+ } else {
+ outs() << "(not in an __OBJC section)\n";
+ }
+ }
+ }
+ if (symtab.cat_def_cnt > 0)
+ outs() << "\tCategory Definitions\n";
+ for (j = 0; j < symtab.cat_def_cnt; j++) {
+ if ((j + symtab.cls_def_cnt + 1) * sizeof(uint32_t) > defs_left) {
+ outs() << "\t(remaining category defs entries entends past the end of "
+ << "the section)\n";
+ break;
+ }
+ memcpy(&def, defs + (j + symtab.cls_def_cnt) * sizeof(uint32_t),
+ sizeof(uint32_t));
+ if (O->isLittleEndian() != sys::IsLittleEndianHost)
+ sys::swapByteOrder(def);
+
+ r = get_pointer_32(def, xoffset, left, xS, &info, true);
+ outs() << "\tdefs[" << j + symtab.cls_def_cnt << "] "
+ << format("0x%08" PRIx32, def);
+ if (r != nullptr) {
+ if (left > sizeof(struct objc_category_t)) {
+ outs() << "\n";
+ memcpy(&objc_category, r, sizeof(struct objc_category_t));
+ } else {
+ outs() << " (entends past the end of the section)\n";
+ memset(&objc_category, '\0', sizeof(struct objc_category_t));
+ memcpy(&objc_category, r, left);
+ }
+ if (O->isLittleEndian() != sys::IsLittleEndianHost)
+ swapStruct(objc_category);
+ print_objc_objc_category_t(&objc_category, &info);
+ } else {
+ outs() << "(not in an __OBJC section)\n";
+ }
+ }
+ }
+ const SectionRef II = get_section(O, "__OBJC", "__image_info");
+ if (II != SectionRef())
+ print_image_info(II, &info);
+
+ return true;
+}
+
+static void DumpProtocolSection(MachOObjectFile *O, const char *sect,
+ uint32_t size, uint32_t addr) {
+ SymbolAddressMap AddrMap;
+ CreateSymbolAddressMap(O, &AddrMap);
+
+ std::vector<SectionRef> Sections;
+ for (const SectionRef &Section : O->sections()) {
+ StringRef SectName;
+ Section.getName(SectName);
+ Sections.push_back(Section);
+ }
+
+ struct DisassembleInfo info;
+ // Set up the block of info used by the Symbolizer call backs.
+ info.verbose = true;
+ info.O = O;
+ info.AddrMap = &AddrMap;
+ info.Sections = &Sections;
+ info.class_name = nullptr;
+ info.selector_name = nullptr;
+ info.method = nullptr;
+ info.demangled_name = nullptr;
+ info.bindtable = nullptr;
+ info.adrp_addr = 0;
+ info.adrp_inst = 0;
+
+ const char *p;
+ struct objc_protocol_t protocol;
+ uint32_t left, paddr;
+ for (p = sect; p < sect + size; p += sizeof(struct objc_protocol_t)) {
+ memset(&protocol, '\0', sizeof(struct objc_protocol_t));
+ left = size - (p - sect);
+ if (left < sizeof(struct objc_protocol_t)) {
+ outs() << "Protocol extends past end of __protocol section\n";
+ memcpy(&protocol, p, left);
+ } else
+ memcpy(&protocol, p, sizeof(struct objc_protocol_t));
+ if (O->isLittleEndian() != sys::IsLittleEndianHost)
+ swapStruct(protocol);
+ paddr = addr + (p - sect);
+ outs() << "Protocol " << format("0x%" PRIx32, paddr);
+ if (print_protocol(paddr, 0, &info))
+ outs() << "(not in an __OBJC section)\n";
+ }
+}
+
+static void printObjcMetaData(MachOObjectFile *O, bool verbose) {
+ if (O->is64Bit())
+ printObjc2_64bit_MetaData(O, verbose);
+ else {
+ MachO::mach_header H;
+ H = O->getHeader();
+ if (H.cputype == MachO::CPU_TYPE_ARM)
+ printObjc2_32bit_MetaData(O, verbose);
+ else {
+ // This is the 32-bit non-arm cputype case. Which is normally
+ // the first Objective-C ABI. But it may be the case of a
+ // binary for the iOS simulator which is the second Objective-C
+ // ABI. In that case printObjc1_32bit_MetaData() will determine that
+ // and return false.
+ if (printObjc1_32bit_MetaData(O, verbose) == false)
+ printObjc2_32bit_MetaData(O, verbose);
+ }
+ }
+}
+
// GuessLiteralPointer returns a string which for the item in the Mach-O file
// for the address passed in as ReferenceValue for printing as a comment with
// the instruction and also returns the corresponding type of that item
@@ -1705,9 +5642,10 @@ uint64_t get_objc2_64bit_selref(uint64_t ReferenceValue,
//
// If there is no item in the Mach-O file for the address passed in as
// ReferenceValue nullptr is returned and ReferenceType is unchanged.
-const char *GuessLiteralPointer(uint64_t ReferenceValue, uint64_t ReferencePC,
- uint64_t *ReferenceType,
- struct DisassembleInfo *info) {
+static const char *GuessLiteralPointer(uint64_t ReferenceValue,
+ uint64_t ReferencePC,
+ uint64_t *ReferenceType,
+ struct DisassembleInfo *info) {
// First see if there is an external relocation entry at the ReferencePC.
uint64_t sect_addr = info->S.getAddress();
uint64_t sect_offset = ReferencePC - sect_addr;
@@ -1749,7 +5687,7 @@ const char *GuessLiteralPointer(uint64_t ReferenceValue, uint64_t ReferencePC,
bool classref, selref, msgref, cfstring;
uint64_t pointer_value = GuessPointerPointer(ReferenceValue, info, classref,
selref, msgref, cfstring);
- if (classref == true && pointer_value == 0) {
+ if (classref && pointer_value == 0) {
// Note the ReferenceValue is a pointer into the __objc_classrefs section.
// And the pointer_value in that section is typically zero as it will be
// set by dyld as part of the "bind information".
@@ -1765,7 +5703,7 @@ const char *GuessLiteralPointer(uint64_t ReferenceValue, uint64_t ReferencePC,
}
}
- if (classref == true) {
+ if (classref) {
*ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Class_Ref;
const char *name =
get_objc2_64bit_class_name(pointer_value, ReferenceValue, info);
@@ -1776,13 +5714,13 @@ const char *GuessLiteralPointer(uint64_t ReferenceValue, uint64_t ReferencePC,
return name;
}
- if (cfstring == true) {
+ if (cfstring) {
*ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_CFString_Ref;
const char *name = get_objc2_64bit_cfstring_name(ReferenceValue, info);
return name;
}
- if (selref == true && pointer_value == 0)
+ if (selref && pointer_value == 0)
pointer_value = get_objc2_64bit_selref(ReferenceValue, info);
if (pointer_value != 0)
@@ -1790,10 +5728,10 @@ const char *GuessLiteralPointer(uint64_t ReferenceValue, uint64_t ReferencePC,
const char *name = GuessCstringPointer(ReferenceValue, info);
if (name) {
- if (pointer_value != 0 && selref == true) {
+ if (pointer_value != 0 && selref) {
*ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Selector_Ref;
info->selector_name = name;
- } else if (pointer_value != 0 && msgref == true) {
+ } else if (pointer_value != 0 && msgref) {
info->class_name = nullptr;
*ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message_Ref;
info->selector_name = name;
@@ -1841,19 +5779,20 @@ const char *GuessLiteralPointer(uint64_t ReferenceValue, uint64_t ReferencePC,
// SymbolValue is checked to be an address of literal pointer, symbol pointer,
// or an Objective-C meta data reference. If so the output ReferenceType is
// set to correspond to that as well as setting the ReferenceName.
-const char *SymbolizerSymbolLookUp(void *DisInfo, uint64_t ReferenceValue,
- uint64_t *ReferenceType,
- uint64_t ReferencePC,
- const char **ReferenceName) {
+static const char *SymbolizerSymbolLookUp(void *DisInfo,
+ uint64_t ReferenceValue,
+ uint64_t *ReferenceType,
+ uint64_t ReferencePC,
+ const char **ReferenceName) {
struct DisassembleInfo *info = (struct DisassembleInfo *)DisInfo;
// If no verbose symbolic information is wanted then just return nullptr.
- if (info->verbose == false) {
+ if (!info->verbose) {
*ReferenceName = nullptr;
*ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
return nullptr;
}
- const char *SymbolName = GuessSymbolName(ReferenceValue, info);
+ const char *SymbolName = GuessSymbolName(ReferenceValue, info->AddrMap);
if (*ReferenceType == LLVMDisassembler_ReferenceType_In_Branch) {
*ReferenceName = GuessIndirectSymbol(ReferenceValue, info);
@@ -2017,7 +5956,8 @@ static void emitComments(raw_svector_ostream &CommentStream,
CommentStream.resync();
}
-static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF) {
+static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF,
+ StringRef DisSegName, StringRef DisSectName) {
const char *McpuDefault = nullptr;
const Target *ThumbTarget = nullptr;
const Target *TheTarget = GetTarget(MachOOF, &McpuDefault, &ThumbTarget);
@@ -2059,12 +5999,12 @@ static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF) {
if (RelInfo) {
Symbolizer.reset(TheTarget->createMCSymbolizer(
TripleName, SymbolizerGetOpInfo, SymbolizerSymbolLookUp,
- &SymbolizerInfo, &Ctx, RelInfo.release()));
+ &SymbolizerInfo, &Ctx, std::move(RelInfo)));
DisAsm->setSymbolizer(std::move(Symbolizer));
}
int AsmPrinterVariant = AsmInfo->getAssemblerDialect();
std::unique_ptr<MCInstPrinter> IP(TheTarget->createMCInstPrinter(
- AsmPrinterVariant, *AsmInfo, *InstrInfo, *MRI, *STI));
+ Triple(TripleName), AsmPrinterVariant, *AsmInfo, *InstrInfo, *MRI));
// Set the display preference for hex vs. decimal immediates.
IP->setPrintImmHex(PrintImmHex);
// Comment stream and backing vector.
@@ -2107,13 +6047,13 @@ static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF) {
if (ThumbRelInfo) {
ThumbSymbolizer.reset(ThumbTarget->createMCSymbolizer(
ThumbTripleName, SymbolizerGetOpInfo, SymbolizerSymbolLookUp,
- &ThumbSymbolizerInfo, PtrThumbCtx, ThumbRelInfo.release()));
+ &ThumbSymbolizerInfo, PtrThumbCtx, std::move(ThumbRelInfo)));
ThumbDisAsm->setSymbolizer(std::move(ThumbSymbolizer));
}
int ThumbAsmPrinterVariant = ThumbAsmInfo->getAssemblerDialect();
ThumbIP.reset(ThumbTarget->createMCInstPrinter(
- ThumbAsmPrinterVariant, *ThumbAsmInfo, *ThumbInstrInfo, *ThumbMRI,
- *ThumbSTI));
+ Triple(ThumbTripleName), ThumbAsmPrinterVariant, *ThumbAsmInfo,
+ *ThumbInstrInfo, *ThumbMRI));
// Set the display preference for hex vs. decimal immediates.
ThumbIP->setPrintImmHex(PrintImmHex);
}
@@ -2182,31 +6122,21 @@ static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF) {
}
// Setup the DIContext
- diContext.reset(DIContext::getDWARFContext(*DbgObj));
+ diContext.reset(new DWARFContextInMemory(*DbgObj));
}
- // TODO: For now this only disassembles the (__TEXT,__text) section (see the
- // checks in the code below at the top of this loop). It should allow a
- // darwin otool(1) like -s option to disassemble any named segment & section
- // that is marked as containing instructions with the attributes
- // S_ATTR_PURE_INSTRUCTIONS or S_ATTR_SOME_INSTRUCTIONS in the flags field of
- // the section structure.
- outs() << "(__TEXT,__text) section\n";
+ if (DumpSections.size() == 0)
+ outs() << "(" << DisSegName << "," << DisSectName << ") section\n";
for (unsigned SectIdx = 0; SectIdx != Sections.size(); SectIdx++) {
-
- bool SectIsText = Sections[SectIdx].isText();
- if (SectIsText == false)
- continue;
-
StringRef SectName;
- if (Sections[SectIdx].getName(SectName) || SectName != "__text")
- continue; // Skip non-text sections
+ if (Sections[SectIdx].getName(SectName) || SectName != DisSectName)
+ continue;
DataRefImpl DR = Sections[SectIdx].getRawDataRefImpl();
StringRef SegmentName = MachOOF->getSectionFinalSegmentName(DR);
- if (SegmentName != "__TEXT")
+ if (SegmentName != DisSegName)
continue;
StringRef BytesStr;
@@ -2234,6 +6164,7 @@ static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF) {
// Create a map of symbol addresses to symbol names for use by
// the SymbolizerSymbolLookUp() routine.
SymbolAddressMap AddrMap;
+ bool DisSymNameFound = false;
for (const SymbolRef &Symbol : MachOOF->symbols()) {
SymbolRef::Type ST;
Symbol.getType(ST);
@@ -2244,10 +6175,16 @@ static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF) {
StringRef SymName;
Symbol.getName(SymName);
AddrMap[Address] = SymName;
+ if (!DisSymName.empty() && DisSymName == SymName)
+ DisSymNameFound = true;
}
}
+ if (!DisSymName.empty() && !DisSymNameFound) {
+ outs() << "Can't find -dis-symname: " << DisSymName << "\n";
+ return;
+ }
// Set up the block of info used by the Symbolizer call backs.
- SymbolizerInfo.verbose = true;
+ SymbolizerInfo.verbose = !NoSymbolicOperands;
SymbolizerInfo.O = MachOOF;
SymbolizerInfo.S = Sections[SectIdx];
SymbolizerInfo.AddrMap = &AddrMap;
@@ -2260,7 +6197,7 @@ static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF) {
SymbolizerInfo.adrp_addr = 0;
SymbolizerInfo.adrp_inst = 0;
// Same for the ThumbSymbolizer
- ThumbSymbolizerInfo.verbose = true;
+ ThumbSymbolizerInfo.verbose = !NoSymbolicOperands;
ThumbSymbolizerInfo.O = MachOOF;
ThumbSymbolizerInfo.S = Sections[SectIdx];
ThumbSymbolizerInfo.AddrMap = &AddrMap;
@@ -2288,6 +6225,10 @@ static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF) {
if (!containsSym)
continue;
+ // If we are only disassembling one symbol see if this is that symbol.
+ if (!DisSymName.empty() && DisSymName != SymName)
+ continue;
+
// Start at the address of the symbol relative to the section's address.
uint64_t Start = 0;
uint64_t SectionAddress = Sections[SectIdx].getAddress();
@@ -2328,13 +6269,15 @@ static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF) {
MCInst Inst;
uint64_t PC = SectAddress + Index;
- if (FullLeadingAddr) {
- if (MachOOF->is64Bit())
- outs() << format("%016" PRIx64, PC);
- else
- outs() << format("%08" PRIx64, PC);
- } else {
- outs() << format("%8" PRIx64 ":", PC);
+ if (!NoLeadingAddr) {
+ if (FullLeadingAddr) {
+ if (MachOOF->is64Bit())
+ outs() << format("%016" PRIx64, PC);
+ else
+ outs() << format("%08" PRIx64, PC);
+ } else {
+ outs() << format("%8" PRIx64 ":", PC);
+ }
}
if (!NoShowRawInsn)
outs() << "\t";
@@ -2351,9 +6294,7 @@ static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF) {
DTI->second.getLength(Length);
uint16_t Kind;
DTI->second.getKind(Kind);
- Size = DumpDataInCode(reinterpret_cast<const char *>(Bytes.data()) +
- Index,
- Length, Kind);
+ Size = DumpDataInCode(Bytes.data() + Index, Length, Kind);
if ((Kind == MachO::DICE_KIND_JUMP_TABLE8) &&
(PC == (DTI->first + Length - 1)) && (Length & 1))
Size++;
@@ -2372,16 +6313,15 @@ static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF) {
DebugOut, Annotations);
if (gotInst) {
if (!NoShowRawInsn) {
- DumpBytes(StringRef(
- reinterpret_cast<const char *>(Bytes.data()) + Index, Size));
+ DumpBytes(ArrayRef<uint8_t>(Bytes.data() + Index, Size));
}
formatted_raw_ostream FormattedOS(outs());
Annotations.flush();
StringRef AnnotationsStr = Annotations.str();
if (isThumb)
- ThumbIP->printInst(&Inst, FormattedOS, AnnotationsStr);
+ ThumbIP->printInst(&Inst, FormattedOS, AnnotationsStr, *ThumbSTI);
else
- IP->printInst(&Inst, FormattedOS, AnnotationsStr);
+ IP->printInst(&Inst, FormattedOS, AnnotationsStr, *STI);
emitComments(CommentStream, CommentsToEmit, FormattedOS, *AsmInfo);
// Print debug info.
@@ -2426,21 +6366,21 @@ static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF) {
uint64_t PC = SectAddress + Index;
if (DisAsm->getInstruction(Inst, InstSize, Bytes.slice(Index), PC,
DebugOut, nulls())) {
- if (FullLeadingAddr) {
- if (MachOOF->is64Bit())
- outs() << format("%016" PRIx64, PC);
- else
- outs() << format("%08" PRIx64, PC);
- } else {
- outs() << format("%8" PRIx64 ":", PC);
+ if (!NoLeadingAddr) {
+ if (FullLeadingAddr) {
+ if (MachOOF->is64Bit())
+ outs() << format("%016" PRIx64, PC);
+ else
+ outs() << format("%08" PRIx64, PC);
+ } else {
+ outs() << format("%8" PRIx64 ":", PC);
+ }
}
if (!NoShowRawInsn) {
outs() << "\t";
- DumpBytes(
- StringRef(reinterpret_cast<const char *>(Bytes.data()) + Index,
- InstSize));
+ DumpBytes(ArrayRef<uint8_t>(Bytes.data() + Index, InstSize));
}
- IP->printInst(&Inst, outs(), "");
+ IP->printInst(&Inst, outs(), "", *STI);
outs() << "\n";
} else {
unsigned int Arch = MachOOF->getArch();
@@ -2544,7 +6484,7 @@ static void findUnwindRelocNameAddend(const MachOObjectFile *Obj,
}
auto RE = Obj->getRelocation(Reloc.getRawDataRefImpl());
- SectionRef RelocSection = Obj->getRelocationSection(RE);
+ SectionRef RelocSection = Obj->getAnyRelocationSection(RE);
uint64_t SectionAddr = RelocSection.getAddress();
@@ -4588,8 +8528,8 @@ void llvm::printMachOFileHeader(const object::ObjectFile *Obj) {
uint32_t ncmds = 0;
uint32_t filetype = 0;
uint32_t cputype = 0;
- getAndPrintMachHeader(file, ncmds, filetype, cputype, true);
- PrintLoadCommands(file, ncmds, filetype, cputype, true);
+ getAndPrintMachHeader(file, ncmds, filetype, cputype, !NonVerbose);
+ PrintLoadCommands(file, ncmds, filetype, cputype, !NonVerbose);
}
//===----------------------------------------------------------------------===//
diff --git a/contrib/llvm/tools/llvm-objdump/llvm-objdump.cpp b/contrib/llvm/tools/llvm-objdump/llvm-objdump.cpp
index aff6272..e442ac0 100644
--- a/contrib/llvm/tools/llvm-objdump/llvm-objdump.cpp
+++ b/contrib/llvm/tools/llvm-objdump/llvm-objdump.cpp
@@ -68,14 +68,14 @@ static cl::alias
Disassembled("d", cl::desc("Alias for --disassemble"),
cl::aliasopt(Disassemble));
-static cl::opt<bool>
-Relocations("r", cl::desc("Display the relocation entries in the file"));
+cl::opt<bool>
+llvm::Relocations("r", cl::desc("Display the relocation entries in the file"));
-static cl::opt<bool>
-SectionContents("s", cl::desc("Display the content of each section"));
+cl::opt<bool>
+llvm::SectionContents("s", cl::desc("Display the content of each section"));
-static cl::opt<bool>
-SymbolTable("t", cl::desc("Display the symbol table"));
+cl::opt<bool>
+llvm::SymbolTable("t", cl::desc("Display the symbol table"));
cl::opt<bool>
llvm::ExportsTrie("exports-trie", cl::desc("Display mach-o exported symbols"));
@@ -111,9 +111,9 @@ cl::opt<std::string>
llvm::ArchName("arch-name", cl::desc("Target arch to disassemble for, "
"see -version for available targets"));
-static cl::opt<bool>
-SectionHeaders("section-headers", cl::desc("Display summaries of the headers "
- "for each section."));
+cl::opt<bool>
+llvm::SectionHeaders("section-headers", cl::desc("Display summaries of the "
+ "headers for each section."));
static cl::alias
SectionHeadersShort("headers", cl::desc("Alias for --section-headers"),
cl::aliasopt(SectionHeaders));
@@ -132,8 +132,8 @@ llvm::NoShowRawInsn("no-show-raw-insn", cl::desc("When disassembling "
"instructions, do not print "
"the instruction bytes."));
-static cl::opt<bool>
-UnwindInfo("unwind-info", cl::desc("Display unwind information"));
+cl::opt<bool>
+llvm::UnwindInfo("unwind-info", cl::desc("Display unwind information"));
static cl::alias
UnwindInfoShort("u", cl::desc("Alias for --unwind-info"),
@@ -194,30 +194,17 @@ static const Target *getTarget(const ObjectFile *Obj = nullptr) {
return TheTarget;
}
-void llvm::DumpBytes(StringRef bytes) {
+void llvm::DumpBytes(ArrayRef<uint8_t> bytes) {
static const char hex_rep[] = "0123456789abcdef";
- // FIXME: The real way to do this is to figure out the longest instruction
- // and align to that size before printing. I'll fix this when I get
- // around to outputting relocations.
- // 15 is the longest x86 instruction
- // 3 is for the hex rep of a byte + a space.
- // 1 is for the null terminator.
- enum { OutputSize = (15 * 3) + 1 };
- char output[OutputSize];
-
- assert(bytes.size() <= 15
- && "DumpBytes only supports instructions of up to 15 bytes");
- memset(output, ' ', sizeof(output));
- unsigned index = 0;
- for (StringRef::iterator i = bytes.begin(),
- e = bytes.end(); i != e; ++i) {
- output[index] = hex_rep[(*i & 0xF0) >> 4];
- output[index + 1] = hex_rep[*i & 0xF];
- index += 3;
+ SmallString<64> output;
+
+ for (char i: bytes) {
+ output.push_back(hex_rep[(i & 0xF0) >> 4]);
+ output.push_back(hex_rep[i & 0xF]);
+ output.push_back(' ');
}
- output[sizeof(output) - 1] = 0;
- outs() << output;
+ outs() << output.c_str();
}
bool llvm::RelocAddressLess(RelocationRef a, RelocationRef b) {
@@ -287,7 +274,7 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {
int AsmPrinterVariant = AsmInfo->getAssemblerDialect();
std::unique_ptr<MCInstPrinter> IP(TheTarget->createMCInstPrinter(
- AsmPrinterVariant, *AsmInfo, *MII, *MRI, *STI));
+ Triple(TripleName), AsmPrinterVariant, *AsmInfo, *MII, *MRI));
if (!IP) {
errs() << "error: no instruction printer for target " << TripleName
<< '\n';
@@ -412,10 +399,9 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {
outs() << format("%8" PRIx64 ":", SectionAddr + Index);
if (!NoShowRawInsn) {
outs() << "\t";
- DumpBytes(StringRef(
- reinterpret_cast<const char *>(Bytes.data()) + Index, Size));
+ DumpBytes(ArrayRef<uint8_t>(Bytes.data() + Index, Size));
}
- IP->printInst(&Inst, outs(), "");
+ IP->printInst(&Inst, outs(), "", *STI);
outs() << CommentStream.str();
Comments.clear();
outs() << "\n";
@@ -453,7 +439,7 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) {
}
}
-static void PrintRelocations(const ObjectFile *Obj) {
+void llvm::PrintRelocations(const ObjectFile *Obj) {
StringRef Fmt = Obj->getBytesInAddress() > 4 ? "%016" PRIx64 :
"%08" PRIx64;
// Regular objdump doesn't print relocations in non-relocatable object
@@ -490,7 +476,7 @@ static void PrintRelocations(const ObjectFile *Obj) {
}
}
-static void PrintSectionHeaders(const ObjectFile *Obj) {
+void llvm::PrintSectionHeaders(const ObjectFile *Obj) {
outs() << "Sections:\n"
"Idx Name Size Address Type\n";
unsigned i = 0;
@@ -511,7 +497,7 @@ static void PrintSectionHeaders(const ObjectFile *Obj) {
}
}
-static void PrintSectionContents(const ObjectFile *Obj) {
+void llvm::PrintSectionContents(const ObjectFile *Obj) {
std::error_code EC;
for (const SectionRef &Section : Obj->sections()) {
StringRef Name;
@@ -614,7 +600,7 @@ static void PrintCOFFSymbolTable(const COFFObjectFile *coff) {
}
}
-static void PrintSymbolTable(const ObjectFile *o) {
+void llvm::PrintSymbolTable(const ObjectFile *o) {
outs() << "SYMBOL TABLE:\n";
if (const COFFObjectFile *coff = dyn_cast<const COFFObjectFile>(o)) {
@@ -642,7 +628,16 @@ static void PrintSymbolTable(const ObjectFile *o) {
bool Global = Flags & SymbolRef::SF_Global;
bool Weak = Flags & SymbolRef::SF_Weak;
bool Absolute = Flags & SymbolRef::SF_Absolute;
-
+ bool Common = Flags & SymbolRef::SF_Common;
+ bool Hidden = Flags & SymbolRef::SF_Hidden;
+
+ if (Common) {
+ uint32_t Alignment;
+ if (error(Symbol.getAlignment(Alignment)))
+ Alignment = 0;
+ Address = Size;
+ Size = Alignment;
+ }
if (Address == UnknownAddressOrSize)
Address = 0;
if (Size == UnknownAddressOrSize)
@@ -672,6 +667,8 @@ static void PrintSymbolTable(const ObjectFile *o) {
<< ' ';
if (Absolute) {
outs() << "*ABS*";
+ } else if (Common) {
+ outs() << "*COM*";
} else if (Section == o->section_end()) {
outs() << "*UND*";
} else {
@@ -687,8 +684,11 @@ static void PrintSymbolTable(const ObjectFile *o) {
outs() << SectionName;
}
outs() << '\t'
- << format("%08" PRIx64 " ", Size)
- << Name
+ << format("%08" PRIx64 " ", Size);
+ if (Hidden) {
+ outs() << ".hidden ";
+ }
+ outs() << Name
<< '\n';
}
}
@@ -892,7 +892,16 @@ int main(int argc, char **argv) {
&& !Bind
&& !LazyBind
&& !WeakBind
- && !(UniversalHeaders && MachOOpt)) {
+ && !(UniversalHeaders && MachOOpt)
+ && !(ArchiveHeaders && MachOOpt)
+ && !(IndirectSymbols && MachOOpt)
+ && !(DataInCode && MachOOpt)
+ && !(LinkOptHints && MachOOpt)
+ && !(InfoPlist && MachOOpt)
+ && !(DylibsUsed && MachOOpt)
+ && !(DylibId && MachOOpt)
+ && !(ObjcMetaData && MachOOpt)
+ && !(DumpSections.size() != 0 && MachOOpt)) {
cl::PrintHelpMessage();
return 2;
}
diff --git a/contrib/llvm/tools/llvm-objdump/llvm-objdump.h b/contrib/llvm/tools/llvm-objdump/llvm-objdump.h
index f829dd1..bde72e0 100644
--- a/contrib/llvm/tools/llvm-objdump/llvm-objdump.h
+++ b/contrib/llvm/tools/llvm-objdump/llvm-objdump.h
@@ -1,4 +1,3 @@
-//===-- llvm-objdump.h ----------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -26,6 +25,8 @@ extern cl::opt<std::string> TripleName;
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,11 +36,26 @@ extern cl::opt<bool> Bind;
extern cl::opt<bool> LazyBind;
extern cl::opt<bool> WeakBind;
extern cl::opt<bool> UniversalHeaders;
+extern cl::opt<bool> ArchiveHeaders;
+extern cl::opt<bool> IndirectSymbols;
+extern cl::opt<bool> DataInCode;
+extern cl::opt<bool> LinkOptHints;
+extern cl::opt<bool> InfoPlist;
+extern cl::opt<bool> DylibsUsed;
+extern cl::opt<bool> DylibId;
+extern cl::opt<bool> ObjcMetaData;
+extern cl::opt<std::string> DisSymName;
+extern cl::opt<bool> NonVerbose;
+extern cl::opt<bool> Relocations;
+extern cl::opt<bool> SectionHeaders;
+extern cl::opt<bool> SectionContents;
+extern cl::opt<bool> SymbolTable;
+extern cl::opt<bool> UnwindInfo;
// Various helper functions.
bool error(std::error_code ec);
bool RelocAddressLess(object::RelocationRef a, object::RelocationRef b);
-void DumpBytes(StringRef bytes);
+void DumpBytes(ArrayRef<uint8_t> bytes);
void ParseInputMachO(StringRef Filename);
void printCOFFUnwindInfo(const object::COFFObjectFile* o);
void printMachOUnwindInfo(const object::MachOObjectFile* o);
@@ -56,6 +72,10 @@ 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 PrintRelocations(const object::ObjectFile *o);
+void PrintSectionHeaders(const object::ObjectFile *o);
+void PrintSectionContents(const object::ObjectFile *o);
+void PrintSymbolTable(const object::ObjectFile *o);
} // end namespace llvm
diff --git a/contrib/llvm/tools/llvm-pdbdump/BuiltinDumper.cpp b/contrib/llvm/tools/llvm-pdbdump/BuiltinDumper.cpp
new file mode 100644
index 0000000..d808298
--- /dev/null
+++ b/contrib/llvm/tools/llvm-pdbdump/BuiltinDumper.cpp
@@ -0,0 +1,87 @@
+//===- BuiltinDumper.cpp ---------------------------------------- *- C++ *-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "BuiltinDumper.h"
+#include "LinePrinter.h"
+#include "llvm-pdbdump.h"
+
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h"
+
+using namespace llvm;
+
+BuiltinDumper::BuiltinDumper(LinePrinter &P)
+ : PDBSymDumper(false), Printer(P) {}
+
+void BuiltinDumper::start(const PDBSymbolTypeBuiltin &Symbol) {
+ PDB_BuiltinType Type = Symbol.getBuiltinType();
+ switch (Type) {
+ case PDB_BuiltinType::Float:
+ if (Symbol.getLength() == 4)
+ WithColor(Printer, PDB_ColorItem::Type).get() << "float";
+ else
+ WithColor(Printer, PDB_ColorItem::Type).get() << "double";
+ break;
+ case PDB_BuiltinType::UInt:
+ WithColor(Printer, PDB_ColorItem::Type).get() << "unsigned";
+ if (Symbol.getLength() == 8)
+ WithColor(Printer, PDB_ColorItem::Type).get() << " __int64";
+ break;
+ case PDB_BuiltinType::Int:
+ if (Symbol.getLength() == 4)
+ WithColor(Printer, PDB_ColorItem::Type).get() << "int";
+ else
+ WithColor(Printer, PDB_ColorItem::Type).get() << "__int64";
+ break;
+ case PDB_BuiltinType::Char:
+ WithColor(Printer, PDB_ColorItem::Type).get() << "char";
+ break;
+ case PDB_BuiltinType::WCharT:
+ WithColor(Printer, PDB_ColorItem::Type).get() << "wchar_t";
+ break;
+ case PDB_BuiltinType::Void:
+ WithColor(Printer, PDB_ColorItem::Type).get() << "void";
+ break;
+ case PDB_BuiltinType::Long:
+ WithColor(Printer, PDB_ColorItem::Type).get() << "long";
+ break;
+ case PDB_BuiltinType::ULong:
+ WithColor(Printer, PDB_ColorItem::Type).get() << "unsigned long";
+ break;
+ case PDB_BuiltinType::Bool:
+ WithColor(Printer, PDB_ColorItem::Type).get() << "bool";
+ break;
+ case PDB_BuiltinType::Currency:
+ WithColor(Printer, PDB_ColorItem::Type).get() << "CURRENCY";
+ break;
+ case PDB_BuiltinType::Date:
+ WithColor(Printer, PDB_ColorItem::Type).get() << "DATE";
+ break;
+ case PDB_BuiltinType::Variant:
+ WithColor(Printer, PDB_ColorItem::Type).get() << "VARIANT";
+ break;
+ case PDB_BuiltinType::Complex:
+ WithColor(Printer, PDB_ColorItem::Type).get() << "complex";
+ break;
+ case PDB_BuiltinType::Bitfield:
+ WithColor(Printer, PDB_ColorItem::Type).get() << "bitfield";
+ break;
+ case PDB_BuiltinType::BSTR:
+ WithColor(Printer, PDB_ColorItem::Type).get() << "BSTR";
+ break;
+ case PDB_BuiltinType::HResult:
+ WithColor(Printer, PDB_ColorItem::Type).get() << "HRESULT";
+ break;
+ case PDB_BuiltinType::BCD:
+ WithColor(Printer, PDB_ColorItem::Type).get() << "HRESULT";
+ break;
+ default:
+ WithColor(Printer, PDB_ColorItem::Type).get() << "void";
+ break;
+ }
+}
diff --git a/contrib/llvm/tools/llvm-pdbdump/BuiltinDumper.h b/contrib/llvm/tools/llvm-pdbdump/BuiltinDumper.h
new file mode 100644
index 0000000..8cf984a0
--- /dev/null
+++ b/contrib/llvm/tools/llvm-pdbdump/BuiltinDumper.h
@@ -0,0 +1,30 @@
+//===- BuiltinDumper.h ---------------------------------------- *- C++ --*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVMPDBDUMP_BUILTINDUMPER_H
+#define LLVM_TOOLS_LLVMPDBDUMP_BUILTINDUMPER_H
+
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+
+namespace llvm {
+
+class LinePrinter;
+
+class BuiltinDumper : public PDBSymDumper {
+public:
+ BuiltinDumper(LinePrinter &P);
+
+ void start(const PDBSymbolTypeBuiltin &Symbol);
+
+private:
+ LinePrinter &Printer;
+};
+}
+
+#endif
diff --git a/contrib/llvm/tools/llvm-pdbdump/ClassDefinitionDumper.cpp b/contrib/llvm/tools/llvm-pdbdump/ClassDefinitionDumper.cpp
new file mode 100644
index 0000000..8abf3fa
--- /dev/null
+++ b/contrib/llvm/tools/llvm-pdbdump/ClassDefinitionDumper.cpp
@@ -0,0 +1,190 @@
+//===- ClassDefinitionDumper.cpp --------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClassDefinitionDumper.h"
+#include "EnumDumper.h"
+#include "FunctionDumper.h"
+#include "LinePrinter.h"
+#include "llvm-pdbdump.h"
+#include "TypedefDumper.h"
+#include "VariableDumper.h"
+
+#include "llvm/DebugInfo/PDB/IPDBSession.h"
+#include "llvm/DebugInfo/PDB/PDBExtras.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolData.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolFunc.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypePointer.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h"
+#include "llvm/Support/Format.h"
+
+using namespace llvm;
+
+ClassDefinitionDumper::ClassDefinitionDumper(LinePrinter &P)
+ : PDBSymDumper(true), Printer(P) {}
+
+void ClassDefinitionDumper::start(const PDBSymbolTypeUDT &Class) {
+ std::string Name = Class.getName();
+ WithColor(Printer, PDB_ColorItem::Keyword).get() << Class.getUdtKind() << " ";
+ WithColor(Printer, PDB_ColorItem::Type).get() << Class.getName();
+
+ auto Bases = Class.findAllChildren<PDBSymbolTypeBaseClass>();
+ if (Bases->getChildCount() > 0) {
+ Printer.Indent();
+ Printer.NewLine();
+ Printer << ":";
+ uint32_t BaseIndex = 0;
+ while (auto Base = Bases->getNext()) {
+ Printer << " ";
+ WithColor(Printer, PDB_ColorItem::Keyword).get() << Base->getAccess();
+ if (Base->isVirtualBaseClass())
+ WithColor(Printer, PDB_ColorItem::Keyword).get() << " virtual";
+ WithColor(Printer, PDB_ColorItem::Type).get() << " " << Base->getName();
+ if (++BaseIndex < Bases->getChildCount()) {
+ Printer.NewLine();
+ Printer << ",";
+ }
+ }
+ Printer.Unindent();
+ }
+
+ Printer << " {";
+ auto Children = Class.findAllChildren();
+ if (Children->getChildCount() == 0) {
+ Printer << "}";
+ return;
+ }
+
+ // Try to dump symbols organized by member access level. Public members
+ // first, then protected, then private. This might be slow, so it's worth
+ // reconsidering the value of this if performance of large PDBs is a problem.
+ // NOTE: Access level of nested types is not recorded in the PDB, so we have
+ // a special case for them.
+ SymbolGroupByAccess Groups;
+ Groups.insert(std::make_pair(0, SymbolGroup()));
+ Groups.insert(std::make_pair((int)PDB_MemberAccess::Private, SymbolGroup()));
+ Groups.insert(
+ std::make_pair((int)PDB_MemberAccess::Protected, SymbolGroup()));
+ Groups.insert(std::make_pair((int)PDB_MemberAccess::Public, SymbolGroup()));
+
+ while (auto Child = Children->getNext()) {
+ PDB_MemberAccess Access = Child->getRawSymbol().getAccess();
+ if (isa<PDBSymbolTypeBaseClass>(*Child))
+ continue;
+
+ auto &AccessGroup = Groups.find((int)Access)->second;
+
+ if (auto Func = dyn_cast<PDBSymbolFunc>(Child.get())) {
+ if (Func->isCompilerGenerated() && opts::ExcludeCompilerGenerated)
+ continue;
+ if (Func->getLength() == 0 && !Func->isPureVirtual() &&
+ !Func->isIntroVirtualFunction())
+ continue;
+ Child.release();
+ AccessGroup.Functions.push_back(std::unique_ptr<PDBSymbolFunc>(Func));
+ } else if (auto Data = dyn_cast<PDBSymbolData>(Child.get())) {
+ Child.release();
+ AccessGroup.Data.push_back(std::unique_ptr<PDBSymbolData>(Data));
+ } else {
+ AccessGroup.Unknown.push_back(std::move(Child));
+ }
+ }
+
+ int Count = 0;
+ Count += dumpAccessGroup((PDB_MemberAccess)0, Groups[0]);
+ Count += dumpAccessGroup(PDB_MemberAccess::Public,
+ Groups[(int)PDB_MemberAccess::Public]);
+ Count += dumpAccessGroup(PDB_MemberAccess::Protected,
+ Groups[(int)PDB_MemberAccess::Protected]);
+ Count += dumpAccessGroup(PDB_MemberAccess::Private,
+ Groups[(int)PDB_MemberAccess::Private]);
+ if (Count > 0)
+ Printer.NewLine();
+ Printer << "}";
+}
+
+int ClassDefinitionDumper::dumpAccessGroup(PDB_MemberAccess Access,
+ const SymbolGroup &Group) {
+ if (Group.Functions.empty() && Group.Data.empty() && Group.Unknown.empty())
+ return 0;
+
+ int Count = 0;
+ if (Access == PDB_MemberAccess::Private) {
+ Printer.NewLine();
+ WithColor(Printer, PDB_ColorItem::Keyword).get() << "private";
+ Printer << ":";
+ } else if (Access == PDB_MemberAccess::Protected) {
+ Printer.NewLine();
+ WithColor(Printer, PDB_ColorItem::Keyword).get() << "protected";
+ Printer << ":";
+ } else if (Access == PDB_MemberAccess::Public) {
+ Printer.NewLine();
+ WithColor(Printer, PDB_ColorItem::Keyword).get() << "public";
+ Printer << ":";
+ }
+ Printer.Indent();
+ for (auto iter = Group.Functions.begin(), end = Group.Functions.end();
+ iter != end; ++iter) {
+ ++Count;
+ (*iter)->dump(*this);
+ }
+ for (auto iter = Group.Data.begin(), end = Group.Data.end(); iter != end;
+ ++iter) {
+ ++Count;
+ (*iter)->dump(*this);
+ }
+ for (auto iter = Group.Unknown.begin(), end = Group.Unknown.end();
+ iter != end; ++iter) {
+ ++Count;
+ (*iter)->dump(*this);
+ }
+ Printer.Unindent();
+ return Count;
+}
+
+void ClassDefinitionDumper::dump(const PDBSymbolTypeBaseClass &Symbol) {}
+
+void ClassDefinitionDumper::dump(const PDBSymbolData &Symbol) {
+ VariableDumper Dumper(Printer);
+ Dumper.start(Symbol);
+}
+
+void ClassDefinitionDumper::dump(const PDBSymbolFunc &Symbol) {
+ if (Printer.IsSymbolExcluded(Symbol.getName()))
+ return;
+
+ Printer.NewLine();
+ FunctionDumper Dumper(Printer);
+ Dumper.start(Symbol, FunctionDumper::PointerType::None);
+}
+
+void ClassDefinitionDumper::dump(const PDBSymbolTypeVTable &Symbol) {}
+
+void ClassDefinitionDumper::dump(const PDBSymbolTypeEnum &Symbol) {
+ if (Printer.IsTypeExcluded(Symbol.getName()))
+ return;
+
+ Printer.NewLine();
+ EnumDumper Dumper(Printer);
+ Dumper.start(Symbol);
+}
+
+void ClassDefinitionDumper::dump(const PDBSymbolTypeTypedef &Symbol) {
+ if (Printer.IsTypeExcluded(Symbol.getName()))
+ return;
+
+ Printer.NewLine();
+ TypedefDumper Dumper(Printer);
+ Dumper.start(Symbol);
+}
+
+void ClassDefinitionDumper::dump(const PDBSymbolTypeUDT &Symbol) {}
diff --git a/contrib/llvm/tools/llvm-pdbdump/ClassDefinitionDumper.h b/contrib/llvm/tools/llvm-pdbdump/ClassDefinitionDumper.h
new file mode 100644
index 0000000..5b48ba8
--- /dev/null
+++ b/contrib/llvm/tools/llvm-pdbdump/ClassDefinitionDumper.h
@@ -0,0 +1,62 @@
+//===- ClassDefinitionDumper.h - --------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVMPDBDUMP_CLASSDEFINITIONDUMPER_H
+#define LLVM_TOOLS_LLVMPDBDUMP_CLASSDEFINITIONDUMPER_H
+
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolFunc.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolData.h"
+
+#include <list>
+#include <memory>
+#include <unordered_map>
+
+namespace llvm {
+
+class LinePrinter;
+
+class ClassDefinitionDumper : public PDBSymDumper {
+public:
+ ClassDefinitionDumper(LinePrinter &P);
+
+ void start(const PDBSymbolTypeUDT &Exe);
+
+ void dump(const PDBSymbolTypeBaseClass &Symbol) override;
+ void dump(const PDBSymbolData &Symbol) override;
+ void dump(const PDBSymbolTypeEnum &Symbol) override;
+ void dump(const PDBSymbolFunc &Symbol) override;
+ void dump(const PDBSymbolTypeTypedef &Symbol) override;
+ void dump(const PDBSymbolTypeUDT &Symbol) override;
+ void dump(const PDBSymbolTypeVTable &Symbol) override;
+
+private:
+ LinePrinter &Printer;
+
+ struct SymbolGroup {
+ SymbolGroup() {}
+ SymbolGroup(SymbolGroup &&Other) {
+ Functions = std::move(Other.Functions);
+ Data = std::move(Other.Data);
+ Unknown = std::move(Other.Unknown);
+ }
+
+ std::list<std::unique_ptr<PDBSymbolFunc>> Functions;
+ std::list<std::unique_ptr<PDBSymbolData>> Data;
+ std::list<std::unique_ptr<PDBSymbol>> Unknown;
+ SymbolGroup(const SymbolGroup &other) = delete;
+ SymbolGroup &operator=(const SymbolGroup &other) = delete;
+ };
+ typedef std::unordered_map<int, SymbolGroup> SymbolGroupByAccess;
+
+ int dumpAccessGroup(PDB_MemberAccess Access, const SymbolGroup &Group);
+};
+}
+
+#endif
diff --git a/contrib/llvm/tools/llvm-pdbdump/CompilandDumper.cpp b/contrib/llvm/tools/llvm-pdbdump/CompilandDumper.cpp
new file mode 100644
index 0000000..68ceb62
--- /dev/null
+++ b/contrib/llvm/tools/llvm-pdbdump/CompilandDumper.cpp
@@ -0,0 +1,140 @@
+//===- CompilandDumper.cpp - llvm-pdbdump compiland symbol dumper *- C++ *-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CompilandDumper.h"
+#include "LinePrinter.h"
+#include "llvm-pdbdump.h"
+
+#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
+#include "llvm/DebugInfo/PDB/IPDBSession.h"
+#include "llvm/DebugInfo/PDB/PDBExtras.h"
+#include "llvm/DebugInfo/PDB/PDBSymbol.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolData.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolFunc.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolFuncDebugEnd.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolFuncDebugStart.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolLabel.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolThunk.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolUnknown.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/raw_ostream.h"
+
+#include "FunctionDumper.h"
+
+#include <utility>
+#include <vector>
+
+using namespace llvm;
+
+CompilandDumper::CompilandDumper(LinePrinter &P)
+ : PDBSymDumper(true), Printer(P) {}
+
+void CompilandDumper::dump(const PDBSymbolCompilandDetails &Symbol) {}
+
+void CompilandDumper::dump(const PDBSymbolCompilandEnv &Symbol) {}
+
+void CompilandDumper::start(const PDBSymbolCompiland &Symbol, bool Children) {
+ std::string FullName = Symbol.getName();
+ if (Printer.IsCompilandExcluded(FullName))
+ return;
+
+ Printer.NewLine();
+ WithColor(Printer, PDB_ColorItem::Path).get() << FullName;
+ if (!Children)
+ return;
+
+ auto ChildrenEnum = Symbol.findAllChildren();
+ Printer.Indent();
+ while (auto Child = ChildrenEnum->getNext())
+ Child->dump(*this);
+ Printer.Unindent();
+}
+
+void CompilandDumper::dump(const PDBSymbolData &Symbol) {
+ if (Printer.IsSymbolExcluded(Symbol.getName()))
+ return;
+
+ Printer.NewLine();
+
+ switch (auto LocType = Symbol.getLocationType()) {
+ case PDB_LocType::Static:
+ Printer << "data: ";
+ WithColor(Printer, PDB_ColorItem::Address).get()
+ << "[" << format_hex(Symbol.getVirtualAddress(), 10) << "]";
+ break;
+ case PDB_LocType::Constant:
+ Printer << "constant: ";
+ WithColor(Printer, PDB_ColorItem::LiteralValue).get()
+ << "[" << Symbol.getValue() << "]";
+ break;
+ default:
+ Printer << "data(unexpected type=" << LocType << ")";
+ }
+
+ Printer << " ";
+ WithColor(Printer, PDB_ColorItem::Identifier).get() << Symbol.getName();
+}
+
+void CompilandDumper::dump(const PDBSymbolFunc &Symbol) {
+ if (Symbol.getLength() == 0)
+ return;
+ if (Printer.IsSymbolExcluded(Symbol.getName()))
+ return;
+
+ Printer.NewLine();
+ FunctionDumper Dumper(Printer);
+ Dumper.start(Symbol, FunctionDumper::PointerType::None);
+}
+
+void CompilandDumper::dump(const PDBSymbolLabel &Symbol) {
+ if (Printer.IsSymbolExcluded(Symbol.getName()))
+ return;
+
+ Printer.NewLine();
+ Printer << "label ";
+ WithColor(Printer, PDB_ColorItem::Address).get()
+ << "[" << format_hex(Symbol.getVirtualAddress(), 10) << "] ";
+ WithColor(Printer, PDB_ColorItem::Identifier).get() << Symbol.getName();
+}
+
+void CompilandDumper::dump(const PDBSymbolThunk &Symbol) {
+ if (Printer.IsSymbolExcluded(Symbol.getName()))
+ return;
+
+ Printer.NewLine();
+ Printer << "thunk ";
+ PDB_ThunkOrdinal Ordinal = Symbol.getThunkOrdinal();
+ uint64_t VA = Symbol.getVirtualAddress();
+ if (Ordinal == PDB_ThunkOrdinal::TrampIncremental) {
+ uint64_t Target = Symbol.getTargetVirtualAddress();
+ WithColor(Printer, PDB_ColorItem::Address).get() << format_hex(VA, 10);
+ Printer << " -> ";
+ WithColor(Printer, PDB_ColorItem::Address).get() << format_hex(Target, 10);
+ } else {
+ WithColor(Printer, PDB_ColorItem::Address).get()
+ << "[" << format_hex(VA, 10) << " - "
+ << format_hex(VA + Symbol.getLength(), 10) << "]";
+ }
+ Printer << " (";
+ WithColor(Printer, PDB_ColorItem::Register).get() << Ordinal;
+ Printer << ") ";
+ std::string Name = Symbol.getName();
+ if (!Name.empty())
+ WithColor(Printer, PDB_ColorItem::Identifier).get() << Name;
+}
+
+void CompilandDumper::dump(const PDBSymbolTypeTypedef &Symbol) {}
+
+void CompilandDumper::dump(const PDBSymbolUnknown &Symbol) {
+ Printer.NewLine();
+ Printer << "unknown (" << Symbol.getSymTag() << ")";
+}
diff --git a/contrib/llvm/tools/llvm-pdbdump/CompilandDumper.h b/contrib/llvm/tools/llvm-pdbdump/CompilandDumper.h
new file mode 100644
index 0000000..0d1d27c
--- /dev/null
+++ b/contrib/llvm/tools/llvm-pdbdump/CompilandDumper.h
@@ -0,0 +1,39 @@
+//===- CompilandDumper.h - llvm-pdbdump compiland symbol dumper *- C++ --*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVMPDBDUMP_COMPILANDDUMPER_H
+#define LLVM_TOOLS_LLVMPDBDUMP_COMPILANDDUMPER_H
+
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+
+namespace llvm {
+
+class LinePrinter;
+
+class CompilandDumper : public PDBSymDumper {
+public:
+ CompilandDumper(LinePrinter &P);
+
+ void start(const PDBSymbolCompiland &Symbol, bool Children);
+
+ void dump(const PDBSymbolCompilandDetails &Symbol) override;
+ void dump(const PDBSymbolCompilandEnv &Symbol) override;
+ void dump(const PDBSymbolData &Symbol) override;
+ void dump(const PDBSymbolFunc &Symbol) override;
+ void dump(const PDBSymbolLabel &Symbol) override;
+ void dump(const PDBSymbolThunk &Symbol) override;
+ void dump(const PDBSymbolTypeTypedef &Symbol) override;
+ void dump(const PDBSymbolUnknown &Symbol) override;
+
+private:
+ LinePrinter &Printer;
+};
+}
+
+#endif
diff --git a/contrib/llvm/tools/llvm-pdbdump/EnumDumper.cpp b/contrib/llvm/tools/llvm-pdbdump/EnumDumper.cpp
new file mode 100644
index 0000000..3514c39
--- /dev/null
+++ b/contrib/llvm/tools/llvm-pdbdump/EnumDumper.cpp
@@ -0,0 +1,52 @@
+//===- EnumDumper.cpp -------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "EnumDumper.h"
+
+#include "BuiltinDumper.h"
+#include "LinePrinter.h"
+#include "llvm-pdbdump.h"
+
+#include "llvm/DebugInfo/PDB/PDBSymbolData.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
+
+using namespace llvm;
+
+EnumDumper::EnumDumper(LinePrinter &P) : PDBSymDumper(true), Printer(P) {}
+
+void EnumDumper::start(const PDBSymbolTypeEnum &Symbol) {
+ WithColor(Printer, PDB_ColorItem::Keyword).get() << "enum ";
+ WithColor(Printer, PDB_ColorItem::Type).get() << Symbol.getName();
+ if (!opts::NoEnumDefs) {
+ auto BuiltinType = Symbol.getUnderlyingType();
+ if (BuiltinType->getBuiltinType() != PDB_BuiltinType::Int ||
+ BuiltinType->getLength() != 4) {
+ Printer << " : ";
+ BuiltinDumper Dumper(Printer);
+ Dumper.start(*BuiltinType);
+ }
+ Printer << " {";
+ Printer.Indent();
+ auto EnumValues = Symbol.findAllChildren<PDBSymbolData>();
+ while (auto EnumValue = EnumValues->getNext()) {
+ if (EnumValue->getDataKind() != PDB_DataKind::Constant)
+ continue;
+ Printer.NewLine();
+ WithColor(Printer, PDB_ColorItem::Identifier).get()
+ << EnumValue->getName();
+ Printer << " = ";
+ WithColor(Printer, PDB_ColorItem::LiteralValue).get()
+ << EnumValue->getValue();
+ }
+ Printer.Unindent();
+ Printer.NewLine();
+ Printer << "}";
+ }
+}
diff --git a/contrib/llvm/tools/llvm-pdbdump/EnumDumper.h b/contrib/llvm/tools/llvm-pdbdump/EnumDumper.h
new file mode 100644
index 0000000..23de061
--- /dev/null
+++ b/contrib/llvm/tools/llvm-pdbdump/EnumDumper.h
@@ -0,0 +1,30 @@
+//===- EnumDumper.h - -------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVMPDBDUMP_ENUMDUMPER_H
+#define LLVM_TOOLS_LLVMPDBDUMP_ENUMDUMPER_H
+
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+
+namespace llvm {
+
+class LinePrinter;
+
+class EnumDumper : public PDBSymDumper {
+public:
+ EnumDumper(LinePrinter &P);
+
+ void start(const PDBSymbolTypeEnum &Symbol);
+
+private:
+ LinePrinter &Printer;
+};
+}
+
+#endif
diff --git a/contrib/llvm/tools/llvm-pdbdump/ExternalSymbolDumper.cpp b/contrib/llvm/tools/llvm-pdbdump/ExternalSymbolDumper.cpp
new file mode 100644
index 0000000..c4e9f47
--- /dev/null
+++ b/contrib/llvm/tools/llvm-pdbdump/ExternalSymbolDumper.cpp
@@ -0,0 +1,40 @@
+//===- ExternalSymbolDumper.cpp -------------------------------- *- C++ *-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ExternalSymbolDumper.h"
+#include "LinePrinter.h"
+
+#include "llvm/DebugInfo/PDB/PDBSymbolExe.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolPublicSymbol.h"
+#include "llvm/Support/Format.h"
+
+using namespace llvm;
+
+ExternalSymbolDumper::ExternalSymbolDumper(LinePrinter &P)
+ : PDBSymDumper(true), Printer(P) {}
+
+void ExternalSymbolDumper::start(const PDBSymbolExe &Symbol) {
+ auto Vars = Symbol.findAllChildren<PDBSymbolPublicSymbol>();
+ while (auto Var = Vars->getNext())
+ Var->dump(*this);
+}
+
+void ExternalSymbolDumper::dump(const PDBSymbolPublicSymbol &Symbol) {
+ std::string LinkageName = Symbol.getName();
+ if (Printer.IsSymbolExcluded(LinkageName))
+ return;
+
+ Printer.NewLine();
+ uint64_t Addr = Symbol.getVirtualAddress();
+
+ Printer << "[";
+ WithColor(Printer, PDB_ColorItem::Address).get() << format_hex(Addr, 10);
+ Printer << "] ";
+ WithColor(Printer, PDB_ColorItem::Identifier).get() << LinkageName;
+}
diff --git a/contrib/llvm/tools/llvm-pdbdump/ExternalSymbolDumper.h b/contrib/llvm/tools/llvm-pdbdump/ExternalSymbolDumper.h
new file mode 100644
index 0000000..d77b09c
--- /dev/null
+++ b/contrib/llvm/tools/llvm-pdbdump/ExternalSymbolDumper.h
@@ -0,0 +1,32 @@
+//===- ExternalSymbolDumper.h --------------------------------- *- C++ --*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVMPDBDUMP_EXTERNALSYMBOLDUMPER_H
+#define LLVM_TOOLS_LLVMPDBDUMP_EXTERNALSYMBOLDUMPER_H
+
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+
+namespace llvm {
+
+class LinePrinter;
+
+class ExternalSymbolDumper : public PDBSymDumper {
+public:
+ ExternalSymbolDumper(LinePrinter &P);
+
+ void start(const PDBSymbolExe &Symbol);
+
+ void dump(const PDBSymbolPublicSymbol &Symbol) override;
+
+private:
+ LinePrinter &Printer;
+};
+}
+
+#endif
diff --git a/contrib/llvm/tools/llvm-pdbdump/FunctionDumper.cpp b/contrib/llvm/tools/llvm-pdbdump/FunctionDumper.cpp
new file mode 100644
index 0000000..9584812
--- /dev/null
+++ b/contrib/llvm/tools/llvm-pdbdump/FunctionDumper.cpp
@@ -0,0 +1,254 @@
+//===- FunctionDumper.cpp ------------------------------------ *- C++ *-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "FunctionDumper.h"
+#include "BuiltinDumper.h"
+#include "LinePrinter.h"
+#include "llvm-pdbdump.h"
+
+#include "llvm/DebugInfo/PDB/IPDBSession.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolData.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolFunc.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolFuncDebugEnd.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolFuncDebugStart.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeArray.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionArg.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypePointer.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"
+#include "llvm/Support/Format.h"
+
+using namespace llvm;
+
+namespace {
+template <class T>
+void dumpClassParentWithScopeOperator(const T &Symbol, LinePrinter &Printer,
+ llvm::FunctionDumper &Dumper) {
+ uint32_t ClassParentId = Symbol.getClassParentId();
+ auto ClassParent =
+ Symbol.getSession().template getConcreteSymbolById<PDBSymbolTypeUDT>(
+ ClassParentId);
+ if (!ClassParent)
+ return;
+
+ WithColor(Printer, PDB_ColorItem::Type).get() << ClassParent->getName();
+ Printer << "::";
+}
+}
+
+FunctionDumper::FunctionDumper(LinePrinter &P)
+ : PDBSymDumper(true), Printer(P) {}
+
+void FunctionDumper::start(const PDBSymbolTypeFunctionSig &Symbol,
+ const char *Name, PointerType Pointer) {
+ auto ReturnType = Symbol.getReturnType();
+ ReturnType->dump(*this);
+ Printer << " ";
+ uint32_t ClassParentId = Symbol.getClassParentId();
+ auto ClassParent =
+ Symbol.getSession().getConcreteSymbolById<PDBSymbolTypeUDT>(
+ ClassParentId);
+
+ PDB_CallingConv CC = Symbol.getCallingConvention();
+ bool ShouldDumpCallingConvention = true;
+ if ((ClassParent && CC == PDB_CallingConv::Thiscall) ||
+ (!ClassParent && CC == PDB_CallingConv::NearStdcall)) {
+ ShouldDumpCallingConvention = false;
+ }
+
+ if (Pointer == PointerType::None) {
+ if (ShouldDumpCallingConvention)
+ WithColor(Printer, PDB_ColorItem::Keyword).get() << CC << " ";
+ if (ClassParent) {
+ Printer << "(";
+ WithColor(Printer, PDB_ColorItem::Identifier).get()
+ << ClassParent->getName();
+ Printer << "::)";
+ }
+ } else {
+ Printer << "(";
+ if (ShouldDumpCallingConvention)
+ WithColor(Printer, PDB_ColorItem::Keyword).get() << CC << " ";
+ if (ClassParent) {
+ WithColor(Printer, PDB_ColorItem::Identifier).get()
+ << ClassParent->getName();
+ Printer << "::";
+ }
+ if (Pointer == PointerType::Reference)
+ Printer << "&";
+ else
+ Printer << "*";
+ if (Name)
+ WithColor(Printer, PDB_ColorItem::Identifier).get() << Name;
+ Printer << ")";
+ }
+
+ Printer << "(";
+ if (auto ChildEnum = Symbol.getArguments()) {
+ uint32_t Index = 0;
+ while (auto Arg = ChildEnum->getNext()) {
+ Arg->dump(*this);
+ if (++Index < ChildEnum->getChildCount())
+ Printer << ", ";
+ }
+ }
+ Printer << ")";
+
+ if (Symbol.isConstType())
+ WithColor(Printer, PDB_ColorItem::Keyword).get() << " const";
+ if (Symbol.isVolatileType())
+ WithColor(Printer, PDB_ColorItem::Keyword).get() << " volatile";
+}
+
+void FunctionDumper::start(const PDBSymbolFunc &Symbol, PointerType Pointer) {
+ uint64_t FuncStart = Symbol.getVirtualAddress();
+ uint64_t FuncEnd = FuncStart + Symbol.getLength();
+
+ Printer << "func [";
+ WithColor(Printer, PDB_ColorItem::Address).get() << format_hex(FuncStart, 10);
+ if (auto DebugStart = Symbol.findOneChild<PDBSymbolFuncDebugStart>()) {
+ uint64_t Prologue = DebugStart->getVirtualAddress() - FuncStart;
+ WithColor(Printer, PDB_ColorItem::Offset).get() << "+" << Prologue;
+ }
+ Printer << " - ";
+ WithColor(Printer, PDB_ColorItem::Address).get() << format_hex(FuncEnd, 10);
+ if (auto DebugEnd = Symbol.findOneChild<PDBSymbolFuncDebugEnd>()) {
+ uint64_t Epilogue = FuncEnd - DebugEnd->getVirtualAddress();
+ WithColor(Printer, PDB_ColorItem::Offset).get() << "-" << Epilogue;
+ }
+ Printer << "] (";
+
+ if (Symbol.hasFramePointer()) {
+ WithColor(Printer, PDB_ColorItem::Register).get()
+ << Symbol.getLocalBasePointerRegisterId();
+ } else {
+ WithColor(Printer, PDB_ColorItem::Register).get() << "FPO";
+ }
+ Printer << ") ";
+
+ if (Symbol.isVirtual() || Symbol.isPureVirtual())
+ WithColor(Printer, PDB_ColorItem::Keyword).get() << "virtual ";
+
+ auto Signature = Symbol.getSignature();
+ if (!Signature) {
+ WithColor(Printer, PDB_ColorItem::Identifier).get() << Symbol.getName();
+ if (Pointer == PointerType::Pointer)
+ Printer << "*";
+ else if (Pointer == FunctionDumper::PointerType::Reference)
+ Printer << "&";
+ return;
+ }
+
+ auto ReturnType = Signature->getReturnType();
+ ReturnType->dump(*this);
+ Printer << " ";
+
+ auto ClassParent = Symbol.getClassParent();
+ PDB_CallingConv CC = Signature->getCallingConvention();
+ if (Pointer != FunctionDumper::PointerType::None)
+ Printer << "(";
+
+ if ((ClassParent && CC != PDB_CallingConv::Thiscall) ||
+ (!ClassParent && CC != PDB_CallingConv::NearStdcall)) {
+ WithColor(Printer, PDB_ColorItem::Keyword).get()
+ << Signature->getCallingConvention() << " ";
+ }
+ WithColor(Printer, PDB_ColorItem::Identifier).get() << Symbol.getName();
+ if (Pointer != FunctionDumper::PointerType::None) {
+ if (Pointer == PointerType::Pointer)
+ Printer << "*";
+ else if (Pointer == FunctionDumper::PointerType::Reference)
+ Printer << "&";
+ Printer << ")";
+ }
+
+ Printer << "(";
+ if (auto Arguments = Symbol.getArguments()) {
+ uint32_t Index = 0;
+ while (auto Arg = Arguments->getNext()) {
+ auto ArgType = Arg->getType();
+ ArgType->dump(*this);
+ WithColor(Printer, PDB_ColorItem::Identifier).get() << " "
+ << Arg->getName();
+ if (++Index < Arguments->getChildCount())
+ Printer << ", ";
+ }
+ }
+ Printer << ")";
+ if (Symbol.isConstType())
+ WithColor(Printer, PDB_ColorItem::Keyword).get() << " const";
+ if (Symbol.isVolatileType())
+ WithColor(Printer, PDB_ColorItem::Keyword).get() << " volatile";
+ if (Symbol.isPureVirtual())
+ Printer << " = 0";
+}
+
+void FunctionDumper::dump(const PDBSymbolTypeArray &Symbol) {
+ uint32_t ElementTypeId = Symbol.getTypeId();
+ auto ElementType = Symbol.getSession().getSymbolById(ElementTypeId);
+ if (!ElementType)
+ return;
+
+ ElementType->dump(*this);
+ Printer << "[";
+ WithColor(Printer, PDB_ColorItem::LiteralValue).get() << Symbol.getLength();
+ Printer << "]";
+}
+
+void FunctionDumper::dump(const PDBSymbolTypeBuiltin &Symbol) {
+ BuiltinDumper Dumper(Printer);
+ Dumper.start(Symbol);
+}
+
+void FunctionDumper::dump(const PDBSymbolTypeEnum &Symbol) {
+ dumpClassParentWithScopeOperator(Symbol, Printer, *this);
+ WithColor(Printer, PDB_ColorItem::Type).get() << Symbol.getName();
+}
+
+void FunctionDumper::dump(const PDBSymbolTypeFunctionArg &Symbol) {
+ // PDBSymbolTypeFunctionArg is just a shim over the real argument. Just drill
+ // through to the real thing and dump it.
+ uint32_t TypeId = Symbol.getTypeId();
+ auto Type = Symbol.getSession().getSymbolById(TypeId);
+ if (!Type)
+ return;
+ Type->dump(*this);
+}
+
+void FunctionDumper::dump(const PDBSymbolTypeTypedef &Symbol) {
+ dumpClassParentWithScopeOperator(Symbol, Printer, *this);
+ WithColor(Printer, PDB_ColorItem::Type).get() << Symbol.getName();
+}
+
+void FunctionDumper::dump(const PDBSymbolTypePointer &Symbol) {
+ uint32_t PointeeId = Symbol.getTypeId();
+ auto PointeeType = Symbol.getSession().getSymbolById(PointeeId);
+ if (!PointeeType)
+ return;
+
+ if (auto FuncSig = dyn_cast<PDBSymbolTypeFunctionSig>(PointeeType.get())) {
+ FunctionDumper NestedDumper(Printer);
+ PointerType Pointer =
+ Symbol.isReference() ? PointerType::Reference : PointerType::Pointer;
+ NestedDumper.start(*FuncSig, nullptr, Pointer);
+ } else {
+ if (Symbol.isConstType())
+ WithColor(Printer, PDB_ColorItem::Keyword).get() << "const ";
+ if (Symbol.isVolatileType())
+ WithColor(Printer, PDB_ColorItem::Keyword).get() << "volatile ";
+ PointeeType->dump(*this);
+ Printer << (Symbol.isReference() ? "&" : "*");
+ }
+}
+
+void FunctionDumper::dump(const PDBSymbolTypeUDT &Symbol) {
+ WithColor(Printer, PDB_ColorItem::Type).get() << Symbol.getName();
+}
diff --git a/contrib/llvm/tools/llvm-pdbdump/FunctionDumper.h b/contrib/llvm/tools/llvm-pdbdump/FunctionDumper.h
new file mode 100644
index 0000000..19a0014
--- /dev/null
+++ b/contrib/llvm/tools/llvm-pdbdump/FunctionDumper.h
@@ -0,0 +1,42 @@
+//===- FunctionDumper.h --------------------------------------- *- C++ --*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVMPDBDUMP_FUNCTIONDUMPER_H
+#define LLVM_TOOLS_LLVMPDBDUMP_FUNCTIONDUMPER_H
+
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+
+namespace llvm {
+
+class LinePrinter;
+
+class FunctionDumper : public PDBSymDumper {
+public:
+ FunctionDumper(LinePrinter &P);
+
+ enum class PointerType { None, Pointer, Reference };
+
+ void start(const PDBSymbolTypeFunctionSig &Symbol, const char *Name,
+ PointerType Pointer);
+ void start(const PDBSymbolFunc &Symbol, PointerType Pointer);
+
+ void dump(const PDBSymbolTypeArray &Symbol) override;
+ void dump(const PDBSymbolTypeBuiltin &Symbol) override;
+ void dump(const PDBSymbolTypeEnum &Symbol) override;
+ void dump(const PDBSymbolTypeFunctionArg &Symbol) override;
+ void dump(const PDBSymbolTypePointer &Symbol) override;
+ void dump(const PDBSymbolTypeTypedef &Symbol) override;
+ void dump(const PDBSymbolTypeUDT &Symbol) override;
+
+private:
+ LinePrinter &Printer;
+};
+}
+
+#endif
diff --git a/contrib/llvm/tools/llvm-pdbdump/LinePrinter.cpp b/contrib/llvm/tools/llvm-pdbdump/LinePrinter.cpp
new file mode 100644
index 0000000..6bbc403
--- /dev/null
+++ b/contrib/llvm/tools/llvm-pdbdump/LinePrinter.cpp
@@ -0,0 +1,124 @@
+//===- LinePrinter.cpp ------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "LinePrinter.h"
+
+#include "llvm-pdbdump.h"
+
+#include "llvm/Support/Regex.h"
+
+#include <algorithm>
+
+using namespace llvm;
+
+LinePrinter::LinePrinter(int Indent, llvm::raw_ostream &Stream)
+ : OS(Stream), IndentSpaces(Indent), CurrentIndent(0) {
+ SetFilters(TypeFilters, opts::ExcludeTypes.begin(), opts::ExcludeTypes.end());
+ SetFilters(SymbolFilters, opts::ExcludeSymbols.begin(),
+ opts::ExcludeSymbols.end());
+ SetFilters(CompilandFilters, opts::ExcludeCompilands.begin(),
+ opts::ExcludeCompilands.end());
+}
+
+void LinePrinter::Indent() { CurrentIndent += IndentSpaces; }
+
+void LinePrinter::Unindent() {
+ CurrentIndent = std::max(0, CurrentIndent - IndentSpaces);
+}
+
+void LinePrinter::NewLine() {
+ OS << "\n";
+ OS.indent(CurrentIndent);
+}
+
+bool LinePrinter::IsTypeExcluded(llvm::StringRef TypeName) {
+ if (TypeName.empty())
+ return false;
+
+ for (auto &Expr : TypeFilters) {
+ if (Expr.match(TypeName))
+ return true;
+ }
+ return false;
+}
+
+bool LinePrinter::IsSymbolExcluded(llvm::StringRef SymbolName) {
+ if (SymbolName.empty())
+ return false;
+
+ for (auto &Expr : SymbolFilters) {
+ if (Expr.match(SymbolName))
+ return true;
+ }
+ return false;
+}
+
+bool LinePrinter::IsCompilandExcluded(llvm::StringRef CompilandName) {
+ if (CompilandName.empty())
+ return false;
+
+ for (auto &Expr : CompilandFilters) {
+ if (Expr.match(CompilandName))
+ return true;
+ }
+ return false;
+}
+
+WithColor::WithColor(LinePrinter &P, PDB_ColorItem C) : OS(P.OS) {
+ if (C == PDB_ColorItem::None)
+ OS.resetColor();
+ else {
+ raw_ostream::Colors Color;
+ bool Bold;
+ translateColor(C, Color, Bold);
+ OS.changeColor(Color, Bold);
+ }
+}
+
+WithColor::~WithColor() { OS.resetColor(); }
+
+void WithColor::translateColor(PDB_ColorItem C, raw_ostream::Colors &Color,
+ bool &Bold) const {
+ switch (C) {
+ case PDB_ColorItem::Address:
+ Color = raw_ostream::YELLOW;
+ Bold = true;
+ return;
+ case PDB_ColorItem::Keyword:
+ Color = raw_ostream::MAGENTA;
+ Bold = true;
+ return;
+ case PDB_ColorItem::Register:
+ case PDB_ColorItem::Offset:
+ Color = raw_ostream::YELLOW;
+ Bold = false;
+ return;
+ case PDB_ColorItem::Type:
+ Color = raw_ostream::CYAN;
+ Bold = true;
+ return;
+ case PDB_ColorItem::Identifier:
+ Color = raw_ostream::CYAN;
+ Bold = false;
+ return;
+ case PDB_ColorItem::Path:
+ Color = raw_ostream::CYAN;
+ Bold = false;
+ return;
+ case PDB_ColorItem::SectionHeader:
+ Color = raw_ostream::RED;
+ Bold = true;
+ return;
+ case PDB_ColorItem::LiteralValue:
+ Color = raw_ostream::GREEN;
+ Bold = true;
+ default:
+ return;
+ }
+}
diff --git a/contrib/llvm/tools/llvm-pdbdump/LinePrinter.h b/contrib/llvm/tools/llvm-pdbdump/LinePrinter.h
new file mode 100644
index 0000000..c2a3ab6
--- /dev/null
+++ b/contrib/llvm/tools/llvm-pdbdump/LinePrinter.h
@@ -0,0 +1,89 @@
+//===- LinePrinter.h ------------------------------------------ *- C++ --*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVMPDBDUMP_LINEPRINTER_H
+#define LLVM_TOOLS_LLVMPDBDUMP_LINEPRINTER_H
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/Regex.h"
+
+#include <list>
+
+namespace llvm {
+
+class LinePrinter {
+ friend class WithColor;
+
+public:
+ LinePrinter(int Indent, raw_ostream &Stream);
+
+ void Indent();
+ void Unindent();
+ void NewLine();
+
+ raw_ostream &getStream() { return OS; }
+ int getIndentLevel() const { return CurrentIndent; }
+
+ bool IsTypeExcluded(llvm::StringRef TypeName);
+ bool IsSymbolExcluded(llvm::StringRef SymbolName);
+ bool IsCompilandExcluded(llvm::StringRef CompilandName);
+
+private:
+ template <typename Iter>
+ void SetFilters(std::list<Regex> &List, Iter Begin, Iter End) {
+ List.clear();
+ for (; Begin != End; ++Begin)
+ List.push_back(StringRef(*Begin));
+ }
+
+ raw_ostream &OS;
+ int IndentSpaces;
+ int CurrentIndent;
+
+ std::list<Regex> CompilandFilters;
+ std::list<Regex> TypeFilters;
+ std::list<Regex> SymbolFilters;
+};
+
+template <class T>
+inline raw_ostream &operator<<(LinePrinter &Printer, const T &Item) {
+ Printer.getStream() << Item;
+ return Printer.getStream();
+}
+
+enum class PDB_ColorItem {
+ None,
+ Address,
+ Type,
+ Keyword,
+ Offset,
+ Identifier,
+ Path,
+ SectionHeader,
+ LiteralValue,
+ Register,
+};
+
+class WithColor {
+public:
+ WithColor(LinePrinter &P, PDB_ColorItem C);
+ ~WithColor();
+
+ raw_ostream &get() { return OS; }
+
+private:
+ void translateColor(PDB_ColorItem C, raw_ostream::Colors &Color,
+ bool &Bold) const;
+ raw_ostream &OS;
+};
+}
+
+#endif
diff --git a/contrib/llvm/tools/llvm-pdbdump/TypeDumper.cpp b/contrib/llvm/tools/llvm-pdbdump/TypeDumper.cpp
new file mode 100644
index 0000000..88c0bd6
--- /dev/null
+++ b/contrib/llvm/tools/llvm-pdbdump/TypeDumper.cpp
@@ -0,0 +1,97 @@
+//===- TypeDumper.cpp - PDBSymDumper implementation for types *----- C++ *-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "TypeDumper.h"
+
+#include "BuiltinDumper.h"
+#include "ClassDefinitionDumper.h"
+#include "EnumDumper.h"
+#include "LinePrinter.h"
+#include "llvm-pdbdump.h"
+#include "TypedefDumper.h"
+
+#include "llvm/DebugInfo/PDB/IPDBSession.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolExe.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"
+
+using namespace llvm;
+
+TypeDumper::TypeDumper(LinePrinter &P) : PDBSymDumper(true), Printer(P) {}
+
+void TypeDumper::start(const PDBSymbolExe &Exe) {
+ auto Enums = Exe.findAllChildren<PDBSymbolTypeEnum>();
+ Printer.NewLine();
+ WithColor(Printer, PDB_ColorItem::Identifier).get() << "Enums";
+ Printer << ": (" << Enums->getChildCount() << " items)";
+ Printer.Indent();
+ while (auto Enum = Enums->getNext())
+ Enum->dump(*this);
+ Printer.Unindent();
+
+ auto Typedefs = Exe.findAllChildren<PDBSymbolTypeTypedef>();
+ Printer.NewLine();
+ WithColor(Printer, PDB_ColorItem::Identifier).get() << "Typedefs";
+ Printer << ": (" << Typedefs->getChildCount() << " items)";
+ Printer.Indent();
+ while (auto Typedef = Typedefs->getNext())
+ Typedef->dump(*this);
+ Printer.Unindent();
+
+ auto Classes = Exe.findAllChildren<PDBSymbolTypeUDT>();
+ Printer.NewLine();
+ WithColor(Printer, PDB_ColorItem::Identifier).get() << "Classes";
+ Printer << ": (" << Classes->getChildCount() << " items)";
+ Printer.Indent();
+ while (auto Class = Classes->getNext())
+ Class->dump(*this);
+ Printer.Unindent();
+}
+
+void TypeDumper::dump(const PDBSymbolTypeEnum &Symbol) {
+ if (Symbol.getUnmodifiedTypeId() != 0)
+ return;
+ if (Printer.IsTypeExcluded(Symbol.getName()))
+ return;
+ // Dump member enums when dumping their class definition.
+ if (Symbol.isNested())
+ return;
+
+ Printer.NewLine();
+ EnumDumper Dumper(Printer);
+ Dumper.start(Symbol);
+}
+
+void TypeDumper::dump(const PDBSymbolTypeTypedef &Symbol) {
+ if (Printer.IsTypeExcluded(Symbol.getName()))
+ return;
+
+ Printer.NewLine();
+ TypedefDumper Dumper(Printer);
+ Dumper.start(Symbol);
+}
+
+void TypeDumper::dump(const PDBSymbolTypeUDT &Symbol) {
+ if (Symbol.getUnmodifiedTypeId() != 0)
+ return;
+ if (Printer.IsTypeExcluded(Symbol.getName()))
+ return;
+
+ Printer.NewLine();
+
+ if (opts::NoClassDefs) {
+ WithColor(Printer, PDB_ColorItem::Keyword).get() << "class ";
+ WithColor(Printer, PDB_ColorItem::Identifier).get() << Symbol.getName();
+ } else {
+ ClassDefinitionDumper Dumper(Printer);
+ Dumper.start(Symbol);
+ }
+}
diff --git a/contrib/llvm/tools/llvm-pdbdump/TypeDumper.h b/contrib/llvm/tools/llvm-pdbdump/TypeDumper.h
new file mode 100644
index 0000000..5c0832e
--- /dev/null
+++ b/contrib/llvm/tools/llvm-pdbdump/TypeDumper.h
@@ -0,0 +1,34 @@
+//===- TypeDumper.h - PDBSymDumper implementation for types *- C++ ------*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVMPDBDUMP_TYPEDUMPER_H
+#define LLVM_TOOLS_LLVMPDBDUMP_TYPEDUMPER_H
+
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+
+namespace llvm {
+
+class LinePrinter;
+
+class TypeDumper : public PDBSymDumper {
+public:
+ TypeDumper(LinePrinter &P);
+
+ void start(const PDBSymbolExe &Exe);
+
+ void dump(const PDBSymbolTypeEnum &Symbol) override;
+ void dump(const PDBSymbolTypeTypedef &Symbol) override;
+ void dump(const PDBSymbolTypeUDT &Symbol) override;
+
+private:
+ LinePrinter &Printer;
+};
+}
+
+#endif
diff --git a/contrib/llvm/tools/llvm-pdbdump/TypedefDumper.cpp b/contrib/llvm/tools/llvm-pdbdump/TypedefDumper.cpp
new file mode 100644
index 0000000..a6b5c53
--- /dev/null
+++ b/contrib/llvm/tools/llvm-pdbdump/TypedefDumper.cpp
@@ -0,0 +1,79 @@
+//===- TypedefDumper.cpp - PDBSymDumper impl for typedefs -------- * C++ *-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "TypedefDumper.h"
+
+#include "BuiltinDumper.h"
+#include "FunctionDumper.h"
+#include "LinePrinter.h"
+#include "llvm-pdbdump.h"
+
+#include "llvm/DebugInfo/PDB/IPDBSession.h"
+#include "llvm/DebugInfo/PDB/PDBExtras.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypePointer.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"
+
+using namespace llvm;
+
+TypedefDumper::TypedefDumper(LinePrinter &P) : PDBSymDumper(true), Printer(P) {}
+
+void TypedefDumper::start(const PDBSymbolTypeTypedef &Symbol) {
+ WithColor(Printer, PDB_ColorItem::Keyword).get() << "typedef ";
+ uint32_t TargetId = Symbol.getTypeId();
+ if (auto TypeSymbol = Symbol.getSession().getSymbolById(TargetId))
+ TypeSymbol->dump(*this);
+ WithColor(Printer, PDB_ColorItem::Identifier).get() << " "
+ << Symbol.getName();
+}
+
+void TypedefDumper::dump(const PDBSymbolTypeArray &Symbol) {}
+
+void TypedefDumper::dump(const PDBSymbolTypeBuiltin &Symbol) {
+ BuiltinDumper Dumper(Printer);
+ Dumper.start(Symbol);
+}
+
+void TypedefDumper::dump(const PDBSymbolTypeEnum &Symbol) {
+ WithColor(Printer, PDB_ColorItem::Keyword).get() << "enum ";
+ WithColor(Printer, PDB_ColorItem::Type).get() << " " << Symbol.getName();
+}
+
+void TypedefDumper::dump(const PDBSymbolTypePointer &Symbol) {
+ if (Symbol.isConstType())
+ WithColor(Printer, PDB_ColorItem::Keyword).get() << "const ";
+ if (Symbol.isVolatileType())
+ WithColor(Printer, PDB_ColorItem::Keyword).get() << "volatile ";
+ uint32_t PointeeId = Symbol.getTypeId();
+ auto PointeeType = Symbol.getSession().getSymbolById(PointeeId);
+ if (!PointeeType)
+ return;
+ if (auto FuncSig = dyn_cast<PDBSymbolTypeFunctionSig>(PointeeType.get())) {
+ FunctionDumper::PointerType Pointer = FunctionDumper::PointerType::Pointer;
+ if (Symbol.isReference())
+ Pointer = FunctionDumper::PointerType::Reference;
+ FunctionDumper NestedDumper(Printer);
+ NestedDumper.start(*FuncSig, nullptr, Pointer);
+ } else {
+ PointeeType->dump(*this);
+ Printer << ((Symbol.isReference()) ? "&" : "*");
+ }
+}
+
+void TypedefDumper::dump(const PDBSymbolTypeFunctionSig &Symbol) {
+ FunctionDumper Dumper(Printer);
+ Dumper.start(Symbol, nullptr, FunctionDumper::PointerType::None);
+}
+
+void TypedefDumper::dump(const PDBSymbolTypeUDT &Symbol) {
+ WithColor(Printer, PDB_ColorItem::Keyword).get() << "class ";
+ WithColor(Printer, PDB_ColorItem::Type).get() << Symbol.getName();
+}
diff --git a/contrib/llvm/tools/llvm-pdbdump/TypedefDumper.h b/contrib/llvm/tools/llvm-pdbdump/TypedefDumper.h
new file mode 100644
index 0000000..8cd578c
--- /dev/null
+++ b/contrib/llvm/tools/llvm-pdbdump/TypedefDumper.h
@@ -0,0 +1,37 @@
+//===- TypedefDumper.h - llvm-pdbdump typedef dumper ---------*- C++ ----*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVMPDBDUMP_TYPEDEFDUMPER_H
+#define LLVM_TOOLS_LLVMPDBDUMP_TYPEDEFDUMPER_H
+
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+
+namespace llvm {
+
+class LinePrinter;
+
+class TypedefDumper : public PDBSymDumper {
+public:
+ TypedefDumper(LinePrinter &P);
+
+ void start(const PDBSymbolTypeTypedef &Symbol);
+
+ void dump(const PDBSymbolTypeArray &Symbol) override;
+ void dump(const PDBSymbolTypeBuiltin &Symbol) override;
+ void dump(const PDBSymbolTypeEnum &Symbol) override;
+ void dump(const PDBSymbolTypeFunctionSig &Symbol) override;
+ void dump(const PDBSymbolTypePointer &Symbol) override;
+ void dump(const PDBSymbolTypeUDT &Symbol) override;
+
+private:
+ LinePrinter &Printer;
+};
+}
+
+#endif
diff --git a/contrib/llvm/tools/llvm-pdbdump/VariableDumper.cpp b/contrib/llvm/tools/llvm-pdbdump/VariableDumper.cpp
new file mode 100644
index 0000000..e5665b5
--- /dev/null
+++ b/contrib/llvm/tools/llvm-pdbdump/VariableDumper.cpp
@@ -0,0 +1,170 @@
+//===- VariableDumper.cpp - -------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "VariableDumper.h"
+
+#include "BuiltinDumper.h"
+#include "LinePrinter.h"
+#include "llvm-pdbdump.h"
+#include "FunctionDumper.h"
+
+#include "llvm/DebugInfo/PDB/PDBSymbolData.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolFunc.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeArray.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypePointer.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"
+
+#include "llvm/Support/Format.h"
+
+using namespace llvm;
+
+VariableDumper::VariableDumper(LinePrinter &P)
+ : PDBSymDumper(true), Printer(P) {}
+
+void VariableDumper::start(const PDBSymbolData &Var) {
+ if (Var.isCompilerGenerated() && opts::ExcludeCompilerGenerated)
+ return;
+ if (Printer.IsSymbolExcluded(Var.getName()))
+ return;
+
+ auto VarType = Var.getType();
+
+ switch (auto LocType = Var.getLocationType()) {
+ case PDB_LocType::Static:
+ Printer.NewLine();
+ Printer << "data [";
+ WithColor(Printer, PDB_ColorItem::Address).get()
+ << format_hex(Var.getVirtualAddress(), 10);
+ Printer << "] ";
+ WithColor(Printer, PDB_ColorItem::Keyword).get() << "static ";
+ dumpSymbolTypeAndName(*VarType, Var.getName());
+ break;
+ case PDB_LocType::Constant:
+ if (isa<PDBSymbolTypeEnum>(*VarType))
+ break;
+ Printer.NewLine();
+ Printer << "data ";
+ WithColor(Printer, PDB_ColorItem::Keyword).get() << "const ";
+ dumpSymbolTypeAndName(*VarType, Var.getName());
+ Printer << " = ";
+ WithColor(Printer, PDB_ColorItem::LiteralValue).get() << Var.getValue();
+ break;
+ case PDB_LocType::ThisRel:
+ Printer.NewLine();
+ Printer << "data ";
+ WithColor(Printer, PDB_ColorItem::Offset).get()
+ << "+" << format_hex(Var.getOffset(), 4) << " ";
+ dumpSymbolTypeAndName(*VarType, Var.getName());
+ break;
+ case PDB_LocType::BitField:
+ Printer.NewLine();
+ Printer << "data ";
+ WithColor(Printer, PDB_ColorItem::Offset).get()
+ << "+" << format_hex(Var.getOffset(), 4) << " ";
+ dumpSymbolTypeAndName(*VarType, Var.getName());
+ Printer << " : ";
+ WithColor(Printer, PDB_ColorItem::LiteralValue).get() << Var.getLength();
+ break;
+ default:
+ Printer.NewLine();
+ Printer << "data ";
+ Printer << "unknown(" << LocType << ") ";
+ WithColor(Printer, PDB_ColorItem::Identifier).get() << Var.getName();
+ break;
+ }
+}
+
+void VariableDumper::dump(const PDBSymbolTypeBuiltin &Symbol) {
+ BuiltinDumper Dumper(Printer);
+ Dumper.start(Symbol);
+}
+
+void VariableDumper::dump(const PDBSymbolTypeEnum &Symbol) {
+ WithColor(Printer, PDB_ColorItem::Type).get() << Symbol.getName();
+}
+
+void VariableDumper::dump(const PDBSymbolTypeFunctionSig &Symbol) {}
+
+void VariableDumper::dump(const PDBSymbolTypePointer &Symbol) {
+ auto PointeeType = Symbol.getPointeeType();
+ if (!PointeeType)
+ return;
+
+ if (auto Func = dyn_cast<PDBSymbolFunc>(PointeeType.get())) {
+ FunctionDumper NestedDumper(Printer);
+ FunctionDumper::PointerType Pointer =
+ Symbol.isReference() ? FunctionDumper::PointerType::Reference
+ : FunctionDumper::PointerType::Pointer;
+ NestedDumper.start(*Func, Pointer);
+ } else {
+ if (Symbol.isConstType())
+ WithColor(Printer, PDB_ColorItem::Keyword).get() << "const ";
+ if (Symbol.isVolatileType())
+ WithColor(Printer, PDB_ColorItem::Keyword).get() << "volatile ";
+ PointeeType->dump(*this);
+ Printer << (Symbol.isReference() ? "&" : "*");
+ }
+}
+
+void VariableDumper::dump(const PDBSymbolTypeTypedef &Symbol) {
+ WithColor(Printer, PDB_ColorItem::Keyword).get() << "typedef ";
+ WithColor(Printer, PDB_ColorItem::Type).get() << Symbol.getName();
+}
+
+void VariableDumper::dump(const PDBSymbolTypeUDT &Symbol) {
+ WithColor(Printer, PDB_ColorItem::Type).get() << Symbol.getName();
+}
+
+void VariableDumper::dumpSymbolTypeAndName(const PDBSymbol &Type,
+ StringRef Name) {
+ if (auto *ArrayType = dyn_cast<PDBSymbolTypeArray>(&Type)) {
+ std::string IndexSpec;
+ raw_string_ostream IndexStream(IndexSpec);
+ std::unique_ptr<PDBSymbol> ElementType = ArrayType->getElementType();
+ while (auto NestedArray = dyn_cast<PDBSymbolTypeArray>(ElementType.get())) {
+ IndexStream << "[";
+ IndexStream << NestedArray->getCount();
+ IndexStream << "]";
+ ElementType = NestedArray->getElementType();
+ }
+ IndexStream << "[" << ArrayType->getCount() << "]";
+ ElementType->dump(*this);
+ WithColor(Printer, PDB_ColorItem::Identifier).get() << " " << Name;
+ Printer << IndexStream.str();
+ } else {
+ if (!tryDumpFunctionPointer(Type, Name)) {
+ Type.dump(*this);
+ WithColor(Printer, PDB_ColorItem::Identifier).get() << " " << Name;
+ }
+ }
+}
+
+bool VariableDumper::tryDumpFunctionPointer(const PDBSymbol &Type,
+ StringRef Name) {
+ // Function pointers come across as pointers to function signatures. But the
+ // signature carries no name, so we have to handle this case separately.
+ if (auto *PointerType = dyn_cast<PDBSymbolTypePointer>(&Type)) {
+ auto PointeeType = PointerType->getPointeeType();
+ if (auto *FunctionSig =
+ dyn_cast<PDBSymbolTypeFunctionSig>(PointeeType.get())) {
+ FunctionDumper Dumper(Printer);
+ FunctionDumper::PointerType PT = FunctionDumper::PointerType::Pointer;
+ if (PointerType->isReference())
+ PT = FunctionDumper::PointerType::Reference;
+ std::string NameStr(Name.begin(), Name.end());
+ Dumper.start(*FunctionSig, NameStr.c_str(), PT);
+ return true;
+ }
+ }
+ return false;
+}
diff --git a/contrib/llvm/tools/llvm-pdbdump/VariableDumper.h b/contrib/llvm/tools/llvm-pdbdump/VariableDumper.h
new file mode 100644
index 0000000..db8d8ea
--- /dev/null
+++ b/contrib/llvm/tools/llvm-pdbdump/VariableDumper.h
@@ -0,0 +1,41 @@
+//===- VariableDumper.h - PDBSymDumper implementation for types -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVMPDBDUMP_VARIABLEDUMPER_H
+#define LLVM_TOOLS_LLVMPDBDUMP_VARIABLEDUMPER_H
+
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+#include "llvm/ADT/StringRef.h"
+
+namespace llvm {
+
+class LinePrinter;
+
+class VariableDumper : public PDBSymDumper {
+public:
+ VariableDumper(LinePrinter &P);
+
+ void start(const PDBSymbolData &Var);
+
+ void dump(const PDBSymbolTypeBuiltin &Symbol) override;
+ void dump(const PDBSymbolTypeEnum &Symbol) override;
+ void dump(const PDBSymbolTypeFunctionSig &Symbol) override;
+ void dump(const PDBSymbolTypePointer &Symbol) override;
+ void dump(const PDBSymbolTypeTypedef &Symbol) override;
+ void dump(const PDBSymbolTypeUDT &Symbol) override;
+
+private:
+ void dumpSymbolTypeAndName(const PDBSymbol &Type, StringRef Name);
+ bool tryDumpFunctionPointer(const PDBSymbol &Type, StringRef Name);
+
+ LinePrinter &Printer;
+};
+}
+
+#endif
diff --git a/contrib/llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp b/contrib/llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp
new file mode 100644
index 0000000..4a4c64b
--- /dev/null
+++ b/contrib/llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp
@@ -0,0 +1,284 @@
+//===- llvm-pdbdump.cpp - Dump debug info from a PDB file -------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Dumps debug information present in PDB files. This utility makes use of
+// the Microsoft Windows SDK, so will not compile or run on non-Windows
+// platforms.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm-pdbdump.h"
+#include "CompilandDumper.h"
+#include "ExternalSymbolDumper.h"
+#include "FunctionDumper.h"
+#include "LinePrinter.h"
+#include "TypeDumper.h"
+#include "VariableDumper.h"
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/Config/config.h"
+#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
+#include "llvm/DebugInfo/PDB/IPDBRawSymbol.h"
+#include "llvm/DebugInfo/PDB/IPDBSession.h"
+#include "llvm/DebugInfo/PDB/PDB.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolData.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolExe.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolFunc.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolThunk.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/ConvertUTF.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/PrettyStackTrace.h"
+#include "llvm/Support/Process.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/Signals.h"
+
+#if defined(HAVE_DIA_SDK)
+#include <Windows.h>
+#endif
+
+using namespace llvm;
+
+namespace opts {
+
+enum class PDB_DumpType { ByType, ByObjFile, Both };
+
+cl::list<std::string> InputFilenames(cl::Positional,
+ cl::desc("<input PDB files>"),
+ cl::OneOrMore);
+
+cl::OptionCategory TypeCategory("Symbol Type Options");
+cl::OptionCategory FilterCategory("Filtering Options");
+cl::OptionCategory OtherOptions("Other Options");
+
+cl::opt<bool> Compilands("compilands", cl::desc("Display compilands"),
+ cl::cat(TypeCategory));
+cl::opt<bool> Symbols("symbols", cl::desc("Display symbols for each compiland"),
+ cl::cat(TypeCategory));
+cl::opt<bool> Globals("globals", cl::desc("Dump global symbols"),
+ cl::cat(TypeCategory));
+cl::opt<bool> Externals("externals", cl::desc("Dump external symbols"),
+ cl::cat(TypeCategory));
+cl::opt<bool> Types("types", cl::desc("Display types"), cl::cat(TypeCategory));
+cl::opt<bool>
+ All("all", cl::desc("Implies all other options in 'Symbol Types' category"),
+ cl::cat(TypeCategory));
+
+cl::opt<uint64_t> LoadAddress(
+ "load-address",
+ cl::desc("Assume the module is loaded at the specified address"),
+ cl::cat(OtherOptions));
+
+cl::list<std::string>
+ ExcludeTypes("exclude-types",
+ cl::desc("Exclude types by regular expression"),
+ cl::ZeroOrMore, cl::cat(FilterCategory));
+cl::list<std::string>
+ ExcludeSymbols("exclude-symbols",
+ cl::desc("Exclude symbols by regular expression"),
+ cl::ZeroOrMore, cl::cat(FilterCategory));
+cl::list<std::string>
+ ExcludeCompilands("exclude-compilands",
+ cl::desc("Exclude compilands by regular expression"),
+ cl::ZeroOrMore, cl::cat(FilterCategory));
+cl::opt<bool> ExcludeCompilerGenerated(
+ "no-compiler-generated",
+ cl::desc("Don't show compiler generated types and symbols"),
+ cl::cat(FilterCategory));
+cl::opt<bool>
+ ExcludeSystemLibraries("no-system-libs",
+ cl::desc("Don't show symbols from system libraries"),
+ cl::cat(FilterCategory));
+cl::opt<bool> NoClassDefs("no-class-definitions",
+ cl::desc("Don't display full class definitions"),
+ cl::cat(FilterCategory));
+cl::opt<bool> NoEnumDefs("no-enum-definitions",
+ cl::desc("Don't display full enum definitions"),
+ cl::cat(FilterCategory));
+}
+
+static void dumpInput(StringRef Path) {
+ std::unique_ptr<IPDBSession> Session;
+ PDB_ErrorCode Error =
+ llvm::loadDataForPDB(PDB_ReaderType::DIA, Path, Session);
+ switch (Error) {
+ case PDB_ErrorCode::Success:
+ break;
+ case PDB_ErrorCode::NoPdbImpl:
+ outs() << "Reading PDBs is not supported on this platform.\n";
+ return;
+ case PDB_ErrorCode::InvalidPath:
+ outs() << "Unable to load PDB at '" << Path
+ << "'. Check that the file exists and is readable.\n";
+ return;
+ case PDB_ErrorCode::InvalidFileFormat:
+ outs() << "Unable to load PDB at '" << Path
+ << "'. The file has an unrecognized format.\n";
+ return;
+ default:
+ outs() << "Unable to load PDB at '" << Path
+ << "'. An unknown error occured.\n";
+ return;
+ }
+ if (opts::LoadAddress)
+ Session->setLoadAddress(opts::LoadAddress);
+
+ LinePrinter Printer(2, outs());
+
+ auto GlobalScope(Session->getGlobalScope());
+ std::string FileName(GlobalScope->getSymbolsFileName());
+
+ WithColor(Printer, PDB_ColorItem::None).get() << "Summary for ";
+ WithColor(Printer, PDB_ColorItem::Path).get() << FileName;
+ Printer.Indent();
+ uint64_t FileSize = 0;
+
+ Printer.NewLine();
+ WithColor(Printer, PDB_ColorItem::Identifier).get() << "Size";
+ if (!llvm::sys::fs::file_size(FileName, FileSize)) {
+ Printer << ": " << FileSize << " bytes";
+ } else {
+ Printer << ": (Unable to obtain file size)";
+ }
+
+ Printer.NewLine();
+ WithColor(Printer, PDB_ColorItem::Identifier).get() << "Guid";
+ Printer << ": " << GlobalScope->getGuid();
+
+ Printer.NewLine();
+ WithColor(Printer, PDB_ColorItem::Identifier).get() << "Age";
+ Printer << ": " << GlobalScope->getAge();
+
+ Printer.NewLine();
+ WithColor(Printer, PDB_ColorItem::Identifier).get() << "Attributes";
+ Printer << ": ";
+ if (GlobalScope->hasCTypes())
+ outs() << "HasCTypes ";
+ if (GlobalScope->hasPrivateSymbols())
+ outs() << "HasPrivateSymbols ";
+ Printer.Unindent();
+
+ if (opts::Compilands) {
+ Printer.NewLine();
+ WithColor(Printer, PDB_ColorItem::SectionHeader).get()
+ << "---COMPILANDS---";
+ Printer.Indent();
+ auto Compilands = GlobalScope->findAllChildren<PDBSymbolCompiland>();
+ CompilandDumper Dumper(Printer);
+ while (auto Compiland = Compilands->getNext())
+ Dumper.start(*Compiland, false);
+ Printer.Unindent();
+ }
+
+ if (opts::Types) {
+ Printer.NewLine();
+ WithColor(Printer, PDB_ColorItem::SectionHeader).get() << "---TYPES---";
+ Printer.Indent();
+ TypeDumper Dumper(Printer);
+ Dumper.start(*GlobalScope);
+ Printer.Unindent();
+ }
+
+ if (opts::Symbols) {
+ Printer.NewLine();
+ WithColor(Printer, PDB_ColorItem::SectionHeader).get() << "---SYMBOLS---";
+ Printer.Indent();
+ auto Compilands = GlobalScope->findAllChildren<PDBSymbolCompiland>();
+ CompilandDumper Dumper(Printer);
+ while (auto Compiland = Compilands->getNext())
+ Dumper.start(*Compiland, true);
+ Printer.Unindent();
+ }
+
+ if (opts::Globals) {
+ Printer.NewLine();
+ WithColor(Printer, PDB_ColorItem::SectionHeader).get() << "---GLOBALS---";
+ Printer.Indent();
+ {
+ FunctionDumper Dumper(Printer);
+ auto Functions = GlobalScope->findAllChildren<PDBSymbolFunc>();
+ while (auto Function = Functions->getNext()) {
+ Printer.NewLine();
+ Dumper.start(*Function, FunctionDumper::PointerType::None);
+ }
+ }
+ {
+ auto Vars = GlobalScope->findAllChildren<PDBSymbolData>();
+ VariableDumper Dumper(Printer);
+ while (auto Var = Vars->getNext())
+ Dumper.start(*Var);
+ }
+ {
+ auto Thunks = GlobalScope->findAllChildren<PDBSymbolThunk>();
+ CompilandDumper Dumper(Printer);
+ while (auto Thunk = Thunks->getNext())
+ Dumper.dump(*Thunk);
+ }
+ Printer.Unindent();
+ }
+ if (opts::Externals) {
+ Printer.NewLine();
+ WithColor(Printer, PDB_ColorItem::SectionHeader).get() << "---EXTERNALS---";
+ Printer.Indent();
+ ExternalSymbolDumper Dumper(Printer);
+ Dumper.start(*GlobalScope);
+ }
+ outs().flush();
+}
+
+int main(int argc_, const char *argv_[]) {
+ // Print a stack trace if we signal out.
+ sys::PrintStackTraceOnErrorSignal();
+ PrettyStackTraceProgram X(argc_, argv_);
+
+ SmallVector<const char *, 256> argv;
+ llvm::SpecificBumpPtrAllocator<char> ArgAllocator;
+ std::error_code EC = llvm::sys::Process::GetArgumentVector(
+ argv, llvm::makeArrayRef(argv_, argc_), ArgAllocator);
+ if (EC) {
+ llvm::errs() << "error: couldn't get arguments: " << EC.message() << '\n';
+ return 1;
+ }
+
+ llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
+
+ cl::ParseCommandLineOptions(argv.size(), argv.data(), "LLVM PDB Dumper\n");
+ if (opts::All) {
+ opts::Compilands = true;
+ opts::Symbols = true;
+ opts::Globals = true;
+ opts::Types = true;
+ opts::Externals = true;
+ }
+ if (opts::ExcludeCompilerGenerated) {
+ opts::ExcludeTypes.push_back("__vc_attributes");
+ opts::ExcludeCompilands.push_back("* Linker *");
+ }
+ if (opts::ExcludeSystemLibraries) {
+ opts::ExcludeCompilands.push_back(
+ "f:\\binaries\\Intermediate\\vctools\\crt_bld");
+ }
+
+#if defined(HAVE_DIA_SDK)
+ CoInitializeEx(nullptr, COINIT_MULTITHREADED);
+#endif
+
+ std::for_each(opts::InputFilenames.begin(), opts::InputFilenames.end(),
+ dumpInput);
+
+#if defined(HAVE_DIA_SDK)
+ CoUninitialize();
+#endif
+
+ return 0;
+}
diff --git a/contrib/llvm/tools/llvm-pdbdump/llvm-pdbdump.h b/contrib/llvm/tools/llvm-pdbdump/llvm-pdbdump.h
new file mode 100644
index 0000000..586a9ea
--- /dev/null
+++ b/contrib/llvm/tools/llvm-pdbdump/llvm-pdbdump.h
@@ -0,0 +1,32 @@
+//===- llvm-pdbdump.h ----------------------------------------- *- C++ --*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVMPDBDUMP_LLVMPDBDUMP_H
+#define LLVM_TOOLS_LLVMPDBDUMP_LLVMPDBDUMP_H
+
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace opts {
+extern llvm::cl::opt<bool> Compilands;
+extern llvm::cl::opt<bool> Symbols;
+extern llvm::cl::opt<bool> Globals;
+extern llvm::cl::opt<bool> Types;
+extern llvm::cl::opt<bool> All;
+
+extern llvm::cl::opt<bool> ExcludeCompilerGenerated;
+
+extern llvm::cl::opt<bool> NoClassDefs;
+extern llvm::cl::opt<bool> NoEnumDefs;
+extern llvm::cl::list<std::string> ExcludeTypes;
+extern llvm::cl::list<std::string> ExcludeSymbols;
+extern llvm::cl::list<std::string> ExcludeCompilands;
+}
+
+#endif \ No newline at end of file
diff --git a/contrib/llvm/tools/llvm-profdata/llvm-profdata.cpp b/contrib/llvm/tools/llvm-profdata/llvm-profdata.cpp
index 25531c7..1bfdb18 100644
--- a/contrib/llvm/tools/llvm-profdata/llvm-profdata.cpp
+++ b/contrib/llvm/tools/llvm-profdata/llvm-profdata.cpp
@@ -22,6 +22,7 @@
#include "llvm/Support/Format.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Path.h"
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/Signals.h"
#include "llvm/Support/raw_ostream.h"
@@ -38,7 +39,8 @@ static void exitWithError(const Twine &Message, StringRef Whence = "") {
enum ProfileKinds { instr, sample };
-void mergeInstrProfile(cl::list<std::string> Inputs, StringRef OutputFilename) {
+static void mergeInstrProfile(const cl::list<std::string> &Inputs,
+ StringRef OutputFilename) {
if (OutputFilename.compare("-") == 0)
exitWithError("Cannot write indexed profdata format to stdout.");
@@ -64,8 +66,9 @@ void mergeInstrProfile(cl::list<std::string> Inputs, StringRef OutputFilename) {
Writer.write(Output);
}
-void mergeSampleProfile(cl::list<std::string> Inputs, StringRef OutputFilename,
- sampleprof::SampleProfileFormat OutputFormat) {
+static void mergeSampleProfile(const cl::list<std::string> &Inputs,
+ StringRef OutputFilename,
+ sampleprof::SampleProfileFormat OutputFormat) {
using namespace sampleprof;
auto WriterOrErr = SampleProfileWriter::create(OutputFilename, OutputFormat);
if (std::error_code EC = WriterOrErr.getError())
@@ -95,7 +98,7 @@ void mergeSampleProfile(cl::list<std::string> Inputs, StringRef OutputFilename,
Writer->write(ProfileMap);
}
-int merge_main(int argc, const char *argv[]) {
+static int merge_main(int argc, const char *argv[]) {
cl::list<std::string> Inputs(cl::Positional, cl::Required, cl::OneOrMore,
cl::desc("<filenames...>"));
@@ -128,9 +131,9 @@ int merge_main(int argc, const char *argv[]) {
return 0;
}
-int showInstrProfile(std::string Filename, bool ShowCounts,
- bool ShowAllFunctions, std::string ShowFunction,
- raw_fd_ostream &OS) {
+static int showInstrProfile(std::string Filename, bool ShowCounts,
+ bool ShowAllFunctions, std::string ShowFunction,
+ raw_fd_ostream &OS) {
auto ReaderOrErr = InstrProfReader::create(Filename);
if (std::error_code EC = ReaderOrErr.getError())
exitWithError(EC.message(), Filename);
@@ -181,9 +184,9 @@ int showInstrProfile(std::string Filename, bool ShowCounts,
return 0;
}
-int showSampleProfile(std::string Filename, bool ShowCounts,
- bool ShowAllFunctions, std::string ShowFunction,
- raw_fd_ostream &OS) {
+static int showSampleProfile(std::string Filename, bool ShowCounts,
+ bool ShowAllFunctions, std::string ShowFunction,
+ raw_fd_ostream &OS) {
using namespace sampleprof;
auto ReaderOrErr = SampleProfileReader::create(Filename, getGlobalContext());
if (std::error_code EC = ReaderOrErr.getError())
@@ -199,7 +202,7 @@ int showSampleProfile(std::string Filename, bool ShowCounts,
return 0;
}
-int show_main(int argc, const char *argv[]) {
+static int show_main(int argc, const char *argv[]) {
cl::opt<std::string> Filename(cl::Positional, cl::Required,
cl::desc("<profdata-file>"));
diff --git a/contrib/llvm/tools/llvm-readobj/COFFDumper.cpp b/contrib/llvm/tools/llvm-readobj/COFFDumper.cpp
index 156e39a..1412111 100644
--- a/contrib/llvm/tools/llvm-readobj/COFFDumper.cpp
+++ b/contrib/llvm/tools/llvm-readobj/COFFDumper.cpp
@@ -71,7 +71,7 @@ private:
void printBaseOfDataField(const pe32_header *Hdr);
void printBaseOfDataField(const pe32plus_header *Hdr);
- void printCodeViewLineTables(const SectionRef &Section);
+ void printCodeViewDebugInfo(const SectionRef &Section);
void printCodeViewSymbolsSubsection(StringRef Subsection,
const SectionRef &Section,
@@ -469,7 +469,7 @@ void COFFDumper::printBaseOfDataField(const pe32_header *Hdr) {
void COFFDumper::printBaseOfDataField(const pe32plus_header *) {}
-void COFFDumper::printCodeViewLineTables(const SectionRef &Section) {
+void COFFDumper::printCodeViewDebugInfo(const SectionRef &Section) {
StringRef Data;
if (error(Section.getContents(Data)))
return;
@@ -477,7 +477,7 @@ void COFFDumper::printCodeViewLineTables(const SectionRef &Section) {
SmallVector<StringRef, 10> FunctionNames;
StringMap<StringRef> FunctionLineTables;
- ListScope D(W, "CodeViewLineTables");
+ ListScope D(W, "CodeViewDebugInfo");
{
// FIXME: Add more offset correctness checks.
DataExtractor DE(Data, true, 4);
@@ -503,14 +503,17 @@ void COFFDumper::printCodeViewLineTables(const SectionRef &Section) {
return;
}
- // Print the raw contents to simplify debugging if anything goes wrong
- // afterwards.
StringRef Contents = Data.substr(Offset, PayloadSize);
- W.printBinaryBlock("Contents", Contents);
+ if (opts::CodeViewSubsectionBytes) {
+ // Print the raw contents to simplify debugging if anything goes wrong
+ // afterwards.
+ W.printBinaryBlock("Contents", Contents);
+ }
switch (SubSectionType) {
case COFF::DEBUG_SYMBOL_SUBSECTION:
- printCodeViewSymbolsSubsection(Contents, Section, Offset);
+ if (opts::SectionSymbols)
+ printCodeViewSymbolsSubsection(Contents, Section, Offset);
break;
case COFF::DEBUG_LINE_TABLE_SUBSECTION: {
// Holds a PC to file:line table. Some data to parse this subsection is
@@ -695,10 +698,20 @@ void COFFDumper::printCodeViewSymbolsSubsection(StringRef Subsection,
InFunctionScope = false;
break;
}
- default:
+ default: {
+ if (opts::CodeViewSubsectionBytes) {
+ ListScope S(W, "Record");
+ W.printHex("Size", Size);
+ W.printHex("Type", Type);
+
+ StringRef Contents = DE.getData().substr(Offset, Size);
+ W.printBinaryBlock("Contents", Contents);
+ }
+
Offset += Size;
break;
}
+ }
}
if (InFunctionScope)
@@ -747,8 +760,8 @@ void COFFDumper::printSections() {
}
}
- if (Name == ".debug$S" && opts::CodeViewLineTables)
- printCodeViewLineTables(Sec);
+ if (Name == ".debug$S" && opts::CodeView)
+ printCodeViewDebugInfo(Sec);
if (opts::SectionData &&
!(Section->Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA)) {
@@ -1107,6 +1120,7 @@ static StringRef getBaseRelocTypeName(uint8_t Type) {
case COFF::IMAGE_REL_BASED_LOW: return "LOW";
case COFF::IMAGE_REL_BASED_HIGHLOW: return "HIGHLOW";
case COFF::IMAGE_REL_BASED_HIGHADJ: return "HIGHADJ";
+ case COFF::IMAGE_REL_BASED_ARM_MOV32T: return "ARM_MOV32(T)";
case COFF::IMAGE_REL_BASED_DIR64: return "DIR64";
default: return "unknown (" + llvm::utostr(Type) + ")";
}
diff --git a/contrib/llvm/tools/llvm-readobj/ELFDumper.cpp b/contrib/llvm/tools/llvm-readobj/ELFDumper.cpp
index d68c786..a20512f 100644
--- a/contrib/llvm/tools/llvm-readobj/ELFDumper.cpp
+++ b/contrib/llvm/tools/llvm-readobj/ELFDumper.cpp
@@ -26,6 +26,7 @@
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/MathExtras.h"
+#include "llvm/Support/MipsABIFlags.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
@@ -56,6 +57,7 @@ public:
void printAttributes() override;
void printMipsPLTGOT() override;
+ void printMipsABIFlags() override;
private:
typedef ELFFile<ELFT> ELFO;
@@ -170,6 +172,16 @@ findSectionByAddress(const ELFFile<ELFT> *Obj, uint64_t Addr) {
return nullptr;
}
+template <class ELFT>
+static const typename ELFFile<ELFT>::Elf_Shdr *
+findSectionByName(const ELFFile<ELFT> &Obj, StringRef Name) {
+ for (const auto &Shdr : Obj.sections()) {
+ if (Name == errorOrDefault(Obj.getSectionName(&Shdr)))
+ return &Shdr;
+ }
+ return nullptr;
+}
+
static const EnumEntry<unsigned> ElfClass[] = {
{ "None", ELF::ELFCLASSNONE },
{ "32-bit", ELF::ELFCLASS32 },
@@ -207,6 +219,7 @@ static const EnumEntry<unsigned> ElfOSABI[] = {
{ "NSK", ELF::ELFOSABI_NSK },
{ "AROS", ELF::ELFOSABI_AROS },
{ "FenixOS", ELF::ELFOSABI_FENIXOS },
+ { "CloudABI", ELF::ELFOSABI_CLOUDABI },
{ "C6000_ELFABI", ELF::ELFOSABI_C6000_ELFABI },
{ "C6000_LINUX" , ELF::ELFOSABI_C6000_LINUX },
{ "ARM", ELF::ELFOSABI_ARM },
@@ -372,9 +385,10 @@ static const EnumEntry<unsigned> ElfMachineType[] = {
};
static const EnumEntry<unsigned> ElfSymbolBindings[] = {
- { "Local", ELF::STB_LOCAL },
- { "Global", ELF::STB_GLOBAL },
- { "Weak", ELF::STB_WEAK }
+ { "Local", ELF::STB_LOCAL },
+ { "Global", ELF::STB_GLOBAL },
+ { "Weak", ELF::STB_WEAK },
+ { "Unique", ELF::STB_GNU_UNIQUE }
};
static const EnumEntry<unsigned> ElfSymbolTypes[] = {
@@ -469,6 +483,7 @@ static const char *getElfSegmentType(unsigned Arch, unsigned Type) {
LLVM_READOBJ_ENUM_CASE(ELF, PT_MIPS_REGINFO);
LLVM_READOBJ_ENUM_CASE(ELF, PT_MIPS_RTPROC);
LLVM_READOBJ_ENUM_CASE(ELF, PT_MIPS_OPTIONS);
+ LLVM_READOBJ_ENUM_CASE(ELF, PT_MIPS_ABIFLAGS);
}
}
@@ -503,10 +518,33 @@ static const EnumEntry<unsigned> ElfHeaderMipsFlags[] = {
LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_CPIC),
LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ABI2),
LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_32BITMODE),
+ LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_FP64),
LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_NAN2008),
LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ABI_O32),
+ LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ABI_O64),
+ LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ABI_EABI32),
+ LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ABI_EABI64),
+ LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_MACH_3900),
+ LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_MACH_4010),
+ LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_MACH_4100),
+ LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_MACH_4650),
+ LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_MACH_4120),
+ LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_MACH_4111),
+ LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_MACH_SB1),
+ LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_MACH_OCTEON),
+ LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_MACH_XLR),
+ LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_MACH_OCTEON2),
+ LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_MACH_OCTEON3),
+ LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_MACH_5400),
+ LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_MACH_5900),
+ LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_MACH_5500),
+ LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_MACH_9000),
+ LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_MACH_LS2E),
+ LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_MACH_LS2F),
+ LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_MACH_LS3A),
LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_MICROMIPS),
LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ARCH_ASE_M16),
+ LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ARCH_ASE_MDMX),
LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ARCH_1),
LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ARCH_2),
LLVM_READOBJ_ENUM_ENT(ELF, EF_MIPS_ARCH_3),
@@ -549,7 +587,8 @@ void ELFDumper<ELFT>::printFileHeaders() {
W.printHex ("SectionHeaderOffset", Header->e_shoff);
if (Header->e_machine == EM_MIPS)
W.printFlags("Flags", Header->e_flags, makeArrayRef(ElfHeaderMipsFlags),
- unsigned(ELF::EF_MIPS_ARCH));
+ unsigned(ELF::EF_MIPS_ARCH), unsigned(ELF::EF_MIPS_ABI),
+ unsigned(ELF::EF_MIPS_MACH));
else
W.printFlags("Flags", Header->e_flags);
W.printNumber("HeaderSize", Header->e_ehsize);
@@ -739,6 +778,7 @@ static const char *getTypeString(uint64_t Type) {
LLVM_READOBJ_TYPE_CASE(FINI_ARRAY);
LLVM_READOBJ_TYPE_CASE(FINI_ARRAYSZ);
LLVM_READOBJ_TYPE_CASE(FLAGS);
+ LLVM_READOBJ_TYPE_CASE(FLAGS_1);
LLVM_READOBJ_TYPE_CASE(HASH);
LLVM_READOBJ_TYPE_CASE(INIT);
LLVM_READOBJ_TYPE_CASE(INIT_ARRAY);
@@ -780,6 +820,7 @@ static const char *getTypeString(uint64_t Type) {
LLVM_READOBJ_TYPE_CASE(MIPS_GOTSYM);
LLVM_READOBJ_TYPE_CASE(MIPS_RLD_MAP);
LLVM_READOBJ_TYPE_CASE(MIPS_PLTGOT);
+ LLVM_READOBJ_TYPE_CASE(MIPS_OPTIONS);
default: return "unknown";
}
}
@@ -797,6 +838,34 @@ static const EnumEntry<unsigned> ElfDynamicDTFlags[] = {
LLVM_READOBJ_DT_FLAG_ENT(DF, STATIC_TLS)
};
+static const EnumEntry<unsigned> ElfDynamicDTFlags1[] = {
+ LLVM_READOBJ_DT_FLAG_ENT(DF_1, NOW),
+ LLVM_READOBJ_DT_FLAG_ENT(DF_1, GLOBAL),
+ LLVM_READOBJ_DT_FLAG_ENT(DF_1, GROUP),
+ LLVM_READOBJ_DT_FLAG_ENT(DF_1, NODELETE),
+ LLVM_READOBJ_DT_FLAG_ENT(DF_1, LOADFLTR),
+ LLVM_READOBJ_DT_FLAG_ENT(DF_1, INITFIRST),
+ LLVM_READOBJ_DT_FLAG_ENT(DF_1, NOOPEN),
+ LLVM_READOBJ_DT_FLAG_ENT(DF_1, ORIGIN),
+ LLVM_READOBJ_DT_FLAG_ENT(DF_1, DIRECT),
+ LLVM_READOBJ_DT_FLAG_ENT(DF_1, TRANS),
+ LLVM_READOBJ_DT_FLAG_ENT(DF_1, INTERPOSE),
+ LLVM_READOBJ_DT_FLAG_ENT(DF_1, NODEFLIB),
+ LLVM_READOBJ_DT_FLAG_ENT(DF_1, NODUMP),
+ LLVM_READOBJ_DT_FLAG_ENT(DF_1, CONFALT),
+ LLVM_READOBJ_DT_FLAG_ENT(DF_1, ENDFILTEE),
+ LLVM_READOBJ_DT_FLAG_ENT(DF_1, DISPRELDNE),
+ LLVM_READOBJ_DT_FLAG_ENT(DF_1, NODIRECT),
+ LLVM_READOBJ_DT_FLAG_ENT(DF_1, IGNMULDEF),
+ LLVM_READOBJ_DT_FLAG_ENT(DF_1, NOKSYMS),
+ LLVM_READOBJ_DT_FLAG_ENT(DF_1, NOHDR),
+ LLVM_READOBJ_DT_FLAG_ENT(DF_1, EDITED),
+ LLVM_READOBJ_DT_FLAG_ENT(DF_1, NORELOC),
+ LLVM_READOBJ_DT_FLAG_ENT(DF_1, SYMINTPOSE),
+ LLVM_READOBJ_DT_FLAG_ENT(DF_1, GLOBAUDIT),
+ LLVM_READOBJ_DT_FLAG_ENT(DF_1, SINGLETON)
+};
+
static const EnumEntry<unsigned> ElfDynamicDTMipsFlags[] = {
LLVM_READOBJ_DT_FLAG_ENT(RHF, NONE),
LLVM_READOBJ_DT_FLAG_ENT(RHF, QUICKSTART),
@@ -871,6 +940,7 @@ static void printValue(const ELFFile<ELFT> *O, uint64_t Type, uint64_t Value,
case DT_MIPS_GOTSYM:
case DT_MIPS_RLD_MAP:
case DT_MIPS_PLTGOT:
+ case DT_MIPS_OPTIONS:
OS << format("0x%" PRIX64, Value);
break;
case DT_RELCOUNT:
@@ -909,6 +979,9 @@ static void printValue(const ELFFile<ELFT> *O, uint64_t Type, uint64_t Value,
case DT_FLAGS:
printFlags(Value, makeArrayRef(ElfDynamicDTFlags), OS);
break;
+ case DT_FLAGS_1:
+ printFlags(Value, makeArrayRef(ElfDynamicDTFlags1), OS);
+ break;
}
}
@@ -1240,3 +1313,112 @@ template <class ELFT> void ELFDumper<ELFT>::printMipsPLTGOT() {
MipsGOTParser<ELFT>(Obj, W).parseGOT(*GotShdr);
}
+
+static const EnumEntry<unsigned> ElfMipsISAExtType[] = {
+ {"None", Mips::AFL_EXT_NONE},
+ {"Broadcom SB-1", Mips::AFL_EXT_SB1},
+ {"Cavium Networks Octeon", Mips::AFL_EXT_OCTEON},
+ {"Cavium Networks Octeon2", Mips::AFL_EXT_OCTEON2},
+ {"Cavium Networks OcteonP", Mips::AFL_EXT_OCTEONP},
+ {"Cavium Networks Octeon3", Mips::AFL_EXT_OCTEON3},
+ {"LSI R4010", Mips::AFL_EXT_4010},
+ {"Loongson 2E", Mips::AFL_EXT_LOONGSON_2E},
+ {"Loongson 2F", Mips::AFL_EXT_LOONGSON_2F},
+ {"Loongson 3A", Mips::AFL_EXT_LOONGSON_3A},
+ {"MIPS R4650", Mips::AFL_EXT_4650},
+ {"MIPS R5900", Mips::AFL_EXT_5900},
+ {"MIPS R10000", Mips::AFL_EXT_10000},
+ {"NEC VR4100", Mips::AFL_EXT_4100},
+ {"NEC VR4111/VR4181", Mips::AFL_EXT_4111},
+ {"NEC VR4120", Mips::AFL_EXT_4120},
+ {"NEC VR5400", Mips::AFL_EXT_5400},
+ {"NEC VR5500", Mips::AFL_EXT_5500},
+ {"RMI Xlr", Mips::AFL_EXT_XLR},
+ {"Toshiba R3900", Mips::AFL_EXT_3900}
+};
+
+static const EnumEntry<unsigned> ElfMipsASEFlags[] = {
+ {"DSP", Mips::AFL_ASE_DSP},
+ {"DSPR2", Mips::AFL_ASE_DSPR2},
+ {"Enhanced VA Scheme", Mips::AFL_ASE_EVA},
+ {"MCU", Mips::AFL_ASE_MCU},
+ {"MDMX", Mips::AFL_ASE_MDMX},
+ {"MIPS-3D", Mips::AFL_ASE_MIPS3D},
+ {"MT", Mips::AFL_ASE_MT},
+ {"SmartMIPS", Mips::AFL_ASE_SMARTMIPS},
+ {"VZ", Mips::AFL_ASE_VIRT},
+ {"MSA", Mips::AFL_ASE_MSA},
+ {"MIPS16", Mips::AFL_ASE_MIPS16},
+ {"microMIPS", Mips::AFL_ASE_MICROMIPS},
+ {"XPA", Mips::AFL_ASE_XPA}
+};
+
+static const EnumEntry<unsigned> ElfMipsFpABIType[] = {
+ {"Hard or soft float", Mips::Val_GNU_MIPS_ABI_FP_ANY},
+ {"Hard float (double precision)", Mips::Val_GNU_MIPS_ABI_FP_DOUBLE},
+ {"Hard float (single precision)", Mips::Val_GNU_MIPS_ABI_FP_SINGLE},
+ {"Soft float", Mips::Val_GNU_MIPS_ABI_FP_SOFT},
+ {"Hard float (MIPS32r2 64-bit FPU 12 callee-saved)",
+ Mips::Val_GNU_MIPS_ABI_FP_OLD_64},
+ {"Hard float (32-bit CPU, Any FPU)", Mips::Val_GNU_MIPS_ABI_FP_XX},
+ {"Hard float (32-bit CPU, 64-bit FPU)", Mips::Val_GNU_MIPS_ABI_FP_64},
+ {"Hard float compat (32-bit CPU, 64-bit FPU)",
+ Mips::Val_GNU_MIPS_ABI_FP_64A}
+};
+
+static const EnumEntry<unsigned> ElfMipsFlags1[] {
+ {"ODDSPREG", Mips::AFL_FLAGS1_ODDSPREG},
+};
+
+static int getMipsRegisterSize(uint8_t Flag) {
+ switch (Flag) {
+ case Mips::AFL_REG_NONE:
+ return 0;
+ case Mips::AFL_REG_32:
+ return 32;
+ case Mips::AFL_REG_64:
+ return 64;
+ case Mips::AFL_REG_128:
+ return 128;
+ default:
+ return -1;
+ }
+}
+
+template <class ELFT> void ELFDumper<ELFT>::printMipsABIFlags() {
+ const Elf_Shdr *Shdr = findSectionByName(*Obj, ".MIPS.abiflags");
+ if (!Shdr) {
+ W.startLine() << "There is no .MIPS.abiflags section in the file.\n";
+ return;
+ }
+ ErrorOr<ArrayRef<uint8_t>> Sec = Obj->getSectionContents(Shdr);
+ if (!Sec) {
+ W.startLine() << "The .MIPS.abiflags section is empty.\n";
+ return;
+ }
+ if (Sec->size() != sizeof(Elf_Mips_ABIFlags<ELFT>)) {
+ W.startLine() << "The .MIPS.abiflags section has a wrong size.\n";
+ return;
+ }
+
+ auto *Flags = reinterpret_cast<const Elf_Mips_ABIFlags<ELFT> *>(Sec->data());
+
+ raw_ostream &OS = W.getOStream();
+ DictScope GS(W, "MIPS ABI Flags");
+
+ W.printNumber("Version", Flags->version);
+ W.startLine() << "ISA: ";
+ if (Flags->isa_rev <= 1)
+ OS << format("MIPS%u", Flags->isa_level);
+ else
+ OS << format("MIPS%ur%u", Flags->isa_level, Flags->isa_rev);
+ OS << "\n";
+ W.printEnum("ISA Extension", Flags->isa_ext, makeArrayRef(ElfMipsISAExtType));
+ W.printFlags("ASEs", Flags->ases, makeArrayRef(ElfMipsASEFlags));
+ W.printEnum("FP ABI", Flags->fp_abi, makeArrayRef(ElfMipsFpABIType));
+ W.printNumber("GPR size", getMipsRegisterSize(Flags->gpr_size));
+ W.printNumber("CPR1 size", getMipsRegisterSize(Flags->cpr1_size));
+ W.printNumber("CPR2 size", getMipsRegisterSize(Flags->cpr2_size));
+ W.printFlags("Flags 1", Flags->flags1, makeArrayRef(ElfMipsFlags1));
+ W.printHex("Flags 2", Flags->flags2);
+}
diff --git a/contrib/llvm/tools/llvm-readobj/MachODumper.cpp b/contrib/llvm/tools/llvm-readobj/MachODumper.cpp
index 7e8fdad..40691a2 100644
--- a/contrib/llvm/tools/llvm-readobj/MachODumper.cpp
+++ b/contrib/llvm/tools/llvm-readobj/MachODumper.cpp
@@ -203,31 +203,6 @@ static const EnumEntry<uint32_t> MachOHeaderFlags[] = {
LLVM_READOBJ_ENUM_ENT(MachO, MH_APP_EXTENSION_SAFE),
};
-static const EnumEntry<unsigned> MachOSectionTypes[] = {
- { "Regular" , 0x00 },
- { "ZeroFill" , 0x01 },
- { "CStringLiterals" , 0x02 },
- { "4ByteLiterals" , 0x03 },
- { "8ByteLiterals" , 0x04 },
- { "LiteralPointers" , 0x05 },
- { "NonLazySymbolPointers" , 0x06 },
- { "LazySymbolPointers" , 0x07 },
- { "SymbolStubs" , 0x08 },
- { "ModInitFuncs" , 0x09 },
- { "ModTermFuncs" , 0x0A },
- { "Coalesced" , 0x0B },
- { "GBZeroFill" , 0x0C },
- { "Interposing" , 0x0D },
- { "16ByteLiterals" , 0x0E },
- { "DTraceDOF" , 0x0F },
- { "LazyDylibSymbolPoints" , 0x10 },
- { "ThreadLocalRegular" , 0x11 },
- { "ThreadLocalZerofill" , 0x12 },
- { "ThreadLocalVariables" , 0x13 },
- { "ThreadLocalVariablePointers" , 0x14 },
- { "ThreadLocalInitFunctionPointers", 0x15 }
-};
-
static const EnumEntry<unsigned> MachOSectionAttributes[] = {
{ "LocReloc" , 1 << 0 /*S_ATTR_LOC_RELOC */ },
{ "ExtReloc" , 1 << 1 /*S_ATTR_EXT_RELOC */ },
diff --git a/contrib/llvm/tools/llvm-readobj/ObjDumper.h b/contrib/llvm/tools/llvm-readobj/ObjDumper.h
index 27e658f..5750d6f 100644
--- a/contrib/llvm/tools/llvm-readobj/ObjDumper.h
+++ b/contrib/llvm/tools/llvm-readobj/ObjDumper.h
@@ -42,6 +42,7 @@ public:
// Only implemented for MIPS ELF at this time.
virtual void printMipsPLTGOT() { }
+ virtual void printMipsABIFlags() { }
// Only implemented for PE/COFF.
virtual void printCOFFImports() { }
diff --git a/contrib/llvm/tools/llvm-readobj/StreamWriter.h b/contrib/llvm/tools/llvm-readobj/StreamWriter.h
index 2fc53ee..245588b 100644
--- a/contrib/llvm/tools/llvm-readobj/StreamWriter.h
+++ b/contrib/llvm/tools/llvm-readobj/StreamWriter.h
@@ -96,9 +96,10 @@ public:
}
}
- template<typename T, typename TFlag>
- void printFlags(StringRef Label, T Value, ArrayRef<EnumEntry<TFlag> > Flags,
- TFlag EnumMask = TFlag(0)) {
+ template <typename T, typename TFlag>
+ void printFlags(StringRef Label, T Value, ArrayRef<EnumEntry<TFlag>> Flags,
+ TFlag EnumMask1 = {}, TFlag EnumMask2 = {},
+ TFlag EnumMask3 = {}) {
typedef EnumEntry<TFlag> FlagEntry;
typedef SmallVector<FlagEntry, 10> FlagVector;
FlagVector SetFlags;
@@ -107,6 +108,13 @@ public:
if (Flag.Value == 0)
continue;
+ TFlag EnumMask{};
+ if (Flag.Value & EnumMask1)
+ EnumMask = EnumMask1;
+ else if (Flag.Value & EnumMask2)
+ EnumMask = EnumMask2;
+ else if (Flag.Value & EnumMask3)
+ EnumMask = EnumMask3;
bool IsEnum = (Flag.Value & EnumMask) != 0;
if ((!IsEnum && (Value & Flag.Value) == Flag.Value) ||
(IsEnum && (Value & EnumMask) == Flag.Value)) {
diff --git a/contrib/llvm/tools/llvm-readobj/llvm-readobj.cpp b/contrib/llvm/tools/llvm-readobj/llvm-readobj.cpp
index f95fea8..be7bbe9 100644
--- a/contrib/llvm/tools/llvm-readobj/llvm-readobj.cpp
+++ b/contrib/llvm/tools/llvm-readobj/llvm-readobj.cpp
@@ -25,6 +25,7 @@
#include "StreamWriter.h"
#include "llvm/Object/Archive.h"
#include "llvm/Object/ELFObjectFile.h"
+#include "llvm/Object/MachOUniversal.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/CommandLine.h"
@@ -127,9 +128,14 @@ namespace opts {
cl::opt<bool> ExpandRelocs("expand-relocs",
cl::desc("Expand each shown relocation to multiple lines"));
- // -codeview-linetables
- cl::opt<bool> CodeViewLineTables("codeview-linetables",
- cl::desc("Display CodeView line table information"));
+ // -codeview
+ cl::opt<bool> CodeView("codeview",
+ cl::desc("Display CodeView debug information"));
+
+ // -codeview-subsection-bytes
+ cl::opt<bool> CodeViewSubsectionBytes(
+ "codeview-subsection-bytes",
+ cl::desc("Dump raw contents of codeview debug sections and records"));
// -arm-attributes, -a
cl::opt<bool> ARMAttributes("arm-attributes",
@@ -142,6 +148,10 @@ namespace opts {
MipsPLTGOT("mips-plt-got",
cl::desc("Display the MIPS GOT and PLT GOT sections"));
+ // -mips-abi-flags
+ cl::opt<bool> MipsABIFlags("mips-abi-flags",
+ cl::desc("Display the MIPS.abiflags section"));
+
// -coff-imports
cl::opt<bool>
COFFImports("coff-imports", cl::desc("Display the PE/COFF import table"));
@@ -281,9 +291,12 @@ static void dumpObject(const ObjectFile *Obj) {
if (Obj->getArch() == llvm::Triple::arm && Obj->isELF())
if (opts::ARMAttributes)
Dumper->printAttributes();
- if (isMipsArch(Obj->getArch()) && Obj->isELF())
+ if (isMipsArch(Obj->getArch()) && Obj->isELF()) {
if (opts::MipsPLTGOT)
Dumper->printMipsPLTGOT();
+ if (opts::MipsABIFlags)
+ Dumper->printMipsABIFlags();
+ }
if (opts::COFFImports)
Dumper->printCOFFImports();
if (opts::COFFExports)
@@ -315,6 +328,18 @@ static void dumpArchive(const Archive *Arc) {
}
}
+/// @brief Dumps each object file in \a MachO Universal Binary;
+static void dumpMachOUniversalBinary(const MachOUniversalBinary *UBinary) {
+ for (const MachOUniversalBinary::ObjectForArch &Obj : UBinary->objects()) {
+ ErrorOr<std::unique_ptr<MachOObjectFile>> ObjOrErr = Obj.getAsObjectFile();
+ if (ObjOrErr)
+ dumpObject(&*ObjOrErr.get());
+ else if (ErrorOr<std::unique_ptr<Archive>> AOrErr = Obj.getAsArchive())
+ dumpArchive(&*AOrErr.get());
+ else
+ reportError(UBinary->getFileName(), ObjOrErr.getError().message());
+ }
+}
/// @brief Opens \a File and dumps it.
static void dumpInput(StringRef File) {
@@ -334,6 +359,9 @@ static void dumpInput(StringRef File) {
if (Archive *Arc = dyn_cast<Archive>(&Binary))
dumpArchive(Arc);
+ else if (MachOUniversalBinary *UBinary =
+ dyn_cast<MachOUniversalBinary>(&Binary))
+ dumpMachOUniversalBinary(UBinary);
else if (ObjectFile *Obj = dyn_cast<ObjectFile>(&Binary))
dumpObject(Obj);
else
diff --git a/contrib/llvm/tools/llvm-readobj/llvm-readobj.h b/contrib/llvm/tools/llvm-readobj/llvm-readobj.h
index 1c33417..74b9a60 100644
--- a/contrib/llvm/tools/llvm-readobj/llvm-readobj.h
+++ b/contrib/llvm/tools/llvm-readobj/llvm-readobj.h
@@ -36,7 +36,8 @@ namespace opts {
extern llvm::cl::opt<bool> DynamicSymbols;
extern llvm::cl::opt<bool> UnwindInfo;
extern llvm::cl::opt<bool> ExpandRelocs;
- extern llvm::cl::opt<bool> CodeViewLineTables;
+ extern llvm::cl::opt<bool> CodeView;
+ extern llvm::cl::opt<bool> CodeViewSubsectionBytes;
extern llvm::cl::opt<bool> ARMAttributes;
extern llvm::cl::opt<bool> MipsPLTGOT;
} // namespace opts
diff --git a/contrib/llvm/tools/llvm-rtdyld/llvm-rtdyld.cpp b/contrib/llvm/tools/llvm-rtdyld/llvm-rtdyld.cpp
index 5b6f301..e87f1e2 100644
--- a/contrib/llvm/tools/llvm-rtdyld/llvm-rtdyld.cpp
+++ b/contrib/llvm/tools/llvm-rtdyld/llvm-rtdyld.cpp
@@ -13,6 +13,8 @@
#include "llvm/ADT/StringMap.h"
#include "llvm/DebugInfo/DIContext.h"
+#include "llvm/DebugInfo/DWARF/DWARFContext.h"
+#include "llvm/ExecutionEngine/RTDyldMemoryManager.h"
#include "llvm/ExecutionEngine/RuntimeDyld.h"
#include "llvm/ExecutionEngine/RuntimeDyldChecker.h"
#include "llvm/MC/MCAsmInfo.h"
@@ -21,6 +23,7 @@
#include "llvm/MC/MCInstPrinter.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCRegisterInfo.h"
+#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/Object/MachO.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/DynamicLibrary.h"
@@ -45,6 +48,7 @@ InputFileList(cl::Positional, cl::ZeroOrMore,
enum ActionType {
AC_Execute,
AC_PrintLineInfo,
+ AC_PrintDebugLineInfo,
AC_Verify
};
@@ -55,6 +59,8 @@ Action(cl::desc("Action to perform:"),
"Load, link, and execute the inputs."),
clEnumValN(AC_PrintLineInfo, "printline",
"Load, link, and print line information for each function."),
+ clEnumValN(AC_PrintDebugLineInfo, "printdebugline",
+ "Load, link, and print line information for each function using the debug object"),
clEnumValN(AC_Verify, "verify",
"Load, link and verify the resulting memory image."),
clEnumValEnd));
@@ -186,7 +192,9 @@ static void loadDylibs() {
/* *** */
-static int printLineInfoForInput() {
+static int printLineInfoForInput(bool LoadObjects, bool UseDebugObj) {
+ assert(LoadObjects || !UseDebugObj);
+
// Load any dylibs requested on the command line.
loadDylibs();
@@ -196,7 +204,7 @@ static int printLineInfoForInput() {
for(unsigned i = 0, e = InputFileList.size(); i != e; ++i) {
// Instantiate a dynamic linker.
TrivialMemoryManager MemMgr;
- RuntimeDyld Dyld(&MemMgr);
+ RuntimeDyld Dyld(MemMgr, MemMgr);
// Load the input memory buffer.
@@ -213,24 +221,32 @@ static int printLineInfoForInput() {
ObjectFile &Obj = **MaybeObj;
- // Load the object file
- std::unique_ptr<RuntimeDyld::LoadedObjectInfo> LoadedObjInfo =
- Dyld.loadObject(Obj);
+ OwningBinary<ObjectFile> DebugObj;
+ std::unique_ptr<RuntimeDyld::LoadedObjectInfo> LoadedObjInfo = nullptr;
+ ObjectFile *SymbolObj = &Obj;
+ if (LoadObjects) {
+ // Load the object file
+ LoadedObjInfo =
+ Dyld.loadObject(Obj);
- if (Dyld.hasError())
- return Error(Dyld.getErrorString());
+ if (Dyld.hasError())
+ return Error(Dyld.getErrorString());
- // Resolve all the relocations we can.
- Dyld.resolveRelocations();
+ // Resolve all the relocations we can.
+ Dyld.resolveRelocations();
- OwningBinary<ObjectFile> DebugObj = LoadedObjInfo->getObjectForDebug(Obj);
+ if (UseDebugObj) {
+ DebugObj = LoadedObjInfo->getObjectForDebug(Obj);
+ SymbolObj = DebugObj.getBinary();
+ }
+ }
std::unique_ptr<DIContext> Context(
- DIContext::getDWARFContext(*DebugObj.getBinary()));
+ new DWARFContextInMemory(*SymbolObj,LoadedObjInfo.get()));
// Use symbol info to iterate functions in the object.
- for (object::symbol_iterator I = DebugObj.getBinary()->symbol_begin(),
- E = DebugObj.getBinary()->symbol_end();
+ for (object::symbol_iterator I = SymbolObj->symbol_begin(),
+ E = SymbolObj->symbol_end();
I != E; ++I) {
object::SymbolRef::Type SymType;
if (I->getType(SymType)) continue;
@@ -242,7 +258,21 @@ static int printLineInfoForInput() {
if (I->getAddress(Addr)) continue;
if (I->getSize(Size)) continue;
- outs() << "Function: " << Name << ", Size = " << Size << "\n";
+ // If we're not using the debug object, compute the address of the
+ // symbol in memory (rather than that in the unrelocated object file)
+ // and use that to query the DWARFContext.
+ if (!UseDebugObj && LoadObjects) {
+ object::section_iterator Sec(SymbolObj->section_end());
+ I->getSection(Sec);
+ StringRef SecName;
+ Sec->getName(SecName);
+ uint64_t SectionLoadAddress =
+ LoadedObjInfo->getSectionLoadAddress(SecName);
+ if (SectionLoadAddress != 0)
+ Addr += SectionLoadAddress - Sec->getAddress();
+ }
+
+ outs() << "Function: " << Name << ", Size = " << Size << ", Addr = " << Addr << "\n";
DILineInfoTable Lines = Context->getLineInfoForAddressRange(Addr, Size);
DILineInfoTable::iterator Begin = Lines.begin();
@@ -264,7 +294,12 @@ static int executeInput() {
// Instantiate a dynamic linker.
TrivialMemoryManager MemMgr;
- RuntimeDyld Dyld(&MemMgr);
+ RuntimeDyld Dyld(MemMgr, MemMgr);
+
+ // FIXME: Preserve buffers until resolveRelocations time to work around a bug
+ // in RuntimeDyldELF.
+ // This fixme should be fixed ASAP. This is a very brittle workaround.
+ std::vector<std::unique_ptr<MemoryBuffer>> InputBuffers;
// If we don't have any input files, read from stdin.
if (!InputFileList.size())
@@ -282,6 +317,7 @@ static int executeInput() {
return Error("unable to create object file: '" + EC.message() + "'");
ObjectFile &Obj = **MaybeObj;
+ InputBuffers.push_back(std::move(*InputBuffer));
// Load the object file
Dyld.loadObject(Obj);
@@ -298,7 +334,7 @@ static int executeInput() {
// FIXME: Error out if there are unresolved relocations.
// Get the address of the entry point (_main by default).
- void *MainAddress = Dyld.getSymbolAddress(EntryPoint);
+ void *MainAddress = Dyld.getSymbolLocalAddress(EntryPoint);
if (!MainAddress)
return Error("no definition for '" + EntryPoint + "'");
@@ -339,7 +375,7 @@ static int checkAllExpressions(RuntimeDyldChecker &Checker) {
return 0;
}
-std::map<void*, uint64_t>
+static std::map<void *, uint64_t>
applySpecificSectionMappings(RuntimeDyldChecker &Checker) {
std::map<void*, uint64_t> SpecificMappings;
@@ -397,9 +433,9 @@ applySpecificSectionMappings(RuntimeDyldChecker &Checker) {
// Defaults to zero. Set to something big
// (e.g. 1 << 32) to stress-test stubs, GOTs, etc.
//
-void remapSections(const llvm::Triple &TargetTriple,
- const TrivialMemoryManager &MemMgr,
- RuntimeDyldChecker &Checker) {
+static void remapSections(const llvm::Triple &TargetTriple,
+ const TrivialMemoryManager &MemMgr,
+ RuntimeDyldChecker &Checker) {
// Set up a work list (section addr/size pairs).
typedef std::list<std::pair<void*, uint64_t>> WorklistT;
@@ -506,18 +542,23 @@ static int linkAndVerify() {
std::unique_ptr<MCInstrInfo> MII(TheTarget->createMCInstrInfo());
std::unique_ptr<MCInstPrinter> InstPrinter(
- TheTarget->createMCInstPrinter(0, *MAI, *MII, *MRI, *STI));
+ TheTarget->createMCInstPrinter(Triple(TripleName), 0, *MAI, *MII, *MRI));
// Load any dylibs requested on the command line.
loadDylibs();
// Instantiate a dynamic linker.
TrivialMemoryManager MemMgr;
- RuntimeDyld Dyld(&MemMgr);
+ RuntimeDyld Dyld(MemMgr, MemMgr);
Dyld.setProcessAllSections(true);
RuntimeDyldChecker Checker(Dyld, Disassembler.get(), InstPrinter.get(),
llvm::dbgs());
+ // FIXME: Preserve buffers until resolveRelocations time to work around a bug
+ // in RuntimeDyldELF.
+ // This fixme should be fixed ASAP. This is a very brittle workaround.
+ std::vector<std::unique_ptr<MemoryBuffer>> InputBuffers;
+
// If we don't have any input files, read from stdin.
if (!InputFileList.size())
InputFileList.push_back("-");
@@ -536,6 +577,7 @@ static int linkAndVerify() {
return Error("unable to create object file: '" + EC.message() + "'");
ObjectFile &Obj = **MaybeObj;
+ InputBuffers.push_back(std::move(*InputBuffer));
// Load the object file
Dyld.loadObject(Obj);
@@ -579,8 +621,10 @@ int main(int argc, char **argv) {
switch (Action) {
case AC_Execute:
return executeInput();
+ case AC_PrintDebugLineInfo:
+ return printLineInfoForInput(true,true);
case AC_PrintLineInfo:
- return printLineInfoForInput();
+ return printLineInfoForInput(true,false);
case AC_Verify:
return linkAndVerify();
}
diff --git a/contrib/llvm/tools/llvm-stress/llvm-stress.cpp b/contrib/llvm/tools/llvm-stress/llvm-stress.cpp
index 21a79e3..f5e718b 100644
--- a/contrib/llvm/tools/llvm-stress/llvm-stress.cpp
+++ b/contrib/llvm/tools/llvm-stress/llvm-stress.cpp
@@ -20,7 +20,7 @@
#include "llvm/IR/LegacyPassNameParser.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Verifier.h"
-#include "llvm/PassManager.h"
+#include "llvm/IR/LegacyPassManager.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/ManagedStatic.h"
@@ -711,9 +711,8 @@ int main(int argc, char **argv) {
return 1;
}
- PassManager Passes;
+ legacy::PassManager Passes;
Passes.add(createVerifierPass());
- Passes.add(createDebugInfoVerifierPass());
Passes.add(createPrintModulePass(Out->os()));
Passes.run(*M.get());
Out->keep();
diff --git a/contrib/llvm/tools/llvm-symbolizer/LLVMSymbolize.cpp b/contrib/llvm/tools/llvm-symbolizer/LLVMSymbolize.cpp
index 36061d7..afb7cc8 100644
--- a/contrib/llvm/tools/llvm-symbolizer/LLVMSymbolize.cpp
+++ b/contrib/llvm/tools/llvm-symbolizer/LLVMSymbolize.cpp
@@ -14,6 +14,9 @@
#include "LLVMSymbolize.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Config/config.h"
+#include "llvm/DebugInfo/DWARF/DWARFContext.h"
+#include "llvm/DebugInfo/PDB/PDB.h"
+#include "llvm/DebugInfo/PDB/PDBContext.h"
#include "llvm/Object/ELFObjectFile.h"
#include "llvm/Object/MachO.h"
#include "llvm/Support/Casting.h"
@@ -26,6 +29,11 @@
#include <sstream>
#include <stdlib.h>
+#if defined(_MSC_VER)
+#include <Windows.h>
+#include <DbgHelp.h>
+#endif
+
namespace llvm {
namespace symbolize {
@@ -163,6 +171,7 @@ DILineInfo ModuleInfo::symbolizeCode(
DIInliningInfo ModuleInfo::symbolizeInlinedCode(
uint64_t ModuleOffset, const LLVMSymbolizer::Options &Opts) const {
DIInliningInfo InlinedContext;
+
if (DebugInfoContext) {
InlinedContext = DebugInfoContext->getInliningInfoForAddress(
ModuleOffset, getDILineInfoSpecifier(Opts));
@@ -460,7 +469,20 @@ LLVMSymbolizer::getOrCreateModuleInfo(const std::string &ModuleName) {
Modules.insert(make_pair(ModuleName, (ModuleInfo *)nullptr));
return nullptr;
}
- DIContext *Context = DIContext::getDWARFContext(*Objects.second);
+ DIContext *Context = nullptr;
+ if (auto CoffObject = dyn_cast<COFFObjectFile>(Objects.first)) {
+ // If this is a COFF object, assume it contains PDB debug information. If
+ // we don't find any we will fall back to the DWARF case.
+ std::unique_ptr<IPDBSession> Session;
+ PDB_ErrorCode Error = loadDataForEXE(PDB_ReaderType::DIA,
+ Objects.first->getFileName(), Session);
+ if (Error == PDB_ErrorCode::Success) {
+ Context = new PDBContext(*CoffObject, std::move(Session),
+ Opts.RelativeAddresses);
+ }
+ }
+ if (!Context)
+ Context = new DWARFContextInMemory(*Objects.second);
assert(Context);
ModuleInfo *Info = new ModuleInfo(Objects.first, Context);
Modules.insert(make_pair(ModuleName, Info));
@@ -507,7 +529,17 @@ std::string LLVMSymbolizer::DemangleName(const std::string &Name) {
free(DemangledName);
return Result;
#else
- return Name;
+ char DemangledName[1024] = {0};
+ DWORD result = ::UnDecorateSymbolName(
+ Name.c_str(), DemangledName, 1023,
+ UNDNAME_NO_ACCESS_SPECIFIERS | // Strip public, private, protected
+ UNDNAME_NO_ALLOCATION_LANGUAGE | // Strip __thiscall, __stdcall, etc
+ UNDNAME_NO_THROW_SIGNATURES | // Strip throw() specifications
+ UNDNAME_NO_MEMBER_TYPE | // Strip virtual, static, etc specifiers
+ UNDNAME_NO_MS_KEYWORDS | // Strip all MS extension keywords
+ UNDNAME_NO_FUNCTION_RETURNS); // Strip function return types
+
+ return (result == 0) ? Name : std::string(DemangledName);
#endif
}
diff --git a/contrib/llvm/tools/llvm-symbolizer/LLVMSymbolize.h b/contrib/llvm/tools/llvm-symbolizer/LLVMSymbolize.h
index ff848fc..1c2006f 100644
--- a/contrib/llvm/tools/llvm-symbolizer/LLVMSymbolize.h
+++ b/contrib/llvm/tools/llvm-symbolizer/LLVMSymbolize.h
@@ -35,19 +35,20 @@ class ModuleInfo;
class LLVMSymbolizer {
public:
struct Options {
- bool UseSymbolTable : 1;
FunctionNameKind PrintFunctions;
+ bool UseSymbolTable : 1;
bool PrintInlining : 1;
bool Demangle : 1;
+ bool RelativeAddresses : 1;
std::string DefaultArch;
std::vector<std::string> DsymHints;
- Options(bool UseSymbolTable = true,
- FunctionNameKind PrintFunctions = FunctionNameKind::LinkageName,
- bool PrintInlining = true, bool Demangle = true,
+ Options(FunctionNameKind PrintFunctions = FunctionNameKind::LinkageName,
+ bool UseSymbolTable = true, bool PrintInlining = true,
+ bool Demangle = true, bool RelativeAddresses = false,
std::string DefaultArch = "")
- : UseSymbolTable(UseSymbolTable),
- PrintFunctions(PrintFunctions), PrintInlining(PrintInlining),
- Demangle(Demangle), DefaultArch(DefaultArch) {}
+ : PrintFunctions(PrintFunctions), UseSymbolTable(UseSymbolTable),
+ PrintInlining(PrintInlining), Demangle(Demangle),
+ RelativeAddresses(RelativeAddresses), DefaultArch(DefaultArch) {}
};
LLVMSymbolizer(const Options &Opts = Options()) : Opts(Opts) {}
diff --git a/contrib/llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp b/contrib/llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp
index d554022..9c9f3ad 100644
--- a/contrib/llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp
+++ b/contrib/llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp
@@ -17,10 +17,12 @@
#include "LLVMSymbolize.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/COM.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/Path.h"
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/Signals.h"
#include "llvm/Support/raw_ostream.h"
@@ -47,8 +49,13 @@ static cl::opt<FunctionNameKind> ClPrintFunctions(
clEnumValEnd));
static cl::opt<bool>
-ClPrintInlining("inlining", cl::init(true),
- cl::desc("Print all inlined frames for a given address"));
+ ClUseRelativeAddress("relative-address", cl::init(false),
+ cl::desc("Interpret addresses as relative addresses"),
+ cl::ReallyHidden);
+
+static cl::opt<bool>
+ ClPrintInlining("inlining", cl::init(true),
+ cl::desc("Print all inlined frames for a given address"));
static cl::opt<bool>
ClDemangle("demangle", cl::init(true), cl::desc("Demangle function names"));
@@ -122,9 +129,12 @@ int main(int argc, char **argv) {
PrettyStackTraceProgram X(argc, argv);
llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
+ llvm::sys::InitializeCOMRAII COM(llvm::sys::COMThreadingMode::MultiThreaded);
+
cl::ParseCommandLineOptions(argc, argv, "llvm-symbolizer\n");
- LLVMSymbolizer::Options Opts(ClUseSymbolTable, ClPrintFunctions,
- ClPrintInlining, ClDemangle, ClDefaultArch);
+ LLVMSymbolizer::Options Opts(ClPrintFunctions, ClUseSymbolTable,
+ ClPrintInlining, ClDemangle,
+ ClUseRelativeAddress, ClDefaultArch);
for (const auto &hint : ClDsymHint) {
if (sys::path::extension(hint) == ".dSYM") {
Opts.DsymHints.push_back(hint);
@@ -145,5 +155,6 @@ int main(int argc, char **argv) {
outs() << Result << "\n";
outs().flush();
}
+
return 0;
}
diff --git a/contrib/llvm/tools/opt/BreakpointPrinter.cpp b/contrib/llvm/tools/opt/BreakpointPrinter.cpp
index 3cbc0ae..363a7cd 100644
--- a/contrib/llvm/tools/opt/BreakpointPrinter.cpp
+++ b/contrib/llvm/tools/opt/BreakpointPrinter.cpp
@@ -29,18 +29,16 @@ struct BreakpointPrinter : public ModulePass {
BreakpointPrinter(raw_ostream &out) : ModulePass(ID), Out(out) {}
- void getContextName(DIDescriptor Context, std::string &N) {
- if (Context.isNameSpace()) {
- DINameSpace NS(Context);
- if (!NS.getName().empty()) {
- getContextName(NS.getContext(), N);
- N = N + NS.getName().str() + "::";
+ void getContextName(const DIScope *Context, std::string &N) {
+ if (auto *NS = dyn_cast<DINamespace>(Context)) {
+ if (!NS->getName().empty()) {
+ getContextName(NS->getScope(), N);
+ N = N + NS->getName().str() + "::";
}
- } else if (Context.isType()) {
- DIType TY(Context);
- if (!TY.getName().empty()) {
- getContextName(TY.getContext().resolve(TypeIdentifierMap), N);
- N = N + TY.getName().str() + "::";
+ } else if (auto *TY = dyn_cast<DIType>(Context)) {
+ if (!TY->getName().empty()) {
+ getContextName(TY->getScope().resolve(TypeIdentifierMap), N);
+ N = N + TY->getName().str() + "::";
}
}
}
@@ -55,13 +53,11 @@ struct BreakpointPrinter : public ModulePass {
if (NamedMDNode *NMD = M.getNamedMetadata("llvm.dbg.sp"))
for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) {
std::string Name;
- DISubprogram SP(NMD->getOperand(i));
- assert((!SP || SP.isSubprogram()) &&
- "A MDNode in llvm.dbg.sp should be null or a DISubprogram.");
+ auto *SP = cast_or_null<DISubprogram>(NMD->getOperand(i));
if (!SP)
continue;
- getContextName(SP.getContext().resolve(TypeIdentifierMap), Name);
- Name = Name + SP.getDisplayName().str();
+ getContextName(SP->getScope().resolve(TypeIdentifierMap), Name);
+ Name = Name + SP->getDisplayName().str();
if (!Name.empty() && Processed.insert(Name).second) {
Out << Name << "\n";
}
diff --git a/contrib/llvm/tools/opt/NewPMDriver.cpp b/contrib/llvm/tools/opt/NewPMDriver.cpp
index f215c77..3030d65 100644
--- a/contrib/llvm/tools/opt/NewPMDriver.cpp
+++ b/contrib/llvm/tools/opt/NewPMDriver.cpp
@@ -14,7 +14,6 @@
//===----------------------------------------------------------------------===//
#include "NewPMDriver.h"
-#include "Passes.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Analysis/CGSCCPassManager.h"
#include "llvm/Bitcode/BitcodeWriterPass.h"
@@ -24,9 +23,11 @@
#include "llvm/IR/Module.h"
#include "llvm/IR/PassManager.h"
#include "llvm/IR/Verifier.h"
+#include "llvm/Passes/PassBuilder.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/ToolOutputFile.h"
+#include "llvm/Target/TargetMachine.h"
using namespace llvm;
using namespace opt_tool;
@@ -36,16 +37,21 @@ static cl::opt<bool>
cl::desc("Print pass management debugging information"));
bool llvm::runPassPipeline(StringRef Arg0, LLVMContext &Context, Module &M,
- tool_output_file *Out, StringRef PassPipeline,
- OutputKind OK, VerifierKind VK) {
+ TargetMachine *TM, tool_output_file *Out,
+ StringRef PassPipeline, OutputKind OK,
+ VerifierKind VK,
+ bool ShouldPreserveAssemblyUseListOrder,
+ bool ShouldPreserveBitcodeUseListOrder) {
+ PassBuilder PB(TM);
+
FunctionAnalysisManager FAM(DebugPM);
CGSCCAnalysisManager CGAM(DebugPM);
ModuleAnalysisManager MAM(DebugPM);
// Register all the basic analyses with the managers.
- registerModuleAnalyses(MAM);
- registerCGSCCAnalyses(CGAM);
- registerFunctionAnalyses(FAM);
+ PB.registerModuleAnalyses(MAM);
+ PB.registerCGSCCAnalyses(CGAM);
+ PB.registerFunctionAnalyses(FAM);
// Cross register the analysis managers through their proxies.
MAM.registerPass(FunctionAnalysisManagerModuleProxy(FAM));
@@ -59,7 +65,8 @@ bool llvm::runPassPipeline(StringRef Arg0, LLVMContext &Context, Module &M,
if (VK > VK_NoVerifier)
MPM.addPass(VerifierPass());
- if (!parsePassPipeline(MPM, PassPipeline, VK == VK_VerifyEachPass, DebugPM)) {
+ if (!PB.parsePassPipeline(MPM, PassPipeline, VK == VK_VerifyEachPass,
+ DebugPM)) {
errs() << Arg0 << ": unable to parse pass pipeline description.\n";
return false;
}
@@ -72,10 +79,12 @@ bool llvm::runPassPipeline(StringRef Arg0, LLVMContext &Context, Module &M,
case OK_NoOutput:
break; // No output pass needed.
case OK_OutputAssembly:
- MPM.addPass(PrintModulePass(Out->os()));
+ MPM.addPass(
+ PrintModulePass(Out->os(), "", ShouldPreserveAssemblyUseListOrder));
break;
case OK_OutputBitcode:
- MPM.addPass(BitcodeWriterPass(Out->os()));
+ MPM.addPass(
+ BitcodeWriterPass(Out->os(), ShouldPreserveBitcodeUseListOrder));
break;
}
diff --git a/contrib/llvm/tools/opt/NewPMDriver.h b/contrib/llvm/tools/opt/NewPMDriver.h
index f977bac..349a7b1 100644
--- a/contrib/llvm/tools/opt/NewPMDriver.h
+++ b/contrib/llvm/tools/opt/NewPMDriver.h
@@ -26,6 +26,7 @@
namespace llvm {
class LLVMContext;
class Module;
+class TargetMachine;
class tool_output_file;
namespace opt_tool {
@@ -48,8 +49,11 @@ enum VerifierKind {
/// file. It's interface is consequentially somewhat ad-hoc, but will go away
/// when the transition finishes.
bool runPassPipeline(StringRef Arg0, LLVMContext &Context, Module &M,
- tool_output_file *Out, StringRef PassPipeline,
- opt_tool::OutputKind OK, opt_tool::VerifierKind VK);
+ TargetMachine *TM, tool_output_file *Out,
+ StringRef PassPipeline, opt_tool::OutputKind OK,
+ opt_tool::VerifierKind VK,
+ bool ShouldPreserveAssemblyUseListOrder,
+ bool ShouldPreserveBitcodeUseListOrder);
}
#endif
diff --git a/contrib/llvm/tools/opt/PassRegistry.def b/contrib/llvm/tools/opt/PassRegistry.def
deleted file mode 100644
index c98de60..0000000
--- a/contrib/llvm/tools/opt/PassRegistry.def
+++ /dev/null
@@ -1,65 +0,0 @@
-//===- PassRegistry.def - Registry of passes --------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file is used as the registry of passes that are part of the core LLVM
-// libraries. This file describes both transformation passes and analyses
-// Analyses are registered while transformation passes have names registered
-// that can be used when providing a textual pass pipeline.
-//
-//===----------------------------------------------------------------------===//
-
-// NOTE: NO INCLUDE GUARD DESIRED!
-
-#ifndef MODULE_ANALYSIS
-#define MODULE_ANALYSIS(NAME, CREATE_PASS)
-#endif
-MODULE_ANALYSIS("lcg", LazyCallGraphAnalysis())
-MODULE_ANALYSIS("no-op-module", NoOpModuleAnalysis())
-#undef MODULE_ANALYSIS
-
-#ifndef MODULE_PASS
-#define MODULE_PASS(NAME, CREATE_PASS)
-#endif
-MODULE_PASS("invalidate<all>", InvalidateAllAnalysesPass())
-MODULE_PASS("no-op-module", NoOpModulePass())
-MODULE_PASS("print", PrintModulePass(dbgs()))
-MODULE_PASS("print-cg", LazyCallGraphPrinterPass(dbgs()))
-MODULE_PASS("verify", VerifierPass())
-#undef MODULE_PASS
-
-#ifndef CGSCC_ANALYSIS
-#define CGSCC_ANALYSIS(NAME, CREATE_PASS)
-#endif
-CGSCC_ANALYSIS("no-op-cgscc", NoOpCGSCCAnalysis())
-#undef CGSCC_ANALYSIS
-
-#ifndef CGSCC_PASS
-#define CGSCC_PASS(NAME, CREATE_PASS)
-#endif
-CGSCC_PASS("invalidate<all>", InvalidateAllAnalysesPass())
-CGSCC_PASS("no-op-cgscc", NoOpCGSCCPass())
-#undef CGSCC_PASS
-
-#ifndef FUNCTION_ANALYSIS
-#define FUNCTION_ANALYSIS(NAME, CREATE_PASS)
-#endif
-FUNCTION_ANALYSIS("domtree", DominatorTreeAnalysis())
-FUNCTION_ANALYSIS("no-op-function", NoOpFunctionAnalysis())
-#undef FUNCTION_ANALYSIS
-
-#ifndef FUNCTION_PASS
-#define FUNCTION_PASS(NAME, CREATE_PASS)
-#endif
-FUNCTION_PASS("invalidate<all>", InvalidateAllAnalysesPass())
-FUNCTION_PASS("no-op-function", NoOpFunctionPass())
-FUNCTION_PASS("print", PrintFunctionPass(dbgs()))
-FUNCTION_PASS("print<domtree>", DominatorTreePrinterPass(dbgs()))
-FUNCTION_PASS("verify", VerifierPass())
-FUNCTION_PASS("verify<domtree>", DominatorTreeVerifierPass())
-#undef FUNCTION_PASS
diff --git a/contrib/llvm/tools/opt/Passes.cpp b/contrib/llvm/tools/opt/Passes.cpp
deleted file mode 100644
index 518112a..0000000
--- a/contrib/llvm/tools/opt/Passes.cpp
+++ /dev/null
@@ -1,397 +0,0 @@
-//===- Passes.cpp - Parsing, selection, and running of passes -------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-/// \file
-///
-/// This file provides the infrastructure to parse and build a custom pass
-/// manager based on a commandline flag. It also provides helpers to aid in
-/// analyzing, debugging, and testing pass structures.
-///
-//===----------------------------------------------------------------------===//
-
-#include "Passes.h"
-#include "llvm/Analysis/CGSCCPassManager.h"
-#include "llvm/Analysis/LazyCallGraph.h"
-#include "llvm/IR/Dominators.h"
-#include "llvm/IR/IRPrintingPasses.h"
-#include "llvm/IR/PassManager.h"
-#include "llvm/IR/Verifier.h"
-#include "llvm/Support/Debug.h"
-
-using namespace llvm;
-
-namespace {
-
-/// \brief No-op module pass which does nothing.
-struct NoOpModulePass {
- PreservedAnalyses run(Module &M) { return PreservedAnalyses::all(); }
- static StringRef name() { return "NoOpModulePass"; }
-};
-
-/// \brief No-op module analysis.
-struct NoOpModuleAnalysis {
- struct Result {};
- Result run(Module &) { return Result(); }
- static StringRef name() { return "NoOpModuleAnalysis"; }
- static void *ID() { return (void *)&PassID; }
-private:
- static char PassID;
-};
-
-char NoOpModuleAnalysis::PassID;
-
-/// \brief No-op CGSCC pass which does nothing.
-struct NoOpCGSCCPass {
- PreservedAnalyses run(LazyCallGraph::SCC &C) {
- return PreservedAnalyses::all();
- }
- static StringRef name() { return "NoOpCGSCCPass"; }
-};
-
-/// \brief No-op CGSCC analysis.
-struct NoOpCGSCCAnalysis {
- struct Result {};
- Result run(LazyCallGraph::SCC &) { return Result(); }
- static StringRef name() { return "NoOpCGSCCAnalysis"; }
- static void *ID() { return (void *)&PassID; }
-private:
- static char PassID;
-};
-
-char NoOpCGSCCAnalysis::PassID;
-
-/// \brief No-op function pass which does nothing.
-struct NoOpFunctionPass {
- PreservedAnalyses run(Function &F) { return PreservedAnalyses::all(); }
- static StringRef name() { return "NoOpFunctionPass"; }
-};
-
-/// \brief No-op function analysis.
-struct NoOpFunctionAnalysis {
- struct Result {};
- Result run(Function &) { return Result(); }
- static StringRef name() { return "NoOpFunctionAnalysis"; }
- static void *ID() { return (void *)&PassID; }
-private:
- static char PassID;
-};
-
-char NoOpFunctionAnalysis::PassID;
-
-} // End anonymous namespace.
-
-void llvm::registerModuleAnalyses(ModuleAnalysisManager &MAM) {
-#define MODULE_ANALYSIS(NAME, CREATE_PASS) \
- MAM.registerPass(CREATE_PASS);
-#include "PassRegistry.def"
-}
-
-void llvm::registerCGSCCAnalyses(CGSCCAnalysisManager &CGAM) {
-#define CGSCC_ANALYSIS(NAME, CREATE_PASS) \
- CGAM.registerPass(CREATE_PASS);
-#include "PassRegistry.def"
-}
-
-void llvm::registerFunctionAnalyses(FunctionAnalysisManager &FAM) {
-#define FUNCTION_ANALYSIS(NAME, CREATE_PASS) \
- FAM.registerPass(CREATE_PASS);
-#include "PassRegistry.def"
-}
-
-#ifndef NDEBUG
-static bool isModulePassName(StringRef Name) {
-#define MODULE_PASS(NAME, CREATE_PASS) if (Name == NAME) return true;
-#define MODULE_ANALYSIS(NAME, CREATE_PASS) \
- if (Name == "require<" NAME ">" || Name == "invalidate<" NAME ">") \
- return true;
-#include "PassRegistry.def"
-
- return false;
-}
-#endif
-
-static bool isCGSCCPassName(StringRef Name) {
-#define CGSCC_PASS(NAME, CREATE_PASS) if (Name == NAME) return true;
-#define CGSCC_ANALYSIS(NAME, CREATE_PASS) \
- if (Name == "require<" NAME ">" || Name == "invalidate<" NAME ">") \
- return true;
-#include "PassRegistry.def"
-
- return false;
-}
-
-static bool isFunctionPassName(StringRef Name) {
-#define FUNCTION_PASS(NAME, CREATE_PASS) if (Name == NAME) return true;
-#define FUNCTION_ANALYSIS(NAME, CREATE_PASS) \
- if (Name == "require<" NAME ">" || Name == "invalidate<" NAME ">") \
- return true;
-#include "PassRegistry.def"
-
- return false;
-}
-
-static bool parseModulePassName(ModulePassManager &MPM, StringRef Name) {
-#define MODULE_PASS(NAME, CREATE_PASS) \
- if (Name == NAME) { \
- MPM.addPass(CREATE_PASS); \
- return true; \
- }
-#define MODULE_ANALYSIS(NAME, CREATE_PASS) \
- if (Name == "require<" NAME ">") { \
- MPM.addPass(RequireAnalysisPass<decltype(CREATE_PASS)>()); \
- return true; \
- } \
- if (Name == "invalidate<" NAME ">") { \
- MPM.addPass(InvalidateAnalysisPass<decltype(CREATE_PASS)>()); \
- return true; \
- }
-#include "PassRegistry.def"
-
- return false;
-}
-
-static bool parseCGSCCPassName(CGSCCPassManager &CGPM, StringRef Name) {
-#define CGSCC_PASS(NAME, CREATE_PASS) \
- if (Name == NAME) { \
- CGPM.addPass(CREATE_PASS); \
- return true; \
- }
-#define CGSCC_ANALYSIS(NAME, CREATE_PASS) \
- if (Name == "require<" NAME ">") { \
- CGPM.addPass(RequireAnalysisPass<decltype(CREATE_PASS)>()); \
- return true; \
- } \
- if (Name == "invalidate<" NAME ">") { \
- CGPM.addPass(InvalidateAnalysisPass<decltype(CREATE_PASS)>()); \
- return true; \
- }
-#include "PassRegistry.def"
-
- return false;
-}
-
-static bool parseFunctionPassName(FunctionPassManager &FPM, StringRef Name) {
-#define FUNCTION_PASS(NAME, CREATE_PASS) \
- if (Name == NAME) { \
- FPM.addPass(CREATE_PASS); \
- return true; \
- }
-#define FUNCTION_ANALYSIS(NAME, CREATE_PASS) \
- if (Name == "require<" NAME ">") { \
- FPM.addPass(RequireAnalysisPass<decltype(CREATE_PASS)>()); \
- return true; \
- } \
- if (Name == "invalidate<" NAME ">") { \
- FPM.addPass(InvalidateAnalysisPass<decltype(CREATE_PASS)>()); \
- return true; \
- }
-#include "PassRegistry.def"
-
- return false;
-}
-
-static bool parseFunctionPassPipeline(FunctionPassManager &FPM,
- StringRef &PipelineText,
- bool VerifyEachPass, bool DebugLogging) {
- for (;;) {
- // Parse nested pass managers by recursing.
- if (PipelineText.startswith("function(")) {
- FunctionPassManager NestedFPM(DebugLogging);
-
- // Parse the inner pipeline inte the nested manager.
- PipelineText = PipelineText.substr(strlen("function("));
- if (!parseFunctionPassPipeline(NestedFPM, PipelineText, VerifyEachPass,
- DebugLogging) ||
- PipelineText.empty())
- return false;
- assert(PipelineText[0] == ')');
- PipelineText = PipelineText.substr(1);
-
- // Add the nested pass manager with the appropriate adaptor.
- FPM.addPass(std::move(NestedFPM));
- } else {
- // Otherwise try to parse a pass name.
- size_t End = PipelineText.find_first_of(",)");
- if (!parseFunctionPassName(FPM, PipelineText.substr(0, End)))
- return false;
- if (VerifyEachPass)
- FPM.addPass(VerifierPass());
-
- PipelineText = PipelineText.substr(End);
- }
-
- if (PipelineText.empty() || PipelineText[0] == ')')
- return true;
-
- assert(PipelineText[0] == ',');
- PipelineText = PipelineText.substr(1);
- }
-}
-
-static bool parseCGSCCPassPipeline(CGSCCPassManager &CGPM,
- StringRef &PipelineText, bool VerifyEachPass,
- bool DebugLogging) {
- for (;;) {
- // Parse nested pass managers by recursing.
- if (PipelineText.startswith("cgscc(")) {
- CGSCCPassManager NestedCGPM(DebugLogging);
-
- // Parse the inner pipeline into the nested manager.
- PipelineText = PipelineText.substr(strlen("cgscc("));
- if (!parseCGSCCPassPipeline(NestedCGPM, PipelineText, VerifyEachPass,
- DebugLogging) ||
- PipelineText.empty())
- return false;
- assert(PipelineText[0] == ')');
- PipelineText = PipelineText.substr(1);
-
- // Add the nested pass manager with the appropriate adaptor.
- CGPM.addPass(std::move(NestedCGPM));
- } else if (PipelineText.startswith("function(")) {
- FunctionPassManager NestedFPM(DebugLogging);
-
- // Parse the inner pipeline inte the nested manager.
- PipelineText = PipelineText.substr(strlen("function("));
- if (!parseFunctionPassPipeline(NestedFPM, PipelineText, VerifyEachPass,
- DebugLogging) ||
- PipelineText.empty())
- return false;
- assert(PipelineText[0] == ')');
- PipelineText = PipelineText.substr(1);
-
- // Add the nested pass manager with the appropriate adaptor.
- CGPM.addPass(createCGSCCToFunctionPassAdaptor(std::move(NestedFPM)));
- } else {
- // Otherwise try to parse a pass name.
- size_t End = PipelineText.find_first_of(",)");
- if (!parseCGSCCPassName(CGPM, PipelineText.substr(0, End)))
- return false;
- // FIXME: No verifier support for CGSCC passes!
-
- PipelineText = PipelineText.substr(End);
- }
-
- if (PipelineText.empty() || PipelineText[0] == ')')
- return true;
-
- assert(PipelineText[0] == ',');
- PipelineText = PipelineText.substr(1);
- }
-}
-
-static bool parseModulePassPipeline(ModulePassManager &MPM,
- StringRef &PipelineText,
- bool VerifyEachPass, bool DebugLogging) {
- for (;;) {
- // Parse nested pass managers by recursing.
- if (PipelineText.startswith("module(")) {
- ModulePassManager NestedMPM(DebugLogging);
-
- // Parse the inner pipeline into the nested manager.
- PipelineText = PipelineText.substr(strlen("module("));
- if (!parseModulePassPipeline(NestedMPM, PipelineText, VerifyEachPass,
- DebugLogging) ||
- PipelineText.empty())
- return false;
- assert(PipelineText[0] == ')');
- PipelineText = PipelineText.substr(1);
-
- // Now add the nested manager as a module pass.
- MPM.addPass(std::move(NestedMPM));
- } else if (PipelineText.startswith("cgscc(")) {
- CGSCCPassManager NestedCGPM(DebugLogging);
-
- // Parse the inner pipeline inte the nested manager.
- PipelineText = PipelineText.substr(strlen("cgscc("));
- if (!parseCGSCCPassPipeline(NestedCGPM, PipelineText, VerifyEachPass,
- DebugLogging) ||
- PipelineText.empty())
- return false;
- assert(PipelineText[0] == ')');
- PipelineText = PipelineText.substr(1);
-
- // Add the nested pass manager with the appropriate adaptor.
- MPM.addPass(
- createModuleToPostOrderCGSCCPassAdaptor(std::move(NestedCGPM)));
- } else if (PipelineText.startswith("function(")) {
- FunctionPassManager NestedFPM(DebugLogging);
-
- // Parse the inner pipeline inte the nested manager.
- PipelineText = PipelineText.substr(strlen("function("));
- if (!parseFunctionPassPipeline(NestedFPM, PipelineText, VerifyEachPass,
- DebugLogging) ||
- PipelineText.empty())
- return false;
- assert(PipelineText[0] == ')');
- PipelineText = PipelineText.substr(1);
-
- // Add the nested pass manager with the appropriate adaptor.
- MPM.addPass(createModuleToFunctionPassAdaptor(std::move(NestedFPM)));
- } else {
- // Otherwise try to parse a pass name.
- size_t End = PipelineText.find_first_of(",)");
- if (!parseModulePassName(MPM, PipelineText.substr(0, End)))
- return false;
- if (VerifyEachPass)
- MPM.addPass(VerifierPass());
-
- PipelineText = PipelineText.substr(End);
- }
-
- if (PipelineText.empty() || PipelineText[0] == ')')
- return true;
-
- assert(PipelineText[0] == ',');
- PipelineText = PipelineText.substr(1);
- }
-}
-
-// Primary pass pipeline description parsing routine.
-// FIXME: Should this routine accept a TargetMachine or require the caller to
-// pre-populate the analysis managers with target-specific stuff?
-bool llvm::parsePassPipeline(ModulePassManager &MPM, StringRef PipelineText,
- bool VerifyEachPass, bool DebugLogging) {
- // By default, try to parse the pipeline as-if it were within an implicit
- // 'module(...)' pass pipeline. If this will parse at all, it needs to
- // consume the entire string.
- if (parseModulePassPipeline(MPM, PipelineText, VerifyEachPass, DebugLogging))
- return PipelineText.empty();
-
- // This isn't parsable as a module pipeline, look for the end of a pass name
- // and directly drop down to that layer.
- StringRef FirstName =
- PipelineText.substr(0, PipelineText.find_first_of(",)"));
- assert(!isModulePassName(FirstName) &&
- "Already handled all module pipeline options.");
-
- // If this looks like a CGSCC pass, parse the whole thing as a CGSCC
- // pipeline.
- if (isCGSCCPassName(FirstName)) {
- CGSCCPassManager CGPM(DebugLogging);
- if (!parseCGSCCPassPipeline(CGPM, PipelineText, VerifyEachPass,
- DebugLogging) ||
- !PipelineText.empty())
- return false;
- MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM)));
- return true;
- }
-
- // Similarly, if this looks like a Function pass, parse the whole thing as
- // a Function pipelien.
- if (isFunctionPassName(FirstName)) {
- FunctionPassManager FPM(DebugLogging);
- if (!parseFunctionPassPipeline(FPM, PipelineText, VerifyEachPass,
- DebugLogging) ||
- !PipelineText.empty())
- return false;
- MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
- return true;
- }
-
- return false;
-}
diff --git a/contrib/llvm/tools/opt/Passes.h b/contrib/llvm/tools/opt/Passes.h
deleted file mode 100644
index 623da9f..0000000
--- a/contrib/llvm/tools/opt/Passes.h
+++ /dev/null
@@ -1,78 +0,0 @@
-//===- Passes.h - Parsing, selection, and running of passes -----*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-/// \file
-///
-/// Interfaces for producing common pass manager configurations and parsing
-/// textual pass specifications.
-///
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_TOOLS_OPT_PASSES_H
-#define LLVM_TOOLS_OPT_PASSES_H
-
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Analysis/CGSCCPassManager.h"
-#include "llvm/IR/PassManager.h"
-
-namespace llvm {
-
-/// \brief Registers all available module analysis passes.
-///
-/// This is an interface that can be used to populate a \c
-/// ModuleAnalysisManager with all registered module analyses. Callers can
-/// still manually register any additional analyses.
-void registerModuleAnalyses(ModuleAnalysisManager &MAM);
-
-/// \brief Registers all available CGSCC analysis passes.
-///
-/// This is an interface that can be used to populate a \c CGSCCAnalysisManager
-/// with all registered CGSCC analyses. Callers can still manually register any
-/// additional analyses.
-void registerCGSCCAnalyses(CGSCCAnalysisManager &CGAM);
-
-/// \brief Registers all available function analysis passes.
-///
-/// This is an interface that can be used to populate a \c
-/// FunctionAnalysisManager with all registered function analyses. Callers can
-/// still manually register any additional analyses.
-void registerFunctionAnalyses(FunctionAnalysisManager &FAM);
-
-/// \brief Parse a textual pass pipeline description into a \c ModulePassManager.
-///
-/// The format of the textual pass pipeline description looks something like:
-///
-/// module(function(instcombine,sroa),dce,cgscc(inliner,function(...)),...)
-///
-/// Pass managers have ()s describing the nest structure of passes. All passes
-/// are comma separated. As a special shortcut, if the very first pass is not
-/// a module pass (as a module pass manager is), this will automatically form
-/// the shortest stack of pass managers that allow inserting that first pass.
-/// So, assuming function passes 'fpassN', CGSCC passes 'cgpassN', and loop passes
-/// 'lpassN', all of these are valid:
-///
-/// fpass1,fpass2,fpass3
-/// cgpass1,cgpass2,cgpass3
-/// lpass1,lpass2,lpass3
-///
-/// And they are equivalent to the following (resp.):
-///
-/// module(function(fpass1,fpass2,fpass3))
-/// module(cgscc(cgpass1,cgpass2,cgpass3))
-/// module(function(loop(lpass1,lpass2,lpass3)))
-///
-/// This shortcut is especially useful for debugging and testing small pass
-/// combinations. Note that these shortcuts don't introduce any other magic. If
-/// the sequence of passes aren't all the exact same kind of pass, it will be
-/// an error. You cannot mix different levels implicitly, you must explicitly
-/// form a pass manager in which to nest passes.
-bool parsePassPipeline(ModulePassManager &MPM, StringRef PipelineText,
- bool VerifyEachPass = true, bool DebugLogging = false);
-}
-
-#endif
diff --git a/contrib/llvm/tools/opt/opt.cpp b/contrib/llvm/tools/opt/opt.cpp
index 9867589..55426e7 100644
--- a/contrib/llvm/tools/opt/opt.cpp
+++ b/contrib/llvm/tools/opt/opt.cpp
@@ -20,9 +20,12 @@
#include "llvm/Analysis/CallGraphSCCPass.h"
#include "llvm/Analysis/LoopPass.h"
#include "llvm/Analysis/RegionPass.h"
+#include "llvm/Analysis/TargetLibraryInfo.h"
+#include "llvm/Analysis/TargetTransformInfo.h"
#include "llvm/Bitcode/BitcodeWriterPass.h"
#include "llvm/CodeGen/CommandFlags.h"
#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/DebugInfo.h"
#include "llvm/IR/IRPrintingPasses.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/LegacyPassNameParser.h"
@@ -33,9 +36,10 @@
#include "llvm/LinkAllIR.h"
#include "llvm/LinkAllPasses.h"
#include "llvm/MC/SubtargetFeature.h"
-#include "llvm/PassManager.h"
+#include "llvm/IR/LegacyPassManager.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Host.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/PluginLoader.h"
#include "llvm/Support/PrettyStackTrace.h"
@@ -45,7 +49,6 @@
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/ToolOutputFile.h"
-#include "llvm/Target/TargetLibraryInfo.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
#include <algorithm>
@@ -177,27 +180,33 @@ DefaultDataLayout("default-data-layout",
cl::desc("data layout string to use if not specified by module"),
cl::value_desc("layout-string"), cl::init(""));
+static cl::opt<bool> PreserveBitcodeUseListOrder(
+ "preserve-bc-uselistorder",
+ cl::desc("Preserve use-list order when writing LLVM bitcode."),
+ cl::init(true), cl::Hidden);
+static cl::opt<bool> PreserveAssemblyUseListOrder(
+ "preserve-ll-uselistorder",
+ cl::desc("Preserve use-list order when writing LLVM assembly."),
+ cl::init(false), cl::Hidden);
-static inline void addPass(PassManagerBase &PM, Pass *P) {
+static inline void addPass(legacy::PassManagerBase &PM, Pass *P) {
// Add the pass to the pass manager...
PM.add(P);
// If we are verifying all of the intermediate steps, add the verifier...
- if (VerifyEach) {
+ if (VerifyEach)
PM.add(createVerifierPass());
- PM.add(createDebugInfoVerifierPass());
- }
}
/// This routine adds optimization passes based on selected optimization level,
/// OptLevel.
///
/// OptLevel - Optimization Level
-static void AddOptimizationPasses(PassManagerBase &MPM,FunctionPassManager &FPM,
+static void AddOptimizationPasses(legacy::PassManagerBase &MPM,
+ legacy::FunctionPassManager &FPM,
unsigned OptLevel, unsigned SizeLevel) {
- FPM.add(createVerifierPass()); // Verify that input is correct
- MPM.add(createDebugInfoVerifierPass()); // Verify that debug info is correct
+ FPM.add(createVerifierPass()); // Verify that input is correct
PassManagerBuilder Builder;
Builder.OptLevel = OptLevel;
@@ -229,10 +238,9 @@ static void AddOptimizationPasses(PassManagerBase &MPM,FunctionPassManager &FPM,
Builder.populateModulePassManager(MPM);
}
-static void AddStandardLinkPasses(PassManagerBase &PM) {
+static void AddStandardLinkPasses(legacy::PassManagerBase &PM) {
PassManagerBuilder Builder;
Builder.VerifyInput = true;
- Builder.StripDebug = StripDebug;
if (DisableOptimizations)
Builder.OptLevel = 0;
@@ -245,7 +253,7 @@ static void AddStandardLinkPasses(PassManagerBase &PM) {
// CodeGen-related helper functions.
//
-CodeGenOpt::Level GetCodeGenOptLevel() {
+static CodeGenOpt::Level GetCodeGenOptLevel() {
if (OptLevelO1)
return CodeGenOpt::Less;
if (OptLevelO2)
@@ -256,7 +264,9 @@ CodeGenOpt::Level GetCodeGenOptLevel() {
}
// Returns the TargetMachine instance or zero if no triple is provided.
-static TargetMachine* GetTargetMachine(Triple TheTriple) {
+static TargetMachine* GetTargetMachine(Triple TheTriple, StringRef CPUStr,
+ StringRef FeaturesStr,
+ const TargetOptions &Options) {
std::string Error;
const Target *TheTarget = TargetRegistry::lookupTarget(MArch, TheTriple,
Error);
@@ -265,18 +275,8 @@ static TargetMachine* GetTargetMachine(Triple TheTriple) {
return nullptr;
}
- // Package up features to be passed to target/subtarget
- std::string FeaturesStr;
- if (MAttrs.size()) {
- SubtargetFeatures Features;
- for (unsigned i = 0; i != MAttrs.size(); ++i)
- Features.AddFeature(MAttrs[i]);
- FeaturesStr = Features.getString();
- }
-
return TheTarget->createTargetMachine(TheTriple.getTriple(),
- MCPU, FeaturesStr,
- InitTargetOptionsFromCodeGenFlags(),
+ CPUStr, FeaturesStr, Options,
RelocModel, CMModel,
GetCodeGenOptLevel());
}
@@ -322,6 +322,8 @@ int main(int argc, char **argv) {
initializeCodeGenPreparePass(Registry);
initializeAtomicExpandPass(Registry);
initializeRewriteSymbolsPass(Registry);
+ initializeWinEHPreparePass(Registry);
+ initializeDwarfEHPreparePass(Registry);
#ifdef LINK_POLLY_INTO_TOOLS
polly::initializePollyPasses(Registry);
@@ -345,6 +347,19 @@ int main(int argc, char **argv) {
return 1;
}
+ // Strip debug info before running the verifier.
+ if (StripDebug)
+ StripDebugInfo(*M);
+
+ // Immediately run the verifier to catch any problems before starting up the
+ // pass pipelines. Otherwise we can crash on broken code during
+ // doInitialization().
+ if (!NoVerify && verifyModule(*M, &errs())) {
+ errs() << argv[0] << ": " << InputFilename
+ << ": error: input module is broken!\n";
+ return 1;
+ }
+
// If we are supposed to override the target triple, do so now.
if (!TargetTriple.empty())
M->setTargetTriple(Triple::normalize(TargetTriple));
@@ -368,6 +383,23 @@ int main(int argc, char **argv) {
}
}
+ Triple ModuleTriple(M->getTargetTriple());
+ std::string CPUStr, FeaturesStr;
+ TargetMachine *Machine = nullptr;
+ const TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
+
+ if (ModuleTriple.getArch()) {
+ CPUStr = getCPUStr();
+ FeaturesStr = getFeaturesStr();
+ Machine = GetTargetMachine(ModuleTriple, CPUStr, FeaturesStr, Options);
+ }
+
+ std::unique_ptr<TargetMachine> TM(Machine);
+
+ // Override function attributes based on CPUStr, FeaturesStr, and command line
+ // flags.
+ setFunctionAttributes(CPUStr, FeaturesStr, *M);
+
// If the output is set to be emitted to standard out, and standard out is a
// console, print out a warning message and refuse to do it. We don't
// impress anyone by spewing tons of binary goo to a terminal.
@@ -389,8 +421,9 @@ int main(int argc, char **argv) {
// The user has asked to use the new pass manager and provided a pipeline
// string. Hand off the rest of the functionality to the new code for that
// layer.
- return runPassPipeline(argv[0], Context, *M, Out.get(), PassPipeline,
- OK, VK)
+ return runPassPipeline(argv[0], Context, *M, TM.get(), Out.get(),
+ PassPipeline, OK, VK, PreserveAssemblyUseListOrder,
+ PreserveBitcodeUseListOrder)
? 0
: 1;
}
@@ -398,44 +431,31 @@ int main(int argc, char **argv) {
// Create a PassManager to hold and optimize the collection of passes we are
// about to build.
//
- PassManager Passes;
+ legacy::PassManager Passes;
// Add an appropriate TargetLibraryInfo pass for the module's triple.
- TargetLibraryInfo *TLI = new TargetLibraryInfo(Triple(M->getTargetTriple()));
+ TargetLibraryInfoImpl TLII(ModuleTriple);
// The -disable-simplify-libcalls flag actually disables all builtin optzns.
if (DisableSimplifyLibCalls)
- TLI->disableAllFunctions();
- Passes.add(TLI);
+ TLII.disableAllFunctions();
+ Passes.add(new TargetLibraryInfoWrapperPass(TLII));
// Add an appropriate DataLayout instance for this module.
- const DataLayout *DL = M->getDataLayout();
- if (!DL && !DefaultDataLayout.empty()) {
+ const DataLayout &DL = M->getDataLayout();
+ if (DL.isDefault() && !DefaultDataLayout.empty()) {
M->setDataLayout(DefaultDataLayout);
- DL = M->getDataLayout();
}
- if (DL)
- Passes.add(new DataLayoutPass());
-
- Triple ModuleTriple(M->getTargetTriple());
- TargetMachine *Machine = nullptr;
- if (ModuleTriple.getArch())
- Machine = GetTargetMachine(Triple(ModuleTriple));
- std::unique_ptr<TargetMachine> TM(Machine);
-
// Add internal analysis passes from the target machine.
- if (TM)
- TM->addAnalysisPasses(Passes);
+ Passes.add(createTargetTransformInfoWrapperPass(TM ? TM->getTargetIRAnalysis()
+ : TargetIRAnalysis()));
- std::unique_ptr<FunctionPassManager> FPasses;
+ std::unique_ptr<legacy::FunctionPassManager> FPasses;
if (OptLevelO1 || OptLevelO2 || OptLevelOs || OptLevelOz || OptLevelO3) {
- FPasses.reset(new FunctionPassManager(M.get()));
- if (DL)
- FPasses->add(new DataLayoutPass());
- if (TM)
- TM->addAnalysisPasses(*FPasses);
-
+ FPasses.reset(new legacy::FunctionPassManager(M.get()));
+ FPasses->add(createTargetTransformInfoWrapperPass(
+ TM ? TM->getTargetIRAnalysis() : TargetIRAnalysis()));
}
if (PrintBreakpoints) {
@@ -456,10 +476,6 @@ int main(int argc, char **argv) {
NoOutput = true;
}
- // If the -strip-debug command line option was specified, add it.
- if (StripDebug)
- addPass(Passes, createStripSymbolsPass(true));
-
// Create a new optimization pass for each one specified on the command line
for (unsigned i = 0; i < PassList.size(); ++i) {
if (StandardLinkOpts &&
@@ -531,7 +547,8 @@ int main(int argc, char **argv) {
}
if (PrintEachXForm)
- Passes.add(createPrintModulePass(errs()));
+ Passes.add(
+ createPrintModulePass(errs(), "", PreserveAssemblyUseListOrder));
}
if (StandardLinkOpts) {
@@ -562,17 +579,17 @@ int main(int argc, char **argv) {
}
// Check that the module is well formed on completion of optimization
- if (!NoVerify && !VerifyEach) {
+ if (!NoVerify && !VerifyEach)
Passes.add(createVerifierPass());
- Passes.add(createDebugInfoVerifierPass());
- }
// Write bitcode or assembly to the output as the last step...
if (!NoOutput && !AnalyzeOnly) {
if (OutputAssembly)
- Passes.add(createPrintModulePass(Out->os()));
+ Passes.add(
+ createPrintModulePass(Out->os(), "", PreserveAssemblyUseListOrder));
else
- Passes.add(createBitcodeWriterPass(Out->os()));
+ Passes.add(
+ createBitcodeWriterPass(Out->os(), PreserveBitcodeUseListOrder));
}
// Before executing passes, print the final values of the LLVM options.
OpenPOWER on IntegriCloud