Chinaunix首页 | 论坛 | 博客
  • 博客访问: 3881780
  • 博文数量: 146
  • 博客积分: 3918
  • 博客等级: 少校
  • 技术积分: 8585
  • 用 户 组: 普通用户
  • 注册时间: 2010-10-17 13:52
个人简介

个人微薄: weibo.com/manuscola

文章分类

全部博文(146)

文章存档

2016年(3)

2015年(2)

2014年(5)

2013年(42)

2012年(31)

2011年(58)

2010年(5)

分类: LINUX

2013-10-16 21:25:25

     最近我在重装了我的笔记本,OS用的是Ubuntu12.04.3,内核版本是:
  1. root@manu-hacks:~/software/systemtap# uname -r
    3.8.0-29-generic
    熟悉我博客的人知道,去年写过一博客,就叫systemtap在Ubuntu的安装,当时我用的是Ubuntu 12.04,内核还是3.2.0-29的内核。为啥我又冒出来一篇博客。
   我安装的最新版本是3.8.0.29,但是发现按照老的方法不行了。执行:
  1. 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掉了。 
  1. if (!strcmp(m->name, "kernel")) {
  2. /* notes_addr = m->build_id_offset; REPLACE THIS LINE BY THE NEXT ONE */
  3.    notes_addr = _stp_module_relocate("kernel", "_stext", m->build_id_offset);
  4.    base_addr = _stp_module_relocate("kernel", "_stext", 0);
  5. } else {
    我们看下当前的源代码:
  1.           /* notes end address */
  2.           if (!strcmp(m->name, "kernel")) {
  3.               notes_addr = _stp_kmodule_relocate("kernel",
  4.                   "_stext", m->build_id_offset);
  5.               base_addr = _stp_kmodule_relocate("kernel",
  6.                   "_stext", 0);
     接下来搜到了这篇文章:SystemTap初体验,这片文章把打印出Build-id dismatch那部分的检查代码给修改了,跳过了检查build-id。
     代码还是在runtime/sym.c下,把theory!= practice这个条件注释掉。
  1. if (rc /*|| (theory != practice*)*/) {
  2. #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
  3.       _stp_error ("Build-id mismatch [man error::buildid]: \"%s\" byte %d (0x%02x vs 0x%02x) address %#lx rc %d\n",
  4.          m->path, j, theory, practice, notes_addr, rc);
  5.       return 1
    表面上看,结果是对的,但是执行真正的内核探察,就会发现会报错。因为systemtap报错是有原因的。他表明了内核符号表和运行的内核不匹配,你跳过检查,不过是掩耳盗铃的勾当。

    一线曙光
   
我痛苦我彷徨我纠结的时候,我看到了这个帖子:,下面有个回复提供了,这个脚本执行的结果我指明了方向。为了不让这个给了我巨大帮助的脚本湮没在历史的长河之中,为了表示我对作者的无限感激,我把它全文copy下来: 
  1. #!/bin/bash

  2. distro="$(lsb_release --id --short)"
  3. if [ "$distro" != "Debian" -a "$distro" != "Ubuntu" ]; then
  4.     echo Unsupported distro $distro
  5.     exit 1
  6. fi

  7. # 2.6.32-5-amd64
  8. # 2.6.32-37-generic
  9. abiname="$(cut -d " " -f 3 /proc/version)"

  10. # 2.6.32
  11. baseversion="$(echo "$abiname" | cut -d "-" -f 1)"

  12. case "$distro" in
  13. Debian) # 2.6.32-39
  14.     if uname -v | grep -q Debian; then
  15.      version=$(uname -v | cut -d " " -f 4)
  16.     else
  17.      version="$(cut -d " " -f 5 /proc/version | cut -d ")" -f 1)"
  18.     fi
  19.     ;;
  20. Ubuntu)
  21.     # 2.6.32-37.81
  22.     version="$(cut -d " " -f 2 /proc/version_signature | cut -d "-" -f 1-2)"
  23.     ;;
  24. esac


  25. (
  26. echo make >= 0
  27. echo linux-image-$abiname = $version
  28. echo linux-headers-$abiname = $version
  29. echo linux-kbuild-$baseversion >= $version
  30. case "$distro" in
  31. Debian) echo linux-image-$abiname-dbg = $version
  32.     ;;
  33. Ubuntu) echo linux-image-$abiname-dbgsym = $version
  34.     ;;
  35. esac
  36. ) | while read package relation requiredversion; do
  37.     installedversion="$(dpkg-query -W "$package" 2> /dev/null | cut -f 2)"
  38.     if [ "$installedversion" = "" ]; then
  39.     availableversion="$(apt-cache show $package 2> /dev/null | grep ^Version: | cut -d " " -f 2)"
  40.     if [ "$availableversion" = "" ]; then
  41.      echo "You need package $package but it does not seem to be available"
  42.      if [ "$distro" = "Ubuntu" -a "$(echo $package | grep dbgsym$)" ]; then
  43.         echo " Ubuntu -dbgsym packages are typically in a separate repository"
  44.         echo " Follow to add this repository"
  45.      elif [ "$distro" = "Debian" -a "$(echo $package | grep dbg$)" ]; then
  46.         echo " Debian does not have -dbg packages for all kernels. Consider switching to a kernel that has one."
  47.      fi
  48.     else
  49.      echo "Please install $package"
  50.     fi
  51.     elif ! dpkg --compare-versions $installedversion $relation $requiredversion; then
  52.     echo "Package $package version $installedversion does not match version of currently running kernel: $requiredversion"
  53.     echo " Consider apt-get upgrade && reboot"
  54.     fi
  55. done

  56. user="$(id --user --name)"
  57. if [ "$user" != "root" ]; then
  58.     groups="$(id --groups --name)"
  59.     for i in stapusr stapdev; do
  60.     if [ "$(echo $groups | grep $i)" = "" ]; then
  61.      echo "Be root or adduser $user $i"
  62.     fi
  63.     done
  64. fi
    执行结果如下:
  1. 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
    记忆力好的筒子可能会记得,我前面提到,我的内核版本是:
  1. root@manu-hacks:~/software/systemtap# uname -r
  2. 3.8.0-29-generic
    尼玛,我的内核版本明明是3.8.0-29.42~precise1,可是uname -r告诉我的是
3.8.0-29-generic,而我上篇博客提到的get-dbg,错误的下载了debuginfo。

 

   正确的方法 
    1 寻找到正确的内核版本,执行这个,看到我们的版本信息是
  1. root@manu-hacks:~/software/systemtap# cat /proc/version_signature
  2. Ubuntu 3.8.0-29.42~precise1-generic 3.8.13.5
    2
路径下找到你的debug info。下载之
  1. 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 安装之    
  1. 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),或者自行搜索 
How do I build a debuginfo kernel if one isn't available?
  1.     $ cd $HOME
  2.     $ sudo apt-get install dpkg-dev debhelper gawk
  3.     $ mkdir tmp
  4.     $ cd tmp
  5.     $ sudo apt-get build-dep --no-install-recommends linux-image-$(uname -r)
  6.     $ apt-get source linux-image-$(uname -r)
  7.     $ cd linux-2.6.31 (this is currently the kernel version of 9.10)
  8.     $ fakeroot debian/rules clean
  9.     $ AUTOBUILD=1 fakeroot debian/rules binary-generic skipdbg=false
  10.     $ sudo dpkg -i ../linux-image-debug-2.6.31-19-generic_2.6.31-19.56_amd64.ddeb
    最后,我不是文艺青年,我只是一个想顺顺利利装上systemtap的苦逼青年。泪流满面啊。

阅读(8783) | 评论(2) | 转发(1) |
给主人留下些什么吧!~~

snail_3142013-11-10 18:03:12

HI, guy, are you kernel hacker working in Nanjing? For which kind of tech. company are you servicing for?