// Copyright 2016 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "src/eh-frame.h" #include "src/objects-inl.h" #include "src/objects.h" namespace v8 { namespace internal { static const int DW_EH_PE_pcrel = 0x10; static const int DW_EH_PE_datarel = 0x30; static const int DW_EH_PE_udata4 = 0x03; static const int DW_EH_PE_sdata4 = 0x0b; const int EhFrameHdr::kCIESize = 0; static const int kVersionSize = 1; static const int kEncodingSpecifiersSize = 3; // // In order to calculate offsets in the .eh_frame_hdr, we must know the layout // of the DSO generated by perf inject, which is assumed to be the following: // // | ... | | // +---------------+ <-- (F) --- | Larger offsets in file // | | ^ | // | Instructions | | .text v // | | v // +---------------+ <-- (E) --- // |///////////////| // |////Padding////| // |///////////////| // +---------------+ <-- (D) --- // | | ^ // | CIE | | // | | | // +---------------+ <-- (C) | .eh_frame // | | | // | FDE | | // | | v // +---------------+ <-- (B) --- // | version | ^ // +---------------+ | // | encoding | | // | specifiers | | // +---------------+ <---(A) | .eh_frame_hdr // | offset to | | // | .eh_frame | | // +---------------+ | // | ... | ... // // (F) is aligned at a 16-byte boundary. // (D) is aligned at a 8-byte boundary. // (B) is aligned at a 4-byte boundary. // (E), (C) and (A) have no alignment requirements. // // The distance between (A) and (B) is 4 bytes. // // The size of the .eh_frame is required to be a multiple of the pointer size, // which means that (B) will be naturally aligned to a 4-byte boundary on all // the architectures we support. // // Because (E) has no alignment requirements, there is padding between (E) and // (D). (F) is aligned at a 16-byte boundary, thus to a 8-byte one as well. // EhFrameHdr::EhFrameHdr(Code* code) { int code_size = code->is_crankshafted() ? code->safepoint_table_offset() : code->instruction_size(); version_ = 1; eh_frame_ptr_encoding_ = DW_EH_PE_sdata4 | DW_EH_PE_pcrel; lut_size_encoding_ = DW_EH_PE_udata4; lut_entries_encoding_ = DW_EH_PE_sdata4 | DW_EH_PE_datarel; // .eh_frame pointer and LUT if (code->has_unwinding_info()) { DCHECK_GE(code->unwinding_info_size(), EhFrameHdr::kRecordSize); int eh_frame_size = code->unwinding_info_size() - EhFrameHdr::kRecordSize; offset_to_eh_frame_ = -(eh_frame_size + kVersionSize + kEncodingSpecifiersSize); // A -> D lut_entries_number_ = 1; offset_to_procedure_ = -(RoundUp(code_size, 8) + eh_frame_size); // B -> F offset_to_fde_ = -(eh_frame_size - kCIESize); // B -> C } else { // Create a dummy table offset_to_eh_frame_ = 0; lut_entries_number_ = 0; offset_to_procedure_ = 0; offset_to_fde_ = 0; } } } // namespace internal } // namespace v8