LLVM Call Graph may not cover all calls

Hi there,
I am working with opt-6.0 and try to generate a call graph of libsndfile, but it seems the call graph doesn’t cover all call relationship.
Actually, I am doing static analysis on CVE-2014-8130, which is a zero division on libtiff/tif_write.c TIFFWriteScanline. (see https://security-tracker.debian.org/tracker/CVE-2014-8130)
Theoretically, the main function in tiffdither.c will call fsdither, and fsdither will call TIFFWriteScanLine. main (tiffdither.c) → fsdither (tiffdither.c) → TIFFWriteScanLine (tif_write.c)
I want to get a call graph of the buggy program tiffdither but I find the call graph generated doesn’t cover the call relationship from fsdither → TIFFWriteScanLine.
For short, the call graph now shows TIFFWriteScanLine is only called by an external node.
I already compile tiffdither, and I upload it as an attached file. I also write a small python to help analyze the dot file.
Actually, I do opt-6.0 -analyze -dot-callgraph tiffdither.bc to generate the dot file. And then modify the dotPath in dotHandle.py. You can modify the python code to help analyze.
I can’t figure out why this happens, and I will be very appreciate if you can help!

Thanks & Regards,
Chaz

tiffdither.bc (1.99 MB)

dotHandle.py (2.04 KB)

How are you generating the calligraph from? Generally a compiler only acts on a per translation unit basis, so it couldn’t form the complete program call graph across multiple files (hence why it’s missing the edge that crosses the boundary between .C files)

Looks like this is old LLVM IR - I don’t have an old version of LLVM that can read this. (I only have LLVM from subversion). Not sure what version it is, but if it’s not past the upgrade horizon, distributing/sharing bitcode (as LLVM has backwards compatibility guarantees for that) rather than textual IR might be more effective.

In any case, I’d suggest you try to create a reduced test case that demonstrates the problem. Strip out unrelated instructions, functions, etc, while preserving the IR, and see if it still produces the problem - when you can’t strip out anything else without losing the problem, then you have something someone else can more easily look at and explain/understand (equally, by oding this, maybe you find something critical that helps you understand what’s going on)

Hi,
I also have the same problem and I wrote some codes to mitigate this problem.
You can find it on github https://github.com/coffezhou/OverCG. I try it on the IR you
provided and it can get the call relationship from fsdither → TIFFWriteScanLine.
I hope it can help you.

Best,
Zhide

Hi zhide,
Cool Bro!!!
Your tool solve my problem perfectly !!!
It seems the original call graph has some problems. Then why don’t you submit your solution to LLVM-dev and integrate your code into the next version of opt? Your code may help lots of people like me who is not very familiar with LLVM.
BTW, probably CFG has the same problem because I think call graph is generated from CFG. Did you check before?
Anyway, Thanks a lot !!

Regards,
Chaz

cszide <cszide@163.com> 于2018年11月17日周六 上午9:38写道:

Hi Chaz,
Thanks for your suggestions. But, as the tool’s name, ‘OverCG’, the call graph may be over-approximation, and I only test it for c code.
Maybe I will implement a plugin using c++, I currently am learning how to use llvm:)
If you have any suggestions, please let me know. Thank you!

The CFG is right. Currently, the developers of opt/llvm only consider the direct call made by the call instruction, since the different language (rust, julia …) has different calling convention.

Best,
Zhide