Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

376 lines
7.0 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. vsym.c
  5. Abstract:
  6. This function implements virtual symbols that can be added by the caller.
  7. Author:
  8. Pat Styles (patst) 5-June-2001
  9. Environment:
  10. User Mode
  11. --*/
  12. #include "private.h"
  13. #include "symbols.h"
  14. #include "globals.h"
  15. int __cdecl
  16. vsCompareAddrs(
  17. const void *one,
  18. const void *two
  19. )
  20. {
  21. PVIRTUAL_SYMBOL vs1 = (PVIRTUAL_SYMBOL)one;
  22. PVIRTUAL_SYMBOL vs2 = (PVIRTUAL_SYMBOL)two;
  23. if (vs2->addr > vs1->addr)
  24. return -1;
  25. if (vs1->addr > vs2->addr)
  26. return 1;
  27. return 0;
  28. }
  29. BOOL
  30. vsAddSymbol(
  31. PMODULE_ENTRY mi,
  32. PCSTR name,
  33. DWORD64 addr,
  34. DWORD size
  35. )
  36. {
  37. PVIRTUAL_SYMBOL vs;
  38. DWORD i;
  39. // look for another symbol at the same address
  40. vs = vsGetSymbol(mi, NULL, addr);
  41. if (vs) {
  42. SetLastError(ERROR_ALREADY_EXISTS);
  43. return false;
  44. }
  45. // look for an empty slot in the already existing list
  46. vs = vsBlankSymbol(mi);
  47. // not found: allow a new list or realloc to new size
  48. if (!vs) {
  49. i = mi->cvs + 1;
  50. if (!mi->vs) {
  51. assert(mi->cvs == 0);
  52. vs = (PVIRTUAL_SYMBOL)MemAlloc(sizeof(VIRTUAL_SYMBOL));
  53. } else {
  54. assert(mi->cvs);
  55. vs = (PVIRTUAL_SYMBOL)MemReAlloc(mi->vs, i * sizeof(VIRTUAL_SYMBOL));
  56. }
  57. if (!vs) {
  58. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  59. return false;
  60. }
  61. // reset the pointer and increment the count
  62. mi->vs = vs;
  63. vs = mi->vs + mi->cvs;
  64. mi->cvs++;
  65. }
  66. // copy in the new symbol
  67. CopyStrArray(vs->name, name);
  68. vs->addr = addr;
  69. vs->size = size;
  70. qsort(mi->vs, mi->cvs, sizeof(VIRTUAL_SYMBOL), vsCompareAddrs);
  71. mi->SymLoadError = SYMLOAD_OK;
  72. return true;
  73. }
  74. BOOL
  75. vsMatchSymbol(
  76. PVIRTUAL_SYMBOL vs,
  77. PCSTR name,
  78. DWORD64 addr
  79. )
  80. {
  81. // Look for a mismatch in either name or addr.
  82. if (name && *name && strcmp(vs->name, name))
  83. return false;
  84. if (addr && vs->addr != addr)
  85. return false;
  86. // When passing a null name and addr, we are looking
  87. // for a blank entry. Check if addr is zero.
  88. if (!name && !addr && vs->addr)
  89. return false;
  90. // hit!
  91. return true;
  92. }
  93. PVIRTUAL_SYMBOL
  94. vsGetSymbol(
  95. PMODULE_ENTRY mi,
  96. PCSTR name,
  97. DWORD64 addr
  98. )
  99. {
  100. PVIRTUAL_SYMBOL vs;
  101. DWORD i;
  102. for (vs = mi->vs, i = 0; i < mi->cvs; vs++, i++) {
  103. if (vsMatchSymbol(vs, name, addr))
  104. return vs;
  105. }
  106. return NULL;
  107. }
  108. BOOL
  109. vsDeleteSymbol(
  110. PMODULE_ENTRY mi,
  111. PCSTR name,
  112. DWORD64 addr
  113. )
  114. {
  115. PVIRTUAL_SYMBOL vs;
  116. DWORD i;
  117. // look for an empty slot in the already existing list
  118. vs = NULL;
  119. for (vs = mi->vs, i = 0; i < mi->cvs; vs++, i++) {
  120. if (vsMatchSymbol(vs, name, addr)) {
  121. vs->addr = 0;
  122. return true;
  123. }
  124. }
  125. SetLastError(ERROR_NOT_FOUND);
  126. return false;
  127. }
  128. BOOL
  129. vsDumpSymbols(
  130. PMODULE_ENTRY mi
  131. )
  132. // for debugging...
  133. {
  134. PVIRTUAL_SYMBOL vs;
  135. DWORD i;
  136. if (!mi->vs)
  137. return false;
  138. for (vs = mi->vs, i = 0; i < mi->cvs; vs++, i++) {
  139. if (vs->addr)
  140. dtrace("%s %I64lx\n", vs->name, vs->addr);
  141. }
  142. return true;
  143. }
  144. BOOL
  145. vsFillSymbolInfo(
  146. PSYMBOL_INFO si,
  147. PMODULE_ENTRY mi,
  148. PVIRTUAL_SYMBOL vs
  149. )
  150. {
  151. DWORD dw;
  152. dw = si->MaxNameLen;
  153. ZeroMemory(si, sizeof(SYMBOL_INFO));
  154. si->MaxNameLen = dw;
  155. CopyString(si->Name, vs->name, si->MaxNameLen);
  156. si->ModBase = mi->BaseOfDll;
  157. si->Address = vs->addr;
  158. si->Size = vs->size;
  159. si->Flags = SYMFLAG_VIRTUAL;
  160. return true;
  161. }
  162. BOOL
  163. vsGetSymbols(
  164. IN PPROCESS_ENTRY pe,
  165. IN PMODULE_ENTRY mi,
  166. IN PCSTR mask,
  167. IN DWORD64 addr,
  168. IN PROC callback,
  169. IN PVOID context,
  170. IN BOOL use64,
  171. IN BOOL unicode
  172. )
  173. {
  174. PVIRTUAL_SYMBOL vs;
  175. DWORD i;
  176. BOOL fCase;
  177. BOOL rc;
  178. if (!mi->vs)
  179. return callback ? true : false;
  180. fCase = option(SYMOPT_CASE_INSENSITIVE) ? false : true;
  181. for (vs = mi->vs, i = 0; i < mi->cvs; vs++, i++) {
  182. if (mask && *mask && strcmpre(vs->name, mask, fCase))
  183. continue;
  184. if (addr && (vs->addr != addr))
  185. continue;
  186. vsFillSymbolInfo(&mi->vssi, mi, vs);
  187. if (!callback)
  188. return true;
  189. rc = DoEnumCallback(pe, &mi->vssi, mi->vssi.Size, callback, context, use64, unicode);
  190. if (!rc) {
  191. mi->code = ERROR_CANCELLED;
  192. return false;
  193. }
  194. }
  195. return callback ? true : false;
  196. }
  197. PSYMBOL_INFO
  198. vsFindSymbolByName(
  199. PPROCESS_ENTRY pe,
  200. PMODULE_ENTRY mi,
  201. LPSTR SymName
  202. )
  203. {
  204. if (!vsGetSymbols(pe, mi, SymName, 0, NULL, NULL, 0, 0))
  205. return NULL;
  206. if (!mi)
  207. mi = pe->ipmi;
  208. return &mi->vssi;
  209. }
  210. PSYMBOL_INFO
  211. vsGetSymNextPrev(
  212. PMODULE_ENTRY mi,
  213. DWORD64 addr,
  214. BOOL direction
  215. )
  216. {
  217. PVIRTUAL_SYMBOL vs;
  218. PVIRTUAL_SYMBOL vsprev;
  219. DWORD i;
  220. // no entries, bail
  221. if (!mi->cvs)
  222. return NULL;
  223. // walk to the entry with a higher address
  224. vsprev = NULL;
  225. for (vs = mi->vs, i = 0; i < mi->cvs; vs++, i++) {
  226. if (vs->addr < addr)
  227. vsprev = vs;
  228. if (vs->addr > addr)
  229. break;
  230. }
  231. if (direction < 0)
  232. vs = vsprev;
  233. else if (i == mi->cvs)
  234. return NULL;
  235. if (!vs)
  236. return NULL;
  237. vsFillSymbolInfo(&mi->vssi, mi, vs);
  238. return &mi->vssi;
  239. }
  240. PSYMBOL_INFO
  241. vsGetSymFromAddr(
  242. PMODULE_ENTRY mi,
  243. DWORD64 addr,
  244. PDWORD64 disp
  245. )
  246. {
  247. PVIRTUAL_SYMBOL vs;
  248. DWORD i;
  249. // find the entry with a higher address
  250. for (vs = mi->vs, i = 0; i < mi->cvs; vs++, i++) {
  251. if (vs->addr > addr)
  252. break;
  253. }
  254. // no hit, bail
  255. if (!i)
  256. return NULL;
  257. // rewind back to the hit.
  258. // If the symbol has a size, make sure we're within the limits.
  259. vs--;
  260. if (vs->size && (vs->addr + vs->size) < addr)
  261. return NULL;
  262. // bullseye!
  263. vsFillSymbolInfo(&mi->vssi, mi, vs);
  264. if (disp)
  265. *disp = addr - mi->vssi.Address;
  266. return &mi->vssi;
  267. }
  268. PSYMBOL_ENTRY
  269. vsGetSymEntryFromAddr(
  270. PMODULE_ENTRY mi,
  271. DWORD64 addr,
  272. PDWORD64 disp
  273. )
  274. {
  275. PSYMBOL_INFO si;
  276. si = vsGetSymFromAddr(mi, addr, disp);
  277. if (!si)
  278. return NULL;
  279. si2se(si, &mi->vsTmpSym);
  280. if (disp)
  281. *disp = addr - si->Address;
  282. return &mi->vsTmpSym;
  283. }