2

I'm reverse engineering some firmware from a device running an ARM Cortex M0 (specifically, Nordic nrf51802). For reference, the pertinent part of the memory map looks like this:

memory map snippet

I'm trying to add proper data types and names to global variables, but I don't quite understand what is going on.

Consider this simple bit of C code:

static volatile u32_t wait_for_ack_timeout_us;

static void update_radio_bitrate(void)
{
    NRF_RADIO->MODE = esb_cfg.bitrate << RADIO_MODE_MODE_Pos;

    switch (esb_cfg.bitrate) {
    case NRF_ESB_BITRATE_2MBPS:
        wait_for_ack_timeout_us = RX_ACK_TIMEOUT_US_2MBPS;
        break;

    case NRF_ESB_BITRATE_1MBPS:
        wait_for_ack_timeout_us = RX_ACK_TIMEOUT_US_1MBPS;
        break;

    case NRF_ESB_BITRATE_250KBPS:
        wait_for_ack_timeout_us = RX_ACK_TIMEOUT_US_250KBPS;
        break;

    case NRF_ESB_BITRATE_1MBPS_BLE:
        wait_for_ack_timeout_us = RX_ACK_TIMEOUT_US_1MBPS_BLE;
        break;

    default:
        /* Should not be reached */
    }
}

Ghidra decompiles this as:

enter image description here

Double-clicking PTR_DAT_00003d24 reveals:

enter image description here

Double-clicking DAT_2000003c here reveals where wait_for_ack_timeout_us actually lives in memory:

enter image description here

I changed the data type to uint32_t and added the variable name, but the decompiled code still shows the weird pointer dereference.

enter image description here

My questions are:

  1. Why is there the added level of pointer indirection to access the static variable? Is this just how statics are implemented in ARM?
  2. Ultimately what I'd like to get is decompiler output that looks like this:
void update_radio_bitrate(void)

{
  char cVar1;
  
  *(uint *)(PTR_NRF_RADIO_Type_40001000.RESERVED6[59]_00003d20 + 0x10) =
       (uint)(byte)PTR_nrf_esb_config_00003d1c[8];
  cVar1 = PTR_nrf_esb_config_00003d1c[8];
  if (cVar1 == '\0') {
    wait_for_ack_timeout_us = 0x40;
  }
  else if (cVar1 == '\x01') {
    wait_for_ack_timeout_us = 0x30;
  }
  else if (cVar1 == '\x02') {
    wait_for_ack_timeout_us = 0xfa;
  }
  else if (cVar1 == '\x03') {
    wait_for_ack_timeout_us = 0x40;
  }
  return;
}

Is this possible?

1 Answer 1

1

Right click PTR_DAT_00003d24 and retype it to be a pointer** and it should show up correctly

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.