From c6bf9d0590ecb44c04c85a1e4f1142d45bf7a15b Mon Sep 17 00:00:00 2001 From: Download-Fritz Date: Fri, 19 Oct 2018 05:55:38 +0200 Subject: [PATCH] OcMachoLib: Introduce Context concept. --- Include/Library/OcMachoLib.h | 115 +++++++++------- Library/OcMachoLib/CxxSymbols.c | 30 ++--- Library/OcMachoLib/Header.c | 216 ++++++++++++++++++++----------- Library/OcMachoLib/Relocations.c | 11 +- Library/OcMachoLib/Symbols.c | 32 ++--- 5 files changed, 247 insertions(+), 157 deletions(-) diff --git a/Include/Library/OcMachoLib.h b/Include/Library/OcMachoLib.h index 64ac7600..82dcff76 100644 --- a/Include/Library/OcMachoLib.h +++ b/Include/Library/OcMachoLib.h @@ -17,21 +17,46 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #include +/// +/// Context used to refer to a MACH-O. +/// +typedef struct { + CONST MACH_HEADER_64 *MachHeader; + UINTN FileSize; +} OC_MACHO_CONTEXT; + +/** + Initializes a MACH-O Context. + + @param[in] MachHeader Header of the MACH-O. + @param[in] FileSize File size of the MACH-O. + @param[out] Context MACH-O Context to initialize. + + @return Whether Context has been initialized successfully. + +**/ +BOOLEAN +MachoInitializeContext ( + IN CONST MACH_HEADER_64 *MachHeader, + IN UINTN FileSize, + OUT OC_MACHO_CONTEXT *Context + ); + /** Returns the last virtual address of a MACH-O. - @param[in] MachHeader Header of the MACH-O. + @param[in] Context Context of the MACH-O. **/ UINT64 MachoGetLastAddress64 ( - IN CONST MACH_HEADER_64 *MachHeader + IN CONST OC_MACHO_CONTEXT *Context ); /** Retrieves the first Load Command of type LoadCommandType. - @param[in] MachHeader Header of the MACH-O. + @param[in] Context Context of the MACH-O. @param[in] LoadCommandType Type of the Load Command to retrieve. @retval NULL NULL is returned on failure. @@ -39,14 +64,14 @@ MachoGetLastAddress64 ( **/ MACH_LOAD_COMMAND * MachoGetFirstCommand64 ( - IN CONST MACH_HEADER_64 *MachHeader, + IN CONST OC_MACHO_CONTEXT *Context, IN MACH_LOAD_COMMAND_TYPE LoadCommandType ); /** Retrieves the first Load Command of type LoadCommandType. - @param[in] MachHeader Header of the MACH-O. + @param[in] Context Context of the MACH-O. @param[in] LoadCommandType Type of the Load Command to retrieve. @param[in] LoadCommand Previous Load Command. @@ -55,7 +80,7 @@ MachoGetFirstCommand64 ( **/ MACH_LOAD_COMMAND * MachoGetNextCommand64 ( - IN CONST MACH_HEADER_64 *MachHeader, + IN CONST OC_MACHO_CONTEXT *Context, IN MACH_LOAD_COMMAND_TYPE LoadCommandType, IN CONST MACH_LOAD_COMMAND *LoadCommand ); @@ -63,20 +88,20 @@ MachoGetNextCommand64 ( /** Retrieves the first UUID Load Command. - @param[in] MachHeader Header of the MACH-O. + @param[in] Context Context of the MACH-O. @retval NULL NULL is returned on failure. **/ MACH_UUID_COMMAND * MachoGetUuid64 ( - IN CONST MACH_HEADER_64 *MachHeader + IN CONST OC_MACHO_CONTEXT *Context ); /** Retrieves the first segment by the name of SegmentName. - @param[in] MachHeader Header of the MACH-O. + @param[in] Context Context of the MACH-O. @param[in] SegmentName Segment name to search for. @retval NULL NULL is returned on failure. @@ -84,14 +109,14 @@ MachoGetUuid64 ( **/ MACH_SEGMENT_COMMAND_64 * MachoGetSegmentByName64 ( - IN CONST MACH_HEADER_64 *MachHeader, - IN CONST CHAR8 *SegmentName + IN CONST OC_MACHO_CONTEXT *Context, + IN CONST CHAR8 *SegmentName ); /** Retrieves the first section by the name of SectionName. - @param[in] MachHeader Header of the MACH-O. + @param[in] Context Context of the MACH-O. @param[in] Segment Segment to search in. @param[in] SectionName Section name to search for. @@ -100,7 +125,7 @@ MachoGetSegmentByName64 ( **/ MACH_SECTION_64 * MachoGetSectionByName64 ( - IN CONST MACH_HEADER_64 *MachHeader, + IN CONST OC_MACHO_CONTEXT *Context, IN CONST MACH_SEGMENT_COMMAND_64 *Segment, IN CONST CHAR8 *SectionName ); @@ -108,7 +133,7 @@ MachoGetSectionByName64 ( /** Retrieves a section within a segment by the name of SegmentName. - @param[in] MachHeader Header of the MACH-O. + @param[in] Context Context of the MACH-O. @param[in] SegmentName The name of the segment to search in. @param[in] SectionName The name of the section to search for. @@ -117,36 +142,36 @@ MachoGetSectionByName64 ( **/ MACH_SECTION_64 * MachoGetSegmentSectionByName64 ( - IN CONST MACH_HEADER_64 *MachHeader, - IN CONST CHAR8 *SegmentName, - IN CONST CHAR8 *SectionName + IN CONST OC_MACHO_CONTEXT *Context, + IN CONST CHAR8 *SegmentName, + IN CONST CHAR8 *SectionName ); /** Retrieves the first segment. - @param[in] MachHeader Header of the MACH-O. + @param[in] Context Context of the MACH-O. @retval NULL NULL is returned on failure. **/ MACH_SEGMENT_COMMAND_64 * MachoGetFirstSegment64 ( - IN CONST MACH_HEADER_64 *MachHeader + IN CONST OC_MACHO_CONTEXT *Context ); /** Retrieves the next segment. - @param[in] MachHeader Header of the MACH-O. - @param[in] Segment Segment to retrieve the successor of. + @param[in] Context Context of the MACH-O. + @param[in] Segment Segment to retrieve the successor of. @retal NULL NULL is returned on failure. **/ MACH_SEGMENT_COMMAND_64 * MachoGetNextSegment64 ( - IN CONST MACH_HEADER_64 *MachHeader, + IN CONST OC_MACHO_CONTEXT *Context, IN CONST MACH_SEGMENT_COMMAND_64 *Segment ); @@ -181,31 +206,31 @@ MachoGetNextSection64 ( /** Retrieves a section by its index. - @param[in] MachHeader Header of the MACH-O. - @param[in] Index Index of the section to retrieve. + @param[in] Context Context of the MACH-O. + @param[in] Index Index of the section to retrieve. @retval NULL NULL is returned on failure. **/ CONST MACH_SECTION_64 * MachoGetSectionByIndex64 ( - IN CONST MACH_HEADER_64 *MachHeader, - IN UINTN Index + IN CONST OC_MACHO_CONTEXT *Context, + IN UINTN Index ); /** Retrieves a section by its address. - @param[in] MachHeader Header of the MACH-O. - @param[in] Address Address of the section to retrieve. + @param[in] Context Context of the MACH-O. + @param[in] Address Address of the section to retrieve. @retval NULL NULL is returned on failure. **/ CONST MACH_SECTION_64 * MachoGetSectionByAddress64 ( - IN CONST MACH_HEADER_64 *MachHeader, - IN UINT64 Address + IN CONST OC_MACHO_CONTEXT *Context, + IN UINT64 Address ); /** @@ -233,7 +258,7 @@ MachoSymbolIsDefined ( /** Returns whether Symbol is defined locally. - @param[in] MachHeader Header of the MACH-O. + @param[in] Context Context of the MACH-O. @param[in] SymbolTable Symbol Table of the MACH-O. @param[in] DySymtab Dynamic Symbol Table of the MACH-O. @param[in] Symbol Symbol to evaluate. @@ -241,7 +266,7 @@ MachoSymbolIsDefined ( **/ BOOLEAN MachoSymbolIsLocalDefined ( - IN CONST MACH_HEADER_64 *MachHeader, + IN CONST OC_MACHO_CONTEXT *Context, IN CONST MACH_NLIST_64 *SymbolTable, IN CONST MACH_DYSYMTAB_COMMAND *DySymtab, IN CONST MACH_NLIST_64 *Symbol @@ -286,7 +311,7 @@ MachoGetLocalDefinedSymbolByName ( /** Relocate Symbol to be against LinkAddress. - @param[in] MachHeader MACH-O header of the KEXT to relocate. + @param[in] Context Context of the MACH-O. @param[in] LinkAddress The address to be linked against. @param[in,out] Symbol The symbol to be relocated. @@ -295,15 +320,15 @@ MachoGetLocalDefinedSymbolByName ( **/ BOOLEAN MachoRelocateSymbol64 ( - IN CONST MACH_HEADER_64 *MachHeader, - IN UINT64 LinkAddress, - IN OUT MACH_NLIST_64 *Symbol + IN CONST OC_MACHO_CONTEXT *Context, + IN UINT64 LinkAddress, + IN OUT MACH_NLIST_64 *Symbol ); /** Retrieves a symbol by the Relocation it is referenced by. - @param[in] MachHeader Header of the MACH-O. + @param[in] Context Context of the MACH-O. @param[in] NumberOfSymbols Number of symbols in SymbolTable. @param[in] SymbolTable Symbol Table of the MACH-O. @param[in] StringTable String Table of the MACH-O. @@ -314,7 +339,7 @@ MachoRelocateSymbol64 ( **/ CONST MACH_NLIST_64 * MachoGetCxxSymbolByRelocation64 ( - IN CONST MACH_HEADER_64 *MachHeader, + IN CONST OC_MACHO_CONTEXT *Context, IN UINTN NumberOfSymbols, IN CONST MACH_NLIST_64 *SymbolTable, IN CONST CHAR8 *StringTable, @@ -513,20 +538,20 @@ MachoIsSymbolNameCxx ( /** Returns the number of VTable entires in VtableData. - @param[in] MachHeader Header of the MACH-O. + @param[in] Context Context of the MACH-O. @param[in] VtableData The VTable's data. **/ UINTN MachoVtableGetNumberOfEntries64 ( - IN CONST MACH_HEADER_64 *MachHeader, - IN CONST UINT64 *VtableData + IN CONST OC_MACHO_CONTEXT *Context, + IN CONST UINT64 *VtableData ); /** Retrieves Metaclass symbol of a SMCP. - @param[in] MachHeader Header of the MACH-O. + @param[in] Context Context of the MACH-O. @param[in] NumberOfSymbols Number of symbols in SymbolTable. @param[in] SymbolTable Symbol Table of the MACH-O. @param[in] StringTable String Table of the MACH-O. @@ -539,7 +564,7 @@ MachoVtableGetNumberOfEntries64 ( **/ CONST MACH_NLIST_64 * MachoGetMetaclassSymbolFromSmcpSymbol64 ( - IN CONST MACH_HEADER_64 *MachHeader, + IN CONST OC_MACHO_CONTEXT *Context, IN UINTN NumberOfSymbols, IN CONST MACH_NLIST_64 *SymbolTable, IN CONST CHAR8 *StringTable, @@ -608,7 +633,7 @@ MachoPreserveRelocationIntel64 ( /** Retrieves a Relocation by the address it targets. - @param[in] MachHeader Header of the MACH-O. + @param[in] Context Context of the MACH-O. @param[in] NumberOfRelocations Number of Relocations in Relocations. @param[in] Relocations The Relocations to search. @param[in] Address The address to search for. @@ -618,7 +643,7 @@ MachoPreserveRelocationIntel64 ( **/ CONST MACH_RELOCATION_INFO * MachoGetRelocationByOffset ( - IN CONST MACH_HEADER_64 *MachHeader, + IN CONST OC_MACHO_CONTEXT *Context, IN UINTN NumberOfRelocations, IN CONST MACH_RELOCATION_INFO *Relocations, IN UINT64 Address diff --git a/Library/OcMachoLib/CxxSymbols.c b/Library/OcMachoLib/CxxSymbols.c index 8565276d..a781b66a 100644 --- a/Library/OcMachoLib/CxxSymbols.c +++ b/Library/OcMachoLib/CxxSymbols.c @@ -499,30 +499,28 @@ MachoIsSymbolNameCxx ( /** Returns the number of VTable entires in VtableData. - @param[in] MachHeader Header of the MACH-O. + @param[in] Context Context of the MACH-O. @param[in] VtableData The VTable's data. **/ UINTN MachoVtableGetNumberOfEntries64 ( - IN CONST MACH_HEADER_64 *MachHeader, - IN CONST UINT64 *VtableData + IN CONST OC_MACHO_CONTEXT *Context, + IN CONST UINT64 *VtableData ) { UINTN Index; UINTN NumberOfEntries; + ASSERT (Context != NULL); ASSERT (VtableData != NULL); NumberOfEntries = 0; - - if ((MachHeader->CpuType != MachCpuTypeArm) - && (MachHeader->CpuType != MachCpuTypeArm64)) { - for (Index = VTABLE_HEADER_LEN_64; VtableData[Index] != 0; ++Index) { - ++NumberOfEntries; - } - } else { - ASSERT (FALSE); + // + // Assumption: Not ARM. Currently verified by the Context initialization. + // + for (Index = VTABLE_HEADER_LEN_64; VtableData[Index] != 0; ++Index) { + ++NumberOfEntries; } return NumberOfEntries; @@ -531,7 +529,7 @@ MachoVtableGetNumberOfEntries64 ( /** Retrieves Metaclass symbol of a SMCP. - @param[in] MachHeader Header of the MACH-O. + @param[in] Context Context of the MACH-O. @param[in] NumberOfSymbols Number of symbols in SymbolTable. @param[in] SymbolTable Symbol Table of the MACH-O. @param[in] StringTable String Table of the MACH-O. @@ -544,7 +542,7 @@ MachoVtableGetNumberOfEntries64 ( **/ CONST MACH_NLIST_64 * MachoGetMetaclassSymbolFromSmcpSymbol64 ( - IN CONST MACH_HEADER_64 *MachHeader, + IN CONST OC_MACHO_CONTEXT *Context, IN UINTN NumberOfSymbols, IN CONST MACH_NLIST_64 *SymbolTable, IN CONST CHAR8 *StringTable, @@ -555,14 +553,14 @@ MachoGetMetaclassSymbolFromSmcpSymbol64 ( { CONST MACH_RELOCATION_INFO *Relocation; - ASSERT (MachHeader != NULL); + ASSERT (Context != NULL); ASSERT (SymbolTable != NULL); ASSERT (StringTable != NULL); ASSERT (Relocations != NULL); ASSERT (Smcp != NULL); Relocation = MachoGetRelocationByOffset ( - MachHeader, + Context, NumberOfRelocations, Relocations, Smcp->Value @@ -572,7 +570,7 @@ MachoGetMetaclassSymbolFromSmcpSymbol64 ( } return MachoGetCxxSymbolByRelocation64 ( - MachHeader, + Context, NumberOfSymbols, SymbolTable, StringTable, diff --git a/Library/OcMachoLib/Header.c b/Library/OcMachoLib/Header.c index ed58785b..8582e223 100644 --- a/Library/OcMachoLib/Header.c +++ b/Library/OcMachoLib/Header.c @@ -20,15 +20,82 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #include #include +/** + Initializes a MACH-O Context. + + @param[in] MachHeader Header of the MACH-O. + @param[in] FileSize File size of the MACH-O. + @param[out] Context MACH-O Context to initialize. + + @return Whether Context has been initialized successfully. + +**/ +BOOLEAN +MachoInitializeContext ( + IN CONST MACH_HEADER_64 *MachHeader, + IN UINTN FileSize, + OUT OC_MACHO_CONTEXT *Context + ) +{ + UINTN TopOfCommands; + UINTN Index; + CONST MACH_LOAD_COMMAND *Command; + UINTN CommandsSize; + // + // Verify MACH-O Header sanity. + // + TopOfCommands = ((UINTN)MachHeader->Commands + MachHeader->CommandsSize); + if ((MachHeader->Signature != MACH_HEADER_64_SIGNATURE) + || (TopOfCommands > ((UINTN)MachHeader + FileSize))) { + return FALSE; + } + + CommandsSize = 0; + + for ( + Index = 0, Command = MachHeader->Commands; + Index < MachHeader->NumberOfCommands; + ++Index, Command = NEXT_MACH_LOAD_COMMAND (Command) + ) { + if (((UINTN)Command >= ((UINTN)MachHeader + MachHeader->CommandsSize)) + || (Command->Size < sizeof (*Command)) + || ((Command->Size % 8) != 0) // Assumption: 64-bit, see below. + ) { + return FALSE; + } + + CommandsSize += Command->Size; + } + + if (MachHeader->CommandsSize != CommandsSize) { + return FALSE; + } + // + // Verify assumptions made by this library. + // Carefully audit all "Assumption:" remarks before modifying these checks. + // + if ((MachHeader->CpuType != MachCpuTypeX8664) + || ((MachHeader->FileType != MachHeaderFileTypeKextBundle) + && (MachHeader->FileType != MachHeaderFileTypeExecute))) { + ASSERT (FALSE); + return FALSE; + } + + Context->MachHeader = MachHeader; + Context->FileSize = FileSize; + + return TRUE; +} + /** Returns the last virtual address of a MACH-O. - @param[in] MachHeader Header of the MACH-O. + @param[in] Context Context of the MACH-O. **/ UINT64 MachoGetLastAddress64 ( - IN CONST MACH_HEADER_64 *MachHeader + IN CONST OC_MACHO_CONTEXT *Context ) { UINT64 LastAddress; @@ -36,14 +103,14 @@ MachoGetLastAddress64 ( CONST MACH_SEGMENT_COMMAND_64 *Segment; UINT64 Address; - ASSERT (MachHeader != NULL); + ASSERT (Context != NULL); LastAddress = 0; for ( - Segment = MachoGetFirstSegment64 (MachHeader); + Segment = MachoGetFirstSegment64 (Context); Segment != NULL; - Segment = MachoGetNextSegment64 (MachHeader, Segment) + Segment = MachoGetNextSegment64 (Context, Segment) ) { Address = (Segment->VirtualAddress + Segment->Hdr.Size); @@ -58,7 +125,7 @@ MachoGetLastAddress64 ( /** Retrieves the first Load Command of type LoadCommandType. - @param[in] MachHeader Header of the MACH-O. + @param[in] Context Context of the MACH-O. @param[in] LoadCommandType Type of the Load Command to retrieve. @param[in] LoadCommand Previous Load Command. @@ -67,30 +134,28 @@ MachoGetLastAddress64 ( **/ MACH_LOAD_COMMAND * MachoGetNextCommand64 ( - IN CONST MACH_HEADER_64 *MachHeader, + IN CONST OC_MACHO_CONTEXT *Context, IN MACH_LOAD_COMMAND_TYPE LoadCommandType, IN CONST MACH_LOAD_COMMAND *LoadCommand ) { CONST MACH_LOAD_COMMAND *Command; + CONST MACH_HEADER_64 *MachHeader; UINTN TopOfCommands; - ASSERT (MachHeader != NULL); - // - // LoadCommand being past the MachHeader Load Commands is implicitly caught - // by the while-loop. - // - if ((MachHeader->Signature != MACH_HEADER_64_SIGNATURE) - || (LoadCommand < MachHeader->Commands)) { - return NULL; - } + ASSERT (Context != NULL); + MachHeader = Context->MachHeader; TopOfCommands = ((UINTN)MachHeader->Commands + MachHeader->CommandsSize); + + ASSERT ( + (LoadCommand >= &MachHeader->Commands[0]) + && ((UINTN)LoadCommand <= TopOfCommands) + ); for ( Command = NEXT_MACH_LOAD_COMMAND (LoadCommand); - ((UINTN)Command < TopOfCommands) - && (((UINTN)Command + Command->Size) <= TopOfCommands); + (UINTN)Command < TopOfCommands; Command = NEXT_MACH_LOAD_COMMAND (Command) ) { if (Command->Type == LoadCommandType) { @@ -104,7 +169,7 @@ MachoGetNextCommand64 ( /** Retrieves the first Load Command of type LoadCommandType. - @param[in] MachHeader Header of the MACH-O. + @param[in] Context Context of the MACH-O. @param[in] LoadCommandType Type of the Load Command to retrieve. @retval NULL NULL is returned on failure. @@ -112,14 +177,17 @@ MachoGetNextCommand64 ( **/ MACH_LOAD_COMMAND * MachoGetFirstCommand64 ( - IN CONST MACH_HEADER_64 *MachHeader, + IN CONST OC_MACHO_CONTEXT *Context, IN MACH_LOAD_COMMAND_TYPE LoadCommandType ) { - ASSERT (MachHeader != NULL); + CONST MACH_HEADER_64 *MachHeader; - if ((MachHeader->Signature != MACH_HEADER_64_SIGNATURE) - || (MachHeader->NumberOfCommands == 0)) { + ASSERT (Context != NULL); + + MachHeader = Context->MachHeader; + + if (MachHeader->NumberOfCommands == 0) { return NULL; } @@ -128,7 +196,7 @@ MachoGetFirstCommand64 ( } return MachoGetNextCommand64 ( - MachHeader, + Context, LoadCommandType, &MachHeader->Commands[0] ); @@ -137,27 +205,27 @@ MachoGetFirstCommand64 ( /** Retrieves the first UUID Load Command. - @param[in] MachHeader Header of the MACH-O. + @param[in] Context Context of the MACH-O. @retval NULL NULL is returned on failure. **/ MACH_UUID_COMMAND * MachoGetUuid64 ( - IN CONST MACH_HEADER_64 *MachHeader + IN CONST OC_MACHO_CONTEXT *Context ) { - ASSERT (MachHeader != NULL); + ASSERT (Context != NULL); return (MACH_UUID_COMMAND *)( - MachoGetFirstCommand64 (MachHeader, MACH_LOAD_COMMAND_UUID) + MachoGetFirstCommand64 (Context, MACH_LOAD_COMMAND_UUID) ); } /** Retrieves the first segment by the name of SegmentName. - @param[in] MachHeader Header of the MACH-O. + @param[in] Context Context of the MACH-O. @param[in] SegmentName Segment name to search for. @retval NULL NULL is returned on failure. @@ -165,20 +233,20 @@ MachoGetUuid64 ( **/ MACH_SEGMENT_COMMAND_64 * MachoGetSegmentByName64 ( - IN CONST MACH_HEADER_64 *MachHeader, - IN CONST CHAR8 *SegmentName + IN CONST OC_MACHO_CONTEXT *Context, + IN CONST CHAR8 *SegmentName ) { CONST MACH_SEGMENT_COMMAND_64 *Segment; INTN Result; - ASSERT (MachHeader != NULL); + ASSERT (Context != NULL); ASSERT (SegmentName != NULL); for ( - Segment = MachoGetFirstSegment64 (MachHeader); + Segment = MachoGetFirstSegment64 (Context); Segment != NULL; - Segment = MachoGetNextSegment64 (MachHeader, Segment) + Segment = MachoGetNextSegment64 (Context, Segment) ) { if (Segment->Hdr.Type == MACH_LOAD_COMMAND_SEGMENT_64) { Result = AsciiStrnCmp ( @@ -198,7 +266,7 @@ MachoGetSegmentByName64 ( /** Retrieves the first section by the name of SectionName. - @param[in] MachHeader Header of the MACH-O. + @param[in] Context Context of the MACH-O. @param[in] Segment Segment to search in. @param[in] SectionName Section name to search for. @@ -207,7 +275,7 @@ MachoGetSegmentByName64 ( **/ MACH_SECTION_64 * MachoGetSectionByName64 ( - IN CONST MACH_HEADER_64 *MachHeader, + IN CONST OC_MACHO_CONTEXT *Context, IN CONST MACH_SEGMENT_COMMAND_64 *Segment, IN CONST CHAR8 *SectionName ) @@ -216,22 +284,10 @@ MachoGetSectionByName64 ( UINTN Index; INTN Result; - ASSERT (MachHeader != NULL); + ASSERT (Context != NULL); ASSERT (Segment != NULL); ASSERT (SectionName != NULL); - if (MachHeader->Signature != MACH_HEADER_64_SIGNATURE) { - return NULL; - } - // - // MH_OBJECT might have sections in segments they do not belong in for - // performance reasons. We do not support intermediate objects. - // - if (MachHeader->FileType == MachHeaderFileTypeObject) { - ASSERT (FALSE); - return NULL; - } - SectionWalker = &Segment->Sections[0]; for (Index = 0; Index < Segment->NumberOfSections; ++Index) { @@ -241,6 +297,12 @@ MachoGetSectionByName64 ( ARRAY_SIZE (SectionWalker->SegmentName) ); if (Result == 0) { + // + // Assumption: MACH-O is not of type MH_OBJECT. + // MH_OBJECT might have sections in segments they do not belong in for + // performance reasons. This library does not support intermediate + // objects. + // DEBUG_CODE ( Result = AsciiStrnCmp ( SectionWalker->SegmentName, @@ -265,7 +327,7 @@ MachoGetSectionByName64 ( /** Retrieves a section within a segment by the name of SegmentName. - @param[in] MachHeader Header of the MACH-O. + @param[in] Context Context of the MACH-O. @param[in] SegmentName The name of the segment to search in. @param[in] SectionName The name of the section to search for. @@ -274,21 +336,21 @@ MachoGetSectionByName64 ( **/ MACH_SECTION_64 * MachoGetSegmentSectionByName64 ( - IN CONST MACH_HEADER_64 *MachHeader, - IN CONST CHAR8 *SegmentName, - IN CONST CHAR8 *SectionName + IN CONST OC_MACHO_CONTEXT *Context, + IN CONST CHAR8 *SegmentName, + IN CONST CHAR8 *SectionName ) { CONST MACH_SEGMENT_COMMAND_64 *Segment; - ASSERT (MachHeader != NULL); + ASSERT (Context != NULL); ASSERT (SegmentName != NULL); ASSERT (SectionName != NULL); - Segment = MachoGetSegmentByName64 (MachHeader, SegmentName); + Segment = MachoGetSegmentByName64 (Context, SegmentName); if (Segment != NULL) { - return MachoGetSectionByName64 (MachHeader, Segment, SectionName); + return MachoGetSectionByName64 (Context, Segment, SectionName); } return NULL; @@ -297,39 +359,39 @@ MachoGetSegmentSectionByName64 ( /** Retrieves the first segment. - @param[in] MachHeader Header of the MACH-O. + @param[in] Context Context of the MACH-O. @retval NULL NULL is returned on failure. **/ MACH_SEGMENT_COMMAND_64 * MachoGetFirstSegment64 ( - IN CONST MACH_HEADER_64 *MachHeader + IN CONST OC_MACHO_CONTEXT *Context ) { return (MACH_SEGMENT_COMMAND_64 *)( - MachoGetFirstCommand64 (MachHeader, MACH_LOAD_COMMAND_SEGMENT_64) + MachoGetFirstCommand64 (Context, MACH_LOAD_COMMAND_SEGMENT_64) ); } /** Retrieves the next segment. - @param[in] MachHeader Header of the MACH-O. - @param[in] Segment Segment to retrieve the successor of. + @param[in] Context Context of the MACH-O. + @param[in] Segment Segment to retrieve the successor of. @retal NULL NULL is returned on failure. **/ MACH_SEGMENT_COMMAND_64 * MachoGetNextSegment64 ( - IN CONST MACH_HEADER_64 *MachHeader, + IN CONST OC_MACHO_CONTEXT *Context, IN CONST MACH_SEGMENT_COMMAND_64 *Segment ) { return (MACH_SEGMENT_COMMAND_64 *)( MachoGetNextCommand64 ( - MachHeader, + Context, MACH_LOAD_COMMAND_SEGMENT_64, &Segment->Hdr ) @@ -388,29 +450,29 @@ MachoGetNextSection64 ( /** Retrieves a section by its index. - @param[in] MachHeader Header of the MACH-O. - @param[in] Index Index of the section to retrieve. + @param[in] Context Context of the MACH-O. + @param[in] Index Index of the section to retrieve. @retval NULL NULL is returned on failure. **/ CONST MACH_SECTION_64 * MachoGetSectionByIndex64 ( - IN CONST MACH_HEADER_64 *MachHeader, - IN UINTN Index + IN CONST OC_MACHO_CONTEXT *Context, + IN UINTN Index ) { CONST MACH_SEGMENT_COMMAND_64 *Segment; UINTN SectionIndex; - ASSERT (MachHeader != NULL); + ASSERT (Context != NULL); SectionIndex = 0; for ( - Segment = MachoGetFirstSegment64 (MachHeader); + Segment = MachoGetFirstSegment64 (Context); Segment != NULL; - Segment = MachoGetNextSegment64 (MachHeader, Segment) + Segment = MachoGetNextSegment64 (Context, Segment) ) { if (Index <= (SectionIndex + (Segment->NumberOfSections - 1))) { return &Segment->Sections[Index - SectionIndex]; @@ -425,28 +487,28 @@ MachoGetSectionByIndex64 ( /** Retrieves a section by its address. - @param[in] MachHeader Header of the MACH-O. - @param[in] Address Address of the section to retrieve. + @param[in] Context Context of the MACH-O. + @param[in] Address Address of the section to retrieve. @retval NULL NULL is returned on failure. **/ CONST MACH_SECTION_64 * MachoGetSectionByAddress64 ( - IN CONST MACH_HEADER_64 *MachHeader, - IN UINT64 Address + IN CONST OC_MACHO_CONTEXT *Context, + IN UINT64 Address ) { CONST MACH_SEGMENT_COMMAND_64 *Segment; CONST MACH_SECTION_64 *Section; UINTN Index; - ASSERT (MachHeader != NULL); + ASSERT (Context != NULL); for ( - Segment = MachoGetFirstSegment64 (MachHeader); + Segment = MachoGetFirstSegment64 (Context); Segment != NULL; - Segment = MachoGetNextSegment64 (MachHeader, Segment) + Segment = MachoGetNextSegment64 (Context, Segment) ) { if ((Address >= Segment->VirtualAddress) && (Address < (Segment->VirtualAddress + Address >= Segment->FileSize))) { diff --git a/Library/OcMachoLib/Relocations.c b/Library/OcMachoLib/Relocations.c index b7f2a9ba..4a37f86f 100644 --- a/Library/OcMachoLib/Relocations.c +++ b/Library/OcMachoLib/Relocations.c @@ -17,6 +17,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #include #include +#include /** Returns whether the Relocation's type indicates a Pair for the Intel 64 @@ -65,7 +66,7 @@ MachoPreserveRelocationIntel64 ( /** Retrieves a Relocation by the address it targets. - @param[in] MachHeader Header of the MACH-O. + @param[in] Context Context of the MACH-O. @param[in] NumberOfRelocations Number of Relocations in Relocations. @param[in] Relocations The Relocations to search. @param[in] Address The address to search for. @@ -75,7 +76,7 @@ MachoPreserveRelocationIntel64 ( **/ CONST MACH_RELOCATION_INFO * MachoGetRelocationByOffset ( - IN CONST MACH_HEADER_64 *MachHeader, + IN CONST OC_MACHO_CONTEXT *Context, IN UINTN NumberOfRelocations, IN CONST MACH_RELOCATION_INFO *Relocations, IN UINT64 Address @@ -84,6 +85,7 @@ MachoGetRelocationByOffset ( UINTN Index; CONST MACH_RELOCATION_INFO *Relocation; + ASSERT (Context != NULL); ASSERT (Relocations != NULL); for ( @@ -106,9 +108,10 @@ MachoGetRelocationByOffset ( } // // Relocation Pairs can be skipped. + // Assumption: Intel X64. Currently verified by the Context + // initialization. // - if ((MachHeader->CpuType == MachCpuTypeX8664) - && MachoRelocationIsPairIntel64 (Relocation->Type)) { + if (MachoRelocationIsPairIntel64 (Relocation->Type)) { ++Index; ++Relocation; } diff --git a/Library/OcMachoLib/Symbols.c b/Library/OcMachoLib/Symbols.c index 1a4736a6..f9cdb5ce 100644 --- a/Library/OcMachoLib/Symbols.c +++ b/Library/OcMachoLib/Symbols.c @@ -92,7 +92,7 @@ MachoSymbolIsDefined ( /** Returns whether Symbol is defined locally. - @param[in] MachHeader Header of the MACH-O. + @param[in] Context Context of the MACH-O. @param[in] SymbolTable Symbol Table of the MACH-O. @param[in] DySymtab Dynamic Symbol Table of the MACH-O. @param[in] Symbol Symbol to evaluate. @@ -100,7 +100,7 @@ MachoSymbolIsDefined ( **/ BOOLEAN MachoSymbolIsLocalDefined ( - IN CONST MACH_HEADER_64 *MachHeader, + IN CONST OC_MACHO_CONTEXT *Context, IN CONST MACH_NLIST_64 *SymbolTable, IN CONST MACH_DYSYMTAB_COMMAND *DySymtab, IN CONST MACH_NLIST_64 *Symbol @@ -111,7 +111,7 @@ MachoSymbolIsLocalDefined ( CONST MACH_NLIST_64 *IndirectSymbols; CONST MACH_NLIST_64 *IndirectSymbolsTop; - ASSERT (MachHeader != NULL); + ASSERT (Context != NULL); ASSERT (SymbolTable != NULL); ASSERT (DySymtab != NULL); ASSERT (Symbol != NULL); @@ -129,7 +129,8 @@ MachoSymbolIsLocalDefined ( } IndirectSymbols = (CONST MACH_NLIST_64 *)( - (UINTN)MachHeader + DySymtab->IndirectSymbolsOffset + (UINTN)Context->MachHeader + + DySymtab->IndirectSymbolsOffset ); IndirectSymbolsTop = &IndirectSymbols[DySymtab->NumberOfIndirectSymbols]; @@ -225,7 +226,7 @@ MachoGetLocalDefinedSymbolByName ( /** Relocate Symbol to be against LinkAddress. - @param[in] MachHeader MACH-O header of the KEXT to relocate. + @param[in] Context Context of the MACH-O. @param[in] LinkAddress The address to be linked against. @param[in,out] Symbol The symbol to be relocated. @@ -234,21 +235,21 @@ MachoGetLocalDefinedSymbolByName ( **/ BOOLEAN MachoRelocateSymbol64 ( - IN CONST MACH_HEADER_64 *MachHeader, - IN UINT64 LinkAddress, - IN OUT MACH_NLIST_64 *Symbol + IN CONST OC_MACHO_CONTEXT *Context, + IN UINT64 LinkAddress, + IN OUT MACH_NLIST_64 *Symbol ) { CONST MACH_SECTION_64 *Section; - ASSERT (MachHeader != NULL); + ASSERT (Context != NULL); ASSERT (Symbol != NULL); ASSERT ((Symbol->Type & MACH_N_TYPE_EXT) == 0); // // Symbols are relocated when they describe sections. // if (MachoSymbolIsSection (Symbol)) { - Section = MachoGetSectionByAddress64 (MachHeader, Symbol->Value); + Section = MachoGetSectionByAddress64 (Context, Symbol->Value); if (Section == NULL) { return FALSE; } @@ -266,7 +267,7 @@ MachoRelocateSymbol64 ( /** Retrieves a symbol by the Relocation it is referenced by. - @param[in] MachHeader Header of the MACH-O. + @param[in] Context Header of the MACH-O. @param[in] NumberOfSymbols Number of symbols in SymbolTable. @param[in] SymbolTable Symbol Table of the MACH-O. @param[in] StringTable String Table of the MACH-O. @@ -277,7 +278,7 @@ MachoRelocateSymbol64 ( **/ CONST MACH_NLIST_64 * MachoGetCxxSymbolByRelocation64 ( - IN CONST MACH_HEADER_64 *MachHeader, + IN CONST OC_MACHO_CONTEXT *Context, IN UINTN NumberOfSymbols, IN CONST MACH_NLIST_64 *SymbolTable, IN CONST CHAR8 *StringTable, @@ -290,7 +291,7 @@ MachoGetCxxSymbolByRelocation64 ( CONST MACH_NLIST_64 *Symbol; CONST CHAR8 *Name; - ASSERT (MachHeader != NULL); + ASSERT (Context != NULL); ASSERT (SymbolTable != NULL); ASSERT (StringTable != NULL); ASSERT (Relocation != NULL); @@ -303,13 +304,14 @@ MachoGetCxxSymbolByRelocation64 ( return &SymbolTable[Relocation->SymbolNumber]; } - Section = MachoGetSectionByIndex64 (MachHeader, Relocation->SymbolNumber); + Section = MachoGetSectionByIndex64 (Context, Relocation->SymbolNumber); if (Section == NULL) { return NULL; } Value = *(CONST UINT64 *)( - (UINTN)MachHeader + Section->Address + Relocation->Address + (UINTN)Context->MachHeader + + (Section->Address + Relocation->Address) ); for (Index = 0; Index < NumberOfSymbols; ++Index) { Symbol = &SymbolTable[Index];