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