5 #include "src/gdb-jit.h" 10 #include "src/api-inl.h" 11 #include "src/base/bits.h" 12 #include "src/base/platform/platform.h" 13 #include "src/bootstrapper.h" 14 #include "src/frames-inl.h" 15 #include "src/frames.h" 16 #include "src/global-handles.h" 17 #include "src/objects.h" 18 #include "src/ostreams.h" 19 #include "src/snapshot/natives.h" 20 #include "src/splay-tree-inl.h" 21 #include "src/zone/zone-chunk-list.h" 25 namespace GDBJITInterface {
27 #ifdef ENABLE_GDB_JIT_INTERFACE 33 typedef MachO DebugObject;
34 typedef MachOSection DebugSection;
39 typedef ELF DebugObject;
40 typedef ELFSection DebugSection;
45 explicit Writer(DebugObject* debug_object)
46 : debug_object_(debug_object),
49 buffer_(reinterpret_cast<byte*>(malloc(capacity_))) {
63 Slot(Writer* w,
uintptr_t offset) : w_(w), offset_(offset) { }
66 return w_->RawSlotAt<T>(offset_);
69 void set(
const T& value) {
70 *w_->RawSlotAt<T>(offset_) = value;
74 return Slot<T>(w_, offset_ +
sizeof(T) *
i);
83 void Write(
const T& val) {
84 Ensure(position_ +
sizeof(T));
85 *RawSlotAt<T>(position_) = val;
86 position_ +=
sizeof(T);
91 Ensure(offset +
sizeof(T));
92 return Slot<T>(
this, offset);
96 Slot<T> CreateSlotHere() {
97 return CreateSlotsHere<T>(1);
101 Slot<T> CreateSlotsHere(
uint32_t count) {
103 position_ +=
sizeof(T) * count;
105 return SlotAt<T>(slot_position);
109 if (capacity_ < pos) {
110 while (capacity_ < pos) capacity_ *= 2;
111 buffer_ =
reinterpret_cast<byte*
>(realloc(buffer_, capacity_));
115 DebugObject* debug_object() {
return debug_object_; }
117 byte* buffer() {
return buffer_; }
121 if (delta == 0)
return;
123 Ensure(position_ += padding);
124 DCHECK_EQ(position_ % align, 0);
129 uint8_t byte = value & 0x7F;
131 if (value != 0) byte |= 0x80;
132 Write<uint8_t>(byte);
133 }
while (value != 0);
136 void WriteSLEB128(intptr_t value) {
139 int8_t byte = value & 0x7F;
140 bool byte_sign = byte & 0x40;
143 if ((value == 0 && !byte_sign) || (value == -1 && byte_sign)) {
153 void WriteString(
const char* str) {
160 template<
typename T>
friend class Slot;
164 DCHECK(offset < capacity_ && offset +
sizeof(T) <= capacity_);
165 return reinterpret_cast<T*
>(&buffer_[offset]);
168 DebugObject* debug_object_;
174 class ELFStringTable;
176 template<
typename THeader>
177 class DebugSectionBase :
public ZoneObject {
179 virtual ~DebugSectionBase() =
default;
181 virtual void WriteBody(Writer::Slot<THeader> header, Writer* writer) {
183 if (WriteBodyInternal(writer)) {
185 header->offset =
static_cast<uint32_t>(start);
186 #if defined(__MACH_O) 189 header->size = end - start;
193 virtual bool WriteBodyInternal(Writer* writer) {
197 typedef THeader Header;
201 struct MachOSectionHeader {
204 #if V8_TARGET_ARCH_IA32 221 class MachOSection :
public DebugSectionBase<MachOSectionHeader> {
225 S_ATTR_COALESCED = 0xBu,
226 S_ATTR_SOME_INSTRUCTIONS = 0x400u,
227 S_ATTR_DEBUG = 0x02000000u,
228 S_ATTR_PURE_INSTRUCTIONS = 0x80000000u
231 MachOSection(
const char* name,
const char* segment,
uint32_t align,
233 : name_(name), segment_(segment), align_(align), flags_(flags) {
235 DCHECK(base::bits::IsPowerOfTwo(align));
236 align_ = WhichPowerOf2(align_);
240 ~MachOSection()
override =
default;
242 virtual void PopulateHeader(Writer::Slot<Header> header) {
246 header->align = align_;
249 header->flags = flags_;
250 header->reserved1 = 0;
251 header->reserved2 = 0;
252 memset(header->sectname, 0,
sizeof(header->sectname));
253 memset(header->segname, 0,
sizeof(header->segname));
254 DCHECK(strlen(name_) <
sizeof(header->sectname));
255 DCHECK(strlen(segment_) <
sizeof(header->segname));
256 strncpy(header->sectname, name_,
sizeof(header->sectname));
257 strncpy(header->segname, segment_,
sizeof(header->segname));
262 const char* segment_;
268 struct ELFSectionHeader {
283 class ELFSection :
public DebugSectionBase<ELFSectionHeader> {
298 TYPE_LOPROC = 0x70000000,
299 TYPE_X86_64_UNWIND = 0x70000001,
300 TYPE_HIPROC = 0x7FFFFFFF,
301 TYPE_LOUSER = 0x80000000,
302 TYPE_HIUSER = 0xFFFFFFFF
311 enum SpecialIndexes { INDEX_ABSOLUTE = 0xFFF1 };
314 : name_(name), type_(type), align_(align) { }
316 ~ELFSection()
override =
default;
318 void PopulateHeader(Writer::Slot<Header> header, ELFStringTable* strtab);
320 void WriteBody(Writer::Slot<Header> header, Writer* w)
override {
322 if (WriteBodyInternal(w)) {
324 header->offset = start;
325 header->size = end - start;
329 bool WriteBodyInternal(Writer* w)
override {
return false; }
331 uint16_t index()
const {
return index_; }
332 void set_index(uint16_t index) { index_ = index; }
335 virtual void PopulateHeader(Writer::Slot<Header> header) {
342 header->entry_size = 0;
351 #endif // defined(__ELF) 354 #if defined(__MACH_O) 355 class MachOTextSection :
public MachOSection {
358 : MachOSection(
"__text",
"__TEXT", align,
359 MachOSection::S_REGULAR |
360 MachOSection::S_ATTR_SOME_INSTRUCTIONS |
361 MachOSection::S_ATTR_PURE_INSTRUCTIONS),
366 virtual void PopulateHeader(Writer::Slot<Header> header) {
367 MachOSection::PopulateHeader(header);
368 header->addr = addr_;
369 header->size = size_;
376 #endif // defined(__MACH_O) 380 class FullHeaderELFSection :
public ELFSection {
382 FullHeaderELFSection(
const char* name,
389 : ELFSection(name, type, align),
396 void PopulateHeader(Writer::Slot<Header> header)
override {
397 ELFSection::PopulateHeader(header);
398 header->address = addr_;
399 header->offset = offset_;
400 header->size = size_;
401 header->flags = flags_;
412 class ELFStringTable :
public ELFSection {
414 explicit ELFStringTable(
const char* name)
415 : ELFSection(name, TYPE_STRTAB, 1),
421 if (*str ==
'\0')
return 0;
428 void AttachWriter(Writer* w) {
430 offset_ = writer_->position();
436 void DetachWriter() { writer_ =
nullptr; }
438 void WriteBody(Writer::Slot<Header> header, Writer* w)
override {
439 DCHECK_NULL(writer_);
440 header->offset = offset_;
441 header->size = size_;
445 void WriteString(
const char* str) {
448 writer_->Write(*str);
461 void ELFSection::PopulateHeader(Writer::Slot<ELFSection::Header> header,
462 ELFStringTable* strtab) {
463 header->name =
static_cast<uint32_t>(strtab->Add(name_));
464 header->type = type_;
465 header->alignment = align_;
466 PopulateHeader(header);
468 #endif // defined(__ELF) 471 #if defined(__MACH_O) 474 explicit MachO(Zone* zone) : sections_(zone) {}
476 size_t AddSection(MachOSection* section) {
477 sections_.push_back(section);
478 return sections_.size() - 1;
482 Writer::Slot<MachOHeader> header = WriteHeader(w);
483 uintptr_t load_command_start = w->position();
484 Writer::Slot<MachOSegmentCommand> cmd = WriteSegmentCommand(w,
487 WriteSections(w, cmd, header, load_command_start);
499 #if V8_TARGET_ARCH_X64 504 struct MachOSegmentCommand {
508 #if V8_TARGET_ARCH_IA32 525 enum MachOLoadCommandCmd {
526 LC_SEGMENT_32 = 0x00000001u,
527 LC_SEGMENT_64 = 0x00000019u
531 Writer::Slot<MachOHeader> WriteHeader(Writer* w) {
532 DCHECK_EQ(w->position(), 0);
533 Writer::Slot<MachOHeader> header = w->CreateSlotHere<MachOHeader>();
534 #if V8_TARGET_ARCH_IA32 535 header->magic = 0xFEEDFACEu;
537 header->cpusubtype = 3;
538 #elif V8_TARGET_ARCH_X64 539 header->magic = 0xFEEDFACFu;
540 header->cputype = 7 | 0x01000000;
541 header->cpusubtype = 3;
542 header->reserved = 0;
544 #error Unsupported target architecture. 546 header->filetype = 0x1;
548 header->sizeofcmds = 0;
554 Writer::Slot<MachOSegmentCommand> WriteSegmentCommand(Writer* w,
557 Writer::Slot<MachOSegmentCommand> cmd =
558 w->CreateSlotHere<MachOSegmentCommand>();
559 #if V8_TARGET_ARCH_IA32 560 cmd->cmd = LC_SEGMENT_32;
562 cmd->cmd = LC_SEGMENT_64;
564 cmd->vmaddr = code_start;
565 cmd->vmsize = code_size;
571 cmd->nsects =
static_cast<uint32_t>(sections_.size());
572 memset(cmd->segname, 0, 16);
573 cmd->cmdsize =
sizeof(MachOSegmentCommand) +
sizeof(MachOSection::Header) *
579 void WriteSections(Writer* w,
580 Writer::Slot<MachOSegmentCommand> cmd,
581 Writer::Slot<MachOHeader> header,
583 Writer::Slot<MachOSection::Header> headers =
584 w->CreateSlotsHere<MachOSection::Header>(
585 static_cast<uint32_t>(sections_.size()));
586 cmd->fileoff = w->position();
588 static_cast<uint32_t>(w->position() - load_command_start);
590 for (MachOSection* section : sections_) {
591 section->PopulateHeader(headers.at(index));
592 section->WriteBody(headers.at(index), w);
595 cmd->filesize = w->position() - (
uintptr_t)cmd->fileoff;
598 ZoneChunkList<MachOSection*> sections_;
600 #endif // defined(__MACH_O) 606 explicit ELF(Zone* zone) : sections_(zone) {
607 sections_.push_back(
new (zone) ELFSection(
"", ELFSection::TYPE_NULL, 0));
608 sections_.push_back(
new (zone) ELFStringTable(
".shstrtab"));
611 void Write(Writer* w) {
613 WriteSectionTable(w);
617 ELFSection* SectionAt(
uint32_t index) {
return *sections_.Find(index); }
619 size_t AddSection(ELFSection* section) {
620 sections_.push_back(section);
621 section->set_index(sections_.size() - 1);
622 return sections_.size() - 1;
635 uint16_t header_size;
636 uint16_t pht_entry_size;
637 uint16_t pht_entry_num;
638 uint16_t sht_entry_size;
639 uint16_t sht_entry_num;
640 uint16_t sht_strtab_index;
644 void WriteHeader(Writer* w) {
645 DCHECK_EQ(w->position(), 0);
646 Writer::Slot<ELFHeader> header = w->CreateSlotHere<ELFHeader>();
647 #if (V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_ARM || \ 648 (V8_TARGET_ARCH_X64 && V8_TARGET_ARCH_32_BIT)) 649 const uint8_t ident[16] = {0x7F,
'E',
'L',
'F', 1, 1, 1, 0,
650 0, 0, 0, 0, 0, 0, 0, 0};
651 #elif(V8_TARGET_ARCH_X64 && V8_TARGET_ARCH_64_BIT) || \ 652 (V8_TARGET_ARCH_PPC64 && V8_TARGET_LITTLE_ENDIAN) 653 const uint8_t ident[16] = {0x7F,
'E',
'L',
'F', 2, 1, 1, 0,
654 0, 0, 0, 0, 0, 0, 0, 0};
655 #elif V8_TARGET_ARCH_PPC64 && V8_TARGET_BIG_ENDIAN && V8_OS_LINUX 656 const uint8_t ident[16] = {0x7F,
'E',
'L',
'F', 2, 2, 1, 0,
657 0, 0, 0, 0, 0, 0, 0, 0};
658 #elif V8_TARGET_ARCH_S390X 659 const uint8_t ident[16] = {0x7F,
'E',
'L',
'F', 2, 2, 1, 3,
660 0, 0, 0, 0, 0, 0, 0, 0};
661 #elif V8_TARGET_ARCH_S390 662 const uint8_t ident[16] = {0x7F,
'E',
'L',
'F', 1, 2, 1, 3,
663 0, 0, 0, 0, 0, 0, 0, 0};
665 #error Unsupported target architecture. 667 memcpy(header->ident, ident, 16);
669 #if V8_TARGET_ARCH_IA32 671 #elif V8_TARGET_ARCH_X64 675 header->machine = 62;
676 #elif V8_TARGET_ARCH_ARM 679 header->machine = 40;
680 #elif V8_TARGET_ARCH_PPC64 && V8_OS_LINUX 687 header->machine = 21;
688 #elif V8_TARGET_ARCH_S390 692 header->machine = 22;
694 #error Unsupported target architecture. 698 header->pht_offset = 0;
699 header->sht_offset =
sizeof(ELFHeader);
701 header->header_size =
sizeof(ELFHeader);
702 header->pht_entry_size = 0;
703 header->pht_entry_num = 0;
704 header->sht_entry_size =
sizeof(ELFSection::Header);
705 header->sht_entry_num = sections_.size();
706 header->sht_strtab_index = 1;
709 void WriteSectionTable(Writer* w) {
711 DCHECK(w->position() ==
sizeof(ELFHeader));
713 Writer::Slot<ELFSection::Header> headers =
714 w->CreateSlotsHere<ELFSection::Header>(
715 static_cast<uint32_t>(sections_.size()));
718 ELFStringTable* strtab =
static_cast<ELFStringTable*
>(SectionAt(1));
719 strtab->AttachWriter(w);
721 for (ELFSection* section : sections_) {
722 section->PopulateHeader(headers.at(index), strtab);
725 strtab->DetachWriter();
728 int SectionHeaderPosition(
uint32_t section_index) {
729 return sizeof(ELFHeader) +
sizeof(ELFSection::Header) * section_index;
732 void WriteSections(Writer* w) {
733 Writer::Slot<ELFSection::Header> headers =
734 w->SlotAt<ELFSection::Header>(
sizeof(ELFHeader));
737 for (ELFSection* section : sections_) {
738 section->WriteBody(headers.at(index), w);
743 ZoneChunkList<ELFSection*> sections_;
766 ELFSymbol(
const char* name,
775 info((binding << 4) | type),
780 Binding binding()
const {
781 return static_cast<Binding
>(info >> 4);
783 #if (V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_ARM || \ 784 (V8_TARGET_ARCH_X64 && V8_TARGET_ARCH_32_BIT) || \ 785 (V8_TARGET_ARCH_S390 && V8_TARGET_ARCH_32_BIT)) 786 struct SerializedLayout {
796 info((binding << 4) | type),
808 #elif(V8_TARGET_ARCH_X64 && V8_TARGET_ARCH_64_BIT) || \ 809 (V8_TARGET_ARCH_PPC64 && V8_OS_LINUX) || V8_TARGET_ARCH_S390X 810 struct SerializedLayout {
818 info((binding << 4) | type),
834 void Write(Writer::Slot<SerializedLayout> s, ELFStringTable* t)
const {
836 s->name =
static_cast<uint32_t>(t->Add(name));
841 s->section = section;
854 class ELFSymbolTable :
public ELFSection {
856 ELFSymbolTable(
const char* name, Zone* zone)
857 : ELFSection(name, TYPE_SYMTAB, sizeof(
uintptr_t)),
861 void WriteBody(Writer::Slot<Header> header, Writer* w)
override {
862 w->Align(header->alignment);
863 size_t total_symbols = locals_.size() + globals_.size() + 1;
864 header->offset = w->position();
866 Writer::Slot<ELFSymbol::SerializedLayout> symbols =
867 w->CreateSlotsHere<ELFSymbol::SerializedLayout>(
868 static_cast<uint32_t>(total_symbols));
870 header->size = w->position() - header->offset;
873 ELFStringTable* strtab =
874 static_cast<ELFStringTable*
>(w->debug_object()->SectionAt(index() + 1));
875 strtab->AttachWriter(w);
876 symbols.at(0).set(ELFSymbol::SerializedLayout(0,
879 ELFSymbol::BIND_LOCAL,
880 ELFSymbol::TYPE_NOTYPE,
882 WriteSymbolsList(&locals_, symbols.at(1), strtab);
883 WriteSymbolsList(&globals_,
884 symbols.at(static_cast<uint32_t>(locals_.size() + 1)),
886 strtab->DetachWriter();
889 void Add(
const ELFSymbol& symbol) {
890 if (symbol.binding() == ELFSymbol::BIND_LOCAL) {
891 locals_.push_back(symbol);
893 globals_.push_back(symbol);
898 void PopulateHeader(Writer::Slot<Header> header)
override {
899 ELFSection::PopulateHeader(header);
901 header->link = index() + 1;
902 header->info =
static_cast<uint32_t>(locals_.size() + 1);
903 header->entry_size =
sizeof(ELFSymbol::SerializedLayout);
907 void WriteSymbolsList(
const ZoneChunkList<ELFSymbol>* src,
908 Writer::Slot<ELFSymbol::SerializedLayout> dst,
909 ELFStringTable* strtab) {
911 for (
const ELFSymbol& symbol : *src) {
912 symbol.Write(dst.at(
i++), strtab);
916 ZoneChunkList<ELFSymbol> locals_;
917 ZoneChunkList<ELFSymbol> globals_;
919 #endif // defined(__ELF) 922 class LineInfo :
public Malloced {
924 void SetPosition(intptr_t pc,
int pos,
bool is_statement) {
925 AddPCInfo(PCInfo(pc, pos, is_statement));
929 PCInfo(intptr_t pc,
int pos,
bool is_statement)
930 : pc_(pc), pos_(pos), is_statement_(is_statement) {}
937 std::vector<PCInfo>* pc_info() {
return &pc_info_; }
940 void AddPCInfo(
const PCInfo& pc_info) { pc_info_.push_back(pc_info); }
942 std::vector<PCInfo> pc_info_;
945 class CodeDescription {
947 #if V8_TARGET_ARCH_X64 956 CodeDescription(
const char* name, Code code, SharedFunctionInfo* shared,
958 : name_(name), code_(code), shared_info_(shared), lineinfo_(lineinfo) {}
960 const char* name()
const {
964 LineInfo* lineinfo()
const {
return lineinfo_; }
966 bool is_function()
const {
967 Code::Kind kind = code_->kind();
968 return kind == Code::OPTIMIZED_FUNCTION;
971 bool has_scope_info()
const {
return shared_info_ !=
nullptr; }
973 ScopeInfo scope_info()
const {
974 DCHECK(has_scope_info());
975 return shared_info_->scope_info();
979 return static_cast<uintptr_t>(code_->InstructionStart());
983 return static_cast<uintptr_t>(code_->InstructionEnd());
987 return CodeEnd() - CodeStart();
991 return shared_info_ !=
nullptr && shared_info_->script()->IsScript();
994 Script* script() {
return Script::cast(shared_info_->script()); }
996 bool IsLineInfoAvailable() {
return lineinfo_ !=
nullptr; }
998 #if V8_TARGET_ARCH_X64 999 uintptr_t GetStackStateStartAddress(StackState state)
const {
1000 DCHECK(state < STACK_STATE_MAX);
1001 return stack_state_start_addresses_[state];
1004 void SetStackStateStartAddress(StackState state,
uintptr_t addr) {
1005 DCHECK(state < STACK_STATE_MAX);
1006 stack_state_start_addresses_[state] = addr;
1010 std::unique_ptr<char[]> GetFilename() {
1011 if (shared_info_ !=
nullptr) {
1012 return String::cast(script()->name())->ToCString();
1014 std::unique_ptr<char[]> result(
new char[1]);
1020 int GetScriptLineNumber(
int pos) {
1021 if (shared_info_ !=
nullptr) {
1022 return script()->GetLineNumber(pos) + 1;
1031 SharedFunctionInfo* shared_info_;
1032 LineInfo* lineinfo_;
1033 #if V8_TARGET_ARCH_X64 1034 uintptr_t stack_state_start_addresses_[STACK_STATE_MAX];
1039 static void CreateSymbolsTable(CodeDescription* desc, Zone* zone, ELF* elf,
1040 size_t text_section_index) {
1041 ELFSymbolTable* symtab =
new(zone) ELFSymbolTable(
".symtab", zone);
1042 ELFStringTable* strtab =
new(zone) ELFStringTable(
".strtab");
1045 elf->AddSection(symtab);
1046 elf->AddSection(strtab);
1048 symtab->Add(ELFSymbol(
"V8 Code", 0, 0, ELFSymbol::BIND_LOCAL,
1049 ELFSymbol::TYPE_FILE, ELFSection::INDEX_ABSOLUTE));
1051 symtab->Add(ELFSymbol(desc->name(), 0, desc->CodeSize(),
1052 ELFSymbol::BIND_GLOBAL, ELFSymbol::TYPE_FUNC,
1053 text_section_index));
1055 #endif // defined(__ELF) 1058 class DebugInfoSection :
public DebugSection {
1060 explicit DebugInfoSection(CodeDescription* desc)
1062 : ELFSection(
".debug_info", TYPE_PROGBITS, 1),
1064 : MachOSection(
"__debug_info",
1067 MachOSection::S_REGULAR | MachOSection::S_ATTR_DEBUG),
1072 enum DWARF2LocationOp {
1108 enum DWARF2Encoding {
1109 DW_ATE_ADDRESS = 0x1,
1113 bool WriteBodyInternal(Writer* w)
override {
1115 Writer::Slot<uint32_t> size = w->CreateSlotHere<
uint32_t>();
1117 w->Write<uint16_t>(2);
1119 w->Write<uint8_t>(
sizeof(intptr_t));
1122 w->WriteString(desc_->GetFilename().get());
1123 w->Write<intptr_t>(desc_->CodeStart());
1124 w->Write<intptr_t>(desc_->CodeStart() + desc_->CodeSize());
1129 w->Write<uint8_t>(kPointerSize);
1130 w->WriteString(
"v8value");
1132 if (desc_->has_scope_info()) {
1133 ScopeInfo scope = desc_->scope_info();
1135 w->WriteString(desc_->name());
1136 w->Write<intptr_t>(desc_->CodeStart());
1137 w->Write<intptr_t>(desc_->CodeStart() + desc_->CodeSize());
1138 Writer::Slot<uint32_t> fb_block_size = w->CreateSlotHere<
uint32_t>();
1139 uintptr_t fb_block_start = w->position();
1140 #if V8_TARGET_ARCH_IA32 1141 w->Write<uint8_t>(DW_OP_reg5);
1142 #elif V8_TARGET_ARCH_X64 1143 w->Write<uint8_t>(DW_OP_reg6);
1144 #elif V8_TARGET_ARCH_ARM 1146 #elif V8_TARGET_ARCH_MIPS 1148 #elif V8_TARGET_ARCH_MIPS64 1150 #elif V8_TARGET_ARCH_PPC64 && V8_OS_LINUX 1151 w->Write<uint8_t>(DW_OP_reg31);
1152 #elif V8_TARGET_ARCH_S390 1153 w->Write<uint8_t>(DW_OP_reg11);
1155 #error Unsupported target architecture. 1157 fb_block_size.set(static_cast<uint32_t>(w->position() - fb_block_start));
1159 int params = scope->ParameterCount();
1160 int context_slots = scope->ContextLocalCount();
1162 int internal_slots = Context::MIN_CONTEXT_SLOTS;
1163 int current_abbreviation = 4;
1165 EmbeddedVector<char, 256> buffer;
1166 StringBuilder builder(buffer.start(), buffer.length());
1168 for (
int param = 0; param < params; ++param) {
1169 w->WriteULEB128(current_abbreviation++);
1171 builder.AddFormatted(
"param%d", param);
1172 w->WriteString(builder.Finalize());
1174 Writer::Slot<uint32_t> block_size = w->CreateSlotHere<
uint32_t>();
1176 w->Write<uint8_t>(DW_OP_fbreg);
1178 JavaScriptFrameConstants::kLastParameterOffset +
1179 kPointerSize * (params - param - 1));
1180 block_size.set(static_cast<uint32_t>(w->position() - block_start));
1184 DCHECK_EQ(Context::MIN_CONTEXT_SLOTS, 4);
1185 DCHECK_EQ(Context::SCOPE_INFO_INDEX, 0);
1186 DCHECK_EQ(Context::PREVIOUS_INDEX, 1);
1187 DCHECK_EQ(Context::EXTENSION_INDEX, 2);
1188 DCHECK_EQ(Context::NATIVE_CONTEXT_INDEX, 3);
1189 w->WriteULEB128(current_abbreviation++);
1190 w->WriteString(
".scope_info");
1191 w->WriteULEB128(current_abbreviation++);
1192 w->WriteString(
".previous");
1193 w->WriteULEB128(current_abbreviation++);
1194 w->WriteString(
".extension");
1195 w->WriteULEB128(current_abbreviation++);
1196 w->WriteString(
".native_context");
1198 for (
int context_slot = 0;
1199 context_slot < context_slots;
1201 w->WriteULEB128(current_abbreviation++);
1203 builder.AddFormatted(
"context_slot%d", context_slot + internal_slots);
1204 w->WriteString(builder.Finalize());
1208 w->WriteULEB128(current_abbreviation++);
1209 w->WriteString(
"__function");
1211 Writer::Slot<uint32_t> block_size = w->CreateSlotHere<
uint32_t>();
1213 w->Write<uint8_t>(DW_OP_fbreg);
1214 w->WriteSLEB128(JavaScriptFrameConstants::kFunctionOffset);
1215 block_size.set(static_cast<uint32_t>(w->position() - block_start));
1219 w->WriteULEB128(current_abbreviation++);
1220 w->WriteString(
"__context");
1222 Writer::Slot<uint32_t> block_size = w->CreateSlotHere<
uint32_t>();
1224 w->Write<uint8_t>(DW_OP_fbreg);
1225 w->WriteSLEB128(StandardFrameConstants::kContextOffset);
1226 block_size.set(static_cast<uint32_t>(w->position() - block_start));
1233 size.set(static_cast<uint32_t>(w->position() - start));
1238 CodeDescription* desc_;
1242 class DebugAbbrevSection :
public DebugSection {
1244 explicit DebugAbbrevSection(CodeDescription* desc)
1246 : ELFSection(
".debug_abbrev", TYPE_PROGBITS, 1),
1248 : MachOSection(
"__debug_abbrev",
1251 MachOSection::S_REGULAR | MachOSection::S_ATTR_DEBUG),
1257 DW_TAG_FORMAL_PARAMETER = 0x05,
1258 DW_TAG_POINTER_TYPE = 0xF,
1259 DW_TAG_COMPILE_UNIT = 0x11,
1260 DW_TAG_STRUCTURE_TYPE = 0x13,
1261 DW_TAG_BASE_TYPE = 0x24,
1262 DW_TAG_SUBPROGRAM = 0x2E,
1263 DW_TAG_VARIABLE = 0x34
1267 enum DWARF2ChildrenDetermination {
1273 enum DWARF2Attribute {
1274 DW_AT_LOCATION = 0x2,
1276 DW_AT_BYTE_SIZE = 0xB,
1277 DW_AT_STMT_LIST = 0x10,
1278 DW_AT_LOW_PC = 0x11,
1279 DW_AT_HIGH_PC = 0x12,
1280 DW_AT_ENCODING = 0x3E,
1281 DW_AT_FRAME_BASE = 0x40,
1286 enum DWARF2AttributeForm {
1288 DW_FORM_BLOCK4 = 0x4,
1289 DW_FORM_STRING = 0x8,
1290 DW_FORM_DATA4 = 0x6,
1291 DW_FORM_BLOCK = 0x9,
1292 DW_FORM_DATA1 = 0xB,
1297 void WriteVariableAbbreviation(Writer* w,
1298 int abbreviation_code,
1300 bool is_parameter) {
1301 w->WriteULEB128(abbreviation_code);
1302 w->WriteULEB128(is_parameter ? DW_TAG_FORMAL_PARAMETER : DW_TAG_VARIABLE);
1303 w->Write<uint8_t>(DW_CHILDREN_NO);
1304 w->WriteULEB128(DW_AT_NAME);
1305 w->WriteULEB128(DW_FORM_STRING);
1307 w->WriteULEB128(DW_AT_TYPE);
1308 w->WriteULEB128(DW_FORM_REF4);
1309 w->WriteULEB128(DW_AT_LOCATION);
1310 w->WriteULEB128(DW_FORM_BLOCK4);
1316 bool WriteBodyInternal(Writer* w)
override {
1317 int current_abbreviation = 1;
1318 bool extra_info = desc_->has_scope_info();
1319 DCHECK(desc_->IsLineInfoAvailable());
1320 w->WriteULEB128(current_abbreviation++);
1321 w->WriteULEB128(DW_TAG_COMPILE_UNIT);
1322 w->Write<uint8_t>(extra_info ? DW_CHILDREN_YES : DW_CHILDREN_NO);
1323 w->WriteULEB128(DW_AT_NAME);
1324 w->WriteULEB128(DW_FORM_STRING);
1325 w->WriteULEB128(DW_AT_LOW_PC);
1326 w->WriteULEB128(DW_FORM_ADDR);
1327 w->WriteULEB128(DW_AT_HIGH_PC);
1328 w->WriteULEB128(DW_FORM_ADDR);
1329 w->WriteULEB128(DW_AT_STMT_LIST);
1330 w->WriteULEB128(DW_FORM_DATA4);
1335 ScopeInfo scope = desc_->scope_info();
1336 int params = scope->ParameterCount();
1337 int context_slots = scope->ContextLocalCount();
1339 int internal_slots = Context::MIN_CONTEXT_SLOTS;
1345 w->WriteULEB128(current_abbreviation++);
1346 w->WriteULEB128(DW_TAG_SUBPROGRAM);
1347 w->Write<uint8_t>(DW_CHILDREN_YES);
1348 w->WriteULEB128(DW_AT_NAME);
1349 w->WriteULEB128(DW_FORM_STRING);
1350 w->WriteULEB128(DW_AT_LOW_PC);
1351 w->WriteULEB128(DW_FORM_ADDR);
1352 w->WriteULEB128(DW_AT_HIGH_PC);
1353 w->WriteULEB128(DW_FORM_ADDR);
1354 w->WriteULEB128(DW_AT_FRAME_BASE);
1355 w->WriteULEB128(DW_FORM_BLOCK4);
1359 w->WriteULEB128(current_abbreviation++);
1360 w->WriteULEB128(DW_TAG_STRUCTURE_TYPE);
1361 w->Write<uint8_t>(DW_CHILDREN_NO);
1362 w->WriteULEB128(DW_AT_BYTE_SIZE);
1363 w->WriteULEB128(DW_FORM_DATA1);
1364 w->WriteULEB128(DW_AT_NAME);
1365 w->WriteULEB128(DW_FORM_STRING);
1369 for (
int param = 0; param < params; ++param) {
1370 WriteVariableAbbreviation(w, current_abbreviation++,
true,
true);
1373 for (
int internal_slot = 0;
1374 internal_slot < internal_slots;
1376 WriteVariableAbbreviation(w, current_abbreviation++,
false,
false);
1379 for (
int context_slot = 0;
1380 context_slot < context_slots;
1382 WriteVariableAbbreviation(w, current_abbreviation++,
false,
false);
1386 WriteVariableAbbreviation(w, current_abbreviation++,
true,
false);
1389 WriteVariableAbbreviation(w, current_abbreviation++,
true,
false);
1399 CodeDescription* desc_;
1403 class DebugLineSection :
public DebugSection {
1405 explicit DebugLineSection(CodeDescription* desc)
1407 : ELFSection(
".debug_line", TYPE_PROGBITS, 1),
1409 : MachOSection(
"__debug_line",
1412 MachOSection::S_REGULAR | MachOSection::S_ATTR_DEBUG),
1417 enum DWARF2Opcodes {
1419 DW_LNS_ADVANCE_PC = 2,
1420 DW_LNS_ADVANCE_LINE = 3,
1421 DW_LNS_SET_FILE = 4,
1422 DW_LNS_SET_COLUMN = 5,
1423 DW_LNS_NEGATE_STMT = 6
1427 enum DWARF2ExtendedOpcode {
1428 DW_LNE_END_SEQUENCE = 1,
1429 DW_LNE_SET_ADDRESS = 2,
1430 DW_LNE_DEFINE_FILE = 3
1433 bool WriteBodyInternal(Writer* w)
override {
1435 Writer::Slot<uint32_t> total_length = w->CreateSlotHere<
uint32_t>();
1439 const int8_t line_base = 1;
1440 const uint8_t line_range = 7;
1441 const int8_t max_line_incr = (line_base + line_range - 1);
1442 const uint8_t opcode_base = DW_LNS_NEGATE_STMT + 1;
1444 w->Write<uint16_t>(2);
1445 Writer::Slot<uint32_t> prologue_length = w->CreateSlotHere<
uint32_t>();
1446 uintptr_t prologue_start = w->position();
1447 w->Write<uint8_t>(1);
1448 w->Write<uint8_t>(1);
1449 w->Write<int8_t>(line_base);
1450 w->Write<uint8_t>(line_range);
1451 w->Write<uint8_t>(opcode_base);
1452 w->Write<uint8_t>(0);
1453 w->Write<uint8_t>(1);
1454 w->Write<uint8_t>(1);
1455 w->Write<uint8_t>(1);
1456 w->Write<uint8_t>(1);
1457 w->Write<uint8_t>(0);
1458 w->Write<uint8_t>(0);
1459 w->WriteString(desc_->GetFilename().get());
1463 w->Write<uint8_t>(0);
1464 prologue_length.set(static_cast<uint32_t>(w->position() - prologue_start));
1466 WriteExtendedOpcode(w, DW_LNE_SET_ADDRESS,
sizeof(intptr_t));
1467 w->Write<intptr_t>(desc_->CodeStart());
1468 w->Write<uint8_t>(DW_LNS_COPY);
1472 bool is_statement =
true;
1474 std::vector<LineInfo::PCInfo>* pc_info = desc_->lineinfo()->pc_info();
1475 std::sort(pc_info->begin(), pc_info->end(), &ComparePCInfo);
1477 for (
size_t i = 0;
i < pc_info->size();
i++) {
1478 LineInfo::PCInfo* info = &pc_info->at(
i);
1479 DCHECK(info->pc_ >= pc);
1483 intptr_t new_line = desc_->GetScriptLineNumber(info->pos_);
1484 if (new_line == line) {
1492 if ((
i + 1) == pc_info->size()) {
1493 if (!is_statement) {
1494 w->Write<uint8_t>(DW_LNS_NEGATE_STMT);
1496 }
else if (is_statement != info->is_statement_) {
1497 w->Write<uint8_t>(DW_LNS_NEGATE_STMT);
1498 is_statement = !is_statement;
1505 intptr_t line_diff = new_line - line;
1508 intptr_t special_opcode = (line_diff - line_base) +
1509 (line_range * pc_diff) + opcode_base;
1516 if ((special_opcode >= opcode_base) && (special_opcode <= 255) &&
1517 (line_diff <= max_line_incr) && (line_diff >= line_base)) {
1518 w->Write<uint8_t>(special_opcode);
1520 w->Write<uint8_t>(DW_LNS_ADVANCE_PC);
1521 w->WriteSLEB128(pc_diff);
1522 w->Write<uint8_t>(DW_LNS_ADVANCE_LINE);
1523 w->WriteSLEB128(line_diff);
1524 w->Write<uint8_t>(DW_LNS_COPY);
1533 w->Write<uint8_t>(DW_LNS_ADVANCE_PC);
1534 w->WriteSLEB128(desc_->CodeSize() - pc);
1535 WriteExtendedOpcode(w, DW_LNE_END_SEQUENCE, 0);
1536 total_length.set(static_cast<uint32_t>(w->position() - start));
1541 void WriteExtendedOpcode(Writer* w,
1542 DWARF2ExtendedOpcode op,
1543 size_t operands_size) {
1544 w->Write<uint8_t>(0);
1545 w->WriteULEB128(operands_size + 1);
1546 w->Write<uint8_t>(op);
1549 static bool ComparePCInfo(
const LineInfo::PCInfo& a,
1550 const LineInfo::PCInfo& b) {
1551 if (a.pc_ == b.pc_) {
1552 if (a.is_statement_ != b.is_statement_) {
1553 return !b.is_statement_;
1557 return a.pc_ < b.pc_;
1560 CodeDescription* desc_;
1564 #if V8_TARGET_ARCH_X64 1566 class UnwindInfoSection :
public DebugSection {
1568 explicit UnwindInfoSection(CodeDescription* desc);
1569 bool WriteBodyInternal(Writer* w)
override;
1571 int WriteCIE(Writer* w);
1572 void WriteFDE(Writer* w,
int);
1574 void WriteFDEStateOnEntry(Writer* w);
1575 void WriteFDEStateAfterRBPPush(Writer* w);
1576 void WriteFDEStateAfterRBPSet(Writer* w);
1577 void WriteFDEStateAfterRBPPop(Writer* w);
1579 void WriteLength(Writer* w,
1580 Writer::Slot<uint32_t>* length_slot,
1581 int initial_position);
1584 CodeDescription* desc_;
1587 enum CFIInstructions {
1588 DW_CFA_ADVANCE_LOC = 0x40,
1589 DW_CFA_OFFSET = 0x80,
1590 DW_CFA_RESTORE = 0xC0,
1592 DW_CFA_SET_LOC = 0x01,
1593 DW_CFA_ADVANCE_LOC1 = 0x02,
1594 DW_CFA_ADVANCE_LOC2 = 0x03,
1595 DW_CFA_ADVANCE_LOC4 = 0x04,
1596 DW_CFA_OFFSET_EXTENDED = 0x05,
1597 DW_CFA_RESTORE_EXTENDED = 0x06,
1598 DW_CFA_UNDEFINED = 0x07,
1599 DW_CFA_SAME_VALUE = 0x08,
1600 DW_CFA_REGISTER = 0x09,
1601 DW_CFA_REMEMBER_STATE = 0x0A,
1602 DW_CFA_RESTORE_STATE = 0x0B,
1603 DW_CFA_DEF_CFA = 0x0C,
1604 DW_CFA_DEF_CFA_REGISTER = 0x0D,
1605 DW_CFA_DEF_CFA_OFFSET = 0x0E,
1607 DW_CFA_DEF_CFA_EXPRESSION = 0x0F,
1608 DW_CFA_EXPRESSION = 0x10,
1609 DW_CFA_OFFSET_EXTENDED_SF = 0x11,
1610 DW_CFA_DEF_CFA_SF = 0x12,
1611 DW_CFA_DEF_CFA_OFFSET_SF = 0x13,
1612 DW_CFA_VAL_OFFSET = 0x14,
1613 DW_CFA_VAL_OFFSET_SF = 0x15,
1614 DW_CFA_VAL_EXPRESSION = 0x16
1618 enum RegisterMapping {
1628 CODE_ALIGN_FACTOR = 1,
1629 DATA_ALIGN_FACTOR = 1,
1630 RETURN_ADDRESS_REGISTER = AMD64_RA
1635 void UnwindInfoSection::WriteLength(Writer* w,
1636 Writer::Slot<uint32_t>* length_slot,
1637 int initial_position) {
1638 uint32_t align = (w->position() - initial_position) % kPointerSize;
1641 for (
uint32_t i = 0;
i < (kPointerSize - align);
i++) {
1642 w->Write<uint8_t>(DW_CFA_NOP);
1646 DCHECK_EQ((w->position() - initial_position) % kPointerSize, 0);
1647 length_slot->set(static_cast<uint32_t>(w->position() - initial_position));
1651 UnwindInfoSection::UnwindInfoSection(CodeDescription* desc)
1653 : ELFSection(
".eh_frame", TYPE_X86_64_UNWIND, 1),
1655 : MachOSection(
"__eh_frame",
"__TEXT",
sizeof(
uintptr_t),
1656 MachOSection::S_REGULAR),
1660 int UnwindInfoSection::WriteCIE(Writer* w) {
1661 Writer::Slot<uint32_t> cie_length_slot = w->CreateSlotHere<
uint32_t>();
1668 w->Write<uint8_t>(CIE_VERSION);
1669 w->Write<uint8_t>(0);
1670 w->WriteSLEB128(CODE_ALIGN_FACTOR);
1671 w->WriteSLEB128(DATA_ALIGN_FACTOR);
1672 w->Write<uint8_t>(RETURN_ADDRESS_REGISTER);
1674 WriteLength(w, &cie_length_slot, cie_position);
1676 return cie_position;
1680 void UnwindInfoSection::WriteFDE(Writer* w,
int cie_position) {
1682 Writer::Slot<uint32_t> fde_length_slot = w->CreateSlotHere<
uint32_t>();
1683 int fde_position =
static_cast<uint32_t>(w->position());
1684 w->Write<int32_t>(fde_position - cie_position + 4);
1686 w->Write<
uintptr_t>(desc_->CodeStart());
1689 WriteFDEStateOnEntry(w);
1690 WriteFDEStateAfterRBPPush(w);
1691 WriteFDEStateAfterRBPSet(w);
1692 WriteFDEStateAfterRBPPop(w);
1694 WriteLength(w, &fde_length_slot, fde_position);
1698 void UnwindInfoSection::WriteFDEStateOnEntry(Writer* w) {
1704 w->Write<uint8_t>(DW_CFA_DEF_CFA_SF);
1705 w->WriteULEB128(AMD64_RSP);
1706 w->WriteSLEB128(-kPointerSize);
1710 w->Write<uint8_t>(DW_CFA_OFFSET_EXTENDED);
1711 w->WriteULEB128(AMD64_RA);
1712 w->WriteSLEB128(StandardFrameConstants::kCallerPCOffset);
1715 w->Write<uint8_t>(DW_CFA_SAME_VALUE);
1716 w->WriteULEB128(AMD64_RBP);
1719 w->Write<uint8_t>(DW_CFA_SET_LOC);
1721 desc_->GetStackStateStartAddress(CodeDescription::POST_RBP_PUSH));
1725 void UnwindInfoSection::WriteFDEStateAfterRBPPush(Writer* w) {
1730 w->Write<uint8_t>(DW_CFA_DEF_CFA_OFFSET);
1735 w->Write<uint8_t>(DW_CFA_OFFSET_EXTENDED);
1736 w->WriteULEB128(AMD64_RBP);
1737 w->WriteSLEB128(StandardFrameConstants::kCallerFPOffset);
1740 w->Write<uint8_t>(DW_CFA_SET_LOC);
1742 desc_->GetStackStateStartAddress(CodeDescription::POST_RBP_SET));
1746 void UnwindInfoSection::WriteFDEStateAfterRBPSet(Writer* w) {
1750 w->Write<uint8_t>(DW_CFA_DEF_CFA);
1751 w->WriteULEB128(AMD64_RBP);
1755 w->Write<uint8_t>(DW_CFA_SET_LOC);
1757 desc_->GetStackStateStartAddress(CodeDescription::POST_RBP_POP));
1761 void UnwindInfoSection::WriteFDEStateAfterRBPPop(Writer* w) {
1766 w->Write<uint8_t>(DW_CFA_DEF_CFA_SF);
1767 w->WriteULEB128(AMD64_RSP);
1768 w->WriteSLEB128(-kPointerSize);
1771 w->Write<uint8_t>(DW_CFA_OFFSET_EXTENDED);
1772 w->WriteULEB128(AMD64_RBP);
1773 w->WriteSLEB128(StandardFrameConstants::kCallerFPOffset);
1776 w->Write<uint8_t>(DW_CFA_SET_LOC);
1777 w->Write<uint64_t>(desc_->CodeEnd());
1781 bool UnwindInfoSection::WriteBodyInternal(Writer* w) {
1782 uint32_t cie_position = WriteCIE(w);
1783 WriteFDE(w, cie_position);
1788 #endif // V8_TARGET_ARCH_X64 1790 static void CreateDWARFSections(CodeDescription* desc,
1793 if (desc->IsLineInfoAvailable()) {
1794 obj->AddSection(
new(zone) DebugInfoSection(desc));
1795 obj->AddSection(
new(zone) DebugAbbrevSection(desc));
1796 obj->AddSection(
new(zone) DebugLineSection(desc));
1798 #if V8_TARGET_ARCH_X64 1799 obj->AddSection(
new(zone) UnwindInfoSection(desc));
1814 struct JITCodeEntry {
1815 JITCodeEntry* next_;
1816 JITCodeEntry* prev_;
1817 Address symfile_addr_;
1818 uint64_t symfile_size_;
1821 struct JITDescriptor {
1824 JITCodeEntry* relevant_entry_;
1825 JITCodeEntry* first_entry_;
1831 void __attribute__((noinline)) __jit_debug_register_code() {
1838 JITDescriptor __jit_debug_descriptor = {1, 0,
nullptr,
nullptr};
1841 void __gdb_print_v8_object(Object*
object) {
1850 static JITCodeEntry* CreateCodeEntry(Address symfile_addr,
1852 JITCodeEntry* entry =
static_cast<JITCodeEntry*
>(
1853 malloc(
sizeof(JITCodeEntry) + symfile_size));
1855 entry->symfile_addr_ =
reinterpret_cast<Address
>(entry + 1);
1856 entry->symfile_size_ = symfile_size;
1857 MemCopy(reinterpret_cast<void*>(entry->symfile_addr_),
1858 reinterpret_cast<void*>(symfile_addr), symfile_size);
1860 entry->prev_ = entry->next_ =
nullptr;
1866 static void DestroyCodeEntry(JITCodeEntry* entry) {
1871 static void RegisterCodeEntry(JITCodeEntry* entry) {
1872 entry->next_ = __jit_debug_descriptor.first_entry_;
1873 if (entry->next_ !=
nullptr) entry->next_->prev_ = entry;
1874 __jit_debug_descriptor.first_entry_ =
1875 __jit_debug_descriptor.relevant_entry_ = entry;
1877 __jit_debug_descriptor.action_flag_ = JIT_REGISTER_FN;
1878 __jit_debug_register_code();
1882 static void UnregisterCodeEntry(JITCodeEntry* entry) {
1883 if (entry->prev_ !=
nullptr) {
1884 entry->prev_->next_ = entry->next_;
1886 __jit_debug_descriptor.first_entry_ = entry->next_;
1889 if (entry->next_ !=
nullptr) {
1890 entry->next_->prev_ = entry->prev_;
1893 __jit_debug_descriptor.relevant_entry_ = entry;
1894 __jit_debug_descriptor.action_flag_ = JIT_UNREGISTER_FN;
1895 __jit_debug_register_code();
1899 static JITCodeEntry* CreateELFObject(CodeDescription* desc, Isolate* isolate) {
1901 Zone zone(isolate->allocator(), ZONE_NAME);
1902 MachO mach_o(&zone);
1905 mach_o.AddSection(
new(&zone) MachOTextSection(kCodeAlignment,
1909 CreateDWARFSections(desc, &zone, &mach_o);
1911 mach_o.Write(&w, desc->CodeStart(), desc->CodeSize());
1913 Zone zone(isolate->allocator(), ZONE_NAME);
1917 size_t text_section_index = elf.AddSection(
new (&zone) FullHeaderELFSection(
1918 ".text", ELFSection::TYPE_NOBITS, kCodeAlignment, desc->CodeStart(), 0,
1919 desc->CodeSize(), ELFSection::FLAG_ALLOC | ELFSection::FLAG_EXEC));
1921 CreateSymbolsTable(desc, &zone, &elf, text_section_index);
1923 CreateDWARFSections(desc, &zone, &elf);
1928 return CreateCodeEntry(reinterpret_cast<Address>(w.buffer()), w.position());
1932 struct AddressRange {
1937 struct SplayTreeConfig {
1938 typedef AddressRange Key;
1939 typedef JITCodeEntry*
Value;
1940 static const AddressRange kNoKey;
1941 static Value NoValue() {
return nullptr; }
1942 static int Compare(
const AddressRange& a,
const AddressRange& b) {
1944 if (a.start < b.start)
return -1;
1945 if (a.start == b.start)
return 0;
1950 const AddressRange SplayTreeConfig::kNoKey = {0, 0};
1951 typedef SplayTree<SplayTreeConfig> CodeMap;
1953 static CodeMap* GetCodeMap() {
1954 static CodeMap* code_map =
nullptr;
1955 if (code_map ==
nullptr) code_map =
new CodeMap();
1960 static uint32_t HashCodeAddress(Address addr) {
1961 static const uintptr_t kGoldenRatio = 2654435761u;
1962 return static_cast<uint32_t>((addr >> kCodeAlignmentBits) * kGoldenRatio);
1965 static base::HashMap* GetLineMap() {
1966 static base::HashMap* line_map =
nullptr;
1967 if (line_map ==
nullptr) {
1968 line_map =
new base::HashMap();
1974 static void PutLineInfo(Address addr, LineInfo* info) {
1975 base::HashMap* line_map = GetLineMap();
1976 base::HashMap::Entry* e = line_map->LookupOrInsert(
1977 reinterpret_cast<void*>(addr), HashCodeAddress(addr));
1978 if (e->value !=
nullptr)
delete static_cast<LineInfo*
>(e->value);
1983 static LineInfo* GetLineInfo(Address addr) {
1984 void* value = GetLineMap()->Remove(reinterpret_cast<void*>(addr),
1985 HashCodeAddress(addr));
1986 return static_cast<LineInfo*
>(value);
1990 static void AddUnwindInfo(CodeDescription* desc) {
1991 #if V8_TARGET_ARCH_X64 1992 if (desc->is_function()) {
1996 static const int kFramePointerPushOffset = 1;
1997 static const int kFramePointerSetOffset = 4;
1998 static const int kFramePointerPopOffset = -3;
2001 desc->CodeStart() + kFramePointerPushOffset;
2004 desc->CodeStart() + kFramePointerSetOffset;
2007 desc->CodeEnd() + kFramePointerPopOffset;
2009 desc->SetStackStateStartAddress(CodeDescription::POST_RBP_PUSH,
2010 frame_pointer_push_address);
2011 desc->SetStackStateStartAddress(CodeDescription::POST_RBP_SET,
2012 frame_pointer_set_address);
2013 desc->SetStackStateStartAddress(CodeDescription::POST_RBP_POP,
2014 frame_pointer_pop_address);
2016 desc->SetStackStateStartAddress(CodeDescription::POST_RBP_PUSH,
2018 desc->SetStackStateStartAddress(CodeDescription::POST_RBP_SET,
2020 desc->SetStackStateStartAddress(CodeDescription::POST_RBP_POP,
2023 #endif // V8_TARGET_ARCH_X64 2027 static base::LazyMutex mutex = LAZY_MUTEX_INITIALIZER;
2032 static void RemoveJITCodeEntries(CodeMap* map,
const AddressRange& range) {
2033 DCHECK(range.start < range.end);
2034 CodeMap::Locator cur;
2035 if (map->FindGreatestLessThan(range, &cur) || map->FindLeast(&cur)) {
2037 while (cur.key().end <= range.start) {
2041 AddressRange new_key;
2042 new_key.start = cur.key().end;
2044 if (!map->FindLeastGreaterThan(new_key, &cur))
return;
2047 while (cur.key().start < range.end) {
2048 AddressRange old_range = cur.key();
2049 JITCodeEntry* old_entry = cur.value();
2051 UnregisterCodeEntry(old_entry);
2052 DestroyCodeEntry(old_entry);
2054 CHECK(map->Remove(old_range));
2055 if (!map->FindLeastGreaterThan(old_range, &cur))
return;
2062 static void AddJITCodeEntry(CodeMap* map,
const AddressRange& range,
2063 JITCodeEntry* entry,
bool dump_if_enabled,
2064 const char* name_hint) {
2065 #if defined(DEBUG) && !V8_OS_WIN 2066 static int file_num = 0;
2067 if (FLAG_gdbjit_dump && dump_if_enabled) {
2068 static const int kMaxFileNameSize = 64;
2071 SNPrintF(Vector<char>(file_name, kMaxFileNameSize),
"/tmp/elfdump%s%d.o",
2072 (name_hint !=
nullptr) ? name_hint :
"", file_num++);
2073 WriteBytes(file_name, reinterpret_cast<byte*>(entry->symfile_addr_),
2074 static_cast<int>(entry->symfile_size_));
2078 CodeMap::Locator cur;
2079 CHECK(map->Insert(range, &cur));
2080 cur.set_value(entry);
2082 RegisterCodeEntry(entry);
2085 static void AddCode(
const char* name, Code code, SharedFunctionInfo* shared,
2086 LineInfo* lineinfo) {
2087 DisallowHeapAllocation no_gc;
2089 CodeMap* code_map = GetCodeMap();
2091 range.start = code->address();
2092 range.end = code->address() + code->CodeSize();
2093 RemoveJITCodeEntries(code_map, range);
2095 CodeDescription code_desc(name, code, shared, lineinfo);
2097 if (!FLAG_gdbjit_full && !code_desc.IsLineInfoAvailable()) {
2102 AddUnwindInfo(&code_desc);
2103 Isolate* isolate = code->GetIsolate();
2104 JITCodeEntry* entry = CreateELFObject(&code_desc, isolate);
2108 const char* name_hint =
nullptr;
2109 bool should_dump =
false;
2110 if (FLAG_gdbjit_dump) {
2111 if (strlen(FLAG_gdbjit_dump_filter) == 0) {
2114 }
else if (name !=
nullptr) {
2115 name_hint = strstr(name, FLAG_gdbjit_dump_filter);
2116 should_dump = (name_hint !=
nullptr);
2119 AddJITCodeEntry(code_map, range, entry, should_dump, name_hint);
2123 void EventHandler(
const v8::JitCodeEvent* event) {
2124 if (!FLAG_gdbjit)
return;
2125 if (event->code_type != v8::JitCodeEvent::JIT_CODE)
return;
2126 base::MutexGuard lock_guard(mutex.Pointer());
2127 switch (event->type) {
2128 case v8::JitCodeEvent::CODE_ADDED: {
2129 Address addr =
reinterpret_cast<Address
>(
event->code_start);
2130 Isolate* isolate =
reinterpret_cast<Isolate*
>(
event->isolate);
2131 Code code = isolate->heap()->GcSafeFindCodeForInnerPointer(addr);
2132 LineInfo* lineinfo = GetLineInfo(addr);
2133 EmbeddedVector<char, 256> buffer;
2134 StringBuilder builder(buffer.start(), buffer.length());
2135 builder.AddSubstring(event->name.str, static_cast<int>(event->name.len));
2137 SharedFunctionInfo* shared =
event->script.IsEmpty()
2139 : *Utils::OpenHandle(*event->script);
2140 AddCode(builder.Finalize(), code, shared, lineinfo);
2143 case v8::JitCodeEvent::CODE_MOVED:
2147 case v8::JitCodeEvent::CODE_REMOVED:
2151 case v8::JitCodeEvent::CODE_ADD_LINE_POS_INFO: {
2152 LineInfo* line_info =
reinterpret_cast<LineInfo*
>(
event->user_data);
2153 line_info->SetPosition(static_cast<intptr_t>(event->line_info.offset),
2154 static_cast<int>(event->line_info.pos),
2155 event->line_info.position_type ==
2156 v8::JitCodeEvent::STATEMENT_POSITION);
2159 case v8::JitCodeEvent::CODE_START_LINE_INFO_RECORDING: {
2160 v8::JitCodeEvent* mutable_event =
const_cast<v8::JitCodeEvent*
>(event);
2161 mutable_event->user_data =
new LineInfo();
2164 case v8::JitCodeEvent::CODE_END_LINE_INFO_RECORDING: {
2165 LineInfo* line_info =
reinterpret_cast<LineInfo*
>(
event->user_data);
2166 PutLineInfo(reinterpret_cast<Address>(event->code_start), line_info);