LCOV - code coverage report
Current view: top level - src - gdb-jit.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 0 618 0.0 %
Date: 2017-04-26 Functions: 0 96 0.0 %

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

Generated by: LCOV version 1.10