Major `dwarf dump` rework
- Supports games with C++ DWARF info - Syntax highlighting when printing to console (disable with `--no-color`) - Overall improvements to parsing and output
This commit is contained in:
parent
4935708b61
commit
5e13998e93
|
@ -310,7 +310,8 @@ dependencies = [
|
|||
"flate2",
|
||||
"glob",
|
||||
"hex",
|
||||
"indexmap",
|
||||
"indent",
|
||||
"indexmap 2.0.2",
|
||||
"itertools",
|
||||
"log",
|
||||
"memchr",
|
||||
|
@ -334,12 +335,22 @@ dependencies = [
|
|||
"sha-1",
|
||||
"smallvec",
|
||||
"supports-color 2.1.0",
|
||||
"syntect",
|
||||
"tracing",
|
||||
"tracing-attributes",
|
||||
"tracing-subscriber",
|
||||
"xxhash-rust",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "deranged"
|
||||
version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0f32d04922c60427da6f9fef14d042d9edddef64cb9d4ce0d64d0685fbeb1fd3"
|
||||
dependencies = [
|
||||
"powerfmt",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "digest"
|
||||
version = "0.10.6"
|
||||
|
@ -428,6 +439,12 @@ dependencies = [
|
|||
"miniz_oxide 0.7.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fnv"
|
||||
version = "1.0.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
||||
|
||||
[[package]]
|
||||
name = "generic-array"
|
||||
version = "0.14.6"
|
||||
|
@ -459,6 +476,12 @@ version = "0.3.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.12.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.14.1"
|
||||
|
@ -489,6 +512,22 @@ version = "0.4.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
|
||||
|
||||
[[package]]
|
||||
name = "indent"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d9f1a0777d972970f204fdf8ef319f1f4f8459131636d7e3c96c5d59570d0fa6"
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "1.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"hashbrown 0.12.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "2.0.2"
|
||||
|
@ -496,7 +535,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "8adf3ddd720272c6ea8bf59463c04e0f93d0bbf7c5439b691bca2987e0270897"
|
||||
dependencies = [
|
||||
"equivalent",
|
||||
"hashbrown",
|
||||
"hashbrown 0.14.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -543,6 +582,21 @@ version = "0.2.147"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3"
|
||||
|
||||
[[package]]
|
||||
name = "line-wrap"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f30344350a2a51da54c1d53be93fade8a237e545dbcc4bdbe635413f2117cab9"
|
||||
dependencies = [
|
||||
"safemem",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "linked-hash-map"
|
||||
version = "0.5.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f"
|
||||
|
||||
[[package]]
|
||||
name = "linux-raw-sys"
|
||||
version = "0.4.10"
|
||||
|
@ -681,8 +735,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0"
|
||||
dependencies = [
|
||||
"crc32fast",
|
||||
"hashbrown",
|
||||
"indexmap",
|
||||
"hashbrown 0.14.1",
|
||||
"indexmap 2.0.2",
|
||||
"memchr",
|
||||
]
|
||||
|
||||
|
@ -692,6 +746,28 @@ version = "1.18.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
|
||||
|
||||
[[package]]
|
||||
name = "onig"
|
||||
version = "6.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8c4b31c8722ad9171c6d77d3557db078cab2bd50afcc9d09c8b315c59df8ca4f"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
"libc",
|
||||
"once_cell",
|
||||
"onig_sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "onig_sys"
|
||||
version = "69.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7b829e3d7e9cc74c7e315ee8edb185bf4190da5acde74afd7fc59c35b1f086e7"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"pkg-config",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "overload"
|
||||
version = "0.1.1"
|
||||
|
@ -720,7 +796,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "e1d3afd2628e69da2be385eb6f2fd57c8ac7977ceeff6dc166ff1657b0e386a9"
|
||||
dependencies = [
|
||||
"fixedbitset",
|
||||
"indexmap",
|
||||
"indexmap 2.0.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -729,6 +805,32 @@ version = "0.2.12"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "12cc1b0bf1727a77a54b6654e7b5f1af8604923edc8b81885f8ec92f9e3f0a05"
|
||||
|
||||
[[package]]
|
||||
name = "pkg-config"
|
||||
version = "0.3.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964"
|
||||
|
||||
[[package]]
|
||||
name = "plist"
|
||||
version = "1.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a4a0cfc5fb21a09dc6af4bf834cf10d4a32fccd9e2ea468c4b1751a097487aa"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"indexmap 1.9.3",
|
||||
"line-wrap",
|
||||
"quick-xml",
|
||||
"serde",
|
||||
"time",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "powerfmt"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
|
||||
|
||||
[[package]]
|
||||
name = "ppc750cl"
|
||||
version = "0.2.0"
|
||||
|
@ -770,6 +872,15 @@ dependencies = [
|
|||
"unicase",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quick-xml"
|
||||
version = "0.30.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eff6510e86862b57b210fd8cbe8ed3f0d7d600b9c2863cd4549a2e033c66e956"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.33"
|
||||
|
@ -883,6 +994,21 @@ version = "1.0.15"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741"
|
||||
|
||||
[[package]]
|
||||
name = "safemem"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ef703b7cb59335eae2eb93ceb664c0eb7ea6bf567079d843e09420219668e072"
|
||||
|
||||
[[package]]
|
||||
name = "same-file"
|
||||
version = "1.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
|
||||
dependencies = [
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "scopeguard"
|
||||
version = "1.2.0"
|
||||
|
@ -937,7 +1063,7 @@ version = "0.9.25"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1a49e178e4452f45cb61d0cd8cebc1b0fafd3e41929e996cef79aa3aca91f574"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"indexmap 2.0.2",
|
||||
"itoa",
|
||||
"ryu",
|
||||
"serde",
|
||||
|
@ -1018,6 +1144,27 @@ dependencies = [
|
|||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syntect"
|
||||
version = "5.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e02b4b303bf8d08bfeb0445cba5068a3d306b6baece1d5582171a9bf49188f91"
|
||||
dependencies = [
|
||||
"bincode",
|
||||
"bitflags 1.3.2",
|
||||
"flate2",
|
||||
"fnv",
|
||||
"once_cell",
|
||||
"onig",
|
||||
"plist",
|
||||
"regex-syntax 0.7.5",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"thiserror",
|
||||
"walkdir",
|
||||
"yaml-rust",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "textwrap"
|
||||
version = "0.11.0"
|
||||
|
@ -1057,6 +1204,35 @@ dependencies = [
|
|||
"once_cell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time"
|
||||
version = "0.3.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c4a34ab300f2dee6e562c10a046fc05e358b29f9bf92277f30c3c8d82275f6f5"
|
||||
dependencies = [
|
||||
"deranged",
|
||||
"itoa",
|
||||
"powerfmt",
|
||||
"serde",
|
||||
"time-core",
|
||||
"time-macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time-core"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3"
|
||||
|
||||
[[package]]
|
||||
name = "time-macros"
|
||||
version = "0.2.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4ad70d68dba9e1f8aceda7aa6711965dfec1cac869f311a51bd08b3a2ccbce20"
|
||||
dependencies = [
|
||||
"time-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "0.5.11"
|
||||
|
@ -1179,6 +1355,16 @@ version = "0.9.4"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
||||
|
||||
[[package]]
|
||||
name = "walkdir"
|
||||
version = "2.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee"
|
||||
dependencies = [
|
||||
"same-file",
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.9"
|
||||
|
@ -1195,6 +1381,15 @@ version = "0.4.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-util"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-x86_64-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
|
@ -1329,3 +1524,12 @@ name = "xxhash-rust"
|
|||
version = "0.8.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9828b178da53440fa9c766a3d2f73f7cf5d0ac1fe3980c1e5018d899fd19e07b"
|
||||
|
||||
[[package]]
|
||||
name = "yaml-rust"
|
||||
version = "0.4.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85"
|
||||
dependencies = [
|
||||
"linked-hash-map",
|
||||
]
|
||||
|
|
|
@ -35,6 +35,7 @@ flagset = { version = "0.4.4", features = ["serde"] }
|
|||
flate2 = "1.0.27"
|
||||
glob = "0.3.1"
|
||||
hex = "0.4.3"
|
||||
indent = "0.1.1"
|
||||
indexmap = "2.0.2"
|
||||
itertools = "0.11.0"
|
||||
log = "0.4.20"
|
||||
|
@ -59,6 +60,7 @@ serde_yaml = "0.9.25"
|
|||
sha-1 = "0.10.1"
|
||||
smallvec = "1.11.1"
|
||||
supports-color = "2.1.0"
|
||||
syntect = "5.1.0"
|
||||
tracing = "0.1.37"
|
||||
tracing-attributes = "0.1.26"
|
||||
tracing-subscriber = { version = "0.3.17", features = ["env-filter"] }
|
||||
|
|
250
src/cmd/dwarf.rs
250
src/cmd/dwarf.rs
|
@ -2,16 +2,21 @@ use std::{
|
|||
collections::{btree_map, BTreeMap},
|
||||
io::{stdout, Cursor, Read, Write},
|
||||
path::PathBuf,
|
||||
str::from_utf8,
|
||||
};
|
||||
|
||||
use anyhow::{anyhow, bail, Result};
|
||||
use anyhow::{anyhow, bail, Context, Result};
|
||||
use argp::FromArgs;
|
||||
use object::{elf, Object, ObjectSection, ObjectSymbol, RelocationKind, RelocationTarget, Section};
|
||||
use syntect::{
|
||||
highlighting::{Color, HighlightIterator, HighlightState, Highlighter, Theme, ThemeSet},
|
||||
parsing::{ParseState, ScopeStack, SyntaxReference, SyntaxSet},
|
||||
};
|
||||
|
||||
use crate::util::{
|
||||
dwarf::{
|
||||
process_address, process_type, process_variable_location, read_debug_section, type_string,
|
||||
ud_type, ud_type_def, ud_type_string, AttributeKind, TagKind,
|
||||
process_root_tag, read_debug_section, should_skip_tag, tag_type_string, AttributeKind,
|
||||
TagKind,
|
||||
},
|
||||
file::{buf_writer, map_file},
|
||||
};
|
||||
|
@ -40,6 +45,9 @@ pub struct DumpArgs {
|
|||
#[argp(option, short = 'o')]
|
||||
/// Output file. (Or directory, for archive)
|
||||
out: Option<PathBuf>,
|
||||
#[argp(switch)]
|
||||
/// Disable color output.
|
||||
no_color: bool,
|
||||
}
|
||||
|
||||
pub fn run(args: Args) -> Result<()> {
|
||||
|
@ -49,6 +57,12 @@ pub fn run(args: Args) -> Result<()> {
|
|||
}
|
||||
|
||||
fn dump(args: DumpArgs) -> Result<()> {
|
||||
let theme_set = ThemeSet::load_defaults();
|
||||
let theme = theme_set.themes.get("Solarized (dark)").context("Failed to load theme")?;
|
||||
let syntax_set = SyntaxSet::load_defaults_newlines();
|
||||
let syntax =
|
||||
syntax_set.find_syntax_by_extension("cpp").context("Failed to find syntax")?.clone();
|
||||
|
||||
let file = map_file(&args.in_file)?;
|
||||
let buf = file.as_slice();
|
||||
if buf.starts_with(b"!<arch>\n") {
|
||||
|
@ -80,9 +94,13 @@ fn dump(args: DumpArgs) -> Result<()> {
|
|||
let mut file = buf_writer(file_path)?;
|
||||
dump_debug_section(&mut file, &obj_file, debug_section)?;
|
||||
file.flush()?;
|
||||
} else {
|
||||
println!("\nFile {}:", name);
|
||||
} else if args.no_color {
|
||||
println!("\n// File {}:", name);
|
||||
dump_debug_section(&mut stdout(), &obj_file, debug_section)?;
|
||||
} else {
|
||||
let mut writer = HighlightWriter::new(syntax_set.clone(), syntax.clone(), theme);
|
||||
writeln!(writer, "\n// File {}:", name)?;
|
||||
dump_debug_section(&mut writer, &obj_file, debug_section)?;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -94,8 +112,11 @@ fn dump(args: DumpArgs) -> Result<()> {
|
|||
let mut file = buf_writer(out_path)?;
|
||||
dump_debug_section(&mut file, &obj_file, debug_section)?;
|
||||
file.flush()?;
|
||||
} else {
|
||||
} else if args.no_color {
|
||||
dump_debug_section(&mut stdout(), &obj_file, debug_section)?;
|
||||
} else {
|
||||
let mut writer = HighlightWriter::new(syntax_set, syntax, theme);
|
||||
dump_debug_section(&mut writer, &obj_file, debug_section)?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
|
@ -145,140 +166,37 @@ where
|
|||
.string_attribute(AttributeKind::Name)
|
||||
.ok_or_else(|| anyhow!("CompileUnit without name {:?}", tag))?;
|
||||
if units.contains(unit) {
|
||||
log::warn!("Duplicate unit '{}'", unit);
|
||||
// log::warn!("Duplicate unit '{}'", unit);
|
||||
} else {
|
||||
units.push(unit.clone());
|
||||
}
|
||||
writeln!(w, "\n// Compile unit: {}", unit)?;
|
||||
|
||||
let children = tag.children(&tags);
|
||||
let mut typedefs = BTreeMap::<u32, Vec<u32>>::new();
|
||||
for child in children {
|
||||
match child.kind {
|
||||
TagKind::GlobalSubroutine | TagKind::Subroutine => {
|
||||
let _is_prototyped =
|
||||
child.string_attribute(AttributeKind::Prototyped).is_some();
|
||||
if let (Some(_hi), Some(_lo)) = (
|
||||
child.address_attribute(AttributeKind::HighPc),
|
||||
child.address_attribute(AttributeKind::LowPc),
|
||||
) {}
|
||||
let name = child
|
||||
.string_attribute(AttributeKind::Name)
|
||||
.ok_or_else(|| anyhow!("Subroutine without name"))?;
|
||||
let udt = ud_type(&tags, child)?;
|
||||
let ts = ud_type_string(&tags, &typedefs, &udt)?;
|
||||
writeln!(w, "{} {}{} {{", ts.prefix, name, ts.suffix)?;
|
||||
for tag in child.children(&tags) {
|
||||
match tag.kind {
|
||||
TagKind::LocalVariable => {}
|
||||
_ => continue,
|
||||
}
|
||||
let type_attr = tag.type_attribute().ok_or_else(|| {
|
||||
anyhow!("LocalVariable without type attr")
|
||||
})?;
|
||||
let var_type = process_type(type_attr)?;
|
||||
let ts = type_string(&tags, &typedefs, &var_type)?;
|
||||
let name = tag
|
||||
.string_attribute(AttributeKind::Name)
|
||||
.ok_or_else(|| anyhow!("LocalVariable without name"))?;
|
||||
write!(w, "\t{} {}{};", ts.prefix, name, ts.suffix)?;
|
||||
if let Some(location) =
|
||||
tag.block_attribute(AttributeKind::Location)
|
||||
{
|
||||
if !location.is_empty() {
|
||||
write!(
|
||||
w,
|
||||
" // {}",
|
||||
process_variable_location(location)?
|
||||
)?;
|
||||
}
|
||||
}
|
||||
writeln!(w)?;
|
||||
}
|
||||
writeln!(w, "}}")?;
|
||||
}
|
||||
TagKind::Typedef => {
|
||||
let name = child
|
||||
.string_attribute(AttributeKind::Name)
|
||||
.ok_or_else(|| anyhow!("Typedef without name"))?;
|
||||
let attr = child
|
||||
.type_attribute()
|
||||
.ok_or_else(|| anyhow!("Typedef without type attribute"))?;
|
||||
let t = process_type(attr)?;
|
||||
let ts = type_string(&tags, &typedefs, &t)?;
|
||||
writeln!(w, "typedef {} {}{};", ts.prefix, name, ts.suffix)?;
|
||||
let tag_type = process_root_tag(&tags, child)?;
|
||||
if should_skip_tag(&tag_type) {
|
||||
continue;
|
||||
}
|
||||
writeln!(w, "{}", tag_type_string(&tags, &typedefs, &tag_type)?)?;
|
||||
|
||||
// TODO fundamental typedefs?
|
||||
if let Some(ud_type_ref) =
|
||||
child.reference_attribute(AttributeKind::UserDefType)
|
||||
{
|
||||
match typedefs.entry(ud_type_ref) {
|
||||
btree_map::Entry::Vacant(e) => {
|
||||
e.insert(vec![child.key]);
|
||||
}
|
||||
btree_map::Entry::Occupied(e) => {
|
||||
e.into_mut().push(child.key);
|
||||
}
|
||||
if let TagKind::Typedef = child.kind {
|
||||
// TODO fundamental typedefs?
|
||||
if let Some(ud_type_ref) =
|
||||
child.reference_attribute(AttributeKind::UserDefType)
|
||||
{
|
||||
match typedefs.entry(ud_type_ref) {
|
||||
btree_map::Entry::Vacant(e) => {
|
||||
e.insert(vec![child.key]);
|
||||
}
|
||||
btree_map::Entry::Occupied(e) => {
|
||||
e.into_mut().push(child.key);
|
||||
}
|
||||
}
|
||||
}
|
||||
TagKind::GlobalVariable | TagKind::LocalVariable => {
|
||||
let name = child
|
||||
.string_attribute(AttributeKind::Name)
|
||||
.ok_or_else(|| anyhow!("Variable without name"))?;
|
||||
let address = if let Some(location) =
|
||||
child.block_attribute(AttributeKind::Location)
|
||||
{
|
||||
Some(process_address(location)?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
if let Some(type_attr) = child.type_attribute() {
|
||||
let var_type = process_type(type_attr)?;
|
||||
// log::info!("{:?}", var_type);
|
||||
// if let TypeKind::UserDefined(key) = var_type.kind {
|
||||
// let ud_tag = tags
|
||||
// .get(&key)
|
||||
// .ok_or_else(|| anyhow!("Invalid UD type ref"))?;
|
||||
// let ud_type = ud_type(&tags, ud_tag)?;
|
||||
// log::info!("{:?}", ud_type);
|
||||
// }
|
||||
let ts = type_string(&tags, &typedefs, &var_type)?;
|
||||
let st = if child.kind == TagKind::LocalVariable {
|
||||
"static "
|
||||
} else {
|
||||
""
|
||||
};
|
||||
let address_str = match address {
|
||||
Some(addr) => format!(" : {:#010X}", addr),
|
||||
None => String::new(),
|
||||
};
|
||||
let size = var_type.size(&tags)?;
|
||||
writeln!(
|
||||
w,
|
||||
"{}{} {}{}{}; // size: {:#X}",
|
||||
st, ts.prefix, name, ts.suffix, address_str, size,
|
||||
)?;
|
||||
}
|
||||
}
|
||||
TagKind::StructureType
|
||||
| TagKind::ArrayType
|
||||
| TagKind::EnumerationType
|
||||
| TagKind::UnionType
|
||||
| TagKind::ClassType
|
||||
| TagKind::SubroutineType => {
|
||||
let udt = ud_type(&tags, child)?;
|
||||
if child.string_attribute(AttributeKind::Name).is_some() {
|
||||
writeln!(w, "{}", ud_type_def(&tags, &typedefs, &udt)?)?;
|
||||
} else {
|
||||
// log::warn!("No name for tag: {:?}", child);
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
log::warn!("Unhandled CompileUnit child {:?}", child.kind);
|
||||
}
|
||||
}
|
||||
}
|
||||
// println!("Children: {:?}", children.iter().map(|c| c.kind).collect::<Vec<TagKind>>());
|
||||
}
|
||||
_ => {
|
||||
log::warn!("Expected CompileUnit, got {:?}", tag.kind);
|
||||
|
@ -298,3 +216,81 @@ where
|
|||
// }
|
||||
Ok(())
|
||||
}
|
||||
|
||||
struct HighlightWriter<'a> {
|
||||
line: String,
|
||||
highlighter: Highlighter<'a>,
|
||||
parse_state: ParseState,
|
||||
highlight_state: HighlightState,
|
||||
syntax_set: SyntaxSet,
|
||||
}
|
||||
|
||||
impl<'a> HighlightWriter<'a> {
|
||||
pub fn new(
|
||||
syntax_set: SyntaxSet,
|
||||
syntax: SyntaxReference,
|
||||
theme: &'a Theme,
|
||||
) -> HighlightWriter<'a> {
|
||||
let highlighter = Highlighter::new(theme);
|
||||
let highlight_state = HighlightState::new(&highlighter, ScopeStack::new());
|
||||
HighlightWriter {
|
||||
line: String::new(),
|
||||
highlighter,
|
||||
syntax_set,
|
||||
parse_state: ParseState::new(&syntax),
|
||||
highlight_state,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn blend_fg_color(fg: Color, bg: Color) -> Color {
|
||||
if fg.a == 0xff {
|
||||
return fg;
|
||||
}
|
||||
let ratio = fg.a as u32;
|
||||
let r = (fg.r as u32 * ratio + bg.r as u32 * (255 - ratio)) / 255;
|
||||
let g = (fg.g as u32 * ratio + bg.g as u32 * (255 - ratio)) / 255;
|
||||
let b = (fg.b as u32 * ratio + bg.b as u32 * (255 - ratio)) / 255;
|
||||
Color { r: r as u8, g: g as u8, b: b as u8, a: 255 }
|
||||
}
|
||||
|
||||
impl Write for HighlightWriter<'_> {
|
||||
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
|
||||
let str = from_utf8(buf).map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e))?;
|
||||
for s in str.split_inclusive('\n') {
|
||||
self.line.push_str(s);
|
||||
if self.line.ends_with('\n') {
|
||||
self.flush()?;
|
||||
}
|
||||
}
|
||||
Ok(buf.len())
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> std::io::Result<()> {
|
||||
if self.line.is_empty() {
|
||||
return Ok(());
|
||||
}
|
||||
let ops = self
|
||||
.parse_state
|
||||
.parse_line(&self.line, &self.syntax_set)
|
||||
.map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e))?;
|
||||
let iter = HighlightIterator::new(
|
||||
&mut self.highlight_state,
|
||||
&ops[..],
|
||||
&self.line,
|
||||
&self.highlighter,
|
||||
);
|
||||
for (style, text) in iter {
|
||||
print!(
|
||||
"\x1b[48;2;{};{};{}m",
|
||||
style.background.r, style.background.g, style.background.b
|
||||
);
|
||||
let fg = blend_fg_color(style.foreground, style.background);
|
||||
print!("\x1b[38;2;{};{};{}m{}", fg.r, fg.g, fg.b, text);
|
||||
}
|
||||
print!("\x1b[0m");
|
||||
self.line.clear();
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
1461
src/util/dwarf.rs
1461
src/util/dwarf.rs
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue