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 <iomanip> | |
| 7 #include <limits> | |
| 8 #include <ostream> | |
|
rmcilroy
2016/06/28 10:37:33
Newline before <iomanip> and after <ostream> (a ne
Stefano Sanfilippo
2016/06/29 15:16:20
Done.
| |
| 6 #include "src/objects-inl.h" | 9 #include "src/objects-inl.h" |
| 7 #include "src/objects.h" | 10 #include "src/objects.h" |
| 8 | 11 |
| 12 #if V8_TARGET_ARCH_X64 | |
| 13 #include "src/x64/eh-frame-x64.h" | |
| 14 #elif V8_TARGET_ARCH_ARM | |
| 15 #include "src/arm/eh-frame-arm.h" | |
| 16 #elif V8_TARGET_ARCH_ARM64 | |
| 17 #include "src/arm64/eh-frame-arm64.h" | |
| 18 #else | |
| 19 | |
| 20 // Dummy placeholders | |
| 21 | |
| 9 namespace v8 { | 22 namespace v8 { |
| 10 namespace internal { | 23 namespace internal { |
| 11 | 24 |
| 12 static const int DW_EH_PE_pcrel = 0x10; | 25 static const int kInitialCFARegister = 0; |
| 13 static const int DW_EH_PE_datarel = 0x30; | 26 static const int kInitialCFAOffset = 0; |
| 14 static const int DW_EH_PE_udata4 = 0x03; | 27 static const int kDataAlignmentFactor = 1; |
| 15 static const int DW_EH_PE_sdata4 = 0x0b; | 28 static const int kInitialStateOffsetInCIE = 0; |
| 16 | 29 |
| 17 const int EhFrameHdr::kCIESize = 0; | 30 static const byte kCIE[8] = {0}; |
| 31 | |
| 32 const char* GetRegisterName(int register_number) { | |
| 33 UNIMPLEMENTED(); | |
| 34 return nullptr; | |
| 35 } | |
| 36 | |
| 37 } // namespace internal | |
| 38 } // namespace v8 | |
| 39 | |
| 40 #endif | |
| 41 | |
| 42 namespace v8 { | |
| 43 namespace internal { | |
| 44 | |
| 45 static_assert(sizeof(kCIE) % kPointerSize == 0, | |
| 46 "CIE must be aligned to pointer size"); | |
| 47 | |
| 48 static const char DW_CFA_nop = 0x00; | |
| 49 | |
| 50 static const byte DW_CFA_advance_loc1 = 0x02; | |
| 51 static const byte DW_CFA_advance_loc2 = 0x03; | |
| 52 static const byte DW_CFA_advance_loc4 = 0x04; | |
| 53 static const byte DW_CFA_same_value = 0x08; | |
| 54 static const byte DW_CFA_def_cfa = 0x0c; | |
| 55 static const byte DW_CFA_def_cfa_register = 0x0d; | |
| 56 static const byte DW_CFA_def_cfa_offset = 0x0e; | |
|
rmcilroy
2016/06/28 10:37:33
Move all these constants to be private constants i
Stefano Sanfilippo
2016/06/29 15:16:20
Done.
| |
| 57 | |
| 58 static const byte DW_EH_PE_pcrel = 0x10; | |
| 59 static const byte DW_EH_PE_datarel = 0x30; | |
| 60 static const byte DW_EH_PE_udata4 = 0x03; | |
| 61 static const byte DW_EH_PE_sdata4 = 0x0b; | |
|
rmcilroy
2016/06/28 10:37:32
These are all unused - either move to the arch spe
Stefano Sanfilippo
2016/06/29 15:16:21
Actually, these are used in the EhFrameHdr ctor be
| |
| 62 | |
| 63 static const byte kEhFrameTerminator[] = {0x00, 0x00, 0x00, 0x00}; | |
| 64 | |
| 65 static const byte kFDEPadding[] = {DW_CFA_nop, DW_CFA_nop, DW_CFA_nop, | |
|
rmcilroy
2016/06/28 10:37:32
Move into finish function where it's used.
Stefano Sanfilippo
2016/06/29 15:16:20
Done.
| |
| 66 DW_CFA_nop, DW_CFA_nop, DW_CFA_nop, | |
| 67 DW_CFA_nop, DW_CFA_nop}; | |
| 68 | |
| 69 const char* GetRegisterName(int register_number); | |
| 70 | |
| 71 const int EhFrameWriter::kCIESize = sizeof(kCIE); | |
|
rmcilroy
2016/06/28 10:37:33
I think you need STATIC_CONST_MEMBER_DEFINITION fo
Stefano Sanfilippo
2016/06/29 15:16:21
Done.
| |
| 72 | |
| 73 EhFrameWriter::EhFrameWriter() | |
| 74 : last_pc_offset_(0), | |
| 75 cfa_register_(kInitialCFARegister), | |
| 76 cfa_offset_(kInitialCFAOffset) { | |
| 77 WriteBytes(&kCIE[0], sizeof(kCIE)); | |
| 78 WriteFDEHeader(); | |
| 79 } | |
| 80 | |
| 81 static const int kFDEHeaderSize = 4 * kInt32Size + 1; | |
|
rmcilroy
2016/06/28 10:37:32
Move this with the rest of the constants.
Stefano Sanfilippo
2016/06/29 15:16:20
Done.
| |
| 82 | |
| 83 void EhFrameWriter::WriteFDEHeader() { | |
| 84 WriteInt32(0); // Placeholder for size of the FDE | |
| 85 WriteInt32(sizeof(kCIE) + kInt32Size); // Backwards offset to the CIE | |
| 86 WriteInt32(0); // Placeholder for pointer to procedure | |
| 87 WriteInt32(0); // Placeholder for size of the procedure | |
| 88 WriteByte(0); // No augmentation data | |
| 89 } | |
| 90 | |
| 91 void EhFrameWriter::AdvanceLocation(int pc_offset) { | |
| 92 DCHECK_GE(pc_offset, last_pc_offset_); | |
| 93 // No way to handle 64bit values, but that's an unrealistic delta anyway. | |
|
rmcilroy
2016/06/28 10:37:32
No need for this comment, the pc_offset is already
Stefano Sanfilippo
2016/06/29 15:16:21
Done.
| |
| 94 uint32_t delta = pc_offset - last_pc_offset_; | |
| 95 | |
| 96 if (delta <= 0x3f) { | |
| 97 WriteByte((1 << 6) | (delta & 0x3f)); // DW_CFA_advance_loc | |
|
rmcilroy
2016/06/28 10:37:33
use a constant instead of 0x3f
Stefano Sanfilippo
2016/06/29 15:16:20
Done.
| |
| 98 } else if (delta <= std::numeric_limits<uint8_t>::max()) { | |
|
rmcilroy
2016/06/28 10:37:32
kMaxUInt8
Stefano Sanfilippo
2016/06/29 15:16:20
Done.
| |
| 99 WriteByte(DW_CFA_advance_loc1); | |
| 100 WriteByte(delta); | |
| 101 } else if (delta <= std::numeric_limits<uint16_t>::max()) { | |
|
rmcilroy
2016/06/28 10:37:32
kMaxUInt16
Stefano Sanfilippo
2016/06/29 15:16:21
Done.
| |
| 102 WriteByte(DW_CFA_advance_loc2); | |
| 103 WriteInt16(delta); | |
| 104 } else { | |
| 105 WriteByte(DW_CFA_advance_loc4); | |
| 106 WriteInt32(delta); | |
| 107 } | |
| 108 | |
| 109 last_pc_offset_ = pc_offset; | |
| 110 } | |
| 111 | |
| 112 void EhFrameWriter::DefineCFAOffset(int cfa_offset) { | |
| 113 DCHECK_GE(cfa_offset, 0); | |
| 114 WriteByte(DW_CFA_def_cfa_offset); | |
| 115 WriteULEB128(cfa_offset); | |
| 116 cfa_offset_ = cfa_offset; | |
| 117 } | |
| 118 | |
| 119 void EhFrameWriter::DefineCFARegister(int code) { | |
| 120 WriteByte(DW_CFA_def_cfa_register); | |
| 121 WriteULEB128(code); | |
| 122 cfa_register_ = code; | |
| 123 } | |
| 124 | |
| 125 void EhFrameWriter::DefineCFARegisterOffset(int code, int cfa_offset) { | |
| 126 WriteByte(DW_CFA_def_cfa); | |
| 127 WriteULEB128(code); | |
| 128 WriteULEB128(cfa_offset); | |
| 129 cfa_offset_ = cfa_offset; | |
| 130 cfa_register_ = code; | |
| 131 } | |
| 132 | |
| 133 // Following the DWARF terminology, this method should be called Offset(), | |
| 134 // but that name is way too generic. | |
|
rmcilroy
2016/06/28 10:37:33
Don't use the DWARF terminology - could you rename
Stefano Sanfilippo
2016/06/29 15:16:20
Comment removed. Please let me know if you think t
| |
| 135 void EhFrameWriter::SaveRegisterToStack(int code, int offset) { | |
| 136 DCHECK_GE(code, 0); | |
| 137 DCHECK_LE(code, 0x3f); | |
| 138 DCHECK_EQ(offset % kDataAlignmentFactor, 0); | |
| 139 | |
| 140 WriteByte((2 << 6) | (code & 0x3f)); // DW_CFA_offset | |
|
rmcilroy
2016/06/28 10:37:33
constant
Stefano Sanfilippo
2016/06/29 15:16:21
Done.
| |
| 141 WriteULEB128(offset / std::abs(kDataAlignmentFactor)); | |
| 142 } | |
| 143 | |
| 144 // This method should be SameValue(), but again that name is too generic. | |
|
rmcilroy
2016/06/28 10:37:32
ditto
Stefano Sanfilippo
2016/06/29 15:16:21
Done.
| |
| 145 void EhFrameWriter::RegisterHasInitialValue(int code) { | |
| 146 DCHECK_GE(code, 0); | |
| 147 WriteByte(DW_CFA_same_value); | |
| 148 WriteULEB128(code); | |
| 149 } | |
| 150 | |
| 151 void EhFrameWriter::Finish(int code_size) { | |
| 152 DCHECK_GE(unwinding_info_.length(), kCIESize); | |
| 153 | |
| 154 // Add padding | |
| 155 int unpadded_fde_size = unwinding_info_.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 DCHECK_LT(fde_padding_size, static_cast<int>(sizeof(kFDEPadding))); | |
| 160 WriteBytes(&kFDEPadding[0], fde_padding_size); | |
| 161 | |
| 162 // Write the size of the FDE now that we know it. | |
| 163 int fde_offset = kCIESize; | |
|
rmcilroy
2016/06/28 10:37:33
Please have these as static consts, and DCHECK tha
Stefano Sanfilippo
2016/06/29 15:16:20
Done.
| |
| 164 PatchInt32(fde_offset, padded_fde_size); | |
| 165 | |
| 166 // Write the size and offset to procedure. | |
| 167 int function_boundaries_offset = fde_offset + 2 * kInt32Size; | |
| 168 PatchInt32(function_boundaries_offset, | |
| 169 -(RoundUp(code_size, 8) + function_boundaries_offset)); | |
| 170 | |
| 171 int code_size_offset = function_boundaries_offset + kInt32Size; | |
| 172 PatchInt32(code_size_offset, code_size); | |
| 173 | |
| 174 // Terminate the .eh_frame. | |
| 175 WriteBytes(&kEhFrameTerminator[0], sizeof(kEhFrameTerminator)); | |
| 176 | |
| 177 // Add .eh_frame_hdr placeholder. | |
| 178 unwinding_info_.AddBlock(0x00, EhFrameHdr::kRecordSize); | |
|
rmcilroy
2016/06/28 10:37:33
Could you not just add the actual EhFrameHdr block
Stefano Sanfilippo
2016/06/29 15:16:21
Yes. This change resulted in a bit of refactoring
| |
| 179 } | |
| 180 | |
| 181 // Remember to call Finish() before GetUnwindingInfo()! | |
|
rmcilroy
2016/06/28 10:37:33
This comment here is useless since it's in the cc
Stefano Sanfilippo
2016/06/29 15:16:20
Done. The only way to know if Finish() was called
| |
| 182 void EhFrameWriter::GetEhFrame(CodeDesc* desc) { | |
| 183 desc->unwinding_info_size = unwinding_info_.length(); | |
| 184 desc->unwinding_info = unwinding_info_.begin(); | |
| 185 } | |
| 186 | |
| 187 void EhFrameWriter::WriteULEB128(uint32_t value) { | |
| 188 do { | |
| 189 byte chunk = value & 0x7f; | |
| 190 value >>= 7; | |
| 191 if (value != 0) chunk |= 0x80; | |
| 192 unwinding_info_.Add(chunk); | |
| 193 } while (value != 0); | |
| 194 } | |
| 195 | |
| 196 static uint32_t DecodeULEB128(const byte* encoded, int* encoded_size) { | |
| 197 const byte* cur = encoded; | |
| 198 uint32_t decoded_value = 0; | |
| 199 | |
| 200 do { | |
| 201 decoded_value <<= 7; | |
| 202 decoded_value += static_cast<uint32_t>(static_cast<unsigned>(*cur & 0x7f)); | |
| 203 } while (*cur++ >= 0x80); | |
| 204 | |
| 205 *encoded_size = static_cast<int>(cur - encoded); | |
| 206 return decoded_value; | |
| 207 } | |
| 208 | |
|
rmcilroy
2016/06/28 10:37:32
#ifdef ENABLE_DISASSEMBLER
Stefano Sanfilippo
2016/06/29 15:16:21
Done.
| |
| 209 namespace { | |
| 210 | |
| 211 class StreamModifiersScope final { | |
| 212 public: | |
| 213 explicit StreamModifiersScope(std::ostream* stream) | |
| 214 : stream_(stream), flags_(stream->flags()) { | |
| 215 DCHECK_NOT_NULL(stream); | |
|
rmcilroy
2016/06/28 10:37:33
No need for this, it will already have exploded in
Stefano Sanfilippo
2016/06/29 15:16:21
Fair enough. Done.
| |
| 216 } | |
| 217 ~StreamModifiersScope() { stream_->flags(flags_); } | |
| 218 | |
| 219 private: | |
| 220 std::ostream* stream_; | |
| 221 std::ios::fmtflags flags_; | |
| 222 }; | |
| 223 | |
| 224 } // namespace | |
| 225 | |
| 226 static void DumpDWARFDirectives(std::ostream& stream, // NOLINT | |
|
rmcilroy
2016/06/28 10:37:32
Put this in the annonymous name space instead of s
Stefano Sanfilippo
2016/06/29 15:16:21
Done.
| |
| 227 const byte* begin, const byte* end) { | |
| 228 StreamModifiersScope modifiers_scope(&stream); | |
| 229 | |
| 230 const byte* cur = begin; | |
| 231 uint32_t offset_in_procedure = 0; | |
| 232 | |
| 233 while (cur != end) { | |
| 234 stream << reinterpret_cast<const void*>(cur) << " "; | |
| 235 | |
| 236 if (((*cur >> 6) & 0xff) == 1) { | |
|
rmcilroy
2016/06/28 10:37:32
Use constants
Stefano Sanfilippo
2016/06/29 15:16:20
Done.
| |
| 237 int value = *cur & 0x3f; | |
| 238 cur += sizeof(byte); | |
| 239 offset_in_procedure += value; | |
| 240 stream << "| pc_offset=" << std::dec << offset_in_procedure | |
| 241 << " (delta=0x" << std::hex << value << ")\n"; | |
| 242 continue; | |
| 243 } | |
| 244 | |
| 245 if (((*cur >> 6) & 0xff) == 2) { | |
|
rmcilroy
2016/06/28 10:37:33
ditto
Stefano Sanfilippo
2016/06/29 15:16:21
Done.
| |
| 246 stream << "| " << GetRegisterName(*cur & 0x3f); | |
| 247 cur += sizeof(byte); | |
| 248 int decoded_size = 0; | |
| 249 int decoded_offset = static_cast<int>(DecodeULEB128(cur, &decoded_size)); | |
| 250 cur += decoded_size; | |
| 251 stream << " saved at cfa" << std::showpos << std::dec | |
| 252 << decoded_offset * kDataAlignmentFactor << '\n'; | |
| 253 continue; | |
| 254 } | |
| 255 | |
| 256 switch (*cur) { | |
| 257 case DW_CFA_advance_loc1: { | |
| 258 cur += sizeof(byte); | |
|
rmcilroy
2016/06/28 10:37:32
You always cur += sizeof(byte) - just do it once a
Stefano Sanfilippo
2016/06/29 15:16:21
Done.
| |
| 259 unsigned value = *reinterpret_cast<const uint8_t*>(cur); | |
| 260 cur += sizeof(uint8_t); | |
| 261 offset_in_procedure += value; | |
| 262 stream << "| pc_offset=" << std::dec << offset_in_procedure | |
| 263 << " (delta=0x" << std::hex << value << ")\n"; | |
| 264 break; | |
| 265 } | |
| 266 case DW_CFA_advance_loc2: { | |
| 267 cur += sizeof(byte); | |
| 268 uint16_t value = *reinterpret_cast<const uint16_t*>(cur); | |
|
rmcilroy
2016/06/28 10:37:33
This won't work on machines that don't support una
Stefano Sanfilippo
2016/06/29 15:16:21
Done.
| |
| 269 cur += sizeof(uint16_t); | |
| 270 offset_in_procedure += value; | |
| 271 stream << "| pc_offset=" << std::dec << offset_in_procedure | |
| 272 << " (delta=0x" << std::hex << value << ")\n"; | |
| 273 break; | |
| 274 } | |
| 275 case DW_CFA_advance_loc4: { | |
| 276 cur += sizeof(byte); | |
| 277 uint32_t value = *reinterpret_cast<const uint32_t*>(cur); | |
| 278 offset_in_procedure += value; | |
| 279 cur += sizeof(uint32_t); | |
| 280 stream << "| pc_offset=" << std::dec << offset_in_procedure | |
| 281 << " (delta=0x" << std::hex << value << ")\n"; | |
| 282 break; | |
| 283 } | |
| 284 case DW_CFA_def_cfa: { | |
| 285 cur += sizeof(byte); | |
| 286 int decoded_size = 0; | |
| 287 int cfa_register = DecodeULEB128(cur, &decoded_size); | |
| 288 cur += decoded_size; | |
| 289 int cfa_initial_offset = DecodeULEB128(cur, &decoded_size); | |
| 290 cur += decoded_size; | |
| 291 stream << "| cfa_register=" << GetRegisterName(cfa_register) | |
| 292 << ", cfa_offset=0x" << std::hex << cfa_initial_offset << '\n'; | |
| 293 break; | |
| 294 } | |
| 295 case DW_CFA_def_cfa_offset: { | |
| 296 cur += sizeof(byte); | |
| 297 int decoded_size = 0; | |
| 298 stream << "| cfa_offset=0x" << std::hex | |
| 299 << DecodeULEB128(cur, &decoded_size) << '\n'; | |
| 300 cur += decoded_size; | |
| 301 break; | |
| 302 } | |
| 303 case DW_CFA_def_cfa_register: { | |
| 304 cur += sizeof(byte); | |
| 305 int decoded_size = 0; | |
| 306 stream << "| cfa_register=" | |
| 307 << GetRegisterName(DecodeULEB128(cur, &decoded_size)) << '\n'; | |
| 308 cur += decoded_size; | |
| 309 break; | |
| 310 } | |
| 311 case DW_CFA_same_value: { | |
| 312 cur += sizeof(byte); | |
| 313 int decoded_size = 0; | |
| 314 stream << "| " << GetRegisterName(DecodeULEB128(cur, &decoded_size)) | |
| 315 << " to initial value\n"; | |
| 316 cur += decoded_size; | |
| 317 break; | |
| 318 } | |
| 319 case DW_CFA_nop: | |
| 320 cur += sizeof(byte); | |
| 321 stream << "| nop\n"; | |
| 322 break; | |
| 323 default: | |
| 324 stream << "| UNKNOWN BYTECODE 0x" << std::hex << std::setw(2) | |
| 325 << std::setfill('0') << static_cast<unsigned>(*cur) << '\n'; | |
|
rmcilroy
2016/06/28 10:37:32
Just the UNREACHABLE here, no need to print the un
Stefano Sanfilippo
2016/06/29 15:16:21
Done.
| |
| 326 UNREACHABLE(); | |
| 327 return; | |
| 328 } | |
| 329 } | |
| 330 } | |
| 331 | |
| 332 void EhFrameWriter::DisassembleToStream(std::ostream& stream, // NOLINT | |
| 333 const byte* start, const byte* end) { | |
| 334 const byte* cie_directives_start = start + kInitialStateOffsetInCIE; | |
| 335 const byte* cie_directives_end = start + sizeof(kCIE); | |
| 336 DCHECK_LE(cie_directives_start, cie_directives_end); | |
| 337 | |
| 338 const byte* fde_start = start + sizeof(kCIE); | |
| 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 = fde_start + 2 * kInt32Size; | |
|
rmcilroy
2016/06/28 10:37:32
Constant offsets
Stefano Sanfilippo
2016/06/29 15:16:20
Done.
| |
| 344 int32_t procedure_offset = | |
| 345 *reinterpret_cast<const int32_t*>(procedure_offset_address); | |
| 346 | |
| 347 const byte* procedure_size_address = fde_start + 3 * kInt32Size; | |
|
rmcilroy
2016/06/28 10:37:32
ditto
Stefano Sanfilippo
2016/06/29 15:16:21
Done.
| |
| 348 uint32_t procedure_size = | |
| 349 *reinterpret_cast<const uint32_t*>(procedure_size_address); | |
| 350 | |
| 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 = fde_start + kFDEHeaderSize; | |
| 358 const byte* fde_directives_end = | |
| 359 end - EhFrameHdr::kRecordSize - sizeof(kEhFrameTerminator); | |
| 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 + sizeof(kEhFrameTerminator); | |
| 370 stream << reinterpret_cast<const void*>(eh_frame_hdr_start) | |
| 371 << " .eh_frame_hdr: placeholder\n"; | |
|
rmcilroy
2016/06/28 10:37:32
Why bother printing the terminator and placeholder
Stefano Sanfilippo
2016/06/29 15:16:20
I believe it might be useful to check the exact la
| |
| 372 } | |
| 18 | 373 |
| 19 static const int kVersionSize = 1; | 374 static const int kVersionSize = 1; |
| 20 static const int kEncodingSpecifiersSize = 3; | 375 static const int kEncodingSpecifiersSize = 3; |
|
rmcilroy
2016/06/28 10:37:32
Move with other constants
Stefano Sanfilippo
2016/06/29 15:16:21
Done.
| |
| 21 | 376 |
| 22 // | 377 // |
| 23 // In order to calculate offsets in the .eh_frame_hdr, we must know the layout | 378 // 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: | 379 // of the DSO generated by perf inject, which is assumed to be the following: |
| 25 // | 380 // |
| 26 // | ... | | | 381 // | ... | | |
| 27 // +---------------+ <-- (F) --- | Larger offsets in file | 382 // +---------------+ <-- (F) --- | Larger offsets in file |
| 28 // | | ^ | | 383 // | | ^ | |
| 29 // | Instructions | | .text v | 384 // | Instructions | | .text v |
| 30 // | | v | 385 // | | v |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 75 | 430 |
| 76 // .eh_frame pointer and LUT | 431 // .eh_frame pointer and LUT |
| 77 if (code->has_unwinding_info()) { | 432 if (code->has_unwinding_info()) { |
| 78 DCHECK_GE(code->unwinding_info_size(), EhFrameHdr::kRecordSize); | 433 DCHECK_GE(code->unwinding_info_size(), EhFrameHdr::kRecordSize); |
| 79 int eh_frame_size = code->unwinding_info_size() - EhFrameHdr::kRecordSize; | 434 int eh_frame_size = code->unwinding_info_size() - EhFrameHdr::kRecordSize; |
| 80 | 435 |
| 81 offset_to_eh_frame_ = | 436 offset_to_eh_frame_ = |
| 82 -(eh_frame_size + kVersionSize + kEncodingSpecifiersSize); // A -> D | 437 -(eh_frame_size + kVersionSize + kEncodingSpecifiersSize); // A -> D |
| 83 lut_entries_number_ = 1; | 438 lut_entries_number_ = 1; |
| 84 offset_to_procedure_ = -(RoundUp(code_size, 8) + eh_frame_size); // B -> F | 439 offset_to_procedure_ = -(RoundUp(code_size, 8) + eh_frame_size); // B -> F |
| 85 offset_to_fde_ = -(eh_frame_size - kCIESize); // B -> C | 440 offset_to_fde_ = -(eh_frame_size - EhFrameWriter::kCIESize); // B -> C |
| 86 } else { | 441 } else { |
| 87 // Create a dummy table | 442 // Create a dummy table |
| 88 offset_to_eh_frame_ = 0; | 443 offset_to_eh_frame_ = 0; |
| 89 lut_entries_number_ = 0; | 444 lut_entries_number_ = 0; |
| 90 offset_to_procedure_ = 0; | 445 offset_to_procedure_ = 0; |
| 91 offset_to_fde_ = 0; | 446 offset_to_fde_ = 0; |
| 92 } | 447 } |
| 93 } | 448 } |
| 94 | 449 |
| 95 } // namespace internal | 450 } // namespace internal |
| 96 } // namespace v8 | 451 } // namespace v8 |
| OLD | NEW |