| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206 |
- //-------------------------------------------------------------------------------------------------------
- // Copyright (C) Microsoft. All rights reserved.
- // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
- //-------------------------------------------------------------------------------------------------------
- #pragma once
- typedef BYTE ubyte;
- typedef uint16 uhalf;
- typedef uint32 uword;
- CompileAssert(sizeof(ubyte) == 1);
- CompileAssert(sizeof(uhalf) == 2);
- CompileAssert(sizeof(uword) == 4);
- BYTE* EmitLEB128(BYTE* pc, unsigned value);
- BYTE* EmitLEB128(BYTE* pc, int value);
- ubyte GetDwarfRegNum(ubyte regNum);
- template <class T>
- class LEB128Wrapper
- {
- private:
- T value;
- public:
- LEB128Wrapper(T value): value(value)
- {}
- BYTE* Write(BYTE* pc) const
- {
- return EmitLEB128(pc, value);
- }
- };
- typedef LEB128Wrapper<unsigned> ULEB128;
- typedef LEB128Wrapper<int> LEB128;
- //
- // EhFrame emits .eh_frame unwind data for our JIT code. We emit only one CIE
- // followed by one FDE for each JIT function.
- //
- class EhFrame
- {
- // Simple buffer writer. Must operate on a buffer of sufficient size.
- class Writer
- {
- private:
- BYTE* buffer; // original buffer head
- BYTE* cur; // current output position
- const size_t size; // original size of buffer, for debug only
- public:
- Writer(BYTE* buffer, size_t size) : buffer(buffer), cur(buffer), size(size)
- {}
- // Write a value, and advance cur position
- template <class T>
- void Write(T value)
- {
- *reinterpret_cast<T*>(cur) = value;
- cur += sizeof(value);
- Assert(Count() <= size);
- }
- // Write a ULEB128 or LEB128 value, and advance cur position
- template <class T>
- void Write(const LEB128Wrapper<T>& leb128)
- {
- cur = leb128.Write(cur);
- Assert(Count() <= size);
- }
- // Write a value at an absolute position
- template <class T>
- void Write(size_t offset, T value)
- {
- Assert(offset + sizeof(value) <= size);
- *reinterpret_cast<T*>(buffer + offset) = value;
- }
- // Get original buffer head
- BYTE* Buffer() const
- {
- return buffer;
- }
- // Get count of written bytes (== offset of cur position)
- size_t Count() const
- {
- return cur - buffer;
- }
- };
- // Base class for CIE and FDE
- class Entry
- {
- protected:
- Writer* writer;
- size_t beginOffset; // where we'll update "length" record
- // To limit supported value types
- void Emit(ubyte value) { writer->Write(value); }
- void Emit(uhalf value) { writer->Write(value); }
- void Emit(uword value) { writer->Write(value); }
- void Emit(const void* absptr) { writer->Write(absptr); }
- void Emit(LEB128 value) { writer->Write(value); }
- void Emit(ULEB128 value) { writer->Write(value); }
- template <class T1>
- void Emit(ubyte op, T1 arg1)
- {
- Emit(op);
- Emit(arg1);
- }
- template <class T1, class T2>
- void Emit(ubyte op, T1 arg1, T2 arg2)
- {
- Emit(op, arg1);
- Emit(arg2);
- }
- public:
- Entry(Writer* writer) : writer(writer), beginOffset(-1)
- {}
- void Begin();
- void End();
- #define ENTRY(name, op) \
- void cfi_##name() \
- { Emit(static_cast<ubyte>(op)); }
- #define ENTRY1(name, op, arg1_type) \
- void cfi_##name(arg1_type arg1) \
- { Emit(op, arg1); }
- #define ENTRY2(name, op, arg1_type, arg2_type) \
- void cfi_##name(arg1_type arg1, arg2_type arg2) \
- { Emit(op, arg1, arg2); }
- #define ENTRY_SM1(name, op, arg1_type) \
- void cfi_##name(arg1_type arg1) \
- { Assert((arg1) <= 0x3F); Emit(static_cast<ubyte>((op) | arg1)); }
- #define ENTRY_SM2(name, op, arg1_type, arg2_type) \
- void cfi_##name(arg1_type arg1, arg2_type arg2) \
- { Assert((arg1) <= 0x3F); Emit((op) | arg1, arg2); }
- #include "EhFrameCFI.inc"
- void cfi_advance(uword advance);
- };
- // Common Information Entry
- class CIE : public Entry
- {
- public:
- CIE(Writer* writer) : Entry(writer)
- {}
- void Begin();
- };
- // Frame Description Entry
- class FDE: public Entry
- {
- private:
- size_t pcBeginOffset;
- public:
- FDE(Writer* writer) : Entry(writer)
- {}
- void Begin();
- void UpdateAddressRange(const void* pcBegin, size_t pcRange);
- };
- private:
- Writer writer;
- FDE fde;
- public:
- EhFrame(BYTE* buffer, size_t size);
- Writer* GetWriter()
- {
- return &writer;
- }
- FDE* GetFDE()
- {
- return &fde;
- }
- void End();
- BYTE* Buffer() const
- {
- return writer.Buffer();
- }
- size_t Count() const
- {
- return writer.Count();
- }
- };
|