diff options
Diffstat (limited to 'contrib/llvm/tools/llvm-rtdyld/llvm-rtdyld.cpp')
-rw-r--r-- | contrib/llvm/tools/llvm-rtdyld/llvm-rtdyld.cpp | 155 |
1 files changed, 126 insertions, 29 deletions
diff --git a/contrib/llvm/tools/llvm-rtdyld/llvm-rtdyld.cpp b/contrib/llvm/tools/llvm-rtdyld/llvm-rtdyld.cpp index 5b6f301..f857b2e 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" @@ -44,7 +47,9 @@ InputFileList(cl::Positional, cl::ZeroOrMore, enum ActionType { AC_Execute, + AC_PrintObjectLineInfo, AC_PrintLineInfo, + AC_PrintDebugLineInfo, AC_Verify }; @@ -55,6 +60,10 @@ 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_PrintObjectLineInfo, "printobjline", + "Like -printlineinfo but does not load the object first"), clEnumValN(AC_Verify, "verify", "Load, link and verify the resulting memory image."), clEnumValEnd)); @@ -130,6 +139,11 @@ public: // explicit cache flush, otherwise JIT code manipulations (like resolved // relocations) will get to the data cache but not to the instruction cache. virtual void invalidateInstructionCache(); + + void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr, + size_t Size) override {} + void deregisterEHFrames(uint8_t *Addr, uint64_t LoadAddr, + size_t Size) override {} }; uint8_t *TrivialMemoryManager::allocateCodeSection(uintptr_t Size, @@ -186,7 +200,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 +212,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,36 +229,101 @@ 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())); + + // 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(); @@ -264,7 +345,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 +368,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 +385,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 +426,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 +484,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 +593,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 +628,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 +672,12 @@ int main(int argc, char **argv) { 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(); } |