Skip to content

Add function signature reconstruction for Issue #14#79

Open
kami922 wants to merge 3 commits intomandiant:masterfrom
kami922:issue-14-define-apply-structs
Open

Add function signature reconstruction for Issue #14#79
kami922 wants to merge 3 commits intomandiant:masterfrom
kami922:issue-14-define-apply-structs

Conversation

@kami922
Copy link
Contributor

@kami922 kami922 commented Jan 22, 2026

  • Parse FuncType metadata to extract input/output parameter types (including variadic flag).
  • Build C-style function pointer typedefs and emit them in CReconstructed for Func kinds.
  • Represent multiple returns by commenting them in the typedef (C still single-return).
  • Add IDA script scaffolding to ingest function types (signature application is intentionally left as future work).
  • JSON now carries function signatures instead of opaque void* for functions.

- Parse FuncType metadata to extract input/output parameter types
- Build C-style function pointer typedefs with proper signatures
- Handle variadic functions and multiple return values
- Add infrastructure in IDA script to receive function types
- Emit CReconstructed field for Func types in JSON output

This enables IDA to import function signatures as types, laying
groundwork for applying types to function arguments/locals.
@kami922
Copy link
Contributor Author

kami922 commented Jan 22, 2026

@stevemk14ebr Hello

based on your review, here is the remaining checklist for the next commit. let me know if I missed anything.

  • Implement[apply_function_type in the IDA script to actually apply reconstructed signatures to funcs/args/locals.
  • Improve multiple-return handling (currently commented in typedef; consider struct/tuple).
  • Add small Go fixtures/tests to assert CReconstructed for funcs and an IDA import smoke test.

@stevemk14ebr
Copy link
Collaborator

stevemk14ebr commented Jan 22, 2026

I like where this is going! We can do better with the arg type and return type parsing though. Checkout this case

.rodata:00000000005B1F40 RTYPE_funcunsafe_Pointer_comma__unsafe_Pointer_bool RTYPE <8, 8, 6BB69B10h, TFLAG_EXTRASTAR, 8, 8, \
.rodata:00000000005B1F40                                         ; DATA XREF: .rodata:00000000005C7F08↓o
.rodata:00000000005B1F40                                         ; .rodata:00000000005C7F18↓o ...
.rodata:00000000005B1F40                        KIND_FUNC or KIND_DIRECTIFACE, 0, offset runtime_gcbits__ptr_, \
.rodata:00000000005B1F40                        offset byte_5A2644 - offset type__ptr_, 0>
.rodata:00000000005B1F70                 FUNC_TYPE <2, 1>
.rodata:00000000005B1F74                 align 8
.rodata:00000000005B1F78                 dq offset RTYPE_unsafe_Pointer
.rodata:00000000005B1F80                 dq offset RTYPE_unsafe_Pointer
.rodata:00000000005B1F88                 dq offset RTYPE_bool
.rodata:00000000005B1F90                 align 20h

This function takes 2 inputs, has 1 output, and the types of all 3 are present. Our reconstructed typedef is

{
    VA: 5971776, 
    Str: "func(unsafe.Pointer, unsafe.Pointer) bool", 
    CStr: "func(unsafe_Pointer,_unsafe_Pointer)_bool_funcptr", 
    Kind: "Func", 
    Reconstructed: "", 
    CReconstructed: "typedef void* (*func(unsafe_Pointer,_unsafe_Pointer)_bool_funcptr)(void*, void*)", 
    baseSize: 48, 
    kindEnum: Func (19), 
    flags: tflagExtraStar (2)
}

I'd expect the CStr to be bool (unsafe_Pointer,_unsafe_Pointer), the Reconstructed to be type funcunsafe_Pointer_comma__unsafe_Pointer_bool(unsafe.Pointer, unsafe.Pointer) bool or something similar. The CReconstructed is wrong, it should be something similar to typedef bool (*func_unsafe_Pointer__unsafe_Pointer_bool_funcptr)(unsafe_Pointer, unsafe_Pointer). In general we try to match the naming scheme of IDA, Reconstructed tries to use Go syntax, and CReconstructed tries to use C or C++ syntax.

So there's some formatting issues with the reconstruction, but the raw parsing logic seems mostly working! I agree with all the follow on work points, especially about tests.

For multiple return values we can use either structures or tuples, the project uses structures now, but IDA recently added tuples for Go so lets prefer those for this function type work. https://hex-rays.com/blog/stop-guessing-and-start-going

Actually applying these signatures via IDA scripting can be quite tricky since the types recursively depend on other types. I am completely ok with not having the IDA script implemented for now. I care most about reasonable and correct symbol recovery. We can do the IDA script work later.

Fix param array offset from baseSize+4 to baseSize+ptrSize to account
for struct padding on 64-bit. Add tflagUncommon handling (+16 bytes).
Reformat CStr as "returnType (params)", add Reconstructed with Go
syntax, fix CReconstructed with actual parsed types and clean funcptr
name. Collect both Go and C type names during param parsing.
@stevemk14ebr
Copy link
Collaborator

The CStr output formatting is inconsistent. See this case:

 RTYPE_func_int_comma__bool RTYPE <8, 8, 5B738012h, TFLAG_EXTRASTAR, 8, 8, \
.rdata:00000000004B2E40                                         ; DATA XREF: .rdata:00000000004B7928↓o
.rdata:00000000004B2E40                                         ; .rdata:00000000004B7930↓o ...
.rdata:00000000004B2E40                        KIND_FUNC or KIND_DIRECTIFACE, 0, offset unk_4E7708, \
.rdata:00000000004B2E40                        offset byte_4AA839 - offset byte_4A6000, 0>
.rdata:00000000004B2E70                 FUNC_TYPE <0, 2>
.rdata:00000000004B2E74                 align 8
.rdata:00000000004B2E78                 dq offset RTYPE_int
.rdata:00000000004B2E80                 dq offset RTYPE_bool
.rdata:00000000004B2E88                 align 20h
objfile.Type {
VA: 4927040, 
Str: "func() (int, bool)", 
CStr: "void (void)", 
Kind: "Func", 
Reconstructed: "func() (int, bool)", 
CReconstructed: "typedef tuple(int, bool) (*func_int_bool_funcptr)(void)", 
baseSize: 48,
 kindEnum: Func (19), 
flags: tflagExtraStar (2)}

The type recovery indicates 2 output arguments, but the CStr reconstruction is void (void).

Handle multiple returns using tuple syntax in CStr field.
For func() (int, bool), CStr now shows 'tuple(int32, bool) (void)'
instead of incorrectly showing 'void (void)'.
@kami922
Copy link
Contributor Author

kami922 commented Feb 9, 2026

@stevemk14ebr Hello, just dropping by to remind you about the pr.

@stevemk14ebr
Copy link
Collaborator

stevemk14ebr commented Feb 9, 2026

Hi, have other work taking priority I will review when able, thanks!

@kami922
Copy link
Contributor Author

kami922 commented Feb 20, 2026

@stevemk14ebr Hello dropping by again for review whenever convenient

@kami922
Copy link
Contributor Author

kami922 commented Feb 24, 2026

@stevemk14ebr Hello can you please review this as well?

@stevemk14ebr
Copy link
Collaborator

stevemk14ebr commented Feb 25, 2026

I'm aware of this, this one's a bit bigger so I have to set aside some time to review with the focus needed

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