嵌入式工具——oprofile

时间:2023-01-11 20:17:27

oprofile是linux平台功能强大的性能分析工具,支持两种采样(sampling)方式:基于事件的采样(event based)和基于时间的采样(time based)。

1、需要下载版本:

oprofile-0.9.7.tar.gz: http://oprofile.sourceforge.net/download/

popt-1.14.tar.gz: http://freshmeat.net/projects/popt/

binutils-2.21.1.tar.gz: http://ftp.gnu.org/gnu/binutils/


2、编译方法:

将下面内容放进shell脚本,修改交叉编译器,一键生成。

#!/bin/bash

#将上面3个包解压到同一个目录里,同时建立一下三个目录

mkdir target_dir
mkdir tmp_dir
mkdir bin

#arm-hisiv300-linux交叉编译器
CROSS_COMPILE=arm-hisiv300-linux
TMP_DIR=$PWD/tmp_dir
TARGET_DIR=$PWD/target_dir 

#1. compile popt library
cd popt-1.14 
make clean
./configure --with-kernel-support --host=$CROSS_COMPILE --prefix=$TMP_DIR LDFLAGS=-static ac_cv_va_copy=C99
make && make install
cd -

#2. compile binutils
cd binutils-2.21.1
make clean
./configure --with-kernel-support --host=$CROSS_COMPILE --enable-install-libbfd --prefix=$TMP_DIR --disable-nls
make && make install
cd -

#3. compile oprofile
cd oprofile-0.9.8
make clean
./configure --with-kernel-support --host=$CROSS_COMPILE  --with-binutils=$TMP_DIR --prefix=$TARGET_DIR LDFLAGS=-static
make
#use tatically linked
#<make install>

#(1)compile ophelp and op-check-perfevents
cd utils
rm ophelp
$CROSS_COMPILE-gcc -W -Wall -fno-common -Wdeclaration-after-statement -g -O2 -static -L$TMP_DIR/lib -Xlinker -R -Xlinker $TMP_DIR/lib -static -o ophelp ophelp.o ../libop/libop.a ../libutil/libutil.a -lpopt -liberty -ldl

rm op-check-perfevents
$CROSS_COMPILE-gcc -W -Wall -fno-common -Wdeclaration-after-statement -g -O2 -static -L$TMP_DIR/lib -Xlinker -R -Xlinker $TMP_DIR/lib -static -o op-check-perfevents op_check_perfevents-op_perf_events_checker.o  -lpopt -liberty -ldl

cd -

#(2)compile opannotate, oparchive, opgprof, opreport
cd pp
rm opannotate
$CROSS_COMPILE-g++ -W -Wall -fno-common -ftemplate-depth-50 -g -O2 -static -L$TMP_DIR/lib -Xlinker -R -Xlinker $TMP_DIR/lib -static -o opannotate opannotate.o opannotate_options.o common_option.o ../libpp/libpp.a ../libopt++/libopt++.a ../libregex/libop_regex.a ../libutil++/libutil++.a ../libop/libop.a ../libutil/libutil.a ../libdb/libodb.a -lpopt -lbfd -liberty -ldl

rm oparchive
$CROSS_COMPILE-g++ -W -Wall -fno-common -ftemplate-depth-50 -g -O2 -static -L$TMP_DIR/lib -Xlinker -R -Xlinker $TMP_DIR/lib -static -o oparchive oparchive.o oparchive_options.o common_option.o ../libpp/libpp.a ../libopt++/libopt++.a ../libregex/libop_regex.a ../libutil++/libutil++.a ../libop/libop.a ../libutil/libutil.a ../libdb/libodb.a -lpopt -lbfd -liberty -ldl

rm opgprof
$CROSS_COMPILE-g++ -W -Wall -fno-common -ftemplate-depth-50 -g -O2 -static -L$TMP_DIR/lib -Xlinker -R -Xlinker $TMP_DIR/lib -static -o opgprof opgprof.o opgprof_options.o common_option.o ../libpp/libpp.a ../libopt++/libopt++.a ../libregex/libop_regex.a ../libutil++/libutil++.a ../libop/libop.a ../libutil/libutil.a ../libdb/libodb.a -lpopt -lbfd -liberty -ldl

rm opreport
$CROSS_COMPILE-g++ -W -Wall -fno-common -ftemplate-depth-50 -g -O2 -static -L$TMP_DIR/lib -Xlinker -R -Xlinker $TMP_DIR/lib -static -o opreport opreport.o opreport_options.o common_option.o ../libpp/libpp.a ../libopt++/libopt++.a ../libregex/libop_regex.a ../libutil++/libutil++.a ../libop/libop.a ../libutil/libutil.a ../libdb/libodb.a -lpopt -lbfd -liberty -ldl

cd -

#(3)compile opjitconv
cd opjitconv
rm opjitconv
$CROSS_COMPILE-gcc -W -Wall -fno-common -Wdeclaration-after-statement -g -O2 -static -L$TMP_DIR/lib -Xlinker -R -Xlinker $TMP_DIR/lib -static -o opjitconv opjitconv.o conversion.o parse_dump.o jitsymbol.o create_bfd.o debug_line.o ../libutil/libutil.a -lbfd -liberty -ldl

cd -

#(4)compile opimport
cd libabi
rm opimport
$CROSS_COMPILE-g++ -W -Wall -fno-common -ftemplate-depth-50 -g -O2 -static -L$TMP_DIR/lib -Xlinker -R -Xlinker $TMP_DIR/lib -static -o opimport opimport.o libabi.a ../libdb/libodb.a ../libopt++/libopt++.a ../libutil++/libutil++.a ../libutil/libutil.a -lpopt -liberty -ldl

cd -

#(5)Last step
cd ..
cp oprofile-0.9.8/utils/op-check-perfevents bin/
cp oprofile-0.9.8/utils/ophelp bin/
cp oprofile-0.9.8/utils/opcontrol bin/
cp oprofile-0.9.8/pp/opannotate bin/
cp oprofile-0.9.8/pp/oparchive bin/
cp oprofile-0.9.8/pp/opgprof bin/
cp oprofile-0.9.8/pp/opreport bin/
cp oprofile-0.9.8/opjitconv/opjitconv bin/
cp oprofile-0.9.8/libabi/opimport bin/
cp oprofile-0.9.8/daemon/oprofiled bin/
chmod 755 bin/*

#将这个bin下的东西挂载到设备上

3、内核和打包坏境修改

(1)内核需要支持
选择内核的配置选项
General setup  --->  
 [*] Profiling support 
  <*> OProfile system profiling  

(2)busybox需要选择上oprofile使用的命令
tr, dirname, expr, id, which, pidof, grep, seq
另外,dirname\which 需要软连接到/usr/bin目录下

(3)在打包中创建root目录
在fstab中添加如下语句
tmpfs           /root           tmpfs   defaults        0       0
在/etc/mtab中
nodev /dev/oprofile oprofilefs rw 0 0

(4)将上面编译出来的所有bin文件挂载到设备上


4、基本使用方法

将bin挂载到设备后,进入挂载目录运行:

./opcontrol --reset
mount -t oprofilefs nodev /dev/oprofile
./opcontrol --reset
./opcontrol --init
#./opcontrol --no-vmlinux 
./opcontrol --vmlinux=./vmlinux
./opcontrol --start
./<应用程序,使用DEBUG版本>
./opcontrol --dump
./opcontrol --stop
<./opcontrol --shutdown>
./opreport -l(./opreport -l din1_debug) 查看函数级的分析结果

./opannotate --source   查看代码级别的分析结果


5、可能会出现的问题及解决方法

(1)编译出现undefined "query_module "
解决方法:oprofile-0.9.8/daemon/liblegacy/p_module.h中添加:
__attribute__((weak))

(2)opcontrol --reset出现如下错误1
Kernel support not available, missing opcontrol --init as root ?
解决方法:

在/etc/mtab中
nodev /dev/oprofile oprofilefs rw 0 0

(3)opcontrol --init出现如下错误2
cat: can't open '/dev/oprofile/cpu_type': No such file or directory
直接挂载mount -t oprofilefs nodev /dev/oprofile,如下错误:
mount: mounting nodev on /dev/oprofile failed: No such file or directory

需要先opcontrol --reset
再mount -t oprofilefs nodev /dev/oprofile

(4)./opcontrol --start
objdump is not installed on this system, use opcontrol --kernel-range=start,end or opcontrol --xen-range= or install objdump
由于在分析内核时使用到objdump,复制binutils-2.21.1/binutils/objdump 至文件系统的/bin文件下。(objdump在符号分析时用到)