EhFrame.cpp 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  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. #include "Backend.h"
  6. #include "EhFrame.h"
  7. // AMD64 ABI -- DWARF register number mapping
  8. static const ubyte DWARF_RegNum[] =
  9. {
  10. // Exactly same order as RegList.h!
  11. -1, // NOREG,
  12. 0, // RAX,
  13. 2, // RCX,
  14. 1, // RDX,
  15. 3, // RBX,
  16. 7, // RSP,
  17. 6, // RBP,
  18. 4, // RSI,
  19. 5, // RDI,
  20. 8, // R8,
  21. 9, // R9,
  22. 10, // R10,
  23. 11, // R11,
  24. 12, // R12,
  25. 13, // R13,
  26. 14, // R14,
  27. 15, // R15,
  28. 17, // XMM0,
  29. 18, // XMM1,
  30. 19, // XMM2,
  31. 20, // XMM3,
  32. 21, // XMM4,
  33. 22, // XMM5,
  34. 23, // XMM6,
  35. 24, // XMM7,
  36. 25, // XMM8,
  37. 26, // XMM9,
  38. 27, // XMM10,
  39. 28, // XMM11,
  40. 29, // XMM12,
  41. 30, // XMM13,
  42. 31, // XMM14,
  43. 32, // XMM15,
  44. };
  45. static const ubyte DWARF_RegRA = 16;
  46. ubyte GetDwarfRegNum(ubyte regNum)
  47. {
  48. return DWARF_RegNum[regNum];
  49. }
  50. // Encode into ULEB128 (Unsigned Little Endian Base 128)
  51. BYTE* EmitLEB128(BYTE* pc, unsigned value)
  52. {
  53. do
  54. {
  55. BYTE b = value & 0x7F; // low order 7 bits
  56. value >>= 7;
  57. if (value) // more bytes to come
  58. {
  59. b |= 0x80;
  60. }
  61. *pc++ = b;
  62. }
  63. while (value != 0);
  64. return pc;
  65. }
  66. // Encode into signed LEB128 (Signed Little Endian Base 128)
  67. BYTE* EmitLEB128(BYTE* pc, int value)
  68. {
  69. static const int size = sizeof(value) * 8;
  70. static const bool isLogicShift = (-1 >> 1) != -1;
  71. const bool signExtend = isLogicShift && value < 0;
  72. bool more = true;
  73. while (more)
  74. {
  75. BYTE b = value & 0x7F; // low order 7 bits
  76. value >>= 7;
  77. if (signExtend)
  78. {
  79. value |= - (1 << (size - 7)); // sign extend
  80. }
  81. const bool signBit = (b & 0x40) != 0;
  82. if ((value == 0 && !signBit) || (value == -1 && signBit))
  83. {
  84. more = false;
  85. }
  86. else
  87. {
  88. b |= 0x80;
  89. }
  90. *pc++ = b;
  91. }
  92. return pc;
  93. }
  94. void EhFrame::Entry::Begin()
  95. {
  96. Assert(beginOffset == -1);
  97. beginOffset = writer->Count();
  98. // Write Length place holder
  99. const uword length = 0;
  100. writer->Write(length);
  101. }
  102. void EhFrame::Entry::End()
  103. {
  104. Assert(beginOffset != -1); // Must have called Begin()
  105. // padding
  106. size_t padding = (MachPtr - writer->Count() % MachPtr) % MachPtr;
  107. for (size_t i = 0; i < padding; i++)
  108. {
  109. cfi_nop();
  110. }
  111. // update length record
  112. uword length = writer->Count() - beginOffset
  113. - sizeof(length); // exclude length itself
  114. writer->Write(beginOffset, length);
  115. }
  116. void EhFrame::Entry::cfi_advance(uword advance)
  117. {
  118. if (advance <= 0x3F) // 6-bits
  119. {
  120. cfi_advance_loc(static_cast<ubyte>(advance));
  121. }
  122. else if (advance <= 0xFF) // 1-byte
  123. {
  124. cfi_advance_loc1(static_cast<ubyte>(advance));
  125. }
  126. else if (advance <= 0xFFFF) // 2-byte
  127. {
  128. cfi_advance_loc2(static_cast<uword>(advance));
  129. }
  130. else // 4-byte
  131. {
  132. cfi_advance_loc4(advance);
  133. }
  134. }
  135. void EhFrame::CIE::Begin()
  136. {
  137. Assert(writer->Count() == 0);
  138. Entry::Begin();
  139. const uword cie_id = 0;
  140. Emit(cie_id);
  141. const ubyte version = 1;
  142. Emit(version);
  143. const ubyte augmentationString = 0; // none
  144. Emit(augmentationString);
  145. const ULEB128 codeAlignmentFactor = 1;
  146. Emit(codeAlignmentFactor);
  147. const LEB128 dataAlignmentFactor = - MachPtr;
  148. Emit(dataAlignmentFactor);
  149. const ubyte returnAddressRegister = DWARF_RegRA;
  150. Emit(returnAddressRegister);
  151. }
  152. void EhFrame::FDE::Begin()
  153. {
  154. Entry::Begin();
  155. const uword cie_id = writer->Count();
  156. Emit(cie_id);
  157. // Write pc <begin, range> placeholder
  158. pcBeginOffset = writer->Count();
  159. const void* pc = nullptr;
  160. Emit(pc);
  161. Emit(pc);
  162. }
  163. void EhFrame::FDE::UpdateAddressRange(const void* pcBegin, size_t pcRange)
  164. {
  165. writer->Write(pcBeginOffset, pcBegin);
  166. writer->Write(pcBeginOffset + sizeof(pcBegin),
  167. reinterpret_cast<const void*>(pcRange));
  168. }
  169. EhFrame::EhFrame(BYTE* buffer, size_t size)
  170. : writer(buffer, size), fde(&writer)
  171. {
  172. CIE cie(&writer);
  173. cie.Begin();
  174. // CIE initial instructions
  175. // DW_CFA_def_cfa: r7 (rsp) ofs 8
  176. cie.cfi_def_cfa(DWARF_RegNum[LowererMDArch::GetRegStackPointer()], MachPtr);
  177. // DW_CFA_offset: r16 (rip) at cfa-8 (data alignment -8)
  178. cie.cfi_offset(DWARF_RegRA, 1);
  179. cie.End();
  180. fde.Begin();
  181. }
  182. void EhFrame::End()
  183. {
  184. fde.End();
  185. // Write length 0 to mark terminate entry
  186. const uword terminate_entry_length = 0;
  187. writer.Write(terminate_entry_length);
  188. }