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
use crate::{
header,
section::{self, Section32},
segment,
};
#[repr(C)]
#[derive(Default, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)]
pub struct ELF32 {
pub ehdr: header::Ehdr32,
pub sections: Vec<section::Section32>,
pub segments: Vec<segment::Segment32>,
}
impl ELF32 {
pub fn add_section(&mut self, mut sct: section::Section32) {
let is_section_name_table = sct.name == ".shstrtab";
let last_sct_idx = self.sections.len() - 1;
self.fill_elf_info(&mut sct, last_sct_idx, &self.sections[last_sct_idx]);
self.ehdr.e_shoff += sct.header.sh_size;
self.ehdr.e_shnum += 1;
self.sections.push(sct);
if is_section_name_table {
self.ehdr.e_shstrndx = self.sections.len() as u16 - 1;
}
}
pub fn add_segment(&mut self, sgt: segment::Segment32) {
self.ehdr.e_shoff += segment::Phdr32::SIZE as u32;
for sct in self.sections.iter_mut() {
sct.header.sh_offset += segment::Phdr32::SIZE as u32;
}
self.ehdr.e_phnum += 1;
self.segments.push(sgt);
}
pub fn to_le_bytes(&self) -> Vec<u8> {
let mut file_binary: Vec<u8> = Vec::new();
let mut header_binary = self.ehdr.to_le_bytes();
file_binary.append(&mut header_binary);
for seg in self.segments.iter() {
let mut phdr_binary = seg.header.to_le_bytes();
file_binary.append(&mut phdr_binary);
}
for sct in self.sections.iter() {
let mut section_binary = sct.to_le_bytes();
file_binary.append(&mut section_binary);
}
for sct in self.sections.iter() {
let mut shdr_binary = sct.header.to_le_bytes();
file_binary.append(&mut shdr_binary);
}
file_binary
}
fn fill_elf_info(&self, new_sct: &mut Section32, prev_sct_idx: usize, prev_sct: &Section32) {
let prev_name_idx = prev_sct.header.sh_name;
let prev_name_len = prev_sct.name.as_bytes().len() as u32;
let prev_offset = prev_sct.header.sh_offset;
let prev_size = prev_sct.header.sh_size;
new_sct.header.sh_name = prev_name_idx + prev_name_len + 1;
if prev_sct_idx == 0 {
new_sct.header.sh_offset = header::Ehdr32::SIZE as u32
+ segment::Phdr32::SIZE as u32 * self.segments.len() as u32;
} else {
new_sct.header.sh_offset = prev_offset + prev_size;
}
new_sct.header.sh_size = new_sct.contents.size() as u32;
}
}