mirror of
https://github.com/acidanthera/OpenCorePkg.git
synced 2025-12-08 19:25:01 +00:00
426 lines
9.7 KiB
C
426 lines
9.7 KiB
C
/** @file
|
|
Provides services for C++ symbols.
|
|
|
|
Copyright (c) 2018, Download-Fritz. All rights reserved.<BR>
|
|
This program and the accompanying materials are licensed and made available
|
|
under the terms and conditions of the BSD License which accompanies this
|
|
distribution. The full text of the license may be found at
|
|
http://opensource.org/licenses/bsd-license.php.
|
|
|
|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|
|
|
**/
|
|
|
|
#include <Uefi.h>
|
|
|
|
#include <IndustryStandard/AppleMachoImage.h>
|
|
|
|
#include <Library/BaseLib.h>
|
|
#include <Library/BaseMemoryLib.h>
|
|
#include <Library/DebugLib.h>
|
|
#include <Library/OcGuardLib.h>
|
|
#include <Library/OcMachoLib.h>
|
|
#include <Library/OcStringLib.h>
|
|
|
|
#define CXX_PREFIX "__Z"
|
|
#define VTABLE_PREFIX CXX_PREFIX "TV"
|
|
#define OSOBJ_PREFIX CXX_PREFIX "N"
|
|
#define RESERVED_TOKEN "_RESERVED"
|
|
#define METACLASS_TOKEN "10gMetaClassE"
|
|
#define SMCP_TOKEN "10superClassE"
|
|
#define METACLASS_VTABLE_PREFIX VTABLE_PREFIX "N"
|
|
#define METACLASS_VTABLE_SUFFIX "9MetaClassE"
|
|
#define CXX_PURE_VIRTUAL "___cxa_pure_virtual"
|
|
#define FINAL_CLASS_TOKEN "14__OSFinalClassEv"
|
|
|
|
#define VTABLE_ENTRY_SIZE_64 8U
|
|
#define VTABLE_HEADER_LEN_64 2U
|
|
#define VTABLE_HEADER_SIZE_64 (VTABLE_HEADER_LEN_64 * VTABLE_ENTRY_SIZE_64)
|
|
|
|
BOOLEAN
|
|
MachoSymbolNameIsPureVirtual (
|
|
IN CONST CHAR8 *Name
|
|
)
|
|
{
|
|
ASSERT (Name != NULL);
|
|
return (AsciiStrCmp (Name, CXX_PURE_VIRTUAL) == 0);
|
|
}
|
|
|
|
BOOLEAN
|
|
MachoSymbolNameIsPadslot (
|
|
IN CONST CHAR8 *Name
|
|
)
|
|
{
|
|
ASSERT (Name != NULL);
|
|
return (AsciiStrStr (Name, RESERVED_TOKEN) != NULL);
|
|
}
|
|
|
|
BOOLEAN
|
|
MachoSymbolNameIsSmcp (
|
|
IN OUT OC_MACHO_CONTEXT *Context,
|
|
IN CONST CHAR8 *SymbolName
|
|
)
|
|
{
|
|
CONST CHAR8 *Suffix;
|
|
|
|
ASSERT (Context != NULL);
|
|
ASSERT (SymbolName != NULL);
|
|
//
|
|
// Verify the symbol has...
|
|
// 1) The C++ prefix.
|
|
// 2) The SMCP suffix.
|
|
// 3) At least one character between the prefix and the suffix.
|
|
//
|
|
Suffix = AsciiStrStr (SymbolName, SMCP_TOKEN);
|
|
|
|
if ( (Suffix == NULL)
|
|
|| (AsciiStrnCmp (SymbolName, OSOBJ_PREFIX, L_STR_LEN (OSOBJ_PREFIX)) != 0)
|
|
|| ((UINTN)(Suffix - SymbolName) <= L_STR_LEN (OSOBJ_PREFIX)))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOLEAN
|
|
MachoSymbolNameIsMetaclassPointer (
|
|
IN OUT OC_MACHO_CONTEXT *Context,
|
|
IN CONST CHAR8 *SymbolName
|
|
)
|
|
{
|
|
CONST CHAR8 *Suffix;
|
|
|
|
ASSERT (Context != NULL);
|
|
ASSERT (SymbolName != NULL);
|
|
//
|
|
// Verify the symbol has...
|
|
// 1) The C++ prefix.
|
|
// 2) The MetaClass suffix.
|
|
// 3) At least one character between the prefix and the suffix.
|
|
//
|
|
Suffix = AsciiStrStr (SymbolName, METACLASS_TOKEN);
|
|
|
|
if ( (Suffix == NULL)
|
|
|| (AsciiStrnCmp (SymbolName, OSOBJ_PREFIX, L_STR_LEN (OSOBJ_PREFIX)) != 0)
|
|
|| ((UINTN)(Suffix - SymbolName) <= L_STR_LEN (OSOBJ_PREFIX)))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOLEAN
|
|
MachoGetClassNameFromSuperMetaClassPointer (
|
|
IN OUT OC_MACHO_CONTEXT *Context,
|
|
IN CONST CHAR8 *SmcpName,
|
|
IN UINTN ClassNameSize,
|
|
OUT CHAR8 *ClassName
|
|
)
|
|
{
|
|
UINTN PrefixSize;
|
|
UINTN SuffixSize;
|
|
UINTN OutputSize;
|
|
|
|
ASSERT (Context != NULL);
|
|
ASSERT (SmcpName != NULL);
|
|
ASSERT (ClassNameSize > 0);
|
|
ASSERT (ClassName != NULL);
|
|
|
|
ASSERT (Context->StringTable != NULL);
|
|
|
|
ASSERT (MachoSymbolNameIsSmcp (Context, SmcpName));
|
|
|
|
PrefixSize = L_STR_LEN (OSOBJ_PREFIX);
|
|
SuffixSize = L_STR_LEN (SMCP_TOKEN);
|
|
|
|
OutputSize = (AsciiStrLen (SmcpName) - PrefixSize - SuffixSize);
|
|
|
|
if ((OutputSize + 1) > ClassNameSize) {
|
|
return FALSE;
|
|
}
|
|
|
|
CopyMem (ClassName, &SmcpName[PrefixSize], OutputSize);
|
|
ClassName[OutputSize] = '\0';
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
CONST CHAR8 *
|
|
MachoGetClassNameFromVtableName (
|
|
IN CONST CHAR8 *VtableName
|
|
)
|
|
{
|
|
ASSERT (VtableName != NULL);
|
|
ASSERT (MachoSymbolNameIsVtable (VtableName));
|
|
//
|
|
// As there is no suffix, just return a pointer from within VtableName.
|
|
//
|
|
return &VtableName[L_STR_LEN (VTABLE_PREFIX)];
|
|
}
|
|
|
|
BOOLEAN
|
|
MachoGetFunctionPrefixFromClassName (
|
|
IN CONST CHAR8 *ClassName,
|
|
IN UINTN FunctionPrefixSize,
|
|
OUT CHAR8 *FunctionPrefix
|
|
)
|
|
{
|
|
UINTN Index;
|
|
UINTN BodySize;
|
|
BOOLEAN Result;
|
|
UINTN TotalSize;
|
|
|
|
ASSERT (ClassName != NULL);
|
|
ASSERT (FunctionPrefixSize > 0);
|
|
ASSERT (FunctionPrefix != NULL);
|
|
|
|
BodySize = AsciiStrSize (ClassName);
|
|
Result = OcOverflowAddUN (L_STR_LEN (OSOBJ_PREFIX), BodySize, &TotalSize);
|
|
if (Result || (FunctionPrefixSize < TotalSize)) {
|
|
return FALSE;
|
|
}
|
|
|
|
Index = 0;
|
|
CopyMem (
|
|
&FunctionPrefix[Index],
|
|
OSOBJ_PREFIX,
|
|
L_STR_LEN (OSOBJ_PREFIX)
|
|
);
|
|
|
|
Index += L_STR_LEN (OSOBJ_PREFIX);
|
|
CopyMem (
|
|
&FunctionPrefix[Index],
|
|
ClassName,
|
|
BodySize
|
|
);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOLEAN
|
|
MachoGetClassNameFromMetaClassPointer (
|
|
IN OUT OC_MACHO_CONTEXT *Context,
|
|
IN CONST CHAR8 *MetaClassName,
|
|
IN UINTN ClassNameSize,
|
|
OUT CHAR8 *ClassName
|
|
)
|
|
{
|
|
UINTN PrefixSize;
|
|
UINTN SuffixSize;
|
|
UINTN ClassNameLength;
|
|
|
|
ASSERT (Context != NULL);
|
|
ASSERT (MetaClassName != NULL);
|
|
ASSERT (ClassNameSize > 0);
|
|
ASSERT (ClassName != NULL);
|
|
|
|
ASSERT (Context->StringTable != NULL);
|
|
|
|
ASSERT (MachoSymbolNameIsMetaclassPointer (Context, MetaClassName));
|
|
|
|
PrefixSize = L_STR_LEN (OSOBJ_PREFIX);
|
|
SuffixSize = L_STR_LEN (METACLASS_TOKEN);
|
|
|
|
ClassNameLength = (AsciiStrLen (MetaClassName) - PrefixSize - SuffixSize);
|
|
if ((ClassNameLength + 1) > ClassNameSize) {
|
|
return FALSE;
|
|
}
|
|
|
|
CopyMem (ClassName, &MetaClassName[PrefixSize], ClassNameLength);
|
|
ClassName[ClassNameLength] = '\0';
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOLEAN
|
|
MachoGetVtableNameFromClassName (
|
|
IN CONST CHAR8 *ClassName,
|
|
IN UINTN VtableNameSize,
|
|
OUT CHAR8 *VtableName
|
|
)
|
|
{
|
|
UINTN Index;
|
|
UINTN BodySize;
|
|
BOOLEAN Result;
|
|
UINTN TotalSize;
|
|
|
|
ASSERT (ClassName != NULL);
|
|
ASSERT (VtableNameSize > 0);
|
|
ASSERT (VtableName != NULL);
|
|
|
|
BodySize = AsciiStrSize (ClassName);
|
|
|
|
Result = OcOverflowAddUN (
|
|
L_STR_LEN (VTABLE_PREFIX),
|
|
BodySize,
|
|
&TotalSize
|
|
);
|
|
if (Result || (VtableNameSize < TotalSize)) {
|
|
return FALSE;
|
|
}
|
|
|
|
Index = 0;
|
|
CopyMem (
|
|
&VtableName[Index],
|
|
VTABLE_PREFIX,
|
|
L_STR_LEN (VTABLE_PREFIX)
|
|
);
|
|
|
|
Index += L_STR_LEN (VTABLE_PREFIX);
|
|
CopyMem (&VtableName[Index], ClassName, BodySize);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOLEAN
|
|
MachoGetMetaVtableNameFromClassName (
|
|
IN CONST CHAR8 *ClassName,
|
|
IN UINTN VtableNameSize,
|
|
OUT CHAR8 *VtableName
|
|
)
|
|
{
|
|
UINTN BodyLength;
|
|
BOOLEAN Result;
|
|
UINTN TotalSize;
|
|
UINTN Index;
|
|
|
|
ASSERT (ClassName != NULL);
|
|
ASSERT (VtableNameSize > 0);
|
|
ASSERT (VtableName != NULL);
|
|
|
|
BodyLength = AsciiStrLen (ClassName);
|
|
|
|
Result = OcOverflowTriAddUN (
|
|
L_STR_LEN (METACLASS_VTABLE_PREFIX),
|
|
BodyLength,
|
|
L_STR_SIZE (METACLASS_VTABLE_SUFFIX),
|
|
&TotalSize
|
|
);
|
|
if (Result || (VtableNameSize < TotalSize)) {
|
|
return FALSE;
|
|
}
|
|
|
|
Index = 0;
|
|
CopyMem (
|
|
&VtableName[Index],
|
|
METACLASS_VTABLE_PREFIX,
|
|
L_STR_LEN (METACLASS_VTABLE_PREFIX)
|
|
);
|
|
|
|
Index += L_STR_LEN (METACLASS_VTABLE_PREFIX);
|
|
CopyMem (&VtableName[Index], ClassName, BodyLength);
|
|
|
|
Index += BodyLength;
|
|
CopyMem (
|
|
&VtableName[Index],
|
|
METACLASS_VTABLE_SUFFIX,
|
|
L_STR_SIZE (METACLASS_VTABLE_SUFFIX)
|
|
);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOLEAN
|
|
MachoGetFinalSymbolNameFromClassName (
|
|
IN CONST CHAR8 *ClassName,
|
|
IN UINTN FinalSymbolNameSize,
|
|
OUT CHAR8 *FinalSymbolName
|
|
)
|
|
{
|
|
UINTN BodyLength;
|
|
BOOLEAN Result;
|
|
UINTN TotalSize;
|
|
UINTN Index;
|
|
|
|
ASSERT (ClassName != NULL);
|
|
ASSERT (FinalSymbolNameSize > 0);
|
|
ASSERT (FinalSymbolName != NULL);
|
|
|
|
BodyLength = AsciiStrLen (ClassName);
|
|
|
|
Result = OcOverflowTriAddUN (
|
|
L_STR_LEN (OSOBJ_PREFIX),
|
|
BodyLength,
|
|
L_STR_SIZE (FINAL_CLASS_TOKEN),
|
|
&TotalSize
|
|
);
|
|
if (Result || (FinalSymbolNameSize < TotalSize)) {
|
|
return FALSE;
|
|
}
|
|
|
|
Index = 0;
|
|
CopyMem (
|
|
&FinalSymbolName[Index],
|
|
OSOBJ_PREFIX,
|
|
L_STR_LEN (OSOBJ_PREFIX)
|
|
);
|
|
|
|
Index += L_STR_LEN (OSOBJ_PREFIX);
|
|
CopyMem (
|
|
&FinalSymbolName[Index],
|
|
ClassName,
|
|
BodyLength
|
|
);
|
|
|
|
Index += BodyLength;
|
|
CopyMem (
|
|
&FinalSymbolName[Index],
|
|
FINAL_CLASS_TOKEN,
|
|
L_STR_SIZE (FINAL_CLASS_TOKEN)
|
|
);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOLEAN
|
|
MachoSymbolNameIsVtable (
|
|
IN CONST CHAR8 *SymbolName
|
|
)
|
|
{
|
|
ASSERT (SymbolName != NULL);
|
|
//
|
|
// Implicitely checks for METACLASS_VTABLE_PREFIX.
|
|
//
|
|
return AsciiStrnCmp (SymbolName, VTABLE_PREFIX, L_STR_LEN (VTABLE_PREFIX)) == 0;
|
|
}
|
|
|
|
BOOLEAN
|
|
MachoSymbolNameIsCxx (
|
|
IN CONST CHAR8 *Name
|
|
)
|
|
{
|
|
ASSERT (Name != NULL);
|
|
return AsciiStrnCmp (Name, CXX_PREFIX, L_STR_LEN (CXX_PREFIX)) == 0;
|
|
}
|
|
|
|
MACH_NLIST_ANY *
|
|
MachoGetMetaclassSymbolFromSmcpSymbol (
|
|
IN OUT OC_MACHO_CONTEXT *Context,
|
|
IN CONST MACH_NLIST_ANY *Smcp
|
|
)
|
|
{
|
|
ASSERT (Context != NULL);
|
|
|
|
return Context->Is32Bit ?
|
|
(MACH_NLIST_ANY *)MachoGetMetaclassSymbolFromSmcpSymbol32 (Context, &Smcp->Symbol32) :
|
|
(MACH_NLIST_ANY *)MachoGetMetaclassSymbolFromSmcpSymbol64 (Context, &Smcp->Symbol64);
|
|
}
|
|
|
|
BOOLEAN
|
|
MachoGetVtableSymbolsFromSmcp (
|
|
IN OUT OC_MACHO_CONTEXT *Context,
|
|
IN CONST CHAR8 *SmcpName,
|
|
OUT CONST MACH_NLIST_ANY **Vtable,
|
|
OUT CONST MACH_NLIST_ANY **MetaVtable
|
|
)
|
|
{
|
|
ASSERT (Context != NULL);
|
|
|
|
return Context->Is32Bit ?
|
|
MachoGetVtableSymbolsFromSmcp32 (Context, SmcpName, (CONST MACH_NLIST **)Vtable, (CONST MACH_NLIST **)MetaVtable) :
|
|
MachoGetVtableSymbolsFromSmcp64 (Context, SmcpName, (CONST MACH_NLIST_64 **)Vtable, (CONST MACH_NLIST_64 **)MetaVtable);
|
|
}
|