11cb0ef41Sopenharmony_ci// Copyright 2010 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/gdb-jit.h"
61cb0ef41Sopenharmony_ci
71cb0ef41Sopenharmony_ci#include <iterator>
81cb0ef41Sopenharmony_ci#include <map>
91cb0ef41Sopenharmony_ci#include <memory>
101cb0ef41Sopenharmony_ci#include <vector>
111cb0ef41Sopenharmony_ci
121cb0ef41Sopenharmony_ci#include "include/v8-callbacks.h"
131cb0ef41Sopenharmony_ci#include "src/api/api-inl.h"
141cb0ef41Sopenharmony_ci#include "src/base/address-region.h"
151cb0ef41Sopenharmony_ci#include "src/base/bits.h"
161cb0ef41Sopenharmony_ci#include "src/base/hashmap.h"
171cb0ef41Sopenharmony_ci#include "src/base/memory.h"
181cb0ef41Sopenharmony_ci#include "src/base/platform/platform.h"
191cb0ef41Sopenharmony_ci#include "src/base/platform/wrappers.h"
201cb0ef41Sopenharmony_ci#include "src/base/strings.h"
211cb0ef41Sopenharmony_ci#include "src/base/vector.h"
221cb0ef41Sopenharmony_ci#include "src/execution/frames-inl.h"
231cb0ef41Sopenharmony_ci#include "src/execution/frames.h"
241cb0ef41Sopenharmony_ci#include "src/handles/global-handles.h"
251cb0ef41Sopenharmony_ci#include "src/init/bootstrapper.h"
261cb0ef41Sopenharmony_ci#include "src/objects/objects.h"
271cb0ef41Sopenharmony_ci#include "src/utils/ostreams.h"
281cb0ef41Sopenharmony_ci#include "src/zone/zone-chunk-list.h"
291cb0ef41Sopenharmony_ci
301cb0ef41Sopenharmony_cinamespace v8 {
311cb0ef41Sopenharmony_cinamespace internal {
321cb0ef41Sopenharmony_cinamespace GDBJITInterface {
331cb0ef41Sopenharmony_ci
341cb0ef41Sopenharmony_ci#ifdef ENABLE_GDB_JIT_INTERFACE
351cb0ef41Sopenharmony_ci
361cb0ef41Sopenharmony_ci#ifdef __APPLE__
371cb0ef41Sopenharmony_ci#define __MACH_O
381cb0ef41Sopenharmony_ciclass MachO;
391cb0ef41Sopenharmony_ciclass MachOSection;
401cb0ef41Sopenharmony_ciusing DebugObject = MachO;
411cb0ef41Sopenharmony_ciusing DebugSection = MachOSection;
421cb0ef41Sopenharmony_ci#else
431cb0ef41Sopenharmony_ci#define __ELF
441cb0ef41Sopenharmony_ciclass ELF;
451cb0ef41Sopenharmony_ciclass ELFSection;
461cb0ef41Sopenharmony_ciusing DebugObject = ELF;
471cb0ef41Sopenharmony_ciusing DebugSection = ELFSection;
481cb0ef41Sopenharmony_ci#endif
491cb0ef41Sopenharmony_ci
501cb0ef41Sopenharmony_ciclass Writer {
511cb0ef41Sopenharmony_ci public:
521cb0ef41Sopenharmony_ci  explicit Writer(DebugObject* debug_object)
531cb0ef41Sopenharmony_ci      : debug_object_(debug_object),
541cb0ef41Sopenharmony_ci        position_(0),
551cb0ef41Sopenharmony_ci        capacity_(1024),
561cb0ef41Sopenharmony_ci        buffer_(reinterpret_cast<byte*>(base::Malloc(capacity_))) {}
571cb0ef41Sopenharmony_ci
581cb0ef41Sopenharmony_ci  ~Writer() { base::Free(buffer_); }
591cb0ef41Sopenharmony_ci
601cb0ef41Sopenharmony_ci  uintptr_t position() const { return position_; }
611cb0ef41Sopenharmony_ci
621cb0ef41Sopenharmony_ci  template <typename T>
631cb0ef41Sopenharmony_ci  class Slot {
641cb0ef41Sopenharmony_ci   public:
651cb0ef41Sopenharmony_ci    Slot(Writer* w, uintptr_t offset) : w_(w), offset_(offset) {}
661cb0ef41Sopenharmony_ci
671cb0ef41Sopenharmony_ci    T* operator->() { return w_->RawSlotAt<T>(offset_); }
681cb0ef41Sopenharmony_ci
691cb0ef41Sopenharmony_ci    void set(const T& value) {
701cb0ef41Sopenharmony_ci      base::WriteUnalignedValue(w_->AddressAt<T>(offset_), value);
711cb0ef41Sopenharmony_ci    }
721cb0ef41Sopenharmony_ci
731cb0ef41Sopenharmony_ci    Slot<T> at(int i) { return Slot<T>(w_, offset_ + sizeof(T) * i); }
741cb0ef41Sopenharmony_ci
751cb0ef41Sopenharmony_ci   private:
761cb0ef41Sopenharmony_ci    Writer* w_;
771cb0ef41Sopenharmony_ci    uintptr_t offset_;
781cb0ef41Sopenharmony_ci  };
791cb0ef41Sopenharmony_ci
801cb0ef41Sopenharmony_ci  template <typename T>
811cb0ef41Sopenharmony_ci  void Write(const T& val) {
821cb0ef41Sopenharmony_ci    Ensure(position_ + sizeof(T));
831cb0ef41Sopenharmony_ci    base::WriteUnalignedValue(AddressAt<T>(position_), val);
841cb0ef41Sopenharmony_ci    position_ += sizeof(T);
851cb0ef41Sopenharmony_ci  }
861cb0ef41Sopenharmony_ci
871cb0ef41Sopenharmony_ci  template <typename T>
881cb0ef41Sopenharmony_ci  Slot<T> SlotAt(uintptr_t offset) {
891cb0ef41Sopenharmony_ci    Ensure(offset + sizeof(T));
901cb0ef41Sopenharmony_ci    return Slot<T>(this, offset);
911cb0ef41Sopenharmony_ci  }
921cb0ef41Sopenharmony_ci
931cb0ef41Sopenharmony_ci  template <typename T>
941cb0ef41Sopenharmony_ci  Slot<T> CreateSlotHere() {
951cb0ef41Sopenharmony_ci    return CreateSlotsHere<T>(1);
961cb0ef41Sopenharmony_ci  }
971cb0ef41Sopenharmony_ci
981cb0ef41Sopenharmony_ci  template <typename T>
991cb0ef41Sopenharmony_ci  Slot<T> CreateSlotsHere(uint32_t count) {
1001cb0ef41Sopenharmony_ci    uintptr_t slot_position = position_;
1011cb0ef41Sopenharmony_ci    position_ += sizeof(T) * count;
1021cb0ef41Sopenharmony_ci    Ensure(position_);
1031cb0ef41Sopenharmony_ci    return SlotAt<T>(slot_position);
1041cb0ef41Sopenharmony_ci  }
1051cb0ef41Sopenharmony_ci
1061cb0ef41Sopenharmony_ci  void Ensure(uintptr_t pos) {
1071cb0ef41Sopenharmony_ci    if (capacity_ < pos) {
1081cb0ef41Sopenharmony_ci      while (capacity_ < pos) capacity_ *= 2;
1091cb0ef41Sopenharmony_ci      buffer_ = reinterpret_cast<byte*>(base::Realloc(buffer_, capacity_));
1101cb0ef41Sopenharmony_ci    }
1111cb0ef41Sopenharmony_ci  }
1121cb0ef41Sopenharmony_ci
1131cb0ef41Sopenharmony_ci  DebugObject* debug_object() { return debug_object_; }
1141cb0ef41Sopenharmony_ci
1151cb0ef41Sopenharmony_ci  byte* buffer() { return buffer_; }
1161cb0ef41Sopenharmony_ci
1171cb0ef41Sopenharmony_ci  void Align(uintptr_t align) {
1181cb0ef41Sopenharmony_ci    uintptr_t delta = position_ % align;
1191cb0ef41Sopenharmony_ci    if (delta == 0) return;
1201cb0ef41Sopenharmony_ci    uintptr_t padding = align - delta;
1211cb0ef41Sopenharmony_ci    Ensure(position_ += padding);
1221cb0ef41Sopenharmony_ci    DCHECK_EQ(position_ % align, 0);
1231cb0ef41Sopenharmony_ci  }
1241cb0ef41Sopenharmony_ci
1251cb0ef41Sopenharmony_ci  void WriteULEB128(uintptr_t value) {
1261cb0ef41Sopenharmony_ci    do {
1271cb0ef41Sopenharmony_ci      uint8_t byte = value & 0x7F;
1281cb0ef41Sopenharmony_ci      value >>= 7;
1291cb0ef41Sopenharmony_ci      if (value != 0) byte |= 0x80;
1301cb0ef41Sopenharmony_ci      Write<uint8_t>(byte);
1311cb0ef41Sopenharmony_ci    } while (value != 0);
1321cb0ef41Sopenharmony_ci  }
1331cb0ef41Sopenharmony_ci
1341cb0ef41Sopenharmony_ci  void WriteSLEB128(intptr_t value) {
1351cb0ef41Sopenharmony_ci    bool more = true;
1361cb0ef41Sopenharmony_ci    while (more) {
1371cb0ef41Sopenharmony_ci      int8_t byte = value & 0x7F;
1381cb0ef41Sopenharmony_ci      bool byte_sign = byte & 0x40;
1391cb0ef41Sopenharmony_ci      value >>= 7;
1401cb0ef41Sopenharmony_ci
1411cb0ef41Sopenharmony_ci      if ((value == 0 && !byte_sign) || (value == -1 && byte_sign)) {
1421cb0ef41Sopenharmony_ci        more = false;
1431cb0ef41Sopenharmony_ci      } else {
1441cb0ef41Sopenharmony_ci        byte |= 0x80;
1451cb0ef41Sopenharmony_ci      }
1461cb0ef41Sopenharmony_ci
1471cb0ef41Sopenharmony_ci      Write<int8_t>(byte);
1481cb0ef41Sopenharmony_ci    }
1491cb0ef41Sopenharmony_ci  }
1501cb0ef41Sopenharmony_ci
1511cb0ef41Sopenharmony_ci  void WriteString(const char* str) {
1521cb0ef41Sopenharmony_ci    do {
1531cb0ef41Sopenharmony_ci      Write<char>(*str);
1541cb0ef41Sopenharmony_ci    } while (*str++);
1551cb0ef41Sopenharmony_ci  }
1561cb0ef41Sopenharmony_ci
1571cb0ef41Sopenharmony_ci private:
1581cb0ef41Sopenharmony_ci  template <typename T>
1591cb0ef41Sopenharmony_ci  friend class Slot;
1601cb0ef41Sopenharmony_ci
1611cb0ef41Sopenharmony_ci  template <typename T>
1621cb0ef41Sopenharmony_ci  Address AddressAt(uintptr_t offset) {
1631cb0ef41Sopenharmony_ci    DCHECK(offset < capacity_ && offset + sizeof(T) <= capacity_);
1641cb0ef41Sopenharmony_ci    return reinterpret_cast<Address>(&buffer_[offset]);
1651cb0ef41Sopenharmony_ci  }
1661cb0ef41Sopenharmony_ci
1671cb0ef41Sopenharmony_ci  template <typename T>
1681cb0ef41Sopenharmony_ci  T* RawSlotAt(uintptr_t offset) {
1691cb0ef41Sopenharmony_ci    DCHECK(offset < capacity_ && offset + sizeof(T) <= capacity_);
1701cb0ef41Sopenharmony_ci    return reinterpret_cast<T*>(&buffer_[offset]);
1711cb0ef41Sopenharmony_ci  }
1721cb0ef41Sopenharmony_ci
1731cb0ef41Sopenharmony_ci  DebugObject* debug_object_;
1741cb0ef41Sopenharmony_ci  uintptr_t position_;
1751cb0ef41Sopenharmony_ci  uintptr_t capacity_;
1761cb0ef41Sopenharmony_ci  byte* buffer_;
1771cb0ef41Sopenharmony_ci};
1781cb0ef41Sopenharmony_ci
1791cb0ef41Sopenharmony_ciclass ELFStringTable;
1801cb0ef41Sopenharmony_ci
1811cb0ef41Sopenharmony_citemplate <typename THeader>
1821cb0ef41Sopenharmony_ciclass DebugSectionBase : public ZoneObject {
1831cb0ef41Sopenharmony_ci public:
1841cb0ef41Sopenharmony_ci  virtual ~DebugSectionBase() = default;
1851cb0ef41Sopenharmony_ci
1861cb0ef41Sopenharmony_ci  virtual void WriteBody(Writer::Slot<THeader> header, Writer* writer) {
1871cb0ef41Sopenharmony_ci    uintptr_t start = writer->position();
1881cb0ef41Sopenharmony_ci    if (WriteBodyInternal(writer)) {
1891cb0ef41Sopenharmony_ci      uintptr_t end = writer->position();
1901cb0ef41Sopenharmony_ci      header->offset = static_cast<uint32_t>(start);
1911cb0ef41Sopenharmony_ci#if defined(__MACH_O)
1921cb0ef41Sopenharmony_ci      header->addr = 0;
1931cb0ef41Sopenharmony_ci#endif
1941cb0ef41Sopenharmony_ci      header->size = end - start;
1951cb0ef41Sopenharmony_ci    }
1961cb0ef41Sopenharmony_ci  }
1971cb0ef41Sopenharmony_ci
1981cb0ef41Sopenharmony_ci  virtual bool WriteBodyInternal(Writer* writer) { return false; }
1991cb0ef41Sopenharmony_ci
2001cb0ef41Sopenharmony_ci  using Header = THeader;
2011cb0ef41Sopenharmony_ci};
2021cb0ef41Sopenharmony_ci
2031cb0ef41Sopenharmony_cistruct MachOSectionHeader {
2041cb0ef41Sopenharmony_ci  char sectname[16];
2051cb0ef41Sopenharmony_ci  char segname[16];
2061cb0ef41Sopenharmony_ci#if V8_TARGET_ARCH_IA32
2071cb0ef41Sopenharmony_ci  uint32_t addr;
2081cb0ef41Sopenharmony_ci  uint32_t size;
2091cb0ef41Sopenharmony_ci#else
2101cb0ef41Sopenharmony_ci  uint64_t addr;
2111cb0ef41Sopenharmony_ci  uint64_t size;
2121cb0ef41Sopenharmony_ci#endif
2131cb0ef41Sopenharmony_ci  uint32_t offset;
2141cb0ef41Sopenharmony_ci  uint32_t align;
2151cb0ef41Sopenharmony_ci  uint32_t reloff;
2161cb0ef41Sopenharmony_ci  uint32_t nreloc;
2171cb0ef41Sopenharmony_ci  uint32_t flags;
2181cb0ef41Sopenharmony_ci  uint32_t reserved1;
2191cb0ef41Sopenharmony_ci  uint32_t reserved2;
2201cb0ef41Sopenharmony_ci};
2211cb0ef41Sopenharmony_ci
2221cb0ef41Sopenharmony_ciclass MachOSection : public DebugSectionBase<MachOSectionHeader> {
2231cb0ef41Sopenharmony_ci public:
2241cb0ef41Sopenharmony_ci  enum Type {
2251cb0ef41Sopenharmony_ci    S_REGULAR = 0x0u,
2261cb0ef41Sopenharmony_ci    S_ATTR_COALESCED = 0xBu,
2271cb0ef41Sopenharmony_ci    S_ATTR_SOME_INSTRUCTIONS = 0x400u,
2281cb0ef41Sopenharmony_ci    S_ATTR_DEBUG = 0x02000000u,
2291cb0ef41Sopenharmony_ci    S_ATTR_PURE_INSTRUCTIONS = 0x80000000u
2301cb0ef41Sopenharmony_ci  };
2311cb0ef41Sopenharmony_ci
2321cb0ef41Sopenharmony_ci  MachOSection(const char* name, const char* segment, uint32_t align,
2331cb0ef41Sopenharmony_ci               uint32_t flags)
2341cb0ef41Sopenharmony_ci      : name_(name), segment_(segment), align_(align), flags_(flags) {
2351cb0ef41Sopenharmony_ci    if (align_ != 0) {
2361cb0ef41Sopenharmony_ci      DCHECK(base::bits::IsPowerOfTwo(align));
2371cb0ef41Sopenharmony_ci      align_ = base::bits::WhichPowerOfTwo(align_);
2381cb0ef41Sopenharmony_ci    }
2391cb0ef41Sopenharmony_ci  }
2401cb0ef41Sopenharmony_ci
2411cb0ef41Sopenharmony_ci  ~MachOSection() override = default;
2421cb0ef41Sopenharmony_ci
2431cb0ef41Sopenharmony_ci  virtual void PopulateHeader(Writer::Slot<Header> header) {
2441cb0ef41Sopenharmony_ci    header->addr = 0;
2451cb0ef41Sopenharmony_ci    header->size = 0;
2461cb0ef41Sopenharmony_ci    header->offset = 0;
2471cb0ef41Sopenharmony_ci    header->align = align_;
2481cb0ef41Sopenharmony_ci    header->reloff = 0;
2491cb0ef41Sopenharmony_ci    header->nreloc = 0;
2501cb0ef41Sopenharmony_ci    header->flags = flags_;
2511cb0ef41Sopenharmony_ci    header->reserved1 = 0;
2521cb0ef41Sopenharmony_ci    header->reserved2 = 0;
2531cb0ef41Sopenharmony_ci    memset(header->sectname, 0, sizeof(header->sectname));
2541cb0ef41Sopenharmony_ci    memset(header->segname, 0, sizeof(header->segname));
2551cb0ef41Sopenharmony_ci    DCHECK(strlen(name_) < sizeof(header->sectname));
2561cb0ef41Sopenharmony_ci    DCHECK(strlen(segment_) < sizeof(header->segname));
2571cb0ef41Sopenharmony_ci    strncpy(header->sectname, name_, sizeof(header->sectname));
2581cb0ef41Sopenharmony_ci    strncpy(header->segname, segment_, sizeof(header->segname));
2591cb0ef41Sopenharmony_ci  }
2601cb0ef41Sopenharmony_ci
2611cb0ef41Sopenharmony_ci private:
2621cb0ef41Sopenharmony_ci  const char* name_;
2631cb0ef41Sopenharmony_ci  const char* segment_;
2641cb0ef41Sopenharmony_ci  uint32_t align_;
2651cb0ef41Sopenharmony_ci  uint32_t flags_;
2661cb0ef41Sopenharmony_ci};
2671cb0ef41Sopenharmony_ci
2681cb0ef41Sopenharmony_cistruct ELFSectionHeader {
2691cb0ef41Sopenharmony_ci  uint32_t name;
2701cb0ef41Sopenharmony_ci  uint32_t type;
2711cb0ef41Sopenharmony_ci  uintptr_t flags;
2721cb0ef41Sopenharmony_ci  uintptr_t address;
2731cb0ef41Sopenharmony_ci  uintptr_t offset;
2741cb0ef41Sopenharmony_ci  uintptr_t size;
2751cb0ef41Sopenharmony_ci  uint32_t link;
2761cb0ef41Sopenharmony_ci  uint32_t info;
2771cb0ef41Sopenharmony_ci  uintptr_t alignment;
2781cb0ef41Sopenharmony_ci  uintptr_t entry_size;
2791cb0ef41Sopenharmony_ci};
2801cb0ef41Sopenharmony_ci
2811cb0ef41Sopenharmony_ci#if defined(__ELF)
2821cb0ef41Sopenharmony_ciclass ELFSection : public DebugSectionBase<ELFSectionHeader> {
2831cb0ef41Sopenharmony_ci public:
2841cb0ef41Sopenharmony_ci  enum Type {
2851cb0ef41Sopenharmony_ci    TYPE_NULL = 0,
2861cb0ef41Sopenharmony_ci    TYPE_PROGBITS = 1,
2871cb0ef41Sopenharmony_ci    TYPE_SYMTAB = 2,
2881cb0ef41Sopenharmony_ci    TYPE_STRTAB = 3,
2891cb0ef41Sopenharmony_ci    TYPE_RELA = 4,
2901cb0ef41Sopenharmony_ci    TYPE_HASH = 5,
2911cb0ef41Sopenharmony_ci    TYPE_DYNAMIC = 6,
2921cb0ef41Sopenharmony_ci    TYPE_NOTE = 7,
2931cb0ef41Sopenharmony_ci    TYPE_NOBITS = 8,
2941cb0ef41Sopenharmony_ci    TYPE_REL = 9,
2951cb0ef41Sopenharmony_ci    TYPE_SHLIB = 10,
2961cb0ef41Sopenharmony_ci    TYPE_DYNSYM = 11,
2971cb0ef41Sopenharmony_ci    TYPE_LOPROC = 0x70000000,
2981cb0ef41Sopenharmony_ci    TYPE_X86_64_UNWIND = 0x70000001,
2991cb0ef41Sopenharmony_ci    TYPE_HIPROC = 0x7FFFFFFF,
3001cb0ef41Sopenharmony_ci    TYPE_LOUSER = 0x80000000,
3011cb0ef41Sopenharmony_ci    TYPE_HIUSER = 0xFFFFFFFF
3021cb0ef41Sopenharmony_ci  };
3031cb0ef41Sopenharmony_ci
3041cb0ef41Sopenharmony_ci  enum Flags { FLAG_WRITE = 1, FLAG_ALLOC = 2, FLAG_EXEC = 4 };
3051cb0ef41Sopenharmony_ci
3061cb0ef41Sopenharmony_ci  enum SpecialIndexes { INDEX_ABSOLUTE = 0xFFF1 };
3071cb0ef41Sopenharmony_ci
3081cb0ef41Sopenharmony_ci  ELFSection(const char* name, Type type, uintptr_t align)
3091cb0ef41Sopenharmony_ci      : name_(name), type_(type), align_(align) {}
3101cb0ef41Sopenharmony_ci
3111cb0ef41Sopenharmony_ci  ~ELFSection() override = default;
3121cb0ef41Sopenharmony_ci
3131cb0ef41Sopenharmony_ci  void PopulateHeader(Writer::Slot<Header> header, ELFStringTable* strtab);
3141cb0ef41Sopenharmony_ci
3151cb0ef41Sopenharmony_ci  void WriteBody(Writer::Slot<Header> header, Writer* w) override {
3161cb0ef41Sopenharmony_ci    uintptr_t start = w->position();
3171cb0ef41Sopenharmony_ci    if (WriteBodyInternal(w)) {
3181cb0ef41Sopenharmony_ci      uintptr_t end = w->position();
3191cb0ef41Sopenharmony_ci      header->offset = start;
3201cb0ef41Sopenharmony_ci      header->size = end - start;
3211cb0ef41Sopenharmony_ci    }
3221cb0ef41Sopenharmony_ci  }
3231cb0ef41Sopenharmony_ci
3241cb0ef41Sopenharmony_ci  bool WriteBodyInternal(Writer* w) override { return false; }
3251cb0ef41Sopenharmony_ci
3261cb0ef41Sopenharmony_ci  uint16_t index() const { return index_; }
3271cb0ef41Sopenharmony_ci  void set_index(uint16_t index) { index_ = index; }
3281cb0ef41Sopenharmony_ci
3291cb0ef41Sopenharmony_ci protected:
3301cb0ef41Sopenharmony_ci  virtual void PopulateHeader(Writer::Slot<Header> header) {
3311cb0ef41Sopenharmony_ci    header->flags = 0;
3321cb0ef41Sopenharmony_ci    header->address = 0;
3331cb0ef41Sopenharmony_ci    header->offset = 0;
3341cb0ef41Sopenharmony_ci    header->size = 0;
3351cb0ef41Sopenharmony_ci    header->link = 0;
3361cb0ef41Sopenharmony_ci    header->info = 0;
3371cb0ef41Sopenharmony_ci    header->entry_size = 0;
3381cb0ef41Sopenharmony_ci  }
3391cb0ef41Sopenharmony_ci
3401cb0ef41Sopenharmony_ci private:
3411cb0ef41Sopenharmony_ci  const char* name_;
3421cb0ef41Sopenharmony_ci  Type type_;
3431cb0ef41Sopenharmony_ci  uintptr_t align_;
3441cb0ef41Sopenharmony_ci  uint16_t index_;
3451cb0ef41Sopenharmony_ci};
3461cb0ef41Sopenharmony_ci#endif  // defined(__ELF)
3471cb0ef41Sopenharmony_ci
3481cb0ef41Sopenharmony_ci#if defined(__MACH_O)
3491cb0ef41Sopenharmony_ciclass MachOTextSection : public MachOSection {
3501cb0ef41Sopenharmony_ci public:
3511cb0ef41Sopenharmony_ci  MachOTextSection(uint32_t align, uintptr_t addr, uintptr_t size)
3521cb0ef41Sopenharmony_ci      : MachOSection("__text", "__TEXT", align,
3531cb0ef41Sopenharmony_ci                     MachOSection::S_REGULAR |
3541cb0ef41Sopenharmony_ci                         MachOSection::S_ATTR_SOME_INSTRUCTIONS |
3551cb0ef41Sopenharmony_ci                         MachOSection::S_ATTR_PURE_INSTRUCTIONS),
3561cb0ef41Sopenharmony_ci        addr_(addr),
3571cb0ef41Sopenharmony_ci        size_(size) {}
3581cb0ef41Sopenharmony_ci
3591cb0ef41Sopenharmony_ci protected:
3601cb0ef41Sopenharmony_ci  virtual void PopulateHeader(Writer::Slot<Header> header) {
3611cb0ef41Sopenharmony_ci    MachOSection::PopulateHeader(header);
3621cb0ef41Sopenharmony_ci    header->addr = addr_;
3631cb0ef41Sopenharmony_ci    header->size = size_;
3641cb0ef41Sopenharmony_ci  }
3651cb0ef41Sopenharmony_ci
3661cb0ef41Sopenharmony_ci private:
3671cb0ef41Sopenharmony_ci  uintptr_t addr_;
3681cb0ef41Sopenharmony_ci  uintptr_t size_;
3691cb0ef41Sopenharmony_ci};
3701cb0ef41Sopenharmony_ci#endif  // defined(__MACH_O)
3711cb0ef41Sopenharmony_ci
3721cb0ef41Sopenharmony_ci#if defined(__ELF)
3731cb0ef41Sopenharmony_ciclass FullHeaderELFSection : public ELFSection {
3741cb0ef41Sopenharmony_ci public:
3751cb0ef41Sopenharmony_ci  FullHeaderELFSection(const char* name, Type type, uintptr_t align,
3761cb0ef41Sopenharmony_ci                       uintptr_t addr, uintptr_t offset, uintptr_t size,
3771cb0ef41Sopenharmony_ci                       uintptr_t flags)
3781cb0ef41Sopenharmony_ci      : ELFSection(name, type, align),
3791cb0ef41Sopenharmony_ci        addr_(addr),
3801cb0ef41Sopenharmony_ci        offset_(offset),
3811cb0ef41Sopenharmony_ci        size_(size),
3821cb0ef41Sopenharmony_ci        flags_(flags) {}
3831cb0ef41Sopenharmony_ci
3841cb0ef41Sopenharmony_ci protected:
3851cb0ef41Sopenharmony_ci  void PopulateHeader(Writer::Slot<Header> header) override {
3861cb0ef41Sopenharmony_ci    ELFSection::PopulateHeader(header);
3871cb0ef41Sopenharmony_ci    header->address = addr_;
3881cb0ef41Sopenharmony_ci    header->offset = offset_;
3891cb0ef41Sopenharmony_ci    header->size = size_;
3901cb0ef41Sopenharmony_ci    header->flags = flags_;
3911cb0ef41Sopenharmony_ci  }
3921cb0ef41Sopenharmony_ci
3931cb0ef41Sopenharmony_ci private:
3941cb0ef41Sopenharmony_ci  uintptr_t addr_;
3951cb0ef41Sopenharmony_ci  uintptr_t offset_;
3961cb0ef41Sopenharmony_ci  uintptr_t size_;
3971cb0ef41Sopenharmony_ci  uintptr_t flags_;
3981cb0ef41Sopenharmony_ci};
3991cb0ef41Sopenharmony_ci
4001cb0ef41Sopenharmony_ciclass ELFStringTable : public ELFSection {
4011cb0ef41Sopenharmony_ci public:
4021cb0ef41Sopenharmony_ci  explicit ELFStringTable(const char* name)
4031cb0ef41Sopenharmony_ci      : ELFSection(name, TYPE_STRTAB, 1),
4041cb0ef41Sopenharmony_ci        writer_(nullptr),
4051cb0ef41Sopenharmony_ci        offset_(0),
4061cb0ef41Sopenharmony_ci        size_(0) {}
4071cb0ef41Sopenharmony_ci
4081cb0ef41Sopenharmony_ci  uintptr_t Add(const char* str) {
4091cb0ef41Sopenharmony_ci    if (*str == '\0') return 0;
4101cb0ef41Sopenharmony_ci
4111cb0ef41Sopenharmony_ci    uintptr_t offset = size_;
4121cb0ef41Sopenharmony_ci    WriteString(str);
4131cb0ef41Sopenharmony_ci    return offset;
4141cb0ef41Sopenharmony_ci  }
4151cb0ef41Sopenharmony_ci
4161cb0ef41Sopenharmony_ci  void AttachWriter(Writer* w) {
4171cb0ef41Sopenharmony_ci    writer_ = w;
4181cb0ef41Sopenharmony_ci    offset_ = writer_->position();
4191cb0ef41Sopenharmony_ci
4201cb0ef41Sopenharmony_ci    // First entry in the string table should be an empty string.
4211cb0ef41Sopenharmony_ci    WriteString("");
4221cb0ef41Sopenharmony_ci  }
4231cb0ef41Sopenharmony_ci
4241cb0ef41Sopenharmony_ci  void DetachWriter() { writer_ = nullptr; }
4251cb0ef41Sopenharmony_ci
4261cb0ef41Sopenharmony_ci  void WriteBody(Writer::Slot<Header> header, Writer* w) override {
4271cb0ef41Sopenharmony_ci    DCHECK_NULL(writer_);
4281cb0ef41Sopenharmony_ci    header->offset = offset_;
4291cb0ef41Sopenharmony_ci    header->size = size_;
4301cb0ef41Sopenharmony_ci  }
4311cb0ef41Sopenharmony_ci
4321cb0ef41Sopenharmony_ci private:
4331cb0ef41Sopenharmony_ci  void WriteString(const char* str) {
4341cb0ef41Sopenharmony_ci    uintptr_t written = 0;
4351cb0ef41Sopenharmony_ci    do {
4361cb0ef41Sopenharmony_ci      writer_->Write(*str);
4371cb0ef41Sopenharmony_ci      written++;
4381cb0ef41Sopenharmony_ci    } while (*str++);
4391cb0ef41Sopenharmony_ci    size_ += written;
4401cb0ef41Sopenharmony_ci  }
4411cb0ef41Sopenharmony_ci
4421cb0ef41Sopenharmony_ci  Writer* writer_;
4431cb0ef41Sopenharmony_ci
4441cb0ef41Sopenharmony_ci  uintptr_t offset_;
4451cb0ef41Sopenharmony_ci  uintptr_t size_;
4461cb0ef41Sopenharmony_ci};
4471cb0ef41Sopenharmony_ci
4481cb0ef41Sopenharmony_civoid ELFSection::PopulateHeader(Writer::Slot<ELFSection::Header> header,
4491cb0ef41Sopenharmony_ci                                ELFStringTable* strtab) {
4501cb0ef41Sopenharmony_ci  header->name = static_cast<uint32_t>(strtab->Add(name_));
4511cb0ef41Sopenharmony_ci  header->type = type_;
4521cb0ef41Sopenharmony_ci  header->alignment = align_;
4531cb0ef41Sopenharmony_ci  PopulateHeader(header);
4541cb0ef41Sopenharmony_ci}
4551cb0ef41Sopenharmony_ci#endif  // defined(__ELF)
4561cb0ef41Sopenharmony_ci
4571cb0ef41Sopenharmony_ci#if defined(__MACH_O)
4581cb0ef41Sopenharmony_ciclass MachO {
4591cb0ef41Sopenharmony_ci public:
4601cb0ef41Sopenharmony_ci  explicit MachO(Zone* zone) : sections_(zone) {}
4611cb0ef41Sopenharmony_ci
4621cb0ef41Sopenharmony_ci  size_t AddSection(MachOSection* section) {
4631cb0ef41Sopenharmony_ci    sections_.push_back(section);
4641cb0ef41Sopenharmony_ci    return sections_.size() - 1;
4651cb0ef41Sopenharmony_ci  }
4661cb0ef41Sopenharmony_ci
4671cb0ef41Sopenharmony_ci  void Write(Writer* w, uintptr_t code_start, uintptr_t code_size) {
4681cb0ef41Sopenharmony_ci    Writer::Slot<MachOHeader> header = WriteHeader(w);
4691cb0ef41Sopenharmony_ci    uintptr_t load_command_start = w->position();
4701cb0ef41Sopenharmony_ci    Writer::Slot<MachOSegmentCommand> cmd =
4711cb0ef41Sopenharmony_ci        WriteSegmentCommand(w, code_start, code_size);
4721cb0ef41Sopenharmony_ci    WriteSections(w, cmd, header, load_command_start);
4731cb0ef41Sopenharmony_ci  }
4741cb0ef41Sopenharmony_ci
4751cb0ef41Sopenharmony_ci private:
4761cb0ef41Sopenharmony_ci  struct MachOHeader {
4771cb0ef41Sopenharmony_ci    uint32_t magic;
4781cb0ef41Sopenharmony_ci    uint32_t cputype;
4791cb0ef41Sopenharmony_ci    uint32_t cpusubtype;
4801cb0ef41Sopenharmony_ci    uint32_t filetype;
4811cb0ef41Sopenharmony_ci    uint32_t ncmds;
4821cb0ef41Sopenharmony_ci    uint32_t sizeofcmds;
4831cb0ef41Sopenharmony_ci    uint32_t flags;
4841cb0ef41Sopenharmony_ci#if V8_TARGET_ARCH_X64
4851cb0ef41Sopenharmony_ci    uint32_t reserved;
4861cb0ef41Sopenharmony_ci#endif
4871cb0ef41Sopenharmony_ci  };
4881cb0ef41Sopenharmony_ci
4891cb0ef41Sopenharmony_ci  struct MachOSegmentCommand {
4901cb0ef41Sopenharmony_ci    uint32_t cmd;
4911cb0ef41Sopenharmony_ci    uint32_t cmdsize;
4921cb0ef41Sopenharmony_ci    char segname[16];
4931cb0ef41Sopenharmony_ci#if V8_TARGET_ARCH_IA32
4941cb0ef41Sopenharmony_ci    uint32_t vmaddr;
4951cb0ef41Sopenharmony_ci    uint32_t vmsize;
4961cb0ef41Sopenharmony_ci    uint32_t fileoff;
4971cb0ef41Sopenharmony_ci    uint32_t filesize;
4981cb0ef41Sopenharmony_ci#else
4991cb0ef41Sopenharmony_ci    uint64_t vmaddr;
5001cb0ef41Sopenharmony_ci    uint64_t vmsize;
5011cb0ef41Sopenharmony_ci    uint64_t fileoff;
5021cb0ef41Sopenharmony_ci    uint64_t filesize;
5031cb0ef41Sopenharmony_ci#endif
5041cb0ef41Sopenharmony_ci    uint32_t maxprot;
5051cb0ef41Sopenharmony_ci    uint32_t initprot;
5061cb0ef41Sopenharmony_ci    uint32_t nsects;
5071cb0ef41Sopenharmony_ci    uint32_t flags;
5081cb0ef41Sopenharmony_ci  };
5091cb0ef41Sopenharmony_ci
5101cb0ef41Sopenharmony_ci  enum MachOLoadCommandCmd {
5111cb0ef41Sopenharmony_ci    LC_SEGMENT_32 = 0x00000001u,
5121cb0ef41Sopenharmony_ci    LC_SEGMENT_64 = 0x00000019u
5131cb0ef41Sopenharmony_ci  };
5141cb0ef41Sopenharmony_ci
5151cb0ef41Sopenharmony_ci  Writer::Slot<MachOHeader> WriteHeader(Writer* w) {
5161cb0ef41Sopenharmony_ci    DCHECK_EQ(w->position(), 0);
5171cb0ef41Sopenharmony_ci    Writer::Slot<MachOHeader> header = w->CreateSlotHere<MachOHeader>();
5181cb0ef41Sopenharmony_ci#if V8_TARGET_ARCH_IA32
5191cb0ef41Sopenharmony_ci    header->magic = 0xFEEDFACEu;
5201cb0ef41Sopenharmony_ci    header->cputype = 7;     // i386
5211cb0ef41Sopenharmony_ci    header->cpusubtype = 3;  // CPU_SUBTYPE_I386_ALL
5221cb0ef41Sopenharmony_ci#elif V8_TARGET_ARCH_X64
5231cb0ef41Sopenharmony_ci    header->magic = 0xFEEDFACFu;
5241cb0ef41Sopenharmony_ci    header->cputype = 7 | 0x01000000;  // i386 | 64-bit ABI
5251cb0ef41Sopenharmony_ci    header->cpusubtype = 3;            // CPU_SUBTYPE_I386_ALL
5261cb0ef41Sopenharmony_ci    header->reserved = 0;
5271cb0ef41Sopenharmony_ci#else
5281cb0ef41Sopenharmony_ci#error Unsupported target architecture.
5291cb0ef41Sopenharmony_ci#endif
5301cb0ef41Sopenharmony_ci    header->filetype = 0x1;  // MH_OBJECT
5311cb0ef41Sopenharmony_ci    header->ncmds = 1;
5321cb0ef41Sopenharmony_ci    header->sizeofcmds = 0;
5331cb0ef41Sopenharmony_ci    header->flags = 0;
5341cb0ef41Sopenharmony_ci    return header;
5351cb0ef41Sopenharmony_ci  }
5361cb0ef41Sopenharmony_ci
5371cb0ef41Sopenharmony_ci  Writer::Slot<MachOSegmentCommand> WriteSegmentCommand(Writer* w,
5381cb0ef41Sopenharmony_ci                                                        uintptr_t code_start,
5391cb0ef41Sopenharmony_ci                                                        uintptr_t code_size) {
5401cb0ef41Sopenharmony_ci    Writer::Slot<MachOSegmentCommand> cmd =
5411cb0ef41Sopenharmony_ci        w->CreateSlotHere<MachOSegmentCommand>();
5421cb0ef41Sopenharmony_ci#if V8_TARGET_ARCH_IA32
5431cb0ef41Sopenharmony_ci    cmd->cmd = LC_SEGMENT_32;
5441cb0ef41Sopenharmony_ci#else
5451cb0ef41Sopenharmony_ci    cmd->cmd = LC_SEGMENT_64;
5461cb0ef41Sopenharmony_ci#endif
5471cb0ef41Sopenharmony_ci    cmd->vmaddr = code_start;
5481cb0ef41Sopenharmony_ci    cmd->vmsize = code_size;
5491cb0ef41Sopenharmony_ci    cmd->fileoff = 0;
5501cb0ef41Sopenharmony_ci    cmd->filesize = 0;
5511cb0ef41Sopenharmony_ci    cmd->maxprot = 7;
5521cb0ef41Sopenharmony_ci    cmd->initprot = 7;
5531cb0ef41Sopenharmony_ci    cmd->flags = 0;
5541cb0ef41Sopenharmony_ci    cmd->nsects = static_cast<uint32_t>(sections_.size());
5551cb0ef41Sopenharmony_ci    memset(cmd->segname, 0, 16);
5561cb0ef41Sopenharmony_ci    cmd->cmdsize = sizeof(MachOSegmentCommand) +
5571cb0ef41Sopenharmony_ci                   sizeof(MachOSection::Header) * cmd->nsects;
5581cb0ef41Sopenharmony_ci    return cmd;
5591cb0ef41Sopenharmony_ci  }
5601cb0ef41Sopenharmony_ci
5611cb0ef41Sopenharmony_ci  void WriteSections(Writer* w, Writer::Slot<MachOSegmentCommand> cmd,
5621cb0ef41Sopenharmony_ci                     Writer::Slot<MachOHeader> header,
5631cb0ef41Sopenharmony_ci                     uintptr_t load_command_start) {
5641cb0ef41Sopenharmony_ci    Writer::Slot<MachOSection::Header> headers =
5651cb0ef41Sopenharmony_ci        w->CreateSlotsHere<MachOSection::Header>(
5661cb0ef41Sopenharmony_ci            static_cast<uint32_t>(sections_.size()));
5671cb0ef41Sopenharmony_ci    cmd->fileoff = w->position();
5681cb0ef41Sopenharmony_ci    header->sizeofcmds =
5691cb0ef41Sopenharmony_ci        static_cast<uint32_t>(w->position() - load_command_start);
5701cb0ef41Sopenharmony_ci    uint32_t index = 0;
5711cb0ef41Sopenharmony_ci    for (MachOSection* section : sections_) {
5721cb0ef41Sopenharmony_ci      section->PopulateHeader(headers.at(index));
5731cb0ef41Sopenharmony_ci      section->WriteBody(headers.at(index), w);
5741cb0ef41Sopenharmony_ci      index++;
5751cb0ef41Sopenharmony_ci    }
5761cb0ef41Sopenharmony_ci    cmd->filesize = w->position() - (uintptr_t)cmd->fileoff;
5771cb0ef41Sopenharmony_ci  }
5781cb0ef41Sopenharmony_ci
5791cb0ef41Sopenharmony_ci  ZoneChunkList<MachOSection*> sections_;
5801cb0ef41Sopenharmony_ci};
5811cb0ef41Sopenharmony_ci#endif  // defined(__MACH_O)
5821cb0ef41Sopenharmony_ci
5831cb0ef41Sopenharmony_ci#if defined(__ELF)
5841cb0ef41Sopenharmony_ciclass ELF {
5851cb0ef41Sopenharmony_ci public:
5861cb0ef41Sopenharmony_ci  explicit ELF(Zone* zone) : sections_(zone) {
5871cb0ef41Sopenharmony_ci    sections_.push_back(zone->New<ELFSection>("", ELFSection::TYPE_NULL, 0));
5881cb0ef41Sopenharmony_ci    sections_.push_back(zone->New<ELFStringTable>(".shstrtab"));
5891cb0ef41Sopenharmony_ci  }
5901cb0ef41Sopenharmony_ci
5911cb0ef41Sopenharmony_ci  void Write(Writer* w) {
5921cb0ef41Sopenharmony_ci    WriteHeader(w);
5931cb0ef41Sopenharmony_ci    WriteSectionTable(w);
5941cb0ef41Sopenharmony_ci    WriteSections(w);
5951cb0ef41Sopenharmony_ci  }
5961cb0ef41Sopenharmony_ci
5971cb0ef41Sopenharmony_ci  ELFSection* SectionAt(uint32_t index) { return *sections_.Find(index); }
5981cb0ef41Sopenharmony_ci
5991cb0ef41Sopenharmony_ci  size_t AddSection(ELFSection* section) {
6001cb0ef41Sopenharmony_ci    sections_.push_back(section);
6011cb0ef41Sopenharmony_ci    section->set_index(sections_.size() - 1);
6021cb0ef41Sopenharmony_ci    return sections_.size() - 1;
6031cb0ef41Sopenharmony_ci  }
6041cb0ef41Sopenharmony_ci
6051cb0ef41Sopenharmony_ci private:
6061cb0ef41Sopenharmony_ci  struct ELFHeader {
6071cb0ef41Sopenharmony_ci    uint8_t ident[16];
6081cb0ef41Sopenharmony_ci    uint16_t type;
6091cb0ef41Sopenharmony_ci    uint16_t machine;
6101cb0ef41Sopenharmony_ci    uint32_t version;
6111cb0ef41Sopenharmony_ci    uintptr_t entry;
6121cb0ef41Sopenharmony_ci    uintptr_t pht_offset;
6131cb0ef41Sopenharmony_ci    uintptr_t sht_offset;
6141cb0ef41Sopenharmony_ci    uint32_t flags;
6151cb0ef41Sopenharmony_ci    uint16_t header_size;
6161cb0ef41Sopenharmony_ci    uint16_t pht_entry_size;
6171cb0ef41Sopenharmony_ci    uint16_t pht_entry_num;
6181cb0ef41Sopenharmony_ci    uint16_t sht_entry_size;
6191cb0ef41Sopenharmony_ci    uint16_t sht_entry_num;
6201cb0ef41Sopenharmony_ci    uint16_t sht_strtab_index;
6211cb0ef41Sopenharmony_ci  };
6221cb0ef41Sopenharmony_ci
6231cb0ef41Sopenharmony_ci  void WriteHeader(Writer* w) {
6241cb0ef41Sopenharmony_ci    DCHECK_EQ(w->position(), 0);
6251cb0ef41Sopenharmony_ci    Writer::Slot<ELFHeader> header = w->CreateSlotHere<ELFHeader>();
6261cb0ef41Sopenharmony_ci#if (V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_ARM)
6271cb0ef41Sopenharmony_ci    const uint8_t ident[16] = {0x7F, 'E', 'L', 'F', 1, 1, 1, 0,
6281cb0ef41Sopenharmony_ci                               0,    0,   0,   0,   0, 0, 0, 0};
6291cb0ef41Sopenharmony_ci#elif V8_TARGET_ARCH_X64 && V8_TARGET_ARCH_64_BIT || \
6301cb0ef41Sopenharmony_ci    V8_TARGET_ARCH_PPC64 && V8_TARGET_LITTLE_ENDIAN
6311cb0ef41Sopenharmony_ci    const uint8_t ident[16] = {0x7F, 'E', 'L', 'F', 2, 1, 1, 0,
6321cb0ef41Sopenharmony_ci                               0,    0,   0,   0,   0, 0, 0, 0};
6331cb0ef41Sopenharmony_ci#elif V8_TARGET_ARCH_PPC64 && V8_TARGET_BIG_ENDIAN && V8_OS_LINUX
6341cb0ef41Sopenharmony_ci    const uint8_t ident[16] = {0x7F, 'E', 'L', 'F', 2, 2, 1, 0,
6351cb0ef41Sopenharmony_ci                               0,    0,   0,   0,   0, 0, 0, 0};
6361cb0ef41Sopenharmony_ci#elif V8_TARGET_ARCH_S390X
6371cb0ef41Sopenharmony_ci    const uint8_t ident[16] = {0x7F, 'E', 'L', 'F', 2, 2, 1, 3,
6381cb0ef41Sopenharmony_ci                               0,    0,   0,   0,   0, 0, 0, 0};
6391cb0ef41Sopenharmony_ci#elif V8_TARGET_ARCH_S390
6401cb0ef41Sopenharmony_ci    const uint8_t ident[16] = {0x7F, 'E', 'L', 'F', 1, 2, 1, 3,
6411cb0ef41Sopenharmony_ci                               0,    0,   0,   0,   0, 0, 0, 0};
6421cb0ef41Sopenharmony_ci#else
6431cb0ef41Sopenharmony_ci#error Unsupported target architecture.
6441cb0ef41Sopenharmony_ci#endif
6451cb0ef41Sopenharmony_ci    memcpy(header->ident, ident, 16);
6461cb0ef41Sopenharmony_ci    header->type = 1;
6471cb0ef41Sopenharmony_ci#if V8_TARGET_ARCH_IA32
6481cb0ef41Sopenharmony_ci    header->machine = 3;
6491cb0ef41Sopenharmony_ci#elif V8_TARGET_ARCH_X64
6501cb0ef41Sopenharmony_ci    // Processor identification value for x64 is 62 as defined in
6511cb0ef41Sopenharmony_ci    //    System V ABI, AMD64 Supplement
6521cb0ef41Sopenharmony_ci    //    http://www.x86-64.org/documentation/abi.pdf
6531cb0ef41Sopenharmony_ci    header->machine = 62;
6541cb0ef41Sopenharmony_ci#elif V8_TARGET_ARCH_ARM
6551cb0ef41Sopenharmony_ci    // Set to EM_ARM, defined as 40, in "ARM ELF File Format" at
6561cb0ef41Sopenharmony_ci    // infocenter.arm.com/help/topic/com.arm.doc.dui0101a/DUI0101A_Elf.pdf
6571cb0ef41Sopenharmony_ci    header->machine = 40;
6581cb0ef41Sopenharmony_ci#elif V8_TARGET_ARCH_PPC64 && V8_OS_LINUX
6591cb0ef41Sopenharmony_ci    // Set to EM_PPC64, defined as 21, in Power ABI,
6601cb0ef41Sopenharmony_ci    // Join the next 4 lines, omitting the spaces and double-slashes.
6611cb0ef41Sopenharmony_ci    // https://www-03.ibm.com/technologyconnect/tgcm/TGCMFileServlet.wss/
6621cb0ef41Sopenharmony_ci    // ABI64BitOpenPOWERv1.1_16July2015_pub.pdf?
6631cb0ef41Sopenharmony_ci    // id=B81AEC1A37F5DAF185257C3E004E8845&linkid=1n0000&c_t=
6641cb0ef41Sopenharmony_ci    // c9xw7v5dzsj7gt1ifgf4cjbcnskqptmr
6651cb0ef41Sopenharmony_ci    header->machine = 21;
6661cb0ef41Sopenharmony_ci#elif V8_TARGET_ARCH_S390
6671cb0ef41Sopenharmony_ci    // Processor identification value is 22 (EM_S390) as defined in the ABI:
6681cb0ef41Sopenharmony_ci    // http://refspecs.linuxbase.org/ELF/zSeries/lzsabi0_s390.html#AEN1691
6691cb0ef41Sopenharmony_ci    // http://refspecs.linuxbase.org/ELF/zSeries/lzsabi0_zSeries.html#AEN1599
6701cb0ef41Sopenharmony_ci    header->machine = 22;
6711cb0ef41Sopenharmony_ci#else
6721cb0ef41Sopenharmony_ci#error Unsupported target architecture.
6731cb0ef41Sopenharmony_ci#endif
6741cb0ef41Sopenharmony_ci    header->version = 1;
6751cb0ef41Sopenharmony_ci    header->entry = 0;
6761cb0ef41Sopenharmony_ci    header->pht_offset = 0;
6771cb0ef41Sopenharmony_ci    header->sht_offset = sizeof(ELFHeader);  // Section table follows header.
6781cb0ef41Sopenharmony_ci    header->flags = 0;
6791cb0ef41Sopenharmony_ci    header->header_size = sizeof(ELFHeader);
6801cb0ef41Sopenharmony_ci    header->pht_entry_size = 0;
6811cb0ef41Sopenharmony_ci    header->pht_entry_num = 0;
6821cb0ef41Sopenharmony_ci    header->sht_entry_size = sizeof(ELFSection::Header);
6831cb0ef41Sopenharmony_ci    header->sht_entry_num = sections_.size();
6841cb0ef41Sopenharmony_ci    header->sht_strtab_index = 1;
6851cb0ef41Sopenharmony_ci  }
6861cb0ef41Sopenharmony_ci
6871cb0ef41Sopenharmony_ci  void WriteSectionTable(Writer* w) {
6881cb0ef41Sopenharmony_ci    // Section headers table immediately follows file header.
6891cb0ef41Sopenharmony_ci    DCHECK(w->position() == sizeof(ELFHeader));
6901cb0ef41Sopenharmony_ci
6911cb0ef41Sopenharmony_ci    Writer::Slot<ELFSection::Header> headers =
6921cb0ef41Sopenharmony_ci        w->CreateSlotsHere<ELFSection::Header>(
6931cb0ef41Sopenharmony_ci            static_cast<uint32_t>(sections_.size()));
6941cb0ef41Sopenharmony_ci
6951cb0ef41Sopenharmony_ci    // String table for section table is the first section.
6961cb0ef41Sopenharmony_ci    ELFStringTable* strtab = static_cast<ELFStringTable*>(SectionAt(1));
6971cb0ef41Sopenharmony_ci    strtab->AttachWriter(w);
6981cb0ef41Sopenharmony_ci    uint32_t index = 0;
6991cb0ef41Sopenharmony_ci    for (ELFSection* section : sections_) {
7001cb0ef41Sopenharmony_ci      section->PopulateHeader(headers.at(index), strtab);
7011cb0ef41Sopenharmony_ci      index++;
7021cb0ef41Sopenharmony_ci    }
7031cb0ef41Sopenharmony_ci    strtab->DetachWriter();
7041cb0ef41Sopenharmony_ci  }
7051cb0ef41Sopenharmony_ci
7061cb0ef41Sopenharmony_ci  int SectionHeaderPosition(uint32_t section_index) {
7071cb0ef41Sopenharmony_ci    return sizeof(ELFHeader) + sizeof(ELFSection::Header) * section_index;
7081cb0ef41Sopenharmony_ci  }
7091cb0ef41Sopenharmony_ci
7101cb0ef41Sopenharmony_ci  void WriteSections(Writer* w) {
7111cb0ef41Sopenharmony_ci    Writer::Slot<ELFSection::Header> headers =
7121cb0ef41Sopenharmony_ci        w->SlotAt<ELFSection::Header>(sizeof(ELFHeader));
7131cb0ef41Sopenharmony_ci
7141cb0ef41Sopenharmony_ci    uint32_t index = 0;
7151cb0ef41Sopenharmony_ci    for (ELFSection* section : sections_) {
7161cb0ef41Sopenharmony_ci      section->WriteBody(headers.at(index), w);
7171cb0ef41Sopenharmony_ci      index++;
7181cb0ef41Sopenharmony_ci    }
7191cb0ef41Sopenharmony_ci  }
7201cb0ef41Sopenharmony_ci
7211cb0ef41Sopenharmony_ci  ZoneChunkList<ELFSection*> sections_;
7221cb0ef41Sopenharmony_ci};
7231cb0ef41Sopenharmony_ci
7241cb0ef41Sopenharmony_ciclass ELFSymbol {
7251cb0ef41Sopenharmony_ci public:
7261cb0ef41Sopenharmony_ci  enum Type {
7271cb0ef41Sopenharmony_ci    TYPE_NOTYPE = 0,
7281cb0ef41Sopenharmony_ci    TYPE_OBJECT = 1,
7291cb0ef41Sopenharmony_ci    TYPE_FUNC = 2,
7301cb0ef41Sopenharmony_ci    TYPE_SECTION = 3,
7311cb0ef41Sopenharmony_ci    TYPE_FILE = 4,
7321cb0ef41Sopenharmony_ci    TYPE_LOPROC = 13,
7331cb0ef41Sopenharmony_ci    TYPE_HIPROC = 15
7341cb0ef41Sopenharmony_ci  };
7351cb0ef41Sopenharmony_ci
7361cb0ef41Sopenharmony_ci  enum Binding {
7371cb0ef41Sopenharmony_ci    BIND_LOCAL = 0,
7381cb0ef41Sopenharmony_ci    BIND_GLOBAL = 1,
7391cb0ef41Sopenharmony_ci    BIND_WEAK = 2,
7401cb0ef41Sopenharmony_ci    BIND_LOPROC = 13,
7411cb0ef41Sopenharmony_ci    BIND_HIPROC = 15
7421cb0ef41Sopenharmony_ci  };
7431cb0ef41Sopenharmony_ci
7441cb0ef41Sopenharmony_ci  ELFSymbol(const char* name, uintptr_t value, uintptr_t size, Binding binding,
7451cb0ef41Sopenharmony_ci            Type type, uint16_t section)
7461cb0ef41Sopenharmony_ci      : name(name),
7471cb0ef41Sopenharmony_ci        value(value),
7481cb0ef41Sopenharmony_ci        size(size),
7491cb0ef41Sopenharmony_ci        info((binding << 4) | type),
7501cb0ef41Sopenharmony_ci        other(0),
7511cb0ef41Sopenharmony_ci        section(section) {}
7521cb0ef41Sopenharmony_ci
7531cb0ef41Sopenharmony_ci  Binding binding() const { return static_cast<Binding>(info >> 4); }
7541cb0ef41Sopenharmony_ci#if (V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_ARM || \
7551cb0ef41Sopenharmony_ci     (V8_TARGET_ARCH_S390 && V8_TARGET_ARCH_32_BIT))
7561cb0ef41Sopenharmony_ci  struct SerializedLayout {
7571cb0ef41Sopenharmony_ci    SerializedLayout(uint32_t name, uintptr_t value, uintptr_t size,
7581cb0ef41Sopenharmony_ci                     Binding binding, Type type, uint16_t section)
7591cb0ef41Sopenharmony_ci        : name(name),
7601cb0ef41Sopenharmony_ci          value(value),
7611cb0ef41Sopenharmony_ci          size(size),
7621cb0ef41Sopenharmony_ci          info((binding << 4) | type),
7631cb0ef41Sopenharmony_ci          other(0),
7641cb0ef41Sopenharmony_ci          section(section) {}
7651cb0ef41Sopenharmony_ci
7661cb0ef41Sopenharmony_ci    uint32_t name;
7671cb0ef41Sopenharmony_ci    uintptr_t value;
7681cb0ef41Sopenharmony_ci    uintptr_t size;
7691cb0ef41Sopenharmony_ci    uint8_t info;
7701cb0ef41Sopenharmony_ci    uint8_t other;
7711cb0ef41Sopenharmony_ci    uint16_t section;
7721cb0ef41Sopenharmony_ci  };
7731cb0ef41Sopenharmony_ci#elif V8_TARGET_ARCH_X64 && V8_TARGET_ARCH_64_BIT || \
7741cb0ef41Sopenharmony_ci    V8_TARGET_ARCH_PPC64 && V8_OS_LINUX || V8_TARGET_ARCH_S390X
7751cb0ef41Sopenharmony_ci  struct SerializedLayout {
7761cb0ef41Sopenharmony_ci    SerializedLayout(uint32_t name, uintptr_t value, uintptr_t size,
7771cb0ef41Sopenharmony_ci                     Binding binding, Type type, uint16_t section)
7781cb0ef41Sopenharmony_ci        : name(name),
7791cb0ef41Sopenharmony_ci          info((binding << 4) | type),
7801cb0ef41Sopenharmony_ci          other(0),
7811cb0ef41Sopenharmony_ci          section(section),
7821cb0ef41Sopenharmony_ci          value(value),
7831cb0ef41Sopenharmony_ci          size(size) {}
7841cb0ef41Sopenharmony_ci
7851cb0ef41Sopenharmony_ci    uint32_t name;
7861cb0ef41Sopenharmony_ci    uint8_t info;
7871cb0ef41Sopenharmony_ci    uint8_t other;
7881cb0ef41Sopenharmony_ci    uint16_t section;
7891cb0ef41Sopenharmony_ci    uintptr_t value;
7901cb0ef41Sopenharmony_ci    uintptr_t size;
7911cb0ef41Sopenharmony_ci  };
7921cb0ef41Sopenharmony_ci#endif
7931cb0ef41Sopenharmony_ci
7941cb0ef41Sopenharmony_ci  void Write(Writer::Slot<SerializedLayout> s, ELFStringTable* t) const {
7951cb0ef41Sopenharmony_ci    // Convert symbol names from strings to indexes in the string table.
7961cb0ef41Sopenharmony_ci    s->name = static_cast<uint32_t>(t->Add(name));
7971cb0ef41Sopenharmony_ci    s->value = value;
7981cb0ef41Sopenharmony_ci    s->size = size;
7991cb0ef41Sopenharmony_ci    s->info = info;
8001cb0ef41Sopenharmony_ci    s->other = other;
8011cb0ef41Sopenharmony_ci    s->section = section;
8021cb0ef41Sopenharmony_ci  }
8031cb0ef41Sopenharmony_ci
8041cb0ef41Sopenharmony_ci private:
8051cb0ef41Sopenharmony_ci  const char* name;
8061cb0ef41Sopenharmony_ci  uintptr_t value;
8071cb0ef41Sopenharmony_ci  uintptr_t size;
8081cb0ef41Sopenharmony_ci  uint8_t info;
8091cb0ef41Sopenharmony_ci  uint8_t other;
8101cb0ef41Sopenharmony_ci  uint16_t section;
8111cb0ef41Sopenharmony_ci};
8121cb0ef41Sopenharmony_ci
8131cb0ef41Sopenharmony_ciclass ELFSymbolTable : public ELFSection {
8141cb0ef41Sopenharmony_ci public:
8151cb0ef41Sopenharmony_ci  ELFSymbolTable(const char* name, Zone* zone)
8161cb0ef41Sopenharmony_ci      : ELFSection(name, TYPE_SYMTAB, sizeof(uintptr_t)),
8171cb0ef41Sopenharmony_ci        locals_(zone),
8181cb0ef41Sopenharmony_ci        globals_(zone) {}
8191cb0ef41Sopenharmony_ci
8201cb0ef41Sopenharmony_ci  void WriteBody(Writer::Slot<Header> header, Writer* w) override {
8211cb0ef41Sopenharmony_ci    w->Align(header->alignment);
8221cb0ef41Sopenharmony_ci    size_t total_symbols = locals_.size() + globals_.size() + 1;
8231cb0ef41Sopenharmony_ci    header->offset = w->position();
8241cb0ef41Sopenharmony_ci
8251cb0ef41Sopenharmony_ci    Writer::Slot<ELFSymbol::SerializedLayout> symbols =
8261cb0ef41Sopenharmony_ci        w->CreateSlotsHere<ELFSymbol::SerializedLayout>(
8271cb0ef41Sopenharmony_ci            static_cast<uint32_t>(total_symbols));
8281cb0ef41Sopenharmony_ci
8291cb0ef41Sopenharmony_ci    header->size = w->position() - header->offset;
8301cb0ef41Sopenharmony_ci
8311cb0ef41Sopenharmony_ci    // String table for this symbol table should follow it in the section table.
8321cb0ef41Sopenharmony_ci    ELFStringTable* strtab =
8331cb0ef41Sopenharmony_ci        static_cast<ELFStringTable*>(w->debug_object()->SectionAt(index() + 1));
8341cb0ef41Sopenharmony_ci    strtab->AttachWriter(w);
8351cb0ef41Sopenharmony_ci    symbols.at(0).set(ELFSymbol::SerializedLayout(
8361cb0ef41Sopenharmony_ci        0, 0, 0, ELFSymbol::BIND_LOCAL, ELFSymbol::TYPE_NOTYPE, 0));
8371cb0ef41Sopenharmony_ci    WriteSymbolsList(&locals_, symbols.at(1), strtab);
8381cb0ef41Sopenharmony_ci    WriteSymbolsList(&globals_,
8391cb0ef41Sopenharmony_ci                     symbols.at(static_cast<uint32_t>(locals_.size() + 1)),
8401cb0ef41Sopenharmony_ci                     strtab);
8411cb0ef41Sopenharmony_ci    strtab->DetachWriter();
8421cb0ef41Sopenharmony_ci  }
8431cb0ef41Sopenharmony_ci
8441cb0ef41Sopenharmony_ci  void Add(const ELFSymbol& symbol) {
8451cb0ef41Sopenharmony_ci    if (symbol.binding() == ELFSymbol::BIND_LOCAL) {
8461cb0ef41Sopenharmony_ci      locals_.push_back(symbol);
8471cb0ef41Sopenharmony_ci    } else {
8481cb0ef41Sopenharmony_ci      globals_.push_back(symbol);
8491cb0ef41Sopenharmony_ci    }
8501cb0ef41Sopenharmony_ci  }
8511cb0ef41Sopenharmony_ci
8521cb0ef41Sopenharmony_ci protected:
8531cb0ef41Sopenharmony_ci  void PopulateHeader(Writer::Slot<Header> header) override {
8541cb0ef41Sopenharmony_ci    ELFSection::PopulateHeader(header);
8551cb0ef41Sopenharmony_ci    // We are assuming that string table will follow symbol table.
8561cb0ef41Sopenharmony_ci    header->link = index() + 1;
8571cb0ef41Sopenharmony_ci    header->info = static_cast<uint32_t>(locals_.size() + 1);
8581cb0ef41Sopenharmony_ci    header->entry_size = sizeof(ELFSymbol::SerializedLayout);
8591cb0ef41Sopenharmony_ci  }
8601cb0ef41Sopenharmony_ci
8611cb0ef41Sopenharmony_ci private:
8621cb0ef41Sopenharmony_ci  void WriteSymbolsList(const ZoneChunkList<ELFSymbol>* src,
8631cb0ef41Sopenharmony_ci                        Writer::Slot<ELFSymbol::SerializedLayout> dst,
8641cb0ef41Sopenharmony_ci                        ELFStringTable* strtab) {
8651cb0ef41Sopenharmony_ci    int i = 0;
8661cb0ef41Sopenharmony_ci    for (const ELFSymbol& symbol : *src) {
8671cb0ef41Sopenharmony_ci      symbol.Write(dst.at(i++), strtab);
8681cb0ef41Sopenharmony_ci    }
8691cb0ef41Sopenharmony_ci  }
8701cb0ef41Sopenharmony_ci
8711cb0ef41Sopenharmony_ci  ZoneChunkList<ELFSymbol> locals_;
8721cb0ef41Sopenharmony_ci  ZoneChunkList<ELFSymbol> globals_;
8731cb0ef41Sopenharmony_ci};
8741cb0ef41Sopenharmony_ci#endif  // defined(__ELF)
8751cb0ef41Sopenharmony_ci
8761cb0ef41Sopenharmony_ciclass LineInfo : public Malloced {
8771cb0ef41Sopenharmony_ci public:
8781cb0ef41Sopenharmony_ci  void SetPosition(intptr_t pc, int pos, bool is_statement) {
8791cb0ef41Sopenharmony_ci    AddPCInfo(PCInfo(pc, pos, is_statement));
8801cb0ef41Sopenharmony_ci  }
8811cb0ef41Sopenharmony_ci
8821cb0ef41Sopenharmony_ci  struct PCInfo {
8831cb0ef41Sopenharmony_ci    PCInfo(intptr_t pc, int pos, bool is_statement)
8841cb0ef41Sopenharmony_ci        : pc_(pc), pos_(pos), is_statement_(is_statement) {}
8851cb0ef41Sopenharmony_ci
8861cb0ef41Sopenharmony_ci    intptr_t pc_;
8871cb0ef41Sopenharmony_ci    int pos_;
8881cb0ef41Sopenharmony_ci    bool is_statement_;
8891cb0ef41Sopenharmony_ci  };
8901cb0ef41Sopenharmony_ci
8911cb0ef41Sopenharmony_ci  std::vector<PCInfo>* pc_info() { return &pc_info_; }
8921cb0ef41Sopenharmony_ci
8931cb0ef41Sopenharmony_ci private:
8941cb0ef41Sopenharmony_ci  void AddPCInfo(const PCInfo& pc_info) { pc_info_.push_back(pc_info); }
8951cb0ef41Sopenharmony_ci
8961cb0ef41Sopenharmony_ci  std::vector<PCInfo> pc_info_;
8971cb0ef41Sopenharmony_ci};
8981cb0ef41Sopenharmony_ci
8991cb0ef41Sopenharmony_ciclass CodeDescription {
9001cb0ef41Sopenharmony_ci public:
9011cb0ef41Sopenharmony_ci#if V8_TARGET_ARCH_X64
9021cb0ef41Sopenharmony_ci  enum StackState {
9031cb0ef41Sopenharmony_ci    POST_RBP_PUSH,
9041cb0ef41Sopenharmony_ci    POST_RBP_SET,
9051cb0ef41Sopenharmony_ci    POST_RBP_POP,
9061cb0ef41Sopenharmony_ci    STACK_STATE_MAX
9071cb0ef41Sopenharmony_ci  };
9081cb0ef41Sopenharmony_ci#endif
9091cb0ef41Sopenharmony_ci
9101cb0ef41Sopenharmony_ci  CodeDescription(const char* name, base::AddressRegion region,
9111cb0ef41Sopenharmony_ci                  SharedFunctionInfo shared, LineInfo* lineinfo,
9121cb0ef41Sopenharmony_ci                  bool is_function)
9131cb0ef41Sopenharmony_ci      : name_(name),
9141cb0ef41Sopenharmony_ci        shared_info_(shared),
9151cb0ef41Sopenharmony_ci        lineinfo_(lineinfo),
9161cb0ef41Sopenharmony_ci        is_function_(is_function),
9171cb0ef41Sopenharmony_ci        code_region_(region) {}
9181cb0ef41Sopenharmony_ci
9191cb0ef41Sopenharmony_ci  const char* name() const { return name_; }
9201cb0ef41Sopenharmony_ci
9211cb0ef41Sopenharmony_ci  LineInfo* lineinfo() const { return lineinfo_; }
9221cb0ef41Sopenharmony_ci
9231cb0ef41Sopenharmony_ci  bool is_function() const { return is_function_; }
9241cb0ef41Sopenharmony_ci
9251cb0ef41Sopenharmony_ci  bool has_scope_info() const { return !shared_info_.is_null(); }
9261cb0ef41Sopenharmony_ci
9271cb0ef41Sopenharmony_ci  ScopeInfo scope_info() const {
9281cb0ef41Sopenharmony_ci    DCHECK(has_scope_info());
9291cb0ef41Sopenharmony_ci    return shared_info_.scope_info();
9301cb0ef41Sopenharmony_ci  }
9311cb0ef41Sopenharmony_ci
9321cb0ef41Sopenharmony_ci  uintptr_t CodeStart() const { return code_region_.begin(); }
9331cb0ef41Sopenharmony_ci
9341cb0ef41Sopenharmony_ci  uintptr_t CodeEnd() const { return code_region_.end(); }
9351cb0ef41Sopenharmony_ci
9361cb0ef41Sopenharmony_ci  uintptr_t CodeSize() const { return code_region_.size(); }
9371cb0ef41Sopenharmony_ci
9381cb0ef41Sopenharmony_ci  bool has_script() {
9391cb0ef41Sopenharmony_ci    return !shared_info_.is_null() && shared_info_.script().IsScript();
9401cb0ef41Sopenharmony_ci  }
9411cb0ef41Sopenharmony_ci
9421cb0ef41Sopenharmony_ci  Script script() { return Script::cast(shared_info_.script()); }
9431cb0ef41Sopenharmony_ci
9441cb0ef41Sopenharmony_ci  bool IsLineInfoAvailable() { return lineinfo_ != nullptr; }
9451cb0ef41Sopenharmony_ci
9461cb0ef41Sopenharmony_ci  base::AddressRegion region() { return code_region_; }
9471cb0ef41Sopenharmony_ci
9481cb0ef41Sopenharmony_ci#if V8_TARGET_ARCH_X64
9491cb0ef41Sopenharmony_ci  uintptr_t GetStackStateStartAddress(StackState state) const {
9501cb0ef41Sopenharmony_ci    DCHECK(state < STACK_STATE_MAX);
9511cb0ef41Sopenharmony_ci    return stack_state_start_addresses_[state];
9521cb0ef41Sopenharmony_ci  }
9531cb0ef41Sopenharmony_ci
9541cb0ef41Sopenharmony_ci  void SetStackStateStartAddress(StackState state, uintptr_t addr) {
9551cb0ef41Sopenharmony_ci    DCHECK(state < STACK_STATE_MAX);
9561cb0ef41Sopenharmony_ci    stack_state_start_addresses_[state] = addr;
9571cb0ef41Sopenharmony_ci  }
9581cb0ef41Sopenharmony_ci#endif
9591cb0ef41Sopenharmony_ci
9601cb0ef41Sopenharmony_ci  std::unique_ptr<char[]> GetFilename() {
9611cb0ef41Sopenharmony_ci    if (!shared_info_.is_null() && script().name().IsString()) {
9621cb0ef41Sopenharmony_ci      return String::cast(script().name()).ToCString();
9631cb0ef41Sopenharmony_ci    } else {
9641cb0ef41Sopenharmony_ci      std::unique_ptr<char[]> result(new char[1]);
9651cb0ef41Sopenharmony_ci      result[0] = 0;
9661cb0ef41Sopenharmony_ci      return result;
9671cb0ef41Sopenharmony_ci    }
9681cb0ef41Sopenharmony_ci  }
9691cb0ef41Sopenharmony_ci
9701cb0ef41Sopenharmony_ci  int GetScriptLineNumber(int pos) {
9711cb0ef41Sopenharmony_ci    if (!shared_info_.is_null()) {
9721cb0ef41Sopenharmony_ci      return script().GetLineNumber(pos) + 1;
9731cb0ef41Sopenharmony_ci    } else {
9741cb0ef41Sopenharmony_ci      return 0;
9751cb0ef41Sopenharmony_ci    }
9761cb0ef41Sopenharmony_ci  }
9771cb0ef41Sopenharmony_ci
9781cb0ef41Sopenharmony_ci private:
9791cb0ef41Sopenharmony_ci  const char* name_;
9801cb0ef41Sopenharmony_ci  SharedFunctionInfo shared_info_;
9811cb0ef41Sopenharmony_ci  LineInfo* lineinfo_;
9821cb0ef41Sopenharmony_ci  bool is_function_;
9831cb0ef41Sopenharmony_ci  base::AddressRegion code_region_;
9841cb0ef41Sopenharmony_ci#if V8_TARGET_ARCH_X64
9851cb0ef41Sopenharmony_ci  uintptr_t stack_state_start_addresses_[STACK_STATE_MAX];
9861cb0ef41Sopenharmony_ci#endif
9871cb0ef41Sopenharmony_ci};
9881cb0ef41Sopenharmony_ci
9891cb0ef41Sopenharmony_ci#if defined(__ELF)
9901cb0ef41Sopenharmony_cistatic void CreateSymbolsTable(CodeDescription* desc, Zone* zone, ELF* elf,
9911cb0ef41Sopenharmony_ci                               size_t text_section_index) {
9921cb0ef41Sopenharmony_ci  ELFSymbolTable* symtab = zone->New<ELFSymbolTable>(".symtab", zone);
9931cb0ef41Sopenharmony_ci  ELFStringTable* strtab = zone->New<ELFStringTable>(".strtab");
9941cb0ef41Sopenharmony_ci
9951cb0ef41Sopenharmony_ci  // Symbol table should be followed by the linked string table.
9961cb0ef41Sopenharmony_ci  elf->AddSection(symtab);
9971cb0ef41Sopenharmony_ci  elf->AddSection(strtab);
9981cb0ef41Sopenharmony_ci
9991cb0ef41Sopenharmony_ci  symtab->Add(ELFSymbol("V8 Code", 0, 0, ELFSymbol::BIND_LOCAL,
10001cb0ef41Sopenharmony_ci                        ELFSymbol::TYPE_FILE, ELFSection::INDEX_ABSOLUTE));
10011cb0ef41Sopenharmony_ci
10021cb0ef41Sopenharmony_ci  symtab->Add(ELFSymbol(desc->name(), 0, desc->CodeSize(),
10031cb0ef41Sopenharmony_ci                        ELFSymbol::BIND_GLOBAL, ELFSymbol::TYPE_FUNC,
10041cb0ef41Sopenharmony_ci                        text_section_index));
10051cb0ef41Sopenharmony_ci}
10061cb0ef41Sopenharmony_ci#endif  // defined(__ELF)
10071cb0ef41Sopenharmony_ci
10081cb0ef41Sopenharmony_ciclass DebugInfoSection : public DebugSection {
10091cb0ef41Sopenharmony_ci public:
10101cb0ef41Sopenharmony_ci  explicit DebugInfoSection(CodeDescription* desc)
10111cb0ef41Sopenharmony_ci#if defined(__ELF)
10121cb0ef41Sopenharmony_ci      : ELFSection(".debug_info", TYPE_PROGBITS, 1),
10131cb0ef41Sopenharmony_ci#else
10141cb0ef41Sopenharmony_ci      : MachOSection("__debug_info", "__DWARF", 1,
10151cb0ef41Sopenharmony_ci                     MachOSection::S_REGULAR | MachOSection::S_ATTR_DEBUG),
10161cb0ef41Sopenharmony_ci#endif
10171cb0ef41Sopenharmony_ci        desc_(desc) {
10181cb0ef41Sopenharmony_ci  }
10191cb0ef41Sopenharmony_ci
10201cb0ef41Sopenharmony_ci  // DWARF2 standard
10211cb0ef41Sopenharmony_ci  enum DWARF2LocationOp {
10221cb0ef41Sopenharmony_ci    DW_OP_reg0 = 0x50,
10231cb0ef41Sopenharmony_ci    DW_OP_reg1 = 0x51,
10241cb0ef41Sopenharmony_ci    DW_OP_reg2 = 0x52,
10251cb0ef41Sopenharmony_ci    DW_OP_reg3 = 0x53,
10261cb0ef41Sopenharmony_ci    DW_OP_reg4 = 0x54,
10271cb0ef41Sopenharmony_ci    DW_OP_reg5 = 0x55,
10281cb0ef41Sopenharmony_ci    DW_OP_reg6 = 0x56,
10291cb0ef41Sopenharmony_ci    DW_OP_reg7 = 0x57,
10301cb0ef41Sopenharmony_ci    DW_OP_reg8 = 0x58,
10311cb0ef41Sopenharmony_ci    DW_OP_reg9 = 0x59,
10321cb0ef41Sopenharmony_ci    DW_OP_reg10 = 0x5A,
10331cb0ef41Sopenharmony_ci    DW_OP_reg11 = 0x5B,
10341cb0ef41Sopenharmony_ci    DW_OP_reg12 = 0x5C,
10351cb0ef41Sopenharmony_ci    DW_OP_reg13 = 0x5D,
10361cb0ef41Sopenharmony_ci    DW_OP_reg14 = 0x5E,
10371cb0ef41Sopenharmony_ci    DW_OP_reg15 = 0x5F,
10381cb0ef41Sopenharmony_ci    DW_OP_reg16 = 0x60,
10391cb0ef41Sopenharmony_ci    DW_OP_reg17 = 0x61,
10401cb0ef41Sopenharmony_ci    DW_OP_reg18 = 0x62,
10411cb0ef41Sopenharmony_ci    DW_OP_reg19 = 0x63,
10421cb0ef41Sopenharmony_ci    DW_OP_reg20 = 0x64,
10431cb0ef41Sopenharmony_ci    DW_OP_reg21 = 0x65,
10441cb0ef41Sopenharmony_ci    DW_OP_reg22 = 0x66,
10451cb0ef41Sopenharmony_ci    DW_OP_reg23 = 0x67,
10461cb0ef41Sopenharmony_ci    DW_OP_reg24 = 0x68,
10471cb0ef41Sopenharmony_ci    DW_OP_reg25 = 0x69,
10481cb0ef41Sopenharmony_ci    DW_OP_reg26 = 0x6A,
10491cb0ef41Sopenharmony_ci    DW_OP_reg27 = 0x6B,
10501cb0ef41Sopenharmony_ci    DW_OP_reg28 = 0x6C,
10511cb0ef41Sopenharmony_ci    DW_OP_reg29 = 0x6D,
10521cb0ef41Sopenharmony_ci    DW_OP_reg30 = 0x6E,
10531cb0ef41Sopenharmony_ci    DW_OP_reg31 = 0x6F,
10541cb0ef41Sopenharmony_ci    DW_OP_fbreg = 0x91  // 1 param: SLEB128 offset
10551cb0ef41Sopenharmony_ci  };
10561cb0ef41Sopenharmony_ci
10571cb0ef41Sopenharmony_ci  enum DWARF2Encoding { DW_ATE_ADDRESS = 0x1, DW_ATE_SIGNED = 0x5 };
10581cb0ef41Sopenharmony_ci
10591cb0ef41Sopenharmony_ci  bool WriteBodyInternal(Writer* w) override {
10601cb0ef41Sopenharmony_ci    uintptr_t cu_start = w->position();
10611cb0ef41Sopenharmony_ci    Writer::Slot<uint32_t> size = w->CreateSlotHere<uint32_t>();
10621cb0ef41Sopenharmony_ci    uintptr_t start = w->position();
10631cb0ef41Sopenharmony_ci    w->Write<uint16_t>(2);  // DWARF version.
10641cb0ef41Sopenharmony_ci    w->Write<uint32_t>(0);  // Abbreviation table offset.
10651cb0ef41Sopenharmony_ci    w->Write<uint8_t>(sizeof(intptr_t));
10661cb0ef41Sopenharmony_ci
10671cb0ef41Sopenharmony_ci    w->WriteULEB128(1);  // Abbreviation code.
10681cb0ef41Sopenharmony_ci    w->WriteString(desc_->GetFilename().get());
10691cb0ef41Sopenharmony_ci    w->Write<intptr_t>(desc_->CodeStart());
10701cb0ef41Sopenharmony_ci    w->Write<intptr_t>(desc_->CodeStart() + desc_->CodeSize());
10711cb0ef41Sopenharmony_ci    w->Write<uint32_t>(0);
10721cb0ef41Sopenharmony_ci
10731cb0ef41Sopenharmony_ci    uint32_t ty_offset = static_cast<uint32_t>(w->position() - cu_start);
10741cb0ef41Sopenharmony_ci    w->WriteULEB128(3);
10751cb0ef41Sopenharmony_ci    w->Write<uint8_t>(kSystemPointerSize);
10761cb0ef41Sopenharmony_ci    w->WriteString("v8value");
10771cb0ef41Sopenharmony_ci
10781cb0ef41Sopenharmony_ci    if (desc_->has_scope_info()) {
10791cb0ef41Sopenharmony_ci      ScopeInfo scope = desc_->scope_info();
10801cb0ef41Sopenharmony_ci      w->WriteULEB128(2);
10811cb0ef41Sopenharmony_ci      w->WriteString(desc_->name());
10821cb0ef41Sopenharmony_ci      w->Write<intptr_t>(desc_->CodeStart());
10831cb0ef41Sopenharmony_ci      w->Write<intptr_t>(desc_->CodeStart() + desc_->CodeSize());
10841cb0ef41Sopenharmony_ci      Writer::Slot<uint32_t> fb_block_size = w->CreateSlotHere<uint32_t>();
10851cb0ef41Sopenharmony_ci      uintptr_t fb_block_start = w->position();
10861cb0ef41Sopenharmony_ci#if V8_TARGET_ARCH_IA32
10871cb0ef41Sopenharmony_ci      w->Write<uint8_t>(DW_OP_reg5);  // The frame pointer's here on ia32
10881cb0ef41Sopenharmony_ci#elif V8_TARGET_ARCH_X64
10891cb0ef41Sopenharmony_ci      w->Write<uint8_t>(DW_OP_reg6);  // and here on x64.
10901cb0ef41Sopenharmony_ci#elif V8_TARGET_ARCH_ARM
10911cb0ef41Sopenharmony_ci      UNIMPLEMENTED();
10921cb0ef41Sopenharmony_ci#elif V8_TARGET_ARCH_MIPS
10931cb0ef41Sopenharmony_ci      UNIMPLEMENTED();
10941cb0ef41Sopenharmony_ci#elif V8_TARGET_ARCH_MIPS64
10951cb0ef41Sopenharmony_ci      UNIMPLEMENTED();
10961cb0ef41Sopenharmony_ci#elif V8_TARGET_ARCH_LOONG64
10971cb0ef41Sopenharmony_ci      UNIMPLEMENTED();
10981cb0ef41Sopenharmony_ci#elif V8_TARGET_ARCH_PPC64 && V8_OS_LINUX
10991cb0ef41Sopenharmony_ci      w->Write<uint8_t>(DW_OP_reg31);  // The frame pointer is here on PPC64.
11001cb0ef41Sopenharmony_ci#elif V8_TARGET_ARCH_S390
11011cb0ef41Sopenharmony_ci      w->Write<uint8_t>(DW_OP_reg11);  // The frame pointer's here on S390.
11021cb0ef41Sopenharmony_ci#else
11031cb0ef41Sopenharmony_ci#error Unsupported target architecture.
11041cb0ef41Sopenharmony_ci#endif
11051cb0ef41Sopenharmony_ci      fb_block_size.set(static_cast<uint32_t>(w->position() - fb_block_start));
11061cb0ef41Sopenharmony_ci
11071cb0ef41Sopenharmony_ci      int params = scope.ParameterCount();
11081cb0ef41Sopenharmony_ci      int context_slots = scope.ContextLocalCount();
11091cb0ef41Sopenharmony_ci      // The real slot ID is internal_slots + context_slot_id.
11101cb0ef41Sopenharmony_ci      int internal_slots = scope.ContextHeaderLength();
11111cb0ef41Sopenharmony_ci      int current_abbreviation = 4;
11121cb0ef41Sopenharmony_ci
11131cb0ef41Sopenharmony_ci      for (int param = 0; param < params; ++param) {
11141cb0ef41Sopenharmony_ci        w->WriteULEB128(current_abbreviation++);
11151cb0ef41Sopenharmony_ci        w->WriteString("param");
11161cb0ef41Sopenharmony_ci        w->Write(std::to_string(param).c_str());
11171cb0ef41Sopenharmony_ci        w->Write<uint32_t>(ty_offset);
11181cb0ef41Sopenharmony_ci        Writer::Slot<uint32_t> block_size = w->CreateSlotHere<uint32_t>();
11191cb0ef41Sopenharmony_ci        uintptr_t block_start = w->position();
11201cb0ef41Sopenharmony_ci        w->Write<uint8_t>(DW_OP_fbreg);
11211cb0ef41Sopenharmony_ci        w->WriteSLEB128(StandardFrameConstants::kFixedFrameSizeAboveFp +
11221cb0ef41Sopenharmony_ci                        kSystemPointerSize * (params - param - 1));
11231cb0ef41Sopenharmony_ci        block_size.set(static_cast<uint32_t>(w->position() - block_start));
11241cb0ef41Sopenharmony_ci      }
11251cb0ef41Sopenharmony_ci
11261cb0ef41Sopenharmony_ci      // See contexts.h for more information.
11271cb0ef41Sopenharmony_ci      DCHECK(internal_slots == 2 || internal_slots == 3);
11281cb0ef41Sopenharmony_ci      DCHECK_EQ(Context::SCOPE_INFO_INDEX, 0);
11291cb0ef41Sopenharmony_ci      DCHECK_EQ(Context::PREVIOUS_INDEX, 1);
11301cb0ef41Sopenharmony_ci      DCHECK_EQ(Context::EXTENSION_INDEX, 2);
11311cb0ef41Sopenharmony_ci      w->WriteULEB128(current_abbreviation++);
11321cb0ef41Sopenharmony_ci      w->WriteString(".scope_info");
11331cb0ef41Sopenharmony_ci      w->WriteULEB128(current_abbreviation++);
11341cb0ef41Sopenharmony_ci      w->WriteString(".previous");
11351cb0ef41Sopenharmony_ci      if (internal_slots == 3) {
11361cb0ef41Sopenharmony_ci        w->WriteULEB128(current_abbreviation++);
11371cb0ef41Sopenharmony_ci        w->WriteString(".extension");
11381cb0ef41Sopenharmony_ci      }
11391cb0ef41Sopenharmony_ci
11401cb0ef41Sopenharmony_ci      for (int context_slot = 0; context_slot < context_slots; ++context_slot) {
11411cb0ef41Sopenharmony_ci        w->WriteULEB128(current_abbreviation++);
11421cb0ef41Sopenharmony_ci        w->WriteString("context_slot");
11431cb0ef41Sopenharmony_ci        w->Write(std::to_string(context_slot + internal_slots).c_str());
11441cb0ef41Sopenharmony_ci      }
11451cb0ef41Sopenharmony_ci
11461cb0ef41Sopenharmony_ci      {
11471cb0ef41Sopenharmony_ci        w->WriteULEB128(current_abbreviation++);
11481cb0ef41Sopenharmony_ci        w->WriteString("__function");
11491cb0ef41Sopenharmony_ci        w->Write<uint32_t>(ty_offset);
11501cb0ef41Sopenharmony_ci        Writer::Slot<uint32_t> block_size = w->CreateSlotHere<uint32_t>();
11511cb0ef41Sopenharmony_ci        uintptr_t block_start = w->position();
11521cb0ef41Sopenharmony_ci        w->Write<uint8_t>(DW_OP_fbreg);
11531cb0ef41Sopenharmony_ci        w->WriteSLEB128(StandardFrameConstants::kFunctionOffset);
11541cb0ef41Sopenharmony_ci        block_size.set(static_cast<uint32_t>(w->position() - block_start));
11551cb0ef41Sopenharmony_ci      }
11561cb0ef41Sopenharmony_ci
11571cb0ef41Sopenharmony_ci      {
11581cb0ef41Sopenharmony_ci        w->WriteULEB128(current_abbreviation++);
11591cb0ef41Sopenharmony_ci        w->WriteString("__context");
11601cb0ef41Sopenharmony_ci        w->Write<uint32_t>(ty_offset);
11611cb0ef41Sopenharmony_ci        Writer::Slot<uint32_t> block_size = w->CreateSlotHere<uint32_t>();
11621cb0ef41Sopenharmony_ci        uintptr_t block_start = w->position();
11631cb0ef41Sopenharmony_ci        w->Write<uint8_t>(DW_OP_fbreg);
11641cb0ef41Sopenharmony_ci        w->WriteSLEB128(StandardFrameConstants::kContextOffset);
11651cb0ef41Sopenharmony_ci        block_size.set(static_cast<uint32_t>(w->position() - block_start));
11661cb0ef41Sopenharmony_ci      }
11671cb0ef41Sopenharmony_ci
11681cb0ef41Sopenharmony_ci      w->WriteULEB128(0);  // Terminate the sub program.
11691cb0ef41Sopenharmony_ci    }
11701cb0ef41Sopenharmony_ci
11711cb0ef41Sopenharmony_ci    w->WriteULEB128(0);  // Terminate the compile unit.
11721cb0ef41Sopenharmony_ci    size.set(static_cast<uint32_t>(w->position() - start));
11731cb0ef41Sopenharmony_ci    return true;
11741cb0ef41Sopenharmony_ci  }
11751cb0ef41Sopenharmony_ci
11761cb0ef41Sopenharmony_ci private:
11771cb0ef41Sopenharmony_ci  CodeDescription* desc_;
11781cb0ef41Sopenharmony_ci};
11791cb0ef41Sopenharmony_ci
11801cb0ef41Sopenharmony_ciclass DebugAbbrevSection : public DebugSection {
11811cb0ef41Sopenharmony_ci public:
11821cb0ef41Sopenharmony_ci  explicit DebugAbbrevSection(CodeDescription* desc)
11831cb0ef41Sopenharmony_ci#ifdef __ELF
11841cb0ef41Sopenharmony_ci      : ELFSection(".debug_abbrev", TYPE_PROGBITS, 1),
11851cb0ef41Sopenharmony_ci#else
11861cb0ef41Sopenharmony_ci      : MachOSection("__debug_abbrev", "__DWARF", 1,
11871cb0ef41Sopenharmony_ci                     MachOSection::S_REGULAR | MachOSection::S_ATTR_DEBUG),
11881cb0ef41Sopenharmony_ci#endif
11891cb0ef41Sopenharmony_ci        desc_(desc) {
11901cb0ef41Sopenharmony_ci  }
11911cb0ef41Sopenharmony_ci
11921cb0ef41Sopenharmony_ci  // DWARF2 standard, figure 14.
11931cb0ef41Sopenharmony_ci  enum DWARF2Tags {
11941cb0ef41Sopenharmony_ci    DW_TAG_FORMAL_PARAMETER = 0x05,
11951cb0ef41Sopenharmony_ci    DW_TAG_POINTER_TYPE = 0xF,
11961cb0ef41Sopenharmony_ci    DW_TAG_COMPILE_UNIT = 0x11,
11971cb0ef41Sopenharmony_ci    DW_TAG_STRUCTURE_TYPE = 0x13,
11981cb0ef41Sopenharmony_ci    DW_TAG_BASE_TYPE = 0x24,
11991cb0ef41Sopenharmony_ci    DW_TAG_SUBPROGRAM = 0x2E,
12001cb0ef41Sopenharmony_ci    DW_TAG_VARIABLE = 0x34
12011cb0ef41Sopenharmony_ci  };
12021cb0ef41Sopenharmony_ci
12031cb0ef41Sopenharmony_ci  // DWARF2 standard, figure 16.
12041cb0ef41Sopenharmony_ci  enum DWARF2ChildrenDetermination { DW_CHILDREN_NO = 0, DW_CHILDREN_YES = 1 };
12051cb0ef41Sopenharmony_ci
12061cb0ef41Sopenharmony_ci  // DWARF standard, figure 17.
12071cb0ef41Sopenharmony_ci  enum DWARF2Attribute {
12081cb0ef41Sopenharmony_ci    DW_AT_LOCATION = 0x2,
12091cb0ef41Sopenharmony_ci    DW_AT_NAME = 0x3,
12101cb0ef41Sopenharmony_ci    DW_AT_BYTE_SIZE = 0xB,
12111cb0ef41Sopenharmony_ci    DW_AT_STMT_LIST = 0x10,
12121cb0ef41Sopenharmony_ci    DW_AT_LOW_PC = 0x11,
12131cb0ef41Sopenharmony_ci    DW_AT_HIGH_PC = 0x12,
12141cb0ef41Sopenharmony_ci    DW_AT_ENCODING = 0x3E,
12151cb0ef41Sopenharmony_ci    DW_AT_FRAME_BASE = 0x40,
12161cb0ef41Sopenharmony_ci    DW_AT_TYPE = 0x49
12171cb0ef41Sopenharmony_ci  };
12181cb0ef41Sopenharmony_ci
12191cb0ef41Sopenharmony_ci  // DWARF2 standard, figure 19.
12201cb0ef41Sopenharmony_ci  enum DWARF2AttributeForm {
12211cb0ef41Sopenharmony_ci    DW_FORM_ADDR = 0x1,
12221cb0ef41Sopenharmony_ci    DW_FORM_BLOCK4 = 0x4,
12231cb0ef41Sopenharmony_ci    DW_FORM_STRING = 0x8,
12241cb0ef41Sopenharmony_ci    DW_FORM_DATA4 = 0x6,
12251cb0ef41Sopenharmony_ci    DW_FORM_BLOCK = 0x9,
12261cb0ef41Sopenharmony_ci    DW_FORM_DATA1 = 0xB,
12271cb0ef41Sopenharmony_ci    DW_FORM_FLAG = 0xC,
12281cb0ef41Sopenharmony_ci    DW_FORM_REF4 = 0x13
12291cb0ef41Sopenharmony_ci  };
12301cb0ef41Sopenharmony_ci
12311cb0ef41Sopenharmony_ci  void WriteVariableAbbreviation(Writer* w, int abbreviation_code,
12321cb0ef41Sopenharmony_ci                                 bool has_value, bool is_parameter) {
12331cb0ef41Sopenharmony_ci    w->WriteULEB128(abbreviation_code);
12341cb0ef41Sopenharmony_ci    w->WriteULEB128(is_parameter ? DW_TAG_FORMAL_PARAMETER : DW_TAG_VARIABLE);
12351cb0ef41Sopenharmony_ci    w->Write<uint8_t>(DW_CHILDREN_NO);
12361cb0ef41Sopenharmony_ci    w->WriteULEB128(DW_AT_NAME);
12371cb0ef41Sopenharmony_ci    w->WriteULEB128(DW_FORM_STRING);
12381cb0ef41Sopenharmony_ci    if (has_value) {
12391cb0ef41Sopenharmony_ci      w->WriteULEB128(DW_AT_TYPE);
12401cb0ef41Sopenharmony_ci      w->WriteULEB128(DW_FORM_REF4);
12411cb0ef41Sopenharmony_ci      w->WriteULEB128(DW_AT_LOCATION);
12421cb0ef41Sopenharmony_ci      w->WriteULEB128(DW_FORM_BLOCK4);
12431cb0ef41Sopenharmony_ci    }
12441cb0ef41Sopenharmony_ci    w->WriteULEB128(0);
12451cb0ef41Sopenharmony_ci    w->WriteULEB128(0);
12461cb0ef41Sopenharmony_ci  }
12471cb0ef41Sopenharmony_ci
12481cb0ef41Sopenharmony_ci  bool WriteBodyInternal(Writer* w) override {
12491cb0ef41Sopenharmony_ci    int current_abbreviation = 1;
12501cb0ef41Sopenharmony_ci    bool extra_info = desc_->has_scope_info();
12511cb0ef41Sopenharmony_ci    DCHECK(desc_->IsLineInfoAvailable());
12521cb0ef41Sopenharmony_ci    w->WriteULEB128(current_abbreviation++);
12531cb0ef41Sopenharmony_ci    w->WriteULEB128(DW_TAG_COMPILE_UNIT);
12541cb0ef41Sopenharmony_ci    w->Write<uint8_t>(extra_info ? DW_CHILDREN_YES : DW_CHILDREN_NO);
12551cb0ef41Sopenharmony_ci    w->WriteULEB128(DW_AT_NAME);
12561cb0ef41Sopenharmony_ci    w->WriteULEB128(DW_FORM_STRING);
12571cb0ef41Sopenharmony_ci    w->WriteULEB128(DW_AT_LOW_PC);
12581cb0ef41Sopenharmony_ci    w->WriteULEB128(DW_FORM_ADDR);
12591cb0ef41Sopenharmony_ci    w->WriteULEB128(DW_AT_HIGH_PC);
12601cb0ef41Sopenharmony_ci    w->WriteULEB128(DW_FORM_ADDR);
12611cb0ef41Sopenharmony_ci    w->WriteULEB128(DW_AT_STMT_LIST);
12621cb0ef41Sopenharmony_ci    w->WriteULEB128(DW_FORM_DATA4);
12631cb0ef41Sopenharmony_ci    w->WriteULEB128(0);
12641cb0ef41Sopenharmony_ci    w->WriteULEB128(0);
12651cb0ef41Sopenharmony_ci
12661cb0ef41Sopenharmony_ci    if (extra_info) {
12671cb0ef41Sopenharmony_ci      ScopeInfo scope = desc_->scope_info();
12681cb0ef41Sopenharmony_ci      int params = scope.ParameterCount();
12691cb0ef41Sopenharmony_ci      int context_slots = scope.ContextLocalCount();
12701cb0ef41Sopenharmony_ci      // The real slot ID is internal_slots + context_slot_id.
12711cb0ef41Sopenharmony_ci      int internal_slots = Context::MIN_CONTEXT_SLOTS;
12721cb0ef41Sopenharmony_ci      // Total children is params + context_slots + internal_slots + 2
12731cb0ef41Sopenharmony_ci      // (__function and __context).
12741cb0ef41Sopenharmony_ci
12751cb0ef41Sopenharmony_ci      // The extra duplication below seems to be necessary to keep
12761cb0ef41Sopenharmony_ci      // gdb from getting upset on OSX.
12771cb0ef41Sopenharmony_ci      w->WriteULEB128(current_abbreviation++);  // Abbreviation code.
12781cb0ef41Sopenharmony_ci      w->WriteULEB128(DW_TAG_SUBPROGRAM);
12791cb0ef41Sopenharmony_ci      w->Write<uint8_t>(DW_CHILDREN_YES);
12801cb0ef41Sopenharmony_ci      w->WriteULEB128(DW_AT_NAME);
12811cb0ef41Sopenharmony_ci      w->WriteULEB128(DW_FORM_STRING);
12821cb0ef41Sopenharmony_ci      w->WriteULEB128(DW_AT_LOW_PC);
12831cb0ef41Sopenharmony_ci      w->WriteULEB128(DW_FORM_ADDR);
12841cb0ef41Sopenharmony_ci      w->WriteULEB128(DW_AT_HIGH_PC);
12851cb0ef41Sopenharmony_ci      w->WriteULEB128(DW_FORM_ADDR);
12861cb0ef41Sopenharmony_ci      w->WriteULEB128(DW_AT_FRAME_BASE);
12871cb0ef41Sopenharmony_ci      w->WriteULEB128(DW_FORM_BLOCK4);
12881cb0ef41Sopenharmony_ci      w->WriteULEB128(0);
12891cb0ef41Sopenharmony_ci      w->WriteULEB128(0);
12901cb0ef41Sopenharmony_ci
12911cb0ef41Sopenharmony_ci      w->WriteULEB128(current_abbreviation++);
12921cb0ef41Sopenharmony_ci      w->WriteULEB128(DW_TAG_STRUCTURE_TYPE);
12931cb0ef41Sopenharmony_ci      w->Write<uint8_t>(DW_CHILDREN_NO);
12941cb0ef41Sopenharmony_ci      w->WriteULEB128(DW_AT_BYTE_SIZE);
12951cb0ef41Sopenharmony_ci      w->WriteULEB128(DW_FORM_DATA1);
12961cb0ef41Sopenharmony_ci      w->WriteULEB128(DW_AT_NAME);
12971cb0ef41Sopenharmony_ci      w->WriteULEB128(DW_FORM_STRING);
12981cb0ef41Sopenharmony_ci      w->WriteULEB128(0);
12991cb0ef41Sopenharmony_ci      w->WriteULEB128(0);
13001cb0ef41Sopenharmony_ci
13011cb0ef41Sopenharmony_ci      for (int param = 0; param < params; ++param) {
13021cb0ef41Sopenharmony_ci        WriteVariableAbbreviation(w, current_abbreviation++, true, true);
13031cb0ef41Sopenharmony_ci      }
13041cb0ef41Sopenharmony_ci
13051cb0ef41Sopenharmony_ci      for (int internal_slot = 0; internal_slot < internal_slots;
13061cb0ef41Sopenharmony_ci           ++internal_slot) {
13071cb0ef41Sopenharmony_ci        WriteVariableAbbreviation(w, current_abbreviation++, false, false);
13081cb0ef41Sopenharmony_ci      }
13091cb0ef41Sopenharmony_ci
13101cb0ef41Sopenharmony_ci      for (int context_slot = 0; context_slot < context_slots; ++context_slot) {
13111cb0ef41Sopenharmony_ci        WriteVariableAbbreviation(w, current_abbreviation++, false, false);
13121cb0ef41Sopenharmony_ci      }
13131cb0ef41Sopenharmony_ci
13141cb0ef41Sopenharmony_ci      // The function.
13151cb0ef41Sopenharmony_ci      WriteVariableAbbreviation(w, current_abbreviation++, true, false);
13161cb0ef41Sopenharmony_ci
13171cb0ef41Sopenharmony_ci      // The context.
13181cb0ef41Sopenharmony_ci      WriteVariableAbbreviation(w, current_abbreviation++, true, false);
13191cb0ef41Sopenharmony_ci
13201cb0ef41Sopenharmony_ci      w->WriteULEB128(0);  // Terminate the sibling list.
13211cb0ef41Sopenharmony_ci    }
13221cb0ef41Sopenharmony_ci
13231cb0ef41Sopenharmony_ci    w->WriteULEB128(0);  // Terminate the table.
13241cb0ef41Sopenharmony_ci    return true;
13251cb0ef41Sopenharmony_ci  }
13261cb0ef41Sopenharmony_ci
13271cb0ef41Sopenharmony_ci private:
13281cb0ef41Sopenharmony_ci  CodeDescription* desc_;
13291cb0ef41Sopenharmony_ci};
13301cb0ef41Sopenharmony_ci
13311cb0ef41Sopenharmony_ciclass DebugLineSection : public DebugSection {
13321cb0ef41Sopenharmony_ci public:
13331cb0ef41Sopenharmony_ci  explicit DebugLineSection(CodeDescription* desc)
13341cb0ef41Sopenharmony_ci#ifdef __ELF
13351cb0ef41Sopenharmony_ci      : ELFSection(".debug_line", TYPE_PROGBITS, 1),
13361cb0ef41Sopenharmony_ci#else
13371cb0ef41Sopenharmony_ci      : MachOSection("__debug_line", "__DWARF", 1,
13381cb0ef41Sopenharmony_ci                     MachOSection::S_REGULAR | MachOSection::S_ATTR_DEBUG),
13391cb0ef41Sopenharmony_ci#endif
13401cb0ef41Sopenharmony_ci        desc_(desc) {
13411cb0ef41Sopenharmony_ci  }
13421cb0ef41Sopenharmony_ci
13431cb0ef41Sopenharmony_ci  // DWARF2 standard, figure 34.
13441cb0ef41Sopenharmony_ci  enum DWARF2Opcodes {
13451cb0ef41Sopenharmony_ci    DW_LNS_COPY = 1,
13461cb0ef41Sopenharmony_ci    DW_LNS_ADVANCE_PC = 2,
13471cb0ef41Sopenharmony_ci    DW_LNS_ADVANCE_LINE = 3,
13481cb0ef41Sopenharmony_ci    DW_LNS_SET_FILE = 4,
13491cb0ef41Sopenharmony_ci    DW_LNS_SET_COLUMN = 5,
13501cb0ef41Sopenharmony_ci    DW_LNS_NEGATE_STMT = 6
13511cb0ef41Sopenharmony_ci  };
13521cb0ef41Sopenharmony_ci
13531cb0ef41Sopenharmony_ci  // DWARF2 standard, figure 35.
13541cb0ef41Sopenharmony_ci  enum DWARF2ExtendedOpcode {
13551cb0ef41Sopenharmony_ci    DW_LNE_END_SEQUENCE = 1,
13561cb0ef41Sopenharmony_ci    DW_LNE_SET_ADDRESS = 2,
13571cb0ef41Sopenharmony_ci    DW_LNE_DEFINE_FILE = 3
13581cb0ef41Sopenharmony_ci  };
13591cb0ef41Sopenharmony_ci
13601cb0ef41Sopenharmony_ci  bool WriteBodyInternal(Writer* w) override {
13611cb0ef41Sopenharmony_ci    // Write prologue.
13621cb0ef41Sopenharmony_ci    Writer::Slot<uint32_t> total_length = w->CreateSlotHere<uint32_t>();
13631cb0ef41Sopenharmony_ci    uintptr_t start = w->position();
13641cb0ef41Sopenharmony_ci
13651cb0ef41Sopenharmony_ci    // Used for special opcodes
13661cb0ef41Sopenharmony_ci    const int8_t line_base = 1;
13671cb0ef41Sopenharmony_ci    const uint8_t line_range = 7;
13681cb0ef41Sopenharmony_ci    const int8_t max_line_incr = (line_base + line_range - 1);
13691cb0ef41Sopenharmony_ci    const uint8_t opcode_base = DW_LNS_NEGATE_STMT + 1;
13701cb0ef41Sopenharmony_ci
13711cb0ef41Sopenharmony_ci    w->Write<uint16_t>(2);  // Field version.
13721cb0ef41Sopenharmony_ci    Writer::Slot<uint32_t> prologue_length = w->CreateSlotHere<uint32_t>();
13731cb0ef41Sopenharmony_ci    uintptr_t prologue_start = w->position();
13741cb0ef41Sopenharmony_ci    w->Write<uint8_t>(1);            // Field minimum_instruction_length.
13751cb0ef41Sopenharmony_ci    w->Write<uint8_t>(1);            // Field default_is_stmt.
13761cb0ef41Sopenharmony_ci    w->Write<int8_t>(line_base);     // Field line_base.
13771cb0ef41Sopenharmony_ci    w->Write<uint8_t>(line_range);   // Field line_range.
13781cb0ef41Sopenharmony_ci    w->Write<uint8_t>(opcode_base);  // Field opcode_base.
13791cb0ef41Sopenharmony_ci    w->Write<uint8_t>(0);            // DW_LNS_COPY operands count.
13801cb0ef41Sopenharmony_ci    w->Write<uint8_t>(1);            // DW_LNS_ADVANCE_PC operands count.
13811cb0ef41Sopenharmony_ci    w->Write<uint8_t>(1);            // DW_LNS_ADVANCE_LINE operands count.
13821cb0ef41Sopenharmony_ci    w->Write<uint8_t>(1);            // DW_LNS_SET_FILE operands count.
13831cb0ef41Sopenharmony_ci    w->Write<uint8_t>(1);            // DW_LNS_SET_COLUMN operands count.
13841cb0ef41Sopenharmony_ci    w->Write<uint8_t>(0);            // DW_LNS_NEGATE_STMT operands count.
13851cb0ef41Sopenharmony_ci    w->Write<uint8_t>(0);            // Empty include_directories sequence.
13861cb0ef41Sopenharmony_ci    w->WriteString(desc_->GetFilename().get());  // File name.
13871cb0ef41Sopenharmony_ci    w->WriteULEB128(0);                          // Current directory.
13881cb0ef41Sopenharmony_ci    w->WriteULEB128(0);                          // Unknown modification time.
13891cb0ef41Sopenharmony_ci    w->WriteULEB128(0);                          // Unknown file size.
13901cb0ef41Sopenharmony_ci    w->Write<uint8_t>(0);
13911cb0ef41Sopenharmony_ci    prologue_length.set(static_cast<uint32_t>(w->position() - prologue_start));
13921cb0ef41Sopenharmony_ci
13931cb0ef41Sopenharmony_ci    WriteExtendedOpcode(w, DW_LNE_SET_ADDRESS, sizeof(intptr_t));
13941cb0ef41Sopenharmony_ci    w->Write<intptr_t>(desc_->CodeStart());
13951cb0ef41Sopenharmony_ci    w->Write<uint8_t>(DW_LNS_COPY);
13961cb0ef41Sopenharmony_ci
13971cb0ef41Sopenharmony_ci    intptr_t pc = 0;
13981cb0ef41Sopenharmony_ci    intptr_t line = 1;
13991cb0ef41Sopenharmony_ci    bool is_statement = true;
14001cb0ef41Sopenharmony_ci
14011cb0ef41Sopenharmony_ci    std::vector<LineInfo::PCInfo>* pc_info = desc_->lineinfo()->pc_info();
14021cb0ef41Sopenharmony_ci    std::sort(pc_info->begin(), pc_info->end(), &ComparePCInfo);
14031cb0ef41Sopenharmony_ci
14041cb0ef41Sopenharmony_ci    for (size_t i = 0; i < pc_info->size(); i++) {
14051cb0ef41Sopenharmony_ci      LineInfo::PCInfo* info = &pc_info->at(i);
14061cb0ef41Sopenharmony_ci      DCHECK(info->pc_ >= pc);
14071cb0ef41Sopenharmony_ci
14081cb0ef41Sopenharmony_ci      // Reduce bloating in the debug line table by removing duplicate line
14091cb0ef41Sopenharmony_ci      // entries (per DWARF2 standard).
14101cb0ef41Sopenharmony_ci      intptr_t new_line = desc_->GetScriptLineNumber(info->pos_);
14111cb0ef41Sopenharmony_ci      if (new_line == line) {
14121cb0ef41Sopenharmony_ci        continue;
14131cb0ef41Sopenharmony_ci      }
14141cb0ef41Sopenharmony_ci
14151cb0ef41Sopenharmony_ci      // Mark statement boundaries.  For a better debugging experience, mark
14161cb0ef41Sopenharmony_ci      // the last pc address in the function as a statement (e.g. "}"), so that
14171cb0ef41Sopenharmony_ci      // a user can see the result of the last line executed in the function,
14181cb0ef41Sopenharmony_ci      // should control reach the end.
14191cb0ef41Sopenharmony_ci      if ((i + 1) == pc_info->size()) {
14201cb0ef41Sopenharmony_ci        if (!is_statement) {
14211cb0ef41Sopenharmony_ci          w->Write<uint8_t>(DW_LNS_NEGATE_STMT);
14221cb0ef41Sopenharmony_ci        }
14231cb0ef41Sopenharmony_ci      } else if (is_statement != info->is_statement_) {
14241cb0ef41Sopenharmony_ci        w->Write<uint8_t>(DW_LNS_NEGATE_STMT);
14251cb0ef41Sopenharmony_ci        is_statement = !is_statement;
14261cb0ef41Sopenharmony_ci      }
14271cb0ef41Sopenharmony_ci
14281cb0ef41Sopenharmony_ci      // Generate special opcodes, if possible.  This results in more compact
14291cb0ef41Sopenharmony_ci      // debug line tables.  See the DWARF 2.0 standard to learn more about
14301cb0ef41Sopenharmony_ci      // special opcodes.
14311cb0ef41Sopenharmony_ci      uintptr_t pc_diff = info->pc_ - pc;
14321cb0ef41Sopenharmony_ci      intptr_t line_diff = new_line - line;
14331cb0ef41Sopenharmony_ci
14341cb0ef41Sopenharmony_ci      // Compute special opcode (see DWARF 2.0 standard)
14351cb0ef41Sopenharmony_ci      intptr_t special_opcode =
14361cb0ef41Sopenharmony_ci          (line_diff - line_base) + (line_range * pc_diff) + opcode_base;
14371cb0ef41Sopenharmony_ci
14381cb0ef41Sopenharmony_ci      // If special_opcode is less than or equal to 255, it can be used as a
14391cb0ef41Sopenharmony_ci      // special opcode.  If line_diff is larger than the max line increment
14401cb0ef41Sopenharmony_ci      // allowed for a special opcode, or if line_diff is less than the minimum
14411cb0ef41Sopenharmony_ci      // line that can be added to the line register (i.e. line_base), then
14421cb0ef41Sopenharmony_ci      // special_opcode can't be used.
14431cb0ef41Sopenharmony_ci      if ((special_opcode >= opcode_base) && (special_opcode <= 255) &&
14441cb0ef41Sopenharmony_ci          (line_diff <= max_line_incr) && (line_diff >= line_base)) {
14451cb0ef41Sopenharmony_ci        w->Write<uint8_t>(special_opcode);
14461cb0ef41Sopenharmony_ci      } else {
14471cb0ef41Sopenharmony_ci        w->Write<uint8_t>(DW_LNS_ADVANCE_PC);
14481cb0ef41Sopenharmony_ci        w->WriteSLEB128(pc_diff);
14491cb0ef41Sopenharmony_ci        w->Write<uint8_t>(DW_LNS_ADVANCE_LINE);
14501cb0ef41Sopenharmony_ci        w->WriteSLEB128(line_diff);
14511cb0ef41Sopenharmony_ci        w->Write<uint8_t>(DW_LNS_COPY);
14521cb0ef41Sopenharmony_ci      }
14531cb0ef41Sopenharmony_ci
14541cb0ef41Sopenharmony_ci      // Increment the pc and line operands.
14551cb0ef41Sopenharmony_ci      pc += pc_diff;
14561cb0ef41Sopenharmony_ci      line += line_diff;
14571cb0ef41Sopenharmony_ci    }
14581cb0ef41Sopenharmony_ci    // Advance the pc to the end of the routine, since the end sequence opcode
14591cb0ef41Sopenharmony_ci    // requires this.
14601cb0ef41Sopenharmony_ci    w->Write<uint8_t>(DW_LNS_ADVANCE_PC);
14611cb0ef41Sopenharmony_ci    w->WriteSLEB128(desc_->CodeSize() - pc);
14621cb0ef41Sopenharmony_ci    WriteExtendedOpcode(w, DW_LNE_END_SEQUENCE, 0);
14631cb0ef41Sopenharmony_ci    total_length.set(static_cast<uint32_t>(w->position() - start));
14641cb0ef41Sopenharmony_ci    return true;
14651cb0ef41Sopenharmony_ci  }
14661cb0ef41Sopenharmony_ci
14671cb0ef41Sopenharmony_ci private:
14681cb0ef41Sopenharmony_ci  void WriteExtendedOpcode(Writer* w, DWARF2ExtendedOpcode op,
14691cb0ef41Sopenharmony_ci                           size_t operands_size) {
14701cb0ef41Sopenharmony_ci    w->Write<uint8_t>(0);
14711cb0ef41Sopenharmony_ci    w->WriteULEB128(operands_size + 1);
14721cb0ef41Sopenharmony_ci    w->Write<uint8_t>(op);
14731cb0ef41Sopenharmony_ci  }
14741cb0ef41Sopenharmony_ci
14751cb0ef41Sopenharmony_ci  static bool ComparePCInfo(const LineInfo::PCInfo& a,
14761cb0ef41Sopenharmony_ci                            const LineInfo::PCInfo& b) {
14771cb0ef41Sopenharmony_ci    if (a.pc_ == b.pc_) {
14781cb0ef41Sopenharmony_ci      if (a.is_statement_ != b.is_statement_) {
14791cb0ef41Sopenharmony_ci        return !b.is_statement_;
14801cb0ef41Sopenharmony_ci      }
14811cb0ef41Sopenharmony_ci      return false;
14821cb0ef41Sopenharmony_ci    }
14831cb0ef41Sopenharmony_ci    return a.pc_ < b.pc_;
14841cb0ef41Sopenharmony_ci  }
14851cb0ef41Sopenharmony_ci
14861cb0ef41Sopenharmony_ci  CodeDescription* desc_;
14871cb0ef41Sopenharmony_ci};
14881cb0ef41Sopenharmony_ci
14891cb0ef41Sopenharmony_ci#if V8_TARGET_ARCH_X64
14901cb0ef41Sopenharmony_ci
14911cb0ef41Sopenharmony_ciclass UnwindInfoSection : public DebugSection {
14921cb0ef41Sopenharmony_ci public:
14931cb0ef41Sopenharmony_ci  explicit UnwindInfoSection(CodeDescription* desc);
14941cb0ef41Sopenharmony_ci  bool WriteBodyInternal(Writer* w) override;
14951cb0ef41Sopenharmony_ci
14961cb0ef41Sopenharmony_ci  int WriteCIE(Writer* w);
14971cb0ef41Sopenharmony_ci  void WriteFDE(Writer* w, int);
14981cb0ef41Sopenharmony_ci
14991cb0ef41Sopenharmony_ci  void WriteFDEStateOnEntry(Writer* w);
15001cb0ef41Sopenharmony_ci  void WriteFDEStateAfterRBPPush(Writer* w);
15011cb0ef41Sopenharmony_ci  void WriteFDEStateAfterRBPSet(Writer* w);
15021cb0ef41Sopenharmony_ci  void WriteFDEStateAfterRBPPop(Writer* w);
15031cb0ef41Sopenharmony_ci
15041cb0ef41Sopenharmony_ci  void WriteLength(Writer* w, Writer::Slot<uint32_t>* length_slot,
15051cb0ef41Sopenharmony_ci                   int initial_position);
15061cb0ef41Sopenharmony_ci
15071cb0ef41Sopenharmony_ci private:
15081cb0ef41Sopenharmony_ci  CodeDescription* desc_;
15091cb0ef41Sopenharmony_ci
15101cb0ef41Sopenharmony_ci  // DWARF3 Specification, Table 7.23
15111cb0ef41Sopenharmony_ci  enum CFIInstructions {
15121cb0ef41Sopenharmony_ci    DW_CFA_ADVANCE_LOC = 0x40,
15131cb0ef41Sopenharmony_ci    DW_CFA_OFFSET = 0x80,
15141cb0ef41Sopenharmony_ci    DW_CFA_RESTORE = 0xC0,
15151cb0ef41Sopenharmony_ci    DW_CFA_NOP = 0x00,
15161cb0ef41Sopenharmony_ci    DW_CFA_SET_LOC = 0x01,
15171cb0ef41Sopenharmony_ci    DW_CFA_ADVANCE_LOC1 = 0x02,
15181cb0ef41Sopenharmony_ci    DW_CFA_ADVANCE_LOC2 = 0x03,
15191cb0ef41Sopenharmony_ci    DW_CFA_ADVANCE_LOC4 = 0x04,
15201cb0ef41Sopenharmony_ci    DW_CFA_OFFSET_EXTENDED = 0x05,
15211cb0ef41Sopenharmony_ci    DW_CFA_RESTORE_EXTENDED = 0x06,
15221cb0ef41Sopenharmony_ci    DW_CFA_UNDEFINED = 0x07,
15231cb0ef41Sopenharmony_ci    DW_CFA_SAME_VALUE = 0x08,
15241cb0ef41Sopenharmony_ci    DW_CFA_REGISTER = 0x09,
15251cb0ef41Sopenharmony_ci    DW_CFA_REMEMBER_STATE = 0x0A,
15261cb0ef41Sopenharmony_ci    DW_CFA_RESTORE_STATE = 0x0B,
15271cb0ef41Sopenharmony_ci    DW_CFA_DEF_CFA = 0x0C,
15281cb0ef41Sopenharmony_ci    DW_CFA_DEF_CFA_REGISTER = 0x0D,
15291cb0ef41Sopenharmony_ci    DW_CFA_DEF_CFA_OFFSET = 0x0E,
15301cb0ef41Sopenharmony_ci
15311cb0ef41Sopenharmony_ci    DW_CFA_DEF_CFA_EXPRESSION = 0x0F,
15321cb0ef41Sopenharmony_ci    DW_CFA_EXPRESSION = 0x10,
15331cb0ef41Sopenharmony_ci    DW_CFA_OFFSET_EXTENDED_SF = 0x11,
15341cb0ef41Sopenharmony_ci    DW_CFA_DEF_CFA_SF = 0x12,
15351cb0ef41Sopenharmony_ci    DW_CFA_DEF_CFA_OFFSET_SF = 0x13,
15361cb0ef41Sopenharmony_ci    DW_CFA_VAL_OFFSET = 0x14,
15371cb0ef41Sopenharmony_ci    DW_CFA_VAL_OFFSET_SF = 0x15,
15381cb0ef41Sopenharmony_ci    DW_CFA_VAL_EXPRESSION = 0x16
15391cb0ef41Sopenharmony_ci  };
15401cb0ef41Sopenharmony_ci
15411cb0ef41Sopenharmony_ci  // System V ABI, AMD64 Supplement, Version 0.99.5, Figure 3.36
15421cb0ef41Sopenharmony_ci  enum RegisterMapping {
15431cb0ef41Sopenharmony_ci    // Only the relevant ones have been added to reduce clutter.
15441cb0ef41Sopenharmony_ci    AMD64_RBP = 6,
15451cb0ef41Sopenharmony_ci    AMD64_RSP = 7,
15461cb0ef41Sopenharmony_ci    AMD64_RA = 16
15471cb0ef41Sopenharmony_ci  };
15481cb0ef41Sopenharmony_ci
15491cb0ef41Sopenharmony_ci  enum CFIConstants {
15501cb0ef41Sopenharmony_ci    CIE_ID = 0,
15511cb0ef41Sopenharmony_ci    CIE_VERSION = 1,
15521cb0ef41Sopenharmony_ci    CODE_ALIGN_FACTOR = 1,
15531cb0ef41Sopenharmony_ci    DATA_ALIGN_FACTOR = 1,
15541cb0ef41Sopenharmony_ci    RETURN_ADDRESS_REGISTER = AMD64_RA
15551cb0ef41Sopenharmony_ci  };
15561cb0ef41Sopenharmony_ci};
15571cb0ef41Sopenharmony_ci
15581cb0ef41Sopenharmony_civoid UnwindInfoSection::WriteLength(Writer* w,
15591cb0ef41Sopenharmony_ci                                    Writer::Slot<uint32_t>* length_slot,
15601cb0ef41Sopenharmony_ci                                    int initial_position) {
15611cb0ef41Sopenharmony_ci  uint32_t align = (w->position() - initial_position) % kSystemPointerSize;
15621cb0ef41Sopenharmony_ci
15631cb0ef41Sopenharmony_ci  if (align != 0) {
15641cb0ef41Sopenharmony_ci    for (uint32_t i = 0; i < (kSystemPointerSize - align); i++) {
15651cb0ef41Sopenharmony_ci      w->Write<uint8_t>(DW_CFA_NOP);
15661cb0ef41Sopenharmony_ci    }
15671cb0ef41Sopenharmony_ci  }
15681cb0ef41Sopenharmony_ci
15691cb0ef41Sopenharmony_ci  DCHECK_EQ((w->position() - initial_position) % kSystemPointerSize, 0);
15701cb0ef41Sopenharmony_ci  length_slot->set(static_cast<uint32_t>(w->position() - initial_position));
15711cb0ef41Sopenharmony_ci}
15721cb0ef41Sopenharmony_ci
15731cb0ef41Sopenharmony_ciUnwindInfoSection::UnwindInfoSection(CodeDescription* desc)
15741cb0ef41Sopenharmony_ci#ifdef __ELF
15751cb0ef41Sopenharmony_ci    : ELFSection(".eh_frame", TYPE_X86_64_UNWIND, 1),
15761cb0ef41Sopenharmony_ci#else
15771cb0ef41Sopenharmony_ci    : MachOSection("__eh_frame", "__TEXT", sizeof(uintptr_t),
15781cb0ef41Sopenharmony_ci                   MachOSection::S_REGULAR),
15791cb0ef41Sopenharmony_ci#endif
15801cb0ef41Sopenharmony_ci      desc_(desc) {
15811cb0ef41Sopenharmony_ci}
15821cb0ef41Sopenharmony_ci
15831cb0ef41Sopenharmony_ciint UnwindInfoSection::WriteCIE(Writer* w) {
15841cb0ef41Sopenharmony_ci  Writer::Slot<uint32_t> cie_length_slot = w->CreateSlotHere<uint32_t>();
15851cb0ef41Sopenharmony_ci  uint32_t cie_position = static_cast<uint32_t>(w->position());
15861cb0ef41Sopenharmony_ci
15871cb0ef41Sopenharmony_ci  // Write out the CIE header. Currently no 'common instructions' are
15881cb0ef41Sopenharmony_ci  // emitted onto the CIE; every FDE has its own set of instructions.
15891cb0ef41Sopenharmony_ci
15901cb0ef41Sopenharmony_ci  w->Write<uint32_t>(CIE_ID);
15911cb0ef41Sopenharmony_ci  w->Write<uint8_t>(CIE_VERSION);
15921cb0ef41Sopenharmony_ci  w->Write<uint8_t>(0);  // Null augmentation string.
15931cb0ef41Sopenharmony_ci  w->WriteSLEB128(CODE_ALIGN_FACTOR);
15941cb0ef41Sopenharmony_ci  w->WriteSLEB128(DATA_ALIGN_FACTOR);
15951cb0ef41Sopenharmony_ci  w->Write<uint8_t>(RETURN_ADDRESS_REGISTER);
15961cb0ef41Sopenharmony_ci
15971cb0ef41Sopenharmony_ci  WriteLength(w, &cie_length_slot, cie_position);
15981cb0ef41Sopenharmony_ci
15991cb0ef41Sopenharmony_ci  return cie_position;
16001cb0ef41Sopenharmony_ci}
16011cb0ef41Sopenharmony_ci
16021cb0ef41Sopenharmony_civoid UnwindInfoSection::WriteFDE(Writer* w, int cie_position) {
16031cb0ef41Sopenharmony_ci  // The only FDE for this function. The CFA is the current RBP.
16041cb0ef41Sopenharmony_ci  Writer::Slot<uint32_t> fde_length_slot = w->CreateSlotHere<uint32_t>();
16051cb0ef41Sopenharmony_ci  int fde_position = static_cast<uint32_t>(w->position());
16061cb0ef41Sopenharmony_ci  w->Write<int32_t>(fde_position - cie_position + 4);
16071cb0ef41Sopenharmony_ci
16081cb0ef41Sopenharmony_ci  w->Write<uintptr_t>(desc_->CodeStart());
16091cb0ef41Sopenharmony_ci  w->Write<uintptr_t>(desc_->CodeSize());
16101cb0ef41Sopenharmony_ci
16111cb0ef41Sopenharmony_ci  WriteFDEStateOnEntry(w);
16121cb0ef41Sopenharmony_ci  WriteFDEStateAfterRBPPush(w);
16131cb0ef41Sopenharmony_ci  WriteFDEStateAfterRBPSet(w);
16141cb0ef41Sopenharmony_ci  WriteFDEStateAfterRBPPop(w);
16151cb0ef41Sopenharmony_ci
16161cb0ef41Sopenharmony_ci  WriteLength(w, &fde_length_slot, fde_position);
16171cb0ef41Sopenharmony_ci}
16181cb0ef41Sopenharmony_ci
16191cb0ef41Sopenharmony_civoid UnwindInfoSection::WriteFDEStateOnEntry(Writer* w) {
16201cb0ef41Sopenharmony_ci  // The first state, just after the control has been transferred to the the
16211cb0ef41Sopenharmony_ci  // function.
16221cb0ef41Sopenharmony_ci
16231cb0ef41Sopenharmony_ci  // RBP for this function will be the value of RSP after pushing the RBP
16241cb0ef41Sopenharmony_ci  // for the previous function. The previous RBP has not been pushed yet.
16251cb0ef41Sopenharmony_ci  w->Write<uint8_t>(DW_CFA_DEF_CFA_SF);
16261cb0ef41Sopenharmony_ci  w->WriteULEB128(AMD64_RSP);
16271cb0ef41Sopenharmony_ci  w->WriteSLEB128(-kSystemPointerSize);
16281cb0ef41Sopenharmony_ci
16291cb0ef41Sopenharmony_ci  // The RA is stored at location CFA + kCallerPCOffset. This is an invariant,
16301cb0ef41Sopenharmony_ci  // and hence omitted from the next states.
16311cb0ef41Sopenharmony_ci  w->Write<uint8_t>(DW_CFA_OFFSET_EXTENDED);
16321cb0ef41Sopenharmony_ci  w->WriteULEB128(AMD64_RA);
16331cb0ef41Sopenharmony_ci  w->WriteSLEB128(StandardFrameConstants::kCallerPCOffset);
16341cb0ef41Sopenharmony_ci
16351cb0ef41Sopenharmony_ci  // The RBP of the previous function is still in RBP.
16361cb0ef41Sopenharmony_ci  w->Write<uint8_t>(DW_CFA_SAME_VALUE);
16371cb0ef41Sopenharmony_ci  w->WriteULEB128(AMD64_RBP);
16381cb0ef41Sopenharmony_ci
16391cb0ef41Sopenharmony_ci  // Last location described by this entry.
16401cb0ef41Sopenharmony_ci  w->Write<uint8_t>(DW_CFA_SET_LOC);
16411cb0ef41Sopenharmony_ci  w->Write<uint64_t>(
16421cb0ef41Sopenharmony_ci      desc_->GetStackStateStartAddress(CodeDescription::POST_RBP_PUSH));
16431cb0ef41Sopenharmony_ci}
16441cb0ef41Sopenharmony_ci
16451cb0ef41Sopenharmony_civoid UnwindInfoSection::WriteFDEStateAfterRBPPush(Writer* w) {
16461cb0ef41Sopenharmony_ci  // The second state, just after RBP has been pushed.
16471cb0ef41Sopenharmony_ci
16481cb0ef41Sopenharmony_ci  // RBP / CFA for this function is now the current RSP, so just set the
16491cb0ef41Sopenharmony_ci  // offset from the previous rule (from -8) to 0.
16501cb0ef41Sopenharmony_ci  w->Write<uint8_t>(DW_CFA_DEF_CFA_OFFSET);
16511cb0ef41Sopenharmony_ci  w->WriteULEB128(0);
16521cb0ef41Sopenharmony_ci
16531cb0ef41Sopenharmony_ci  // The previous RBP is stored at CFA + kCallerFPOffset. This is an invariant
16541cb0ef41Sopenharmony_ci  // in this and the next state, and hence omitted in the next state.
16551cb0ef41Sopenharmony_ci  w->Write<uint8_t>(DW_CFA_OFFSET_EXTENDED);
16561cb0ef41Sopenharmony_ci  w->WriteULEB128(AMD64_RBP);
16571cb0ef41Sopenharmony_ci  w->WriteSLEB128(StandardFrameConstants::kCallerFPOffset);
16581cb0ef41Sopenharmony_ci
16591cb0ef41Sopenharmony_ci  // Last location described by this entry.
16601cb0ef41Sopenharmony_ci  w->Write<uint8_t>(DW_CFA_SET_LOC);
16611cb0ef41Sopenharmony_ci  w->Write<uint64_t>(
16621cb0ef41Sopenharmony_ci      desc_->GetStackStateStartAddress(CodeDescription::POST_RBP_SET));
16631cb0ef41Sopenharmony_ci}
16641cb0ef41Sopenharmony_ci
16651cb0ef41Sopenharmony_civoid UnwindInfoSection::WriteFDEStateAfterRBPSet(Writer* w) {
16661cb0ef41Sopenharmony_ci  // The third state, after the RBP has been set.
16671cb0ef41Sopenharmony_ci
16681cb0ef41Sopenharmony_ci  // The CFA can now directly be set to RBP.
16691cb0ef41Sopenharmony_ci  w->Write<uint8_t>(DW_CFA_DEF_CFA);
16701cb0ef41Sopenharmony_ci  w->WriteULEB128(AMD64_RBP);
16711cb0ef41Sopenharmony_ci  w->WriteULEB128(0);
16721cb0ef41Sopenharmony_ci
16731cb0ef41Sopenharmony_ci  // Last location described by this entry.
16741cb0ef41Sopenharmony_ci  w->Write<uint8_t>(DW_CFA_SET_LOC);
16751cb0ef41Sopenharmony_ci  w->Write<uint64_t>(
16761cb0ef41Sopenharmony_ci      desc_->GetStackStateStartAddress(CodeDescription::POST_RBP_POP));
16771cb0ef41Sopenharmony_ci}
16781cb0ef41Sopenharmony_ci
16791cb0ef41Sopenharmony_civoid UnwindInfoSection::WriteFDEStateAfterRBPPop(Writer* w) {
16801cb0ef41Sopenharmony_ci  // The fourth (final) state. The RBP has been popped (just before issuing a
16811cb0ef41Sopenharmony_ci  // return).
16821cb0ef41Sopenharmony_ci
16831cb0ef41Sopenharmony_ci  // The CFA can is now calculated in the same way as in the first state.
16841cb0ef41Sopenharmony_ci  w->Write<uint8_t>(DW_CFA_DEF_CFA_SF);
16851cb0ef41Sopenharmony_ci  w->WriteULEB128(AMD64_RSP);
16861cb0ef41Sopenharmony_ci  w->WriteSLEB128(-kSystemPointerSize);
16871cb0ef41Sopenharmony_ci
16881cb0ef41Sopenharmony_ci  // The RBP
16891cb0ef41Sopenharmony_ci  w->Write<uint8_t>(DW_CFA_OFFSET_EXTENDED);
16901cb0ef41Sopenharmony_ci  w->WriteULEB128(AMD64_RBP);
16911cb0ef41Sopenharmony_ci  w->WriteSLEB128(StandardFrameConstants::kCallerFPOffset);
16921cb0ef41Sopenharmony_ci
16931cb0ef41Sopenharmony_ci  // Last location described by this entry.
16941cb0ef41Sopenharmony_ci  w->Write<uint8_t>(DW_CFA_SET_LOC);
16951cb0ef41Sopenharmony_ci  w->Write<uint64_t>(desc_->CodeEnd());
16961cb0ef41Sopenharmony_ci}
16971cb0ef41Sopenharmony_ci
16981cb0ef41Sopenharmony_cibool UnwindInfoSection::WriteBodyInternal(Writer* w) {
16991cb0ef41Sopenharmony_ci  uint32_t cie_position = WriteCIE(w);
17001cb0ef41Sopenharmony_ci  WriteFDE(w, cie_position);
17011cb0ef41Sopenharmony_ci  return true;
17021cb0ef41Sopenharmony_ci}
17031cb0ef41Sopenharmony_ci
17041cb0ef41Sopenharmony_ci#endif  // V8_TARGET_ARCH_X64
17051cb0ef41Sopenharmony_ci
17061cb0ef41Sopenharmony_cistatic void CreateDWARFSections(CodeDescription* desc, Zone* zone,
17071cb0ef41Sopenharmony_ci                                DebugObject* obj) {
17081cb0ef41Sopenharmony_ci  if (desc->IsLineInfoAvailable()) {
17091cb0ef41Sopenharmony_ci    obj->AddSection(zone->New<DebugInfoSection>(desc));
17101cb0ef41Sopenharmony_ci    obj->AddSection(zone->New<DebugAbbrevSection>(desc));
17111cb0ef41Sopenharmony_ci    obj->AddSection(zone->New<DebugLineSection>(desc));
17121cb0ef41Sopenharmony_ci  }
17131cb0ef41Sopenharmony_ci#if V8_TARGET_ARCH_X64
17141cb0ef41Sopenharmony_ci  obj->AddSection(zone->New<UnwindInfoSection>(desc));
17151cb0ef41Sopenharmony_ci#endif
17161cb0ef41Sopenharmony_ci}
17171cb0ef41Sopenharmony_ci
17181cb0ef41Sopenharmony_ci// -------------------------------------------------------------------
17191cb0ef41Sopenharmony_ci// Binary GDB JIT Interface as described in
17201cb0ef41Sopenharmony_ci//   http://sourceware.org/gdb/onlinedocs/gdb/Declarations.html
17211cb0ef41Sopenharmony_ciextern "C" {
17221cb0ef41Sopenharmony_cienum JITAction { JIT_NOACTION = 0, JIT_REGISTER_FN, JIT_UNREGISTER_FN };
17231cb0ef41Sopenharmony_ci
17241cb0ef41Sopenharmony_cistruct JITCodeEntry {
17251cb0ef41Sopenharmony_ci  JITCodeEntry* next_;
17261cb0ef41Sopenharmony_ci  JITCodeEntry* prev_;
17271cb0ef41Sopenharmony_ci  Address symfile_addr_;
17281cb0ef41Sopenharmony_ci  uint64_t symfile_size_;
17291cb0ef41Sopenharmony_ci};
17301cb0ef41Sopenharmony_ci
17311cb0ef41Sopenharmony_cistruct JITDescriptor {
17321cb0ef41Sopenharmony_ci  uint32_t version_;
17331cb0ef41Sopenharmony_ci  uint32_t action_flag_;
17341cb0ef41Sopenharmony_ci  JITCodeEntry* relevant_entry_;
17351cb0ef41Sopenharmony_ci  JITCodeEntry* first_entry_;
17361cb0ef41Sopenharmony_ci};
17371cb0ef41Sopenharmony_ci
17381cb0ef41Sopenharmony_ci// GDB will place breakpoint into this function.
17391cb0ef41Sopenharmony_ci// To prevent GCC from inlining or removing it we place noinline attribute
17401cb0ef41Sopenharmony_ci// and inline assembler statement inside.
17411cb0ef41Sopenharmony_civoid __attribute__((noinline)) __jit_debug_register_code() { __asm__(""); }
17421cb0ef41Sopenharmony_ci
17431cb0ef41Sopenharmony_ci// GDB will inspect contents of this descriptor.
17441cb0ef41Sopenharmony_ci// Static initialization is necessary to prevent GDB from seeing
17451cb0ef41Sopenharmony_ci// uninitialized descriptor.
17461cb0ef41Sopenharmony_ciJITDescriptor __jit_debug_descriptor = {1, 0, nullptr, nullptr};
17471cb0ef41Sopenharmony_ci
17481cb0ef41Sopenharmony_ci#ifdef OBJECT_PRINT
17491cb0ef41Sopenharmony_civoid __gdb_print_v8_object(Object object) {
17501cb0ef41Sopenharmony_ci  StdoutStream os;
17511cb0ef41Sopenharmony_ci  object.Print(os);
17521cb0ef41Sopenharmony_ci  os << std::flush;
17531cb0ef41Sopenharmony_ci}
17541cb0ef41Sopenharmony_ci#endif
17551cb0ef41Sopenharmony_ci}
17561cb0ef41Sopenharmony_ci
17571cb0ef41Sopenharmony_cistatic JITCodeEntry* CreateCodeEntry(Address symfile_addr,
17581cb0ef41Sopenharmony_ci                                     uintptr_t symfile_size) {
17591cb0ef41Sopenharmony_ci  JITCodeEntry* entry = static_cast<JITCodeEntry*>(
17601cb0ef41Sopenharmony_ci      base::Malloc(sizeof(JITCodeEntry) + symfile_size));
17611cb0ef41Sopenharmony_ci
17621cb0ef41Sopenharmony_ci  entry->symfile_addr_ = reinterpret_cast<Address>(entry + 1);
17631cb0ef41Sopenharmony_ci  entry->symfile_size_ = symfile_size;
17641cb0ef41Sopenharmony_ci  MemCopy(reinterpret_cast<void*>(entry->symfile_addr_),
17651cb0ef41Sopenharmony_ci          reinterpret_cast<void*>(symfile_addr), symfile_size);
17661cb0ef41Sopenharmony_ci
17671cb0ef41Sopenharmony_ci  entry->prev_ = entry->next_ = nullptr;
17681cb0ef41Sopenharmony_ci
17691cb0ef41Sopenharmony_ci  return entry;
17701cb0ef41Sopenharmony_ci}
17711cb0ef41Sopenharmony_ci
17721cb0ef41Sopenharmony_cistatic void DestroyCodeEntry(JITCodeEntry* entry) { base::Free(entry); }
17731cb0ef41Sopenharmony_ci
17741cb0ef41Sopenharmony_cistatic void RegisterCodeEntry(JITCodeEntry* entry) {
17751cb0ef41Sopenharmony_ci  entry->next_ = __jit_debug_descriptor.first_entry_;
17761cb0ef41Sopenharmony_ci  if (entry->next_ != nullptr) entry->next_->prev_ = entry;
17771cb0ef41Sopenharmony_ci  __jit_debug_descriptor.first_entry_ = __jit_debug_descriptor.relevant_entry_ =
17781cb0ef41Sopenharmony_ci      entry;
17791cb0ef41Sopenharmony_ci
17801cb0ef41Sopenharmony_ci  __jit_debug_descriptor.action_flag_ = JIT_REGISTER_FN;
17811cb0ef41Sopenharmony_ci  __jit_debug_register_code();
17821cb0ef41Sopenharmony_ci}
17831cb0ef41Sopenharmony_ci
17841cb0ef41Sopenharmony_cistatic void UnregisterCodeEntry(JITCodeEntry* entry) {
17851cb0ef41Sopenharmony_ci  if (entry->prev_ != nullptr) {
17861cb0ef41Sopenharmony_ci    entry->prev_->next_ = entry->next_;
17871cb0ef41Sopenharmony_ci  } else {
17881cb0ef41Sopenharmony_ci    __jit_debug_descriptor.first_entry_ = entry->next_;
17891cb0ef41Sopenharmony_ci  }
17901cb0ef41Sopenharmony_ci
17911cb0ef41Sopenharmony_ci  if (entry->next_ != nullptr) {
17921cb0ef41Sopenharmony_ci    entry->next_->prev_ = entry->prev_;
17931cb0ef41Sopenharmony_ci  }
17941cb0ef41Sopenharmony_ci
17951cb0ef41Sopenharmony_ci  __jit_debug_descriptor.relevant_entry_ = entry;
17961cb0ef41Sopenharmony_ci  __jit_debug_descriptor.action_flag_ = JIT_UNREGISTER_FN;
17971cb0ef41Sopenharmony_ci  __jit_debug_register_code();
17981cb0ef41Sopenharmony_ci}
17991cb0ef41Sopenharmony_ci
18001cb0ef41Sopenharmony_cistatic JITCodeEntry* CreateELFObject(CodeDescription* desc, Isolate* isolate) {
18011cb0ef41Sopenharmony_ci#ifdef __MACH_O
18021cb0ef41Sopenharmony_ci  Zone zone(isolate->allocator(), ZONE_NAME);
18031cb0ef41Sopenharmony_ci  MachO mach_o(&zone);
18041cb0ef41Sopenharmony_ci  Writer w(&mach_o);
18051cb0ef41Sopenharmony_ci
18061cb0ef41Sopenharmony_ci  const uint32_t code_alignment = static_cast<uint32_t>(kCodeAlignment);
18071cb0ef41Sopenharmony_ci  static_assert(code_alignment == kCodeAlignment,
18081cb0ef41Sopenharmony_ci                "Unsupported code alignment value");
18091cb0ef41Sopenharmony_ci  mach_o.AddSection(zone.New<MachOTextSection>(
18101cb0ef41Sopenharmony_ci      code_alignment, desc->CodeStart(), desc->CodeSize()));
18111cb0ef41Sopenharmony_ci
18121cb0ef41Sopenharmony_ci  CreateDWARFSections(desc, &zone, &mach_o);
18131cb0ef41Sopenharmony_ci
18141cb0ef41Sopenharmony_ci  mach_o.Write(&w, desc->CodeStart(), desc->CodeSize());
18151cb0ef41Sopenharmony_ci#else
18161cb0ef41Sopenharmony_ci  Zone zone(isolate->allocator(), ZONE_NAME);
18171cb0ef41Sopenharmony_ci  ELF elf(&zone);
18181cb0ef41Sopenharmony_ci  Writer w(&elf);
18191cb0ef41Sopenharmony_ci
18201cb0ef41Sopenharmony_ci  size_t text_section_index = elf.AddSection(zone.New<FullHeaderELFSection>(
18211cb0ef41Sopenharmony_ci      ".text", ELFSection::TYPE_NOBITS, kCodeAlignment, desc->CodeStart(), 0,
18221cb0ef41Sopenharmony_ci      desc->CodeSize(), ELFSection::FLAG_ALLOC | ELFSection::FLAG_EXEC));
18231cb0ef41Sopenharmony_ci
18241cb0ef41Sopenharmony_ci  CreateSymbolsTable(desc, &zone, &elf, text_section_index);
18251cb0ef41Sopenharmony_ci
18261cb0ef41Sopenharmony_ci  CreateDWARFSections(desc, &zone, &elf);
18271cb0ef41Sopenharmony_ci
18281cb0ef41Sopenharmony_ci  elf.Write(&w);
18291cb0ef41Sopenharmony_ci#endif
18301cb0ef41Sopenharmony_ci
18311cb0ef41Sopenharmony_ci  return CreateCodeEntry(reinterpret_cast<Address>(w.buffer()), w.position());
18321cb0ef41Sopenharmony_ci}
18331cb0ef41Sopenharmony_ci
18341cb0ef41Sopenharmony_ci// Like base::AddressRegion::StartAddressLess but also compares |end| when
18351cb0ef41Sopenharmony_ci// |begin| is equal.
18361cb0ef41Sopenharmony_cistruct AddressRegionLess {
18371cb0ef41Sopenharmony_ci  bool operator()(const base::AddressRegion& a,
18381cb0ef41Sopenharmony_ci                  const base::AddressRegion& b) const {
18391cb0ef41Sopenharmony_ci    if (a.begin() == b.begin()) return a.end() < b.end();
18401cb0ef41Sopenharmony_ci    return a.begin() < b.begin();
18411cb0ef41Sopenharmony_ci  }
18421cb0ef41Sopenharmony_ci};
18431cb0ef41Sopenharmony_ci
18441cb0ef41Sopenharmony_ciusing CodeMap = std::map<base::AddressRegion, JITCodeEntry*, AddressRegionLess>;
18451cb0ef41Sopenharmony_ci
18461cb0ef41Sopenharmony_cistatic CodeMap* GetCodeMap() {
18471cb0ef41Sopenharmony_ci  // TODO(jgruber): Don't leak.
18481cb0ef41Sopenharmony_ci  static CodeMap* code_map = nullptr;
18491cb0ef41Sopenharmony_ci  if (code_map == nullptr) code_map = new CodeMap();
18501cb0ef41Sopenharmony_ci  return code_map;
18511cb0ef41Sopenharmony_ci}
18521cb0ef41Sopenharmony_ci
18531cb0ef41Sopenharmony_cistatic uint32_t HashCodeAddress(Address addr) {
18541cb0ef41Sopenharmony_ci  static const uintptr_t kGoldenRatio = 2654435761u;
18551cb0ef41Sopenharmony_ci  return static_cast<uint32_t>((addr >> kCodeAlignmentBits) * kGoldenRatio);
18561cb0ef41Sopenharmony_ci}
18571cb0ef41Sopenharmony_ci
18581cb0ef41Sopenharmony_cistatic base::HashMap* GetLineMap() {
18591cb0ef41Sopenharmony_ci  static base::HashMap* line_map = nullptr;
18601cb0ef41Sopenharmony_ci  if (line_map == nullptr) {
18611cb0ef41Sopenharmony_ci    line_map = new base::HashMap();
18621cb0ef41Sopenharmony_ci  }
18631cb0ef41Sopenharmony_ci  return line_map;
18641cb0ef41Sopenharmony_ci}
18651cb0ef41Sopenharmony_ci
18661cb0ef41Sopenharmony_cistatic void PutLineInfo(Address addr, LineInfo* info) {
18671cb0ef41Sopenharmony_ci  base::HashMap* line_map = GetLineMap();
18681cb0ef41Sopenharmony_ci  base::HashMap::Entry* e = line_map->LookupOrInsert(
18691cb0ef41Sopenharmony_ci      reinterpret_cast<void*>(addr), HashCodeAddress(addr));
18701cb0ef41Sopenharmony_ci  if (e->value != nullptr) delete static_cast<LineInfo*>(e->value);
18711cb0ef41Sopenharmony_ci  e->value = info;
18721cb0ef41Sopenharmony_ci}
18731cb0ef41Sopenharmony_ci
18741cb0ef41Sopenharmony_cistatic LineInfo* GetLineInfo(Address addr) {
18751cb0ef41Sopenharmony_ci  void* value = GetLineMap()->Remove(reinterpret_cast<void*>(addr),
18761cb0ef41Sopenharmony_ci                                     HashCodeAddress(addr));
18771cb0ef41Sopenharmony_ci  return static_cast<LineInfo*>(value);
18781cb0ef41Sopenharmony_ci}
18791cb0ef41Sopenharmony_ci
18801cb0ef41Sopenharmony_cistatic void AddUnwindInfo(CodeDescription* desc) {
18811cb0ef41Sopenharmony_ci#if V8_TARGET_ARCH_X64
18821cb0ef41Sopenharmony_ci  if (desc->is_function()) {
18831cb0ef41Sopenharmony_ci    // To avoid propagating unwinding information through
18841cb0ef41Sopenharmony_ci    // compilation pipeline we use an approximation.
18851cb0ef41Sopenharmony_ci    // For most use cases this should not affect usability.
18861cb0ef41Sopenharmony_ci    static const int kFramePointerPushOffset = 1;
18871cb0ef41Sopenharmony_ci    static const int kFramePointerSetOffset = 4;
18881cb0ef41Sopenharmony_ci    static const int kFramePointerPopOffset = -3;
18891cb0ef41Sopenharmony_ci
18901cb0ef41Sopenharmony_ci    uintptr_t frame_pointer_push_address =
18911cb0ef41Sopenharmony_ci        desc->CodeStart() + kFramePointerPushOffset;
18921cb0ef41Sopenharmony_ci
18931cb0ef41Sopenharmony_ci    uintptr_t frame_pointer_set_address =
18941cb0ef41Sopenharmony_ci        desc->CodeStart() + kFramePointerSetOffset;
18951cb0ef41Sopenharmony_ci
18961cb0ef41Sopenharmony_ci    uintptr_t frame_pointer_pop_address =
18971cb0ef41Sopenharmony_ci        desc->CodeEnd() + kFramePointerPopOffset;
18981cb0ef41Sopenharmony_ci
18991cb0ef41Sopenharmony_ci    desc->SetStackStateStartAddress(CodeDescription::POST_RBP_PUSH,
19001cb0ef41Sopenharmony_ci                                    frame_pointer_push_address);
19011cb0ef41Sopenharmony_ci    desc->SetStackStateStartAddress(CodeDescription::POST_RBP_SET,
19021cb0ef41Sopenharmony_ci                                    frame_pointer_set_address);
19031cb0ef41Sopenharmony_ci    desc->SetStackStateStartAddress(CodeDescription::POST_RBP_POP,
19041cb0ef41Sopenharmony_ci                                    frame_pointer_pop_address);
19051cb0ef41Sopenharmony_ci  } else {
19061cb0ef41Sopenharmony_ci    desc->SetStackStateStartAddress(CodeDescription::POST_RBP_PUSH,
19071cb0ef41Sopenharmony_ci                                    desc->CodeStart());
19081cb0ef41Sopenharmony_ci    desc->SetStackStateStartAddress(CodeDescription::POST_RBP_SET,
19091cb0ef41Sopenharmony_ci                                    desc->CodeStart());
19101cb0ef41Sopenharmony_ci    desc->SetStackStateStartAddress(CodeDescription::POST_RBP_POP,
19111cb0ef41Sopenharmony_ci                                    desc->CodeEnd());
19121cb0ef41Sopenharmony_ci  }
19131cb0ef41Sopenharmony_ci#endif  // V8_TARGET_ARCH_X64
19141cb0ef41Sopenharmony_ci}
19151cb0ef41Sopenharmony_ci
19161cb0ef41Sopenharmony_cistatic base::LazyMutex mutex = LAZY_MUTEX_INITIALIZER;
19171cb0ef41Sopenharmony_ci
19181cb0ef41Sopenharmony_cistatic base::Optional<std::pair<CodeMap::iterator, CodeMap::iterator>>
19191cb0ef41Sopenharmony_ciGetOverlappingRegions(CodeMap* map, const base::AddressRegion region) {
19201cb0ef41Sopenharmony_ci  DCHECK_LT(region.begin(), region.end());
19211cb0ef41Sopenharmony_ci
19221cb0ef41Sopenharmony_ci  if (map->empty()) return {};
19231cb0ef41Sopenharmony_ci
19241cb0ef41Sopenharmony_ci  // Find the first overlapping entry.
19251cb0ef41Sopenharmony_ci
19261cb0ef41Sopenharmony_ci  // If successful, points to the first element not less than `region`. The
19271cb0ef41Sopenharmony_ci  // returned iterator has the key in `first` and the value in `second`.
19281cb0ef41Sopenharmony_ci  auto it = map->lower_bound(region);
19291cb0ef41Sopenharmony_ci  auto start_it = it;
19301cb0ef41Sopenharmony_ci
19311cb0ef41Sopenharmony_ci  if (it == map->end()) {
19321cb0ef41Sopenharmony_ci    start_it = map->begin();
19331cb0ef41Sopenharmony_ci    // Find the first overlapping entry.
19341cb0ef41Sopenharmony_ci    for (; start_it != map->end(); ++start_it) {
19351cb0ef41Sopenharmony_ci      if (start_it->first.end() > region.begin()) {
19361cb0ef41Sopenharmony_ci        break;
19371cb0ef41Sopenharmony_ci      }
19381cb0ef41Sopenharmony_ci    }
19391cb0ef41Sopenharmony_ci  } else if (it != map->begin()) {
19401cb0ef41Sopenharmony_ci    for (--it; it != map->begin(); --it) {
19411cb0ef41Sopenharmony_ci      if ((*it).first.end() <= region.begin()) break;
19421cb0ef41Sopenharmony_ci      start_it = it;
19431cb0ef41Sopenharmony_ci    }
19441cb0ef41Sopenharmony_ci    if (it == map->begin() && it->first.end() > region.begin()) {
19451cb0ef41Sopenharmony_ci      start_it = it;
19461cb0ef41Sopenharmony_ci    }
19471cb0ef41Sopenharmony_ci  }
19481cb0ef41Sopenharmony_ci
19491cb0ef41Sopenharmony_ci  if (start_it == map->end()) {
19501cb0ef41Sopenharmony_ci    return {};
19511cb0ef41Sopenharmony_ci  }
19521cb0ef41Sopenharmony_ci
19531cb0ef41Sopenharmony_ci  // Find the first non-overlapping entry after `region`.
19541cb0ef41Sopenharmony_ci
19551cb0ef41Sopenharmony_ci  const auto end_it = map->lower_bound({region.end(), 0});
19561cb0ef41Sopenharmony_ci
19571cb0ef41Sopenharmony_ci  // Return a range containing intersecting regions.
19581cb0ef41Sopenharmony_ci
19591cb0ef41Sopenharmony_ci  if (std::distance(start_it, end_it) < 1)
19601cb0ef41Sopenharmony_ci    return {};  // No overlapping entries.
19611cb0ef41Sopenharmony_ci
19621cb0ef41Sopenharmony_ci  return {{start_it, end_it}};
19631cb0ef41Sopenharmony_ci}
19641cb0ef41Sopenharmony_ci
19651cb0ef41Sopenharmony_ci// Remove entries from the map that intersect the given address region,
19661cb0ef41Sopenharmony_ci// and deregister them from GDB.
19671cb0ef41Sopenharmony_cistatic void RemoveJITCodeEntries(CodeMap* map,
19681cb0ef41Sopenharmony_ci                                 const base::AddressRegion region) {
19691cb0ef41Sopenharmony_ci  if (auto overlap = GetOverlappingRegions(map, region)) {
19701cb0ef41Sopenharmony_ci    auto start_it = overlap->first;
19711cb0ef41Sopenharmony_ci    auto end_it = overlap->second;
19721cb0ef41Sopenharmony_ci    for (auto it = start_it; it != end_it; it++) {
19731cb0ef41Sopenharmony_ci      JITCodeEntry* old_entry = (*it).second;
19741cb0ef41Sopenharmony_ci      UnregisterCodeEntry(old_entry);
19751cb0ef41Sopenharmony_ci      DestroyCodeEntry(old_entry);
19761cb0ef41Sopenharmony_ci    }
19771cb0ef41Sopenharmony_ci
19781cb0ef41Sopenharmony_ci    map->erase(start_it, end_it);
19791cb0ef41Sopenharmony_ci  }
19801cb0ef41Sopenharmony_ci}
19811cb0ef41Sopenharmony_ci
19821cb0ef41Sopenharmony_ci// Insert the entry into the map and register it with GDB.
19831cb0ef41Sopenharmony_cistatic void AddJITCodeEntry(CodeMap* map, const base::AddressRegion region,
19841cb0ef41Sopenharmony_ci                            JITCodeEntry* entry, bool dump_if_enabled,
19851cb0ef41Sopenharmony_ci                            const char* name_hint) {
19861cb0ef41Sopenharmony_ci#if defined(DEBUG) && !V8_OS_WIN
19871cb0ef41Sopenharmony_ci  static int file_num = 0;
19881cb0ef41Sopenharmony_ci  if (FLAG_gdbjit_dump && dump_if_enabled) {
19891cb0ef41Sopenharmony_ci    static const int kMaxFileNameSize = 64;
19901cb0ef41Sopenharmony_ci    char file_name[64];
19911cb0ef41Sopenharmony_ci
19921cb0ef41Sopenharmony_ci    SNPrintF(base::Vector<char>(file_name, kMaxFileNameSize),
19931cb0ef41Sopenharmony_ci             "/tmp/elfdump%s%d.o", (name_hint != nullptr) ? name_hint : "",
19941cb0ef41Sopenharmony_ci             file_num++);
19951cb0ef41Sopenharmony_ci    WriteBytes(file_name, reinterpret_cast<byte*>(entry->symfile_addr_),
19961cb0ef41Sopenharmony_ci               static_cast<int>(entry->symfile_size_));
19971cb0ef41Sopenharmony_ci  }
19981cb0ef41Sopenharmony_ci#endif
19991cb0ef41Sopenharmony_ci
20001cb0ef41Sopenharmony_ci  auto result = map->emplace(region, entry);
20011cb0ef41Sopenharmony_ci  DCHECK(result.second);  // Insertion happened.
20021cb0ef41Sopenharmony_ci  USE(result);
20031cb0ef41Sopenharmony_ci
20041cb0ef41Sopenharmony_ci  RegisterCodeEntry(entry);
20051cb0ef41Sopenharmony_ci}
20061cb0ef41Sopenharmony_ci
20071cb0ef41Sopenharmony_cistatic void AddCode(const char* name, base::AddressRegion region,
20081cb0ef41Sopenharmony_ci                    SharedFunctionInfo shared, LineInfo* lineinfo,
20091cb0ef41Sopenharmony_ci                    Isolate* isolate, bool is_function) {
20101cb0ef41Sopenharmony_ci  DisallowGarbageCollection no_gc;
20111cb0ef41Sopenharmony_ci  CodeDescription code_desc(name, region, shared, lineinfo, is_function);
20121cb0ef41Sopenharmony_ci
20131cb0ef41Sopenharmony_ci  CodeMap* code_map = GetCodeMap();
20141cb0ef41Sopenharmony_ci  RemoveJITCodeEntries(code_map, region);
20151cb0ef41Sopenharmony_ci
20161cb0ef41Sopenharmony_ci  if (!FLAG_gdbjit_full && !code_desc.IsLineInfoAvailable()) {
20171cb0ef41Sopenharmony_ci    delete lineinfo;
20181cb0ef41Sopenharmony_ci    return;
20191cb0ef41Sopenharmony_ci  }
20201cb0ef41Sopenharmony_ci
20211cb0ef41Sopenharmony_ci  AddUnwindInfo(&code_desc);
20221cb0ef41Sopenharmony_ci  JITCodeEntry* entry = CreateELFObject(&code_desc, isolate);
20231cb0ef41Sopenharmony_ci
20241cb0ef41Sopenharmony_ci  delete lineinfo;
20251cb0ef41Sopenharmony_ci
20261cb0ef41Sopenharmony_ci  const char* name_hint = nullptr;
20271cb0ef41Sopenharmony_ci  bool should_dump = false;
20281cb0ef41Sopenharmony_ci  if (FLAG_gdbjit_dump) {
20291cb0ef41Sopenharmony_ci    if (strlen(FLAG_gdbjit_dump_filter) == 0) {
20301cb0ef41Sopenharmony_ci      name_hint = name;
20311cb0ef41Sopenharmony_ci      should_dump = true;
20321cb0ef41Sopenharmony_ci    } else if (name != nullptr) {
20331cb0ef41Sopenharmony_ci      name_hint = strstr(name, FLAG_gdbjit_dump_filter);
20341cb0ef41Sopenharmony_ci      should_dump = (name_hint != nullptr);
20351cb0ef41Sopenharmony_ci    }
20361cb0ef41Sopenharmony_ci  }
20371cb0ef41Sopenharmony_ci  AddJITCodeEntry(code_map, region, entry, should_dump, name_hint);
20381cb0ef41Sopenharmony_ci}
20391cb0ef41Sopenharmony_ci
20401cb0ef41Sopenharmony_civoid EventHandler(const v8::JitCodeEvent* event) {
20411cb0ef41Sopenharmony_ci  if (!FLAG_gdbjit) return;
20421cb0ef41Sopenharmony_ci  if ((event->code_type != v8::JitCodeEvent::JIT_CODE) &&
20431cb0ef41Sopenharmony_ci      (event->code_type != v8::JitCodeEvent::WASM_CODE)) {
20441cb0ef41Sopenharmony_ci    return;
20451cb0ef41Sopenharmony_ci  }
20461cb0ef41Sopenharmony_ci  base::MutexGuard lock_guard(mutex.Pointer());
20471cb0ef41Sopenharmony_ci  switch (event->type) {
20481cb0ef41Sopenharmony_ci    case v8::JitCodeEvent::CODE_ADDED: {
20491cb0ef41Sopenharmony_ci      Address addr = reinterpret_cast<Address>(event->code_start);
20501cb0ef41Sopenharmony_ci      LineInfo* lineinfo = GetLineInfo(addr);
20511cb0ef41Sopenharmony_ci      std::string event_name(event->name.str, event->name.len);
20521cb0ef41Sopenharmony_ci      // It's called UnboundScript in the API but it's a SharedFunctionInfo.
20531cb0ef41Sopenharmony_ci      SharedFunctionInfo shared = event->script.IsEmpty()
20541cb0ef41Sopenharmony_ci                                      ? SharedFunctionInfo()
20551cb0ef41Sopenharmony_ci                                      : *Utils::OpenHandle(*event->script);
20561cb0ef41Sopenharmony_ci      Isolate* isolate = reinterpret_cast<Isolate*>(event->isolate);
20571cb0ef41Sopenharmony_ci      bool is_function = false;
20581cb0ef41Sopenharmony_ci      // TODO(zhin): See if we can use event->code_type to determine
20591cb0ef41Sopenharmony_ci      // is_function, the difference currently is that JIT_CODE is SparkPlug,
20601cb0ef41Sopenharmony_ci      // TurboProp, TurboFan, whereas CodeKindIsOptimizedJSFunction is only
20611cb0ef41Sopenharmony_ci      // TurboProp and TurboFan. is_function is used for AddUnwindInfo, and the
20621cb0ef41Sopenharmony_ci      // prologue that SP generates probably matches that of TP/TF, so we can
20631cb0ef41Sopenharmony_ci      // use event->code_type here instead of finding the Code.
20641cb0ef41Sopenharmony_ci      // TODO(zhin): Rename is_function to be more accurate.
20651cb0ef41Sopenharmony_ci      if (event->code_type == v8::JitCodeEvent::JIT_CODE) {
20661cb0ef41Sopenharmony_ci        Code code = isolate->heap()->GcSafeFindCodeForInnerPointer(addr);
20671cb0ef41Sopenharmony_ci        is_function = CodeKindIsOptimizedJSFunction(code.kind());
20681cb0ef41Sopenharmony_ci      }
20691cb0ef41Sopenharmony_ci      AddCode(event_name.c_str(), {addr, event->code_len}, shared, lineinfo,
20701cb0ef41Sopenharmony_ci              isolate, is_function);
20711cb0ef41Sopenharmony_ci      break;
20721cb0ef41Sopenharmony_ci    }
20731cb0ef41Sopenharmony_ci    case v8::JitCodeEvent::CODE_MOVED:
20741cb0ef41Sopenharmony_ci      // Enabling the GDB JIT interface should disable code compaction.
20751cb0ef41Sopenharmony_ci      UNREACHABLE();
20761cb0ef41Sopenharmony_ci    case v8::JitCodeEvent::CODE_REMOVED:
20771cb0ef41Sopenharmony_ci      // Do nothing.  Instead, adding code causes eviction of any entry whose
20781cb0ef41Sopenharmony_ci      // address range intersects the address range of the added code.
20791cb0ef41Sopenharmony_ci      break;
20801cb0ef41Sopenharmony_ci    case v8::JitCodeEvent::CODE_ADD_LINE_POS_INFO: {
20811cb0ef41Sopenharmony_ci      LineInfo* line_info = reinterpret_cast<LineInfo*>(event->user_data);
20821cb0ef41Sopenharmony_ci      line_info->SetPosition(static_cast<intptr_t>(event->line_info.offset),
20831cb0ef41Sopenharmony_ci                             static_cast<int>(event->line_info.pos),
20841cb0ef41Sopenharmony_ci                             event->line_info.position_type ==
20851cb0ef41Sopenharmony_ci                                 v8::JitCodeEvent::STATEMENT_POSITION);
20861cb0ef41Sopenharmony_ci      break;
20871cb0ef41Sopenharmony_ci    }
20881cb0ef41Sopenharmony_ci    case v8::JitCodeEvent::CODE_START_LINE_INFO_RECORDING: {
20891cb0ef41Sopenharmony_ci      v8::JitCodeEvent* mutable_event = const_cast<v8::JitCodeEvent*>(event);
20901cb0ef41Sopenharmony_ci      mutable_event->user_data = new LineInfo();
20911cb0ef41Sopenharmony_ci      break;
20921cb0ef41Sopenharmony_ci    }
20931cb0ef41Sopenharmony_ci    case v8::JitCodeEvent::CODE_END_LINE_INFO_RECORDING: {
20941cb0ef41Sopenharmony_ci      LineInfo* line_info = reinterpret_cast<LineInfo*>(event->user_data);
20951cb0ef41Sopenharmony_ci      PutLineInfo(reinterpret_cast<Address>(event->code_start), line_info);
20961cb0ef41Sopenharmony_ci      break;
20971cb0ef41Sopenharmony_ci    }
20981cb0ef41Sopenharmony_ci  }
20991cb0ef41Sopenharmony_ci}
21001cb0ef41Sopenharmony_ci
21011cb0ef41Sopenharmony_civoid AddRegionForTesting(const base::AddressRegion region) {
21021cb0ef41Sopenharmony_ci  // For testing purposes we don't care about JITCodeEntry, pass nullptr.
21031cb0ef41Sopenharmony_ci  auto result = GetCodeMap()->emplace(region, nullptr);
21041cb0ef41Sopenharmony_ci  DCHECK(result.second);  // Insertion happened.
21051cb0ef41Sopenharmony_ci  USE(result);
21061cb0ef41Sopenharmony_ci}
21071cb0ef41Sopenharmony_ci
21081cb0ef41Sopenharmony_civoid ClearCodeMapForTesting() { GetCodeMap()->clear(); }
21091cb0ef41Sopenharmony_ci
21101cb0ef41Sopenharmony_cisize_t NumOverlapEntriesForTesting(const base::AddressRegion region) {
21111cb0ef41Sopenharmony_ci  if (auto overlaps = GetOverlappingRegions(GetCodeMap(), region)) {
21121cb0ef41Sopenharmony_ci    return std::distance(overlaps->first, overlaps->second);
21131cb0ef41Sopenharmony_ci  }
21141cb0ef41Sopenharmony_ci  return 0;
21151cb0ef41Sopenharmony_ci}
21161cb0ef41Sopenharmony_ci
21171cb0ef41Sopenharmony_ci#endif
21181cb0ef41Sopenharmony_ci}  // namespace GDBJITInterface
21191cb0ef41Sopenharmony_ci}  // namespace internal
21201cb0ef41Sopenharmony_ci}  // namespace v8
21211cb0ef41Sopenharmony_ci
21221cb0ef41Sopenharmony_ci#undef __MACH_O
21231cb0ef41Sopenharmony_ci#undef __ELF
2124