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

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

Generated by: LCOV version 1.10