blob: 68cb0533b8e3695eceebc634e0a209a14fc106fb [file] [log] [blame]
Ben Murdochb8e0da22011-05-16 14:20:40 +01001// Copyright 2010 the V8 project authors. All rights reserved.
2// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#ifdef ENABLE_GDB_JIT_INTERFACE
Steve Block44f0eee2011-05-26 01:26:41 +010029#include "v8.h"
Ben Murdochb8e0da22011-05-16 14:20:40 +010030#include "gdb-jit.h"
31
32#include "bootstrapper.h"
33#include "compiler.h"
34#include "global-handles.h"
35#include "messages.h"
36#include "natives.h"
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000037#include "scopeinfo.h"
Ben Murdochb8e0da22011-05-16 14:20:40 +010038
39namespace v8 {
40namespace internal {
41
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000042#ifdef __APPLE__
43#define __MACH_O
44class MachO;
45class MachOSection;
46typedef MachO DebugObject;
47typedef MachOSection DebugSection;
48#else
49#define __ELF
Ben Murdochb8e0da22011-05-16 14:20:40 +010050class ELF;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000051class ELFSection;
52typedef ELF DebugObject;
53typedef ELFSection DebugSection;
54#endif
Ben Murdochb8e0da22011-05-16 14:20:40 +010055
56class Writer BASE_EMBEDDED {
57 public:
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000058 explicit Writer(DebugObject* debug_object)
59 : debug_object_(debug_object),
Ben Murdochb8e0da22011-05-16 14:20:40 +010060 position_(0),
61 capacity_(1024),
62 buffer_(reinterpret_cast<byte*>(malloc(capacity_))) {
63 }
64
65 ~Writer() {
66 free(buffer_);
67 }
68
69 uintptr_t position() const {
70 return position_;
71 }
72
73 template<typename T>
74 class Slot {
75 public:
76 Slot(Writer* w, uintptr_t offset) : w_(w), offset_(offset) { }
77
78 T* operator-> () {
79 return w_->RawSlotAt<T>(offset_);
80 }
81
82 void set(const T& value) {
83 *w_->RawSlotAt<T>(offset_) = value;
84 }
85
86 Slot<T> at(int i) {
87 return Slot<T>(w_, offset_ + sizeof(T) * i);
88 }
89
90 private:
91 Writer* w_;
92 uintptr_t offset_;
93 };
94
95 template<typename T>
96 void Write(const T& val) {
97 Ensure(position_ + sizeof(T));
98 *RawSlotAt<T>(position_) = val;
99 position_ += sizeof(T);
100 }
101
102 template<typename T>
103 Slot<T> SlotAt(uintptr_t offset) {
104 Ensure(offset + sizeof(T));
105 return Slot<T>(this, offset);
106 }
107
108 template<typename T>
109 Slot<T> CreateSlotHere() {
110 return CreateSlotsHere<T>(1);
111 }
112
113 template<typename T>
114 Slot<T> CreateSlotsHere(uint32_t count) {
115 uintptr_t slot_position = position_;
116 position_ += sizeof(T) * count;
117 Ensure(position_);
118 return SlotAt<T>(slot_position);
119 }
120
121 void Ensure(uintptr_t pos) {
122 if (capacity_ < pos) {
123 while (capacity_ < pos) capacity_ *= 2;
124 buffer_ = reinterpret_cast<byte*>(realloc(buffer_, capacity_));
125 }
126 }
127
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000128 DebugObject* debug_object() { return debug_object_; }
Ben Murdochb8e0da22011-05-16 14:20:40 +0100129
130 byte* buffer() { return buffer_; }
131
132 void Align(uintptr_t align) {
133 uintptr_t delta = position_ % align;
134 if (delta == 0) return;
135 uintptr_t padding = align - delta;
136 Ensure(position_ += padding);
137 ASSERT((position_ % align) == 0);
138 }
139
140 void WriteULEB128(uintptr_t value) {
141 do {
142 uint8_t byte = value & 0x7F;
143 value >>= 7;
144 if (value != 0) byte |= 0x80;
145 Write<uint8_t>(byte);
146 } while (value != 0);
147 }
148
149 void WriteSLEB128(intptr_t value) {
150 bool more = true;
151 while (more) {
152 int8_t byte = value & 0x7F;
153 bool byte_sign = byte & 0x40;
154 value >>= 7;
155
156 if ((value == 0 && !byte_sign) || (value == -1 && byte_sign)) {
157 more = false;
158 } else {
159 byte |= 0x80;
160 }
161
162 Write<int8_t>(byte);
163 }
164 }
165
166 void WriteString(const char* str) {
167 do {
168 Write<char>(*str);
169 } while (*str++);
170 }
171
172 private:
173 template<typename T> friend class Slot;
174
175 template<typename T>
176 T* RawSlotAt(uintptr_t offset) {
177 ASSERT(offset < capacity_ && offset + sizeof(T) <= capacity_);
178 return reinterpret_cast<T*>(&buffer_[offset]);
179 }
180
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000181 DebugObject* debug_object_;
Ben Murdochb8e0da22011-05-16 14:20:40 +0100182 uintptr_t position_;
183 uintptr_t capacity_;
184 byte* buffer_;
185};
186
187class StringTable;
188
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000189template<typename THeader>
190class DebugSectionBase : public ZoneObject {
Ben Murdochb8e0da22011-05-16 14:20:40 +0100191 public:
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000192 virtual ~DebugSectionBase() { }
193
194 virtual void WriteBody(Writer::Slot<THeader> header, Writer* writer) {
195 uintptr_t start = writer->position();
196 if (WriteBody(writer)) {
197 uintptr_t end = writer->position();
198 header->offset = start;
199#if defined(__MACH_O)
200 header->addr = 0;
201#endif
202 header->size = end - start;
203 }
204 }
205
206 virtual bool WriteBody(Writer* writer) {
207 return false;
208 }
209
210 typedef THeader Header;
211};
212
213
214struct MachOSectionHeader {
215 char sectname[16];
216 char segname[16];
217#if defined(V8_TARGET_ARCH_IA32)
218 uint32_t addr;
219 uint32_t size;
220#else
221 uint64_t addr;
222 uint64_t size;
223#endif
224 uint32_t offset;
225 uint32_t align;
226 uint32_t reloff;
227 uint32_t nreloc;
228 uint32_t flags;
229 uint32_t reserved1;
230 uint32_t reserved2;
231};
232
233
234class MachOSection : public DebugSectionBase<MachOSectionHeader> {
235 public:
236 enum Type {
237 S_REGULAR = 0x0u,
238 S_ATTR_COALESCED = 0xbu,
239 S_ATTR_SOME_INSTRUCTIONS = 0x400u,
240 S_ATTR_DEBUG = 0x02000000u,
241 S_ATTR_PURE_INSTRUCTIONS = 0x80000000u
Ben Murdochb8e0da22011-05-16 14:20:40 +0100242 };
243
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000244 MachOSection(const char* name,
245 const char* segment,
246 uintptr_t align,
247 uint32_t flags)
248 : name_(name),
249 segment_(segment),
250 align_(align),
251 flags_(flags) {
252 ASSERT(IsPowerOf2(align));
253 if (align_ != 0) {
254 align_ = WhichPowerOf2(align_);
255 }
256 }
257
258 virtual ~MachOSection() { }
259
260 virtual void PopulateHeader(Writer::Slot<Header> header) {
261 header->addr = 0;
262 header->size = 0;
263 header->offset = 0;
264 header->align = align_;
265 header->reloff = 0;
266 header->nreloc = 0;
267 header->flags = flags_;
268 header->reserved1 = 0;
269 header->reserved2 = 0;
270 memset(header->sectname, 0, sizeof(header->sectname));
271 memset(header->segname, 0, sizeof(header->segname));
272 ASSERT(strlen(name_) < sizeof(header->sectname));
273 ASSERT(strlen(segment_) < sizeof(header->segname));
274 strncpy(header->sectname, name_, sizeof(header->sectname));
275 strncpy(header->segname, segment_, sizeof(header->segname));
276 }
277
278 private:
279 const char* name_;
280 const char* segment_;
281 uintptr_t align_;
282 uint32_t flags_;
283};
284
285
286struct ELFSectionHeader {
287 uint32_t name;
288 uint32_t type;
289 uintptr_t flags;
290 uintptr_t address;
291 uintptr_t offset;
292 uintptr_t size;
293 uint32_t link;
294 uint32_t info;
295 uintptr_t alignment;
296 uintptr_t entry_size;
297};
298
299
300#if defined(__ELF)
301class ELFSection : public DebugSectionBase<ELFSectionHeader> {
302 public:
Ben Murdochb8e0da22011-05-16 14:20:40 +0100303 enum Type {
304 TYPE_NULL = 0,
305 TYPE_PROGBITS = 1,
306 TYPE_SYMTAB = 2,
307 TYPE_STRTAB = 3,
308 TYPE_RELA = 4,
309 TYPE_HASH = 5,
310 TYPE_DYNAMIC = 6,
311 TYPE_NOTE = 7,
312 TYPE_NOBITS = 8,
313 TYPE_REL = 9,
314 TYPE_SHLIB = 10,
315 TYPE_DYNSYM = 11,
316 TYPE_LOPROC = 0x70000000,
Steve Block1e0659c2011-05-24 12:43:12 +0100317 TYPE_X86_64_UNWIND = 0x70000001,
Ben Murdochb8e0da22011-05-16 14:20:40 +0100318 TYPE_HIPROC = 0x7fffffff,
319 TYPE_LOUSER = 0x80000000,
320 TYPE_HIUSER = 0xffffffff
321 };
322
323 enum Flags {
324 FLAG_WRITE = 1,
325 FLAG_ALLOC = 2,
326 FLAG_EXEC = 4
327 };
328
329 enum SpecialIndexes {
330 INDEX_ABSOLUTE = 0xfff1
331 };
332
333 ELFSection(const char* name, Type type, uintptr_t align)
334 : name_(name), type_(type), align_(align) { }
335
336 virtual ~ELFSection() { }
337
338 void PopulateHeader(Writer::Slot<Header> header, StringTable* strtab);
339
340 virtual void WriteBody(Writer::Slot<Header> header, Writer* w) {
341 uintptr_t start = w->position();
342 if (WriteBody(w)) {
343 uintptr_t end = w->position();
344 header->offset = start;
345 header->size = end - start;
346 }
347 }
348
349 virtual bool WriteBody(Writer* w) {
350 return false;
351 }
352
353 uint16_t index() const { return index_; }
354 void set_index(uint16_t index) { index_ = index; }
355
356 protected:
357 virtual void PopulateHeader(Writer::Slot<Header> header) {
358 header->flags = 0;
359 header->address = 0;
360 header->offset = 0;
361 header->size = 0;
362 header->link = 0;
363 header->info = 0;
364 header->entry_size = 0;
365 }
366
Ben Murdochb8e0da22011-05-16 14:20:40 +0100367 private:
368 const char* name_;
369 Type type_;
370 uintptr_t align_;
371 uint16_t index_;
372};
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000373#endif // defined(__ELF)
Ben Murdochb8e0da22011-05-16 14:20:40 +0100374
375
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000376#if defined(__MACH_O)
377class MachOTextSection : public MachOSection {
378 public:
379 MachOTextSection(uintptr_t align,
380 uintptr_t addr,
381 uintptr_t size)
382 : MachOSection("__text",
383 "__TEXT",
384 align,
385 MachOSection::S_REGULAR |
386 MachOSection::S_ATTR_SOME_INSTRUCTIONS |
387 MachOSection::S_ATTR_PURE_INSTRUCTIONS),
388 addr_(addr),
389 size_(size) { }
390
391 protected:
392 virtual void PopulateHeader(Writer::Slot<Header> header) {
393 MachOSection::PopulateHeader(header);
394 header->addr = addr_;
395 header->size = size_;
396 }
397
398 private:
399 uintptr_t addr_;
400 uintptr_t size_;
401};
402#endif // defined(__MACH_O)
403
404
405#if defined(__ELF)
Ben Murdochb8e0da22011-05-16 14:20:40 +0100406class FullHeaderELFSection : public ELFSection {
407 public:
408 FullHeaderELFSection(const char* name,
409 Type type,
410 uintptr_t align,
411 uintptr_t addr,
412 uintptr_t offset,
413 uintptr_t size,
414 uintptr_t flags)
415 : ELFSection(name, type, align),
416 addr_(addr),
417 offset_(offset),
418 size_(size),
419 flags_(flags) { }
420
421 protected:
422 virtual void PopulateHeader(Writer::Slot<Header> header) {
423 ELFSection::PopulateHeader(header);
424 header->address = addr_;
425 header->offset = offset_;
426 header->size = size_;
427 header->flags = flags_;
428 }
429
430 private:
431 uintptr_t addr_;
432 uintptr_t offset_;
433 uintptr_t size_;
434 uintptr_t flags_;
435};
436
437
438class StringTable : public ELFSection {
439 public:
440 explicit StringTable(const char* name)
441 : ELFSection(name, TYPE_STRTAB, 1), writer_(NULL), offset_(0), size_(0) {
442 }
443
444 uintptr_t Add(const char* str) {
445 if (*str == '\0') return 0;
446
447 uintptr_t offset = size_;
448 WriteString(str);
449 return offset;
450 }
451
452 void AttachWriter(Writer* w) {
453 writer_ = w;
454 offset_ = writer_->position();
455
456 // First entry in the string table should be an empty string.
457 WriteString("");
458 }
459
460 void DetachWriter() {
461 writer_ = NULL;
462 }
463
464 virtual void WriteBody(Writer::Slot<Header> header, Writer* w) {
465 ASSERT(writer_ == NULL);
466 header->offset = offset_;
467 header->size = size_;
468 }
469
470 private:
471 void WriteString(const char* str) {
472 uintptr_t written = 0;
473 do {
474 writer_->Write(*str);
475 written++;
476 } while (*str++);
477 size_ += written;
478 }
479
480 Writer* writer_;
481
482 uintptr_t offset_;
483 uintptr_t size_;
484};
485
486
487void ELFSection::PopulateHeader(Writer::Slot<ELFSection::Header> header,
488 StringTable* strtab) {
489 header->name = strtab->Add(name_);
490 header->type = type_;
491 header->alignment = align_;
492 PopulateHeader(header);
493}
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000494#endif // defined(__ELF)
Ben Murdochb8e0da22011-05-16 14:20:40 +0100495
496
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000497#if defined(__MACH_O)
498class MachO BASE_EMBEDDED {
499 public:
500 MachO() : sections_(6) { }
501
502 uint32_t AddSection(MachOSection* section) {
503 sections_.Add(section);
504 return sections_.length() - 1;
505 }
506
507 void Write(Writer* w, uintptr_t code_start, uintptr_t code_size) {
508 Writer::Slot<MachOHeader> header = WriteHeader(w);
509 uintptr_t load_command_start = w->position();
510 Writer::Slot<MachOSegmentCommand> cmd = WriteSegmentCommand(w,
511 code_start,
512 code_size);
513 WriteSections(w, cmd, header, load_command_start);
514 }
515
516 private:
517 struct MachOHeader {
518 uint32_t magic;
519 uint32_t cputype;
520 uint32_t cpusubtype;
521 uint32_t filetype;
522 uint32_t ncmds;
523 uint32_t sizeofcmds;
524 uint32_t flags;
525#if defined(V8_TARGET_ARCH_X64)
526 uint32_t reserved;
527#endif
528 };
529
530 struct MachOSegmentCommand {
531 uint32_t cmd;
532 uint32_t cmdsize;
533 char segname[16];
534#if defined(V8_TARGET_ARCH_IA32)
535 uint32_t vmaddr;
536 uint32_t vmsize;
537 uint32_t fileoff;
538 uint32_t filesize;
539#else
540 uint64_t vmaddr;
541 uint64_t vmsize;
542 uint64_t fileoff;
543 uint64_t filesize;
544#endif
545 uint32_t maxprot;
546 uint32_t initprot;
547 uint32_t nsects;
548 uint32_t flags;
549 };
550
551 enum MachOLoadCommandCmd {
552 LC_SEGMENT_32 = 0x00000001u,
553 LC_SEGMENT_64 = 0x00000019u
554 };
555
556
557 Writer::Slot<MachOHeader> WriteHeader(Writer* w) {
558 ASSERT(w->position() == 0);
559 Writer::Slot<MachOHeader> header = w->CreateSlotHere<MachOHeader>();
560#if defined(V8_TARGET_ARCH_IA32)
561 header->magic = 0xFEEDFACEu;
562 header->cputype = 7; // i386
563 header->cpusubtype = 3; // CPU_SUBTYPE_I386_ALL
564#elif defined(V8_TARGET_ARCH_X64)
565 header->magic = 0xFEEDFACFu;
566 header->cputype = 7 | 0x01000000; // i386 | 64-bit ABI
567 header->cpusubtype = 3; // CPU_SUBTYPE_I386_ALL
568 header->reserved = 0;
569#else
570#error Unsupported target architecture.
571#endif
572 header->filetype = 0x1; // MH_OBJECT
573 header->ncmds = 1;
574 header->sizeofcmds = 0;
575 header->flags = 0;
576 return header;
577 }
578
579
580 Writer::Slot<MachOSegmentCommand> WriteSegmentCommand(Writer* w,
581 uintptr_t code_start,
582 uintptr_t code_size) {
583 Writer::Slot<MachOSegmentCommand> cmd =
584 w->CreateSlotHere<MachOSegmentCommand>();
585#if defined(V8_TARGET_ARCH_IA32)
586 cmd->cmd = LC_SEGMENT_32;
587#else
588 cmd->cmd = LC_SEGMENT_64;
589#endif
590 cmd->vmaddr = code_start;
591 cmd->vmsize = code_size;
592 cmd->fileoff = 0;
593 cmd->filesize = 0;
594 cmd->maxprot = 7;
595 cmd->initprot = 7;
596 cmd->flags = 0;
597 cmd->nsects = sections_.length();
598 memset(cmd->segname, 0, 16);
599 cmd->cmdsize = sizeof(MachOSegmentCommand) + sizeof(MachOSection::Header) *
600 cmd->nsects;
601 return cmd;
602 }
603
604
605 void WriteSections(Writer* w,
606 Writer::Slot<MachOSegmentCommand> cmd,
607 Writer::Slot<MachOHeader> header,
608 uintptr_t load_command_start) {
609 Writer::Slot<MachOSection::Header> headers =
610 w->CreateSlotsHere<MachOSection::Header>(sections_.length());
611 cmd->fileoff = w->position();
612 header->sizeofcmds = w->position() - load_command_start;
613 for (int section = 0; section < sections_.length(); ++section) {
614 sections_[section]->PopulateHeader(headers.at(section));
615 sections_[section]->WriteBody(headers.at(section), w);
616 }
617 cmd->filesize = w->position() - (uintptr_t)cmd->fileoff;
618 }
619
620
621 ZoneList<MachOSection*> sections_;
622};
623#endif // defined(__MACH_O)
624
625
626#if defined(__ELF)
Ben Murdochb8e0da22011-05-16 14:20:40 +0100627class ELF BASE_EMBEDDED {
628 public:
629 ELF() : sections_(6) {
630 sections_.Add(new ELFSection("", ELFSection::TYPE_NULL, 0));
631 sections_.Add(new StringTable(".shstrtab"));
632 }
633
634 void Write(Writer* w) {
635 WriteHeader(w);
636 WriteSectionTable(w);
637 WriteSections(w);
638 }
639
640 ELFSection* SectionAt(uint32_t index) {
641 return sections_[index];
642 }
643
644 uint32_t AddSection(ELFSection* section) {
645 sections_.Add(section);
646 section->set_index(sections_.length() - 1);
647 return sections_.length() - 1;
648 }
649
650 private:
651 struct ELFHeader {
652 uint8_t ident[16];
653 uint16_t type;
654 uint16_t machine;
655 uint32_t version;
656 uintptr_t entry;
657 uintptr_t pht_offset;
658 uintptr_t sht_offset;
659 uint32_t flags;
660 uint16_t header_size;
661 uint16_t pht_entry_size;
662 uint16_t pht_entry_num;
663 uint16_t sht_entry_size;
664 uint16_t sht_entry_num;
665 uint16_t sht_strtab_index;
666 };
667
668
669 void WriteHeader(Writer* w) {
670 ASSERT(w->position() == 0);
671 Writer::Slot<ELFHeader> header = w->CreateSlotHere<ELFHeader>();
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100672#if defined(V8_TARGET_ARCH_IA32) || defined(V8_TARGET_ARCH_ARM)
Ben Murdochb8e0da22011-05-16 14:20:40 +0100673 const uint8_t ident[16] =
674 { 0x7f, 'E', 'L', 'F', 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0};
675#elif defined(V8_TARGET_ARCH_X64)
676 const uint8_t ident[16] =
677 { 0x7f, 'E', 'L', 'F', 2, 1, 1, 0, 0, 0 , 0, 0, 0, 0, 0, 0};
678#else
679#error Unsupported target architecture.
680#endif
681 memcpy(header->ident, ident, 16);
682 header->type = 1;
683#if defined(V8_TARGET_ARCH_IA32)
684 header->machine = 3;
685#elif defined(V8_TARGET_ARCH_X64)
686 // Processor identification value for x64 is 62 as defined in
687 // System V ABI, AMD64 Supplement
688 // http://www.x86-64.org/documentation/abi.pdf
689 header->machine = 62;
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100690#elif defined(V8_TARGET_ARCH_ARM)
691 // Set to EM_ARM, defined as 40, in "ARM ELF File Format" at
692 // infocenter.arm.com/help/topic/com.arm.doc.dui0101a/DUI0101A_Elf.pdf
693 header->machine = 40;
Ben Murdochb8e0da22011-05-16 14:20:40 +0100694#else
695#error Unsupported target architecture.
696#endif
697 header->version = 1;
698 header->entry = 0;
699 header->pht_offset = 0;
700 header->sht_offset = sizeof(ELFHeader); // Section table follows header.
701 header->flags = 0;
702 header->header_size = sizeof(ELFHeader);
703 header->pht_entry_size = 0;
704 header->pht_entry_num = 0;
705 header->sht_entry_size = sizeof(ELFSection::Header);
706 header->sht_entry_num = sections_.length();
707 header->sht_strtab_index = 1;
708 }
709
710 void WriteSectionTable(Writer* w) {
711 // Section headers table immediately follows file header.
712 ASSERT(w->position() == sizeof(ELFHeader));
713
714 Writer::Slot<ELFSection::Header> headers =
715 w->CreateSlotsHere<ELFSection::Header>(sections_.length());
716
717 // String table for section table is the first section.
718 StringTable* strtab = static_cast<StringTable*>(SectionAt(1));
719 strtab->AttachWriter(w);
720 for (int i = 0, length = sections_.length();
721 i < length;
722 i++) {
723 sections_[i]->PopulateHeader(headers.at(i), strtab);
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 for (int i = 0, length = sections_.length();
737 i < length;
738 i++) {
739 sections_[i]->WriteBody(headers.at(i), w);
740 }
741 }
742
743 ZoneList<ELFSection*> sections_;
744};
745
746
747class ELFSymbol BASE_EMBEDDED {
748 public:
749 enum Type {
750 TYPE_NOTYPE = 0,
751 TYPE_OBJECT = 1,
752 TYPE_FUNC = 2,
753 TYPE_SECTION = 3,
754 TYPE_FILE = 4,
755 TYPE_LOPROC = 13,
756 TYPE_HIPROC = 15
757 };
758
759 enum Binding {
760 BIND_LOCAL = 0,
761 BIND_GLOBAL = 1,
762 BIND_WEAK = 2,
763 BIND_LOPROC = 13,
764 BIND_HIPROC = 15
765 };
766
767 ELFSymbol(const char* name,
768 uintptr_t value,
769 uintptr_t size,
770 Binding binding,
771 Type type,
772 uint16_t section)
773 : name(name),
774 value(value),
775 size(size),
776 info((binding << 4) | type),
777 other(0),
778 section(section) {
779 }
780
781 Binding binding() const {
782 return static_cast<Binding>(info >> 4);
783 }
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100784#if defined(V8_TARGET_ARCH_IA32) || defined(V8_TARGET_ARCH_ARM)
Ben Murdochb8e0da22011-05-16 14:20:40 +0100785 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 defined(V8_TARGET_ARCH_X64)
808 struct SerializedLayout {
809 SerializedLayout(uint32_t name,
810 uintptr_t value,
811 uintptr_t size,
812 Binding binding,
813 Type type,
814 uint16_t section)
815 : name(name),
816 info((binding << 4) | type),
817 other(0),
818 section(section),
819 value(value),
820 size(size) {
821 }
822
823 uint32_t name;
824 uint8_t info;
825 uint8_t other;
826 uint16_t section;
827 uintptr_t value;
828 uintptr_t size;
829 };
830#endif
831
832 void Write(Writer::Slot<SerializedLayout> s, StringTable* t) {
833 // Convert symbol names from strings to indexes in the string table.
834 s->name = t->Add(name);
835 s->value = value;
836 s->size = size;
837 s->info = info;
838 s->other = other;
839 s->section = section;
840 }
841
842 private:
843 const char* name;
844 uintptr_t value;
845 uintptr_t size;
846 uint8_t info;
847 uint8_t other;
848 uint16_t section;
849};
850
851
852class ELFSymbolTable : public ELFSection {
853 public:
854 explicit ELFSymbolTable(const char* name)
855 : ELFSection(name, TYPE_SYMTAB, sizeof(uintptr_t)),
856 locals_(1),
857 globals_(1) {
858 }
859
860 virtual void WriteBody(Writer::Slot<Header> header, Writer* w) {
861 w->Align(header->alignment);
862 int total_symbols = locals_.length() + globals_.length() + 1;
863 header->offset = w->position();
864
865 Writer::Slot<ELFSymbol::SerializedLayout> symbols =
866 w->CreateSlotsHere<ELFSymbol::SerializedLayout>(total_symbols);
867
868 header->size = w->position() - header->offset;
869
870 // String table for this symbol table should follow it in the section table.
871 StringTable* strtab =
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000872 static_cast<StringTable*>(w->debug_object()->SectionAt(index() + 1));
Ben Murdochb8e0da22011-05-16 14:20:40 +0100873 strtab->AttachWriter(w);
874 symbols.at(0).set(ELFSymbol::SerializedLayout(0,
875 0,
876 0,
877 ELFSymbol::BIND_LOCAL,
878 ELFSymbol::TYPE_NOTYPE,
879 0));
880 WriteSymbolsList(&locals_, symbols.at(1), strtab);
881 WriteSymbolsList(&globals_, symbols.at(locals_.length() + 1), strtab);
882 strtab->DetachWriter();
883 }
884
885 void Add(const ELFSymbol& symbol) {
886 if (symbol.binding() == ELFSymbol::BIND_LOCAL) {
887 locals_.Add(symbol);
888 } else {
889 globals_.Add(symbol);
890 }
891 }
892
893 protected:
894 virtual void PopulateHeader(Writer::Slot<Header> header) {
895 ELFSection::PopulateHeader(header);
896 // We are assuming that string table will follow symbol table.
897 header->link = index() + 1;
898 header->info = locals_.length() + 1;
899 header->entry_size = sizeof(ELFSymbol::SerializedLayout);
900 }
901
902 private:
903 void WriteSymbolsList(const ZoneList<ELFSymbol>* src,
904 Writer::Slot<ELFSymbol::SerializedLayout> dst,
905 StringTable* strtab) {
906 for (int i = 0, len = src->length();
907 i < len;
908 i++) {
909 src->at(i).Write(dst.at(i), strtab);
910 }
911 }
912
913 ZoneList<ELFSymbol> locals_;
914 ZoneList<ELFSymbol> globals_;
915};
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000916#endif // defined(__ELF)
Ben Murdochb8e0da22011-05-16 14:20:40 +0100917
918
919class CodeDescription BASE_EMBEDDED {
920 public:
Steve Block1e0659c2011-05-24 12:43:12 +0100921#ifdef V8_TARGET_ARCH_X64
922 enum StackState {
923 POST_RBP_PUSH,
924 POST_RBP_SET,
925 POST_RBP_POP,
926 STACK_STATE_MAX
927 };
928#endif
929
Ben Murdochb8e0da22011-05-16 14:20:40 +0100930 CodeDescription(const char* name,
931 Code* code,
932 Handle<Script> script,
Steve Block1e0659c2011-05-24 12:43:12 +0100933 GDBJITLineInfo* lineinfo,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000934 GDBJITInterface::CodeTag tag,
935 CompilationInfo* info)
Steve Block1e0659c2011-05-24 12:43:12 +0100936 : name_(name),
937 code_(code),
938 script_(script),
939 lineinfo_(lineinfo),
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000940 tag_(tag),
941 info_(info) {
Steve Block1e0659c2011-05-24 12:43:12 +0100942 }
Ben Murdochb8e0da22011-05-16 14:20:40 +0100943
Steve Block1e0659c2011-05-24 12:43:12 +0100944 const char* name() const {
Ben Murdochb8e0da22011-05-16 14:20:40 +0100945 return name_;
946 }
947
Steve Block1e0659c2011-05-24 12:43:12 +0100948 GDBJITLineInfo* lineinfo() const {
949 return lineinfo_;
Ben Murdochb8e0da22011-05-16 14:20:40 +0100950 }
951
Steve Block1e0659c2011-05-24 12:43:12 +0100952 GDBJITInterface::CodeTag tag() const {
953 return tag_;
Ben Murdochb8e0da22011-05-16 14:20:40 +0100954 }
955
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000956 CompilationInfo* info() const {
957 return info_;
958 }
959
960 bool IsInfoAvailable() const {
961 return info_ != NULL;
962 }
963
Steve Block1e0659c2011-05-24 12:43:12 +0100964 uintptr_t CodeStart() const {
965 return reinterpret_cast<uintptr_t>(code_->instruction_start());
966 }
967
968 uintptr_t CodeEnd() const {
969 return reinterpret_cast<uintptr_t>(code_->instruction_end());
970 }
971
972 uintptr_t CodeSize() const {
973 return CodeEnd() - CodeStart();
974 }
975
976 bool IsLineInfoAvailable() {
Ben Murdochb8e0da22011-05-16 14:20:40 +0100977 return !script_.is_null() &&
978 script_->source()->IsString() &&
979 script_->HasValidSource() &&
980 script_->name()->IsString() &&
981 lineinfo_ != NULL;
982 }
983
Steve Block1e0659c2011-05-24 12:43:12 +0100984#ifdef V8_TARGET_ARCH_X64
985 uintptr_t GetStackStateStartAddress(StackState state) const {
986 ASSERT(state < STACK_STATE_MAX);
987 return stack_state_start_addresses_[state];
988 }
Ben Murdochb8e0da22011-05-16 14:20:40 +0100989
Steve Block1e0659c2011-05-24 12:43:12 +0100990 void SetStackStateStartAddress(StackState state, uintptr_t addr) {
991 ASSERT(state < STACK_STATE_MAX);
992 stack_state_start_addresses_[state] = addr;
993 }
994#endif
995
Ben Murdoch589d6972011-11-30 16:04:58 +0000996 SmartArrayPointer<char> GetFilename() {
Ben Murdochb8e0da22011-05-16 14:20:40 +0100997 return String::cast(script_->name())->ToCString();
998 }
999
1000 int GetScriptLineNumber(int pos) {
1001 return GetScriptLineNumberSafe(script_, pos) + 1;
1002 }
1003
Steve Block1e0659c2011-05-24 12:43:12 +01001004
Ben Murdochb8e0da22011-05-16 14:20:40 +01001005 private:
1006 const char* name_;
1007 Code* code_;
1008 Handle<Script> script_;
1009 GDBJITLineInfo* lineinfo_;
Steve Block1e0659c2011-05-24 12:43:12 +01001010 GDBJITInterface::CodeTag tag_;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001011 CompilationInfo* info_;
Steve Block1e0659c2011-05-24 12:43:12 +01001012#ifdef V8_TARGET_ARCH_X64
1013 uintptr_t stack_state_start_addresses_[STACK_STATE_MAX];
1014#endif
Ben Murdochb8e0da22011-05-16 14:20:40 +01001015};
1016
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001017#if defined(__ELF)
Ben Murdochb8e0da22011-05-16 14:20:40 +01001018static void CreateSymbolsTable(CodeDescription* desc,
1019 ELF* elf,
1020 int text_section_index) {
1021 ELFSymbolTable* symtab = new ELFSymbolTable(".symtab");
1022 StringTable* strtab = new StringTable(".strtab");
1023
1024 // Symbol table should be followed by the linked string table.
1025 elf->AddSection(symtab);
1026 elf->AddSection(strtab);
1027
1028 symtab->Add(ELFSymbol("V8 Code",
1029 0,
1030 0,
1031 ELFSymbol::BIND_LOCAL,
1032 ELFSymbol::TYPE_FILE,
1033 ELFSection::INDEX_ABSOLUTE));
1034
Steve Block1e0659c2011-05-24 12:43:12 +01001035 symtab->Add(ELFSymbol(desc->name(),
Ben Murdochb8e0da22011-05-16 14:20:40 +01001036 0,
Steve Block1e0659c2011-05-24 12:43:12 +01001037 desc->CodeSize(),
Ben Murdochb8e0da22011-05-16 14:20:40 +01001038 ELFSymbol::BIND_GLOBAL,
1039 ELFSymbol::TYPE_FUNC,
1040 text_section_index));
1041}
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001042#endif // defined(__ELF)
Ben Murdochb8e0da22011-05-16 14:20:40 +01001043
1044
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001045class DebugInfoSection : public DebugSection {
Ben Murdochb8e0da22011-05-16 14:20:40 +01001046 public:
1047 explicit DebugInfoSection(CodeDescription* desc)
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001048#if defined(__ELF)
1049 : ELFSection(".debug_info", TYPE_PROGBITS, 1),
1050#else
1051 : MachOSection("__debug_info",
1052 "__DWARF",
1053 1,
1054 MachOSection::S_REGULAR | MachOSection::S_ATTR_DEBUG),
1055#endif
1056 desc_(desc) { }
1057
1058 // DWARF2 standard
1059 enum DWARF2LocationOp {
1060 DW_OP_reg0 = 0x50,
1061 DW_OP_reg1 = 0x51,
1062 DW_OP_reg2 = 0x52,
1063 DW_OP_reg3 = 0x53,
1064 DW_OP_reg4 = 0x54,
1065 DW_OP_reg5 = 0x55,
1066 DW_OP_reg6 = 0x56,
1067 DW_OP_reg7 = 0x57,
1068 DW_OP_fbreg = 0x91 // 1 param: SLEB128 offset
1069 };
1070
1071 enum DWARF2Encoding {
1072 DW_ATE_ADDRESS = 0x1,
1073 DW_ATE_SIGNED = 0x5
1074 };
Ben Murdochb8e0da22011-05-16 14:20:40 +01001075
1076 bool WriteBody(Writer* w) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001077 uintptr_t cu_start = w->position();
Ben Murdochb8e0da22011-05-16 14:20:40 +01001078 Writer::Slot<uint32_t> size = w->CreateSlotHere<uint32_t>();
1079 uintptr_t start = w->position();
1080 w->Write<uint16_t>(2); // DWARF version.
1081 w->Write<uint32_t>(0); // Abbreviation table offset.
1082 w->Write<uint8_t>(sizeof(intptr_t));
1083
1084 w->WriteULEB128(1); // Abbreviation code.
Steve Block1e0659c2011-05-24 12:43:12 +01001085 w->WriteString(*desc_->GetFilename());
1086 w->Write<intptr_t>(desc_->CodeStart());
1087 w->Write<intptr_t>(desc_->CodeStart() + desc_->CodeSize());
Ben Murdochb8e0da22011-05-16 14:20:40 +01001088 w->Write<uint32_t>(0);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001089
1090 uint32_t ty_offset = static_cast<uint32_t>(w->position() - cu_start);
1091 w->WriteULEB128(3);
1092 w->Write<uint8_t>(kPointerSize);
1093 w->WriteString("v8value");
1094
1095 if (desc_->IsInfoAvailable()) {
1096 CompilationInfo* info = desc_->info();
1097 ScopeInfo<FreeStoreAllocationPolicy> scope_info(info->scope());
1098 w->WriteULEB128(2);
1099 w->WriteString(desc_->name());
1100 w->Write<intptr_t>(desc_->CodeStart());
1101 w->Write<intptr_t>(desc_->CodeStart() + desc_->CodeSize());
1102 Writer::Slot<uint32_t> fb_block_size = w->CreateSlotHere<uint32_t>();
1103 uintptr_t fb_block_start = w->position();
1104#if defined(V8_TARGET_ARCH_IA32)
1105 w->Write<uint8_t>(DW_OP_reg5); // The frame pointer's here on ia32
1106#elif defined(V8_TARGET_ARCH_X64)
1107 w->Write<uint8_t>(DW_OP_reg6); // and here on x64.
1108#else
1109#error Unsupported target architecture.
1110#endif
1111 fb_block_size.set(static_cast<uint32_t>(w->position() - fb_block_start));
1112
1113 int params = scope_info.number_of_parameters();
1114 int slots = scope_info.number_of_stack_slots();
1115 int context_slots = scope_info.number_of_context_slots();
1116 // The real slot ID is internal_slots + context_slot_id.
1117 int internal_slots = Context::MIN_CONTEXT_SLOTS;
1118 int locals = scope_info.NumberOfLocals();
1119 int current_abbreviation = 4;
1120
1121 for (int param = 0; param < params; ++param) {
1122 w->WriteULEB128(current_abbreviation++);
1123 w->WriteString(
1124 *scope_info.parameter_name(param)->ToCString(DISALLOW_NULLS));
1125 w->Write<uint32_t>(ty_offset);
1126 Writer::Slot<uint32_t> block_size = w->CreateSlotHere<uint32_t>();
1127 uintptr_t block_start = w->position();
1128 w->Write<uint8_t>(DW_OP_fbreg);
1129 w->WriteSLEB128(
1130 JavaScriptFrameConstants::kLastParameterOffset +
1131 kPointerSize * (params - param - 1));
1132 block_size.set(static_cast<uint32_t>(w->position() - block_start));
1133 }
1134
1135 EmbeddedVector<char, 256> buffer;
1136 StringBuilder builder(buffer.start(), buffer.length());
1137
1138 for (int slot = 0; slot < slots; ++slot) {
1139 w->WriteULEB128(current_abbreviation++);
1140 builder.Reset();
1141 builder.AddFormatted("slot%d", slot);
1142 w->WriteString(builder.Finalize());
1143 }
1144
1145 // See contexts.h for more information.
1146 ASSERT(Context::MIN_CONTEXT_SLOTS == 4);
1147 ASSERT(Context::CLOSURE_INDEX == 0);
1148 ASSERT(Context::PREVIOUS_INDEX == 1);
1149 ASSERT(Context::EXTENSION_INDEX == 2);
1150 ASSERT(Context::GLOBAL_INDEX == 3);
1151 w->WriteULEB128(current_abbreviation++);
1152 w->WriteString(".closure");
1153 w->WriteULEB128(current_abbreviation++);
1154 w->WriteString(".previous");
1155 w->WriteULEB128(current_abbreviation++);
1156 w->WriteString(".extension");
1157 w->WriteULEB128(current_abbreviation++);
1158 w->WriteString(".global");
1159
1160 for (int context_slot = 0;
1161 context_slot < context_slots;
1162 ++context_slot) {
1163 w->WriteULEB128(current_abbreviation++);
1164 builder.Reset();
1165 builder.AddFormatted("context_slot%d", context_slot + internal_slots);
1166 w->WriteString(builder.Finalize());
1167 }
1168
1169 for (int local = 0; local < locals; ++local) {
1170 w->WriteULEB128(current_abbreviation++);
1171 w->WriteString(
1172 *scope_info.LocalName(local)->ToCString(DISALLOW_NULLS));
1173 w->Write<uint32_t>(ty_offset);
1174 Writer::Slot<uint32_t> block_size = w->CreateSlotHere<uint32_t>();
1175 uintptr_t block_start = w->position();
1176 w->Write<uint8_t>(DW_OP_fbreg);
1177 w->WriteSLEB128(
1178 JavaScriptFrameConstants::kLocal0Offset -
1179 kPointerSize * local);
1180 block_size.set(static_cast<uint32_t>(w->position() - block_start));
1181 }
1182
1183 {
1184 w->WriteULEB128(current_abbreviation++);
1185 w->WriteString("__function");
1186 w->Write<uint32_t>(ty_offset);
1187 Writer::Slot<uint32_t> block_size = w->CreateSlotHere<uint32_t>();
1188 uintptr_t block_start = w->position();
1189 w->Write<uint8_t>(DW_OP_fbreg);
1190 w->WriteSLEB128(JavaScriptFrameConstants::kFunctionOffset);
1191 block_size.set(static_cast<uint32_t>(w->position() - block_start));
1192 }
1193
1194 {
1195 w->WriteULEB128(current_abbreviation++);
1196 w->WriteString("__context");
1197 w->Write<uint32_t>(ty_offset);
1198 Writer::Slot<uint32_t> block_size = w->CreateSlotHere<uint32_t>();
1199 uintptr_t block_start = w->position();
1200 w->Write<uint8_t>(DW_OP_fbreg);
1201 w->WriteSLEB128(StandardFrameConstants::kContextOffset);
1202 block_size.set(static_cast<uint32_t>(w->position() - block_start));
1203 }
1204 }
1205
Ben Murdochb8e0da22011-05-16 14:20:40 +01001206 size.set(static_cast<uint32_t>(w->position() - start));
1207 return true;
1208 }
1209
1210 private:
1211 CodeDescription* desc_;
1212};
1213
1214
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001215class DebugAbbrevSection : public DebugSection {
Ben Murdochb8e0da22011-05-16 14:20:40 +01001216 public:
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001217 explicit DebugAbbrevSection(CodeDescription* desc)
1218#ifdef __ELF
1219 : ELFSection(".debug_abbrev", TYPE_PROGBITS, 1),
1220#else
1221 : MachOSection("__debug_abbrev",
1222 "__DWARF",
1223 1,
1224 MachOSection::S_REGULAR | MachOSection::S_ATTR_DEBUG),
1225#endif
1226 desc_(desc) { }
Ben Murdochb8e0da22011-05-16 14:20:40 +01001227
1228 // DWARF2 standard, figure 14.
1229 enum DWARF2Tags {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001230 DW_TAG_FORMAL_PARAMETER = 0x05,
1231 DW_TAG_POINTER_TYPE = 0xf,
1232 DW_TAG_COMPILE_UNIT = 0x11,
1233 DW_TAG_STRUCTURE_TYPE = 0x13,
1234 DW_TAG_BASE_TYPE = 0x24,
1235 DW_TAG_SUBPROGRAM = 0x2e,
1236 DW_TAG_VARIABLE = 0x34
Ben Murdochb8e0da22011-05-16 14:20:40 +01001237 };
1238
1239 // DWARF2 standard, figure 16.
1240 enum DWARF2ChildrenDetermination {
1241 DW_CHILDREN_NO = 0,
1242 DW_CHILDREN_YES = 1
1243 };
1244
1245 // DWARF standard, figure 17.
1246 enum DWARF2Attribute {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001247 DW_AT_LOCATION = 0x2,
Ben Murdochb8e0da22011-05-16 14:20:40 +01001248 DW_AT_NAME = 0x3,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001249 DW_AT_BYTE_SIZE = 0xb,
Ben Murdochb8e0da22011-05-16 14:20:40 +01001250 DW_AT_STMT_LIST = 0x10,
1251 DW_AT_LOW_PC = 0x11,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001252 DW_AT_HIGH_PC = 0x12,
1253 DW_AT_ENCODING = 0x3e,
1254 DW_AT_FRAME_BASE = 0x40,
1255 DW_AT_TYPE = 0x49
Ben Murdochb8e0da22011-05-16 14:20:40 +01001256 };
1257
1258 // DWARF2 standard, figure 19.
1259 enum DWARF2AttributeForm {
1260 DW_FORM_ADDR = 0x1,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001261 DW_FORM_BLOCK4 = 0x4,
Ben Murdochb8e0da22011-05-16 14:20:40 +01001262 DW_FORM_STRING = 0x8,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001263 DW_FORM_DATA4 = 0x6,
1264 DW_FORM_BLOCK = 0x9,
1265 DW_FORM_DATA1 = 0xb,
1266 DW_FORM_FLAG = 0xc,
1267 DW_FORM_REF4 = 0x13
Ben Murdochb8e0da22011-05-16 14:20:40 +01001268 };
1269
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001270 void WriteVariableAbbreviation(Writer* w,
1271 int abbreviation_code,
1272 bool has_value,
1273 bool is_parameter) {
1274 w->WriteULEB128(abbreviation_code);
1275 w->WriteULEB128(is_parameter ? DW_TAG_FORMAL_PARAMETER : DW_TAG_VARIABLE);
Ben Murdochb8e0da22011-05-16 14:20:40 +01001276 w->Write<uint8_t>(DW_CHILDREN_NO);
1277 w->WriteULEB128(DW_AT_NAME);
1278 w->WriteULEB128(DW_FORM_STRING);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001279 if (has_value) {
1280 w->WriteULEB128(DW_AT_TYPE);
1281 w->WriteULEB128(DW_FORM_REF4);
1282 w->WriteULEB128(DW_AT_LOCATION);
1283 w->WriteULEB128(DW_FORM_BLOCK4);
1284 }
1285 w->WriteULEB128(0);
1286 w->WriteULEB128(0);
1287 }
1288
1289 bool WriteBody(Writer* w) {
1290 int current_abbreviation = 1;
1291 bool extra_info = desc_->IsInfoAvailable();
1292 ASSERT(desc_->IsLineInfoAvailable());
1293 w->WriteULEB128(current_abbreviation++);
1294 w->WriteULEB128(DW_TAG_COMPILE_UNIT);
1295 w->Write<uint8_t>(extra_info ? DW_CHILDREN_YES : DW_CHILDREN_NO);
1296 w->WriteULEB128(DW_AT_NAME);
1297 w->WriteULEB128(DW_FORM_STRING);
Ben Murdochb8e0da22011-05-16 14:20:40 +01001298 w->WriteULEB128(DW_AT_LOW_PC);
1299 w->WriteULEB128(DW_FORM_ADDR);
1300 w->WriteULEB128(DW_AT_HIGH_PC);
1301 w->WriteULEB128(DW_FORM_ADDR);
1302 w->WriteULEB128(DW_AT_STMT_LIST);
1303 w->WriteULEB128(DW_FORM_DATA4);
1304 w->WriteULEB128(0);
1305 w->WriteULEB128(0);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001306
1307 if (extra_info) {
1308 CompilationInfo* info = desc_->info();
1309 ScopeInfo<FreeStoreAllocationPolicy> scope_info(info->scope());
1310 int params = scope_info.number_of_parameters();
1311 int slots = scope_info.number_of_stack_slots();
1312 int context_slots = scope_info.number_of_context_slots();
1313 // The real slot ID is internal_slots + context_slot_id.
1314 int internal_slots = Context::MIN_CONTEXT_SLOTS;
1315 int locals = scope_info.NumberOfLocals();
1316 int total_children =
1317 params + slots + context_slots + internal_slots + locals + 2;
1318
1319 // The extra duplication below seems to be necessary to keep
1320 // gdb from getting upset on OSX.
1321 w->WriteULEB128(current_abbreviation++); // Abbreviation code.
1322 w->WriteULEB128(DW_TAG_SUBPROGRAM);
1323 w->Write<uint8_t>(
1324 total_children != 0 ? DW_CHILDREN_YES : DW_CHILDREN_NO);
1325 w->WriteULEB128(DW_AT_NAME);
1326 w->WriteULEB128(DW_FORM_STRING);
1327 w->WriteULEB128(DW_AT_LOW_PC);
1328 w->WriteULEB128(DW_FORM_ADDR);
1329 w->WriteULEB128(DW_AT_HIGH_PC);
1330 w->WriteULEB128(DW_FORM_ADDR);
1331 w->WriteULEB128(DW_AT_FRAME_BASE);
1332 w->WriteULEB128(DW_FORM_BLOCK4);
1333 w->WriteULEB128(0);
1334 w->WriteULEB128(0);
1335
1336 w->WriteULEB128(current_abbreviation++);
1337 w->WriteULEB128(DW_TAG_STRUCTURE_TYPE);
1338 w->Write<uint8_t>(DW_CHILDREN_NO);
1339 w->WriteULEB128(DW_AT_BYTE_SIZE);
1340 w->WriteULEB128(DW_FORM_DATA1);
1341 w->WriteULEB128(DW_AT_NAME);
1342 w->WriteULEB128(DW_FORM_STRING);
1343 w->WriteULEB128(0);
1344 w->WriteULEB128(0);
1345
1346 for (int param = 0; param < params; ++param) {
1347 WriteVariableAbbreviation(w, current_abbreviation++, true, true);
1348 }
1349
1350 for (int slot = 0; slot < slots; ++slot) {
1351 WriteVariableAbbreviation(w, current_abbreviation++, false, false);
1352 }
1353
1354 for (int internal_slot = 0;
1355 internal_slot < internal_slots;
1356 ++internal_slot) {
1357 WriteVariableAbbreviation(w, current_abbreviation++, false, false);
1358 }
1359
1360 for (int context_slot = 0;
1361 context_slot < context_slots;
1362 ++context_slot) {
1363 WriteVariableAbbreviation(w, current_abbreviation++, false, false);
1364 }
1365
1366 for (int local = 0; local < locals; ++local) {
1367 WriteVariableAbbreviation(w, current_abbreviation++, true, false);
1368 }
1369
1370 // The function.
1371 WriteVariableAbbreviation(w, current_abbreviation++, true, false);
1372
1373 // The context.
1374 WriteVariableAbbreviation(w, current_abbreviation++, true, false);
1375
1376 if (total_children != 0) {
1377 w->WriteULEB128(0); // Terminate the sibling list.
1378 }
1379 }
1380
1381 w->WriteULEB128(0); // Terminate the table.
Ben Murdochb8e0da22011-05-16 14:20:40 +01001382 return true;
1383 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001384
1385 private:
1386 CodeDescription* desc_;
Ben Murdochb8e0da22011-05-16 14:20:40 +01001387};
1388
1389
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001390class DebugLineSection : public DebugSection {
Ben Murdochb8e0da22011-05-16 14:20:40 +01001391 public:
1392 explicit DebugLineSection(CodeDescription* desc)
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001393#ifdef __ELF
Ben Murdochb8e0da22011-05-16 14:20:40 +01001394 : ELFSection(".debug_line", TYPE_PROGBITS, 1),
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001395#else
1396 : MachOSection("__debug_line",
1397 "__DWARF",
1398 1,
1399 MachOSection::S_REGULAR | MachOSection::S_ATTR_DEBUG),
1400#endif
Ben Murdochb8e0da22011-05-16 14:20:40 +01001401 desc_(desc) { }
1402
1403 // DWARF2 standard, figure 34.
1404 enum DWARF2Opcodes {
1405 DW_LNS_COPY = 1,
1406 DW_LNS_ADVANCE_PC = 2,
1407 DW_LNS_ADVANCE_LINE = 3,
1408 DW_LNS_SET_FILE = 4,
1409 DW_LNS_SET_COLUMN = 5,
1410 DW_LNS_NEGATE_STMT = 6
1411 };
1412
1413 // DWARF2 standard, figure 35.
1414 enum DWARF2ExtendedOpcode {
1415 DW_LNE_END_SEQUENCE = 1,
1416 DW_LNE_SET_ADDRESS = 2,
1417 DW_LNE_DEFINE_FILE = 3
1418 };
1419
1420 bool WriteBody(Writer* w) {
1421 // Write prologue.
1422 Writer::Slot<uint32_t> total_length = w->CreateSlotHere<uint32_t>();
1423 uintptr_t start = w->position();
1424
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001425 // Used for special opcodes
1426 const int8_t line_base = 1;
1427 const uint8_t line_range = 7;
1428 const int8_t max_line_incr = (line_base + line_range - 1);
1429 const uint8_t opcode_base = DW_LNS_NEGATE_STMT + 1;
1430
Ben Murdochb8e0da22011-05-16 14:20:40 +01001431 w->Write<uint16_t>(2); // Field version.
1432 Writer::Slot<uint32_t> prologue_length = w->CreateSlotHere<uint32_t>();
1433 uintptr_t prologue_start = w->position();
1434 w->Write<uint8_t>(1); // Field minimum_instruction_length.
1435 w->Write<uint8_t>(1); // Field default_is_stmt.
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001436 w->Write<int8_t>(line_base); // Field line_base.
1437 w->Write<uint8_t>(line_range); // Field line_range.
1438 w->Write<uint8_t>(opcode_base); // Field opcode_base.
Ben Murdochb8e0da22011-05-16 14:20:40 +01001439 w->Write<uint8_t>(0); // DW_LNS_COPY operands count.
1440 w->Write<uint8_t>(1); // DW_LNS_ADVANCE_PC operands count.
1441 w->Write<uint8_t>(1); // DW_LNS_ADVANCE_LINE operands count.
1442 w->Write<uint8_t>(1); // DW_LNS_SET_FILE operands count.
1443 w->Write<uint8_t>(1); // DW_LNS_SET_COLUMN operands count.
1444 w->Write<uint8_t>(0); // DW_LNS_NEGATE_STMT operands count.
1445 w->Write<uint8_t>(0); // Empty include_directories sequence.
Steve Block1e0659c2011-05-24 12:43:12 +01001446 w->WriteString(*desc_->GetFilename()); // File name.
Ben Murdochb8e0da22011-05-16 14:20:40 +01001447 w->WriteULEB128(0); // Current directory.
1448 w->WriteULEB128(0); // Unknown modification time.
1449 w->WriteULEB128(0); // Unknown file size.
1450 w->Write<uint8_t>(0);
1451 prologue_length.set(static_cast<uint32_t>(w->position() - prologue_start));
1452
1453 WriteExtendedOpcode(w, DW_LNE_SET_ADDRESS, sizeof(intptr_t));
Steve Block1e0659c2011-05-24 12:43:12 +01001454 w->Write<intptr_t>(desc_->CodeStart());
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001455 w->Write<uint8_t>(DW_LNS_COPY);
Ben Murdochb8e0da22011-05-16 14:20:40 +01001456
1457 intptr_t pc = 0;
1458 intptr_t line = 1;
1459 bool is_statement = true;
1460
1461 List<GDBJITLineInfo::PCInfo>* pc_info = desc_->lineinfo()->pc_info();
1462 pc_info->Sort(&ComparePCInfo);
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001463
1464 int pc_info_length = pc_info->length();
1465 for (int i = 0; i < pc_info_length; i++) {
Ben Murdochb8e0da22011-05-16 14:20:40 +01001466 GDBJITLineInfo::PCInfo* info = &pc_info->at(i);
Ben Murdochb8e0da22011-05-16 14:20:40 +01001467 ASSERT(info->pc_ >= pc);
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001468
1469 // Reduce bloating in the debug line table by removing duplicate line
1470 // entries (per DWARF2 standard).
1471 intptr_t new_line = desc_->GetScriptLineNumber(info->pos_);
1472 if (new_line == line) {
1473 continue;
Ben Murdochb8e0da22011-05-16 14:20:40 +01001474 }
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001475
1476 // Mark statement boundaries. For a better debugging experience, mark
1477 // the last pc address in the function as a statement (e.g. "}"), so that
1478 // a user can see the result of the last line executed in the function,
1479 // should control reach the end.
1480 if ((i+1) == pc_info_length) {
1481 if (!is_statement) {
1482 w->Write<uint8_t>(DW_LNS_NEGATE_STMT);
1483 }
1484 } else if (is_statement != info->is_statement_) {
Ben Murdochb8e0da22011-05-16 14:20:40 +01001485 w->Write<uint8_t>(DW_LNS_NEGATE_STMT);
1486 is_statement = !is_statement;
1487 }
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001488
1489 // Generate special opcodes, if possible. This results in more compact
1490 // debug line tables. See the DWARF 2.0 standard to learn more about
1491 // special opcodes.
1492 uintptr_t pc_diff = info->pc_ - pc;
1493 intptr_t line_diff = new_line - line;
1494
1495 // Compute special opcode (see DWARF 2.0 standard)
1496 intptr_t special_opcode = (line_diff - line_base) +
1497 (line_range * pc_diff) + opcode_base;
1498
1499 // If special_opcode is less than or equal to 255, it can be used as a
1500 // special opcode. If line_diff is larger than the max line increment
1501 // allowed for a special opcode, or if line_diff is less than the minimum
1502 // line that can be added to the line register (i.e. line_base), then
1503 // special_opcode can't be used.
1504 if ((special_opcode >= opcode_base) && (special_opcode <= 255) &&
1505 (line_diff <= max_line_incr) && (line_diff >= line_base)) {
1506 w->Write<uint8_t>(special_opcode);
1507 } else {
1508 w->Write<uint8_t>(DW_LNS_ADVANCE_PC);
1509 w->WriteSLEB128(pc_diff);
1510 w->Write<uint8_t>(DW_LNS_ADVANCE_LINE);
1511 w->WriteSLEB128(line_diff);
Ben Murdochb8e0da22011-05-16 14:20:40 +01001512 w->Write<uint8_t>(DW_LNS_COPY);
1513 }
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001514
1515 // Increment the pc and line operands.
1516 pc += pc_diff;
1517 line += line_diff;
Ben Murdochb8e0da22011-05-16 14:20:40 +01001518 }
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001519 // Advance the pc to the end of the routine, since the end sequence opcode
1520 // requires this.
1521 w->Write<uint8_t>(DW_LNS_ADVANCE_PC);
1522 w->WriteSLEB128(desc_->CodeSize() - pc);
Ben Murdochb8e0da22011-05-16 14:20:40 +01001523 WriteExtendedOpcode(w, DW_LNE_END_SEQUENCE, 0);
1524 total_length.set(static_cast<uint32_t>(w->position() - start));
1525 return true;
1526 }
1527
1528 private:
1529 void WriteExtendedOpcode(Writer* w,
1530 DWARF2ExtendedOpcode op,
1531 size_t operands_size) {
1532 w->Write<uint8_t>(0);
1533 w->WriteULEB128(operands_size + 1);
1534 w->Write<uint8_t>(op);
1535 }
1536
1537 static int ComparePCInfo(const GDBJITLineInfo::PCInfo* a,
1538 const GDBJITLineInfo::PCInfo* b) {
1539 if (a->pc_ == b->pc_) {
1540 if (a->is_statement_ != b->is_statement_) {
1541 return b->is_statement_ ? +1 : -1;
1542 }
1543 return 0;
1544 } else if (a->pc_ > b->pc_) {
1545 return +1;
1546 } else {
1547 return -1;
1548 }
1549 }
1550
1551 CodeDescription* desc_;
1552};
1553
1554
Steve Block1e0659c2011-05-24 12:43:12 +01001555#ifdef V8_TARGET_ARCH_X64
1556
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001557class UnwindInfoSection : public DebugSection {
Steve Block1e0659c2011-05-24 12:43:12 +01001558 public:
1559 explicit UnwindInfoSection(CodeDescription *desc);
1560 virtual bool WriteBody(Writer *w);
1561
1562 int WriteCIE(Writer *w);
1563 void WriteFDE(Writer *w, int);
1564
1565 void WriteFDEStateOnEntry(Writer *w);
1566 void WriteFDEStateAfterRBPPush(Writer *w);
1567 void WriteFDEStateAfterRBPSet(Writer *w);
1568 void WriteFDEStateAfterRBPPop(Writer *w);
1569
1570 void WriteLength(Writer *w,
1571 Writer::Slot<uint32_t>* length_slot,
1572 int initial_position);
1573
1574 private:
1575 CodeDescription *desc_;
1576
1577 // DWARF3 Specification, Table 7.23
1578 enum CFIInstructions {
1579 DW_CFA_ADVANCE_LOC = 0x40,
1580 DW_CFA_OFFSET = 0x80,
1581 DW_CFA_RESTORE = 0xC0,
1582 DW_CFA_NOP = 0x00,
1583 DW_CFA_SET_LOC = 0x01,
1584 DW_CFA_ADVANCE_LOC1 = 0x02,
1585 DW_CFA_ADVANCE_LOC2 = 0x03,
1586 DW_CFA_ADVANCE_LOC4 = 0x04,
1587 DW_CFA_OFFSET_EXTENDED = 0x05,
1588 DW_CFA_RESTORE_EXTENDED = 0x06,
1589 DW_CFA_UNDEFINED = 0x07,
1590 DW_CFA_SAME_VALUE = 0x08,
1591 DW_CFA_REGISTER = 0x09,
1592 DW_CFA_REMEMBER_STATE = 0x0A,
1593 DW_CFA_RESTORE_STATE = 0x0B,
1594 DW_CFA_DEF_CFA = 0x0C,
1595 DW_CFA_DEF_CFA_REGISTER = 0x0D,
1596 DW_CFA_DEF_CFA_OFFSET = 0x0E,
1597
1598 DW_CFA_DEF_CFA_EXPRESSION = 0x0F,
1599 DW_CFA_EXPRESSION = 0x10,
1600 DW_CFA_OFFSET_EXTENDED_SF = 0x11,
1601 DW_CFA_DEF_CFA_SF = 0x12,
1602 DW_CFA_DEF_CFA_OFFSET_SF = 0x13,
1603 DW_CFA_VAL_OFFSET = 0x14,
1604 DW_CFA_VAL_OFFSET_SF = 0x15,
1605 DW_CFA_VAL_EXPRESSION = 0x16
1606 };
1607
1608 // System V ABI, AMD64 Supplement, Version 0.99.5, Figure 3.36
1609 enum RegisterMapping {
1610 // Only the relevant ones have been added to reduce clutter.
1611 AMD64_RBP = 6,
1612 AMD64_RSP = 7,
1613 AMD64_RA = 16
1614 };
1615
1616 enum CFIConstants {
1617 CIE_ID = 0,
1618 CIE_VERSION = 1,
1619 CODE_ALIGN_FACTOR = 1,
1620 DATA_ALIGN_FACTOR = 1,
1621 RETURN_ADDRESS_REGISTER = AMD64_RA
1622 };
1623};
1624
1625
1626void UnwindInfoSection::WriteLength(Writer *w,
1627 Writer::Slot<uint32_t>* length_slot,
1628 int initial_position) {
1629 uint32_t align = (w->position() - initial_position) % kPointerSize;
1630
1631 if (align != 0) {
1632 for (uint32_t i = 0; i < (kPointerSize - align); i++) {
1633 w->Write<uint8_t>(DW_CFA_NOP);
1634 }
1635 }
1636
1637 ASSERT((w->position() - initial_position) % kPointerSize == 0);
1638 length_slot->set(w->position() - initial_position);
1639}
1640
1641
1642UnwindInfoSection::UnwindInfoSection(CodeDescription *desc)
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001643#ifdef __ELF
1644 : ELFSection(".eh_frame", TYPE_X86_64_UNWIND, 1),
1645#else
1646 : MachOSection("__eh_frame", "__TEXT", sizeof(uintptr_t),
1647 MachOSection::S_REGULAR),
1648#endif
1649 desc_(desc) { }
Steve Block1e0659c2011-05-24 12:43:12 +01001650
1651int UnwindInfoSection::WriteCIE(Writer *w) {
1652 Writer::Slot<uint32_t> cie_length_slot = w->CreateSlotHere<uint32_t>();
1653 uint32_t cie_position = w->position();
1654
1655 // Write out the CIE header. Currently no 'common instructions' are
1656 // emitted onto the CIE; every FDE has its own set of instructions.
1657
1658 w->Write<uint32_t>(CIE_ID);
1659 w->Write<uint8_t>(CIE_VERSION);
1660 w->Write<uint8_t>(0); // Null augmentation string.
1661 w->WriteSLEB128(CODE_ALIGN_FACTOR);
1662 w->WriteSLEB128(DATA_ALIGN_FACTOR);
1663 w->Write<uint8_t>(RETURN_ADDRESS_REGISTER);
1664
1665 WriteLength(w, &cie_length_slot, cie_position);
1666
1667 return cie_position;
1668}
1669
1670
1671void UnwindInfoSection::WriteFDE(Writer *w, int cie_position) {
1672 // The only FDE for this function. The CFA is the current RBP.
1673 Writer::Slot<uint32_t> fde_length_slot = w->CreateSlotHere<uint32_t>();
1674 int fde_position = w->position();
1675 w->Write<int32_t>(fde_position - cie_position + 4);
1676
1677 w->Write<uintptr_t>(desc_->CodeStart());
1678 w->Write<uintptr_t>(desc_->CodeSize());
1679
1680 WriteFDEStateOnEntry(w);
1681 WriteFDEStateAfterRBPPush(w);
1682 WriteFDEStateAfterRBPSet(w);
1683 WriteFDEStateAfterRBPPop(w);
1684
1685 WriteLength(w, &fde_length_slot, fde_position);
1686}
1687
1688
1689void UnwindInfoSection::WriteFDEStateOnEntry(Writer *w) {
1690 // The first state, just after the control has been transferred to the the
1691 // function.
1692
1693 // RBP for this function will be the value of RSP after pushing the RBP
1694 // for the previous function. The previous RBP has not been pushed yet.
1695 w->Write<uint8_t>(DW_CFA_DEF_CFA_SF);
1696 w->WriteULEB128(AMD64_RSP);
1697 w->WriteSLEB128(-kPointerSize);
1698
1699 // The RA is stored at location CFA + kCallerPCOffset. This is an invariant,
1700 // and hence omitted from the next states.
1701 w->Write<uint8_t>(DW_CFA_OFFSET_EXTENDED);
1702 w->WriteULEB128(AMD64_RA);
1703 w->WriteSLEB128(StandardFrameConstants::kCallerPCOffset);
1704
1705 // The RBP of the previous function is still in RBP.
1706 w->Write<uint8_t>(DW_CFA_SAME_VALUE);
1707 w->WriteULEB128(AMD64_RBP);
1708
1709 // Last location described by this entry.
1710 w->Write<uint8_t>(DW_CFA_SET_LOC);
1711 w->Write<uint64_t>(
1712 desc_->GetStackStateStartAddress(CodeDescription::POST_RBP_PUSH));
1713}
1714
1715
1716void UnwindInfoSection::WriteFDEStateAfterRBPPush(Writer *w) {
1717 // The second state, just after RBP has been pushed.
1718
1719 // RBP / CFA for this function is now the current RSP, so just set the
1720 // offset from the previous rule (from -8) to 0.
1721 w->Write<uint8_t>(DW_CFA_DEF_CFA_OFFSET);
1722 w->WriteULEB128(0);
1723
1724 // The previous RBP is stored at CFA + kCallerFPOffset. This is an invariant
1725 // in this and the next state, and hence omitted in the next state.
1726 w->Write<uint8_t>(DW_CFA_OFFSET_EXTENDED);
1727 w->WriteULEB128(AMD64_RBP);
1728 w->WriteSLEB128(StandardFrameConstants::kCallerFPOffset);
1729
1730 // Last location described by this entry.
1731 w->Write<uint8_t>(DW_CFA_SET_LOC);
1732 w->Write<uint64_t>(
1733 desc_->GetStackStateStartAddress(CodeDescription::POST_RBP_SET));
1734}
1735
1736
1737void UnwindInfoSection::WriteFDEStateAfterRBPSet(Writer *w) {
1738 // The third state, after the RBP has been set.
1739
1740 // The CFA can now directly be set to RBP.
1741 w->Write<uint8_t>(DW_CFA_DEF_CFA);
1742 w->WriteULEB128(AMD64_RBP);
1743 w->WriteULEB128(0);
1744
1745 // Last location described by this entry.
1746 w->Write<uint8_t>(DW_CFA_SET_LOC);
1747 w->Write<uint64_t>(
1748 desc_->GetStackStateStartAddress(CodeDescription::POST_RBP_POP));
1749}
1750
1751
1752void UnwindInfoSection::WriteFDEStateAfterRBPPop(Writer *w) {
1753 // The fourth (final) state. The RBP has been popped (just before issuing a
1754 // return).
1755
1756 // The CFA can is now calculated in the same way as in the first state.
1757 w->Write<uint8_t>(DW_CFA_DEF_CFA_SF);
1758 w->WriteULEB128(AMD64_RSP);
1759 w->WriteSLEB128(-kPointerSize);
1760
1761 // The RBP
1762 w->Write<uint8_t>(DW_CFA_OFFSET_EXTENDED);
1763 w->WriteULEB128(AMD64_RBP);
1764 w->WriteSLEB128(StandardFrameConstants::kCallerFPOffset);
1765
1766 // Last location described by this entry.
1767 w->Write<uint8_t>(DW_CFA_SET_LOC);
1768 w->Write<uint64_t>(desc_->CodeEnd());
1769}
1770
1771
1772bool UnwindInfoSection::WriteBody(Writer *w) {
1773 uint32_t cie_position = WriteCIE(w);
1774 WriteFDE(w, cie_position);
1775 return true;
1776}
1777
1778
1779#endif // V8_TARGET_ARCH_X64
1780
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001781static void CreateDWARFSections(CodeDescription* desc, DebugObject* obj) {
Steve Block1e0659c2011-05-24 12:43:12 +01001782 if (desc->IsLineInfoAvailable()) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001783 obj->AddSection(new DebugInfoSection(desc));
1784 obj->AddSection(new DebugAbbrevSection(desc));
1785 obj->AddSection(new DebugLineSection(desc));
Ben Murdochb8e0da22011-05-16 14:20:40 +01001786 }
Steve Block1e0659c2011-05-24 12:43:12 +01001787#ifdef V8_TARGET_ARCH_X64
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001788 obj->AddSection(new UnwindInfoSection(desc));
Steve Block1e0659c2011-05-24 12:43:12 +01001789#endif
Ben Murdochb8e0da22011-05-16 14:20:40 +01001790}
1791
1792
1793// -------------------------------------------------------------------
1794// Binary GDB JIT Interface as described in
1795// http://sourceware.org/gdb/onlinedocs/gdb/Declarations.html
1796extern "C" {
1797 typedef enum {
1798 JIT_NOACTION = 0,
1799 JIT_REGISTER_FN,
1800 JIT_UNREGISTER_FN
1801 } JITAction;
1802
1803 struct JITCodeEntry {
1804 JITCodeEntry* next_;
1805 JITCodeEntry* prev_;
1806 Address symfile_addr_;
1807 uint64_t symfile_size_;
1808 };
1809
1810 struct JITDescriptor {
1811 uint32_t version_;
1812 uint32_t action_flag_;
1813 JITCodeEntry *relevant_entry_;
1814 JITCodeEntry *first_entry_;
1815 };
1816
1817 // GDB will place breakpoint into this function.
1818 // To prevent GCC from inlining or removing it we place noinline attribute
1819 // and inline assembler statement inside.
1820 void __attribute__((noinline)) __jit_debug_register_code() {
1821 __asm__("");
1822 }
1823
1824 // GDB will inspect contents of this descriptor.
1825 // Static initialization is necessary to prevent GDB from seeing
1826 // uninitialized descriptor.
1827 JITDescriptor __jit_debug_descriptor = { 1, 0, 0, 0 };
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001828
1829#ifdef OBJECT_PRINT
1830 void __gdb_print_v8_object(MaybeObject* object) {
1831 object->Print();
1832 fprintf(stdout, "\n");
1833 }
1834#endif
Ben Murdochb8e0da22011-05-16 14:20:40 +01001835}
1836
1837
1838static JITCodeEntry* CreateCodeEntry(Address symfile_addr,
1839 uintptr_t symfile_size) {
1840 JITCodeEntry* entry = static_cast<JITCodeEntry*>(
1841 malloc(sizeof(JITCodeEntry) + symfile_size));
1842
1843 entry->symfile_addr_ = reinterpret_cast<Address>(entry + 1);
1844 entry->symfile_size_ = symfile_size;
1845 memcpy(entry->symfile_addr_, symfile_addr, symfile_size);
1846
1847 entry->prev_ = entry->next_ = NULL;
1848
1849 return entry;
1850}
1851
1852
1853static void DestroyCodeEntry(JITCodeEntry* entry) {
1854 free(entry);
1855}
1856
1857
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001858static void RegisterCodeEntry(JITCodeEntry* entry,
1859 bool dump_if_enabled,
1860 const char* name_hint) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001861#if defined(DEBUG) && !defined(WIN32)
1862 static int file_num = 0;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001863 if (FLAG_gdbjit_dump && dump_if_enabled) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001864 static const int kMaxFileNameSize = 64;
1865 static const char* kElfFilePrefix = "/tmp/elfdump";
1866 static const char* kObjFileExt = ".o";
1867 char file_name[64];
1868
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001869 OS::SNPrintF(Vector<char>(file_name, kMaxFileNameSize),
1870 "%s%s%d%s",
1871 kElfFilePrefix,
1872 (name_hint != NULL) ? name_hint : "",
1873 file_num++,
1874 kObjFileExt);
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001875 WriteBytes(file_name, entry->symfile_addr_, entry->symfile_size_);
1876 }
1877#endif
1878
Ben Murdochb8e0da22011-05-16 14:20:40 +01001879 entry->next_ = __jit_debug_descriptor.first_entry_;
1880 if (entry->next_ != NULL) entry->next_->prev_ = entry;
1881 __jit_debug_descriptor.first_entry_ =
1882 __jit_debug_descriptor.relevant_entry_ = entry;
1883
1884 __jit_debug_descriptor.action_flag_ = JIT_REGISTER_FN;
1885 __jit_debug_register_code();
1886}
1887
1888
1889static void UnregisterCodeEntry(JITCodeEntry* entry) {
1890 if (entry->prev_ != NULL) {
1891 entry->prev_->next_ = entry->next_;
1892 } else {
1893 __jit_debug_descriptor.first_entry_ = entry->next_;
1894 }
1895
1896 if (entry->next_ != NULL) {
1897 entry->next_->prev_ = entry->prev_;
1898 }
1899
1900 __jit_debug_descriptor.relevant_entry_ = entry;
1901 __jit_debug_descriptor.action_flag_ = JIT_UNREGISTER_FN;
1902 __jit_debug_register_code();
1903}
1904
1905
1906static JITCodeEntry* CreateELFObject(CodeDescription* desc) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001907 ZoneScope zone_scope(Isolate::Current(), DELETE_ON_EXIT);
1908#ifdef __MACH_O
1909 MachO mach_o;
1910 Writer w(&mach_o);
Ben Murdochb8e0da22011-05-16 14:20:40 +01001911
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001912 mach_o.AddSection(new MachOTextSection(kCodeAlignment,
1913 desc->CodeStart(),
1914 desc->CodeSize()));
1915
1916 CreateDWARFSections(desc, &mach_o);
1917
1918 mach_o.Write(&w, desc->CodeStart(), desc->CodeSize());
1919#else
Ben Murdochb8e0da22011-05-16 14:20:40 +01001920 ELF elf;
1921 Writer w(&elf);
1922
1923 int text_section_index = elf.AddSection(
1924 new FullHeaderELFSection(".text",
1925 ELFSection::TYPE_NOBITS,
1926 kCodeAlignment,
Steve Block1e0659c2011-05-24 12:43:12 +01001927 desc->CodeStart(),
Ben Murdochb8e0da22011-05-16 14:20:40 +01001928 0,
Steve Block1e0659c2011-05-24 12:43:12 +01001929 desc->CodeSize(),
Ben Murdochb8e0da22011-05-16 14:20:40 +01001930 ELFSection::FLAG_ALLOC | ELFSection::FLAG_EXEC));
1931
1932 CreateSymbolsTable(desc, &elf, text_section_index);
1933
1934 CreateDWARFSections(desc, &elf);
1935
1936 elf.Write(&w);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001937#endif
Ben Murdochb8e0da22011-05-16 14:20:40 +01001938
1939 return CreateCodeEntry(w.buffer(), w.position());
1940}
1941
1942
1943static bool SameCodeObjects(void* key1, void* key2) {
1944 return key1 == key2;
1945}
1946
1947
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001948static HashMap* GetEntries() {
1949 static HashMap* entries = NULL;
1950 if (entries == NULL) {
1951 entries = new HashMap(&SameCodeObjects);
1952 }
1953 return entries;
1954}
Ben Murdochb8e0da22011-05-16 14:20:40 +01001955
1956
1957static uint32_t HashForCodeObject(Code* code) {
1958 static const uintptr_t kGoldenRatio = 2654435761u;
1959 uintptr_t hash = reinterpret_cast<uintptr_t>(code->address());
1960 return static_cast<uint32_t>((hash >> kCodeAlignmentBits) * kGoldenRatio);
1961}
1962
1963
1964static const intptr_t kLineInfoTag = 0x1;
1965
1966
1967static bool IsLineInfoTagged(void* ptr) {
1968 return 0 != (reinterpret_cast<intptr_t>(ptr) & kLineInfoTag);
1969}
1970
1971
1972static void* TagLineInfo(GDBJITLineInfo* ptr) {
1973 return reinterpret_cast<void*>(
1974 reinterpret_cast<intptr_t>(ptr) | kLineInfoTag);
1975}
1976
1977
1978static GDBJITLineInfo* UntagLineInfo(void* ptr) {
1979 return reinterpret_cast<GDBJITLineInfo*>(
1980 reinterpret_cast<intptr_t>(ptr) & ~kLineInfoTag);
1981}
1982
1983
1984void GDBJITInterface::AddCode(Handle<String> name,
1985 Handle<Script> script,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001986 Handle<Code> code,
1987 CompilationInfo* info) {
Ben Murdochb8e0da22011-05-16 14:20:40 +01001988 if (!FLAG_gdbjit) return;
1989
1990 // Force initialization of line_ends array.
1991 GetScriptLineNumber(script, 0);
1992
1993 if (!name.is_null()) {
Ben Murdoch589d6972011-11-30 16:04:58 +00001994 SmartArrayPointer<char> name_cstring = name->ToCString(DISALLOW_NULLS);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001995 AddCode(*name_cstring, *code, GDBJITInterface::FUNCTION, *script, info);
Ben Murdochb8e0da22011-05-16 14:20:40 +01001996 } else {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001997 AddCode("", *code, GDBJITInterface::FUNCTION, *script, info);
Ben Murdochb8e0da22011-05-16 14:20:40 +01001998 }
1999}
2000
Steve Block1e0659c2011-05-24 12:43:12 +01002001static void AddUnwindInfo(CodeDescription *desc) {
2002#ifdef V8_TARGET_ARCH_X64
2003 if (desc->tag() == GDBJITInterface::FUNCTION) {
2004 // To avoid propagating unwinding information through
Ben Murdoche0cee9b2011-05-25 10:26:03 +01002005 // compilation pipeline we use an approximation.
2006 // For most use cases this should not affect usability.
Steve Block1e0659c2011-05-24 12:43:12 +01002007 static const int kFramePointerPushOffset = 1;
2008 static const int kFramePointerSetOffset = 4;
2009 static const int kFramePointerPopOffset = -3;
2010
2011 uintptr_t frame_pointer_push_address =
2012 desc->CodeStart() + kFramePointerPushOffset;
2013
2014 uintptr_t frame_pointer_set_address =
2015 desc->CodeStart() + kFramePointerSetOffset;
2016
2017 uintptr_t frame_pointer_pop_address =
2018 desc->CodeEnd() + kFramePointerPopOffset;
2019
Steve Block1e0659c2011-05-24 12:43:12 +01002020 desc->SetStackStateStartAddress(CodeDescription::POST_RBP_PUSH,
2021 frame_pointer_push_address);
2022 desc->SetStackStateStartAddress(CodeDescription::POST_RBP_SET,
2023 frame_pointer_set_address);
2024 desc->SetStackStateStartAddress(CodeDescription::POST_RBP_POP,
2025 frame_pointer_pop_address);
2026 } else {
2027 desc->SetStackStateStartAddress(CodeDescription::POST_RBP_PUSH,
2028 desc->CodeStart());
2029 desc->SetStackStateStartAddress(CodeDescription::POST_RBP_SET,
2030 desc->CodeStart());
2031 desc->SetStackStateStartAddress(CodeDescription::POST_RBP_POP,
2032 desc->CodeEnd());
2033 }
2034#endif // V8_TARGET_ARCH_X64
2035}
2036
Ben Murdochb8e0da22011-05-16 14:20:40 +01002037
Ben Murdoch8b112d22011-06-08 16:22:53 +01002038Mutex* GDBJITInterface::mutex_ = OS::CreateMutex();
2039
2040
Ben Murdochb8e0da22011-05-16 14:20:40 +01002041void GDBJITInterface::AddCode(const char* name,
2042 Code* code,
Steve Block1e0659c2011-05-24 12:43:12 +01002043 GDBJITInterface::CodeTag tag,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002044 Script* script,
2045 CompilationInfo* info) {
Ben Murdochb8e0da22011-05-16 14:20:40 +01002046 if (!FLAG_gdbjit) return;
Ben Murdoch8b112d22011-06-08 16:22:53 +01002047
2048 ScopedLock lock(mutex_);
Ben Murdochb8e0da22011-05-16 14:20:40 +01002049 AssertNoAllocation no_gc;
2050
Ben Murdoche0cee9b2011-05-25 10:26:03 +01002051 HashMap::Entry* e = GetEntries()->Lookup(code, HashForCodeObject(code), true);
Ben Murdochb8e0da22011-05-16 14:20:40 +01002052 if (e->value != NULL && !IsLineInfoTagged(e->value)) return;
2053
2054 GDBJITLineInfo* lineinfo = UntagLineInfo(e->value);
2055 CodeDescription code_desc(name,
2056 code,
2057 script != NULL ? Handle<Script>(script)
2058 : Handle<Script>(),
Steve Block1e0659c2011-05-24 12:43:12 +01002059 lineinfo,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002060 tag,
2061 info);
Ben Murdochb8e0da22011-05-16 14:20:40 +01002062
Steve Block1e0659c2011-05-24 12:43:12 +01002063 if (!FLAG_gdbjit_full && !code_desc.IsLineInfoAvailable()) {
Ben Murdochb8e0da22011-05-16 14:20:40 +01002064 delete lineinfo;
Ben Murdoche0cee9b2011-05-25 10:26:03 +01002065 GetEntries()->Remove(code, HashForCodeObject(code));
Ben Murdochb8e0da22011-05-16 14:20:40 +01002066 return;
2067 }
2068
Steve Block1e0659c2011-05-24 12:43:12 +01002069 AddUnwindInfo(&code_desc);
Ben Murdochb8e0da22011-05-16 14:20:40 +01002070 JITCodeEntry* entry = CreateELFObject(&code_desc);
2071 ASSERT(!IsLineInfoTagged(entry));
2072
2073 delete lineinfo;
2074 e->value = entry;
2075
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002076 const char* name_hint = NULL;
2077 bool should_dump = false;
2078 if (FLAG_gdbjit_dump) {
2079 if (strlen(FLAG_gdbjit_dump_filter) == 0) {
2080 name_hint = name;
2081 should_dump = true;
2082 } else if (name != NULL) {
2083 name_hint = strstr(name, FLAG_gdbjit_dump_filter);
2084 should_dump = (name_hint != NULL);
2085 }
2086 }
2087 RegisterCodeEntry(entry, should_dump, name_hint);
Ben Murdochb8e0da22011-05-16 14:20:40 +01002088}
2089
2090
2091void GDBJITInterface::AddCode(GDBJITInterface::CodeTag tag,
2092 const char* name,
2093 Code* code) {
2094 if (!FLAG_gdbjit) return;
2095
2096 EmbeddedVector<char, 256> buffer;
2097 StringBuilder builder(buffer.start(), buffer.length());
2098
2099 builder.AddString(Tag2String(tag));
2100 if ((name != NULL) && (*name != '\0')) {
2101 builder.AddString(": ");
2102 builder.AddString(name);
2103 } else {
2104 builder.AddFormatted(": code object %p", static_cast<void*>(code));
2105 }
2106
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002107 AddCode(builder.Finalize(), code, tag, NULL, NULL);
Ben Murdochb8e0da22011-05-16 14:20:40 +01002108}
2109
2110
2111void GDBJITInterface::AddCode(GDBJITInterface::CodeTag tag,
2112 String* name,
2113 Code* code) {
2114 if (!FLAG_gdbjit) return;
2115 AddCode(tag, name != NULL ? *name->ToCString(DISALLOW_NULLS) : NULL, code);
2116}
2117
2118
2119void GDBJITInterface::AddCode(GDBJITInterface::CodeTag tag, Code* code) {
2120 if (!FLAG_gdbjit) return;
2121
2122 AddCode(tag, "", code);
2123}
2124
2125
2126void GDBJITInterface::RemoveCode(Code* code) {
2127 if (!FLAG_gdbjit) return;
2128
Ben Murdoch8b112d22011-06-08 16:22:53 +01002129 ScopedLock lock(mutex_);
Ben Murdoche0cee9b2011-05-25 10:26:03 +01002130 HashMap::Entry* e = GetEntries()->Lookup(code,
2131 HashForCodeObject(code),
2132 false);
Ben Murdochb8e0da22011-05-16 14:20:40 +01002133 if (e == NULL) return;
2134
2135 if (IsLineInfoTagged(e->value)) {
2136 delete UntagLineInfo(e->value);
2137 } else {
2138 JITCodeEntry* entry = static_cast<JITCodeEntry*>(e->value);
2139 UnregisterCodeEntry(entry);
2140 DestroyCodeEntry(entry);
2141 }
2142 e->value = NULL;
Ben Murdoche0cee9b2011-05-25 10:26:03 +01002143 GetEntries()->Remove(code, HashForCodeObject(code));
Ben Murdochb8e0da22011-05-16 14:20:40 +01002144}
2145
2146
2147void GDBJITInterface::RegisterDetailedLineInfo(Code* code,
2148 GDBJITLineInfo* line_info) {
Ben Murdoch8b112d22011-06-08 16:22:53 +01002149 ScopedLock lock(mutex_);
Ben Murdochb8e0da22011-05-16 14:20:40 +01002150 ASSERT(!IsLineInfoTagged(line_info));
Ben Murdoche0cee9b2011-05-25 10:26:03 +01002151 HashMap::Entry* e = GetEntries()->Lookup(code, HashForCodeObject(code), true);
Ben Murdochb8e0da22011-05-16 14:20:40 +01002152 ASSERT(e->value == NULL);
2153 e->value = TagLineInfo(line_info);
2154}
2155
2156
2157} } // namespace v8::internal
2158#endif