sbpf_assembler/
section.rs

1use crate::astnode::ASTNode;
2use crate::astnode::ROData;
3use crate::debuginfo::DebugInfo;
4use crate::dynsym::DynamicSymbol;
5use crate::dynsym::RelDyn;
6use crate::header::SectionHeader;
7use crate::lexer::Token;
8use std::collections::HashMap;
9
10// Base Section trait
11pub trait Section {
12    fn name(&self) -> &str {
13        ".unknown" // Default section name
14    }
15
16    fn bytecode(&self) -> Vec<u8> {
17        Vec::new() // Default empty bytecode
18    }
19
20    // fn get_size(&self) -> u64
21    fn size(&self) -> u64 {
22        self.bytecode().len() as u64
23    }
24
25    // fn get_aligned_size(&self) -> u64
26
27    // fn section_header_bytecode(&self) -> Vec<u8>
28}
29
30// Code Section implementation
31#[derive(Debug)]
32pub struct CodeSection {
33    name: String,
34    nodes: Vec<ASTNode>,
35    size: u64,
36    offset: u64,
37    debug_map: HashMap<u64, DebugInfo>,
38}
39
40impl CodeSection {
41    pub fn new(nodes: Vec<ASTNode>, size: u64) -> Self {
42        let mut debug_map = HashMap::new();
43        for node in &nodes {
44            if let Some((_, node_debug_map)) = node.bytecode_with_debug_map() {
45                debug_map.extend(node_debug_map);
46            }
47        }
48        Self {
49            name: String::from(".text"),
50            nodes,
51            size,
52            offset: 0,
53            debug_map,
54        }
55    }
56
57    pub fn get_nodes(&self) -> &Vec<ASTNode> {
58        &self.nodes
59    }
60
61    pub fn get_size(&self) -> u64 {
62        self.size
63    }
64
65    pub fn get_debug_map(&self) -> &HashMap<u64, DebugInfo> {
66        &self.debug_map
67    }
68
69    pub fn set_offset(&mut self, offset: u64) {
70        self.offset = offset;
71    }
72
73    pub fn section_header_bytecode(&self) -> Vec<u8> {
74        let flags = SectionHeader::SHF_ALLOC | SectionHeader::SHF_EXECINSTR;
75        SectionHeader::new(
76            1,
77            SectionHeader::SHT_PROGBITS,
78            flags,
79            self.offset,
80            self.offset,
81            self.size,
82            0,
83            0,
84            4,
85            0,
86        )
87        .bytecode()
88    }
89}
90
91impl Section for CodeSection {
92    fn name(&self) -> &str {
93        &self.name
94    }
95
96    fn bytecode(&self) -> Vec<u8> {
97        let mut bytecode = Vec::new();
98        for node in &self.nodes {
99            if let Some(node_bytes) = node.bytecode() {
100                bytecode.extend(node_bytes);
101            }
102        }
103        bytecode
104    }
105
106    fn size(&self) -> u64 {
107        self.size
108    }
109}
110
111// Data Section implementation
112#[derive(Debug)]
113pub struct DataSection {
114    name: String,
115    nodes: Vec<ASTNode>,
116    size: u64,
117    offset: u64,
118}
119
120impl DataSection {
121    pub fn new(nodes: Vec<ASTNode>, size: u64) -> Self {
122        Self {
123            name: String::from(".rodata"),
124            nodes,
125            size,
126            offset: 0,
127        }
128    }
129
130    pub fn get_nodes(&self) -> &Vec<ASTNode> {
131        &self.nodes
132    }
133
134    pub fn get_size(&self) -> u64 {
135        self.size
136    }
137
138    pub fn set_offset(&mut self, offset: u64) {
139        self.offset = offset;
140    }
141
142    pub fn rodata(&self) -> Vec<(String, usize, String)> {
143        let mut ro_data_labels = Vec::new();
144        for node in &self.nodes {
145            if let ASTNode::ROData {
146                rodata: ROData { name, args, .. },
147                offset,
148            } = node
149            {
150                if let Some(Token::StringLiteral(str_literal, _)) = args.get(1) {
151                    ro_data_labels.push((name.clone(), *offset as usize, str_literal.clone()));
152                }
153            }
154        }
155        ro_data_labels
156    }
157
158    pub fn section_header_bytecode(&self) -> Vec<u8> {
159        let flags = SectionHeader::SHF_ALLOC; // Read-only data
160        SectionHeader::new(
161            7,
162            SectionHeader::SHT_PROGBITS,
163            flags,
164            self.offset,
165            self.offset,
166            self.size,
167            0,
168            0,
169            1,
170            0,
171        )
172        .bytecode()
173    }
174}
175
176impl Section for DataSection {
177    fn name(&self) -> &str {
178        &self.name
179    }
180
181    fn size(&self) -> u64 {
182        self.size
183    }
184
185    fn bytecode(&self) -> Vec<u8> {
186        let mut bytecode = Vec::new();
187        for node in &self.nodes {
188            if let Some(node_bytes) = node.bytecode() {
189                bytecode.extend(node_bytes);
190            }
191        }
192        // Add padding to make size multiple of 8
193        while bytecode.len() % 8 != 0 {
194            bytecode.push(0);
195        }
196
197        bytecode
198    }
199}
200
201#[derive(Debug, Default)]
202pub struct NullSection {
203    name: String,
204    offset: u64,
205}
206
207impl NullSection {
208    pub fn new() -> Self {
209        Self::default()
210    }
211
212    pub fn section_header_bytecode(&self) -> Vec<u8> {
213        SectionHeader::new(0, SectionHeader::SHT_NULL, 0, 0, 0, 0, 0, 0, 0, 0).bytecode()
214    }
215}
216
217impl Section for NullSection {
218    // We can use all default implementations from the Section trait
219}
220
221#[derive(Debug)]
222pub struct ShStrTabSection {
223    name: String,
224    name_offset: u32,
225    section_names: Vec<String>,
226    offset: u64,
227}
228
229impl ShStrTabSection {
230    pub fn new(name_offset: u32, section_names: Vec<String>) -> Self {
231        Self {
232            name: String::from(".s"),
233            name_offset,
234            section_names: {
235                let mut names = section_names;
236                names.push(".s".to_string());
237                names
238            },
239            offset: 0,
240        }
241    }
242
243    pub fn set_offset(&mut self, offset: u64) {
244        self.offset = offset;
245    }
246
247    pub fn section_header_bytecode(&self) -> Vec<u8> {
248        SectionHeader::new(
249            self.name_offset,
250            SectionHeader::SHT_STRTAB,
251            0,
252            0,
253            self.offset,
254            self.size(),
255            0,
256            0,
257            1,
258            0,
259        )
260        .bytecode()
261    }
262}
263
264impl Section for ShStrTabSection {
265    fn name(&self) -> &str {
266        &self.name
267    }
268
269    fn bytecode(&self) -> Vec<u8> {
270        let mut bytes = Vec::new();
271        // First byte is null
272        bytes.push(0);
273
274        // Add each non-empty section name with null terminator
275        for name in &self.section_names {
276            if !name.is_empty() {
277                bytes.extend(name.as_bytes());
278                bytes.push(0); // null terminator
279            }
280        }
281
282        // Add padding to make size multiple of 8
283        while bytes.len() % 8 != 0 {
284            bytes.push(0);
285        }
286
287        bytes
288    }
289
290    fn size(&self) -> u64 {
291        // Calculate section header offset
292        let mut section_name_size = 0;
293
294        for name in &self.section_names {
295            if !name.is_empty() {
296                section_name_size += 1 + name.len();
297            }
298        }
299
300        section_name_size += 1; // null section
301
302        section_name_size as u64 // Return the calculated size
303    }
304}
305
306#[derive(Debug)]
307pub struct DynamicSection {
308    name: String,
309    name_offset: u32,
310    offset: u64,
311    rel_offset: u64,
312    rel_size: u64,
313    rel_count: u64,
314    dynsym_offset: u64,
315    dynstr_offset: u64,
316    dynstr_size: u64,
317}
318
319impl DynamicSection {
320    pub fn new(name_offset: u32) -> Self {
321        Self {
322            name: String::from(".dynamic"),
323            name_offset,
324            offset: 0,
325            rel_offset: 0,
326            rel_size: 0,
327            rel_count: 0,
328            dynsym_offset: 0,
329            dynstr_offset: 0,
330            dynstr_size: 0,
331        }
332    }
333
334    pub fn set_offset(&mut self, offset: u64) {
335        self.offset = offset;
336    }
337
338    pub fn set_rel_offset(&mut self, offset: u64) {
339        self.rel_offset = offset;
340    }
341
342    pub fn set_rel_size(&mut self, size: u64) {
343        self.rel_size = size;
344    }
345
346    pub fn set_rel_count(&mut self, count: u64) {
347        self.rel_count = count;
348    }
349
350    pub fn set_dynsym_offset(&mut self, offset: u64) {
351        self.dynsym_offset = offset;
352    }
353
354    pub fn set_dynstr_offset(&mut self, offset: u64) {
355        self.dynstr_offset = offset;
356    }
357
358    pub fn set_dynstr_size(&mut self, size: u64) {
359        self.dynstr_size = size;
360    }
361
362    pub fn section_header_bytecode(&self) -> Vec<u8> {
363        SectionHeader::new(
364            self.name_offset,
365            SectionHeader::SHT_DYNAMIC,
366            SectionHeader::SHF_ALLOC | SectionHeader::SHF_WRITE,
367            self.offset,
368            self.offset,
369            self.size(),
370            5,
371            0,
372            8,
373            16,
374        )
375        .bytecode()
376    }
377}
378
379impl Section for DynamicSection {
380    fn name(&self) -> &str {
381        &self.name
382    }
383
384    fn bytecode(&self) -> Vec<u8> {
385        let mut bytes = Vec::new();
386
387        // DT_FLAGS (DF_TEXTREL)
388        bytes.extend_from_slice(&0x1e_u64.to_le_bytes());
389        bytes.extend_from_slice(&0x04_u64.to_le_bytes());
390
391        // DT_REL
392        bytes.extend_from_slice(&0x11_u64.to_le_bytes());
393        bytes.extend_from_slice(&self.rel_offset.to_le_bytes());
394
395        // DT_RELSZ
396        bytes.extend_from_slice(&0x12_u64.to_le_bytes());
397        bytes.extend_from_slice(&self.rel_size.to_le_bytes());
398
399        // DT_RELENT
400        bytes.extend_from_slice(&0x13_u64.to_le_bytes());
401        bytes.extend_from_slice(&0x10_u64.to_le_bytes()); // Constant: 16 bytes per entry
402
403        // DT_RELCOUNT: number of relative relocation entries
404        if self.rel_count > 0 {
405            bytes.extend_from_slice(&0x6fff_fffa_u64.to_le_bytes());
406            bytes.extend_from_slice(&self.rel_count.to_le_bytes());
407        }
408
409        // DT_SYMTAB
410        bytes.extend_from_slice(&0x06_u64.to_le_bytes());
411        bytes.extend_from_slice(&self.dynsym_offset.to_le_bytes());
412
413        // DT_SYMENT
414        bytes.extend_from_slice(&0x0b_u64.to_le_bytes());
415        bytes.extend_from_slice(&0x18_u64.to_le_bytes()); // Constant: 24 bytes per symbol
416
417        // DT_STRTAB
418        bytes.extend_from_slice(&0x05_u64.to_le_bytes());
419        bytes.extend_from_slice(&self.dynstr_offset.to_le_bytes());
420
421        // DT_STRSZ
422        bytes.extend_from_slice(&0x0a_u64.to_le_bytes());
423        bytes.extend_from_slice(&self.dynstr_size.to_le_bytes());
424
425        // DT_TEXTREL
426        bytes.extend_from_slice(&0x16_u64.to_le_bytes());
427        bytes.extend_from_slice(&0x00_u64.to_le_bytes());
428
429        // DT_NULL
430        bytes.extend_from_slice(&0x00_u64.to_le_bytes());
431        bytes.extend_from_slice(&0x00_u64.to_le_bytes());
432
433        bytes
434    }
435
436    fn size(&self) -> u64 {
437        if self.rel_count > 0 { 11 * 16 } else { 10 * 16 }
438    }
439}
440
441#[derive(Debug)]
442pub struct DynStrSection {
443    name: String,
444    name_offset: u32,
445    symbol_names: Vec<String>,
446    offset: u64,
447}
448
449impl DynStrSection {
450    pub fn new(name_offset: u32, symbol_names: Vec<String>) -> Self {
451        Self {
452            name: String::from(".dynstr"),
453            name_offset,
454            symbol_names,
455            offset: 0,
456        }
457    }
458
459    pub fn set_offset(&mut self, offset: u64) {
460        self.offset = offset;
461    }
462
463    pub fn section_header_bytecode(&self) -> Vec<u8> {
464        SectionHeader::new(
465            self.name_offset,
466            SectionHeader::SHT_STRTAB,
467            SectionHeader::SHF_ALLOC, // Allocatable section
468            self.offset,
469            self.offset,
470            self.size(),
471            0,
472            0,
473            1,
474            0,
475        )
476        .bytecode()
477    }
478}
479
480impl Section for DynStrSection {
481    fn name(&self) -> &str {
482        &self.name
483    }
484
485    fn bytecode(&self) -> Vec<u8> {
486        let mut bytes = Vec::new();
487        // First byte is null
488        bytes.push(0);
489
490        // Add each symbol name with null terminator
491        for name in &self.symbol_names {
492            bytes.extend(name.as_bytes());
493            bytes.push(0); // null terminator
494        }
495        // add padding to make size multiple of 8
496        while bytes.len() % 8 != 0 {
497            bytes.push(0);
498        }
499        bytes
500    }
501
502    fn size(&self) -> u64 {
503        // Calculate total size: initial null byte + sum of (name lengths + null terminators)
504        let mut size = 1 + self
505            .symbol_names
506            .iter()
507            .map(|name| name.len() + 1)
508            .sum::<usize>();
509        // add padding to make size multiple of 8
510        while size % 8 != 0 {
511            size += 1;
512        }
513        size as u64
514    }
515}
516
517#[derive(Debug)]
518pub struct DynSymSection {
519    name: String,
520    name_offset: u32,
521    offset: u64,
522    symbols: Vec<DynamicSymbol>,
523}
524
525impl DynSymSection {
526    pub fn new(name_offset: u32, symbols: Vec<DynamicSymbol>) -> Self {
527        Self {
528            name: String::from(".dynsym"),
529            name_offset,
530            offset: 0,
531            symbols,
532        }
533    }
534
535    pub fn set_offset(&mut self, offset: u64) {
536        self.offset = offset;
537    }
538
539    pub fn section_header_bytecode(&self) -> Vec<u8> {
540        let flags = SectionHeader::SHF_ALLOC;
541        SectionHeader::new(
542            self.name_offset,
543            SectionHeader::SHT_DYNSYM,
544            flags,
545            self.offset,
546            self.offset,
547            self.size(),
548            5,
549            1,
550            8,
551            24,
552        )
553        .bytecode()
554    }
555}
556
557impl Section for DynSymSection {
558    fn name(&self) -> &str {
559        &self.name
560    }
561
562    fn size(&self) -> u64 {
563        // Each symbol entry is 24 bytes
564        (self.symbols.len() as u64) * 24
565    }
566
567    fn bytecode(&self) -> Vec<u8> {
568        let mut bytes = Vec::new();
569        for symbol in &self.symbols {
570            bytes.extend(symbol.bytecode());
571        }
572        bytes
573    }
574}
575
576#[derive(Debug)]
577pub struct RelDynSection {
578    name: String,
579    name_offset: u32,
580    offset: u64,
581    entries: Vec<RelDyn>,
582}
583
584impl RelDynSection {
585    pub fn new(name_offset: u32, entries: Vec<RelDyn>) -> Self {
586        Self {
587            name: String::from(".rel.dyn"),
588            name_offset,
589            offset: 0,
590            entries,
591        }
592    }
593
594    pub fn set_offset(&mut self, offset: u64) {
595        self.offset = offset;
596    }
597
598    pub fn size(&self) -> u64 {
599        (self.entries.len() * 16) as u64 // Each RelDyn entry is 16 bytes
600    }
601
602    pub fn section_header_bytecode(&self) -> Vec<u8> {
603        let flags = SectionHeader::SHF_ALLOC;
604        SectionHeader::new(
605            self.name_offset,
606            SectionHeader::SHT_REL,
607            flags,
608            self.offset,
609            self.offset,
610            self.size(),
611            4,
612            0,
613            8,
614            16,
615        )
616        .bytecode()
617    }
618}
619
620impl Section for RelDynSection {
621    fn name(&self) -> &str {
622        &self.name
623    }
624
625    fn size(&self) -> u64 {
626        self.size()
627    }
628
629    fn bytecode(&self) -> Vec<u8> {
630        let mut bytes = Vec::new();
631        for entry in &self.entries {
632            bytes.extend(entry.bytecode());
633        }
634        bytes
635    }
636}
637
638#[derive(Debug)]
639pub enum SectionType {
640    Code(CodeSection),
641    Data(DataSection),
642    ShStrTab(ShStrTabSection),
643    Dynamic(DynamicSection),
644    DynStr(DynStrSection),
645    DynSym(DynSymSection),
646    Default(NullSection),
647    RelDyn(RelDynSection),
648}
649
650impl SectionType {
651    pub fn name(&self) -> &str {
652        match self {
653            SectionType::Code(cs) => &cs.name,
654            SectionType::Data(ds) => &ds.name,
655            SectionType::ShStrTab(ss) => &ss.name,
656            SectionType::Dynamic(ds) => &ds.name,
657            SectionType::DynStr(ds) => &ds.name,
658            SectionType::DynSym(ds) => &ds.name,
659            SectionType::Default(ds) => &ds.name,
660            SectionType::RelDyn(ds) => &ds.name,
661        }
662    }
663
664    pub fn bytecode(&self) -> Vec<u8> {
665        match self {
666            SectionType::Code(cs) => cs.bytecode(),
667            SectionType::Data(ds) => ds.bytecode(),
668            SectionType::ShStrTab(ss) => ss.bytecode(),
669            SectionType::Dynamic(ds) => ds.bytecode(),
670            SectionType::DynStr(ds) => ds.bytecode(),
671            SectionType::DynSym(ds) => ds.bytecode(),
672            SectionType::Default(ds) => ds.bytecode(),
673            SectionType::RelDyn(ds) => ds.bytecode(),
674        }
675    }
676
677    pub fn size(&self) -> u64 {
678        match self {
679            SectionType::Code(cs) => cs.size(),
680            SectionType::Data(ds) => ds.size(),
681            SectionType::ShStrTab(ss) => ss.size(),
682            SectionType::Dynamic(ds) => ds.size(),
683            SectionType::DynStr(ds) => ds.size(),
684            SectionType::DynSym(ds) => ds.size(),
685            SectionType::Default(ds) => ds.size(),
686            SectionType::RelDyn(ds) => ds.size(),
687        }
688    }
689
690    pub fn section_header_bytecode(&self) -> Vec<u8> {
691        match self {
692            SectionType::Code(cs) => cs.section_header_bytecode(),
693            SectionType::Data(ds) => ds.section_header_bytecode(),
694            SectionType::ShStrTab(ss) => ss.section_header_bytecode(),
695            SectionType::Dynamic(ds) => ds.section_header_bytecode(),
696            SectionType::DynStr(ds) => ds.section_header_bytecode(),
697            SectionType::DynSym(ds) => ds.section_header_bytecode(),
698            SectionType::Default(ds) => ds.section_header_bytecode(),
699            SectionType::RelDyn(ds) => ds.section_header_bytecode(),
700        }
701    }
702
703    pub fn set_offset(&mut self, offset: u64) {
704        match self {
705            SectionType::Code(cs) => cs.set_offset(offset),
706            SectionType::Data(ds) => ds.set_offset(offset),
707            SectionType::ShStrTab(ss) => ss.set_offset(offset),
708            SectionType::Dynamic(ds) => ds.set_offset(offset),
709            SectionType::DynStr(ds) => ds.set_offset(offset),
710            SectionType::DynSym(ds) => ds.set_offset(offset),
711            SectionType::RelDyn(ds) => ds.set_offset(offset),
712            SectionType::Default(_) => (), // NullSection doesn't need offset
713        }
714    }
715
716    pub fn offset(&self) -> u64 {
717        match self {
718            SectionType::Code(cs) => cs.offset,
719            SectionType::Data(ds) => ds.offset,
720            SectionType::ShStrTab(ss) => ss.offset,
721            SectionType::Dynamic(ds) => ds.offset,
722            SectionType::DynStr(ds) => ds.offset,
723            SectionType::DynSym(ds) => ds.offset,
724            SectionType::Default(ns) => ns.offset,
725            SectionType::RelDyn(rs) => rs.offset,
726        }
727    }
728}