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.
324 lines
8.2 KiB
324 lines
8.2 KiB
3 years ago
|
/* BEGIN_LEGAL
|
||
|
|
||
|
Copyright (c) 2021 Intel Corporation
|
||
|
|
||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
you may not use this file except in compliance with the License.
|
||
|
You may obtain a copy of the License at
|
||
|
|
||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||
|
|
||
|
Unless required by applicable law or agreed to in writing, software
|
||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
See the License for the specific language governing permissions and
|
||
|
limitations under the License.
|
||
|
|
||
|
END_LEGAL */
|
||
|
#include "udhelp.H"
|
||
|
#include <stdio.h>
|
||
|
extern "C" {
|
||
|
#include "xed/xed-interface.h"
|
||
|
#include "xed-examples-util.h" // xed_strdup
|
||
|
}
|
||
|
#include <process.h>
|
||
|
#include <windows.h>
|
||
|
#include <io.h>
|
||
|
#include <cstring>
|
||
|
#include <cstdio>
|
||
|
#include <cassert>
|
||
|
|
||
|
#if defined(XED_USING_DEBUG_HELP) && defined(XED_DECODER)
|
||
|
BOOL CALLBACK dbg_help_client_t::enum_modules(
|
||
|
LPSTR ModuleName,
|
||
|
DWORD64 BaseOfDll,
|
||
|
PVOID UserContext )
|
||
|
{
|
||
|
dbg_help_client_t* pthis = (dbg_help_client_t*)UserContext;
|
||
|
pthis->gBaseOfDll = BaseOfDll;
|
||
|
pthis->gModule=ModuleName;
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
BOOL CALLBACK dbg_help_client_t::enum_sym(
|
||
|
PSYMBOL_INFO pSymInfo,
|
||
|
ULONG SymbolSize,
|
||
|
PVOID UserContext)
|
||
|
{
|
||
|
dbg_help_client_t* pthis = (dbg_help_client_t*)UserContext;
|
||
|
xed_uint64_t addr = static_cast<xed_uint64_t>(pSymInfo->Address);
|
||
|
|
||
|
xst_add_global_symbol(&pthis->sym_tab,
|
||
|
addr,
|
||
|
xed_strdup(pSymInfo->Name));
|
||
|
return TRUE;
|
||
|
(void)SymbolSize; //pacify compiler warning about unused param
|
||
|
}
|
||
|
|
||
|
|
||
|
dbg_help_client_t::dbg_help_client_t() {
|
||
|
xed_symbol_table_init(&sym_tab);
|
||
|
initialized=false;
|
||
|
}
|
||
|
|
||
|
|
||
|
char* find_base_path(char* driver_name) {
|
||
|
char* x;
|
||
|
char* path = xed_strdup(driver_name);
|
||
|
x = strrchr(path,'\\');
|
||
|
if (x) {
|
||
|
*x = 0;
|
||
|
}
|
||
|
else {
|
||
|
x = strrchr(path,'/');
|
||
|
if (x) {
|
||
|
*x = 0;
|
||
|
}
|
||
|
else {
|
||
|
/* FIXME */
|
||
|
}
|
||
|
}
|
||
|
return path;
|
||
|
}
|
||
|
|
||
|
static char* append3(const char* s1, const char* s2, const char* s3) {
|
||
|
xed_uint_t n = 1;
|
||
|
char* p = 0;
|
||
|
assert(s1 != 0);
|
||
|
n += xed_strlen(s1);
|
||
|
if (s2) n += xed_strlen(s2);
|
||
|
if (s3) n += xed_strlen(s3);
|
||
|
p = (char*) malloc(sizeof(char)*n);
|
||
|
n=xed_strncpy(p,s1,n);
|
||
|
if (s2) n=xed_strncat(p,s2,n);
|
||
|
if (s3) n=xed_strncat(p,s3,n);
|
||
|
return p;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
typedef union {
|
||
|
short a[2];
|
||
|
int i;
|
||
|
} union16_t;
|
||
|
|
||
|
void get_dll_version(char* file_name, short u[4]) {
|
||
|
VS_FIXEDFILEINFO* vsf;
|
||
|
DWORD verlen, error, handle;
|
||
|
UINT len;
|
||
|
BOOL ret;
|
||
|
char* ver;
|
||
|
|
||
|
verlen = GetFileVersionInfoSize(file_name,&handle);
|
||
|
if (verlen == 0) {
|
||
|
error = GetLastError();
|
||
|
fprintf(stderr,"GetFileVersionInfoSize: error code was %u (0x%x)\n",
|
||
|
error, error);
|
||
|
exit(1);
|
||
|
}
|
||
|
|
||
|
ver = new char[verlen];
|
||
|
ret = GetFileVersionInfo(file_name,handle,verlen,ver);
|
||
|
if (!ret) {
|
||
|
error = GetLastError();
|
||
|
fprintf(stderr,
|
||
|
"GetFileVersionInfo: error code was %u (0x%x)\n", error, error);
|
||
|
exit(1);
|
||
|
}
|
||
|
|
||
|
// get a pointer to a location in ver stored in vsf
|
||
|
ret = VerQueryValue(ver,"\\",(LPVOID*)&vsf,&len);
|
||
|
if (!ret) {
|
||
|
error = GetLastError();
|
||
|
fprintf(stderr,
|
||
|
"VerQueryValue: error code was %u (0x%x)\n", error, error);
|
||
|
exit(1);
|
||
|
}
|
||
|
assert(len == sizeof(VS_FIXEDFILEINFO));
|
||
|
|
||
|
union16_t upper,lower;
|
||
|
upper.i = vsf->dwFileVersionMS;
|
||
|
lower.i = vsf->dwFileVersionLS;
|
||
|
u[0] = upper.a[1];
|
||
|
u[1] = upper.a[0];
|
||
|
u[2] = lower.a[1];
|
||
|
u[3] = lower.a[0];
|
||
|
|
||
|
delete[] ver;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
int dbg_help_client_t::init(char const* const path,
|
||
|
char const* const search_path)
|
||
|
{
|
||
|
DWORD64 dwBaseAddr=0;
|
||
|
|
||
|
int chars;
|
||
|
char exe_path[MAX_PATH];
|
||
|
chars = GetModuleFileName(NULL, exe_path, MAX_PATH);
|
||
|
if (chars == 0) {
|
||
|
fprintf(stderr,"Could not find base path for XED executable\n");
|
||
|
fflush(stderr);
|
||
|
exit(1);
|
||
|
}
|
||
|
|
||
|
char* dir = find_base_path(exe_path);
|
||
|
|
||
|
char* dbghelp = append3(dir,"\\","dbghelp.dll");
|
||
|
#if defined(PIN_CRT)
|
||
|
if (access(dbghelp,4) != 0)
|
||
|
#else
|
||
|
if (_access_s(dbghelp,4) != 0)
|
||
|
#endif
|
||
|
{
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
SymSetOptions(SYMOPT_UNDNAME | SYMOPT_LOAD_LINES );
|
||
|
hProcess = GetCurrentProcess();
|
||
|
|
||
|
if (SymInitialize(hProcess, NULL, FALSE)) {
|
||
|
// nothing
|
||
|
}
|
||
|
else {
|
||
|
error = GetLastError();
|
||
|
fprintf(stderr,"SymInitialize returned error : %u 0x%x\n",
|
||
|
error, error);
|
||
|
fflush(stderr);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
if (search_path)
|
||
|
{
|
||
|
if (SymSetSearchPath(hProcess, search_path)) {
|
||
|
// nothing
|
||
|
}
|
||
|
else {
|
||
|
error = GetLastError();
|
||
|
fprintf(stderr,"SymSetSearchPath returned error : %u 0x%x\n",
|
||
|
error, error);
|
||
|
fflush(stderr);
|
||
|
return 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
actual_base = SymLoadModuleEx(hProcess, NULL, path, NULL,
|
||
|
dwBaseAddr, 0, NULL, 0);
|
||
|
if (actual_base) {
|
||
|
// nothing
|
||
|
}
|
||
|
else {
|
||
|
error = GetLastError();
|
||
|
fprintf(stderr,"SymLoadModuleEx returned error : %u 0x%x\n",
|
||
|
error, error);
|
||
|
fflush(stderr);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
if (SymEnumerateModules64(hProcess,
|
||
|
(PSYM_ENUMMODULES_CALLBACK64)enum_modules, this)) {
|
||
|
// nothing
|
||
|
}
|
||
|
else {
|
||
|
error = GetLastError();
|
||
|
fprintf(stderr,"SymEnumerateModules64 returned error : %d 0x%x\n",
|
||
|
error, error);
|
||
|
fflush(stderr);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
if (SymEnumSymbols(hProcess, actual_base, 0, enum_sym, this)) {
|
||
|
// nothing
|
||
|
}
|
||
|
else {
|
||
|
error = GetLastError();
|
||
|
fprintf(stderr,"SymEnumSymbols failed: %d 0x%x\n", error, error);
|
||
|
fflush(stderr);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
initialized = true;
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
bool dbg_help_client_t::get_symbol(DWORD64 address, char* symbol_name,
|
||
|
int sym_name_buflen, DWORD64* offset)
|
||
|
{
|
||
|
DWORD64 displacement;
|
||
|
ULONG64 n = (sizeof(SYMBOL_INFO) +
|
||
|
sym_name_buflen*sizeof(TCHAR) +
|
||
|
sizeof(ULONG64) - 1) / sizeof(ULONG64);
|
||
|
ULONG64* buffer = new ULONG64[n];
|
||
|
PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer;
|
||
|
|
||
|
pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO);
|
||
|
pSymbol->MaxNameLen = sym_name_buflen;
|
||
|
|
||
|
if (SymFromAddr(hProcess, address, &displacement, pSymbol)) {
|
||
|
if (offset)
|
||
|
*offset = displacement;
|
||
|
if (offset || displacement == 0) {
|
||
|
xed_strncpy(symbol_name, pSymbol->Name, sym_name_buflen);
|
||
|
// force a null. WINDOWS doesn't have strlcpy()
|
||
|
symbol_name[sym_name_buflen-1] = 0;
|
||
|
delete [] buffer;
|
||
|
return 0;
|
||
|
}
|
||
|
else {
|
||
|
/* not at the beginning of a symbol and no offset was supplied */
|
||
|
delete [] buffer;
|
||
|
return 1;
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
error = GetLastError();
|
||
|
fprintf(stderr,
|
||
|
"SymFromAddr returned error : %d 0x%x for address %llx\n",
|
||
|
error, error, address);
|
||
|
delete [] buffer;
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
|
||
|
}
|
||
|
|
||
|
bool dbg_help_client_t::cleanup() {
|
||
|
if (SymCleanup(hProcess)) {
|
||
|
return 0;
|
||
|
}
|
||
|
else {
|
||
|
error = GetLastError();
|
||
|
fprintf(stderr,
|
||
|
"SymCleanup returned error : %d 0x%x\n", error,error);
|
||
|
return 1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
xed_bool_t dbg_help_client_t::get_file_and_line(xed_uint64_t address,
|
||
|
char** filename,
|
||
|
xed_uint32_t* line,
|
||
|
xed_uint32_t* column)
|
||
|
{
|
||
|
DWORD dw_column;
|
||
|
IMAGEHLP_LINE64 imgline;
|
||
|
imgline.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
|
||
|
if (SymGetLineFromAddr64(hProcess, address, &dw_column, &imgline))
|
||
|
{
|
||
|
xed_uint32_t len = xed_strlen(imgline.FileName);
|
||
|
*column = dw_column;
|
||
|
*line = imgline.LineNumber;
|
||
|
*filename =(char*) malloc(len+1);
|
||
|
xed_strncpy(*filename, imgline.FileName, len+1);
|
||
|
return 1; //success
|
||
|
}
|
||
|
return 0; //failed
|
||
|
}
|
||
|
|
||
|
#endif
|