OLD | NEW |
---|---|
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 #include "src/eh-frame.h" | 5 #include "src/eh-frame.h" |
6 #include "src/objects-inl.h" | 6 |
7 #include "src/objects.h" | 7 #include <iomanip> |
8 #include <ostream> | |
9 | |
10 #if !defined(V8_TARGET_ARCH_X64) && !defined(V8_TARGET_ARCH_ARM) && \ | |
11 !defined(V8_TARGET_ARCH_ARM64) | |
12 | |
13 // Placeholders for unsupported architectures. | |
8 | 14 |
9 namespace v8 { | 15 namespace v8 { |
10 namespace internal { | 16 namespace internal { |
11 | 17 |
12 static const int DW_EH_PE_pcrel = 0x10; | 18 STATIC_CONST_MEMBER_DEFINITION const int EhFrameWriter::kDataAlignmentFactor = |
13 static const int DW_EH_PE_datarel = 0x30; | 19 1; |
14 static const int DW_EH_PE_udata4 = 0x03; | 20 |
15 static const int DW_EH_PE_sdata4 = 0x0b; | 21 void EhFrameWriter::WriteReturnAddressRegisterCode() { UNIMPLEMENTED(); } |
16 | 22 |
17 const int EhFrameHdr::kCIESize = 0; | 23 void EhFrameWriter::WriteInitialState() { UNIMPLEMENTED(); } |
18 | 24 |
19 static const int kVersionSize = 1; | 25 const char* EhFrameWriter::DwarfRegisterCodeToString(int) { |
20 static const int kEncodingSpecifiersSize = 3; | 26 UNIMPLEMENTED(); |
27 return nullptr; | |
28 } | |
29 | |
30 int EhFrameWriter::RegisterToDwarfCode(Register) { | |
31 UNIMPLEMENTED(); | |
32 return -1; | |
33 } | |
34 | |
35 } // namespace internal | |
36 } // namespace v8 | |
37 | |
38 #endif | |
39 | |
40 namespace v8 { | |
41 namespace internal { | |
42 | |
43 STATIC_CONST_MEMBER_DEFINITION const int EhFrameWriter::kTerminatorSize; | |
44 STATIC_CONST_MEMBER_DEFINITION const uint32_t EhFrameWriter::kInt32Placeholder; | |
rmcilroy
2016/07/05 10:56:12
I don't think you need these do you?
Stefano Sanfilippo
2016/07/05 16:02:13
Unfortunately I do, otherwise I get a linking erro
| |
45 | |
46 EhFrameWriter::EhFrameWriter() | |
47 : last_pc_offset_(0), | |
48 eh_frame_finalised_(false), | |
49 base_register_(no_reg), | |
50 base_offset_(0) { | |
rmcilroy
2016/07/05 10:56:12
Set cie_size_ to zero here, to ensure they are pro
Stefano Sanfilippo
2016/07/05 16:02:13
Done.
| |
51 eh_frame_buffer_.reserve(100); | |
rmcilroy
2016/07/05 10:56:12
100 seems slightly random. Why not 128?
Stefano Sanfilippo
2016/07/05 16:02:13
I observed that the eh_frame for our code objects
rmcilroy
2016/07/06 13:59:30
64 in that case seems reasonable in that case (see
Stefano Sanfilippo
2016/07/06 16:54:49
Done, I went with 128 so we are covered in almost
| |
52 int cie_start_offset = eh_frame_offset(); | |
53 WriteCIE(); | |
54 cie_size_ = eh_frame_offset() - cie_start_offset; | |
rmcilroy
2016/07/05 10:56:12
Set this in WriteCIE ?
Stefano Sanfilippo
2016/07/05 16:02:13
Done.
| |
55 WriteFDEHeader(); | |
56 } | |
57 | |
58 void EhFrameWriter::WriteCIE() { | |
59 static const int kCIEIdentifier = 0; | |
60 static const int kCIEVersion = 3; | |
61 static const int kCodeAlignmentFactor = 1; | |
62 static const int kAugmentationDataSize = 2; | |
63 static const byte kAugmentationString[] = {'z', 'L', 'R', 0}; | |
64 | |
65 int cie_size_offset = eh_frame_offset(); | |
66 WriteInt32(kInt32Placeholder); | |
67 int cie_start_offset = eh_frame_offset(); | |
68 WriteInt32(kCIEIdentifier); | |
69 WriteByte(kCIEVersion); | |
70 WriteBytes(&kAugmentationString[0], sizeof(kAugmentationString)); | |
71 WriteSLEB128(kCodeAlignmentFactor); | |
72 WriteSLEB128(kDataAlignmentFactor); | |
73 WriteReturnAddressRegisterCode(); | |
74 WriteByte(kAugmentationDataSize); | |
75 WriteByte(kOmit); | |
76 WriteByte(kSData4 | kPcRel); | |
77 DCHECK_EQ(eh_frame_offset() - cie_size_offset, kInitialStateOffsetInCIE); | |
78 WriteInitialState(); | |
79 Align(); | |
80 int cie_end_offset = eh_frame_offset(); | |
81 int encoded_cie_size = cie_end_offset - cie_start_offset; | |
82 PatchInt32(cie_size_offset, encoded_cie_size); | |
rmcilroy
2016/07/05 10:56:12
Some whitespace would be good to break up this cod
Stefano Sanfilippo
2016/07/05 16:02:13
Done.
| |
83 } | |
84 | |
85 void EhFrameWriter::WriteFDEHeader() { | |
86 DCHECK_EQ(eh_frame_offset(), fde_offset()); | |
rmcilroy
2016/07/05 10:56:12
DCHECK_NE(cie_size_, 0)
Stefano Sanfilippo
2016/07/05 16:02:13
Done.
| |
87 WriteInt32(kInt32Placeholder); // Placeholder for size of the FDE | |
88 WriteInt32(cie_size_ + kInt32Size); // Backwards offset to the CIE | |
89 DCHECK_EQ(eh_frame_offset(), procedure_address_offset()); | |
90 WriteInt32(kInt32Placeholder); // Placeholder for pointer to procedure | |
91 DCHECK_EQ(eh_frame_offset(), procedure_size_offset()); | |
92 WriteInt32(kInt32Placeholder); // Placeholder for size of the procedure | |
93 WriteByte(0); // No augmentation data | |
rmcilroy
2016/07/05 10:56:12
Newlines between each of these fields, with commen
Stefano Sanfilippo
2016/07/05 16:02:13
Done.
| |
94 } | |
95 | |
96 void EhFrameWriter::Align() { | |
97 DCHECK(!eh_frame_finalised_); | |
98 | |
99 int unpadded_size = eh_frame_offset(); | |
100 int padded_size = RoundUp(unpadded_size, 8); | |
101 int padding_size = padded_size - unpadded_size; | |
102 | |
103 static const byte kPadding[] = {kNop, kNop, kNop, kNop, | |
104 kNop, kNop, kNop, kNop}; | |
105 DCHECK_LE(padding_size, static_cast<int>(sizeof(kPadding))); | |
106 WriteBytes(&kPadding[0], padding_size); | |
107 } | |
108 | |
109 void EhFrameWriter::AdvanceLocation(int pc_offset) { | |
110 DCHECK(!eh_frame_finalised_); | |
111 DCHECK_GE(pc_offset, last_pc_offset_); | |
112 uint32_t delta = pc_offset - last_pc_offset_; | |
113 | |
114 if (delta <= kLocationMask) { | |
115 WriteByte((kLocationTag << kLocationMaskSize) | (delta & kLocationMask)); | |
116 } else if (delta <= kMaxUInt8) { | |
117 WriteByte(kAdvanceLoc1); | |
118 WriteByte(delta); | |
119 } else if (delta <= kMaxUInt16) { | |
120 WriteByte(kAdvanceLoc2); | |
121 WriteInt16(delta); | |
122 } else { | |
123 WriteByte(kAdvanceLoc4); | |
124 WriteInt32(delta); | |
125 } | |
126 | |
127 last_pc_offset_ = pc_offset; | |
128 } | |
129 | |
130 void EhFrameWriter::SetBaseAddressOffset(int base_offset) { | |
131 DCHECK(!eh_frame_finalised_); | |
132 DCHECK_GE(base_offset, 0); | |
133 WriteByte(kDefCfaOffset); | |
134 WriteULEB128(base_offset); | |
135 base_offset_ = base_offset; | |
136 } | |
137 | |
138 void EhFrameWriter::SetBaseAddressRegister(Register base_register) { | |
139 DCHECK(!eh_frame_finalised_); | |
140 int code = RegisterToDwarfCode(base_register); | |
141 WriteByte(kDefCfaRegister); | |
142 WriteULEB128(code); | |
143 base_register_ = base_register; | |
144 } | |
145 | |
146 void EhFrameWriter::SetBaseAddressRegisterAndOffset(Register base_register, | |
147 int base_offset) { | |
148 DCHECK(!eh_frame_finalised_); | |
149 int code = RegisterToDwarfCode(base_register); | |
150 WriteByte(kDefCfa); | |
151 WriteULEB128(code); | |
152 WriteULEB128(base_offset); | |
153 base_offset_ = base_offset; | |
154 base_register_ = base_register; | |
155 } | |
156 | |
157 void EhFrameWriter::RegisterSavedToStack(int register_code, int offset) { | |
rmcilroy
2016/07/05 10:56:12
RecordRegisterSavedToStack
Stefano Sanfilippo
2016/07/05 16:02:13
Done.
| |
158 DCHECK(!eh_frame_finalised_); | |
159 DCHECK_EQ(offset % kDataAlignmentFactor, 0); | |
160 int factored_offset = offset / std::abs(kDataAlignmentFactor); | |
161 if (factored_offset >= 0) { | |
162 DCHECK_LE(register_code, kSavedRegisterMask); | |
163 WriteByte((kSavedRegisterTag << kSavedRegisterMaskSize) | | |
164 (register_code & kSavedRegisterMask)); | |
165 WriteULEB128(factored_offset); | |
166 } else { | |
167 WriteByte(kOffsetExtendedSf); | |
168 WriteULEB128(register_code); | |
169 WriteSLEB128(factored_offset); | |
170 } | |
171 } | |
172 | |
173 void EhFrameWriter::RegisterIsValid(Register name) { | |
rmcilroy
2016/07/05 10:56:12
RecordRegisterIsValid
Stefano Sanfilippo
2016/07/05 16:02:13
Done.
| |
174 int code = RegisterToDwarfCode(name); | |
175 DCHECK(!eh_frame_finalised_); | |
176 DCHECK_GE(code, 0); | |
177 WriteByte(kSameValue); | |
178 WriteULEB128(code); | |
179 } | |
180 | |
181 void EhFrameWriter::Finish(int code_size) { | |
182 DCHECK(!eh_frame_finalised_); | |
183 DCHECK_GE(eh_frame_offset(), cie_size_); | |
184 | |
185 Align(); | |
186 | |
187 // Write the size of the FDE now that we know it. | |
188 int fde_size = eh_frame_offset() - fde_offset(); | |
189 PatchInt32(fde_offset(), fde_size); | |
190 | |
191 // Write the size and offset to procedure. | |
192 PatchInt32(procedure_address_offset(), | |
193 -(RoundUp(code_size, 8) + procedure_address_offset())); | |
194 PatchInt32(procedure_size_offset(), code_size); | |
195 | |
196 // Terminate the .eh_frame. | |
197 static const byte kTerminator[kTerminatorSize] = {0}; | |
198 WriteBytes(&kTerminator[0], kTerminatorSize); | |
199 | |
200 // Write .eh_frame_hdr | |
201 EhFrameHdr eh_frame_hdr(code_size, eh_frame_offset(), cie_size_); | |
202 WriteBytes(reinterpret_cast<const byte*>(&eh_frame_hdr), | |
203 EhFrameHdr::kRecordSize); | |
204 | |
205 eh_frame_finalised_ = true; | |
206 } | |
207 | |
208 void EhFrameWriter::GetEhFrame(CodeDesc* desc) { | |
209 DCHECK(eh_frame_finalised_); | |
210 desc->unwinding_info_size = static_cast<int>(eh_frame_buffer_.size()); | |
211 desc->unwinding_info = eh_frame_buffer_.data(); | |
212 } | |
213 | |
214 void EhFrameWriter::WriteULEB128(uint32_t value) { | |
215 do { | |
216 byte chunk = value & 0x7f; | |
217 value >>= 7; | |
218 if (value != 0) chunk |= 0x80; | |
219 eh_frame_buffer_.push_back(chunk); | |
220 } while (value != 0); | |
221 } | |
222 | |
223 void EhFrameWriter::WriteSLEB128(int32_t value) { | |
224 static const int kSignBitMask = 0x40; | |
225 bool done; | |
226 do { | |
227 byte chunk = value & 0x7f; | |
228 value >>= 7; | |
229 done = ((value == 0) && ((chunk & kSignBitMask) == 0)) || | |
230 ((value == -1) && ((chunk & kSignBitMask) != 0)); | |
231 if (!done) chunk |= 0x80; | |
232 eh_frame_buffer_.push_back(chunk); | |
233 } while (!done); | |
234 } | |
235 | |
236 // static | |
237 uint32_t EhFrameWriter::DecodeULEB128(const byte* encoded, int* encoded_size) { | |
238 const byte* current = encoded; | |
239 uint32_t result = 0; | |
240 int shift = 0; | |
241 | |
242 do { | |
243 DCHECK_LT(shift, 8 * static_cast<int>(sizeof(result))); | |
244 result |= (*current & 0x7f) << shift; | |
245 shift += 7; | |
246 } while (*current++ >= 128); | |
247 | |
248 DCHECK_NOT_NULL(encoded_size); | |
249 *encoded_size = static_cast<int>(current - encoded); | |
250 | |
251 return result; | |
252 } | |
253 | |
254 // static | |
255 int32_t EhFrameWriter::DecodeSLEB128(const byte* encoded, int* encoded_size) { | |
256 static const byte kSignBitMask = 0x40; | |
257 | |
258 const byte* current = encoded; | |
259 int32_t result = 0; | |
260 int shift = 0; | |
261 byte chunk; | |
262 | |
263 do { | |
264 chunk = *current++; | |
265 DCHECK_LT(shift, 8 * static_cast<int>(sizeof(result))); | |
266 result |= (chunk & 0x7f) << shift; | |
267 shift += 7; | |
268 } while (chunk >= 128); | |
269 | |
270 // Sign extend the result if the last chunk has the sign bit set. | |
271 if (chunk & kSignBitMask) result |= (~0ull) << shift; | |
272 | |
273 DCHECK_NOT_NULL(encoded_size); | |
274 *encoded_size = static_cast<int>(current - encoded); | |
275 | |
276 return result; | |
277 } | |
278 | |
279 #ifdef ENABLE_DISASSEMBLER | |
280 | |
281 namespace { | |
282 | |
283 class StreamModifiersScope final { | |
284 public: | |
285 explicit StreamModifiersScope(std::ostream* stream) | |
286 : stream_(stream), flags_(stream->flags()) {} | |
287 ~StreamModifiersScope() { stream_->flags(flags_); } | |
288 | |
289 private: | |
290 std::ostream* stream_; | |
291 std::ios::fmtflags flags_; | |
292 }; | |
293 | |
294 } // namespace | |
295 | |
296 // static | |
297 void EhFrameWriter::DumpDWARFDirectives(std::ostream& stream, // NOLINT | |
298 const byte* begin, const byte* end) { | |
299 StreamModifiersScope modifiers_scope(&stream); | |
300 | |
301 const byte* cur = begin; | |
302 uint32_t offset_in_procedure = 0; | |
303 | |
304 while (cur != end) { | |
305 stream << reinterpret_cast<const void*>(cur) << " "; | |
306 | |
307 if (((*cur >> kLocationMaskSize) & 0xff) == kLocationTag) { | |
308 int value = *cur & kLocationMask; | |
309 cur += sizeof(byte); | |
310 offset_in_procedure += value; | |
311 stream << "| pc_offset=" << std::dec << offset_in_procedure | |
312 << " (delta=0x" << std::hex << value << ")\n"; | |
313 continue; | |
314 } | |
315 | |
316 if (((*cur >> kSavedRegisterMaskSize) & 0xff) == kSavedRegisterTag) { | |
317 stream << "| " << DwarfRegisterCodeToString(*cur & kLocationMask); | |
318 cur += sizeof(byte); | |
319 int decoded_size = 0; | |
320 int decoded_offset = static_cast<int>(DecodeULEB128(cur, &decoded_size)); | |
321 cur += decoded_size; | |
322 stream << " saved at base" << std::showpos << std::dec | |
323 << decoded_offset * kDataAlignmentFactor << '\n'; | |
324 continue; | |
325 } | |
326 | |
327 uint8_t bytecode = *cur; | |
328 cur += sizeof(byte); | |
329 | |
330 switch (bytecode) { | |
331 case kOffsetExtendedSf: { | |
332 int decoded_size = 0; | |
333 stream << "| " | |
334 << DwarfRegisterCodeToString(DecodeULEB128(cur, &decoded_size)); | |
335 cur += decoded_size; | |
336 int32_t decoded_offset = DecodeSLEB128(cur, &decoded_size); | |
337 cur += decoded_size; | |
338 stream << " saved at base" << std::showpos << std::dec | |
339 << decoded_offset * kDataAlignmentFactor << '\n'; | |
340 } | |
341 case kAdvanceLoc1: { | |
342 unsigned value = *reinterpret_cast<const uint8_t*>(cur); | |
343 cur += sizeof(uint8_t); | |
344 offset_in_procedure += value; | |
345 stream << "| pc_offset=" << std::dec << offset_in_procedure | |
346 << " (delta=0x" << std::hex << value << ")\n"; | |
347 break; | |
348 } | |
349 case kAdvanceLoc2: { | |
350 uint16_t value = ReadUnalignedUInt16(cur); | |
351 cur += sizeof(uint16_t); | |
352 offset_in_procedure += value; | |
353 stream << "| pc_offset=" << std::dec << offset_in_procedure | |
354 << " (delta=0x" << std::hex << value << ")\n"; | |
355 break; | |
356 } | |
357 case kAdvanceLoc4: { | |
358 uint32_t value = ReadUnalignedUInt32(cur); | |
359 offset_in_procedure += value; | |
360 cur += sizeof(uint32_t); | |
361 stream << "| pc_offset=" << std::dec << offset_in_procedure | |
362 << " (delta=0x" << std::hex << value << ")\n"; | |
363 break; | |
364 } | |
365 case kDefCfa: { | |
366 int decoded_size = 0; | |
367 int base_register = DecodeULEB128(cur, &decoded_size); | |
368 cur += decoded_size; | |
369 int base_offset = DecodeULEB128(cur, &decoded_size); | |
370 cur += decoded_size; | |
371 stream << "| base_register=" << DwarfRegisterCodeToString(base_register) | |
372 << ", base_offset=0x" << std::hex << base_offset << '\n'; | |
373 break; | |
374 } | |
375 case kDefCfaOffset: { | |
376 int decoded_size = 0; | |
377 stream << "| base_offset=0x" << std::hex | |
378 << DecodeULEB128(cur, &decoded_size) << '\n'; | |
379 cur += decoded_size; | |
380 break; | |
381 } | |
382 case kDefCfaRegister: { | |
383 int decoded_size = 0; | |
384 stream << "| base_register=" | |
385 << DwarfRegisterCodeToString(DecodeULEB128(cur, &decoded_size)) | |
386 << '\n'; | |
387 cur += decoded_size; | |
388 break; | |
389 } | |
390 case kSameValue: { | |
391 int decoded_size = 0; | |
392 stream << "| " | |
393 << DwarfRegisterCodeToString(DecodeULEB128(cur, &decoded_size)) | |
394 << " to initial value\n"; | |
395 cur += decoded_size; | |
396 break; | |
397 } | |
398 case kNop: | |
399 stream << "| nop\n"; | |
400 break; | |
401 default: | |
402 UNREACHABLE(); | |
403 return; | |
404 } | |
405 } | |
406 } | |
407 | |
408 // static | |
409 void EhFrameWriter::DisassembleToStream(std::ostream& stream, // NOLINT | |
410 const byte* start, const byte* end) { | |
411 // The encoded CIE size does not include the size field itself. | |
412 const int cie_size = ReadUnalignedUInt32(start) + kInt32Size; | |
413 const int fde_offset = cie_size; | |
414 | |
415 const byte* cie_directives_start = start + kInitialStateOffsetInCIE; | |
416 const byte* cie_directives_end = start + cie_size; | |
417 DCHECK_LE(cie_directives_start, cie_directives_end); | |
418 | |
419 stream << reinterpret_cast<const void*>(start) << " .eh_frame: CIE\n"; | |
420 DumpDWARFDirectives(stream, cie_directives_start, cie_directives_end); | |
421 | |
422 const byte* procedure_offset_address = | |
423 start + fde_offset + kProcedureAddressOffsetInFde; | |
424 int32_t procedure_offset = | |
425 ReadUnalignedValue<int32_t>(procedure_offset_address); | |
426 | |
427 const byte* procedure_size_address = | |
428 start + fde_offset + kProcedureSizeOffsetInFde; | |
429 uint32_t procedure_size = ReadUnalignedUInt32(procedure_size_address); | |
430 | |
431 const byte* fde_start = start + fde_offset; | |
432 stream << reinterpret_cast<const void*>(fde_start) << " .eh_frame: FDE\n" | |
433 << reinterpret_cast<const void*>(procedure_offset_address) | |
434 << " | procedure offset=" << procedure_offset << '\n' | |
435 << reinterpret_cast<const void*>(procedure_size_address) | |
436 << " | procedure size=" << procedure_size << '\n'; | |
437 | |
438 const int fde_directives_offset = fde_offset + 4 * kInt32Size + 1; | |
439 | |
440 const byte* fde_directives_start = start + fde_directives_offset; | |
441 const byte* fde_directives_end = | |
442 end - EhFrameHdr::kRecordSize - kTerminatorSize; | |
443 DCHECK_LE(fde_directives_start, fde_directives_end); | |
444 | |
445 DumpDWARFDirectives(stream, fde_directives_start, fde_directives_end); | |
446 | |
447 const byte* fde_terminator_start = fde_directives_end; | |
448 stream << reinterpret_cast<const void*>(fde_terminator_start) | |
449 << " .eh_frame: terminator\n"; | |
450 | |
451 const byte* eh_frame_hdr_start = fde_terminator_start + kTerminatorSize; | |
452 stream << reinterpret_cast<const void*>(eh_frame_hdr_start) | |
453 << " .eh_frame_hdr: placeholder\n"; | |
454 } | |
455 | |
456 #endif | |
21 | 457 |
22 // | 458 // |
23 // In order to calculate offsets in the .eh_frame_hdr, we must know the layout | 459 // In order to calculate offsets in the .eh_frame_hdr, we must know the layout |
24 // of the DSO generated by perf inject, which is assumed to be the following: | 460 // of the DSO generated by perf inject, which is assumed to be the following: |
25 // | 461 // |
26 // | ... | | | 462 // | ... | | |
27 // +---------------+ <-- (F) --- | Larger offsets in file | 463 // +---------------+ <-- (F) --- | Larger offsets in file |
28 // | | ^ | | 464 // | | ^ | |
29 // | Instructions | | .text v | 465 // | Instructions | | .text v |
30 // | | v | 466 // | | v |
(...skipping 13 matching lines...) Expand all Loading... | |
44 // | version | ^ | 480 // | version | ^ |
45 // +---------------+ | | 481 // +---------------+ | |
46 // | encoding | | | 482 // | encoding | | |
47 // | specifiers | | | 483 // | specifiers | | |
48 // +---------------+ <---(A) | .eh_frame_hdr | 484 // +---------------+ <---(A) | .eh_frame_hdr |
49 // | offset to | | | 485 // | offset to | | |
50 // | .eh_frame | | | 486 // | .eh_frame | | |
51 // +---------------+ | | 487 // +---------------+ | |
52 // | ... | ... | 488 // | ... | ... |
53 // | 489 // |
54 // (F) is aligned at a 16-byte boundary. | 490 // (F) is aligned to a 16-byte boundary. |
55 // (D) is aligned at a 8-byte boundary. | 491 // (D) is aligned to a 8-byte boundary. |
56 // (B) is aligned at a 4-byte boundary. | 492 // (B) is aligned to a 4-byte boundary. |
57 // (E), (C) and (A) have no alignment requirements. | 493 // (C) is aligned to an addressing unit size boundary. |
494 // (E) and (A) have no alignment requirements. | |
58 // | 495 // |
59 // The distance between (A) and (B) is 4 bytes. | 496 // The distance between (A) and (B) is 4 bytes. |
60 // | 497 // |
61 // The size of the .eh_frame is required to be a multiple of the pointer size, | 498 // The size of the FDE is required to be a multiple of the pointer size, which |
62 // which means that (B) will be naturally aligned to a 4-byte boundary on all | 499 // means that (B) will be naturally aligned to a 4-byte boundary on all the |
63 // the architectures we support. | 500 // architectures we support. |
64 // | 501 // |
65 // Because (E) has no alignment requirements, there is padding between (E) and | 502 // Because (E) has no alignment requirements, there is padding between (E) and |
66 // (D). (F) is aligned at a 16-byte boundary, thus to a 8-byte one as well. | 503 // (D). (F) is aligned at a 16-byte boundary, thus to a 8-byte one as well. |
67 // | 504 // |
68 EhFrameHdr::EhFrameHdr(Code* code) { | 505 EhFrameHdr::EhFrameHdr(int code_size, int eh_frame_size, int cie_size) { |
69 int code_size = code->is_crankshafted() ? code->safepoint_table_offset() | 506 static const int kFdeVersionSize = 1; |
70 : code->instruction_size(); | 507 static const int kFdeEncodingSpecifiersSize = 3; |
71 version_ = 1; | |
72 eh_frame_ptr_encoding_ = DW_EH_PE_sdata4 | DW_EH_PE_pcrel; | |
73 lut_size_encoding_ = DW_EH_PE_udata4; | |
74 lut_entries_encoding_ = DW_EH_PE_sdata4 | DW_EH_PE_datarel; | |
75 | 508 |
76 // .eh_frame pointer and LUT | 509 version_ = kEhFrameHdrVersion; |
77 if (code->has_unwinding_info()) { | |
78 DCHECK_GE(code->unwinding_info_size(), EhFrameHdr::kRecordSize); | |
79 int eh_frame_size = code->unwinding_info_size() - EhFrameHdr::kRecordSize; | |
80 | 510 |
81 offset_to_eh_frame_ = | 511 eh_frame_ptr_encoding_ = EhFrameWriter::kSData4 | EhFrameWriter::kPcRel; |
82 -(eh_frame_size + kVersionSize + kEncodingSpecifiersSize); // A -> D | 512 lut_size_encoding_ = EhFrameWriter::kUData4; |
83 lut_entries_number_ = 1; | 513 lut_entries_encoding_ = EhFrameWriter::kSData4 | EhFrameWriter::kDataRel; |
84 offset_to_procedure_ = -(RoundUp(code_size, 8) + eh_frame_size); // B -> F | 514 offset_to_eh_frame_ = -(eh_frame_size + kFdeVersionSize + |
85 offset_to_fde_ = -(eh_frame_size - kCIESize); // B -> C | 515 kFdeEncodingSpecifiersSize); // A -> D |
86 } else { | 516 lut_entries_number_ = 1; |
87 // Create a dummy table | 517 offset_to_procedure_ = -(RoundUp(code_size, 8) + eh_frame_size); // B -> F |
88 offset_to_eh_frame_ = 0; | 518 offset_to_fde_ = -(eh_frame_size - cie_size); // B -> C |
89 lut_entries_number_ = 0; | 519 } |
90 offset_to_procedure_ = 0; | 520 |
91 offset_to_fde_ = 0; | 521 // static |
92 } | 522 EhFrameHdr EhFrameHdr::CreateEmptyHeader() { |
523 EhFrameHdr dummy_frame; | |
524 dummy_frame.version_ = kEhFrameHdrVersion; | |
525 dummy_frame.eh_frame_ptr_encoding_ = | |
526 EhFrameWriter::kSData4 | EhFrameWriter::kPcRel; | |
527 dummy_frame.lut_size_encoding_ = EhFrameWriter::kUData4; | |
528 dummy_frame.lut_entries_encoding_ = | |
529 EhFrameWriter::kSData4 | EhFrameWriter::kDataRel; | |
530 dummy_frame.offset_to_eh_frame_ = 0; | |
531 dummy_frame.lut_entries_number_ = 0; | |
532 dummy_frame.offset_to_procedure_ = 0; | |
533 dummy_frame.offset_to_fde_ = 0; | |
534 return dummy_frame; | |
93 } | 535 } |
94 | 536 |
95 } // namespace internal | 537 } // namespace internal |
96 } // namespace v8 | 538 } // namespace v8 |
OLD | NEW |