strace 速查表

此文是 strace cheat sheet 的翻译。

TL;DR

strace 可以追踪系统调用、信号,在调试中,它还是收集上下文环境的非常好的工具。 此速查表将会展示一些技巧来说明 strace 的使用方法、如何过滤输出,并且介绍了一些 strace 的实用参数。

strace PTRACE_TRACEME EPERM (Operation not permitted)

你应该以 root 身份来运行 strace。如果你以 root 用户运行,也得到这个提示,这说明在你的系统中,strace 不允许附加到进程上。 你可以修改 /proc 中的设置,来开启 strace 附加到进程的功能:

1
sudo bash -c 'echo 0 > /proc/sys/kernel/yama/ptrace_scope'

为了让这个修改永久生效,请首先检查你的系统有没有 /etc/sysctl.d/10-ptrace.conf  文件。 如果你的系统有这个文件,修改该文件:

1
kernel.yama.ptrace_scope = 0

如果你的系统没有这个文件:

  1. 打开 /etc/sysctl.conf 文件
  2. 找到设置 kernel.yama.ptrace_scope
  3. 如果该设置存在,将其修改为 0
  4. 如果不存在,添加一行 kernel.yama.ptrace_scope = 0
阅读更多

给Eclipse添加pkg-config支持

原来用gedit+gcc来编写GTK程序(主要是学习例程),后来随着代码越写越多,需要一个IDE来辅助开发,于是想到了万能的Eclipse。 可是Eclipse可以支持C语言开发,却不支持pkg-config命令集成。搞得每次新建GTK工程都要把pkgconfig的输出改到Eclipse中。 后来烦了,自己google之,得解:http://marketplace.eclipse.org/content/pkg-config-support-eclipse-cdt

安装Eclipse

首先,安装jre和jdk等依赖。 接下来下载Eclipse。我原来下载了Eclipse 4.3 Classic ,但是最新版成了Eclipse 4.3 Standard ,都是可以的。 然后解压Eclipse。(双击eclipse文件即可运行Eclipse) 另外,Eclipse CDT和gtk开发的其他依赖包也要安装。

安装Eclipse Marketpalce Client(MPC)

我下载的是Eclipse 4.3 Classic,所以需要安装MPC;如果你下载的是Eclipse 4.3 Standard,可以跳过此步。 在Install New Software窗口中选上所有网站,然后搜索market即可看到MPC;点击下一步,然后同意许可协议等。 安装完成后重启Eclipse即可完成MPC的安装。

在market中安装Pkg-config support

在帮助菜单中打开Eclipse Marketpalce: 1 搜索pkg-config,如图: 2 点击安装,一直确认、同意许可协议。

Pkg-config support的使用

首先,创建一个Hello World C工程,贴入GTK程序代码(代码附后),此时Eclipse提示程序中有好几处错误/警告: 3 接下来,打开项目的设置菜单 -> C/C++ Build -> Settings -> Pkg-config 选项卡: 4 在其中的选项中勾选 GTK+-2.0 (我个人使用的是GTK 2.0,可根据自己的情况酌情选择): 5 然后点击确定。 稍等几秒后就会发现Eclipse识别出来了头文件包含、GTK类型定义等,如图: 6 点击运行(Run),可以看到GTK程序在Eclipse中正常运行: 7 GTK测试代码

#include <stdio.h>
#include <stdlib.h>
#include <gtk/gtk.h>

阅读更多

unzip的中文问题

唉,unzip的-O选项一直是一个传说中的存在,而且unzip的开发者一直没有意向修复。 故自己动手,丰衣足食,用python写了一个MultiCharset ZIP,代码附上:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#!/usr/bin/python
# -*- coding: utf-8 -*-

import os
import sys
import zipfile
from optparse import OptionParser

def listZip(zipf):
    print "Archive:  %s" %zipf
    print "  Length      Date    Time    Name"
    print "---------  ---------- -----   ----"
    filist=zipfile.ZipFile(zipf).infolist()
    totalnum=0
    totalsize=0
    for finfo in filist:
        totalnum+=1
        totalsize+=finfo.file_size
        print "%9d " %finfo.file_size ,
        print "%04d-%02d-%02d" %(finfo.date_time[0],finfo.date_time[1],finfo.date_time[2]),
        print "%02d:%02d  " %(finfo.date_time[3],finfo.date_time[4]),
        print finfo.filename.decode('gb18030').encode('utf-8')
    print "---------                     -------"
    print "%9d" %totalsize ,
    print "                   ",
    print "%d files" %totalnum

def exZip(zipf,exdir):
    zf=zipfile.ZipFile(zipf)
    nlist=zf.namelist()
    nlist.sort(key=lambda x:len(x))
    for fn in nlist:
        fnew=unicode(fn,'gb2312').encode('utf8')
        if fnew.endswith('/'):
            os.mkdir(exdir+fnew)
        else:
            file(exdir+fnew,'wb').write(zf.read(fn))
        print fnew
    zf.close()

def main():
    usage = "usage: "+sys.argv[0]+" [options] zipfile1 zipfile2"
    parser = OptionParser(usage=usage)
    parser.add_option("-l","--list",action="store_true",help="list files in zip file",dest="islist",default=True)
    parser.add_option("-x","--extract",action="store_true",help="extract zip files",dest="isex",default=False)
    parser.add_option("-d","--exdir",action="store",help="define extract directory",dest="exdir",default=".")
    #parser.add_option("-z","--exdir",action="store",dest="exidr")

    (options,args)=parser.parse_args();

    if(options.isex):
        for zf in args:
            exZip(zf,options.exdir+"/")
    else:
        if(options.islist):
            for zf in args:
                listZip(zf)

if __name__ == "__main__":
    main()

可以在~/bin/目录下创建一个mczip文件,写入代码,添加可执行权限,即可在终端中用mczip来列出zip文件内容、解压zip文件。

用法:

1
2
3
4
5
6
Usage:mczip.py [options] zipfile1 zipfile2
Options:
-h, --help            show this help message and exit
-l, --list            list files in zip file
-x, --extract         extract zip files
-d EXDIR, --exdir=EXDIR     define extract directory`

只有列出zip包的文件内容和解压zip文件两个功能,只能处理gb18030编码。

注:Python3的zip模块判断更加奇葩了,只要文件名不是ascii编码,就认为是utf8编码,而且不保留bytes格式的文件名,有点难办啊。

阅读更多

gcc的使用和编译时的符号确定

一般来说,我们编译c语言程序要经过编译(预处理)、和链接两步。当然教材上讲的时候还有预处理。 预处理

1
gcc -E code.c -o code.e.c

预处理主要处理文件包含和宏定义等等。 编译

1
gcc -c code.c -o code.o

编译主要把c语句翻译成二进制代码(一般此步骤包括了预处理)。 但是有一些函数的实现没有在预处理过的c语言文件中,类似的还有extern声明的变量,所以现在编译的文件还没有办法执行。这些无法决定位置的函数和变量,在.o文件中统称为未定义的符号。 链接

1
gcc code.o -o code

在这一步我们要把所有.o文件中的未定义符号给确定下来,确定的来源有两种,查看其他.o文件的导出表中查找,从其他.so(dll)文件的导出表中查找。 gcc还有一个重要的参数是-g,表示编译的时候保留调试信息(包括c语句和汇编语句的对应关系,变量的分配) gcc的-o参数指定输出文件的名字。 让我们通过一个例子来了解这个流程

test.c
1
2
3
4
5
6
7
8
9
10
11
#include <stdio.h>

extern int a;

extern void test();

int main()
{
test();
return 0;
}

先预处理它:

1
gcc -E test.c -o test.e.c
阅读更多