|
|
/*++
Copyright (c) 2000 Microsoft Corporation
Module Name:
bldrthnk.c
Abstract:
This module implements a program which generates code to thunk from 32-bit to 64-bit structures.
This code is generated as an aid to the AMD64 boot loader, which must generate 64-bit structures from 32-bit structures.
Author:
Forrest C. Foltz (forrestf) 15-May-2000
To use:
Revision History:
--*/
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include "bldrthnk.h"
//
// Internal type definitions follow
//
typedef struct _OBJ { PCHAR Image; LONG ImageSize; PDEFINITIONS Definitions; } OBJ, *POBJ;
typedef struct _TYPE_REC *PTYPE_REC; typedef struct _FIELD_REC *PFIELD_REC;
typedef struct _TYPE_REC { PTYPE_REC Next; PCHAR Name; ULONG Size32; ULONG Size64; PFIELD_REC FieldList; BOOL SignExtend; BOOL Fabricated; BOOL Only64; } TYPE_REC;
typedef struct _FIELD_REC { PFIELD_REC Next; PCHAR Name; PCHAR TypeName; PCHAR SizeFormula; ULONG TypeSize32; ULONG TypeSize64; ULONG Offset32; ULONG Offset64; ULONG Size32; ULONG Size64; PTYPE_REC TypeRec; } FIELD_REC;
//
// Static TYPE_REC describing a 64-bit pointer type
//
TYPE_REC pointer64_typerec = { NULL, "POINTER64", 4, 8, NULL, TRUE, TRUE };
//
// Inline routine to generate a 32-bit pointer value from a ULONGLONG
// value found in an .obj file.
//
__inline PVOID CalcPtr( IN ULONGLONG Address ) { return (PVOID)((ULONG)Address); }
//
// Forward declarations follow
//
VOID ApplyFixupsToImage( IN PCHAR ObjImage );
VOID __cdecl CheckCondition( int Condition, const char *FormatString, ... );
VOID FabricateMissingTypes( VOID );
PTYPE_REC FindTypeRec( IN PCHAR Name );
PVOID GetMem( IN ULONG Size );
VOID NewGlobalType( IN PTYPE_REC TypeRec );
BOOL ProcessStructure( IN ULONG StrucIndex );
void ReadObj( IN PCHAR Path, OUT POBJ Obj );
int Usage( void );
VOID WriteCopyList( IN PTYPE_REC TypeRec );
VOID WriteCopyListWorker( IN PTYPE_REC TypeRec, IN ULONG Offset32, IN ULONG Offset64, IN PCHAR ParentName );
VOID WriteCopyRoutine( IN PTYPE_REC TypeRec );
VOID WriteThunkSource( VOID );
//
// Global data follows.
//
OBJ Obj32; OBJ Obj64; PTYPE_REC TypeRecList = NULL;
int __cdecl main( IN int argc, IN char *argv[] )
/*++
Routine Description:
This is the main entrypoint of bldrthnk.exe. Two command-line arguments are expected: first the path to the 32-bit .obj module, the second to the path to the 64-bit .obj module. The .objs are expected to be the result of compiling m4-generated structure definition code.
Arguments:
Return value:
0 for success, non-zero otherwise.
--*/
{ ULONG strucIndex;
//
// argv[1] is the name of the 32-bit obj, argv[2] is the name of the
// 64-bit obj
//
if (argc != 3) { return Usage(); }
//
// Usage:
//
// bldrthnk <32-bit.obj> <64-bit.obj>
//
ReadObj( argv[1], &Obj32 ); ReadObj( argv[2], &Obj64 );
//
// Process each STRUC_DEF structure
//
strucIndex = 0; while (ProcessStructure( strucIndex )) { strucIndex += 1; }
FabricateMissingTypes();
//
// Write out the file
//
WriteThunkSource();
return 0; }
int Usage( VOID )
/*++
Routine Description:
Displays program usage.
Arguments:
Return value:
--*/
{ fprintf(stderr, "Usage: bldrthnk.exe <32-bit obj> <64-bit obj>\n"); return -1; }
void ReadObj( IN PCHAR Path, OUT POBJ Obj )
/*++
Routine Description:
Allocates an appropriate buffer, and reads into it the supplied object image in its entirety.
Arguments:
Path - Supplies the path of the object image to process.
Obj - Supplies a pointer to an OBJ structure which upon return will updated with the appropriate data.
Return value:
None.
--*/
{ FILE *objFile; int result; long objImageSize; PCHAR objImage; PULONG sigPtr; PULONG srchEnd; PDEFINITIONS definitions; LONGLONG imageBias;
//
// Open the file
//
objFile = fopen( Path, "rb" ); CheckCondition( objFile != NULL, "Cannot open %s for reading.\n", Path );
//
// Get the file size, allocate a buffer, read it in, and close.
//
result = fseek( objFile, 0, SEEK_END ); CheckCondition( result == 0, "fseek() failed, error %d\n", errno );
objImageSize = ftell( objFile ); CheckCondition( objImageSize != -1L, "ftell() failed, error %d\n", errno );
CheckCondition( objImageSize > 0, "%s appears to be corrupt\n", Path );
objImage = GetMem( objImageSize );
result = fseek( objFile, 0, SEEK_SET ); CheckCondition( result == 0, "fseek() failed, error %d\n", errno );
result = fread( objImage, 1, objImageSize, objFile ); CheckCondition( result == objImageSize, "Error reading from %s\n", Path );
fclose( objFile );
//
// Find the start of the "definitions" array by looking for
// SIG_1 followed by SIG_2
//
srchEnd = (PULONG)(objImage + objImageSize - 2 * sizeof(SIG_1)); sigPtr = (PULONG)objImage; definitions = NULL;
while (sigPtr < srchEnd) {
if (sigPtr[0] == SIG_1 && sigPtr[1] == SIG_2) { definitions = (PDEFINITIONS)sigPtr; break; }
sigPtr = (PULONG)((PCHAR)sigPtr + 1); } CheckCondition( definitions != NULL, "Error: could not find signature in %s\n", Path );
//
// Perform fixups on the image
//
ApplyFixupsToImage( objImage );
//
// Fill in the output structure and return
//
Obj->Image = objImage; Obj->ImageSize = objImageSize; Obj->Definitions = definitions; }
VOID __cdecl CheckCondition( int Condition, const char *FormatString, ... )
/*++
Routine Description:
Asserts that Condition is non-zero. If Condition is zero, FormatString is processed and displayed, and the program is terminated.
Arguments:
Condition - Supplies the boolean value to evaluate.
FormatString, ... - Supplies the format string and optional parameters to display in the event of a zero Condition.
Return value:
None.
--*/
{ va_list(arglist);
va_start(arglist, FormatString);
if( Condition == 0 ){
//
// A fatal error was encountered. Bail.
//
vprintf( FormatString, arglist ); perror( "genxx" ); exit(-1); } }
BOOL ProcessStructure( IN ULONG StrucIndex )
/*++
Routine Description:
Processes a single pair of structure definitions, 32-bit and 64-bit, respectively.
Processing includes generating a TYPE_REC and associated FIELD_RECs for the definition pair.
Arguments:
StrucIndex - Supplies the index into the array of STRUC_DEF structures found within each of the object images.
Return value:
TRUE if the processing was successful, FALSE otherwise (e.g. a terminating record was located).
--*/
{ PSTRUC_DEF Struc32, Struc64; PFIELD_DEF Field32, Field64;
ULONG strLen; ULONG strLen2; ULONG strLen3; PTYPE_REC typeRec; PFIELD_REC fieldRec; PFIELD_REC insertNode; BOOL only64;
ULONG index;
Struc32 = CalcPtr( Obj32.Definitions->Structures[ StrucIndex ] ); Struc64 = CalcPtr( Obj64.Definitions->Structures[ StrucIndex ] );
if (Struc64 == NULL) { return FALSE; }
if (Struc32 == NULL) { only64 = TRUE; } else { only64 = FALSE; }
CheckCondition( Struc64 != NULL && ((only64 != FALSE) || strcmp( Struc32->Name, Struc64->Name ) == 0), "Mismatched structure definitions found.\n" );
//
// Allocate and build a TYPE_REC for this STRUC_DEF
//
strLen = strlen( Struc64->Name ) + sizeof(char); typeRec = GetMem( sizeof(TYPE_REC) + strLen ); typeRec->Name = (PCHAR)(typeRec + 1); typeRec->Only64 = only64;
memcpy( typeRec->Name, Struc64->Name, strLen );
if (only64 == FALSE) { typeRec->Size32 = Struc32->Size; }
typeRec->Size64 = Struc64->Size; typeRec->FieldList = NULL; typeRec->SignExtend = FALSE; typeRec->Fabricated = FALSE;
//
// Create the FIELD_RECs hanging off of this type
//
index = 0; while (TRUE) {
if (only64 == FALSE) { Field32 = CalcPtr( Struc32->Fields[index] ); }
Field64 = CalcPtr( Struc64->Fields[index] );
if (Field64 == NULL) { break; }
if (only64 == FALSE) { CheckCondition( strcmp( Field32->Name, Field64->Name ) == 0 && strcmp( Field32->TypeName, Field64->TypeName ) == 0, "Mismatched structure definitions found.\n" ); }
strLen = strlen( Field64->Name ) + sizeof(CHAR); strLen2 = strlen( Field64->TypeName ) + sizeof(CHAR); strLen3 = strlen( Field64->SizeFormula ); if (strLen3 > 0) { strLen3 += sizeof(CHAR); }
fieldRec = GetMem( sizeof(FIELD_REC) + strLen + strLen2 + strLen3 ); fieldRec->Name = (PCHAR)(fieldRec + 1); fieldRec->TypeName = fieldRec->Name + strLen;
memcpy( fieldRec->Name, Field64->Name, strLen ); memcpy( fieldRec->TypeName, Field64->TypeName, strLen2 );
if (strLen3 > 0) { fieldRec->SizeFormula = fieldRec->TypeName + strLen2; memcpy( fieldRec->SizeFormula, Field64->SizeFormula, strLen3 ); } else { fieldRec->SizeFormula = NULL; }
if (only64 == FALSE) { fieldRec->Offset32 = Field32->Offset; fieldRec->Size32 = Field32->Size; fieldRec->TypeSize32 = Field32->TypeSize; }
fieldRec->Offset64 = Field64->Offset; fieldRec->TypeSize64 = Field64->TypeSize; fieldRec->Size64 = Field64->Size;
fieldRec->Next = NULL; fieldRec->TypeRec = NULL;
//
// Insert at the end of the list
//
insertNode = CONTAINING_RECORD( &typeRec->FieldList, FIELD_REC, Next ); while (insertNode->Next != NULL) { insertNode = insertNode->Next; } insertNode->Next = fieldRec;
index += 1; }
//
// Insert it into the global list
//
CheckCondition( FindTypeRec( typeRec->Name ) == NULL, "Duplicate definition for structure %s\n", typeRec->Name );
NewGlobalType( typeRec );
return TRUE; }
PTYPE_REC FindTypeRec( IN PCHAR Name )
/*++
Routine Description:
Searches the global list of TYPE_REC structures for one with a name that matches the supplied name.
Arguments:
Name - pointer to a null-terminated string representing the name of the sought type.
Return value:
A pointer to the matching TYPE_REC, or NULL if a match was not found.
--*/
{ PTYPE_REC typeRec;
typeRec = TypeRecList; while (typeRec != NULL) {
if (strcmp( Name, typeRec->Name ) == 0) { return typeRec; }
typeRec = typeRec->Next; } return NULL; }
PVOID GetMem( IN ULONG Size )
/*++
Routine Description:
Memory allocator. Works just like malloc() except that triggers a fatal error in the event of an out-of-memory condition.
Arguments:
Size - number of bytes to allocate.
Return value:
Returns a pointer to a block of memory of the specified size.
--*/
{ PVOID mem;
mem = malloc( Size ); CheckCondition( mem != NULL, "Out of memory.\n" );
return mem; }
VOID FabricateMissingTypes( VOID )
/*++
Routine Description:
Routine to generate TYPE_REC records for simple types referenced, but not defined, by a structure layout file.
Arguments:
None.
Return value:
None.
--*/
{ PTYPE_REC typeRec; PTYPE_REC fieldTypeRec; PFIELD_REC fieldRec; PCHAR fieldTypeName; ULONG strLen;
typeRec = TypeRecList; while (typeRec != NULL) {
fieldRec = typeRec->FieldList; while (fieldRec != NULL) {
fieldTypeRec = FindTypeRec( fieldRec->TypeName ); if (fieldTypeRec == NULL) {
if (typeRec->Only64 == FALSE) { CheckCondition( (fieldRec->Size32 == fieldRec->Size64) || ((fieldRec->Size32 == 1 || fieldRec->Size32 == 2 || fieldRec->Size32 == 4 || fieldRec->Size32 == 8) && (fieldRec->Size64 > fieldRec->Size32) && (fieldRec->Size64 % fieldRec->Size32 == 0)), "Must specify type %s (%s)\n", fieldRec->TypeName, typeRec->Name ); }
//
// No typerec exists for this type. Assume it is a simple
// type.
//
if ((typeRec->Only64 != FALSE && fieldRec->Size64 == sizeof(ULONGLONG) && *fieldRec->TypeName == 'P') ||
(fieldRec->Size32 == sizeof(PVOID) && fieldRec->Size64 == sizeof(ULONGLONG))) {
//
// Either a pointer or [U]LONG_PTR type. Make
// it longlong.
//
fieldTypeRec = &pointer64_typerec;
} else {
//
// Some other type.
//
strLen = strlen( fieldRec->TypeName ) + sizeof(CHAR); fieldTypeRec = GetMem( sizeof(TYPE_REC) + strLen ); fieldTypeRec->Name = (PCHAR)(fieldTypeRec + 1); memcpy( fieldTypeRec->Name, fieldRec->TypeName, strLen ); fieldTypeRec->Size32 = fieldRec->Size32; fieldTypeRec->Size64 = fieldRec->Size64; fieldTypeRec->FieldList = NULL; fieldTypeRec->SignExtend = TRUE; fieldTypeRec->Fabricated = TRUE;
NewGlobalType( fieldTypeRec ); }
} fieldRec->TypeRec = fieldTypeRec; fieldRec = fieldRec->Next; } typeRec = typeRec->Next; } }
VOID WriteCopyRecord( IN ULONG Offset32, IN ULONG Offset64, IN PCHAR TypeName, IN ULONG Size32, IN ULONG Size64, IN BOOL SignExtend, IN PCHAR FieldName, IN BOOL Last )
/*++
Routine Description:
Support routine to generate the text of a copy record.
Arguments:
Offset32 - Offset of this field within a 32-bit structure layout
Offset64 - Offset of this field within a 64-bit structure layout
Size32 - Size of this field within a 32-bit structure layout
Size64 - Size of this field within a 64-bit structure layout
SignExtend - Indicates whether this type should be sign extended or not
FieldName - Name of the field
Last - Whether this is the last copy record in a zero-terminated list
Return value:
None
--*/
{ CHAR buf[ 255 ];
if (SignExtend) { sprintf(buf,"IS_SIGNED_TYPE(%s)", TypeName); } else { sprintf(buf,"FALSE"); }
printf(" { \t0x%x, \t0x%x, \t0x%x, \t0x%x, \t%5s }%s\n", Offset32, Offset64, Size32, Size64, buf, Last ? "" : "," ); }
VOID WriteDefinition64( IN PTYPE_REC TypeRec )
/*++
Routine Description:
Generates a structure definition that represents, to a 32-bit compiler, the layout of a 64-bit structure.
Arguments:
TypeRec - Pointer to the TYPE_REC structure defining this type.
Return value:
None.
--*/
{ PFIELD_REC fieldRec; ULONG currentOffset; PTYPE_REC fieldTypeRec; ULONG padBytes; ULONG reservedCount;
currentOffset = 0; reservedCount = 0;
printf("typedef struct _%s_64 {\n", TypeRec->Name );
fieldRec = TypeRec->FieldList; while (fieldRec != NULL) {
fieldTypeRec = fieldRec->TypeRec; padBytes = fieldRec->Offset64 - currentOffset; if (padBytes > 0) {
printf(" UCHAR Reserved%d[ 0x%x ];\n", reservedCount, padBytes );
currentOffset += padBytes; reservedCount += 1; }
printf(" %s%s %s", fieldTypeRec->Name, fieldTypeRec->Fabricated ? "" : "_64", fieldRec->Name );
if (fieldRec->Size64 > fieldRec->TypeSize64) {
CheckCondition( fieldRec->Size64 % fieldRec->TypeSize64 == 0, "Internal error type %s.%s\n", TypeRec->Name, fieldRec->Name );
//
// This field must be an array
//
printf("[%d]", fieldRec->Size64 / fieldRec->TypeSize64); }
printf(";\n");
currentOffset += fieldRec->Size64;
fieldRec = fieldRec->Next; }
padBytes = TypeRec->Size64 - currentOffset; if (padBytes > 0) {
printf(" UCHAR Reserved%d[ 0x%x ];\n", reservedCount, padBytes ); currentOffset += padBytes; reservedCount += 1; }
printf("} %s_64, *P%s_64;\n\n", TypeRec->Name, TypeRec->Name );
fieldRec = TypeRec->FieldList; while (fieldRec != NULL) {
fieldTypeRec = fieldRec->TypeRec; printf("C_ASSERT( FIELD_OFFSET(%s_64,%s) == 0x%x);\n", TypeRec->Name, fieldRec->Name, fieldRec->Offset64);
fieldRec = fieldRec->Next; } printf("\n"); }
VOID WriteCopyList( IN PTYPE_REC TypeRec )
/*++
Routine Description:
Generates the list of copy records necessary to copy the contents of each of the fields with TypeRec from their 32-bit layout to their 64-bit layout.
Arguments:
TypeRec - Pointer to the TYPE_REC structure that defines this type.
Return value:
None.
--*/
{ PFIELD_REC fieldRec;
printf("COPY_REC cr3264_%s[] = {\n", TypeRec->Name);
WriteCopyListWorker( TypeRec, 0, 0, NULL );
WriteCopyRecord( 0,0,NULL,0,0,FALSE,NULL,TRUE ); printf("};\n\n"); }
VOID WriteCopyListWorker( IN PTYPE_REC TypeRec, IN ULONG Offset32, IN ULONG Offset64, IN PCHAR ParentName
)
/*++
Routine Description:
Recursively-called support routine for WriteCopyList. This routine generates a copy record if this type is not composed of child types, otherwise it calls itself recursively for each child type.
Arguments:
TypeRec - Pointer to the definition of the type to process.
Offset32 - Current offset within the master structure being defined.
Offset64 - Current offset within the master structure being defined.
ParentName - Not currently used.
Return value:
None.
--*/
{ PFIELD_REC fieldRec; PTYPE_REC typeRec; CHAR fieldName[ 255 ]; PCHAR fieldStart;
fieldRec = TypeRec->FieldList; if (fieldRec == NULL) {
WriteCopyRecord( Offset32, Offset64, TypeRec->Name, TypeRec->Size32, TypeRec->Size64, TypeRec->SignExtend, ParentName, FALSE ); } else {
//
// Build the field name
//
if (ParentName != NULL) { strcpy( fieldName, ParentName ); strcat( fieldName, "." ); } else { fieldName[0] = '\0'; } fieldStart = &fieldName[ strlen(fieldName) ];
do { strcpy( fieldStart, fieldRec->Name );
// typeRec = FindTypeRec( fieldRec->TypeName );
typeRec = fieldRec->TypeRec; WriteCopyListWorker( typeRec, fieldRec->Offset32 + Offset32, fieldRec->Offset64 + Offset64, fieldName ); fieldRec = fieldRec->Next; } while (fieldRec != NULL); } }
VOID WriteBufferCopies( IN PTYPE_REC TypeRec, IN PCHAR StrucName ) { PFIELD_REC fieldRec; PTYPE_REC typeRec; CHAR strucName[ 255 ]; CHAR sizeFormula[ 255 ]; PCHAR fieldPos; PCHAR src; PCHAR dst;
if (TypeRec == NULL) { return; }
strcpy(strucName,StrucName ); if (*StrucName != '\0') { strcat(strucName,"."); } fieldPos = &strucName[ strlen(strucName) ];
fieldRec = TypeRec->FieldList; while (fieldRec != NULL) {
strcpy(fieldPos,fieldRec->Name); if (fieldRec->SizeFormula != NULL) {
//
// Perform substitution on the size formula
//
dst = sizeFormula; src = fieldRec->SizeFormula; do { if (*src == '%' && *(src+1) == '1') {
dst += sprintf(dst, "Source->%s%s", StrucName, *StrucName == '\0' ? "" : "."); src += 2; } else { *dst++ = *src++; } } while (*src != '\0'); *dst = '\0';
printf("\n" " status = \n" " CopyBuf( Source->%s,\n" " &Destination->%s,\n" " %s );\n" " if (status != ESUCCESS) {\n" " return status;\n" " }\n", strucName, strucName, sizeFormula); }
typeRec = fieldRec->TypeRec; WriteBufferCopies( typeRec, strucName );
fieldRec = fieldRec->Next; } }
VOID WriteThunkSource( VOID )
/*++
Routine Description:
Generates the source code and supporting definitions necessary to copy all or portions of the contents of 32-bit structures to the equivalent 64-bit layout.
Arguments:
None.
Return value:
None.
--*/
{ PTYPE_REC typeRec;
printf("//\n"); printf("// Autogenerated file, do not edit\n"); printf("//\n\n");
printf("#include <bldrthnk.h>\n\n"); printf("#pragma warning(disable:4296)\n\n");
//
// Output the 64-bit type definitions
//
printf("#pragma pack(push,1)\n\n");
typeRec = TypeRecList; while (typeRec != NULL) {
if (typeRec->Fabricated == FALSE) { WriteDefinition64( typeRec ); }
typeRec = typeRec->Next; }
printf("#pragma pack(pop)\n\n");
//
// Output the copy records
//
typeRec = TypeRecList; while (typeRec != NULL) {
if (typeRec->Only64 == FALSE && typeRec->Fabricated == FALSE) { WriteCopyList( typeRec ); }
typeRec = typeRec->Next; }
//
// Generate the copy routines
//
typeRec = TypeRecList; while (typeRec != NULL) {
if (typeRec->Only64 == FALSE && typeRec->Fabricated == FALSE) { WriteCopyRoutine( typeRec ); }
typeRec = typeRec->Next; } printf("\n"); }
VOID WriteCopyRoutine( IN PTYPE_REC TypeRec )
/*++
Routine Description:
Generates text that implements a function to copy the contents of a structure of the specified type from a 32-bit layout to a 64-bit layout.
Arguments:
TypeRec - Pointer to the type for which the function should be generated.
Return value:
None.
--*/
{ PCHAR typeName;
typeName = TypeRec->Name;
printf("\n" "ARC_STATUS\n" "__inline\n" "static\n" "Copy_%s(\n" " IN %s *Source,\n" " OUT %s_64 *Destination\n" " )\n" "{\n" " ARC_STATUS status = ESUCCESS;" "\n" " DbgPrint(\"BLAMD64: Copy %s->%s_64 (0x%%08x->0x%%08x)\\n\",\n" " (ULONG)Source, (ULONG)Destination );\n" "\n" " CopyRec( Source, Destination, cr3264_%s );\n", typeName, typeName, typeName, typeName, typeName, typeName );
WriteBufferCopies( TypeRec, "" ); printf(" return status;\n"); printf("}\n\n"); }
VOID ApplyFixupsToImage( IN PCHAR ObjImage )
/*++
Routine Description:
Processes fixup records found within an object image.
Arguments:
Pointer to a buffer containing the entire image.
Return value:
None.
--*/
{ //
// Applies fixups to the OBJ image loaded at ObjImage
//
PIMAGE_FILE_HEADER fileHeader; PIMAGE_SECTION_HEADER sectionHeader; PIMAGE_SECTION_HEADER sectionHeaderArray; PIMAGE_SYMBOL symbolTable; PIMAGE_SYMBOL symbol; PIMAGE_RELOCATION reloc; PIMAGE_RELOCATION relocArray; ULONG sectionNum; ULONG relocNum; ULONG_PTR targetVa; PULONG_PTR fixupVa;
fileHeader = (PIMAGE_FILE_HEADER)ObjImage;
//
// We need the symbol table to apply the fixups
//
symbolTable = (PIMAGE_SYMBOL)(ObjImage + fileHeader->PointerToSymbolTable);
//
// Get a pointer to the first element in the section header
//
sectionHeaderArray = (PIMAGE_SECTION_HEADER)(ObjImage + sizeof( IMAGE_FILE_HEADER ) + fileHeader->SizeOfOptionalHeader);
//
// Apply the fixups for each section
//
for( sectionNum = 0; sectionNum < fileHeader->NumberOfSections; sectionNum++ ){
sectionHeader = §ionHeaderArray[ sectionNum ];
//
// Apply each fixup in this section
//
relocArray = (PIMAGE_RELOCATION)(ObjImage + sectionHeader->PointerToRelocations); for( relocNum = 0; relocNum < sectionHeader->NumberOfRelocations; relocNum++ ){
reloc = &relocArray[ relocNum ];
//
// The relocation gives us the position in the image of the
// relocation modification (VirtualAddress). To find out what
// to put there, we have to look the symbol up in the symbol index.
//
symbol = &symbolTable[ reloc->SymbolTableIndex ];
targetVa = sectionHeaderArray[ symbol->SectionNumber-1 ].PointerToRawData;
targetVa += symbol->Value; targetVa += (ULONG_PTR)ObjImage;
fixupVa = (PULONG_PTR)(ObjImage + reloc->VirtualAddress + sectionHeader->PointerToRawData );
*fixupVa = targetVa; } } }
VOID NewGlobalType( IN PTYPE_REC TypeRec )
/*++
Routine Description:
Inserts a new TYPE_REC structure at the end of the global TYPE_REC list.
Arguments:
TypeRec - Pointer to the TYPE_REC structure to insert.
Return value:
None.
--*/
{ PTYPE_REC insertNode;
insertNode = CONTAINING_RECORD( &TypeRecList, TYPE_REC, Next ); while (insertNode->Next != NULL) { insertNode = insertNode->Next; } insertNode->Next = TypeRec; TypeRec->Next = NULL; }
|