blob: e73b7337e75f85a383b65219038c8cef8e20495d [file] [log] [blame]
Ben Murdochb8e0da22011-05-16 14:20:40 +01001// Copyright 2010 the V8 project authors. All rights reserved.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
Ben Murdochb8e0da22011-05-16 14:20:40 +01004
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005#include "src/gdb-jit.h"
Ben Murdochb8e0da22011-05-16 14:20:40 +01006
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007#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"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013#include "src/global-handles.h"
14#include "src/messages.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015#include "src/objects.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016#include "src/ostreams.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017#include "src/snapshot/natives.h"
18#include "src/splay-tree-inl.h"
Ben Murdochb8e0da22011-05-16 14:20:40 +010019
20namespace v8 {
21namespace internal {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022namespace GDBJITInterface {
23
24#ifdef ENABLE_GDB_JIT_INTERFACE
Ben Murdochb8e0da22011-05-16 14:20:40 +010025
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000026#ifdef __APPLE__
27#define __MACH_O
28class MachO;
29class MachOSection;
30typedef MachO DebugObject;
31typedef MachOSection DebugSection;
32#else
33#define __ELF
Ben Murdochb8e0da22011-05-16 14:20:40 +010034class ELF;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000035class ELFSection;
36typedef ELF DebugObject;
37typedef ELFSection DebugSection;
38#endif
Ben Murdochb8e0da22011-05-16 14:20:40 +010039
40class Writer BASE_EMBEDDED {
41 public:
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000042 explicit Writer(DebugObject* debug_object)
43 : debug_object_(debug_object),
Ben Murdochb8e0da22011-05-16 14:20:40 +010044 position_(0),
45 capacity_(1024),
46 buffer_(reinterpret_cast<byte*>(malloc(capacity_))) {
47 }
48
49 ~Writer() {
50 free(buffer_);
51 }
52
53 uintptr_t position() const {
54 return position_;
55 }
56
57 template<typename T>
58 class Slot {
59 public:
60 Slot(Writer* w, uintptr_t offset) : w_(w), offset_(offset) { }
61
62 T* operator-> () {
63 return w_->RawSlotAt<T>(offset_);
64 }
65
66 void set(const T& value) {
67 *w_->RawSlotAt<T>(offset_) = value;
68 }
69
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>
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>
87 Slot<T> SlotAt(uintptr_t offset) {
88 Ensure(offset + sizeof(T));
89 return Slot<T>(this, offset);
90 }
91
92 template<typename T>
93 Slot<T> CreateSlotHere() {
94 return CreateSlotsHere<T>(1);
95 }
96
97 template<typename T>
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
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
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000112 DebugObject* debug_object() { return debug_object_; }
Ben Murdochb8e0da22011-05-16 14:20:40 +0100113
114 byte* buffer() { return buffer_; }
115
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);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000121 DCHECK((position_ % align) == 0);
Ben Murdochb8e0da22011-05-16 14:20:40 +0100122 }
123
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
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
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>
160 T* RawSlotAt(uintptr_t offset) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000161 DCHECK(offset < capacity_ && offset + sizeof(T) <= capacity_);
Ben Murdochb8e0da22011-05-16 14:20:40 +0100162 return reinterpret_cast<T*>(&buffer_[offset]);
163 }
164
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000165 DebugObject* debug_object_;
Ben Murdochb8e0da22011-05-16 14:20:40 +0100166 uintptr_t position_;
167 uintptr_t capacity_;
168 byte* buffer_;
169};
170
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000171class ELFStringTable;
Ben Murdochb8e0da22011-05-16 14:20:40 +0100172
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000173template<typename THeader>
174class DebugSectionBase : public ZoneObject {
Ben Murdochb8e0da22011-05-16 14:20:40 +0100175 public:
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000176 virtual ~DebugSectionBase() { }
177
178 virtual void WriteBody(Writer::Slot<THeader> header, Writer* writer) {
179 uintptr_t start = writer->position();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000180 if (WriteBodyInternal(writer)) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000181 uintptr_t end = writer->position();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000182 header->offset = static_cast<uint32_t>(start);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000183#if defined(__MACH_O)
184 header->addr = 0;
185#endif
186 header->size = end - start;
187 }
188 }
189
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000190 virtual bool WriteBodyInternal(Writer* writer) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000191 return false;
192 }
193
194 typedef THeader Header;
195};
196
197
198struct MachOSectionHeader {
199 char sectname[16];
200 char segname[16];
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000201#if V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_X87
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000202 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
218class 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
Ben Murdochb8e0da22011-05-16 14:20:40 +0100226 };
227
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000228 MachOSection(const char* name, const char* segment, uint32_t align,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000229 uint32_t flags)
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000230 : name_(name), segment_(segment), align_(align), flags_(flags) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000231 if (align_ != 0) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000232 DCHECK(base::bits::IsPowerOfTwo32(align));
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000233 align_ = WhichPowerOf2(align_);
234 }
235 }
236
237 virtual ~MachOSection() { }
238
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));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000251 DCHECK(strlen(name_) < sizeof(header->sectname));
252 DCHECK(strlen(segment_) < sizeof(header->segname));
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000253 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_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000260 uint32_t align_;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000261 uint32_t flags_;
262};
263
264
265struct 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)
280class ELFSection : public DebugSectionBase<ELFSectionHeader> {
281 public:
Ben Murdochb8e0da22011-05-16 14:20:40 +0100282 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,
Steve Block1e0659c2011-05-24 12:43:12 +0100296 TYPE_X86_64_UNWIND = 0x70000001,
Ben Murdochb8e0da22011-05-16 14:20:40 +0100297 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
312 ELFSection(const char* name, Type type, uintptr_t align)
313 : name_(name), type_(type), align_(align) { }
314
315 virtual ~ELFSection() { }
316
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000317 void PopulateHeader(Writer::Slot<Header> header, ELFStringTable* strtab);
Ben Murdochb8e0da22011-05-16 14:20:40 +0100318
319 virtual void WriteBody(Writer::Slot<Header> header, Writer* w) {
320 uintptr_t start = w->position();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000321 if (WriteBodyInternal(w)) {
Ben Murdochb8e0da22011-05-16 14:20:40 +0100322 uintptr_t end = w->position();
323 header->offset = start;
324 header->size = end - start;
325 }
326 }
327
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000328 virtual bool WriteBodyInternal(Writer* w) {
Ben Murdochb8e0da22011-05-16 14:20:40 +0100329 return false;
330 }
331
332 uint16_t index() const { return index_; }
333 void set_index(uint16_t index) { index_ = index; }
334
335 protected:
336 virtual void PopulateHeader(Writer::Slot<Header> header) {
337 header->flags = 0;
338 header->address = 0;
339 header->offset = 0;
340 header->size = 0;
341 header->link = 0;
342 header->info = 0;
343 header->entry_size = 0;
344 }
345
Ben Murdochb8e0da22011-05-16 14:20:40 +0100346 private:
347 const char* name_;
348 Type type_;
349 uintptr_t align_;
350 uint16_t index_;
351};
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000352#endif // defined(__ELF)
Ben Murdochb8e0da22011-05-16 14:20:40 +0100353
354
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000355#if defined(__MACH_O)
356class MachOTextSection : public MachOSection {
357 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000358 MachOTextSection(uint32_t align, uintptr_t addr, uintptr_t size)
359 : MachOSection("__text", "__TEXT", align,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000360 MachOSection::S_REGULAR |
361 MachOSection::S_ATTR_SOME_INSTRUCTIONS |
362 MachOSection::S_ATTR_PURE_INSTRUCTIONS),
363 addr_(addr),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000364 size_(size) {}
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000365
366 protected:
367 virtual void PopulateHeader(Writer::Slot<Header> header) {
368 MachOSection::PopulateHeader(header);
369 header->addr = addr_;
370 header->size = size_;
371 }
372
373 private:
374 uintptr_t addr_;
375 uintptr_t size_;
376};
377#endif // defined(__MACH_O)
378
379
380#if defined(__ELF)
Ben Murdochb8e0da22011-05-16 14:20:40 +0100381class FullHeaderELFSection : public ELFSection {
382 public:
383 FullHeaderELFSection(const char* name,
384 Type type,
385 uintptr_t align,
386 uintptr_t addr,
387 uintptr_t offset,
388 uintptr_t size,
389 uintptr_t flags)
390 : ELFSection(name, type, align),
391 addr_(addr),
392 offset_(offset),
393 size_(size),
394 flags_(flags) { }
395
396 protected:
397 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
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000413class ELFStringTable : public ELFSection {
Ben Murdochb8e0da22011-05-16 14:20:40 +0100414 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000415 explicit ELFStringTable(const char* name)
Ben Murdochb8e0da22011-05-16 14:20:40 +0100416 : ELFSection(name, TYPE_STRTAB, 1), writer_(NULL), offset_(0), size_(0) {
417 }
418
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
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
435 void DetachWriter() {
436 writer_ = NULL;
437 }
438
439 virtual void WriteBody(Writer::Slot<Header> header, Writer* w) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000440 DCHECK(writer_ == NULL);
Ben Murdochb8e0da22011-05-16 14:20:40 +0100441 header->offset = offset_;
442 header->size = size_;
443 }
444
445 private:
446 void WriteString(const char* str) {
447 uintptr_t written = 0;
448 do {
449 writer_->Write(*str);
450 written++;
451 } while (*str++);
452 size_ += written;
453 }
454
455 Writer* writer_;
456
457 uintptr_t offset_;
458 uintptr_t size_;
459};
460
461
462void ELFSection::PopulateHeader(Writer::Slot<ELFSection::Header> header,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000463 ELFStringTable* strtab) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000464 header->name = static_cast<uint32_t>(strtab->Add(name_));
Ben Murdochb8e0da22011-05-16 14:20:40 +0100465 header->type = type_;
466 header->alignment = align_;
467 PopulateHeader(header);
468}
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000469#endif // defined(__ELF)
Ben Murdochb8e0da22011-05-16 14:20:40 +0100470
471
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000472#if defined(__MACH_O)
473class MachO BASE_EMBEDDED {
474 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000475 explicit MachO(Zone* zone) : zone_(zone), sections_(6, zone) { }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000476
477 uint32_t AddSection(MachOSection* section) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000478 sections_.Add(section, zone_);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000479 return sections_.length() - 1;
480 }
481
482 void Write(Writer* w, uintptr_t code_start, uintptr_t code_size) {
483 Writer::Slot<MachOHeader> header = WriteHeader(w);
484 uintptr_t load_command_start = w->position();
485 Writer::Slot<MachOSegmentCommand> cmd = WriteSegmentCommand(w,
486 code_start,
487 code_size);
488 WriteSections(w, cmd, header, load_command_start);
489 }
490
491 private:
492 struct MachOHeader {
493 uint32_t magic;
494 uint32_t cputype;
495 uint32_t cpusubtype;
496 uint32_t filetype;
497 uint32_t ncmds;
498 uint32_t sizeofcmds;
499 uint32_t flags;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000500#if V8_TARGET_ARCH_X64
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000501 uint32_t reserved;
502#endif
503 };
504
505 struct MachOSegmentCommand {
506 uint32_t cmd;
507 uint32_t cmdsize;
508 char segname[16];
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000509#if V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_X87
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000510 uint32_t vmaddr;
511 uint32_t vmsize;
512 uint32_t fileoff;
513 uint32_t filesize;
514#else
515 uint64_t vmaddr;
516 uint64_t vmsize;
517 uint64_t fileoff;
518 uint64_t filesize;
519#endif
520 uint32_t maxprot;
521 uint32_t initprot;
522 uint32_t nsects;
523 uint32_t flags;
524 };
525
526 enum MachOLoadCommandCmd {
527 LC_SEGMENT_32 = 0x00000001u,
528 LC_SEGMENT_64 = 0x00000019u
529 };
530
531
532 Writer::Slot<MachOHeader> WriteHeader(Writer* w) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000533 DCHECK(w->position() == 0);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000534 Writer::Slot<MachOHeader> header = w->CreateSlotHere<MachOHeader>();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000535#if V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_X87
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000536 header->magic = 0xFEEDFACEu;
537 header->cputype = 7; // i386
538 header->cpusubtype = 3; // CPU_SUBTYPE_I386_ALL
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000539#elif V8_TARGET_ARCH_X64
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000540 header->magic = 0xFEEDFACFu;
541 header->cputype = 7 | 0x01000000; // i386 | 64-bit ABI
542 header->cpusubtype = 3; // CPU_SUBTYPE_I386_ALL
543 header->reserved = 0;
544#else
545#error Unsupported target architecture.
546#endif
547 header->filetype = 0x1; // MH_OBJECT
548 header->ncmds = 1;
549 header->sizeofcmds = 0;
550 header->flags = 0;
551 return header;
552 }
553
554
555 Writer::Slot<MachOSegmentCommand> WriteSegmentCommand(Writer* w,
556 uintptr_t code_start,
557 uintptr_t code_size) {
558 Writer::Slot<MachOSegmentCommand> cmd =
559 w->CreateSlotHere<MachOSegmentCommand>();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000560#if V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_X87
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000561 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
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();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000587 header->sizeofcmds =
588 static_cast<uint32_t>(w->position() - load_command_start);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000589 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
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000596 Zone* zone_;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000597 ZoneList<MachOSection*> sections_;
598};
599#endif // defined(__MACH_O)
600
601
602#if defined(__ELF)
Ben Murdochb8e0da22011-05-16 14:20:40 +0100603class ELF BASE_EMBEDDED {
604 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000605 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);
Ben Murdochb8e0da22011-05-16 14:20:40 +0100608 }
609
610 void Write(Writer* w) {
611 WriteHeader(w);
612 WriteSectionTable(w);
613 WriteSections(w);
614 }
615
616 ELFSection* SectionAt(uint32_t index) {
617 return sections_[index];
618 }
619
620 uint32_t AddSection(ELFSection* section) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000621 sections_.Add(section, zone_);
Ben Murdochb8e0da22011-05-16 14:20:40 +0100622 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
645 void WriteHeader(Writer* w) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000646 DCHECK(w->position() == 0);
Ben Murdochb8e0da22011-05-16 14:20:40 +0100647 Writer::Slot<ELFHeader> header = w->CreateSlotHere<ELFHeader>();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000648#if (V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_X87 || \
649 (V8_TARGET_ARCH_X64 && V8_TARGET_ARCH_32_BIT))
Ben Murdochb8e0da22011-05-16 14:20:40 +0100650 const uint8_t ident[16] =
651 { 0x7f, 'E', 'L', 'F', 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000652#elif(V8_TARGET_ARCH_X64 && V8_TARGET_ARCH_64_BIT) || \
653 (V8_TARGET_ARCH_PPC64 && V8_TARGET_LITTLE_ENDIAN)
Ben Murdochb8e0da22011-05-16 14:20:40 +0100654 const uint8_t ident[16] =
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000655 { 0x7f, 'E', 'L', 'F', 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000656#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};
Ben Murdochda12d292016-06-02 14:46:10 +0100659#elif V8_TARGET_ARCH_S390X
660 const uint8_t ident[16] = {0x7f, 'E', 'L', 'F', 2, 2, 1, 3,
661 0, 0, 0, 0, 0, 0, 0, 0};
662#elif V8_TARGET_ARCH_S390
663 const uint8_t ident[16] = {0x7f, 'E', 'L', 'F', 1, 2, 1, 3,
664 0, 0, 0, 0, 0, 0, 0, 0};
Ben Murdochb8e0da22011-05-16 14:20:40 +0100665#else
666#error Unsupported target architecture.
667#endif
668 memcpy(header->ident, ident, 16);
669 header->type = 1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000670#if V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_X87
Ben Murdochb8e0da22011-05-16 14:20:40 +0100671 header->machine = 3;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000672#elif V8_TARGET_ARCH_X64
Ben Murdochb8e0da22011-05-16 14:20:40 +0100673 // Processor identification value for x64 is 62 as defined in
674 // System V ABI, AMD64 Supplement
675 // http://www.x86-64.org/documentation/abi.pdf
676 header->machine = 62;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000677#elif V8_TARGET_ARCH_ARM
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100678 // Set to EM_ARM, defined as 40, in "ARM ELF File Format" at
679 // infocenter.arm.com/help/topic/com.arm.doc.dui0101a/DUI0101A_Elf.pdf
680 header->machine = 40;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000681#elif V8_TARGET_ARCH_PPC64 && V8_OS_LINUX
682 // Set to EM_PPC64, defined as 21, in Power ABI,
683 // Join the next 4 lines, omitting the spaces and double-slashes.
684 // https://www-03.ibm.com/technologyconnect/tgcm/TGCMFileServlet.wss/
685 // ABI64BitOpenPOWERv1.1_16July2015_pub.pdf?
686 // id=B81AEC1A37F5DAF185257C3E004E8845&linkid=1n0000&c_t=
687 // c9xw7v5dzsj7gt1ifgf4cjbcnskqptmr
688 header->machine = 21;
Ben Murdochda12d292016-06-02 14:46:10 +0100689#elif V8_TARGET_ARCH_S390
690 // Processor identification value is 22 (EM_S390) as defined in the ABI:
691 // http://refspecs.linuxbase.org/ELF/zSeries/lzsabi0_s390.html#AEN1691
692 // http://refspecs.linuxbase.org/ELF/zSeries/lzsabi0_zSeries.html#AEN1599
693 header->machine = 22;
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.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000712 DCHECK(w->position() == sizeof(ELFHeader));
Ben Murdochb8e0da22011-05-16 14:20:40 +0100713
714 Writer::Slot<ELFSection::Header> headers =
715 w->CreateSlotsHere<ELFSection::Header>(sections_.length());
716
717 // String table for section table is the first section.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000718 ELFStringTable* strtab = static_cast<ELFStringTable*>(SectionAt(1));
Ben Murdochb8e0da22011-05-16 14:20:40 +0100719 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
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000743 Zone* zone_;
Ben Murdochb8e0da22011-05-16 14:20:40 +0100744 ZoneList<ELFSection*> sections_;
745};
746
747
748class ELFSymbol BASE_EMBEDDED {
749 public:
750 enum Type {
751 TYPE_NOTYPE = 0,
752 TYPE_OBJECT = 1,
753 TYPE_FUNC = 2,
754 TYPE_SECTION = 3,
755 TYPE_FILE = 4,
756 TYPE_LOPROC = 13,
757 TYPE_HIPROC = 15
758 };
759
760 enum Binding {
761 BIND_LOCAL = 0,
762 BIND_GLOBAL = 1,
763 BIND_WEAK = 2,
764 BIND_LOPROC = 13,
765 BIND_HIPROC = 15
766 };
767
768 ELFSymbol(const char* name,
769 uintptr_t value,
770 uintptr_t size,
771 Binding binding,
772 Type type,
773 uint16_t section)
774 : name(name),
775 value(value),
776 size(size),
777 info((binding << 4) | type),
778 other(0),
779 section(section) {
780 }
781
782 Binding binding() const {
783 return static_cast<Binding>(info >> 4);
784 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000785#if (V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_X87 || \
Ben Murdochda12d292016-06-02 14:46:10 +0100786 (V8_TARGET_ARCH_X64 && V8_TARGET_ARCH_32_BIT) || \
787 (V8_TARGET_ARCH_S390 && V8_TARGET_ARCH_32_BIT))
Ben Murdochb8e0da22011-05-16 14:20:40 +0100788 struct SerializedLayout {
789 SerializedLayout(uint32_t name,
790 uintptr_t value,
791 uintptr_t size,
792 Binding binding,
793 Type type,
794 uint16_t section)
795 : name(name),
796 value(value),
797 size(size),
798 info((binding << 4) | type),
799 other(0),
800 section(section) {
801 }
802
803 uint32_t name;
804 uintptr_t value;
805 uintptr_t size;
806 uint8_t info;
807 uint8_t other;
808 uint16_t section;
809 };
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000810#elif(V8_TARGET_ARCH_X64 && V8_TARGET_ARCH_64_BIT) || \
Ben Murdochda12d292016-06-02 14:46:10 +0100811 (V8_TARGET_ARCH_PPC64 && V8_OS_LINUX) || V8_TARGET_ARCH_S390X
Ben Murdochb8e0da22011-05-16 14:20:40 +0100812 struct SerializedLayout {
813 SerializedLayout(uint32_t name,
814 uintptr_t value,
815 uintptr_t size,
816 Binding binding,
817 Type type,
818 uint16_t section)
819 : name(name),
820 info((binding << 4) | type),
821 other(0),
822 section(section),
823 value(value),
824 size(size) {
825 }
826
827 uint32_t name;
828 uint8_t info;
829 uint8_t other;
830 uint16_t section;
831 uintptr_t value;
832 uintptr_t size;
833 };
834#endif
835
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000836 void Write(Writer::Slot<SerializedLayout> s, ELFStringTable* t) {
Ben Murdochb8e0da22011-05-16 14:20:40 +0100837 // Convert symbol names from strings to indexes in the string table.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000838 s->name = static_cast<uint32_t>(t->Add(name));
Ben Murdochb8e0da22011-05-16 14:20:40 +0100839 s->value = value;
840 s->size = size;
841 s->info = info;
842 s->other = other;
843 s->section = section;
844 }
845
846 private:
847 const char* name;
848 uintptr_t value;
849 uintptr_t size;
850 uint8_t info;
851 uint8_t other;
852 uint16_t section;
853};
854
855
856class ELFSymbolTable : public ELFSection {
857 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000858 ELFSymbolTable(const char* name, Zone* zone)
Ben Murdochb8e0da22011-05-16 14:20:40 +0100859 : ELFSection(name, TYPE_SYMTAB, sizeof(uintptr_t)),
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000860 locals_(1, zone),
861 globals_(1, zone) {
Ben Murdochb8e0da22011-05-16 14:20:40 +0100862 }
863
864 virtual void WriteBody(Writer::Slot<Header> header, Writer* w) {
865 w->Align(header->alignment);
866 int total_symbols = locals_.length() + globals_.length() + 1;
867 header->offset = w->position();
868
869 Writer::Slot<ELFSymbol::SerializedLayout> symbols =
870 w->CreateSlotsHere<ELFSymbol::SerializedLayout>(total_symbols);
871
872 header->size = w->position() - header->offset;
873
874 // String table for this symbol table should follow it in the section table.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000875 ELFStringTable* strtab =
876 static_cast<ELFStringTable*>(w->debug_object()->SectionAt(index() + 1));
Ben Murdochb8e0da22011-05-16 14:20:40 +0100877 strtab->AttachWriter(w);
878 symbols.at(0).set(ELFSymbol::SerializedLayout(0,
879 0,
880 0,
881 ELFSymbol::BIND_LOCAL,
882 ELFSymbol::TYPE_NOTYPE,
883 0));
884 WriteSymbolsList(&locals_, symbols.at(1), strtab);
885 WriteSymbolsList(&globals_, symbols.at(locals_.length() + 1), strtab);
886 strtab->DetachWriter();
887 }
888
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000889 void Add(const ELFSymbol& symbol, Zone* zone) {
Ben Murdochb8e0da22011-05-16 14:20:40 +0100890 if (symbol.binding() == ELFSymbol::BIND_LOCAL) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000891 locals_.Add(symbol, zone);
Ben Murdochb8e0da22011-05-16 14:20:40 +0100892 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000893 globals_.Add(symbol, zone);
Ben Murdochb8e0da22011-05-16 14:20:40 +0100894 }
895 }
896
897 protected:
898 virtual void PopulateHeader(Writer::Slot<Header> header) {
899 ELFSection::PopulateHeader(header);
900 // We are assuming that string table will follow symbol table.
901 header->link = index() + 1;
902 header->info = locals_.length() + 1;
903 header->entry_size = sizeof(ELFSymbol::SerializedLayout);
904 }
905
906 private:
907 void WriteSymbolsList(const ZoneList<ELFSymbol>* src,
908 Writer::Slot<ELFSymbol::SerializedLayout> dst,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000909 ELFStringTable* strtab) {
Ben Murdochb8e0da22011-05-16 14:20:40 +0100910 for (int i = 0, len = src->length();
911 i < len;
912 i++) {
913 src->at(i).Write(dst.at(i), strtab);
914 }
915 }
916
917 ZoneList<ELFSymbol> locals_;
918 ZoneList<ELFSymbol> globals_;
919};
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000920#endif // defined(__ELF)
Ben Murdochb8e0da22011-05-16 14:20:40 +0100921
922
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000923class LineInfo : public Malloced {
924 public:
925 LineInfo() : pc_info_(10) {}
926
927 void SetPosition(intptr_t pc, int pos, bool is_statement) {
928 AddPCInfo(PCInfo(pc, pos, is_statement));
929 }
930
931 struct PCInfo {
932 PCInfo(intptr_t pc, int pos, bool is_statement)
933 : pc_(pc), pos_(pos), is_statement_(is_statement) {}
934
935 intptr_t pc_;
936 int pos_;
937 bool is_statement_;
938 };
939
940 List<PCInfo>* pc_info() { return &pc_info_; }
941
942 private:
943 void AddPCInfo(const PCInfo& pc_info) { pc_info_.Add(pc_info); }
944
945 List<PCInfo> pc_info_;
946};
947
948
Ben Murdochb8e0da22011-05-16 14:20:40 +0100949class CodeDescription BASE_EMBEDDED {
950 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000951#if V8_TARGET_ARCH_X64
Steve Block1e0659c2011-05-24 12:43:12 +0100952 enum StackState {
953 POST_RBP_PUSH,
954 POST_RBP_SET,
955 POST_RBP_POP,
956 STACK_STATE_MAX
957 };
958#endif
959
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000960 CodeDescription(const char* name, Code* code, SharedFunctionInfo* shared,
961 LineInfo* lineinfo)
962 : name_(name), code_(code), shared_info_(shared), lineinfo_(lineinfo) {}
Ben Murdochb8e0da22011-05-16 14:20:40 +0100963
Steve Block1e0659c2011-05-24 12:43:12 +0100964 const char* name() const {
Ben Murdochb8e0da22011-05-16 14:20:40 +0100965 return name_;
966 }
967
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000968 LineInfo* lineinfo() const { return lineinfo_; }
Ben Murdochb8e0da22011-05-16 14:20:40 +0100969
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000970 bool is_function() const {
971 Code::Kind kind = code_->kind();
972 return kind == Code::FUNCTION || kind == Code::OPTIMIZED_FUNCTION;
Ben Murdochb8e0da22011-05-16 14:20:40 +0100973 }
974
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000975 bool has_scope_info() const { return shared_info_ != NULL; }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000976
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000977 ScopeInfo* scope_info() const {
978 DCHECK(has_scope_info());
979 return shared_info_->scope_info();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000980 }
981
Steve Block1e0659c2011-05-24 12:43:12 +0100982 uintptr_t CodeStart() const {
983 return reinterpret_cast<uintptr_t>(code_->instruction_start());
984 }
985
986 uintptr_t CodeEnd() const {
987 return reinterpret_cast<uintptr_t>(code_->instruction_end());
988 }
989
990 uintptr_t CodeSize() const {
991 return CodeEnd() - CodeStart();
992 }
993
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000994 bool has_script() {
995 return shared_info_ != NULL && shared_info_->script()->IsScript();
996 }
997
998 Script* script() { return Script::cast(shared_info_->script()); }
999
Steve Block1e0659c2011-05-24 12:43:12 +01001000 bool IsLineInfoAvailable() {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001001 return has_script() && script()->source()->IsString() &&
1002 script()->HasValidSource() && script()->name()->IsString() &&
1003 lineinfo_ != NULL;
Ben Murdochb8e0da22011-05-16 14:20:40 +01001004 }
1005
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001006#if V8_TARGET_ARCH_X64
Steve Block1e0659c2011-05-24 12:43:12 +01001007 uintptr_t GetStackStateStartAddress(StackState state) const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001008 DCHECK(state < STACK_STATE_MAX);
Steve Block1e0659c2011-05-24 12:43:12 +01001009 return stack_state_start_addresses_[state];
1010 }
Ben Murdochb8e0da22011-05-16 14:20:40 +01001011
Steve Block1e0659c2011-05-24 12:43:12 +01001012 void SetStackStateStartAddress(StackState state, uintptr_t addr) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001013 DCHECK(state < STACK_STATE_MAX);
Steve Block1e0659c2011-05-24 12:43:12 +01001014 stack_state_start_addresses_[state] = addr;
1015 }
1016#endif
1017
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001018 base::SmartArrayPointer<char> GetFilename() {
1019 return String::cast(script()->name())->ToCString();
Ben Murdochb8e0da22011-05-16 14:20:40 +01001020 }
1021
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001022 int GetScriptLineNumber(int pos) { return script()->GetLineNumber(pos) + 1; }
Ben Murdochb8e0da22011-05-16 14:20:40 +01001023
Steve Block1e0659c2011-05-24 12:43:12 +01001024
Ben Murdochb8e0da22011-05-16 14:20:40 +01001025 private:
1026 const char* name_;
1027 Code* code_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001028 SharedFunctionInfo* shared_info_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001029 LineInfo* lineinfo_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001030#if V8_TARGET_ARCH_X64
Steve Block1e0659c2011-05-24 12:43:12 +01001031 uintptr_t stack_state_start_addresses_[STACK_STATE_MAX];
1032#endif
Ben Murdochb8e0da22011-05-16 14:20:40 +01001033};
1034
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001035#if defined(__ELF)
Ben Murdochb8e0da22011-05-16 14:20:40 +01001036static void CreateSymbolsTable(CodeDescription* desc,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001037 Zone* zone,
Ben Murdochb8e0da22011-05-16 14:20:40 +01001038 ELF* elf,
1039 int text_section_index) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001040 ELFSymbolTable* symtab = new(zone) ELFSymbolTable(".symtab", zone);
1041 ELFStringTable* strtab = new(zone) ELFStringTable(".strtab");
Ben Murdochb8e0da22011-05-16 14:20:40 +01001042
1043 // Symbol table should be followed by the linked string table.
1044 elf->AddSection(symtab);
1045 elf->AddSection(strtab);
1046
1047 symtab->Add(ELFSymbol("V8 Code",
1048 0,
1049 0,
1050 ELFSymbol::BIND_LOCAL,
1051 ELFSymbol::TYPE_FILE,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001052 ELFSection::INDEX_ABSOLUTE),
1053 zone);
Ben Murdochb8e0da22011-05-16 14:20:40 +01001054
Steve Block1e0659c2011-05-24 12:43:12 +01001055 symtab->Add(ELFSymbol(desc->name(),
Ben Murdochb8e0da22011-05-16 14:20:40 +01001056 0,
Steve Block1e0659c2011-05-24 12:43:12 +01001057 desc->CodeSize(),
Ben Murdochb8e0da22011-05-16 14:20:40 +01001058 ELFSymbol::BIND_GLOBAL,
1059 ELFSymbol::TYPE_FUNC,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001060 text_section_index),
1061 zone);
Ben Murdochb8e0da22011-05-16 14:20:40 +01001062}
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001063#endif // defined(__ELF)
Ben Murdochb8e0da22011-05-16 14:20:40 +01001064
1065
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001066class DebugInfoSection : public DebugSection {
Ben Murdochb8e0da22011-05-16 14:20:40 +01001067 public:
1068 explicit DebugInfoSection(CodeDescription* desc)
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001069#if defined(__ELF)
1070 : ELFSection(".debug_info", TYPE_PROGBITS, 1),
1071#else
1072 : MachOSection("__debug_info",
1073 "__DWARF",
1074 1,
1075 MachOSection::S_REGULAR | MachOSection::S_ATTR_DEBUG),
1076#endif
1077 desc_(desc) { }
1078
1079 // DWARF2 standard
1080 enum DWARF2LocationOp {
1081 DW_OP_reg0 = 0x50,
1082 DW_OP_reg1 = 0x51,
1083 DW_OP_reg2 = 0x52,
1084 DW_OP_reg3 = 0x53,
1085 DW_OP_reg4 = 0x54,
1086 DW_OP_reg5 = 0x55,
1087 DW_OP_reg6 = 0x56,
1088 DW_OP_reg7 = 0x57,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001089 DW_OP_reg8 = 0x58,
1090 DW_OP_reg9 = 0x59,
1091 DW_OP_reg10 = 0x5a,
1092 DW_OP_reg11 = 0x5b,
1093 DW_OP_reg12 = 0x5c,
1094 DW_OP_reg13 = 0x5d,
1095 DW_OP_reg14 = 0x5e,
1096 DW_OP_reg15 = 0x5f,
1097 DW_OP_reg16 = 0x60,
1098 DW_OP_reg17 = 0x61,
1099 DW_OP_reg18 = 0x62,
1100 DW_OP_reg19 = 0x63,
1101 DW_OP_reg20 = 0x64,
1102 DW_OP_reg21 = 0x65,
1103 DW_OP_reg22 = 0x66,
1104 DW_OP_reg23 = 0x67,
1105 DW_OP_reg24 = 0x68,
1106 DW_OP_reg25 = 0x69,
1107 DW_OP_reg26 = 0x6a,
1108 DW_OP_reg27 = 0x6b,
1109 DW_OP_reg28 = 0x6c,
1110 DW_OP_reg29 = 0x6d,
1111 DW_OP_reg30 = 0x6e,
1112 DW_OP_reg31 = 0x6f,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001113 DW_OP_fbreg = 0x91 // 1 param: SLEB128 offset
1114 };
1115
1116 enum DWARF2Encoding {
1117 DW_ATE_ADDRESS = 0x1,
1118 DW_ATE_SIGNED = 0x5
1119 };
Ben Murdochb8e0da22011-05-16 14:20:40 +01001120
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001121 bool WriteBodyInternal(Writer* w) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001122 uintptr_t cu_start = w->position();
Ben Murdochb8e0da22011-05-16 14:20:40 +01001123 Writer::Slot<uint32_t> size = w->CreateSlotHere<uint32_t>();
1124 uintptr_t start = w->position();
1125 w->Write<uint16_t>(2); // DWARF version.
1126 w->Write<uint32_t>(0); // Abbreviation table offset.
1127 w->Write<uint8_t>(sizeof(intptr_t));
1128
1129 w->WriteULEB128(1); // Abbreviation code.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001130 w->WriteString(desc_->GetFilename().get());
Steve Block1e0659c2011-05-24 12:43:12 +01001131 w->Write<intptr_t>(desc_->CodeStart());
1132 w->Write<intptr_t>(desc_->CodeStart() + desc_->CodeSize());
Ben Murdochb8e0da22011-05-16 14:20:40 +01001133 w->Write<uint32_t>(0);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001134
1135 uint32_t ty_offset = static_cast<uint32_t>(w->position() - cu_start);
1136 w->WriteULEB128(3);
1137 w->Write<uint8_t>(kPointerSize);
1138 w->WriteString("v8value");
1139
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001140 if (desc_->has_scope_info()) {
1141 ScopeInfo* scope = desc_->scope_info();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001142 w->WriteULEB128(2);
1143 w->WriteString(desc_->name());
1144 w->Write<intptr_t>(desc_->CodeStart());
1145 w->Write<intptr_t>(desc_->CodeStart() + desc_->CodeSize());
1146 Writer::Slot<uint32_t> fb_block_size = w->CreateSlotHere<uint32_t>();
1147 uintptr_t fb_block_start = w->position();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001148#if V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_X87
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001149 w->Write<uint8_t>(DW_OP_reg5); // The frame pointer's here on ia32
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001150#elif V8_TARGET_ARCH_X64
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001151 w->Write<uint8_t>(DW_OP_reg6); // and here on x64.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001152#elif V8_TARGET_ARCH_ARM
1153 UNIMPLEMENTED();
1154#elif V8_TARGET_ARCH_MIPS
1155 UNIMPLEMENTED();
1156#elif V8_TARGET_ARCH_MIPS64
1157 UNIMPLEMENTED();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001158#elif V8_TARGET_ARCH_PPC64 && V8_OS_LINUX
1159 w->Write<uint8_t>(DW_OP_reg31); // The frame pointer is here on PPC64.
Ben Murdochda12d292016-06-02 14:46:10 +01001160#elif V8_TARGET_ARCH_S390
1161 w->Write<uint8_t>(DW_OP_reg11); // The frame pointer's here on S390.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001162#else
1163#error Unsupported target architecture.
1164#endif
1165 fb_block_size.set(static_cast<uint32_t>(w->position() - fb_block_start));
1166
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001167 int params = scope->ParameterCount();
1168 int slots = scope->StackLocalCount();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001169 int context_slots = scope->ContextLocalCount();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001170 // The real slot ID is internal_slots + context_slot_id.
1171 int internal_slots = Context::MIN_CONTEXT_SLOTS;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001172 int locals = scope->StackLocalCount();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001173 int current_abbreviation = 4;
1174
1175 for (int param = 0; param < params; ++param) {
1176 w->WriteULEB128(current_abbreviation++);
1177 w->WriteString(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001178 scope->ParameterName(param)->ToCString(DISALLOW_NULLS).get());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001179 w->Write<uint32_t>(ty_offset);
1180 Writer::Slot<uint32_t> block_size = w->CreateSlotHere<uint32_t>();
1181 uintptr_t block_start = w->position();
1182 w->Write<uint8_t>(DW_OP_fbreg);
1183 w->WriteSLEB128(
1184 JavaScriptFrameConstants::kLastParameterOffset +
1185 kPointerSize * (params - param - 1));
1186 block_size.set(static_cast<uint32_t>(w->position() - block_start));
1187 }
1188
1189 EmbeddedVector<char, 256> buffer;
1190 StringBuilder builder(buffer.start(), buffer.length());
1191
1192 for (int slot = 0; slot < slots; ++slot) {
1193 w->WriteULEB128(current_abbreviation++);
1194 builder.Reset();
1195 builder.AddFormatted("slot%d", slot);
1196 w->WriteString(builder.Finalize());
1197 }
1198
1199 // See contexts.h for more information.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001200 DCHECK(Context::MIN_CONTEXT_SLOTS == 4);
1201 DCHECK(Context::CLOSURE_INDEX == 0);
1202 DCHECK(Context::PREVIOUS_INDEX == 1);
1203 DCHECK(Context::EXTENSION_INDEX == 2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001204 DCHECK(Context::NATIVE_CONTEXT_INDEX == 3);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001205 w->WriteULEB128(current_abbreviation++);
1206 w->WriteString(".closure");
1207 w->WriteULEB128(current_abbreviation++);
1208 w->WriteString(".previous");
1209 w->WriteULEB128(current_abbreviation++);
1210 w->WriteString(".extension");
1211 w->WriteULEB128(current_abbreviation++);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001212 w->WriteString(".native_context");
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001213
1214 for (int context_slot = 0;
1215 context_slot < context_slots;
1216 ++context_slot) {
1217 w->WriteULEB128(current_abbreviation++);
1218 builder.Reset();
1219 builder.AddFormatted("context_slot%d", context_slot + internal_slots);
1220 w->WriteString(builder.Finalize());
1221 }
1222
1223 for (int local = 0; local < locals; ++local) {
1224 w->WriteULEB128(current_abbreviation++);
1225 w->WriteString(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001226 scope->StackLocalName(local)->ToCString(DISALLOW_NULLS).get());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001227 w->Write<uint32_t>(ty_offset);
1228 Writer::Slot<uint32_t> block_size = w->CreateSlotHere<uint32_t>();
1229 uintptr_t block_start = w->position();
1230 w->Write<uint8_t>(DW_OP_fbreg);
1231 w->WriteSLEB128(
1232 JavaScriptFrameConstants::kLocal0Offset -
1233 kPointerSize * local);
1234 block_size.set(static_cast<uint32_t>(w->position() - block_start));
1235 }
1236
1237 {
1238 w->WriteULEB128(current_abbreviation++);
1239 w->WriteString("__function");
1240 w->Write<uint32_t>(ty_offset);
1241 Writer::Slot<uint32_t> block_size = w->CreateSlotHere<uint32_t>();
1242 uintptr_t block_start = w->position();
1243 w->Write<uint8_t>(DW_OP_fbreg);
1244 w->WriteSLEB128(JavaScriptFrameConstants::kFunctionOffset);
1245 block_size.set(static_cast<uint32_t>(w->position() - block_start));
1246 }
1247
1248 {
1249 w->WriteULEB128(current_abbreviation++);
1250 w->WriteString("__context");
1251 w->Write<uint32_t>(ty_offset);
1252 Writer::Slot<uint32_t> block_size = w->CreateSlotHere<uint32_t>();
1253 uintptr_t block_start = w->position();
1254 w->Write<uint8_t>(DW_OP_fbreg);
1255 w->WriteSLEB128(StandardFrameConstants::kContextOffset);
1256 block_size.set(static_cast<uint32_t>(w->position() - block_start));
1257 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001258
1259 w->WriteULEB128(0); // Terminate the sub program.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001260 }
1261
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001262 w->WriteULEB128(0); // Terminate the compile unit.
Ben Murdochb8e0da22011-05-16 14:20:40 +01001263 size.set(static_cast<uint32_t>(w->position() - start));
1264 return true;
1265 }
1266
1267 private:
1268 CodeDescription* desc_;
1269};
1270
1271
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001272class DebugAbbrevSection : public DebugSection {
Ben Murdochb8e0da22011-05-16 14:20:40 +01001273 public:
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001274 explicit DebugAbbrevSection(CodeDescription* desc)
1275#ifdef __ELF
1276 : ELFSection(".debug_abbrev", TYPE_PROGBITS, 1),
1277#else
1278 : MachOSection("__debug_abbrev",
1279 "__DWARF",
1280 1,
1281 MachOSection::S_REGULAR | MachOSection::S_ATTR_DEBUG),
1282#endif
1283 desc_(desc) { }
Ben Murdochb8e0da22011-05-16 14:20:40 +01001284
1285 // DWARF2 standard, figure 14.
1286 enum DWARF2Tags {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001287 DW_TAG_FORMAL_PARAMETER = 0x05,
1288 DW_TAG_POINTER_TYPE = 0xf,
1289 DW_TAG_COMPILE_UNIT = 0x11,
1290 DW_TAG_STRUCTURE_TYPE = 0x13,
1291 DW_TAG_BASE_TYPE = 0x24,
1292 DW_TAG_SUBPROGRAM = 0x2e,
1293 DW_TAG_VARIABLE = 0x34
Ben Murdochb8e0da22011-05-16 14:20:40 +01001294 };
1295
1296 // DWARF2 standard, figure 16.
1297 enum DWARF2ChildrenDetermination {
1298 DW_CHILDREN_NO = 0,
1299 DW_CHILDREN_YES = 1
1300 };
1301
1302 // DWARF standard, figure 17.
1303 enum DWARF2Attribute {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001304 DW_AT_LOCATION = 0x2,
Ben Murdochb8e0da22011-05-16 14:20:40 +01001305 DW_AT_NAME = 0x3,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001306 DW_AT_BYTE_SIZE = 0xb,
Ben Murdochb8e0da22011-05-16 14:20:40 +01001307 DW_AT_STMT_LIST = 0x10,
1308 DW_AT_LOW_PC = 0x11,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001309 DW_AT_HIGH_PC = 0x12,
1310 DW_AT_ENCODING = 0x3e,
1311 DW_AT_FRAME_BASE = 0x40,
1312 DW_AT_TYPE = 0x49
Ben Murdochb8e0da22011-05-16 14:20:40 +01001313 };
1314
1315 // DWARF2 standard, figure 19.
1316 enum DWARF2AttributeForm {
1317 DW_FORM_ADDR = 0x1,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001318 DW_FORM_BLOCK4 = 0x4,
Ben Murdochb8e0da22011-05-16 14:20:40 +01001319 DW_FORM_STRING = 0x8,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001320 DW_FORM_DATA4 = 0x6,
1321 DW_FORM_BLOCK = 0x9,
1322 DW_FORM_DATA1 = 0xb,
1323 DW_FORM_FLAG = 0xc,
1324 DW_FORM_REF4 = 0x13
Ben Murdochb8e0da22011-05-16 14:20:40 +01001325 };
1326
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001327 void WriteVariableAbbreviation(Writer* w,
1328 int abbreviation_code,
1329 bool has_value,
1330 bool is_parameter) {
1331 w->WriteULEB128(abbreviation_code);
1332 w->WriteULEB128(is_parameter ? DW_TAG_FORMAL_PARAMETER : DW_TAG_VARIABLE);
Ben Murdochb8e0da22011-05-16 14:20:40 +01001333 w->Write<uint8_t>(DW_CHILDREN_NO);
1334 w->WriteULEB128(DW_AT_NAME);
1335 w->WriteULEB128(DW_FORM_STRING);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001336 if (has_value) {
1337 w->WriteULEB128(DW_AT_TYPE);
1338 w->WriteULEB128(DW_FORM_REF4);
1339 w->WriteULEB128(DW_AT_LOCATION);
1340 w->WriteULEB128(DW_FORM_BLOCK4);
1341 }
1342 w->WriteULEB128(0);
1343 w->WriteULEB128(0);
1344 }
1345
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001346 bool WriteBodyInternal(Writer* w) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001347 int current_abbreviation = 1;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001348 bool extra_info = desc_->has_scope_info();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001349 DCHECK(desc_->IsLineInfoAvailable());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001350 w->WriteULEB128(current_abbreviation++);
1351 w->WriteULEB128(DW_TAG_COMPILE_UNIT);
1352 w->Write<uint8_t>(extra_info ? DW_CHILDREN_YES : DW_CHILDREN_NO);
1353 w->WriteULEB128(DW_AT_NAME);
1354 w->WriteULEB128(DW_FORM_STRING);
Ben Murdochb8e0da22011-05-16 14:20:40 +01001355 w->WriteULEB128(DW_AT_LOW_PC);
1356 w->WriteULEB128(DW_FORM_ADDR);
1357 w->WriteULEB128(DW_AT_HIGH_PC);
1358 w->WriteULEB128(DW_FORM_ADDR);
1359 w->WriteULEB128(DW_AT_STMT_LIST);
1360 w->WriteULEB128(DW_FORM_DATA4);
1361 w->WriteULEB128(0);
1362 w->WriteULEB128(0);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001363
1364 if (extra_info) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001365 ScopeInfo* scope = desc_->scope_info();
1366 int params = scope->ParameterCount();
1367 int slots = scope->StackLocalCount();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001368 int context_slots = scope->ContextLocalCount();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001369 // The real slot ID is internal_slots + context_slot_id.
1370 int internal_slots = Context::MIN_CONTEXT_SLOTS;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001371 int locals = scope->StackLocalCount();
1372 // Total children is params + slots + context_slots + internal_slots +
1373 // locals + 2 (__function and __context).
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001374
1375 // The extra duplication below seems to be necessary to keep
1376 // gdb from getting upset on OSX.
1377 w->WriteULEB128(current_abbreviation++); // Abbreviation code.
1378 w->WriteULEB128(DW_TAG_SUBPROGRAM);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001379 w->Write<uint8_t>(DW_CHILDREN_YES);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001380 w->WriteULEB128(DW_AT_NAME);
1381 w->WriteULEB128(DW_FORM_STRING);
1382 w->WriteULEB128(DW_AT_LOW_PC);
1383 w->WriteULEB128(DW_FORM_ADDR);
1384 w->WriteULEB128(DW_AT_HIGH_PC);
1385 w->WriteULEB128(DW_FORM_ADDR);
1386 w->WriteULEB128(DW_AT_FRAME_BASE);
1387 w->WriteULEB128(DW_FORM_BLOCK4);
1388 w->WriteULEB128(0);
1389 w->WriteULEB128(0);
1390
1391 w->WriteULEB128(current_abbreviation++);
1392 w->WriteULEB128(DW_TAG_STRUCTURE_TYPE);
1393 w->Write<uint8_t>(DW_CHILDREN_NO);
1394 w->WriteULEB128(DW_AT_BYTE_SIZE);
1395 w->WriteULEB128(DW_FORM_DATA1);
1396 w->WriteULEB128(DW_AT_NAME);
1397 w->WriteULEB128(DW_FORM_STRING);
1398 w->WriteULEB128(0);
1399 w->WriteULEB128(0);
1400
1401 for (int param = 0; param < params; ++param) {
1402 WriteVariableAbbreviation(w, current_abbreviation++, true, true);
1403 }
1404
1405 for (int slot = 0; slot < slots; ++slot) {
1406 WriteVariableAbbreviation(w, current_abbreviation++, false, false);
1407 }
1408
1409 for (int internal_slot = 0;
1410 internal_slot < internal_slots;
1411 ++internal_slot) {
1412 WriteVariableAbbreviation(w, current_abbreviation++, false, false);
1413 }
1414
1415 for (int context_slot = 0;
1416 context_slot < context_slots;
1417 ++context_slot) {
1418 WriteVariableAbbreviation(w, current_abbreviation++, false, false);
1419 }
1420
1421 for (int local = 0; local < locals; ++local) {
1422 WriteVariableAbbreviation(w, current_abbreviation++, true, false);
1423 }
1424
1425 // The function.
1426 WriteVariableAbbreviation(w, current_abbreviation++, true, false);
1427
1428 // The context.
1429 WriteVariableAbbreviation(w, current_abbreviation++, true, false);
1430
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001431 w->WriteULEB128(0); // Terminate the sibling list.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001432 }
1433
1434 w->WriteULEB128(0); // Terminate the table.
Ben Murdochb8e0da22011-05-16 14:20:40 +01001435 return true;
1436 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001437
1438 private:
1439 CodeDescription* desc_;
Ben Murdochb8e0da22011-05-16 14:20:40 +01001440};
1441
1442
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001443class DebugLineSection : public DebugSection {
Ben Murdochb8e0da22011-05-16 14:20:40 +01001444 public:
1445 explicit DebugLineSection(CodeDescription* desc)
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001446#ifdef __ELF
Ben Murdochb8e0da22011-05-16 14:20:40 +01001447 : ELFSection(".debug_line", TYPE_PROGBITS, 1),
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001448#else
1449 : MachOSection("__debug_line",
1450 "__DWARF",
1451 1,
1452 MachOSection::S_REGULAR | MachOSection::S_ATTR_DEBUG),
1453#endif
Ben Murdochb8e0da22011-05-16 14:20:40 +01001454 desc_(desc) { }
1455
1456 // DWARF2 standard, figure 34.
1457 enum DWARF2Opcodes {
1458 DW_LNS_COPY = 1,
1459 DW_LNS_ADVANCE_PC = 2,
1460 DW_LNS_ADVANCE_LINE = 3,
1461 DW_LNS_SET_FILE = 4,
1462 DW_LNS_SET_COLUMN = 5,
1463 DW_LNS_NEGATE_STMT = 6
1464 };
1465
1466 // DWARF2 standard, figure 35.
1467 enum DWARF2ExtendedOpcode {
1468 DW_LNE_END_SEQUENCE = 1,
1469 DW_LNE_SET_ADDRESS = 2,
1470 DW_LNE_DEFINE_FILE = 3
1471 };
1472
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001473 bool WriteBodyInternal(Writer* w) {
Ben Murdochb8e0da22011-05-16 14:20:40 +01001474 // Write prologue.
1475 Writer::Slot<uint32_t> total_length = w->CreateSlotHere<uint32_t>();
1476 uintptr_t start = w->position();
1477
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001478 // Used for special opcodes
1479 const int8_t line_base = 1;
1480 const uint8_t line_range = 7;
1481 const int8_t max_line_incr = (line_base + line_range - 1);
1482 const uint8_t opcode_base = DW_LNS_NEGATE_STMT + 1;
1483
Ben Murdochb8e0da22011-05-16 14:20:40 +01001484 w->Write<uint16_t>(2); // Field version.
1485 Writer::Slot<uint32_t> prologue_length = w->CreateSlotHere<uint32_t>();
1486 uintptr_t prologue_start = w->position();
1487 w->Write<uint8_t>(1); // Field minimum_instruction_length.
1488 w->Write<uint8_t>(1); // Field default_is_stmt.
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001489 w->Write<int8_t>(line_base); // Field line_base.
1490 w->Write<uint8_t>(line_range); // Field line_range.
1491 w->Write<uint8_t>(opcode_base); // Field opcode_base.
Ben Murdochb8e0da22011-05-16 14:20:40 +01001492 w->Write<uint8_t>(0); // DW_LNS_COPY operands count.
1493 w->Write<uint8_t>(1); // DW_LNS_ADVANCE_PC operands count.
1494 w->Write<uint8_t>(1); // DW_LNS_ADVANCE_LINE operands count.
1495 w->Write<uint8_t>(1); // DW_LNS_SET_FILE operands count.
1496 w->Write<uint8_t>(1); // DW_LNS_SET_COLUMN operands count.
1497 w->Write<uint8_t>(0); // DW_LNS_NEGATE_STMT operands count.
1498 w->Write<uint8_t>(0); // Empty include_directories sequence.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001499 w->WriteString(desc_->GetFilename().get()); // File name.
Ben Murdochb8e0da22011-05-16 14:20:40 +01001500 w->WriteULEB128(0); // Current directory.
1501 w->WriteULEB128(0); // Unknown modification time.
1502 w->WriteULEB128(0); // Unknown file size.
1503 w->Write<uint8_t>(0);
1504 prologue_length.set(static_cast<uint32_t>(w->position() - prologue_start));
1505
1506 WriteExtendedOpcode(w, DW_LNE_SET_ADDRESS, sizeof(intptr_t));
Steve Block1e0659c2011-05-24 12:43:12 +01001507 w->Write<intptr_t>(desc_->CodeStart());
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001508 w->Write<uint8_t>(DW_LNS_COPY);
Ben Murdochb8e0da22011-05-16 14:20:40 +01001509
1510 intptr_t pc = 0;
1511 intptr_t line = 1;
1512 bool is_statement = true;
1513
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001514 List<LineInfo::PCInfo>* pc_info = desc_->lineinfo()->pc_info();
Ben Murdochb8e0da22011-05-16 14:20:40 +01001515 pc_info->Sort(&ComparePCInfo);
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001516
1517 int pc_info_length = pc_info->length();
1518 for (int i = 0; i < pc_info_length; i++) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001519 LineInfo::PCInfo* info = &pc_info->at(i);
1520 DCHECK(info->pc_ >= pc);
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001521
1522 // Reduce bloating in the debug line table by removing duplicate line
1523 // entries (per DWARF2 standard).
1524 intptr_t new_line = desc_->GetScriptLineNumber(info->pos_);
1525 if (new_line == line) {
1526 continue;
Ben Murdochb8e0da22011-05-16 14:20:40 +01001527 }
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001528
1529 // Mark statement boundaries. For a better debugging experience, mark
1530 // the last pc address in the function as a statement (e.g. "}"), so that
1531 // a user can see the result of the last line executed in the function,
1532 // should control reach the end.
1533 if ((i+1) == pc_info_length) {
1534 if (!is_statement) {
1535 w->Write<uint8_t>(DW_LNS_NEGATE_STMT);
1536 }
1537 } else if (is_statement != info->is_statement_) {
Ben Murdochb8e0da22011-05-16 14:20:40 +01001538 w->Write<uint8_t>(DW_LNS_NEGATE_STMT);
1539 is_statement = !is_statement;
1540 }
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001541
1542 // Generate special opcodes, if possible. This results in more compact
1543 // debug line tables. See the DWARF 2.0 standard to learn more about
1544 // special opcodes.
1545 uintptr_t pc_diff = info->pc_ - pc;
1546 intptr_t line_diff = new_line - line;
1547
1548 // Compute special opcode (see DWARF 2.0 standard)
1549 intptr_t special_opcode = (line_diff - line_base) +
1550 (line_range * pc_diff) + opcode_base;
1551
1552 // If special_opcode is less than or equal to 255, it can be used as a
1553 // special opcode. If line_diff is larger than the max line increment
1554 // allowed for a special opcode, or if line_diff is less than the minimum
1555 // line that can be added to the line register (i.e. line_base), then
1556 // special_opcode can't be used.
1557 if ((special_opcode >= opcode_base) && (special_opcode <= 255) &&
1558 (line_diff <= max_line_incr) && (line_diff >= line_base)) {
1559 w->Write<uint8_t>(special_opcode);
1560 } else {
1561 w->Write<uint8_t>(DW_LNS_ADVANCE_PC);
1562 w->WriteSLEB128(pc_diff);
1563 w->Write<uint8_t>(DW_LNS_ADVANCE_LINE);
1564 w->WriteSLEB128(line_diff);
Ben Murdochb8e0da22011-05-16 14:20:40 +01001565 w->Write<uint8_t>(DW_LNS_COPY);
1566 }
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001567
1568 // Increment the pc and line operands.
1569 pc += pc_diff;
1570 line += line_diff;
Ben Murdochb8e0da22011-05-16 14:20:40 +01001571 }
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001572 // Advance the pc to the end of the routine, since the end sequence opcode
1573 // requires this.
1574 w->Write<uint8_t>(DW_LNS_ADVANCE_PC);
1575 w->WriteSLEB128(desc_->CodeSize() - pc);
Ben Murdochb8e0da22011-05-16 14:20:40 +01001576 WriteExtendedOpcode(w, DW_LNE_END_SEQUENCE, 0);
1577 total_length.set(static_cast<uint32_t>(w->position() - start));
1578 return true;
1579 }
1580
1581 private:
1582 void WriteExtendedOpcode(Writer* w,
1583 DWARF2ExtendedOpcode op,
1584 size_t operands_size) {
1585 w->Write<uint8_t>(0);
1586 w->WriteULEB128(operands_size + 1);
1587 w->Write<uint8_t>(op);
1588 }
1589
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001590 static int ComparePCInfo(const LineInfo::PCInfo* a,
1591 const LineInfo::PCInfo* b) {
Ben Murdochb8e0da22011-05-16 14:20:40 +01001592 if (a->pc_ == b->pc_) {
1593 if (a->is_statement_ != b->is_statement_) {
1594 return b->is_statement_ ? +1 : -1;
1595 }
1596 return 0;
1597 } else if (a->pc_ > b->pc_) {
1598 return +1;
1599 } else {
1600 return -1;
1601 }
1602 }
1603
1604 CodeDescription* desc_;
1605};
1606
1607
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001608#if V8_TARGET_ARCH_X64
Steve Block1e0659c2011-05-24 12:43:12 +01001609
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001610class UnwindInfoSection : public DebugSection {
Steve Block1e0659c2011-05-24 12:43:12 +01001611 public:
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001612 explicit UnwindInfoSection(CodeDescription* desc);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001613 virtual bool WriteBodyInternal(Writer* w);
Steve Block1e0659c2011-05-24 12:43:12 +01001614
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001615 int WriteCIE(Writer* w);
1616 void WriteFDE(Writer* w, int);
Steve Block1e0659c2011-05-24 12:43:12 +01001617
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001618 void WriteFDEStateOnEntry(Writer* w);
1619 void WriteFDEStateAfterRBPPush(Writer* w);
1620 void WriteFDEStateAfterRBPSet(Writer* w);
1621 void WriteFDEStateAfterRBPPop(Writer* w);
Steve Block1e0659c2011-05-24 12:43:12 +01001622
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001623 void WriteLength(Writer* w,
Steve Block1e0659c2011-05-24 12:43:12 +01001624 Writer::Slot<uint32_t>* length_slot,
1625 int initial_position);
1626
1627 private:
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001628 CodeDescription* desc_;
Steve Block1e0659c2011-05-24 12:43:12 +01001629
1630 // DWARF3 Specification, Table 7.23
1631 enum CFIInstructions {
1632 DW_CFA_ADVANCE_LOC = 0x40,
1633 DW_CFA_OFFSET = 0x80,
1634 DW_CFA_RESTORE = 0xC0,
1635 DW_CFA_NOP = 0x00,
1636 DW_CFA_SET_LOC = 0x01,
1637 DW_CFA_ADVANCE_LOC1 = 0x02,
1638 DW_CFA_ADVANCE_LOC2 = 0x03,
1639 DW_CFA_ADVANCE_LOC4 = 0x04,
1640 DW_CFA_OFFSET_EXTENDED = 0x05,
1641 DW_CFA_RESTORE_EXTENDED = 0x06,
1642 DW_CFA_UNDEFINED = 0x07,
1643 DW_CFA_SAME_VALUE = 0x08,
1644 DW_CFA_REGISTER = 0x09,
1645 DW_CFA_REMEMBER_STATE = 0x0A,
1646 DW_CFA_RESTORE_STATE = 0x0B,
1647 DW_CFA_DEF_CFA = 0x0C,
1648 DW_CFA_DEF_CFA_REGISTER = 0x0D,
1649 DW_CFA_DEF_CFA_OFFSET = 0x0E,
1650
1651 DW_CFA_DEF_CFA_EXPRESSION = 0x0F,
1652 DW_CFA_EXPRESSION = 0x10,
1653 DW_CFA_OFFSET_EXTENDED_SF = 0x11,
1654 DW_CFA_DEF_CFA_SF = 0x12,
1655 DW_CFA_DEF_CFA_OFFSET_SF = 0x13,
1656 DW_CFA_VAL_OFFSET = 0x14,
1657 DW_CFA_VAL_OFFSET_SF = 0x15,
1658 DW_CFA_VAL_EXPRESSION = 0x16
1659 };
1660
1661 // System V ABI, AMD64 Supplement, Version 0.99.5, Figure 3.36
1662 enum RegisterMapping {
1663 // Only the relevant ones have been added to reduce clutter.
1664 AMD64_RBP = 6,
1665 AMD64_RSP = 7,
1666 AMD64_RA = 16
1667 };
1668
1669 enum CFIConstants {
1670 CIE_ID = 0,
1671 CIE_VERSION = 1,
1672 CODE_ALIGN_FACTOR = 1,
1673 DATA_ALIGN_FACTOR = 1,
1674 RETURN_ADDRESS_REGISTER = AMD64_RA
1675 };
1676};
1677
1678
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001679void UnwindInfoSection::WriteLength(Writer* w,
Steve Block1e0659c2011-05-24 12:43:12 +01001680 Writer::Slot<uint32_t>* length_slot,
1681 int initial_position) {
1682 uint32_t align = (w->position() - initial_position) % kPointerSize;
1683
1684 if (align != 0) {
1685 for (uint32_t i = 0; i < (kPointerSize - align); i++) {
1686 w->Write<uint8_t>(DW_CFA_NOP);
1687 }
1688 }
1689
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001690 DCHECK((w->position() - initial_position) % kPointerSize == 0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001691 length_slot->set(static_cast<uint32_t>(w->position() - initial_position));
Steve Block1e0659c2011-05-24 12:43:12 +01001692}
1693
1694
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001695UnwindInfoSection::UnwindInfoSection(CodeDescription* desc)
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001696#ifdef __ELF
1697 : ELFSection(".eh_frame", TYPE_X86_64_UNWIND, 1),
1698#else
1699 : MachOSection("__eh_frame", "__TEXT", sizeof(uintptr_t),
1700 MachOSection::S_REGULAR),
1701#endif
1702 desc_(desc) { }
Steve Block1e0659c2011-05-24 12:43:12 +01001703
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001704int UnwindInfoSection::WriteCIE(Writer* w) {
Steve Block1e0659c2011-05-24 12:43:12 +01001705 Writer::Slot<uint32_t> cie_length_slot = w->CreateSlotHere<uint32_t>();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001706 uint32_t cie_position = static_cast<uint32_t>(w->position());
Steve Block1e0659c2011-05-24 12:43:12 +01001707
1708 // Write out the CIE header. Currently no 'common instructions' are
1709 // emitted onto the CIE; every FDE has its own set of instructions.
1710
1711 w->Write<uint32_t>(CIE_ID);
1712 w->Write<uint8_t>(CIE_VERSION);
1713 w->Write<uint8_t>(0); // Null augmentation string.
1714 w->WriteSLEB128(CODE_ALIGN_FACTOR);
1715 w->WriteSLEB128(DATA_ALIGN_FACTOR);
1716 w->Write<uint8_t>(RETURN_ADDRESS_REGISTER);
1717
1718 WriteLength(w, &cie_length_slot, cie_position);
1719
1720 return cie_position;
1721}
1722
1723
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001724void UnwindInfoSection::WriteFDE(Writer* w, int cie_position) {
Steve Block1e0659c2011-05-24 12:43:12 +01001725 // The only FDE for this function. The CFA is the current RBP.
1726 Writer::Slot<uint32_t> fde_length_slot = w->CreateSlotHere<uint32_t>();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001727 int fde_position = static_cast<uint32_t>(w->position());
Steve Block1e0659c2011-05-24 12:43:12 +01001728 w->Write<int32_t>(fde_position - cie_position + 4);
1729
1730 w->Write<uintptr_t>(desc_->CodeStart());
1731 w->Write<uintptr_t>(desc_->CodeSize());
1732
1733 WriteFDEStateOnEntry(w);
1734 WriteFDEStateAfterRBPPush(w);
1735 WriteFDEStateAfterRBPSet(w);
1736 WriteFDEStateAfterRBPPop(w);
1737
1738 WriteLength(w, &fde_length_slot, fde_position);
1739}
1740
1741
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001742void UnwindInfoSection::WriteFDEStateOnEntry(Writer* w) {
Steve Block1e0659c2011-05-24 12:43:12 +01001743 // The first state, just after the control has been transferred to the the
1744 // function.
1745
1746 // RBP for this function will be the value of RSP after pushing the RBP
1747 // for the previous function. The previous RBP has not been pushed yet.
1748 w->Write<uint8_t>(DW_CFA_DEF_CFA_SF);
1749 w->WriteULEB128(AMD64_RSP);
1750 w->WriteSLEB128(-kPointerSize);
1751
1752 // The RA is stored at location CFA + kCallerPCOffset. This is an invariant,
1753 // and hence omitted from the next states.
1754 w->Write<uint8_t>(DW_CFA_OFFSET_EXTENDED);
1755 w->WriteULEB128(AMD64_RA);
1756 w->WriteSLEB128(StandardFrameConstants::kCallerPCOffset);
1757
1758 // The RBP of the previous function is still in RBP.
1759 w->Write<uint8_t>(DW_CFA_SAME_VALUE);
1760 w->WriteULEB128(AMD64_RBP);
1761
1762 // Last location described by this entry.
1763 w->Write<uint8_t>(DW_CFA_SET_LOC);
1764 w->Write<uint64_t>(
1765 desc_->GetStackStateStartAddress(CodeDescription::POST_RBP_PUSH));
1766}
1767
1768
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001769void UnwindInfoSection::WriteFDEStateAfterRBPPush(Writer* w) {
Steve Block1e0659c2011-05-24 12:43:12 +01001770 // The second state, just after RBP has been pushed.
1771
1772 // RBP / CFA for this function is now the current RSP, so just set the
1773 // offset from the previous rule (from -8) to 0.
1774 w->Write<uint8_t>(DW_CFA_DEF_CFA_OFFSET);
1775 w->WriteULEB128(0);
1776
1777 // The previous RBP is stored at CFA + kCallerFPOffset. This is an invariant
1778 // in this and the next state, and hence omitted in the next state.
1779 w->Write<uint8_t>(DW_CFA_OFFSET_EXTENDED);
1780 w->WriteULEB128(AMD64_RBP);
1781 w->WriteSLEB128(StandardFrameConstants::kCallerFPOffset);
1782
1783 // Last location described by this entry.
1784 w->Write<uint8_t>(DW_CFA_SET_LOC);
1785 w->Write<uint64_t>(
1786 desc_->GetStackStateStartAddress(CodeDescription::POST_RBP_SET));
1787}
1788
1789
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001790void UnwindInfoSection::WriteFDEStateAfterRBPSet(Writer* w) {
Steve Block1e0659c2011-05-24 12:43:12 +01001791 // The third state, after the RBP has been set.
1792
1793 // The CFA can now directly be set to RBP.
1794 w->Write<uint8_t>(DW_CFA_DEF_CFA);
1795 w->WriteULEB128(AMD64_RBP);
1796 w->WriteULEB128(0);
1797
1798 // Last location described by this entry.
1799 w->Write<uint8_t>(DW_CFA_SET_LOC);
1800 w->Write<uint64_t>(
1801 desc_->GetStackStateStartAddress(CodeDescription::POST_RBP_POP));
1802}
1803
1804
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001805void UnwindInfoSection::WriteFDEStateAfterRBPPop(Writer* w) {
Steve Block1e0659c2011-05-24 12:43:12 +01001806 // The fourth (final) state. The RBP has been popped (just before issuing a
1807 // return).
1808
1809 // The CFA can is now calculated in the same way as in the first state.
1810 w->Write<uint8_t>(DW_CFA_DEF_CFA_SF);
1811 w->WriteULEB128(AMD64_RSP);
1812 w->WriteSLEB128(-kPointerSize);
1813
1814 // The RBP
1815 w->Write<uint8_t>(DW_CFA_OFFSET_EXTENDED);
1816 w->WriteULEB128(AMD64_RBP);
1817 w->WriteSLEB128(StandardFrameConstants::kCallerFPOffset);
1818
1819 // Last location described by this entry.
1820 w->Write<uint8_t>(DW_CFA_SET_LOC);
1821 w->Write<uint64_t>(desc_->CodeEnd());
1822}
1823
1824
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001825bool UnwindInfoSection::WriteBodyInternal(Writer* w) {
Steve Block1e0659c2011-05-24 12:43:12 +01001826 uint32_t cie_position = WriteCIE(w);
1827 WriteFDE(w, cie_position);
1828 return true;
1829}
1830
1831
1832#endif // V8_TARGET_ARCH_X64
1833
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001834static void CreateDWARFSections(CodeDescription* desc,
1835 Zone* zone,
1836 DebugObject* obj) {
Steve Block1e0659c2011-05-24 12:43:12 +01001837 if (desc->IsLineInfoAvailable()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001838 obj->AddSection(new(zone) DebugInfoSection(desc));
1839 obj->AddSection(new(zone) DebugAbbrevSection(desc));
1840 obj->AddSection(new(zone) DebugLineSection(desc));
Ben Murdochb8e0da22011-05-16 14:20:40 +01001841 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001842#if V8_TARGET_ARCH_X64
1843 obj->AddSection(new(zone) UnwindInfoSection(desc));
Steve Block1e0659c2011-05-24 12:43:12 +01001844#endif
Ben Murdochb8e0da22011-05-16 14:20:40 +01001845}
1846
1847
1848// -------------------------------------------------------------------
1849// Binary GDB JIT Interface as described in
1850// http://sourceware.org/gdb/onlinedocs/gdb/Declarations.html
1851extern "C" {
1852 typedef enum {
1853 JIT_NOACTION = 0,
1854 JIT_REGISTER_FN,
1855 JIT_UNREGISTER_FN
1856 } JITAction;
1857
1858 struct JITCodeEntry {
1859 JITCodeEntry* next_;
1860 JITCodeEntry* prev_;
1861 Address symfile_addr_;
1862 uint64_t symfile_size_;
1863 };
1864
1865 struct JITDescriptor {
1866 uint32_t version_;
1867 uint32_t action_flag_;
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001868 JITCodeEntry* relevant_entry_;
1869 JITCodeEntry* first_entry_;
Ben Murdochb8e0da22011-05-16 14:20:40 +01001870 };
1871
1872 // GDB will place breakpoint into this function.
1873 // To prevent GCC from inlining or removing it we place noinline attribute
1874 // and inline assembler statement inside.
1875 void __attribute__((noinline)) __jit_debug_register_code() {
1876 __asm__("");
1877 }
1878
1879 // GDB will inspect contents of this descriptor.
1880 // Static initialization is necessary to prevent GDB from seeing
1881 // uninitialized descriptor.
1882 JITDescriptor __jit_debug_descriptor = { 1, 0, 0, 0 };
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001883
1884#ifdef OBJECT_PRINT
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001885 void __gdb_print_v8_object(Object* object) {
1886 OFStream os(stdout);
1887 object->Print(os);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001888 os << std::flush;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001889 }
1890#endif
Ben Murdochb8e0da22011-05-16 14:20:40 +01001891}
1892
1893
1894static JITCodeEntry* CreateCodeEntry(Address symfile_addr,
1895 uintptr_t symfile_size) {
1896 JITCodeEntry* entry = static_cast<JITCodeEntry*>(
1897 malloc(sizeof(JITCodeEntry) + symfile_size));
1898
1899 entry->symfile_addr_ = reinterpret_cast<Address>(entry + 1);
1900 entry->symfile_size_ = symfile_size;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001901 MemCopy(entry->symfile_addr_, symfile_addr, symfile_size);
Ben Murdochb8e0da22011-05-16 14:20:40 +01001902
1903 entry->prev_ = entry->next_ = NULL;
1904
1905 return entry;
1906}
1907
1908
1909static void DestroyCodeEntry(JITCodeEntry* entry) {
1910 free(entry);
1911}
1912
1913
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001914static void RegisterCodeEntry(JITCodeEntry* entry) {
Ben Murdochb8e0da22011-05-16 14:20:40 +01001915 entry->next_ = __jit_debug_descriptor.first_entry_;
1916 if (entry->next_ != NULL) entry->next_->prev_ = entry;
1917 __jit_debug_descriptor.first_entry_ =
1918 __jit_debug_descriptor.relevant_entry_ = entry;
1919
1920 __jit_debug_descriptor.action_flag_ = JIT_REGISTER_FN;
1921 __jit_debug_register_code();
1922}
1923
1924
1925static void UnregisterCodeEntry(JITCodeEntry* entry) {
1926 if (entry->prev_ != NULL) {
1927 entry->prev_->next_ = entry->next_;
1928 } else {
1929 __jit_debug_descriptor.first_entry_ = entry->next_;
1930 }
1931
1932 if (entry->next_ != NULL) {
1933 entry->next_->prev_ = entry->prev_;
1934 }
1935
1936 __jit_debug_descriptor.relevant_entry_ = entry;
1937 __jit_debug_descriptor.action_flag_ = JIT_UNREGISTER_FN;
1938 __jit_debug_register_code();
1939}
1940
1941
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001942static JITCodeEntry* CreateELFObject(CodeDescription* desc, Isolate* isolate) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001943#ifdef __MACH_O
Ben Murdochda12d292016-06-02 14:46:10 +01001944 Zone zone(isolate->allocator());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001945 MachO mach_o(&zone);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001946 Writer w(&mach_o);
Ben Murdochb8e0da22011-05-16 14:20:40 +01001947
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001948 mach_o.AddSection(new(&zone) MachOTextSection(kCodeAlignment,
1949 desc->CodeStart(),
1950 desc->CodeSize()));
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001951
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001952 CreateDWARFSections(desc, &zone, &mach_o);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001953
1954 mach_o.Write(&w, desc->CodeStart(), desc->CodeSize());
1955#else
Ben Murdochda12d292016-06-02 14:46:10 +01001956 Zone zone(isolate->allocator());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001957 ELF elf(&zone);
Ben Murdochb8e0da22011-05-16 14:20:40 +01001958 Writer w(&elf);
1959
1960 int text_section_index = elf.AddSection(
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001961 new(&zone) FullHeaderELFSection(
1962 ".text",
1963 ELFSection::TYPE_NOBITS,
1964 kCodeAlignment,
1965 desc->CodeStart(),
1966 0,
1967 desc->CodeSize(),
1968 ELFSection::FLAG_ALLOC | ELFSection::FLAG_EXEC));
Ben Murdochb8e0da22011-05-16 14:20:40 +01001969
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001970 CreateSymbolsTable(desc, &zone, &elf, text_section_index);
Ben Murdochb8e0da22011-05-16 14:20:40 +01001971
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001972 CreateDWARFSections(desc, &zone, &elf);
Ben Murdochb8e0da22011-05-16 14:20:40 +01001973
1974 elf.Write(&w);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001975#endif
Ben Murdochb8e0da22011-05-16 14:20:40 +01001976
1977 return CreateCodeEntry(w.buffer(), w.position());
1978}
1979
1980
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001981struct AddressRange {
1982 Address start;
1983 Address end;
1984};
Ben Murdochb8e0da22011-05-16 14:20:40 +01001985
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001986struct SplayTreeConfig {
1987 typedef AddressRange Key;
1988 typedef JITCodeEntry* Value;
1989 static const AddressRange kNoKey;
1990 static Value NoValue() { return NULL; }
1991 static int Compare(const AddressRange& a, const AddressRange& b) {
1992 // ptrdiff_t probably doesn't fit in an int.
1993 if (a.start < b.start) return -1;
1994 if (a.start == b.start) return 0;
1995 return 1;
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001996 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001997};
1998
1999const AddressRange SplayTreeConfig::kNoKey = {0, 0};
2000typedef SplayTree<SplayTreeConfig> CodeMap;
2001
2002static CodeMap* GetCodeMap() {
2003 static CodeMap* code_map = NULL;
2004 if (code_map == NULL) code_map = new CodeMap();
2005 return code_map;
Ben Murdoche0cee9b2011-05-25 10:26:03 +01002006}
Ben Murdochb8e0da22011-05-16 14:20:40 +01002007
2008
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002009static uint32_t HashCodeAddress(Address addr) {
Ben Murdochb8e0da22011-05-16 14:20:40 +01002010 static const uintptr_t kGoldenRatio = 2654435761u;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002011 uintptr_t offset = OffsetFrom(addr);
2012 return static_cast<uint32_t>((offset >> kCodeAlignmentBits) * kGoldenRatio);
Ben Murdochb8e0da22011-05-16 14:20:40 +01002013}
2014
Ben Murdoch61f157c2016-09-16 13:49:30 +01002015static base::HashMap* GetLineMap() {
2016 static base::HashMap* line_map = NULL;
2017 if (line_map == NULL) {
2018 line_map = new base::HashMap(&base::HashMap::PointersMatch);
2019 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002020 return line_map;
Ben Murdochb8e0da22011-05-16 14:20:40 +01002021}
2022
2023
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002024static void PutLineInfo(Address addr, LineInfo* info) {
Ben Murdoch61f157c2016-09-16 13:49:30 +01002025 base::HashMap* line_map = GetLineMap();
2026 base::HashMap::Entry* e =
2027 line_map->LookupOrInsert(addr, HashCodeAddress(addr));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002028 if (e->value != NULL) delete static_cast<LineInfo*>(e->value);
2029 e->value = info;
Ben Murdochb8e0da22011-05-16 14:20:40 +01002030}
2031
2032
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002033static LineInfo* GetLineInfo(Address addr) {
2034 void* value = GetLineMap()->Remove(addr, HashCodeAddress(addr));
2035 return static_cast<LineInfo*>(value);
Ben Murdochb8e0da22011-05-16 14:20:40 +01002036}
2037
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002038
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002039static void AddUnwindInfo(CodeDescription* desc) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002040#if V8_TARGET_ARCH_X64
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002041 if (desc->is_function()) {
Steve Block1e0659c2011-05-24 12:43:12 +01002042 // To avoid propagating unwinding information through
Ben Murdoche0cee9b2011-05-25 10:26:03 +01002043 // compilation pipeline we use an approximation.
2044 // For most use cases this should not affect usability.
Steve Block1e0659c2011-05-24 12:43:12 +01002045 static const int kFramePointerPushOffset = 1;
2046 static const int kFramePointerSetOffset = 4;
2047 static const int kFramePointerPopOffset = -3;
2048
2049 uintptr_t frame_pointer_push_address =
2050 desc->CodeStart() + kFramePointerPushOffset;
2051
2052 uintptr_t frame_pointer_set_address =
2053 desc->CodeStart() + kFramePointerSetOffset;
2054
2055 uintptr_t frame_pointer_pop_address =
2056 desc->CodeEnd() + kFramePointerPopOffset;
2057
Steve Block1e0659c2011-05-24 12:43:12 +01002058 desc->SetStackStateStartAddress(CodeDescription::POST_RBP_PUSH,
2059 frame_pointer_push_address);
2060 desc->SetStackStateStartAddress(CodeDescription::POST_RBP_SET,
2061 frame_pointer_set_address);
2062 desc->SetStackStateStartAddress(CodeDescription::POST_RBP_POP,
2063 frame_pointer_pop_address);
2064 } else {
2065 desc->SetStackStateStartAddress(CodeDescription::POST_RBP_PUSH,
2066 desc->CodeStart());
2067 desc->SetStackStateStartAddress(CodeDescription::POST_RBP_SET,
2068 desc->CodeStart());
2069 desc->SetStackStateStartAddress(CodeDescription::POST_RBP_POP,
2070 desc->CodeEnd());
2071 }
2072#endif // V8_TARGET_ARCH_X64
2073}
2074
Ben Murdochb8e0da22011-05-16 14:20:40 +01002075
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002076static base::LazyMutex mutex = LAZY_MUTEX_INITIALIZER;
Ben Murdoch8b112d22011-06-08 16:22:53 +01002077
2078
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002079// Remove entries from the splay tree that intersect the given address range,
2080// and deregister them from GDB.
2081static void RemoveJITCodeEntries(CodeMap* map, const AddressRange& range) {
2082 DCHECK(range.start < range.end);
2083 CodeMap::Locator cur;
2084 if (map->FindGreatestLessThan(range, &cur) || map->FindLeast(&cur)) {
2085 // Skip entries that are entirely less than the range of interest.
2086 while (cur.key().end <= range.start) {
2087 // CodeMap::FindLeastGreaterThan succeeds for entries whose key is greater
2088 // than _or equal to_ the given key, so we have to advance our key to get
2089 // the next one.
2090 AddressRange new_key;
2091 new_key.start = cur.key().end;
2092 new_key.end = 0;
2093 if (!map->FindLeastGreaterThan(new_key, &cur)) return;
2094 }
2095 // Evict intersecting ranges.
2096 while (cur.key().start < range.end) {
2097 AddressRange old_range = cur.key();
2098 JITCodeEntry* old_entry = cur.value();
2099
2100 UnregisterCodeEntry(old_entry);
2101 DestroyCodeEntry(old_entry);
2102
2103 CHECK(map->Remove(old_range));
2104 if (!map->FindLeastGreaterThan(old_range, &cur)) return;
2105 }
2106 }
2107}
2108
2109
2110// Insert the entry into the splay tree and register it with GDB.
2111static void AddJITCodeEntry(CodeMap* map, const AddressRange& range,
2112 JITCodeEntry* entry, bool dump_if_enabled,
2113 const char* name_hint) {
2114#if defined(DEBUG) && !V8_OS_WIN
2115 static int file_num = 0;
2116 if (FLAG_gdbjit_dump && dump_if_enabled) {
2117 static const int kMaxFileNameSize = 64;
2118 char file_name[64];
2119
2120 SNPrintF(Vector<char>(file_name, kMaxFileNameSize), "/tmp/elfdump%s%d.o",
2121 (name_hint != NULL) ? name_hint : "", file_num++);
2122 WriteBytes(file_name, entry->symfile_addr_,
2123 static_cast<int>(entry->symfile_size_));
2124 }
2125#endif
2126
2127 CodeMap::Locator cur;
2128 CHECK(map->Insert(range, &cur));
2129 cur.set_value(entry);
2130
2131 RegisterCodeEntry(entry);
2132}
2133
2134
2135static void AddCode(const char* name, Code* code, SharedFunctionInfo* shared,
2136 LineInfo* lineinfo) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002137 DisallowHeapAllocation no_gc;
Ben Murdochb8e0da22011-05-16 14:20:40 +01002138
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002139 CodeMap* code_map = GetCodeMap();
2140 AddressRange range;
2141 range.start = code->address();
2142 range.end = code->address() + code->CodeSize();
2143 RemoveJITCodeEntries(code_map, range);
Ben Murdochb8e0da22011-05-16 14:20:40 +01002144
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002145 CodeDescription code_desc(name, code, shared, lineinfo);
Ben Murdochb8e0da22011-05-16 14:20:40 +01002146
Steve Block1e0659c2011-05-24 12:43:12 +01002147 if (!FLAG_gdbjit_full && !code_desc.IsLineInfoAvailable()) {
Ben Murdochb8e0da22011-05-16 14:20:40 +01002148 delete lineinfo;
Ben Murdochb8e0da22011-05-16 14:20:40 +01002149 return;
2150 }
2151
Steve Block1e0659c2011-05-24 12:43:12 +01002152 AddUnwindInfo(&code_desc);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002153 Isolate* isolate = code->GetIsolate();
2154 JITCodeEntry* entry = CreateELFObject(&code_desc, isolate);
Ben Murdochb8e0da22011-05-16 14:20:40 +01002155
2156 delete lineinfo;
Ben Murdochb8e0da22011-05-16 14:20:40 +01002157
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002158 const char* name_hint = NULL;
2159 bool should_dump = false;
2160 if (FLAG_gdbjit_dump) {
2161 if (strlen(FLAG_gdbjit_dump_filter) == 0) {
2162 name_hint = name;
2163 should_dump = true;
2164 } else if (name != NULL) {
2165 name_hint = strstr(name, FLAG_gdbjit_dump_filter);
2166 should_dump = (name_hint != NULL);
2167 }
2168 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002169 AddJITCodeEntry(code_map, range, entry, should_dump, name_hint);
Ben Murdochb8e0da22011-05-16 14:20:40 +01002170}
2171
2172
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002173void EventHandler(const v8::JitCodeEvent* event) {
Ben Murdochb8e0da22011-05-16 14:20:40 +01002174 if (!FLAG_gdbjit) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002175 base::LockGuard<base::Mutex> lock_guard(mutex.Pointer());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002176 switch (event->type) {
2177 case v8::JitCodeEvent::CODE_ADDED: {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002178 Address addr = reinterpret_cast<Address>(event->code_start);
2179 Code* code = Code::GetCodeFromTargetAddress(addr);
2180 LineInfo* lineinfo = GetLineInfo(addr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002181 EmbeddedVector<char, 256> buffer;
2182 StringBuilder builder(buffer.start(), buffer.length());
2183 builder.AddSubstring(event->name.str, static_cast<int>(event->name.len));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002184 // It's called UnboundScript in the API but it's a SharedFunctionInfo.
2185 SharedFunctionInfo* shared =
2186 event->script.IsEmpty() ? NULL : *Utils::OpenHandle(*event->script);
2187 AddCode(builder.Finalize(), code, shared, lineinfo);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002188 break;
2189 }
2190 case v8::JitCodeEvent::CODE_MOVED:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002191 // Enabling the GDB JIT interface should disable code compaction.
2192 UNREACHABLE();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002193 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002194 case v8::JitCodeEvent::CODE_REMOVED:
2195 // Do nothing. Instead, adding code causes eviction of any entry whose
2196 // address range intersects the address range of the added code.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002197 break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002198 case v8::JitCodeEvent::CODE_ADD_LINE_POS_INFO: {
2199 LineInfo* line_info = reinterpret_cast<LineInfo*>(event->user_data);
2200 line_info->SetPosition(static_cast<intptr_t>(event->line_info.offset),
2201 static_cast<int>(event->line_info.pos),
2202 event->line_info.position_type ==
2203 v8::JitCodeEvent::STATEMENT_POSITION);
2204 break;
2205 }
2206 case v8::JitCodeEvent::CODE_START_LINE_INFO_RECORDING: {
2207 v8::JitCodeEvent* mutable_event = const_cast<v8::JitCodeEvent*>(event);
2208 mutable_event->user_data = new LineInfo();
2209 break;
2210 }
2211 case v8::JitCodeEvent::CODE_END_LINE_INFO_RECORDING: {
2212 LineInfo* line_info = reinterpret_cast<LineInfo*>(event->user_data);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002213 PutLineInfo(reinterpret_cast<Address>(event->code_start), line_info);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002214 break;
2215 }
2216 }
2217}
Ben Murdochb8e0da22011-05-16 14:20:40 +01002218#endif
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002219} // namespace GDBJITInterface
2220} // namespace internal
2221} // namespace v8