在 Fedora 9 下面配置 ISATAP IPV6 tunnel

Fedora 9 终于换成了 2.6.25 kernel,2.6.25 支持 ISATAP 方式的 ipv6 tunnel 接入。于是把自己的机器简单配置了一下支持 IPV6

1: 保证 kernel 支持 ipv6
2: 编辑 /etc/sysconfig/network ,增加下面这行

IPV6_DEFAULTGW=your ipv6 gateway

3: 编辑 /etc/sysconfig/network-scripts/ifcfg-sit1, 内容如下

DEVICE=sit1
ONBOOT=yes
IPV6INIT=yes
IPV6TUNNELIPV4=your isatap tunnel IP
IPV6TUNNELIPV4LOCAL=your local ipv4 ip
IPV6ADDR=your ipv6 address

4: ifup sit1

UPDATE: 我还没有试验过这个在 F9 上重启是否有效,但在 centos 5.1 上面不好用,似乎 ifup-sit 不会创建对应的 sit1 设备,先得手动创建以后才有效。

Fedora 9 升级达成!

虽然网上说可能会有风险,因为 F9 用 upstart 替换掉了 Sysinitv 启动,多年的启动习惯终于被改变了。不过看起来我的运气还成,直接 yum 成功了。

[root@comman ~]# uptime
01:05:37 up 9 min, 1 user, load average: 0.10, 0.15, 0.10
[root@comman ~]# cat /etc/redhat-release
Fedora release 9 (Sulphur)
[root@comman ~]# uname -a
Linux comman.org 2.6.25.3-18.fc9.i686 #1 SMP Tue May 13 05:38:53 EDT 2008 i686 i686 i386 GNU/Linux

明天有时间配一下期待已久的 ISATAP 接入,这样就有 IPV6 可用啦!

Admire 龙芯电脑

当机器是 512M 内存的时候,只能用 64bit kernel,否则只能用 256M 内存(这个还能理解)
当机器是 256M 内存的时候,只能用 32bit kernel,否则就会随机死机,是彻底死掉,不是 panic。

Reiserfs 看来真是要倒台了。

今天某站的 reiserfs 又不成了,列不出来目录,重启以后无法 mount。我在被窝里面被电话吵醒,然后起来 fsck.reiserfs。根据上次某人的经验,就用 fsck.reiserfs 做一次 –fix-fixable 就可以了。不过这个过程超过想象的漫长。

中间我准备上 reiserfs 的官方网站 www.namesys.com 上面看看,却发现域名已经无法解析,whois 结果如下

Registrant:
Namesys
Hans Reiser
6979 Exeter Dr
Oakland, CA 94611
US
Email: reiser@namesys.com

Registrar Name….: REGISTER.COM, INC.
Registrar Whois…: whois.register.com
Registrar Homepage: www.register.com

Domain Name: namesys.com

Created on…………..: Fri, Mar 24, 2000
Expires on…………..: Tue, Mar 24, 2009
Record last updated on..: Tue, Mar 06, 2007

看起来好像还没过期,不过也很有可能是注册商给多续了一年保护,以敲诈更多银两。 反正不管怎么说, reiserfs 从 Hans Reiser 进局子以后,怎么看怎么都像不太成了的样子,现在连主页都能倒掉。可怜我们这些套牢在 reiserfs 上面的用户了。

无责任闲谈 – LD_PRELOAD 和模块内调用

无责任闲谈 – LD_PRELOAD 和模块内调用

这个问题的提出是因为某天伟大的布总问了我一个问题。

如果某个 .so 里面有两个函数, 一个 foo ,一个 bar, bar 调用了 foo ,那么 bar 调用 foo 的地方应该是直接生成对 foo 的调用呢?还是通过跳转表来实现呢?

我们讨论了一下,都觉得如果没有加 -fPIC 的话,这个怎么也不应该通过跳转表来实现。但是布总却发现,如果之前弄一个 inject.so 里面包含一个叫做 foo 的函数,然后通过 LD_PRELOAD 来预先加载,不管编译时候有没有加 -fPIC,调用 bar 的时候,调用的都是 inject.so 里面的 foo 函数。这就有点奇怪了,ld-linux.so 怎么会去修改原来 .so 中 foo 对 bar 的调用呢?

还是反汇编一下看看吧:

不带 -fPIC

00000498 :
498: 55 push %ebp
499: 89 e5 mov %esp,%ebp
49b: 5d pop %ebp
49c: c3 ret

0000049d :
49d: 55 push %ebp
49e: 89 e5 mov %esp,%ebp
4a0: e8 fc ff ff ff call 4a1
4a5: 5d pop %ebp

带 -fPIC
000004a8 :
4a8: 55 push %ebp
4a9: 89 e5 mov %esp,%ebp
4ab: 5d pop %ebp
4ac: c3 ret

000004ad :
4ad: 55 push %ebp
4ae: 89 e5 mov %esp,%ebp
4b0: 53 push %ebx
4b1: 83 ec 04 sub $0x4,%esp
4b4: e8 eb ff ff ff call 4a4 <__i686.get_pc_thunk.bx>
4b9: 81 c3 4b 11 00 00 add $0x114b,%ebx
4bf: e8 fc fe ff ff call 3c0 // PLT thunk
4c4: 83 c4 04 add $0x4,%esp
4c7: 5b pop %ebx
4c8: 5d pop %ebp

其中相关的 PLT 内容如下:

000003c0 :
3c0: ff a3 10 00 00 00 jmp *0x10(%ebx) // 指向跳转表项的指针
3c6: 68 08 00 00 00 push $0x8
3cb: e9 d0 ff ff ff jmp 3a0 <_init+0x18>

-fPIC 的情况很好理解,跳转都是通过 PLT 进行的,直接去修改跳转表中的数据即可。那么没有 -fPIC 的情况,loader 是怎么能够修改调用让他指向另外 .so 里面的函数呢?

从汇编里面可以看出来,没有 -fPIC 的情况下面,对 foo 的调用指向的也不是 foo ,而是一个没有意义的地址,观察 .so 的 reloc 信息可知,有一条 reloc 指向 bar 对 foo 调用的地方,内容是 “foo”

DYNAMIC RELOCATION RECORDS
OFFSET TYPE VALUE
000015fc R_386_RELATIVE *ABS*
00001600 R_386_RELATIVE *ABS*
000004a1 R_386_PC32 foo

因此在 LD_PRELOAD 的情况下面, loader 会查找 foo 的地址并填入 bar 对 foo 调用的地方。

这种按照名字 reloc 的方式在 Win32 下面似乎没有见到过。Win32 下面 reloc 只是用于修正 DLL 加载以后导致数据指针位置不对的问题,操作方法是简单的把位置上面的值减掉原基址加上新基址,相当于 R_386_RELATIVE 这种类型的 reloc。但是仔细想想,这种 reloc 其实并没有任何必要,RELATIVE 方式已经足够解决问题了,怀疑这个 PC32 的方式,就是单独为了支持 LD_PRELOAD 这一历史遗留产物而设计的。(我比较懒得查阅资料,谁查到了麻烦讲一下)

在 64 位下面,这个把戏不能用了,因为 64bit 下面函数调用一般还只是通过 E8 指令来调用 32 位范围内的地址,而 foo 函数的位置可能离 bar 调用它的地方超过了 2G,因此 ld 遇到这样的 reloc 会报告失败,要求你必须用 -fPIC 来编译。

有人可能会问, -fPIC 了不是会影响性能?这个确实没办法了,在很久以前大家没有意识到需要 module local symbol ,觉得除了 static 的所有函数都全局可见就好了,结果这个习惯就一直继承下来了,虽然现在 ELF 格式中确实支持 module local 的 symbol。但是因为历史上就是这么下来的,为了维持兼容性,只好继续保持这一行为。很多函数并没有跨模块调用的需要,只是因为有跨文件调用就不得不变成非 static 的,在上面说的这种情况下就会受到影响。

一个很土鳖的解决方法就是把所有函数都堆进一个 .c ,然后除了真正需要导出的函数,都改成 static 的。也许 gcc 现在支持什么扩展,可以将符号声明成 module local 的,不过我也是懒得查资料了,有人知道的话,请不吝赐教。 //bow

最近评论

时光机

其他