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