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

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: Use natural direction for offsets in register saved directives. 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
« no previous file with comments | « src/crankshaft/lithium.cc ('k') | src/eh-frame.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 // Register saved at location <base_address> + <offset>
69 void RecordRegisterSavedToStack(Register name, int offset) {
70 RecordRegisterSavedToStack(RegisterToDwarfCode(name), offset);
71 }
72
73 void RecordRegisterIsValid(Register name);
74
75 void RecordRegisterFollowsInitialRule(Register name);
76
77 void Finish(int code_size);
78
79 // Remember to call Finish() before GetEhFrame().
80 //
81 // The EhFrameWriter instance owns the buffer pointed by
82 // CodeDesc::unwinding_info, and must outlive any use of the CodeDesc.
83 void GetEhFrame(CodeDesc* desc);
84
85 int last_pc_offset() const { return last_pc_offset_; }
86 Register base_register() const { return base_register_; }
87 int base_offset() const { return base_offset_; }
88
89 private:
90 static const uint32_t kInt32Placeholder = 0xdeadc0de;
91
92 static int RegisterToDwarfCode(Register name);
93
94 void WriteSLEB128(int32_t value);
95 void WriteULEB128(uint32_t value);
96
97 void WriteByte(byte value) { eh_frame_buffer_.push_back(value); }
98 void WriteOpcode(DwarfOpcodes opcode) {
99 WriteByte(static_cast<byte>(opcode));
100 }
101 void WriteBytes(const byte* start, int size) {
102 eh_frame_buffer_.insert(eh_frame_buffer_.end(), start, start + size);
103 }
104 void WriteInt16(uint16_t value) {
105 WriteBytes(reinterpret_cast<const byte*>(&value), sizeof(value));
106 }
107 void WriteInt32(uint32_t value) {
108 WriteBytes(reinterpret_cast<const byte*>(&value), sizeof(value));
109 }
110 void PatchInt32(int base_offset, uint32_t value) {
111 DCHECK_EQ(ReadUnalignedUInt32(eh_frame_buffer_.data() + base_offset),
112 kInt32Placeholder);
113 DCHECK_LT(base_offset + kInt32Size, eh_frame_offset());
114 WriteUnalignedUInt32(eh_frame_buffer_.data() + base_offset, value);
115 }
116
117 void WriteCIE();
118 void WriteReturnAddressRegisterCode();
119 void WriteInitialStateInCIE();
120 void WriteFDEHeader();
121 void WritePaddingTo8ByteAlignment();
122
123 // Internal version that directly accepts a DWARF register code, needed for
124 // handling pseudoregisters on some platforms, such as x64.
125 void RecordRegisterSavedToStack(int register_code, int offset);
126
127 int eh_frame_offset() const {
128 return static_cast<int>(eh_frame_buffer_.size());
129 }
130
131 int fde_offset() const { return cie_size_; }
132
133 int procedure_address_offset() const {
134 return fde_offset() + kProcedureAddressOffsetInFde;
135 }
136
137 int procedure_size_offset() const {
138 return fde_offset() + kProcedureSizeOffsetInFde;
139 }
140
141 int cie_size_;
142 int last_pc_offset_;
143 bool eh_frame_finalised_;
144 Register base_register_;
145 int base_offset_;
146 std::vector<byte> eh_frame_buffer_;
147 };
148
149 class EhFrameIterator {
150 public:
151 explicit EhFrameIterator(EhFrameWriter* writer);
rmcilroy 2016/07/06 13:59:30 Why does this take a frame writer? It should take
Stefano Sanfilippo 2016/07/06 16:54:50 In order to extract the buffer from the EhFrameWri
152
153 EhFrameIterator(const byte* start, const byte* end)
154 : start_(start), next_(start), end_(end) {
155 DCHECK_LE(start, end);
156 }
157
158 void SkipCIE() {
159 DCHECK_EQ(next_, start_);
160 next_ += ReadUnalignedUInt32(next_) + kInt32Size;
161 }
162
163 void SkipToFDEDirectives() {
164 SkipCIE();
165 // Skip the FDE header.
166 Skip(4 * kInt32Size + 1);
rmcilroy 2016/07/06 13:59:30 You should have a constant for the size of the FDE
Stefano Sanfilippo 2016/07/06 16:54:50 Done.
167 }
168
169 void Skip(int how_many) {
170 next_ += how_many;
171 DCHECK_LE(next_, end_);
172 }
173
174 uint32_t GetNextUInt32() { return GetNextIntegral<uint32_t>(); }
175 uint16_t GetNextUInt16() { return GetNextIntegral<uint16_t>(); }
176 byte GetNextByte() { return GetNextIntegral<byte>(); }
177 EhFrameWriter::DwarfOpcodes GetNextOpcode() {
178 return static_cast<EhFrameWriter::DwarfOpcodes>(GetNextByte());
179 }
180
181 uint32_t GetNextULEB128();
182 int32_t GetNextSLEB128();
183
184 bool ReachedEnd() const {
rmcilroy 2016/07/06 13:59:30 nit - Done() or Finished() is the usual naming
Stefano Sanfilippo 2016/07/06 16:54:50 Done.
185 DCHECK_LE(next_, end_);
186 return next_ == end_;
187 }
188
189 const void* current_address() const {
190 return reinterpret_cast<const void*>(next_);
191 }
192 int GetCurrentOffset() const {
rmcilroy 2016/07/06 13:59:30 newline
Stefano Sanfilippo 2016/07/06 16:54:50 Done.
193 DCHECK_GE(next_, start_);
194 return static_cast<int>(next_ - start_);
195 }
196 int GetBufferSize() { return static_cast<int>(end_ - start_); }
197
198 private:
199 static uint32_t DecodeULEB128(const byte* encoded, int* encoded_size);
200 static int32_t DecodeSLEB128(const byte* encoded, int* encoded_size);
201
202 template <typename T>
203 T GetNextIntegral() {
rmcilroy 2016/07/06 13:59:30 /s/Integral/Value
Stefano Sanfilippo 2016/07/06 16:54:50 Done.
204 T result;
205 DCHECK_LE(next_ + sizeof(result), end_);
206 result = ReadUnalignedValue<T>(next_);
207 next_ += sizeof(result);
208 return result;
209 }
210
211 const byte* start_;
212 const byte* next_;
213 const byte* end_;
214
215 friend class EhFrameIteratorTest;
216 };
217
218 #ifdef ENABLE_DISASSEMBLER
219
220 class EhFrameDisassembler final {
221 public:
222 EhFrameDisassembler(const byte* start, const byte* end)
223 : start_(start), end_(end) {
224 DCHECK_LE(start, end);
225 }
226
227 void DisassembleToStream(std::ostream& stream); // NOLINT
228
229 private:
230 static void DumpDWARFDirectives(std::ostream& stream, // NOLINT
231 const byte* start, const byte* end);
232
233 static const char* DwarfRegisterCodeToString(int code);
234
235 const byte* start_;
236 const byte* end_;
237 };
238
239 #endif
14 240
15 class EhFrameHdr final { 241 class EhFrameHdr final {
16 public: 242 public:
17 static const int kRecordSize = 20; 243 static const int kRecordSize = 20;
18 static const int kCIESize; 244
19 245 EhFrameHdr(int code_size, int eh_frame_size, int cie_size);
20 explicit EhFrameHdr(Code* code); 246 static EhFrameHdr CreateEmptyHeader();
21 247
22 int32_t offset_to_eh_frame() const { return offset_to_eh_frame_; } 248 int32_t offset_to_eh_frame() const { return offset_to_eh_frame_; }
23 uint32_t lut_entries_number() const { return lut_entries_number_; } 249 uint32_t lut_entries_number() const { return lut_entries_number_; }
24 int32_t offset_to_procedure() const { return offset_to_procedure_; } 250 int32_t offset_to_procedure() const { return offset_to_procedure_; }
25 int32_t offset_to_fde() const { return offset_to_fde_; } 251 int32_t offset_to_fde() const { return offset_to_fde_; }
26 252
27 private: 253 private:
254 static const int kEhFrameHdrVersion = 1;
255
256 EhFrameHdr() {}
257
28 uint8_t version_; 258 uint8_t version_;
29 uint8_t eh_frame_ptr_encoding_; 259 uint8_t eh_frame_ptr_encoding_;
30 uint8_t lut_size_encoding_; 260 uint8_t lut_size_encoding_;
31 uint8_t lut_entries_encoding_; 261 uint8_t lut_entries_encoding_;
32 int32_t offset_to_eh_frame_; 262 int32_t offset_to_eh_frame_;
33 uint32_t lut_entries_number_; 263 uint32_t lut_entries_number_;
34 int32_t offset_to_procedure_; 264 int32_t offset_to_procedure_;
35 int32_t offset_to_fde_; 265 int32_t offset_to_fde_;
36 }; 266 };
37 267
38 } // namespace internal 268 } // namespace internal
39 } // namespace v8 269 } // namespace v8
40 270
41 #endif 271 #endif
OLDNEW
« no previous file with comments | « src/crankshaft/lithium.cc ('k') | src/eh-frame.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698