Date: Wed, 5 Sep 2012 16:28:13 +0100 From: Jonathan Anderson <jonathan@FreeBSD.org> To: freebsd-arch@freebsd.org Subject: Call graphs with bsd.obj.mk Message-ID: <CAMGEAwCNuF-P80XgsMBm1a=vSPBhB_GNw%2Bqw5ZUmPXRC2NrsGQ@mail.gmail.com>
next in thread | raw e-mail | index | archive | help
[-- Attachment #1 --]
Hi all,
While doing some hacking recently, I really wanted a call graph. Clang
and LLVM make this pretty easy, assuming you have the right CFLAGS, so
a little build system integration seemed to be in order. I did this,
it's pretty small and modular, and I find it useful, so I'm sharing
this work with the list in the hope of putting it into -CURRENT.
I've attached two BSD makefiles that let me produce call graphs from
any directory that includes bsd.obj.mk (which notably includes
binaries and libraries in src):
- bsd.analysis.mk contains a 'callgraph' target that produces
${.OBJDIR}/_callgraph_.dot
- bsd.llvm.mk contains a few LLVM helpers (e.g. to generate LLVM IR)
If you have clang, llvm-link and opt installed, this allows you to
generate a complete call graph for C code; assembler files are ignored
because we don't currently have assembly -> IR transformations. The
resulting graph can be pretty large and ugly (e.g. LLVM shows an
"external node" pseudo-function that calls everything), but it can be
filtered with scripts like those found at
https://github.com/trombonehero/dot-tools to produce really useful
graphs.
llvm-link and opt aren't included in the bootstrap tools, so I'm
currently doing this by installing the llvm-devel package. Perhaps we
might copy llvm-link and opt over to /usr/obj/usr/src/tmp, possibly
governed by a WITH_LLVM_TOOLS flag in src.conf or something?
Jon
--
Jonathan Anderson
jonathan@FreeBSD.org
http://freebsd.org/~jonathan/
[-- Attachment #2 --]
# $FreeBSD$
#
# The include file <bsd.analysis.mk> provides source code analysis tools like
# C call graphs.
#
# +++ targets +++
#
# callgraph:
# Generate a GraphViz .dot file in ${.OBJDIR}/_callgraph_.dot containing
# the call graph of all C (and maybe C++) functions.
#
# The resulting graph may be quite large, so you may like to filter it
# using scripts from https://github.com/trombonehero/dot-tools.
#
.include <bsd.init.mk>
.include <bsd.llvm.mk>
.SUFFIXES: .dot
DOTFILES= ${LLVM_BC:R:S/$/.dot/g}
CLEANFILES+= ${DOTFILES} _callgraph_.dot _callgraph_.bc
callgraph: _callgraph_.dot
_callgraph_.bc: ${LLVM_BC}
llvm-link -o $@ $?
# Extract call graph from LLVM IR (binary .bc or textual .ll).
.bc.dot:
opt -analyze -dot-callgraph $<
mv callgraph.dot $@ # LLVM currently hardcodes the .dot output file
.ll.dot:
opt -analyze -dot-callgraph $<
mv callgraph.dot $@ # LLVM currently hardcodes the .dot output file
[-- Attachment #3 --]
# $FreeBSD$
#
# The include file <bsd.llvm.mk> handles LLVM-specific tasks like compiling
# C to LLVM IR.
#
# +++ targets +++
#
# bc:
# compile all C sources in ${SRCS} to binary LLVM IR format
#
# ir:
# compile all C sources in ${SRCS} to textual LLVM IR format
#
.include <bsd.init.mk>
.SUFFIXES: .c .cc .cpp .cxx .C .bc .ll
# LLVM bytecode is a binary format.
LLVM_BC= ${SRCS:N*.h:N*.S:R:S/$/.bc/g}
# LLVM IR contains the same information, but in an assembly-like format.
LLVM_IR= ${SRCS:N*.h:N*.S:R:S/$/.ll/g}
CLEANFILES+= ${LLVM_BC} ${LLVM_IR}
# Build all LLVM IR (binary .bc or textual .ll).
bc: ${LLVM_BC}
ir: ${LLVM_IR}
# Compile C code to binary LLVM IR bytecode.
.c.bc: usingclang
.if defined(PROG_CXX)
clang++ -c -emit-llvm ${CFLAGS} -o $@ $<
.else
clang -c -emit-llvm ${CFLAGS} -o $@ $<
.endif
# Compile C code to textual LLVM IR format.
.c.ll: usingclang
.if defined(PROG_CXX)
clang++ -S -emit-llvm ${CFLAGS} -o $@ $<
.else
clang -S -emit-llvm ${CFLAGS} -o $@ $<
.endif
# Ensure that we are compiling with clang.
usingclang:
.if ${MK_CLANG} != "yes"
@echo "===================================================================="
@echo "C -> LLVM IR compilation requires clang."
@echo "You may wish to enable WITH_CLANG in /etc/make.conf."
@echo "===================================================================="
@exit 1
.endif
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?CAMGEAwCNuF-P80XgsMBm1a=vSPBhB_GNw%2Bqw5ZUmPXRC2NrsGQ>
