|
|
|
|
@@ -60,6 +60,9 @@
|
|
|
|
|
|
|
|
|
|
#include "i386-tdep.h"
|
|
|
|
|
#include "i387-tdep.h"
|
|
|
|
|
#ifdef __x86_64__
|
|
|
|
|
#include "amd64-tdep.h"
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#include "windows-tdep.h"
|
|
|
|
|
#include "windows-nat.h"
|
|
|
|
|
@@ -71,6 +74,8 @@
|
|
|
|
|
#include "gdbsupport/gdb_wait.h"
|
|
|
|
|
#include "nat/windows-nat.h"
|
|
|
|
|
#include "gdbsupport/symbol.h"
|
|
|
|
|
#include "buildsym.h"
|
|
|
|
|
#include "block.h"
|
|
|
|
|
|
|
|
|
|
using namespace windows_nat;
|
|
|
|
|
|
|
|
|
|
@@ -3042,6 +3047,104 @@ windows_nat_target::thread_name (struct thread_info *thr)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct pdb_regrel_baton
|
|
|
|
|
{
|
|
|
|
|
int regnum;
|
|
|
|
|
ULONG64 offset;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static value *
|
|
|
|
|
pdb_read_variable (struct symbol *symbol, struct frame_info *frame)
|
|
|
|
|
{
|
|
|
|
|
pdb_regrel_baton *baton
|
|
|
|
|
= (pdb_regrel_baton *) SYMBOL_LOCATION_BATON (symbol);
|
|
|
|
|
ULONGEST regvalue = get_frame_register_unsigned (frame, baton->regnum);
|
|
|
|
|
return value_at_lazy (symbol->type (), regvalue + baton->offset);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct pdb_tls_baton
|
|
|
|
|
{
|
|
|
|
|
ULONG64 offset;
|
|
|
|
|
int tib_ofs;
|
|
|
|
|
int ptr_size;
|
|
|
|
|
symbol *tls_index_sym;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static value *
|
|
|
|
|
pdb_tls_read_variable (struct symbol *symbol, struct frame_info *frame)
|
|
|
|
|
{
|
|
|
|
|
pdb_tls_baton *baton = (pdb_tls_baton *) SYMBOL_LOCATION_BATON (symbol);
|
|
|
|
|
|
|
|
|
|
CORE_ADDR tib;
|
|
|
|
|
if (baton->tls_index_sym != nullptr
|
|
|
|
|
&& the_windows_nat_target.get_tib_address (inferior_ptid, &tib))
|
|
|
|
|
{
|
|
|
|
|
struct gdbarch *gdbarch = get_frame_arch (frame);
|
|
|
|
|
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
|
|
|
|
|
ULONGEST thread_local_storage
|
|
|
|
|
= read_memory_unsigned_integer (tib + baton->tib_ofs,
|
|
|
|
|
baton->ptr_size, byte_order);
|
|
|
|
|
DWORD tls_index = read_memory_unsigned_integer
|
|
|
|
|
(SYMBOL_VALUE_ADDRESS (baton->tls_index_sym), 4, byte_order);
|
|
|
|
|
ULONGEST tls = read_memory_unsigned_integer
|
|
|
|
|
(thread_local_storage + tls_index * baton->ptr_size,
|
|
|
|
|
baton->ptr_size, byte_order);
|
|
|
|
|
return value_at_lazy (symbol->type (), tls + baton->offset);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return allocate_optimized_out_value (symbol->type ());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static enum symbol_needs_kind
|
|
|
|
|
pdb_get_symbol_read_needs (struct symbol *symbol)
|
|
|
|
|
{
|
|
|
|
|
return SYMBOL_NEEDS_FRAME;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
pdb_describe_location (struct symbol *symbol, CORE_ADDR addr,
|
|
|
|
|
struct ui_file *stream)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
pdb_tracepoint_var_ref (struct symbol *symbol, struct agent_expr *ax,
|
|
|
|
|
struct axs_value *value)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
pdb_generate_c_location (struct symbol *symbol, string_file *stream,
|
|
|
|
|
struct gdbarch *gdbarch,
|
|
|
|
|
std::vector<bool> ®isters_used,
|
|
|
|
|
CORE_ADDR pc, const char *result_name)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const struct symbol_computed_ops pdb_regrel_funcs = {
|
|
|
|
|
pdb_read_variable,
|
|
|
|
|
NULL,
|
|
|
|
|
pdb_get_symbol_read_needs,
|
|
|
|
|
pdb_describe_location,
|
|
|
|
|
0, /* location_has_loclist */
|
|
|
|
|
pdb_tracepoint_var_ref,
|
|
|
|
|
pdb_generate_c_location
|
|
|
|
|
};
|
|
|
|
|
static int pdb_regrel_index;
|
|
|
|
|
|
|
|
|
|
const struct symbol_computed_ops pdb_tls_funcs = {
|
|
|
|
|
pdb_tls_read_variable,
|
|
|
|
|
NULL,
|
|
|
|
|
pdb_get_symbol_read_needs,
|
|
|
|
|
pdb_describe_location,
|
|
|
|
|
0, /* location_has_loclist */
|
|
|
|
|
pdb_tracepoint_var_ref,
|
|
|
|
|
pdb_generate_c_location
|
|
|
|
|
};
|
|
|
|
|
static int pdb_tls_index;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void _initialize_windows_nat ();
|
|
|
|
|
void
|
|
|
|
|
_initialize_windows_nat ()
|
|
|
|
|
@@ -3143,6 +3246,10 @@ Show whether to display kernel exceptions in child process."), NULL,
|
|
|
|
|
cannot automatically find executable file or library to read symbols.\n\
|
|
|
|
|
Use \"file\" or \"dll\" command to load executable/libraries directly."));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pdb_regrel_index = register_symbol_computed_impl (LOC_COMPUTED,
|
|
|
|
|
&pdb_regrel_funcs);
|
|
|
|
|
pdb_tls_index = register_symbol_computed_impl (LOC_COMPUTED, &pdb_tls_funcs);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Hardware watchpoint support, adapted from go32-nat.c code. */
|
|
|
|
|
@@ -3215,6 +3322,782 @@ windows_nat_target::thread_alive (ptid_t ptid)
|
|
|
|
|
return WaitForSingleObject (th->h, 0) != WAIT_OBJECT_0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
typedef BOOL WINAPI (SymInitialize_ftype) (HANDLE, PCSTR, BOOL);
|
|
|
|
|
typedef BOOL WINAPI (SymCleanup_ftype) (HANDLE);
|
|
|
|
|
typedef DWORD64 WINAPI (SymLoadModule64_ftype) (HANDLE, HANDLE, PCSTR,
|
|
|
|
|
PCSTR, DWORD64, DWORD);
|
|
|
|
|
typedef BOOL WINAPI (SymGetModuleInfo64_ftype)
|
|
|
|
|
(HANDLE, DWORD64, PIMAGEHLP_MODULE64);
|
|
|
|
|
typedef BOOL WINAPI (SymFromName_ftype) (HANDLE, PCSTR, PSYMBOL_INFO);
|
|
|
|
|
typedef BOOL WINAPI (SymEnumTypes_ftype)
|
|
|
|
|
(HANDLE, ULONG64, PSYM_ENUMERATESYMBOLS_CALLBACK, PVOID);
|
|
|
|
|
typedef BOOL WINAPI (SymEnumSymbols_ftype)
|
|
|
|
|
(HANDLE, ULONG64, PCSTR, PSYM_ENUMERATESYMBOLS_CALLBACK, PVOID);
|
|
|
|
|
typedef BOOL WINAPI (SymEnumSourceLines_ftype)
|
|
|
|
|
(HANDLE, ULONG64, PCSTR, PCSTR, DWORD, DWORD, PSYM_ENUMLINES_CALLBACK,
|
|
|
|
|
PVOID);
|
|
|
|
|
typedef BOOL WINAPI (SymGetTypeInfo_ftype)
|
|
|
|
|
(HANDLE, DWORD64, ULONG, IMAGEHLP_SYMBOL_TYPE_INFO, PVOID);
|
|
|
|
|
typedef BOOL WINAPI (SymSetContext_ftype)
|
|
|
|
|
(HANDLE, PIMAGEHLP_STACK_FRAME, PIMAGEHLP_CONTEXT);
|
|
|
|
|
typedef BOOL WINAPI (SymSearch_ftype)
|
|
|
|
|
(HANDLE, ULONG64, DWORD, DWORD, PCSTR, DWORD64,
|
|
|
|
|
PSYM_ENUMERATESYMBOLS_CALLBACK, PVOID, DWORD);
|
|
|
|
|
|
|
|
|
|
enum SymTagEnum
|
|
|
|
|
{
|
|
|
|
|
SymTagNull,
|
|
|
|
|
SymTagExe,
|
|
|
|
|
SymTagCompiland,
|
|
|
|
|
SymTagCompilandDetails,
|
|
|
|
|
SymTagCompilandEnv,
|
|
|
|
|
SymTagFunction,
|
|
|
|
|
SymTagBlock,
|
|
|
|
|
SymTagData,
|
|
|
|
|
SymTagAnnotation,
|
|
|
|
|
SymTagLabel,
|
|
|
|
|
SymTagPublicSymbol,
|
|
|
|
|
SymTagUDT,
|
|
|
|
|
SymTagEnum,
|
|
|
|
|
SymTagFunctionType,
|
|
|
|
|
SymTagPointerType,
|
|
|
|
|
SymTagArrayType,
|
|
|
|
|
SymTagBaseType,
|
|
|
|
|
SymTagTypedef,
|
|
|
|
|
SymTagBaseClass,
|
|
|
|
|
SymTagFriend,
|
|
|
|
|
SymTagFunctionArgType,
|
|
|
|
|
SymTagFuncDebugStart,
|
|
|
|
|
SymTagFuncDebugEnd,
|
|
|
|
|
SymTagUsingNamespace,
|
|
|
|
|
SymTagVTableShape,
|
|
|
|
|
SymTagVTable,
|
|
|
|
|
SymTagCustom,
|
|
|
|
|
SymTagThunk,
|
|
|
|
|
SymTagCustomType,
|
|
|
|
|
SymTagManagedType,
|
|
|
|
|
SymTagDimension,
|
|
|
|
|
SymTagCallSite,
|
|
|
|
|
SymTagMax
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
enum UdtKind
|
|
|
|
|
{
|
|
|
|
|
UdtStruct,
|
|
|
|
|
UdtClass,
|
|
|
|
|
UdtUnion,
|
|
|
|
|
UdtInterface
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
enum DataKind
|
|
|
|
|
{
|
|
|
|
|
DataIsUnknown,
|
|
|
|
|
DataIsLocal,
|
|
|
|
|
DataIsStaticLocal,
|
|
|
|
|
DataIsParam,
|
|
|
|
|
DataIsObjectPtr,
|
|
|
|
|
DataIsFileStatic,
|
|
|
|
|
DataIsGlobal,
|
|
|
|
|
DataIsMember,
|
|
|
|
|
DataIsStaticMember,
|
|
|
|
|
DataIsConstant
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct pdb_line_info
|
|
|
|
|
{
|
|
|
|
|
minimal_symbol_reader *reader;
|
|
|
|
|
buildsym_compunit *builder;
|
|
|
|
|
pending **local_symbols;
|
|
|
|
|
objfile *objfile;
|
|
|
|
|
HANDLE p;
|
|
|
|
|
SymGetTypeInfo_ftype *fSymGetTypeInfo;
|
|
|
|
|
SymEnumSymbols_ftype *fSymEnumSymbols;
|
|
|
|
|
SymSetContext_ftype *fSymSetContext;
|
|
|
|
|
SymSearch_ftype *fSymSearch;
|
|
|
|
|
DWORD64 addr;
|
|
|
|
|
ULONGEST base_ofs;
|
|
|
|
|
DWORD64 max_addr;
|
|
|
|
|
symbol *tls_index_sym;
|
|
|
|
|
std::vector<type *> cache;
|
|
|
|
|
std::vector<symbol *> functions;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static const char *wchar_to_objfile (pdb_line_info *pli, WCHAR *nameW)
|
|
|
|
|
{
|
|
|
|
|
int len = WideCharToMultiByte (CP_ACP, 0, nameW, -1,
|
|
|
|
|
NULL, 0, NULL, NULL);
|
|
|
|
|
gdb::unique_xmalloc_ptr<char> name;
|
|
|
|
|
if (len > 1)
|
|
|
|
|
{
|
|
|
|
|
name.reset ((char *) xmalloc (len));
|
|
|
|
|
WideCharToMultiByte (CP_ACP, 0, nameW, -1,
|
|
|
|
|
name.get (), len, NULL, NULL);
|
|
|
|
|
}
|
|
|
|
|
LocalFree (nameW);
|
|
|
|
|
return pli->objfile->intern (name.get ());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static LONGEST get_pdb_int_constant (pdb_line_info *pli, DWORD type_index)
|
|
|
|
|
{
|
|
|
|
|
VARIANT v;
|
|
|
|
|
if (pli->fSymGetTypeInfo (pli->p, pli->addr, type_index,
|
|
|
|
|
TI_GET_VALUE, &v))
|
|
|
|
|
{
|
|
|
|
|
switch (v.vt)
|
|
|
|
|
{
|
|
|
|
|
case VT_I1: return v.cVal;
|
|
|
|
|
case VT_I2: return v.iVal;
|
|
|
|
|
case VT_I4: return v.lVal;
|
|
|
|
|
case VT_I8: return v.llVal;
|
|
|
|
|
case VT_UI1: return v.bVal;
|
|
|
|
|
case VT_UI2: return v.uiVal;
|
|
|
|
|
case VT_UI4: return v.ulVal;
|
|
|
|
|
case VT_UI8: return v.ullVal;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static type *get_pdb_type (pdb_line_info *pli, DWORD type_index);
|
|
|
|
|
|
|
|
|
|
static type *get_pdb_type_cached (pdb_line_info *pli, DWORD type_index)
|
|
|
|
|
{
|
|
|
|
|
const struct objfile_type *ot = objfile_type (pli->objfile);
|
|
|
|
|
|
|
|
|
|
DWORD tag;
|
|
|
|
|
if (!pli->fSymGetTypeInfo (pli->p, pli->addr, type_index,
|
|
|
|
|
TI_GET_SYMTAG, &tag))
|
|
|
|
|
return ot->builtin_void;
|
|
|
|
|
|
|
|
|
|
switch (tag)
|
|
|
|
|
{
|
|
|
|
|
case SymTagFunctionType:
|
|
|
|
|
{
|
|
|
|
|
DWORD tid;
|
|
|
|
|
if (pli->fSymGetTypeInfo (pli->p, pli->addr, type_index,
|
|
|
|
|
TI_GET_TYPEID, &tid))
|
|
|
|
|
{
|
|
|
|
|
type *ftype = lookup_function_type (get_pdb_type (pli, tid));
|
|
|
|
|
|
|
|
|
|
DWORD children;
|
|
|
|
|
if (pli->fSymGetTypeInfo (pli->p, pli->addr, type_index,
|
|
|
|
|
TI_GET_CHILDRENCOUNT, &children)
|
|
|
|
|
&& children > 0)
|
|
|
|
|
{
|
|
|
|
|
gdb::unique_xmalloc_ptr<TI_FINDCHILDREN_PARAMS> args
|
|
|
|
|
((TI_FINDCHILDREN_PARAMS *)
|
|
|
|
|
xmalloc (sizeof (TI_FINDCHILDREN_PARAMS)
|
|
|
|
|
+ children * sizeof (ULONG)));
|
|
|
|
|
args->Count = children;
|
|
|
|
|
args->Start = 0;
|
|
|
|
|
if (pli->fSymGetTypeInfo (pli->p, pli->addr, type_index,
|
|
|
|
|
TI_FINDCHILDREN, args.get ()))
|
|
|
|
|
{
|
|
|
|
|
std::vector<DWORD> arg_types;
|
|
|
|
|
for (DWORD i = 0; i < children; i++)
|
|
|
|
|
{
|
|
|
|
|
if (pli->fSymGetTypeInfo (pli->p, pli->addr,
|
|
|
|
|
args->ChildId[i],
|
|
|
|
|
TI_GET_SYMTAG, &tag)
|
|
|
|
|
&& tag == SymTagFunctionArgType
|
|
|
|
|
&& pli->fSymGetTypeInfo (pli->p, pli->addr,
|
|
|
|
|
args->ChildId[i],
|
|
|
|
|
TI_GET_TYPEID, &tid))
|
|
|
|
|
arg_types.push_back (tid);
|
|
|
|
|
}
|
|
|
|
|
if (!arg_types.empty ())
|
|
|
|
|
{
|
|
|
|
|
int nparams = arg_types.size ();
|
|
|
|
|
ftype->set_num_fields (nparams);
|
|
|
|
|
ftype->set_fields
|
|
|
|
|
((struct field *) TYPE_ZALLOC
|
|
|
|
|
(ftype, nparams * sizeof (struct field)));
|
|
|
|
|
for (int i = 0; i < nparams; i++)
|
|
|
|
|
ftype->field (i).set_type
|
|
|
|
|
(get_pdb_type (pli, arg_types[i]));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ftype;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case SymTagBaseType:
|
|
|
|
|
{
|
|
|
|
|
DWORD basetype;
|
|
|
|
|
ULONG64 length;
|
|
|
|
|
if (pli->fSymGetTypeInfo (pli->p, pli->addr, type_index,
|
|
|
|
|
TI_GET_BASETYPE, &basetype)
|
|
|
|
|
&& pli->fSymGetTypeInfo (pli->p, pli->addr, type_index,
|
|
|
|
|
TI_GET_LENGTH, &length))
|
|
|
|
|
{
|
|
|
|
|
switch (basetype)
|
|
|
|
|
{
|
|
|
|
|
case 1: // void
|
|
|
|
|
return ot->builtin_void;
|
|
|
|
|
case 2: // signed char
|
|
|
|
|
return ot->builtin_signed_char;
|
|
|
|
|
case 3: // wchar
|
|
|
|
|
return builtin_type (pli->objfile->arch ())->builtin_wchar;
|
|
|
|
|
case 6: // signed short/int/long_long
|
|
|
|
|
if (length == 2)
|
|
|
|
|
return ot->builtin_short;
|
|
|
|
|
else if (length == 4)
|
|
|
|
|
return ot->builtin_int;
|
|
|
|
|
else if (length == 8)
|
|
|
|
|
return ot->builtin_long_long;
|
|
|
|
|
break;
|
|
|
|
|
case 7: // unsigned char/short/int/long_long
|
|
|
|
|
if (length == 1)
|
|
|
|
|
return ot->builtin_unsigned_char;
|
|
|
|
|
else if (length == 2)
|
|
|
|
|
return ot->builtin_unsigned_short;
|
|
|
|
|
else if (length == 4)
|
|
|
|
|
return ot->builtin_unsigned_int;
|
|
|
|
|
else if (length == 8)
|
|
|
|
|
return ot->builtin_unsigned_long_long;
|
|
|
|
|
break;
|
|
|
|
|
case 8: // float/double
|
|
|
|
|
if (length == 4)
|
|
|
|
|
return ot->builtin_float;
|
|
|
|
|
else if (length == 8)
|
|
|
|
|
return ot->builtin_double;
|
|
|
|
|
break;
|
|
|
|
|
case 10: // bool
|
|
|
|
|
return builtin_type (pli->objfile->arch ())->builtin_bool;
|
|
|
|
|
case 13: // signed long
|
|
|
|
|
return ot->builtin_long;
|
|
|
|
|
case 14: // unsigned long
|
|
|
|
|
return ot->builtin_unsigned_long;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case SymTagPointerType:
|
|
|
|
|
{
|
|
|
|
|
DWORD tid;
|
|
|
|
|
if (pli->fSymGetTypeInfo (pli->p, pli->addr, type_index,
|
|
|
|
|
TI_GET_TYPEID, &tid))
|
|
|
|
|
return lookup_pointer_type (get_pdb_type (pli, tid));
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case SymTagUDT:
|
|
|
|
|
{
|
|
|
|
|
DWORD udtkind;
|
|
|
|
|
ULONG64 length;
|
|
|
|
|
WCHAR *nameW = NULL;
|
|
|
|
|
if (pli->fSymGetTypeInfo (pli->p, pli->addr, type_index,
|
|
|
|
|
TI_GET_UDTKIND, &udtkind)
|
|
|
|
|
&& pli->fSymGetTypeInfo (pli->p, pli->addr, type_index,
|
|
|
|
|
TI_GET_LENGTH, &length)
|
|
|
|
|
&& pli->fSymGetTypeInfo (pli->p, pli->addr, type_index,
|
|
|
|
|
TI_GET_SYMNAME, &nameW))
|
|
|
|
|
{
|
|
|
|
|
type *t = alloc_type (pli->objfile);
|
|
|
|
|
INIT_CPLUS_SPECIFIC (t);
|
|
|
|
|
|
|
|
|
|
pli->cache[type_index] = t;
|
|
|
|
|
|
|
|
|
|
t->set_name (wchar_to_objfile (pli, nameW));
|
|
|
|
|
|
|
|
|
|
if (udtkind == UdtUnion)
|
|
|
|
|
t->set_code (TYPE_CODE_UNION);
|
|
|
|
|
else
|
|
|
|
|
t->set_code (TYPE_CODE_STRUCT);
|
|
|
|
|
TYPE_LENGTH (t) = length;
|
|
|
|
|
|
|
|
|
|
DWORD children;
|
|
|
|
|
if (pli->fSymGetTypeInfo (pli->p, pli->addr, type_index,
|
|
|
|
|
TI_GET_CHILDRENCOUNT, &children)
|
|
|
|
|
&& children > 0)
|
|
|
|
|
{
|
|
|
|
|
gdb::unique_xmalloc_ptr<TI_FINDCHILDREN_PARAMS> members
|
|
|
|
|
((TI_FINDCHILDREN_PARAMS *)
|
|
|
|
|
xmalloc (sizeof (TI_FINDCHILDREN_PARAMS)
|
|
|
|
|
+ children * sizeof (ULONG)));
|
|
|
|
|
members->Count = children;
|
|
|
|
|
members->Start = 0;
|
|
|
|
|
if (pli->fSymGetTypeInfo (pli->p, pli->addr, type_index,
|
|
|
|
|
TI_FINDCHILDREN, members.get ()))
|
|
|
|
|
{
|
|
|
|
|
t->set_num_fields (children);
|
|
|
|
|
t->set_fields ((struct field *) TYPE_ZALLOC
|
|
|
|
|
(t, children * sizeof (struct field)));
|
|
|
|
|
DWORD i;
|
|
|
|
|
for (i = 0; i < children; i++)
|
|
|
|
|
{
|
|
|
|
|
DWORD tid, dk, ofs;
|
|
|
|
|
if (pli->fSymGetTypeInfo (pli->p, pli->addr,
|
|
|
|
|
members->ChildId[i],
|
|
|
|
|
TI_GET_SYMTAG, &tag)
|
|
|
|
|
&& tag == SymTagData
|
|
|
|
|
&& pli->fSymGetTypeInfo (pli->p, pli->addr,
|
|
|
|
|
members->ChildId[i],
|
|
|
|
|
TI_GET_TYPEID, &tid)
|
|
|
|
|
&& pli->fSymGetTypeInfo (pli->p, pli->addr,
|
|
|
|
|
members->ChildId[i],
|
|
|
|
|
TI_GET_DATAKIND, &dk)
|
|
|
|
|
&& dk == DataIsMember
|
|
|
|
|
&& pli->fSymGetTypeInfo (pli->p, pli->addr,
|
|
|
|
|
members->ChildId[i],
|
|
|
|
|
TI_GET_OFFSET, &ofs)
|
|
|
|
|
&& pli->fSymGetTypeInfo (pli->p, pli->addr,
|
|
|
|
|
members->ChildId[i],
|
|
|
|
|
TI_GET_SYMNAME, &nameW))
|
|
|
|
|
{
|
|
|
|
|
t->field (i).set_type (get_pdb_type (pli, tid));
|
|
|
|
|
t->field (i).set_name (wchar_to_objfile
|
|
|
|
|
(pli, nameW));
|
|
|
|
|
DWORD bitofs = 0;
|
|
|
|
|
DWORD bitpos;
|
|
|
|
|
if (pli->fSymGetTypeInfo
|
|
|
|
|
(pli->p, pli->addr, members->ChildId[i],
|
|
|
|
|
TI_GET_BITPOSITION, &bitpos)
|
|
|
|
|
&& pli->fSymGetTypeInfo
|
|
|
|
|
(pli->p, pli->addr, members->ChildId[i],
|
|
|
|
|
TI_GET_LENGTH, &length))
|
|
|
|
|
{
|
|
|
|
|
bitofs = bitpos;
|
|
|
|
|
FIELD_BITSIZE (t->field (i)) = length;
|
|
|
|
|
}
|
|
|
|
|
t->field (i).set_loc_bitpos (ofs * 8 + bitofs);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return t;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case SymTagArrayType:
|
|
|
|
|
{
|
|
|
|
|
DWORD tid, index_tid;
|
|
|
|
|
DWORD count;
|
|
|
|
|
if (pli->fSymGetTypeInfo (pli->p, pli->addr, type_index,
|
|
|
|
|
TI_GET_TYPEID, &tid)
|
|
|
|
|
&& pli->fSymGetTypeInfo (pli->p, pli->addr, type_index,
|
|
|
|
|
TI_GET_ARRAYINDEXTYPEID, &index_tid)
|
|
|
|
|
&& pli->fSymGetTypeInfo (pli->p, pli->addr, type_index,
|
|
|
|
|
TI_GET_COUNT, &count))
|
|
|
|
|
{
|
|
|
|
|
type *element_type = get_pdb_type (pli, tid);
|
|
|
|
|
type *index_type = get_pdb_type (pli, index_tid);
|
|
|
|
|
type *range_type
|
|
|
|
|
= create_static_range_type (NULL, index_type, 0, count - 1);
|
|
|
|
|
return create_array_type (NULL, element_type, range_type);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case SymTagTypedef:
|
|
|
|
|
{
|
|
|
|
|
DWORD tid;
|
|
|
|
|
WCHAR *nameW = NULL;
|
|
|
|
|
if (pli->fSymGetTypeInfo (pli->p, pli->addr, type_index,
|
|
|
|
|
TI_GET_TYPEID, &tid)
|
|
|
|
|
&& pli->fSymGetTypeInfo (pli->p, pli->addr, type_index,
|
|
|
|
|
TI_GET_SYMNAME, &nameW))
|
|
|
|
|
{
|
|
|
|
|
type *t = init_type (pli->objfile, TYPE_CODE_TYPEDEF, 0,
|
|
|
|
|
wchar_to_objfile (pli, nameW));
|
|
|
|
|
TYPE_TARGET_TYPE (t) = get_pdb_type (pli, tid);
|
|
|
|
|
return t;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case SymTagEnum:
|
|
|
|
|
{
|
|
|
|
|
DWORD tid;
|
|
|
|
|
DWORD children;
|
|
|
|
|
WCHAR *nameW = NULL;
|
|
|
|
|
if (pli->fSymGetTypeInfo (pli->p, pli->addr, type_index,
|
|
|
|
|
TI_GET_TYPEID, &tid)
|
|
|
|
|
&& pli->fSymGetTypeInfo (pli->p, pli->addr, type_index,
|
|
|
|
|
TI_GET_CHILDRENCOUNT, &children)
|
|
|
|
|
&& children > 0
|
|
|
|
|
&& pli->fSymGetTypeInfo (pli->p, pli->addr, type_index,
|
|
|
|
|
TI_GET_SYMNAME, &nameW))
|
|
|
|
|
{
|
|
|
|
|
type *t = alloc_type (pli->objfile);
|
|
|
|
|
t->set_code (TYPE_CODE_ENUM);
|
|
|
|
|
t->set_name (wchar_to_objfile (pli, nameW));
|
|
|
|
|
TYPE_TARGET_TYPE (t) = get_pdb_type (pli, tid);
|
|
|
|
|
t->set_is_unsigned (TYPE_TARGET_TYPE (t)->is_unsigned ());
|
|
|
|
|
TYPE_LENGTH (t) = TYPE_LENGTH (TYPE_TARGET_TYPE (t));
|
|
|
|
|
|
|
|
|
|
gdb::unique_xmalloc_ptr<TI_FINDCHILDREN_PARAMS> values
|
|
|
|
|
((TI_FINDCHILDREN_PARAMS *)
|
|
|
|
|
xmalloc (sizeof (TI_FINDCHILDREN_PARAMS)
|
|
|
|
|
+ children * sizeof (ULONG)));
|
|
|
|
|
values->Count = children;
|
|
|
|
|
values->Start = 0;
|
|
|
|
|
if (pli->fSymGetTypeInfo (pli->p, pli->addr, type_index,
|
|
|
|
|
TI_FINDCHILDREN, values.get ()))
|
|
|
|
|
{
|
|
|
|
|
t->set_num_fields (children);
|
|
|
|
|
t->set_fields ((struct field *) TYPE_ZALLOC
|
|
|
|
|
(t, children * sizeof (struct field)));
|
|
|
|
|
DWORD i;
|
|
|
|
|
for (i = 0; i < children; i++)
|
|
|
|
|
{
|
|
|
|
|
DWORD dk;
|
|
|
|
|
if (pli->fSymGetTypeInfo (pli->p, pli->addr,
|
|
|
|
|
values->ChildId[i],
|
|
|
|
|
TI_GET_SYMTAG, &tag)
|
|
|
|
|
&& tag == SymTagData
|
|
|
|
|
&& pli->fSymGetTypeInfo (pli->p, pli->addr,
|
|
|
|
|
values->ChildId[i],
|
|
|
|
|
TI_GET_DATAKIND, &dk)
|
|
|
|
|
&& dk == DataIsConstant
|
|
|
|
|
&& pli->fSymGetTypeInfo (pli->p, pli->addr,
|
|
|
|
|
values->ChildId[i],
|
|
|
|
|
TI_GET_SYMNAME, &nameW))
|
|
|
|
|
{
|
|
|
|
|
t->field (i).set_name (wchar_to_objfile
|
|
|
|
|
(pli, nameW));
|
|
|
|
|
t->field (i).set_loc_enumval
|
|
|
|
|
(get_pdb_int_constant (pli, values->ChildId[i]));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return t;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ot->builtin_void;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static type *get_pdb_type (pdb_line_info *pli, DWORD type_index)
|
|
|
|
|
{
|
|
|
|
|
if (type_index >= pli->cache.size ())
|
|
|
|
|
pli->cache.resize (type_index + 1, nullptr);
|
|
|
|
|
else if (pli->cache[type_index] != nullptr)
|
|
|
|
|
return pli->cache[type_index];
|
|
|
|
|
|
|
|
|
|
type *t = get_pdb_type_cached (pli, type_index);
|
|
|
|
|
pli->cache[type_index] = t;
|
|
|
|
|
|
|
|
|
|
return t;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static BOOL CALLBACK symbol_callback(PSYMBOL_INFO si,
|
|
|
|
|
ULONG /*SymbolSize*/, PVOID UserContext);
|
|
|
|
|
|
|
|
|
|
static void pdb_enum_locals(pdb_line_info *pli, PSYMBOL_INFO si)
|
|
|
|
|
{
|
|
|
|
|
pending **local_symbols = pli->local_symbols;
|
|
|
|
|
pli->local_symbols = pli->builder->get_local_symbols ();
|
|
|
|
|
IMAGEHLP_STACK_FRAME isf;
|
|
|
|
|
memset (&isf, 0, sizeof (isf));
|
|
|
|
|
isf.InstructionOffset = si->Address;
|
|
|
|
|
pli->fSymSetContext (pli->p, &isf, NULL);
|
|
|
|
|
pli->fSymEnumSymbols (pli->p, 0, NULL, symbol_callback, pli);
|
|
|
|
|
pli->local_symbols = local_symbols;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static BOOL CALLBACK block_callback(PSYMBOL_INFO si,
|
|
|
|
|
ULONG /*SymbolSize*/, PVOID UserContext)
|
|
|
|
|
{
|
|
|
|
|
pdb_line_info *pli = (pdb_line_info *) UserContext;
|
|
|
|
|
|
|
|
|
|
ULONG64 length;
|
|
|
|
|
if (si->Tag == SymTagBlock
|
|
|
|
|
&& pli->fSymGetTypeInfo (pli->p, pli->addr, si->info,
|
|
|
|
|
TI_GET_LENGTH, &length))
|
|
|
|
|
{
|
|
|
|
|
ULONGEST addr = si->Address + pli->base_ofs;
|
|
|
|
|
|
|
|
|
|
pli->builder->push_context (0, addr);
|
|
|
|
|
|
|
|
|
|
pdb_enum_locals (pli, si);
|
|
|
|
|
|
|
|
|
|
pli->fSymSearch (pli->p, 0, 0, SymTagBlock, NULL, 0,
|
|
|
|
|
block_callback, pli, 0);
|
|
|
|
|
|
|
|
|
|
struct context_stack cstk = pli->builder->pop_context ();
|
|
|
|
|
|
|
|
|
|
if (*pli->builder->get_local_symbols () != NULL)
|
|
|
|
|
pli->builder->finish_block (0, cstk.old_blocks, NULL,
|
|
|
|
|
addr, addr + length);
|
|
|
|
|
|
|
|
|
|
*pli->builder->get_local_symbols () = cstk.locals;
|
|
|
|
|
pli->builder->set_local_using_directives (cstk.local_using_directives);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static symbol *
|
|
|
|
|
pdb_read_data_symbol (PSYMBOL_INFO si, pdb_line_info *pli, const char *name)
|
|
|
|
|
{
|
|
|
|
|
objfile *objfile = pli->objfile;
|
|
|
|
|
|
|
|
|
|
if (si->info >= pli->cache.size ())
|
|
|
|
|
pli->cache.resize (si->info + 1, nullptr);
|
|
|
|
|
else if (pli->cache[si->info] != nullptr)
|
|
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
|
|
symbol *sym = new (&objfile->objfile_obstack) symbol;
|
|
|
|
|
sym->set_linkage_name (objfile->intern (name));
|
|
|
|
|
sym->set_language (language_c, &objfile->objfile_obstack);
|
|
|
|
|
sym->set_domain (VAR_DOMAIN);
|
|
|
|
|
type *t = get_pdb_type (pli, si->TypeIndex);
|
|
|
|
|
sym->set_type (t);
|
|
|
|
|
if (si->Flags & SYMFLAG_REGREL)
|
|
|
|
|
{
|
|
|
|
|
pdb_regrel_baton *baton
|
|
|
|
|
= XOBNEW (&objfile->objfile_obstack, pdb_regrel_baton);
|
|
|
|
|
#ifdef __x86_64__
|
|
|
|
|
if (gdbarch_ptr_bit (objfile->arch ()) == 64)
|
|
|
|
|
baton->regnum = AMD64_RSP_REGNUM;
|
|
|
|
|
else
|
|
|
|
|
#endif
|
|
|
|
|
baton->regnum = I386_EBP_REGNUM;
|
|
|
|
|
baton->offset = si->Address;
|
|
|
|
|
SYMBOL_LOCATION_BATON (sym) = baton;
|
|
|
|
|
sym->set_aclass_index (pdb_regrel_index);
|
|
|
|
|
if (si->Flags & SYMFLAG_PARAMETER)
|
|
|
|
|
sym->set_is_argument (true);
|
|
|
|
|
}
|
|
|
|
|
else if (si->Flags & SYMFLAG_TLSREL)
|
|
|
|
|
{
|
|
|
|
|
pdb_tls_baton *baton
|
|
|
|
|
= XOBNEW (&objfile->objfile_obstack, pdb_tls_baton);
|
|
|
|
|
baton->offset = si->Address;
|
|
|
|
|
#ifdef __x86_64__
|
|
|
|
|
if (gdbarch_ptr_bit (objfile->arch ()) == 64)
|
|
|
|
|
{
|
|
|
|
|
baton->tib_ofs = 88;
|
|
|
|
|
baton->ptr_size = 8;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
#endif
|
|
|
|
|
{
|
|
|
|
|
baton->tib_ofs = 44;
|
|
|
|
|
baton->ptr_size = 4;
|
|
|
|
|
}
|
|
|
|
|
baton->tls_index_sym = pli->tls_index_sym;
|
|
|
|
|
SYMBOL_LOCATION_BATON (sym) = baton;
|
|
|
|
|
sym->set_aclass_index (pdb_tls_index);
|
|
|
|
|
}
|
|
|
|
|
else if (si->Flags & 0x80000) // SYMFLAG_NULL
|
|
|
|
|
{
|
|
|
|
|
sym->set_aclass_index (LOC_OPTIMIZED_OUT);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
SET_SYMBOL_VALUE_ADDRESS (sym, si->Address + pli->base_ofs);
|
|
|
|
|
sym->set_aclass_index (LOC_STATIC);
|
|
|
|
|
}
|
|
|
|
|
if (pli->local_symbols != nullptr)
|
|
|
|
|
add_symbol_to_list (sym, pli->local_symbols);
|
|
|
|
|
else
|
|
|
|
|
add_symbol_to_list (sym, pli->builder->get_global_symbols ());
|
|
|
|
|
|
|
|
|
|
pli->cache[si->info] = t;
|
|
|
|
|
|
|
|
|
|
return sym;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static BOOL CALLBACK symbol_callback(PSYMBOL_INFO si,
|
|
|
|
|
ULONG /*SymbolSize*/, PVOID UserContext)
|
|
|
|
|
{
|
|
|
|
|
pdb_line_info *pli = (pdb_line_info *) UserContext;
|
|
|
|
|
objfile *objfile = pli->objfile;
|
|
|
|
|
ULONGEST base_ofs = pli->base_ofs;
|
|
|
|
|
|
|
|
|
|
if (si->Tag == SymTagFunction)
|
|
|
|
|
{
|
|
|
|
|
ULONGEST addr = si->Address + base_ofs;
|
|
|
|
|
|
|
|
|
|
context_stack *newobj = pli->builder->push_context (0, addr);
|
|
|
|
|
symbol *sym = new (&objfile->objfile_obstack) symbol;
|
|
|
|
|
sym->set_linkage_name (objfile->intern (si->Name));
|
|
|
|
|
sym->set_language (language_c, &objfile->objfile_obstack);
|
|
|
|
|
sym->set_domain (VAR_DOMAIN);
|
|
|
|
|
sym->set_type (get_pdb_type (pli, si->TypeIndex));
|
|
|
|
|
sym->set_aclass_index (LOC_BLOCK);
|
|
|
|
|
SET_SYMBOL_VALUE_ADDRESS (sym, addr);
|
|
|
|
|
add_symbol_to_list (sym, pli->builder->get_global_symbols ());
|
|
|
|
|
newobj->name = sym;
|
|
|
|
|
|
|
|
|
|
// locals
|
|
|
|
|
pdb_enum_locals (pli, si);
|
|
|
|
|
|
|
|
|
|
// inner scopes
|
|
|
|
|
pli->fSymSearch (pli->p, 0, 0, SymTagBlock, NULL, 0,
|
|
|
|
|
block_callback, pli, 0);
|
|
|
|
|
|
|
|
|
|
struct context_stack cstk = pli->builder->pop_context ();
|
|
|
|
|
pli->builder->finish_block (cstk.name, cstk.old_blocks, cstk.static_link,
|
|
|
|
|
addr, addr + si->Size);
|
|
|
|
|
gdbarch_make_symbol_special (objfile->arch (), cstk.name, objfile);
|
|
|
|
|
|
|
|
|
|
pli->functions.push_back (sym);
|
|
|
|
|
}
|
|
|
|
|
else if (si->Tag == SymTagData)
|
|
|
|
|
{
|
|
|
|
|
pdb_read_data_symbol (si, pli, si->Name);
|
|
|
|
|
}
|
|
|
|
|
else if (si->Tag == SymTagThunk)
|
|
|
|
|
{
|
|
|
|
|
for (symbol *sym : pli->functions)
|
|
|
|
|
{
|
|
|
|
|
if (BLOCK_START (SYMBOL_BLOCK_VALUE (sym)) == si->Value + base_ofs)
|
|
|
|
|
{
|
|
|
|
|
std::string imp_name
|
|
|
|
|
= string_printf ("__thunk_%s", sym->linkage_name ());
|
|
|
|
|
struct minimal_symbol *msym = pli->reader->record_full
|
|
|
|
|
(imp_name.c_str (), true, si->Address, mst_data, 0);
|
|
|
|
|
if (msym)
|
|
|
|
|
SET_MSYMBOL_SIZE (msym, si->Size);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (si->Tag == SymTagUDT || si->Tag == SymTagTypedef
|
|
|
|
|
|| si->Tag == SymTagEnum)
|
|
|
|
|
{
|
|
|
|
|
symbol *sym = new (&objfile->objfile_obstack) symbol;
|
|
|
|
|
sym->set_linkage_name (objfile->intern (si->Name));
|
|
|
|
|
sym->set_language (language_c, &objfile->objfile_obstack);
|
|
|
|
|
sym->set_aclass_index (LOC_TYPEDEF);
|
|
|
|
|
sym->set_domain (si->Tag == SymTagTypedef ? VAR_DOMAIN : STRUCT_DOMAIN);
|
|
|
|
|
sym->set_type (get_pdb_type (pli, si->TypeIndex));
|
|
|
|
|
add_symbol_to_list (sym, pli->builder->get_global_symbols ());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static BOOL CALLBACK line_callback(PSRCCODEINFO li, PVOID UserContext)
|
|
|
|
|
{
|
|
|
|
|
pdb_line_info *pli = (pdb_line_info *) UserContext;
|
|
|
|
|
ULONGEST addr = li->Address + pli->base_ofs;
|
|
|
|
|
if (addr > pli->max_addr)
|
|
|
|
|
pli->max_addr = addr;
|
|
|
|
|
buildsym_compunit *builder = pli->builder;
|
|
|
|
|
subfile *sf = builder->get_current_subfile ();
|
|
|
|
|
if (sf == nullptr || strcmp (sf->name, li->FileName) != 0)
|
|
|
|
|
{
|
|
|
|
|
builder->start_subfile (li->FileName);
|
|
|
|
|
sf = builder->get_current_subfile ();
|
|
|
|
|
}
|
|
|
|
|
builder->record_line (sf, li->LineNumber, 0, addr, true);
|
|
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool pdb_load_functions (const char *name, minimal_symbol_reader *reader,
|
|
|
|
|
struct objfile *objfile);
|
|
|
|
|
bool
|
|
|
|
|
pdb_load_functions (const char *name, minimal_symbol_reader *reader,
|
|
|
|
|
struct objfile *objfile)
|
|
|
|
|
{
|
|
|
|
|
if (GetModuleHandle("ucrtbase.dll") == NULL)
|
|
|
|
|
LoadLibrary("ucrtbase.dll");
|
|
|
|
|
|
|
|
|
|
HMODULE dh = LoadLibrary("dbghelp.dll");
|
|
|
|
|
if (dh == NULL)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
SymInitialize_ftype *fSymInitialize = (SymInitialize_ftype *)
|
|
|
|
|
GetProcAddress (dh, "SymInitialize");
|
|
|
|
|
SymCleanup_ftype *fSymCleanup = (SymCleanup_ftype *)
|
|
|
|
|
GetProcAddress (dh, "SymCleanup");
|
|
|
|
|
SymFromName_ftype *fSymFromName = (SymFromName_ftype *)
|
|
|
|
|
GetProcAddress (dh, "SymFromName");
|
|
|
|
|
SymEnumTypes_ftype *fSymEnumTypes = (SymEnumTypes_ftype *)
|
|
|
|
|
GetProcAddress (dh, "SymEnumTypes");
|
|
|
|
|
SymEnumSymbols_ftype *fSymEnumSymbols = (SymEnumSymbols_ftype *)
|
|
|
|
|
GetProcAddress (dh, "SymEnumSymbols");
|
|
|
|
|
SymLoadModule64_ftype *fSymLoadModule64 = (SymLoadModule64_ftype *)
|
|
|
|
|
GetProcAddress (dh, "SymLoadModule64");
|
|
|
|
|
SymGetModuleInfo64_ftype *fSymGetModuleInfo64 = (SymGetModuleInfo64_ftype *)
|
|
|
|
|
GetProcAddress (dh, "SymGetModuleInfo64");
|
|
|
|
|
SymEnumSourceLines_ftype *fSymEnumSourceLines = (SymEnumSourceLines_ftype *)
|
|
|
|
|
GetProcAddress (dh, "SymEnumSourceLines");
|
|
|
|
|
SymGetTypeInfo_ftype *fSymGetTypeInfo = (SymGetTypeInfo_ftype *)
|
|
|
|
|
GetProcAddress (dh, "SymGetTypeInfo");
|
|
|
|
|
SymSetContext_ftype *fSymSetContext = (SymSetContext_ftype *)
|
|
|
|
|
GetProcAddress (dh, "SymSetContext");
|
|
|
|
|
SymSearch_ftype *fSymSearch = (SymSearch_ftype *)
|
|
|
|
|
GetProcAddress (dh, "SymSearch");
|
|
|
|
|
if (fSymInitialize != NULL && fSymCleanup != NULL
|
|
|
|
|
&& fSymLoadModule64 != NULL && fSymGetModuleInfo64 != NULL
|
|
|
|
|
&& fSymFromName != NULL
|
|
|
|
|
&& fSymEnumTypes != NULL && fSymEnumSymbols != NULL
|
|
|
|
|
&& fSymEnumSourceLines != NULL && fSymGetTypeInfo != NULL
|
|
|
|
|
&& fSymSetContext != NULL && fSymSearch != NULL)
|
|
|
|
|
{
|
|
|
|
|
HANDLE p = (void *) 1;
|
|
|
|
|
|
|
|
|
|
fSymInitialize (p, NULL, FALSE);
|
|
|
|
|
DWORD64 addr = fSymLoadModule64(p, NULL, name, NULL, 0, 0);
|
|
|
|
|
|
|
|
|
|
IMAGEHLP_MODULE64 mi;
|
|
|
|
|
memset (&mi, 0, sizeof(mi));
|
|
|
|
|
mi.SizeOfStruct = sizeof(mi);
|
|
|
|
|
if (!fSymGetModuleInfo64 (p, addr, &mi) || mi.SymType != SymPdb)
|
|
|
|
|
{
|
|
|
|
|
fSymCleanup(p);
|
|
|
|
|
FreeLibrary(dh);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::unique_ptr<buildsym_compunit> builder;
|
|
|
|
|
builder.reset (new buildsym_compunit
|
|
|
|
|
(objfile, name, NULL, language_c, addr));
|
|
|
|
|
pdb_line_info pli;
|
|
|
|
|
pli.reader = reader;
|
|
|
|
|
pli.builder = builder.get ();
|
|
|
|
|
pli.local_symbols = nullptr;
|
|
|
|
|
pli.objfile = objfile;
|
|
|
|
|
pli.p = p;
|
|
|
|
|
pli.fSymGetTypeInfo = fSymGetTypeInfo;
|
|
|
|
|
pli.fSymEnumSymbols = fSymEnumSymbols;
|
|
|
|
|
pli.fSymSetContext = fSymSetContext;
|
|
|
|
|
pli.fSymSearch = fSymSearch;
|
|
|
|
|
pli.addr = addr;
|
|
|
|
|
pli.base_ofs = objfile->text_section_offset ();
|
|
|
|
|
pli.max_addr = 0;
|
|
|
|
|
pli.tls_index_sym = nullptr;
|
|
|
|
|
|
|
|
|
|
SYMBOL_INFO si;
|
|
|
|
|
memset (&si, 0, sizeof (si));
|
|
|
|
|
si.SizeOfStruct = sizeof (si);
|
|
|
|
|
if (fSymFromName (p, "_tls_index", &si))
|
|
|
|
|
pli.tls_index_sym = pdb_read_data_symbol (&si, &pli, "_tls_index");
|
|
|
|
|
|
|
|
|
|
fSymEnumTypes(p, addr, symbol_callback, &pli);
|
|
|
|
|
fSymEnumSymbols(p, addr, NULL, symbol_callback, &pli);
|
|
|
|
|
|
|
|
|
|
fSymSearch (p, addr, 0, SymTagThunk, NULL, 0, symbol_callback, &pli,
|
|
|
|
|
SYMSEARCH_RECURSE);
|
|
|
|
|
|
|
|
|
|
fSymEnumSourceLines(p, addr, NULL, NULL, 0, 0, line_callback, &pli);
|
|
|
|
|
builder->end_symtab (pli.max_addr, SECT_OFF_TEXT (objfile));
|
|
|
|
|
|
|
|
|
|
fSymCleanup(p);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FreeLibrary(dh);
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void _initialize_check_for_gdb_ini ();
|
|
|
|
|
void
|
|
|
|
|
_initialize_check_for_gdb_ini ()
|
|
|
|
|
|