Hello,
when we look at the "program graph" of a function, we can see basic blocks containing CALL instruction, which means that CALL does not create a new basic block. However, when getting an iterator using API, we always get basic blocks that are created with CALL too. For example,
```
sbm=SimpleBlockModel(currentProgram, False)
function = getFirstFunction()
while function is not None:
entry_addr=function.getEntryPoint()
blocks=sbm.getCodeBlocksContaining(function.getBody(), monitor)
while (blocks.hasNext()):
bb = blocks.next();
dest=bb.getDestinations(monitor)
while (dest.hasNext()):
dbb = dest.next();
print "\t[*] 0x%x:" % dbb.getDestinationAddress().getOffset()
function = getFunctionAfter(function)
```When we run the above code, we also get target destination (for getDestinationAddress().getOffset()) that are CALL to other functions and then the code iterate on those functions.
Any suggestions?
I think I got the answer by reading a bt more into the API doc. if we use BasicBlockModel(), we get what I asked for. HOwever, on a closer look, I found another problem: For a given function, I am getting references that are not contained in the function! any idea what happens when we use function.getBody() ?
Hey thanks for submitting this issue @tosanjay. I didn't realize there were differences between SimpleBlockModel and BasicBlockModel. Switching from simple to basic solved part of my problem as well. As you've stated, for some reason when iterating over basic blocks, we're getting the root basic block from any calls.
Until this is resolved, I've been using getFunctionAt() to determine if the destination block is the result of a call. getFunctionAt() is useful because it returns None (python) if the address provided is not the entry point of a function. So we can use it to ignore basic blocks we don't want. Here's an example:
from ghidra.program.model.block import BasicBlockModel
from ghidra.util.task import ConsoleTaskMonitor
funcName = 'main'
blockModel = BasicBlockModel(currentProgram)
monitor = ConsoleTaskMonitor()
func = getGlobalFunctions(funcName)[0]
print("Basic block details for function '{}':".format(funcName))
blocks = blockModel.getCodeBlocksContaining(func.getBody(), monitor)
# print first block
print("\t[*] {} ".format(func.getEntryPoint()))
# print any remaining blocks
while(blocks.hasNext()):
bb = blocks.next()
dest = bb.getDestinations(monitor)
while(dest.hasNext()):
dbb = dest.next()
if not getFunctionAt(dbb.getDestinationAddress()):
print("\t[*] {} ".format(dbb))
Here's the output of my target binary:
Basic block details for function 'main':
[*] 00100690
[*] 001006b1 -> 00100700
[*] 001006fc -> 00100700
[*] 00100709 -> 001006b3
[*] 00100709 -> 0010070b
If anyone has a better way to do this, please let me know. Thanks!
Most helpful comment
Hey thanks for submitting this issue @tosanjay. I didn't realize there were differences between
SimpleBlockModelandBasicBlockModel. Switching from simple to basic solved part of my problem as well. As you've stated, for some reason when iterating over basic blocks, we're getting the root basic block from any calls.Until this is resolved, I've been using
getFunctionAt()to determine if the destination block is the result of a call.getFunctionAt()is useful because it returnsNone(python) if the address provided is not the entry point of a function. So we can use it to ignore basic blocks we don't want. Here's an example:Here's the output of my target binary:
If anyone has a better way to do this, please let me know. Thanks!