[RuntimeDyld] Adds the necessary hooks to MCJIT to be able to debug generated

MachO files using the GDB JIT debugging interface.

Patch by Keno Fischer. Thanks Keno!



git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@211652 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Lang Hames 2014-06-25 00:20:53 +00:00
parent 49b52b35d4
commit 7ede4b96de
4 changed files with 133 additions and 12 deletions

View File

@ -228,10 +228,12 @@ public:
return v->isMachO();
}
const char *getSectionPointer(DataRefImpl Rel) const;
private:
typedef SmallVector<const char*, 1> SectionList;
typedef SmallVector<const char *, 1> SectionList;
SectionList Sections;
typedef SmallVector<const char*, 1> LibraryList;
typedef SmallVector<const char *, 1> LibraryList;
LibraryList Libraries;
typedef SmallVector<StringRef, 1> LibraryShortName;
LibraryShortName LibrariesShortNames;

View File

@ -14,6 +14,8 @@
#include "RuntimeDyldMachO.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringRef.h"
#include "ObjectImageCommon.h"
#include "JITRegistrar.h"
using namespace llvm;
using namespace llvm::object;
@ -21,6 +23,123 @@ using namespace llvm::object;
namespace llvm {
class MachOObjectImage : public ObjectImageCommon {
private:
typedef SmallVector<uint64_t, 1> SectionAddrList;
SectionAddrList OldSectionAddrList;
protected:
bool is64;
bool Registered;
private:
void initOldAddress() {
MachOObjectFile *objf = static_cast<MachOObjectFile *>(ObjFile.get());
// Unfortunately we need to do this, since there's information encoded
// in the original addr of the section that we could not otherwise
// recover. The reason for this is that symbols do not actually store
// their file offset, but only their vmaddr. This means that in order
// to locate the symbol correctly in the object file, we need to know
// where the original start of the section was (including any padding,
// etc).
for (section_iterator i = objf->section_begin(), e = objf->section_end();
i != e; ++i) {
uint64_t Addr;
i->getAddress(Addr);
OldSectionAddrList[i->getRawDataRefImpl().d.a] = Addr;
}
}
public:
MachOObjectImage(ObjectBuffer *Input, bool is64)
: ObjectImageCommon(Input),
OldSectionAddrList(ObjFile->section_end()->getRawDataRefImpl().d.a, 0),
is64(is64), Registered(false) {
initOldAddress();
}
MachOObjectImage(std::unique_ptr<object::ObjectFile> Input, bool is64)
: ObjectImageCommon(std::move(Input)),
OldSectionAddrList(ObjFile->section_end()->getRawDataRefImpl().d.a, 0),
is64(is64), Registered(false) {
initOldAddress();
}
virtual ~MachOObjectImage() {}
// Subclasses can override these methods to update the image with loaded
// addresses for sections and common symbols
virtual void updateSectionAddress(const SectionRef &Sec, uint64_t Addr) {
MachOObjectFile *objf = static_cast<MachOObjectFile *>(ObjFile.get());
char *data =
const_cast<char *>(objf->getSectionPointer(Sec.getRawDataRefImpl()));
uint64_t oldAddr = OldSectionAddrList[Sec.getRawDataRefImpl().d.a];
if (is64) {
((MachO::section_64 *)data)->addr = Addr;
} else {
((MachO::section *)data)->addr = Addr;
}
for (symbol_iterator i = objf->symbol_begin(), e = objf->symbol_end();
i != e; ++i) {
section_iterator symSec(objf->section_end());
(*i).getSection(symSec);
if (*symSec == Sec) {
uint64_t symAddr;
(*i).getAddress(symAddr);
updateSymbolAddress(*i, symAddr + Addr - oldAddr);
}
}
}
uint64_t getOldSectionAddr(const SectionRef &Sec) const {
return OldSectionAddrList[Sec.getRawDataRefImpl().d.a];
}
virtual void updateSymbolAddress(const SymbolRef &Sym, uint64_t Addr) {
char *data = const_cast<char *>(
reinterpret_cast<const char *>(Sym.getRawDataRefImpl().p));
if (is64)
((MachO::nlist_64 *)data)->n_value = Addr;
else
((MachO::nlist *)data)->n_value = Addr;
}
virtual void registerWithDebugger() {
JITRegistrar::getGDBRegistrar().registerObject(*Buffer);
Registered = true;
}
virtual void deregisterWithDebugger() {
JITRegistrar::getGDBRegistrar().deregisterObject(*Buffer);
}
};
ObjectImage *RuntimeDyldMachO::createObjectImage(ObjectBuffer *Buffer) {
uint32_t magic = *((uint32_t *)Buffer->getBufferStart());
bool is64 = (magic == MachO::MH_MAGIC_64);
assert((magic == MachO::MH_MAGIC_64 || magic == MachO::MH_MAGIC) &&
"Unrecognized Macho Magic");
return new MachOObjectImage(Buffer, is64);
}
ObjectImage *RuntimeDyldMachO::createObjectImageFromFile(
std::unique_ptr<object::ObjectFile> ObjFile) {
if (!ObjFile)
return nullptr;
MemoryBuffer *Buffer =
MemoryBuffer::getMemBuffer(ObjFile->getData(), "", false);
uint32_t magic = *((uint32_t *)Buffer->getBufferStart());
bool is64 = (magic == MachO::MH_MAGIC_64);
assert((magic == MachO::MH_MAGIC_64 || magic == MachO::MH_MAGIC) &&
"Unrecognized Macho Magic");
return new MachOObjectImage(std::move(ObjFile), is64);
}
static unsigned char *processFDE(unsigned char *P, intptr_t DeltaForText,
intptr_t DeltaForEH) {
DEBUG(dbgs() << "Processing FDE: Delta for text: " << DeltaForText
@ -533,6 +652,7 @@ relocation_iterator RuntimeDyldMachO::processRelocationRef(
ObjSectionToIDMap &ObjSectionToID, const SymbolTableMap &Symbols,
StubMap &Stubs) {
const ObjectFile *OF = Obj.getObjectFile();
const MachOObjectImage &MachOObj = *static_cast<MachOObjectImage *>(&Obj);
const MachOObjectFile *MachO = static_cast<const MachOObjectFile *>(OF);
MachO::any_relocation_info RE =
MachO->getRelocation(RelI->getRawDataRefImpl());
@ -609,8 +729,8 @@ relocation_iterator RuntimeDyldMachO::processRelocationRef(
bool IsCode = false;
Sec.isText(IsCode);
Value.SectionID = findOrEmitSection(Obj, Sec, IsCode, ObjSectionToID);
uint64_t Addr;
Sec.getAddress(Addr);
uint64_t Addr = MachOObj.getOldSectionAddr(Sec);
DEBUG(dbgs() << "\nAddr: " << Addr << "\nAddend: " << Addend);
Value.Addend = Addend - Addr;
if (IsPCRel)
Value.Addend += Offset + NumBytes;

View File

@ -105,14 +105,9 @@ public:
void finalizeLoad(ObjectImage &ObjImg,
ObjSectionToIDMap &SectionMap) override;
static ObjectImage *createObjectImage(ObjectBuffer *InputBuffer) {
return new ObjectImageCommon(InputBuffer);
}
static ObjectImage *createObjectImage(ObjectBuffer *Buffer);
static ObjectImage *
createObjectImageFromFile(std::unique_ptr<object::ObjectFile> InputObject) {
return new ObjectImageCommon(std::move(InputObject));
}
createObjectImageFromFile(std::unique_ptr<object::ObjectFile> InputObject);
};
} // end namespace llvm

View File

@ -1797,7 +1797,7 @@ StringRef MachOObjectFile::getStringTableData() const {
bool MachOObjectFile::is64Bit() const {
return getType() == getMachOType(false, true) ||
getType() == getMachOType(true, true);
getType() == getMachOType(true, true);
}
void MachOObjectFile::ReadULEB128s(uint64_t Index,
@ -1812,6 +1812,10 @@ void MachOObjectFile::ReadULEB128s(uint64_t Index,
}
}
const char *MachOObjectFile::getSectionPointer(DataRefImpl Rel) const {
return Sections[Rel.d.a];
}
ErrorOr<ObjectFile *>
ObjectFile::createMachOObjectFile(std::unique_ptr<MemoryBuffer> &Buffer) {
StringRef Magic = Buffer->getBuffer().slice(0, 4);