1374 lines
28 KiB
C
1374 lines
28 KiB
C
/*++
|
|
|
|
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;
|
|
}
|
|
|