OpenCore  1.0.4
OpenCore Bootloader
Loading...
Searching...
No Matches
HeaderX.h
Go to the documentation of this file.
1
15#include "MachoX.h"
16
25STATIC
26BOOLEAN
28 IN OUT OC_MACHO_CONTEXT *Context,
29 IN CONST MACH_SECTION_X *Section,
30 IN CONST MACH_SEGMENT_COMMAND_X *Segment
31 )
32{
33 MACH_UINT_X TopOffsetX;
34 UINT32 TopOffset32;
35 MACH_UINT_X TopOfSegment;
36 BOOLEAN Result;
37 MACH_UINT_X TopOfSection;
38
39 ASSERT (Context != NULL);
40 ASSERT (Section != NULL);
41 ASSERT (Segment != NULL);
42 MACH_ASSERT_X (Context);
43
44 //
45 // Section->Alignment is stored as a power of 2.
46 //
47 if ( (Section->Alignment > 31)
48 || ((Section->Offset != 0) && (Section->Offset < Segment->FileOffset)))
49 {
50 return FALSE;
51 }
52
53 TopOfSegment = (Segment->VirtualAddress + Segment->Size);
54 Result = MACH_X (BaseOverflowAddU)(
55 Section->Address,
56 Section->Size,
57 &TopOfSection
58 );
59 if (Result || (TopOfSection > TopOfSegment)) {
60 return FALSE;
61 }
62
63 Result = MACH_X (BaseOverflowAddU)(
64 Section->Offset,
65 Section->Size,
66 &TopOffsetX
67 );
68 if (Result || (TopOffsetX > (Segment->FileOffset + Segment->FileSize))) {
69 return FALSE;
70 }
71
72 if (Section->NumRelocations != 0) {
73 Result = BaseOverflowMulAddU32 (
74 Section->NumRelocations,
75 sizeof (MACH_RELOCATION_INFO),
76 Section->RelocationsOffset,
77 &TopOffset32
78 );
79 if (Result || (TopOffset32 > Context->FileSize)) {
80 return FALSE;
81 }
82 }
83
84 return TRUE;
85}
86
95STATIC
96VOID
98 IN OUT MACH_HEADER_X *MachHeader
99 )
100{
101 STATIC CONST MACH_LOAD_COMMAND_TYPE LoadCommandsToStrip[] = {
109 };
110
111 UINT32 Index;
112 UINT32 Index2;
113 MACH_LOAD_COMMAND *LoadCommand;
114 UINT32 SizeOfLeftCommands;
115 UINT32 OriginalCommandSize;
116
117 //
118 // Delete the Code Signature Load Command if existent as we modified the
119 // binary, as well as linker metadata not needed for runtime operation.
120 //
121 LoadCommand = MachHeader->Commands;
122 SizeOfLeftCommands = MachHeader->CommandsSize;
123 OriginalCommandSize = SizeOfLeftCommands;
124
125 for (Index = 0; Index < MachHeader->NumCommands; ++Index) {
126 SizeOfLeftCommands -= LoadCommand->CommandSize;
127
128 for (Index2 = 0; Index2 < ARRAY_SIZE (LoadCommandsToStrip); ++Index2) {
129 if (LoadCommand->CommandType == LoadCommandsToStrip[Index2]) {
130 if (Index != (MachHeader->NumCommands - 1)) {
131 //
132 // If the current Load Command is not the last one, relocate the
133 // subsequent ones.
134 //
135 CopyMem (
136 LoadCommand,
137 NEXT_MACH_LOAD_COMMAND (LoadCommand),
138 SizeOfLeftCommands
139 );
140 }
141
142 --MachHeader->NumCommands;
143 MachHeader->CommandsSize -= LoadCommand->CommandSize;
144
145 break;
146 }
147 }
148
149 LoadCommand = NEXT_MACH_LOAD_COMMAND (LoadCommand);
150 }
151
152 ZeroMem (LoadCommand, OriginalCommandSize - MachHeader->CommandsSize);
153}
154
155UINT32
158 )(
159 IN OUT OC_MACHO_CONTEXT *Context
160 ) {
161 MACH_UINT_X VmSize;
162 MACH_SEGMENT_COMMAND_X *Segment;
163
164 ASSERT (Context != NULL);
165 ASSERT (Context->FileSize != 0);
166 MACH_ASSERT_X (Context);
167
168 VmSize = 0;
169
170 for (
171 Segment = MACH_X (MachoGetNextSegment)(Context, NULL);
172 Segment != NULL;
173 Segment = MACH_X (MachoGetNextSegment)(Context, Segment)
174 )
175 {
176 if (MACH_X (BaseOverflowAddU)(VmSize, Segment->Size, &VmSize)) {
177 return 0;
178 }
179
180 VmSize = MACHO_ALIGN (VmSize);
181 }
182
183 #ifndef MACHO_LIB_32
184 if (VmSize > MAX_UINT32) {
185 return 0;
186 }
187
188 #endif
189
190 return MACH_X_TO_UINT32 (VmSize);
191}
192
196 )(
197 IN OUT OC_MACHO_CONTEXT *Context,
198 IN MACH_LOAD_COMMAND_TYPE LoadCommandType,
199 IN CONST MACH_LOAD_COMMAND *LoadCommand OPTIONAL
200 ) {
202 MACH_HEADER_X *MachHeader;
203 UINTN TopOfCommands;
204
205 ASSERT (Context != NULL);
206 ASSERT (Context->MachHeader != NULL);
207 MACH_ASSERT_X (Context);
208
209 MachHeader = MACH_X (&Context->MachHeader->Header);
210
211 TopOfCommands = ((UINTN)MachHeader->Commands + MachHeader->CommandsSize);
212
213 if (LoadCommand != NULL) {
214 ASSERT (
215 (LoadCommand >= &MachHeader->Commands[0])
216 && ((UINTN)LoadCommand <= TopOfCommands)
217 );
218 Command = NEXT_MACH_LOAD_COMMAND (LoadCommand);
219 } else {
220 Command = &MachHeader->Commands[0];
221 }
222
223 for (
224 ;
225 (UINTN)Command < TopOfCommands;
227 )
228 {
229 if (Command->CommandType == LoadCommandType) {
230 return Command;
231 }
232 }
233
234 return NULL;
235}
236
237VOID *
240 )(
241 IN OUT OC_MACHO_CONTEXT *Context,
242 IN MACH_UINT_X Address,
243 OUT UINT32 *MaxSize OPTIONAL
244 ) {
245 CONST MACH_SEGMENT_COMMAND_X *Segment;
246 MACH_UINT_X Offset;
247
248 ASSERT (Context != NULL);
249 MACH_ASSERT_X (Context);
250
251 Segment = NULL;
252 while ((Segment = MACH_X (MachoGetNextSegment)(Context, Segment)) != NULL) {
253 if ( (Address >= Segment->VirtualAddress)
254 && (Address < Segment->VirtualAddress + Segment->Size))
255 {
256 Offset = (Address - Segment->VirtualAddress);
257
258 if (MaxSize != NULL) {
259 *MaxSize = MACH_X_TO_UINT32 (Segment->Size - Offset);
260 }
261
262 Offset += Segment->FileOffset;
263 return (VOID *)((UINTN)Context->FileData + (UINTN)Offset);
264 }
265 }
266
267 return NULL;
268}
269
270UINT32
273 )(
274 IN OC_MACHO_CONTEXT *Context,
275 IN BOOLEAN CalculateSizeOnly,
276 OUT UINT8 *Destination,
277 IN UINT32 DestinationSize,
278 IN BOOLEAN Strip,
279 OUT UINT64 *FileOffset OPTIONAL
280 ) {
282 UINT8 *Source;
283 UINT32 HeaderSize;
284 UINT32 HeaderSizeAligned;
285 BOOLEAN IsObject;
286
287 MACH_UINT_X CopyFileOffset;
288 MACH_UINT_X CopyFileSize;
289 MACH_UINT_X CopyVmSize;
290 MACH_UINT_X SegmentOffset;
291 UINT32 SectionOffset;
292 UINT32 SymbolsOffset;
293 UINT32 StringsOffset;
294 UINT32 AlignedOffset;
295 UINT32 RelocationsSize;
296 UINT32 SymtabSize;
297 UINT32 CurrentDelta;
298 UINT32 OriginalDelta;
299 MACH_UINT_X CurrentSize;
300 UINT32 FileSize;
301 MACH_SEGMENT_COMMAND_X *Segment;
302 MACH_SEGMENT_COMMAND_X *FirstSegment;
303 MACH_SEGMENT_COMMAND_X *DstSegment;
304 MACH_SYMTAB_COMMAND *Symtab;
305 MACH_DYSYMTAB_COMMAND *DySymtab;
306 UINT32 Index;
307 BOOLEAN FoundLinkedit;
308
309 ASSERT (Context != NULL);
310 ASSERT (Context->FileSize > 0);
311 MACH_ASSERT_X (Context);
312
313 if (!CalculateSizeOnly) {
314 ASSERT (Destination != NULL);
315 ASSERT (DestinationSize > 0);
316 }
317
318 //
319 // Header is valid, copy it first.
320 //
321 Header = MACH_X (MachoGetMachHeader)(Context);
322
323 //
324 // Mach-O files with an offset header (e.g., inner kernel files of Kernel
325 // Collections) cannot be reasonably expanded.
326 //
327 ASSERT ((CONST VOID *)Header == Context->FileData);
328
329 IsObject = Header->FileType == MachHeaderFileTypeObject;
330 Source = (UINT8 *)Header;
331 HeaderSize = sizeof (*Header) + Header->CommandsSize;
332 if (!CalculateSizeOnly) {
333 if (HeaderSize > DestinationSize) {
334 return 0;
335 }
336
337 CopyMem (Destination, Header, HeaderSize);
338 }
339
340 //
341 // Align header size to page size if this is an MH_OBJECT.
342 // The header does not exist in a segment in MH_OBJECT files.
343 //
344 HeaderSizeAligned = 0;
345 if (IsObject) {
346 HeaderSizeAligned = MACHO_ALIGN (HeaderSize);
347 if (!CalculateSizeOnly) {
348 if (HeaderSizeAligned > DestinationSize) {
349 return 0;
350 }
351
352 ZeroMem (&Destination[HeaderSize], HeaderSizeAligned - HeaderSize);
353 }
354 }
355
356 if (FileOffset != NULL) {
357 *FileOffset = 0;
358 }
359
360 CurrentDelta = 0;
361 FirstSegment = NULL;
362 CurrentSize = 0;
363 FoundLinkedit = FALSE;
364 for (
365 Segment = MACH_X (MachoGetNextSegment)(Context, NULL);
366 Segment != NULL;
367 Segment = MACH_X (MachoGetNextSegment)(Context, Segment)
368 )
369 {
370 if (Segment->FileSize > Segment->Size) {
371 return 0;
372 }
373
374 DEBUG ((
375 DEBUG_VERBOSE,
376 "OCMCO: Src segment offset 0x%X size 0x%X delta 0x%X\n",
377 Segment->FileOffset,
378 Segment->FileSize,
379 CurrentDelta
380 ));
381
382 //
383 // Align delta by x86 page size, this is what our lib expects.
384 //
385 OriginalDelta = CurrentDelta;
386 CurrentDelta = MACHO_ALIGN (CurrentDelta);
387
388 //
389 // Do not overwrite header. Header must be in the first segment, but not if we are MH_OBJECT.
390 // For objects, the header size will be aligned so we'll need to shift segments to account for this.
391 //
392 CopyFileOffset = Segment->FileOffset;
393 CopyFileSize = Segment->FileSize;
394 CopyVmSize = Segment->Size;
395
396 if (IsObject && (CopyFileOffset <= HeaderSizeAligned)) {
397 CurrentDelta = HeaderSizeAligned - HeaderSize;
398 //
399 // Some kexts seem to have empty space after header and before segment.
400 //
401 if (CopyFileOffset > HeaderSize) {
402 CurrentDelta -= (UINT32)(CopyFileOffset - HeaderSize);
403 }
404
405 if (FileOffset != NULL) {
406 *FileOffset = HeaderSizeAligned;
407 }
408 } else if (!IsObject && (CopyFileOffset <= HeaderSize)) {
409 CopyFileOffset = HeaderSize;
410 CopyFileSize = Segment->FileSize - CopyFileOffset;
411 CopyVmSize = Segment->Size - CopyFileOffset;
412 if ((CopyFileSize > Segment->FileSize) || (CopyVmSize > Segment->Size)) {
413 //
414 // Header must fit in one segment.
415 //
416 return 0;
417 }
418 }
419
420 //
421 // Store first segment.
422 //
423 if (FirstSegment == NULL) {
424 FirstSegment = Segment;
425 }
426
427 //
428 // Ensure that it still fits. In legit files segments are ordered.
429 // We do not care for other (the file will be truncated).
430 //
431 if ( MACH_X (BaseOverflowTriAddU)(CopyFileOffset, CurrentDelta, CopyVmSize, &CurrentSize)
432 || (!CalculateSizeOnly && (CurrentSize > DestinationSize)))
433 {
434 return 0;
435 }
436
437 //
438 // Copy and zero fill file data. We can do this because only last sections can have 0 file size.
439 //
440 #ifndef MACHO_LIB_32
441 ASSERT (CopyFileSize <= MAX_UINTN && CopyVmSize <= MAX_UINTN);
442 #endif
443 if (!CalculateSizeOnly) {
444 ZeroMem (&Destination[CopyFileOffset + OriginalDelta], CurrentDelta - OriginalDelta);
445 CopyMem (&Destination[CopyFileOffset + CurrentDelta], &Source[CopyFileOffset], (UINTN)CopyFileSize);
446 ZeroMem (&Destination[CopyFileOffset + CurrentDelta + CopyFileSize], (UINTN)(CopyVmSize - CopyFileSize));
447 }
448
449 //
450 // Grab pointer to destination segment and updated offsets.
451 // If we are only calculating a size, we'll just use the source segment
452 // here for a cleaner function.
453 //
454 if (!CalculateSizeOnly) {
455 DstSegment = (MACH_SEGMENT_COMMAND_X *)((UINT8 *)Segment - Source + Destination);
456 } else {
457 DstSegment = Segment;
458 }
459
460 SegmentOffset = DstSegment->FileOffset + CurrentDelta;
461
462 DEBUG ((
463 DEBUG_VERBOSE,
464 "OCMCO: Dst segment offset 0x%X size 0x%X delta 0x%X\n",
465 SegmentOffset,
466 DstSegment->Size,
467 CurrentDelta
468 ));
469
470 if (!IsObject && (DstSegment->VirtualAddress - SegmentOffset != FirstSegment->VirtualAddress)) {
471 return 0;
472 }
473
474 if (!CalculateSizeOnly) {
475 DstSegment->FileOffset = SegmentOffset;
476 DstSegment->FileSize = DstSegment->Size;
477 }
478
479 //
480 // We need to update fields in SYMTAB and DYSYMTAB. Tables have to be present before 0 FileSize
481 // sections as they have data, so we update them before parsing sections.
482 // Note: There is an assumption they are in __LINKEDIT segment, another option is to check addresses.
483 //
484 if (AsciiStrnCmp (DstSegment->SegmentName, "__LINKEDIT", ARRAY_SIZE (DstSegment->SegmentName)) == 0) {
485 FoundLinkedit = TRUE;
486
487 if (!CalculateSizeOnly) {
488 Symtab = (MACH_SYMTAB_COMMAND *)(
490 Context,
492 NULL
493 )
494 );
495
496 if (Symtab != NULL) {
497 Symtab = (MACH_SYMTAB_COMMAND *)((UINT8 *)Symtab - Source + Destination);
498 if (Symtab->SymbolsOffset != 0) {
499 Symtab->SymbolsOffset += CurrentDelta;
500 }
501
502 if (Symtab->StringsOffset != 0) {
503 Symtab->StringsOffset += CurrentDelta;
504 }
505 }
506
507 DySymtab = (MACH_DYSYMTAB_COMMAND *)(
509 Context,
511 NULL
512 )
513 );
514
515 if (DySymtab != NULL) {
516 DySymtab = (MACH_DYSYMTAB_COMMAND *)((UINT8 *)DySymtab - Source + Destination);
517 if (DySymtab->TableOfContentsNumEntries != 0) {
518 DySymtab->TableOfContentsNumEntries += CurrentDelta;
519 }
520
521 if (DySymtab->ModuleTableFileOffset != 0) {
522 DySymtab->ModuleTableFileOffset += CurrentDelta;
523 }
524
525 if (DySymtab->ReferencedSymbolTableFileOffset != 0) {
526 DySymtab->ReferencedSymbolTableFileOffset += CurrentDelta;
527 }
528
529 if (DySymtab->IndirectSymbolsOffset != 0) {
530 DySymtab->IndirectSymbolsOffset += CurrentDelta;
531 }
532
533 if (DySymtab->ExternalRelocationsOffset != 0) {
534 DySymtab->ExternalRelocationsOffset += CurrentDelta;
535 }
536
537 if (DySymtab->LocalRelocationsOffset != 0) {
538 DySymtab->LocalRelocationsOffset += CurrentDelta;
539 }
540 }
541 }
542 }
543
544 //
545 // These may well wrap around with invalid data.
546 // But we do not care, as we do not access these fields ourselves,
547 // and later on the section values are checked by MachoLib.
548 // Note: There is an assumption that 'CopyFileOffset + CurrentDelta' is aligned.
549 //
550 OriginalDelta = CurrentDelta;
551 CopyFileOffset = DstSegment->FileOffset;
552 for (Index = 0; Index < DstSegment->NumSections; ++Index) {
553 SectionOffset = DstSegment->Sections[Index].Offset;
554
555 DEBUG ((
556 DEBUG_VERBOSE,
557 "OCMCO: Src section %u offset 0x%X size 0x%X delta 0x%X\n",
558 Index,
559 SectionOffset,
560 DstSegment->Sections[Index].Size,
561 CurrentDelta
562 ));
563
564 //
565 // Allocate space for zero offset sections.
566 // For all other sections, copy as-is.
567 //
568 if (DstSegment->Sections[Index].Offset == 0) {
569 SectionOffset = MACH_X_TO_UINT32 (CopyFileOffset);
570 CopyFileOffset += MACH_X_TO_UINT32 (DstSegment->Sections[Index].Size);
571 CurrentDelta += MACH_X_TO_UINT32 (DstSegment->Sections[Index].Size);
572 } else {
573 SectionOffset += CurrentDelta;
574 CopyFileOffset = SectionOffset + DstSegment->Sections[Index].Size;
575 }
576
577 DEBUG ((
578 DEBUG_VERBOSE,
579 "OCMCO: Dst section %u offset 0x%X size 0x%X delta 0x%X\n",
580 Index,
581 SectionOffset,
582 DstSegment->Sections[Index].Size,
583 CurrentDelta
584 ));
585
586 if (!CalculateSizeOnly) {
587 DstSegment->Sections[Index].Offset = SectionOffset;
588 }
589 }
590
591 CurrentDelta = OriginalDelta + MACH_X_TO_UINT32 (Segment->Size - Segment->FileSize);
592 }
593
594 //
595 // If we did not find __LINKEDIT, we'll need to manually update SYMTAB and section relocations.
596 // This assumes that if there is __LINKEDIT, all relocations are in __LINKEDIT and not in sections.
597 //
598 if (!FoundLinkedit) {
599 DEBUG ((DEBUG_VERBOSE, "OCMCO: __LINKEDIT not found\n"));
600
601 //
602 // Copy section relocations.
603 //
604 for (
605 Segment = MACH_X (MachoGetNextSegment)(Context, NULL);
606 Segment != NULL;
607 Segment = MACH_X (MachoGetNextSegment)(Context, Segment)
608 )
609 {
610 if (!CalculateSizeOnly) {
611 DstSegment = (MACH_SEGMENT_COMMAND_X *)((UINT8 *)Segment - Source + Destination);
612 } else {
613 DstSegment = Segment;
614 }
615
616 for (Index = 0; Index < DstSegment->NumSections; ++Index) {
617 SectionOffset = DstSegment->Sections[Index].RelocationsOffset;
618
619 if (SectionOffset != 0) {
620 DEBUG ((
621 DEBUG_VERBOSE,
622 "OCMCO: Src section %u relocs offset 0x%X count %u delta 0x%X\n",
623 Index,
624 SectionOffset,
625 DstSegment->Sections[Index].NumRelocations,
626 CurrentDelta
627 ));
628
629 CopyFileOffset = SectionOffset;
630 RelocationsSize = DstSegment->Sections[Index].NumRelocations * sizeof (MACH_RELOCATION_INFO);
631 AlignedOffset = ALIGN_VALUE (SectionOffset + CurrentDelta, sizeof (MACH_RELOCATION_INFO));
632 CurrentDelta = AlignedOffset - SectionOffset;
633
634 if ( MACH_X (BaseOverflowTriAddU)(CopyFileOffset, CurrentDelta, RelocationsSize, &CurrentSize)
635 || (!CalculateSizeOnly && (CurrentSize > DestinationSize)))
636 {
637 return 0;
638 }
639
640 SectionOffset += CurrentDelta;
641
642 DEBUG ((
643 DEBUG_VERBOSE,
644 "OCMCO: Dst section %u relocs offset 0x%X count %u delta 0x%X\n",
645 Index,
646 SectionOffset,
647 DstSegment->Sections[Index].NumRelocations,
648 CurrentDelta
649 ));
650
651 if (!CalculateSizeOnly) {
652 DstSegment->Sections[Index].RelocationsOffset = SectionOffset;
653 CopyMem (&Destination[CopyFileOffset + CurrentDelta], &Source[CopyFileOffset], RelocationsSize);
654 }
655 }
656 }
657 }
658
659 //
660 // Copy symbols and string tables.
661 //
662 Symtab = (MACH_SYMTAB_COMMAND *)(
664 Context,
666 NULL
667 )
668 );
669 if (Symtab != NULL) {
670 SymbolsOffset = Symtab->SymbolsOffset;
671 StringsOffset = Symtab->StringsOffset;
672
673 DEBUG ((
674 DEBUG_VERBOSE,
675 "OCMCO: Src symtab 0x%X (%u symbols), strings 0x%X (size 0x%X) delta 0x%X\n",
676 SymbolsOffset,
677 Symtab->NumSymbols,
678 StringsOffset,
679 Symtab->StringsSize,
680 CurrentDelta
681 ));
682
683 if (!CalculateSizeOnly) {
684 Symtab = (MACH_SYMTAB_COMMAND *)((UINT8 *)Symtab - Source + Destination);
685 }
686
687 //
688 // Copy symbol table.
689 //
690 if (SymbolsOffset != 0) {
691 CopyFileOffset = SymbolsOffset;
692 SymtabSize = Symtab->NumSymbols * sizeof (MACH_NLIST_X);
693 AlignedOffset = ALIGN_VALUE (SymbolsOffset + CurrentDelta, sizeof (MACH_NLIST_X));
694 CurrentDelta = AlignedOffset - SymbolsOffset;
695
696 if ( MACH_X (BaseOverflowTriAddU)(CopyFileOffset, CurrentDelta, SymtabSize, &CurrentSize)
697 || (!CalculateSizeOnly && (CurrentSize > DestinationSize)))
698 {
699 return 0;
700 }
701
702 SymbolsOffset += CurrentDelta;
703
704 if (!CalculateSizeOnly) {
705 Symtab->SymbolsOffset = SymbolsOffset;
706 CopyMem (&Destination[CopyFileOffset + CurrentDelta], &Source[CopyFileOffset], SymtabSize);
707 }
708 }
709
710 //
711 // Copy string table.
712 //
713 if (StringsOffset != 0) {
714 CopyFileOffset = StringsOffset;
715 if ( MACH_X (BaseOverflowTriAddU)(CopyFileOffset, CurrentDelta, Symtab->StringsSize, &CurrentSize)
716 || (!CalculateSizeOnly && (CurrentSize > DestinationSize)))
717 {
718 return 0;
719 }
720
721 StringsOffset += CurrentDelta;
722
723 if (!CalculateSizeOnly) {
724 Symtab->StringsOffset = StringsOffset;
725 CopyMem (&Destination[CopyFileOffset + CurrentDelta], &Source[CopyFileOffset], Symtab->StringsSize);
726 }
727 }
728
729 DEBUG ((
730 DEBUG_VERBOSE,
731 "OCMCO: Dst symtab 0x%X (%u symbols), strings 0x%X (size 0x%X) delta 0x%X\n",
732 SymbolsOffset,
733 Symtab->NumSymbols,
734 StringsOffset,
735 Symtab->StringsSize,
736 CurrentDelta
737 ));
738 }
739 }
740
741 //
742 // CurrentSize will only be 0 if there are no valid segments, which is the
743 // case for Kernel Resource KEXTs. In this case, try to use the raw file.
744 //
745 if (CurrentSize == 0) {
746 FileSize = MachoGetFileSize (Context);
747 //
748 // HeaderSize must be at most as big as the file size by OcMachoLib
749 // guarantees. It's sanity-checked to ensure the safety of the subtraction.
750 //
751 ASSERT (FileSize >= HeaderSize);
752
753 if ((!CalculateSizeOnly && (FileSize > DestinationSize))) {
754 return 0;
755 }
756
757 if (!CalculateSizeOnly) {
758 CopyMem (
759 Destination + HeaderSize,
760 (UINT8 *)Header + HeaderSize,
761 FileSize - HeaderSize
762 );
763 }
764
765 CurrentSize = FileSize;
766 }
767
768 if (!CalculateSizeOnly && Strip) {
770 }
771
772 //
773 // This cast is safe because CurrentSize is verified against DestinationSize.
774 //
775 return MACH_X_TO_UINT32 (CurrentSize);
776}
777
778BOOLEAN
781 )(
782 IN OUT OC_MACHO_CONTEXT *Context,
783 IN CONST CHAR8 *Prefix
784 ) {
785 UINT32 LcIndex;
786 MACH_LOAD_COMMAND *LoadCommand;
787 MACH_SEGMENT_COMMAND_X *Segment;
788 MACH_SEGMENT_COMMAND_X *FirstSegment;
790 UINTN PrefixLength;
791 UINTN RemainingArea;
792 UINT32 SkipCount;
793
794 ASSERT (Context != NULL);
795 ASSERT (Context->FileSize != 0);
796 ASSERT (Prefix != NULL);
797 MACH_ASSERT_X (Context);
798
799 Header = MACH_X (MachoGetMachHeader)(Context);
800 PrefixLength = AsciiStrLen (Prefix);
801 FirstSegment = NULL;
802
803 SkipCount = 0;
804
805 LoadCommand = &Header->Commands[0];
806
807 for (LcIndex = 0; LcIndex < Header->NumCommands; ++LcIndex) {
808 //
809 // Either skip or stop at unrelated commands.
810 //
811 Segment = (MACH_SEGMENT_COMMAND_X *)(VOID *)LoadCommand;
812
813 if ( (LoadCommand->CommandType != MACH_LOAD_COMMAND_SEGMENT_X)
814 || (AsciiStrnCmp (Segment->SegmentName, Prefix, PrefixLength) != 0))
815 {
816 if (FirstSegment != NULL) {
817 break;
818 }
819
820 LoadCommand = NEXT_MACH_LOAD_COMMAND (LoadCommand);
821 continue;
822 }
823
824 //
825 // We have a segment starting with the prefix.
826 //
827
828 //
829 // Do not support this for now as it will require changes in the file.
830 //
831 if (Segment->Size != Segment->FileSize) {
832 return FALSE;
833 }
834
835 //
836 // Remember the first segment or assume it is a skip.
837 //
838 if (FirstSegment == NULL) {
839 FirstSegment = Segment;
840 } else {
841 ++SkipCount;
842
843 //
844 // Expand the first segment.
845 // TODO: Do we need to check these for overflow for our own purposes?
846 //
847 FirstSegment->Size = Segment->VirtualAddress - FirstSegment->VirtualAddress + Segment->Size;
848 FirstSegment->FileSize = Segment->FileOffset - FirstSegment->FileOffset + Segment->FileSize;
849
850 //
851 // Add new segment protection to the first segment.
852 //
853 FirstSegment->InitialProtection |= Segment->InitialProtection;
854 FirstSegment->MaximumProtection |= Segment->MaximumProtection;
855 }
856
857 LoadCommand = NEXT_MACH_LOAD_COMMAND (LoadCommand);
858 }
859
860 //
861 // The segment does not exist.
862 //
863 if (FirstSegment == NULL) {
864 return FALSE;
865 }
866
867 //
868 // The segment is only one.
869 //
870 if (SkipCount == 0) {
871 return FALSE;
872 }
873
874 //
875 // Move back remaining commands ontop of the skipped ones and zero this area.
876 //
877 RemainingArea = Header->CommandsSize - ((UINTN)LoadCommand - (UINTN)&Header->Commands[0]);
878 CopyMem (
879 (UINT8 *)FirstSegment + FirstSegment->CommandSize,
880 LoadCommand,
881 RemainingArea
882 );
883 ZeroMem (LoadCommand, RemainingArea);
884
885 //
886 // Account for dropped commands in the header.
887 //
888 Header->NumCommands -= SkipCount;
889 Header->CommandsSize -= (UINT32)(sizeof (MACH_SEGMENT_COMMAND_X) * SkipCount);
890
891 return TRUE;
892}
893
894BOOLEAN
897 )(
898 OUT OC_MACHO_CONTEXT *Context,
899 IN VOID *FileData,
900 IN UINT32 FileSize,
901 IN UINT32 HeaderOffset,
902 IN UINT32 InnerSize
903 ) {
904 EFI_STATUS Status;
905 VOID *MachData;
906 MACH_HEADER_X *MachHeader;
907 UINTN TopOfFile;
908 UINTN TopOfCommands;
909 UINT32 Index;
911 UINTN TopOfCommand;
912 UINT32 CommandsSize;
913 BOOLEAN Result;
914
915 ASSERT (FileData != NULL);
916 ASSERT (FileSize > 0);
917 ASSERT (FileSize >= HeaderOffset);
918 ASSERT (Context != NULL);
919
920 if (HeaderOffset == 0) {
921 ASSERT (InnerSize == FileSize);
922 }
923
924 ASSERT (FileSize >= InnerSize && FileSize - InnerSize >= HeaderOffset);
925
926 TopOfFile = ((UINTN)FileData + FileSize);
927 ASSERT (TopOfFile > (UINTN)FileData);
928
929 MachData = (UINT8 *)FileData + HeaderOffset;
930
931 //
932 // Inner files of Kernel Collections cannot be FAT.
933 //
934 if (HeaderOffset == 0) {
935 #ifdef MACHO_LIB_32
936 Status = FatFilterArchitecture32 ((UINT8 **)&MachData, &FileSize);
937 #else
938 Status = FatFilterArchitecture64 ((UINT8 **)&MachData, &FileSize);
939 #endif
940 if (EFI_ERROR (Status)) {
941 return FALSE;
942 }
943
944 FileData = MachData;
945 InnerSize = FileSize;
946 }
947
948 if ( (FileSize < sizeof (*MachHeader))
949 || !BASE_TYPE_ALIGNED (MACH_HEADER_X, MachData))
950 {
951 return FALSE;
952 }
953
954 MachHeader = (MACH_HEADER_X *)MachData;
955 #ifdef MACHO_LIB_32
956 if (MachHeader->Signature != MACH_HEADER_SIGNATURE) {
957 #else
958 if (MachHeader->Signature != MACH_HEADER_64_SIGNATURE) {
959 #endif
960 return FALSE;
961 }
962
963 Result = BaseOverflowAddUN (
964 (UINTN)MachHeader->Commands,
965 MachHeader->CommandsSize,
966 &TopOfCommands
967 );
968 if (Result || (TopOfCommands > TopOfFile)) {
969 return FALSE;
970 }
971
972 CommandsSize = 0;
973
974 for (
975 Index = 0, Command = MachHeader->Commands;
976 Index < MachHeader->NumCommands;
978 )
979 {
980 Result = BaseOverflowAddUN (
981 (UINTN)Command,
982 sizeof (*Command),
983 &TopOfCommand
984 );
985 if ( Result
986 || (TopOfCommand > TopOfCommands)
987 || (Command->CommandSize < sizeof (*Command))
988 || ((Command->CommandSize % sizeof (MACH_UINT_X)) != 0)
989 )
990 {
991 return FALSE;
992 }
993
994 Result = BaseOverflowAddU32 (
995 CommandsSize,
996 Command->CommandSize,
997 &CommandsSize
998 );
999 if (Result) {
1000 return FALSE;
1001 }
1002 }
1003
1004 if (MachHeader->CommandsSize != CommandsSize) {
1005 return FALSE;
1006 }
1007
1008 //
1009 // Verify assumptions made by this library.
1010 // Carefully audit all "Assumption:" remarks before modifying these checks.
1011 //
1012 #ifdef MACHO_LIB_32
1013 if ( (MachHeader->CpuType != MachCpuTypeI386)
1014 #else
1015 if ((MachHeader->CpuType != MachCpuTypeX8664)
1016 #endif
1017 || ( (MachHeader->FileType != MachHeaderFileTypeKextBundle)
1018 && (MachHeader->FileType != MachHeaderFileTypeExecute)
1019 && (MachHeader->FileType != MachHeaderFileTypeFileSet)
1020 #ifdef MACHO_LIB_32
1021 && (MachHeader->FileType != MachHeaderFileTypeObject)))
1022 {
1023 #else
1024 )) {
1025 #endif
1026 return FALSE;
1027 }
1028
1029 ZeroMem (Context, sizeof (*Context));
1030
1031 Context->MachHeader = (MACH_HEADER_ANY *)MachHeader;
1032 Context->Is32Bit = MachHeader->CpuType == MachCpuTypeI386;
1033 Context->FileData = FileData;
1034 Context->FileSize = FileSize;
1035 Context->InnerSize = InnerSize;
1036
1037 return TRUE;
1038}
1039
1043 )(
1044 IN OUT OC_MACHO_CONTEXT *Context
1045 ) {
1046 ASSERT (Context != NULL);
1047 ASSERT (Context->MachHeader != NULL);
1048 MACH_ASSERT_X (Context);
1049
1050 return MACH_X (&Context->MachHeader->Header);
1051}
1052
1056 )(
1057 IN OUT OC_MACHO_CONTEXT *Context
1058 ) {
1059 MACH_UINT_X LastAddress;
1060
1061 CONST MACH_SEGMENT_COMMAND_X *Segment;
1062 MACH_UINT_X Address;
1063
1064 ASSERT (Context != NULL);
1065 MACH_ASSERT_X (Context);
1066
1067 LastAddress = 0;
1068
1069 for (
1070 Segment = MACH_X (MachoGetNextSegment)(Context, NULL);
1071 Segment != NULL;
1072 Segment = MACH_X (MachoGetNextSegment)(Context, Segment)
1073 )
1074 {
1075 Address = (Segment->VirtualAddress + Segment->Size);
1076
1077 if (Address > LastAddress) {
1078 LastAddress = Address;
1079 }
1080 }
1081
1082 return LastAddress;
1083}
1084
1088 )(
1089 IN OUT OC_MACHO_CONTEXT *Context,
1090 IN CONST CHAR8 *SegmentName
1091 ) {
1092 MACH_SEGMENT_COMMAND_X *Segment;
1093 INTN Result;
1094
1095 ASSERT (Context != NULL);
1096 ASSERT (SegmentName != NULL);
1097 MACH_ASSERT_X (Context);
1098
1099 Result = 0;
1100
1101 for (
1102 Segment = MACH_X (MachoGetNextSegment)(Context, NULL);
1103 Segment != NULL;
1104 Segment = MACH_X (MachoGetNextSegment)(Context, Segment)
1105 )
1106 {
1107 Result = AsciiStrnCmp (
1108 Segment->SegmentName,
1109 SegmentName,
1110 ARRAY_SIZE (Segment->SegmentName)
1111 );
1112 if (Result == 0) {
1113 return Segment;
1114 }
1115 }
1116
1117 return NULL;
1118}
1119
1123 )(
1124 IN OUT OC_MACHO_CONTEXT *Context,
1125 IN MACH_SEGMENT_COMMAND_X *Segment,
1126 IN CONST CHAR8 *SectionName
1127 ) {
1128 MACH_SECTION_X *Section;
1129 INTN Result;
1130
1131 ASSERT (Context != NULL);
1132 ASSERT (Segment != NULL);
1133 ASSERT (SectionName != NULL);
1134 MACH_ASSERT_X (Context);
1135
1136 for (
1137 Section = MACH_X (MachoGetNextSection)(Context, Segment, NULL);
1138 Section != NULL;
1139 Section = MACH_X (MachoGetNextSection)(Context, Segment, Section)
1140 )
1141 {
1142 //
1143 // Assumption: Mach-O is not of type MH_OBJECT.
1144 // MH_OBJECT might have sections in segments they do not belong in for
1145 // performance reasons. This library does not support intermediate
1146 // objects.
1147 //
1148 Result = AsciiStrnCmp (
1149 Section->SectionName,
1150 SectionName,
1151 ARRAY_SIZE (Section->SectionName)
1152 );
1153 if (Result == 0) {
1154 return Section;
1155 }
1156 }
1157
1158 return NULL;
1159}
1160
1164 )(
1165 IN OUT OC_MACHO_CONTEXT *Context,
1166 IN CONST CHAR8 *SegmentName,
1167 IN CONST CHAR8 *SectionName
1168 ) {
1169 MACH_SEGMENT_COMMAND_X *Segment;
1170
1171 ASSERT (Context != NULL);
1172 ASSERT (SegmentName != NULL);
1173 ASSERT (SectionName != NULL);
1174 MACH_ASSERT_X (Context);
1175
1176 Segment = MACH_X (MachoGetSegmentByName)(Context, SegmentName);
1177
1178 if (Segment != NULL) {
1179 return MACH_X (MachoGetSectionByName)(Context, Segment, SectionName);
1180 }
1181
1182 return NULL;
1183}
1184
1188 )(
1189 IN OUT OC_MACHO_CONTEXT *Context,
1190 IN CONST MACH_SEGMENT_COMMAND_X *Segment OPTIONAL
1191 ) {
1192 MACH_SEGMENT_COMMAND_X *NextSegment;
1193
1194 CONST MACH_HEADER_X *MachHeader;
1195 UINTN TopOfCommands;
1196 BOOLEAN Result;
1197 MACH_UINT_X TopOfSegment;
1198 UINTN TopOfSections;
1199
1200 ASSERT (Context != NULL);
1201 ASSERT (Context->FileSize > 0);
1202 MACH_ASSERT_X (Context);
1203
1204 if (Segment != NULL) {
1205 MachHeader = MACH_X (MachoGetMachHeader)(Context);
1206 TopOfCommands = ((UINTN)MachHeader->Commands + MachHeader->CommandsSize);
1207 ASSERT (
1208 ((UINTN)Segment >= (UINTN)&MachHeader->Commands[0])
1209 && ((UINTN)Segment < TopOfCommands)
1210 );
1211 }
1212
1213 //
1214 // Context initialisation guarantees the command size is a multiple of 8.
1215 //
1217 BASE_ALIGNOF (MACH_SEGMENT_COMMAND_X) <= sizeof (UINT64),
1218 "Alignment is not guaranteed."
1219 );
1220 NextSegment = (MACH_SEGMENT_COMMAND_X *)(VOID *)MachoGetNextCommand (
1221 Context,
1223 (CONST MACH_LOAD_COMMAND *)Segment
1224 );
1225 if ((NextSegment == NULL) || (NextSegment->CommandSize < sizeof (*NextSegment))) {
1226 return NULL;
1227 }
1228
1229 Result = BaseOverflowMulAddUN (
1230 NextSegment->NumSections,
1231 sizeof (*NextSegment->Sections),
1232 (UINTN)NextSegment->Sections,
1233 &TopOfSections
1234 );
1235 if (Result || (((UINTN)NextSegment + NextSegment->CommandSize) < TopOfSections)) {
1236 return NULL;
1237 }
1238
1239 Result = MACH_X (BaseOverflowAddU)(
1240 NextSegment->FileOffset,
1241 NextSegment->FileSize,
1242 &TopOfSegment
1243 );
1244 if (Result || (TopOfSegment > Context->FileSize)) {
1245 return NULL;
1246 }
1247
1248 if (NextSegment->VirtualAddress + NextSegment->Size < NextSegment->VirtualAddress) {
1249 return NULL;
1250 }
1251
1252 return NextSegment;
1253}
1254
1258 )(
1259 IN OUT OC_MACHO_CONTEXT *Context,
1260 IN MACH_SEGMENT_COMMAND_X *Segment,
1261 IN MACH_SECTION_X *Section OPTIONAL
1262 ) {
1263 ASSERT (Context != NULL);
1264 ASSERT (Segment != NULL);
1265 MACH_ASSERT_X (Context);
1266
1267 if (Section != NULL) {
1268 ASSERT (Section >= Segment->Sections);
1269
1270 ++Section;
1271
1272 if (Section >= &Segment->Sections[Segment->NumSections]) {
1273 return NULL;
1274 }
1275 } else if (Segment->NumSections > 0) {
1276 Section = &Segment->Sections[0];
1277 } else {
1278 return NULL;
1279 }
1280
1281 if (!InternalSectionIsSane (Context, Section, Segment)) {
1282 return NULL;
1283 }
1284
1285 return Section;
1286}
1287
1291 )(
1292 IN OUT OC_MACHO_CONTEXT *Context,
1293 IN UINT32 Index
1294 ) {
1295 MACH_SECTION_X *Section;
1296
1297 MACH_SEGMENT_COMMAND_X *Segment;
1298 UINT32 SectionIndex;
1299 UINT32 NextSectionIndex;
1300 BOOLEAN Result;
1301
1302 ASSERT (Context != NULL);
1303 MACH_ASSERT_X (Context);
1304
1305 SectionIndex = 0;
1306
1307 Segment = NULL;
1308 for (
1309 Segment = MACH_X (MachoGetNextSegment)(Context, NULL);
1310 Segment != NULL;
1311 Segment = MACH_X (MachoGetNextSegment)(Context, Segment)
1312 )
1313 {
1314 Result = BaseOverflowAddU32 (
1315 SectionIndex,
1316 Segment->NumSections,
1317 &NextSectionIndex
1318 );
1319 //
1320 // If NextSectionIndex is wrapping around, Index must be contained.
1321 //
1322 if (Result || (Index < NextSectionIndex)) {
1323 Section = &Segment->Sections[Index - SectionIndex];
1324 if (!InternalSectionIsSane (Context, Section, Segment)) {
1325 return NULL;
1326 }
1327
1328 return Section;
1329 }
1330
1331 SectionIndex = NextSectionIndex;
1332 }
1333
1334 return NULL;
1335}
1336
1340 )(
1341 IN OUT OC_MACHO_CONTEXT *Context,
1342 IN MACH_UINT_X Address
1343 ) {
1344 MACH_SEGMENT_COMMAND_X *Segment;
1345 MACH_SECTION_X *Section;
1346 MACH_UINT_X TopOfSegment;
1347 MACH_UINT_X TopOfSection;
1348
1349 ASSERT (Context != NULL);
1350 MACH_ASSERT_X (Context);
1351
1352 for (
1353 Segment = MACH_X (MachoGetNextSegment)(Context, NULL);
1354 Segment != NULL;
1355 Segment = MACH_X (MachoGetNextSegment)(Context, Segment)
1356 )
1357 {
1358 TopOfSegment = (Segment->VirtualAddress + Segment->Size);
1359 if ((Address >= Segment->VirtualAddress) && (Address < TopOfSegment)) {
1360 for (
1361 Section = MACH_X (MachoGetNextSection)(Context, Segment, NULL);
1362 Section != NULL;
1363 Section = MACH_X (MachoGetNextSection)(Context, Segment, Section)
1364 )
1365 {
1366 TopOfSection = (Section->Address + Section->Size);
1367 if ((Address >= Section->Address) && (Address < TopOfSection)) {
1368 return Section;
1369 }
1370 }
1371 }
1372 }
1373
1374 return NULL;
1375}
1376
1377UINT32
1380 )(
1381 IN OUT OC_MACHO_CONTEXT *Context,
1382 OUT CONST MACH_NLIST_X **SymbolTable,
1383 OUT CONST CHAR8 **StringTable OPTIONAL,
1384 OUT CONST MACH_NLIST_X **LocalSymbols OPTIONAL,
1385 OUT UINT32 *NumLocalSymbols OPTIONAL,
1386 OUT CONST MACH_NLIST_X **ExternalSymbols OPTIONAL,
1387 OUT UINT32 *NumExternalSymbols OPTIONAL,
1388 OUT CONST MACH_NLIST_X **UndefinedSymbols OPTIONAL,
1389 OUT UINT32 *NumUndefinedSymbols OPTIONAL
1390 ) {
1391 UINT32 Index;
1392 CONST MACH_NLIST_X *SymTab;
1393 UINT32 NoLocalSymbols;
1394 UINT32 NoExternalSymbols;
1395 UINT32 NoUndefinedSymbols;
1396
1397 ASSERT (Context != NULL);
1398 ASSERT (SymbolTable != NULL);
1399 MACH_ASSERT_X (Context);
1400
1401 if (!InternalRetrieveSymtabs (Context)) {
1402 return 0;
1403 }
1404
1405 if (Context->Symtab->NumSymbols == 0) {
1406 return 0;
1407 }
1408
1409 SymTab = MACH_X (&Context->SymbolTable->Symbol);
1410
1411 for (Index = 0; Index < Context->Symtab->NumSymbols; ++Index) {
1412 if (!MACH_X (InternalSymbolIsSane)(Context, &SymTab[Index])) {
1413 return 0;
1414 }
1415 }
1416
1417 *SymbolTable = MACH_X (&Context->SymbolTable->Symbol);
1418
1419 if (StringTable != NULL) {
1420 *StringTable = Context->StringTable;
1421 }
1422
1423 NoLocalSymbols = 0;
1424 NoExternalSymbols = 0;
1425 NoUndefinedSymbols = 0;
1426
1427 if (Context->DySymtab != NULL) {
1428 NoLocalSymbols = Context->DySymtab->NumLocalSymbols;
1429 NoExternalSymbols = Context->DySymtab->NumExternalSymbols;
1430 NoUndefinedSymbols = Context->DySymtab->NumUndefinedSymbols;
1431 }
1432
1433 if (NumLocalSymbols != NULL) {
1434 ASSERT (LocalSymbols != NULL);
1435 *NumLocalSymbols = NoLocalSymbols;
1436 if (NoLocalSymbols != 0) {
1437 *LocalSymbols = &SymTab[Context->DySymtab->LocalSymbolsIndex];
1438 }
1439 }
1440
1441 if (NumExternalSymbols != NULL) {
1442 ASSERT (ExternalSymbols != NULL);
1443 *NumExternalSymbols = NoExternalSymbols;
1444 if (NoExternalSymbols != 0) {
1445 *ExternalSymbols = &SymTab[Context->DySymtab->ExternalSymbolsIndex];
1446 }
1447 }
1448
1449 if (NumUndefinedSymbols != NULL) {
1450 ASSERT (UndefinedSymbols != NULL);
1451 *NumUndefinedSymbols = NoUndefinedSymbols;
1452 if (NoUndefinedSymbols != 0) {
1453 *UndefinedSymbols = &SymTab[Context->DySymtab->UndefinedSymbolsIndex];
1454 }
1455 }
1456
1457 return Context->Symtab->NumSymbols;
1458}
1459
1460UINT32
1463 )(
1464 IN OUT OC_MACHO_CONTEXT *Context,
1465 OUT CONST MACH_NLIST_X **SymbolTable
1466 ) {
1467 UINT32 Index;
1468
1469 ASSERT (Context != NULL);
1470 ASSERT (SymbolTable != NULL);
1471 MACH_ASSERT_X (Context);
1472
1473 if (!InternalRetrieveSymtabs (Context) || (Context->DySymtab == NULL)) {
1474 return 0;
1475 }
1476
1477 for (Index = 0; Index < Context->DySymtab->NumIndirectSymbols; ++Index) {
1478 if (
1479 !MACH_X (InternalSymbolIsSane)(Context, &(MACH_X (&Context->IndirectSymbolTable->Symbol))[Index])
1480 )
1481 {
1482 return 0;
1483 }
1484 }
1485
1486 *SymbolTable = MACH_X (&Context->IndirectSymbolTable->Symbol);
1487
1488 return Context->DySymtab->NumIndirectSymbols;
1489}
VENDOR_DEVICE_PATH Header
#define ARRAY_SIZE(Array)
Definition AppleMacEfi.h:34
#define MACH_LOAD_COMMAND_DYLD_INFO
#define MACH_LOAD_COMMAND_DYLIB_CODE_SIGN_DRS
#define MACH_LOAD_COMMAND_DYLD_INFO_ONLY
#define NEXT_MACH_LOAD_COMMAND(Command)
@ MachCpuTypeI386
@ MachCpuTypeX8664
#define MACH_LOAD_COMMAND_DYSYMTAB
#define MACH_LOAD_COMMAND_UNIX_THREAD
#define MACH_LOAD_COMMAND_SYMTAB
#define MACH_LOAD_COMMAND_FUNCTION_STARTS
UINT32 MACH_LOAD_COMMAND_TYPE
#define MACH_HEADER_SIGNATURE
the mach magic number
#define MACH_HEADER_64_SIGNATURE
the 64-bit mach magic number
#define MACH_LOAD_COMMAND_CODE_SIGNATURE
#define MACH_LOAD_COMMAND_DATA_IN_CODE
@ MachHeaderFileTypeExecute
@ MachHeaderFileTypeKextBundle
@ MachHeaderFileTypeFileSet
@ MachHeaderFileTypeObject
UINT8 Command[7]
Actual command for the Command Page.
Definition AppleNec.h:74
BOOLEAN InternalRetrieveSymtabs(IN OUT OC_MACHO_CONTEXT *Context)
Definition Header.c:508
VOID *MACH_X InternalMachoGetFilePointerByAddress(IN OUT OC_MACHO_CONTEXT *Context, IN MACH_UINT_X Address, OUT UINT32 *MaxSize OPTIONAL)
Definition HeaderX.h:240
MACH_LOAD_COMMAND *MACH_X InternalMachoGetNextCommand(IN OUT OC_MACHO_CONTEXT *Context, IN MACH_LOAD_COMMAND_TYPE LoadCommandType, IN CONST MACH_LOAD_COMMAND *LoadCommand OPTIONAL)
Definition HeaderX.h:196
MACH_SEGMENT_COMMAND_X *MACH_X MachoGetNextSegment(IN OUT OC_MACHO_CONTEXT *Context, IN CONST MACH_SEGMENT_COMMAND_X *Segment OPTIONAL)
Definition HeaderX.h:1188
STATIC BOOLEAN InternalSectionIsSane(IN OUT OC_MACHO_CONTEXT *Context, IN CONST MACH_SECTION_X *Section, IN CONST MACH_SEGMENT_COMMAND_X *Segment)
Definition HeaderX.h:27
UINT32 MACH_X InternalMachoExpandImage(IN OC_MACHO_CONTEXT *Context, IN BOOLEAN CalculateSizeOnly, OUT UINT8 *Destination, IN UINT32 DestinationSize, IN BOOLEAN Strip, OUT UINT64 *FileOffset OPTIONAL)
Definition HeaderX.h:273
MACH_SECTION_X *MACH_X MachoGetSectionByIndex(IN OUT OC_MACHO_CONTEXT *Context, IN UINT32 Index)
Definition HeaderX.h:1291
MACH_SEGMENT_COMMAND_X *MACH_X MachoGetSegmentByName(IN OUT OC_MACHO_CONTEXT *Context, IN CONST CHAR8 *SegmentName)
Definition HeaderX.h:1088
MACH_SECTION_X *MACH_X MachoGetSegmentSectionByName(IN OUT OC_MACHO_CONTEXT *Context, IN CONST CHAR8 *SegmentName, IN CONST CHAR8 *SectionName)
Definition HeaderX.h:1164
UINT32 MACH_X InternalMachoGetVmSize(IN OUT OC_MACHO_CONTEXT *Context)
Definition HeaderX.h:158
MACH_UINT_X MACH_X InternalMachoGetLastAddress(IN OUT OC_MACHO_CONTEXT *Context)
Definition HeaderX.h:1056
MACH_HEADER_X *MACH_X MachoGetMachHeader(IN OUT OC_MACHO_CONTEXT *Context)
Definition HeaderX.h:1043
UINT32 MACH_X MachoGetSymbolTable(IN OUT OC_MACHO_CONTEXT *Context, OUT CONST MACH_NLIST_X **SymbolTable, OUT CONST CHAR8 **StringTable OPTIONAL, OUT CONST MACH_NLIST_X **LocalSymbols OPTIONAL, OUT UINT32 *NumLocalSymbols OPTIONAL, OUT CONST MACH_NLIST_X **ExternalSymbols OPTIONAL, OUT UINT32 *NumExternalSymbols OPTIONAL, OUT CONST MACH_NLIST_X **UndefinedSymbols OPTIONAL, OUT UINT32 *NumUndefinedSymbols OPTIONAL)
Definition HeaderX.h:1380
BOOLEAN MACH_X InternalMachoMergeSegments(IN OUT OC_MACHO_CONTEXT *Context, IN CONST CHAR8 *Prefix)
Definition HeaderX.h:781
MACH_SECTION_X *MACH_X MachoGetSectionByName(IN OUT OC_MACHO_CONTEXT *Context, IN MACH_SEGMENT_COMMAND_X *Segment, IN CONST CHAR8 *SectionName)
Definition HeaderX.h:1123
STATIC VOID InternalStripLoadCommands(IN OUT MACH_HEADER_X *MachHeader)
Definition HeaderX.h:97
UINT32 MACH_X MachoGetIndirectSymbolTable(IN OUT OC_MACHO_CONTEXT *Context, OUT CONST MACH_NLIST_X **SymbolTable)
Definition HeaderX.h:1463
MACH_SECTION_X *MACH_X MachoGetNextSection(IN OUT OC_MACHO_CONTEXT *Context, IN MACH_SEGMENT_COMMAND_X *Segment, IN MACH_SECTION_X *Section OPTIONAL)
Definition HeaderX.h:1258
BOOLEAN MACH_X MachoInitializeContext(OUT OC_MACHO_CONTEXT *Context, IN VOID *FileData, IN UINT32 FileSize, IN UINT32 HeaderOffset, IN UINT32 InnerSize)
Definition HeaderX.h:897
MACH_SECTION_X *MACH_X MachoGetSectionByAddress(IN OUT OC_MACHO_CONTEXT *Context, IN MACH_UINT_X Address)
Definition HeaderX.h:1340
#define MACHO_LIB_32
Definition Macho32.c:18
#define MACH_ASSERT_X(a)
Definition MachoX.h:63
#define MACH_SEGMENT_COMMAND_X
Definition MachoX.h:57
#define MACH_UINT_X
Definition MachoX.h:54
#define MACH_X_TO_UINT32(a)
Definition MachoX.h:65
#define MACH_HEADER_X
Definition MachoX.h:55
#define MACH_SECTION_X
Definition MachoX.h:56
#define MACH_NLIST_X
Definition MachoX.h:58
#define MACH_X(a)
Definition MachoX.h:62
#define MACH_LOAD_COMMAND_SEGMENT_X
Definition MachoX.h:60
STATIC_ASSERT(BYTES_PER_PIXEL==sizeof(UINT32), "Non 4-byte pixels are unsupported!")
UINT32 MachoGetFileSize(IN OUT OC_MACHO_CONTEXT *Context)
Definition Header.c:77
EFI_STATUS FatFilterArchitecture64(IN OUT UINT8 **FileData, IN OUT UINT32 *FileSize)
Definition MachoFat.c:151
EFI_STATUS FatFilterArchitecture32(IN OUT UINT8 **FileData, IN OUT UINT32 *FileSize)
Definition MachoFat.c:142
#define MACHO_ALIGN(x)
Definition OcMachoLib.h:28
MACH_LOAD_COMMAND * MachoGetNextCommand(IN OUT OC_MACHO_CONTEXT *Context, IN MACH_LOAD_COMMAND_TYPE LoadCommandType, IN CONST MACH_LOAD_COMMAND *LoadCommand OPTIONAL)
Definition Header.c:110
BOOLEAN MACH_X InternalSymbolIsSane(IN OUT OC_MACHO_CONTEXT *Context, IN CONST MACH_NLIST_X *Symbol)
Definition SymbolsX.h:170
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
#define ASSERT(x)
Definition coder.h:55
UINT32 ModuleTableFileOffset
file offset to module table
UINT32 LocalRelocationsOffset
offset to local relocation entries
UINT32 StringsSize
string table size in bytes
MACH_LOAD_COMMAND_HDR_ UINT32 SymbolsOffset
symbol table offset
UINT32 NumSymbols
number of symbol table entries
UINT32 StringsOffset
string table offset