Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Custom Storage "Only the last entry may be of type Stack" error prevents accurately representing ARM APCS calling convention #7434

Open
LRFLEW opened this issue Feb 1, 2025 · 0 comments

Comments

@LRFLEW
Copy link
Contributor

LRFLEW commented Feb 1, 2025

Describe the bug
This issue is related to #3977. That issue report is about how double-word sized function arguments (ulonglong and double for 32-bit ARM) don't use registers in the ARM calling convention due to missing cspec entries. Specifically, that issue report describes the modern AAPCS standard, which requires double-word sized values to be passed using r1:4,r0:4, r3:4,r2:4, or the stack. However, the older APCS standard is more permissive about where the value starts, such as allowing it to passed using r2:4,r1:4. This is where the problem occurs.

I'm analyzing a little-endian APCS binary currently, and I'm using the "Use Custom Storage" option to correct for the calling convention issues. However, one function has a double argument as the third argument (with the preceding 3 arguments being word sized). For the little-endian APCS standard, this stores the least-significant half in r3, and the other half on the stack. (See this goldbolt example for reference. Note that r3 gets written to the stack, then immediately read to r0 for returning.) This means that the storage should be set to Stack[0x0]:4,r3:4. However, trying to set this in the Storage Address Editor window gives the message "Only the last entry may be of type Stack" and it stops me from applying the storage layout. Swapping the order lets me apply the storage, but it puts the halves in the wrong order.

I understand that having values split between the stack and registers is an uncommon case that probably hadn't been considered, but since there is a calling convention that uses it (even if it's an outdated one), this case should probably be supported by Ghidra

To Reproduce
Steps to reproduce the behavior:

  1. Create a project for a 32-bit ARM binary (I used an ARMv4T binary) that uses the older APCS ABI (eg. using -mabi=atpcs with gcc)
  2. Open the Edit Function window for a function
  3. Check the box for "Uses Custom Storage"
  4. Double click an argument's storage to open the Storage Address Editor
  5. Set the Storage Locations to Stack[0x0]:4 first and r3:4 second
  6. Note the error and grayed out OK button

Expected behavior
Ghidra should accept the storage layout, since it's part of a standardized calling convention.

Screenshots

Image

Environment (please complete the following information):

  • OS: Windows 10 22H2
  • Java Version: 23.0.1
  • Ghidra Version: 11.2.1
  • Ghidra Origin: Github precompiled release
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

No branches or pull requests

1 participant