Change the x86 unwinder from using edis as its disassembler

API (to get the length of x86 instructions) to using the LLVM-MC
disassembler.
<rdar://problem/12411000>

llvm-svn: 165587
This commit is contained in:
Jason Molenda 2012-10-10 01:45:33 +00:00
parent 3f31fa05d5
commit a8399a8cf1
2 changed files with 46 additions and 67 deletions

View File

@ -9,7 +9,7 @@
#include "UnwindAssembly-x86.h"
#include "llvm-c/EnhancedDisassembly.h"
#include "llvm-c/Disassembler.h"
#include "llvm/Support/TargetSelect.h"
#include "lldb/Core/Address.h"
@ -117,7 +117,9 @@ static int x86_64_register_map_initialized = 0;
class AssemblyParse_x86 {
public:
AssemblyParse_x86 (const ExecutionContext &exe_ctx, int cpu, AddressRange func);
AssemblyParse_x86 (const ExecutionContext &exe_ctx, int cpu, ArchSpec &arch, AddressRange func);
~AssemblyParse_x86 ();
bool get_non_call_site_unwind_plan (UnwindPlan &unwind_plan);
@ -157,11 +159,13 @@ private:
int m_wordsize;
int m_cpu;
ArchSpec m_arch;
::LLVMDisasmContextRef m_disasm_context;
DISALLOW_COPY_AND_ASSIGN (AssemblyParse_x86);
};
AssemblyParse_x86::AssemblyParse_x86 (const ExecutionContext &exe_ctx, int cpu, AddressRange func) :
AssemblyParse_x86::AssemblyParse_x86 (const ExecutionContext &exe_ctx, int cpu, ArchSpec &arch, AddressRange func) :
m_exe_ctx (exe_ctx),
m_func_bounds(func),
m_cur_insn (),
@ -172,7 +176,8 @@ AssemblyParse_x86::AssemblyParse_x86 (const ExecutionContext &exe_ctx, int cpu,
m_lldb_sp_regnum (LLDB_INVALID_REGNUM),
m_lldb_fp_regnum (LLDB_INVALID_REGNUM),
m_wordsize (-1),
m_cpu(cpu)
m_cpu(cpu),
m_arch(arch)
{
int *initialized_flag = NULL;
if (cpu == k_i386)
@ -236,8 +241,18 @@ AssemblyParse_x86::AssemblyParse_x86 (const ExecutionContext &exe_ctx, int cpu,
if (machine_regno_to_lldb_regno (m_machine_ip_regnum, lldb_regno))
m_lldb_ip_regnum = lldb_regno;
}
m_disasm_context = ::LLVMCreateDisasm(m_arch.GetTriple().getTriple().c_str(),
(void*)this,
/*TagType=*/1,
NULL,
NULL);
}
AssemblyParse_x86::~AssemblyParse_x86 ()
{
::LLVMDisasmDispose(m_disasm_context);
}
// This function expects an x86 native register number (i.e. the bits stripped out of the
// actual instruction), not an lldb register number.
@ -451,79 +466,39 @@ AssemblyParse_x86::machine_regno_to_lldb_regno (int machine_regno, uint32_t &lld
return false;
}
struct edis_byte_read_token
{
Address *address;
Target *target;
};
static int
read_byte_for_edis (uint8_t *buf, uint64_t offset_address, void *arg)
{
if (arg == 0)
return -1;
struct edis_byte_read_token *tok = (edis_byte_read_token *) arg;
Address *base_address = tok->address;
Target *target = tok->target;
Address read_addr = *base_address;
read_addr.SetOffset (offset_address);
uint8_t onebyte_buf[1];
Error error;
const bool prefer_file_cache = true;
if (target->ReadMemory (read_addr, prefer_file_cache, onebyte_buf, 1, error) != -1)
{
*buf = onebyte_buf[0];
return 0;
}
return -1;
}
bool
AssemblyParse_x86::instruction_length (Address addr, int &length)
{
const char *triple;
const uint32_t max_op_byte_size = m_arch.GetMaximumOpcodeByteSize();
if (!addr.IsValid())
return false;
// FIXME should probably pass down the ArchSpec and work from that to make a portable triple
if (m_cpu == k_i386)
triple = "i386-unknown-unknown";
else
triple = "x86_64-unknown-unknown";
// Initialize the LLVM objects needed to use the disassembler.
static struct InitializeLLVM {
InitializeLLVM() {
llvm::InitializeAllTargetInfos();
llvm::InitializeAllTargetMCs();
llvm::InitializeAllAsmParsers();
llvm::InitializeAllDisassemblers();
}
} InitializeLLVM;
EDDisassemblerRef disasm;
EDInstRef cur_insn;
if (EDGetDisassembler (&disasm, triple, kEDAssemblySyntaxX86ATT) != 0)
uint8_t *opcode_data = (uint8_t *) malloc (max_op_byte_size);
if (opcode_data == NULL)
{
return false;
}
uint64_t addr_offset = addr.GetOffset();
struct edis_byte_read_token arg;
arg.address = &addr;
arg.target = m_exe_ctx.GetTargetPtr();
if (EDCreateInsts (&cur_insn, 1, disasm, read_byte_for_edis, addr_offset, &arg) != 1)
const bool prefer_file_cache = true;
Error error;
Target *target = m_exe_ctx.GetTargetPtr();
if (target->ReadMemory (addr, prefer_file_cache, opcode_data, max_op_byte_size, error) == -1)
{
return false;
}
length = EDInstByteSize (cur_insn);
EDReleaseInst (cur_insn);
char out_string[512];
const addr_t pc = addr.GetFileAddress();
const size_t inst_size = ::LLVMDisasmInstruction (m_disasm_context,
opcode_data,
max_op_byte_size,
pc, // PC value
out_string,
sizeof(out_string));
length = inst_size;
return true;
}
@ -907,7 +882,8 @@ AssemblyParse_x86::find_first_non_prologue_insn (Address &address)
UnwindAssembly_x86::UnwindAssembly_x86 (const ArchSpec &arch, int cpu) :
lldb_private::UnwindAssembly(arch),
m_cpu(cpu)
m_cpu(cpu),
m_arch(arch)
{
}
@ -920,7 +896,7 @@ bool
UnwindAssembly_x86::GetNonCallSiteUnwindPlanFromAssembly (AddressRange& func, Thread& thread, UnwindPlan& unwind_plan)
{
ExecutionContext exe_ctx (thread.shared_from_this());
AssemblyParse_x86 asm_parse(exe_ctx, m_cpu, func);
AssemblyParse_x86 asm_parse(exe_ctx, m_cpu, m_arch, func);
return asm_parse.get_non_call_site_unwind_plan (unwind_plan);
}
@ -928,14 +904,14 @@ bool
UnwindAssembly_x86::GetFastUnwindPlan (AddressRange& func, Thread& thread, UnwindPlan &unwind_plan)
{
ExecutionContext exe_ctx (thread.shared_from_this());
AssemblyParse_x86 asm_parse(exe_ctx, m_cpu, func);
AssemblyParse_x86 asm_parse(exe_ctx, m_cpu, m_arch, func);
return asm_parse.get_fast_unwind_plan (func, unwind_plan);
}
bool
UnwindAssembly_x86::FirstNonPrologueInsn (AddressRange& func, const ExecutionContext &exe_ctx, Address& first_non_prologue_insn)
{
AssemblyParse_x86 asm_parse(exe_ctx, m_cpu, func);
AssemblyParse_x86 asm_parse(exe_ctx, m_cpu, m_arch, func);
return asm_parse.find_first_non_prologue_insn (first_non_prologue_insn);
}

View File

@ -10,6 +10,8 @@
#ifndef liblldb_UnwindAssembly_x86_h_
#define liblldb_UnwindAssembly_x86_h_
#include "llvm-c/Disassembler.h"
#include "lldb/lldb-private.h"
#include "lldb/Target/UnwindAssembly.h"
@ -67,6 +69,7 @@ private:
UnwindAssembly_x86 (const lldb_private::ArchSpec &arch, int cpu);
int m_cpu;
lldb_private::ArchSpec m_arch;
};