Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 27 | 27 |
| 28 #ifdef ENABLE_GDB_JIT_INTERFACE | 28 #ifdef ENABLE_GDB_JIT_INTERFACE |
| 29 #include "v8.h" | 29 #include "v8.h" |
| 30 #include "gdb-jit.h" | 30 #include "gdb-jit.h" |
| 31 | 31 |
| 32 #include "bootstrapper.h" | 32 #include "bootstrapper.h" |
| 33 #include "compiler.h" | 33 #include "compiler.h" |
| 34 #include "global-handles.h" | 34 #include "global-handles.h" |
| 35 #include "messages.h" | 35 #include "messages.h" |
| 36 #include "natives.h" | 36 #include "natives.h" |
| 37 #include "scopeinfo.h" | |
| 37 | 38 |
| 38 namespace v8 { | 39 namespace v8 { |
| 39 namespace internal { | 40 namespace internal { |
| 40 | 41 |
| 42 #ifdef __APPLE__ | |
| 43 #define __MACH_O | |
| 44 class MachO; | |
| 45 class MachOSection; | |
| 46 typedef MachO DebugObject; | |
| 47 typedef MachOSection DebugSection; | |
| 48 #else | |
| 49 #define __ELF | |
| 41 class ELF; | 50 class ELF; |
| 51 class ELFSection; | |
| 52 typedef ELF DebugObject; | |
| 53 typedef ELFSection DebugSection; | |
| 54 #endif | |
| 42 | 55 |
| 43 class Writer BASE_EMBEDDED { | 56 class Writer BASE_EMBEDDED { |
| 44 public: | 57 public: |
| 45 explicit Writer(ELF* elf) | 58 explicit Writer(DebugObject* debug_object) |
| 46 : elf_(elf), | 59 : debug_object_(debug_object), |
| 47 position_(0), | 60 position_(0), |
| 48 capacity_(1024), | 61 capacity_(1024), |
| 49 buffer_(reinterpret_cast<byte*>(malloc(capacity_))) { | 62 buffer_(reinterpret_cast<byte*>(malloc(capacity_))) { |
| 50 } | 63 } |
| 51 | 64 |
| 52 ~Writer() { | 65 ~Writer() { |
| 53 free(buffer_); | 66 free(buffer_); |
| 54 } | 67 } |
| 55 | 68 |
| 56 uintptr_t position() const { | 69 uintptr_t position() const { |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 105 return SlotAt<T>(slot_position); | 118 return SlotAt<T>(slot_position); |
| 106 } | 119 } |
| 107 | 120 |
| 108 void Ensure(uintptr_t pos) { | 121 void Ensure(uintptr_t pos) { |
| 109 if (capacity_ < pos) { | 122 if (capacity_ < pos) { |
| 110 while (capacity_ < pos) capacity_ *= 2; | 123 while (capacity_ < pos) capacity_ *= 2; |
| 111 buffer_ = reinterpret_cast<byte*>(realloc(buffer_, capacity_)); | 124 buffer_ = reinterpret_cast<byte*>(realloc(buffer_, capacity_)); |
| 112 } | 125 } |
| 113 } | 126 } |
| 114 | 127 |
| 115 ELF* elf() { return elf_; } | 128 DebugObject* debug_object() { return debug_object_; } |
| 116 | 129 |
| 117 byte* buffer() { return buffer_; } | 130 byte* buffer() { return buffer_; } |
| 118 | 131 |
| 119 void Align(uintptr_t align) { | 132 void Align(uintptr_t align) { |
| 120 uintptr_t delta = position_ % align; | 133 uintptr_t delta = position_ % align; |
| 121 if (delta == 0) return; | 134 if (delta == 0) return; |
| 122 uintptr_t padding = align - delta; | 135 uintptr_t padding = align - delta; |
| 123 Ensure(position_ += padding); | 136 Ensure(position_ += padding); |
| 124 ASSERT((position_ % align) == 0); | 137 ASSERT((position_ % align) == 0); |
| 125 } | 138 } |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 158 | 171 |
| 159 private: | 172 private: |
| 160 template<typename T> friend class Slot; | 173 template<typename T> friend class Slot; |
| 161 | 174 |
| 162 template<typename T> | 175 template<typename T> |
| 163 T* RawSlotAt(uintptr_t offset) { | 176 T* RawSlotAt(uintptr_t offset) { |
| 164 ASSERT(offset < capacity_ && offset + sizeof(T) <= capacity_); | 177 ASSERT(offset < capacity_ && offset + sizeof(T) <= capacity_); |
| 165 return reinterpret_cast<T*>(&buffer_[offset]); | 178 return reinterpret_cast<T*>(&buffer_[offset]); |
| 166 } | 179 } |
| 167 | 180 |
| 168 ELF* elf_; | 181 DebugObject* debug_object_; |
| 169 uintptr_t position_; | 182 uintptr_t position_; |
| 170 uintptr_t capacity_; | 183 uintptr_t capacity_; |
| 171 byte* buffer_; | 184 byte* buffer_; |
| 172 }; | 185 }; |
| 173 | 186 |
| 174 class StringTable; | 187 class StringTable; |
| 175 | 188 |
| 176 class ELFSection : public ZoneObject { | 189 template<typename THeader> |
| 190 class DebugSectionBase : public ZoneObject { | |
| 177 public: | 191 public: |
| 178 struct Header { | 192 virtual ~DebugSectionBase() { } |
| 179 uint32_t name; | 193 |
| 180 uint32_t type; | 194 virtual void WriteBody(Writer::Slot<THeader> header, Writer* writer) { |
| 181 uintptr_t flags; | 195 uintptr_t start = writer->position(); |
| 182 uintptr_t address; | 196 if (WriteBody(writer)) { |
| 183 uintptr_t offset; | 197 uintptr_t end = writer->position(); |
| 184 uintptr_t size; | 198 header->offset = start; |
| 185 uint32_t link; | 199 #if defined(__MACH_O) |
| 186 uint32_t info; | 200 header->addr = 0; |
| 187 uintptr_t alignment; | 201 #endif |
| 188 uintptr_t entry_size; | 202 header->size = end - start; |
| 203 } | |
| 204 } | |
| 205 | |
| 206 virtual bool WriteBody(Writer* writer) { | |
| 207 return false; | |
| 208 } | |
| 209 | |
| 210 typedef THeader Header; | |
| 211 }; | |
| 212 | |
| 213 | |
| 214 struct MachOSectionHeader { | |
| 215 char sectname[16]; | |
| 216 char segname[16]; | |
| 217 #if defined(V8_TARGET_ARCH_IA32) | |
| 218 uint32_t addr; | |
| 219 uint32_t size; | |
| 220 #else | |
| 221 uint64_t addr; | |
| 222 uint64_t size; | |
| 223 #endif | |
| 224 uint32_t offset; | |
| 225 uint32_t align; | |
| 226 uint32_t reloff; | |
| 227 uint32_t nreloc; | |
| 228 uint32_t flags; | |
| 229 uint32_t reserved1; | |
| 230 uint32_t reserved2; | |
| 231 }; | |
| 232 | |
| 233 | |
| 234 class MachOSection : public DebugSectionBase<MachOSectionHeader> { | |
| 235 public: | |
| 236 enum Type { | |
| 237 S_REGULAR = 0x0u, | |
| 238 S_ATTR_COALESCED = 0xbu, | |
| 239 S_ATTR_SOME_INSTRUCTIONS = 0x400u, | |
| 240 S_ATTR_DEBUG = 0x02000000u, | |
| 241 S_ATTR_PURE_INSTRUCTIONS = 0x80000000u | |
| 189 }; | 242 }; |
| 190 | 243 |
| 244 MachOSection(const char* name, | |
| 245 const char* segment, | |
| 246 uintptr_t align, | |
| 247 uint32_t flags) | |
| 248 : name_(name), | |
| 249 segment_(segment), | |
| 250 align_(align), | |
| 251 flags_(flags) { | |
| 252 ASSERT(IsPowerOf2(align)); | |
| 253 if (align_ != 0) { | |
| 254 align_ = WhichPowerOf2(align_); | |
| 255 } | |
| 256 } | |
| 257 | |
| 258 virtual ~MachOSection() { } | |
| 259 | |
| 260 virtual void PopulateHeader(Writer::Slot<Header> header) { | |
| 261 header->addr = 0; | |
| 262 header->size = 0; | |
| 263 header->offset = 0; | |
| 264 header->align = align_; | |
| 265 header->reloff = 0; | |
| 266 header->nreloc = 0; | |
| 267 header->flags = flags_; | |
| 268 header->reserved1 = 0; | |
| 269 header->reserved2 = 0; | |
| 270 memset(header->sectname, 0, 16); | |
| 271 memset(header->segname, 0, 16); | |
| 272 ASSERT(strlen(name_) < 16); | |
| 273 ASSERT(strlen(segment_) < 16); | |
| 274 strcpy(header->sectname, name_); | |
| 275 strcpy(header->segname, segment_); | |
| 276 } | |
| 277 | |
| 278 private: | |
| 279 const char* name_; | |
| 280 const char* segment_; | |
| 281 uintptr_t align_; | |
| 282 uint32_t flags_; | |
| 283 }; | |
| 284 | |
| 285 | |
| 286 struct ELFSectionHeader { | |
| 287 uint32_t name; | |
| 288 uint32_t type; | |
| 289 uintptr_t flags; | |
| 290 uintptr_t address; | |
| 291 uintptr_t offset; | |
| 292 uintptr_t size; | |
| 293 uint32_t link; | |
| 294 uint32_t info; | |
| 295 uintptr_t alignment; | |
| 296 uintptr_t entry_size; | |
| 297 }; | |
| 298 | |
| 299 | |
| 300 #if defined(__ELF) | |
| 301 class ELFSection : public DebugSectionBase<ELFSectionHeader> { | |
| 302 public: | |
| 191 enum Type { | 303 enum Type { |
| 192 TYPE_NULL = 0, | 304 TYPE_NULL = 0, |
| 193 TYPE_PROGBITS = 1, | 305 TYPE_PROGBITS = 1, |
| 194 TYPE_SYMTAB = 2, | 306 TYPE_SYMTAB = 2, |
| 195 TYPE_STRTAB = 3, | 307 TYPE_STRTAB = 3, |
| 196 TYPE_RELA = 4, | 308 TYPE_RELA = 4, |
| 197 TYPE_HASH = 5, | 309 TYPE_HASH = 5, |
| 198 TYPE_DYNAMIC = 6, | 310 TYPE_DYNAMIC = 6, |
| 199 TYPE_NOTE = 7, | 311 TYPE_NOTE = 7, |
| 200 TYPE_NOBITS = 8, | 312 TYPE_NOBITS = 8, |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 245 virtual void PopulateHeader(Writer::Slot<Header> header) { | 357 virtual void PopulateHeader(Writer::Slot<Header> header) { |
| 246 header->flags = 0; | 358 header->flags = 0; |
| 247 header->address = 0; | 359 header->address = 0; |
| 248 header->offset = 0; | 360 header->offset = 0; |
| 249 header->size = 0; | 361 header->size = 0; |
| 250 header->link = 0; | 362 header->link = 0; |
| 251 header->info = 0; | 363 header->info = 0; |
| 252 header->entry_size = 0; | 364 header->entry_size = 0; |
| 253 } | 365 } |
| 254 | 366 |
| 255 | |
| 256 private: | 367 private: |
| 257 const char* name_; | 368 const char* name_; |
| 258 Type type_; | 369 Type type_; |
| 259 uintptr_t align_; | 370 uintptr_t align_; |
| 260 uint16_t index_; | 371 uint16_t index_; |
| 261 }; | 372 }; |
| 373 #endif // defined(__ELF) | |
| 262 | 374 |
| 263 | 375 |
| 376 #if defined(__MACH_O) | |
| 377 class MachOTextSection : public MachOSection { | |
| 378 public: | |
| 379 MachOTextSection(uintptr_t align, | |
| 380 uintptr_t addr, | |
| 381 uintptr_t size) | |
| 382 : MachOSection("__text", | |
| 383 "__TEXT", | |
| 384 align, | |
| 385 MachOSection::S_REGULAR | | |
| 386 MachOSection::S_ATTR_SOME_INSTRUCTIONS | | |
| 387 MachOSection::S_ATTR_PURE_INSTRUCTIONS), | |
| 388 addr_(addr), | |
| 389 size_(size) { } | |
| 390 | |
| 391 protected: | |
| 392 virtual void PopulateHeader(Writer::Slot<Header> header) { | |
| 393 MachOSection::PopulateHeader(header); | |
| 394 header->addr = addr_; | |
| 395 header->size = size_; | |
| 396 } | |
| 397 | |
| 398 private: | |
| 399 uintptr_t addr_; | |
| 400 uintptr_t size_; | |
| 401 }; | |
| 402 #endif // defined(__MACH_O) | |
| 403 | |
| 404 | |
| 405 #if defined(__ELF) | |
| 264 class FullHeaderELFSection : public ELFSection { | 406 class FullHeaderELFSection : public ELFSection { |
| 265 public: | 407 public: |
| 266 FullHeaderELFSection(const char* name, | 408 FullHeaderELFSection(const char* name, |
| 267 Type type, | 409 Type type, |
| 268 uintptr_t align, | 410 uintptr_t align, |
| 269 uintptr_t addr, | 411 uintptr_t addr, |
| 270 uintptr_t offset, | 412 uintptr_t offset, |
| 271 uintptr_t size, | 413 uintptr_t size, |
| 272 uintptr_t flags) | 414 uintptr_t flags) |
| 273 : ELFSection(name, type, align), | 415 : ELFSection(name, type, align), |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 342 }; | 484 }; |
| 343 | 485 |
| 344 | 486 |
| 345 void ELFSection::PopulateHeader(Writer::Slot<ELFSection::Header> header, | 487 void ELFSection::PopulateHeader(Writer::Slot<ELFSection::Header> header, |
| 346 StringTable* strtab) { | 488 StringTable* strtab) { |
| 347 header->name = strtab->Add(name_); | 489 header->name = strtab->Add(name_); |
| 348 header->type = type_; | 490 header->type = type_; |
| 349 header->alignment = align_; | 491 header->alignment = align_; |
| 350 PopulateHeader(header); | 492 PopulateHeader(header); |
| 351 } | 493 } |
| 494 #endif // defined(__ELF) | |
| 352 | 495 |
| 353 | 496 |
| 497 #if defined(__MACH_O) | |
| 498 class MachO BASE_EMBEDDED { | |
| 499 public: | |
| 500 MachO() : sections_(6) { } | |
| 501 | |
| 502 uint32_t AddSection(MachOSection* section) { | |
| 503 sections_.Add(section); | |
| 504 return sections_.length() - 1; | |
| 505 } | |
| 506 | |
| 507 void Write(Writer* w, uintptr_t code_start, uintptr_t code_size) { | |
| 508 Writer::Slot<MachOHeader> header = WriteHeader(w); | |
| 509 uintptr_t load_command_start = w->position(); | |
| 510 Writer::Slot<MachOSegmentCommand> cmd = WriteSegmentCommand(w, | |
| 511 code_start, | |
| 512 code_size); | |
| 513 WriteSections(w, cmd, header, load_command_start); | |
| 514 } | |
| 515 | |
| 516 private: | |
| 517 struct MachOHeader { | |
| 518 uint32_t magic; | |
| 519 uint32_t cputype; | |
| 520 uint32_t cpusubtype; | |
| 521 uint32_t filetype; | |
| 522 uint32_t ncmds; | |
| 523 uint32_t sizeofcmds; | |
| 524 uint32_t flags; | |
| 525 #if defined(V8_TARGET_ARCH_X64) | |
| 526 uint32_t reserved; | |
| 527 #endif | |
| 528 }; | |
| 529 | |
| 530 struct MachOSegmentCommand { | |
| 531 uint32_t cmd; | |
| 532 uint32_t cmdsize; | |
| 533 char segname[16]; | |
| 534 #if defined(V8_TARGET_ARCH_IA32) | |
| 535 uint32_t vmaddr; | |
| 536 uint32_t vmsize; | |
| 537 uint32_t fileoff; | |
| 538 uint32_t filesize; | |
| 539 #else | |
| 540 uint64_t vmaddr; | |
| 541 uint64_t vmsize; | |
| 542 uint64_t fileoff; | |
| 543 uint64_t filesize; | |
| 544 #endif | |
| 545 uint32_t maxprot; | |
| 546 uint32_t initprot; | |
| 547 uint32_t nsects; | |
| 548 uint32_t flags; | |
| 549 }; | |
| 550 | |
| 551 enum MachOLoadCommandCmd { | |
| 552 LC_SEGMENT_32 = 0x00000001u, | |
| 553 LC_SEGMENT_64 = 0x00000019u | |
| 554 }; | |
| 555 | |
| 556 | |
| 557 Writer::Slot<MachOHeader> WriteHeader(Writer* w) { | |
| 558 ASSERT(w->position() == 0); | |
| 559 Writer::Slot<MachOHeader> header = w->CreateSlotHere<MachOHeader>(); | |
| 560 #if defined(V8_TARGET_ARCH_IA32) | |
| 561 header->magic = 0xFEEDFACEu; | |
| 562 header->cputype = 7; // i386 | |
| 563 header->cpusubtype = 3; // CPU_SUBTYPE_I386_ALL | |
| 564 #elif defined(V8_TARGET_ARCH_X64) | |
| 565 header->magic = 0xFEEDFACFu; | |
| 566 header->cputype = 7 | 0x01000000; // i386 | 64-bit ABI | |
| 567 header->cpusubtype = 3; // CPU_SUBTYPE_I386_ALL | |
| 568 header->reserved = 0; | |
| 569 #else | |
| 570 #error Unsupported target architecture. | |
| 571 #endif | |
| 572 header->filetype = 0x1; // MH_OBJECT | |
| 573 header->ncmds = 1; | |
| 574 header->sizeofcmds = 0; | |
| 575 header->flags = 0; | |
| 576 return header; | |
| 577 } | |
| 578 | |
| 579 | |
| 580 Writer::Slot<MachOSegmentCommand> WriteSegmentCommand(Writer* w, | |
| 581 uintptr_t code_start, | |
| 582 uintptr_t code_size) { | |
| 583 Writer::Slot<MachOSegmentCommand> cmd = | |
| 584 w->CreateSlotHere<MachOSegmentCommand>(); | |
| 585 #if defined(V8_TARGET_ARCH_IA32) | |
| 586 cmd->cmd = LC_SEGMENT_32; | |
| 587 #else | |
| 588 cmd->cmd = LC_SEGMENT_64; | |
| 589 #endif | |
| 590 cmd->vmaddr = code_start; | |
| 591 cmd->vmsize = code_size; | |
| 592 cmd->fileoff = 0; | |
| 593 cmd->filesize = 0; | |
| 594 cmd->maxprot = 7; | |
| 595 cmd->initprot = 7; | |
| 596 cmd->flags = 0; | |
| 597 cmd->nsects = sections_.length(); | |
| 598 memset(cmd->segname, 0, 16); | |
| 599 cmd->cmdsize = sizeof(MachOSegmentCommand) + sizeof(MachOSection::Header) * | |
| 600 cmd->nsects; | |
| 601 return cmd; | |
| 602 } | |
| 603 | |
| 604 | |
| 605 void WriteSections(Writer* w, | |
| 606 Writer::Slot<MachOSegmentCommand> cmd, | |
| 607 Writer::Slot<MachOHeader> header, | |
| 608 uintptr_t load_command_start) { | |
| 609 Writer::Slot<MachOSection::Header> headers = | |
| 610 w->CreateSlotsHere<MachOSection::Header>(sections_.length()); | |
| 611 cmd->fileoff = w->position(); | |
| 612 header->sizeofcmds = w->position() - load_command_start; | |
| 613 for (int section = 0; section < sections_.length(); ++section) { | |
| 614 sections_[section]->PopulateHeader(headers.at(section)); | |
| 615 sections_[section]->WriteBody(headers.at(section), w); | |
| 616 } | |
| 617 cmd->filesize = w->position() - (uintptr_t)cmd->fileoff; | |
| 618 } | |
| 619 | |
| 620 | |
| 621 ZoneList<MachOSection*> sections_; | |
| 622 }; | |
| 623 #endif // defined(__MACH_O) | |
| 624 | |
| 625 | |
| 626 #if defined(__ELF) | |
| 354 class ELF BASE_EMBEDDED { | 627 class ELF BASE_EMBEDDED { |
| 355 public: | 628 public: |
| 356 ELF() : sections_(6) { | 629 ELF() : sections_(6) { |
| 357 sections_.Add(new ELFSection("", ELFSection::TYPE_NULL, 0)); | 630 sections_.Add(new ELFSection("", ELFSection::TYPE_NULL, 0)); |
| 358 sections_.Add(new StringTable(".shstrtab")); | 631 sections_.Add(new StringTable(".shstrtab")); |
| 359 } | 632 } |
| 360 | 633 |
| 361 void Write(Writer* w) { | 634 void Write(Writer* w) { |
| 362 WriteHeader(w); | 635 WriteHeader(w); |
| 363 WriteSectionTable(w); | 636 WriteSectionTable(w); |
| (...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 589 int total_symbols = locals_.length() + globals_.length() + 1; | 862 int total_symbols = locals_.length() + globals_.length() + 1; |
| 590 header->offset = w->position(); | 863 header->offset = w->position(); |
| 591 | 864 |
| 592 Writer::Slot<ELFSymbol::SerializedLayout> symbols = | 865 Writer::Slot<ELFSymbol::SerializedLayout> symbols = |
| 593 w->CreateSlotsHere<ELFSymbol::SerializedLayout>(total_symbols); | 866 w->CreateSlotsHere<ELFSymbol::SerializedLayout>(total_symbols); |
| 594 | 867 |
| 595 header->size = w->position() - header->offset; | 868 header->size = w->position() - header->offset; |
| 596 | 869 |
| 597 // String table for this symbol table should follow it in the section table. | 870 // String table for this symbol table should follow it in the section table. |
| 598 StringTable* strtab = | 871 StringTable* strtab = |
| 599 static_cast<StringTable*>(w->elf()->SectionAt(index() + 1)); | 872 static_cast<StringTable*>(w->debug_object()->SectionAt(index() + 1)); |
| 600 strtab->AttachWriter(w); | 873 strtab->AttachWriter(w); |
| 601 symbols.at(0).set(ELFSymbol::SerializedLayout(0, | 874 symbols.at(0).set(ELFSymbol::SerializedLayout(0, |
| 602 0, | 875 0, |
| 603 0, | 876 0, |
| 604 ELFSymbol::BIND_LOCAL, | 877 ELFSymbol::BIND_LOCAL, |
| 605 ELFSymbol::TYPE_NOTYPE, | 878 ELFSymbol::TYPE_NOTYPE, |
| 606 0)); | 879 0)); |
| 607 WriteSymbolsList(&locals_, symbols.at(1), strtab); | 880 WriteSymbolsList(&locals_, symbols.at(1), strtab); |
| 608 WriteSymbolsList(&globals_, symbols.at(locals_.length() + 1), strtab); | 881 WriteSymbolsList(&globals_, symbols.at(locals_.length() + 1), strtab); |
| 609 strtab->DetachWriter(); | 882 strtab->DetachWriter(); |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 633 for (int i = 0, len = src->length(); | 906 for (int i = 0, len = src->length(); |
| 634 i < len; | 907 i < len; |
| 635 i++) { | 908 i++) { |
| 636 src->at(i).Write(dst.at(i), strtab); | 909 src->at(i).Write(dst.at(i), strtab); |
| 637 } | 910 } |
| 638 } | 911 } |
| 639 | 912 |
| 640 ZoneList<ELFSymbol> locals_; | 913 ZoneList<ELFSymbol> locals_; |
| 641 ZoneList<ELFSymbol> globals_; | 914 ZoneList<ELFSymbol> globals_; |
| 642 }; | 915 }; |
| 916 #endif // defined(__ELF) | |
| 643 | 917 |
| 644 | 918 |
| 645 class CodeDescription BASE_EMBEDDED { | 919 class CodeDescription BASE_EMBEDDED { |
| 646 public: | 920 public: |
| 647 #ifdef V8_TARGET_ARCH_X64 | 921 #ifdef V8_TARGET_ARCH_X64 |
| 648 enum StackState { | 922 enum StackState { |
| 649 POST_RBP_PUSH, | 923 POST_RBP_PUSH, |
| 650 POST_RBP_SET, | 924 POST_RBP_SET, |
| 651 POST_RBP_POP, | 925 POST_RBP_POP, |
| 652 STACK_STATE_MAX | 926 STACK_STATE_MAX |
| 653 }; | 927 }; |
| 654 #endif | 928 #endif |
| 655 | 929 |
| 656 CodeDescription(const char* name, | 930 CodeDescription(const char* name, |
| 657 Code* code, | 931 Code* code, |
| 658 Handle<Script> script, | 932 Handle<Script> script, |
| 659 GDBJITLineInfo* lineinfo, | 933 GDBJITLineInfo* lineinfo, |
| 660 GDBJITInterface::CodeTag tag) | 934 GDBJITInterface::CodeTag tag, |
| 935 CompilationInfo* info) | |
| 661 : name_(name), | 936 : name_(name), |
| 662 code_(code), | 937 code_(code), |
| 663 script_(script), | 938 script_(script), |
| 664 lineinfo_(lineinfo), | 939 lineinfo_(lineinfo), |
| 665 tag_(tag) { | 940 tag_(tag), |
| 941 info_(info) { | |
| 666 } | 942 } |
| 667 | 943 |
| 668 const char* name() const { | 944 const char* name() const { |
| 669 return name_; | 945 return name_; |
| 670 } | 946 } |
| 671 | 947 |
| 672 GDBJITLineInfo* lineinfo() const { | 948 GDBJITLineInfo* lineinfo() const { |
| 673 return lineinfo_; | 949 return lineinfo_; |
| 674 } | 950 } |
| 675 | 951 |
| 676 GDBJITInterface::CodeTag tag() const { | 952 GDBJITInterface::CodeTag tag() const { |
| 677 return tag_; | 953 return tag_; |
| 678 } | 954 } |
| 679 | 955 |
| 956 CompilationInfo* info() const { | |
| 957 return info_; | |
| 958 } | |
| 959 | |
| 960 bool IsInfoAvailable() const { | |
| 961 return info_ != NULL; | |
| 962 } | |
| 963 | |
| 680 uintptr_t CodeStart() const { | 964 uintptr_t CodeStart() const { |
| 681 return reinterpret_cast<uintptr_t>(code_->instruction_start()); | 965 return reinterpret_cast<uintptr_t>(code_->instruction_start()); |
| 682 } | 966 } |
| 683 | 967 |
| 684 uintptr_t CodeEnd() const { | 968 uintptr_t CodeEnd() const { |
| 685 return reinterpret_cast<uintptr_t>(code_->instruction_end()); | 969 return reinterpret_cast<uintptr_t>(code_->instruction_end()); |
| 686 } | 970 } |
| 687 | 971 |
| 688 uintptr_t CodeSize() const { | 972 uintptr_t CodeSize() const { |
| 689 return CodeEnd() - CodeStart(); | 973 return CodeEnd() - CodeStart(); |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 717 return GetScriptLineNumberSafe(script_, pos) + 1; | 1001 return GetScriptLineNumberSafe(script_, pos) + 1; |
| 718 } | 1002 } |
| 719 | 1003 |
| 720 | 1004 |
| 721 private: | 1005 private: |
| 722 const char* name_; | 1006 const char* name_; |
| 723 Code* code_; | 1007 Code* code_; |
| 724 Handle<Script> script_; | 1008 Handle<Script> script_; |
| 725 GDBJITLineInfo* lineinfo_; | 1009 GDBJITLineInfo* lineinfo_; |
| 726 GDBJITInterface::CodeTag tag_; | 1010 GDBJITInterface::CodeTag tag_; |
| 1011 CompilationInfo* info_; | |
| 727 #ifdef V8_TARGET_ARCH_X64 | 1012 #ifdef V8_TARGET_ARCH_X64 |
| 728 uintptr_t stack_state_start_addresses_[STACK_STATE_MAX]; | 1013 uintptr_t stack_state_start_addresses_[STACK_STATE_MAX]; |
| 729 #endif | 1014 #endif |
| 730 }; | 1015 }; |
| 731 | 1016 |
| 732 | 1017 #if defined(__ELF) |
| 733 static void CreateSymbolsTable(CodeDescription* desc, | 1018 static void CreateSymbolsTable(CodeDescription* desc, |
| 734 ELF* elf, | 1019 ELF* elf, |
| 735 int text_section_index) { | 1020 int text_section_index) { |
| 736 ELFSymbolTable* symtab = new ELFSymbolTable(".symtab"); | 1021 ELFSymbolTable* symtab = new ELFSymbolTable(".symtab"); |
| 737 StringTable* strtab = new StringTable(".strtab"); | 1022 StringTable* strtab = new StringTable(".strtab"); |
| 738 | 1023 |
| 739 // Symbol table should be followed by the linked string table. | 1024 // Symbol table should be followed by the linked string table. |
| 740 elf->AddSection(symtab); | 1025 elf->AddSection(symtab); |
| 741 elf->AddSection(strtab); | 1026 elf->AddSection(strtab); |
| 742 | 1027 |
| 743 symtab->Add(ELFSymbol("V8 Code", | 1028 symtab->Add(ELFSymbol("V8 Code", |
| 744 0, | 1029 0, |
| 745 0, | 1030 0, |
| 746 ELFSymbol::BIND_LOCAL, | 1031 ELFSymbol::BIND_LOCAL, |
| 747 ELFSymbol::TYPE_FILE, | 1032 ELFSymbol::TYPE_FILE, |
| 748 ELFSection::INDEX_ABSOLUTE)); | 1033 ELFSection::INDEX_ABSOLUTE)); |
| 749 | 1034 |
| 750 symtab->Add(ELFSymbol(desc->name(), | 1035 symtab->Add(ELFSymbol(desc->name(), |
| 751 0, | 1036 0, |
| 752 desc->CodeSize(), | 1037 desc->CodeSize(), |
| 753 ELFSymbol::BIND_GLOBAL, | 1038 ELFSymbol::BIND_GLOBAL, |
| 754 ELFSymbol::TYPE_FUNC, | 1039 ELFSymbol::TYPE_FUNC, |
| 755 text_section_index)); | 1040 text_section_index)); |
| 756 } | 1041 } |
| 1042 #endif // defined(__ELF) | |
| 757 | 1043 |
| 758 | 1044 |
| 759 class DebugInfoSection : public ELFSection { | 1045 class DebugInfoSection : public DebugSection { |
| 760 public: | 1046 public: |
| 761 explicit DebugInfoSection(CodeDescription* desc) | 1047 explicit DebugInfoSection(CodeDescription* desc) |
| 762 : ELFSection(".debug_info", TYPE_PROGBITS, 1), desc_(desc) { } | 1048 #if defined(__ELF) |
| 1049 : ELFSection(".debug_info", TYPE_PROGBITS, 1), | |
| 1050 #else | |
| 1051 : MachOSection("__debug_info", | |
| 1052 "__DWARF", | |
| 1053 1, | |
| 1054 MachOSection::S_REGULAR | MachOSection::S_ATTR_DEBUG), | |
| 1055 #endif | |
| 1056 desc_(desc) { } | |
| 1057 | |
| 1058 // DWARF2 standard | |
| 1059 enum DWARF2LocationOp { | |
| 1060 DW_OP_reg0 = 0x50, | |
| 1061 DW_OP_reg1 = 0x51, | |
| 1062 DW_OP_reg2 = 0x52, | |
| 1063 DW_OP_reg3 = 0x53, | |
| 1064 DW_OP_reg4 = 0x54, | |
| 1065 DW_OP_reg5 = 0x55, | |
| 1066 DW_OP_reg6 = 0x56, | |
| 1067 DW_OP_reg7 = 0x57, | |
| 1068 DW_OP_fbreg = 0x91 // 1 param: SLEB128 offset | |
| 1069 }; | |
| 1070 | |
| 1071 enum DWARF2Encoding { | |
| 1072 DW_ATE_ADDRESS = 0x1, | |
| 1073 DW_ATE_SIGNED = 0x5 | |
| 1074 }; | |
| 763 | 1075 |
| 764 bool WriteBody(Writer* w) { | 1076 bool WriteBody(Writer* w) { |
| 1077 uintptr_t cu_start = w->position(); | |
| 765 Writer::Slot<uint32_t> size = w->CreateSlotHere<uint32_t>(); | 1078 Writer::Slot<uint32_t> size = w->CreateSlotHere<uint32_t>(); |
| 766 uintptr_t start = w->position(); | 1079 uintptr_t start = w->position(); |
| 767 w->Write<uint16_t>(2); // DWARF version. | 1080 w->Write<uint16_t>(2); // DWARF version. |
| 768 w->Write<uint32_t>(0); // Abbreviation table offset. | 1081 w->Write<uint32_t>(0); // Abbreviation table offset. |
| 769 w->Write<uint8_t>(sizeof(intptr_t)); | 1082 w->Write<uint8_t>(sizeof(intptr_t)); |
| 770 | 1083 |
| 771 w->WriteULEB128(1); // Abbreviation code. | 1084 w->WriteULEB128(1); // Abbreviation code. |
| 772 w->WriteString(*desc_->GetFilename()); | 1085 w->WriteString(*desc_->GetFilename()); |
| 773 w->Write<intptr_t>(desc_->CodeStart()); | 1086 w->Write<intptr_t>(desc_->CodeStart()); |
| 774 w->Write<intptr_t>(desc_->CodeStart() + desc_->CodeSize()); | 1087 w->Write<intptr_t>(desc_->CodeStart() + desc_->CodeSize()); |
| 775 w->Write<uint32_t>(0); | 1088 w->Write<uint32_t>(0); |
| 1089 | |
| 1090 uint32_t ty_offset = static_cast<uint32_t>(w->position() - cu_start); | |
| 1091 w->WriteULEB128(3); | |
| 1092 w->Write<uint8_t>(kPointerSize); | |
| 1093 w->WriteString("v8value"); | |
| 1094 | |
| 1095 if (desc_->IsInfoAvailable()) { | |
| 1096 CompilationInfo* info = desc_->info(); | |
| 1097 ScopeInfo<FreeStoreAllocationPolicy> scope_info(info->scope()); | |
| 1098 w->WriteULEB128(2); | |
| 1099 w->WriteString(desc_->name()); | |
| 1100 w->Write<intptr_t>(desc_->CodeStart()); | |
| 1101 w->Write<intptr_t>(desc_->CodeStart() + desc_->CodeSize()); | |
| 1102 Writer::Slot<uint32_t> fb_block_size = w->CreateSlotHere<uint32_t>(); | |
| 1103 uintptr_t fb_block_start = w->position(); | |
| 1104 #if defined(V8_TARGET_ARCH_IA32) | |
| 1105 w->Write<uint8_t>(DW_OP_reg5); // The frame pointer's here on ia32 | |
| 1106 #elif defined(V8_TARGET_ARCH_X64) | |
| 1107 w->Write<uint8_t>(DW_OP_reg6); // and here on x64. | |
| 1108 #else | |
| 1109 #error Unsupported target architecture. | |
| 1110 #endif | |
| 1111 fb_block_size.set(static_cast<uint32_t>(w->position() - fb_block_start)); | |
| 1112 | |
| 1113 int params = scope_info.number_of_parameters(); | |
| 1114 int slots = scope_info.number_of_stack_slots(); | |
| 1115 int context_slots = scope_info.number_of_context_slots(); | |
| 1116 // The real slot ID is internal_slots + context_slot_id. | |
| 1117 int internal_slots = Context::MIN_CONTEXT_SLOTS; | |
| 1118 int locals = scope_info.NumberOfLocals(); | |
| 1119 int current_abbreviation = 4; | |
| 1120 | |
| 1121 for (int param = 0; param < params; ++param) { | |
| 1122 w->WriteULEB128(current_abbreviation++); | |
| 1123 w->WriteString( | |
| 1124 *scope_info.parameter_name(param)->ToCString(DISALLOW_NULLS)); | |
| 1125 w->Write<uint32_t>(ty_offset); | |
| 1126 Writer::Slot<uint32_t> block_size = w->CreateSlotHere<uint32_t>(); | |
| 1127 uintptr_t block_start = w->position(); | |
| 1128 w->Write<uint8_t>(DW_OP_fbreg); | |
| 1129 w->WriteSLEB128( | |
| 1130 JavaScriptFrameConstants::kLastParameterOffset + | |
| 1131 kPointerSize * (params - param - 1)); | |
| 1132 block_size.set(static_cast<uint32_t>(w->position() - block_start)); | |
| 1133 } | |
| 1134 | |
| 1135 EmbeddedVector<char, 256> buffer; | |
| 1136 StringBuilder builder(buffer.start(), buffer.length()); | |
| 1137 | |
| 1138 for (int slot = 0; slot < slots; ++slot) { | |
| 1139 w->WriteULEB128(current_abbreviation++); | |
| 1140 builder.Reset(); | |
| 1141 builder.AddFormatted("slot%d", slot); | |
| 1142 w->WriteString(builder.Finalize()); | |
| 1143 } | |
| 1144 | |
| 1145 // See contexts.h for more information. | |
| 1146 ASSERT(Context::MIN_CONTEXT_SLOTS == 4); | |
| 1147 ASSERT(Context::CLOSURE_INDEX == 0); | |
| 1148 ASSERT(Context::PREVIOUS_INDEX == 1); | |
| 1149 ASSERT(Context::EXTENSION_INDEX == 2); | |
| 1150 ASSERT(Context::GLOBAL_INDEX == 3); | |
| 1151 w->WriteULEB128(current_abbreviation++); | |
| 1152 w->WriteString(".closure"); | |
| 1153 w->WriteULEB128(current_abbreviation++); | |
| 1154 w->WriteString(".previous"); | |
| 1155 w->WriteULEB128(current_abbreviation++); | |
| 1156 w->WriteString(".extension"); | |
| 1157 w->WriteULEB128(current_abbreviation++); | |
| 1158 w->WriteString(".global"); | |
| 1159 | |
| 1160 for (int context_slot = 0; | |
| 1161 context_slot < context_slots; | |
| 1162 ++context_slot) { | |
| 1163 w->WriteULEB128(current_abbreviation++); | |
| 1164 builder.Reset(); | |
| 1165 builder.AddFormatted("context_slot%d", context_slot + internal_slots); | |
| 1166 w->WriteString(builder.Finalize()); | |
| 1167 } | |
| 1168 | |
| 1169 for (int local = 0; local < locals; ++local) { | |
| 1170 w->WriteULEB128(current_abbreviation++); | |
| 1171 w->WriteString( | |
| 1172 *scope_info.LocalName(local)->ToCString(DISALLOW_NULLS)); | |
| 1173 w->Write<uint32_t>(ty_offset); | |
| 1174 Writer::Slot<uint32_t> block_size = w->CreateSlotHere<uint32_t>(); | |
| 1175 uintptr_t block_start = w->position(); | |
| 1176 w->Write<uint8_t>(DW_OP_fbreg); | |
| 1177 w->WriteSLEB128( | |
| 1178 JavaScriptFrameConstants::kLocal0Offset - | |
| 1179 kPointerSize * local); | |
| 1180 block_size.set(static_cast<uint32_t>(w->position() - block_start)); | |
| 1181 } | |
| 1182 | |
| 1183 { | |
| 1184 w->WriteULEB128(current_abbreviation++); | |
| 1185 w->WriteString("__function"); | |
| 1186 w->Write<uint32_t>(ty_offset); | |
| 1187 Writer::Slot<uint32_t> block_size = w->CreateSlotHere<uint32_t>(); | |
| 1188 uintptr_t block_start = w->position(); | |
| 1189 w->Write<uint8_t>(DW_OP_fbreg); | |
| 1190 w->WriteSLEB128(JavaScriptFrameConstants::kFunctionOffset); | |
| 1191 block_size.set(static_cast<uint32_t>(w->position() - block_start)); | |
| 1192 } | |
| 1193 | |
| 1194 { | |
| 1195 w->WriteULEB128(current_abbreviation++); | |
| 1196 w->WriteString("__context"); | |
| 1197 w->Write<uint32_t>(ty_offset); | |
| 1198 Writer::Slot<uint32_t> block_size = w->CreateSlotHere<uint32_t>(); | |
| 1199 uintptr_t block_start = w->position(); | |
| 1200 w->Write<uint8_t>(DW_OP_fbreg); | |
| 1201 w->WriteSLEB128(StandardFrameConstants::kContextOffset); | |
| 1202 block_size.set(static_cast<uint32_t>(w->position() - block_start)); | |
| 1203 } | |
| 1204 } | |
| 1205 | |
| 776 size.set(static_cast<uint32_t>(w->position() - start)); | 1206 size.set(static_cast<uint32_t>(w->position() - start)); |
| 777 return true; | 1207 return true; |
| 778 } | 1208 } |
| 779 | 1209 |
| 780 private: | 1210 private: |
| 781 CodeDescription* desc_; | 1211 CodeDescription* desc_; |
| 782 }; | 1212 }; |
| 783 | 1213 |
| 784 | 1214 |
| 785 class DebugAbbrevSection : public ELFSection { | 1215 class DebugAbbrevSection : public DebugSection { |
| 786 public: | 1216 public: |
| 787 DebugAbbrevSection() : ELFSection(".debug_abbrev", TYPE_PROGBITS, 1) { } | 1217 explicit DebugAbbrevSection(CodeDescription* desc) |
| 1218 #ifdef __ELF | |
| 1219 : ELFSection(".debug_abbrev", TYPE_PROGBITS, 1), | |
| 1220 #else | |
| 1221 : MachOSection("__debug_abbrev", | |
| 1222 "__DWARF", | |
| 1223 1, | |
| 1224 MachOSection::S_REGULAR | MachOSection::S_ATTR_DEBUG), | |
| 1225 #endif | |
| 1226 desc_(desc) { } | |
| 788 | 1227 |
| 789 // DWARF2 standard, figure 14. | 1228 // DWARF2 standard, figure 14. |
| 790 enum DWARF2Tags { | 1229 enum DWARF2Tags { |
| 791 DW_TAG_COMPILE_UNIT = 0x11 | 1230 DW_TAG_FORMAL_PARAMETER = 0x05, |
| 1231 DW_TAG_POINTER_TYPE = 0xf, | |
| 1232 DW_TAG_COMPILE_UNIT = 0x11, | |
| 1233 DW_TAG_STRUCTURE_TYPE = 0x13, | |
| 1234 DW_TAG_BASE_TYPE = 0x24, | |
| 1235 DW_TAG_SUBPROGRAM = 0x2e, | |
| 1236 DW_TAG_VARIABLE = 0x34 | |
| 792 }; | 1237 }; |
| 793 | 1238 |
| 794 // DWARF2 standard, figure 16. | 1239 // DWARF2 standard, figure 16. |
| 795 enum DWARF2ChildrenDetermination { | 1240 enum DWARF2ChildrenDetermination { |
| 796 DW_CHILDREN_NO = 0, | 1241 DW_CHILDREN_NO = 0, |
| 797 DW_CHILDREN_YES = 1 | 1242 DW_CHILDREN_YES = 1 |
| 798 }; | 1243 }; |
| 799 | 1244 |
| 800 // DWARF standard, figure 17. | 1245 // DWARF standard, figure 17. |
| 801 enum DWARF2Attribute { | 1246 enum DWARF2Attribute { |
| 1247 DW_AT_LOCATION = 0x2, | |
| 802 DW_AT_NAME = 0x3, | 1248 DW_AT_NAME = 0x3, |
| 1249 DW_AT_BYTE_SIZE = 0xb, | |
| 803 DW_AT_STMT_LIST = 0x10, | 1250 DW_AT_STMT_LIST = 0x10, |
| 804 DW_AT_LOW_PC = 0x11, | 1251 DW_AT_LOW_PC = 0x11, |
| 805 DW_AT_HIGH_PC = 0x12 | 1252 DW_AT_HIGH_PC = 0x12, |
| 1253 DW_AT_ENCODING = 0x3e, | |
| 1254 DW_AT_FRAME_BASE = 0x40, | |
| 1255 DW_AT_TYPE = 0x49 | |
| 806 }; | 1256 }; |
| 807 | 1257 |
| 808 // DWARF2 standard, figure 19. | 1258 // DWARF2 standard, figure 19. |
| 809 enum DWARF2AttributeForm { | 1259 enum DWARF2AttributeForm { |
| 810 DW_FORM_ADDR = 0x1, | 1260 DW_FORM_ADDR = 0x1, |
| 1261 DW_FORM_BLOCK4 = 0x4, | |
| 811 DW_FORM_STRING = 0x8, | 1262 DW_FORM_STRING = 0x8, |
| 812 DW_FORM_DATA4 = 0x6 | 1263 DW_FORM_DATA4 = 0x6, |
| 1264 DW_FORM_BLOCK = 0x9, | |
| 1265 DW_FORM_DATA1 = 0xb, | |
| 1266 DW_FORM_FLAG = 0xc, | |
| 1267 DW_FORM_REF4 = 0x13 | |
| 813 }; | 1268 }; |
| 814 | 1269 |
| 815 bool WriteBody(Writer* w) { | 1270 void WriteVariableAbbreviation(Writer* w, |
| 816 w->WriteULEB128(1); | 1271 int abbreviation_code, |
| 817 w->WriteULEB128(DW_TAG_COMPILE_UNIT); | 1272 bool has_value, |
| 1273 bool is_parameter) { | |
| 1274 w->WriteULEB128(abbreviation_code); | |
| 1275 w->WriteULEB128(is_parameter ? DW_TAG_FORMAL_PARAMETER : DW_TAG_VARIABLE); | |
| 818 w->Write<uint8_t>(DW_CHILDREN_NO); | 1276 w->Write<uint8_t>(DW_CHILDREN_NO); |
| 819 w->WriteULEB128(DW_AT_NAME); | 1277 w->WriteULEB128(DW_AT_NAME); |
| 820 w->WriteULEB128(DW_FORM_STRING); | 1278 w->WriteULEB128(DW_FORM_STRING); |
| 1279 if (has_value) { | |
| 1280 w->WriteULEB128(DW_AT_TYPE); | |
| 1281 w->WriteULEB128(DW_FORM_REF4); | |
| 1282 w->WriteULEB128(DW_AT_LOCATION); | |
| 1283 w->WriteULEB128(DW_FORM_BLOCK4); | |
| 1284 } | |
| 1285 w->WriteULEB128(0); | |
| 1286 w->WriteULEB128(0); | |
| 1287 } | |
| 1288 | |
| 1289 bool WriteBody(Writer* w) { | |
| 1290 int current_abbreviation = 1; | |
| 1291 bool extra_info = desc_->IsInfoAvailable(); | |
| 1292 ASSERT(desc_->IsLineInfoAvailable()); | |
| 1293 w->WriteULEB128(current_abbreviation++); | |
| 1294 w->WriteULEB128(DW_TAG_COMPILE_UNIT); | |
| 1295 w->Write<uint8_t>(extra_info ? DW_CHILDREN_YES : DW_CHILDREN_NO); | |
| 1296 w->WriteULEB128(DW_AT_NAME); | |
| 1297 w->WriteULEB128(DW_FORM_STRING); | |
| 821 w->WriteULEB128(DW_AT_LOW_PC); | 1298 w->WriteULEB128(DW_AT_LOW_PC); |
| 822 w->WriteULEB128(DW_FORM_ADDR); | 1299 w->WriteULEB128(DW_FORM_ADDR); |
| 823 w->WriteULEB128(DW_AT_HIGH_PC); | 1300 w->WriteULEB128(DW_AT_HIGH_PC); |
| 824 w->WriteULEB128(DW_FORM_ADDR); | 1301 w->WriteULEB128(DW_FORM_ADDR); |
| 825 w->WriteULEB128(DW_AT_STMT_LIST); | 1302 w->WriteULEB128(DW_AT_STMT_LIST); |
| 826 w->WriteULEB128(DW_FORM_DATA4); | 1303 w->WriteULEB128(DW_FORM_DATA4); |
| 827 w->WriteULEB128(0); | 1304 w->WriteULEB128(0); |
| 828 w->WriteULEB128(0); | 1305 w->WriteULEB128(0); |
| 829 w->WriteULEB128(0); | 1306 |
| 1307 if (extra_info) { | |
| 1308 CompilationInfo* info = desc_->info(); | |
| 1309 ScopeInfo<FreeStoreAllocationPolicy> scope_info(info->scope()); | |
| 1310 int params = scope_info.number_of_parameters(); | |
| 1311 int slots = scope_info.number_of_stack_slots(); | |
| 1312 int context_slots = scope_info.number_of_context_slots(); | |
| 1313 // The real slot ID is internal_slots + context_slot_id. | |
| 1314 int internal_slots = Context::MIN_CONTEXT_SLOTS; | |
| 1315 int locals = scope_info.NumberOfLocals(); | |
| 1316 int total_children = | |
| 1317 params + slots + context_slots + internal_slots + locals + 2; | |
| 1318 | |
| 1319 // The extra duplication below seems to be necessary to keep | |
| 1320 // gdb from getting upset on OSX. | |
| 1321 w->WriteULEB128(current_abbreviation++); // Abbreviation code. | |
| 1322 w->WriteULEB128(DW_TAG_SUBPROGRAM); | |
| 1323 w->Write<uint8_t>( | |
| 1324 total_children != 0 ? DW_CHILDREN_YES : DW_CHILDREN_NO); | |
| 1325 w->WriteULEB128(DW_AT_NAME); | |
| 1326 w->WriteULEB128(DW_FORM_STRING); | |
| 1327 w->WriteULEB128(DW_AT_LOW_PC); | |
| 1328 w->WriteULEB128(DW_FORM_ADDR); | |
| 1329 w->WriteULEB128(DW_AT_HIGH_PC); | |
| 1330 w->WriteULEB128(DW_FORM_ADDR); | |
| 1331 w->WriteULEB128(DW_AT_FRAME_BASE); | |
| 1332 w->WriteULEB128(DW_FORM_BLOCK4); | |
| 1333 w->WriteULEB128(0); | |
| 1334 w->WriteULEB128(0); | |
| 1335 | |
| 1336 w->WriteULEB128(current_abbreviation++); | |
| 1337 w->WriteULEB128(DW_TAG_STRUCTURE_TYPE); | |
|
Vyacheslav Egorov (Chromium)
2011/06/29 12:12:02
What about using DW_TAG_base_type with DW_ATE_addr
| |
| 1338 w->Write<uint8_t>(DW_CHILDREN_NO); | |
| 1339 w->WriteULEB128(DW_AT_BYTE_SIZE); | |
| 1340 w->WriteULEB128(DW_FORM_DATA1); | |
| 1341 w->WriteULEB128(DW_AT_NAME); | |
| 1342 w->WriteULEB128(DW_FORM_STRING); | |
| 1343 w->WriteULEB128(0); | |
| 1344 w->WriteULEB128(0); | |
| 1345 | |
| 1346 for (int param = 0; param < params; ++param) { | |
| 1347 WriteVariableAbbreviation(w, current_abbreviation++, true, true); | |
| 1348 } | |
| 1349 | |
| 1350 for (int slot = 0; slot < slots; ++slot) { | |
| 1351 WriteVariableAbbreviation(w, current_abbreviation++, false, false); | |
| 1352 } | |
| 1353 | |
| 1354 for (int internal_slot = 0; | |
| 1355 internal_slot < internal_slots; | |
| 1356 ++internal_slot) { | |
| 1357 WriteVariableAbbreviation(w, current_abbreviation++, false, false); | |
| 1358 } | |
| 1359 | |
| 1360 for (int context_slot = 0; | |
| 1361 context_slot < context_slots; | |
| 1362 ++context_slot) { | |
| 1363 WriteVariableAbbreviation(w, current_abbreviation++, false, false); | |
| 1364 } | |
| 1365 | |
| 1366 for (int local = 0; local < locals; ++local) { | |
| 1367 WriteVariableAbbreviation(w, current_abbreviation++, true, false); | |
| 1368 } | |
| 1369 | |
| 1370 // The function. | |
| 1371 WriteVariableAbbreviation(w, current_abbreviation++, true, false); | |
| 1372 | |
| 1373 // The context. | |
| 1374 WriteVariableAbbreviation(w, current_abbreviation++, true, false); | |
| 1375 | |
| 1376 if (total_children != 0) { | |
| 1377 w->WriteULEB128(0); // Terminate the sibling list. | |
| 1378 } | |
| 1379 } | |
| 1380 | |
| 1381 w->WriteULEB128(0); // Terminate the table. | |
| 830 return true; | 1382 return true; |
| 831 } | 1383 } |
| 1384 | |
| 1385 private: | |
| 1386 CodeDescription* desc_; | |
| 832 }; | 1387 }; |
| 833 | 1388 |
| 834 | 1389 |
| 835 class DebugLineSection : public ELFSection { | 1390 class DebugLineSection : public DebugSection { |
| 836 public: | 1391 public: |
| 837 explicit DebugLineSection(CodeDescription* desc) | 1392 explicit DebugLineSection(CodeDescription* desc) |
| 1393 #ifdef __ELF | |
| 838 : ELFSection(".debug_line", TYPE_PROGBITS, 1), | 1394 : ELFSection(".debug_line", TYPE_PROGBITS, 1), |
| 1395 #else | |
| 1396 : MachOSection("__debug_line", | |
| 1397 "__DWARF", | |
| 1398 1, | |
| 1399 MachOSection::S_REGULAR | MachOSection::S_ATTR_DEBUG), | |
| 1400 #endif | |
| 839 desc_(desc) { } | 1401 desc_(desc) { } |
| 840 | 1402 |
| 841 // DWARF2 standard, figure 34. | 1403 // DWARF2 standard, figure 34. |
| 842 enum DWARF2Opcodes { | 1404 enum DWARF2Opcodes { |
| 843 DW_LNS_COPY = 1, | 1405 DW_LNS_COPY = 1, |
| 844 DW_LNS_ADVANCE_PC = 2, | 1406 DW_LNS_ADVANCE_PC = 2, |
| 845 DW_LNS_ADVANCE_LINE = 3, | 1407 DW_LNS_ADVANCE_LINE = 3, |
| 846 DW_LNS_SET_FILE = 4, | 1408 DW_LNS_SET_FILE = 4, |
| 847 DW_LNS_SET_COLUMN = 5, | 1409 DW_LNS_SET_COLUMN = 5, |
| 848 DW_LNS_NEGATE_STMT = 6 | 1410 DW_LNS_NEGATE_STMT = 6 |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 985 return -1; | 1547 return -1; |
| 986 } | 1548 } |
| 987 } | 1549 } |
| 988 | 1550 |
| 989 CodeDescription* desc_; | 1551 CodeDescription* desc_; |
| 990 }; | 1552 }; |
| 991 | 1553 |
| 992 | 1554 |
| 993 #ifdef V8_TARGET_ARCH_X64 | 1555 #ifdef V8_TARGET_ARCH_X64 |
| 994 | 1556 |
| 995 | 1557 class UnwindInfoSection : public DebugSection { |
| 996 class UnwindInfoSection : public ELFSection { | |
| 997 public: | 1558 public: |
| 998 explicit UnwindInfoSection(CodeDescription *desc); | 1559 explicit UnwindInfoSection(CodeDescription *desc); |
| 999 virtual bool WriteBody(Writer *w); | 1560 virtual bool WriteBody(Writer *w); |
| 1000 | 1561 |
| 1001 int WriteCIE(Writer *w); | 1562 int WriteCIE(Writer *w); |
| 1002 void WriteFDE(Writer *w, int); | 1563 void WriteFDE(Writer *w, int); |
| 1003 | 1564 |
| 1004 void WriteFDEStateOnEntry(Writer *w); | 1565 void WriteFDEStateOnEntry(Writer *w); |
| 1005 void WriteFDEStateAfterRBPPush(Writer *w); | 1566 void WriteFDEStateAfterRBPPush(Writer *w); |
| 1006 void WriteFDEStateAfterRBPSet(Writer *w); | 1567 void WriteFDEStateAfterRBPSet(Writer *w); |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1072 w->Write<uint8_t>(DW_CFA_NOP); | 1633 w->Write<uint8_t>(DW_CFA_NOP); |
| 1073 } | 1634 } |
| 1074 } | 1635 } |
| 1075 | 1636 |
| 1076 ASSERT((w->position() - initial_position) % kPointerSize == 0); | 1637 ASSERT((w->position() - initial_position) % kPointerSize == 0); |
| 1077 length_slot->set(w->position() - initial_position); | 1638 length_slot->set(w->position() - initial_position); |
| 1078 } | 1639 } |
| 1079 | 1640 |
| 1080 | 1641 |
| 1081 UnwindInfoSection::UnwindInfoSection(CodeDescription *desc) | 1642 UnwindInfoSection::UnwindInfoSection(CodeDescription *desc) |
| 1082 : ELFSection(".eh_frame", TYPE_X86_64_UNWIND, 1), desc_(desc) | 1643 #ifdef __ELF |
| 1083 { } | 1644 : ELFSection(".eh_frame", TYPE_X86_64_UNWIND, 1), |
| 1645 #else | |
| 1646 : MachOSection("__eh_frame", "__TEXT", sizeof(uintptr_t), | |
| 1647 MachOSection::S_REGULAR), | |
| 1648 #endif | |
| 1649 desc_(desc) { } | |
| 1084 | 1650 |
| 1085 int UnwindInfoSection::WriteCIE(Writer *w) { | 1651 int UnwindInfoSection::WriteCIE(Writer *w) { |
| 1086 Writer::Slot<uint32_t> cie_length_slot = w->CreateSlotHere<uint32_t>(); | 1652 Writer::Slot<uint32_t> cie_length_slot = w->CreateSlotHere<uint32_t>(); |
| 1087 uint32_t cie_position = w->position(); | 1653 uint32_t cie_position = w->position(); |
| 1088 | 1654 |
| 1089 // Write out the CIE header. Currently no 'common instructions' are | 1655 // Write out the CIE header. Currently no 'common instructions' are |
| 1090 // emitted onto the CIE; every FDE has its own set of instructions. | 1656 // emitted onto the CIE; every FDE has its own set of instructions. |
| 1091 | 1657 |
| 1092 w->Write<uint32_t>(CIE_ID); | 1658 w->Write<uint32_t>(CIE_ID); |
| 1093 w->Write<uint8_t>(CIE_VERSION); | 1659 w->Write<uint8_t>(CIE_VERSION); |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1205 | 1771 |
| 1206 bool UnwindInfoSection::WriteBody(Writer *w) { | 1772 bool UnwindInfoSection::WriteBody(Writer *w) { |
| 1207 uint32_t cie_position = WriteCIE(w); | 1773 uint32_t cie_position = WriteCIE(w); |
| 1208 WriteFDE(w, cie_position); | 1774 WriteFDE(w, cie_position); |
| 1209 return true; | 1775 return true; |
| 1210 } | 1776 } |
| 1211 | 1777 |
| 1212 | 1778 |
| 1213 #endif // V8_TARGET_ARCH_X64 | 1779 #endif // V8_TARGET_ARCH_X64 |
| 1214 | 1780 |
| 1215 | 1781 static void CreateDWARFSections(CodeDescription* desc, DebugObject* obj) { |
| 1216 static void CreateDWARFSections(CodeDescription* desc, ELF* elf) { | |
| 1217 if (desc->IsLineInfoAvailable()) { | 1782 if (desc->IsLineInfoAvailable()) { |
| 1218 elf->AddSection(new DebugInfoSection(desc)); | 1783 obj->AddSection(new DebugInfoSection(desc)); |
| 1219 elf->AddSection(new DebugAbbrevSection); | 1784 obj->AddSection(new DebugAbbrevSection(desc)); |
| 1220 elf->AddSection(new DebugLineSection(desc)); | 1785 obj->AddSection(new DebugLineSection(desc)); |
| 1221 } | 1786 } |
| 1222 #ifdef V8_TARGET_ARCH_X64 | 1787 #ifdef V8_TARGET_ARCH_X64 |
| 1223 elf->AddSection(new UnwindInfoSection(desc)); | 1788 obj->AddSection(new UnwindInfoSection(desc)); |
| 1224 #endif | 1789 #endif |
| 1225 } | 1790 } |
| 1226 | 1791 |
| 1227 | 1792 |
| 1228 // ------------------------------------------------------------------- | 1793 // ------------------------------------------------------------------- |
| 1229 // Binary GDB JIT Interface as described in | 1794 // Binary GDB JIT Interface as described in |
| 1230 // http://sourceware.org/gdb/onlinedocs/gdb/Declarations.html | 1795 // http://sourceware.org/gdb/onlinedocs/gdb/Declarations.html |
| 1231 extern "C" { | 1796 extern "C" { |
| 1232 typedef enum { | 1797 typedef enum { |
| 1233 JIT_NOACTION = 0, | 1798 JIT_NOACTION = 0, |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 1253 // To prevent GCC from inlining or removing it we place noinline attribute | 1818 // To prevent GCC from inlining or removing it we place noinline attribute |
| 1254 // and inline assembler statement inside. | 1819 // and inline assembler statement inside. |
| 1255 void __attribute__((noinline)) __jit_debug_register_code() { | 1820 void __attribute__((noinline)) __jit_debug_register_code() { |
| 1256 __asm__(""); | 1821 __asm__(""); |
| 1257 } | 1822 } |
| 1258 | 1823 |
| 1259 // GDB will inspect contents of this descriptor. | 1824 // GDB will inspect contents of this descriptor. |
| 1260 // Static initialization is necessary to prevent GDB from seeing | 1825 // Static initialization is necessary to prevent GDB from seeing |
| 1261 // uninitialized descriptor. | 1826 // uninitialized descriptor. |
| 1262 JITDescriptor __jit_debug_descriptor = { 1, 0, 0, 0 }; | 1827 JITDescriptor __jit_debug_descriptor = { 1, 0, 0, 0 }; |
| 1828 | |
| 1829 #ifdef OBJECT_PRINT | |
| 1830 void __gdb_print_v8_object(MaybeObject* object) { | |
| 1831 object->Print(); | |
| 1832 fprintf(stdout, "\n"); | |
| 1833 } | |
| 1834 #endif | |
| 1263 } | 1835 } |
| 1264 | 1836 |
| 1265 | 1837 |
| 1266 static JITCodeEntry* CreateCodeEntry(Address symfile_addr, | 1838 static JITCodeEntry* CreateCodeEntry(Address symfile_addr, |
| 1267 uintptr_t symfile_size) { | 1839 uintptr_t symfile_size) { |
| 1268 JITCodeEntry* entry = static_cast<JITCodeEntry*>( | 1840 JITCodeEntry* entry = static_cast<JITCodeEntry*>( |
| 1269 malloc(sizeof(JITCodeEntry) + symfile_size)); | 1841 malloc(sizeof(JITCodeEntry) + symfile_size)); |
| 1270 | 1842 |
| 1271 entry->symfile_addr_ = reinterpret_cast<Address>(entry + 1); | 1843 entry->symfile_addr_ = reinterpret_cast<Address>(entry + 1); |
| 1272 entry->symfile_size_ = symfile_size; | 1844 entry->symfile_size_ = symfile_size; |
| 1273 memcpy(entry->symfile_addr_, symfile_addr, symfile_size); | 1845 memcpy(entry->symfile_addr_, symfile_addr, symfile_size); |
| 1274 | 1846 |
| 1275 entry->prev_ = entry->next_ = NULL; | 1847 entry->prev_ = entry->next_ = NULL; |
| 1276 | 1848 |
| 1277 return entry; | 1849 return entry; |
| 1278 } | 1850 } |
| 1279 | 1851 |
| 1280 | 1852 |
| 1281 static void DestroyCodeEntry(JITCodeEntry* entry) { | 1853 static void DestroyCodeEntry(JITCodeEntry* entry) { |
| 1282 free(entry); | 1854 free(entry); |
| 1283 } | 1855 } |
| 1284 | 1856 |
| 1285 | 1857 |
| 1286 static void RegisterCodeEntry(JITCodeEntry* entry) { | 1858 static void RegisterCodeEntry(JITCodeEntry* entry, |
| 1859 bool dump_if_enabled, | |
| 1860 const char* name_hint) { | |
| 1287 #if defined(DEBUG) && !defined(WIN32) | 1861 #if defined(DEBUG) && !defined(WIN32) |
| 1288 static int file_num = 0; | 1862 static int file_num = 0; |
| 1289 if (FLAG_gdbjit_dump) { | 1863 if (FLAG_gdbjit_dump && dump_if_enabled) { |
| 1290 static const int kMaxFileNameSize = 64; | 1864 static const int kMaxFileNameSize = 64; |
| 1291 static const char* kElfFilePrefix = "/tmp/elfdump"; | 1865 static const char* kElfFilePrefix = "/tmp/elfdump"; |
| 1292 static const char* kObjFileExt = ".o"; | 1866 static const char* kObjFileExt = ".o"; |
| 1293 char file_name[64]; | 1867 char file_name[64]; |
| 1294 | 1868 |
| 1295 OS::SNPrintF(Vector<char>(file_name, kMaxFileNameSize), "%s%d%s", | 1869 OS::SNPrintF(Vector<char>(file_name, kMaxFileNameSize), |
| 1296 kElfFilePrefix, file_num++, kObjFileExt); | 1870 "%s%s%d%s", |
| 1871 kElfFilePrefix, | |
| 1872 (name_hint != NULL) ? name_hint : "", | |
| 1873 file_num++, | |
| 1874 kObjFileExt); | |
| 1297 WriteBytes(file_name, entry->symfile_addr_, entry->symfile_size_); | 1875 WriteBytes(file_name, entry->symfile_addr_, entry->symfile_size_); |
| 1298 } | 1876 } |
| 1299 #endif | 1877 #endif |
| 1300 | 1878 |
| 1301 entry->next_ = __jit_debug_descriptor.first_entry_; | 1879 entry->next_ = __jit_debug_descriptor.first_entry_; |
| 1302 if (entry->next_ != NULL) entry->next_->prev_ = entry; | 1880 if (entry->next_ != NULL) entry->next_->prev_ = entry; |
| 1303 __jit_debug_descriptor.first_entry_ = | 1881 __jit_debug_descriptor.first_entry_ = |
| 1304 __jit_debug_descriptor.relevant_entry_ = entry; | 1882 __jit_debug_descriptor.relevant_entry_ = entry; |
| 1305 | 1883 |
| 1306 __jit_debug_descriptor.action_flag_ = JIT_REGISTER_FN; | 1884 __jit_debug_descriptor.action_flag_ = JIT_REGISTER_FN; |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 1320 } | 1898 } |
| 1321 | 1899 |
| 1322 __jit_debug_descriptor.relevant_entry_ = entry; | 1900 __jit_debug_descriptor.relevant_entry_ = entry; |
| 1323 __jit_debug_descriptor.action_flag_ = JIT_UNREGISTER_FN; | 1901 __jit_debug_descriptor.action_flag_ = JIT_UNREGISTER_FN; |
| 1324 __jit_debug_register_code(); | 1902 __jit_debug_register_code(); |
| 1325 } | 1903 } |
| 1326 | 1904 |
| 1327 | 1905 |
| 1328 static JITCodeEntry* CreateELFObject(CodeDescription* desc) { | 1906 static JITCodeEntry* CreateELFObject(CodeDescription* desc) { |
| 1329 ZoneScope zone_scope(Isolate::Current(), DELETE_ON_EXIT); | 1907 ZoneScope zone_scope(Isolate::Current(), DELETE_ON_EXIT); |
| 1908 #ifdef __MACH_O | |
| 1909 MachO mach_o; | |
| 1910 Writer w(&mach_o); | |
| 1330 | 1911 |
| 1912 mach_o.AddSection(new MachOTextSection(kCodeAlignment, | |
| 1913 desc->CodeStart(), | |
| 1914 desc->CodeSize())); | |
| 1915 | |
| 1916 CreateDWARFSections(desc, &mach_o); | |
| 1917 | |
| 1918 mach_o.Write(&w, desc->CodeStart(), desc->CodeSize()); | |
| 1919 #else | |
| 1331 ELF elf; | 1920 ELF elf; |
| 1332 Writer w(&elf); | 1921 Writer w(&elf); |
| 1333 | 1922 |
| 1334 int text_section_index = elf.AddSection( | 1923 int text_section_index = elf.AddSection( |
| 1335 new FullHeaderELFSection(".text", | 1924 new FullHeaderELFSection(".text", |
| 1336 ELFSection::TYPE_NOBITS, | 1925 ELFSection::TYPE_NOBITS, |
| 1337 kCodeAlignment, | 1926 kCodeAlignment, |
| 1338 desc->CodeStart(), | 1927 desc->CodeStart(), |
| 1339 0, | 1928 0, |
| 1340 desc->CodeSize(), | 1929 desc->CodeSize(), |
| 1341 ELFSection::FLAG_ALLOC | ELFSection::FLAG_EXEC)); | 1930 ELFSection::FLAG_ALLOC | ELFSection::FLAG_EXEC)); |
| 1342 | 1931 |
| 1343 CreateSymbolsTable(desc, &elf, text_section_index); | 1932 CreateSymbolsTable(desc, &elf, text_section_index); |
| 1344 | 1933 |
| 1345 CreateDWARFSections(desc, &elf); | 1934 CreateDWARFSections(desc, &elf); |
| 1346 | 1935 |
| 1347 elf.Write(&w); | 1936 elf.Write(&w); |
| 1937 #endif | |
| 1348 | 1938 |
| 1349 return CreateCodeEntry(w.buffer(), w.position()); | 1939 return CreateCodeEntry(w.buffer(), w.position()); |
| 1350 } | 1940 } |
| 1351 | 1941 |
| 1352 | 1942 |
| 1353 static bool SameCodeObjects(void* key1, void* key2) { | 1943 static bool SameCodeObjects(void* key1, void* key2) { |
| 1354 return key1 == key2; | 1944 return key1 == key2; |
| 1355 } | 1945 } |
| 1356 | 1946 |
| 1357 | 1947 |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 1386 | 1976 |
| 1387 | 1977 |
| 1388 static GDBJITLineInfo* UntagLineInfo(void* ptr) { | 1978 static GDBJITLineInfo* UntagLineInfo(void* ptr) { |
| 1389 return reinterpret_cast<GDBJITLineInfo*>( | 1979 return reinterpret_cast<GDBJITLineInfo*>( |
| 1390 reinterpret_cast<intptr_t>(ptr) & ~kLineInfoTag); | 1980 reinterpret_cast<intptr_t>(ptr) & ~kLineInfoTag); |
| 1391 } | 1981 } |
| 1392 | 1982 |
| 1393 | 1983 |
| 1394 void GDBJITInterface::AddCode(Handle<String> name, | 1984 void GDBJITInterface::AddCode(Handle<String> name, |
| 1395 Handle<Script> script, | 1985 Handle<Script> script, |
| 1396 Handle<Code> code) { | 1986 Handle<Code> code, |
| 1987 CompilationInfo* info) { | |
| 1397 if (!FLAG_gdbjit) return; | 1988 if (!FLAG_gdbjit) return; |
| 1398 | 1989 |
| 1399 // Force initialization of line_ends array. | 1990 // Force initialization of line_ends array. |
| 1400 GetScriptLineNumber(script, 0); | 1991 GetScriptLineNumber(script, 0); |
| 1401 | 1992 |
| 1402 if (!name.is_null()) { | 1993 if (!name.is_null()) { |
| 1403 SmartPointer<char> name_cstring = name->ToCString(DISALLOW_NULLS); | 1994 SmartPointer<char> name_cstring = name->ToCString(DISALLOW_NULLS); |
| 1404 AddCode(*name_cstring, *code, GDBJITInterface::FUNCTION, *script); | 1995 AddCode(*name_cstring, *code, GDBJITInterface::FUNCTION, *script, info); |
| 1405 } else { | 1996 } else { |
| 1406 AddCode("", *code, GDBJITInterface::FUNCTION, *script); | 1997 AddCode("", *code, GDBJITInterface::FUNCTION, *script, info); |
| 1407 } | 1998 } |
| 1408 } | 1999 } |
| 1409 | 2000 |
| 1410 static void AddUnwindInfo(CodeDescription *desc) { | 2001 static void AddUnwindInfo(CodeDescription *desc) { |
| 1411 #ifdef V8_TARGET_ARCH_X64 | 2002 #ifdef V8_TARGET_ARCH_X64 |
| 1412 if (desc->tag() == GDBJITInterface::FUNCTION) { | 2003 if (desc->tag() == GDBJITInterface::FUNCTION) { |
| 1413 // To avoid propagating unwinding information through | 2004 // To avoid propagating unwinding information through |
| 1414 // compilation pipeline we use an approximation. | 2005 // compilation pipeline we use an approximation. |
| 1415 // For most use cases this should not affect usability. | 2006 // For most use cases this should not affect usability. |
| 1416 static const int kFramePointerPushOffset = 1; | 2007 static const int kFramePointerPushOffset = 1; |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 1443 #endif // V8_TARGET_ARCH_X64 | 2034 #endif // V8_TARGET_ARCH_X64 |
| 1444 } | 2035 } |
| 1445 | 2036 |
| 1446 | 2037 |
| 1447 Mutex* GDBJITInterface::mutex_ = OS::CreateMutex(); | 2038 Mutex* GDBJITInterface::mutex_ = OS::CreateMutex(); |
| 1448 | 2039 |
| 1449 | 2040 |
| 1450 void GDBJITInterface::AddCode(const char* name, | 2041 void GDBJITInterface::AddCode(const char* name, |
| 1451 Code* code, | 2042 Code* code, |
| 1452 GDBJITInterface::CodeTag tag, | 2043 GDBJITInterface::CodeTag tag, |
| 1453 Script* script) { | 2044 Script* script, |
| 2045 CompilationInfo* info) { | |
| 1454 if (!FLAG_gdbjit) return; | 2046 if (!FLAG_gdbjit) return; |
| 1455 | 2047 |
| 1456 ScopedLock lock(mutex_); | 2048 ScopedLock lock(mutex_); |
| 1457 AssertNoAllocation no_gc; | 2049 AssertNoAllocation no_gc; |
| 1458 | 2050 |
| 1459 HashMap::Entry* e = GetEntries()->Lookup(code, HashForCodeObject(code), true); | 2051 HashMap::Entry* e = GetEntries()->Lookup(code, HashForCodeObject(code), true); |
| 1460 if (e->value != NULL && !IsLineInfoTagged(e->value)) return; | 2052 if (e->value != NULL && !IsLineInfoTagged(e->value)) return; |
| 1461 | 2053 |
| 1462 GDBJITLineInfo* lineinfo = UntagLineInfo(e->value); | 2054 GDBJITLineInfo* lineinfo = UntagLineInfo(e->value); |
| 1463 CodeDescription code_desc(name, | 2055 CodeDescription code_desc(name, |
| 1464 code, | 2056 code, |
| 1465 script != NULL ? Handle<Script>(script) | 2057 script != NULL ? Handle<Script>(script) |
| 1466 : Handle<Script>(), | 2058 : Handle<Script>(), |
| 1467 lineinfo, | 2059 lineinfo, |
| 1468 tag); | 2060 tag, |
| 2061 info); | |
| 1469 | 2062 |
| 1470 if (!FLAG_gdbjit_full && !code_desc.IsLineInfoAvailable()) { | 2063 if (!FLAG_gdbjit_full && !code_desc.IsLineInfoAvailable()) { |
| 1471 delete lineinfo; | 2064 delete lineinfo; |
| 1472 GetEntries()->Remove(code, HashForCodeObject(code)); | 2065 GetEntries()->Remove(code, HashForCodeObject(code)); |
| 1473 return; | 2066 return; |
| 1474 } | 2067 } |
| 1475 | 2068 |
| 1476 AddUnwindInfo(&code_desc); | 2069 AddUnwindInfo(&code_desc); |
| 1477 JITCodeEntry* entry = CreateELFObject(&code_desc); | 2070 JITCodeEntry* entry = CreateELFObject(&code_desc); |
| 1478 ASSERT(!IsLineInfoTagged(entry)); | 2071 ASSERT(!IsLineInfoTagged(entry)); |
| 1479 | 2072 |
| 1480 delete lineinfo; | 2073 delete lineinfo; |
| 1481 e->value = entry; | 2074 e->value = entry; |
| 1482 | 2075 |
| 1483 RegisterCodeEntry(entry); | 2076 const char* name_hint = NULL; |
| 2077 bool should_dump = false; | |
| 2078 if (FLAG_gdbjit_dump) { | |
| 2079 if (strlen(FLAG_gdbjit_dump_filter) == 0) { | |
| 2080 name_hint = name; | |
| 2081 should_dump = true; | |
| 2082 } else if (name != NULL) { | |
| 2083 name_hint = strstr(name, FLAG_gdbjit_dump_filter); | |
| 2084 should_dump = (name_hint != NULL); | |
| 2085 } | |
| 2086 } | |
| 2087 RegisterCodeEntry(entry, should_dump, name_hint); | |
| 1484 } | 2088 } |
| 1485 | 2089 |
| 1486 | 2090 |
| 1487 void GDBJITInterface::AddCode(GDBJITInterface::CodeTag tag, | 2091 void GDBJITInterface::AddCode(GDBJITInterface::CodeTag tag, |
| 1488 const char* name, | 2092 const char* name, |
| 1489 Code* code) { | 2093 Code* code) { |
| 1490 if (!FLAG_gdbjit) return; | 2094 if (!FLAG_gdbjit) return; |
| 1491 | 2095 |
| 1492 EmbeddedVector<char, 256> buffer; | 2096 EmbeddedVector<char, 256> buffer; |
| 1493 StringBuilder builder(buffer.start(), buffer.length()); | 2097 StringBuilder builder(buffer.start(), buffer.length()); |
| 1494 | 2098 |
| 1495 builder.AddString(Tag2String(tag)); | 2099 builder.AddString(Tag2String(tag)); |
| 1496 if ((name != NULL) && (*name != '\0')) { | 2100 if ((name != NULL) && (*name != '\0')) { |
| 1497 builder.AddString(": "); | 2101 builder.AddString(": "); |
| 1498 builder.AddString(name); | 2102 builder.AddString(name); |
| 1499 } else { | 2103 } else { |
| 1500 builder.AddFormatted(": code object %p", static_cast<void*>(code)); | 2104 builder.AddFormatted(": code object %p", static_cast<void*>(code)); |
| 1501 } | 2105 } |
| 1502 | 2106 |
| 1503 AddCode(builder.Finalize(), code, tag); | 2107 AddCode(builder.Finalize(), code, tag, NULL, NULL); |
| 1504 } | 2108 } |
| 1505 | 2109 |
| 1506 | 2110 |
| 1507 void GDBJITInterface::AddCode(GDBJITInterface::CodeTag tag, | 2111 void GDBJITInterface::AddCode(GDBJITInterface::CodeTag tag, |
| 1508 String* name, | 2112 String* name, |
| 1509 Code* code) { | 2113 Code* code) { |
| 1510 if (!FLAG_gdbjit) return; | 2114 if (!FLAG_gdbjit) return; |
| 1511 AddCode(tag, name != NULL ? *name->ToCString(DISALLOW_NULLS) : NULL, code); | 2115 AddCode(tag, name != NULL ? *name->ToCString(DISALLOW_NULLS) : NULL, code); |
| 1512 } | 2116 } |
| 1513 | 2117 |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1545 ScopedLock lock(mutex_); | 2149 ScopedLock lock(mutex_); |
| 1546 ASSERT(!IsLineInfoTagged(line_info)); | 2150 ASSERT(!IsLineInfoTagged(line_info)); |
| 1547 HashMap::Entry* e = GetEntries()->Lookup(code, HashForCodeObject(code), true); | 2151 HashMap::Entry* e = GetEntries()->Lookup(code, HashForCodeObject(code), true); |
| 1548 ASSERT(e->value == NULL); | 2152 ASSERT(e->value == NULL); |
| 1549 e->value = TagLineInfo(line_info); | 2153 e->value = TagLineInfo(line_info); |
| 1550 } | 2154 } |
| 1551 | 2155 |
| 1552 | 2156 |
| 1553 } } // namespace v8::internal | 2157 } } // namespace v8::internal |
| 1554 #endif | 2158 #endif |
| OLD | NEW |