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.
491 lines
13 KiB
491 lines
13 KiB
/*
|
|
This
|
|
is a place to hang .obj file munging
|
|
currently it only offers the ability to do simple renaming of symbol
|
|
names .obj files. It cannot lengthen symbol names.
|
|
|
|
Jay Krell
|
|
December 19, 2001
|
|
*/
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <ctype.h>
|
|
#include "windows.h"
|
|
#define NUMBER_OF(x) (sizeof(x)/sizeof((x)[0]))
|
|
|
|
#define GetStdout() stdout
|
|
#define GetStdin() stdin
|
|
#define GetStderr() stderr
|
|
|
|
void Usage(char * argv0)
|
|
{
|
|
char * upper;
|
|
char * argv0base1;
|
|
char * argv0base2;
|
|
char * argv0base;
|
|
|
|
argv0base1 = strrchr(argv0, '\\');
|
|
argv0base2 = strrchr(argv0, '/');
|
|
argv0base = (argv0base1 > argv0base2) ? argv0base1 : argv0base2;
|
|
argv0base += (*argv0base == '\\' || *argv0base == '/');
|
|
|
|
upper = _strdup(argv0base);
|
|
if (upper != NULL)
|
|
_strupr(upper);
|
|
else
|
|
upper = argv0;
|
|
printf(
|
|
"%s: usage: %s SymbolRename Objfile From To\n"
|
|
"%s:\n"
|
|
"%s: To must not be longer than From\n",
|
|
upper, argv0, upper, upper, upper
|
|
);
|
|
if (upper != argv0)
|
|
free(upper);
|
|
}
|
|
|
|
BOOL MyIsHandleValid(HANDLE Handle)
|
|
{
|
|
return (Handle != NULL && Handle != INVALID_HANDLE_VALUE);
|
|
}
|
|
|
|
void MyFindClose(HANDLE * Handle)
|
|
{
|
|
HANDLE Local;
|
|
|
|
Local = *Handle;
|
|
*Handle = NULL;
|
|
if (MyIsHandleValid(Local))
|
|
FindClose(Local);
|
|
}
|
|
|
|
void MyUnmapViewOfFile(HANDLE * Handle)
|
|
{
|
|
HANDLE Local;
|
|
|
|
Local = *Handle;
|
|
*Handle = NULL;
|
|
if (MyIsHandleValid(Local))
|
|
UnmapViewOfFile(Local);
|
|
}
|
|
|
|
void
|
|
__cdecl
|
|
Error(
|
|
const char * Format,
|
|
...
|
|
)
|
|
{
|
|
va_list Args;
|
|
|
|
va_start(Args, Format);
|
|
vfprintf(GetStderr(), Format, Args);
|
|
va_end(Args);
|
|
}
|
|
|
|
#define Warning Error
|
|
|
|
void MyCloseHandle(HANDLE * Handle)
|
|
{
|
|
HANDLE Local;
|
|
|
|
Local = *Handle;
|
|
*Handle = NULL;
|
|
if (MyIsHandleValid(Local))
|
|
CloseHandle(Local);
|
|
}
|
|
|
|
typedef struct _OBJFILE {
|
|
PCSTR FileName;
|
|
HANDLE FileHandle;
|
|
HANDLE FileMappingHandle;
|
|
PVOID VoidViewBase;
|
|
PBYTE ByteViewBase;
|
|
PIMAGE_FILE_HEADER ImageFileHeader;
|
|
ULONG Machine;
|
|
BOOL IsMachineKnown;
|
|
ULONG FileOffsetToSymbolTable;
|
|
PIMAGE_SYMBOL SymbolTable;
|
|
ULONG NumberOfSymbols;
|
|
PSTR StringTable;
|
|
ULONG StringTableSize;
|
|
} OBJFILE, *POBJFILE;
|
|
|
|
|
|
BOOL
|
|
ObjfileIsMachineKnown(
|
|
ULONG Machine
|
|
)
|
|
{
|
|
switch (Machine)
|
|
{
|
|
default:
|
|
return FALSE;
|
|
case IMAGE_FILE_MACHINE_UNKNOWN:
|
|
case IMAGE_FILE_MACHINE_I386:
|
|
case IMAGE_FILE_MACHINE_R3000:
|
|
case IMAGE_FILE_MACHINE_R4000:
|
|
case IMAGE_FILE_MACHINE_R10000:
|
|
case IMAGE_FILE_MACHINE_WCEMIPSV2:
|
|
case IMAGE_FILE_MACHINE_ALPHA:
|
|
case IMAGE_FILE_MACHINE_SH3:
|
|
case IMAGE_FILE_MACHINE_SH3DSP:
|
|
case IMAGE_FILE_MACHINE_SH3E:
|
|
case IMAGE_FILE_MACHINE_SH4:
|
|
case IMAGE_FILE_MACHINE_SH5:
|
|
case IMAGE_FILE_MACHINE_ARM:
|
|
case IMAGE_FILE_MACHINE_THUMB:
|
|
case IMAGE_FILE_MACHINE_AM33:
|
|
case IMAGE_FILE_MACHINE_POWERPC:
|
|
case IMAGE_FILE_MACHINE_POWERPCFP:
|
|
case IMAGE_FILE_MACHINE_IA64:
|
|
case IMAGE_FILE_MACHINE_MIPS16:
|
|
case IMAGE_FILE_MACHINE_ALPHA64:
|
|
case IMAGE_FILE_MACHINE_MIPSFPU:
|
|
case IMAGE_FILE_MACHINE_MIPSFPU16:
|
|
//case IMAGE_FILE_MACHINE_AXP64:
|
|
case IMAGE_FILE_MACHINE_TRICORE:
|
|
case IMAGE_FILE_MACHINE_CEF:
|
|
case IMAGE_FILE_MACHINE_EBC:
|
|
case IMAGE_FILE_MACHINE_AMD64:
|
|
case IMAGE_FILE_MACHINE_M32R:
|
|
case IMAGE_FILE_MACHINE_CEE:
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
BOOL CloseObjfile(POBJFILE Objfile)
|
|
{
|
|
BOOL Success = FALSE;
|
|
|
|
if (!Objfile)
|
|
goto Exit;
|
|
|
|
Objfile->FileName;
|
|
MyCloseHandle(&Objfile->FileHandle);
|
|
MyCloseHandle(&Objfile->FileMappingHandle);
|
|
MyUnmapViewOfFile(&Objfile->VoidViewBase);
|
|
ZeroMemory(Objfile, sizeof(*Objfile));
|
|
|
|
Success = TRUE;
|
|
Exit:
|
|
return Success;
|
|
}
|
|
|
|
BOOL OpenObjfile(PCSTR FileName, POBJFILE Objfile)
|
|
{
|
|
const static char Function[] = __FUNCTION__;
|
|
ULONG LastWin32Error;
|
|
BOOL Success = FALSE;
|
|
|
|
if (!FileName)
|
|
goto Exit;
|
|
if (!Objfile)
|
|
goto Exit;
|
|
|
|
Objfile->FileName = FileName;
|
|
|
|
Objfile->FileHandle = CreateFile(
|
|
FileName,
|
|
GENERIC_READ | GENERIC_WRITE,
|
|
0,
|
|
NULL,
|
|
OPEN_EXISTING,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
NULL);
|
|
if (!MyIsHandleValid(Objfile->FileHandle))
|
|
{
|
|
LastWin32Error = GetLastError();
|
|
Error("%s: CreateFile(%s, GENERIC_WRITE, OPEN_EXISTING) 0x%lx\n", Function, FileName, LastWin32Error);
|
|
goto Exit;
|
|
}
|
|
Objfile->FileMappingHandle = CreateFileMapping(
|
|
Objfile->FileHandle, NULL, PAGE_READWRITE, 0, 0, NULL);
|
|
if (!MyIsHandleValid(Objfile->FileMappingHandle))
|
|
{
|
|
LastWin32Error = GetLastError();
|
|
Error("%s: CreateFileMapping(%s) 0x%lx\n", Function, FileName, LastWin32Error);
|
|
goto Exit;
|
|
}
|
|
Objfile->VoidViewBase = MapViewOfFile(Objfile->FileMappingHandle, FILE_MAP_WRITE, 0, 0, 0);
|
|
Objfile->ByteViewBase = (PBYTE)Objfile->VoidViewBase;
|
|
if (!MyIsHandleValid(Objfile->VoidViewBase))
|
|
{
|
|
LastWin32Error = GetLastError();
|
|
Error("%s MapViewOfFile(%s) 0x%lx\n", Function, FileName, LastWin32Error);
|
|
goto Exit;
|
|
}
|
|
Objfile->ImageFileHeader = (PIMAGE_FILE_HEADER)Objfile->VoidViewBase;
|
|
Objfile->Machine = Objfile->ImageFileHeader->Machine;
|
|
Objfile->IsMachineKnown = ObjfileIsMachineKnown(Objfile->Machine);
|
|
if (!Objfile->IsMachineKnown)
|
|
{
|
|
Warning("%s: Unknown machine 0x%lx, processing file anyway..\n", Function, Objfile->Machine);
|
|
}
|
|
else if (Objfile->Machine == IMAGE_FILE_MACHINE_UNKNOWN)
|
|
{
|
|
Error("%s: 'anon' .obj file ignored\n", Function);
|
|
goto Exit;
|
|
}
|
|
Objfile->FileOffsetToSymbolTable = Objfile->ImageFileHeader->PointerToSymbolTable;
|
|
Objfile->NumberOfSymbols = Objfile->ImageFileHeader->NumberOfSymbols;
|
|
if (Objfile->FileOffsetToSymbolTable == 0)
|
|
{
|
|
Error("%s: file %s, PointerToSymbolTable == 0, no symbols, ignoring\n", Function, FileName);
|
|
goto Exit;
|
|
}
|
|
if (Objfile->NumberOfSymbols == 0)
|
|
{
|
|
Error("%s: file %s, NumberOfSymbols == 0, no symbols, ignoring\n", Function, FileName);
|
|
goto Exit;
|
|
}
|
|
Objfile->SymbolTable = (PIMAGE_SYMBOL)(Objfile->ByteViewBase + Objfile->FileOffsetToSymbolTable);
|
|
Objfile->StringTable = (PSTR)(Objfile->SymbolTable + Objfile->NumberOfSymbols);
|
|
Objfile->StringTableSize = *(PULONG)Objfile->StringTable;
|
|
Success = TRUE;
|
|
Exit:
|
|
if (!Success)
|
|
{
|
|
CloseObjfile(Objfile);
|
|
}
|
|
return Success;
|
|
}
|
|
|
|
typedef struct _OBJFILE_SYMBOL {
|
|
ULONG Index;
|
|
PIMAGE_SYMBOL ImageSymbol;
|
|
PSTR Name; /* never NULL */
|
|
size_t NameLength;
|
|
BOOL IsShort;
|
|
ULONG UNALIGNED * PointerToOffsetToLongName; /* may be 0 */
|
|
ULONG OffsetToLongName; /* may be 0 */
|
|
PSTR PointerToLongNameStorage; /* may be NULL */
|
|
PSTR PointerToShortNameStorage; /* never NULL */
|
|
} OBJFILE_SYMBOL, *POBJFILE_SYMBOL;
|
|
|
|
BOOL
|
|
ObjfileResolveSymbol(
|
|
POBJFILE Objfile,
|
|
ULONG Index,
|
|
POBJFILE_SYMBOL OutSymbol
|
|
)
|
|
{
|
|
const static char Function[] = __FUNCTION__;
|
|
BOOL Success = FALSE;
|
|
OBJFILE_SYMBOL Symbol = { 0 };
|
|
|
|
if (!Objfile)
|
|
goto Exit;
|
|
if (!OutSymbol)
|
|
goto Exit;
|
|
|
|
*OutSymbol = Symbol;
|
|
|
|
if (Index >= Objfile->NumberOfSymbols)
|
|
{
|
|
Warning("%s: file %s, SymbolIndex >= NumberOfSymbols (0x%lx, 0x%lx)\n",
|
|
Function,
|
|
Objfile->FileName,
|
|
Index,
|
|
Objfile->NumberOfSymbols
|
|
);
|
|
goto Exit;
|
|
}
|
|
|
|
Symbol.Index = Index;
|
|
Symbol.ImageSymbol = &Objfile->SymbolTable[Index];
|
|
Symbol.PointerToShortNameStorage = (PSTR)Symbol.ImageSymbol->N.ShortName;
|
|
if (Symbol.ImageSymbol->N.Name.Short)
|
|
{
|
|
for ( ;
|
|
Symbol.NameLength != IMAGE_SIZEOF_SHORT_NAME ;
|
|
++Symbol.NameLength
|
|
)
|
|
{
|
|
if (Symbol.PointerToShortNameStorage[Symbol.NameLength] == 0)
|
|
break;
|
|
}
|
|
Symbol.Name = Symbol.PointerToShortNameStorage;
|
|
Symbol.IsShort = TRUE;
|
|
}
|
|
else
|
|
{
|
|
Symbol.PointerToOffsetToLongName = &Symbol.ImageSymbol->N.Name.Long;
|
|
Symbol.OffsetToLongName = *Symbol.PointerToOffsetToLongName;
|
|
if (Symbol.OffsetToLongName >= Objfile->StringTableSize)
|
|
{
|
|
Warning("%s: file %s, OffsetToLongName >= StringTableSize (0x%lx, 0x%lx)\n",
|
|
Function,
|
|
Objfile->FileName,
|
|
Symbol.OffsetToLongName,
|
|
Objfile->StringTableSize
|
|
);
|
|
goto Exit;
|
|
}
|
|
Symbol.Name = (Objfile->StringTable + Symbol.OffsetToLongName);
|
|
Symbol.PointerToLongNameStorage = Symbol.Name;
|
|
Symbol.NameLength = strlen(Symbol.Name);
|
|
}
|
|
*OutSymbol = Symbol;
|
|
Success = TRUE;
|
|
Exit:
|
|
return Success;
|
|
}
|
|
|
|
BOOL
|
|
ObjfileSetSymbolName(
|
|
POBJFILE Objfile,
|
|
POBJFILE_SYMBOL Symbol,
|
|
PCSTR NewSymbolName
|
|
)
|
|
{
|
|
const static char Function[] = __FUNCTION__;
|
|
PIMAGE_SYMBOL ImageSymbol;
|
|
size_t i;
|
|
BOOL Success = FALSE;
|
|
|
|
if (!Objfile)
|
|
goto Exit;
|
|
if (!Symbol)
|
|
goto Exit;
|
|
if (!NewSymbolName)
|
|
goto Exit;
|
|
|
|
ImageSymbol = Symbol->ImageSymbol;
|
|
i = strlen(NewSymbolName);
|
|
if (i <= IMAGE_SIZEOF_SHORT_NAME)
|
|
{
|
|
//
|
|
// we abandon the string table entry if there was one.
|
|
//
|
|
memmove(Symbol->PointerToShortNameStorage, NewSymbolName, i);
|
|
ZeroMemory(Symbol->PointerToShortNameStorage + i, IMAGE_SIZEOF_SHORT_NAME - i);
|
|
}
|
|
else if (!Symbol->IsShort && i <= Symbol->NameLength)
|
|
{
|
|
//
|
|
// like
|
|
// \0\reallylonglonglong\0
|
|
// -> \0\lesslonglong\0long\0
|
|
//
|
|
memmove(Symbol->PointerToLongNameStorage, NewSymbolName, i);
|
|
Symbol->PointerToLongNameStorage[i] = 0;
|
|
}
|
|
else
|
|
{
|
|
Warning("%s: objfile %s, new symbol does not fit over old symbol (%s, %*s)\n",
|
|
Function,
|
|
Objfile->FileName,
|
|
NewSymbolName,
|
|
(int)Symbol->NameLength,
|
|
Symbol->Name
|
|
);
|
|
goto Exit;
|
|
}
|
|
Success = TRUE;
|
|
Exit:
|
|
return Success;
|
|
}
|
|
|
|
BOOL
|
|
SymbolRename(
|
|
PCSTR ObjfileName,
|
|
PCSTR From,
|
|
PCSTR To,
|
|
PULONG NumberFound
|
|
)
|
|
{
|
|
const static char Function[] = __FUNCTION__;
|
|
OBJFILE Objfile = { 0 };
|
|
ULONG SymbolIndex;
|
|
OBJFILE_SYMBOL Symbol = { 0 };
|
|
size_t FromLength;
|
|
BOOL Success = FALSE;
|
|
|
|
if (NumberFound == NULL)
|
|
goto Exit;
|
|
|
|
*NumberFound = 0;
|
|
|
|
if (!OpenObjfile(ObjfileName, &Objfile))
|
|
goto Exit;
|
|
|
|
FromLength = strlen(From);
|
|
|
|
for ( SymbolIndex = 0 ;
|
|
SymbolIndex != Objfile.NumberOfSymbols ;
|
|
SymbolIndex += 1 + Symbol.ImageSymbol->NumberOfAuxSymbols
|
|
)
|
|
{
|
|
if (!ObjfileResolveSymbol(&Objfile, SymbolIndex, &Symbol))
|
|
goto Exit;
|
|
if (FromLength == Symbol.NameLength
|
|
&& memcmp(From, Symbol.Name, FromLength) == 0)
|
|
{
|
|
if (*NumberFound != 0)
|
|
{
|
|
Warning("%s: objfile %s, multiple symbols with same name found (%s)\n",
|
|
Function,
|
|
Objfile.FileName,
|
|
From
|
|
);
|
|
}
|
|
|
|
*NumberFound += 1;
|
|
|
|
if (!ObjfileSetSymbolName(&Objfile, &Symbol, To))
|
|
goto Exit;
|
|
|
|
}
|
|
}
|
|
Success = TRUE;
|
|
Exit:
|
|
CloseObjfile(&Objfile);
|
|
return Success;
|
|
}
|
|
|
|
void Objtool(int argc, char ** argv)
|
|
{
|
|
const static char Function[] = __FUNCTION__;
|
|
PCSTR From;
|
|
PCSTR To;
|
|
PCSTR ObjfileName;
|
|
ULONG NumberFound = 0;
|
|
int i;
|
|
const char * symren[] =
|
|
{ "symren", "symrename", "symbolrename", "symbolren" };
|
|
|
|
if (argc < 2)
|
|
{
|
|
Usage(argv[0]);
|
|
return;
|
|
}
|
|
|
|
argv[1] += (argv[1][0] == '-' || argv[1][0] == '/');
|
|
for (i = 0 ; i != NUMBER_OF(symren) ; ++i)
|
|
{
|
|
if (_stricmp(argv[1], symren[i]) == 0)
|
|
{
|
|
if (
|
|
(ObjfileName = argv[2]) == NULL
|
|
|| (From = argv[3]) == NULL
|
|
|| (To = argv[4]) == NULL
|
|
|| strlen(To) > strlen(From)
|
|
)
|
|
{
|
|
Usage(argv[0]);
|
|
return;
|
|
}
|
|
SymbolRename(ObjfileName, From, To, &NumberFound);
|
|
return;
|
|
}
|
|
}
|
|
Usage(argv[0]);
|
|
}
|
|
|
|
int __cdecl main(int argc, char ** argv)
|
|
{
|
|
Objtool(argc, argv);
|
|
return 0;
|
|
}
|