Rust · 2834 bytes Raw Blame History
1 use std::fmt::Write as _;
2 use std::io;
3 use std::path::Path;
4
5 use crate::icf::FoldedSymbol;
6 use crate::layout::{Layout, LayoutInput};
7 use crate::macho::writer::LinkEditPlan;
8 use crate::why_live::DeadStrippedSymbol;
9 use crate::LinkOptions;
10
11 pub fn write_link_map(
12 path: &Path,
13 opts: &LinkOptions,
14 layout: &Layout,
15 layout_inputs: &[LayoutInput<'_>],
16 linkedit: &LinkEditPlan,
17 folded_symbols: &[FoldedSymbol],
18 dead_stripped: &[DeadStrippedSymbol],
19 ) -> io::Result<()> {
20 let output_path = opts.output.as_deref().unwrap_or_else(|| Path::new("a.out"));
21 let mut out = String::new();
22
23 writeln!(&mut out, "# Path: {}", output_path.display()).unwrap();
24 writeln!(&mut out, "# Arch: arm64").unwrap();
25 writeln!(&mut out, "# Object files:").unwrap();
26 writeln!(&mut out, "[ 0] linker synthesized").unwrap();
27 for (idx, input) in layout_inputs.iter().enumerate() {
28 writeln!(&mut out, "[{:>3}] {}", idx + 1, input.object.path.display()).unwrap();
29 }
30
31 writeln!(&mut out, "\n# Sections:").unwrap();
32 writeln!(
33 &mut out,
34 "# Address Size Segment Section"
35 )
36 .unwrap();
37 for section in &layout.sections {
38 writeln!(
39 &mut out,
40 "{:#018x} {:#010x} {:<8} {}",
41 section.addr, section.size, section.segment, section.name
42 )
43 .unwrap();
44 }
45
46 writeln!(&mut out, "\n# Symbols:").unwrap();
47 writeln!(&mut out, "# Address Size File Name").unwrap();
48 let mut symbols = linkedit.map_symbols.clone();
49 symbols.sort_by(|lhs, rhs| {
50 lhs.addr
51 .cmp(&rhs.addr)
52 .then_with(|| lhs.name.cmp(&rhs.name))
53 });
54 for symbol in &symbols {
55 let file = if symbol.file_index == 0 {
56 "linker".to_string()
57 } else {
58 format!("[{:>3}]", symbol.file_index)
59 };
60 writeln!(
61 &mut out,
62 "{:#018x} {:#010x} {:<7} {}",
63 symbol.addr, symbol.size, file, symbol.name
64 )
65 .unwrap();
66 }
67
68 writeln!(&mut out, "\n# Folded symbols:").unwrap();
69 for symbol in folded_symbols {
70 let file = if symbol.file_index == 0 {
71 "linker".to_string()
72 } else {
73 format!("[{:>3}]", symbol.file_index)
74 };
75 writeln!(
76 &mut out,
77 "{:<7} {} folded to {}",
78 file, symbol.name, symbol.winner
79 )
80 .unwrap();
81 }
82
83 writeln!(&mut out, "\n# Dead stripped:").unwrap();
84 for symbol in dead_stripped {
85 let file = if symbol.file_index == 0 {
86 "linker".to_string()
87 } else {
88 format!("[{:>3}]", symbol.file_index)
89 };
90 writeln!(&mut out, "{:<7} {}", file, symbol.name).unwrap();
91 }
92
93 std::fs::write(path, out)
94 }
95