/*++ | |
Copyright (c) 2004-2006 Intel Corporation. All rights reserved | |
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. | |
Module Name: | |
ZeroDebugData.c | |
Abstract: | |
Zero the Debug Data Fields of Portable Executable (PE) format file. | |
--*/ | |
#include <stdio.h> | |
#include <string.h> | |
#include <stdlib.h> | |
#define UTILITY_NAME "GenTEImage" | |
#define UTILITY_MAJOR_VERSION 0 | |
#define UTILITY_MINOR_VERSION 1 | |
void | |
Version ( | |
void | |
) | |
/*++ | |
Routine Description: | |
print version information for this utility | |
Arguments: | |
None | |
Returns: | |
None | |
--*/ | |
// GC_TODO: void - add argument and description to function comment | |
{ | |
// | |
// print usage of command | |
// | |
printf ("%s v%d.%d -Utility to zero the Debug Data Fields of Portable Executable (PE) format file.\n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION); | |
printf ("Copyright (c) 1999-2007 Intel Corporation. All rights reserved.\n"); | |
} | |
void | |
Usage ( | |
void | |
) | |
/*++ | |
Routine Description: | |
print usage of ZeroDebugData command | |
Arguments: | |
None | |
Returns: | |
None | |
--*/ | |
// GC_TODO: void - add argument and description to function comment | |
{ | |
Version(); | |
// | |
// print usage of command | |
// | |
printf ("\nUsage: ZeroDebugData <PE-File> [DebugData-File]\n"); | |
} | |
int | |
ReadFromFile ( | |
FILE *fp, | |
long offset, | |
void *buffer, | |
int size | |
) | |
/*++ | |
Routine Description: | |
read data from a specified location of file | |
Arguments: | |
fp - file pointer | |
offset - number of bytes from beginning of file | |
buffer - buffer used to store data | |
size - size of buffer | |
Returns: | |
= 0 - Success | |
= -1 - Failed | |
--*/ | |
{ | |
// | |
// set file pointer to the specified location of file | |
// | |
if (fseek (fp, offset, SEEK_SET) != 0) { | |
printf ("Error: Cannot move the current location of the file.\n"); | |
return -1; | |
} | |
// | |
// read data from the file | |
// | |
if (fread (buffer, size, 1, fp) != 1) { | |
printf ("Error: Cannot read data from the file.\n"); | |
return -1; | |
} | |
return 0; | |
} | |
int | |
ZeroDebugData ( | |
FILE *fp, | |
FILE *fpData | |
) | |
/*++ | |
Routine Description: | |
Zero the debug data fields of the file | |
Arguments: | |
fp - file pointer | |
fpData - pointer to output file that ZeroDebugData progress is written to | |
Returns: | |
= 0 - Success | |
= -1 - Failed | |
--*/ | |
{ | |
unsigned char header[4]; | |
unsigned long offset; | |
unsigned long NumberOfRvaAndSizes; | |
unsigned int nvalue; | |
unsigned long lvalue; | |
unsigned long Size; | |
unsigned long Pointer; | |
unsigned char *Buffer; | |
unsigned long Index; | |
// | |
// read the header of file | |
// | |
if (ReadFromFile (fp, 0, header, 2) != 0) { | |
printf ("Error: open image file\n"); | |
return -1; | |
} | |
// | |
// "MZ" -- the header of image file (PE) | |
// | |
if (strncmp ((char *) header, "MZ", 2) != 0) { | |
printf ("Error: Invalid Image file.\n"); | |
return -1; | |
} | |
// | |
// At location 0x3C, the stub has the file offset to the | |
// PE signature. | |
// | |
if (ReadFromFile (fp, 0x3C, &offset, 4) != 0) { | |
return -1; | |
} | |
// | |
// read the header of optional | |
// | |
if (ReadFromFile (fp, offset, header, 4) != 0) { | |
return -1; | |
} | |
// | |
// "PE\0\0" -- the signature of optional header | |
// | |
if (strncmp ((char *) header, "PE\0\0", 4) != 0) { | |
printf ("Error: Invalid PE format file.\n"); | |
return -1; | |
} | |
// | |
// Add 16 to skip COFF file header, and get to optional header. | |
// | |
offset += 24; | |
// | |
// Check the magic field, 0x10B for PE32 and 0x20B for PE32+ | |
// | |
if (ReadFromFile (fp, offset, &nvalue, 2) != 0) { | |
return -1; | |
} | |
// | |
// If this is PE32 image file, offset of NumberOfRvaAndSizes is 92. | |
// Else it is 108. | |
// | |
switch (nvalue & 0xFFFF) { | |
case 0x10B: | |
offset += 92; | |
printf ("Info: Image is PE32. "); | |
break; | |
case 0x20B: | |
offset += 108; | |
printf ("Info: Image is PE32+. "); | |
break; | |
default: | |
printf ("Error: Magic value is unknown.\n"); | |
return -1; | |
} | |
// | |
// get the value of NumberOfRvaAndSizes | |
// | |
if (ReadFromFile (fp, offset, &NumberOfRvaAndSizes, 4) != 0) { | |
printf ("Error: read NumberOfRvaAndSizes error.\n"); | |
return -1; | |
} | |
// | |
// printf ("Info: NumberOfRvaAndSizes = %d\n", NumberOfRvaAndSizes); | |
// | |
// | |
// Finding Debug Table, offset of Debug Table | |
// is 4 + 6 * 8 = 52. | |
// | |
if (NumberOfRvaAndSizes >= 7) { | |
if (ReadFromFile (fp, offset + 52, &lvalue, 4) != 0) { | |
return -1; | |
} | |
// | |
// Read the SizeOfData(16) and PointerToRawData(24) | |
// | |
if (ReadFromFile (fp, lvalue + 16, &Size, 4) != 0) { | |
printf ("error: Size = %d\n", Size); | |
return -1; | |
} | |
printf ("Debug data: size = %xh, ", Size); | |
fprintf (fpData, "Debug data: size = %xh, ", Size); | |
if (ReadFromFile (fp, lvalue + 20, &Pointer, 4) != 0) { | |
printf ("error: LoadOffset = %xh\n", Pointer); | |
return -1; | |
} | |
// | |
// printf ("LoadOffset = %xh, ", Pointer); | |
// | |
fprintf (fpData, "LoadOffset = %xh, ", Pointer); | |
if (ReadFromFile (fp, lvalue + 24, &Pointer, 4) != 0) { | |
printf ("error: FileOffset = %xh\n", Pointer); | |
return -1; | |
} | |
printf ("FileOffset = %xh, ", Pointer); | |
fprintf (fpData, "FileOffset = %xh, \n", Pointer); | |
if ((lvalue != 0) && (Pointer != 0)) { | |
// | |
// prepare buffer | |
// | |
Buffer = malloc (Size + 1); | |
if (Buffer == NULL) { | |
printf ("Error: Cannot allocate memory.\n"); | |
return -1; | |
} | |
// | |
// set file pointer to the specified location of file | |
// | |
if (fseek (fp, Pointer, SEEK_SET) != 0) { | |
printf ("Error: Cannot move the current location of the file.\n"); | |
free (Buffer); | |
return -1; | |
} | |
// | |
// read data from PE file | |
// | |
if (fread (Buffer, Size, 1, fp) != 1) { | |
printf ("Error: Cannot read data from the file.\n"); | |
free (Buffer); | |
return -1; | |
} | |
// | |
// write to data file | |
// | |
for (Index = 0; Index < Size;) { | |
fprintf (fpData, "%02x ", Buffer[Index]); | |
Index++; | |
if (Index % 8 == 0) { | |
fprintf (fpData, "\n"); | |
} | |
} | |
fprintf (fpData, "\n"); | |
// | |
// zero buffer and write back to PE file | |
// | |
if (fseek (fp, Pointer, SEEK_SET) != 0) { | |
printf ("Error: Cannot move the current location of the file.\n"); | |
free (Buffer); | |
return -1; | |
} | |
memset (Buffer, 0, Size); | |
if (fwrite (Buffer, Size, 1, fp) != 1) { | |
perror ("Error: Cannot write zero to the file.\n"); | |
free (Buffer); | |
return -1; | |
} | |
// | |
// set file pointer to the specified location of file | |
// | |
if (fseek (fp, lvalue + 4, SEEK_SET) != 0) { | |
printf ("Error: Cannot move the current location of the file.\n"); | |
free (Buffer); | |
return -1; | |
} | |
if (fwrite (Buffer, 4, 1, fp) != 1) { | |
perror ("Error: Cannot write zero to the file.\n"); | |
free (Buffer); | |
return -1; | |
} | |
free (Buffer); | |
} | |
} | |
return 0; | |
} | |
int | |
main ( | |
int argc, | |
char *argv[] | |
) | |
/*++ | |
Routine Description: | |
Prints the zero debug data of the PE file to the DebugData file. | |
Executes the ZeroDebugData function. | |
Arguments: | |
argc - Standard C argument, number of command line arguments. | |
argv[] - Standard C argument, array of pointers to the input files, | |
such as the PE and DebugData files. | |
Returns: | |
zero - success | |
nonzero - failure | |
--*/ | |
{ | |
FILE *fp; | |
FILE *fpData; | |
char DataFile[1024] = ""; | |
if (argc == 1) { | |
Usage(); | |
return -1; | |
} | |
if ((strcmp(argv[1], "-h") == 0) || (strcmp(argv[1], "--help") == 0) || | |
(strcmp(argv[1], "-?") == 0) || (strcmp(argv[1], "/?") == 0)) { | |
Usage(); | |
return -1; | |
} | |
if ((strcmp(argv[1], "-V") == 0) || (strcmp(argv[1], "--version") == 0)) { | |
Version(); | |
return -1; | |
} | |
if (argc == 2) { | |
Usage(); | |
return -1; | |
} | |
// | |
// open the DebugData file, if not exists, return | |
// | |
if (argc >= 3) { | |
strcpy (DataFile, argv[2]); | |
} else { | |
strcpy (DataFile, "DebugData.dat"); | |
} | |
fpData = fopen (DataFile, "a+"); | |
if (fpData == NULL) { | |
fpData = fopen (DataFile, "w"); | |
if (fpData == NULL) { | |
printf ("Error: Cannot open the data file!\n"); | |
return -1; | |
} | |
} | |
// | |
// open the PE file | |
// | |
fp = fopen (argv[1], "r+b"); | |
if (fp == NULL) { | |
printf ("Error: Cannot open the PE file!\n"); | |
return -1; | |
} | |
// | |
// Zero the Debug Data to the PE file | |
// | |
printf ("Zero Debug Data to file %s:\n", argv[1]); | |
fprintf (fpData, "\nZero Debug Data to file %s:\n", argv[1]); | |
if ((int *) ZeroDebugData (fp, fpData) != 0) { | |
printf ("Error: Zero Debug Data PE file\n"); | |
fclose (fp); | |
return -1; | |
} | |
printf (" success\n"); | |
// | |
// close the PE file | |
// | |
fflush (fpData); | |
fflush (fp); | |
fclose (fpData); | |
fclose (fp); | |
return 0; | |
} |