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