forked from Imagelibrary/binutils-gdb
Compare commits
18 Commits
binutils-2
...
users/ssbs
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
80f0e38f11 | ||
|
|
30605047d3 | ||
|
|
54ba83a63d | ||
|
|
5f758d8cea | ||
|
|
701a2f8749 | ||
|
|
9aa93eac41 | ||
|
|
48852b4dc8 | ||
|
|
f6201a399a | ||
|
|
966dffcb4f | ||
|
|
232738a7b1 | ||
|
|
b594ecd867 | ||
|
|
df03b57cee | ||
|
|
7ceacbf8ad | ||
|
|
020fd79ff7 | ||
|
|
3abda17b82 | ||
|
|
8b27d76d9e | ||
|
|
e4405d097d | ||
|
|
bf22f1d710 |
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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 *
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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> ®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 ();
|
||||||
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 ()
|
||||||
|
|||||||
Reference in New Issue
Block a user