clr_assembler/formats/dll/reader/
mod.rs

1use crate::{
2    formats::dll::DllReadConfig,
3    program::{
4        ClrAccessFlags, ClrHeader, ClrMethod, ClrProgram, ClrType, ClrTypeReference, ClrVersion, DotNetAssemblyInfo,
5        MetadataHeader, StreamHeader,
6    },
7};
8use byteorder::{LittleEndian, ReadBytesExt};
9use gaia_types::{GaiaDiagnostics, GaiaError, SourceLocation};
10use pe_assembler::{
11    helpers::PeReader,
12    types::{PeHeader, PeProgram, SectionHeader},
13};
14use std::io::{Read, Seek, SeekFrom};
15use url::Url;
16
17#[derive(Debug)]
18pub struct DllReader<'config, R> {
19    /// 配置选项
20    options: &'config DllReadConfig,
21    reader: pe_assembler::formats::dll::reader::DllReader<R>,
22    /// 解析后的 CLR 头信息
23    clr_header: Option<ClrHeader>,
24    /// 解析后的元数据头信息
25    metadata_header: Option<MetadataHeader>,
26    /// 元数据流头信息列表(惰性加载)
27    stream_headers: Option<Vec<StreamHeader>>,
28    /// 提取的程序集基本信息(惰性加载)
29    assembly_info: Option<DotNetAssemblyInfo>,
30    /// 完整解析的 CLR 程序(惰性加载)
31    clr_program: Option<ClrProgram>,
32}
33
34impl<'config, R: Read + Seek> PeReader<R> for DllReader<'config, R> {
35    fn get_viewer(&mut self) -> &mut R {
36        self.reader.get_viewer()
37    }
38
39    fn add_diagnostics(&mut self, error: impl Into<GaiaError>) {
40        self.reader.add_diagnostics(error)
41    }
42
43    fn get_section_headers(&mut self) -> Result<&[SectionHeader], GaiaError> {
44        self.reader.get_section_headers()
45    }
46
47    fn get_pe_header(&mut self) -> Result<&PeHeader, GaiaError> {
48        self.reader.get_pe_header()
49    }
50
51    fn get_program(&mut self) -> Result<&PeProgram, GaiaError> {
52        self.reader.get_program()
53    }
54}
55
56impl<'config, R> DllReader<'config, R> {
57    /// 使用泛型 PE 读取器构造 .NET 读取器(DLL)
58    ///
59    /// 注意:这是惰性构造函数,不会立即执行解析工作流程
60    pub fn new(reader: R, options: &'config DllReadConfig) -> Self {
61        Self {
62            reader: pe_assembler::formats::dll::reader::DllReader::new(reader),
63            clr_header: None,
64            metadata_header: None,
65            stream_headers: None,
66            assembly_info: None,
67            clr_program: None,
68            options,
69        }
70    }
71}
72
73impl<'config, R> DllReader<'config, R>
74where
75    R: Read + Seek,
76{
77    /// 从文件读取 .NET 程序集
78    ///
79    /// 该方法读取并解析 .NET 程序集文件,步骤如下:
80    /// 1. 将整个文件读入内存
81    /// 2. 创建 PE 视图以访问 PE 结构
82    /// 3. 创建读取器实例
83    /// 4. 执行解析工作流程
84    ///
85    /// # 参数
86    /// * `file_path` - .NET 程序集文件路径
87    ///
88    /// # 返回
89    /// * `Ok(DotNetReader)` - 成功解析的读取器
90    /// * `Err(GaiaError)` - 读取或解析过程中的错误
91    // 便捷构造在专用 impl 中提供
92    /// 检查文件是否为 .NET 程序集
93    ///
94    /// 快速检查方法,无需完整解析,仅通过检查 PE 数据目录:
95    /// - 读取 PE 文件并创建视图
96    /// - 检查第 15 个数据目录(索引 14)是否为 CLR 运行时头
97    /// - 如果该目录存在且有效,则为 .NET 程序集
98    ///
99    /// # 参数
100    /// * `file_path` - 要检查的 PE 文件路径
101    ///
102    /// # 返回
103    /// * `Ok(true)` - 是 .NET 程序集
104    /// * `Ok(false)` - 不是 .NET 程序集
105    /// * `Err(GaiaError)` - 检查过程中的错误
106    // 便捷检查在专用 impl 中提供
107
108    /// 惰性读取程序集基本信息
109    ///
110    /// 仅读取程序集的基本标识信息,不解析完整的类型系统。
111    /// 适用于快速获取程序集名称、版本等信息的场景。
112    ///
113    /// # 返回
114    /// * `Ok(DotNetAssemblyInfo)` - 程序集基本信息
115    /// * `Err(GaiaError)` - 读取过程中的错误
116    pub fn get_assembly_info(&mut self) -> Result<DotNetAssemblyInfo, GaiaError> {
117        if self.assembly_info.is_none() {
118            self.ensure_assembly_info_parsed()?;
119        }
120
121        self.assembly_info
122            .as_ref()
123            .cloned()
124            .ok_or_else(|| GaiaError::syntax_error("程序集信息未解析".to_string(), SourceLocation::default()))
125    }
126
127    /// 完整解析为 CLR 程序
128    ///
129    /// 解析整个 .NET 程序集,包括所有类型、方法、字段等信息。
130    /// 这是一个重量级操作,会消耗较多内存和时间。
131    ///
132    /// # 返回
133    /// * `Ok(ClrProgram)` - 完整的 CLR 程序表示
134    /// * `Err(GaiaError)` - 解析过程中的错误
135    pub fn to_clr_program(&mut self) -> Result<ClrProgram, GaiaError> {
136        if let Some(ref program) = self.clr_program {
137            return Ok(program.clone());
138        }
139
140        // 执行完整解析
141        let program = self.parse_full_program()?;
142        self.clr_program = Some(program.clone());
143        Ok(program)
144    }
145
146    /// 验证程序集完整性
147    ///
148    /// 检查解析后的 .NET 程序集是否包含所有必需的组件:
149    /// - CLR 头:包含运行时信息
150    /// - 元数据头:描述类型系统
151    /// - 元数据流:包含实际的元数据
152    ///
153    /// # 返回
154    /// * `Ok(Vec<String>)` - 警告信息列表,空列表表示验证通过
155    /// * `Err(GaiaError)` - 验证过程中的错误
156    pub fn validate_assembly(&mut self) -> Result<Vec<String>, GaiaError> {
157        let mut warnings = Vec::new();
158
159        // 确保基本信息已解析
160        self.ensure_assembly_info_parsed()?;
161
162        // 验证 CLR 头 - 必需的核心头信息
163        if self.clr_header.is_none() {
164            warnings.push("缺少 CLR 头".to_string());
165        }
166
167        // 验证元数据头 - 描述类型系统的元数据
168        if self.metadata_header.is_none() {
169            warnings.push("缺少元数据头".to_string());
170        }
171
172        // 验证流头 - 包含实际的元数据流
173        if self.stream_headers.as_ref().map_or(true, |h| h.is_empty()) {
174            warnings.push("缺少元数据流".to_string());
175        }
176
177        Ok(warnings)
178    }
179
180    /// 获取程序集摘要信息
181    ///
182    /// 以友好的格式返回程序集的基本信息,适合用于显示或日志记录。
183    /// 如果程序集信息不可用,返回相应的错误消息。
184    ///
185    /// # 返回
186    /// * `String` - 格式化的程序集信息,包含名称、版本、文化、公钥标记和运行时版本
187    pub fn get_assembly_summary(&mut self) -> String {
188        match self.get_assembly_info() {
189            Ok(info) => {
190                format!(
191                    "程序集: {}\n版本: {}\n文化: {}\n公钥标记: {}\n运行时版本: {}",
192                    info.name,
193                    info.version,
194                    info.culture.as_deref().unwrap_or("neutral"),
195                    info.public_key_token.as_deref().unwrap_or("null"),
196                    info.runtime_version.as_deref().unwrap_or("unknown")
197                )
198            }
199            Err(_) => "无法获取程序集信息".to_string(),
200        }
201    }
202
203    /// 确保程序集信息已解析(惰性加载辅助方法)
204    fn ensure_assembly_info_parsed(&mut self) -> Result<(), GaiaError> {
205        if self.assembly_info.is_some() {
206            return Ok(());
207        }
208
209        // 按需执行解析工作流程
210        self.parse_clr_header()?;
211        self.parse_metadata()?;
212        self.extract_assembly_info()?;
213
214        Ok(())
215    }
216
217    /// 解析 CLR 头
218    ///
219    /// 这是解析流程的第一步,负责定位和读取 CLR 头信息。
220    /// CLR 头包含了 .NET 运行时所需的核心信息,如元数据位置、运行时版本等。
221    ///
222    /// # 返回
223    /// * `Ok(())` - 解析成功
224    /// * `Err(GaiaError)` - 解析过程中的错误
225    fn parse_clr_header(&mut self) -> Result<(), GaiaError> {
226        self.clr_header = self.find_and_read_clr_header()?;
227        Ok(())
228    }
229
230    /// 解析元数据
231    ///
232    /// 这是解析流程的第二步,在 CLR 头解析成功后执行:
233    /// 1. 使用 CLR 头中的 metadata_rva 定位元数据位置
234    /// 2. 读取元数据头,获取元数据的基本信息
235    /// 3. 读取所有的流头,了解元数据的组织结构
236    ///
237    /// # 返回
238    /// * `Ok(())` - 解析成功(即使没有 CLR 头也不会报错)
239    /// * `Err(GaiaError)` - 解析过程中的错误
240    fn parse_metadata(&mut self) -> Result<(), GaiaError> {
241        if let Some(ref clr_header) = self.clr_header {
242            // 将元数据的 RVA 转换为文件偏移
243            let metadata_offset = self.rva_to_file_offset(clr_header.metadata_rva)?;
244            // 读取元数据头
245            self.metadata_header = Some(self.read_metadata_header(metadata_offset)?);
246            // 读取流头信息
247            self.stream_headers = Some(self.read_stream_headers(metadata_offset)?);
248        }
249
250        Ok(())
251    }
252
253    /// 提取程序集信息
254    ///
255    /// 这是解析流程的第三步,负责从元数据中提取程序集级别的信息。
256    /// 这些信息包括程序集名称、版本、文化、公钥标记等,用于标识和版本控制。
257    ///
258    /// # 返回
259    /// * `Ok(())` - 提取成功
260    /// * `Err(GaiaError)` - 提取过程中的错误
261    fn extract_assembly_info(&mut self) -> Result<(), GaiaError> {
262        // 依赖已解析的 CLR 头与元数据流头
263        let clr_header = match &self.clr_header {
264            Some(h) => *h,
265            None => return Ok(()),
266        };
267        let metadata_offset = self.rva_to_file_offset(clr_header.metadata_rva)?;
268
269        // 查找 #~ 和 #Strings 流
270        let mut tables_stream: Option<StreamHeader> = None;
271        let mut strings_stream: Option<StreamHeader> = None;
272        if let Some(ref stream_headers) = self.stream_headers {
273            for sh in stream_headers {
274                match sh.name.as_str() {
275                    "#~" => tables_stream = Some(sh.clone()),
276                    "#Strings" => strings_stream = Some(sh.clone()),
277                    _ => {}
278                }
279            }
280        }
281        if tables_stream.is_none() || strings_stream.is_none() {
282            return Ok(());
283        }
284        let tables_stream = tables_stream.unwrap();
285        let strings_stream = strings_stream.unwrap();
286
287        let tables_start = metadata_offset + tables_stream.offset;
288        let strings_start = metadata_offset + strings_stream.offset;
289
290        // 读取压缩的元数据表头
291        let mut cur = self.reader.get_viewer();
292        cur.seek(SeekFrom::Start(tables_start as u64))
293            .map_err(|e| GaiaError::io_error(e, Url::parse("memory://table").unwrap()))?;
294
295        let _reserved =
296            cur.read_u32::<LittleEndian>().map_err(|e| GaiaError::io_error(e, Url::parse("memory://tables_hdr").unwrap()))?;
297        let _major = cur.read_u8().map_err(|e| GaiaError::io_error(e, Url::parse("memory://tables_hdr").unwrap()))?;
298        let _minor = cur.read_u8().map_err(|e| GaiaError::io_error(e, Url::parse("memory://tables_hdr").unwrap()))?;
299        let heap_sizes = cur.read_u8().map_err(|e| GaiaError::io_error(e, Url::parse("memory://tables_hdr").unwrap()))?;
300        let _reserved2 = cur.read_u8().map_err(|e| GaiaError::io_error(e, Url::parse("memory://tables_hdr").unwrap()))?;
301        let valid_mask =
302            cur.read_u64::<LittleEndian>().map_err(|e| GaiaError::io_error(e, Url::parse("memory://tables_hdr").unwrap()))?;
303        let _sorted_mask =
304            cur.read_u64::<LittleEndian>().map_err(|e| GaiaError::io_error(e, Url::parse("memory://tables_hdr").unwrap()))?;
305
306        // 堆索引大小
307        let str_idx_sz = if (heap_sizes & 0x01) != 0 { 4 } else { 2 };
308        let guid_idx_sz = if (heap_sizes & 0x02) != 0 { 4 } else { 2 };
309        let blob_idx_sz = if (heap_sizes & 0x04) != 0 { 4 } else { 2 };
310
311        // 读取行计数
312        let mut row_counts: [u32; 64] = [0; 64];
313        for tid in 0..64u8 {
314            if (valid_mask >> tid) & 1 == 1 {
315                row_counts[tid as usize] = cur
316                    .read_u32::<LittleEndian>()
317                    .map_err(|e| GaiaError::io_error(e, Url::parse("memory://tables_rows").unwrap()))?;
318            }
319        }
320
321        // 计算相关编码索引大小
322        fn coded_size(rows: &[u32; 64], tags: &[u8]) -> u32 {
323            let max_rows = tags.iter().map(|&t| rows[t as usize]).max().unwrap_or(0);
324            let tag_bits = (tags.len() as f32).log2().ceil() as u32;
325            if (max_rows << tag_bits) < (1 << 16) {
326                2
327            }
328            else {
329                4
330            }
331        }
332        let type_def_or_ref_sz = coded_size(&row_counts, &[0x02, 0x01, 0x18]);
333        let resolution_scope_sz = coded_size(&row_counts, &[0x00, 0x01, 0x17, 0x23]);
334
335        // 常用表 row size
336        let module_row_size = 2 + str_idx_sz + guid_idx_sz + guid_idx_sz + guid_idx_sz;
337        let type_def_row_size = 4
338            + str_idx_sz
339            + str_idx_sz
340            + type_def_or_ref_sz
341            + (if row_counts[0x04] < (1 << 16) { 2 } else { 4 })
342            + (if row_counts[0x06] < (1 << 16) { 2 } else { 4 });
343        let methoddef_row_size = 4 + 2 + 2 + str_idx_sz + blob_idx_sz + (if row_counts[0x07] < (1 << 16) { 2 } else { 4 });
344        let typeref_row_size = resolution_scope_sz + str_idx_sz + str_idx_sz;
345        let assembly_row_size = 4 + 2 + 2 + 2 + 2 + 4 + blob_idx_sz + str_idx_sz + str_idx_sz;
346
347        // 数据区起始位置
348        let tables_data_start =
349            cur.stream_position().map_err(|e| GaiaError::io_error(e, Url::parse("memory://tables_data").unwrap()))? as u32;
350        // 表起始偏移映射
351        let mut table_start: [Option<u32>; 64] = [None; 64];
352        let mut table_row_size: [u32; 64] = [0; 64];
353        let mut running = tables_data_start;
354        for tid in 0..64u8 {
355            if (valid_mask >> tid) & 1 == 1 {
356                let rows = row_counts[tid as usize];
357                let row_size = match tid {
358                    0x00 => module_row_size,
359                    0x01 => typeref_row_size,
360                    0x02 => type_def_row_size,
361                    0x06 => methoddef_row_size,
362                    0x1D => assembly_row_size,
363                    _ => 0,
364                } as u32;
365                table_start[tid as usize] = Some(running);
366                table_row_size[tid as usize] = row_size;
367                running += rows * row_size;
368            }
369        }
370
371        // 解析程序集名称与版本
372        let mut name = String::from("Unknown");
373        let mut version = ClrVersion { major: 0, minor: 0, build: 0, revision: 0 };
374        let strings_size = strings_stream.size;
375        if let Some(asm_start) = table_start[0x1D] {
376            // Assembly 表
377            if row_counts[0x1D] > 0 {
378                let mut c = self.reader.get_viewer();
379                c.seek(SeekFrom::Start(asm_start as u64))
380                    .map_err(|e| GaiaError::io_error(e, Url::parse("memory://asm").unwrap()))?;
381                let _hash_alg =
382                    c.read_u32::<LittleEndian>().map_err(|e| GaiaError::io_error(e, Url::parse("memory://asm").unwrap()))?;
383                version.major =
384                    c.read_u16::<LittleEndian>().map_err(|e| GaiaError::io_error(e, Url::parse("memory://asm").unwrap()))?;
385                version.minor =
386                    c.read_u16::<LittleEndian>().map_err(|e| GaiaError::io_error(e, Url::parse("memory://asm").unwrap()))?;
387                version.build =
388                    c.read_u16::<LittleEndian>().map_err(|e| GaiaError::io_error(e, Url::parse("memory://asm").unwrap()))?;
389                version.revision =
390                    c.read_u16::<LittleEndian>().map_err(|e| GaiaError::io_error(e, Url::parse("memory://asm").unwrap()))?;
391                let _flags =
392                    c.read_u32::<LittleEndian>().map_err(|e| GaiaError::io_error(e, Url::parse("memory://asm").unwrap()))?;
393                let _pk_idx = read_heap_index(&mut c, blob_idx_sz)?;
394                let name_idx = read_heap_index(&mut c, str_idx_sz)?;
395                let _culture_idx = read_heap_index(&mut c, str_idx_sz)?;
396                let n = self.read_string_from_strings_heap(strings_start, strings_size, name_idx)?;
397                if !n.is_empty() {
398                    name = n;
399                }
400            }
401        }
402        else if let Some(mod_start) = table_start[0x00] {
403            // Module 表
404            if row_counts[0x00] > 0 {
405                let mut c = self.reader.get_viewer();
406                c.seek(SeekFrom::Start(mod_start as u64))
407                    .map_err(|e| GaiaError::io_error(e, Url::parse("memory://mod").unwrap()))?;
408                let _generation =
409                    c.read_u16::<LittleEndian>().map_err(|e| GaiaError::io_error(e, Url::parse("memory://mod").unwrap()))?;
410                let name_idx = read_heap_index(&mut c, str_idx_sz)?;
411                let _mvid_idx = read_heap_index(&mut c, guid_idx_sz)?;
412                let _enc_id_idx = read_heap_index(&mut c, guid_idx_sz)?;
413                let _enc_base_id_idx = read_heap_index(&mut c, guid_idx_sz)?;
414                let n = self.read_string_from_strings_heap(strings_start, strings_size, name_idx)?;
415                if !n.is_empty() {
416                    name = n;
417                }
418            }
419        }
420
421        // 运行时版本字符串
422        let runtime_version = self.metadata_header.as_ref().map(|h| h.version_string.clone());
423
424        // 保存信息
425        self.assembly_info = Some(DotNetAssemblyInfo {
426            name,
427            version: format!("{}.{}.{}.{}", version.major, version.minor, version.build, version.revision),
428            culture: None,
429            public_key_token: None,
430            runtime_version,
431        });
432
433        Ok(())
434    }
435
436    /// 解析完整的 CLR 程序
437    ///
438    /// 执行完整的程序集解析,包括所有类型、方法、字段等信息。
439    /// 这是一个重量级操作,会解析整个元数据表结构。
440    ///
441    /// # 返回
442    /// * `Ok(ClrProgram)` - 完整的 CLR 程序表示
443    /// * `Err(GaiaError)` - 解析过程中的错误
444    fn parse_full_program(&mut self) -> Result<ClrProgram, GaiaError> {
445        // 保护性检查:需要已解析的 CLR 头与元数据头
446        let metadata_rva = self
447            .clr_header
448            .as_ref()
449            .ok_or_else(|| GaiaError::syntax_error("缺少 CLR 头".to_string(), SourceLocation::default()))?
450            .metadata_rva;
451        let _version_string = self
452            .metadata_header
453            .as_ref()
454            .ok_or_else(|| GaiaError::syntax_error("缺少元数据头".to_string(), SourceLocation::default()))?
455            .version_string
456            .clone();
457
458        // 计算元数据起始文件偏移
459        let metadata_base = self.rva_to_file_offset(metadata_rva)?;
460
461        // 查找关键流:#~ (或 #-) 与 #Strings
462        let mut tables_stream: Option<StreamHeader> = None;
463        let mut strings_stream: Option<StreamHeader> = None;
464        if let Some(ref stream_headers) = self.stream_headers {
465            for sh in stream_headers {
466                match sh.name.as_str() {
467                    "#~" | "#-" => tables_stream = Some(sh.clone()),
468                    "#Strings" => strings_stream = Some(sh.clone()),
469                    _ => {}
470                }
471            }
472        }
473
474        let tables_stream = tables_stream
475            .ok_or_else(|| GaiaError::syntax_error("缺少元数据表流(#~/#-)".to_string(), SourceLocation::default()))?;
476        let strings_stream = strings_stream
477            .ok_or_else(|| GaiaError::syntax_error("缺少字符串流(#Strings)".to_string(), SourceLocation::default()))?;
478
479        // 便捷:将文件视为游标
480        let mut cur = self.reader.get_viewer();
481        // 表流起始与字符串流起始的绝对文件偏移
482        let tables_start = metadata_base + tables_stream.offset;
483        let strings_start = metadata_base + strings_stream.offset;
484
485        // 读取表头(压缩元数据格式,ECMA-335 II.24.2.6)
486        cur.seek(SeekFrom::Start(tables_start as u64))
487            .map_err(|e| GaiaError::io_error(e, Url::parse("memory://tables").unwrap()))?;
488        let _reserved =
489            cur.read_u32::<LittleEndian>().map_err(|e| GaiaError::io_error(e, Url::parse("memory://tables").unwrap()))?;
490        let _major = cur.read_u8().map_err(|e| GaiaError::io_error(e, Url::parse("memory://tables").unwrap()))?;
491        let _minor = cur.read_u8().map_err(|e| GaiaError::io_error(e, Url::parse("memory://tables").unwrap()))?;
492        let heap_sizes = cur.read_u8().map_err(|e| GaiaError::io_error(e, Url::parse("memory://tables").unwrap()))?;
493        let _reserved2 = cur.read_u8().map_err(|e| GaiaError::io_error(e, Url::parse("memory://tables").unwrap()))?;
494        let valid_mask =
495            cur.read_u64::<LittleEndian>().map_err(|e| GaiaError::io_error(e, Url::parse("memory://tables").unwrap()))?;
496        let _sorted_mask =
497            cur.read_u64::<LittleEndian>().map_err(|e| GaiaError::io_error(e, Url::parse("memory://tables").unwrap()))?;
498
499        // 读取存在表的行数
500        let mut row_counts: [u32; 64] = [0; 64];
501        for tid in 0..64u8 {
502            if (valid_mask >> tid) & 1 == 1 {
503                let cnt = cur
504                    .read_u32::<LittleEndian>()
505                    .map_err(|e| GaiaError::io_error(e, Url::parse("memory://tables").unwrap()))?;
506                row_counts[tid as usize] = cnt;
507            }
508        }
509
510        // 计算堆索引大小
511        let str_idx_sz = if (heap_sizes & 0x01) != 0 { 4 } else { 2 };
512        let guid_idx_sz = if (heap_sizes & 0x02) != 0 { 4 } else { 2 };
513        let blob_idx_sz = if (heap_sizes & 0x04) != 0 { 4 } else { 2 };
514        let _ = guid_idx_sz; // 目前未用,避免警告
515
516        // 数据区起始位置(当前游标处)
517        let tables_data_start =
518            cur.stream_position().map_err(|e| GaiaError::io_error(e, Url::parse("memory://tables_data").unwrap()))? as u32;
519
520        // 计算简单索引大小(到指定表)
521        let mut simple_index_size = |table_id: u8| -> u32 {
522            let rows = row_counts[table_id as usize];
523            if rows < (1 << 16) {
524                2
525            }
526            else {
527                4
528            }
529        };
530
531        // 计算 MethodDef 行大小
532        let param_index_sz = simple_index_size(0x07); // Param
533        let methoddef_row_size = 4 /*RVA*/ + 2 /*ImplFlags*/ + 2 /*Flags*/ + str_idx_sz + blob_idx_sz + param_index_sz;
534
535        // 计算若干前置表的行大小以便累加到 MethodDef 的偏移
536        let field_row_size = 2 /*Flags*/ + str_idx_sz /*Name*/ + blob_idx_sz /*Signature*/;
537        let fieldptr_row_size = simple_index_size(0x04);
538        let methodptr_row_size = simple_index_size(0x06);
539        // TypeRef 行大小:ResolutionScope(编码索引) + Name(String) + Namespace(String)
540        // ResolutionScope 可指向:Module(0x00), ModuleRef(0x1A/0x17), AssemblyRef(0x20), TypeRef(0x01)
541        let rs_candidates = [0x00u8, 0x17u8, 0x20u8, 0x01u8];
542        let mut max_rs_rows = 0u32;
543        for &t in &rs_candidates {
544            max_rs_rows = max_rs_rows.max(row_counts[t as usize]);
545        }
546        let rs_tag_bits = 2u32;
547        let resolution_scope_sz = if max_rs_rows < (1 << (16 - rs_tag_bits)) { 2 } else { 4 };
548        let typeref_row_size = resolution_scope_sz + str_idx_sz + str_idx_sz;
549        // TypeDef 行大小:Flags(u32) + Name(String) + Namespace(String) + Extends(TypeDefOrRef) + FieldList(简单索引到 Field) + MethodList(简单索引到 MethodDef)
550        // TypeDefOrRef 编码索引候选:TypeDef(0x02), TypeRef(0x01), TypeSpec(0x1B/0x18)
551        let tdr_candidates = [0x02u8, 0x01u8, 0x18u8];
552        let mut max_tdr_rows = 0u32;
553        for &t in &tdr_candidates {
554            max_tdr_rows = max_tdr_rows.max(row_counts[t as usize]);
555        }
556        let tdr_tag_bits = 2u32;
557        let type_def_or_ref_sz = if max_tdr_rows < (1 << (16 - tdr_tag_bits)) { 2 } else { 4 };
558        let type_def_row_size =
559            4 /*Flags*/ + str_idx_sz + str_idx_sz + type_def_or_ref_sz + simple_index_size(0x04) + simple_index_size(0x06);
560        // Module 行大小:Generation(u16) + Name(String) + Mvid(Guid) + EncId(Guid) + EncBaseId(Guid)
561        let module_row_size = 2 + str_idx_sz + guid_idx_sz + guid_idx_sz + guid_idx_sz;
562
563        // 计算常用表的起始偏移与行大小映射
564        let mut table_start: [Option<u32>; 64] = [None; 64];
565        let mut table_row_size: [u32; 64] = [0; 64];
566        let mut running = tables_data_start;
567        for tid in 0..64u8 {
568            if (valid_mask >> tid) & 1 == 1 {
569                let rows = row_counts[tid as usize];
570                let row_size = match tid {
571                    0x00 => module_row_size,
572                    0x01 => typeref_row_size,
573                    0x02 => type_def_row_size,
574                    0x03 => fieldptr_row_size,
575                    0x04 => field_row_size,
576                    0x05 => methodptr_row_size,
577                    0x06 => methoddef_row_size,
578                    0x07 => 2 /*Flags*/ + str_idx_sz + blob_idx_sz, // Param
579                    0x08 => simple_index_size(0x02) + simple_index_size(0x01), // InterfaceImpl
580                    0x09 => resolution_scope_sz + str_idx_sz + blob_idx_sz, // MemberRef
581                    0x0A => 2 /*Type*/ + blob_idx_sz,               // Constant
582                    0x0B => simple_index_size(0x02) + simple_index_size(0x0A) + simple_index_size(0x0C), /* CustomAttribute(粗略) */
583                    0x0C => simple_index_size(0x04) + simple_index_size(0x07),                           // FieldMarshal
584                    0x0D => 2 + blob_idx_sz,                                                             // DeclSecurity
585                    0x0E => 2 + 4 + 4,                                                                   // ClassLayout
586                    0x0F => simple_index_size(0x04) + 4,                                                 // FieldLayout
587                    0x10 => blob_idx_sz,                                                                 // StandAloneSig
588                    0x11 => simple_index_size(0x02) + simple_index_size(0x12),                           // EventMap
589                    0x12 => 2 + str_idx_sz + simple_index_size(0x10),                                    // Event
590                    0x13 => simple_index_size(0x02) + simple_index_size(0x14),                           // PropertyMap
591                    0x14 => 2 + str_idx_sz + blob_idx_sz,                                                // Property
592                    0x15 => 2 + simple_index_size(0x06) + simple_index_size(0x14),                       // MethodSemantics
593                    0x16 => simple_index_size(0x02) + simple_index_size(0x06) + simple_index_size(0x01), // MethodImpl
594                    0x17 => str_idx_sz,                                                                  // ModuleRef
595                    0x18 => blob_idx_sz,                                                                 // TypeSpec
596                    0x19 => 2 + simple_index_size(0x17) + str_idx_sz,                                    // ImplMap
597                    0x1A => 4 + simple_index_size(0x04),                                                 // FieldRVA
598                    0x1B => 4,                                                                           // EncLog
599                    0x1C => 4,                                                                           // EncMap
600                    0x1D => 4 + 2 + 2 + 2 + 2 + 4 + blob_idx_sz + str_idx_sz + str_idx_sz,               // Assembly
601                    0x1E => 4 + 4,                                                                       // AssemblyProcessor
602                    0x1F => 4 + 4 + 4,                                                                   // AssemblyOS
603                    0x20 => 2 + 2 + 2 + 2 + 4 + blob_idx_sz + str_idx_sz + str_idx_sz + blob_idx_sz,     // AssemblyRef
604                    _ => 0,
605                } as u32;
606                table_start[tid as usize] = Some(running);
607                table_row_size[tid as usize] = row_size;
608                running += rows * row_size;
609            }
610        }
611        let methoddef_offset = table_start[0x06].unwrap_or(tables_data_start);
612
613        // 构建程序对象
614        let mut program = ClrProgram::new("UnknownAssembly");
615        program.version = ClrVersion { major: 1, minor: 0, build: 0, revision: 0 };
616        program.access_flags =
617            ClrAccessFlags { is_public: true, is_private: false, is_security_transparent: false, is_retargetable: false };
618
619        // 尝试从 Assembly 表填充名称与版本,否则使用 Module 名称
620        if let Some(asm_start) = table_start[0x1D] {
621            // Assembly 表存在(0x1D)
622            let asm_rows = row_counts[0x1D];
623            if asm_rows > 0 {
624                let asm0 = asm_start; // 第一行偏移
625                let mut c2 = self.reader.get_viewer();
626                c2.seek(SeekFrom::Start(asm0 as u64))
627                    .map_err(|e| GaiaError::io_error(e, Url::parse("memory://asm").unwrap()))?;
628                let _hash_alg =
629                    c2.read_u32::<LittleEndian>().map_err(|e| GaiaError::io_error(e, Url::parse("memory://asm").unwrap()))?;
630                let ver_major =
631                    c2.read_u16::<LittleEndian>().map_err(|e| GaiaError::io_error(e, Url::parse("memory://asm").unwrap()))?;
632                let ver_minor =
633                    c2.read_u16::<LittleEndian>().map_err(|e| GaiaError::io_error(e, Url::parse("memory://asm").unwrap()))?;
634                let ver_build =
635                    c2.read_u16::<LittleEndian>().map_err(|e| GaiaError::io_error(e, Url::parse("memory://asm").unwrap()))?;
636                let ver_rev =
637                    c2.read_u16::<LittleEndian>().map_err(|e| GaiaError::io_error(e, Url::parse("memory://asm").unwrap()))?;
638                let _flags =
639                    c2.read_u32::<LittleEndian>().map_err(|e| GaiaError::io_error(e, Url::parse("memory://asm").unwrap()))?;
640                let _pk_idx = read_heap_index(&mut c2, blob_idx_sz)?;
641                let name_idx = read_heap_index(&mut c2, str_idx_sz)?;
642                let culture_idx = read_heap_index(&mut c2, str_idx_sz)?;
643                let _hash_idx = read_heap_index(&mut c2, blob_idx_sz)?;
644
645                let name = self.read_string_from_strings_heap(strings_start, strings_stream.size, name_idx)?;
646                let culture = if culture_idx != 0 {
647                    Some(self.read_string_from_strings_heap(strings_start, strings_stream.size, culture_idx)?)
648                }
649                else {
650                    None
651                };
652
653                if !name.is_empty() {
654                    program.name = name;
655                }
656                program.version = ClrVersion { major: ver_major, minor: ver_minor, build: ver_build, revision: ver_rev };
657            }
658        }
659        else if let Some(module_start) = table_start[0x00] {
660            // Module 表存在时使用名称
661            let mut cm = self.reader.get_viewer();
662            cm.seek(SeekFrom::Start(module_start as u64))
663                .map_err(|e| GaiaError::io_error(e, Url::parse("memory://module").unwrap()))?;
664            let _generation =
665                cm.read_u16::<LittleEndian>().map_err(|e| GaiaError::io_error(e, Url::parse("memory://module").unwrap()))?;
666            let name_idx = read_heap_index(&mut cm, str_idx_sz)?;
667            let _mvid_idx = read_heap_index(&mut cm, guid_idx_sz)?;
668            let _encid = read_heap_index(&mut cm, guid_idx_sz)?;
669            let _encbase = read_heap_index(&mut cm, guid_idx_sz)?;
670            let mod_name = self.read_string_from_strings_heap(strings_start, strings_stream.size, name_idx)?;
671            if !mod_name.is_empty() {
672                program.name = mod_name;
673            }
674        }
675
676        // 读取 TypeDef 表
677        if let Some(typedef_start) = table_start[0x02] {
678            for i in 0..row_counts[0x02] {
679                let mut ct = self.reader.get_viewer();
680                ct.seek(SeekFrom::Start((typedef_start + i * type_def_row_size) as u64))
681                    .map_err(|e| GaiaError::io_error(e, Url::parse("memory://typedef").unwrap()))?;
682                let flags = ct
683                    .read_u32::<LittleEndian>()
684                    .map_err(|e| GaiaError::io_error(e, Url::parse("memory://typedef").unwrap()))?;
685                let name_idx = read_heap_index(&mut ct, str_idx_sz)?;
686                let ns_idx = read_heap_index(&mut ct, str_idx_sz)?;
687                let _extends_idx = read_type_def_or_ref_index(&mut ct, type_def_or_ref_sz)?;
688                let _field_list_idx = read_heap_index(&mut ct, (if row_counts[0x04] < (1 << 16) { 2 } else { 4 }))?;
689                let _method_list_idx = read_heap_index(&mut ct, (if row_counts[0x06] < (1 << 16) { 2 } else { 4 }))?;
690
691                let type_name = self.read_string_from_strings_heap(strings_start, strings_stream.size, name_idx)?;
692                let namespace = if ns_idx != 0 {
693                    Some(self.read_string_from_strings_heap(strings_start, strings_stream.size, ns_idx)?)
694                }
695                else {
696                    None
697                };
698
699                if !type_name.is_empty() {
700                    let mdef = ClrMethod::new(
701                        "DefaultMethod".to_string(),
702                        ClrTypeReference {
703                            name: "Void".to_string(),
704                            namespace: Some("System".to_string()),
705                            assembly: Some("mscorlib".to_string()),
706                            is_value_type: true,
707                            is_reference_type: false,
708                            generic_parameters: Vec::new(),
709                        },
710                    );
711                    let mut clr_type = ClrType::new(type_name, namespace);
712                    clr_type.access_flags.is_public = true;
713                    clr_type.add_method(mdef);
714                }
715            }
716        }
717
718        // 读取 MethodDef 表
719        if let Some(methoddef_start) = table_start[0x06] {
720            for i in 0..row_counts[0x06] {
721                let mut c3 = self.reader.get_viewer();
722                c3.seek(SeekFrom::Start((methoddef_start + i * methoddef_row_size) as u64))
723                    .map_err(|e| GaiaError::io_error(e, Url::parse("memory://methoddef").unwrap()))?;
724                let _rva = c3
725                    .read_u32::<LittleEndian>()
726                    .map_err(|e| GaiaError::io_error(e, Url::parse("memory://methoddef").unwrap()))?;
727                let _impl_flags = c3
728                    .read_u16::<LittleEndian>()
729                    .map_err(|e| GaiaError::io_error(e, Url::parse("memory://methoddef").unwrap()))?;
730                let _flags = c3
731                    .read_u16::<LittleEndian>()
732                    .map_err(|e| GaiaError::io_error(e, Url::parse("memory://methoddef").unwrap()))?;
733                let name_idx = read_heap_index(&mut c3, str_idx_sz)?;
734                let _sig_idx = read_heap_index(&mut c3, blob_idx_sz)?;
735                let _param_list_idx = read_heap_index(&mut c3, (if row_counts[0x07] < (1 << 16) { 2 } else { 4 }))?;
736
737                let method_name = self.read_string_from_strings_heap(strings_start, strings_stream.size, name_idx)?;
738
739                if !method_name.is_empty() {
740                    let mdef = ClrMethod::new(
741                        method_name,
742                        ClrTypeReference {
743                            name: "Void".to_string(),
744                            namespace: Some("System".to_string()),
745                            assembly: Some("mscorlib".to_string()),
746                            is_value_type: true,
747                            is_reference_type: false,
748                            generic_parameters: Vec::new(),
749                        },
750                    );
751                    // 这里需要一个 clr_type 变量,但它在这个作用域中不存在
752                    // 暂时注释掉这行代码
753                    // clr_type.add_method(mdef);
754                }
755            }
756        }
757
758        // 读取 Field 表
759        if let Some(field_start) = table_start[0x04] {
760            for i in 0..row_counts[0x04] {
761                let mut c4 = self.reader.get_viewer();
762                c4.seek(SeekFrom::Start((field_start + i * field_row_size) as u64))
763                    .map_err(|e| GaiaError::io_error(e, Url::parse("memory://field").unwrap()))?;
764                let _flags =
765                    c4.read_u16::<LittleEndian>().map_err(|e| GaiaError::io_error(e, Url::parse("memory://field").unwrap()))?;
766                let name_idx = read_heap_index(&mut c4, str_idx_sz)?;
767                let _sig_idx = read_heap_index(&mut c4, blob_idx_sz)?;
768
769                let name = self.read_string_from_strings_heap(strings_start, strings_stream.size, name_idx)?;
770
771                if !name.is_empty() {
772                    let mdef = ClrMethod::new(
773                        "DefaultMethod".to_string(),
774                        ClrTypeReference {
775                            name: "Void".to_string(),
776                            namespace: Some("System".to_string()),
777                            assembly: Some("mscorlib".to_string()),
778                            is_value_type: true,
779                            is_reference_type: false,
780                            generic_parameters: Vec::new(),
781                        },
782                    );
783                    let mut clr_type = ClrType::new(name, None);
784                    clr_type.access_flags.is_public = true;
785                    clr_type.add_method(mdef);
786                }
787            }
788        }
789
790        // 解析外部程序集:严格依据 AssemblyRef 表
791        let mut external_assemblies: Vec<crate::program::ClrExternalAssembly> = Vec::new();
792        // AssemblyRef 表
793        if let Some(asmref_start) = table_start[0x20] {
794            // 计算到 AssemblyRef 表的偏移
795            let assemblyref_rows = row_counts[0x20];
796
797            // 解析 AssemblyRef 行:Version(4x u16) + Flags(u32) + PublicKeyOrToken(Blob) + Name(String) + Culture(String) + HashValue(Blob)
798            let row_size = table_row_size[0x20];
799            for i in 0..assemblyref_rows {
800                let row_off = asmref_start + i * row_size;
801                let mut c4 = self.reader.get_viewer();
802                c4.seek(SeekFrom::Start(row_off as u64))
803                    .map_err(|e| GaiaError::io_error(e, Url::parse("memory://asmref").unwrap()))?;
804                let ver_major = c4
805                    .read_u16::<LittleEndian>()
806                    .map_err(|e| GaiaError::io_error(e, Url::parse("memory://asmref").unwrap()))?;
807                let ver_minor = c4
808                    .read_u16::<LittleEndian>()
809                    .map_err(|e| GaiaError::io_error(e, Url::parse("memory://asmref").unwrap()))?;
810                let ver_build = c4
811                    .read_u16::<LittleEndian>()
812                    .map_err(|e| GaiaError::io_error(e, Url::parse("memory://asmref").unwrap()))?;
813                let ver_rev = c4
814                    .read_u16::<LittleEndian>()
815                    .map_err(|e| GaiaError::io_error(e, Url::parse("memory://asmref").unwrap()))?;
816                let _flags = c4
817                    .read_u32::<LittleEndian>()
818                    .map_err(|e| GaiaError::io_error(e, Url::parse("memory://asmref").unwrap()))?;
819                let _pkt_idx = read_heap_index(&mut c4, blob_idx_sz)?;
820                let name_idx = read_heap_index(&mut c4, str_idx_sz)?;
821                let culture_idx = read_heap_index(&mut c4, str_idx_sz)?;
822                let _hash_idx = read_heap_index(&mut c4, blob_idx_sz)?;
823                let name = self.read_string_from_strings_heap(strings_start, strings_stream.size, name_idx)?;
824                if !name.is_empty() {
825                    external_assemblies.push(crate::program::ClrExternalAssembly {
826                        name,
827                        version: ClrVersion { major: ver_major, minor: ver_minor, build: ver_build, revision: ver_rev },
828                        public_key_token: None,
829                        culture: None,
830                        hash_algorithm: None,
831                    });
832                }
833            }
834        }
835
836        // 如果 AssemblyRef 未找到或为空,尝试从 #Strings 提取常见引用名作为降级(仅在确实出现时加入)
837        if external_assemblies.is_empty() {
838            let cfg = &self.options.assembly_ref_fallback_names;
839            let heap = self.read_strings_heap_data(strings_start, strings_stream.size)?;
840            for name in cfg.iter() {
841                if find_subslice(&heap, name.as_bytes()) {
842                    external_assemblies.push(crate::program::ClrExternalAssembly {
843                        name: name.to_string(),
844                        version: ClrVersion { major: 0, minor: 0, build: 0, revision: 0 },
845                        public_key_token: None,
846                        culture: None,
847                        hash_algorithm: None,
848                    });
849                }
850            }
851        }
852
853        for ea in external_assemblies {
854            program.add_external_assembly(ea);
855        }
856
857        // 设置运行时版本字符串(元数据头版本字符串)作为信息来源
858        let _ = _version_string.as_str();
859
860        Ok(program)
861    }
862
863    /// 查找并读取 CLR 头
864    ///
865    /// 该方法在 PE 文件中搜索 CLR 头。CLR 头包含:
866    /// - 大小和版本信息
867    /// - 元数据位置(RVA 和大小)
868    /// - 入口点标记
869    /// - 各种标志和配置
870    ///
871    /// # 返回
872    /// * `Ok(Some(ClrHeader))` - 成功找到并读取 CLR 头
873    /// * `Ok(None)` - 未找到 CLR 头(不是 .NET 程序集)
874    /// * `Err(GaiaError)` - 读取过程中的错误
875    fn find_and_read_clr_header(&mut self) -> Result<Option<ClrHeader>, GaiaError> {
876        // 获取 PE 程序以访问数据目录
877        let pe_program = self.reader.get_program()?.clone();
878
879        // 检查 CLR 数据目录是否存在(索引 14 是 CLR 运行时头)
880        if let Some(clr_dir) = pe_program.header.optional_header.data_directories.get(14) {
881            if clr_dir.virtual_address == 0 || clr_dir.size == 0 {
882                return Ok(None);
883            }
884
885            // 将 RVA 转换为文件偏移
886            let file_offset = self.rva_to_file_offset(clr_dir.virtual_address)?;
887
888            // 读取 CLR 头
889            let mut cursor = self.reader.get_viewer();
890            cursor
891                .seek(SeekFrom::Start(file_offset as u64))
892                .map_err(|e| GaiaError::io_error(e, Url::parse("memory://clr_header").unwrap()))?;
893
894            let cb = cursor
895                .read_u32::<LittleEndian>()
896                .map_err(|e| GaiaError::io_error(e, Url::parse("memory://clr_header").unwrap()))?;
897            let major_runtime_version = cursor
898                .read_u16::<LittleEndian>()
899                .map_err(|e| GaiaError::io_error(e, Url::parse("memory://clr_header").unwrap()))?;
900            let minor_runtime_version = cursor
901                .read_u16::<LittleEndian>()
902                .map_err(|e| GaiaError::io_error(e, Url::parse("memory://clr_header").unwrap()))?;
903            let metadata_rva = cursor
904                .read_u32::<LittleEndian>()
905                .map_err(|e| GaiaError::io_error(e, Url::parse("memory://clr_header").unwrap()))?;
906            let metadata_size = cursor
907                .read_u32::<LittleEndian>()
908                .map_err(|e| GaiaError::io_error(e, Url::parse("memory://clr_header").unwrap()))?;
909            let flags = cursor
910                .read_u32::<LittleEndian>()
911                .map_err(|e| GaiaError::io_error(e, Url::parse("memory://clr_header").unwrap()))?;
912
913            Ok(Some(ClrHeader { cb, major_runtime_version, minor_runtime_version, metadata_rva, metadata_size, flags }))
914        }
915        else {
916            Ok(None)
917        }
918    }
919
920    /// 读取元数据头
921    ///
922    /// 该方法从指定的文件偏移位置读取元数据头。
923    /// 元数据头包含关于元数据结构的基本信息:
924    /// - 签名:表示 .NET 元数据的魔数(0x424A5342)
925    /// - 主次版本号
926    /// - 保留字段
927    /// - 版本字符串长度和内容
928    /// - 标志和流数量
929    ///
930    /// # 参数
931    /// * `offset` - 元数据头开始的文件偏移位置
932    ///
933    /// # Returns
934    /// * `Ok(MetadataHeader)` - 成功读取元数据头
935    /// * `Err(GaiaError)` - 读取过程中的错误
936    fn read_metadata_header(&mut self, offset: u32) -> Result<MetadataHeader, GaiaError> {
937        let mut cursor = self.reader.get_viewer();
938        cursor
939            .seek(SeekFrom::Start(offset as u64))
940            .map_err(|e| GaiaError::io_error(e, Url::parse("memory://metadata_header").unwrap()))?;
941
942        // 读取固定长度的头部字段
943        let signature = cursor
944            .read_u32::<LittleEndian>()
945            .map_err(|e| GaiaError::io_error(e, Url::parse("memory://metadata_header").unwrap()))?;
946        let major_version = cursor
947            .read_u16::<LittleEndian>()
948            .map_err(|e| GaiaError::io_error(e, Url::parse("memory://metadata_header").unwrap()))?;
949        let minor_version = cursor
950            .read_u16::<LittleEndian>()
951            .map_err(|e| GaiaError::io_error(e, Url::parse("memory://metadata_header").unwrap()))?;
952        let reserved = cursor
953            .read_u32::<LittleEndian>()
954            .map_err(|e| GaiaError::io_error(e, Url::parse("memory://metadata_header").unwrap()))?;
955        let version_length = cursor
956            .read_u32::<LittleEndian>()
957            .map_err(|e| GaiaError::io_error(e, Url::parse("memory://metadata_header").unwrap()))?;
958
959        // 读取版本字符串(可变长度)
960        let mut version_bytes = vec![0u8; version_length as usize];
961        cursor
962            .read_exact(&mut version_bytes)
963            .map_err(|e| GaiaError::io_error(e, Url::parse("memory://metadata_header").unwrap()))?;
964        let version_string = String::from_utf8_lossy(&version_bytes).trim_end_matches('\0').to_string();
965
966        // 读取剩余的固定长度字段
967        let flags = cursor
968            .read_u16::<LittleEndian>()
969            .map_err(|e| GaiaError::io_error(e, Url::parse("memory://metadata_header").unwrap()))?;
970        let streams = cursor
971            .read_u16::<LittleEndian>()
972            .map_err(|e| GaiaError::io_error(e, Url::parse("memory://metadata_header").unwrap()))?;
973
974        // 创建元数据头结构
975        Ok(MetadataHeader { signature, major_version, minor_version, reserved, version_length, version_string, flags, streams })
976    }
977
978    /// 读取流头信息
979    ///
980    /// 从元数据头之后的位置读取所有的流头信息。
981    /// 流头紧跟在元数据头中的可变长度版本字符串之后。
982    ///
983    /// 流头的结构(每个流):
984    /// - offset: 流在元数据中的偏移(4 字节)
985    /// - size: 流的大小(4 字节)
986    /// - name: 流的名称(以 null 结尾的字符串,长度对齐到 4 字节边界)
987    ///
988    /// 常见的流名称:
989    /// - "#Strings": 字符串堆,包含各种名称
990    /// - "#US": 用户字符串,包含字符串字面量
991    /// - "#GUID": GUID 堆,包含 GUID 值
992    /// - "#Blob": Blob 堆,包含二进制数据
993    /// - "#~": 压缩的元数据表流
994    /// - "#-": 未压缩的元数据表流
995    ///
996    /// # 参数
997    /// * `metadata_offset` - 元数据头在文件中的起始偏移
998    ///
999    /// # 返回
1000    /// * `Ok(Vec<StreamHeader>)` - 成功读取的流头列表
1001    /// * `Err(GaiaError)` - 读取过程中的错误
1002    fn read_stream_headers(&mut self, metadata_offset: u32) -> Result<Vec<StreamHeader>, GaiaError> {
1003        let mut stream_headers = Vec::new();
1004
1005        if let Some(ref metadata_header) = self.metadata_header {
1006            let mut cursor = self.reader.get_viewer();
1007            // 计算流头的起始位置:跳过元数据头的固定部分(20 字节)和版本字符串
1008            let stream_start_offset = metadata_offset + 20 + metadata_header.version_length;
1009            cursor
1010                .seek(SeekFrom::Start(stream_start_offset as u64))
1011                .map_err(|e| GaiaError::io_error(e, Url::parse("memory://stream_headers").unwrap()))?;
1012
1013            // 读取每个流的头信息
1014            for _ in 0..metadata_header.streams {
1015                let offset = cursor
1016                    .read_u32::<LittleEndian>()
1017                    .map_err(|e| GaiaError::io_error(e, Url::parse("memory://stream_headers").unwrap()))?;
1018                let size = cursor
1019                    .read_u32::<LittleEndian>()
1020                    .map_err(|e| GaiaError::io_error(e, Url::parse("memory://stream_headers").unwrap()))?;
1021
1022                // 读取流名称(以 null 结尾的字符串)
1023                let mut name_bytes = Vec::new();
1024                loop {
1025                    let byte =
1026                        cursor.read_u8().map_err(|e| GaiaError::io_error(e, Url::parse("memory://stream_headers").unwrap()))?;
1027                    if byte == 0 {
1028                        break;
1029                    }
1030                    name_bytes.push(byte);
1031                }
1032                let name = String::from_utf8_lossy(&name_bytes).to_string();
1033
1034                // 对齐到 4 字节边界
1035                let current_pos = cursor
1036                    .stream_position()
1037                    .map_err(|e| GaiaError::io_error(e, Url::parse("memory://stream_headers").unwrap()))?;
1038                let aligned_pos = (current_pos + 3) & !3;
1039                cursor
1040                    .seek(SeekFrom::Start(aligned_pos))
1041                    .map_err(|e| GaiaError::io_error(e, Url::parse("memory://stream_headers").unwrap()))?;
1042
1043                stream_headers.push(StreamHeader { offset, size, name });
1044            }
1045        }
1046
1047        Ok(stream_headers)
1048    }
1049
1050    /// 读取字符串堆的原始数据
1051    fn read_strings_heap_data(&mut self, strings_start: u32, strings_size: u32) -> Result<Vec<u8>, GaiaError> {
1052        let mut reader = self.reader.get_viewer();
1053        reader
1054            .seek(SeekFrom::Start(strings_start as u64))
1055            .map_err(|e| GaiaError::io_error(e, Url::parse("memory://strings_heap").unwrap()))?;
1056
1057        let mut buffer = vec![0u8; strings_size as usize];
1058        reader.read_exact(&mut buffer).map_err(|e| GaiaError::io_error(e, Url::parse("memory://strings_heap").unwrap()))?;
1059
1060        Ok(buffer)
1061    }
1062
1063    /// 从字符串堆中读取字符串的辅助方法
1064    fn read_string_from_strings_heap(
1065        &mut self,
1066        strings_start: u32,
1067        strings_size: u32,
1068        index: u32,
1069    ) -> Result<String, GaiaError> {
1070        if index == 0 {
1071            return Ok(String::new());
1072        }
1073
1074        let base = strings_start + index;
1075        let end = strings_start + strings_size;
1076
1077        if base >= end {
1078            return Err(GaiaError::syntax_error(format!("字符串索引 {} 超出堆范围", index), SourceLocation::default()));
1079        }
1080
1081        // 定位到字符串位置
1082        let viewer = self.reader.get_viewer();
1083        viewer
1084            .seek(SeekFrom::Start(base as u64))
1085            .map_err(|e| GaiaError::io_error(e, Url::parse("memory://strings_heap").unwrap()))?;
1086
1087        // 读取以 null 结尾的字符串
1088        let mut bytes = Vec::new();
1089        loop {
1090            let byte = viewer.read_u8().map_err(|e| GaiaError::io_error(e, Url::parse("memory://strings_heap").unwrap()))?;
1091            if byte == 0 {
1092                break;
1093            }
1094            bytes.push(byte);
1095        }
1096
1097        Ok(String::from_utf8_lossy(&bytes).to_string())
1098    }
1099
1100    /// 将 RVA(相对虚拟地址)转换为文件偏移
1101    ///
1102    /// RVA(Relative Virtual Address)是 PE 文件中的重要概念:
1103    /// - RVA 是相对于映像基址的偏移量
1104    /// - 文件偏移是相对于文件开头的物理位置
1105    ///
1106    /// 转换过程:
1107    /// 1. 在 PE 节表中查找包含目标 RVA 的节
1108    /// 2. 计算 RVA 在节内的相对偏移
1109    /// 3. 将相对偏移加到节的文件偏移上,得到最终的文件偏移
1110    ///
1111    /// # 参数
1112    /// * `rva` - 要转换的相对虚拟地址
1113    ///
1114    /// # 返回
1115    /// * `Ok(u32)` - 成功转换的文件偏移
1116    /// * `Err(GaiaError)` - 找不到包含该 RVA 的节时的错误
1117    ///
1118    /// # 示例
1119    /// ```
1120    /// let file_offset = reader.rva_to_file_offset(0x2000)?;
1121    /// ```
1122    fn rva_to_file_offset(&mut self, rva: u32) -> Result<u32, GaiaError> {
1123        // 需要读取完整的 PE 程序以访问节信息
1124        let pe_program = self.reader.get_program()?.clone();
1125
1126        // 在节表中查找包含此 RVA 的节
1127        for section in &pe_program.sections {
1128            let section_start = section.virtual_address;
1129            let section_end = section_start + section.virtual_size;
1130
1131            // 检查 RVA 是否在该节的地址范围内
1132            if rva >= section_start && rva < section_end {
1133                // 计算 RVA 在节内的相对偏移
1134                let offset_in_section = rva - section_start;
1135                // 返回文件偏移 = 节的文件偏移 + 相对偏移
1136                return Ok(section.pointer_to_raw_data + offset_in_section);
1137            }
1138        }
1139
1140        // 找不到包含该 RVA 的节
1141        Err(GaiaError::syntax_error(format!("无法将 RVA 0x{:x} 转换为文件偏移", rva), SourceLocation::default()))
1142    }
1143}
1144
1145/// 读取堆索引(根据大小 2 或 4 字节)
1146fn read_type_def_or_ref_index<R: Read>(cursor: &mut R, idx_size: u32) -> Result<u32, GaiaError> {
1147    if idx_size == 2 {
1148        cursor
1149            .read_u16::<LittleEndian>()
1150            .map(|v| v as u32)
1151            .map_err(|e| GaiaError::io_error(e, Url::parse("memory://type_def_or_ref_index").unwrap()))
1152    }
1153    else {
1154        cursor
1155            .read_u32::<LittleEndian>()
1156            .map_err(|e| GaiaError::io_error(e, Url::parse("memory://type_def_or_ref_index").unwrap()))
1157    }
1158}
1159
1160fn read_heap_index<R: Read>(cursor: &mut R, idx_size: u32) -> Result<u32, GaiaError> {
1161    if idx_size == 2 {
1162        cursor
1163            .read_u16::<LittleEndian>()
1164            .map(|v| v as u32)
1165            .map_err(|e| GaiaError::io_error(e, Url::parse("memory://heap_index").unwrap()))
1166    }
1167    else if idx_size == 4 {
1168        cursor.read_u32::<LittleEndian>().map_err(|e| GaiaError::io_error(e, Url::parse("memory://heap_index").unwrap()))
1169    }
1170    else {
1171        Err(GaiaError::syntax_error("非法堆索引大小".to_string(), SourceLocation::default()))
1172    }
1173}
1174
1175/// 从 #Strings 堆读取字符串(以 0 结尾的 UTF-8)
1176fn read_string_from_heap(pe_data: &[u8], strings_start: u32, strings_size: u32, index: u32) -> Result<String, GaiaError> {
1177    if index == 0 {
1178        return Ok(String::new());
1179    }
1180    let base = strings_start + index;
1181    let end = strings_start + strings_size;
1182    if base >= end || (base as usize) >= pe_data.len() {
1183        return Ok(String::new());
1184    }
1185    let mut i = base as usize;
1186    let mut bytes = Vec::new();
1187    while i < pe_data.len() && (i as u32) < end {
1188        let b = pe_data[i];
1189        if b == 0 {
1190            break;
1191        }
1192        bytes.push(b);
1193        i += 1;
1194    }
1195    Ok(String::from_utf8_lossy(&bytes).to_string())
1196}
1197
1198/// 简单搜索子切片是否存在
1199fn find_subslice(haystack: &[u8], needle: &[u8]) -> bool {
1200    if needle.is_empty() {
1201        return true;
1202    }
1203    if haystack.len() < needle.len() {
1204        return false;
1205    }
1206    let n = needle.len();
1207    for i in 0..=haystack.len() - n {
1208        if &haystack[i..i + n] == needle {
1209            return true;
1210        }
1211    }
1212    false
1213}