这张图真的还是假的?
今天王冬同学发给我的。哪位如果用搜狗输入法能否帮忙确认一下真假?怎么看也不像PS的啊!(真要是话的说明那人PS水平不低~!)不知道是哪位高人做的?或者是西邮在搜狐有卧底?
今天王冬同学发给我的。哪位如果用搜狗输入法能否帮忙确认一下真假?怎么看也不像PS的啊!(真要是话的说明那人PS水平不低~!)不知道是哪位高人做的?或者是西邮在搜狐有卧底?
如果编译一个relocatable目标文件,你通过反汇编不难发现所有的call指令竟然都是同一个机器码!即:e8 fc ff ff ff。
我们知道,不同的函数有不同的入口,可这里怎么都会用这么一个奇怪的地址呢?
翻一下Intel指令手册,我们很容易就能在3-104 Vol. 2A中找到call指令的各种编码方式。根据这里的opcode为e8我们不难确定这个call是用的下面这种方式:
E8 cd CALL rel32
tempEIP ←EIP +DEST; ( DEST is rel32 )
IF tempEIP is not within code segment limit THEN #GP(0); FI;
IF stack not large enough for a 4-byte return address
THEN #SS(0); FI;
Push(EIP);
EIP ←tempEIP;
我们知道,relocatable目标文件的符号地址都是不能使用的,因为还没经过linker转化。linker转化后的地址才是最终的地址,也就是说从上面那个地址到最后的地址还有一段过程,由ld来完成。
我们知道,这里正确的地址应该是该符号实际的地址与这个call地址之间的偏移。而这等于这个函数的实际入口与.text section之间的偏移减去这个符号相对.text的偏移!后者由ELF格式直接给出,而前者也很容易计算。
到这里你会发现,不对,我们那个fc ff ff ff还没用上!是,因为我们前面忽视了很重要的一点,EIP是指向下一条指令的而不是当前这条的地址!也就是说,我们前面的结果需要修正!具体说是需要修正一个 -0x4。再看一下fc ff ff ff,不正是-4么?!(x86是little endian!)对,正是这个由assembler故意安排的-4修正了我们call指令!
当然了,如果符号不是一个函数地址,而是一个全局变量的地址,这就不需要修正,相应的relocatable文件里就是0。
不得不说这是一个很聪明的hack!
还有,如果你看最后executable文件,你可能又困惑了,call后面的修正似乎和上面不一样。举个例子:
80483ba: e8 18 00 00 00 call 80483d7 <foo>
就是那个e8啊!
内核中printk发出的消息是这样传递到用户空间的。
内核留给用户空间的接口是syslog(2),glibc对它进行了包装,于是就有了klogctl(3)和syslog(3)。
先由klogd通过klogctl(3)搜集内核消息(见sysklogd/klogd.c),并通过自己实现的syslog()(注意:和syslog(2),syslog(3)都不一样)传递给 syslogd。syslogd根据/etc/syslog.conf的配置情况进行记录。syslogd提供的是一个统一的方式,它不单单记录内核的消息,还包括其它服务器进程的消息,比如Apache,vsftp。
klogd和syslogd用的syslog()的实现用的是Unix domain socket,如果你看源代码(sysklogd/syslog.c)的话很容易就知道这一点。所以,所谓的syslog()/openlog()/closelog()等接口无非就是对这个socket操作的一个包装。这也就清楚了klogd和syslogd之间的通信方式。
根据syslogd的源代码(sysklogd/syslogd.c)来看,记录日志也可以是发送到远程的,而那个socket就是用的inet socket了。
多说一句,其实内核给出的oops只是一堆地址,而把地址和相应的符号对应起来也是由klogd完成的。sysklogd/ksym.c里有搜索System.map的过程,搜索的顺序是:
“/boot/System.map”
“/System.map”
“/usr/src/linux/System.map”
这就是最好的证据。一些细心的人或许还会奇怪,我们不是还有/proc/kallsyms么?怎么不用它?我知道的解释是:为了照顾那些没有/proc文件系统的Linux系统。;-)
我们再来看syslog(3),即glibc实现的syslog()。看一下glibc中的源代码,我们就会发现glibc中的syslog和sysklogd自己的实现类似,也是用unix domain socket来实现的。具体可以看:glibc/misc/syslog.c。
这两种实现之所以都能够传递给syslogd,是因为它们的unix domain socket都是用的/dev/log这个文件。
而我们最常用的查看内核消息的命令dmesg(1)和上面两位守候进程没太大关系,它是直接通过glibc的klogctl(3)函数来读取内核消息的。详细见:util-linux-2.13-pre7/sys-utils/dmesg.c。
如果想了解更多关于syslogd的东西,可以参考这篇文章。
想了解内核的中对syslog(2)的实现,可以参考内核源代码:kernel/printk.c。
正如董溥同学给我留的言,coolcode插件不支持C语言,这是事实。而且用coolcode插件往wordpress里贴代码也是不很爽~!
于是乎,我就hack了一个脚本,调用vim来生成html,然后往博客里贴时复制里面的html代码就是了。恩,我知道emacs有个htmlize插件,可惜它生成的html是CSS的,貌似wordpress不支持直接贴那玩意(未经验证)。我用它更新了一下前面一篇文章中的代码,效果还不错,代码如下:
#!/bin/bash #Copyright(C) 2008, WANG Cong #GPLv3 applies. if (($# != 1)) ; thenecho "Bad usage!"
exit 1
fi if [ ! -f $1 ] ; thenecho "$1: No such file!"
exit 2
fivim -n -c ‘:so $VIMRUNTIME/syntax/2html.vim‘ -c ":w $1.html"
-c ":qa" $1 > /dev/null 2> /dev/null
exit 0有句话说得好:“生,容易。活,容易。生活,不容易!”
生活很多时候都会是很平淡的,时间长了就会觉得无趣。这时候别着急,你得学着折腾,没事折腾点事来做。这样的生活才会精彩! 折腾够了这个,歇歇再折腾那个。让生活不再那么无聊!
有时候,生活也会不那么顺心,别着急,把它当成生活给你提供的“折腾”,这样省得你再自己折腾!折腾过去了再回头看看,生活不还是得继续么?还是得重回无趣?
然后就接着折腾……
生命不息,折腾不止!
“这些墙很有趣。刚入狱的时候,你痛恨周围的高墙;慢慢地,你习惯了生活在其中;最终你会发现自己不得不依靠它而生存。这就叫体制化。 ”——《肖申克的救赎》
我发现,墙忒有才了!
首先,墙懂得正则表达式!它对”^wiki“域名的网站一概过滤,而”wiki$”却没事。
其次,墙知道今天是愚人节!为了幽大家一默,今天破例可以访问blogspot和en.wikipedia.org!
如果第2条猜测不成立,即明天仍可以访问,那就说明墙懂得支持闹运会。8月24之后应该就会关闭!
如果最后一点仍不成立,那说明你在做梦!
哎,墙啊,你这玩笑开得太突然了!突然没了你俺受不了啊!俺这心挖凉挖凉的!
(今天距离北京闹运会结束还有145天。。。)
我发现,一本正经的扯淡也是一种本事。老外们对干这种事乐不知疲啊~!
先是RFC中的扯淡,凡是April 1发布的RFC基本上都是(全都是?)joke性质的。从1989年到2007年,只有2006年没有,其它几年还有一次发布好几个的~! 这里有一个搜集,列出了每年4月1号的RFC,非常有意思。当然了,里面最出名的一个恐怕是IPv9的那个了,更joking的是居然有人把此当正事去做!(不许联想!!否则后果自负!)
当然啦,带有joke性质的RFC不光是这一天有,有几年在其它日期也出现了。更搞笑的是,连大名鼎鼎的Cerf(Dr. Chen 的偶像) 也来joke了一把。有兴趣的同学穿墙去看微机百科好了~!如果你NB到可以提交RFC,看看这个。俺期待着某年的今天看到你写的RFC!
今天lkml上也joke了一把,一本正经地说kernel.org要停机,原因是要从Fedora Core 5升级到FreeBSD!真逗~~!俺也回复了一把,说根据RFC 1606,Linux kernel应该考虑汇入net/ipv9这个分支吧~! ;-)
Update:谷歌今天也不甘寂寞,joke了一把。
Happy Joking!