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