LCOV - code coverage report
Current view: top level - src - gdb-jit.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 1 592 0.2 %
Date: 2019-04-18 Functions: 1 85 1.2 %

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

Generated by: LCOV version 1.10