OpenCore  1.0.4
OpenCore Bootloader
Loading...
Searching...
No Matches
PrelinkedKext.c
Go to the documentation of this file.
1
15#include <Base.h>
16
17#include <Library/BaseLib.h>
18#include <Library/BaseMemoryLib.h>
19#include <Library/DebugLib.h>
20#include <Library/MemoryAllocationLib.h>
22#include <Library/OcMachoLib.h>
23#include <Library/OcStringLib.h>
24#include <Library/OcXmlLib.h>
25
26#include "PrelinkedInternal.h"
27
37STATIC
40 IN OUT PRELINKED_CONTEXT *Prelinked OPTIONAL,
41 IN XML_NODE *KextPlist,
42 IN CONST CHAR8 *Identifier OPTIONAL,
43 IN BOOLEAN Is32Bit
44 )
45{
46 PRELINKED_KEXT *NewKext;
47 UINT32 FieldIndex;
48 UINT32 FieldCount;
49 CONST CHAR8 *KextPlistKey;
50 XML_NODE *KextPlistValue;
51 CONST CHAR8 *KextIdentifier;
52 XML_NODE *BundleLibraries;
53 XML_NODE *BundleLibraries64;
54 CONST CHAR8 *CompatibleVersion;
55 UINT64 VirtualBase;
56 UINT64 VirtualKmod;
57 UINT64 SourceBase;
58 UINT64 SourceSize;
59 UINT32 InnerSize;
60 UINT64 CalculatedSourceSize;
61 UINT64 SourceEnd;
62 MACH_SEGMENT_COMMAND_ANY *BaseSegment;
63 UINT64 KxldState;
64 UINT64 KxldOffset;
65 UINT32 KxldStateSize;
66 UINT32 HeaderOffset;
67 BOOLEAN Found;
68 BOOLEAN HasExe;
69 BOOLEAN IsKpi;
70
71 KextIdentifier = NULL;
72 BundleLibraries = NULL;
73 BundleLibraries64 = NULL;
74 CompatibleVersion = NULL;
75 VirtualBase = 0;
76 VirtualKmod = 0;
77 SourceBase = 0;
78 SourceSize = 0;
79 KxldState = 0;
80 KxldStateSize = 0;
81
82 Found = Identifier == NULL;
83
84 //
85 // Prelinked bitness overrides parameter.
86 //
87 if (Prelinked != NULL) {
88 Is32Bit = Prelinked->Is32Bit;
89 }
90
91 FieldCount = PlistDictChildren (KextPlist);
92 for (FieldIndex = 0; FieldIndex < FieldCount; ++FieldIndex) {
93 KextPlistKey = PlistKeyValue (PlistDictChild (KextPlist, FieldIndex, &KextPlistValue));
94 if (KextPlistKey == NULL) {
95 continue;
96 }
97
98 if ((KextIdentifier == NULL) && (AsciiStrCmp (KextPlistKey, INFO_BUNDLE_IDENTIFIER_KEY) == 0)) {
99 KextIdentifier = XmlNodeContent (KextPlistValue);
100 if ((PlistNodeCast (KextPlistValue, PLIST_NODE_TYPE_STRING) == NULL) || (KextIdentifier == NULL)) {
101 break;
102 }
103
104 if (!Found && (AsciiStrCmp (KextIdentifier, Identifier) == 0)) {
105 Found = TRUE;
106 }
107 } else if ((BundleLibraries == NULL) && (AsciiStrCmp (KextPlistKey, INFO_BUNDLE_LIBRARIES_KEY) == 0)) {
108 if (PlistNodeCast (KextPlistValue, PLIST_NODE_TYPE_DICT) == NULL) {
109 break;
110 }
111
112 BundleLibraries = KextPlistValue;
113 } else if ((BundleLibraries64 == NULL) && (AsciiStrCmp (KextPlistKey, INFO_BUNDLE_LIBRARIES_64_KEY) == 0) && !Is32Bit) {
114 if (PlistNodeCast (KextPlistValue, PLIST_NODE_TYPE_DICT) == NULL) {
115 break;
116 }
117
118 BundleLibraries64 = BundleLibraries = KextPlistValue;
119 } else if ((CompatibleVersion == NULL) && (AsciiStrCmp (KextPlistKey, INFO_BUNDLE_COMPATIBLE_VERSION_KEY) == 0)) {
120 if (PlistNodeCast (KextPlistValue, PLIST_NODE_TYPE_STRING) == NULL) {
121 break;
122 }
123
124 CompatibleVersion = XmlNodeContent (KextPlistValue);
125 if (CompatibleVersion == NULL) {
126 break;
127 }
128 } else if ((Prelinked != NULL) && (VirtualBase == 0) && (AsciiStrCmp (KextPlistKey, PRELINK_INFO_EXECUTABLE_LOAD_ADDR_KEY) == 0)) {
129 if (!PlistIntegerValue (KextPlistValue, &VirtualBase, sizeof (VirtualBase), TRUE)) {
130 break;
131 }
132 } else if ((Prelinked != NULL) && (VirtualKmod == 0) && (AsciiStrCmp (KextPlistKey, PRELINK_INFO_KMOD_INFO_KEY) == 0)) {
133 if (!PlistIntegerValue (KextPlistValue, &VirtualKmod, sizeof (VirtualKmod), TRUE)) {
134 break;
135 }
136 } else if ((Prelinked != NULL) && (SourceBase == 0) && (AsciiStrCmp (KextPlistKey, PRELINK_INFO_EXECUTABLE_SOURCE_ADDR_KEY) == 0)) {
137 if (!PlistIntegerValue (KextPlistValue, &SourceBase, sizeof (SourceBase), TRUE)) {
138 break;
139 }
140 } else if ((Prelinked != NULL) && (SourceSize == 0) && (AsciiStrCmp (KextPlistKey, PRELINK_INFO_EXECUTABLE_SIZE_KEY) == 0)) {
141 if (!PlistIntegerValue (KextPlistValue, &SourceSize, sizeof (SourceSize), TRUE)) {
142 break;
143 }
144 } else if ((Prelinked != NULL) && (KxldState == 0) && (AsciiStrCmp (KextPlistKey, PRELINK_INFO_LINK_STATE_ADDR_KEY) == 0)) {
145 if (!PlistIntegerValue (KextPlistValue, &KxldState, sizeof (KxldState), TRUE)) {
146 break;
147 }
148 } else if ((Prelinked != NULL) && (KxldStateSize == 0) && (AsciiStrCmp (KextPlistKey, PRELINK_INFO_LINK_STATE_SIZE_KEY) == 0)) {
149 if (!PlistIntegerValue (KextPlistValue, &KxldStateSize, sizeof (KxldStateSize), TRUE)) {
150 break;
151 }
152 }
153
154 if ( (KextIdentifier != NULL)
155 && (((BundleLibraries64 != NULL) && !Is32Bit) || ((BundleLibraries != NULL) && Is32Bit))
156 && (CompatibleVersion != NULL)
157 && ( (Prelinked == NULL)
158 || ( (Prelinked != NULL)
159 && (VirtualBase != 0)
160 && (VirtualKmod != 0)
161 && (SourceBase != 0)
162 && (SourceSize != 0)
163 && (KxldState != 0)
164 && (KxldStateSize != 0))))
165 {
166 break;
167 }
168 }
169
170 //
171 // BundleLibraries, CompatibleVersion, and KmodInfo are optional and thus not checked.
172 //
173 if (!Found || (KextIdentifier == NULL) || (SourceBase < VirtualBase)) {
174 return NULL;
175 }
176
177 //
178 // KPIs on 10.6.8 may not have executables, but for all other types they are required.
179 //
180 if (Prelinked != NULL) {
181 HasExe = VirtualBase != 0 && SourceBase != 0 && SourceSize != 0 && SourceSize <= MAX_UINT32;
182 IsKpi = VirtualBase == 0 && SourceBase == 0 && SourceSize == 0
183 && KxldState != 0 && KxldStateSize != 0 && !Prelinked->IsKernelCollection;
184 if (!IsKpi && !HasExe) {
185 return NULL;
186 }
187 }
188
189 if ((Prelinked != NULL) && Prelinked->IsKernelCollection) {
190 CalculatedSourceSize = KcGetKextSize (Prelinked, SourceBase);
191 if ((CalculatedSourceSize < MAX_UINT32) && (CalculatedSourceSize > SourceSize)) {
192 DEBUG ((
193 DEBUG_INFO,
194 "OCAK: Patching invalid size %Lx with %Lx for %a\n",
195 SourceSize,
196 CalculatedSourceSize,
197 KextIdentifier
198 ));
199 SourceSize = CalculatedSourceSize;
200 }
201 }
202
203 if ((Prelinked != NULL) && HasExe) {
204 if (Prelinked->IsKernelCollection) {
205 BaseSegment = (MACH_SEGMENT_COMMAND_ANY *)Prelinked->RegionSegment;
206 } else {
207 BaseSegment = Prelinked->PrelinkedTextSegment;
208 }
209
210 SourceBase -= Prelinked->Is32Bit ? BaseSegment->Segment32.VirtualAddress : BaseSegment->Segment64.VirtualAddress;
211 if ( BaseOverflowAddU64 (SourceBase, Prelinked->Is32Bit ? BaseSegment->Segment32.FileOffset : BaseSegment->Segment64.FileOffset, &SourceBase)
212 || BaseOverflowAddU64 (SourceBase, SourceSize, &SourceEnd)
213 || (SourceEnd > Prelinked->PrelinkedSize))
214 {
215 return NULL;
216 }
217
218 HeaderOffset = 0;
219 InnerSize = (UINT32)SourceSize;
220 if (Prelinked->IsKernelCollection) {
221 HeaderOffset = (UINT32)SourceBase;
222
223 //
224 // The Mach-O image is the entire Kernel Collection image. This is because
225 // as of macOS 13 Developer Beta 3, the inner kernel Mach-O references
226 // segments that preceed it.
227 //
228 SourceBase = 0;
229 SourceSize = Prelinked->PrelinkedSize;
230 }
231 }
232
233 //
234 // Important to ZeroPool for dependency cleanup.
235 //
236 NewKext = AllocateZeroPool (sizeof (*NewKext));
237 if (NewKext == NULL) {
238 return NULL;
239 }
240
241 if ( (Prelinked != NULL)
242 && HasExe
243 && !MachoInitializeContext (&NewKext->Context.MachContext, &Prelinked->Prelinked[SourceBase], (UINT32)SourceSize, HeaderOffset, InnerSize, Prelinked->Is32Bit))
244 {
245 FreePool (NewKext);
246 return NULL;
247 }
248
250 NewKext->Identifier = KextIdentifier;
251 NewKext->BundleLibraries = BundleLibraries;
252 NewKext->CompatibleVersion = CompatibleVersion;
253 NewKext->Context.VirtualBase = VirtualBase;
254 NewKext->Context.VirtualKmod = VirtualKmod;
255 NewKext->Context.IsKernelCollection = Prelinked != NULL ? Prelinked->IsKernelCollection : FALSE;
256 NewKext->Context.Is32Bit = Is32Bit;
257
258 //
259 // Provide pointer to 10.6.8 KXLD state.
260 //
261 if ( (Prelinked != NULL)
262 && (KxldState != 0)
263 && (KxldStateSize != 0)
264 && (Prelinked->PrelinkedStateKextsAddress != 0)
265 && (Prelinked->PrelinkedStateKextsAddress <= KxldState)
266 && (Prelinked->PrelinkedStateKextsSize >= KxldStateSize))
267 {
268 KxldOffset = KxldState - Prelinked->PrelinkedStateKextsAddress;
269 if (KxldOffset <= Prelinked->PrelinkedStateKextsSize - KxldStateSize) {
270 NewKext->Context.KxldState = (UINT8 *)Prelinked->PrelinkedStateKexts + KxldOffset;
271 NewKext->Context.KxldStateSize = KxldStateSize;
272 }
273 }
274
275 DEBUG ((
276 DEBUG_VERBOSE,
277 "OCAK: %a got KXLD %p %u\n",
278 NewKext->Identifier,
279 NewKext->Context.KxldState,
280 NewKext->Context.KxldStateSize
281 ));
282
283 return NewKext;
284}
285
286STATIC
287VOID
289 IN OUT PRELINKED_KEXT *Kext,
290 IN PRELINKED_CONTEXT *Context
291 )
292{
293 //
294 // Prefer KXLD state when available.
295 //
296 if (Kext->Context.KxldState != NULL) {
297 return;
298 }
299
300 if ((Kext->LinkEditSegment == NULL) && (Kext->NumberOfSymbols == 0)) {
301 if (AsciiStrCmp (Kext->Identifier, PRELINK_KERNEL_IDENTIFIER) == 0) {
302 Kext->LinkEditSegment = Context->LinkEditSegment;
303 } else {
304 Kext->LinkEditSegment = MachoGetSegmentByName (
305 &Kext->Context.MachContext,
306 "__LINKEDIT"
307 );
308 }
309
310 DEBUG ((
311 DEBUG_VERBOSE,
312 "OCAK: Requesting __LINKEDIT for %a - %p at %p\n",
313 Kext->Identifier,
314 Kext->LinkEditSegment,
315 (UINT8 *)MachoGetMachHeader (&Kext->Context.MachContext) - Context->Prelinked
316 ));
317 }
318
319 if ((Kext->SymbolTable == NULL) && (Kext->NumberOfSymbols == 0)) {
320 Kext->NumberOfSymbols = MachoGetSymbolTable (
321 &Kext->Context.MachContext,
322 &Kext->SymbolTable,
323 &Kext->StringTable,
324 NULL,
325 NULL,
326 NULL,
327 NULL,
328 NULL,
329 NULL
330 );
331 DEBUG ((
332 DEBUG_VERBOSE,
333 "OCAK: Requesting SymbolTable for %a - %u\n",
334 Kext->Identifier,
335 Kext->NumberOfSymbols
336 ));
337 }
338}
339
340STATIC
341EFI_STATUS
343 IN OUT PRELINKED_KEXT *Kext,
344 IN PRELINKED_CONTEXT *Context
345 )
346{
347 CONST MACH_HEADER_ANY *MachHeader;
348 BOOLEAN ResolveSymbols;
349 PRELINKED_KEXT_SYMBOL *SymbolTable;
350 PRELINKED_KEXT_SYMBOL *WalkerBottom;
351 PRELINKED_KEXT_SYMBOL *WalkerTop;
352 UINT32 NumCxxSymbols;
353 UINT32 NumDiscardedSyms;
354 UINT32 Index;
355 CONST MACH_NLIST_ANY *Symbol;
356 UINT8 SymbolType;
357 MACH_NLIST_ANY SymbolScratch;
358 CONST PRELINKED_KEXT_SYMBOL *ResolvedSymbol;
359 CONST CHAR8 *Name;
360 BOOLEAN Result;
361
362 if (Kext->LinkedSymbolTable != NULL) {
363 return EFI_SUCCESS;
364 }
365
366 SymbolTable = AllocatePool (Kext->NumberOfSymbols * sizeof (*SymbolTable));
367 if (SymbolTable == NULL) {
368 return EFI_OUT_OF_RESOURCES;
369 }
370
371 MachHeader = MachoGetMachHeader (&Kext->Context.MachContext);
372 ASSERT (MachHeader != NULL);
373 //
374 // KPIs declare undefined and indirect symbols even in prelinkedkernel.
375 //
376 ResolveSymbols = (((Context->Is32Bit ? MachHeader->Header32.Flags : MachHeader->Header64.Flags) & MACH_HEADER_FLAG_NO_UNDEFINED_REFERENCES) == 0);
377 NumDiscardedSyms = 0;
378
379 WalkerBottom = &SymbolTable[0];
380 WalkerTop = &SymbolTable[Kext->NumberOfSymbols - 1];
381
382 NumCxxSymbols = 0;
383
384 for (Index = 0; Index < Kext->NumberOfSymbols; ++Index) {
385 if (Context->Is32Bit) {
386 Symbol = (MACH_NLIST_ANY *)&(&Kext->SymbolTable->Symbol32)[Index];
387 } else {
388 Symbol = (MACH_NLIST_ANY *)&(&Kext->SymbolTable->Symbol64)[Index];
389 }
390
391 SymbolType = Context->Is32Bit ? Symbol->Symbol32.Type : Symbol->Symbol64.Type;
392 if ((SymbolType & MACH_N_TYPE_STAB) != 0) {
393 ++NumDiscardedSyms;
394 continue;
395 }
396
397 //
398 // Undefined symbols will be resolved via the KPI's dependencies and
399 // hence do not need to be included (again).
400 //
401 if ((SymbolType & MACH_N_TYPE_TYPE) == MACH_N_TYPE_UNDF) {
402 ++NumDiscardedSyms;
403 continue;
404 }
405
406 Name = MachoGetSymbolName (&Kext->Context.MachContext, Symbol);
407 Result = MachoSymbolNameIsCxx (Name);
408
409 if (ResolveSymbols) {
410 //
411 // Resolve indirect symbols via the KPI's dependencies (kernel).
412 //
413 if ((SymbolType & MACH_N_TYPE_TYPE) == MACH_N_TYPE_INDR) {
414 Name = MachoGetIndirectSymbolName (&Kext->Context.MachContext, Symbol);
415 if (Name == NULL) {
416 FreePool (SymbolTable);
417 return EFI_LOAD_ERROR;
418 }
419
420 CopyMem (&SymbolScratch, Symbol, Context->Is32Bit ? sizeof (SymbolScratch.Symbol32) : sizeof (SymbolScratch.Symbol64));
421 ResolvedSymbol = InternalOcGetSymbolName (
422 Context,
423 Kext,
424 Name,
426 );
427 if (ResolvedSymbol == NULL) {
428 FreePool (SymbolTable);
429 return EFI_NOT_FOUND;
430 }
431
432 if (Context->Is32Bit) {
433 SymbolScratch.Symbol32.Value = (UINT32)ResolvedSymbol->Value;
434 } else {
435 SymbolScratch.Symbol64.Value = ResolvedSymbol->Value;
436 }
437
438 Symbol = &SymbolScratch;
439 }
440 }
441
442 if (!Result) {
443 WalkerBottom->Value = Context->Is32Bit ? Symbol->Symbol32.Value : Symbol->Symbol64.Value;
444 WalkerBottom->Name = Kext->StringTable + (Context->Is32Bit ?
445 Symbol->Symbol32.UnifiedName.StringIndex : Symbol->Symbol64.UnifiedName.StringIndex);
446 WalkerBottom->Length = (UINT32)AsciiStrLen (WalkerBottom->Name);
447 ++WalkerBottom;
448 } else {
449 WalkerTop->Value = Context->Is32Bit ? Symbol->Symbol32.Value : Symbol->Symbol64.Value;
450 WalkerTop->Name = Kext->StringTable + (Context->Is32Bit ?
451 Symbol->Symbol32.UnifiedName.StringIndex : Symbol->Symbol64.UnifiedName.StringIndex);
452 WalkerTop->Length = (UINT32)AsciiStrLen (WalkerTop->Name);
453 --WalkerTop;
454
455 ++NumCxxSymbols;
456 }
457 }
458
459 //
460 // Move the C++ symbols to the actual end of the non-C++ symbols as undefined
461 // symbols got discarded.
462 //
463 if (NumDiscardedSyms > 0) {
464 CopyMem (
465 &SymbolTable[Kext->NumberOfSymbols - NumCxxSymbols - NumDiscardedSyms],
466 &SymbolTable[Kext->NumberOfSymbols - NumCxxSymbols],
467 (NumCxxSymbols * sizeof (*SymbolTable))
468 );
469 Kext->NumberOfSymbols -= NumDiscardedSyms;
470 }
471
472 Kext->NumberOfCxxSymbols = NumCxxSymbols;
473 Kext->LinkedSymbolTable = SymbolTable;
474
475 return EFI_SUCCESS;
476}
477
478STATIC
479EFI_STATUS
481 IN OUT PRELINKED_KEXT *Kext,
482 IN PRELINKED_CONTEXT *Context
483 )
484{
486 UINT32 MaxSize;
487 BOOLEAN Result;
488 UINT32 NumVtables;
489 UINT32 NumEntries;
490 UINT32 NumEntriesTemp;
491 UINT32 Index;
492 UINT32 VtableMaxSize;
493 UINT32 ResultingSize;
494 CONST VOID *VtableData;
495 PRELINKED_VTABLE *LinkedVtables;
496
497 if (Kext->LinkedVtables != NULL) {
498 return EFI_SUCCESS;
499 }
500
501 VtableLookups = Context->LinkBuffer;
502 MaxSize = Context->LinkBufferSize;
503
505 Kext,
506 MaxSize,
507 &NumVtables,
508 VtableLookups
509 );
510 if (!Result) {
511 return EFI_UNSUPPORTED;
512 }
513
514 NumEntries = 0;
515
516 for (Index = 0; Index < NumVtables; ++Index) {
517 //
518 // NOTE: KXLD locates the section via MACH_NLIST_64.Section. However, as we
519 // need to abort anyway when the value is out of its bounds, we can
520 // just locate it by address in the first place.
521 //
522 VtableData = MachoGetFilePointerByAddress (
523 &Kext->Context.MachContext,
524 VtableLookups[Index].Vtable.Value,
525 &VtableMaxSize
526 );
527 if ((VtableData == NULL) || (Context->Is32Bit ? !BASE_TYPE_ALIGNED (UINT32, VtableData) : !BASE_TYPE_ALIGNED (UINT64, VtableData))) {
528 return EFI_UNSUPPORTED;
529 }
530
531 Result = InternalGetVtableEntries (
532 Context->Is32Bit,
533 VtableData,
534 VtableMaxSize,
535 &NumEntriesTemp
536 );
537 if (!Result) {
538 return EFI_UNSUPPORTED;
539 }
540
541 VtableLookups[Index].Vtable.Data = VtableData;
542
543 if (BaseOverflowAddU32 (NumEntries, NumEntriesTemp, &NumEntries)) {
544 return EFI_OUT_OF_RESOURCES;
545 }
546 }
547
548 if ( BaseOverflowMulU32 (NumVtables, sizeof (*LinkedVtables), &ResultingSize)
549 || BaseOverflowMulAddU32 (NumEntries, sizeof (*LinkedVtables->Entries), ResultingSize, &ResultingSize))
550 {
551 return EFI_OUT_OF_RESOURCES;
552 }
553
554 LinkedVtables = AllocatePool (ResultingSize);
555 if (LinkedVtables == NULL) {
556 return EFI_OUT_OF_RESOURCES;
557 }
558
560 Context,
561 Kext,
562 NumVtables,
563 VtableLookups,
564 LinkedVtables
565 );
566
567 Kext->NumberOfVtables = NumVtables;
568 Kext->LinkedVtables = LinkedVtables;
569
570 return EFI_SUCCESS;
571}
572
573STATIC
574UINT32
576 IN OUT PRELINKED_KEXT *Kext
577 )
578{
579 UINT32 Size;
580
581 //
582 // LinkBuffer must be able to hold all symbols and for KEXTs to be prelinked
583 // also the __LINKEDIT segment (however not both simultaneously/separately).
584 //
585 Size = Kext->NumberOfSymbols * (Kext->Context.Is32Bit ? sizeof (MACH_NLIST) : sizeof (MACH_NLIST_64));
586
587 if (Kext->LinkEditSegment != NULL) {
588 Size = MAX (
589 (UINT32)(Kext->Context.Is32Bit ?
590 Kext->LinkEditSegment->Segment32.FileSize : Kext->LinkEditSegment->Segment64.FileSize),
591 Size
592 );
593 }
594
595 return Size;
596}
597
598STATIC
599EFI_STATUS
601 IN OUT PRELINKED_KEXT *Kext,
602 IN OUT PRELINKED_CONTEXT *Context
603 )
604{
605 UINT32 BufferSize;
606
607 ASSERT (Kext != NULL);
608 ASSERT (Context != NULL);
609
610 if (Context->LinkBuffer == NULL) {
611 //
612 // Context->LinkBufferSize was updated recursively during initial dependency
613 // walk to save reallocations.
614 //
615 ASSERT (Context->LinkBufferSize >= InternalGetLinkBufferSize (Kext));
616
617 Context->LinkBuffer = AllocatePool (Context->LinkBufferSize);
618 if (Context->LinkBuffer == NULL) {
619 return EFI_OUT_OF_RESOURCES;
620 }
621 } else {
622 BufferSize = InternalGetLinkBufferSize (Kext);
623
624 if (Context->LinkBufferSize < BufferSize) {
625 FreePool (Context->LinkBuffer);
626
627 Context->LinkBufferSize = BufferSize;
628 Context->LinkBuffer = AllocatePool (Context->LinkBufferSize);
629 if (Context->LinkBuffer == NULL) {
630 return EFI_OUT_OF_RESOURCES;
631 }
632 }
633 }
634
635 return EFI_SUCCESS;
636}
637
638STATIC
639EFI_STATUS
641 IN OUT PRELINKED_KEXT *Kext,
642 IN OUT PRELINKED_CONTEXT *Context,
643 IN UINT32 DependencyIndex,
644 IN OUT PRELINKED_KEXT *DependencyKext
645 )
646{
647 EFI_STATUS Status;
648
649 if (DependencyIndex >= ARRAY_SIZE (Kext->Dependencies)) {
650 DEBUG ((DEBUG_INFO, "OCAK: Kext %a has more than %u or more dependencies!", Kext->Identifier, DependencyIndex));
651 return EFI_OUT_OF_RESOURCES;
652 }
653
654 Status = InternalScanPrelinkedKext (DependencyKext, Context, TRUE);
655 if (EFI_ERROR (Status)) {
656 return Status;
657 }
658
659 Kext->Dependencies[DependencyIndex] = DependencyKext;
660
661 return EFI_SUCCESS;
662}
663
666 IN OC_MACHO_CONTEXT *Context,
667 IN XML_NODE *KextPlist
668 )
669{
670 PRELINKED_KEXT *NewKext;
671
672 NewKext = InternalCreatePrelinkedKext (NULL, KextPlist, NULL, Context->Is32Bit);
673 if (NewKext == NULL) {
674 return NULL;
675 }
676
677 CopyMem (&NewKext->Context.MachContext, Context, sizeof (NewKext->Context.MachContext));
678 return NewKext;
679}
680
681VOID
683 IN PRELINKED_KEXT *Kext
684 )
685{
686 if (Kext->LinkedSymbolTable != NULL) {
687 FreePool (Kext->LinkedSymbolTable);
688 Kext->LinkedSymbolTable = NULL;
689 }
690
691 if (Kext->LinkedVtables != NULL) {
692 FreePool (Kext->LinkedVtables);
693 Kext->LinkedVtables = NULL;
694 }
695
696 FreePool (Kext);
697}
698
701 IN OUT PRELINKED_CONTEXT *Prelinked,
702 IN CONST CHAR8 *Identifier
703 )
704{
705 PRELINKED_KEXT *NewKext;
706 LIST_ENTRY *Kext;
707 UINT32 Index;
708 UINT32 KextCount;
709 XML_NODE *KextPlist;
710
711 //
712 // Find cached entry if any.
713 //
714 Kext = GetFirstNode (&Prelinked->PrelinkedKexts);
715 while (!IsNull (&Prelinked->PrelinkedKexts, Kext)) {
716 if (AsciiStrCmp (Identifier, GET_PRELINKED_KEXT_FROM_LINK (Kext)->Identifier) == 0) {
717 return GET_PRELINKED_KEXT_FROM_LINK (Kext);
718 }
719
720 Kext = GetNextNode (&Prelinked->PrelinkedKexts, Kext);
721 }
722
723 //
724 // Try with real entry.
725 //
726 NewKext = NULL;
727 KextCount = XmlNodeChildren (Prelinked->KextList);
728 for (Index = 0; Index < KextCount; ++Index) {
729 KextPlist = PlistNodeCast (XmlNodeChild (Prelinked->KextList, Index), PLIST_NODE_TYPE_DICT);
730
731 if (KextPlist == NULL) {
732 continue;
733 }
734
735 NewKext = InternalCreatePrelinkedKext (Prelinked, KextPlist, Identifier, Prelinked->Is32Bit);
736 if (NewKext != NULL) {
737 break;
738 }
739 }
740
741 if (NewKext == NULL) {
742 return NULL;
743 }
744
745 InsertTailList (&Prelinked->PrelinkedKexts, &NewKext->Link);
746
747 return NewKext;
748}
749
750EFI_STATUS
752 IN OUT PRELINKED_CONTEXT *Prelinked,
753 IN CONST CHAR8 *Identifier
754 )
755{
756 LIST_ENTRY *Link;
757 BOOLEAN Found;
758 PRELINKED_KEXT *Kext;
759
760 //
761 // Find kext identifier.
762 //
763 Found = FALSE;
764 Link = GetFirstNode (&Prelinked->PrelinkedKexts);
765 Kext = NULL;
766 while (!IsNull (&Prelinked->PrelinkedKexts, Link)) {
767 Kext = GET_PRELINKED_KEXT_FROM_LINK (Link);
768
769 if (AsciiStrCmp (Identifier, Kext->Identifier) == 0) {
770 Found = TRUE;
771 break;
772 }
773
774 Link = GetNextNode (&Prelinked->PrelinkedKexts, Link);
775 }
776
777 if (!Found) {
778 DEBUG ((DEBUG_INFO, "OCAK: Found no kext to drop\n"));
779 return EFI_NOT_FOUND;
780 }
781
782 DEBUG ((
783 DEBUG_INFO,
784 "OCAK: Found kext %a (%p) from link %p to drop\n",
785 Kext->Identifier,
786 Kext,
787 Link
788 ));
789
790 RemoveEntryList (Link);
792
793 return EFI_SUCCESS;
794}
795
798 IN OUT PRELINKED_CONTEXT *Prelinked
799 )
800{
801 LIST_ENTRY *Kext;
802 PRELINKED_KEXT *NewKext;
804
805 UINT64 VirtualAddress;
806 UINT64 FileOffset;
807 UINT64 KernelSize;
808 UINT64 KextsSize;
809 UINT64 KernelOffset;
810 UINT64 KextsOffset;
811
812 //
813 // First entry is prelinked kernel.
814 //
815 Kext = GetFirstNode (&Prelinked->PrelinkedKexts);
816 if (!IsNull (&Prelinked->PrelinkedKexts, Kext)) {
817 return GET_PRELINKED_KEXT_FROM_LINK (Kext);
818 }
819
820 NewKext = AllocateZeroPool (sizeof (*NewKext));
821 if (NewKext == NULL) {
822 return NULL;
823 }
824
825 ASSERT (Prelinked->Prelinked != NULL);
826 ASSERT (Prelinked->PrelinkedSize > 0);
827
828 CopyMem (
829 &NewKext->Context.MachContext,
830 &Prelinked->PrelinkedMachContext,
831 sizeof (NewKext->Context.MachContext)
832 );
833
834 Segment = MachoGetSegmentByName (
835 &NewKext->Context.MachContext,
836 "__TEXT"
837 );
838 if (Segment == NULL) {
839 FreePool (NewKext);
840 return NULL;
841 }
842
843 VirtualAddress = Prelinked->Is32Bit ? Segment->Segment32.VirtualAddress : Segment->Segment64.VirtualAddress;
844 FileOffset = Prelinked->Is32Bit ? Segment->Segment32.FileOffset : Segment->Segment64.FileOffset;
845
846 if (VirtualAddress < FileOffset) {
847 FreePool (NewKext);
848 return NULL;
849 }
850
853 NewKext->BundleLibraries = NULL;
854 NewKext->CompatibleVersion = "0";
855 NewKext->Context.Is32Bit = Prelinked->Is32Bit;
856 NewKext->Context.VirtualBase = VirtualAddress - FileOffset;
857 NewKext->Context.VirtualKmod = 0;
858 NewKext->Context.IsKernelCollection = Prelinked->IsKernelCollection;
859
860 if (!Prelinked->IsKernelCollection) {
861 //
862 // Find optional __PRELINK_STATE segment, present in 10.6.8
863 //
864 Prelinked->PrelinkedStateSegment = MachoGetSegmentByName (
865 &Prelinked->PrelinkedMachContext,
867 );
868
869 if (Prelinked->PrelinkedStateSegment != NULL) {
870 Prelinked->PrelinkedStateSectionKernel = MachoGetSectionByName (
871 &Prelinked->PrelinkedMachContext,
872 Prelinked->PrelinkedStateSegment,
874 );
875 Prelinked->PrelinkedStateSectionKexts = MachoGetSectionByName (
876 &Prelinked->PrelinkedMachContext,
877 Prelinked->PrelinkedStateSegment,
879 );
880
881 if ( (Prelinked->PrelinkedStateSectionKernel != NULL)
882 && (Prelinked->PrelinkedStateSectionKexts != NULL))
883 {
884 KernelSize = Prelinked->Is32Bit ?
885 Prelinked->PrelinkedStateSectionKernel->Section32.Size :
886 Prelinked->PrelinkedStateSectionKernel->Section64.Size;
887 KextsSize = Prelinked->Is32Bit ?
888 Prelinked->PrelinkedStateSectionKexts->Section32.Size :
889 Prelinked->PrelinkedStateSectionKexts->Section64.Size;
890 KernelOffset = Prelinked->Is32Bit ?
891 Prelinked->PrelinkedStateSectionKernel->Section32.Offset :
892 Prelinked->PrelinkedStateSectionKernel->Section64.Offset;
893 KextsOffset = Prelinked->Is32Bit ?
894 Prelinked->PrelinkedStateSectionKexts->Section32.Offset :
895 Prelinked->PrelinkedStateSectionKexts->Section64.Offset;
896
897 if ((KernelSize > 0) && (KextsSize > 0)) {
898 Prelinked->PrelinkedStateKernelSize = (UINT32)KernelSize;
899 Prelinked->PrelinkedStateKextsSize = (UINT32)KextsSize;
900 Prelinked->PrelinkedStateKernel = AllocateCopyPool (
901 Prelinked->PrelinkedStateKernelSize,
902 &Prelinked->Prelinked[KernelOffset]
903 );
904 Prelinked->PrelinkedStateKexts = AllocateCopyPool (
905 Prelinked->PrelinkedStateKextsSize,
906 &Prelinked->Prelinked[KextsOffset]
907 );
908 if ( (Prelinked->PrelinkedStateKernel != NULL)
909 && (Prelinked->PrelinkedStateKexts != NULL))
910 {
911 Prelinked->PrelinkedStateKextsAddress = Prelinked->Is32Bit ?
912 Prelinked->PrelinkedStateSectionKexts->Section32.Address :
913 Prelinked->PrelinkedStateSectionKexts->Section64.Address;
914 NewKext->Context.KxldState = Prelinked->PrelinkedStateKernel;
915 NewKext->Context.KxldStateSize = Prelinked->PrelinkedStateKernelSize;
916 } else {
917 DEBUG ((
918 DEBUG_INFO,
919 "OCAK: Ignoring unused PK state __kernel %p __kexts %p\n",
920 Prelinked->PrelinkedStateSectionKernel,
921 Prelinked->PrelinkedStateSectionKexts
922 ));
923 if (Prelinked->PrelinkedStateKernel != NULL) {
924 FreePool (Prelinked->PrelinkedStateKernel);
925 }
926
927 if (Prelinked->PrelinkedStateKexts != NULL) {
928 FreePool (Prelinked->PrelinkedStateKexts);
929 }
930
931 Prelinked->PrelinkedStateSectionKernel = NULL;
932 Prelinked->PrelinkedStateSectionKexts = NULL;
933 Prelinked->PrelinkedStateSegment = NULL;
934 }
935 }
936 }
937 }
938 }
939
940 InsertTailList (&Prelinked->PrelinkedKexts, &NewKext->Link);
941
942 return NewKext;
943}
944
947 IN CONST CHAR8 *DependencyId,
948 IN OUT PRELINKED_CONTEXT *Context
949 )
950{
951 PRELINKED_KEXT *DependencyKext;
952
953 ASSERT (DependencyId != NULL);
954 ASSERT (Context != NULL);
955
956 DependencyKext = NULL;
957 //
958 // Some kexts, notably VoodooPS2 forks, link against IOHIDSystem.kext, which is a plist-only
959 // dummy, macOS does not add to the prelinkedkernel. This cannot succeed as /S/L/E directory
960 // is not accessible (and can be encrypted). Normally kext's Info.plist is to be fixed, but
961 // we also put a hack here to let some common kexts work.
962 //
963 if (AsciiStrCmp (DependencyId, "com.apple.iokit.IOHIDSystem") == 0) {
964 DependencyKext = InternalCachedPrelinkedKext (Context, "com.apple.iokit.IOHIDFamily");
965 DEBUG ((
966 DEBUG_WARN,
967 "Dependency %a fallback to %a %a. Please fix your kext!\n",
968 DependencyId,
969 "com.apple.iokit.IOHIDFamily",
970 DependencyKext != NULL ? "succeeded" : "failed"
971 ));
972 }
973
974 return DependencyKext;
975}
976
977EFI_STATUS
979 IN OUT PRELINKED_KEXT *Kext,
980 IN OUT PRELINKED_CONTEXT *Context,
981 IN BOOLEAN Dependency
982 )
983{
984 EFI_STATUS Status;
985 UINT32 FieldCount;
986 UINT32 FieldIndex;
987 UINT32 DependencyIndex;
988 CONST CHAR8 *DependencyId;
989 PRELINKED_KEXT *DependencyKext;
990
991 //
992 // __LINKEDIT may validly not be present, as seen for 10.7.5's
993 // com.apple.kpi.unsupported.
994 //
996 //
997 // Find the biggest LinkBuffer size down the first dependency tree walk to
998 // possibly save a few re-allocations.
999 //
1000 if (Context->LinkBuffer == NULL) {
1001 Context->LinkBufferSize = MAX (
1003 Context->LinkBufferSize
1004 );
1005 }
1006
1007 //
1008 // Always add kernel dependency.
1009 //
1010 DependencyKext = InternalCachedPrelinkedKernel (Context);
1011 if (DependencyKext == NULL) {
1012 return EFI_NOT_FOUND;
1013 }
1014
1015 if (DependencyKext != Kext) {
1016 Status = InternalInsertPrelinkedKextDependency (Kext, Context, 0, DependencyKext);
1017 if (EFI_ERROR (Status)) {
1018 return Status;
1019 }
1020 }
1021
1022 if (Kext->BundleLibraries != NULL) {
1023 DependencyIndex = 1;
1024 FieldCount = PlistDictChildren (Kext->BundleLibraries);
1025
1026 for (FieldIndex = 0; FieldIndex < FieldCount; ++FieldIndex) {
1027 DependencyId = PlistKeyValue (PlistDictChild (Kext->BundleLibraries, FieldIndex, NULL));
1028 if (DependencyId == NULL) {
1029 continue;
1030 }
1031
1032 DEBUG ((DEBUG_VERBOSE, "OCAK: Checking dependency %a for kext %a\n", DependencyId, Kext->Identifier));
1033
1034 //
1035 // In 11.0 KPIs just like plist-only kexts are not present in memory and their
1036 // _PrelinkExecutableLoadAddr / _PrelinkExecutableSourceAddr values equal to MAX_INT64.
1037 // Skip them early to improve performance.
1038 //
1039 if ( Context->IsKernelCollection
1040 && (AsciiStrnCmp (DependencyId, "com.apple.kpi.", L_STR_LEN ("com.apple.kpi.")) == 0))
1041 {
1042 DEBUG ((DEBUG_VERBOSE, "OCAK: Ignoring KPI %a for kext %a in KC/state mode\n", DependencyId, Kext->Identifier));
1043 continue;
1044 }
1045
1046 //
1047 // We still need to add KPI dependencies, as they may have indirect symbols,
1048 // which are not present in kernel (e.g. _IOLockLock).
1049 //
1050 DependencyKext = InternalCachedPrelinkedKext (Context, DependencyId);
1051 if (DependencyKext == NULL) {
1052 DEBUG ((DEBUG_INFO, "OCAK: Dependency %a was not found for kext %a\n", DependencyId, Kext->Identifier));
1053
1054 DependencyKext = InternalGetQuirkDependencyKext (DependencyId, Context);
1055 if (DependencyKext == NULL) {
1056 //
1057 // Skip missing dependencies. PLIST-only dependencies, such as used
1058 // in macOS Catalina, will not be found in prelinkedkernel and are
1059 // assumed to be safe to ignore. Any actual problems will be found
1060 // during linking.
1061 //
1062 continue;
1063 }
1064 }
1065
1066 Status = InternalInsertPrelinkedKextDependency (Kext, Context, DependencyIndex, DependencyKext);
1067 if (EFI_ERROR (Status)) {
1068 return Status;
1069 }
1070
1071 ++DependencyIndex;
1072 }
1073
1074 //
1075 // We do not need this anymore.
1076 // Additionally it may point to invalid memory on prelinked kexts.
1077 //
1078 Kext->BundleLibraries = NULL;
1079 }
1080
1081 //
1082 // Extend or allocate LinkBuffer in case there are no dependencies (kernel).
1083 //
1084 Status = InternalUpdateLinkBuffer (Kext, Context);
1085 if (EFI_ERROR (Status)) {
1086 return Status;
1087 }
1088
1089 //
1090 // Collect data to enable linking against this KEXT.
1091 //
1092 if (Dependency) {
1093 if (Kext->Context.KxldState != NULL) {
1094 //
1095 // Use KXLD state as is for 10.6.8 kernel.
1096 //
1098 Kext,
1099 Context
1100 );
1101 if (EFI_ERROR (Status)) {
1102 return Status;
1103 }
1104
1106 Kext,
1107 Context
1108 );
1109 if (EFI_ERROR (Status)) {
1110 return Status;
1111 }
1112 } else {
1113 //
1114 // Use normal LINKEDIT building for newer kernels and all kexts.
1115 //
1116 Status = InternalScanBuildLinkedSymbolTable (Kext, Context);
1117 if (EFI_ERROR (Status)) {
1118 return Status;
1119 }
1120
1121 Status = InternalScanBuildLinkedVtables (Kext, Context);
1122 if (EFI_ERROR (Status)) {
1123 return Status;
1124 }
1125 }
1126 }
1127
1128 return EFI_SUCCESS;
1129}
1130
1131VOID
1133 IN PRELINKED_CONTEXT *Context
1134 )
1135{
1136 LIST_ENTRY *Kext;
1137
1138 Kext = GetFirstNode (&Context->PrelinkedKexts);
1139 while (!IsNull (&Context->PrelinkedKexts, Kext)) {
1140 GET_PRELINKED_KEXT_FROM_LINK (Kext)->Processed = FALSE;
1141 Kext = GetNextNode (&Context->PrelinkedKexts, Kext);
1142 }
1143}
1144
1147 IN OUT PRELINKED_CONTEXT *Context,
1148 IN OUT OC_MACHO_CONTEXT *Executable,
1149 IN XML_NODE *PlistRoot,
1150 IN UINT64 LoadAddress,
1151 IN UINT64 KmodAddress,
1152 IN UINT64 FileOffset
1153 )
1154{
1155 EFI_STATUS Status;
1156 PRELINKED_KEXT *Kext;
1157
1158 Kext = InternalNewPrelinkedKext (Executable, PlistRoot);
1159 if (Kext == NULL) {
1160 return NULL;
1161 }
1162
1163 Status = InternalScanPrelinkedKext (Kext, Context, FALSE);
1164 if (EFI_ERROR (Status)) {
1166 return NULL;
1167 }
1168
1169 //
1170 // Detach Identifier from temporary memory location.
1171 //
1172 Kext->Identifier = AllocateCopyPool (AsciiStrSize (Kext->Identifier), Kext->Identifier);
1173 if (Kext->Identifier == NULL) {
1175 return NULL;
1176 }
1177
1178 Status = PrelinkedDependencyInsert (Context, (VOID *)Kext->Identifier);
1179 if (EFI_ERROR (Status)) {
1180 FreePool ((VOID *)Kext->Identifier);
1182 return NULL;
1183 }
1184
1185 //
1186 // Also detach bundle compatible version if any.
1187 //
1188 if (Kext->CompatibleVersion != NULL) {
1189 Kext->CompatibleVersion = AllocateCopyPool (AsciiStrSize (Kext->CompatibleVersion), Kext->CompatibleVersion);
1190 if (Kext->CompatibleVersion == NULL) {
1192 return NULL;
1193 }
1194
1195 Status = PrelinkedDependencyInsert (Context, (VOID *)Kext->CompatibleVersion);
1196 if (EFI_ERROR (Status)) {
1197 FreePool ((VOID *)Kext->CompatibleVersion);
1199 return NULL;
1200 }
1201 }
1202
1203 //
1204 // Set virtual addresses.
1205 //
1206 Kext->Context.VirtualBase = LoadAddress;
1207 Kext->Context.VirtualKmod = KmodAddress;
1208
1209 Status = InternalPrelinkKext (Context, Kext, LoadAddress, FileOffset);
1210
1211 if (EFI_ERROR (Status)) {
1213 return NULL;
1214 }
1215
1216 Kext->SymbolTable = NULL;
1217 Kext->StringTable = NULL;
1218 Kext->NumberOfSymbols = 0;
1219 //
1220 // TODO: VTable and entry names are not updated after relocating StringTable,
1221 // which means that to avoid linkage issues for plugins we must either continue
1222 // re-constructing VTables (as done below) or implement some optimisations.
1223 // For example, we could recalculate addresses after linking has finished.
1224 // We could also store the name's offset and access via a StringTable pointer,
1225 // yet it was prone to errors and was already removed once.
1226 //
1227 if (Kext->LinkedVtables != NULL) {
1228 FreePool (Kext->LinkedVtables);
1229 Kext->LinkedVtables = NULL;
1230 Kext->NumberOfVtables = 0;
1231 }
1232
1233 return Kext;
1234}
#define ARRAY_SIZE(Array)
Definition AppleMacEfi.h:34
#define MACH_N_TYPE_TYPE
mask for the type bit
#define MACH_HEADER_FLAG_NO_UNDEFINED_REFERENCES
#define MACH_N_TYPE_STAB
#define MACH_N_TYPE_UNDF
undefined, n_sect == NO_SECT
#define MACH_N_TYPE_INDR
indirect
EFI_STATUS InternalKxldStateBuildLinkedSymbolTable(IN OUT PRELINKED_KEXT *Kext, IN PRELINKED_CONTEXT *Context)
Definition KxldState.c:192
EFI_STATUS InternalKxldStateBuildLinkedVtables(IN OUT PRELINKED_KEXT *Kext, IN PRELINKED_CONTEXT *Context)
Definition KxldState.c:292
DMG_SIZE_DEVICE_PATH Size
UINT32 KcGetKextSize(IN PRELINKED_CONTEXT *Context, IN UINT64 SourceAddress)
#define PRELINK_INFO_LINK_STATE_SIZE_KEY
EFI_STATUS PrelinkedDependencyInsert(IN OUT PRELINKED_CONTEXT *Context, IN VOID *Buffer)
#define INFO_BUNDLE_LIBRARIES_64_KEY
#define PRELINK_INFO_LINK_STATE_ADDR_KEY
#define PRELINK_INFO_EXECUTABLE_LOAD_ADDR_KEY
#define PRELINK_STATE_SECTION_KEXTS
#define PRELINK_STATE_SEGMENT
#define PRELINK_INFO_KMOD_INFO_KEY
#define PRELINK_INFO_EXECUTABLE_SOURCE_ADDR_KEY
#define PRELINK_KERNEL_IDENTIFIER
#define PRELINK_INFO_EXECUTABLE_SIZE_KEY
#define INFO_BUNDLE_LIBRARIES_KEY
#define INFO_BUNDLE_COMPATIBLE_VERSION_KEY
#define PRELINK_STATE_SECTION_KERNEL
#define INFO_BUNDLE_IDENTIFIER_KEY
BOOLEAN MachoSymbolNameIsCxx(IN CONST CHAR8 *Name)
Definition CxxSymbols.c:391
MACH_SECTION_ANY * MachoGetSectionByName(IN OUT OC_MACHO_CONTEXT *Context, IN MACH_SEGMENT_COMMAND_ANY *Segment, IN CONST CHAR8 *SectionName)
Definition Header.c:214
CONST CHAR8 * MachoGetIndirectSymbolName(IN OUT OC_MACHO_CONTEXT *Context, IN CONST MACH_NLIST_ANY *Symbol)
Definition Symbols.c:93
VOID * MachoGetFilePointerByAddress(IN OUT OC_MACHO_CONTEXT *Context, IN UINT64 Address, OUT UINT32 *MaxSize OPTIONAL)
Definition Header.c:627
MACH_HEADER_ANY * MachoGetMachHeader(IN OUT OC_MACHO_CONTEXT *Context)
Definition Header.c:44
BOOLEAN MachoInitializeContext(OUT OC_MACHO_CONTEXT *Context, IN VOID *FileData, IN UINT32 FileSize, IN UINT32 HeaderOffset, IN UINT32 InnerSize, IN BOOLEAN Is32Bit)
Definition Header.c:29
UINT32 MachoGetSymbolTable(IN OUT OC_MACHO_CONTEXT *Context, OUT CONST MACH_NLIST_ANY **SymbolTable, OUT CONST CHAR8 **StringTable OPTIONAL, OUT CONST MACH_NLIST_ANY **LocalSymbols OPTIONAL, OUT UINT32 *NumLocalSymbols OPTIONAL, OUT CONST MACH_NLIST_ANY **ExternalSymbols OPTIONAL, OUT UINT32 *NumExternalSymbols OPTIONAL, OUT CONST MACH_NLIST_ANY **UndefinedSymbols OPTIONAL, OUT UINT32 *NumUndefinedSymbols OPTIONAL)
Definition Header.c:519
CONST CHAR8 * MachoGetSymbolName(IN OUT OC_MACHO_CONTEXT *Context, IN CONST MACH_NLIST_ANY *Symbol)
Definition Symbols.c:80
MACH_SEGMENT_COMMAND_ANY * MachoGetSegmentByName(IN OUT OC_MACHO_CONTEXT *Context, IN CONST CHAR8 *SegmentName)
Definition Header.c:201
#define L_STR_LEN(String)
Definition OcStringLib.h:26
@ PLIST_NODE_TYPE_DICT
Definition OcXmlLib.h:91
@ PLIST_NODE_TYPE_STRING
Definition OcXmlLib.h:93
CONST CHAR8 * PlistKeyValue(IN XML_NODE *Node OPTIONAL)
Definition OcXmlLib.c:1841
UINT32 XmlNodeChildren(IN CONST XML_NODE *Node)
Definition OcXmlLib.c:1493
CONST CHAR8 * XmlNodeContent(IN CONST XML_NODE *Node)
Definition OcXmlLib.c:1467
UINT32 PlistDictChildren(IN CONST XML_NODE *Node)
Definition OcXmlLib.c:1813
BOOLEAN PlistIntegerValue(IN XML_NODE *Node OPTIONAL, OUT VOID *Value, IN UINT32 Size, IN BOOLEAN Hex)
Definition OcXmlLib.c:1943
XML_NODE * PlistNodeCast(IN XML_NODE *Node OPTIONAL, IN PLIST_NODE_TYPE Type)
Definition OcXmlLib.c:1760
XML_NODE * XmlNodeChild(IN CONST XML_NODE *Node, IN UINT32 Child)
Definition OcXmlLib.c:1503
XML_NODE * PlistDictChild(IN CONST XML_NODE *Node, IN UINT32 Child, OUT XML_NODE **Value OPTIONAL)
Definition OcXmlLib.c:1823
#define PRELINKED_KEXT_SIGNATURE
VOID InternalCreateVtablesPrelinked(IN PRELINKED_CONTEXT *Context, IN OUT PRELINKED_KEXT *Kext, IN UINT32 NumVtables, IN CONST OC_PRELINKED_VTABLE_LOOKUP_ENTRY *VtableLookups, OUT PRELINKED_VTABLE *VtableBuffer)
Definition Vtables.c:235
@ OcGetSymbolFirstLevel
#define GET_PRELINKED_KEXT_FROM_LINK(This)
BOOLEAN InternalGetVtableEntries(IN BOOLEAN Is32Bit, IN CONST VOID *VtableData, IN UINT32 MaxSize, OUT UINT32 *NumEntries)
Definition Vtables.c:151
BOOLEAN InternalPrepareCreateVtablesPrelinked(IN PRELINKED_KEXT *Kext, IN UINT32 MaxSize, OUT UINT32 *NumVtables, OUT OC_PRELINKED_VTABLE_LOOKUP_ENTRY *Vtables)
Definition Vtables.c:179
VOID InternalFreePrelinkedKext(IN PRELINKED_KEXT *Kext)
STATIC EFI_STATUS InternalUpdateLinkBuffer(IN OUT PRELINKED_KEXT *Kext, IN OUT PRELINKED_CONTEXT *Context)
STATIC EFI_STATUS InternalScanBuildLinkedSymbolTable(IN OUT PRELINKED_KEXT *Kext, IN PRELINKED_CONTEXT *Context)
EFI_STATUS InternalScanPrelinkedKext(IN OUT PRELINKED_KEXT *Kext, IN OUT PRELINKED_CONTEXT *Context, IN BOOLEAN Dependency)
PRELINKED_KEXT * InternalNewPrelinkedKext(IN OC_MACHO_CONTEXT *Context, IN XML_NODE *KextPlist)
STATIC VOID InternalScanCurrentPrelinkedKextLinkInfo(IN OUT PRELINKED_KEXT *Kext, IN PRELINKED_CONTEXT *Context)
STATIC EFI_STATUS InternalScanBuildLinkedVtables(IN OUT PRELINKED_KEXT *Kext, IN PRELINKED_CONTEXT *Context)
STATIC UINT32 InternalGetLinkBufferSize(IN OUT PRELINKED_KEXT *Kext)
PRELINKED_KEXT * InternalCachedPrelinkedKext(IN OUT PRELINKED_CONTEXT *Prelinked, IN CONST CHAR8 *Identifier)
STATIC PRELINKED_KEXT * InternalCreatePrelinkedKext(IN OUT PRELINKED_CONTEXT *Prelinked OPTIONAL, IN XML_NODE *KextPlist, IN CONST CHAR8 *Identifier OPTIONAL, IN BOOLEAN Is32Bit)
STATIC EFI_STATUS InternalInsertPrelinkedKextDependency(IN OUT PRELINKED_KEXT *Kext, IN OUT PRELINKED_CONTEXT *Context, IN UINT32 DependencyIndex, IN OUT PRELINKED_KEXT *DependencyKext)
PRELINKED_KEXT * InternalCachedPrelinkedKernel(IN OUT PRELINKED_CONTEXT *Prelinked)
EFI_STATUS InternalDropCachedPrelinkedKext(IN OUT PRELINKED_CONTEXT *Prelinked, IN CONST CHAR8 *Identifier)
VOID InternalUnlockContextKexts(IN PRELINKED_CONTEXT *Context)
PRELINKED_KEXT * InternalGetQuirkDependencyKext(IN CONST CHAR8 *DependencyId, IN OUT PRELINKED_CONTEXT *Context)
PRELINKED_KEXT * InternalLinkPrelinkedKext(IN OUT PRELINKED_CONTEXT *Context, IN OUT OC_MACHO_CONTEXT *Executable, IN XML_NODE *PlistRoot, IN UINT64 LoadAddress, IN UINT64 KmodAddress, IN UINT64 FileOffset)
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
#define ASSERT(x)
Definition coder.h:55
#define MAX(a, b)
Definition coder.h:59
UINT64 Value
value of this symbol (or stab offset)
UINT32 Value
value of this symbol (or stab offset)
UINT64 FileOffset
file offset of this segment
UINT64 VirtualAddress
memory address of this segment
UINT32 FileOffset
file offset of this segment
UINT32 VirtualAddress
memory address of this segment
union OC_PRELINKED_VTABLE_LOOKUP_ENTRY::@87 Vtable
OC_MACHO_CONTEXT MachContext
CONST VOID * KxldState
XML_NODE * BundleLibraries
CONST CHAR8 * StringTable
CONST MACH_NLIST_ANY * SymbolTable
PATCHER_CONTEXT Context
CONST CHAR8 * Identifier
CONST CHAR8 * CompatibleVersion
PRELINKED_VTABLE * LinkedVtables
CONST CHAR8 * Name
name of this symbol
UINT64 Value
value of this symbol (or stab offset)
PRELINKED_VTABLE_ENTRY Entries[]
The VTable entries.
MACH_NLIST_64 Symbol64
MACH_SEGMENT_COMMAND_64 Segment64
MACH_SEGMENT_COMMAND Segment32