Rust · 2418 bytes Raw Blame History
1 //! afs-ld — standalone ARM64 Mach-O linker.
2 //!
3 //! Sprint 0 scaffolding: public surface is declared but every link attempt
4 //! returns `LinkError::NotYetImplemented`. Subsequent sprints fill in the
5 //! reader, resolver, layout, reloc, synth, writer, and signing paths.
6
7 pub mod archive;
8 pub mod args;
9 pub mod diag;
10 pub mod dump;
11 pub mod input;
12 pub mod leb;
13 pub mod macho;
14 pub mod reloc;
15 pub mod section;
16 pub mod string_table;
17 pub mod symbol;
18
19 use std::path::PathBuf;
20
21 /// What kind of Mach-O file the linker is producing.
22 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
23 pub enum OutputKind {
24 Executable,
25 Dylib,
26 }
27
28 /// User-facing linker configuration, populated by the CLI parser.
29 #[derive(Debug, Clone)]
30 pub struct LinkOptions {
31 pub inputs: Vec<PathBuf>,
32 pub output: Option<PathBuf>,
33 pub entry: Option<String>,
34 pub arch: Option<String>,
35 pub kind: OutputKind,
36 /// When set, afs-ld operates in dump mode and prints the given file's
37 /// header + load commands instead of linking.
38 pub dump: Option<PathBuf>,
39 /// When set, afs-ld dumps the named static archive's structure.
40 pub dump_archive: Option<PathBuf>,
41 }
42
43 impl Default for LinkOptions {
44 fn default() -> Self {
45 Self {
46 inputs: Vec::new(),
47 output: None,
48 entry: None,
49 arch: None,
50 kind: OutputKind::Executable,
51 dump: None,
52 dump_archive: None,
53 }
54 }
55 }
56
57 #[derive(Debug)]
58 pub enum LinkError {
59 /// No input files were provided on the command line.
60 NoInputs,
61 /// Path to this sprint's incomplete functionality.
62 NotYetImplemented(&'static str),
63 }
64
65 impl std::fmt::Display for LinkError {
66 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
67 match self {
68 LinkError::NoInputs => write!(f, "no input files"),
69 LinkError::NotYetImplemented(what) => write!(f, "not yet implemented: {what}"),
70 }
71 }
72 }
73
74 /// The linker itself. Sprint 0 only validates that inputs exist; later sprints
75 /// grow this into the full pipeline described in `.docs/overview.md`.
76 pub struct Linker;
77
78 impl Linker {
79 pub fn run(opts: &LinkOptions) -> Result<(), LinkError> {
80 if opts.inputs.is_empty() {
81 return Err(LinkError::NoInputs);
82 }
83 Err(LinkError::NotYetImplemented(
84 "input parsing (Sprint 1) lands next",
85 ))
86 }
87 }
88