Hello all,
This week I have been seeing lldb-server reporting an Illegal
Instruction signal when a shared library is loaded while debugging an
(ARM) android executable.
I have traced this back to the DYLD Rendezvous breakpoint being inserted
as an ARM breakpoint when it should be THUMB.
I have attached a very rough patch that will fix this problem, but I
wanted to check with the list to try and find a robust solution that
will work in all cases.
Here are the key parts of the problem:
- The rendezvous breakpoint address is not a public symbol so is marked
as eAddressClassUnknown.
- When the rendezvous breakpoint address is read from the DT_DEBUG
structure it has bit 0 set which marks it as THUMB.
- Once the address is found it calls into Process::CreateBreakpointSite
(), which in turn calls Target::GetOpcodeLoadAddress ().
- GetOpcodeLoadAddress() checks if the machine type is ARM and will mask
out bit 0, at which point all information that it is a THUMB address has
been lost.
- Down the line PlatformLinux::GetSoftwareBreakpointTrapOpcode() will
see that bit 0 is not set and so will insert a ARM trap opcode.
My temporary solution was to not strip bit 0 from an address marked as
eAddressClassUnknown in GetOpcodeLoadAddress() and also make the check in
GetSoftwareBreakpointTrapOpcode() more relaxed.
I feel this may have repercussions in other scenarios I'm not considering.
Does anyone have any thoughts or advice for a good solution to this problem?
Thanks,
Aidan
diff --git a/source/Plugins/Platform/Linux/PlatformLinux.cpp b/source/Plugins/Platform/Linux/PlatformLinux.cpp
index e656f7a..536736a 100644
--- a/source/Plugins/Platform/Linux/PlatformLinux.cpp
+++ b/source/Plugins/Platform/Linux/PlatformLinux.cpp
@@ -588,34 +588,33 @@ PlatformLinux::GetSoftwareBreakpointTrapOpcode (Target &target,
trap_opcode_size = sizeof(g_hex_opcode);
}
break;
case llvm::Triple::arm:
{
// The ARM reference recommends the use of 0xe7fddefe and 0xdefe
// but the linux kernel does otherwise.
static const uint8_t g_arm_breakpoint_opcode[] = { 0xf0, 0x01, 0xf0, 0xe7 };
static const uint8_t g_thumb_breakpoint_opcode[] = { 0x01, 0xde };
lldb::BreakpointLocationSP bp_loc_sp (bp_site->GetOwnerAtIndex (0));
AddressClass addr_class = eAddressClassUnknown;
if (bp_loc_sp)
addr_class = bp_loc_sp->GetAddress ().GetAddressClass ();
- if (addr_class == eAddressClassCodeAlternateISA
- || (addr_class == eAddressClassUnknown && (bp_site->GetLoadAddress() & 1)))
+ if (addr_class == eAddressClassCodeAlternateISA || bp_site->GetLoadAddress() & 1)
{
trap_opcode = g_thumb_breakpoint_opcode;
trap_opcode_size = sizeof(g_thumb_breakpoint_opcode);
}
else
{
trap_opcode = g_arm_breakpoint_opcode;
trap_opcode_size = sizeof(g_arm_breakpoint_opcode);
}
}
break;
case llvm::Triple::mips:
case llvm::Triple::mips64:
{
static const uint8_t g_hex_opcode[] = { 0x00, 0x00, 0x00, 0x0d };
trap_opcode = g_hex_opcode;
diff --git a/source/Target/Target.cpp b/source/Target/Target.cpp
index 13b5c6e..303747f 100644
--- a/source/Target/Target.cpp
+++ b/source/Target/Target.cpp
@@ -2094,32 +2094,34 @@ Target::GetCallableLoadAddress (lldb::addr_t load_addr, AddressClass addr_class)
lldb::addr_t
Target::GetOpcodeLoadAddress (lldb::addr_t load_addr, AddressClass addr_class) const
{
addr_t opcode_addr = load_addr;
switch (m_arch.GetMachine())
{
case llvm::Triple::arm:
case llvm::Triple::thumb:
switch (addr_class)
{
case eAddressClassData:
case eAddressClassDebug:
return LLDB_INVALID_ADDRESS;
case eAddressClassInvalid:
case eAddressClassUnknown:
+ break;
+
case eAddressClassCode:
case eAddressClassCodeAlternateISA:
case eAddressClassRuntime:
opcode_addr &= ~(1ull);
break;
}
break;
default:
break;
}
return opcode_addr;
}
SourceManager &
Target::GetSourceManager ()
_______________________________________________
lldb-dev mailing list
lldb-dev@cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/lldb-dev