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

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: Rename methods that are not purely getters, add comments. 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 struct EhFrameConstants final {
rmcilroy 2016/07/07 10:11:03 class
Stefano Sanfilippo 2016/07/07 10:57:00 Done.
14 14 enum class DwarfOpcodes : byte {
15 class EhFrameHdr final { 15 kNop = 0x00,
16 kAdvanceLoc1 = 0x02,
17 kAdvanceLoc2 = 0x03,
18 kAdvanceLoc4 = 0x04,
19 kSameValue = 0x08,
20 kDefCfa = 0x0c,
21 kDefCfaRegister = 0x0d,
22 kDefCfaOffset = 0x0e,
23 kOffsetExtendedSf = 0x11,
24 };
25
26 enum DwarfEncodingSpecifiers : byte {
27 kUData4 = 0x03,
28 kSData4 = 0x0b,
29 kPcRel = 0x10,
30 kDataRel = 0x30,
31 kOmit = 0xff,
32 };
33
34 static const int kLocationTag = 1;
35 static const int kLocationMask = 0x3f;
36 static const int kLocationMaskSize = 6;
37
38 static const int kSavedRegisterTag = 2;
39 static const int kSavedRegisterMask = 0x3f;
40 static const int kSavedRegisterMaskSize = 6;
41
42 static const int kFollowInitialRuleTag = 3;
43 static const int kFollowInitialRuleMask = 0x3f;
44 static const int kFollowInitialRuleMaskSize = 6;
45
46 static const int kProcedureAddressOffsetInFde = 2 * kInt32Size;
47 static const int kProcedureSizeOffsetInFde = 3 * kInt32Size;
48
49 static const int kInitialStateOffsetInCIE = 19;
50 static const int kEhFrameTerminatorSize = 4;
51
52 static const int kDataAlignmentFactor;
rmcilroy 2016/07/07 10:11:03 Add a comment that this is defined in eh-writer-<a
Stefano Sanfilippo 2016/07/07 10:57:00 Done.
53
54 static const int kFdeVersionSize = 1;
55 static const int kFdeEncodingSpecifiersSize = 3;
56
57 static const int kEhFrameHdrVersion = 1;
58 static const int kEhFrameHdrSize = 20;
59
60 static const byte kDummyEhFrame[kEhFrameHdrSize];
rmcilroy 2016/07/07 10:11:03 Don't make this a static with static initializatio
Stefano Sanfilippo 2016/07/07 10:57:00 Done.
61 };
62
63 class EhFrameWriter {
16 public: 64 public:
17 static const int kRecordSize = 20; 65 explicit EhFrameWriter(Zone* zone);
18 static const int kCIESize; 66
19 67 void AdvanceLocation(int pc_offset);
20 explicit EhFrameHdr(Code* code); 68
21 69 // The <base_address> is the one to which all <offset>s in SaveRegisterToStack
22 int32_t offset_to_eh_frame() const { return offset_to_eh_frame_; } 70 // directives are relative. It is given by <base_register> + <base_offset>.
23 uint32_t lut_entries_number() const { return lut_entries_number_; } 71 void SetBaseAddressRegister(Register base_register);
24 int32_t offset_to_procedure() const { return offset_to_procedure_; } 72 void SetBaseAddressOffset(int base_offset);
25 int32_t offset_to_fde() const { return offset_to_fde_; } 73 void IncreaseBaseAddressOffset(int base_delta) {
74 SetBaseAddressOffset(base_offset_ + base_delta);
75 }
76 void SetBaseAddressRegisterAndOffset(Register base_register, int base_offset);
77
78 // Register saved at location <base_address> + <offset>
79 void RecordRegisterSavedToStack(Register name, int offset) {
80 RecordRegisterSavedToStack(RegisterToDwarfCode(name), offset);
81 }
82
83 // The content of the register is valid (by default, it is undefined).
84 void RecordRegisterIsValid(Register name);
85
86 // The register follows the rule defined in the CIE.
87 void RecordRegisterFollowsInitialRule(Register name);
88
89 void Finish(int code_size);
90
91 // Remember to call Finish() before GetEhFrame().
92 //
93 // The EhFrameWriter instance owns the buffer pointed by
94 // CodeDesc::unwinding_info, and must outlive any use of the CodeDesc.
95 void GetEhFrame(CodeDesc* desc);
96
97 int last_pc_offset() const { return last_pc_offset_; }
98 Register base_register() const { return base_register_; }
99 int base_offset() const { return base_offset_; }
26 100
27 private: 101 private:
28 uint8_t version_; 102 static const uint32_t kInt32Placeholder = 0xdeadc0de;
29 uint8_t eh_frame_ptr_encoding_; 103
30 uint8_t lut_size_encoding_; 104 static int RegisterToDwarfCode(Register name);
31 uint8_t lut_entries_encoding_; 105
32 int32_t offset_to_eh_frame_; 106 void WriteSLEB128(int32_t value);
33 uint32_t lut_entries_number_; 107 void WriteULEB128(uint32_t value);
34 int32_t offset_to_procedure_; 108
35 int32_t offset_to_fde_; 109 void WriteByte(byte value) { eh_frame_buffer_.push_back(value); }
36 }; 110 void WriteOpcode(EhFrameConstants::DwarfOpcodes opcode) {
111 WriteByte(static_cast<byte>(opcode));
112 }
113 void WriteBytes(const byte* start, int size) {
114 eh_frame_buffer_.insert(eh_frame_buffer_.end(), start, start + size);
115 }
116 void WriteInt16(uint16_t value) {
117 WriteBytes(reinterpret_cast<const byte*>(&value), sizeof(value));
118 }
119 void WriteInt32(uint32_t value) {
120 WriteBytes(reinterpret_cast<const byte*>(&value), sizeof(value));
121 }
122 void PatchInt32(int base_offset, uint32_t value) {
123 DCHECK_EQ(ReadUnalignedUInt32(eh_frame_buffer_.data() + base_offset),
124 kInt32Placeholder);
125 DCHECK_LT(base_offset + kInt32Size, eh_frame_offset());
126 WriteUnalignedUInt32(eh_frame_buffer_.data() + base_offset, value);
127 }
128
129 // Write the common information entry, which includes encoding specifiers,
130 // alignment factors, the return address (pseudo) register code and the
131 // directives to construct the initial state of the unwinding table.
132 void WriteCIE();
133
134 // Write directives to build the initial state in the CIE.
135 // This bit is platform specific.
rmcilroy 2016/07/07 10:11:03 Don't use "bit". If you want group all the archite
Stefano Sanfilippo 2016/07/07 10:57:00 Done.
136 void WriteInitialStateInCIE();
137
138 // Write the return address (pseudo) register code.
139 void WriteReturnAddressRegisterCode();
140
141 // Write the header of the function data entry, containing a pointer to the
142 // correspondent CIE and the position and size of the associated routine.
143 void WriteFDEHeader();
144
145 // Write the contents of the .eh_frame_hdr section, including encoder
146 // specifiers and the routine => FDE lookup table.
147 void WriteEhFrameHdr(int code_size);
148
149 // Write nops to the buffer until the size reaches a multiple of 8 bytes.
150 void WritePaddingTo8ByteAlignment();
151
152 // Internal version that directly accepts a DWARF register code, needed for
153 // handling pseudoregisters on some platforms, such as x64.
rmcilroy 2016/07/07 10:11:03 pseudo-registers and drop the ", such as x64"
Stefano Sanfilippo 2016/07/07 10:57:00 Done.
154 void RecordRegisterSavedToStack(int register_code, int offset);
155
156 int GetProcedureAddressOffset() const {
157 return fde_offset() + EhFrameConstants::kProcedureAddressOffsetInFde;
158 }
159
160 int GetProcedureSizeOffset() const {
161 return fde_offset() + EhFrameConstants::kProcedureSizeOffsetInFde;
162 }
163
164 int eh_frame_offset() const {
165 return static_cast<int>(eh_frame_buffer_.size());
166 }
167
168 int fde_offset() const { return cie_size_; }
169
170 int cie_size_;
171 int last_pc_offset_;
172 bool eh_frame_finalised_;
173 Register base_register_;
174 int base_offset_;
175 ZoneVector<byte> eh_frame_buffer_;
176 };
177
178 class EhFrameIterator {
179 public:
180 EhFrameIterator(const byte* start, const byte* end)
181 : start_(start), next_(start), end_(end) {
182 DCHECK_LE(start, end);
183 }
184
185 void SkipCIE() {
186 DCHECK_EQ(next_, start_);
187 next_ += ReadUnalignedUInt32(next_) + kInt32Size;
188 }
189
190 void SkipToFDEDirectives() {
191 SkipCIE();
192 // Skip the FDE header.
193 Skip(kDirectivesOffsetInFDE);
194 }
195
196 void Skip(int how_many) {
197 DCHECK_GE(how_many, 0);
198 next_ += how_many;
199 DCHECK_LE(next_, end_);
200 }
201
202 uint32_t GetNextUInt32() { return GetNextValue<uint32_t>(); }
203 uint16_t GetNextUInt16() { return GetNextValue<uint16_t>(); }
204 byte GetNextByte() { return GetNextValue<byte>(); }
205 EhFrameConstants::DwarfOpcodes GetNextOpcode() {
206 return static_cast<EhFrameConstants::DwarfOpcodes>(GetNextByte());
207 }
208
209 uint32_t GetNextULEB128();
210 int32_t GetNextSLEB128();
211
212 bool Done() const {
213 DCHECK_LE(next_, end_);
214 return next_ == end_;
215 }
216
217 int GetCurrentOffset() const {
218 DCHECK_GE(next_, start_);
219 return static_cast<int>(next_ - start_);
220 }
221
222 int GetBufferSize() { return static_cast<int>(end_ - start_); }
223
224 const void* current_address() const {
225 return reinterpret_cast<const void*>(next_);
226 }
227
228 private:
229 static const int kDirectivesOffsetInFDE = 4 * kInt32Size + 1;
230
231 static uint32_t DecodeULEB128(const byte* encoded, int* encoded_size);
232 static int32_t DecodeSLEB128(const byte* encoded, int* encoded_size);
233
234 template <typename T>
235 T GetNextValue() {
236 T result;
237 DCHECK_LE(next_ + sizeof(result), end_);
238 result = ReadUnalignedValue<T>(next_);
239 next_ += sizeof(result);
240 return result;
241 }
242
243 const byte* start_;
244 const byte* next_;
245 const byte* end_;
246 };
247
248 #ifdef ENABLE_DISASSEMBLER
249
250 class EhFrameDisassembler final {
251 public:
252 EhFrameDisassembler(const byte* start, const byte* end)
253 : start_(start), end_(end) {
254 DCHECK_LT(start, end);
255 }
256
257 void DisassembleToStream(std::ostream& stream); // NOLINT
258
259 private:
260 static void DumpDWARFDirectives(std::ostream& stream, // NOLINT
261 const byte* start, const byte* end);
262
263 static const char* DwarfRegisterCodeToString(int code);
264
265 const byte* start_;
266 const byte* end_;
267 };
268
269 #endif
37 270
38 } // namespace internal 271 } // namespace internal
39 } // namespace v8 272 } // namespace v8
40 273
41 #endif 274 #endif
OLDNEW
« no previous file with comments | « src/crankshaft/lithium.cc ('k') | src/eh-frame.cc » ('j') | src/eh-frame.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698