开发实用命令和工具----小话c语言(16)

[Mac 10.7.1  Lion  Intel-based  x64  gcc4.2.1]


Q: 有的时候,记得在某个目录下写过某个变量或者其它什么文本形式的东西,但是后来忘记写在哪个文件里了,怎么找到?

A: 这个就需要用到grep命令了。它很强大,尤其对于开发或者寻找某个东西在哪里的时候。举个例子,有个目录里面有一些文件:

开发实用命令和工具----小话c语言(16)_第1张图片

而且,有一些文件里面含有main字符串,现在需要把它们找出来:

很可惜,在mac10.7.1下面,grep的一个参数-r似乎无效,不能递归到子目录下搜索;不过在cygwin里面是ok的;bug列表中没有找到,但是实践确实无效,也许是个bug吧。

上面测试用的grep版本是2.5.1.

当然,它还支持很多参数,比如-i忽略大小写,-E进行egrep扩展等等。


Q: 经常会遇到,创建一个进程,但是后来想把它关闭,ps -ax命令得到一堆进程,不便于寻找,怎么快速能定位它?

A: 同样可以使用上面的grep命令。例如,需要寻找系统是否启动了httpd进程:


Q: 有时,需要分析一个生成的可执行文件的内部结构,怎么办?

A: 使用otool命令,它异常的强大。它支持很多参数,帮您将可执行文件,也包括中间文件、库等文件的内部展示地一览无余。


Q: 我需要查看一个可执行文件的mach头,怎么办?

A: 可以使用-h参数。如下,写一个简单的代码,保存为hello.c:

#include <stdio.h>

int main()
{
    int i = 2;
    printf("%d\n", i);
    return 0;
}

使用gcc  -o  hello  hello.c编译得到hello.它将对hello进行分析:

开发实用命令和工具----小话c语言(16)_第2张图片

用它和系统的mach header头文件结构对应,就可以得到它的具体含义。同理,使用-l命令可以得到mach-o格式文件的load commands.


Q: 我想得到某个可执行文件依赖哪些动态库,怎么办?

A: 可以使用otool命令的-L参数即可。同上使用上面的hello文件,


Q: 我想知道一个可执行文件它的代码段,怎么办?

A: 可以使用otool命令的-t参数。同样使用上面的可执行文件hello,

不过,它是二进制形式的。


Q: 怎么才能显示上面的二进制形式的汇编形式代码?

A: 可以配合-V命令或者-v命令(二者有一定区别)。

xichenMac:c_simple xichen$ otool -Vt hello
hello:
(__TEXT,__text) section
start:
0000000100000eb0	pushq	$0x00
0000000100000eb2	movq	%rsp,%rbp
0000000100000eb5	andq	$0xf0,%rsp
0000000100000eb9	movq	0x08(%rbp),%rdi
0000000100000ebd	leaq	0x10(%rbp),%rsi
0000000100000ec1	movl	%edi,%edx
0000000100000ec3	addl	$0x01,%edx
0000000100000ec6	shll	$0x03,%edx
0000000100000ec9	addq	%rsi,%rdx
0000000100000ecc	movq	%rdx,%rcx
0000000100000ecf	jmp	0x100000ed5
0000000100000ed1	addq	$0x08,%rcx
0000000100000ed5	cmpq	$0x00,(%rcx)
0000000100000ed9	jne	0x100000ed1
0000000100000edb	addq	$0x08,%rcx
0000000100000edf	callq	_main
0000000100000ee4	movl	%eax,%edi
0000000100000ee6	callq	0x100000f2e	; symbol stub for: _exit
0000000100000eeb	hlt
0000000100000eec	nop
0000000100000eed	nop
0000000100000eee	nop
0000000100000eef	nop
_main:
0000000100000ef0	pushq	%rbp
0000000100000ef1	movq	%rsp,%rbp
0000000100000ef4	subq	$0x10,%rsp
0000000100000ef8	movl	$0x00000002,0xf4(%rbp)
0000000100000eff	movl	0xf4(%rbp),%eax
0000000100000f02	xorb	%cl,%cl
0000000100000f04	leaq	0x00000055(%rip),%rdx
0000000100000f0b	movq	%rdx,%rdi
0000000100000f0e	movl	%eax,%esi
0000000100000f10	movb	%cl,%al
0000000100000f12	callq	0x100000f34	; symbol stub for: _printf
0000000100000f17	movl	$0x00000000,0xf8(%rbp)
0000000100000f1e	movl	0xf8(%rbp),%eax
0000000100000f21	movl	%eax,0xfc(%rbp)
0000000100000f24	movl	0xfc(%rbp),%eax
0000000100000f27	addq	$0x10,%rsp
0000000100000f2b	popq	%rbp
0000000100000f2c	ret
xichenMac:c_simple xichen$ 
可以看到,对应的汇编已经出来了。


Q: 我想查看__TEXT段的字符串字面量,怎么查看?

A: 可以使用-sv  __TEXT  __cstring参数来得到。修改hello.c, 如下:

#include <stdio.h>

int g_i = 0xAA;
const int g_j = 0xBB;
char *str = "hello";

int main()
{
    int i = 2;
    printf("%d\n", i);
    return 0;
}
编译成hello.

可以看到,全局的str对应的hello\0和printf输出的%d\n\0字符串被显示了


Q: 我想查看数据区__DATA里面的数据(__data),怎么办?

A: 可以使用-sv  __DATA  __data参数来得到。使用上面的hello,

可以看到前4个字节对应的全局变量g_i在此被显示。如果使用otool  -d  hello会查看hello的__DATA区的数据。


Q: 我想查看全局const变量g_i对应的数据,怎么查看?

A: 可以使用-sv  __TEXT  __const参数来查看。

开发实用命令和工具----小话c语言(16)_第3张图片

可以看到0xBB变量的数据在此展示了。


Q: 我只想查看某个函数的汇编形式,怎么办?

A: 可以使用-p参数来指定查看的函数。如下:

开发实用命令和工具----小话c语言(16)_第4张图片

上面查看了hello中的main函数的汇编形式(注意,虽然代码中是main函数,但是在可执行文件的符号表中,可能会被改变,这依赖编译器).


Q: 有的可执行文件支持不止一种硬件架构的代码,如何查看包含哪些?

A: 可以使用file命令查看。如上,查看上面的hello文件的信息:

可以看到它是64位运行于x64平台上的可执行文件。


Q: 如何编译得到一个可执行文件,它是通用的,可以包含几种架构代码的?

A: 使用gcc的-arch参数功能来实现。依然使用上面的hello.c代码:

再运行file命令:

可以看到,文件包含了两种架构体系代码。


Q: 看到很多逆向工具,可以修改特定的目标文件实现特定的目的,是否可以修改hello文件来得到希望的执行效果?

A: 是的。我并不善于修改汇编代码,我们可以修改数据段来查看效果。

修改上面的hello.c代码如下:

#include <stdio.h>

int g_i = 0xAA;
const int g_j = 0xBB;
char *str = "hello";

int main()
{
    int i = 2;
    printf("%s %d\n", str, i);
    return 0;
}

编译成hello.并查看执行效果:

下面就使用vi来修改可执行文件的hello字符串为iello, 最后查看执行效果。使用vi打开hello文件,定位到hello字符串的位置:

开发实用命令和工具----小话c语言(16)_第5张图片

修改hello的h为i:

保存,然后执行hello:

可以看到,执行结果已经变了。


Q: 有时,需要查看一个目标文件中各个段的大小,如何查看?

A: 可以使用size命令。


Q: 有时,需要查看目标文件中可打印的字符串有哪些,如何查看?

A: 可以使用strings命令。


Q: 很多编译好的程序,里面包含了符号表或者一些调试信息,如何去除它们?

A: 可以使用strip命令。

开发实用命令和工具----小话c语言(16)_第6张图片

使用strip命令后:

开发实用命令和工具----小话c语言(16)_第7张图片

可以看到,符号信息确实少了。


Q: 上面提到的nm命令,它是做什么的?

A: 它是可以查看目标文件中包含的符号信息的。


xichen

2012-5-25 12:50:52


你可能感兴趣的:(c,汇编,gcc,语言,工具,编译器)