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.

400 lines
9.7 KiB

  1. //----------------------------------------------------------------------------
  2. //
  3. // Functions dealing with instructions, such as assembly or disassembly.
  4. //
  5. // Copyright (C) Microsoft Corporation, 1997-2002.
  6. //
  7. //----------------------------------------------------------------------------
  8. #include "ntsdp.hpp"
  9. ADDR g_DisasmSearchStartAddress;
  10. ADDR g_DisasmSearchLastPc;
  11. char g_DisasmSearchLastPattern[256];
  12. ULONG g_AsmOptions;
  13. ULONG g_X86BiosBaseAddress;
  14. // This array must be in DEBUG_ASMOPT bit order.
  15. PCSTR g_AsmOptionNames[] =
  16. {
  17. "verbose",
  18. "no_code_bytes",
  19. "ignore_output_width",
  20. };
  21. void
  22. DotAsm(PDOT_COMMAND Cmd, DebugClient* Client)
  23. {
  24. ULONG Flags = 0;
  25. PSTR Arg;
  26. ULONG i;
  27. for (;;)
  28. {
  29. //
  30. // Parse out a single flag argument.
  31. //
  32. if (!PeekChar() || *g_CurCmd == ';')
  33. {
  34. break;
  35. }
  36. Arg = g_CurCmd;
  37. while (*g_CurCmd && !isspace(*g_CurCmd))
  38. {
  39. g_CurCmd++;
  40. }
  41. if (isspace(*g_CurCmd))
  42. {
  43. *g_CurCmd++ = 0;
  44. }
  45. //
  46. // Find value for argument.
  47. //
  48. for (i = 0; i < DIMA(g_AsmOptionNames); i++)
  49. {
  50. if (!_stricmp(Arg, g_AsmOptionNames[i]))
  51. {
  52. break;
  53. }
  54. }
  55. if (i < DIMA(g_AsmOptionNames))
  56. {
  57. Flags |= 1 << i;
  58. }
  59. else
  60. {
  61. ErrOut("Unknown assembly option '%s'\n", Arg);
  62. }
  63. }
  64. if (Cmd->Name[3] != '-')
  65. {
  66. g_AsmOptions |= Flags;
  67. }
  68. else
  69. {
  70. g_AsmOptions &= ~Flags;
  71. }
  72. NotifyChangeEngineState(DEBUG_CES_ASSEMBLY_OPTIONS, g_AsmOptions, TRUE);
  73. dprintf("Assembly options:");
  74. if (g_AsmOptions == 0)
  75. {
  76. dprintf(" <default>\n");
  77. }
  78. else
  79. {
  80. for (i = 0; i < DIMA(g_AsmOptionNames); i++)
  81. {
  82. if (g_AsmOptions & (1 << i))
  83. {
  84. dprintf(" %s", g_AsmOptionNames[i]);
  85. }
  86. }
  87. dprintf("\n");
  88. }
  89. }
  90. void
  91. ParseInstrGrep(void)
  92. {
  93. ADDR NextGrepAddr;
  94. ADDR CurrGrepAddr;
  95. char SourceLine[MAX_DISASM_LEN];
  96. PSTR Pattern;
  97. char Save;
  98. ULONG64 Length;
  99. if (IS_CUR_CONTEXT_ACCESSIBLE())
  100. {
  101. g_Machine->GetPC(&g_DisasmSearchLastPc);
  102. }
  103. Pattern = StringValue(STRV_SPACE_IS_SEPARATOR |
  104. STRV_ESCAPED_CHARACTERS |
  105. STRV_ALLOW_EMPTY_STRING, &Save);
  106. if (Pattern)
  107. {
  108. g_DisasmSearchLastPattern[0] = '*';
  109. g_DisasmSearchLastPattern[1] = 0;
  110. while (Pattern[0] == '*')
  111. {
  112. Pattern++;
  113. }
  114. CatString(g_DisasmSearchLastPattern, Pattern,
  115. DIMA(g_DisasmSearchLastPattern));
  116. if (Pattern[strlen(Pattern) - 1] != '*')
  117. {
  118. CatString(g_DisasmSearchLastPattern, "*",
  119. DIMA(g_DisasmSearchLastPattern));
  120. }
  121. *g_CurCmd = Save;
  122. Length = DEBUG_INVALID_OFFSET;
  123. g_PrefixSymbols = TRUE;
  124. GetRange(&g_DisasmSearchStartAddress, &Length, 1,
  125. SEGREG_CODE, DEFAULT_RANGE_LIMIT);
  126. g_PrefixSymbols = FALSE;
  127. }
  128. if (!Flat(g_DisasmSearchStartAddress))
  129. {
  130. if (IS_CUR_CONTEXT_ACCESSIBLE())
  131. {
  132. dprintf("Search address set to ");
  133. dprintAddr(&g_DisasmSearchLastPc);
  134. dprintf("\n");
  135. g_DisasmSearchStartAddress = g_DisasmSearchLastPc;
  136. }
  137. else
  138. {
  139. ErrOut("Search address required\n");
  140. }
  141. return;
  142. }
  143. NextGrepAddr = g_DisasmSearchStartAddress;
  144. while (Length == DEBUG_INVALID_OFFSET ||
  145. Length-- > 0)
  146. {
  147. CurrGrepAddr = NextGrepAddr;
  148. if (!g_Machine->
  149. Disassemble(g_Process, &NextGrepAddr, SourceLine, FALSE))
  150. {
  151. break;
  152. }
  153. if (MatchPattern(SourceLine, g_DisasmSearchLastPattern))
  154. {
  155. g_LastEvalResult.SetU64(Flat(CurrGrepAddr));
  156. g_DisasmSearchStartAddress = NextGrepAddr;
  157. OutputSymAddr(Flat(CurrGrepAddr),
  158. SYMADDR_FORCE | SYMADDR_LABEL | SYMADDR_SOURCE,
  159. NULL);
  160. dprintf("%s", SourceLine);
  161. if (Length == DEBUG_INVALID_OFFSET)
  162. {
  163. return;
  164. }
  165. }
  166. if (CheckUserInterrupt())
  167. {
  168. return;
  169. }
  170. }
  171. }
  172. void
  173. TryAssemble(PADDR Addr)
  174. {
  175. char Assemble[MAX_DISASM_LEN];
  176. //
  177. // Set local prompt and command.
  178. //
  179. g_CommandStart = Assemble;
  180. g_CurCmd = Assemble;
  181. g_PromptLength = 9;
  182. Assemble[0] = '\0';
  183. while (TRUE)
  184. {
  185. char Ch;
  186. dprintAddr(Addr);
  187. GetInput("", Assemble, sizeof(Assemble), GETIN_LOG_INPUT_LINE);
  188. g_CurCmd = Assemble;
  189. RemoveDelChar(g_CurCmd);
  190. do
  191. {
  192. Ch = *g_CurCmd++;
  193. }
  194. while (Ch == ' ' || Ch == '\t');
  195. if (Ch == '\0')
  196. {
  197. break;
  198. }
  199. g_CurCmd--;
  200. DBG_ASSERT(fFlat(*Addr) || fInstrPtr(*Addr));
  201. g_Machine->Assemble(g_Process, Addr, g_CurCmd);
  202. }
  203. }
  204. void
  205. ParseAssemble(void)
  206. {
  207. //
  208. // Save present prompt and command.
  209. //
  210. PSTR StartSave = g_CommandStart; // saved start of cmd buffer
  211. PSTR CommandSave = g_CurCmd; // current ptr in cmd buffer
  212. ULONG PromptSave = g_PromptLength; // size of prompt string
  213. BOOL Done = FALSE;
  214. char Ch;
  215. if (!IS_CUR_MACHINE_ACCESSIBLE())
  216. {
  217. error(BADTHREAD);
  218. }
  219. if ((Ch = PeekChar()) != '\0' && Ch != ';')
  220. {
  221. GetAddrExpression(SEGREG_CODE, &g_AssemDefault);
  222. }
  223. while (!Done)
  224. {
  225. __try
  226. {
  227. TryAssemble(&g_AssemDefault);
  228. // If assembly returned normally we're done.
  229. Done = TRUE;
  230. }
  231. __except(CommandExceptionFilter(GetExceptionInformation()))
  232. {
  233. // If illegal input was encountered keep looping.
  234. }
  235. }
  236. //
  237. // Restore entry prompt and command.
  238. //
  239. g_CommandStart = StartSave;
  240. g_CurCmd = CommandSave;
  241. g_PromptLength = PromptSave;
  242. }
  243. void
  244. ParseUnassemble(void)
  245. {
  246. char Ch;
  247. ULONG64 Length;
  248. BOOL HasLength;
  249. char Text[MAX_DISASM_LEN];
  250. if (!IS_CUR_MACHINE_ACCESSIBLE())
  251. {
  252. error(BADTHREAD);
  253. }
  254. Ch = (char)tolower(*g_CurCmd);
  255. if (Ch == 'r')
  256. {
  257. g_CurCmd++;
  258. }
  259. else if (IS_KERNEL_TARGET(g_Target) && Ch == 'x')
  260. {
  261. g_CurCmd += 1;
  262. }
  263. Length = (g_Machine->m_ExecTypes[0] == IMAGE_FILE_MACHINE_IA64) ? 9 : 8;
  264. g_PrefixSymbols = TRUE;
  265. HasLength = GetRange(&g_UnasmDefault, &Length, 0, SEGREG_CODE,
  266. DEFAULT_RANGE_LIMIT);
  267. g_PrefixSymbols = FALSE;
  268. if (IS_KERNEL_TARGET(g_Target) && Ch == 'x')
  269. {
  270. ADDR Addr;
  271. if (g_X86BiosBaseAddress == 0)
  272. {
  273. ULONG64 SymAddr;
  274. if (GetOffsetFromSym(g_Process, "hal!HalpEisaMemoryBase",
  275. &SymAddr, NULL) != 1)
  276. {
  277. error(VARDEF);
  278. }
  279. if (g_Target->
  280. ReadAllVirtual(g_Process, SymAddr,
  281. &g_X86BiosBaseAddress,
  282. sizeof(ULONG)) != S_OK)
  283. {
  284. g_X86BiosBaseAddress = 0;
  285. error(MEMORY);
  286. }
  287. }
  288. Addr = g_UnasmDefault;
  289. Addr.flat += (g_X86BiosBaseAddress + (Addr.seg << 4));
  290. Addr.off = Addr.flat;
  291. Addr.type = ADDR_V86 | INSTR_POINTER;
  292. while (Length-- > 0)
  293. {
  294. g_Target->m_Machines[MACHIDX_I386]->
  295. Disassemble(g_Process, &Addr, Text, TRUE);
  296. Addr.flat = Addr.off;
  297. dprintf("%s", Text);
  298. }
  299. g_UnasmDefault = Addr;
  300. g_UnasmDefault.off -=
  301. (g_X86BiosBaseAddress + (Addr.seg << 4));
  302. g_UnasmDefault.flat = g_UnasmDefault.off;
  303. }
  304. else
  305. {
  306. MachineInfo* Machine;
  307. if (Ch == 'r')
  308. {
  309. // Force V86-mode address to force 16-bit disassembly.
  310. // We leave the flat address so that the actual
  311. // address used is not changed and we tweak
  312. // the seg:off pair to represent a count from the
  313. // start address.
  314. g_UnasmDefault.seg = 0;
  315. g_UnasmDefault.off = Flat(g_UnasmDefault) & 0xffff;
  316. g_UnasmDefault.type = ADDR_V86 | FLAT_COMPUTED |
  317. FLAT_BASIS;
  318. Machine = g_Target->m_Machines[MACHIDX_I386];
  319. }
  320. else
  321. {
  322. Machine = g_Machine;
  323. }
  324. BOOL Status;
  325. ADDR EndAddr;
  326. ULONG SymAddrFlags = SYMADDR_FORCE | SYMADDR_LABEL | SYMADDR_SOURCE;
  327. ADDRFLAT(&EndAddr, Length);
  328. while ((HasLength && Length--) ||
  329. (!HasLength && AddrLt(g_UnasmDefault, EndAddr)))
  330. {
  331. OutputSymAddr(Flat(g_UnasmDefault), SymAddrFlags, NULL);
  332. Status = Machine->
  333. Disassemble(g_Process, &g_UnasmDefault, Text, FALSE);
  334. dprintf("%s", Text);
  335. if (!Status)
  336. {
  337. error(MEMORY);
  338. }
  339. SymAddrFlags &= ~SYMADDR_FORCE;
  340. if (CheckUserInterrupt())
  341. {
  342. return;
  343. }
  344. }
  345. }
  346. }