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

Unified Diff: src/gdb-jit.cc

Issue 6371011: Ensures that GDB prints stacktraces correctly for x64 builds when debugging t... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 9 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: src/gdb-jit.cc
===================================================================
--- src/gdb-jit.cc (revision 6445)
+++ src/gdb-jit.cc (working copy)
@@ -201,6 +201,7 @@
TYPE_SHLIB = 10,
TYPE_DYNSYM = 11,
TYPE_LOPROC = 0x70000000,
+ TYPE_X86_64_UNWIND = 0x70000001,
TYPE_HIPROC = 0x7fffffff,
TYPE_LOUSER = 0x80000000,
TYPE_HIUSER = 0xffffffff
@@ -1166,5 +1167,264 @@
}
+#ifdef V8_TARGET_ARCH_X64
+
+
+class UnwindInfoSection : public ELFSection {
+ public:
+ explicit UnwindInfoSection(UnwindInfoInterface::UnwindInformation *);
+ explicit UnwindInfoSection(uintptr_t begin, uintptr_t end);
Vyacheslav Egorov (Chromium) 2011/01/25 12:50:11 2 argument constructors don't need explicit.
+ virtual bool WriteBody(Writer *w);
+
+ private:
+ UnwindInfoInterface::UnwindInformation *info_;
+ uintptr_t begin_, length_;
Vyacheslav Egorov (Chromium) 2011/01/25 12:50:11 uintptr_t begin_; uintptr_t length_;
+ bool is_code_stub_;
+
+ // DWARF3 Specification, Table 7.23
+ enum CFIInstructions {
+ DW_CFA_ADVANCE_LOC = 0X40,
Vyacheslav Egorov (Chromium) 2011/01/25 12:50:11 style nit: 0X -> 0x
+ DW_CFA_OFFSET = 0X80,
+ DW_CFA_RESTORE = 0XC0,
+ DW_CFA_NOP = 0X00,
+ DW_CFA_SET_LOC = 0X01,
+ DW_CFA_ADVANCE_LOC1 = 0X02,
+ DW_CFA_ADVANCE_LOC2 = 0X03,
+ DW_CFA_ADVANCE_LOC4 = 0X04,
+ DW_CFA_OFFSET_EXTENDED = 0X05,
+ DW_CFA_RESTORE_EXTENDED = 0X06,
+ DW_CFA_UNDEFINED = 0X07,
+ DW_CFA_SAME_VALUE = 0X08,
+ DW_CFA_REGISTER = 0X09,
+ DW_CFA_REMEMBER_STATE = 0X0A,
+ DW_CFA_RESTORE_STATE = 0X0B,
+ DW_CFA_DEF_CFA = 0X0C,
+ DW_CFA_DEF_CFA_REGISTER = 0X0D,
+ DW_CFA_DEF_CFA_OFFSET = 0X0E,
+
+ DW_CFA_DEF_CFA_EXPRESSION = 0X0F,
+ DW_CFA_EXPRESSION = 0X10,
+ DW_CFA_OFFSET_EXTENDED_SF = 0X11,
+ DW_CFA_DEF_CFA_SF = 0X12,
+ DW_CFA_DEF_CFA_OFFSET_SF = 0X13,
+ DW_CFA_VAL_OFFSET = 0X14,
+ DW_CFA_VAL_OFFSET_SF = 0X15,
+ DW_CFA_VAL_EXPRESSION = 0X16
+ };
+
+ // System V ABI, AMD64 Supplement, Version 0.99.5, Figure 3.36
+ enum RegisterMapping {
+ // Only the relevant ones have been added to reduce clutter.
+ AMD64_RBP = 6,
+ AMD64_RSP = 7,
+ AMD64_RA = 16
+ };
+
+ enum CFIConstants {
+ CIE_ID = 0,
+ CIE_VERSION = 1,
+ CODE_ALIGN_FACTOR = 1,
+ DATA_ALIGN_FACTOR = 1,
+ RETURN_ADDRESS_REGISTER = AMD64_RA
+ };
+};
+
+
+UnwindInfoSection::UnwindInfoSection(UnwindInfoInterface::UnwindInformation
Vyacheslav Egorov (Chromium) 2011/01/25 12:50:11 I think the right way to format this will be Unw
+ *info)
+ : ELFSection(".eh_frame", TYPE_X86_64_UNWIND, 1), info_(info),
Vyacheslav Egorov (Chromium) 2011/01/25 12:50:11 either all on a single line or each initializer on
+ is_code_stub_(false) { }
+
+
+UnwindInfoSection::UnwindInfoSection(uintptr_t begin, uintptr_t length)
+ : ELFSection(".eh_frame", TYPE_X86_64_UNWIND, 1), begin_(begin),
Vyacheslav Egorov (Chromium) 2011/01/25 12:50:11 ditto
+ length_(length), is_code_stub_(true) { }
+
+
+bool UnwindInfoSection::WriteBody(Writer *w) {
+ Writer::Slot<uint32_t> cie_length_slot = w->CreateSlotHere<uint32_t>();
+ uint32_t cie_position = w->position(), align;
+
+ // Write out the CIE header. Currently no 'common instructions' are
+ // emitted onto the CIE; every FDE has its own set of instructions.
+
+ w->Write<uint32_t>(CIE_ID);
+ w->Write<uint8_t>(CIE_VERSION);
+ w->Write<uint8_t>(0); // Augmentation string.
+ w->WriteSLEB128(CODE_ALIGN_FACTOR);
+ w->WriteSLEB128(DATA_ALIGN_FACTOR);
+ w->Write<uint8_t>(RETURN_ADDRESS_REGISTER);
+
+ align = (w->position() - cie_position) % kPointerSize;
+ if (align) {
Vyacheslav Egorov (Chromium) 2011/01/25 12:50:11 We don't rely on implicit int->bool convertions, s
+ for (uint32_t i = 0; i < (kPointerSize - align); i++) {
+ w->Write<uint8_t>(DW_CFA_NOP);
+ }
+ }
+ ASSERT((w->position() - cie_position) % kPointerSize == 0);
+ cie_length_slot.set(w->position() - cie_position);
+
+ Writer::Slot<uint32_t> fde_length_slot = w->CreateSlotHere<uint32_t>();
+ int fde_position = w->position();
+ w->Write<int32_t>(fde_position - cie_position + 4); // Pointer to CIE
+
+ // The (only) FDE for this function
+
+ if (!is_code_stub_) {
+ w->Write<uintptr_t>(info_->begin_);
+ w->Write<uintptr_t>
+ (info_->state_offsets_[UnwindInfoInterface::UNWIND_STATE_AFTER_RETURN]);
+
+ // The CFA is the frame-pointer of the current function. This seemed the
+ // most straightforward since (it seems) both the full-codegen and the
+ // classic codegen maintain the frame-pointer.
+
+ // -- The first state, just after the control has been transferred to the
Vyacheslav Egorov (Chromium) 2011/01/25 12:50:11 Can you split this into four different functions f
+ // -- the function.
+
+ // RBP for this function will be the value of RSP after pushing the RBP
+ // for the previous function. The previous RBP has not been pushed yet.
+ w->Write<uint8_t>(DW_CFA_DEF_CFA_SF);
+ w->WriteULEB128(AMD64_RSP);
+ w->WriteSLEB128(-kPointerSize);
+
+ // The RA is stored at location CFA + kCallerPCOffset. This is an invariant,
+ // and hence omitted from the next states.
+ w->Write<uint8_t>(DW_CFA_OFFSET_EXTENDED);
+ w->WriteULEB128(AMD64_RA);
+ w->WriteSLEB128(StandardFrameConstants::kCallerPCOffset);
+
+ // The RBP of the previous function is still in RBP.
+ w->Write<uint8_t>(DW_CFA_SAME_VALUE);
+ w->WriteULEB128(AMD64_RBP);
+
+ // Last location described by this entry.
+ w->Write<uint8_t>(DW_CFA_SET_LOC);
+ w->Write<uint64_t>
+ (info_->begin_ + info_->state_offsets_
+ [UnwindInfoInterface::UNWIND_STATE_AFTER_RBP_PUSH]);
+
+ // -- The second state, just after RBP has been pushed.
+
+ // RBP / CFA for this function is now the current RSP, so just set the
+ // offset from the previous rule (from -8) to 0.
+ w->Write<uint8_t>(DW_CFA_DEF_CFA_OFFSET);
+ w->WriteULEB128(0);
+
+ // The previous RBP is stored at CFA + kCallerFPOffset. This is an invariant
+ // in this and the next state, and hence omitted in the next state.
+ w->Write<uint8_t>(DW_CFA_OFFSET_EXTENDED);
+ w->WriteULEB128(AMD64_RBP);
+ w->WriteSLEB128(StandardFrameConstants::kCallerFPOffset);
+
+ // Last location described by this entry.
+ w->Write<uint8_t>(DW_CFA_SET_LOC);
+ w->Write<uint64_t>
+ (info_->begin_ + info_->state_offsets_
+ [UnwindInfoInterface::UNWIND_STATE_AFTER_RBP_SET]);
+
+ // -- The third state, after the RBP has been set.
+
+ // The CFA can now directly be set to RBP.
+ w->Write<uint8_t>(DW_CFA_DEF_CFA);
+ w->WriteULEB128(AMD64_RBP);
+ w->WriteULEB128(0);
+
+ // Last location described by this entry.
+ w->Write<uint8_t>(DW_CFA_SET_LOC);
+ w->Write<uint64_t>
+ (info_->begin_ + info_->state_offsets_
+ [UnwindInfoInterface::UNWIND_STATE_AFTER_RBP_POP]);
+
+ // -- The fourth (final) state. The RBP has been popped (just before issuing
+ // a return.
+
+ // The CFA can is now calculated in the same way as in the first state.
+ w->Write<uint8_t>(DW_CFA_DEF_CFA_SF);
+ w->WriteULEB128(AMD64_RSP);
+ w->WriteSLEB128(-kPointerSize);
+
+ // The RBP
+ w->Write<uint8_t>(DW_CFA_OFFSET_EXTENDED);
+ w->WriteULEB128(AMD64_RBP);
+ w->WriteSLEB128(StandardFrameConstants::kCallerFPOffset);
+
+ // Last location described by this entry.
+ w->Write<uint8_t>(DW_CFA_SET_LOC);
+ w->Write<uint64_t>
+ (info_->begin_ +
+ info_->state_offsets_[UnwindInfoInterface::UNWIND_STATE_AFTER_RETURN]);
+ } else {
+ // This is a code-stub. Unwind information for code-stubs is not divided
+ // into stages, we just tell GDB to unwind using the frame pointer.
+ w->Write<uintptr_t>(begin_);
+ w->Write<uintptr_t>(length_);
+
+ // The CFA is the current function's RBP
+ w->Write<uint8_t>(DW_CFA_DEF_CFA);
+ w->WriteULEB128(AMD64_RBP);
+ w->WriteULEB128(0);
+
+ // These assumptions are not true at the code-stub entry and exit. However,
+ // we are assuming that the debugger will halt code-stubs only at their
+ // call sites.
+ w->Write<uint8_t>(DW_CFA_OFFSET_EXTENDED);
+ w->WriteULEB128(AMD64_RA);
+ w->WriteSLEB128(StandardFrameConstants::kCallerPCOffset);
+
+ w->Write<uint8_t>(DW_CFA_OFFSET_EXTENDED);
+ w->WriteULEB128(AMD64_RBP);
+ w->WriteSLEB128(StandardFrameConstants::kCallerFPOffset);
+
+ // The last location described by this entry.
+ w->Write<uint8_t>(DW_CFA_SET_LOC);
+ w->Write<uint64_t>(begin_ + length_);
+ }
+
+ if ((align = (w->position() - fde_position) % kPointerSize)) {
Vyacheslav Egorov (Chromium) 2011/01/25 12:50:11 I think we usually avoid assignments in expression
+ for (uint32_t i = 0; i < (kPointerSize - align); i++)
+ w->Write<uint8_t>(DW_CFA_NOP);
+ }
+
+ ASSERT((w->position() - fde_position) % kPointerSize == 0);
+ fde_length_slot.set(w->position() - fde_position);
+
+ return true;
+}
+
+
+UnwindInfoInterface::UnwindInformationList *UnwindInfoInterface::info_ = NULL;
+
+
+static void SaveUnwindInfo(UnwindInfoSection *section) {
+ ELF elf;
+ elf.AddSection(section);
+ Writer w(&elf);
+ elf.Write(&w);
+ JITCodeEntry *entry = CreateCodeEntry(w.buffer(), w.position());
+ RegisterCodeEntry(entry);
+}
+
+
+UnwindInfoInterface::~UnwindInfoInterface() {
+ ASSERT(info_ != NULL);
+
+ UnwindInfoSection unwind_section(&info_->data_);
+ SaveUnwindInfo(&unwind_section);
+ UnwindInformationList *tmp = info_->next_;
+ delete info_;
+ info_ = tmp;
+}
+
+
+void UnwindInfoInterface::SetCodeStub(uintptr_t b, uintptr_t l) {
+ UnwindInfoSection unwind_section(b, l);
+ SaveUnwindInfo(&unwind_section);
+}
+
+
+#endif // V8_TARGET_ARCH_X64
+
+
} } // namespace v8::internal
#endif

Powered by Google App Engine
This is Rietveld 408576698