Index: src/eh-frame.h |
diff --git a/src/eh-frame.h b/src/eh-frame.h |
index 75781acb502ee8f420e93b240e7515e6e9f7348d..201469c9acd5760a1045840fd09e4388ad864240 100644 |
--- a/src/eh-frame.h |
+++ b/src/eh-frame.h |
@@ -5,19 +5,122 @@ |
#ifndef V8_EH_FRAME_H_ |
#define V8_EH_FRAME_H_ |
-#include <cstdint> |
+#include "src/list.h" |
+#include "src/macro-assembler.h" |
namespace v8 { |
namespace internal { |
-class Code; |
+struct CodeDesc; |
+ |
+class EhFrameWriter { |
+ public: |
+ static const int kCIESize; |
+ |
+ EhFrameWriter(); |
+ |
+ void AdvanceLocation(int pc_offset); |
+ |
+ // <base address> = <base register> + <base offset> |
rmcilroy
2016/06/30 15:23:11
What is the base address? Please explain how it re
Stefano Sanfilippo
2016/07/04 18:21:15
Done.
|
+ void DefineBaseAddressRegister(Register base_register); |
+ void DefineBaseAddressOffset(int base_offset); |
+ void IncreaseBaseAddressOffset(int base_delta) { |
+ DefineBaseAddressOffset(base_offset_ + base_delta); |
+ } |
+ void DefineBaseAddressRegisterOffset(Register base_register, int base_offset); |
rmcilroy
2016/06/30 15:23:11
DefineBaseAddressRegisterAndOffset
Stefano Sanfilippo
2016/07/04 18:21:14
Done.
|
+ |
+ // Offset relative to <base address> |
+ void SaveRegisterToStack(Register name, int offset); |
+ void SaveRegisterToStack(Register name) { |
+ SaveRegisterToStack(name, base_offset_); |
+ } |
+ void RegisterIsValid(Register name); |
+ |
+ void Finish(int code_size); |
+ |
+ // Remember to call Finish() before GetEhFrame()! |
rmcilroy
2016/06/30 15:23:11
Make it clear that the EhWriter must outlive the C
Stefano Sanfilippo
2016/07/04 18:21:14
Done.
|
+ void GetEhFrame(CodeDesc* desc); |
+ |
+ int last_pc_offset() const { return last_pc_offset_; } |
+ Register base_register() const { return base_register_; } |
+ int base_offset() const { return base_offset_; } |
+ |
+#ifdef ENABLE_DISASSEMBLER |
+ static void DisassembleToStream(std::ostream& stream, // NOLINT |
+ const byte* start, const byte* end); |
+#endif |
+ |
+ protected: |
+ void WriteByte(byte value) { eh_frame_buffer_.Add(value); } |
+ |
+ void WriteBytes(const byte* value, int size) { |
+ eh_frame_buffer_.AddAll(Vector<byte>(const_cast<byte*>(value), size)); |
+ } |
+ |
+ void WriteInt16(uint16_t value) { |
+ eh_frame_buffer_.AddAll( |
+ Vector<byte>(reinterpret_cast<byte*>(&value), sizeof(value))); |
+ } |
+ |
+ void WriteInt32(uint32_t value) { |
+ eh_frame_buffer_.AddAll( |
+ Vector<byte>(reinterpret_cast<byte*>(&value), sizeof(value))); |
+ } |
+ |
+ void WriteULEB128(uint32_t value); |
+ |
+ void PatchInt32(int base_offset, uint32_t value) { |
+ DCHECK_EQ(ReadUnalignedUInt32(eh_frame_buffer_.begin() + base_offset), |
+ kInt32Placeholder); |
+ MemCopy(eh_frame_buffer_.begin() + base_offset, &value, sizeof(value)); |
+ } |
+ |
+ void WriteFDEHeader(); |
+ |
+ int eh_frame_offset() const { return eh_frame_buffer_.length(); } |
+ |
+ private: |
+ static const byte kNop = 0x00; |
+ static const byte kAdvanceLoc1 = 0x02; |
+ static const byte kAdvanceLoc2 = 0x03; |
+ static const byte kAdvanceLoc4 = 0x04; |
+ static const byte kSameValue = 0x08; |
+ static const byte kDefCFA = 0x0c; |
+ static const byte kDefCFARegister = 0x0d; |
+ static const byte kDefCFAOffset = 0x0e; |
rmcilroy
2016/06/30 15:23:11
This could be enums (enum class DwarfOpcode: byte)
Stefano Sanfilippo
2016/07/04 18:21:15
Done.
|
+ static const uint32_t kInt32Placeholder = 0xdeadc0de; |
rmcilroy
2016/06/30 15:23:11
newlines between groups
Stefano Sanfilippo
2016/07/04 18:21:14
Done.
|
+ static const int kEhFrameTerminatorSize = 4; |
+ static const int kLocationTag = 1; |
+ static const int kSavedRegisterTag = 2; |
rmcilroy
2016/06/30 15:23:11
this should be 1 << 1 to make it clear its a bit f
Stefano Sanfilippo
2016/07/04 18:21:15
It's not a bit field, the 2 MSBs are used as opcod
|
+ static const int kLocationMask = 0x3f; |
+ static const int kLocationMaskSize = 6; |
+ static const int kSavedRegisterMask = 0x3f; |
+ static const int kSavedRegisterMaskSize = 6; |
rmcilroy
2016/06/30 15:23:11
group tags with masks
Stefano Sanfilippo
2016/07/04 18:21:14
Done.
|
+ static const int kFDEOffset; |
+ static const int kProcedureAddressOffset; |
+ static const int kProcedureSizeOffset; |
+#ifdef ENABLE_DISASSEMBLER |
+ static const int kFDEDirectivesOffset; |
+ |
+ static void DumpDWARFDirectives(std::ostream& stream, // NOLINT |
+ const byte* begin, const byte* end); |
+#endif |
+ |
+ int last_pc_offset_; |
+#if DEBUG |
+ bool eh_frame_finalised_; |
rmcilroy
2016/06/30 15:23:11
no need to make this debug only, setting a bool is
Stefano Sanfilippo
2016/07/04 18:21:14
Fine, done.
|
+#endif |
+ Register base_register_; |
+ int base_offset_; |
+ List<byte> eh_frame_buffer_; |
rmcilroy
2016/06/30 15:23:11
Why list and not vector?
Stefano Sanfilippo
2016/07/04 18:21:14
I assumed V8 APIs took priority, replaced with std
|
+}; |
class EhFrameHdr final { |
public: |
static const int kRecordSize = 20; |
- static const int kCIESize; |
- explicit EhFrameHdr(Code* code); |
+ static EhFrameHdr MakeDummy(); |
rmcilroy
2016/06/30 15:23:11
below constructor. Also, how about Empty instead o
Stefano Sanfilippo
2016/07/04 18:21:14
Moved.
*Empty* is fine for me, renamed.
|
+ EhFrameHdr(int code_size, int eh_frame_size); |
int32_t offset_to_eh_frame() const { return offset_to_eh_frame_; } |
uint32_t lut_entries_number() const { return lut_entries_number_; } |
@@ -25,6 +128,16 @@ class EhFrameHdr final { |
int32_t offset_to_fde() const { return offset_to_fde_; } |
private: |
+ static const byte kPcRel = 0x10; |
+ static const byte kDataRel = 0x30; |
+ static const byte kUData4 = 0x03; |
+ static const byte kSData4 = 0x0b; |
+ static const int kEhFrameHdrVersion = 1; |
+ static const int kFDEVersionSize = 1; |
+ static const int kFDEEncodingSpecifiersSize = 3; |
+ |
+ EhFrameHdr() {} |
+ |
uint8_t version_; |
uint8_t eh_frame_ptr_encoding_; |
uint8_t lut_size_encoding_; |