| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228 |
- //-------------------------------------------------------------------------------------------------------
- // Copyright (C) Microsoft. All rights reserved.
- // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
- //-------------------------------------------------------------------------------------------------------
- #include "Backend.h"
- #include "EhFrame.h"
- // AMD64 ABI -- DWARF register number mapping
- static const ubyte DWARF_RegNum[] =
- {
- // Exactly same order as RegList.h!
- -1, // NOREG,
- 0, // RAX,
- 2, // RCX,
- 1, // RDX,
- 3, // RBX,
- 7, // RSP,
- 6, // RBP,
- 4, // RSI,
- 5, // RDI,
- 8, // R8,
- 9, // R9,
- 10, // R10,
- 11, // R11,
- 12, // R12,
- 13, // R13,
- 14, // R14,
- 15, // R15,
- 17, // XMM0,
- 18, // XMM1,
- 19, // XMM2,
- 20, // XMM3,
- 21, // XMM4,
- 22, // XMM5,
- 23, // XMM6,
- 24, // XMM7,
- 25, // XMM8,
- 26, // XMM9,
- 27, // XMM10,
- 28, // XMM11,
- 29, // XMM12,
- 30, // XMM13,
- 31, // XMM14,
- 32, // XMM15,
- };
- static const ubyte DWARF_RegRA = 16;
- ubyte GetDwarfRegNum(ubyte regNum)
- {
- return DWARF_RegNum[regNum];
- }
- // Encode into ULEB128 (Unsigned Little Endian Base 128)
- BYTE* EmitLEB128(BYTE* pc, unsigned value)
- {
- do
- {
- BYTE b = value & 0x7F; // low order 7 bits
- value >>= 7;
- if (value) // more bytes to come
- {
- b |= 0x80;
- }
- *pc++ = b;
- }
- while (value != 0);
- return pc;
- }
- // Encode into signed LEB128 (Signed Little Endian Base 128)
- BYTE* EmitLEB128(BYTE* pc, int value)
- {
- static const int size = sizeof(value) * 8;
- static const bool isLogicShift = (-1 >> 1) != -1;
- const bool signExtend = isLogicShift && value < 0;
- bool more = true;
- while (more)
- {
- BYTE b = value & 0x7F; // low order 7 bits
- value >>= 7;
- if (signExtend)
- {
- value |= - (1 << (size - 7)); // sign extend
- }
- const bool signBit = (b & 0x40) != 0;
- if ((value == 0 && !signBit) || (value == -1 && signBit))
- {
- more = false;
- }
- else
- {
- b |= 0x80;
- }
- *pc++ = b;
- }
- return pc;
- }
- void EhFrame::Entry::Begin()
- {
- Assert(beginOffset == -1);
- beginOffset = writer->Count();
- // Write Length place holder
- const uword length = 0;
- writer->Write(length);
- }
- void EhFrame::Entry::End()
- {
- Assert(beginOffset != -1); // Must have called Begin()
- // padding
- size_t padding = (MachPtr - writer->Count() % MachPtr) % MachPtr;
- for (size_t i = 0; i < padding; i++)
- {
- cfi_nop();
- }
- // update length record
- uword length = writer->Count() - beginOffset
- - sizeof(length); // exclude length itself
- writer->Write(beginOffset, length);
- }
- void EhFrame::Entry::cfi_advance(uword advance)
- {
- if (advance <= 0x3F) // 6-bits
- {
- cfi_advance_loc(static_cast<ubyte>(advance));
- }
- else if (advance <= 0xFF) // 1-byte
- {
- cfi_advance_loc1(static_cast<ubyte>(advance));
- }
- else if (advance <= 0xFFFF) // 2-byte
- {
- cfi_advance_loc2(static_cast<uword>(advance));
- }
- else // 4-byte
- {
- cfi_advance_loc4(advance);
- }
- }
- void EhFrame::CIE::Begin()
- {
- Assert(writer->Count() == 0);
- Entry::Begin();
- const uword cie_id = 0;
- Emit(cie_id);
- const ubyte version = 1;
- Emit(version);
- const ubyte augmentationString = 0; // none
- Emit(augmentationString);
- const ULEB128 codeAlignmentFactor = 1;
- Emit(codeAlignmentFactor);
- const LEB128 dataAlignmentFactor = - MachPtr;
- Emit(dataAlignmentFactor);
- const ubyte returnAddressRegister = DWARF_RegRA;
- Emit(returnAddressRegister);
- }
- void EhFrame::FDE::Begin()
- {
- Entry::Begin();
- const uword cie_id = writer->Count();
- Emit(cie_id);
- // Write pc <begin, range> placeholder
- pcBeginOffset = writer->Count();
- const void* pc = nullptr;
- Emit(pc);
- Emit(pc);
- }
- void EhFrame::FDE::UpdateAddressRange(const void* pcBegin, size_t pcRange)
- {
- writer->Write(pcBeginOffset, pcBegin);
- writer->Write(pcBeginOffset + sizeof(pcBegin),
- reinterpret_cast<const void*>(pcRange));
- }
- EhFrame::EhFrame(BYTE* buffer, size_t size)
- : writer(buffer, size), fde(&writer)
- {
- CIE cie(&writer);
- cie.Begin();
- // CIE initial instructions
- // DW_CFA_def_cfa: r7 (rsp) ofs 8
- cie.cfi_def_cfa(DWARF_RegNum[LowererMDArch::GetRegStackPointer()], MachPtr);
- // DW_CFA_offset: r16 (rip) at cfa-8 (data alignment -8)
- cie.cfi_offset(DWARF_RegRA, 1);
- cie.End();
- fde.Begin();
- }
- void EhFrame::End()
- {
- fde.End();
- // Write length 0 to mark terminate entry
- const uword terminate_entry_length = 0;
- writer.Write(terminate_entry_length);
- }
|