Compare commits

...

18 Commits

Author SHA1 Message Date
Hannes Domani
80f0e38f11 PDB: Increase maximum number of "aclass" registrations 2022-04-20 22:03:36 +02:00
Hannes Domani
30605047d3 PDB: DLLs 2022-04-18 18:58:11 +02:00
Hannes Domani
54ba83a63d PDB: optimized-out variables 2022-04-18 16:28:00 +02:00
Hannes Domani
5f758d8cea PDB: thread-local variables 2022-04-18 16:27:59 +02:00
Hannes Domani
701a2f8749 PDB: add wchar/bool base types 2022-04-18 16:27:58 +02:00
Hannes Domani
9aa93eac41 PDB: refactor variable symbols 2022-04-18 16:27:57 +02:00
Hannes Domani
48852b4dc8 PDB: bitfields 2022-04-18 16:27:56 +02:00
Hannes Domani
f6201a399a PDB: on i386 local variables are relative to $ebp 2022-04-16 20:52:56 +02:00
Hannes Domani
966dffcb4f PDB: skip jump thunks for i386 also 2022-04-16 18:21:19 +02:00
Hannes Domani
232738a7b1 PDB: inner function scopes 2022-04-16 18:21:13 +02:00
Hannes Domani
b594ecd867 PDB: enums 2022-04-16 18:21:03 +02:00
Hannes Domani
df03b57cee PDB: typedefs 2022-04-16 18:20:55 +02:00
Hannes Domani
7ceacbf8ad PDB: skip jump thunks 2022-04-15 20:38:46 +02:00
Hannes Domani
020fd79ff7 Fix overflow when reading the exception directory 2022-04-15 20:38:35 +02:00
Hannes Domani
3abda17b82 PDB: local variables relative to $rsp 2022-04-13 20:27:45 +02:00
Hannes Domani
8b27d76d9e PDB: array 2022-04-11 19:38:10 +02:00
Hannes Domani
e4405d097d PDB: cache types 2022-04-11 19:37:59 +02:00
Hannes Domani
bf22f1d710 pdb, part one 2022-04-10 20:45:41 +02:00
5 changed files with 932 additions and 5 deletions

View File

@@ -1033,7 +1033,7 @@ amd64_windows_find_unwind_info (struct gdbarch *gdbarch, CORE_ADDR pc,
lo = 0; lo = 0;
hi = dir->Size / sizeof (struct external_pex64_runtime_function); hi = dir->Size / sizeof (struct external_pex64_runtime_function);
*unwind_info = 0; *unwind_info = 0;
while (lo <= hi) while (lo < hi)
{ {
unsigned long mid = lo + (hi - lo) / 2; unsigned long mid = lo + (hi - lo) / 2;
struct external_pex64_runtime_function d; struct external_pex64_runtime_function d;
@@ -1046,7 +1046,7 @@ amd64_windows_find_unwind_info (struct gdbarch *gdbarch, CORE_ADDR pc,
sa = extract_unsigned_integer (d.rva_BeginAddress, 4, byte_order); sa = extract_unsigned_integer (d.rva_BeginAddress, 4, byte_order);
ea = extract_unsigned_integer (d.rva_EndAddress, 4, byte_order); ea = extract_unsigned_integer (d.rva_EndAddress, 4, byte_order);
if (pc < base + sa) if (pc < base + sa)
hi = mid - 1; hi = mid;
else if (pc >= base + ea) else if (pc >= base + ea)
lo = mid + 1; lo = mid + 1;
else if (pc >= base + sa && pc < base + ea) else if (pc >= base + sa && pc < base + ea)
@@ -1237,7 +1237,8 @@ amd64_windows_skip_trampoline_code (struct frame_info *frame, CORE_ADDR pc)
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
/* Check for jmp *<offset>(%rip) (jump near, absolute indirect (/4)). */ /* Check for jmp *<offset>(%rip) (jump near, absolute indirect (/4)). */
if (pc && read_memory_unsigned_integer (pc, 2, byte_order) == 0x25ff) unsigned instr = pc ? read_memory_unsigned_integer (pc, 2, byte_order) : 0;
if (instr == 0x25ff)
{ {
/* Get opcode offset and see if we can find a reference in our data. */ /* Get opcode offset and see if we can find a reference in our data. */
ULONGEST offset ULONGEST offset
@@ -1260,6 +1261,18 @@ amd64_windows_skip_trampoline_code (struct frame_info *frame, CORE_ADDR pc)
= read_memory_unsigned_integer (indirect_addr, 8, byte_order); = read_memory_unsigned_integer (indirect_addr, 8, byte_order);
} }
} }
else if ((instr & 0xff) == 0xe9)
{
struct minimal_symbol *sym = lookup_minimal_symbol_by_pc (pc).minsym;
const char *symname = sym ? sym->linkage_name () : NULL;
if (symname && startswith (symname, "__thunk_"))
{
ULONGEST offset
= read_memory_unsigned_integer (pc + 1, 4, byte_order);
destination = pc + offset + 5;
}
}
return destination; return destination;
} }

View File

@@ -325,6 +325,12 @@ pe_as32 (void *ptr)
return b[0] + (b[1] << 8) + (b[2] << 16) + (b[3] << 24); return b[0] + (b[1] << 8) + (b[2] << 16) + (b[3] << 24);
} }
#ifdef _WIN32
bool pdb_load_functions (const char *name, minimal_symbol_reader *reader,
struct objfile *objfile);
#endif
/* Read the (non-debug) export symbol table from a portable /* Read the (non-debug) export symbol table from a portable
executable. Code originally lifted from the ld function executable. Code originally lifted from the ld function
@@ -384,6 +390,11 @@ read_pe_exported_syms (minimal_symbol_reader &reader,
return; return;
} }
#ifdef _WIN32
if (pdb_load_functions (dll_name, &reader, objfile))
return;
#endif
/* Get pe_header, optional header and numbers of export entries. */ /* Get pe_header, optional header and numbers of export entries. */
pe_header_offset = pe_get32 (dll, 0x3c); pe_header_offset = pe_get32 (dll, 0x3c);
opthdr_ofs = pe_header_offset + 4 + 20; opthdr_ofs = pe_header_offset + 4 + 20;

View File

@@ -92,7 +92,27 @@ static int i386_windows_gregset_reg_offset[] =
static CORE_ADDR static CORE_ADDR
i386_windows_skip_trampoline_code (struct frame_info *frame, CORE_ADDR pc) i386_windows_skip_trampoline_code (struct frame_info *frame, CORE_ADDR pc)
{ {
return i386_pe_skip_trampoline_code (frame, pc, NULL); CORE_ADDR addr = i386_pe_skip_trampoline_code (frame, pc, NULL);
if (addr == 0 && pc != 0)
{
struct gdbarch *gdbarch = get_frame_arch (frame);
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
if (read_memory_unsigned_integer (pc, 1, byte_order) == 0xe9)
{
struct minimal_symbol *sym = lookup_minimal_symbol_by_pc (pc).minsym;
const char *symname = sym ? sym->linkage_name () : NULL;
if (symname && (startswith (symname, "__thunk_")
|| startswith (symname, "_thunk_")))
{
ULONGEST offset
= read_memory_unsigned_integer (pc + 1, 4, byte_order);
return pc + offset + 5;
}
}
}
return addr;
} }
static const char * static const char *

View File

@@ -6480,7 +6480,7 @@ static int next_aclass_value = LOC_FINAL_VALUE;
/* The maximum number of "aclass" registrations we support. This is /* The maximum number of "aclass" registrations we support. This is
constant for convenience. */ constant for convenience. */
#define MAX_SYMBOL_IMPLS (LOC_FINAL_VALUE + 10) #define MAX_SYMBOL_IMPLS (LOC_FINAL_VALUE + 16)
/* The objects representing the various "aclass" values. The elements /* The objects representing the various "aclass" values. The elements
from 0 up to LOC_FINAL_VALUE-1 represent themselves, and subsequent from 0 up to LOC_FINAL_VALUE-1 represent themselves, and subsequent

View File

@@ -60,6 +60,9 @@
#include "i386-tdep.h" #include "i386-tdep.h"
#include "i387-tdep.h" #include "i387-tdep.h"
#ifdef __x86_64__
#include "amd64-tdep.h"
#endif
#include "windows-tdep.h" #include "windows-tdep.h"
#include "windows-nat.h" #include "windows-nat.h"
@@ -71,6 +74,8 @@
#include "gdbsupport/gdb_wait.h" #include "gdbsupport/gdb_wait.h"
#include "nat/windows-nat.h" #include "nat/windows-nat.h"
#include "gdbsupport/symbol.h" #include "gdbsupport/symbol.h"
#include "buildsym.h"
#include "block.h"
using namespace windows_nat; 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> &registers_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 ();
void void
_initialize_windows_nat () _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\ cannot automatically find executable file or library to read symbols.\n\
Use \"file\" or \"dll\" command to load executable/libraries directly.")); 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. */ /* 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; 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 ();
void void
_initialize_check_for_gdb_ini () _initialize_check_for_gdb_ini ()