Skip to content

Commit

Permalink
Add a dump-all command to resymc
Browse files Browse the repository at this point in the history
This addresses issue #33
  • Loading branch information
ergrelet committed Feb 19, 2023
1 parent 06cfbe5 commit 3ef2c52
Show file tree
Hide file tree
Showing 3 changed files with 147 additions and 17 deletions.
38 changes: 37 additions & 1 deletion resym_core/src/backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ pub enum BackendCommand {
bool,
bool,
),
/// Reconstruct all types found in a given PDB.
ReconstructAllTypes(PDBSlot, PrimitiveReconstructionFlavor, bool, bool),
/// Retrieve a list of types that match the given filter for a given PDB.
UpdateTypeFilter(PDBSlot, String, bool, bool),
/// Retrieve a list of types that match the given filter for multiple PDBs
Expand Down Expand Up @@ -185,6 +187,25 @@ fn worker_thread_routine(
}
}

BackendCommand::ReconstructAllTypes(
pdb_slot,
primitives_flavor,
print_header,
print_access_specifiers,
) => {
if let Some(pdb_file) = pdb_files.get(&pdb_slot) {
let reconstructed_type_result = reconstruct_all_types_command(
pdb_file,
primitives_flavor,
print_header,
print_access_specifiers,
);
frontend_controller.send_command(FrontendCommand::ReconstructTypeResult(
reconstructed_type_result,
))?;
}
}

BackendCommand::UpdateTypeFilter(
pdb_slot,
search_filter,
Expand Down Expand Up @@ -274,7 +295,7 @@ fn reconstruct_type_by_index_command(
) -> Result<String> {
let data = pdb_file.reconstruct_type_by_type_index(
type_index,
&primitives_flavor,
primitives_flavor,
reconstruct_dependencies,
print_access_specifiers,
)?;
Expand Down Expand Up @@ -308,6 +329,21 @@ fn reconstruct_type_by_name_command(
}
}

fn reconstruct_all_types_command(
pdb_file: &PdbFile,
primitives_flavor: PrimitiveReconstructionFlavor,
print_header: bool,
print_access_specifiers: bool,
) -> Result<String> {
let data = pdb_file.reconstruct_all_types(primitives_flavor, print_access_specifiers)?;
if print_header {
let file_header = generate_file_header(pdb_file, primitives_flavor, true);
Ok(format!("{file_header}{data}"))
} else {
Ok(data)
}
}

fn generate_file_header(
pdb_file: &PdbFile,
primitives_flavor: PrimitiveReconstructionFlavor,
Expand Down
58 changes: 53 additions & 5 deletions resym_core/src/pdb_file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ impl<'p> PdbFile<'p> {
self.reconstruct_type_by_type_index_internal(
&type_finder,
type_index,
&primitives_flavor,
primitives_flavor,
reconstruct_dependencies,
print_access_specifiers,
)
Expand All @@ -231,7 +231,7 @@ impl<'p> PdbFile<'p> {
pub fn reconstruct_type_by_type_index(
&self,
type_index: pdb::TypeIndex,
primitives_flavor: &PrimitiveReconstructionFlavor,
primitives_flavor: PrimitiveReconstructionFlavor,
reconstruct_dependencies: bool,
print_access_specifiers: bool,
) -> Result<String> {
Expand All @@ -257,7 +257,7 @@ impl<'p> PdbFile<'p> {
&self,
type_finder: &pdb::TypeFinder,
type_index: pdb::TypeIndex,
primitives_flavor: &PrimitiveReconstructionFlavor,
primitives_flavor: PrimitiveReconstructionFlavor,
reconstruct_dependencies: bool,
print_access_specifiers: bool,
) -> Result<String> {
Expand All @@ -272,7 +272,7 @@ impl<'p> PdbFile<'p> {
type_finder,
&self.forwarder_to_complete_type,
type_index,
primitives_flavor,
&primitives_flavor,
&mut needed_types,
)?;

Expand All @@ -298,7 +298,7 @@ impl<'p> PdbFile<'p> {
type_finder,
&self.forwarder_to_complete_type,
needed_type_index,
primitives_flavor,
&primitives_flavor,
&mut needed_types,
)?;

Expand All @@ -316,4 +316,52 @@ impl<'p> PdbFile<'p> {
type_data.reconstruct(&fmt_configuration, &mut reconstruction_output)?;
Ok(reconstruction_output)
}

pub fn reconstruct_all_types(
&self,
primitives_flavor: PrimitiveReconstructionFlavor,
print_access_specifiers: bool,
) -> Result<String> {
let mut type_data = pdb_types::Data::new();

let mut type_finder = self.type_information.finder();
{
// Populate our `TypeFinder`
let mut type_iter = self.type_information.iter();
while (type_iter.next()?).is_some() {
type_finder.update(&type_iter);
}

// Add the requested types
type_iter = self.type_information.iter();
while let Some(item) = type_iter.next()? {
let mut needed_types = pdb_types::TypeSet::new();
let type_index = item.index();
let result = type_data.add(
&type_finder,
&self.forwarder_to_complete_type,
type_index,
&primitives_flavor,
&mut needed_types,
);
if let Err(err) = result {
match err {
ResymCoreError::PdbError(err) => {
// Ignore this kind of error since some particular PDB features might not be supported.
// This allows the recontruction to go through with the correctly reconstructed types.
log::warn!("Failed to reconstruct type with index {type_index}: {err}")
}
_ => return Err(err),
}
}
}
}

let fmt_configuration = DataFormatConfiguration {
print_access_specifiers,
};
let mut reconstruction_output = String::new();
type_data.reconstruct(&fmt_configuration, &mut reconstruction_output)?;
Ok(reconstruction_output)
}
}
68 changes: 57 additions & 11 deletions resymc/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,31 @@ fn main() -> Result<()> {
highlight_syntax,
} => app.dump_types_command(
pdb_path,
type_name,
Some(type_name),
primitive_types_flavor.unwrap_or(PrimitiveReconstructionFlavor::Portable),
print_header,
print_dependencies,
print_access_specifiers,
highlight_syntax,
output_file_path,
),
ResymOptions::DumpAll {
pdb_path,
output_file_path,
primitive_types_flavor,
print_header,
print_access_specifiers,
highlight_syntax,
} => app.dump_types_command(
pdb_path,
None,
primitive_types_flavor.unwrap_or(PrimitiveReconstructionFlavor::Portable),
print_header,
false,
print_access_specifiers,
highlight_syntax,
output_file_path,
),
ResymOptions::Diff {
from_pdb_path,
to_pdb_path,
Expand Down Expand Up @@ -129,6 +146,25 @@ enum ResymOptions {
#[structopt(short = "H", long)]
highlight_syntax: bool,
},
/// Dump all types from a given PDB file
DumpAll {
/// Path to the PDB file
pdb_path: PathBuf,
/// Path of the output file
output_file_path: Option<PathBuf>,
/// Representation of primitive types
#[structopt(short = "f", long)]
primitive_types_flavor: Option<PrimitiveReconstructionFlavor>,
/// Print header
#[structopt(short = "h", long)]
print_header: bool,
/// Print C++ access specifiers
#[structopt(short = "a", long)]
print_access_specifiers: bool,
/// Highlight C++ output
#[structopt(short = "H", long)]
highlight_syntax: bool,
},
/// Compute diff for a type between two given PDB files
Diff {
/// Path of the PDB file to compute the diff from
Expand Down Expand Up @@ -230,7 +266,7 @@ impl ResymcApp {
fn dump_types_command(
&self,
pdb_path: PathBuf,
type_name: String,
type_name: Option<String>,
primitive_types_flavor: PrimitiveReconstructionFlavor,
print_header: bool,
print_dependencies: bool,
Expand All @@ -251,15 +287,25 @@ impl ResymcApp {
}

// Queue a request for the backend to reconstruct the given type
self.backend
.send_command(BackendCommand::ReconstructTypeByName(
PDB_MAIN_SLOT,
type_name,
primitive_types_flavor,
print_header,
print_dependencies,
print_access_specifiers,
))?;
if let Some(type_name) = type_name {
self.backend
.send_command(BackendCommand::ReconstructTypeByName(
PDB_MAIN_SLOT,
type_name,
primitive_types_flavor,
print_header,
print_dependencies,
print_access_specifiers,
))?;
} else {
self.backend
.send_command(BackendCommand::ReconstructAllTypes(
PDB_MAIN_SLOT,
primitive_types_flavor,
print_header,
print_access_specifiers,
))?;
}
// Wait for the backend to finish filtering types
if let FrontendCommand::ReconstructTypeResult(reconstructed_type_result) =
self.frontend_controller.rx_ui.recv()?
Expand Down

0 comments on commit 3ef2c52

Please sign in to comment.