pe_assembler/formats/lib/reader/
mod.rs1use 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#[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 }
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() }
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 }
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 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 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 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 fn read_library_force(&mut self) -> Result<StaticLibrary, GaiaError> {
128 if !self.is_valid_lib()? {
130 return Err(GaiaError::invalid_data("不是有效的静态库文件"));
131 }
132
133 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 while self.get_position()? < file_size {
145 let current_pos = self.get_position()?;
146 println!("当前位置: {}, 剩余: {} bytes", current_pos, file_size - current_pos);
147
148 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 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 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 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 }
190 else {
191 println!("发现普通成员: {}", member.header.name);
192 }
194 members.push(member);
195 }
196 Err(e) => {
197 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 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 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 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 if header.size % 2 == 1 {
240 self.reader.read_u8()?;
241 }
242
243 let coff_object = if data.len() > 20 {
245 None
249 }
250 else {
251 None
252 };
253
254 Ok(ArchiveMember { header, data, coff_object })
255 }
256
257 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 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 return Ok(symbols);
271 }
272
273 let string_table_start = 4 + symbol_count * 4;
275
276 if string_table_start >= data.len() {
277 return Ok(symbols);
278 }
279
280 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 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 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 let name_str = std::str::from_utf8(&name).map_err(|_| GaiaError::invalid_data("无效的名称字段"))?;
333 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); 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}