NationalSecurityAgency / ghidra

Ghidra is a software reverse engineering (SRE) framework
https://www.nsa.gov/ghidra
Apache License 2.0
52.16k stars 5.91k forks source link

dsPIC30 ELF relocation issue #1689

Closed ryanmkurtz closed 4 years ago

ryanmkurtz commented 4 years ago

Here is a small program's ELF object file for the dsPIC30:

#include <stdio.h>

int main(void) {

    printf("Hello World\n");
}
Capture

Here is objdump's relocation information for the .text section:

OFFSET   TYPE              VALUE
00000002 WORD              .LC0
00000004 PC RELATIVE BRANCH  _puts

And Ghidra's corresponding relocation table entry:

Captu2re

Ghidra appears to be fixing up relocations in the wrong locations, resulting in a bad call target and a corrupted return instruction.

main.zip

ghidra1 commented 4 years ago

Could you please provide a fully linked binary which includes this object module. Need to ensure that while addressing object module concerns we do not break those for a fully linked module.

ryanmkurtz commented 4 years ago

Sure:

Test.X.production.zip

ghidra1 commented 4 years ago

There are a number of issues involved:

  1. the relocation offset (r_offset) needs to be treated as byte offset within relevant section. Need to investigate generalization of r_offset treatment. With corrected offset applied relocation still fails to produce correct result (rcall to puts) - need to examine relocation computation (type 0x1c).
  2. The .const section was created as overlay causing section load to be messed-up. Overlay creation triggered by conflicting placement of __c30_signature section which needs investigation.
  3. With applied relocation at 0x10002 (with correct r_offset treatment) W0 is assigned a value of 0x5 for rcall to puts while string is at offset 0xa within .const - this seems wrong.
ryanmkurtz commented 4 years ago

Additionally, the object file for this code introduces two new relocation types that aren't implemented: 0x15 and 0x18.

__prog__ const char __attribute__((space(psv))) hello_world[] = "Hello World";

int main(void) {

    printf("%s\n", hello_world);
    printf("Hello World!\n");
}

main.zip

ryanmkurtz commented 4 years ago
__prog__ const char __attribute__((space(psv))) hello_world[] = "Hello World";

int main(void) {

    printf("%s, %d\n", hello_world, 5);
    printf("Hello World, %d\n", 6);
}

main.zip Test.X.zip

ryanmkurtz commented 4 years ago
__prog__ const char __attribute__((space(psv))) hello_world[] = "Hello World";

int sum(int n, ...) {
    int i, ret = 0;
    va_list valist;
    va_start(valist, n);

    for (i = 0; i < n; i++) {
        ret += va_arg(valist, int);
    }

    va_end(valist);

    return ret;
}

int main(void) {

    printf("%s, %d\n", hello_world, 5);
    printf("Hello World, %d\n", 6);
    printf("sum(5, 1,2,3,4,5) = %d", sum(5,1,2,3,4,5));
}

main.zip Test.X.zip

ryanmkurtz commented 4 years ago

Fixed by 305a1ddf98076cfe540e1d7046dc774fd6b89a67

emteere commented 4 years ago

Fixed in master and future 9.2