radareorg / radare2

UNIX-like reverse engineering framework and command-line toolset
https://www.radare.org/
GNU Lesser General Public License v3.0
20.39k stars 2.98k forks source link

ARM Remote GDB not working #10578

Closed SpenserStyles closed 6 years ago

SpenserStyles commented 6 years ago

Work environment

Questions Answers
OS/arch/bits (mandatory) macOS 10.13.5 64-bit
File format of the file you reverse (mandatory) BIN
Architecture/bits of the file (mandatory) ARM Cortex 16-bits
r2 -v full output, not truncated (mandatory) radare2 2.6.9 18640 @ darwin-x86-64 git.2.6.9 commit: 159d16b34550f4a83ee496839981c8316339ac4d build: 2018-07-02__11:32:1

Expected behavior

Succesful connection to GDB server enabling single-stepping and register printing

Actual behavior

Appears to connect to GDB server and can dump memory but unable to "dr" registers and a single-step causes Visual mode to display address 0x00

Steps to reproduce the behavior

Try remotely connecting to a STM32 device through JLink GDB Server.

Additional Logs, screenshots, source-code, configuration dump, ...

Notice that dr does not print any debug registers. dc did let the device continue and break but the address offset is always reset to 0 in the disassembly. image

This proves the connection is made although it appears to not like one of the packets. It always shows that the PC is halted after i control-c the dc command. image

XVilka commented 6 years ago

Can you record a session and upload here PCAP file? It is hard to reproduce without hardware.

On Tue, Jul 3, 2018, 12:46 AM SpenserStyles notifications@github.com wrote:

Work environment Questions Answers OS/arch/bits (mandatory) macOS 10.13.5 64-bit File format of the file you reverse (mandatory) BIN Architecture/bits of the file (mandatory) ARM Cortex 16-bits r2 -v full output, not truncated (mandatory) radare2 2.6.9 18640 @ darwin-x86-64 git.2.6.9 commit: 159d16b https://github.com/radare/radare2/commit/159d16b34550f4a83ee496839981c8316339ac4d build: 2018-07-02__11:32:1 Expected behavior

Succesful connection to GDB server enabling single-stepping and register printing Actual behavior

Appears to connect to GDB server and can dump memory but unable to "dr" registers and a single-step causes Visual mode to display address 0x00 Steps to reproduce the behavior

Try remotely connecting to a STM32 device through JLink GDB Server. Additional Logs, screenshots, source-code, configuration dump, ...

Notice that dr does not print any debug registers. dc did let the device continue and break but the address offset is always reset to 0 in the disassembly. [image: image] https://user-images.githubusercontent.com/31034116/42175999-7bb5321c-7df5-11e8-8619-6ce96a20f9bc.png

This proves the connection is made although it appears to not like one of the packets. It always shows that the PC is halted after i control-c the dc command. [image: image] https://user-images.githubusercontent.com/31034116/42176037-9ea09866-7df5-11e8-9495-bf9564dcd058.png

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/radare/radare2/issues/10578, or mute the thread https://github.com/notifications/unsubscribe-auth/AAMZ_Vrj45hx07g2jQn-JSF03vnXncwnks5uCk5kgaJpZM4U_oIl .

SpenserStyles commented 6 years ago

Here is a couple of pcaps. Let me know if you need me to grab anything else.

gdb_pcaps.zip

SpenserStyles commented 6 years ago

I figured out what the root cause of the issue. The gdbr_parse_target_xml() prepends the register name for PC, SP, and A0-A3. These register names are hardcoded and do not take into account the register name returned by the GDB Server. So the PC name was hardcoded to r15 but the name returned by the GDB Server is "pc".

Here is the target XML returned by the GDB Server:

$m<?xml version="1.0"?>
<!-- Copyright (C) 2008 Free Software Foundation, Inc.

     Copying and distribution of this file, with or without modification,
     are permitted in any medium without royalty provided the copyright
     notice and this notice are preserved.  -->

<!DOCTYPE feature SYSTEM "gdb-target.dtd">
<target version="1.0">
  <architecture>arm</architecture>
  <feature name="org.gnu.gdb.arm.m-profile">
    <reg name="r0" bitsize="32" regnum="0" type="uint32" group="general"/>
    <reg name="r1" bitsize="32" regnum="1" type="uint32" group="general"/>
    <reg name="r2" bitsize="32" regnum="2" type="uint32" group="general"/>
    <reg name="r3" bitsize="32" regnum="3" type="uint32" group="general"/>
    <reg name="r4" bitsize="32" regnum="4" type="uint32" group="general"/>
    <reg name="r5" bitsize="32" regnum="5" type="uint32" group="general"/>
    <reg name="r6" bitsize="32" regnum="6" type="uint32" group="general"/>
    <reg name="r7" bitsize="32" regnum="7" type="uint32" group="general"/>
    <reg name="r8" bitsize="32" regnum="8" type="uint32" group="general"/>
    <reg name="r9" bitsize="32" regnum="9" type="uint32" group="general"/>
    <reg name="r10" bitsize="32" regnum="10" type="uint32" group="general"/>
    <reg name="r11" bitsize="32" regnum="11" type="uint32" group="general"/>
    <reg name="r12" bitsize="32" regnum="12" type="uint32" group="general"/>
    <reg name="sp" bitsize="32" regnum="13" type="data_ptr" group="general"/>
    <reg name="lr" bitsize="32" regnum="14" type="uint32" group="general"/>
    <reg name="pc" bitsize="32" regnum="15" type="code_ptr" group="general"/>
    <reg name="xpsr" bitsize="32" regnum="25" type="uint32" group="general"/>
  </feature>
  <feature name="org.gnu.gdb.arm.m-system">
    <reg name="msp" bitsize="32" regnum="26" type="uint32" group="general"/>
    <reg name="psp" bitsize="32" regnum="27" type="uint32" group="general"/>
    <reg name="primask" bitsize="32" regnum="28" type="uint32" group="general"/>
    <reg name="basepri" bit#88

Below is the gdbr_parse_target_xml() function that has PC and SP hardcoded to r15,r15

case R_SYS_ARCH_ARM:
        switch (g->target.bits) {
        case 32:
            if (!(profile = r_str_prefix (profile,
                            "=PC    r15\n" 
                            "=SP    r14\n" // XXX
                            "=A0    r0\n"
                            "=A1    r1\n"
                            "=A2    r2\n"
                            "=A3    r3\n"
                              ))) {
                goto exit_err;
            }
            break;

When I change this to the below then everything works (at least what I have tested so far)

case R_SYS_ARCH_ARM:
        switch (g->target.bits) {
        case 32:
            if (!(profile = r_str_prefix (profile,
                            "=PC    pc\n" // CHANGED TO MATCH TARGET XML REG NAME
                            "=SP    sp\n" // CHANGED TO MATCH TARGET XML REG NAME
                            "=A0    r0\n"
                            "=A1    r1\n"
                            "=A2    r2\n"
                            "=A3    r3\n"
                              ))) {
                goto exit_err;
            }
            break;

I think the "real" fix should use the reg name returned by the target XML instead of hardcoding the value.

radare commented 6 years ago

Dont use -D gdb gdb://

Just use -d gdb://

On 3 Jul 2018, at 02:52, Anton Kochkov notifications@github.com wrote:

Can you record a session and upload here PCAP file? It is hard to reproduce without hardware.

On Tue, Jul 3, 2018, 12:46 AM SpenserStyles notifications@github.com wrote:

Work environment Questions Answers OS/arch/bits (mandatory) macOS 10.13.5 64-bit File format of the file you reverse (mandatory) BIN Architecture/bits of the file (mandatory) ARM Cortex 16-bits r2 -v full output, not truncated (mandatory) radare2 2.6.9 18640 @ darwin-x86-64 git.2.6.9 commit: 159d16b https://github.com/radare/radare2/commit/159d16b34550f4a83ee496839981c8316339ac4d build: 2018-07-02__11:32:1 Expected behavior

Succesful connection to GDB server enabling single-stepping and register printing Actual behavior

Appears to connect to GDB server and can dump memory but unable to "dr" registers and a single-step causes Visual mode to display address 0x00 Steps to reproduce the behavior

Try remotely connecting to a STM32 device through JLink GDB Server. Additional Logs, screenshots, source-code, configuration dump, ...

Notice that dr does not print any debug registers. dc did let the device continue and break but the address offset is always reset to 0 in the disassembly. [image: image] https://user-images.githubusercontent.com/31034116/42175999-7bb5321c-7df5-11e8-8619-6ce96a20f9bc.png

This proves the connection is made although it appears to not like one of the packets. It always shows that the PC is halted after i control-c the dc command. [image: image] https://user-images.githubusercontent.com/31034116/42176037-9ea09866-7df5-11e8-9495-bf9564dcd058.png

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/radare/radare2/issues/10578, or mute the thread https://github.com/notifications/unsubscribe-auth/AAMZ_Vrj45hx07g2jQn-JSF03vnXncwnks5uCk5kgaJpZM4U_oIl .

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub, or mute the thread.

radare commented 6 years ago

Can you send a pullreq fixing this issue? Thanks!

On 3 Jul 2018, at 16:03, SpenserStyles notifications@github.com wrote:

I figured out what the root cause of the issue. The gdbr_parse_target_xml() prepends the register name for PC, SP, and A0-A3. These register names are hardcoded and do not take into account the register name returned by the GDB Server. So the PC name was hardcoded to r15 but the name returned by the GDB Server is "pc".

Here is the target XML returned by the GDB Server:

$m<?xml version="1.0"?>

<!DOCTYPE feature SYSTEM "gdb-target.dtd">

arm target.bits) { case 32: if (!(profile = r_str_prefix (profile, "=PC r15\n" "=SP r14\n" // XXX "=A0 r0\n" "=A1 r1\n" "=A2 r2\n" "=A3 r3\n" ))) { goto exit_err; } break; When I change this to the below then everything works (at least what I have tested so far) case R_SYS_ARCH_ARM: switch (g->target.bits) { case 32: if (!(profile = r_str_prefix (profile, "=PC pc\n" // CHANGED TO MATCH TARGET XML REG NAME "=SP sp\n" // CHANGED TO MATCH TARGET XML REG NAME "=A0 r0\n" "=A1 r1\n" "=A2 r2\n" "=A3 r3\n" ))) { goto exit_err; } break; I think the "real" fix should use the reg name returned by the target XML instead of hardcoding the value. — You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub, or mute the thread.
d4em0n commented 6 years ago

This is issue should be closed after #10818