JITDebugRegisterer.cpp [plain text]
#include "JITDebugRegisterer.h"
#include "../../CodeGen/ELF.h"
#include "../../CodeGen/ELFWriter.h"
#include "llvm/LLVMContext.h"
#include "llvm/Function.h"
#include "llvm/Module.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/MutexGuard.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/Mutex.h"
#include <string>
namespace llvm {
extern "C" {
LLVM_ATTRIBUTE_NOINLINE void __jit_debug_register_code() { }
struct jit_descriptor __jit_debug_descriptor = { 1, 0, 0, 0 };
}
namespace {
sys::Mutex JITDebugLock;
}
JITDebugRegisterer::JITDebugRegisterer(TargetMachine &tm) : TM(tm), FnMap() { }
JITDebugRegisterer::~JITDebugRegisterer() {
for (RegisteredFunctionsMap::iterator I = FnMap.begin(), E = FnMap.end();
I != E; ++I) {
UnregisterFunctionInternal(I);
}
FnMap.clear();
}
std::string JITDebugRegisterer::MakeELF(const Function *F, DebugInfo &I) {
LLVMContext Context;
Module M("", Context);
std::string Buffer;
raw_string_ostream O(Buffer);
ELFWriter EW(O, TM);
EW.doInitialization(M);
ELFSection &Text = EW.getTextSection(const_cast<Function *>(F));
Text.Addr = (uint64_t)I.FnStart;
Text.getData().assign(I.FnStart, I.FnEnd);
ELFSection &EH = EW.getSection(".eh_frame", ELF::SHT_PROGBITS,
ELF::SHF_ALLOC);
EH.Addr = (uint64_t)I.EhStart;
EH.getData().assign(I.EhStart, I.EhEnd);
ELFSym *FnSym = ELFSym::getGV(F,
ELF::STB_GLOBAL,
ELF::STT_FUNC,
ELF::STV_DEFAULT);
FnSym->SectionIdx = Text.SectionIdx;
FnSym->Size = I.FnEnd - I.FnStart;
FnSym->Value = 0; EW.SymbolList.push_back(FnSym);
EW.doFinalization(M);
O.flush();
if (JITEmitDebugInfoToDisk) {
std::string Filename;
raw_string_ostream O2(Filename);
O2 << "/tmp/llvm_function_" << I.FnStart << "_" << F->getNameStr() << ".o";
O2.flush();
std::string Errors;
raw_fd_ostream O3(Filename.c_str(), Errors);
O3 << Buffer;
O3.close();
}
return Buffer;
}
void JITDebugRegisterer::RegisterFunction(const Function *F, DebugInfo &I) {
if (!TM.getELFWriterInfo())
return;
std::string Buffer = MakeELF(F, I);
jit_code_entry *JITCodeEntry = new jit_code_entry();
JITCodeEntry->symfile_addr = Buffer.c_str();
JITCodeEntry->symfile_size = Buffer.size();
FnMap[F] = std::make_pair(Buffer, JITCodeEntry);
{
MutexGuard locked(JITDebugLock);
__jit_debug_descriptor.action_flag = JIT_REGISTER_FN;
JITCodeEntry->prev_entry = NULL;
jit_code_entry *NextEntry = __jit_debug_descriptor.first_entry;
JITCodeEntry->next_entry = NextEntry;
if (NextEntry != NULL) {
NextEntry->prev_entry = JITCodeEntry;
}
__jit_debug_descriptor.first_entry = JITCodeEntry;
__jit_debug_descriptor.relevant_entry = JITCodeEntry;
__jit_debug_register_code();
}
}
void JITDebugRegisterer::UnregisterFunctionInternal(
RegisteredFunctionsMap::iterator I) {
jit_code_entry *&JITCodeEntry = I->second.second;
{
MutexGuard locked(JITDebugLock);
__jit_debug_descriptor.action_flag = JIT_UNREGISTER_FN;
jit_code_entry *PrevEntry = JITCodeEntry->prev_entry;
jit_code_entry *NextEntry = JITCodeEntry->next_entry;
if (NextEntry) {
NextEntry->prev_entry = PrevEntry;
}
if (PrevEntry) {
PrevEntry->next_entry = NextEntry;
} else {
assert(__jit_debug_descriptor.first_entry == JITCodeEntry);
__jit_debug_descriptor.first_entry = NextEntry;
}
__jit_debug_descriptor.relevant_entry = JITCodeEntry;
__jit_debug_register_code();
}
delete JITCodeEntry;
JITCodeEntry = NULL;
std::string &Buffer = I->second.first;
Buffer.clear();
}
void JITDebugRegisterer::UnregisterFunction(const Function *F) {
if (!TM.getELFWriterInfo())
return;
RegisteredFunctionsMap::iterator I = FnMap.find(F);
if (I == FnMap.end()) return;
UnregisterFunctionInternal(I);
FnMap.erase(I);
}
}