1use crate::{
2 astnode::{ASTNode, ROData},
3 dynsym::{DynamicSymbol, RelDyn},
4 header::SectionHeader,
5 parser::Token,
6};
7
8pub trait Section {
10 fn name(&self) -> &str {
11 ".unknown" }
13
14 fn bytecode(&self) -> Vec<u8> {
15 Vec::new() }
17
18 fn size(&self) -> u64 {
20 self.bytecode().len() as u64
21 }
22
23 }
27
28#[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#[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; 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 (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 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 }
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 bytes.push(0);
259
260 for name in &self.section_names {
262 if !name.is_empty() {
263 bytes.extend(name.as_bytes());
264 bytes.push(0); }
266 }
267
268 while bytes.len() % 8 != 0 {
270 bytes.push(0);
271 }
272
273 bytes
274 }
275
276 fn size(&self) -> u64 {
277 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; section_name_size as u64 }
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 bytes.extend_from_slice(&0x1e_u64.to_le_bytes());
381 bytes.extend_from_slice(&0x04_u64.to_le_bytes());
382
383 bytes.extend_from_slice(&0x11_u64.to_le_bytes());
385 bytes.extend_from_slice(&self.rel_offset.to_le_bytes());
386
387 bytes.extend_from_slice(&0x12_u64.to_le_bytes());
389 bytes.extend_from_slice(&self.rel_size.to_le_bytes());
390
391 bytes.extend_from_slice(&0x13_u64.to_le_bytes());
393 bytes.extend_from_slice(&0x10_u64.to_le_bytes()); 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 bytes.extend_from_slice(&0x06_u64.to_le_bytes());
403 bytes.extend_from_slice(&self.dynsym_offset.to_le_bytes());
404
405 bytes.extend_from_slice(&0x0b_u64.to_le_bytes());
407 bytes.extend_from_slice(&0x18_u64.to_le_bytes()); bytes.extend_from_slice(&0x05_u64.to_le_bytes());
411 bytes.extend_from_slice(&self.dynstr_offset.to_le_bytes());
412
413 bytes.extend_from_slice(&0x0a_u64.to_le_bytes());
415 bytes.extend_from_slice(&self.dynstr_size.to_le_bytes());
416
417 bytes.extend_from_slice(&0x16_u64.to_le_bytes());
419 bytes.extend_from_slice(&0x00_u64.to_le_bytes());
420
421 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, 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 bytes.push(0);
481
482 for name in &self.symbol_names {
484 bytes.extend(name.as_bytes());
485 bytes.push(0); }
487 while bytes.len() % 8 != 0 {
489 bytes.push(0);
490 }
491 bytes
492 }
493
494 fn size(&self) -> u64 {
495 let mut size = 1 + self
497 .symbol_names
498 .iter()
499 .map(|name| name.len() + 1)
500 .sum::<usize>();
501 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 (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 }
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, 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(_) => (), 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); }
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); }
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); }
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); }
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); }
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}