NationalSecurityAgency / ghidra

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

incorrect decompiled address for relative jumps with AVR8 microcontroller #1951

Open owbeg opened 4 years ago

owbeg commented 4 years ago

Describe the bug I am trying to analyze firmware for AVR8 microcontroller (to be more specific - for ATmega8535). Ghidra in some cases generates incorrect address for relative jumps commands RJMP/RCALL when calculated address is "outside" of programm address space - this happened because (as I understand) Ghidra for AVR8 uses 24bit aritmetic for address calculation.

Example: address (0xfffc48) for RCALL command (calling procedure SUB_code_fffc48) calculated incorrectly, current address 0x441, offset in RCALL command is 0x806 (it is negative value) so Ghidra got (using 24bit arithmetic) finall address 0x441 + 0xFFF806 + 1 = 0xFFFc48 which is outside of program address space for ATmega8535 (actually address bus for this MCU is 12bit), correct addres is 0xc48. Ghidra marked this line with error "Address not in memory" ("Could not follow disassembly flow into non-existing memory at code:fffc48 (flow from code:000441)")

code:00043f a0 30           cpi        Xlo,0x0
code:000440 19 f0           brbs       LAB_code_000444,Zflg
code:000441 06 d8           rcall      offset SUB_code_fffc48

I understand how to correct this issue manually for single line - it is possible to edit Reference by changing destination address to correct value. But currently I have about 100 such errors so manual modification is not useful.

Please guide me how to solve this issue. I think it is a bug in the CPU definition (I think Ghidra should take into account code address space size)

To Reproduce Attached files 1) simple assembly file (contains only forever loop and at startup calls procedure proc_0x1f00 which placed at the end of program memory) - main.asm.txt 2) compiled assembly in Intel HEX format - asm_project.hex.txt 3) screenshot of Ghidra CodeBrowser with Listing window (which contains disassembled code)

For this example Ghidra incoorectly build address for procedure in RCALL command - it generate address 0xFFFF80, and as result - for RCALL command produced error "Could not follow disassembly flow into non-existing memory at code:ffff80 (flow from code:00001c)"

Expected behavior Address in RCALL command must be 0xF80

Attachments main.asm.txt asm_project.hex.txt avr8issue

Environment (please complete the following information):

owbeg commented 4 years ago

okey. Maybe anyone sugget how to correct this with Ghidra scripting? Like:

piotrva commented 3 months ago

Hi, I ran into the same issue with analyzing the code for ATMega8.

It seems like the issue originates from the fact, that some compilers simply make use of the fact, that memory of these chips (both ATMega8 and your ATMega8535) are 8KB, so maximum (16-bit word) address is 0xFFF. So they do assume that the most significant nibble will not be used and therefore addresses of 0xF123 and 0x0123 (as well as probably any other value of the most significant nibble) would result calling the same physical address of 0x123.

So I modified the avr8.sinc file and applied that mask, as follows:

rel12addr: rel  is oplow12signed [ rel = (oplow12signed + inst_start + 1) & 0x0FFF; ] { 
  export *[code]:2 rel;
}

Please do note, that for now it will only work with 8KB chips, and the original avr8.sinc was designed based on ATMega64 chip.