v8  3.14.5(node0.10.28)
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 StringTable;
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 defined(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, StringTable* 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 StringTable : public ELFSection {
442  public:
443  explicit StringTable(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  StringTable* 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  MachO() : sections_(6) { }
504 
505  uint32_t AddSection(MachOSection* section) {
506  sections_.Add(section);
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 defined(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 defined(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 defined(V8_TARGET_ARCH_IA32)
564  header->magic = 0xFEEDFACEu;
565  header->cputype = 7; // i386
566  header->cpusubtype = 3; // CPU_SUBTYPE_I386_ALL
567 #elif defined(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 defined(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 
624  ZoneList<MachOSection*> sections_;
625 };
626 #endif // defined(__MACH_O)
627 
628 
629 #if defined(__ELF)
630 class ELF BASE_EMBEDDED {
631  public:
632  ELF(Zone* zone) : sections_(6, zone) {
633  sections_.Add(new(zone) ELFSection("", ELFSection::TYPE_NULL, 0), zone);
634  sections_.Add(new(zone) StringTable(".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, Zone* zone) {
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 defined(V8_TARGET_ARCH_IA32) || defined(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 defined(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  memcpy(header->ident, ident, 16);
685  header->type = 1;
686 #if defined(V8_TARGET_ARCH_IA32)
687  header->machine = 3;
688 #elif defined(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 defined(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  StringTable* strtab = static_cast<StringTable*>(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  ZoneList<ELFSection*> sections_;
747 };
748 
749 
750 class ELFSymbol BASE_EMBEDDED {
751  public:
752  enum Type {
753  TYPE_NOTYPE = 0,
754  TYPE_OBJECT = 1,
755  TYPE_FUNC = 2,
756  TYPE_SECTION = 3,
757  TYPE_FILE = 4,
758  TYPE_LOPROC = 13,
759  TYPE_HIPROC = 15
760  };
761 
762  enum Binding {
763  BIND_LOCAL = 0,
764  BIND_GLOBAL = 1,
765  BIND_WEAK = 2,
766  BIND_LOPROC = 13,
767  BIND_HIPROC = 15
768  };
769 
770  ELFSymbol(const char* name,
771  uintptr_t value,
772  uintptr_t size,
773  Binding binding,
774  Type type,
775  uint16_t section)
776  : name(name),
777  value(value),
778  size(size),
779  info((binding << 4) | type),
780  other(0),
781  section(section) {
782  }
783 
784  Binding binding() const {
785  return static_cast<Binding>(info >> 4);
786  }
787 #if defined(V8_TARGET_ARCH_IA32) || defined(V8_TARGET_ARCH_ARM)
788  struct SerializedLayout {
789  SerializedLayout(uint32_t name,
790  uintptr_t value,
791  uintptr_t size,
792  Binding binding,
793  Type type,
794  uint16_t section)
795  : name(name),
796  value(value),
797  size(size),
798  info((binding << 4) | type),
799  other(0),
800  section(section) {
801  }
802 
803  uint32_t name;
804  uintptr_t value;
805  uintptr_t size;
806  uint8_t info;
807  uint8_t other;
808  uint16_t section;
809  };
810 #elif defined(V8_TARGET_ARCH_X64)
811  struct SerializedLayout {
812  SerializedLayout(uint32_t name,
813  uintptr_t value,
814  uintptr_t size,
815  Binding binding,
816  Type type,
817  uint16_t section)
818  : name(name),
819  info((binding << 4) | type),
820  other(0),
821  section(section),
822  value(value),
823  size(size) {
824  }
825 
826  uint32_t name;
827  uint8_t info;
828  uint8_t other;
829  uint16_t section;
830  uintptr_t value;
831  uintptr_t size;
832  };
833 #endif
834 
835  void Write(Writer::Slot<SerializedLayout> s, StringTable* t) {
836  // Convert symbol names from strings to indexes in the string table.
837  s->name = t->Add(name);
838  s->value = value;
839  s->size = size;
840  s->info = info;
841  s->other = other;
842  s->section = section;
843  }
844 
845  private:
846  const char* name;
847  uintptr_t value;
848  uintptr_t size;
849  uint8_t info;
850  uint8_t other;
851  uint16_t section;
852 };
853 
854 
855 class ELFSymbolTable : public ELFSection {
856  public:
857  ELFSymbolTable(const char* name, Zone* zone)
858  : ELFSection(name, TYPE_SYMTAB, sizeof(uintptr_t)),
859  locals_(1, zone),
860  globals_(1, zone) {
861  }
862 
863  virtual void WriteBody(Writer::Slot<Header> header, Writer* w) {
864  w->Align(header->alignment);
865  int total_symbols = locals_.length() + globals_.length() + 1;
866  header->offset = w->position();
867 
868  Writer::Slot<ELFSymbol::SerializedLayout> symbols =
869  w->CreateSlotsHere<ELFSymbol::SerializedLayout>(total_symbols);
870 
871  header->size = w->position() - header->offset;
872 
873  // String table for this symbol table should follow it in the section table.
874  StringTable* strtab =
875  static_cast<StringTable*>(w->debug_object()->SectionAt(index() + 1));
876  strtab->AttachWriter(w);
877  symbols.at(0).set(ELFSymbol::SerializedLayout(0,
878  0,
879  0,
880  ELFSymbol::BIND_LOCAL,
881  ELFSymbol::TYPE_NOTYPE,
882  0));
883  WriteSymbolsList(&locals_, symbols.at(1), strtab);
884  WriteSymbolsList(&globals_, symbols.at(locals_.length() + 1), strtab);
885  strtab->DetachWriter();
886  }
887 
888  void Add(const ELFSymbol& symbol, Zone* zone) {
889  if (symbol.binding() == ELFSymbol::BIND_LOCAL) {
890  locals_.Add(symbol, zone);
891  } else {
892  globals_.Add(symbol, zone);
893  }
894  }
895 
896  protected:
897  virtual void PopulateHeader(Writer::Slot<Header> header) {
898  ELFSection::PopulateHeader(header);
899  // We are assuming that string table will follow symbol table.
900  header->link = index() + 1;
901  header->info = locals_.length() + 1;
902  header->entry_size = sizeof(ELFSymbol::SerializedLayout);
903  }
904 
905  private:
906  void WriteSymbolsList(const ZoneList<ELFSymbol>* src,
907  Writer::Slot<ELFSymbol::SerializedLayout> dst,
908  StringTable* strtab) {
909  for (int i = 0, len = src->length();
910  i < len;
911  i++) {
912  src->at(i).Write(dst.at(i), strtab);
913  }
914  }
915 
916  ZoneList<ELFSymbol> locals_;
917  ZoneList<ELFSymbol> globals_;
918 };
919 #endif // defined(__ELF)
920 
921 
922 class CodeDescription BASE_EMBEDDED {
923  public:
924 #ifdef V8_TARGET_ARCH_X64
925  enum StackState {
926  POST_RBP_PUSH,
927  POST_RBP_SET,
928  POST_RBP_POP,
929  STACK_STATE_MAX
930  };
931 #endif
932 
933  CodeDescription(const char* name,
934  Code* code,
935  Handle<Script> script,
936  GDBJITLineInfo* lineinfo,
937  GDBJITInterface::CodeTag tag,
938  CompilationInfo* info)
939  : name_(name),
940  code_(code),
941  script_(script),
942  lineinfo_(lineinfo),
943  tag_(tag),
944  info_(info) {
945  }
946 
947  const char* name() const {
948  return name_;
949  }
950 
951  GDBJITLineInfo* lineinfo() const {
952  return lineinfo_;
953  }
954 
955  GDBJITInterface::CodeTag tag() const {
956  return tag_;
957  }
958 
959  CompilationInfo* info() const {
960  return info_;
961  }
962 
963  bool IsInfoAvailable() const {
964  return info_ != NULL;
965  }
966 
967  uintptr_t CodeStart() const {
968  return reinterpret_cast<uintptr_t>(code_->instruction_start());
969  }
970 
971  uintptr_t CodeEnd() const {
972  return reinterpret_cast<uintptr_t>(code_->instruction_end());
973  }
974 
975  uintptr_t CodeSize() const {
976  return CodeEnd() - CodeStart();
977  }
978 
979  bool IsLineInfoAvailable() {
980  return !script_.is_null() &&
981  script_->source()->IsString() &&
982  script_->HasValidSource() &&
983  script_->name()->IsString() &&
984  lineinfo_ != NULL;
985  }
986 
987 #ifdef V8_TARGET_ARCH_X64
988  uintptr_t GetStackStateStartAddress(StackState state) const {
989  ASSERT(state < STACK_STATE_MAX);
990  return stack_state_start_addresses_[state];
991  }
992 
993  void SetStackStateStartAddress(StackState state, uintptr_t addr) {
994  ASSERT(state < STACK_STATE_MAX);
995  stack_state_start_addresses_[state] = addr;
996  }
997 #endif
998 
999  SmartArrayPointer<char> GetFilename() {
1000  return String::cast(script_->name())->ToCString();
1001  }
1002 
1003  int GetScriptLineNumber(int pos) {
1004  return GetScriptLineNumberSafe(script_, pos) + 1;
1005  }
1006 
1007 
1008  private:
1009  const char* name_;
1010  Code* code_;
1011  Handle<Script> script_;
1012  GDBJITLineInfo* lineinfo_;
1013  GDBJITInterface::CodeTag tag_;
1014  CompilationInfo* info_;
1015 #ifdef V8_TARGET_ARCH_X64
1016  uintptr_t stack_state_start_addresses_[STACK_STATE_MAX];
1017 #endif
1018 };
1019 
1020 #if defined(__ELF)
1021 static void CreateSymbolsTable(CodeDescription* desc,
1022  ELF* elf,
1023  int text_section_index) {
1024  Zone* zone = desc->info()->zone();
1025  ELFSymbolTable* symtab = new(zone) ELFSymbolTable(".symtab", zone);
1026  StringTable* strtab = new(zone) StringTable(".strtab");
1027 
1028  // Symbol table should be followed by the linked string table.
1029  elf->AddSection(symtab, zone);
1030  elf->AddSection(strtab, zone);
1031 
1032  symtab->Add(ELFSymbol("V8 Code",
1033  0,
1034  0,
1035  ELFSymbol::BIND_LOCAL,
1036  ELFSymbol::TYPE_FILE,
1037  ELFSection::INDEX_ABSOLUTE),
1038  zone);
1039 
1040  symtab->Add(ELFSymbol(desc->name(),
1041  0,
1042  desc->CodeSize(),
1043  ELFSymbol::BIND_GLOBAL,
1044  ELFSymbol::TYPE_FUNC,
1045  text_section_index),
1046  zone);
1047 }
1048 #endif // defined(__ELF)
1049 
1050 
1051 class DebugInfoSection : public DebugSection {
1052  public:
1053  explicit DebugInfoSection(CodeDescription* desc)
1054 #if defined(__ELF)
1055  : ELFSection(".debug_info", TYPE_PROGBITS, 1),
1056 #else
1057  : MachOSection("__debug_info",
1058  "__DWARF",
1059  1,
1060  MachOSection::S_REGULAR | MachOSection::S_ATTR_DEBUG),
1061 #endif
1062  desc_(desc) { }
1063 
1064  // DWARF2 standard
1065  enum DWARF2LocationOp {
1066  DW_OP_reg0 = 0x50,
1067  DW_OP_reg1 = 0x51,
1068  DW_OP_reg2 = 0x52,
1069  DW_OP_reg3 = 0x53,
1070  DW_OP_reg4 = 0x54,
1071  DW_OP_reg5 = 0x55,
1072  DW_OP_reg6 = 0x56,
1073  DW_OP_reg7 = 0x57,
1074  DW_OP_fbreg = 0x91 // 1 param: SLEB128 offset
1075  };
1076 
1077  enum DWARF2Encoding {
1078  DW_ATE_ADDRESS = 0x1,
1079  DW_ATE_SIGNED = 0x5
1080  };
1081 
1082  bool WriteBodyInternal(Writer* w) {
1083  uintptr_t cu_start = w->position();
1084  Writer::Slot<uint32_t> size = w->CreateSlotHere<uint32_t>();
1085  uintptr_t start = w->position();
1086  w->Write<uint16_t>(2); // DWARF version.
1087  w->Write<uint32_t>(0); // Abbreviation table offset.
1088  w->Write<uint8_t>(sizeof(intptr_t));
1089 
1090  w->WriteULEB128(1); // Abbreviation code.
1091  w->WriteString(*desc_->GetFilename());
1092  w->Write<intptr_t>(desc_->CodeStart());
1093  w->Write<intptr_t>(desc_->CodeStart() + desc_->CodeSize());
1094  w->Write<uint32_t>(0);
1095 
1096  uint32_t ty_offset = static_cast<uint32_t>(w->position() - cu_start);
1097  w->WriteULEB128(3);
1098  w->Write<uint8_t>(kPointerSize);
1099  w->WriteString("v8value");
1100 
1101  if (desc_->IsInfoAvailable()) {
1102  Scope* scope = desc_->info()->scope();
1103  w->WriteULEB128(2);
1104  w->WriteString(desc_->name());
1105  w->Write<intptr_t>(desc_->CodeStart());
1106  w->Write<intptr_t>(desc_->CodeStart() + desc_->CodeSize());
1107  Writer::Slot<uint32_t> fb_block_size = w->CreateSlotHere<uint32_t>();
1108  uintptr_t fb_block_start = w->position();
1109 #if defined(V8_TARGET_ARCH_IA32)
1110  w->Write<uint8_t>(DW_OP_reg5); // The frame pointer's here on ia32
1111 #elif defined(V8_TARGET_ARCH_X64)
1112  w->Write<uint8_t>(DW_OP_reg6); // and here on x64.
1113 #elif defined(V8_TARGET_ARCH_ARM)
1114  UNIMPLEMENTED();
1115 #elif defined(V8_TARGET_ARCH_MIPS)
1116  UNIMPLEMENTED();
1117 #else
1118 #error Unsupported target architecture.
1119 #endif
1120  fb_block_size.set(static_cast<uint32_t>(w->position() - fb_block_start));
1121 
1122  int params = scope->num_parameters();
1123  int slots = scope->num_stack_slots();
1124  int context_slots = scope->ContextLocalCount();
1125  // The real slot ID is internal_slots + context_slot_id.
1126  int internal_slots = Context::MIN_CONTEXT_SLOTS;
1127  int locals = scope->StackLocalCount();
1128  int current_abbreviation = 4;
1129 
1130  for (int param = 0; param < params; ++param) {
1131  w->WriteULEB128(current_abbreviation++);
1132  w->WriteString(
1133  *scope->parameter(param)->name()->ToCString(DISALLOW_NULLS));
1134  w->Write<uint32_t>(ty_offset);
1135  Writer::Slot<uint32_t> block_size = w->CreateSlotHere<uint32_t>();
1136  uintptr_t block_start = w->position();
1137  w->Write<uint8_t>(DW_OP_fbreg);
1138  w->WriteSLEB128(
1140  kPointerSize * (params - param - 1));
1141  block_size.set(static_cast<uint32_t>(w->position() - block_start));
1142  }
1143 
1144  EmbeddedVector<char, 256> buffer;
1145  StringBuilder builder(buffer.start(), buffer.length());
1146 
1147  for (int slot = 0; slot < slots; ++slot) {
1148  w->WriteULEB128(current_abbreviation++);
1149  builder.Reset();
1150  builder.AddFormatted("slot%d", slot);
1151  w->WriteString(builder.Finalize());
1152  }
1153 
1154  // See contexts.h for more information.
1160  w->WriteULEB128(current_abbreviation++);
1161  w->WriteString(".closure");
1162  w->WriteULEB128(current_abbreviation++);
1163  w->WriteString(".previous");
1164  w->WriteULEB128(current_abbreviation++);
1165  w->WriteString(".extension");
1166  w->WriteULEB128(current_abbreviation++);
1167  w->WriteString(".global");
1168 
1169  for (int context_slot = 0;
1170  context_slot < context_slots;
1171  ++context_slot) {
1172  w->WriteULEB128(current_abbreviation++);
1173  builder.Reset();
1174  builder.AddFormatted("context_slot%d", context_slot + internal_slots);
1175  w->WriteString(builder.Finalize());
1176  }
1177 
1178  ZoneList<Variable*> stack_locals(locals, scope->zone());
1179  ZoneList<Variable*> context_locals(context_slots, scope->zone());
1180  scope->CollectStackAndContextLocals(&stack_locals, &context_locals);
1181  for (int local = 0; local < locals; ++local) {
1182  w->WriteULEB128(current_abbreviation++);
1183  w->WriteString(
1184  *stack_locals[local]->name()->ToCString(DISALLOW_NULLS));
1185  w->Write<uint32_t>(ty_offset);
1186  Writer::Slot<uint32_t> block_size = w->CreateSlotHere<uint32_t>();
1187  uintptr_t block_start = w->position();
1188  w->Write<uint8_t>(DW_OP_fbreg);
1189  w->WriteSLEB128(
1191  kPointerSize * local);
1192  block_size.set(static_cast<uint32_t>(w->position() - block_start));
1193  }
1194 
1195  {
1196  w->WriteULEB128(current_abbreviation++);
1197  w->WriteString("__function");
1198  w->Write<uint32_t>(ty_offset);
1199  Writer::Slot<uint32_t> block_size = w->CreateSlotHere<uint32_t>();
1200  uintptr_t block_start = w->position();
1201  w->Write<uint8_t>(DW_OP_fbreg);
1203  block_size.set(static_cast<uint32_t>(w->position() - block_start));
1204  }
1205 
1206  {
1207  w->WriteULEB128(current_abbreviation++);
1208  w->WriteString("__context");
1209  w->Write<uint32_t>(ty_offset);
1210  Writer::Slot<uint32_t> block_size = w->CreateSlotHere<uint32_t>();
1211  uintptr_t block_start = w->position();
1212  w->Write<uint8_t>(DW_OP_fbreg);
1213  w->WriteSLEB128(StandardFrameConstants::kContextOffset);
1214  block_size.set(static_cast<uint32_t>(w->position() - block_start));
1215  }
1216  }
1217 
1218  size.set(static_cast<uint32_t>(w->position() - start));
1219  return true;
1220  }
1221 
1222  private:
1223  CodeDescription* desc_;
1224 };
1225 
1226 
1227 class DebugAbbrevSection : public DebugSection {
1228  public:
1229  explicit DebugAbbrevSection(CodeDescription* desc)
1230 #ifdef __ELF
1231  : ELFSection(".debug_abbrev", TYPE_PROGBITS, 1),
1232 #else
1233  : MachOSection("__debug_abbrev",
1234  "__DWARF",
1235  1,
1236  MachOSection::S_REGULAR | MachOSection::S_ATTR_DEBUG),
1237 #endif
1238  desc_(desc) { }
1239 
1240  // DWARF2 standard, figure 14.
1241  enum DWARF2Tags {
1242  DW_TAG_FORMAL_PARAMETER = 0x05,
1243  DW_TAG_POINTER_TYPE = 0xf,
1244  DW_TAG_COMPILE_UNIT = 0x11,
1245  DW_TAG_STRUCTURE_TYPE = 0x13,
1246  DW_TAG_BASE_TYPE = 0x24,
1247  DW_TAG_SUBPROGRAM = 0x2e,
1248  DW_TAG_VARIABLE = 0x34
1249  };
1250 
1251  // DWARF2 standard, figure 16.
1252  enum DWARF2ChildrenDetermination {
1253  DW_CHILDREN_NO = 0,
1254  DW_CHILDREN_YES = 1
1255  };
1256 
1257  // DWARF standard, figure 17.
1258  enum DWARF2Attribute {
1259  DW_AT_LOCATION = 0x2,
1260  DW_AT_NAME = 0x3,
1261  DW_AT_BYTE_SIZE = 0xb,
1262  DW_AT_STMT_LIST = 0x10,
1263  DW_AT_LOW_PC = 0x11,
1264  DW_AT_HIGH_PC = 0x12,
1265  DW_AT_ENCODING = 0x3e,
1266  DW_AT_FRAME_BASE = 0x40,
1267  DW_AT_TYPE = 0x49
1268  };
1269 
1270  // DWARF2 standard, figure 19.
1271  enum DWARF2AttributeForm {
1272  DW_FORM_ADDR = 0x1,
1273  DW_FORM_BLOCK4 = 0x4,
1274  DW_FORM_STRING = 0x8,
1275  DW_FORM_DATA4 = 0x6,
1276  DW_FORM_BLOCK = 0x9,
1277  DW_FORM_DATA1 = 0xb,
1278  DW_FORM_FLAG = 0xc,
1279  DW_FORM_REF4 = 0x13
1280  };
1281 
1282  void WriteVariableAbbreviation(Writer* w,
1283  int abbreviation_code,
1284  bool has_value,
1285  bool is_parameter) {
1286  w->WriteULEB128(abbreviation_code);
1287  w->WriteULEB128(is_parameter ? DW_TAG_FORMAL_PARAMETER : DW_TAG_VARIABLE);
1288  w->Write<uint8_t>(DW_CHILDREN_NO);
1289  w->WriteULEB128(DW_AT_NAME);
1290  w->WriteULEB128(DW_FORM_STRING);
1291  if (has_value) {
1292  w->WriteULEB128(DW_AT_TYPE);
1293  w->WriteULEB128(DW_FORM_REF4);
1294  w->WriteULEB128(DW_AT_LOCATION);
1295  w->WriteULEB128(DW_FORM_BLOCK4);
1296  }
1297  w->WriteULEB128(0);
1298  w->WriteULEB128(0);
1299  }
1300 
1301  bool WriteBodyInternal(Writer* w) {
1302  int current_abbreviation = 1;
1303  bool extra_info = desc_->IsInfoAvailable();
1304  ASSERT(desc_->IsLineInfoAvailable());
1305  w->WriteULEB128(current_abbreviation++);
1306  w->WriteULEB128(DW_TAG_COMPILE_UNIT);
1307  w->Write<uint8_t>(extra_info ? DW_CHILDREN_YES : DW_CHILDREN_NO);
1308  w->WriteULEB128(DW_AT_NAME);
1309  w->WriteULEB128(DW_FORM_STRING);
1310  w->WriteULEB128(DW_AT_LOW_PC);
1311  w->WriteULEB128(DW_FORM_ADDR);
1312  w->WriteULEB128(DW_AT_HIGH_PC);
1313  w->WriteULEB128(DW_FORM_ADDR);
1314  w->WriteULEB128(DW_AT_STMT_LIST);
1315  w->WriteULEB128(DW_FORM_DATA4);
1316  w->WriteULEB128(0);
1317  w->WriteULEB128(0);
1318 
1319  if (extra_info) {
1320  Scope* scope = desc_->info()->scope();
1321  int params = scope->num_parameters();
1322  int slots = scope->num_stack_slots();
1323  int context_slots = scope->ContextLocalCount();
1324  // The real slot ID is internal_slots + context_slot_id.
1325  int internal_slots = Context::MIN_CONTEXT_SLOTS;
1326  int locals = scope->StackLocalCount();
1327  int total_children =
1328  params + slots + context_slots + internal_slots + locals + 2;
1329 
1330  // The extra duplication below seems to be necessary to keep
1331  // gdb from getting upset on OSX.
1332  w->WriteULEB128(current_abbreviation++); // Abbreviation code.
1333  w->WriteULEB128(DW_TAG_SUBPROGRAM);
1334  w->Write<uint8_t>(
1335  total_children != 0 ? DW_CHILDREN_YES : DW_CHILDREN_NO);
1336  w->WriteULEB128(DW_AT_NAME);
1337  w->WriteULEB128(DW_FORM_STRING);
1338  w->WriteULEB128(DW_AT_LOW_PC);
1339  w->WriteULEB128(DW_FORM_ADDR);
1340  w->WriteULEB128(DW_AT_HIGH_PC);
1341  w->WriteULEB128(DW_FORM_ADDR);
1342  w->WriteULEB128(DW_AT_FRAME_BASE);
1343  w->WriteULEB128(DW_FORM_BLOCK4);
1344  w->WriteULEB128(0);
1345  w->WriteULEB128(0);
1346 
1347  w->WriteULEB128(current_abbreviation++);
1348  w->WriteULEB128(DW_TAG_STRUCTURE_TYPE);
1349  w->Write<uint8_t>(DW_CHILDREN_NO);
1350  w->WriteULEB128(DW_AT_BYTE_SIZE);
1351  w->WriteULEB128(DW_FORM_DATA1);
1352  w->WriteULEB128(DW_AT_NAME);
1353  w->WriteULEB128(DW_FORM_STRING);
1354  w->WriteULEB128(0);
1355  w->WriteULEB128(0);
1356 
1357  for (int param = 0; param < params; ++param) {
1358  WriteVariableAbbreviation(w, current_abbreviation++, true, true);
1359  }
1360 
1361  for (int slot = 0; slot < slots; ++slot) {
1362  WriteVariableAbbreviation(w, current_abbreviation++, false, false);
1363  }
1364 
1365  for (int internal_slot = 0;
1366  internal_slot < internal_slots;
1367  ++internal_slot) {
1368  WriteVariableAbbreviation(w, current_abbreviation++, false, false);
1369  }
1370 
1371  for (int context_slot = 0;
1372  context_slot < context_slots;
1373  ++context_slot) {
1374  WriteVariableAbbreviation(w, current_abbreviation++, false, false);
1375  }
1376 
1377  for (int local = 0; local < locals; ++local) {
1378  WriteVariableAbbreviation(w, current_abbreviation++, true, false);
1379  }
1380 
1381  // The function.
1382  WriteVariableAbbreviation(w, current_abbreviation++, true, false);
1383 
1384  // The context.
1385  WriteVariableAbbreviation(w, current_abbreviation++, true, false);
1386 
1387  if (total_children != 0) {
1388  w->WriteULEB128(0); // Terminate the sibling list.
1389  }
1390  }
1391 
1392  w->WriteULEB128(0); // Terminate the table.
1393  return true;
1394  }
1395 
1396  private:
1397  CodeDescription* desc_;
1398 };
1399 
1400 
1401 class DebugLineSection : public DebugSection {
1402  public:
1403  explicit DebugLineSection(CodeDescription* desc)
1404 #ifdef __ELF
1405  : ELFSection(".debug_line", TYPE_PROGBITS, 1),
1406 #else
1407  : MachOSection("__debug_line",
1408  "__DWARF",
1409  1,
1410  MachOSection::S_REGULAR | MachOSection::S_ATTR_DEBUG),
1411 #endif
1412  desc_(desc) { }
1413 
1414  // DWARF2 standard, figure 34.
1415  enum DWARF2Opcodes {
1416  DW_LNS_COPY = 1,
1417  DW_LNS_ADVANCE_PC = 2,
1418  DW_LNS_ADVANCE_LINE = 3,
1419  DW_LNS_SET_FILE = 4,
1420  DW_LNS_SET_COLUMN = 5,
1421  DW_LNS_NEGATE_STMT = 6
1422  };
1423 
1424  // DWARF2 standard, figure 35.
1425  enum DWARF2ExtendedOpcode {
1426  DW_LNE_END_SEQUENCE = 1,
1427  DW_LNE_SET_ADDRESS = 2,
1428  DW_LNE_DEFINE_FILE = 3
1429  };
1430 
1431  bool WriteBodyInternal(Writer* w) {
1432  // Write prologue.
1433  Writer::Slot<uint32_t> total_length = w->CreateSlotHere<uint32_t>();
1434  uintptr_t start = w->position();
1435 
1436  // Used for special opcodes
1437  const int8_t line_base = 1;
1438  const uint8_t line_range = 7;
1439  const int8_t max_line_incr = (line_base + line_range - 1);
1440  const uint8_t opcode_base = DW_LNS_NEGATE_STMT + 1;
1441 
1442  w->Write<uint16_t>(2); // Field version.
1443  Writer::Slot<uint32_t> prologue_length = w->CreateSlotHere<uint32_t>();
1444  uintptr_t prologue_start = w->position();
1445  w->Write<uint8_t>(1); // Field minimum_instruction_length.
1446  w->Write<uint8_t>(1); // Field default_is_stmt.
1447  w->Write<int8_t>(line_base); // Field line_base.
1448  w->Write<uint8_t>(line_range); // Field line_range.
1449  w->Write<uint8_t>(opcode_base); // Field opcode_base.
1450  w->Write<uint8_t>(0); // DW_LNS_COPY operands count.
1451  w->Write<uint8_t>(1); // DW_LNS_ADVANCE_PC operands count.
1452  w->Write<uint8_t>(1); // DW_LNS_ADVANCE_LINE operands count.
1453  w->Write<uint8_t>(1); // DW_LNS_SET_FILE operands count.
1454  w->Write<uint8_t>(1); // DW_LNS_SET_COLUMN operands count.
1455  w->Write<uint8_t>(0); // DW_LNS_NEGATE_STMT operands count.
1456  w->Write<uint8_t>(0); // Empty include_directories sequence.
1457  w->WriteString(*desc_->GetFilename()); // File name.
1458  w->WriteULEB128(0); // Current directory.
1459  w->WriteULEB128(0); // Unknown modification time.
1460  w->WriteULEB128(0); // Unknown file size.
1461  w->Write<uint8_t>(0);
1462  prologue_length.set(static_cast<uint32_t>(w->position() - prologue_start));
1463 
1464  WriteExtendedOpcode(w, DW_LNE_SET_ADDRESS, sizeof(intptr_t));
1465  w->Write<intptr_t>(desc_->CodeStart());
1466  w->Write<uint8_t>(DW_LNS_COPY);
1467 
1468  intptr_t pc = 0;
1469  intptr_t line = 1;
1470  bool is_statement = true;
1471 
1472  List<GDBJITLineInfo::PCInfo>* pc_info = desc_->lineinfo()->pc_info();
1473  pc_info->Sort(&ComparePCInfo);
1474 
1475  int pc_info_length = pc_info->length();
1476  for (int i = 0; i < pc_info_length; i++) {
1477  GDBJITLineInfo::PCInfo* info = &pc_info->at(i);
1478  ASSERT(info->pc_ >= pc);
1479 
1480  // Reduce bloating in the debug line table by removing duplicate line
1481  // entries (per DWARF2 standard).
1482  intptr_t new_line = desc_->GetScriptLineNumber(info->pos_);
1483  if (new_line == line) {
1484  continue;
1485  }
1486 
1487  // Mark statement boundaries. For a better debugging experience, mark
1488  // the last pc address in the function as a statement (e.g. "}"), so that
1489  // a user can see the result of the last line executed in the function,
1490  // should control reach the end.
1491  if ((i+1) == pc_info_length) {
1492  if (!is_statement) {
1493  w->Write<uint8_t>(DW_LNS_NEGATE_STMT);
1494  }
1495  } else if (is_statement != info->is_statement_) {
1496  w->Write<uint8_t>(DW_LNS_NEGATE_STMT);
1497  is_statement = !is_statement;
1498  }
1499 
1500  // Generate special opcodes, if possible. This results in more compact
1501  // debug line tables. See the DWARF 2.0 standard to learn more about
1502  // special opcodes.
1503  uintptr_t pc_diff = info->pc_ - pc;
1504  intptr_t line_diff = new_line - line;
1505 
1506  // Compute special opcode (see DWARF 2.0 standard)
1507  intptr_t special_opcode = (line_diff - line_base) +
1508  (line_range * pc_diff) + opcode_base;
1509 
1510  // If special_opcode is less than or equal to 255, it can be used as a
1511  // special opcode. If line_diff is larger than the max line increment
1512  // allowed for a special opcode, or if line_diff is less than the minimum
1513  // line that can be added to the line register (i.e. line_base), then
1514  // special_opcode can't be used.
1515  if ((special_opcode >= opcode_base) && (special_opcode <= 255) &&
1516  (line_diff <= max_line_incr) && (line_diff >= line_base)) {
1517  w->Write<uint8_t>(special_opcode);
1518  } else {
1519  w->Write<uint8_t>(DW_LNS_ADVANCE_PC);
1520  w->WriteSLEB128(pc_diff);
1521  w->Write<uint8_t>(DW_LNS_ADVANCE_LINE);
1522  w->WriteSLEB128(line_diff);
1523  w->Write<uint8_t>(DW_LNS_COPY);
1524  }
1525 
1526  // Increment the pc and line operands.
1527  pc += pc_diff;
1528  line += line_diff;
1529  }
1530  // Advance the pc to the end of the routine, since the end sequence opcode
1531  // requires this.
1532  w->Write<uint8_t>(DW_LNS_ADVANCE_PC);
1533  w->WriteSLEB128(desc_->CodeSize() - pc);
1534  WriteExtendedOpcode(w, DW_LNE_END_SEQUENCE, 0);
1535  total_length.set(static_cast<uint32_t>(w->position() - start));
1536  return true;
1537  }
1538 
1539  private:
1540  void WriteExtendedOpcode(Writer* w,
1541  DWARF2ExtendedOpcode op,
1542  size_t operands_size) {
1543  w->Write<uint8_t>(0);
1544  w->WriteULEB128(operands_size + 1);
1545  w->Write<uint8_t>(op);
1546  }
1547 
1548  static int ComparePCInfo(const GDBJITLineInfo::PCInfo* a,
1549  const GDBJITLineInfo::PCInfo* b) {
1550  if (a->pc_ == b->pc_) {
1551  if (a->is_statement_ != b->is_statement_) {
1552  return b->is_statement_ ? +1 : -1;
1553  }
1554  return 0;
1555  } else if (a->pc_ > b->pc_) {
1556  return +1;
1557  } else {
1558  return -1;
1559  }
1560  }
1561 
1562  CodeDescription* desc_;
1563 };
1564 
1565 
1566 #ifdef V8_TARGET_ARCH_X64
1567 
1568 class UnwindInfoSection : public DebugSection {
1569  public:
1570  explicit UnwindInfoSection(CodeDescription* desc);
1571  virtual bool WriteBodyInternal(Writer* w);
1572 
1573  int WriteCIE(Writer* w);
1574  void WriteFDE(Writer* w, int);
1575 
1576  void WriteFDEStateOnEntry(Writer* w);
1577  void WriteFDEStateAfterRBPPush(Writer* w);
1578  void WriteFDEStateAfterRBPSet(Writer* w);
1579  void WriteFDEStateAfterRBPPop(Writer* w);
1580 
1581  void WriteLength(Writer* w,
1582  Writer::Slot<uint32_t>* length_slot,
1583  int initial_position);
1584 
1585  private:
1586  CodeDescription* desc_;
1587 
1588  // DWARF3 Specification, Table 7.23
1589  enum CFIInstructions {
1590  DW_CFA_ADVANCE_LOC = 0x40,
1591  DW_CFA_OFFSET = 0x80,
1592  DW_CFA_RESTORE = 0xC0,
1593  DW_CFA_NOP = 0x00,
1594  DW_CFA_SET_LOC = 0x01,
1595  DW_CFA_ADVANCE_LOC1 = 0x02,
1596  DW_CFA_ADVANCE_LOC2 = 0x03,
1597  DW_CFA_ADVANCE_LOC4 = 0x04,
1598  DW_CFA_OFFSET_EXTENDED = 0x05,
1599  DW_CFA_RESTORE_EXTENDED = 0x06,
1600  DW_CFA_UNDEFINED = 0x07,
1601  DW_CFA_SAME_VALUE = 0x08,
1602  DW_CFA_REGISTER = 0x09,
1603  DW_CFA_REMEMBER_STATE = 0x0A,
1604  DW_CFA_RESTORE_STATE = 0x0B,
1605  DW_CFA_DEF_CFA = 0x0C,
1606  DW_CFA_DEF_CFA_REGISTER = 0x0D,
1607  DW_CFA_DEF_CFA_OFFSET = 0x0E,
1608 
1609  DW_CFA_DEF_CFA_EXPRESSION = 0x0F,
1610  DW_CFA_EXPRESSION = 0x10,
1611  DW_CFA_OFFSET_EXTENDED_SF = 0x11,
1612  DW_CFA_DEF_CFA_SF = 0x12,
1613  DW_CFA_DEF_CFA_OFFSET_SF = 0x13,
1614  DW_CFA_VAL_OFFSET = 0x14,
1615  DW_CFA_VAL_OFFSET_SF = 0x15,
1616  DW_CFA_VAL_EXPRESSION = 0x16
1617  };
1618 
1619  // System V ABI, AMD64 Supplement, Version 0.99.5, Figure 3.36
1620  enum RegisterMapping {
1621  // Only the relevant ones have been added to reduce clutter.
1622  AMD64_RBP = 6,
1623  AMD64_RSP = 7,
1624  AMD64_RA = 16
1625  };
1626 
1627  enum CFIConstants {
1628  CIE_ID = 0,
1629  CIE_VERSION = 1,
1630  CODE_ALIGN_FACTOR = 1,
1631  DATA_ALIGN_FACTOR = 1,
1632  RETURN_ADDRESS_REGISTER = AMD64_RA
1633  };
1634 };
1635 
1636 
1637 void UnwindInfoSection::WriteLength(Writer* w,
1638  Writer::Slot<uint32_t>* length_slot,
1639  int initial_position) {
1640  uint32_t align = (w->position() - initial_position) % kPointerSize;
1641 
1642  if (align != 0) {
1643  for (uint32_t i = 0; i < (kPointerSize - align); i++) {
1644  w->Write<uint8_t>(DW_CFA_NOP);
1645  }
1646  }
1647 
1648  ASSERT((w->position() - initial_position) % kPointerSize == 0);
1649  length_slot->set(w->position() - initial_position);
1650 }
1651 
1652 
1653 UnwindInfoSection::UnwindInfoSection(CodeDescription* desc)
1654 #ifdef __ELF
1655  : ELFSection(".eh_frame", TYPE_X86_64_UNWIND, 1),
1656 #else
1657  : MachOSection("__eh_frame", "__TEXT", sizeof(uintptr_t),
1658  MachOSection::S_REGULAR),
1659 #endif
1660  desc_(desc) { }
1661 
1662 int UnwindInfoSection::WriteCIE(Writer* w) {
1663  Writer::Slot<uint32_t> cie_length_slot = w->CreateSlotHere<uint32_t>();
1664  uint32_t cie_position = w->position();
1665 
1666  // Write out the CIE header. Currently no 'common instructions' are
1667  // emitted onto the CIE; every FDE has its own set of instructions.
1668 
1669  w->Write<uint32_t>(CIE_ID);
1670  w->Write<uint8_t>(CIE_VERSION);
1671  w->Write<uint8_t>(0); // Null augmentation string.
1672  w->WriteSLEB128(CODE_ALIGN_FACTOR);
1673  w->WriteSLEB128(DATA_ALIGN_FACTOR);
1674  w->Write<uint8_t>(RETURN_ADDRESS_REGISTER);
1675 
1676  WriteLength(w, &cie_length_slot, cie_position);
1677 
1678  return cie_position;
1679 }
1680 
1681 
1682 void UnwindInfoSection::WriteFDE(Writer* w, int cie_position) {
1683  // The only FDE for this function. The CFA is the current RBP.
1684  Writer::Slot<uint32_t> fde_length_slot = w->CreateSlotHere<uint32_t>();
1685  int fde_position = w->position();
1686  w->Write<int32_t>(fde_position - cie_position + 4);
1687 
1688  w->Write<uintptr_t>(desc_->CodeStart());
1689  w->Write<uintptr_t>(desc_->CodeSize());
1690 
1691  WriteFDEStateOnEntry(w);
1692  WriteFDEStateAfterRBPPush(w);
1693  WriteFDEStateAfterRBPSet(w);
1694  WriteFDEStateAfterRBPPop(w);
1695 
1696  WriteLength(w, &fde_length_slot, fde_position);
1697 }
1698 
1699 
1700 void UnwindInfoSection::WriteFDEStateOnEntry(Writer* w) {
1701  // The first state, just after the control has been transferred to the the
1702  // function.
1703 
1704  // RBP for this function will be the value of RSP after pushing the RBP
1705  // for the previous function. The previous RBP has not been pushed yet.
1706  w->Write<uint8_t>(DW_CFA_DEF_CFA_SF);
1707  w->WriteULEB128(AMD64_RSP);
1708  w->WriteSLEB128(-kPointerSize);
1709 
1710  // The RA is stored at location CFA + kCallerPCOffset. This is an invariant,
1711  // and hence omitted from the next states.
1712  w->Write<uint8_t>(DW_CFA_OFFSET_EXTENDED);
1713  w->WriteULEB128(AMD64_RA);
1714  w->WriteSLEB128(StandardFrameConstants::kCallerPCOffset);
1715 
1716  // The RBP of the previous function is still in RBP.
1717  w->Write<uint8_t>(DW_CFA_SAME_VALUE);
1718  w->WriteULEB128(AMD64_RBP);
1719 
1720  // Last location described by this entry.
1721  w->Write<uint8_t>(DW_CFA_SET_LOC);
1722  w->Write<uint64_t>(
1723  desc_->GetStackStateStartAddress(CodeDescription::POST_RBP_PUSH));
1724 }
1725 
1726 
1727 void UnwindInfoSection::WriteFDEStateAfterRBPPush(Writer* w) {
1728  // The second state, just after RBP has been pushed.
1729 
1730  // RBP / CFA for this function is now the current RSP, so just set the
1731  // offset from the previous rule (from -8) to 0.
1732  w->Write<uint8_t>(DW_CFA_DEF_CFA_OFFSET);
1733  w->WriteULEB128(0);
1734 
1735  // The previous RBP is stored at CFA + kCallerFPOffset. This is an invariant
1736  // in this and the next state, and hence omitted in the next state.
1737  w->Write<uint8_t>(DW_CFA_OFFSET_EXTENDED);
1738  w->WriteULEB128(AMD64_RBP);
1739  w->WriteSLEB128(StandardFrameConstants::kCallerFPOffset);
1740 
1741  // Last location described by this entry.
1742  w->Write<uint8_t>(DW_CFA_SET_LOC);
1743  w->Write<uint64_t>(
1744  desc_->GetStackStateStartAddress(CodeDescription::POST_RBP_SET));
1745 }
1746 
1747 
1748 void UnwindInfoSection::WriteFDEStateAfterRBPSet(Writer* w) {
1749  // The third state, after the RBP has been set.
1750 
1751  // The CFA can now directly be set to RBP.
1752  w->Write<uint8_t>(DW_CFA_DEF_CFA);
1753  w->WriteULEB128(AMD64_RBP);
1754  w->WriteULEB128(0);
1755 
1756  // Last location described by this entry.
1757  w->Write<uint8_t>(DW_CFA_SET_LOC);
1758  w->Write<uint64_t>(
1759  desc_->GetStackStateStartAddress(CodeDescription::POST_RBP_POP));
1760 }
1761 
1762 
1763 void UnwindInfoSection::WriteFDEStateAfterRBPPop(Writer* w) {
1764  // The fourth (final) state. The RBP has been popped (just before issuing a
1765  // return).
1766 
1767  // The CFA can is now calculated in the same way as in the first state.
1768  w->Write<uint8_t>(DW_CFA_DEF_CFA_SF);
1769  w->WriteULEB128(AMD64_RSP);
1770  w->WriteSLEB128(-kPointerSize);
1771 
1772  // The RBP
1773  w->Write<uint8_t>(DW_CFA_OFFSET_EXTENDED);
1774  w->WriteULEB128(AMD64_RBP);
1775  w->WriteSLEB128(StandardFrameConstants::kCallerFPOffset);
1776 
1777  // Last location described by this entry.
1778  w->Write<uint8_t>(DW_CFA_SET_LOC);
1779  w->Write<uint64_t>(desc_->CodeEnd());
1780 }
1781 
1782 
1783 bool UnwindInfoSection::WriteBodyInternal(Writer* w) {
1784  uint32_t cie_position = WriteCIE(w);
1785  WriteFDE(w, cie_position);
1786  return true;
1787 }
1788 
1789 
1790 #endif // V8_TARGET_ARCH_X64
1791 
1792 static void CreateDWARFSections(CodeDescription* desc, DebugObject* obj) {
1793  Zone* zone = desc->info()->zone();
1794  if (desc->IsLineInfoAvailable()) {
1795  obj->AddSection(new(zone) DebugInfoSection(desc), zone);
1796  obj->AddSection(new(zone) DebugAbbrevSection(desc), zone);
1797  obj->AddSection(new(zone) DebugLineSection(desc), zone);
1798  }
1799 #ifdef V8_TARGET_ARCH_X64
1800  obj->AddSection(new(zone) UnwindInfoSection(desc), zone);
1801 #endif
1802 }
1803 
1804 
1805 // -------------------------------------------------------------------
1806 // Binary GDB JIT Interface as described in
1807 // http://sourceware.org/gdb/onlinedocs/gdb/Declarations.html
1808 extern "C" {
1809  typedef enum {
1810  JIT_NOACTION = 0,
1811  JIT_REGISTER_FN,
1812  JIT_UNREGISTER_FN
1813  } JITAction;
1814 
1815  struct JITCodeEntry {
1816  JITCodeEntry* next_;
1817  JITCodeEntry* prev_;
1818  Address symfile_addr_;
1819  uint64_t symfile_size_;
1820  };
1821 
1822  struct JITDescriptor {
1823  uint32_t version_;
1824  uint32_t action_flag_;
1825  JITCodeEntry* relevant_entry_;
1826  JITCodeEntry* first_entry_;
1827  };
1828 
1829  // GDB will place breakpoint into this function.
1830  // To prevent GCC from inlining or removing it we place noinline attribute
1831  // and inline assembler statement inside.
1832  void __attribute__((noinline)) __jit_debug_register_code() {
1833  __asm__("");
1834  }
1835 
1836  // GDB will inspect contents of this descriptor.
1837  // Static initialization is necessary to prevent GDB from seeing
1838  // uninitialized descriptor.
1839  JITDescriptor __jit_debug_descriptor = { 1, 0, 0, 0 };
1840 
1841 #ifdef OBJECT_PRINT
1842  void __gdb_print_v8_object(MaybeObject* object) {
1843  object->Print();
1844  fprintf(stdout, "\n");
1845  }
1846 #endif
1847 }
1848 
1849 
1850 static JITCodeEntry* CreateCodeEntry(Address symfile_addr,
1851  uintptr_t symfile_size) {
1852  JITCodeEntry* entry = static_cast<JITCodeEntry*>(
1853  malloc(sizeof(JITCodeEntry) + symfile_size));
1854 
1855  entry->symfile_addr_ = reinterpret_cast<Address>(entry + 1);
1856  entry->symfile_size_ = symfile_size;
1857  memcpy(entry->symfile_addr_, symfile_addr, symfile_size);
1858 
1859  entry->prev_ = entry->next_ = NULL;
1860 
1861  return entry;
1862 }
1863 
1864 
1865 static void DestroyCodeEntry(JITCodeEntry* entry) {
1866  free(entry);
1867 }
1868 
1869 
1870 static void RegisterCodeEntry(JITCodeEntry* entry,
1871  bool dump_if_enabled,
1872  const char* name_hint) {
1873 #if defined(DEBUG) && !defined(WIN32)
1874  static int file_num = 0;
1875  if (FLAG_gdbjit_dump && dump_if_enabled) {
1876  static const int kMaxFileNameSize = 64;
1877  static const char* kElfFilePrefix = "/tmp/elfdump";
1878  static const char* kObjFileExt = ".o";
1879  char file_name[64];
1880 
1881  OS::SNPrintF(Vector<char>(file_name, kMaxFileNameSize),
1882  "%s%s%d%s",
1883  kElfFilePrefix,
1884  (name_hint != NULL) ? name_hint : "",
1885  file_num++,
1886  kObjFileExt);
1887  WriteBytes(file_name, entry->symfile_addr_, entry->symfile_size_);
1888  }
1889 #endif
1890 
1891  entry->next_ = __jit_debug_descriptor.first_entry_;
1892  if (entry->next_ != NULL) entry->next_->prev_ = entry;
1893  __jit_debug_descriptor.first_entry_ =
1894  __jit_debug_descriptor.relevant_entry_ = entry;
1895 
1896  __jit_debug_descriptor.action_flag_ = JIT_REGISTER_FN;
1897  __jit_debug_register_code();
1898 }
1899 
1900 
1901 static void UnregisterCodeEntry(JITCodeEntry* entry) {
1902  if (entry->prev_ != NULL) {
1903  entry->prev_->next_ = entry->next_;
1904  } else {
1905  __jit_debug_descriptor.first_entry_ = entry->next_;
1906  }
1907 
1908  if (entry->next_ != NULL) {
1909  entry->next_->prev_ = entry->prev_;
1910  }
1911 
1912  __jit_debug_descriptor.relevant_entry_ = entry;
1913  __jit_debug_descriptor.action_flag_ = JIT_UNREGISTER_FN;
1914  __jit_debug_register_code();
1915 }
1916 
1917 
1918 static JITCodeEntry* CreateELFObject(CodeDescription* desc) {
1919  Zone* zone = desc->info()->zone();
1920  ZoneScope zone_scope(zone, DELETE_ON_EXIT);
1921 #ifdef __MACH_O
1922  MachO mach_o;
1923  Writer w(&mach_o);
1924 
1925  mach_o.AddSection(new MachOTextSection(kCodeAlignment,
1926  desc->CodeStart(),
1927  desc->CodeSize()));
1928 
1929  CreateDWARFSections(desc, &mach_o);
1930 
1931  mach_o.Write(&w, desc->CodeStart(), desc->CodeSize());
1932 #else
1933  ELF elf(zone);
1934  Writer w(&elf);
1935 
1936  int text_section_index = elf.AddSection(
1937  new(zone) FullHeaderELFSection(
1938  ".text",
1939  ELFSection::TYPE_NOBITS,
1941  desc->CodeStart(),
1942  0,
1943  desc->CodeSize(),
1944  ELFSection::FLAG_ALLOC | ELFSection::FLAG_EXEC),
1945  zone);
1946 
1947  CreateSymbolsTable(desc, &elf, text_section_index);
1948 
1949  CreateDWARFSections(desc, &elf);
1950 
1951  elf.Write(&w);
1952 #endif
1953 
1954  return CreateCodeEntry(w.buffer(), w.position());
1955 }
1956 
1957 
1958 static bool SameCodeObjects(void* key1, void* key2) {
1959  return key1 == key2;
1960 }
1961 
1962 
1963 static HashMap* GetEntries() {
1964  static HashMap* entries = NULL;
1965  if (entries == NULL) {
1966  entries = new HashMap(&SameCodeObjects);
1967  }
1968  return entries;
1969 }
1970 
1971 
1972 static uint32_t HashForCodeObject(Code* code) {
1973  static const uintptr_t kGoldenRatio = 2654435761u;
1974  uintptr_t hash = reinterpret_cast<uintptr_t>(code->address());
1975  return static_cast<uint32_t>((hash >> kCodeAlignmentBits) * kGoldenRatio);
1976 }
1977 
1978 
1979 static const intptr_t kLineInfoTag = 0x1;
1980 
1981 
1982 static bool IsLineInfoTagged(void* ptr) {
1983  return 0 != (reinterpret_cast<intptr_t>(ptr) & kLineInfoTag);
1984 }
1985 
1986 
1987 static void* TagLineInfo(GDBJITLineInfo* ptr) {
1988  return reinterpret_cast<void*>(
1989  reinterpret_cast<intptr_t>(ptr) | kLineInfoTag);
1990 }
1991 
1992 
1993 static GDBJITLineInfo* UntagLineInfo(void* ptr) {
1994  return reinterpret_cast<GDBJITLineInfo*>(
1995  reinterpret_cast<intptr_t>(ptr) & ~kLineInfoTag);
1996 }
1997 
1998 
1999 void GDBJITInterface::AddCode(Handle<String> name,
2000  Handle<Script> script,
2001  Handle<Code> code,
2002  CompilationInfo* info) {
2003  if (!FLAG_gdbjit) return;
2004 
2005  // Force initialization of line_ends array.
2006  GetScriptLineNumber(script, 0);
2007 
2008  if (!name.is_null()) {
2009  SmartArrayPointer<char> name_cstring = name->ToCString(DISALLOW_NULLS);
2010  AddCode(*name_cstring, *code, GDBJITInterface::FUNCTION, *script, info);
2011  } else {
2012  AddCode("", *code, GDBJITInterface::FUNCTION, *script, info);
2013  }
2014 }
2015 
2016 static void AddUnwindInfo(CodeDescription* desc) {
2017 #ifdef V8_TARGET_ARCH_X64
2018  if (desc->tag() == GDBJITInterface::FUNCTION) {
2019  // To avoid propagating unwinding information through
2020  // compilation pipeline we use an approximation.
2021  // For most use cases this should not affect usability.
2022  static const int kFramePointerPushOffset = 1;
2023  static const int kFramePointerSetOffset = 4;
2024  static const int kFramePointerPopOffset = -3;
2025 
2026  uintptr_t frame_pointer_push_address =
2027  desc->CodeStart() + kFramePointerPushOffset;
2028 
2029  uintptr_t frame_pointer_set_address =
2030  desc->CodeStart() + kFramePointerSetOffset;
2031 
2032  uintptr_t frame_pointer_pop_address =
2033  desc->CodeEnd() + kFramePointerPopOffset;
2034 
2035  desc->SetStackStateStartAddress(CodeDescription::POST_RBP_PUSH,
2036  frame_pointer_push_address);
2037  desc->SetStackStateStartAddress(CodeDescription::POST_RBP_SET,
2038  frame_pointer_set_address);
2039  desc->SetStackStateStartAddress(CodeDescription::POST_RBP_POP,
2040  frame_pointer_pop_address);
2041  } else {
2042  desc->SetStackStateStartAddress(CodeDescription::POST_RBP_PUSH,
2043  desc->CodeStart());
2044  desc->SetStackStateStartAddress(CodeDescription::POST_RBP_SET,
2045  desc->CodeStart());
2046  desc->SetStackStateStartAddress(CodeDescription::POST_RBP_POP,
2047  desc->CodeEnd());
2048  }
2049 #endif // V8_TARGET_ARCH_X64
2050 }
2051 
2052 
2053 static LazyMutex mutex = LAZY_MUTEX_INITIALIZER;
2054 
2055 
2056 void GDBJITInterface::AddCode(const char* name,
2057  Code* code,
2058  GDBJITInterface::CodeTag tag,
2059  Script* script,
2060  CompilationInfo* info) {
2061  if (!FLAG_gdbjit) return;
2062 
2063  ScopedLock lock(mutex.Pointer());
2064  AssertNoAllocation no_gc;
2065 
2066  HashMap::Entry* e = GetEntries()->Lookup(code, HashForCodeObject(code), true);
2067  if (e->value != NULL && !IsLineInfoTagged(e->value)) return;
2068 
2069  GDBJITLineInfo* lineinfo = UntagLineInfo(e->value);
2070  CodeDescription code_desc(name,
2071  code,
2072  script != NULL ? Handle<Script>(script)
2073  : Handle<Script>(),
2074  lineinfo,
2075  tag,
2076  info);
2077 
2078  if (!FLAG_gdbjit_full && !code_desc.IsLineInfoAvailable()) {
2079  delete lineinfo;
2080  GetEntries()->Remove(code, HashForCodeObject(code));
2081  return;
2082  }
2083 
2084  AddUnwindInfo(&code_desc);
2085  JITCodeEntry* entry = CreateELFObject(&code_desc);
2086  ASSERT(!IsLineInfoTagged(entry));
2087 
2088  delete lineinfo;
2089  e->value = entry;
2090 
2091  const char* name_hint = NULL;
2092  bool should_dump = false;
2093  if (FLAG_gdbjit_dump) {
2094  if (strlen(FLAG_gdbjit_dump_filter) == 0) {
2095  name_hint = name;
2096  should_dump = true;
2097  } else if (name != NULL) {
2098  name_hint = strstr(name, FLAG_gdbjit_dump_filter);
2099  should_dump = (name_hint != NULL);
2100  }
2101  }
2102  RegisterCodeEntry(entry, should_dump, name_hint);
2103 }
2104 
2105 
2106 void GDBJITInterface::AddCode(GDBJITInterface::CodeTag tag,
2107  const char* name,
2108  Code* code) {
2109  if (!FLAG_gdbjit) return;
2110 
2111  EmbeddedVector<char, 256> buffer;
2112  StringBuilder builder(buffer.start(), buffer.length());
2113 
2114  builder.AddString(Tag2String(tag));
2115  if ((name != NULL) && (*name != '\0')) {
2116  builder.AddString(": ");
2117  builder.AddString(name);
2118  } else {
2119  builder.AddFormatted(": code object %p", static_cast<void*>(code));
2120  }
2121 
2122  AddCode(builder.Finalize(), code, tag, NULL, NULL);
2123 }
2124 
2125 
2126 void GDBJITInterface::AddCode(GDBJITInterface::CodeTag tag,
2127  String* name,
2128  Code* code) {
2129  if (!FLAG_gdbjit) return;
2130  AddCode(tag, name != NULL ? *name->ToCString(DISALLOW_NULLS) : NULL, code);
2131 }
2132 
2133 
2134 void GDBJITInterface::AddCode(GDBJITInterface::CodeTag tag, Code* code) {
2135  if (!FLAG_gdbjit) return;
2136 
2137  AddCode(tag, "", code);
2138 }
2139 
2140 
2141 void GDBJITInterface::RemoveCode(Code* code) {
2142  if (!FLAG_gdbjit) return;
2143 
2144  ScopedLock lock(mutex.Pointer());
2145  HashMap::Entry* e = GetEntries()->Lookup(code,
2146  HashForCodeObject(code),
2147  false);
2148  if (e == NULL) return;
2149 
2150  if (IsLineInfoTagged(e->value)) {
2151  delete UntagLineInfo(e->value);
2152  } else {
2153  JITCodeEntry* entry = static_cast<JITCodeEntry*>(e->value);
2154  UnregisterCodeEntry(entry);
2155  DestroyCodeEntry(entry);
2156  }
2157  e->value = NULL;
2158  GetEntries()->Remove(code, HashForCodeObject(code));
2159 }
2160 
2161 
2162 void GDBJITInterface::RegisterDetailedLineInfo(Code* code,
2163  GDBJITLineInfo* line_info) {
2164  ScopedLock lock(mutex.Pointer());
2165  ASSERT(!IsLineInfoTagged(line_info));
2166  HashMap::Entry* e = GetEntries()->Lookup(code, HashForCodeObject(code), true);
2167  ASSERT(e->value == NULL);
2168  e->value = TagLineInfo(line_info);
2169 }
2170 
2171 
2172 } } // namespace v8::internal
2173 #endif
byte * Address
Definition: globals.h:157
const char * ToCString(const v8::String::Utf8Value &value)
static String * cast(Object *obj)
int int32_t
Definition: unicode.cc:47
#define ASSERT(condition)
Definition: checks.h:270
LinuxKernelCmpxchgFunc pLinuxKernelCmpxchg __attribute__((weak))
unsigned short uint16_t
Definition: unicode.cc:46
const intptr_t kCodeAlignment
Definition: v8globals.h:58
StringInputBuffer *const buffer_
int WhichPowerOf2(uint32_t x)
Definition: utils.h:56
uint8_t byte
Definition: globals.h:156
const int kPointerSize
Definition: globals.h:220
const Register pc
int GetScriptLineNumberSafe(Handle< Script > script, int code_pos)
Definition: handles.cc:517
bool IsPowerOf2(T x)
Definition: utils.h:50
#define BASE_EMBEDDED
Definition: allocation.h:68
LazyDynamicInstance< Mutex, CreateMutexTrait, ThreadSafeInitOnceTrait >::type LazyMutex
Definition: platform.h:583
#define T(name, string, precedence)
Definition: token.cc:48
static int SNPrintF(Vector< char > str, const char *format,...)
int GetScriptLineNumber(Handle< Script > script, int code_pos)
Definition: handles.cc:479
#define UNIMPLEMENTED()
Definition: checks.h:48
const int kCodeAlignmentBits
Definition: v8globals.h:57
TemplateHashMapImpl< FreeStoreAllocationPolicy > HashMap
Definition: hashmap.h:113
activate correct semantics for inheriting readonliness enable harmony semantics for typeof enable harmony enable harmony proxies enable all harmony harmony_scoping harmony_proxies harmony_scoping tracks arrays with only smi values automatically unbox arrays of doubles use crankshaft use hydrogen range analysis use hydrogen global value numbering use function inlining maximum number of AST nodes considered for a single inlining loop invariant code motion print statistics for hydrogen trace generated IR for specified phases trace register allocator trace range analysis trace representation types environment for every instruction put a break point before deoptimizing polymorphic inlining perform array bounds checks elimination use dead code elimination trace on stack replacement optimize closures cache optimized code for closures functions with arguments object loop weight for representation inference allow uint32 values on optimize frames if they are used only in safe operations track parallel recompilation enable all profiler experiments number of stack frames inspected by the profiler call recompile stub directly when self optimizing trigger profiler ticks based on counting instead of timing weight back edges by jump distance for interrupt triggering percentage of ICs that must have type info to allow optimization watch_ic_patching retry_self_opt interrupt_at_exit 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 SAHF instruction if enable use of VFP3 instructions if available this implies enabling ARMv7 and VFP2 enable use of VFP2 instructions if available 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 MIPS FPU instructions if NULL
Definition: flags.cc:301
int WriteBytes(const char *filename, const byte *bytes, int size, bool verbose)
Definition: v8utils.cc:248
activate correct semantics for inheriting readonliness enable harmony semantics for typeof enable harmony enable harmony proxies enable all harmony harmony_scoping harmony_proxies harmony_scoping tracks arrays with only smi values automatically unbox arrays of doubles use crankshaft use hydrogen range analysis use hydrogen global value numbering use function inlining maximum number of AST nodes considered for a single inlining loop invariant code motion print statistics for hydrogen trace generated IR for specified phases trace register allocator trace range analysis trace representation types environment for every instruction put a break point before deoptimizing polymorphic inlining perform array bounds checks elimination use dead code elimination trace on stack replacement optimize closures cache optimized code for closures functions with arguments object loop weight for representation inference allow uint32 values on optimize frames if they are used only in safe operations track parallel recompilation enable all profiler experiments number of stack frames inspected by the profiler call recompile stub directly when self optimizing trigger profiler ticks based on counting instead of timing weight back edges by jump distance for interrupt triggering percentage of ICs that must have type info to allow optimization watch_ic_patching retry_self_opt interrupt_at_exit extra verbose compilation tracing generate extra code(assertions) for debugging") DEFINE_bool(code_comments
activate correct semantics for inheriting readonliness enable harmony semantics for typeof enable harmony enable harmony proxies enable all harmony harmony_scoping harmony_proxies harmony_scoping tracks arrays with only smi values automatically unbox arrays of doubles use crankshaft use hydrogen range analysis use hydrogen global value numbering use function inlining maximum number of AST nodes considered for a single inlining loop invariant code motion print statistics for hydrogen trace generated IR for specified phases trace register allocator trace range analysis trace representation types environment for every instruction put a break point before deoptimizing polymorphic inlining perform array bounds checks elimination use dead code elimination trace on stack replacement optimize closures cache optimized code for closures functions with arguments object loop weight for representation inference allow uint32 values on optimize frames if they are used only in safe operations track parallel recompilation enable all profiler experiments number of stack frames inspected by the profiler call recompile stub directly when self optimizing trigger profiler ticks based on counting instead of timing weight back edges by jump distance for interrupt triggering percentage of ICs that must have type info to allow optimization watch_ic_patching retry_self_opt interrupt_at_exit 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 SAHF instruction if enable use of VFP3 instructions if available this implies enabling ARMv7 and VFP2 enable use of VFP2 instructions if available 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 MIPS FPU instructions if expose natives in global object expose gc extension number of stack frames to capture disable builtin natives files print a stack trace if an assertion failure occurs use random jit cookie to mask large constants trace lazy optimization use adaptive optimizations prepare for turning on always opt minimum length for automatic enable preparsing maximum number of optimization attempts before giving up cache prototype transitions automatically set the debug break flag when debugger commands are in the queue always cause a debug break before aborting 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 more details following each garbage collection print amount of external allocated memory after each time it is adjusted flush code that we expect not to use again before full gc do incremental marking steps track object counts and memory usage use caching Perform compaction on every full GC Never perform compaction on full GC testing only Compact code space on full incremental collections Default seed for initializing random allows verbose printing trace parsing and preparsing Check icache flushes in ARM and MIPS simulator Stack alingment in bytes in print stack trace when throwing exceptions randomize hashes to avoid predictable hash Fixed seed to use to hash property activate a timer that switches between V8 threads testing_bool_flag float flag Seed used for threading test randomness A filename with extra code to be included in the Print usage including flags
Definition: flags.cc:495
#define LAZY_MUTEX_INITIALIZER
Definition: platform.h:585