program.rs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  1. use {
  2. crate::{
  3. debuginfo::DebugInfo,
  4. dynsym::{DynamicSymbol, RelDyn, RelocationType},
  5. header::{ElfHeader, ProgramHeader},
  6. parser::ParseResult,
  7. section::{
  8. DynStrSection, DynSymSection, DynamicSection, NullSection, RelDynSection, Section,
  9. SectionType, ShStrTabSection,
  10. },
  11. },
  12. std::{collections::HashMap, fs::File, io::Write, path::Path},
  13. };
  14. #[derive(Debug)]
  15. pub struct Program {
  16. pub elf_header: ElfHeader,
  17. pub program_headers: Option<Vec<ProgramHeader>>,
  18. pub sections: Vec<SectionType>,
  19. }
  20. impl Program {
  21. pub fn from_parse_result(
  22. ParseResult {
  23. code_section,
  24. data_section,
  25. dynamic_symbols,
  26. relocation_data,
  27. prog_is_static,
  28. }: ParseResult,
  29. ) -> Self {
  30. let mut elf_header = ElfHeader::new();
  31. let mut program_headers = None;
  32. // omit program headers if static
  33. let ph_count = if prog_is_static { 0 } else { 3 };
  34. elf_header.e_phnum = ph_count;
  35. // save read + execute size for program header before
  36. // ownership of code/data sections is transferred
  37. let text_size = code_section.size() + data_section.size();
  38. // Calculate base offset after ELF header and program headers
  39. let mut current_offset = 64 + (ph_count as u64 * 56); // 64 bytes ELF header, 56 bytes per program header
  40. elf_header.e_entry = current_offset;
  41. // Create a vector of sections
  42. let mut sections = Vec::new();
  43. sections.push(SectionType::Default(NullSection::new()));
  44. let mut section_names = Vec::new();
  45. // Code section
  46. let mut text_section = SectionType::Code(code_section);
  47. text_section.set_offset(current_offset);
  48. current_offset += text_section.size();
  49. section_names.push(text_section.name().to_string());
  50. sections.push(text_section);
  51. // Data section
  52. if data_section.size() > 0 {
  53. let mut rodata_section = SectionType::Data(data_section);
  54. rodata_section.set_offset(current_offset);
  55. current_offset += rodata_section.size();
  56. section_names.push(rodata_section.name().to_string());
  57. sections.push(rodata_section);
  58. }
  59. let padding = (8 - (current_offset % 8)) % 8;
  60. current_offset += padding;
  61. if !prog_is_static {
  62. let mut symbol_names = Vec::new();
  63. let mut dyn_syms = Vec::new();
  64. let mut dyn_str_offset = 1;
  65. dyn_syms.push(DynamicSymbol::new(0, 0, 0, 0, 0, 0));
  66. // all symbols handled right now are all global symbols
  67. for (name, _) in dynamic_symbols.get_entry_points() {
  68. symbol_names.push(name.clone());
  69. dyn_syms.push(DynamicSymbol::new(
  70. dyn_str_offset as u32,
  71. 0x10,
  72. 0,
  73. 1,
  74. elf_header.e_entry,
  75. 0,
  76. ));
  77. dyn_str_offset += name.len() + 1;
  78. }
  79. for (name, _) in dynamic_symbols.get_call_targets() {
  80. symbol_names.push(name.clone());
  81. dyn_syms.push(DynamicSymbol::new(dyn_str_offset as u32, 0x10, 0, 0, 0, 0));
  82. dyn_str_offset += name.len() + 1;
  83. }
  84. let mut rel_count = 0;
  85. let mut rel_dyns = Vec::new();
  86. for (offset, rel_type, name) in relocation_data.get_rel_dyns() {
  87. if rel_type == RelocationType::RSbfSyscall {
  88. if let Some(index) = symbol_names.iter().position(|n| *n == name) {
  89. rel_dyns.push(RelDyn::new(
  90. offset + elf_header.e_entry,
  91. rel_type as u64,
  92. index as u64 + 1,
  93. ));
  94. } else {
  95. panic!("Symbol {} not found in symbol_names", name);
  96. }
  97. } else if rel_type == RelocationType::RSbf64Relative {
  98. rel_count += 1;
  99. rel_dyns.push(RelDyn::new(offset + elf_header.e_entry, rel_type as u64, 0));
  100. }
  101. }
  102. let mut dynamic_section = SectionType::Dynamic(DynamicSection::new(
  103. (section_names
  104. .iter()
  105. .map(|name| name.len() + 1)
  106. .sum::<usize>()
  107. + 1) as u32,
  108. ));
  109. dynamic_section.set_offset(current_offset);
  110. if let SectionType::Dynamic(ref mut dynamic_section) = dynamic_section {
  111. dynamic_section.set_rel_count(rel_count);
  112. }
  113. current_offset += dynamic_section.size();
  114. section_names.push(dynamic_section.name().to_string());
  115. let mut dynsym_section = SectionType::DynSym(DynSymSection::new(
  116. (section_names
  117. .iter()
  118. .map(|name| name.len() + 1)
  119. .sum::<usize>()
  120. + 1) as u32,
  121. dyn_syms,
  122. ));
  123. dynsym_section.set_offset(current_offset);
  124. current_offset += dynsym_section.size();
  125. section_names.push(dynsym_section.name().to_string());
  126. let mut dynstr_section = SectionType::DynStr(DynStrSection::new(
  127. (section_names
  128. .iter()
  129. .map(|name| name.len() + 1)
  130. .sum::<usize>()
  131. + 1) as u32,
  132. symbol_names,
  133. ));
  134. dynstr_section.set_offset(current_offset);
  135. current_offset += dynstr_section.size();
  136. section_names.push(dynstr_section.name().to_string());
  137. let mut rel_dyn_section = SectionType::RelDyn(RelDynSection::new(
  138. (section_names
  139. .iter()
  140. .map(|name| name.len() + 1)
  141. .sum::<usize>()
  142. + 1) as u32,
  143. rel_dyns,
  144. ));
  145. rel_dyn_section.set_offset(current_offset);
  146. current_offset += rel_dyn_section.size();
  147. section_names.push(rel_dyn_section.name().to_string());
  148. if let SectionType::Dynamic(ref mut dynamic_section) = dynamic_section {
  149. dynamic_section.set_rel_offset(rel_dyn_section.offset());
  150. dynamic_section.set_rel_size(rel_dyn_section.size());
  151. dynamic_section.set_dynsym_offset(dynsym_section.offset());
  152. dynamic_section.set_dynstr_offset(dynstr_section.offset());
  153. dynamic_section.set_dynstr_size(dynstr_section.size());
  154. }
  155. let mut shstrtab_section = SectionType::ShStrTab(ShStrTabSection::new(
  156. (section_names
  157. .iter()
  158. .map(|name| name.len() + 1)
  159. .sum::<usize>()
  160. + 1) as u32,
  161. section_names,
  162. ));
  163. shstrtab_section.set_offset(current_offset);
  164. current_offset += shstrtab_section.size();
  165. program_headers = Some(vec![
  166. ProgramHeader::new_load(
  167. elf_header.e_entry,
  168. text_size,
  169. true, // executable
  170. ),
  171. ProgramHeader::new_load(
  172. dynsym_section.offset(),
  173. dynsym_section.size() + dynstr_section.size() + rel_dyn_section.size(),
  174. false,
  175. ),
  176. ProgramHeader::new_dynamic(dynamic_section.offset(), dynamic_section.size()),
  177. ]);
  178. sections.push(dynamic_section);
  179. sections.push(dynsym_section);
  180. sections.push(dynstr_section);
  181. sections.push(rel_dyn_section);
  182. sections.push(shstrtab_section);
  183. } else {
  184. // Create a vector of section names
  185. let mut section_names = Vec::new();
  186. for section in &sections {
  187. section_names.push(section.name().to_string());
  188. }
  189. let mut shstrtab_section = ShStrTabSection::new(
  190. section_names
  191. .iter()
  192. .map(|name| name.len() + 1)
  193. .sum::<usize>() as u32,
  194. section_names,
  195. );
  196. shstrtab_section.set_offset(current_offset);
  197. current_offset += shstrtab_section.size();
  198. sections.push(SectionType::ShStrTab(shstrtab_section));
  199. }
  200. // Update section header offset in ELF header
  201. let padding = (8 - (current_offset % 8)) % 8;
  202. elf_header.e_shoff = current_offset + padding;
  203. elf_header.e_shnum = sections.len() as u16;
  204. elf_header.e_shstrndx = sections.len() as u16 - 1;
  205. Self {
  206. elf_header,
  207. program_headers,
  208. sections,
  209. }
  210. }
  211. pub fn emit_bytecode(&self) -> Vec<u8> {
  212. let mut bytes = Vec::new();
  213. // Emit ELF Header bytes
  214. bytes.extend(self.elf_header.bytecode());
  215. // Emit program headers
  216. if self.program_headers.is_some() {
  217. for ph in self.program_headers.as_ref().unwrap() {
  218. bytes.extend(ph.bytecode());
  219. }
  220. }
  221. // Emit sections
  222. for section in &self.sections {
  223. bytes.extend(section.bytecode());
  224. }
  225. // Emit section headers
  226. for section in &self.sections {
  227. bytes.extend(section.section_header_bytecode());
  228. }
  229. bytes
  230. }
  231. pub fn has_rodata(&self) -> bool {
  232. self.sections.iter().any(|s| s.name() == ".rodata")
  233. }
  234. pub fn parse_rodata(&self) -> Vec<(String, usize, String)> {
  235. let rodata = self
  236. .sections
  237. .iter()
  238. .find(|s| s.name() == ".rodata")
  239. .unwrap();
  240. if let SectionType::Data(data_section) = rodata {
  241. data_section.rodata()
  242. } else {
  243. panic!("ROData section not found");
  244. }
  245. }
  246. pub fn get_debug_map(&self) -> HashMap<u64, DebugInfo> {
  247. let code = self.sections.iter().find(|s| s.name() == ".text").unwrap();
  248. if let SectionType::Code(code_section) = code {
  249. code_section.get_debug_map().clone()
  250. } else {
  251. panic!("Code section not found");
  252. }
  253. }
  254. pub fn save_to_file(&self, input_path: &str) -> std::io::Result<()> {
  255. // Get the file stem (name without extension) from input path
  256. let path = Path::new(input_path);
  257. let file_stem = path
  258. .file_stem()
  259. .and_then(|s| s.to_str())
  260. .unwrap_or("output");
  261. // Create the output file name with .so extension
  262. let output_path = format!("{}.so", file_stem);
  263. // Get the bytecode
  264. let bytes = self.emit_bytecode();
  265. // Write bytes to file
  266. let mut file = File::create(output_path)?;
  267. file.write_all(&bytes)?;
  268. Ok(())
  269. }
  270. }