SystemTap在Ubuntu 12.04上的安装 Build-id mismatch

本文发布时间: 2019-Mar-22
最近我在重装了我的笔记本,OS用的是Ubuntu12.04.3,内核版本是:root@manu-hacks:~/software/systemtap# uname -r3.8.0-29-generic 熟悉我博客的人知道,去年写过一博客,就叫systemtap在Ubuntu的安装,当时我用的是Ubuntu 12.04,内核还是3.2.0-29的内核。为啥我又冒出来一篇博客。 我安装的最新版本是3.8.0.29,但是发现按照老的方法不行了。执行:stap -e 'probe kernel.function("sys_open") {log("hello world") exit()}' 结果报错,报错信息是ERROR:Build-id mismatch 云云。 不愿意听我罗嗦的,直接跳转到正确的方法 错误的尝试 我最初以为是因为systemtap版本太低,然后源代码装了systemtap 2.0/2.1/2.3的版本,结果还是不行。后来我怀疑是不是因为我kernel升过级,重新安装还是不行。在后来,我看到了Brenden's blog中有一文章叫Using SystemTap提到了这个问题,给出了Solution,无奈他的方法是老黄历了,不能解决问题,这个bug,SystemTap早就修过了. 他的解决方法是:在runtime/sym.c中将注释行替换成下面的一行,事实上,这个bug ,systemtap早就已经fix掉了。if (!strcmp(m->name, "kernel")) {/* notes_addr = m->build_id_offset; REPLACE THIS LINE BY THE NEXT ONE */ notes_addr = _stp_module_relocate("kernel", "_stext", m->build_id_offset); base_addr = _stp_module_relocate("kernel", "_stext", 0);} else { 我们看下当前的源代码: /* notes end address */ if (!strcmp(m->name, "kernel")) { notes_addr = _stp_kmodule_relocate("kernel", "_stext", m->build_id_offset); base_addr = _stp_kmodule_relocate("kernel", "_stext", 0); 接下来搜到了这篇文章:SystemTap初体验,这片文章把打印出Build-id dismatch那部分的检查代码给修改了,跳过了检查build-id。 代码还是在runtime/sym.c下,把theory!= practice这个条件注释掉。if (rc /*|| (theory != practice*)*/) {#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) _stp_error ("Build-id mismatch [man error::buildid]: \"%s\" byte %d (0x%02x vs 0x%02x) address %#lx rc %d\n", m->path, j, theory, practice, notes_addr, rc); return 1 表面上看,结果是对的,但是执行真正的内核探察,就会发现会报错。因为systemtap报错是有原因的。他表明了内核符号表和运行的内核不匹配,你跳过检查,不过是掩耳盗铃的勾当。 一线曙光 我痛苦我彷徨我纠结的时候,我看到了这个帖子:systemtap reports error 'Build-id mismatch',下面有个回复提供了脚本,这个脚本执行的结果我指明了方向。为了不让这个给了我巨大帮助的脚本湮没在历史的长河之中,为了表示我对作者的无限感激,我把它全文copy下来:#!/bin/bashdistro="$(lsb_release --id --short)"if [ "$distro" != "Debian" -a "$distro" != "Ubuntu" ]; then echo Unsupported distro $distro exit 1fi# 2.6.32-5-amd64# 2.6.32-37-genericabiname="$(cut -d " " -f 3 /proc/version)"# 2.6.32baseversion="$(echo "$abiname" | cut -d "-" -f 1)"case "$distro" in Debian) # 2.6.32-39 if uname -v | grep -q Debian; then version=$(uname -v | cut -d " " -f 4) else version="$(cut -d " " -f 5 /proc/version | cut -d ")" -f 1)" fi ;;Ubuntu) # 2.6.32-37.81 version="$(cut -d " " -f 2 /proc/version_signature | cut -d "-" -f 1-2)" ;;esac(echo make >= 0echo linux-image-$abiname = $versionecho linux-headers-$abiname = $versionecho linux-kbuild-$baseversion >= $versioncase "$distro" inDebian) echo linux-image-$abiname-dbg = $version ;;Ubuntu) echo linux-image-$abiname-dbgsym = $version ;;esac) | while read package relation requiredversion; do installedversion="$(dpkg-query -W "$package" 2> /dev/null | cut -f 2)" if [ "$installedversion" = "" ]; then availableversion="$(apt-cache show $package 2> /dev/null | grep ^Version: | cut -d " " -f 2)" if [ "$availableversion" = "" ]; then echo "You need package $package but it does not seem to be available" if [ "$distro" = "Ubuntu" -a "$(echo $package | grep dbgsym$)" ]; then echo " Ubuntu -dbgsym packages are typically in a separate repository" echo " Follow https://wiki.edubuntu.org/DebuggingProgramCrash to add this repository" elif [ "$distro" = "Debian" -a "$(echo $package | grep dbg$)" ]; then echo " Debian does not have -dbg packages for all kernels. Consider switching to a kernel that has one." fi else echo "Please install $package" fi elif ! dpkg --compare-versions $installedversion $relation $requiredversion; then echo "Package $package version $installedversion does not match version of currently running kernel: $requiredversion" echo " Consider apt-get upgrade && reboot" fidoneuser="$(id --user --name)"if [ "$user" != "root" ]; then groups="$(id --groups --name)" for i in stapusr stapdev; do if [ "$(echo $groups | grep $i)" = "" ]; then echo "Be root or adduser $user $i" fi donefi 执行结果如下:Package linux-image-3.8.0-29-generic-dbgsym version 3.8.0-29.42 does not match version of currently running kernel: 3.8.0-29.42~precise1 记忆力好的筒子可能会记得,我前面提到,我的内核版本是:root@manu-hacks:~/software/systemtap# uname -r3.8.0-29-generic 尼玛,我的内核版本明明是3.8.0-29.42~precise1,可是uname -r告诉我的是3.8.0-29-generic,而我上篇博客提到的get-dbg,错误的下载了debuginfo。 正确的方法 1 寻找到正确的内核版本,执行这个,看到我们的版本信息是root@manu-hacks:~/software/systemtap# cat /proc/version_signature Ubuntu 3.8.0-29.42~precise1-generic 3.8.13.5 2去http://ddebs.ubuntu.com/pool/main/l/linux-lts-raring/路径下找到你的debug info。下载之wget http://ddebs.ubuntu.com/pool/main/l/linux-lts-raring/linux-image-3.8.0-29-generic-dbgsym_3.8.0-29.42~precise1_i386.ddeb 3 安装之dpkg -i linux-image-3.8.0-29-generic-dbgsym_3.8.0-29.42~precise1_i386.ddeb 如果你和我一样苦逼,装错了,请先执行dpkg -r 错误的版本。 如果你记不清楚错误的名字,请执行dpkg --list |grep linux-image. 如果你不是普通青年,你是文艺青年,你也可以自己下载source code,自己编出内核符号表。参考下面的步骤,来源在:Linux系统分析工具续-SystemTap和火焰图(Flame Graph) $ cd $HOME $ sudo apt-get install dpkg-dev debhelper gawk $ mkdir tmp $ cd tmp $ sudo apt-get build-dep --no-install-recommends linux-image-$(uname -r) $ apt-get source linux-image-$(uname -r) $ cd linux-2.6.31 (this is currently the kernel version of 9.10) $ fakeroot debian/rules clean $ AUTOBUILD=1 fakeroot debian/rules binary-generic skipdbg=false $ sudo dpkg -i ../linux-image-debug-2.6.31-19-generic_2.6.31-19.56_amd64.ddeb 最后,我不是文艺青年,我只是一个想顺顺利利装上systemtap的苦逼青年。泪流满面啊。


(以上内容不代表本站观点。)
---------------------------------
本网站以及域名有仲裁协议。
本網站以及域名有仲裁協議。

2024-Mar-04 02:10pm
栏目列表