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); |
} |