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::{
15    io::{ Read, Seek, SeekFrom},
16};
17use url::Url;
18
19#[derive(Debug)]
20pub struct DllReader<'config, R> {
21    /// 配置选项
22    options: &'config DllReadConfig,
23    reader: pe_assembler::formats::dll::reader::DllReader<R>,
24    /// 解析后的 CLR 头信息
25    clr_header: Option<ClrHeader>,
26    /// 解析后的元数据头信息
27    metadata_header: Option<MetadataHeader>,
28    /// 元数据流头信息列表(惰性加载)
29    stream_headers: Option<Vec<StreamHeader>>,
30    /// 提取的程序集基本信息(惰性加载)
31    assembly_info: Option<DotNetAssemblyInfo>,
32    /// 完整解析的 CLR 程序(惰性加载)
33    clr_program: Option<ClrProgram>,
34}
35
36impl<'config, R: Read + Seek> PeReader<R> for DllReader<'config, R> {
37    fn get_viewer(&mut self) -> &mut R {
38        self.reader.get_viewer()
39    }
40
41    fn add_diagnostics(&mut self, error: impl Into<GaiaError>) {
42        self.reader.add_diagnostics(error)
43    }
44
45    fn get_section_headers(&mut self) -> Result<&[SectionHeader], GaiaError> {
46        self.reader.get_section_headers()
47    }
48
49    fn get_pe_header(&mut self) -> Result<&PeHeader, GaiaError> {
50        self.reader.get_pe_header()
51    }
52
53    fn get_program(&mut self) -> Result<&PeProgram, GaiaError> {
54        self.reader.get_program()
55    }
56}
57
58impl<'config, R> DllReader<'config, R> {
59    /// 使用泛型 PE 读取器构造 .NET 读取器(DLL)
60    ///
61    /// 注意:这是惰性构造函数,不会立即执行解析工作流程
62    pub fn new(reader: R, options: &'config DllReadConfig) -> Self {
63        Self {
64            reader: pe_assembler::formats::dll::reader::DllReader::new(reader),
65            clr_header: None,
66            metadata_header: None,
67            stream_headers: None,
68            assembly_info: None,
69            clr_program: None,
70            options,
71        }
72    }
73}
74
75impl<'config, R> DllReader<'config, R>
76where
77    R: Read + Seek,
78{
79    /// 从文件读取 .NET 程序集
80    ///
81    /// 该方法读取并解析 .NET 程序集文件,步骤如下:
82    /// 1. 将整个文件读入内存
83    /// 2. 创建 PE 视图以访问 PE 结构
84    /// 3. 创建读取器实例
85    /// 4. 执行解析工作流程
86    ///
87    /// # 参数
88    /// * `file_path` - .NET 程序集文件路径
89    ///
90    /// # 返回
91    /// * `Ok(DotNetReader)` - 成功解析的读取器
92    /// * `Err(GaiaError)` - 读取或解析过程中的错误
93    // 便捷构造在专用 impl 中提供
94    /// 检查文件是否为 .NET 程序集
95    ///
96    /// 快速检查方法,无需完整解析,仅通过检查 PE 数据目录:
97    /// - 读取 PE 文件并创建视图
98    /// - 检查第 15 个数据目录(索引 14)是否为 CLR 运行时头
99    /// - 如果该目录存在且有效,则为 .NET 程序集
100    ///
101    /// # 参数
102    /// * `file_path` - 要检查的 PE 文件路径
103    ///
104    /// # 返回
105    /// * `Ok(true)` - 是 .NET 程序集
106    /// * `Ok(false)` - 不是 .NET 程序集
107    /// * `Err(GaiaError)` - 检查过程中的错误
108    // 便捷检查在专用 impl 中提供
109
110    /// 惰性读取程序集基本信息
111    ///
112    /// 仅读取程序集的基本标识信息,不解析完整的类型系统。
113    /// 适用于快速获取程序集名称、版本等信息的场景。
114    ///
115    /// # 返回
116    /// * `Ok(DotNetAssemblyInfo)` - 程序集基本信息
117    /// * `Err(GaiaError)` - 读取过程中的错误
118    pub fn get_assembly_info(&mut self) -> Result<DotNetAssemblyInfo, GaiaError> {
119        if self.assembly_info.is_none() {
120            self.ensure_assembly_info_parsed()?;
121        }
122
123        self.assembly_info
124            .as_ref()
125            .cloned()
126            .ok_or_else(|| GaiaError::syntax_error("程序集信息未解析".to_string(), SourceLocation::default()))
127    }
128
129    /// 完整解析为 CLR 程序
130    ///
131    /// 解析整个 .NET 程序集,包括所有类型、方法、字段等信息。
132    /// 这是一个重量级操作,会消耗较多内存和时间。
133    ///
134    /// # 返回
135    /// * `Ok(ClrProgram)` - 完整的 CLR 程序表示
136    /// * `Err(GaiaError)` - 解析过程中的错误
137    pub fn to_clr_program(&mut self) -> Result<ClrProgram, GaiaError> {
138        if let Some(ref program) = self.clr_program {
139            return Ok(program.clone());
140        }
141
142        // 执行完整解析
143        let program = self.parse_full_program()?;
144        self.clr_program = Some(program.clone());
145        Ok(program)
146    }
147
148    /// 验证程序集完整性
149    ///
150    /// 检查解析后的 .NET 程序集是否包含所有必需的组件:
151    /// - CLR 头:包含运行时信息
152    /// - 元数据头:描述类型系统
153    /// - 元数据流:包含实际的元数据
154    ///
155    /// # 返回
156    /// * `Ok(Vec<String>)` - 警告信息列表,空列表表示验证通过
157    /// * `Err(GaiaError)` - 验证过程中的错误
158    pub fn validate_assembly(&mut self) -> Result<Vec<String>, GaiaError> {
159        let mut warnings = Vec::new();
160
161        // 确保基本信息已解析
162        self.ensure_assembly_info_parsed()?;
163
164        // 验证 CLR 头 - 必需的核心头信息
165        if self.clr_header.is_none() {
166            warnings.push("缺少 CLR 头".to_string());
167        }
168
169        // 验证元数据头 - 描述类型系统的元数据
170        if self.metadata_header.is_none() {
171            warnings.push("缺少元数据头".to_string());
172        }
173
174        // 验证流头 - 包含实际的元数据流
175        if self.stream_headers.as_ref().map_or(true, |h| h.is_empty()) {
176            warnings.push("缺少元数据流".to_string());
177        }
178
179        Ok(warnings)
180    }
181
182    /// 获取程序集摘要信息
183    ///
184    /// 以友好的格式返回程序集的基本信息,适合用于显示或日志记录。
185    /// 如果程序集信息不可用,返回相应的错误消息。
186    ///
187    /// # 返回
188    /// * `String` - 格式化的程序集信息,包含名称、版本、文化、公钥标记和运行时版本
189    pub fn get_assembly_summary(&mut self) -> String {
190        match self.get_assembly_info() {
191            Ok(info) => {
192                format!(
193                    "程序集: {}\n版本: {}\n文化: {}\n公钥标记: {}\n运行时版本: {}",
194                    info.name,
195                    info.version,
196                    info.culture.as_deref().unwrap_or("neutral"),
197                    info.public_key_token.as_deref().unwrap_or("null"),
198                    info.runtime_version.as_deref().unwrap_or("unknown")
199                )
200            }
201            Err(_) => "无法获取程序集信息".to_string(),
202        }
203    }
204
205    /// 确保程序集信息已解析(惰性加载辅助方法)
206    fn ensure_assembly_info_parsed(&mut self) -> Result<(), GaiaError> {
207        if self.assembly_info.is_some() {
208            return Ok(());
209        }
210
211        // 按需执行解析工作流程
212        self.parse_clr_header()?;
213        self.parse_metadata()?;
214        self.extract_assembly_info()?;
215
216        Ok(())
217    }
218
219    /// 解析 CLR 头
220    ///
221    /// 这是解析流程的第一步,负责定位和读取 CLR 头信息。
222    /// CLR 头包含了 .NET 运行时所需的核心信息,如元数据位置、运行时版本等。
223    ///
224    /// # 返回
225    /// * `Ok(())` - 解析成功
226    /// * `Err(GaiaError)` - 解析过程中的错误
227    fn parse_clr_header(&mut self) -> Result<(), GaiaError> {
228        self.clr_header = self.find_and_read_clr_header()?;
229        Ok(())
230    }
231
232    /// 解析元数据
233    ///
234    /// 这是解析流程的第二步,在 CLR 头解析成功后执行:
235    /// 1. 使用 CLR 头中的 metadata_rva 定位元数据位置
236    /// 2. 读取元数据头,获取元数据的基本信息
237    /// 3. 读取所有的流头,了解元数据的组织结构
238    ///
239    /// # 返回
240    /// * `Ok(())` - 解析成功(即使没有 CLR 头也不会报错)
241    /// * `Err(GaiaError)` - 解析过程中的错误
242    fn parse_metadata(&mut self) -> Result<(), GaiaError> {
243        if let Some(ref clr_header) = self.clr_header {
244            // 将元数据的 RVA 转换为文件偏移
245            let metadata_offset = self.rva_to_file_offset(clr_header.metadata_rva)?;
246            // 读取元数据头
247            self.metadata_header = Some(self.read_metadata_header(metadata_offset)?);
248            // 读取流头信息
249            self.stream_headers = Some(self.read_stream_headers(metadata_offset)?);
250        }
251
252        Ok(())
253    }
254
255    /// 提取程序集信息
256    ///
257    /// 这是解析流程的第三步,负责从元数据中提取程序集级别的信息。
258    /// 这些信息包括程序集名称、版本、文化、公钥标记等,用于标识和版本控制。
259    ///
260    /// # 返回
261    /// * `Ok(())` - 提取成功
262    /// * `Err(GaiaError)` - 提取过程中的错误
263    fn extract_assembly_info(&mut self) -> Result<(), GaiaError> {
264        // 依赖已解析的 CLR 头与元数据流头
265        let clr_header = match &self.clr_header {
266            Some(h) => *h,
267            None => return Ok(()),
268        };
269        let metadata_offset = self.rva_to_file_offset(clr_header.metadata_rva)?;
270
271        // 查找 #~ 和 #Strings 流
272        let mut tables_stream: Option<StreamHeader> = None;
273        let mut strings_stream: Option<StreamHeader> = None;
274        if let Some(ref stream_headers) = self.stream_headers {
275            for sh in stream_headers {
276                match sh.name.as_str() {
277                    "#~" => tables_stream = Some(sh.clone()),
278                    "#Strings" => strings_stream = Some(sh.clone()),
279                    _ => {}
280                }
281            }
282        }
283        if tables_stream.is_none() || strings_stream.is_none() {
284            return Ok(());
285        }
286        let tables_stream = tables_stream.unwrap();
287        let strings_stream = strings_stream.unwrap();
288
289        let tables_start = metadata_offset + tables_stream.offset;
290        let strings_start = metadata_offset + strings_stream.offset;
291
292        // 读取压缩的元数据表头
293        let mut cur = self.reader.get_viewer();
294        cur.seek(SeekFrom::Start(tables_start as u64))
295            .map_err(|e| GaiaError::io_error(e, Url::parse("memory://table").unwrap()))?;
296
297        let _reserved =
298            cur.read_u32::<LittleEndian>().map_err(|e| GaiaError::io_error(e, Url::parse("memory://tables_hdr").unwrap()))?;
299        let _major = cur.read_u8().map_err(|e| GaiaError::io_error(e, Url::parse("memory://tables_hdr").unwrap()))?;
300        let _minor = cur.read_u8().map_err(|e| GaiaError::io_error(e, Url::parse("memory://tables_hdr").unwrap()))?;
301        let heap_sizes = cur.read_u8().map_err(|e| GaiaError::io_error(e, Url::parse("memory://tables_hdr").unwrap()))?;
302        let _reserved2 = cur.read_u8().map_err(|e| GaiaError::io_error(e, Url::parse("memory://tables_hdr").unwrap()))?;
303        let valid_mask =
304            cur.read_u64::<LittleEndian>().map_err(|e| GaiaError::io_error(e, Url::parse("memory://tables_hdr").unwrap()))?;
305        let _sorted_mask =
306            cur.read_u64::<LittleEndian>().map_err(|e| GaiaError::io_error(e, Url::parse("memory://tables_hdr").unwrap()))?;
307
308        // 堆索引大小
309        let str_idx_sz = if (heap_sizes & 0x01) != 0 { 4 } else { 2 };
310        let guid_idx_sz = if (heap_sizes & 0x02) != 0 { 4 } else { 2 };
311        let blob_idx_sz = if (heap_sizes & 0x04) != 0 { 4 } else { 2 };
312
313        // 读取行计数
314        let mut row_counts: [u32; 64] = [0; 64];
315        for tid in 0..64u8 {
316            if (valid_mask >> tid) & 1 == 1 {
317                row_counts[tid as usize] = cur
318                    .read_u32::<LittleEndian>()
319                    .map_err(|e| GaiaError::io_error(e, Url::parse("memory://tables_rows").unwrap()))?;
320            }
321        }
322
323        // 计算相关编码索引大小
324        fn coded_size(rows: &[u32; 64], tags: &[u8]) -> u32 {
325            let max_rows = tags.iter().map(|&t| rows[t as usize]).max().unwrap_or(0);
326            let tag_bits = (tags.len() as f32).log2().ceil() as u32;
327            if (max_rows << tag_bits) < (1 << 16) {
328                2
329            }
330            else {
331                4
332            }
333        }
334        let type_def_or_ref_sz = coded_size(&row_counts, &[0x02, 0x01, 0x18]);
335        let resolution_scope_sz = coded_size(&row_counts, &[0x00, 0x01, 0x17, 0x23]);
336
337        // 常用表 row size
338        let module_row_size = 2 + str_idx_sz + guid_idx_sz + guid_idx_sz + guid_idx_sz;
339        let type_def_row_size = 4
340            + str_idx_sz
341            + str_idx_sz
342            + type_def_or_ref_sz
343            + (if row_counts[0x04] < (1 << 16) { 2 } else { 4 })
344            + (if row_counts[0x06] < (1 << 16) { 2 } else { 4 });
345        let methoddef_row_size = 4 + 2 + 2 + str_idx_sz + blob_idx_sz + (if row_counts[0x07] < (1 << 16) { 2 } else { 4 });
346        let typeref_row_size = resolution_scope_sz + str_idx_sz + str_idx_sz;
347        let assembly_row_size = 4 + 2 + 2 + 2 + 2 + 4 + blob_idx_sz + str_idx_sz + str_idx_sz;
348
349        // 数据区起始位置
350        let tables_data_start = cur.stream_position().map_err(|e| GaiaError::io_error(e, Url::parse("memory://tables_data").unwrap()))? as u32;
351        // 表起始偏移映射
352        let mut table_start: [Option<u32>; 64] = [None; 64];
353        let mut table_row_size: [u32; 64] = [0; 64];
354        let mut running = tables_data_start;
355        for tid in 0..64u8 {
356            if (valid_mask >> tid) & 1 == 1 {
357                let rows = row_counts[tid as usize];
358                let row_size = match tid {
359                    0x00 => module_row_size,
360                    0x01 => typeref_row_size,
361                    0x02 => type_def_row_size,
362                    0x06 => methoddef_row_size,
363                    0x1D => assembly_row_size,
364                    _ => 0,
365                } as u32;
366                table_start[tid as usize] = Some(running);
367                table_row_size[tid as usize] = row_size;
368                running += rows * row_size;
369            }
370        }
371
372        // 解析程序集名称与版本
373        let mut name = String::from("Unknown");
374        let mut version = ClrVersion { major: 0, minor: 0, build: 0, revision: 0 };
375        let strings_size = strings_stream.size;
376        if let Some(asm_start) = table_start[0x1D] {
377            // Assembly 表
378            if row_counts[0x1D] > 0 {
379                let mut c = self.reader.get_viewer();
380                c.seek(SeekFrom::Start(asm_start as u64))
381                    .map_err(|e| GaiaError::io_error(e, Url::parse("memory://asm").unwrap()))?;
382                let _hash_alg =
383                    c.read_u32::<LittleEndian>().map_err(|e| GaiaError::io_error(e, Url::parse("memory://asm").unwrap()))?;
384                version.major =
385                    c.read_u16::<LittleEndian>().map_err(|e| GaiaError::io_error(e, Url::parse("memory://asm").unwrap()))?;
386                version.minor =
387                    c.read_u16::<LittleEndian>().map_err(|e| GaiaError::io_error(e, Url::parse("memory://asm").unwrap()))?;
388                version.build =
389                    c.read_u16::<LittleEndian>().map_err(|e| GaiaError::io_error(e, Url::parse("memory://asm").unwrap()))?;
390                version.revision =
391                    c.read_u16::<LittleEndian>().map_err(|e| GaiaError::io_error(e, Url::parse("memory://asm").unwrap()))?;
392                let _flags =
393                    c.read_u32::<LittleEndian>().map_err(|e| GaiaError::io_error(e, Url::parse("memory://asm").unwrap()))?;
394                let _pk_idx = read_heap_index(&mut c, blob_idx_sz)?;
395                let name_idx = read_heap_index(&mut c, str_idx_sz)?;
396                let _culture_idx = read_heap_index(&mut c, str_idx_sz)?;
397                let n = self.read_string_from_strings_heap(strings_start, strings_size, name_idx)?;
398                if !n.is_empty() {
399                    name = n;
400                }
401            }
402        }
403        else if let Some(mod_start) = table_start[0x00] {
404            // Module 表
405            if row_counts[0x00] > 0 {
406                let mut c = self.reader.get_viewer();
407                c.seek(SeekFrom::Start(mod_start as u64))
408                    .map_err(|e| GaiaError::io_error(e, Url::parse("memory://mod").unwrap()))?;
409                let _generation =
410                    c.read_u16::<LittleEndian>().map_err(|e| GaiaError::io_error(e, Url::parse("memory://mod").unwrap()))?;
411                let name_idx = read_heap_index(&mut c, str_idx_sz)?;
412                let _mvid_idx = read_heap_index(&mut c, guid_idx_sz)?;
413                let _enc_id_idx = read_heap_index(&mut c, guid_idx_sz)?;
414                let _enc_base_id_idx = read_heap_index(&mut c, guid_idx_sz)?;
415                let n = self.read_string_from_strings_heap(strings_start, strings_size, name_idx)?;
416                if !n.is_empty() {
417                    name = n;
418                }
419            }
420        }
421
422        // 运行时版本字符串
423        let runtime_version = self.metadata_header.as_ref().map(|h| h.version_string.clone());
424
425        // 保存信息
426        self.assembly_info = Some(DotNetAssemblyInfo {
427            name,
428            version: format!("{}.{}.{}.{}", version.major, version.minor, version.build, version.revision),
429            culture: None,
430            public_key_token: None,
431            runtime_version,
432        });
433
434        Ok(())
435    }
436
437    /// 解析完整的 CLR 程序
438    ///
439    /// 执行完整的程序集解析,包括所有类型、方法、字段等信息。
440    /// 这是一个重量级操作,会解析整个元数据表结构。
441    ///
442    /// # 返回
443    /// * `Ok(ClrProgram)` - 完整的 CLR 程序表示
444    /// * `Err(GaiaError)` - 解析过程中的错误
445    fn parse_full_program(&mut self) -> Result<ClrProgram, GaiaError> {
446        // 保护性检查:需要已解析的 CLR 头与元数据头
447        let metadata_rva = self
448            .clr_header
449            .as_ref()
450            .ok_or_else(|| GaiaError::syntax_error("缺少 CLR 头".to_string(), SourceLocation::default()))?
451            .metadata_rva;
452        let _version_string = self
453            .metadata_header
454            .as_ref()
455            .ok_or_else(|| GaiaError::syntax_error("缺少元数据头".to_string(), SourceLocation::default()))?
456            .version_string
457            .clone();
458
459        // 计算元数据起始文件偏移
460        let metadata_base = self.rva_to_file_offset(metadata_rva)?;
461
462        // 查找关键流:#~ (或 #-) 与 #Strings
463        let mut tables_stream: Option<StreamHeader> = None;
464        let mut strings_stream: Option<StreamHeader> = None;
465        if let Some(ref stream_headers) = self.stream_headers {
466            for sh in stream_headers {
467                match sh.name.as_str() {
468                    "#~" | "#-" => tables_stream = Some(sh.clone()),
469                    "#Strings" => strings_stream = Some(sh.clone()),
470                    _ => {}
471                }
472            }
473        }
474
475        let tables_stream = tables_stream
476            .ok_or_else(|| GaiaError::syntax_error("缺少元数据表流(#~/#-)".to_string(), SourceLocation::default()))?;
477        let strings_stream = strings_stream
478            .ok_or_else(|| GaiaError::syntax_error("缺少字符串流(#Strings)".to_string(), SourceLocation::default()))?;
479
480        // 便捷:将文件视为游标
481        let mut cur = self.reader.get_viewer();
482        // 表流起始与字符串流起始的绝对文件偏移
483        let tables_start = metadata_base + tables_stream.offset;
484        let strings_start = metadata_base + strings_stream.offset;
485
486        // 读取表头(压缩元数据格式,ECMA-335 II.24.2.6)
487        cur.seek(SeekFrom::Start(tables_start as u64))
488            .map_err(|e| GaiaError::io_error(e, Url::parse("memory://tables").unwrap()))?;
489        let _reserved =
490            cur.read_u32::<LittleEndian>().map_err(|e| GaiaError::io_error(e, Url::parse("memory://tables").unwrap()))?;
491        let _major = cur.read_u8().map_err(|e| GaiaError::io_error(e, Url::parse("memory://tables").unwrap()))?;
492        let _minor = cur.read_u8().map_err(|e| GaiaError::io_error(e, Url::parse("memory://tables").unwrap()))?;
493        let heap_sizes = cur.read_u8().map_err(|e| GaiaError::io_error(e, Url::parse("memory://tables").unwrap()))?;
494        let _reserved2 = cur.read_u8().map_err(|e| GaiaError::io_error(e, Url::parse("memory://tables").unwrap()))?;
495        let valid_mask =
496            cur.read_u64::<LittleEndian>().map_err(|e| GaiaError::io_error(e, Url::parse("memory://tables").unwrap()))?;
497        let _sorted_mask =
498            cur.read_u64::<LittleEndian>().map_err(|e| GaiaError::io_error(e, Url::parse("memory://tables").unwrap()))?;
499
500        // 读取存在表的行数
501        let mut row_counts: [u32; 64] = [0; 64];
502        for tid in 0..64u8 {
503            if (valid_mask >> tid) & 1 == 1 {
504                let cnt = cur
505                    .read_u32::<LittleEndian>()
506                    .map_err(|e| GaiaError::io_error(e, Url::parse("memory://tables").unwrap()))?;
507                row_counts[tid as usize] = cnt;
508            }
509        }
510
511        // 计算堆索引大小
512        let str_idx_sz = if (heap_sizes & 0x01) != 0 { 4 } else { 2 };
513        let guid_idx_sz = if (heap_sizes & 0x02) != 0 { 4 } else { 2 };
514        let blob_idx_sz = if (heap_sizes & 0x04) != 0 { 4 } else { 2 };
515        let _ = guid_idx_sz; // 目前未用,避免警告
516
517        // 数据区起始位置(当前游标处)
518        let tables_data_start = 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.stream_position().map_err(|e| GaiaError::io_error(e, Url::parse("memory://stream_headers").unwrap()))?;
1036                let aligned_pos = (current_pos + 3) & !3;
1037                cursor
1038                    .seek(SeekFrom::Start(aligned_pos))
1039                    .map_err(|e| GaiaError::io_error(e, Url::parse("memory://stream_headers").unwrap()))?;
1040
1041                stream_headers.push(StreamHeader { offset, size, name });
1042            }
1043        }
1044
1045        Ok(stream_headers)
1046    }
1047
1048    /// 读取字符串堆的原始数据
1049    fn read_strings_heap_data(&mut self, strings_start: u32, strings_size: u32) -> Result<Vec<u8>, GaiaError> {
1050        let mut reader = self.reader.get_viewer();
1051        reader
1052            .seek(SeekFrom::Start(strings_start as u64))
1053            .map_err(|e| GaiaError::io_error(e, Url::parse("memory://strings_heap").unwrap()))?;
1054        
1055        let mut buffer = vec![0u8; strings_size as usize];
1056        reader
1057            .read_exact(&mut buffer)
1058            .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    } else {
1153        cursor
1154            .read_u32::<LittleEndian>()
1155            .map_err(|e| GaiaError::io_error(e, Url::parse("memory://type_def_or_ref_index").unwrap()))
1156    }
1157}
1158
1159fn read_heap_index<R: Read>(cursor: &mut R, idx_size: u32) -> Result<u32, GaiaError> {
1160    if idx_size == 2 {
1161        cursor
1162            .read_u16::<LittleEndian>()
1163            .map(|v| v as u32)
1164            .map_err(|e| GaiaError::io_error(e, Url::parse("memory://heap_index").unwrap()))
1165    }
1166    else if idx_size == 4 {
1167        cursor.read_u32::<LittleEndian>().map_err(|e| GaiaError::io_error(e, Url::parse("memory://heap_index").unwrap()))
1168    }
1169    else {
1170        Err(GaiaError::syntax_error("非法堆索引大小".to_string(), SourceLocation::default()))
1171    }
1172}
1173
1174/// 从 #Strings 堆读取字符串(以 0 结尾的 UTF-8)
1175fn read_string_from_heap(pe_data: &[u8], strings_start: u32, strings_size: u32, index: u32) -> Result<String, GaiaError> {
1176    if index == 0 {
1177        return Ok(String::new());
1178    }
1179    let base = strings_start + index;
1180    let end = strings_start + strings_size;
1181    if base >= end || (base as usize) >= pe_data.len() {
1182        return Ok(String::new());
1183    }
1184    let mut i = base as usize;
1185    let mut bytes = Vec::new();
1186    while i < pe_data.len() && (i as u32) < end {
1187        let b = pe_data[i];
1188        if b == 0 {
1189            break;
1190        }
1191        bytes.push(b);
1192        i += 1;
1193    }
1194    Ok(String::from_utf8_lossy(&bytes).to_string())
1195}
1196
1197/// 简单搜索子切片是否存在
1198fn find_subslice(haystack: &[u8], needle: &[u8]) -> bool {
1199    if needle.is_empty() {
1200        return true;
1201    }
1202    if haystack.len() < needle.len() {
1203        return false;
1204    }
1205    let n = needle.len();
1206    for i in 0..=haystack.len() - n {
1207        if &haystack[i..i + n] == needle {
1208            return true;
1209        }
1210    }
1211    false
1212}