ghidra icon indicating copy to clipboard operation
ghidra copied to clipboard

Decompiler: Low-level Error: Could not find op at target address: (code, ...) (AVR)

Open ghost opened this issue 1 year ago • 4 comments

I have been consistently hitting this issue while reconstructing an AVR sample manually (with 10.2.3, with the code segment "loading" emulating by copying the relevant blocks into a new codebyte segment, which is already present at program import time apparently):

Low-level Error: Could not find op at target address: (code,0x00336b)

The relevant disasm:

     byte: 64 e1           ldi        R22,0x14
     byte: 77 e5           ldi        R23,0x57
     byte: 8d 5b           subi       R24,0xbd
     byte: 9f 4f           sbci       R25,0xff
     byte: f7 01           movw       Z,R15R14
     byte: 19 95           eicall
     byte: d8 01           movw       X,R17R16
     byte: 5b 96           adiw       X,0x1b
     byte: 8d 93           st         X+,R24

Another test case:

     byte: cf 93           push       Ylo
     byte: 80 91 27 3a     lds        R24,DAT_mem_xxxx
     byte: 83 30           cpi        R24,0x3
     byte: a1 f0           brbs       FUN_code_xxxa2e,Zflg
     byte: 80 91 3f 3c     lds        R24,BYTE_ARRAY_mem_xxx[...]
     byte: 88 23           and        R24,R24
     byte: 81 f0           brbs       LAB_code_00xxx+2,Zflg
     byte: c2 e0           ldi        Ylo,0x2
     byte: c0 93 05 06     sts        PORTA_OUTSET,Ylo                                 = ??
     byte: e0 91 c0 3c     lds        Zlo,DAT_mem_xxx0
     byte: f0 91 c1 3c     lds        Zhi,DAT_mem_xxx1
     byte: 04 84           ldd        R0,Z+0xc
     byte: f5 85           ldd        Zhi,Z+0xd
     byte: e0 2d           mov        Zlo,R0
     byte: 6c e6           ldi        R22,0x6c
     byte: 77 e3           ldi        R23=>DAT_mem_xxxc,0x37
     byte: 80 e0           ldi        R24,0x0
     byte: 19 95           eicall
     byte: c0 93 06 06     sts        PORTA_OUTCLR,Ylo                                 = ??
     byte: cf 91           pop        Ylo
     byte: 08 95           ret

Gives: Low-level Error: Could not find op at target address: (code,0x002a2e)

Notice the eicall op (see https://gcc.gnu.org/onlinedocs/gcc-4.7.4/gcc/AVR-Options.html EIND handling).

My initial suspicion is that EICALL constructs are not being handled properly, or something else is amiss, since all of these have the common denominator of not being detected by auto-analysis. Many of them have proper push/pop prologues/epilogues and ret/jmp "exits", so I can easily find them manually and force a function to be created in place.

It makes RE tedious and time consuming since it just so happens to be affecting the interesting bits of my sample. The AVR capabilities have come a long way, and I'm happy with being a guinea pig for the improvements. I'm not reliant solely on the decompiler so it isn't a blocking issue per se, but it is definitely causing problems as far as references are involved.

ghost avatar Mar 01 '23 16:03 ghost

Notes from Wikipedia (memory refresh):

(Rare) models with >128 KiB of ROM have a 3-byte program counter. Subroutine calls and returns use an additional byte of stack space, there is a new EIND register to provide additional high bits for indirect jumps and calls, and there are new extended instructions EIJMP and EICALL which use EIND:Z as the destination address. (The previous IJMP and ICALL instructions use zero-extended Z.)

(Rare) models with >64 KiB of RAM address space extend the 16-bit RAM addressing limits with RAMPX, RAMPY, RAMPZ and RAMPD registers. These provide additional high bits for addressing modes which use the X, Y, or Z register pairs, respectively, or the direct addressing instructions LDS/STS. Unlike ROM access, there are no distinct "extended" instructions; instead the RAMP registers are used unconditionally.

Now, back to Ghidra:

     code: 4a 5f           subi       R20,250
     code: 5f 4f           sbci       R21,0xff
     code: 84 e1           ldi        R24,0x14
     code: 90 e0           ldi        R25,0x0
     code: 19 95           eicall

Yields:

                puVar18 = (undefined2 *)FUN_code_xxxx();
              auStack_13 = (undefined  [3])0xXXX ;// code segment
              (*(code *)CONCAT12(EIND,*puVar18))
                        (0x14,*(int *)(pbVar15 + 10),*(char *)(*(int *)(pbVar15 + 10) + 2) * 2 + 6);

Seems like this could be easily simplified... the CONCAT(EIND,puVar18) and auStack decompilation is quite obfuscated. Unfortunately I'm not yet familiar enough with the internals of the AVR processor in Ghidra and I'm still relatively new to this particular RE target, but so far it seems many functions that are apparently orphaned (no incoming references) just happen to be the side effect of some issues with call constructs not being properly handled. The segments are there, in this case I manually reconstructed most of the ".text" and I am certain 99% of the sample is both mapped, including EEPROM and memory data extracted and mapped into the right spot.

ghost avatar Mar 07 '23 02:03 ghost

We really need a complete function sample to diagnose this kind of exception in the decompiler. Assuming the second sample is complete, I loaded it in ghidra-10.2.3 as an AVR8:LE:24:xmega:gcc at address code:2a15, but was still unable to produce the Low-level Error. It seemed to decompile just fine. Please double check that your avr8 .sinc and .slaspec files aren't modified. If that isn't the issue, you could try uploading the output from the "Debug Function Decompilation" action, which is available from a drop-down menu in the upper right corner of the decompiler window, and which will give us more information about what the decompiler is seeing. You should be able to produce this output even though the window is only displaying "Low-level Error: ...".

caheckman avatar May 01 '23 18:05 caheckman

Do you have an e-mail address I could get back to?

ghost avatar May 14 '23 15:05 ghost

I recommened creating a private GitHub repo and inviting us to it.

ryanmkurtz avatar May 15 '23 12:05 ryanmkurtz