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.

2496 lines
71 KiB

  1. /*++
  2. Copyright (c) 1993-2001 Microsoft Corporation
  3. Module Name:
  4. walkarm.c
  5. Abstract:
  6. This file implements the ARM stack walking api.
  7. Author:
  8. Wesley Witt (wesw) 1-Oct-1993
  9. Glenn Hirschowitz Jan-1995
  10. Janet Schneider 17-March-1997
  11. Robert Denkewalter Jan-1999
  12. Added Thumb unwinder, modified WalkArm, added caching,
  13. split FunctionTableAccessOrTranslateAddress, added global hProcess, etc.,
  14. Environment:
  15. User Mode
  16. --*/
  17. #define TARGET_ARM
  18. #define _IMAGEHLP_SOURCE_
  19. //#define _CROSS_PLATFORM_
  20. #include <nt.h>
  21. #include <ntrtl.h>
  22. #include <nturtl.h>
  23. #include "private.h"
  24. #define NOEXTAPI
  25. #include "wdbgexts.h"
  26. #include "ntdbg.h"
  27. #include "symbols.h"
  28. #include "fecache.hpp"
  29. #include "globals.h"
  30. #include <arminst.h>
  31. #define MODE_ARM 0
  32. #define MODE_THUMB 1
  33. #define REGISTER_SIZE 4
  34. //
  35. // XXX drewb - Need to provide a real implementation.
  36. //
  37. DWORD
  38. WceTranslateAddress(HANDLE hpid,
  39. HANDLE htid,
  40. DWORD addrIn,
  41. DWORD dwStackFrameAddr,
  42. DWORD * pdwNewStackFrameAddr)
  43. {
  44. *pdwNewStackFrameAddr = 0;
  45. return addrIn;
  46. }
  47. //
  48. // Conspicuously absent from VC6's nt headers.
  49. //
  50. #define STRI_LR_SPU_MASK 0x073de000L // Load or Store of LR with stack update
  51. #define STRI_LR_SPU_INSTR 0x052de000L // Store LR (with immediate offset, update SP)
  52. #if DBG
  53. // This is our local version of "assert."
  54. #define TestAssumption(c, m) assert(c)
  55. #else
  56. #define TestAssumption(c, m)
  57. #endif
  58. // If the Thumb unwinder handles the unwind,
  59. // it'll return UNWIND_HANDLED, so that the
  60. // ARM unwinder will not bother...
  61. #define UNWIND_NOT_HANDLED 0
  62. #define UNWIND_HANDLED 1
  63. // Face it: Many of the routines in this module require these routines
  64. // and variables. Further, WalkArm is the only way into this module.
  65. // Just let WalkArm initialize these on every pass, and then we don't
  66. // have to keep passing them around. Further, we can build nice wrappers
  67. // around them to make them easier to use.
  68. //
  69. // XXX drewb - However, this isn't thread-safe and technically
  70. // is broken. It's not important enough to fix right now.
  71. // A similar approach with putting the variables in TLS data would
  72. // be a simple fix and would preserve the convenience. It should
  73. // probably be built into StackWalk64 itself so that it's available
  74. // by default in all walkers.
  75. static HANDLE UW_hProcess;
  76. static HANDLE UW_hThread;
  77. static PREAD_PROCESS_MEMORY_ROUTINE64 UW_ReadMemory;
  78. static PFUNCTION_TABLE_ACCESS_ROUTINE64 UW_FunctionTableAccess;
  79. // We do this enough to make a special routine for it.
  80. static BOOL
  81. LoadWordIntoRegister(ULONG StartAddr, LPDWORD pRegister)
  82. {
  83. BOOL rc;
  84. ULONG cb;
  85. rc = UW_ReadMemory( UW_hProcess, (ULONG64)(LONG)StartAddr,
  86. (LPVOID)pRegister, REGISTER_SIZE, &cb );
  87. if (!rc || (cb != REGISTER_SIZE)) {
  88. return FALSE;
  89. } else {
  90. return rc;
  91. }
  92. }
  93. static BOOL
  94. ReadMemory(ULONG StartAddr, ULONG Size, LPVOID Buffer)
  95. {
  96. BOOL rc;
  97. ULONG cb;
  98. rc = UW_ReadMemory( UW_hProcess, (ULONG64)(LONG)StartAddr,
  99. (LPVOID)Buffer, Size, &cb );
  100. if (!rc || (cb != Size)) {
  101. return FALSE;
  102. } else {
  103. return rc;
  104. }
  105. }
  106. #define EXCINFO_NULL_HANDLER 0
  107. // For ARM, prolog helpers have HandlerData == 1, not 2 as in MIPS
  108. #define EXCINFO_PROLOG_HELPER 1
  109. // For ARM, epilog helpers have HandlerData == 2, not 3 as in MIPS
  110. #define EXCINFO_EPILOG_HELPER 2
  111. #define IS_HELPER_FUNCTION(rfe) \
  112. ( \
  113. (rfe)? \
  114. ( \
  115. ((rfe)->ExceptionHandler==EXCINFO_NULL_HANDLER) && \
  116. ( ((rfe)->HandlerData==EXCINFO_PROLOG_HELPER) || \
  117. ((rfe)->HandlerData==EXCINFO_EPILOG_HELPER) \
  118. ) \
  119. ): \
  120. FALSE \
  121. )
  122. #define IS_PROLOG_HELPER_FUNCTION(rfe) \
  123. ( \
  124. (rfe)? \
  125. ( \
  126. ((rfe)->ExceptionHandler==EXCINFO_NULL_HANDLER) && \
  127. ((rfe)->HandlerData==EXCINFO_PROLOG_HELPER) \
  128. ): \
  129. FALSE \
  130. )
  131. #define IS_EPILOG_HELPER_FUNCTION(rfe) \
  132. ( \
  133. (rfe)? \
  134. ( \
  135. ((rfe)->ExceptionHandler==EXCINFO_NULL_HANDLER) && \
  136. ((rfe)->HandlerData==EXCINFO_EPILOG_HELPER) \
  137. ): \
  138. FALSE \
  139. )
  140. static int
  141. ThumbVirtualUnwind (DWORD,PIMAGE_ARM_RUNTIME_FUNCTION_ENTRY,
  142. PARM_CONTEXT,DWORD*);
  143. static BOOL
  144. WalkArmGetStackFrame(
  145. LPDWORD ReturnAddress,
  146. LPDWORD FramePointer,
  147. PARM_CONTEXT Context,
  148. int * Mode
  149. );
  150. static VOID
  151. WalkArmDataProcess(
  152. ARMI instr,
  153. PULONG Register
  154. );
  155. static BOOL
  156. WalkArmLoadI(
  157. ARMI instr,
  158. PULONG Register
  159. );
  160. static BOOL
  161. WalkArmLoadMultiple(
  162. PIMAGE_ARM_RUNTIME_FUNCTION_ENTRY FunctionEntry,
  163. ARMI instr,
  164. PULONG Register
  165. );
  166. static BOOL
  167. CheckConditionCodes(
  168. ULONG CPSR,
  169. DWORD instr
  170. );
  171. //
  172. // The saved registers are the permanent general registers (ie. those
  173. // that get restored in the epilog) R4-R11 R13-R15
  174. //
  175. #define SAVED_REGISTER_MASK 0x0000eff0 /* saved integer registers */
  176. #define IS_REGISTER_SAVED(Register) ((SAVED_REGISTER_MASK >> Register) & 1L)
  177. BOOL
  178. WalkArm(
  179. HANDLE hProcess,
  180. HANDLE hThread,
  181. LPSTACKFRAME64 StackFrame,
  182. PVOID ContextRecord,
  183. PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemoryRoutine,
  184. PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine,
  185. PGET_MODULE_BASE_ROUTINE64 GetModuleBase
  186. )
  187. {
  188. static DWORD PrevFramePC;
  189. static ARM_CONTEXT SavedContext;
  190. BOOL rval;
  191. PIMAGE_ARM_RUNTIME_FUNCTION_ENTRY Rfe;
  192. IMAGE_ARM_RUNTIME_FUNCTION_ENTRY LoopRFE;
  193. DWORD TempPc, TempFp;
  194. PARM_CONTEXT Context = (PARM_CONTEXT)ContextRecord;
  195. // Initialize the module's "global" variables and routines:
  196. UW_hProcess = hProcess;
  197. UW_hThread = hThread;
  198. UW_ReadMemory = ReadMemoryRoutine;
  199. UW_FunctionTableAccess = FunctionTableAccessRoutine;
  200. // This way of unwinding differs from the other, "old" ways of unwinding.
  201. // It removes duplicate code from WalkArmInit and WalkArmNext, and it saves
  202. // the previous stack frame so that each stack frame is unwound only once.
  203. rval = TRUE;
  204. do {
  205. Rfe = (PIMAGE_ARM_RUNTIME_FUNCTION_ENTRY)
  206. UW_FunctionTableAccess( UW_hProcess, Context->Pc );
  207. if (Rfe) {
  208. LoopRFE = *Rfe;
  209. } else {
  210. ZeroMemory(&LoopRFE, sizeof(LoopRFE));
  211. }
  212. // If this is the first pass in the unwind,
  213. // fill in the SavedContext from the
  214. // Context passed in, and initialize the StackFrame fields
  215. if (!StackFrame->Virtual) {
  216. ZeroMemory(StackFrame, sizeof(*StackFrame));
  217. // Set Virtual so that next pass, we know we're not initializing
  218. StackFrame->Virtual = TRUE;
  219. StackFrame->AddrPC.Mode = AddrModeFlat;
  220. StackFrame->AddrFrame.Mode = AddrModeFlat;
  221. StackFrame->AddrReturn.Mode = AddrModeFlat;
  222. PrevFramePC = 0;
  223. SavedContext = *Context;
  224. }
  225. // Use the context we saved from last time (or just initialized)
  226. // to set the previous frame.
  227. *Context = SavedContext;
  228. DWORD dwNewSp = 0;
  229. StackFrame->AddrPC.Offset =
  230. WceTranslateAddress(UW_hProcess, UW_hThread,
  231. Context->Pc, Context->Sp, &dwNewSp);
  232. if (dwNewSp) {
  233. Context->Sp = dwNewSp;
  234. }
  235. StackFrame->AddrFrame.Offset = Context->Sp;
  236. // PC == 0 means unwinding is finished.
  237. if ( StackFrame->AddrPC.Offset != 0x0 ) {
  238. int Mode;
  239. PrevFramePC = TempPc = SavedContext.Pc;
  240. TempFp = SavedContext.Sp;
  241. // We already have the frame we want to return, except for one
  242. // little detail. We want the return address from this frame.
  243. // So, we unwind it. This unwinding actually yields the
  244. // previous frame. We don't want to duplicate this effort
  245. // next time, so we'll save the results.
  246. if (WalkArmGetStackFrame(&TempPc, &TempFp, &SavedContext, &Mode)) {
  247. SavedContext.Pc = TempPc;
  248. TestAssumption(TempFp == SavedContext.Sp, "FP wrong2");
  249. StackFrame->AddrReturn.Offset = SavedContext.Pc;
  250. StackFrame->Params[0] = SavedContext.R0;
  251. StackFrame->Params[1] = SavedContext.R1;
  252. StackFrame->Params[2] = SavedContext.R2;
  253. StackFrame->Params[3] = SavedContext.R3;
  254. } else {
  255. // No place to return to...
  256. StackFrame->AddrReturn.Offset = 0;
  257. // ...and the saved context probably has a bogus PC.
  258. SavedContext.Pc = 0;
  259. rval = FALSE;
  260. }
  261. } else {
  262. rval = FALSE;
  263. }
  264. } while (IS_HELPER_FUNCTION(&LoopRFE) && rval);
  265. if (rval) {
  266. StackFrame->FuncTableEntry =
  267. UW_FunctionTableAccess(UW_hProcess, StackFrame->AddrPC.Offset);
  268. }
  269. return rval;
  270. }
  271. static DWORD
  272. ArmVirtualUnwind (
  273. DWORD ControlPc,
  274. PIMAGE_ARM_RUNTIME_FUNCTION_ENTRY FunctionEntry,
  275. PARM_CONTEXT Context
  276. )
  277. /*++
  278. Routine Description:
  279. This function virtually unwinds the specfified function by executing its
  280. prologue code backwards (or its epilog forward).
  281. If the function is a leaf function, then the address where control left
  282. the previous frame is obtained from the context record. If the function
  283. is a nested function, but not an exception or interrupt frame, then the
  284. prologue code is executed backwards and the address where control left
  285. the previous frame is obtained from the updated context record.
  286. Otherwise, an exception or interrupt entry to the system is being unwound
  287. and a specially coded prologue restores the return address twice. Once
  288. from the fault instruction address and once from the saved return address
  289. register. The first restore is returned as the function value and the
  290. second restore is place in the updated context record.
  291. If a context pointers record is specified, then the address where each
  292. nonvolatile registers is restored from is recorded in the appropriate
  293. element of the context pointers record.
  294. Arguments:
  295. ControlPc - Supplies the address where control left the specified
  296. function.
  297. FunctionEntry - Supplies the address of the function table entry for the
  298. specified function.
  299. Context - Supplies the address of a context record.
  300. Return Value:
  301. The address where control left the previous frame is returned as the
  302. function value.
  303. --*/
  304. {
  305. ULONG Address;
  306. LONG cb;
  307. DWORD EpilogPc;
  308. BOOL ExecutingEpilog;
  309. BOOL IsFramePointer = FALSE;
  310. LONG i,j;
  311. ARMI instr, instr2;
  312. BOOL PermanentsRestored = FALSE;
  313. ARMI Prolog[50]; // The prolog will never be more than 10 instructions
  314. PULONG Register;
  315. BOOL bEpiWindAlready = FALSE;
  316. ARM_CONTEXT ContextBeforeEpiWind;
  317. //
  318. // NOTE: When unwinding the call stack, we assume that all instructions
  319. // in the prolog have the condition code "Always execute." This is not
  320. // necessarily true for the epilog.
  321. //
  322. if( !FunctionEntry ) {
  323. return 0;
  324. }
  325. Register = &Context->R0;
  326. if( FunctionEntry->PrologEndAddress - FunctionEntry->BeginAddress == 0 ) {
  327. //
  328. // No prolog, so just copy the link register into the PC and return.
  329. //
  330. goto CopyLrToPcAndExit;
  331. }
  332. //
  333. // First check to see if we are in the epilog. If so, forward execution
  334. // through the end of the epilog is required. Epilogs are composed of the
  335. // following:
  336. //
  337. // An ldmdb which uses the frame pointer, R11, as the base and updates
  338. // the PC.
  339. //
  340. // -or-
  341. //
  342. // A stack unlink (ADD R13, x) if necessary, followed by an ldmia which
  343. // updates the PC or a single mov instruction to copy the link register
  344. // to the PC
  345. //
  346. // -or-
  347. //
  348. // An ldmia which updates the link register, followed by a regular
  349. // branch instruction. (This is an optimization when the last instruction
  350. // before a return is a call.)
  351. //
  352. // A routine may also have an empty epilog. (The last instruction is to
  353. // branch to another routine, and it doesn't modify any permanent
  354. // registers.) But, in this case, we would also have an empty prolog.
  355. //
  356. // If we are in an epilog, and the condition codes dictate that the
  357. // instructions should not be executed, treat this as not an epilog at all.
  358. //
  359. // backup the context before trying to execute the epilogue forward
  360. ContextBeforeEpiWind = *Context;
  361. EpilogPc = ControlPc;
  362. if( EpilogPc >= FunctionEntry->PrologEndAddress ) {
  363. //
  364. // Check the condition code of the first instruction. If it won't be
  365. // executed, don't bother checking what type of instruction it is.
  366. //
  367. if(!ReadMemory(EpilogPc, 4L, (LPVOID)&instr ))
  368. return 0;
  369. ExecutingEpilog = CheckConditionCodes( Register[16],
  370. instr.instruction );
  371. while( ExecutingEpilog ) {
  372. if( !ReadMemory( EpilogPc, 4L, (LPVOID)&instr ))
  373. return 0;
  374. //
  375. // Test for these instructions:
  376. //
  377. // ADD R13, X - stack unlink
  378. //
  379. // MOV PC, LR - return
  380. //
  381. // LDMIA or LDMDB including PC - update registers and return
  382. // ( SP ) ( FP )
  383. //
  384. // LDMIA including LR, followed by a branch
  385. // Update registers and branch. (In our case, return.)
  386. //
  387. // A branch preceded by an LDMIA including LR
  388. // Copy the LR to the PC to get the call stack
  389. //
  390. if(( instr.instruction & ADD_SP_MASK ) == ADD_SP_INSTR ) {
  391. WalkArmDataProcess( instr, Register );
  392. } else if(( instr.instruction & MOV_PC_LR_MASK ) == MOV_PC_LR ) {
  393. WalkArmDataProcess( instr, Register );
  394. goto ExitReturnPc;
  395. } else if(( instr.instruction & LDM_PC_MASK ) == LDM_PC_INSTR ) {
  396. if( !WalkArmLoadMultiple( FunctionEntry,
  397. instr,
  398. Register )) {
  399. return 0;
  400. }
  401. goto ExitReturnPc;
  402. } else if(( instr.instruction & LDM_LR_MASK ) == LDM_LR_INSTR ) {
  403. if( !ReadMemory( (ULONG)EpilogPc + 4, 4L, (LPVOID)&instr2))
  404. return 0;
  405. if (((instr2.instruction & B_BL_MASK ) == B_INSTR) || ((instr2.instruction & BX_MASK ) == BX_INSTR)){
  406. if( !WalkArmLoadMultiple( FunctionEntry,
  407. instr,
  408. Register )) {
  409. return 0;
  410. }
  411. goto CopyLrToPcAndExit;
  412. } else {
  413. ExecutingEpilog = FALSE;
  414. }
  415. } else if (((instr.instruction & B_BL_MASK ) == B_INSTR) || ((instr.instruction & BX_MASK ) == BX_INSTR)) {
  416. if( !ReadMemory( (ULONG)EpilogPc - 4, 4L,(LPVOID)&instr2))
  417. return 0;
  418. if(( instr2.instruction & LDM_LR_MASK ) == LDM_LR_INSTR ) {
  419. goto CopyLrToPcAndExit;
  420. }
  421. } else {
  422. ExecutingEpilog = FALSE;
  423. }
  424. EpilogPc += 4;
  425. bEpiWindAlready = TRUE;
  426. }
  427. }
  428. //
  429. // We were not in the epilog. Load in the prolog, and reverse execute it.
  430. //
  431. if (bEpiWindAlready)
  432. {
  433. // if we have already winded some instructions that we
  434. // thought to be the epilog, we may have mess up with the context
  435. // restore the initial context
  436. *Context = ContextBeforeEpiWind;
  437. }
  438. cb = FunctionEntry->PrologEndAddress - FunctionEntry->BeginAddress;
  439. if( cb > sizeof( Prolog )) {
  440. assert( FALSE ); // The prolog should never be more than 10 instructions
  441. return 0;
  442. }
  443. if( !ReadMemory( FunctionEntry->BeginAddress, cb, (LPVOID)Prolog))
  444. return 0;
  445. //
  446. // Check to see if we're already in the prolog.
  447. //
  448. if( ControlPc < FunctionEntry->PrologEndAddress ) {
  449. cb -= ( FunctionEntry->PrologEndAddress - ControlPc );
  450. }
  451. //
  452. // Reverse execute starting with the last instruction in the prolog
  453. // that has been executed.
  454. //
  455. i = cb/4;
  456. i--;
  457. while( i >= 0 ) {
  458. if(( Prolog[i].instruction & DATA_PROC_MASK ) == DP_R11_INSTR ) {
  459. //
  460. // We have a frame pointer.
  461. //
  462. IsFramePointer = TRUE;
  463. } else if((( Prolog[i].instruction & SUB_SP_MASK ) == SUB_SP_INSTR) ||
  464. (( Prolog[i].instruction & ADD_SP_MASK ) == ADD_SP_INSTR)
  465. ) {
  466. //
  467. // This is a stack link. Unlink the stack.
  468. //
  469. if(( Prolog[i].dataproc.bits != 0x1 ) &&
  470. ( Prolog[i].dpshi.rm == 0xc )) {
  471. //
  472. // Look for an LDR instruction above this one.
  473. //
  474. j = i - 1;
  475. while(( j >= 0 ) &&
  476. (( Prolog[j].instruction & LDR_MASK ) != LDR_PC_INSTR )) {
  477. j--;
  478. }
  479. if( j < 0 ) {
  480. assert( FALSE ); // This should never happen
  481. return 0;
  482. }
  483. //
  484. // Get the address of the ldr instruction + 8 + the offset
  485. //
  486. Address = (( j*4 + FunctionEntry->BeginAddress ) +
  487. Prolog[j].ldr.offset ) + 8;
  488. //
  489. // R12 is the value at that location.
  490. //
  491. if( !LoadWordIntoRegister(Address, &Register[12] ))
  492. return 0;
  493. }
  494. //
  495. // Change the subtract to an add (or the add to a subtract)
  496. // and execute the instruction
  497. //
  498. if( Prolog[i].dataproc.opcode == OP_SUB ) {
  499. Prolog[i].dataproc.opcode = OP_ADD;
  500. } else {
  501. Prolog[i].dataproc.opcode = OP_SUB;
  502. }
  503. WalkArmDataProcess( Prolog[i], Register );
  504. } else if(( Prolog[i].instruction & STM_MASK ) == STM_INSTR ) {
  505. if( Prolog[i].ldm.reglist & 0x7ff0 ) { // Check for permanent regs
  506. //
  507. // This is the instruction that stored all of the permanent
  508. // registers. Change the reglist to update R13 (SP) instead of
  509. // R12, and change the STMDB to an LDMDB of R11 or an LDMIA of
  510. // R13.
  511. // Note: We are restoring R14 (LR) - so we'll need to copy
  512. // it to the PC at the end of this function.
  513. //
  514. if(( Prolog[i].ldm.reglist & 0x1000 ) &&
  515. !( Prolog[i].ldm.reglist & 0x2000 )) {
  516. Prolog[i].ldm.reglist &= 0xefff; // Mask out R12
  517. Prolog[i].ldm.reglist |= 0x2000; // Add in R13 (SP)
  518. }
  519. if(( Prolog[i].ldm.reglist & 0x2000 ) || IsFramePointer ) {
  520. Prolog[i].ldm.w = 0; // Clear write-back bit.
  521. }
  522. Prolog[i].ldm.l = 1; // Change to a load.
  523. if( IsFramePointer ) {
  524. Prolog[i].ldm.u = 0; // Decrement
  525. Prolog[i].ldm.p = 1; // Before
  526. Prolog[i].ldm.rn = 0xb; // R11
  527. } else {
  528. Prolog[i].ldm.u = 1; // Increment
  529. Prolog[i].ldm.p = 0; // After
  530. Prolog[i].ldm.rn = 0xd; // R13 (Stack pointer)
  531. }
  532. if( !WalkArmLoadMultiple( FunctionEntry,
  533. Prolog[i],
  534. Register )) {
  535. return 0;
  536. }
  537. PermanentsRestored = TRUE;
  538. } else if( !PermanentsRestored ) {
  539. //
  540. // This is the instruction to load the arguments. Reverse
  541. // execute this instruction only if the permanent registers
  542. // have not been restored.
  543. //
  544. Prolog[i].ldm.l = 1; // Change to a load.
  545. Prolog[i].ldm.u = 1; // Increment
  546. Prolog[i].ldm.p = 0; // After
  547. if( !WalkArmLoadMultiple( FunctionEntry,
  548. Prolog[i],
  549. Register )) {
  550. return 0;
  551. }
  552. }
  553. //
  554. // ajtuck 12/21/97 - added changes from Arm compiler team's unwind.c per jls
  555. //
  556. } else if ((Prolog[i].instruction & STRI_LR_SPU_MASK) == STRI_LR_SPU_INSTR) {
  557. // Store of the link register that updates the stack as a base
  558. // register must be reverse executed to restore LR and SP
  559. // to their values on entry. This type of prolog is generated
  560. // for finally funclets.
  561. Prolog[i].ldr.l = 1; // Clange to a load.
  562. // Since we are updating the base register, we need to change
  563. // when the offset is added to reverse execute the store.
  564. if (Prolog[i].ldr.p == 1)
  565. Prolog[i].ldr.p = 0;
  566. else
  567. Prolog[i].ldr.p = 1;
  568. // And negate the offset
  569. if (Prolog[i].ldr.u == 1)
  570. Prolog[i].ldr.u = 0;
  571. else
  572. Prolog[i].ldr.u = 1;
  573. if (!WalkArmLoadI(Prolog[i], Register))
  574. return ControlPc;
  575. // NOTE: Code could be added above to execute the epilog which
  576. // in this case would be a load to the PC that updates SP as
  577. // the base register. Since the epilog will always be only one
  578. // instruction in this case it is not needed since reverse
  579. // executing the prolog will have the same result.
  580. }
  581. i--;
  582. }
  583. //
  584. // Move the link register into the PC and return.
  585. //
  586. CopyLrToPcAndExit:
  587. // To continue unwinding, put the Link Register into
  588. // the Program Counter slot and carry on; stopping
  589. // when the PC says 0x0. However, the catch is that
  590. // for ARM the Link Register at the bottom of the
  591. // stack says 0x4, not 0x0 as we expect.
  592. // So, do a little dance to take an LR of 0x4
  593. // and turn it into a PC of 0x0 to stop the unwind.
  594. // -- stevea 10/7/99.
  595. if( Register[14] != 0x4 )
  596. Register[15] = Register[14];
  597. else
  598. Register[15] = 0x0;
  599. ExitReturnPc:
  600. return Register[15];
  601. }
  602. BOOL
  603. WalkArmGetStackFrame(
  604. LPDWORD ReturnAddress,
  605. LPDWORD FramePointer,
  606. PARM_CONTEXT Context,
  607. int * Mode
  608. )
  609. {
  610. PIMAGE_ARM_RUNTIME_FUNCTION_ENTRY Rfe;
  611. IMAGE_ARM_RUNTIME_FUNCTION_ENTRY PcFe;
  612. DWORD dwRa;
  613. if (Mode) {
  614. *Mode = MODE_ARM;
  615. }
  616. TestAssumption(*ReturnAddress == Context->Pc, "WAGSF:SF-Cxt mismatch!");
  617. Rfe = (PIMAGE_ARM_RUNTIME_FUNCTION_ENTRY)
  618. UW_FunctionTableAccess(UW_hProcess, *ReturnAddress);
  619. if (!Rfe) {
  620. // For leaf functions, just return the Lr as the return Address.
  621. dwRa = Context->Pc = Context->Lr;
  622. } else {
  623. PcFe = *Rfe;
  624. if (ThumbVirtualUnwind (*ReturnAddress, &PcFe, Context,
  625. &dwRa) == UNWIND_HANDLED) {
  626. // The thumb unwinder handled it.
  627. if (Mode) {
  628. *Mode = MODE_THUMB;
  629. }
  630. } else {
  631. // Now, let the ARM unwinder try it.
  632. dwRa = ArmVirtualUnwind( *ReturnAddress, &PcFe, Context );
  633. }
  634. }
  635. DWORD dwNewSp = 0;
  636. *ReturnAddress = WceTranslateAddress(UW_hProcess, UW_hThread,
  637. dwRa, Context->Sp, &dwNewSp);
  638. if (dwNewSp)
  639. {
  640. Context->Sp = dwNewSp;
  641. }
  642. *FramePointer = Context->Sp;
  643. return TRUE;
  644. }
  645. static VOID
  646. WalkArmDataProcess(
  647. ARMI instr,
  648. PULONG Register
  649. )
  650. /*++
  651. Routine Description:
  652. This function executes an ARM data processing instruction using the
  653. current register set. It automatically updates the destination register.
  654. Arguments:
  655. instr The ARM 32-bit instruction
  656. Register Pointer to the ARM integer registers.
  657. Return Value:
  658. None.
  659. --*/
  660. {
  661. ULONG Op1, Op2;
  662. ULONG Cflag = (Register[16] & 0x20000000L) == 0x20000000L; // CPSR
  663. ULONG shift;
  664. //
  665. // We are checking for all addressing modes and op codes, even though
  666. // the prolog and epilog don't use them all right now. In the future,
  667. // more instructions and addressing modes may be added.
  668. //
  669. //
  670. // Figure out the addressing mode (there are 11 of them), and get the
  671. // operands.
  672. //
  673. Op1 = Register[ instr.dataproc.rn ];
  674. if( instr.dataproc.bits == 0x1 ) {
  675. //
  676. // Immediate addressing - Type 1
  677. //
  678. Op2 = _lrotr( instr.dpi.immediate,
  679. instr.dpi.rotate * 2 );
  680. } else {
  681. //
  682. // Register addressing - start by getting the value of Rm.
  683. //
  684. Op2 = Register[ instr.dpshi.rm ];
  685. if( instr.dprre.bits == 0x6 ) {
  686. //
  687. // Rotate right with extended - Type 11
  688. //
  689. Op2 = ( Cflag << 31 ) | ( Op2 >> 1 );
  690. } else if( instr.dataproc.operand2 & 0x10 ) {
  691. //
  692. // Register shifts. Types 4, 6, 8, and 10
  693. //
  694. //
  695. // Get the shift value from the least-significant byte of the
  696. // shift register.
  697. //
  698. shift = Register[ instr.dpshr.rs ];
  699. shift &= 0xff;
  700. switch( instr.dpshr.bits ) {
  701. case 0x1: // 4 Logical shift left by register
  702. if( shift >= 32 ) {
  703. Op2 = 0;
  704. } else {
  705. Op2 = Op2 << shift;
  706. }
  707. break;
  708. case 0x3: // 6 Logical shift right by register
  709. if( shift >= 32 ) {
  710. Op2 = 0;
  711. } else {
  712. Op2 = Op2 >> shift;
  713. }
  714. break;
  715. case 0x5: // 8 Arithmetic shift right by register
  716. if( shift >= 32 ) {
  717. if( Op2 & 0x80000000 ) {
  718. Op2 = 0xffffffff;
  719. } else {
  720. Op2 = 0;
  721. }
  722. } else {
  723. Op2 = (LONG)Op2 >> shift;
  724. }
  725. break;
  726. case 0x7: // 10 Rotate right by register
  727. if( !( shift == 0 ) && !(( shift & 0xf ) == 0 ) ) {
  728. Op2 = _lrotl( Op2, shift );
  729. }
  730. default:
  731. break;
  732. }
  733. } else {
  734. //
  735. // Immediate shifts. Types 2, 3, 5, 7, and 9
  736. //
  737. //
  738. // Get the shift value from the instruction.
  739. //
  740. shift = instr.dpshi.shift;
  741. switch( instr.dpshi.bits ) {
  742. case 0x0: // 2,3 Register, Logical shift left by immediate
  743. if( shift != 0 ) {
  744. Op2 = Op2 << shift;
  745. }
  746. break;
  747. case 0x2: // 5 Logical shift right by immediate
  748. if( shift == 0 ) {
  749. Op2 = 0;
  750. } else {
  751. Op2 = Op2 >> shift;
  752. }
  753. break;
  754. case 0x4: // 7 Arithmetic shift right by immediate
  755. if( shift == 0 ) {
  756. Op2 = 0;
  757. } else {
  758. Op2 = (LONG)Op2 >> shift;
  759. }
  760. break;
  761. case 0x6: // 9 Rotate right by immediate
  762. Op2 = _lrotl( Op2, shift );
  763. break;
  764. default:
  765. break;
  766. }
  767. }
  768. }
  769. //
  770. // Determine the result (the new PC), based on the opcode.
  771. //
  772. switch( instr.dataproc.opcode ) {
  773. case OP_AND:
  774. Register[ instr.dataproc.rd ] = Op1 & Op2;
  775. break;
  776. case OP_EOR:
  777. Register[ instr.dataproc.rd ] = Op1 ^ Op2;
  778. break;
  779. case OP_SUB:
  780. Register[ instr.dataproc.rd ] = Op1 - Op2;
  781. break;
  782. case OP_RSB:
  783. Register[ instr.dataproc.rd ] = Op2 - Op1;
  784. break;
  785. case OP_ADD:
  786. Register[ instr.dataproc.rd ] = Op1 + Op2;
  787. break;
  788. case OP_ADC:
  789. Register[ instr.dataproc.rd ] = (Op1 + Op2) + Cflag;
  790. break;
  791. case OP_SBC:
  792. Register[ instr.dataproc.rd ] = (Op1 - Op2) - ~Cflag;
  793. break;
  794. case OP_RSC:
  795. Register[ instr.dataproc.rd ] = (Op2 - Op1) - ~Cflag;
  796. break;
  797. case OP_ORR:
  798. Register[ instr.dataproc.rd ] = Op1 | Op2;
  799. break;
  800. case OP_MOV:
  801. Register[ instr.dataproc.rd ] = Op2;
  802. break;
  803. case OP_BIC:
  804. Register[ instr.dataproc.rd ] = Op1 & ~Op2;
  805. break;
  806. case OP_MVN:
  807. Register[ instr.dataproc.rd ] = ~Op2;
  808. break;
  809. case OP_TST:
  810. case OP_TEQ:
  811. case OP_CMP:
  812. case OP_CMN:
  813. default:
  814. //
  815. // These instructions do not have a destination register.
  816. // There is nothing to do.
  817. //
  818. break;
  819. }
  820. }
  821. static BOOL
  822. WalkArmLoadMultiple(
  823. PIMAGE_ARM_RUNTIME_FUNCTION_ENTRY FunctionEntry,
  824. ARMI instr,
  825. PULONG Register
  826. )
  827. /*++
  828. Routine Description:
  829. This function executes an ARM load multiple instruction.
  830. Arguments:
  831. FunctionEntry Supplies the address of the function table entry for the
  832. specified function.
  833. instr The ARM 32-bit instruction
  834. Register Pointer to the ARM integer registers.
  835. Return Value:
  836. TRUE if successful, FALSE otherwise.
  837. --*/
  838. {
  839. ULONG cb;
  840. LONG i;
  841. ULONG RegList;
  842. PULONG Rn;
  843. //
  844. // Load multiple with the PC bit set. We are currently checking for all
  845. // four addressing modes, even though decrement before and increment
  846. // after are the only modes currently used in the epilog and prolog.
  847. //
  848. //
  849. // Rn is the address at which to begin, and RegList is the bit map of which
  850. // registers to read.
  851. //
  852. Rn = (PULONG)(ULONG_PTR)Register[ instr.ldm.rn ];
  853. RegList = instr.ldm.reglist;
  854. if( instr.ldm.p ) {
  855. if( instr.ldm.u ) {
  856. //
  857. // Increment before
  858. //
  859. for( i = 0; i <= 15; i++ ) {
  860. if( RegList & 0x1 ) {
  861. Rn++;
  862. if(!LoadWordIntoRegister((ULONG)(ULONG_PTR)Rn,&Register[i])){
  863. return FALSE;
  864. }
  865. }
  866. RegList = RegList >> 1;
  867. }
  868. } else {
  869. //
  870. // Decrement before
  871. //
  872. for( i = 15; i >= 0; i-- ) {
  873. if( RegList & 0x8000 ) {
  874. Rn--;
  875. if( !LoadWordIntoRegister((ULONG)(ULONG_PTR)Rn,&Register[i])) {
  876. return FALSE;
  877. }
  878. }
  879. RegList = RegList << 1;
  880. }
  881. }
  882. } else {
  883. if( instr.ldm.u ) {
  884. //
  885. // Increment after
  886. //
  887. for( i = 0; i <= 15; i++ ) {
  888. if( RegList & 0x1 ) {
  889. if( !LoadWordIntoRegister((ULONG)(ULONG_PTR)Rn,&Register[i])) {
  890. return FALSE;
  891. }
  892. Rn++;
  893. }
  894. RegList = RegList >> 1;
  895. }
  896. } else {
  897. //
  898. // Decrement after
  899. //
  900. for( i = 15; i >= 0; i-- ) {
  901. if( RegList & 0x8000 ) {
  902. if( !LoadWordIntoRegister((ULONG)(ULONG_PTR)Rn,&Register[i])) {
  903. return FALSE;
  904. }
  905. Rn--;
  906. }
  907. RegList = RegList << 1;
  908. }
  909. }
  910. }
  911. if( instr.ldm.w ) {
  912. //
  913. // Update the base register.
  914. //
  915. Register[ instr.ldm.rn ] = (ULONG)(ULONG_PTR)Rn;
  916. }
  917. return TRUE;
  918. }
  919. static BOOL
  920. WalkArmLoadI(
  921. ARMI instr,
  922. PULONG Register
  923. )
  924. /*++
  925. Routine Description:
  926. This function executes an ARM load instruction with an immediat offset.
  927. Arguments:
  928. instr The ARM 32-bit instruction
  929. Register Pointer to the ARM integer registers.
  930. Return Value:
  931. TRUE if successful, FALSE otherwise.
  932. --*/
  933. {
  934. LONG offset;
  935. LONG size;
  936. PULONG Rn;
  937. DWORD cb;
  938. Rn = (PULONG)(ULONG_PTR)Register[instr.ldr.rn];
  939. offset = instr.ldr.offset;
  940. if (instr.ldr.u == 0)
  941. offset = -offset;
  942. if (instr.ldr.b == 0)
  943. size = 4;
  944. else
  945. size = 1;
  946. if (instr.ldm.p) { // add offset before transfer
  947. if( !ReadMemory( (ULONG)(ULONG_PTR)(Rn + offset), size, (LPVOID)&Register[instr.ldr.rd]))
  948. return FALSE;
  949. if (instr.ldr.w)
  950. Register[instr.ldr.rn] += offset;
  951. } else {
  952. if( !ReadMemory( (ULONG)(ULONG_PTR)Rn, size, (LPVOID)&Register[instr.ldr.rd]))
  953. return FALSE;
  954. if (instr.ldr.w)
  955. Register[instr.ldr.rn] += offset;
  956. }
  957. return TRUE;
  958. }
  959. static BOOL
  960. CheckConditionCodes(
  961. ULONG CPSR,
  962. DWORD instr
  963. )
  964. /*++
  965. Routine Description:
  966. Checks the condition codes of the instruction and the values of the
  967. condition flags in the current program status register, and determines
  968. whether or not the instruction will be executed.
  969. Arguments:
  970. CPSR - The value of the Current Program Status Register.
  971. instr - The instruction to analyze.
  972. Return Value:
  973. TRUE if the instruction will be executed, FALSE otherwise.
  974. --*/
  975. {
  976. BOOL Execute = FALSE;
  977. BOOL Nset = (CPSR & 0x80000000L) == 0x80000000L;
  978. BOOL Zset = (CPSR & 0x40000000L) == 0x40000000L;
  979. BOOL Cset = (CPSR & 0x20000000L) == 0x20000000L;
  980. BOOL Vset = (CPSR & 0x10000000L) == 0x10000000L;
  981. instr &= COND_MASK;
  982. switch( instr ) {
  983. case COND_EQ: // Z set
  984. if( Zset ) Execute = TRUE;
  985. break;
  986. case COND_NE: // Z clear
  987. if( !Zset ) Execute = TRUE;
  988. break;
  989. case COND_CS: // C set
  990. if( Cset ) Execute = TRUE;
  991. break;
  992. case COND_CC: // C clear
  993. if( !Cset ) Execute = TRUE;
  994. break;
  995. case COND_MI: // N set
  996. if( Nset ) Execute = TRUE;
  997. break;
  998. case COND_PL: // N clear
  999. if( !Nset ) Execute = TRUE;
  1000. break;
  1001. case COND_VS: // V set
  1002. if( Vset ) Execute = TRUE;
  1003. break;
  1004. case COND_VC: // V clear
  1005. if( !Vset ) Execute = TRUE;
  1006. break;
  1007. case COND_HI: // C set and Z clear
  1008. if( Cset && !Zset ) Execute = TRUE;
  1009. break;
  1010. case COND_LS: // C clear or Z set
  1011. if( !Cset || Zset ) Execute = TRUE;
  1012. break;
  1013. case COND_GE: // N == V
  1014. if(( Nset && Vset ) || ( !Nset && !Vset )) Execute = TRUE;
  1015. break;
  1016. case COND_LT: // N != V
  1017. if(( Nset && !Vset ) || ( !Nset && Vset )) Execute = TRUE;
  1018. break;
  1019. case COND_GT: // Z clear, and N == V
  1020. if( !Zset &&
  1021. (( Nset && Vset ) || ( !Nset && !Vset ))) Execute = TRUE;
  1022. break;
  1023. case COND_LE: // Z set, and N != V
  1024. if( Zset &&
  1025. (( Nset && !Vset ) || ( !Nset && Vset ))) Execute = TRUE;
  1026. break;
  1027. case COND_AL: // Always execute
  1028. Execute = TRUE;
  1029. break;
  1030. default:
  1031. case COND_NV: // Never - undefined.
  1032. assert( FALSE );
  1033. break;
  1034. }
  1035. return Execute;
  1036. }
  1037. /*
  1038. THUMB!!!
  1039. */
  1040. typedef struct _DcfInst {
  1041. int InstNum;
  1042. union {
  1043. DWORD Auxil;
  1044. DWORD Rd;
  1045. };
  1046. union {
  1047. DWORD Aux2;
  1048. DWORD Rs;
  1049. };
  1050. } DcfInst;
  1051. typedef struct _DIList {
  1052. DWORD Val,Mask;
  1053. int InstNum;
  1054. DWORD RdMask;
  1055. int RdShift;
  1056. DWORD RsMask;
  1057. int RsShift;
  1058. } DIList;
  1059. DIList dilistThumb[] = {
  1060. #define DI_PUSH 0x02
  1061. #define DI_POP 0x03
  1062. {0xB400,0xFE00,DI_PUSH, 0x00FF,0,0x0100,-8}, //PUSH
  1063. {0xBC00,0xFE00,DI_POP, 0x00FF,0,0x0100,-8}, //POP
  1064. #define DI_DECSP 0x04
  1065. #define DI_INCSP 0x05
  1066. {0xB080,0xFF80,DI_DECSP, 0x007F,2,0x0000,0}, //DecSP
  1067. {0xB000,0xFF80,DI_INCSP, 0x007F,2,0x0000,0}, //IncSP
  1068. #define DI_MOVHI 0x08
  1069. #define DI_ADDHI 0x09
  1070. {0x4600,0xFF00,DI_MOVHI, 0x0007,0,0x0078,-3}, //MovHiRegs
  1071. {0x4400,0xFF00,DI_ADDHI, 0x0007,0,0x0078,-3}, //AddHiRegs
  1072. #define DI_BLPFX 0x10
  1073. #define DI_BL 0x11
  1074. {0xF000,0xF800,DI_BLPFX, 0x07FF,12,0x0000,0}, //BL prefix
  1075. {0xF800,0xF800,DI_BL, 0x07FF,1,0x0000,0}, //BL
  1076. #define DI_BX_TMB 0x20
  1077. {0x4700,0xFF87,DI_BX_TMB, 0x0078,-3,0x0000,0}, //BX
  1078. #define DI_LDRPC 0x40
  1079. {0x4800,0xF800,DI_LDRPC, 0x0700,-8,0x00FF,2}, //LDR pc
  1080. #define DI_NEG 0x80
  1081. {0x4240,0xFFC0,DI_NEG, 0x0007,0,0x0038,-3}, //Neg Rx,Ry
  1082. {0x0000,0x0000,0x00, 0x0000,0,0x0000,0} //End of list
  1083. };
  1084. DIList dilistARM[] = {
  1085. #define DI_STMDB 0x102
  1086. #define DI_LDMIA 0x103
  1087. {0xE92D0000,0xFFFF0000,DI_STMDB, 0x0000FFFF,0,0x00000000,0}, // STMDB
  1088. {0xE8BD0000,0xFFFF0000,DI_LDMIA, 0x0000FFFF,0,0x00000000,0}, // LDMIA
  1089. #define DI_BX_ARM 0x120
  1090. {0x012FFF10,0x0FFFFFF0,DI_BX_ARM, 0x0000000F,0,0x00000000,0}, // BX_ARM
  1091. {0x00000000,0x00000000,0, 0x00000000,0,0x00000000,0} // end of list
  1092. };
  1093. static int DecipherInstruction(DWORD inst, DcfInst *DI, int Mode)
  1094. {
  1095. int i;
  1096. DIList *dl = dilistThumb;
  1097. assert(DI);
  1098. if(!DI) return 0;
  1099. memset(DI,0,sizeof(DcfInst));
  1100. if(Mode==MODE_ARM) dl = dilistARM;
  1101. for(i=0;dl[i].Mask!=0 && DI->InstNum==0; i++) {
  1102. if((inst&dl[i].Mask)==dl[i].Val) {
  1103. DI->InstNum = dl[i].InstNum;
  1104. DI->Rd = (inst&dl[i].RdMask);
  1105. if(DI->Rd && dl[i].RdShift) {
  1106. if(dl[i].RdShift>0) DI->Rd <<= dl[i].RdShift;
  1107. else if(dl[i].RdShift<0) DI->Rd >>= (-dl[i].RdShift);
  1108. }
  1109. DI->Rs = (inst&dl[i].RsMask);
  1110. if(DI->Rs && dl[i].RsShift) {
  1111. if(dl[i].RsShift>0) DI->Rs <<= dl[i].RsShift;
  1112. else if(dl[i].RsShift<0) DI->Rs >>= (-dl[i].RsShift);
  1113. }
  1114. // Special case to handle MovHiRegs and AddHiRegs.
  1115. if((DI->InstNum&~0x01)==8 ) {
  1116. DI->Rd |= ((inst&0x0080)>>4);
  1117. }
  1118. }
  1119. }
  1120. if(Mode==MODE_ARM) return 4;
  1121. return 2; // Instructions are 2 bytes long.
  1122. }
  1123. #if 0
  1124. static DWORD
  1125. ComputeCallAddress(DWORD RetAddr, int Mode)
  1126. {
  1127. DWORD instr;
  1128. DcfInst di;
  1129. // If the caller is ARM mode, then the call address
  1130. // is always 4 less than the return address.
  1131. if(RetAddr&0x01) return RetAddr-4;
  1132. if(!ReadMemory(&instr,RetAddr,2)) return RetAddr;
  1133. DcfInst(instr,&di,Mode);
  1134. if(di.InstNum==BL_TMB)
  1135. #endif
  1136. enum
  1137. {
  1138. PushOp, // Also used for Pop operations.
  1139. AdjSpOp,
  1140. MovOp
  1141. }; // Used for operation field below
  1142. typedef struct _OpEntry {
  1143. struct _OpEntry *next;
  1144. struct _OpEntry *prev;
  1145. int Operation;
  1146. int RegNumber; // Used for Push/Pop
  1147. int SpAdj; // Used for AdjSpOp, and PushOp.
  1148. int Rd; // Used for MovOp
  1149. int Rs; // Used for MovOp
  1150. ULONG Address; // Instruction address that generated this OpEntry
  1151. } OpEntry;
  1152. typedef struct _OpList {
  1153. OpEntry *head;
  1154. OpEntry *tail;
  1155. } OpList;
  1156. static OpEntry*
  1157. MakeNewOpEntry
  1158. (
  1159. int Operation,
  1160. OpEntry* prev,
  1161. ULONG Address
  1162. )
  1163. {
  1164. ULONG size = sizeof(OpEntry);
  1165. OpEntry *oe = (OpEntry*)MemAlloc(size);
  1166. if(!oe) return NULL;
  1167. memset(oe,0,sizeof(OpEntry));
  1168. oe->prev = prev;
  1169. oe->Operation = Operation;
  1170. oe->Address = Address;
  1171. return oe;
  1172. }
  1173. static void
  1174. FreeOpList(OpList* ol)
  1175. {
  1176. OpEntry *oe;
  1177. OpEntry *next;
  1178. if(!ol)return;
  1179. for(oe=ol->head;oe;oe=next){
  1180. next = oe->next;
  1181. memset(oe,0xCA,sizeof(OpEntry));
  1182. MemFree(oe);
  1183. }
  1184. ol->head = ol->tail = NULL;
  1185. }
  1186. static void
  1187. BuildOnePushPopOp
  1188. (
  1189. OpList* pOL,
  1190. int RegNum,
  1191. ULONG Address
  1192. )
  1193. {
  1194. if(pOL->head == NULL) {
  1195. OpEntry* Entry = MakeNewOpEntry(PushOp,NULL,Address);
  1196. if (!Entry) {
  1197. return;
  1198. }
  1199. pOL->head = pOL->tail = Entry;
  1200. } else {
  1201. OpEntry* Entry = MakeNewOpEntry(PushOp,pOL->tail,Address);
  1202. if (!Entry) {
  1203. return;
  1204. }
  1205. pOL->tail->next = Entry;
  1206. pOL->tail = pOL->tail->next;
  1207. }
  1208. pOL->tail->RegNumber = RegNum;
  1209. pOL->tail->SpAdj = REGISTER_SIZE;
  1210. }
  1211. // PushLR is only for use by Thumb PUSH op, and should be 0
  1212. // for ARM STMDB op.
  1213. static int
  1214. BuildPushOp
  1215. (
  1216. OpList* pOL,
  1217. DWORD PushList,
  1218. DWORD PushLR,
  1219. ULONG Address
  1220. )
  1221. {
  1222. int RegNum;
  1223. int cop = 0;
  1224. if(PushList==0 && PushLR==0) return 0;
  1225. DWORD RegMask = 0x8000;
  1226. if(PushLR){ BuildOnePushPopOp(pOL,14,Address); cop++; }
  1227. for(RegNum=15;RegNum>=0;RegNum--) {
  1228. if(PushList&RegMask) { BuildOnePushPopOp(pOL,RegNum,Address); cop++; }
  1229. RegMask = RegMask>>1;
  1230. }
  1231. return cop;
  1232. }
  1233. // PopPC is only for use by Thumb Pop op, and should be 0
  1234. // for ARM LDMIA op.
  1235. static int
  1236. BuildPopOp
  1237. (
  1238. OpList* pOL,
  1239. DWORD PopList,
  1240. DWORD PopPC,
  1241. ULONG Address
  1242. )
  1243. {
  1244. int RegNum;
  1245. int cop = 0;
  1246. if(PopList==0 && PopPC==0) return 0;
  1247. for(RegNum=0;PopList;RegNum++) {
  1248. if(PopList&1) { BuildOnePushPopOp(pOL,RegNum,Address); cop++; }
  1249. PopList = PopList>>1;
  1250. }
  1251. if(PopPC) { BuildOnePushPopOp(pOL,15,Address); cop++; }
  1252. return cop;
  1253. }
  1254. static int
  1255. BuildAdjSpOp
  1256. (
  1257. OpList *pOL,
  1258. int Val,
  1259. ULONG Address
  1260. )
  1261. {
  1262. if(Val==0) return 0;
  1263. if(pOL->head == NULL) {
  1264. OpEntry* Entry = MakeNewOpEntry(AdjSpOp,NULL,Address);
  1265. if (!Entry) {
  1266. return 0;
  1267. }
  1268. pOL->head = pOL->tail = Entry;
  1269. } else {
  1270. // Don't try to compress this by combining adjacent AdjSpOp's.
  1271. // Each actual instruction must yield at least one OpEntry
  1272. // for use when we unwind the epilog.
  1273. OpEntry* Entry = MakeNewOpEntry(AdjSpOp,pOL->tail,Address);
  1274. if (!Entry) {
  1275. return 0;
  1276. }
  1277. pOL->tail->next = Entry;
  1278. pOL->tail = pOL->tail->next;
  1279. }
  1280. pOL->tail->SpAdj = Val;
  1281. return 1;
  1282. }
  1283. static int
  1284. BuildMovOp(OpList *pOL, int Rd, int Rs, ULONG Address)
  1285. {
  1286. if(pOL->head == NULL) {
  1287. OpEntry* Entry = MakeNewOpEntry(MovOp,NULL,Address);
  1288. if (!Entry) {
  1289. return 0;
  1290. }
  1291. pOL->head = pOL->tail = Entry;
  1292. } else {
  1293. OpEntry* Entry = MakeNewOpEntry(MovOp,pOL->tail,Address);
  1294. if (!Entry) {
  1295. return 0;
  1296. }
  1297. pOL->tail->next = Entry;
  1298. pOL->tail = pOL->tail->next;
  1299. }
  1300. pOL->tail->Rd = Rd;
  1301. pOL->tail->Rs = Rs;
  1302. return 1;
  1303. }
  1304. static BOOL
  1305. BuildOps
  1306. (
  1307. ULONG SectionStart,
  1308. ULONG SectionLen,
  1309. PULONG CxtRegs,
  1310. int Mode,
  1311. OpList *pOL,
  1312. LONG* cOps
  1313. )
  1314. {
  1315. BOOL rc; ULONG cb;
  1316. ULONG Pc;
  1317. ULONG PcTemp;
  1318. ULONG InstAddr;
  1319. DWORD ThisInstruction;
  1320. BOOL Continue;
  1321. ULONG Ra;
  1322. BOOL InHelper = FALSE;
  1323. DcfInst di;
  1324. int len;
  1325. long spadj;
  1326. PIMAGE_ARM_RUNTIME_FUNCTION_ENTRY HelperFE;
  1327. ULONG HelperStart;
  1328. ULONG HelperLen;
  1329. ULONG HelperEnd;
  1330. ULONG Register[16];
  1331. ULONG DummyReg[16];
  1332. BOOL DummyInit[16];
  1333. ULONG SectionEnd = SectionStart + SectionLen;
  1334. int i;
  1335. OpEntry *pOE;
  1336. pOL->head = pOL->tail = NULL;
  1337. for(i=0;i<16;i++){
  1338. Register[i] = CxtRegs[i];
  1339. DummyInit[i]=FALSE;
  1340. DummyReg[i]=0xBADDC0DE;
  1341. }
  1342. *cOps = 0;
  1343. Pc = SectionStart;
  1344. Continue = TRUE;
  1345. while(Continue || (InHelper && (Pc <= HelperEnd))) {
  1346. InstAddr = Pc;
  1347. ReadMemory(Pc,4,&ThisInstruction);
  1348. len = DecipherInstruction(ThisInstruction,&di,Mode);
  1349. Pc += len;
  1350. if(((Pc >= SectionEnd) && !InHelper) ||
  1351. (InHelper && (Pc > HelperEnd)))
  1352. {
  1353. Continue = FALSE; // This will be our last pass.
  1354. }
  1355. switch(di.InstNum) {
  1356. case DI_STMDB:
  1357. case DI_PUSH:
  1358. *cOps += BuildPushOp(pOL,di.Auxil,di.Aux2,InstAddr);
  1359. break;
  1360. case DI_LDMIA:
  1361. case DI_POP:
  1362. *cOps += BuildPopOp(pOL,di.Auxil,di.Aux2,InstAddr);
  1363. break;
  1364. case DI_DECSP:
  1365. case DI_INCSP:
  1366. *cOps += BuildAdjSpOp(pOL,di.Auxil,InstAddr);
  1367. break;
  1368. case DI_MOVHI:
  1369. // The ops we care about are
  1370. // MOV Rx,SP / MOV SP,Rx FramePointer saves
  1371. // MOV Rx,LR Used in epilog helpers
  1372. if ((di.Rd != 15) && ((di.Rs == 13) || (di.Rd == 13) || (di.Rs == 14)))
  1373. {
  1374. // epilogue helpers move LR to R3 and BX to R3 to return.
  1375. if (DummyInit[di.Rs])
  1376. {
  1377. DummyReg[di.Rd] = DummyReg[di.Rs];
  1378. DummyInit[di.Rd] = TRUE;
  1379. }
  1380. *cOps += BuildMovOp(pOL,di.Rd,di.Rs,InstAddr);
  1381. }
  1382. break;
  1383. case DI_LDRPC:
  1384. {
  1385. // the offset for the ldr instruction is always
  1386. // pc + 4 (InstAddr is pc here).
  1387. DWORD Addr = InstAddr+4+di.Aux2;
  1388. // Also need to ensure that the data is 4-byte aligned
  1389. // so mask off the last bits (we sometimes get 2-byte
  1390. // aligned offsets in retail builds of the OS).
  1391. Addr &= ~(0x3);
  1392. if(!LoadWordIntoRegister(Addr, &DummyReg[di.Rd])) return FALSE;
  1393. DummyInit[di.Rd] = TRUE;
  1394. break;
  1395. }
  1396. case DI_NEG:
  1397. assert(DummyInit[di.Rs]);
  1398. DummyReg[di.Rd] = (~DummyReg[di.Rs])+1;
  1399. DummyInit[di.Rd] = DummyInit[di.Rs];
  1400. break;
  1401. case DI_ADDHI:
  1402. assert(di.Rd==13); // Used only to make big changes to SP.
  1403. // Better have the source register initialized with an
  1404. // immediate.
  1405. if (!DummyInit[di.Rs])
  1406. {
  1407. // we're probably walking the epilogue forward and the
  1408. // value we need is already in the real register
  1409. DummyReg[di.Rs] = Register[di.Rs];
  1410. DummyInit[di.Rs] = TRUE;
  1411. }
  1412. spadj = (long)(DummyReg[di.Rs]);
  1413. if(spadj<0) spadj = -spadj;
  1414. *cOps += BuildAdjSpOp(pOL,spadj,InstAddr);
  1415. break;
  1416. case DI_BLPFX:
  1417. // Sign extend the Auxil:
  1418. if(di.Auxil & 0x00400000) di.Auxil |= 0xFF800000;
  1419. DummyReg[14] = Pc + 2 + (int)(di.Auxil);
  1420. DummyInit[14] = TRUE;
  1421. break;
  1422. case DI_BL:
  1423. {
  1424. // This can happen if there is an epilog/prolog helper
  1425. // function for this particular unwind.
  1426. // use some local value to verify that it is indeed an
  1427. // epilog/prolog helper before messing up the global
  1428. // data
  1429. DWORD TempPc = Pc;
  1430. DWORD TempRa;
  1431. DWORD DummyReg14 = DummyReg[14];
  1432. if(DummyInit[14]==FALSE)
  1433. {
  1434. // Didn't catch the first instruction of the two
  1435. // instruction BL. That means that it's likely
  1436. // we're attempting to forward execute an epilog.
  1437. // The heuristic used to find the beginning
  1438. // of the epilog doesn't always do exactly the
  1439. // right thing, so the address indicated as the
  1440. // beginning of the epilog really isn't, and in
  1441. // this case ended up grabbing the last half of
  1442. // a BL pair. To get around this, just NOP it.
  1443. // -- stevea 3/21/2000
  1444. break;
  1445. }
  1446. // Compute the return address.
  1447. TempRa = TempPc | 1; // Pc already points to next instruction.
  1448. // Sign extend the Auxil:
  1449. if(di.Auxil & 0x00001000) di.Auxil |= 0xFFFFE000;
  1450. // Generate the BL target
  1451. TempPc = DummyReg14 + (int)(di.Auxil);
  1452. DummyReg14 = TempRa;
  1453. // Examine the target of this branch:
  1454. HelperFE = (PIMAGE_ARM_RUNTIME_FUNCTION_ENTRY)
  1455. UW_FunctionTableAccess(UW_hProcess, TempPc);
  1456. if (HelperFE)
  1457. {
  1458. // Make sure that this is a prologue/epilogue helper.
  1459. if (IS_HELPER_FUNCTION(HelperFE))
  1460. {
  1461. // just continue with the next instruction
  1462. break;
  1463. }
  1464. // Actually is a prologue/epilogue helper
  1465. Pc = TempPc;
  1466. Ra = TempRa;
  1467. DummyReg[14] = DummyReg14;
  1468. HelperStart = HelperFE->BeginAddress & ~0x01;
  1469. HelperEnd = HelperFE->EndAddress & ~0x01;
  1470. HelperLen = HelperEnd - HelperStart;
  1471. InHelper = TRUE;
  1472. }
  1473. break;
  1474. }
  1475. case DI_BX_ARM:
  1476. // If we're unwinding, and we're working our way
  1477. // through a helper, then when we get to this
  1478. // instruction, we just slip neatly back to the main body:
  1479. if(InHelper) {
  1480. assert((di.Rd==14) || (di.Rd==3)); // BX LR is the only way out of a prologue helper.
  1481. // BX r3 is the only way out of an epilogue helper.
  1482. assert(DummyInit[di.Rd]);
  1483. InHelper = FALSE;
  1484. if(DummyInit[di.Rd] && (DummyReg[di.Rd] & 0x1)) { // returning to thumb code...
  1485. Pc = DummyReg[di.Rd] & ~0x01;
  1486. Mode = MODE_THUMB;
  1487. assert(Pc>SectionStart && Pc<=SectionEnd);
  1488. } else { // returning to ARM code? This is wrong.
  1489. assert(FALSE);
  1490. return FALSE;
  1491. }
  1492. } else {
  1493. // We've encountered this instruction, but not in a helper.
  1494. // We must have started out inside a helper, and somehow
  1495. // got this far. OK, we're done unwinding.
  1496. Continue = FALSE;
  1497. }
  1498. break;
  1499. case DI_BX_TMB:
  1500. if(di.Auxil==15) { // BX PC
  1501. Pc = (Pc+2)&~0x03;
  1502. Mode = MODE_ARM; // Now, we're in ARM mode, because PC is always even.
  1503. } else {
  1504. ULONG NewPc;
  1505. Mode = (Register[di.Auxil] &0x01)?MODE_THUMB:MODE_ARM;
  1506. if(Mode==MODE_THUMB)
  1507. NewPc = Register[di.Auxil] & ~0x01;
  1508. else
  1509. NewPc = Register[di.Auxil] & ~0x03;
  1510. }
  1511. break;
  1512. default:
  1513. break;
  1514. } // end of switch statement
  1515. } // end of while(Pc<EndAddress) loop.
  1516. return TRUE;
  1517. }
  1518. #define NEED_MORE_EPILOG -1
  1519. #define DOESNT_MATCH 0
  1520. #define DOES_MATCH 1
  1521. static BOOL PrologMatchesCandidateEpilog(OpList*,OpList*,int,ULONG*);
  1522. // TODO: This function currently treats a prologue/epilogue helper function as if it has
  1523. // TODO: its own stack frame when the PC is inside the helper. This doesn't work very
  1524. // TODO: well because the frame below it has special knowledge of the helper as well,
  1525. // TODO: so we end up unwinding the helper anywhere (fractions included) between 0 and
  1526. // TODO: times. It should really treat the helper as part of its calling frame and
  1527. // TODO: unwind everything exactly once.
  1528. static int
  1529. ThumbVirtualUnwind (
  1530. DWORD ControlPc,
  1531. PIMAGE_ARM_RUNTIME_FUNCTION_ENTRY FunctionEntry,
  1532. PARM_CONTEXT Context,
  1533. DWORD* ReturnAddress
  1534. )
  1535. /*++
  1536. Routine Description:
  1537. This function virtually unwinds the specfified function by executing its
  1538. prologue code backwards (or its epilog forward).
  1539. If the function is a leaf function, then the address where control left
  1540. the previous frame is obtained from the context record. If the function
  1541. is a nested function, but not an exception or interrupt frame, then the
  1542. prologue code is executed backwards and the address where control left
  1543. the previous frame is obtained from the updated context record.
  1544. Otherwise, an exception or interrupt entry to the system is being unwound
  1545. and a specially coded prologue restores the return address twice. Once
  1546. from the fault instruction address and once from the saved return address
  1547. register. The first restore is returned as the function value and the
  1548. second restore is place in the updated context record.
  1549. If a context pointers record is specified, then the address where each
  1550. nonvolatile registers is restored from is recorded in the appropriate
  1551. element of the context pointers record.
  1552. Arguments:
  1553. ControlPc - Supplies the address where control left the specified
  1554. function.
  1555. FunctionEntry - Supplies the address of the function table entry for the
  1556. specified function.
  1557. Context - Supplies the address of a context record.
  1558. Return Value:
  1559. The address where control left the previous frame is returned as the
  1560. function value.
  1561. --*/
  1562. {
  1563. ULONG Address;
  1564. ULONG FunctionStart;
  1565. OpEntry* pOE;
  1566. BYTE* Prolog;
  1567. ULONG PrologStart,PrologLen,PrologEnd;
  1568. OpList PrologOL = {NULL,NULL};
  1569. LONG PrologOpCount = 0;
  1570. BYTE* Epilog;
  1571. ULONG EpilogStart,EpilogLen,MaxEpilogLen,EpilogEnd;
  1572. BOOL FoundEpilogEnd = FALSE;
  1573. int ReturnRegisterIndex = 14;
  1574. DWORD EpilogPc;
  1575. LONG i,j,Sp;
  1576. ARMI instr, instr2;
  1577. PULONG Register = &Context->R0;
  1578. LONG StackSize = 0;
  1579. ULONG FramePointer = 0;
  1580. ULONG DummyReg[16];
  1581. BOOL DummyRegInit[16];
  1582. BOOL rc; LONG cb;
  1583. enum {
  1584. StartingInProlog,
  1585. StartingInFunctionBody,
  1586. StartingInEpilog,
  1587. StartingInPrologHelper,
  1588. StartingInEpilogHelper,
  1589. StartingInCallThunk,
  1590. StartingInLongBranchThunk
  1591. } StartingPlace = StartingInFunctionBody; // default assumption.
  1592. // Default: return the value that will terminate unwind.
  1593. *ReturnAddress = 0;
  1594. if( !FunctionEntry ) return UNWIND_NOT_HANDLED;
  1595. // If not a Thumb function, don't handle it here.
  1596. if(!(FunctionEntry->BeginAddress&0x01)) return UNWIND_NOT_HANDLED;
  1597. // Inside of a thumb function, so the PC will have the
  1598. // 16-bit mode set. Clear that out for our purposes here.
  1599. ControlPc &= ~0x1;
  1600. PrologStart = FunctionStart = FunctionEntry->BeginAddress & ~0x01;
  1601. PrologEnd = FunctionEntry->PrologEndAddress & ~0x01;
  1602. PrologLen = PrologEnd-PrologStart;
  1603. // Look at Exception Info to see if we're in a helper.
  1604. if(FunctionEntry->ExceptionHandler == EXCINFO_NULL_HANDLER) {
  1605. switch ((int)FunctionEntry->HandlerData) {
  1606. case EXCINFO_PROLOG_HELPER:
  1607. StartingPlace = StartingInPrologHelper;
  1608. break;
  1609. case EXCINFO_EPILOG_HELPER:
  1610. StartingPlace = StartingInEpilogHelper;
  1611. break;
  1612. }
  1613. }
  1614. switch(StartingPlace) {
  1615. case StartingInFunctionBody:
  1616. FoundEpilogEnd = FALSE;
  1617. if(ControlPc==PrologStart) {
  1618. // Haven't done anything yet, just copy LR to PC and return:
  1619. goto ThumbUnwindExit;
  1620. }
  1621. if(PrologStart==PrologEnd) {
  1622. // No prolog. Just copy LR to PC and return.
  1623. goto ThumbUnwindExit;
  1624. }
  1625. if(ControlPc>PrologStart && ControlPc<=PrologEnd) {
  1626. StartingPlace = StartingInProlog;
  1627. }
  1628. break;
  1629. case StartingInPrologHelper:
  1630. // If we're in a prolog helper, then the whole function is a prolog!
  1631. PrologEnd = FunctionEntry->EndAddress & ~0x1;
  1632. PrologLen = PrologEnd-PrologStart;
  1633. break;
  1634. case StartingInEpilogHelper:
  1635. // If we're in an epilog helper, then the whole function is an epilog!
  1636. FoundEpilogEnd = TRUE;
  1637. EpilogStart = FunctionEntry->BeginAddress & ~0x01;
  1638. EpilogEnd = FunctionEntry->EndAddress & ~0x01;
  1639. EpilogLen = EpilogEnd-EpilogStart;
  1640. break;
  1641. }
  1642. if((StartingPlace != StartingInProlog) && (StartingPlace != StartingInPrologHelper))
  1643. {
  1644. DWORD inst;
  1645. DcfInst di;
  1646. // First, let's see if we're in the epilog...
  1647. // We'll know that we are, because the epilog is the only place where
  1648. // we find a set of instructions that undoes the action of the prolog,
  1649. // and then does a MOV PC,Rx, or BX Rx.
  1650. // If we don't know where the end of the epilog is yet, find a candidate.
  1651. if(FoundEpilogEnd==FALSE) {
  1652. // The epilog can be a few instructions longer than the prolog. That
  1653. // limits our search distance:
  1654. MaxEpilogLen = PrologLen+4;
  1655. // Find a MOV PC,Rx or BX Rx within that distance, or we're not in the
  1656. // epilog.
  1657. for(EpilogPc=ControlPc;EpilogPc<ControlPc+MaxEpilogLen&&FoundEpilogEnd==FALSE;) {
  1658. if(!ReadMemory(EpilogPc,4,(LPVOID)&inst)) return UNWIND_HANDLED;
  1659. EpilogPc += DecipherInstruction(inst,&di,MODE_THUMB);
  1660. if(di.InstNum==DI_MOVHI && di.Rd==15){
  1661. FoundEpilogEnd = TRUE;
  1662. EpilogEnd = EpilogPc;
  1663. EpilogStart = EpilogPc-MaxEpilogLen;
  1664. ReturnRegisterIndex = di.Rs;
  1665. } else if(di.InstNum==DI_BX_TMB){
  1666. FoundEpilogEnd = TRUE;
  1667. EpilogEnd = EpilogPc;
  1668. EpilogStart = EpilogPc-MaxEpilogLen;
  1669. ReturnRegisterIndex = di.Rd;
  1670. }
  1671. } // end of loop through instructions
  1672. }
  1673. // Either we started in an Epilog Helper, or we found a candidate for the
  1674. // end of the Epilog.
  1675. if(FoundEpilogEnd==TRUE) {
  1676. LONG EpilogOpCount;
  1677. OpList EpilogOL = {NULL,NULL};
  1678. int Mode = MODE_THUMB;
  1679. if (StartingPlace == StartingInEpilogHelper)
  1680. {
  1681. // we skipped the part above where we find the return address register, so
  1682. // find it here. The return for an epilogue helper is an ARM instruction.
  1683. if(ReadMemory(EpilogEnd-4,4, (LPVOID)&inst) &&
  1684. (DecipherInstruction(inst, &di, MODE_ARM) == 4) &&
  1685. di.InstNum == DI_BX_ARM)
  1686. {
  1687. // The epilogue doesn't always return via LR
  1688. ReturnRegisterIndex = di.Rd;
  1689. }
  1690. else
  1691. {
  1692. // Unexpected helper; terminate the walk
  1693. Register[ReturnRegisterIndex] = 0x4;
  1694. goto ThumbUnwindExit;
  1695. }
  1696. // If we're inside the epilog helper we can imply that we're unwinding the top
  1697. // frame where it is valid to use the T-bit to determine the mode from which
  1698. // we should start to disassemble
  1699. if (!(Context->Psr & 0x20))
  1700. {
  1701. Mode = MODE_ARM;
  1702. }
  1703. }
  1704. // If we are in the epilog, then we've found the end. Let's build the ops for the
  1705. // epilog, so that we can compare it to the prolog.
  1706. BuildOps(ControlPc,EpilogEnd-ControlPc,Register,Mode,&EpilogOL,&EpilogOpCount);
  1707. // Extract total stack size from ops, and fill the stack cache.
  1708. for(pOE=EpilogOL.tail;pOE;pOE=pOE->prev) {
  1709. StackSize += pOE->SpAdj;
  1710. }
  1711. // Forward execute the rest of the epilog
  1712. for(pOE=EpilogOL.head;pOE;pOE=pOE->next) {
  1713. switch(pOE->Operation) {
  1714. case MovOp:
  1715. Register[pOE->Rd] = Register[pOE->Rs];
  1716. break;
  1717. case AdjSpOp:
  1718. Register[13] += pOE->SpAdj;
  1719. break;
  1720. case PushOp:
  1721. LoadWordIntoRegister(Register[13],&Register[pOE->RegNumber]);
  1722. Register[13] += pOE->SpAdj;
  1723. break;
  1724. }
  1725. }
  1726. FreeOpList(&EpilogOL);
  1727. goto ThumbUnwindExit;
  1728. }
  1729. }
  1730. // If we've started inside the function body, move the PC to the end of the prolog.
  1731. if(ControlPc > PrologEnd) ControlPc = PrologEnd;
  1732. // We're in the prolog. Because of the use of prolog helpers,
  1733. // we cannot merely execute backwards. We need to step forward
  1734. // through the prolog, accumulating information about what has been
  1735. // done, and then undo that.
  1736. BuildOps(PrologStart,ControlPc-PrologStart,Register,MODE_THUMB,&PrologOL,&PrologOpCount);
  1737. // Extract total stack size from ops, and fill the stack cache.
  1738. FramePointer = Register[13];
  1739. for(pOE=PrologOL.head;pOE;pOE=pOE->next) {
  1740. StackSize += pOE->SpAdj;
  1741. if(pOE->Operation==MovOp && pOE->Rs==13)
  1742. FramePointer = Register[pOE->Rd];
  1743. }
  1744. // At this point, we've got an exact description of the prolog's action.
  1745. // Let's undo it.
  1746. for(pOE = PrologOL.tail; pOE; pOE=pOE->prev) {
  1747. switch(pOE->Operation) {
  1748. case MovOp:
  1749. Register[pOE->Rs] = Register[pOE->Rd];
  1750. break;
  1751. case AdjSpOp:
  1752. Register[13] += pOE->SpAdj;
  1753. break;
  1754. case PushOp:
  1755. LoadWordIntoRegister(Register[13],&Register[pOE->RegNumber]);
  1756. Register[13] += pOE->SpAdj;
  1757. break;
  1758. }
  1759. }
  1760. FreeOpList(&PrologOL);
  1761. ThumbUnwindExit:
  1762. // Now, whatever's left in Register[14] is our return address:
  1763. // To continue unwinding, put the Link Register into
  1764. // the Program Counter slot and carry on; stopping
  1765. // when the PC says 0x0. However, the catch is that
  1766. // for THUMB the Link Register at the bottom of the
  1767. // stack says 0x4, not 0x0 as we expect.
  1768. // So, do a little dance to take an LR of 0x4
  1769. // and turn it into a PC of 0x0 to stop the unwind.
  1770. // -- stevea 2/23/00.
  1771. if( Register[ReturnRegisterIndex] != 0x4 )
  1772. Register[15] = Register[ReturnRegisterIndex];
  1773. else
  1774. Register[15] = 0x0;
  1775. *ReturnAddress = Register[15];
  1776. return UNWIND_HANDLED;
  1777. }
  1778. static int
  1779. PrologMatchesCandidateEpilog
  1780. (
  1781. OpList* PrologOL,
  1782. OpList* EpilogOL,
  1783. int ReturnRegister,
  1784. PULONG EpilogStart
  1785. )
  1786. {
  1787. int Matches = DOES_MATCH;
  1788. OpEntry* pPOE=(OpEntry*)MemAlloc(sizeof(OpEntry));
  1789. OpEntry* pEOE=(OpEntry*)MemAlloc(sizeof(OpEntry));
  1790. // We aren't allowed to damage the OpLists we get, so copy
  1791. // the entries like this.
  1792. if(PrologOL->head) memcpy(pPOE,PrologOL->head,sizeof(OpEntry));
  1793. else { MemFree(pPOE); pPOE = NULL; }
  1794. if(EpilogOL->tail) memcpy(pEOE,EpilogOL->tail,sizeof(OpEntry));
  1795. else { MemFree(pEOE); pEOE = NULL; }
  1796. while(pPOE && Matches == TRUE) {
  1797. if(pEOE==NULL) return NEED_MORE_EPILOG;
  1798. // Keep track of the actual start of the epilog.
  1799. *EpilogStart = pEOE->Address;
  1800. switch(pPOE->Operation) {
  1801. case PushOp:
  1802. switch (pPOE->RegNumber) {
  1803. case 0:case 1:case 2:case 3:
  1804. // the epilog will just adjsp to pop these registers.
  1805. if(pEOE->Operation!=AdjSpOp) Matches = DOESNT_MATCH;
  1806. if(pEOE->SpAdj<4) Matches = DOESNT_MATCH;
  1807. pEOE->SpAdj-=4; pPOE->SpAdj-=4;
  1808. break;
  1809. case 4:case 5:case 6:case 7:case 8:case 9:case 10:case 11:
  1810. // The epilog must pop these saved regs back into their original location.
  1811. if(pEOE->Operation!=PushOp) Matches = DOESNT_MATCH;
  1812. if(pEOE->RegNumber!=pPOE->RegNumber) Matches = DOESNT_MATCH;
  1813. pEOE->SpAdj-=4; pPOE->SpAdj-=4;
  1814. break;
  1815. case 14:
  1816. // The epilog must pop the saved LR into the register it will use to
  1817. // return. We found the index of this register when we searched for the
  1818. // end of the epilog...
  1819. if(pEOE->Operation!=PushOp) Matches = DOESNT_MATCH;
  1820. if(pEOE->RegNumber!=ReturnRegister) Matches = DOESNT_MATCH;
  1821. pEOE->SpAdj-=4; pPOE->SpAdj-=4;
  1822. break;
  1823. }
  1824. break;
  1825. case AdjSpOp:
  1826. if(pEOE->Operation!=AdjSpOp) Matches = DOESNT_MATCH;
  1827. // The addspspi's and subspspi's could be mixed in with
  1828. // pop's and push's, so just do it this way.
  1829. if(pEOE->SpAdj >= pPOE->SpAdj) {
  1830. pEOE->SpAdj -= pPOE->SpAdj;
  1831. pPOE->SpAdj = 0;
  1832. } else {
  1833. pPOE->SpAdj -= pEOE->SpAdj;
  1834. pEOE->SpAdj = 0;
  1835. }
  1836. break;
  1837. case MovOp:
  1838. if(pEOE->Operation!=MovOp) Matches = DOESNT_MATCH;
  1839. if(pEOE->Rs != pPOE->Rd) Matches = DOESNT_MATCH;
  1840. if(pEOE->Rd != pPOE->Rs) Matches = DOESNT_MATCH;
  1841. break;
  1842. }
  1843. // If we're comparing a bunch of pushes to addspspi, then only
  1844. // move on to the previous epilog instruction when we've pushed
  1845. // enough registers to account for the addspspi.
  1846. if(pEOE->SpAdj<=0) {
  1847. if(pEOE->prev) memcpy(pEOE,pEOE->prev,sizeof(OpEntry));
  1848. else { MemFree(pEOE); pEOE = NULL; }
  1849. }
  1850. if(pPOE->SpAdj<=0) {
  1851. if(pPOE->next) memcpy(pPOE,pPOE->next,sizeof(OpEntry));
  1852. else { MemFree(pPOE); pPOE = NULL; }
  1853. }
  1854. }
  1855. if(!Matches) *EpilogStart = 0L;
  1856. if(pEOE) MemFree(pEOE);
  1857. if(pPOE) MemFree(pPOE);
  1858. return Matches;
  1859. }