use std::collections::{HashMap, HashSet};
use object::build;
use super::{Error, Result};
#[derive(Debug, Default)]
#[non_exhaustive]
pub struct Options {
pub delete_symbols: HashSet<Vec<u8>>,
pub rename_symbols: HashMap<Vec<u8>, Vec<u8>>,
pub delete_sections: HashSet<Vec<u8>>,
pub rename_sections: HashMap<Vec<u8>, Vec<u8>>,
pub elf: super::ElfOptions,
}
#[derive(Debug)]
pub struct Rewriter<'data> {
pub(crate) builder: build::elf::Builder<'data>,
pub(crate) modified: bool,
}
impl<'data> Rewriter<'data> {
pub fn read(data: &'data [u8]) -> Result<Self> {
let builder = build::elf::Builder::read(data).map_err(Error::parse)?;
Ok(Self {
builder,
modified: false,
})
}
pub fn write<W: std::io::Write>(mut self, w: W) -> Result<()> {
self.elf_finalize()?;
let mut buffer = object::write::StreamingBuffer::new(w);
self.builder.write(&mut buffer).map_err(Error::write)?;
buffer.result().map_err(Error::io)
}
pub fn modify(&mut self, options: Options) -> Result<()> {
if !options.delete_symbols.is_empty() {
self.delete_symbols(&options.delete_symbols);
}
if !options.rename_symbols.is_empty() {
self.rename_symbols(&options.rename_symbols);
}
if !options.delete_sections.is_empty() {
self.delete_sections(&options.delete_sections);
}
if !options.rename_sections.is_empty() {
self.rename_sections(&options.rename_sections);
}
self.elf_modify(options.elf)?;
Ok(())
}
pub fn delete_symbols(&mut self, names: &HashSet<Vec<u8>>) {
self.elf_delete_symbols(names);
self.elf_delete_dynamic_symbols(names);
}
pub fn rename_symbols(&mut self, names: &HashMap<Vec<u8>, Vec<u8>>) {
self.elf_rename_symbols(names);
self.elf_rename_dynamic_symbols(names);
}
pub fn delete_sections(&mut self, names: &HashSet<Vec<u8>>) {
self.elf_delete_sections(names);
}
pub fn rename_sections(&mut self, names: &HashMap<Vec<u8>, Vec<u8>>) {
self.elf_rename_sections(names);
}
}