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