Chromium Code Reviews| Index: src/gdb-jit.cc |
| diff --git a/src/gdb-jit.cc b/src/gdb-jit.cc |
| index b4992a7f52680e0d766e6b8befa5ca31b6ec607b..32988d7833345e3e8747fa8792853e18370cdaa4 100644 |
| --- a/src/gdb-jit.cc |
| +++ b/src/gdb-jit.cc |
| @@ -34,16 +34,37 @@ |
| #include "global-handles.h" |
| #include "messages.h" |
| #include "natives.h" |
| +#include "scopeinfo.h" |
| + |
| +#ifdef __APPLE__ |
| +#define __MACH_O |
| +#define SECTION_BASE MachOSection |
| +#define OBJ_FORMAT MachO |
| +#else |
| +#define __ELF |
| +#define SECTION_BASE ELFSection |
| +#define OBJ_FORMAT ELF |
| +#endif |
|
Vyacheslav Egorov (Chromium)
2011/06/23 11:14:47
I don't think we are using macros for anything lik
zarko
2011/06/27 22:24:29
Done (though I have kept the __MACH_O/__ELF define
|
| namespace v8 { |
| namespace internal { |
| class ELF; |
| +class MachO; |
| class Writer BASE_EMBEDDED { |
| public: |
| explicit Writer(ELF* elf) |
| : elf_(elf), |
| + mach_o_(0), |
|
Vyacheslav Egorov (Chromium)
2011/06/23 11:14:47
Instead of duplicating code and members replace el
zarko
2011/06/27 22:24:29
Done.
|
| + position_(0), |
| + capacity_(1024), |
| + buffer_(reinterpret_cast<byte*>(malloc(capacity_))) { |
| + } |
| + |
| + explicit Writer(MachO* mach_o) |
| + : elf_(0), |
| + mach_o_(mach_o), |
| position_(0), |
| capacity_(1024), |
| buffer_(reinterpret_cast<byte*>(malloc(capacity_))) { |
| @@ -112,7 +133,9 @@ class Writer BASE_EMBEDDED { |
| } |
| } |
| - ELF* elf() { return elf_; } |
| + ELF* elf() { ASSERT(elf_ != 0); return elf_; } |
| + |
| + MachO* mach_o() { ASSERT(mach_o_ != 0); return mach_o_; } |
| byte* buffer() { return buffer_; } |
| @@ -166,6 +189,7 @@ class Writer BASE_EMBEDDED { |
| } |
| ELF* elf_; |
| + MachO* mach_o_; |
| uintptr_t position_; |
| uintptr_t capacity_; |
| byte* buffer_; |
| @@ -173,6 +197,91 @@ class Writer BASE_EMBEDDED { |
| class StringTable; |
| +class MachOSection : public ZoneObject { |
| + public: |
| + struct Header { |
| + char sectname[16]; |
| + char segname[16]; |
| +#if defined(V8_TARGET_ARCH_IA32) |
| + uint32_t addr; |
| + uint32_t size; |
| +#else |
| + uint64_t addr; |
| + uint64_t size; |
| +#endif |
| + uint32_t offset; |
| + uint32_t align; |
| + uint32_t reloff; |
| + uint32_t nreloc; |
| + uint32_t flags; |
| + uint32_t reserved1; |
| + uint32_t reserved2; |
| + }; |
| + |
| + enum Type { |
| + S_REGULAR = 0x0u, |
| + S_ATTR_COALESCED = 0xbu, |
| + S_ATTR_SOME_INSTRUCTIONS = 0x400u, |
| + S_ATTR_DEBUG = 0x02000000u, |
| + S_ATTR_PURE_INSTRUCTIONS = 0x80000000u |
| + }; |
| + |
| + MachOSection(const char* name, |
| + const char* segment, |
| + uintptr_t align, |
| + uint32_t flags) |
| + : name_(name), |
| + segment_(segment), |
| + align_(align), |
| + flags_(flags) { |
| + ASSERT(IsPowerOf2(align)); |
| + if (align_ != 0) { |
| + align_ = WhichPowerOf2(align_); |
| + } |
| + } |
| + |
| + virtual ~MachOSection() { } |
| + |
| + virtual void PopulateHeader(Writer::Slot<Header> header) { |
| + header->addr = 0; |
| + header->size = 0; |
| + header->offset = 0; |
| + header->align = align_; |
| + header->reloff = 0; |
| + header->nreloc = 0; |
| + header->flags = flags_; |
| + header->reserved1 = 0; |
| + header->reserved2 = 0; |
| + memset(header->sectname, 0, 16); |
| + memset(header->segname, 0, 16); |
| + ASSERT(strlen(name_) < 16); |
| + ASSERT(strlen(segment_) < 16); |
| + strcpy(header->sectname, name_); |
| + strcpy(header->segname, segment_); |
| + } |
| + |
| + virtual void WriteBody(Writer::Slot<Header> header, Writer* writer) { |
|
Vyacheslav Egorov (Chromium)
2011/06/23 11:14:47
Seems to be shared between ELFSection and MachOSec
zarko
2011/06/27 22:24:29
Done.
|
| + uintptr_t start = writer->position(); |
| + if (WriteBody(writer)) { |
| + uintptr_t end = writer->position(); |
| + header->offset = start; |
| + header->addr = 0; |
| + header->size = end - start; |
| + } |
| + } |
| + |
| + virtual bool WriteBody(Writer* writer) { |
|
Vyacheslav Egorov (Chromium)
2011/06/23 11:14:47
Ditto.
zarko
2011/06/27 22:24:29
Done.
|
| + return false; |
| + } |
| + |
| + private: |
| + const char* name_; |
| + const char* segment_; |
| + uintptr_t align_; |
| + uint32_t flags_; |
| +}; |
| + |
| + |
| class ELFSection : public ZoneObject { |
| public: |
| struct Header { |
| @@ -252,7 +361,6 @@ class ELFSection : public ZoneObject { |
| header->entry_size = 0; |
| } |
| - |
| private: |
| const char* name_; |
| Type type_; |
| @@ -261,6 +369,33 @@ class ELFSection : public ZoneObject { |
| }; |
| +class MachOTextSection : public MachOSection { |
| + public: |
| + MachOTextSection(uintptr_t align, |
| + uintptr_t addr, |
| + uintptr_t size) |
| + : MachOSection("__text", |
| + "__TEXT", |
| + align, |
| + MachOSection::S_REGULAR | |
| + MachOSection::S_ATTR_SOME_INSTRUCTIONS | |
| + MachOSection::S_ATTR_PURE_INSTRUCTIONS), |
| + addr_(addr), |
| + size_(size) { } |
| + |
| + protected: |
| + virtual void PopulateHeader(Writer::Slot<Header> header) { |
| + MachOSection::PopulateHeader(header); |
| + header->addr = addr_; |
| + header->size = size_; |
| + } |
| + |
| + private: |
| + uintptr_t addr_; |
| + uintptr_t size_; |
| +}; |
| + |
| + |
| class FullHeaderELFSection : public ELFSection { |
| public: |
| FullHeaderELFSection(const char* name, |
| @@ -351,6 +486,113 @@ void ELFSection::PopulateHeader(Writer::Slot<ELFSection::Header> header, |
| } |
| +class MachO BASE_EMBEDDED { |
| + public: |
| + MachO() : sections_(6) { } |
| + |
| + uint32_t AddSection(MachOSection* section) { |
| + sections_.Add(section); |
| + return sections_.length() - 1; |
| + } |
| + |
| + void Write(Writer* w, uintptr_t code_start, uintptr_t code_size); |
| + |
| + private: |
| + struct MachOHeader { |
| + uint32_t magic; |
| + uint32_t cputype; |
| + uint32_t cpusubtype; |
| + uint32_t filetype; |
| + uint32_t ncmds; |
| + uint32_t sizeofcmds; |
| + uint32_t flags; |
| +#if defined(V8_TARGET_ARCH_X64) |
| + uint32_t reserved; |
| +#endif |
| + }; |
| + |
| + struct MachOSegmentCommand { |
| + uint32_t cmd; |
| + uint32_t cmdsize; |
| + char segname[16]; |
| +#if defined(V8_TARGET_ARCH_IA32) |
| + uint32_t vmaddr; |
| + uint32_t vmsize; |
| + uint32_t fileoff; |
| + uint32_t filesize; |
| +#else |
| + uint64_t vmaddr; |
| + uint64_t vmsize; |
| + uint64_t fileoff; |
| + uint64_t filesize; |
| +#endif |
| + uint32_t maxprot; |
| + uint32_t initprot; |
| + uint32_t nsects; |
| + uint32_t flags; |
| + }; |
| + |
| + enum MachOLoadCommandCmd { |
| + LC_SEGMENT_32 = 0x00000001u, |
| + LC_SEGMENT_64 = 0x00000019u |
| + }; |
| + |
| + ZoneList<MachOSection*> sections_; |
| +}; |
| + |
| + |
| +void MachO::Write(Writer* w, |
| + uintptr_t code_start, |
| + uintptr_t code_size) { |
| + ASSERT(w->position() == 0); |
|
Vyacheslav Egorov (Chromium)
2011/06/23 11:14:47
Can you split this method into several like it is
zarko
2011/06/27 22:24:29
Done.
|
| + Writer::Slot<MachOHeader> header = w->CreateSlotHere<MachOHeader>(); |
| +#if defined(V8_TARGET_ARCH_IA32) |
| + header->magic = 0xFEEDFACEu; |
| + header->cputype = 7; // i386 |
| + header->cpusubtype = 3; // CPU_SUBTYPE_I386_ALL |
| +#elif defined(V8_TARGET_ARCH_X64) |
| + header->magic = 0xFEEDFACFu; |
| + header->cputype = 7 | 0x01000000; // i386 | 64-bit ABI |
| + header->cpusubtype = 3; // CPU_SUBTYPE_I386_ALL |
| + header->reserved = 0; |
| +#else |
| +#error Unsupported target architecture. |
| +#endif |
| + header->filetype = 0x1; // MH_OBJECT |
| + header->ncmds = 1; |
| + header->sizeofcmds = 0; |
| + header->flags = 0; |
| + uintptr_t load_command_start = w->position(); |
| + Writer::Slot<MachOSegmentCommand> cmd = |
| + w->CreateSlotHere<MachOSegmentCommand>(); |
| +#if defined(V8_TARGET_ARCH_IA32) |
| + cmd->cmd = LC_SEGMENT_32; |
| +#else |
| + cmd->cmd = LC_SEGMENT_64; |
| +#endif |
| + cmd->vmaddr = code_start; |
| + cmd->vmsize = code_size; |
| + cmd->fileoff = 0; |
| + cmd->filesize = 0; |
| + cmd->maxprot = 7; |
| + cmd->initprot = 7; |
| + cmd->flags = 0; |
| + cmd->nsects = sections_.length(); |
| + memset(cmd->segname, 0, 16); |
| + cmd->cmdsize = sizeof(MachOSegmentCommand) + sizeof(MachOSection::Header) * |
| + cmd->nsects; |
| + Writer::Slot<MachOSection::Header> headers = |
| + w->CreateSlotsHere<MachOSection::Header>(sections_.length()); |
| + cmd->fileoff = w->position(); |
| + header->sizeofcmds = w->position() - load_command_start; |
| + for (int section = 0; section < sections_.length(); ++section) { |
| + sections_[section]->PopulateHeader(headers.at(section)); |
| + sections_[section]->WriteBody(headers.at(section), w); |
| + } |
| + cmd->filesize = w->position() - (uintptr_t)cmd->fileoff; |
| +} |
| + |
| + |
| class ELF BASE_EMBEDDED { |
| public: |
| ELF() : sections_(6) { |
| @@ -657,12 +899,14 @@ class CodeDescription BASE_EMBEDDED { |
| Code* code, |
| Handle<Script> script, |
| GDBJITLineInfo* lineinfo, |
| - GDBJITInterface::CodeTag tag) |
| + GDBJITInterface::CodeTag tag, |
| + CompilationInfo* info) |
| : name_(name), |
| code_(code), |
| script_(script), |
| lineinfo_(lineinfo), |
| - tag_(tag) { |
| + tag_(tag), |
| + info_(info) { |
| } |
| const char* name() const { |
| @@ -677,6 +921,14 @@ class CodeDescription BASE_EMBEDDED { |
| return tag_; |
| } |
| + CompilationInfo* info() const { |
| + return info_; |
| + } |
| + |
| + bool IsInfoAvailable() const { |
| + return info_ != NULL; |
| + } |
| + |
| uintptr_t CodeStart() const { |
| return reinterpret_cast<uintptr_t>(code_->instruction_start()); |
| } |
| @@ -724,12 +976,13 @@ class CodeDescription BASE_EMBEDDED { |
| Handle<Script> script_; |
| GDBJITLineInfo* lineinfo_; |
| GDBJITInterface::CodeTag tag_; |
| + CompilationInfo* info_; |
| #ifdef V8_TARGET_ARCH_X64 |
| uintptr_t stack_state_start_addresses_[STACK_STATE_MAX]; |
| #endif |
| }; |
| - |
| +#ifdef __ELF |
| static void CreateSymbolsTable(CodeDescription* desc, |
| ELF* elf, |
| int text_section_index) { |
| @@ -754,14 +1007,40 @@ static void CreateSymbolsTable(CodeDescription* desc, |
| ELFSymbol::TYPE_FUNC, |
| text_section_index)); |
| } |
| +#endif |
| -class DebugInfoSection : public ELFSection { |
| +class DebugInfoSection : public SECTION_BASE { |
| public: |
| explicit DebugInfoSection(CodeDescription* desc) |
| - : ELFSection(".debug_info", TYPE_PROGBITS, 1), desc_(desc) { } |
| +#ifdef __ELF |
| + : ELFSection(".debug_info", TYPE_PROGBITS, 1), |
| +#else |
| + : MachOSection("__debug_info", "__DWARF", 1, |
|
Vyacheslav Egorov (Chromium)
2011/06/23 11:14:47
one argument per line.
zarko
2011/06/27 22:24:29
Done.
|
| + MachOSection::S_REGULAR | MachOSection::S_ATTR_DEBUG), |
| +#endif |
| + desc_(desc) { } |
| + |
| + // DWARF2 standard |
| + enum DWARF2LocationOp { |
| + DW_OP_reg0 = 0x50, |
| + DW_OP_reg1 = 0x51, |
| + DW_OP_reg2 = 0x52, |
| + DW_OP_reg3 = 0x53, |
| + DW_OP_reg4 = 0x54, |
| + DW_OP_reg5 = 0x55, |
| + DW_OP_reg6 = 0x56, |
| + DW_OP_reg7 = 0x57, |
| + DW_OP_fbreg = 0x91 // 1 param: SLEB128 offset |
| + }; |
| + |
| + enum DWARF2Encoding { |
| + DW_ATE_ADDRESS = 0x1, |
| + DW_ATE_SIGNED = 0x5 |
| + }; |
| bool WriteBody(Writer* w) { |
| + uintptr_t cu_start = w->position(); |
| Writer::Slot<uint32_t> size = w->CreateSlotHere<uint32_t>(); |
| uintptr_t start = w->position(); |
| w->Write<uint16_t>(2); // DWARF version. |
| @@ -773,6 +1052,125 @@ class DebugInfoSection : public ELFSection { |
| w->Write<intptr_t>(desc_->CodeStart()); |
| w->Write<intptr_t>(desc_->CodeStart() + desc_->CodeSize()); |
| w->Write<uint32_t>(0); |
| + |
| + uint32_t ty_offset = static_cast<uint32_t>(w->position() - cu_start); |
| + w->WriteULEB128(3); |
| + w->Write<uint8_t>(kPointerSize); |
| + w->WriteString("v8value"); |
| + |
| + if (desc_->IsInfoAvailable()) { |
| + CompilationInfo* info = desc_->info(); |
| + ScopeInfo<FreeStoreAllocationPolicy> scope_info(info->scope()); |
| + w->WriteULEB128(2); |
| + w->WriteString(desc_->name()); |
| + w->Write<intptr_t>(desc_->CodeStart()); |
| + w->Write<intptr_t>(desc_->CodeStart() + desc_->CodeSize()); |
| + Writer::Slot<uint32_t> fb_block_size = w->CreateSlotHere<uint32_t>(); |
| + uintptr_t fb_block_start = w->position(); |
| +#if defined(V8_TARGET_ARCH_IA32) |
| + w->Write<uint8_t>(DW_OP_reg5); // The frame pointer's here on ia32 |
| +#elif defined(V8_TARGET_ARCH_X64) |
| + w->Write<uint8_t>(DW_OP_reg6); // and here on x64. |
| +#else |
| +#error Unsupported target architecture. |
| +#endif |
| + fb_block_size.set(static_cast<uint32_t>(w->position() - fb_block_start)); |
| + |
| + int params = scope_info.number_of_parameters(); |
| + int slots = scope_info.number_of_stack_slots(); |
| + int context_slots = scope_info.number_of_context_slots(); |
| + // The real slot ID is internal_slots + context_slot_id. |
| + int internal_slots = Context::MIN_CONTEXT_SLOTS; |
| + int locals = scope_info.NumberOfLocals(); |
| + int current_abbreviation = 4; |
| + |
| + for (int param = 0; param < params; ++param) { |
| + w->WriteULEB128(current_abbreviation++); |
| + w->WriteString( |
| + *scope_info.parameter_name(param)->ToCString(DISALLOW_NULLS)); |
| + w->Write<uint32_t>(ty_offset); |
| + Writer::Slot<uint32_t> block_size = w->CreateSlotHere<uint32_t>(); |
| + uintptr_t block_start = w->position(); |
| + w->Write<uint8_t>(DW_OP_fbreg); |
| + w->WriteSLEB128( |
| + JavaScriptFrameConstants::kLastParameterOffset + |
| + kPointerSize * (params - param - 1)); |
| + block_size.set(static_cast<uint32_t>(w->position() - block_start)); |
| + } |
| + |
| + EmbeddedVector<char, 256> buffer; |
| + StringBuilder builder(buffer.start(), buffer.length()); |
| + |
| + for (int slot = 0; slot < slots; ++slot) { |
| + w->WriteULEB128(current_abbreviation++); |
| + builder.Reset(); |
| + builder.AddFormatted("slot%d", slot); |
| + w->WriteString(builder.Finalize()); |
| + } |
| + |
| + // See contexts.h for more information. |
| + ASSERT(Context::MIN_CONTEXT_SLOTS == 5); |
| + ASSERT(Context::CLOSURE_INDEX == 0); |
| + ASSERT(Context::FCONTEXT_INDEX == 1); |
| + ASSERT(Context::PREVIOUS_INDEX == 2); |
| + ASSERT(Context::EXTENSION_INDEX == 3); |
| + ASSERT(Context::GLOBAL_INDEX == 4); |
| + w->WriteULEB128(current_abbreviation++); |
| + w->WriteString(".closure"); |
| + w->WriteULEB128(current_abbreviation++); |
| + w->WriteString(".fcontext"); |
| + w->WriteULEB128(current_abbreviation++); |
| + w->WriteString(".previous"); |
| + w->WriteULEB128(current_abbreviation++); |
| + w->WriteString(".extension"); |
| + w->WriteULEB128(current_abbreviation++); |
| + w->WriteString(".global"); |
| + |
| + for (int context_slot = 0; context_slot < context_slots; |
|
Vyacheslav Egorov (Chromium)
2011/06/23 11:14:47
for(x;
y;
z)
zarko
2011/06/27 22:24:29
Done.
|
| + ++context_slot) { |
| + w->WriteULEB128(current_abbreviation++); |
| + builder.Reset(); |
| + builder.AddFormatted("context_slot%d", context_slot + internal_slots); |
| + w->WriteString(builder.Finalize()); |
| + } |
| + |
| + for (int local = 0; local < locals; ++local) { |
| + w->WriteULEB128(current_abbreviation++); |
| + w->WriteString( |
| + *scope_info.LocalName(local)->ToCString(DISALLOW_NULLS)); |
| + w->Write<uint32_t>(ty_offset); |
| + Writer::Slot<uint32_t> block_size = w->CreateSlotHere<uint32_t>(); |
| + uintptr_t block_start = w->position(); |
| + w->Write<uint8_t>(DW_OP_fbreg); |
| + w->WriteSLEB128( |
| + JavaScriptFrameConstants::kLocal0Offset - |
| + kPointerSize * local); |
| + block_size.set(static_cast<uint32_t>(w->position() - block_start)); |
| + } |
| + |
| + { |
| + w->WriteULEB128(current_abbreviation++); |
| + w->WriteString("__function"); |
| + w->Write<uint32_t>(ty_offset); |
| + Writer::Slot<uint32_t> block_size = w->CreateSlotHere<uint32_t>(); |
| + uintptr_t block_start = w->position(); |
| + w->Write<uint8_t>(DW_OP_fbreg); |
| + w->WriteSLEB128(JavaScriptFrameConstants::kFunctionOffset); |
| + block_size.set(static_cast<uint32_t>(w->position() - block_start)); |
| + } |
| + |
| + { |
| + w->WriteULEB128(current_abbreviation++); |
| + w->WriteString("__context"); |
| + w->Write<uint32_t>(ty_offset); |
| + Writer::Slot<uint32_t> block_size = w->CreateSlotHere<uint32_t>(); |
| + uintptr_t block_start = w->position(); |
| + w->Write<uint8_t>(DW_OP_fbreg); |
| + w->WriteSLEB128(StandardFrameConstants::kContextOffset); |
| + block_size.set(static_cast<uint32_t>(w->position() - block_start)); |
| + } |
| + } |
| + |
| size.set(static_cast<uint32_t>(w->position() - start)); |
| return true; |
| } |
| @@ -782,13 +1180,26 @@ class DebugInfoSection : public ELFSection { |
| }; |
| -class DebugAbbrevSection : public ELFSection { |
| +class DebugAbbrevSection : public SECTION_BASE { |
| public: |
| - DebugAbbrevSection() : ELFSection(".debug_abbrev", TYPE_PROGBITS, 1) { } |
| + explicit DebugAbbrevSection(CodeDescription* desc) |
| +#ifdef __ELF |
| + : ELFSection(".debug_abbrev", TYPE_PROGBITS, 1), |
| +#else |
| + : MachOSection("__debug_abbrev", "__DWARF", 1, |
|
Vyacheslav Egorov (Chromium)
2011/06/23 11:14:47
Argument per line
zarko
2011/06/27 22:24:29
Done.
|
| + MachOSection::S_REGULAR | MachOSection::S_ATTR_DEBUG), |
| +#endif |
| + desc_(desc) { } |
| // DWARF2 standard, figure 14. |
| enum DWARF2Tags { |
| - DW_TAG_COMPILE_UNIT = 0x11 |
| + DW_TAG_FORMAL_PARAMETER = 0x05, |
| + DW_TAG_POINTER_TYPE = 0xf, |
| + DW_TAG_COMPILE_UNIT = 0x11, |
| + DW_TAG_STRUCTURE_TYPE = 0x13, |
| + DW_TAG_BASE_TYPE = 0x24, |
| + DW_TAG_SUBPROGRAM = 0x2e, |
| + DW_TAG_VARIABLE = 0x34 |
| }; |
| // DWARF2 standard, figure 16. |
| @@ -799,23 +1210,35 @@ class DebugAbbrevSection : public ELFSection { |
| // DWARF standard, figure 17. |
| enum DWARF2Attribute { |
| + DW_AT_LOCATION = 0x2, |
| DW_AT_NAME = 0x3, |
| + DW_AT_BYTE_SIZE = 0xb, |
| DW_AT_STMT_LIST = 0x10, |
| DW_AT_LOW_PC = 0x11, |
| - DW_AT_HIGH_PC = 0x12 |
| + DW_AT_HIGH_PC = 0x12, |
| + DW_AT_ENCODING = 0x3e, |
| + DW_AT_FRAME_BASE = 0x40, |
| + DW_AT_TYPE = 0x49 |
| }; |
| // DWARF2 standard, figure 19. |
| enum DWARF2AttributeForm { |
| DW_FORM_ADDR = 0x1, |
| + DW_FORM_BLOCK4 = 0x4, |
| DW_FORM_STRING = 0x8, |
| - DW_FORM_DATA4 = 0x6 |
| + DW_FORM_DATA4 = 0x6, |
| + DW_FORM_BLOCK = 0x9, |
| + DW_FORM_DATA1 = 0xb, |
| + DW_FORM_FLAG = 0xc, |
| + DW_FORM_REF4 = 0x13 |
| }; |
| bool WriteBody(Writer* w) { |
| + bool extra_info = desc_->IsInfoAvailable(); |
| + ASSERT(desc_->IsLineInfoAvailable()); |
| w->WriteULEB128(1); |
| w->WriteULEB128(DW_TAG_COMPILE_UNIT); |
| - w->Write<uint8_t>(DW_CHILDREN_NO); |
| + w->Write<uint8_t>(extra_info ? DW_CHILDREN_YES : DW_CHILDREN_NO); |
| w->WriteULEB128(DW_AT_NAME); |
| w->WriteULEB128(DW_FORM_STRING); |
| w->WriteULEB128(DW_AT_LOW_PC); |
| @@ -826,16 +1249,157 @@ class DebugAbbrevSection : public ELFSection { |
| w->WriteULEB128(DW_FORM_DATA4); |
| w->WriteULEB128(0); |
| w->WriteULEB128(0); |
| - w->WriteULEB128(0); |
| + |
| + if (extra_info) { |
| + CompilationInfo* info = desc_->info(); |
| + ScopeInfo<FreeStoreAllocationPolicy> scope_info(info->scope()); |
| + int params = scope_info.number_of_parameters(); |
| + int slots = scope_info.number_of_stack_slots(); |
| + int context_slots = scope_info.number_of_context_slots(); |
| + // The real slot ID is internal_slots + context_slot_id. |
| + int internal_slots = Context::MIN_CONTEXT_SLOTS; |
| + int locals = scope_info.NumberOfLocals(); |
| + int total_children = |
| + params + slots + context_slots + internal_slots + locals + 2; |
| + |
| + // The extra duplication below seems to be necessary to keep |
| + // gdb from getting upset on OSX. |
| + |
| + w->WriteULEB128(2); // Abbreviation code. |
| + w->WriteULEB128(DW_TAG_SUBPROGRAM); |
| + w->Write<uint8_t>( |
| + total_children != 0 ? DW_CHILDREN_YES : DW_CHILDREN_NO); |
| + w->WriteULEB128(DW_AT_NAME); |
| + w->WriteULEB128(DW_FORM_STRING); |
| + w->WriteULEB128(DW_AT_LOW_PC); |
| + w->WriteULEB128(DW_FORM_ADDR); |
| + w->WriteULEB128(DW_AT_HIGH_PC); |
| + w->WriteULEB128(DW_FORM_ADDR); |
| + w->WriteULEB128(DW_AT_FRAME_BASE); |
| + w->WriteULEB128(DW_FORM_BLOCK4); |
| + w->WriteULEB128(0); |
| + w->WriteULEB128(0); |
| + |
| + w->WriteULEB128(3); |
| + w->WriteULEB128(DW_TAG_STRUCTURE_TYPE); |
| + w->Write<uint8_t>(DW_CHILDREN_NO); |
| + w->WriteULEB128(DW_AT_BYTE_SIZE); |
| + w->WriteULEB128(DW_FORM_DATA1); |
| + w->WriteULEB128(DW_AT_NAME); |
| + w->WriteULEB128(DW_FORM_STRING); |
| + w->WriteULEB128(0); |
| + w->WriteULEB128(0); |
| + |
| + int current_abbreviation = 4; |
|
Vyacheslav Egorov (Chromium)
2011/06/23 11:28:37
Move it to the beginning of the function and use i
zarko
2011/06/27 22:24:29
Done.
|
| + for (int param = 0; param < params; ++param) { |
| + w->WriteULEB128(current_abbreviation++); |
| + w->WriteULEB128(DW_TAG_FORMAL_PARAMETER); |
| + w->Write<uint8_t>(DW_CHILDREN_NO); |
| + w->WriteULEB128(DW_AT_NAME); |
| + w->WriteULEB128(DW_FORM_STRING); |
| + w->WriteULEB128(DW_AT_TYPE); |
| + w->WriteULEB128(DW_FORM_REF4); |
| + w->WriteULEB128(DW_AT_LOCATION); |
| + w->WriteULEB128(DW_FORM_BLOCK4); |
| + w->WriteULEB128(0); |
| + w->WriteULEB128(0); |
| + } |
| + |
| + for (int slot = 0; slot < slots; ++slot) { |
| + w->WriteULEB128(current_abbreviation++); |
| + w->WriteULEB128(DW_TAG_VARIABLE); |
| + w->Write<uint8_t>(DW_CHILDREN_NO); |
| + w->WriteULEB128(DW_AT_NAME); |
| + w->WriteULEB128(DW_FORM_STRING); |
| + w->WriteULEB128(0); |
| + w->WriteULEB128(0); |
| + } |
| + |
| + for (int context_slot = 0; context_slot < context_slots; |
|
Vyacheslav Egorov (Chromium)
2011/06/23 11:28:37
for(x;
y;
z)
zarko
2011/06/27 22:24:29
Done.
|
| + ++context_slot) { |
| + w->WriteULEB128(current_abbreviation++); |
|
Vyacheslav Egorov (Chromium)
2011/06/23 11:28:37
Seems to be duplicated. Extract to a method?
|
| + w->WriteULEB128(DW_TAG_VARIABLE); |
| + w->Write<uint8_t>(DW_CHILDREN_NO); |
| + w->WriteULEB128(DW_AT_NAME); |
| + w->WriteULEB128(DW_FORM_STRING); |
| + w->WriteULEB128(0); |
| + w->WriteULEB128(0); |
| + } |
| + |
| + for (int internal_slot = 0; internal_slot < internal_slots; |
|
Vyacheslav Egorov (Chromium)
2011/06/23 11:28:37
for(x;
y;
z)
zarko
2011/06/27 22:24:29
Done.
|
| + ++internal_slot) { |
| + w->WriteULEB128(current_abbreviation++); |
|
Vyacheslav Egorov (Chromium)
2011/06/23 11:28:37
Seems to be duplicated. Extract to a method?
Mayb
|
| + w->WriteULEB128(DW_TAG_VARIABLE); |
| + w->Write<uint8_t>(DW_CHILDREN_NO); |
| + w->WriteULEB128(DW_AT_NAME); |
| + w->WriteULEB128(DW_FORM_STRING); |
| + w->WriteULEB128(0); |
| + w->WriteULEB128(0); |
| + } |
| + |
| + for (int local = 0; local < locals; ++local) { |
| + w->WriteULEB128(current_abbreviation++); |
|
Vyacheslav Egorov (Chromium)
2011/06/23 11:28:37
Partially duplicated. If possible try to unify wit
|
| + w->WriteULEB128(DW_TAG_VARIABLE); |
| + w->Write<uint8_t>(DW_CHILDREN_NO); |
| + w->WriteULEB128(DW_AT_NAME); |
| + w->WriteULEB128(DW_FORM_STRING); |
| + w->WriteULEB128(DW_AT_TYPE); |
| + w->WriteULEB128(DW_FORM_REF4); |
| + w->WriteULEB128(DW_AT_LOCATION); |
| + w->WriteULEB128(DW_FORM_BLOCK4); |
| + w->WriteULEB128(0); |
| + w->WriteULEB128(0); |
| + } |
| + |
| + // The function. |
| + w->WriteULEB128(current_abbreviation++); |
| + w->WriteULEB128(DW_TAG_VARIABLE); |
| + w->Write<uint8_t>(DW_CHILDREN_NO); |
| + w->WriteULEB128(DW_AT_NAME); |
| + w->WriteULEB128(DW_FORM_STRING); |
| + w->WriteULEB128(DW_AT_TYPE); |
| + w->WriteULEB128(DW_FORM_REF4); |
| + w->WriteULEB128(DW_AT_LOCATION); |
| + w->WriteULEB128(DW_FORM_BLOCK4); |
| + w->WriteULEB128(0); |
| + w->WriteULEB128(0); |
| + |
| + // The context. |
| + w->WriteULEB128(current_abbreviation++); |
|
Vyacheslav Egorov (Chromium)
2011/06/23 11:28:37
Duplicated?
|
| + w->WriteULEB128(DW_TAG_VARIABLE); |
| + w->Write<uint8_t>(DW_CHILDREN_NO); |
| + w->WriteULEB128(DW_AT_NAME); |
| + w->WriteULEB128(DW_FORM_STRING); |
| + w->WriteULEB128(DW_AT_TYPE); |
| + w->WriteULEB128(DW_FORM_REF4); |
| + w->WriteULEB128(DW_AT_LOCATION); |
| + w->WriteULEB128(DW_FORM_BLOCK4); |
| + w->WriteULEB128(0); |
| + w->WriteULEB128(0); |
| + |
| + if (total_children != 0) { |
| + w->WriteULEB128(0); // Terminate the sibling list. |
| + } |
| + } |
| + |
| + w->WriteULEB128(0); // Terminate the table. |
| return true; |
| } |
| + |
| + private: |
| + CodeDescription* desc_; |
| }; |
| -class DebugLineSection : public ELFSection { |
| +class DebugLineSection : public SECTION_BASE { |
| public: |
| explicit DebugLineSection(CodeDescription* desc) |
| +#ifdef __ELF |
| : ELFSection(".debug_line", TYPE_PROGBITS, 1), |
| +#else |
| + : MachOSection("__debug_line", "__DWARF", 1, |
| + MachOSection::S_REGULAR | MachOSection::S_ATTR_DEBUG), |
| +#endif |
| desc_(desc) { } |
| // DWARF2 standard, figure 34. |
| @@ -992,8 +1556,7 @@ class DebugLineSection : public ELFSection { |
| #ifdef V8_TARGET_ARCH_X64 |
| - |
| -class UnwindInfoSection : public ELFSection { |
| +class UnwindInfoSection : public SECTION_BASE { |
| public: |
| explicit UnwindInfoSection(CodeDescription *desc); |
| virtual bool WriteBody(Writer *w); |
| @@ -1079,8 +1642,13 @@ void UnwindInfoSection::WriteLength(Writer *w, |
| UnwindInfoSection::UnwindInfoSection(CodeDescription *desc) |
| - : ELFSection(".eh_frame", TYPE_X86_64_UNWIND, 1), desc_(desc) |
| -{ } |
| +#ifdef __ELF |
| + : ELFSection(".eh_frame", TYPE_X86_64_UNWIND, 1), |
| +#else |
| + : MachOSection("__eh_frame", "__TEXT", sizeof(uintptr_t), |
| + MachOSection::S_REGULAR), |
| +#endif |
| + desc_(desc) { } |
| int UnwindInfoSection::WriteCIE(Writer *w) { |
| Writer::Slot<uint32_t> cie_length_slot = w->CreateSlotHere<uint32_t>(); |
| @@ -1212,15 +1780,14 @@ bool UnwindInfoSection::WriteBody(Writer *w) { |
| #endif // V8_TARGET_ARCH_X64 |
| - |
| -static void CreateDWARFSections(CodeDescription* desc, ELF* elf) { |
| +static void CreateDWARFSections(CodeDescription* desc, OBJ_FORMAT* obj) { |
| if (desc->IsLineInfoAvailable()) { |
| - elf->AddSection(new DebugInfoSection(desc)); |
| - elf->AddSection(new DebugAbbrevSection); |
| - elf->AddSection(new DebugLineSection(desc)); |
| + obj->AddSection(new DebugInfoSection(desc)); |
| + obj->AddSection(new DebugAbbrevSection(desc)); |
| + obj->AddSection(new DebugLineSection(desc)); |
| } |
| #ifdef V8_TARGET_ARCH_X64 |
| - elf->AddSection(new UnwindInfoSection(desc)); |
| + obj->AddSection(new UnwindInfoSection(desc)); |
| #endif |
| } |
| @@ -1260,6 +1827,13 @@ extern "C" { |
| // Static initialization is necessary to prevent GDB from seeing |
| // uninitialized descriptor. |
| JITDescriptor __jit_debug_descriptor = { 1, 0, 0, 0 }; |
| + |
| +#ifdef OBJECT_PRINT |
| + void __gdb_print_v8_object(MaybeObject* object) { |
|
Vyacheslav Egorov (Chromium)
2011/06/23 11:14:47
Frankly speaking I don't see any reason to add thi
zarko
2011/06/27 22:24:29
gdb was having some trouble finding the symbol for
|
| + object->Print(); |
| + fprintf(stdout, "\n"); |
| + } |
| +#endif |
| } |
| @@ -1283,17 +1857,20 @@ static void DestroyCodeEntry(JITCodeEntry* entry) { |
| } |
| -static void RegisterCodeEntry(JITCodeEntry* entry) { |
| +static void RegisterCodeEntry(JITCodeEntry* entry, |
| + bool dump_if_enabled, |
|
Vyacheslav Egorov (Chromium)
2011/06/23 11:14:47
something with indentation.
zarko
2011/06/27 22:24:29
Done.
|
| + const char* name_hint) { |
| #if defined(DEBUG) && !defined(WIN32) |
| static int file_num = 0; |
| - if (FLAG_gdbjit_dump) { |
| + if (FLAG_gdbjit_dump && dump_if_enabled) { |
| static const int kMaxFileNameSize = 64; |
| static const char* kElfFilePrefix = "/tmp/elfdump"; |
| static const char* kObjFileExt = ".o"; |
| char file_name[64]; |
| - OS::SNPrintF(Vector<char>(file_name, kMaxFileNameSize), "%s%d%s", |
| - kElfFilePrefix, file_num++, kObjFileExt); |
| + OS::SNPrintF(Vector<char>(file_name, kMaxFileNameSize), "%s%s%d%s", |
|
Vyacheslav Egorov (Chromium)
2011/06/23 11:14:47
One argument per line.
(somehow I missed this pla
zarko
2011/06/27 22:24:29
Done.
|
| + kElfFilePrefix, (name_hint != NULL) ? name_hint : "", |
| + file_num++, kObjFileExt); |
| WriteBytes(file_name, entry->symfile_addr_, entry->symfile_size_); |
| } |
| #endif |
| @@ -1327,7 +1904,18 @@ static void UnregisterCodeEntry(JITCodeEntry* entry) { |
| static JITCodeEntry* CreateELFObject(CodeDescription* desc) { |
| ZoneScope zone_scope(Isolate::Current(), DELETE_ON_EXIT); |
| +#ifdef __MACH_O |
| + MachO mach_o; |
| + Writer w(&mach_o); |
| + |
| + mach_o.AddSection(new MachOTextSection(kCodeAlignment, |
| + desc->CodeStart(), |
| + desc->CodeSize())); |
| + |
| + CreateDWARFSections(desc, &mach_o); |
| + mach_o.Write(&w, desc->CodeStart(), desc->CodeSize()); |
| +#else |
| ELF elf; |
| Writer w(&elf); |
| @@ -1345,6 +1933,7 @@ static JITCodeEntry* CreateELFObject(CodeDescription* desc) { |
| CreateDWARFSections(desc, &elf); |
| elf.Write(&w); |
| +#endif |
| return CreateCodeEntry(w.buffer(), w.position()); |
| } |
| @@ -1393,7 +1982,8 @@ static GDBJITLineInfo* UntagLineInfo(void* ptr) { |
| void GDBJITInterface::AddCode(Handle<String> name, |
| Handle<Script> script, |
| - Handle<Code> code) { |
| + Handle<Code> code, |
| + CompilationInfo* info) { |
| if (!FLAG_gdbjit) return; |
| // Force initialization of line_ends array. |
| @@ -1401,9 +1991,9 @@ void GDBJITInterface::AddCode(Handle<String> name, |
| if (!name.is_null()) { |
| SmartPointer<char> name_cstring = name->ToCString(DISALLOW_NULLS); |
| - AddCode(*name_cstring, *code, GDBJITInterface::FUNCTION, *script); |
| + AddCode(*name_cstring, *code, GDBJITInterface::FUNCTION, *script, info); |
| } else { |
| - AddCode("", *code, GDBJITInterface::FUNCTION, *script); |
| + AddCode("", *code, GDBJITInterface::FUNCTION, *script, info); |
| } |
| } |
| @@ -1450,7 +2040,8 @@ Mutex* GDBJITInterface::mutex_ = OS::CreateMutex(); |
| void GDBJITInterface::AddCode(const char* name, |
| Code* code, |
| GDBJITInterface::CodeTag tag, |
| - Script* script) { |
| + Script* script, |
| + CompilationInfo* info) { |
| if (!FLAG_gdbjit) return; |
| ScopedLock lock(mutex_); |
| @@ -1465,7 +2056,8 @@ void GDBJITInterface::AddCode(const char* name, |
| script != NULL ? Handle<Script>(script) |
| : Handle<Script>(), |
| lineinfo, |
| - tag); |
| + tag, |
| + info); |
| if (!FLAG_gdbjit_full && !code_desc.IsLineInfoAvailable()) { |
| delete lineinfo; |
| @@ -1480,7 +2072,18 @@ void GDBJITInterface::AddCode(const char* name, |
| delete lineinfo; |
| e->value = entry; |
| - RegisterCodeEntry(entry); |
| + const char* name_hint = NULL; |
| + bool should_dump = false; |
| + if (FLAG_gdbjit_dump) { |
| + if (strlen(FLAG_gdbjit_dump_filter) == 0) { |
| + name_hint = name; |
| + should_dump = true; |
| + } else if (name != NULL) { |
| + name_hint = strstr(name, FLAG_gdbjit_dump_filter); |
| + should_dump = (name_hint != NULL); |
| + } |
| + } |
| + RegisterCodeEntry(entry, should_dump, name_hint); |
| } |