mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
192 lines
6.4 KiB
192 lines
6.4 KiB
/*++
|
|
|
|
Copyright (c) 1995 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
machine.cpp
|
|
|
|
Abstract:
|
|
|
|
This file implements the CreateMachApiThunk() function. This
|
|
function is responsible for emitting the individual API thunks
|
|
for the ppc architecture.
|
|
|
|
Author:
|
|
|
|
Wesley Witt (wesw) 28-June-1995
|
|
|
|
Environment:
|
|
|
|
User Mode
|
|
|
|
--*/
|
|
|
|
#include "apidllp.h"
|
|
#pragma hdrstop
|
|
|
|
//
|
|
// The following structure is used to save instructions in thunk.s by
|
|
// capturing global data in a single structure, thus avoiding TOC references.
|
|
//
|
|
|
|
extern "C" {
|
|
|
|
typedef
|
|
struct _APIDLL_PPC_DATA {
|
|
PVOID TlsGetValueEntry;
|
|
PVOID TlsGetValueToc;
|
|
PVOID TlsSetValueEntry;
|
|
PVOID TlsSetValueToc;
|
|
PVOID GetLastErrorEntry;
|
|
PVOID GetLastErrorToc;
|
|
PVOID SetLastErrorEntry;
|
|
PVOID SetLastErrorToc;
|
|
PVOID QueryPerformanceCounterEntry;
|
|
PVOID QueryPerformanceCounterToc;
|
|
PVOID ApiMonThunkCompleteEntry;
|
|
PVOID ApiTraceEnabled;
|
|
PVOID ApiCounter;
|
|
DWORD TlsReEnter;
|
|
DWORD TlsStack;
|
|
} APIDLL_PPC_DATA, *PAPIDLL_PPC_DATA;
|
|
|
|
APIDLL_PPC_DATA ApidllPpcData = {0};
|
|
|
|
}
|
|
|
|
PUCHAR
|
|
CreateMachApiThunk(
|
|
PULONG IatAddress,
|
|
PUCHAR Text,
|
|
PDLL_INFO DllInfo,
|
|
PAPI_INFO ApiInfo
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Emits the machine specific code for the API thunks.
|
|
|
|
Arguments:
|
|
|
|
IatAddress - Pointer to the IAT for this API
|
|
Text - Pointer to a buffer to place the generated code
|
|
DllInfo - Pointer to the DLL_INFO structure
|
|
ApiInfo - Pointer to the API_INFO structure
|
|
|
|
Return Value:
|
|
|
|
Pointer to the next byte to place more generated code.
|
|
|
|
--*/
|
|
|
|
{
|
|
PULONG Code = (PULONG)Text;
|
|
|
|
//
|
|
// If the ApidllPpcData structure hasn't been initialized yet, do so now.
|
|
//
|
|
|
|
if ( ApidllPpcData.TlsGetValueEntry == NULL ) {
|
|
ApidllPpcData.TlsGetValueEntry = ((PVOID *)pTlsGetValue)[0];
|
|
ApidllPpcData.TlsGetValueToc = ((PVOID *)pTlsGetValue)[1];
|
|
ApidllPpcData.TlsSetValueEntry = ((PVOID *)pTlsSetValue)[0];
|
|
ApidllPpcData.TlsSetValueToc = ((PVOID *)pTlsSetValue)[1];
|
|
ApidllPpcData.GetLastErrorEntry = ((PVOID *)pGetLastError)[0];
|
|
ApidllPpcData.GetLastErrorToc = ((PVOID *)pGetLastError)[1];
|
|
ApidllPpcData.SetLastErrorEntry = ((PVOID *)pSetLastError)[0];
|
|
ApidllPpcData.SetLastErrorToc = ((PVOID *)pSetLastError)[1];
|
|
ApidllPpcData.QueryPerformanceCounterEntry = ((PVOID *)pQueryPerformanceCounter)[0];
|
|
ApidllPpcData.QueryPerformanceCounterToc = ((PVOID *)pQueryPerformanceCounter)[1];
|
|
ApidllPpcData.ApiMonThunkCompleteEntry = ((PVOID *)ApiMonThunkComplete)[0];
|
|
ApidllPpcData.ApiTraceEnabled = ApiTraceEnabled;
|
|
ApidllPpcData.ApiCounter = ApiCounter;
|
|
ApidllPpcData.TlsReEnter = TlsReEnter;
|
|
ApidllPpcData.TlsStack = TlsStack;
|
|
}
|
|
|
|
//
|
|
// The entry in the IAT contains a pointer to the function descriptor
|
|
// for the target API.
|
|
//
|
|
|
|
PULONG TargetDescriptorAddress = *(PULONG *)IatAddress;
|
|
|
|
//
|
|
// The thunk needs to jump to ApiMonThunk using ApiMonThunk's function descriptor.
|
|
//
|
|
|
|
ULONG ApiMonThunkEntry = *(PULONG)ApiMonThunk;
|
|
ULONG ApiMonThunkToc = *((PULONG)ApiMonThunk + 1);
|
|
|
|
//
|
|
// If we've already created a thunk for this API, just point the IAT entry
|
|
// to the thunk's function descriptor.
|
|
//
|
|
|
|
if (ApiInfo->ThunkAddress) {
|
|
*IatAddress = ApiInfo->ThunkAddress;
|
|
return Text;
|
|
}
|
|
|
|
//
|
|
// Change the IAT entry to point to the function descriptor that we're about
|
|
// to create. Also, remember that we've thunked this API.
|
|
//
|
|
|
|
*IatAddress = (ULONG)Text;
|
|
ApiInfo->ThunkAddress = *IatAddress;
|
|
|
|
//
|
|
// Create a function descriptor for the thunk. The function starts right
|
|
// after the descriptor. Its TOC is APIDLL's TOC.
|
|
//
|
|
|
|
Code[0] = (ULONG)&Code[2];
|
|
Code++;
|
|
*Code++ = ApiMonThunkToc;
|
|
|
|
//
|
|
// Create the thunk. Branch via the CTR to ..ApiMonThunk. Note that we don't
|
|
// need to load r2 here because the caller will have loaded APIDLL's TOC via
|
|
// the function descriptor. The arguments to the thunk are as follows:
|
|
//
|
|
// r0 -- API flag
|
|
// r11 -- DllInfo
|
|
// r12 -- ApiInfo
|
|
//
|
|
|
|
*Code++ = 0x3c000000 | HIGH_ADDRX(ApiMonThunkEntry); // lis r0,0
|
|
*Code++ = 0x60000000 | LOW_ADDR(ApiMonThunkEntry); // ori r0,r0,0
|
|
*Code++ = 0x3d600000 | HIGH_ADDRX(DllInfo); // lis r11,0
|
|
*Code++ = 0x616b0000 | LOW_ADDR(DllInfo); // ori r11,r11,0
|
|
*Code++ = 0x3d800000 | HIGH_ADDRX(ApiInfo); // lis r12,0
|
|
*Code++ = 0x618c0000 | LOW_ADDR(ApiInfo); // ori r12,r12,0
|
|
*Code++ = 0x7c0903a6; // mtctr r0
|
|
//
|
|
if (_stricmp(DllInfo->Name,KERNEL32)==0) { //
|
|
if (strcmp((LPSTR)(ApiInfo->Name+(LPSTR)MemPtr),LOADLIBRARYA)==0) { //
|
|
*Code++ = 0x3c000001; // li r0,1
|
|
} else //
|
|
if (strcmp((LPSTR)(ApiInfo->Name+(LPSTR)MemPtr),LOADLIBRARYW)==0) { //
|
|
*Code++ = 0x3c000002; // li r0,2
|
|
} else //
|
|
if (strcmp((LPSTR)(ApiInfo->Name+(LPSTR)MemPtr),FREELIBRARY )==0) { //
|
|
*Code++ = 0x3c000003; // li r0,3
|
|
} else { //
|
|
*Code++ = 0x3c000000; // li r0,0
|
|
} //
|
|
} else { //
|
|
*Code++ = 0x3c000000; // li r0,0
|
|
} //
|
|
//
|
|
*Code++ = 0x4e800420; // bctr
|
|
|
|
//
|
|
// Return the next available thunk location.
|
|
//
|
|
|
|
return (PUCHAR)Code;
|
|
}
|