Skip to content

Conversation

@bdash
Copy link
Contributor

@bdash bdash commented Sep 25, 2025

LC_FUNCTION_STARTS includes both functions and jump tables. We want to avoid calling AddFunctionForAnalysis on jump tables since it can result in a function being created at the jump table's location with a bogus body.

We already skip adding functions for entries in LC_FUNCTION_STARTS if the lifting of their first few bytes end up including LLIL_UNDEF. However, arm64 intentionally lifts udf instructions (i.e., opcodes in the Permanently Undefined range) to LLIL_TRAP in order to preserve the immediate portion of the instruction.

To address this, MachoView::IsValidFunctionStart now returns false if the first lifted instruction is LLIL_TRAP in addition to when the lifting contains LLIL_UNDEF.

@bdash
Copy link
Contributor Author

bdash commented Sep 25, 2025

This prevents functions like this from being created:

00045b7c    void jump_table_45b7c() __noreturn

00045b7c     0  0c000000   udf     #0xc
{ Does not return }

Instead they are displayed as jump table data like so:

00045b7c  uint32_t jump_table_45b7c[0x58] = 
00045b7c  {
00045b7c      [0x00] = __macho_header.filetype
00045b80      [0x01] = __macho_section_64_[6][4]
00045b84      [0x02] = data_3dc
00045b88      [0x03] = 0x25c
00045b8c      [0x04] = 0x21c
00045b90      [0x05] = 0x27c
00045b94      [0x06] = 0x31c
00045b98      [0x07] = 0x3fc
00045b9c      [0x08] = 0x43c
00045ba0      [0x09] = 0x468

`LC_FUNCTION_STARTS` includes both functions and jump tables. We want to
avoid calling `AddFunctionForAnalysis` on jump tables since it can
result in a function being created at the jump table's location with a
bogus body.

We already skip adding functions for entries in `LC_FUNCTION_STARTS` if
the lifting of their first few bytes end up including `LLIL_UNDEF`.
However, arm64 intentionally lifts `udf` instructions (i.e., opcodes in
the Permanently Undefined range) to `LLIL_TRAP` in order to preserve the
immediate portion of the instruction.

To address this, `MachoView::IsValidFunctionStart` now returns false if
the first lifted instruction is `LLIL_TRAP` in addition to when the
lifting contains `LLIL_UNDEF`.
@bdash bdash force-pushed the macho-function-starts branch from 023684e to dcf1126 Compare October 2, 2025 16:16
@bdash bdash merged commit dcf1126 into dev Oct 2, 2025
4 of 5 checks passed
@bdash bdash deleted the macho-function-starts branch October 2, 2025 16:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants