1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
use clap::{Parser, Subcommand, ValueEnum};
use std::path::PathBuf;
#[derive(Parser)]
#[command(name = "struct-audit")]
#[command(
author,
version,
about = "Analyze binary memory layouts to detect padding inefficiencies"
)]
#[command(
long_about = "struct-audit parses DWARF debugging information to visualize the physical \
layout of data structures, detect padding holes, and analyze cache line efficiency.\n\n\
Example:\n struct-audit inspect ./target/debug/myapp --filter MyStruct"
)]
pub struct Cli {
#[command(subcommand)]
pub command: Commands,
}
#[derive(Subcommand)]
pub enum Commands {
/// Analyze and display struct layouts from a binary
Inspect {
/// Path to the binary file to analyze
#[arg(value_name = "BINARY")]
binary: PathBuf,
/// Filter structs by name (substring match)
#[arg(short, long)]
filter: Option<String>,
/// Output format
#[arg(short, long, value_enum, default_value = "table")]
output: OutputFormat,
/// Sort structs by field
#[arg(short, long, value_enum, default_value = "name")]
sort_by: SortField,
/// Show only the top N structs (by sort order)
#[arg(short = 'n', long)]
top: Option<usize>,
/// Show only structs with at least N bytes of padding
#[arg(long)]
min_padding: Option<u64>,
/// Disable colored output
#[arg(long)]
no_color: bool,
/// Cache line size in bytes (must be > 0)
#[arg(long, default_value = "64", value_parser = clap::value_parser!(u32).range(1..))]
cache_line: u32,
/// Pretty-print JSON output
#[arg(long)]
pretty: bool,
},
/// Compare struct layouts between two binaries
Diff {
/// Path to the old (baseline) binary
#[arg(value_name = "OLD")]
old: PathBuf,
/// Path to the new binary
#[arg(value_name = "NEW")]
new: PathBuf,
/// Filter structs by name (substring match)
#[arg(short, long)]
filter: Option<String>,
/// Output format
#[arg(short, long, value_enum, default_value = "table")]
output: OutputFormat,
/// Cache line size in bytes (must be > 0)
#[arg(long, default_value = "64", value_parser = clap::value_parser!(u32).range(1..))]
cache_line: u32,
/// Exit with error code 1 if any regressions found (size or padding increased)
#[arg(long)]
fail_on_regression: bool,
},
/// Check struct layouts against budget constraints
Check {
/// Path to the binary file to analyze
#[arg(value_name = "BINARY")]
binary: PathBuf,
/// Path to config file (.struct-audit.yaml)
#[arg(short, long, default_value = ".struct-audit.yaml")]
config: PathBuf,
/// Cache line size in bytes (must be > 0)
#[arg(long, default_value = "64", value_parser = clap::value_parser!(u32).range(1..))]
cache_line: u32,
},
}
#[derive(Copy, Clone, PartialEq, Eq, ValueEnum)]
pub enum OutputFormat {
Table,
Json,
}
#[derive(Copy, Clone, PartialEq, Eq, ValueEnum)]
pub enum SortField {
/// Sort by struct name (alphabetical)
Name,
/// Sort by total size (largest first)
Size,
/// Sort by padding bytes (most padding first)
Padding,
/// Sort by padding percentage (worst efficiency first)
PaddingPct,
}