11cb0ef41Sopenharmony_ci// Copyright 2016 the V8 project authors. All rights reserved.
21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be
31cb0ef41Sopenharmony_ci// found in the LICENSE file.
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_ci#include "src/diagnostics/eh-frame.h"
61cb0ef41Sopenharmony_ci
71cb0ef41Sopenharmony_ci#include <iomanip>
81cb0ef41Sopenharmony_ci#include <ostream>
91cb0ef41Sopenharmony_ci
101cb0ef41Sopenharmony_ci#include "src/codegen/code-desc.h"
111cb0ef41Sopenharmony_ci
121cb0ef41Sopenharmony_ci#if !defined(V8_TARGET_ARCH_X64) && !defined(V8_TARGET_ARCH_ARM) &&     \
131cb0ef41Sopenharmony_ci    !defined(V8_TARGET_ARCH_ARM64) && !defined(V8_TARGET_ARCH_S390X) && \
141cb0ef41Sopenharmony_ci    !defined(V8_TARGET_ARCH_PPC64)
151cb0ef41Sopenharmony_ci
161cb0ef41Sopenharmony_ci// Placeholders for unsupported architectures.
171cb0ef41Sopenharmony_ci
181cb0ef41Sopenharmony_cinamespace v8 {
191cb0ef41Sopenharmony_cinamespace internal {
201cb0ef41Sopenharmony_ci
211cb0ef41Sopenharmony_ciconst int EhFrameConstants::kCodeAlignmentFactor = 1;
221cb0ef41Sopenharmony_ciconst int EhFrameConstants::kDataAlignmentFactor = 1;
231cb0ef41Sopenharmony_ci
241cb0ef41Sopenharmony_civoid EhFrameWriter::WriteReturnAddressRegisterCode() { UNIMPLEMENTED(); }
251cb0ef41Sopenharmony_ci
261cb0ef41Sopenharmony_civoid EhFrameWriter::WriteInitialStateInCie() { UNIMPLEMENTED(); }
271cb0ef41Sopenharmony_ci
281cb0ef41Sopenharmony_ciint EhFrameWriter::RegisterToDwarfCode(Register) {
291cb0ef41Sopenharmony_ci  UNIMPLEMENTED();
301cb0ef41Sopenharmony_ci}
311cb0ef41Sopenharmony_ci
321cb0ef41Sopenharmony_ci#ifdef ENABLE_DISASSEMBLER
331cb0ef41Sopenharmony_ci
341cb0ef41Sopenharmony_ciconst char* EhFrameDisassembler::DwarfRegisterCodeToString(int) {
351cb0ef41Sopenharmony_ci  UNIMPLEMENTED();
361cb0ef41Sopenharmony_ci}
371cb0ef41Sopenharmony_ci
381cb0ef41Sopenharmony_ci#endif
391cb0ef41Sopenharmony_ci
401cb0ef41Sopenharmony_ci}  // namespace internal
411cb0ef41Sopenharmony_ci}  // namespace v8
421cb0ef41Sopenharmony_ci
431cb0ef41Sopenharmony_ci#endif
441cb0ef41Sopenharmony_ci
451cb0ef41Sopenharmony_cinamespace v8 {
461cb0ef41Sopenharmony_cinamespace internal {
471cb0ef41Sopenharmony_ci
481cb0ef41Sopenharmony_ciSTATIC_CONST_MEMBER_DEFINITION const int
491cb0ef41Sopenharmony_ci    EhFrameConstants::kEhFrameTerminatorSize;
501cb0ef41Sopenharmony_ciSTATIC_CONST_MEMBER_DEFINITION const int EhFrameConstants::kEhFrameHdrVersion;
511cb0ef41Sopenharmony_ciSTATIC_CONST_MEMBER_DEFINITION const int EhFrameConstants::kEhFrameHdrSize;
521cb0ef41Sopenharmony_ci
531cb0ef41Sopenharmony_ciSTATIC_CONST_MEMBER_DEFINITION const uint32_t EhFrameWriter::kInt32Placeholder;
541cb0ef41Sopenharmony_ci
551cb0ef41Sopenharmony_ci// static
561cb0ef41Sopenharmony_civoid EhFrameWriter::WriteEmptyEhFrame(std::ostream& stream) {
571cb0ef41Sopenharmony_ci  stream.put(EhFrameConstants::kEhFrameHdrVersion);
581cb0ef41Sopenharmony_ci
591cb0ef41Sopenharmony_ci  // .eh_frame pointer encoding specifier.
601cb0ef41Sopenharmony_ci  stream.put(EhFrameConstants::kSData4 | EhFrameConstants::kPcRel);
611cb0ef41Sopenharmony_ci
621cb0ef41Sopenharmony_ci  // Lookup table size encoding.
631cb0ef41Sopenharmony_ci  stream.put(EhFrameConstants::kUData4);
641cb0ef41Sopenharmony_ci
651cb0ef41Sopenharmony_ci  // Lookup table entries encoding.
661cb0ef41Sopenharmony_ci  stream.put(EhFrameConstants::kSData4 | EhFrameConstants::kDataRel);
671cb0ef41Sopenharmony_ci
681cb0ef41Sopenharmony_ci  // Dummy pointers and 0 entries in the lookup table.
691cb0ef41Sopenharmony_ci  char dummy_data[EhFrameConstants::kEhFrameHdrSize - 4] = {0};
701cb0ef41Sopenharmony_ci  stream.write(&dummy_data[0], sizeof(dummy_data));
711cb0ef41Sopenharmony_ci}
721cb0ef41Sopenharmony_ci
731cb0ef41Sopenharmony_ciEhFrameWriter::EhFrameWriter(Zone* zone)
741cb0ef41Sopenharmony_ci    : cie_size_(0),
751cb0ef41Sopenharmony_ci      last_pc_offset_(0),
761cb0ef41Sopenharmony_ci      writer_state_(InternalState::kUndefined),
771cb0ef41Sopenharmony_ci      base_register_(no_reg),
781cb0ef41Sopenharmony_ci      base_offset_(0),
791cb0ef41Sopenharmony_ci      eh_frame_buffer_(zone) {}
801cb0ef41Sopenharmony_ci
811cb0ef41Sopenharmony_civoid EhFrameWriter::Initialize() {
821cb0ef41Sopenharmony_ci  DCHECK_EQ(writer_state_, InternalState::kUndefined);
831cb0ef41Sopenharmony_ci  eh_frame_buffer_.reserve(128);
841cb0ef41Sopenharmony_ci  writer_state_ = InternalState::kInitialized;
851cb0ef41Sopenharmony_ci  WriteCie();
861cb0ef41Sopenharmony_ci  WriteFdeHeader();
871cb0ef41Sopenharmony_ci}
881cb0ef41Sopenharmony_ci
891cb0ef41Sopenharmony_civoid EhFrameWriter::WriteCie() {
901cb0ef41Sopenharmony_ci  static const int kCIEIdentifier = 0;
911cb0ef41Sopenharmony_ci  static const int kCIEVersion = 3;
921cb0ef41Sopenharmony_ci  static const int kAugmentationDataSize = 2;
931cb0ef41Sopenharmony_ci  static const byte kAugmentationString[] = {'z', 'L', 'R', 0};
941cb0ef41Sopenharmony_ci
951cb0ef41Sopenharmony_ci  // Placeholder for the size of the CIE.
961cb0ef41Sopenharmony_ci  int size_offset = eh_frame_offset();
971cb0ef41Sopenharmony_ci  WriteInt32(kInt32Placeholder);
981cb0ef41Sopenharmony_ci
991cb0ef41Sopenharmony_ci  // CIE identifier and version.
1001cb0ef41Sopenharmony_ci  int record_start_offset = eh_frame_offset();
1011cb0ef41Sopenharmony_ci  WriteInt32(kCIEIdentifier);
1021cb0ef41Sopenharmony_ci  WriteByte(kCIEVersion);
1031cb0ef41Sopenharmony_ci
1041cb0ef41Sopenharmony_ci  // Augmentation data contents descriptor: LSDA and FDE encoding.
1051cb0ef41Sopenharmony_ci  WriteBytes(&kAugmentationString[0], sizeof(kAugmentationString));
1061cb0ef41Sopenharmony_ci
1071cb0ef41Sopenharmony_ci  // Alignment factors.
1081cb0ef41Sopenharmony_ci  WriteSLeb128(EhFrameConstants::kCodeAlignmentFactor);
1091cb0ef41Sopenharmony_ci  WriteSLeb128(EhFrameConstants::kDataAlignmentFactor);
1101cb0ef41Sopenharmony_ci
1111cb0ef41Sopenharmony_ci  WriteReturnAddressRegisterCode();
1121cb0ef41Sopenharmony_ci
1131cb0ef41Sopenharmony_ci  // Augmentation data.
1141cb0ef41Sopenharmony_ci  WriteULeb128(kAugmentationDataSize);
1151cb0ef41Sopenharmony_ci  // No language-specific data area (LSDA).
1161cb0ef41Sopenharmony_ci  WriteByte(EhFrameConstants::kOmit);
1171cb0ef41Sopenharmony_ci  // FDE pointers encoding.
1181cb0ef41Sopenharmony_ci  WriteByte(EhFrameConstants::kSData4 | EhFrameConstants::kPcRel);
1191cb0ef41Sopenharmony_ci
1201cb0ef41Sopenharmony_ci  // Write directives to build the initial state of the unwinding table.
1211cb0ef41Sopenharmony_ci  DCHECK_EQ(eh_frame_offset() - size_offset,
1221cb0ef41Sopenharmony_ci            EhFrameConstants::kInitialStateOffsetInCie);
1231cb0ef41Sopenharmony_ci  WriteInitialStateInCie();
1241cb0ef41Sopenharmony_ci
1251cb0ef41Sopenharmony_ci  WritePaddingToAlignedSize(eh_frame_offset() - record_start_offset);
1261cb0ef41Sopenharmony_ci
1271cb0ef41Sopenharmony_ci  int record_end_offset = eh_frame_offset();
1281cb0ef41Sopenharmony_ci  int encoded_cie_size = record_end_offset - record_start_offset;
1291cb0ef41Sopenharmony_ci  cie_size_ = record_end_offset - size_offset;
1301cb0ef41Sopenharmony_ci
1311cb0ef41Sopenharmony_ci  // Patch the size of the CIE now that we know it.
1321cb0ef41Sopenharmony_ci  PatchInt32(size_offset, encoded_cie_size);
1331cb0ef41Sopenharmony_ci}
1341cb0ef41Sopenharmony_ci
1351cb0ef41Sopenharmony_civoid EhFrameWriter::WriteFdeHeader() {
1361cb0ef41Sopenharmony_ci  DCHECK_NE(cie_size_, 0);
1371cb0ef41Sopenharmony_ci
1381cb0ef41Sopenharmony_ci  // Placeholder for size of the FDE. Will be filled in Finish().
1391cb0ef41Sopenharmony_ci  DCHECK_EQ(eh_frame_offset(), fde_offset());
1401cb0ef41Sopenharmony_ci  WriteInt32(kInt32Placeholder);
1411cb0ef41Sopenharmony_ci
1421cb0ef41Sopenharmony_ci  // Backwards offset to the CIE.
1431cb0ef41Sopenharmony_ci  WriteInt32(cie_size_ + kInt32Size);
1441cb0ef41Sopenharmony_ci
1451cb0ef41Sopenharmony_ci  // Placeholder for pointer to procedure. Will be filled in Finish().
1461cb0ef41Sopenharmony_ci  DCHECK_EQ(eh_frame_offset(), GetProcedureAddressOffset());
1471cb0ef41Sopenharmony_ci  WriteInt32(kInt32Placeholder);
1481cb0ef41Sopenharmony_ci
1491cb0ef41Sopenharmony_ci  // Placeholder for size of the procedure. Will be filled in Finish().
1501cb0ef41Sopenharmony_ci  DCHECK_EQ(eh_frame_offset(), GetProcedureSizeOffset());
1511cb0ef41Sopenharmony_ci  WriteInt32(kInt32Placeholder);
1521cb0ef41Sopenharmony_ci
1531cb0ef41Sopenharmony_ci  // No augmentation data.
1541cb0ef41Sopenharmony_ci  WriteByte(0);
1551cb0ef41Sopenharmony_ci}
1561cb0ef41Sopenharmony_ci
1571cb0ef41Sopenharmony_civoid EhFrameWriter::WriteEhFrameHdr(int code_size) {
1581cb0ef41Sopenharmony_ci  DCHECK_EQ(writer_state_, InternalState::kInitialized);
1591cb0ef41Sopenharmony_ci
1601cb0ef41Sopenharmony_ci  //
1611cb0ef41Sopenharmony_ci  // In order to calculate offsets in the .eh_frame_hdr, we must know the layout
1621cb0ef41Sopenharmony_ci  // of the DSO generated by perf inject, which is assumed to be the following:
1631cb0ef41Sopenharmony_ci  //
1641cb0ef41Sopenharmony_ci  //  |      ...      |                        |
1651cb0ef41Sopenharmony_ci  //  +---------------+ <-- (F) ---            |  Larger offsets in file
1661cb0ef41Sopenharmony_ci  //  |               |           ^            |
1671cb0ef41Sopenharmony_ci  //  |  Instructions |           | .text      v
1681cb0ef41Sopenharmony_ci  //  |               |           v
1691cb0ef41Sopenharmony_ci  //  +---------------+ <-- (E) ---
1701cb0ef41Sopenharmony_ci  //  |///////////////|
1711cb0ef41Sopenharmony_ci  //  |////Padding////|
1721cb0ef41Sopenharmony_ci  //  |///////////////|
1731cb0ef41Sopenharmony_ci  //  +---------------+ <-- (D) ---
1741cb0ef41Sopenharmony_ci  //  |               |           ^
1751cb0ef41Sopenharmony_ci  //  |      CIE      |           |
1761cb0ef41Sopenharmony_ci  //  |               |           |
1771cb0ef41Sopenharmony_ci  //  +---------------+ <-- (C)   |
1781cb0ef41Sopenharmony_ci  //  |               |           | .eh_frame
1791cb0ef41Sopenharmony_ci  //  |      FDE      |           |
1801cb0ef41Sopenharmony_ci  //  |               |           |
1811cb0ef41Sopenharmony_ci  //  +---------------+           |
1821cb0ef41Sopenharmony_ci  //  |   terminator  |           v
1831cb0ef41Sopenharmony_ci  //  +---------------+ <-- (B) ---
1841cb0ef41Sopenharmony_ci  //  |    version    |           ^
1851cb0ef41Sopenharmony_ci  //  +---------------+           |
1861cb0ef41Sopenharmony_ci  //  |   encoding    |           |
1871cb0ef41Sopenharmony_ci  //  |  specifiers   |           |
1881cb0ef41Sopenharmony_ci  //  +---------------+ <---(A)   | .eh_frame_hdr
1891cb0ef41Sopenharmony_ci  //  |   offset to   |           |
1901cb0ef41Sopenharmony_ci  //  |   .eh_frame   |           |
1911cb0ef41Sopenharmony_ci  //  +---------------+           |
1921cb0ef41Sopenharmony_ci  //  |      ...      |          ...
1931cb0ef41Sopenharmony_ci  //
1941cb0ef41Sopenharmony_ci  // (F) is aligned to a 16-byte boundary.
1951cb0ef41Sopenharmony_ci  // (D) is aligned to a  8-byte boundary.
1961cb0ef41Sopenharmony_ci  // (B) is aligned to a  4-byte boundary.
1971cb0ef41Sopenharmony_ci  // (C), (E) and (A) have no alignment requirements.
1981cb0ef41Sopenharmony_ci  //
1991cb0ef41Sopenharmony_ci  // The distance between (A) and (B) is 4 bytes.
2001cb0ef41Sopenharmony_ci  //
2011cb0ef41Sopenharmony_ci  // The size of the FDE is required to be a multiple of the pointer size, which
2021cb0ef41Sopenharmony_ci  // means that (B) will be naturally aligned to a 4-byte boundary on all the
2031cb0ef41Sopenharmony_ci  // architectures we support.
2041cb0ef41Sopenharmony_ci  //
2051cb0ef41Sopenharmony_ci  // Because (E) has no alignment requirements, there is padding between (E) and
2061cb0ef41Sopenharmony_ci  // (D). (F) is aligned at a 16-byte boundary, thus to a 8-byte one as well.
2071cb0ef41Sopenharmony_ci  //
2081cb0ef41Sopenharmony_ci
2091cb0ef41Sopenharmony_ci  int eh_frame_size = eh_frame_offset();
2101cb0ef41Sopenharmony_ci
2111cb0ef41Sopenharmony_ci  WriteByte(EhFrameConstants::kEhFrameHdrVersion);
2121cb0ef41Sopenharmony_ci
2131cb0ef41Sopenharmony_ci  // .eh_frame pointer encoding specifier.
2141cb0ef41Sopenharmony_ci  WriteByte(EhFrameConstants::kSData4 | EhFrameConstants::kPcRel);
2151cb0ef41Sopenharmony_ci  // Lookup table size encoding specifier.
2161cb0ef41Sopenharmony_ci  WriteByte(EhFrameConstants::kUData4);
2171cb0ef41Sopenharmony_ci  // Lookup table entries encoding specifier.
2181cb0ef41Sopenharmony_ci  WriteByte(EhFrameConstants::kSData4 | EhFrameConstants::kDataRel);
2191cb0ef41Sopenharmony_ci
2201cb0ef41Sopenharmony_ci  // Pointer to .eh_frame, relative to this offset (A -> D in the diagram).
2211cb0ef41Sopenharmony_ci  WriteInt32(-(eh_frame_size + EhFrameConstants::kFdeVersionSize +
2221cb0ef41Sopenharmony_ci               EhFrameConstants::kFdeEncodingSpecifiersSize));
2231cb0ef41Sopenharmony_ci
2241cb0ef41Sopenharmony_ci  // Number of entries in the LUT, one for the only routine.
2251cb0ef41Sopenharmony_ci  WriteInt32(1);
2261cb0ef41Sopenharmony_ci
2271cb0ef41Sopenharmony_ci  // Pointer to the start of the routine, relative to the beginning of the
2281cb0ef41Sopenharmony_ci  // .eh_frame_hdr (B -> F in the diagram).
2291cb0ef41Sopenharmony_ci  WriteInt32(-(RoundUp(code_size, 8) + eh_frame_size));
2301cb0ef41Sopenharmony_ci
2311cb0ef41Sopenharmony_ci  // Pointer to the start of the associated FDE, relative to the start of the
2321cb0ef41Sopenharmony_ci  // .eh_frame_hdr (B -> C  in the diagram).
2331cb0ef41Sopenharmony_ci  WriteInt32(-(eh_frame_size - cie_size_));
2341cb0ef41Sopenharmony_ci
2351cb0ef41Sopenharmony_ci  DCHECK_EQ(eh_frame_offset() - eh_frame_size,
2361cb0ef41Sopenharmony_ci            EhFrameConstants::kEhFrameHdrSize);
2371cb0ef41Sopenharmony_ci}
2381cb0ef41Sopenharmony_ci
2391cb0ef41Sopenharmony_civoid EhFrameWriter::WritePaddingToAlignedSize(int unpadded_size) {
2401cb0ef41Sopenharmony_ci  DCHECK_EQ(writer_state_, InternalState::kInitialized);
2411cb0ef41Sopenharmony_ci  DCHECK_GE(unpadded_size, 0);
2421cb0ef41Sopenharmony_ci
2431cb0ef41Sopenharmony_ci  int padding_size = RoundUp(unpadded_size, kSystemPointerSize) - unpadded_size;
2441cb0ef41Sopenharmony_ci
2451cb0ef41Sopenharmony_ci  byte nop = static_cast<byte>(EhFrameConstants::DwarfOpcodes::kNop);
2461cb0ef41Sopenharmony_ci  static const byte kPadding[] = {nop, nop, nop, nop, nop, nop, nop, nop};
2471cb0ef41Sopenharmony_ci  DCHECK_LE(padding_size, static_cast<int>(sizeof(kPadding)));
2481cb0ef41Sopenharmony_ci  WriteBytes(&kPadding[0], padding_size);
2491cb0ef41Sopenharmony_ci}
2501cb0ef41Sopenharmony_ci
2511cb0ef41Sopenharmony_civoid EhFrameWriter::AdvanceLocation(int pc_offset) {
2521cb0ef41Sopenharmony_ci  DCHECK_EQ(writer_state_, InternalState::kInitialized);
2531cb0ef41Sopenharmony_ci  DCHECK_GE(pc_offset, last_pc_offset_);
2541cb0ef41Sopenharmony_ci  uint32_t delta = pc_offset - last_pc_offset_;
2551cb0ef41Sopenharmony_ci
2561cb0ef41Sopenharmony_ci  DCHECK_EQ(delta % EhFrameConstants::kCodeAlignmentFactor, 0u);
2571cb0ef41Sopenharmony_ci  uint32_t factored_delta = delta / EhFrameConstants::kCodeAlignmentFactor;
2581cb0ef41Sopenharmony_ci
2591cb0ef41Sopenharmony_ci  if (factored_delta <= EhFrameConstants::kLocationMask) {
2601cb0ef41Sopenharmony_ci    WriteByte((EhFrameConstants::kLocationTag
2611cb0ef41Sopenharmony_ci               << EhFrameConstants::kLocationMaskSize) |
2621cb0ef41Sopenharmony_ci              (factored_delta & EhFrameConstants::kLocationMask));
2631cb0ef41Sopenharmony_ci  } else if (factored_delta <= kMaxUInt8) {
2641cb0ef41Sopenharmony_ci    WriteOpcode(EhFrameConstants::DwarfOpcodes::kAdvanceLoc1);
2651cb0ef41Sopenharmony_ci    WriteByte(factored_delta);
2661cb0ef41Sopenharmony_ci  } else if (factored_delta <= kMaxUInt16) {
2671cb0ef41Sopenharmony_ci    WriteOpcode(EhFrameConstants::DwarfOpcodes::kAdvanceLoc2);
2681cb0ef41Sopenharmony_ci    WriteInt16(factored_delta);
2691cb0ef41Sopenharmony_ci  } else {
2701cb0ef41Sopenharmony_ci    WriteOpcode(EhFrameConstants::DwarfOpcodes::kAdvanceLoc4);
2711cb0ef41Sopenharmony_ci    WriteInt32(factored_delta);
2721cb0ef41Sopenharmony_ci  }
2731cb0ef41Sopenharmony_ci
2741cb0ef41Sopenharmony_ci  last_pc_offset_ = pc_offset;
2751cb0ef41Sopenharmony_ci}
2761cb0ef41Sopenharmony_ci
2771cb0ef41Sopenharmony_civoid EhFrameWriter::SetBaseAddressOffset(int base_offset) {
2781cb0ef41Sopenharmony_ci  DCHECK_EQ(writer_state_, InternalState::kInitialized);
2791cb0ef41Sopenharmony_ci  DCHECK_GE(base_offset, 0);
2801cb0ef41Sopenharmony_ci  WriteOpcode(EhFrameConstants::DwarfOpcodes::kDefCfaOffset);
2811cb0ef41Sopenharmony_ci  WriteULeb128(base_offset);
2821cb0ef41Sopenharmony_ci  base_offset_ = base_offset;
2831cb0ef41Sopenharmony_ci}
2841cb0ef41Sopenharmony_ci
2851cb0ef41Sopenharmony_civoid EhFrameWriter::SetBaseAddressRegister(Register base_register) {
2861cb0ef41Sopenharmony_ci  DCHECK_EQ(writer_state_, InternalState::kInitialized);
2871cb0ef41Sopenharmony_ci  int code = RegisterToDwarfCode(base_register);
2881cb0ef41Sopenharmony_ci  WriteOpcode(EhFrameConstants::DwarfOpcodes::kDefCfaRegister);
2891cb0ef41Sopenharmony_ci  WriteULeb128(code);
2901cb0ef41Sopenharmony_ci  base_register_ = base_register;
2911cb0ef41Sopenharmony_ci}
2921cb0ef41Sopenharmony_ci
2931cb0ef41Sopenharmony_civoid EhFrameWriter::SetBaseAddressRegisterAndOffset(Register base_register,
2941cb0ef41Sopenharmony_ci                                                    int base_offset) {
2951cb0ef41Sopenharmony_ci  DCHECK_EQ(writer_state_, InternalState::kInitialized);
2961cb0ef41Sopenharmony_ci  DCHECK_GE(base_offset, 0);
2971cb0ef41Sopenharmony_ci  int code = RegisterToDwarfCode(base_register);
2981cb0ef41Sopenharmony_ci  WriteOpcode(EhFrameConstants::DwarfOpcodes::kDefCfa);
2991cb0ef41Sopenharmony_ci  WriteULeb128(code);
3001cb0ef41Sopenharmony_ci  WriteULeb128(base_offset);
3011cb0ef41Sopenharmony_ci  base_offset_ = base_offset;
3021cb0ef41Sopenharmony_ci  base_register_ = base_register;
3031cb0ef41Sopenharmony_ci}
3041cb0ef41Sopenharmony_ci
3051cb0ef41Sopenharmony_civoid EhFrameWriter::RecordRegisterSavedToStack(int dwarf_register_code,
3061cb0ef41Sopenharmony_ci                                               int offset) {
3071cb0ef41Sopenharmony_ci  DCHECK_EQ(writer_state_, InternalState::kInitialized);
3081cb0ef41Sopenharmony_ci  DCHECK_EQ(offset % EhFrameConstants::kDataAlignmentFactor, 0);
3091cb0ef41Sopenharmony_ci  int factored_offset = offset / EhFrameConstants::kDataAlignmentFactor;
3101cb0ef41Sopenharmony_ci  if (factored_offset >= 0) {
3111cb0ef41Sopenharmony_ci    DCHECK_LE(dwarf_register_code, EhFrameConstants::kSavedRegisterMask);
3121cb0ef41Sopenharmony_ci    WriteByte((EhFrameConstants::kSavedRegisterTag
3131cb0ef41Sopenharmony_ci               << EhFrameConstants::kSavedRegisterMaskSize) |
3141cb0ef41Sopenharmony_ci              (dwarf_register_code & EhFrameConstants::kSavedRegisterMask));
3151cb0ef41Sopenharmony_ci    WriteULeb128(factored_offset);
3161cb0ef41Sopenharmony_ci  } else {
3171cb0ef41Sopenharmony_ci    WriteOpcode(EhFrameConstants::DwarfOpcodes::kOffsetExtendedSf);
3181cb0ef41Sopenharmony_ci    WriteULeb128(dwarf_register_code);
3191cb0ef41Sopenharmony_ci    WriteSLeb128(factored_offset);
3201cb0ef41Sopenharmony_ci  }
3211cb0ef41Sopenharmony_ci}
3221cb0ef41Sopenharmony_ci
3231cb0ef41Sopenharmony_civoid EhFrameWriter::RecordRegisterNotModified(Register name) {
3241cb0ef41Sopenharmony_ci  RecordRegisterNotModified(RegisterToDwarfCode(name));
3251cb0ef41Sopenharmony_ci}
3261cb0ef41Sopenharmony_ci
3271cb0ef41Sopenharmony_civoid EhFrameWriter::RecordRegisterNotModified(int dwarf_register_code) {
3281cb0ef41Sopenharmony_ci  DCHECK_EQ(writer_state_, InternalState::kInitialized);
3291cb0ef41Sopenharmony_ci  WriteOpcode(EhFrameConstants::DwarfOpcodes::kSameValue);
3301cb0ef41Sopenharmony_ci  WriteULeb128(dwarf_register_code);
3311cb0ef41Sopenharmony_ci}
3321cb0ef41Sopenharmony_ci
3331cb0ef41Sopenharmony_civoid EhFrameWriter::RecordRegisterFollowsInitialRule(Register name) {
3341cb0ef41Sopenharmony_ci  RecordRegisterFollowsInitialRule(RegisterToDwarfCode(name));
3351cb0ef41Sopenharmony_ci}
3361cb0ef41Sopenharmony_ci
3371cb0ef41Sopenharmony_civoid EhFrameWriter::RecordRegisterFollowsInitialRule(int dwarf_register_code) {
3381cb0ef41Sopenharmony_ci  DCHECK_EQ(writer_state_, InternalState::kInitialized);
3391cb0ef41Sopenharmony_ci  if (dwarf_register_code <= EhFrameConstants::kFollowInitialRuleMask) {
3401cb0ef41Sopenharmony_ci    WriteByte((EhFrameConstants::kFollowInitialRuleTag
3411cb0ef41Sopenharmony_ci               << EhFrameConstants::kFollowInitialRuleMaskSize) |
3421cb0ef41Sopenharmony_ci              (dwarf_register_code & EhFrameConstants::kFollowInitialRuleMask));
3431cb0ef41Sopenharmony_ci  } else {
3441cb0ef41Sopenharmony_ci    WriteOpcode(EhFrameConstants::DwarfOpcodes::kRestoreExtended);
3451cb0ef41Sopenharmony_ci    WriteULeb128(dwarf_register_code);
3461cb0ef41Sopenharmony_ci  }
3471cb0ef41Sopenharmony_ci}
3481cb0ef41Sopenharmony_ci
3491cb0ef41Sopenharmony_civoid EhFrameWriter::Finish(int code_size) {
3501cb0ef41Sopenharmony_ci  DCHECK_EQ(writer_state_, InternalState::kInitialized);
3511cb0ef41Sopenharmony_ci  DCHECK_GE(eh_frame_offset(), cie_size_);
3521cb0ef41Sopenharmony_ci
3531cb0ef41Sopenharmony_ci  DCHECK_GE(eh_frame_offset(), fde_offset() + kInt32Size);
3541cb0ef41Sopenharmony_ci  WritePaddingToAlignedSize(eh_frame_offset() - fde_offset() - kInt32Size);
3551cb0ef41Sopenharmony_ci
3561cb0ef41Sopenharmony_ci  // Write the size of the FDE now that we know it.
3571cb0ef41Sopenharmony_ci  // The encoded size does not include the size field itself.
3581cb0ef41Sopenharmony_ci  int encoded_fde_size = eh_frame_offset() - fde_offset() - kInt32Size;
3591cb0ef41Sopenharmony_ci  PatchInt32(fde_offset(), encoded_fde_size);
3601cb0ef41Sopenharmony_ci
3611cb0ef41Sopenharmony_ci  // Write size and offset to procedure.
3621cb0ef41Sopenharmony_ci  PatchInt32(GetProcedureAddressOffset(),
3631cb0ef41Sopenharmony_ci             -(RoundUp(code_size, 8) + GetProcedureAddressOffset()));
3641cb0ef41Sopenharmony_ci  PatchInt32(GetProcedureSizeOffset(), code_size);
3651cb0ef41Sopenharmony_ci
3661cb0ef41Sopenharmony_ci  // Terminate the .eh_frame.
3671cb0ef41Sopenharmony_ci  static const byte kTerminator[EhFrameConstants::kEhFrameTerminatorSize] = {0};
3681cb0ef41Sopenharmony_ci  WriteBytes(&kTerminator[0], EhFrameConstants::kEhFrameTerminatorSize);
3691cb0ef41Sopenharmony_ci
3701cb0ef41Sopenharmony_ci  WriteEhFrameHdr(code_size);
3711cb0ef41Sopenharmony_ci
3721cb0ef41Sopenharmony_ci  writer_state_ = InternalState::kFinalized;
3731cb0ef41Sopenharmony_ci}
3741cb0ef41Sopenharmony_ci
3751cb0ef41Sopenharmony_civoid EhFrameWriter::GetEhFrame(CodeDesc* desc) {
3761cb0ef41Sopenharmony_ci  DCHECK_EQ(writer_state_, InternalState::kFinalized);
3771cb0ef41Sopenharmony_ci  desc->unwinding_info_size = static_cast<int>(eh_frame_buffer_.size());
3781cb0ef41Sopenharmony_ci  desc->unwinding_info = eh_frame_buffer_.data();
3791cb0ef41Sopenharmony_ci}
3801cb0ef41Sopenharmony_ci
3811cb0ef41Sopenharmony_civoid EhFrameWriter::WriteULeb128(uint32_t value) {
3821cb0ef41Sopenharmony_ci  do {
3831cb0ef41Sopenharmony_ci    byte chunk = value & 0x7F;
3841cb0ef41Sopenharmony_ci    value >>= 7;
3851cb0ef41Sopenharmony_ci    if (value != 0) chunk |= 0x80;
3861cb0ef41Sopenharmony_ci    WriteByte(chunk);
3871cb0ef41Sopenharmony_ci  } while (value != 0);
3881cb0ef41Sopenharmony_ci}
3891cb0ef41Sopenharmony_ci
3901cb0ef41Sopenharmony_civoid EhFrameWriter::WriteSLeb128(int32_t value) {
3911cb0ef41Sopenharmony_ci  static const int kSignBitMask = 0x40;
3921cb0ef41Sopenharmony_ci  bool done;
3931cb0ef41Sopenharmony_ci  do {
3941cb0ef41Sopenharmony_ci    byte chunk = value & 0x7F;
3951cb0ef41Sopenharmony_ci    value >>= 7;
3961cb0ef41Sopenharmony_ci    done = ((value == 0) && ((chunk & kSignBitMask) == 0)) ||
3971cb0ef41Sopenharmony_ci           ((value == -1) && ((chunk & kSignBitMask) != 0));
3981cb0ef41Sopenharmony_ci    if (!done) chunk |= 0x80;
3991cb0ef41Sopenharmony_ci    WriteByte(chunk);
4001cb0ef41Sopenharmony_ci  } while (!done);
4011cb0ef41Sopenharmony_ci}
4021cb0ef41Sopenharmony_ci
4031cb0ef41Sopenharmony_ciuint32_t EhFrameIterator::GetNextULeb128() {
4041cb0ef41Sopenharmony_ci  int size = 0;
4051cb0ef41Sopenharmony_ci  uint32_t result = DecodeULeb128(next_, &size);
4061cb0ef41Sopenharmony_ci  DCHECK_LE(next_ + size, end_);
4071cb0ef41Sopenharmony_ci  next_ += size;
4081cb0ef41Sopenharmony_ci  return result;
4091cb0ef41Sopenharmony_ci}
4101cb0ef41Sopenharmony_ci
4111cb0ef41Sopenharmony_ciint32_t EhFrameIterator::GetNextSLeb128() {
4121cb0ef41Sopenharmony_ci  int size = 0;
4131cb0ef41Sopenharmony_ci  int32_t result = DecodeSLeb128(next_, &size);
4141cb0ef41Sopenharmony_ci  DCHECK_LE(next_ + size, end_);
4151cb0ef41Sopenharmony_ci  next_ += size;
4161cb0ef41Sopenharmony_ci  return result;
4171cb0ef41Sopenharmony_ci}
4181cb0ef41Sopenharmony_ci
4191cb0ef41Sopenharmony_ci// static
4201cb0ef41Sopenharmony_ciuint32_t EhFrameIterator::DecodeULeb128(const byte* encoded,
4211cb0ef41Sopenharmony_ci                                        int* encoded_size) {
4221cb0ef41Sopenharmony_ci  const byte* current = encoded;
4231cb0ef41Sopenharmony_ci  uint32_t result = 0;
4241cb0ef41Sopenharmony_ci  int shift = 0;
4251cb0ef41Sopenharmony_ci
4261cb0ef41Sopenharmony_ci  do {
4271cb0ef41Sopenharmony_ci    DCHECK_LT(shift, 8 * static_cast<int>(sizeof(result)));
4281cb0ef41Sopenharmony_ci    result |= (*current & 0x7F) << shift;
4291cb0ef41Sopenharmony_ci    shift += 7;
4301cb0ef41Sopenharmony_ci  } while (*current++ >= 128);
4311cb0ef41Sopenharmony_ci
4321cb0ef41Sopenharmony_ci  DCHECK_NOT_NULL(encoded_size);
4331cb0ef41Sopenharmony_ci  *encoded_size = static_cast<int>(current - encoded);
4341cb0ef41Sopenharmony_ci
4351cb0ef41Sopenharmony_ci  return result;
4361cb0ef41Sopenharmony_ci}
4371cb0ef41Sopenharmony_ci
4381cb0ef41Sopenharmony_ci// static
4391cb0ef41Sopenharmony_ciint32_t EhFrameIterator::DecodeSLeb128(const byte* encoded, int* encoded_size) {
4401cb0ef41Sopenharmony_ci  static const byte kSignBitMask = 0x40;
4411cb0ef41Sopenharmony_ci
4421cb0ef41Sopenharmony_ci  const byte* current = encoded;
4431cb0ef41Sopenharmony_ci  int32_t result = 0;
4441cb0ef41Sopenharmony_ci  int shift = 0;
4451cb0ef41Sopenharmony_ci  byte chunk;
4461cb0ef41Sopenharmony_ci
4471cb0ef41Sopenharmony_ci  do {
4481cb0ef41Sopenharmony_ci    chunk = *current++;
4491cb0ef41Sopenharmony_ci    DCHECK_LT(shift, 8 * static_cast<int>(sizeof(result)));
4501cb0ef41Sopenharmony_ci    result |= (chunk & 0x7F) << shift;
4511cb0ef41Sopenharmony_ci    shift += 7;
4521cb0ef41Sopenharmony_ci  } while (chunk >= 128);
4531cb0ef41Sopenharmony_ci
4541cb0ef41Sopenharmony_ci  // Sign extend the result if the last chunk has the sign bit set.
4551cb0ef41Sopenharmony_ci  if (chunk & kSignBitMask) result |= (~0ull) << shift;
4561cb0ef41Sopenharmony_ci
4571cb0ef41Sopenharmony_ci  DCHECK_NOT_NULL(encoded_size);
4581cb0ef41Sopenharmony_ci  *encoded_size = static_cast<int>(current - encoded);
4591cb0ef41Sopenharmony_ci
4601cb0ef41Sopenharmony_ci  return result;
4611cb0ef41Sopenharmony_ci}
4621cb0ef41Sopenharmony_ci
4631cb0ef41Sopenharmony_ci#ifdef ENABLE_DISASSEMBLER
4641cb0ef41Sopenharmony_ci
4651cb0ef41Sopenharmony_cinamespace {
4661cb0ef41Sopenharmony_ci
4671cb0ef41Sopenharmony_ciclass V8_NODISCARD StreamModifiersScope final {
4681cb0ef41Sopenharmony_ci public:
4691cb0ef41Sopenharmony_ci  explicit StreamModifiersScope(std::ostream* stream)
4701cb0ef41Sopenharmony_ci      : stream_(stream), flags_(stream->flags()) {}
4711cb0ef41Sopenharmony_ci  ~StreamModifiersScope() { stream_->flags(flags_); }
4721cb0ef41Sopenharmony_ci
4731cb0ef41Sopenharmony_ci private:
4741cb0ef41Sopenharmony_ci  std::ostream* stream_;
4751cb0ef41Sopenharmony_ci  std::ios::fmtflags flags_;
4761cb0ef41Sopenharmony_ci};
4771cb0ef41Sopenharmony_ci
4781cb0ef41Sopenharmony_ci}  // namespace
4791cb0ef41Sopenharmony_ci
4801cb0ef41Sopenharmony_ci// static
4811cb0ef41Sopenharmony_civoid EhFrameDisassembler::DumpDwarfDirectives(std::ostream& stream,
4821cb0ef41Sopenharmony_ci                                              const byte* start,
4831cb0ef41Sopenharmony_ci                                              const byte* end) {
4841cb0ef41Sopenharmony_ci  StreamModifiersScope modifiers_scope(&stream);
4851cb0ef41Sopenharmony_ci
4861cb0ef41Sopenharmony_ci  EhFrameIterator eh_frame_iterator(start, end);
4871cb0ef41Sopenharmony_ci  uint32_t offset_in_procedure = 0;
4881cb0ef41Sopenharmony_ci
4891cb0ef41Sopenharmony_ci  while (!eh_frame_iterator.Done()) {
4901cb0ef41Sopenharmony_ci    stream << eh_frame_iterator.current_address() << "  ";
4911cb0ef41Sopenharmony_ci
4921cb0ef41Sopenharmony_ci    byte bytecode = eh_frame_iterator.GetNextByte();
4931cb0ef41Sopenharmony_ci
4941cb0ef41Sopenharmony_ci    if (((bytecode >> EhFrameConstants::kLocationMaskSize) & 0xFF) ==
4951cb0ef41Sopenharmony_ci        EhFrameConstants::kLocationTag) {
4961cb0ef41Sopenharmony_ci      int value = (bytecode & EhFrameConstants::kLocationMask) *
4971cb0ef41Sopenharmony_ci                  EhFrameConstants::kCodeAlignmentFactor;
4981cb0ef41Sopenharmony_ci      offset_in_procedure += value;
4991cb0ef41Sopenharmony_ci      stream << "| pc_offset=" << offset_in_procedure << " (delta=" << value
5001cb0ef41Sopenharmony_ci             << ")\n";
5011cb0ef41Sopenharmony_ci      continue;
5021cb0ef41Sopenharmony_ci    }
5031cb0ef41Sopenharmony_ci
5041cb0ef41Sopenharmony_ci    if (((bytecode >> EhFrameConstants::kSavedRegisterMaskSize) & 0xFF) ==
5051cb0ef41Sopenharmony_ci        EhFrameConstants::kSavedRegisterTag) {
5061cb0ef41Sopenharmony_ci      int32_t decoded_offset = eh_frame_iterator.GetNextULeb128();
5071cb0ef41Sopenharmony_ci      stream << "| "
5081cb0ef41Sopenharmony_ci             << DwarfRegisterCodeToString(bytecode &
5091cb0ef41Sopenharmony_ci                                          EhFrameConstants::kLocationMask)
5101cb0ef41Sopenharmony_ci             << " saved at base" << std::showpos
5111cb0ef41Sopenharmony_ci             << decoded_offset * EhFrameConstants::kDataAlignmentFactor
5121cb0ef41Sopenharmony_ci             << std::noshowpos << '\n';
5131cb0ef41Sopenharmony_ci      continue;
5141cb0ef41Sopenharmony_ci    }
5151cb0ef41Sopenharmony_ci
5161cb0ef41Sopenharmony_ci    if (((bytecode >> EhFrameConstants::kFollowInitialRuleMaskSize) & 0xFF) ==
5171cb0ef41Sopenharmony_ci        EhFrameConstants::kFollowInitialRuleTag) {
5181cb0ef41Sopenharmony_ci      stream << "| "
5191cb0ef41Sopenharmony_ci             << DwarfRegisterCodeToString(bytecode &
5201cb0ef41Sopenharmony_ci                                          EhFrameConstants::kLocationMask)
5211cb0ef41Sopenharmony_ci             << " follows rule in CIE\n";
5221cb0ef41Sopenharmony_ci      continue;
5231cb0ef41Sopenharmony_ci    }
5241cb0ef41Sopenharmony_ci
5251cb0ef41Sopenharmony_ci    switch (static_cast<EhFrameConstants::DwarfOpcodes>(bytecode)) {
5261cb0ef41Sopenharmony_ci      case EhFrameConstants::DwarfOpcodes::kOffsetExtendedSf: {
5271cb0ef41Sopenharmony_ci        stream << "| "
5281cb0ef41Sopenharmony_ci               << DwarfRegisterCodeToString(eh_frame_iterator.GetNextULeb128());
5291cb0ef41Sopenharmony_ci        int32_t decoded_offset = eh_frame_iterator.GetNextSLeb128();
5301cb0ef41Sopenharmony_ci        stream << " saved at base" << std::showpos
5311cb0ef41Sopenharmony_ci               << decoded_offset * EhFrameConstants::kDataAlignmentFactor
5321cb0ef41Sopenharmony_ci               << std::noshowpos << '\n';
5331cb0ef41Sopenharmony_ci        break;
5341cb0ef41Sopenharmony_ci      }
5351cb0ef41Sopenharmony_ci      case EhFrameConstants::DwarfOpcodes::kAdvanceLoc1: {
5361cb0ef41Sopenharmony_ci        int value = eh_frame_iterator.GetNextByte() *
5371cb0ef41Sopenharmony_ci                    EhFrameConstants::kCodeAlignmentFactor;
5381cb0ef41Sopenharmony_ci        offset_in_procedure += value;
5391cb0ef41Sopenharmony_ci        stream << "| pc_offset=" << offset_in_procedure << " (delta=" << value
5401cb0ef41Sopenharmony_ci               << ")\n";
5411cb0ef41Sopenharmony_ci        break;
5421cb0ef41Sopenharmony_ci      }
5431cb0ef41Sopenharmony_ci      case EhFrameConstants::DwarfOpcodes::kAdvanceLoc2: {
5441cb0ef41Sopenharmony_ci        int value = eh_frame_iterator.GetNextUInt16() *
5451cb0ef41Sopenharmony_ci                    EhFrameConstants::kCodeAlignmentFactor;
5461cb0ef41Sopenharmony_ci        offset_in_procedure += value;
5471cb0ef41Sopenharmony_ci        stream << "| pc_offset=" << offset_in_procedure << " (delta=" << value
5481cb0ef41Sopenharmony_ci               << ")\n";
5491cb0ef41Sopenharmony_ci        break;
5501cb0ef41Sopenharmony_ci      }
5511cb0ef41Sopenharmony_ci      case EhFrameConstants::DwarfOpcodes::kAdvanceLoc4: {
5521cb0ef41Sopenharmony_ci        int value = eh_frame_iterator.GetNextUInt32() *
5531cb0ef41Sopenharmony_ci                    EhFrameConstants::kCodeAlignmentFactor;
5541cb0ef41Sopenharmony_ci        offset_in_procedure += value;
5551cb0ef41Sopenharmony_ci        stream << "| pc_offset=" << offset_in_procedure << " (delta=" << value
5561cb0ef41Sopenharmony_ci               << ")\n";
5571cb0ef41Sopenharmony_ci        break;
5581cb0ef41Sopenharmony_ci      }
5591cb0ef41Sopenharmony_ci      case EhFrameConstants::DwarfOpcodes::kDefCfa: {
5601cb0ef41Sopenharmony_ci        uint32_t base_register = eh_frame_iterator.GetNextULeb128();
5611cb0ef41Sopenharmony_ci        uint32_t base_offset = eh_frame_iterator.GetNextULeb128();
5621cb0ef41Sopenharmony_ci        stream << "| base_register=" << DwarfRegisterCodeToString(base_register)
5631cb0ef41Sopenharmony_ci               << ", base_offset=" << base_offset << '\n';
5641cb0ef41Sopenharmony_ci        break;
5651cb0ef41Sopenharmony_ci      }
5661cb0ef41Sopenharmony_ci      case EhFrameConstants::DwarfOpcodes::kDefCfaOffset: {
5671cb0ef41Sopenharmony_ci        stream << "| base_offset=" << eh_frame_iterator.GetNextULeb128()
5681cb0ef41Sopenharmony_ci               << '\n';
5691cb0ef41Sopenharmony_ci        break;
5701cb0ef41Sopenharmony_ci      }
5711cb0ef41Sopenharmony_ci      case EhFrameConstants::DwarfOpcodes::kDefCfaRegister: {
5721cb0ef41Sopenharmony_ci        stream << "| base_register="
5731cb0ef41Sopenharmony_ci               << DwarfRegisterCodeToString(eh_frame_iterator.GetNextULeb128())
5741cb0ef41Sopenharmony_ci               << '\n';
5751cb0ef41Sopenharmony_ci        break;
5761cb0ef41Sopenharmony_ci      }
5771cb0ef41Sopenharmony_ci      case EhFrameConstants::DwarfOpcodes::kSameValue: {
5781cb0ef41Sopenharmony_ci        stream << "| "
5791cb0ef41Sopenharmony_ci               << DwarfRegisterCodeToString(eh_frame_iterator.GetNextULeb128())
5801cb0ef41Sopenharmony_ci               << " not modified from previous frame\n";
5811cb0ef41Sopenharmony_ci        break;
5821cb0ef41Sopenharmony_ci      }
5831cb0ef41Sopenharmony_ci      case EhFrameConstants::DwarfOpcodes::kNop:
5841cb0ef41Sopenharmony_ci        stream << "| nop\n";
5851cb0ef41Sopenharmony_ci        break;
5861cb0ef41Sopenharmony_ci      default:
5871cb0ef41Sopenharmony_ci        UNREACHABLE();
5881cb0ef41Sopenharmony_ci    }
5891cb0ef41Sopenharmony_ci  }
5901cb0ef41Sopenharmony_ci}
5911cb0ef41Sopenharmony_ci
5921cb0ef41Sopenharmony_civoid EhFrameDisassembler::DisassembleToStream(std::ostream& stream) {
5931cb0ef41Sopenharmony_ci  // The encoded CIE size does not include the size field itself.
5941cb0ef41Sopenharmony_ci  const int cie_size =
5951cb0ef41Sopenharmony_ci      base::ReadUnalignedValue<uint32_t>(reinterpret_cast<Address>(start_)) +
5961cb0ef41Sopenharmony_ci      kInt32Size;
5971cb0ef41Sopenharmony_ci  const int fde_offset = cie_size;
5981cb0ef41Sopenharmony_ci
5991cb0ef41Sopenharmony_ci  const byte* cie_directives_start =
6001cb0ef41Sopenharmony_ci      start_ + EhFrameConstants::kInitialStateOffsetInCie;
6011cb0ef41Sopenharmony_ci  const byte* cie_directives_end = start_ + cie_size;
6021cb0ef41Sopenharmony_ci  DCHECK_LE(cie_directives_start, cie_directives_end);
6031cb0ef41Sopenharmony_ci
6041cb0ef41Sopenharmony_ci  stream << reinterpret_cast<const void*>(start_) << "  .eh_frame: CIE\n";
6051cb0ef41Sopenharmony_ci  DumpDwarfDirectives(stream, cie_directives_start, cie_directives_end);
6061cb0ef41Sopenharmony_ci
6071cb0ef41Sopenharmony_ci  Address procedure_offset_address =
6081cb0ef41Sopenharmony_ci      reinterpret_cast<Address>(start_) + fde_offset +
6091cb0ef41Sopenharmony_ci      EhFrameConstants::kProcedureAddressOffsetInFde;
6101cb0ef41Sopenharmony_ci  int32_t procedure_offset =
6111cb0ef41Sopenharmony_ci      base::ReadUnalignedValue<int32_t>(procedure_offset_address);
6121cb0ef41Sopenharmony_ci
6131cb0ef41Sopenharmony_ci  Address procedure_size_address = reinterpret_cast<Address>(start_) +
6141cb0ef41Sopenharmony_ci                                   fde_offset +
6151cb0ef41Sopenharmony_ci                                   EhFrameConstants::kProcedureSizeOffsetInFde;
6161cb0ef41Sopenharmony_ci  uint32_t procedure_size =
6171cb0ef41Sopenharmony_ci      base::ReadUnalignedValue<uint32_t>(procedure_size_address);
6181cb0ef41Sopenharmony_ci
6191cb0ef41Sopenharmony_ci  const byte* fde_start = start_ + fde_offset;
6201cb0ef41Sopenharmony_ci  stream << reinterpret_cast<const void*>(fde_start) << "  .eh_frame: FDE\n"
6211cb0ef41Sopenharmony_ci         << reinterpret_cast<const void*>(procedure_offset_address)
6221cb0ef41Sopenharmony_ci         << "  | procedure_offset=" << procedure_offset << '\n'
6231cb0ef41Sopenharmony_ci         << reinterpret_cast<const void*>(procedure_size_address)
6241cb0ef41Sopenharmony_ci         << "  | procedure_size=" << procedure_size << '\n';
6251cb0ef41Sopenharmony_ci
6261cb0ef41Sopenharmony_ci  const int fde_directives_offset = fde_offset + 4 * kInt32Size + 1;
6271cb0ef41Sopenharmony_ci
6281cb0ef41Sopenharmony_ci  const byte* fde_directives_start = start_ + fde_directives_offset;
6291cb0ef41Sopenharmony_ci  const byte* fde_directives_end = end_ - EhFrameConstants::kEhFrameHdrSize -
6301cb0ef41Sopenharmony_ci                                   EhFrameConstants::kEhFrameTerminatorSize;
6311cb0ef41Sopenharmony_ci  DCHECK_LE(fde_directives_start, fde_directives_end);
6321cb0ef41Sopenharmony_ci
6331cb0ef41Sopenharmony_ci  DumpDwarfDirectives(stream, fde_directives_start, fde_directives_end);
6341cb0ef41Sopenharmony_ci
6351cb0ef41Sopenharmony_ci  const byte* fde_terminator_start = fde_directives_end;
6361cb0ef41Sopenharmony_ci  stream << reinterpret_cast<const void*>(fde_terminator_start)
6371cb0ef41Sopenharmony_ci         << "  .eh_frame: terminator\n";
6381cb0ef41Sopenharmony_ci
6391cb0ef41Sopenharmony_ci  const byte* eh_frame_hdr_start =
6401cb0ef41Sopenharmony_ci      fde_terminator_start + EhFrameConstants::kEhFrameTerminatorSize;
6411cb0ef41Sopenharmony_ci  stream << reinterpret_cast<const void*>(eh_frame_hdr_start)
6421cb0ef41Sopenharmony_ci         << "  .eh_frame_hdr\n";
6431cb0ef41Sopenharmony_ci}
6441cb0ef41Sopenharmony_ci
6451cb0ef41Sopenharmony_ci#endif
6461cb0ef41Sopenharmony_ci
6471cb0ef41Sopenharmony_ci}  // namespace internal
6481cb0ef41Sopenharmony_ci}  // namespace v8
649