1use std::slice::Iter;
96
97use crate::{BufferIterator, FromBytes, ToBytes, WritableBuffer};
98
99use self::sections::{DataSection, FuncSection, SectionHeader, StringTable, SymbolTable};
100use self::sections::{ReldSection, SectionKind};
101
102pub mod errors;
103pub mod instructions;
104pub mod sections;
105pub mod symbols;
106
107use crate::ko::errors::{HeaderParseError, KOParseError, ValidationError};
108use crate::ko::sections::StringIdx;
109pub use instructions::Instr;
110
111const FILE_VERSION: u8 = 4;
112const MAGIC_NUMBER: u32 = 0x666f016b;
114
115#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
122pub struct SectionIdx(u16);
123
124impl From<u8> for SectionIdx {
125 fn from(i: u8) -> Self {
126 Self(i as u16)
127 }
128}
129
130impl From<u16> for SectionIdx {
131 fn from(i: u16) -> Self {
132 Self(i)
133 }
134}
135
136impl From<SectionIdx> for u16 {
137 fn from(idx: SectionIdx) -> Self {
138 idx.0
139 }
140}
141
142impl From<SectionIdx> for usize {
143 fn from(idx: SectionIdx) -> Self {
144 idx.0 as usize
145 }
146}
147
148impl SectionIdx {
149 pub const NULL: SectionIdx = SectionIdx(0u16);
151}
152
153#[derive(Debug)]
157pub struct KOFile {
158 header: KOHeader,
159 shstrtab: StringTable,
160 section_headers: Vec<SectionHeader>,
161 str_tabs: Vec<StringTable>,
162 sym_tabs: Vec<SymbolTable>,
163 data_sections: Vec<DataSection>,
164 func_sections: Vec<FuncSection>,
165 reld_sections: Vec<ReldSection>,
166}
167
168impl KOFile {
169 pub fn new() -> Self {
175 let shstrtab_idx = SectionIdx::from(1u16);
177
178 let mut kofile = Self {
179 header: KOHeader::new(2, shstrtab_idx),
180 shstrtab: StringTable::with_capacity(256, shstrtab_idx),
181 section_headers: Vec::with_capacity(4),
182 str_tabs: Vec::with_capacity(2),
183 sym_tabs: Vec::with_capacity(1),
184 data_sections: Vec::with_capacity(1),
185 func_sections: Vec::with_capacity(1),
186 reld_sections: Vec::with_capacity(1),
187 };
188
189 kofile.add_section_header(SectionHeader::null());
191
192 let name_idx = kofile.shstrtab.add(".shstrtab");
193
194 kofile.add_section_header(SectionHeader::new(name_idx, SectionKind::StrTab));
196
197 kofile
198 }
199
200 pub fn add_section_name(&mut self, name: impl Into<String>) -> StringIdx {
202 self.shstrtab.add(name)
203 }
204
205 pub fn get_section_name(&self, index: StringIdx) -> Option<&String> {
208 self.shstrtab.get(index)
209 }
210
211 pub fn get_section_name_by_index(&self, index: SectionIdx) -> Option<&String> {
215 let header = self.section_headers.get(usize::from(index))?;
216 self.shstrtab.get(header.name_idx)
217 }
218
219 pub fn add_section_header(&mut self, header: SectionHeader) -> SectionIdx {
225 let index = self.section_headers.len();
226
227 if index > u16::MAX as usize {
228 panic!(
229 "Attempted to insert {} section headers. Section indices have a maximum of {}",
230 u16::MAX as usize + 1,
231 u16::MAX
232 );
233 }
234
235 self.section_headers.push(header);
236 SectionIdx::from(index as u16)
237 }
238
239 pub fn get_section_header(&self, index: SectionIdx) -> Option<&SectionHeader> {
242 self.section_headers.get(usize::from(index))
243 }
244
245 pub fn get_header_name(&self, header: &SectionHeader) -> Option<&String> {
248 self.shstrtab.get(header.name_idx)
249 }
250
251 pub fn add_str_tab(&mut self, str_tab: StringTable) {
253 self.str_tabs.push(str_tab);
254 }
255
256 pub fn add_sym_tab(&mut self, sym_tab: SymbolTable) {
258 self.sym_tabs.push(sym_tab);
259 }
260
261 pub fn add_data_section(&mut self, data_section: DataSection) {
263 self.data_sections.push(data_section);
264 }
265
266 pub fn add_func_section(&mut self, func_section: FuncSection) {
268 self.func_sections.push(func_section);
269 }
270
271 pub fn add_reld_section(&mut self, reld_section: ReldSection) {
273 self.reld_sections.push(reld_section);
274 }
275
276 pub fn str_tabs(&self) -> Iter<StringTable> {
278 self.str_tabs.iter()
279 }
280
281 pub fn sym_tabs(&self) -> Iter<SymbolTable> {
283 self.sym_tabs.iter()
284 }
285
286 pub fn data_sections(&self) -> Iter<DataSection> {
288 self.data_sections.iter()
289 }
290
291 pub fn func_sections(&self) -> Iter<FuncSection> {
293 self.func_sections.iter()
294 }
295
296 pub fn reld_sections(&self) -> Iter<ReldSection> {
298 self.reld_sections.iter()
299 }
300
301 pub fn new_section_header(&mut self, name: impl Into<String>, kind: SectionKind) -> SectionIdx {
304 let name_idx = self.add_section_name(name);
305 let header = SectionHeader::new(name_idx, kind);
306 self.add_section_header(header)
307 }
308
309 pub fn get_section_index_by_name(&self, name: impl AsRef<str>) -> Option<SectionIdx> {
312 for (index, header) in self.section_headers.iter().enumerate() {
313 let name_idx = header.name_idx;
314 let sh_name = match self.shstrtab.get(name_idx) {
315 Some(name) => name,
316 None => {
317 continue;
318 }
319 };
320
321 if name.as_ref() == sh_name {
322 return Some(SectionIdx::from(index as u16));
323 }
324 }
325
326 None
327 }
328
329 pub fn header(&self) -> KOHeader {
331 self.header
332 }
333
334 pub fn section_headers(&self) -> Iter<SectionHeader> {
337 self.section_headers.iter()
338 }
339
340 pub fn section_header_count(&self) -> usize {
343 self.section_headers.len()
344 }
345
346 pub fn shstrtab_index(&self) -> SectionIdx {
348 self.shstrtab.section_index()
349 }
350
351 fn update_section_header(
355 &mut self,
356 section_kind: SectionKind,
357 section_index: SectionIdx,
358 section_size: u32,
359 ) -> Result<(), ValidationError> {
360 match self
361 .section_headers
362 .get_mut(u16::from(section_index) as usize)
363 {
364 Some(header) => {
365 if header.section_kind != section_kind {
366 Err(ValidationError::SectionKindMismatchError(
367 section_kind,
368 u16::from(section_index),
369 header.section_kind,
370 ))
371 } else {
372 header.size = section_size;
373 Ok(())
374 }
375 }
376 None => Err(ValidationError::InvalidSectionIndexError(
377 section_kind,
378 u16::from(section_index),
379 )),
380 }
381 }
382
383 fn update_section_headers(&mut self) -> Result<(), ValidationError> {
387 let mut header_set = vec![self.shstrtab.section_index()];
390
391 self.section_headers
393 .get_mut(usize::from(self.shstrtab.section_index()))
394 .unwrap()
395 .size = self.shstrtab.size();
396
397 for i in 0..self.str_tabs.len() {
398 let section = self.str_tabs.get(i).unwrap();
399 let idx = section.section_index();
400 let size = section.size();
401 header_set.push(idx);
402
403 self.update_section_header(SectionKind::StrTab, idx, size)?;
404 }
405
406 for i in 0..self.sym_tabs.len() {
407 let section = self.sym_tabs.get(i).unwrap();
408 let idx = section.section_index();
409 let size = section.size();
410 header_set.push(idx);
411
412 self.update_section_header(SectionKind::SymTab, idx, size)?;
413 }
414
415 for i in 0..self.data_sections.len() {
416 let section = self.data_sections.get(i).unwrap();
417 let idx = section.section_index();
418 let size = section.size();
419
420 header_set.push(idx);
421
422 self.update_section_header(SectionKind::Data, idx, size)?;
423 }
424
425 for i in 0..self.func_sections.len() {
426 let section = self.func_sections.get(i).unwrap();
427 let idx = section.section_index();
428 let size = section.size();
429 header_set.push(idx);
430
431 self.update_section_header(SectionKind::Func, idx, size)?;
432 }
433
434 for i in 0..self.reld_sections.len() {
435 let section = self.reld_sections.get(i).unwrap();
436 let idx = section.section_index();
437 let size = section.size();
438 header_set.push(idx);
439
440 self.update_section_header(SectionKind::Reld, idx, size)?;
441 }
442
443 for (i, header) in self
445 .section_headers
446 .iter()
447 .enumerate()
448 .skip(1)
449 .map(|(i, h)| (SectionIdx::from(i as u16), h))
450 {
451 let name = self
452 .shstrtab
453 .get(header.name_idx)
454 .ok_or_else(|| {
455 ValidationError::InvalidSectionHeaderNameIndexError(
456 u16::from(i),
457 header.section_kind,
458 usize::from(header.name_idx),
459 )
460 })?
461 .clone();
462
463 if !header_set.contains(&i) {
464 return Err(ValidationError::InvalidSectionHeaderError(
465 u16::from(i),
466 header.section_kind,
467 name,
468 ));
469 }
470 }
471
472 Ok(())
473 }
474
475 pub fn validate(mut self) -> Result<WritableKOFile, (Self, ValidationError)> {
484 self.header = KOHeader::new(
485 self.section_headers.len() as u16,
486 self.shstrtab.section_index(),
487 );
488
489 if let Err(e) = self.update_section_headers() {
490 Err((self, e))
491 } else {
492 Ok(WritableKOFile(self))
493 }
494 }
495
496 pub fn parse(source: &mut BufferIterator) -> Result<Self, KOParseError> {
498 let header = KOHeader::parse(source).map_err(KOParseError::HeaderError)?;
499 let mut section_headers = Vec::with_capacity(header.num_headers as usize);
500 let mut str_tabs;
501 let mut sym_tabs;
502 let mut data_sections;
503 let mut func_sections;
504 let mut reld_sections;
505 let mut num_str_tabs = 0;
506 let mut num_sym_tabs = 0;
507 let mut num_data_sections = 0;
508 let mut num_func_sections = 0;
509 let mut num_reld_sections = 0;
510
511 let null_header =
512 SectionHeader::parse(source).map_err(KOParseError::SectionHeaderParseError)?;
513
514 if null_header.section_kind != SectionKind::Null {
516 return Err(KOParseError::MissingNullSectionHeader(
517 null_header.section_kind,
518 ));
519 }
520 section_headers.push(null_header);
521
522 for i in 1..header.num_headers {
523 let header =
524 SectionHeader::parse(source).map_err(KOParseError::SectionHeaderParseError)?;
525
526 match header.section_kind {
527 SectionKind::StrTab => {
528 num_str_tabs += 1;
529 }
530 SectionKind::SymTab => {
531 num_sym_tabs += 1;
532 }
533 SectionKind::Data => {
534 num_data_sections += 1;
535 }
536 SectionKind::Func => {
537 num_func_sections += 1;
538 }
539 SectionKind::Reld => {
540 num_reld_sections += 1;
541 }
542 SectionKind::Debug => {
543 return Err(KOParseError::DebugSectionUnsupportedError(i));
544 }
545 SectionKind::Null => {
546 return Err(KOParseError::StrayNullSectionHeader(i));
547 }
548 }
549
550 section_headers.push(header);
551 }
552
553 if header.shstrtab_idx == SectionIdx::from(0u16) {
555 return Err(KOParseError::NullShStrTabIndexError);
556 }
557
558 str_tabs = Vec::with_capacity(num_str_tabs);
560 sym_tabs = Vec::with_capacity(num_sym_tabs);
561 data_sections = Vec::with_capacity(num_data_sections);
562 func_sections = Vec::with_capacity(num_func_sections);
563 reld_sections = Vec::with_capacity(num_reld_sections);
564
565 let shstrtab_size = section_headers
566 .get(usize::from(header.shstrtab_idx))
567 .ok_or_else(|| {
568 KOParseError::InvalidShStrTabIndexError(
569 header.shstrtab_idx.into(),
570 section_headers.len() as u16,
571 )
572 })?
573 .size;
574
575 let shstrtab = StringTable::parse(source, shstrtab_size, header.shstrtab_idx)
576 .map_err(KOParseError::StringTableParseError)?;
577
578 for section_idx in (1..section_headers.len() as u16).map(SectionIdx::from) {
580 if section_idx == header.shstrtab_idx {
582 continue;
583 }
584
585 let header = section_headers.get(usize::from(section_idx)).unwrap();
586
587 match header.section_kind {
588 SectionKind::StrTab => {
589 str_tabs.push(
590 StringTable::parse(source, header.size, section_idx)
591 .map_err(KOParseError::StringTableParseError)?,
592 );
593 }
594 SectionKind::SymTab => {
595 sym_tabs.push(
596 SymbolTable::parse(source, header.size, section_idx)
597 .map_err(KOParseError::SymbolTableParseError)?,
598 );
599 }
600 SectionKind::Data => {
601 data_sections.push(
602 DataSection::parse(source, header.size, section_idx)
603 .map_err(KOParseError::DataSectionParseError)?,
604 );
605 }
606 SectionKind::Func => {
607 func_sections.push(
608 FuncSection::parse(source, header.size, section_idx)
609 .map_err(KOParseError::FunctionSectionParseError)?,
610 );
611 }
612 SectionKind::Reld => {
613 reld_sections.push(
614 ReldSection::parse(source, header.size, section_idx)
615 .map_err(KOParseError::ReldSectionParseError)?,
616 );
617 }
618 SectionKind::Debug => unimplemented!(),
619 SectionKind::Null => {
620 panic!("Internal library error. Attempted to parse \"null\" section, this should be unreachable.");
621 }
622 }
623 }
624
625 Ok(Self {
626 header,
627 shstrtab,
628 section_headers,
629 str_tabs,
630 sym_tabs,
631 data_sections,
632 func_sections,
633 reld_sections,
634 })
635 }
636
637 }
640
641impl Default for KOFile {
642 fn default() -> Self {
643 Self::new()
644 }
645}
646
647#[derive(Debug)]
650pub struct WritableKOFile(KOFile);
651
652impl WritableKOFile {
653 pub fn write(&self, buf: &mut impl WritableBuffer) {
655 let ko = &self.0;
656 ko.header.write(buf);
658
659 for header in &ko.section_headers {
661 header.write(buf);
662 }
663
664 for section_index in (0..ko.section_header_count()).map(|i| SectionIdx::from(i as u16)) {
666 if self.0.shstrtab.section_index() == section_index {
667 self.0.shstrtab.write(buf);
668 continue;
669 }
670
671 if let Some(section) = ko
672 .str_tabs
673 .iter()
674 .find(|s| s.section_index() == section_index)
675 {
676 section.write(buf);
677 continue;
678 }
679
680 if let Some(section) = ko
681 .sym_tabs
682 .iter()
683 .find(|s| s.section_index() == section_index)
684 {
685 section.write(buf);
686 continue;
687 }
688
689 if let Some(section) = ko
690 .data_sections
691 .iter()
692 .find(|s| s.section_index() == section_index)
693 {
694 section.write(buf);
695 continue;
696 }
697
698 if let Some(section) = ko
699 .func_sections
700 .iter()
701 .find(|s| s.section_index() == section_index)
702 {
703 section.write(buf);
704 continue;
705 }
706
707 if let Some(section) = ko
708 .reld_sections
709 .iter()
710 .find(|s| s.section_index() == section_index)
711 {
712 section.write(buf);
713 continue;
714 }
715 }
716 }
717
718 pub fn get(self) -> KOFile {
720 self.0
721 }
722}
723
724impl From<WritableKOFile> for KOFile {
725 fn from(w_kofile: WritableKOFile) -> Self {
726 w_kofile.0
727 }
728}
729
730#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
732pub struct KOHeader {
733 pub magic: u32,
735 pub version: u8,
737 pub num_headers: u16,
739 pub shstrtab_idx: SectionIdx,
741}
742
743impl KOHeader {
744 const HEADER_SIZE: usize = 9;
746
747 pub const fn new(num_headers: u16, shstrtab_idx: SectionIdx) -> Self {
749 Self {
750 magic: MAGIC_NUMBER,
751 version: FILE_VERSION,
752 num_headers,
753 shstrtab_idx,
754 }
755 }
756
757 pub const fn size() -> usize {
759 Self::HEADER_SIZE
760 }
761
762 fn write(&self, buf: &mut impl WritableBuffer) {
764 self.magic.to_bytes(buf);
765 self.version.to_bytes(buf);
766 self.num_headers.to_bytes(buf);
767 u16::from(self.shstrtab_idx).to_bytes(buf);
768 }
769
770 pub fn parse(source: &mut BufferIterator) -> Result<Self, HeaderParseError> {
772 let magic = u32::from_bytes(source).map_err(|_| HeaderParseError::MissingMagicError)?;
773 let version = u8::from_bytes(source).map_err(|_| HeaderParseError::MissingVersionError)?;
774 let num_headers =
775 u16::from_bytes(source).map_err(|_| HeaderParseError::MissingNumHeaders)?;
776 let shstrtab_idx = SectionIdx(
777 u16::from_bytes(source).map_err(|_| HeaderParseError::MissingShStrTabIndex)?,
778 );
779
780 if magic != MAGIC_NUMBER {
781 return Err(HeaderParseError::InvalidMagicError(magic, MAGIC_NUMBER));
782 }
783
784 if version != FILE_VERSION {
785 return Err(HeaderParseError::UnsupportedVersionError(
786 version,
787 FILE_VERSION,
788 ));
789 }
790
791 Ok(Self {
792 magic,
793 version,
794 num_headers,
795 shstrtab_idx,
796 })
797 }
798}
799
800macro_rules! gen_get_by_name {
803 ($(#[$ref_attr:meta])* => $func_name: ident, $(#[$mut_attr:meta])* => $mut_func_name: ident, $section_name: ident, $section_type: ty) => {
804 $(#[$ref_attr])*
805 pub fn $func_name(&self, name: impl AsRef<str>) -> Option<&$section_type> {
806 self.$section_name.iter().find(|section| {
807 match self.get_section_name_by_index(section.section_index()) {
808 Some(s) => s == name.as_ref(),
809 None => false,
810 }
811 })
812 }
813
814 $(#[$mut_attr])*
815 pub fn $mut_func_name(&mut self, name: impl AsRef<str>) -> Option<&mut $section_type> {
816 let mut index_opt = Some(0);
817
818 for (index, section) in self.$section_name.iter().enumerate() {
819 match self.get_section_name_by_index(section.section_index()) {
820 Some(s) => {
821 if s == name.as_ref() {
822 index_opt = Some(index);
823 break;
824 }
825 }
826 None => continue,
827 }
828 }
829
830 let index = index_opt?;
831
832 self.$section_name.iter_mut().nth(index)
833 }
834 };
835}
836
837macro_rules! gen_new_section {
838 ($(#[$attr:meta])* => $func_name: ident, $section_type: ty, $section_kind: expr) => {
839 $(#[$attr])*
840 pub fn $func_name(&mut self, name: impl Into<String>) -> $section_type {
841 let sh_index = self.new_section_header(name, $section_kind);
842 <$section_type>::with_capacity(4, sh_index)
843 }
844 };
845}
846
847impl KOFile {
848 gen_new_section! {
849 =>
854 new_strtab,
855 StringTable,
856 SectionKind::StrTab
857 }
858
859 gen_new_section! {
860 =>
865 new_symtab,
866 SymbolTable,
867 SectionKind::SymTab
868 }
869
870 gen_new_section! {
871 =>
876 new_data_section,
877 DataSection,
878 SectionKind::Data
879 }
880
881 gen_new_section! {
882 =>
887 new_func_section,
888 FuncSection,
889 SectionKind::Func
890 }
891
892 gen_new_section! {
893 =>
898 new_reld_section,
899 ReldSection,
900 SectionKind::Reld
901 }
902
903 gen_get_by_name! {
904 =>
907 str_tab_by_name,
908 =>
911 str_tab_by_name_mut, str_tabs, StringTable}
912
913 gen_get_by_name! {
914 =>
917 sym_tab_by_name,
918 =>
921 sym_tab_by_name_mut,
922 sym_tabs,
923 SymbolTable
924 }
925
926 gen_get_by_name! {
927 =>
930 data_section_by_name,
931 =>
934 data_section_by_name_mut,
935 data_sections,
936 DataSection
937 }
938
939 gen_get_by_name! {
940 =>
943 func_section_by_name,
944 =>
947 func_section_by_name_mut,
948 func_sections,
949 FuncSection
950 }
951
952 gen_get_by_name!(
953 =>
956 reld_section_by_name,
957 =>
960 reld_section_by_name_mut,
961 reld_sections,
962 ReldSection
963 );
964}