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