Skip to main content

sbpf_assembler/
section.rs

1use crate::{
2    astnode::{ASTNode, ROData},
3    dynsym::{DynamicSymbol, RelDyn},
4    header::SectionHeader,
5    parser::Token,
6};
7
8// Base Section trait
9pub trait Section {
10    fn name(&self) -> &str {
11        ".unknown" // Default section name
12    }
13
14    fn bytecode(&self) -> Vec<u8> {
15        Vec::new() // Default empty bytecode
16    }
17
18    // fn get_size(&self) -> u64
19    fn size(&self) -> u64 {
20        self.bytecode().len() as u64
21    }
22
23    // fn get_aligned_size(&self) -> u64
24
25    // fn section_header_bytecode(&self) -> Vec<u8>
26}
27
28// Code Section implementation
29#[derive(Debug)]
30pub struct CodeSection {
31    name: String,
32    nodes: Vec<ASTNode>,
33    size: u64,
34    offset: u64,
35}
36
37impl CodeSection {
38    pub fn new(nodes: Vec<ASTNode>, size: u64) -> Self {
39        Self {
40            name: String::from(".text"),
41            nodes,
42            size,
43            offset: 0,
44        }
45    }
46
47    pub fn get_nodes(&self) -> &Vec<ASTNode> {
48        &self.nodes
49    }
50
51    pub fn get_size(&self) -> u64 {
52        self.size
53    }
54
55    pub fn set_offset(&mut self, offset: u64) {
56        self.offset = offset;
57    }
58
59    pub fn section_header_bytecode(&self) -> Vec<u8> {
60        let flags = SectionHeader::SHF_ALLOC | SectionHeader::SHF_EXECINSTR;
61        SectionHeader::new(
62            1,
63            SectionHeader::SHT_PROGBITS,
64            flags,
65            self.offset,
66            self.offset,
67            self.size,
68            0,
69            0,
70            4,
71            0,
72        )
73        .bytecode()
74    }
75}
76
77impl Section for CodeSection {
78    fn name(&self) -> &str {
79        &self.name
80    }
81
82    fn bytecode(&self) -> Vec<u8> {
83        let mut bytecode = Vec::new();
84        for node in &self.nodes {
85            if let Some(node_bytes) = node.bytecode() {
86                bytecode.extend(node_bytes);
87            }
88        }
89        bytecode
90    }
91
92    fn size(&self) -> u64 {
93        self.size
94    }
95}
96
97// Data Section implementation
98#[derive(Debug)]
99pub struct DataSection {
100    name: String,
101    nodes: Vec<ASTNode>,
102    size: u64,
103    offset: u64,
104}
105
106impl DataSection {
107    pub fn new(nodes: Vec<ASTNode>, size: u64) -> Self {
108        Self {
109            name: String::from(".rodata"),
110            nodes,
111            size,
112            offset: 0,
113        }
114    }
115
116    pub fn get_nodes(&self) -> &Vec<ASTNode> {
117        &self.nodes
118    }
119
120    pub fn get_size(&self) -> u64 {
121        self.size
122    }
123
124    pub fn set_offset(&mut self, offset: u64) {
125        self.offset = offset;
126    }
127
128    pub fn rodata(&self) -> Vec<(String, usize, String)> {
129        let mut ro_data_labels = Vec::new();
130        for node in &self.nodes {
131            if let ASTNode::ROData {
132                rodata: ROData { name, args, .. },
133                offset,
134            } = node
135                && let Some(Token::StringLiteral(str_literal, _)) = args.get(1)
136            {
137                ro_data_labels.push((name.clone(), *offset as usize, str_literal.clone()));
138            }
139        }
140        ro_data_labels
141    }
142
143    pub fn section_header_bytecode(&self) -> Vec<u8> {
144        let flags = SectionHeader::SHF_ALLOC; // Read-only data
145        SectionHeader::new(
146            7,
147            SectionHeader::SHT_PROGBITS,
148            flags,
149            self.offset,
150            self.offset,
151            self.size,
152            0,
153            0,
154            1,
155            0,
156        )
157        .bytecode()
158    }
159}
160
161impl Section for DataSection {
162    fn name(&self) -> &str {
163        &self.name
164    }
165
166    fn size(&self) -> u64 {
167        // Return 8-byte aligned size
168        (self.size + 7) & !7
169    }
170
171    fn bytecode(&self) -> Vec<u8> {
172        let mut bytecode = Vec::new();
173        for node in &self.nodes {
174            if let Some(node_bytes) = node.bytecode() {
175                bytecode.extend(node_bytes);
176            }
177        }
178        // Add padding to make size multiple of 8
179        while bytecode.len() % 8 != 0 {
180            bytecode.push(0);
181        }
182
183        bytecode
184    }
185}
186
187#[derive(Debug, Default)]
188pub struct NullSection {
189    name: String,
190    offset: u64,
191}
192
193impl NullSection {
194    pub fn new() -> Self {
195        Self::default()
196    }
197
198    pub fn section_header_bytecode(&self) -> Vec<u8> {
199        SectionHeader::new(0, SectionHeader::SHT_NULL, 0, 0, 0, 0, 0, 0, 0, 0).bytecode()
200    }
201}
202
203impl Section for NullSection {
204    // We can use all default implementations from the Section trait
205}
206
207#[derive(Debug)]
208pub struct ShStrTabSection {
209    name: String,
210    name_offset: u32,
211    section_names: Vec<String>,
212    offset: u64,
213}
214
215impl ShStrTabSection {
216    pub fn new(name_offset: u32, section_names: Vec<String>) -> Self {
217        Self {
218            name: String::from(".s"),
219            name_offset,
220            section_names: {
221                let mut names = section_names;
222                names.push(".s".to_string());
223                names
224            },
225            offset: 0,
226        }
227    }
228
229    pub fn set_offset(&mut self, offset: u64) {
230        self.offset = offset;
231    }
232
233    pub fn section_header_bytecode(&self) -> Vec<u8> {
234        SectionHeader::new(
235            self.name_offset,
236            SectionHeader::SHT_STRTAB,
237            0,
238            0,
239            self.offset,
240            self.size(),
241            0,
242            0,
243            1,
244            0,
245        )
246        .bytecode()
247    }
248}
249
250impl Section for ShStrTabSection {
251    fn name(&self) -> &str {
252        &self.name
253    }
254
255    fn bytecode(&self) -> Vec<u8> {
256        let mut bytes = Vec::new();
257        // First byte is null
258        bytes.push(0);
259
260        // Add each non-empty section name with null terminator
261        for name in &self.section_names {
262            if !name.is_empty() {
263                bytes.extend(name.as_bytes());
264                bytes.push(0); // null terminator
265            }
266        }
267
268        // Add padding to make size multiple of 8
269        while bytes.len() % 8 != 0 {
270            bytes.push(0);
271        }
272
273        bytes
274    }
275
276    fn size(&self) -> u64 {
277        // Calculate section header offset
278        let mut section_name_size = 0;
279
280        for name in &self.section_names {
281            if !name.is_empty() {
282                section_name_size += 1 + name.len();
283            }
284        }
285
286        section_name_size += 1; // null section
287
288        section_name_size as u64 // Return the calculated size
289    }
290}
291
292#[derive(Debug)]
293pub struct DynamicSection {
294    name: String,
295    name_offset: u32,
296    offset: u64,
297    link: u32,
298    rel_offset: u64,
299    rel_size: u64,
300    rel_count: u64,
301    dynsym_offset: u64,
302    dynstr_offset: u64,
303    dynstr_size: u64,
304}
305
306impl DynamicSection {
307    pub fn new(name_offset: u32) -> Self {
308        Self {
309            name: String::from(".dynamic"),
310            name_offset,
311            offset: 0,
312            link: 0,
313            rel_offset: 0,
314            rel_size: 0,
315            rel_count: 0,
316            dynsym_offset: 0,
317            dynstr_offset: 0,
318            dynstr_size: 0,
319        }
320    }
321
322    pub fn set_offset(&mut self, offset: u64) {
323        self.offset = offset;
324    }
325
326    pub fn set_link(&mut self, link: u32) {
327        self.link = link;
328    }
329
330    pub fn set_rel_offset(&mut self, offset: u64) {
331        self.rel_offset = offset;
332    }
333
334    pub fn set_rel_size(&mut self, size: u64) {
335        self.rel_size = size;
336    }
337
338    pub fn set_rel_count(&mut self, count: u64) {
339        self.rel_count = count;
340    }
341
342    pub fn set_dynsym_offset(&mut self, offset: u64) {
343        self.dynsym_offset = offset;
344    }
345
346    pub fn set_dynstr_offset(&mut self, offset: u64) {
347        self.dynstr_offset = offset;
348    }
349
350    pub fn set_dynstr_size(&mut self, size: u64) {
351        self.dynstr_size = size;
352    }
353
354    pub fn section_header_bytecode(&self) -> Vec<u8> {
355        SectionHeader::new(
356            self.name_offset,
357            SectionHeader::SHT_DYNAMIC,
358            SectionHeader::SHF_ALLOC | SectionHeader::SHF_WRITE,
359            self.offset,
360            self.offset,
361            self.size(),
362            self.link,
363            0,
364            8,
365            16,
366        )
367        .bytecode()
368    }
369}
370
371impl Section for DynamicSection {
372    fn name(&self) -> &str {
373        &self.name
374    }
375
376    fn bytecode(&self) -> Vec<u8> {
377        let mut bytes = Vec::new();
378
379        // DT_FLAGS (DF_TEXTREL)
380        bytes.extend_from_slice(&0x1e_u64.to_le_bytes());
381        bytes.extend_from_slice(&0x04_u64.to_le_bytes());
382
383        // DT_REL
384        bytes.extend_from_slice(&0x11_u64.to_le_bytes());
385        bytes.extend_from_slice(&self.rel_offset.to_le_bytes());
386
387        // DT_RELSZ
388        bytes.extend_from_slice(&0x12_u64.to_le_bytes());
389        bytes.extend_from_slice(&self.rel_size.to_le_bytes());
390
391        // DT_RELENT
392        bytes.extend_from_slice(&0x13_u64.to_le_bytes());
393        bytes.extend_from_slice(&0x10_u64.to_le_bytes()); // Constant: 16 bytes per entry
394
395        // DT_RELCOUNT: number of relative relocation entries
396        if self.rel_count > 0 {
397            bytes.extend_from_slice(&0x6fff_fffa_u64.to_le_bytes());
398            bytes.extend_from_slice(&self.rel_count.to_le_bytes());
399        }
400
401        // DT_SYMTAB
402        bytes.extend_from_slice(&0x06_u64.to_le_bytes());
403        bytes.extend_from_slice(&self.dynsym_offset.to_le_bytes());
404
405        // DT_SYMENT
406        bytes.extend_from_slice(&0x0b_u64.to_le_bytes());
407        bytes.extend_from_slice(&0x18_u64.to_le_bytes()); // Constant: 24 bytes per symbol
408
409        // DT_STRTAB
410        bytes.extend_from_slice(&0x05_u64.to_le_bytes());
411        bytes.extend_from_slice(&self.dynstr_offset.to_le_bytes());
412
413        // DT_STRSZ
414        bytes.extend_from_slice(&0x0a_u64.to_le_bytes());
415        bytes.extend_from_slice(&self.dynstr_size.to_le_bytes());
416
417        // DT_TEXTREL
418        bytes.extend_from_slice(&0x16_u64.to_le_bytes());
419        bytes.extend_from_slice(&0x00_u64.to_le_bytes());
420
421        // DT_NULL
422        bytes.extend_from_slice(&0x00_u64.to_le_bytes());
423        bytes.extend_from_slice(&0x00_u64.to_le_bytes());
424
425        bytes
426    }
427
428    fn size(&self) -> u64 {
429        if self.rel_count > 0 { 11 * 16 } else { 10 * 16 }
430    }
431}
432
433#[derive(Debug)]
434pub struct DynStrSection {
435    name: String,
436    name_offset: u32,
437    symbol_names: Vec<String>,
438    offset: u64,
439}
440
441impl DynStrSection {
442    pub fn new(name_offset: u32, symbol_names: Vec<String>) -> Self {
443        Self {
444            name: String::from(".dynstr"),
445            name_offset,
446            symbol_names,
447            offset: 0,
448        }
449    }
450
451    pub fn set_offset(&mut self, offset: u64) {
452        self.offset = offset;
453    }
454
455    pub fn section_header_bytecode(&self) -> Vec<u8> {
456        SectionHeader::new(
457            self.name_offset,
458            SectionHeader::SHT_STRTAB,
459            SectionHeader::SHF_ALLOC, // Allocatable section
460            self.offset,
461            self.offset,
462            self.size(),
463            0,
464            0,
465            1,
466            0,
467        )
468        .bytecode()
469    }
470}
471
472impl Section for DynStrSection {
473    fn name(&self) -> &str {
474        &self.name
475    }
476
477    fn bytecode(&self) -> Vec<u8> {
478        let mut bytes = Vec::new();
479        // First byte is null
480        bytes.push(0);
481
482        // Add each symbol name with null terminator
483        for name in &self.symbol_names {
484            bytes.extend(name.as_bytes());
485            bytes.push(0); // null terminator
486        }
487        // add padding to make size multiple of 8
488        while bytes.len() % 8 != 0 {
489            bytes.push(0);
490        }
491        bytes
492    }
493
494    fn size(&self) -> u64 {
495        // Calculate total size: initial null byte + sum of (name lengths + null terminators)
496        let mut size = 1 + self
497            .symbol_names
498            .iter()
499            .map(|name| name.len() + 1)
500            .sum::<usize>();
501        // add padding to make size multiple of 8
502        while size % 8 != 0 {
503            size += 1;
504        }
505        size as u64
506    }
507}
508
509#[derive(Debug)]
510pub struct DynSymSection {
511    name: String,
512    name_offset: u32,
513    offset: u64,
514    link: u32,
515    symbols: Vec<DynamicSymbol>,
516}
517
518impl DynSymSection {
519    pub fn new(name_offset: u32, symbols: Vec<DynamicSymbol>) -> Self {
520        Self {
521            name: String::from(".dynsym"),
522            name_offset,
523            offset: 0,
524            link: 0,
525            symbols,
526        }
527    }
528
529    pub fn set_offset(&mut self, offset: u64) {
530        self.offset = offset;
531    }
532
533    pub fn set_link(&mut self, link: u32) {
534        self.link = link;
535    }
536
537    pub fn section_header_bytecode(&self) -> Vec<u8> {
538        let flags = SectionHeader::SHF_ALLOC;
539        SectionHeader::new(
540            self.name_offset,
541            SectionHeader::SHT_DYNSYM,
542            flags,
543            self.offset,
544            self.offset,
545            self.size(),
546            self.link,
547            1,
548            8,
549            24,
550        )
551        .bytecode()
552    }
553}
554
555impl Section for DynSymSection {
556    fn name(&self) -> &str {
557        &self.name
558    }
559
560    fn size(&self) -> u64 {
561        // Each symbol entry is 24 bytes
562        (self.symbols.len() as u64) * 24
563    }
564
565    fn bytecode(&self) -> Vec<u8> {
566        let mut bytes = Vec::new();
567        for symbol in &self.symbols {
568            bytes.extend(symbol.bytecode());
569        }
570        bytes
571    }
572}
573
574#[derive(Debug)]
575pub struct RelDynSection {
576    name: String,
577    name_offset: u32,
578    offset: u64,
579    link: u32,
580    entries: Vec<RelDyn>,
581}
582
583impl RelDynSection {
584    pub fn new(name_offset: u32, entries: Vec<RelDyn>) -> Self {
585        Self {
586            name: String::from(".rel.dyn"),
587            name_offset,
588            offset: 0,
589            link: 0,
590            entries,
591        }
592    }
593
594    pub fn set_offset(&mut self, offset: u64) {
595        self.offset = offset;
596    }
597
598    pub fn set_link(&mut self, link: u32) {
599        self.link = link;
600    }
601
602    pub fn size(&self) -> u64 {
603        (self.entries.len() * 16) as u64 // Each RelDyn entry is 16 bytes
604    }
605
606    pub fn section_header_bytecode(&self) -> Vec<u8> {
607        let flags = SectionHeader::SHF_ALLOC;
608        SectionHeader::new(
609            self.name_offset,
610            SectionHeader::SHT_REL,
611            flags,
612            self.offset,
613            self.offset,
614            self.size(),
615            self.link,
616            0,
617            8,
618            16,
619        )
620        .bytecode()
621    }
622}
623
624impl Section for RelDynSection {
625    fn name(&self) -> &str {
626        &self.name
627    }
628
629    fn size(&self) -> u64 {
630        self.size()
631    }
632
633    fn bytecode(&self) -> Vec<u8> {
634        let mut bytes = Vec::new();
635        for entry in &self.entries {
636            bytes.extend(entry.bytecode());
637        }
638        bytes
639    }
640}
641#[derive(Debug, Clone)]
642pub struct DebugSection {
643    name: String,
644    name_offset: u32,
645    data: Vec<u8>,
646    offset: u64,
647}
648
649impl DebugSection {
650    pub fn new(name: &str, name_offset: u32, data: Vec<u8>) -> Self {
651        Self {
652            name: name.to_string(),
653            name_offset,
654            data,
655            offset: 0,
656        }
657    }
658
659    pub fn name(&self) -> &str {
660        &self.name
661    }
662
663    pub fn size(&self) -> u64 {
664        let raw = self.data.len();
665        let padding = (8 - (raw % 8)) % 8;
666        (raw + padding) as u64
667    }
668
669    pub fn bytecode(&self) -> Vec<u8> {
670        let mut bytes = self.data.clone();
671        while !bytes.len().is_multiple_of(8) {
672            bytes.push(0);
673        }
674        bytes
675    }
676
677    pub fn set_offset(&mut self, offset: u64) {
678        self.offset = offset;
679    }
680
681    pub fn offset(&self) -> u64 {
682        self.offset
683    }
684
685    pub fn set_name_offset(&mut self, name_offset: u32) {
686        self.name_offset = name_offset;
687    }
688
689    pub fn name_offset(&self) -> u32 {
690        self.name_offset
691    }
692
693    pub fn section_header_bytecode(&self) -> Vec<u8> {
694        SectionHeader::new(
695            self.name_offset,
696            SectionHeader::SHT_PROGBITS,
697            0,
698            0,
699            self.offset,
700            self.data.len() as u64, // size without padding
701            0,
702            0,
703            1,
704            0,
705        )
706        .bytecode()
707    }
708}
709
710#[derive(Debug)]
711pub enum SectionType {
712    Code(CodeSection),
713    Data(DataSection),
714    ShStrTab(ShStrTabSection),
715    Dynamic(DynamicSection),
716    DynStr(DynStrSection),
717    DynSym(DynSymSection),
718    Default(NullSection),
719    RelDyn(RelDynSection),
720    DebugAbbrev(DebugSection),
721    DebugInfo(DebugSection),
722    DebugLine(DebugSection),
723    DebugLineStr(DebugSection),
724    DebugStr(DebugSection),
725    DebugFrame(DebugSection),
726    DebugLoc(DebugSection),
727    DebugRanges(DebugSection),
728}
729
730impl SectionType {
731    pub fn name(&self) -> &str {
732        match self {
733            SectionType::Code(cs) => &cs.name,
734            SectionType::Data(ds) => &ds.name,
735            SectionType::ShStrTab(ss) => &ss.name,
736            SectionType::Dynamic(ds) => &ds.name,
737            SectionType::DynStr(ds) => &ds.name,
738            SectionType::DynSym(ds) => &ds.name,
739            SectionType::Default(ds) => &ds.name,
740            SectionType::RelDyn(ds) => &ds.name,
741            SectionType::DebugAbbrev(ds) => ds.name(),
742            SectionType::DebugInfo(ds) => ds.name(),
743            SectionType::DebugLine(ds) => ds.name(),
744            SectionType::DebugLineStr(ds) => ds.name(),
745            SectionType::DebugStr(ds) => ds.name(),
746            SectionType::DebugFrame(ds) => ds.name(),
747            SectionType::DebugLoc(ds) => ds.name(),
748            SectionType::DebugRanges(ds) => ds.name(),
749        }
750    }
751
752    pub fn bytecode(&self) -> Vec<u8> {
753        match self {
754            SectionType::Code(cs) => cs.bytecode(),
755            SectionType::Data(ds) => ds.bytecode(),
756            SectionType::ShStrTab(ss) => ss.bytecode(),
757            SectionType::Dynamic(ds) => ds.bytecode(),
758            SectionType::DynStr(ds) => ds.bytecode(),
759            SectionType::DynSym(ds) => ds.bytecode(),
760            SectionType::Default(ds) => ds.bytecode(),
761            SectionType::RelDyn(ds) => ds.bytecode(),
762            SectionType::DebugAbbrev(ds) => ds.bytecode(),
763            SectionType::DebugInfo(ds) => ds.bytecode(),
764            SectionType::DebugLine(ds) => ds.bytecode(),
765            SectionType::DebugLineStr(ds) => ds.bytecode(),
766            SectionType::DebugStr(ds) => ds.bytecode(),
767            SectionType::DebugFrame(ds) => ds.bytecode(),
768            SectionType::DebugLoc(ds) => ds.bytecode(),
769            SectionType::DebugRanges(ds) => ds.bytecode(),
770        }
771    }
772
773    pub fn size(&self) -> u64 {
774        match self {
775            SectionType::Code(cs) => cs.size(),
776            SectionType::Data(ds) => ds.size(),
777            SectionType::ShStrTab(ss) => ss.size(),
778            SectionType::Dynamic(ds) => ds.size(),
779            SectionType::DynStr(ds) => ds.size(),
780            SectionType::DynSym(ds) => ds.size(),
781            SectionType::Default(ds) => ds.size(),
782            SectionType::RelDyn(ds) => ds.size(),
783            SectionType::DebugAbbrev(ds) => ds.size(),
784            SectionType::DebugInfo(ds) => ds.size(),
785            SectionType::DebugLine(ds) => ds.size(),
786            SectionType::DebugLineStr(ds) => ds.size(),
787            SectionType::DebugStr(ds) => ds.size(),
788            SectionType::DebugFrame(ds) => ds.size(),
789            SectionType::DebugLoc(ds) => ds.size(),
790            SectionType::DebugRanges(ds) => ds.size(),
791        }
792    }
793
794    pub fn section_header_bytecode(&self) -> Vec<u8> {
795        match self {
796            SectionType::Code(cs) => cs.section_header_bytecode(),
797            SectionType::Data(ds) => ds.section_header_bytecode(),
798            SectionType::ShStrTab(ss) => ss.section_header_bytecode(),
799            SectionType::Dynamic(ds) => ds.section_header_bytecode(),
800            SectionType::DynStr(ds) => ds.section_header_bytecode(),
801            SectionType::DynSym(ds) => ds.section_header_bytecode(),
802            SectionType::Default(ds) => ds.section_header_bytecode(),
803            SectionType::RelDyn(ds) => ds.section_header_bytecode(),
804            SectionType::DebugAbbrev(ds) => ds.section_header_bytecode(),
805            SectionType::DebugInfo(ds) => ds.section_header_bytecode(),
806            SectionType::DebugLine(ds) => ds.section_header_bytecode(),
807            SectionType::DebugLineStr(ds) => ds.section_header_bytecode(),
808            SectionType::DebugStr(ds) => ds.section_header_bytecode(),
809            SectionType::DebugFrame(ds) => ds.section_header_bytecode(),
810            SectionType::DebugLoc(ds) => ds.section_header_bytecode(),
811            SectionType::DebugRanges(ds) => ds.section_header_bytecode(),
812        }
813    }
814
815    pub fn set_offset(&mut self, offset: u64) {
816        match self {
817            SectionType::Code(cs) => cs.set_offset(offset),
818            SectionType::Data(ds) => ds.set_offset(offset),
819            SectionType::ShStrTab(ss) => ss.set_offset(offset),
820            SectionType::Dynamic(ds) => ds.set_offset(offset),
821            SectionType::DynStr(ds) => ds.set_offset(offset),
822            SectionType::DynSym(ds) => ds.set_offset(offset),
823            SectionType::RelDyn(ds) => ds.set_offset(offset),
824            SectionType::Default(_) => (), // NullSection doesn't need offset
825            SectionType::DebugAbbrev(ds) => ds.set_offset(offset),
826            SectionType::DebugInfo(ds) => ds.set_offset(offset),
827            SectionType::DebugLine(ds) => ds.set_offset(offset),
828            SectionType::DebugLineStr(ds) => ds.set_offset(offset),
829            SectionType::DebugStr(ds) => ds.set_offset(offset),
830            SectionType::DebugFrame(ds) => ds.set_offset(offset),
831            SectionType::DebugLoc(ds) => ds.set_offset(offset),
832            SectionType::DebugRanges(ds) => ds.set_offset(offset),
833        }
834    }
835
836    pub fn offset(&self) -> u64 {
837        match self {
838            SectionType::Code(cs) => cs.offset,
839            SectionType::Data(ds) => ds.offset,
840            SectionType::ShStrTab(ss) => ss.offset,
841            SectionType::Dynamic(ds) => ds.offset,
842            SectionType::DynStr(ds) => ds.offset,
843            SectionType::DynSym(ds) => ds.offset,
844            SectionType::Default(ns) => ns.offset,
845            SectionType::RelDyn(rs) => rs.offset,
846            SectionType::DebugAbbrev(ds) => ds.offset(),
847            SectionType::DebugInfo(ds) => ds.offset(),
848            SectionType::DebugLine(ds) => ds.offset(),
849            SectionType::DebugLineStr(ds) => ds.offset(),
850            SectionType::DebugStr(ds) => ds.offset(),
851            SectionType::DebugFrame(ds) => ds.offset(),
852            SectionType::DebugLoc(ds) => ds.offset(),
853            SectionType::DebugRanges(ds) => ds.offset(),
854        }
855    }
856}
857
858#[cfg(test)]
859mod tests {
860    use {
861        super::*,
862        sbpf_common::{instruction::Instruction, opcode::Opcode},
863    };
864
865    #[test]
866    fn test_code_section_new() {
867        let inst = Instruction {
868            opcode: Opcode::Exit,
869            dst: None,
870            src: None,
871            off: None,
872            imm: None,
873            span: 0..4,
874        };
875        let nodes = vec![ASTNode::Instruction {
876            instruction: inst,
877            offset: 0,
878        }];
879
880        let section = CodeSection::new(nodes, 8);
881        assert_eq!(section.name(), ".text");
882        assert_eq!(section.get_size(), 8);
883    }
884
885    #[test]
886    fn test_code_section_bytecode() {
887        let inst = Instruction {
888            opcode: Opcode::Exit,
889            dst: None,
890            src: None,
891            off: None,
892            imm: None,
893            span: 0..4,
894        };
895        let nodes = vec![ASTNode::Instruction {
896            instruction: inst,
897            offset: 0,
898        }];
899
900        let section = CodeSection::new(nodes, 8);
901        let bytes = section.bytecode();
902        assert_eq!(bytes.len(), 8);
903    }
904
905    #[test]
906    fn test_data_section_new() {
907        let rodata = ROData {
908            name: "msg".to_string(),
909            args: vec![
910                Token::Directive("ascii".to_string(), 0..5),
911                Token::StringLiteral("Hi".to_string(), 6..10),
912            ],
913            span: 0..10,
914        };
915        let nodes = vec![ASTNode::ROData { rodata, offset: 0 }];
916
917        let section = DataSection::new(nodes, 2);
918        assert_eq!(section.name(), ".rodata");
919        assert_eq!(section.get_size(), 2);
920    }
921
922    #[test]
923    fn test_data_section_rodata() {
924        let rodata = ROData {
925            name: "my_str".to_string(),
926            args: vec![
927                Token::Directive("ascii".to_string(), 0..5),
928                Token::StringLiteral("test".to_string(), 6..12),
929            ],
930            span: 0..12,
931        };
932        let nodes = vec![ASTNode::ROData { rodata, offset: 0 }];
933
934        let section = DataSection::new(nodes, 4);
935        let rodata = section.rodata();
936        assert_eq!(rodata.len(), 1);
937        assert_eq!(rodata[0].0, "my_str");
938        assert_eq!(rodata[0].2, "test");
939    }
940
941    #[test]
942    fn test_null_section() {
943        let section = NullSection::new();
944        assert_eq!(section.name(), ".unknown");
945        assert_eq!(section.bytecode().len(), 0);
946        assert_eq!(section.size(), 0);
947    }
948
949    #[test]
950    fn test_shstrtab_section() {
951        let names = vec![".text".to_string(), ".data".to_string()];
952        let mut section = ShStrTabSection::new(10, names);
953        section.set_offset(100);
954
955        assert_eq!(section.name(), ".s");
956        assert!(section.size() > 0);
957
958        let bytes = section.bytecode();
959        assert!(!bytes.is_empty());
960        assert_eq!(bytes[0], 0); // First byte is null
961    }
962
963    #[test]
964    fn test_dynamic_section_setters() {
965        let mut section = DynamicSection::new(5);
966        section.set_offset(100);
967        section.set_link(3);
968        section.set_rel_offset(200);
969        section.set_rel_size(48);
970        section.set_rel_count(2);
971        section.set_dynsym_offset(300);
972        section.set_dynstr_offset(400);
973        section.set_dynstr_size(50);
974
975        assert_eq!(section.name(), ".dynamic");
976        assert!(section.size() > 0);
977    }
978
979    #[test]
980    fn test_dynamic_section_bytecode_with_rel_count() {
981        let mut section = DynamicSection::new(0);
982        section.set_rel_count(3);
983        assert_eq!(section.size(), 11 * 16); // With rel_count
984    }
985
986    #[test]
987    fn test_dynamic_section_bytecode_without_rel_count() {
988        let section = DynamicSection::new(0);
989        assert_eq!(section.size(), 10 * 16); // Without rel_count
990    }
991
992    #[test]
993    fn test_dynstr_section() {
994        let names = vec!["entrypoint".to_string(), "function".to_string()];
995        let mut section = DynStrSection::new(8, names);
996        section.set_offset(200);
997
998        assert_eq!(section.name(), ".dynstr");
999
1000        let bytes = section.bytecode();
1001        assert_eq!(bytes[0], 0);
1002        assert_eq!(bytes.len() % 8, 0);
1003    }
1004
1005    #[test]
1006    fn test_dynsym_section() {
1007        let symbols = vec![
1008            DynamicSymbol::new(0, 0, 0, 0, 0, 0),
1009            DynamicSymbol::new(1, 0x12, 0, 1, 0x120, 48),
1010        ];
1011        let mut section = DynSymSection::new(15, symbols);
1012        section.set_offset(300);
1013        section.set_link(4);
1014
1015        assert_eq!(section.name(), ".dynsym");
1016        assert_eq!(section.size(), 2 * 24); // 2 symbols * 24 bytes each
1017    }
1018
1019    #[test]
1020    fn test_rel_dyn_section() {
1021        let entries = vec![RelDyn::new(0x120, 0x08, 0), RelDyn::new(0x200, 0x0a, 1)];
1022        let mut section = RelDynSection::new(18, entries);
1023        section.set_offset(400);
1024        section.set_link(3);
1025
1026        assert_eq!(section.name(), ".rel.dyn");
1027        assert_eq!(section.size(), 2 * 16); // 2 entries * 16 bytes each
1028    }
1029
1030    #[test]
1031    fn test_section_type_enum_code() {
1032        let inst = Instruction {
1033            opcode: Opcode::Exit,
1034            dst: None,
1035            src: None,
1036            off: None,
1037            imm: None,
1038            span: 0..4,
1039        };
1040        let code_section = CodeSection::new(
1041            vec![ASTNode::Instruction {
1042                instruction: inst,
1043                offset: 0,
1044            }],
1045            8,
1046        );
1047
1048        let section_type = SectionType::Code(code_section);
1049        assert_eq!(section_type.name(), ".text");
1050        assert_eq!(section_type.size(), 8);
1051    }
1052
1053    #[test]
1054    fn test_section_type_set_offset() {
1055        let mut section = SectionType::Default(NullSection::new());
1056        section.set_offset(100);
1057
1058        let mut dyn_section = SectionType::Dynamic(DynamicSection::new(0));
1059        dyn_section.set_offset(200);
1060        assert_eq!(dyn_section.offset(), 200);
1061    }
1062
1063    #[test]
1064    fn test_debug_section_types() {
1065        let sections = [
1066            SectionType::DebugAbbrev(DebugSection::new(".debug_abbrev", 0, vec![1, 2, 3])),
1067            SectionType::DebugInfo(DebugSection::new(".debug_info", 0, vec![4, 5, 6])),
1068            SectionType::DebugLine(DebugSection::new(".debug_line", 0, vec![7, 8, 9])),
1069            SectionType::DebugLineStr(DebugSection::new(".debug_line_str", 0, vec![10, 11, 12])),
1070        ];
1071
1072        let expected_names = [
1073            ".debug_abbrev",
1074            ".debug_info",
1075            ".debug_line",
1076            ".debug_line_str",
1077        ];
1078        for (i, section) in sections.iter().enumerate() {
1079            assert_eq!(section.name(), expected_names[i]);
1080            assert_eq!(section.size(), 8);
1081            assert_eq!(section.bytecode().len(), 8);
1082            assert!(!section.section_header_bytecode().is_empty());
1083        }
1084    }
1085}