radareorg / radare2

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

analyze function not finished on IAR generated elf for ARM Cortex-M device. #22327

Open knightLee opened 1 year ago

knightLee commented 1 year ago

Environment

$ date Mon, Oct 16, 2023 10:35:45 AM

$ radare2.exe -v radare2 5.8.8 1 @ windows-x86-64 birth: git.5.8.8 Thu 06/08/2023__14:01:37.60 commit: ea7f0356519884715cf1d5fba16042bac72b2df5 options: gpl -O? cs:5 cl:1 meson

$ uname -ms MINGW64_NT-10.0-19044 x86_64

Description

size and realsize field of function block information goes wrong.

[0x0804d114]> afi
#
offset: 0x0804d114
name: loc..text_49
size: 18
is-pure: false
realsz: 18
stackframe: 8
call-convention: arm16
cyclomatic-cost: 21
cyclomatic-complexity: 1
bits: 16
type: fcn [NEW]
num-bbs: 1
num-instrs: 6
edges: 0
minbound: 0x0804d114
maxbound: 0x0804d126
is-lineal: true
end-bbs: 1
call-refs: 0x0804bdf8 C 0x0804d2dc C 0x0804d12c J
data-refs: 0x0804d424
noreturn: false
in-degree: 0
out-degree: 2
data-xrefs:
locals: 0
args: 0
diff: type: new

with pdf,we can see sym.osIdleTask ends at 0x0804d152, not 0x804d124

[0x0804d114]> pd
            ;-- osIdleTask:
            ;-- pc:
            ;-- r15:
/ 18: loc..text_49 ();
|           0x0804d114      80b5           push {r7, lr}
|           0x0804d116      fef76ffe       bl loc..text_20_12
|           0x0804d11a      dff80813       ldr.w r1, obj.g_osIdleTaskThreadId
|           0x0804d11e      0860           str r0, [r1]
|           0x0804d120      00f0dcf8       bl sym.MC_ClearClkTimerInit
\       ,=< 0x0804d124      02e0           b sym.__osIdleTask_0
        |   ; CODE XREF from sym.__osIdleTask_0 @ 0x804d14a(x)
/ 6: sym.__osIdleTask_1 ();
|      .--> 0x0804d126      0120           movs r0, 1                  
\      :|   0x0804d128      fff7abff       bl sym.EnterSleep
       :|   ; CODE XREF from loc..text_49 @ 0x804d124(x)
       :|   ; CODE XREF from sym.__osIdleTask_2 @ 0x804d152(x)
/ 32: sym.__osIdleTask_0 (int16_t arg1);
|      :|   ; arg int16_t arg1 @ r0
|     .-`-> 0x0804d12c      1df07dfd       bl loc..text_17_13
|     ::    0x0804d130      0028           cmp r0, 0
|     ::,=< 0x0804d132      0bd0           beq sym.__osIdleTask_2
|     ::|   0x0804d134      06f09bfd       bl loc..text_20_11
|     ::|   0x0804d138      0128           cmp r0, 1                   
|    ,====< 0x0804d13a      07d1           bne sym.__osIdleTask_2
|    |::|   0x0804d13c      fff782ff       bl sym.HAL_BusIsBusy
|    |::|   0x0804d140      0028           cmp r0, 0
|   ,=====< 0x0804d142      03d1           bne sym.__osIdleTask_2
|   ||::|   0x0804d144      fff791ff       bl sym.HAL_SystemIsBusy
|   ||::|   ; STRN XREF from sym.__GetSleepTime_7 @ 0x804cd66(r)
|   ||::|   0x0804d148      0028           cmp r0, 0
\   ||:`==< 0x0804d14a      ecd0           beq sym.__osIdleTask_1
    ||: |   ; CODE XREFS from sym.__osIdleTask_0 @ 0x804d132(x), 0x804d13a(x), 0x804d142(x)
/ 8: sym.__osIdleTask_2 ();
|   ``--`-> 0x0804d14c      0020           movs r0, 0                  
|     :     0x0804d14e      fff798ff       bl sym.EnterSleep
\     `===< 0x0804d152      ebe7           b sym.__osIdleTask_0
[0x0804d114]> afbo
0x0804d114
0x0804d116
0x0804d11a
0x0804d11e
0x0804d120
0x0804d124

And with agcj, I can only get a only part of function callgraph of sym.osIdleTask, which starts from 0x804d114 and ends at 0x804d124( What I expected is 0x804d152).

[0x804d114]> agcj
[{"name":"loc..text_49","size":18,"imports":["sym.osThreadGetId","sym.MC_ClearClkTimerInit"]}]

Test

The ELF file is compiled with IAR Embedded Workbench. And for security constraint, I can not provide you ELF file.

$ radare2.exe -m 0x803c000 out.elf
WARN: using oba to load the syminfo from different mapaddress
[0x0803c000]> afco cc-arm-16.sdb
| afco path  open Calling Convention sdb profile from given path
[0x0803c000]> aaa
INFO: Analyze all flags starting with sym. and entry0 (aa)
INFO: Analyze all functions arguments/locals (afva@@@F)
INFO: Analyze function calls (aac)
INFO: Analyze len bytes of instructions for references (aar)
INFO: Finding and parsing C++ vtables (avrr)
INFO: Finding xrefs in noncode section (e anal.in=io.maps.x)
INFO: Analyze value pointers (aav)
INFO: aav: 0x0803c000-0x08297633 in 0x803c000-0x8297633
INFO: Emulate functions to find computed references (aaef)
INFO: Type matching analysis for all functions (aaft)
ERROR: Invalid program counter PC=-1 coming from 0x0824ae1c
ERROR: Invalid program counter PC=-1 coming from 0x08250d1c
ERROR: Invalid program counter PC=-1 coming from 0x0821c37c
ERROR: Invalid program counter PC=-1 coming from 0x080ded54
ERROR: Invalid program counter PC=-1 coming from 0x0828a304
ERROR: Invalid program counter PC=-1 coming from 0x08106840
INFO: Propagate noreturn information (aanr)
INFO: Use -AA or aaaa to perform additional experimental analysis
[0x0803c000]> f-loc* 
trufae commented 1 year ago

The reason why the function is split in that jump is because the destination have a symbol. so it's "correct", but wonder why there's a simbol in a basic block. there are configuration options to circumvent that case, but yeah thats not common construction, can you share this elf?

knightLee commented 1 year ago

For security constraint, I can not provide you ELF file. As to the configuration options, I have tested the following ones, some will hang the execution of radare2. e anal.hasnext = true # hang e anal.datarefs = true e anal.jmp.cref = true e anal.jmp.ref = true e anal.jmp.indir = true e anal.jmp.tbl = true

What's the prossibly working options, I can give a try?

trufae commented 7 months ago

Can you try with latest r2 from git?