Rust提取PDB信息时如何延长变量生命周期解决借用问题
解决Rust PDB符号提取中的生命周期错误
我正在编写一个提取PDB信息的脚本,目前遇到info变量生命周期过短的问题,运行代码时触发“borrowed value does not live long enough”错误。我明白这是info.symbols()的借用导致的,但不知道如何修复。请问该如何将符号项添加到mod_symbols中?
相关库代码
pub struct PDB<'s, S> { msf: Box<dyn Msf<'s, S> + 's>, dbi_header: Option<DBIHeader>, dbi_extra_streams: Option<DBIExtraStreams>, } impl<'s, S: Source<'s> + 's> PDB<'s, S> { pub fn module_info<'m>(&mut self, module: &Module<'m>) -> Result<Option<ModuleInfo<'s>>> { Ok(self .raw_stream(module.info().stream)? .map(|stream| ModuleInfo::parse(stream, module))) } } pub struct ModuleInfo<'s> { stream: Stream<'s>, symbols_size: usize, lines_size: LinesSize, } impl<'s> ModuleInfo<'s> { /// Get an iterator over the all symbols in this module. pub fn symbols(&self) -> Result<SymbolIter<'_>> { let mut buf = self.stream.parse_buffer(); buf.truncate(self.symbols_size)?; if self.symbols_size > 0 { let sig = buf.parse_u32()?; if sig != constants::CV_SIGNATURE_C13 { return Err(Error::UnimplementedFeature( "Unsupported symbol data format", )); } } Ok(SymbolIter::new(buf)) } }
我的脚本
fn dump_pdb<'a>(filename: &str, imagebase: u64) -> pdb::Result<()> { let file: File = std::fs::File::open(filename)?; let mut pdb: PDB<File> = pdb::PDB::open(file)?; // ... let dbi: DebugInformation = pdb.debug_information()?; let mut modules: ModuleIter = dbi.modules()?; // merge the module functions let mut mod_symbols: Vec<pdb::Symbol> = Vec::new(); while let Some(module) = modules.next()? { println!("Module: {}", module.object_file_name()); let info: ModuleInfo = match pdb.module_info(&module)? { Some(info) => info, None => { println!("no module info"); continue; } }; while let Some(symbol) = info.symbols()?.next()? { // `info` does not live long enough mod_symbols.push(symbol); // borrow later used here } } // ... }
错误信息
error[E0597]: `info` does not live long enough --> examples\pdb_symbols2json.rs:251:34 | 251 | while let Some(symbol) = info.symbols()?.next()? { | ^^^^^^^^^^^^^^ borrowed value does not live long enough 252 | mod_symbols.push(symbol); | ------------------------ borrow later used here ... 282 | } | - `info` dropped here while still borrowed
解决方案
问题根源在于pdb::Symbol是引用类型,它的生命周期绑定到ModuleInfo内部的stream。当循环结束时info会被销毁,此时mod_symbols中存储的符号引用会变成悬空引用,Rust的借用检查器会直接阻止这种不安全行为。
解决思路是将符号转换为拥有所有权的类型,存储符号的具体数据而非引用:
- 定义自定义结构体,存储你需要的符号字段:
#[derive(Debug, Clone)] struct OwnedSymbol { name: String, rva: u32, // 根据需求添加其他字段,比如符号类型、大小等 }
- 遍历符号时,提取
pdb::Symbol中的数据并转换为自定义结构体:
fn dump_pdb(filename: &str, imagebase: u64) -> pdb::Result<()> { let file: File = std::fs::File::open(filename)?; let mut pdb: PDB<File> = pdb::PDB::open(file)?; // ... let dbi: DebugInformation = pdb.debug_information()?; let mut modules: ModuleIter = dbi.modules()?; // 改为存储自定义的拥有所有权的符号类型 let mut mod_symbols: Vec<OwnedSymbol> = Vec::new(); while let Some(module) = modules.next()? { println!("Module: {}", module.object_file_name()); let info: ModuleInfo = match pdb.module_info(&module)? { Some(info) => info, None => { println!("no module info"); continue; } }; // 遍历符号,转换为拥有所有权的结构 let symbols_iter = info.symbols()?; for symbol_result in symbols_iter { let symbol = symbol_result?; // 解析符号数据并提取所需字段 match symbol.parse() { Ok(pdb::SymbolData::Public(public_data)) => { let owned_symbol = OwnedSymbol { name: public_data.name().to_string(), rva: public_data.offset.rva, }; mod_symbols.push(owned_symbol); } // 可以根据需求处理其他符号类型,比如函数、变量等 Ok(pdb::SymbolData::Function(func_data)) => { let owned_symbol = OwnedSymbol { name: func_data.name().to_string(), rva: func_data.offset.rva, }; mod_symbols.push(owned_symbol); } _ => continue, // 忽略不需要的符号类型 } } } // ... 后续可以正常使用mod_symbols中的数据 Ok(()) }
这样修改后,mod_symbols存储的是拥有完整所有权的OwnedSymbol实例,不再依赖info的生命周期,就能绕过借用检查器的限制。
内容的提问来源于stack exchange,提问作者mimak
相关产品推荐
相关产品推荐

