19#include <Library/BaseLib.h>
20#include <Library/BaseOverflowLib.h>
21#include <Library/DebugLib.h>
22#include <Library/MemoryAllocationLib.h>
44 Index = 0, Vtable = Kext->LinkedVtables;
45 Index < Kext->NumberOfVtables;
49 Result = AsciiStrCmp (Vtable->Name, Name);
55 for (Index = 0; Index <
ARRAY_SIZE (Kext->Dependencies); ++Index) {
57 if (Dependency == NULL) {
99 CONST VOID *VtableData;
105 ASSERT (VtableLookup != NULL);
108 VtableData = VtableLookup->Vtable.Data;
109 Vtable->Name = VtableLookup->Name;
127 if (Context->IsKernelCollection) {
138 if (Symbol != NULL) {
139 Vtable->Entries[Index].Address = Value;
140 Vtable->Entries[Index].Name = Symbol->Name;
142 Vtable->Entries[Index].Address = 0;
143 Vtable->Entries[Index].Name = NULL;
147 Vtable->NumEntries = Index;
153 IN CONST VOID *VtableData,
155 OUT UINT32 *NumEntries
160 ASSERT (VtableData != NULL);
161 ASSERT (NumEntries != NULL);
169 if (Index >= MaxSize) {
182 OUT UINT32 *NumVtables,
195 MaxSize /=
sizeof (*Vtables);
197 Index = (Kext->NumberOfSymbols - Kext->NumberOfCxxSymbols);
198 Index < Kext->NumberOfSymbols;
202 Symbol = &Kext->LinkedSymbolTable[Index];
214 if (Symbol->Value == 0) {
215 DEBUG ((DEBUG_VERBOSE,
"OCAK: Skipping %a with NULL value\n", Symbol->Name));
219 if (VtableIndex >= MaxSize) {
223 Vtables[VtableIndex].Name = Symbol->Name;
224 Vtables[VtableIndex].Vtable.Value = Symbol->Value;
229 *NumVtables = VtableIndex;
238 IN UINT32 NumVtables,
247 for (Index = 0; Index < NumVtables; ++Index) {
251 &VtableLookups[Index],
266 IN CONST CHAR8 *VtableName,
273 CONST CHAR8 *ClassName;
277 ASSERT (ParentEntry != NULL);
284 if (ParentEntry->Name == NULL) {
310 Result = AsciiStrCmp (Name, ParentEntry->Name);
339 sizeof (FunctionPrefix),
346 Result = AsciiStrCmp (Name, FunctionPrefix);
382 Name = ParentEntry->Name;
384 && (((MachoContext->Is32Bit ? Symbol->Symbol32.Value : Symbol->Symbol64.Value) & 1U) != 0))
386 DEBUG ((DEBUG_WARN,
"OCAK: Prelink: Invalid VTable symbol\n"));
399 IN CONST VOID *VtableData,
400 IN UINT32 NumSolveSymbols,
406 CONST CHAR8 *VtableName;
411 UINT32 SolveSymbolIndex;
415 MachoContext = &Kext->Context.MachContext;
416 VtableEntries = Vtable->Entries;
419 SolveSymbolIndex = 0;
424 for (Index = 0; Index < SuperVtable->NumEntries; ++Index) {
426 if (EntryValue != 0) {
440 if (OcSymbol != NULL) {
441 VtableEntries[Index].
Name = OcSymbol->Name;
442 VtableEntries[Index].
Address = OcSymbol->Value;
446 if (SolveSymbolIndex >= NumSolveSymbols) {
453 Symbol = SolveSymbols[SolveSymbolIndex];
460 if (Symbol != NULL) {
463 &SuperVtable->Entries[Index],
468 DEBUG ((DEBUG_INFO,
"OCAK: Failed to patch symbol %a for vtable %a\n",
MachoGetSymbolName (MachoContext, Symbol), VtableName));
478 VtableEntries[Index].
Name = NULL;
479 VtableEntries[Index].
Address = 0;
482 Vtable->Name = VtableName;
483 Vtable->NumEntries = Index;
493 IN OUT UINT32 *MaxSize,
494 OUT VOID **VtableDataPtr,
495 OUT UINT32 *NumEntries,
496 OUT UINT32 *NumSymbols,
502 UINT32 VtableMaxSize;
522 ASSERT (FileData != NULL);
524 VtableData = (VOID *)((UINTN)FileData + VtableOffset);
525 if (MachoContext->Is32Bit ? !BASE_TYPE_ALIGNED (UINT32, VtableData) : !BASE_TYPE_ALIGNED (UINT64, VtableData)) {
540 EntryOffset < VtableMaxSize;
544 if (
VTABLE_ENTRY_X (MachoContext->Is32Bit, VtableData, EntryOffset) == 0) {
545 Result = BaseOverflowAddU64 (
546 MachoContext->Is32Bit ? VtableSymbol->Symbol32.Value : VtableSymbol->Symbol64.Value,
565 *VtableDataPtr = VtableData;
567 *NumSymbols = SymIndex;
571 if (SymIndex >= MaxSymbols) {
575 SolveSymbols[SymIndex] = Symbol;
597 UINT32 NumEntriesTemp;
605 CONST VOID *OcSymbolDummy;
612 BOOLEAN SuccessfulIteration;
618 Entries = Context->LinkBuffer;
619 MaxSize = Context->LinkBufferSize;
621 MachoContext = &Kext->Context.MachContext;
625 EntryWalker = Entries;
636 if ( (((Context->Is32Bit ? Smcp->Symbol32.Type : Smcp->Symbol64.Type) &
MACH_N_TYPE_STAB) == 0)
639 if (MaxSize <
sizeof (*EntryWalker)) {
659 EntryWalker->
Smcp = Smcp;
674 NumEntries += NumEntriesTemp;
689 NumEntries += NumEntriesTemp;
701 Kext->LinkedVtables = AllocatePool (
702 ((NumTables * 2) *
sizeof (*Kext->LinkedVtables))
703 + (NumEntries * sizeof (*Kext->LinkedVtables->Entries))
705 if (Kext->LinkedVtables == NULL) {
709 CurrentVtable = Kext->LinkedVtables;
715 while (NumPatched < NumTables) {
716 SuccessfulIteration = FALSE;
719 Index = 0, EntryWalker = Entries;
724 Smcp = EntryWalker->Smcp;
769 if (MetaClass == NULL) {
779 sizeof (SuperClassName),
788 sizeof (SuperVtableName),
804 if (SuperVtable == NULL) {
813 sizeof (FinalSymbolName),
830 if (OcSymbolDummy != NULL) {
838 if (SymbolDummy != NULL) {
850 EntryWalker->VtableData,
851 EntryWalker->MetaSymsIndex,
852 EntryWalker->SolveSymbols,
856 DEBUG ((DEBUG_INFO,
"OCAK: Failed to patch vtable for superclass %a\n", SuperClassName));
878 if (MetaVtable != NULL) {
892 if (SuperVtable == NULL) {
906 EntryWalker->MetaVtable,
907 EntryWalker->MetaVtableData,
908 (EntryWalker->NumSolveSymbols - EntryWalker->MetaSymsIndex),
909 &EntryWalker->SolveSymbols[EntryWalker->MetaSymsIndex],
913 DEBUG ((DEBUG_INFO,
"OCAK: Failed to patch meta vtable for superclass %a\n", SuperClassName));
919 Kext->NumberOfVtables += 2;
921 EntryWalker->Smcp = NULL;
924 SuccessfulIteration = TRUE;
931 if (!SuccessfulIteration) {
#define ARRAY_SIZE(Array)
CONST PRELINKED_KEXT_SYMBOL * InternalOcGetSymbolName(IN PRELINKED_CONTEXT *Context, IN PRELINKED_KEXT *Kext, IN CONST CHAR8 *LookupValue, IN OC_GET_SYMBOL_LEVEL SymbolLevel)
CONST PRELINKED_KEXT_SYMBOL * InternalOcGetSymbolValue(IN PRELINKED_CONTEXT *Context, IN PRELINKED_KEXT *Kext, IN UINT64 LookupValue, IN OC_GET_SYMBOL_LEVEL SymbolLevel)
VOID InternalSolveSymbolValue(IN BOOLEAN Is32Bit, IN UINT64 Value, OUT MACH_NLIST_ANY *Symbol)
UINT64 KcFixupValue(IN UINT64 Value, IN CONST CHAR8 *Name OPTIONAL)
MACH_NLIST_ANY * MachoGetLocalDefinedSymbolByName(IN OUT OC_MACHO_CONTEXT *Context, IN CONST CHAR8 *Name)
BOOLEAN MachoSymbolNameIsPadslot(IN CONST CHAR8 *Name)
BOOLEAN MachoGetClassNameFromMetaClassPointer(IN OUT OC_MACHO_CONTEXT *Context, IN CONST CHAR8 *MetaClassName, IN UINTN ClassNameSize, OUT CHAR8 *ClassName)
BOOLEAN MachoGetClassNameFromSuperMetaClassPointer(IN OUT OC_MACHO_CONTEXT *Context, IN CONST CHAR8 *SmcpName, IN UINTN ClassNameSize, OUT CHAR8 *ClassName)
BOOLEAN MachoSymbolIsLocalDefined(IN OUT OC_MACHO_CONTEXT *Context, IN CONST MACH_NLIST_ANY *Symbol)
CONST CHAR8 * MachoGetClassNameFromVtableName(IN CONST CHAR8 *VtableName)
BOOLEAN MachoGetVtableSymbolsFromSmcp(IN OUT OC_MACHO_CONTEXT *Context, IN CONST CHAR8 *SmcpName, OUT CONST MACH_NLIST_ANY **Vtable, OUT CONST MACH_NLIST_ANY **MetaVtable)
BOOLEAN MachoGetFunctionPrefixFromClassName(IN CONST CHAR8 *ClassName, IN UINTN FunctionPrefixSize, OUT CHAR8 *FunctionPrefix)
VOID * MachoGetFileData(IN OUT OC_MACHO_CONTEXT *Context)
BOOLEAN MachoGetSymbolByExternRelocationOffset(IN OUT OC_MACHO_CONTEXT *Context, IN UINT64 Address, OUT MACH_NLIST_ANY **Symbol)
BOOLEAN MachoGetFinalSymbolNameFromClassName(IN CONST CHAR8 *ClassName, IN UINTN FinalSymbolNameSize, OUT CHAR8 *FinalSymbolName)
MACH_NLIST_ANY * MachoGetMetaclassSymbolFromSmcpSymbol(IN OUT OC_MACHO_CONTEXT *Context, IN CONST MACH_NLIST_ANY *Smcp)
MACH_NLIST_ANY * MachoGetSymbolByIndex(IN OUT OC_MACHO_CONTEXT *Context, IN UINT32 Index)
CONST CHAR8 * MachoGetSymbolName(IN OUT OC_MACHO_CONTEXT *Context, IN CONST MACH_NLIST_ANY *Symbol)
BOOLEAN MachoSymbolNameIsVtable(IN CONST CHAR8 *SymbolName)
BOOLEAN MachoGetVtableNameFromClassName(IN CONST CHAR8 *ClassName, IN UINTN VtableNameSize, OUT CHAR8 *VtableName)
BOOLEAN MachoSymbolNameIsSmcp(IN OUT OC_MACHO_CONTEXT *Context, IN CONST CHAR8 *SymbolName)
BOOLEAN MachoSymbolIsDefined(IN OUT OC_MACHO_CONTEXT *Context, IN CONST MACH_NLIST_ANY *Symbol)
BOOLEAN MachoSymbolNameIsPureVirtual(IN CONST CHAR8 *Name)
BOOLEAN MachoSymbolGetFileOffset(IN OUT OC_MACHO_CONTEXT *Context, IN CONST MACH_NLIST_ANY *Symbol, OUT UINT32 *FileOffset, OUT UINT32 *MaxSize OPTIONAL)
BOOLEAN MachoGetMetaVtableNameFromClassName(IN CONST CHAR8 *ClassName, IN UINTN VtableNameSize, OUT CHAR8 *VtableName)
#define OS_METACLASS_VTABLE_NAME
#define VTABLE_ENTRY_SIZE_X(a)
#define VTABLE_HEADER_LEN
#define VTABLE_ENTRY_X(a, b, c)
#define GET_NEXT_OC_VTABLE_PATCH_ENTRY(Entry)
#define GET_NEXT_PRELINKED_VTABLE(This)
VOID InternalUnlockContextKexts(IN PRELINKED_CONTEXT *Context)
CONST PRELINKED_VTABLE * InternalGetOcVtableByName(IN PRELINKED_CONTEXT *Context, IN PRELINKED_KEXT *Kext, IN CONST CHAR8 *Name)
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)
STATIC BOOLEAN InternalInitializeVtablePatchData(IN OUT OC_MACHO_CONTEXT *MachoContext, IN CONST MACH_NLIST_ANY *VtableSymbol, IN OUT UINT32 *MaxSize, OUT VOID **VtableDataPtr, OUT UINT32 *NumEntries, OUT UINT32 *NumSymbols, OUT MACH_NLIST_ANY **SolveSymbols)
BOOLEAN InternalPatchByVtables(IN PRELINKED_CONTEXT *Context, IN OUT PRELINKED_KEXT *Kext)
CONST PRELINKED_VTABLE * InternalGetOcVtableByNameWorker(IN PRELINKED_CONTEXT *Context, IN PRELINKED_KEXT *Kext, IN CONST CHAR8 *Name)
STATIC BOOLEAN InternalPatchVtableSymbol(IN OUT OC_MACHO_CONTEXT *MachoContext, IN CONST PRELINKED_VTABLE_ENTRY *ParentEntry, IN CONST CHAR8 *VtableName, OUT MACH_NLIST_ANY *Symbol)
STATIC BOOLEAN InternalInitializeVtableByEntriesAndRelocations(IN PRELINKED_CONTEXT *Context, IN PRELINKED_KEXT *Kext, IN CONST PRELINKED_VTABLE *SuperVtable, IN CONST MACH_NLIST_ANY *VtableSymbol, IN CONST VOID *VtableData, IN UINT32 NumSolveSymbols, IN OUT MACH_NLIST_ANY **SolveSymbols, OUT PRELINKED_VTABLE *Vtable)
BOOLEAN InternalGetVtableEntries(IN BOOLEAN Is32Bit, IN CONST VOID *VtableData, IN UINT32 MaxSize, OUT UINT32 *NumEntries)
STATIC VOID InternalConstructVtablePrelinked(IN PRELINKED_CONTEXT *Context, IN OUT PRELINKED_KEXT *Kext, IN CONST OC_PRELINKED_VTABLE_LOOKUP_ENTRY *VtableLookup, OUT PRELINKED_VTABLE *Vtable)
BOOLEAN InternalPrepareCreateVtablesPrelinked(IN PRELINKED_KEXT *Kext, IN UINT32 MaxSize, OUT UINT32 *NumVtables, OUT OC_PRELINKED_VTABLE_LOOKUP_ENTRY *Vtables)
UINT64 Value
value of this symbol (or stab offset)
UINT32 Value
value of this symbol (or stab offset)
CONST MACH_NLIST_ANY * MetaVtable
CONST MACH_NLIST_ANY * Smcp
CONST MACH_NLIST_ANY * Vtable
MACH_NLIST_ANY * SolveSymbols[]
PRELINKED_KEXT * Dependencies[MAX_KEXT_DEPEDENCIES]
UINT64 Address
The symbol's address.
CONST CHAR8 * Name
The symbol's name.