Skip to content

Wrong type definitions for self-referencing structs when imported from dwarf #7943

@waskyo

Description

@waskyo

Version and Platform (required):

  • Binary Ninja Version: 5.3.9062-dev Ultimate (1e8a86db)
  • Edition: Non-Ultimate
  • OS: Debian Linux
  • OS Version: unstable
  • CPU Architecture: Binary is arm32, I'm running on x64.

Bug Description:
I'm not sure if the title of the bug is correct but that's as good as I was able to come up. I am also not sure if the problem is only with structs that reference themselves, but that was the minimal test case I was able to create.

The attached binary has dwarf information, and one of the types looks like this in the original source:

typedef struct self_ref {
  struct self_ref *next;
  int a;
  int b;
} self_ref;

However, when I open the binary in BN and look at the type in the sidebar it has invalid C:

struct self_ref __packed
{
    self_ref* next;  // <--- Should be struct self_ref* 
    int a;
    int b;
};

And similarly in the console:

>>> s = bv.types['self_ref']
>>> print("\n".join("%s" % line for line in s.get_lines(bv, 'self_ref')))
struct self_ref __packed
{
    self_ref* next;
    int a;
    int b;
};

Interestingly enough if I export the header for the binary the problem is not there (see attached header file).

And I can sort of workaround around the problem by importing the header back, and telling BN to replace the definition of the bogus type with the one coming from the header:

Image

This is what I get after the import:

>>> s = bv.types['self_ref']
>>> print("\n".join("%s" % line for line in s.get_lines(bv, 'self_ref')))
struct self_ref __packed
{
    struct self_ref* next;
    int32_t a;
    int32_t b;
};

However, this is not ideal since you have to figure out all the types that need reimporting, and deal with duplicated types (like the one in the screenshot, Elf32_Ident_1).

We have a plugin that relies on type definitions from BN so this is breaking things for us when people try to use it with binaries that have dwarf info.

Steps To Reproduce:

See description above.

Expected Behavior:

When I open the attached binary, the type for self_ref contains valid C:

>>> s = bv.types['self_ref']
>>> print("\n".join("%s" % line for line in s.get_lines(bv, 'self_ref')))
struct self_ref __packed
{
    struct self_ref* next;
    int32_t a;
    int32_t b;
};

Screenshots/Video Recording:

See above

Binary:

bug_report.zip

And here's the header that BN exports from the binary which doesn't have the invalid C code:

bn_exported_header.txt

Metadata

Metadata

Assignees

Labels

Type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions