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