2016-06-27 15:06:32 +00:00
|
|
|
// 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"
|
2016-07-13 14:20:27 +00:00
|
|
|
#include "src/objects-inl.h"
|
|
|
|
#include "src/objects.h"
|
2016-06-27 15:06:32 +00:00
|
|
|
|
|
|
|
namespace v8 {
|
|
|
|
namespace internal {
|
|
|
|
|
2016-07-13 14:20:27 +00:00
|
|
|
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
|
2016-06-27 15:06:32 +00:00
|
|
|
} else {
|
2016-07-13 14:20:27 +00:00
|
|
|
// Create a dummy table
|
|
|
|
offset_to_eh_frame_ = 0;
|
|
|
|
lut_entries_number_ = 0;
|
|
|
|
offset_to_procedure_ = 0;
|
|
|
|
offset_to_fde_ = 0;
|
2016-06-27 15:06:32 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace internal
|
|
|
|
} // namespace v8
|