Skip site navigation (1)Skip section navigation (2)
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>