Chromium Code Reviews| 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 V8_TARGET_ARCH_X64 | |
| 11 #include "src/x64/eh-frame-x64.h" | |
| 12 #elif V8_TARGET_ARCH_ARM | |
| 13 #include "src/arm/eh-frame-arm.h" | |
| 14 #elif V8_TARGET_ARCH_ARM64 | |
| 15 #include "src/arm64/eh-frame-arm64.h" | |
| 16 #else | |
| 17 | |
| 18 // Dummy placeholders | |
| 8 | 19 |
| 9 namespace v8 { | 20 namespace v8 { |
| 10 namespace internal { | 21 namespace internal { |
| 11 | 22 |
| 12 static const int DW_EH_PE_pcrel = 0x10; | 23 static const Register kInitialBaseRegister = {Register::kCode_no_reg}; |
| 13 static const int DW_EH_PE_datarel = 0x30; | 24 static const int kInitialBaseOffset = 0; |
| 14 static const int DW_EH_PE_udata4 = 0x03; | 25 static const int kDataAlignmentFactor = 1; |
| 15 static const int DW_EH_PE_sdata4 = 0x0b; | 26 static const byte kCIE[8] = {0}; |
| 16 | 27 #if ENABLE_DISASSEMBLER |
| 17 const int EhFrameHdr::kCIESize = 0; | 28 static const int kInitialStateOffsetInCIE = 0; |
| 18 | 29 #endif |
| 19 static const int kVersionSize = 1; | 30 |
| 20 static const int kEncodingSpecifiersSize = 3; | 31 const char* DwarfRegisterCodeToString(int) { |
| 32 UNIMPLEMENTED(); | |
| 33 return nullptr; | |
| 34 } | |
| 35 | |
| 36 int RegisterToDwarfCode(Register) { | |
| 37 UNIMPLEMENTED(); | |
| 38 return -1; | |
| 39 } | |
| 40 | |
| 41 } // namespace internal | |
| 42 } // namespace v8 | |
| 43 | |
| 44 #endif | |
| 45 | |
| 46 namespace v8 { | |
| 47 namespace internal { | |
| 48 | |
| 49 STATIC_CONST_MEMBER_DEFINITION const uint32_t EhFrameWriter::kInt32Placeholder; | |
| 50 | |
| 51 STATIC_CONST_MEMBER_DEFINITION const int EhFrameWriter::kCIESize = sizeof(kCIE); | |
| 52 static_assert(EhFrameWriter::kCIESize % kPointerSize == 0, | |
| 53 "CIE size must be a multiple of pointer size"); | |
| 54 | |
| 55 STATIC_CONST_MEMBER_DEFINITION const int EhFrameWriter::kFDEOffset = kCIESize; | |
| 56 STATIC_CONST_MEMBER_DEFINITION const int | |
| 57 EhFrameWriter::kProcedureAddressOffset = kFDEOffset + 2 * kInt32Size; | |
|
rmcilroy
2016/06/30 15:23:10
I think it would be better if these were relative
Stefano Sanfilippo
2016/07/04 18:21:14
Done.
| |
| 58 STATIC_CONST_MEMBER_DEFINITION const int EhFrameWriter::kProcedureSizeOffset = | |
| 59 kFDEOffset + 3 * kInt32Size; | |
| 60 #ifdef ENABLE_DISASSEMBLER | |
| 61 STATIC_CONST_MEMBER_DEFINITION const int EhFrameWriter::kFDEDirectivesOffset = | |
|
rmcilroy
2016/06/30 15:23:10
This is only used in DisassembleToStream, just def
Stefano Sanfilippo
2016/07/04 18:21:14
Done.
| |
| 62 kFDEOffset + 4 * kInt32Size + 1; | |
| 63 #endif | |
| 64 | |
| 65 const char* DwarfRegisterCodeToString(int code); | |
| 66 int RegisterToDwarfCode(Register name); | |
|
rmcilroy
2016/06/30 15:23:10
these should be methods in EhFrameWriter
Stefano Sanfilippo
2016/07/04 18:21:14
Done.
| |
| 67 | |
| 68 EhFrameWriter::EhFrameWriter() | |
| 69 : last_pc_offset_(0), | |
| 70 #if DEBUG | |
| 71 eh_frame_finalised_(false), | |
| 72 #endif | |
| 73 base_register_(kInitialBaseRegister), | |
| 74 base_offset_(kInitialBaseOffset) { | |
| 75 WriteBytes(&kCIE[0], sizeof(kCIE)); | |
| 76 WriteFDEHeader(); | |
| 77 } | |
| 78 | |
| 79 void EhFrameWriter::WriteFDEHeader() { | |
| 80 DCHECK_EQ(eh_frame_offset(), kFDEOffset); | |
| 81 WriteInt32(kInt32Placeholder); // Placeholder for size of the FDE | |
| 82 WriteInt32(kCIESize + kInt32Size); // Backwards offset to the CIE | |
| 83 DCHECK_EQ(eh_frame_offset(), kProcedureAddressOffset); | |
| 84 WriteInt32(kInt32Placeholder); // Placeholder for pointer to procedure | |
| 85 DCHECK_EQ(eh_frame_offset(), kProcedureSizeOffset); | |
| 86 WriteInt32(kInt32Placeholder); // Placeholder for size of the procedure | |
| 87 WriteByte(0); // No augmentation data | |
| 88 } | |
| 89 | |
| 90 void EhFrameWriter::AdvanceLocation(int pc_offset) { | |
| 91 DCHECK_GE(pc_offset, last_pc_offset_); | |
| 92 uint32_t delta = pc_offset - last_pc_offset_; | |
| 93 | |
| 94 if (delta <= kLocationMask) { | |
| 95 WriteByte((kLocationTag << kLocationMaskSize) | (delta & kLocationMask)); | |
| 96 } else if (delta <= kMaxUInt8) { | |
| 97 WriteByte(kAdvanceLoc1); | |
| 98 WriteByte(delta); | |
| 99 } else if (delta <= kMaxUInt16) { | |
| 100 WriteByte(kAdvanceLoc2); | |
| 101 WriteInt16(delta); | |
| 102 } else { | |
| 103 WriteByte(kAdvanceLoc4); | |
| 104 WriteInt32(delta); | |
| 105 } | |
| 106 | |
| 107 last_pc_offset_ = pc_offset; | |
| 108 } | |
| 109 | |
| 110 void EhFrameWriter::DefineBaseAddressOffset(int base_offset) { | |
| 111 DCHECK_GE(base_offset, 0); | |
| 112 WriteByte(kDefCFAOffset); | |
| 113 WriteULEB128(base_offset); | |
| 114 base_offset_ = base_offset; | |
| 115 } | |
| 116 | |
| 117 void EhFrameWriter::DefineBaseAddressRegister(Register name) { | |
| 118 int code = RegisterToDwarfCode(name); | |
| 119 WriteByte(kDefCFARegister); | |
| 120 WriteULEB128(code); | |
| 121 base_register_ = name; | |
| 122 } | |
| 123 | |
| 124 void EhFrameWriter::DefineBaseAddressRegisterOffset(Register name, | |
| 125 int base_offset) { | |
| 126 int code = RegisterToDwarfCode(name); | |
| 127 WriteByte(kDefCFA); | |
| 128 WriteULEB128(code); | |
| 129 WriteULEB128(base_offset); | |
| 130 base_offset_ = base_offset; | |
| 131 base_register_ = name; | |
| 132 } | |
| 133 | |
| 134 void EhFrameWriter::SaveRegisterToStack(Register name, int offset) { | |
| 135 int code = RegisterToDwarfCode(name); | |
| 136 DCHECK_GE(code, 0); | |
| 137 DCHECK_LE(code, kSavedRegisterMask); | |
| 138 DCHECK_EQ(offset % kDataAlignmentFactor, 0); | |
| 139 WriteByte((kSavedRegisterTag << kSavedRegisterMaskSize) | | |
| 140 (code & kSavedRegisterMask)); | |
| 141 WriteULEB128(offset / std::abs(kDataAlignmentFactor)); | |
| 142 } | |
| 143 | |
| 144 void EhFrameWriter::RegisterIsValid(Register name) { | |
| 145 int code = RegisterToDwarfCode(name); | |
| 146 DCHECK_GE(code, 0); | |
| 147 WriteByte(kSameValue); | |
| 148 WriteULEB128(code); | |
| 149 } | |
| 150 | |
| 151 void EhFrameWriter::Finish(int code_size) { | |
| 152 DCHECK_GE(eh_frame_buffer_.length(), kCIESize); | |
| 153 | |
|
rmcilroy
2016/06/30 15:23:10
DCHECK(!eh_frame_finalized_)
Stefano Sanfilippo
2016/07/04 18:21:14
Done.
| |
| 154 // Add padding | |
| 155 int unpadded_fde_size = eh_frame_buffer_.length() - kCIESize; | |
| 156 int padded_fde_size = RoundUp(unpadded_fde_size, 8); | |
| 157 int fde_padding_size = padded_fde_size - unpadded_fde_size; | |
| 158 | |
| 159 static const byte kFDEPadding[] = {kNop, kNop, kNop, kNop, | |
| 160 kNop, kNop, kNop, kNop}; | |
| 161 DCHECK_LT(fde_padding_size, static_cast<int>(sizeof(kFDEPadding))); | |
| 162 WriteBytes(&kFDEPadding[0], fde_padding_size); | |
| 163 | |
| 164 // Write the size of the FDE now that we know it. | |
| 165 PatchInt32(kFDEOffset, padded_fde_size); | |
| 166 | |
| 167 // Write the size and offset to procedure. | |
| 168 PatchInt32(kProcedureAddressOffset, | |
| 169 -(RoundUp(code_size, 8) + kProcedureAddressOffset)); | |
| 170 PatchInt32(kProcedureSizeOffset, code_size); | |
| 171 | |
| 172 // Terminate the .eh_frame. | |
| 173 static const byte kEhFrameTerminator[kEhFrameTerminatorSize] = {0}; | |
| 174 WriteBytes(&kEhFrameTerminator[0], kEhFrameTerminatorSize); | |
| 175 | |
| 176 // Write .eh_frame_hdr | |
| 177 EhFrameHdr eh_frame_hdr(code_size, eh_frame_offset()); | |
| 178 WriteBytes(reinterpret_cast<const byte*>(&eh_frame_hdr), | |
| 179 EhFrameHdr::kRecordSize); | |
| 180 | |
| 181 #if DEBUG | |
| 182 eh_frame_finalised_ = true; | |
| 183 #endif | |
| 184 } | |
| 185 | |
| 186 void EhFrameWriter::GetEhFrame(CodeDesc* desc) { | |
| 187 DCHECK(eh_frame_finalised_); | |
| 188 desc->unwinding_info_size = eh_frame_buffer_.length(); | |
| 189 desc->unwinding_info = eh_frame_buffer_.begin(); | |
| 190 } | |
| 191 | |
| 192 void EhFrameWriter::WriteULEB128(uint32_t value) { | |
| 193 do { | |
| 194 byte chunk = value & 0x7f; | |
| 195 value >>= 7; | |
| 196 if (value != 0) chunk |= 0x80; | |
| 197 eh_frame_buffer_.Add(chunk); | |
| 198 } while (value != 0); | |
| 199 } | |
| 200 | |
| 201 #ifdef ENABLE_DISASSEMBLER | |
| 202 | |
| 203 namespace { | |
| 204 | |
| 205 uint32_t DecodeULEB128(const byte* encoded, int* encoded_size) { | |
| 206 const byte* cur = encoded; | |
| 207 uint32_t decoded_value = 0; | |
| 208 | |
| 209 do { | |
| 210 decoded_value <<= 7; | |
| 211 decoded_value += static_cast<uint32_t>(static_cast<unsigned>(*cur & 0x7f)); | |
| 212 } while (*cur++ >= 0x80); | |
| 213 | |
| 214 *encoded_size = static_cast<int>(cur - encoded); | |
| 215 return decoded_value; | |
| 216 } | |
| 217 | |
| 218 class StreamModifiersScope final { | |
| 219 public: | |
| 220 explicit StreamModifiersScope(std::ostream* stream) | |
| 221 : stream_(stream), flags_(stream->flags()) {} | |
| 222 ~StreamModifiersScope() { stream_->flags(flags_); } | |
| 223 | |
| 224 private: | |
| 225 std::ostream* stream_; | |
| 226 std::ios::fmtflags flags_; | |
| 227 }; | |
| 228 | |
| 229 } // namespace | |
| 230 | |
| 231 // static | |
| 232 void EhFrameWriter::DumpDWARFDirectives(std::ostream& stream, // NOLINT | |
| 233 const byte* begin, const byte* end) { | |
| 234 StreamModifiersScope modifiers_scope(&stream); | |
| 235 | |
| 236 const byte* cur = begin; | |
| 237 uint32_t offset_in_procedure = 0; | |
| 238 | |
| 239 while (cur != end) { | |
| 240 stream << reinterpret_cast<const void*>(cur) << " "; | |
| 241 | |
| 242 if (((*cur >> kLocationMaskSize) & 0xff) == kLocationTag) { | |
| 243 int value = *cur & kLocationMask; | |
| 244 cur += sizeof(byte); | |
| 245 offset_in_procedure += value; | |
| 246 stream << "| pc_offset=" << std::dec << offset_in_procedure | |
| 247 << " (delta=0x" << std::hex << value << ")\n"; | |
| 248 continue; | |
| 249 } | |
| 250 | |
| 251 if (((*cur >> kSavedRegisterMaskSize) & 0xff) == kSavedRegisterTag) { | |
| 252 stream << "| " << DwarfRegisterCodeToString(*cur & kLocationMask); | |
| 253 cur += sizeof(byte); | |
| 254 int decoded_size = 0; | |
| 255 int decoded_offset = static_cast<int>(DecodeULEB128(cur, &decoded_size)); | |
| 256 cur += decoded_size; | |
| 257 stream << " saved at base" << std::showpos << std::dec | |
| 258 << decoded_offset * kDataAlignmentFactor << '\n'; | |
| 259 continue; | |
| 260 } | |
| 261 | |
| 262 uint8_t bytecode = *cur; | |
| 263 cur += sizeof(byte); | |
| 264 | |
| 265 switch (bytecode) { | |
| 266 case kAdvanceLoc1: { | |
| 267 unsigned value = *reinterpret_cast<const uint8_t*>(cur); | |
| 268 cur += sizeof(uint8_t); | |
| 269 offset_in_procedure += value; | |
| 270 stream << "| pc_offset=" << std::dec << offset_in_procedure | |
| 271 << " (delta=0x" << std::hex << value << ")\n"; | |
| 272 break; | |
| 273 } | |
| 274 case kAdvanceLoc2: { | |
| 275 uint16_t value = ReadUnalignedUInt16(cur); | |
| 276 cur += sizeof(uint16_t); | |
| 277 offset_in_procedure += value; | |
| 278 stream << "| pc_offset=" << std::dec << offset_in_procedure | |
| 279 << " (delta=0x" << std::hex << value << ")\n"; | |
| 280 break; | |
| 281 } | |
| 282 case kAdvanceLoc4: { | |
| 283 uint32_t value = ReadUnalignedUInt32(cur); | |
| 284 offset_in_procedure += value; | |
| 285 cur += sizeof(uint32_t); | |
| 286 stream << "| pc_offset=" << std::dec << offset_in_procedure | |
| 287 << " (delta=0x" << std::hex << value << ")\n"; | |
| 288 break; | |
| 289 } | |
| 290 case kDefCFA: { | |
| 291 int decoded_size = 0; | |
| 292 int base_register = DecodeULEB128(cur, &decoded_size); | |
| 293 cur += decoded_size; | |
| 294 int base_offset = DecodeULEB128(cur, &decoded_size); | |
| 295 cur += decoded_size; | |
| 296 stream << "| base_register=" << DwarfRegisterCodeToString(base_register) | |
| 297 << ", base_offset=0x" << std::hex << base_offset << '\n'; | |
| 298 break; | |
| 299 } | |
| 300 case kDefCFAOffset: { | |
| 301 int decoded_size = 0; | |
| 302 stream << "| base_offset=0x" << std::hex | |
| 303 << DecodeULEB128(cur, &decoded_size) << '\n'; | |
| 304 cur += decoded_size; | |
| 305 break; | |
| 306 } | |
| 307 case kDefCFARegister: { | |
| 308 int decoded_size = 0; | |
| 309 stream << "| base_register=" | |
| 310 << DwarfRegisterCodeToString(DecodeULEB128(cur, &decoded_size)) | |
| 311 << '\n'; | |
| 312 cur += decoded_size; | |
| 313 break; | |
| 314 } | |
| 315 case kSameValue: { | |
| 316 int decoded_size = 0; | |
| 317 stream << "| " | |
| 318 << DwarfRegisterCodeToString(DecodeULEB128(cur, &decoded_size)) | |
| 319 << " to initial value\n"; | |
| 320 cur += decoded_size; | |
| 321 break; | |
| 322 } | |
| 323 case kNop: | |
| 324 stream << "| nop\n"; | |
| 325 break; | |
| 326 default: | |
| 327 UNREACHABLE(); | |
| 328 return; | |
| 329 } | |
| 330 } | |
| 331 } | |
| 332 | |
| 333 // static | |
| 334 void EhFrameWriter::DisassembleToStream(std::ostream& stream, // NOLINT | |
| 335 const byte* start, const byte* end) { | |
| 336 const byte* cie_directives_start = start + kInitialStateOffsetInCIE; | |
| 337 const byte* cie_directives_end = start + kCIESize; | |
| 338 DCHECK_LE(cie_directives_start, cie_directives_end); | |
| 339 | |
| 340 stream << reinterpret_cast<const void*>(start) << " .eh_frame: CIE\n"; | |
| 341 DumpDWARFDirectives(stream, cie_directives_start, cie_directives_end); | |
| 342 | |
| 343 const byte* procedure_offset_address = start + kProcedureAddressOffset; | |
| 344 int32_t procedure_offset = | |
| 345 ReadUnalignedValue<int32_t>(procedure_offset_address); | |
| 346 | |
| 347 const byte* procedure_size_address = start + kProcedureSizeOffset; | |
| 348 uint32_t procedure_size = ReadUnalignedUInt32(procedure_size_address); | |
| 349 | |
| 350 const byte* fde_start = start + kCIESize; | |
| 351 stream << reinterpret_cast<const void*>(fde_start) << " .eh_frame: FDE\n" | |
| 352 << reinterpret_cast<const void*>(procedure_offset_address) | |
| 353 << " | procedure offset=" << procedure_offset << '\n' | |
| 354 << reinterpret_cast<const void*>(procedure_size_address) | |
| 355 << " | procedure size=" << procedure_size << '\n'; | |
| 356 | |
| 357 const byte* fde_directives_start = start + kFDEDirectivesOffset; | |
| 358 const byte* fde_directives_end = | |
| 359 end - EhFrameHdr::kRecordSize - kEhFrameTerminatorSize; | |
| 360 DCHECK_LE(fde_directives_start, fde_directives_end); | |
| 361 | |
| 362 DumpDWARFDirectives(stream, fde_directives_start, fde_directives_end); | |
| 363 | |
| 364 const byte* fde_terminator_start = fde_directives_end; | |
| 365 stream << reinterpret_cast<const void*>(fde_terminator_start) | |
| 366 << " .eh_frame: terminator\n"; | |
| 367 | |
| 368 const byte* eh_frame_hdr_start = | |
| 369 fde_terminator_start + kEhFrameTerminatorSize; | |
| 370 stream << reinterpret_cast<const void*>(eh_frame_hdr_start) | |
| 371 << " .eh_frame_hdr: placeholder\n"; | |
| 372 } | |
| 373 | |
| 374 #endif | |
| 21 | 375 |
| 22 // | 376 // |
| 23 // In order to calculate offsets in the .eh_frame_hdr, we must know the layout | 377 // 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: | 378 // of the DSO generated by perf inject, which is assumed to be the following: |
| 25 // | 379 // |
| 26 // | ... | | | 380 // | ... | | |
| 27 // +---------------+ <-- (F) --- | Larger offsets in file | 381 // +---------------+ <-- (F) --- | Larger offsets in file |
| 28 // | | ^ | | 382 // | | ^ | |
| 29 // | Instructions | | .text v | 383 // | Instructions | | .text v |
| 30 // | | v | 384 // | | v |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 44 // | version | ^ | 398 // | version | ^ |
| 45 // +---------------+ | | 399 // +---------------+ | |
| 46 // | encoding | | | 400 // | encoding | | |
| 47 // | specifiers | | | 401 // | specifiers | | |
| 48 // +---------------+ <---(A) | .eh_frame_hdr | 402 // +---------------+ <---(A) | .eh_frame_hdr |
| 49 // | offset to | | | 403 // | offset to | | |
| 50 // | .eh_frame | | | 404 // | .eh_frame | | |
| 51 // +---------------+ | | 405 // +---------------+ | |
| 52 // | ... | ... | 406 // | ... | ... |
| 53 // | 407 // |
| 54 // (F) is aligned at a 16-byte boundary. | 408 // (F) is aligned to a 16-byte boundary. |
| 55 // (D) is aligned at a 8-byte boundary. | 409 // (D) is aligned to a 8-byte boundary. |
| 56 // (B) is aligned at a 4-byte boundary. | 410 // (B) is aligned to a 4-byte boundary. |
| 57 // (E), (C) and (A) have no alignment requirements. | 411 // (C) is aligned to an addressing unit size boundary. |
| 412 // (E) and (A) have no alignment requirements. | |
| 58 // | 413 // |
| 59 // The distance between (A) and (B) is 4 bytes. | 414 // The distance between (A) and (B) is 4 bytes. |
| 60 // | 415 // |
| 61 // The size of the .eh_frame is required to be a multiple of the pointer size, | 416 // 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 | 417 // means that (B) will be naturally aligned to a 4-byte boundary on all the |
| 63 // the architectures we support. | 418 // architectures we support. |
| 64 // | 419 // |
| 65 // Because (E) has no alignment requirements, there is padding between (E) and | 420 // 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. | 421 // (D). (F) is aligned at a 16-byte boundary, thus to a 8-byte one as well. |
| 67 // | 422 // |
| 68 EhFrameHdr::EhFrameHdr(Code* code) { | 423 EhFrameHdr::EhFrameHdr(int code_size, int eh_frame_size) { |
| 69 int code_size = code->is_crankshafted() ? code->safepoint_table_offset() | 424 version_ = kEhFrameHdrVersion; |
| 70 : code->instruction_size(); | |
| 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 | 425 |
| 76 // .eh_frame pointer and LUT | 426 eh_frame_ptr_encoding_ = kSData4 | kPcRel; |
| 77 if (code->has_unwinding_info()) { | 427 lut_size_encoding_ = kUData4; |
| 78 DCHECK_GE(code->unwinding_info_size(), EhFrameHdr::kRecordSize); | 428 lut_entries_encoding_ = kSData4 | kDataRel; |
| 79 int eh_frame_size = code->unwinding_info_size() - EhFrameHdr::kRecordSize; | |
| 80 | 429 |
| 81 offset_to_eh_frame_ = | 430 offset_to_eh_frame_ = -(eh_frame_size + kFDEVersionSize + |
| 82 -(eh_frame_size + kVersionSize + kEncodingSpecifiersSize); // A -> D | 431 kFDEEncodingSpecifiersSize); // A -> D |
| 83 lut_entries_number_ = 1; | 432 lut_entries_number_ = 1; |
| 84 offset_to_procedure_ = -(RoundUp(code_size, 8) + eh_frame_size); // B -> F | 433 offset_to_procedure_ = -(RoundUp(code_size, 8) + eh_frame_size); // B -> F |
| 85 offset_to_fde_ = -(eh_frame_size - kCIESize); // B -> C | 434 offset_to_fde_ = -(eh_frame_size - EhFrameWriter::kCIESize); // B -> C |
| 86 } else { | 435 } |
| 87 // Create a dummy table | 436 |
| 88 offset_to_eh_frame_ = 0; | 437 // static |
| 89 lut_entries_number_ = 0; | 438 EhFrameHdr EhFrameHdr::MakeDummy() { |
| 90 offset_to_procedure_ = 0; | 439 EhFrameHdr dummy_frame; |
| 91 offset_to_fde_ = 0; | 440 dummy_frame.version_ = kEhFrameHdrVersion; |
| 92 } | 441 dummy_frame.eh_frame_ptr_encoding_ = kSData4 | kPcRel; |
| 442 dummy_frame.lut_size_encoding_ = kUData4; | |
| 443 dummy_frame.lut_entries_encoding_ = kSData4 | kDataRel; | |
| 444 dummy_frame.offset_to_eh_frame_ = 0; | |
| 445 dummy_frame.lut_entries_number_ = 0; | |
| 446 dummy_frame.offset_to_procedure_ = 0; | |
| 447 dummy_frame.offset_to_fde_ = 0; | |
| 448 return dummy_frame; | |
| 93 } | 449 } |
| 94 | 450 |
| 95 } // namespace internal | 451 } // namespace internal |
| 96 } // namespace v8 | 452 } // namespace v8 |
| OLD | NEW |