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

Wrong output of getCallingFunctions and getCalledFunctions #7532

Open
X-l-l-l opened this issue Feb 21, 2025 · 5 comments
Open

Wrong output of getCallingFunctions and getCalledFunctions #7532

X-l-l-l opened this issue Feb 21, 2025 · 5 comments
Assignees
Labels
Status: Waiting on customer Waiting for customer feedback

Comments

@X-l-l-l
Copy link

X-l-l-l commented Feb 21, 2025

Describe the bug
I am using the methods getCallingFunctions and getCalledFunctions to create a callgraph of the functions and it seams like their output is wrong.

To Reproduce
Steps to reproduce the behavior:

  1. create a flat_api by opening a program with open_program
  2. create a function manager with getFunctionManager()
  3. create a ConsoleTaskMonitor()
  4. use getCallingFunctions and getCalledFunctions with both pyghidra with 1.13 and pyhidra 1.12
  5. observe that the output differs

Expected behavior
I have this example, using a dummy executable that prints a string, and by using the methods above and creating a dictionary representing the hierarchy i get:

  • with old pyhidra and ghidra 1.12:
{'_init': {'__gmon_start__': {}}, 'FUN_00101020': {}, '_start': {'main': {...}, '__libc_start_main': {}}, '__do_global_dtors_aux': {'deregister_tm_clones': {...}, 'FUN_00101040': {...}}, 'frame_dummy': {'register_tm_clones': {...}}, '_fini': {}}
  • with new pyghidra and ghidra 1.13 (or 1.13.1)
{'_init': {'__gmon_start__': {}}, 'FUN_00101020': {}, '_start': {'__libc_start_main': {}}, '__do_global_dtors_aux': {'FUN_00101040': {...}, 'deregister_tm_clones': {...}}, 'frame_dummy': {'register_tm_clones': {...}}, 'main': {'puts': {}}, '_fini': {}}

Issue is that _start calls main, which the old version outputs correctly, but not the new one.

Environment (please complete the following information):

  • OS: Ubuntu 24.0.4.1 LTS
  • Java Version: openjdk 21.0.6 2025-01-21
  • Ghidra Version: 1.13.1
  • Ghidra Origin: official GitHub distro

Additional context
I have double checked with the ghidra gui and also IDA and can confirm that _start calls main.

@ghidracadabra
Copy link
Contributor

This is likely a difference between Ghidra 11.2 and Ghidra 11.3. The behavior of getCallingFunctions and getCalledFunction was corrected.

In your example, does _start actually call main? Or does _start call _libc_start_main and pass _libc_start_main the address of _main as an argument?

@ghidracadabra ghidracadabra self-assigned this Feb 21, 2025
@ghidracadabra ghidracadabra added the Status: Waiting on customer Waiting for customer feedback label Feb 21, 2025
@X-l-l-l
Copy link
Author

X-l-l-l commented Feb 21, 2025

Indeed it is passed as an argument, but the graphs in both ghidra gui and IDA show main as a "child" of _start.
So if my understanding of this is correct, the output of the 2 functions now is correct because main isn't actually called, which does make sense. Although, if this was right main would be a "root" function, which i don't really think it should be.
Is there maybe another way to get the same output as ghidra 11.2 did, or would you say that it is correct that main has no other parents (is not called)?

@X-l-l-l
Copy link
Author

X-l-l-l commented Feb 21, 2025

Also, i got this screenshot form opening the said executable in the ui of ghidra 1.13.1 which shows the function call trees:

Image

@ghidracadabra
Copy link
Contributor

In the function call tree, the "link" icon (immediately to the left of the "5") controls whether non-call references are excluded. Toggling that should determine whether main appears as an outgoing reference for start. For a call tree entry, the link icon means that the reference is not a call reference. The purple f for _libc_start_main means that it is a call reference.

To re-create the old behavior, you could make a method in your script based on the implementation of getCallingFunctions

public Set<Function> getCalledFunctions(TaskMonitor monitor) {

Basically, you iterate over all references whose "from" address is in the function's body. If the "to" address of a reference is the entry point of a function, add the referenced function to a set. You would omit the check on line 2748, which restricts to call references.

@X-l-l-l
Copy link
Author

X-l-l-l commented Feb 21, 2025

Ok, that sounds nice, I'll look into it. Thanks a lot!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Status: Waiting on customer Waiting for customer feedback
Projects
None yet
Development

No branches or pull requests

2 participants