#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"
#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"
enum ActionType {
AC_Execute,
+ AC_PrintObjectLineInfo,
AC_PrintLineInfo,
+ AC_PrintDebugLineInfo,
AC_Verify
};
"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_PrintObjectLineInfo, "printobjline",
+ "Like -printlineinfo but does not load the object first"),
clEnumValN(AC_Verify, "verify",
"Load, link and verify the resulting memory image."),
clEnumValEnd));
/* *** */
-static int printLineInfoForInput() {
+static int printLineInfoForInput(bool LoadObjects, bool UseDebugObj) {
+ assert(LoadObjects || !UseDebugObj);
+
// Load any dylibs requested on the command line.
loadDylibs();
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.
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()));
+
+ // FIXME: This is generally useful. Figure out a place in lib/Object to
+ // put utility functions.
+ std::map<object::SectionRef, std::vector<uint64_t>> FuncAddresses;
+ if (!isa<ELFObjectFileBase>(SymbolObj)) {
+ for (object::SymbolRef Sym : SymbolObj->symbols()) {
+ object::SymbolRef::Type SymType;
+ if (Sym.getType(SymType))
+ continue;
+ if (SymType != object::SymbolRef::ST_Function)
+ continue;
+ uint64_t Addr;
+ if (Sym.getAddress(Addr))
+ continue;
+ object::section_iterator Sec = SymbolObj->section_end();
+ if (Sym.getSection(Sec))
+ continue;
+ std::vector<uint64_t> &Addrs = FuncAddresses[*Sec];
+ if (Addrs.empty()) {
+ uint64_t SecAddr = Sec->getAddress();
+ uint64_t SecSize = Sec->getSize();
+ Addrs.push_back(SecAddr + SecSize);
+ }
+ Addrs.push_back(Addr);
+ }
+ for (auto &Pair : FuncAddresses) {
+ std::vector<uint64_t> &Addrs = Pair.second;
+ array_pod_sort(Addrs.begin(), Addrs.end());
+ }
+ }
// Use symbol info to iterate functions in the object.
- for (object::symbol_iterator I = DebugObj.getBinary()->symbol_begin(),
- E = DebugObj.getBinary()->symbol_end();
- I != E; ++I) {
+ for (object::SymbolRef Sym : SymbolObj->symbols()) {
object::SymbolRef::Type SymType;
- if (I->getType(SymType)) continue;
+ if (Sym.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;
+ if (Sym.getName(Name))
+ continue;
+ if (Sym.getAddress(Addr))
+ continue;
+
+ uint64_t Size;
+ if (isa<ELFObjectFileBase>(SymbolObj)) {
+ Size = Sym.getSize();
+ } else {
+ object::section_iterator Sec = SymbolObj->section_end();
+ if (Sym.getSection(Sec))
+ continue;
+ const std::vector<uint64_t> &Addrs = FuncAddresses[*Sec];
+ auto AddrI = std::find(Addrs.begin(), Addrs.end(), Addr);
+ assert(AddrI != Addrs.end() && (AddrI + 1) != Addrs.end());
+ assert(*AddrI == Addr);
+ Size = *(AddrI + 1) - Addr;
+ }
- 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());
+ Sym.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();
// 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())
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);
// 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 + "'");
return 0;
}
-std::map<void*, uint64_t>
+static std::map<void *, uint64_t>
applySpecificSectionMappings(RuntimeDyldChecker &Checker) {
std::map<void*, uint64_t> SpecificMappings;
// 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;
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("-");
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);
switch (Action) {
case AC_Execute:
return executeInput();
+ case AC_PrintDebugLineInfo:
+ return printLineInfoForInput(/* LoadObjects */ true,/* UseDebugObj */ true);
case AC_PrintLineInfo:
- return printLineInfoForInput();
+ return printLineInfoForInput(/* LoadObjects */ true,/* UseDebugObj */false);
+ case AC_PrintObjectLineInfo:
+ return printLineInfoForInput(/* LoadObjects */false,/* UseDebugObj */false);
case AC_Verify:
return linkAndVerify();
}