mirror of
https://github.com/Noratrieb/elven-forest.git
synced 2026-01-14 10:45:03 +01:00
qpath parsing
This commit is contained in:
parent
a7f34d3025
commit
a5058bef51
4 changed files with 129 additions and 7 deletions
15
Cargo.lock
generated
15
Cargo.lock
generated
|
|
@ -109,6 +109,7 @@ dependencies = [
|
||||||
"clap",
|
"clap",
|
||||||
"elven-parser",
|
"elven-parser",
|
||||||
"memmap2",
|
"memmap2",
|
||||||
|
"rustc-demangle",
|
||||||
"tabled",
|
"tabled",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
@ -319,18 +320,18 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.51"
|
version = "1.0.56"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5d727cae5b39d21da60fa540906919ad737832fe0b1c165da3a34d6548c849d6"
|
checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quote"
|
name = "quote"
|
||||||
version = "1.0.23"
|
version = "1.0.26"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b"
|
checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
]
|
]
|
||||||
|
|
@ -359,6 +360,12 @@ version = "0.6.28"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848"
|
checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustc-demangle"
|
||||||
|
version = "0.1.23"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustix"
|
name = "rustix"
|
||||||
version = "0.36.8"
|
version = "0.36.8"
|
||||||
|
|
|
||||||
|
|
@ -10,4 +10,5 @@ anyhow = "1.0.69"
|
||||||
clap = { version = "4.1.6", features = ["derive"] }
|
clap = { version = "4.1.6", features = ["derive"] }
|
||||||
elven-parser = { path = "../elven-parser" }
|
elven-parser = { path = "../elven-parser" }
|
||||||
memmap2 = "0.5.8"
|
memmap2 = "0.5.8"
|
||||||
|
rustc-demangle = { version = "0.1.23", features = ["std"] }
|
||||||
tabled = "0.10.0"
|
tabled = "0.10.0"
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,9 @@
|
||||||
mod size;
|
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
fmt::Display,
|
fmt::Display,
|
||||||
fs::File,
|
fs::File,
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
};
|
};
|
||||||
|
mod size;
|
||||||
|
|
||||||
use anyhow::Context;
|
use anyhow::Context;
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
|
|
|
||||||
|
|
@ -35,8 +35,123 @@ pub fn analyze_text_bloat(elf: ElfReader<'_>) -> Result<()> {
|
||||||
symbol_sizes.reverse();
|
symbol_sizes.reverse();
|
||||||
|
|
||||||
for (sym, size) in symbol_sizes {
|
for (sym, size) in symbol_sizes {
|
||||||
println!("{size} {sym}");
|
let components =
|
||||||
|
symbol_components(std::str::from_utf8(sym)?).with_context(|| sym.to_string())?;
|
||||||
|
|
||||||
|
println!("{size} {components}");
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn symbol_components(sym: &str) -> Result<String> {
|
||||||
|
let demangled = rustc_demangle::demangle(sym).to_string();
|
||||||
|
|
||||||
|
if demangled.starts_with('<') {
|
||||||
|
let qpath = parse_qpath(&demangled).context("invalid qpath")?;
|
||||||
|
|
||||||
|
// qpath
|
||||||
|
return Ok(demangled);
|
||||||
|
} else {
|
||||||
|
// normal path
|
||||||
|
let components = demangled.split("::").collect::<Vec<_>>();
|
||||||
|
let path = components.join(";");
|
||||||
|
return Ok(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq)]
|
||||||
|
struct QPath<'a> {
|
||||||
|
qself: &'a str,
|
||||||
|
trait_: &'a str,
|
||||||
|
pathy_bit: &'a str,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_qpath(s: &str) -> Result<QPath<'_>> {
|
||||||
|
let mut chars = s.char_indices().skip(1);
|
||||||
|
let mut angle_brackets = 1u64;
|
||||||
|
|
||||||
|
let mut result = None;
|
||||||
|
let mut as_idx = None;
|
||||||
|
|
||||||
|
while let Some((idx, char)) = chars.next() {
|
||||||
|
match char {
|
||||||
|
'<' => angle_brackets += 1,
|
||||||
|
'>' => {
|
||||||
|
angle_brackets -= 1;
|
||||||
|
if angle_brackets == 0 {
|
||||||
|
result = Some(idx);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
' ' => {
|
||||||
|
if angle_brackets == 1 && as_idx == None {
|
||||||
|
as_idx = Some(idx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let q_close_idx = result.with_context(|| {
|
||||||
|
format!("qualified symbol `{s}` does not end qualified part with > properly")
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let as_idx =
|
||||||
|
as_idx.with_context(|| format!("qualified symbol `{s}` does not contain ` as `"))?;
|
||||||
|
|
||||||
|
let q = &s[..q_close_idx];
|
||||||
|
let pathy_bit = &s[q_close_idx + 1..];
|
||||||
|
let pathy_bit = pathy_bit.strip_prefix("::").with_context(|| {
|
||||||
|
format!("path after qualification does not start with `::`: `{pathy_bit}`")
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let qself = &q[1..as_idx];
|
||||||
|
let trait_ = &q[(as_idx + " as ".len())..];
|
||||||
|
|
||||||
|
Ok(QPath {
|
||||||
|
qself,
|
||||||
|
trait_,
|
||||||
|
pathy_bit,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use crate::size::QPath;
|
||||||
|
|
||||||
|
use super::{parse_qpath, symbol_components};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn parse_qpaths() {
|
||||||
|
assert_eq!(
|
||||||
|
parse_qpath("<std::path::Components as core::fmt::Debug>::fmt").unwrap(),
|
||||||
|
QPath {
|
||||||
|
qself: "std::path::Components",
|
||||||
|
trait_: "core::fmt::Debug",
|
||||||
|
pathy_bit: "fmt",
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
parse_qpath("<<std::path::Components as core::fmt::Debug>::fmt::DebugHelper as core::fmt::Debug>::fmt").unwrap(),
|
||||||
|
QPath {
|
||||||
|
qself: "<std::path::Components as core::fmt::Debug>::fmt::DebugHelper",
|
||||||
|
trait_: "core::fmt::Debug",
|
||||||
|
pathy_bit: "fmt",
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn path_debug_helper() {
|
||||||
|
// <<std::path::Components as core::fmt::Debug>::fmt::DebugHelper as core::fmt::Debug>::fmt::hc586615181f69e94
|
||||||
|
let sym = "_ZN106_$LT$$LT$std..path..Iter$u20$as$u20$core..fmt..Debug$GT$..fmt..DebugHelper$u20$as$u20$core..fmt..Debug$GT$3fmt17h4f87ac80fb33df05E";
|
||||||
|
let components = symbol_components(sym).unwrap();
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
components,
|
||||||
|
"std;path;Iter;fmt;DebugHelper;fmt;hc586615181f69e94"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue