Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(187)

Side by Side Diff: src/eh-frame.h

Issue 2023503002: Reland Implement .eh_frame writer and disassembler. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@eh-frame-base
Patch Set: Refactor tests, small fixes, improved EhFrameIterator iface. Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2016 the V8 project authors. All rights reserved. 1 // Copyright 2016 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #ifndef V8_EH_FRAME_H_ 5 #ifndef V8_EH_FRAME_H_
6 #define V8_EH_FRAME_H_ 6 #define V8_EH_FRAME_H_
7 7
8 #include <cstdint> 8 #include "src/macro-assembler.h"
9 9
10 namespace v8 { 10 namespace v8 {
11 namespace internal { 11 namespace internal {
12 12
13 class Code; 13 class EhFrameWriter {
14 public:
15 enum class DwarfOpcodes : byte {
16 kNop = 0x00,
17 kAdvanceLoc1 = 0x02,
18 kAdvanceLoc2 = 0x03,
19 kAdvanceLoc4 = 0x04,
20 kSameValue = 0x08,
21 kDefCfa = 0x0c,
22 kDefCfaRegister = 0x0d,
23 kDefCfaOffset = 0x0e,
24 kOffsetExtendedSf = 0x11,
25 };
26
27 enum DwarfEncodingSpecifiers : byte {
28 kUData4 = 0x03,
29 kSData4 = 0x0b,
30 kPcRel = 0x10,
31 kDataRel = 0x30,
32 kOmit = 0xff,
33 };
34
35 static const int kLocationTag = 1;
36 static const int kLocationMask = 0x3f;
37 static const int kLocationMaskSize = 6;
38
39 static const int kSavedRegisterTag = 2;
40 static const int kSavedRegisterMask = 0x3f;
41 static const int kSavedRegisterMaskSize = 6;
42
43 static const int kFollowInitialRuleTag = 3;
44 static const int kFollowInitialRuleMask = 0x3f;
45 static const int kFollowInitialRuleMaskSize = 6;
46
47 static const int kProcedureAddressOffsetInFde = 2 * kInt32Size;
48 static const int kProcedureSizeOffsetInFde = 3 * kInt32Size;
49
50 static const int kInitialStateOffsetInCIE = 19;
51 static const int kEhFrameTerminatorSize = 4;
52
53 static const int kDataAlignmentFactor;
54
55 EhFrameWriter();
56
57 void AdvanceLocation(int pc_offset);
58
59 // The <base_address> is the one to which all <offset>s in SaveRegisterToStack
60 // directives are relative. It is given by <base_register> + <base_offset>.
61 void SetBaseAddressRegister(Register base_register);
62 void SetBaseAddressOffset(int base_offset);
63 void IncreaseBaseAddressOffset(int base_delta) {
64 SetBaseAddressOffset(base_offset_ + base_delta);
65 }
66 void SetBaseAddressRegisterAndOffset(Register base_register, int base_offset);
67
68 // Offset relative to <base address>, positive offsets go in the direction
69 // of stack growth (downwards on all architectures we support).
70 void RecordRegisterSavedToStack(Register name, int offset) {
71 RecordRegisterSavedToStack(RegisterToDwarfCode(name), offset);
72 }
73
74 void RecordRegisterSavedToStack(Register name) {
75 RecordRegisterSavedToStack(name, base_offset_);
76 }
77
78 void RecordRegisterIsValid(Register name);
79
80 void RecordRegisterFollowsInitialRule(Register name);
81
82 void Finish(int code_size);
83
84 // Remember to call Finish() before GetEhFrame().
85 //
86 // The EhFrameWriter instance owns the buffer pointed by
87 // CodeDesc::unwinding_info, and must outlive any use of the CodeDesc.
88 void GetEhFrame(CodeDesc* desc);
89
90 int last_pc_offset() const { return last_pc_offset_; }
91 Register base_register() const { return base_register_; }
92 int base_offset() const { return base_offset_; }
93
94 private:
95 static const uint32_t kInt32Placeholder = 0xdeadc0de;
96
97 static int RegisterToDwarfCode(Register name);
98
99 void WriteSLEB128(int32_t value);
100 void WriteULEB128(uint32_t value);
101
102 void WriteByte(byte value) { eh_frame_buffer_.push_back(value); }
103 void WriteOpcode(DwarfOpcodes opcode) {
104 WriteByte(static_cast<byte>(opcode));
105 }
106 void WriteBytes(const byte* start, int size) {
107 eh_frame_buffer_.insert(eh_frame_buffer_.end(), start, start + size);
108 }
109 void WriteInt16(uint16_t value) {
110 WriteBytes(reinterpret_cast<const byte*>(&value), sizeof(value));
111 }
112 void WriteInt32(uint32_t value) {
113 WriteBytes(reinterpret_cast<const byte*>(&value), sizeof(value));
114 }
115 void PatchInt32(int base_offset, uint32_t value) {
116 DCHECK_EQ(ReadUnalignedUInt32(eh_frame_buffer_.data() + base_offset),
117 kInt32Placeholder);
118 DCHECK_LT(base_offset + kInt32Size, eh_frame_offset());
119 WriteUnalignedUInt32(eh_frame_buffer_.data() + base_offset, value);
120 }
121
122 void WriteCIE();
Stefano Sanfilippo 2016/07/05 19:53:56 I am not sure how to describe these methods in a c
rmcilroy 2016/07/06 13:59:30 "Write the Common Information Entry header" is fin
Stefano Sanfilippo 2016/07/06 16:54:50 Comments added.
123 void WriteReturnAddressRegisterCode();
124 void WriteInitialStateInCIE();
125 void WriteFDEHeader();
126 void WritePaddingTo8ByteAlignment();
127
128 // Internal version that directly accepts a DWARF register code, needed for
129 // handling pseudoregisters on some platforms, such as x64.
130 void RecordRegisterSavedToStack(int register_code, int offset);
131
132 int eh_frame_offset() const {
133 return static_cast<int>(eh_frame_buffer_.size());
134 }
135
136 int fde_offset() const { return cie_size_; }
137
138 int procedure_address_offset() const {
139 return fde_offset() + kProcedureAddressOffsetInFde;
140 }
141
142 int procedure_size_offset() const {
143 return fde_offset() + kProcedureSizeOffsetInFde;
144 }
145
146 int cie_size_;
147 int last_pc_offset_;
148 bool eh_frame_finalised_;
149 Register base_register_;
150 int base_offset_;
151 std::vector<byte> eh_frame_buffer_;
152 };
153
154 class EhFrameIterator {
155 public:
156 explicit EhFrameIterator(EhFrameWriter* writer);
157
158 EhFrameIterator(const byte* start, const byte* end)
159 : start_(start), next_(start), end_(end) {
160 DCHECK_LE(start, end);
161 }
162
163 void SkipCIE() {
164 DCHECK_EQ(next_, start_);
165 next_ += ReadUnalignedUInt32(next_) + kInt32Size;
166 }
167
168 void SkipToFDEDirectives() {
169 SkipCIE();
170 // Skip the FDE header.
171 Skip(4 * kInt32Size + 1);
172 }
173
174 void Skip(int how_many) {
175 next_ += how_many;
176 DCHECK_LE(next_, end_);
177 }
178
179 uint32_t GetNextUInt32() { return GetNextIntegral<uint32_t>(); }
180 uint16_t GetNextUInt16() { return GetNextIntegral<uint16_t>(); }
181 byte GetNextByte() { return GetNextIntegral<byte>(); }
182 EhFrameWriter::DwarfOpcodes GetNextOpcode() {
183 return static_cast<EhFrameWriter::DwarfOpcodes>(GetNextByte());
184 }
185
186 uint32_t GetNextULEB128();
187 int32_t GetNextSLEB128();
188
189 bool ReachedEnd() const {
190 DCHECK_LE(next_, end_);
191 return next_ == end_;
192 }
193
194 const void* current_address() const {
195 return reinterpret_cast<const void*>(next_);
196 }
197 int GetCurrentOffset() const {
198 DCHECK_GE(next_, start_);
199 return static_cast<int>(next_ - start_);
200 }
201 int GetBufferSize() { return static_cast<int>(end_ - start_); }
202
203 private:
204 static uint32_t DecodeULEB128(const byte* encoded, int* encoded_size);
205 static int32_t DecodeSLEB128(const byte* encoded, int* encoded_size);
206
207 template <typename T>
208 T GetNextIntegral() {
209 T result;
210 DCHECK_LE(next_ + sizeof(result), end_);
211 result = ReadUnalignedValue<T>(next_);
212 next_ += sizeof(result);
213 return result;
214 }
215
216 const byte* start_;
217 const byte* next_;
218 const byte* end_;
219
220 friend class EhFrameIteratorTest;
221 };
222
223 #ifdef ENABLE_DISASSEMBLER
224
225 class EhFrameDisassembler final {
226 public:
227 EhFrameDisassembler(const byte* start, const byte* end)
228 : start_(start), end_(end) {
229 DCHECK_LE(start, end);
230 }
231
232 void DisassembleToStream(std::ostream& stream); // NOLINT
233
234 private:
235 static void DumpDWARFDirectives(std::ostream& stream, // NOLINT
236 const byte* start, const byte* end);
237
238 static const char* DwarfRegisterCodeToString(int code);
239
240 const byte* start_;
241 const byte* end_;
242 };
243
244 #endif
14 245
15 class EhFrameHdr final { 246 class EhFrameHdr final {
16 public: 247 public:
17 static const int kRecordSize = 20; 248 static const int kRecordSize = 20;
18 static const int kCIESize; 249
19 250 EhFrameHdr(int code_size, int eh_frame_size, int cie_size);
20 explicit EhFrameHdr(Code* code); 251 static EhFrameHdr CreateEmptyHeader();
21 252
22 int32_t offset_to_eh_frame() const { return offset_to_eh_frame_; } 253 int32_t offset_to_eh_frame() const { return offset_to_eh_frame_; }
23 uint32_t lut_entries_number() const { return lut_entries_number_; } 254 uint32_t lut_entries_number() const { return lut_entries_number_; }
24 int32_t offset_to_procedure() const { return offset_to_procedure_; } 255 int32_t offset_to_procedure() const { return offset_to_procedure_; }
25 int32_t offset_to_fde() const { return offset_to_fde_; } 256 int32_t offset_to_fde() const { return offset_to_fde_; }
26 257
27 private: 258 private:
259 static const int kEhFrameHdrVersion = 1;
260
261 EhFrameHdr() {}
262
28 uint8_t version_; 263 uint8_t version_;
29 uint8_t eh_frame_ptr_encoding_; 264 uint8_t eh_frame_ptr_encoding_;
30 uint8_t lut_size_encoding_; 265 uint8_t lut_size_encoding_;
31 uint8_t lut_entries_encoding_; 266 uint8_t lut_entries_encoding_;
32 int32_t offset_to_eh_frame_; 267 int32_t offset_to_eh_frame_;
33 uint32_t lut_entries_number_; 268 uint32_t lut_entries_number_;
34 int32_t offset_to_procedure_; 269 int32_t offset_to_procedure_;
35 int32_t offset_to_fde_; 270 int32_t offset_to_fde_;
36 }; 271 };
37 272
38 } // namespace internal 273 } // namespace internal
39 } // namespace v8 274 } // namespace v8
40 275
41 #endif 276 #endif
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698