强制程序使用int 0x80做系统调用

因为大多数情况下程序都是通过libc间接地发出系统调用的,所以只要编译一个只使用int 0x80的glibc库,然后在执行程序的时候用LD_LIBRARY_PATH或其他方法指定使用新编译的glibc库即可。 以glibc-2.9, Linux i386为例,在sysdeps/unix/sysv/linux/i386/syscall.S中可以看到 ENTRY (syscall) PUSHARGS_6 /* Save register contents. */ _DOARGS_6(44) /* Load arguments. */ movl 20(%esp), %eax /* Load syscall number into %eax. */ ENTER_KERNEL /* Do the system call. */ POPARGS_6 /* Restore register contents. */ cmpl $-4095, %eax /* Check %eax for error. */ jae SYSCALL_ERROR_LABEL /* Jump to error handler if error. */ 这里使用了ENTER_KERNEL这个宏做系统调用,接下来在sysdeps/unix/sysv/linux/i386/sysdep.h里可以找到这个宏的定义 /* The original calling convention for system calls on Linux/i386 is to use int $0x80. 阅读全文 →

Git 命令行自动补全

在Pro Git上看到的技巧,git的源代码包里的contrib/completion目录下有个git-completion.bash,把这个文件保存到~/.git-completion.bash,然后在.bashrc中加入一行 source ~/.git-completion.bash 这样就能在bash下用tab自动补全git命令、branch等内容了。另外Debian/Ubuntu里有个包就叫git-completion,这个包安装完成后会自动把这个补全脚本放到/etc/bash_completion.d/下,由bash-compleletion载入执行。 阅读全文 →

使用 grep 查找进程的技巧

使用grep在ps aux的输出结果中查找进程的时候经常会把grep进程本身也找出来,比如查找emacs进程: $ ps aux | grep emacs wyx 7090 0.0 0.0 3336 796 pts/2 S+ 04:49 0:00 grep emacs wyx 10128 0.1 4.9 66904 50388 pts/3 S+ Jan21 2:21 emacs 一个常见的防止grep进程出现的方法就是在后面再加一个grep -v grep: $ ps aux | grep emacs | grep -v grep wyx 10128 0.1 4.9 66904 50388 pts/3 S+ Jan21 2:21 emacs 今天在Santosa的博客上看到了另一个巧妙的做法,使用grep [e]macs来搜索emacs这个进程: $ ps aux | grep [e]macs wyx 10128 0.1 4.9 66904 50388 pts/3 S+ Jan21 2:21 emacs 为什么会有这样的效果,知道grep正则中[]的作用后想一想就能明白啦。很有意思的trick,虽然说它比| grep -v grep也未必方便多少,因为后者能通过alias简化输入。 阅读全文 →

Ubuntu 下编译 Linux-xen 的问题

在Ubuntu下编译Linux-xen时碰到arch/i386/kernel/head-xen.o无法找到的问题,而该目录下有head-xen.S这个文件,说明make之前的的工作并没有把这个.S文件编译成.o。而同样的代码,在ArchLinux和Fedora上svn checkout后编译没有任何问题。 最后发现问题在于Ubuntu默认会把/bin/sh指向/bin/dash,在scripts/Makefile.build里面加上一行SHELL=/bin/bash指定$(shell)使用bash即可。后来还搜了一下为什么Ubuntu使用dash而不是bash,其理由是dash的执行效率更高,但不可否认的是这个改动也导致了一些项目无法成功编译,虽然无法成功编译的原因可能是Makefile里使用了一些bash的特性而非POSIX shell所提供的那些。 另外在debug过程中在网上找到了一些debug Makefile的技巧: make -n 可以仅仅打印出将要被执行的命令,而不去实际执行 make -np 可以打印出更多的信息(使用的规则和变量),并执行每一条命令 remake也是个不错的选择:“remakeis a patched and modernized version of GNU make utility that adds improved error reporting, the ability to trace execution in a comprehensible way, and a debugger.” 在检查shell命令的时候,可以使用set -x使得所有shell命令在执行前都能被输出。 阅读全文 →

Chomp 游戏

把一堆石子排成n行m列,两人轮流从里面取出石子,条件是取出一个石子后所有在它右边和上面的石子也要被取走。谁取走最后一个石子就算输。以3*5的棋盘举例来说,先手取了(2,5),因此(3,5)也要被取走;后手取了(3,3),同时也要取走(3,4)。现在棋盘的状态如下(O代表这个位子的石子还没被取走,x代表已经被取走): 3 O O x x x 2 O O O O x 1 O O O O O 1 2 3 4 5 接下来先手又取了(2,1),于是第二排和第三排就一颗石子都不剩了 3 x x x x x 2 x x x x x 1 O O O O O 1 2 3 4 5 后手取(1,2) 3 x x x x x 2 x x x x x 1 O x x x x 1 2 3 4 5 接下来先手就只能取最后一个石子了,后手胜。 阅读全文 →

Emacs 中对不同项目指定不同的风格

我的Emacs配置里C语言默认的缩进风格是用4个空格,最近要修改Chromium的代码,而Google的C/C++风格统一为2个空格缩进,所以改代码的时候要把c-basic-offset设置为2。这样在不同项目间切换的时候很不方便。 在stackoverflow上发帖求助后发现了Emacs 23.1一个很好用的新功能,Per-Directory Local Variables,只需要在项目主目录下放一个.dir-locals.el文件,里面设置该项目特有的变量值,就能应用到整个项目了。 以我的Chromium为例,Google已经提供了一份C/C++风格的配置,只需要在~/chromius/src/.dir-locals.el里把google-c-style常量粘贴进去即可。另外我不知道为啥加上c-offsets-alist那段后Emacs缩进会变得很奇怪,所以我把它删了。附修改后的.dir-locals.el ((c++-mode . ((c-recognize-knr-p . nil) (c-enable-xemacs-performance-kludge-p . t) ; speed up indentation in XEmacs (c-basic-offset . 2) (indent-tabs-mode . nil) (c-comment-only-line-offset . 0) (c-hanging-braces-alist . ((defun-open after) (defun-close before after) (class-open after) (class-close before after) (namespace-open after) (inline-open after) (inline-close before after) (block-open after) (block-close . c-snug-do-while) (extern-lang-open after) (extern-lang-close after) (statement-case-open after) (substatement-open after))) (c-hanging-colons-alist . ((case-label) (label after) (access-label after) (member-init-intro before) (inher-intro))) (c-hanging-semi&comma-criteria . 阅读全文 →

NoteExpress and BibTex

最近写了篇survey,分享下用NoteExpress一些经验 bibtex 关键字设置: 工具->样式->选择当前输出样式,选择BibTex,然后就能在题录的字段中找到bibtex 关键字一项了 导出bibtex时选择ANSI编码,如果设置为UTF-8貌似编译latex时会给出类似You’re missing an entry type—line 1 of file xxx.bib的提示。 导出引用的网页:我的解决方法是在BibTex样式->题录->模版里新增一个网页模版,然后右键编辑区选择从模版通用复制,并在里面增加一条***Howpublished = {\url{链接}}, 这样就能使用howpublished字段导出网页链接了。不过好像这样网页地址不会换行,于是我最后还是用手动断行改了下.bib。 另外提下,把png/jpg转成eps,我用的是sam2p,aur上就有。 阅读全文 →

在 Git 中修改之前提交的内容

其实这个问题我以前在 Stackoverflow 上回答过别人(链接),不过现在自己反而忘了,还是贴在这下次查起来方便点 先用 git rebase bbc643cd^ --interactive 退回到要修改的commit的前一个点,这里 bbc643cd 就是要修改的 commit,执行后 git 会调用默认的编辑器显示该次 commit 到最新 commit 的所有记录,在这里我们把要修改的那一项的行首的 pick 改成 edit。 接下来运行 git commit --amend,使用默认编辑器修改这次 commit。 最后执行 git rebase --continue 就能提交修改后的 commit 并且返回到原来的 commit 了。 阅读全文 →

新装硬盘空间只有31B/32MB的解决方案

这周买了块西数的1T硬盘,用来放各种美剧/高清电影。装好进入Win7后提示检测到新硬盘,然后进入磁盘管理一看发现磁盘大小只有31兆,重启进入BIOS看到的磁盘容量是0MB。换了一台电脑问题依然存在。 于是求助superuser,发现了这篇文章http://www.pcstats.com/articleview.cfm?articleid=1139&page=12,貌似是LBA(Logical Block Addressing)相关的问题,下载了个HDD Capacity Restore Tool修复后问题解决。 阅读全文 →

几个有趣的 Quine 变种

Quine是指一类能生成自己的程序,例如下面这个C程序运行后就能把自己的源码完整的打印出来: char*f="char*f=%c%s%c;main() {printf(f,34,f,34,10);}%c"; main(){printf(f,34,f,34,10);} 这类程序的构造方法计算理论导引或者其他相关的书籍中都有涉及,这里不再赘述。这个月看到几个Quine的变种,都挺有趣的。 首先是sigfpe构造出来的三阶Quine,这是一个只有两行的Haskell程序: q a b c=putStrLn $ b ++ [toEnum 10,'q','('] ++ show b ++ [','] ++ show c ++ [','] ++ show a ++ [')'] main=q "q a b c=putStrLn $ b ++ [toEnum 10,'q','('] ++ show b ++ [','] ++ show c ++ [','] ++ show a ++ [')']" "def q(a,b,c):print b+chr(10)+'q('+repr(b)+','+repr(c)+','+repr(a)+')'" "def e(x) return 34.chr+x+34.chr end;def q(a,b,c) print b+10.chr+'main=q '+e(b)+' '+e(c)+' '+e(a)+' '+10.chr end" 这段程序牛逼在哪里呢?运行后这个程序首先会输出一个Python程序,然后再运行这个Python程序会输出一段Ruby代码,最后这个Ruby代码的运行结果是原来的程序。或者说 阅读全文 →