程序员的自我修养学习笔记——第五章
PE: Portable Executable
COFF: Common Object File Format
跟ELF一样,PE中也允许程序员将变量后函数放到自定义段。在GCC中使用“__attribute__((section)("name"))”,在VISUAL C++中可以使用 “#pragma”编译器指示。
#pragma data_seg("FOO")
int global = 1;
#pragma data_seg(".data")
使用cl 编译器:
开始 –> 所有程序 -> Microsoft Visual Studio ->
Visual Studio Tools -> Developer Command Prompt
cl /c /Za SimpleSectionc.c
/c参数表示只编译,不链接,生成SimpleSection.obj
/Za 参数禁用这些扩展,使得我们的程序跟标准的C/C++ 兼容,使用/Za参数时,编译器自动定义了__STDC__这个宏,我们可以再程序里通过判断这个宏是否被定义而确定编译器是否禁用了Microsoft C/C++ 语法扩展。
Windows下查看可执行文件和目标文件的工具:dumpbin
查看SimpleSection.obj:
dumpbin /ALL SimpleSection.obj > SimpleSection.txt
该命令打印出所以目标文件的相关信息,输出到SimpleSection.txt中。
查看基本信息:
D:\Program Files\...>dumpbin SimpleSection.obj /SUMMARY
Microsoft (R) COFF/PE Dumper Version 11.00.50214.1
Copyright (C) Microsoft Corporation. All rights reserved.
Dump of file SimpleSection.obj
File Type: COFF OBJECT
Summary
4 .bss
C .data
84 .debug$S
18 .drectve
4E .text
COFF文件结构:
COFF文件头包括两部分:一个是描述文件总体和属性的映像头,另外一个是描述该文件中包含的段属性的段表
typedef struct _IMAGE_FILE_HEADER {
WORD Machine; //运行平台
WORD NumberOfSections; //区块数目
DWORD TimeDateStamp; //文件日期时间戳
DWORD PointerToSymbolTable; //指向符号表
DWORD NumberOfSymbols; //符号表中的符号数量
WORD SizeOfOptionalHeader; //映像可选头结构的大小
WORD Characteristics; //文件特征值
} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;
对应“SimpleSection.txt”中的输出信息,“FILE HEADER VALUES”中的内容跟COFF映像头中的成员是一一对应的:
Dump of file SimpleSection.obj
File Type: COFF OBJECT
FILE HEADER VALUES
14C machine (x86)
5 number of sections
4F84D87A time date stamp Wed Apr 11 09:03:54 2012
204 file pointer to symbol table
14 number of symbols
0 size of optional header
0 characteristics
映像头后面紧跟着的是COFF文件的段表,是一个类型为“IMGAE_SECTION_HEADER”结构的数组,数组中每个元素代表一个段,跟ELF文件中的“Elf32_Shdr”很相似。
typedef struct _IMAGE_SECTION_HEADER {
BYTE Name[IMAGE_SIZEOF_SHORT_NAME];
union {
DWORD PhysicalAddress;
DWORD VirtualSize;
} Misc;
DWORD VirtualAddress;
DWORD SizeOfRawData;
DWORD PointerToRawData;
DWORD PointerToRelocations;
DWORD PointerToLinenumbers;
WORD NumberOfRelocations;
WORD NumberOfLinenumbers;
DWORD Characteristics;
} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;
每个段拥有的属性包括:段名(Section Name)、物理地址(Physical address)、虚拟地址(Virtual address)、原始数据大小(Size of raw data)、段在文件中的位置(File pointer to raw data)、该段的重定位表在文件中的位置(File pointer to relocation table)、该段的行号表在文件中的位置(File pointer to line numbers)、标志位(Characteristics)等。
符号表:
“SimpleSection.txt”的最后一部分是COFF符号表(Symbol table),COFF文件的符号表包含的内容几乎跟ELF文件的符号表一样,主要就是符号名、、符号的类型、所在的位置。
SimpleSection.obj的符号表:
COFF SYMBOL TABLE
000 00CEC426 ABS notype Static | @comp.id
001 80000191 ABS notype Static | @feat.00
002 00000000 SECT1 notype Static | .drectve
Section length 18, #relocs 0, #linenums 0, checksum 0
004 00000000 SECT2 notype Static | .debug$S
Section length 84, #relocs 0, #linenums 0, checksum 0
006 00000000 SECT3 notype Static | .data
Section length C, #relocs 0, #linenums 0, checksum AC5AB941
008 00000000 SECT3 notype External | _global_init_var
009 00000004 UNDEF notype External | _global_uninit_var
00A 00000004 SECT3 notype Static | $SG1281
00B 00000008 SECT3 notype Static | ?static_var@?1??main@@9@9 (`main'::`2'::static_var)
00C 00000000 UNDEF notype () External | _printf
00D 00000000 SECT4 notype Static | .text
Section length 4E, #relocs 5, #linenums 0, checksum CC61DB94
00F 00000000 SECT4 notype () External | _func1
010 00000020 SECT4 notype () External | _main
011 00000000 SECT5 notype Static | .bss
Section length 4, #relocs 0, #linenums 0, checksum 0
013 00000000 SECT5 notype Static | ?static_var2@?1??main@@9@9 (`main'::`2'::static_var2)
String Table Size = 0x5D bytes
第三列是符号所在的位置,“ABS”表示符号的绝对值,它不存在于任何段中;SECT1(Section#1)表示符号所表示的对象定义在COFF文件的第一个段中,即本例中的.drectve段;UNDEF(Undefined)表示符号是未定义的,即这个符号被定义在其他目标文件中的。Static表示绝不变量,External表示全局变量。
“_global_init_varabal”这个符号位于Section#3即 .data段,它的长度是4个字节,可见范围是全局的。
PE文件是基于COFF扩展,比COFF文件多了几个结构。最主要的变化有两个:第一个是文件最开始部分不是COFF文件头,而是DOS MZ可执行文件格式的文件头和桩代码,第二个变化是原来的COFF文件头中的“IMAGE_FILE_HEADER”被扩展成为了PE文件头结构“IMGAE_NT_HEADERS”
PE 文件格式
程序员的自我修养学习笔记——第五章相关推荐
- 程序员的自我修养——学习笔记1
文章目录 计算机硬件 早期计算机 发展 SMP和多核 计算机软件 操作系统和设备驱动的作用 文件系统 存储设备 未使用内存管理时 解决思路:地址空间 分段 分页 线程进程 参考资料 计算机硬件 计算机 ...
- 程序员的自我修养读书笔记-1
前序:作为一个马上就要工作的非科班本科生,前段时间为了找工作,有针对性的学习了一些编程语言,数据结构,网络方面的知识,学的非常浅,非常杂乱,存粹是为了应对找工作.现在空下来了,想着以后应该就是走程序员 ...
- 程序员的自我修养阅读笔记
编译和链接 将编译和链接合并到一起的过程称为构建(Build). 从源文件生成最终可执行目标文件共有4个步骤: 预处理(Prepressing) 编译(Compilation) 汇编(Assembly ...
- 程序员的自我修养 - 读书笔记文字版
第1部分 简介 第1章 温故而知新 程序在运行的时候先通过分段(segmentation)的方式将虚拟地址空间与真实的物理内存地址空间进行一一的映射,但是这种方式每次换入换出的是整个程序,导致IO变大 ...
- 《程序员的自我修养》笔记
第1章 引言 说明:①本书中将计算机的范围限定于PC机,更具体的讲是采用x86指令集的32位CPU的个人计算机. 1.1 CPU与外围部件的连接方式 计算机最核心的三个硬件设备是:CPU.内存.I/O ...
- 程序员的自我修养——读书笔记
第一部分:温故而知新 第一章:介绍基本的背景知识--操作系统.线程.硬件 1.关于C语言中的hello world这些问题你都清楚吗? 2.计算机硬件设备的三个核心部件: 1>中央处理器CPU ...
- 弱符号与弱引用 -> 程序员的自我修养 第3,4章笔记
1. 在程序中声明并使用节名 先看下面一段有意思的程序 #include <stdio.h>__attribute__((section("abcd"))) int s ...
- 《程序员的自我修养--链接、装载与库》学习笔记(一)
本系列文章是<程序员的自我修养–链接.装载与库>(电子工业出版社)一书的学习摘录笔记,本文是书中1.1至1.4部分. 文章目录 基础概念 硬件 软件 基础概念 #include <s ...
- 《程序员的自我修养》学习笔记
程序员的自我修养 第一章 谈职业生涯 1.程序员应该是那些不断追求更高技术,并有着自己产品梦的工匠.当你通过对自己技术不断打磨,一次又一次做出那些优秀产品的时候,你会发现自己不再是他人口中的码农或是屌 ...
最新文章
- 多核片上系统(SoC)架构的嵌入式DSP软件设计
- 可视化卷积神经网络的过滤器_万字长文:深度卷积神经网络特征可视化技术(CAM)最新综述...
- 北京大学纳家勇治研究组在《美国国家科学院院刊》发文阐明时序记忆的神经机制
- System.Security.Cryptography.CryptographicException,密钥集不存在
- Java8 Time
- 无缓冲channel
- 微服务实践分享(2)api网关
- 机器学习实战3--豆瓣读书简介
- YouTube键盘快捷键:速查表
- 【HDU - 6574】Rng(概率,古典概型)
- linux命令取数字前两位,linux中head命令使用详解(显示开头数量的文字块)
- iOS 14.5 目前已經發布了8 個測試版更新
- hql与sql的区别(转)
- 季节性ARIMA模型【R语言】
- js图片自动循环播放
- java汉字转拼音,pinyin4j简单介绍
- 详解百度大脑EdgeBoard出色的视频处理技术
- office2007打开word提示《向程序发送命令时出现问题》
- 矩阵微分与向量函数Taylor展开
- 在线pdf转epub网站
热门文章
- ubuntu20.04下安装Docker和NVIDIA Container Toolkit教程
- Docker知识4:如何在win10下安装 / 使用ubuntu ?应用WSL2
- mysql+date+范围+性能_MySQL性能优化的最佳20+条经验
- 【新星计划】汽车纵向动力学模型
- Spring学习6之自动装配Bean02
- php 类 静态调用 实例化 效率,php类的静态调用和实例化调用有哪些不同点?
- ad 原理图差分线_Altium差分线如何从原理图到PCB布线?
- spring boot和spring cloud的区别_Spring聊聊application和bootstrap
- 利用SIFT和RANSAC算法(openCV框架)实现物体的检测与定位,并求出变换矩阵(findFundamentalMat和findHomography的比较)
- 老手是这样教新手编程的