Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(50)

Side by Side Diff: src/gdbjit.cc

Issue 5965011: Basic GDB JIT Interface integration. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: minor formatting cleanup Created 9 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // 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_GDBJIT_INTERFACE
29 #include "gdbjit.h"
30
31 #include "bootstrapper.h"
32 #include "compiler.h"
33 #include "global-handles.h"
34 #include "messages.h"
35 #include "natives.h"
36
37 namespace v8 {
38 namespace internal {
39
40 class ELF;
41
42 class Writer BASE_EMBEDDED {
43 public:
44 explicit Writer(ELF* elf)
45 : elf_(elf),
46 position_(0),
47 capacity_(1024),
48 buffer_(reinterpret_cast<byte*>(malloc(capacity_))) {
49 }
50
51 ~Writer() {
52 free(buffer_);
53 }
54
55 uintptr_t position() const {
56 return position_;
57 }
58
59 template<typename T>
60 class Slot {
61 public:
62 Slot(Writer* w, uintptr_t offset) : w_(w), offset_(offset) { }
63
64 T* operator-> () {
65 return w_->RawSlotAt<T>(offset_);
66 }
67
68 void set(const T& value) {
69 *w_->RawSlotAt<T>(offset_) = value;
70 }
71
72 Slot<T> at(int i) {
73 return Slot<T>(w_, offset_ + sizeof(T) * i);
74 }
75
76 private:
77 Writer* w_;
78 uintptr_t offset_;
79 };
80
81 template<typename T>
82 void Write(const T& val) {
83 Ensure(position_ + sizeof(T));
84 *RawSlotAt<T>(position_) = val;
85 position_ += sizeof(T);
86 }
87
88 template<typename T>
89 Slot<T> SlotAt(uintptr_t offset) {
90 Ensure(offset + sizeof(T));
91 return Slot<T>(this, offset);
92 }
93
94 template<typename T>
95 Slot<T> SlotHere() {
Erik Corry 2011/01/04 14:21:48 The name should reflect the fact that this functio
Vyacheslav Egorov (Chromium) 2011/01/18 16:10:42 Done.
96 return SlotsHere<T>(1);
97 }
98
99 template<typename T>
100 Slot<T> SlotsHere(uint32_t count) {
101 uintptr_t slot_position = position_;
102 Ensure(position_ += sizeof(T) * count);
Erik Corry 2011/01/04 14:21:48 no no no no
Vyacheslav Egorov (Chromium) 2011/01/18 16:10:42 Done.
103 return SlotAt<T>(slot_position);
104 }
105
106 void Ensure(uintptr_t pos) {
107 if (capacity_ < pos) {
108 while (capacity_ < pos) capacity_ *= 2;
109 buffer_ = reinterpret_cast<byte*>(realloc(buffer_, capacity_));
110 }
111 }
112
113 ELF* elf() { return elf_; }
114
115 byte* buffer() { return buffer_; }
116
117 void Align(uintptr_t align) {
118 uintptr_t delta = position_ % align;
119 if (delta == 0) return;
120 uintptr_t padding = align - delta;
121 Ensure(position_ += padding);
122 ASSERT((position_ % align) == 0);
123 }
124
125 void WriteULEB128(uintptr_t value) {
126 do {
127 uint8_t byte = value & 0x7F;
128 value >>= 7;
129 if (value != 0) byte |= 0x80;
130 Write<uint8_t>(byte);
131 } while (value != 0);
132 }
133
134 void WriteSLEB128(intptr_t value) {
135 bool more = true;
136 while (more) {
137 int8_t byte = value & 0x7F;
138 bool byte_sign = byte & 0x40;
139 value >>= 7;
140
141 if ((value == 0 && !byte_sign) || (value == -1 && byte_sign)) {
142 more = false;
143 } else {
144 byte |= 0x80;
145 }
146
147 Write<int8_t>(byte);
148 }
149 }
150
151 void WriteString(const char* str) {
152 do {
153 Write<char>(*str);
154 } while (*str++);
155 }
156
157 private:
158 template<typename T> friend class Slot;
159
160 template<typename T>
161 T* RawSlotAt(uintptr_t offset) {
162 ASSERT(offset < capacity_ && offset + sizeof(T) <= capacity_);
163 return reinterpret_cast<T*>(&buffer_[offset]);
164 }
165
166 ELF* elf_;
167 uintptr_t position_;
168 uintptr_t capacity_;
169 byte* buffer_;
170 };
171
172 class StringTable;
173
174 class ELFSection : public ZoneObject {
175 public:
176 struct Header {
177 uint32_t name;
178 uint32_t type;
179 uintptr_t flags;
180 uintptr_t address;
181 uintptr_t offset;
182 uintptr_t size;
183 uint32_t link;
184 uint32_t info;
185 uintptr_t alignment;
186 uintptr_t entry_size;
187 };
188
189 enum Type {
190 TYPE_NULL = 0,
191 TYPE_PROGBITS = 1,
192 TYPE_SYMTAB = 2,
193 TYPE_STRTAB = 3,
194 TYPE_RELA = 4,
195 TYPE_HASH = 5,
196 TYPE_DYNAMIC = 6,
197 TYPE_NOTE = 7,
198 TYPE_NOBITS = 8,
199 TYPE_REL = 9,
200 TYPE_SHLIB = 10,
201 TYPE_DYNSYM = 11,
202 TYPE_LOPROC = 0x70000000,
203 TYPE_HIPROC = 0x7fffffff,
204 TYPE_LOUSER = 0x80000000,
205 TYPE_HIUSER = 0xffffffff
206 };
207
208 enum Flags {
209 FLAG_WRITE = 1,
210 FLAG_ALLOC = 2,
211 FLAG_EXEC = 4
212 };
213
214 enum SpecialIndexes {
215 INDEX_ABSOLUTE = 0xfff1
216 };
217
218 ELFSection(const char* name, Type type, uintptr_t align)
219 : name_(name), type_(type), align_(align) { }
220
221 virtual ~ELFSection() { }
222
223 void PopulateHeader(Writer::Slot<Header> header, StringTable* strtab);
224
225 virtual void WriteBody(Writer::Slot<Header> header, Writer* w) {
226 uintptr_t start = w->position();
227 if (WriteBody(w)) {
228 uintptr_t end = w->position();
229 header->offset = start;
230 header->size = end - start;
231 }
232 }
233
234 virtual bool WriteBody(Writer* w) {
235 return false;
236 }
237
238 uint16_t index() const { return index_; }
239 void set_index(uint16_t index) { index_ = index; }
240
241 protected:
242 virtual void PopulateHeader(Writer::Slot<Header> header) {
243 header->flags = 0;
244 header->address = 0;
245 header->offset = 0;
246 header->size = 0;
247 header->link = 0;
248 header->info = 0;
249 header->entry_size = 0;
250 }
251
252
253 private:
254 const char* name_;
255 Type type_;
256 uintptr_t align_;
257 uint16_t index_;
258 };
259
260
261 class FullHeaderELFSection : public ELFSection {
262 public:
263 FullHeaderELFSection(const char* name,
264 Type type,
265 uintptr_t align,
266 uintptr_t addr,
267 uintptr_t offset,
268 uintptr_t size,
269 uintptr_t flags)
270 : ELFSection(name, type, align),
271 addr_(addr),
272 offset_(offset),
273 size_(size),
274 flags_(flags) { }
275
276 protected:
277 virtual void PopulateHeader(Writer::Slot<Header> header) {
278 ELFSection::PopulateHeader(header);
279 header->address = addr_;
280 header->offset = offset_;
281 header->size = size_;
282 header->flags = flags_;
283 }
284
285 private:
286 uintptr_t addr_;
287 uintptr_t offset_;
288 uintptr_t size_;
289 uintptr_t flags_;
290 };
291
292
293 class StringTable : public ELFSection {
294 public:
295 explicit StringTable(const char* name)
296 : ELFSection(name, TYPE_STRTAB, 1), writer_(NULL), offset_(0), size_(0) {
297 }
298
299 uintptr_t Add(const char* str) {
300 if (*str == '\0') return 0;
301
302 uintptr_t offset = size_;
303 WriteString(str);
304 return offset;
305 }
306
307 void AttachWriter(Writer* w) {
308 writer_ = w;
309 offset_ = writer_->position();
310
311 WriteString("");
Erik Corry 2011/01/04 14:21:48 I'm sure there is a good reason why we do this whi
Vyacheslav Egorov (Chromium) 2011/01/18 16:10:42 Done.
312 }
313
314 void DetachWriter() {
315 writer_ = NULL;
316 }
317
318 virtual void WriteBody(Writer::Slot<Header> header, Writer* w) {
319 ASSERT(writer_ == NULL);
320 header->offset = offset_;
321 header->size = size_;
322 }
323
324 private:
325 void WriteString(const char* str) {
326 uintptr_t written = 0;
327 do {
328 writer_->Write(*str);
329 written++;
330 } while (*str++);
331 size_ += written;
332 }
333
334 Writer* writer_;
335
336 uintptr_t offset_;
337 uintptr_t size_;
338 };
339
340
341 void ELFSection::PopulateHeader(Writer::Slot<ELFSection::Header> header,
342 StringTable* strtab) {
343 header->name = strtab->Add(name_);
344 header->type = type_;
345 header->alignment = align_;
346 PopulateHeader(header);
347 }
348
349
350 class ELF BASE_EMBEDDED {
351 public:
352 ELF() : sections_(6) {
353 sections_.Add(new ELFSection("", ELFSection::TYPE_NULL, 0));
354 sections_.Add(new StringTable(".shstrtab"));
355 }
356
357 void Write(Writer* w) {
358 WriteHeader(w);
359 WriteSectionTable(w);
360 WriteSections(w);
361 }
362
363 ELFSection* SectionAt(uint32_t index) {
364 return sections_[index];
365 }
366
367 uint32_t AddSection(ELFSection* section) {
368 sections_.Add(section);
369 section->set_index(sections_.length() - 1);
370 return sections_.length() - 1;
371 }
372
373 private:
374 struct ELFHeader {
375 uint8_t ident[16];
376 uint16_t type;
377 uint16_t machine;
378 uint32_t version;
379 uintptr_t entry;
380 uintptr_t pht_offset;
381 uintptr_t sht_offset;
382 uint32_t flags;
383 uint16_t header_size;
384 uint16_t pht_entry_size;
385 uint16_t pht_entry_num;
386 uint16_t sht_entry_size;
387 uint16_t sht_entry_num;
388 uint16_t sht_strtab_index;
389 };
390
391
392 void WriteHeader(Writer* w) {
393 ASSERT(w->position() == 0);
394 Writer::Slot<ELFHeader> header = w->SlotHere<ELFHeader>();
395 #if defined(V8_TARGET_ARCH_IA32)
396 const uint8_t ident[16] =
397 { 0x7f, 'E', 'L', 'F', 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0};
398 #elif defined(V8_TARGET_ARCH_X64)
399 const uint8_t ident[16] =
400 { 0x7f, 'E', 'L', 'F', 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0};
401 #endif
Erik Corry 2011/01/04 14:21:48 At least one place in this file should have an els
Vyacheslav Egorov (Chromium) 2011/01/18 16:10:42 Done.
402 memcpy(header->ident, ident, 16);
403 header->type = 1;
404 #if defined(V8_TARGET_ARCH_IA32)
405 header->machine = 3;
406 #elif defined(V8_TARGET_ARCH_X64)
407 // Processor identification value for x64 is 62 as defined in
408 // System V ABI, AMD64 Supplement
409 // http://www.x86-64.org/documentation/abi.pdf
410 header->machine = 62;
411 #endif
412 header->version = 1;
413 header->entry = 0;
414 header->pht_offset = 0;
415 header->sht_offset = sizeof(ELFHeader); // Section table follows header.
416 header->flags = 0;
417 header->header_size = sizeof(ELFHeader);
418 header->pht_entry_size = 0;
419 header->pht_entry_num = 0;
420 header->sht_entry_size = sizeof(ELFSection::Header);
421 header->sht_entry_num = sections_.length();
422 header->sht_strtab_index = 1;
423 }
424
425 void WriteSectionTable(Writer* w) {
426 // Section headers table immediately follows file header.
427 ASSERT(w->position() == sizeof(ELFHeader));
428
429 Writer::Slot<ELFSection::Header> headers =
430 w->SlotsHere<ELFSection::Header>(sections_.length());
431
432 // String table for section table is the first section.
433 StringTable* strtab = static_cast<StringTable*>(SectionAt(1));
434 strtab->AttachWriter(w);
435 for (int i = 0, length = sections_.length();
436 i < length;
437 i++) {
438 sections_[i]->PopulateHeader(headers.at(i), strtab);
439 }
440 strtab->DetachWriter();
441 }
442
443 int SectionHeaderPosition(uint32_t section_index) {
444 return sizeof(ELFHeader) + sizeof(ELFSection::Header) * section_index;
445 }
446
447 void WriteSections(Writer* w) {
448 Writer::Slot<ELFSection::Header> headers =
449 w->SlotAt<ELFSection::Header>(sizeof(ELFHeader));
450
451 for (int i = 0, length = sections_.length();
452 i < length;
453 i++) {
454 sections_[i]->WriteBody(headers.at(i), w);
455 }
456 }
457
458 ZoneList<ELFSection*> sections_;
459 };
460
461
462 class ELFSymbol BASE_EMBEDDED {
463 public:
464 enum Type {
465 TYPE_NOTYPE = 0,
466 TYPE_OBJECT = 1,
467 TYPE_FUNC = 2,
468 TYPE_SECTION = 3,
469 TYPE_FILE = 4,
470 TYPE_LOPROC = 13,
471 TYPE_HIPROC = 15
472 };
473
474 enum Binding {
475 BIND_LOCAL = 0,
476 BIND_GLOBAL = 1,
477 BIND_WEAK = 2,
478 BIND_LOPROC = 13,
479 BIND_HIPROC = 15
480 };
481
482 ELFSymbol(const char* name,
483 uintptr_t value,
484 uintptr_t size,
485 Binding binding,
486 Type type,
487 uint16_t section)
488 : name(name),
489 value(value),
490 size(size),
491 info((binding << 4) | type),
492 other(0),
493 section(section) {
494 }
495
496 Binding binding() const {
497 return static_cast<Binding>(info >> 4);
498 }
499
500 #if defined(V8_TARGET_ARCH_IA32)
501 struct SerializedLayout {
502 SerializedLayout(uint32_t name,
503 uintptr_t value,
504 uintptr_t size,
505 Binding binding,
506 Type type,
507 uint16_t section)
508 : name(name),
509 value(value),
510 size(size),
511 info((binding << 4) | type),
512 other(0),
513 section(section) {
514 }
515
516 uint32_t name;
517 uintptr_t value;
518 uintptr_t size;
519 uint8_t info;
520 uint8_t other;
521 uint16_t section;
522 };
523 #elif defined(V8_TARGET_ARCH_X64)
524 struct SerializedLayout {
525 SerializedLayout(uint32_t name,
526 uintptr_t value,
527 uintptr_t size,
528 Binding binding,
529 Type type,
530 uint16_t section)
531 : name(name),
532 info((binding << 4) | type),
533 other(0),
534 section(section),
535 value(value),
536 size(size) {
537 }
538
539 uint32_t name;
540 uint8_t info;
541 uint8_t other;
542 uint16_t section;
543 uintptr_t value;
544 uintptr_t size;
545 };
546 #endif
547
548 void Write(Writer::Slot<SerializedLayout> s, StringTable* t) {
549 // Convert symbol names from strings to indexes in the string table.
550 s->name = t->Add(name);
551 s->value = value;
552 s->size = size;
553 s->info = info;
554 s->other = other;
555 s->section = section;
556 }
557
558 private:
559 const char* name;
560 uintptr_t value;
561 uintptr_t size;
562 uint8_t info;
563 uint8_t other;
564 uint16_t section;
565 };
566
567
568 class ELFSymbolTable : public ELFSection {
569 public:
570 explicit ELFSymbolTable(const char* name)
571 : ELFSection(name, TYPE_SYMTAB, sizeof(uintptr_t)),
572 locals_(1),
573 globals_(1) {
574 }
575
576 virtual void WriteBody(Writer::Slot<Header> header, Writer* w) {
577 w->Align(header->alignment);
578 int total_symbols = locals_.length() + globals_.length() + 1;
579 header->offset = w->position();
580
581 Writer::Slot<ELFSymbol::SerializedLayout> symbols =
582 w->SlotsHere<ELFSymbol::SerializedLayout>(total_symbols);
583
584 header->size = w->position() - header->offset;
585
586 // String table for this symbol table should follow it in the section table.
587 StringTable* strtab =
588 static_cast<StringTable*>(w->elf()->SectionAt(index() + 1));
589 strtab->AttachWriter(w);
590 symbols.at(0).set(ELFSymbol::SerializedLayout(0,
591 0,
592 0,
593 ELFSymbol::BIND_LOCAL,
594 ELFSymbol::TYPE_NOTYPE,
595 0));
596 WriteSymbolsList(&locals_, symbols.at(1), strtab);
597 WriteSymbolsList(&globals_, symbols.at(locals_.length() + 1), strtab);
598 strtab->DetachWriter();
599 }
600
601 void Add(const ELFSymbol& symbol) {
602 if (symbol.binding() == ELFSymbol::BIND_LOCAL) {
603 locals_.Add(symbol);
604 } else {
605 globals_.Add(symbol);
606 }
607 }
608
609 protected:
610 virtual void PopulateHeader(Writer::Slot<Header> header) {
611 ELFSection::PopulateHeader(header);
612 // We are assuming that string table will follow symbol table.
613 header->link = index() + 1;
614 header->info = locals_.length() + 1;
615 header->entry_size = sizeof(ELFSymbol::SerializedLayout);
616 }
617
618 private:
619 void WriteSymbolsList(const ZoneList<ELFSymbol>* src,
620 Writer::Slot<ELFSymbol::SerializedLayout> dst,
621 StringTable* strtab) {
622 for (int i = 0, len = src->length();
623 i < len;
624 i++) {
625 src->at(i).Write(dst.at(i), strtab);
626 }
627 }
628
629 ZoneList<ELFSymbol> locals_;
630 ZoneList<ELFSymbol> globals_;
631 };
632
633
634 class CodeDescription BASE_EMBEDDED {
635 public:
636 CodeDescription(const char* name,
637 Code* code,
638 Handle<Script> script,
639 GDBJITLineInfo* lineinfo)
640 : name_(name), code_(code), script_(script), lineinfo_(lineinfo)
641 { }
642
643 const char* code_name() const {
644 return name_;
645 }
646
647 uintptr_t code_size() const {
648 return code_->instruction_end() - code_->instruction_start();
649 }
650
651 uintptr_t code_start() const {
652 return (uintptr_t)code_->instruction_start();
653 }
654
655 bool is_line_info_available() {
656 return !script_.is_null() &&
657 script_->source()->IsString() &&
658 script_->HasValidSource() &&
659 script_->name()->IsString() &&
660 lineinfo_ != NULL;
661 }
662
663 GDBJITLineInfo* lineinfo() const { return lineinfo_; }
664
665 SmartPointer<char> filename() {
666 return String::cast(script_->name())->ToCString();
667 }
668
669 int GetScriptLineNumber(int pos) {
670 return GetScriptLineNumberSafe(script_, pos) + 1;
671 }
672
673 private:
674 const char* name_;
675 Code* code_;
676 Handle<Script> script_;
677 GDBJITLineInfo* lineinfo_;
678 };
679
680
681 static void CreateSymbolsTable(CodeDescription* desc,
682 ELF* elf,
683 int text_section_index) {
684 ELFSymbolTable* symtab = new ELFSymbolTable(".symtab");
685 StringTable* strtab = new StringTable(".strtab");
686
687 // Symbol table should be followed by the linked string table.
688 elf->AddSection(symtab);
689 elf->AddSection(strtab);
690
691 symtab->Add(ELFSymbol("V8 Code",
692 0,
693 0,
694 ELFSymbol::BIND_LOCAL,
695 ELFSymbol::TYPE_FILE,
696 ELFSection::INDEX_ABSOLUTE));
697
698 symtab->Add(ELFSymbol(desc->code_name(),
699 0,
700 desc->code_size(),
701 ELFSymbol::BIND_GLOBAL,
702 ELFSymbol::TYPE_FUNC,
703 text_section_index));
704 }
705
706
707 class DebugInfoSection : public ELFSection {
708 public:
709 explicit DebugInfoSection(CodeDescription* desc)
710 : ELFSection(".debug_info", TYPE_PROGBITS, 1), desc_(desc) { }
711
712 bool WriteBody(Writer* w) {
713 Writer::Slot<uint32_t> size = w->SlotHere<uint32_t>();
714 uintptr_t start = w->position();
715 w->Write<uint16_t>(2); // DWARF version.
716 w->Write<uint32_t>(0); // Abbreviation table offset.
717 w->Write<uint8_t>(sizeof(intptr_t));
718
719 w->WriteULEB128(1); // Abbreviation code.
720 w->WriteString(*desc_->filename());
721 w->Write<intptr_t>(desc_->code_start());
722 w->Write<intptr_t>(desc_->code_start() + desc_->code_size());
723 w->Write<uint32_t>(0);
724 size.set(static_cast<uint32_t>(w->position() - start));
725 return true;
726 }
727
728 private:
729 CodeDescription* desc_;
730 };
731
732
733 class DebugAbbrevSection : public ELFSection {
734 public:
735 DebugAbbrevSection() : ELFSection(".debug_abbrev", TYPE_PROGBITS, 1) { }
736
737 // DWARF2 standard, figure 14.
738 enum DWARF2Tags {
739 DW_TAG_COMPILE_UNIT = 0x11
740 };
741
742 // DWARF2 standard, figure 16.
743 enum DWARF2ChildrenDetermination {
744 DW_CHILDREN_NO = 0,
745 DW_CHILDREN_YES = 1
746 };
747
748 // DWARF standard, figure 17.
749 enum DWARF2Attribute {
750 DW_AT_NAME = 0x3,
751 DW_AT_STMT_LIST = 0x10,
752 DW_AT_LOW_PC = 0x11,
753 DW_AT_HIGH_PC = 0x12
754 };
755
756 // DWARF2 standard, figure 19.
757 enum DWARF2AttributeForm {
758 DW_FORM_ADDR = 0x1,
759 DW_FORM_STRING = 0x8,
760 DW_FORM_DATA4 = 0x6
761 };
762
763 bool WriteBody(Writer* w) {
764 w->WriteULEB128(1);
765 w->WriteULEB128(DW_TAG_COMPILE_UNIT);
766 w->Write<uint8_t>(DW_CHILDREN_NO);
767 w->WriteULEB128(DW_AT_NAME);
768 w->WriteULEB128(DW_FORM_STRING);
769 w->WriteULEB128(DW_AT_LOW_PC);
770 w->WriteULEB128(DW_FORM_ADDR);
771 w->WriteULEB128(DW_AT_HIGH_PC);
772 w->WriteULEB128(DW_FORM_ADDR);
773 w->WriteULEB128(DW_AT_STMT_LIST);
774 w->WriteULEB128(DW_FORM_DATA4);
775 w->WriteULEB128(0);
776 w->WriteULEB128(0);
777 w->WriteULEB128(0);
778 return true;
779 }
780 };
781
782
783 class DebugLineSection : public ELFSection {
784 public:
785 explicit DebugLineSection(CodeDescription* desc)
786 : ELFSection(".debug_line", TYPE_PROGBITS, 1),
787 desc_(desc) { }
788
789 // DWARF2 standard, figure 34.
790 enum DWARF2Opcodes {
791 DW_LNS_COPY = 1,
792 DW_LNS_ADVANCE_PC = 2,
793 DW_LNS_ADVANCE_LINE = 3,
794 DW_LNS_SET_FILE = 4,
795 DW_LNS_SET_COLUMN = 5,
796 DW_LNS_NEGATE_STMT = 6
797 };
798
799 // DWARF2 standard, figure 35.
800 enum DWARF2ExtendedOpcode {
801 DW_LNE_END_SEQUENCE = 1,
802 DW_LNE_SET_ADDRESS = 2,
803 DW_LNE_DEFINE_FILE = 3
804 };
805
806 bool WriteBody(Writer* w) {
807 // Write prologue.
808 Writer::Slot<uint32_t> total_length = w->SlotHere<uint32_t>();
809 uintptr_t start = w->position();
810
811 w->Write<uint16_t>(2); // Field version.
812 Writer::Slot<uint32_t> prologue_length = w->SlotHere<uint32_t>();
813 uintptr_t prologue_start = w->position();
814 w->Write<uint8_t>(1); // Field minimum_instruction_length.
815 w->Write<uint8_t>(1); // Field default_is_stmt.
816 w->Write<int8_t>(0); // Field line_base.
817 w->Write<uint8_t>(2); // Field line_range.
818 w->Write<uint8_t>(DW_LNS_NEGATE_STMT + 1); // Field opcode_base.
819 w->Write<uint8_t>(0); // DW_LNS_COPY operands count.
820 w->Write<uint8_t>(1); // DW_LNS_ADVANCE_PC operands count.
821 w->Write<uint8_t>(1); // DW_LNS_ADVANCE_LINE operands count.
822 w->Write<uint8_t>(1); // DW_LNS_SET_FILE operands count.
823 w->Write<uint8_t>(1); // DW_LNS_SET_COLUMN operands count.
824 w->Write<uint8_t>(0); // DW_LNS_NEGATE_STMT operands count.
825 w->Write<uint8_t>(0); // Empty include_directories sequence.
826 w->WriteString(*desc_->filename()); // File name.
827 w->WriteULEB128(0); // Current directory.
828 w->WriteULEB128(0); // Unknown modification time.
829 w->WriteULEB128(0); // Unknown file size.
830 w->Write<uint8_t>(0);
831 prologue_length.set(static_cast<uint32_t>(w->position() - prologue_start));
832
833 WriteExtendedOpcode(w, DW_LNE_SET_ADDRESS, sizeof(intptr_t));
834 w->Write<intptr_t>(desc_->code_start());
835
836 intptr_t pc = 0;
837 intptr_t line = 1;
838 bool is_statement = true;
839
840 List<GDBJITLineInfo::PCInfo>* pc_info = desc_->lineinfo()->pc_info();
841 for (int i = 0; i < pc_info->length(); i++) {
842 GDBJITLineInfo::PCInfo* info = &pc_info->at(i);
843 uintptr_t pc_diff = info->pc_ - pc;
844 ASSERT(info->pc_ >= pc);
845 if (pc_diff != 0) {
846 w->Write<uint8_t>(DW_LNS_ADVANCE_PC);
847 w->WriteSLEB128(pc_diff);
848 pc += pc_diff;
849 }
850 intptr_t line_diff = desc_->GetScriptLineNumber(info->pos_) - line;
851 if (line_diff != 0) {
852 w->Write<uint8_t>(DW_LNS_ADVANCE_LINE);
853 w->WriteSLEB128(line_diff);
854 line += line_diff;
855 }
856 if (is_statement != info->is_statement_) {
857 w->Write<uint8_t>(DW_LNS_NEGATE_STMT);
858 is_statement = !is_statement;
Erik Corry 2011/01/04 14:21:48 How about is_statement = info->is_statement_;
Vyacheslav Egorov (Chromium) 2011/01/18 16:10:42 I want to reflect the meaning of an emitted operat
859 }
860 if (pc_diff != 0 || i == 0) {
861 w->Write<uint8_t>(DW_LNS_COPY);
862 }
863 }
864 WriteExtendedOpcode(w, DW_LNE_END_SEQUENCE, 0);
865 total_length.set(static_cast<uint32_t>(w->position() - start));
866 return true;
867 }
868
869 private:
870 void WriteExtendedOpcode(Writer* w,
871 DWARF2ExtendedOpcode op,
872 size_t operands_size) {
873 w->Write<uint8_t>(0);
874 w->WriteULEB128(operands_size + 1);
875 w->Write<uint8_t>(op);
876 }
877
878 CodeDescription* desc_;
879 };
880
881
882 static void CreateDWARFSections(CodeDescription* desc, ELF* elf) {
883 if (desc->is_line_info_available()) {
884 elf->AddSection(new DebugInfoSection(desc));
885 elf->AddSection(new DebugAbbrevSection);
886 elf->AddSection(new DebugLineSection(desc));
887 }
888 }
889
890
891 // -------------------------------------------------------------------
892 // GDB JIT Interface declarations copied as is from
893 // http://sourceware.org/gdb/onlinedocs/gdb/Declarations.html
894 extern "C" {
895 typedef enum {
896 JIT_NOACTION = 0,
897 JIT_REGISTER_FN,
898 JIT_UNREGISTER_FN
899 } jit_actions_t;
900
901 struct jit_code_entry {
902 struct jit_code_entry *next_entry;
903 struct jit_code_entry *prev_entry;
904 char *symfile_addr;
905 uint64_t symfile_size;
906 };
907
908 struct jit_descriptor {
909 uint32_t version;
910 uint32_t action_flag;
911 struct jit_code_entry *relevant_entry;
912 struct jit_code_entry *first_entry;
913 };
914
915 void __attribute__((noinline)) __jit_debug_register_code() {
916 __asm__ ("");
917 }
918
919 struct jit_descriptor __jit_debug_descriptor = { 1, 0, 0, 0 };
920 }
921
922
923 static jit_code_entry* CreateCodeEntry(byte* symfile_addr,
924 uintptr_t symfile_size) {
925 jit_code_entry* entry = static_cast<jit_code_entry*>(
926 malloc(sizeof(jit_code_entry) + symfile_size));
927
928 entry->symfile_addr = reinterpret_cast<char*>(entry + 1);
929 entry->symfile_size = symfile_size;
930 memcpy(entry->symfile_addr, symfile_addr, symfile_size);
931
932 entry->prev_entry = entry->next_entry = NULL;
933
934 return entry;
935 }
936
937
938 static void DestroyCodeEntry(jit_code_entry* entry) {
939 free(entry);
940 }
941
942
943 static void RegisterCodeEntry(jit_code_entry* entry) {
944 entry->next_entry = __jit_debug_descriptor.first_entry;
945 if (entry->next_entry != NULL) entry->next_entry->prev_entry = entry;
946 __jit_debug_descriptor.first_entry =
947 __jit_debug_descriptor.relevant_entry = entry;
948
949 __jit_debug_descriptor.action_flag = JIT_REGISTER_FN;
950 __jit_debug_register_code();
951 }
952
953
954 static void UnregisterCodeEntry(jit_code_entry* entry) {
955 if (entry->prev_entry != NULL) {
956 entry->prev_entry->next_entry = entry->next_entry;
957 } else {
958 __jit_debug_descriptor.first_entry = entry->next_entry;
959 }
960
961 if (entry->next_entry != NULL) {
962 entry->next_entry->prev_entry = entry->prev_entry;
963 }
964
965 __jit_debug_descriptor.relevant_entry = entry;
966 __jit_debug_descriptor.action_flag = JIT_UNREGISTER_FN;
967 __jit_debug_register_code();
968 }
969
970
971 static jit_code_entry* CreateELFObject(CodeDescription* desc) {
972 ZoneScope zone_scope(DELETE_ON_EXIT);
973
974 ELF elf;
975 Writer w(&elf);
976
977 int text_section_index = elf.AddSection(
978 new FullHeaderELFSection(".text",
979 ELFSection::TYPE_NOBITS,
980 kCodeAlignment,
981 desc->code_start(),
982 0,
983 desc->code_size(),
984 ELFSection::FLAG_ALLOC | ELFSection::FLAG_EXEC));
985
986 CreateSymbolsTable(desc, &elf, text_section_index);
987
988 CreateDWARFSections(desc, &elf);
989
990 elf.Write(&w);
991
992 return CreateCodeEntry(w.buffer(), w.position());
993 }
994
995
996 static bool SameCodeObjects(void* key1, void* key2) {
997 return key1 == key2;
998 }
999
1000
1001 static HashMap entries(&SameCodeObjects);
1002
1003
1004 static uint32_t HashForCodeObject(Code* code) {
1005 static const uintptr_t kGoldenRatio = 2654435761u;
1006 uintptr_t hash = reinterpret_cast<uintptr_t>(code->address());
1007 return static_cast<uint32_t>((hash >> kCodeAlignmentBits) * kGoldenRatio);
1008 }
1009
1010
1011 static const intptr_t kLineInfoTag = 0x1;
1012
1013
1014 static bool IsLineInfoTagged(void* ptr) {
1015 return 0 != (reinterpret_cast<intptr_t>(ptr) & kLineInfoTag);
1016 }
1017
1018
1019 static void* TagLineInfo(GDBJITLineInfo* ptr) {
1020 return reinterpret_cast<void*>(
1021 reinterpret_cast<intptr_t>(ptr) | kLineInfoTag);
1022 }
1023
1024
1025 static GDBJITLineInfo* UntagLineInfo(void* ptr) {
1026 return reinterpret_cast<GDBJITLineInfo*>(
1027 reinterpret_cast<intptr_t>(ptr) & ~kLineInfoTag);
1028 }
1029
1030
1031 void GDBJITInterface::AddCode(Handle<String> name,
1032 Handle<Script> script,
1033 Handle<Code> code) {
1034 if (!FLAG_gdbjit) return;
1035
1036 // Force initialization of line_ends array.
1037 GetScriptLineNumber(script, 0);
1038
1039 if (!name.is_null()) {
1040 SmartPointer<char> name_cstring = name->ToCString(DISALLOW_NULLS);
1041 AddCode(*name_cstring, *code, *script);
1042 } else {
1043 AddCode("", *code, *script);
1044 }
1045 }
1046
1047
1048 void GDBJITInterface::AddCode(const char* name,
1049 Code* code,
1050 Script* script) {
1051 if (!FLAG_gdbjit) return;
1052 AssertNoAllocation no_gc;
1053
1054 HashMap::Entry* e = entries.Lookup(code, HashForCodeObject(code), true);
1055 if (e->value != NULL && !IsLineInfoTagged(e->value)) return;
1056
1057 GDBJITLineInfo* lineinfo = UntagLineInfo(e->value);
1058 CodeDescription code_desc(name,
1059 code,
1060 script != NULL ? Handle<Script>(script)
1061 : Handle<Script>(),
1062 lineinfo);
1063
1064 if (!FLAG_gdbjit_full && !code_desc.is_line_info_available()) {
1065 delete lineinfo;
1066 entries.Remove(code, HashForCodeObject(code));
1067 return;
1068 }
1069
1070 jit_code_entry* entry = CreateELFObject(&code_desc);
1071 ASSERT(!IsLineInfoTagged(entry));
1072
1073 delete lineinfo;
1074 e->value = entry;
1075
1076 RegisterCodeEntry(entry);
1077 }
1078
1079
1080 void GDBJITInterface::AddCode(GDBJITInterface::CodeTag tag,
1081 const char* name,
1082 Code* code) {
1083 if (!FLAG_gdbjit) return;
1084
1085 EmbeddedVector<char, 256> buffer;
1086 StringBuilder builder(buffer.start(), buffer.length());
1087
1088 builder.AddString(Tag2String(tag));
1089 if ((name != NULL) && (*name != '\0')) {
1090 builder.AddString(": ");
1091 builder.AddString(name);
1092 } else {
1093 builder.AddFormatted(": code object %p", static_cast<void*>(code));
1094 }
1095
1096 AddCode(builder.Finalize(), code);
1097 }
1098
1099
1100 void GDBJITInterface::AddCode(GDBJITInterface::CodeTag tag,
1101 String* name,
1102 Code* code) {
1103 if (!FLAG_gdbjit) return;
1104 AddCode(tag, name != NULL ? *name->ToCString(DISALLOW_NULLS) : NULL, code);
1105 }
1106
1107
1108 void GDBJITInterface::AddCode(GDBJITInterface::CodeTag tag, Code* code) {
1109 if (!FLAG_gdbjit) return;
1110
1111 AddCode(tag, "", code);
1112 }
1113
1114
1115 void GDBJITInterface::RemoveCode(Code* code) {
1116 if (!FLAG_gdbjit) return;
1117
1118 HashMap::Entry* e = entries.Lookup(code, HashForCodeObject(code), false);
1119 if (e == NULL) return;
1120
1121 if (IsLineInfoTagged(e->value)) {
1122 delete UntagLineInfo(e->value);
1123 } else {
1124 jit_code_entry* entry = static_cast<jit_code_entry*>(e->value);
1125 UnregisterCodeEntry(entry);
1126 DestroyCodeEntry(entry);
1127 }
1128 e->value = NULL;
1129 entries.Remove(code, HashForCodeObject(code));
1130 }
1131
1132
1133 void GDBJITInterface::RegisterDetailedLineInfo(Code* code,
1134 GDBJITLineInfo* line_info) {
1135 ASSERT(!IsLineInfoTagged(line_info));
1136 HashMap::Entry* e = entries.Lookup(code, HashForCodeObject(code), true);
1137 ASSERT(e->value == NULL);
1138 e->value = TagLineInfo(line_info);
1139 }
1140
1141
1142 } } // namespace v8::internal
1143 #endif
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698