Skip to main content

pe_assembler/formats/lib/reader/
mod.rs

1use crate::{
2    helpers::CoffReader,
3    types::{
4        coff::{ArchiveMember, ArchiveMemberHeader, CoffFileType, CoffInfo, StaticLibrary},
5        CoffHeader, CoffObject, SectionHeader,
6    },
7};
8use byteorder::ReadBytesExt;
9use gaia_types::{
10    helpers::{Architecture, Url},
11    GaiaDiagnostics, GaiaError,
12};
13use std::io::{Read, Seek};
14
15/// LIB 结构,惰性读取器
16#[derive(Debug)]
17pub struct LibReader<R> {
18    reader: R,
19    url: Option<Url>,
20    lazy_library: Option<StaticLibrary>,
21    lazy_info: Option<CoffInfo>,
22    errors: Vec<GaiaError>,
23}
24
25impl<R> LibReader<R> {
26    pub fn new(reader: R) -> Self {
27        Self { reader, url: None, lazy_library: None, lazy_info: None, errors: vec![] }
28    }
29    pub fn with_url(mut self, url: Url) -> Self {
30        self.url = Some(url);
31        self
32    }
33    pub fn finish(mut self) -> GaiaDiagnostics<StaticLibrary>
34    where
35        R: Read + Seek,
36    {
37        if self.lazy_library.is_none() {
38            if let Err(e) = self.read_library() {
39                return GaiaDiagnostics { result: Err(e), diagnostics: self.errors };
40            }
41        }
42        match self.lazy_library {
43            Some(s) => GaiaDiagnostics { result: Ok(s), diagnostics: self.errors },
44            None => unreachable!(),
45        }
46    }
47}
48
49impl<R: Read + Seek> CoffReader<R> for LibReader<R> {
50    fn get_viewer(&mut self) -> &mut R {
51        &mut self.reader
52    }
53
54    fn add_diagnostics(&mut self, error: impl Into<GaiaError>) {
55        self.errors.push(error.into())
56    }
57
58    fn get_coff_header(&mut self) -> Result<&CoffHeader, GaiaError> {
59        Err(GaiaError::not_implemented("LibReader 不支持直接读取 COFF 头,请使用成员对象"))
60    }
61
62    fn set_coff_header(&mut self, _head: CoffHeader) -> Option<CoffHeader> {
63        None // LibReader 不支持设置 COFF 头
64    }
65
66    fn get_section_headers(&mut self) -> Result<&[SectionHeader], GaiaError> {
67        Err(GaiaError::not_implemented("LibReader 不支持直接读取节头,请使用成员对象"))
68    }
69
70    fn set_section_headers(&mut self, _headers: Vec<SectionHeader>) -> Vec<SectionHeader> {
71        Vec::new() // LibReader 不支持设置节头
72    }
73
74    fn get_coff_object(&mut self) -> Result<&CoffObject, GaiaError> {
75        Err(GaiaError::not_implemented("LibReader 不支持直接读取 COFF 对象,请使用成员对象"))
76    }
77
78    fn set_coff_object(&mut self, _object: CoffObject) -> Option<CoffObject> {
79        None // LibReader 不支持设置 COFF 对象
80    }
81
82    fn get_coff_info(&mut self) -> Result<&CoffInfo, GaiaError> {
83        if self.lazy_info.is_none() {
84            let info = self.create_lib_info()?;
85            self.lazy_info = Some(info);
86        }
87        Ok(self.lazy_info.as_ref().unwrap())
88    }
89
90    fn set_coff_info(&mut self, info: CoffInfo) -> Option<CoffInfo> {
91        self.lazy_info.replace(info)
92    }
93}
94
95impl<R: Read + Seek> LibReader<R> {
96    /// 检测是否为有效的静态库文件
97    pub fn is_valid_lib(&mut self) -> Result<bool, GaiaError> {
98        let mut magic = [0u8; 8];
99        self.reader.read_exact(&mut magic)?;
100        self.reader.seek(std::io::SeekFrom::Start(0))?;
101        Ok(&magic == b"!<arch>\n")
102    }
103
104    /// 查看静态库文件信息
105    pub fn view(&mut self) -> Result<CoffInfo, GaiaError> {
106        if let Some(ref info) = self.lazy_info {
107            return Ok(info.clone());
108        }
109
110        let info = self.create_lib_info()?;
111        self.lazy_info = Some(info.clone());
112        Ok(info)
113    }
114
115    /// 读取静态库
116    pub fn read_library(&mut self) -> Result<&StaticLibrary, GaiaError> {
117        if self.lazy_library.is_none() {
118            self.lazy_library = Some(self.read_library_force()?);
119        }
120        match self.lazy_library.as_ref() {
121            Some(s) => Ok(s),
122            None => unreachable!(),
123        }
124    }
125
126    /// 强制读取静态库(不使用缓存)
127    fn read_library_force(&mut self) -> Result<StaticLibrary, GaiaError> {
128        // 验证文件头
129        if !self.is_valid_lib()? {
130            return Err(GaiaError::invalid_data("不是有效的静态库文件"));
131        }
132
133        // 跳过文件头 "!<arch>\n" (8字节)
134        self.reader.seek(std::io::SeekFrom::Start(8))?;
135
136        let mut members = Vec::new();
137        let mut symbol_index = Vec::new();
138        let file_size = self.get_file_size()?;
139
140        println!("开始解析库文件,文件大小: {} bytes", file_size);
141        println!("跳过文件头后,从位置8开始读取成员");
142
143        // 读取所有成员
144        while self.get_position()? < file_size {
145            let current_pos = self.get_position()?;
146            println!("当前位置: {}, 剩余: {} bytes", current_pos, file_size - current_pos);
147
148            // 检查是否还有足够的数据读取成员头(60字节)
149            if current_pos + 60 > file_size {
150                println!("剩余数据不足60字节,停止解析");
151                break;
152            }
153
154            match self.read_member() {
155                Ok(member) => {
156                    println!("读取到成员: '{}', 大小: {} bytes", member.header.name, member.header.size);
157
158                    // 检查是否是符号表(支持传统格式"/"和现代格式"/<ECSYMBOLS>")
159                    if member.header.name == "/" || member.header.name.starts_with("/<ECSYMBOLS>") {
160                        println!("发现符号表: '{}', 开始解析符号", member.header.name);
161                        println!("符号表数据大小: {} bytes", member.data.len());
162                        if member.data.len() >= 4 {
163                            let symbol_count_be =
164                                u32::from_be_bytes([member.data[0], member.data[1], member.data[2], member.data[3]]);
165                            println!("符号表头部显示符号数量: {}", symbol_count_be);
166                            // 打印前16个字节的十六进制内容
167                            let preview_len = std::cmp::min(16, member.data.len());
168                            let hex_preview: String =
169                                member.data[..preview_len].iter().map(|b| format!("{:02X}", b)).collect::<Vec<_>>().join(" ");
170                            println!("符号表前{}字节内容: {}", preview_len, hex_preview);
171                        }
172                        // 这是符号表,解析符号
173                        match self.parse_symbol_table(&member.data, members.len()) {
174                            Ok(symbols) => {
175                                println!("成功解析 {} 个符号", symbols.len());
176                                if !symbols.is_empty() {
177                                    println!("前5个符号: {:?}", &symbols[..std::cmp::min(5, symbols.len())]);
178                                }
179                                symbol_index.extend(symbols);
180                            }
181                            Err(e) => {
182                                println!("符号表解析失败: {:?}", e);
183                            }
184                        }
185                    }
186                    else if member.header.name == "//" {
187                        println!("发现扩展名称表,跳过");
188                        // 这是扩展名称表,跳过
189                    }
190                    else {
191                        println!("发现普通成员: {}", member.header.name);
192                        // 这是普通成员
193                    }
194                    members.push(member);
195                }
196                Err(e) => {
197                    // 如果读取失败,记录错误但继续
198                    println!("读取成员失败: {:?}", e);
199                    self.add_diagnostics(e);
200                    break;
201                }
202            }
203        }
204
205        println!("解析完成,总成员数: {}, 总符号数: {}", members.len(), symbol_index.len());
206        Ok(StaticLibrary { signature: "!<arch>\n".to_string(), members, symbol_index })
207    }
208
209    /// 创建库信息
210    fn create_lib_info(&mut self) -> Result<CoffInfo, GaiaError> {
211        let file_size = self.get_file_size()?;
212        let library = self.read_library()?;
213
214        Ok(CoffInfo {
215            file_type: CoffFileType::StaticLibrary,
216            target_arch: Architecture::Unknown,
217            section_count: 0,
218            symbol_count: library.symbol_index.len() as u32,
219            file_size,
220            timestamp: 0,
221        })
222    }
223
224    /// 获取文件大小
225    pub fn get_file_size(&mut self) -> Result<u64, GaiaError> {
226        let current_pos = self.get_position()?;
227        let size = self.reader.seek(std::io::SeekFrom::End(0))?;
228        self.set_position(current_pos)?;
229        Ok(size)
230    }
231
232    /// 读取成员
233    fn read_member(&mut self) -> Result<ArchiveMember, GaiaError> {
234        let header = self.read_member_header()?;
235        let mut data = vec![0u8; header.size as usize];
236        self.reader.read_exact(&mut data)?;
237
238        // 对齐到偶数边界
239        if header.size % 2 == 1 {
240            self.reader.read_u8()?;
241        }
242
243        // 尝试解析 COFF 对象(如果数据是有效的 COFF 格式)
244        let coff_object = if data.len() > 20 {
245            // 尝试从数据中读取 COFF 对象
246            // 这里暂时返回 None,因为需要一个具体的 CoffReader 实现
247            // TODO: 实现一个简单的 COFF 对象解析器
248            None
249        }
250        else {
251            None
252        };
253
254        Ok(ArchiveMember { header, data, coff_object })
255    }
256
257    /// 解析符号表
258    fn parse_symbol_table(&self, data: &[u8], member_index: usize) -> Result<Vec<(String, usize)>, GaiaError> {
259        let mut symbols = Vec::new();
260
261        if data.len() < 4 {
262            return Ok(symbols);
263        }
264
265        // 读取符号数量(前4个字节,大端序)
266        let symbol_count = u32::from_be_bytes([data[0], data[1], data[2], data[3]]) as usize;
267
268        if symbol_count == 0 || symbol_count > 100000 {
269            // 符号数量不合理,可能不是标准的符号表格式
270            return Ok(symbols);
271        }
272
273        // 跳过符号偏移表(每个符号4字节偏移)
274        let string_table_start = 4 + symbol_count * 4;
275
276        if string_table_start >= data.len() {
277            return Ok(symbols);
278        }
279
280        // 解析字符串表
281        let string_data = &data[string_table_start..];
282        let mut current_pos = 0;
283
284        while current_pos < string_data.len() && symbols.len() < symbol_count {
285            // 查找下一个null终止符
286            if let Some(null_pos) = string_data[current_pos..].iter().position(|&b| b == 0) {
287                if null_pos > 0 {
288                    if let Ok(symbol_name) = std::str::from_utf8(&string_data[current_pos..current_pos + null_pos]) {
289                        symbols.push((symbol_name.to_string(), member_index));
290                    }
291                }
292                current_pos += null_pos + 1;
293            }
294            else {
295                break;
296            }
297        }
298
299        Ok(symbols)
300    }
301
302    /// 读取成员头
303    fn read_member_header(&mut self) -> Result<ArchiveMemberHeader, GaiaError> {
304        let mut name = [0u8; 16];
305        self.reader.read_exact(&mut name)?;
306
307        let mut date = [0u8; 12];
308        self.reader.read_exact(&mut date)?;
309
310        let mut uid = [0u8; 6];
311        self.reader.read_exact(&mut uid)?;
312
313        let mut gid = [0u8; 6];
314        self.reader.read_exact(&mut gid)?;
315
316        let mut mode = [0u8; 8];
317        self.reader.read_exact(&mut mode)?;
318
319        let mut size = [0u8; 10];
320        self.reader.read_exact(&mut size)?;
321
322        let mut end_chars = [0u8; 2];
323        self.reader.read_exact(&mut end_chars)?;
324
325        println!("成员头结束符: {:02X} {:02X} (期望: 60 0A)", end_chars[0], end_chars[1]);
326
327        if &end_chars != b"`\n" {
328            return Err(GaiaError::invalid_data("无效的成员头结束符"));
329        }
330
331        // 解析字段 - ar格式的字段都是ASCII字符串,右填充空格
332        let name_str = std::str::from_utf8(&name).map_err(|_| GaiaError::invalid_data("无效的名称字段"))?;
333        // ar格式中名称以斜杠结尾,然后用空格填充
334        let name = name_str.trim_end_matches(' ').trim_end_matches('/').to_string();
335
336        let date_str = std::str::from_utf8(&date).map_err(|_| GaiaError::invalid_data("无效的日期字段"))?;
337        let timestamp = date_str.trim_end_matches(' ').parse::<u32>().unwrap_or(0);
338
339        let uid_str = std::str::from_utf8(&uid).map_err(|_| GaiaError::invalid_data("无效的用户ID字段"))?;
340        let user_id = uid_str.trim_end_matches(' ').parse::<u16>().unwrap_or(0);
341
342        let gid_str = std::str::from_utf8(&gid).map_err(|_| GaiaError::invalid_data("无效的组ID字段"))?;
343        let group_id = gid_str.trim_end_matches(' ').parse::<u16>().unwrap_or(0);
344
345        let mode_str = std::str::from_utf8(&mode).map_err(|_| GaiaError::invalid_data("无效的模式字段"))?;
346        let mode = u32::from_str_radix(mode_str.trim_end_matches(' '), 8).unwrap_or(0); // 模式字段是八进制
347
348        let size_str = std::str::from_utf8(&size).map_err(|_| GaiaError::invalid_data("无效的大小字段"))?;
349        let size = size_str.trim_end_matches(' ').parse::<u32>().unwrap_or(0);
350        Ok(ArchiveMemberHeader { name, timestamp, user_id, group_id, mode, size })
351    }
352}