Files
archived-xed/examples/udhelp.cpp
Mark Charney fcd2d41b2b moving headers to xed/ directory for install & kit. DISRUPTIVE CHANGE
* compiled kit users must refer to "#include "xed/xed-interface.h"
      and xed/ on any other public headers that they reference as part
      of the kit or new /usr/local installs.  Or they can change their
      -I flag to include the xed/ path component.  All the examples
      use xed/ in the #include statements now.

    * new knob --prefix=/usr/local (for example) that puts the
      compiled library in /usr/local/lib and the headers in
      /usr/local/include/xed .

    * To install in /usr/local, one typically must sudo.  If you do
      the whole build at sudo, then it'll create root-owned files in
      your build directory whic you might not want.  So I suggest
      first building as the local user and then sudo only for the
      final install.

         > ./mfile.py
	 > sudo ./mfile.py --prefix=/usr/local

    * There is also a --prefix-lib-dir knob to specify something other
      than "lib" for /usr/local/lib. Some systems use lib, lib32 or
      lib64 and I don't know how to tell which is which so I give
      users a knob so they can decide for themselves.

         > ./mfile.py --host-cpu=ia32
	 > sudo ./mfile.py --prefix=/usr/local --prefix-lib-dir=lib32
         > ./mfile.py --host-cpu=intel64
	 > sudo ./mfile.py --prefix=/usr/local --prefix-lib-dir=lib64

    * added xed-util.h to xed-interface.h

    * moved headers from include/public to include/public/xed

    * genutil minor cleanup

Change-Id: I3786d2280f24ff8d7e075fa7a75d90f3b28dd8c3
2016-12-21 13:53:14 -05:00

324 lines
8.2 KiB
C++

/*BEGIN_LEGAL
Copyright (c) 2016 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 %d (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 %d (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 %d (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 : %d 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 : %d 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 : %d 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