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

Reply via email to