aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/bugpoint-passes/CMakeLists.txt4
-rw-r--r--tools/bugpoint/CMakeLists.txt2
-rw-r--r--tools/bugpoint/ExecutionDriver.cpp2
-rw-r--r--tools/bugpoint/LLVMBuild.txt2
-rw-r--r--tools/bugpoint/Makefile2
-rw-r--r--tools/bugpoint/ToolRunner.cpp2
-rw-r--r--tools/bugpoint/bugpoint.cpp3
-rw-r--r--tools/lli/CMakeLists.txt2
-rw-r--r--tools/lli/Makefile2
-rw-r--r--tools/lli/RecordingMemoryManager.cpp47
-rw-r--r--tools/lli/RecordingMemoryManager.h8
-rw-r--r--tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp169
-rw-r--r--tools/llvm-dwarfdump/llvm-dwarfdump.cpp32
-rw-r--r--tools/llvm-jitlistener/CMakeLists.txt1
-rw-r--r--tools/llvm-jitlistener/Makefile2
-rw-r--r--tools/llvm-jitlistener/llvm-jitlistener.cpp2
-rw-r--r--tools/llvm-mc/llvm-mc.cpp17
-rw-r--r--tools/llvm-nm/llvm-nm.cpp4
-rw-r--r--tools/llvm-objdump/ELFDump.cpp34
-rw-r--r--tools/llvm-objdump/llvm-objdump.cpp13
-rw-r--r--tools/llvm-readobj/CMakeLists.txt1
-rw-r--r--tools/llvm-readobj/ELF.cpp196
-rw-r--r--tools/llvm-readobj/llvm-readobj.cpp23
-rw-r--r--tools/llvm-readobj/llvm-readobj.h22
-rw-r--r--tools/llvm-rtdyld/CMakeLists.txt2
-rw-r--r--tools/llvm-rtdyld/Makefile2
-rw-r--r--tools/llvm-rtdyld/llvm-rtdyld.cpp68
-rw-r--r--tools/llvm-stress/llvm-stress.cpp26
-rw-r--r--tools/llvm-symbolizer/CMakeLists.txt1
-rw-r--r--tools/llvm-symbolizer/LLVMSymbolize.cpp287
-rw-r--r--tools/llvm-symbolizer/LLVMSymbolize.h97
-rw-r--r--tools/llvm-symbolizer/llvm-symbolizer.cpp310
-rw-r--r--tools/lto/LTOCodeGenerator.cpp1
-rw-r--r--tools/lto/LTOModule.cpp8
-rw-r--r--tools/lto/Makefile2
-rw-r--r--tools/macho-dump/macho-dump.cpp30
-rw-r--r--tools/opt/CMakeLists.txt2
-rw-r--r--tools/opt/GraphPrinters.cpp73
-rw-r--r--tools/opt/LLVMBuild.txt2
-rw-r--r--tools/opt/Makefile2
-rw-r--r--tools/opt/opt.cpp3
41 files changed, 1018 insertions, 490 deletions
diff --git a/tools/bugpoint-passes/CMakeLists.txt b/tools/bugpoint-passes/CMakeLists.txt
index b2f1bb5..05f190a 100644
--- a/tools/bugpoint-passes/CMakeLists.txt
+++ b/tools/bugpoint-passes/CMakeLists.txt
@@ -1,3 +1,7 @@
+if( NOT LLVM_BUILD_TOOLS )
+ set(EXCLUDE_FROM_ALL ON)
+endif()
+
add_llvm_loadable_module( BugpointPasses
TestPasses.cpp
)
diff --git a/tools/bugpoint/CMakeLists.txt b/tools/bugpoint/CMakeLists.txt
index ee2235b..3c5e64f 100644
--- a/tools/bugpoint/CMakeLists.txt
+++ b/tools/bugpoint/CMakeLists.txt
@@ -1,5 +1,5 @@
set(LLVM_LINK_COMPONENTS asmparser instrumentation scalaropts ipo
- linker bitreader bitwriter vectorize)
+ linker bitreader bitwriter vectorize objcarcopts)
add_llvm_tool(bugpoint
BugDriver.cpp
diff --git a/tools/bugpoint/ExecutionDriver.cpp b/tools/bugpoint/ExecutionDriver.cpp
index 218a559..da36045 100644
--- a/tools/bugpoint/ExecutionDriver.cpp
+++ b/tools/bugpoint/ExecutionDriver.cpp
@@ -230,7 +230,7 @@ bool BugDriver::initializeExecutionEnvironment() {
}
if (!SafeInterpreter) {
SafeInterpreterSel = AutoPick;
- Message = "Sorry, I can't automatically select an interpreter!\n";
+ Message = "Sorry, I can't automatically select a safe interpreter!\n";
}
break;
case RunLLC:
diff --git a/tools/bugpoint/LLVMBuild.txt b/tools/bugpoint/LLVMBuild.txt
index 549d9d0..e03c594 100644
--- a/tools/bugpoint/LLVMBuild.txt
+++ b/tools/bugpoint/LLVMBuild.txt
@@ -19,4 +19,4 @@
type = Tool
name = bugpoint
parent = Tools
-required_libraries = AsmParser BitReader BitWriter IPO Instrumentation Linker Scalar
+required_libraries = AsmParser BitReader BitWriter IPO Instrumentation Linker Scalar ObjCARC
diff --git a/tools/bugpoint/Makefile b/tools/bugpoint/Makefile
index 34f4bdd..65ffc13 100644
--- a/tools/bugpoint/Makefile
+++ b/tools/bugpoint/Makefile
@@ -10,6 +10,6 @@
LEVEL := ../..
TOOLNAME := bugpoint
LINK_COMPONENTS := asmparser instrumentation scalaropts ipo linker bitreader \
- bitwriter vectorize
+ bitwriter vectorize objcarcopts
include $(LEVEL)/Makefile.common
diff --git a/tools/bugpoint/ToolRunner.cpp b/tools/bugpoint/ToolRunner.cpp
index e7d3978..735061d 100644
--- a/tools/bugpoint/ToolRunner.cpp
+++ b/tools/bugpoint/ToolRunner.cpp
@@ -531,12 +531,12 @@ LLC *AbstractInterpreter::createLLC(const char *Argv0,
return 0;
}
- Message = "Found llc: " + LLCPath + "\n";
GCC *gcc = GCC::create(Message, GCCBinary, GCCArgs);
if (!gcc) {
errs() << Message << "\n";
exit(1);
}
+ Message = "Found llc: " + LLCPath + "\n";
return new LLC(LLCPath, gcc, Args, UseIntegratedAssembler);
}
diff --git a/tools/bugpoint/bugpoint.cpp b/tools/bugpoint/bugpoint.cpp
index 3049421..5e8fdd1 100644
--- a/tools/bugpoint/bugpoint.cpp
+++ b/tools/bugpoint/bugpoint.cpp
@@ -16,8 +16,8 @@
#include "BugDriver.h"
#include "ToolRunner.h"
#include "llvm/IR/LLVMContext.h"
+#include "llvm/LinkAllIR.h"
#include "llvm/LinkAllPasses.h"
-#include "llvm/LinkAllVMCore.h"
#include "llvm/PassManager.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ManagedStatic.h"
@@ -120,6 +120,7 @@ int main(int argc, char **argv) {
PassRegistry &Registry = *PassRegistry::getPassRegistry();
initializeCore(Registry);
initializeScalarOpts(Registry);
+ initializeObjCARCOpts(Registry);
initializeVectorization(Registry);
initializeIPO(Registry);
initializeAnalysis(Registry);
diff --git a/tools/lli/CMakeLists.txt b/tools/lli/CMakeLists.txt
index ed479f5..356233f 100644
--- a/tools/lli/CMakeLists.txt
+++ b/tools/lli/CMakeLists.txt
@@ -11,7 +11,9 @@ endif( LLVM_USE_OPROFILE )
if( LLVM_USE_INTEL_JITEVENTS )
set(LLVM_LINK_COMPONENTS
${LLVM_LINK_COMPONENTS}
+ DebugInfo
IntelJITEvents
+ Object
)
endif( LLVM_USE_INTEL_JITEVENTS )
diff --git a/tools/lli/Makefile b/tools/lli/Makefile
index 31f3ab8..85ac6b4 100644
--- a/tools/lli/Makefile
+++ b/tools/lli/Makefile
@@ -17,7 +17,7 @@ LINK_COMPONENTS := mcjit jit interpreter nativecodegen bitreader asmparser selec
# If Intel JIT Events support is confiured, link against the LLVM Intel JIT
# Events interface library
ifeq ($(USE_INTEL_JITEVENTS), 1)
- LINK_COMPONENTS += inteljitevents
+ LINK_COMPONENTS += debuginfo inteljitevents object
endif
# If oprofile support is confiured, link against the LLVM oprofile interface
diff --git a/tools/lli/RecordingMemoryManager.cpp b/tools/lli/RecordingMemoryManager.cpp
index 75cb978..e4d992d 100644
--- a/tools/lli/RecordingMemoryManager.cpp
+++ b/tools/lli/RecordingMemoryManager.cpp
@@ -15,16 +15,26 @@
#include "RecordingMemoryManager.h"
using namespace llvm;
+RecordingMemoryManager::~RecordingMemoryManager() {
+ for (SmallVectorImpl<Allocation>::iterator
+ I = AllocatedCodeMem.begin(), E = AllocatedCodeMem.end();
+ I != E; ++I)
+ sys::Memory::releaseMappedMemory(I->first);
+ for (SmallVectorImpl<Allocation>::iterator
+ I = AllocatedDataMem.begin(), E = AllocatedDataMem.end();
+ I != E; ++I)
+ sys::Memory::releaseMappedMemory(I->first);
+}
+
uint8_t *RecordingMemoryManager::
allocateCodeSection(uintptr_t Size, unsigned Alignment, unsigned SectionID) {
// The recording memory manager is just a local copy of the remote target.
// The alignment requirement is just stored here for later use. Regular
- // heap storage is sufficient here.
- void *Addr = malloc(Size);
- assert(Addr && "malloc() failure!");
- sys::MemoryBlock Block(Addr, Size);
+ // heap storage is sufficient here, but we're using mapped memory to work
+ // around a bug in MCJIT.
+ sys::MemoryBlock Block = allocateSection(Size);
AllocatedCodeMem.push_back(Allocation(Block, Alignment));
- return (uint8_t*)Addr;
+ return (uint8_t*)Block.base();
}
uint8_t *RecordingMemoryManager::
@@ -32,13 +42,30 @@ allocateDataSection(uintptr_t Size, unsigned Alignment,
unsigned SectionID, bool IsReadOnly) {
// The recording memory manager is just a local copy of the remote target.
// The alignment requirement is just stored here for later use. Regular
- // heap storage is sufficient here.
- void *Addr = malloc(Size);
- assert(Addr && "malloc() failure!");
- sys::MemoryBlock Block(Addr, Size);
+ // heap storage is sufficient here, but we're using mapped memory to work
+ // around a bug in MCJIT.
+ sys::MemoryBlock Block = allocateSection(Size);
AllocatedDataMem.push_back(Allocation(Block, Alignment));
- return (uint8_t*)Addr;
+ return (uint8_t*)Block.base();
+}
+
+sys::MemoryBlock RecordingMemoryManager::allocateSection(uintptr_t Size) {
+ error_code ec;
+ sys::MemoryBlock MB = sys::Memory::allocateMappedMemory(Size,
+ &Near,
+ sys::Memory::MF_READ |
+ sys::Memory::MF_WRITE,
+ ec);
+ assert(!ec && MB.base());
+
+ // FIXME: This is part of a work around to keep sections near one another
+ // when MCJIT performs relocations after code emission but before
+ // the generated code is moved to the remote target.
+ // Save this address as the basis for our next request
+ Near = MB;
+ return MB;
}
+
void RecordingMemoryManager::setMemoryWritable() { llvm_unreachable("Unexpected!"); }
void RecordingMemoryManager::setMemoryExecutable() { llvm_unreachable("Unexpected!"); }
void RecordingMemoryManager::setPoisonMemory(bool poison) { llvm_unreachable("Unexpected!"); }
diff --git a/tools/lli/RecordingMemoryManager.h b/tools/lli/RecordingMemoryManager.h
index 20fd0c2..991f535 100644
--- a/tools/lli/RecordingMemoryManager.h
+++ b/tools/lli/RecordingMemoryManager.h
@@ -31,9 +31,15 @@ private:
SmallVector<Allocation, 16> AllocatedDataMem;
SmallVector<Allocation, 16> AllocatedCodeMem;
+ // FIXME: This is part of a work around to keep sections near one another
+ // when MCJIT performs relocations after code emission but before
+ // the generated code is moved to the remote target.
+ sys::MemoryBlock Near;
+ sys::MemoryBlock allocateSection(uintptr_t Size);
+
public:
RecordingMemoryManager() {}
- virtual ~RecordingMemoryManager() {}
+ virtual ~RecordingMemoryManager();
typedef SmallVectorImpl<Allocation>::const_iterator const_data_iterator;
typedef SmallVectorImpl<Allocation>::const_iterator const_code_iterator;
diff --git a/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp b/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp
index 46b687e..99479a4 100644
--- a/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp
+++ b/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp
@@ -98,16 +98,17 @@ static const char *GetBlockName(unsigned BlockID,
if (CurStreamType != LLVMIRBitstream) return 0;
switch (BlockID) {
- default: return 0;
- case bitc::MODULE_BLOCK_ID: return "MODULE_BLOCK";
- case bitc::PARAMATTR_BLOCK_ID: return "PARAMATTR_BLOCK";
- case bitc::TYPE_BLOCK_ID_NEW: return "TYPE_BLOCK_ID";
- case bitc::CONSTANTS_BLOCK_ID: return "CONSTANTS_BLOCK";
- case bitc::FUNCTION_BLOCK_ID: return "FUNCTION_BLOCK";
- case bitc::VALUE_SYMTAB_BLOCK_ID: return "VALUE_SYMTAB";
- case bitc::METADATA_BLOCK_ID: return "METADATA_BLOCK";
- case bitc::METADATA_ATTACHMENT_ID: return "METADATA_ATTACHMENT_BLOCK";
- case bitc::USELIST_BLOCK_ID: return "USELIST_BLOCK_ID";
+ default: return 0;
+ case bitc::MODULE_BLOCK_ID: return "MODULE_BLOCK";
+ case bitc::PARAMATTR_BLOCK_ID: return "PARAMATTR_BLOCK";
+ case bitc::PARAMATTR_GROUP_BLOCK_ID: return "PARAMATTR_GROUP_BLOCK_ID";
+ case bitc::TYPE_BLOCK_ID_NEW: return "TYPE_BLOCK_ID";
+ case bitc::CONSTANTS_BLOCK_ID: return "CONSTANTS_BLOCK";
+ case bitc::FUNCTION_BLOCK_ID: return "FUNCTION_BLOCK";
+ case bitc::VALUE_SYMTAB_BLOCK_ID: return "VALUE_SYMTAB";
+ case bitc::METADATA_BLOCK_ID: return "METADATA_BLOCK";
+ case bitc::METADATA_ATTACHMENT_ID: return "METADATA_ATTACHMENT_BLOCK";
+ case bitc::USELIST_BLOCK_ID: return "USELIST_BLOCK_ID";
}
}
@@ -159,7 +160,9 @@ static const char *GetCodeName(unsigned CodeID, unsigned BlockID,
case bitc::PARAMATTR_BLOCK_ID:
switch (CodeID) {
default: return 0;
- case bitc::PARAMATTR_CODE_ENTRY: return "ENTRY";
+ case bitc::PARAMATTR_CODE_ENTRY_OLD: return "ENTRY";
+ case bitc::PARAMATTR_CODE_ENTRY: return "ENTRY";
+ case bitc::PARAMATTR_GRP_CODE_ENTRY: return "ENTRY";
}
case bitc::TYPE_BLOCK_ID_NEW:
switch (CodeID) {
@@ -318,10 +321,10 @@ static bool Error(const std::string &Err) {
}
/// ParseBlock - Read a block, updating statistics, etc.
-static bool ParseBlock(BitstreamCursor &Stream, unsigned IndentLevel) {
+static bool ParseBlock(BitstreamCursor &Stream, unsigned BlockID,
+ unsigned IndentLevel) {
std::string Indent(IndentLevel*2, ' ');
uint64_t BlockBitStart = Stream.GetCurrentBitNo();
- unsigned BlockID = Stream.ReadSubBlockID();
// Get the statistics for this BlockID.
PerBlockIDStats &BlockStats = BlockIDStats[BlockID];
@@ -354,7 +357,7 @@ static bool ParseBlock(BitstreamCursor &Stream, unsigned IndentLevel) {
outs() << " BlockID=" << BlockID;
outs() << " NumWords=" << NumWords
- << " BlockCodeSize=" << Stream.GetAbbrevIDWidth() << ">\n";
+ << " BlockCodeSize=" << Stream.getAbbrevIDWidth() << ">\n";
}
SmallVector<uint64_t, 64> Record;
@@ -366,12 +369,13 @@ static bool ParseBlock(BitstreamCursor &Stream, unsigned IndentLevel) {
uint64_t RecordStartBit = Stream.GetCurrentBitNo();
- // Read the code for this record.
- unsigned AbbrevID = Stream.ReadCode();
- switch (AbbrevID) {
- case bitc::END_BLOCK: {
- if (Stream.ReadBlockEnd())
- return Error("Error at end of block");
+ BitstreamEntry Entry =
+ Stream.advance(BitstreamCursor::AF_DontAutoprocessAbbrevs);
+
+ switch (Entry.Kind) {
+ case BitstreamEntry::Error:
+ return Error("malformed bitcode file");
+ case BitstreamEntry::EndBlock: {
uint64_t BlockBitEnd = Stream.GetCurrentBitNo();
BlockStats.NumBits += BlockBitEnd-BlockBitStart;
if (Dump) {
@@ -383,80 +387,81 @@ static bool ParseBlock(BitstreamCursor &Stream, unsigned IndentLevel) {
}
return false;
}
- case bitc::ENTER_SUBBLOCK: {
+
+ case BitstreamEntry::SubBlock: {
uint64_t SubBlockBitStart = Stream.GetCurrentBitNo();
- if (ParseBlock(Stream, IndentLevel+1))
+ if (ParseBlock(Stream, Entry.ID, IndentLevel+1))
return true;
++BlockStats.NumSubBlocks;
uint64_t SubBlockBitEnd = Stream.GetCurrentBitNo();
-
+
// Don't include subblock sizes in the size of this block.
BlockBitStart += SubBlockBitEnd-SubBlockBitStart;
+ continue;
+ }
+ case BitstreamEntry::Record:
+ // The interesting case.
break;
}
- case bitc::DEFINE_ABBREV:
+
+ if (Entry.ID == bitc::DEFINE_ABBREV) {
Stream.ReadAbbrevRecord();
++BlockStats.NumAbbrevs;
- break;
- default:
- Record.clear();
-
- ++BlockStats.NumRecords;
- if (AbbrevID != bitc::UNABBREV_RECORD)
- ++BlockStats.NumAbbreviatedRecords;
-
- const char *BlobStart = 0;
- unsigned BlobLen = 0;
- unsigned Code = Stream.ReadRecord(AbbrevID, Record, BlobStart, BlobLen);
-
-
-
- // Increment the # occurrences of this code.
- if (BlockStats.CodeFreq.size() <= Code)
- BlockStats.CodeFreq.resize(Code+1);
- BlockStats.CodeFreq[Code].NumInstances++;
- BlockStats.CodeFreq[Code].TotalBits +=
- Stream.GetCurrentBitNo()-RecordStartBit;
- if (AbbrevID != bitc::UNABBREV_RECORD)
- BlockStats.CodeFreq[Code].NumAbbrev++;
+ continue;
+ }
+
+ Record.clear();
+
+ ++BlockStats.NumRecords;
+
+ StringRef Blob;
+ unsigned Code = Stream.readRecord(Entry.ID, Record, &Blob);
+
+ // Increment the # occurrences of this code.
+ if (BlockStats.CodeFreq.size() <= Code)
+ BlockStats.CodeFreq.resize(Code+1);
+ BlockStats.CodeFreq[Code].NumInstances++;
+ BlockStats.CodeFreq[Code].TotalBits +=
+ Stream.GetCurrentBitNo()-RecordStartBit;
+ if (Entry.ID != bitc::UNABBREV_RECORD) {
+ BlockStats.CodeFreq[Code].NumAbbrev++;
+ ++BlockStats.NumAbbreviatedRecords;
+ }
- if (Dump) {
- outs() << Indent << " <";
- if (const char *CodeName =
- GetCodeName(Code, BlockID, *Stream.getBitStreamReader()))
- outs() << CodeName;
- else
- outs() << "UnknownCode" << Code;
- if (NonSymbolic &&
+ if (Dump) {
+ outs() << Indent << " <";
+ if (const char *CodeName =
GetCodeName(Code, BlockID, *Stream.getBitStreamReader()))
- outs() << " codeid=" << Code;
- if (AbbrevID != bitc::UNABBREV_RECORD)
- outs() << " abbrevid=" << AbbrevID;
-
- for (unsigned i = 0, e = Record.size(); i != e; ++i)
- outs() << " op" << i << "=" << (int64_t)Record[i];
-
- outs() << "/>";
-
- if (BlobStart) {
- outs() << " blob data = ";
- bool BlobIsPrintable = true;
- for (unsigned i = 0; i != BlobLen; ++i)
- if (!isprint(BlobStart[i])) {
- BlobIsPrintable = false;
- break;
- }
-
- if (BlobIsPrintable)
- outs() << "'" << std::string(BlobStart, BlobStart+BlobLen) <<"'";
- else
- outs() << "unprintable, " << BlobLen << " bytes.";
- }
-
- outs() << "\n";
+ outs() << CodeName;
+ else
+ outs() << "UnknownCode" << Code;
+ if (NonSymbolic &&
+ GetCodeName(Code, BlockID, *Stream.getBitStreamReader()))
+ outs() << " codeid=" << Code;
+ if (Entry.ID != bitc::UNABBREV_RECORD)
+ outs() << " abbrevid=" << Entry.ID;
+
+ for (unsigned i = 0, e = Record.size(); i != e; ++i)
+ outs() << " op" << i << "=" << (int64_t)Record[i];
+
+ outs() << "/>";
+
+ 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.";
}
- break;
+ outs() << "\n";
}
}
}
@@ -519,7 +524,9 @@ static int AnalyzeBitcode() {
if (Code != bitc::ENTER_SUBBLOCK)
return Error("Invalid record at top-level");
- if (ParseBlock(Stream, 0))
+ unsigned BlockID = Stream.ReadSubBlockID();
+
+ if (ParseBlock(Stream, BlockID, 0))
return true;
++NumTopBlocks;
}
diff --git a/tools/llvm-dwarfdump/llvm-dwarfdump.cpp b/tools/llvm-dwarfdump/llvm-dwarfdump.cpp
index 34302fa..8094856 100644
--- a/tools/llvm-dwarfdump/llvm-dwarfdump.cpp
+++ b/tools/llvm-dwarfdump/llvm-dwarfdump.cpp
@@ -52,6 +52,25 @@ static cl::opt<bool>
PrintInlining("inlining", cl::init(false),
cl::desc("Print all inlined frames for a given address"));
+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_Aranges, "aranges", ".debug_aranges"),
+ clEnumValN(DIDT_Info, "info", ".debug_info"),
+ clEnumValN(DIDT_InfoDwo, "info.dwo", ".debug_info.dwo"),
+ clEnumValN(DIDT_Line, "line", ".debug_line"),
+ clEnumValN(DIDT_Frames, "frames", ".debug_frame"),
+ clEnumValN(DIDT_Ranges, "ranges", ".debug_ranges"),
+ clEnumValN(DIDT_Pubnames, "pubnames", ".debug_pubnames"),
+ 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 PrintDILineInfo(DILineInfo dli) {
if (PrintFunctions)
outs() << (dli.getFunctionName() ? dli.getFunctionName() : "<unknown>")
@@ -69,13 +88,18 @@ static void DumpInput(const StringRef &Filename) {
}
OwningPtr<ObjectFile> Obj(ObjectFile::createObjectFile(Buff.take()));
- OwningPtr<DIContext> dictx(DIContext::getDWARFContext(Obj.get()));
+ if (!Obj) {
+ errs() << Filename << ": Unknown object file format\n";
+ return;
+ }
+
+ OwningPtr<DIContext> DICtx(DIContext::getDWARFContext(Obj.get()));
if (Address == -1ULL) {
outs() << Filename
<< ":\tfile format " << Obj->getFileFormatName() << "\n\n";
// Dump the complete DWARF structure.
- dictx->dump(outs());
+ DICtx->dump(outs(), DumpType);
} else {
// Print line info for the specified address.
int SpecFlags = DILineInfoSpecifier::FileLineInfo |
@@ -84,7 +108,7 @@ static void DumpInput(const StringRef &Filename) {
SpecFlags |= DILineInfoSpecifier::FunctionName;
if (PrintInlining) {
DIInliningInfo InliningInfo =
- dictx->getInliningInfoForAddress(Address, SpecFlags);
+ DICtx->getInliningInfoForAddress(Address, SpecFlags);
uint32_t n = InliningInfo.getNumberOfFrames();
if (n == 0) {
// Print one empty debug line info in any case.
@@ -96,7 +120,7 @@ static void DumpInput(const StringRef &Filename) {
}
}
} else {
- DILineInfo dli = dictx->getLineInfoForAddress(Address, SpecFlags);
+ DILineInfo dli = DICtx->getLineInfoForAddress(Address, SpecFlags);
PrintDILineInfo(dli);
}
}
diff --git a/tools/llvm-jitlistener/CMakeLists.txt b/tools/llvm-jitlistener/CMakeLists.txt
index 57a4a0c..d429af9 100644
--- a/tools/llvm-jitlistener/CMakeLists.txt
+++ b/tools/llvm-jitlistener/CMakeLists.txt
@@ -6,6 +6,7 @@ include_directories( ${LLVM_INTEL_JITEVENTS_INCDIR} )
set(LLVM_LINK_COMPONENTS
asmparser
bitreader
+ debuginfo
inteljitevents
interpreter
jit
diff --git a/tools/llvm-jitlistener/Makefile b/tools/llvm-jitlistener/Makefile
index 0971e6a..3018235 100644
--- a/tools/llvm-jitlistener/Makefile
+++ b/tools/llvm-jitlistener/Makefile
@@ -18,7 +18,7 @@ LINK_COMPONENTS := mcjit jit interpreter nativecodegen bitreader asmparser selec
# Events interface library. If not, this tool will do nothing useful, but it
# will build correctly.
ifeq ($(USE_INTEL_JITEVENTS), 1)
- LINK_COMPONENTS += inteljitevents
+ LINK_COMPONENTS += debuginfo inteljitevents
endif
# This tool has no plugins, optimize startup time.
diff --git a/tools/llvm-jitlistener/llvm-jitlistener.cpp b/tools/llvm-jitlistener/llvm-jitlistener.cpp
index 2f72e42..d6f5032 100644
--- a/tools/llvm-jitlistener/llvm-jitlistener.cpp
+++ b/tools/llvm-jitlistener/llvm-jitlistener.cpp
@@ -137,7 +137,7 @@ protected:
// Override the triple to generate ELF on Windows since that's supported
Triple Tuple(TheModule->getTargetTriple());
if (Tuple.getTriple().empty())
- Tuple.setTriple(LLVM_HOSTTRIPLE);
+ Tuple.setTriple(sys::getProcessTriple());
if (Tuple.isOSWindows() && Triple::ELF != Tuple.getEnvironment()) {
Tuple.setEnvironment(Triple::ELF);
diff --git a/tools/llvm-mc/llvm-mc.cpp b/tools/llvm-mc/llvm-mc.cpp
index e77f27e..243899b 100644
--- a/tools/llvm-mc/llvm-mc.cpp
+++ b/tools/llvm-mc/llvm-mc.cpp
@@ -22,7 +22,6 @@
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCObjectFileInfo.h"
#include "llvm/MC/MCParser/AsmLexer.h"
-#include "llvm/MC/MCParser/MCAsmLexer.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCSectionMachO.h"
#include "llvm/MC/MCStreamer.h"
@@ -236,6 +235,13 @@ static void setDwarfDebugFlags(int argc, char **argv) {
}
}
+static std::string DwarfDebugProducer;
+static void setDwarfDebugProducer(void) {
+ if(!getenv("DEBUG_PRODUCER"))
+ return;
+ DwarfDebugProducer += getenv("DEBUG_PRODUCER");
+}
+
static int AsLexInput(SourceMgr &SrcMgr, MCAsmInfo &MAI, tool_output_file *Out) {
AsmLexer Lexer(MAI);
@@ -353,6 +359,8 @@ int main(int argc, char **argv) {
TripleName = Triple::normalize(TripleName);
setDwarfDebugFlags(argc, argv);
+ setDwarfDebugProducer();
+
const char *ProgName = argv[0];
const Target *TheTarget = GetTarget(ProgName);
if (!TheTarget)
@@ -374,7 +382,6 @@ int main(int argc, char **argv) {
// it later.
SrcMgr.setIncludeDirs(IncludeDirs);
-
llvm::OwningPtr<MCAsmInfo> MAI(TheTarget->createMCAsmInfo(TripleName));
assert(MAI && "Unable to create target asm info!");
@@ -393,6 +400,8 @@ int main(int argc, char **argv) {
Ctx.setGenDwarfForAssembly(GenDwarfForAssembly);
if (!DwarfDebugFlags.empty())
Ctx.setDwarfDebugFlags(StringRef(DwarfDebugFlags));
+ if (!DwarfDebugProducer.empty())
+ Ctx.setDwarfDebugProducer(StringRef(DwarfDebugProducer));
if (!DebugCompilationDir.empty())
Ctx.setCompilationDir(DebugCompilationDir);
if (!MainFileName.empty())
@@ -418,7 +427,7 @@ int main(int argc, char **argv) {
OwningPtr<MCSubtargetInfo>
STI(TheTarget->createMCSubtargetInfo(TripleName, MCPU, FeaturesStr));
- MCInstPrinter *IP;
+ MCInstPrinter *IP = NULL;
if (FileType == OFT_AssemblyFile) {
IP =
TheTarget->createMCInstPrinter(OutputAsmVariant, *MAI, *MCII, *MRI, *STI);
@@ -456,10 +465,12 @@ int main(int argc, char **argv) {
Res = AssembleInput(ProgName, TheTarget, SrcMgr, Ctx, *Str, *MAI, *STI);
break;
case AC_MDisassemble:
+ assert(IP && "Expected assembly output");
IP->setUseMarkup(1);
disassemble = true;
break;
case AC_HDisassemble:
+ assert(IP && "Expected assembly output");
IP->setPrintImmHex(1);
disassemble = true;
break;
diff --git a/tools/llvm-nm/llvm-nm.cpp b/tools/llvm-nm/llvm-nm.cpp
index 056fd35..a24aae6 100644
--- a/tools/llvm-nm/llvm-nm.cpp
+++ b/tools/llvm-nm/llvm-nm.cpp
@@ -384,7 +384,9 @@ static void DumpSymbolNamesFromFile(std::string &Filename) {
OwningPtr<Binary> child;
if (i->getAsBinary(child)) {
// Try opening it as a bitcode file.
- OwningPtr<MemoryBuffer> buff(i->getBuffer());
+ OwningPtr<MemoryBuffer> buff;
+ if (error(i->getMemoryBuffer(buff)))
+ return;
Module *Result = 0;
if (buff)
Result = ParseBitcodeFile(buff.get(), Context, &ErrorMessage);
diff --git a/tools/llvm-objdump/ELFDump.cpp b/tools/llvm-objdump/ELFDump.cpp
index a635fef..72c512e 100644
--- a/tools/llvm-objdump/ELFDump.cpp
+++ b/tools/llvm-objdump/ELFDump.cpp
@@ -13,7 +13,6 @@
//===----------------------------------------------------------------------===//
#include "llvm-objdump.h"
-
#include "llvm/Object/ELF.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/MathExtras.h"
@@ -22,10 +21,10 @@
using namespace llvm;
using namespace llvm::object;
-template<endianness target_endianness, std::size_t max_alignment, bool is64Bits>
+template<class ELFT>
void printProgramHeaders(
- const ELFObjectFile<target_endianness, max_alignment, is64Bits> *o) {
- typedef ELFObjectFile<target_endianness, max_alignment, is64Bits> ELFO;
+ const ELFObjectFile<ELFT> *o) {
+ typedef ELFObjectFile<ELFT> ELFO;
outs() << "Program Header:\n";
for (typename ELFO::Elf_Phdr_Iter pi = o->begin_program_headers(),
pe = o->end_program_headers();
@@ -40,11 +39,20 @@ void printProgramHeaders(
case ELF::PT_GNU_EH_FRAME:
outs() << "EH_FRAME ";
break;
+ case ELF::PT_INTERP:
+ outs() << " INTERP ";
+ break;
+ case ELF::PT_DYNAMIC:
+ outs() << " DYNAMIC ";
+ break;
+ case ELF::PT_PHDR:
+ outs() << " PHDR ";
+ break;
default:
outs() << " UNKNOWN ";
}
- const char *Fmt = is64Bits ? "0x%016" PRIx64 " " : "0x%08" PRIx64 " ";
+ const char *Fmt = ELFT::Is64Bits ? "0x%016" PRIx64 " " : "0x%08" PRIx64 " ";
outs() << "off "
<< format(Fmt, (uint64_t)pi->p_offset)
@@ -68,22 +76,22 @@ void printProgramHeaders(
void llvm::printELFFileHeader(const object::ObjectFile *Obj) {
// Little-endian 32-bit
- if (const ELFObjectFile<support::little, 4, false> *ELFObj =
- dyn_cast<ELFObjectFile<support::little, 4, false> >(Obj))
+ if (const ELFObjectFile<ELFType<support::little, 4, false> > *ELFObj =
+ dyn_cast<ELFObjectFile<ELFType<support::little, 4, false> > >(Obj))
printProgramHeaders(ELFObj);
// Big-endian 32-bit
- if (const ELFObjectFile<support::big, 4, false> *ELFObj =
- dyn_cast<ELFObjectFile<support::big, 4, false> >(Obj))
+ if (const ELFObjectFile<ELFType<support::big, 4, false> > *ELFObj =
+ dyn_cast<ELFObjectFile<ELFType<support::big, 4, false> > >(Obj))
printProgramHeaders(ELFObj);
// Little-endian 64-bit
- if (const ELFObjectFile<support::little, 8, true> *ELFObj =
- dyn_cast<ELFObjectFile<support::little, 8, true> >(Obj))
+ if (const ELFObjectFile<ELFType<support::little, 8, true> > *ELFObj =
+ dyn_cast<ELFObjectFile<ELFType<support::little, 8, true> > >(Obj))
printProgramHeaders(ELFObj);
// Big-endian 64-bit
- if (const ELFObjectFile<support::big, 8, true> *ELFObj =
- dyn_cast<ELFObjectFile<support::big, 8, true> >(Obj))
+ if (const ELFObjectFile<ELFType<support::big, 8, true> > *ELFObj =
+ dyn_cast<ELFObjectFile<ELFType<support::big, 8, true> > >(Obj))
printProgramHeaders(ELFObj);
}
diff --git a/tools/llvm-objdump/llvm-objdump.cpp b/tools/llvm-objdump/llvm-objdump.cpp
index 9958dad..322bd21 100644
--- a/tools/llvm-objdump/llvm-objdump.cpp
+++ b/tools/llvm-objdump/llvm-objdump.cpp
@@ -11,6 +11,9 @@
// dumps out a plethora of information about an object file depending on the
// flags.
//
+// The flags and output of this program should be near identical to those of
+// binutils objdump.
+//
//===----------------------------------------------------------------------===//
#include "llvm-objdump.h"
@@ -28,7 +31,6 @@
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/Object/Archive.h"
#include "llvm/Object/COFF.h"
-#include "llvm/Object/ELF.h"
#include "llvm/Object/MachO.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Support/Casting.h"
@@ -442,7 +444,7 @@ static void PrintSectionHeaders(const ObjectFile *o) {
if (error(si->isBSS(BSS))) return;
std::string Type = (std::string(Text ? "TEXT " : "") +
(Data ? "DATA " : "") + (BSS ? "BSS" : ""));
- outs() << format("%3d %-13s %09" PRIx64 " %017" PRIx64 " %s\n",
+ outs() << format("%3d %-13s %08" PRIx64 " %016" PRIx64 " %s\n",
i, Name.str().c_str(), Size, Address, Type.c_str());
++i;
}
@@ -479,7 +481,7 @@ static void PrintSectionContents(const ObjectFile *o) {
// Print ascii.
outs() << " ";
for (std::size_t i = 0; i < 16 && addr + i < end; ++i) {
- if (std::isprint(Contents[addr + i] & 0xFF))
+ if (std::isprint(static_cast<unsigned char>(Contents[addr + i]) & 0xFF))
outs() << Contents[addr + i];
else
outs() << ".";
@@ -572,7 +574,10 @@ static void PrintSymbolTable(const ObjectFile *o) {
else if (Type == SymbolRef::ST_Function)
FileFunc = 'F';
- outs() << format("%08" PRIx64, Address) << " "
+ const char *Fmt = o->getBytesInAddress() > 4 ? "%016" PRIx64 :
+ "%08" PRIx64;
+
+ outs() << format(Fmt, Address) << " "
<< GlobLoc // Local -> 'l', Global -> 'g', Neither -> ' '
<< (Weak ? 'w' : ' ') // Weak?
<< ' ' // Constructor. Not supported yet.
diff --git a/tools/llvm-readobj/CMakeLists.txt b/tools/llvm-readobj/CMakeLists.txt
index be80469..676c23d 100644
--- a/tools/llvm-readobj/CMakeLists.txt
+++ b/tools/llvm-readobj/CMakeLists.txt
@@ -1,5 +1,6 @@
set(LLVM_LINK_COMPONENTS archive bitreader object)
add_llvm_tool(llvm-readobj
+ ELF.cpp
llvm-readobj.cpp
)
diff --git a/tools/llvm-readobj/ELF.cpp b/tools/llvm-readobj/ELF.cpp
new file mode 100644
index 0000000..07f15b3
--- /dev/null
+++ b/tools/llvm-readobj/ELF.cpp
@@ -0,0 +1,196 @@
+//===- llvm-readobj/ELF.cpp - ELF Specific Dumper -------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm-readobj.h"
+
+#include "llvm/Object/ELF.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/Format.h"
+
+namespace llvm {
+using namespace object;
+using namespace ELF;
+
+const char *getTypeString(uint64_t Type) {
+ switch (Type) {
+ case DT_BIND_NOW:
+ return "(BIND_NOW)";
+ case DT_DEBUG:
+ return "(DEBUG)";
+ case DT_FINI:
+ return "(FINI)";
+ case DT_FINI_ARRAY:
+ return "(FINI_ARRAY)";
+ case DT_FINI_ARRAYSZ:
+ return "(FINI_ARRAYSZ)";
+ case DT_FLAGS:
+ return "(FLAGS)";
+ case DT_HASH:
+ return "(HASH)";
+ case DT_INIT:
+ return "(INIT)";
+ case DT_INIT_ARRAY:
+ return "(INIT_ARRAY)";
+ case DT_INIT_ARRAYSZ:
+ return "(INIT_ARRAYSZ)";
+ case DT_PREINIT_ARRAY:
+ return "(PREINIT_ARRAY)";
+ case DT_PREINIT_ARRAYSZ:
+ return "(PREINIT_ARRAYSZ)";
+ case DT_JMPREL:
+ return "(JMPREL)";
+ case DT_NEEDED:
+ return "(NEEDED)";
+ case DT_NULL:
+ return "(NULL)";
+ case DT_PLTGOT:
+ return "(PLTGOT)";
+ case DT_PLTREL:
+ return "(PLTREL)";
+ case DT_PLTRELSZ:
+ return "(PLTRELSZ)";
+ case DT_REL:
+ return "(REL)";
+ case DT_RELA:
+ return "(RELA)";
+ case DT_RELENT:
+ return "(RELENT)";
+ case DT_RELSZ:
+ return "(RELSZ)";
+ case DT_RELAENT:
+ return "(RELAENT)";
+ case DT_RELASZ:
+ return "(RELASZ)";
+ case DT_RPATH:
+ return "(RPATH)";
+ case DT_RUNPATH:
+ return "(RUNPATH)";
+ case DT_SONAME:
+ return "(SONAME)";
+ case DT_STRSZ:
+ return "(STRSZ)";
+ case DT_STRTAB:
+ return "(STRTAB)";
+ case DT_SYMBOLIC:
+ return "(SYMBOLIC)";
+ case DT_SYMENT:
+ return "(SYMENT)";
+ case DT_SYMTAB:
+ return "(SYMTAB)";
+ case DT_TEXTREL:
+ return "(TEXTREL)";
+ default:
+ return "unknown";
+ }
+}
+
+template <class ELFT>
+void printValue(const ELFObjectFile<ELFT> *O, uint64_t Type, uint64_t Value,
+ bool Is64, raw_ostream &OS) {
+ switch (Type) {
+ case DT_PLTREL:
+ if (Value == DT_REL) {
+ OS << "REL";
+ break;
+ } else if (Value == DT_RELA) {
+ OS << "RELA";
+ break;
+ }
+ // Fallthrough.
+ case DT_PLTGOT:
+ case DT_HASH:
+ case DT_STRTAB:
+ case DT_SYMTAB:
+ case DT_RELA:
+ case DT_INIT:
+ case DT_FINI:
+ case DT_REL:
+ case DT_JMPREL:
+ case DT_INIT_ARRAY:
+ case DT_FINI_ARRAY:
+ case DT_PREINIT_ARRAY:
+ case DT_DEBUG:
+ case DT_NULL:
+ OS << format("0x%" PRIx64, Value);
+ break;
+ case DT_PLTRELSZ:
+ case DT_RELASZ:
+ case DT_RELAENT:
+ case DT_STRSZ:
+ case DT_SYMENT:
+ case DT_RELSZ:
+ case DT_RELENT:
+ case DT_INIT_ARRAYSZ:
+ case DT_FINI_ARRAYSZ:
+ case DT_PREINIT_ARRAYSZ:
+ OS << Value << " (bytes)";
+ break;
+ case DT_NEEDED:
+ OS << "Shared library: ["
+ << O->getString(O->getDynamicStringTableSectionHeader(), Value) << "]";
+ break;
+ case DT_SONAME:
+ OS << "Library soname: ["
+ << O->getString(O->getDynamicStringTableSectionHeader(), Value) << "]";
+ break;
+ }
+}
+
+template <class ELFT>
+ErrorOr<void> dumpDynamicTable(const ELFObjectFile<ELFT> *O, raw_ostream &OS) {
+ typedef ELFObjectFile<ELFT> ELFO;
+ typedef typename ELFO::Elf_Dyn_iterator EDI;
+ EDI Start = O->begin_dynamic_table(),
+ End = O->end_dynamic_table(true);
+
+ if (Start == End)
+ return error_code::success();
+
+ ptrdiff_t Total = std::distance(Start, End);
+ OS << "Dynamic section contains " << Total << " entries\n";
+
+ bool Is64 = O->getBytesInAddress() == 8;
+
+ OS << " Tag" << (Is64 ? " " : " ") << "Type"
+ << " " << "Name/Value\n";
+ for (; Start != End; ++Start) {
+ OS << " "
+ << format(Is64 ? "0x%016" PRIx64 : "0x%08" PRIx64, Start->getTag())
+ << " " << format("%-21s", getTypeString(Start->getTag()));
+ printValue(O, Start->getTag(), Start->getVal(), Is64, OS);
+ OS << "\n";
+ }
+
+ OS << " Total: " << Total << "\n\n";
+ return error_code::success();
+}
+
+ErrorOr<void> dumpELFDynamicTable(ObjectFile *O, raw_ostream &OS) {
+ // Little-endian 32-bit
+ if (const ELFObjectFile<ELFType<support::little, 4, false> > *ELFObj =
+ dyn_cast<ELFObjectFile<ELFType<support::little, 4, false> > >(O))
+ return dumpDynamicTable(ELFObj, OS);
+
+ // Big-endian 32-bit
+ if (const ELFObjectFile<ELFType<support::big, 4, false> > *ELFObj =
+ dyn_cast<ELFObjectFile<ELFType<support::big, 4, false> > >(O))
+ return dumpDynamicTable(ELFObj, OS);
+
+ // Little-endian 64-bit
+ if (const ELFObjectFile<ELFType<support::little, 8, true> > *ELFObj =
+ dyn_cast<ELFObjectFile<ELFType<support::little, 8, true> > >(O))
+ return dumpDynamicTable(ELFObj, OS);
+
+ // Big-endian 64-bit
+ if (const ELFObjectFile<ELFType<support::big, 8, true> > *ELFObj =
+ dyn_cast<ELFObjectFile<ELFType<support::big, 8, true> > >(O))
+ return dumpDynamicTable(ELFObj, OS);
+ return error_code(object_error::invalid_file_type);
+}
+} // end namespace llvm
diff --git a/tools/llvm-readobj/llvm-readobj.cpp b/tools/llvm-readobj/llvm-readobj.cpp
index d22ecd1..8f0917f 100644
--- a/tools/llvm-readobj/llvm-readobj.cpp
+++ b/tools/llvm-readobj/llvm-readobj.cpp
@@ -7,15 +7,20 @@
//
//===----------------------------------------------------------------------===//
//
-// This program is a utility that works like traditional Unix "readelf",
-// except that it can handle any type of object file recognized by lib/Object.
+// This is a tool similar to readelf, except it works on multiple object file
+// formats. The main purpose of this tool is to provide detailed output suitable
+// for FileCheck.
//
-// It makes use of the generic ObjectFile interface.
+// Flags should be similar to readelf where supported, but the output format
+// does not need to be identical. The point is to not make users learn yet
+// another set of flags.
//
-// Caution: This utility is new, experimental, unsupported, and incomplete.
+// Output should be specialized for each format where appropriate.
//
//===----------------------------------------------------------------------===//
+#include "llvm-readobj.h"
+
#include "llvm/ADT/Triple.h"
#include "llvm/Analysis/Verifier.h"
#include "llvm/Object/ELF.h"
@@ -237,7 +242,8 @@ int main(int argc, char** argv) {
return 1;
}
- ObjectFile *obj = ObjectFile::createObjectFile(File.take());
+ OwningPtr<ObjectFile> o(ObjectFile::createObjectFile(File.take()));
+ ObjectFile *obj = o.get();
if (!obj) {
errs() << InputFilename << ": Object type not recognized\n";
}
@@ -259,6 +265,13 @@ int main(int argc, char** argv) {
dump(obj, &dumpSection, obj->begin_sections(), obj->end_sections(),
"Section iteration failed");
+ if (obj->isELF()) {
+ if (ErrorOr<void> e = dumpELFDynamicTable(obj, outs()))
+ ;
+ else
+ errs() << "InputFilename" << ": " << error_code(e).message() << "\n";
+ }
+
outs() << "Libraries needed:\n";
dump(obj, &dumpLibrary, obj->begin_libraries_needed(),
obj->end_libraries_needed(), "Needed libraries iteration failed");
diff --git a/tools/llvm-readobj/llvm-readobj.h b/tools/llvm-readobj/llvm-readobj.h
new file mode 100644
index 0000000..cf492b2
--- /dev/null
+++ b/tools/llvm-readobj/llvm-readobj.h
@@ -0,0 +1,22 @@
+//===- llvm-readobj.h - Dump contents of an Object File -------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_READ_OBJ_H
+#define LLVM_TOOLS_READ_OBJ_H
+
+#include "llvm/Support/ErrorOr.h"
+
+namespace llvm {
+namespace object { class ObjectFile; }
+class raw_ostream;
+
+ErrorOr<void> dumpELFDynamicTable(object::ObjectFile *O, raw_ostream &OS);
+} // end namespace llvm
+
+#endif
diff --git a/tools/llvm-rtdyld/CMakeLists.txt b/tools/llvm-rtdyld/CMakeLists.txt
index 17e2c3e..8d161d3 100644
--- a/tools/llvm-rtdyld/CMakeLists.txt
+++ b/tools/llvm-rtdyld/CMakeLists.txt
@@ -1,4 +1,4 @@
-set(LLVM_LINK_COMPONENTS ${LLVM_TARGETS_TO_BUILD} support MC object RuntimeDyld JIT)
+set(LLVM_LINK_COMPONENTS ${LLVM_TARGETS_TO_BUILD} support MC object RuntimeDyld JIT debuginfo)
add_llvm_tool(llvm-rtdyld
llvm-rtdyld.cpp
diff --git a/tools/llvm-rtdyld/Makefile b/tools/llvm-rtdyld/Makefile
index 30fbee0..fabdd68 100644
--- a/tools/llvm-rtdyld/Makefile
+++ b/tools/llvm-rtdyld/Makefile
@@ -9,7 +9,7 @@
LEVEL := ../..
TOOLNAME := llvm-rtdyld
-LINK_COMPONENTS := all-targets support MC object RuntimeDyld JIT
+LINK_COMPONENTS := all-targets support MC object RuntimeDyld JIT debuginfo
# This tool has no plugins, optimize startup time.
TOOL_NO_EXPORTS := 1
diff --git a/tools/llvm-rtdyld/llvm-rtdyld.cpp b/tools/llvm-rtdyld/llvm-rtdyld.cpp
index ec63c9b..4d8d345 100644
--- a/tools/llvm-rtdyld/llvm-rtdyld.cpp
+++ b/tools/llvm-rtdyld/llvm-rtdyld.cpp
@@ -13,6 +13,7 @@
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/StringMap.h"
+#include "llvm/DebugInfo/DIContext.h"
#include "llvm/ExecutionEngine/ObjectBuffer.h"
#include "llvm/ExecutionEngine/ObjectImage.h"
#include "llvm/ExecutionEngine/RuntimeDyld.h"
@@ -31,7 +32,8 @@ InputFileList(cl::Positional, cl::ZeroOrMore,
cl::desc("<input file>"));
enum ActionType {
- AC_Execute
+ AC_Execute,
+ AC_PrintLineInfo
};
static cl::opt<ActionType>
@@ -39,6 +41,8 @@ Action(cl::desc("Action to perform:"),
cl::init(AC_Execute),
cl::values(clEnumValN(AC_Execute, "execute",
"Load, link, and execute the inputs."),
+ clEnumValN(AC_PrintLineInfo, "printline",
+ "Load, link, and print line information for each function."),
clEnumValEnd));
static cl::opt<std::string>
@@ -114,6 +118,66 @@ static int Error(const Twine &Msg) {
/* *** */
+static int printLineInfoForInput() {
+ // If we don't have any input files, read from stdin.
+ if (!InputFileList.size())
+ InputFileList.push_back("-");
+ for(unsigned i = 0, e = InputFileList.size(); i != e; ++i) {
+ // Instantiate a dynamic linker.
+ TrivialMemoryManager *MemMgr = new TrivialMemoryManager;
+ RuntimeDyld Dyld(MemMgr);
+
+ // Load the input memory buffer.
+ OwningPtr<MemoryBuffer> InputBuffer;
+ OwningPtr<ObjectImage> LoadedObject;
+ if (error_code ec = MemoryBuffer::getFileOrSTDIN(InputFileList[i],
+ InputBuffer))
+ return Error("unable to read input: '" + ec.message() + "'");
+
+ // Load the object file
+ LoadedObject.reset(Dyld.loadObject(new ObjectBuffer(InputBuffer.take())));
+ if (!LoadedObject) {
+ return Error(Dyld.getErrorString());
+ }
+
+ // Resolve all the relocations we can.
+ Dyld.resolveRelocations();
+
+ OwningPtr<DIContext> Context(DIContext::getDWARFContext(LoadedObject->getObjectFile()));
+
+ // Use symbol info to iterate functions in the object.
+ error_code ec;
+ for (object::symbol_iterator I = LoadedObject->begin_symbols(),
+ E = LoadedObject->end_symbols();
+ I != E && !ec;
+ I.increment(ec)) {
+ object::SymbolRef::Type SymType;
+ if (I->getType(SymType)) continue;
+ if (SymType == object::SymbolRef::ST_Function) {
+ StringRef Name;
+ uint64_t Addr;
+ uint64_t Size;
+ if (I->getName(Name)) continue;
+ if (I->getAddress(Addr)) continue;
+ if (I->getSize(Size)) continue;
+
+ outs() << "Function: " << Name << ", Size = " << Size << "\n";
+
+ DILineInfoTable Lines = Context->getLineInfoForAddressRange(Addr, Size);
+ DILineInfoTable::iterator Begin = Lines.begin();
+ DILineInfoTable::iterator End = Lines.end();
+ for (DILineInfoTable::iterator It = Begin; It != End; ++It) {
+ outs() << " Line info @ " << It->first - Addr << ": "
+ << It->second.getFileName()
+ << ", line:" << It->second.getLine() << "\n";
+ }
+ }
+ }
+ }
+
+ return 0;
+}
+
static int executeInput() {
// Instantiate a dynamic linker.
TrivialMemoryManager *MemMgr = new TrivialMemoryManager;
@@ -180,5 +244,7 @@ int main(int argc, char **argv) {
switch (Action) {
case AC_Execute:
return executeInput();
+ case AC_PrintLineInfo:
+ return printLineInfoForInput();
}
}
diff --git a/tools/llvm-stress/llvm-stress.cpp b/tools/llvm-stress/llvm-stress.cpp
index bb15c6b..fbda1b7 100644
--- a/tools/llvm-stress/llvm-stress.cpp
+++ b/tools/llvm-stress/llvm-stress.cpp
@@ -12,6 +12,7 @@
//
//===----------------------------------------------------------------------===//
#include "llvm/IR/LLVMContext.h"
+#include "llvm/ADT/OwningPtr.h"
#include "llvm/Analysis/CallGraphSCCPass.h"
#include "llvm/Analysis/Verifier.h"
#include "llvm/Assembly/PrintModulePass.h"
@@ -26,7 +27,6 @@
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/ToolOutputFile.h"
#include <algorithm>
-#include <memory>
#include <set>
#include <sstream>
#include <vector>
@@ -379,9 +379,7 @@ struct ConstModifier: public Modifier {
RandomBits[i] = Ran->Rand64();
APInt RandomInt(Ty->getPrimitiveSizeInBits(), makeArrayRef(RandomBits));
-
- bool isIEEE = !Ty->isX86_FP80Ty() && !Ty->isPPC_FP128Ty();
- APFloat RandomFloat(RandomInt, isIEEE);
+ APFloat RandomFloat(Ty->getFltSemantics(), RandomInt);
if (Ran->Rand() & 1)
return PT->push_back(ConstantFP::getNullValue(Ty));
@@ -624,15 +622,15 @@ void FillFunction(Function *F, Random &R) {
// List of modifiers which add new random instructions.
std::vector<Modifier*> Modifiers;
- std::auto_ptr<Modifier> LM(new LoadModifier(BB, &PT, &R));
- std::auto_ptr<Modifier> SM(new StoreModifier(BB, &PT, &R));
- std::auto_ptr<Modifier> EE(new ExtractElementModifier(BB, &PT, &R));
- std::auto_ptr<Modifier> SHM(new ShuffModifier(BB, &PT, &R));
- std::auto_ptr<Modifier> IE(new InsertElementModifier(BB, &PT, &R));
- std::auto_ptr<Modifier> BM(new BinModifier(BB, &PT, &R));
- std::auto_ptr<Modifier> CM(new CastModifier(BB, &PT, &R));
- std::auto_ptr<Modifier> SLM(new SelectModifier(BB, &PT, &R));
- std::auto_ptr<Modifier> PM(new CmpModifier(BB, &PT, &R));
+ OwningPtr<Modifier> LM(new LoadModifier(BB, &PT, &R));
+ OwningPtr<Modifier> SM(new StoreModifier(BB, &PT, &R));
+ OwningPtr<Modifier> EE(new ExtractElementModifier(BB, &PT, &R));
+ OwningPtr<Modifier> SHM(new ShuffModifier(BB, &PT, &R));
+ OwningPtr<Modifier> IE(new InsertElementModifier(BB, &PT, &R));
+ OwningPtr<Modifier> BM(new BinModifier(BB, &PT, &R));
+ OwningPtr<Modifier> CM(new CastModifier(BB, &PT, &R));
+ OwningPtr<Modifier> SLM(new SelectModifier(BB, &PT, &R));
+ OwningPtr<Modifier> PM(new CmpModifier(BB, &PT, &R));
Modifiers.push_back(LM.get());
Modifiers.push_back(SM.get());
Modifiers.push_back(EE.get());
@@ -686,7 +684,7 @@ int main(int argc, char **argv) {
cl::ParseCommandLineOptions(argc, argv, "llvm codegen stress-tester\n");
llvm_shutdown_obj Y;
- std::auto_ptr<Module> M(new Module("/tmp/autogen.bc", getGlobalContext()));
+ OwningPtr<Module> M(new Module("/tmp/autogen.bc", getGlobalContext()));
Function *F = GenEmptyFunction(M.get());
// Pick an initial seed value
diff --git a/tools/llvm-symbolizer/CMakeLists.txt b/tools/llvm-symbolizer/CMakeLists.txt
index 5e27463..5967b89 100644
--- a/tools/llvm-symbolizer/CMakeLists.txt
+++ b/tools/llvm-symbolizer/CMakeLists.txt
@@ -9,5 +9,6 @@ set(LLVM_LINK_COMPONENTS
)
add_llvm_tool(llvm-symbolizer
+ LLVMSymbolize.cpp
llvm-symbolizer.cpp
)
diff --git a/tools/llvm-symbolizer/LLVMSymbolize.cpp b/tools/llvm-symbolizer/LLVMSymbolize.cpp
new file mode 100644
index 0000000..86ea34b
--- /dev/null
+++ b/tools/llvm-symbolizer/LLVMSymbolize.cpp
@@ -0,0 +1,287 @@
+//===-- LLVMSymbolize.cpp -------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Implementation for LLVM symbolization library.
+//
+//===----------------------------------------------------------------------===//
+
+#include "LLVMSymbolize.h"
+#include "llvm/Object/MachO.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/Path.h"
+
+#include <sstream>
+
+namespace llvm {
+namespace symbolize {
+
+static bool error(error_code ec) {
+ if (!ec)
+ return false;
+ errs() << "LLVMSymbolizer: error reading file: " << ec.message() << ".\n";
+ return true;
+}
+
+static uint32_t
+getDILineInfoSpecifierFlags(const LLVMSymbolizer::Options &Opts) {
+ uint32_t Flags = llvm::DILineInfoSpecifier::FileLineInfo |
+ llvm::DILineInfoSpecifier::AbsoluteFilePath;
+ if (Opts.PrintFunctions)
+ Flags |= llvm::DILineInfoSpecifier::FunctionName;
+ return Flags;
+}
+
+static void patchFunctionNameInDILineInfo(const std::string &NewFunctionName,
+ DILineInfo &LineInfo) {
+ std::string FileName = LineInfo.getFileName();
+ LineInfo = DILineInfo(StringRef(FileName), StringRef(NewFunctionName),
+ LineInfo.getLine(), LineInfo.getColumn());
+}
+
+ModuleInfo::ModuleInfo(ObjectFile *Obj, DIContext *DICtx)
+ : Module(Obj), DebugInfoContext(DICtx) {
+ error_code ec;
+ for (symbol_iterator si = Module->begin_symbols(), se = Module->end_symbols();
+ si != se; si.increment(ec)) {
+ if (error(ec))
+ return;
+ SymbolRef::Type SymbolType;
+ if (error(si->getType(SymbolType)))
+ continue;
+ if (SymbolType != SymbolRef::ST_Function &&
+ SymbolType != SymbolRef::ST_Data)
+ continue;
+ uint64_t SymbolAddress;
+ if (error(si->getAddress(SymbolAddress)) ||
+ SymbolAddress == UnknownAddressOrSize)
+ continue;
+ uint64_t SymbolSize;
+ if (error(si->getSize(SymbolSize)) || SymbolSize == UnknownAddressOrSize)
+ continue;
+ StringRef SymbolName;
+ if (error(si->getName(SymbolName)))
+ continue;
+ // FIXME: If a function has alias, there are two entries in symbol table
+ // with same address size. Make sure we choose the correct one.
+ SymbolMapTy &M = SymbolType == SymbolRef::ST_Function ? Functions : Objects;
+ SymbolDesc SD = { SymbolAddress, SymbolAddress + SymbolSize };
+ M.insert(std::make_pair(SD, SymbolName));
+ }
+}
+
+bool ModuleInfo::getNameFromSymbolTable(SymbolRef::Type Type, uint64_t Address,
+ std::string &Name, uint64_t &Addr,
+ uint64_t &Size) const {
+ const SymbolMapTy &M = Type == SymbolRef::ST_Function ? Functions : Objects;
+ SymbolDesc SD = { Address, Address + 1 };
+ SymbolMapTy::const_iterator it = M.find(SD);
+ if (it == M.end())
+ return false;
+ if (Address < it->first.Addr || Address >= it->first.AddrEnd)
+ return false;
+ Name = it->second.str();
+ Addr = it->first.Addr;
+ Size = it->first.AddrEnd - it->first.Addr;
+ return true;
+}
+
+DILineInfo ModuleInfo::symbolizeCode(
+ uint64_t ModuleOffset, const LLVMSymbolizer::Options &Opts) const {
+ DILineInfo LineInfo;
+ if (DebugInfoContext) {
+ LineInfo = DebugInfoContext->getLineInfoForAddress(
+ ModuleOffset, getDILineInfoSpecifierFlags(Opts));
+ }
+ // Override function name from symbol table if necessary.
+ if (Opts.PrintFunctions && Opts.UseSymbolTable) {
+ std::string FunctionName;
+ uint64_t Start, Size;
+ if (getNameFromSymbolTable(SymbolRef::ST_Function, ModuleOffset,
+ FunctionName, Start, Size)) {
+ patchFunctionNameInDILineInfo(FunctionName, LineInfo);
+ }
+ }
+ return LineInfo;
+}
+
+DIInliningInfo ModuleInfo::symbolizeInlinedCode(
+ uint64_t ModuleOffset, const LLVMSymbolizer::Options &Opts) const {
+ DIInliningInfo InlinedContext;
+ if (DebugInfoContext) {
+ InlinedContext = DebugInfoContext->getInliningInfoForAddress(
+ ModuleOffset, getDILineInfoSpecifierFlags(Opts));
+ }
+ // Make sure there is at least one frame in context.
+ if (InlinedContext.getNumberOfFrames() == 0) {
+ InlinedContext.addFrame(DILineInfo());
+ }
+ // Override the function name in lower frame with name from symbol table.
+ if (Opts.PrintFunctions && Opts.UseSymbolTable) {
+ DIInliningInfo PatchedInlinedContext;
+ for (uint32_t i = 0, n = InlinedContext.getNumberOfFrames(); i < n; i++) {
+ DILineInfo LineInfo = InlinedContext.getFrame(i);
+ if (i == n - 1) {
+ std::string FunctionName;
+ uint64_t Start, Size;
+ if (getNameFromSymbolTable(SymbolRef::ST_Function, ModuleOffset,
+ FunctionName, Start, Size)) {
+ patchFunctionNameInDILineInfo(FunctionName, LineInfo);
+ }
+ }
+ PatchedInlinedContext.addFrame(LineInfo);
+ }
+ InlinedContext = PatchedInlinedContext;
+ }
+ return InlinedContext;
+}
+
+bool ModuleInfo::symbolizeData(uint64_t ModuleOffset, std::string &Name,
+ uint64_t &Start, uint64_t &Size) const {
+ return getNameFromSymbolTable(SymbolRef::ST_Data, ModuleOffset, Name, Start,
+ Size);
+}
+
+const char LLVMSymbolizer::kBadString[] = "??";
+
+std::string LLVMSymbolizer::symbolizeCode(const std::string &ModuleName,
+ uint64_t ModuleOffset) {
+ ModuleInfo *Info = getOrCreateModuleInfo(ModuleName);
+ if (Info == 0)
+ return printDILineInfo(DILineInfo());
+ if (Opts.PrintInlining) {
+ DIInliningInfo InlinedContext =
+ Info->symbolizeInlinedCode(ModuleOffset, Opts);
+ uint32_t FramesNum = InlinedContext.getNumberOfFrames();
+ assert(FramesNum > 0);
+ std::string Result;
+ for (uint32_t i = 0; i < FramesNum; i++) {
+ DILineInfo LineInfo = InlinedContext.getFrame(i);
+ Result += printDILineInfo(LineInfo);
+ }
+ return Result;
+ }
+ DILineInfo LineInfo = Info->symbolizeCode(ModuleOffset, Opts);
+ return printDILineInfo(LineInfo);
+}
+
+std::string LLVMSymbolizer::symbolizeData(const std::string &ModuleName,
+ uint64_t ModuleOffset) {
+ std::string Name = kBadString;
+ uint64_t Start = 0;
+ uint64_t Size = 0;
+ if (Opts.UseSymbolTable) {
+ if (ModuleInfo *Info = getOrCreateModuleInfo(ModuleName)) {
+ if (Info->symbolizeData(ModuleOffset, Name, Start, Size))
+ DemangleName(Name);
+ }
+ }
+ std::stringstream ss;
+ ss << Name << "\n" << Start << " " << Size << "\n";
+ return ss.str();
+}
+
+// Returns true if the object endianness is known.
+static bool getObjectEndianness(const ObjectFile *Obj, bool &IsLittleEndian) {
+ // FIXME: Implement this when libLLVMObject allows to do it easily.
+ IsLittleEndian = true;
+ return true;
+}
+
+static ObjectFile *getObjectFile(const std::string &Path) {
+ OwningPtr<MemoryBuffer> Buff;
+ if (error_code ec = MemoryBuffer::getFile(Path, Buff))
+ error(ec);
+ return ObjectFile::createObjectFile(Buff.take());
+}
+
+static std::string getDarwinDWARFResourceForModule(const std::string &Path) {
+ StringRef Basename = sys::path::filename(Path);
+ const std::string &DSymDirectory = Path + ".dSYM";
+ SmallString<16> ResourceName = StringRef(DSymDirectory);
+ sys::path::append(ResourceName, "Contents", "Resources", "DWARF");
+ sys::path::append(ResourceName, Basename);
+ return ResourceName.str();
+}
+
+ModuleInfo *
+LLVMSymbolizer::getOrCreateModuleInfo(const std::string &ModuleName) {
+ ModuleMapTy::iterator I = Modules.find(ModuleName);
+ if (I != Modules.end())
+ return I->second;
+
+ ObjectFile *Obj = getObjectFile(ModuleName);
+ if (Obj == 0) {
+ // Module name doesn't point to a valid object file.
+ Modules.insert(make_pair(ModuleName, (ModuleInfo *)0));
+ return 0;
+ }
+
+ DIContext *Context = 0;
+ bool IsLittleEndian;
+ if (getObjectEndianness(Obj, IsLittleEndian)) {
+ // On Darwin we may find DWARF in separate object file in
+ // resource directory.
+ ObjectFile *DbgObj = Obj;
+ if (isa<MachOObjectFile>(Obj)) {
+ const std::string &ResourceName =
+ getDarwinDWARFResourceForModule(ModuleName);
+ ObjectFile *ResourceObj = getObjectFile(ResourceName);
+ if (ResourceObj != 0)
+ DbgObj = ResourceObj;
+ }
+ Context = DIContext::getDWARFContext(DbgObj);
+ assert(Context);
+ }
+
+ ModuleInfo *Info = new ModuleInfo(Obj, Context);
+ Modules.insert(make_pair(ModuleName, Info));
+ return Info;
+}
+
+std::string LLVMSymbolizer::printDILineInfo(DILineInfo LineInfo) const {
+ // By default, DILineInfo contains "<invalid>" for function/filename it
+ // cannot fetch. We replace it to "??" to make our output closer to addr2line.
+ static const std::string kDILineInfoBadString = "<invalid>";
+ std::stringstream Result;
+ if (Opts.PrintFunctions) {
+ std::string FunctionName = LineInfo.getFunctionName();
+ if (FunctionName == kDILineInfoBadString)
+ FunctionName = kBadString;
+ DemangleName(FunctionName);
+ Result << FunctionName << "\n";
+ }
+ std::string Filename = LineInfo.getFileName();
+ if (Filename == kDILineInfoBadString)
+ Filename = kBadString;
+ Result << Filename << ":" << LineInfo.getLine() << ":" << LineInfo.getColumn()
+ << "\n";
+ return Result.str();
+}
+
+#if !defined(_MSC_VER)
+// Assume that __cxa_demangle is provided by libcxxabi (except for Windows).
+extern "C" char *__cxa_demangle(const char *mangled_name, char *output_buffer,
+ size_t *length, int *status);
+#endif
+
+void LLVMSymbolizer::DemangleName(std::string &Name) const {
+#if !defined(_MSC_VER)
+ if (!Opts.Demangle)
+ return;
+ int status = 0;
+ char *DemangledName = __cxa_demangle(Name.c_str(), 0, 0, &status);
+ if (status != 0)
+ return;
+ Name = DemangledName;
+ free(DemangledName);
+#endif
+}
+
+} // namespace symbolize
+} // namespace llvm
diff --git a/tools/llvm-symbolizer/LLVMSymbolize.h b/tools/llvm-symbolizer/LLVMSymbolize.h
new file mode 100644
index 0000000..e6220aa
--- /dev/null
+++ b/tools/llvm-symbolizer/LLVMSymbolize.h
@@ -0,0 +1,97 @@
+//===-- LLVMSymbolize.h ----------------------------------------- C++ -----===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Header for LLVM symbolization library.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_SYMBOLIZE_H
+#define LLVM_SYMBOLIZE_H
+
+#include "llvm/ADT/OwningPtr.h"
+#include "llvm/DebugInfo/DIContext.h"
+#include "llvm/Object/ObjectFile.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include <map>
+#include <string>
+
+namespace llvm {
+
+using namespace object;
+
+namespace symbolize {
+
+class ModuleInfo;
+
+class LLVMSymbolizer {
+public:
+ struct Options {
+ bool UseSymbolTable : 1;
+ bool PrintFunctions : 1;
+ bool PrintInlining : 1;
+ bool Demangle : 1;
+ Options(bool UseSymbolTable = true, bool PrintFunctions = true,
+ bool PrintInlining = true, bool Demangle = true)
+ : UseSymbolTable(UseSymbolTable), PrintFunctions(PrintFunctions),
+ PrintInlining(PrintInlining), Demangle(Demangle) {
+ }
+ };
+
+ LLVMSymbolizer(const Options &Opts = Options()) : Opts(Opts) {}
+
+ // Returns the result of symbolization for module name/offset as
+ // a string (possibly containing newlines).
+ std::string
+ symbolizeCode(const std::string &ModuleName, uint64_t ModuleOffset);
+ std::string
+ symbolizeData(const std::string &ModuleName, uint64_t ModuleOffset);
+private:
+ ModuleInfo *getOrCreateModuleInfo(const std::string &ModuleName);
+ std::string printDILineInfo(DILineInfo LineInfo) const;
+ void DemangleName(std::string &Name) const;
+
+ typedef std::map<std::string, ModuleInfo *> ModuleMapTy;
+ ModuleMapTy Modules;
+ Options Opts;
+ static const char kBadString[];
+};
+
+class ModuleInfo {
+public:
+ ModuleInfo(ObjectFile *Obj, DIContext *DICtx);
+
+ DILineInfo symbolizeCode(uint64_t ModuleOffset,
+ const LLVMSymbolizer::Options &Opts) const;
+ DIInliningInfo symbolizeInlinedCode(
+ uint64_t ModuleOffset, const LLVMSymbolizer::Options &Opts) const;
+ bool symbolizeData(uint64_t ModuleOffset, std::string &Name, uint64_t &Start,
+ uint64_t &Size) const;
+
+private:
+ bool getNameFromSymbolTable(SymbolRef::Type Type, uint64_t Address,
+ std::string &Name, uint64_t &Addr,
+ uint64_t &Size) const;
+ OwningPtr<ObjectFile> Module;
+ OwningPtr<DIContext> DebugInfoContext;
+
+ struct SymbolDesc {
+ uint64_t Addr;
+ uint64_t AddrEnd;
+ friend bool operator<(const SymbolDesc &s1, const SymbolDesc &s2) {
+ return s1.AddrEnd <= s2.Addr;
+ }
+ };
+ typedef std::map<SymbolDesc, StringRef> SymbolMapTy;
+ SymbolMapTy Functions;
+ SymbolMapTy Objects;
+};
+
+} // namespace symbolize
+} // namespace llvm
+
+#endif // LLVM_SYMBOLIZE_H
diff --git a/tools/llvm-symbolizer/llvm-symbolizer.cpp b/tools/llvm-symbolizer/llvm-symbolizer.cpp
index 6a5eb4a..d039ec6 100644
--- a/tools/llvm-symbolizer/llvm-symbolizer.cpp
+++ b/tools/llvm-symbolizer/llvm-symbolizer.cpp
@@ -15,292 +15,69 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/ADT/OwningPtr.h"
+#include "LLVMSymbolize.h"
#include "llvm/ADT/StringRef.h"
-#include "llvm/DebugInfo/DIContext.h"
-#include "llvm/Object/MachO.h"
-#include "llvm/Object/ObjectFile.h"
-#include "llvm/Support/Casting.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.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"
#include <cstdio>
#include <cstring>
-#include <map>
#include <string>
using namespace llvm;
-using namespace object;
+using namespace symbolize;
static cl::opt<bool>
-UseSymbolTable("use-symbol-table", cl::init(true),
- cl::desc("Prefer names in symbol table to names "
- "in debug info"));
+ClUseSymbolTable("use-symbol-table", cl::init(true),
+ cl::desc("Prefer names in symbol table to names "
+ "in debug info"));
static cl::opt<bool>
-PrintFunctions("functions", cl::init(true),
- cl::desc("Print function names as well as line "
- "information for a given address"));
+ClPrintFunctions("functions", cl::init(true),
+ cl::desc("Print function names as well as line "
+ "information for a given address"));
static cl::opt<bool>
-PrintInlining("inlining", cl::init(true),
- cl::desc("Print all inlined frames for a given address"));
+ClPrintInlining("inlining", cl::init(true),
+ cl::desc("Print all inlined frames for a given address"));
static cl::opt<bool>
-Demangle("demangle", cl::init(true),
- cl::desc("Demangle function names"));
-
-static StringRef ToolInvocationPath;
-
-static bool error(error_code ec) {
- if (!ec) return false;
- errs() << ToolInvocationPath << ": error reading file: "
- << ec.message() << ".\n";
- return true;
-}
-
-static uint32_t getDILineInfoSpecifierFlags() {
- uint32_t Flags = llvm::DILineInfoSpecifier::FileLineInfo |
- llvm::DILineInfoSpecifier::AbsoluteFilePath;
- if (PrintFunctions)
- Flags |= llvm::DILineInfoSpecifier::FunctionName;
- return Flags;
-}
-
-static void patchFunctionNameInDILineInfo(const std::string &NewFunctionName,
- DILineInfo &LineInfo) {
- std::string FileName = LineInfo.getFileName();
- LineInfo = DILineInfo(StringRef(FileName), StringRef(NewFunctionName),
- LineInfo.getLine(), LineInfo.getColumn());
-}
-
-namespace {
-class ModuleInfo {
- OwningPtr<ObjectFile> Module;
- OwningPtr<DIContext> DebugInfoContext;
- public:
- ModuleInfo(ObjectFile *Obj, DIContext *DICtx)
- : Module(Obj), DebugInfoContext(DICtx) {}
-
- DILineInfo symbolizeCode(uint64_t ModuleOffset) const {
- DILineInfo LineInfo;
- if (DebugInfoContext) {
- LineInfo = DebugInfoContext->getLineInfoForAddress(
- ModuleOffset, getDILineInfoSpecifierFlags());
- }
- // Override function name from symbol table if necessary.
- if (PrintFunctions && UseSymbolTable) {
- std::string Function;
- if (getFunctionNameFromSymbolTable(ModuleOffset, Function)) {
- patchFunctionNameInDILineInfo(Function, LineInfo);
- }
- }
- return LineInfo;
- }
-
- DIInliningInfo symbolizeInlinedCode(uint64_t ModuleOffset) const {
- DIInliningInfo InlinedContext;
- if (DebugInfoContext) {
- InlinedContext = DebugInfoContext->getInliningInfoForAddress(
- ModuleOffset, getDILineInfoSpecifierFlags());
- }
- // Make sure there is at least one frame in context.
- if (InlinedContext.getNumberOfFrames() == 0) {
- InlinedContext.addFrame(DILineInfo());
- }
- // Override the function name in lower frame with name from symbol table.
- if (PrintFunctions && UseSymbolTable) {
- DIInliningInfo PatchedInlinedContext;
- for (uint32_t i = 0, n = InlinedContext.getNumberOfFrames();
- i != n; i++) {
- DILineInfo LineInfo = InlinedContext.getFrame(i);
- if (i == n - 1) {
- std::string Function;
- if (getFunctionNameFromSymbolTable(ModuleOffset, Function)) {
- patchFunctionNameInDILineInfo(Function, LineInfo);
- }
- }
- PatchedInlinedContext.addFrame(LineInfo);
- }
- InlinedContext = PatchedInlinedContext;
- }
- return InlinedContext;
- }
-
- private:
- bool getFunctionNameFromSymbolTable(uint64_t Address,
- std::string &FunctionName) const {
- assert(Module);
- error_code ec;
- for (symbol_iterator si = Module->begin_symbols(),
- se = Module->end_symbols();
- si != se; si.increment(ec)) {
- if (error(ec)) return false;
- uint64_t SymbolAddress;
- uint64_t SymbolSize;
- SymbolRef::Type SymbolType;
- if (error(si->getAddress(SymbolAddress)) ||
- SymbolAddress == UnknownAddressOrSize) continue;
- if (error(si->getSize(SymbolSize)) ||
- SymbolSize == UnknownAddressOrSize) continue;
- if (error(si->getType(SymbolType))) continue;
- // FIXME: If a function has alias, there are two entries in symbol table
- // with same address size. Make sure we choose the correct one.
- if (SymbolAddress <= Address && Address < SymbolAddress + SymbolSize &&
- SymbolType == SymbolRef::ST_Function) {
- StringRef Name;
- if (error(si->getName(Name))) continue;
- FunctionName = Name.str();
- return true;
- }
- }
- return false;
- }
-};
-
-typedef std::map<std::string, ModuleInfo*> ModuleMapTy;
-typedef ModuleMapTy::iterator ModuleMapIter;
-} // namespace
-
-static ModuleMapTy Modules;
-
-// Returns true if the object endianness is known.
-static bool getObjectEndianness(const ObjectFile *Obj,
- bool &IsLittleEndian) {
- // FIXME: Implement this when libLLVMObject allows to do it easily.
- IsLittleEndian = true;
- return true;
-}
-
-static ObjectFile *getObjectFile(const std::string &Path) {
- OwningPtr<MemoryBuffer> Buff;
- MemoryBuffer::getFile(Path, Buff);
- return ObjectFile::createObjectFile(Buff.take());
-}
-
-static std::string getDarwinDWARFResourceForModule(const std::string &Path) {
- StringRef Basename = sys::path::filename(Path);
- const std::string &DSymDirectory = Path + ".dSYM";
- SmallString<16> ResourceName = StringRef(DSymDirectory);
- sys::path::append(ResourceName, "Contents", "Resources", "DWARF");
- sys::path::append(ResourceName, Basename);
- return ResourceName.str();
-}
-
-static ModuleInfo *getOrCreateModuleInfo(const std::string &ModuleName) {
- ModuleMapIter I = Modules.find(ModuleName);
- if (I != Modules.end())
- return I->second;
-
- ObjectFile *Obj = getObjectFile(ModuleName);
- ObjectFile *DbgObj = Obj;
- if (Obj == 0) {
- // Module name doesn't point to a valid object file.
- Modules.insert(make_pair(ModuleName, (ModuleInfo*)0));
- return 0;
- }
-
- DIContext *Context = 0;
- bool IsLittleEndian;
- if (getObjectEndianness(Obj, IsLittleEndian)) {
- // On Darwin we may find DWARF in separate object file in
- // resource directory.
- if (isa<MachOObjectFile>(Obj)) {
- const std::string &ResourceName = getDarwinDWARFResourceForModule(
- ModuleName);
- ObjectFile *ResourceObj = getObjectFile(ResourceName);
- if (ResourceObj != 0)
- DbgObj = ResourceObj;
- }
- Context = DIContext::getDWARFContext(DbgObj);
- assert(Context);
- }
-
- ModuleInfo *Info = new ModuleInfo(Obj, Context);
- Modules.insert(make_pair(ModuleName, Info));
- return Info;
-}
-
-#if !defined(_MSC_VER)
-// Assume that __cxa_demangle is provided by libcxxabi (except for Windows).
-extern "C" char *__cxa_demangle(const char *mangled_name, char *output_buffer,
- size_t *length, int *status);
-#endif
-
-static void printDILineInfo(DILineInfo LineInfo) {
- // By default, DILineInfo contains "<invalid>" for function/filename it
- // cannot fetch. We replace it to "??" to make our output closer to addr2line.
- static const std::string kDILineInfoBadString = "<invalid>";
- static const std::string kSymbolizerBadString = "??";
- if (PrintFunctions) {
- std::string FunctionName = LineInfo.getFunctionName();
- if (FunctionName == kDILineInfoBadString)
- FunctionName = kSymbolizerBadString;
-#if !defined(_MSC_VER)
- if (Demangle) {
- int status = 0;
- char *DemangledName = __cxa_demangle(
- FunctionName.c_str(), 0, 0, &status);
- if (status == 0) {
- FunctionName = DemangledName;
- free(DemangledName);
- }
- }
-#endif
- outs() << FunctionName << "\n";
- }
- std::string Filename = LineInfo.getFileName();
- if (Filename == kDILineInfoBadString)
- Filename = kSymbolizerBadString;
- outs() << Filename <<
- ":" << LineInfo.getLine() <<
- ":" << LineInfo.getColumn() <<
- "\n";
-}
-
-static void symbolize(std::string ModuleName, std::string ModuleOffsetStr) {
- ModuleInfo *Info = getOrCreateModuleInfo(ModuleName);
- uint64_t Offset = 0;
- if (Info == 0 ||
- StringRef(ModuleOffsetStr).getAsInteger(0, Offset)) {
- printDILineInfo(DILineInfo());
- } else if (PrintInlining) {
- DIInliningInfo InlinedContext = Info->symbolizeInlinedCode(Offset);
- uint32_t FramesNum = InlinedContext.getNumberOfFrames();
- assert(FramesNum > 0);
- for (uint32_t i = 0; i < FramesNum; i++) {
- DILineInfo LineInfo = InlinedContext.getFrame(i);
- printDILineInfo(LineInfo);
- }
- } else {
- DILineInfo LineInfo = Info->symbolizeCode(Offset);
- printDILineInfo(LineInfo);
- }
-
- outs() << "\n"; // Print extra empty line to mark the end of output.
- outs().flush();
-}
-
-static bool parseModuleNameAndOffset(std::string &ModuleName,
- std::string &ModuleOffsetStr) {
- static const int kMaxInputStringLength = 1024;
- static const char kDelimiters[] = " \n";
+ClDemangle("demangle", cl::init(true), cl::desc("Demangle function names"));
+
+static bool parseCommand(bool &IsData, std::string &ModuleName,
+ uint64_t &ModuleOffset) {
+ const char *kDataCmd = "DATA ";
+ const char *kCodeCmd = "CODE ";
+ const int kMaxInputStringLength = 1024;
+ const char kDelimiters[] = " \n";
char InputString[kMaxInputStringLength];
if (!fgets(InputString, sizeof(InputString), stdin))
return false;
+ IsData = false;
ModuleName = "";
- ModuleOffsetStr = "";
+ std::string ModuleOffsetStr = "";
+ char *pos = InputString;
+ if (strncmp(pos, kDataCmd, strlen(kDataCmd)) == 0) {
+ IsData = true;
+ pos += strlen(kDataCmd);
+ } else if (strncmp(pos, kCodeCmd, strlen(kCodeCmd)) == 0) {
+ IsData = false;
+ pos += strlen(kCodeCmd);
+ } else {
+ // If no cmd, assume it's CODE.
+ IsData = false;
+ }
// FIXME: Handle case when filename is given in quotes.
- if (char *FilePath = strtok(InputString, kDelimiters)) {
+ if (char *FilePath = strtok(pos, kDelimiters)) {
ModuleName = FilePath;
- if (char *OffsetStr = strtok((char*)0, kDelimiters))
+ if (char *OffsetStr = strtok((char *)0, kDelimiters))
ModuleOffsetStr = OffsetStr;
}
+ if (StringRef(ModuleOffsetStr).getAsInteger(0, ModuleOffset))
+ return false;
return true;
}
@@ -308,15 +85,22 @@ int main(int argc, char **argv) {
// Print stack trace if we signal out.
sys::PrintStackTraceOnErrorSignal();
PrettyStackTraceProgram X(argc, argv);
- llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
+ llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
cl::ParseCommandLineOptions(argc, argv, "llvm symbolizer for compiler-rt\n");
- ToolInvocationPath = argv[0];
+ LLVMSymbolizer::Options Opts(ClUseSymbolTable, ClPrintFunctions,
+ ClPrintInlining, ClDemangle);
+ LLVMSymbolizer Symbolizer(Opts);
+ bool IsData = false;
std::string ModuleName;
- std::string ModuleOffsetStr;
- while (parseModuleNameAndOffset(ModuleName, ModuleOffsetStr)) {
- symbolize(ModuleName, ModuleOffsetStr);
+ uint64_t ModuleOffset;
+ while (parseCommand(IsData, ModuleName, ModuleOffset)) {
+ std::string Result =
+ IsData ? Symbolizer.symbolizeData(ModuleName, ModuleOffset)
+ : Symbolizer.symbolizeCode(ModuleName, ModuleOffset);
+ outs() << Result << "\n";
+ outs().flush();
}
return 0;
}
diff --git a/tools/lto/LTOCodeGenerator.cpp b/tools/lto/LTOCodeGenerator.cpp
index e87b378..477bd2d 100644
--- a/tools/lto/LTOCodeGenerator.cpp
+++ b/tools/lto/LTOCodeGenerator.cpp
@@ -387,6 +387,7 @@ bool LTOCodeGenerator::generateObjectFile(raw_ostream &out,
FunctionPassManager *codeGenPasses = new FunctionPassManager(mergedModule);
codeGenPasses->add(new DataLayout(*_target->getDataLayout()));
+ _target->addAnalysisPasses(*codeGenPasses);
formatted_raw_ostream Out(out);
diff --git a/tools/lto/LTOModule.cpp b/tools/lto/LTOModule.cpp
index 23a8fb4..ff67769 100644
--- a/tools/lto/LTOModule.cpp
+++ b/tools/lto/LTOModule.cpp
@@ -733,7 +733,8 @@ namespace {
return Symbols.end();
}
- RecordStreamer(MCContext &Context) : MCStreamer(Context) {}
+ RecordStreamer(MCContext &Context)
+ : MCStreamer(SK_RecordStreamer, Context) {}
virtual void EmitInstruction(const MCInst &Inst) {
// Scan for values.
@@ -771,6 +772,7 @@ namespace {
// Noop calls.
virtual void ChangeSection(const MCSection *Section) {}
+ virtual void InitToTextSection() {}
virtual void InitSections() {}
virtual void EmitAssemblerFlag(MCAssemblerFlag Flag) {}
virtual void EmitThumbFunc(MCSymbol *Func) {}
@@ -803,6 +805,10 @@ namespace {
const MCSymbol *Label,
unsigned PointerSize) {}
virtual void FinishImpl() {}
+
+ static bool classof(const MCStreamer *S) {
+ return S->getKind() == SK_RecordStreamer;
+ }
};
} // end anonymous namespace
diff --git a/tools/lto/Makefile b/tools/lto/Makefile
index 3610fed..ab2e16e 100644
--- a/tools/lto/Makefile
+++ b/tools/lto/Makefile
@@ -51,7 +51,7 @@ ifeq ($(HOST_OS),Darwin)
endif
# If we're doing an Apple-style build, add the LTO object path.
- ifeq ($(RC_BUILDIT),YES)
+ ifeq ($(RC_XBS),YES)
TempFile := $(shell mkdir -p ${OBJROOT}/dSYMs ; mktemp ${OBJROOT}/dSYMs/llvm-lto.XXXXXX)
LLVMLibsOptions := $(LLVMLibsOptions) \
-Wl,-object_path_lto -Wl,$(TempFile)
diff --git a/tools/macho-dump/macho-dump.cpp b/tools/macho-dump/macho-dump.cpp
index 20deda9..3bd3ecc 100644
--- a/tools/macho-dump/macho-dump.cpp
+++ b/tools/macho-dump/macho-dump.cpp
@@ -337,7 +337,7 @@ static int DumpDataInCodeDataCommand(MachOObject &Obj,
InMemoryStruct<macho::LinkeditDataLoadCommand> LLC;
Obj.ReadLinkeditDataLoadCommand(LCI, LLC);
if (!LLC)
- return Error("unable to read segment load command");
+ return Error("unable to read data-in-code load command");
outs() << " ('dataoff', " << LLC->DataOffset << ")\n"
<< " ('datasize', " << LLC->DataSize << ")\n"
@@ -361,6 +361,31 @@ static int DumpDataInCodeDataCommand(MachOObject &Obj,
return 0;
}
+static int DumpLinkerOptionsCommand(MachOObject &Obj,
+ const MachOObject::LoadCommandInfo &LCI) {
+ InMemoryStruct<macho::LinkerOptionsLoadCommand> LOLC;
+ Obj.ReadLinkerOptionsLoadCommand(LCI, LOLC);
+ if (!LOLC)
+ return Error("unable to read linker options load command");
+
+ outs() << " ('count', " << LOLC->Count << ")\n"
+ << " ('_strings', [\n";
+
+ uint64_t DataSize = LOLC->Size - sizeof(macho::LinkerOptionsLoadCommand);
+ StringRef Data = Obj.getData(
+ LCI.Offset + sizeof(macho::LinkerOptionsLoadCommand), DataSize);
+ for (unsigned i = 0; i != LOLC->Count; ++i) {
+ std::pair<StringRef,StringRef> Split = Data.split('\0');
+ outs() << "\t\"";
+ outs().write_escaped(Split.first);
+ outs() << "\",\n";
+ Data = Split.second;
+ }
+ outs() <<" ])\n";
+
+ return 0;
+}
+
static int DumpLoadCommand(MachOObject &Obj, unsigned Index) {
const MachOObject::LoadCommandInfo &LCI = Obj.getLoadCommandInfo(Index);
@@ -390,6 +415,9 @@ static int DumpLoadCommand(MachOObject &Obj, unsigned Index) {
case macho::LCT_DataInCode:
Res = DumpDataInCodeDataCommand(Obj, LCI);
break;
+ case macho::LCT_LinkerOptions:
+ Res = DumpLinkerOptionsCommand(Obj, LCI);
+ break;
default:
Warning("unknown load command: " + Twine(LCI.Command.Type));
break;
diff --git a/tools/opt/CMakeLists.txt b/tools/opt/CMakeLists.txt
index 32de6d4..cf5e5a8 100644
--- a/tools/opt/CMakeLists.txt
+++ b/tools/opt/CMakeLists.txt
@@ -1,4 +1,4 @@
-set(LLVM_LINK_COMPONENTS ${LLVM_TARGETS_TO_BUILD} bitreader asmparser bitwriter instrumentation scalaropts ipo vectorize)
+set(LLVM_LINK_COMPONENTS ${LLVM_TARGETS_TO_BUILD} bitreader asmparser bitwriter instrumentation scalaropts objcarcopts ipo vectorize)
add_llvm_tool(opt
AnalysisWrappers.cpp
diff --git a/tools/opt/GraphPrinters.cpp b/tools/opt/GraphPrinters.cpp
index c7481e5..f271966 100644
--- a/tools/opt/GraphPrinters.cpp
+++ b/tools/opt/GraphPrinters.cpp
@@ -14,81 +14,10 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/Analysis/CallGraph.h"
#include "llvm/Analysis/Dominators.h"
-#include "llvm/IR/Value.h"
#include "llvm/Pass.h"
-#include "llvm/Support/GraphWriter.h"
-#include "llvm/Support/ToolOutputFile.h"
-using namespace llvm;
-
-template<typename GraphType>
-static void WriteGraphToFile(raw_ostream &O, const std::string &GraphName,
- const GraphType &GT) {
- std::string Filename = GraphName + ".dot";
- O << "Writing '" << Filename << "'...";
- std::string ErrInfo;
- tool_output_file F(Filename.c_str(), ErrInfo);
-
- if (ErrInfo.empty()) {
- WriteGraph(F.os(), GT);
- F.os().close();
- if (!F.os().has_error()) {
- O << "\n";
- F.keep();
- return;
- }
- }
- O << " error opening file for writing!\n";
- F.os().clear_error();
-}
-
-
-//===----------------------------------------------------------------------===//
-// Call Graph Printer
-//===----------------------------------------------------------------------===//
-
-namespace llvm {
- template<>
- struct DOTGraphTraits<CallGraph*> : public DefaultDOTGraphTraits {
-
- DOTGraphTraits (bool isSimple=false) : DefaultDOTGraphTraits(isSimple) {}
-
- static std::string getGraphName(CallGraph *F) {
- return "Call Graph";
- }
- static std::string getNodeLabel(CallGraphNode *Node, CallGraph *Graph) {
- if (Node->getFunction())
- return ((Value*)Node->getFunction())->getName();
- return "external node";
- }
- };
-}
-
-
-namespace {
- struct CallGraphPrinter : public ModulePass {
- static char ID; // Pass ID, replacement for typeid
- CallGraphPrinter() : ModulePass(ID) {}
-
- virtual bool runOnModule(Module &M) {
- WriteGraphToFile(llvm::errs(), "callgraph", &getAnalysis<CallGraph>());
- return false;
- }
-
- void print(raw_ostream &OS, const llvm::Module*) const {}
-
- virtual void getAnalysisUsage(AnalysisUsage &AU) const {
- AU.addRequired<CallGraph>();
- AU.setPreservesAll();
- }
- };
-}
-
-char CallGraphPrinter::ID = 0;
-static RegisterPass<CallGraphPrinter> P2("dot-callgraph",
- "Print Call Graph to 'dot' file");
+using namespace llvm;
//===----------------------------------------------------------------------===//
// DomInfoPrinter Pass
diff --git a/tools/opt/LLVMBuild.txt b/tools/opt/LLVMBuild.txt
index b174431..a866d12 100644
--- a/tools/opt/LLVMBuild.txt
+++ b/tools/opt/LLVMBuild.txt
@@ -19,4 +19,4 @@
type = Tool
name = opt
parent = Tools
-required_libraries = AsmParser BitReader BitWriter IPO Instrumentation Scalar all-targets
+required_libraries = AsmParser BitReader BitWriter IPO Instrumentation Scalar ObjCARC all-targets
diff --git a/tools/opt/Makefile b/tools/opt/Makefile
index ee7e1cf..79ed815 100644
--- a/tools/opt/Makefile
+++ b/tools/opt/Makefile
@@ -9,6 +9,6 @@
LEVEL := ../..
TOOLNAME := opt
-LINK_COMPONENTS := bitreader bitwriter asmparser instrumentation scalaropts ipo vectorize all-targets
+LINK_COMPONENTS := bitreader bitwriter asmparser instrumentation scalaropts objcarcopts ipo vectorize all-targets
include $(LEVEL)/Makefile.common
diff --git a/tools/opt/opt.cpp b/tools/opt/opt.cpp
index ac8323b..81a2de2 100644
--- a/tools/opt/opt.cpp
+++ b/tools/opt/opt.cpp
@@ -26,8 +26,8 @@
#include "llvm/DebugInfo.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/Module.h"
+#include "llvm/LinkAllIR.h"
#include "llvm/LinkAllPasses.h"
-#include "llvm/LinkAllVMCore.h"
#include "llvm/MC/SubtargetFeature.h"
#include "llvm/PassManager.h"
#include "llvm/Support/Debug.h"
@@ -567,6 +567,7 @@ int main(int argc, char **argv) {
PassRegistry &Registry = *PassRegistry::getPassRegistry();
initializeCore(Registry);
initializeScalarOpts(Registry);
+ initializeObjCARCOpts(Registry);
initializeVectorization(Registry);
initializeIPO(Registry);
initializeAnalysis(Registry);