LCOV - code coverage report
Current view: top level - src - gdb-jit.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 1 602 0.2 %
Date: 2019-02-19 Functions: 2 97 2.1 %

          Line data    Source code
       1             : // Copyright 2010 the V8 project authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : #include "src/gdb-jit.h"
       6             : 
       7             : #include <memory>
       8             : #include <vector>
       9             : 
      10             : #include "src/api-inl.h"
      11             : #include "src/base/bits.h"
      12             : #include "src/base/platform/platform.h"
      13             : #include "src/bootstrapper.h"
      14             : #include "src/frames-inl.h"
      15             : #include "src/frames.h"
      16             : #include "src/global-handles.h"
      17             : #include "src/objects.h"
      18             : #include "src/ostreams.h"
      19             : #include "src/snapshot/natives.h"
      20             : #include "src/splay-tree-inl.h"
      21             : #include "src/zone/zone-chunk-list.h"
      22             : 
      23             : namespace v8 {
      24             : namespace internal {
      25             : namespace GDBJITInterface {
      26             : 
      27             : #ifdef ENABLE_GDB_JIT_INTERFACE
      28             : 
      29             : #ifdef __APPLE__
      30             : #define __MACH_O
      31             : class MachO;
      32             : class MachOSection;
      33             : typedef MachO DebugObject;
      34             : typedef MachOSection DebugSection;
      35             : #else
      36             : #define __ELF
      37             : class ELF;
      38             : class ELFSection;
      39             : typedef ELF DebugObject;
      40             : typedef ELFSection DebugSection;
      41             : #endif
      42             : 
      43             : class Writer {
      44             :  public:
      45             :   explicit Writer(DebugObject* debug_object)
      46             :       : debug_object_(debug_object),
      47             :         position_(0),
      48             :         capacity_(1024),
      49           0 :         buffer_(reinterpret_cast<byte*>(malloc(capacity_))) {
      50             :   }
      51             : 
      52             :   ~Writer() {
      53           0 :     free(buffer_);
      54             :   }
      55             : 
      56             :   uintptr_t position() const {
      57             :     return position_;
      58             :   }
      59             : 
      60             :   template<typename T>
      61             :   class Slot {
      62             :    public:
      63             :     Slot(Writer* w, uintptr_t offset) : w_(w), offset_(offset) { }
      64             : 
      65             :     T* operator-> () {
      66           0 :       return w_->RawSlotAt<T>(offset_);
      67             :     }
      68             : 
      69             :     void set(const T& value) {
      70           0 :       *w_->RawSlotAt<T>(offset_) = value;
      71             :     }
      72             : 
      73             :     Slot<T> at(int i) {
      74           0 :       return Slot<T>(w_, offset_ + sizeof(T) * i);
      75             :     }
      76             : 
      77             :    private:
      78             :     Writer* w_;
      79             :     uintptr_t offset_;
      80             :   };
      81             : 
      82             :   template<typename T>
      83           0 :   void Write(const T& val) {
      84           0 :     Ensure(position_ + sizeof(T));
      85           0 :     *RawSlotAt<T>(position_) = val;
      86           0 :     position_ += sizeof(T);
      87           0 :   }
      88             : 
      89             :   template<typename T>
      90             :   Slot<T> SlotAt(uintptr_t offset) {
      91           0 :     Ensure(offset + sizeof(T));
      92             :     return Slot<T>(this, offset);
      93             :   }
      94             : 
      95             :   template<typename T>
      96             :   Slot<T> CreateSlotHere() {
      97           0 :     return CreateSlotsHere<T>(1);
      98             :   }
      99             : 
     100             :   template<typename T>
     101           0 :   Slot<T> CreateSlotsHere(uint32_t count) {
     102           0 :     uintptr_t slot_position = position_;
     103           0 :     position_ += sizeof(T) * count;
     104           0 :     Ensure(position_);
     105           0 :     return SlotAt<T>(slot_position);
     106             :   }
     107             : 
     108           0 :   void Ensure(uintptr_t pos) {
     109           0 :     if (capacity_ < pos) {
     110           0 :       while (capacity_ < pos) capacity_ *= 2;
     111           0 :       buffer_ = reinterpret_cast<byte*>(realloc(buffer_, capacity_));
     112             :     }
     113           0 :   }
     114             : 
     115             :   DebugObject* debug_object() { return debug_object_; }
     116             : 
     117             :   byte* buffer() { return buffer_; }
     118             : 
     119           0 :   void Align(uintptr_t align) {
     120           0 :     uintptr_t delta = position_ % align;
     121           0 :     if (delta == 0) return;
     122           0 :     uintptr_t padding = align - delta;
     123           0 :     Ensure(position_ += padding);
     124             :     DCHECK_EQ(position_ % align, 0);
     125             :   }
     126             : 
     127           0 :   void WriteULEB128(uintptr_t value) {
     128           0 :     do {
     129           0 :       uint8_t byte = value & 0x7F;
     130           0 :       value >>= 7;
     131           0 :       if (value != 0) byte |= 0x80;
     132           0 :       Write<uint8_t>(byte);
     133             :     } while (value != 0);
     134           0 :   }
     135             : 
     136           0 :   void WriteSLEB128(intptr_t value) {
     137             :     bool more = true;
     138           0 :     while (more) {
     139           0 :       int8_t byte = value & 0x7F;
     140           0 :       bool byte_sign = byte & 0x40;
     141           0 :       value >>= 7;
     142             : 
     143           0 :       if ((value == 0 && !byte_sign) || (value == -1 && byte_sign)) {
     144             :         more = false;
     145             :       } else {
     146           0 :         byte |= 0x80;
     147             :       }
     148             : 
     149           0 :       Write<int8_t>(byte);
     150             :     }
     151           0 :   }
     152             : 
     153             :   void WriteString(const char* str) {
     154           0 :     do {
     155           0 :       Write<char>(*str);
     156             :     } while (*str++);
     157             :   }
     158             : 
     159             :  private:
     160             :   template<typename T> friend class Slot;
     161             : 
     162             :   template<typename T>
     163             :   T* RawSlotAt(uintptr_t offset) {
     164             :     DCHECK(offset < capacity_ && offset + sizeof(T) <= capacity_);
     165           0 :     return reinterpret_cast<T*>(&buffer_[offset]);
     166             :   }
     167             : 
     168             :   DebugObject* debug_object_;
     169             :   uintptr_t position_;
     170             :   uintptr_t capacity_;
     171             :   byte* buffer_;
     172             : };
     173             : 
     174             : class ELFStringTable;
     175             : 
     176             : template<typename THeader>
     177           0 : class DebugSectionBase : public ZoneObject {
     178             :  public:
     179           0 :   virtual ~DebugSectionBase() = default;
     180             : 
     181           0 :   virtual void WriteBody(Writer::Slot<THeader> header, Writer* writer) {
     182             :     uintptr_t start = writer->position();
     183           0 :     if (WriteBodyInternal(writer)) {
     184             :       uintptr_t end = writer->position();
     185           0 :       header->offset = static_cast<uint32_t>(start);
     186             : #if defined(__MACH_O)
     187             :       header->addr = 0;
     188             : #endif
     189           0 :       header->size = end - start;
     190             :     }
     191           0 :   }
     192             : 
     193           0 :   virtual bool WriteBodyInternal(Writer* writer) {
     194           0 :     return false;
     195             :   }
     196             : 
     197             :   typedef THeader Header;
     198             : };
     199             : 
     200             : 
     201             : struct MachOSectionHeader {
     202             :   char sectname[16];
     203             :   char segname[16];
     204             : #if V8_TARGET_ARCH_IA32
     205             :   uint32_t addr;
     206             :   uint32_t size;
     207             : #else
     208             :   uint64_t addr;
     209             :   uint64_t size;
     210             : #endif
     211             :   uint32_t offset;
     212             :   uint32_t align;
     213             :   uint32_t reloff;
     214             :   uint32_t nreloc;
     215             :   uint32_t flags;
     216             :   uint32_t reserved1;
     217             :   uint32_t reserved2;
     218             : };
     219             : 
     220             : 
     221             : class MachOSection : public DebugSectionBase<MachOSectionHeader> {
     222             :  public:
     223             :   enum Type {
     224             :     S_REGULAR = 0x0u,
     225             :     S_ATTR_COALESCED = 0xBu,
     226             :     S_ATTR_SOME_INSTRUCTIONS = 0x400u,
     227             :     S_ATTR_DEBUG = 0x02000000u,
     228             :     S_ATTR_PURE_INSTRUCTIONS = 0x80000000u
     229             :   };
     230             : 
     231             :   MachOSection(const char* name, const char* segment, uint32_t align,
     232             :                uint32_t flags)
     233             :       : name_(name), segment_(segment), align_(align), flags_(flags) {
     234             :     if (align_ != 0) {
     235             :       DCHECK(base::bits::IsPowerOfTwo(align));
     236             :       align_ = WhichPowerOf2(align_);
     237             :     }
     238             :   }
     239             : 
     240           0 :   ~MachOSection() override = default;
     241             : 
     242           0 :   virtual void PopulateHeader(Writer::Slot<Header> header) {
     243           0 :     header->addr = 0;
     244           0 :     header->size = 0;
     245           0 :     header->offset = 0;
     246           0 :     header->align = align_;
     247           0 :     header->reloff = 0;
     248           0 :     header->nreloc = 0;
     249           0 :     header->flags = flags_;
     250           0 :     header->reserved1 = 0;
     251           0 :     header->reserved2 = 0;
     252           0 :     memset(header->sectname, 0, sizeof(header->sectname));
     253           0 :     memset(header->segname, 0, sizeof(header->segname));
     254             :     DCHECK(strlen(name_) < sizeof(header->sectname));
     255             :     DCHECK(strlen(segment_) < sizeof(header->segname));
     256           0 :     strncpy(header->sectname, name_, sizeof(header->sectname));
     257           0 :     strncpy(header->segname, segment_, sizeof(header->segname));
     258           0 :   }
     259             : 
     260             :  private:
     261             :   const char* name_;
     262             :   const char* segment_;
     263             :   uint32_t align_;
     264             :   uint32_t flags_;
     265             : };
     266             : 
     267             : 
     268             : struct ELFSectionHeader {
     269             :   uint32_t name;
     270             :   uint32_t type;
     271             :   uintptr_t flags;
     272             :   uintptr_t address;
     273             :   uintptr_t offset;
     274             :   uintptr_t size;
     275             :   uint32_t link;
     276             :   uint32_t info;
     277             :   uintptr_t alignment;
     278             :   uintptr_t entry_size;
     279             : };
     280             : 
     281             : 
     282             : #if defined(__ELF)
     283             : class ELFSection : public DebugSectionBase<ELFSectionHeader> {
     284             :  public:
     285             :   enum Type {
     286             :     TYPE_NULL = 0,
     287             :     TYPE_PROGBITS = 1,
     288             :     TYPE_SYMTAB = 2,
     289             :     TYPE_STRTAB = 3,
     290             :     TYPE_RELA = 4,
     291             :     TYPE_HASH = 5,
     292             :     TYPE_DYNAMIC = 6,
     293             :     TYPE_NOTE = 7,
     294             :     TYPE_NOBITS = 8,
     295             :     TYPE_REL = 9,
     296             :     TYPE_SHLIB = 10,
     297             :     TYPE_DYNSYM = 11,
     298             :     TYPE_LOPROC = 0x70000000,
     299             :     TYPE_X86_64_UNWIND = 0x70000001,
     300             :     TYPE_HIPROC = 0x7FFFFFFF,
     301             :     TYPE_LOUSER = 0x80000000,
     302             :     TYPE_HIUSER = 0xFFFFFFFF
     303             :   };
     304             : 
     305             :   enum Flags {
     306             :     FLAG_WRITE = 1,
     307             :     FLAG_ALLOC = 2,
     308             :     FLAG_EXEC = 4
     309             :   };
     310             : 
     311             :   enum SpecialIndexes { INDEX_ABSOLUTE = 0xFFF1 };
     312             : 
     313             :   ELFSection(const char* name, Type type, uintptr_t align)
     314           0 :       : name_(name), type_(type), align_(align) { }
     315             : 
     316           0 :   ~ELFSection() override = default;
     317             : 
     318             :   void PopulateHeader(Writer::Slot<Header> header, ELFStringTable* strtab);
     319             : 
     320           0 :   void WriteBody(Writer::Slot<Header> header, Writer* w) override {
     321             :     uintptr_t start = w->position();
     322           0 :     if (WriteBodyInternal(w)) {
     323             :       uintptr_t end = w->position();
     324           0 :       header->offset = start;
     325           0 :       header->size = end - start;
     326             :     }
     327           0 :   }
     328             : 
     329           0 :   bool WriteBodyInternal(Writer* w) override { return false; }
     330             : 
     331             :   uint16_t index() const { return index_; }
     332           0 :   void set_index(uint16_t index) { index_ = index; }
     333             : 
     334             :  protected:
     335           0 :   virtual void PopulateHeader(Writer::Slot<Header> header) {
     336           0 :     header->flags = 0;
     337           0 :     header->address = 0;
     338           0 :     header->offset = 0;
     339           0 :     header->size = 0;
     340           0 :     header->link = 0;
     341           0 :     header->info = 0;
     342           0 :     header->entry_size = 0;
     343           0 :   }
     344             : 
     345             :  private:
     346             :   const char* name_;
     347             :   Type type_;
     348             :   uintptr_t align_;
     349             :   uint16_t index_;
     350             : };
     351             : #endif  // defined(__ELF)
     352             : 
     353             : 
     354             : #if defined(__MACH_O)
     355             : class MachOTextSection : public MachOSection {
     356             :  public:
     357             :   MachOTextSection(uint32_t align, uintptr_t addr, uintptr_t size)
     358             :       : MachOSection("__text", "__TEXT", align,
     359             :                      MachOSection::S_REGULAR |
     360             :                          MachOSection::S_ATTR_SOME_INSTRUCTIONS |
     361             :                          MachOSection::S_ATTR_PURE_INSTRUCTIONS),
     362             :         addr_(addr),
     363             :         size_(size) {}
     364             : 
     365             :  protected:
     366             :   virtual void PopulateHeader(Writer::Slot<Header> header) {
     367             :     MachOSection::PopulateHeader(header);
     368             :     header->addr = addr_;
     369             :     header->size = size_;
     370             :   }
     371             : 
     372             :  private:
     373             :   uintptr_t addr_;
     374             :   uintptr_t size_;
     375             : };
     376             : #endif  // defined(__MACH_O)
     377             : 
     378             : 
     379             : #if defined(__ELF)
     380           0 : class FullHeaderELFSection : public ELFSection {
     381             :  public:
     382             :   FullHeaderELFSection(const char* name,
     383             :                        Type type,
     384             :                        uintptr_t align,
     385             :                        uintptr_t addr,
     386             :                        uintptr_t offset,
     387             :                        uintptr_t size,
     388             :                        uintptr_t flags)
     389             :       : ELFSection(name, type, align),
     390             :         addr_(addr),
     391             :         offset_(offset),
     392             :         size_(size),
     393           0 :         flags_(flags) { }
     394             : 
     395             :  protected:
     396           0 :   void PopulateHeader(Writer::Slot<Header> header) override {
     397           0 :     ELFSection::PopulateHeader(header);
     398           0 :     header->address = addr_;
     399           0 :     header->offset = offset_;
     400           0 :     header->size = size_;
     401           0 :     header->flags = flags_;
     402           0 :   }
     403             : 
     404             :  private:
     405             :   uintptr_t addr_;
     406             :   uintptr_t offset_;
     407             :   uintptr_t size_;
     408             :   uintptr_t flags_;
     409             : };
     410             : 
     411             : 
     412           0 : class ELFStringTable : public ELFSection {
     413             :  public:
     414             :   explicit ELFStringTable(const char* name)
     415             :       : ELFSection(name, TYPE_STRTAB, 1),
     416             :         writer_(nullptr),
     417             :         offset_(0),
     418           0 :         size_(0) {}
     419             : 
     420             :   uintptr_t Add(const char* str) {
     421           0 :     if (*str == '\0') return 0;
     422             : 
     423           0 :     uintptr_t offset = size_;
     424           0 :     WriteString(str);
     425             :     return offset;
     426             :   }
     427             : 
     428             :   void AttachWriter(Writer* w) {
     429           0 :     writer_ = w;
     430           0 :     offset_ = writer_->position();
     431             : 
     432             :     // First entry in the string table should be an empty string.
     433           0 :     WriteString("");
     434             :   }
     435             : 
     436           0 :   void DetachWriter() { writer_ = nullptr; }
     437             : 
     438           0 :   void WriteBody(Writer::Slot<Header> header, Writer* w) override {
     439             :     DCHECK_NULL(writer_);
     440           0 :     header->offset = offset_;
     441           0 :     header->size = size_;
     442           0 :   }
     443             : 
     444             :  private:
     445           0 :   void WriteString(const char* str) {
     446             :     uintptr_t written = 0;
     447           0 :     do {
     448           0 :       writer_->Write(*str);
     449           0 :       written++;
     450             :     } while (*str++);
     451           0 :     size_ += written;
     452           0 :   }
     453             : 
     454             :   Writer* writer_;
     455             : 
     456             :   uintptr_t offset_;
     457             :   uintptr_t size_;
     458             : };
     459             : 
     460             : 
     461           0 : void ELFSection::PopulateHeader(Writer::Slot<ELFSection::Header> header,
     462             :                                 ELFStringTable* strtab) {
     463           0 :   header->name = static_cast<uint32_t>(strtab->Add(name_));
     464           0 :   header->type = type_;
     465           0 :   header->alignment = align_;
     466           0 :   PopulateHeader(header);
     467           0 : }
     468             : #endif  // defined(__ELF)
     469             : 
     470             : 
     471             : #if defined(__MACH_O)
     472             : class MachO {
     473             :  public:
     474             :   explicit MachO(Zone* zone) : sections_(zone) {}
     475             : 
     476             :   size_t AddSection(MachOSection* section) {
     477             :     sections_.push_back(section);
     478             :     return sections_.size() - 1;
     479             :   }
     480             : 
     481             :   void Write(Writer* w, uintptr_t code_start, uintptr_t code_size) {
     482             :     Writer::Slot<MachOHeader> header = WriteHeader(w);
     483             :     uintptr_t load_command_start = w->position();
     484             :     Writer::Slot<MachOSegmentCommand> cmd = WriteSegmentCommand(w,
     485             :                                                                 code_start,
     486             :                                                                 code_size);
     487             :     WriteSections(w, cmd, header, load_command_start);
     488             :   }
     489             : 
     490             :  private:
     491             :   struct MachOHeader {
     492             :     uint32_t magic;
     493             :     uint32_t cputype;
     494             :     uint32_t cpusubtype;
     495             :     uint32_t filetype;
     496             :     uint32_t ncmds;
     497             :     uint32_t sizeofcmds;
     498             :     uint32_t flags;
     499             : #if V8_TARGET_ARCH_X64
     500             :     uint32_t reserved;
     501             : #endif
     502             :   };
     503             : 
     504             :   struct MachOSegmentCommand {
     505             :     uint32_t cmd;
     506             :     uint32_t cmdsize;
     507             :     char segname[16];
     508             : #if V8_TARGET_ARCH_IA32
     509             :     uint32_t vmaddr;
     510             :     uint32_t vmsize;
     511             :     uint32_t fileoff;
     512             :     uint32_t filesize;
     513             : #else
     514             :     uint64_t vmaddr;
     515             :     uint64_t vmsize;
     516             :     uint64_t fileoff;
     517             :     uint64_t filesize;
     518             : #endif
     519             :     uint32_t maxprot;
     520             :     uint32_t initprot;
     521             :     uint32_t nsects;
     522             :     uint32_t flags;
     523             :   };
     524             : 
     525             :   enum MachOLoadCommandCmd {
     526             :     LC_SEGMENT_32 = 0x00000001u,
     527             :     LC_SEGMENT_64 = 0x00000019u
     528             :   };
     529             : 
     530             : 
     531             :   Writer::Slot<MachOHeader> WriteHeader(Writer* w) {
     532             :     DCHECK_EQ(w->position(), 0);
     533             :     Writer::Slot<MachOHeader> header = w->CreateSlotHere<MachOHeader>();
     534             : #if V8_TARGET_ARCH_IA32
     535             :     header->magic = 0xFEEDFACEu;
     536             :     header->cputype = 7;  // i386
     537             :     header->cpusubtype = 3;  // CPU_SUBTYPE_I386_ALL
     538             : #elif V8_TARGET_ARCH_X64
     539             :     header->magic = 0xFEEDFACFu;
     540             :     header->cputype = 7 | 0x01000000;  // i386 | 64-bit ABI
     541             :     header->cpusubtype = 3;  // CPU_SUBTYPE_I386_ALL
     542             :     header->reserved = 0;
     543             : #else
     544             : #error Unsupported target architecture.
     545             : #endif
     546             :     header->filetype = 0x1;  // MH_OBJECT
     547             :     header->ncmds = 1;
     548             :     header->sizeofcmds = 0;
     549             :     header->flags = 0;
     550             :     return header;
     551             :   }
     552             : 
     553             : 
     554             :   Writer::Slot<MachOSegmentCommand> WriteSegmentCommand(Writer* w,
     555             :                                                         uintptr_t code_start,
     556             :                                                         uintptr_t code_size) {
     557             :     Writer::Slot<MachOSegmentCommand> cmd =
     558             :         w->CreateSlotHere<MachOSegmentCommand>();
     559             : #if V8_TARGET_ARCH_IA32
     560             :     cmd->cmd = LC_SEGMENT_32;
     561             : #else
     562             :     cmd->cmd = LC_SEGMENT_64;
     563             : #endif
     564             :     cmd->vmaddr = code_start;
     565             :     cmd->vmsize = code_size;
     566             :     cmd->fileoff = 0;
     567             :     cmd->filesize = 0;
     568             :     cmd->maxprot = 7;
     569             :     cmd->initprot = 7;
     570             :     cmd->flags = 0;
     571             :     cmd->nsects = static_cast<uint32_t>(sections_.size());
     572             :     memset(cmd->segname, 0, 16);
     573             :     cmd->cmdsize = sizeof(MachOSegmentCommand) + sizeof(MachOSection::Header) *
     574             :         cmd->nsects;
     575             :     return cmd;
     576             :   }
     577             : 
     578             : 
     579             :   void WriteSections(Writer* w,
     580             :                      Writer::Slot<MachOSegmentCommand> cmd,
     581             :                      Writer::Slot<MachOHeader> header,
     582             :                      uintptr_t load_command_start) {
     583             :     Writer::Slot<MachOSection::Header> headers =
     584             :         w->CreateSlotsHere<MachOSection::Header>(
     585             :             static_cast<uint32_t>(sections_.size()));
     586             :     cmd->fileoff = w->position();
     587             :     header->sizeofcmds =
     588             :         static_cast<uint32_t>(w->position() - load_command_start);
     589             :     uint32_t index = 0;
     590             :     for (MachOSection* section : sections_) {
     591             :       section->PopulateHeader(headers.at(index));
     592             :       section->WriteBody(headers.at(index), w);
     593             :       index++;
     594             :     }
     595             :     cmd->filesize = w->position() - (uintptr_t)cmd->fileoff;
     596             :   }
     597             : 
     598             :   ZoneChunkList<MachOSection*> sections_;
     599             : };
     600             : #endif  // defined(__MACH_O)
     601             : 
     602             : 
     603             : #if defined(__ELF)
     604             : class ELF {
     605             :  public:
     606           0 :   explicit ELF(Zone* zone) : sections_(zone) {
     607           0 :     sections_.push_back(new (zone) ELFSection("", ELFSection::TYPE_NULL, 0));
     608           0 :     sections_.push_back(new (zone) ELFStringTable(".shstrtab"));
     609           0 :   }
     610             : 
     611           0 :   void Write(Writer* w) {
     612           0 :     WriteHeader(w);
     613           0 :     WriteSectionTable(w);
     614           0 :     WriteSections(w);
     615           0 :   }
     616             : 
     617           0 :   ELFSection* SectionAt(uint32_t index) { return *sections_.Find(index); }
     618             : 
     619             :   size_t AddSection(ELFSection* section) {
     620           0 :     sections_.push_back(section);
     621           0 :     section->set_index(sections_.size() - 1);
     622           0 :     return sections_.size() - 1;
     623             :   }
     624             : 
     625             :  private:
     626             :   struct ELFHeader {
     627             :     uint8_t ident[16];
     628             :     uint16_t type;
     629             :     uint16_t machine;
     630             :     uint32_t version;
     631             :     uintptr_t entry;
     632             :     uintptr_t pht_offset;
     633             :     uintptr_t sht_offset;
     634             :     uint32_t flags;
     635             :     uint16_t header_size;
     636             :     uint16_t pht_entry_size;
     637             :     uint16_t pht_entry_num;
     638             :     uint16_t sht_entry_size;
     639             :     uint16_t sht_entry_num;
     640             :     uint16_t sht_strtab_index;
     641             :   };
     642             : 
     643             : 
     644           0 :   void WriteHeader(Writer* w) {
     645             :     DCHECK_EQ(w->position(), 0);
     646             :     Writer::Slot<ELFHeader> header = w->CreateSlotHere<ELFHeader>();
     647             : #if (V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_ARM)
     648             :     const uint8_t ident[16] = {0x7F, 'E', 'L', 'F', 1, 1, 1, 0,
     649             :                                0,    0,   0,   0,   0, 0, 0, 0};
     650             : #elif(V8_TARGET_ARCH_X64 && V8_TARGET_ARCH_64_BIT) || \
     651             :     (V8_TARGET_ARCH_PPC64 && V8_TARGET_LITTLE_ENDIAN)
     652             :     const uint8_t ident[16] = {0x7F, 'E', 'L', 'F', 2, 1, 1, 0,
     653           0 :                                0,    0,   0,   0,   0, 0, 0, 0};
     654             : #elif V8_TARGET_ARCH_PPC64 && V8_TARGET_BIG_ENDIAN && V8_OS_LINUX
     655             :     const uint8_t ident[16] = {0x7F, 'E', 'L', 'F', 2, 2, 1, 0,
     656             :                                0,    0,   0,   0,   0, 0, 0, 0};
     657             : #elif V8_TARGET_ARCH_S390X
     658             :     const uint8_t ident[16] = {0x7F, 'E', 'L', 'F', 2, 2, 1, 3,
     659             :                                0,    0,   0,   0,   0, 0, 0, 0};
     660             : #elif V8_TARGET_ARCH_S390
     661             :     const uint8_t ident[16] = {0x7F, 'E', 'L', 'F', 1, 2, 1, 3,
     662             :                                0,    0,   0,   0,   0, 0, 0, 0};
     663             : #else
     664             : #error Unsupported target architecture.
     665             : #endif
     666           0 :     memcpy(header->ident, ident, 16);
     667           0 :     header->type = 1;
     668             : #if V8_TARGET_ARCH_IA32
     669             :     header->machine = 3;
     670             : #elif V8_TARGET_ARCH_X64
     671             :     // Processor identification value for x64 is 62 as defined in
     672             :     //    System V ABI, AMD64 Supplement
     673             :     //    http://www.x86-64.org/documentation/abi.pdf
     674           0 :     header->machine = 62;
     675             : #elif V8_TARGET_ARCH_ARM
     676             :     // Set to EM_ARM, defined as 40, in "ARM ELF File Format" at
     677             :     // infocenter.arm.com/help/topic/com.arm.doc.dui0101a/DUI0101A_Elf.pdf
     678             :     header->machine = 40;
     679             : #elif V8_TARGET_ARCH_PPC64 && V8_OS_LINUX
     680             :     // Set to EM_PPC64, defined as 21, in Power ABI,
     681             :     // Join the next 4 lines, omitting the spaces and double-slashes.
     682             :     // https://www-03.ibm.com/technologyconnect/tgcm/TGCMFileServlet.wss/
     683             :     // ABI64BitOpenPOWERv1.1_16July2015_pub.pdf?
     684             :     // id=B81AEC1A37F5DAF185257C3E004E8845&linkid=1n0000&c_t=
     685             :     // c9xw7v5dzsj7gt1ifgf4cjbcnskqptmr
     686             :     header->machine = 21;
     687             : #elif V8_TARGET_ARCH_S390
     688             :     // Processor identification value is 22 (EM_S390) as defined in the ABI:
     689             :     // http://refspecs.linuxbase.org/ELF/zSeries/lzsabi0_s390.html#AEN1691
     690             :     // http://refspecs.linuxbase.org/ELF/zSeries/lzsabi0_zSeries.html#AEN1599
     691             :     header->machine = 22;
     692             : #else
     693             : #error Unsupported target architecture.
     694             : #endif
     695           0 :     header->version = 1;
     696           0 :     header->entry = 0;
     697           0 :     header->pht_offset = 0;
     698           0 :     header->sht_offset = sizeof(ELFHeader);  // Section table follows header.
     699           0 :     header->flags = 0;
     700           0 :     header->header_size = sizeof(ELFHeader);
     701           0 :     header->pht_entry_size = 0;
     702           0 :     header->pht_entry_num = 0;
     703           0 :     header->sht_entry_size = sizeof(ELFSection::Header);
     704           0 :     header->sht_entry_num = sections_.size();
     705           0 :     header->sht_strtab_index = 1;
     706           0 :   }
     707             : 
     708           0 :   void WriteSectionTable(Writer* w) {
     709             :     // Section headers table immediately follows file header.
     710             :     DCHECK(w->position() == sizeof(ELFHeader));
     711             : 
     712             :     Writer::Slot<ELFSection::Header> headers =
     713             :         w->CreateSlotsHere<ELFSection::Header>(
     714           0 :             static_cast<uint32_t>(sections_.size()));
     715             : 
     716             :     // String table for section table is the first section.
     717             :     ELFStringTable* strtab = static_cast<ELFStringTable*>(SectionAt(1));
     718             :     strtab->AttachWriter(w);
     719             :     uint32_t index = 0;
     720           0 :     for (ELFSection* section : sections_) {
     721           0 :       section->PopulateHeader(headers.at(index), strtab);
     722           0 :       index++;
     723             :     }
     724             :     strtab->DetachWriter();
     725           0 :   }
     726             : 
     727             :   int SectionHeaderPosition(uint32_t section_index) {
     728             :     return sizeof(ELFHeader) + sizeof(ELFSection::Header) * section_index;
     729             :   }
     730             : 
     731           0 :   void WriteSections(Writer* w) {
     732             :     Writer::Slot<ELFSection::Header> headers =
     733             :         w->SlotAt<ELFSection::Header>(sizeof(ELFHeader));
     734             : 
     735             :     uint32_t index = 0;
     736           0 :     for (ELFSection* section : sections_) {
     737           0 :       section->WriteBody(headers.at(index), w);
     738           0 :       index++;
     739             :     }
     740           0 :   }
     741             : 
     742             :   ZoneChunkList<ELFSection*> sections_;
     743             : };
     744             : 
     745             : class ELFSymbol {
     746             :  public:
     747             :   enum Type {
     748             :     TYPE_NOTYPE = 0,
     749             :     TYPE_OBJECT = 1,
     750             :     TYPE_FUNC = 2,
     751             :     TYPE_SECTION = 3,
     752             :     TYPE_FILE = 4,
     753             :     TYPE_LOPROC = 13,
     754             :     TYPE_HIPROC = 15
     755             :   };
     756             : 
     757             :   enum Binding {
     758             :     BIND_LOCAL = 0,
     759             :     BIND_GLOBAL = 1,
     760             :     BIND_WEAK = 2,
     761             :     BIND_LOPROC = 13,
     762             :     BIND_HIPROC = 15
     763             :   };
     764             : 
     765             :   ELFSymbol(const char* name,
     766             :             uintptr_t value,
     767             :             uintptr_t size,
     768             :             Binding binding,
     769             :             Type type,
     770             :             uint16_t section)
     771             :       : name(name),
     772             :         value(value),
     773             :         size(size),
     774             :         info((binding << 4) | type),
     775             :         other(0),
     776           0 :         section(section) {
     777             :   }
     778             : 
     779             :   Binding binding() const {
     780           0 :     return static_cast<Binding>(info >> 4);
     781             :   }
     782             : #if (V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_ARM ||     \
     783             :      (V8_TARGET_ARCH_S390 && V8_TARGET_ARCH_32_BIT))
     784             :   struct SerializedLayout {
     785             :     SerializedLayout(uint32_t name,
     786             :                      uintptr_t value,
     787             :                      uintptr_t size,
     788             :                      Binding binding,
     789             :                      Type type,
     790             :                      uint16_t section)
     791             :         : name(name),
     792             :           value(value),
     793             :           size(size),
     794             :           info((binding << 4) | type),
     795             :           other(0),
     796             :           section(section) {
     797             :     }
     798             : 
     799             :     uint32_t name;
     800             :     uintptr_t value;
     801             :     uintptr_t size;
     802             :     uint8_t info;
     803             :     uint8_t other;
     804             :     uint16_t section;
     805             :   };
     806             : #elif(V8_TARGET_ARCH_X64 && V8_TARGET_ARCH_64_BIT) || \
     807             :     (V8_TARGET_ARCH_PPC64 && V8_OS_LINUX) || V8_TARGET_ARCH_S390X
     808             :   struct SerializedLayout {
     809             :     SerializedLayout(uint32_t name,
     810             :                      uintptr_t value,
     811             :                      uintptr_t size,
     812             :                      Binding binding,
     813             :                      Type type,
     814             :                      uint16_t section)
     815             :         : name(name),
     816             :           info((binding << 4) | type),
     817             :           other(0),
     818             :           section(section),
     819             :           value(value),
     820             :           size(size) {
     821             :     }
     822             : 
     823             :     uint32_t name;
     824             :     uint8_t info;
     825             :     uint8_t other;
     826             :     uint16_t section;
     827             :     uintptr_t value;
     828             :     uintptr_t size;
     829             :   };
     830             : #endif
     831             : 
     832           0 :   void Write(Writer::Slot<SerializedLayout> s, ELFStringTable* t) const {
     833             :     // Convert symbol names from strings to indexes in the string table.
     834           0 :     s->name = static_cast<uint32_t>(t->Add(name));
     835           0 :     s->value = value;
     836           0 :     s->size = size;
     837           0 :     s->info = info;
     838           0 :     s->other = other;
     839           0 :     s->section = section;
     840           0 :   }
     841             : 
     842             :  private:
     843             :   const char* name;
     844             :   uintptr_t value;
     845             :   uintptr_t size;
     846             :   uint8_t info;
     847             :   uint8_t other;
     848             :   uint16_t section;
     849             : };
     850             : 
     851             : 
     852           0 : class ELFSymbolTable : public ELFSection {
     853             :  public:
     854             :   ELFSymbolTable(const char* name, Zone* zone)
     855             :       : ELFSection(name, TYPE_SYMTAB, sizeof(uintptr_t)),
     856             :         locals_(zone),
     857           0 :         globals_(zone) {}
     858             : 
     859           0 :   void WriteBody(Writer::Slot<Header> header, Writer* w) override {
     860           0 :     w->Align(header->alignment);
     861           0 :     size_t total_symbols = locals_.size() + globals_.size() + 1;
     862           0 :     header->offset = w->position();
     863             : 
     864             :     Writer::Slot<ELFSymbol::SerializedLayout> symbols =
     865             :         w->CreateSlotsHere<ELFSymbol::SerializedLayout>(
     866           0 :             static_cast<uint32_t>(total_symbols));
     867             : 
     868           0 :     header->size = w->position() - header->offset;
     869             : 
     870             :     // String table for this symbol table should follow it in the section table.
     871             :     ELFStringTable* strtab =
     872           0 :         static_cast<ELFStringTable*>(w->debug_object()->SectionAt(index() + 1));
     873             :     strtab->AttachWriter(w);
     874             :     symbols.at(0).set(ELFSymbol::SerializedLayout(0,
     875             :                                                   0,
     876             :                                                   0,
     877             :                                                   ELFSymbol::BIND_LOCAL,
     878             :                                                   ELFSymbol::TYPE_NOTYPE,
     879             :                                                   0));
     880           0 :     WriteSymbolsList(&locals_, symbols.at(1), strtab);
     881             :     WriteSymbolsList(&globals_,
     882             :                      symbols.at(static_cast<uint32_t>(locals_.size() + 1)),
     883           0 :                      strtab);
     884             :     strtab->DetachWriter();
     885           0 :   }
     886             : 
     887           0 :   void Add(const ELFSymbol& symbol) {
     888           0 :     if (symbol.binding() == ELFSymbol::BIND_LOCAL) {
     889           0 :       locals_.push_back(symbol);
     890             :     } else {
     891           0 :       globals_.push_back(symbol);
     892             :     }
     893           0 :   }
     894             : 
     895             :  protected:
     896           0 :   void PopulateHeader(Writer::Slot<Header> header) override {
     897           0 :     ELFSection::PopulateHeader(header);
     898             :     // We are assuming that string table will follow symbol table.
     899           0 :     header->link = index() + 1;
     900           0 :     header->info = static_cast<uint32_t>(locals_.size() + 1);
     901           0 :     header->entry_size = sizeof(ELFSymbol::SerializedLayout);
     902           0 :   }
     903             : 
     904             :  private:
     905           0 :   void WriteSymbolsList(const ZoneChunkList<ELFSymbol>* src,
     906             :                         Writer::Slot<ELFSymbol::SerializedLayout> dst,
     907             :                         ELFStringTable* strtab) {
     908             :     int i = 0;
     909           0 :     for (const ELFSymbol& symbol : *src) {
     910           0 :       symbol.Write(dst.at(i++), strtab);
     911             :     }
     912           0 :   }
     913             : 
     914             :   ZoneChunkList<ELFSymbol> locals_;
     915             :   ZoneChunkList<ELFSymbol> globals_;
     916             : };
     917             : #endif  // defined(__ELF)
     918             : 
     919             : 
     920             : class LineInfo : public Malloced {
     921             :  public:
     922             :   void SetPosition(intptr_t pc, int pos, bool is_statement) {
     923           0 :     AddPCInfo(PCInfo(pc, pos, is_statement));
     924             :   }
     925             : 
     926             :   struct PCInfo {
     927             :     PCInfo(intptr_t pc, int pos, bool is_statement)
     928           0 :         : pc_(pc), pos_(pos), is_statement_(is_statement) {}
     929             : 
     930             :     intptr_t pc_;
     931             :     int pos_;
     932             :     bool is_statement_;
     933             :   };
     934             : 
     935             :   std::vector<PCInfo>* pc_info() { return &pc_info_; }
     936             : 
     937             :  private:
     938           0 :   void AddPCInfo(const PCInfo& pc_info) { pc_info_.push_back(pc_info); }
     939             : 
     940             :   std::vector<PCInfo> pc_info_;
     941             : };
     942             : 
     943             : class CodeDescription {
     944             :  public:
     945             : #if V8_TARGET_ARCH_X64
     946             :   enum StackState {
     947             :     POST_RBP_PUSH,
     948             :     POST_RBP_SET,
     949             :     POST_RBP_POP,
     950             :     STACK_STATE_MAX
     951             :   };
     952             : #endif
     953             : 
     954             :   CodeDescription(const char* name, Code code, SharedFunctionInfo shared,
     955             :                   LineInfo* lineinfo)
     956           0 :       : name_(name), code_(code), shared_info_(shared), lineinfo_(lineinfo) {}
     957             : 
     958             :   const char* name() const {
     959             :     return name_;
     960             :   }
     961             : 
     962             :   LineInfo* lineinfo() const { return lineinfo_; }
     963             : 
     964             :   bool is_function() const {
     965             :     Code::Kind kind = code_->kind();
     966             :     return kind == Code::OPTIMIZED_FUNCTION;
     967             :   }
     968             : 
     969           0 :   bool has_scope_info() const { return !shared_info_.is_null(); }
     970             : 
     971             :   ScopeInfo scope_info() const {
     972             :     DCHECK(has_scope_info());
     973           0 :     return shared_info_->scope_info();
     974             :   }
     975             : 
     976             :   uintptr_t CodeStart() const {
     977           0 :     return static_cast<uintptr_t>(code_->InstructionStart());
     978             :   }
     979             : 
     980             :   uintptr_t CodeEnd() const {
     981           0 :     return static_cast<uintptr_t>(code_->InstructionEnd());
     982             :   }
     983             : 
     984           0 :   uintptr_t CodeSize() const {
     985           0 :     return CodeEnd() - CodeStart();
     986             :   }
     987             : 
     988             :   bool has_script() {
     989             :     return !shared_info_.is_null() && shared_info_->script()->IsScript();
     990             :   }
     991             : 
     992           0 :   Script script() { return Script::cast(shared_info_->script()); }
     993             : 
     994             :   bool IsLineInfoAvailable() { return lineinfo_ != nullptr; }
     995             : 
     996             : #if V8_TARGET_ARCH_X64
     997             :   uintptr_t GetStackStateStartAddress(StackState state) const {
     998             :     DCHECK(state < STACK_STATE_MAX);
     999           0 :     return stack_state_start_addresses_[state];
    1000             :   }
    1001             : 
    1002             :   void SetStackStateStartAddress(StackState state, uintptr_t addr) {
    1003             :     DCHECK(state < STACK_STATE_MAX);
    1004           0 :     stack_state_start_addresses_[state] = addr;
    1005             :   }
    1006             : #endif
    1007             : 
    1008           0 :   std::unique_ptr<char[]> GetFilename() {
    1009           0 :     if (!shared_info_.is_null()) {
    1010           0 :       return String::cast(script()->name())->ToCString();
    1011             :     } else {
    1012           0 :       std::unique_ptr<char[]> result(new char[1]);
    1013           0 :       result[0] = 0;
    1014             :       return result;
    1015             :     }
    1016             :   }
    1017             : 
    1018           0 :   int GetScriptLineNumber(int pos) {
    1019           0 :     if (!shared_info_.is_null()) {
    1020           0 :       return script()->GetLineNumber(pos) + 1;
    1021             :     } else {
    1022             :       return 0;
    1023             :     }
    1024             :   }
    1025             : 
    1026             :  private:
    1027             :   const char* name_;
    1028             :   Code code_;
    1029             :   SharedFunctionInfo shared_info_;
    1030             :   LineInfo* lineinfo_;
    1031             : #if V8_TARGET_ARCH_X64
    1032             :   uintptr_t stack_state_start_addresses_[STACK_STATE_MAX];
    1033             : #endif
    1034             : };
    1035             : 
    1036             : #if defined(__ELF)
    1037           0 : static void CreateSymbolsTable(CodeDescription* desc, Zone* zone, ELF* elf,
    1038             :                                size_t text_section_index) {
    1039             :   ELFSymbolTable* symtab = new(zone) ELFSymbolTable(".symtab", zone);
    1040             :   ELFStringTable* strtab = new(zone) ELFStringTable(".strtab");
    1041             : 
    1042             :   // Symbol table should be followed by the linked string table.
    1043             :   elf->AddSection(symtab);
    1044             :   elf->AddSection(strtab);
    1045             : 
    1046             :   symtab->Add(ELFSymbol("V8 Code", 0, 0, ELFSymbol::BIND_LOCAL,
    1047           0 :                         ELFSymbol::TYPE_FILE, ELFSection::INDEX_ABSOLUTE));
    1048             : 
    1049             :   symtab->Add(ELFSymbol(desc->name(), 0, desc->CodeSize(),
    1050             :                         ELFSymbol::BIND_GLOBAL, ELFSymbol::TYPE_FUNC,
    1051           0 :                         text_section_index));
    1052           0 : }
    1053             : #endif  // defined(__ELF)
    1054             : 
    1055             : 
    1056           0 : class DebugInfoSection : public DebugSection {
    1057             :  public:
    1058             :   explicit DebugInfoSection(CodeDescription* desc)
    1059             : #if defined(__ELF)
    1060             :       : ELFSection(".debug_info", TYPE_PROGBITS, 1),
    1061             : #else
    1062             :       : MachOSection("__debug_info",
    1063             :                      "__DWARF",
    1064             :                      1,
    1065             :                      MachOSection::S_REGULAR | MachOSection::S_ATTR_DEBUG),
    1066             : #endif
    1067           0 :         desc_(desc) { }
    1068             : 
    1069             :   // DWARF2 standard
    1070             :   enum DWARF2LocationOp {
    1071             :     DW_OP_reg0 = 0x50,
    1072             :     DW_OP_reg1 = 0x51,
    1073             :     DW_OP_reg2 = 0x52,
    1074             :     DW_OP_reg3 = 0x53,
    1075             :     DW_OP_reg4 = 0x54,
    1076             :     DW_OP_reg5 = 0x55,
    1077             :     DW_OP_reg6 = 0x56,
    1078             :     DW_OP_reg7 = 0x57,
    1079             :     DW_OP_reg8 = 0x58,
    1080             :     DW_OP_reg9 = 0x59,
    1081             :     DW_OP_reg10 = 0x5A,
    1082             :     DW_OP_reg11 = 0x5B,
    1083             :     DW_OP_reg12 = 0x5C,
    1084             :     DW_OP_reg13 = 0x5D,
    1085             :     DW_OP_reg14 = 0x5E,
    1086             :     DW_OP_reg15 = 0x5F,
    1087             :     DW_OP_reg16 = 0x60,
    1088             :     DW_OP_reg17 = 0x61,
    1089             :     DW_OP_reg18 = 0x62,
    1090             :     DW_OP_reg19 = 0x63,
    1091             :     DW_OP_reg20 = 0x64,
    1092             :     DW_OP_reg21 = 0x65,
    1093             :     DW_OP_reg22 = 0x66,
    1094             :     DW_OP_reg23 = 0x67,
    1095             :     DW_OP_reg24 = 0x68,
    1096             :     DW_OP_reg25 = 0x69,
    1097             :     DW_OP_reg26 = 0x6A,
    1098             :     DW_OP_reg27 = 0x6B,
    1099             :     DW_OP_reg28 = 0x6C,
    1100             :     DW_OP_reg29 = 0x6D,
    1101             :     DW_OP_reg30 = 0x6E,
    1102             :     DW_OP_reg31 = 0x6F,
    1103             :     DW_OP_fbreg = 0x91  // 1 param: SLEB128 offset
    1104             :   };
    1105             : 
    1106             :   enum DWARF2Encoding {
    1107             :     DW_ATE_ADDRESS = 0x1,
    1108             :     DW_ATE_SIGNED = 0x5
    1109             :   };
    1110             : 
    1111           0 :   bool WriteBodyInternal(Writer* w) override {
    1112             :     uintptr_t cu_start = w->position();
    1113             :     Writer::Slot<uint32_t> size = w->CreateSlotHere<uint32_t>();
    1114             :     uintptr_t start = w->position();
    1115           0 :     w->Write<uint16_t>(2);  // DWARF version.
    1116           0 :     w->Write<uint32_t>(0);  // Abbreviation table offset.
    1117           0 :     w->Write<uint8_t>(sizeof(intptr_t));
    1118             : 
    1119           0 :     w->WriteULEB128(1);  // Abbreviation code.
    1120           0 :     w->WriteString(desc_->GetFilename().get());
    1121           0 :     w->Write<intptr_t>(desc_->CodeStart());
    1122           0 :     w->Write<intptr_t>(desc_->CodeStart() + desc_->CodeSize());
    1123           0 :     w->Write<uint32_t>(0);
    1124             : 
    1125           0 :     uint32_t ty_offset = static_cast<uint32_t>(w->position() - cu_start);
    1126           0 :     w->WriteULEB128(3);
    1127           0 :     w->Write<uint8_t>(kSystemPointerSize);
    1128             :     w->WriteString("v8value");
    1129             : 
    1130           0 :     if (desc_->has_scope_info()) {
    1131           0 :       ScopeInfo scope = desc_->scope_info();
    1132           0 :       w->WriteULEB128(2);
    1133           0 :       w->WriteString(desc_->name());
    1134           0 :       w->Write<intptr_t>(desc_->CodeStart());
    1135           0 :       w->Write<intptr_t>(desc_->CodeStart() + desc_->CodeSize());
    1136             :       Writer::Slot<uint32_t> fb_block_size = w->CreateSlotHere<uint32_t>();
    1137             :       uintptr_t fb_block_start = w->position();
    1138             : #if V8_TARGET_ARCH_IA32
    1139             :       w->Write<uint8_t>(DW_OP_reg5);  // The frame pointer's here on ia32
    1140             : #elif V8_TARGET_ARCH_X64
    1141           0 :       w->Write<uint8_t>(DW_OP_reg6);  // and here on x64.
    1142             : #elif V8_TARGET_ARCH_ARM
    1143             :       UNIMPLEMENTED();
    1144             : #elif V8_TARGET_ARCH_MIPS
    1145             :       UNIMPLEMENTED();
    1146             : #elif V8_TARGET_ARCH_MIPS64
    1147             :       UNIMPLEMENTED();
    1148             : #elif V8_TARGET_ARCH_PPC64 && V8_OS_LINUX
    1149             :       w->Write<uint8_t>(DW_OP_reg31);  // The frame pointer is here on PPC64.
    1150             : #elif V8_TARGET_ARCH_S390
    1151             :       w->Write<uint8_t>(DW_OP_reg11);  // The frame pointer's here on S390.
    1152             : #else
    1153             : #error Unsupported target architecture.
    1154             : #endif
    1155           0 :       fb_block_size.set(static_cast<uint32_t>(w->position() - fb_block_start));
    1156             : 
    1157           0 :       int params = scope->ParameterCount();
    1158           0 :       int context_slots = scope->ContextLocalCount();
    1159             :       // The real slot ID is internal_slots + context_slot_id.
    1160             :       int internal_slots = Context::MIN_CONTEXT_SLOTS;
    1161             :       int current_abbreviation = 4;
    1162             : 
    1163             :       EmbeddedVector<char, 256> buffer;
    1164             :       StringBuilder builder(buffer.start(), buffer.length());
    1165             : 
    1166           0 :       for (int param = 0; param < params; ++param) {
    1167           0 :         w->WriteULEB128(current_abbreviation++);
    1168             :         builder.Reset();
    1169           0 :         builder.AddFormatted("param%d", param);
    1170           0 :         w->WriteString(builder.Finalize());
    1171           0 :         w->Write<uint32_t>(ty_offset);
    1172             :         Writer::Slot<uint32_t> block_size = w->CreateSlotHere<uint32_t>();
    1173             :         uintptr_t block_start = w->position();
    1174           0 :         w->Write<uint8_t>(DW_OP_fbreg);
    1175           0 :         w->WriteSLEB128(JavaScriptFrameConstants::kLastParameterOffset +
    1176           0 :                         kSystemPointerSize * (params - param - 1));
    1177           0 :         block_size.set(static_cast<uint32_t>(w->position() - block_start));
    1178             :       }
    1179             : 
    1180             :       // See contexts.h for more information.
    1181             :       DCHECK_EQ(Context::MIN_CONTEXT_SLOTS, 4);
    1182             :       DCHECK_EQ(Context::SCOPE_INFO_INDEX, 0);
    1183             :       DCHECK_EQ(Context::PREVIOUS_INDEX, 1);
    1184             :       DCHECK_EQ(Context::EXTENSION_INDEX, 2);
    1185             :       DCHECK_EQ(Context::NATIVE_CONTEXT_INDEX, 3);
    1186           0 :       w->WriteULEB128(current_abbreviation++);
    1187             :       w->WriteString(".scope_info");
    1188           0 :       w->WriteULEB128(current_abbreviation++);
    1189             :       w->WriteString(".previous");
    1190           0 :       w->WriteULEB128(current_abbreviation++);
    1191             :       w->WriteString(".extension");
    1192           0 :       w->WriteULEB128(current_abbreviation++);
    1193             :       w->WriteString(".native_context");
    1194             : 
    1195           0 :       for (int context_slot = 0;
    1196             :            context_slot < context_slots;
    1197             :            ++context_slot) {
    1198           0 :         w->WriteULEB128(current_abbreviation++);
    1199             :         builder.Reset();
    1200           0 :         builder.AddFormatted("context_slot%d", context_slot + internal_slots);
    1201           0 :         w->WriteString(builder.Finalize());
    1202             :       }
    1203             : 
    1204             :       {
    1205           0 :         w->WriteULEB128(current_abbreviation++);
    1206             :         w->WriteString("__function");
    1207           0 :         w->Write<uint32_t>(ty_offset);
    1208             :         Writer::Slot<uint32_t> block_size = w->CreateSlotHere<uint32_t>();
    1209             :         uintptr_t block_start = w->position();
    1210           0 :         w->Write<uint8_t>(DW_OP_fbreg);
    1211           0 :         w->WriteSLEB128(JavaScriptFrameConstants::kFunctionOffset);
    1212           0 :         block_size.set(static_cast<uint32_t>(w->position() - block_start));
    1213             :       }
    1214             : 
    1215             :       {
    1216           0 :         w->WriteULEB128(current_abbreviation++);
    1217             :         w->WriteString("__context");
    1218           0 :         w->Write<uint32_t>(ty_offset);
    1219             :         Writer::Slot<uint32_t> block_size = w->CreateSlotHere<uint32_t>();
    1220             :         uintptr_t block_start = w->position();
    1221           0 :         w->Write<uint8_t>(DW_OP_fbreg);
    1222           0 :         w->WriteSLEB128(StandardFrameConstants::kContextOffset);
    1223           0 :         block_size.set(static_cast<uint32_t>(w->position() - block_start));
    1224             :       }
    1225             : 
    1226           0 :       w->WriteULEB128(0);  // Terminate the sub program.
    1227             :     }
    1228             : 
    1229           0 :     w->WriteULEB128(0);  // Terminate the compile unit.
    1230           0 :     size.set(static_cast<uint32_t>(w->position() - start));
    1231           0 :     return true;
    1232             :   }
    1233             : 
    1234             :  private:
    1235             :   CodeDescription* desc_;
    1236             : };
    1237             : 
    1238             : 
    1239           0 : class DebugAbbrevSection : public DebugSection {
    1240             :  public:
    1241             :   explicit DebugAbbrevSection(CodeDescription* desc)
    1242             : #ifdef __ELF
    1243             :       : ELFSection(".debug_abbrev", TYPE_PROGBITS, 1),
    1244             : #else
    1245             :       : MachOSection("__debug_abbrev",
    1246             :                      "__DWARF",
    1247             :                      1,
    1248             :                      MachOSection::S_REGULAR | MachOSection::S_ATTR_DEBUG),
    1249             : #endif
    1250           0 :         desc_(desc) { }
    1251             : 
    1252             :   // DWARF2 standard, figure 14.
    1253             :   enum DWARF2Tags {
    1254             :     DW_TAG_FORMAL_PARAMETER = 0x05,
    1255             :     DW_TAG_POINTER_TYPE = 0xF,
    1256             :     DW_TAG_COMPILE_UNIT = 0x11,
    1257             :     DW_TAG_STRUCTURE_TYPE = 0x13,
    1258             :     DW_TAG_BASE_TYPE = 0x24,
    1259             :     DW_TAG_SUBPROGRAM = 0x2E,
    1260             :     DW_TAG_VARIABLE = 0x34
    1261             :   };
    1262             : 
    1263             :   // DWARF2 standard, figure 16.
    1264             :   enum DWARF2ChildrenDetermination {
    1265             :     DW_CHILDREN_NO = 0,
    1266             :     DW_CHILDREN_YES = 1
    1267             :   };
    1268             : 
    1269             :   // DWARF standard, figure 17.
    1270             :   enum DWARF2Attribute {
    1271             :     DW_AT_LOCATION = 0x2,
    1272             :     DW_AT_NAME = 0x3,
    1273             :     DW_AT_BYTE_SIZE = 0xB,
    1274             :     DW_AT_STMT_LIST = 0x10,
    1275             :     DW_AT_LOW_PC = 0x11,
    1276             :     DW_AT_HIGH_PC = 0x12,
    1277             :     DW_AT_ENCODING = 0x3E,
    1278             :     DW_AT_FRAME_BASE = 0x40,
    1279             :     DW_AT_TYPE = 0x49
    1280             :   };
    1281             : 
    1282             :   // DWARF2 standard, figure 19.
    1283             :   enum DWARF2AttributeForm {
    1284             :     DW_FORM_ADDR = 0x1,
    1285             :     DW_FORM_BLOCK4 = 0x4,
    1286             :     DW_FORM_STRING = 0x8,
    1287             :     DW_FORM_DATA4 = 0x6,
    1288             :     DW_FORM_BLOCK = 0x9,
    1289             :     DW_FORM_DATA1 = 0xB,
    1290             :     DW_FORM_FLAG = 0xC,
    1291             :     DW_FORM_REF4 = 0x13
    1292             :   };
    1293             : 
    1294           0 :   void WriteVariableAbbreviation(Writer* w,
    1295             :                                  int abbreviation_code,
    1296             :                                  bool has_value,
    1297             :                                  bool is_parameter) {
    1298           0 :     w->WriteULEB128(abbreviation_code);
    1299           0 :     w->WriteULEB128(is_parameter ? DW_TAG_FORMAL_PARAMETER : DW_TAG_VARIABLE);
    1300           0 :     w->Write<uint8_t>(DW_CHILDREN_NO);
    1301           0 :     w->WriteULEB128(DW_AT_NAME);
    1302           0 :     w->WriteULEB128(DW_FORM_STRING);
    1303           0 :     if (has_value) {
    1304           0 :       w->WriteULEB128(DW_AT_TYPE);
    1305           0 :       w->WriteULEB128(DW_FORM_REF4);
    1306           0 :       w->WriteULEB128(DW_AT_LOCATION);
    1307           0 :       w->WriteULEB128(DW_FORM_BLOCK4);
    1308             :     }
    1309           0 :     w->WriteULEB128(0);
    1310           0 :     w->WriteULEB128(0);
    1311           0 :   }
    1312             : 
    1313           0 :   bool WriteBodyInternal(Writer* w) override {
    1314             :     int current_abbreviation = 1;
    1315           0 :     bool extra_info = desc_->has_scope_info();
    1316             :     DCHECK(desc_->IsLineInfoAvailable());
    1317           0 :     w->WriteULEB128(current_abbreviation++);
    1318           0 :     w->WriteULEB128(DW_TAG_COMPILE_UNIT);
    1319           0 :     w->Write<uint8_t>(extra_info ? DW_CHILDREN_YES : DW_CHILDREN_NO);
    1320           0 :     w->WriteULEB128(DW_AT_NAME);
    1321           0 :     w->WriteULEB128(DW_FORM_STRING);
    1322           0 :     w->WriteULEB128(DW_AT_LOW_PC);
    1323           0 :     w->WriteULEB128(DW_FORM_ADDR);
    1324           0 :     w->WriteULEB128(DW_AT_HIGH_PC);
    1325           0 :     w->WriteULEB128(DW_FORM_ADDR);
    1326           0 :     w->WriteULEB128(DW_AT_STMT_LIST);
    1327           0 :     w->WriteULEB128(DW_FORM_DATA4);
    1328           0 :     w->WriteULEB128(0);
    1329           0 :     w->WriteULEB128(0);
    1330             : 
    1331           0 :     if (extra_info) {
    1332           0 :       ScopeInfo scope = desc_->scope_info();
    1333           0 :       int params = scope->ParameterCount();
    1334           0 :       int context_slots = scope->ContextLocalCount();
    1335             :       // The real slot ID is internal_slots + context_slot_id.
    1336             :       int internal_slots = Context::MIN_CONTEXT_SLOTS;
    1337             :       // Total children is params + context_slots + internal_slots + 2
    1338             :       // (__function and __context).
    1339             : 
    1340             :       // The extra duplication below seems to be necessary to keep
    1341             :       // gdb from getting upset on OSX.
    1342           0 :       w->WriteULEB128(current_abbreviation++);  // Abbreviation code.
    1343           0 :       w->WriteULEB128(DW_TAG_SUBPROGRAM);
    1344           0 :       w->Write<uint8_t>(DW_CHILDREN_YES);
    1345           0 :       w->WriteULEB128(DW_AT_NAME);
    1346           0 :       w->WriteULEB128(DW_FORM_STRING);
    1347           0 :       w->WriteULEB128(DW_AT_LOW_PC);
    1348           0 :       w->WriteULEB128(DW_FORM_ADDR);
    1349           0 :       w->WriteULEB128(DW_AT_HIGH_PC);
    1350           0 :       w->WriteULEB128(DW_FORM_ADDR);
    1351           0 :       w->WriteULEB128(DW_AT_FRAME_BASE);
    1352           0 :       w->WriteULEB128(DW_FORM_BLOCK4);
    1353           0 :       w->WriteULEB128(0);
    1354           0 :       w->WriteULEB128(0);
    1355             : 
    1356           0 :       w->WriteULEB128(current_abbreviation++);
    1357           0 :       w->WriteULEB128(DW_TAG_STRUCTURE_TYPE);
    1358           0 :       w->Write<uint8_t>(DW_CHILDREN_NO);
    1359           0 :       w->WriteULEB128(DW_AT_BYTE_SIZE);
    1360           0 :       w->WriteULEB128(DW_FORM_DATA1);
    1361           0 :       w->WriteULEB128(DW_AT_NAME);
    1362           0 :       w->WriteULEB128(DW_FORM_STRING);
    1363           0 :       w->WriteULEB128(0);
    1364           0 :       w->WriteULEB128(0);
    1365             : 
    1366           0 :       for (int param = 0; param < params; ++param) {
    1367           0 :         WriteVariableAbbreviation(w, current_abbreviation++, true, true);
    1368             :       }
    1369             : 
    1370           0 :       for (int internal_slot = 0;
    1371             :            internal_slot < internal_slots;
    1372             :            ++internal_slot) {
    1373           0 :         WriteVariableAbbreviation(w, current_abbreviation++, false, false);
    1374             :       }
    1375             : 
    1376           0 :       for (int context_slot = 0;
    1377             :            context_slot < context_slots;
    1378             :            ++context_slot) {
    1379           0 :         WriteVariableAbbreviation(w, current_abbreviation++, false, false);
    1380             :       }
    1381             : 
    1382             :       // The function.
    1383           0 :       WriteVariableAbbreviation(w, current_abbreviation++, true, false);
    1384             : 
    1385             :       // The context.
    1386           0 :       WriteVariableAbbreviation(w, current_abbreviation++, true, false);
    1387             : 
    1388           0 :       w->WriteULEB128(0);  // Terminate the sibling list.
    1389             :     }
    1390             : 
    1391           0 :     w->WriteULEB128(0);  // Terminate the table.
    1392           0 :     return true;
    1393             :   }
    1394             : 
    1395             :  private:
    1396             :   CodeDescription* desc_;
    1397             : };
    1398             : 
    1399             : 
    1400           0 : class DebugLineSection : public DebugSection {
    1401             :  public:
    1402             :   explicit DebugLineSection(CodeDescription* desc)
    1403             : #ifdef __ELF
    1404             :       : ELFSection(".debug_line", TYPE_PROGBITS, 1),
    1405             : #else
    1406             :       : MachOSection("__debug_line",
    1407             :                      "__DWARF",
    1408             :                      1,
    1409             :                      MachOSection::S_REGULAR | MachOSection::S_ATTR_DEBUG),
    1410             : #endif
    1411           0 :         desc_(desc) { }
    1412             : 
    1413             :   // DWARF2 standard, figure 34.
    1414             :   enum DWARF2Opcodes {
    1415             :     DW_LNS_COPY = 1,
    1416             :     DW_LNS_ADVANCE_PC = 2,
    1417             :     DW_LNS_ADVANCE_LINE = 3,
    1418             :     DW_LNS_SET_FILE = 4,
    1419             :     DW_LNS_SET_COLUMN = 5,
    1420             :     DW_LNS_NEGATE_STMT = 6
    1421             :   };
    1422             : 
    1423             :   // DWARF2 standard, figure 35.
    1424             :   enum DWARF2ExtendedOpcode {
    1425             :     DW_LNE_END_SEQUENCE = 1,
    1426             :     DW_LNE_SET_ADDRESS = 2,
    1427             :     DW_LNE_DEFINE_FILE = 3
    1428             :   };
    1429             : 
    1430           0 :   bool WriteBodyInternal(Writer* w) override {
    1431             :     // Write prologue.
    1432             :     Writer::Slot<uint32_t> total_length = w->CreateSlotHere<uint32_t>();
    1433             :     uintptr_t start = w->position();
    1434             : 
    1435             :     // Used for special opcodes
    1436           0 :     const int8_t line_base = 1;
    1437           0 :     const uint8_t line_range = 7;
    1438             :     const int8_t max_line_incr = (line_base + line_range - 1);
    1439           0 :     const uint8_t opcode_base = DW_LNS_NEGATE_STMT + 1;
    1440             : 
    1441           0 :     w->Write<uint16_t>(2);  // Field version.
    1442             :     Writer::Slot<uint32_t> prologue_length = w->CreateSlotHere<uint32_t>();
    1443             :     uintptr_t prologue_start = w->position();
    1444           0 :     w->Write<uint8_t>(1);  // Field minimum_instruction_length.
    1445           0 :     w->Write<uint8_t>(1);  // Field default_is_stmt.
    1446           0 :     w->Write<int8_t>(line_base);  // Field line_base.
    1447           0 :     w->Write<uint8_t>(line_range);  // Field line_range.
    1448           0 :     w->Write<uint8_t>(opcode_base);  // Field opcode_base.
    1449           0 :     w->Write<uint8_t>(0);  // DW_LNS_COPY operands count.
    1450           0 :     w->Write<uint8_t>(1);  // DW_LNS_ADVANCE_PC operands count.
    1451           0 :     w->Write<uint8_t>(1);  // DW_LNS_ADVANCE_LINE operands count.
    1452           0 :     w->Write<uint8_t>(1);  // DW_LNS_SET_FILE operands count.
    1453           0 :     w->Write<uint8_t>(1);  // DW_LNS_SET_COLUMN operands count.
    1454           0 :     w->Write<uint8_t>(0);  // DW_LNS_NEGATE_STMT operands count.
    1455           0 :     w->Write<uint8_t>(0);  // Empty include_directories sequence.
    1456           0 :     w->WriteString(desc_->GetFilename().get());  // File name.
    1457           0 :     w->WriteULEB128(0);  // Current directory.
    1458           0 :     w->WriteULEB128(0);  // Unknown modification time.
    1459           0 :     w->WriteULEB128(0);  // Unknown file size.
    1460           0 :     w->Write<uint8_t>(0);
    1461           0 :     prologue_length.set(static_cast<uint32_t>(w->position() - prologue_start));
    1462             : 
    1463           0 :     WriteExtendedOpcode(w, DW_LNE_SET_ADDRESS, sizeof(intptr_t));
    1464           0 :     w->Write<intptr_t>(desc_->CodeStart());
    1465           0 :     w->Write<uint8_t>(DW_LNS_COPY);
    1466             : 
    1467             :     intptr_t pc = 0;
    1468             :     intptr_t line = 1;
    1469             :     bool is_statement = true;
    1470             : 
    1471           0 :     std::vector<LineInfo::PCInfo>* pc_info = desc_->lineinfo()->pc_info();
    1472           0 :     std::sort(pc_info->begin(), pc_info->end(), &ComparePCInfo);
    1473             : 
    1474           0 :     for (size_t i = 0; i < pc_info->size(); i++) {
    1475             :       LineInfo::PCInfo* info = &pc_info->at(i);
    1476             :       DCHECK(info->pc_ >= pc);
    1477             : 
    1478             :       // Reduce bloating in the debug line table by removing duplicate line
    1479             :       // entries (per DWARF2 standard).
    1480           0 :       intptr_t  new_line = desc_->GetScriptLineNumber(info->pos_);
    1481           0 :       if (new_line == line) {
    1482             :         continue;
    1483             :       }
    1484             : 
    1485             :       // Mark statement boundaries.  For a better debugging experience, mark
    1486             :       // the last pc address in the function as a statement (e.g. "}"), so that
    1487             :       // a user can see the result of the last line executed in the function,
    1488             :       // should control reach the end.
    1489           0 :       if ((i + 1) == pc_info->size()) {
    1490           0 :         if (!is_statement) {
    1491           0 :           w->Write<uint8_t>(DW_LNS_NEGATE_STMT);
    1492             :         }
    1493           0 :       } else if (is_statement != info->is_statement_) {
    1494           0 :         w->Write<uint8_t>(DW_LNS_NEGATE_STMT);
    1495           0 :         is_statement = !is_statement;
    1496             :       }
    1497             : 
    1498             :       // Generate special opcodes, if possible.  This results in more compact
    1499             :       // debug line tables.  See the DWARF 2.0 standard to learn more about
    1500             :       // special opcodes.
    1501           0 :       uintptr_t pc_diff = info->pc_ - pc;
    1502           0 :       intptr_t line_diff = new_line - line;
    1503             : 
    1504             :       // Compute special opcode (see DWARF 2.0 standard)
    1505             :       intptr_t special_opcode = (line_diff - line_base) +
    1506           0 :                                 (line_range * pc_diff) + opcode_base;
    1507             : 
    1508             :       // If special_opcode is less than or equal to 255, it can be used as a
    1509             :       // special opcode.  If line_diff is larger than the max line increment
    1510             :       // allowed for a special opcode, or if line_diff is less than the minimum
    1511             :       // line that can be added to the line register (i.e. line_base), then
    1512             :       // special_opcode can't be used.
    1513           0 :       if ((special_opcode >= opcode_base) && (special_opcode <= 255) &&
    1514           0 :           (line_diff <= max_line_incr) && (line_diff >= line_base)) {
    1515           0 :         w->Write<uint8_t>(special_opcode);
    1516             :       } else {
    1517           0 :         w->Write<uint8_t>(DW_LNS_ADVANCE_PC);
    1518           0 :         w->WriteSLEB128(pc_diff);
    1519           0 :         w->Write<uint8_t>(DW_LNS_ADVANCE_LINE);
    1520           0 :         w->WriteSLEB128(line_diff);
    1521           0 :         w->Write<uint8_t>(DW_LNS_COPY);
    1522             :       }
    1523             : 
    1524             :       // Increment the pc and line operands.
    1525           0 :       pc += pc_diff;
    1526             :       line += line_diff;
    1527             :     }
    1528             :     // Advance the pc to the end of the routine, since the end sequence opcode
    1529             :     // requires this.
    1530           0 :     w->Write<uint8_t>(DW_LNS_ADVANCE_PC);
    1531           0 :     w->WriteSLEB128(desc_->CodeSize() - pc);
    1532           0 :     WriteExtendedOpcode(w, DW_LNE_END_SEQUENCE, 0);
    1533           0 :     total_length.set(static_cast<uint32_t>(w->position() - start));
    1534           0 :     return true;
    1535             :   }
    1536             : 
    1537             :  private:
    1538           0 :   void WriteExtendedOpcode(Writer* w,
    1539             :                            DWARF2ExtendedOpcode op,
    1540             :                            size_t operands_size) {
    1541           0 :     w->Write<uint8_t>(0);
    1542           0 :     w->WriteULEB128(operands_size + 1);
    1543           0 :     w->Write<uint8_t>(op);
    1544           0 :   }
    1545             : 
    1546           0 :   static bool ComparePCInfo(const LineInfo::PCInfo& a,
    1547             :                             const LineInfo::PCInfo& b) {
    1548           0 :     if (a.pc_ == b.pc_) {
    1549           0 :       if (a.is_statement_ != b.is_statement_) {
    1550           0 :         return !b.is_statement_;
    1551             :       }
    1552             :       return false;
    1553             :     }
    1554           0 :     return a.pc_ < b.pc_;
    1555             :   }
    1556             : 
    1557             :   CodeDescription* desc_;
    1558             : };
    1559             : 
    1560             : 
    1561             : #if V8_TARGET_ARCH_X64
    1562             : 
    1563           0 : class UnwindInfoSection : public DebugSection {
    1564             :  public:
    1565             :   explicit UnwindInfoSection(CodeDescription* desc);
    1566             :   bool WriteBodyInternal(Writer* w) override;
    1567             : 
    1568             :   int WriteCIE(Writer* w);
    1569             :   void WriteFDE(Writer* w, int);
    1570             : 
    1571             :   void WriteFDEStateOnEntry(Writer* w);
    1572             :   void WriteFDEStateAfterRBPPush(Writer* w);
    1573             :   void WriteFDEStateAfterRBPSet(Writer* w);
    1574             :   void WriteFDEStateAfterRBPPop(Writer* w);
    1575             : 
    1576             :   void WriteLength(Writer* w,
    1577             :                    Writer::Slot<uint32_t>* length_slot,
    1578             :                    int initial_position);
    1579             : 
    1580             :  private:
    1581             :   CodeDescription* desc_;
    1582             : 
    1583             :   // DWARF3 Specification, Table 7.23
    1584             :   enum CFIInstructions {
    1585             :     DW_CFA_ADVANCE_LOC = 0x40,
    1586             :     DW_CFA_OFFSET = 0x80,
    1587             :     DW_CFA_RESTORE = 0xC0,
    1588             :     DW_CFA_NOP = 0x00,
    1589             :     DW_CFA_SET_LOC = 0x01,
    1590             :     DW_CFA_ADVANCE_LOC1 = 0x02,
    1591             :     DW_CFA_ADVANCE_LOC2 = 0x03,
    1592             :     DW_CFA_ADVANCE_LOC4 = 0x04,
    1593             :     DW_CFA_OFFSET_EXTENDED = 0x05,
    1594             :     DW_CFA_RESTORE_EXTENDED = 0x06,
    1595             :     DW_CFA_UNDEFINED = 0x07,
    1596             :     DW_CFA_SAME_VALUE = 0x08,
    1597             :     DW_CFA_REGISTER = 0x09,
    1598             :     DW_CFA_REMEMBER_STATE = 0x0A,
    1599             :     DW_CFA_RESTORE_STATE = 0x0B,
    1600             :     DW_CFA_DEF_CFA = 0x0C,
    1601             :     DW_CFA_DEF_CFA_REGISTER = 0x0D,
    1602             :     DW_CFA_DEF_CFA_OFFSET = 0x0E,
    1603             : 
    1604             :     DW_CFA_DEF_CFA_EXPRESSION = 0x0F,
    1605             :     DW_CFA_EXPRESSION = 0x10,
    1606             :     DW_CFA_OFFSET_EXTENDED_SF = 0x11,
    1607             :     DW_CFA_DEF_CFA_SF = 0x12,
    1608             :     DW_CFA_DEF_CFA_OFFSET_SF = 0x13,
    1609             :     DW_CFA_VAL_OFFSET = 0x14,
    1610             :     DW_CFA_VAL_OFFSET_SF = 0x15,
    1611             :     DW_CFA_VAL_EXPRESSION = 0x16
    1612             :   };
    1613             : 
    1614             :   // System V ABI, AMD64 Supplement, Version 0.99.5, Figure 3.36
    1615             :   enum RegisterMapping {
    1616             :     // Only the relevant ones have been added to reduce clutter.
    1617             :     AMD64_RBP = 6,
    1618             :     AMD64_RSP = 7,
    1619             :     AMD64_RA = 16
    1620             :   };
    1621             : 
    1622             :   enum CFIConstants {
    1623             :     CIE_ID = 0,
    1624             :     CIE_VERSION = 1,
    1625             :     CODE_ALIGN_FACTOR = 1,
    1626             :     DATA_ALIGN_FACTOR = 1,
    1627             :     RETURN_ADDRESS_REGISTER = AMD64_RA
    1628             :   };
    1629             : };
    1630             : 
    1631             : 
    1632           0 : void UnwindInfoSection::WriteLength(Writer* w,
    1633             :                                     Writer::Slot<uint32_t>* length_slot,
    1634             :                                     int initial_position) {
    1635           0 :   uint32_t align = (w->position() - initial_position) % kSystemPointerSize;
    1636             : 
    1637           0 :   if (align != 0) {
    1638           0 :     for (uint32_t i = 0; i < (kSystemPointerSize - align); i++) {
    1639           0 :       w->Write<uint8_t>(DW_CFA_NOP);
    1640             :     }
    1641             :   }
    1642             : 
    1643             :   DCHECK_EQ((w->position() - initial_position) % kSystemPointerSize, 0);
    1644           0 :   length_slot->set(static_cast<uint32_t>(w->position() - initial_position));
    1645           0 : }
    1646             : 
    1647             : 
    1648           0 : UnwindInfoSection::UnwindInfoSection(CodeDescription* desc)
    1649             : #ifdef __ELF
    1650             :     : ELFSection(".eh_frame", TYPE_X86_64_UNWIND, 1),
    1651             : #else
    1652             :     : MachOSection("__eh_frame", "__TEXT", sizeof(uintptr_t),
    1653             :                    MachOSection::S_REGULAR),
    1654             : #endif
    1655           0 :       desc_(desc) { }
    1656             : 
    1657           0 : int UnwindInfoSection::WriteCIE(Writer* w) {
    1658           0 :   Writer::Slot<uint32_t> cie_length_slot = w->CreateSlotHere<uint32_t>();
    1659             :   uint32_t cie_position = static_cast<uint32_t>(w->position());
    1660             : 
    1661             :   // Write out the CIE header. Currently no 'common instructions' are
    1662             :   // emitted onto the CIE; every FDE has its own set of instructions.
    1663             : 
    1664           0 :   w->Write<uint32_t>(CIE_ID);
    1665           0 :   w->Write<uint8_t>(CIE_VERSION);
    1666           0 :   w->Write<uint8_t>(0);  // Null augmentation string.
    1667           0 :   w->WriteSLEB128(CODE_ALIGN_FACTOR);
    1668           0 :   w->WriteSLEB128(DATA_ALIGN_FACTOR);
    1669           0 :   w->Write<uint8_t>(RETURN_ADDRESS_REGISTER);
    1670             : 
    1671           0 :   WriteLength(w, &cie_length_slot, cie_position);
    1672             : 
    1673           0 :   return cie_position;
    1674             : }
    1675             : 
    1676             : 
    1677           0 : void UnwindInfoSection::WriteFDE(Writer* w, int cie_position) {
    1678             :   // The only FDE for this function. The CFA is the current RBP.
    1679           0 :   Writer::Slot<uint32_t> fde_length_slot = w->CreateSlotHere<uint32_t>();
    1680           0 :   int fde_position = static_cast<uint32_t>(w->position());
    1681           0 :   w->Write<int32_t>(fde_position - cie_position + 4);
    1682             : 
    1683           0 :   w->Write<uintptr_t>(desc_->CodeStart());
    1684           0 :   w->Write<uintptr_t>(desc_->CodeSize());
    1685             : 
    1686           0 :   WriteFDEStateOnEntry(w);
    1687           0 :   WriteFDEStateAfterRBPPush(w);
    1688           0 :   WriteFDEStateAfterRBPSet(w);
    1689           0 :   WriteFDEStateAfterRBPPop(w);
    1690             : 
    1691           0 :   WriteLength(w, &fde_length_slot, fde_position);
    1692           0 : }
    1693             : 
    1694             : 
    1695           0 : void UnwindInfoSection::WriteFDEStateOnEntry(Writer* w) {
    1696             :   // The first state, just after the control has been transferred to the the
    1697             :   // function.
    1698             : 
    1699             :   // RBP for this function will be the value of RSP after pushing the RBP
    1700             :   // for the previous function. The previous RBP has not been pushed yet.
    1701           0 :   w->Write<uint8_t>(DW_CFA_DEF_CFA_SF);
    1702           0 :   w->WriteULEB128(AMD64_RSP);
    1703           0 :   w->WriteSLEB128(-kSystemPointerSize);
    1704             : 
    1705             :   // The RA is stored at location CFA + kCallerPCOffset. This is an invariant,
    1706             :   // and hence omitted from the next states.
    1707           0 :   w->Write<uint8_t>(DW_CFA_OFFSET_EXTENDED);
    1708           0 :   w->WriteULEB128(AMD64_RA);
    1709           0 :   w->WriteSLEB128(StandardFrameConstants::kCallerPCOffset);
    1710             : 
    1711             :   // The RBP of the previous function is still in RBP.
    1712           0 :   w->Write<uint8_t>(DW_CFA_SAME_VALUE);
    1713           0 :   w->WriteULEB128(AMD64_RBP);
    1714             : 
    1715             :   // Last location described by this entry.
    1716           0 :   w->Write<uint8_t>(DW_CFA_SET_LOC);
    1717             :   w->Write<uint64_t>(
    1718           0 :       desc_->GetStackStateStartAddress(CodeDescription::POST_RBP_PUSH));
    1719           0 : }
    1720             : 
    1721             : 
    1722           0 : void UnwindInfoSection::WriteFDEStateAfterRBPPush(Writer* w) {
    1723             :   // The second state, just after RBP has been pushed.
    1724             : 
    1725             :   // RBP / CFA for this function is now the current RSP, so just set the
    1726             :   // offset from the previous rule (from -8) to 0.
    1727           0 :   w->Write<uint8_t>(DW_CFA_DEF_CFA_OFFSET);
    1728           0 :   w->WriteULEB128(0);
    1729             : 
    1730             :   // The previous RBP is stored at CFA + kCallerFPOffset. This is an invariant
    1731             :   // in this and the next state, and hence omitted in the next state.
    1732           0 :   w->Write<uint8_t>(DW_CFA_OFFSET_EXTENDED);
    1733           0 :   w->WriteULEB128(AMD64_RBP);
    1734           0 :   w->WriteSLEB128(StandardFrameConstants::kCallerFPOffset);
    1735             : 
    1736             :   // Last location described by this entry.
    1737           0 :   w->Write<uint8_t>(DW_CFA_SET_LOC);
    1738             :   w->Write<uint64_t>(
    1739           0 :       desc_->GetStackStateStartAddress(CodeDescription::POST_RBP_SET));
    1740           0 : }
    1741             : 
    1742             : 
    1743           0 : void UnwindInfoSection::WriteFDEStateAfterRBPSet(Writer* w) {
    1744             :   // The third state, after the RBP has been set.
    1745             : 
    1746             :   // The CFA can now directly be set to RBP.
    1747           0 :   w->Write<uint8_t>(DW_CFA_DEF_CFA);
    1748           0 :   w->WriteULEB128(AMD64_RBP);
    1749           0 :   w->WriteULEB128(0);
    1750             : 
    1751             :   // Last location described by this entry.
    1752           0 :   w->Write<uint8_t>(DW_CFA_SET_LOC);
    1753             :   w->Write<uint64_t>(
    1754           0 :       desc_->GetStackStateStartAddress(CodeDescription::POST_RBP_POP));
    1755           0 : }
    1756             : 
    1757             : 
    1758           0 : void UnwindInfoSection::WriteFDEStateAfterRBPPop(Writer* w) {
    1759             :   // The fourth (final) state. The RBP has been popped (just before issuing a
    1760             :   // return).
    1761             : 
    1762             :   // The CFA can is now calculated in the same way as in the first state.
    1763           0 :   w->Write<uint8_t>(DW_CFA_DEF_CFA_SF);
    1764           0 :   w->WriteULEB128(AMD64_RSP);
    1765           0 :   w->WriteSLEB128(-kSystemPointerSize);
    1766             : 
    1767             :   // The RBP
    1768           0 :   w->Write<uint8_t>(DW_CFA_OFFSET_EXTENDED);
    1769           0 :   w->WriteULEB128(AMD64_RBP);
    1770           0 :   w->WriteSLEB128(StandardFrameConstants::kCallerFPOffset);
    1771             : 
    1772             :   // Last location described by this entry.
    1773           0 :   w->Write<uint8_t>(DW_CFA_SET_LOC);
    1774           0 :   w->Write<uint64_t>(desc_->CodeEnd());
    1775           0 : }
    1776             : 
    1777             : 
    1778           0 : bool UnwindInfoSection::WriteBodyInternal(Writer* w) {
    1779           0 :   uint32_t cie_position = WriteCIE(w);
    1780           0 :   WriteFDE(w, cie_position);
    1781           0 :   return true;
    1782             : }
    1783             : 
    1784             : 
    1785             : #endif  // V8_TARGET_ARCH_X64
    1786             : 
    1787           0 : static void CreateDWARFSections(CodeDescription* desc,
    1788             :                                 Zone* zone,
    1789             :                                 DebugObject* obj) {
    1790           0 :   if (desc->IsLineInfoAvailable()) {
    1791             :     obj->AddSection(new(zone) DebugInfoSection(desc));
    1792             :     obj->AddSection(new(zone) DebugAbbrevSection(desc));
    1793             :     obj->AddSection(new(zone) DebugLineSection(desc));
    1794             :   }
    1795             : #if V8_TARGET_ARCH_X64
    1796             :   obj->AddSection(new(zone) UnwindInfoSection(desc));
    1797             : #endif
    1798           0 : }
    1799             : 
    1800             : 
    1801             : // -------------------------------------------------------------------
    1802             : // Binary GDB JIT Interface as described in
    1803             : //   http://sourceware.org/gdb/onlinedocs/gdb/Declarations.html
    1804             : extern "C" {
    1805             :   typedef enum {
    1806             :     JIT_NOACTION = 0,
    1807             :     JIT_REGISTER_FN,
    1808             :     JIT_UNREGISTER_FN
    1809             :   } JITAction;
    1810             : 
    1811             :   struct JITCodeEntry {
    1812             :     JITCodeEntry* next_;
    1813             :     JITCodeEntry* prev_;
    1814             :     Address symfile_addr_;
    1815             :     uint64_t symfile_size_;
    1816             :   };
    1817             : 
    1818             :   struct JITDescriptor {
    1819             :     uint32_t version_;
    1820             :     uint32_t action_flag_;
    1821             :     JITCodeEntry* relevant_entry_;
    1822             :     JITCodeEntry* first_entry_;
    1823             :   };
    1824             : 
    1825             :   // GDB will place breakpoint into this function.
    1826             :   // To prevent GCC from inlining or removing it we place noinline attribute
    1827             :   // and inline assembler statement inside.
    1828           0 :   void __attribute__((noinline)) __jit_debug_register_code() {
    1829           0 :     __asm__("");
    1830           0 :   }
    1831             : 
    1832             :   // GDB will inspect contents of this descriptor.
    1833             :   // Static initialization is necessary to prevent GDB from seeing
    1834             :   // uninitialized descriptor.
    1835             :   JITDescriptor __jit_debug_descriptor = {1, 0, nullptr, nullptr};
    1836             : 
    1837             : #ifdef OBJECT_PRINT
    1838             :   void __gdb_print_v8_object(Object object) {
    1839             :     StdoutStream os;
    1840             :     object->Print(os);
    1841             :     os << std::flush;
    1842             :   }
    1843             : #endif
    1844             : }
    1845             : 
    1846             : 
    1847           0 : static JITCodeEntry* CreateCodeEntry(Address symfile_addr,
    1848             :                                      uintptr_t symfile_size) {
    1849             :   JITCodeEntry* entry = static_cast<JITCodeEntry*>(
    1850           0 :       malloc(sizeof(JITCodeEntry) + symfile_size));
    1851             : 
    1852           0 :   entry->symfile_addr_ = reinterpret_cast<Address>(entry + 1);
    1853           0 :   entry->symfile_size_ = symfile_size;
    1854             :   MemCopy(reinterpret_cast<void*>(entry->symfile_addr_),
    1855           0 :           reinterpret_cast<void*>(symfile_addr), symfile_size);
    1856             : 
    1857           0 :   entry->prev_ = entry->next_ = nullptr;
    1858             : 
    1859           0 :   return entry;
    1860             : }
    1861             : 
    1862             : 
    1863             : static void DestroyCodeEntry(JITCodeEntry* entry) {
    1864           0 :   free(entry);
    1865             : }
    1866             : 
    1867             : 
    1868           0 : static void RegisterCodeEntry(JITCodeEntry* entry) {
    1869           0 :   entry->next_ = __jit_debug_descriptor.first_entry_;
    1870           0 :   if (entry->next_ != nullptr) entry->next_->prev_ = entry;
    1871             :   __jit_debug_descriptor.first_entry_ =
    1872           0 :       __jit_debug_descriptor.relevant_entry_ = entry;
    1873             : 
    1874           0 :   __jit_debug_descriptor.action_flag_ = JIT_REGISTER_FN;
    1875           0 :   __jit_debug_register_code();
    1876           0 : }
    1877             : 
    1878             : 
    1879           0 : static void UnregisterCodeEntry(JITCodeEntry* entry) {
    1880           0 :   if (entry->prev_ != nullptr) {
    1881           0 :     entry->prev_->next_ = entry->next_;
    1882             :   } else {
    1883           0 :     __jit_debug_descriptor.first_entry_ = entry->next_;
    1884             :   }
    1885             : 
    1886           0 :   if (entry->next_ != nullptr) {
    1887           0 :     entry->next_->prev_ = entry->prev_;
    1888             :   }
    1889             : 
    1890           0 :   __jit_debug_descriptor.relevant_entry_ = entry;
    1891           0 :   __jit_debug_descriptor.action_flag_ = JIT_UNREGISTER_FN;
    1892           0 :   __jit_debug_register_code();
    1893           0 : }
    1894             : 
    1895             : 
    1896           0 : static JITCodeEntry* CreateELFObject(CodeDescription* desc, Isolate* isolate) {
    1897             : #ifdef __MACH_O
    1898             :   Zone zone(isolate->allocator(), ZONE_NAME);
    1899             :   MachO mach_o(&zone);
    1900             :   Writer w(&mach_o);
    1901             : 
    1902             :   mach_o.AddSection(new(&zone) MachOTextSection(kCodeAlignment,
    1903             :                                                 desc->CodeStart(),
    1904             :                                                 desc->CodeSize()));
    1905             : 
    1906             :   CreateDWARFSections(desc, &zone, &mach_o);
    1907             : 
    1908             :   mach_o.Write(&w, desc->CodeStart(), desc->CodeSize());
    1909             : #else
    1910           0 :   Zone zone(isolate->allocator(), ZONE_NAME);
    1911           0 :   ELF elf(&zone);
    1912             :   Writer w(&elf);
    1913             : 
    1914             :   size_t text_section_index = elf.AddSection(new (&zone) FullHeaderELFSection(
    1915             :       ".text", ELFSection::TYPE_NOBITS, kCodeAlignment, desc->CodeStart(), 0,
    1916           0 :       desc->CodeSize(), ELFSection::FLAG_ALLOC | ELFSection::FLAG_EXEC));
    1917             : 
    1918           0 :   CreateSymbolsTable(desc, &zone, &elf, text_section_index);
    1919             : 
    1920           0 :   CreateDWARFSections(desc, &zone, &elf);
    1921             : 
    1922           0 :   elf.Write(&w);
    1923             : #endif
    1924             : 
    1925           0 :   return CreateCodeEntry(reinterpret_cast<Address>(w.buffer()), w.position());
    1926             : }
    1927             : 
    1928             : 
    1929             : struct AddressRange {
    1930             :   Address start;
    1931             :   Address end;
    1932             : };
    1933             : 
    1934             : struct SplayTreeConfig {
    1935             :   typedef AddressRange Key;
    1936             :   typedef JITCodeEntry* Value;
    1937             :   static const AddressRange kNoKey;
    1938             :   static Value NoValue() { return nullptr; }
    1939             :   static int Compare(const AddressRange& a, const AddressRange& b) {
    1940             :     // ptrdiff_t probably doesn't fit in an int.
    1941           0 :     if (a.start < b.start) return -1;
    1942           0 :     if (a.start == b.start) return 0;
    1943             :     return 1;
    1944             :   }
    1945             : };
    1946             : 
    1947             : const AddressRange SplayTreeConfig::kNoKey = {0, 0};
    1948             : typedef SplayTree<SplayTreeConfig> CodeMap;
    1949             : 
    1950           0 : static CodeMap* GetCodeMap() {
    1951             :   static CodeMap* code_map = nullptr;
    1952           0 :   if (code_map == nullptr) code_map = new CodeMap();
    1953           0 :   return code_map;
    1954             : }
    1955             : 
    1956             : 
    1957             : static uint32_t HashCodeAddress(Address addr) {
    1958             :   static const uintptr_t kGoldenRatio = 2654435761u;
    1959           0 :   return static_cast<uint32_t>((addr >> kCodeAlignmentBits) * kGoldenRatio);
    1960             : }
    1961             : 
    1962           0 : static base::HashMap* GetLineMap() {
    1963             :   static base::HashMap* line_map = nullptr;
    1964           0 :   if (line_map == nullptr) {
    1965           0 :     line_map = new base::HashMap();
    1966             :   }
    1967           0 :   return line_map;
    1968             : }
    1969             : 
    1970             : 
    1971           0 : static void PutLineInfo(Address addr, LineInfo* info) {
    1972           0 :   base::HashMap* line_map = GetLineMap();
    1973             :   base::HashMap::Entry* e = line_map->LookupOrInsert(
    1974           0 :       reinterpret_cast<void*>(addr), HashCodeAddress(addr));
    1975           0 :   if (e->value != nullptr) delete static_cast<LineInfo*>(e->value);
    1976           0 :   e->value = info;
    1977           0 : }
    1978             : 
    1979             : 
    1980           0 : static LineInfo* GetLineInfo(Address addr) {
    1981           0 :   void* value = GetLineMap()->Remove(reinterpret_cast<void*>(addr),
    1982           0 :                                      HashCodeAddress(addr));
    1983           0 :   return static_cast<LineInfo*>(value);
    1984             : }
    1985             : 
    1986             : 
    1987           0 : static void AddUnwindInfo(CodeDescription* desc) {
    1988             : #if V8_TARGET_ARCH_X64
    1989           0 :   if (desc->is_function()) {
    1990             :     // To avoid propagating unwinding information through
    1991             :     // compilation pipeline we use an approximation.
    1992             :     // For most use cases this should not affect usability.
    1993             :     static const int kFramePointerPushOffset = 1;
    1994             :     static const int kFramePointerSetOffset = 4;
    1995             :     static const int kFramePointerPopOffset = -3;
    1996             : 
    1997             :     uintptr_t frame_pointer_push_address =
    1998           0 :         desc->CodeStart() + kFramePointerPushOffset;
    1999             : 
    2000             :     uintptr_t frame_pointer_set_address =
    2001           0 :         desc->CodeStart() + kFramePointerSetOffset;
    2002             : 
    2003             :     uintptr_t frame_pointer_pop_address =
    2004           0 :         desc->CodeEnd() + kFramePointerPopOffset;
    2005             : 
    2006             :     desc->SetStackStateStartAddress(CodeDescription::POST_RBP_PUSH,
    2007             :                                     frame_pointer_push_address);
    2008             :     desc->SetStackStateStartAddress(CodeDescription::POST_RBP_SET,
    2009             :                                     frame_pointer_set_address);
    2010             :     desc->SetStackStateStartAddress(CodeDescription::POST_RBP_POP,
    2011             :                                     frame_pointer_pop_address);
    2012             :   } else {
    2013             :     desc->SetStackStateStartAddress(CodeDescription::POST_RBP_PUSH,
    2014             :                                     desc->CodeStart());
    2015             :     desc->SetStackStateStartAddress(CodeDescription::POST_RBP_SET,
    2016             :                                     desc->CodeStart());
    2017             :     desc->SetStackStateStartAddress(CodeDescription::POST_RBP_POP,
    2018             :                                     desc->CodeEnd());
    2019             :   }
    2020             : #endif  // V8_TARGET_ARCH_X64
    2021           0 : }
    2022             : 
    2023             : 
    2024             : static base::LazyMutex mutex = LAZY_MUTEX_INITIALIZER;
    2025             : 
    2026             : 
    2027             : // Remove entries from the splay tree that intersect the given address range,
    2028             : // and deregister them from GDB.
    2029           0 : static void RemoveJITCodeEntries(CodeMap* map, const AddressRange& range) {
    2030             :   DCHECK(range.start < range.end);
    2031             :   CodeMap::Locator cur;
    2032           0 :   if (map->FindGreatestLessThan(range, &cur) || map->FindLeast(&cur)) {
    2033             :     // Skip entries that are entirely less than the range of interest.
    2034           0 :     while (cur.key().end <= range.start) {
    2035             :       // CodeMap::FindLeastGreaterThan succeeds for entries whose key is greater
    2036             :       // than _or equal to_ the given key, so we have to advance our key to get
    2037             :       // the next one.
    2038             :       AddressRange new_key;
    2039           0 :       new_key.start = cur.key().end;
    2040           0 :       new_key.end = 0;
    2041           0 :       if (!map->FindLeastGreaterThan(new_key, &cur)) return;
    2042             :     }
    2043             :     // Evict intersecting ranges.
    2044           0 :     while (cur.key().start < range.end) {
    2045           0 :       AddressRange old_range = cur.key();
    2046           0 :       JITCodeEntry* old_entry = cur.value();
    2047             : 
    2048           0 :       UnregisterCodeEntry(old_entry);
    2049             :       DestroyCodeEntry(old_entry);
    2050             : 
    2051           0 :       CHECK(map->Remove(old_range));
    2052           0 :       if (!map->FindLeastGreaterThan(old_range, &cur)) return;
    2053             :     }
    2054             :   }
    2055             : }
    2056             : 
    2057             : 
    2058             : // Insert the entry into the splay tree and register it with GDB.
    2059           0 : static void AddJITCodeEntry(CodeMap* map, const AddressRange& range,
    2060             :                             JITCodeEntry* entry, bool dump_if_enabled,
    2061             :                             const char* name_hint) {
    2062             : #if defined(DEBUG) && !V8_OS_WIN
    2063             :   static int file_num = 0;
    2064             :   if (FLAG_gdbjit_dump && dump_if_enabled) {
    2065             :     static const int kMaxFileNameSize = 64;
    2066             :     char file_name[64];
    2067             : 
    2068             :     SNPrintF(Vector<char>(file_name, kMaxFileNameSize), "/tmp/elfdump%s%d.o",
    2069             :              (name_hint != nullptr) ? name_hint : "", file_num++);
    2070             :     WriteBytes(file_name, reinterpret_cast<byte*>(entry->symfile_addr_),
    2071             :                static_cast<int>(entry->symfile_size_));
    2072             :   }
    2073             : #endif
    2074             : 
    2075             :   CodeMap::Locator cur;
    2076           0 :   CHECK(map->Insert(range, &cur));
    2077             :   cur.set_value(entry);
    2078             : 
    2079           0 :   RegisterCodeEntry(entry);
    2080           0 : }
    2081             : 
    2082           0 : static void AddCode(const char* name, Code code, SharedFunctionInfo shared,
    2083             :                     LineInfo* lineinfo) {
    2084             :   DisallowHeapAllocation no_gc;
    2085             : 
    2086           0 :   CodeMap* code_map = GetCodeMap();
    2087             :   AddressRange range;
    2088           0 :   range.start = code->address();
    2089           0 :   range.end = code->address() + code->CodeSize();
    2090           0 :   RemoveJITCodeEntries(code_map, range);
    2091             : 
    2092             :   CodeDescription code_desc(name, code, shared, lineinfo);
    2093             : 
    2094           0 :   if (!FLAG_gdbjit_full && !code_desc.IsLineInfoAvailable()) {
    2095           0 :     delete lineinfo;
    2096           0 :     return;
    2097             :   }
    2098             : 
    2099           0 :   AddUnwindInfo(&code_desc);
    2100             :   Isolate* isolate = code->GetIsolate();
    2101           0 :   JITCodeEntry* entry = CreateELFObject(&code_desc, isolate);
    2102             : 
    2103           0 :   delete lineinfo;
    2104             : 
    2105             :   const char* name_hint = nullptr;
    2106             :   bool should_dump = false;
    2107             :   if (FLAG_gdbjit_dump) {
    2108             :     if (strlen(FLAG_gdbjit_dump_filter) == 0) {
    2109             :       name_hint = name;
    2110             :       should_dump = true;
    2111             :     } else if (name != nullptr) {
    2112             :       name_hint = strstr(name, FLAG_gdbjit_dump_filter);
    2113             :       should_dump = (name_hint != nullptr);
    2114             :     }
    2115             :   }
    2116           0 :   AddJITCodeEntry(code_map, range, entry, should_dump, name_hint);
    2117             : }
    2118             : 
    2119           0 : void EventHandler(const v8::JitCodeEvent* event) {
    2120           0 :   if (!FLAG_gdbjit) return;
    2121           0 :   if (event->code_type != v8::JitCodeEvent::JIT_CODE) return;
    2122             :   base::MutexGuard lock_guard(mutex.Pointer());
    2123           0 :   switch (event->type) {
    2124             :     case v8::JitCodeEvent::CODE_ADDED: {
    2125           0 :       Address addr = reinterpret_cast<Address>(event->code_start);
    2126           0 :       Isolate* isolate = reinterpret_cast<Isolate*>(event->isolate);
    2127           0 :       Code code = isolate->heap()->GcSafeFindCodeForInnerPointer(addr);
    2128           0 :       LineInfo* lineinfo = GetLineInfo(addr);
    2129             :       EmbeddedVector<char, 256> buffer;
    2130             :       StringBuilder builder(buffer.start(), buffer.length());
    2131           0 :       builder.AddSubstring(event->name.str, static_cast<int>(event->name.len));
    2132             :       // It's called UnboundScript in the API but it's a SharedFunctionInfo.
    2133             :       SharedFunctionInfo shared = event->script.IsEmpty()
    2134             :                                       ? SharedFunctionInfo()
    2135           0 :                                       : *Utils::OpenHandle(*event->script);
    2136           0 :       AddCode(builder.Finalize(), code, shared, lineinfo);
    2137             :       break;
    2138             :     }
    2139             :     case v8::JitCodeEvent::CODE_MOVED:
    2140             :       // Enabling the GDB JIT interface should disable code compaction.
    2141           0 :       UNREACHABLE();
    2142             :       break;
    2143             :     case v8::JitCodeEvent::CODE_REMOVED:
    2144             :       // Do nothing.  Instead, adding code causes eviction of any entry whose
    2145             :       // address range intersects the address range of the added code.
    2146             :       break;
    2147             :     case v8::JitCodeEvent::CODE_ADD_LINE_POS_INFO: {
    2148           0 :       LineInfo* line_info = reinterpret_cast<LineInfo*>(event->user_data);
    2149             :       line_info->SetPosition(static_cast<intptr_t>(event->line_info.offset),
    2150             :                              static_cast<int>(event->line_info.pos),
    2151             :                              event->line_info.position_type ==
    2152           0 :                                  v8::JitCodeEvent::STATEMENT_POSITION);
    2153             :       break;
    2154             :     }
    2155             :     case v8::JitCodeEvent::CODE_START_LINE_INFO_RECORDING: {
    2156             :       v8::JitCodeEvent* mutable_event = const_cast<v8::JitCodeEvent*>(event);
    2157           0 :       mutable_event->user_data = new LineInfo();
    2158           0 :       break;
    2159             :     }
    2160             :     case v8::JitCodeEvent::CODE_END_LINE_INFO_RECORDING: {
    2161           0 :       LineInfo* line_info = reinterpret_cast<LineInfo*>(event->user_data);
    2162           0 :       PutLineInfo(reinterpret_cast<Address>(event->code_start), line_info);
    2163           0 :       break;
    2164             :     }
    2165             :   }
    2166             : }
    2167             : #endif
    2168             : }  // namespace GDBJITInterface
    2169             : }  // namespace internal
    2170      178779 : }  // namespace v8

Generated by: LCOV version 1.10