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