implicit declaration又出来害人了

说把vps迁移到64位系统后,collectd不记数据了,rrdupdate直接crash…… 调试发现是implicit declaration干的好事情…… rrdupdate.c用到了basename(),但是没有引用libgen.h,于是basename()是隐式声明的。 根据古老的c的规定,隐式声明的函数返回值被当作了int,而64位系统上int是32位的。 所以本来好好的char*的返回值就被当作了int,返回值的高32位被干掉了,指针直接就飞了…… 其实是有编译警告的,但是who cares…… 所以c代码都该直接当c++编译,好的c代码应该可以直接编译…… 不声明就用算是什么feature,简直是个bug…… 另外其实上游已经修了这个bug: https://github.com/oetiker/rrdtool-1.x/commit/d0bd4217d9fb69db9f94363087936cf93fa9b4ea,不过修完之后没有发新release,于是下游也没人管,毕竟谁喜欢用git tag打包……

用Python Descriptor弱智了一把

Python Descriptor是个有意思的功能,类似于c++里面的重载operator=和operator T,可以在你访问这个对象的时候,调你定义的__get__(),把返回值作为访问结果,在你给对象赋值的时候,调你的__set__()。 昨晚大约是在搞这么一个类: class Field(object): def __get__(self, obj, objtype): …. def __set__(self, obj, val): ….   class Data: x = Field()   d = Data()class Field(object): def __get__(self, obj, objtype): …. def __set__(self, obj, val): …. class Data: x = Field() d = Data() 然后在访问d.x的时候,没啥问题,__get__被调用了;但是给d.x赋值的时候,__set__没被调用,只是貌似给d搞上了一个域叫x,之后再访问d.x也不会调__get__了…… 在折腾了若干时间之后,最后发现问题特别弱智:Data不是new-style class。只要改成Data(object)就好了……   虽然是我弱智吧,这个语言方面也有问题吧…… 既然old-style class不支持Descriptor,为啥__get__能用__set__却不行…… 而且也没个警告之类……

DTrace

这两天搞了一把DTrace,貌似还挺有意思的。 DTrace是个动态跟踪工具,可以在动态环境下向内核/程序中插入探头(probe),收集处理以及显示一些信息。 其实本来搞DTrace是为了一个FreeBSD的bug。搞chromecast的时候发现,IP multicast的目标mac不对。不过后来分析代码大致定位到了出问题的文件,然后在最新代码里发现这个bug已经修了(PR 185395),于是纯粹就是学习DTrace了。 一开始在我的机子上DTrace还跑不起来,后来发现是因为我跑的UEFI分支里的内核路径有些特别,于是DTrace找不到符号。打了个补丁(dt_kernel_path.patch)之后,dtrace终于能用了。 DTrace脚本的主体是一堆事件处理函数。跑DTrace脚本的时候,系统碰到某个符合的事件,就调用对应的函数。这些函数用D语言(不是那个D语言,是DTrace自己的一种语言)写成,语法和C差不多。基本的赋值/比较都能干,不过没有循环,也没有if/then/else。能控制流程的,基本上就是每个事件自带的条件,和三元操作符,也就是?:。 虽然前面那个bug是修了,我还是搞了个简单脚本来试DTrace。我希望观察arpresolve函数的参数和返回结果,也就是那个返回IP对应mac地址的函数。 arpresolve的原型是 int arpresolve(struct ifnet *ifp, struct rtentry *rt0, struct mbuf *m, const struct sockaddr *dst, u_char *desten, struct llentry **lle)int arpresolve(struct ifnet *ifp, struct rtentry *rt0, struct mbuf *m, const struct sockaddr *dst, u_char *desten, struct llentry **lle) 我希望查看dst里的ip地址,和desten里返回的mac地址。 DTrace脚本如下: fbt::arpresolve:entry /execname == "ping" && arg4 != …

Continue reading ‘DTrace’ »

64位系统上的老程序

之前写的某小程序在新的64位系统上seg fault了…… gdb之后,发现是getenv()返回了一个很小的负数…… 但是getenv()返回类型是char*,应该或者返回地址或者返回NULL啊…… 编译的时候有个warning,说将int转化为了pointer…… 其实就是忘了#include 了…… 于是getenv()没有声明过,默认成了返回int 32位系统上无所谓,反正int和char*一样大。64位就不一样了,int只有32位。 于是,在没有声明的情况下,返回值只拿到了后32位…… 再赋给char*自然也不行。 所以c这个没有声明直接可以用的特性有什么好的,而且连个没声明的警告也没有(貌似新的gcc会给……),不如直接编译失败……

Xoom更新4.1.1

之前听说Android 4.1.1在Xoom上公开测试了,昨儿听说已经OTA了,于是去系统设置里检查更新,没有…… 去网上看,说可以清除Google Service Framework的数据再试。试了一次,果然刷出来一个更新,4.1.1的。Google这是故意的么…… 下完之后,更新,刚过百分之十几,就成了个倒了的Android的样子,上面还有个红色三角。 根据经验,反正是升级败了。重启,去/cache,发现recovery目录里有last_log。看最后说啥验证失败。 E: failed to verify whole-file signature E: signature verification failed Installation aborted 我一开始以为是更新包验证败了,但是弄到电脑上,能正常解开……(更新包就在/cache里,一个zip) 那估计和上次一样,因为这是个补丁包,所以要先验证源文件正确,才能打补丁,而某些文件可能被改过了,在Root或者别的时候。 这时候我想起来,上次见到过一个叫OTA RootKeeper的东西,可以在更新后保留Root,就去装了一个,打开之后,选保留Root以及暂时unroot。 然后重启到EOS Recovery,尝试装那个zip,果然有apply_patch_check失败的,首先是/system/bin/gzip。进去一看,貌似被改成了到busybox的链接…… 大约是哪个busybox安装器干的好事。从网上下了一个4.0.4的完整镜像,从里面扒出gzip换掉系统里那个符号链接,再试,这次换成了ip。重复操作,搞定了ping和toolbox之后,这次是boot分区校验和挂了…… 重启到fastboot,刷那个4.0.4镜像里的,再更新,还是不行…… 想想大概是4.0.4那个镜像的boot改过了,去下载的地方,发现是root过的镜像…… 搜了一圈,就是找不到没root过的4.0.4 boot分区。 网上的恢复办法都是刷回3.x然后一路更新上来,好像很麻烦…… 我想,可以弄来3.x的boot.img和之后所有的补丁,一路打上来,弄到一个4.0.4的boot.img,再刷进去…… 在xda的http://forum.xda-developers.com/showthread.php?t=1597609这个帖子里有个网站,里面有3.0.1的原始镜像和所有升级包。把镜像里的boot.img和升级包里的所有boot.img.p扒出来,然后就是咋打补丁的问题了。 我记得android里有applypatch,于是去android source里面找,果然有这个东西。尝试编译一份主机可用的,居然成功了,命令如下: 在applypatch目录里 gcc utils.c imgpatch.c bspatch.c freecache.c bsdiff.c main.c applypatch.c -o applypatch -I../../../system/core/include/ -I../ ../minelf/Retouch.c -lbz2 -lz ../../bootloader/legacy/libc/sha.c ../mtdutils/mtdutils.c 然后跑,发现命令格式挺简单,就是 applypatch …

Continue reading ‘Xoom更新4.1.1’ »