From 8255f23ff0d41e66af76891f0f5ec88d3906cfd2 Mon Sep 17 00:00:00 2001 From: vit9696 Date: Fri, 29 Mar 2019 01:24:04 +0300 Subject: [PATCH] OcAppleKernelLib: Tune based on profiling data --- Library/OcAppleKernelLib/Link.c | 46 +++++++++++++++++--- Library/OcAppleKernelLib/PrelinkedInternal.h | 6 +-- Library/OcAppleKernelLib/PrelinkedKext.c | 10 +++-- Library/OcAppleKernelLib/Vtables.c | 10 ++--- Library/OcCompressionLib/lzss/lzss.h | 12 +++++ Library/OcCompressionLib/lzvn/lzvn.h | 8 ++++ Library/OcXmlLib/OcXmlLib.c | 5 ++- Tests/KernelTest/KernelTest.c | 11 +++++ TestsUser/Include/Base.h | 24 +++++----- TestsUser/Prelinked/Prelinked.c | 2 +- 10 files changed, 101 insertions(+), 33 deletions(-) diff --git a/Library/OcAppleKernelLib/Link.c b/Library/OcAppleKernelLib/Link.c index 73eb7964..42617dbf 100644 --- a/Library/OcAppleKernelLib/Link.c +++ b/Library/OcAppleKernelLib/Link.c @@ -39,12 +39,14 @@ CONST PRELINKED_KEXT_SYMBOL * InternalOcGetSymbolWorkerName ( IN PRELINKED_KEXT *Kext, IN CONST CHAR8 *LookupValue, + IN UINT32 LookupValueLength, IN OC_GET_SYMBOL_LEVEL SymbolLevel ) { PRELINKED_KEXT *Dependency; CONST PRELINKED_KEXT_SYMBOL *Symbols; CONST PRELINKED_KEXT_SYMBOL *SymbolsEnd; + CONST CHAR8 *LookedSymbol; UINT32 Index; UINT32 NumSymbols; @@ -63,8 +65,24 @@ InternalOcGetSymbolWorkerName ( SymbolsEnd = &Symbols[NumSymbols]; while (Symbols < SymbolsEnd) { - if (AsciiStrCmp (LookupValue, Symbols->Name) == 0) { - return Symbols; + // + // Symbol names often start and end similarly due to C++ mangling (e.g. __ZN). + // To optimise the lookup we compare their length check in the middle. + // Please do not change this without careful profiling. + // + if (Symbols->Length == LookupValueLength) { + LookedSymbol = Kext->StringTable + Symbols->Name; + if (LookedSymbol[LookupValueLength/2] == LookupValue[LookupValueLength/2] + && LookedSymbol[LookupValueLength/2 + 1] == LookupValue[LookupValueLength/2 + 1]) { + for (Index = 0; Index < LookupValueLength; ++Index) { + if (LookedSymbol[Index] != LookupValue[Index]) { + break; + } + } + if (Index == LookupValueLength) { + return Symbols; + } + } } Symbols++; } @@ -83,6 +101,7 @@ InternalOcGetSymbolWorkerName ( Symbols = InternalOcGetSymbolWorkerName ( Dependency, LookupValue, + LookupValueLength, OcGetSymbolOnlyCxx ); if (Symbols != NULL) { @@ -165,7 +184,7 @@ CONST PRELINKED_KEXT_SYMBOL * InternalOcGetSymbolName ( IN PRELINKED_CONTEXT *Context, IN PRELINKED_KEXT *Kext, - IN UINT64 LookupValue, + IN CONST CHAR8 *LookupValue, IN OC_GET_SYMBOL_LEVEL SymbolLevel ) { @@ -173,11 +192,25 @@ InternalOcGetSymbolName ( PRELINKED_KEXT *Dependency; UINT32 Index; + UINT32 LookupValueLength; Symbol = NULL; + LookupValueLength = (UINT32) AsciiStrLen (LookupValue); + + // + // Such symbols are illegit, but InternalOcGetSymbolWorkerName assumes Length > 0. + // + if (LookupValueLength == 0) { + return NULL; + } if ((SymbolLevel == OcGetSymbolOnlyCxx) && (Kext->LinkedSymbolTable != NULL)) { - Symbol = InternalOcGetSymbolWorkerName (Kext, (CHAR8 *)(UINTN)LookupValue, SymbolLevel); + Symbol = InternalOcGetSymbolWorkerName ( + Kext, + LookupValue, + LookupValueLength, + SymbolLevel + ); } else { for (Index = 0; Index < ARRAY_SIZE (Kext->Dependencies); ++Index) { Dependency = Kext->Dependencies[Index]; @@ -187,7 +220,8 @@ InternalOcGetSymbolName ( Symbol = InternalOcGetSymbolWorkerName ( Dependency, - (CHAR8 *)(UINTN)LookupValue, + LookupValue, + LookupValueLength, SymbolLevel ); if (Symbol != NULL) { @@ -317,7 +351,7 @@ InternalSolveSymbolNonWeak64 ( ResolveSymbol = InternalOcGetSymbolName ( Context, Kext, - (UINTN)Name, + Name, OcGetSymbolFirstLevel ); if (ResolveSymbol != NULL) { diff --git a/Library/OcAppleKernelLib/PrelinkedInternal.h b/Library/OcAppleKernelLib/PrelinkedInternal.h index fb277729..da41a7d5 100644 --- a/Library/OcAppleKernelLib/PrelinkedInternal.h +++ b/Library/OcAppleKernelLib/PrelinkedInternal.h @@ -34,7 +34,8 @@ typedef struct { // Value is declared first as it has shown to improve comparison performance. // UINT64 Value; ///< value of this symbol (or stab offset) - CONST CHAR8 *Name; ///< name of this symbol + UINT32 Name; ///< name of this symbol + UINT32 Length; } PRELINKED_KEXT_SYMBOL; typedef struct { @@ -341,12 +342,11 @@ typedef enum { OcGetSymbolOnlyCxx } OC_GET_SYMBOL_LEVEL; -// TODO: Move? CONST PRELINKED_KEXT_SYMBOL * InternalOcGetSymbolName ( IN PRELINKED_CONTEXT *Context, IN PRELINKED_KEXT *Kext, - IN UINT64 LookupValue, + IN CONST CHAR8 *LookupValue, IN OC_GET_SYMBOL_LEVEL SymbolLevel ); diff --git a/Library/OcAppleKernelLib/PrelinkedKext.c b/Library/OcAppleKernelLib/PrelinkedKext.c index d23655f6..77ab5108 100644 --- a/Library/OcAppleKernelLib/PrelinkedKext.c +++ b/Library/OcAppleKernelLib/PrelinkedKext.c @@ -284,7 +284,7 @@ InternalScanBuildLinkedSymbolTable ( ResolvedSymbol = InternalOcGetSymbolName ( Context, Kext, - (UINTN)Name, + Name, OcGetSymbolFirstLevel ); if (ResolvedSymbol == NULL) { @@ -297,12 +297,14 @@ InternalScanBuildLinkedSymbolTable ( } if (!Result) { - WalkerBottom->Name = (Kext->StringTable + Symbol->UnifiedName.StringIndex); WalkerBottom->Value = Symbol->Value; + WalkerBottom->Name = Symbol->UnifiedName.StringIndex; + WalkerBottom->Length = AsciiStrLen (Kext->StringTable + Symbol->UnifiedName.StringIndex); ++WalkerBottom; } else { - WalkerTop->Name = (Kext->StringTable + Symbol->UnifiedName.StringIndex); - WalkerTop->Value = Symbol->Value; + WalkerTop->Value = Symbol->Value; + WalkerTop->Name = Symbol->UnifiedName.StringIndex; + WalkerTop->Length = AsciiStrLen (Kext->StringTable + Symbol->UnifiedName.StringIndex); --WalkerTop; ++NumCxxSymbols; diff --git a/Library/OcAppleKernelLib/Vtables.c b/Library/OcAppleKernelLib/Vtables.c index 0afc4436..623aee77 100644 --- a/Library/OcAppleKernelLib/Vtables.c +++ b/Library/OcAppleKernelLib/Vtables.c @@ -135,7 +135,7 @@ InternalConstructVtablePrelinked64 ( if (Symbol != NULL) { Vtable->Entries[Index].Address = Value; - Vtable->Entries[Index].Name = Symbol->Name; + Vtable->Entries[Index].Name = Kext->StringTable + Symbol->Name; } else { Vtable->Entries[Index].Address = 0; Vtable->Entries[Index].Name = NULL; @@ -198,12 +198,12 @@ InternalPrepareCreateVtablesPrelinked64 ( ++Index ) { Symbol = &Kext->LinkedSymbolTable[Index]; - if (MachoSymbolNameIsVtable64 (Symbol->Name)) { + if (MachoSymbolNameIsVtable64 (Kext->StringTable + Symbol->Name)) { if ((Symbol->Value == 0) || (VtableIndex >= MaxSize)) { return FALSE; } - Vtables[VtableIndex].Name = Symbol->Name; + Vtables[VtableIndex].Name = Kext->StringTable + Symbol->Name; Vtables[VtableIndex].Vtable.Value = Symbol->Value; ++VtableIndex; } @@ -421,7 +421,7 @@ InternalInitializeVtableByEntriesAndRelocations64 ( OcGetSymbolOnlyCxx ); if (OcSymbol != NULL) { - VtableEntries[Index].Name = OcSymbol->Name; + VtableEntries[Index].Name = Kext->StringTable + OcSymbol->Name; VtableEntries[Index].Address = OcSymbol->Value; continue; } @@ -787,7 +787,7 @@ InternalPatchByVtables64 ( OcSymbolDummy = InternalOcGetSymbolName ( Context, Kext, - (UINTN)FinalSymbolName, + FinalSymbolName, OcGetSymbolAnyLevel ); if (OcSymbolDummy != NULL) { diff --git a/Library/OcCompressionLib/lzss/lzss.h b/Library/OcCompressionLib/lzss/lzss.h index 5681923b..66ca821b 100644 --- a/Library/OcCompressionLib/lzss/lzss.h +++ b/Library/OcCompressionLib/lzss/lzss.h @@ -30,6 +30,18 @@ typedef INT32 int32_t; #define compress_lzss CompressLZSS #define decompress_lzss DecompressLZSS +#ifdef bzero +#undef bzero +#endif + +#ifdef malloc +#undef malloc +#endif + +#ifdef free +#undef free +#endif + #define bzero(Dst, Size) ZeroMem ((Dst), (Size)) #define malloc(Size) AllocatePool (Size) #define free(Ptr) FreePool (Ptr) diff --git a/Library/OcCompressionLib/lzvn/lzvn.h b/Library/OcCompressionLib/lzvn/lzvn.h index d607f294..e74f458e 100644 --- a/Library/OcCompressionLib/lzvn/lzvn.h +++ b/Library/OcCompressionLib/lzvn/lzvn.h @@ -31,6 +31,14 @@ typedef UINTN uintmax_t; #define lzvn_decode_buffer DecompressLZVN +#ifdef memset +#undef memset +#endif + +#ifdef memcpy +#undef memcpy +#endif + #define memset(Dst, Value, Size) SetMem ((Dst), (Size), (UINT8)(Value)) #define memcpy(Dst, Src, Size) CopyMem ((Dst), (Src), (Size)) diff --git a/Library/OcXmlLib/OcXmlLib.c b/Library/OcXmlLib/OcXmlLib.c index c5348885..a917d694 100755 --- a/Library/OcXmlLib/OcXmlLib.c +++ b/Library/OcXmlLib/OcXmlLib.c @@ -238,9 +238,10 @@ XmlNodeChildPush ( } // - // Allocate twice more room. + // Allocate three times more room. + // This balances performance and memory usage on large files like prelinked plist. // - AllocCount *= 2; + AllocCount *= 3; NewList = (XML_NODE_LIST *) AllocatePool ( sizeof (XML_NODE_LIST) + sizeof (NewList->NodeList[0]) * AllocCount diff --git a/Tests/KernelTest/KernelTest.c b/Tests/KernelTest/KernelTest.c index 32d18637..49f70a82 100644 --- a/Tests/KernelTest/KernelTest.c +++ b/Tests/KernelTest/KernelTest.c @@ -525,6 +525,17 @@ TestFileOpen ( return EFI_OUT_OF_RESOURCES; } +#if 0 + STATIC UINT32 DumpCounter; + CHAR16 DumpName[64]; + UnicodeSPrint (DumpName, sizeof (DumpName), L"prel%u.bin", DumpCounter++); + Print ( + L"Writing resulting kernel of %u bytes - %r\n", + KernelSize, + WriteFileData (NULL, DumpName, Kernel, KernelSize) + ); +#endif + // // Return our handle. // diff --git a/TestsUser/Include/Base.h b/TestsUser/Include/Base.h index b82dfc31..84d92244 100644 --- a/TestsUser/Include/Base.h +++ b/TestsUser/Include/Base.h @@ -486,14 +486,14 @@ struct _LIST_ENTRY { // Functions // -#define AllocatePool(x) malloc(x) -#define AllocateZeroPool(x) calloc(1, x) -#define ReallocatePool(a,b,c) realloc(c,b) -#define FreePool(x) free(x) -#define CompareMem(a,b,c) memcmp((a),(b),(c)) -#define CopyMem(a,b,c) memmove((a),(b),(c)) -#define ZeroMem(a,b) memset(a, 0, b) -#define SetMem(Dst, Size, Value) memset(Dst, Value, Size) +#define AllocatePool(x) (malloc)(x) +#define AllocateZeroPool(x) (calloc)(1, x) +#define ReallocatePool(a,b,c) (realloc)(c,b) +#define FreePool(x) (free)(x) +#define CompareMem(a,b,c) (memcmp)((a),(b),(c)) +#define CopyMem(a,b,c) (memmove)((a),(b),(c)) +#define ZeroMem(a,b) (memset)(a, 0, b) +#define SetMem(Dst, Size, Value) (memset)(Dst, Value, Size) #define AsciiSPrint snppprintf #define AsciiStrCmp strcmp #define AsciiStrLen strlen @@ -501,15 +501,15 @@ struct _LIST_ENTRY { #define AsciiStrnCmp strncmp #define AsciiStrSize(x) (strlen(x) + 1) #define AsciiStrnCpyS(a, b, c, d) oc_strlcpy(a, c, b) -#define AsciiStrDecimalToUint64(a) strtoull(a, NULL, 10) -#define AsciiStrHexToUint64(a) strtoull(a, NULL, 16) +#define AsciiStrDecimalToUint64(a) (strtoull)(a, NULL, 10) +#define AsciiStrHexToUint64(a) (strtoull)(a, NULL, 16) #define ASSERT(x) assert(x) #define DebugCodeEnabled() true #define DebugAssertEnabled() true #define FreePages(a,b) do {} while (0) #define UnicodeSPrint(...) assert(false) -#define CompareGuid(a, b) (memcmp((a), (b), sizeof (EFI_GUID)) == 0) -#define CopyGuid(a, b) memcpy((a), (b), sizeof (EFI_GUID)) +#define CompareGuid(a, b) ((memcmp)((a), (b), sizeof (EFI_GUID)) == 0) +#define CopyGuid(a, b) (memcpy)((a), (b), sizeof (EFI_GUID)) EFI_STATUS EfiGetSystemConfigurationTable (EFI_GUID *TableGuid, OUT VOID **Table); diff --git a/TestsUser/Prelinked/Prelinked.c b/TestsUser/Prelinked/Prelinked.c index eb3a1073..dff5cd63 100644 --- a/TestsUser/Prelinked/Prelinked.c +++ b/TestsUser/Prelinked/Prelinked.c @@ -670,7 +670,7 @@ INT32 LLVMFuzzerTestOneInput(CONST UINT8 *Data, UINTN Size) { } int main(int argc, char *argv[]) { - for (size_t i = 0; i < 15; i++) { + for (size_t i = 0; i < 1; i++) { wrap_main(argc, argv); } return 0;