Source code of Windows XP (NT5)
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.

389 lines
8.3 KiB

  1. //----------------------------------------------------------------------------
  2. //
  3. // Functions dealing with instructions, such as assembly or disassembly.
  4. //
  5. // Copyright (C) Microsoft Corporation, 1997-2001.
  6. //
  7. //----------------------------------------------------------------------------
  8. #include "ntsdp.hpp"
  9. static ULONG64 s_igrepSearchStartAddress = 0L;
  10. static ULONG64 s_igrepLastPc;
  11. static CHAR s_igrepLastPattern[256];
  12. ULONG g_AsmOptions;
  13. // This array must be in ASMOPT bit order.
  14. PCSTR g_AsmOptionNames[] =
  15. {
  16. "verbose"
  17. };
  18. void ChangeAsmOptions(BOOL Set, PSTR Args)
  19. {
  20. ULONG Flags = 0;
  21. PSTR Arg;
  22. ULONG i;
  23. for (;;)
  24. {
  25. //
  26. // Parse out a single flag argument.
  27. //
  28. while (isspace(*Args))
  29. {
  30. *Args++;
  31. }
  32. if (*Args == 0)
  33. {
  34. break;
  35. }
  36. Arg = Args;
  37. while (*Args && !isspace(*Args))
  38. {
  39. Args++;
  40. }
  41. if (isspace(*Args))
  42. {
  43. *Args++ = 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 (Set)
  65. {
  66. g_AsmOptions |= Flags;
  67. }
  68. else
  69. {
  70. g_AsmOptions &= ~Flags;
  71. }
  72. dprintf("Assembly options:");
  73. if (g_AsmOptions == 0)
  74. {
  75. dprintf(" <default>\n");
  76. }
  77. else
  78. {
  79. for (i = 0; i < DIMA(g_AsmOptionNames); i++)
  80. {
  81. if (g_AsmOptions & (1 << i))
  82. {
  83. dprintf(" %s", g_AsmOptionNames[i]);
  84. }
  85. }
  86. dprintf("\n");
  87. }
  88. }
  89. void igrep (void)
  90. {
  91. ULONG64 dwNextGrepAddr;
  92. ULONG64 dwCurrGrepAddr;
  93. CHAR SourceLine[MAX_DISASM_LEN];
  94. BOOL NewPc;
  95. ULONG64 d;
  96. PCHAR pc = g_CurCmd;
  97. PCHAR Pattern;
  98. PCHAR Expression;
  99. CHAR Symbol[MAX_SYMBOL_LEN];
  100. ULONG64 Displacement;
  101. ADDR TempAddr;
  102. ULONG64 dwCurrentPc;
  103. g_Machine->GetPC(&TempAddr);
  104. dwCurrentPc = Flat(TempAddr);
  105. if ( s_igrepLastPc && s_igrepLastPc == dwCurrentPc )
  106. {
  107. NewPc = FALSE;
  108. }
  109. else
  110. {
  111. s_igrepLastPc = dwCurrentPc;
  112. NewPc = TRUE;
  113. }
  114. //
  115. // check for pattern.
  116. //
  117. Pattern = NULL;
  118. Expression = NULL;
  119. if (*pc)
  120. {
  121. while (*pc <= ' ')
  122. {
  123. pc++;
  124. }
  125. Pattern = pc;
  126. while (*pc > ' ')
  127. {
  128. pc++;
  129. }
  130. //
  131. // check for an expression
  132. //
  133. if (*pc != '\0')
  134. {
  135. *pc = '\0';
  136. pc++;
  137. if (*pc <= ' ')
  138. {
  139. while (*pc <= ' ')
  140. {
  141. pc++;
  142. }
  143. }
  144. if (*pc)
  145. {
  146. Expression = pc;
  147. }
  148. }
  149. }
  150. if (Pattern)
  151. {
  152. for (pc = Pattern; *pc; pc++)
  153. {
  154. *pc = (CHAR)toupper(*pc);
  155. }
  156. s_igrepLastPattern[0] = '*';
  157. strcpy(s_igrepLastPattern + 1, Pattern);
  158. if (Pattern[0] == '*')
  159. {
  160. strcpy(s_igrepLastPattern, Pattern);
  161. }
  162. if (Pattern[strlen(Pattern)] != '*')
  163. {
  164. strcat(s_igrepLastPattern, "*");
  165. }
  166. }
  167. if (Expression)
  168. {
  169. s_igrepSearchStartAddress = ExtGetExpression(Expression);
  170. }
  171. if (!s_igrepSearchStartAddress)
  172. {
  173. dprintf("Search address set to %s\n", FormatAddr64(s_igrepLastPc));
  174. s_igrepSearchStartAddress = s_igrepLastPc;
  175. return;
  176. }
  177. dwNextGrepAddr = s_igrepSearchStartAddress;
  178. dwCurrGrepAddr = dwNextGrepAddr;
  179. d = ExtDisasm(&dwNextGrepAddr, SourceLine, FALSE);
  180. while (d)
  181. {
  182. for (pc = SourceLine; *pc; pc++)
  183. {
  184. *pc = (CHAR)tolower(*pc);
  185. }
  186. if (MatchPattern(SourceLine, s_igrepLastPattern))
  187. {
  188. g_LastExpressionValue = dwCurrGrepAddr;
  189. s_igrepSearchStartAddress = dwNextGrepAddr;
  190. GetSymbolStdCall(dwCurrGrepAddr, Symbol, sizeof(Symbol),
  191. &Displacement, NULL);
  192. ExtDisasm(&dwCurrGrepAddr, SourceLine, FALSE);
  193. dprintf("%s", SourceLine);
  194. return;
  195. }
  196. if (CheckUserInterrupt())
  197. {
  198. return;
  199. }
  200. dwCurrGrepAddr = dwNextGrepAddr;
  201. d = ExtDisasm(&dwNextGrepAddr, SourceLine, FALSE);
  202. }
  203. }
  204. /*** fnAssemble - interactive assembly routine
  205. *
  206. * Purpose:
  207. * Function of "a <range>" command.
  208. *
  209. * Prompt the user with successive assembly addresses until
  210. * a blank line is input. Assembly errors do not abort the
  211. * function, but the prompt is output again for a retry.
  212. * The variables g_CommandStart, g_CurCmd, and cbPrompt
  213. * are set to make a local error context and restored on routine
  214. * exit.
  215. *
  216. * Input:
  217. * *addr - starting address for assembly
  218. *
  219. * Output:
  220. * *addr - address after the last assembled instruction.
  221. *
  222. * Notes:
  223. * all error processing is local, no errors are returned.
  224. *
  225. *************************************************************************/
  226. void
  227. TryAssemble(PADDR paddr)
  228. {
  229. char Assemble[MAX_DISASM_LEN];
  230. //
  231. // Set local prompt and command.
  232. //
  233. g_CommandStart = Assemble;
  234. g_CurCmd = Assemble;
  235. g_PromptLength = 9;
  236. Assemble[0] = '\0';
  237. while (TRUE)
  238. {
  239. char ch;
  240. dprintAddr(paddr);
  241. GetInput("", Assemble, sizeof(Assemble));
  242. g_CurCmd = Assemble;
  243. RemoveDelChar(g_CurCmd);
  244. do
  245. {
  246. ch = *g_CurCmd++;
  247. }
  248. while (ch == ' ' || ch == '\t');
  249. if (ch == '\0')
  250. {
  251. break;
  252. }
  253. g_CurCmd--;
  254. assert(fFlat(*paddr) || fInstrPtr(*paddr));
  255. g_Machine->Assemble(paddr, g_CurCmd);
  256. }
  257. }
  258. void
  259. fnAssemble(PADDR paddr)
  260. {
  261. //
  262. // Save present prompt and command.
  263. //
  264. PSTR StartSave = g_CommandStart; // saved start of cmd buffer
  265. PSTR CommandSave = g_CurCmd; // current ptr in cmd buffer
  266. ULONG PromptSave = g_PromptLength; // size of prompt string
  267. BOOL Done = FALSE;
  268. while (!Done)
  269. {
  270. __try
  271. {
  272. TryAssemble(paddr);
  273. // If assembly returned normally we're done.
  274. Done = TRUE;
  275. }
  276. __except(CommandExceptionFilter(GetExceptionInformation()))
  277. {
  278. // If illegal input was encountered keep looping.
  279. }
  280. }
  281. //
  282. // Restore entry prompt and command.
  283. //
  284. g_CommandStart = StartSave;
  285. g_CurCmd = CommandSave;
  286. g_PromptLength = PromptSave;
  287. }
  288. /*** fnUnassemble - disassembly of an address range
  289. *
  290. * Purpose:
  291. * Function of "u<range>" command.
  292. *
  293. * Output the disassembly of the instruction in the given
  294. * address range. Since some processors have variable
  295. * instruction lengths, use fLength value to determine if
  296. * instruction count or inclusive range should be used.
  297. *
  298. * Input:
  299. * *addr - pointer to starting address to disassemble
  300. * value - if fLength = TRUE, count of instructions to output
  301. * if fLength = FALSE, ending address of inclusive range
  302. *
  303. * Output:
  304. * *addr - address after last instruction disassembled
  305. *
  306. * Exceptions:
  307. * error exit: MEMORY - memory access error
  308. *
  309. * Notes:
  310. *
  311. *************************************************************************/
  312. void
  313. fnUnassemble (
  314. PADDR Addr,
  315. ULONG64 Value,
  316. BOOL Length
  317. )
  318. {
  319. if (!IS_MACHINE_ACCESSIBLE())
  320. {
  321. error(BADTHREAD);
  322. }
  323. CHAR Buffer[MAX_DISASM_LEN];
  324. BOOL Status;
  325. ADDR EndAddr;
  326. ULONG SymAddrFlags = SYMADDR_FORCE | SYMADDR_LABEL | SYMADDR_SOURCE;
  327. Flat(EndAddr) = Value;
  328. while ((Length && Value--) || (!Length && AddrLt(*Addr, EndAddr)))
  329. {
  330. OutputSymAddr(Flat(*Addr), SymAddrFlags);
  331. Status = g_Machine->Disassemble(Addr, Buffer, FALSE);
  332. dprintf("%s", Buffer);
  333. if (!Status)
  334. {
  335. error(MEMORY);
  336. }
  337. SymAddrFlags &= ~SYMADDR_FORCE;
  338. if (CheckUserInterrupt())
  339. {
  340. return;
  341. }
  342. }
  343. }