ReactOS  0.4.15-dev-4921-g25fcdc5
dbghelp.c
Go to the documentation of this file.
1 /*
2  * File dbghelp.c - generic routines (process) for dbghelp DLL
3  *
4  * Copyright (C) 2004, Eric Pouech
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20 
21 #ifndef DBGHELP_STATIC_LIB
22 
23 #include <unistd.h>
24 #include "dbghelp_private.h"
25 #include "winternl.h"
26 #include "winerror.h"
27 #include "psapi.h"
28 #include "wine/debug.h"
29 #include "wdbgexts.h"
30 #include "winnls.h"
31 #else
32 #include "dbghelp_private.h"
33 #include "wdbgexts.h"
34 #endif
35 
37 
38 /* TODO
39  * - support for symbols' types is still partly missing
40  * + C++ support
41  * + we should store the underlying type for an enum in the symt_enum struct
42  * + for enums, we store the names & values (associated to the enum type),
43  * but those values are not directly usable from a debugger (that's why, I
44  * assume, that we have also to define constants for enum values, as
45  * Codeview does BTW.
46  * + SymEnumTypes should only return *user* defined types (UDT, typedefs...) not
47  * all the types stored/used in the modules (like char*)
48  * - SymGetLine{Next|Prev} don't work as expected (they don't seem to work across
49  * functions, and even across function blocks...). Basically, for *Next* to work
50  * it requires an address after the prolog of the func (the base address of the
51  * func doesn't work)
52  * - most options (dbghelp_options) are not used (loading lines...)
53  * - in symbol lookup by name, we don't use RE everywhere we should. Moreover, when
54  * we're supposed to use RE, it doesn't make use of our hash tables. Therefore,
55  * we could use hash if name isn't a RE, and fall back to a full search when we
56  * get a full RE
57  * - msc:
58  * + we should add parameters' types to the function's signature
59  * while processing a function's parameters
60  * + add support for function-less labels (as MSC seems to define them)
61  * + C++ management
62  * - stabs:
63  * + when, in a same module, the same definition is used in several compilation
64  * units, we get several definitions of the same object (especially
65  * struct/union). we should find a way not to duplicate them
66  * + in some cases (dlls/user/dialog16.c DIALOG_GetControl16), the same static
67  * global variable is defined several times (at different scopes). We are
68  * getting several of those while looking for a unique symbol. Part of the
69  * issue is that we don't give a scope to a static variable inside a function
70  * + C++ management
71  */
72 
75 #ifndef DBGHELP_STATIC_LIB
77 #endif
78 
79 static struct process* process_first /* = NULL */;
80 
81 #ifndef DBGHELP_STATIC_LIB
83 {
84  switch (reason)
85  {
86  case DLL_PROCESS_ATTACH:
89  break;
90  }
91  return TRUE;
92 }
93 #endif
94 
95 /******************************************************************
96  * process_find_by_handle
97  *
98  */
100 {
101  struct process* p;
102 
103  for (p = process_first; p && p->handle != hProcess; p = p->next);
105  return p;
106 }
107 
108 /******************************************************************
109  * validate_addr64 (internal)
110  *
111  */
113 {
114  if (sizeof(void*) == sizeof(int) && (addr >> 32))
115  {
116  FIXME("Unsupported address %s\n", wine_dbgstr_longlong(addr));
118  return FALSE;
119  }
120  return TRUE;
121 }
122 
123 /******************************************************************
124  * fetch_buffer
125  *
126  * Ensures process' internal buffer is large enough.
127  */
128 void* fetch_buffer(struct process* pcs, unsigned size)
129 {
130  if (size > pcs->buffer_size)
131  {
132  if (pcs->buffer)
133  pcs->buffer = HeapReAlloc(GetProcessHeap(), 0, pcs->buffer, size);
134  else
135  pcs->buffer = HeapAlloc(GetProcessHeap(), 0, size);
136  pcs->buffer_size = (pcs->buffer) ? size : 0;
137  }
138  return pcs->buffer;
139 }
140 
141 #ifndef DBGHELP_STATIC_LIB
142 const char* wine_dbgstr_addr(const ADDRESS64* addr)
143 {
144  if (!addr) return "(null)";
145  switch (addr->Mode)
146  {
147  case AddrModeFlat:
148  return wine_dbg_sprintf("flat<%s>", wine_dbgstr_longlong(addr->Offset));
149  case AddrMode1616:
150  return wine_dbg_sprintf("1616<%04x:%04x>", addr->Segment, (DWORD)addr->Offset);
151  case AddrMode1632:
152  return wine_dbg_sprintf("1632<%04x:%08x>", addr->Segment, (DWORD)addr->Offset);
153  case AddrModeReal:
154  return wine_dbg_sprintf("real<%04x:%04x>", addr->Segment, (DWORD)addr->Offset);
155  default:
156  return "unknown";
157  }
158 }
159 #endif
160 
161 extern struct cpu cpu_i386, cpu_x86_64, cpu_arm, cpu_arm64;
162 
163 #ifndef DBGHELP_STATIC_LIB
164 static struct cpu* dbghelp_cpus[] = {&cpu_i386, &cpu_x86_64, &cpu_arm, &cpu_arm64, NULL};
165 #else
166 static struct cpu* dbghelp_cpus[] = {&cpu_i386, NULL};
167 #endif
168 
170 #if defined(__i386__) || defined(DBGHELP_STATIC_LIB)
171  &cpu_i386
172 #elif defined(__x86_64__)
173  &cpu_x86_64
174 #elif defined(__arm__)
175  &cpu_arm
176 #elif defined(__aarch64__)
177  &cpu_arm64
178 #else
179 #error define support for your CPU
180 #endif
181  ;
182 
184 {
185  struct cpu** cpu;
186 
187  for (cpu = dbghelp_cpus ; *cpu; cpu++)
188  {
189  if (cpu[0]->machine == machine) return cpu[0];
190  }
191  return NULL;
192 }
193 
195 {
196  WCHAR* search_path;
197  WCHAR* p;
198  unsigned sym_path_len;
199  unsigned alt_sym_path_len;
200 
201  sym_path_len = GetEnvironmentVariableW(L"_NT_SYMBOL_PATH", NULL, 0);
202  alt_sym_path_len = GetEnvironmentVariableW(L"_NT_ALT_SYMBOL_PATH", NULL, 0);
203 
204  /* The default symbol path is ".[;%_NT_SYMBOL_PATH%][;%_NT_ALT_SYMBOL_PATH%]".
205  * If the variables exist, the lengths include a null-terminator. We use that
206  * space for the semicolons, and only add the initial dot and the final null. */
207  search_path = HeapAlloc(GetProcessHeap(), 0,
208  (1 + sym_path_len + alt_sym_path_len + 1) * sizeof(WCHAR));
209  if (!search_path) return NULL;
210 
211  p = search_path;
212  *p++ = L'.';
213  if (sym_path_len)
214  {
215  *p++ = L';';
216  GetEnvironmentVariableW(L"_NT_SYMBOL_PATH", p, sym_path_len);
217  p += sym_path_len - 1;
218  }
219 
220  if (alt_sym_path_len)
221  {
222  *p++ = L';';
223  GetEnvironmentVariableW(L"_NT_ALT_SYMBOL_PATH", p, alt_sym_path_len);
224  p += alt_sym_path_len - 1;
225  }
226  *p = L'\0';
227 
228  return search_path;
229 }
230 
231 /******************************************************************
232  * SymSetSearchPathW (DBGHELP.@)
233  *
234  */
236 {
237  struct process* pcs = process_find_by_handle(hProcess);
238  WCHAR* search_path_buffer;
239 
240  if (!pcs) return FALSE;
241 
242  if (searchPath)
243  {
244  search_path_buffer = HeapAlloc(GetProcessHeap(), 0,
245  (lstrlenW(searchPath) + 1) * sizeof(WCHAR));
246  if (!search_path_buffer) return FALSE;
247  lstrcpyW(search_path_buffer, searchPath);
248  }
249  else
250  {
251  search_path_buffer = make_default_search_path();
252  if (!search_path_buffer) return FALSE;
253  }
254  HeapFree(GetProcessHeap(), 0, pcs->search_path);
255  pcs->search_path = search_path_buffer;
256  return TRUE;
257 }
258 
259 /******************************************************************
260  * SymSetSearchPath (DBGHELP.@)
261  *
262  */
264 {
265  BOOL ret = FALSE;
266  unsigned len;
267  WCHAR* sp = NULL;
268 
269  if (searchPath)
270  {
271  len = MultiByteToWideChar(CP_ACP, 0, searchPath, -1, NULL, 0);
272  sp = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
273  if (!sp) return FALSE;
274  MultiByteToWideChar(CP_ACP, 0, searchPath, -1, sp, len);
275  }
276 
278 
279  HeapFree(GetProcessHeap(), 0, sp);
280  return ret;
281 }
282 
283 /***********************************************************************
284  * SymGetSearchPathW (DBGHELP.@)
285  */
287  DWORD SearchPathLength)
288 {
289  struct process* pcs = process_find_by_handle(hProcess);
290  if (!pcs) return FALSE;
291 
292  lstrcpynW(szSearchPath, pcs->search_path, SearchPathLength);
293  return TRUE;
294 }
295 
296 /***********************************************************************
297  * SymGetSearchPath (DBGHELP.@)
298  */
300  DWORD SearchPathLength)
301 {
302  WCHAR* buffer = HeapAlloc(GetProcessHeap(), 0, SearchPathLength * sizeof(WCHAR));
303  BOOL ret = FALSE;
304 
305  if (buffer)
306  {
307  ret = SymGetSearchPathW(hProcess, buffer, SearchPathLength);
308  if (ret)
309  WideCharToMultiByte(CP_ACP, 0, buffer, SearchPathLength,
310  szSearchPath, SearchPathLength, NULL, NULL);
312  }
313  return ret;
314 }
315 
316 #ifndef DBGHELP_STATIC_LIB
317 /******************************************************************
318  * invade_process
319  *
320  * SymInitialize helper: loads in dbghelp all known (and loaded modules)
321  * this assumes that hProcess is a handle on a valid process
322  */
324 {
325  WCHAR tmp[MAX_PATH];
326  HANDLE hProcess = user;
327 
329  lstrcpynW(tmp, name, ARRAY_SIZE(tmp));
330 
331  SymLoadModuleExW(hProcess, 0, tmp, name, base, size, NULL, 0);
332  return TRUE;
333 }
334 
335 const WCHAR *process_getenv(const struct process *process, const WCHAR *name)
336 {
337  size_t name_len;
338  const WCHAR *iter;
339 
340  if (!process->environment) return NULL;
341  name_len = lstrlenW(name);
342 
343  for (iter = process->environment; *iter; iter += lstrlenW(iter) + 1)
344  {
345  if (!wcsnicmp(iter, name, name_len) && iter[name_len] == '=')
346  return iter + name_len + 1;
347  }
348 
349  return NULL;
350 }
351 
352 /******************************************************************
353  * check_live_target
354  *
355  */
356 static BOOL check_live_target(struct process* pcs)
357 {
359  ULONG_PTR base = 0, env = 0;
360 
361  if (!GetProcessId(pcs->handle)) return FALSE;
362  if (GetEnvironmentVariableA("DBGHELP_NOLIVE", NULL, 0)) return FALSE;
363 
365  &pbi, sizeof(pbi), NULL ))
366  return FALSE;
367 
368  if (!pcs->is_64bit)
369  {
370  DWORD env32;
371  PEB32 peb32;
372  C_ASSERT(sizeof(void*) != 4 || FIELD_OFFSET(RTL_USER_PROCESS_PARAMETERS, Environment) == 0x48);
373  if (!ReadProcessMemory(pcs->handle, pbi.PebBaseAddress, &peb32, sizeof(peb32), NULL)) return FALSE;
374  base = peb32.Reserved[0];
375  if (read_process_memory(pcs, peb32.ProcessParameters + 0x48, &env32, sizeof(env32))) env = env32;
376  }
377  else
378  {
379  PEB peb;
380  if (!ReadProcessMemory(pcs->handle, pbi.PebBaseAddress, &peb, sizeof(peb), NULL)) return FALSE;
381  base = peb.Reserved[0];
383  }
384 
385 #ifdef __REACTOS__
386  /* Wine store their loader base address in peb.reserved[0] and load its symbol from there.
387  * ReactOS does not care about it, we are just happy if we managed to read the value */
388  base = 1;
389 #endif
390 
391  /* read debuggee environment block */
392  if (env)
393  {
394  size_t buf_size = 0, i, last_null = -1;
395  WCHAR *buf = NULL;
396 
397  do
398  {
399  size_t read_size = sysinfo.dwAllocationGranularity - (env & (sysinfo.dwAllocationGranularity - 1));
400  if (buf)
401  {
402  WCHAR *new_buf;
403  if (!(new_buf = realloc(buf, buf_size + read_size))) break;
404  buf = new_buf;
405  }
406  else if(!(buf = malloc(read_size))) break;
407 
408  if (!read_process_memory(pcs, env, (char*)buf + buf_size, read_size)) break;
409  for (i = buf_size / sizeof(WCHAR); i < (buf_size + read_size) / sizeof(WCHAR); i++)
410  {
411  if (buf[i]) continue;
412  if (last_null + 1 == i)
413  {
414  pcs->environment = realloc(buf, (i + 1) * sizeof(WCHAR));
415  buf = NULL;
416  break;
417  }
418  last_null = i;
419  }
420  env += read_size;
421  buf_size += read_size;
422  }
423  while (buf);
424  free(buf);
425  }
426 
427  if (!base) return FALSE;
428 
429  TRACE("got debug info address %#lx from PEB %p\n", base, pbi.PebBaseAddress);
430 #ifndef __REACTOS__
432  WARN("couldn't load process debug info at %#lx\n", base);
433 #endif
434  return TRUE;
435 }
436 #endif
437 
438 /******************************************************************
439  * SymInitializeW (DBGHELP.@)
440  *
441  * The initialisation of a dbghelp's context.
442  * Note that hProcess doesn't need to be a valid process handle (except
443  * when fInvadeProcess is TRUE).
444  * Since we also allow loading ELF (pure) libraries and Wine ELF libraries
445  * containing PE (and NE) module(s), here's how we handle it:
446  * - we load every module (ELF, NE, PE) passed in SymLoadModule
447  * - in fInvadeProcess (in SymInitialize) is TRUE, we set up what is called ELF
448  * synchronization: hProcess should be a valid process handle, and we hook
449  * ourselves on hProcess's loaded ELF-modules, and keep this list in sync with
450  * our internal ELF modules representation (loading / unloading). This way,
451  * we'll pair every loaded builtin PE module with its ELF counterpart (and
452  * access its debug information).
453  * - if fInvadeProcess (in SymInitialize) is FALSE, we check anyway if the
454  * hProcess refers to a running process. We use some heuristics here, so YMMV.
455  * If we detect a live target, then we get the same handling as if
456  * fInvadeProcess is TRUE (except that the modules are not loaded). Otherwise,
457  * we won't be able to make the peering between a builtin PE module and its ELF
458  * counterpart. Hence we won't be able to provide the requested debug
459  * information. We'll however be able to load native PE modules (and their
460  * debug information) without any trouble.
461  * Note also that this scheme can be intertwined with the deferred loading
462  * mechanism (ie only load the debug information when we actually need it).
463  */
464 BOOL WINAPI SymInitializeW(HANDLE hProcess, PCWSTR UserSearchPath, BOOL fInvadeProcess)
465 {
466  struct process* pcs;
467  BOOL wow64, child_wow64;
468 
469  TRACE("(%p %s %u)\n", hProcess, debugstr_w(UserSearchPath), fInvadeProcess);
470 
472  {
473  WARN("the symbols for this process have already been initialized!\n");
474 
475  /* MSDN says to only call this function once unless SymCleanup() has been called since the last call.
476  It also says to call SymRefreshModuleList() instead if you just want the module list refreshed.
477  Native still returns TRUE even if the process has already been initialized. */
478  return TRUE;
479  }
480 
482 
483  if (GetProcessId(hProcess) && !IsWow64Process(hProcess, &child_wow64))
484  return FALSE;
485 
486  pcs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pcs));
487  if (!pcs) return FALSE;
488 
489  pcs->handle = hProcess;
490  pcs->is_64bit = (sizeof(void *) == 8 || wow64) && !child_wow64;
491  pcs->loader = &no_loader_ops; /* platform-specific initialization will override it if loader debug info can be found */
492 
493  if (UserSearchPath)
494  {
496  (lstrlenW(UserSearchPath) + 1) * sizeof(WCHAR)),
497  UserSearchPath);
498  }
499  else
500  {
502  }
503 
504  pcs->lmodules = NULL;
505  pcs->dbg_hdr_addr = 0;
506  pcs->next = process_first;
507  process_first = pcs;
508 
509 #ifndef DBGHELP_STATIC_LIB
510  if (check_live_target(pcs))
511  {
512  if (fInvadeProcess)
514  if (pcs->loader) pcs->loader->synchronize_module_list(pcs);
515  }
516  else if (fInvadeProcess)
517 #else
518  if (fInvadeProcess)
519 #endif
520  {
523  return FALSE;
524  }
525 
526  return TRUE;
527 }
528 
529 /******************************************************************
530  * SymInitialize (DBGHELP.@)
531  *
532  *
533  */
534 BOOL WINAPI SymInitialize(HANDLE hProcess, PCSTR UserSearchPath, BOOL fInvadeProcess)
535 {
536  WCHAR* sp = NULL;
537  BOOL ret;
538 
539  if (UserSearchPath)
540  {
541  unsigned len;
542 
543  len = MultiByteToWideChar(CP_ACP, 0, UserSearchPath, -1, NULL, 0);
544  sp = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
545  MultiByteToWideChar(CP_ACP, 0, UserSearchPath, -1, sp, len);
546  }
547 
548  ret = SymInitializeW(hProcess, sp, fInvadeProcess);
549  HeapFree(GetProcessHeap(), 0, sp);
550  return ret;
551 }
552 
553 /******************************************************************
554  * SymCleanup (DBGHELP.@)
555  *
556  */
558 {
559  struct process** ppcs;
560  struct process* next;
561 
562  for (ppcs = &process_first; *ppcs; ppcs = &(*ppcs)->next)
563  {
564  if ((*ppcs)->handle == hProcess)
565  {
566  while ((*ppcs)->lmodules) module_remove(*ppcs, (*ppcs)->lmodules);
567 
568  HeapFree(GetProcessHeap(), 0, (*ppcs)->search_path);
569  free((*ppcs)->environment);
570  next = (*ppcs)->next;
571  HeapFree(GetProcessHeap(), 0, *ppcs);
572  *ppcs = next;
573  return TRUE;
574  }
575  }
576 
577  ERR("this process has not had SymInitialize() called for it!\n");
578  return FALSE;
579 }
580 
581 /******************************************************************
582  * SymSetOptions (DBGHELP.@)
583  *
584  */
586 {
587  struct process* pcs;
588 
589  for (pcs = process_first; pcs; pcs = pcs->next)
590  {
591  pcs_callback(pcs, CBA_SET_OPTIONS, &opts);
592  }
593  return dbghelp_options = opts;
594 }
595 
596 /******************************************************************
597  * SymGetOptions (DBGHELP.@)
598  *
599  */
601 {
602  return dbghelp_options;
603 }
604 
605 /******************************************************************
606  * SymSetExtendedOption (DBGHELP.@)
607  *
608  */
610 {
611  BOOL old = FALSE;
612 
613  switch(option)
614  {
616  old = dbghelp_opt_native;
618  break;
619  default:
620  FIXME("Unsupported option %d with value %d\n", option, value);
621  }
622 
623  return old;
624 }
625 
626 /******************************************************************
627  * SymGetExtendedOption (DBGHELP.@)
628  *
629  */
631 {
632  switch(option)
633  {
635  return dbghelp_opt_native;
636  default:
637  FIXME("Unsupported option %d\n", option);
638  }
639 
640  return FALSE;
641 }
642 
643 /******************************************************************
644  * SymSetParentWindow (DBGHELP.@)
645  *
646  */
648 {
649  /* Save hwnd so it can be used as parent window */
650  FIXME("(%p): stub\n", hwnd);
651  return TRUE;
652 }
653 
654 /******************************************************************
655  * SymSetContext (DBGHELP.@)
656  *
657  */
660 {
661  struct process* pcs = process_find_by_handle(hProcess);
662  if (!pcs) return FALSE;
663 
664  if (pcs->ctx_frame.ReturnOffset == StackFrame->ReturnOffset &&
665  pcs->ctx_frame.FrameOffset == StackFrame->FrameOffset &&
666  pcs->ctx_frame.StackOffset == StackFrame->StackOffset)
667  {
668  TRACE("Setting same frame {rtn=%s frm=%s stk=%s}\n",
672  pcs->ctx_frame.InstructionOffset = StackFrame->InstructionOffset;
673  SetLastError(ERROR_ACCESS_DENIED); /* latest MSDN says ERROR_SUCCESS */
674  return FALSE;
675  }
676 
677  pcs->ctx_frame = *StackFrame;
678  /* MSDN states that Context is not (no longer?) used */
679  return TRUE;
680 }
681 
682 /******************************************************************
683  * reg_cb64to32 (internal)
684  *
685  * Registered callback for converting information from 64 bit to 32 bit
686  */
688 {
689  struct process* pcs = process_find_by_handle(hProcess);
690  void* data32;
693 
694  if (!pcs) return FALSE;
695  switch (action)
696  {
697  case CBA_DEBUG_INFO:
699  case CBA_SET_OPTIONS:
701  data32 = (void*)(DWORD_PTR)data;
702  break;
708  if (!validate_addr64(idsl64->BaseOfImage))
709  return FALSE;
710  idsl.SizeOfStruct = sizeof(idsl);
711  idsl.BaseOfImage = (DWORD)idsl64->BaseOfImage;
712  idsl.CheckSum = idsl64->CheckSum;
713  idsl.TimeDateStamp = idsl64->TimeDateStamp;
714  memcpy(idsl.FileName, idsl64->FileName, sizeof(idsl.FileName));
715  idsl.Reparse = idsl64->Reparse;
716  data32 = &idsl;
717  break;
719  case CBA_EVENT:
720  case CBA_READ_MEMORY:
721  default:
722  FIXME("No mapping for action %u\n", action);
723  return FALSE;
724  }
725  return pcs->reg_cb32(hProcess, action, data32, (PVOID)(DWORD_PTR)user);
726 }
727 
728 /******************************************************************
729  * pcs_callback (internal)
730  */
731 BOOL pcs_callback(const struct process* pcs, ULONG action, void* data)
732 {
734 
735  TRACE("%p %u %p\n", pcs, action, data);
736 
737  if (!pcs->reg_cb) return FALSE;
738  if (!pcs->reg_is_unicode)
739  {
741 
742  switch (action)
743  {
744  case CBA_DEBUG_INFO:
746  case CBA_SET_OPTIONS:
748  break;
753  idslW = data;
754  idsl.SizeOfStruct = sizeof(idsl);
755  idsl.BaseOfImage = idslW->BaseOfImage;
756  idsl.CheckSum = idslW->CheckSum;
757  idsl.TimeDateStamp = idslW->TimeDateStamp;
758  WideCharToMultiByte(CP_ACP, 0, idslW->FileName, -1,
759  idsl.FileName, sizeof(idsl.FileName), NULL, NULL);
760  idsl.Reparse = idslW->Reparse;
761  data = &idsl;
762  break;
764  case CBA_EVENT:
765  case CBA_READ_MEMORY:
766  default:
767  FIXME("No mapping for action %u\n", action);
768  return FALSE;
769  }
770  }
771  return pcs->reg_cb(pcs->handle, action, (ULONG64)(DWORD_PTR)data, pcs->reg_user);
772 }
773 
774 /******************************************************************
775  * sym_register_cb
776  *
777  * Helper for registering a callback.
778  */
782  DWORD64 user, BOOL unicode)
783 {
784  struct process* pcs = process_find_by_handle(hProcess);
785 
786  if (!pcs) return FALSE;
787  pcs->reg_cb = cb;
788  pcs->reg_cb32 = cb32;
789  pcs->reg_is_unicode = unicode;
790  pcs->reg_user = user;
791 
792  return TRUE;
793 }
794 
795 /***********************************************************************
796  * SymRegisterCallback (DBGHELP.@)
797  */
800  PVOID UserContext)
801 {
802  TRACE("(%p, %p, %p)\n",
803  hProcess, CallbackFunction, UserContext);
805 }
806 
807 /***********************************************************************
808  * SymRegisterCallback64 (DBGHELP.@)
809  */
812  ULONG64 UserContext)
813 {
814  TRACE("(%p, %p, %s)\n",
816  return sym_register_cb(hProcess, CallbackFunction, NULL, UserContext, FALSE);
817 }
818 
819 /***********************************************************************
820  * SymRegisterCallbackW64 (DBGHELP.@)
821  */
824  ULONG64 UserContext)
825 {
826  TRACE("(%p, %p, %s)\n",
828  return sym_register_cb(hProcess, CallbackFunction, NULL, UserContext, TRUE);
829 }
830 
831 /* This is imagehlp version not dbghelp !! */
832 static API_VERSION api_version = { 4, 0, 2, 0 };
833 
834 /***********************************************************************
835  * ImagehlpApiVersion (DBGHELP.@)
836  */
838 {
839  return &api_version;
840 }
841 
842 /***********************************************************************
843  * ImagehlpApiVersionEx (DBGHELP.@)
844  */
846 {
847  if (!AppVersion) return NULL;
848 
849  AppVersion->MajorVersion = api_version.MajorVersion;
850  AppVersion->MinorVersion = api_version.MinorVersion;
851  AppVersion->Revision = api_version.Revision;
852  AppVersion->Reserved = api_version.Reserved;
853 
854  return AppVersion;
855 }
856 
857 /******************************************************************
858  * ExtensionApiVersion (DBGHELP.@)
859  */
861 {
862  static EXT_API_VERSION eav = {5, 5, 5, 0};
863  return &eav;
864 }
865 
866 /******************************************************************
867  * WinDbgExtensionDllInit (DBGHELP.@)
868  */
870  unsigned short major, unsigned short minor)
871 {
872 }
873 
875 {
876  BYTE buffer[8192];
877  DWORD crc = 0;
878  DWORD len;
879 
881  while (ReadFile(handle, buffer, sizeof(buffer), &len, NULL) && len)
882  crc = RtlComputeCrc32(crc, buffer, len);
883  return crc;
884 }
#define realloc
Definition: debug_ros.c:6
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
BOOL WINAPI SymGetExtendedOption(IMAGEHLP_EXTENDED_OPTIONS option)
Definition: dbghelp.c:630
const uint16_t * PCWSTR
Definition: typedefs.h:57
PVOID PVOID PWCHAR PVOID Environment
Definition: env.c:47
BOOL pcs_callback(const struct process *pcs, ULONG action, void *data)
Definition: dbghelp.c:731
WCHAR * search_path
Definition: pdh_main.c:93
DWORD64 WINAPI SymLoadModuleExW(HANDLE, HANDLE, PCWSTR, PCWSTR, DWORD64, DWORD, PMODLOAD_DATA, DWORD)
Definition: module.c:800
#define CBA_DEFERRED_SYMBOL_LOAD_COMPLETE
Definition: compat.h:836
#define WideCharToMultiByte
Definition: compat.h:111
USHORT MajorVersion
Definition: compat.h:1430
DECLSPEC_HIDDEN struct cpu cpu_arm
Definition: cpu_arm.c:258
DWORD dwAllocationGranularity
Definition: winbase.h:1164
IMAGEHLP_EXTENDED_OPTIONS
Definition: compat.h:960
static WCHAR * make_default_search_path(void)
Definition: dbghelp.c:194
#define TRUE
Definition: types.h:120
uint16_t * PWSTR
Definition: typedefs.h:56
#define CP_ACP
Definition: compat.h:109
struct process * process_find_by_handle(HANDLE hProcess)
Definition: dbghelp.c:99
#define free
Definition: debug_ros.c:5
#define WARN(fmt,...)
Definition: debug.h:112
#define ERROR_INVALID_HANDLE
Definition: compat.h:98
BOOL dbghelp_opt_native
Definition: dbghelp.c:74
USHORT MinorVersion
Definition: compat.h:1431
LPAPI_VERSION WINAPI ImagehlpApiVersionEx(LPAPI_VERSION AppVersion)
Definition: dbghelp.c:845
#define CALLBACK
Definition: compat.h:35
DWORD WINAPI SymSetOptions(DWORD opts)
Definition: dbghelp.c:585
BOOL validate_addr64(DWORD64 addr)
Definition: dbghelp.c:112
BOOL WINAPI DisableThreadLibraryCalls(IN HMODULE hLibModule)
Definition: loader.c:85
GLuint buffer
Definition: glext.h:5915
_In_ BOOL _In_ HANDLE hProcess
Definition: mapping.h:70
unsigned buffer_size
#define DLL_PROCESS_ATTACH
Definition: compat.h:131
#define ReadProcessMemory(a, b, c, d, e)
Definition: compat.h:617
static API_VERSION api_version
Definition: dbghelp.c:832
static BOOL sym_register_cb(HANDLE hProcess, PSYMBOL_REGISTERED_CALLBACK64 cb, PSYMBOL_REGISTERED_CALLBACK cb32, DWORD64 user, BOOL unicode)
Definition: dbghelp.c:779
#define FILE_BEGIN
Definition: compat.h:620
PRTL_USER_PROCESS_PARAMETERS ProcessParameters
Definition: btrfs_drv.h:1903
struct cpu * cpu_find(DWORD machine)
Definition: dbghelp.c:183
#define CBA_EVENT
Definition: compat.h:843
#define lstrlenW
Definition: compat.h:609
#define DWORD
Definition: nt_native.h:44
_In_ PCALLBACK_FUNCTION CallbackFunction
Definition: exfuncs.h:1034
IMAGEHLP_STACK_FRAME ctx_frame
#define lstrcpynW
Definition: compat.h:597
WCHAR FileName[MAX_PATH+1]
Definition: compat.h:1026
LPEXT_API_VERSION WINAPI ExtensionApiVersion(void)
Definition: dbghelp.c:860
uint32_t ULONG_PTR
Definition: typedefs.h:65
const char * wine_dbg_sprintf(const char *format,...)
Definition: compat.c:296
static BOOL wow64
Definition: psapi_main.c:44
#define CBA_READ_MEMORY
Definition: compat.h:840
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
USHORT Revision
Definition: compat.h:1432
#define L(x)
Definition: ntvdm.h:50
#define FALSE
Definition: types.h:117
struct module * lmodules
#define ERROR_ACCESS_DENIED
Definition: compat.h:97
ULONG_PTR dbg_hdr_addr
static BOOL check_live_target(struct process *pcs)
Definition: dbghelp.c:356
unsigned int BOOL
Definition: ntddk_ex.h:94
BOOL WINAPI SymCleanup(HANDLE hProcess)
Definition: dbghelp.c:557
#define debugstr_w
Definition: kernel32.h:32
struct cpu cpu_i386 cpu_x86_64 cpu_arm cpu_arm64
Definition: cpu_arm64.c:283
#define FIXME(fmt,...)
Definition: debug.h:111
WCHAR * environment
r reserved
Definition: btrfs.c:2975
void WINAPI WinDbgExtensionDllInit(PWINDBG_EXTENSION_APIS lpExtensionApis, unsigned short major, unsigned short minor)
Definition: dbghelp.c:869
BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved)
Definition: dbghelp.c:82
ULONG major
#define GetModuleFileNameExW(w, x, y, z)
Definition: compat.h:781
Definition: getopt.h:108
_Inout_ PERBANDINFO * pbi
Definition: winddi.h:3917
const char * wine_dbgstr_addr(const ADDRESS64 *addr)
Definition: dbghelp.c:142
PSYMBOL_REGISTERED_CALLBACK reg_cb32
#define C_ASSERT(e)
Definition: intsafe.h:73
#define CBA_DEFERRED_SYMBOL_LOAD_FAILURE
Definition: compat.h:837
#define CBA_SYMBOLS_UNLOADED
Definition: compat.h:838
DWORD64 reg_user
BOOL WINAPI EnumerateLoadedModulesW64(HANDLE hProcess, PENUMLOADED_MODULES_CALLBACKW64 EnumLoadedModulesCallback, PVOID UserContext)
Definition: module.c:1112
void * fetch_buffer(struct process *pcs, unsigned size)
Definition: dbghelp.c:128
BOOL WINAPI IsWow64Process(IN HANDLE hProcess, OUT PBOOL Wow64Process)
Definition: proc.c:1975
BOOL WINAPI SymInitialize(HANDLE hProcess, PCSTR UserSearchPath, BOOL fInvadeProcess)
Definition: dbghelp.c:534
#define TRACE(s)
Definition: solgame.cpp:4
const WCHAR * process_getenv(const struct process *process, const WCHAR *name)
Definition: dbghelp.c:335
GLsizeiptr size
Definition: glext.h:5919
PSYMBOL_REGISTERED_CALLBACK64 reg_cb
#define CBA_DEBUG_INFO
Definition: compat.h:845
#define GetProcessHeap()
Definition: compat.h:595
PVOID WINAPI HeapAlloc(HANDLE, DWORD, SIZE_T)
#define GetEnvironmentVariableA(x, y, z)
Definition: compat.h:613
static struct process * process_first
Definition: dbghelp.c:79
__wchar_t WCHAR
Definition: xmlstorage.h:180
const struct loader_ops * loader
BOOL WINAPI SymSetSearchPath(HANDLE hProcess, PCSTR searchPath)
Definition: dbghelp.c:263
SYSTEM_INFO sysinfo
Definition: dbghelp.c:76
#define MAX_PATH
Definition: compat.h:34
#define WINAPI
Definition: msvc.h:6
void * buffer
unsigned long DWORD
Definition: ntddk_ex.h:95
BOOL WINAPI SymSetSearchPathW(HANDLE hProcess, PCWSTR searchPath)
Definition: dbghelp.c:235
#define SetLastError(x)
Definition: compat.h:611
BOOL WINAPI SymGetSearchPathW(HANDLE hProcess, PWSTR szSearchPath, DWORD SearchPathLength)
Definition: dbghelp.c:286
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
static BOOL WINAPI process_invade_cb(PCWSTR name, ULONG64 base, ULONG size, PVOID user)
Definition: dbghelp.c:323
#define SYMOPT_UNDNAME
Definition: compat.h:847
static WCHAR reason[MAX_STRING_RESOURCE_LEN]
Definition: object.c:1904
unsigned __int64 ULONG64
Definition: imports.h:198
ULONG Reserved[2]
ULONG64 InstructionOffset
Definition: compat.h:1235
int ret
#define wcsnicmp
Definition: compat.h:14
GLenum const GLvoid * addr
Definition: glext.h:9621
BOOL WINAPI SymSetParentWindow(HWND hwnd)
Definition: dbghelp.c:647
DECLSPEC_HIDDEN struct cpu cpu_i386
Definition: cpu_i386.c:706
#define CBA_DUPLICATE_SYMBOL
Definition: compat.h:839
static const char machine[]
Definition: profile.c:104
BOOL WINAPI SymRegisterCallback(HANDLE hProcess, PSYMBOL_REGISTERED_CALLBACK CallbackFunction, PVOID UserContext)
Definition: dbghelp.c:798
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
static struct cpu * dbghelp_cpus[]
Definition: dbghelp.c:164
GLenum GLsizei len
Definition: glext.h:6722
#define GetCurrentProcess()
Definition: compat.h:618
GLsizei const GLfloat * value
Definition: glext.h:6069
ULONG Reserved[2]
Definition: winternl.h:310
static BOOL CALLBACK reg_cb64to32(HANDLE hProcess, ULONG action, ULONG64 data, ULONG64 user)
Definition: dbghelp.c:687
uint32_t DWORD_PTR
Definition: typedefs.h:65
unsigned char BYTE
Definition: xxhash.c:193
const struct loader_ops no_loader_ops
Definition: module.c:1409
BOOL WINAPI SymRegisterCallback64(HANDLE hProcess, PSYMBOL_REGISTERED_CALLBACK64 CallbackFunction, ULONG64 UserContext)
Definition: dbghelp.c:810
#define RtlComputeCrc32
Definition: compat.h:669
#define ERR(fmt,...)
Definition: debug.h:110
USHORT Reserved
Definition: compat.h:1433
#define CBA_DEFERRED_SYMBOL_LOAD_PARTIAL
Definition: compat.h:844
static unsigned __int64 next
Definition: rand_nt.c:6
const WCHAR * action
Definition: action.c:7479
struct process * next
uint64_t DWORD64
Definition: typedefs.h:67
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define lstrcpyW
Definition: compat.h:608
#define ARRAY_SIZE(a)
Definition: main.h:24
BOOL(CALLBACK * PSYMBOL_REGISTERED_CALLBACK64)(HANDLE, ULONG, ULONG64, ULONG64)
Definition: compat.h:1041
DWORD WINAPI SymGetOptions(void)
Definition: dbghelp.c:600
BOOL(CALLBACK * PSYMBOL_REGISTERED_CALLBACK)(HANDLE, ULONG, PVOID, PVOID)
Definition: compat.h:1086
#define HeapReAlloc
Definition: compat.h:593
static HINSTANCE instance
Definition: main.c:40
signed char * PSTR
Definition: retypes.h:7
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
VOID WINAPI GetSystemInfo(IN LPSYSTEM_INFO lpSystemInfo)
Definition: sysinfo.c:142
static BYTE data32[]
Definition: misc.c:535
#define ReadFile(a, b, c, d, e)
Definition: compat.h:601
DWORD calc_crc32(HANDLE handle)
Definition: dbghelp.c:874
#define CBA_DEFERRED_SYMBOL_LOAD_START
Definition: compat.h:835
#define NULL
Definition: types.h:112
unsigned dbghelp_options
Definition: dbghelp.c:73
BOOL module_remove(struct process *pcs, struct module *module) DECLSPEC_HIDDEN
Definition: module.c:889
#define CBA_SET_OPTIONS
Definition: compat.h:842
#define HEAP_ZERO_MEMORY
Definition: compat.h:134
static LPCWSTR LPCWSTR LPCWSTR env
Definition: db.cpp:170
#define MultiByteToWideChar
Definition: compat.h:110
static HMODULE MODULEINFO DWORD cb
Definition: module.c:32
BOOL WINAPI SymSetContext(HANDLE hProcess, PIMAGEHLP_STACK_FRAME StackFrame, PIMAGEHLP_CONTEXT Context)
Definition: dbghelp.c:658
Definition: name.c:38
unsigned int ULONG
Definition: retypes.h:1
HANDLE handle
static __inline const char * wine_dbgstr_longlong(ULONGLONG ll)
Definition: compat.h:49
static const WCHAR sp[]
Definition: suminfo.c:287
BOOL macho_read_wine_loader_dbg_info(struct process *pcs, ULONG_PTR addr) DECLSPEC_HIDDEN
#define malloc
Definition: debug_ros.c:4
const char * PCSTR
Definition: typedefs.h:52
#define CBA_DEFERRED_SYMBOL_LOAD_CANCEL
Definition: compat.h:841
BOOL WINAPI SymSetExtendedOption(IMAGEHLP_EXTENDED_OPTIONS option, BOOL value)
Definition: dbghelp.c:609
GLfloat GLfloat p
Definition: glext.h:8902
ULONG64 ReturnOffset
Definition: compat.h:1236
_In_ LONG _In_ HWND hwnd
Definition: winddi.h:4022
DECLSPEC_HIDDEN struct cpu cpu_x86_64
Definition: cpu_x86_64.c:962
#define GetEnvironmentVariableW(x, y, z)
Definition: compat.h:614
BOOL WINAPI SymGetSearchPath(HANDLE hProcess, PSTR szSearchPath, DWORD SearchPathLength)
Definition: dbghelp.c:299
BOOL WINAPI SymInitializeW(HANDLE hProcess, PCWSTR UserSearchPath, BOOL fInvadeProcess)
Definition: dbghelp.c:464
DWORD ProcessParameters
DWORD WINAPI GetProcessId(IN HANDLE Process)
Definition: proc.c:1200
WINE_DEFAULT_DEBUG_CHANNEL(dbghelp)
static BOOL read_process_memory(const struct process *process, UINT64 addr, void *buf, size_t size)
void user(int argc, const char *argv[])
Definition: cmds.c:1350
ULONG minor
BOOL reg_is_unicode
#define HeapFree(x, y, z)
Definition: compat.h:594
struct cpu * dbghelp_current_cpu
Definition: dbghelp.c:169
#define SetFilePointer
Definition: compat.h:602
BOOL WINAPI SymRegisterCallbackW64(HANDLE hProcess, PSYMBOL_REGISTERED_CALLBACK64 CallbackFunction, ULONG64 UserContext)
Definition: dbghelp.c:822
NTSTATUS NTAPI NtQueryInformationProcess(_In_ HANDLE ProcessHandle, _In_ PROCESSINFOCLASS ProcessInformationClass, _Out_ PVOID ProcessInformation, _In_ ULONG ProcessInformationLength, _Out_opt_ PULONG ReturnLength)
Definition: query.c:59
LPAPI_VERSION WINAPI ImagehlpApiVersion(VOID)
Definition: dbghelp.c:837
BOOL elf_read_wine_loader_dbg_info(struct process *pcs, ULONG_PTR addr) DECLSPEC_HIDDEN
Definition: elf_module.c:1753