pe_assembler/types/coff/
mod.rs

1use byteorder::{LittleEndian, ReadBytesExt};
2use gaia_types::{helpers::Architecture, GaiaError};
3use serde::{Deserialize, Serialize};
4use std::io::Read;
5
6/// COFF 文件头结构
7///
8/// 包含 COFF(Common Object File Format)格式的基本信息,
9/// 定义了目标机器类型、节的数量和时间戳等关键信息。
10#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
11pub struct CoffHeader {
12    /// 目标机器类型,如 x86、x64、ARM 等
13    pub machine: u16,
14    /// 节的数量,表示文件中包含多少个节
15    pub number_of_sections: u16,
16    /// 时间戳,表示文件创建或链接的时间
17    pub time_date_stamp: u32,
18    /// 符号表的文件偏移,如果没有符号表则为 0
19    pub pointer_to_symbol_table: u32,
20    /// 符号表中的符号数量
21    pub number_of_symbols: u32,
22    /// 可选头的大小(以字节为单位)
23    pub size_of_optional_header: u16,
24    /// 文件特征标志,描述文件的各种属性
25    pub characteristics: u16,
26}
27
28impl CoffHeader {
29    /// 创建一个新的 COFF 头,只需要最核心的字段
30    pub fn new(machine: u16, number_of_sections: u16) -> Self {
31        CoffHeader {
32            machine,
33            number_of_sections,
34            time_date_stamp: 0,
35            pointer_to_symbol_table: 0,
36            number_of_symbols: 0,
37            size_of_optional_header: 0,
38            characteristics: 0,
39        }
40    }
41
42    /// 设置时间戳
43    pub fn with_timestamp(mut self, time_date_stamp: u32) -> Self {
44        self.time_date_stamp = time_date_stamp;
45        self
46    }
47
48    /// 设置符号表信息
49    pub fn with_symbol_table(mut self, pointer_to_symbol_table: u32, number_of_symbols: u32) -> Self {
50        self.pointer_to_symbol_table = pointer_to_symbol_table;
51        self.number_of_symbols = number_of_symbols;
52        self
53    }
54
55    /// 设置可选头大小
56    pub fn with_optional_header_size(mut self, size_of_optional_header: u16) -> Self {
57        self.size_of_optional_header = size_of_optional_header;
58        self
59    }
60
61    /// 设置文件特征
62    pub fn with_characteristics(mut self, characteristics: u16) -> Self {
63        self.characteristics = characteristics;
64        self
65    }
66
67    pub fn read<R: Read>(mut reader: R) -> Result<Self, GaiaError> {
68        Ok(CoffHeader {
69            machine: reader.read_u16::<LittleEndian>()?,
70            number_of_sections: reader.read_u16::<LittleEndian>()?,
71            time_date_stamp: reader.read_u32::<LittleEndian>()?,
72            pointer_to_symbol_table: reader.read_u32::<LittleEndian>()?,
73            number_of_symbols: reader.read_u32::<LittleEndian>()?,
74            size_of_optional_header: reader.read_u16::<LittleEndian>()?,
75            characteristics: reader.read_u16::<LittleEndian>()?,
76        })
77    }
78
79    pub fn get_architecture(&self) -> Architecture {
80        match self.machine {
81            0x014C => Architecture::X86,
82            0x8664 => Architecture::X86_64,
83            0x0200 => Architecture::ARM32,
84            0xAA64 => Architecture::ARM64,
85            _ => Architecture::Unknown,
86        }
87    }
88}
89
90/// 节头结构
91///
92/// 包含 COFF 文件中一个节(Section)的元数据信息,如名称、大小、
93/// 位置和属性等。这个结构不包含节的实际数据,只包含描述信息。
94#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
95pub struct SectionHeader {
96    /// 节名称,8字节的ASCII字符串,如 ".text"、".data" 等
97    pub name: [u8; 8],
98    /// 节在内存中的虚拟大小
99    pub virtual_size: u32,
100    /// 节在内存中的虚拟地址(RVA)
101    pub virtual_address: u32,
102    /// 节在文件中的原始数据大小
103    pub size_of_raw_data: u32,
104    /// 节在文件中的偏移地址
105    pub pointer_to_raw_data: u32,
106    /// 重定位表在文件中的偏移地址
107    pub pointer_to_relocations: u32,
108    /// 行号表在文件中的偏移地址
109    pub pointer_to_line_numbers: u32,
110    /// 重定位项的数量
111    pub number_of_relocations: u16,
112    /// 行号项的数量
113    pub number_of_line_numbers: u16,
114    /// 节的特征标志,描述节的属性(可读、可写、可执行等)
115    pub characteristics: u32,
116}
117
118/// COFF 符号表项
119///
120/// 表示 COFF 对象文件中的一个符号,包含符号名称、值、节号等信息。
121/// 符号可以是函数、变量、标签等程序中的标识符。
122#[derive(Clone, Debug, Serialize, Deserialize)]
123pub struct CoffSymbol {
124    /// 符号名称,如果长度超过8字节则存储在字符串表中
125    pub name: String,
126    /// 符号的值,通常是地址或偏移量
127    pub value: u32,
128    /// 符号所在的节号,0表示未定义,-1表示绝对符号,-2表示调试符号
129    pub section_number: i16,
130    /// 符号类型,描述符号的基本类型
131    pub symbol_type: u16,
132    /// 存储类别,描述符号的作用域和生命周期
133    pub storage_class: u8,
134    /// 辅助符号的数量
135    pub number_of_aux_symbols: u8,
136}
137
138/// COFF 重定位项
139///
140/// 表示需要在链接时进行地址重定位的项目。
141/// 重定位是将相对地址转换为绝对地址的过程。
142#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
143pub struct CoffRelocation {
144    /// 需要重定位的虚拟地址
145    pub virtual_address: u32,
146    /// 符号表索引,指向相关的符号
147    pub symbol_table_index: u32,
148    /// 重定位类型,定义如何进行重定位
149    pub relocation_type: u16,
150}
151
152/// COFF 节结构
153///
154/// 表示 COFF 对象文件中的一个节,包含节头和数据。
155/// 与 PE 节类似,但用于对象文件而非可执行文件。
156#[derive(Clone, Debug, Serialize, Deserialize)]
157pub struct CoffSection {
158    /// 节头信息
159    pub header: SectionHeader,
160    /// 节的原始数据
161    #[serde(skip_serializing_if = "Vec::is_empty")]
162    pub data: Vec<u8>,
163    /// 重定位表,包含该节的所有重定位项
164    pub relocations: Vec<CoffRelocation>,
165}
166
167/// COFF 对象文件结构
168///
169/// 表示一个完整的 COFF 对象文件,包含头部、节、符号表等信息。
170/// COFF 对象文件是编译器生成的中间文件,包含未链接的代码和数据。
171#[derive(Clone, Debug, Serialize, Deserialize)]
172pub struct CoffObject {
173    /// COFF 头部信息
174    pub header: CoffHeader,
175    /// 所有节的集合
176    pub sections: Vec<CoffSection>,
177    /// 符号表,包含所有符号信息
178    pub symbols: Vec<CoffSymbol>,
179    /// 字符串表,存储长符号名称
180    pub string_table: Vec<u8>,
181}
182
183/// 库文件成员头
184///
185/// 表示静态库文件中一个成员文件的头部信息。
186/// 静态库是多个对象文件的集合,每个成员都有自己的头部。
187#[derive(Clone, Debug, Serialize, Deserialize)]
188pub struct ArchiveMemberHeader {
189    /// 成员文件名称
190    pub name: String,
191    /// 文件修改时间戳
192    pub timestamp: u32,
193    /// 用户ID
194    pub user_id: u16,
195    /// 组ID
196    pub group_id: u16,
197    /// 文件权限模式
198    pub mode: u32,
199    /// 文件大小
200    pub size: u32,
201}
202
203/// 库文件成员
204///
205/// 表示静态库文件中的一个成员,包含头部和数据。
206/// 每个成员通常是一个 COFF 对象文件。
207#[derive(Clone, Debug, Serialize, Deserialize)]
208pub struct ArchiveMember {
209    /// 成员头部信息
210    pub header: ArchiveMemberHeader,
211    /// 成员数据,通常是 COFF 对象文件的内容
212    pub data: Vec<u8>,
213    /// 解析后的 COFF 对象(如果成功解析)
214    pub coff_object: Option<CoffObject>,
215}
216
217/// 静态库文件结构
218///
219/// 表示一个完整的静态库文件(.lib 文件),包含多个对象文件。
220/// 静态库用于将多个对象文件打包成一个文件,便于分发和链接。
221#[derive(Clone, Debug, Serialize, Deserialize)]
222pub struct StaticLibrary {
223    /// 库文件签名,通常为 "!<arch>\n"
224    pub signature: String,
225    /// 所有成员文件的集合
226    pub members: Vec<ArchiveMember>,
227    /// 符号索引表,用于快速查找符号
228    pub symbol_index: Vec<(String, usize)>, // (symbol_name, member_index)
229}
230
231/// COFF 文件类型枚举
232///
233/// 区分不同类型的 COFF 相关文件格式。
234#[derive(Copy, Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
235pub enum CoffFileType {
236    /// COFF 对象文件 (.obj)
237    Object,
238    /// 静态库文件 (.lib)
239    StaticLibrary,
240    /// PE 可执行文件 (.exe)
241    Executable,
242    /// PE 动态库文件 (.dll)
243    DynamicLibrary,
244}
245
246/// COFF 文件信息
247///
248/// 提供 COFF 相关文件的摘要信息。
249#[derive(Clone, Debug, Serialize, Deserialize)]
250pub struct CoffInfo {
251    /// 文件类型
252    pub file_type: CoffFileType,
253    /// 目标架构
254    pub target_arch: Architecture,
255    /// 节的数量
256    pub section_count: u16,
257    /// 符号的数量
258    pub symbol_count: u32,
259    /// 文件大小
260    pub file_size: u64,
261    /// 时间戳
262    pub timestamp: u32,
263}