1use std::collections::HashMap;
2
3use mlua::UserData;
4use object::{Architecture, Endianness};
5
6use crate::headers::{bitness::Bitness, custom_header::CustomHeader, section::Section};
7
8#[derive(Debug, Clone, Default)]
9pub struct HeaderContext {
10 pub bitness: Option<Bitness>,
11 pub endianness: Option<Endianness>,
12 pub entry: Option<u64>,
13 pub architecture: Option<Architecture>,
14 pub sections: Vec<Section>,
15 pub symbols: HashMap<u64, String>,
16}
17
18impl HeaderContext {
19 pub fn try_into_custom_header(self) -> Option<CustomHeader> {
20 if let (Some(bitness), Some(endianness), Some(entry), Some(architecture)) =
21 (self.bitness, self.endianness, self.entry, self.architecture)
22 {
23 let symbols_by_name = self.symbols.iter().map(|(k, v)| (v.clone(), *k)).collect();
24 Some(CustomHeader {
25 bitness,
26 entry,
27 endianness,
28 architecture,
29 sections: self.sections,
30 symbols: self.symbols,
31 symbols_by_name,
32 })
33 } else {
34 None
35 }
36 }
37}
38
39impl UserData for HeaderContext {
40 fn add_methods<'lua, M: mlua::UserDataMethods<Self>>(methods: &mut M) {
41 methods.add_method_mut("set_bitness", |_, this, bitness: u8| {
42 if this.bitness.is_some() {
43 Err(mlua::Error::external("bitness already set"))
44 } else {
45 match bitness {
46 32 => {
47 this.bitness = Some(Bitness::Bit32);
48 Ok(())
49 }
50 64 => {
51 this.bitness = Some(Bitness::Bit64);
52 Ok(())
53 }
54 _ => Err(mlua::Error::external("invalid bitness")),
55 }
56 }
57 });
58
59 methods.add_method_mut("set_entry", |_, this, entry_point: u64| {
60 if this.entry.is_some() {
61 Err(mlua::Error::external("entry point already set"))
62 } else {
63 this.entry = Some(entry_point);
64 Ok(())
65 }
66 });
67
68 methods.add_method_mut("set_endianness", |_, this, endianness: String| {
69 if this.endianness.is_some() {
70 Err(mlua::Error::external("endianness already set"))
71 } else {
72 match endianness.as_str() {
73 "little" => {
74 this.endianness = Some(Endianness::Little);
75 Ok(())
76 }
77 "big" => {
78 this.endianness = Some(Endianness::Big);
79 Ok(())
80 }
81 _ => Err(mlua::Error::external("invalid endianness")),
82 }
83 }
84 });
85
86 methods.add_method_mut("set_architecture", |_, this, architecture: String| {
87 if this.architecture.is_some() {
88 Err(mlua::Error::external("architecture already set"))
89 } else {
90 let architecture = match architecture.as_str() {
91 "Unknown" => Architecture::Unknown,
92 "Aarch64" => Architecture::Aarch64,
93 "Aarch64_Ilp32" => Architecture::Aarch64_Ilp32,
94 "Arm" => Architecture::Arm,
95 "Avr" => Architecture::Avr,
96 "Bpf" => Architecture::Bpf,
97 "Csky" => Architecture::Csky,
98 "I386" => Architecture::I386,
99 "X86_64" => Architecture::X86_64,
100 "X86_64_X32" => Architecture::X86_64_X32,
101 "Hexagon" => Architecture::Hexagon,
102 "LoongArch64" => Architecture::LoongArch64,
103 "Mips" => Architecture::Mips,
104 "Mips64" => Architecture::Mips64,
105 "Msp430" => Architecture::Msp430,
106 "PowerPc" => Architecture::PowerPc,
107 "PowerPc64" => Architecture::PowerPc64,
108 "Riscv32" => Architecture::Riscv32,
109 "Riscv64" => Architecture::Riscv64,
110 "S390x" => Architecture::S390x,
111 "Sbf" => Architecture::Sbf,
112 "Sharc" => Architecture::Sharc,
113 "Sparc" => Architecture::Sparc,
114 "Sparc32Plus" => Architecture::Sparc32Plus,
115 "Sparc64" => Architecture::Sparc64,
116 "Wasm32" => Architecture::Wasm32,
117 "Wasm64" => Architecture::Wasm64,
118 "Xtensa" => Architecture::Xtensa,
119 _ => return Err(mlua::Error::external("invalid architecture")),
120 };
121 this.architecture = Some(architecture);
122 Ok(())
123 }
124 });
125
126 methods.add_method_mut(
127 "add_section",
128 |_, this, (name, virtual_address, file_offset, size): (String, u64, u64, u64)| {
129 this.sections.push(Section {
130 name,
131 virtual_address,
132 file_offset,
133 size,
134 });
135 Ok(())
136 },
137 );
138
139 methods.add_method_mut("add_symbol", |_, this, (address, name): (u64, String)| {
140 this.symbols.insert(address, name);
141 Ok(())
142 });
143 }
144}