Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Exception table diff view #82

Merged
merged 34 commits into from
Jul 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
352d230
Basic integration
CelestialAmber Jul 11, 2024
7891fe0
Implement basic right click option
CelestialAmber Jul 12, 2024
88bcfd8
nothing to worry about
CelestialAmber Jul 12, 2024
8b73586
Convert extab diff to separate view
CelestialAmber Jul 13, 2024
21b78da
Make clippy and fmt shut up
CelestialAmber Jul 13, 2024
416bda0
Make clippy fmt shut up for real this time
CelestialAmber Jul 13, 2024
00575b1
Print extab/extabindex symbol names in extab view
CelestialAmber Jul 13, 2024
98ffbe6
I hate fmt
CelestialAmber Jul 13, 2024
e526ccc
Basic integration
CelestialAmber Jul 11, 2024
de979fc
Implement basic right click option
CelestialAmber Jul 12, 2024
7a9f4d8
nothing to worry about
CelestialAmber Jul 12, 2024
0bb964b
Convert extab diff to separate view
CelestialAmber Jul 13, 2024
3e6c0c1
Make clippy and fmt shut up
CelestialAmber Jul 13, 2024
4c0bdce
Make clippy fmt shut up for real this time
CelestialAmber Jul 13, 2024
1b94777
Print extab/extabindex symbol names in extab view
CelestialAmber Jul 13, 2024
21854a1
I hate fmt
CelestialAmber Jul 13, 2024
e856609
Merge branch 'extab' of https://github.com/CelestialAmber/objdiff int…
CelestialAmber Jul 15, 2024
13c2cf3
Fix scroll position not being maintained from extab view
CelestialAmber Jul 15, 2024
50d9d8a
Silly me
CelestialAmber Jul 15, 2024
e6c1374
Add rlwinm decoder window
CelestialAmber Jul 20, 2024
5e150d1
Remove extra files
CelestialAmber Jul 20, 2024
eaf6c7c
Create Cargo.lock
CelestialAmber Jul 20, 2024
06e0a2b
Show extab symbol names in hover window
CelestialAmber Jul 20, 2024
a73646f
Merge branch 'rlwinm-tool' into extab
CelestialAmber Jul 20, 2024
504b667
Appease fmt
CelestialAmber Jul 20, 2024
ffdf4a6
Update symbol_diff.rs
CelestialAmber Jul 20, 2024
22083c7
Update symbol_diff.rs
CelestialAmber Jul 20, 2024
2f2e489
Get extab symbol from extabindex relocations instead
CelestialAmber Jul 21, 2024
d13cf25
Update Cargo.lock
CelestialAmber Jul 21, 2024
748178b
Update Cargo.lock
CelestialAmber Jul 21, 2024
fa3837d
Merge branch 'main' into extab
encounter Jul 21, 2024
c0e5e64
Address some feedback
CelestialAmber Jul 22, 2024
a46298f
Make fmt shut up
CelestialAmber Jul 22, 2024
19d48cf
Update read.rs
CelestialAmber Jul 22, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,4 @@ android.keystore
*.frag
*.vert
*.metal
.vscode/launch.json
11 changes: 11 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion objdiff-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ any-arch = [] # Implicit, used to check if any arch is enabled
config = ["globset", "semver", "serde_json", "serde_yaml"]
dwarf = ["gimli"]
mips = ["any-arch", "rabbitizer"]
ppc = ["any-arch", "cwdemangle", "ppc750cl"]
ppc = ["any-arch", "cwdemangle", "cwextab", "ppc750cl"]
x86 = ["any-arch", "cpp_demangle", "iced-x86", "msvc-demangler"]
arm = ["any-arch", "cpp_demangle", "unarm", "arm-attr"]

Expand Down Expand Up @@ -45,6 +45,7 @@ gimli = { version = "0.29.0", default-features = false, features = ["read-all"],

# ppc
cwdemangle = { version = "1.0.0", optional = true }
cwextab = { version = "0.2.3", optional = true }
ppc750cl = { git = "https://github.com/encounter/ppc750cl", rev = "6cbd7d888c7082c2c860f66cbb9848d633f753ed", optional = true }

# mips
Expand Down
13 changes: 13 additions & 0 deletions objdiff-core/src/obj/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ pub mod split_meta;

use std::{borrow::Cow, collections::BTreeMap, fmt, path::PathBuf};

use cwextab::*;
use filetime::FileTime;
use flagset::{flags, FlagSet};
use object::RelocationFlags;
Expand Down Expand Up @@ -113,6 +114,9 @@ pub struct ObjIns {
pub struct ObjSymbol {
pub name: String,
pub demangled_name: Option<String>,
pub has_extab: bool,
pub extab_name: Option<String>,
pub extabindex_name: Option<String>,
pub address: u64,
pub section_address: u64,
pub size: u64,
Expand All @@ -123,13 +127,22 @@ pub struct ObjSymbol {
pub virtual_address: Option<u64>,
}

#[derive(Debug, Clone)]
pub struct ObjExtab {
pub func: ObjSymbol,
pub data: ExceptionTableData,
pub dtors: Vec<ObjSymbol>,
}

pub struct ObjInfo {
pub arch: Box<dyn ObjArch>,
pub path: PathBuf,
pub timestamp: FileTime,
pub sections: Vec<ObjSection>,
/// Common BSS symbols
pub common: Vec<ObjSymbol>,
/// Exception tables
pub extab: Option<Vec<ObjExtab>>,
/// Split object metadata (.note.split section)
pub split_meta: Option<SplitMeta>,
}
Expand Down
125 changes: 121 additions & 4 deletions objdiff-core/src/obj/read.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,21 @@ use std::{collections::HashSet, fs, io::Cursor, path::Path};

use anyhow::{anyhow, bail, ensure, Context, Result};
use byteorder::{BigEndian, ReadBytesExt};
use cwextab::decode_extab;
use filetime::FileTime;
use flagset::Flags;
use object::{
BinaryFormat, File, Object, ObjectSection, ObjectSymbol, RelocationTarget, SectionIndex,
SectionKind, Symbol, SymbolKind, SymbolScope, SymbolSection,
Architecture, BinaryFormat, File, Object, ObjectSection, ObjectSymbol, RelocationTarget,
SectionIndex, SectionKind, Symbol, SymbolKind, SymbolScope, SymbolSection,
};

use crate::{
arch::{new_arch, ObjArch},
diff::DiffObjConfig,
obj::{
split_meta::{SplitMeta, SPLITMETA_SECTION},
ObjInfo, ObjReloc, ObjSection, ObjSectionKind, ObjSymbol, ObjSymbolFlagSet, ObjSymbolFlags,
ObjExtab, ObjInfo, ObjReloc, ObjSection, ObjSectionKind, ObjSymbol, ObjSymbolFlagSet,
ObjSymbolFlags,
},
};

Expand Down Expand Up @@ -71,6 +73,9 @@ fn to_obj_symbol(
Ok(ObjSymbol {
name: name.to_string(),
demangled_name,
has_extab: false,
extab_name: None,
extabindex_name: None,
address,
section_address,
size: symbol.size(),
Expand Down Expand Up @@ -170,6 +175,111 @@ fn common_symbols(
.collect::<Result<Vec<ObjSymbol>>>()
}

fn section_by_name<'a>(sections: &'a mut [ObjSection], name: &str) -> Option<&'a mut ObjSection> {
sections.iter_mut().find(|section| section.name == name)
}

fn exception_tables(
sections: &mut [ObjSection],
obj_file: &File<'_>,
) -> Result<Option<Vec<ObjExtab>>> {
//PowerPC only
if obj_file.architecture() != Architecture::PowerPc {
return Ok(None);
}

//Find the extab/extabindex sections
let extab_section = match section_by_name(sections, "extab") {
Some(section) => section.clone(),
None => {
return Ok(None);
}
};
let extabindex_section = match section_by_name(sections, "extabindex") {
Some(section) => section.clone(),
None => {
return Ok(None);
}
};
let text_section = match section_by_name(sections, ".text") {
Some(section) => section,
None => bail!(".text section is somehow missing, this should not happen"),
};

let mut result: Vec<ObjExtab> = vec![];
let extab_symbol_count = extab_section.symbols.len();
let extabindex_symbol_count = extabindex_section.symbols.len();
let extab_reloc_count = extab_section.relocations.len();
let table_count = extab_symbol_count;
let mut extab_reloc_index: usize = 0;

//Make sure that the number of symbols in the extab/extabindex section matches. If not, exit early
if extab_symbol_count != extabindex_symbol_count {
bail!("Extab/Extabindex symbol counts do not match");
}

//Convert the extab/extabindex section data

//Go through each extabindex entry
for i in 0..table_count {
let extabindex = &extabindex_section.symbols[i];

/* Get the function symbol and extab symbol from the extabindex relocations array. Each extabindex
entry has two relocations (the first for the function, the second for the extab entry) */
let extab_func = extabindex_section.relocations[i * 2].target.clone();
let extab = &extabindex_section.relocations[(i * 2) + 1].target;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems dangerous to assume the index of relocations. Can we fetch these by either source address or target symbol?


let extab_start_addr = extab.address;
let extab_end_addr = extab_start_addr + extab.size;

//Find the function in the text section, and set the has extab flag
for i in 0..text_section.symbols.len() {
let func = &mut text_section.symbols[i];
if func.name == extab_func.name {
func.has_extab = true;
func.extab_name = Some(extab.name.clone());
func.extabindex_name = Some(extabindex.name.clone());
}
}

/* Iterate through the list of extab relocations, continuing until we hit a relocation
that isn't within the current extab symbol. Get the target dtor function symbol from
each relocation used, and add them to the list. */
let mut dtors: Vec<ObjSymbol> = vec![];

while extab_reloc_index < extab_reloc_count {
let extab_reloc = &extab_section.relocations[extab_reloc_index];
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we also sanity check that these are Absolute relocations? In case something else sneaks in... not sure how though

//If the current entry is past the current extab table, stop here
if extab_reloc.address >= extab_end_addr {
break;
}

//Otherwise, the current relocation is used by the current table
dtors.push(extab_reloc.target.clone());
//Go to the next entry
extab_reloc_index += 1;
}

//Decode the extab data
let start_index = extab_start_addr as usize;
let end_index = extab_end_addr as usize;
let extab_data = extab_section.data[start_index..end_index].try_into().unwrap();
let data = match decode_extab(extab_data) {
Some(decoded_data) => decoded_data,
None => {
log::warn!("Exception table decoding failed for function {}", extab_func.name);
return Ok(None);
}
};

//Add the new entry to the list
let entry = ObjExtab { func: extab_func, data, dtors };
result.push(entry);
}

Ok(Some(result))
}

fn find_section_symbol(
arch: &dyn ObjArch,
obj_file: &File<'_>,
Expand Down Expand Up @@ -205,6 +315,9 @@ fn find_section_symbol(
Ok(ObjSymbol {
name: name.to_string(),
demangled_name: None,
has_extab: false,
extab_name: None,
extabindex_name: None,
address: offset,
section_address: address - section.address(),
size: 0,
Expand Down Expand Up @@ -367,6 +480,9 @@ fn update_combined_symbol(symbol: ObjSymbol, address_change: i64) -> Result<ObjS
Ok(ObjSymbol {
name: symbol.name,
demangled_name: symbol.demangled_name,
has_extab: symbol.has_extab,
extab_name: symbol.extab_name,
extabindex_name: symbol.extabindex_name,
address: (symbol.address as i64 + address_change).try_into()?,
section_address: (symbol.section_address as i64 + address_change).try_into()?,
size: symbol.size,
Expand Down Expand Up @@ -482,7 +598,8 @@ pub fn read(obj_path: &Path, config: &DiffObjConfig) -> Result<ObjInfo> {
}
line_info(&obj_file, &mut sections)?;
let common = common_symbols(arch.as_ref(), &obj_file, split_meta.as_ref())?;
Ok(ObjInfo { arch, path: obj_path.to_owned(), timestamp, sections, common, split_meta })
let extab = exception_tables(&mut sections, &obj_file)?;
Ok(ObjInfo { arch, path: obj_path.to_owned(), timestamp, sections, common, extab, split_meta })
}

pub fn has_function(obj_path: &Path, symbol_name: &str) -> Result<bool> {
Expand Down
1 change: 1 addition & 0 deletions objdiff-gui/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ cfg-if = "1.0.0"
const_format = "0.2.32"
cwdemangle = "1.0.0"
rlwinmdec = "1.0.1"
cwextab = "0.2.3"
dirs = "5.0.1"
egui = "0.27.2"
egui_extras = "0.27.2"
Expand Down
5 changes: 5 additions & 0 deletions objdiff-gui/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ use crate::{
data_diff::data_diff_ui,
debug::debug_window,
demangle::{demangle_window, DemangleViewState},
extab_diff::extab_diff_ui,
frame_history::FrameHistory,
function_diff::function_diff_ui,
graphics::{graphics_window, GraphicsConfig, GraphicsViewState},
Expand Down Expand Up @@ -591,6 +592,10 @@ impl eframe::App for App {
egui::CentralPanel::default().show(ctx, |ui| {
data_diff_ui(ui, diff_state, appearance);
});
} else if diff_state.current_view == View::ExtabDiff && build_success {
egui::CentralPanel::default().show(ctx, |ui| {
extab_diff_ui(ui, diff_state, appearance);
});
} else {
egui::SidePanel::left("side_panel").show(ctx, |ui| {
egui::ScrollArea::both().show(ui, |ui| {
Expand Down
Loading