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

Some accesses don't work for 'Create Members at Accessed Offsets', depending on assembly

Open comex opened this issue 3 years ago • 2 comments

Version and Platform (required):

  • Binary Ninja Version: 3.0.3233 (Build ID e250d0a3) and 3.0.3262-dev (Build ID f7b5b2ba)
  • OS: macOS
  • OS Version: 12.1 21C52

Steps To Reproduce:

  1. Open this attached ELF.

  2. Create a function at address 0.

  3. Create a struct type and mark x0 as being a pointer to that struct.

  4. Notice that some accesses appear as accesses to unknown fields (good):

    x0->__offset(0x188).q = 0
    

    but others (bad) appear as either

    (x0 + 0x274)->__offset(0x0).q = 0
    

    or

    *(x0 + 0x274) = 0
    
  5. Right-click x0 and choose 'Create Members at Accessed Offsets'. Note that only the 'good' accesses have fields created for them.

Expected Behavior: All of the accesses have fields created for them.

Additional Information:

  • The 'bad' ones will still be decompiled as field accesses if you manually create a corresponding field in the struct; they just don't get fields automatically created for them.

  • Looking at the disassembly, the 'good' accesses look like

    str     xzr, [x19, #0x188] 
    

    (where x19 has the value originally in x0)

    while the 'bad' accesses look like:

    add     x10, x19, #0x274
    str     xzr, [x10]  {0x0}
    

    These are different assembly patterns but semantically equivalent, so I would expect them to be decompiled the same way.

  • The 'bad' accesses are all misaligned (8-byte accesses at offsets that are only 4-byte aligned), but this is not the reason Binary Ninja is treating them differently. If you edit the binary to make the offsets aligned, the behavior is the same.

    Rather, the misalignment is what caused the compiler to produce an alternate instruction pattern in the first place. AArch64 cannot encode str instructions with an immediate offset that's not a multiple of the store size (because the offset field is implicitly scaled by the store size).

comex avatar Feb 21 '22 05:02 comex

Looks like it's a failure to propagate types in MLIL if I had to guess but I'll let Rusty confirm for sure. You can manually fix it by switching to MLIL or MLIL_SSA and setting the type on the register copy, but it should be automatic I would think as the core does know it's the same base as the already existing type.

Here's an example where I manually fixed up one of those and you can see it become an offset: Screen Shot 2022-02-21 at 1 32 39 PM

psifertex avatar Feb 21 '22 18:02 psifertex

Types are resolved at the MLIL level, but there the assembly is causing there to be a variable that would need to be typed as pointer into the middle of the structure, which is then accessed later. This is blocked on #2461

D0ntPanic avatar Apr 11 '22 16:04 D0ntPanic

This has been resolved as of dev build 3751, with the added support for offset pointer types. The only member not created is at offset 0xa0 which has two accesses of conflicting size.

rssor avatar Oct 13 '22 13:10 rssor