binaryninja-api icon indicating copy to clipboard operation
binaryninja-api copied to clipboard

ARM function calls ignore target function type

Open nshp opened this issue 2 years ago • 6 comments

Version and Platform (required):

  • Binary Ninja Version: All for a long time
  • OS: Ubuntu (and others)
  • OS Version: 22.04
  • CPU Architecture: x64

Bug Description: It seems in most if not all cases function calls in ARMv7 do not respect the type you set for them. This includes when you "override call type" at the call site as well as changing the target function type. For example, I'll set a function type to int sprintf(char *buf, const char *fmt, ...), and some call sites will stubbornly refuse to show anything other than sprintf() with no parameters. This can be hard to see at first because binja's call-site parameter detection usually does a decent job on its own, but for anything else, especially variadic functions, it seems to be unfixable.

I've seen this both in Thumb and ARM mode, in regular Linux ELFs and baremetal firmware, and for a long time. Thought there was a report for this already, but I can't find it now.

nshp avatar Oct 19 '23 21:10 nshp

Hey, I compiled a little binary (hello.zip) with an sprintf() call and another rando function and am able to override both.

Before:

image

After:

image

Could you share your example binary?

lwerdna avatar Oct 25 '23 17:10 lwerdna

Can't share and of course I'm also having trouble reproducing this with other binaries. I'll see if I can figure out what the difference is.

nshp avatar Oct 25 '23 18:10 nshp

of course I'm also having trouble reproducing this with other binaries

Heh it's always that way. I'll watch for a followup.

lwerdna avatar Oct 25 '23 18:10 lwerdna

htop-arm.zip

Found a small example in here. Open, let analysis finish, then go to 0x000a43dc. Set the type of this function to void* xcalloc(uint32_t arg1, uint32_t arg2). Binja automatically adds __convention("cdecl") when changing the type. Let reanalysis finish. The very first xref at 0x00045924 does not (always?) change to reflect the new type, it's still int32_t r0 = xcalloc(). In this case if you go there and "override call type" it does take.

I noticed more weird behavior here - the first time I did these steps it did update that call type, but then I scrolled around a bit and came back and it changed itself back to int32_t r0 = xcalloc(). This was on an M2 MBP in 3.6.4593-dev FWIW.

nshp avatar Nov 05 '23 01:11 nshp

Yep, I can reproduce this on 3.6.4617-dev - Many of the callsites for xcalloc (after following the steps above) do not change type to void*. Thanks for the test case, super helpful!

fuzyll avatar Nov 07 '23 15:11 fuzyll

I suspect this is related to this: https://github.com/Vector35/binaryninja-api/issues/3927

plafosse avatar Jan 31 '24 21:01 plafosse

The root cause of this has been identified, the fix is pending, and it was in fact a duplicate of #4529. Explanation of the bug here.

rssor avatar Apr 17 '25 22:04 rssor