StackFrame.h 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft. All rights reserved.
  3. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  4. //-------------------------------------------------------------------------------------------------------
  5. #pragma once
  6. /*
  7. * Stackwalking on Evanesco:
  8. * ------------------------
  9. * NOTE: This structure is currently only used for _M_ARM64, which walks a chain of frame pointers.
  10. * This requires frame chaining using fp (i.e., no FPO) and the homing of register parameters on
  11. * entry to Javascript functions.
  12. *
  13. * The relevant part of the frame looks like this (high addresses at the top, low ones at the bottom):
  14. *
  15. * ----------------------
  16. * x7 <=== Homed input parameters
  17. * x6 <
  18. * x5 <
  19. * x4 <
  20. * x3 <
  21. * x2 <
  22. * x1 <
  23. * x0 <===
  24. * lr <=== return address
  25. * fp <=== current fp (frame pointer)
  26. * ...
  27. *
  28. */
  29. #if !defined(_M_ARM64)
  30. #error This is only for ARM64
  31. #endif
  32. namespace Js
  33. {
  34. class Arm64StackFrame
  35. {
  36. public:
  37. Arm64StackFrame() : frame(nullptr), codeAddr(nullptr), addressOfCodeAddr(nullptr)
  38. {
  39. }
  40. bool InitializeByFrameId(void * returnAddress, ScriptContext* scriptContext);
  41. bool InitializeByReturnAddress(void * returnAddress, ScriptContext* scriptContext);
  42. bool Next();
  43. void *GetInstructionPointer();
  44. void **GetArgv(bool isCurrentContextNative = false, bool shouldCheckForNativeAddr = true);
  45. void *GetReturnAddress(bool isCurrentContextNative = false, bool shouldCheckForNativeAddr = true);
  46. void *GetAddressOfInstructionPointer() { Assert(addressOfCodeAddr != nullptr); return addressOfCodeAddr; }
  47. void *GetAddressOfReturnAddress(bool isCurrentContextNative = false, bool shouldCheckForNativeAddr = true);
  48. bool SkipToFrame(void * returnAddress);
  49. void *GetFrame() { return (void *)frame;};
  50. size_t GetStackCheckCodeHeight() { return this->stackCheckCodeHeight; }
  51. static bool IsInStackCheckCode(void *entry, void *codeAddr, size_t stackCheckCodeHeight);
  52. private:
  53. void ** frame; // fp (frame pointer) - other interesting values are relative to this address
  54. void * codeAddr; // return address from the current frame
  55. void* addressOfCodeAddr;
  56. //ProbeStack height is 40 when stack probe is before prolog & 58 when it is after prolog (for small stacks)
  57. //Choosing the higher number is safe as @58 we are still in the prolog and inlinee frame is not setup yet and
  58. //we shouldn't try to query the frame height for the inlined function.
  59. //TODO (abchatra): Get rid of this magic number in future and design a more safe way of handling the stack check code height.
  60. static const size_t stackCheckCodeHeight = StackFrameConstants::StackCheckCodeHeight;
  61. };
  62. };