IRC聊天随笔

1.查看eh_frame的内容。

$ readelf -wF foo

2.gdb里查看段信息。

(gdb) info files

3.记录应用程序执行的PC值

qemu-i386 -d in_asm foo

有趣的代码——initfini.c

xmj@hellogcc

1、最近编译glibc库,在链接时遇到一个问题,现象如下:

crtn.S:20: multiple definition of `dummy'
crtn.S:37: multiple definition of `_init'
crtn.S:88: multiple definition of `_fini'
crti.S:58: undefined reference to `i_am_not_a_leaf'
crtn.S:110: undefined reference to `i_am_not_a_leaf'
crtn.S:111: undefined reference to `i_am_not_a_leaf'

搜了下,按照网上的提示把问题解决了。顺便看下initfini.c的代码,感觉挺有意思。

2、这个C文件(initfini.c),首先会被编译成s文件(initfini.s),然后再使用sed程序将其分割成两个S文件(crti.S和crtn.S),最后分别编译成crti.o和crtn.o。文件开头注释里介绍了crti.o和crtn.o的作用:

# This directory contains the C startup code (that which calls main).  This
# consists of the startfile, built from start.c and installed as crt0.o
# (traditionally) or crt1.o (for ELF).  In ELF we also install crti.o and
# crtn.o, special "initializer" and "finalizer" files used in the link
# to make the .init and .fini sections work right; both these files are
# built (in an arcane manner) from initfini.c.

Makefile里,有对应的sed程序:

# We only have one kind of startup code files.  Static binaries and
# shared libraries are build using the PIC version.
$(objpfx)crti.S: $(objpfx)initfini.s
       sed -n -e '1,/@HEADER_ENDS/p' \
              -e '/@_.*_PROLOG_BEGINS/,/@_.*_PROLOG_ENDS/p' \
              -e '/@TRAILER_BEGINS/,$$p' $< > $@
 
$(objpfx)crtn.S: $(objpfx)initfini.s
       sed -n -e '1,/@HEADER_ENDS/p' \
              -e '/@_.*_EPILOG_BEGINS/,/@_.*_EPILOG_ENDS/p' \
              -e '/@TRAILER_BEGINS/,$$p' $< > $@

对照着C代码和生成的汇编代码,就可以看出,它的实现方法是,用sed通过C代码中特定的注释来提取、分割汇编代码的。比如“@HEADER_ENDS”,在C文件中的代码如下:

/* The initial common code ends here. */
asm ("\n/*@HEADER_ENDS*/");

生成的汇编代码如下:

/*@HEADER_ENDS*/

3、显然,这些嵌入的注释,在生成的汇编代码里需要保持原有的顺序,这样才能保证sed可以正确的提取汇编代码。

问题就出在gcc恰恰把生成汇编代码中的注释顺序打乱了,导致sed没能正确提取汇编代码,生成了错误的crti.S和crtn.S。网上的解决方法是,关掉一个优化选项。将Makefile中的

CFLAGS-initfini.s = -g0 -fPIC -fno-inline-functions

改为

CFLAGS-initfini.s = -g0 -fPIC -fno-inline-functions -fno-unit-at-a-time

即可。

Statistics of GDB Commits

今天下午无意中想看看自己有了多少个commit,然后就用 git log 命令查看,发现速度不错。不知道怎么了,灵机一动,想想看看这些global maintainer有多少commit。就有了如下的pie chart。

我来解释一下这个图是怎么得到的。首先我

git log gdb/ | grep ^commit | wc -l 统计一共gdb有多少次commit。然后把每个global maintainer的名字输入到这样的命令
git log gdb/ –author=”NAME” | grep ^commit | wc -l

统计每个global maintainer的commit数量。然后把这些数据画出来,这个时候想起了google chart api,以前同事用过,觉得很fancy,我就自己copy了一个。

从这个图表里边,能看出很多有意思的事情,

    gdbadmin 有很多commit。这些commit大多来自 daily version bump up,其实没有任何实际意义的。
    来自other的部分占约1/4。这部分人可以认为是对gdb代码不是那么了解的人。
    commit最多的是Andrew Cagney。 此人很牛,以前是Redhat GDB的头,后来去做frysk,然后离开了RedHat。 他那个时候,GDB好像还没有现在的 SC 和 Global Maintainer 机制。就他一个,叫 Head Developer。所以,他的commit最多。
    commit 其次多的是 Mark K.,Daniel J.,Joel B. Michael S.。 Michael 已经去世了,Mark K. 很久很久没有commit了。 Daniel J. 貌似 08 年以后也没有什么commit了。 Joel B. 现在的 Release Manager,最近没有什么patch,最近的两个patch,我觉得也不怎么样。貌似是没有时间。
    现在活跃的global maintainer 都有 400到 800个commit,所以,这个能告诉我们什么呢? 就是我们把这句话反着读,就是,如果有了 400到 800个commit, 基本上就能当global maintainer。