异想天开

What's the true meaning of light, Could you tell me why

获得libc的调试信息

日期:2014-07-01 11:04:57
  
最后更新日期:2014-11-25 11:20:32
【技术文章,非码农勿入】
需求:
获得libc的调试信息(研究学习libc内存分配需要)
环境:
[code lang="cpp"]
[root@localhost glibc-2.12.2]# uname -a
Linux localhost.localdomain 2.6.32-431.1.2.0.1.el6.x86_64 #1 SMP Fri Dec 13 13:06:13 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux
[/code]
尝试:
方案一.gdb里面调试到malloc这些函数时,会提示“Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.132.el6.x86_64”。
a.yum搜索debuginfo-install包。 [code lang="cpp"]
[root@localhost glibc_build]# yum search debuginfo-install
Loaded plugins: fastestmirror, refresh-packagekit
Loading mirror speeds from cached hostfile
* base: mirrors.163.com
* extras: mirrors.163.com
* updates: mirrors.163.com
===================================================== Matched: debuginfo-install ======================================================
yum-utils.noarch : Utilities based around the yum package manager
[/code]
b.安装上面搜索到的包:
[code lang="cpp"]
yum install yum-utils.noarch
[/code]
c.安装libc调试版本信息
[code lang="cpp"]
debuginfo-install glibc-2.1
[/code]
提示为"No debuginfo packages available to install"。
后记:
后来才知道,原来是yum配置debug的源默认没有开启(当时以为这样不行,就下载了源码编译,囧)。当前的centos开启方法为:
1.修改/etc/yum.repos.d/CentOS-Debuginfo.repo里面的debuginfo目录中enabled=1,gpgcheck=0。
2.然后再安装debuginfo-install glibc-2.12-1.132.el6.x86_64。glibc这是当前系统的glibc版本,这个命令为gdb里面提示信息,或者直接debuginfo-install glibc应该也可以的。

二.网上虽然有介绍glibc里面的内存分配,但是细节部分,和系统正在运行的软件版本还是会有出入的,因为版本变化,所有直接下载源码编译。
1.下载glibc源码
通过搜索gnu libc会进入gnu的libc首页,找到下载地址下载。

2.编译
懒一点的直接在网上搜索看人家怎么编译的,照搬过来即可,好学生则看解压后的libc目录的README和INSTALL这些文件。我是先看网上的博客,看下日期发现离得还近,然后又想装一下好学生。INSTALL文件里面告诉我们要把源码和编译目录分开,在解压目录的同级别创建一个编译目录gcc_build,然后用相对地址这样编译:
[code lang="cpp"]
$ ../glibc—2.4/configure ARGS...
[/code]
ARGS参数一般我会指定--prefix=/usr/local/glibc_2_4,这样删除这个目录,就很干净的卸载了。

3.使用新编译的glibc
glibc是封装系统的调用的底层c库,系统的基本程序和软件包都依赖它。所以不能直接用这个新的glibc来替换老的glibc,那样做可能会导致系统不能正常启动了。而现在的需求是希望单独测试这个编译的libc库,可以有如下2种方法,可能还有其它方法。
方法1:指定LD_PRELOAD环境变量,该环境变量控制程序优先加载的新编译的库。
[code lang="cpp"]
export LD_PRELOAD=/home/bianzhuang/data/gcc_complie/glibc_build/libc.so.6
[/code]
编译时,还是按系统之前的glibc编译。新编译的glibc版本和之前的glibc版本是一致的。运行时,会用新的glibc来映射。ldd一下,发现glibc已经使用了新的glibc:
[code lang="cpp"]
[root@localhost data]# ldd ./autoout
linux-vdso.so.1 => (0x00007fff9fdff000)
/home/bianzhuang/data/gcc_complie/glibc_build/libc.so.6 (0x00007fbe730b1000)
libstdc++.so.6 => /usr/local/gcc_4_7_4/lib64/libstdc++.so.6 (0x00007fbe72da9000)
libgcc_s.so.1 => /usr/local/gcc_4_7_4/lib64/libgcc_s.so.1 (0x00007fbe72b93000)
/lib64/ld-linux-x86-64.so.2 (0x00007fbe7341b000)
libm.so.6 => /lib64/libm.so.6 (0x00007fbe728ff000)
[/code]
这样可以在gdb下进入malloc函数。
方法2:指定gcc的specs。
gcc是一个编译套件,gcc会根据其配置文件specs和用户指定的参数,调用内部编译过程。这个过程可以用:
[code lang="cpp"]
gcc -v -Wall -lstdc++ foo.cpp -o foo
[/code]
来查看gcc具体怎么编译的。
1.首先导出当前默认的specs。
[code lang="cpp"]
[root@localhost data]# gcc -dumpspecs > gcc_specs.txt
[/code]
2.更改gcc的链接器
注:自己编译glibc,前面指定了prefix,make install会安装到指定的prefix目录,这个时候glibc不会起作用的,因为还没有配置它,所以不会对系统造成影响。
简单一点,就是直接将/lib64/ld-linux-x86-64.so.2,替换为编译的glibc的链接器。我就只更改了:
[code lang="cpp"]
*link:
%{!static:--eh-frame-hdr} %{!r:--build-id} %{!m32:-m elf_x86_64} %{m32:-m elf_i386} --hash-style=gnu %{shared:-shared}
%{!shared: %{!static: %{rdynamic:-export-dynamic}
%{m32:%{!dynamic-linker:-dynamic-linker %{muclibc:%{mglibc:%e-mglibc and -muclibc used together}/lib/ld-uClibc.so.0;:/usr/local/glib_2_12/lib/ld-linux-x86-64.so.2}}}
%{!m32:%{!dynamic-linker:-dynamic-linker
%{muclibc:%{mglibc:%e-mglibc and -muclibc used together}/lib/ld64-uClibc.so.0;:/usr/local/glib_2_12/lib/ld-linux-x86-64.so.2}}}} %{static:-static}}
[/code]
编译:
[code lang="cpp"]
gcc -g -Wall -Werror -lstdc++ -specs ./gcc_specs.txt auto.cpp -o autoout
[/code]
gdb后就可以进入了,glibc的函数了。当然,这些操作并不能一定保证在另外一个系统同样适用,可以再参考lfs的方法或cross complie。
额外知识:
1.linux libc与glibc关系。linux libc和glibc都是stard library c的实现,早期linux自己实现了一套libc,从gnu libc 1.x版本fork出来的,后来linux libc版本到libc 6的时候,就直接用了gnu libc。
[code lang="cpp"]
Linux libc
In the early to mid 1990s, there was for a while Linux libc, a fork of glibc 1.x created by Linux developers who
felt that glibc development at the time was not sufficing for the needs of Linux. Often, this library was
referred to (ambiguously) as just "libc". Linux libc released major versions 2, 3, 4, and 5 (as well as many
minor versions of those releases)
[/code]