LCOV - code coverage report
Current view: top level - src - gdb-jit.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 0 624 0.0 %
Date: 2017-10-20 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             : #include <vector>
       9             : 
      10             : #include "src/api.h"
      11             : #include "src/base/bits.h"
      12             : #include "src/base/platform/platform.h"
      13             : #include "src/bootstrapper.h"
      14             : #include "src/frames-inl.h"
      15             : #include "src/frames.h"
      16             : #include "src/global-handles.h"
      17             : #include "src/messages.h"
      18             : #include "src/objects.h"
      19             : #include "src/ostreams.h"
      20             : #include "src/snapshot/natives.h"
      21             : #include "src/splay-tree-inl.h"
      22             : 
      23             : namespace v8 {
      24             : namespace internal {
      25             : namespace GDBJITInterface {
      26             : 
      27             : #ifdef ENABLE_GDB_JIT_INTERFACE
      28             : 
      29             : #ifdef __APPLE__
      30             : #define __MACH_O
      31             : class MachO;
      32             : class MachOSection;
      33             : typedef MachO DebugObject;
      34             : typedef MachOSection DebugSection;
      35             : #else
      36             : #define __ELF
      37             : class ELF;
      38             : class ELFSection;
      39             : typedef ELF DebugObject;
      40             : typedef ELFSection DebugSection;
      41             : #endif
      42             : 
      43             : class Writer BASE_EMBEDDED {
      44             :  public:
      45             :   explicit Writer(DebugObject* debug_object)
      46             :       : debug_object_(debug_object),
      47             :         position_(0),
      48             :         capacity_(1024),
      49           0 :         buffer_(reinterpret_cast<byte*>(malloc(capacity_))) {
      50             :   }
      51             : 
      52             :   ~Writer() {
      53           0 :     free(buffer_);
      54             :   }
      55             : 
      56             :   uintptr_t position() const {
      57             :     return position_;
      58             :   }
      59             : 
      60             :   template<typename T>
      61             :   class Slot {
      62             :    public:
      63             :     Slot(Writer* w, uintptr_t offset) : w_(w), offset_(offset) { }
      64             : 
      65             :     T* operator-> () {
      66           0 :       return w_->RawSlotAt<T>(offset_);
      67             :     }
      68             : 
      69             :     void set(const T& value) {
      70           0 :       *w_->RawSlotAt<T>(offset_) = value;
      71             :     }
      72             : 
      73             :     Slot<T> at(int i) {
      74           0 :       return Slot<T>(w_, offset_ + sizeof(T) * i);
      75             :     }
      76             : 
      77             :    private:
      78             :     Writer* w_;
      79             :     uintptr_t offset_;
      80             :   };
      81             : 
      82             :   template<typename T>
      83           0 :   void Write(const T& val) {
      84           0 :     Ensure(position_ + sizeof(T));
      85           0 :     *RawSlotAt<T>(position_) = val;
      86           0 :     position_ += sizeof(T);
      87           0 :   }
      88             : 
      89             :   template<typename T>
      90             :   Slot<T> SlotAt(uintptr_t offset) {
      91           0 :     Ensure(offset + sizeof(T));
      92             :     return Slot<T>(this, offset);
      93             :   }
      94             : 
      95             :   template<typename T>
      96             :   Slot<T> CreateSlotHere() {
      97           0 :     return CreateSlotsHere<T>(1);
      98             :   }
      99             : 
     100             :   template<typename T>
     101           0 :   Slot<T> CreateSlotsHere(uint32_t count) {
     102           0 :     uintptr_t slot_position = position_;
     103           0 :     position_ += sizeof(T) * count;
     104           0 :     Ensure(position_);
     105           0 :     return SlotAt<T>(slot_position);
     106             :   }
     107             : 
     108           0 :   void Ensure(uintptr_t pos) {
     109           0 :     if (capacity_ < pos) {
     110           0 :       while (capacity_ < pos) capacity_ *= 2;
     111           0 :       buffer_ = reinterpret_cast<byte*>(realloc(buffer_, capacity_));
     112             :     }
     113           0 :   }
     114             : 
     115             :   DebugObject* debug_object() { return debug_object_; }
     116             : 
     117             :   byte* buffer() { return buffer_; }
     118             : 
     119           0 :   void Align(uintptr_t align) {
     120           0 :     uintptr_t delta = position_ % align;
     121           0 :     if (delta == 0) return;
     122           0 :     uintptr_t padding = align - delta;
     123           0 :     Ensure(position_ += padding);
     124             :     DCHECK_EQ(position_ % align, 0);
     125             :   }
     126             : 
     127           0 :   void WriteULEB128(uintptr_t value) {
     128           0 :     do {
     129           0 :       uint8_t byte = value & 0x7F;
     130           0 :       value >>= 7;
     131           0 :       if (value != 0) byte |= 0x80;
     132           0 :       Write<uint8_t>(byte);
     133             :     } while (value != 0);
     134           0 :   }
     135             : 
     136           0 :   void WriteSLEB128(intptr_t value) {
     137             :     bool more = true;
     138           0 :     while (more) {
     139           0 :       int8_t byte = value & 0x7F;
     140           0 :       bool byte_sign = byte & 0x40;
     141           0 :       value >>= 7;
     142             : 
     143           0 :       if ((value == 0 && !byte_sign) || (value == -1 && byte_sign)) {
     144             :         more = false;
     145             :       } else {
     146           0 :         byte |= 0x80;
     147             :       }
     148             : 
     149           0 :       Write<int8_t>(byte);
     150             :     }
     151           0 :   }
     152             : 
     153             :   void WriteString(const char* str) {
     154           0 :     do {
     155           0 :       Write<char>(*str);
     156             :     } while (*str++);
     157             :   }
     158             : 
     159             :  private:
     160             :   template<typename T> friend class Slot;
     161             : 
     162             :   template<typename T>
     163             :   T* RawSlotAt(uintptr_t offset) {
     164             :     DCHECK(offset < capacity_ && offset + sizeof(T) <= capacity_);
     165           0 :     return reinterpret_cast<T*>(&buffer_[offset]);
     166             :   }
     167             : 
     168             :   DebugObject* debug_object_;
     169             :   uintptr_t position_;
     170             :   uintptr_t capacity_;
     171             :   byte* buffer_;
     172             : };
     173             : 
     174             : class ELFStringTable;
     175             : 
     176             : template<typename THeader>
     177           0 : class DebugSectionBase : public ZoneObject {
     178             :  public:
     179           0 :   virtual ~DebugSectionBase() { }
     180             : 
     181           0 :   virtual void WriteBody(Writer::Slot<THeader> header, Writer* writer) {
     182             :     uintptr_t start = writer->position();
     183           0 :     if (WriteBodyInternal(writer)) {
     184             :       uintptr_t end = writer->position();
     185           0 :       header->offset = static_cast<uint32_t>(start);
     186             : #if defined(__MACH_O)
     187             :       header->addr = 0;
     188             : #endif
     189           0 :       header->size = end - start;
     190             :     }
     191           0 :   }
     192             : 
     193           0 :   virtual bool WriteBodyInternal(Writer* writer) {
     194           0 :     return false;
     195             :   }
     196             : 
     197             :   typedef THeader Header;
     198             : };
     199             : 
     200             : 
     201             : struct MachOSectionHeader {
     202             :   char sectname[16];
     203             :   char segname[16];
     204             : #if V8_TARGET_ARCH_IA32
     205             :   uint32_t addr;
     206             :   uint32_t size;
     207             : #else
     208             :   uint64_t addr;
     209             :   uint64_t size;
     210             : #endif
     211             :   uint32_t offset;
     212             :   uint32_t align;
     213             :   uint32_t reloff;
     214             :   uint32_t nreloc;
     215             :   uint32_t flags;
     216             :   uint32_t reserved1;
     217             :   uint32_t reserved2;
     218             : };
     219             : 
     220             : 
     221             : class MachOSection : public DebugSectionBase<MachOSectionHeader> {
     222             :  public:
     223             :   enum Type {
     224             :     S_REGULAR = 0x0u,
     225             :     S_ATTR_COALESCED = 0xbu,
     226             :     S_ATTR_SOME_INSTRUCTIONS = 0x400u,
     227             :     S_ATTR_DEBUG = 0x02000000u,
     228             :     S_ATTR_PURE_INSTRUCTIONS = 0x80000000u
     229             :   };
     230             : 
     231             :   MachOSection(const char* name, const char* segment, uint32_t align,
     232             :                uint32_t flags)
     233             :       : name_(name), segment_(segment), align_(align), flags_(flags) {
     234             :     if (align_ != 0) {
     235             :       DCHECK(base::bits::IsPowerOfTwo(align));
     236             :       align_ = WhichPowerOf2(align_);
     237             :     }
     238             :   }
     239             : 
     240           0 :   virtual ~MachOSection() { }
     241             : 
     242           0 :   virtual void PopulateHeader(Writer::Slot<Header> header) {
     243           0 :     header->addr = 0;
     244           0 :     header->size = 0;
     245           0 :     header->offset = 0;
     246           0 :     header->align = align_;
     247           0 :     header->reloff = 0;
     248           0 :     header->nreloc = 0;
     249           0 :     header->flags = flags_;
     250           0 :     header->reserved1 = 0;
     251           0 :     header->reserved2 = 0;
     252           0 :     memset(header->sectname, 0, sizeof(header->sectname));
     253           0 :     memset(header->segname, 0, sizeof(header->segname));
     254             :     DCHECK(strlen(name_) < sizeof(header->sectname));
     255             :     DCHECK(strlen(segment_) < sizeof(header->segname));
     256           0 :     strncpy(header->sectname, name_, sizeof(header->sectname));
     257           0 :     strncpy(header->segname, segment_, sizeof(header->segname));
     258           0 :   }
     259             : 
     260             :  private:
     261             :   const char* name_;
     262             :   const char* segment_;
     263             :   uint32_t align_;
     264             :   uint32_t flags_;
     265             : };
     266             : 
     267             : 
     268             : struct ELFSectionHeader {
     269             :   uint32_t name;
     270             :   uint32_t type;
     271             :   uintptr_t flags;
     272             :   uintptr_t address;
     273             :   uintptr_t offset;
     274             :   uintptr_t size;
     275             :   uint32_t link;
     276             :   uint32_t info;
     277             :   uintptr_t alignment;
     278             :   uintptr_t entry_size;
     279             : };
     280             : 
     281             : 
     282             : #if defined(__ELF)
     283             : class ELFSection : public DebugSectionBase<ELFSectionHeader> {
     284             :  public:
     285             :   enum Type {
     286             :     TYPE_NULL = 0,
     287             :     TYPE_PROGBITS = 1,
     288             :     TYPE_SYMTAB = 2,
     289             :     TYPE_STRTAB = 3,
     290             :     TYPE_RELA = 4,
     291             :     TYPE_HASH = 5,
     292             :     TYPE_DYNAMIC = 6,
     293             :     TYPE_NOTE = 7,
     294             :     TYPE_NOBITS = 8,
     295             :     TYPE_REL = 9,
     296             :     TYPE_SHLIB = 10,
     297             :     TYPE_DYNSYM = 11,
     298             :     TYPE_LOPROC = 0x70000000,
     299             :     TYPE_X86_64_UNWIND = 0x70000001,
     300             :     TYPE_HIPROC = 0x7fffffff,
     301             :     TYPE_LOUSER = 0x80000000,
     302             :     TYPE_HIUSER = 0xffffffff
     303             :   };
     304             : 
     305             :   enum Flags {
     306             :     FLAG_WRITE = 1,
     307             :     FLAG_ALLOC = 2,
     308             :     FLAG_EXEC = 4
     309             :   };
     310             : 
     311             :   enum SpecialIndexes {
     312             :     INDEX_ABSOLUTE = 0xfff1
     313             :   };
     314             : 
     315             :   ELFSection(const char* name, Type type, uintptr_t align)
     316           0 :       : name_(name), type_(type), align_(align) { }
     317             : 
     318           0 :   virtual ~ELFSection() { }
     319             : 
     320             :   void PopulateHeader(Writer::Slot<Header> header, ELFStringTable* strtab);
     321             : 
     322           0 :   virtual void WriteBody(Writer::Slot<Header> header, Writer* w) {
     323             :     uintptr_t start = w->position();
     324           0 :     if (WriteBodyInternal(w)) {
     325             :       uintptr_t end = w->position();
     326           0 :       header->offset = start;
     327           0 :       header->size = end - start;
     328             :     }
     329           0 :   }
     330             : 
     331           0 :   virtual bool WriteBodyInternal(Writer* w) {
     332           0 :     return false;
     333             :   }
     334             : 
     335             :   uint16_t index() const { return index_; }
     336           0 :   void set_index(uint16_t index) { index_ = index; }
     337             : 
     338             :  protected:
     339           0 :   virtual void PopulateHeader(Writer::Slot<Header> header) {
     340           0 :     header->flags = 0;
     341           0 :     header->address = 0;
     342           0 :     header->offset = 0;
     343           0 :     header->size = 0;
     344           0 :     header->link = 0;
     345           0 :     header->info = 0;
     346           0 :     header->entry_size = 0;
     347           0 :   }
     348             : 
     349             :  private:
     350             :   const char* name_;
     351             :   Type type_;
     352             :   uintptr_t align_;
     353             :   uint16_t index_;
     354             : };
     355             : #endif  // defined(__ELF)
     356             : 
     357             : 
     358             : #if defined(__MACH_O)
     359             : class MachOTextSection : public MachOSection {
     360             :  public:
     361             :   MachOTextSection(uint32_t align, uintptr_t addr, uintptr_t size)
     362             :       : MachOSection("__text", "__TEXT", align,
     363             :                      MachOSection::S_REGULAR |
     364             :                          MachOSection::S_ATTR_SOME_INSTRUCTIONS |
     365             :                          MachOSection::S_ATTR_PURE_INSTRUCTIONS),
     366             :         addr_(addr),
     367             :         size_(size) {}
     368             : 
     369             :  protected:
     370             :   virtual void PopulateHeader(Writer::Slot<Header> header) {
     371             :     MachOSection::PopulateHeader(header);
     372             :     header->addr = addr_;
     373             :     header->size = size_;
     374             :   }
     375             : 
     376             :  private:
     377             :   uintptr_t addr_;
     378             :   uintptr_t size_;
     379             : };
     380             : #endif  // defined(__MACH_O)
     381             : 
     382             : 
     383             : #if defined(__ELF)
     384           0 : class FullHeaderELFSection : public ELFSection {
     385             :  public:
     386             :   FullHeaderELFSection(const char* name,
     387             :                        Type type,
     388             :                        uintptr_t align,
     389             :                        uintptr_t addr,
     390             :                        uintptr_t offset,
     391             :                        uintptr_t size,
     392             :                        uintptr_t flags)
     393             :       : ELFSection(name, type, align),
     394             :         addr_(addr),
     395             :         offset_(offset),
     396             :         size_(size),
     397           0 :         flags_(flags) { }
     398             : 
     399             :  protected:
     400           0 :   virtual void PopulateHeader(Writer::Slot<Header> header) {
     401           0 :     ELFSection::PopulateHeader(header);
     402           0 :     header->address = addr_;
     403           0 :     header->offset = offset_;
     404           0 :     header->size = size_;
     405           0 :     header->flags = flags_;
     406           0 :   }
     407             : 
     408             :  private:
     409             :   uintptr_t addr_;
     410             :   uintptr_t offset_;
     411             :   uintptr_t size_;
     412             :   uintptr_t flags_;
     413             : };
     414             : 
     415             : 
     416           0 : class ELFStringTable : public ELFSection {
     417             :  public:
     418             :   explicit ELFStringTable(const char* name)
     419             :       : ELFSection(name, TYPE_STRTAB, 1),
     420             :         writer_(nullptr),
     421             :         offset_(0),
     422           0 :         size_(0) {}
     423             : 
     424             :   uintptr_t Add(const char* str) {
     425           0 :     if (*str == '\0') return 0;
     426             : 
     427           0 :     uintptr_t offset = size_;
     428           0 :     WriteString(str);
     429             :     return offset;
     430             :   }
     431             : 
     432             :   void AttachWriter(Writer* w) {
     433           0 :     writer_ = w;
     434           0 :     offset_ = writer_->position();
     435             : 
     436             :     // First entry in the string table should be an empty string.
     437           0 :     WriteString("");
     438             :   }
     439             : 
     440           0 :   void DetachWriter() { writer_ = nullptr; }
     441             : 
     442           0 :   virtual void WriteBody(Writer::Slot<Header> header, Writer* w) {
     443             :     DCHECK_NULL(writer_);
     444           0 :     header->offset = offset_;
     445           0 :     header->size = size_;
     446           0 :   }
     447             : 
     448             :  private:
     449           0 :   void WriteString(const char* str) {
     450             :     uintptr_t written = 0;
     451           0 :     do {
     452           0 :       writer_->Write(*str);
     453           0 :       written++;
     454             :     } while (*str++);
     455           0 :     size_ += written;
     456           0 :   }
     457             : 
     458             :   Writer* writer_;
     459             : 
     460             :   uintptr_t offset_;
     461             :   uintptr_t size_;
     462             : };
     463             : 
     464             : 
     465           0 : void ELFSection::PopulateHeader(Writer::Slot<ELFSection::Header> header,
     466             :                                 ELFStringTable* strtab) {
     467           0 :   header->name = static_cast<uint32_t>(strtab->Add(name_));
     468           0 :   header->type = type_;
     469           0 :   header->alignment = align_;
     470           0 :   PopulateHeader(header);
     471           0 : }
     472             : #endif  // defined(__ELF)
     473             : 
     474             : 
     475             : #if defined(__MACH_O)
     476             : class MachO BASE_EMBEDDED {
     477             :  public:
     478             :   explicit MachO(Zone* zone) : zone_(zone), sections_(6, zone) { }
     479             : 
     480             :   uint32_t AddSection(MachOSection* section) {
     481             :     sections_.Add(section, zone_);
     482             :     return sections_.length() - 1;
     483             :   }
     484             : 
     485             :   void Write(Writer* w, uintptr_t code_start, uintptr_t code_size) {
     486             :     Writer::Slot<MachOHeader> header = WriteHeader(w);
     487             :     uintptr_t load_command_start = w->position();
     488             :     Writer::Slot<MachOSegmentCommand> cmd = WriteSegmentCommand(w,
     489             :                                                                 code_start,
     490             :                                                                 code_size);
     491             :     WriteSections(w, cmd, header, load_command_start);
     492             :   }
     493             : 
     494             :  private:
     495             :   struct MachOHeader {
     496             :     uint32_t magic;
     497             :     uint32_t cputype;
     498             :     uint32_t cpusubtype;
     499             :     uint32_t filetype;
     500             :     uint32_t ncmds;
     501             :     uint32_t sizeofcmds;
     502             :     uint32_t flags;
     503             : #if V8_TARGET_ARCH_X64
     504             :     uint32_t reserved;
     505             : #endif
     506             :   };
     507             : 
     508             :   struct MachOSegmentCommand {
     509             :     uint32_t cmd;
     510             :     uint32_t cmdsize;
     511             :     char segname[16];
     512             : #if V8_TARGET_ARCH_IA32
     513             :     uint32_t vmaddr;
     514             :     uint32_t vmsize;
     515             :     uint32_t fileoff;
     516             :     uint32_t filesize;
     517             : #else
     518             :     uint64_t vmaddr;
     519             :     uint64_t vmsize;
     520             :     uint64_t fileoff;
     521             :     uint64_t filesize;
     522             : #endif
     523             :     uint32_t maxprot;
     524             :     uint32_t initprot;
     525             :     uint32_t nsects;
     526             :     uint32_t flags;
     527             :   };
     528             : 
     529             :   enum MachOLoadCommandCmd {
     530             :     LC_SEGMENT_32 = 0x00000001u,
     531             :     LC_SEGMENT_64 = 0x00000019u
     532             :   };
     533             : 
     534             : 
     535             :   Writer::Slot<MachOHeader> WriteHeader(Writer* w) {
     536             :     DCHECK_EQ(w->position(), 0);
     537             :     Writer::Slot<MachOHeader> header = w->CreateSlotHere<MachOHeader>();
     538             : #if V8_TARGET_ARCH_IA32
     539             :     header->magic = 0xFEEDFACEu;
     540             :     header->cputype = 7;  // i386
     541             :     header->cpusubtype = 3;  // CPU_SUBTYPE_I386_ALL
     542             : #elif V8_TARGET_ARCH_X64
     543             :     header->magic = 0xFEEDFACFu;
     544             :     header->cputype = 7 | 0x01000000;  // i386 | 64-bit ABI
     545             :     header->cpusubtype = 3;  // CPU_SUBTYPE_I386_ALL
     546             :     header->reserved = 0;
     547             : #else
     548             : #error Unsupported target architecture.
     549             : #endif
     550             :     header->filetype = 0x1;  // MH_OBJECT
     551             :     header->ncmds = 1;
     552             :     header->sizeofcmds = 0;
     553             :     header->flags = 0;
     554             :     return header;
     555             :   }
     556             : 
     557             : 
     558             :   Writer::Slot<MachOSegmentCommand> WriteSegmentCommand(Writer* w,
     559             :                                                         uintptr_t code_start,
     560             :                                                         uintptr_t code_size) {
     561             :     Writer::Slot<MachOSegmentCommand> cmd =
     562             :         w->CreateSlotHere<MachOSegmentCommand>();
     563             : #if V8_TARGET_ARCH_IA32
     564             :     cmd->cmd = LC_SEGMENT_32;
     565             : #else
     566             :     cmd->cmd = LC_SEGMENT_64;
     567             : #endif
     568             :     cmd->vmaddr = code_start;
     569             :     cmd->vmsize = code_size;
     570             :     cmd->fileoff = 0;
     571             :     cmd->filesize = 0;
     572             :     cmd->maxprot = 7;
     573             :     cmd->initprot = 7;
     574             :     cmd->flags = 0;
     575             :     cmd->nsects = sections_.length();
     576             :     memset(cmd->segname, 0, 16);
     577             :     cmd->cmdsize = sizeof(MachOSegmentCommand) + sizeof(MachOSection::Header) *
     578             :         cmd->nsects;
     579             :     return cmd;
     580             :   }
     581             : 
     582             : 
     583             :   void WriteSections(Writer* w,
     584             :                      Writer::Slot<MachOSegmentCommand> cmd,
     585             :                      Writer::Slot<MachOHeader> header,
     586             :                      uintptr_t load_command_start) {
     587             :     Writer::Slot<MachOSection::Header> headers =
     588             :         w->CreateSlotsHere<MachOSection::Header>(sections_.length());
     589             :     cmd->fileoff = w->position();
     590             :     header->sizeofcmds =
     591             :         static_cast<uint32_t>(w->position() - load_command_start);
     592             :     for (int section = 0; section < sections_.length(); ++section) {
     593             :       sections_[section]->PopulateHeader(headers.at(section));
     594             :       sections_[section]->WriteBody(headers.at(section), w);
     595             :     }
     596             :     cmd->filesize = w->position() - (uintptr_t)cmd->fileoff;
     597             :   }
     598             : 
     599             :   Zone* zone_;
     600             :   ZoneList<MachOSection*> sections_;
     601             : };
     602             : #endif  // defined(__MACH_O)
     603             : 
     604             : 
     605             : #if defined(__ELF)
     606             : class ELF BASE_EMBEDDED {
     607             :  public:
     608           0 :   explicit ELF(Zone* zone) : zone_(zone), sections_(6, zone) {
     609           0 :     sections_.Add(new(zone) ELFSection("", ELFSection::TYPE_NULL, 0), zone);
     610           0 :     sections_.Add(new(zone) ELFStringTable(".shstrtab"), zone);
     611           0 :   }
     612             : 
     613           0 :   void Write(Writer* w) {
     614           0 :     WriteHeader(w);
     615           0 :     WriteSectionTable(w);
     616           0 :     WriteSections(w);
     617           0 :   }
     618             : 
     619             :   ELFSection* SectionAt(uint32_t index) {
     620           0 :     return sections_[index];
     621             :   }
     622             : 
     623           0 :   uint32_t AddSection(ELFSection* section) {
     624           0 :     sections_.Add(section, zone_);
     625           0 :     section->set_index(sections_.length() - 1);
     626           0 :     return sections_.length() - 1;
     627             :   }
     628             : 
     629             :  private:
     630             :   struct ELFHeader {
     631             :     uint8_t ident[16];
     632             :     uint16_t type;
     633             :     uint16_t machine;
     634             :     uint32_t version;
     635             :     uintptr_t entry;
     636             :     uintptr_t pht_offset;
     637             :     uintptr_t sht_offset;
     638             :     uint32_t flags;
     639             :     uint16_t header_size;
     640             :     uint16_t pht_entry_size;
     641             :     uint16_t pht_entry_num;
     642             :     uint16_t sht_entry_size;
     643             :     uint16_t sht_entry_num;
     644             :     uint16_t sht_strtab_index;
     645             :   };
     646             : 
     647             : 
     648           0 :   void WriteHeader(Writer* w) {
     649             :     DCHECK_EQ(w->position(), 0);
     650             :     Writer::Slot<ELFHeader> header = w->CreateSlotHere<ELFHeader>();
     651             : #if (V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_ARM || \
     652             :      (V8_TARGET_ARCH_X64 && V8_TARGET_ARCH_32_BIT))
     653             :     const uint8_t ident[16] =
     654             :         { 0x7f, 'E', 'L', 'F', 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0};
     655             : #elif(V8_TARGET_ARCH_X64 && V8_TARGET_ARCH_64_BIT) || \
     656             :     (V8_TARGET_ARCH_PPC64 && V8_TARGET_LITTLE_ENDIAN)
     657             :     const uint8_t ident[16] =
     658           0 :         { 0x7f, 'E', 'L', 'F', 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0};
     659             : #elif V8_TARGET_ARCH_PPC64 && V8_TARGET_BIG_ENDIAN && V8_OS_LINUX
     660             :     const uint8_t ident[16] = {0x7f, 'E', 'L', 'F', 2, 2, 1, 0,
     661             :                                0,    0,   0,   0,   0, 0, 0, 0};
     662             : #elif V8_TARGET_ARCH_S390X
     663             :     const uint8_t ident[16] = {0x7f, 'E', 'L', 'F', 2, 2, 1, 3,
     664             :                                0,    0,   0,   0,   0, 0, 0, 0};
     665             : #elif V8_TARGET_ARCH_S390
     666             :     const uint8_t ident[16] = {0x7f, 'E', 'L', 'F', 1, 2, 1, 3,
     667             :                                0,    0,   0,   0,   0, 0, 0, 0};
     668             : #else
     669             : #error Unsupported target architecture.
     670             : #endif
     671           0 :     memcpy(header->ident, ident, 16);
     672           0 :     header->type = 1;
     673             : #if V8_TARGET_ARCH_IA32
     674             :     header->machine = 3;
     675             : #elif V8_TARGET_ARCH_X64
     676             :     // Processor identification value for x64 is 62 as defined in
     677             :     //    System V ABI, AMD64 Supplement
     678             :     //    http://www.x86-64.org/documentation/abi.pdf
     679           0 :     header->machine = 62;
     680             : #elif V8_TARGET_ARCH_ARM
     681             :     // Set to EM_ARM, defined as 40, in "ARM ELF File Format" at
     682             :     // infocenter.arm.com/help/topic/com.arm.doc.dui0101a/DUI0101A_Elf.pdf
     683             :     header->machine = 40;
     684             : #elif V8_TARGET_ARCH_PPC64 && V8_OS_LINUX
     685             :     // Set to EM_PPC64, defined as 21, in Power ABI,
     686             :     // Join the next 4 lines, omitting the spaces and double-slashes.
     687             :     // https://www-03.ibm.com/technologyconnect/tgcm/TGCMFileServlet.wss/
     688             :     // ABI64BitOpenPOWERv1.1_16July2015_pub.pdf?
     689             :     // id=B81AEC1A37F5DAF185257C3E004E8845&linkid=1n0000&c_t=
     690             :     // c9xw7v5dzsj7gt1ifgf4cjbcnskqptmr
     691             :     header->machine = 21;
     692             : #elif V8_TARGET_ARCH_S390
     693             :     // Processor identification value is 22 (EM_S390) as defined in the ABI:
     694             :     // http://refspecs.linuxbase.org/ELF/zSeries/lzsabi0_s390.html#AEN1691
     695             :     // http://refspecs.linuxbase.org/ELF/zSeries/lzsabi0_zSeries.html#AEN1599
     696             :     header->machine = 22;
     697             : #else
     698             : #error Unsupported target architecture.
     699             : #endif
     700           0 :     header->version = 1;
     701           0 :     header->entry = 0;
     702           0 :     header->pht_offset = 0;
     703           0 :     header->sht_offset = sizeof(ELFHeader);  // Section table follows header.
     704           0 :     header->flags = 0;
     705           0 :     header->header_size = sizeof(ELFHeader);
     706           0 :     header->pht_entry_size = 0;
     707           0 :     header->pht_entry_num = 0;
     708           0 :     header->sht_entry_size = sizeof(ELFSection::Header);
     709           0 :     header->sht_entry_num = sections_.length();
     710           0 :     header->sht_strtab_index = 1;
     711           0 :   }
     712             : 
     713           0 :   void WriteSectionTable(Writer* w) {
     714             :     // Section headers table immediately follows file header.
     715             :     DCHECK(w->position() == sizeof(ELFHeader));
     716             : 
     717             :     Writer::Slot<ELFSection::Header> headers =
     718           0 :         w->CreateSlotsHere<ELFSection::Header>(sections_.length());
     719             : 
     720             :     // String table for section table is the first section.
     721             :     ELFStringTable* strtab = static_cast<ELFStringTable*>(SectionAt(1));
     722             :     strtab->AttachWriter(w);
     723           0 :     for (int i = 0, length = sections_.length();
     724             :          i < length;
     725             :          i++) {
     726           0 :       sections_[i]->PopulateHeader(headers.at(i), strtab);
     727             :     }
     728             :     strtab->DetachWriter();
     729           0 :   }
     730             : 
     731             :   int SectionHeaderPosition(uint32_t section_index) {
     732             :     return sizeof(ELFHeader) + sizeof(ELFSection::Header) * section_index;
     733             :   }
     734             : 
     735           0 :   void WriteSections(Writer* w) {
     736             :     Writer::Slot<ELFSection::Header> headers =
     737             :         w->SlotAt<ELFSection::Header>(sizeof(ELFHeader));
     738             : 
     739           0 :     for (int i = 0, length = sections_.length();
     740             :          i < length;
     741             :          i++) {
     742           0 :       sections_[i]->WriteBody(headers.at(i), w);
     743             :     }
     744           0 :   }
     745             : 
     746             :   Zone* zone_;
     747             :   ZoneList<ELFSection*> sections_;
     748             : };
     749             : 
     750             : 
     751             : class ELFSymbol BASE_EMBEDDED {
     752             :  public:
     753             :   enum Type {
     754             :     TYPE_NOTYPE = 0,
     755             :     TYPE_OBJECT = 1,
     756             :     TYPE_FUNC = 2,
     757             :     TYPE_SECTION = 3,
     758             :     TYPE_FILE = 4,
     759             :     TYPE_LOPROC = 13,
     760             :     TYPE_HIPROC = 15
     761             :   };
     762             : 
     763             :   enum Binding {
     764             :     BIND_LOCAL = 0,
     765             :     BIND_GLOBAL = 1,
     766             :     BIND_WEAK = 2,
     767             :     BIND_LOPROC = 13,
     768             :     BIND_HIPROC = 15
     769             :   };
     770             : 
     771             :   ELFSymbol(const char* name,
     772             :             uintptr_t value,
     773             :             uintptr_t size,
     774             :             Binding binding,
     775             :             Type type,
     776             :             uint16_t section)
     777             :       : name(name),
     778             :         value(value),
     779             :         size(size),
     780             :         info((binding << 4) | type),
     781             :         other(0),
     782           0 :         section(section) {
     783             :   }
     784             : 
     785             :   Binding binding() const {
     786           0 :     return static_cast<Binding>(info >> 4);
     787             :   }
     788             : #if (V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_ARM ||     \
     789             :      (V8_TARGET_ARCH_X64 && V8_TARGET_ARCH_32_BIT) || \
     790             :      (V8_TARGET_ARCH_S390 && V8_TARGET_ARCH_32_BIT))
     791             :   struct SerializedLayout {
     792             :     SerializedLayout(uint32_t name,
     793             :                      uintptr_t value,
     794             :                      uintptr_t size,
     795             :                      Binding binding,
     796             :                      Type type,
     797             :                      uint16_t section)
     798             :         : name(name),
     799             :           value(value),
     800             :           size(size),
     801             :           info((binding << 4) | type),
     802             :           other(0),
     803             :           section(section) {
     804             :     }
     805             : 
     806             :     uint32_t name;
     807             :     uintptr_t value;
     808             :     uintptr_t size;
     809             :     uint8_t info;
     810             :     uint8_t other;
     811             :     uint16_t section;
     812             :   };
     813             : #elif(V8_TARGET_ARCH_X64 && V8_TARGET_ARCH_64_BIT) || \
     814             :     (V8_TARGET_ARCH_PPC64 && V8_OS_LINUX) || V8_TARGET_ARCH_S390X
     815             :   struct SerializedLayout {
     816             :     SerializedLayout(uint32_t name,
     817             :                      uintptr_t value,
     818             :                      uintptr_t size,
     819             :                      Binding binding,
     820             :                      Type type,
     821             :                      uint16_t section)
     822             :         : name(name),
     823             :           info((binding << 4) | type),
     824             :           other(0),
     825             :           section(section),
     826             :           value(value),
     827             :           size(size) {
     828             :     }
     829             : 
     830             :     uint32_t name;
     831             :     uint8_t info;
     832             :     uint8_t other;
     833             :     uint16_t section;
     834             :     uintptr_t value;
     835             :     uintptr_t size;
     836             :   };
     837             : #endif
     838             : 
     839           0 :   void Write(Writer::Slot<SerializedLayout> s, ELFStringTable* t) {
     840             :     // Convert symbol names from strings to indexes in the string table.
     841           0 :     s->name = static_cast<uint32_t>(t->Add(name));
     842           0 :     s->value = value;
     843           0 :     s->size = size;
     844           0 :     s->info = info;
     845           0 :     s->other = other;
     846           0 :     s->section = section;
     847           0 :   }
     848             : 
     849             :  private:
     850             :   const char* name;
     851             :   uintptr_t value;
     852             :   uintptr_t size;
     853             :   uint8_t info;
     854             :   uint8_t other;
     855             :   uint16_t section;
     856             : };
     857             : 
     858             : 
     859           0 : class ELFSymbolTable : public ELFSection {
     860             :  public:
     861           0 :   ELFSymbolTable(const char* name, Zone* zone)
     862             :       : ELFSection(name, TYPE_SYMTAB, sizeof(uintptr_t)),
     863             :         locals_(1, zone),
     864           0 :         globals_(1, zone) {
     865           0 :   }
     866             : 
     867           0 :   virtual void WriteBody(Writer::Slot<Header> header, Writer* w) {
     868           0 :     w->Align(header->alignment);
     869           0 :     int total_symbols = locals_.length() + globals_.length() + 1;
     870           0 :     header->offset = w->position();
     871             : 
     872             :     Writer::Slot<ELFSymbol::SerializedLayout> symbols =
     873           0 :         w->CreateSlotsHere<ELFSymbol::SerializedLayout>(total_symbols);
     874             : 
     875           0 :     header->size = w->position() - header->offset;
     876             : 
     877             :     // String table for this symbol table should follow it in the section table.
     878             :     ELFStringTable* strtab =
     879           0 :         static_cast<ELFStringTable*>(w->debug_object()->SectionAt(index() + 1));
     880             :     strtab->AttachWriter(w);
     881             :     symbols.at(0).set(ELFSymbol::SerializedLayout(0,
     882             :                                                   0,
     883             :                                                   0,
     884             :                                                   ELFSymbol::BIND_LOCAL,
     885             :                                                   ELFSymbol::TYPE_NOTYPE,
     886             :                                                   0));
     887           0 :     WriteSymbolsList(&locals_, symbols.at(1), strtab);
     888           0 :     WriteSymbolsList(&globals_, symbols.at(locals_.length() + 1), strtab);
     889             :     strtab->DetachWriter();
     890           0 :   }
     891             : 
     892           0 :   void Add(const ELFSymbol& symbol, Zone* zone) {
     893           0 :     if (symbol.binding() == ELFSymbol::BIND_LOCAL) {
     894           0 :       locals_.Add(symbol, zone);
     895             :     } else {
     896           0 :       globals_.Add(symbol, zone);
     897             :     }
     898           0 :   }
     899             : 
     900             :  protected:
     901           0 :   virtual void PopulateHeader(Writer::Slot<Header> header) {
     902           0 :     ELFSection::PopulateHeader(header);
     903             :     // We are assuming that string table will follow symbol table.
     904           0 :     header->link = index() + 1;
     905           0 :     header->info = locals_.length() + 1;
     906           0 :     header->entry_size = sizeof(ELFSymbol::SerializedLayout);
     907           0 :   }
     908             : 
     909             :  private:
     910           0 :   void WriteSymbolsList(const ZoneList<ELFSymbol>* src,
     911             :                         Writer::Slot<ELFSymbol::SerializedLayout> dst,
     912             :                         ELFStringTable* strtab) {
     913           0 :     for (int i = 0, len = src->length();
     914             :          i < len;
     915             :          i++) {
     916           0 :       src->at(i).Write(dst.at(i), strtab);
     917             :     }
     918           0 :   }
     919             : 
     920             :   ZoneList<ELFSymbol> locals_;
     921             :   ZoneList<ELFSymbol> globals_;
     922             : };
     923             : #endif  // defined(__ELF)
     924             : 
     925             : 
     926             : class LineInfo : public Malloced {
     927             :  public:
     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             :   std::vector<PCInfo>* pc_info() { return &pc_info_; }
     942             : 
     943             :  private:
     944           0 :   void AddPCInfo(const PCInfo& pc_info) { pc_info_.push_back(pc_info); }
     945             : 
     946             :   std::vector<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::OPTIMIZED_FUNCTION;
     974             :   }
     975             : 
     976           0 :   bool has_scope_info() const { return shared_info_ != nullptr; }
     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_ != nullptr && 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_ != nullptr;
    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
    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_EQ(Context::MIN_CONTEXT_SLOTS, 4);
    1202             :       DCHECK_EQ(Context::CLOSURE_INDEX, 0);
    1203             :       DCHECK_EQ(Context::PREVIOUS_INDEX, 1);
    1204             :       DCHECK_EQ(Context::EXTENSION_INDEX, 2);
    1205             :       DCHECK_EQ(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 :     std::vector<LineInfo::PCInfo>* pc_info = desc_->lineinfo()->pc_info();
    1516           0 :     std::sort(pc_info->begin(), pc_info->end(), &ComparePCInfo);
    1517             : 
    1518           0 :     for (size_t i = 0; i < pc_info->size(); i++) {
    1519             :       LineInfo::PCInfo* info = &pc_info->at(i);
    1520             :       DCHECK(info->pc_ >= pc);
    1521             : 
    1522             :       // Reduce bloating in the debug line table by removing duplicate line
    1523             :       // entries (per DWARF2 standard).
    1524           0 :       intptr_t  new_line = desc_->GetScriptLineNumber(info->pos_);
    1525           0 :       if (new_line == line) {
    1526             :         continue;
    1527             :       }
    1528             : 
    1529             :       // Mark statement boundaries.  For a better debugging experience, mark
    1530             :       // the last pc address in the function as a statement (e.g. "}"), so that
    1531             :       // a user can see the result of the last line executed in the function,
    1532             :       // should control reach the end.
    1533           0 :       if ((i + 1) == pc_info->size()) {
    1534           0 :         if (!is_statement) {
    1535           0 :           w->Write<uint8_t>(DW_LNS_NEGATE_STMT);
    1536             :         }
    1537           0 :       } else if (is_statement != info->is_statement_) {
    1538           0 :         w->Write<uint8_t>(DW_LNS_NEGATE_STMT);
    1539           0 :         is_statement = !is_statement;
    1540             :       }
    1541             : 
    1542             :       // Generate special opcodes, if possible.  This results in more compact
    1543             :       // debug line tables.  See the DWARF 2.0 standard to learn more about
    1544             :       // special opcodes.
    1545           0 :       uintptr_t pc_diff = info->pc_ - pc;
    1546           0 :       intptr_t line_diff = new_line - line;
    1547             : 
    1548             :       // Compute special opcode (see DWARF 2.0 standard)
    1549             :       intptr_t special_opcode = (line_diff - line_base) +
    1550           0 :                                 (line_range * pc_diff) + opcode_base;
    1551             : 
    1552             :       // If special_opcode is less than or equal to 255, it can be used as a
    1553             :       // special opcode.  If line_diff is larger than the max line increment
    1554             :       // allowed for a special opcode, or if line_diff is less than the minimum
    1555             :       // line that can be added to the line register (i.e. line_base), then
    1556             :       // special_opcode can't be used.
    1557           0 :       if ((special_opcode >= opcode_base) && (special_opcode <= 255) &&
    1558           0 :           (line_diff <= max_line_incr) && (line_diff >= line_base)) {
    1559           0 :         w->Write<uint8_t>(special_opcode);
    1560             :       } else {
    1561           0 :         w->Write<uint8_t>(DW_LNS_ADVANCE_PC);
    1562           0 :         w->WriteSLEB128(pc_diff);
    1563           0 :         w->Write<uint8_t>(DW_LNS_ADVANCE_LINE);
    1564           0 :         w->WriteSLEB128(line_diff);
    1565           0 :         w->Write<uint8_t>(DW_LNS_COPY);
    1566             :       }
    1567             : 
    1568             :       // Increment the pc and line operands.
    1569           0 :       pc += pc_diff;
    1570             :       line += line_diff;
    1571             :     }
    1572             :     // Advance the pc to the end of the routine, since the end sequence opcode
    1573             :     // requires this.
    1574           0 :     w->Write<uint8_t>(DW_LNS_ADVANCE_PC);
    1575           0 :     w->WriteSLEB128(desc_->CodeSize() - pc);
    1576           0 :     WriteExtendedOpcode(w, DW_LNE_END_SEQUENCE, 0);
    1577           0 :     total_length.set(static_cast<uint32_t>(w->position() - start));
    1578           0 :     return true;
    1579             :   }
    1580             : 
    1581             :  private:
    1582           0 :   void WriteExtendedOpcode(Writer* w,
    1583             :                            DWARF2ExtendedOpcode op,
    1584             :                            size_t operands_size) {
    1585           0 :     w->Write<uint8_t>(0);
    1586           0 :     w->WriteULEB128(operands_size + 1);
    1587           0 :     w->Write<uint8_t>(op);
    1588           0 :   }
    1589             : 
    1590           0 :   static bool ComparePCInfo(const LineInfo::PCInfo& a,
    1591             :                             const LineInfo::PCInfo& b) {
    1592           0 :     if (a.pc_ == b.pc_) {
    1593           0 :       if (a.is_statement_ != b.is_statement_) {
    1594           0 :         return !b.is_statement_;
    1595             :       }
    1596             :       return false;
    1597             :     }
    1598           0 :     return a.pc_ < b.pc_;
    1599             :   }
    1600             : 
    1601             :   CodeDescription* desc_;
    1602             : };
    1603             : 
    1604             : 
    1605             : #if V8_TARGET_ARCH_X64
    1606             : 
    1607           0 : class UnwindInfoSection : public DebugSection {
    1608             :  public:
    1609             :   explicit UnwindInfoSection(CodeDescription* desc);
    1610             :   virtual bool WriteBodyInternal(Writer* w);
    1611             : 
    1612             :   int WriteCIE(Writer* w);
    1613             :   void WriteFDE(Writer* w, int);
    1614             : 
    1615             :   void WriteFDEStateOnEntry(Writer* w);
    1616             :   void WriteFDEStateAfterRBPPush(Writer* w);
    1617             :   void WriteFDEStateAfterRBPSet(Writer* w);
    1618             :   void WriteFDEStateAfterRBPPop(Writer* w);
    1619             : 
    1620             :   void WriteLength(Writer* w,
    1621             :                    Writer::Slot<uint32_t>* length_slot,
    1622             :                    int initial_position);
    1623             : 
    1624             :  private:
    1625             :   CodeDescription* desc_;
    1626             : 
    1627             :   // DWARF3 Specification, Table 7.23
    1628             :   enum CFIInstructions {
    1629             :     DW_CFA_ADVANCE_LOC = 0x40,
    1630             :     DW_CFA_OFFSET = 0x80,
    1631             :     DW_CFA_RESTORE = 0xC0,
    1632             :     DW_CFA_NOP = 0x00,
    1633             :     DW_CFA_SET_LOC = 0x01,
    1634             :     DW_CFA_ADVANCE_LOC1 = 0x02,
    1635             :     DW_CFA_ADVANCE_LOC2 = 0x03,
    1636             :     DW_CFA_ADVANCE_LOC4 = 0x04,
    1637             :     DW_CFA_OFFSET_EXTENDED = 0x05,
    1638             :     DW_CFA_RESTORE_EXTENDED = 0x06,
    1639             :     DW_CFA_UNDEFINED = 0x07,
    1640             :     DW_CFA_SAME_VALUE = 0x08,
    1641             :     DW_CFA_REGISTER = 0x09,
    1642             :     DW_CFA_REMEMBER_STATE = 0x0A,
    1643             :     DW_CFA_RESTORE_STATE = 0x0B,
    1644             :     DW_CFA_DEF_CFA = 0x0C,
    1645             :     DW_CFA_DEF_CFA_REGISTER = 0x0D,
    1646             :     DW_CFA_DEF_CFA_OFFSET = 0x0E,
    1647             : 
    1648             :     DW_CFA_DEF_CFA_EXPRESSION = 0x0F,
    1649             :     DW_CFA_EXPRESSION = 0x10,
    1650             :     DW_CFA_OFFSET_EXTENDED_SF = 0x11,
    1651             :     DW_CFA_DEF_CFA_SF = 0x12,
    1652             :     DW_CFA_DEF_CFA_OFFSET_SF = 0x13,
    1653             :     DW_CFA_VAL_OFFSET = 0x14,
    1654             :     DW_CFA_VAL_OFFSET_SF = 0x15,
    1655             :     DW_CFA_VAL_EXPRESSION = 0x16
    1656             :   };
    1657             : 
    1658             :   // System V ABI, AMD64 Supplement, Version 0.99.5, Figure 3.36
    1659             :   enum RegisterMapping {
    1660             :     // Only the relevant ones have been added to reduce clutter.
    1661             :     AMD64_RBP = 6,
    1662             :     AMD64_RSP = 7,
    1663             :     AMD64_RA = 16
    1664             :   };
    1665             : 
    1666             :   enum CFIConstants {
    1667             :     CIE_ID = 0,
    1668             :     CIE_VERSION = 1,
    1669             :     CODE_ALIGN_FACTOR = 1,
    1670             :     DATA_ALIGN_FACTOR = 1,
    1671             :     RETURN_ADDRESS_REGISTER = AMD64_RA
    1672             :   };
    1673             : };
    1674             : 
    1675             : 
    1676           0 : void UnwindInfoSection::WriteLength(Writer* w,
    1677             :                                     Writer::Slot<uint32_t>* length_slot,
    1678             :                                     int initial_position) {
    1679           0 :   uint32_t align = (w->position() - initial_position) % kPointerSize;
    1680             : 
    1681           0 :   if (align != 0) {
    1682           0 :     for (uint32_t i = 0; i < (kPointerSize - align); i++) {
    1683           0 :       w->Write<uint8_t>(DW_CFA_NOP);
    1684             :     }
    1685             :   }
    1686             : 
    1687             :   DCHECK_EQ((w->position() - initial_position) % kPointerSize, 0);
    1688           0 :   length_slot->set(static_cast<uint32_t>(w->position() - initial_position));
    1689           0 : }
    1690             : 
    1691             : 
    1692           0 : UnwindInfoSection::UnwindInfoSection(CodeDescription* desc)
    1693             : #ifdef __ELF
    1694             :     : ELFSection(".eh_frame", TYPE_X86_64_UNWIND, 1),
    1695             : #else
    1696             :     : MachOSection("__eh_frame", "__TEXT", sizeof(uintptr_t),
    1697             :                    MachOSection::S_REGULAR),
    1698             : #endif
    1699           0 :       desc_(desc) { }
    1700             : 
    1701           0 : int UnwindInfoSection::WriteCIE(Writer* w) {
    1702           0 :   Writer::Slot<uint32_t> cie_length_slot = w->CreateSlotHere<uint32_t>();
    1703             :   uint32_t cie_position = static_cast<uint32_t>(w->position());
    1704             : 
    1705             :   // Write out the CIE header. Currently no 'common instructions' are
    1706             :   // emitted onto the CIE; every FDE has its own set of instructions.
    1707             : 
    1708           0 :   w->Write<uint32_t>(CIE_ID);
    1709           0 :   w->Write<uint8_t>(CIE_VERSION);
    1710           0 :   w->Write<uint8_t>(0);  // Null augmentation string.
    1711           0 :   w->WriteSLEB128(CODE_ALIGN_FACTOR);
    1712           0 :   w->WriteSLEB128(DATA_ALIGN_FACTOR);
    1713           0 :   w->Write<uint8_t>(RETURN_ADDRESS_REGISTER);
    1714             : 
    1715           0 :   WriteLength(w, &cie_length_slot, cie_position);
    1716             : 
    1717           0 :   return cie_position;
    1718             : }
    1719             : 
    1720             : 
    1721           0 : void UnwindInfoSection::WriteFDE(Writer* w, int cie_position) {
    1722             :   // The only FDE for this function. The CFA is the current RBP.
    1723           0 :   Writer::Slot<uint32_t> fde_length_slot = w->CreateSlotHere<uint32_t>();
    1724           0 :   int fde_position = static_cast<uint32_t>(w->position());
    1725           0 :   w->Write<int32_t>(fde_position - cie_position + 4);
    1726             : 
    1727           0 :   w->Write<uintptr_t>(desc_->CodeStart());
    1728           0 :   w->Write<uintptr_t>(desc_->CodeSize());
    1729             : 
    1730           0 :   WriteFDEStateOnEntry(w);
    1731           0 :   WriteFDEStateAfterRBPPush(w);
    1732           0 :   WriteFDEStateAfterRBPSet(w);
    1733           0 :   WriteFDEStateAfterRBPPop(w);
    1734             : 
    1735           0 :   WriteLength(w, &fde_length_slot, fde_position);
    1736           0 : }
    1737             : 
    1738             : 
    1739           0 : void UnwindInfoSection::WriteFDEStateOnEntry(Writer* w) {
    1740             :   // The first state, just after the control has been transferred to the the
    1741             :   // function.
    1742             : 
    1743             :   // RBP for this function will be the value of RSP after pushing the RBP
    1744             :   // for the previous function. The previous RBP has not been pushed yet.
    1745           0 :   w->Write<uint8_t>(DW_CFA_DEF_CFA_SF);
    1746           0 :   w->WriteULEB128(AMD64_RSP);
    1747           0 :   w->WriteSLEB128(-kPointerSize);
    1748             : 
    1749             :   // The RA is stored at location CFA + kCallerPCOffset. This is an invariant,
    1750             :   // and hence omitted from the next states.
    1751           0 :   w->Write<uint8_t>(DW_CFA_OFFSET_EXTENDED);
    1752           0 :   w->WriteULEB128(AMD64_RA);
    1753           0 :   w->WriteSLEB128(StandardFrameConstants::kCallerPCOffset);
    1754             : 
    1755             :   // The RBP of the previous function is still in RBP.
    1756           0 :   w->Write<uint8_t>(DW_CFA_SAME_VALUE);
    1757           0 :   w->WriteULEB128(AMD64_RBP);
    1758             : 
    1759             :   // Last location described by this entry.
    1760           0 :   w->Write<uint8_t>(DW_CFA_SET_LOC);
    1761             :   w->Write<uint64_t>(
    1762           0 :       desc_->GetStackStateStartAddress(CodeDescription::POST_RBP_PUSH));
    1763           0 : }
    1764             : 
    1765             : 
    1766           0 : void UnwindInfoSection::WriteFDEStateAfterRBPPush(Writer* w) {
    1767             :   // The second state, just after RBP has been pushed.
    1768             : 
    1769             :   // RBP / CFA for this function is now the current RSP, so just set the
    1770             :   // offset from the previous rule (from -8) to 0.
    1771           0 :   w->Write<uint8_t>(DW_CFA_DEF_CFA_OFFSET);
    1772           0 :   w->WriteULEB128(0);
    1773             : 
    1774             :   // The previous RBP is stored at CFA + kCallerFPOffset. This is an invariant
    1775             :   // in this and the next state, and hence omitted in the next state.
    1776           0 :   w->Write<uint8_t>(DW_CFA_OFFSET_EXTENDED);
    1777           0 :   w->WriteULEB128(AMD64_RBP);
    1778           0 :   w->WriteSLEB128(StandardFrameConstants::kCallerFPOffset);
    1779             : 
    1780             :   // Last location described by this entry.
    1781           0 :   w->Write<uint8_t>(DW_CFA_SET_LOC);
    1782             :   w->Write<uint64_t>(
    1783           0 :       desc_->GetStackStateStartAddress(CodeDescription::POST_RBP_SET));
    1784           0 : }
    1785             : 
    1786             : 
    1787           0 : void UnwindInfoSection::WriteFDEStateAfterRBPSet(Writer* w) {
    1788             :   // The third state, after the RBP has been set.
    1789             : 
    1790             :   // The CFA can now directly be set to RBP.
    1791           0 :   w->Write<uint8_t>(DW_CFA_DEF_CFA);
    1792           0 :   w->WriteULEB128(AMD64_RBP);
    1793           0 :   w->WriteULEB128(0);
    1794             : 
    1795             :   // Last location described by this entry.
    1796           0 :   w->Write<uint8_t>(DW_CFA_SET_LOC);
    1797             :   w->Write<uint64_t>(
    1798           0 :       desc_->GetStackStateStartAddress(CodeDescription::POST_RBP_POP));
    1799           0 : }
    1800             : 
    1801             : 
    1802           0 : void UnwindInfoSection::WriteFDEStateAfterRBPPop(Writer* w) {
    1803             :   // The fourth (final) state. The RBP has been popped (just before issuing a
    1804             :   // return).
    1805             : 
    1806             :   // The CFA can is now calculated in the same way as in the first state.
    1807           0 :   w->Write<uint8_t>(DW_CFA_DEF_CFA_SF);
    1808           0 :   w->WriteULEB128(AMD64_RSP);
    1809           0 :   w->WriteSLEB128(-kPointerSize);
    1810             : 
    1811             :   // The RBP
    1812           0 :   w->Write<uint8_t>(DW_CFA_OFFSET_EXTENDED);
    1813           0 :   w->WriteULEB128(AMD64_RBP);
    1814           0 :   w->WriteSLEB128(StandardFrameConstants::kCallerFPOffset);
    1815             : 
    1816             :   // Last location described by this entry.
    1817           0 :   w->Write<uint8_t>(DW_CFA_SET_LOC);
    1818           0 :   w->Write<uint64_t>(desc_->CodeEnd());
    1819           0 : }
    1820             : 
    1821             : 
    1822           0 : bool UnwindInfoSection::WriteBodyInternal(Writer* w) {
    1823           0 :   uint32_t cie_position = WriteCIE(w);
    1824           0 :   WriteFDE(w, cie_position);
    1825           0 :   return true;
    1826             : }
    1827             : 
    1828             : 
    1829             : #endif  // V8_TARGET_ARCH_X64
    1830             : 
    1831           0 : static void CreateDWARFSections(CodeDescription* desc,
    1832             :                                 Zone* zone,
    1833             :                                 DebugObject* obj) {
    1834           0 :   if (desc->IsLineInfoAvailable()) {
    1835           0 :     obj->AddSection(new(zone) DebugInfoSection(desc));
    1836           0 :     obj->AddSection(new(zone) DebugAbbrevSection(desc));
    1837           0 :     obj->AddSection(new(zone) DebugLineSection(desc));
    1838             :   }
    1839             : #if V8_TARGET_ARCH_X64
    1840           0 :   obj->AddSection(new(zone) UnwindInfoSection(desc));
    1841             : #endif
    1842           0 : }
    1843             : 
    1844             : 
    1845             : // -------------------------------------------------------------------
    1846             : // Binary GDB JIT Interface as described in
    1847             : //   http://sourceware.org/gdb/onlinedocs/gdb/Declarations.html
    1848             : extern "C" {
    1849             :   typedef enum {
    1850             :     JIT_NOACTION = 0,
    1851             :     JIT_REGISTER_FN,
    1852             :     JIT_UNREGISTER_FN
    1853             :   } JITAction;
    1854             : 
    1855             :   struct JITCodeEntry {
    1856             :     JITCodeEntry* next_;
    1857             :     JITCodeEntry* prev_;
    1858             :     Address symfile_addr_;
    1859             :     uint64_t symfile_size_;
    1860             :   };
    1861             : 
    1862             :   struct JITDescriptor {
    1863             :     uint32_t version_;
    1864             :     uint32_t action_flag_;
    1865             :     JITCodeEntry* relevant_entry_;
    1866             :     JITCodeEntry* first_entry_;
    1867             :   };
    1868             : 
    1869             :   // GDB will place breakpoint into this function.
    1870             :   // To prevent GCC from inlining or removing it we place noinline attribute
    1871             :   // and inline assembler statement inside.
    1872           0 :   void __attribute__((noinline)) __jit_debug_register_code() {
    1873           0 :     __asm__("");
    1874           0 :   }
    1875             : 
    1876             :   // GDB will inspect contents of this descriptor.
    1877             :   // Static initialization is necessary to prevent GDB from seeing
    1878             :   // uninitialized descriptor.
    1879             :   JITDescriptor __jit_debug_descriptor = { 1, 0, 0, 0 };
    1880             : 
    1881             : #ifdef OBJECT_PRINT
    1882             :   void __gdb_print_v8_object(Object* object) {
    1883             :     OFStream os(stdout);
    1884             :     object->Print(os);
    1885             :     os << std::flush;
    1886             :   }
    1887             : #endif
    1888             : }
    1889             : 
    1890             : 
    1891           0 : static JITCodeEntry* CreateCodeEntry(Address symfile_addr,
    1892             :                                      uintptr_t symfile_size) {
    1893             :   JITCodeEntry* entry = static_cast<JITCodeEntry*>(
    1894           0 :       malloc(sizeof(JITCodeEntry) + symfile_size));
    1895             : 
    1896           0 :   entry->symfile_addr_ = reinterpret_cast<Address>(entry + 1);
    1897           0 :   entry->symfile_size_ = symfile_size;
    1898             :   MemCopy(entry->symfile_addr_, symfile_addr, symfile_size);
    1899             : 
    1900           0 :   entry->prev_ = entry->next_ = nullptr;
    1901             : 
    1902           0 :   return entry;
    1903             : }
    1904             : 
    1905             : 
    1906             : static void DestroyCodeEntry(JITCodeEntry* entry) {
    1907           0 :   free(entry);
    1908             : }
    1909             : 
    1910             : 
    1911           0 : static void RegisterCodeEntry(JITCodeEntry* entry) {
    1912           0 :   entry->next_ = __jit_debug_descriptor.first_entry_;
    1913           0 :   if (entry->next_ != nullptr) entry->next_->prev_ = entry;
    1914             :   __jit_debug_descriptor.first_entry_ =
    1915           0 :       __jit_debug_descriptor.relevant_entry_ = entry;
    1916             : 
    1917           0 :   __jit_debug_descriptor.action_flag_ = JIT_REGISTER_FN;
    1918           0 :   __jit_debug_register_code();
    1919           0 : }
    1920             : 
    1921             : 
    1922           0 : static void UnregisterCodeEntry(JITCodeEntry* entry) {
    1923           0 :   if (entry->prev_ != nullptr) {
    1924           0 :     entry->prev_->next_ = entry->next_;
    1925             :   } else {
    1926           0 :     __jit_debug_descriptor.first_entry_ = entry->next_;
    1927             :   }
    1928             : 
    1929           0 :   if (entry->next_ != nullptr) {
    1930           0 :     entry->next_->prev_ = entry->prev_;
    1931             :   }
    1932             : 
    1933           0 :   __jit_debug_descriptor.relevant_entry_ = entry;
    1934           0 :   __jit_debug_descriptor.action_flag_ = JIT_UNREGISTER_FN;
    1935           0 :   __jit_debug_register_code();
    1936           0 : }
    1937             : 
    1938             : 
    1939           0 : static JITCodeEntry* CreateELFObject(CodeDescription* desc, Isolate* isolate) {
    1940             : #ifdef __MACH_O
    1941             :   Zone zone(isolate->allocator(), ZONE_NAME);
    1942             :   MachO mach_o(&zone);
    1943             :   Writer w(&mach_o);
    1944             : 
    1945             :   mach_o.AddSection(new(&zone) MachOTextSection(kCodeAlignment,
    1946             :                                                 desc->CodeStart(),
    1947             :                                                 desc->CodeSize()));
    1948             : 
    1949             :   CreateDWARFSections(desc, &zone, &mach_o);
    1950             : 
    1951             :   mach_o.Write(&w, desc->CodeStart(), desc->CodeSize());
    1952             : #else
    1953           0 :   Zone zone(isolate->allocator(), ZONE_NAME);
    1954           0 :   ELF elf(&zone);
    1955             :   Writer w(&elf);
    1956             : 
    1957             :   int text_section_index = elf.AddSection(
    1958             :       new(&zone) FullHeaderELFSection(
    1959             :           ".text",
    1960             :           ELFSection::TYPE_NOBITS,
    1961             :           kCodeAlignment,
    1962             :           desc->CodeStart(),
    1963             :           0,
    1964             :           desc->CodeSize(),
    1965           0 :           ELFSection::FLAG_ALLOC | ELFSection::FLAG_EXEC));
    1966             : 
    1967           0 :   CreateSymbolsTable(desc, &zone, &elf, text_section_index);
    1968             : 
    1969           0 :   CreateDWARFSections(desc, &zone, &elf);
    1970             : 
    1971           0 :   elf.Write(&w);
    1972             : #endif
    1973             : 
    1974           0 :   return CreateCodeEntry(w.buffer(), w.position());
    1975             : }
    1976             : 
    1977             : 
    1978             : struct AddressRange {
    1979             :   Address start;
    1980             :   Address end;
    1981             : };
    1982             : 
    1983             : struct SplayTreeConfig {
    1984             :   typedef AddressRange Key;
    1985             :   typedef JITCodeEntry* Value;
    1986             :   static const AddressRange kNoKey;
    1987             :   static Value NoValue() { return nullptr; }
    1988             :   static int Compare(const AddressRange& a, const AddressRange& b) {
    1989             :     // ptrdiff_t probably doesn't fit in an int.
    1990           0 :     if (a.start < b.start) return -1;
    1991           0 :     if (a.start == b.start) return 0;
    1992             :     return 1;
    1993             :   }
    1994             : };
    1995             : 
    1996             : const AddressRange SplayTreeConfig::kNoKey = {0, 0};
    1997             : typedef SplayTree<SplayTreeConfig> CodeMap;
    1998             : 
    1999           0 : static CodeMap* GetCodeMap() {
    2000             :   static CodeMap* code_map = nullptr;
    2001           0 :   if (code_map == nullptr) code_map = new CodeMap();
    2002           0 :   return code_map;
    2003             : }
    2004             : 
    2005             : 
    2006             : static uint32_t HashCodeAddress(Address addr) {
    2007             :   static const uintptr_t kGoldenRatio = 2654435761u;
    2008           0 :   uintptr_t offset = OffsetFrom(addr);
    2009           0 :   return static_cast<uint32_t>((offset >> kCodeAlignmentBits) * kGoldenRatio);
    2010             : }
    2011             : 
    2012           0 : static base::HashMap* GetLineMap() {
    2013             :   static base::HashMap* line_map = nullptr;
    2014           0 :   if (line_map == nullptr) {
    2015           0 :     line_map = new base::HashMap();
    2016             :   }
    2017           0 :   return line_map;
    2018             : }
    2019             : 
    2020             : 
    2021           0 : static void PutLineInfo(Address addr, LineInfo* info) {
    2022           0 :   base::HashMap* line_map = GetLineMap();
    2023             :   base::HashMap::Entry* e =
    2024           0 :       line_map->LookupOrInsert(addr, HashCodeAddress(addr));
    2025           0 :   if (e->value != nullptr) delete static_cast<LineInfo*>(e->value);
    2026           0 :   e->value = info;
    2027           0 : }
    2028             : 
    2029             : 
    2030           0 : static LineInfo* GetLineInfo(Address addr) {
    2031           0 :   void* value = GetLineMap()->Remove(addr, HashCodeAddress(addr));
    2032           0 :   return static_cast<LineInfo*>(value);
    2033             : }
    2034             : 
    2035             : 
    2036           0 : static void AddUnwindInfo(CodeDescription* desc) {
    2037             : #if V8_TARGET_ARCH_X64
    2038           0 :   if (desc->is_function()) {
    2039             :     // To avoid propagating unwinding information through
    2040             :     // compilation pipeline we use an approximation.
    2041             :     // For most use cases this should not affect usability.
    2042             :     static const int kFramePointerPushOffset = 1;
    2043             :     static const int kFramePointerSetOffset = 4;
    2044             :     static const int kFramePointerPopOffset = -3;
    2045             : 
    2046             :     uintptr_t frame_pointer_push_address =
    2047           0 :         desc->CodeStart() + kFramePointerPushOffset;
    2048             : 
    2049             :     uintptr_t frame_pointer_set_address =
    2050           0 :         desc->CodeStart() + kFramePointerSetOffset;
    2051             : 
    2052             :     uintptr_t frame_pointer_pop_address =
    2053           0 :         desc->CodeEnd() + kFramePointerPopOffset;
    2054             : 
    2055             :     desc->SetStackStateStartAddress(CodeDescription::POST_RBP_PUSH,
    2056             :                                     frame_pointer_push_address);
    2057             :     desc->SetStackStateStartAddress(CodeDescription::POST_RBP_SET,
    2058             :                                     frame_pointer_set_address);
    2059             :     desc->SetStackStateStartAddress(CodeDescription::POST_RBP_POP,
    2060             :                                     frame_pointer_pop_address);
    2061             :   } else {
    2062             :     desc->SetStackStateStartAddress(CodeDescription::POST_RBP_PUSH,
    2063             :                                     desc->CodeStart());
    2064             :     desc->SetStackStateStartAddress(CodeDescription::POST_RBP_SET,
    2065             :                                     desc->CodeStart());
    2066             :     desc->SetStackStateStartAddress(CodeDescription::POST_RBP_POP,
    2067             :                                     desc->CodeEnd());
    2068             :   }
    2069             : #endif  // V8_TARGET_ARCH_X64
    2070           0 : }
    2071             : 
    2072             : 
    2073             : static base::LazyMutex mutex = LAZY_MUTEX_INITIALIZER;
    2074             : 
    2075             : 
    2076             : // Remove entries from the splay tree that intersect the given address range,
    2077             : // and deregister them from GDB.
    2078           0 : static void RemoveJITCodeEntries(CodeMap* map, const AddressRange& range) {
    2079             :   DCHECK(range.start < range.end);
    2080             :   CodeMap::Locator cur;
    2081           0 :   if (map->FindGreatestLessThan(range, &cur) || map->FindLeast(&cur)) {
    2082             :     // Skip entries that are entirely less than the range of interest.
    2083           0 :     while (cur.key().end <= range.start) {
    2084             :       // CodeMap::FindLeastGreaterThan succeeds for entries whose key is greater
    2085             :       // than _or equal to_ the given key, so we have to advance our key to get
    2086             :       // the next one.
    2087             :       AddressRange new_key;
    2088           0 :       new_key.start = cur.key().end;
    2089           0 :       new_key.end = 0;
    2090           0 :       if (!map->FindLeastGreaterThan(new_key, &cur)) return;
    2091             :     }
    2092             :     // Evict intersecting ranges.
    2093           0 :     while (cur.key().start < range.end) {
    2094           0 :       AddressRange old_range = cur.key();
    2095           0 :       JITCodeEntry* old_entry = cur.value();
    2096             : 
    2097           0 :       UnregisterCodeEntry(old_entry);
    2098             :       DestroyCodeEntry(old_entry);
    2099             : 
    2100           0 :       CHECK(map->Remove(old_range));
    2101           0 :       if (!map->FindLeastGreaterThan(old_range, &cur)) return;
    2102             :     }
    2103             :   }
    2104             : }
    2105             : 
    2106             : 
    2107             : // Insert the entry into the splay tree and register it with GDB.
    2108           0 : static void AddJITCodeEntry(CodeMap* map, const AddressRange& range,
    2109             :                             JITCodeEntry* entry, bool dump_if_enabled,
    2110             :                             const char* name_hint) {
    2111             : #if defined(DEBUG) && !V8_OS_WIN
    2112             :   static int file_num = 0;
    2113             :   if (FLAG_gdbjit_dump && dump_if_enabled) {
    2114             :     static const int kMaxFileNameSize = 64;
    2115             :     char file_name[64];
    2116             : 
    2117             :     SNPrintF(Vector<char>(file_name, kMaxFileNameSize), "/tmp/elfdump%s%d.o",
    2118             :              (name_hint != nullptr) ? name_hint : "", file_num++);
    2119             :     WriteBytes(file_name, entry->symfile_addr_,
    2120             :                static_cast<int>(entry->symfile_size_));
    2121             :   }
    2122             : #endif
    2123             : 
    2124             :   CodeMap::Locator cur;
    2125           0 :   CHECK(map->Insert(range, &cur));
    2126             :   cur.set_value(entry);
    2127             : 
    2128           0 :   RegisterCodeEntry(entry);
    2129           0 : }
    2130             : 
    2131             : 
    2132           0 : static void AddCode(const char* name, Code* code, SharedFunctionInfo* shared,
    2133             :                     LineInfo* lineinfo) {
    2134             :   DisallowHeapAllocation no_gc;
    2135             : 
    2136           0 :   CodeMap* code_map = GetCodeMap();
    2137             :   AddressRange range;
    2138           0 :   range.start = code->address();
    2139           0 :   range.end = code->address() + code->CodeSize();
    2140           0 :   RemoveJITCodeEntries(code_map, range);
    2141             : 
    2142             :   CodeDescription code_desc(name, code, shared, lineinfo);
    2143             : 
    2144           0 :   if (!FLAG_gdbjit_full && !code_desc.IsLineInfoAvailable()) {
    2145           0 :     delete lineinfo;
    2146           0 :     return;
    2147             :   }
    2148             : 
    2149           0 :   AddUnwindInfo(&code_desc);
    2150             :   Isolate* isolate = code->GetIsolate();
    2151           0 :   JITCodeEntry* entry = CreateELFObject(&code_desc, isolate);
    2152             : 
    2153           0 :   delete lineinfo;
    2154             : 
    2155             :   const char* name_hint = nullptr;
    2156             :   bool should_dump = false;
    2157             :   if (FLAG_gdbjit_dump) {
    2158             :     if (strlen(FLAG_gdbjit_dump_filter) == 0) {
    2159             :       name_hint = name;
    2160             :       should_dump = true;
    2161             :     } else if (name != nullptr) {
    2162             :       name_hint = strstr(name, FLAG_gdbjit_dump_filter);
    2163             :       should_dump = (name_hint != nullptr);
    2164             :     }
    2165             :   }
    2166           0 :   AddJITCodeEntry(code_map, range, entry, should_dump, name_hint);
    2167             : }
    2168             : 
    2169             : 
    2170           0 : void EventHandler(const v8::JitCodeEvent* event) {
    2171           0 :   if (!FLAG_gdbjit) return;
    2172             :   base::LockGuard<base::Mutex> lock_guard(mutex.Pointer());
    2173           0 :   switch (event->type) {
    2174             :     case v8::JitCodeEvent::CODE_ADDED: {
    2175           0 :       Address addr = reinterpret_cast<Address>(event->code_start);
    2176           0 :       Code* code = Code::GetCodeFromTargetAddress(addr);
    2177           0 :       LineInfo* lineinfo = GetLineInfo(addr);
    2178             :       EmbeddedVector<char, 256> buffer;
    2179             :       StringBuilder builder(buffer.start(), buffer.length());
    2180           0 :       builder.AddSubstring(event->name.str, static_cast<int>(event->name.len));
    2181             :       // It's called UnboundScript in the API but it's a SharedFunctionInfo.
    2182             :       SharedFunctionInfo* shared = event->script.IsEmpty()
    2183             :                                        ? nullptr
    2184           0 :                                        : *Utils::OpenHandle(*event->script);
    2185           0 :       AddCode(builder.Finalize(), code, shared, lineinfo);
    2186             :       break;
    2187             :     }
    2188             :     case v8::JitCodeEvent::CODE_MOVED:
    2189             :       // Enabling the GDB JIT interface should disable code compaction.
    2190           0 :       UNREACHABLE();
    2191             :       break;
    2192             :     case v8::JitCodeEvent::CODE_REMOVED:
    2193             :       // Do nothing.  Instead, adding code causes eviction of any entry whose
    2194             :       // address range intersects the address range of the added code.
    2195             :       break;
    2196             :     case v8::JitCodeEvent::CODE_ADD_LINE_POS_INFO: {
    2197           0 :       LineInfo* line_info = reinterpret_cast<LineInfo*>(event->user_data);
    2198             :       line_info->SetPosition(static_cast<intptr_t>(event->line_info.offset),
    2199             :                              static_cast<int>(event->line_info.pos),
    2200             :                              event->line_info.position_type ==
    2201           0 :                                  v8::JitCodeEvent::STATEMENT_POSITION);
    2202             :       break;
    2203             :     }
    2204             :     case v8::JitCodeEvent::CODE_START_LINE_INFO_RECORDING: {
    2205             :       v8::JitCodeEvent* mutable_event = const_cast<v8::JitCodeEvent*>(event);
    2206           0 :       mutable_event->user_data = new LineInfo();
    2207           0 :       break;
    2208             :     }
    2209             :     case v8::JitCodeEvent::CODE_END_LINE_INFO_RECORDING: {
    2210           0 :       LineInfo* line_info = reinterpret_cast<LineInfo*>(event->user_data);
    2211           0 :       PutLineInfo(reinterpret_cast<Address>(event->code_start), line_info);
    2212           0 :       break;
    2213             :     }
    2214             :   }
    2215             : }
    2216             : #endif
    2217             : }  // namespace GDBJITInterface
    2218             : }  // namespace internal
    2219             : }  // namespace v8

Generated by: LCOV version 1.10