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
118impl SectionHeader {
119    pub fn get_name(&self) -> &str {
120        unsafe {
121            let name = str::from_utf8_unchecked(&self.name);
122            name.trim_end_matches('\0')
123        }
124    }
125}
126
127/// COFF 符号表项
128///
129/// 表示 COFF 对象文件中的一个符号,包含符号名称、值、节号等信息。
130/// 符号可以是函数、变量、标签等程序中的标识符。
131#[derive(Clone, Debug, Serialize, Deserialize)]
132pub struct CoffSymbol {
133    /// 符号名称,如果长度超过8字节则存储在字符串表中
134    pub name: String,
135    /// 符号的值,通常是地址或偏移量
136    pub value: u32,
137    /// 符号所在的节号,0表示未定义,-1表示绝对符号,-2表示调试符号
138    pub section_number: i16,
139    /// 符号类型,描述符号的基本类型
140    pub symbol_type: u16,
141    /// 存储类别,描述符号的作用域和生命周期
142    pub storage_class: u8,
143    /// 辅助符号的数量
144    pub number_of_aux_symbols: u8,
145}
146
147/// COFF 重定位项
148///
149/// 表示需要在链接时进行地址重定位的项目。
150/// 重定位是将相对地址转换为绝对地址的过程。
151#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
152pub struct CoffRelocation {
153    /// 需要重定位的虚拟地址
154    pub virtual_address: u32,
155    /// 符号表索引,指向相关的符号
156    pub symbol_table_index: u32,
157    /// 重定位类型,定义如何进行重定位
158    pub relocation_type: u16,
159}
160
161/// COFF 节结构
162///
163/// 表示 COFF 对象文件中的一个节,包含节头和数据。
164/// 与 PE 节类似,但用于对象文件而非可执行文件。
165#[derive(Clone, Debug, Serialize, Deserialize)]
166pub struct CoffSection {
167    /// 节头信息
168    pub header: SectionHeader,
169    /// 节的原始数据
170    #[serde(skip_serializing_if = "Vec::is_empty")]
171    pub data: Vec<u8>,
172    /// 重定位表,包含该节的所有重定位项
173    pub relocations: Vec<CoffRelocation>,
174}
175
176/// COFF 对象文件结构
177///
178/// 表示一个完整的 COFF 对象文件,包含头部、节、符号表等信息。
179/// COFF 对象文件是编译器生成的中间文件,包含未链接的代码和数据。
180#[derive(Clone, Debug, Serialize, Deserialize)]
181pub struct CoffObject {
182    /// COFF 头部信息
183    pub header: CoffHeader,
184    /// 所有节的集合
185    pub sections: Vec<CoffSection>,
186    /// 符号表,包含所有符号信息
187    pub symbols: Vec<CoffSymbol>,
188    /// 字符串表,存储长符号名称
189    pub string_table: Vec<u8>,
190}
191
192/// 库文件成员头
193///
194/// 表示静态库文件中一个成员文件的头部信息。
195/// 静态库是多个对象文件的集合,每个成员都有自己的头部。
196#[derive(Clone, Debug, Serialize, Deserialize)]
197pub struct ArchiveMemberHeader {
198    /// 成员文件名称
199    pub name: String,
200    /// 文件修改时间戳
201    pub timestamp: u32,
202    /// 用户ID
203    pub user_id: u16,
204    /// 组ID
205    pub group_id: u16,
206    /// 文件权限模式
207    pub mode: u32,
208    /// 文件大小
209    pub size: u32,
210}
211
212/// 库文件成员
213///
214/// 表示静态库文件中的一个成员,包含头部和数据。
215/// 每个成员通常是一个 COFF 对象文件。
216#[derive(Clone, Debug, Serialize, Deserialize)]
217pub struct ArchiveMember {
218    /// 成员头部信息
219    pub header: ArchiveMemberHeader,
220    /// 成员数据,通常是 COFF 对象文件的内容
221    pub data: Vec<u8>,
222    /// 解析后的 COFF 对象(如果成功解析)
223    pub coff_object: Option<CoffObject>,
224}
225
226/// 静态库文件结构
227///
228/// 表示一个完整的静态库文件(.lib 文件),包含多个对象文件。
229/// 静态库用于将多个对象文件打包成一个文件,便于分发和链接。
230#[derive(Clone, Debug, Serialize, Deserialize)]
231pub struct StaticLibrary {
232    /// 库文件签名,通常为 "!<arch>\n"
233    pub signature: String,
234    /// 所有成员文件的集合
235    pub members: Vec<ArchiveMember>,
236    /// 符号索引表,用于快速查找符号
237    pub symbol_index: Vec<(String, usize)>, // (symbol_name, member_index)
238}
239
240/// COFF 文件类型枚举
241///
242/// 区分不同类型的 COFF 相关文件格式。
243#[derive(Copy, Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
244pub enum CoffFileType {
245    /// COFF 对象文件 (.obj)
246    Object,
247    /// 静态库文件 (.lib)
248    StaticLibrary,
249    /// PE 可执行文件 (.exe)
250    Executable,
251    /// PE 动态库文件 (.dll)
252    DynamicLibrary,
253}
254
255/// COFF 文件信息
256///
257/// 提供 COFF 相关文件的摘要信息。
258#[derive(Clone, Debug, Serialize, Deserialize)]
259pub struct CoffInfo {
260    /// 文件类型
261    pub file_type: CoffFileType,
262    /// 目标架构
263    pub target_arch: Architecture,
264    /// 节的数量
265    pub section_count: u16,
266    /// 符号的数量
267    pub symbol_count: u32,
268    /// 文件大小
269    pub file_size: u64,
270    /// 时间戳
271    pub timestamp: u32,
272}