forked from OSchip/llvm-project
<rdar://problem/11730263>
PC relative loads are missing disassembly comments when disassembled in a live process. This issue was because some sections, like __TEXT and __DATA in libobjc.A.dylib, were being moved when they were put into the dyld shared cache. This could also affect any other system that slides sections individually. The solution is to keep track of wether the bytes we will disassemble are from an executable file (file address), or from a live process (load address). We now do the right thing based off of this input in all cases. llvm-svn: 178315
This commit is contained in:
parent
a486a11dcf
commit
3faf47c462
|
@ -1246,8 +1246,6 @@ public:
|
||||||
bool
|
bool
|
||||||
Append (void* bytes, lldb::offset_t length);
|
Append (void* bytes, lldb::offset_t length);
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
lldb::offset_t
|
lldb::offset_t
|
||||||
BytesLeft (lldb::offset_t offset) const
|
BytesLeft (lldb::offset_t offset) const
|
||||||
{
|
{
|
||||||
|
@ -1257,6 +1255,8 @@ protected:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
//------------------------------------------------------------------
|
//------------------------------------------------------------------
|
||||||
// Member variables
|
// Member variables
|
||||||
//------------------------------------------------------------------
|
//------------------------------------------------------------------
|
||||||
|
|
|
@ -273,7 +273,8 @@ public:
|
||||||
const Address &start,
|
const Address &start,
|
||||||
const void *bytes,
|
const void *bytes,
|
||||||
size_t length,
|
size_t length,
|
||||||
uint32_t num_instructions = UINT32_MAX);
|
uint32_t max_num_instructions,
|
||||||
|
bool data_from_file);
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
Disassemble (Debugger &debugger,
|
Disassemble (Debugger &debugger,
|
||||||
|
@ -356,19 +357,22 @@ public:
|
||||||
size_t
|
size_t
|
||||||
ParseInstructions (const ExecutionContext *exe_ctx,
|
ParseInstructions (const ExecutionContext *exe_ctx,
|
||||||
const AddressRange &range,
|
const AddressRange &range,
|
||||||
Stream *error_strm_ptr);
|
Stream *error_strm_ptr,
|
||||||
|
bool prefer_file_cache);
|
||||||
|
|
||||||
size_t
|
size_t
|
||||||
ParseInstructions (const ExecutionContext *exe_ctx,
|
ParseInstructions (const ExecutionContext *exe_ctx,
|
||||||
const Address &range,
|
const Address &range,
|
||||||
uint32_t num_instructions);
|
uint32_t num_instructions,
|
||||||
|
bool prefer_file_cache);
|
||||||
|
|
||||||
virtual size_t
|
virtual size_t
|
||||||
DecodeInstructions (const Address &base_addr,
|
DecodeInstructions (const Address &base_addr,
|
||||||
const DataExtractor& data,
|
const DataExtractor& data,
|
||||||
lldb::offset_t data_offset,
|
lldb::offset_t data_offset,
|
||||||
size_t num_instructions,
|
size_t num_instructions,
|
||||||
bool append) = 0;
|
bool append,
|
||||||
|
bool data_from_file) = 0;
|
||||||
|
|
||||||
InstructionList &
|
InstructionList &
|
||||||
GetInstructionList ();
|
GetInstructionList ();
|
||||||
|
|
|
@ -2288,14 +2288,22 @@ SBTarget::ReadInstructions (lldb::SBAddress base_addr, uint32_t count, const cha
|
||||||
DataBufferHeap data (target_sp->GetArchitecture().GetMaximumOpcodeByteSize() * count, 0);
|
DataBufferHeap data (target_sp->GetArchitecture().GetMaximumOpcodeByteSize() * count, 0);
|
||||||
bool prefer_file_cache = false;
|
bool prefer_file_cache = false;
|
||||||
lldb_private::Error error;
|
lldb_private::Error error;
|
||||||
const size_t bytes_read = target_sp->ReadMemory(*addr_ptr, prefer_file_cache, data.GetBytes(), data.GetByteSize(), error);
|
lldb::addr_t load_addr = LLDB_INVALID_ADDRESS;
|
||||||
|
const size_t bytes_read = target_sp->ReadMemory(*addr_ptr,
|
||||||
|
prefer_file_cache,
|
||||||
|
data.GetBytes(),
|
||||||
|
data.GetByteSize(),
|
||||||
|
error,
|
||||||
|
&load_addr);
|
||||||
|
const bool data_from_file = load_addr == LLDB_INVALID_ADDRESS;
|
||||||
sb_instructions.SetDisassembler (Disassembler::DisassembleBytes (target_sp->GetArchitecture(),
|
sb_instructions.SetDisassembler (Disassembler::DisassembleBytes (target_sp->GetArchitecture(),
|
||||||
NULL,
|
NULL,
|
||||||
flavor_string,
|
flavor_string,
|
||||||
*addr_ptr,
|
*addr_ptr,
|
||||||
data.GetBytes(),
|
data.GetBytes(),
|
||||||
bytes_read,
|
bytes_read,
|
||||||
count));
|
count,
|
||||||
|
data_from_file));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2322,12 +2330,16 @@ SBTarget::GetInstructionsWithFlavor (lldb::SBAddress base_addr, const char *flav
|
||||||
if (base_addr.get())
|
if (base_addr.get())
|
||||||
addr = *base_addr.get();
|
addr = *base_addr.get();
|
||||||
|
|
||||||
|
const bool data_from_file = true;
|
||||||
|
|
||||||
sb_instructions.SetDisassembler (Disassembler::DisassembleBytes (target_sp->GetArchitecture(),
|
sb_instructions.SetDisassembler (Disassembler::DisassembleBytes (target_sp->GetArchitecture(),
|
||||||
NULL,
|
NULL,
|
||||||
flavor_string,
|
flavor_string,
|
||||||
addr,
|
addr,
|
||||||
buf,
|
buf,
|
||||||
size));
|
size,
|
||||||
|
UINT32_MAX,
|
||||||
|
data_from_file));
|
||||||
}
|
}
|
||||||
|
|
||||||
return sb_instructions;
|
return sb_instructions;
|
||||||
|
|
|
@ -1328,13 +1328,18 @@ DataExtractor::Dump (Stream *s,
|
||||||
{
|
{
|
||||||
lldb::addr_t addr = base_addr + start_offset;
|
lldb::addr_t addr = base_addr + start_offset;
|
||||||
lldb_private::Address so_addr;
|
lldb_private::Address so_addr;
|
||||||
if (!target_sp->GetSectionLoadList().ResolveLoadAddress(addr, so_addr))
|
bool data_from_file = true;
|
||||||
|
if (target_sp->GetSectionLoadList().ResolveLoadAddress(addr, so_addr))
|
||||||
|
{
|
||||||
|
data_from_file = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
if (target_sp->GetSectionLoadList().IsEmpty() || !target_sp->GetImages().ResolveFileAddress(addr, so_addr))
|
if (target_sp->GetSectionLoadList().IsEmpty() || !target_sp->GetImages().ResolveFileAddress(addr, so_addr))
|
||||||
so_addr.SetRawAddress(addr);
|
so_addr.SetRawAddress(addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t bytes_consumed = disassembler_sp->DecodeInstructions (so_addr, *this, start_offset, item_count, false);
|
size_t bytes_consumed = disassembler_sp->DecodeInstructions (so_addr, *this, start_offset, item_count, false, data_from_file);
|
||||||
|
|
||||||
if (bytes_consumed)
|
if (bytes_consumed)
|
||||||
{
|
{
|
||||||
|
|
|
@ -250,7 +250,8 @@ Disassembler::DisassembleRange
|
||||||
|
|
||||||
if (disasm_sp)
|
if (disasm_sp)
|
||||||
{
|
{
|
||||||
size_t bytes_disassembled = disasm_sp->ParseInstructions (&exe_ctx, range, NULL);
|
const bool prefer_file_cache = false;
|
||||||
|
size_t bytes_disassembled = disasm_sp->ParseInstructions (&exe_ctx, range, NULL, prefer_file_cache);
|
||||||
if (bytes_disassembled == 0)
|
if (bytes_disassembled == 0)
|
||||||
disasm_sp.reset();
|
disasm_sp.reset();
|
||||||
}
|
}
|
||||||
|
@ -259,32 +260,31 @@ Disassembler::DisassembleRange
|
||||||
}
|
}
|
||||||
|
|
||||||
lldb::DisassemblerSP
|
lldb::DisassemblerSP
|
||||||
Disassembler::DisassembleBytes
|
Disassembler::DisassembleBytes (const ArchSpec &arch,
|
||||||
(
|
|
||||||
const ArchSpec &arch,
|
|
||||||
const char *plugin_name,
|
const char *plugin_name,
|
||||||
const char *flavor,
|
const char *flavor,
|
||||||
const Address &start,
|
const Address &start,
|
||||||
const void *bytes,
|
const void *src,
|
||||||
size_t length,
|
size_t src_len,
|
||||||
uint32_t num_instructions
|
uint32_t num_instructions,
|
||||||
)
|
bool data_from_file)
|
||||||
{
|
{
|
||||||
lldb::DisassemblerSP disasm_sp;
|
lldb::DisassemblerSP disasm_sp;
|
||||||
|
|
||||||
if (bytes)
|
if (src)
|
||||||
{
|
{
|
||||||
disasm_sp = Disassembler::FindPlugin(arch, flavor, plugin_name);
|
disasm_sp = Disassembler::FindPlugin(arch, flavor, plugin_name);
|
||||||
|
|
||||||
if (disasm_sp)
|
if (disasm_sp)
|
||||||
{
|
{
|
||||||
DataExtractor data(bytes, length, arch.GetByteOrder(), arch.GetAddressByteSize());
|
DataExtractor data(src, src_len, arch.GetByteOrder(), arch.GetAddressByteSize());
|
||||||
|
|
||||||
(void)disasm_sp->DecodeInstructions (start,
|
(void)disasm_sp->DecodeInstructions (start,
|
||||||
data,
|
data,
|
||||||
0,
|
0,
|
||||||
num_instructions,
|
num_instructions,
|
||||||
false);
|
false,
|
||||||
|
data_from_file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -316,8 +316,8 @@ Disassembler::Disassemble
|
||||||
AddressRange range;
|
AddressRange range;
|
||||||
ResolveAddress (exe_ctx, disasm_range.GetBaseAddress(), range.GetBaseAddress());
|
ResolveAddress (exe_ctx, disasm_range.GetBaseAddress(), range.GetBaseAddress());
|
||||||
range.SetByteSize (disasm_range.GetByteSize());
|
range.SetByteSize (disasm_range.GetByteSize());
|
||||||
|
const bool prefer_file_cache = false;
|
||||||
size_t bytes_disassembled = disasm_sp->ParseInstructions (&exe_ctx, range, &strm);
|
size_t bytes_disassembled = disasm_sp->ParseInstructions (&exe_ctx, range, &strm, prefer_file_cache);
|
||||||
if (bytes_disassembled == 0)
|
if (bytes_disassembled == 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -351,13 +351,19 @@ Disassembler::Disassemble
|
||||||
{
|
{
|
||||||
if (num_instructions > 0)
|
if (num_instructions > 0)
|
||||||
{
|
{
|
||||||
lldb::DisassemblerSP disasm_sp (Disassembler::FindPluginForTarget(exe_ctx.GetTargetSP(), arch, flavor, plugin_name));
|
lldb::DisassemblerSP disasm_sp (Disassembler::FindPluginForTarget(exe_ctx.GetTargetSP(),
|
||||||
|
arch,
|
||||||
|
flavor,
|
||||||
|
plugin_name));
|
||||||
if (disasm_sp.get())
|
if (disasm_sp.get())
|
||||||
{
|
{
|
||||||
Address addr;
|
Address addr;
|
||||||
ResolveAddress (exe_ctx, start_address, addr);
|
ResolveAddress (exe_ctx, start_address, addr);
|
||||||
|
const bool prefer_file_cache = false;
|
||||||
size_t bytes_disassembled = disasm_sp->ParseInstructions (&exe_ctx, addr, num_instructions);
|
size_t bytes_disassembled = disasm_sp->ParseInstructions (&exe_ctx,
|
||||||
|
addr,
|
||||||
|
num_instructions,
|
||||||
|
prefer_file_cache);
|
||||||
if (bytes_disassembled == 0)
|
if (bytes_disassembled == 0)
|
||||||
return false;
|
return false;
|
||||||
return PrintInstructions (disasm_sp.get(),
|
return PrintInstructions (disasm_sp.get(),
|
||||||
|
@ -1045,12 +1051,10 @@ InstructionList::GetIndexOfInstructionAtLoadAddress (lldb::addr_t load_addr, Tar
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t
|
size_t
|
||||||
Disassembler::ParseInstructions
|
Disassembler::ParseInstructions (const ExecutionContext *exe_ctx,
|
||||||
(
|
|
||||||
const ExecutionContext *exe_ctx,
|
|
||||||
const AddressRange &range,
|
const AddressRange &range,
|
||||||
Stream *error_strm_ptr
|
Stream *error_strm_ptr,
|
||||||
)
|
bool prefer_file_cache)
|
||||||
{
|
{
|
||||||
if (exe_ctx)
|
if (exe_ctx)
|
||||||
{
|
{
|
||||||
|
@ -1063,12 +1067,13 @@ Disassembler::ParseInstructions
|
||||||
DataBufferSP data_sp(heap_buffer);
|
DataBufferSP data_sp(heap_buffer);
|
||||||
|
|
||||||
Error error;
|
Error error;
|
||||||
const bool prefer_file_cache = true;
|
lldb::addr_t load_addr = LLDB_INVALID_ADDRESS;
|
||||||
const size_t bytes_read = target->ReadMemory (range.GetBaseAddress(),
|
const size_t bytes_read = target->ReadMemory (range.GetBaseAddress(),
|
||||||
prefer_file_cache,
|
prefer_file_cache,
|
||||||
heap_buffer->GetBytes(),
|
heap_buffer->GetBytes(),
|
||||||
heap_buffer->GetByteSize(),
|
heap_buffer->GetByteSize(),
|
||||||
error);
|
error,
|
||||||
|
&load_addr);
|
||||||
|
|
||||||
if (bytes_read > 0)
|
if (bytes_read > 0)
|
||||||
{
|
{
|
||||||
|
@ -1077,7 +1082,8 @@ Disassembler::ParseInstructions
|
||||||
DataExtractor data (data_sp,
|
DataExtractor data (data_sp,
|
||||||
m_arch.GetByteOrder(),
|
m_arch.GetByteOrder(),
|
||||||
m_arch.GetAddressByteSize());
|
m_arch.GetAddressByteSize());
|
||||||
return DecodeInstructions (range.GetBaseAddress(), data, 0, UINT32_MAX, false);
|
const bool data_from_file = load_addr == LLDB_INVALID_ADDRESS;
|
||||||
|
return DecodeInstructions (range.GetBaseAddress(), data, 0, UINT32_MAX, false, data_from_file);
|
||||||
}
|
}
|
||||||
else if (error_strm_ptr)
|
else if (error_strm_ptr)
|
||||||
{
|
{
|
||||||
|
@ -1096,12 +1102,10 @@ Disassembler::ParseInstructions
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t
|
size_t
|
||||||
Disassembler::ParseInstructions
|
Disassembler::ParseInstructions (const ExecutionContext *exe_ctx,
|
||||||
(
|
|
||||||
const ExecutionContext *exe_ctx,
|
|
||||||
const Address &start,
|
const Address &start,
|
||||||
uint32_t num_instructions
|
uint32_t num_instructions,
|
||||||
)
|
bool prefer_file_cache)
|
||||||
{
|
{
|
||||||
m_instruction_list.Clear();
|
m_instruction_list.Clear();
|
||||||
|
|
||||||
|
@ -1119,12 +1123,15 @@ Disassembler::ParseInstructions
|
||||||
DataBufferSP data_sp (heap_buffer);
|
DataBufferSP data_sp (heap_buffer);
|
||||||
|
|
||||||
Error error;
|
Error error;
|
||||||
bool prefer_file_cache = true;
|
lldb::addr_t load_addr = LLDB_INVALID_ADDRESS;
|
||||||
const size_t bytes_read = target->ReadMemory (start,
|
const size_t bytes_read = target->ReadMemory (start,
|
||||||
prefer_file_cache,
|
prefer_file_cache,
|
||||||
heap_buffer->GetBytes(),
|
heap_buffer->GetBytes(),
|
||||||
byte_size,
|
byte_size,
|
||||||
error);
|
error,
|
||||||
|
&load_addr);
|
||||||
|
|
||||||
|
const bool data_from_file = load_addr == LLDB_INVALID_ADDRESS;
|
||||||
|
|
||||||
if (bytes_read == 0)
|
if (bytes_read == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1137,7 +1144,8 @@ Disassembler::ParseInstructions
|
||||||
data,
|
data,
|
||||||
0,
|
0,
|
||||||
num_instructions,
|
num_instructions,
|
||||||
append_instructions);
|
append_instructions,
|
||||||
|
data_from_file);
|
||||||
|
|
||||||
return m_instruction_list.GetSize();
|
return m_instruction_list.GetSize();
|
||||||
}
|
}
|
||||||
|
|
|
@ -234,7 +234,7 @@ IRExecutionUnit::DisassembleFunction (Stream &stream,
|
||||||
DataExtractor::TypeUInt8);
|
DataExtractor::TypeUInt8);
|
||||||
}
|
}
|
||||||
|
|
||||||
disassembler->DecodeInstructions (Address (func_remote_addr), extractor, 0, UINT32_MAX, false);
|
disassembler->DecodeInstructions (Address (func_remote_addr), extractor, 0, UINT32_MAX, false, false);
|
||||||
|
|
||||||
InstructionList &instruction_list = disassembler->GetInstructionList();
|
InstructionList &instruction_list = disassembler->GetInstructionList();
|
||||||
const uint32_t max_opcode_byte_size = instruction_list.GetMaxOpcocdeByteSize();
|
const uint32_t max_opcode_byte_size = instruction_list.GetMaxOpcocdeByteSize();
|
||||||
|
|
|
@ -48,10 +48,10 @@ public:
|
||||||
const lldb_private::Address &address,
|
const lldb_private::Address &address,
|
||||||
AddressClass addr_class) :
|
AddressClass addr_class) :
|
||||||
Instruction (address, addr_class),
|
Instruction (address, addr_class),
|
||||||
m_is_valid(false),
|
|
||||||
m_disasm(disasm),
|
|
||||||
m_disasm_sp (disasm.shared_from_this()),
|
m_disasm_sp (disasm.shared_from_this()),
|
||||||
m_does_branch(eLazyBoolCalculate)
|
m_does_branch (eLazyBoolCalculate),
|
||||||
|
m_is_valid (false),
|
||||||
|
m_using_file_addr (false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,24 +60,12 @@ public:
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
PadToWidth (lldb_private::StreamString &ss,
|
|
||||||
int new_width)
|
|
||||||
{
|
|
||||||
int old_width = ss.GetSize();
|
|
||||||
|
|
||||||
if (old_width < new_width)
|
|
||||||
{
|
|
||||||
ss.Printf("%*s", new_width - old_width, "");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual bool
|
virtual bool
|
||||||
DoesBranch ()
|
DoesBranch ()
|
||||||
{
|
{
|
||||||
if (m_does_branch == eLazyBoolCalculate)
|
if (m_does_branch == eLazyBoolCalculate)
|
||||||
{
|
{
|
||||||
m_disasm.Lock(this, NULL);
|
GetDisassemblerLLVMC().Lock(this, NULL);
|
||||||
DataExtractor data;
|
DataExtractor data;
|
||||||
if (m_opcode.GetData(data))
|
if (m_opcode.GetData(data))
|
||||||
{
|
{
|
||||||
|
@ -85,10 +73,10 @@ public:
|
||||||
lldb::addr_t pc = m_address.GetFileAddress();
|
lldb::addr_t pc = m_address.GetFileAddress();
|
||||||
|
|
||||||
DisassemblerLLVMC::LLVMCDisassembler *mc_disasm_ptr = GetDisasmToUse (is_alternate_isa);
|
DisassemblerLLVMC::LLVMCDisassembler *mc_disasm_ptr = GetDisasmToUse (is_alternate_isa);
|
||||||
uint8_t *opcode_data = const_cast<uint8_t *>(data.PeekData (0, 1));
|
const uint8_t *opcode_data = data.GetDataStart();
|
||||||
const size_t opcode_data_len = data.GetByteSize();
|
const size_t opcode_data_len = data.GetByteSize();
|
||||||
llvm::MCInst inst;
|
llvm::MCInst inst;
|
||||||
size_t inst_size = mc_disasm_ptr->GetMCInst(opcode_data,
|
const size_t inst_size = mc_disasm_ptr->GetMCInst (opcode_data,
|
||||||
opcode_data_len,
|
opcode_data_len,
|
||||||
pc,
|
pc,
|
||||||
inst);
|
inst);
|
||||||
|
@ -97,14 +85,14 @@ public:
|
||||||
m_does_branch = eLazyBoolYes;
|
m_does_branch = eLazyBoolYes;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
bool can_branch = mc_disasm_ptr->CanBranch(inst);
|
const bool can_branch = mc_disasm_ptr->CanBranch(inst);
|
||||||
if (can_branch)
|
if (can_branch)
|
||||||
m_does_branch = eLazyBoolYes;
|
m_does_branch = eLazyBoolYes;
|
||||||
else
|
else
|
||||||
m_does_branch = eLazyBoolNo;
|
m_does_branch = eLazyBoolNo;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_disasm.Unlock();
|
GetDisassemblerLLVMC().Unlock();
|
||||||
}
|
}
|
||||||
return m_does_branch == eLazyBoolYes;
|
return m_does_branch == eLazyBoolYes;
|
||||||
}
|
}
|
||||||
|
@ -112,20 +100,19 @@ public:
|
||||||
DisassemblerLLVMC::LLVMCDisassembler *
|
DisassemblerLLVMC::LLVMCDisassembler *
|
||||||
GetDisasmToUse (bool &is_alternate_isa)
|
GetDisasmToUse (bool &is_alternate_isa)
|
||||||
{
|
{
|
||||||
DisassemblerLLVMC::LLVMCDisassembler *mc_disasm_ptr = m_disasm.m_disasm_ap.get();
|
|
||||||
|
|
||||||
is_alternate_isa = false;
|
is_alternate_isa = false;
|
||||||
if (m_disasm.m_alternate_disasm_ap.get() != NULL)
|
DisassemblerLLVMC &llvm_disasm = GetDisassemblerLLVMC();
|
||||||
|
if (llvm_disasm.m_alternate_disasm_ap.get() != NULL)
|
||||||
{
|
{
|
||||||
const AddressClass address_class = GetAddressClass ();
|
const AddressClass address_class = GetAddressClass ();
|
||||||
|
|
||||||
if (address_class == eAddressClassCodeAlternateISA)
|
if (address_class == eAddressClassCodeAlternateISA)
|
||||||
{
|
{
|
||||||
mc_disasm_ptr = m_disasm.m_alternate_disasm_ap.get();
|
|
||||||
is_alternate_isa = true;
|
is_alternate_isa = true;
|
||||||
|
return llvm_disasm.m_alternate_disasm_ap.get();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return mc_disasm_ptr;
|
return llvm_disasm.m_disasm_ap.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual size_t
|
virtual size_t
|
||||||
|
@ -136,7 +123,8 @@ public:
|
||||||
// All we have to do is read the opcode which can be easy for some
|
// All we have to do is read the opcode which can be easy for some
|
||||||
// architetures
|
// architetures
|
||||||
bool got_op = false;
|
bool got_op = false;
|
||||||
const ArchSpec &arch = m_disasm.GetArchitecture();
|
DisassemblerLLVMC &llvm_disasm = GetDisassemblerLLVMC();
|
||||||
|
const ArchSpec &arch = llvm_disasm.GetArchitecture();
|
||||||
|
|
||||||
const uint32_t min_op_byte_size = arch.GetMinimumOpcodeByteSize();
|
const uint32_t min_op_byte_size = arch.GetMinimumOpcodeByteSize();
|
||||||
const uint32_t max_op_byte_size = arch.GetMaximumOpcodeByteSize();
|
const uint32_t max_op_byte_size = arch.GetMaximumOpcodeByteSize();
|
||||||
|
@ -179,17 +167,6 @@ public:
|
||||||
bool is_alternate_isa = false;
|
bool is_alternate_isa = false;
|
||||||
DisassemblerLLVMC::LLVMCDisassembler *mc_disasm_ptr = GetDisasmToUse (is_alternate_isa);
|
DisassemblerLLVMC::LLVMCDisassembler *mc_disasm_ptr = GetDisasmToUse (is_alternate_isa);
|
||||||
|
|
||||||
if (m_disasm.m_alternate_disasm_ap.get() != NULL)
|
|
||||||
{
|
|
||||||
const AddressClass address_class = GetAddressClass ();
|
|
||||||
|
|
||||||
if (address_class == eAddressClassCodeAlternateISA)
|
|
||||||
{
|
|
||||||
mc_disasm_ptr = m_disasm.m_alternate_disasm_ap.get();
|
|
||||||
is_alternate_isa = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const llvm::Triple::ArchType machine = arch.GetMachine();
|
const llvm::Triple::ArchType machine = arch.GetMachine();
|
||||||
if (machine == llvm::Triple::arm || machine == llvm::Triple::thumb)
|
if (machine == llvm::Triple::arm || machine == llvm::Triple::thumb)
|
||||||
{
|
{
|
||||||
|
@ -219,17 +196,17 @@ public:
|
||||||
{
|
{
|
||||||
// The opcode isn't evenly sized, so we need to actually use the llvm
|
// The opcode isn't evenly sized, so we need to actually use the llvm
|
||||||
// disassembler to parse it and get the size.
|
// disassembler to parse it and get the size.
|
||||||
m_disasm.Lock(this, NULL);
|
|
||||||
uint8_t *opcode_data = const_cast<uint8_t *>(data.PeekData (data_offset, 1));
|
uint8_t *opcode_data = const_cast<uint8_t *>(data.PeekData (data_offset, 1));
|
||||||
const size_t opcode_data_len = data.GetByteSize() - data_offset;
|
const size_t opcode_data_len = data.BytesLeft(data_offset);
|
||||||
const addr_t pc = m_address.GetFileAddress();
|
const addr_t pc = m_address.GetFileAddress();
|
||||||
llvm::MCInst inst;
|
llvm::MCInst inst;
|
||||||
|
|
||||||
|
llvm_disasm.Lock(this, NULL);
|
||||||
const size_t inst_size = mc_disasm_ptr->GetMCInst(opcode_data,
|
const size_t inst_size = mc_disasm_ptr->GetMCInst(opcode_data,
|
||||||
opcode_data_len,
|
opcode_data_len,
|
||||||
pc,
|
pc,
|
||||||
inst);
|
inst);
|
||||||
m_disasm.Unlock();
|
llvm_disasm.Unlock();
|
||||||
if (inst_size == 0)
|
if (inst_size == 0)
|
||||||
m_opcode.Clear();
|
m_opcode.Clear();
|
||||||
else
|
else
|
||||||
|
@ -264,28 +241,39 @@ public:
|
||||||
{
|
{
|
||||||
char out_string[512];
|
char out_string[512];
|
||||||
|
|
||||||
|
DisassemblerLLVMC &llvm_disasm = GetDisassemblerLLVMC();
|
||||||
|
|
||||||
DisassemblerLLVMC::LLVMCDisassembler *mc_disasm_ptr;
|
DisassemblerLLVMC::LLVMCDisassembler *mc_disasm_ptr;
|
||||||
|
|
||||||
if (address_class == eAddressClassCodeAlternateISA)
|
if (address_class == eAddressClassCodeAlternateISA)
|
||||||
mc_disasm_ptr = m_disasm.m_alternate_disasm_ap.get();
|
mc_disasm_ptr = llvm_disasm.m_alternate_disasm_ap.get();
|
||||||
else
|
else
|
||||||
mc_disasm_ptr = m_disasm.m_disasm_ap.get();
|
mc_disasm_ptr = llvm_disasm.m_disasm_ap.get();
|
||||||
|
|
||||||
lldb::addr_t pc = LLDB_INVALID_ADDRESS;
|
lldb::addr_t pc = m_address.GetFileAddress();
|
||||||
|
m_using_file_addr = true;
|
||||||
|
|
||||||
|
const bool data_from_file = GetDisassemblerLLVMC().m_data_from_file;
|
||||||
|
if (!data_from_file)
|
||||||
|
{
|
||||||
if (exe_ctx)
|
if (exe_ctx)
|
||||||
{
|
{
|
||||||
Target *target = exe_ctx->GetTargetPtr();
|
Target *target = exe_ctx->GetTargetPtr();
|
||||||
if (target)
|
if (target)
|
||||||
pc = m_address.GetLoadAddress(target);
|
{
|
||||||
|
const lldb::addr_t load_addr = m_address.GetLoadAddress(target);
|
||||||
|
if (load_addr != LLDB_INVALID_ADDRESS)
|
||||||
|
{
|
||||||
|
pc = load_addr;
|
||||||
|
m_using_file_addr = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pc == LLDB_INVALID_ADDRESS)
|
llvm_disasm.Lock(this, exe_ctx);
|
||||||
pc = m_address.GetFileAddress();
|
|
||||||
|
|
||||||
m_disasm.Lock(this, exe_ctx);
|
const uint8_t *opcode_data = data.GetDataStart();
|
||||||
|
|
||||||
uint8_t *opcode_data = const_cast<uint8_t *>(data.PeekData (0, 1));
|
|
||||||
const size_t opcode_data_len = data.GetByteSize();
|
const size_t opcode_data_len = data.GetByteSize();
|
||||||
llvm::MCInst inst;
|
llvm::MCInst inst;
|
||||||
size_t inst_size = mc_disasm_ptr->GetMCInst (opcode_data,
|
size_t inst_size = mc_disasm_ptr->GetMCInst (opcode_data,
|
||||||
|
@ -296,7 +284,7 @@ public:
|
||||||
if (inst_size > 0)
|
if (inst_size > 0)
|
||||||
mc_disasm_ptr->PrintMCInst(inst, out_string, sizeof(out_string));
|
mc_disasm_ptr->PrintMCInst(inst, out_string, sizeof(out_string));
|
||||||
|
|
||||||
m_disasm.Unlock();
|
llvm_disasm.Unlock();
|
||||||
|
|
||||||
if (inst_size == 0)
|
if (inst_size == 0)
|
||||||
{
|
{
|
||||||
|
@ -361,7 +349,7 @@ public:
|
||||||
{
|
{
|
||||||
if (m_does_branch == eLazyBoolCalculate)
|
if (m_does_branch == eLazyBoolCalculate)
|
||||||
{
|
{
|
||||||
bool can_branch = mc_disasm_ptr->CanBranch(inst);
|
const bool can_branch = mc_disasm_ptr->CanBranch(inst);
|
||||||
if (can_branch)
|
if (can_branch)
|
||||||
m_does_branch = eLazyBoolYes;
|
m_does_branch = eLazyBoolYes;
|
||||||
else
|
else
|
||||||
|
@ -389,22 +377,33 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
IsValid ()
|
IsValid () const
|
||||||
{
|
{
|
||||||
return m_is_valid;
|
return m_is_valid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
UsingFileAddress() const
|
||||||
|
{
|
||||||
|
return m_using_file_addr;
|
||||||
|
}
|
||||||
size_t
|
size_t
|
||||||
GetByteSize ()
|
GetByteSize () const
|
||||||
{
|
{
|
||||||
return m_opcode.GetByteSize();
|
return m_opcode.GetByteSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DisassemblerLLVMC &
|
||||||
|
GetDisassemblerLLVMC ()
|
||||||
|
{
|
||||||
|
return *(DisassemblerLLVMC *)m_disasm_sp.get();
|
||||||
|
}
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
bool m_is_valid;
|
|
||||||
DisassemblerLLVMC &m_disasm;
|
|
||||||
DisassemblerSP m_disasm_sp; // for ownership
|
DisassemblerSP m_disasm_sp; // for ownership
|
||||||
LazyBool m_does_branch;
|
LazyBool m_does_branch;
|
||||||
|
bool m_is_valid;
|
||||||
|
bool m_using_file_addr;
|
||||||
|
|
||||||
static bool s_regex_compiled;
|
static bool s_regex_compiled;
|
||||||
static ::regex_t s_regex;
|
static ::regex_t s_regex;
|
||||||
|
@ -476,11 +475,11 @@ DisassemblerLLVMC::LLVMCDisassembler::LLVMCDisassembler (const char *triple, uns
|
||||||
namespace {
|
namespace {
|
||||||
// This is the memory object we use in GetInstruction.
|
// This is the memory object we use in GetInstruction.
|
||||||
class LLDBDisasmMemoryObject : public llvm::MemoryObject {
|
class LLDBDisasmMemoryObject : public llvm::MemoryObject {
|
||||||
uint8_t *m_bytes;
|
const uint8_t *m_bytes;
|
||||||
uint64_t m_size;
|
uint64_t m_size;
|
||||||
uint64_t m_base_PC;
|
uint64_t m_base_PC;
|
||||||
public:
|
public:
|
||||||
LLDBDisasmMemoryObject(uint8_t *bytes, uint64_t size, uint64_t basePC) :
|
LLDBDisasmMemoryObject(const uint8_t *bytes, uint64_t size, uint64_t basePC) :
|
||||||
m_bytes(bytes), m_size(size), m_base_PC(basePC) {}
|
m_bytes(bytes), m_size(size), m_base_PC(basePC) {}
|
||||||
|
|
||||||
uint64_t getBase() const { return m_base_PC; }
|
uint64_t getBase() const { return m_base_PC; }
|
||||||
|
@ -496,14 +495,12 @@ namespace {
|
||||||
} // End Anonymous Namespace
|
} // End Anonymous Namespace
|
||||||
|
|
||||||
uint64_t
|
uint64_t
|
||||||
DisassemblerLLVMC::LLVMCDisassembler::GetMCInst (
|
DisassemblerLLVMC::LLVMCDisassembler::GetMCInst (const uint8_t *opcode_data,
|
||||||
uint8_t *opcode_data,
|
|
||||||
size_t opcode_data_len,
|
size_t opcode_data_len,
|
||||||
lldb::addr_t pc,
|
lldb::addr_t pc,
|
||||||
llvm::MCInst &mc_inst)
|
llvm::MCInst &mc_inst)
|
||||||
{
|
{
|
||||||
LLDBDisasmMemoryObject memory_object (opcode_data, opcode_data_len, pc);
|
LLDBDisasmMemoryObject memory_object (opcode_data, opcode_data_len, pc);
|
||||||
llvm::MCInst inst;
|
|
||||||
llvm::MCDisassembler::DecodeStatus status;
|
llvm::MCDisassembler::DecodeStatus status;
|
||||||
|
|
||||||
uint64_t new_inst_size;
|
uint64_t new_inst_size;
|
||||||
|
@ -520,17 +517,18 @@ DisassemblerLLVMC::LLVMCDisassembler::GetMCInst (
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t
|
uint64_t
|
||||||
DisassemblerLLVMC::LLVMCDisassembler::PrintMCInst (llvm::MCInst &mc_inst, char *output_buffer, size_t out_buffer_len)
|
DisassemblerLLVMC::LLVMCDisassembler::PrintMCInst (llvm::MCInst &mc_inst,
|
||||||
|
char *dst,
|
||||||
|
size_t dst_len)
|
||||||
{
|
{
|
||||||
llvm::StringRef unused_annotations;
|
llvm::StringRef unused_annotations;
|
||||||
llvm::SmallString<64> inst_string;
|
llvm::SmallString<64> inst_string;
|
||||||
llvm::raw_svector_ostream inst_stream(inst_string);
|
llvm::raw_svector_ostream inst_stream(inst_string);
|
||||||
m_instr_printer_ap->printInst (&mc_inst, inst_stream, unused_annotations);
|
m_instr_printer_ap->printInst (&mc_inst, inst_stream, unused_annotations);
|
||||||
inst_stream.flush();
|
inst_stream.flush();
|
||||||
|
const size_t output_size = std::min(dst_len - 1, inst_string.size());
|
||||||
size_t output_size = std::min(out_buffer_len -1, inst_string.size());
|
std::memcpy(dst, inst_string.data(), output_size);
|
||||||
std::memcpy(output_buffer, inst_string.data(), output_size);
|
dst[output_size] = '\0';
|
||||||
output_buffer[output_size] = '\0';
|
|
||||||
|
|
||||||
return output_size;
|
return output_size;
|
||||||
}
|
}
|
||||||
|
@ -576,7 +574,8 @@ DisassemblerLLVMC::CreateInstance (const ArchSpec &arch, const char *flavor)
|
||||||
DisassemblerLLVMC::DisassemblerLLVMC (const ArchSpec &arch, const char *flavor_string) :
|
DisassemblerLLVMC::DisassemblerLLVMC (const ArchSpec &arch, const char *flavor_string) :
|
||||||
Disassembler(arch, flavor_string),
|
Disassembler(arch, flavor_string),
|
||||||
m_exe_ctx (NULL),
|
m_exe_ctx (NULL),
|
||||||
m_inst (NULL)
|
m_inst (NULL),
|
||||||
|
m_data_from_file (false)
|
||||||
{
|
{
|
||||||
if (!FlavorValidForArchSpec (arch, m_flavor.c_str()))
|
if (!FlavorValidForArchSpec (arch, m_flavor.c_str()))
|
||||||
{
|
{
|
||||||
|
@ -633,7 +632,8 @@ DisassemblerLLVMC::DecodeInstructions (const Address &base_addr,
|
||||||
const DataExtractor& data,
|
const DataExtractor& data,
|
||||||
lldb::offset_t data_offset,
|
lldb::offset_t data_offset,
|
||||||
size_t num_instructions,
|
size_t num_instructions,
|
||||||
bool append)
|
bool append,
|
||||||
|
bool data_from_file)
|
||||||
{
|
{
|
||||||
if (!append)
|
if (!append)
|
||||||
m_instruction_list.Clear();
|
m_instruction_list.Clear();
|
||||||
|
@ -641,6 +641,7 @@ DisassemblerLLVMC::DecodeInstructions (const Address &base_addr,
|
||||||
if (!IsValid())
|
if (!IsValid())
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
m_data_from_file = data_from_file;
|
||||||
uint32_t data_cursor = data_offset;
|
uint32_t data_cursor = data_offset;
|
||||||
const size_t data_byte_size = data.GetByteSize();
|
const size_t data_byte_size = data.GetByteSize();
|
||||||
uint32_t instructions_parsed = 0;
|
uint32_t instructions_parsed = 0;
|
||||||
|
@ -760,36 +761,33 @@ const char *DisassemblerLLVMC::SymbolLookup (uint64_t value,
|
||||||
if (m_exe_ctx && m_inst)
|
if (m_exe_ctx && m_inst)
|
||||||
{
|
{
|
||||||
//std::string remove_this_prior_to_checkin;
|
//std::string remove_this_prior_to_checkin;
|
||||||
Address reference_address;
|
|
||||||
|
|
||||||
Target *target = m_exe_ctx ? m_exe_ctx->GetTargetPtr() : NULL;
|
Target *target = m_exe_ctx ? m_exe_ctx->GetTargetPtr() : NULL;
|
||||||
|
Address value_so_addr;
|
||||||
if (target && !target->GetSectionLoadList().IsEmpty())
|
if (m_inst->UsingFileAddress())
|
||||||
target->GetSectionLoadList().ResolveLoadAddress(value, reference_address);
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
ModuleSP module_sp(m_inst->GetAddress().GetModule());
|
ModuleSP module_sp(m_inst->GetAddress().GetModule());
|
||||||
if (module_sp)
|
if (module_sp)
|
||||||
module_sp->ResolveFileAddress(value, reference_address);
|
module_sp->ResolveFileAddress(value, value_so_addr);
|
||||||
|
}
|
||||||
|
else if (target && !target->GetSectionLoadList().IsEmpty())
|
||||||
|
{
|
||||||
|
target->GetSectionLoadList().ResolveLoadAddress(value, value_so_addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (reference_address.IsValid() && reference_address.GetSection())
|
if (value_so_addr.IsValid() && value_so_addr.GetSection())
|
||||||
{
|
{
|
||||||
StreamString ss;
|
StreamString ss;
|
||||||
|
|
||||||
reference_address.Dump (&ss,
|
value_so_addr.Dump (&ss,
|
||||||
target,
|
target,
|
||||||
Address::DumpStyleResolvedDescriptionNoModule,
|
Address::DumpStyleResolvedDescriptionNoModule,
|
||||||
Address::DumpStyleSectionNameOffset);
|
Address::DumpStyleSectionNameOffset);
|
||||||
|
|
||||||
if (!ss.GetString().empty())
|
if (!ss.GetString().empty())
|
||||||
{
|
{
|
||||||
//remove_this_prior_to_checkin = ss.GetString();
|
|
||||||
//if (*type_ptr)
|
|
||||||
m_inst->AppendComment(ss.GetString());
|
m_inst->AppendComment(ss.GetString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//printf ("DisassemblerLLVMC::SymbolLookup (value=0x%16.16" PRIx64 ", type=%" PRIu64 ", pc=0x%16.16" PRIx64 ", name=\"%s\") m_exe_ctx=%p, m_inst=%p\n", value, *type_ptr, pc, remove_this_prior_to_checkin.c_str(), m_exe_ctx, m_inst);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -45,7 +45,7 @@ class DisassemblerLLVMC : public lldb_private::Disassembler
|
||||||
|
|
||||||
~LLVMCDisassembler() {};
|
~LLVMCDisassembler() {};
|
||||||
|
|
||||||
uint64_t GetMCInst (uint8_t *opcode_data, size_t opcode_data_len, lldb::addr_t pc, llvm::MCInst &mc_inst);
|
uint64_t GetMCInst (const uint8_t *opcode_data, size_t opcode_data_len, lldb::addr_t pc, llvm::MCInst &mc_inst);
|
||||||
uint64_t PrintMCInst (llvm::MCInst &mc_inst, char *output_buffer, size_t out_buffer_len);
|
uint64_t PrintMCInst (llvm::MCInst &mc_inst, char *output_buffer, size_t out_buffer_len);
|
||||||
bool CanBranch (llvm::MCInst &mc_inst);
|
bool CanBranch (llvm::MCInst &mc_inst);
|
||||||
bool IsValid()
|
bool IsValid()
|
||||||
|
@ -88,12 +88,13 @@ public:
|
||||||
virtual
|
virtual
|
||||||
~DisassemblerLLVMC();
|
~DisassemblerLLVMC();
|
||||||
|
|
||||||
size_t
|
virtual size_t
|
||||||
DecodeInstructions (const lldb_private::Address &base_addr,
|
DecodeInstructions (const lldb_private::Address &base_addr,
|
||||||
const lldb_private::DataExtractor& data,
|
const lldb_private::DataExtractor& data,
|
||||||
lldb::offset_t data_offset,
|
lldb::offset_t data_offset,
|
||||||
size_t num_instructions,
|
size_t num_instructions,
|
||||||
bool append);
|
bool append,
|
||||||
|
bool data_from_file);
|
||||||
|
|
||||||
//------------------------------------------------------------------
|
//------------------------------------------------------------------
|
||||||
// PluginInterface protocol
|
// PluginInterface protocol
|
||||||
|
@ -161,6 +162,7 @@ protected:
|
||||||
const lldb_private::ExecutionContext *m_exe_ctx;
|
const lldb_private::ExecutionContext *m_exe_ctx;
|
||||||
InstructionLLVMC *m_inst;
|
InstructionLLVMC *m_inst;
|
||||||
lldb_private::Mutex m_mutex;
|
lldb_private::Mutex m_mutex;
|
||||||
|
bool m_data_from_file;
|
||||||
|
|
||||||
std::auto_ptr<LLVMCDisassembler> m_disasm_ap;
|
std::auto_ptr<LLVMCDisassembler> m_disasm_ap;
|
||||||
std::auto_ptr<LLVMCDisassembler> m_alternate_disasm_ap;
|
std::auto_ptr<LLVMCDisassembler> m_alternate_disasm_ap;
|
||||||
|
|
|
@ -208,10 +208,11 @@ ThreadPlanAssemblyTracer::Log ()
|
||||||
process_sp->GetByteOrder(),
|
process_sp->GetByteOrder(),
|
||||||
process_sp->GetAddressByteSize());
|
process_sp->GetAddressByteSize());
|
||||||
|
|
||||||
|
bool data_from_file = false;
|
||||||
if (addr_valid)
|
if (addr_valid)
|
||||||
disassembler->DecodeInstructions (pc_addr, extractor, 0, 1, false);
|
disassembler->DecodeInstructions (pc_addr, extractor, 0, 1, false, data_from_file);
|
||||||
else
|
else
|
||||||
disassembler->DecodeInstructions (Address (pc), extractor, 0, 1, false);
|
disassembler->DecodeInstructions (Address (pc), extractor, 0, 1, false, data_from_file);
|
||||||
|
|
||||||
InstructionList &instruction_list = disassembler->GetInstructionList();
|
InstructionList &instruction_list = disassembler->GetInstructionList();
|
||||||
const uint32_t max_opcode_byte_size = instruction_list.GetMaxOpcocdeByteSize();
|
const uint32_t max_opcode_byte_size = instruction_list.GetMaxOpcocdeByteSize();
|
||||||
|
|
Loading…
Reference in New Issue