可执行文件内部的秘密----小话c语言(22)

作者:陈曦

日期:2012-6-23   14:24:27

环境:[Mac 10.7.1 Lion Intel i3 支持64位指令 gcc4.2.1 xcode4.2]  

转载请注明出处



Q1: 编译生成的可执行文件内部是如何被执行的?

A: 当然,首先需要知道它的结构。先编写一个简单的程序,保存为testForC.c:

#include <stdio.h>
#include <string.h>

#define PRINT_D(longValue)       printf(#longValue" is %ld\n", ((long)longValue));
#define PRINT_STR(str)              printf(#str" is %s\n", (str));


int main()
{
    printf("hello\n");

    return 0;
}

编译生成32位应用程序testForC.使用file命令得到它的信息:


Q2: Mach-O是什么?

A: 它表示mach架构下的目标文件。我们可以通过工具MachOView来查看:

由上图可以看到mach-o格式开头的基本信息,包括开头的魔数、对应CPU类型等信息。


Q3: 这些结构在哪里可以看到?

A: 在mach-o/arch.h头文件可以看到如下结构:

typedef struct {
    const char *name;
    cpu_type_t cputype;
    cpu_subtype_t cpusubtype;
    enum NXByteOrder byteorder;
    const char *description;
} NXArchInfo;
它包含一些架构信息,在mach-o/loader.h头文件中包含mach-o格式文件头的格式:
/*
 * The 32-bit mach header appears at the very beginning of the object file for
 * 32-bit architectures.
 */
struct mach_header {
	uint32_t	magic;		/* mach magic number identifier */
	cpu_type_t	cputype;	/* cpu specifier */
	cpu_subtype_t	cpusubtype;	/* machine specifier */
	uint32_t	filetype;	/* type of file */
	uint32_t	ncmds;		/* number of load commands */
	uint32_t	sizeofcmds;	/* the size of all the load commands */
	uint32_t	flags;		/* flags */
};
/* Constant for the magic field of the mach_header (32-bit architectures) */
#define	MH_MAGIC	0xfeedface	/* the mach magic number */
#define MH_CIGAM	0xcefaedfe	/* NXSwapInt(MH_MAGIC) */

Q4: 上面的cputype是CPU_TYPE_I386表示的是32位吧,有的应用程序包含32位和64位体系的代码,结构是如何的?

A: 先生成一个这样的文件。依然使用文章开头的代码,使用如下命令编译:

gcc -o testForC testForC.c -arch i386 -arch x86_64

继续使用file命令得到它的信息:

可以看出,它包含两种体系代码。我们同样使用MachOView工具查看它的内部信息:

可以看出,它内部包含了两种架构的信息,并且它的开头有一些特定的信息,之后才是不同架构的信息。


Q5: 上图中的Load Commands表示什么?

A: 它记录了文件中各个段(如代码段,数据段等)如何映射到内存,也包含了文件使用的动态链接器以及文件需要的动态库,同时也包含文件和动态链接器使用的符号表。Load Commands对应的结构定义如下:

/*
 * The segment load command indicates that a part of this file is to be
 * mapped into the task's address space.  The size of this segment in memory,
 * vmsize, maybe equal to or larger than the amount to map from this file,
 * filesize.  The file is mapped starting at fileoff to the beginning of
 * the segment in memory, vmaddr.  The rest of the memory of the segment,
 * if any, is allocated zero fill on demand.  The segment's maximum virtual
 * memory protection and initial virtual memory protection are specified
 * by the maxprot and initprot fields.  If the segment has sections then the
 * section structures directly follow the segment command and their size is
 * reflected in cmdsize.
 */
struct segment_command { /* for 32-bit architectures */
	uint32_t	cmd;		/* LC_SEGMENT */
	uint32_t	cmdsize;	/* includes sizeof section structs */
	char		segname[16];	/* segment name */
	uint32_t	vmaddr;		/* memory address of this segment */
	uint32_t	vmsize;		/* memory size of this segment */
	uint32_t	fileoff;	/* file offset of this segment */
	uint32_t	filesize;	/* amount to map from the file */
	vm_prot_t	maxprot;	/* maximum VM protection */
	vm_prot_t	initprot;	/* initial VM protection */
	uint32_t	nsects;		/* number of sections in segment */
	uint32_t	flags;		/* flags */
};

比如说,对于testForC的第一个截图:

_TEXT段的VM Address为0x1000.

对于section  __text, 它对应的地址是:

由此,我们可以得到__text在文件中的真实位置为: 0x1F10  -  0x1000  =  0xF10.


作者:陈曦

日期:2012-6-23   14:24:27

环境:[Mac 10.7.1 Lion Intel i3 支持64位指令 gcc4.2.1 xcode4.2]  

转载请注明出处



  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值