mirror of
https://github.com/reactos/reactos.git
synced 2024-09-27 21:16:34 +00:00
[CREATESPEC]
- Implement retrieving export names from forwarders - Add error() function to print errors - Refactor image/symbol loading - Fix some bugs and add some hacks, so that it compiles in out tree - Add to build svn path=/trunk/; revision=70569
This commit is contained in:
parent
3c1003aaf5
commit
1c0099452e
|
@ -1,4 +1,5 @@
|
|||
add_subdirectory(bootvid_font_generator)
|
||||
add_subdirectory(createspec)
|
||||
add_subdirectory(gdb2)
|
||||
add_subdirectory(gdihv)
|
||||
add_subdirectory(genguid)
|
||||
|
|
|
@ -8,18 +8,31 @@
|
|||
- Resolve forwarders
|
||||
|
||||
*/
|
||||
#define MINGW_HAS_SECURE_API
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <windows.h>
|
||||
|
||||
#ifdef __REACTOS__
|
||||
#include <dbghelp.h>
|
||||
#include <cvconst.h>
|
||||
|
||||
// dirty hacks!
|
||||
#define sprintf_s(dst, size, format, ...) sprintf(dst, format, __VA_ARGS__)
|
||||
#define vsprintf_s(dst, size, format, ap) vsprintf(dst, format, ap)
|
||||
#define fopen_s(pfile, name, mode) ((*pfile = fopen(name, mode)), (*pfile != 0) ? 0 : -1)
|
||||
#define strcpy_s(dst, size, src) strncpy(dst, src, size)
|
||||
#define strcat_s(dst, size, src) strncat(dst, src, size)
|
||||
|
||||
#else
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable:4091)
|
||||
#endif
|
||||
#define _NO_CVCONST_H
|
||||
#include <dbghelp.h>
|
||||
|
||||
// doesn't seem to be defined anywhere
|
||||
enum BasicType {
|
||||
// This is from cvconst.h, but win sdk lacks this file
|
||||
enum BasicType {
|
||||
btNoType = 0,
|
||||
btVoid = 1,
|
||||
btChar = 2,
|
||||
|
@ -40,7 +53,7 @@ enum BasicType {
|
|||
btHresult = 31
|
||||
};
|
||||
|
||||
typedef enum CV_call_e {
|
||||
typedef enum CV_call_e {
|
||||
CV_CALL_NEAR_C = 0x00,
|
||||
CV_CALL_NEAR_FAST = 0x04,
|
||||
CV_CALL_NEAR_STD = 0x07,
|
||||
|
@ -49,13 +62,21 @@ typedef enum CV_call_e {
|
|||
CV_CALL_CLRCALL = 0x16
|
||||
} CV_call_e;
|
||||
|
||||
#define MAX_SYMBOL_NAME 1024
|
||||
#endif // __REACTOS__
|
||||
|
||||
#define MAX_SYMBOL_NAME 1024
|
||||
typedef struct _SYMINFO_EX
|
||||
{
|
||||
SYMBOL_INFO si;
|
||||
CHAR achName[MAX_SYMBOL_NAME];
|
||||
} SYMINFO_EX;
|
||||
|
||||
typedef struct _SYMBOL64_EX
|
||||
{
|
||||
IMAGEHLP_SYMBOL64 sym64;
|
||||
CHAR achName[MAX_SYMBOL_NAME];
|
||||
} SYMBOL64_EX, *PSYMBOL64_EX;
|
||||
|
||||
typedef enum _PARAM_TYPES
|
||||
{
|
||||
TYPE_NONE,
|
||||
|
@ -99,57 +120,203 @@ typedef struct _EXPORT_DATA
|
|||
} EXPORT_DATA, *PEXPORT_DATA;
|
||||
|
||||
HANDLE ghProcess;
|
||||
CHAR gszModuleFileName[MAX_PATH+1];
|
||||
|
||||
HRESULT
|
||||
OpenFileFromName(
|
||||
_In_ PCSTR pszDllName,
|
||||
_Out_ PHANDLE phFile)
|
||||
void
|
||||
error(
|
||||
_In_ const char* pszFormat,
|
||||
...)
|
||||
{
|
||||
HANDLE hFile;
|
||||
CHAR szBuffer[512];
|
||||
SIZE_T cchBuffer;
|
||||
DWORD dwLastError;
|
||||
va_list argptr;
|
||||
|
||||
/* Try current directory */
|
||||
GetCurrentDirectoryA(MAX_PATH, gszModuleFileName);
|
||||
strcat_s(gszModuleFileName, sizeof(gszModuleFileName), "\\");
|
||||
strcat_s(gszModuleFileName, sizeof(gszModuleFileName), pszDllName);
|
||||
hFile = CreateFileA(gszModuleFileName,
|
||||
FILE_READ_DATA,
|
||||
FILE_SHARE_READ,
|
||||
NULL,
|
||||
OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
NULL);
|
||||
if (hFile != INVALID_HANDLE_VALUE)
|
||||
/* Get last error */
|
||||
dwLastError = GetLastError();
|
||||
|
||||
va_start(argptr, pszFormat);
|
||||
cchBuffer = vsprintf_s(szBuffer, sizeof(szBuffer), pszFormat, argptr);
|
||||
va_end(argptr);
|
||||
|
||||
/* Strip trailing newlines */
|
||||
_Analysis_assume_(cchBuffer < sizeof(szBuffer));
|
||||
while ((cchBuffer >= 1) &&
|
||||
((szBuffer[cchBuffer - 1] == '\r') ||
|
||||
(szBuffer[cchBuffer - 1] == '\n')))
|
||||
{
|
||||
*phFile = hFile;
|
||||
return S_OK;
|
||||
szBuffer[cchBuffer - 1] = '\0';
|
||||
cchBuffer--;
|
||||
}
|
||||
|
||||
/* Try system32 directory */
|
||||
strcat_s(gszModuleFileName, sizeof(gszModuleFileName), "%systemroot%\\system32\\");
|
||||
strcat_s(gszModuleFileName, sizeof(gszModuleFileName), pszDllName);
|
||||
hFile = CreateFileA(gszModuleFileName,
|
||||
FILE_READ_DATA,
|
||||
FILE_SHARE_READ,
|
||||
NULL,
|
||||
OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
NULL);
|
||||
if (hFile != INVALID_HANDLE_VALUE)
|
||||
/* Check if we have an error */
|
||||
if (dwLastError != ERROR_SUCCESS)
|
||||
{
|
||||
*phFile = hFile;
|
||||
return S_OK;
|
||||
/* Append error code */
|
||||
cchBuffer += sprintf_s(szBuffer + cchBuffer,
|
||||
sizeof(szBuffer) - cchBuffer,
|
||||
" [error %lu: ", dwLastError);
|
||||
|
||||
/* Format the last error code */
|
||||
cchBuffer += FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM,
|
||||
NULL,
|
||||
dwLastError,
|
||||
0,
|
||||
szBuffer + cchBuffer,
|
||||
(DWORD)(sizeof(szBuffer) - cchBuffer),
|
||||
NULL);
|
||||
|
||||
/* Strip trailing newlines */
|
||||
_Analysis_assume_(cchBuffer < sizeof(szBuffer));
|
||||
while ((cchBuffer >= 1) &&
|
||||
((szBuffer[cchBuffer - 1] == '\r') ||
|
||||
(szBuffer[cchBuffer - 1] == '\n')))
|
||||
{
|
||||
szBuffer[cchBuffer - 1] = '\0';
|
||||
cchBuffer--;
|
||||
}
|
||||
|
||||
fprintf(stderr, "%s]\n", szBuffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "%s\n", szBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
BOOL
|
||||
InitDbgHelp(
|
||||
VOID)
|
||||
{
|
||||
static const char *pszMsSymbolServer = "srv**symbols*http://msdl.microsoft.com/download/symbols";
|
||||
DWORD Options;
|
||||
|
||||
/* Save current process ;-) */
|
||||
ghProcess = GetCurrentProcess();
|
||||
|
||||
/* Initialize dbghelp */
|
||||
if (!SymInitialize(ghProcess, 0, FALSE))
|
||||
{
|
||||
error("SymInitialize() failed.");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return HRESULT_FROM_WIN32(GetLastError());
|
||||
/* Set options */
|
||||
Options = SymGetOptions();
|
||||
Options |= SYMOPT_ALLOW_ABSOLUTE_SYMBOLS | SYMOPT_INCLUDE_32BIT_MODULES | SYMOPT_DEBUG;// | SYMOPT_NO_PROMPTS;
|
||||
Options &= ~SYMOPT_DEFERRED_LOADS;
|
||||
SymSetOptions(Options);
|
||||
|
||||
/* Test if we can reach the MS symbol server */
|
||||
if (!SymSrvIsStore(ghProcess, pszMsSymbolServer))
|
||||
{
|
||||
error("Failed to connect to symbol server.");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Set MS symbol server as symbol search path */
|
||||
SymSetSearchPath(ghProcess, pszMsSymbolServer);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
HMODULE
|
||||
LoadModuleWithSymbolsFullPath(
|
||||
_In_ PSTR pszFullModuleFileName)
|
||||
{
|
||||
HMODULE hmod;
|
||||
DWORD64 dwModuleBase;
|
||||
|
||||
/* Load the DLL */
|
||||
hmod = LoadLibraryExA(pszFullModuleFileName,
|
||||
NULL,
|
||||
LOAD_IGNORE_CODE_AUTHZ_LEVEL |
|
||||
DONT_RESOLVE_DLL_REFERENCES |
|
||||
LOAD_WITH_ALTERED_SEARCH_PATH);
|
||||
if (hmod == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Load symbols for this module */
|
||||
dwModuleBase = SymLoadModule64(ghProcess,
|
||||
NULL,
|
||||
pszFullModuleFileName,
|
||||
NULL,
|
||||
(DWORD_PTR)hmod,
|
||||
0);
|
||||
if (dwModuleBase == 0)
|
||||
{
|
||||
/* ERROR_SUCCESS means, we have symbols already */
|
||||
if (GetLastError() != ERROR_SUCCESS)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Successfully loaded symbols for '%s'\n",
|
||||
pszFullModuleFileName);
|
||||
}
|
||||
|
||||
return hmod;
|
||||
}
|
||||
|
||||
HMODULE
|
||||
LoadModuleWithSymbols(
|
||||
_In_ PSTR pszModuleName)
|
||||
{
|
||||
CHAR szFullFileName[MAX_PATH];
|
||||
HMODULE hmod;
|
||||
|
||||
/* Check if the file name has a path */
|
||||
if (strchr(pszModuleName, '\\') != NULL)
|
||||
{
|
||||
/* Try as it is */
|
||||
hmod = LoadModuleWithSymbolsFullPath(pszModuleName);
|
||||
if (hmod != NULL)
|
||||
{
|
||||
return hmod;
|
||||
}
|
||||
}
|
||||
|
||||
/* Try current directory */
|
||||
GetCurrentDirectoryA(MAX_PATH, szFullFileName);
|
||||
strcat_s(szFullFileName, sizeof(szFullFileName), "\\");
|
||||
strcat_s(szFullFileName, sizeof(szFullFileName), pszModuleName);
|
||||
hmod = LoadModuleWithSymbolsFullPath(szFullFileName);
|
||||
if (hmod != NULL)
|
||||
{
|
||||
return hmod;
|
||||
}
|
||||
|
||||
/* Try system32 */
|
||||
strcpy_s(szFullFileName, sizeof(szFullFileName), "%systemroot%\\system32");
|
||||
strcat_s(szFullFileName, sizeof(szFullFileName), pszModuleName);
|
||||
hmod = LoadModuleWithSymbolsFullPath(szFullFileName);
|
||||
if (hmod != NULL)
|
||||
{
|
||||
return hmod;
|
||||
}
|
||||
|
||||
#ifdef _WIN64
|
||||
/* Try SysWoW64 */
|
||||
strcpy_s(szFullFileName, sizeof(szFullFileName), "%systemroot%\\system32");
|
||||
strcat_s(szFullFileName, sizeof(szFullFileName), pszModuleName);
|
||||
hmod = LoadModuleWithSymbolsFullPath(szFullFileName);
|
||||
if (hmod != NULL)
|
||||
{
|
||||
return hmod;
|
||||
}
|
||||
#endif // _WIN64
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
GetExportsFromFile(
|
||||
_In_ HANDLE hFile,
|
||||
_In_ HMODULE hmod,
|
||||
_Out_ PEXPORT_DATA* ppExportData)
|
||||
{
|
||||
HANDLE hMap;
|
||||
PBYTE pjImageBase;
|
||||
PIMAGE_EXPORT_DIRECTORY pExportDir;
|
||||
ULONG i, cjExportSize, cFunctions, cjTableSize;
|
||||
|
@ -157,28 +324,18 @@ GetExportsFromFile(
|
|||
PULONG pulAddressTable, pulNameTable;
|
||||
PUSHORT pusOrdinalTable;
|
||||
|
||||
/* Create an image file mapping */
|
||||
hMap = CreateFileMappingA(hFile, NULL, PAGE_READONLY | SEC_IMAGE, 0, 0, NULL);
|
||||
if (!hMap)
|
||||
{
|
||||
fprintf(stderr, "CreateFileMapping() failed: %ld\n", GetLastError());
|
||||
return HRESULT_FROM_WIN32(GetLastError());
|
||||
}
|
||||
pjImageBase = (PBYTE)hmod;
|
||||
|
||||
/* Map the file */
|
||||
pjImageBase = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0);
|
||||
if(pjImageBase == NULL)
|
||||
{
|
||||
fprintf(stderr, "MapViewOfFile() failed: %ld\n", GetLastError());
|
||||
CloseHandle(hMap);
|
||||
return HRESULT_FROM_WIN32(GetLastError());
|
||||
}
|
||||
|
||||
/* Get the export directory */
|
||||
pExportDir = ImageDirectoryEntryToData(pjImageBase,
|
||||
/* Get the export directory */
|
||||
pExportDir = ImageDirectoryEntryToData(pjImageBase,
|
||||
TRUE,
|
||||
IMAGE_DIRECTORY_ENTRY_EXPORT,
|
||||
&cjExportSize);
|
||||
if (pExportDir == NULL)
|
||||
{
|
||||
fprintf(stderr, "Failed to get export directory\n");
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
cFunctions = pExportDir->NumberOfFunctions;
|
||||
cjTableSize = FIELD_OFFSET(EXPORT_DATA, aExports[cFunctions]);
|
||||
|
@ -186,6 +343,7 @@ GetExportsFromFile(
|
|||
pExportData = malloc(cjTableSize);
|
||||
if (pExportData == NULL)
|
||||
{
|
||||
error("Failed to allocate %u bytes of memory for export table\n", cjTableSize);
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
|
@ -199,7 +357,8 @@ GetExportsFromFile(
|
|||
for (i = 0; i < cFunctions; i++)
|
||||
{
|
||||
PVOID pvFunction = (pjImageBase + pulAddressTable[i]);
|
||||
|
||||
|
||||
/* Check if this is a forwarder */
|
||||
if ((ULONG_PTR)((PUCHAR)pvFunction - (PUCHAR)pExportDir) < cjExportSize)
|
||||
{
|
||||
pExportData->aExports[i].pszForwarder = _strdup(pvFunction);
|
||||
|
@ -223,8 +382,6 @@ GetExportsFromFile(
|
|||
}
|
||||
|
||||
*ppExportData = pExportData;
|
||||
UnmapViewOfFile(pjImageBase);
|
||||
CloseHandle(hMap);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
@ -233,7 +390,7 @@ CALLBACK
|
|||
EnumParametersCallback(
|
||||
_In_ PSYMBOL_INFO pSymInfo,
|
||||
_In_ ULONG SymbolSize,
|
||||
_In_opt_ PVOID UserContext)
|
||||
_In_ PVOID UserContext)
|
||||
{
|
||||
PEXPORT pExport = (PEXPORT)UserContext;
|
||||
enum SymTagEnum eSymTag;
|
||||
|
@ -282,7 +439,8 @@ EnumParametersCallback(
|
|||
break;
|
||||
}
|
||||
}
|
||||
/* 'long' type */
|
||||
|
||||
/* Default to 'long' type */
|
||||
pExport->aeParameters[pExport->cParameters - 1] = TYPE_LONG;
|
||||
break;
|
||||
|
||||
|
@ -309,12 +467,15 @@ EnumParametersCallback(
|
|||
TI_GET_BASETYPE,
|
||||
&eBaseType))
|
||||
{
|
||||
/* Check for string types */
|
||||
if (eBaseType == btChar)
|
||||
{
|
||||
/* 'str' type */
|
||||
pExport->aeParameters[pExport->cParameters - 1] = TYPE_STR;
|
||||
}
|
||||
else if (eBaseType == btWChar)
|
||||
{
|
||||
/* 'wstr' type */
|
||||
pExport->aeParameters[pExport->cParameters - 1] = TYPE_WSTR;
|
||||
}
|
||||
}
|
||||
|
@ -335,46 +496,92 @@ EnumParametersCallback(
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
ULONG64
|
||||
GetFunctionFromForwarder(
|
||||
_In_ PCSTR pszForwarder)
|
||||
{
|
||||
CHAR szDllName[MAX_SYMBOL_NAME];
|
||||
PCH pchDot, pszName;
|
||||
ULONG64 ullFunction;
|
||||
HMODULE hmod;
|
||||
|
||||
/* Copy the forwarder name */
|
||||
strcpy_s(szDllName, sizeof(szDllName), pszForwarder);
|
||||
|
||||
/* Find the '.' */
|
||||
pchDot = strchr(szDllName, '.');
|
||||
if (pchDot == NULL)
|
||||
{
|
||||
error("Invalid name for forwarder '%s'!", pszForwarder);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Terminate DLL name */
|
||||
*pchDot = '\0';
|
||||
|
||||
/* Load the DLL */
|
||||
hmod = LoadModuleWithSymbols(szDllName);
|
||||
if (hmod == NULL)
|
||||
{
|
||||
error("Failed to load module for forwarder '%s'!", pszForwarder);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Get the function name and check for ordinal */
|
||||
pszName = pchDot + 1;
|
||||
if (pszName[0] == '#')
|
||||
{
|
||||
ULONG iOrdinal = strtoul(pszName + 1, NULL, 10);
|
||||
if ((iOrdinal == 0) || (iOrdinal > 0xFFFF))
|
||||
{
|
||||
error("Got invalid ordinal %u for ''", iOrdinal, pszForwarder);
|
||||
return 0;
|
||||
}
|
||||
|
||||
pszName = (PSTR)(ULONG_PTR)iOrdinal;
|
||||
}
|
||||
|
||||
/* Get the function address */
|
||||
ullFunction = (ULONG_PTR)GetProcAddress(hmod, pszName);
|
||||
if (ullFunction == 0)
|
||||
{
|
||||
error("Failed to resolve '%s' in '%s'.", pchDot + 1, szDllName);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ullFunction;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
ParseExportSymbols(
|
||||
_In_ HANDLE hFile,
|
||||
ParseImageSymbols(
|
||||
_In_ HMODULE hmod,
|
||||
_Inout_ PEXPORT_DATA pExportData)
|
||||
{
|
||||
DWORD Options;
|
||||
DWORD64 dwModuleBase;
|
||||
ULONG i;
|
||||
IMAGEHLP_STACK_FRAME StackFrame;
|
||||
SYMINFO_EX sym;
|
||||
|
||||
dwModuleBase = (DWORD_PTR)hmod;
|
||||
|
||||
/* Initialize dbghelp */
|
||||
if (!SymInitialize(ghProcess, 0, FALSE))
|
||||
return E_FAIL;
|
||||
|
||||
Options = SymGetOptions();
|
||||
Options |= SYMOPT_ALLOW_ABSOLUTE_SYMBOLS | SYMOPT_DEBUG;// | SYMOPT_NO_PROMPTS;
|
||||
Options &= ~SYMOPT_DEFERRED_LOADS;
|
||||
SymSetOptions(Options);
|
||||
SymSetSearchPath(ghProcess, "srv**symbols*http://msdl.microsoft.com/download/symbols");
|
||||
|
||||
printf("Loading symbols, please wait...\n");
|
||||
dwModuleBase = SymLoadModule64(ghProcess, 0, gszModuleFileName, 0, 0, 0);
|
||||
if (dwModuleBase == 0)
|
||||
{
|
||||
fprintf(stderr, "SymLoadModule64() failed: %ld\n", GetLastError());
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
|
||||
/* Loop through all exports */
|
||||
for (i = 0; i < pExportData->cNumberOfExports; i++)
|
||||
{
|
||||
PEXPORT pExport = &pExportData->aExports[i];
|
||||
ULONG64 ullFunction = dwModuleBase + pExportData->aExports[i].ulRva;
|
||||
ULONG64 ullDisplacement;
|
||||
|
||||
/* Skip forwarder */
|
||||
/* Check if this is a forwarder */
|
||||
if (pExport->pszForwarder != NULL)
|
||||
continue;
|
||||
{
|
||||
/* Load the module and get the function address */
|
||||
ullFunction = GetFunctionFromForwarder(pExport->pszForwarder);
|
||||
if (ullFunction == 0)
|
||||
{
|
||||
printf("Failed to get function for forwarder '%s'. Skipping.\n", pExport->pszForwarder);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
RtlZeroMemory(&sym, sizeof(sym));
|
||||
sym.si.SizeOfStruct = sizeof(SYMBOL_INFO);
|
||||
|
@ -383,16 +590,16 @@ ParseExportSymbols(
|
|||
/* Try to find the symbol */
|
||||
if (!SymFromAddr(ghProcess, ullFunction, &ullDisplacement, &sym.si))
|
||||
{
|
||||
printf("Error: SymFromAddr() failed. Error code: %u \n", GetLastError());
|
||||
error("Error: SymFromAddr() failed.");
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Symbol found. Check if it is a function */
|
||||
/* Get the symbol name */
|
||||
pExport->pszSymbol = _strdup(sym.si.Name);
|
||||
|
||||
/* Check if it is a function */
|
||||
if (sym.si.Tag == SymTagFunction)
|
||||
{
|
||||
/* If we don't have a name yet, get one */
|
||||
pExport->pszSymbol = _strdup(sym.si.Name);
|
||||
|
||||
/* Get the calling convention */
|
||||
if (!SymGetTypeInfo(ghProcess,
|
||||
dwModuleBase,
|
||||
|
@ -401,7 +608,7 @@ ParseExportSymbols(
|
|||
&pExport->dwCallingConvention))
|
||||
{
|
||||
/* Fall back to __stdcall */
|
||||
pExport->dwCallingConvention = 0x07; // CV_CALL_NEAR_STD
|
||||
pExport->dwCallingConvention = CV_CALL_NEAR_STD;
|
||||
}
|
||||
|
||||
/* Set the context to the function address */
|
||||
|
@ -409,8 +616,7 @@ ParseExportSymbols(
|
|||
StackFrame.InstructionOffset = ullFunction;
|
||||
if (!SymSetContext(ghProcess, &StackFrame, NULL))
|
||||
{
|
||||
DWORD dwLastError = GetLastError();
|
||||
__debugbreak();
|
||||
error("SymSetContext failed for i = %u.", i);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -421,11 +627,14 @@ ParseExportSymbols(
|
|||
EnumParametersCallback,
|
||||
pExport))
|
||||
{
|
||||
DWORD dwLastError = GetLastError();
|
||||
__debugbreak();
|
||||
error("SymEnumSymbols failed for i = %u.", i);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (sym.si.Tag == SymTagPublicSymbol)
|
||||
{
|
||||
pExport->dwCallingConvention = CV_CALL_NEAR_STD;
|
||||
}
|
||||
else if (sym.si.Tag == SymTagData)
|
||||
{
|
||||
pExport->fData = TRUE;
|
||||
|
@ -457,8 +666,6 @@ GetCallingConvention(
|
|||
return "syscall";
|
||||
case CV_CALL_THISCALL:
|
||||
return "thiscall";
|
||||
case CV_CALL_CLRCALL:
|
||||
return "clrcall";
|
||||
default:
|
||||
__debugbreak();
|
||||
}
|
||||
|
@ -478,7 +685,7 @@ CreateSpecFile(
|
|||
/* Create the spec file */
|
||||
if (fopen_s(&file, pszSpecFile, "w") != 0)
|
||||
{
|
||||
fprintf(stderr, "Failed to open spec file: '%s'\n", pszSpecFile);
|
||||
error("Failed to open spec file: '%s'\n", pszSpecFile);
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
|
@ -487,7 +694,7 @@ CreateSpecFile(
|
|||
{
|
||||
pExport = &pExportData->aExports[i];
|
||||
|
||||
fprintf(file, "%u %s ", i + 1, GetCallingConvention(pExport));
|
||||
fprintf(file, "%lu %s ", i + 1, GetCallingConvention(pExport));
|
||||
//if (pExport->fNoName)
|
||||
if (pExport->pszName == NULL)
|
||||
{
|
||||
|
@ -504,7 +711,7 @@ CreateSpecFile(
|
|||
}
|
||||
else
|
||||
{
|
||||
fprintf(file, "NamelessExport_%u", i);
|
||||
fprintf(file, "NamelessExport_%lu", i);
|
||||
}
|
||||
|
||||
if (!pExport->fData)
|
||||
|
@ -539,43 +746,24 @@ int main(int argc, char* argv[])
|
|||
HRESULT hr;
|
||||
CHAR szSpecFile[MAX_PATH];
|
||||
PSTR pszSpecFile;
|
||||
HANDLE hFile;
|
||||
PEXPORT_DATA pExportData;
|
||||
HMODULE hmod;
|
||||
|
||||
// check params
|
||||
// help
|
||||
|
||||
ghProcess = GetCurrentProcess();
|
||||
|
||||
/* Open the file */
|
||||
hr = OpenFileFromName(argv[1], &hFile);
|
||||
if (!SUCCEEDED(hr))
|
||||
/* Check parameters */
|
||||
if ((argc < 2) || !strcmp(argv[1], "/?"))
|
||||
{
|
||||
fprintf(stderr, "Failed to open file: %lx\n", hr);
|
||||
return hr;
|
||||
}
|
||||
|
||||
/* Get the exports */
|
||||
hr = GetExportsFromFile(hFile, &pExportData);
|
||||
if (!SUCCEEDED(hr))
|
||||
{
|
||||
fprintf(stderr, "Failed to get exports: %lx\n", hr);
|
||||
return hr;
|
||||
}
|
||||
|
||||
/* Get additional info from symbols */
|
||||
hr = ParseExportSymbols(hFile, pExportData);
|
||||
if (!SUCCEEDED(hr))
|
||||
{
|
||||
fprintf(stderr, "Failed to get symbol information: %lx\n", hr);
|
||||
printf("syntax: createspec <image file> [<spec file>]\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check if we have a spec file name */
|
||||
if (argc > 2)
|
||||
{
|
||||
pszSpecFile = argv[2];
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Create spec file name from image file name */
|
||||
PSTR pszStart = strrchr(argv[1], '\\');
|
||||
if (pszStart == 0)
|
||||
pszStart = argv[1];
|
||||
|
@ -585,9 +773,40 @@ int main(int argc, char* argv[])
|
|||
pszSpecFile = szSpecFile;
|
||||
}
|
||||
|
||||
hr = CreateSpecFile(pszSpecFile, pExportData);
|
||||
/* Initialize dbghelp.dll */
|
||||
if (!InitDbgHelp())
|
||||
{
|
||||
error("Failed to init dbghelp!\n"
|
||||
"Make sure you have dbghelp.dll and symsrv.dll in the same folder.\n");
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
CloseHandle(hFile);
|
||||
/* Load the file including symbols */
|
||||
printf("Loading symbols for '%s', please wait...\n", argv[1]);
|
||||
hmod = LoadModuleWithSymbols(argv[1]);
|
||||
if (hmod == NULL)
|
||||
{
|
||||
error("Failed to load module '%s'!", argv[1]);
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
/* Get the exports */
|
||||
hr = GetExportsFromFile(hmod, &pExportData);
|
||||
if (!SUCCEEDED(hr))
|
||||
{
|
||||
error("Failed to get exports: %lx\n", hr);
|
||||
return hr;
|
||||
}
|
||||
|
||||
/* Get additional info from symbols */
|
||||
hr = ParseImageSymbols(hmod, pExportData);
|
||||
if (!SUCCEEDED(hr))
|
||||
{
|
||||
error("Failed to get symbol information: hr=%lx\n", hr);
|
||||
}
|
||||
|
||||
/* Write the spec file */
|
||||
hr = CreateSpecFile(pszSpecFile, pExportData);
|
||||
|
||||
printf("Spec file '%s' was successfully written.\n", szSpecFile);
|
||||
|
||||
|
|
Loading…
Reference in a new issue