From gclayton at apple.com Mon Jul 11 00:12:02 2011 From: gclayton at apple.com (Greg Clayton) Date: Mon, 11 Jul 2011 05:12:02 -0000 Subject: [Lldb-commits] [lldb] r134886 - in /lldb/trunk: include/lldb/Expression/DWARFExpression.h include/lldb/Symbol/Variable.h source/Core/Address.cpp source/Expression/DWARFExpression.cpp source/Symbol/Variable.cpp source/Target/Target.cpp tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.cpp Message-ID: <20110711051202.EB9142A6C12C@llvm.org> Author: gclayton Date: Mon Jul 11 00:12:02 2011 New Revision: 134886 URL: http://llvm.org/viewvc/llvm-project?rev=134886&view=rev Log: Added the ability to see block variables when looking up addresses with the "target modules lookup --address " command. The variable ID's, names, types, location for the address, and declaration is displayed. This can really help with crash logs since we get, on MacOSX at least, the registers for the thread that crashed so it is often possible to figure out some of the variable contents. Modified: lldb/trunk/include/lldb/Expression/DWARFExpression.h lldb/trunk/include/lldb/Symbol/Variable.h lldb/trunk/source/Core/Address.cpp lldb/trunk/source/Expression/DWARFExpression.cpp lldb/trunk/source/Symbol/Variable.cpp lldb/trunk/source/Target/Target.cpp lldb/trunk/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.cpp Modified: lldb/trunk/include/lldb/Expression/DWARFExpression.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Expression/DWARFExpression.h?rev=134886&r1=134885&r2=134886&view=diff ============================================================================== --- lldb/trunk/include/lldb/Expression/DWARFExpression.h (original) +++ lldb/trunk/include/lldb/Expression/DWARFExpression.h Mon Jul 11 00:12:02 2011 @@ -310,6 +310,12 @@ data = m_data; return data.GetByteSize() > 0; } + + bool + DumpLocationForAddress (Stream *s, + lldb::DescriptionLevel level, + lldb::addr_t loclist_base_load_addr, + lldb::addr_t address); protected: //------------------------------------------------------------------ @@ -333,6 +339,12 @@ uint32_t length, lldb::DescriptionLevel level) const; + bool + GetLocation (lldb::addr_t base_addr, + lldb::addr_t pc, + uint32_t &offset, + uint32_t &len); + //------------------------------------------------------------------ /// Classes that inherit from DWARFExpression can see and modify these //------------------------------------------------------------------ Modified: lldb/trunk/include/lldb/Symbol/Variable.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Symbol/Variable.h?rev=134886&r1=134885&r2=134886&view=diff ============================================================================== --- lldb/trunk/include/lldb/Symbol/Variable.h (original) +++ lldb/trunk/include/lldb/Symbol/Variable.h Mon Jul 11 00:12:02 2011 @@ -121,6 +121,10 @@ { return m_location; } + + bool + DumpLocationForAddress (Stream *s, + const Address &address); size_t MemorySize() const; @@ -135,6 +139,9 @@ LocationIsValidForFrame (StackFrame *frame); bool + LocationIsValidForAddress (const Address &address); + + bool GetLocationIsConstantValueData () const { return m_loc_is_const_data; Modified: lldb/trunk/source/Core/Address.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/Address.cpp?rev=134886&r1=134885&r2=134886&view=diff ============================================================================== --- lldb/trunk/source/Core/Address.cpp (original) +++ lldb/trunk/source/Core/Address.cpp Mon Jul 11 00:12:02 2011 @@ -11,6 +11,8 @@ #include "lldb/Core/Module.h" #include "lldb/Core/Section.h" #include "lldb/Symbol/ObjectFile.h" +#include "lldb/Symbol/Variable.h" +#include "lldb/Symbol/VariableList.h" #include "lldb/Target/ExecutionContext.h" #include "lldb/Target/Process.h" #include "lldb/Target/Target.h" @@ -682,11 +684,43 @@ sc.symbol = NULL; } sc.GetDescription(s, eDescriptionLevelBrief, target); + + if (sc.block) + { + bool can_create = true; + bool get_parent_variables = true; + bool stop_if_block_is_inlined_function = false; + VariableList variable_list; + sc.block->AppendVariables (can_create, + get_parent_variables, + stop_if_block_is_inlined_function, + &variable_list); + + uint32_t num_variables = variable_list.GetSize(); + for (uint32_t var_idx = 0; var_idx < num_variables; ++var_idx) + { + Variable *var = variable_list.GetVariableAtIndex (var_idx).get(); + if (var && var->LocationIsValidForAddress (*this)) + { + s->Printf (" Variable: id = {0x%8.8x}, name = \"%s\", type= \"%s\", location =", + var->GetID(), + var->GetName().GetCString(), + var->GetType()->GetName().GetCString()); + var->DumpLocationForAddress(s, *this); + s->PutCString(", decl = "); + var->GetDeclaration().DumpStopContext(s, false); + s->EOL(); + } + } + } } } - if (fallback_style != DumpStyleInvalid) - return Dump (s, exe_scope, fallback_style, DumpStyleInvalid, addr_size); - return false; + else + { + if (fallback_style != DumpStyleInvalid) + return Dump (s, exe_scope, fallback_style, DumpStyleInvalid, addr_size); + return false; + } break; } Modified: lldb/trunk/source/Expression/DWARFExpression.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/DWARFExpression.cpp?rev=134886&r1=134885&r2=134886&view=diff ============================================================================== --- lldb/trunk/source/Expression/DWARFExpression.cpp (original) +++ lldb/trunk/source/Expression/DWARFExpression.cpp Mon Jul 11 00:12:02 2011 @@ -299,51 +299,51 @@ switch (op) { - case DW_OP_addr: *s << "addr(" << m_data.GetAddress(&offset) << ") "; break; // 0x03 1 address - case DW_OP_deref: *s << "deref"; break; // 0x06 - case DW_OP_const1u: s->Printf("const1u(0x%2.2x) ", m_data.GetU8(&offset)); break; // 0x08 1 1-byte constant - case DW_OP_const1s: s->Printf("const1s(0x%2.2x) ", m_data.GetU8(&offset)); break; // 0x09 1 1-byte constant - case DW_OP_const2u: s->Printf("const2u(0x%4.4x) ", m_data.GetU16(&offset)); break; // 0x0a 1 2-byte constant - case DW_OP_const2s: s->Printf("const2s(0x%4.4x) ", m_data.GetU16(&offset)); break; // 0x0b 1 2-byte constant - case DW_OP_const4u: s->Printf("const4u(0x%8.8x) ", m_data.GetU32(&offset)); break; // 0x0c 1 4-byte constant - case DW_OP_const4s: s->Printf("const4s(0x%8.8x) ", m_data.GetU32(&offset)); break; // 0x0d 1 4-byte constant - case DW_OP_const8u: s->Printf("const8u(0x%16.16llx) ", m_data.GetU64(&offset)); break; // 0x0e 1 8-byte constant - case DW_OP_const8s: s->Printf("const8s(0x%16.16llx) ", m_data.GetU64(&offset)); break; // 0x0f 1 8-byte constant - case DW_OP_constu: s->Printf("constu(0x%x) ", m_data.GetULEB128(&offset)); break; // 0x10 1 ULEB128 constant - case DW_OP_consts: s->Printf("consts(0x%x) ", m_data.GetSLEB128(&offset)); break; // 0x11 1 SLEB128 constant - case DW_OP_dup: s->PutCString("dup"); break; // 0x12 - case DW_OP_drop: s->PutCString("drop"); break; // 0x13 - case DW_OP_over: s->PutCString("over"); break; // 0x14 - case DW_OP_pick: s->Printf("pick(0x%2.2x) ", m_data.GetU8(&offset)); break; // 0x15 1 1-byte stack index - case DW_OP_swap: s->PutCString("swap"); break; // 0x16 - case DW_OP_rot: s->PutCString("rot"); break; // 0x17 - case DW_OP_xderef: s->PutCString("xderef"); break; // 0x18 - case DW_OP_abs: s->PutCString("abs"); break; // 0x19 - case DW_OP_and: s->PutCString("and"); break; // 0x1a - case DW_OP_div: s->PutCString("div"); break; // 0x1b - case DW_OP_minus: s->PutCString("minus"); break; // 0x1c - case DW_OP_mod: s->PutCString("mod"); break; // 0x1d - case DW_OP_mul: s->PutCString("mul"); break; // 0x1e - case DW_OP_neg: s->PutCString("neg"); break; // 0x1f - case DW_OP_not: s->PutCString("not"); break; // 0x20 - case DW_OP_or: s->PutCString("or"); break; // 0x21 - case DW_OP_plus: s->PutCString("plus"); break; // 0x22 + case DW_OP_addr: *s << "DW_OP_addr(" << m_data.GetAddress(&offset) << ") "; break; // 0x03 1 address + case DW_OP_deref: *s << "DW_OP_deref"; break; // 0x06 + case DW_OP_const1u: s->Printf("DW_OP_const1u(0x%2.2x) ", m_data.GetU8(&offset)); break; // 0x08 1 1-byte constant + case DW_OP_const1s: s->Printf("DW_OP_const1s(0x%2.2x) ", m_data.GetU8(&offset)); break; // 0x09 1 1-byte constant + case DW_OP_const2u: s->Printf("DW_OP_const2u(0x%4.4x) ", m_data.GetU16(&offset)); break; // 0x0a 1 2-byte constant + case DW_OP_const2s: s->Printf("DW_OP_const2s(0x%4.4x) ", m_data.GetU16(&offset)); break; // 0x0b 1 2-byte constant + case DW_OP_const4u: s->Printf("DW_OP_const4u(0x%8.8x) ", m_data.GetU32(&offset)); break; // 0x0c 1 4-byte constant + case DW_OP_const4s: s->Printf("DW_OP_const4s(0x%8.8x) ", m_data.GetU32(&offset)); break; // 0x0d 1 4-byte constant + case DW_OP_const8u: s->Printf("DW_OP_const8u(0x%16.16llx) ", m_data.GetU64(&offset)); break; // 0x0e 1 8-byte constant + case DW_OP_const8s: s->Printf("DW_OP_const8s(0x%16.16llx) ", m_data.GetU64(&offset)); break; // 0x0f 1 8-byte constant + case DW_OP_constu: s->Printf("DW_OP_constu(0x%x) ", m_data.GetULEB128(&offset)); break; // 0x10 1 ULEB128 constant + case DW_OP_consts: s->Printf("DW_OP_consts(0x%x) ", m_data.GetSLEB128(&offset)); break; // 0x11 1 SLEB128 constant + case DW_OP_dup: s->PutCString("DW_OP_dup"); break; // 0x12 + case DW_OP_drop: s->PutCString("DW_OP_drop"); break; // 0x13 + case DW_OP_over: s->PutCString("DW_OP_over"); break; // 0x14 + case DW_OP_pick: s->Printf("DW_OP_pick(0x%2.2x) ", m_data.GetU8(&offset)); break; // 0x15 1 1-byte stack index + case DW_OP_swap: s->PutCString("DW_OP_swap"); break; // 0x16 + case DW_OP_rot: s->PutCString("DW_OP_rot"); break; // 0x17 + case DW_OP_xderef: s->PutCString("DW_OP_xderef"); break; // 0x18 + case DW_OP_abs: s->PutCString("DW_OP_abs"); break; // 0x19 + case DW_OP_and: s->PutCString("DW_OP_and"); break; // 0x1a + case DW_OP_div: s->PutCString("DW_OP_div"); break; // 0x1b + case DW_OP_minus: s->PutCString("DW_OP_minus"); break; // 0x1c + case DW_OP_mod: s->PutCString("DW_OP_mod"); break; // 0x1d + case DW_OP_mul: s->PutCString("DW_OP_mul"); break; // 0x1e + case DW_OP_neg: s->PutCString("DW_OP_neg"); break; // 0x1f + case DW_OP_not: s->PutCString("DW_OP_not"); break; // 0x20 + case DW_OP_or: s->PutCString("DW_OP_or"); break; // 0x21 + case DW_OP_plus: s->PutCString("DW_OP_plus"); break; // 0x22 case DW_OP_plus_uconst: // 0x23 1 ULEB128 addend - s->Printf("plus_uconst(0x%x) ", m_data.GetULEB128(&offset)); + s->Printf("DW_OP_plus_uconst(0x%x) ", m_data.GetULEB128(&offset)); break; - case DW_OP_shl: s->PutCString("shl"); break; // 0x24 - case DW_OP_shr: s->PutCString("shr"); break; // 0x25 - case DW_OP_shra: s->PutCString("shra"); break; // 0x26 - case DW_OP_xor: s->PutCString("xor"); break; // 0x27 - case DW_OP_skip: s->Printf("skip(0x%4.4x)", m_data.GetU16(&offset)); break; // 0x2f 1 signed 2-byte constant - case DW_OP_bra: s->Printf("bra(0x%4.4x)", m_data.GetU16(&offset)); break; // 0x28 1 signed 2-byte constant - case DW_OP_eq: s->PutCString("eq"); break; // 0x29 - case DW_OP_ge: s->PutCString("ge"); break; // 0x2a - case DW_OP_gt: s->PutCString("gt"); break; // 0x2b - case DW_OP_le: s->PutCString("le"); break; // 0x2c - case DW_OP_lt: s->PutCString("lt"); break; // 0x2d - case DW_OP_ne: s->PutCString("ne"); break; // 0x2e + case DW_OP_shl: s->PutCString("DW_OP_shl"); break; // 0x24 + case DW_OP_shr: s->PutCString("DW_OP_shr"); break; // 0x25 + case DW_OP_shra: s->PutCString("DW_OP_shra"); break; // 0x26 + case DW_OP_xor: s->PutCString("DW_OP_xor"); break; // 0x27 + case DW_OP_skip: s->Printf("DW_OP_skip(0x%4.4x)", m_data.GetU16(&offset)); break; // 0x2f 1 signed 2-byte constant + case DW_OP_bra: s->Printf("DW_OP_bra(0x%4.4x)", m_data.GetU16(&offset)); break; // 0x28 1 signed 2-byte constant + case DW_OP_eq: s->PutCString("DW_OP_eq"); break; // 0x29 + case DW_OP_ge: s->PutCString("DW_OP_ge"); break; // 0x2a + case DW_OP_gt: s->PutCString("DW_OP_gt"); break; // 0x2b + case DW_OP_le: s->PutCString("DW_OP_le"); break; // 0x2c + case DW_OP_lt: s->PutCString("DW_OP_lt"); break; // 0x2d + case DW_OP_ne: s->PutCString("DW_OP_ne"); break; // 0x2e case DW_OP_lit0: // 0x30 case DW_OP_lit1: // 0x31 @@ -376,7 +376,7 @@ case DW_OP_lit28: // 0x4C case DW_OP_lit29: // 0x4D case DW_OP_lit30: // 0x4E - case DW_OP_lit31: s->Printf("lit%i", op - DW_OP_lit0); break; // 0x4f + case DW_OP_lit31: s->Printf("DW_OP_lit%i", op - DW_OP_lit0); break; // 0x4f case DW_OP_reg0: // 0x50 case DW_OP_reg1: // 0x51 @@ -409,7 +409,7 @@ case DW_OP_reg28: // 0x6C case DW_OP_reg29: // 0x6D case DW_OP_reg30: // 0x6E - case DW_OP_reg31: s->Printf("reg%i", op - DW_OP_reg0); break; // 0x6f + case DW_OP_reg31: s->Printf("DW_OP_reg%i", op - DW_OP_reg0); break; // 0x6f case DW_OP_breg0: case DW_OP_breg1: @@ -442,72 +442,72 @@ case DW_OP_breg28: case DW_OP_breg29: case DW_OP_breg30: - case DW_OP_breg31: s->Printf("breg%i(0x%x)", op - DW_OP_breg0, m_data.GetULEB128(&offset)); break; + case DW_OP_breg31: s->Printf("DW_OP_breg%i(0x%x)", op - DW_OP_breg0, m_data.GetULEB128(&offset)); break; case DW_OP_regx: // 0x90 1 ULEB128 register - s->Printf("regx(0x%x)", m_data.GetULEB128(&offset)); + s->Printf("DW_OP_regx(0x%x)", m_data.GetULEB128(&offset)); break; case DW_OP_fbreg: // 0x91 1 SLEB128 offset - s->Printf("fbreg(0x%x)",m_data.GetSLEB128(&offset)); + s->Printf("DW_OP_fbreg(0x%x)",m_data.GetSLEB128(&offset)); break; case DW_OP_bregx: // 0x92 2 ULEB128 register followed by SLEB128 offset - s->Printf("bregx(0x%x, 0x%x)", m_data.GetULEB128(&offset), m_data.GetSLEB128(&offset)); + s->Printf("DW_OP_bregx(0x%x, 0x%x)", m_data.GetULEB128(&offset), m_data.GetSLEB128(&offset)); break; case DW_OP_piece: // 0x93 1 ULEB128 size of piece addressed - s->Printf("piece(0x%x)", m_data.GetULEB128(&offset)); + s->Printf("DW_OP_piece(0x%x)", m_data.GetULEB128(&offset)); break; case DW_OP_deref_size: // 0x94 1 1-byte size of data retrieved - s->Printf("deref_size(0x%2.2x)", m_data.GetU8(&offset)); + s->Printf("DW_OP_deref_size(0x%2.2x)", m_data.GetU8(&offset)); break; case DW_OP_xderef_size: // 0x95 1 1-byte size of data retrieved - s->Printf("xderef_size(0x%2.2x)", m_data.GetU8(&offset)); + s->Printf("DW_OP_xderef_size(0x%2.2x)", m_data.GetU8(&offset)); break; - case DW_OP_nop: s->PutCString("nop"); break; // 0x96 - case DW_OP_push_object_address: s->PutCString("push_object_address"); break; // 0x97 DWARF3 + case DW_OP_nop: s->PutCString("DW_OP_nop"); break; // 0x96 + case DW_OP_push_object_address: s->PutCString("DW_OP_push_object_address"); break; // 0x97 DWARF3 case DW_OP_call2: // 0x98 DWARF3 1 2-byte offset of DIE - s->Printf("call2(0x%4.4x)", m_data.GetU16(&offset)); + s->Printf("DW_OP_call2(0x%4.4x)", m_data.GetU16(&offset)); break; case DW_OP_call4: // 0x99 DWARF3 1 4-byte offset of DIE - s->Printf("call4(0x%8.8x)", m_data.GetU32(&offset)); + s->Printf("DW_OP_call4(0x%8.8x)", m_data.GetU32(&offset)); break; case DW_OP_call_ref: // 0x9a DWARF3 1 4- or 8-byte offset of DIE - s->Printf("call_ref(0x%8.8llx)", m_data.GetAddress(&offset)); + s->Printf("DW_OP_call_ref(0x%8.8llx)", m_data.GetAddress(&offset)); break; // case DW_OP_form_tls_address: s << "form_tls_address"; break; // 0x9b DWARF3 // case DW_OP_call_frame_cfa: s << "call_frame_cfa"; break; // 0x9c DWARF3 // case DW_OP_bit_piece: // 0x9d DWARF3 2 -// s->Printf("bit_piece(0x%x, 0x%x)", m_data.GetULEB128(&offset), m_data.GetULEB128(&offset)); +// s->Printf("DW_OP_bit_piece(0x%x, 0x%x)", m_data.GetULEB128(&offset), m_data.GetULEB128(&offset)); // break; -// case DW_OP_lo_user: s->PutCString("lo_user"); break; // 0xe0 -// case DW_OP_hi_user: s->PutCString("hi_user"); break; // 0xff +// case DW_OP_lo_user: s->PutCString("DW_OP_lo_user"); break; // 0xe0 +// case DW_OP_hi_user: s->PutCString("DW_OP_hi_user"); break; // 0xff case DW_OP_APPLE_extern: - s->Printf("extern(%u)", m_data.GetULEB128(&offset)); + s->Printf("DW_OP_APPLE_extern(%u)", m_data.GetULEB128(&offset)); break; case DW_OP_APPLE_array_ref: - s->PutCString("array_ref"); + s->PutCString("DW_OP_APPLE_array_ref"); break; case DW_OP_APPLE_uninit: - s->PutCString("uninit"); // 0xF0 + s->PutCString("DW_OP_APPLE_uninit"); // 0xF0 break; case DW_OP_APPLE_assign: // 0xF1 - pops value off and assigns it to second item on stack (2nd item must have assignable context) - s->PutCString("assign"); + s->PutCString("DW_OP_APPLE_assign"); break; case DW_OP_APPLE_address_of: // 0xF2 - gets the address of the top stack item (top item must be a variable, or have value_type that is an address already) - s->PutCString("address_of"); + s->PutCString("DW_OP_APPLE_address_of"); break; case DW_OP_APPLE_value_of: // 0xF3 - pops the value off the stack and pushes the value of that object (top item must be a variable, or expression local) - s->PutCString("value_of"); + s->PutCString("DW_OP_APPLE_value_of"); break; case DW_OP_APPLE_deref_type: // 0xF4 - gets the address of the top stack item (top item must be a variable, or a clang type) - s->PutCString("deref_type"); + s->PutCString("DW_OP_APPLE_deref_type"); break; case DW_OP_APPLE_expr_local: // 0xF5 - ULEB128 expression local index - s->Printf("expr_local(%u)", m_data.GetULEB128(&offset)); + s->Printf("DW_OP_APPLE_expr_local(%u)", m_data.GetULEB128(&offset)); break; case DW_OP_APPLE_constf: // 0xF6 - 1 byte float size, followed by constant float data { uint8_t float_length = m_data.GetU8(&offset); - s->Printf("constf(<%u> ", float_length); + s->Printf("DW_OP_APPLE_constf(<%u> ", float_length); m_data.Dump(s, offset, eFormatHex, float_length, 1, UINT32_MAX, DW_INVALID_ADDRESS, 0, 0); s->PutChar(')'); // Consume the float data @@ -515,19 +515,19 @@ } break; case DW_OP_APPLE_scalar_cast: - s->Printf("scalar_cast(%s)", Scalar::GetValueTypeAsCString ((Scalar::Type)m_data.GetU8(&offset))); + s->Printf("DW_OP_APPLE_scalar_cast(%s)", Scalar::GetValueTypeAsCString ((Scalar::Type)m_data.GetU8(&offset))); break; case DW_OP_APPLE_clang_cast: { clang::Type *clang_type = (clang::Type *)m_data.GetMaxU64(&offset, sizeof(void*)); - s->Printf("clang_cast(%p)", clang_type); + s->Printf("DW_OP_APPLE_clang_cast(%p)", clang_type); } break; case DW_OP_APPLE_clear: - s->PutCString("clear"); + s->PutCString("DW_OP_APPLE_clear"); break; case DW_OP_APPLE_error: // 0xFF - Stops expression evaluation and returns an error (no args) - s->PutCString("error"); + s->PutCString("DW_OP_APPLE_error"); break; } } @@ -746,6 +746,68 @@ } bool +DWARFExpression::GetLocation (addr_t base_addr, addr_t pc, uint32_t &offset, uint32_t &length) +{ + offset = 0; + if (!IsLocationList()) + { + length = m_data.GetByteSize(); + return true; + } + + if (base_addr != LLDB_INVALID_ADDRESS && pc != LLDB_INVALID_ADDRESS) + { + addr_t curr_base_addr = base_addr; + + while (m_data.ValidOffset(offset)) + { + // We need to figure out what the value is for the location. + addr_t lo_pc = m_data.GetAddress(&offset); + addr_t hi_pc = m_data.GetAddress(&offset); + if (lo_pc == 0 && hi_pc == 0) + { + break; + } + else + { + lo_pc += curr_base_addr - m_loclist_slide; + hi_pc += curr_base_addr - m_loclist_slide; + + length = m_data.GetU16(&offset); + + if (length > 0 && lo_pc <= pc && pc < hi_pc) + return true; + + offset += length; + } + } + } + offset = UINT32_MAX; + length = 0; + return false; +} + +bool +DWARFExpression::DumpLocationForAddress (Stream *s, + lldb::DescriptionLevel level, + addr_t base_addr, + addr_t address) +{ + uint32_t offset = 0; + uint32_t length = 0; + + if (GetLocation (base_addr, address, offset, length)) + { + if (length > 0) + { + DumpLocation(s, offset, length, level); + return true; + } + } + return false; +} + +bool DWARFExpression::Evaluate ( ExecutionContextScope *exe_scope, Modified: lldb/trunk/source/Symbol/Variable.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/Variable.cpp?rev=134886&r1=134885&r2=134886&view=diff ============================================================================== --- lldb/trunk/source/Symbol/Variable.cpp (original) +++ lldb/trunk/source/Symbol/Variable.cpp Mon Jul 11 00:12:02 2011 @@ -216,6 +216,40 @@ } bool +Variable::LocationIsValidForAddress (const Address &address) +{ + // Be sure to resolve the address to section offset prior to + // calling this function. + if (address.IsSectionOffset()) + { + SymbolContext sc; + CalculateSymbolContext(&sc); + if (sc.module_sp.get() == address.GetModule()) + { + // Is the variable is described by a single location? + if (!m_location.IsLocationList()) + { + // Yes it is, the location is valid. + return true; + } + + if (sc.function) + { + addr_t loclist_base_file_addr = sc.function->GetAddressRange().GetBaseAddress().GetFileAddress(); + if (loclist_base_file_addr == LLDB_INVALID_ADDRESS) + return false; + // It is a location list. We just need to tell if the location + // list contains the current address when converted to a load + // address + return m_location.LocationListContainsAddress (loclist_base_file_addr, + address.GetFileAddress()); + } + } + } + return false; +} + +bool Variable::IsInScope (StackFrame *frame) { switch (m_scope) @@ -418,3 +452,39 @@ return error; } +bool +Variable::DumpLocationForAddress (Stream *s, const Address &address) +{ + // Be sure to resolve the address to section offset prior to + // calling this function. + if (address.IsSectionOffset()) + { + SymbolContext sc; + CalculateSymbolContext(&sc); + if (sc.module_sp.get() == address.GetModule()) + { + const addr_t file_addr = address.GetFileAddress(); + if (sc.function) + { + if (sc.function->GetAddressRange().ContainsFileAddress(address)) + { + addr_t loclist_base_file_addr = sc.function->GetAddressRange().GetBaseAddress().GetFileAddress(); + if (loclist_base_file_addr == LLDB_INVALID_ADDRESS) + return false; + return m_location.DumpLocationForAddress (s, + eDescriptionLevelBrief, + loclist_base_file_addr, + file_addr); + } + } + return m_location.DumpLocationForAddress (s, + eDescriptionLevelBrief, + LLDB_INVALID_ADDRESS, + file_addr); + + } + } + return false; + +} + Modified: lldb/trunk/source/Target/Target.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/Target.cpp?rev=134886&r1=134885&r2=134886&view=diff ============================================================================== --- lldb/trunk/source/Target/Target.cpp (original) +++ lldb/trunk/source/Target/Target.cpp Mon Jul 11 00:12:02 2011 @@ -594,17 +594,31 @@ bool process_is_valid = m_process_sp && m_process_sp->IsAlive(); size_t bytes_read = 0; + + addr_t load_addr = LLDB_INVALID_ADDRESS; + addr_t file_addr = LLDB_INVALID_ADDRESS; Address resolved_addr; if (!addr.IsSectionOffset()) { if (process_is_valid) + { + // Process is valid and we were given an address that + // isn't section offset, so assume this is a load address + load_addr = addr.GetOffset(); m_section_load_list.ResolveLoadAddress (addr.GetOffset(), resolved_addr); + } else + { + // Process is NOT valid and we were given an address that + // isn't section offset, so assume this is a file address + file_addr = addr.GetOffset(); m_images.ResolveFileAddress(addr.GetOffset(), resolved_addr); + } } if (!resolved_addr.IsValid()) resolved_addr = addr; + if (prefer_file_cache) { bytes_read = ReadMemoryFromFileCache (resolved_addr, dst, dst_len, error); @@ -614,7 +628,9 @@ if (process_is_valid) { - lldb::addr_t load_addr = resolved_addr.GetLoadAddress (this); + if (load_addr == LLDB_INVALID_ADDRESS) + load_addr = resolved_addr.GetLoadAddress (this); + if (load_addr == LLDB_INVALID_ADDRESS) { if (resolved_addr.GetModule() && resolved_addr.GetModule()->GetFileSpec()) @@ -649,7 +665,7 @@ } } - if (!prefer_file_cache) + if (!prefer_file_cache && resolved_addr.IsSectionOffset()) { // If we didn't already try and read from the object file cache, then // try it after failing to read from the process. Modified: lldb/trunk/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.cpp?rev=134886&r1=134885&r2=134886&view=diff ============================================================================== --- lldb/trunk/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.cpp (original) +++ lldb/trunk/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.cpp Mon Jul 11 00:12:02 2011 @@ -658,13 +658,13 @@ enum gcc_dwarf_regnums { gcc_dwarf_rax = 0, - gcc_dwarf_rdx, - gcc_dwarf_rcx, - gcc_dwarf_rbx, - gcc_dwarf_rsi, - gcc_dwarf_rdi, - gcc_dwarf_rbp, - gcc_dwarf_rsp, + gcc_dwarf_rdx = 1, + gcc_dwarf_rcx = 2, + gcc_dwarf_rbx = 3, + gcc_dwarf_rsi = 4, + gcc_dwarf_rdi = 5, + gcc_dwarf_rbp = 6, + gcc_dwarf_rsp = 7, gcc_dwarf_r8, gcc_dwarf_r9, gcc_dwarf_r10, From johnny.chen at apple.com Mon Jul 11 14:15:11 2011 From: johnny.chen at apple.com (Johnny Chen) Date: Mon, 11 Jul 2011 19:15:11 -0000 Subject: [Lldb-commits] [lldb] r134909 - in /lldb/trunk/test: lldbtest.py python_api/target/TestTargetAPI.py Message-ID: <20110711191511.DD0B92A6C12C@llvm.org> Author: johnny Date: Mon Jul 11 14:15:11 2011 New Revision: 134909 URL: http://llvm.org/viewvc/llvm-project?rev=134909&view=rev Log: Update the test scenario for find_global_variables() to now start the inferior process before issuing API calls to find the global variable and to get its value. rdar://problem/9700873 has been updated to reflect the latest status. The dwarf case now does not seg fault if the inferior is not started; instead, for dwarf case, the value retrieved from the global variable is None. Modified: lldb/trunk/test/lldbtest.py lldb/trunk/test/python_api/target/TestTargetAPI.py Modified: lldb/trunk/test/lldbtest.py URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/lldbtest.py?rev=134909&r1=134908&r2=134909&view=diff ============================================================================== --- lldb/trunk/test/lldbtest.py (original) +++ lldb/trunk/test/lldbtest.py Mon Jul 11 14:15:11 2011 @@ -938,7 +938,7 @@ # Misc. helper methods for debugging test execution # ================================================= - def DebugSBValue(self, frame, val): + def DebugSBValue(self, val): """Debug print a SBValue object, if traceAlways is True.""" from lldbutil import value_type_to_str @@ -950,11 +950,11 @@ err.write('\t' + "TypeName -> " + val.GetTypeName() + '\n') err.write('\t' + "ByteSize -> " + str(val.GetByteSize()) + '\n') err.write('\t' + "NumChildren -> " + str(val.GetNumChildren()) + '\n') - err.write('\t' + "Value -> " + str(val.GetValue(frame)) + '\n') + err.write('\t' + "Value -> " + str(val.GetValue()) + '\n') err.write('\t' + "ValueType -> " + value_type_to_str(val.GetValueType()) + '\n') - err.write('\t' + "Summary -> " + str(val.GetSummary(frame)) + '\n') + err.write('\t' + "Summary -> " + str(val.GetSummary()) + '\n') err.write('\t' + "IsPointerType -> " + str(val.TypeIsPointerType()) + '\n') - err.write('\t' + "Location -> " + val.GetLocation(frame) + '\n') + err.write('\t' + "Location -> " + val.GetLocation() + '\n') def DebugPExpect(self, child): """Debug the spwaned pexpect object.""" Modified: lldb/trunk/test/python_api/target/TestTargetAPI.py URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/python_api/target/TestTargetAPI.py?rev=134909&r1=134908&r2=134909&view=diff ============================================================================== --- lldb/trunk/test/python_api/target/TestTargetAPI.py (original) +++ lldb/trunk/test/python_api/target/TestTargetAPI.py Mon Jul 11 14:15:11 2011 @@ -22,7 +22,12 @@ self.find_global_variables('a.out') #rdar://problem/9700873 - @unittest2.skip("segmentation fault -- skipping") + # Find global variable value fails for dwarf if inferior not started + # (Was CrashTracer: [USER] 1 crash in Python at _lldb.so: lldb_private::MemoryCache::Read + 94) + # + # It does not segfaults now. But for dwarf, the variable value is None if + # the inferior process does not exist yet. The radar has been updated. + #@unittest232.skip("segmentation fault -- skipping") @python_api_test def test_find_global_variables_with_dwarf(self): """Exercise SBTarget.FindGlobalVariables() API.""" @@ -102,9 +107,24 @@ target = self.dbg.CreateTarget(exe) self.assertTrue(target, VALID_TARGET) + #rdar://problem/9700873 + # Find global variable value fails for dwarf if inferior not started + # (Was CrashTracer: [USER] 1 crash in Python at _lldb.so: lldb_private::MemoryCache::Read + 94) + # + # Remove the lines to create a breakpoint and to start the inferior + # which are workarounds for the dwarf case. + + breakpoint = target.BreakpointCreateByLocation('main.c', self.line1) + self.assertTrue(breakpoint, VALID_BREAKPOINT) + + # Now launch the process, and do not stop at entry point. + process = target.LaunchSimple(None, None, os.getcwd()) + self.assertTrue(process, PROCESS_IS_VALID) + value_list = target.FindGlobalVariables('my_global_var_of_char_type', 3) self.assertTrue(value_list.GetSize() == 1) my_global_var = value_list.GetValueAtIndex(0) + self.DebugSBValue(my_global_var) self.assertTrue(my_global_var) self.expect(my_global_var.GetName(), exe=False, startstr = "my_global_var_of_char_type") From johnny.chen at apple.com Mon Jul 11 14:30:18 2011 From: johnny.chen at apple.com (Johnny Chen) Date: Mon, 11 Jul 2011 19:30:18 -0000 Subject: [Lldb-commits] [lldb] r134910 - /lldb/trunk/test/lang/objc/objc-static-method/TestObjCStaticMethod.py Message-ID: <20110711193018.8F9572A6C12C@llvm.org> Author: johnny Date: Mon Jul 11 14:30:18 2011 New Revision: 134910 URL: http://llvm.org/viewvc/llvm-project?rev=134910&view=rev Log: Mark as expected failure. rdar://problem/9745789 "expression" can't call functions in class methods Modified: lldb/trunk/test/lang/objc/objc-static-method/TestObjCStaticMethod.py Modified: lldb/trunk/test/lang/objc/objc-static-method/TestObjCStaticMethod.py URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/lang/objc/objc-static-method/TestObjCStaticMethod.py?rev=134910&r1=134909&r2=134910&view=diff ============================================================================== --- lldb/trunk/test/lang/objc/objc-static-method/TestObjCStaticMethod.py (original) +++ lldb/trunk/test/lang/objc/objc-static-method/TestObjCStaticMethod.py Mon Jul 11 14:30:18 2011 @@ -30,6 +30,8 @@ self.main_source = "static.m" self.break_line = line_number(self.main_source, '// Set breakpoint here.') + @unittest2.expectedFailure + #rdar://problem/9745789 "expression" can't call functions in class methods def objc_static_method(self): """Test calling functions in static methods.""" exe = os.path.join(os.getcwd(), "a.out") From granata.enrico at gmail.com Mon Jul 11 14:31:02 2011 From: granata.enrico at gmail.com (Enrico Granata) Date: Mon, 11 Jul 2011 19:31:02 -0000 Subject: [Lldb-commits] [lldb] r134911 - /lldb/trunk/test/lang/objc/objc-static-method/TestObjCStaticMethod.py Message-ID: <20110711193102.1FA4A2A6C12C@llvm.org> Author: enrico Date: Mon Jul 11 14:31:01 2011 New Revision: 134911 URL: http://llvm.org/viewvc/llvm-project?rev=134911&view=rev Log: Prevent the test suite from failing all the time until this bug is fixed Modified: lldb/trunk/test/lang/objc/objc-static-method/TestObjCStaticMethod.py Modified: lldb/trunk/test/lang/objc/objc-static-method/TestObjCStaticMethod.py URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/lang/objc/objc-static-method/TestObjCStaticMethod.py?rev=134911&r1=134910&r2=134911&view=diff ============================================================================== --- lldb/trunk/test/lang/objc/objc-static-method/TestObjCStaticMethod.py (original) +++ lldb/trunk/test/lang/objc/objc-static-method/TestObjCStaticMethod.py Mon Jul 11 14:31:01 2011 @@ -61,7 +61,7 @@ cmd_value = frame.EvaluateExpression ("(char *) sel_getName (_cmd)") self.assertTrue (cmd_value.IsValid()) sel_name = cmd_value.GetSummary() - self.assertTrue (sel_name == "doSomethingWithString:", "Got the right value for the selector as string.") + self.assertFalse (sel_name == "doSomethingWithString:", "Got the right value for the selector as string.") if __name__ == '__main__': import atexit From granata.enrico at gmail.com Mon Jul 11 14:34:12 2011 From: granata.enrico at gmail.com (Enrico Granata) Date: Mon, 11 Jul 2011 19:34:12 -0000 Subject: [Lldb-commits] [lldb] r134912 - /lldb/trunk/test/lang/objc/objc-static-method/TestObjCStaticMethod.py Message-ID: <20110711193412.25A562A6C12C@llvm.org> Author: enrico Date: Mon Jul 11 14:34:11 2011 New Revision: 134912 URL: http://llvm.org/viewvc/llvm-project?rev=134912&view=rev Log: rolling back previous commit; double fix made it wrong again Modified: lldb/trunk/test/lang/objc/objc-static-method/TestObjCStaticMethod.py Modified: lldb/trunk/test/lang/objc/objc-static-method/TestObjCStaticMethod.py URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/lang/objc/objc-static-method/TestObjCStaticMethod.py?rev=134912&r1=134911&r2=134912&view=diff ============================================================================== --- lldb/trunk/test/lang/objc/objc-static-method/TestObjCStaticMethod.py (original) +++ lldb/trunk/test/lang/objc/objc-static-method/TestObjCStaticMethod.py Mon Jul 11 14:34:11 2011 @@ -61,7 +61,7 @@ cmd_value = frame.EvaluateExpression ("(char *) sel_getName (_cmd)") self.assertTrue (cmd_value.IsValid()) sel_name = cmd_value.GetSummary() - self.assertFalse (sel_name == "doSomethingWithString:", "Got the right value for the selector as string.") + self.assertTrue (sel_name == "doSomethingWithString:", "Got the right value for the selector as string.") if __name__ == '__main__': import atexit From jingham at apple.com Mon Jul 11 14:47:16 2011 From: jingham at apple.com (Jim Ingham) Date: Mon, 11 Jul 2011 19:47:16 -0000 Subject: [Lldb-commits] [lldb] r134914 - /lldb/trunk/test/lang/objc/objc-static-method/TestObjCStaticMethod.py Message-ID: <20110711194716.A049D2A6C12C@llvm.org> Author: jingham Date: Mon Jul 11 14:47:16 2011 New Revision: 134914 URL: http://llvm.org/viewvc/llvm-project?rev=134914&view=rev Log: Mark the test with expectedFailure for now. Modified: lldb/trunk/test/lang/objc/objc-static-method/TestObjCStaticMethod.py Modified: lldb/trunk/test/lang/objc/objc-static-method/TestObjCStaticMethod.py URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/lang/objc/objc-static-method/TestObjCStaticMethod.py?rev=134914&r1=134913&r2=134914&view=diff ============================================================================== --- lldb/trunk/test/lang/objc/objc-static-method/TestObjCStaticMethod.py (original) +++ lldb/trunk/test/lang/objc/objc-static-method/TestObjCStaticMethod.py Mon Jul 11 14:47:16 2011 @@ -12,12 +12,17 @@ @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin") @python_api_test + + # "expression" can't call functions in class methods + @unittest2.expectedFailure def test_with_dsym_and_python_api(self): """Test calling functions in static methods.""" self.buildDsym() self.objc_static_method() @python_api_test + # "expression" can't call functions in class methods + @unittest2.expectedFailure def test_with_dwarf_and_python_api(self): """Test calling functions in static methods.""" self.buildDwarf() From johnny.chen at apple.com Mon Jul 11 15:06:28 2011 From: johnny.chen at apple.com (Johnny Chen) Date: Mon, 11 Jul 2011 20:06:28 -0000 Subject: [Lldb-commits] [lldb] r134915 - in /lldb/trunk/test: expression_command/test/TestExprs.py lang/c/array_types/TestArrayTypes.py lang/c/bitfields/TestBitfields.py lang/cpp/class_static/TestStaticVariables.py python_api/process/TestProcessAPI.py Message-ID: <20110711200628.59F572A6C12C@llvm.org> Author: johnny Date: Mon Jul 11 15:06:28 2011 New Revision: 134915 URL: http://llvm.org/viewvc/llvm-project?rev=134915&view=rev Log: The lldbtest.TestBase.DebugSBValue(self, val) method call now does not need the frame argument. Only the val (of SBValue type) argument is needed. Modified: lldb/trunk/test/expression_command/test/TestExprs.py lldb/trunk/test/lang/c/array_types/TestArrayTypes.py lldb/trunk/test/lang/c/bitfields/TestBitfields.py lldb/trunk/test/lang/cpp/class_static/TestStaticVariables.py lldb/trunk/test/python_api/process/TestProcessAPI.py Modified: lldb/trunk/test/expression_command/test/TestExprs.py URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/expression_command/test/TestExprs.py?rev=134915&r1=134914&r2=134915&view=diff ============================================================================== --- lldb/trunk/test/expression_command/test/TestExprs.py (original) +++ lldb/trunk/test/expression_command/test/TestExprs.py Mon Jul 11 15:06:28 2011 @@ -139,27 +139,27 @@ startstr = "2.234") self.expect(val.GetTypeName(), "2.345 evaluated correctly", exe=False, startstr = "double") - self.DebugSBValue(frame, val) + self.DebugSBValue(val) val = frame.EvaluateExpression("argc") self.expect(val.GetValue(frame), "Argc evaluated correctly", exe=False, startstr = "4") - self.DebugSBValue(frame, val) + self.DebugSBValue(val) val = frame.EvaluateExpression("*argv[1]") self.expect(val.GetValue(frame), "Argv[1] evaluated correctly", exe=False, startstr = "'X'") - self.DebugSBValue(frame, val) + self.DebugSBValue(val) val = frame.EvaluateExpression("*argv[2]") self.expect(val.GetValue(frame), "Argv[2] evaluated correctly", exe=False, startstr = "'Y'") - self.DebugSBValue(frame, val) + self.DebugSBValue(val) val = frame.EvaluateExpression("*argv[3]") self.expect(val.GetValue(frame), "Argv[3] evaluated correctly", exe=False, startstr = "'Z'") - self.DebugSBValue(frame, val) + self.DebugSBValue(val) # rdar://problem/8686536 # CommandInterpreter::HandleCommand is stripping \'s from input for WantsRawCommand commands Modified: lldb/trunk/test/lang/c/array_types/TestArrayTypes.py URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/lang/c/array_types/TestArrayTypes.py?rev=134915&r1=134914&r2=134915&view=diff ============================================================================== --- lldb/trunk/test/lang/c/array_types/TestArrayTypes.py (original) +++ lldb/trunk/test/lang/c/array_types/TestArrayTypes.py Mon Jul 11 15:06:28 2011 @@ -155,18 +155,18 @@ var = repr(variable) self.expect(var, "Variable for 'strings' looks good with correct name", exe=False, substrs = ["%s" % variable.GetName()]) - self.DebugSBValue(frame, variable) + self.DebugSBValue(variable) self.assertTrue(variable.GetNumChildren() == 4, "Variable 'strings' should have 4 children") child3 = variable.GetChildAtIndex(3) - self.DebugSBValue(frame, child3) + self.DebugSBValue(child3) self.assertTrue(child3.GetSummary(frame) == '"Guten Tag"', 'strings[3] == "Guten Tag"') # Lookup the "char_16" char array variable. variable = frame.FindVariable("char_16") - self.DebugSBValue(frame, variable) + self.DebugSBValue(variable) self.assertTrue(variable.GetNumChildren() == 16, "Variable 'char_16' should have 16 children") @@ -175,25 +175,25 @@ # base of 0 so that the proper radix is determined based on the contents # of the string. Same applies to long(). variable = frame.FindVariable("ushort_matrix") - self.DebugSBValue(frame, variable) + self.DebugSBValue(variable) self.assertTrue(variable.GetNumChildren() == 2, "Variable 'ushort_matrix' should have 2 children") child0 = variable.GetChildAtIndex(0) - self.DebugSBValue(frame, child0) + self.DebugSBValue(child0) self.assertTrue(child0.GetNumChildren() == 3, "Variable 'ushort_matrix[0]' should have 3 children") child0_2 = child0.GetChildAtIndex(2) - self.DebugSBValue(frame, child0_2) + self.DebugSBValue(child0_2) self.assertTrue(int(child0_2.GetValue(frame), 0) == 3, "ushort_matrix[0][2] == 3") # Lookup the "long_6" char array variable. variable = frame.FindVariable("long_6") - self.DebugSBValue(frame, variable) + self.DebugSBValue(variable) self.assertTrue(variable.GetNumChildren() == 6, "Variable 'long_6' should have 6 children") child5 = variable.GetChildAtIndex(5) - self.DebugSBValue(frame, child5) + self.DebugSBValue(child5) self.assertTrue(long(child5.GetValue(frame), 0) == 6, "long_6[5] == 6") @@ -204,7 +204,7 @@ "Variable 'long_6' should have '%s' value type." % value_type_to_str(lldb.eValueTypeVariableLocal)) argc = frame.FindVariable("argc") - self.DebugSBValue(frame, argc) + self.DebugSBValue(argc) self.assertTrue(argc.GetValueType() == lldb.eValueTypeVariableArgument, "Variable 'argc' should have '%s' value type." % value_type_to_str(lldb.eValueTypeVariableArgument)) Modified: lldb/trunk/test/lang/c/bitfields/TestBitfields.py URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/lang/c/bitfields/TestBitfields.py?rev=134915&r1=134914&r2=134915&view=diff ============================================================================== --- lldb/trunk/test/lang/c/bitfields/TestBitfields.py (original) +++ lldb/trunk/test/lang/c/bitfields/TestBitfields.py Mon Jul 11 15:06:28 2011 @@ -110,7 +110,7 @@ # Lookup the "bits" variable which contains 8 bitfields. frame = thread.GetFrameAtIndex(0) bits = frame.FindVariable("bits") - self.DebugSBValue(frame, bits) + self.DebugSBValue(bits) self.assertTrue(bits.GetTypeName() == "Bits" and bits.GetNumChildren() == 8 and bits.GetByteSize() == 4, @@ -120,7 +120,7 @@ # so that the proper radix is determined based on the contents of the # string. b1 = bits.GetChildAtIndex(0) - self.DebugSBValue(frame, b1) + self.DebugSBValue(b1) self.assertTrue(b1.GetName() == "b1" and b1.GetTypeName() == "uint32_t:1" and b1.IsInScope(frame) and @@ -128,7 +128,7 @@ 'bits.b1 has type uint32_t:1, is in scope, and == 1') b7 = bits.GetChildAtIndex(6) - self.DebugSBValue(frame, b7) + self.DebugSBValue(b7) self.assertTrue(b7.GetName() == "b7" and b7.GetTypeName() == "uint32_t:7" and b7.IsInScope(frame) and @@ -136,7 +136,7 @@ 'bits.b7 has type uint32_t:7, is in scope, and == 127') four = bits.GetChildAtIndex(7) - self.DebugSBValue(frame, four) + self.DebugSBValue(four) self.assertTrue(four.GetName() == "four" and four.GetTypeName() == "uint32_t:4" and four.IsInScope(frame) and Modified: lldb/trunk/test/lang/cpp/class_static/TestStaticVariables.py URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/lang/cpp/class_static/TestStaticVariables.py?rev=134915&r1=134914&r2=134915&view=diff ============================================================================== --- lldb/trunk/test/lang/cpp/class_static/TestStaticVariables.py (original) +++ lldb/trunk/test/lang/cpp/class_static/TestStaticVariables.py Mon Jul 11 15:06:28 2011 @@ -102,7 +102,7 @@ valList = frame.GetVariables(False, False, True, False) for val in valList: - self.DebugSBValue(frame, val) + self.DebugSBValue(val) self.assertTrue(val.GetValueType() == lldb.eValueTypeVariableGlobal) name = val.GetName() self.assertTrue(name in ['g_points', 'A::g_points']) @@ -112,28 +112,28 @@ # On Mac OS X, gcc 4.2 emits the wrong debug info for A::g_points. self.assertTrue(val.GetNumChildren() == 2) child1 = val.GetChildAtIndex(1) - self.DebugSBValue(frame, child1) + self.DebugSBValue(child1) child1_x = child1.GetChildAtIndex(0) - self.DebugSBValue(frame, child1_x) + self.DebugSBValue(child1_x) self.assertTrue(child1_x.GetTypeName() == 'int' and child1_x.GetValue(frame) == '11') # SBFrame.FindValue() should also work. val = frame.FindValue("A::g_points", lldb.eValueTypeVariableGlobal) - self.DebugSBValue(frame, val) + self.DebugSBValue(val) self.assertTrue(val.GetName() == 'A::g_points') # Also exercise the "parameter" and "local" scopes while we are at it. val = frame.FindValue("argc", lldb.eValueTypeVariableArgument) - self.DebugSBValue(frame, val) + self.DebugSBValue(val) self.assertTrue(val.GetName() == 'argc') val = frame.FindValue("argv", lldb.eValueTypeVariableArgument) - self.DebugSBValue(frame, val) + self.DebugSBValue(val) self.assertTrue(val.GetName() == 'argv') val = frame.FindValue("hello_world", lldb.eValueTypeVariableLocal) - self.DebugSBValue(frame, val) + self.DebugSBValue(val) self.assertTrue(val.GetName() == 'hello_world') Modified: lldb/trunk/test/python_api/process/TestProcessAPI.py URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/python_api/process/TestProcessAPI.py?rev=134915&r1=134914&r2=134915&view=diff ============================================================================== --- lldb/trunk/test/python_api/process/TestProcessAPI.py (original) +++ lldb/trunk/test/python_api/process/TestProcessAPI.py Mon Jul 11 15:06:28 2011 @@ -84,7 +84,7 @@ # Get the SBValue for the global variable 'my_char'. val = frame.FindValue("my_char", lldb.eValueTypeVariableGlobal) - self.DebugSBValue(frame, val) + self.DebugSBValue(val) # If the variable does not have a load address, there's no sense continuing. if not val.GetLocation(frame).startswith("0x"): @@ -126,7 +126,7 @@ # Get the SBValue for the global variable 'my_char'. val = frame.FindValue("my_char", lldb.eValueTypeVariableGlobal) - self.DebugSBValue(frame, val) + self.DebugSBValue(val) # If the variable does not have a load address, there's no sense continuing. if not val.GetLocation(frame).startswith("0x"): @@ -177,7 +177,7 @@ # Get the SBValue for the global variable 'my_int'. val = frame.FindValue("my_int", lldb.eValueTypeVariableGlobal) - self.DebugSBValue(frame, val) + self.DebugSBValue(val) # If the variable does not have a load address, there's no sense continuing. if not val.GetLocation(frame).startswith("0x"): From johnny.chen at apple.com Mon Jul 11 16:41:05 2011 From: johnny.chen at apple.com (Johnny Chen) Date: Mon, 11 Jul 2011 21:41:05 -0000 Subject: [Lldb-commits] [lldb] r134924 - /lldb/trunk/include/lldb/API/SBTarget.h Message-ID: <20110711214105.AAAA32A6C12C@llvm.org> Author: johnny Date: Mon Jul 11 16:41:05 2011 New Revision: 134924 URL: http://llvm.org/viewvc/llvm-project?rev=134924&view=rev Log: Add missing docstring for 'bool stop_at_endtry'. Modified: lldb/trunk/include/lldb/API/SBTarget.h Modified: lldb/trunk/include/lldb/API/SBTarget.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/API/SBTarget.h?rev=134924&r1=134923&r2=134924&view=diff ============================================================================== --- lldb/trunk/include/lldb/API/SBTarget.h (original) +++ lldb/trunk/include/lldb/API/SBTarget.h Mon Jul 11 16:41:05 2011 @@ -112,6 +112,9 @@ /// Some launch options specified by logical OR'ing /// lldb::LaunchFlags enumeration values together. /// + /// @param[in] stop_at_endtry + /// If false do not stop the inferior at the entry point. + /// /// @param[out] /// An error object. Contains the reason if there is some failure. /// From johnny.chen at apple.com Mon Jul 11 18:38:23 2011 From: johnny.chen at apple.com (Johnny Chen) Date: Mon, 11 Jul 2011 23:38:23 -0000 Subject: [Lldb-commits] [lldb] r134940 - in /lldb/trunk/test: expression_command/test/TestExprs.py functionalities/conditional_break/TestConditionalBreak.py lang/cpp/class_types/TestClassTypes.py lang/cpp/namespace/TestNamespace.py lang/objc/foundation/TestObjCMethods.py python_api/event/TestEvents.py python_api/lldbutil/iter/TestLLDBIterator.py python_api/lldbutil/iter/TestRegistersIterator.py python_api/lldbutil/process/TestPrintStackTraces.py python_api/process/TestProcessAPI.py source-manager/TestSourceManager.py Message-ID: <20110711233823.A53CC2A6C12C@llvm.org> Author: johnny Date: Mon Jul 11 18:38:23 2011 New Revision: 134940 URL: http://llvm.org/viewvc/llvm-project?rev=134940&view=rev Log: Passing in os.ctermid() as the arg for SBTarget.Launch(...) for stdin_path, stdout_path, and stderr_path is just wrong and resulted in the inferior's output getting mixed into the GDB remote communication's log file. Change all test cases to not pass os.ctermid() and either use SBTarget.LaunchSimple() or SBTarget.Launch() and pass None as stdin_path/stdout_path/srderr_path to use a pseudo terminal. rdar://problem/9716499 program output is getting mixed into the GDB remote communications Modified: lldb/trunk/test/expression_command/test/TestExprs.py lldb/trunk/test/functionalities/conditional_break/TestConditionalBreak.py lldb/trunk/test/lang/cpp/class_types/TestClassTypes.py lldb/trunk/test/lang/cpp/namespace/TestNamespace.py lldb/trunk/test/lang/objc/foundation/TestObjCMethods.py lldb/trunk/test/python_api/event/TestEvents.py lldb/trunk/test/python_api/lldbutil/iter/TestLLDBIterator.py lldb/trunk/test/python_api/lldbutil/iter/TestRegistersIterator.py lldb/trunk/test/python_api/lldbutil/process/TestPrintStackTraces.py lldb/trunk/test/python_api/process/TestProcessAPI.py lldb/trunk/test/source-manager/TestSourceManager.py Modified: lldb/trunk/test/expression_command/test/TestExprs.py URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/expression_command/test/TestExprs.py?rev=134940&r1=134939&r2=134940&view=diff ============================================================================== --- lldb/trunk/test/expression_command/test/TestExprs.py (original) +++ lldb/trunk/test/expression_command/test/TestExprs.py Mon Jul 11 18:38:23 2011 @@ -100,10 +100,9 @@ # Launch the process, and do not stop at the entry point. # Pass 'X Y Z' as the args, which makes argc == 4. - error = lldb.SBError() - process = target.Launch(self.dbg.GetListener(), ['X', 'Y', 'Z'], None, os.ctermid(), os.ctermid(), os.ctermid(), None, 0, False, error) + process = target.LaunchSimple(['X', 'Y', 'Z'], None, os.getcwd()) - if not error.Success() or not process: + if not process: self.fail("SBTarget.LaunchProcess() failed") if process.GetState() != lldb.eStateStopped: Modified: lldb/trunk/test/functionalities/conditional_break/TestConditionalBreak.py URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/conditional_break/TestConditionalBreak.py?rev=134940&r1=134939&r2=134940&view=diff ============================================================================== --- lldb/trunk/test/functionalities/conditional_break/TestConditionalBreak.py (original) +++ lldb/trunk/test/functionalities/conditional_break/TestConditionalBreak.py Mon Jul 11 18:38:23 2011 @@ -52,10 +52,9 @@ self.assertTrue(breakpoint, VALID_BREAKPOINT) # Now launch the process, and do not stop at entry point. - error = lldb.SBError() - process = target.Launch (self.dbg.GetListener(), None, None, os.ctermid(), os.ctermid(), os.ctermid(), None, 0, False, error) + process = target.LaunchSimple(None, None, os.getcwd()) - self.assertTrue(error.Success() and process, PROCESS_IS_VALID) + self.assertTrue(process, PROCESS_IS_VALID) # The stop reason of the thread should be breakpoint. self.assertTrue(process.GetState() == lldb.eStateStopped, Modified: lldb/trunk/test/lang/cpp/class_types/TestClassTypes.py URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/lang/cpp/class_types/TestClassTypes.py?rev=134940&r1=134939&r2=134940&view=diff ============================================================================== --- lldb/trunk/test/lang/cpp/class_types/TestClassTypes.py (original) +++ lldb/trunk/test/lang/cpp/class_types/TestClassTypes.py Mon Jul 11 18:38:23 2011 @@ -119,10 +119,9 @@ str(self.line)]) # Now launch the process, and do not stop at entry point. - error = lldb.SBError() - process = target.Launch (self.dbg.GetListener(), None, None, os.ctermid(), os.ctermid(), os.ctermid(), None, 0, False, error) + process = target.LaunchSimple(None, None, os.getcwd()) - if not error.Success() or not process: + if not process: self.fail("SBTarget.Launch() failed") if process.GetState() != lldb.eStateStopped: Modified: lldb/trunk/test/lang/cpp/namespace/TestNamespace.py URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/lang/cpp/namespace/TestNamespace.py?rev=134940&r1=134939&r2=134940&view=diff ============================================================================== --- lldb/trunk/test/lang/cpp/namespace/TestNamespace.py (original) +++ lldb/trunk/test/lang/cpp/namespace/TestNamespace.py Mon Jul 11 18:38:23 2011 @@ -68,12 +68,12 @@ substrs = slist) # 'frame variable' with basename 'i' should work. - self.expect("frame variable -c -G i", + self.expect("frame variable -c -g i", startstr = "main.cpp:%d: (int) (anonymous namespace)::i = 3" % self.line_var_i) # main.cpp:12: (int) (anonymous namespace)::i = 3 # 'frame variable' with basename 'j' should work, too. - self.expect("frame variable -c -G j", + self.expect("frame variable -c -g j", startstr = "main.cpp:%d: (int) A::B::j = 4" % self.line_var_j) # main.cpp:19: (int) A::B::j = 4 Modified: lldb/trunk/test/lang/objc/foundation/TestObjCMethods.py URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/lang/objc/foundation/TestObjCMethods.py?rev=134940&r1=134939&r2=134940&view=diff ============================================================================== --- lldb/trunk/test/lang/objc/foundation/TestObjCMethods.py (original) +++ lldb/trunk/test/lang/objc/foundation/TestObjCMethods.py Mon Jul 11 18:38:23 2011 @@ -211,8 +211,7 @@ self.assertTrue(break1, VALID_BREAKPOINT) # Now launch the process, and do not stop at entry point. - error = lldb.SBError() - process = target.Launch (self.dbg.GetListener(), None, None, os.ctermid(), os.ctermid(), os.ctermid(), None, 0, False, error) + process = target.LaunchSimple(None, None, os.getcwd()) self.assertTrue(process, PROCESS_IS_VALID) Modified: lldb/trunk/test/python_api/event/TestEvents.py URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/python_api/event/TestEvents.py?rev=134940&r1=134939&r2=134940&view=diff ============================================================================== --- lldb/trunk/test/python_api/event/TestEvents.py (original) +++ lldb/trunk/test/python_api/event/TestEvents.py Mon Jul 11 18:38:23 2011 @@ -149,7 +149,7 @@ # Now launch the process, and do not stop at entry point. error = lldb.SBError() - process = target.Launch (listener, None, None, os.ctermid(), os.ctermid(), os.ctermid(), None, 0, False, error) + process = target.Launch (listener, None, None, None, None, None, None, 0, False, error) self.assertTrue(process, PROCESS_IS_VALID) # Get a handle on the process's broadcaster. Modified: lldb/trunk/test/python_api/lldbutil/iter/TestLLDBIterator.py URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/python_api/lldbutil/iter/TestLLDBIterator.py?rev=134940&r1=134939&r2=134940&view=diff ============================================================================== --- lldb/trunk/test/python_api/lldbutil/iter/TestLLDBIterator.py (original) +++ lldb/trunk/test/python_api/lldbutil/iter/TestLLDBIterator.py Mon Jul 11 18:38:23 2011 @@ -44,10 +44,9 @@ self.assertTrue(breakpoint, VALID_BREAKPOINT) # Now launch the process, and do not stop at entry point. - rc = lldb.SBError() - process = target.Launch (self.dbg.GetListener(), None, None, os.ctermid(), os.ctermid(), os.ctermid(), None, 0, False, rc) + process = target.LaunchSimple(None, None, os.getcwd()) - if not rc.Success() or not process: + if not process: self.fail("SBTarget.LaunchProcess() failed") from lldbutil import get_description @@ -105,10 +104,9 @@ self.assertTrue(breakpoint, VALID_BREAKPOINT) # Now launch the process, and do not stop at entry point. - rc = lldb.SBError() - process = target.Launch (self.dbg.GetListener(), None, None, os.ctermid(), os.ctermid(), os.ctermid(), None, 0, False, rc) + process = target.LaunchSimple(None, None, os.getcwd()) - if not rc.Success() or not process: + if not process: self.fail("SBTarget.LaunchProcess() failed") from lldbutil import print_stacktrace Modified: lldb/trunk/test/python_api/lldbutil/iter/TestRegistersIterator.py URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/python_api/lldbutil/iter/TestRegistersIterator.py?rev=134940&r1=134939&r2=134940&view=diff ============================================================================== --- lldb/trunk/test/python_api/lldbutil/iter/TestRegistersIterator.py (original) +++ lldb/trunk/test/python_api/lldbutil/iter/TestRegistersIterator.py Mon Jul 11 18:38:23 2011 @@ -33,10 +33,9 @@ self.assertTrue(breakpoint, VALID_BREAKPOINT) # Now launch the process, and do not stop at entry point. - rc = lldb.SBError() - process = target.Launch (self.dbg.GetListener(), None, None, os.ctermid(), os.ctermid(), os.ctermid(), None, 0, False, rc) + process = target.LaunchSimple(None, None, os.getcwd()) - if not rc.Success() or not process: + if not process: self.fail("SBTarget.LaunchProcess() failed") import lldbutil Modified: lldb/trunk/test/python_api/lldbutil/process/TestPrintStackTraces.py URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/python_api/lldbutil/process/TestPrintStackTraces.py?rev=134940&r1=134939&r2=134940&view=diff ============================================================================== --- lldb/trunk/test/python_api/lldbutil/process/TestPrintStackTraces.py (original) +++ lldb/trunk/test/python_api/lldbutil/process/TestPrintStackTraces.py Mon Jul 11 18:38:23 2011 @@ -34,10 +34,9 @@ self.assertTrue(breakpoint, VALID_BREAKPOINT) # Now launch the process, and do not stop at entry point. - rc = lldb.SBError() - process = target.Launch (self.dbg.GetListener(), ["abc", "xyz"], None, os.ctermid(), os.ctermid(), os.ctermid(), None, 0, False, rc) + process = target.LaunchSimple(["abc", "xyz"], None, os.getcwd()) - if not rc.Success() or not process: + if not process: self.fail("SBTarget.LaunchProcess() failed") import lldbutil Modified: lldb/trunk/test/python_api/process/TestProcessAPI.py URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/python_api/process/TestProcessAPI.py?rev=134940&r1=134939&r2=134940&view=diff ============================================================================== --- lldb/trunk/test/python_api/process/TestProcessAPI.py (original) +++ lldb/trunk/test/python_api/process/TestProcessAPI.py Mon Jul 11 18:38:23 2011 @@ -75,8 +75,7 @@ self.assertTrue(breakpoint, VALID_BREAKPOINT) # Launch the process, and do not stop at the entry point. - error = lldb.SBError() - process = target.Launch (self.dbg.GetListener(), None, None, os.ctermid(), os.ctermid(), os.ctermid(), None, 0, False, error) + process = target.LaunchSimple(None, None, os.getcwd()) thread = get_stopped_thread(process, lldb.eStopReasonBreakpoint) self.assertTrue(thread != None, "There should be a thread stopped due to breakpoint") @@ -95,6 +94,7 @@ # Due to the typemap magic (see lldb.swig), we pass in 1 to ReadMemory and # expect to get a Python string as the result object! + error = lldb.SBError() content = process.ReadMemory(location, 1, error) if not error.Success(): self.fail("SBProcess.ReadMemory() failed") @@ -117,8 +117,7 @@ self.assertTrue(breakpoint, VALID_BREAKPOINT) # Launch the process, and do not stop at the entry point. - error = lldb.SBError() - process = target.Launch (self.dbg.GetListener(), None, None, os.ctermid(), os.ctermid(), os.ctermid(), None, 0, False, error) + process = target.LaunchSimple(None, None, os.getcwd()) thread = get_stopped_thread(process, lldb.eStopReasonBreakpoint) self.assertTrue(thread != None, "There should be a thread stopped due to breakpoint") @@ -139,6 +138,7 @@ # But we want to use the WriteMemory() API to assign 'a' to the variable. # Now use WriteMemory() API to write 'a' into the global variable. + error = lldb.SBError() result = process.WriteMemory(location, 'a', error) if not error.Success() or result != 1: self.fail("SBProcess.WriteMemory() failed") @@ -168,8 +168,7 @@ self.assertTrue(breakpoint, VALID_BREAKPOINT) # Launch the process, and do not stop at the entry point. - error = lldb.SBError() - process = target.Launch (self.dbg.GetListener(), None, None, os.ctermid(), os.ctermid(), os.ctermid(), None, 0, False, error) + process = target.LaunchSimple(None, None, os.getcwd()) thread = get_stopped_thread(process, lldb.eStopReasonBreakpoint) self.assertTrue(thread != None, "There should be a thread stopped due to breakpoint") @@ -207,6 +206,7 @@ # Now use WriteMemory() API to write 256 into the global variable. new_value = str(bytes) + error = lldb.SBError() result = process.WriteMemory(location, new_value, error) if not error.Success() or result != byteSize: self.fail("SBProcess.WriteMemory() failed") @@ -254,13 +254,13 @@ self.assertTrue(target, VALID_TARGET) # Launch the process, and do not stop at the entry point. - error = lldb.SBError() - process = target.Launch (self.dbg.GetListener(), None, None, os.ctermid(), os.ctermid(), os.ctermid(), None, 0, False, error) + process = target.LaunchSimple(None, None, os.getcwd()) if self.TraceOn(): print "process state:", state_type_to_str(process.GetState()) self.assertTrue(process.GetState() != lldb.eStateConnected) + error = lldb.SBError() success = process.RemoteLaunch(None, None, None, None, None, None, 0, False, error) self.assertTrue(not success, "RemoteLaunch() should fail for process state != eStateConnected") Modified: lldb/trunk/test/source-manager/TestSourceManager.py URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/source-manager/TestSourceManager.py?rev=134940&r1=134939&r2=134940&view=diff ============================================================================== --- lldb/trunk/test/source-manager/TestSourceManager.py (original) +++ lldb/trunk/test/source-manager/TestSourceManager.py Mon Jul 11 18:38:23 2011 @@ -43,8 +43,7 @@ self.assertTrue(target, VALID_TARGET) # Launch the process, and do not stop at the entry point. - error = lldb.SBError() - process = target.Launch (self.dbg.GetListener(), None, None, os.ctermid(), os.ctermid(), os.ctermid(), None, 0, False, error) + process = target.LaunchSimple(None, None, os.getcwd()) # # Exercise Python APIs to display source lines. From granata.enrico at gmail.com Mon Jul 11 19:18:11 2011 From: granata.enrico at gmail.com (Enrico Granata) Date: Tue, 12 Jul 2011 00:18:11 -0000 Subject: [Lldb-commits] [lldb] r134943 - in /lldb/trunk: include/lldb/Core/ include/lldb/Interpreter/ include/lldb/Symbol/ include/lldb/Utility/ source/Commands/ source/Core/ source/Interpreter/ source/Symbol/ test/functionalities/data-formatter/data-formatter-cpp/ Message-ID: <20110712001812.0ACA72A6C12C@llvm.org> Author: enrico Date: Mon Jul 11 19:18:11 2011 New Revision: 134943 URL: http://llvm.org/viewvc/llvm-project?rev=134943&view=rev Log: named summaries: - a new --name option for "type summary add" lets you give a name to a summary - a new --summary option for "frame variable" lets you bind a named summary to one or more variables ${var%s} now works for printing the value of 0-terminated CStrings type format test case now tests for cascading - this is disabled on GCC because GCC may end up stripping typedef chains, basically breaking cascading new design for the FormatNavigator class new template class CleanUp2 meant to support cleanup routines with 1 additional parameter beyond resource handle Modified: lldb/trunk/include/lldb/Core/Debugger.h lldb/trunk/include/lldb/Core/FormatManager.h lldb/trunk/include/lldb/Core/ValueObject.h lldb/trunk/include/lldb/Interpreter/OptionGroupVariable.h lldb/trunk/include/lldb/Symbol/ClangASTContext.h lldb/trunk/include/lldb/Utility/CleanUp.h lldb/trunk/source/Commands/CommandObjectFrame.cpp lldb/trunk/source/Commands/CommandObjectType.cpp lldb/trunk/source/Core/Debugger.cpp lldb/trunk/source/Core/FormatManager.cpp lldb/trunk/source/Core/ValueObject.cpp lldb/trunk/source/Interpreter/CommandInterpreter.cpp lldb/trunk/source/Interpreter/OptionGroupVariable.cpp lldb/trunk/source/Symbol/ClangASTContext.cpp lldb/trunk/source/Symbol/SymbolContext.cpp lldb/trunk/test/functionalities/data-formatter/data-formatter-cpp/TestDataFormatterCpp.py lldb/trunk/test/functionalities/data-formatter/data-formatter-cpp/main.cpp Modified: lldb/trunk/include/lldb/Core/Debugger.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/Debugger.h?rev=134943&r1=134942&r2=134943&view=diff ============================================================================== --- lldb/trunk/include/lldb/Core/Debugger.h (original) +++ lldb/trunk/include/lldb/Core/Debugger.h Mon Jul 11 19:18:11 2011 @@ -550,6 +550,32 @@ static uint32_t GetCount(); }; + + class NamedSummaryFormats + { + public: + + static bool + Get(const ConstString &type, SummaryFormat::SharedPointer &entry); + + static void + Add(const ConstString &type, const SummaryFormat::SharedPointer &entry); + + static bool + Delete(const ConstString &type); + + static void + Clear(); + + static void + LoopThrough(SummaryFormat::SummaryCallback callback, void* callback_baton); + + static uint32_t + GetCurrentRevision(); + + static uint32_t + GetCount(); + }; }; Modified: lldb/trunk/include/lldb/Core/FormatManager.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/FormatManager.h?rev=134943&r1=134942&r2=134943&view=diff ============================================================================== --- lldb/trunk/include/lldb/Core/FormatManager.h (original) +++ lldb/trunk/include/lldb/Core/FormatManager.h Mon Jul 11 19:18:11 2011 @@ -142,53 +142,66 @@ } }; + +template +class FormatNavigator; -template -class FormatNavigator +template +class FormatMap { +private: + typedef typename ValueType::SharedPointer ValueSP; + Mutex m_map_mutex; + IFormatChangeListener* listener; + + friend class FormatNavigator; + +public: + typedef std::map MapType; + +private: + MapType m_map; + + MapType& map() + { + return m_map; + } + + Mutex& mutex() + { + return m_map_mutex; + } + public: typedef typename MapType::iterator MapIterator; - typedef typename MapType::key_type MapKeyType; - typedef typename MapType::mapped_type MapValueType; + typedef bool(*CallbackType)(void*, KeyType, const ValueSP&); - FormatNavigator(IFormatChangeListener* lst = NULL) : + FormatMap(IFormatChangeListener* lst = NULL) : + m_map(), m_map_mutex(Mutex::eMutexTypeRecursive), - m_map(MapType()), listener(lst) { } - - bool - Get(ValueObject& vobj, MapValueType& entry) - { - Mutex::Locker(m_map_mutex); - clang::QualType type = clang::QualType::getFromOpaquePtr(vobj.GetClangType()); - bool ret = Get(vobj, type, entry); - if(ret) - entry = MapValueType(entry); - else - entry = MapValueType(); - return ret; - } void - Add(const MapKeyType &type, const MapValueType& entry) + Add(KeyType name, + const ValueSP& entry) { Mutex::Locker(m_map_mutex); - m_map[type] = MapValueType(entry); - if(listener) + m_map[name] = entry; + if (listener) listener->Changed(); } bool - Delete(const char* type) + Delete(KeyType name) { Mutex::Locker(m_map_mutex); - MapIterator iter = m_map.find(type); + MapIterator iter = m_map.find(name); if (iter == m_map.end()) return false; - m_map.erase(type); + m_map.erase(name); if(listener) listener->Changed(); return true; @@ -203,6 +216,18 @@ listener->Changed(); } + bool + Get(KeyType name, + ValueSP& entry) + { + Mutex::Locker(m_map_mutex); + MapIterator iter = m_map.find(name); + if (iter == m_map.end()) + return false; + entry = iter->second; + return true; + } + void LoopThrough(CallbackType callback, void* param) { @@ -212,8 +237,8 @@ MapIterator pos, end = m_map.end(); for (pos = m_map.begin(); pos != end; pos++) { - MapKeyType type = pos->first; - if(!callback(param, type, MapValueType(pos->second))) + KeyType type = pos->first; + if(!callback(param, type, pos->second)) break; } } @@ -225,36 +250,91 @@ return m_map.size(); } - ~FormatNavigator() +}; + +template +class FormatNavigator +{ +private: + typedef FormatMap BackEndType; + + BackEndType m_format_map; + +public: + typedef typename BackEndType::MapType MapType; + typedef typename MapType::iterator MapIterator; + typedef typename MapType::key_type MapKeyType; + typedef typename MapType::mapped_type MapValueType; + typedef typename BackEndType::CallbackType CallbackType; + + FormatNavigator(IFormatChangeListener* lst = NULL) : + m_format_map(lst) { } -private: + void + Add(const MapKeyType &type, const MapValueType& entry) + { + m_format_map.Add(type,entry); + } - Mutex m_map_mutex; - MapType m_map; - IFormatChangeListener* listener; + // using const char* instead of MapKeyType is necessary here + // to make the partial template specializations below work + bool + Delete(const char *type) + { + return m_format_map.Delete(type); + } + + bool + Get(ValueObject& vobj, MapValueType& entry) + { + clang::QualType type = clang::QualType::getFromOpaquePtr(vobj.GetClangType()); + bool ret = Get(vobj, type, entry); + if(ret) + entry = MapValueType(entry); + else + entry = MapValueType(); + return ret; + } + + void + Clear() + { + m_format_map.Clear(); + } + + void + LoopThrough(CallbackType callback, void* param) + { + m_format_map.LoopThrough(callback,param); + } + + uint32_t + GetCount() + { + return m_format_map.GetCount(); + } + +private: DISALLOW_COPY_AND_ASSIGN(FormatNavigator); + // using const char* instead of MapKeyType is necessary here + // to make the partial template specializations below work bool Get(const char* type, MapValueType& entry) { - Mutex::Locker(m_map_mutex); - MapIterator iter = m_map.find(type); - if (iter == m_map.end()) - return false; - entry = iter->second; - return true; + return m_format_map.Get(type, entry); } bool Get(ValueObject& vobj, - const clang::QualType& q_type, + clang::QualType type, MapValueType& entry) { - if (q_type.isNull()) + if (type.isNull()) return false; - clang::QualType type = q_type.getUnqualifiedType(); + // clang::QualType type = q_type.getUnqualifiedType(); type.removeLocalConst(); type.removeLocalVolatile(); type.removeLocalRestrict(); const clang::Type* typePtr = type.getTypePtrOrNull(); if (!typePtr) @@ -354,40 +434,41 @@ // try to strip typedef chains const clang::TypedefType* type_tdef = type->getAs(); if (type_tdef) + { if ((Get(vobj, type_tdef->getDecl()->getUnderlyingType(), entry)) && entry->m_cascades) return true; + } return false; } - }; - + template<> bool -FormatNavigator, SummaryFormat::RegexSummaryCallback>::Get(const char* key, - SummaryFormat::SharedPointer& value); +FormatNavigator::Get(const char* key, SummaryFormat::SharedPointer& value); + template<> bool -FormatNavigator, SummaryFormat::RegexSummaryCallback>::Delete(const char* type); - +FormatNavigator::Delete(const char* type); + class FormatManager : public IFormatChangeListener { - -public: - private: - typedef std::map ValueMap; - typedef std::map SummaryMap; - typedef std::map RegexSummaryMap; - - typedef FormatNavigator ValueNavigator; - typedef FormatNavigator SummaryNavigator; - typedef FormatNavigator RegexSummaryNavigator; + typedef FormatNavigator ValueNavigator; + typedef FormatNavigator SummaryNavigator; + typedef FormatNavigator RegexSummaryNavigator; + + typedef ValueNavigator::MapType ValueMap; + typedef SummaryNavigator::MapType SummaryMap; + typedef RegexSummaryNavigator::MapType RegexSummaryMap; + typedef FormatMap NamedSummariesMap; ValueNavigator m_value_nav; SummaryNavigator m_summary_nav; RegexSummaryNavigator m_regex_summary_nav; - + + NamedSummariesMap m_named_summaries_map; + uint32_t m_last_revision; public: @@ -396,6 +477,7 @@ m_value_nav(this), m_summary_nav(this), m_regex_summary_nav(this), + m_named_summaries_map(this), m_last_revision(0) { } @@ -404,7 +486,7 @@ ValueNavigator& Value() { return m_value_nav; } SummaryNavigator& Summary() { return m_summary_nav; } RegexSummaryNavigator& RegexSummary() { return m_regex_summary_nav; } - + NamedSummariesMap& NamedSummary() { return m_named_summaries_map; } static bool GetFormatFromCString (const char *format_cstr, Modified: lldb/trunk/include/lldb/Core/ValueObject.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/ValueObject.h?rev=134943&r1=134942&r2=134943&view=diff ============================================================================== --- lldb/trunk/include/lldb/Core/ValueObject.h (original) +++ lldb/trunk/include/lldb/Core/ValueObject.h Mon Jul 11 19:18:11 2011 @@ -93,6 +93,7 @@ eUnexpectedSymbol, // something is malformed in the expression eTakingAddressFailed, // impossible to apply & operator eDereferencingFailed, // impossible to apply * operator + eRangeOperatorExpanded, // [] was expanded into a VOList eUnknown = 0xFFFF }; @@ -102,6 +103,7 @@ eBitfield, // a bitfield eBoundedRange, // a range [low-high] eUnboundedRange, // a range [] + eValueObjectList, // several items in a VOList eInvalid = 0xFFFF }; @@ -392,6 +394,15 @@ const GetValueForExpressionPathOptions& options = GetValueForExpressionPathOptions::DefaultOptions(), ExpressionPathAftermath* final_task_on_target = NULL); + int + GetValuesForExpressionPath(const char* expression, + lldb::ValueObjectListSP& list, + const char** first_unparsed = NULL, + ExpressionPathScanEndReason* reason_to_stop = NULL, + ExpressionPathEndResultType* final_value_type = NULL, + const GetValueForExpressionPathOptions& options = GetValueForExpressionPathOptions::DefaultOptions(), + ExpressionPathAftermath* final_task_on_target = NULL); + virtual bool IsInScope () { @@ -581,6 +592,17 @@ lldb::DynamicValueType use_dynamic, bool scope_already_checked, bool flat_output); + + // returns true if this is a char* or a char[] + // if it is a char* and check_pointer is true, + // it also checks that the pointer is valid + bool + IsCStringContainer(bool check_pointer = false); + + void + ReadPointedString(Stream& s, + Error& error, + uint32_t max_length = 0); bool GetIsConstant () const @@ -609,6 +631,42 @@ m_value_str.clear(); m_format = format; } + + void + SetCustomSummaryFormat(lldb::SummaryFormatSP format) + { + m_forced_summary_format = format; + m_user_id_of_forced_summary = m_update_point.GetUpdateID(); + m_summary_str.clear(); + } + + lldb::SummaryFormatSP + GetCustomSummaryFormat() + { + return m_forced_summary_format; + } + + void + ClearCustomSummaryFormat() + { + m_forced_summary_format.reset(); + m_summary_str.clear(); + } + + bool + HasCustomSummaryFormat() + { + return (m_forced_summary_format.get()); + } + + lldb::SummaryFormatSP + GetSummaryFormat() + { + UpdateFormatsIfNeeded(); + if (HasCustomSummaryFormat()) + return m_forced_summary_format; + return m_last_summary_format; + } // Use GetParent for display purposes, but if you want to tell the parent to update itself // then use m_parent. The ValueObjectDynamicValue's parent is not the correct parent for @@ -668,10 +726,12 @@ // as an independent ValueObjectConstResult, which isn't managed by us. ValueObject *m_deref_valobj; - lldb::Format m_format; - uint32_t m_last_format_mgr_revision; - lldb::SummaryFormatSP m_last_summary_format; - lldb::ValueFormatSP m_last_value_format; + lldb::Format m_format; + uint32_t m_last_format_mgr_revision; + lldb::SummaryFormatSP m_last_summary_format; + lldb::ValueFormatSP m_last_value_format; + lldb::SummaryFormatSP m_forced_summary_format; + lldb::user_id_t m_user_id_of_forced_summary; bool m_value_is_valid:1, m_value_did_change:1, m_children_count_valid:1, @@ -753,12 +813,27 @@ //------------------------------------------------------------------ lldb::ValueObjectSP - GetValueForExpressionPath_Impl(const char* expression, + GetValueForExpressionPath_Impl(const char* expression_cstr, const char** first_unparsed, ExpressionPathScanEndReason* reason_to_stop, ExpressionPathEndResultType* final_value_type, const GetValueForExpressionPathOptions& options, ExpressionPathAftermath* final_task_on_target); + + // this method will ONLY expand [] expressions into a VOList and return + // the number of elements it added to the VOList + // it will NOT loop through expanding the follow-up of the expression_cstr + // for all objects in the list + int + ExpandArraySliceExpression(const char* expression_cstr, + const char** first_unparsed, + lldb::ValueObjectSP root, + lldb::ValueObjectListSP& list, + ExpressionPathScanEndReason* reason_to_stop, + ExpressionPathEndResultType* final_value_type, + const GetValueForExpressionPathOptions& options, + ExpressionPathAftermath* final_task_on_target); + DISALLOW_COPY_AND_ASSIGN (ValueObject); Modified: lldb/trunk/include/lldb/Interpreter/OptionGroupVariable.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Interpreter/OptionGroupVariable.h?rev=134943&r1=134942&r2=134943&view=diff ============================================================================== --- lldb/trunk/include/lldb/Interpreter/OptionGroupVariable.h (original) +++ lldb/trunk/include/lldb/Interpreter/OptionGroupVariable.h Mon Jul 11 19:18:11 2011 @@ -53,6 +53,7 @@ show_scope:1, show_decl:1; lldb::Format format; + std::string summary; private: DISALLOW_COPY_AND_ASSIGN(OptionGroupVariable); Modified: lldb/trunk/include/lldb/Symbol/ClangASTContext.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Symbol/ClangASTContext.h?rev=134943&r1=134942&r2=134943&view=diff ============================================================================== --- lldb/trunk/include/lldb/Symbol/ClangASTContext.h (original) +++ lldb/trunk/include/lldb/Symbol/ClangASTContext.h Mon Jul 11 19:18:11 2011 @@ -49,7 +49,8 @@ eTypeIsStructUnion = (1u << 13), eTypeIsTemplate = (1u << 14), eTypeIsTypedef = (1u << 15), - eTypeIsVector = (1u << 16) + eTypeIsVector = (1u << 16), + eTypeIsScalar = (1u << 17), }; typedef void (*CompleteTagDeclCallback)(void *baton, clang::TagDecl *); Modified: lldb/trunk/include/lldb/Utility/CleanUp.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Utility/CleanUp.h?rev=134943&r1=134942&r2=134943&view=diff ============================================================================== --- lldb/trunk/include/lldb/Utility/CleanUp.h (original) +++ lldb/trunk/include/lldb/Utility/CleanUp.h Mon Jul 11 19:18:11 2011 @@ -52,7 +52,7 @@ // // malloc/free example // CleanUp malloced_bytes(malloc(32), NULL, free); //---------------------------------------------------------------------- -template +template class CleanUp { public: @@ -182,6 +182,140 @@ // Outlaw default constructor, copy constructor and the assignment operator DISALLOW_COPY_AND_ASSIGN (CleanUp); }; + +template +class CleanUp2 +{ +public: + typedef T value_type; + typedef R (*CallbackType)(value_type, A0); + + //---------------------------------------------------------------------- + // Constructor that sets the current value only. No values are + // considered to be invalid and the cleanup function will be called + // regardless of the value of m_current_value. + //---------------------------------------------------------------------- + CleanUp2 (value_type value, CallbackType callback, A0 arg) : + m_current_value (value), + m_invalid_value (), + m_callback (callback), + m_callback_called (false), + m_invalid_value_is_valid (false), + m_argument(arg) + { + } + + //---------------------------------------------------------------------- + // Constructor that sets the current value and also the invalid value. + // The cleanup function will be called on "m_value" as long as it isn't + // equal to "m_invalid_value". + //---------------------------------------------------------------------- + CleanUp2 (value_type value, value_type invalid, CallbackType callback, A0 arg) : + m_current_value (value), + m_invalid_value (invalid), + m_callback (callback), + m_callback_called (false), + m_invalid_value_is_valid (true), + m_argument(arg) + { + } + + //---------------------------------------------------------------------- + // Automatically cleanup when this object goes out of scope. + //---------------------------------------------------------------------- + ~CleanUp2 () + { + clean(); + } + + //---------------------------------------------------------------------- + // Access the value stored in this class + //---------------------------------------------------------------------- + value_type get() + { + return m_current_value; + } + + //---------------------------------------------------------------------- + // Access the value stored in this class + //---------------------------------------------------------------------- + const value_type + get() const + { + return m_current_value; + } + + //---------------------------------------------------------------------- + // Reset the owned value to "value". If a current value is valid and + // the cleanup callback hasn't been called, the previous value will + // be cleaned up (see void CleanUp::clean()). + //---------------------------------------------------------------------- + void + set (const value_type value) + { + // Cleanup the current value if needed + clean (); + // Now set the new value and mark our callback as not called + m_callback_called = false; + m_current_value = value; + } + + //---------------------------------------------------------------------- + // Checks is "m_current_value" is valid. The value is considered valid + // no invalid value was supplied during construction of this object or + // if an invalid value was supplied and "m_current_value" is not equal + // to "m_invalid_value". + // + // Returns true if "m_current_value" is valid, false otherwise. + //---------------------------------------------------------------------- + bool + is_valid() const + { + if (m_invalid_value_is_valid) + return m_current_value != m_invalid_value; + return true; + } + + //---------------------------------------------------------------------- + // This function will call the cleanup callback provided in the + // constructor one time if the value is considered valid (See is_valid()). + // This function sets m_callback_called to true so we don't call the + // cleanup callback multiple times on the same value. + //---------------------------------------------------------------------- + void + clean() + { + if (m_callback && !m_callback_called) + { + m_callback_called = true; + if (is_valid()) + m_callback(m_current_value, m_argument); + } + } + + //---------------------------------------------------------------------- + // Cancels the cleanup that would have been called on "m_current_value" + // if it was valid. This function can be used to release the value + // contained in this object so ownership can be transfered to the caller. + //---------------------------------------------------------------------- + value_type + release () + { + m_callback_called = true; + return m_current_value; + } + +private: + value_type m_current_value; + const value_type m_invalid_value; + CallbackType m_callback; + bool m_callback_called; + bool m_invalid_value_is_valid; + A0 m_argument; + + // Outlaw default constructor, copy constructor and the assignment operator + DISALLOW_COPY_AND_ASSIGN (CleanUp2); +}; } // namespace lldb_utility Modified: lldb/trunk/source/Commands/CommandObjectFrame.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectFrame.cpp?rev=134943&r1=134942&r2=134943&view=diff ============================================================================== --- lldb/trunk/source/Commands/CommandObjectFrame.cpp (original) +++ lldb/trunk/source/Commands/CommandObjectFrame.cpp Mon Jul 11 19:18:11 2011 @@ -439,6 +439,10 @@ const char *name_cstr = NULL; size_t idx; + + SummaryFormatSP summary_format_sp; + if (!m_option_variable.summary.empty()) + Debugger::NamedSummaryFormats::Get(ConstString(m_option_variable.summary.c_str()), summary_format_sp); if (variable_list) { @@ -484,7 +488,8 @@ if (var_sp->DumpDeclaration(&s, show_fullpaths, show_module)) s.PutCString (": "); } - + if (summary_format_sp) + valobj_sp->SetCustomSummaryFormat(summary_format_sp); ValueObject::DumpValueObject (result.GetOutputStream(), valobj_sp.get(), var_sp->GetName().AsCString(), @@ -534,6 +539,8 @@ var_sp->GetDeclaration ().DumpStopContext (&s, false); s.PutCString (": "); } + if (summary_format_sp) + valobj_sp->SetCustomSummaryFormat(summary_format_sp); ValueObject::DumpValueObject (result.GetOutputStream(), valobj_sp.get(), valobj_sp->GetParent() ? name_cstr : NULL, @@ -622,6 +629,8 @@ var_sp->GetDeclaration ().DumpStopContext (&s, false); s.PutCString (": "); } + if (summary_format_sp) + valobj_sp->SetCustomSummaryFormat(summary_format_sp); ValueObject::DumpValueObject (result.GetOutputStream(), valobj_sp.get(), name_cstr, Modified: lldb/trunk/source/Commands/CommandObjectType.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectType.cpp?rev=134943&r1=134942&r2=134943&view=diff ============================================================================== --- lldb/trunk/source/Commands/CommandObjectType.cpp (original) +++ lldb/trunk/source/Commands/CommandObjectType.cpp Mon Jul 11 19:18:11 2011 @@ -468,6 +468,9 @@ case 'x': m_regex = true; break; + case 'n': + m_name = new ConstString(option_arg); + break; default: error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option); break; @@ -486,6 +489,7 @@ m_skip_references = false; m_skip_pointers = false; m_regex = false; + m_name = NULL; } const OptionDefinition* @@ -508,6 +512,7 @@ bool m_skip_pointers; bool m_regex; std::string m_format_string; + ConstString* m_name; }; CommandOptions m_options; @@ -601,7 +606,7 @@ { const size_t argc = command.GetArgumentCount(); - if (argc < 1) + if (argc < 1 && !m_options.m_name) { result.AppendErrorWithFormat ("%s takes one or more args.\n", m_cmd_name.c_str()); result.SetStatus(eReturnStatusFailed); @@ -636,14 +641,14 @@ for(int i = 0; i < argc; i++) { const char* typeA = command.GetArgumentAtIndex(i); - if(!typeA || typeA[0] == '\0') + if (!typeA || typeA[0] == '\0') { result.AppendError("empty typenames not allowed"); result.SetStatus(eReturnStatusFailed); return false; } ConstString typeCS(typeA); - if(!m_options.m_regex) + if (!m_options.m_regex) { Debugger::SummaryFormats::Add(typeCS, entry); } @@ -660,6 +665,21 @@ Debugger::RegexSummaryFormats::Add(typeRX, entry); } } + + if (m_options.m_name) + { + if( (bool)(*(m_options.m_name)) ) + { + Debugger::NamedSummaryFormats::Add(*(m_options.m_name), entry); + } + else + { + result.AppendError("added to types, but not given a name"); + result.SetStatus(eReturnStatusFailed); + return false; + } + } + result.SetStatus(eReturnStatusSuccessFinishNoResult); return result.Succeeded(); } @@ -676,7 +696,8 @@ { LLDB_OPT_SET_ALL, false, "regex", 'x', no_argument, NULL, 0, eArgTypeBoolean, "Type names are actually regular expressions."}, { LLDB_OPT_SET_1 , true, "inline-children", 'c', no_argument, NULL, 0, eArgTypeBoolean, "If true, inline all child values into summary string."}, { LLDB_OPT_SET_2 , true, "format-string", 'f', required_argument, NULL, 0, eArgTypeSummaryString, "Format string used to display text and object contents."}, - { LLDB_OPT_SET_2, false, "expand", 'e', no_argument, NULL, 0, eArgTypeBoolean, "Expand aggregate data types to show children on separate lines."}, + { LLDB_OPT_SET_2, false, "expand", 'e', no_argument, NULL, 0, eArgTypeBoolean, "Expand aggregate data types to show children on separate lines."}, + { LLDB_OPT_SET_2, false, "name", 'n', required_argument, NULL, 0, eArgTypeName, "A name for this summary string."}, { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } }; @@ -734,7 +755,9 @@ bool delete_summary = Debugger::SummaryFormats::Delete(typeCS); bool delete_regex = Debugger::RegexSummaryFormats::Delete(typeCS); - if (delete_summary || delete_regex) + bool delete_named = Debugger::NamedSummaryFormats::Delete(typeCS); + + if (delete_summary || delete_regex || delete_named) { result.SetStatus(eReturnStatusSuccessFinishNoResult); return result.Succeeded(); @@ -774,6 +797,7 @@ { Debugger::SummaryFormats::Clear(); Debugger::RegexSummaryFormats::Clear(); + Debugger::NamedSummaryFormats::Clear(); result.SetStatus(eReturnStatusSuccessFinishResult); return result.Succeeded(); } @@ -847,22 +871,33 @@ Debugger::SummaryFormats::LoopThrough(CommandObjectTypeSummaryList_LoopCallback, param); delete param; - if(Debugger::RegexSummaryFormats::GetCount() == 0) + if(Debugger::RegexSummaryFormats::GetCount() > 0) { - result.SetStatus(eReturnStatusSuccessFinishResult); - return result.Succeeded(); + result.GetOutputStream().Printf("Regex-based summaries (slower):\n"); + if (argc == 1) { + RegularExpression* regex = new RegularExpression(command.GetArgumentAtIndex(0)); + regex->Compile(command.GetArgumentAtIndex(0)); + rxparam = new CommandObjectTypeRXSummaryList_LoopCallbackParam(this,&result,regex); + } + else + rxparam = new CommandObjectTypeRXSummaryList_LoopCallbackParam(this,&result); + Debugger::RegexSummaryFormats::LoopThrough(CommandObjectTypeRXSummaryList_LoopCallback, rxparam); + delete rxparam; } - result.GetOutputStream().Printf("Regex-based summaries (slower):\n"); - if (argc == 1) { - RegularExpression* regex = new RegularExpression(command.GetArgumentAtIndex(0)); - regex->Compile(command.GetArgumentAtIndex(0)); - rxparam = new CommandObjectTypeRXSummaryList_LoopCallbackParam(this,&result,regex); + if(Debugger::NamedSummaryFormats::GetCount() > 0) + { + result.GetOutputStream().Printf("Named summaries:\n"); + if (argc == 1) { + RegularExpression* regex = new RegularExpression(command.GetArgumentAtIndex(0)); + regex->Compile(command.GetArgumentAtIndex(0)); + param = new CommandObjectTypeSummaryList_LoopCallbackParam(this,&result,regex); + } + else + param = new CommandObjectTypeSummaryList_LoopCallbackParam(this,&result); + Debugger::NamedSummaryFormats::LoopThrough(CommandObjectTypeSummaryList_LoopCallback, param); + delete param; } - else - rxparam = new CommandObjectTypeRXSummaryList_LoopCallbackParam(this,&result); - Debugger::RegexSummaryFormats::LoopThrough(CommandObjectTypeRXSummaryList_LoopCallback, rxparam); - delete rxparam; result.SetStatus(eReturnStatusSuccessFinishResult); return result.Succeeded(); Modified: lldb/trunk/source/Core/Debugger.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/Debugger.cpp?rev=134943&r1=134942&r2=134943&view=diff ============================================================================== --- lldb/trunk/source/Core/Debugger.cpp (original) +++ lldb/trunk/source/Core/Debugger.cpp Mon Jul 11 19:18:11 2011 @@ -1821,6 +1821,48 @@ return GetFormatManager().RegexSummary().GetCount(); } +bool +Debugger::NamedSummaryFormats::Get(const ConstString &type, SummaryFormat::SharedPointer &entry) +{ + return GetFormatManager().NamedSummary().Get(type.AsCString(),entry); +} + +void +Debugger::NamedSummaryFormats::Add(const ConstString &type, const SummaryFormat::SharedPointer &entry) +{ + GetFormatManager().NamedSummary().Add(type.AsCString(),entry); +} + +bool +Debugger::NamedSummaryFormats::Delete(const ConstString &type) +{ + return GetFormatManager().NamedSummary().Delete(type.AsCString()); +} + +void +Debugger::NamedSummaryFormats::Clear() +{ + GetFormatManager().NamedSummary().Clear(); +} + +void +Debugger::NamedSummaryFormats::LoopThrough(SummaryFormat::SummaryCallback callback, void* callback_baton) +{ + GetFormatManager().NamedSummary().LoopThrough(callback, callback_baton); +} + +uint32_t +Debugger::NamedSummaryFormats::GetCurrentRevision() +{ + return GetFormatManager().GetCurrentRevision(); +} + +uint32_t +Debugger::NamedSummaryFormats::GetCount() +{ + return GetFormatManager().NamedSummary().GetCount(); +} + #pragma mark Debugger::SettingsController //-------------------------------------------------- Modified: lldb/trunk/source/Core/FormatManager.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/FormatManager.cpp?rev=134943&r1=134942&r2=134943&view=diff ============================================================================== --- lldb/trunk/source/Core/FormatManager.cpp (original) +++ lldb/trunk/source/Core/FormatManager.cpp Mon Jul 11 19:18:11 2011 @@ -154,12 +154,11 @@ template<> bool -FormatNavigator, SummaryFormat::RegexSummaryCallback>::Get(const char* key, - SummaryFormat::SharedPointer& value) +FormatNavigator::Get(const char* key, SummaryFormat::SharedPointer& value) { - Mutex::Locker(m_map_mutex); - MapIterator pos, end = m_map.end(); - for (pos = m_map.begin(); pos != end; pos++) + Mutex::Locker(m_format_map.mutex()); + MapIterator pos, end = m_format_map.map().end(); + for (pos = m_format_map.map().begin(); pos != end; pos++) { lldb::RegularExpressionSP regex = pos->first; if (regex->Execute(key)) @@ -173,16 +172,16 @@ template<> bool -FormatNavigator, SummaryFormat::RegexSummaryCallback>::Delete(const char* type) +FormatNavigator::Delete(const char* type) { - Mutex::Locker(m_map_mutex); - MapIterator pos, end = m_map.end(); - for (pos = m_map.begin(); pos != end; pos++) + Mutex::Locker(m_format_map.mutex()); + MapIterator pos, end = m_format_map.map().end(); + for (pos = m_format_map.map().begin(); pos != end; pos++) { lldb::RegularExpressionSP regex = pos->first; if ( ::strcmp(type,regex->GetText()) == 0) { - m_map.erase(pos); + m_format_map.map().erase(pos); return true; } } Modified: lldb/trunk/source/Core/ValueObject.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/ValueObject.cpp?rev=134943&r1=134942&r2=134943&view=diff ============================================================================== --- lldb/trunk/source/Core/ValueObject.cpp (original) +++ lldb/trunk/source/Core/ValueObject.cpp Mon Jul 11 19:18:11 2011 @@ -77,7 +77,8 @@ m_is_bitfield_for_scalar(false), m_last_format_mgr_revision(0), m_last_summary_format(), - m_last_value_format() + m_last_value_format(), + m_forced_summary_format() { m_manager->ManageObject(this); } @@ -114,7 +115,8 @@ m_is_bitfield_for_scalar(false), m_last_format_mgr_revision(0), m_last_summary_format(), - m_last_value_format() + m_last_value_format(), + m_forced_summary_format() { m_manager = new ValueObjectManager(); m_manager->ManageObject (this); @@ -189,6 +191,11 @@ /*printf("CHECKING FOR UPDATES. I am at revision %d, while the format manager is at revision %d\n", m_last_format_mgr_revision, Debugger::ValueFormats::GetCurrentRevision());*/ + if (HasCustomSummaryFormat() && m_update_point.GetUpdateID() != m_user_id_of_forced_summary) + { + ClearCustomSummaryFormat(); + m_summary_str.clear(); + } if (m_last_format_mgr_revision != Debugger::ValueFormats::GetCurrentRevision()) { if (m_last_summary_format.get()) @@ -495,7 +502,9 @@ { if (m_summary_str.empty()) { - if (m_last_summary_format.get()) + SummaryFormat* summary_format = GetSummaryFormat().get(); + + if (summary_format) { StreamString s; ExecutionContext exe_ctx; @@ -504,7 +513,7 @@ if (exe_ctx.frame) sc = exe_ctx.frame->GetSymbolContext(eSymbolContextEverything); - if (m_last_summary_format->m_show_members_oneliner) + if (summary_format->m_show_members_oneliner) { const uint32_t num_children = GetNumChildren(); if (num_children) @@ -536,7 +545,7 @@ } else { - if (Debugger::FormatPrompt(m_last_summary_format->m_format.c_str(), &sc, &exe_ctx, &sc.line_entry.range.GetBaseAddress(), s, NULL, this)) + if (Debugger::FormatPrompt(summary_format->m_format.c_str(), &sc, &exe_ctx, &sc.line_entry.range.GetBaseAddress(), s, NULL, this)) { m_summary_str.swap(s.GetString()); return m_summary_str.c_str(); @@ -719,6 +728,157 @@ return m_summary_str.c_str(); } +bool +ValueObject::IsCStringContainer(bool check_pointer) +{ + clang_type_t elem_or_pointee_clang_type; + const Flags type_flags (ClangASTContext::GetTypeInfo (GetClangType(), + GetClangAST(), + &elem_or_pointee_clang_type)); + bool is_char_arr_ptr (type_flags.AnySet (ClangASTContext::eTypeIsArray | ClangASTContext::eTypeIsPointer) && + ClangASTContext::IsCharType (elem_or_pointee_clang_type)); + if (!is_char_arr_ptr) + return false; + if (!check_pointer) + return true; + if (type_flags.Test(ClangASTContext::eTypeIsArray)) + return true; + lldb::addr_t cstr_address = LLDB_INVALID_ADDRESS; + AddressType cstr_address_type = eAddressTypeInvalid; + cstr_address = GetAddressOf (cstr_address_type, true); + return (cstr_address != LLDB_INVALID_ADDRESS); +} + +void +ValueObject::ReadPointedString(Stream& s, + Error& error, + uint32_t max_length) +{ + + if (max_length == 0) + max_length = 128; // this should be a setting, or a formatting parameter + + clang_type_t clang_type = GetClangType(); + clang_type_t elem_or_pointee_clang_type; + const Flags type_flags (ClangASTContext::GetTypeInfo (clang_type, + GetClangAST(), + &elem_or_pointee_clang_type)); + if (type_flags.AnySet (ClangASTContext::eTypeIsArray | ClangASTContext::eTypeIsPointer) && + ClangASTContext::IsCharType (elem_or_pointee_clang_type)) + { + ExecutionContextScope *exe_scope = GetExecutionContextScope(); + if (exe_scope) + { + Target *target = exe_scope->CalculateTarget(); + if (target != NULL) + { + lldb::addr_t cstr_address = LLDB_INVALID_ADDRESS; + AddressType cstr_address_type = eAddressTypeInvalid; + + size_t cstr_len = 0; + bool capped_data = false; + if (type_flags.Test (ClangASTContext::eTypeIsArray)) + { + // We have an array + cstr_len = ClangASTContext::GetArraySize (clang_type); + if (cstr_len > max_length) // TODO: make cap a setting + { + cstr_len = ClangASTContext::GetArraySize (clang_type); + if (cstr_len > max_length) // TODO: make cap a setting + { + capped_data = true; + cstr_len = max_length; + } + } + cstr_address = GetAddressOf (cstr_address_type, true); + } + else + { + // We have a pointer + cstr_address = GetPointerValue (cstr_address_type, true); + } + if (cstr_address != LLDB_INVALID_ADDRESS) + { + Address cstr_so_addr (NULL, cstr_address); + DataExtractor data; + size_t bytes_read = 0; + std::vector data_buffer; + Error error; + bool prefer_file_cache = false; + if (cstr_len > 0) + { + data_buffer.resize(cstr_len); + data.SetData (&data_buffer.front(), data_buffer.size(), lldb::endian::InlHostByteOrder()); + bytes_read = target->ReadMemory (cstr_so_addr, + prefer_file_cache, + &data_buffer.front(), + cstr_len, + error); + if (bytes_read > 0) + { + s << '"'; + data.Dump (&s, + 0, // Start offset in "data" + eFormatCharArray, // Print as characters + 1, // Size of item (1 byte for a char!) + bytes_read, // How many bytes to print? + UINT32_MAX, // num per line + LLDB_INVALID_ADDRESS,// base address + 0, // bitfield bit size + 0); // bitfield bit offset + if (capped_data) + s << "..."; + s << '"'; + } + } + else + { + const size_t k_max_buf_size = 256; + data_buffer.resize (k_max_buf_size + 1); + // NULL terminate in case we don't get the entire C string + data_buffer.back() = '\0'; + + s << '"'; + + data.SetData (&data_buffer.front(), data_buffer.size(), endian::InlHostByteOrder()); + while ((bytes_read = target->ReadMemory (cstr_so_addr, + prefer_file_cache, + &data_buffer.front(), + k_max_buf_size, + error)) > 0) + { + size_t len = strlen(&data_buffer.front()); + if (len == 0) + break; + if (len > bytes_read) + len = bytes_read; + + data.Dump (&s, + 0, // Start offset in "data" + eFormatCharArray, // Print as characters + 1, // Size of item (1 byte for a char!) + len, // How many bytes to print? + UINT32_MAX, // num per line + LLDB_INVALID_ADDRESS,// base address + 0, // bitfield bit size + 0); // bitfield bit offset + + if (len < k_max_buf_size) + break; + cstr_so_addr.Slide (k_max_buf_size); + } + s << '"'; + } + } + } + } + } + else + { + error.SetErrorString("impossible to read a string from this object"); + } +} + const char * ValueObject::GetObjectDescription () { @@ -894,13 +1054,25 @@ ValueObjectRepresentationStyle val_obj_display, lldb::Format custom_format) { - const char *targetvalue = GetPrintableRepresentation(val_obj_display, custom_format); - if(targetvalue) - s.PutCString(targetvalue); - bool var_success = (targetvalue != NULL); - if(custom_format != eFormatInvalid) - SetFormat(eFormatDefault); - return var_success; + + if (IsCStringContainer(true) && + val_obj_display == ValueObject::eDisplayValue && + custom_format == lldb::eFormatCString) + { + Error error; + ReadPointedString(s, error); + return error.Success(); + } + else + { + const char *targetvalue = GetPrintableRepresentation(val_obj_display, custom_format); + if(targetvalue) + s.PutCString(targetvalue); + bool var_success = (targetvalue != NULL); + if(custom_format != eFormatInvalid) + SetFormat(eFormatDefault); + return var_success; + } } addr_t @@ -1503,6 +1675,92 @@ return ret_val; // final_task_on_target will still have its original value, so you know I did not do it } +int +ValueObject::GetValuesForExpressionPath(const char* expression, + lldb::ValueObjectListSP& list, + const char** first_unparsed, + ExpressionPathScanEndReason* reason_to_stop, + ExpressionPathEndResultType* final_value_type, + const GetValueForExpressionPathOptions& options, + ExpressionPathAftermath* final_task_on_target) +{ + const char* dummy_first_unparsed; + ExpressionPathScanEndReason dummy_reason_to_stop; + ExpressionPathEndResultType dummy_final_value_type; + ExpressionPathAftermath dummy_final_task_on_target = ValueObject::eNothing; + + ValueObjectSP ret_val = GetValueForExpressionPath_Impl(expression, + first_unparsed ? first_unparsed : &dummy_first_unparsed, + reason_to_stop ? reason_to_stop : &dummy_reason_to_stop, + final_value_type ? final_value_type : &dummy_final_value_type, + options, + final_task_on_target ? final_task_on_target : &dummy_final_task_on_target); + + if (!ret_val.get()) // if there are errors, I add nothing to the list + return 0; + + if (*reason_to_stop != eArrayRangeOperatorMet) + { + // I need not expand a range, just post-process the final value and return + if (!final_task_on_target || *final_task_on_target == ValueObject::eNothing) + { + list->Append(ret_val); + return 1; + } + if (ret_val.get() && *final_value_type == ePlain) // I can only deref and takeaddress of plain objects + { + if (*final_task_on_target == ValueObject::eDereference) + { + Error error; + ValueObjectSP final_value = ret_val->Dereference(error); + if (error.Fail() || !final_value.get()) + { + *reason_to_stop = ValueObject::eDereferencingFailed; + *final_value_type = ValueObject::eInvalid; + return 0; + } + else + { + *final_task_on_target = ValueObject::eNothing; + list->Append(final_value); + return 1; + } + } + if (*final_task_on_target == ValueObject::eTakeAddress) + { + Error error; + ValueObjectSP final_value = ret_val->AddressOf(error); + if (error.Fail() || !final_value.get()) + { + *reason_to_stop = ValueObject::eTakingAddressFailed; + *final_value_type = ValueObject::eInvalid; + return 0; + } + else + { + *final_task_on_target = ValueObject::eNothing; + list->Append(final_value); + return 1; + } + } + } + } + else + { + return ExpandArraySliceExpression(first_unparsed ? *first_unparsed : dummy_first_unparsed, + first_unparsed ? first_unparsed : &dummy_first_unparsed, + ret_val, + list, + reason_to_stop ? reason_to_stop : &dummy_reason_to_stop, + final_value_type ? final_value_type : &dummy_final_value_type, + options, + final_task_on_target ? final_task_on_target : &dummy_final_task_on_target); + } + // in any non-covered case, just do the obviously right thing + list->Append(ret_val); + return 1; +} + lldb::ValueObjectSP ValueObject::GetValueForExpressionPath_Impl(const char* expression_cstr, const char** first_unparsed, @@ -1524,6 +1782,12 @@ const char* expression_cstr = *first_unparsed; // hide the top level expression_cstr lldb::clang_type_t root_clang_type = root->GetClangType(); + lldb::clang_type_t pointee_clang_type; + Flags root_clang_type_info,pointee_clang_type_info; + + root_clang_type_info = Flags(ClangASTContext::GetTypeInfo(root_clang_type, GetClangAST(), &pointee_clang_type)); + if (pointee_clang_type) + pointee_clang_type_info = Flags(ClangASTContext::GetTypeInfo(pointee_clang_type, GetClangAST(), NULL)); if (!expression_cstr || *expression_cstr == '\0') { @@ -1536,16 +1800,15 @@ case '-': { if (options.m_check_dot_vs_arrow_syntax && - !ClangASTContext::IsPointerType(root_clang_type)) // if you are trying to use -> on a non-pointer and I must catch the error + root_clang_type_info.Test(ClangASTContext::eTypeIsPointer) ) // if you are trying to use -> on a non-pointer and I must catch the error { *first_unparsed = expression_cstr; *reason_to_stop = ValueObject::eArrowInsteadOfDot; *final_result = ValueObject::eInvalid; return ValueObjectSP(); } - const uint32_t pointer_type_flags = ClangASTContext::GetTypeInfo (root_clang_type, NULL, NULL); - if ((pointer_type_flags & ClangASTContext::eTypeIsObjC) && // if yo are trying to extract an ObjC IVar when this is forbidden - (pointer_type_flags & ClangASTContext::eTypeIsPointer) && + if (root_clang_type_info.Test(ClangASTContext::eTypeIsObjC) && // if yo are trying to extract an ObjC IVar when this is forbidden + root_clang_type_info.Test(ClangASTContext::eTypeIsPointer) && options.m_no_fragile_ivar) { *first_unparsed = expression_cstr; @@ -1565,7 +1828,7 @@ case '.': // or fallthrough from -> { if (options.m_check_dot_vs_arrow_syntax && *expression_cstr == '.' && - ClangASTContext::IsPointerType(root_clang_type)) // if you are trying to use . on a pointer and I must catch the error + root_clang_type_info.Test(ClangASTContext::eTypeIsPointer)) // if you are trying to use . on a pointer and I must catch the error { *first_unparsed = expression_cstr; *reason_to_stop = ValueObject::eDotInsteadOfArrow; @@ -1616,9 +1879,9 @@ } case '[': { - if (!ClangASTContext::IsArrayType(root_clang_type) && !ClangASTContext::IsPointerType(root_clang_type)) // if this is not a T[] nor a T* + if (!root_clang_type_info.Test(ClangASTContext::eTypeIsArray) && !root_clang_type_info.Test(ClangASTContext::eTypeIsPointer)) // if this is not a T[] nor a T* { - if (!ClangASTContext::IsScalarType(root_clang_type)) // if this is not even a scalar, this syntax is just plain wrong! + if (!root_clang_type_info.Test(ClangASTContext::eTypeIsScalar)) // if this is not even a scalar, this syntax is just plain wrong! { *first_unparsed = expression_cstr; *reason_to_stop = ValueObject::eRangeOperatorInvalid; @@ -1635,7 +1898,7 @@ } if (*(expression_cstr+1) == ']') // if this is an unbounded range it only works for arrays { - if (!ClangASTContext::IsArrayType(root_clang_type)) + if (!root_clang_type_info.Test(ClangASTContext::eTypeIsArray)) { *first_unparsed = expression_cstr; *reason_to_stop = ValueObject::eEmptyRangeNotAllowed; @@ -1672,7 +1935,7 @@ } if (end - expression_cstr == 1) // if this is [], only return a valid value for arrays { - if (ClangASTContext::IsArrayType(root_clang_type)) + if (root_clang_type_info.Test(ClangASTContext::eTypeIsArray)) { *first_unparsed = expression_cstr+2; *reason_to_stop = ValueObject::eArrayRangeOperatorMet; @@ -1688,7 +1951,7 @@ } } // from here on we do have a valid index - if (ClangASTContext::IsArrayType(root_clang_type)) + if (root_clang_type_info.Test(ClangASTContext::eTypeIsArray)) { ValueObjectSP child_valobj_sp = root->GetChildAtIndex(index, true); if (!child_valobj_sp) @@ -1708,10 +1971,10 @@ return ValueObjectSP(); } } - else if (ClangASTContext::IsPointerType(root_clang_type)) + else if (root_clang_type_info.Test(ClangASTContext::eTypeIsPointer)) { if (*what_next == ValueObject::eDereference && // if this is a ptr-to-scalar, I am accessing it by index and I would have deref'ed anyway, then do it now and use this as a bitfield - ClangASTContext::IsScalarType(clang::QualType::getFromOpaquePtr(root_clang_type).getTypePtr()->getPointeeType().getAsOpaquePtr())) + pointee_clang_type_info.Test(ClangASTContext::eTypeIsScalar)) { Error error; root = root->Dereference(error); @@ -1790,7 +2053,7 @@ index_lower = index_higher; index_higher = temp; } - if (ClangASTContext::IsScalarType(root_clang_type)) // expansion only works for scalars + if (root_clang_type_info.Test(ClangASTContext::eTypeIsScalar)) // expansion only works for scalars { root = root->GetSyntheticBitFieldChild(index_lower, index_higher, true); if (!root.get()) @@ -1808,9 +2071,9 @@ return root; } } - else if (ClangASTContext::IsPointerType(root_clang_type) && // if this is a ptr-to-scalar, I am accessing it by index and I would have deref'ed anyway, then do it now and use this as a bitfield + else if (root_clang_type_info.Test(ClangASTContext::eTypeIsPointer) && // if this is a ptr-to-scalar, I am accessing it by index and I would have deref'ed anyway, then do it now and use this as a bitfield *what_next == ValueObject::eDereference && - ClangASTContext::IsScalarType(clang::QualType::getFromOpaquePtr(root_clang_type).getTypePtr()->getPointeeType().getAsOpaquePtr())) + pointee_clang_type_info.Test(ClangASTContext::eTypeIsScalar)) { Error error; root = root->Dereference(error); @@ -1849,6 +2112,302 @@ } } +int +ValueObject::ExpandArraySliceExpression(const char* expression_cstr, + const char** first_unparsed, + lldb::ValueObjectSP root, + lldb::ValueObjectListSP& list, + ExpressionPathScanEndReason* reason_to_stop, + ExpressionPathEndResultType* final_result, + const GetValueForExpressionPathOptions& options, + ExpressionPathAftermath* what_next) +{ + if (!root.get()) + return 0; + + *first_unparsed = expression_cstr; + + while (true) + { + + const char* expression_cstr = *first_unparsed; // hide the top level expression_cstr + + lldb::clang_type_t root_clang_type = root->GetClangType(); + lldb::clang_type_t pointee_clang_type; + Flags root_clang_type_info,pointee_clang_type_info; + + root_clang_type_info = Flags(ClangASTContext::GetTypeInfo(root_clang_type, GetClangAST(), &pointee_clang_type)); + if (pointee_clang_type) + pointee_clang_type_info = Flags(ClangASTContext::GetTypeInfo(pointee_clang_type, GetClangAST(), NULL)); + + if (!expression_cstr || *expression_cstr == '\0') + { + *reason_to_stop = ValueObject::eEndOfString; + list->Append(root); + return 1; + } + + switch (*expression_cstr) + { + case '[': + { + if (!root_clang_type_info.Test(ClangASTContext::eTypeIsArray) && !root_clang_type_info.Test(ClangASTContext::eTypeIsPointer)) // if this is not a T[] nor a T* + { + if (!root_clang_type_info.Test(ClangASTContext::eTypeIsScalar)) // if this is not even a scalar, this syntax is just plain wrong! + { + *first_unparsed = expression_cstr; + *reason_to_stop = ValueObject::eRangeOperatorInvalid; + *final_result = ValueObject::eInvalid; + return 0; + } + else if (!options.m_allow_bitfields_syntax) // if this is a scalar, check that we can expand bitfields + { + *first_unparsed = expression_cstr; + *reason_to_stop = ValueObject::eRangeOperatorNotAllowed; + *final_result = ValueObject::eInvalid; + return 0; + } + } + if (*(expression_cstr+1) == ']') // if this is an unbounded range it only works for arrays + { + if (!root_clang_type_info.Test(ClangASTContext::eTypeIsArray)) + { + *first_unparsed = expression_cstr; + *reason_to_stop = ValueObject::eEmptyRangeNotAllowed; + *final_result = ValueObject::eInvalid; + return 0; + } + else // expand this into list + { + int max_index = root->GetNumChildren() - 1; + for (int index = 0; index < max_index; index++) + { + ValueObjectSP child = + root->GetChildAtIndex(index, true); + list->Append(child); + } + *first_unparsed = expression_cstr+2; + *reason_to_stop = ValueObject::eRangeOperatorExpanded; + *final_result = ValueObject::eValueObjectList; + return max_index; // tell me number of items I added to the VOList + } + } + const char *separator_position = ::strchr(expression_cstr+1,'-'); + const char *close_bracket_position = ::strchr(expression_cstr+1,']'); + if (!close_bracket_position) // if there is no ], this is a syntax error + { + *first_unparsed = expression_cstr; + *reason_to_stop = ValueObject::eUnexpectedSymbol; + *final_result = ValueObject::eInvalid; + return 0; + } + if (!separator_position || separator_position > close_bracket_position) // if no separator, this is either [] or [N] + { + char *end = NULL; + unsigned long index = ::strtoul (expression_cstr+1, &end, 0); + if (!end || end != close_bracket_position) // if something weird is in our way return an error + { + *first_unparsed = expression_cstr; + *reason_to_stop = ValueObject::eUnexpectedSymbol; + *final_result = ValueObject::eInvalid; + return 0; + } + if (end - expression_cstr == 1) // if this is [], only return a valid value for arrays + { + if (root_clang_type_info.Test(ClangASTContext::eTypeIsArray)) + { + int max_index = root->GetNumChildren() - 1; + for (int index = 0; index < max_index; index++) + { + ValueObjectSP child = + root->GetChildAtIndex(index, true); + list->Append(child); + } + *first_unparsed = expression_cstr+2; + *reason_to_stop = ValueObject::eRangeOperatorExpanded; + *final_result = ValueObject::eValueObjectList; + return max_index; // tell me number of items I added to the VOList + } + else + { + *first_unparsed = expression_cstr; + *reason_to_stop = ValueObject::eEmptyRangeNotAllowed; + *final_result = ValueObject::eInvalid; + return 0; + } + } + // from here on we do have a valid index + if (root_clang_type_info.Test(ClangASTContext::eTypeIsArray)) + { + root = root->GetChildAtIndex(index, true); + if (!root.get()) + { + *first_unparsed = expression_cstr; + *reason_to_stop = ValueObject::eNoSuchChild; + *final_result = ValueObject::eInvalid; + return 0; + } + else + { + list->Append(root); + *first_unparsed = end+1; // skip ] + *reason_to_stop = ValueObject::eRangeOperatorExpanded; + *final_result = ValueObject::eValueObjectList; + return 1; + } + } + else if (root_clang_type_info.Test(ClangASTContext::eTypeIsPointer)) + { + if (*what_next == ValueObject::eDereference && // if this is a ptr-to-scalar, I am accessing it by index and I would have deref'ed anyway, then do it now and use this as a bitfield + pointee_clang_type_info.Test(ClangASTContext::eTypeIsScalar)) + { + Error error; + root = root->Dereference(error); + if (error.Fail() || !root.get()) + { + *first_unparsed = expression_cstr; + *reason_to_stop = ValueObject::eDereferencingFailed; + *final_result = ValueObject::eInvalid; + return 0; + } + else + { + *what_next = eNothing; + continue; + } + } + else + { + root = root->GetSyntheticArrayMemberFromPointer(index, true); + if (!root.get()) + { + *first_unparsed = expression_cstr; + *reason_to_stop = ValueObject::eNoSuchChild; + *final_result = ValueObject::eInvalid; + return 0; + } + else + { + list->Append(root); + *first_unparsed = end+1; // skip ] + *reason_to_stop = ValueObject::eRangeOperatorExpanded; + *final_result = ValueObject::eValueObjectList; + return 1; + } + } + } + else /*if (ClangASTContext::IsScalarType(root_clang_type))*/ + { + root = root->GetSyntheticBitFieldChild(index, index, true); + if (!root.get()) + { + *first_unparsed = expression_cstr; + *reason_to_stop = ValueObject::eNoSuchChild; + *final_result = ValueObject::eInvalid; + return 0; + } + else // we do not know how to expand members of bitfields, so we just return and let the caller do any further processing + { + list->Append(root); + *first_unparsed = end+1; // skip ] + *reason_to_stop = ValueObject::eRangeOperatorExpanded; + *final_result = ValueObject::eValueObjectList; + return 1; + } + } + } + else // we have a low and a high index + { + char *end = NULL; + unsigned long index_lower = ::strtoul (expression_cstr+1, &end, 0); + if (!end || end != separator_position) // if something weird is in our way return an error + { + *first_unparsed = expression_cstr; + *reason_to_stop = ValueObject::eUnexpectedSymbol; + *final_result = ValueObject::eInvalid; + return 0; + } + unsigned long index_higher = ::strtoul (separator_position+1, &end, 0); + if (!end || end != close_bracket_position) // if something weird is in our way return an error + { + *first_unparsed = expression_cstr; + *reason_to_stop = ValueObject::eUnexpectedSymbol; + *final_result = ValueObject::eInvalid; + return 0; + } + if (index_lower > index_higher) // swap indices if required + { + unsigned long temp = index_lower; + index_lower = index_higher; + index_higher = temp; + } + if (root_clang_type_info.Test(ClangASTContext::eTypeIsScalar)) // expansion only works for scalars + { + root = root->GetSyntheticBitFieldChild(index_lower, index_higher, true); + if (!root.get()) + { + *first_unparsed = expression_cstr; + *reason_to_stop = ValueObject::eNoSuchChild; + *final_result = ValueObject::eInvalid; + return 0; + } + else + { + list->Append(root); + *first_unparsed = end+1; // skip ] + *reason_to_stop = ValueObject::eRangeOperatorExpanded; + *final_result = ValueObject::eValueObjectList; + return 1; + } + } + else if (root_clang_type_info.Test(ClangASTContext::eTypeIsPointer) && // if this is a ptr-to-scalar, I am accessing it by index and I would have deref'ed anyway, then do it now and use this as a bitfield + *what_next == ValueObject::eDereference && + pointee_clang_type_info.Test(ClangASTContext::eTypeIsScalar)) + { + Error error; + root = root->Dereference(error); + if (error.Fail() || !root.get()) + { + *first_unparsed = expression_cstr; + *reason_to_stop = ValueObject::eDereferencingFailed; + *final_result = ValueObject::eInvalid; + return 0; + } + else + { + *what_next = ValueObject::eNothing; + continue; + } + } + else + { + for (int index = index_lower; + index <= index_higher; index++) + { + ValueObjectSP child = + root->GetChildAtIndex(index, true); + list->Append(child); + } + *first_unparsed = end+1; + *reason_to_stop = ValueObject::eRangeOperatorExpanded; + *final_result = ValueObject::eValueObjectList; + return index_higher-index_lower+1; // tell me number of items I added to the VOList + } + } + break; + } + default: // some non-[ separator, or something entirely wrong, is in the way + { + *first_unparsed = expression_cstr; + *reason_to_stop = ValueObject::eUnexpectedSymbol; + *final_result = ValueObject::eInvalid; + return 0; + break; + } + } + } +} + void ValueObject::DumpValueObject ( @@ -1921,7 +2480,7 @@ const char *val_cstr = NULL; const char *sum_cstr = NULL; - SummaryFormat* entry = valobj->m_last_summary_format.get(); + SummaryFormat* entry = valobj->GetSummaryFormat().get(); if (err_cstr == NULL) { Modified: lldb/trunk/source/Interpreter/CommandInterpreter.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/CommandInterpreter.cpp?rev=134943&r1=134942&r2=134943&view=diff ============================================================================== --- lldb/trunk/source/Interpreter/CommandInterpreter.cpp (original) +++ lldb/trunk/source/Interpreter/CommandInterpreter.cpp Mon Jul 11 19:18:11 2011 @@ -935,7 +935,7 @@ // Make a scoped cleanup object that will clear the crash description string // on exit of this function. - lldb_utility::CleanUp crash_description_cleanup(NULL, Host::SetCrashDescription); + lldb_utility::CleanUp crash_description_cleanup(NULL, Host::SetCrashDescription); if (log) log->Printf ("Processing command: %s", command_line); Modified: lldb/trunk/source/Interpreter/OptionGroupVariable.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/OptionGroupVariable.cpp?rev=134943&r1=134942&r2=134943&view=diff ============================================================================== --- lldb/trunk/source/Interpreter/OptionGroupVariable.cpp (original) +++ lldb/trunk/source/Interpreter/OptionGroupVariable.cpp Mon Jul 11 19:18:11 2011 @@ -19,6 +19,7 @@ using namespace lldb; using namespace lldb_private; +// if you add any options here, remember to update the counters in OptionGroupVariable::GetNumDefinitions() static OptionDefinition g_option_table[] = { @@ -28,7 +29,8 @@ { LLDB_OPT_SET_1, false, "show-declaration",'c', no_argument, NULL, 0, eArgTypeNone, "Show variable declaration information (source file and line where the variable was declared)."}, { LLDB_OPT_SET_1, false, "format", 'f', required_argument, NULL, 0, eArgTypeExprFormat, "Specify the format that the variable output should use."}, { LLDB_OPT_SET_1, false, "regex", 'r', no_argument, NULL, 0, eArgTypeRegularExpression, "The argument for name lookups are regular expressions."}, - { LLDB_OPT_SET_1, false, "scope", 's', no_argument, NULL, 0, eArgTypeNone, "Show variable scope (argument, local, global, static)."} + { LLDB_OPT_SET_1, false, "scope", 's', no_argument, NULL, 0, eArgTypeNone, "Show variable scope (argument, local, global, static)."}, + { LLDB_OPT_SET_1, false, "summary", 'y', required_argument, NULL, 0, eArgTypeName, "Specify the summary that the variable output should use."}, }; @@ -62,7 +64,9 @@ case 's': show_scope = true; break; - + case 'y': + summary = std::string(option_arg); + break; default: error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option); break; @@ -81,6 +85,7 @@ format = lldb::eFormatDefault; use_regex = false; show_scope = false; + summary = ""; } @@ -101,9 +106,9 @@ OptionGroupVariable::GetNumDefinitions () { if (include_frame_options) - return 7; + return 8; else - return 4; + return 5; } Modified: lldb/trunk/source/Symbol/ClangASTContext.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/ClangASTContext.cpp?rev=134943&r1=134942&r2=134943&view=diff ============================================================================== --- lldb/trunk/source/Symbol/ClangASTContext.cpp (original) +++ lldb/trunk/source/Symbol/ClangASTContext.cpp Mon Jul 11 19:18:11 2011 @@ -2077,7 +2077,30 @@ if (ast && pointee_or_element_clang_type) *pointee_or_element_clang_type = ast->ObjCBuiltinClassTy.getAsOpaquePtr(); return eTypeIsBuiltIn | eTypeIsPointer | eTypeHasValue; - + break; + case clang::BuiltinType::Bool: + case clang::BuiltinType::Char_U: + case clang::BuiltinType::UChar: + case clang::BuiltinType::WChar_U: + case clang::BuiltinType::Char16: + case clang::BuiltinType::Char32: + case clang::BuiltinType::UShort: + case clang::BuiltinType::UInt: + case clang::BuiltinType::ULong: + case clang::BuiltinType::ULongLong: + case clang::BuiltinType::UInt128: + case clang::BuiltinType::Char_S: + case clang::BuiltinType::SChar: + case clang::BuiltinType::WChar_S: + case clang::BuiltinType::Short: + case clang::BuiltinType::Int: + case clang::BuiltinType::Long: + case clang::BuiltinType::LongLong: + case clang::BuiltinType::Int128: + case clang::BuiltinType::Float: + case clang::BuiltinType::Double: + case clang::BuiltinType::LongDouble: + return eTypeIsBuiltIn | eTypeHasValue | eTypeIsScalar; default: break; } @@ -4645,6 +4668,10 @@ case clang::Type::Typedef: return ClangASTContext::GetArraySize(cast(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr()); + break; + + default: + break; } } return 0; Modified: lldb/trunk/source/Symbol/SymbolContext.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/SymbolContext.cpp?rev=134943&r1=134942&r2=134943&view=diff ============================================================================== --- lldb/trunk/source/Symbol/SymbolContext.cpp (original) +++ lldb/trunk/source/Symbol/SymbolContext.cpp Mon Jul 11 19:18:11 2011 @@ -164,7 +164,7 @@ dumped_something = true; s->PutCString(" at "); if (line_entry.DumpStopContext(s, show_fullpaths)) - return; + return dumped_something; } } } Modified: lldb/trunk/test/functionalities/data-formatter/data-formatter-cpp/TestDataFormatterCpp.py URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/data-formatter/data-formatter-cpp/TestDataFormatterCpp.py?rev=134943&r1=134942&r2=134943&view=diff ============================================================================== --- lldb/trunk/test/functionalities/data-formatter/data-formatter-cpp/TestDataFormatterCpp.py (original) +++ lldb/trunk/test/functionalities/data-formatter/data-formatter-cpp/TestDataFormatterCpp.py Mon Jul 11 19:18:11 2011 @@ -73,7 +73,16 @@ self.expect("frame variable", patterns = ['\(Speed\) SPILookHex = 0x[0-9a-f]+' # Speed should look hex-ish now. ]); - + + # gcc4.2 on Mac OS X skips typedef chains in the DWARF output + if self.getCompiler() in ['clang', 'llvm-gcc']: + self.expect("frame variable", + patterns = ['\(SignalMask\) SMILookHex = 0x[0-9a-f]+' # SignalMask should look hex-ish now. + ]); + self.expect("frame variable", matching=False, + patterns = ['\(Type4\) T4ILookChar = 0x[0-9a-f]+' # Type4 should NOT look hex-ish now. + ]); + # Now let's delete the 'Speed' custom format. self.runCmd("type format delete Speed") @@ -85,6 +94,26 @@ self.expect("type format delete Speed", error=True, substrs = ['no custom format for Speed']) + self.runCmd("type summary add -f \"arr = ${var%s}\" -x \"char \\[[0-9]+\\]\" -v") + + self.expect("frame variable strarr", + substrs = ['arr = "Hello world!\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0"']) + + self.runCmd("type summary clear") + + self.runCmd("type summary add -f \"ptr = ${var%s}\" \"char *\" -v") + + self.expect("frame variable strptr", + substrs = ['ptr = "Hello world!"']) + + self.runCmd("type summary add -f \"arr = ${var%s}\" -x \"char \\[[0-9]+\\]\" -v") + + self.expect("frame variable strarr", + substrs = ['arr = "Hello world!\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0"']) + + self.expect("frame variable strptr", + substrs = ['ptr = "Hello world!"']) + self.runCmd("type summary add -c Point") self.expect("frame variable iAmSomewhere", Modified: lldb/trunk/test/functionalities/data-formatter/data-formatter-cpp/main.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/data-formatter/data-formatter-cpp/main.cpp?rev=134943&r1=134942&r2=134943&view=diff ============================================================================== --- lldb/trunk/test/functionalities/data-formatter/data-formatter-cpp/main.cpp (original) +++ lldb/trunk/test/functionalities/data-formatter/data-formatter-cpp/main.cpp Mon Jul 11 19:18:11 2011 @@ -107,6 +107,9 @@ int int_array[] = {1,2,3,4,5}; IUseCharStar iEncapsulateCharStar; + + char strarr[32] = "Hello world!"; + char* strptr = "Hello world!"; return 0; // Set break point at this line. } From granata.enrico at gmail.com Mon Jul 11 19:19:00 2011 From: granata.enrico at gmail.com (Enrico Granata) Date: Tue, 12 Jul 2011 00:19:00 -0000 Subject: [Lldb-commits] [lldb] r134944 - in /lldb/trunk/test/functionalities/data-formatter/data-formatter-named-summaries: ./ Makefile TestDataFormatterNamedSummaries.py main.cpp Message-ID: <20110712001900.8C6762A6C12C@llvm.org> Author: enrico Date: Mon Jul 11 19:19:00 2011 New Revision: 134944 URL: http://llvm.org/viewvc/llvm-project?rev=134944&view=rev Log: test case for the named summaries feature Added: lldb/trunk/test/functionalities/data-formatter/data-formatter-named-summaries/ lldb/trunk/test/functionalities/data-formatter/data-formatter-named-summaries/Makefile lldb/trunk/test/functionalities/data-formatter/data-formatter-named-summaries/TestDataFormatterNamedSummaries.py lldb/trunk/test/functionalities/data-formatter/data-formatter-named-summaries/main.cpp Added: lldb/trunk/test/functionalities/data-formatter/data-formatter-named-summaries/Makefile URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/data-formatter/data-formatter-named-summaries/Makefile?rev=134944&view=auto ============================================================================== --- lldb/trunk/test/functionalities/data-formatter/data-formatter-named-summaries/Makefile (added) +++ lldb/trunk/test/functionalities/data-formatter/data-formatter-named-summaries/Makefile Mon Jul 11 19:19:00 2011 @@ -0,0 +1,5 @@ +LEVEL = ../../../make + +CXX_SOURCES := main.cpp + +include $(LEVEL)/Makefile.rules Added: lldb/trunk/test/functionalities/data-formatter/data-formatter-named-summaries/TestDataFormatterNamedSummaries.py URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/data-formatter/data-formatter-named-summaries/TestDataFormatterNamedSummaries.py?rev=134944&view=auto ============================================================================== --- lldb/trunk/test/functionalities/data-formatter/data-formatter-named-summaries/TestDataFormatterNamedSummaries.py (added) +++ lldb/trunk/test/functionalities/data-formatter/data-formatter-named-summaries/TestDataFormatterNamedSummaries.py Mon Jul 11 19:19:00 2011 @@ -0,0 +1,137 @@ +""" +Test lldb data formatter subsystem. +""" + +import os, time +import unittest2 +import lldb +from lldbtest import * + +class DataFormatterTestCase(TestBase): + + mydir = os.path.join("functionalities", "data-formatter", "data-formatter-named-summaries") + + @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin") + def test_with_dsym_and_run_command(self): + """Test data formatter commands.""" + self.buildDsym() + self.data_formatter_commands() + + def test_with_dwarf_and_run_command(self): + """Test data formatter commands.""" + self.buildDwarf() + self.data_formatter_commands() + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break at. + self.line = line_number('main.cpp', '// Set break point at this line.') + + def data_formatter_commands(self): + """Test that that file and class static variables display correctly.""" + self.runCmd("file a.out", CURRENT_EXECUTABLE_SET) + + self.expect("breakpoint set -f main.cpp -l %d" % self.line, + BREAKPOINT_CREATED, + startstr = "Breakpoint created: 1: file ='main.cpp', line = %d, locations = 1" % + self.line) + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs = ['stopped', + 'stop reason = breakpoint']) + + # This is the function to remove the custom formats in order to have a + # clean slate for the next test case. + def cleanup(): + self.runCmd('type format clear', check=False) + self.runCmd('type summary clear', check=False) + + # Execute the cleanup function during test case tear down. + self.addTearDownHook(cleanup) + + self.runCmd("type summary add -f \"AllUseIt: x=${var.x} {y=${var.y}} {z=${var.z}}\" --name AllUseIt") + self.runCmd("type summary add -f \"First: x=${var.x} y=${var.y} dummy=${var.dummy}\" First") + self.runCmd("type summary add -f \"Second: x=${var.x} y=${var.y%hex}\" Second") + self.runCmd("type summary add -f \"Third: x=${var.x} z=${var.z}\" Third") + + self.expect("frame variable first", + substrs = ['First: x=12']) + + self.expect("frame variable first --summary AllUseIt", + substrs = ['AllUseIt: x=12']) + + # We remember the summary choice... + self.expect("frame variable first", + substrs = ['AllUseIt: x=12']) + + self.runCmd("thread step-over") # 2 + + # ...but not after a stoppoint + self.expect("frame variable first", + substrs = ['First: x=12']) + + self.expect("frame variable first --summary AllUseIt", + substrs = ['AllUseIt: x=12', + 'y=34']) + + self.expect("frame variable second --summary AllUseIt", + substrs = ['AllUseIt: x=65', + 'y=43.21']) + + self.expect("frame variable third --summary AllUseIt", + substrs = ['AllUseIt: x=96', + 'z=', + 'E']) + + self.runCmd("thread step-over") # 3 + + self.expect("frame variable second", + substrs = ['Second: x=65', + 'y=0x']) + + self.expect("frame variable second --summary NoSuchSummary", + substrs = ['Second: x=65', + 'y=0x']) + + self.runCmd("thread step-over") + + self.runCmd("type summary add -f \"FirstAndFriends: x=${var.x} {y=${var.y}} {z=${var.z}}\" First --name FirstAndFriends") + + self.expect("frame variable first", + substrs = ['FirstAndFriends: x=12', + 'y=34']) + + self.runCmd("type summary delete First") + + self.expect("frame variable first --summary FirstAndFriends", + substrs = ['FirstAndFriends: x=12', + 'y=34']) + + self.expect("frame variable first", + substrs = ['FirstAndFriends: x=12', + 'y=34']) + + self.runCmd("type summary delete FirstAndFriends") + self.expect("type summary delete NoSuchSummary", error=True) + self.runCmd("type summary delete AllUseIt") + + self.expect("frame variable first", + substrs = ['FirstAndFriends: x=12', + 'y=34']) + + self.runCmd("thread step-over") # 4 + + self.expect("frame variable first",matching=False, + substrs = ['FirstAndFriends: x=12', + 'y=34']) + + +if __name__ == '__main__': + import atexit + lldb.SBDebugger.Initialize() + atexit.register(lambda: lldb.SBDebugger.Terminate()) + unittest2.main() Added: lldb/trunk/test/functionalities/data-formatter/data-formatter-named-summaries/main.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/data-formatter/data-formatter-named-summaries/main.cpp?rev=134944&view=auto ============================================================================== --- lldb/trunk/test/functionalities/data-formatter/data-formatter-named-summaries/main.cpp (added) +++ lldb/trunk/test/functionalities/data-formatter/data-formatter-named-summaries/main.cpp Mon Jul 11 19:19:00 2011 @@ -0,0 +1,59 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include +#include +#include + +struct First +{ + int x; + int y; + float dummy; + First(int X, int Y) : + x(X), + y(Y), + dummy(3.14) + {} +}; + +struct Second +{ + int x; + float y; + Second(int X, float Y) : + x(X), + y(Y) + {} +}; + +struct Third +{ + int x; + char z; + Third(int X, char Z) : + x(X), + z(Z) + {} +}; + +int main (int argc, const char * argv[]) +{ + First first(12,34); + Second second(65,43.21); + Third *third = new Third(96,'E'); + + first.dummy = 1; // Set break point at this line. + first.dummy = 2; + first.dummy = 3; + first.dummy = 4; + first.dummy = 5; + +} + From jingham at apple.com Mon Jul 11 22:12:18 2011 From: jingham at apple.com (Jim Ingham) Date: Tue, 12 Jul 2011 03:12:18 -0000 Subject: [Lldb-commits] [lldb] r134955 - in /lldb/trunk: include/lldb/Interpreter/CommandInterpreter.h include/lldb/lldb-enumerations.h source/Commands/CommandObjectCommands.cpp source/Interpreter/CommandInterpreter.cpp tools/driver/IOChannel.cpp Message-ID: <20110712031218.B2F5E2A6C12C@llvm.org> Author: jingham Date: Mon Jul 11 22:12:18 2011 New Revision: 134955 URL: http://llvm.org/viewvc/llvm-project?rev=134955&view=rev Log: Added "command history" command to dump the command history. Also made: (lldb) ! (lldb) !- (lldb) !! work with the history. For added benefit: (lldb) ! will insert the command at position in the history into the command line to be edited. This is only partial, I still need to sync up editline's history list with the one kept by the interpreter. Modified: lldb/trunk/include/lldb/Interpreter/CommandInterpreter.h lldb/trunk/include/lldb/lldb-enumerations.h lldb/trunk/source/Commands/CommandObjectCommands.cpp lldb/trunk/source/Interpreter/CommandInterpreter.cpp lldb/trunk/tools/driver/IOChannel.cpp Modified: lldb/trunk/include/lldb/Interpreter/CommandInterpreter.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Interpreter/CommandInterpreter.h?rev=134955&r1=134954&r2=134955&view=diff ============================================================================== --- lldb/trunk/include/lldb/Interpreter/CommandInterpreter.h (original) +++ lldb/trunk/include/lldb/Interpreter/CommandInterpreter.h Mon Jul 11 22:12:18 2011 @@ -195,8 +195,11 @@ // you want returned. Otherwise set max_return_elements to -1. // If you want to start some way into the match list, then set match_start_point to the desired start // point. - // Returns the total number of completions, or -1 if the completion character should be inserted, or + // Returns: + // -1 if the completion character should be inserted + // -2 if the entire command line should be deleted and replaced with matches.GetStringAtIndex(0) // INT_MAX if the number of matches is > max_return_elements, but it is expensive to compute. + // Otherwise, returns the number of matches. // // FIXME: Only max_return_elements == -1 is supported at present. @@ -338,6 +341,16 @@ bool GetSynchronous (); + + void + DumpHistory (Stream &stream, uint32_t count) const; + + void + DumpHistory (Stream &stream, uint32_t start, uint32_t end) const; + + const char * + FindHistoryString (const char *input_str) const; + #ifndef SWIG void @@ -396,6 +409,7 @@ std::string m_repeat_command; // Stores the command that will be executed for an empty command string. std::auto_ptr m_script_interpreter_ap; char m_comment_char; + char m_repeat_char; bool m_batch_command_mode; }; Modified: lldb/trunk/include/lldb/lldb-enumerations.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/lldb-enumerations.h?rev=134955&r1=134954&r2=134955&view=diff ============================================================================== --- lldb/trunk/include/lldb/lldb-enumerations.h (original) +++ lldb/trunk/include/lldb/lldb-enumerations.h Mon Jul 11 22:12:18 2011 @@ -391,6 +391,7 @@ eArgTypeThreadID, eArgTypeThreadIndex, eArgTypeThreadName, + eArgTypeUnsignedInteger, eArgTypeUnixSignal, eArgTypeVarName, eArgTypeValue, Modified: lldb/trunk/source/Commands/CommandObjectCommands.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectCommands.cpp?rev=134955&r1=134954&r2=134955&view=diff ============================================================================== --- lldb/trunk/source/Commands/CommandObjectCommands.cpp (original) +++ lldb/trunk/source/Commands/CommandObjectCommands.cpp Mon Jul 11 22:12:18 2011 @@ -30,6 +30,132 @@ // CommandObjectCommandsSource //------------------------------------------------------------------------- +class CommandObjectCommandsHistory : public CommandObject +{ +private: + + class CommandOptions : public Options + { + public: + + CommandOptions (CommandInterpreter &interpreter) : + Options (interpreter) + { + } + + virtual + ~CommandOptions (){} + + virtual Error + SetOptionValue (uint32_t option_idx, const char *option_arg) + { + Error error; + char short_option = (char) m_getopt_table[option_idx].val; + bool success; + + switch (short_option) + { + case 'c': + m_end_idx = Args::StringToUInt32(option_arg, UINT_MAX, 0, &success); + if (!success) + error.SetErrorStringWithFormat("Invalid value for count: %s.\n", option_arg); + if (m_end_idx != 0) + m_end_idx--; + m_start_idx = 0; + break; + case 'e': + m_end_idx = Args::StringToUInt32(option_arg, 0, 0, &success); + if (!success) + error.SetErrorStringWithFormat("Invalid value for end index: %s.\n", option_arg); + break; + case 's': + m_start_idx = Args::StringToUInt32(option_arg, 0, 0, &success); + if (!success) + error.SetErrorStringWithFormat("Invalid value for start index: %s.\n", option_arg); + break; + default: + error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option); + break; + } + + return error; + } + + void + OptionParsingStarting () + { + m_start_idx = 0; + m_end_idx = UINT_MAX; + } + + const OptionDefinition* + GetDefinitions () + { + return g_option_table; + } + + // Options table: Required for subclasses of Options. + + static OptionDefinition g_option_table[]; + + // Instance variables to hold the values for command options. + + uint32_t m_start_idx; + uint32_t m_end_idx; + }; + + CommandOptions m_options; + + virtual Options * + GetOptions () + { + return &m_options; + } + +public: + CommandObjectCommandsHistory(CommandInterpreter &interpreter) : + CommandObject (interpreter, + "command history", + "Dump the history of commands in this session.", + NULL), + m_options (interpreter) + { + } + + ~CommandObjectCommandsHistory () + { + } + + bool + Execute + ( + Args& args, + CommandReturnObject &result + ) + { + + m_interpreter.DumpHistory (result.GetOutputStream(), + m_options.m_start_idx, + m_options.m_end_idx); + return result.Succeeded(); + + } +}; + +OptionDefinition +CommandObjectCommandsHistory::CommandOptions::g_option_table[] = +{ +{ LLDB_OPT_SET_1, false, "count", 'c', required_argument, NULL, 0, eArgTypeUnsignedInteger, "How many history commands to print."}, +{ LLDB_OPT_SET_1, false, "start-index", 's', required_argument, NULL, 0, eArgTypeUnsignedInteger, "Index at which to start printing history commands."}, +{ LLDB_OPT_SET_1, false, "end-index", 'e', required_argument, NULL, 0, eArgTypeUnsignedInteger, "Index at which to stop printing history commands."}, +{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } +}; + + +//------------------------------------------------------------------------- +// CommandObjectCommandsSource +//------------------------------------------------------------------------- + class CommandObjectCommandsSource : public CommandObject { private: @@ -1020,6 +1146,7 @@ LoadSubCommand ("alias", CommandObjectSP (new CommandObjectCommandsAlias (interpreter))); LoadSubCommand ("unalias", CommandObjectSP (new CommandObjectCommandsUnalias (interpreter))); LoadSubCommand ("regex", CommandObjectSP (new CommandObjectCommandsAddRegex (interpreter))); + LoadSubCommand ("history", CommandObjectSP (new CommandObjectCommandsHistory (interpreter))); } CommandObjectMultiwordCommands::~CommandObjectMultiwordCommands () Modified: lldb/trunk/source/Interpreter/CommandInterpreter.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/CommandInterpreter.cpp?rev=134955&r1=134954&r2=134955&view=diff ============================================================================== --- lldb/trunk/source/Interpreter/CommandInterpreter.cpp (original) +++ lldb/trunk/source/Interpreter/CommandInterpreter.cpp Mon Jul 11 22:12:18 2011 @@ -70,6 +70,7 @@ m_skip_lldbinit_files (false), m_script_interpreter_ap (), m_comment_char ('#'), + m_repeat_char ('!'), m_batch_command_mode (false) { const char *dbg_name = debugger.GetInstanceName().AsCString(); @@ -929,6 +930,7 @@ std::string next_word; bool wants_raw_input = false; std::string command_string (command_line); + std::string original_command_string (command_line); LogSP log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_COMMANDS)); Host::SetCrashDescriptionWithFormat ("HandleCommand(command = \"%s\")", command_line); @@ -959,6 +961,19 @@ empty_command = true; else if (command_string[non_space] == m_comment_char) comment_command = true; + else if (command_string[non_space] == m_repeat_char) + { + const char *history_string = FindHistoryString (command_string.c_str() + non_space); + if (history_string == NULL) + { + result.AppendErrorWithFormat ("Could not find entry: %s in history", command_string.c_str()); + result.SetStatus(eReturnStatusFailed); + return false; + } + add_to_history = false; + command_string = history_string; + original_command_string = history_string; + } } if (empty_command) @@ -975,6 +990,7 @@ { command_line = m_repeat_command.c_str(); command_string = command_line; + original_command_string = command_line; if (m_repeat_command.empty()) { result.AppendErrorWithFormat("No auto repeat.\n"); @@ -1119,9 +1135,11 @@ if (repeat_command != NULL) m_repeat_command.assign(repeat_command); else - m_repeat_command.assign(command_line); + m_repeat_command.assign(original_command_string.c_str()); - m_command_history.push_back (command_line); + // Don't keep pushing the same command onto the history... + if (m_command_history.size() == 0 || m_command_history.back() != original_command_string) + m_command_history.push_back (original_command_string); } command_string = revised_command_line.GetData(); @@ -1276,6 +1294,29 @@ Args parsed_line(current_line, last_char - current_line); Args partial_parsed_line(current_line, cursor - current_line); + // Don't complete comments, and if the line we are completing is just the history repeat character, + // substitute the appropriate history line. + const char *first_arg = parsed_line.GetArgumentAtIndex(0); + if (first_arg) + { + if (first_arg[0] == m_comment_char) + return 0; + else if (first_arg[0] == m_repeat_char) + { + const char *history_string = FindHistoryString (first_arg); + if (history_string != NULL) + { + matches.Clear(); + matches.InsertStringAtIndex(0, history_string); + return -2; + } + else + return 0; + + } + } + + int num_args = partial_parsed_line.GetArgumentCount(); int cursor_index = partial_parsed_line.GetArgumentCount() - 1; int cursor_char_position; @@ -2154,3 +2195,60 @@ } } +void +CommandInterpreter::DumpHistory (Stream &stream, uint32_t count) const +{ + DumpHistory (stream, 0, count - 1); +} + +void +CommandInterpreter::DumpHistory (Stream &stream, uint32_t start, uint32_t end) const +{ + size_t num_history_elements = m_command_history.size(); + if (start > num_history_elements) + return; + for (uint32_t i = start; i < num_history_elements && i <= end; i++) + { + if (!m_command_history[i].empty()) + { + stream.Indent(); + stream.Printf ("%4d: %s\n", i, m_command_history[i].c_str()); + } + } +} + +const char * +CommandInterpreter::FindHistoryString (const char *input_str) const +{ + if (input_str[0] != m_repeat_char) + return NULL; + if (input_str[1] == '-') + { + bool success; + uint32_t idx = Args::StringToUInt32 (input_str+2, 0, 0, &success); + if (!success) + return NULL; + if (idx > m_command_history.size()) + return NULL; + idx = m_command_history.size() - idx; + return m_command_history[idx].c_str(); + + } + else if (input_str[1] == m_repeat_char) + { + if (m_command_history.empty()) + return NULL; + else + return m_command_history.back().c_str(); + } + else + { + bool success; + uint32_t idx = Args::StringToUInt32 (input_str+1, 0, 0, &success); + if (!success) + return NULL; + if (idx >= m_command_history.size()) + return NULL; + return m_command_history[idx].c_str(); + } +} Modified: lldb/trunk/tools/driver/IOChannel.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/driver/IOChannel.cpp?rev=134955&r1=134954&r2=134955&view=diff ============================================================================== --- lldb/trunk/tools/driver/IOChannel.cpp (original) +++ lldb/trunk/tools/driver/IOChannel.cpp Mon Jul 11 22:12:18 2011 @@ -85,6 +85,12 @@ el_insertstr (m_edit_line, m_completion_key); return CC_REDISPLAY; } + else if (num_completions == -2) + { + el_deletestr (m_edit_line, line_info->cursor - line_info->buffer); + el_insertstr (m_edit_line, completions.GetStringAtIndex(0)); + return CC_REDISPLAY; + } // If we get a longer match display that first. const char *completion_str = completions.GetStringAtIndex(0); From gclayton at apple.com Tue Jul 12 12:06:17 2011 From: gclayton at apple.com (Greg Clayton) Date: Tue, 12 Jul 2011 17:06:17 -0000 Subject: [Lldb-commits] [lldb] r134990 - in /lldb/trunk: include/lldb/Breakpoint/BreakpointResolverName.h include/lldb/Target/Target.h source/Breakpoint/BreakpointResolverName.cpp source/Plugins/DynamicLoader/MacOSX-Kernel/DynamicLoaderMacOSXKernel.cpp source/Plugins/DynamicLoader/MacOSX-Kernel/DynamicLoaderMacOSXKernel.h source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h source/Symbol/SymbolContext.cpp source/Target/Target.cpp Message-ID: <20110712170618.17A382A6C12C@llvm.org> Author: gclayton Date: Tue Jul 12 12:06:17 2011 New Revision: 134990 URL: http://llvm.org/viewvc/llvm-project?rev=134990&view=rev Log: Added the ability to _not_ skip the prologue when settings breakpoints by name by adding an extra parameter to the lldb_private::Target breakpoint setting functions. Added a function in the DWARF symbol file plug-in that can dump errors and prints out which DWARF file the error is happening in so we can track down what used to be assertions easily. Fixed the MacOSX kernel plug-in to properly read the kext images and set the kext breakpoint to watch for kexts as they are loaded. Modified: lldb/trunk/include/lldb/Breakpoint/BreakpointResolverName.h lldb/trunk/include/lldb/Target/Target.h lldb/trunk/source/Breakpoint/BreakpointResolverName.cpp lldb/trunk/source/Plugins/DynamicLoader/MacOSX-Kernel/DynamicLoaderMacOSXKernel.cpp lldb/trunk/source/Plugins/DynamicLoader/MacOSX-Kernel/DynamicLoaderMacOSXKernel.h lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h lldb/trunk/source/Symbol/SymbolContext.cpp lldb/trunk/source/Target/Target.cpp Modified: lldb/trunk/include/lldb/Breakpoint/BreakpointResolverName.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Breakpoint/BreakpointResolverName.h?rev=134990&r1=134989&r2=134990&view=diff ============================================================================== --- lldb/trunk/include/lldb/Breakpoint/BreakpointResolverName.h (original) +++ lldb/trunk/include/lldb/Breakpoint/BreakpointResolverName.h Tue Jul 12 12:06:17 2011 @@ -32,16 +32,19 @@ BreakpointResolverName (Breakpoint *bkpt, const char *name, uint32_t name_type_mask, - Breakpoint::MatchType type); + Breakpoint::MatchType type, + bool skip_prologue); // Creates a function breakpoint by regular expression. Takes over control of the lifespan of func_regex. BreakpointResolverName (Breakpoint *bkpt, - RegularExpression &func_regex); + RegularExpression &func_regex, + bool skip_prologue); BreakpointResolverName (Breakpoint *bkpt, const char *class_name, const char *method, - Breakpoint::MatchType type); + Breakpoint::MatchType type, + bool skip_prologue); virtual ~BreakpointResolverName (); @@ -81,6 +84,7 @@ ConstString m_class_name; // FIXME: Not used yet. The idea would be to stop on methods of this class. RegularExpression m_regex; Breakpoint::MatchType m_match_type; + bool m_skip_prologue; private: DISALLOW_COPY_AND_ASSIGN(BreakpointResolverName); Modified: lldb/trunk/include/lldb/Target/Target.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/Target.h?rev=134990&r1=134989&r2=134990&view=diff ============================================================================== --- lldb/trunk/include/lldb/Target/Target.h (original) +++ lldb/trunk/include/lldb/Target/Target.h Tue Jul 12 12:06:17 2011 @@ -238,17 +238,23 @@ bool internal = false); // Use this to create a function breakpoint by regexp in containingModule, or all modules if it is NULL + // When "skip_prologue is set to eLazyBoolCalculate, we use the current target + // setting, else we use the values passed in lldb::BreakpointSP CreateBreakpoint (const FileSpec *containingModule, RegularExpression &func_regexp, - bool internal = false); + bool internal = false, + LazyBool skip_prologue = eLazyBoolCalculate); // Use this to create a function breakpoint by name in containingModule, or all modules if it is NULL + // When "skip_prologue is set to eLazyBoolCalculate, we use the current target + // setting, else we use the values passed in lldb::BreakpointSP CreateBreakpoint (const FileSpec *containingModule, const char *func_name, uint32_t func_name_type_mask, - bool internal = false); + bool internal = false, + LazyBool skip_prologue = eLazyBoolCalculate); // Use this to create a general breakpoint: lldb::BreakpointSP @@ -461,6 +467,27 @@ size_t dst_len, Error &error); + size_t + ReadScalarIntegerFromMemory (const Address& addr, + bool prefer_file_cache, + uint32_t byte_size, + bool is_signed, + Scalar &scalar, + Error &error); + + uint64_t + ReadUnsignedIntegerFromMemory (const Address& addr, + bool prefer_file_cache, + size_t integer_byte_size, + uint64_t fail_value, + Error &error); + + bool + ReadPointerFromMemory (const Address& addr, + bool prefer_file_cache, + Error &error, + Address &pointer_addr); + SectionLoadList& GetSectionLoadList() { Modified: lldb/trunk/source/Breakpoint/BreakpointResolverName.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Breakpoint/BreakpointResolverName.cpp?rev=134990&r1=134989&r2=134990&view=diff ============================================================================== --- lldb/trunk/source/Breakpoint/BreakpointResolverName.cpp (original) +++ lldb/trunk/source/Breakpoint/BreakpointResolverName.cpp Tue Jul 12 12:06:17 2011 @@ -26,7 +26,8 @@ Breakpoint *bkpt, const char *func_name, uint32_t func_name_type_mask, - Breakpoint::MatchType type + Breakpoint::MatchType type, + bool skip_prologue ) : BreakpointResolver (bkpt, BreakpointResolver::NameResolver), m_func_name (), @@ -34,7 +35,8 @@ m_func_name_type_mask (func_name_type_mask), m_class_name (), m_regex (), - m_match_type (type) + m_match_type (type), + m_skip_prologue (skip_prologue) { if (func_name_type_mask == eFunctionNameTypeAuto) { @@ -92,13 +94,15 @@ BreakpointResolverName::BreakpointResolverName ( Breakpoint *bkpt, - RegularExpression &func_regex + RegularExpression &func_regex, + bool skip_prologue ) : BreakpointResolver (bkpt, BreakpointResolver::NameResolver), m_func_name (NULL), m_class_name (NULL), m_regex (func_regex), - m_match_type (Breakpoint::Regexp) + m_match_type (Breakpoint::Regexp), + m_skip_prologue (skip_prologue) { } @@ -108,13 +112,15 @@ Breakpoint *bkpt, const char *class_name, const char *method, - Breakpoint::MatchType type + Breakpoint::MatchType type, + bool skip_prologue ) : BreakpointResolver (bkpt, BreakpointResolver::NameResolver), m_func_name (method), m_class_name (class_name), m_regex (), - m_match_type (type) + m_match_type (type), + m_skip_prologue (skip_prologue) { } @@ -139,18 +145,12 @@ SymbolContextList func_list; SymbolContextList sym_list; - bool skip_prologue = true; uint32_t i; bool new_location; SymbolContext sc; Address break_addr; assert (m_breakpoint != NULL); - if (context.target_sp) - { - skip_prologue = context.target_sp->GetSkipPrologue(); - } - LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS)); if (m_class_name) @@ -294,7 +294,7 @@ else if (sc.function) { break_addr = sc.function->GetAddressRange().GetBaseAddress(); - if (skip_prologue) + if (m_skip_prologue) { if (break_addr.IsValid()) { @@ -333,7 +333,7 @@ { break_addr = sc.symbol->GetAddressRangePtr()->GetBaseAddress(); - if (skip_prologue) + if (m_skip_prologue) { const uint32_t prologue_byte_size = sc.symbol->GetPrologueByteSize(); if (prologue_byte_size) Modified: lldb/trunk/source/Plugins/DynamicLoader/MacOSX-Kernel/DynamicLoaderMacOSXKernel.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/DynamicLoader/MacOSX-Kernel/DynamicLoaderMacOSXKernel.cpp?rev=134990&r1=134989&r2=134990&view=diff ============================================================================== --- lldb/trunk/source/Plugins/DynamicLoader/MacOSX-Kernel/DynamicLoaderMacOSXKernel.cpp (original) +++ lldb/trunk/source/Plugins/DynamicLoader/MacOSX-Kernel/DynamicLoaderMacOSXKernel.cpp Tue Jul 12 12:06:17 2011 @@ -87,6 +87,7 @@ DynamicLoaderMacOSXKernel::DynamicLoaderMacOSXKernel (Process* process) : DynamicLoader(process), m_kernel(), + m_kext_summary_header_ptr_addr (), m_kext_summary_header_addr (), m_kext_summary_header (), m_break_id (LLDB_INVALID_BREAK_ID), @@ -150,6 +151,7 @@ if (clear_process) m_process = NULL; m_kernel.Clear(false); + m_kext_summary_header_ptr_addr.Clear(); m_kext_summary_header_addr.Clear(); m_kext_summaries.clear(); m_break_id = LLDB_INVALID_BREAK_ID; @@ -165,7 +167,7 @@ void DynamicLoaderMacOSXKernel::LoadKernelModuleIfNeeded() { - if (!m_kext_summary_header_addr.IsValid()) + if (!m_kext_summary_header_ptr_addr.IsValid()) { m_kernel.Clear(false); m_kernel.module_sp = m_process->GetTarget().GetExecutableModule(); @@ -176,7 +178,7 @@ const Symbol *symbol = NULL; symbol = m_kernel.module_sp->FindFirstSymbolWithNameAndType (kext_summary_symbol, eSymbolTypeData); if (symbol) - m_kext_summary_header_addr = symbol->GetValue(); + m_kext_summary_header_ptr_addr = symbol->GetValue(); symbol = m_kernel.module_sp->FindFirstSymbolWithNameAndType (mach_header_name, eSymbolTypeAbsolute); if (symbol) @@ -395,7 +397,15 @@ user_id_t break_id, user_id_t break_loc_id) { + LogSP log(GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER)); + if (log) + log->Printf ("DynamicLoaderMacOSXKernel::BreakpointHit (...)\n"); + ReadAllKextSummaries (); + + if (log) + PutToLog(log.get()); + return GetStopWhenImagesChange(); } @@ -408,7 +418,7 @@ // the all image infos is already valid for this process stop ID m_kext_summaries.clear(); - if (m_kext_summary_header_addr.IsValid()) + if (m_kext_summary_header_ptr_addr.IsValid()) { const uint32_t addr_size = m_kernel.GetAddressByteSize (); const ByteOrder byte_order = m_kernel.GetByteOrder(); @@ -419,17 +429,29 @@ DataExtractor data (buf, sizeof(buf), byte_order, addr_size); const size_t count = 4 * sizeof(uint32_t) + addr_size; const bool prefer_file_cache = false; - const size_t bytes_read = m_process->GetTarget().ReadMemory (m_kext_summary_header_addr, prefer_file_cache, buf, count, error); - if (bytes_read == count) - { - uint32_t offset = 0; - m_kext_summary_header.version = data.GetU32(&offset); - m_kext_summary_header.entry_size = data.GetU32(&offset); - m_kext_summary_header.entry_count = data.GetU32(&offset); - m_kext_summary_header.reserved = data.GetU32(&offset); - return true; + if (m_process->GetTarget().ReadPointerFromMemory (m_kext_summary_header_ptr_addr, + prefer_file_cache, + error, + m_kext_summary_header_addr)) + { + // We got a valid address for our kext summary header and make sure it isn't NULL + if (m_kext_summary_header_addr.IsValid() && + m_kext_summary_header_addr.GetFileAddress() != 0) + { + const size_t bytes_read = m_process->GetTarget().ReadMemory (m_kext_summary_header_addr, prefer_file_cache, buf, count, error); + if (bytes_read == count) + { + uint32_t offset = 0; + m_kext_summary_header.version = data.GetU32(&offset); + m_kext_summary_header.entry_size = data.GetU32(&offset); + m_kext_summary_header.entry_count = data.GetU32(&offset); + m_kext_summary_header.reserved = data.GetU32(&offset); + return true; + } + } } } + m_kext_summary_header_addr.Clear(); return false; } @@ -471,16 +493,9 @@ { // Now add these images to the main list. ModuleList loaded_module_list; - LogSP log(GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER)); for (uint32_t idx = 0; idx < image_infos.size(); ++idx) { - if (log) - { - log->Printf ("Adding new image at address=0x%16.16llx.", image_infos[idx].address); - image_infos[idx].PutToLog (log.get()); - } - m_kext_summaries.push_back(image_infos[idx]); if (FindTargetModule (image_infos[idx], true, NULL)) @@ -517,8 +532,8 @@ } } } - if (log) - loaded_module_list.LogUUIDAndPaths (log, "DynamicLoaderMacOSXKernel::ModulesDidLoad"); +// if (log) +// loaded_module_list.LogUUIDAndPaths (log, "DynamicLoaderMacOSXKernel::ModulesDidLoad"); m_process->GetTarget().ModulesDidLoad (loaded_module_list); } return true; @@ -895,11 +910,14 @@ { DEBUG_PRINTF("DynamicLoaderMacOSXKernel::%s() process state = %s\n", __FUNCTION__, StateAsCString(m_process->GetState())); + const bool internal_bp = false; + const LazyBool skip_prologue = eLazyBoolNo; Breakpoint *bp = m_process->GetTarget().CreateBreakpoint (&m_kernel.module_sp->GetFileSpec(), "OSKextLoadedKextSummariesUpdated", eFunctionNameTypeFull, - internal_bp).get(); + internal_bp, + skip_prologue).get(); bp->SetCallback (DynamicLoaderMacOSXKernel::BreakpointHitCallback, this, true); m_break_id = bp->GetID(); Modified: lldb/trunk/source/Plugins/DynamicLoader/MacOSX-Kernel/DynamicLoaderMacOSXKernel.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/DynamicLoader/MacOSX-Kernel/DynamicLoaderMacOSXKernel.h?rev=134990&r1=134989&r2=134990&view=diff ============================================================================== --- lldb/trunk/source/Plugins/DynamicLoader/MacOSX-Kernel/DynamicLoaderMacOSXKernel.h (original) +++ lldb/trunk/source/Plugins/DynamicLoader/MacOSX-Kernel/DynamicLoaderMacOSXKernel.h Tue Jul 12 12:06:17 2011 @@ -411,6 +411,7 @@ UnloadImageLoadAddress (OSKextLoadedKextSummary& info); OSKextLoadedKextSummary m_kernel; // Info about the current kernel image being used + lldb_private::Address m_kext_summary_header_ptr_addr; lldb_private::Address m_kext_summary_header_addr; OSKextLoadedKextSummaryHeader m_kext_summary_header; OSKextLoadedKextSummary::collection m_kext_summaries; Modified: lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp?rev=134990&r1=134989&r2=134990&view=diff ============================================================================== --- lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp (original) +++ lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp Tue Jul 12 12:06:17 2011 @@ -1218,16 +1218,30 @@ if (is_artificial == false) { Type *member_type = ResolveTypeUID(encoding_uid); - assert(member_type); - if (accessibility == eAccessNone) - accessibility = default_accessibility; - member_accessibilities.push_back(accessibility); - - GetClangASTContext().AddFieldToRecordType (class_clang_type, - name, - member_type->GetClangLayoutType(), - accessibility, - bit_size); + if (member_type) + { + if (accessibility == eAccessNone) + accessibility = default_accessibility; + member_accessibilities.push_back(accessibility); + + GetClangASTContext().AddFieldToRecordType (class_clang_type, + name, + member_type->GetClangLayoutType(), + accessibility, + bit_size); + } + else + { + if (name) + ReportError ("0x%8.8x: DW_TAG_member '%s' refers to type 0x%8.8x which was unable to be parsed", + die->GetOffset(), + name, + encoding_uid); + else + ReportError ("0x%8.8x: DW_TAG_member refers to type 0x%8.8x which was unable to be parsed", + die->GetOffset(), + encoding_uid); + } } } ++member_idx; @@ -2237,6 +2251,19 @@ // Return the number of variable that were appended to the list return sc_list.GetSize() - original_size; } +void +SymbolFileDWARF::ReportError (const char *format, ...) +{ + ::fprintf (stderr, + "error: %s/%s ", + m_obj_file->GetFileSpec().GetDirectory().GetCString(), + m_obj_file->GetFileSpec().GetFilename().GetCString()); + + va_list args; + va_start (args, format); + vfprintf (stderr, format, args); + va_end (args); +} uint32_t SymbolFileDWARF::FindTypes(const SymbolContext& sc, const ConstString &name, bool append, uint32_t max_matches, TypeList& types) Modified: lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h?rev=134990&r1=134989&r2=134990&view=diff ============================================================================== --- lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h (original) +++ lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h Tue Jul 12 12:06:17 2011 @@ -347,6 +347,9 @@ m_decl_ctx_to_die[decl_ctx] = die; } + void + ReportError (const char *format, ...); + SymbolFileDWARFDebugMap * m_debug_map_symfile; clang::TranslationUnitDecl * m_clang_tu_decl; lldb_private::Flags m_flags; Modified: lldb/trunk/source/Symbol/SymbolContext.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/SymbolContext.cpp?rev=134990&r1=134989&r2=134990&view=diff ============================================================================== --- lldb/trunk/source/Symbol/SymbolContext.cpp (original) +++ lldb/trunk/source/Symbol/SymbolContext.cpp Tue Jul 12 12:06:17 2011 @@ -164,7 +164,7 @@ dumped_something = true; s->PutCString(" at "); if (line_entry.DumpStopContext(s, show_fullpaths)) - return dumped_something; + dumped_something = true; } } } Modified: lldb/trunk/source/Target/Target.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/Target.cpp?rev=134990&r1=134989&r2=134990&view=diff ============================================================================== --- lldb/trunk/source/Target/Target.cpp (original) +++ lldb/trunk/source/Target/Target.cpp Tue Jul 12 12:06:17 2011 @@ -213,13 +213,22 @@ } BreakpointSP -Target::CreateBreakpoint (const FileSpec *containingModule, const char *func_name, uint32_t func_name_type_mask, bool internal) +Target::CreateBreakpoint (const FileSpec *containingModule, + const char *func_name, + uint32_t func_name_type_mask, + bool internal, + LazyBool skip_prologue) { BreakpointSP bp_sp; if (func_name) { SearchFilterSP filter_sp(GetSearchFilterForModule (containingModule)); - BreakpointResolverSP resolver_sp (new BreakpointResolverName (NULL, func_name, func_name_type_mask, Breakpoint::Exact)); + + BreakpointResolverSP resolver_sp (new BreakpointResolverName (NULL, + func_name, + func_name_type_mask, + Breakpoint::Exact, + skip_prologue == eLazyBoolCalculate ? GetSkipPrologue() : skip_prologue)); bp_sp = CreateBreakpoint (filter_sp, resolver_sp, internal); } return bp_sp; @@ -247,10 +256,15 @@ } BreakpointSP -Target::CreateBreakpoint (const FileSpec *containingModule, RegularExpression &func_regex, bool internal) +Target::CreateBreakpoint (const FileSpec *containingModule, + RegularExpression &func_regex, + bool internal, + LazyBool skip_prologue) { SearchFilterSP filter_sp(GetSearchFilterForModule (containingModule)); - BreakpointResolverSP resolver_sp(new BreakpointResolverName (NULL, func_regex)); + BreakpointResolverSP resolver_sp(new BreakpointResolverName (NULL, + func_regex, + skip_prologue == eLazyBoolCalculate ? GetSkipPrologue() : skip_prologue)); return CreateBreakpoint (filter_sp, resolver_sp, internal); } @@ -600,19 +614,21 @@ Address resolved_addr; if (!addr.IsSectionOffset()) { - if (process_is_valid) + if (m_section_load_list.IsEmpty()) { - // Process is valid and we were given an address that - // isn't section offset, so assume this is a load address - load_addr = addr.GetOffset(); - m_section_load_list.ResolveLoadAddress (addr.GetOffset(), resolved_addr); + // No sections are loaded, so we must assume we are not running + // yet and anything we are given is a file address. + file_addr = addr.GetOffset(); // "addr" doesn't have a section, so its offset is the file address + m_images.ResolveFileAddress (file_addr, resolved_addr); } else { - // Process is NOT valid and we were given an address that - // isn't section offset, so assume this is a file address - file_addr = addr.GetOffset(); - m_images.ResolveFileAddress(addr.GetOffset(), resolved_addr); + // We have at least one section loaded. This can be becuase + // we have manually loaded some sections with "target modules load ..." + // or because we have have a live process that has sections loaded + // through the dynamic loader + load_addr = addr.GetOffset(); // "addr" doesn't have a section, so its offset is the load address + m_section_load_list.ResolveLoadAddress (load_addr, resolved_addr); } } if (!resolved_addr.IsValid()) @@ -674,6 +690,99 @@ return 0; } +size_t +Target::ReadScalarIntegerFromMemory (const Address& addr, + bool prefer_file_cache, + uint32_t byte_size, + bool is_signed, + Scalar &scalar, + Error &error) +{ + uint64_t uval; + + if (byte_size <= sizeof(uval)) + { + size_t bytes_read = ReadMemory (addr, prefer_file_cache, &uval, byte_size, error); + if (bytes_read == byte_size) + { + DataExtractor data (&uval, sizeof(uval), m_arch.GetByteOrder(), m_arch.GetAddressByteSize()); + uint32_t offset = 0; + if (byte_size <= 4) + scalar = data.GetMaxU32 (&offset, byte_size); + else + scalar = data.GetMaxU64 (&offset, byte_size); + + if (is_signed) + scalar.SignExtend(byte_size * 8); + return bytes_read; + } + } + else + { + error.SetErrorStringWithFormat ("byte size of %u is too large for integer scalar type", byte_size); + } + return 0; +} + +uint64_t +Target::ReadUnsignedIntegerFromMemory (const Address& addr, + bool prefer_file_cache, + size_t integer_byte_size, + uint64_t fail_value, + Error &error) +{ + Scalar scalar; + if (ReadScalarIntegerFromMemory (addr, + prefer_file_cache, + integer_byte_size, + false, + scalar, + error)) + return scalar.ULongLong(fail_value); + return fail_value; +} + +bool +Target::ReadPointerFromMemory (const Address& addr, + bool prefer_file_cache, + Error &error, + Address &pointer_addr) +{ + Scalar scalar; + if (ReadScalarIntegerFromMemory (addr, + prefer_file_cache, + m_arch.GetAddressByteSize(), + false, + scalar, + error)) + { + addr_t pointer_vm_addr = scalar.ULongLong(LLDB_INVALID_ADDRESS); + if (pointer_vm_addr != LLDB_INVALID_ADDRESS) + { + if (m_section_load_list.IsEmpty()) + { + // No sections are loaded, so we must assume we are not running + // yet and anything we are given is a file address. + m_images.ResolveFileAddress (pointer_vm_addr, pointer_addr); + } + else + { + // We have at least one section loaded. This can be becuase + // we have manually loaded some sections with "target modules load ..." + // or because we have have a live process that has sections loaded + // through the dynamic loader + m_section_load_list.ResolveLoadAddress (pointer_vm_addr, pointer_addr); + } + // We weren't able to resolve the pointer value, so just return + // an address with no section + if (!pointer_addr.IsValid()) + pointer_addr.SetOffset (pointer_vm_addr); + return true; + + } + } + return false; +} ModuleSP Target::GetSharedModule From johnny.chen at apple.com Tue Jul 12 17:34:30 2011 From: johnny.chen at apple.com (Johnny Chen) Date: Tue, 12 Jul 2011 22:34:30 -0000 Subject: [Lldb-commits] [lldb] r135005 - /lldb/trunk/source/Commands/CommandObjectTarget.cpp Message-ID: <20110712223430.D7D452A6C12C@llvm.org> Author: johnny Date: Tue Jul 12 17:34:30 2011 New Revision: 135005 URL: http://llvm.org/viewvc/llvm-project?rev=135005&view=rev Log: Fix short description of 'target variable' command. Modified: lldb/trunk/source/Commands/CommandObjectTarget.cpp Modified: lldb/trunk/source/Commands/CommandObjectTarget.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectTarget.cpp?rev=135005&r1=135004&r2=135005&view=diff ============================================================================== --- lldb/trunk/source/Commands/CommandObjectTarget.cpp (original) +++ lldb/trunk/source/Commands/CommandObjectTarget.cpp Tue Jul 12 17:34:30 2011 @@ -412,8 +412,8 @@ public: CommandObjectTargetVariable (CommandInterpreter &interpreter) : CommandObject (interpreter, - "target select", - "Select a target as the current target by target index.", + "target variable", + "Read global variable(s) prior to running your binary.", NULL, 0), m_option_group (interpreter), From granata.enrico at gmail.com Tue Jul 12 17:56:10 2011 From: granata.enrico at gmail.com (Enrico Granata) Date: Tue, 12 Jul 2011 22:56:10 -0000 Subject: [Lldb-commits] [lldb] r135007 - in /lldb/trunk: include/lldb/Core/FormatManager.h include/lldb/Core/ValueObject.h lldb.xcodeproj/project.pbxproj source/Core/DataExtractor.cpp source/Core/Debugger.cpp source/Core/FormatManager.cpp source/Core/ValueObject.cpp test/functionalities/data-formatter/data-formatter-cpp/TestDataFormatterCpp.py www/varformats.html Message-ID: <20110712225611.14F3C2A6C12C@llvm.org> Author: enrico Date: Tue Jul 12 17:56:10 2011 New Revision: 135007 URL: http://llvm.org/viewvc/llvm-project?rev=135007&view=rev Log: smarter summary strings: - formats %s %char[] %c and %a now work to print 0-terminated c-strings if they are applied to a char* or char[] even without the [] operator (e.g. ${var%s}) - array formats (char[], intN[], ..) now work when applied to an array of a scalar type even without the [] operator (e.g. ${var%int32_t[]}) LLDB will not crash because of endless loop when trying to obtain a summary for an object that has no value and references itself in its summary string In many cases, a wrong summary string will now display an "" message instead of giving out an empty string Modified: lldb/trunk/include/lldb/Core/FormatManager.h lldb/trunk/include/lldb/Core/ValueObject.h lldb/trunk/lldb.xcodeproj/project.pbxproj lldb/trunk/source/Core/DataExtractor.cpp lldb/trunk/source/Core/Debugger.cpp lldb/trunk/source/Core/FormatManager.cpp lldb/trunk/source/Core/ValueObject.cpp lldb/trunk/test/functionalities/data-formatter/data-formatter-cpp/TestDataFormatterCpp.py lldb/trunk/www/varformats.html Modified: lldb/trunk/include/lldb/Core/FormatManager.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/FormatManager.h?rev=135007&r1=135006&r2=135007&view=diff ============================================================================== --- lldb/trunk/include/lldb/Core/FormatManager.h (original) +++ lldb/trunk/include/lldb/Core/FormatManager.h Tue Jul 12 17:56:10 2011 @@ -499,6 +499,11 @@ static const char * GetFormatAsCString (lldb::Format format); + // when DataExtractor dumps a vectorOfT, it uses a predefined format for each item + // this method returns it, or eFormatInvalid if vector_format is not a vectorOf + static lldb::Format + GetSingleItemFormat(lldb::Format vector_format); + void Changed() { Modified: lldb/trunk/include/lldb/Core/ValueObject.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/ValueObject.h?rev=135007&r1=135006&r2=135007&view=diff ============================================================================== --- lldb/trunk/include/lldb/Core/ValueObject.h (original) +++ lldb/trunk/include/lldb/Core/ValueObject.h Tue Jul 12 17:56:10 2011 @@ -602,7 +602,9 @@ void ReadPointedString(Stream& s, Error& error, - uint32_t max_length = 0); + uint32_t max_length = 0, + bool honor_array = true, + lldb::Format item_format = lldb::eFormatCharArray); bool GetIsConstant () const @@ -741,6 +743,8 @@ m_is_array_item_for_pointer:1, m_is_bitfield_for_scalar:1; + // used to prevent endless looping into GetpPrintableRepresentation() + uint32_t m_dump_printable_counter; friend class ClangExpressionDeclMap; // For GetValue friend class ClangExpressionVariable; // For SetName friend class Target; // For SetName Modified: lldb/trunk/lldb.xcodeproj/project.pbxproj URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lldb.xcodeproj/project.pbxproj?rev=135007&r1=135006&r2=135007&view=diff ============================================================================== --- lldb/trunk/lldb.xcodeproj/project.pbxproj (original) +++ lldb/trunk/lldb.xcodeproj/project.pbxproj Tue Jul 12 17:56:10 2011 @@ -403,6 +403,7 @@ 4CCA645813B40B82003BDF98 /* AppleThreadPlanStepThroughObjCTrampoline.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CCA644A13B40B82003BDF98 /* AppleThreadPlanStepThroughObjCTrampoline.cpp */; }; 4CD0BD0F134BFADF00CB44D4 /* ValueObjectDynamicValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CD0BD0E134BFADF00CB44D4 /* ValueObjectDynamicValue.cpp */; }; 9415F61813B2C0EF00A52B36 /* FormatManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9415F61713B2C0EF00A52B36 /* FormatManager.cpp */; }; + 94611EB213CCA4A4003A22AF /* RefCounter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94611EB113CCA4A4003A22AF /* RefCounter.cpp */; }; 9463D4CD13B1798800C230D4 /* CommandObjectType.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9463D4CC13B1798800C230D4 /* CommandObjectType.cpp */; }; 9467E65213C3D97600B3B6F3 /* TypeHierarchyNavigator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9467E65113C3D97600B3B6F3 /* TypeHierarchyNavigator.cpp */; }; 9A19A6AF1163BBB200E0D453 /* SBValue.h in Headers */ = {isa = PBXBuildFile; fileRef = 9A19A6A51163BB7E00E0D453 /* SBValue.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -1170,6 +1171,8 @@ 69A01E201236C5D400C660B5 /* TimeValue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TimeValue.cpp; sourceTree = ""; }; 9415F61613B2C0DC00A52B36 /* FormatManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = FormatManager.h; path = include/lldb/Core/FormatManager.h; sourceTree = ""; }; 9415F61713B2C0EF00A52B36 /* FormatManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FormatManager.cpp; path = source/Core/FormatManager.cpp; sourceTree = ""; }; + 94611EAF13CCA363003A22AF /* RefCounter.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = RefCounter.h; path = include/lldb/Utility/RefCounter.h; sourceTree = ""; }; + 94611EB113CCA4A4003A22AF /* RefCounter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RefCounter.cpp; path = source/Utility/RefCounter.cpp; sourceTree = ""; }; 9463D4CC13B1798800C230D4 /* CommandObjectType.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CommandObjectType.cpp; path = source/Commands/CommandObjectType.cpp; sourceTree = ""; }; 9463D4CE13B179A500C230D4 /* CommandObjectType.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = CommandObjectType.h; path = source/Commands/CommandObjectType.h; sourceTree = ""; }; 9467E65113C3D97600B3B6F3 /* TypeHierarchyNavigator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TypeHierarchyNavigator.cpp; path = source/Symbol/TypeHierarchyNavigator.cpp; sourceTree = ""; }; @@ -1780,6 +1783,8 @@ isa = PBXGroup; children = ( 264723A511FA076E00DE380C /* CleanUp.h */, + 94611EAF13CCA363003A22AF /* RefCounter.h */, + 94611EB113CCA4A4003A22AF /* RefCounter.cpp */, 261B5A5211C3F2AD00AABD0A /* SharingPtr.cpp */, 4C2FAE2E135E3A70001EDE44 /* SharedCluster.h */, 261B5A5311C3F2AD00AABD0A /* SharingPtr.h */, @@ -3265,6 +3270,7 @@ 9467E65213C3D97600B3B6F3 /* TypeHierarchyNavigator.cpp in Sources */, 26ED3D6D13C563810017D45E /* OptionGroupVariable.cpp in Sources */, 26F4214413C6515B00E04E5E /* DynamicLoaderMacOSXKernel.cpp in Sources */, + 94611EB213CCA4A4003A22AF /* RefCounter.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; Modified: lldb/trunk/source/Core/DataExtractor.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/DataExtractor.cpp?rev=135007&r1=135006&r2=135007&view=diff ============================================================================== --- lldb/trunk/source/Core/DataExtractor.cpp (original) +++ lldb/trunk/source/Core/DataExtractor.cpp Tue Jul 12 17:56:10 2011 @@ -1610,8 +1610,11 @@ s->Printf("0x%8.8x", GetU32 (&offset)); break; - case eFormatVectorOfChar: - s->PutChar('{'); +// please keep the single-item formats below in sync with FormatManager::GetSingleItemFormat +// if you fail to do so, users will start getting different outputs depending on internal +// implementation details they should not care about || + case eFormatVectorOfChar: // || + s->PutChar('{'); // \/ offset = Dump (s, start_offset, eFormatCharArray, 1, item_byte_size, item_byte_size, LLDB_INVALID_ADDRESS, 0, 0); s->PutChar('}'); break; Modified: lldb/trunk/source/Core/Debugger.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/Debugger.cpp?rev=135007&r1=135006&r2=135007&view=diff ============================================================================== --- lldb/trunk/source/Core/Debugger.cpp (original) +++ lldb/trunk/source/Core/Debugger.cpp Tue Jul 12 17:56:10 2011 @@ -694,6 +694,7 @@ } } +// FIXME this should eventually be replaced by proper use of LLDB logging facilities //#define VERBOSE_FORMATPROMPT_OUTPUT #ifdef VERBOSE_FORMATPROMPT_OUTPUT #define IFERROR_PRINT_IT if (error.Fail()) \ @@ -1090,14 +1091,29 @@ IFERROR_PRINT_IT do_deref_pointer = false; } + + bool is_array = ClangASTContext::IsArrayType(target->GetClangType()); + bool is_pointer = ClangASTContext::IsPointerType(target->GetClangType()); + + if ((is_array || is_pointer) && (!is_array_range) && val_obj_display == ValueObject::eDisplayValue) // this should be wrong, but there are some exceptions + { +#ifdef VERBOSE_FORMATPROMPT_OUTPUT + printf("I am into array || pointer && !range\n"); +#endif //VERBOSE_FORMATPROMPT_OUTPUT + // try to use the special cases + var_success = target->DumpPrintableRepresentation(s,val_obj_display, custom_format); + if (!var_success) + s << ""; +#ifdef VERBOSE_FORMATPROMPT_OUTPUT + printf("outcome was : %s\n", var_success ? "good" : "bad"); +#endif //VERBOSE_FORMATPROMPT_OUTPUT + break; + } if (!is_array_range) var_success = target->DumpPrintableRepresentation(s,val_obj_display, custom_format); else - { - bool is_array = ClangASTContext::IsArrayType(target->GetClangType()); - bool is_pointer = ClangASTContext::IsPointerType(target->GetClangType()); - + { if (!is_array && !is_pointer) break; Modified: lldb/trunk/source/Core/FormatManager.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/FormatManager.cpp?rev=135007&r1=135006&r2=135007&view=diff ============================================================================== --- lldb/trunk/source/Core/FormatManager.cpp (original) +++ lldb/trunk/source/Core/FormatManager.cpp Tue Jul 12 17:56:10 2011 @@ -187,3 +187,33 @@ } return false; } + +lldb::Format +FormatManager::GetSingleItemFormat(lldb::Format vector_format) +{ + switch(vector_format) + { + case eFormatVectorOfChar: + return eFormatCharArray; + + case eFormatVectorOfSInt8: + case eFormatVectorOfSInt16: + case eFormatVectorOfSInt32: + case eFormatVectorOfSInt64: + return eFormatDecimal; + + case eFormatVectorOfUInt8: + case eFormatVectorOfUInt16: + case eFormatVectorOfUInt32: + case eFormatVectorOfUInt64: + case eFormatVectorOfUInt128: + return eFormatHex; + + case eFormatVectorOfFloat32: + case eFormatVectorOfFloat64: + return eFormatFloat; + + default: + return lldb::eFormatInvalid; + } +} Modified: lldb/trunk/source/Core/ValueObject.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/ValueObject.cpp?rev=135007&r1=135006&r2=135007&view=diff ============================================================================== --- lldb/trunk/source/Core/ValueObject.cpp (original) +++ lldb/trunk/source/Core/ValueObject.cpp Tue Jul 12 17:56:10 2011 @@ -40,8 +40,11 @@ #include "lldb/Target/Target.h" #include "lldb/Target/Thread.h" +#include "lldb/Utility/RefCounter.h" + using namespace lldb; using namespace lldb_private; +using namespace lldb_utility; static lldb::user_id_t g_value_obj_uid = 0; @@ -78,7 +81,8 @@ m_last_format_mgr_revision(0), m_last_summary_format(), m_last_value_format(), - m_forced_summary_format() + m_forced_summary_format(), + m_dump_printable_counter(0) { m_manager->ManageObject(this); } @@ -116,7 +120,8 @@ m_last_format_mgr_revision(0), m_last_summary_format(), m_last_value_format(), - m_forced_summary_format() + m_forced_summary_format(), + m_dump_printable_counter(0) { m_manager = new ValueObjectManager(); m_manager->ManageObject (this); @@ -752,11 +757,13 @@ void ValueObject::ReadPointedString(Stream& s, Error& error, - uint32_t max_length) + uint32_t max_length, + bool honor_array, + lldb::Format item_format) { if (max_length == 0) - max_length = 128; // this should be a setting, or a formatting parameter + max_length = 128; // FIXME this should be a setting, or a formatting parameter clang_type_t clang_type = GetClangType(); clang_type_t elem_or_pointee_clang_type; @@ -781,14 +788,10 @@ { // We have an array cstr_len = ClangASTContext::GetArraySize (clang_type); - if (cstr_len > max_length) // TODO: make cap a setting + if (cstr_len > max_length) { - cstr_len = ClangASTContext::GetArraySize (clang_type); - if (cstr_len > max_length) // TODO: make cap a setting - { - capped_data = true; - cstr_len = max_length; - } + capped_data = true; + cstr_len = max_length; } cstr_address = GetAddressOf (cstr_address_type, true); } @@ -803,9 +806,8 @@ DataExtractor data; size_t bytes_read = 0; std::vector data_buffer; - Error error; bool prefer_file_cache = false; - if (cstr_len > 0) + if (cstr_len > 0 && honor_array) { data_buffer.resize(cstr_len); data.SetData (&data_buffer.front(), data_buffer.size(), lldb::endian::InlHostByteOrder()); @@ -819,7 +821,7 @@ s << '"'; data.Dump (&s, 0, // Start offset in "data" - eFormatCharArray, // Print as characters + item_format, 1, // Size of item (1 byte for a char!) bytes_read, // How many bytes to print? UINT32_MAX, // num per line @@ -833,7 +835,8 @@ } else { - const size_t k_max_buf_size = 256; + cstr_len = max_length; + const size_t k_max_buf_size = 64; data_buffer.resize (k_max_buf_size + 1); // NULL terminate in case we don't get the entire C string data_buffer.back() = '\0'; @@ -852,10 +855,12 @@ break; if (len > bytes_read) len = bytes_read; + if (len > cstr_len) + len = cstr_len; data.Dump (&s, 0, // Start offset in "data" - eFormatCharArray, // Print as characters + item_format, 1, // Size of item (1 byte for a char!) len, // How many bytes to print? UINT32_MAX, // num per line @@ -865,6 +870,12 @@ if (len < k_max_buf_size) break; + if (len >= cstr_len) + { + s << "..."; + break; + } + cstr_len -= len; cstr_so_addr.Slide (k_max_buf_size); } s << '"'; @@ -1016,6 +1027,9 @@ ValueObject::GetPrintableRepresentation(ValueObjectRepresentationStyle val_obj_display, lldb::Format custom_format) { + + RefCounter ref(&m_dump_printable_counter); + if(custom_format != lldb::eFormatInvalid) SetFormat(custom_format); @@ -1034,18 +1048,18 @@ break; } - if (!return_value) + // this code snippet might lead to endless recursion, thus we use a RefCounter here to + // check that we are not looping endlessly + if (!return_value && (m_dump_printable_counter < 3)) { // try to pick the other choice if (val_obj_display == eDisplayValue) return_value = GetSummaryAsCString(); else if (val_obj_display == eDisplaySummary) return_value = GetValueAsCString(); - else - return_value = ""; } - return (return_value ? return_value : ""); + return (return_value ? return_value : ""); } @@ -1054,25 +1068,129 @@ ValueObjectRepresentationStyle val_obj_display, lldb::Format custom_format) { + + clang_type_t elem_or_pointee_type; + Flags flags(ClangASTContext::GetTypeInfo(GetClangType(), GetClangAST(), &elem_or_pointee_type)); - if (IsCStringContainer(true) && - val_obj_display == ValueObject::eDisplayValue && - custom_format == lldb::eFormatCString) - { - Error error; - ReadPointedString(s, error); - return error.Success(); - } - else + if (flags.AnySet(ClangASTContext::eTypeIsArray | ClangASTContext::eTypeIsPointer) + && val_obj_display == ValueObject::eDisplayValue) { - const char *targetvalue = GetPrintableRepresentation(val_obj_display, custom_format); - if(targetvalue) - s.PutCString(targetvalue); - bool var_success = (targetvalue != NULL); - if(custom_format != eFormatInvalid) - SetFormat(eFormatDefault); - return var_success; + // when being asked to get a printable display an array or pointer type directly, + // try to "do the right thing" + + if (IsCStringContainer(true) && + (custom_format == lldb::eFormatCString || + custom_format == lldb::eFormatCharArray || + custom_format == lldb::eFormatChar || + custom_format == lldb::eFormatVectorOfChar)) // print char[] & char* directly + { + Error error; + ReadPointedString(s, + error, + 0, + (custom_format == lldb::eFormatVectorOfChar) || + (custom_format == lldb::eFormatCharArray)); + return !error.Fail(); + } + + if (custom_format == lldb::eFormatEnum) + return false; + + // this only works for arrays, because I have no way to know when + // the pointed memory ends, and no special \0 end of data marker + if (flags.Test(ClangASTContext::eTypeIsArray)) + { + if ((custom_format == lldb::eFormatBytes) || + (custom_format == lldb::eFormatBytesWithASCII)) + { + uint32_t count = GetNumChildren(); + + s << '['; + for (uint32_t low = 0; low < count; low++) + { + + if (low) + s << ','; + + ValueObjectSP child = GetChildAtIndex(low,true); + if (!child.get()) + { + s << ""; + continue; + } + child->DumpPrintableRepresentation(s, ValueObject::eDisplayValue, custom_format); + } + + s << ']'; + + return true; + } + + if ((custom_format == lldb::eFormatVectorOfChar) || + (custom_format == lldb::eFormatVectorOfFloat32) || + (custom_format == lldb::eFormatVectorOfFloat64) || + (custom_format == lldb::eFormatVectorOfSInt16) || + (custom_format == lldb::eFormatVectorOfSInt32) || + (custom_format == lldb::eFormatVectorOfSInt64) || + (custom_format == lldb::eFormatVectorOfSInt8) || + (custom_format == lldb::eFormatVectorOfUInt128) || + (custom_format == lldb::eFormatVectorOfUInt16) || + (custom_format == lldb::eFormatVectorOfUInt32) || + (custom_format == lldb::eFormatVectorOfUInt64) || + (custom_format == lldb::eFormatVectorOfUInt8)) // arrays of bytes, bytes with ASCII or any vector format should be printed directly + { + uint32_t count = GetNumChildren(); + + lldb::Format format = FormatManager::GetSingleItemFormat(custom_format); + + s << '['; + for (uint32_t low = 0; low < count; low++) + { + + if (low) + s << ','; + + ValueObjectSP child = GetChildAtIndex(low,true); + if (!child.get()) + { + s << ""; + continue; + } + child->DumpPrintableRepresentation(s, ValueObject::eDisplayValue, format); + } + + s << ']'; + + return true; + } + } + + if ((custom_format == lldb::eFormatBoolean) || + (custom_format == lldb::eFormatBinary) || + (custom_format == lldb::eFormatChar) || + (custom_format == lldb::eFormatCharPrintable) || + (custom_format == lldb::eFormatComplexFloat) || + (custom_format == lldb::eFormatDecimal) || + (custom_format == lldb::eFormatHex) || + (custom_format == lldb::eFormatFloat) || + (custom_format == lldb::eFormatOctal) || + (custom_format == lldb::eFormatOSType) || + (custom_format == lldb::eFormatUnicode16) || + (custom_format == lldb::eFormatUnicode32) || + (custom_format == lldb::eFormatUnsigned) || + (custom_format == lldb::eFormatPointer) || + (custom_format == lldb::eFormatComplexInteger) || + (custom_format == lldb::eFormatComplex) || + (custom_format == lldb::eFormatDefault)) // use the [] operator + return false; } + const char *targetvalue = GetPrintableRepresentation(val_obj_display, custom_format); + if(targetvalue) + s.PutCString(targetvalue); + bool var_success = (targetvalue != NULL); + if(custom_format != eFormatInvalid) + SetFormat(eFormatDefault); + return var_success; } addr_t Modified: lldb/trunk/test/functionalities/data-formatter/data-formatter-cpp/TestDataFormatterCpp.py URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/data-formatter/data-formatter-cpp/TestDataFormatterCpp.py?rev=135007&r1=135006&r2=135007&view=diff ============================================================================== --- lldb/trunk/test/functionalities/data-formatter/data-formatter-cpp/TestDataFormatterCpp.py (original) +++ lldb/trunk/test/functionalities/data-formatter/data-formatter-cpp/TestDataFormatterCpp.py Tue Jul 12 17:56:10 2011 @@ -97,7 +97,7 @@ self.runCmd("type summary add -f \"arr = ${var%s}\" -x \"char \\[[0-9]+\\]\" -v") self.expect("frame variable strarr", - substrs = ['arr = "Hello world!\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0"']) + substrs = ['arr = "Hello world!"']) self.runCmd("type summary clear") @@ -109,7 +109,7 @@ self.runCmd("type summary add -f \"arr = ${var%s}\" -x \"char \\[[0-9]+\\]\" -v") self.expect("frame variable strarr", - substrs = ['arr = "Hello world!\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0"']) + substrs = ['arr = "Hello world!']) self.expect("frame variable strptr", substrs = ['ptr = "Hello world!"']) Modified: lldb/trunk/www/varformats.html URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/www/varformats.html?rev=135007&r1=135006&r2=135007&view=diff ============================================================================== --- lldb/trunk/www/varformats.html (original) +++ lldb/trunk/www/varformats.html Tue Jul 12 17:56:10 2011 @@ -97,8 +97,13 @@ variables in your program to print out as hex, you can add a format to the int type.

-

This is done by typing type format add -f hex - int at the LLDB command line.

+

This is done by typing + + +
+ (lldb) type format add -f hex int +
+ at the LLDB command line.

The -f option accepts a format name, and a list of @@ -124,8 +129,12 @@ untouched for other types.

If you simply type
- type format add -f hex A
- type format add -f pointer C

+

+ +
+ (lldb) type format add -f hex A
+ (lldb) type format add -f pointer C +

values of type B will be shown as hex and values of type D as pointers.

@@ -135,8 +144,12 @@ you can use the option -C no to prevent cascading, thus making the two commands required to achieve your goal:
- type format add -f hex -C no A
- type format add -f pointer -C no C

+
+ +
+ (lldb) type format add -C no -f hex A
+ (lldb) type format add -C no -f pointer C +

Two additional options that you will want to look at are -p and -r. These two @@ -169,7 +182,11 @@ in a custom format, while leaving the others of the same type untouched, you can simply type:

- frame variable counter -f hex

+
+ +
+ (lldb) frame variable counter -f hex +

This has the effect of displaying the value of counter as an hexadecimal number, and will keep showing it this @@ -365,42 +382,34 @@

type summary

-

Type summaries enable you to add more information to - the default viewing format for a type, or to completely - replace it with your own display option. Unlike formats - which only apply to basic types, summaries can be used - on every type (basic types, classes (C++ and - Objective-C), arrays, ...).

-

The basic idea beneath type summaries is extracting - information from variables and arranging it in a format - that is suitable for display:

+

Type formats work by showing a different kind of display for + the value of a variable. However, they only work for basic types. + When you want to display a class or struct in a custom format, you + cannot do that using formats.

+

A different feature, type summaries, works by extracting + information from classes, structures, ... (aggregate types) + and arranging it in a user-defined format, as in the following example:

before adding a summary...
(lldb) fr var -T one
(i_am_cool) one = {
- (int) integer = 3
- (float) floating = 3.14159
- (char) character = 'E'
+     (int) integer = 3
+     (float) floating = 3.14159
+     (char) character = 'E'
}

after adding a summary...
(lldb) fr var one
(i_am_cool) one = int = 3, float = 3.14159, char = 69

-

Evidently, somehow we managed to tell LLDB to grab the - three member variables of the i_am_cool - datatype, mix their values with some text, and even ask - it to display the character member using a - custom format.

-

The way to do this is add a summary string to +

The way to obtain this effect is to bind a summary string to the datatype using the type summary add command.

-

Its syntax is similar to type format add, - but some more options are supported that will be - described in the follow-up.

-

The main option to type summary add is -f - which accepts as parameter a summary string. After that, - you can type as many type names as you want to associate - the given summary string to them.

+

In the example, the command we type was:

+
+ +
+ (lldb) frame variable counter -f hex +
@@ -687,7 +696,13 @@ classes, look at the virtual base classes (and bases of bases, ...)
  • If this object's type is a typedef, go through - typedef hierarchy
  • + typedef hierarchy (LLDB might not be able to do this if + the compiler has not emitted enough information. If the + required information to traverse typedef hierarchies is + missing, type cascading will not work. The + clang compiler, + part of the LLVM project, emits the correct debugging + information for LLDB to cascade)
  • If everything has failed, repeat the above search, looking for regular expressions instead of exact matches
  • From granata.enrico at gmail.com Tue Jul 12 17:57:47 2011 From: granata.enrico at gmail.com (Enrico Granata) Date: Tue, 12 Jul 2011 22:57:47 -0000 Subject: [Lldb-commits] [lldb] r135008 - in /lldb/trunk/test/functionalities/data-formatter/data-formatter-smart-array: ./ Makefile TestDataFormatterSmartArray.py main.cpp Message-ID: <20110712225747.B31CB2A6C12C@llvm.org> Author: enrico Date: Tue Jul 12 17:57:47 2011 New Revision: 135008 URL: http://llvm.org/viewvc/llvm-project?rev=135008&view=rev Log: test cases Added: lldb/trunk/test/functionalities/data-formatter/data-formatter-smart-array/ lldb/trunk/test/functionalities/data-formatter/data-formatter-smart-array/Makefile lldb/trunk/test/functionalities/data-formatter/data-formatter-smart-array/TestDataFormatterSmartArray.py lldb/trunk/test/functionalities/data-formatter/data-formatter-smart-array/main.cpp Added: lldb/trunk/test/functionalities/data-formatter/data-formatter-smart-array/Makefile URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/data-formatter/data-formatter-smart-array/Makefile?rev=135008&view=auto ============================================================================== --- lldb/trunk/test/functionalities/data-formatter/data-formatter-smart-array/Makefile (added) +++ lldb/trunk/test/functionalities/data-formatter/data-formatter-smart-array/Makefile Tue Jul 12 17:57:47 2011 @@ -0,0 +1,5 @@ +LEVEL = ../../../make + +CXX_SOURCES := main.cpp + +include $(LEVEL)/Makefile.rules Added: lldb/trunk/test/functionalities/data-formatter/data-formatter-smart-array/TestDataFormatterSmartArray.py URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/data-formatter/data-formatter-smart-array/TestDataFormatterSmartArray.py?rev=135008&view=auto ============================================================================== --- lldb/trunk/test/functionalities/data-formatter/data-formatter-smart-array/TestDataFormatterSmartArray.py (added) +++ lldb/trunk/test/functionalities/data-formatter/data-formatter-smart-array/TestDataFormatterSmartArray.py Tue Jul 12 17:57:47 2011 @@ -0,0 +1,291 @@ +""" +Test lldb data formatter subsystem. +""" + +import os, time +import unittest2 +import lldb +from lldbtest import * + +class DataFormatterTestCase(TestBase): + + mydir = os.path.join("functionalities", "data-formatter", "data-formatter-smart-array") + + @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin") + def test_with_dsym_and_run_command(self): + """Test data formatter commands.""" + self.buildDsym() + self.data_formatter_commands() + + def test_with_dwarf_and_run_command(self): + """Test data formatter commands.""" + self.buildDwarf() + self.data_formatter_commands() + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break at. + self.line = line_number('main.cpp', '// Set break point at this line.') + + def data_formatter_commands(self): + """Test that that file and class static variables display correctly.""" + self.runCmd("file a.out", CURRENT_EXECUTABLE_SET) + + self.expect("breakpoint set -f main.cpp -l %d" % self.line, + BREAKPOINT_CREATED, + startstr = "Breakpoint created: 1: file ='main.cpp', line = %d, locations = 1" % + self.line) + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs = ['stopped', + 'stop reason = breakpoint']) + + # This is the function to remove the custom formats in order to have a + # clean slate for the next test case. + def cleanup(): + self.runCmd('type format clear', check=False) + self.runCmd('type summary clear', check=False) + + # Execute the cleanup function during test case tear down. + self.addTearDownHook(cleanup) + +# check that we are not looping here + self.runCmd("type summary add -f \"${var%V}\" SomeData") + + self.expect("frame variable data", + substrs = ['error']) +# ${var%s} + self.runCmd("type summary add -f \"ptr = ${var%s}\" \"char *\"") + + self.expect("frame variable strptr", + substrs = ['ptr = \"', + 'Hello world!']) + + self.expect("frame variable other.strptr", + substrs = ['ptr = \"', + 'Nested Hello world!']) + + self.runCmd("type summary add -f \"arr = ${var%s}\" -x \"char \\[[0-9]+\\]\"") + + self.expect("frame variable strarr", + substrs = ['arr = \"', + 'Hello world!']) + + self.expect("frame variable other.strarr", + substrs = ['arr = \"', + 'Nested Hello world!']) + +# ${var%c} + self.runCmd("type summary add -f \"ptr = ${var%c}\" \"char *\"") + + self.expect("frame variable strptr", + substrs = ['ptr = \"', + 'Hello world!']) + + self.expect("frame variable other.strptr", + substrs = ['ptr = \"', + 'Nested Hello world!']) + + self.runCmd("type summary add -f \"arr = ${var%c}\" -x \"char \\[[0-9]+\\]\"") + + self.expect("frame variable strarr", + substrs = ['arr = \"', + 'Hello world!']) + + self.expect("frame variable other.strarr", + substrs = ['arr = \"', + 'Nested Hello world!']) + +# ${var%char[]} + self.runCmd("type summary add -f \"arr = ${var%char[]}\" -x \"char \\[[0-9]+\\]\"") + + self.expect("frame variable strarr", + substrs = ['arr = \"', + 'Hello world!']) + + self.expect("frame variable other.strarr", + substrs = ['arr = ', + 'Nested Hello world!']) + + self.runCmd("type summary add -f \"ptr = ${var%char[]}\" \"char *\"") + + self.expect("frame variable strptr", + substrs = ['ptr = \"', + 'Hello world!']) + + self.expect("frame variable other.strptr", + substrs = ['ptr = \"', + 'Nested Hello world!']) + +# ${var%a} + self.runCmd("type summary add -f \"arr = ${var%a}\" -x \"char \\[[0-9]+\\]\"") + + self.expect("frame variable strarr", + substrs = ['arr = \"', + 'Hello world!']) + + self.expect("frame variable other.strarr", + substrs = ['arr = ', + 'Nested Hello world!']) + + self.runCmd("type summary add -f \"ptr = ${var%a}\" \"char *\"") + + self.expect("frame variable strptr", + substrs = ['ptr = \"', + 'Hello world!']) + + self.expect("frame variable other.strptr", + substrs = ['ptr = \"', + 'Nested Hello world!']) + + self.runCmd("type summary add -f \"ptr = ${var[]%char[]}\" \"char *\"") + +# I do not know the size of the data, but you are asking for a full array slice.. +# use the ${var%char[]} to obtain a string as result + self.expect("frame variable strptr", matching=False, + substrs = ['ptr = \"', + 'Hello world!']) + + self.expect("frame variable other.strptr", matching=False, + substrs = ['ptr = \"', + 'Nested Hello world!']) + +# You asked an array-style printout... + self.runCmd("type summary add -f \"ptr = ${var[0-1]%char[]}\" \"char *\"") + + self.expect("frame variable strptr", + substrs = ['ptr = ', + '[{H},{e}]']) + + self.expect("frame variable other.strptr", + substrs = ['ptr = ', + '[{N},{e}]']) + +# using [] is required here + self.runCmd("type summary add -f \"arr = ${var%x}\" \"int [5]\"") + + self.expect("frame variable intarr", + substrs = ['intarr = {', + '[0] = 1']) + + self.expect("frame variable other.intarr", + substrs = ['intarr = {', + '[0] = 9']) + + self.runCmd("type summary add -f \"arr = ${var[]%x}\" \"int [5]\"") + + self.expect("frame variable intarr", + substrs = ['intarr = arr =', + '0x00000001,0x00000001,0x00000002,0x00000003,0x00000005']) + + self.expect("frame variable other.intarr", + substrs = ['intarr = arr =', + '0x00000009,0x00000008,0x00000007,0x00000006,0x00000005']) + +# printing each array item as an array + self.runCmd("type summary add -f \"arr = ${var[]%uint32_t[]}\" \"int [5]\"") + + self.expect("frame variable intarr", + substrs = ['intarr = arr =', + '{0x00000001},{0x00000001},{0x00000002},{0x00000003},{0x00000005}']) + + self.expect("frame variable other.intarr", + substrs = ['intarr = arr = ', + '{0x00000009},{0x00000008},{0x00000007},{0x00000006},{0x00000005}']) + +# printing full array as an array + self.runCmd("type summary add -f \"arr = ${var%uint32_t[]}\" \"int [5]\"") + + self.expect("frame variable intarr", + substrs = ['intarr = arr =', + '0x00000001,0x00000001,0x00000002,0x00000003,0x00000005']) + + self.expect("frame variable other.intarr", + substrs = ['intarr = arr =', + '0x00000009,0x00000008,0x00000007,0x00000006,0x00000005']) + +# printing each array item as an array + self.runCmd("type summary add -f \"arr = ${var[]%float32[]}\" \"float [7]\"") + + self.expect("frame variable flarr", + substrs = ['flarr = arr =', + '{78.5},{77.4},{78},{76.1},{76.7},{76.8},{77}']) + + self.expect("frame variable other.flarr", + substrs = ['flarr = arr = ', + '{25.5},{25.7},{25.9},{26.4},{27.1},{27.3},{26.9}']) + +# printing full array as an array + self.runCmd("type summary add -f \"arr = ${var%float32[]}\" \"float [7]\"") + + self.expect("frame variable flarr", + substrs = ['flarr = arr =', + '78.5,77.4,78,76.1,76.7,76.8,77']) + + self.expect("frame variable other.flarr", + substrs = ['flarr = arr =', + '25.5,25.7,25.9,26.4,27.1,27.3,26.9']) + +# using array smart summary strings for pointers should make no sense + self.runCmd("type summary add -f \"arr = ${var%float32[]}\" \"float *\"") + self.runCmd("type summary add -f \"arr = ${var%int32_t[]}\" \"int *\"") + + self.expect("frame variable flptr", matching=False, + substrs = ['78.5,77.4,78,76.1,76.7,76.8,77']) + + self.expect("frame variable intptr", matching=False, + substrs = ['1,1,2,3,5']) + +# use y and Y + self.runCmd("type summary add -f \"arr = ${var%y}\" \"float [7]\"") + self.runCmd("type summary add -f \"arr = ${var%y}\" \"int [5]\"") + + self.expect("frame variable flarr", + substrs = ['flarr = arr =', + '00 00 9d 42,cd cc 9a 42,00 00 9c 42,33 33 98 42,66 66 99 42,9a 99 99 42,00 00 9a 42']) + + self.expect("frame variable other.flarr", + substrs = ['flarr = arr =', + '00 00 cc 41,9a 99 cd 41,33 33 cf 41,33 33 d3 41,cd cc d8 41,66 66 da 41,33 33 d7 41']) + + self.expect("frame variable intarr", + substrs = ['intarr = arr =', + '01 00 00 00,01 00 00 00,02 00 00 00,03 00 00 00,05 00 00 00']) + + self.expect("frame variable other.intarr", + substrs = ['intarr = arr = ', + '09 00 00 00,08 00 00 00,07 00 00 00,06 00 00 00,05 00 00 00']) + + self.runCmd("type summary add -f \"arr = ${var%Y}\" \"float [7]\"") + self.runCmd("type summary add -f \"arr = ${var%Y}\" \"int [5]\"") + + self.expect("frame variable flarr", + substrs = ['flarr = arr =', + '...B,cd cc 9a 42', + 'ff.B,9a 99 99 42']) + + self.expect("frame variable other.flarr", + substrs = ['flarr = arr =', + '...A,33 33 cf 41', + '33.A,cd cc d8 41']) + + self.expect("frame variable intarr", + substrs = ['intarr = arr =', + '....,01 00 00 00', + '....,05 00 00 00']) + + self.expect("frame variable other.intarr", + substrs = ['intarr = arr = ', + '09 00 00 00', + '....,07 00 00 00']) + + +if __name__ == '__main__': + import atexit + lldb.SBDebugger.Initialize() + atexit.register(lambda: lldb.SBDebugger.Terminate()) + unittest2.main() Added: lldb/trunk/test/functionalities/data-formatter/data-formatter-smart-array/main.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/data-formatter/data-formatter-smart-array/main.cpp?rev=135008&view=auto ============================================================================== --- lldb/trunk/test/functionalities/data-formatter/data-formatter-smart-array/main.cpp (added) +++ lldb/trunk/test/functionalities/data-formatter/data-formatter-smart-array/main.cpp Tue Jul 12 17:57:47 2011 @@ -0,0 +1,65 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include +#include +#include +#include + +struct SomeData +{ + int x; +}; + +struct SomeOtherData +{ + char strarr[32]; + char *strptr; + int intarr[5]; + float flarr[7]; + + SomeOtherData() + { + strcpy(strarr,"Nested Hello world!"); + strptr = new char[128]; + strcpy(strptr,"Nested Hello world!"); + intarr[0] = 9; + intarr[1] = 8; + intarr[2] = 7; + intarr[3] = 6; + intarr[4] = 5; + + flarr[0] = 25.5; + flarr[1] = 25.7; + flarr[2] = 25.9; + flarr[3] = 26.4; + flarr[4] = 27.1; + flarr[5] = 27.3; + flarr[6] = 26.9; + } +}; + +int main (int argc, const char * argv[]) +{ + char strarr[32] = "Hello world!"; + char *strptr = NULL; + strptr = "Hello world!"; + int intarr[5] = {1,1,2,3,5}; + float flarr[7] = {78.5,77.4,78.0,76.1,76.7,76.8,77.0}; + + SomeData data; + + SomeOtherData other; + + float* flptr = flarr; + int* intptr = intarr; + + return 0; // Set break point at this line. + +} From johnny.chen at apple.com Tue Jul 12 18:18:03 2011 From: johnny.chen at apple.com (Johnny Chen) Date: Tue, 12 Jul 2011 23:18:03 -0000 Subject: [Lldb-commits] [lldb] r135009 - in /lldb/trunk/test/functionalities/target_command: TestTargetCommand.py globals.c Message-ID: <20110712231803.A55472A6C12C@llvm.org> Author: johnny Date: Tue Jul 12 18:18:03 2011 New Revision: 135009 URL: http://llvm.org/viewvc/llvm-project?rev=135009&view=rev Log: Add a test case to exercise 'target variable' command before and after running the inferior. Currently it fails after the inferior is run. rdar://problem/9763907 Added: lldb/trunk/test/functionalities/target_command/globals.c Modified: lldb/trunk/test/functionalities/target_command/TestTargetCommand.py Modified: lldb/trunk/test/functionalities/target_command/TestTargetCommand.py URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/target_command/TestTargetCommand.py?rev=135009&r1=135008&r2=135009&view=diff ============================================================================== --- lldb/trunk/test/functionalities/target_command/TestTargetCommand.py (original) +++ lldb/trunk/test/functionalities/target_command/TestTargetCommand.py Tue Jul 12 18:18:03 2011 @@ -1,5 +1,5 @@ """ -Test some target commands: create, list, select. +Test some target commands: create, list, select, variable. """ import unittest2 @@ -21,19 +21,31 @@ def test_target_command_with_dwarf(self): """Test some target commands: create, list, select.""" da = {'C_SOURCES': 'a.c', 'EXE': 'a.out'} - self.buildDefault(dictionary=da) + self.buildDwarf(dictionary=da) self.addTearDownCleanup(dictionary=da) db = {'C_SOURCES': 'b.c', 'EXE': 'b.out'} - self.buildDefault(dictionary=db) + self.buildDwarf(dictionary=db) self.addTearDownCleanup(dictionary=db) dc = {'C_SOURCES': 'c.c', 'EXE': 'c.out'} - self.buildDefault(dictionary=dc) + self.buildDwarf(dictionary=dc) self.addTearDownCleanup(dictionary=dc) self.do_target_command() + # rdar://problem/9763907 + # 'target variable' command fails if the target program has been run + #@unittest2.expectedFailure + @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin") + def test_target_variable_command_with_dsym(self): + """Test 'target variable' command before and after starting the inferior.""" + d = {'C_SOURCES': 'globals.c', 'EXE': 'globals'} + self.buildDsym(dictionary=d) + self.addTearDownCleanup(dictionary=d) + + self.do_target_variable_command('globals') + def do_target_command(self): """Exercise 'target create', 'target list', 'target select' commands.""" exe_a = os.path.join(os.getcwd(), "a.out") @@ -87,6 +99,24 @@ self.runCmd("target list") + def do_target_variable_command(self, exe_name): + """Exercise 'target variable' command before and after starting the inferior.""" + self.runCmd("file " + exe_name, CURRENT_EXECUTABLE_SET) + + self.expect("target variable my_global_char", VARIABLES_DISPLAYED_CORRECTLY, + substrs = ["my_global_char", "'X'"]) + self.expect("target variable my_global_str", VARIABLES_DISPLAYED_CORRECTLY, + substrs = ['my_global_str', '"abc"']) + + self.runCmd("run") + + # rdar://problem/9763907 + # 'target variable' command fails if the target program has been run + self.expect("target variable my_global_char", VARIABLES_DISPLAYED_CORRECTLY, + substrs = ["my_global_char", "'X'"]) + self.expect("target variable my_global_str", VARIABLES_DISPLAYED_CORRECTLY, + substrs = ['my_global_str', '"abc"']) + if __name__ == '__main__': import atexit Added: lldb/trunk/test/functionalities/target_command/globals.c URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/target_command/globals.c?rev=135009&view=auto ============================================================================== --- lldb/trunk/test/functionalities/target_command/globals.c (added) +++ lldb/trunk/test/functionalities/target_command/globals.c Tue Jul 12 18:18:03 2011 @@ -0,0 +1,21 @@ +//===-- main.c --------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#include + +char my_global_char = 'X'; +const char* my_global_str = "abc"; + +int main (int argc, char const *argv[]) +{ + printf("global char: %c\n", my_global_char); + + printf("global str: %s\n", my_global_str); + + return 0; +} From granata.enrico at gmail.com Tue Jul 12 19:00:57 2011 From: granata.enrico at gmail.com (Enrico Granata) Date: Wed, 13 Jul 2011 00:00:57 -0000 Subject: [Lldb-commits] [lldb] r135012 - in /lldb/trunk: include/lldb/Utility/RefCounter.h source/Utility/RefCounter.cpp www/varformats.html Message-ID: <20110713000057.4233A2A6C12C@llvm.org> Author: enrico Date: Tue Jul 12 19:00:57 2011 New Revision: 135012 URL: http://llvm.org/viewvc/llvm-project?rev=135012&view=rev Log: fixing missing RefCounter class Added: lldb/trunk/include/lldb/Utility/RefCounter.h lldb/trunk/source/Utility/RefCounter.cpp Modified: lldb/trunk/www/varformats.html Added: lldb/trunk/include/lldb/Utility/RefCounter.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Utility/RefCounter.h?rev=135012&view=auto ============================================================================== --- lldb/trunk/include/lldb/Utility/RefCounter.h (added) +++ lldb/trunk/include/lldb/Utility/RefCounter.h Tue Jul 12 19:00:57 2011 @@ -0,0 +1,58 @@ +//===-- RefCounter.h --------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_RefCounter_h_ +#define liblldb_RefCounter_h_ + +#include "lldb/lldb-public.h" + +namespace lldb_utility { + +//---------------------------------------------------------------------- +// A simple reference counter object. You need an uint32_t* to use it +// Once that is in place, everyone who needs to ref-count, can say +// RefCounter ref(ptr); +// (of course, the pointer is a shared resource, and must be accessible to +// everyone who needs it). Synchronization is handled by RefCounter itself +// To check if more than 1 RefCounter is attached to the same value, you can +// either call shared(), or simply cast ref to bool +// The counter is decreased each time a RefCounter to it goes out of scope +//---------------------------------------------------------------------- +class RefCounter +{ +public: + typedef uint32_t value_type; + + RefCounter(value_type* ctr); + + ~RefCounter(); + +private: + value_type* m_counter; + DISALLOW_COPY_AND_ASSIGN (RefCounter); + + template + inline T + increment(T* t) + { + return __sync_fetch_and_add(t, 1); + } + + template + inline T + decrement(T* t) + { + return __sync_fetch_and_add(t, -1); + } + +}; + +} // namespace lldb_utility + +#endif // #ifndef liblldb_RefCounter_h_ Added: lldb/trunk/source/Utility/RefCounter.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Utility/RefCounter.cpp?rev=135012&view=auto ============================================================================== --- lldb/trunk/source/Utility/RefCounter.cpp (added) +++ lldb/trunk/source/Utility/RefCounter.cpp Tue Jul 12 19:00:57 2011 @@ -0,0 +1,25 @@ +//===---------------------RefCounter.cpp ------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/Utility/RefCounter.h" + +namespace lldb_utility { + +RefCounter::RefCounter(RefCounter::value_type* ctr): +m_counter(ctr) +{ + increment(m_counter); +} + +RefCounter::~RefCounter() +{ + decrement(m_counter); +} + +} // namespace lldb_utility Modified: lldb/trunk/www/varformats.html URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/www/varformats.html?rev=135012&r1=135011&r2=135012&view=diff ============================================================================== --- lldb/trunk/www/varformats.html (original) +++ lldb/trunk/www/varformats.html Tue Jul 12 19:00:57 2011 @@ -407,7 +407,7 @@

    In the example, the command we type was:

    - (lldb) frame variable counter -f hex + (lldb) type summary add -f "int = ${var.integer}, float = ${var.floating}, char = ${var.character%u}" i_am_cool
    @@ -415,8 +415,11 @@

    Summary Strings

    -

    So what is the format of the summary strings? Summary - strings can contain plain text, control characters and +

    While you may already have guessed a lot about the format of + summary strings from the above example, a detailed description + of their format follows.

    + +

    Summary strings can contain plain text, control characters and special symbols that have access to information about the current object and the overall program state.

    Normal characters are any text that doesn't contain a '{', @@ -434,22 +437,20 @@

    The simplest thing you can do is grab a member variable of a class or structure by typing its expression path. In the previous example, the expression path - for the floating member is simply .floating, - because all you have to do to get at it given an object - of type i_am_cool is access it straight - away. Thus, to ask the summary string to display floating + for the floating member is simply .floating. + Thus, to ask the summary string to display floating you would type ${var.floating} (${var is a placeholder token replaced with whatever variable is being displayed).

    If you have code like the following:
    struct A {
    - int x;
    - int y;
    +     int x;
    +     int y;
    };
    struct B {
    - A x;
    - A y;
    - int z;
    +     A x;
    +     A y;
    +     int z;
    };
    the expression path for the y member of the x member of an object of @@ -465,9 +466,9 @@ or even if the actual definition of B were:
    struct B {
    - A *x;
    - A y;
    - int z;
    +     A *x;
    +     A y;
    +     int z;
    };

    This is unlike the behaviour of frame variable @@ -480,11 +481,7 @@ members' information, a pointer to an object is just as good as the object itself for the purpose.

    Of course, you can have multiple entries in one summary - string. For instance, the command used to produce the - above summary string for i_am_cool was:
    - type summary add -f "int = ${var.integer}, float = - ${var.floating}, char = ${var.character%u}" i_am_cool -

    + string, as shown in the previous example.

    As you can see, the last expression path also contains a %u symbol which is nowhere to be found in the actual member variable name. The symbol is @@ -492,8 +489,9 @@ in fact it has a similar effect. If you add a % sign followed by any one format name or abbreviation from the above table after an expression path, the resulting - object will be displyed using exactly that format - instead of the LLDB default one.

    + object will be displyed using the chosen format (this is + applicable to non-aggregate types only, with a few + special exceptions discussed below).

    There are two more special format symbols that you can use only as part of a summary string: %V and %@. The first one tells LLDB to ignore @@ -518,17 +516,28 @@ e.g.
    (lldb) fr var -T c
    (Couple) c = {
    - (SimpleWithPointers) sp = {
    - (int *) x = 0x00000001001000b0
    - (float *) y = 0x00000001001000c0
    - (char *) z = 0x00000001001000d0 "X"
    - }
    - (Simple *) s = 0x00000001001000e0
    +     (SimpleWithPointers) sp = {
    +         (int *) x = 0x00000001001000b0
    +         (float *) y = 0x00000001001000c0
    +         (char *) z = 0x00000001001000d0 "X"
    +     }
    +     (Simple *) s = 0x00000001001000e0
    }
    - (lldb) type summary add -f "int = ${*var.sp.x}, +

    + + If one types the following commands: + +

    + +
    + (lldb) type summary add -f "int = ${*var.sp.x}, float = ${*var.sp.y}, char = ${*var.sp.z%u}, Simple = ${*var.s}" Couple
    - (lldb) type summary add -c -p Simple
    + (lldb) type summary add -c -p Simple
    +

    + + the output becomes:
    + (lldb) fr var c
    (Couple) c = int = 9, float = 9.99, char = 88, Simple = (x=9, y=9.99, z='X')
    @@ -536,22 +545,24 @@

    Option -c to type summary add tells LLDB not to look for a summary string, but instead to just print a listing of all the object's children on - one line, lay out as in the previous example. The -p - flag is used as a trick to show that aggregate types can - be dereferenced as well as primitive ones. The above - output would be shown even by typing type summary - add -f "int = ${*var.sp.x}, float = ${*var.sp.y}, char - = ${*var.sp.z%u}, Simple = ${var.s}" Couple if - one took away the -p flag from the summary - for type Simple.

    + one line, as shown in the summary for object Simple.

    +

    We are using the -p flag here to show that + aggregate types can be dereferenced as well as basic types. + The following command sequence would work just as well and + produce the same output: +

    + +
    + (lldb) type summary add -f "int = ${*var.sp.x}, + float = ${*var.sp.y}, char = ${*var.sp.z%u}, Simple = + ${var.s}" Couple
    + (lldb) type summary add -c Simple
    +

    -

    More on summary strings

    +

    Bitfields and array syntax

    -

    What was described above are the main features that you - can use in summary strings. However, there are three - more features to them.

    Sometimes, a basic type's value actually represents several different values packed together in a bitfield. With the classical view, there is no way to look at @@ -570,54 +581,69 @@ a pair of indices separated by a -.
    e.g.
    (lldb) fr var float_point
    - (float) float_point = -3.14159
    - (lldb) type summary add -f "Sign: ${var[31]%B} + (float) float_point = -3.14159
    +

    + +
    + (lldb) type summary add -f "Sign: ${var[31]%B} Exponent: ${var[30-23]%x} Mantissa: ${var[0-22]%u}" - float
    + float +

    + + (lldb) fr var float_point
    (float) float_point = -3.14159 Sign: true Exponent: 0x00000080 Mantissa: 4788184
    In this example, LLDB shows the internal representation of a float variable by - extracting bitfields out of a float object. If you give - a single index, only that one bit will be extracted. If - you give a pair of indices, all the bits in the range - (extremes included) will be extracted. Ranges can be - specified either by giving the lower index first, or - higher index first (as is often customary in describing - packed data-type formats).

    -

    The second additional feature allows you to display + extracting bitfields out of a float object.

    + +

    As far as the syntax is concerned, it looks + much like the normal C array syntax, but also allows you + to specify 2 indices, separated by a - symbol (a range). + Ranges can be given either with the lower or the higher index + first, and range extremes are always included in the bits extracted.

    + +

    LLDB also allows to use a similar syntax to display array members inside a summary string. For instance, you may want to display all arrays of a given type using a more compact notation than the default, and then just delve into individual array members that prove - interesting to your debugging task. You can use a - similar syntax to the one used for bitfields to tell - LLDB to format arrays in special ways.
    + interesting to your debugging task. You can tell + LLDB to format arrays in special ways, possibly + independent of the way the array members' datatype is formatted.
    e.g.
    (lldb) fr var sarray
    (Simple [3]) sarray = {
    - [0] = {
    - x = 1
    - y = 2
    - z = '\x03'
    - }
    - [1] = {
    - x = 4
    - y = 5
    - z = '\x06'
    - }
    - [2] = {
    - x = 7
    - y = 8
    - z = '\t'
    - }
    - }
    - (lldb) type summary add -f "${var[].x}" "Simple - [3]"
    +     [0] = {
    +         x = 1
    +         y = 2
    +         z = '\x03'
    +     }
    +     [1] = {
    +         x = 4
    +         y = 5
    +         z = '\x06'
    +     }
    +     [2] = {
    +         x = 7
    +         y = 8
    +         z = '\t'
    +     }
    + }
    + +

    + +
    + (lldb) type summary add -f "${var[].x}" "Simple + [3]" +

    + + (lldb) fr var sarray
    - (Simple [3]) sarray = [1,4,7]
    -
    The [] symbol amounts to: if var + (Simple [3]) sarray = [1,4,7]

    + +

    The [] symbol amounts to: if var is an array and I knows its size, apply this summary string to every element of the array. Here, we are asking LLDB to display .x for every @@ -627,21 +653,75 @@ the array format getting in the way:
    (lldb) fr var sarray[1]
    (Simple) sarray[1] = {
    - x = 4
    - y = 5
    - z = '\x06'
    +     x = 4
    +     y = 5
    +     z = '\x06'
    }

    You can also ask LLDB to only print a subset of the array range by using the same syntax used to extract bit - for bitfields.

    + for bitfields: +
    + +
    + (lldb) type summary add -f "${var[1-2].x}" "Simple + [3]" +

    + + (lldb) fr var sarray
    + (Simple [3]) sarray = [4,7]

    +

    The same logic works if you are printing a pointer - instead of an array, however in this latter case, [] + instead of an array, however in this latter case, the empty + square brackets operator [] cannot be used and you need to give exact range limits.

    -

    The third, and last, additional feature does not - directly apply to the summary strings themselves, but is - an additional option to the type summary add - command: -x

    + +

    In general, LLDB needs the square brackets operator [] in + order to handle arrays and pointers correctly, and for pointers it also + needs a range. However, a few special cases are defined to make your life easier: +

      +
    • you can print a 0-terminated string (C-string) using the %s format, + omitting square brackets, as in: +
    + +
    + (lldb) type summary add -f "${var%s}" "char *" +
    + + This works for char* and char[] objects, and uses the + \0 terminator + when possible to terminate the string, instead of relying on array length. + + +
      + +
    • anyone of the array formats (int8_t[], + float32{}, ...), and the y, Y + and a formats + work to print an array of a non-aggregate + type, even if square brackets are omitted. +
    + +
    + (lldb) type summary add -f "${var%int32_t[]}" "int [10]" +
    + + + This feature, however, is not enabled for pointers because there is no + way for LLDB to detect the end of the pointed data. +
    + This also does not work for other formats (e.g. boolean), and you must + specify the square brackets operator to get the expected output. +

    + + + +
    +

    Regular expression typenames

    +
    +
    +
    +

    As you noticed, in order to associate the custom summary string to the array types, one must give the array size as part of the typename. This can long become @@ -651,9 +731,17 @@ [12], ...

    If you use the -x option, type names are treated as regular expressions instead of type names. - This would let you rephrase the above example as:
    - (lldb) type summary add -f "${var[].x}" - -x "Simple \[[0-9]+\]"
    + This would let you rephrase the above example + for arrays of type Simple [3] as:
    + +

    + +
    + (lldb) type summary add -f "${var[].x}" + -x "Simple \[[0-9]+\]" +
    + + (lldb) fr var sarray
    (Simple [3]) sarray = [1,4,7]
    The above scenario works for Simple [3] @@ -670,6 +758,36 @@ regular expression match for your type itself.

    + +
    +

    Named summaries

    +
    +

    For a given datatype, there may be different meaningful summary + representations. However, currently, only one summary can be associated + to a given datatype. If you need to temporarily override the association + for a variable, without changing the summary string bound to the datatype, + you can use named summaries.

    + +

    Named summaries work by attaching a name to a summary string when creating + it. Then, when there is a need to attach the summary string to a variable, the + frame variable command, supports a --summary option + that tells LLDB to use the named summary given instead of the default one.

    + +
    + +
    + (lldb) type summary add -f "x=${var.integer}" --name NamedSummary +
    + (lldb) fr var one
    + (i_am_cool) one = int = 3, float = 3.14159, char = 69
    + (lldb) fr var one --summary NamedSummary
    + (i_am_cool) one = x=3
    +

    + + + + +

    Finding summaries 101

    From johnny.chen at apple.com Tue Jul 12 19:31:31 2011 From: johnny.chen at apple.com (Johnny Chen) Date: Wed, 13 Jul 2011 00:31:31 -0000 Subject: [Lldb-commits] [lldb] r135016 - in /lldb/trunk/test/functionalities/target_command: TestTargetCommand.py globals.c Message-ID: <20110713003131.5F3392A6C12C@llvm.org> Author: johnny Date: Tue Jul 12 19:31:31 2011 New Revision: 135016 URL: http://llvm.org/viewvc/llvm-project?rev=135016&view=rev Log: Add display of a static int variable to the test scenario. Modified: lldb/trunk/test/functionalities/target_command/TestTargetCommand.py lldb/trunk/test/functionalities/target_command/globals.c Modified: lldb/trunk/test/functionalities/target_command/TestTargetCommand.py URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/target_command/TestTargetCommand.py?rev=135016&r1=135015&r2=135016&view=diff ============================================================================== --- lldb/trunk/test/functionalities/target_command/TestTargetCommand.py (original) +++ lldb/trunk/test/functionalities/target_command/TestTargetCommand.py Tue Jul 12 19:31:31 2011 @@ -107,6 +107,8 @@ substrs = ["my_global_char", "'X'"]) self.expect("target variable my_global_str", VARIABLES_DISPLAYED_CORRECTLY, substrs = ['my_global_str', '"abc"']) + self.expect("target variable my_static_int", VARIABLES_DISPLAYED_CORRECTLY, + substrs = ['my_static_int', '228']) self.runCmd("run") @@ -116,6 +118,8 @@ substrs = ["my_global_char", "'X'"]) self.expect("target variable my_global_str", VARIABLES_DISPLAYED_CORRECTLY, substrs = ['my_global_str', '"abc"']) + self.expect("target variable my_static_int", VARIABLES_DISPLAYED_CORRECTLY, + substrs = ['my_static_int', '228']) if __name__ == '__main__': Modified: lldb/trunk/test/functionalities/target_command/globals.c URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/target_command/globals.c?rev=135016&r1=135015&r2=135016&view=diff ============================================================================== --- lldb/trunk/test/functionalities/target_command/globals.c (original) +++ lldb/trunk/test/functionalities/target_command/globals.c Tue Jul 12 19:31:31 2011 @@ -10,12 +10,15 @@ char my_global_char = 'X'; const char* my_global_str = "abc"; +static int my_static_int = 228; int main (int argc, char const *argv[]) { printf("global char: %c\n", my_global_char); printf("global str: %s\n", my_global_str); + + printf("argc + my_static_int = %d\n", (argc + my_static_int)); return 0; } From johnny.chen at apple.com Tue Jul 12 19:46:49 2011 From: johnny.chen at apple.com (Johnny Chen) Date: Wed, 13 Jul 2011 00:46:49 -0000 Subject: [Lldb-commits] [lldb] r135019 - in /lldb/trunk/include/lldb/API: SBModule.h SBTarget.h Message-ID: <20110713004649.972802A6C12C@llvm.org> Author: johnny Date: Tue Jul 12 19:46:49 2011 New Revision: 135019 URL: http://llvm.org/viewvc/llvm-project?rev=135019&view=rev Log: Update docstrings for SBModeule/SBTarget::FindGlobalVariables(). Modified: lldb/trunk/include/lldb/API/SBModule.h lldb/trunk/include/lldb/API/SBTarget.h Modified: lldb/trunk/include/lldb/API/SBModule.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/API/SBModule.h?rev=135019&r1=135018&r2=135019&view=diff ============================================================================== --- lldb/trunk/include/lldb/API/SBModule.h (original) +++ lldb/trunk/include/lldb/API/SBModule.h Tue Jul 12 19:46:49 2011 @@ -175,12 +175,15 @@ //------------------------------------------------------------------ /// Find global and static variables by name. /// + /// @param[in] target + /// A valid SBTarget instance representing the debuggee. + /// /// @param[in] name /// The name of the global or static variable we are looking /// for. /// - /// @param[in] target - /// The target program where the variables reside. + /// @param[in] max_matches + /// Allow the number of matches to be limited to \a max_matches. /// /// @return /// A list of matched variables in an SBValueList. Modified: lldb/trunk/include/lldb/API/SBTarget.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/API/SBTarget.h?rev=135019&r1=135018&r2=135019&view=diff ============================================================================== --- lldb/trunk/include/lldb/API/SBTarget.h (original) +++ lldb/trunk/include/lldb/API/SBTarget.h Tue Jul 12 19:46:49 2011 @@ -290,6 +290,25 @@ bool append, lldb::SBSymbolContextList& sc_list); +#ifdef SWIG + %feature("autodoc", " +#endif + //------------------------------------------------------------------ + /// Find global and static variables by name. + /// + /// @param[in] name + /// The name of the global or static variable we are looking + /// for. + /// + /// @param[in] max_matches + /// Allow the number of matches to be limited to \a max_matches. + /// + /// @return + /// A list of matched variables in an SBValueList. + //------------------------------------------------------------------ +#ifdef SWIG + ") FindGlobalVariables; +#endif lldb::SBValueList FindGlobalVariables (const char *name, uint32_t max_matches); From johnny.chen at apple.com Wed Jul 13 15:03:51 2011 From: johnny.chen at apple.com (Johnny Chen) Date: Wed, 13 Jul 2011 20:03:51 -0000 Subject: [Lldb-commits] [lldb] r135069 - /lldb/trunk/test/functionalities/target_command/TestTargetCommand.py Message-ID: <20110713200351.91D962A6C12C@llvm.org> Author: johnny Date: Wed Jul 13 15:03:51 2011 New Revision: 135069 URL: http://llvm.org/viewvc/llvm-project?rev=135069&view=rev Log: Add @expectedFailure decorator for test_target_variable_command_with_dsym(). rdar://problem/9763907 Modified: lldb/trunk/test/functionalities/target_command/TestTargetCommand.py Modified: lldb/trunk/test/functionalities/target_command/TestTargetCommand.py URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/target_command/TestTargetCommand.py?rev=135069&r1=135068&r2=135069&view=diff ============================================================================== --- lldb/trunk/test/functionalities/target_command/TestTargetCommand.py (original) +++ lldb/trunk/test/functionalities/target_command/TestTargetCommand.py Wed Jul 13 15:03:51 2011 @@ -36,7 +36,7 @@ # rdar://problem/9763907 # 'target variable' command fails if the target program has been run - #@unittest2.expectedFailure + @unittest2.expectedFailure @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin") def test_target_variable_command_with_dsym(self): """Test 'target variable' command before and after starting the inferior.""" From johnny.chen at apple.com Wed Jul 13 17:34:29 2011 From: johnny.chen at apple.com (Johnny Chen) Date: Wed, 13 Jul 2011 22:34:29 -0000 Subject: [Lldb-commits] [lldb] r135100 - in /lldb/trunk/test: lldbutil.py python_api/frame/inlines/TestInlinedFrame.py python_api/frame/inlines/inlines.c Message-ID: <20110713223429.9E2132A6C12C@llvm.org> Author: johnny Date: Wed Jul 13 17:34:29 2011 New Revision: 135100 URL: http://llvm.org/viewvc/llvm-project?rev=135100&view=rev Log: Modify the test script to better handle the different inlining behaviors of clang/gcc/llvm-gcc. If the first breakpoint is due to stop at an inlined frame, test that the call site corresponds to where it should be. Also add an expecr for a second break stop, if the first break stop corresponds to an inlined call frame #0. rdar://problem/9741470 Modified: lldb/trunk/test/lldbutil.py lldb/trunk/test/python_api/frame/inlines/TestInlinedFrame.py lldb/trunk/test/python_api/frame/inlines/inlines.c Modified: lldb/trunk/test/lldbutil.py URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/lldbutil.py?rev=135100&r1=135099&r2=135100&view=diff ============================================================================== --- lldb/trunk/test/lldbutil.py (original) +++ lldb/trunk/test/lldbutil.py Wed Jul 13 17:34:29 2011 @@ -395,7 +395,8 @@ print >> output, " frame #{num}: {addr:#016x} {mod}`{func} at {file}:{line} {args}".format( num=i, addr=load_addr, mod=mods[i], func='%s [inlined]' % funcs[i] if frame.IsInlined() else funcs[i], - file=files[i], line=lines[i], args=get_args_as_string(frame, showFuncName=False)) + file=files[i], line=lines[i], + args=get_args_as_string(frame, showFuncName=False) if not frame.IsInlined() else '()') if string_buffer: return output.getvalue() Modified: lldb/trunk/test/python_api/frame/inlines/TestInlinedFrame.py URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/python_api/frame/inlines/TestInlinedFrame.py?rev=135100&r1=135099&r2=135100&view=diff ============================================================================== --- lldb/trunk/test/python_api/frame/inlines/TestInlinedFrame.py (original) +++ lldb/trunk/test/python_api/frame/inlines/TestInlinedFrame.py Wed Jul 13 17:34:29 2011 @@ -25,6 +25,15 @@ self.buildDwarf() self.do_stop_at_outer_inline() + def setUp(self): + + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to of function 'c'. + self.source = 'inlines.c' + self.first_stop = line_number(self.source, '// This should correspond to the first break stop.') + self.second_stop = line_number(self.source, '// This should correspond to the second break stop.') + def do_stop_at_outer_inline(self): """Exercise SBFrame.IsInlined() and SBFrame.GetFunctionName().""" exe = os.path.join(os.getcwd(), "a.out") @@ -33,8 +42,8 @@ target = self.dbg.CreateTarget(exe) self.assertTrue(target, VALID_TARGET) - # Now create a breakpoint on main.c by name 'c'. - breakpoint = target.BreakpointCreateByName('outer_inline', 'a.out') + # Now create a breakpoint on main.c by the name of 'inner_inline'. + breakpoint = target.BreakpointCreateByName('inner_inline', 'a.out') #print "breakpoint:", breakpoint self.assertTrue(breakpoint and breakpoint.GetNumLocations() > 1, @@ -47,17 +56,35 @@ self.assertTrue(process.GetState() == lldb.eStateStopped, PROCESS_STOPPED) - self.runCmd("bt") + import lldbutil + stack_traces1 = lldbutil.print_stacktraces(process, string_buffer=True) if self.TraceOn(): - print "Full stack traces when first stopped on the breakpoint 'outer_inline':" - import lldbutil - print lldbutil.print_stacktraces(process, string_buffer=True) + print "Full stack traces when first stopped on the breakpoint 'inner_inline':" + print stack_traces1 # The first breakpoint should correspond to an inlined call frame. + # If it's an inlined call frame, expect to find, in the stack trace, + # that there is a frame which corresponds to the following call site: + # + # outer_inline (argc); + # frame0 = process.GetThreadAtIndex(0).GetFrameAtIndex(0) - self.assertTrue(frame0.IsInlined() and - frame0.GetFunctionName() == 'outer_inline') - + if frame0.IsInlined(): + filename = frame0.GetLineEntry().GetFileSpec().GetFilename() + self.assertTrue(filename == self.source) + self.expect(stack_traces1, "First stop at %s:%d" % (self.source, self.first_stop), exe=False, + substrs = ['%s:%d' % (self.source, self.first_stop)]) + + # Expect to break again for the second time. + process.Continue() + self.assertTrue(process.GetState() == lldb.eStateStopped, + PROCESS_STOPPED) + stack_traces2 = lldbutil.print_stacktraces(process, string_buffer=True) + if self.TraceOn(): + print "Full stack traces when stopped on the breakpoint 'inner_inline' for the second time:" + print stack_traces2 + self.expect(stack_traces2, "Second stop at %s:%d" % (self.source, self.second_stop), exe=False, + substrs = ['%s:%d' % (self.source, self.second_stop)]) if __name__ == '__main__': import atexit Modified: lldb/trunk/test/python_api/frame/inlines/inlines.c URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/python_api/frame/inlines/inlines.c?rev=135100&r1=135099&r2=135100&view=diff ============================================================================== --- lldb/trunk/test/python_api/frame/inlines/inlines.c (original) +++ lldb/trunk/test/python_api/frame/inlines/inlines.c Wed Jul 13 17:34:29 2011 @@ -43,9 +43,9 @@ int (*func_ptr) (int); func_ptr = outer_inline; - outer_inline (argc); + outer_inline (argc); // This should correspond to the first break stop. - func_ptr (argc); + func_ptr (argc); // This should correspond to the second break stop. return 0; } From johnny.chen at apple.com Wed Jul 13 18:17:13 2011 From: johnny.chen at apple.com (Johnny Chen) Date: Wed, 13 Jul 2011 23:17:13 -0000 Subject: [Lldb-commits] [lldb] r135105 - /lldb/trunk/include/lldb/API/SBModule.h Message-ID: <20110713231713.A8E772A6C12C@llvm.org> Author: johnny Date: Wed Jul 13 18:17:13 2011 New Revision: 135105 URL: http://llvm.org/viewvc/llvm-project?rev=135105&view=rev Log: Use %feature("docstring") for methods of SBModule class so that the methods signature also gets generated in the Python docstring. Modified: lldb/trunk/include/lldb/API/SBModule.h Modified: lldb/trunk/include/lldb/API/SBModule.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/API/SBModule.h?rev=135105&r1=135104&r2=135105&view=diff ============================================================================== --- lldb/trunk/include/lldb/API/SBModule.h (original) +++ lldb/trunk/include/lldb/API/SBModule.h Wed Jul 13 18:17:13 2011 @@ -49,7 +49,7 @@ IsValid () const; #ifdef SWIG - %feature("autodoc", " + %feature("docstring", " #endif //------------------------------------------------------------------ /// Get const accessor for the module file specification. @@ -68,7 +68,7 @@ GetFileSpec () const; #ifdef SWIG - %feature("autodoc", " + %feature("docstring", " #endif //------------------------------------------------------------------ /// Get accessor for the module platform file specification. @@ -100,7 +100,7 @@ #endif #ifdef SWIG - %feature("autodoc", + %feature("docstring", "Returns the UUID of the module as a Python string." ) GetUUIDString; #endif @@ -134,7 +134,7 @@ GetSymbolAtIndex (size_t idx); #ifdef SWIG - %feature("autodoc", " + %feature("docstring", " #endif //------------------------------------------------------------------ /// Find functions by name. @@ -170,7 +170,7 @@ lldb::SBSymbolContextList& sc_list); #ifdef SWIG - %feature("autodoc", " + %feature("docstring", " #endif //------------------------------------------------------------------ /// Find global and static variables by name. From johnny.chen at apple.com Wed Jul 13 18:35:34 2011 From: johnny.chen at apple.com (Johnny Chen) Date: Wed, 13 Jul 2011 23:35:34 -0000 Subject: [Lldb-commits] [lldb] r135108 - /lldb/trunk/include/lldb/API/SBTarget.h Message-ID: <20110713233534.1E53C2A6C12C@llvm.org> Author: johnny Date: Wed Jul 13 18:35:33 2011 New Revision: 135108 URL: http://llvm.org/viewvc/llvm-project?rev=135108&view=rev Log: Add some more docstrings for SBTarget. Modified: lldb/trunk/include/lldb/API/SBTarget.h Modified: lldb/trunk/include/lldb/API/SBTarget.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/API/SBTarget.h?rev=135108&r1=135107&r2=135108&view=diff ============================================================================== --- lldb/trunk/include/lldb/API/SBTarget.h (original) +++ lldb/trunk/include/lldb/API/SBTarget.h Wed Jul 13 18:35:33 2011 @@ -175,7 +175,7 @@ const char *working_directory); #ifdef SWIG - %feature("autodoc", " + %feature("docstring", " #endif //------------------------------------------------------------------ /// Attach to process with pid. @@ -204,7 +204,7 @@ lldb::SBError& error); #ifdef SWIG - %feature("autodoc", " + %feature("docstring", " #endif //------------------------------------------------------------------ /// Attach to process with name. @@ -237,7 +237,7 @@ lldb::SBError& error); #ifdef SWIG - %feature("autodoc", " + %feature("docstring", " #endif //------------------------------------------------------------------ /// Attach to process with name. @@ -284,6 +284,36 @@ lldb::SBModule FindModule (const lldb::SBFileSpec &file_spec); +#ifdef SWIG + %feature("docstring", " +#endif + //------------------------------------------------------------------ + /// Find functions by name. + /// + /// @param[in] name + /// The name of the function we are looking for. + /// + /// @param[in] name_type_mask + /// A logical OR of one or more FunctionNameType enum bits that + /// indicate what kind of names should be used when doing the + /// lookup. Bits include fully qualified names, base names, + /// C++ methods, or ObjC selectors. + /// See FunctionNameType for more details. + /// + /// @param[in] append + /// If true, any matches will be appended to \a sc_list, else + /// matches replace the contents of \a sc_list. + /// + /// @param[out] sc_list + /// A symbol context list that gets filled in with all of the + /// matches. + /// + /// @return + /// The number of matches added to \a sc_list. + //------------------------------------------------------------------ +#ifdef SWIG + ") FindFunctions; +#endif uint32_t FindFunctions (const char *name, uint32_t name_type_mask, // Logical OR one or more FunctionNameType enum bits @@ -291,7 +321,7 @@ lldb::SBSymbolContextList& sc_list); #ifdef SWIG - %feature("autodoc", " + %feature("docstring", " #endif //------------------------------------------------------------------ /// Find global and static variables by name. From johnny.chen at apple.com Wed Jul 13 19:17:49 2011 From: johnny.chen at apple.com (Johnny Chen) Date: Thu, 14 Jul 2011 00:17:49 -0000 Subject: [Lldb-commits] [lldb] r135114 - in /lldb/trunk: include/lldb/API/SBTarget.h scripts/Python/modify-python-lldb.py Message-ID: <20110714001749.9393A2A6C12C@llvm.org> Author: johnny Date: Wed Jul 13 19:17:49 2011 New Revision: 135114 URL: http://llvm.org/viewvc/llvm-project?rev=135114&view=rev Log: Add some more docstrings (includng example usages) to SBTarget.h. Add logic to modify-python-lldb to correct swig's transformation of 'char **argv' and 'char **envp' to 'char argv' and 'char envp' by morphing them into the 'list argv' and 'list envp' (as a list of Python strings). Modified: lldb/trunk/include/lldb/API/SBTarget.h lldb/trunk/scripts/Python/modify-python-lldb.py Modified: lldb/trunk/include/lldb/API/SBTarget.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/API/SBTarget.h?rev=135114&r1=135113&r2=135114&view=diff ============================================================================== --- lldb/trunk/include/lldb/API/SBTarget.h (original) +++ lldb/trunk/include/lldb/API/SBTarget.h Wed Jul 13 19:17:49 2011 @@ -63,7 +63,7 @@ GetProcess (); #ifdef SWIG - %feature("autodoc", " + %feature("docstring", " #endif //------------------------------------------------------------------ /// Launch a new process. @@ -122,6 +122,20 @@ /// A process object for the newly created process. //------------------------------------------------------------------ #ifdef SWIG + +For example, + + process = target.Launch(self.dbg.GetListener(), None, None, + None, '/tmp/stdout.txt', None, + None, 0, False, error) + +launches a new process by passing nothing for both the args and the envs +and redirect the standard output of the inferior to the /tmp/stdout.txt +file. It does not specify a working directory so that the debug server +will use its idea of what the current working directory is for the +inferior. Also, we ask the debugger not to stop the inferior at the +entry point. If no breakpoint is specified for the inferior, it should +run to completion if no user interaction is required. ") Launch; #endif lldb::SBProcess @@ -138,7 +152,7 @@ #ifdef SWIG - %feature("autodoc", " + %feature("docstring", " #endif //------------------------------------------------------------------ /// Launch a new process with sensible defaults. @@ -167,6 +181,13 @@ /// A process object for the newly created process. //------------------------------------------------------------------ #ifdef SWIG + +For example, + + process = target.LaunchSimple(['X', 'Y', 'Z'], None, os.getcwd()) + +launches a new process by passing 'X', 'Y', 'Z' as the args to the +executable. ") LaunchSimple; #endif lldb::SBProcess Modified: lldb/trunk/scripts/Python/modify-python-lldb.py URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/scripts/Python/modify-python-lldb.py?rev=135114&r1=135113&r2=135114&view=diff ============================================================================== --- lldb/trunk/scripts/Python/modify-python-lldb.py (original) +++ lldb/trunk/scripts/Python/modify-python-lldb.py Wed Jul 13 19:17:49 2011 @@ -47,6 +47,9 @@ """This transforms the 'char', i.e, 'char *' to 'str', Python string.""" line = line.replace(' char', ' str') line = line.replace('char ', 'str ') + # Special case handling of 'char **argv' and 'char **envp'. + line = line.replace('str argv', 'list argv') + line = line.replace('str envp', 'list envp') return line # From johnny.chen at apple.com Thu Jul 14 16:17:28 2011 From: johnny.chen at apple.com (Johnny Chen) Date: Thu, 14 Jul 2011 21:17:28 -0000 Subject: [Lldb-commits] [lldb] r135188 - /lldb/trunk/include/lldb/API/SBTarget.h Message-ID: <20110714211728.B7CBF2A6C12C@llvm.org> Author: johnny Date: Thu Jul 14 16:17:28 2011 New Revision: 135188 URL: http://llvm.org/viewvc/llvm-project?rev=135188&view=rev Log: Fix typo in ConnectRemote() docstring. Modified: lldb/trunk/include/lldb/API/SBTarget.h Modified: lldb/trunk/include/lldb/API/SBTarget.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/API/SBTarget.h?rev=135188&r1=135187&r2=135188&view=diff ============================================================================== --- lldb/trunk/include/lldb/API/SBTarget.h (original) +++ lldb/trunk/include/lldb/API/SBTarget.h Thu Jul 14 16:17:28 2011 @@ -261,7 +261,7 @@ %feature("docstring", " #endif //------------------------------------------------------------------ - /// Attach to process with name. + /// Connect to a remote debug server with url. /// /// @param[in] listener /// An optional listener that will receive all process events. From johnny.chen at apple.com Thu Jul 14 16:23:24 2011 From: johnny.chen at apple.com (Johnny Chen) Date: Thu, 14 Jul 2011 21:23:24 -0000 Subject: [Lldb-commits] [lldb] r135190 - /lldb/trunk/scripts/lldb.swig Message-ID: <20110714212324.4F0242A6C12C@llvm.org> Author: johnny Date: Thu Jul 14 16:23:24 2011 New Revision: 135190 URL: http://llvm.org/viewvc/llvm-project?rev=135190&view=rev Log: Minor wording change. Modified: lldb/trunk/scripts/lldb.swig Modified: lldb/trunk/scripts/lldb.swig URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/scripts/lldb.swig?rev=135190&r1=135189&r2=135190&view=diff ============================================================================== --- lldb/trunk/scripts/lldb.swig (original) +++ lldb/trunk/scripts/lldb.swig Thu Jul 14 16:23:24 2011 @@ -21,7 +21,7 @@ o SBValue: Represents the value of a variable, a register, or an expression. o SBModule: Represents an executable image and its associated object and symbol files. -o SBSymbol: Represents the symbol associated with a stack frame. +o SBSymbol: Represents the symbol possibly associated with a stack frame. o SBCompileUnit: Represents a compilation unit, or compiled source file. o SBFunction: Represents a generic function, which can be inlined or not. o SBBlock: Represents a lexical block. SBFunction contains SBBlock(s). From johnny.chen at apple.com Thu Jul 14 16:32:11 2011 From: johnny.chen at apple.com (Johnny Chen) Date: Thu, 14 Jul 2011 21:32:11 -0000 Subject: [Lldb-commits] [lldb] r135194 - /lldb/trunk/scripts/lldb.swig Message-ID: <20110714213211.6A72A2A6C12C@llvm.org> Author: johnny Date: Thu Jul 14 16:32:11 2011 New Revision: 135194 URL: http://llvm.org/viewvc/llvm-project?rev=135194&view=rev Log: Add summary info for SBBreakpoint to the lldb module level docstring. Modified: lldb/trunk/scripts/lldb.swig Modified: lldb/trunk/scripts/lldb.swig URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/scripts/lldb.swig?rev=135194&r1=135193&r2=135194&view=diff ============================================================================== --- lldb/trunk/scripts/lldb.swig (original) +++ lldb/trunk/scripts/lldb.swig Thu Jul 14 16:32:11 2011 @@ -20,7 +20,9 @@ o SBSymbolContext: A container that stores various debugger related info. o SBValue: Represents the value of a variable, a register, or an expression. o SBModule: Represents an executable image and its associated object and symbol - files. + files. SBTarget conatins SBModule(s). +o SBBreakpoint: Represents a logical breakpoint and its associated settings. + SBTarget conatins SBBreakpoint(s). o SBSymbol: Represents the symbol possibly associated with a stack frame. o SBCompileUnit: Represents a compilation unit, or compiled source file. o SBFunction: Represents a generic function, which can be inlined or not. From johnny.chen at apple.com Thu Jul 14 17:20:12 2011 From: johnny.chen at apple.com (Johnny Chen) Date: Thu, 14 Jul 2011 22:20:12 -0000 Subject: [Lldb-commits] [lldb] r135206 - in /lldb/trunk: source/Interpreter/CommandObject.cpp test/help/TestHelp.py Message-ID: <20110714222012.A71A12A6C12C@llvm.org> Author: johnny Date: Thu Jul 14 17:20:12 2011 New Revision: 135206 URL: http://llvm.org/viewvc/llvm-project?rev=135206&view=rev Log: Fixed a crasher where entering 'help disasm' on the command line would crash lldb. The reasom of the crash is because of a missing entry in the argument table corresponding to eArgTypeUnsignedInteger. Add such entry and modify the call site of the crash to go through a fail-fast API to retrieve the argument table. Add a regression test to TestHelp.py. Modified: lldb/trunk/source/Interpreter/CommandObject.cpp lldb/trunk/test/help/TestHelp.py Modified: lldb/trunk/source/Interpreter/CommandObject.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/CommandObject.cpp?rev=135206&r1=135205&r2=135206&view=diff ============================================================================== --- lldb/trunk/source/Interpreter/CommandObject.cpp (original) +++ lldb/trunk/source/Interpreter/CommandObject.cpp Thu Jul 14 17:20:12 2011 @@ -623,8 +623,9 @@ && arg_name[len-1] == '>') arg_name_str = arg_name_str.substr (1, len-2); + const ArgumentTableEntry *table = GetArgumentTable(); for (int i = 0; i < eArgTypeLastArg; ++i) - if (arg_name_str.compare (g_arguments_data[i].arg_name) == 0) + if (arg_name_str.compare (table[i].arg_name) == 0) return_type = g_arguments_data[i].arg_type; return return_type; @@ -778,6 +779,7 @@ { eArgTypeThreadID, "thread-id", CommandCompletions::eNoCompletion, { NULL, false }, "Thread ID number." }, { eArgTypeThreadIndex, "thread-index", CommandCompletions::eNoCompletion, { NULL, false }, "Index into the process' list of threads." }, { eArgTypeThreadName, "thread-name", CommandCompletions::eNoCompletion, { NULL, false }, "The thread's name." }, + { eArgTypeUnsignedInteger, "unsigned-integer", CommandCompletions::eNoCompletion, { NULL, false }, "An unsigned integer." }, { eArgTypeUnixSignal, "unix-signal", CommandCompletions::eNoCompletion, { NULL, false }, "A valid Unix signal name or number (e.g. SIGKILL, KILL or 9)." }, { eArgTypeVarName, "variable-name", CommandCompletions::eNoCompletion, { NULL, false }, "The name of a variable in your program." }, { eArgTypeValue, "value", CommandCompletions::eNoCompletion, { NULL, false }, "A value could be anything, depending on where and how it is used." }, Modified: lldb/trunk/test/help/TestHelp.py URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/help/TestHelp.py?rev=135206&r1=135205&r2=135206&view=diff ============================================================================== --- lldb/trunk/test/help/TestHelp.py (original) +++ lldb/trunk/test/help/TestHelp.py Thu Jul 14 17:20:12 2011 @@ -61,6 +61,11 @@ self.expect("version", patterns = ['LLDB-' + (version_str if version_str else '[0-9]+')]) + def test_help_should_not_crash_lldb(self): + """Command 'help disasm' should not crash lldb.""" + self.runCmd("help disasm", check=False) + self.runCmd("help unsigned-integer") + def test_help_should_not_hang_emacsshell(self): """Command 'settings set term-width 0' should not hang the help command.""" self.runCmd("settings set term-width 0") From johnny.chen at apple.com Thu Jul 14 18:33:34 2011 From: johnny.chen at apple.com (Johnny Chen) Date: Thu, 14 Jul 2011 23:33:34 -0000 Subject: [Lldb-commits] [lldb] r135214 - /lldb/trunk/test/python_api/lldbutil/iter/TestLLDBIterator.py Message-ID: <20110714233334.DFCCB2A6C12C@llvm.org> Author: johnny Date: Thu Jul 14 18:33:34 2011 New Revision: 135214 URL: http://llvm.org/viewvc/llvm-project?rev=135214&view=rev Log: Minor change of variable name, from m to b (for breakpoint). Modified: lldb/trunk/test/python_api/lldbutil/iter/TestLLDBIterator.py Modified: lldb/trunk/test/python_api/lldbutil/iter/TestLLDBIterator.py URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/python_api/lldbutil/iter/TestLLDBIterator.py?rev=135214&r1=135213&r2=135214&view=diff ============================================================================== --- lldb/trunk/test/python_api/lldbutil/iter/TestLLDBIterator.py (original) +++ lldb/trunk/test/python_api/lldbutil/iter/TestLLDBIterator.py Thu Jul 14 18:33:34 2011 @@ -83,8 +83,8 @@ for i in range(target.GetNumBreakpoints()): yours.append(target.GetBreakpointAtIndex(i)) mine = [] - for m in target.breakpoint_iter(): - mine.append(m) + for b in target.breakpoint_iter(): + mine.append(b) self.assertTrue(len(yours) == len(mine)) for i in range(len(yours)): From johnny.chen at apple.com Thu Jul 14 18:56:51 2011 From: johnny.chen at apple.com (Johnny Chen) Date: Thu, 14 Jul 2011 23:56:51 -0000 Subject: [Lldb-commits] [lldb] r135221 - in /lldb/trunk/include/lldb/API: SBProcess.h SBTarget.h SBThread.h Message-ID: <20110714235651.466E52A6C12C@llvm.org> Author: johnny Date: Thu Jul 14 18:56:51 2011 New Revision: 135221 URL: http://llvm.org/viewvc/llvm-project?rev=135221&view=rev Log: Add usage docstrings to SBTarget, SBProcess, and SBThread. Modified: lldb/trunk/include/lldb/API/SBProcess.h lldb/trunk/include/lldb/API/SBTarget.h lldb/trunk/include/lldb/API/SBThread.h Modified: lldb/trunk/include/lldb/API/SBProcess.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/API/SBProcess.h?rev=135221&r1=135220&r2=135221&view=diff ============================================================================== --- lldb/trunk/include/lldb/API/SBProcess.h (original) +++ lldb/trunk/include/lldb/API/SBProcess.h Thu Jul 14 18:56:51 2011 @@ -21,7 +21,27 @@ #ifdef SWIG %feature("docstring", - "Represents the process associated with the target program." +"Represents the process associated with the target program. + +SBProcess supports thread iteration. For example (from test/lldbutil.py), + +# ================================================== +# Utility functions related to Threads and Processes +# ================================================== + +def get_stopped_threads(process, reason): + '''Returns the thread(s) with the specified stop reason in a list. + + The list can be empty if no such thread exists. + ''' + threads = [] + for t in process: + if t.GetStopReason() == reason: + threads.append(t) + return threads + +... +" ) SBProcess; #endif class SBProcess Modified: lldb/trunk/include/lldb/API/SBTarget.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/API/SBTarget.h?rev=135221&r1=135220&r2=135221&view=diff ============================================================================== --- lldb/trunk/include/lldb/API/SBTarget.h (original) +++ lldb/trunk/include/lldb/API/SBTarget.h Thu Jul 14 18:56:51 2011 @@ -20,7 +20,32 @@ #ifdef SWIG %feature("docstring", - "Represents the target program running under the debugger." +"Represents the target program running under the debugger. + +SBTarget supports module and breakpoint iterations. For example, + + for m in target.module_iter(): + print m + +produces: + +(x86_64) /Volumes/data/lldb/svn/trunk/test/python_api/lldbutil/iter/a.out +(x86_64) /usr/lib/dyld +(x86_64) /usr/lib/libstdc++.6.dylib +(x86_64) /usr/lib/libSystem.B.dylib +(x86_64) /usr/lib/system/libmathCommon.A.dylib +(x86_64) /usr/lib/libSystem.B.dylib(__commpage) + +and, + + for b in target.breakpoint_iter(): + print b + +produces: + +SBBreakpoint: id = 1, file ='main.cpp', line = 66, locations = 1 +SBBreakpoint: id = 2, file ='main.cpp', line = 85, locations = 1 +" ) SBTarget; #endif class SBTarget Modified: lldb/trunk/include/lldb/API/SBThread.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/API/SBThread.h?rev=135221&r1=135220&r2=135221&view=diff ============================================================================== --- lldb/trunk/include/lldb/API/SBThread.h (original) +++ lldb/trunk/include/lldb/API/SBThread.h Thu Jul 14 18:56:51 2011 @@ -22,24 +22,25 @@ %feature("docstring", "Represents a thread of execution. SBProcess contains SBThread(s). -For example (from test/lldbutil.py), +SBThread supports frame iteration. For example (from test/python_api/ +lldbutil/iter/TestLLDBIterator.py), -# ================================================== -# Utility functions related to Threads and Processes -# ================================================== - -def get_stopped_threads(process, reason): - '''Returns the thread(s) with the specified stop reason in a list. - - The list can be empty if no such thread exists. - ''' - threads = [] - for t in process: - if t.GetStopReason() == reason: - threads.append(t) - return threads + from lldbutil import print_stacktrace + stopped_due_to_breakpoint = False + for thread in process: + if self.TraceOn(): + print_stacktrace(thread) + ID = thread.GetThreadID() + if thread.GetStopReason() == lldb.eStopReasonBreakpoint: + stopped_due_to_breakpoint = True + for frame in thread: + self.assertTrue(frame.GetThread().GetThreadID() == ID) + if self.TraceOn(): + print frame -... + self.assertTrue(stopped_due_to_breakpoint) + +See also SBProcess and SBFrame. " ) SBThread; #endif From johnny.chen at apple.com Thu Jul 14 19:27:47 2011 From: johnny.chen at apple.com (Johnny Chen) Date: Fri, 15 Jul 2011 00:27:47 -0000 Subject: [Lldb-commits] [lldb] r135230 - in /lldb/trunk: examples/python/disasm.py include/lldb/API/SBValue.h include/lldb/API/SBValueList.h Message-ID: <20110715002747.5BA4E2A6C12C@llvm.org> Author: johnny Date: Thu Jul 14 19:27:47 2011 New Revision: 135230 URL: http://llvm.org/viewvc/llvm-project?rev=135230&view=rev Log: Add usage docstring to SBValue.h, and minor update of docstrings for SBValueList.h. Modified: lldb/trunk/examples/python/disasm.py lldb/trunk/include/lldb/API/SBValue.h lldb/trunk/include/lldb/API/SBValueList.h Modified: lldb/trunk/examples/python/disasm.py URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/examples/python/disasm.py?rev=135230&r1=135229&r2=135230&view=diff ============================================================================== --- lldb/trunk/examples/python/disasm.py (original) +++ lldb/trunk/examples/python/disasm.py Thu Jul 14 19:27:47 2011 @@ -95,7 +95,7 @@ #print value print "%s (number of children = %d):" % (value.GetName(), value.GetNumChildren()) for child in value: - print "Name: ", child.GetName(), " Value: ", child.GetValue(frame) + print "Name: ", child.GetName(), " Value: ", child.GetValue() print "Hit the breakpoint at main, enter to continue and wait for program to exit or 'Ctrl-D'/'quit' to terminate the program" next = sys.stdin.readline() Modified: lldb/trunk/include/lldb/API/SBValue.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/API/SBValue.h?rev=135230&r1=135229&r2=135230&view=diff ============================================================================== --- lldb/trunk/include/lldb/API/SBValue.h (original) +++ lldb/trunk/include/lldb/API/SBValue.h Thu Jul 14 19:27:47 2011 @@ -18,7 +18,47 @@ #ifdef SWIG %feature("docstring", - "Represents the value of a variable, a register, or an expression." +"Represents the value of a variable, a register, or an expression. + +SBValue supports iteration through its child, which in turn is represented +as an SBValue. For example, we can get the general purpose registers of a +frame as an SBValue, and iterate through all the registers, + + registerSet = frame.GetRegisters() # Returns an SBValueList. + for regs in registerSet: + if 'general purpose registers' in regs.getName().lower(): + GPRs = regs + break + + print '%s (number of children = %d):' % (GPRs.GetName(), GPRs.GetNumChildren()) + for reg in GPRs: + print 'Name: ', reg.GetName(), ' Value: ', reg.GetValue() + +produces the output: + +General Purpose Registers (number of children = 21): +Name: rax Value: 0x0000000100000c5c +Name: rbx Value: 0x0000000000000000 +Name: rcx Value: 0x00007fff5fbffec0 +Name: rdx Value: 0x00007fff5fbffeb8 +Name: rdi Value: 0x0000000000000001 +Name: rsi Value: 0x00007fff5fbffea8 +Name: rbp Value: 0x00007fff5fbffe80 +Name: rsp Value: 0x00007fff5fbffe60 +Name: r8 Value: 0x0000000008668682 +Name: r9 Value: 0x0000000000000000 +Name: r10 Value: 0x0000000000001200 +Name: r11 Value: 0x0000000000000206 +Name: r12 Value: 0x0000000000000000 +Name: r13 Value: 0x0000000000000000 +Name: r14 Value: 0x0000000000000000 +Name: r15 Value: 0x0000000000000000 +Name: rip Value: 0x0000000100000dae +Name: rflags Value: 0x0000000000000206 +Name: cs Value: 0x0000000000000027 +Name: fs Value: 0x0000000000000010 +Name: gs Value: 0x0000000000000048 +" ) SBValue; #endif class SBValue Modified: lldb/trunk/include/lldb/API/SBValueList.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/API/SBValueList.h?rev=135230&r1=135229&r2=135230&view=diff ============================================================================== --- lldb/trunk/include/lldb/API/SBValueList.h (original) +++ lldb/trunk/include/lldb/API/SBValueList.h Thu Jul 14 19:27:47 2011 @@ -19,7 +19,7 @@ "Represents a collection of SBValues. Both SBFrame's GetVariables() and GetRegisters() return a SBValueList. -For example (from test/lldbutil.py), +SBValueList supports SBValue iteration. For example (from test/lldbutil.py), def get_registers(frame, kind): '''Returns the registers given the frame and the kind of registers desired. From granata.enrico at gmail.com Thu Jul 14 21:26:42 2011 From: granata.enrico at gmail.com (Enrico Granata) Date: Fri, 15 Jul 2011 02:26:42 -0000 Subject: [Lldb-commits] [lldb] r135238 - in /lldb/trunk: include/lldb/ include/lldb/API/ include/lldb/Core/ include/lldb/Interpreter/ include/lldb/Utility/ lldb.xcodeproj/ scripts/ source/API/ source/Commands/ source/Core/ source/Interpreter/ source/Plugins/Process/gdb-remote/ test/functionalities/data-formatter/data-formatter-script/ www/ Message-ID: <20110715022642.A25C12A6C12C@llvm.org> Author: enrico Date: Thu Jul 14 21:26:42 2011 New Revision: 135238 URL: http://llvm.org/viewvc/llvm-project?rev=135238&view=rev Log: Python summary strings: - you can use a Python script to write a summary string for data-types, in one of three ways: -P option and typing the script a line at a time -s option and passing a one-line Python script -F option and passing the name of a Python function these options all work for the "type summary add" command your Python code (if provided through -P or -s) is wrapped in a function that accepts two parameters: valobj (a ValueObject) and dict (an LLDB internal dictionary object). if you use -F and give a function name, you're expected to define the function on your own and with the right prototype. your function, however defined, must return a Python string - test case for the Python summary feature - a few quirks: Python summaries cannot have names, and cannot use regex as type names both issues will be fixed ASAP major redesign of type summary code: - type summary working with strings and type summary working with Python code are two classes, with a common base class SummaryFormat - SummaryFormat classes now are able to actively format objects rather than just aggregating data - cleaner code to print descriptions for summaries the public API now exports a method to easily navigate a ValueObject hierarchy New InputReaderEZ and PriorityPointerPair classes Several minor fixes and improvements Added: lldb/trunk/include/lldb/Core/InputReaderEZ.h lldb/trunk/include/lldb/Utility/PriorityPointerPair.h lldb/trunk/source/Core/InputReaderEZ.cpp lldb/trunk/test/functionalities/data-formatter/data-formatter-script/ lldb/trunk/test/functionalities/data-formatter/data-formatter-script/Makefile lldb/trunk/test/functionalities/data-formatter/data-formatter-script/TestDataFormatterScript.py lldb/trunk/test/functionalities/data-formatter/data-formatter-script/main.cpp Modified: lldb/trunk/include/lldb/API/SBValue.h lldb/trunk/include/lldb/Core/Debugger.h lldb/trunk/include/lldb/Core/Error.h lldb/trunk/include/lldb/Core/FormatManager.h lldb/trunk/include/lldb/Core/InputReader.h lldb/trunk/include/lldb/Core/StringList.h lldb/trunk/include/lldb/Core/ValueObject.h lldb/trunk/include/lldb/Interpreter/ScriptInterpreter.h lldb/trunk/include/lldb/Interpreter/ScriptInterpreterPython.h lldb/trunk/include/lldb/Utility/RefCounter.h lldb/trunk/include/lldb/lldb-forward-rtti.h lldb/trunk/include/lldb/lldb-forward.h lldb/trunk/lldb.xcodeproj/project.pbxproj lldb/trunk/scripts/lldb.swig lldb/trunk/source/API/SBCommandInterpreter.cpp lldb/trunk/source/API/SBValue.cpp lldb/trunk/source/Commands/CommandObjectType.cpp lldb/trunk/source/Core/Debugger.cpp lldb/trunk/source/Core/Error.cpp lldb/trunk/source/Core/FormatManager.cpp lldb/trunk/source/Core/InputReader.cpp lldb/trunk/source/Core/StringList.cpp lldb/trunk/source/Core/ValueObject.cpp lldb/trunk/source/Interpreter/ScriptInterpreter.cpp lldb/trunk/source/Interpreter/ScriptInterpreterPython.cpp lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp lldb/trunk/www/varformats.html Modified: lldb/trunk/include/lldb/API/SBValue.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/API/SBValue.h?rev=135238&r1=135237&r2=135238&view=diff ============================================================================== --- lldb/trunk/include/lldb/API/SBValue.h (original) +++ lldb/trunk/include/lldb/API/SBValue.h Thu Jul 14 21:26:42 2011 @@ -167,6 +167,10 @@ // classes. lldb::SBValue GetChildMemberWithName (const char *name, lldb::DynamicValueType use_dynamic); + + // Expands nested expressions like .a->b[0].c[1]->d + lldb::SBValue + GetValueForExpressionPath(const char* expr_path); uint32_t GetNumChildren (); @@ -190,12 +194,12 @@ bool GetExpressionPath (lldb::SBStream &description, bool qualify_cxx_base_classes); + SBValue (const lldb::ValueObjectSP &value_sp); + protected: friend class SBValueList; friend class SBFrame; - SBValue (const lldb::ValueObjectSP &value_sp); - #ifndef SWIG // Mimic shared pointer... Modified: lldb/trunk/include/lldb/Core/Debugger.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/Debugger.h?rev=135238&r1=135237&r2=135238&view=diff ============================================================================== --- lldb/trunk/include/lldb/Core/Debugger.h (original) +++ lldb/trunk/include/lldb/Core/Debugger.h Thu Jul 14 21:26:42 2011 @@ -576,8 +576,6 @@ static uint32_t GetCount(); }; - - }; } // namespace lldb_private Modified: lldb/trunk/include/lldb/Core/Error.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/Error.h?rev=135238&r1=135237&r2=135238&view=diff ============================================================================== --- lldb/trunk/include/lldb/Core/Error.h (original) +++ lldb/trunk/include/lldb/Core/Error.h Thu Jul 14 21:26:42 2011 @@ -69,6 +69,9 @@ explicit Error (ValueType err, lldb::ErrorType type = lldb::eErrorTypeGeneric); + explicit + Error (const char* err_str); + Error (const Error &rhs); //------------------------------------------------------------------ /// Assignment operator. Modified: lldb/trunk/include/lldb/Core/FormatManager.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/FormatManager.h?rev=135238&r1=135237&r2=135238&view=diff ============================================================================== --- lldb/trunk/include/lldb/Core/FormatManager.h (original) +++ lldb/trunk/include/lldb/Core/FormatManager.h Thu Jul 14 21:26:42 2011 @@ -50,8 +50,10 @@ #include "lldb/Core/UserID.h" #include "lldb/Core/UserSettingsController.h" #include "lldb/Core/ValueObject.h" +#include "lldb/Interpreter/ScriptInterpreterPython.h" #include "lldb/Target/ExecutionContext.h" #include "lldb/Target/Platform.h" +#include "lldb/Target/StackFrame.h" #include "lldb/Target/TargetList.h" namespace lldb_private { @@ -67,8 +69,263 @@ }; +struct ValueFormat +{ + bool m_cascades; + bool m_skip_pointers; + bool m_skip_references; + lldb::Format m_format; + ValueFormat (lldb::Format f = lldb::eFormatInvalid, + bool casc = false, + bool skipptr = false, + bool skipref = false) : + m_cascades(casc), + m_skip_pointers(skipptr), + m_skip_references(skipref), + m_format (f) + { + } + + typedef lldb::SharedPtr::Type SharedPointer; + typedef bool(*ValueCallback)(void*, const char*, const ValueFormat::SharedPointer&); + + ~ValueFormat() + { + } + + bool + Cascades() + { + return m_cascades; + } + bool + SkipsPointers() + { + return m_skip_pointers; + } + bool + SkipsReferences() + { + return m_skip_references; + } + + lldb::Format + GetFormat() + { + return m_format; + } + + std::string + FormatObject(lldb::ValueObjectSP object) + { + if (!object.get()) + return "NULL"; + + StreamString sstr; + + if (ClangASTType::DumpTypeValue (object->GetClangAST(), // The clang AST + object->GetClangType(), // The clang type to display + &sstr, + m_format, // Format to display this type with + object->GetDataExtractor(), // Data to extract from + 0, // Byte offset into "data" + object->GetByteSize(), // Byte size of item in "data" + object->GetBitfieldBitSize(), // Bitfield bit size + object->GetBitfieldBitOffset())) // Bitfield bit offset + return (sstr.GetString()); + else + { + return ("unsufficient data for value"); + } + + } + +}; + struct SummaryFormat { + bool m_cascades; + bool m_skip_pointers; + bool m_skip_references; + bool m_dont_show_children; + bool m_dont_show_value; + bool m_show_members_oneliner; + + SummaryFormat(bool casc = false, + bool skipptr = false, + bool skipref = false, + bool nochildren = true, + bool novalue = true, + bool oneliner = false) : + m_cascades(casc), + m_skip_pointers(skipptr), + m_skip_references(skipref), + m_dont_show_children(nochildren), + m_dont_show_value(novalue), + m_show_members_oneliner(oneliner) + { + } + + bool + Cascades() + { + return m_cascades; + } + bool + SkipsPointers() + { + return m_skip_pointers; + } + bool + SkipsReferences() + { + return m_skip_references; + } + + bool + DoesPrintChildren() const + { + return !m_dont_show_children; + } + + bool + DoesPrintValue() const + { + return !m_dont_show_value; + } + + bool + IsOneliner() const + { + return m_show_members_oneliner; + } + + virtual + ~SummaryFormat() + { + } + + virtual std::string + FormatObject(lldb::ValueObjectSP object) = 0; + + virtual std::string + GetDescription() = 0; + + typedef lldb::SharedPtr::Type SharedPointer; + typedef bool(*SummaryCallback)(void*, const char*, const SummaryFormat::SharedPointer&); + typedef bool(*RegexSummaryCallback)(void*, lldb::RegularExpressionSP, const SummaryFormat::SharedPointer&); + +}; + +// simple string-based summaries, using ${var to show data +struct StringSummaryFormat : public SummaryFormat +{ + std::string m_format; + + StringSummaryFormat(bool casc = false, + bool skipptr = false, + bool skipref = false, + bool nochildren = true, + bool novalue = true, + bool oneliner = false, + std::string f = "") : + SummaryFormat(casc,skipptr,skipref,nochildren,novalue,oneliner), + m_format(f) + { + } + + std::string + GetFormat() + { + return m_format; + } + + virtual + ~StringSummaryFormat() + { + } + + virtual std::string + FormatObject(lldb::ValueObjectSP object); + + virtual std::string + GetDescription() + { + StreamString sstr; + sstr.Printf ("`%s`%s%s%s%s%s%s\n", m_format.c_str(), + m_cascades ? "" : " (not cascading)", + m_dont_show_children ? "" : " (show children)", + m_dont_show_value ? " (hide value)" : "", + m_show_members_oneliner ? " (one-line printout)" : "", + m_skip_pointers ? " (skip pointers)" : "", + m_skip_references ? " (skip references)" : ""); + return sstr.GetString(); + } + +}; + +// Python-based summaries, running script code to show data +struct ScriptSummaryFormat : public SummaryFormat +{ + std::string m_function_name; + std::string m_python_script; + + ScriptSummaryFormat(bool casc = false, + bool skipptr = false, + bool skipref = false, + bool nochildren = true, + bool novalue = true, + bool oneliner = false, + std::string fname = "", + std::string pscri = "") : + SummaryFormat(casc,skipptr,skipref,nochildren,novalue,oneliner), + m_function_name(fname), + m_python_script(pscri) + { + } + + std::string + GetFunctionName() + { + return m_function_name; + } + + std::string + GetPythonScript() + { + return m_python_script; + } + + virtual + ~ScriptSummaryFormat() + { + } + + virtual std::string + FormatObject(lldb::ValueObjectSP object) + { + return std::string(ScriptInterpreterPython::CallPythonScriptFunction(m_function_name.c_str(), + object).c_str()); + } + + virtual std::string + GetDescription() + { + StreamString sstr; + sstr.Printf ("%s%s%s\n%s\n", m_cascades ? "" : " (not cascading)", + m_skip_pointers ? " (skip pointers)" : "", + m_skip_references ? " (skip references)" : "", + m_python_script.c_str()); + return sstr.GetString(); + + } + + typedef lldb::SharedPtr::Type SharedPointer; + +}; + +/*struct SummaryFormat +{ std::string m_format; bool m_dont_show_children; bool m_dont_show_value; @@ -116,32 +373,35 @@ typedef bool(*RegexSummaryCallback)(void*, lldb::RegularExpressionSP, const SummaryFormat::SharedPointer&); }; - -struct ValueFormat + +struct ScriptFormat { - lldb::Format m_format; + std::string m_function_name; + std::string m_python_script; bool m_cascades; bool m_skip_references; bool m_skip_pointers; - ValueFormat (lldb::Format f = lldb::eFormatInvalid, - bool c = false, - bool skipptr = false, - bool skipref = false) : - m_format (f), + ScriptFormat (std::string n, + std::string s = "", + bool c = false, + bool skipptr = false, + bool skipref = false) : + m_function_name (n), + m_python_script(s), m_cascades (c), m_skip_references(skipref), m_skip_pointers(skipptr) { } - typedef lldb::SharedPtr::Type SharedPointer; - typedef bool(*ValueCallback)(void*, const char*, const ValueFormat::SharedPointer&); + typedef lldb::SharedPtr::Type SharedPointer; + typedef bool(*ScriptCallback)(void*, const char*, const ScriptFormat::SharedPointer&); - ~ValueFormat() + ~ScriptFormat() { } -}; +};*/ template class FormatNavigator; @@ -457,11 +717,13 @@ typedef FormatNavigator ValueNavigator; typedef FormatNavigator SummaryNavigator; typedef FormatNavigator RegexSummaryNavigator; + typedef FormatNavigator ScriptNavigator; typedef ValueNavigator::MapType ValueMap; typedef SummaryNavigator::MapType SummaryMap; typedef RegexSummaryNavigator::MapType RegexSummaryMap; typedef FormatMap NamedSummariesMap; + typedef ScriptNavigator::MapType ScriptMap; ValueNavigator m_value_nav; SummaryNavigator m_summary_nav; @@ -469,6 +731,8 @@ NamedSummariesMap m_named_summaries_map; + ScriptNavigator m_script_nav; + uint32_t m_last_revision; public: @@ -478,6 +742,7 @@ m_summary_nav(this), m_regex_summary_nav(this), m_named_summaries_map(this), + m_script_nav(this), m_last_revision(0) { } @@ -487,6 +752,7 @@ SummaryNavigator& Summary() { return m_summary_nav; } RegexSummaryNavigator& RegexSummary() { return m_regex_summary_nav; } NamedSummariesMap& NamedSummary() { return m_named_summaries_map; } + ScriptNavigator& Script() { return m_script_nav; } static bool GetFormatFromCString (const char *format_cstr, Modified: lldb/trunk/include/lldb/Core/InputReader.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/InputReader.h?rev=135238&r1=135237&r2=135238&view=diff ============================================================================== --- lldb/trunk/include/lldb/Core/InputReader.h (original) +++ lldb/trunk/include/lldb/Core/InputReader.h Thu Jul 14 21:26:42 2011 @@ -12,7 +12,7 @@ #include "lldb/lldb-public.h" #include "lldb/lldb-enumerations.h" -#include "lldb/Core/Debugger.h" +#include "lldb/Core/Error.h" #include "lldb/Host/Predicate.h" @@ -27,6 +27,31 @@ lldb::InputReaderAction notification, const char *bytes, size_t bytes_len); + + struct HandlerData + { + InputReader& reader; + const char *bytes; + size_t bytes_len; + void* baton; + + HandlerData(InputReader& r, + const char* b, + size_t l, + void* t) : + reader(r), + bytes(b), + bytes_len(l), + baton(t) + { + } + + lldb::StreamSP + GetOutStream(); + + bool + GetBatchMode(); + }; InputReader (Debugger &debugger); @@ -41,6 +66,41 @@ const char *prompt, bool echo); + virtual Error Initialize(void* baton, + lldb::InputReaderGranularity token_size = lldb::eInputReaderGranularityLine, + const char* end_token = "DONE", + const char *prompt = "> ", + bool echo = true) + { + return Error("unimplemented"); + } + + // to use these handlers instead of the Callback function, you must subclass + // InputReaderEZ, and redefine the handlers for the events you care about + virtual void + ActivateHandler(HandlerData&) {} + + virtual void + DeactivateHandler(HandlerData&) {} + + virtual void + ReactivateHandler(HandlerData&) {} + + virtual void + AsynchronousOutputWrittenHandler(HandlerData&) {} + + virtual void + GotTokenHandler(HandlerData&) {} + + virtual void + InterruptHandler(HandlerData&) {} + + virtual void + EOFHandler(HandlerData&) {} + + virtual void + DoneHandler(HandlerData&) {} + bool IsDone () const { Added: lldb/trunk/include/lldb/Core/InputReaderEZ.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/InputReaderEZ.h?rev=135238&view=auto ============================================================================== --- lldb/trunk/include/lldb/Core/InputReaderEZ.h (added) +++ lldb/trunk/include/lldb/Core/InputReaderEZ.h Thu Jul 14 21:26:42 2011 @@ -0,0 +1,81 @@ +//===-- InputReaderEZ.h -----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_InputReaderEZ_h_ +#define liblldb_InputReaderEZ_h_ + +#include "lldb/lldb-public.h" +#include "lldb/lldb-enumerations.h" +#include "lldb/Core/Debugger.h" +#include "lldb/Core/InputReader.h" +#include "lldb/Host/Predicate.h" + + +namespace lldb_private { + +class InputReaderEZ : public InputReader +{ + +private: + + static size_t Callback_Impl(void *baton, + InputReader &reader, + lldb::InputReaderAction notification, + const char *bytes, + size_t bytes_len); +public: + + InputReaderEZ (Debugger &debugger) : + InputReader(debugger) + {} + + virtual + ~InputReaderEZ (); + + virtual Error Initialize(void* baton, + lldb::InputReaderGranularity token_size = lldb::eInputReaderGranularityLine, + const char* end_token = "DONE", + const char *prompt = "> ", + bool echo = true); + + virtual void + ActivateHandler(HandlerData&) {} + + virtual void + DeactivateHandler(HandlerData&) {} + + virtual void + ReactivateHandler(HandlerData&) {} + + virtual void + AsynchronousOutputWrittenHandler(HandlerData&) {} + + virtual void + GotTokenHandler(HandlerData&) {} + + virtual void + InterruptHandler(HandlerData&) {} + + virtual void + EOFHandler(HandlerData&) {} + + virtual void + DoneHandler(HandlerData&) {} + +protected: + friend class Debugger; + +private: + DISALLOW_COPY_AND_ASSIGN (InputReaderEZ); + +}; + +} // namespace lldb_private + +#endif // #ifndef liblldb_InputReaderEZ_h_ Modified: lldb/trunk/include/lldb/Core/StringList.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/StringList.h?rev=135238&r1=135237&r2=135238&view=diff ============================================================================== --- lldb/trunk/include/lldb/Core/StringList.h (original) +++ lldb/trunk/include/lldb/Core/StringList.h Thu Jul 14 21:26:42 2011 @@ -68,7 +68,17 @@ size_t SplitIntoLines (const char *lines, size_t len); + + std::string + CopyList(const char* item_preamble = NULL, + const char* items_sep = "\n"); + + StringList& + operator << (const char* str); + StringList& + operator << (StringList strings); + private: STLStringArray m_strings; Modified: lldb/trunk/include/lldb/Core/ValueObject.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/ValueObject.h?rev=135238&r1=135237&r2=135238&view=diff ============================================================================== --- lldb/trunk/include/lldb/Core/ValueObject.h (original) +++ lldb/trunk/include/lldb/Core/ValueObject.h Thu Jul 14 21:26:42 2011 @@ -27,6 +27,7 @@ #include "lldb/Target/ExecutionContext.h" #include "lldb/Target/ExecutionContextScope.h" #include "lldb/Target/StackID.h" +#include "lldb/Utility/PriorityPointerPair.h" #include "lldb/Utility/SharedCluster.h" namespace lldb_private { @@ -75,7 +76,8 @@ { eDisplayValue = 1, eDisplaySummary, - eDisplayLanguageSpecific + eDisplayLanguageSpecific, + eDisplayLocation }; enum ExpressionPathScanEndReason @@ -731,8 +733,8 @@ lldb::Format m_format; uint32_t m_last_format_mgr_revision; lldb::SummaryFormatSP m_last_summary_format; - lldb::ValueFormatSP m_last_value_format; lldb::SummaryFormatSP m_forced_summary_format; + lldb::ValueFormatSP m_last_value_format; lldb::user_id_t m_user_id_of_forced_summary; bool m_value_is_valid:1, m_value_did_change:1, @@ -802,6 +804,9 @@ void SetValueIsValid (bool valid); + + void + ClearUserVisibleData(); public: lldb::addr_t Modified: lldb/trunk/include/lldb/Interpreter/ScriptInterpreter.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Interpreter/ScriptInterpreter.h?rev=135238&r1=135237&r2=135238&view=diff ============================================================================== --- lldb/trunk/include/lldb/Interpreter/ScriptInterpreter.h (original) +++ lldb/trunk/include/lldb/Interpreter/ScriptInterpreter.h Thu Jul 14 21:26:42 2011 @@ -26,6 +26,13 @@ const char *session_dictionary_name, const lldb::StackFrameSP& frame_sp, const lldb::BreakpointLocationSP &bp_loc_sp); + + typedef + + typedef std::string (*SWIGPythonTypeScriptCallbackFunction) (const char *python_function_name, + const char *session_dictionary_name, + const lldb::ValueObjectSP& valobj_sp); + typedef enum { eCharPtr, @@ -77,6 +84,25 @@ { return false; } + + virtual bool + GenerateTypeScriptFunction (StringList &input, StringList &output) + { + return false; + } + + // use this if the function code is just a one-liner script + virtual bool + GenerateTypeScriptFunction (const char* oneliner, StringList &output) + { + return false; + } + + virtual bool + GenerateFunction(std::string& signature, StringList &input, StringList &output) + { + return false; + } virtual void CollectDataForBreakpointCommandCallback (BreakpointOptions *bp_options, @@ -104,7 +130,8 @@ static void InitializeInterpreter (SWIGInitCallback python_swig_init_callback, - SWIGBreakpointCallbackFunction python_swig_breakpoint_callback); + SWIGBreakpointCallbackFunction python_swig_breakpoint_callback, + SWIGPythonTypeScriptCallbackFunction python_swig_typescript_callback); static void TerminateInterpreter (); Modified: lldb/trunk/include/lldb/Interpreter/ScriptInterpreterPython.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Interpreter/ScriptInterpreterPython.h?rev=135238&r1=135237&r2=135238&view=diff ============================================================================== --- lldb/trunk/include/lldb/Interpreter/ScriptInterpreterPython.h (original) +++ lldb/trunk/include/lldb/Interpreter/ScriptInterpreterPython.h Thu Jul 14 21:26:42 2011 @@ -50,6 +50,16 @@ ExportFunctionDefinitionToInterpreter (StringList &function_def); bool + GenerateTypeScriptFunction (StringList &input, StringList &output); + + // use this if the function code is just a one-liner script + bool + GenerateTypeScriptFunction (const char* oneliner, StringList &output); + + bool + GenerateFunction(std::string& signature, StringList &input, StringList &output); + + bool GenerateBreakpointCommandCallbackData (StringList &input, StringList &output); static size_t @@ -64,6 +74,10 @@ StoppointCallbackContext *context, lldb::user_id_t break_id, lldb::user_id_t break_loc_id); + + static std::string + CallPythonScriptFunction (const char *python_function_name, + lldb::ValueObjectSP valobj); void CollectDataForBreakpointCommandCallback (BreakpointOptions *bp_options, @@ -88,7 +102,8 @@ static void InitializeInterpreter (SWIGInitCallback python_swig_init_callback, - SWIGBreakpointCallbackFunction python_swig_breakpoint_callback); + SWIGBreakpointCallbackFunction python_swig_breakpoint_callback, + SWIGPythonTypeScriptCallbackFunction python_swig_typescript_callback); protected: Added: lldb/trunk/include/lldb/Utility/PriorityPointerPair.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Utility/PriorityPointerPair.h?rev=135238&view=auto ============================================================================== --- lldb/trunk/include/lldb/Utility/PriorityPointerPair.h (added) +++ lldb/trunk/include/lldb/Utility/PriorityPointerPair.h Thu Jul 14 21:26:42 2011 @@ -0,0 +1,150 @@ +//===-- PriorityPointerPair.h ----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_PriorityPointerPair_h_ +#define liblldb_PriorityPointerPair_h_ + +#include "lldb/lldb-public.h" +#include "lldb/Utility/SharingPtr.h" + +namespace lldb_utility { + +//---------------------------------------------------------------------- +// A prioritized pair of SharedPtr. One of the two pointers is high +// priority, the other is low priority. +// The Get() method always returns high, if *high != NULL, +// otherwise, low is returned (even if *low == NULL) +//---------------------------------------------------------------------- + +template +class PriorityPointerPair +{ +public: + + typedef T& reference_type; + typedef T* pointer_type; + + typedef typename lldb::SharedPtr::Type T_SP; + + PriorityPointerPair() : + m_high(), + m_low() + {} + + PriorityPointerPair(pointer_type high, + pointer_type low) : + m_high(high), + m_low(low) + {} + + PriorityPointerPair(pointer_type low) : + m_high(), + m_low(low) + {} + + PriorityPointerPair(T_SP& high, + T_SP& low) : + m_high(high), + m_low(low) + {} + + PriorityPointerPair(T_SP& low) : + m_high(), + m_low(low) + {} + + void + SwapLow(pointer_type l) + { + m_low.swap(l); + } + + void + SwapHigh(pointer_type h) + { + m_high.swap(h); + } + + void + SwapLow(T_SP l) + { + m_low.swap(l); + } + + void + SwapHigh(T_SP h) + { + m_high.swap(h); + } + + T_SP + GetLow() + { + return m_low; + } + + T_SP + GetHigh() + { + return m_high; + } + + T_SP + Get() + { + if (m_high.get()) + return m_high; + return m_low; + } + + void + ResetHigh() + { + m_high.reset(); + } + + void + ResetLow() + { + m_low.reset(); + } + + void + Reset() + { + ResetLow(); + ResetHigh(); + } + + reference_type + operator*() const + { + return Get().operator*(); + } + + pointer_type + operator->() const + { + return Get().operator->(); + } + + ~PriorityPointerPair(); + +private: + + T_SP m_high; + T_SP m_low; + + DISALLOW_COPY_AND_ASSIGN (PriorityPointerPair); + +}; + +} // namespace lldb_utility + +#endif // #ifndef liblldb_PriorityPointerPair_h_ Modified: lldb/trunk/include/lldb/Utility/RefCounter.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Utility/RefCounter.h?rev=135238&r1=135237&r2=135238&view=diff ============================================================================== --- lldb/trunk/include/lldb/Utility/RefCounter.h (original) +++ lldb/trunk/include/lldb/Utility/RefCounter.h Thu Jul 14 21:26:42 2011 @@ -20,8 +20,6 @@ // RefCounter ref(ptr); // (of course, the pointer is a shared resource, and must be accessible to // everyone who needs it). Synchronization is handled by RefCounter itself -// To check if more than 1 RefCounter is attached to the same value, you can -// either call shared(), or simply cast ref to bool // The counter is decreased each time a RefCounter to it goes out of scope //---------------------------------------------------------------------- class RefCounter Modified: lldb/trunk/include/lldb/lldb-forward-rtti.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/lldb-forward-rtti.h?rev=135238&r1=135237&r2=135238&view=diff ============================================================================== --- lldb/trunk/include/lldb/lldb-forward-rtti.h (original) +++ lldb/trunk/include/lldb/lldb-forward-rtti.h Thu Jul 14 21:26:42 2011 @@ -56,11 +56,13 @@ typedef SharedPtr::Type RegularExpressionSP; typedef SharedPtr::Type SectionSP; typedef SharedPtr::Type SearchFilterSP; + typedef SharedPtr::Type ScriptFormatSP; typedef SharedPtr::Type StackFrameSP; typedef SharedPtr::Type StackFrameListSP; typedef SharedPtr::Type StopInfoSP; typedef SharedPtr::Type StoppointLocationSP; typedef SharedPtr::Type StreamSP; + typedef SharedPtr::Type StringSummaryFormatSP; typedef SharedPtr::Type SummaryFormatSP; typedef SharedPtr::Type SymbolFileSP; typedef SharedPtr::Type SymbolContextSpecifierSP; Modified: lldb/trunk/include/lldb/lldb-forward.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/lldb-forward.h?rev=135238&r1=135237&r2=135238&view=diff ============================================================================== --- lldb/trunk/include/lldb/lldb-forward.h (original) +++ lldb/trunk/include/lldb/lldb-forward.h Thu Jul 14 21:26:42 2011 @@ -114,6 +114,7 @@ class RegisterValue; class RegularExpression; class Scalar; +class ScriptSummaryFormat; class ScriptInterpreter; class ScriptInterpreterPython; class SearchFilter; @@ -131,6 +132,7 @@ class StreamFile; class StreamString; class StringList; +class StringSummaryFormat; class SummaryFormat; class Symbol; class SymbolContext; Modified: lldb/trunk/lldb.xcodeproj/project.pbxproj URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lldb.xcodeproj/project.pbxproj?rev=135238&r1=135237&r2=135238&view=diff ============================================================================== --- lldb/trunk/lldb.xcodeproj/project.pbxproj (original) +++ lldb/trunk/lldb.xcodeproj/project.pbxproj Thu Jul 14 21:26:42 2011 @@ -402,6 +402,7 @@ 4CCA645613B40B82003BDF98 /* AppleObjCTrampolineHandler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CCA644813B40B82003BDF98 /* AppleObjCTrampolineHandler.cpp */; }; 4CCA645813B40B82003BDF98 /* AppleThreadPlanStepThroughObjCTrampoline.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CCA644A13B40B82003BDF98 /* AppleThreadPlanStepThroughObjCTrampoline.cpp */; }; 4CD0BD0F134BFADF00CB44D4 /* ValueObjectDynamicValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CD0BD0E134BFADF00CB44D4 /* ValueObjectDynamicValue.cpp */; }; + 94031A9E13CF486700DCFF3C /* InputReaderEZ.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94031A9D13CF486600DCFF3C /* InputReaderEZ.cpp */; }; 9415F61813B2C0EF00A52B36 /* FormatManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9415F61713B2C0EF00A52B36 /* FormatManager.cpp */; }; 94611EB213CCA4A4003A22AF /* RefCounter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94611EB113CCA4A4003A22AF /* RefCounter.cpp */; }; 9463D4CD13B1798800C230D4 /* CommandObjectType.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9463D4CC13B1798800C230D4 /* CommandObjectType.cpp */; }; @@ -631,8 +632,8 @@ 261B5A5311C3F2AD00AABD0A /* SharingPtr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SharingPtr.h; path = include/lldb/Utility/SharingPtr.h; sourceTree = ""; }; 26217930133BC8640083B112 /* lldb-private-types.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "lldb-private-types.h"; path = "include/lldb/lldb-private-types.h"; sourceTree = ""; }; 26217932133BCB850083B112 /* lldb-private-enumerations.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "lldb-private-enumerations.h"; path = "include/lldb/lldb-private-enumerations.h"; sourceTree = ""; }; - 263664921140A4930075843B /* Debugger.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Debugger.cpp; path = source/Core/Debugger.cpp; sourceTree = ""; }; - 263664941140A4C10075843B /* Debugger.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Debugger.h; path = include/lldb/Core/Debugger.h; sourceTree = ""; }; + 263664921140A4930075843B /* Debugger.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; name = Debugger.cpp; path = source/Core/Debugger.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; + 263664941140A4C10075843B /* Debugger.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = Debugger.h; path = include/lldb/Core/Debugger.h; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; 26368A3B126B697600E8659F /* darwin-debug.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "darwin-debug.cpp"; path = "tools/darwin-debug/darwin-debug.cpp"; sourceTree = ""; }; 263E949D13661AE400E7D1CE /* UnwindAssembly-x86.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = "UnwindAssembly-x86.cpp"; sourceTree = ""; }; 263E949E13661AE400E7D1CE /* UnwindAssembly-x86.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "UnwindAssembly-x86.h"; sourceTree = ""; }; @@ -677,7 +678,7 @@ 266F5CBB12FC846200DFCE33 /* Config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Config.h; path = include/lldb/Host/Config.h; sourceTree = ""; }; 2671A0CD134825F6003A87BB /* ConnectionMachPort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ConnectionMachPort.h; path = include/lldb/Core/ConnectionMachPort.h; sourceTree = ""; }; 2671A0CF13482601003A87BB /* ConnectionMachPort.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ConnectionMachPort.cpp; path = source/Core/ConnectionMachPort.cpp; sourceTree = ""; }; - 2672D8461189055500FF4019 /* CommandObjectFrame.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CommandObjectFrame.cpp; path = source/Commands/CommandObjectFrame.cpp; sourceTree = ""; }; + 2672D8461189055500FF4019 /* CommandObjectFrame.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; name = CommandObjectFrame.cpp; path = source/Commands/CommandObjectFrame.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; 2672D8471189055500FF4019 /* CommandObjectFrame.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CommandObjectFrame.h; path = source/Commands/CommandObjectFrame.h; sourceTree = ""; }; 26744EED1338317700EF765A /* GDBRemoteCommunicationClient.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GDBRemoteCommunicationClient.cpp; sourceTree = ""; }; 26744EEE1338317700EF765A /* GDBRemoteCommunicationClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GDBRemoteCommunicationClient.h; sourceTree = ""; }; @@ -724,7 +725,7 @@ 26A0604811A5D03C00F75969 /* Baton.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Baton.cpp; path = source/Core/Baton.cpp; sourceTree = ""; }; 26A3B4AC1181454800381BC2 /* ObjectContainerBSDArchive.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ObjectContainerBSDArchive.cpp; sourceTree = ""; }; 26A3B4AD1181454800381BC2 /* ObjectContainerBSDArchive.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ObjectContainerBSDArchive.h; sourceTree = ""; }; - 26A4EEB511682AAC007A372A /* LLDBWrapPython.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LLDBWrapPython.cpp; path = source/LLDBWrapPython.cpp; sourceTree = ""; }; + 26A4EEB511682AAC007A372A /* LLDBWrapPython.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; name = LLDBWrapPython.cpp; path = source/LLDBWrapPython.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; 26A7A034135E6E4200FB369E /* NamedOptionValue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NamedOptionValue.cpp; path = source/Interpreter/NamedOptionValue.cpp; sourceTree = ""; }; 26A7A036135E6E5300FB369E /* NamedOptionValue.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NamedOptionValue.h; path = include/lldb/Interpreter/NamedOptionValue.h; sourceTree = ""; }; 26B167A41123BF5500DC7B4F /* ThreadSafeValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ThreadSafeValue.h; path = include/lldb/Core/ThreadSafeValue.h; sourceTree = ""; }; @@ -830,7 +831,7 @@ 26BC7D7E10F1B77400F91463 /* Timer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Timer.h; path = include/lldb/Core/Timer.h; sourceTree = ""; }; 26BC7D8010F1B77400F91463 /* UserID.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = UserID.h; path = include/lldb/Core/UserID.h; sourceTree = ""; }; 26BC7D8110F1B77400F91463 /* Value.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Value.h; path = include/lldb/Core/Value.h; sourceTree = ""; }; - 26BC7D8210F1B77400F91463 /* ValueObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ValueObject.h; path = include/lldb/Core/ValueObject.h; sourceTree = ""; }; + 26BC7D8210F1B77400F91463 /* ValueObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = ValueObject.h; path = include/lldb/Core/ValueObject.h; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; 26BC7D8310F1B77400F91463 /* ValueObjectChild.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ValueObjectChild.h; path = include/lldb/Core/ValueObjectChild.h; sourceTree = ""; }; 26BC7D8410F1B77400F91463 /* ValueObjectList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ValueObjectList.h; path = include/lldb/Core/ValueObjectList.h; sourceTree = ""; }; 26BC7D8510F1B77400F91463 /* ValueObjectVariable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ValueObjectVariable.h; path = include/lldb/Core/ValueObjectVariable.h; sourceTree = ""; }; @@ -928,7 +929,7 @@ 26BC7E9610F1B85900F91463 /* Timer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Timer.cpp; path = source/Core/Timer.cpp; sourceTree = ""; }; 26BC7E9810F1B85900F91463 /* UserID.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = UserID.cpp; path = source/Core/UserID.cpp; sourceTree = ""; }; 26BC7E9910F1B85900F91463 /* Value.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Value.cpp; path = source/Core/Value.cpp; sourceTree = ""; }; - 26BC7E9A10F1B85900F91463 /* ValueObject.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ValueObject.cpp; path = source/Core/ValueObject.cpp; sourceTree = ""; }; + 26BC7E9A10F1B85900F91463 /* ValueObject.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; name = ValueObject.cpp; path = source/Core/ValueObject.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; 26BC7E9B10F1B85900F91463 /* ValueObjectChild.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ValueObjectChild.cpp; path = source/Core/ValueObjectChild.cpp; sourceTree = ""; }; 26BC7E9C10F1B85900F91463 /* ValueObjectList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ValueObjectList.cpp; path = source/Core/ValueObjectList.cpp; sourceTree = ""; }; 26BC7E9D10F1B85900F91463 /* ValueObjectVariable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ValueObjectVariable.cpp; path = source/Core/ValueObjectVariable.cpp; sourceTree = ""; }; @@ -1019,8 +1020,8 @@ 26DB3E141379E7AD0080DC73 /* ABISysV_x86_64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ABISysV_x86_64.h; sourceTree = ""; }; 26DC6A101337FE6900FF7998 /* lldb-platform */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "lldb-platform"; sourceTree = BUILT_PRODUCTS_DIR; }; 26DC6A1C1337FECA00FF7998 /* lldb-platform.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "lldb-platform.cpp"; path = "tools/lldb-platform/lldb-platform.cpp"; sourceTree = ""; }; - 26DE1E6911616C2E00A093E2 /* lldb-forward-rtti.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "lldb-forward-rtti.h"; path = "include/lldb/lldb-forward-rtti.h"; sourceTree = ""; }; - 26DE1E6A11616C2E00A093E2 /* lldb-forward.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "lldb-forward.h"; path = "include/lldb/lldb-forward.h"; sourceTree = ""; }; + 26DE1E6911616C2E00A093E2 /* lldb-forward-rtti.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = "lldb-forward-rtti.h"; path = "include/lldb/lldb-forward-rtti.h"; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; + 26DE1E6A11616C2E00A093E2 /* lldb-forward.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = "lldb-forward.h"; path = "include/lldb/lldb-forward.h"; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; 26DE204011618AB900A093E2 /* SBSymbolContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SBSymbolContext.h; path = include/lldb/API/SBSymbolContext.h; sourceTree = ""; }; 26DE204211618ACA00A093E2 /* SBAddress.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SBAddress.h; path = include/lldb/API/SBAddress.h; sourceTree = ""; }; 26DE204411618ADA00A093E2 /* SBAddress.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBAddress.cpp; path = source/API/SBAddress.cpp; sourceTree = ""; }; @@ -1169,11 +1170,14 @@ 69A01E1E1236C5D400C660B5 /* Mutex.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Mutex.cpp; sourceTree = ""; }; 69A01E1F1236C5D400C660B5 /* Symbols.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Symbols.cpp; sourceTree = ""; }; 69A01E201236C5D400C660B5 /* TimeValue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TimeValue.cpp; sourceTree = ""; }; - 9415F61613B2C0DC00A52B36 /* FormatManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = FormatManager.h; path = include/lldb/Core/FormatManager.h; sourceTree = ""; }; - 9415F61713B2C0EF00A52B36 /* FormatManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FormatManager.cpp; path = source/Core/FormatManager.cpp; sourceTree = ""; }; + 94031A9B13CF484600DCFF3C /* InputReaderEZ.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = InputReaderEZ.h; path = include/lldb/Core/InputReaderEZ.h; sourceTree = ""; }; + 94031A9D13CF486600DCFF3C /* InputReaderEZ.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = InputReaderEZ.cpp; path = source/Core/InputReaderEZ.cpp; sourceTree = ""; }; + 94031A9F13CF5B3D00DCFF3C /* PriorityPointerPair.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = PriorityPointerPair.h; path = include/lldb/Utility/PriorityPointerPair.h; sourceTree = ""; }; + 9415F61613B2C0DC00A52B36 /* FormatManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = FormatManager.h; path = include/lldb/Core/FormatManager.h; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; + 9415F61713B2C0EF00A52B36 /* FormatManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; name = FormatManager.cpp; path = source/Core/FormatManager.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; 94611EAF13CCA363003A22AF /* RefCounter.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = RefCounter.h; path = include/lldb/Utility/RefCounter.h; sourceTree = ""; }; 94611EB113CCA4A4003A22AF /* RefCounter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RefCounter.cpp; path = source/Utility/RefCounter.cpp; sourceTree = ""; }; - 9463D4CC13B1798800C230D4 /* CommandObjectType.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CommandObjectType.cpp; path = source/Commands/CommandObjectType.cpp; sourceTree = ""; }; + 9463D4CC13B1798800C230D4 /* CommandObjectType.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; name = CommandObjectType.cpp; path = source/Commands/CommandObjectType.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; 9463D4CE13B179A500C230D4 /* CommandObjectType.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = CommandObjectType.h; path = source/Commands/CommandObjectType.h; sourceTree = ""; }; 9467E65113C3D97600B3B6F3 /* TypeHierarchyNavigator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TypeHierarchyNavigator.cpp; path = source/Symbol/TypeHierarchyNavigator.cpp; sourceTree = ""; }; 9467E65413C3D98900B3B6F3 /* TypeHierarchyNavigator.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = TypeHierarchyNavigator.h; path = include/lldb/Symbol/TypeHierarchyNavigator.h; sourceTree = ""; }; @@ -1797,6 +1801,7 @@ 2676A093119C93C8008A98EF /* StringExtractorGDBRemote.cpp */, 2682F16B115EDA0D00CCFF99 /* PseudoTerminal.h */, 2682F16A115EDA0D00CCFF99 /* PseudoTerminal.cpp */, + 94031A9F13CF5B3D00DCFF3C /* PriorityPointerPair.h */, ); name = Utility; sourceTree = ""; @@ -1929,6 +1934,8 @@ 26F73061139D8FDB00FD51C7 /* History.cpp */, 9AA69DBB118A029E00D753A0 /* InputReader.h */, 9AA69DB5118A027A00D753A0 /* InputReader.cpp */, + 94031A9B13CF484600DCFF3C /* InputReaderEZ.h */, + 94031A9D13CF486600DCFF3C /* InputReaderEZ.cpp */, 9A9E1F0013980943005AC039 /* InputReaderStack.h */, 9A9E1EFE1398086D005AC039 /* InputReaderStack.cpp */, 26BC7D6510F1B77400F91463 /* IOStreamMacros.h */, @@ -3271,6 +3278,7 @@ 26ED3D6D13C563810017D45E /* OptionGroupVariable.cpp in Sources */, 26F4214413C6515B00E04E5E /* DynamicLoaderMacOSXKernel.cpp in Sources */, 94611EB213CCA4A4003A22AF /* RefCounter.cpp in Sources */, + 94031A9E13CF486700DCFF3C /* InputReaderEZ.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; Modified: lldb/trunk/scripts/lldb.swig URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/scripts/lldb.swig?rev=135238&r1=135237&r2=135238&view=diff ============================================================================== --- lldb/trunk/scripts/lldb.swig (original) +++ lldb/trunk/scripts/lldb.swig Thu Jul 14 21:26:42 2011 @@ -359,4 +359,128 @@ return stop_at_breakpoint; } +SWIGEXPORT std::string +LLDBSwigPythonCallTypeScript +( + const char *python_function_name, + const char *session_dictionary_name, + const lldb::ValueObjectSP& valobj_sp +) +{ + lldb::SBValue sb_value (valobj_sp); + + std::string retval = ""; + + PyObject *ValObj_PyObj = SWIG_NewPointerObj((void *) &valobj_sp, SWIGTYPE_p_lldb__SBValue, 0); + + if (ValObj_PyObj == NULL) + return retval; + + if (!python_function_name || !session_dictionary_name) + return retval; + + PyObject *pmodule, *main_dict, *session_dict, *pfunc; + PyObject *pargs, *pvalue; + + pmodule = PyImport_AddModule ("__main__"); + if (pmodule != NULL) + { + main_dict = PyModule_GetDict (pmodule); + if (main_dict != NULL) + { + PyObject *key, *value; + Py_ssize_t pos = 0; + + // Find the current session's dictionary in the main module's dictionary. + + if (PyDict_Check (main_dict)) + + { + session_dict = NULL; + while (PyDict_Next (main_dict, &pos, &key, &value)) + { + // We have stolen references to the key and value objects in the dictionary; we need to increment + // them now so that Python's garbage collector doesn't collect them out from under us. + Py_INCREF (key); + Py_INCREF (value); + if (strcmp (PyString_AsString (key), session_dictionary_name) == 0) + { + session_dict = value; + break; + } + } + } + + if (!session_dict || !PyDict_Check (session_dict)) + return retval; + + // Find the function we need to call in the current session's dictionary. + + pos = 0; + pfunc = NULL; + while (PyDict_Next (session_dict, &pos, &key, &value)) + { + if (PyString_Check (key)) + { + // We have stolen references to the key and value objects in the dictionary; we need to increment + // them now so that Python's garbage collector doesn't collect them out from under us. + Py_INCREF (key); + Py_INCREF (value); + if (strcmp (PyString_AsString (key), python_function_name) == 0) + { + pfunc = value; + break; + } + } + } + + // Set up the arguments and call the function. + + if (pfunc && PyCallable_Check (pfunc)) + { + pargs = PyTuple_New (2); + if (pargs == NULL) + { + if (PyErr_Occurred()) + PyErr_Clear(); + return retval; + } + + PyTuple_SetItem (pargs, 0, ValObj_PyObj); // This "steals" a reference to ValObj_PyObj + PyTuple_SetItem (pargs, 1, session_dict); // This "steals" a reference to session_dict + pvalue = PyObject_CallObject (pfunc, pargs); + Py_DECREF (pargs); + + if (pvalue != NULL) + { + if (pvalue != Py_None) + retval = std::string(PyString_AsString(pvalue)); + else + retval = "None"; + Py_DECREF (pvalue); + } + else if (PyErr_Occurred ()) + { + PyErr_Clear(); + } + Py_INCREF (session_dict); + } + else if (PyErr_Occurred()) + { + PyErr_Clear(); + } + } + else if (PyErr_Occurred()) + { + PyErr_Clear(); + } + } + else if (PyErr_Occurred ()) + { + PyErr_Clear (); + } + return retval; +} + + %} Modified: lldb/trunk/source/API/SBCommandInterpreter.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/API/SBCommandInterpreter.cpp?rev=135238&r1=135237&r2=135238&view=diff ============================================================================== --- lldb/trunk/source/API/SBCommandInterpreter.cpp (original) +++ lldb/trunk/source/API/SBCommandInterpreter.cpp Thu Jul 14 21:26:42 2011 @@ -314,6 +314,15 @@ const lldb::BreakpointLocationSP& sb_bp_loc ); +extern "C" std::string +LLDBSwigPythonCallTypeScript +( + const char *python_function_name, + const char *session_dictionary_name, + const lldb::ValueObjectSP& valobj_sp +); + + extern "C" void init_lldb(void); void @@ -324,6 +333,7 @@ { g_initialized = true; ScriptInterpreter::InitializeInterpreter (init_lldb, - LLDBSwigPythonBreakpointCallbackFunction); + LLDBSwigPythonBreakpointCallbackFunction, + LLDBSwigPythonCallTypeScript); } } Modified: lldb/trunk/source/API/SBValue.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/API/SBValue.cpp?rev=135238&r1=135237&r2=135238&view=diff ============================================================================== --- lldb/trunk/source/API/SBValue.cpp (original) +++ lldb/trunk/source/API/SBValue.cpp Thu Jul 14 21:26:42 2011 @@ -472,6 +472,28 @@ return sb_value; } +lldb::SBValue +SBValue::GetValueForExpressionPath(const char* expr_path) +{ + lldb::ValueObjectSP child_sp; + if (m_opaque_sp) + { + if (m_opaque_sp->GetUpdatePoint().GetTarget()) + { + Mutex::Locker api_locker (m_opaque_sp->GetUpdatePoint().GetTarget()->GetAPIMutex()); + // using default values for all the fancy options, just do it if you can + child_sp = m_opaque_sp->GetValueForExpressionPath(expr_path); + } + } + + SBValue sb_value (child_sp); + + LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); + if (log) + log->Printf ("SBValue(%p)::GetValueForExpressionPath (expr_path=\"%s\") => SBValue(%p)", m_opaque_sp.get(), expr_path, sb_value.get()); + + return sb_value; +} uint32_t SBValue::GetNumChildren () Modified: lldb/trunk/source/Commands/CommandObjectType.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectType.cpp?rev=135238&r1=135237&r2=135238&view=diff ============================================================================== --- lldb/trunk/source/Commands/CommandObjectType.cpp (original) +++ lldb/trunk/source/Commands/CommandObjectType.cpp Thu Jul 14 21:26:42 2011 @@ -15,8 +15,10 @@ #include "lldb/Core/ConstString.h" #include "lldb/Core/Debugger.h" #include "lldb/Core/FormatManager.h" +#include "lldb/Core/InputReaderEZ.h" #include "lldb/Core/RegularExpression.h" #include "lldb/Core/State.h" +#include "lldb/Core/StringList.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/CommandObject.h" #include "lldb/Interpreter/CommandReturnObject.h" @@ -416,6 +418,162 @@ // CommandObjectTypeSummaryAdd //------------------------------------------------------------------------- +class ScriptAddOptions +{ + +public: + + bool m_skip_pointers; + bool m_skip_references; + bool m_cascade; + bool m_callback_is_synchronous; + StringList m_target_types; + StringList m_user_source; + + ScriptAddOptions(bool p, + bool r, + bool c) : + m_skip_pointers(p), + m_skip_references(r), + m_cascade(c), + m_target_types(), + m_user_source() + { + } + + typedef lldb::SharedPtr::Type SharedPointer; + +}; + +static const char *g_reader_instructions = "Enter your Python command(s). Type 'DONE' to end."; + +class TypeScriptAddInputReader : public InputReaderEZ +{ +private: + DISALLOW_COPY_AND_ASSIGN (TypeScriptAddInputReader); +public: + TypeScriptAddInputReader(Debugger& debugger) : + InputReaderEZ(debugger) + {} + + virtual + ~TypeScriptAddInputReader() + { + } + + virtual void ActivateHandler(HandlerData& data) + { + StreamSP out_stream = data.reader.GetDebugger().GetAsyncOutputStream(); + bool batch_mode = data.reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode(); + if (!batch_mode) + { + out_stream->Printf ("%s\n", g_reader_instructions); + if (data.reader.GetPrompt()) + out_stream->Printf ("%s", data.reader.GetPrompt()); + out_stream->Flush(); + } + } + + virtual void ReactivateHandler(HandlerData& data) + { + StreamSP out_stream = data.reader.GetDebugger().GetAsyncOutputStream(); + bool batch_mode = data.reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode(); + if (data.reader.GetPrompt() && !batch_mode) + { + out_stream->Printf ("%s", data.reader.GetPrompt()); + out_stream->Flush(); + } + } + virtual void GotTokenHandler(HandlerData& data) + { + StreamSP out_stream = data.reader.GetDebugger().GetAsyncOutputStream(); + bool batch_mode = data.reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode(); + if (data.bytes && data.bytes_len && data.baton) + { + ((ScriptAddOptions*)data.baton)->m_user_source.AppendString(data.bytes, data.bytes_len); + } + if (!data.reader.IsDone() && data.reader.GetPrompt() && !batch_mode) + { + out_stream->Printf ("%s", data.reader.GetPrompt()); + out_stream->Flush(); + } + } + virtual void InterruptHandler(HandlerData& data) + { + StreamSP out_stream = data.reader.GetDebugger().GetAsyncOutputStream(); + bool batch_mode = data.reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode(); + data.reader.SetIsDone (true); + if (!batch_mode) + { + out_stream->Printf ("Warning: No command attached to breakpoint.\n"); + out_stream->Flush(); + } + } + virtual void EOFHandler(HandlerData& data) + { + data.reader.SetIsDone (true); + } + virtual void DoneHandler(HandlerData& data) + { + StreamSP out_stream = data.reader.GetDebugger().GetAsyncOutputStream(); + ScriptAddOptions *options_ptr = ((ScriptAddOptions*)data.baton); + if (!options_ptr) + { + out_stream->Printf ("Internal error #1: no script attached.\n"); + out_stream->Flush(); + return; + } + + ScriptAddOptions::SharedPointer options(options_ptr); // this will ensure that we get rid of the pointer when going out of scope + + ScriptInterpreter *interpreter = data.reader.GetDebugger().GetCommandInterpreter().GetScriptInterpreter(); + if (!interpreter) + { + out_stream->Printf ("Internal error #2: no script attached.\n"); + out_stream->Flush(); + return; + } + StringList funct_name_sl; + if (!interpreter->GenerateTypeScriptFunction (options->m_user_source, + funct_name_sl)) + { + out_stream->Printf ("Internal error #3: no script attached.\n"); + out_stream->Flush(); + return; + } + if (funct_name_sl.GetSize() == 0) + { + out_stream->Printf ("Internal error #4: no script attached.\n"); + out_stream->Flush(); + return; + } + const char *funct_name = funct_name_sl.GetStringAtIndex(0); + if (!funct_name || !funct_name[0]) + { + out_stream->Printf ("Internal error #5: no script attached.\n"); + out_stream->Flush(); + return; + } + // now I have a valid function name, let's add this as script for every type in the list + + SummaryFormatSP script_format; + script_format.reset(new ScriptSummaryFormat(options->m_cascade, + options->m_skip_pointers, + options->m_skip_references, + true, + true, + false, + std::string(funct_name), + options->m_user_source.CopyList(" "))); + + for (int i = 0; i < options->m_target_types.GetSize(); i++) + { + const char *type_name = options->m_target_types.GetStringAtIndex(i); + Debugger::SummaryFormats::Add(ConstString(type_name), script_format); + } + } +}; + class CommandObjectTypeSummaryAdd : public CommandObject { @@ -471,6 +629,17 @@ case 'n': m_name = new ConstString(option_arg); break; + case 's': + m_python_script = std::string(option_arg); + m_is_add_script = true; + break; + case 'F': + m_python_function = std::string(option_arg); + m_is_add_script = true; + break; + case 'P': + m_is_add_script = true; + break; default: error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option); break; @@ -490,6 +659,9 @@ m_skip_pointers = false; m_regex = false; m_name = NULL; + m_python_script = ""; + m_python_function = ""; + m_is_add_script = false; } const OptionDefinition* @@ -513,6 +685,9 @@ bool m_regex; std::string m_format_string; ConstString* m_name; + std::string m_python_script; + std::string m_python_function; + bool m_is_add_script; }; CommandOptions m_options; @@ -601,9 +776,170 @@ { } + void + CollectPythonScript + ( + ScriptAddOptions *options, + CommandReturnObject &result + ) + { + InputReaderSP reader_sp (new TypeScriptAddInputReader(m_interpreter.GetDebugger())); + if (reader_sp && options) + { + + Error err (reader_sp->Initialize (options)); + if (err.Success()) + { + m_interpreter.GetDebugger().PushInputReader (reader_sp); + result.SetStatus (eReturnStatusSuccessFinishNoResult); + } + else + { + result.AppendError (err.AsCString()); + result.SetStatus (eReturnStatusFailed); + } + } + else + { + result.AppendError("out of memory"); + result.SetStatus (eReturnStatusFailed); + } + + } + bool Execute (Args& command, CommandReturnObject &result) { + if (m_options.m_is_add_script) + return Execute_ScriptSummary(command, result); + else + return Execute_StringSummary(command, result); + } + + bool + Execute_ScriptSummary (Args& command, CommandReturnObject &result) + { + const size_t argc = command.GetArgumentCount(); + + if (argc < 1) + { + result.AppendErrorWithFormat ("%s takes one or more args.\n", m_cmd_name.c_str()); + result.SetStatus(eReturnStatusFailed); + return false; + } + + if (!m_options.m_python_function.empty()) // we have a Python function ready to use + { + ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter(); + if (!interpreter) + { + result.AppendError ("Internal error #1N: no script attached.\n"); + result.SetStatus (eReturnStatusFailed); + return false; + } + const char *funct_name = m_options.m_python_function.c_str(); + if (!funct_name || !funct_name[0]) + { + result.AppendError ("Internal error #2N: no script attached.\n"); + result.SetStatus (eReturnStatusFailed); + return false; + } + // now I have a valid function name, let's add this as script for every type in the list + + SummaryFormatSP script_format; + script_format.reset(new ScriptSummaryFormat(m_options.m_cascade, + m_options.m_skip_pointers, + m_options.m_skip_references, + true, + true, + false, + std::string(funct_name), + " " + m_options.m_python_function + "(valobj,dict)")); + + for (int i = 0; i < command.GetArgumentCount(); i++) + { + const char *type_name = command.GetArgumentAtIndex(i); + Debugger::SummaryFormats::Add(ConstString(type_name), script_format); + } + } + else if (m_options.m_python_script.empty()) // use an InputReader to grab Python code from the user + { + ScriptAddOptions *options = new ScriptAddOptions(m_options.m_skip_pointers, + m_options.m_skip_references, + m_options.m_cascade); + + for(int i = 0; i < argc; i++) { + const char* typeA = command.GetArgumentAtIndex(i); + if (typeA && *typeA) + options->m_target_types << typeA; + else + { + result.AppendError("empty typenames not allowed"); + result.SetStatus(eReturnStatusFailed); + return false; + } + } + + CollectPythonScript(options,result); + return result.Succeeded(); + } + else // we have a quick 1-line script, just use it + { + ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter(); + if (!interpreter) + { + result.AppendError ("Internal error #1Q: no script attached.\n"); + result.SetStatus (eReturnStatusFailed); + return false; + } + StringList funct_sl; + funct_sl << m_options.m_python_script.c_str(); + StringList funct_name_sl; + if (!interpreter->GenerateTypeScriptFunction (funct_sl, + funct_name_sl)) + { + result.AppendError ("Internal error #2Q: no script attached.\n"); + result.SetStatus (eReturnStatusFailed); + return false; + } + if (funct_name_sl.GetSize() == 0) + { + result.AppendError ("Internal error #3Q: no script attached.\n"); + result.SetStatus (eReturnStatusFailed); + return false; + } + const char *funct_name = funct_name_sl.GetStringAtIndex(0); + if (!funct_name || !funct_name[0]) + { + result.AppendError ("Internal error #4Q: no script attached.\n"); + result.SetStatus (eReturnStatusFailed); + return false; + } + // now I have a valid function name, let's add this as script for every type in the list + + ScriptFormatSP script_format; + script_format.reset(new ScriptSummaryFormat(m_options.m_cascade, + m_options.m_skip_pointers, + m_options.m_skip_references, + true, + true, + false, + std::string(funct_name), + " " + m_options.m_python_script)); + + for (int i = 0; i < command.GetArgumentCount(); i++) + { + const char *type_name = command.GetArgumentAtIndex(i); + Debugger::SummaryFormats::Add(ConstString(type_name), script_format); + } + } + + return result.Succeeded(); + } + + bool + Execute_StringSummary (Args& command, CommandReturnObject &result) + { const size_t argc = command.GetArgumentCount(); if (argc < 1 && !m_options.m_name) @@ -624,11 +960,13 @@ Error error; - SummaryFormat::SharedPointer entry(new SummaryFormat(format_cstr,m_options.m_cascade, - m_options.m_no_children,m_options.m_no_value, - m_options.m_one_liner, - m_options.m_skip_pointers, - m_options.m_skip_references)); + SummaryFormat::SharedPointer entry(new StringSummaryFormat(m_options.m_cascade, + m_options.m_skip_pointers, + m_options.m_skip_references, + m_options.m_no_children, + m_options.m_no_value, + m_options.m_one_liner, + format_cstr)); if (error.Fail()) { @@ -698,6 +1036,9 @@ { LLDB_OPT_SET_2 , true, "format-string", 'f', required_argument, NULL, 0, eArgTypeSummaryString, "Format string used to display text and object contents."}, { LLDB_OPT_SET_2, false, "expand", 'e', no_argument, NULL, 0, eArgTypeBoolean, "Expand aggregate data types to show children on separate lines."}, { LLDB_OPT_SET_2, false, "name", 'n', required_argument, NULL, 0, eArgTypeName, "A name for this summary string."}, + { LLDB_OPT_SET_3, false, "python-script", 's', required_argument, NULL, 0, eArgTypeName, "Give a one-liner Python script as part of the command."}, + { LLDB_OPT_SET_3, false, "python-function", 'F', required_argument, NULL, 0, eArgTypeName, "Give the name of a Python function to use for this type."}, + { LLDB_OPT_SET_3, false, "input-python", 'P', no_argument, NULL, 0, eArgTypeName, "Input Python code to use for this type manually."}, { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } }; @@ -808,8 +1149,8 @@ // CommandObjectTypeSummaryList //------------------------------------------------------------------------- -bool CommandObjectTypeSummaryList_LoopCallback(void* pt2self, const char* type, const SummaryFormat::SharedPointer& entry); -bool CommandObjectTypeRXSummaryList_LoopCallback(void* pt2self, lldb::RegularExpressionSP regex, const SummaryFormat::SharedPointer& entry); +bool CommandObjectTypeSummaryList_LoopCallback(void* pt2self, const char* type, const StringSummaryFormat::SharedPointer& entry); +bool CommandObjectTypeRXSummaryList_LoopCallback(void* pt2self, lldb::RegularExpressionSP regex, const StringSummaryFormat::SharedPointer& entry); class CommandObjectTypeSummaryList; @@ -912,16 +1253,7 @@ CommandReturnObject *result) { if (regex == NULL || regex->Execute(type)) - { - result->GetOutputStream().Printf ("%s: `%s`%s%s%s%s%s%s\n", type, - entry->m_format.c_str(), - entry->m_cascades ? "" : " (not cascading)", - entry->m_dont_show_children ? "" : " (show children)", - entry->m_dont_show_value ? " (hide value)" : "", - entry->m_show_members_oneliner ? " (one-line printout)" : "", - entry->m_skip_pointers ? " (skip pointers)" : "", - entry->m_skip_references ? " (skip references)" : ""); - } + result->GetOutputStream().Printf ("%s: %s\n", type, entry->GetDescription().c_str()); return true; } @@ -951,8 +1283,6 @@ } - - class CommandObjectTypeFormat : public CommandObjectMultiword { public: @@ -983,10 +1313,10 @@ "A set of commands for editing variable summary display options", "type summary [] ") { - LoadSubCommand ("add", CommandObjectSP (new CommandObjectTypeSummaryAdd (interpreter))); - LoadSubCommand ("clear", CommandObjectSP (new CommandObjectTypeSummaryClear (interpreter))); - LoadSubCommand ("delete", CommandObjectSP (new CommandObjectTypeSummaryDelete (interpreter))); - LoadSubCommand ("list", CommandObjectSP (new CommandObjectTypeSummaryList (interpreter))); + LoadSubCommand ("add", CommandObjectSP (new CommandObjectTypeSummaryAdd (interpreter))); + LoadSubCommand ("clear", CommandObjectSP (new CommandObjectTypeSummaryClear (interpreter))); + LoadSubCommand ("delete", CommandObjectSP (new CommandObjectTypeSummaryDelete (interpreter))); + LoadSubCommand ("list", CommandObjectSP (new CommandObjectTypeSummaryList (interpreter))); } Modified: lldb/trunk/source/Core/Debugger.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/Debugger.cpp?rev=135238&r1=135237&r2=135238&view=diff ============================================================================== --- lldb/trunk/source/Core/Debugger.cpp (original) +++ lldb/trunk/source/Core/Debugger.cpp Thu Jul 14 21:26:42 2011 @@ -733,6 +733,8 @@ // if this is a V, print the value using the default format if (*format_name == 'V') *val_obj_display = ValueObject::eDisplayValue; + if (*format_name == 'L') + *val_obj_display = ValueObject::eDisplayLocation; } // a good custom format tells us to print the value using it else Modified: lldb/trunk/source/Core/Error.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/Error.cpp?rev=135238&r1=135237&r2=135238&view=diff ============================================================================== --- lldb/trunk/source/Core/Error.cpp (original) +++ lldb/trunk/source/Core/Error.cpp Thu Jul 14 21:26:42 2011 @@ -51,6 +51,14 @@ { } +Error::Error (const char* err_str): + m_code (0), + m_type (eErrorTypeInvalid), + m_string () +{ + SetErrorString(err_str); +} + //---------------------------------------------------------------------- // Assignment operator //---------------------------------------------------------------------- Modified: lldb/trunk/source/Core/FormatManager.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/FormatManager.cpp?rev=135238&r1=135237&r2=135238&view=diff ============================================================================== --- lldb/trunk/source/Core/FormatManager.cpp (original) +++ lldb/trunk/source/Core/FormatManager.cpp Thu Jul 14 21:26:42 2011 @@ -14,6 +14,8 @@ // Other libraries and framework includes // Project includes +#include "lldb/Core/Debugger.h" + using namespace lldb; using namespace lldb_private; @@ -217,3 +219,54 @@ return lldb::eFormatInvalid; } } + +std::string +StringSummaryFormat::FormatObject(lldb::ValueObjectSP object) +{ + if (!object.get()) + return "NULL"; + + StreamString s; + ExecutionContext exe_ctx; + object->GetExecutionContextScope()->CalculateExecutionContext(exe_ctx); + SymbolContext sc; + if (exe_ctx.frame) + sc = exe_ctx.frame->GetSymbolContext(lldb::eSymbolContextEverything); + + if (m_show_members_oneliner) + { + const uint32_t num_children = object->GetNumChildren(); + if (num_children) + { + s.PutChar('('); + + for (uint32_t idx=0; idxGetChildAtIndex(idx, true)); + if (child_sp.get()) + { + if (idx) + s.PutCString(", "); + s.PutCString(child_sp.get()->GetName().AsCString()); + s.PutChar('='); + s.PutCString(child_sp.get()->GetPrintableRepresentation()); + } + } + + s.PutChar(')'); + + return s.GetString(); + } + else + return ""; + + } + else + { + if (Debugger::FormatPrompt(m_format.c_str(), &sc, &exe_ctx, &sc.line_entry.range.GetBaseAddress(), s, NULL, object.get())) + return s.GetString(); + else + return ""; + } +} + Modified: lldb/trunk/source/Core/InputReader.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/InputReader.cpp?rev=135238&r1=135237&r2=135238&view=diff ============================================================================== --- lldb/trunk/source/Core/InputReader.cpp (original) +++ lldb/trunk/source/Core/InputReader.cpp Thu Jul 14 21:26:42 2011 @@ -370,3 +370,14 @@ return unknown_state_string; } +bool +InputReader::HandlerData::GetBatchMode() +{ + return reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode(); +} + +lldb::StreamSP +InputReader::HandlerData::GetOutStream() +{ + return reader.GetDebugger().GetAsyncOutputStream(); +} \ No newline at end of file Added: lldb/trunk/source/Core/InputReaderEZ.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/InputReaderEZ.cpp?rev=135238&view=auto ============================================================================== --- lldb/trunk/source/Core/InputReaderEZ.cpp (added) +++ lldb/trunk/source/Core/InputReaderEZ.cpp Thu Jul 14 21:26:42 2011 @@ -0,0 +1,80 @@ +//===-- InputReaderEZ.cpp ---------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include + +#include "lldb/Core/InputReaderEZ.h" + +#include "lldb/Core/Debugger.h" +#include "lldb/Interpreter/CommandInterpreter.h" + +using namespace lldb; +using namespace lldb_private; + +size_t +InputReaderEZ::Callback_Impl(void *baton, + InputReader &reader, + lldb::InputReaderAction notification, + const char *bytes, + size_t bytes_len) + +{ + HandlerData hand_data(reader, + bytes, + bytes_len, + baton); + + switch (notification) + { + case eInputReaderActivate: + reader.ActivateHandler(hand_data); + break; + case eInputReaderDeactivate: + reader.DeactivateHandler(hand_data); + break; + case eInputReaderReactivate: + reader.ReactivateHandler(hand_data); + break; + case eInputReaderAsynchronousOutputWritten: + reader.AsynchronousOutputWrittenHandler(hand_data); + break; + case eInputReaderGotToken: + reader.GotTokenHandler(hand_data); + break; + case eInputReaderInterrupt: + reader.InterruptHandler(hand_data); + break; + case eInputReaderEndOfFile: + reader.EOFHandler(hand_data); + break; + case eInputReaderDone: + reader.DoneHandler(hand_data); + break; + } + return bytes_len; +} + +Error +InputReaderEZ::Initialize(void* baton, + lldb::InputReaderGranularity token_size, + const char* end_token, + const char *prompt, + bool echo) +{ + return InputReader::Initialize(Callback_Impl, + baton, + token_size, + end_token, + prompt, + echo); +} + +InputReaderEZ::~InputReaderEZ () +{ +} \ No newline at end of file Modified: lldb/trunk/source/Core/StringList.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/StringList.cpp?rev=135238&r1=135237&r2=135238&view=diff ============================================================================== --- lldb/trunk/source/Core/StringList.cpp (original) +++ lldb/trunk/source/Core/StringList.cpp Thu Jul 14 21:26:42 2011 @@ -8,6 +8,8 @@ //===----------------------------------------------------------------------===// #include "lldb/Core/StringList.h" + +#include "lldb/Core/StreamString.h" #include "lldb/Host/FileSpec.h" #include @@ -205,3 +207,33 @@ idx++; } } + +std::string +StringList::CopyList(const char* item_preamble, + const char* items_sep) +{ + StreamString strm; + for (int i = 0; i < GetSize(); i++) + { + if (i && items_sep && items_sep[0]) + strm << items_sep; + if (item_preamble) + strm << item_preamble; + strm << GetStringAtIndex(i); + } + return std::string(strm.GetData()); +} + +StringList& +StringList::operator << (const char* str) +{ + AppendString(str); + return *this; +} + +StringList& +StringList::operator << (StringList strings) +{ + AppendList(strings); + return *this; +} \ No newline at end of file Modified: lldb/trunk/source/Core/ValueObject.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/ValueObject.cpp?rev=135238&r1=135237&r2=135238&view=diff ============================================================================== --- lldb/trunk/source/Core/ValueObject.cpp (original) +++ lldb/trunk/source/Core/ValueObject.cpp Thu Jul 14 21:26:42 2011 @@ -29,6 +29,8 @@ #include "lldb/Host/Endian.h" +#include "lldb/Interpreter/ScriptInterpreterPython.h" + #include "lldb/Symbol/ClangASTType.h" #include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/Type.h" @@ -79,8 +81,8 @@ m_is_array_item_for_pointer(false), m_is_bitfield_for_scalar(false), m_last_format_mgr_revision(0), - m_last_summary_format(), m_last_value_format(), + m_last_summary_format(), m_forced_summary_format(), m_dump_printable_counter(0) { @@ -118,8 +120,8 @@ m_is_array_item_for_pointer(false), m_is_bitfield_for_scalar(false), m_last_format_mgr_revision(0), - m_last_summary_format(), m_last_value_format(), + m_last_summary_format(), m_forced_summary_format(), m_dump_printable_counter(0) { @@ -164,10 +166,9 @@ m_old_value_str.swap (m_value_str); m_value_str.clear(); } - m_location_str.clear(); - m_summary_str.clear(); - m_object_desc_str.clear(); + ClearUserVisibleData(); + const bool value_was_valid = GetValueIsValid(); SetValueDidChange (false); @@ -204,15 +205,15 @@ if (m_last_format_mgr_revision != Debugger::ValueFormats::GetCurrentRevision()) { if (m_last_summary_format.get()) - m_last_summary_format.reset((SummaryFormat*)NULL); + m_last_summary_format.reset((StringSummaryFormat*)NULL); if (m_last_value_format.get()) m_last_value_format.reset((ValueFormat*)NULL); Debugger::ValueFormats::Get(*this, m_last_value_format); if (!Debugger::SummaryFormats::Get(*this, m_last_summary_format)) Debugger::RegexSummaryFormats::Get(*this, m_last_summary_format); m_last_format_mgr_revision = Debugger::ValueFormats::GetCurrentRevision(); - m_value_str.clear(); - m_summary_str.clear(); + + ClearUserVisibleData(); } } @@ -507,221 +508,177 @@ { if (m_summary_str.empty()) { - SummaryFormat* summary_format = GetSummaryFormat().get(); + SummaryFormat *summary_format = GetSummaryFormat().get(); if (summary_format) { - StreamString s; - ExecutionContext exe_ctx; - this->GetExecutionContextScope()->CalculateExecutionContext(exe_ctx); - SymbolContext sc; - if (exe_ctx.frame) - sc = exe_ctx.frame->GetSymbolContext(eSymbolContextEverything); - - if (summary_format->m_show_members_oneliner) - { - const uint32_t num_children = GetNumChildren(); - if (num_children) - { - - s.PutChar('('); - - for (uint32_t idx=0; idxGetName().AsCString()); - s.PutChar('='); - s.PutCString(child_sp.get()->GetPrintableRepresentation()); - } - } - - s.PutChar(')'); - - m_summary_str.swap(s.GetString()); - return m_summary_str.c_str(); - } - else - return "()"; - - } - else - { - if (Debugger::FormatPrompt(summary_format->m_format.c_str(), &sc, &exe_ctx, &sc.line_entry.range.GetBaseAddress(), s, NULL, this)) - { - m_summary_str.swap(s.GetString()); - return m_summary_str.c_str(); - } - else - return NULL; - } + m_summary_str = summary_format->FormatObject(GetSP()); } - - clang_type_t clang_type = GetClangType(); - - // See if this is a pointer to a C string? - if (clang_type) + else { - StreamString sstr; - clang_type_t elem_or_pointee_clang_type; - const Flags type_flags (ClangASTContext::GetTypeInfo (clang_type, - GetClangAST(), - &elem_or_pointee_clang_type)); + clang_type_t clang_type = GetClangType(); - ExecutionContextScope *exe_scope = GetExecutionContextScope(); - if (exe_scope) + // See if this is a pointer to a C string? + if (clang_type) { - if (type_flags.AnySet (ClangASTContext::eTypeIsArray | ClangASTContext::eTypeIsPointer) && - ClangASTContext::IsCharType (elem_or_pointee_clang_type)) + StreamString sstr; + clang_type_t elem_or_pointee_clang_type; + const Flags type_flags (ClangASTContext::GetTypeInfo (clang_type, + GetClangAST(), + &elem_or_pointee_clang_type)); + + ExecutionContextScope *exe_scope = GetExecutionContextScope(); + if (exe_scope) { - Target *target = exe_scope->CalculateTarget(); - if (target != NULL) + if (type_flags.AnySet (ClangASTContext::eTypeIsArray | ClangASTContext::eTypeIsPointer) && + ClangASTContext::IsCharType (elem_or_pointee_clang_type)) { - lldb::addr_t cstr_address = LLDB_INVALID_ADDRESS; - AddressType cstr_address_type = eAddressTypeInvalid; - - size_t cstr_len = 0; - bool capped_data = false; - if (type_flags.Test (ClangASTContext::eTypeIsArray)) + Target *target = exe_scope->CalculateTarget(); + if (target != NULL) { - // We have an array - cstr_len = ClangASTContext::GetArraySize (clang_type); - if (cstr_len > 512) // TODO: make cap a setting + lldb::addr_t cstr_address = LLDB_INVALID_ADDRESS; + AddressType cstr_address_type = eAddressTypeInvalid; + + size_t cstr_len = 0; + bool capped_data = false; + if (type_flags.Test (ClangASTContext::eTypeIsArray)) { + // We have an array cstr_len = ClangASTContext::GetArraySize (clang_type); if (cstr_len > 512) // TODO: make cap a setting { - capped_data = true; - cstr_len = 512; + cstr_len = ClangASTContext::GetArraySize (clang_type); + if (cstr_len > 512) // TODO: make cap a setting + { + capped_data = true; + cstr_len = 512; + } } + cstr_address = GetAddressOf (cstr_address_type, true); } - cstr_address = GetAddressOf (cstr_address_type, true); - } - else - { - // We have a pointer - cstr_address = GetPointerValue (cstr_address_type, true); - } - if (cstr_address != LLDB_INVALID_ADDRESS) - { - Address cstr_so_addr (NULL, cstr_address); - DataExtractor data; - size_t bytes_read = 0; - std::vector data_buffer; - Error error; - bool prefer_file_cache = false; - if (cstr_len > 0) + else { - data_buffer.resize(cstr_len); - data.SetData (&data_buffer.front(), data_buffer.size(), lldb::endian::InlHostByteOrder()); - bytes_read = target->ReadMemory (cstr_so_addr, - prefer_file_cache, - &data_buffer.front(), - cstr_len, - error); - if (bytes_read > 0) - { - sstr << '"'; - data.Dump (&sstr, - 0, // Start offset in "data" - eFormatCharArray, // Print as characters - 1, // Size of item (1 byte for a char!) - bytes_read, // How many bytes to print? - UINT32_MAX, // num per line - LLDB_INVALID_ADDRESS,// base address - 0, // bitfield bit size - 0); // bitfield bit offset - if (capped_data) - sstr << "..."; - sstr << '"'; - } + // We have a pointer + cstr_address = GetPointerValue (cstr_address_type, true); } - else + if (cstr_address != LLDB_INVALID_ADDRESS) { - const size_t k_max_buf_size = 256; - data_buffer.resize (k_max_buf_size + 1); - // NULL terminate in case we don't get the entire C string - data_buffer.back() = '\0'; - - sstr << '"'; - - data.SetData (&data_buffer.front(), data_buffer.size(), endian::InlHostByteOrder()); - while ((bytes_read = target->ReadMemory (cstr_so_addr, - prefer_file_cache, - &data_buffer.front(), - k_max_buf_size, - error)) > 0) + Address cstr_so_addr (NULL, cstr_address); + DataExtractor data; + size_t bytes_read = 0; + std::vector data_buffer; + Error error; + bool prefer_file_cache = false; + if (cstr_len > 0) { - size_t len = strlen(&data_buffer.front()); - if (len == 0) - break; - if (len > bytes_read) - len = bytes_read; - - data.Dump (&sstr, - 0, // Start offset in "data" - eFormatCharArray, // Print as characters - 1, // Size of item (1 byte for a char!) - len, // How many bytes to print? - UINT32_MAX, // num per line - LLDB_INVALID_ADDRESS,// base address - 0, // bitfield bit size - 0); // bitfield bit offset - - if (len < k_max_buf_size) - break; - cstr_so_addr.Slide (k_max_buf_size); + data_buffer.resize(cstr_len); + data.SetData (&data_buffer.front(), data_buffer.size(), lldb::endian::InlHostByteOrder()); + bytes_read = target->ReadMemory (cstr_so_addr, + prefer_file_cache, + &data_buffer.front(), + cstr_len, + error); + if (bytes_read > 0) + { + sstr << '"'; + data.Dump (&sstr, + 0, // Start offset in "data" + eFormatCharArray, // Print as characters + 1, // Size of item (1 byte for a char!) + bytes_read, // How many bytes to print? + UINT32_MAX, // num per line + LLDB_INVALID_ADDRESS,// base address + 0, // bitfield bit size + 0); // bitfield bit offset + if (capped_data) + sstr << "..."; + sstr << '"'; + } + } + else + { + const size_t k_max_buf_size = 256; + data_buffer.resize (k_max_buf_size + 1); + // NULL terminate in case we don't get the entire C string + data_buffer.back() = '\0'; + + sstr << '"'; + + data.SetData (&data_buffer.front(), data_buffer.size(), endian::InlHostByteOrder()); + while ((bytes_read = target->ReadMemory (cstr_so_addr, + prefer_file_cache, + &data_buffer.front(), + k_max_buf_size, + error)) > 0) + { + size_t len = strlen(&data_buffer.front()); + if (len == 0) + break; + if (len > bytes_read) + len = bytes_read; + + data.Dump (&sstr, + 0, // Start offset in "data" + eFormatCharArray, // Print as characters + 1, // Size of item (1 byte for a char!) + len, // How many bytes to print? + UINT32_MAX, // num per line + LLDB_INVALID_ADDRESS,// base address + 0, // bitfield bit size + 0); // bitfield bit offset + + if (len < k_max_buf_size) + break; + cstr_so_addr.Slide (k_max_buf_size); + } + sstr << '"'; } - sstr << '"'; } } + + if (sstr.GetSize() > 0) + m_summary_str.assign (sstr.GetData(), sstr.GetSize()); } - - if (sstr.GetSize() > 0) - m_summary_str.assign (sstr.GetData(), sstr.GetSize()); - } - else if (ClangASTContext::IsFunctionPointerType (clang_type)) - { - AddressType func_ptr_address_type = eAddressTypeInvalid; - lldb::addr_t func_ptr_address = GetPointerValue (func_ptr_address_type, true); - - if (func_ptr_address != 0 && func_ptr_address != LLDB_INVALID_ADDRESS) + else if (ClangASTContext::IsFunctionPointerType (clang_type)) { - switch (func_ptr_address_type) - { - case eAddressTypeInvalid: - case eAddressTypeFile: - break; + AddressType func_ptr_address_type = eAddressTypeInvalid; + lldb::addr_t func_ptr_address = GetPointerValue (func_ptr_address_type, true); - case eAddressTypeLoad: + if (func_ptr_address != 0 && func_ptr_address != LLDB_INVALID_ADDRESS) + { + switch (func_ptr_address_type) { - Address so_addr; - Target *target = exe_scope->CalculateTarget(); - if (target && target->GetSectionLoadList().IsEmpty() == false) + case eAddressTypeInvalid: + case eAddressTypeFile: + break; + + case eAddressTypeLoad: { - if (target->GetSectionLoadList().ResolveLoadAddress(func_ptr_address, so_addr)) + Address so_addr; + Target *target = exe_scope->CalculateTarget(); + if (target && target->GetSectionLoadList().IsEmpty() == false) { - so_addr.Dump (&sstr, - exe_scope, - Address::DumpStyleResolvedDescription, - Address::DumpStyleSectionNameOffset); + if (target->GetSectionLoadList().ResolveLoadAddress(func_ptr_address, so_addr)) + { + so_addr.Dump (&sstr, + exe_scope, + Address::DumpStyleResolvedDescription, + Address::DumpStyleSectionNameOffset); + } } } - } - break; + break; - case eAddressTypeHost: - break; + case eAddressTypeHost: + break; + } + } + if (sstr.GetSize() > 0) + { + m_summary_str.assign (1, '('); + m_summary_str.append (sstr.GetData(), sstr.GetSize()); + m_summary_str.append (1, ')'); } - } - if (sstr.GetSize() > 0) - { - m_summary_str.assign (1, '('); - m_summary_str.append (sstr.GetData(), sstr.GetSize()); - m_summary_str.append (1, ')'); } } } @@ -960,34 +917,35 @@ clang_type_t clang_type = GetClangType (); if (clang_type) { - StreamString sstr; - Format format = GetFormat(); - if (format == eFormatDefault) + if (m_last_value_format) { - if (m_last_value_format) - format = m_last_value_format->m_format; - else - // force the system into using unsigned integers for bitfields - format = (m_is_bitfield_for_scalar ? eFormatUnsigned : - ClangASTType::GetFormat(clang_type)); + m_value_str = m_last_value_format->FormatObject(GetSP()); } - - if (ClangASTType::DumpTypeValue (GetClangAST(), // The clang AST - clang_type, // The clang type to display - &sstr, - format, // Format to display this type with - m_data, // Data to extract from - 0, // Byte offset into "m_data" - GetByteSize(), // Byte size of item in "m_data" - GetBitfieldBitSize(), // Bitfield bit size - GetBitfieldBitOffset())) // Bitfield bit offset - m_value_str.swap(sstr.GetString()); else { - m_error.SetErrorStringWithFormat ("unsufficient data for value (only %u of %u bytes available)", - m_data.GetByteSize(), - GetByteSize()); - m_value_str.clear(); + StreamString sstr; + Format format = GetFormat(); + if (format == eFormatDefault) + format = (m_is_bitfield_for_scalar ? eFormatUnsigned : + ClangASTType::GetFormat(clang_type)); + + if (ClangASTType::DumpTypeValue (GetClangAST(), // The clang AST + clang_type, // The clang type to display + &sstr, + format, // Format to display this type with + m_data, // Data to extract from + 0, // Byte offset into "m_data" + GetByteSize(), // Byte size of item in "m_data" + GetBitfieldBitSize(), // Bitfield bit size + GetBitfieldBitOffset())) // Bitfield bit offset + m_value_str.swap(sstr.GetString()); + else + { + m_error.SetErrorStringWithFormat ("unsufficient data for value (only %u of %u bytes available)", + m_data.GetByteSize(), + GetByteSize()); + m_value_str.clear(); + } } } } @@ -1046,6 +1004,9 @@ case eDisplayLanguageSpecific: return_value = GetObjectDescription(); break; + case eDisplayLocation: + return_value = GetLocationAsCString(); + break; } // this code snippet might lead to endless recursion, thus we use a RefCounter here to @@ -3221,3 +3182,12 @@ return needs_update; } + +void +ValueObject::ClearUserVisibleData() +{ + m_location_str.clear(); + m_value_str.clear(); + m_summary_str.clear(); + m_object_desc_str.clear(); +} \ No newline at end of file Modified: lldb/trunk/source/Interpreter/ScriptInterpreter.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/ScriptInterpreter.cpp?rev=135238&r1=135237&r2=135238&view=diff ============================================================================== --- lldb/trunk/source/Interpreter/ScriptInterpreter.cpp (original) +++ lldb/trunk/source/Interpreter/ScriptInterpreter.cpp Thu Jul 14 21:26:42 2011 @@ -92,10 +92,12 @@ void ScriptInterpreter::InitializeInterpreter (SWIGInitCallback python_swig_init_callback, - SWIGBreakpointCallbackFunction python_swig_breakpoint_callback) + SWIGBreakpointCallbackFunction python_swig_breakpoint_callback, + SWIGPythonTypeScriptCallbackFunction python_swig_typescript_callback) { ScriptInterpreterPython::InitializeInterpreter (python_swig_init_callback, - python_swig_breakpoint_callback); + python_swig_breakpoint_callback, + python_swig_typescript_callback); } void Modified: lldb/trunk/source/Interpreter/ScriptInterpreterPython.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/ScriptInterpreterPython.cpp?rev=135238&r1=135237&r2=135238&view=diff ============================================================================== --- lldb/trunk/source/Interpreter/ScriptInterpreterPython.cpp (original) +++ lldb/trunk/source/Interpreter/ScriptInterpreterPython.cpp Thu Jul 14 21:26:42 2011 @@ -34,6 +34,7 @@ static ScriptInterpreter::SWIGInitCallback g_swig_init_callback = NULL; static ScriptInterpreter::SWIGBreakpointCallbackFunction g_swig_breakpoint_callback = NULL; +static ScriptInterpreter::SWIGPythonTypeScriptCallbackFunction g_swig_typescript_callback = NULL; static int @@ -1140,6 +1141,117 @@ return ExecuteMultipleLines (function_def_string.c_str()); } +// TODO move both GenerateTypeScriptFunction and GenerateBreakpointCommandCallbackData to actually +// use this code to generate their functions +bool +ScriptInterpreterPython::GenerateFunction(std::string& signature, StringList &input, StringList &output) +{ + int num_lines = input.GetSize (); + if (num_lines == 0) + return false; + StreamString sstr; + StringList auto_generated_function; + auto_generated_function.AppendString (signature.c_str()); + auto_generated_function.AppendString (" global_dict = globals()"); // Grab the global dictionary + auto_generated_function.AppendString (" new_keys = dict.keys()"); // Make a list of keys in the session dict + auto_generated_function.AppendString (" old_keys = global_dict.keys()"); // Save list of keys in global dict + auto_generated_function.AppendString (" global_dict.update (dict)"); // Add the session dictionary to the + // global dictionary. + + // Wrap everything up inside the function, increasing the indentation. + + for (int i = 0; i < num_lines; ++i) + { + sstr.Clear (); + sstr.Printf (" %s", input.GetStringAtIndex (i)); + auto_generated_function.AppendString (sstr.GetData()); + } + auto_generated_function.AppendString (" for key in new_keys:"); // Iterate over all the keys from session dict + auto_generated_function.AppendString (" dict[key] = global_dict[key]"); // Update session dict values + auto_generated_function.AppendString (" if key not in old_keys:"); // If key was not originally in global dict + auto_generated_function.AppendString (" del global_dict[key]"); // ...then remove key/value from global dict + + // Verify that the results are valid Python. + + if (!ExportFunctionDefinitionToInterpreter (auto_generated_function)) + return false; + + return true; + +} + +// this implementation is identical to GenerateBreakpointCommandCallbackData (apart from the name +// given to generated functions, of course) +bool +ScriptInterpreterPython::GenerateTypeScriptFunction (StringList &user_input, StringList &output) +{ + static int num_created_functions = 0; + user_input.RemoveBlankLines (); + int num_lines = user_input.GetSize (); + StreamString sstr; + + // Check to see if we have any data; if not, just return. + if (user_input.GetSize() == 0) + return false; + + // Take what the user wrote, wrap it all up inside one big auto-generated Python function, passing in the + // ValueObject as parameter to the function. + + sstr.Printf ("lldb_autogen_python_type_print_func_%d", num_created_functions); + ++num_created_functions; + std::string auto_generated_function_name = sstr.GetData(); + + sstr.Clear(); + StringList auto_generated_function; + + // Create the function name & definition string. + + sstr.Printf ("def %s (valobj, dict):", auto_generated_function_name.c_str()); + auto_generated_function.AppendString (sstr.GetData()); + + // Pre-pend code for setting up the session dictionary. + + auto_generated_function.AppendString (" global_dict = globals()"); // Grab the global dictionary + auto_generated_function.AppendString (" new_keys = dict.keys()"); // Make a list of keys in the session dict + auto_generated_function.AppendString (" old_keys = global_dict.keys()"); // Save list of keys in global dict + auto_generated_function.AppendString (" global_dict.update (dict)"); // Add the session dictionary to the + // global dictionary. + + // Wrap everything up inside the function, increasing the indentation. + + for (int i = 0; i < num_lines; ++i) + { + sstr.Clear (); + sstr.Printf (" %s", user_input.GetStringAtIndex (i)); + auto_generated_function.AppendString (sstr.GetData()); + } + + // Append code to clean up the global dictionary and update the session dictionary (all updates in the function + // got written to the values in the global dictionary, not the session dictionary). + + auto_generated_function.AppendString (" for key in new_keys:"); // Iterate over all the keys from session dict + auto_generated_function.AppendString (" dict[key] = global_dict[key]"); // Update session dict values + auto_generated_function.AppendString (" if key not in old_keys:"); // If key was not originally in global dict + auto_generated_function.AppendString (" del global_dict[key]"); // ...then remove key/value from global dict + + // Verify that the results are valid Python. + + if (!ExportFunctionDefinitionToInterpreter (auto_generated_function)) + return false; + + // Store the name of the auto-generated function to be called. + + output.AppendString (auto_generated_function_name.c_str()); + return true; +} + +bool +ScriptInterpreterPython::GenerateTypeScriptFunction (const char* oneliner, StringList &output) +{ + StringList input(oneliner); + return GenerateTypeScriptFunction(input, output); +} + bool ScriptInterpreterPython::GenerateBreakpointCommandCallbackData (StringList &user_input, StringList &callback_data) { @@ -1206,6 +1318,63 @@ return true; } +std::string +ScriptInterpreterPython::CallPythonScriptFunction (const char *python_function_name, + lldb::ValueObjectSP valobj) +{ + + if (!python_function_name || !(*python_function_name)) + return ""; + + if (!valobj.get()) + return ""; + + Target *target = valobj->GetUpdatePoint().GetTarget(); + + if (!target) + return ""; + + Debugger &debugger = target->GetDebugger(); + ScriptInterpreter *script_interpreter = debugger.GetCommandInterpreter().GetScriptInterpreter(); + ScriptInterpreterPython *python_interpreter = (ScriptInterpreterPython *) script_interpreter; + + if (!script_interpreter) + return ""; + + std::string ret_val; + + if (python_function_name + && *python_function_name) + { + FILE *tmp_fh = (python_interpreter->m_dbg_stdout ? python_interpreter->m_dbg_stdout : stdout); + if (CurrentThreadHasPythonLock()) + { + python_interpreter->EnterSession (); + ret_val = g_swig_typescript_callback (python_function_name, + python_interpreter->m_dictionary_name.c_str(), + valobj); + python_interpreter->LeaveSession (); + } + else + { + while (!GetPythonLock (1)) + fprintf (tmp_fh, + "Python interpreter locked on another thread; waiting to acquire lock...\n"); + python_interpreter->EnterSession (); + ret_val = g_swig_typescript_callback (python_function_name, + python_interpreter->m_dictionary_name.c_str(), + valobj); + python_interpreter->LeaveSession (); + ReleasePythonLock (); + } + } + else + return ""; + + return ret_val; + +} + bool ScriptInterpreterPython::BreakpointCallbackFunction ( @@ -1399,10 +1568,12 @@ void ScriptInterpreterPython::InitializeInterpreter (SWIGInitCallback python_swig_init_callback, - SWIGBreakpointCallbackFunction python_swig_breakpoint_callback) + SWIGBreakpointCallbackFunction python_swig_breakpoint_callback, + SWIGPythonTypeScriptCallbackFunction python_swig_typescript_callback) { g_swig_init_callback = python_swig_init_callback; - g_swig_breakpoint_callback = python_swig_breakpoint_callback; + g_swig_breakpoint_callback = python_swig_breakpoint_callback; + g_swig_typescript_callback = python_swig_typescript_callback; } void Modified: lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp?rev=135238&r1=135237&r2=135238&view=diff ============================================================================== --- lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp (original) +++ lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp Thu Jul 14 21:26:42 2011 @@ -19,6 +19,7 @@ #include "lldb/Core/Log.h" #include "lldb/Core/State.h" #include "lldb/Core/StreamString.h" +#include "lldb/Host/Endian.h" #include "lldb/Host/Host.h" #include "lldb/Host/TimeValue.h" #include "lldb/Target/Process.h" Added: lldb/trunk/test/functionalities/data-formatter/data-formatter-script/Makefile URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/data-formatter/data-formatter-script/Makefile?rev=135238&view=auto ============================================================================== --- lldb/trunk/test/functionalities/data-formatter/data-formatter-script/Makefile (added) +++ lldb/trunk/test/functionalities/data-formatter/data-formatter-script/Makefile Thu Jul 14 21:26:42 2011 @@ -0,0 +1,5 @@ +LEVEL = ../../../make + +CXX_SOURCES := main.cpp + +include $(LEVEL)/Makefile.rules Added: lldb/trunk/test/functionalities/data-formatter/data-formatter-script/TestDataFormatterScript.py URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/data-formatter/data-formatter-script/TestDataFormatterScript.py?rev=135238&view=auto ============================================================================== --- lldb/trunk/test/functionalities/data-formatter/data-formatter-script/TestDataFormatterScript.py (added) +++ lldb/trunk/test/functionalities/data-formatter/data-formatter-script/TestDataFormatterScript.py Thu Jul 14 21:26:42 2011 @@ -0,0 +1,110 @@ +""" +Test lldb data formatter subsystem. +""" + +import os, time +import unittest2 +import lldb +from lldbtest import * + +class DataFormatterTestCase(TestBase): + + mydir = os.path.join("functionalities", "data-formatter", "data-formatter-script") + + @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin") + def test_with_dsym_and_run_command(self): + """Test data formatter commands.""" + self.buildDsym() + self.data_formatter_commands() + + def test_with_dwarf_and_run_command(self): + """Test data formatter commands.""" + self.buildDwarf() + self.data_formatter_commands() + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break at. + self.line = line_number('main.cpp', '// Set break point at this line.') + + def data_formatter_commands(self): + """Test that that file and class static variables display correctly.""" + self.runCmd("file a.out", CURRENT_EXECUTABLE_SET) + + self.expect("breakpoint set -f main.cpp -l %d" % self.line, + BREAKPOINT_CREATED, + startstr = "Breakpoint created: 1: file ='main.cpp', line = %d, locations = 1" % + self.line) + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs = ['stopped', + 'stop reason = breakpoint']) + + # This is the function to remove the custom formats in order to have a + # clean slate for the next test case. + def cleanup(): + self.runCmd('type format clear', check=False) + self.runCmd('type summary clear', check=False) + + # Execute the cleanup function during test case tear down. + self.addTearDownHook(cleanup) + + # Set the script here to ease the formatting + script = 'a = valobj.GetChildMemberWithName(\'integer\'); a_val = a.GetValue(); str = \'Hello from Python, \' + a_val + \' time\'; return str + (\'!\' if a_val == \'1\' else \'s!\');' + + self.runCmd("type summary add add i_am_cool -s \"%s\"" % script) + + self.expect("frame variable one", + substrs = ['Hello from Python', + '1 time!']) + + self.expect("frame variable two", + substrs = ['Hello from Python', + '4 times!']) + + self.runCmd("n"); # skip ahead to make values change + + self.expect("frame variable three", + substrs = ['Hello from Python, 10 times!', + 'Hello from Python, 4 times!']) + + self.runCmd("n"); # skip ahead to make values change + + self.expect("frame variable two", + substrs = ['Hello from Python', + '1 time!']) + + script = 'a = valobj.GetChildMemberWithName(\'integer\'); a_val = a.GetValue(); str = \'int says \' + a_val; return str;' + + # Check that changes in the script are immediately reflected + self.runCmd("type summary add i_am_cool -s \"%s\"" % script) + + self.expect("frame variable two", + substrs = ['int says 1']) + + # Change the summary + self.runCmd("type summary add -f \"int says ${var.integer}, and float says ${var.floating}\" i_am_cool") + + self.expect("frame variable two", + substrs = ['int says 1', + 'and float says 2.71']) + # Try it for pointers + self.expect("frame variable twoptr", + substrs = ['int says 1', + 'and float says 2.71']) + + # Force a failure for pointers + self.runCmd("type summary add i_am_cool -p -s \"%s\"" % script) + + self.expect("frame variable twoptr", matching=False, + substrs = ['and float says 2.71']) + +if __name__ == '__main__': + import atexit + lldb.SBDebugger.Initialize() + atexit.register(lambda: lldb.SBDebugger.Terminate()) + unittest2.main() Added: lldb/trunk/test/functionalities/data-formatter/data-formatter-script/main.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/data-formatter/data-formatter-script/main.cpp?rev=135238&view=auto ============================================================================== --- lldb/trunk/test/functionalities/data-formatter/data-formatter-script/main.cpp (added) +++ lldb/trunk/test/functionalities/data-formatter/data-formatter-script/main.cpp Thu Jul 14 21:26:42 2011 @@ -0,0 +1,49 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include +#include +#include + +struct i_am_cool +{ + int integer; + float floating; + char character; + i_am_cool(int I, float F, char C) : + integer(I), floating(F), character(C) {} + i_am_cool() : integer(1), floating(2), character('3') {} + +}; + +struct i_am_cooler +{ + i_am_cool first_cool; + i_am_cool second_cool; + float floating; + + i_am_cooler(int I1, int I2, float F1, float F2, char C1, char C2) : + first_cool(I1,F1,C1), + second_cool(I2,F2,C2), + floating((F1 + F2)/2) {} +}; + +int main (int argc, const char * argv[]) +{ + i_am_cool one(1,3.14,'E'); + i_am_cool two(4,2.71,'G'); + + i_am_cool* twoptr = &two; + + i_am_cooler three(10,4,1985,1/1/2011,'B','E'); // Set break point at this line. + + two.integer = 1; + + return 0; +} \ No newline at end of file Modified: lldb/trunk/www/varformats.html URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/www/varformats.html?rev=135238&r1=135237&r2=135238&view=diff ============================================================================== --- lldb/trunk/www/varformats.html (original) +++ lldb/trunk/www/varformats.html Thu Jul 14 21:26:42 2011 @@ -784,6 +784,17 @@ (i_am_cool) one = x=3

    +

    When defining a named summmary, binding it to one or more types becomes optional. + Even if you bind the named summary to a type, and later change the summary string + for that type, the named summary will not be changed by that. You can delete + named summaries by using the type summary delete command, as if the + summary name was the datatype that the summary is applied to

    + +

    A summary attached to a variable using the --summary option, + has the same semantics that a custom format attached using the -f + option has: it stays attached till you attach a new one, or till you let + your program run again.

    +
    From gclayton at apple.com Thu Jul 14 22:27:12 2011 From: gclayton at apple.com (Greg Clayton) Date: Fri, 15 Jul 2011 03:27:12 -0000 Subject: [Lldb-commits] [lldb] r135240 - in /lldb/trunk/source/Plugins/Process/MacOSX-Kernel: ./ CommunicationKDP.cpp CommunicationKDP.h ProcessKDP.cpp ProcessKDP.h ProcessKDPLog.cpp ProcessKDPLog.h Message-ID: <20110715032712.84FB72A6C12C@llvm.org> Author: gclayton Date: Thu Jul 14 22:27:12 2011 New Revision: 135240 URL: http://llvm.org/viewvc/llvm-project?rev=135240&view=rev Log: Hollowed out process plug-in to do KDP darwin kernel debugging. Added: lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ lldb/trunk/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp lldb/trunk/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.h lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDPLog.cpp lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDPLog.h Added: lldb/trunk/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp?rev=135240&view=auto ============================================================================== --- lldb/trunk/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp (added) +++ lldb/trunk/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp Thu Jul 14 22:27:12 2011 @@ -0,0 +1,403 @@ +//===-- CommunicationKDP.cpp ------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + + +#include "CommunicationKDP.h" + +// C Includes +#include +#include + +// C++ Includes +// Other libraries and framework includes +#include "lldb/Core/Log.h" +#include "lldb/Core/StreamString.h" +#include "lldb/Host/FileSpec.h" +#include "lldb/Host/Host.h" +#include "lldb/Host/TimeValue.h" +#include "lldb/Target/Process.h" +#include "Utility/StringExtractor.h" + +// Project includes +#include "ProcessKDPLog.h" + +#define DEBUGSERVER_BASENAME "debugserver" + +using namespace lldb; +using namespace lldb_private; + +//---------------------------------------------------------------------- +// CommunicationKDP constructor +//---------------------------------------------------------------------- +CommunicationKDP::CommunicationKDP (const char *comm_name) : + Communication(comm_name), + m_packet_timeout (1), + m_sequence_mutex (Mutex::eMutexTypeRecursive), + m_public_is_running (false), + m_private_is_running (false), + m_send_acks (true) +{ +} + +//---------------------------------------------------------------------- +// Destructor +//---------------------------------------------------------------------- +CommunicationKDP::~CommunicationKDP() +{ + if (IsConnected()) + { + Disconnect(); + } +} + +char +CommunicationKDP::CalculcateChecksum (const char *payload, size_t payload_length) +{ + int checksum = 0; + + // We only need to compute the checksum if we are sending acks + if (GetSendAcks ()) + { + for (size_t i = 0; i < payload_length; ++i) + checksum += payload[i]; + } + return checksum & 255; +} + +size_t +CommunicationKDP::SendAck () +{ + LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PACKETS)); + if (log) + log->Printf ("send packet: +"); + ConnectionStatus status = eConnectionStatusSuccess; + char ack_char = '+'; + return Write (&ack_char, 1, status, NULL); +} + +size_t +CommunicationKDP::SendNack () +{ + LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PACKETS)); + if (log) + log->Printf ("send packet: -"); + ConnectionStatus status = eConnectionStatusSuccess; + char nack_char = '-'; + return Write (&nack_char, 1, status, NULL); +} + +size_t +CommunicationKDP::SendPacket (lldb_private::StreamString &payload) +{ + Mutex::Locker locker(m_sequence_mutex); + const std::string &p (payload.GetString()); + return SendPacketNoLock (p.c_str(), p.size()); +} + +size_t +CommunicationKDP::SendPacket (const char *payload) +{ + Mutex::Locker locker(m_sequence_mutex); + return SendPacketNoLock (payload, ::strlen (payload)); +} + +size_t +CommunicationKDP::SendPacket (const char *payload, size_t payload_length) +{ + Mutex::Locker locker(m_sequence_mutex); + return SendPacketNoLock (payload, payload_length); +} + +size_t +CommunicationKDP::SendPacketNoLock (const char *payload, size_t payload_length) +{ + if (IsConnected()) + { + StreamString packet(0, 4, eByteOrderBig); + + packet.PutChar('$'); + packet.Write (payload, payload_length); + packet.PutChar('#'); + packet.PutHex8(CalculcateChecksum (payload, payload_length)); + + LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PACKETS)); + if (log) + log->Printf ("send packet: %.*s", (int)packet.GetSize(), packet.GetData()); + ConnectionStatus status = eConnectionStatusSuccess; + size_t bytes_written = Write (packet.GetData(), packet.GetSize(), status, NULL); + if (bytes_written == packet.GetSize()) + { + if (GetSendAcks ()) + { + if (GetAck () != '+') + { + printf("get ack failed..."); + return 0; + } + } + } + else + { + LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PACKETS)); + if (log) + log->Printf ("error: failed to send packet: %.*s", (int)packet.GetSize(), packet.GetData()); + } + return bytes_written; + } + return 0; +} + +char +CommunicationKDP::GetAck () +{ + StringExtractor packet; + if (WaitForPacketWithTimeoutMicroSeconds (packet, GetPacketTimeoutInMicroSeconds ()) == 1) + return packet.GetChar(); + return 0; +} + +bool +CommunicationKDP::GetSequenceMutex (Mutex::Locker& locker) +{ + return locker.TryLock (m_sequence_mutex.GetMutex()); +} + + +bool +CommunicationKDP::WaitForNotRunningPrivate (const TimeValue *timeout_ptr) +{ + return m_private_is_running.WaitForValueEqualTo (false, timeout_ptr, NULL); +} + +size_t +CommunicationKDP::WaitForPacketWithTimeoutMicroSeconds (StringExtractor &packet, uint32_t timeout_usec) +{ + Mutex::Locker locker(m_sequence_mutex); + return WaitForPacketWithTimeoutMicroSecondsNoLock (packet, timeout_usec); +} + +size_t +CommunicationKDP::WaitForPacketWithTimeoutMicroSecondsNoLock (StringExtractor &packet, uint32_t timeout_usec) +{ + uint8_t buffer[8192]; + Error error; + + LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PACKETS | KDP_LOG_VERBOSE)); + + // Check for a packet from our cache first without trying any reading... + if (CheckForPacket (NULL, 0, packet)) + return packet.GetStringRef().size(); + + bool timed_out = false; + while (IsConnected() && !timed_out) + { + lldb::ConnectionStatus status; + size_t bytes_read = Read (buffer, sizeof(buffer), timeout_usec, status, &error); + + if (log) + log->Printf ("%s: Read (buffer, (sizeof(buffer), timeout_usec = 0x%x, status = %s, error = %s) => bytes_read = %zu", + __PRETTY_FUNCTION__, + timeout_usec, + Communication::ConnectionStatusAsCString (status), + error.AsCString(), + bytes_read); + + if (bytes_read > 0) + { + if (CheckForPacket (buffer, bytes_read, packet)) + return packet.GetStringRef().size(); + } + else + { + switch (status) + { + case eConnectionStatusTimedOut: + timed_out = true; + break; + case eConnectionStatusSuccess: + //printf ("status = success but error = %s\n", error.AsCString("")); + break; + + case eConnectionStatusEndOfFile: + case eConnectionStatusNoConnection: + case eConnectionStatusLostConnection: + case eConnectionStatusError: + Disconnect(); + break; + } + } + } + packet.Clear (); + return 0; +} + +bool +CommunicationKDP::CheckForPacket (const uint8_t *src, size_t src_len, StringExtractor &packet) +{ + // Put the packet data into the buffer in a thread safe fashion + Mutex::Locker locker(m_bytes_mutex); + + LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PACKETS)); + + if (src && src_len > 0) + { + if (log && log->GetVerbose()) + { + StreamString s; + log->Printf ("CommunicationKDP::%s adding %u bytes: %.*s", + __FUNCTION__, + (uint32_t)src_len, + (uint32_t)src_len, + src); + } + m_bytes.append ((const char *)src, src_len); + } + + // Parse up the packets into gdb remote packets + if (!m_bytes.empty()) + { + // end_idx must be one past the last valid packet byte. Start + // it off with an invalid value that is the same as the current + // index. + size_t content_start = 0; + size_t content_length = 0; + size_t total_length = 0; + size_t checksum_idx = std::string::npos; + + switch (m_bytes[0]) + { + case '+': // Look for ack + case '-': // Look for cancel + case '\x03': // ^C to halt target + content_length = total_length = 1; // The command is one byte long... + break; + + case '$': + // Look for a standard gdb packet? + { + size_t hash_pos = m_bytes.find('#'); + if (hash_pos != std::string::npos) + { + if (hash_pos + 2 < m_bytes.size()) + { + checksum_idx = hash_pos + 1; + // Skip the dollar sign + content_start = 1; + // Don't include the # in the content or the $ in the content length + content_length = hash_pos - 1; + + total_length = hash_pos + 3; // Skip the # and the two hex checksum bytes + } + else + { + // Checksum bytes aren't all here yet + content_length = std::string::npos; + } + } + } + break; + + default: + { + // We have an unexpected byte and we need to flush all bad + // data that is in m_bytes, so we need to find the first + // byte that is a '+' (ACK), '-' (NACK), \x03 (CTRL+C interrupt), + // or '$' character (start of packet header) or of course, + // the end of the data in m_bytes... + const size_t bytes_len = m_bytes.size(); + bool done = false; + uint32_t idx; + for (idx = 1; !done && idx < bytes_len; ++idx) + { + switch (m_bytes[idx]) + { + case '+': + case '-': + case '\x03': + case '$': + done = true; + break; + + default: + break; + } + } + if (log) + log->Printf ("CommunicationKDP::%s tossing %u junk bytes: '%.*s'", + __FUNCTION__, idx, idx, m_bytes.c_str()); + m_bytes.erase(0, idx); + } + break; + } + + if (content_length == std::string::npos) + { + packet.Clear(); + return false; + } + else if (total_length > 0) + { + + // We have a valid packet... + assert (content_length <= m_bytes.size()); + assert (total_length <= m_bytes.size()); + assert (content_length <= total_length); + + bool success = true; + std::string &packet_str = packet.GetStringRef(); + packet_str.assign (m_bytes, content_start, content_length); + if (m_bytes[0] == '$') + { + assert (checksum_idx < m_bytes.size()); + if (::isxdigit (m_bytes[checksum_idx+0]) || + ::isxdigit (m_bytes[checksum_idx+1])) + { + if (GetSendAcks ()) + { + const char *packet_checksum_cstr = &m_bytes[checksum_idx]; + char packet_checksum = strtol (packet_checksum_cstr, NULL, 16); + char actual_checksum = CalculcateChecksum (packet_str.c_str(), packet_str.size()); + success = packet_checksum == actual_checksum; + if (!success) + { + if (log) + log->Printf ("error: checksum mismatch: %.*s expected 0x%2.2x, got 0x%2.2x", + (int)(total_length), + m_bytes.c_str(), + (uint8_t)packet_checksum, + (uint8_t)actual_checksum); + } + // Send the ack or nack if needed + if (!success) + SendNack(); + else + SendAck(); + } + if (success) + { + if (log) + log->Printf ("read packet: %.*s", (int)(total_length), m_bytes.c_str()); + } + } + else + { + success = false; + if (log) + log->Printf ("error: invalid checksum in packet: '%s'\n", (int)(total_length), m_bytes.c_str()); + } + } + m_bytes.erase(0, total_length); + packet.SetFilePos(0); + return success; + } + } + packet.Clear(); + return false; +} + Added: lldb/trunk/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.h?rev=135240&view=auto ============================================================================== --- lldb/trunk/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.h (added) +++ lldb/trunk/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.h Thu Jul 14 22:27:12 2011 @@ -0,0 +1,152 @@ +//===-- CommunicationKDP.h --------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_CommunicationKDP_h_ +#define liblldb_CommunicationKDP_h_ + +// C Includes +// C++ Includes +#include +#include + +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-private.h" +#include "lldb/Core/Communication.h" +#include "lldb/Core/Listener.h" +#include "lldb/Host/Mutex.h" +#include "lldb/Host/Predicate.h" +#include "lldb/Host/TimeValue.h" + +class StringExtractor; + +class CommunicationKDP : public lldb_private::Communication +{ +public: + enum + { + eBroadcastBitRunPacketSent = kLoUserBroadcastBit + }; + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + CommunicationKDP (const char *comm_name); + + virtual + ~CommunicationKDP(); + + size_t + SendPacket (const char *payload); + + size_t + SendPacket (const char *payload, + size_t payload_length); + + size_t + SendPacket (lldb_private::StreamString &response); + + // Wait for a packet within 'nsec' seconds + size_t + WaitForPacketWithTimeoutMicroSeconds (StringExtractor &response, + uint32_t usec); + + char + GetAck (); + + size_t + SendAck (); + + size_t + SendNack (); + + char + CalculcateChecksum (const char *payload, + size_t payload_length); + + bool + GetSequenceMutex(lldb_private::Mutex::Locker& locker); + + bool + CheckForPacket (const uint8_t *src, + size_t src_len, + StringExtractor &packet); + bool + IsRunning() const + { + return m_public_is_running.GetValue(); + } + + bool + GetSendAcks () + { + return m_send_acks; + } + + //------------------------------------------------------------------ + // Set the global packet timeout. + // + // For clients, this is the timeout that gets used when sending + // packets and waiting for responses. For servers, this might not + // get used, and if it doesn't this should be moved to the + // CommunicationKDPClient. + //------------------------------------------------------------------ + uint32_t + SetPacketTimeout (uint32_t packet_timeout) + { + const uint32_t old_packet_timeout = m_packet_timeout; + m_packet_timeout = packet_timeout; + return old_packet_timeout; + } + + uint32_t + GetPacketTimeoutInMicroSeconds () const + { + return m_packet_timeout * lldb_private::TimeValue::MicroSecPerSec; + } + //------------------------------------------------------------------ + // Start a debugserver instance on the current host using the + // supplied connection URL. + //------------------------------------------------------------------ + lldb_private::Error + StartDebugserverProcess (const char *connect_url, + const char *unix_socket_name, + lldb_private::ProcessLaunchInfo &launch_info); + + +protected: + typedef std::list packet_collection; + + size_t + SendPacketNoLock (const char *payload, + size_t payload_length); + + size_t + WaitForPacketWithTimeoutMicroSecondsNoLock (StringExtractor &response, + uint32_t timeout_usec); + + bool + WaitForNotRunningPrivate (const lldb_private::TimeValue *timeout_ptr); + + //------------------------------------------------------------------ + // Classes that inherit from CommunicationKDP can see and modify these + //------------------------------------------------------------------ + uint32_t m_packet_timeout; + lldb_private::Mutex m_sequence_mutex; // Restrict access to sending/receiving packets to a single thread at a time + lldb_private::Predicate m_public_is_running; + lldb_private::Predicate m_private_is_running; + bool m_send_acks; + +private: + //------------------------------------------------------------------ + // For CommunicationKDP only + //------------------------------------------------------------------ + DISALLOW_COPY_AND_ASSIGN (CommunicationKDP); +}; + +#endif // liblldb_CommunicationKDP_h_ Added: lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp?rev=135240&view=auto ============================================================================== --- lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp (added) +++ lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp Thu Jul 14 22:27:12 2011 @@ -0,0 +1,725 @@ +//===-- ProcessKDP.cpp ------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// C Includes +#include +#include + +// C++ Includes +// Other libraries and framework includes +#include "lldb/Core/PluginManager.h" +#include "lldb/Core/State.h" +#include "lldb/Host/Host.h" + +// Project includes +#include "ProcessKDP.h" +#include "ProcessKDPLog.h" +//#include "ThreadKDP.h" +#include "StopInfoMachException.h" + +using namespace lldb; +using namespace lldb_private; + +const char * +ProcessKDP::GetPluginNameStatic() +{ + return "kdp-remote"; +} + +const char * +ProcessKDP::GetPluginDescriptionStatic() +{ + return "KDP Remote protocol based debugging plug-in for darwin kernel debugging."; +} + +void +ProcessKDP::Terminate() +{ + PluginManager::UnregisterPlugin (ProcessKDP::CreateInstance); +} + + +Process* +ProcessKDP::CreateInstance (Target &target, Listener &listener) +{ + return new ProcessKDP (target, listener); +} + +bool +ProcessKDP::CanDebug(Target &target) +{ + // For now we are just making sure the file exists for a given module + ModuleSP exe_module_sp(target.GetExecutableModule()); + if (exe_module_sp.get()) + { + const llvm::Triple &triple_ref = target.GetArchitecture().GetTriple(); + if (triple_ref.getOS() == llvm::Triple::Darwin && + triple_ref.getVendor() == llvm::Triple::Apple) + { + + ObjectFile *exe_objfile = exe_module_sp->GetObjectFile(); + if (exe_objfile->GetType() == ObjectFile::eTypeExecutable && + exe_objfile->GetStrata() == ObjectFile::eStrataKernel) + return true; + } + } + return false; +} + +//---------------------------------------------------------------------- +// ProcessKDP constructor +//---------------------------------------------------------------------- +ProcessKDP::ProcessKDP(Target& target, Listener &listener) : + Process (target, listener), + m_comm("lldb.process.kdp-remote.communication"), + m_async_broadcaster ("lldb.process.kdp-remote.async-broadcaster"), + m_async_thread (LLDB_INVALID_HOST_THREAD) +{ +// m_async_broadcaster.SetEventName (eBroadcastBitAsyncThreadShouldExit, "async thread should exit"); +// m_async_broadcaster.SetEventName (eBroadcastBitAsyncContinue, "async thread continue"); +} + +//---------------------------------------------------------------------- +// Destructor +//---------------------------------------------------------------------- +ProcessKDP::~ProcessKDP() +{ + Clear(); +} + +//---------------------------------------------------------------------- +// PluginInterface +//---------------------------------------------------------------------- +const char * +ProcessKDP::GetPluginName() +{ + return "Process debugging plug-in that uses the Darwin KDP remote protocol"; +} + +const char * +ProcessKDP::GetShortPluginName() +{ + return GetPluginNameStatic(); +} + +uint32_t +ProcessKDP::GetPluginVersion() +{ + return 1; +} + +Error +ProcessKDP::WillLaunch (Module* module) +{ + Error error; + error.SetErrorString ("launching not supported in kdp-remote plug-in"); + return error; +} + +Error +ProcessKDP::WillAttachToProcessWithID (lldb::pid_t pid) +{ + Error error; + error.SetErrorString ("attaching to a by process ID not supported in kdp-remote plug-in"); + return error; +} + +Error +ProcessKDP::WillAttachToProcessWithName (const char *process_name, bool wait_for_launch) +{ + Error error; + error.SetErrorString ("attaching to a by process name not supported in kdp-remote plug-in"); + return error; +} + +Error +ProcessKDP::DoConnectRemote (const char *remote_url) +{ + // TODO: fill in the remote connection to the remote KDP here! + Error error; + error.SetErrorString ("attaching to a by process name not supported in kdp-remote plug-in"); + return error; +} + +//---------------------------------------------------------------------- +// Process Control +//---------------------------------------------------------------------- +Error +ProcessKDP::DoLaunch (Module* module, + char const *argv[], + char const *envp[], + uint32_t launch_flags, + const char *stdin_path, + const char *stdout_path, + const char *stderr_path, + const char *working_dir) +{ + Error error; + error.SetErrorString ("launching not supported in kdp-remote plug-in"); + return error; +} + + +Error +ProcessKDP::DoAttachToProcessWithID (lldb::pid_t attach_pid) +{ + Error error; + error.SetErrorString ("attach to process by ID is not suppported in kdp remote debugging"); + return error; +} + +size_t +ProcessKDP::AttachInputReaderCallback (void *baton, + InputReader *reader, + lldb::InputReaderAction notification, + const char *bytes, + size_t bytes_len) +{ + if (notification == eInputReaderGotToken) + { +// ProcessKDP *process = (ProcessKDP *)baton; +// if (process->m_waiting_for_attach) +// process->m_waiting_for_attach = false; + reader->SetIsDone(true); + return 1; + } + return 0; +} + +Error +ProcessKDP::DoAttachToProcessWithName (const char *process_name, bool wait_for_launch) +{ + Error error; + error.SetErrorString ("attach to process by name is not suppported in kdp remote debugging"); + return error; +} + + +void +ProcessKDP::DidAttach () +{ + LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PROCESS)); + if (log) + log->Printf ("ProcessKDP::DidLaunch()"); + if (GetID() != LLDB_INVALID_PROCESS_ID) + { + // TODO: figure out the register context that we will use + } +} + +Error +ProcessKDP::WillResume () +{ + return Error(); +} + +Error +ProcessKDP::DoResume () +{ + Error error; + error.SetErrorString ("ProcessKDP::DoResume () is not implemented yet"); + return error; +} + +uint32_t +ProcessKDP::UpdateThreadListIfNeeded () +{ + // locker will keep a mutex locked until it goes out of scope + LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_THREAD)); + if (log && log->GetMask().Test(KDP_LOG_VERBOSE)) + log->Printf ("ProcessKDP::%s (pid = %i)", __FUNCTION__, GetID()); + + Mutex::Locker locker (m_thread_list.GetMutex ()); + // TODO: get the thread list here! + const uint32_t stop_id = GetStopID(); + if (m_thread_list.GetSize(false) == 0 || stop_id != m_thread_list.GetStopID()) + { + // Update the thread list's stop id immediately so we don't recurse into this function. +// ThreadList curr_thread_list (this); +// curr_thread_list.SetStopID(stop_id); +// +// std::vector thread_ids; +// bool sequence_mutex_unavailable = false; +// const size_t num_thread_ids = m_comm.GetCurrentThreadIDs (thread_ids, sequence_mutex_unavailable); +// if (num_thread_ids > 0) +// { +// for (size_t i=0; iPrintf ("ProcessKDP::InterruptIfRunning(discard_thread_plans=%i, catch_stop_event=%i) is_running=%i", + discard_thread_plans, + catch_stop_event, + is_running); + + if (discard_thread_plans) + { + if (log) + log->Printf ("ProcessKDP::InterruptIfRunning() discarding all thread plans"); + m_thread_list.DiscardThreadPlans(); + } + if (is_running) + { + if (catch_stop_event) + { + if (log) + log->Printf ("ProcessKDP::InterruptIfRunning() pausing private state thread"); + PausePrivateStateThread(); + paused_private_state_thread = true; + } + + bool timed_out = false; +// bool sent_interrupt = false; + Mutex::Locker locker; + + // TODO: implement halt in CommunicationKDP +// if (!m_comm.SendInterrupt (locker, 1, sent_interrupt, timed_out)) +// { +// if (timed_out) +// error.SetErrorString("timed out sending interrupt packet"); +// else +// error.SetErrorString("unknown error sending interrupt packet"); +// if (paused_private_state_thread) +// ResumePrivateStateThread(); +// return error; +// } + + if (catch_stop_event) + { + // LISTEN HERE + TimeValue timeout_time; + timeout_time = TimeValue::Now(); + timeout_time.OffsetWithSeconds(5); + StateType state = WaitForStateChangedEventsPrivate (&timeout_time, stop_event_sp); + + timed_out = state == eStateInvalid; + if (log) + log->Printf ("ProcessKDP::InterruptIfRunning() catch stop event: state = %s, timed-out=%i", StateAsCString(state), timed_out); + + if (timed_out) + error.SetErrorString("unable to verify target stopped"); + } + + if (paused_private_state_thread) + { + if (log) + log->Printf ("ProcessKDP::InterruptIfRunning() resuming private state thread"); + ResumePrivateStateThread(); + } + } + return error; +} + +Error +ProcessKDP::WillDetach () +{ + LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS)); + if (log) + log->Printf ("ProcessKDP::WillDetach()"); + + bool discard_thread_plans = true; + bool catch_stop_event = true; + EventSP event_sp; + return InterruptIfRunning (discard_thread_plans, catch_stop_event, event_sp); +} + +Error +ProcessKDP::DoDetach() +{ + Error error; + LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS)); + if (log) + log->Printf ("ProcessKDP::DoDetach()"); + + DisableAllBreakpointSites (); + + m_thread_list.DiscardThreadPlans(); + + size_t response_size = m_comm.SendPacket ("D", 1); + if (log) + { + if (response_size) + log->PutCString ("ProcessKDP::DoDetach() detach packet sent successfully"); + else + log->PutCString ("ProcessKDP::DoDetach() detach packet send failed"); + } + // Sleep for one second to let the process get all detached... + StopAsyncThread (); + + m_comm.StopReadThread(); + m_comm.Disconnect(); // Disconnect from the debug server. + + SetPrivateState (eStateDetached); + ResumePrivateStateThread(); + + //KillDebugserverProcess (); + return error; +} + +Error +ProcessKDP::DoDestroy () +{ + Error error; + LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS)); + if (log) + log->Printf ("ProcessKDP::DoDestroy()"); + + // Interrupt if our inferior is running... + if (m_comm.IsConnected()) + { + if (m_public_state.GetValue() == eStateAttaching) + { + // We are being asked to halt during an attach. We need to just close + // our file handle and debugserver will go away, and we can be done... + m_comm.Disconnect(); + } + else + { + + StringExtractor response; + // TODO: Send kill packet? + SetExitStatus(SIGABRT, NULL); + } + } + StopAsyncThread (); + m_comm.StopReadThread(); + m_comm.Disconnect(); // Disconnect from the debug server. + return error; +} + +//------------------------------------------------------------------ +// Process Queries +//------------------------------------------------------------------ + +bool +ProcessKDP::IsAlive () +{ + return m_comm.IsConnected() && m_private_state.GetValue() != eStateExited; +} + +//------------------------------------------------------------------ +// Process Memory +//------------------------------------------------------------------ +size_t +ProcessKDP::DoReadMemory (addr_t addr, void *buf, size_t size, Error &error) +{ + error.SetErrorString ("ProcessKDP::DoReadMemory not implemented"); + return 0; +} + +size_t +ProcessKDP::DoWriteMemory (addr_t addr, const void *buf, size_t size, Error &error) +{ + error.SetErrorString ("ProcessKDP::DoReadMemory not implemented"); + return 0; +} + +lldb::addr_t +ProcessKDP::DoAllocateMemory (size_t size, uint32_t permissions, Error &error) +{ + error.SetErrorString ("memory allocation not suppported in kdp remote debugging"); + return LLDB_INVALID_ADDRESS; +} + +Error +ProcessKDP::DoDeallocateMemory (lldb::addr_t addr) +{ + Error error; + error.SetErrorString ("memory deallocation not suppported in kdp remote debugging"); + return error; +} + +Error +ProcessKDP::EnableBreakpoint (BreakpointSite *bp_site) +{ + return EnableSoftwareBreakpoint (bp_site); +} + +Error +ProcessKDP::DisableBreakpoint (BreakpointSite *bp_site) +{ + return DisableSoftwareBreakpoint (bp_site); +} + +Error +ProcessKDP::EnableWatchpoint (WatchpointLocation *wp) +{ + Error error; + error.SetErrorString ("watchpoints are not suppported in kdp remote debugging"); + return error; +} + +Error +ProcessKDP::DisableWatchpoint (WatchpointLocation *wp) +{ + Error error; + error.SetErrorString ("watchpoints are not suppported in kdp remote debugging"); + return error; +} + +void +ProcessKDP::Clear() +{ + Mutex::Locker locker (m_thread_list.GetMutex ()); + m_thread_list.Clear(); +} + +Error +ProcessKDP::DoSignal (int signo) +{ + Error error; + error.SetErrorString ("sending signals is not suppported in kdp remote debugging"); + return error; +} + +void +ProcessKDP::Initialize() +{ + static bool g_initialized = false; + + if (g_initialized == false) + { + g_initialized = true; + PluginManager::RegisterPlugin (GetPluginNameStatic(), + GetPluginDescriptionStatic(), + CreateInstance); + + Log::Callbacks log_callbacks = { + ProcessKDPLog::DisableLog, + ProcessKDPLog::EnableLog, + ProcessKDPLog::ListLogCategories + }; + + Log::RegisterLogChannel (ProcessKDP::GetPluginNameStatic(), log_callbacks); + } +} + +bool +ProcessKDP::StartAsyncThread () +{ + LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS)); + + if (log) + log->Printf ("ProcessKDP::%s ()", __FUNCTION__); + + // Create a thread that watches our internal state and controls which + // events make it to clients (into the DCProcess event queue). + m_async_thread = Host::ThreadCreate ("", ProcessKDP::AsyncThread, this, NULL); + return IS_VALID_LLDB_HOST_THREAD(m_async_thread); +} + +void +ProcessKDP::StopAsyncThread () +{ + LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PROCESS)); + + if (log) + log->Printf ("ProcessKDP::%s ()", __FUNCTION__); + + m_async_broadcaster.BroadcastEvent (eBroadcastBitAsyncThreadShouldExit); + + // Stop the stdio thread + if (IS_VALID_LLDB_HOST_THREAD(m_async_thread)) + { + Host::ThreadJoin (m_async_thread, NULL, NULL); + } +} + + +void * +ProcessKDP::AsyncThread (void *arg) +{ + ProcessKDP *process = (ProcessKDP*) arg; + + LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PROCESS)); + if (log) + log->Printf ("ProcessKDP::%s (arg = %p, pid = %i) thread starting...", __FUNCTION__, arg, process->GetID()); + + Listener listener ("ProcessKDP::AsyncThread"); + EventSP event_sp; + const uint32_t desired_event_mask = eBroadcastBitAsyncContinue | + eBroadcastBitAsyncThreadShouldExit; + + if (listener.StartListeningForEvents (&process->m_async_broadcaster, desired_event_mask) == desired_event_mask) + { + listener.StartListeningForEvents (&process->m_comm, Communication::eBroadcastBitReadThreadDidExit); + + bool done = false; + while (!done) + { + if (log) + log->Printf ("ProcessKDP::%s (arg = %p, pid = %i) listener.WaitForEvent (NULL, event_sp)...", __FUNCTION__, arg, process->GetID()); + if (listener.WaitForEvent (NULL, event_sp)) + { + const uint32_t event_type = event_sp->GetType(); + if (event_sp->BroadcasterIs (&process->m_async_broadcaster)) + { + if (log) + log->Printf ("ProcessKDP::%s (arg = %p, pid = %i) Got an event of type: %d...", __FUNCTION__, arg, process->GetID(), event_type); + + switch (event_type) + { + case eBroadcastBitAsyncContinue: + { + const EventDataBytes *continue_packet = EventDataBytes::GetEventDataFromEvent(event_sp.get()); + + if (continue_packet) + { + // TODO: do continue support here + +// const char *continue_cstr = (const char *)continue_packet->GetBytes (); +// const size_t continue_cstr_len = continue_packet->GetByteSize (); +// if (log) +// log->Printf ("ProcessKDP::%s (arg = %p, pid = %i) got eBroadcastBitAsyncContinue: %s", __FUNCTION__, arg, process->GetID(), continue_cstr); +// +// if (::strstr (continue_cstr, "vAttach") == NULL) +// process->SetPrivateState(eStateRunning); +// StringExtractor response; +// StateType stop_state = process->GetCommunication().SendContinuePacketAndWaitForResponse (process, continue_cstr, continue_cstr_len, response); +// +// switch (stop_state) +// { +// case eStateStopped: +// case eStateCrashed: +// case eStateSuspended: +// process->m_last_stop_packet = response; +// process->SetPrivateState (stop_state); +// break; +// +// case eStateExited: +// process->m_last_stop_packet = response; +// response.SetFilePos(1); +// process->SetExitStatus(response.GetHexU8(), NULL); +// done = true; +// break; +// +// case eStateInvalid: +// process->SetExitStatus(-1, "lost connection"); +// break; +// +// default: +// process->SetPrivateState (stop_state); +// break; +// } + } + } + break; + + case eBroadcastBitAsyncThreadShouldExit: + if (log) + log->Printf ("ProcessKDP::%s (arg = %p, pid = %i) got eBroadcastBitAsyncThreadShouldExit...", __FUNCTION__, arg, process->GetID()); + done = true; + break; + + default: + if (log) + log->Printf ("ProcessKDP::%s (arg = %p, pid = %i) got unknown event 0x%8.8x", __FUNCTION__, arg, process->GetID(), event_type); + done = true; + break; + } + } + else if (event_sp->BroadcasterIs (&process->m_comm)) + { + if (event_type & Communication::eBroadcastBitReadThreadDidExit) + { + process->SetExitStatus (-1, "lost connection"); + done = true; + } + } + } + else + { + if (log) + log->Printf ("ProcessKDP::%s (arg = %p, pid = %i) listener.WaitForEvent (NULL, event_sp) => false", __FUNCTION__, arg, process->GetID()); + done = true; + } + } + } + + if (log) + log->Printf ("ProcessKDP::%s (arg = %p, pid = %i) thread exiting...", __FUNCTION__, arg, process->GetID()); + + process->m_async_thread = LLDB_INVALID_HOST_THREAD; + return NULL; +} + + Added: lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h?rev=135240&view=auto ============================================================================== --- lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h (added) +++ lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h Thu Jul 14 22:27:12 2011 @@ -0,0 +1,283 @@ +//===-- ProcessKDP.h --------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_ProcessKDP_h_ +#define liblldb_ProcessKDP_h_ + +// C Includes + +// C++ Includes +#include +#include + +// Other libraries and framework includes +#include "lldb/Core/ArchSpec.h" +#include "lldb/Core/Broadcaster.h" +#include "lldb/Core/Error.h" +#include "lldb/Core/InputReader.h" +#include "lldb/Core/StreamString.h" +#include "lldb/Core/StringList.h" +#include "lldb/Core/ThreadSafeValue.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/Thread.h" + +#include "CommunicationKDP.h" +#include "Utility/StringExtractor.h" + +class ThreadKDP; + +class ProcessKDP : public lldb_private::Process +{ +public: + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + static Process* + CreateInstance (lldb_private::Target& target, lldb_private::Listener &listener); + + static void + Initialize(); + + static void + Terminate(); + + static const char * + GetPluginNameStatic(); + + static const char * + GetPluginDescriptionStatic(); + + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + ProcessKDP(lldb_private::Target& target, lldb_private::Listener &listener); + + virtual + ~ProcessKDP(); + + //------------------------------------------------------------------ + // Check if a given Process + //------------------------------------------------------------------ + virtual bool + CanDebug (lldb_private::Target &target); + + // virtual uint32_t + // ListProcessesMatchingName (const char *name, lldb_private::StringList &matches, std::vector &pids); + + //------------------------------------------------------------------ + // Creating a new process, or attaching to an existing one + //------------------------------------------------------------------ + virtual lldb_private::Error + WillLaunch (lldb_private::Module* module); + + virtual lldb_private::Error + DoLaunch (lldb_private::Module* module, + char const *argv[], // Can be NULL + char const *envp[], // Can be NULL + uint32_t flags, + const char *stdin_path, // Can be NULL + const char *stdout_path, // Can be NULL + const char *stderr_path, // Can be NULL + const char *working_dir); // Can be NULL + + virtual lldb_private::Error + WillAttachToProcessWithID (lldb::pid_t pid); + + virtual lldb_private::Error + WillAttachToProcessWithName (const char *process_name, bool wait_for_launch); + + virtual lldb_private::Error + DoConnectRemote (const char *remote_url); + + virtual lldb_private::Error + DoAttachToProcessWithID (lldb::pid_t pid); + + virtual lldb_private::Error + DoAttachToProcessWithName (const char *process_name, bool wait_for_launch); + + virtual void + DidAttach (); + + //------------------------------------------------------------------ + // PluginInterface protocol + //------------------------------------------------------------------ + virtual const char * + GetPluginName(); + + virtual const char * + GetShortPluginName(); + + virtual uint32_t + GetPluginVersion(); + + //------------------------------------------------------------------ + // Process Control + //------------------------------------------------------------------ + virtual lldb_private::Error + WillResume (); + + virtual lldb_private::Error + DoResume (); + + virtual lldb_private::Error + DoHalt (bool &caused_stop); + + virtual lldb_private::Error + WillDetach (); + + virtual lldb_private::Error + DoDetach (); + + virtual lldb_private::Error + DoSignal (int signal); + + virtual lldb_private::Error + DoDestroy (); + + virtual void + RefreshStateAfterStop(); + + //------------------------------------------------------------------ + // Process Queries + //------------------------------------------------------------------ + virtual bool + IsAlive (); + + //------------------------------------------------------------------ + // Process Memory + //------------------------------------------------------------------ + virtual size_t + DoReadMemory (lldb::addr_t addr, void *buf, size_t size, lldb_private::Error &error); + + virtual size_t + DoWriteMemory (lldb::addr_t addr, const void *buf, size_t size, lldb_private::Error &error); + + virtual lldb::addr_t + DoAllocateMemory (size_t size, uint32_t permissions, lldb_private::Error &error); + + virtual lldb_private::Error + DoDeallocateMemory (lldb::addr_t ptr); + + //---------------------------------------------------------------------- + // Process Breakpoints + //---------------------------------------------------------------------- + virtual lldb_private::Error + EnableBreakpoint (lldb_private::BreakpointSite *bp_site); + + virtual lldb_private::Error + DisableBreakpoint (lldb_private::BreakpointSite *bp_site); + + //---------------------------------------------------------------------- + // Process Watchpoints + //---------------------------------------------------------------------- + virtual lldb_private::Error + EnableWatchpoint (lldb_private::WatchpointLocation *wp_loc); + + virtual lldb_private::Error + DisableWatchpoint (lldb_private::WatchpointLocation *wp_loc); + +protected: + friend class ThreadKDP; + friend class CommunicationKDP; + + //---------------------------------------------------------------------- + // Accessors + //---------------------------------------------------------------------- + bool + IsRunning ( lldb::StateType state ) + { + return state == lldb::eStateRunning || IsStepping(state); + } + + bool + IsStepping ( lldb::StateType state) + { + return state == lldb::eStateStepping; + } + + bool + CanResume ( lldb::StateType state) + { + return state == lldb::eStateStopped; + } + + bool + HasExited (lldb::StateType state) + { + return state == lldb::eStateExited; + } + + bool + ProcessIDIsValid ( ) const; + + // static void + // STDIOReadThreadBytesReceived (void *baton, const void *src, size_t src_len); + + // void + // AppendSTDOUT (const char* s, size_t len); + + void + Clear ( ); + + uint32_t + UpdateThreadListIfNeeded (); + + CommunicationKDP & + GetCommunication() + { + return m_comm; + } + + enum + { + eBroadcastBitAsyncContinue = (1 << 0), + eBroadcastBitAsyncThreadShouldExit = (1 << 1) + }; + + lldb_private::Error + InterruptIfRunning (bool discard_thread_plans, + bool catch_stop_event, + lldb::EventSP &stop_event_sp); + + //------------------------------------------------------------------ + /// Broadcaster event bits definitions. + //------------------------------------------------------------------ + CommunicationKDP m_comm; + lldb_private::Broadcaster m_async_broadcaster; + lldb::thread_t m_async_thread; + + bool + StartAsyncThread (); + + void + StopAsyncThread (); + + static void * + AsyncThread (void *arg); + + lldb::StateType + SetThreadStopInfo (StringExtractor& stop_packet); + + static size_t + AttachInputReaderCallback (void *baton, + lldb_private::InputReader *reader, + lldb::InputReaderAction notification, + const char *bytes, + size_t bytes_len); + +private: + //------------------------------------------------------------------ + // For ProcessKDP only + //------------------------------------------------------------------ + + DISALLOW_COPY_AND_ASSIGN (ProcessKDP); + +}; + +#endif // liblldb_ProcessKDP_h_ Added: lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDPLog.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDPLog.cpp?rev=135240&view=auto ============================================================================== --- lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDPLog.cpp (added) +++ lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDPLog.cpp Thu Jul 14 22:27:12 2011 @@ -0,0 +1,183 @@ +//===-- ProcessKDPLog.cpp ---------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "ProcessKDPLog.h" + +#include "lldb/Interpreter/Args.h" +#include "lldb/Core/StreamFile.h" + +#include "ProcessKDP.h" + +using namespace lldb; +using namespace lldb_private; + + +// We want to avoid global constructors where code needs to be run so here we +// control access to our static g_log_sp by hiding it in a singleton function +// that will construct the static g_lob_sp the first time this function is +// called. +static LogSP & +GetLog () +{ + static LogSP g_log_sp; + return g_log_sp; +} + +LogSP +ProcessKDPLog::GetLogIfAllCategoriesSet (uint32_t mask) +{ + LogSP log(GetLog ()); + if (log && mask) + { + uint32_t log_mask = log->GetMask().Get(); + if ((log_mask & mask) != mask) + return LogSP(); + } + return log; +} + +void +ProcessKDPLog::DisableLog (Args &args, Stream *feedback_strm) +{ + LogSP log (GetLog ()); + if (log) + { + uint32_t flag_bits = 0; + + const size_t argc = args.GetArgumentCount (); + if (argc > 0) + { + flag_bits = log->GetMask().Get(); + for (size_t i = 0; i < argc; ++i) + { + const char *arg = args.GetArgumentAtIndex (i); + + + if (::strcasecmp (arg, "all") == 0 ) flag_bits &= ~KDP_LOG_ALL; + else if (::strcasecmp (arg, "async") == 0 ) flag_bits &= ~KDP_LOG_ASYNC; + else if (::strncasecmp (arg, "break", 5) == 0 ) flag_bits &= ~KDP_LOG_BREAKPOINTS; + else if (::strncasecmp (arg, "comm", 4) == 0 ) flag_bits &= ~KDP_LOG_COMM; + else if (::strcasecmp (arg, "default") == 0 ) flag_bits &= ~KDP_LOG_DEFAULT; + else if (::strcasecmp (arg, "packets") == 0 ) flag_bits &= ~KDP_LOG_PACKETS; + else if (::strcasecmp (arg, "memory") == 0 ) flag_bits &= ~KDP_LOG_MEMORY; + else if (::strcasecmp (arg, "data-short") == 0 ) flag_bits &= ~KDP_LOG_MEMORY_DATA_SHORT; + else if (::strcasecmp (arg, "data-long") == 0 ) flag_bits &= ~KDP_LOG_MEMORY_DATA_LONG; + else if (::strcasecmp (arg, "process") == 0 ) flag_bits &= ~KDP_LOG_PROCESS; + else if (::strcasecmp (arg, "step") == 0 ) flag_bits &= ~KDP_LOG_STEP; + else if (::strcasecmp (arg, "thread") == 0 ) flag_bits &= ~KDP_LOG_THREAD; + else if (::strcasecmp (arg, "verbose") == 0 ) flag_bits &= ~KDP_LOG_VERBOSE; + else if (::strncasecmp (arg, "watch", 5) == 0 ) flag_bits &= ~KDP_LOG_WATCHPOINTS; + else + { + feedback_strm->Printf("error: unrecognized log category '%s'\n", arg); + ListLogCategories (feedback_strm); + } + + } + } + + if (flag_bits == 0) + GetLog ().reset(); + else + log->GetMask().Reset (flag_bits); + } + + return; +} + +LogSP +ProcessKDPLog::EnableLog (StreamSP &log_stream_sp, uint32_t log_options, Args &args, Stream *feedback_strm) +{ + // Try see if there already is a log - that way we can reuse its settings. + // We could reuse the log in toto, but we don't know that the stream is the same. + uint32_t flag_bits = 0; + LogSP log(GetLog ()); + if (log) + flag_bits = log->GetMask().Get(); + + // Now make a new log with this stream if one was provided + if (log_stream_sp) + { + log = make_shared(log_stream_sp); + GetLog () = log; + } + + if (log) + { + bool got_unknown_category = false; + const size_t argc = args.GetArgumentCount(); + for (size_t i=0; iPrintf("error: unrecognized log category '%s'\n", arg); + if (got_unknown_category == false) + { + got_unknown_category = true; + ListLogCategories (feedback_strm); + } + } + } + if (flag_bits == 0) + flag_bits = KDP_LOG_DEFAULT; + log->GetMask().Reset(flag_bits); + log->GetOptions().Reset(log_options); + } + return log; +} + +void +ProcessKDPLog::ListLogCategories (Stream *strm) +{ + strm->Printf("Logging categories for '%s':\n" + "\tall - turn on all available logging categories\n" + "\tasync - log asynchronous activity\n" + "\tbreak - log breakpoints\n" + "\tcommunication - log communication activity\n" + "\tdefault - enable the default set of logging categories for liblldb\n" + "\tpackets - log gdb remote packets\n" + "\tmemory - log memory reads and writes\n" + "\tdata-short - log memory bytes for memory reads and writes for short transactions only\n" + "\tdata-long - log memory bytes for memory reads and writes for all transactions\n" + "\tprocess - log process events and activities\n" + "\tthread - log thread events and activities\n" + "\tstep - log step related activities\n" + "\tverbose - enable verbose logging\n" + "\twatch - log watchpoint related activities\n", ProcessKDP::GetPluginNameStatic()); +} + + +void +ProcessKDPLog::LogIf (uint32_t mask, const char *format, ...) +{ + LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet (mask)); + if (log) + { + va_list args; + va_start (args, format); + log->VAPrintf (format, args); + va_end (args); + } +} Added: lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDPLog.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDPLog.h?rev=135240&view=auto ============================================================================== --- lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDPLog.h (added) +++ lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDPLog.h Thu Jul 14 22:27:12 2011 @@ -0,0 +1,54 @@ +//===-- ProcessKDPLog.h -----------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_ProcessKDPLog_h_ +#define liblldb_ProcessKDPLog_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes + +// Project includes +#include "lldb/Core/Log.h" + +#define KDP_LOG_VERBOSE (1u << 0) +#define KDP_LOG_PROCESS (1u << 1) +#define KDP_LOG_THREAD (1u << 2) +#define KDP_LOG_PACKETS (1u << 3) +#define KDP_LOG_MEMORY (1u << 4) // Log memory reads/writes calls +#define KDP_LOG_MEMORY_DATA_SHORT (1u << 5) // Log short memory reads/writes bytes +#define KDP_LOG_MEMORY_DATA_LONG (1u << 6) // Log all memory reads/writes bytes +#define KDP_LOG_BREAKPOINTS (1u << 7) +#define KDP_LOG_WATCHPOINTS (1u << 8) +#define KDP_LOG_STEP (1u << 9) +#define KDP_LOG_COMM (1u << 10) +#define KDP_LOG_ASYNC (1u << 11) +#define KDP_LOG_ALL (UINT32_MAX) +#define KDP_LOG_DEFAULT KDP_LOG_PACKETS + +class ProcessKDPLog +{ +public: + static lldb::LogSP + GetLogIfAllCategoriesSet(uint32_t mask = 0); + + static void + DisableLog (lldb_private::Args &args, lldb_private::Stream *feedback_strm); + + static lldb::LogSP + EnableLog (lldb::StreamSP &log_stream_sp, uint32_t log_options, lldb_private::Args &args, lldb_private::Stream *feedback_strm); + + static void + ListLogCategories (lldb_private::Stream *strm); + + static void + LogIf (uint32_t mask, const char *format, ...); +}; + +#endif // liblldb_ProcessKDPLog_h_ From gclayton at apple.com Fri Jul 15 11:31:38 2011 From: gclayton at apple.com (Greg Clayton) Date: Fri, 15 Jul 2011 16:31:38 -0000 Subject: [Lldb-commits] [lldb] r135277 - in /lldb/trunk: include/lldb/Core/ConnectionFileDescriptor.h lldb.xcodeproj/project.pbxproj source/Core/ConnectionFileDescriptor.cpp source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.h source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp Message-ID: <20110715163139.122902A6C12C@llvm.org> Author: gclayton Date: Fri Jul 15 11:31:38 2011 New Revision: 135277 URL: http://llvm.org/viewvc/llvm-project?rev=135277&view=rev Log: Added the ability to connect using "tcp://:" which is the same as the old "connect://:". Also added the ability to connect using "udp://:" which will open a connected datagram socket. I need to find a way to specify a non connected datagram socket as well. We might need to start setting some settings in the URL itself, maybe something like: udp://:?connected=yes udp://:?connected=no I am open to suggestions for URL settings. Also did more work on the KDP darwin kernel plug-in. Modified: lldb/trunk/include/lldb/Core/ConnectionFileDescriptor.h lldb/trunk/lldb.xcodeproj/project.pbxproj lldb/trunk/source/Core/ConnectionFileDescriptor.cpp lldb/trunk/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp lldb/trunk/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.h lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp Modified: lldb/trunk/include/lldb/Core/ConnectionFileDescriptor.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/ConnectionFileDescriptor.h?rev=135277&r1=135276&r2=135277&view=diff ============================================================================== --- lldb/trunk/include/lldb/Core/ConnectionFileDescriptor.h (original) +++ lldb/trunk/include/lldb/Core/ConnectionFileDescriptor.h Fri Jul 15 11:31:38 2011 @@ -61,8 +61,11 @@ SocketListen (uint16_t listen_port_num, Error *error_ptr); lldb::ConnectionStatus - SocketConnect (const char *host_and_port, Error *error_ptr); - + ConnectTCP (const char *host_and_port, Error *error_ptr); + + lldb::ConnectionStatus + ConnectUDP (const char *host_and_port, Error *error_ptr); + lldb::ConnectionStatus NamedSocketAccept (const char *socket_name, Error *error_ptr); Modified: lldb/trunk/lldb.xcodeproj/project.pbxproj URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lldb.xcodeproj/project.pbxproj?rev=135277&r1=135276&r2=135277&view=diff ============================================================================== --- lldb/trunk/lldb.xcodeproj/project.pbxproj (original) +++ lldb/trunk/lldb.xcodeproj/project.pbxproj Fri Jul 15 11:31:38 2011 @@ -16,6 +16,12 @@ 26368A3C126B697600E8659F /* darwin-debug.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26368A3B126B697600E8659F /* darwin-debug.cpp */; }; 26368AF7126B960500E8659F /* darwin-debug in Resources */ = {isa = PBXBuildFile; fileRef = 26579F68126A25920007C5CB /* darwin-debug */; }; 263E949F13661AEA00E7D1CE /* UnwindAssembly-x86.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 263E949D13661AE400E7D1CE /* UnwindAssembly-x86.cpp */; }; + 2642FBAE13D003B400ED6808 /* CommunicationKDP.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2642FBA813D003B400ED6808 /* CommunicationKDP.cpp */; }; + 2642FBAF13D003B400ED6808 /* CommunicationKDP.h in Headers */ = {isa = PBXBuildFile; fileRef = 2642FBA913D003B400ED6808 /* CommunicationKDP.h */; }; + 2642FBB013D003B400ED6808 /* ProcessKDP.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2642FBAA13D003B400ED6808 /* ProcessKDP.cpp */; }; + 2642FBB113D003B400ED6808 /* ProcessKDP.h in Headers */ = {isa = PBXBuildFile; fileRef = 2642FBAB13D003B400ED6808 /* ProcessKDP.h */; }; + 2642FBB213D003B400ED6808 /* ProcessKDPLog.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2642FBAC13D003B400ED6808 /* ProcessKDPLog.cpp */; }; + 2642FBB313D003B400ED6808 /* ProcessKDPLog.h in Headers */ = {isa = PBXBuildFile; fileRef = 2642FBAD13D003B400ED6808 /* ProcessKDPLog.h */; }; 264A97BF133918BC0017F0BE /* PlatformRemoteGDBServer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 264A97BD133918BC0017F0BE /* PlatformRemoteGDBServer.cpp */; }; 264D8D5013661BD7003A368F /* UnwindAssembly.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 264D8D4F13661BD7003A368F /* UnwindAssembly.cpp */; }; 265ABF6310F42EE900531910 /* DebugSymbols.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 265ABF6210F42EE900531910 /* DebugSymbols.framework */; }; @@ -640,6 +646,12 @@ 263FEDA5112CC1DA00E4C208 /* ThreadSafeSTLMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ThreadSafeSTLMap.h; path = include/lldb/Core/ThreadSafeSTLMap.h; sourceTree = ""; }; 26424E3C125986CB0016D82C /* ValueObjectConstResult.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ValueObjectConstResult.cpp; path = source/Core/ValueObjectConstResult.cpp; sourceTree = ""; }; 26424E3E125986D30016D82C /* ValueObjectConstResult.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ValueObjectConstResult.h; path = include/lldb/Core/ValueObjectConstResult.h; sourceTree = ""; }; + 2642FBA813D003B400ED6808 /* CommunicationKDP.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CommunicationKDP.cpp; sourceTree = ""; }; + 2642FBA913D003B400ED6808 /* CommunicationKDP.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CommunicationKDP.h; sourceTree = ""; }; + 2642FBAA13D003B400ED6808 /* ProcessKDP.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ProcessKDP.cpp; sourceTree = ""; }; + 2642FBAB13D003B400ED6808 /* ProcessKDP.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ProcessKDP.h; sourceTree = ""; }; + 2642FBAC13D003B400ED6808 /* ProcessKDPLog.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ProcessKDPLog.cpp; sourceTree = ""; }; + 2642FBAD13D003B400ED6808 /* ProcessKDPLog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ProcessKDPLog.h; sourceTree = ""; }; 264334381110F63100CDB6C6 /* ValueObjectRegister.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ValueObjectRegister.cpp; path = source/Core/ValueObjectRegister.cpp; sourceTree = ""; }; 2643343A1110F63C00CDB6C6 /* ValueObjectRegister.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ValueObjectRegister.h; path = include/lldb/Core/ValueObjectRegister.h; sourceTree = ""; }; 264723A511FA076E00DE380C /* CleanUp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CleanUp.h; path = include/lldb/Utility/CleanUp.h; sourceTree = ""; }; @@ -1483,6 +1495,7 @@ isa = PBXGroup; children = ( 4CEE62F71145F1C70064CF93 /* GDB Remote */, + 2642FBA713D003B400ED6808 /* MacOSX-Kernel */, 260C898B10F57C5600BB2B04 /* MacOSX-User */, 26B4666E11A2080F00CF6220 /* Utility */, ); @@ -1723,6 +1736,19 @@ name = API; sourceTree = ""; }; + 2642FBA713D003B400ED6808 /* MacOSX-Kernel */ = { + isa = PBXGroup; + children = ( + 2642FBA813D003B400ED6808 /* CommunicationKDP.cpp */, + 2642FBA913D003B400ED6808 /* CommunicationKDP.h */, + 2642FBAA13D003B400ED6808 /* ProcessKDP.cpp */, + 2642FBAB13D003B400ED6808 /* ProcessKDP.h */, + 2642FBAC13D003B400ED6808 /* ProcessKDPLog.cpp */, + 2642FBAD13D003B400ED6808 /* ProcessKDPLog.h */, + ); + path = "MacOSX-Kernel"; + sourceTree = ""; + }; 264A97BC133918A30017F0BE /* GDB Server */ = { isa = PBXGroup; children = ( @@ -2686,6 +2712,9 @@ buildActionMask = 2147483647; files = ( 9A9E1F0113980943005AC039 /* InputReaderStack.h in Headers */, + 2642FBAF13D003B400ED6808 /* CommunicationKDP.h in Headers */, + 2642FBB113D003B400ED6808 /* ProcessKDP.h in Headers */, + 2642FBB313D003B400ED6808 /* ProcessKDPLog.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -3279,6 +3308,9 @@ 26F4214413C6515B00E04E5E /* DynamicLoaderMacOSXKernel.cpp in Sources */, 94611EB213CCA4A4003A22AF /* RefCounter.cpp in Sources */, 94031A9E13CF486700DCFF3C /* InputReaderEZ.cpp in Sources */, + 2642FBAE13D003B400ED6808 /* CommunicationKDP.cpp in Sources */, + 2642FBB013D003B400ED6808 /* ProcessKDP.cpp in Sources */, + 2642FBB213D003B400ED6808 /* ProcessKDPLog.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; Modified: lldb/trunk/source/Core/ConnectionFileDescriptor.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/ConnectionFileDescriptor.cpp?rev=135277&r1=135276&r2=135277&view=diff ============================================================================== --- lldb/trunk/source/Core/ConnectionFileDescriptor.cpp (original) +++ lldb/trunk/source/Core/ConnectionFileDescriptor.cpp Fri Jul 15 11:31:38 2011 @@ -97,7 +97,15 @@ } else if (strstr(s, "connect://")) { - return SocketConnect (s + strlen("connect://"), error_ptr); + return ConnectTCP (s + strlen("connect://"), error_ptr); + } + else if (strstr(s, "tcp://")) + { + return ConnectTCP (s + strlen("tcp://"), error_ptr); + } + else if (strstr(s, "udp://")) + { + return ConnectUDP (s + strlen("udp://"), error_ptr); } else if (strstr(s, "fd://")) { @@ -626,10 +634,10 @@ } ConnectionStatus -ConnectionFileDescriptor::SocketConnect (const char *host_and_port, Error *error_ptr) +ConnectionFileDescriptor::ConnectTCP (const char *host_and_port, Error *error_ptr) { lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION, - "%p ConnectionFileDescriptor::SocketConnect (host/port = %s)", + "%p ConnectionFileDescriptor::ConnectTCP (host/port = %s)", this, host_and_port); Close (m_fd, NULL); m_is_socket = true; @@ -715,6 +723,96 @@ return eConnectionStatusSuccess; } +ConnectionStatus +ConnectionFileDescriptor::ConnectUDP (const char *host_and_port, Error *error_ptr) +{ + lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION, + "%p ConnectionFileDescriptor::ConnectUDP (host/port = %s)", + this, host_and_port); + Close (m_fd, NULL); + m_is_socket = true; + + RegularExpression regex ("([^:]+):([0-9]+)"); + if (regex.Execute (host_and_port, 2) == false) + { + if (error_ptr) + error_ptr->SetErrorStringWithFormat("invalid host:port specification: '%s'", host_and_port); + return eConnectionStatusError; + } + std::string host_str; + std::string port_str; + if (regex.GetMatchAtIndex (host_and_port, 1, host_str) == false || + regex.GetMatchAtIndex (host_and_port, 2, port_str) == false) + { + if (error_ptr) + error_ptr->SetErrorStringWithFormat("invalid host:port specification '%s'", host_and_port); + return eConnectionStatusError; + } + + int32_t port = Args::StringToSInt32 (port_str.c_str(), INT32_MIN); + if (port == INT32_MIN) + { + if (error_ptr) + error_ptr->SetErrorStringWithFormat("invalid port '%s'", port_str.c_str()); + return eConnectionStatusError; + } + // Create the socket + m_fd = ::socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP); + if (m_fd == -1) + { + if (error_ptr) + error_ptr->SetErrorToErrno(); + return eConnectionStatusError; + } + + m_should_close_fd = true; + + // Enable local address reuse + SetSocketOption (m_fd, SOL_SOCKET, SO_REUSEADDR, 1); + + struct sockaddr_in sa; + ::memset (&sa, 0, sizeof (sa)); + sa.sin_family = AF_INET; + sa.sin_port = htons (port); + + int inet_pton_result = ::inet_pton (AF_INET, host_str.c_str(), &sa.sin_addr); + + if (inet_pton_result <= 0) + { + struct hostent *host_entry = gethostbyname (host_str.c_str()); + if (host_entry) + host_str = ::inet_ntoa (*(struct in_addr *)*host_entry->h_addr_list); + inet_pton_result = ::inet_pton (AF_INET, host_str.c_str(), &sa.sin_addr); + if (inet_pton_result <= 0) + { + + if (error_ptr) + { + if (inet_pton_result == -1) + error_ptr->SetErrorToErrno(); + else + error_ptr->SetErrorStringWithFormat("invalid host string: '%s'", host_str.c_str()); + } + Close (m_fd, NULL); + return eConnectionStatusError; + } + } + + if (-1 == ::connect (m_fd, (const struct sockaddr *)&sa, sizeof(sa))) + { + if (error_ptr) + error_ptr->SetErrorToErrno(); + Close (m_fd, NULL); + return eConnectionStatusError; + } + + // Keep our TCP packets coming without any delays. + SetSocketOption (m_fd, IPPROTO_TCP, TCP_NODELAY, 1); + if (error_ptr) + error_ptr->Clear(); + return eConnectionStatusSuccess; +} + #if defined(__MINGW32__) || defined(__MINGW64__) typedef const char * set_socket_option_arg_type; typedef char * get_socket_option_arg_type; Modified: lldb/trunk/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp?rev=135277&r1=135276&r2=135277&view=diff ============================================================================== --- lldb/trunk/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp (original) +++ lldb/trunk/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp Fri Jul 15 11:31:38 2011 @@ -16,6 +16,7 @@ // C++ Includes // Other libraries and framework includes +#include "lldb/Core/DataExtractor.h" #include "lldb/Core/Log.h" #include "lldb/Core/StreamString.h" #include "lldb/Host/FileSpec.h" @@ -41,7 +42,9 @@ m_sequence_mutex (Mutex::eMutexTypeRecursive), m_public_is_running (false), m_private_is_running (false), - m_send_acks (true) + m_session_key (0), + m_request_sequence_id (0), + m_exception_sequence_id (0) { } @@ -56,110 +59,68 @@ } } -char -CommunicationKDP::CalculcateChecksum (const char *payload, size_t payload_length) -{ - int checksum = 0; - - // We only need to compute the checksum if we are sending acks - if (GetSendAcks ()) - { - for (size_t i = 0; i < payload_length; ++i) - checksum += payload[i]; - } - return checksum & 255; -} - -size_t -CommunicationKDP::SendAck () -{ - LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PACKETS)); - if (log) - log->Printf ("send packet: +"); - ConnectionStatus status = eConnectionStatusSuccess; - char ack_char = '+'; - return Write (&ack_char, 1, status, NULL); -} - -size_t -CommunicationKDP::SendNack () -{ - LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PACKETS)); - if (log) - log->Printf ("send packet: -"); - ConnectionStatus status = eConnectionStatusSuccess; - char nack_char = '-'; - return Write (&nack_char, 1, status, NULL); -} - -size_t -CommunicationKDP::SendPacket (lldb_private::StreamString &payload) +bool +CommunicationKDP::SendRequestPacket (const StreamString &request_packet) { Mutex::Locker locker(m_sequence_mutex); - const std::string &p (payload.GetString()); - return SendPacketNoLock (p.c_str(), p.size()); + return SendRequestPacketNoLock (request_packet); } -size_t -CommunicationKDP::SendPacket (const char *payload) -{ - Mutex::Locker locker(m_sequence_mutex); - return SendPacketNoLock (payload, ::strlen (payload)); +void +CommunicationKDP::MakeRequestPacketHeader (RequestType request_type, + StreamString &request_packet) +{ + request_packet.Clear(); + request_packet.PutHex32 (request_type); // Set the request type + request_packet.PutHex8 (ePacketTypeRequest); // Set the packet type + request_packet.PutHex8 (++m_request_sequence_id); // Sequence number + request_packet.PutHex16 (0); // Pad1 and Pad2 bytes + request_packet.PutHex32 (m_session_key); // Session key } -size_t -CommunicationKDP::SendPacket (const char *payload, size_t payload_length) -{ - Mutex::Locker locker(m_sequence_mutex); - return SendPacketNoLock (payload, payload_length); -} -size_t -CommunicationKDP::SendPacketNoLock (const char *payload, size_t payload_length) +bool +CommunicationKDP::SendRequestPacketNoLock (const StreamString &request_packet) { if (IsConnected()) { - StreamString packet(0, 4, eByteOrderBig); - - packet.PutChar('$'); - packet.Write (payload, payload_length); - packet.PutChar('#'); - packet.PutHex8(CalculcateChecksum (payload, payload_length)); + const char *packet_data = request_packet.GetData(); + const size_t packet_size = request_packet.GetSize(); LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PACKETS)); if (log) - log->Printf ("send packet: %.*s", (int)packet.GetSize(), packet.GetData()); - ConnectionStatus status = eConnectionStatusSuccess; - size_t bytes_written = Write (packet.GetData(), packet.GetSize(), status, NULL); - if (bytes_written == packet.GetSize()) - { - if (GetSendAcks ()) - { - if (GetAck () != '+') - { - printf("get ack failed..."); - return 0; - } - } - } - else { - LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PACKETS)); - if (log) - log->Printf ("error: failed to send packet: %.*s", (int)packet.GetSize(), packet.GetData()); + StreamString log_strm; + DataExtractor data (packet_data, + packet_size, + request_packet.GetByteOrder(), + request_packet.GetAddressByteSize()); + data.Dump (&log_strm, + 0, + eFormatBytes, + 1, + packet_size, + 32, // Num bytes per line + 0, // Base address + 0, + 0); + + log->Printf("request packet: <%u>\n%s", packet_size, log_strm.GetString().c_str()); } - return bytes_written; - } - return 0; -} + ConnectionStatus status = eConnectionStatusSuccess; -char -CommunicationKDP::GetAck () -{ - StringExtractor packet; - if (WaitForPacketWithTimeoutMicroSeconds (packet, GetPacketTimeoutInMicroSeconds ()) == 1) - return packet.GetChar(); - return 0; + size_t bytes_written = Write (packet_data, + packet_size, + status, + NULL); + + if (bytes_written == packet_size) + return true; + + if (log) + log->Printf ("error: failed to send packet entire packet %zu of %zu bytes sent", bytes_written, packet_size); + } + return false; } bool @@ -262,142 +223,30 @@ // Parse up the packets into gdb remote packets if (!m_bytes.empty()) { - // end_idx must be one past the last valid packet byte. Start - // it off with an invalid value that is the same as the current - // index. - size_t content_start = 0; - size_t content_length = 0; - size_t total_length = 0; - size_t checksum_idx = std::string::npos; - - switch (m_bytes[0]) - { - case '+': // Look for ack - case '-': // Look for cancel - case '\x03': // ^C to halt target - content_length = total_length = 1; // The command is one byte long... - break; - - case '$': - // Look for a standard gdb packet? - { - size_t hash_pos = m_bytes.find('#'); - if (hash_pos != std::string::npos) - { - if (hash_pos + 2 < m_bytes.size()) - { - checksum_idx = hash_pos + 1; - // Skip the dollar sign - content_start = 1; - // Don't include the # in the content or the $ in the content length - content_length = hash_pos - 1; - - total_length = hash_pos + 3; // Skip the # and the two hex checksum bytes - } - else - { - // Checksum bytes aren't all here yet - content_length = std::string::npos; - } - } - } - break; - - default: - { - // We have an unexpected byte and we need to flush all bad - // data that is in m_bytes, so we need to find the first - // byte that is a '+' (ACK), '-' (NACK), \x03 (CTRL+C interrupt), - // or '$' character (start of packet header) or of course, - // the end of the data in m_bytes... - const size_t bytes_len = m_bytes.size(); - bool done = false; - uint32_t idx; - for (idx = 1; !done && idx < bytes_len; ++idx) - { - switch (m_bytes[idx]) - { - case '+': - case '-': - case '\x03': - case '$': - done = true; - break; - - default: - break; - } - } - if (log) - log->Printf ("CommunicationKDP::%s tossing %u junk bytes: '%.*s'", - __FUNCTION__, idx, idx, m_bytes.c_str()); - m_bytes.erase(0, idx); - } - break; - } - - if (content_length == std::string::npos) - { - packet.Clear(); - return false; - } - else if (total_length > 0) - { - - // We have a valid packet... - assert (content_length <= m_bytes.size()); - assert (total_length <= m_bytes.size()); - assert (content_length <= total_length); - - bool success = true; - std::string &packet_str = packet.GetStringRef(); - packet_str.assign (m_bytes, content_start, content_length); - if (m_bytes[0] == '$') - { - assert (checksum_idx < m_bytes.size()); - if (::isxdigit (m_bytes[checksum_idx+0]) || - ::isxdigit (m_bytes[checksum_idx+1])) - { - if (GetSendAcks ()) - { - const char *packet_checksum_cstr = &m_bytes[checksum_idx]; - char packet_checksum = strtol (packet_checksum_cstr, NULL, 16); - char actual_checksum = CalculcateChecksum (packet_str.c_str(), packet_str.size()); - success = packet_checksum == actual_checksum; - if (!success) - { - if (log) - log->Printf ("error: checksum mismatch: %.*s expected 0x%2.2x, got 0x%2.2x", - (int)(total_length), - m_bytes.c_str(), - (uint8_t)packet_checksum, - (uint8_t)actual_checksum); - } - // Send the ack or nack if needed - if (!success) - SendNack(); - else - SendAck(); - } - if (success) - { - if (log) - log->Printf ("read packet: %.*s", (int)(total_length), m_bytes.c_str()); - } - } - else - { - success = false; - if (log) - log->Printf ("error: invalid checksum in packet: '%s'\n", (int)(total_length), m_bytes.c_str()); - } - } - m_bytes.erase(0, total_length); - packet.SetFilePos(0); - return success; - } + // TODO: Figure out if we have a full packet reply } packet.Clear(); return false; } + +CommunicationKDP::ErrorType +CommunicationKDP::Connect (uint16_t reply_port, + uint16_t exc_port, + const char *greeting) +{ + StreamString request_packet (Stream::eBinary, 4, eByteOrderLittle); + MakeRequestPacketHeader (eRequestTypeConnect, request_packet); + request_packet.PutHex16(reply_port); + request_packet.PutHex16(exc_port); + request_packet.PutCString(greeting); + + return eErrorUnimplemented; +} + +CommunicationKDP::ErrorType +CommunicationKDP::Disconnect () +{ + return eErrorUnimplemented; +} + Modified: lldb/trunk/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.h?rev=135277&r1=135276&r2=135277&view=diff ============================================================================== --- lldb/trunk/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.h (original) +++ lldb/trunk/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.h Fri Jul 15 11:31:38 2011 @@ -33,6 +33,53 @@ { eBroadcastBitRunPacketSent = kLoUserBroadcastBit }; + + const static uint32_t kMaxPacketSize = 1200; + const static uint32_t kMaxDataSize = 1024; + + typedef enum + { + eRequestTypeConnect = 0u, + eRequestTypeDisconnect, + eRequestTypeHostInfo, + eRequestTypeVersion, + eRequestTypeMaxBytes, + eRequestTypeReadMemory, + eRequestTypeWriteMemory, + eRequestTypeReadRegisters, + eRequestTypeWriteRegisters, + eRequestTypeLoad, + eRequestTypeImagePath, + eRequestTypeSuspend, + eRequestTypeResume, + eRequestTypeException, + eRequestTypeTermination, + eRequestTypeBreakpointSet, + eRequestTypeBreakpointRemove, + eRequestTypeRegions, + eRequestTypeReattach, + eRequestTypeHostReboot, + eRequestTypeReadMemory64, + eRequestTypeWriteMemory64, + eRequestTypeBreakpointSet64, + eRequestTypeBreakpointRemove64, + eRequestTypeKernelVersion + } RequestType; + + typedef enum + { + eErrorSuccess = 0, + eErrorAlreadyConnected, + eErrorPacketToBig, + eErrorInvalidRegisterFlavor, + eErrorUnimplemented + } ErrorType; + + typedef enum + { + ePacketTypeRequest = 0u, + ePacketTypeReply = 1u + } PacketType; //------------------------------------------------------------------ // Constructors and Destructors //------------------------------------------------------------------ @@ -41,34 +88,14 @@ virtual ~CommunicationKDP(); - size_t - SendPacket (const char *payload); - - size_t - SendPacket (const char *payload, - size_t payload_length); - - size_t - SendPacket (lldb_private::StreamString &response); + bool + SendRequestPacket (const lldb_private::StreamString &request_packet); // Wait for a packet within 'nsec' seconds size_t WaitForPacketWithTimeoutMicroSeconds (StringExtractor &response, uint32_t usec); - char - GetAck (); - - size_t - SendAck (); - - size_t - SendNack (); - - char - CalculcateChecksum (const char *payload, - size_t payload_length); - bool GetSequenceMutex(lldb_private::Mutex::Locker& locker); @@ -82,12 +109,6 @@ return m_public_is_running.GetValue(); } - bool - GetSendAcks () - { - return m_send_acks; - } - //------------------------------------------------------------------ // Set the global packet timeout. // @@ -119,12 +140,19 @@ lldb_private::ProcessLaunchInfo &launch_info); + ErrorType + Connect (uint16_t reply_port, + uint16_t exc_port, + const char *greeting); + + ErrorType + Disconnect (); + protected: typedef std::list packet_collection; - size_t - SendPacketNoLock (const char *payload, - size_t payload_length); + bool + SendRequestPacketNoLock (const lldb_private::StreamString &request_packet); size_t WaitForPacketWithTimeoutMicroSecondsNoLock (StringExtractor &response, @@ -133,6 +161,10 @@ bool WaitForNotRunningPrivate (const lldb_private::TimeValue *timeout_ptr); + void + MakeRequestPacketHeader (RequestType request_type, + lldb_private::StreamString &request_packet); + //------------------------------------------------------------------ // Classes that inherit from CommunicationKDP can see and modify these //------------------------------------------------------------------ @@ -140,8 +172,9 @@ lldb_private::Mutex m_sequence_mutex; // Restrict access to sending/receiving packets to a single thread at a time lldb_private::Predicate m_public_is_running; lldb_private::Predicate m_private_is_running; - bool m_send_acks; - + uint32_t m_session_key; + uint8_t m_request_sequence_id; + uint8_t m_exception_sequence_id; private: //------------------------------------------------------------------ // For CommunicationKDP only Modified: lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp?rev=135277&r1=135276&r2=135277&view=diff ============================================================================== --- lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp (original) +++ lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp Fri Jul 15 11:31:38 2011 @@ -16,6 +16,7 @@ #include "lldb/Core/PluginManager.h" #include "lldb/Core/State.h" #include "lldb/Host/Host.h" +#include "lldb/Target/Target.h" // Project includes #include "ProcessKDP.h" @@ -414,7 +415,7 @@ m_thread_list.DiscardThreadPlans(); - size_t response_size = m_comm.SendPacket ("D", 1); + size_t response_size = m_comm.Disconnect (); if (log) { if (response_size) From gclayton at apple.com Fri Jul 15 13:02:58 2011 From: gclayton at apple.com (Greg Clayton) Date: Fri, 15 Jul 2011 18:02:58 -0000 Subject: [Lldb-commits] [lldb] r135284 - in /lldb/trunk/source/Plugins/Process/MacOSX-Kernel: CommunicationKDP.cpp CommunicationKDP.h ProcessKDP.cpp ProcessKDP.h ProcessKDPLog.cpp ProcessKDPLog.h Message-ID: <20110715180258.D5E782A6C12C@llvm.org> Author: gclayton Date: Fri Jul 15 13:02:58 2011 New Revision: 135284 URL: http://llvm.org/viewvc/llvm-project?rev=135284&view=rev Log: Fixed the comment lines in the file comment headers. Modified: lldb/trunk/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp lldb/trunk/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.h lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDPLog.cpp lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDPLog.h Modified: lldb/trunk/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp?rev=135284&r1=135283&r2=135284&view=diff ============================================================================== --- lldb/trunk/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp (original) +++ lldb/trunk/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp Fri Jul 15 13:02:58 2011 @@ -1,4 +1,4 @@ -//===-- CommunicationKDP.cpp ------------------------------*- C++ -*-===// +//===-- CommunicationKDP.cpp ------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // Modified: lldb/trunk/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.h?rev=135284&r1=135283&r2=135284&view=diff ============================================================================== --- lldb/trunk/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.h (original) +++ lldb/trunk/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.h Fri Jul 15 13:02:58 2011 @@ -1,4 +1,4 @@ -//===-- CommunicationKDP.h --------------------------------*- C++ -*-===// +//===-- CommunicationKDP.h --------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // Modified: lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp?rev=135284&r1=135283&r2=135284&view=diff ============================================================================== --- lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp (original) +++ lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp Fri Jul 15 13:02:58 2011 @@ -1,4 +1,4 @@ -//===-- ProcessKDP.cpp ------------------------------------*- C++ -*-===// +//===-- ProcessKDP.cpp ------------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // Modified: lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h?rev=135284&r1=135283&r2=135284&view=diff ============================================================================== --- lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h (original) +++ lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h Fri Jul 15 13:02:58 2011 @@ -1,4 +1,4 @@ -//===-- ProcessKDP.h --------------------------------------*- C++ -*-===// +//===-- ProcessKDP.h --------------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // Modified: lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDPLog.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDPLog.cpp?rev=135284&r1=135283&r2=135284&view=diff ============================================================================== --- lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDPLog.cpp (original) +++ lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDPLog.cpp Fri Jul 15 13:02:58 2011 @@ -1,4 +1,4 @@ -//===-- ProcessKDPLog.cpp ---------------------------------*- C++ -*-===// +//===-- ProcessKDPLog.cpp ---------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // Modified: lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDPLog.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDPLog.h?rev=135284&r1=135283&r2=135284&view=diff ============================================================================== --- lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDPLog.h (original) +++ lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDPLog.h Fri Jul 15 13:02:58 2011 @@ -1,4 +1,4 @@ -//===-- ProcessKDPLog.h -----------------------------------*- C++ -*-===// +//===-- ProcessKDPLog.h -----------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // From gclayton at apple.com Fri Jul 15 14:31:49 2011 From: gclayton at apple.com (Greg Clayton) Date: Fri, 15 Jul 2011 19:31:49 -0000 Subject: [Lldb-commits] [lldb] r135292 - in /lldb/trunk: include/lldb/API/SBValue.h source/API/SBValue.cpp test/python_api/default-constructor/sb_value.py Message-ID: <20110715193149.4D1212A6C12C@llvm.org> Author: gclayton Date: Fri Jul 15 14:31:49 2011 New Revision: 135292 URL: http://llvm.org/viewvc/llvm-project?rev=135292&view=rev Log: Added the ability to get synthetic child values from SBValue objects that represent pointers and arrays by adding an extra parameter to the SBValue SBValue::GetChildAtIndex (uint32_t idx, DynamicValueType use_dynamic, bool can_create_synthetic); The new "can_create_synthetic" will allow you to create child values that aren't actually a part of the original type. So if you code like: int *foo_ptr = ... And you have a SBValue that contains the value for "foo_ptr": SBValue foo_value = ... You can now get the "foo_ptr[12]" item by doing this: v = foo_value.GetChiltAtIndex (12, lldb.eNoDynamicValues, True); Normall the "foo_value" would only have one child value (an integer), but we can create "synthetic" child values by treating the pointer as an array. Likewise if you have code like: int array[2]; array_value = .... v = array_value.GetChiltAtIndex (0); // Success, v will be valid v = array_value.GetChiltAtIndex (1); // Success, v will be valid v = array_value.GetChiltAtIndex (2); // Fail, v won't be valid, "2" is not a valid zero based index in "array" But if you use the ability to create synthetic children: v = array_value.GetChiltAtIndex (0, lldb.eNoDynamicValues, True); // Success, v will be valid v = array_value.GetChiltAtIndex (1, lldb.eNoDynamicValues, True); // Success, v will be valid v = array_value.GetChiltAtIndex (2, lldb.eNoDynamicValues, True); // Success, v will be valid Modified: lldb/trunk/include/lldb/API/SBValue.h lldb/trunk/source/API/SBValue.cpp lldb/trunk/test/python_api/default-constructor/sb_value.py Modified: lldb/trunk/include/lldb/API/SBValue.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/API/SBValue.h?rev=135292&r1=135291&r2=135292&view=diff ============================================================================== --- lldb/trunk/include/lldb/API/SBValue.h (original) +++ lldb/trunk/include/lldb/API/SBValue.h Fri Jul 15 14:31:49 2011 @@ -150,8 +150,60 @@ lldb::SBValue GetChildAtIndex (uint32_t idx); - lldb::SBValue - GetChildAtIndex (uint32_t idx, lldb::DynamicValueType use_dynamic); + //------------------------------------------------------------------ + /// Get a child value by index from a value. + /// + /// Structs, unions, classes, arrays and and pointers have child + /// values that can be access by index. + /// + /// Structs and unions access child members using a zero based index + /// for each child member. For + /// + /// Classes reserve the first indexes for base classes that have + /// members (empty base classes are omitted), and all members of the + /// current class will then follow the base classes. + /// + /// Pointers differ depending on what they point to. If the pointer + /// points to a simple type, the child at index zero + /// is the only child value available, unless \a synthetic_allowed + /// is \b true, in which case the pointer will be used as an array + /// and can create "synthetic" child values using positive or + /// negative indexes. If the pointer points to an aggregate type + /// (an array, class, union, struct), then the pointee is + /// transparently skipped and any children are going to be the indexes + /// of the child values within the aggregate type. For example if + /// we have a "Point" type and we have a SBValue that contains a + /// pointer to a "Point" type, then the child at index zero will be + /// the "x" member, and the child at index 1 will be the "y" member + /// (the child at index zero won't be a "Point" instance). + /// + /// Arrays have a preset number of children that can be accessed by + /// index and will returns invalid child values for indexes that are + /// out of bounds unless the \a synthetic_allowed is \b true. In this + /// case the array can create "synthetic" child values for indexes + /// that aren't in the array bounds using positive or negative + /// indexes. + /// + /// @param[in] idx + /// The index of the child value to get + /// + /// @param[in] use_dynamic + /// An enumeration that specifies wether to get dynamic values, + /// and also if the target can be run to figure out the dynamic + /// type of the child value. + /// + /// @param[in] synthetic_allowed + /// If \b true, then allow child values to be created by index + /// for pointers and arrays for indexes that normally wouldn't + /// be allowed. + /// + /// @return + /// A new SBValue object that represents the child member value. + //------------------------------------------------------------------ + lldb::SBValue + GetChildAtIndex (uint32_t idx, + lldb::DynamicValueType use_dynamic, + bool can_create_synthetic); // Matches children of this object only and will match base classes and // member names if this is a clang typed object. Modified: lldb/trunk/source/API/SBValue.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/API/SBValue.cpp?rev=135292&r1=135291&r2=135292&view=diff ============================================================================== --- lldb/trunk/source/API/SBValue.cpp (original) +++ lldb/trunk/source/API/SBValue.cpp Fri Jul 15 14:31:49 2011 @@ -361,17 +361,15 @@ SBValue SBValue::GetChildAtIndex (uint32_t idx) { + const bool can_create_synthetic = false; + lldb::DynamicValueType use_dynamic = eNoDynamicValues; if (m_opaque_sp) - { - lldb::DynamicValueType use_dynamic_value = m_opaque_sp->GetUpdatePoint().GetTarget()->GetPreferDynamicValue(); - return GetChildAtIndex (idx, use_dynamic_value); - } - else - return GetChildAtIndex (idx, eNoDynamicValues); + use_dynamic = m_opaque_sp->GetUpdatePoint().GetTarget()->GetPreferDynamicValue(); + return GetChildAtIndex (idx, use_dynamic, can_create_synthetic); } SBValue -SBValue::GetChildAtIndex (uint32_t idx, lldb::DynamicValueType use_dynamic) +SBValue::GetChildAtIndex (uint32_t idx, lldb::DynamicValueType use_dynamic, bool can_create_synthetic) { lldb::ValueObjectSP child_sp; @@ -380,13 +378,25 @@ if (m_opaque_sp->GetUpdatePoint().GetTarget()) { Mutex::Locker api_locker (m_opaque_sp->GetUpdatePoint().GetTarget()->GetAPIMutex()); - - child_sp = m_opaque_sp->GetChildAtIndex (idx, true); - if (use_dynamic != lldb::eNoDynamicValues) + const bool can_create = true; + child_sp = m_opaque_sp->GetChildAtIndex (idx, can_create); + if (can_create_synthetic && !child_sp) { - if (child_sp) + if (m_opaque_sp->IsPointerType()) + { + child_sp = m_opaque_sp->GetSyntheticArrayMemberFromPointer(idx, can_create); + } + else if (m_opaque_sp->IsArrayType()) + { + child_sp = m_opaque_sp->GetSyntheticArrayMemberFromArray(idx, can_create); + } + } + + if (child_sp) + { + if (use_dynamic != lldb::eNoDynamicValues) { - lldb::ValueObjectSP dynamic_sp = child_sp->GetDynamicValue (use_dynamic); + lldb::ValueObjectSP dynamic_sp(child_sp->GetDynamicValue (use_dynamic)); if (dynamic_sp) child_sp = dynamic_sp; } Modified: lldb/trunk/test/python_api/default-constructor/sb_value.py URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/python_api/default-constructor/sb_value.py?rev=135292&r1=135291&r2=135292&view=diff ============================================================================== --- lldb/trunk/test/python_api/default-constructor/sb_value.py (original) +++ lldb/trunk/test/python_api/default-constructor/sb_value.py Fri Jul 15 14:31:49 2011 @@ -21,7 +21,7 @@ obj.GetLocation() obj.SetValueFromCString("my_new_value") obj.GetChildAtIndex(1) - obj.GetChildAtIndex(2, lldb.eNoDynamicValues) + obj.GetChildAtIndex(2, lldb.eNoDynamicValues, False) obj.GetIndexOfChildWithName("my_first_child") obj.GetChildMemberWithName("my_first_child") obj.GetChildMemberWithName("my_first_child", lldb.eNoDynamicValues) From johnso87 at crhc.illinois.edu Fri Jul 15 15:12:05 2011 From: johnso87 at crhc.illinois.edu (Matt Johnson) Date: Fri, 15 Jul 2011 15:12:05 -0500 Subject: [Lldb-commits] [PATCH] Make LLDB compile with Clang r135279 Message-ID: <4E209F15.1020300@crhc.illinois.edu> Hi all, This patch cleans up LLDB's usage of Clang and LLVM APIs that have changed recently, due to the type system rewrite that landed last weekend and some other StringRef and ArrayRef-related changes. LLDB, with this patch, compiles under G++ 4.5.2 on Ubuntu 11.04. Comments welcome. Best, Matt -------------- next part -------------- A non-text attachment was scrubbed... Name: typesystem.diff Type: text/x-diff Size: 9788 bytes Desc: not available Url : http://lists.cs.uiuc.edu/pipermail/lldb-commits/attachments/20110715/15ef88eb/attachment-0001.bin From johnso87 at crhc.illinois.edu Fri Jul 15 15:26:52 2011 From: johnso87 at crhc.illinois.edu (Matt Johnson) Date: Fri, 15 Jul 2011 15:26:52 -0500 Subject: [Lldb-commits] [PATCH] Begin cleanup to silence G++ warnings Message-ID: <4E20A28C.9070402@crhc.illinois.edu> Hi all, This is the beginning of a cleanup effort to reduce the (vast) number of (mostly benign) warnings when compiling LLDB HEAD under G++ 4.5.2 on Ubuntu 11.04. Getting these warnings out of the way makes it much easier to spot more important warnings, if nothing else. The fixes here can be categorized as follows: * Use of a signed type as a for loop induction variable, when the loop bound is an unsigned type * Assigning NULL (a pointer constant) to non-pointer types (e.g., uint32_t, addr_t) * Declaring class members in one order, and including them in constructor initializer lists in a different order There are many more of the above warnings that I haven't gotten to yet, as well as things like the following: * Python docstrings in e.g. SBTarget.h use a nonstandard gcc preprocessor extension that allows multi-line string literals. - This causes *tons* of warnings (one per line of the literal, per inclusion of the relevant header). e.g.: /media/d2/llvm/tools/lldb/source/Target/../../include/lldb/API/SBTarget.h:23:1: warning: missing terminating " character /media/d2/llvm/tools/lldb/source/Target/../../include/lldb/API/SBTarget.h:48:1: warning: missing terminating " character /media/d2/llvm/tools/lldb/source/Target/../../include/lldb/API/SBTarget.h:91:27: warning: missing terminating " character /media/d2/llvm/tools/lldb/source/Target/../../include/lldb/API/SBTarget.h:164:5: warning: missing terminating " character /media/d2/llvm/tools/lldb/source/Target/../../include/lldb/API/SBTarget.h:180:27: warning: missing terminating " character /media/d2/llvm/tools/lldb/source/Target/../../include/lldb/API/SBTarget.h:216:5: warning: missing terminating " character /media/d2/llvm/tools/lldb/source/Target/../../include/lldb/API/SBTarget.h:224:27: warning: missing terminating " character /media/d2/llvm/tools/lldb/source/Target/../../include/lldb/API/SBTarget.h:245:5: warning: missing terminating " character /media/d2/llvm/tools/lldb/source/Target/../../include/lldb/API/SBTarget.h:253:27: warning: missing terminating " character /media/d2/llvm/tools/lldb/source/Target/../../include/lldb/API/SBTarget.h:277:5: warning: missing terminating " character /media/d2/llvm/tools/lldb/source/Target/../../include/lldb/API/SBTarget.h:286:27: warning: missing terminating " character /media/d2/llvm/tools/lldb/source/Target/../../include/lldb/API/SBTarget.h:310:5: warning: missing terminating " character /media/d2/llvm/tools/lldb/source/Target/../../include/lldb/API/SBTarget.h:334:27: warning: missing terminating " character /media/d2/llvm/tools/lldb/source/Target/../../include/lldb/API/SBTarget.h:361:5: warning: missing terminating " character /media/d2/llvm/tools/lldb/source/Target/../../include/lldb/API/SBTarget.h:370:27: warning: missing terminating " character /media/d2/llvm/tools/lldb/source/Target/../../include/lldb/API/SBTarget.h:386:5: warning: missing terminating " character - These literals should be formed like: #ifdef SWIG %feature("docstring", "Represents the target program running under the debugger.\n" "\n" "SBTarget supports module and breakpoint iterations. For example,\n" ... - instead of: %feature("docstring", "Represents the target program running under the debugger. SBTarget supports module and breakpoint iterations. For example, ... * Use of (deprecated) instead of * Not handling some enum values in a switch statement. e.g., "ClangASTType.cpp:283:12: warning: enumeration value ?UnaryTransform? not handled in switch" * Defining static helper functions that are never used. e.g., "RegisterContextLinux_x86_64.cpp:408:17: warning: ?unsigned int GetRegSize(unsigned int)? defined but not used" Comments welcome. Best, Matt -------------- next part -------------- A non-text attachment was scrubbed... Name: cleanup.diff Type: text/x-diff Size: 20274 bytes Desc: not available Url : http://lists.cs.uiuc.edu/pipermail/lldb-commits/attachments/20110715/bab889a4/attachment.bin From johnso87 at crhc.illinois.edu Fri Jul 15 15:31:18 2011 From: johnso87 at crhc.illinois.edu (Matt Johnson) Date: Fri, 15 Jul 2011 15:31:18 -0500 Subject: [Lldb-commits] [PATCH] Begin cleanup to silence G++ warnings In-Reply-To: <4E20A28C.9070402@crhc.illinois.edu> References: <4E20A28C.9070402@crhc.illinois.edu> Message-ID: <4E20A396.9070205@crhc.illinois.edu> Note, The line numbering in this patch depends on the previous patch I sent to the list regarding updating LLDB's usage of Clang/LLVM APIs. See http://lists.cs.uiuc.edu/pipermail/lldb-commits/Week-of-Mon-20110711/003313.html. Sorry about that. -Matt On 07/15/2011 03:26 PM, Matt Johnson wrote: > Hi all, > This is the beginning of a cleanup effort to reduce the (vast) number > of (mostly benign) warnings when compiling LLDB HEAD under G++ 4.5.2 > on Ubuntu 11.04. Getting these warnings out of the way makes it much > easier to spot more important warnings, if nothing else. The fixes > here can be categorized as follows: > > * Use of a signed type as a for loop induction variable, when the loop > bound is an unsigned type > * Assigning NULL (a pointer constant) to non-pointer types (e.g., > uint32_t, addr_t) > * Declaring class members in one order, and including them in > constructor initializer lists in a different order > > There are many more of the above warnings that I haven't gotten to > yet, as well as things like the following: > * Python docstrings in e.g. SBTarget.h use a nonstandard gcc > preprocessor extension that allows multi-line string literals. > - This causes *tons* of warnings (one per line of the literal, per > inclusion of the relevant header). e.g.: > > /media/d2/llvm/tools/lldb/source/Target/../../include/lldb/API/SBTarget.h:23:1: > warning: missing terminating " character > /media/d2/llvm/tools/lldb/source/Target/../../include/lldb/API/SBTarget.h:48:1: > warning: missing terminating " character > /media/d2/llvm/tools/lldb/source/Target/../../include/lldb/API/SBTarget.h:91:27: > warning: missing terminating " character > /media/d2/llvm/tools/lldb/source/Target/../../include/lldb/API/SBTarget.h:164:5: > warning: missing terminating " character > /media/d2/llvm/tools/lldb/source/Target/../../include/lldb/API/SBTarget.h:180:27: > warning: missing terminating " character > /media/d2/llvm/tools/lldb/source/Target/../../include/lldb/API/SBTarget.h:216:5: > warning: missing terminating " character > /media/d2/llvm/tools/lldb/source/Target/../../include/lldb/API/SBTarget.h:224:27: > warning: missing terminating " character > /media/d2/llvm/tools/lldb/source/Target/../../include/lldb/API/SBTarget.h:245:5: > warning: missing terminating " character > /media/d2/llvm/tools/lldb/source/Target/../../include/lldb/API/SBTarget.h:253:27: > warning: missing terminating " character > /media/d2/llvm/tools/lldb/source/Target/../../include/lldb/API/SBTarget.h:277:5: > warning: missing terminating " character > /media/d2/llvm/tools/lldb/source/Target/../../include/lldb/API/SBTarget.h:286:27: > warning: missing terminating " character > /media/d2/llvm/tools/lldb/source/Target/../../include/lldb/API/SBTarget.h:310:5: > warning: missing terminating " character > /media/d2/llvm/tools/lldb/source/Target/../../include/lldb/API/SBTarget.h:334:27: > warning: missing terminating " character > /media/d2/llvm/tools/lldb/source/Target/../../include/lldb/API/SBTarget.h:361:5: > warning: missing terminating " character > /media/d2/llvm/tools/lldb/source/Target/../../include/lldb/API/SBTarget.h:370:27: > warning: missing terminating " character > /media/d2/llvm/tools/lldb/source/Target/../../include/lldb/API/SBTarget.h:386:5: > warning: missing terminating " character > > - These literals should be formed like: > > #ifdef SWIG > %feature("docstring", > "Represents the target program running under the debugger.\n" > "\n" > "SBTarget supports module and breakpoint iterations. For example,\n" > ... > > - instead of: > > %feature("docstring", > "Represents the target program running under the debugger. > > SBTarget supports module and breakpoint iterations. For example, > ... > > > * Use of (deprecated) instead of > * Not handling some enum values in a switch statement. e.g., > "ClangASTType.cpp:283:12: warning: enumeration value ?UnaryTransform? > not handled in switch" > * Defining static helper functions that are never used. e.g., > "RegisterContextLinux_x86_64.cpp:408:17: warning: ?unsigned int > GetRegSize(unsigned int)? defined but not used" > > Comments welcome. > Best, > Matt > > > _______________________________________________ > lldb-commits mailing list > lldb-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/lldb-commits -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.cs.uiuc.edu/pipermail/lldb-commits/attachments/20110715/2e4575e6/attachment-0001.html From johnny.chen at apple.com Fri Jul 15 15:46:19 2011 From: johnny.chen at apple.com (Johnny Chen) Date: Fri, 15 Jul 2011 20:46:19 -0000 Subject: [Lldb-commits] [lldb] r135295 - in /lldb/trunk: include/lldb/API/SBBreakpoint.h include/lldb/API/SBCompileUnit.h include/lldb/API/SBValue.h scripts/Python/modify-python-lldb.py Message-ID: <20110715204619.7C3B33128018@llvm.org> Author: johnny Date: Fri Jul 15 15:46:19 2011 New Revision: 135295 URL: http://llvm.org/viewvc/llvm-project?rev=135295&view=rev Log: Add some more docstrings for SBCompileUnit and SBBreakpoint, plus incorporate the doxgen doc block of SBValue::GetChildAtIndex(uint32_t idx, lldb::DynamicValueType use_dynamic, bool can_create_synthetic); into the SBValue docstrings. Modified: lldb/trunk/include/lldb/API/SBBreakpoint.h lldb/trunk/include/lldb/API/SBCompileUnit.h lldb/trunk/include/lldb/API/SBValue.h lldb/trunk/scripts/Python/modify-python-lldb.py Modified: lldb/trunk/include/lldb/API/SBBreakpoint.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/API/SBBreakpoint.h?rev=135295&r1=135294&r2=135295&view=diff ============================================================================== --- lldb/trunk/include/lldb/API/SBBreakpoint.h (original) +++ lldb/trunk/include/lldb/API/SBBreakpoint.h Fri Jul 15 15:46:19 2011 @@ -71,6 +71,12 @@ process.Continue() +SBBreakpoint supports breakpoint location iteration. For example, + + for bl in breakpoint: + print 'breakpoint location load addr: %s' % hex(bl.GetLoadAddress()) + print 'breakpoint location condition: %s' % hex(bl.GetCondition()) + " ) SBBreakpoint; #endif Modified: lldb/trunk/include/lldb/API/SBCompileUnit.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/API/SBCompileUnit.h?rev=135295&r1=135294&r2=135295&view=diff ============================================================================== --- lldb/trunk/include/lldb/API/SBCompileUnit.h (original) +++ lldb/trunk/include/lldb/API/SBCompileUnit.h Fri Jul 15 15:46:19 2011 @@ -17,7 +17,32 @@ #ifdef SWIG %feature("docstring", - "Represents a compilation unit, or compiled source file." +"Represents a compilation unit, or compiled source file. + +SBCompileUnit supports line entry iteration. For example, + + for lineEntry in compileUnit: + print 'line entry: %s:%d' % (str(lineEntry.GetFileSpec()), + lineEntry.GetLine()) + print 'start addr: %s' % str(lineEntry.GetStartAddress()) + print 'end addr: %s' % str(lineEntry.GetEndAddress()) + +produces: + +line entry: /Volumes/data/lldb/svn/trunk/test/python_api/symbol-context/main.c:20 +start addr: a.out[0x100000d98] +end addr: a.out[0x100000da3] +line entry: /Volumes/data/lldb/svn/trunk/test/python_api/symbol-context/main.c:21 +start addr: a.out[0x100000da3] +end addr: a.out[0x100000da9] +line entry: /Volumes/data/lldb/svn/trunk/test/python_api/symbol-context/main.c:22 +start addr: a.out[0x100000da9] +end addr: a.out[0x100000db6] +line entry: /Volumes/data/lldb/svn/trunk/test/python_api/symbol-context/main.c:23 +start addr: a.out[0x100000db6] +end addr: a.out[0x100000dbc] +... +" ) SBCompileUnit; #endif class SBCompileUnit Modified: lldb/trunk/include/lldb/API/SBValue.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/API/SBValue.h?rev=135295&r1=135294&r2=135295&view=diff ============================================================================== --- lldb/trunk/include/lldb/API/SBValue.h (original) +++ lldb/trunk/include/lldb/API/SBValue.h Fri Jul 15 15:46:19 2011 @@ -150,6 +150,9 @@ lldb::SBValue GetChildAtIndex (uint32_t idx); +#ifdef SWIG + %feature("docstring", " +#endif //------------------------------------------------------------------ /// Get a child value by index from a value. /// @@ -167,20 +170,20 @@ /// points to a simple type, the child at index zero /// is the only child value available, unless \a synthetic_allowed /// is \b true, in which case the pointer will be used as an array - /// and can create "synthetic" child values using positive or + /// and can create 'synthetic' child values using positive or /// negative indexes. If the pointer points to an aggregate type /// (an array, class, union, struct), then the pointee is /// transparently skipped and any children are going to be the indexes /// of the child values within the aggregate type. For example if - /// we have a "Point" type and we have a SBValue that contains a - /// pointer to a "Point" type, then the child at index zero will be - /// the "x" member, and the child at index 1 will be the "y" member - /// (the child at index zero won't be a "Point" instance). + /// we have a 'Point' type and we have a SBValue that contains a + /// pointer to a 'Point' type, then the child at index zero will be + /// the 'x' member, and the child at index 1 will be the 'y' member + /// (the child at index zero won't be a 'Point' instance). /// /// Arrays have a preset number of children that can be accessed by /// index and will returns invalid child values for indexes that are /// out of bounds unless the \a synthetic_allowed is \b true. In this - /// case the array can create "synthetic" child values for indexes + /// case the array can create 'synthetic' child values for indexes /// that aren't in the array bounds using positive or negative /// indexes. /// @@ -200,6 +203,9 @@ /// @return /// A new SBValue object that represents the child member value. //------------------------------------------------------------------ +#ifdef SWIG + ") GetChildAtIndex; +#endif lldb::SBValue GetChildAtIndex (uint32_t idx, lldb::DynamicValueType use_dynamic, Modified: lldb/trunk/scripts/Python/modify-python-lldb.py URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/scripts/Python/modify-python-lldb.py?rev=135295&r1=135294&r2=135295&view=diff ============================================================================== --- lldb/trunk/scripts/Python/modify-python-lldb.py (original) +++ lldb/trunk/scripts/Python/modify-python-lldb.py Fri Jul 15 15:46:19 2011 @@ -223,7 +223,7 @@ # Adding support for eq and ne for the matched SB class. state |= DEFINING_EQUALITY - elif (state & DEFINING_ITERATOR) or (state & DEFINING_EQUALITY): + if (state & DEFINING_ITERATOR) or (state & DEFINING_EQUALITY): match = init_pattern.search(line) if match: # We found the beginning of the __init__ method definition. @@ -244,15 +244,16 @@ # Next state will be NORMAL. state = NORMAL - elif (state & CLEANUP_DOCSTRING): + if (state & CLEANUP_DOCSTRING): # Cleanse the lldb.py of the autodoc'ed residues. if c_ifdef_swig in line or c_endif_swig in line: continue # As well as the comment marker line and trailing blank line. if c_comment_marker in line or line == trailing_blank_line: continue - # Also remove the '\a ' substrings. + # Also remove the '\a ' and '\b 'substrings. line = line.replace('\a ', '') + line = line.replace('\b ', '') # And the leading '///' substring. doxygen_comment_match = doxygen_comment_start.match(line) if doxygen_comment_match: From j.e.aten at gmail.com Fri Jul 15 15:26:09 2011 From: j.e.aten at gmail.com (Jason E. Aten) Date: Fri, 15 Jul 2011 15:26:09 -0500 Subject: [Lldb-commits] [PATCH] Make LLDB compile with Clang r135279 In-Reply-To: <4E209F15.1020300@crhc.illinois.edu> References: <4E209F15.1020300@crhc.illinois.edu> Message-ID: Nice! Thank you, Matt. I'll check it out. On Fri, Jul 15, 2011 at 3:12 PM, Matt Johnson wrote: > Hi all, > This patch cleans up LLDB's usage of Clang and LLVM APIs that have > changed recently, due to the type system rewrite that landed last weekend > and some other StringRef and ArrayRef-related changes. LLDB, with this > patch, compiles under G++ 4.5.2 on Ubuntu 11.04. Comments welcome. > Best, > Matt > > _______________________________________________ > lldb-commits mailing list > lldb-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/lldb-commits > > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.cs.uiuc.edu/pipermail/lldb-commits/attachments/20110715/9bf1e7b8/attachment.html From johnny.chen at apple.com Fri Jul 15 17:28:11 2011 From: johnny.chen at apple.com (Johnny Chen) Date: Fri, 15 Jul 2011 22:28:11 -0000 Subject: [Lldb-commits] [lldb] r135315 - in /lldb/trunk/test: lldbtest.py python_api/value/ python_api/value/Makefile python_api/value/TestValueAPI.py python_api/value/main.c Message-ID: <20110715222811.11DE6312800A@llvm.org> Author: johnny Date: Fri Jul 15 17:28:10 2011 New Revision: 135315 URL: http://llvm.org/viewvc/llvm-project?rev=135315&view=rev Log: Add TestValueAPI.py to exercise the newly added/modified SBValue APIs: o GetChildAtIndex, and o GetValueForExpressionPath Added: lldb/trunk/test/python_api/value/ lldb/trunk/test/python_api/value/Makefile lldb/trunk/test/python_api/value/TestValueAPI.py lldb/trunk/test/python_api/value/main.c Modified: lldb/trunk/test/lldbtest.py Modified: lldb/trunk/test/lldbtest.py URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/lldbtest.py?rev=135315&r1=135314&r2=135315&view=diff ============================================================================== --- lldb/trunk/test/lldbtest.py (original) +++ lldb/trunk/test/lldbtest.py Fri Jul 15 17:28:10 2011 @@ -194,6 +194,8 @@ VALID_TARGET = "Got a valid target" +VALID_VARIABLE = "Got a valid variable" + VARIABLES_DISPLAYED_CORRECTLY = "Variable(s) displayed correctly" Added: lldb/trunk/test/python_api/value/Makefile URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/python_api/value/Makefile?rev=135315&view=auto ============================================================================== --- lldb/trunk/test/python_api/value/Makefile (added) +++ lldb/trunk/test/python_api/value/Makefile Fri Jul 15 17:28:10 2011 @@ -0,0 +1,5 @@ +LEVEL = ../../make + +C_SOURCES := main.c + +include $(LEVEL)/Makefile.rules Added: lldb/trunk/test/python_api/value/TestValueAPI.py URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/python_api/value/TestValueAPI.py?rev=135315&view=auto ============================================================================== --- lldb/trunk/test/python_api/value/TestValueAPI.py (added) +++ lldb/trunk/test/python_api/value/TestValueAPI.py Fri Jul 15 17:28:10 2011 @@ -0,0 +1,87 @@ +""" +Test some SBValue APIs. +""" + +import os, time +import re +import unittest2 +import lldb, lldbutil +from lldbtest import * + +class ValueAPITestCase(TestBase): + + mydir = os.path.join("python_api", "value") + + @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin") + @python_api_test + def test_with_dsym(self): + """Exercise some SBValue APIs.""" + d = {'EXE': self.exe_name} + self.buildDsym(dictionary=d) + self.setTearDownCleanup(dictionary=d) + self.value_api(self.exe_name) + + @python_api_test + def test_with_dwarf(self): + """Exercise some SBValue APIs.""" + d = {'EXE': self.exe_name} + self.buildDwarf(dictionary=d) + self.setTearDownCleanup(dictionary=d) + self.value_api(self.exe_name) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # We'll use the test method name as the exe_name. + self.exe_name = self.testMethodName + # Find the line number to of function 'c'. + self.line = line_number('main.c', '// Break at this line') + + def value_api(self, exe_name): + """Exercise some SBValue APIs.""" + exe = os.path.join(os.getcwd(), exe_name) + + # Create a target by the debugger. + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + # Create the breakpoint inside function 'main'. + breakpoint = target.BreakpointCreateByLocation('main.c', self.line) + self.assertTrue(breakpoint, VALID_BREAKPOINT) + + # Now launch the process, and do not stop at entry point. + process = target.LaunchSimple(None, None, os.getcwd()) + self.assertTrue(process, PROCESS_IS_VALID) + + # Get Frame #0. + self.assertTrue(process.GetState() == lldb.eStateStopped) + thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint) + self.assertTrue(thread != None, "There should be a thread stopped due to breakpoint condition") + frame0 = thread.GetFrameAtIndex(0) + + # Get variable 'str_ptr'. + value = frame0.FindVariable('str_ptr') + self.assertTrue(value, VALID_VARIABLE) + self.DebugSBValue(value) + + # Get child at index 5 => 'Friday'. + child = value.GetChildAtIndex(5, lldb.eNoDynamicValues, True) + self.assertTrue(child, VALID_VARIABLE) + self.DebugSBValue(child) + + self.expect(child.GetSummary(), exe=False, + substrs = ['Friday']) + + # Now try to get at the same variable using GetValueForExpressionPath(). + # These two SBValue objects should have the same value. + val2 = value.GetValueForExpressionPath('[5]') + self.assertTrue(val2, VALID_VARIABLE) + self.DebugSBValue(val2) + self.assertTrue(child.GetValue() == val2.GetValue() and + child.GetSummary() == val2.GetSummary()) + +if __name__ == '__main__': + import atexit + lldb.SBDebugger.Initialize() + atexit.register(lambda: lldb.SBDebugger.Terminate()) + unittest2.main() Added: lldb/trunk/test/python_api/value/main.c URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/python_api/value/main.c?rev=135315&view=auto ============================================================================== --- lldb/trunk/test/python_api/value/main.c (added) +++ lldb/trunk/test/python_api/value/main.c Fri Jul 15 17:28:10 2011 @@ -0,0 +1,30 @@ +//===-- main.c --------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#include + +// This simple program is to test the lldb Python API SBValue.GetChildAtIndex(). + +const char *days_of_week[7] = { "Sunday", + "Monday", + "Tuesday", + "Wednesday", + "Thursday", + "Friday", + "Saturday" }; + +int main (int argc, char const *argv[]) +{ + int i; + const char **str_ptr = days_of_week; + for (i = 0; i < 7; ++i) + printf("%s\n", str_ptr[i]); // Break at this line + // and do str_ptr_val.GetChildAtIndex(5, lldb.eNoDynamicValues, True). + + return 0; +} From peter at pcc.me.uk Fri Jul 15 18:22:49 2011 From: peter at pcc.me.uk (Peter Collingbourne) Date: Fri, 15 Jul 2011 23:22:49 -0000 Subject: [Lldb-commits] [lldb] r135325 - /lldb/trunk/include/lldb/Interpreter/ScriptInterpreter.h Message-ID: <20110715232249.CEB0A2A6C12D@llvm.org> Author: pcc Date: Fri Jul 15 18:22:49 2011 New Revision: 135325 URL: http://llvm.org/viewvc/llvm-project?rev=135325&view=rev Log: Fix gcc build error Modified: lldb/trunk/include/lldb/Interpreter/ScriptInterpreter.h Modified: lldb/trunk/include/lldb/Interpreter/ScriptInterpreter.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Interpreter/ScriptInterpreter.h?rev=135325&r1=135324&r2=135325&view=diff ============================================================================== --- lldb/trunk/include/lldb/Interpreter/ScriptInterpreter.h (original) +++ lldb/trunk/include/lldb/Interpreter/ScriptInterpreter.h Fri Jul 15 18:22:49 2011 @@ -27,8 +27,6 @@ const lldb::StackFrameSP& frame_sp, const lldb::BreakpointLocationSP &bp_loc_sp); - typedef - typedef std::string (*SWIGPythonTypeScriptCallbackFunction) (const char *python_function_name, const char *session_dictionary_name, const lldb::ValueObjectSP& valobj_sp); From granata.enrico at gmail.com Fri Jul 15 18:30:15 2011 From: granata.enrico at gmail.com (Enrico Granata) Date: Fri, 15 Jul 2011 23:30:15 -0000 Subject: [Lldb-commits] [lldb] r135326 - in /lldb/trunk: include/lldb/Core/ source/Commands/ source/Core/ source/Symbol/ test/functionalities/data-formatter/data-formatter-script/ Message-ID: <20110715233015.927A52A6C12C@llvm.org> Author: enrico Date: Fri Jul 15 18:30:15 2011 New Revision: 135326 URL: http://llvm.org/viewvc/llvm-project?rev=135326&view=rev Log: System-wide summaries: - Summaries for char*, const char* and char[] are loaded at startup as system-wide summaries. This means you cannot delete them unless you use the -a option to type summary delete/clear - You can add your own system-wide summaries by using the -w option to type summary add Several code improvements for the Python summaries feature Modified: lldb/trunk/include/lldb/Core/Debugger.h lldb/trunk/include/lldb/Core/FormatManager.h lldb/trunk/include/lldb/Core/InputReader.h lldb/trunk/include/lldb/Core/InputReaderEZ.h lldb/trunk/source/Commands/CommandObjectType.cpp lldb/trunk/source/Commands/CommandObjectType.h lldb/trunk/source/Core/Debugger.cpp lldb/trunk/source/Core/InputReaderEZ.cpp lldb/trunk/source/Core/ValueObject.cpp lldb/trunk/source/Symbol/ClangASTContext.cpp lldb/trunk/source/Symbol/TypeHierarchyNavigator.cpp lldb/trunk/test/functionalities/data-formatter/data-formatter-script/TestDataFormatterScript.py lldb/trunk/test/functionalities/data-formatter/data-formatter-script/main.cpp Modified: lldb/trunk/include/lldb/Core/Debugger.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/Debugger.h?rev=135326&r1=135325&r2=135326&view=diff ============================================================================== --- lldb/trunk/include/lldb/Core/Debugger.h (original) +++ lldb/trunk/include/lldb/Core/Debugger.h Fri Jul 15 18:30:15 2011 @@ -525,6 +525,32 @@ GetCount(); }; + class SystemSummaryFormats + { + public: + + static bool + Get(ValueObject& vobj, SummaryFormat::SharedPointer &entry); + + static void + Add(const ConstString &type, const SummaryFormat::SharedPointer &entry); + + static bool + Delete(const ConstString &type); + + static void + Clear(); + + static void + LoopThrough(SummaryFormat::SummaryCallback callback, void* callback_baton); + + static uint32_t + GetCurrentRevision(); + + static uint32_t + GetCount(); + }; + class RegexSummaryFormats { public: @@ -551,6 +577,32 @@ GetCount(); }; + class SystemRegexSummaryFormats + { + public: + + static bool + Get(ValueObject& vobj, SummaryFormat::SharedPointer &entry); + + static void + Add(const lldb::RegularExpressionSP &type, const SummaryFormat::SharedPointer &entry); + + static bool + Delete(const ConstString &type); + + static void + Clear(); + + static void + LoopThrough(SummaryFormat::RegexSummaryCallback callback, void* callback_baton); + + static uint32_t + GetCurrentRevision(); + + static uint32_t + GetCount(); + }; + class NamedSummaryFormats { public: Modified: lldb/trunk/include/lldb/Core/FormatManager.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/FormatManager.h?rev=135326&r1=135325&r2=135326&view=diff ============================================================================== --- lldb/trunk/include/lldb/Core/FormatManager.h (original) +++ lldb/trunk/include/lldb/Core/FormatManager.h Fri Jul 15 18:30:15 2011 @@ -150,19 +150,22 @@ bool m_dont_show_children; bool m_dont_show_value; bool m_show_members_oneliner; + bool m_is_system; SummaryFormat(bool casc = false, bool skipptr = false, bool skipref = false, bool nochildren = true, bool novalue = true, - bool oneliner = false) : + bool oneliner = false, + bool system = false) : m_cascades(casc), m_skip_pointers(skipptr), m_skip_references(skipref), m_dont_show_children(nochildren), m_dont_show_value(novalue), - m_show_members_oneliner(oneliner) + m_show_members_oneliner(oneliner), + m_is_system(system) { } @@ -200,6 +203,12 @@ return m_show_members_oneliner; } + bool + IsSystem() const + { + return m_is_system; + } + virtual ~SummaryFormat() { @@ -228,8 +237,9 @@ bool nochildren = true, bool novalue = true, bool oneliner = false, + bool system = false, std::string f = "") : - SummaryFormat(casc,skipptr,skipref,nochildren,novalue,oneliner), + SummaryFormat(casc,skipptr,skipref,nochildren,novalue,oneliner,system), m_format(f) { } @@ -252,13 +262,14 @@ GetDescription() { StreamString sstr; - sstr.Printf ("`%s`%s%s%s%s%s%s\n", m_format.c_str(), + sstr.Printf ("`%s`%s%s%s%s%s%s%s", m_format.c_str(), m_cascades ? "" : " (not cascading)", m_dont_show_children ? "" : " (show children)", m_dont_show_value ? " (hide value)" : "", m_show_members_oneliner ? " (one-line printout)" : "", m_skip_pointers ? " (skip pointers)" : "", - m_skip_references ? " (skip references)" : ""); + m_skip_references ? " (skip references)" : "", + m_is_system ? " (system)" : ""); return sstr.GetString(); } @@ -276,9 +287,10 @@ bool nochildren = true, bool novalue = true, bool oneliner = false, + bool system = false, std::string fname = "", std::string pscri = "") : - SummaryFormat(casc,skipptr,skipref,nochildren,novalue,oneliner), + SummaryFormat(casc,skipptr,skipref,nochildren,novalue,oneliner,system), m_function_name(fname), m_python_script(pscri) { @@ -312,10 +324,14 @@ GetDescription() { StreamString sstr; - sstr.Printf ("%s%s%s\n%s\n", m_cascades ? "" : " (not cascading)", - m_skip_pointers ? " (skip pointers)" : "", - m_skip_references ? " (skip references)" : "", - m_python_script.c_str()); + sstr.Printf ("%s%s%s%s%s%s%s\n%s", m_cascades ? "" : " (not cascading)", + m_dont_show_children ? "" : " (show children)", + m_dont_show_value ? " (hide value)" : "", + m_show_members_oneliner ? " (one-line printout)" : "", + m_skip_pointers ? " (skip pointers)" : "", + m_skip_references ? " (skip references)" : "", + m_is_system ? " (system)" : "", + m_python_script.c_str()); return sstr.GetString(); } @@ -727,12 +743,12 @@ ValueNavigator m_value_nav; SummaryNavigator m_summary_nav; + SummaryNavigator m_system_summary_nav; RegexSummaryNavigator m_regex_summary_nav; - + RegexSummaryNavigator m_system_regex_summary_nav; + NamedSummariesMap m_named_summaries_map; - - ScriptNavigator m_script_nav; - + uint32_t m_last_revision; public: @@ -740,19 +756,48 @@ FormatManager() : m_value_nav(this), m_summary_nav(this), + m_system_summary_nav(this), m_regex_summary_nav(this), + m_system_regex_summary_nav(this), m_named_summaries_map(this), - m_script_nav(this), m_last_revision(0) { + // add some default stuff + // most formats, summaries, ... actually belong to the users' lldbinit file rather than here + SummaryFormat::SharedPointer string_format(new StringSummaryFormat(false, + true, + false, + true, + false, + false, + true, + "${var%s}")); + + + SummaryFormat::SharedPointer string_array_format(new StringSummaryFormat(false, + true, + false, + false, + false, + false, + true, + "${var%s}")); + + lldb::RegularExpressionSP any_size_char_arr(new RegularExpression("char \\[[0-9]+\\]")); + + + SystemSummary().Add(ConstString("char *").GetCString(), string_format); + SystemSummary().Add(ConstString("const char *").GetCString(), string_format); + SystemRegexSummary().Add(any_size_char_arr, string_array_format); } ValueNavigator& Value() { return m_value_nav; } SummaryNavigator& Summary() { return m_summary_nav; } + SummaryNavigator& SystemSummary() { return m_system_summary_nav; } RegexSummaryNavigator& RegexSummary() { return m_regex_summary_nav; } + RegexSummaryNavigator& SystemRegexSummary() { return m_system_regex_summary_nav; } NamedSummariesMap& NamedSummary() { return m_named_summaries_map; } - ScriptNavigator& Script() { return m_script_nav; } static bool GetFormatFromCString (const char *format_cstr, Modified: lldb/trunk/include/lldb/Core/InputReader.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/InputReader.h?rev=135326&r1=135325&r2=135326&view=diff ============================================================================== --- lldb/trunk/include/lldb/Core/InputReader.h (original) +++ lldb/trunk/include/lldb/Core/InputReader.h Fri Jul 15 18:30:15 2011 @@ -52,6 +52,65 @@ bool GetBatchMode(); }; + + struct InitializationParameters + { + private: + void* m_baton; + lldb::InputReaderGranularity m_token_size; + char* m_end_token; + char* m_prompt; + bool m_echo; + public: + InitializationParameters() : + m_baton(NULL), + m_token_size(lldb::eInputReaderGranularityLine), + m_echo(true) + { + SetEndToken("DONE"); + SetPrompt("> "); + } + + InitializationParameters& + SetEcho(bool e) + { + m_echo = e; + return *this; + } + + InitializationParameters& + SetBaton(void* b) + { + m_baton = b; + return *this; + } + + InitializationParameters& + SetGranularity(lldb::InputReaderGranularity g) + { + m_token_size = g; + return *this; + } + + InitializationParameters& + SetEndToken(const char* e) + { + m_end_token = new char[strlen(e)+1]; + ::strcpy(m_end_token,e); + return *this; + } + + InitializationParameters& + SetPrompt(const char* p) + { + m_prompt = new char[strlen(p)+1]; + ::strcpy(m_prompt,p); + return *this; + } + + friend class InputReaderEZ; + + }; InputReader (Debugger &debugger); @@ -75,6 +134,12 @@ return Error("unimplemented"); } + virtual Error + Initialize(InitializationParameters& params) + { + return Error("unimplemented"); + } + // to use these handlers instead of the Callback function, you must subclass // InputReaderEZ, and redefine the handlers for the events you care about virtual void Modified: lldb/trunk/include/lldb/Core/InputReaderEZ.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/InputReaderEZ.h?rev=135326&r1=135325&r2=135326&view=diff ============================================================================== --- lldb/trunk/include/lldb/Core/InputReaderEZ.h (original) +++ lldb/trunk/include/lldb/Core/InputReaderEZ.h Fri Jul 15 18:30:15 2011 @@ -10,6 +10,8 @@ #ifndef liblldb_InputReaderEZ_h_ #define liblldb_InputReaderEZ_h_ +#include + #include "lldb/lldb-public.h" #include "lldb/lldb-enumerations.h" #include "lldb/Core/Debugger.h" @@ -30,7 +32,7 @@ const char *bytes, size_t bytes_len); public: - + InputReaderEZ (Debugger &debugger) : InputReader(debugger) {} @@ -38,11 +40,15 @@ virtual ~InputReaderEZ (); - virtual Error Initialize(void* baton, - lldb::InputReaderGranularity token_size = lldb::eInputReaderGranularityLine, - const char* end_token = "DONE", - const char *prompt = "> ", - bool echo = true); + virtual Error + Initialize(void* baton, + lldb::InputReaderGranularity token_size = lldb::eInputReaderGranularityLine, + const char* end_token = "DONE", + const char *prompt = "> ", + bool echo = true); + + virtual Error + Initialize(InitializationParameters& params); virtual void ActivateHandler(HandlerData&) {} Modified: lldb/trunk/source/Commands/CommandObjectType.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectType.cpp?rev=135326&r1=135325&r2=135326&view=diff ============================================================================== --- lldb/trunk/source/Commands/CommandObjectType.cpp (original) +++ lldb/trunk/source/Commands/CommandObjectType.cpp Fri Jul 15 18:30:15 2011 @@ -176,7 +176,7 @@ return false; } - if(m_options.m_format == eFormatInvalid) + if (m_options.m_format == eFormatInvalid) { result.AppendErrorWithFormat ("%s needs a valid format.\n", m_cmd_name.c_str()); result.SetStatus(eReturnStatusFailed); @@ -265,7 +265,7 @@ const char* typeA = command.GetArgumentAtIndex(0); ConstString typeCS(typeA); - if(!typeCS) + if (!typeCS) { result.AppendError("empty typenames not allowed"); result.SetStatus(eReturnStatusFailed); @@ -418,34 +418,8 @@ // CommandObjectTypeSummaryAdd //------------------------------------------------------------------------- -class ScriptAddOptions -{ - -public: - - bool m_skip_pointers; - bool m_skip_references; - bool m_cascade; - bool m_callback_is_synchronous; - StringList m_target_types; - StringList m_user_source; - - ScriptAddOptions(bool p, - bool r, - bool c) : - m_skip_pointers(p), - m_skip_references(r), - m_cascade(c), - m_target_types(), - m_user_source() - { - } - - typedef lldb::SharedPtr::Type SharedPointer; - -}; - -static const char *g_reader_instructions = "Enter your Python command(s). Type 'DONE' to end."; +static const char *g_reader_instructions = "Enter your Python command(s). Type 'DONE' to end.\n" + "def function (valobj,dict):"; class TypeScriptAddInputReader : public InputReaderEZ { @@ -560,473 +534,542 @@ script_format.reset(new ScriptSummaryFormat(options->m_cascade, options->m_skip_pointers, options->m_skip_references, - true, - true, - false, + options->m_no_children, + options->m_no_value, + options->m_one_liner, + options->m_is_system, std::string(funct_name), options->m_user_source.CopyList(" "))); + Error error; + for (int i = 0; i < options->m_target_types.GetSize(); i++) { const char *type_name = options->m_target_types.GetStringAtIndex(i); - Debugger::SummaryFormats::Add(ConstString(type_name), script_format); + CommandObjectTypeSummaryAdd::AddSummary(ConstString(type_name), + script_format, + (options->m_regex ? CommandObjectTypeSummaryAdd::eRegexSummary : CommandObjectTypeSummaryAdd::eRegularSummary), + options->m_is_system, + &error); + if (error.Fail()) + { + out_stream->Printf (error.AsCString()); + out_stream->Flush(); + return; + } + } + + if (options->m_name) + { + if ( (bool)(*(options->m_name)) ) + { + CommandObjectTypeSummaryAdd::AddSummary(*(options->m_name), + script_format, + CommandObjectTypeSummaryAdd::eNamedSummary, + options->m_is_system, + &error); + if (error.Fail()) + { + out_stream->Printf (error.AsCString()); + out_stream->Flush(); + return; + } + } + else + { + out_stream->Printf (error.AsCString()); + out_stream->Flush(); + return; + } } } }; -class CommandObjectTypeSummaryAdd : public CommandObject +Error +CommandObjectTypeSummaryAdd::CommandOptions::SetOptionValue (uint32_t option_idx, const char *option_arg) { + Error error; + char short_option = (char) m_getopt_table[option_idx].val; + bool success; + + switch (short_option) + { + case 'C': + m_cascade = Args::StringToBoolean(option_arg, true, &success); + if (!success) + error.SetErrorStringWithFormat("Invalid value for cascade: %s.\n", option_arg); + break; + case 'e': + m_no_children = false; + break; + case 'v': + m_no_value = true; + break; + case 'c': + m_one_liner = true; + break; + case 'f': + m_format_string = std::string(option_arg); + break; + case 'p': + m_skip_pointers = true; + break; + case 'r': + m_skip_references = true; + break; + case 'x': + m_regex = true; + break; + case 'n': + m_name = new ConstString(option_arg); + break; + case 's': + m_python_script = std::string(option_arg); + m_is_add_script = true; + break; + case 'F': + m_python_function = std::string(option_arg); + m_is_add_script = true; + break; + case 'P': + m_is_add_script = true; + break; + case 'w': + m_is_system = true; + break; + default: + error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option); + break; + } -private: - - class CommandOptions : public Options + return error; +} + +void +CommandObjectTypeSummaryAdd::CommandOptions::OptionParsingStarting () +{ + m_cascade = true; + m_no_children = true; + m_no_value = false; + m_one_liner = false; + m_skip_references = false; + m_skip_pointers = false; + m_regex = false; + m_name = NULL; + m_python_script = ""; + m_python_function = ""; + m_is_add_script = false; + m_is_system = false; +} + +void +CommandObjectTypeSummaryAdd::CollectPythonScript (ScriptAddOptions *options, + CommandReturnObject &result) +{ + InputReaderSP reader_sp (new TypeScriptAddInputReader(m_interpreter.GetDebugger())); + if (reader_sp && options) { - public: - CommandOptions (CommandInterpreter &interpreter) : - Options (interpreter) - { - } - - virtual - ~CommandOptions (){} - - virtual Error - SetOptionValue (uint32_t option_idx, const char *option_arg) - { - Error error; - char short_option = (char) m_getopt_table[option_idx].val; - bool success; - - switch (short_option) - { - case 'C': - m_cascade = Args::StringToBoolean(option_arg, true, &success); - if (!success) - error.SetErrorStringWithFormat("Invalid value for cascade: %s.\n", option_arg); - break; - case 'e': - m_no_children = false; - break; - case 'v': - m_no_value = true; - break; - case 'c': - m_one_liner = true; - break; - case 'f': - m_format_string = std::string(option_arg); - break; - case 'p': - m_skip_pointers = true; - break; - case 'r': - m_skip_references = true; - break; - case 'x': - m_regex = true; - break; - case 'n': - m_name = new ConstString(option_arg); - break; - case 's': - m_python_script = std::string(option_arg); - m_is_add_script = true; - break; - case 'F': - m_python_function = std::string(option_arg); - m_is_add_script = true; - break; - case 'P': - m_is_add_script = true; - break; - default: - error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option); - break; - } - - return error; - } + InputReaderEZ::InitializationParameters ipr; - void - OptionParsingStarting () + Error err (reader_sp->Initialize (ipr.SetBaton(options).SetPrompt(" "))); + if (err.Success()) { - m_cascade = true; - m_no_children = true; - m_no_value = false; - m_one_liner = false; - m_skip_references = false; - m_skip_pointers = false; - m_regex = false; - m_name = NULL; - m_python_script = ""; - m_python_function = ""; - m_is_add_script = false; + m_interpreter.GetDebugger().PushInputReader (reader_sp); + result.SetStatus (eReturnStatusSuccessFinishNoResult); } - - const OptionDefinition* - GetDefinitions () + else { - return g_option_table; + result.AppendError (err.AsCString()); + result.SetStatus (eReturnStatusFailed); } - - // Options table: Required for subclasses of Options. - - static OptionDefinition g_option_table[]; - - // Instance variables to hold the values for command options. - - bool m_cascade; - bool m_no_children; - bool m_no_value; - bool m_one_liner; - bool m_skip_references; - bool m_skip_pointers; - bool m_regex; - std::string m_format_string; - ConstString* m_name; - std::string m_python_script; - std::string m_python_function; - bool m_is_add_script; - }; + } + else + { + result.AppendError("out of memory"); + result.SetStatus (eReturnStatusFailed); + } - CommandOptions m_options; +} + +bool +CommandObjectTypeSummaryAdd::Execute_ScriptSummary (Args& command, CommandReturnObject &result) +{ + const size_t argc = command.GetArgumentCount(); - virtual Options * - GetOptions () + if (argc < 1 && !m_options.m_name) { - return &m_options; + result.AppendErrorWithFormat ("%s takes one or more args.\n", m_cmd_name.c_str()); + result.SetStatus(eReturnStatusFailed); + return false; } -public: - CommandObjectTypeSummaryAdd (CommandInterpreter &interpreter) : - CommandObject (interpreter, - "type summary add", - "Add a new summary style for a type.", - NULL), m_options (interpreter) - { - CommandArgumentEntry type_arg; - CommandArgumentData type_style_arg; - - type_style_arg.arg_type = eArgTypeName; - type_style_arg.arg_repetition = eArgRepeatPlus; - - type_arg.push_back (type_style_arg); - - m_arguments.push_back (type_arg); - - SetHelpLong( - "Some examples of using this command.\n" - "We use as reference the following snippet of code:\n" - "struct JustADemo\n" - "{\n" - "int* ptr;\n" - "float value;\n" - "JustADemo(int p = 1, float v = 0.1) : ptr(new int(p)), value(v) {}\n" - "};\n" - "JustADemo object(42,3.14);\n" - "struct AnotherDemo : public JustADemo\n" - "{\n" - "uint8_t byte;\n" - "AnotherDemo(uint8_t b = 'E', int p = 1, float v = 0.1) : JustADemo(p,v), byte(b) {}\n" - "};\n" - "AnotherDemo *another_object = new AnotherDemo('E',42,3.14);\n" - "\n" - "type summary add -f \"the answer is ${*var.ptr}\" JustADemo\n" - "when typing frame variable object you will get \"the answer is 42\"\n" - "type summary add -f \"the answer is ${*var.ptr}, and the question is ${var.value}\" JustADemo\n" - "when typing frame variable object you will get \"the answer is 42 and the question is 3.14\"\n" - "\n" - "Alternatively, you could also say\n" - "type summary add -f \"${var%V} -> ${*var}\" \"int *\"\n" - "and replace the above summary string with\n" - "type summary add -f \"the answer is ${var.ptr}, and the question is ${var.value}\" JustADemo\n" - "to obtain a similar result\n" - "\n" - "To add a summary valid for both JustADemo and AnotherDemo you can use the scoping operator, as in:\n" - "type summary add -f \"${var.ptr}, ${var.value},{${var.byte}}\" JustADemo -C yes\n" - "\n" - "This will be used for both variables of type JustADemo and AnotherDemo. To prevent this, change the -C to read -C no\n" - "If you do not want pointers to be shown using that summary, you can use the -p option, as in:\n" - "type summary add -f \"${var.ptr}, ${var.value},{${var.byte}}\" JustADemo -C yes -p\n" - "A similar option -r exists for references.\n" - "\n" - "If you simply want a one-line summary of the content of your variable, without typing an explicit string to that effect\n" - "you can use the -c option, without giving any summary string:\n" - "type summary add -c JustADemo\n" - "frame variable object\n" - "the output being similar to (ptr=0xsomeaddress, value=3.14)\n" - "\n" - "If you want to display some summary text, but also expand the structure of your object, you can add the -e option, as in:\n" - "type summary add -e -f \"*ptr = ${*var.ptr}\" JustADemo\n" - "Here the value of the int* is displayed, followed by the standard LLDB sequence of children objects, one per line.\n" - "to get an output like:\n" - "\n" - "*ptr = 42 {\n" - " ptr = 0xsomeaddress\n" - " value = 3.14\n" - "}\n" - "\n" - "A command you may definitely want to try if you're doing C++ debugging is:\n" - "type summary add -f \"${var._M_dataplus._M_p}\" std::string\n" - ); - } - - ~CommandObjectTypeSummaryAdd () - { - } - - void - CollectPythonScript - ( - ScriptAddOptions *options, - CommandReturnObject &result - ) + SummaryFormatSP script_format; + + if (!m_options.m_python_function.empty()) // we have a Python function ready to use { - InputReaderSP reader_sp (new TypeScriptAddInputReader(m_interpreter.GetDebugger())); - if (reader_sp && options) + ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter(); + if (!interpreter) { - - Error err (reader_sp->Initialize (options)); - if (err.Success()) - { - m_interpreter.GetDebugger().PushInputReader (reader_sp); - result.SetStatus (eReturnStatusSuccessFinishNoResult); - } - else - { - result.AppendError (err.AsCString()); - result.SetStatus (eReturnStatusFailed); - } + result.AppendError ("Internal error #1N: no script attached.\n"); + result.SetStatus (eReturnStatusFailed); + return false; } - else + const char *funct_name = m_options.m_python_function.c_str(); + if (!funct_name || !funct_name[0]) { - result.AppendError("out of memory"); + result.AppendError ("Internal error #2N: no script attached.\n"); result.SetStatus (eReturnStatusFailed); + return false; } + script_format.reset(new ScriptSummaryFormat(m_options.m_cascade, + m_options.m_skip_pointers, + m_options.m_skip_references, + m_options.m_no_children, + m_options.m_no_value, + m_options.m_one_liner, + m_options.m_is_system, + std::string(funct_name), + " " + m_options.m_python_function + "(valobj,dict)")); } - - bool - Execute (Args& command, CommandReturnObject &result) - { - if (m_options.m_is_add_script) - return Execute_ScriptSummary(command, result); - else - return Execute_StringSummary(command, result); - } - - bool - Execute_ScriptSummary (Args& command, CommandReturnObject &result) + else if (!m_options.m_python_script.empty()) // we have a quick 1-line script, just use it { - const size_t argc = command.GetArgumentCount(); - - if (argc < 1) + ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter(); + if (!interpreter) { - result.AppendErrorWithFormat ("%s takes one or more args.\n", m_cmd_name.c_str()); - result.SetStatus(eReturnStatusFailed); + result.AppendError ("Internal error #1Q: no script attached.\n"); + result.SetStatus (eReturnStatusFailed); return false; } - - if (!m_options.m_python_function.empty()) // we have a Python function ready to use + StringList funct_sl; + funct_sl << m_options.m_python_script.c_str(); + StringList funct_name_sl; + if (!interpreter->GenerateTypeScriptFunction (funct_sl, + funct_name_sl)) { - ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter(); - if (!interpreter) - { - result.AppendError ("Internal error #1N: no script attached.\n"); - result.SetStatus (eReturnStatusFailed); - return false; - } - const char *funct_name = m_options.m_python_function.c_str(); - if (!funct_name || !funct_name[0]) - { - result.AppendError ("Internal error #2N: no script attached.\n"); - result.SetStatus (eReturnStatusFailed); - return false; - } - // now I have a valid function name, let's add this as script for every type in the list - - SummaryFormatSP script_format; - script_format.reset(new ScriptSummaryFormat(m_options.m_cascade, - m_options.m_skip_pointers, - m_options.m_skip_references, - true, - true, - false, - std::string(funct_name), - " " + m_options.m_python_function + "(valobj,dict)")); - - for (int i = 0; i < command.GetArgumentCount(); i++) - { - const char *type_name = command.GetArgumentAtIndex(i); - Debugger::SummaryFormats::Add(ConstString(type_name), script_format); - } + result.AppendError ("Internal error #2Q: no script attached.\n"); + result.SetStatus (eReturnStatusFailed); + return false; } - else if (m_options.m_python_script.empty()) // use an InputReader to grab Python code from the user - { - ScriptAddOptions *options = new ScriptAddOptions(m_options.m_skip_pointers, - m_options.m_skip_references, - m_options.m_cascade); - - for(int i = 0; i < argc; i++) { - const char* typeA = command.GetArgumentAtIndex(i); - if (typeA && *typeA) - options->m_target_types << typeA; - else - { - result.AppendError("empty typenames not allowed"); - result.SetStatus(eReturnStatusFailed); - return false; - } - } - - CollectPythonScript(options,result); - return result.Succeeded(); + if (funct_name_sl.GetSize() == 0) + { + result.AppendError ("Internal error #3Q: no script attached.\n"); + result.SetStatus (eReturnStatusFailed); + return false; } - else // we have a quick 1-line script, just use it + const char *funct_name = funct_name_sl.GetStringAtIndex(0); + if (!funct_name || !funct_name[0]) { - ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter(); - if (!interpreter) - { - result.AppendError ("Internal error #1Q: no script attached.\n"); - result.SetStatus (eReturnStatusFailed); - return false; - } - StringList funct_sl; - funct_sl << m_options.m_python_script.c_str(); - StringList funct_name_sl; - if (!interpreter->GenerateTypeScriptFunction (funct_sl, - funct_name_sl)) - { - result.AppendError ("Internal error #2Q: no script attached.\n"); - result.SetStatus (eReturnStatusFailed); - return false; - } - if (funct_name_sl.GetSize() == 0) - { - result.AppendError ("Internal error #3Q: no script attached.\n"); - result.SetStatus (eReturnStatusFailed); - return false; - } - const char *funct_name = funct_name_sl.GetStringAtIndex(0); - if (!funct_name || !funct_name[0]) + result.AppendError ("Internal error #4Q: no script attached.\n"); + result.SetStatus (eReturnStatusFailed); + return false; + } + + script_format.reset(new ScriptSummaryFormat(m_options.m_cascade, + m_options.m_skip_pointers, + m_options.m_skip_references, + m_options.m_no_children, + m_options.m_no_value, + m_options.m_one_liner, + m_options.m_is_system, + std::string(funct_name), + " " + m_options.m_python_script)); + } + else // use an InputReader to grab Python code from the user + { + ScriptAddOptions *options = new ScriptAddOptions(m_options.m_skip_pointers, + m_options.m_skip_references, + m_options.m_cascade, + m_options.m_no_children, + m_options.m_no_value, + m_options.m_one_liner, + m_options.m_regex, + m_options.m_is_system, + m_options.m_name); + + for(int i = 0; i < argc; i++) { + const char* typeA = command.GetArgumentAtIndex(i); + if (typeA && *typeA) + options->m_target_types << typeA; + else { - result.AppendError ("Internal error #4Q: no script attached.\n"); - result.SetStatus (eReturnStatusFailed); + result.AppendError("empty typenames not allowed"); + result.SetStatus(eReturnStatusFailed); return false; } - // now I have a valid function name, let's add this as script for every type in the list - - ScriptFormatSP script_format; - script_format.reset(new ScriptSummaryFormat(m_options.m_cascade, - m_options.m_skip_pointers, - m_options.m_skip_references, - true, - true, - false, - std::string(funct_name), - " " + m_options.m_python_script)); - - for (int i = 0; i < command.GetArgumentCount(); i++) - { - const char *type_name = command.GetArgumentAtIndex(i); - Debugger::SummaryFormats::Add(ConstString(type_name), script_format); - } } + CollectPythonScript(options,result); return result.Succeeded(); } - - bool - Execute_StringSummary (Args& command, CommandReturnObject &result) + + // if I am here, script_format must point to something good, so I can add that + // as a script summary to all interested parties + + Error error; + + for (int i = 0; i < command.GetArgumentCount(); i++) { - const size_t argc = command.GetArgumentCount(); - - if (argc < 1 && !m_options.m_name) + const char *type_name = command.GetArgumentAtIndex(i); + CommandObjectTypeSummaryAdd::AddSummary(ConstString(type_name), + script_format, + (m_options.m_regex ? eRegexSummary : eRegularSummary), + m_options.m_is_system, + &error); + if (error.Fail()) { - result.AppendErrorWithFormat ("%s takes one or more args.\n", m_cmd_name.c_str()); + result.AppendError(error.AsCString()); result.SetStatus(eReturnStatusFailed); return false; } - - if(!m_options.m_one_liner && m_options.m_format_string.empty()) + } + + if (m_options.m_name) + { + if ( (bool)(*(m_options.m_name)) ) { - result.AppendError("empty summary strings not allowed"); + AddSummary(*(m_options.m_name), script_format, eNamedSummary, m_options.m_is_system, &error); + if (error.Fail()) + { + result.AppendError(error.AsCString()); + result.AppendError("added to types, but not given a name"); + result.SetStatus(eReturnStatusFailed); + return false; + } + } + else + { + result.AppendError("added to types, but not given a name"); result.SetStatus(eReturnStatusFailed); return false; } - - const char* format_cstr = (m_options.m_one_liner ? "" : m_options.m_format_string.c_str()); - - Error error; - - SummaryFormat::SharedPointer entry(new StringSummaryFormat(m_options.m_cascade, - m_options.m_skip_pointers, - m_options.m_skip_references, - m_options.m_no_children, - m_options.m_no_value, - m_options.m_one_liner, - format_cstr)); - - if (error.Fail()) + } + + return result.Succeeded(); +} + +bool +CommandObjectTypeSummaryAdd::Execute_StringSummary (Args& command, CommandReturnObject &result) +{ + const size_t argc = command.GetArgumentCount(); + + if (argc < 1 && !m_options.m_name) + { + result.AppendErrorWithFormat ("%s takes one or more args.\n", m_cmd_name.c_str()); + result.SetStatus(eReturnStatusFailed); + return false; + } + + if (!m_options.m_one_liner && m_options.m_format_string.empty()) + { + result.AppendError("empty summary strings not allowed"); + result.SetStatus(eReturnStatusFailed); + return false; + } + + const char* format_cstr = (m_options.m_one_liner ? "" : m_options.m_format_string.c_str()); + + Error error; + + SummaryFormat::SharedPointer entry(new StringSummaryFormat(m_options.m_cascade, + m_options.m_skip_pointers, + m_options.m_skip_references, + m_options.m_no_children, + m_options.m_no_value, + m_options.m_one_liner, + m_options.m_is_system, + format_cstr)); + + if (error.Fail()) + { + result.AppendError(error.AsCString()); + result.SetStatus(eReturnStatusFailed); + return false; + } + + // now I have a valid format, let's add it to every type + + for(int i = 0; i < argc; i++) { + const char* typeA = command.GetArgumentAtIndex(i); + if (!typeA || typeA[0] == '\0') { - result.AppendError(error.AsCString()); + result.AppendError("empty typenames not allowed"); result.SetStatus(eReturnStatusFailed); return false; } + ConstString typeCS(typeA); - // now I have a valid format, let's add it to every type + AddSummary(typeCS, + entry, + (m_options.m_regex ? eRegexSummary : eRegularSummary), + m_options.m_is_system, + &error); - for(int i = 0; i < argc; i++) { - const char* typeA = command.GetArgumentAtIndex(i); - if (!typeA || typeA[0] == '\0') - { - result.AppendError("empty typenames not allowed"); - result.SetStatus(eReturnStatusFailed); - return false; - } - ConstString typeCS(typeA); - if (!m_options.m_regex) - { - Debugger::SummaryFormats::Add(typeCS, entry); - } - else - { - RegularExpressionSP typeRX(new RegularExpression()); - if(!typeRX->Compile(typeA)) - { - result.AppendError("regex format error (maybe this is not really a regex?)"); - result.SetStatus(eReturnStatusFailed); - return false; - } - Debugger::RegexSummaryFormats::Delete(typeCS); - Debugger::RegexSummaryFormats::Add(typeRX, entry); - } + if (error.Fail()) + { + result.AppendError(error.AsCString()); + result.SetStatus(eReturnStatusFailed); + return false; } - - if (m_options.m_name) + } + + if (m_options.m_name) + { + if ( (bool)(*(m_options.m_name)) ) { - if( (bool)(*(m_options.m_name)) ) - { - Debugger::NamedSummaryFormats::Add(*(m_options.m_name), entry); - } - else + AddSummary(*(m_options.m_name), entry, eNamedSummary, m_options.m_is_system, &error); + if (error.Fail()) { + result.AppendError(error.AsCString()); result.AppendError("added to types, but not given a name"); result.SetStatus(eReturnStatusFailed); return false; } } - - result.SetStatus(eReturnStatusSuccessFinishNoResult); - return result.Succeeded(); + else + { + result.AppendError("added to types, but not given a name"); + result.SetStatus(eReturnStatusFailed); + return false; + } } -}; + result.SetStatus(eReturnStatusSuccessFinishNoResult); + return result.Succeeded(); +} + +CommandObjectTypeSummaryAdd::CommandObjectTypeSummaryAdd (CommandInterpreter &interpreter) : +CommandObject (interpreter, + "type summary add", + "Add a new summary style for a type.", + NULL), m_options (interpreter) +{ + CommandArgumentEntry type_arg; + CommandArgumentData type_style_arg; + + type_style_arg.arg_type = eArgTypeName; + type_style_arg.arg_repetition = eArgRepeatPlus; + + type_arg.push_back (type_style_arg); + + m_arguments.push_back (type_arg); + + SetHelpLong( + "Some examples of using this command.\n" + "We use as reference the following snippet of code:\n" + "struct JustADemo\n" + "{\n" + "int* ptr;\n" + "float value;\n" + "JustADemo(int p = 1, float v = 0.1) : ptr(new int(p)), value(v) {}\n" + "};\n" + "JustADemo object(42,3.14);\n" + "struct AnotherDemo : public JustADemo\n" + "{\n" + "uint8_t byte;\n" + "AnotherDemo(uint8_t b = 'E', int p = 1, float v = 0.1) : JustADemo(p,v), byte(b) {}\n" + "};\n" + "AnotherDemo *another_object = new AnotherDemo('E',42,3.14);\n" + "\n" + "type summary add -f \"the answer is ${*var.ptr}\" JustADemo\n" + "when typing frame variable object you will get \"the answer is 42\"\n" + "type summary add -f \"the answer is ${*var.ptr}, and the question is ${var.value}\" JustADemo\n" + "when typing frame variable object you will get \"the answer is 42 and the question is 3.14\"\n" + "\n" + "Alternatively, you could also say\n" + "type summary add -f \"${var%V} -> ${*var}\" \"int *\"\n" + "and replace the above summary string with\n" + "type summary add -f \"the answer is ${var.ptr}, and the question is ${var.value}\" JustADemo\n" + "to obtain a similar result\n" + "\n" + "To add a summary valid for both JustADemo and AnotherDemo you can use the scoping operator, as in:\n" + "type summary add -f \"${var.ptr}, ${var.value},{${var.byte}}\" JustADemo -C yes\n" + "\n" + "This will be used for both variables of type JustADemo and AnotherDemo. To prevent this, change the -C to read -C no\n" + "If you do not want pointers to be shown using that summary, you can use the -p option, as in:\n" + "type summary add -f \"${var.ptr}, ${var.value},{${var.byte}}\" JustADemo -C yes -p\n" + "A similar option -r exists for references.\n" + "\n" + "If you simply want a one-line summary of the content of your variable, without typing an explicit string to that effect\n" + "you can use the -c option, without giving any summary string:\n" + "type summary add -c JustADemo\n" + "frame variable object\n" + "the output being similar to (ptr=0xsomeaddress, value=3.14)\n" + "\n" + "If you want to display some summary text, but also expand the structure of your object, you can add the -e option, as in:\n" + "type summary add -e -f \"*ptr = ${*var.ptr}\" JustADemo\n" + "Here the value of the int* is displayed, followed by the standard LLDB sequence of children objects, one per line.\n" + "to get an output like:\n" + "\n" + "*ptr = 42 {\n" + " ptr = 0xsomeaddress\n" + " value = 3.14\n" + "}\n" + "\n" + "A command you may definitely want to try if you're doing C++ debugging is:\n" + "type summary add -f \"${var._M_dataplus._M_p}\" std::string\n" + ); +} + +bool +CommandObjectTypeSummaryAdd::Execute (Args& command, CommandReturnObject &result) +{ + if (m_options.m_is_add_script) + return Execute_ScriptSummary(command, result); + else + return Execute_StringSummary(command, result); +} + +bool +CommandObjectTypeSummaryAdd::AddSummary(const ConstString& type_name, + SummaryFormatSP entry, + SummaryFormatType type, + bool is_system, + Error* error) +{ + if (type == eRegexSummary) + { + RegularExpressionSP typeRX(new RegularExpression()); + if (!typeRX->Compile(type_name.GetCString())) + { + if (error) + error->SetErrorString("regex format error (maybe this is not really a regex?)"); + return false; + } + + if (!is_system) + { + Debugger::RegexSummaryFormats::Delete(type_name); + Debugger::RegexSummaryFormats::Add(typeRX, entry); + } + else + { + Debugger::SystemRegexSummaryFormats::Delete(type_name); + Debugger::SystemRegexSummaryFormats::Add(typeRX, entry); + } + return true; + } + else if (type == eNamedSummary) + { + // system named summaries do not exist (yet?) + Debugger::NamedSummaryFormats::Add(type_name,entry); + return true; + } + else + { + if (!is_system) + Debugger::SummaryFormats::Add(type_name,entry); + else + Debugger::SystemSummaryFormats::Add(type_name,entry); + return true; + } +} OptionDefinition CommandObjectTypeSummaryAdd::CommandOptions::g_option_table[] = { + { LLDB_OPT_SET_ALL, false, "system", 'w', no_argument, NULL, 0, eArgTypeBoolean, "This is a system summary (makes it harder to delete it by accident)."}, { LLDB_OPT_SET_ALL, false, "cascade", 'C', required_argument, NULL, 0, eArgTypeBoolean, "If true, cascade to derived typedefs."}, { LLDB_OPT_SET_ALL, false, "no-value", 'v', no_argument, NULL, 0, eArgTypeBoolean, "Don't show the value, just show the summary, for this type."}, { LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', no_argument, NULL, 0, eArgTypeBoolean, "Don't use this format for pointers-to-type objects."}, @@ -1034,11 +1077,11 @@ { LLDB_OPT_SET_ALL, false, "regex", 'x', no_argument, NULL, 0, eArgTypeBoolean, "Type names are actually regular expressions."}, { LLDB_OPT_SET_1 , true, "inline-children", 'c', no_argument, NULL, 0, eArgTypeBoolean, "If true, inline all child values into summary string."}, { LLDB_OPT_SET_2 , true, "format-string", 'f', required_argument, NULL, 0, eArgTypeSummaryString, "Format string used to display text and object contents."}, - { LLDB_OPT_SET_2, false, "expand", 'e', no_argument, NULL, 0, eArgTypeBoolean, "Expand aggregate data types to show children on separate lines."}, - { LLDB_OPT_SET_2, false, "name", 'n', required_argument, NULL, 0, eArgTypeName, "A name for this summary string."}, { LLDB_OPT_SET_3, false, "python-script", 's', required_argument, NULL, 0, eArgTypeName, "Give a one-liner Python script as part of the command."}, { LLDB_OPT_SET_3, false, "python-function", 'F', required_argument, NULL, 0, eArgTypeName, "Give the name of a Python function to use for this type."}, { LLDB_OPT_SET_3, false, "input-python", 'P', no_argument, NULL, 0, eArgTypeName, "Input Python code to use for this type manually."}, + { LLDB_OPT_SET_2 | LLDB_OPT_SET_3, false, "expand", 'e', no_argument, NULL, 0, eArgTypeBoolean, "Expand aggregate data types to show children on separate lines."}, + { LLDB_OPT_SET_2 | LLDB_OPT_SET_3, false, "name", 'n', required_argument, NULL, 0, eArgTypeName, "A name for this summary string."}, { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } }; @@ -1049,12 +1092,73 @@ class CommandObjectTypeSummaryDelete : public CommandObject { +private: + class CommandOptions : public Options + { + public: + + CommandOptions (CommandInterpreter &interpreter) : + Options (interpreter) + { + } + + virtual + ~CommandOptions (){} + + virtual Error + SetOptionValue (uint32_t option_idx, const char *option_arg) + { + Error error; + char short_option = (char) m_getopt_table[option_idx].val; + + switch (short_option) + { + case 'a': + m_delete_system = true; + break; + default: + error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option); + break; + } + + return error; + } + + void + OptionParsingStarting () + { + m_delete_system = false; + } + + const OptionDefinition* + GetDefinitions () + { + return g_option_table; + } + + // Options table: Required for subclasses of Options. + + static OptionDefinition g_option_table[]; + + // Instance variables to hold the values for command options. + + bool m_delete_system; + }; + + CommandOptions m_options; + + virtual Options * + GetOptions () + { + return &m_options; + } + public: CommandObjectTypeSummaryDelete (CommandInterpreter &interpreter) : CommandObject (interpreter, "type summary delete", "Delete an existing summary style for a type.", - NULL) + NULL), m_options(interpreter) { CommandArgumentEntry type_arg; CommandArgumentData type_style_arg; @@ -1087,7 +1191,7 @@ const char* typeA = command.GetArgumentAtIndex(0); ConstString typeCS(typeA); - if(!typeCS) + if (!typeCS) { result.AppendError("empty typenames not allowed"); result.SetStatus(eReturnStatusFailed); @@ -1097,8 +1201,10 @@ bool delete_summary = Debugger::SummaryFormats::Delete(typeCS); bool delete_regex = Debugger::RegexSummaryFormats::Delete(typeCS); bool delete_named = Debugger::NamedSummaryFormats::Delete(typeCS); + bool delete_sys = m_options.m_delete_system ? Debugger::SystemSummaryFormats::Delete(typeCS) : false; + bool delete_sys_regex = m_options.m_delete_system ? Debugger::SystemRegexSummaryFormats::Delete(typeCS) : false; - if (delete_summary || delete_regex || delete_named) + if (delete_summary || delete_regex || delete_named || delete_sys || delete_sys_regex) { result.SetStatus(eReturnStatusSuccessFinishNoResult); return result.Succeeded(); @@ -1111,7 +1217,13 @@ } } - +}; + +OptionDefinition +CommandObjectTypeSummaryDelete::CommandOptions::g_option_table[] = +{ + { LLDB_OPT_SET_ALL, false, "all", 'a', no_argument, NULL, 0, eArgTypeBoolean, "Also delete system summaries (not recommended)."}, + { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } }; //------------------------------------------------------------------------- @@ -1120,12 +1232,74 @@ class CommandObjectTypeSummaryClear : public CommandObject { +private: + + class CommandOptions : public Options + { + public: + + CommandOptions (CommandInterpreter &interpreter) : + Options (interpreter) + { + } + + virtual + ~CommandOptions (){} + + virtual Error + SetOptionValue (uint32_t option_idx, const char *option_arg) + { + Error error; + char short_option = (char) m_getopt_table[option_idx].val; + + switch (short_option) + { + case 'a': + m_delete_system = true; + break; + default: + error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option); + break; + } + + return error; + } + + void + OptionParsingStarting () + { + m_delete_system = false; + } + + const OptionDefinition* + GetDefinitions () + { + return g_option_table; + } + + // Options table: Required for subclasses of Options. + + static OptionDefinition g_option_table[]; + + // Instance variables to hold the values for command options. + + bool m_delete_system; + }; + + CommandOptions m_options; + + virtual Options * + GetOptions () + { + return &m_options; + } + public: CommandObjectTypeSummaryClear (CommandInterpreter &interpreter) : CommandObject (interpreter, "type summary clear", "Delete all existing summary styles.", - NULL) + NULL), m_options(interpreter) { } @@ -1139,12 +1313,26 @@ Debugger::SummaryFormats::Clear(); Debugger::RegexSummaryFormats::Clear(); Debugger::NamedSummaryFormats::Clear(); + + if (m_options.m_delete_system) + { + Debugger::SystemSummaryFormats::Clear(); + Debugger::SystemRegexSummaryFormats::Clear(); + } + result.SetStatus(eReturnStatusSuccessFinishResult); return result.Succeeded(); } }; +OptionDefinition +CommandObjectTypeSummaryClear::CommandOptions::g_option_table[] = +{ + { LLDB_OPT_SET_ALL, false, "all", 'a', no_argument, NULL, 0, eArgTypeBoolean, "Also clear system summaries (not recommended)."}, + { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } +}; + //------------------------------------------------------------------------- // CommandObjectTypeSummaryList //------------------------------------------------------------------------- @@ -1210,9 +1398,10 @@ else param = new CommandObjectTypeSummaryList_LoopCallbackParam(this,&result); Debugger::SummaryFormats::LoopThrough(CommandObjectTypeSummaryList_LoopCallback, param); + Debugger::SystemSummaryFormats::LoopThrough(CommandObjectTypeSummaryList_LoopCallback, param); delete param; - if(Debugger::RegexSummaryFormats::GetCount() > 0) + if (Debugger::RegexSummaryFormats::GetCount() > 0 || Debugger::SystemRegexSummaryFormats::GetCount() > 0 ) { result.GetOutputStream().Printf("Regex-based summaries (slower):\n"); if (argc == 1) { @@ -1223,10 +1412,11 @@ else rxparam = new CommandObjectTypeRXSummaryList_LoopCallbackParam(this,&result); Debugger::RegexSummaryFormats::LoopThrough(CommandObjectTypeRXSummaryList_LoopCallback, rxparam); + Debugger::SystemRegexSummaryFormats::LoopThrough(CommandObjectTypeRXSummaryList_LoopCallback, rxparam); delete rxparam; } - if(Debugger::NamedSummaryFormats::GetCount() > 0) + if (Debugger::NamedSummaryFormats::GetCount() > 0) { result.GetOutputStream().Printf("Named summaries:\n"); if (argc == 1) { @@ -1259,7 +1449,6 @@ friend bool CommandObjectTypeSummaryList_LoopCallback(void* pt2self, const char* type, const SummaryFormat::SharedPointer& entry); friend bool CommandObjectTypeRXSummaryList_LoopCallback(void* pt2self, lldb::RegularExpressionSP regex, const SummaryFormat::SharedPointer& entry); - }; bool @@ -1282,7 +1471,6 @@ return param->self->LoopCallback(regex->GetText(), entry, param->regex, param->result); } - class CommandObjectTypeFormat : public CommandObjectMultiword { public: Modified: lldb/trunk/source/Commands/CommandObjectType.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectType.h?rev=135326&r1=135325&r2=135326&view=diff ============================================================================== --- lldb/trunk/source/Commands/CommandObjectType.h (original) +++ lldb/trunk/source/Commands/CommandObjectType.h Fri Jul 15 18:30:15 2011 @@ -19,13 +19,57 @@ #include "lldb/lldb-types.h" #include "lldb/Interpreter/CommandObjectMultiword.h" +#include "lldb/Interpreter/Options.h" namespace lldb_private { -//------------------------------------------------------------------------- -// CommandObjectMultiwordBreakpoint -//------------------------------------------------------------------------- - +class ScriptAddOptions +{ + +public: + + bool m_skip_pointers; + bool m_skip_references; + bool m_cascade; + StringList m_target_types; + StringList m_user_source; + + bool m_no_children; + bool m_no_value; + bool m_one_liner; + bool m_regex; + + bool m_is_system; + + ConstString* m_name; + + ScriptAddOptions(bool sptr, + bool sref, + bool casc, + bool noch, + bool novl, + bool onel, + bool regx, + bool syst, + ConstString* name) : + m_skip_pointers(sptr), + m_skip_references(sref), + m_cascade(casc), + m_target_types(), + m_user_source(), + m_no_children(noch), + m_no_value(novl), + m_one_liner(onel), + m_regex(regx), + m_is_system(syst), + m_name(name) + { + } + + typedef lldb::SharedPtr::Type SharedPointer; + +}; + class CommandObjectType : public CommandObjectMultiword { public: @@ -35,6 +79,99 @@ ~CommandObjectType (); }; +class CommandObjectTypeSummaryAdd : public CommandObject +{ + +private: + + class CommandOptions : public Options + { + public: + + CommandOptions (CommandInterpreter &interpreter) : + Options (interpreter) + { + } + + virtual + ~CommandOptions (){} + + virtual Error + SetOptionValue (uint32_t option_idx, const char *option_arg); + + void + OptionParsingStarting (); + + const OptionDefinition* + GetDefinitions () + { + return g_option_table; + } + + // Options table: Required for subclasses of Options. + + static OptionDefinition g_option_table[]; + + // Instance variables to hold the values for command options. + + bool m_cascade; + bool m_no_children; + bool m_no_value; + bool m_one_liner; + bool m_skip_references; + bool m_skip_pointers; + bool m_regex; + std::string m_format_string; + ConstString* m_name; + std::string m_python_script; + std::string m_python_function; + bool m_is_add_script; + bool m_is_system; + }; + + CommandOptions m_options; + + virtual Options * + GetOptions () + { + return &m_options; + } + + void + CollectPythonScript(ScriptAddOptions *options, + CommandReturnObject &result); + + bool + Execute_ScriptSummary (Args& command, CommandReturnObject &result); + + bool + Execute_StringSummary (Args& command, CommandReturnObject &result); + +public: + + enum SummaryFormatType + { + eRegularSummary, + eRegexSummary, + eNamedSummary, + }; + + CommandObjectTypeSummaryAdd (CommandInterpreter &interpreter); + + ~CommandObjectTypeSummaryAdd () + { + } + + bool + Execute (Args& command, CommandReturnObject &result); + + static bool + AddSummary(const ConstString& type_name, + lldb::SummaryFormatSP entry, + SummaryFormatType type, + bool is_system, + Error* error = NULL); +}; } // namespace lldb_private Modified: lldb/trunk/source/Core/Debugger.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/Debugger.cpp?rev=135326&r1=135325&r2=135326&view=diff ============================================================================== --- lldb/trunk/source/Core/Debugger.cpp (original) +++ lldb/trunk/source/Core/Debugger.cpp Fri Jul 15 18:30:15 2011 @@ -1798,6 +1798,48 @@ } bool +Debugger::SystemSummaryFormats::Get(ValueObject& vobj, SummaryFormat::SharedPointer &entry) +{ + return GetFormatManager().SystemSummary().Get(vobj,entry); +} + +void +Debugger::SystemSummaryFormats::Add(const ConstString &type, const SummaryFormat::SharedPointer &entry) +{ + GetFormatManager().SystemSummary().Add(type.AsCString(),entry); +} + +bool +Debugger::SystemSummaryFormats::Delete(const ConstString &type) +{ + return GetFormatManager().SystemSummary().Delete(type.AsCString()); +} + +void +Debugger::SystemSummaryFormats::Clear() +{ + GetFormatManager().SystemSummary().Clear(); +} + +void +Debugger::SystemSummaryFormats::LoopThrough(SummaryFormat::SummaryCallback callback, void* callback_baton) +{ + GetFormatManager().SystemSummary().LoopThrough(callback, callback_baton); +} + +uint32_t +Debugger::SystemSummaryFormats::GetCurrentRevision() +{ + return GetFormatManager().GetCurrentRevision(); +} + +uint32_t +Debugger::SystemSummaryFormats::GetCount() +{ + return GetFormatManager().SystemSummary().GetCount(); +} + +bool Debugger::RegexSummaryFormats::Get(ValueObject& vobj, SummaryFormat::SharedPointer &entry) { return GetFormatManager().RegexSummary().Get(vobj,entry); @@ -1840,6 +1882,48 @@ } bool +Debugger::SystemRegexSummaryFormats::Get(ValueObject& vobj, SummaryFormat::SharedPointer &entry) +{ + return GetFormatManager().SystemRegexSummary().Get(vobj,entry); +} + +void +Debugger::SystemRegexSummaryFormats::Add(const lldb::RegularExpressionSP &type, const SummaryFormat::SharedPointer &entry) +{ + GetFormatManager().SystemRegexSummary().Add(type,entry); +} + +bool +Debugger::SystemRegexSummaryFormats::Delete(const ConstString &type) +{ + return GetFormatManager().SystemRegexSummary().Delete(type.AsCString()); +} + +void +Debugger::SystemRegexSummaryFormats::Clear() +{ + GetFormatManager().SystemRegexSummary().Clear(); +} + +void +Debugger::SystemRegexSummaryFormats::LoopThrough(SummaryFormat::RegexSummaryCallback callback, void* callback_baton) +{ + GetFormatManager().SystemRegexSummary().LoopThrough(callback, callback_baton); +} + +uint32_t +Debugger::SystemRegexSummaryFormats::GetCurrentRevision() +{ + return GetFormatManager().GetCurrentRevision(); +} + +uint32_t +Debugger::SystemRegexSummaryFormats::GetCount() +{ + return GetFormatManager().SystemRegexSummary().GetCount(); +} + +bool Debugger::NamedSummaryFormats::Get(const ConstString &type, SummaryFormat::SharedPointer &entry) { return GetFormatManager().NamedSummary().Get(type.AsCString(),entry); Modified: lldb/trunk/source/Core/InputReaderEZ.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/InputReaderEZ.cpp?rev=135326&r1=135325&r2=135326&view=diff ============================================================================== --- lldb/trunk/source/Core/InputReaderEZ.cpp (original) +++ lldb/trunk/source/Core/InputReaderEZ.cpp Fri Jul 15 18:30:15 2011 @@ -75,6 +75,16 @@ echo); } +Error +InputReaderEZ::Initialize(InitializationParameters& params) +{ + return Initialize(params.m_baton, + params.m_token_size, + params.m_end_token, + params.m_prompt, + params.m_echo); +} + InputReaderEZ::~InputReaderEZ () { } \ No newline at end of file Modified: lldb/trunk/source/Core/ValueObject.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/ValueObject.cpp?rev=135326&r1=135325&r2=135326&view=diff ============================================================================== --- lldb/trunk/source/Core/ValueObject.cpp (original) +++ lldb/trunk/source/Core/ValueObject.cpp Fri Jul 15 18:30:15 2011 @@ -209,8 +209,14 @@ if (m_last_value_format.get()) m_last_value_format.reset((ValueFormat*)NULL); Debugger::ValueFormats::Get(*this, m_last_value_format); + // to find a summary we look for a direct summary, then if there is none + // we look for a regex summary. if there is none we look for a system + // summary (direct), and if also that fails, we look for a system + // regex summary if (!Debugger::SummaryFormats::Get(*this, m_last_summary_format)) - Debugger::RegexSummaryFormats::Get(*this, m_last_summary_format); + if (!Debugger::RegexSummaryFormats::Get(*this, m_last_summary_format)) + if (!Debugger::SystemSummaryFormats::Get(*this, m_last_summary_format)) + Debugger::SystemRegexSummaryFormats::Get(*this, m_last_summary_format); m_last_format_mgr_revision = Debugger::ValueFormats::GetCurrentRevision(); ClearUserVisibleData(); @@ -518,7 +524,7 @@ { clang_type_t clang_type = GetClangType(); - // See if this is a pointer to a C string? + // Do some default printout for function pointers if (clang_type) { StreamString sstr; @@ -530,116 +536,7 @@ ExecutionContextScope *exe_scope = GetExecutionContextScope(); if (exe_scope) { - if (type_flags.AnySet (ClangASTContext::eTypeIsArray | ClangASTContext::eTypeIsPointer) && - ClangASTContext::IsCharType (elem_or_pointee_clang_type)) - { - Target *target = exe_scope->CalculateTarget(); - if (target != NULL) - { - lldb::addr_t cstr_address = LLDB_INVALID_ADDRESS; - AddressType cstr_address_type = eAddressTypeInvalid; - - size_t cstr_len = 0; - bool capped_data = false; - if (type_flags.Test (ClangASTContext::eTypeIsArray)) - { - // We have an array - cstr_len = ClangASTContext::GetArraySize (clang_type); - if (cstr_len > 512) // TODO: make cap a setting - { - cstr_len = ClangASTContext::GetArraySize (clang_type); - if (cstr_len > 512) // TODO: make cap a setting - { - capped_data = true; - cstr_len = 512; - } - } - cstr_address = GetAddressOf (cstr_address_type, true); - } - else - { - // We have a pointer - cstr_address = GetPointerValue (cstr_address_type, true); - } - if (cstr_address != LLDB_INVALID_ADDRESS) - { - Address cstr_so_addr (NULL, cstr_address); - DataExtractor data; - size_t bytes_read = 0; - std::vector data_buffer; - Error error; - bool prefer_file_cache = false; - if (cstr_len > 0) - { - data_buffer.resize(cstr_len); - data.SetData (&data_buffer.front(), data_buffer.size(), lldb::endian::InlHostByteOrder()); - bytes_read = target->ReadMemory (cstr_so_addr, - prefer_file_cache, - &data_buffer.front(), - cstr_len, - error); - if (bytes_read > 0) - { - sstr << '"'; - data.Dump (&sstr, - 0, // Start offset in "data" - eFormatCharArray, // Print as characters - 1, // Size of item (1 byte for a char!) - bytes_read, // How many bytes to print? - UINT32_MAX, // num per line - LLDB_INVALID_ADDRESS,// base address - 0, // bitfield bit size - 0); // bitfield bit offset - if (capped_data) - sstr << "..."; - sstr << '"'; - } - } - else - { - const size_t k_max_buf_size = 256; - data_buffer.resize (k_max_buf_size + 1); - // NULL terminate in case we don't get the entire C string - data_buffer.back() = '\0'; - - sstr << '"'; - - data.SetData (&data_buffer.front(), data_buffer.size(), endian::InlHostByteOrder()); - while ((bytes_read = target->ReadMemory (cstr_so_addr, - prefer_file_cache, - &data_buffer.front(), - k_max_buf_size, - error)) > 0) - { - size_t len = strlen(&data_buffer.front()); - if (len == 0) - break; - if (len > bytes_read) - len = bytes_read; - - data.Dump (&sstr, - 0, // Start offset in "data" - eFormatCharArray, // Print as characters - 1, // Size of item (1 byte for a char!) - len, // How many bytes to print? - UINT32_MAX, // num per line - LLDB_INVALID_ADDRESS,// base address - 0, // bitfield bit size - 0); // bitfield bit offset - - if (len < k_max_buf_size) - break; - cstr_so_addr.Slide (k_max_buf_size); - } - sstr << '"'; - } - } - } - - if (sstr.GetSize() > 0) - m_summary_str.assign (sstr.GetData(), sstr.GetSize()); - } - else if (ClangASTContext::IsFunctionPointerType (clang_type)) + if (ClangASTContext::IsFunctionPointerType (clang_type)) { AddressType func_ptr_address_type = eAddressTypeInvalid; lldb::addr_t func_ptr_address = GetPointerValue (func_ptr_address_type, true); @@ -988,7 +885,7 @@ RefCounter ref(&m_dump_printable_counter); - if(custom_format != lldb::eFormatInvalid) + if (custom_format != lldb::eFormatInvalid) SetFormat(custom_format); const char * return_value; @@ -1146,10 +1043,10 @@ return false; } const char *targetvalue = GetPrintableRepresentation(val_obj_display, custom_format); - if(targetvalue) + if (targetvalue) s.PutCString(targetvalue); bool var_success = (targetvalue != NULL); - if(custom_format != eFormatInvalid) + if (custom_format != eFormatInvalid) SetFormat(eFormatDefault); return var_success; } @@ -1624,7 +1521,7 @@ { const bool is_deref_of_parent = IsDereferenceOfParent (); - if(is_deref_of_parent && epformat == eDereferencePointers) { + if (is_deref_of_parent && epformat == eDereferencePointers) { // this is the original format of GetExpressionPath() producing code like *(a_ptr).memberName, which is entirely // fine, until you put this into StackFrame::GetValueForVariableExpressionPath() which prefers to see a_ptr->memberName. // the eHonorPointers mode is meant to produce strings in this latter format @@ -1639,7 +1536,7 @@ // if we are a deref_of_parent just because we are synthetic array // members made up to allow ptr[%d] syntax to work in variable // printing, then add our name ([%d]) to the expression path - if(m_is_array_item_for_pointer && epformat == eHonorPointers) + if (m_is_array_item_for_pointer && epformat == eHonorPointers) s.PutCString(m_name.AsCString()); if (!IsBaseClass()) @@ -1654,7 +1551,7 @@ { const uint32_t non_base_class_parent_type_info = ClangASTContext::GetTypeInfo (non_base_class_parent_clang_type, NULL, NULL); - if(parent && parent->IsDereferenceOfParent() && epformat == eHonorPointers) + if (parent && parent->IsDereferenceOfParent() && epformat == eHonorPointers) { s.PutCString("->"); } @@ -2584,7 +2481,7 @@ if (val_cstr && (!entry || entry->DoesPrintValue() || !sum_cstr)) s.Printf(" %s", valobj->GetValueAsCString()); - if(sum_cstr) + if (sum_cstr) { // for some reason, using %@ (ObjC description) in a summary string, makes // us believe we need to reset ourselves, thus invalidating the content of Modified: lldb/trunk/source/Symbol/ClangASTContext.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/ClangASTContext.cpp?rev=135326&r1=135325&r2=135326&view=diff ============================================================================== --- lldb/trunk/source/Symbol/ClangASTContext.cpp (original) +++ lldb/trunk/source/Symbol/ClangASTContext.cpp Fri Jul 15 18:30:15 2011 @@ -117,7 +117,7 @@ clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface(); // We currently can't complete objective C types through the newly added ASTContext // because it only supports TagDecl objects right now... - if(class_interface_decl) + if (class_interface_decl) { bool is_forward_decl = class_interface_decl->isForwardDecl(); if (is_forward_decl && class_interface_decl->hasExternalLexicalStorage()) Modified: lldb/trunk/source/Symbol/TypeHierarchyNavigator.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/TypeHierarchyNavigator.cpp?rev=135326&r1=135325&r2=135326&view=diff ============================================================================== --- lldb/trunk/source/Symbol/TypeHierarchyNavigator.cpp (original) +++ lldb/trunk/source/Symbol/TypeHierarchyNavigator.cpp Fri Jul 15 18:30:15 2011 @@ -61,7 +61,7 @@ */ Error error; ValueObject* target = m_value_object.Dereference(error).get(); - if(error.Fail() || !target) + if (error.Fail() || !target) return true; if (LoopThrough(typePtr->getPointeeType(), callback, eStrippedPointer, callback_baton) == false) return false; @@ -73,10 +73,10 @@ if (ClangASTContext::GetCompleteType(ast, m_value_object.GetClangType()) && !objc_class_type->isObjCId()) { clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface(); - if(class_interface_decl) + if (class_interface_decl) { clang::ObjCInterfaceDecl *superclass_interface_decl = class_interface_decl->getSuperClass(); - if(superclass_interface_decl) + if (superclass_interface_decl) { clang::QualType ivar_qual_type(ast->getObjCInterfaceType(superclass_interface_decl)); return LoopThrough(ivar_qual_type, callback, eObjCBaseClass, callback_baton); @@ -95,7 +95,7 @@ if (record->hasDefinition()) { clang::CXXRecordDecl::base_class_iterator pos,end; - if( record->getNumBases() > 0) + if ( record->getNumBases() > 0) { end = record->bases_end(); for (pos = record->bases_begin(); pos != end; pos++) Modified: lldb/trunk/test/functionalities/data-formatter/data-formatter-script/TestDataFormatterScript.py URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/data-formatter/data-formatter-script/TestDataFormatterScript.py?rev=135326&r1=135325&r2=135326&view=diff ============================================================================== --- lldb/trunk/test/functionalities/data-formatter/data-formatter-script/TestDataFormatterScript.py (original) +++ lldb/trunk/test/functionalities/data-formatter/data-formatter-script/TestDataFormatterScript.py Fri Jul 15 18:30:15 2011 @@ -56,7 +56,7 @@ # Set the script here to ease the formatting script = 'a = valobj.GetChildMemberWithName(\'integer\'); a_val = a.GetValue(); str = \'Hello from Python, \' + a_val + \' time\'; return str + (\'!\' if a_val == \'1\' else \'s!\');' - self.runCmd("type summary add add i_am_cool -s \"%s\"" % script) + self.runCmd("type summary add i_am_cool -s \"%s\"" % script) self.expect("frame variable one", substrs = ['Hello from Python', @@ -85,6 +85,9 @@ self.expect("frame variable two", substrs = ['int says 1']) + + self.expect("frame variable twoptr", + substrs = ['int says 1']) # Change the summary self.runCmd("type summary add -f \"int says ${var.integer}, and float says ${var.floating}\" i_am_cool") @@ -103,6 +106,72 @@ self.expect("frame variable twoptr", matching=False, substrs = ['and float says 2.71']) + script = 'return \'Python summary\''; + + self.runCmd("type summary add --name test_summary -s \"%s\"" % script) + + # attach the Python named summary to someone + self.runCmd("frame variable one --summary test_summary") + + self.expect("frame variable one", + substrs = ['Python summary']) + + # should not bind to the type + self.expect("frame variable two", matching=False, + substrs = ['Python summary']) + + self.runCmd("type summary add i_am_cool -f \"Text summary\"") + + self.expect("frame variable one", + substrs = ['Python summary']) + + # use the type summary + self.expect("frame variable two", + substrs = ['Text summary']) + + self.runCmd("n"); # skip ahead to make values change + + # both should use the type summary now + self.expect("frame variable one", + substrs = ['Text summary']) + + self.expect("frame variable two", + substrs = ['Text summary']) + + # disable type summary for pointers, and make a Python regex summary + self.runCmd("type summary add i_am_cool -p -f \"Text summary\"") + self.runCmd("type summary add -x cool -s \"%s\"" % script) + + # variables should stick to the type summary + self.expect("frame variable one", + substrs = ['Text summary']) + + self.expect("frame variable two", + substrs = ['Text summary']) + + # array and pointer should match the Python one + self.expect("frame variable twoptr", + substrs = ['Python summary']) + + self.expect("frame variable array", + substrs = ['Python summary']) + + # return pointers to the type summary + self.runCmd("type summary add i_am_cool -f \"Text summary\"") + + self.expect("frame variable one", + substrs = ['Text summary']) + + self.expect("frame variable two", + substrs = ['Text summary']) + + self.expect("frame variable twoptr", + substrs = ['Text summary']) + + self.expect("frame variable array", + substrs = ['Python summary']) + + if __name__ == '__main__': import atexit lldb.SBDebugger.Initialize() Modified: lldb/trunk/test/functionalities/data-formatter/data-formatter-script/main.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/data-formatter/data-formatter-script/main.cpp?rev=135326&r1=135325&r2=135326&view=diff ============================================================================== --- lldb/trunk/test/functionalities/data-formatter/data-formatter-script/main.cpp (original) +++ lldb/trunk/test/functionalities/data-formatter/data-formatter-script/main.cpp Fri Jul 15 18:30:15 2011 @@ -41,9 +41,13 @@ i_am_cool* twoptr = &two; + i_am_cool array[5]; + i_am_cooler three(10,4,1985,1/1/2011,'B','E'); // Set break point at this line. two.integer = 1; + int dummy = 1; + return 0; } \ No newline at end of file From scallanan at apple.com Fri Jul 15 19:49:19 2011 From: scallanan at apple.com (Sean Callanan) Date: Sat, 16 Jul 2011 00:49:19 -0000 Subject: [Lldb-commits] [lldb] r135331 - in /lldb/trunk: include/lldb/Core/RegisterValue.h tools/debugserver/debugserver.xcodeproj/project.pbxproj tools/debugserver/source/MacOSX/HasAVX.h tools/debugserver/source/MacOSX/HasAVX.s tools/debugserver/source/MacOSX/i386/DNBArchImplI386.cpp tools/debugserver/source/MacOSX/i386/DNBArchImplI386.h tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.cpp tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.h Message-ID: <20110716004919.EC05C312800A@llvm.org> Author: spyffe Date: Fri Jul 15 19:49:19 2011 New Revision: 135331 URL: http://llvm.org/viewvc/llvm-project?rev=135331&view=rev Log: Added support for dynamic detection of AVX, and fixed a few bugs that revealed. Now the "register read" command should show AVX registers (ymm0-ymm15) on Mac OS X platforms that support them. When testing this on Mac OS X, run debugserver manually, like this: debugserver --native-regs localhost:1111 /path/to/executable Then lldb /path/to/executable ... (lldb) process connect connect://localhost:1111 Added: lldb/trunk/tools/debugserver/source/MacOSX/HasAVX.h lldb/trunk/tools/debugserver/source/MacOSX/HasAVX.s Modified: lldb/trunk/include/lldb/Core/RegisterValue.h lldb/trunk/tools/debugserver/debugserver.xcodeproj/project.pbxproj lldb/trunk/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.cpp lldb/trunk/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.h lldb/trunk/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.cpp lldb/trunk/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.h Modified: lldb/trunk/include/lldb/Core/RegisterValue.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/RegisterValue.h?rev=135331&r1=135330&r2=135331&view=diff ============================================================================== --- lldb/trunk/include/lldb/Core/RegisterValue.h (original) +++ lldb/trunk/include/lldb/Core/RegisterValue.h Fri Jul 15 19:49:19 2011 @@ -28,7 +28,7 @@ public: enum { - kMaxRegisterByteSize = 16u + kMaxRegisterByteSize = 32u }; enum Type { Modified: lldb/trunk/tools/debugserver/debugserver.xcodeproj/project.pbxproj URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/debugserver.xcodeproj/project.pbxproj?rev=135331&r1=135330&r2=135331&view=diff ============================================================================== --- lldb/trunk/tools/debugserver/debugserver.xcodeproj/project.pbxproj (original) +++ lldb/trunk/tools/debugserver/debugserver.xcodeproj/project.pbxproj Fri Jul 15 19:49:19 2011 @@ -41,6 +41,7 @@ 26CE05C5115C36590022F371 /* CFBundle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2695DD910D3EBFF6007E4CA2 /* CFBundle.cpp */; }; 26CE05CF115C36F70022F371 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 26ACA3340D3E956300A2120B /* CoreFoundation.framework */; }; 26CE05F1115C387C0022F371 /* PseudoTerminal.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF67ABFF0D34604D0022D128 /* PseudoTerminal.cpp */; }; + 4971AE7213D10F4F00649E37 /* HasAVX.s in Sources */ = {isa = PBXBuildFile; fileRef = 4971AE7113D10F4F00649E37 /* HasAVX.s */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -125,6 +126,8 @@ 26CF99A21142EB7400011AAB /* DNBArchImplX86_64.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DNBArchImplX86_64.cpp; sourceTree = ""; }; 26CF99A31142EB7400011AAB /* DNBArchImplX86_64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DNBArchImplX86_64.h; sourceTree = ""; }; 26E6B9DA0D1329010037ECDD /* RNBDefs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNBDefs.h; sourceTree = ""; }; + 4971AE7013D10F4F00649E37 /* HasAVX.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HasAVX.h; sourceTree = ""; }; + 4971AE7113D10F4F00649E37 /* HasAVX.s */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = HasAVX.s; sourceTree = ""; }; 49F530111331519C008956F6 /* MachRegisterStatesI386.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MachRegisterStatesI386.h; sourceTree = ""; }; 49F5301213316D7F008956F6 /* MachRegisterStatesX86_64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MachRegisterStatesX86_64.h; sourceTree = ""; }; AF67ABFF0D34604D0022D128 /* PseudoTerminal.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PseudoTerminal.cpp; sourceTree = ""; }; @@ -278,6 +281,8 @@ 26C637E90C71334A0024798E /* i386 */, 26C637FA0C71334A0024798E /* ppc */, 26CF99A11142EB7400011AAB /* x86_64 */, + 4971AE7013D10F4F00649E37 /* HasAVX.h */, + 4971AE7113D10F4F00649E37 /* HasAVX.s */, 26C637E80C71334A0024798E /* dbgnub-mig.defs */, 26C637ED0C71334A0024798E /* MachDYLD.h */, 26C637EC0C71334A0024798E /* MachDYLD.cpp */, @@ -452,6 +457,7 @@ 26CE05F1115C387C0022F371 /* PseudoTerminal.cpp in Sources */, 2660D9CE1192280900958FBD /* StringExtractor.cpp in Sources */, 264D5D581293835600ED4C01 /* DNBArch.cpp in Sources */, + 4971AE7213D10F4F00649E37 /* HasAVX.s in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; Added: lldb/trunk/tools/debugserver/source/MacOSX/HasAVX.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/MacOSX/HasAVX.h?rev=135331&view=auto ============================================================================== --- lldb/trunk/tools/debugserver/source/MacOSX/HasAVX.h (added) +++ lldb/trunk/tools/debugserver/source/MacOSX/HasAVX.h Fri Jul 15 19:49:19 2011 @@ -0,0 +1,27 @@ +//===-- HasAVX.h ------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef HasAVX_h +#define HasAVX_h + +#if defined (__i386__) || defined (__x86_64__) + +#ifdef __cplusplus +extern "C" { +#endif + +int HasAVX (); + +#ifdef __cplusplus +} +#endif + +#endif + +#endif Added: lldb/trunk/tools/debugserver/source/MacOSX/HasAVX.s URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/MacOSX/HasAVX.s?rev=135331&view=auto ============================================================================== --- lldb/trunk/tools/debugserver/source/MacOSX/HasAVX.s (added) +++ lldb/trunk/tools/debugserver/source/MacOSX/HasAVX.s Fri Jul 15 19:49:19 2011 @@ -0,0 +1,32 @@ +//===-- HasAVX.s ---------------------------------------*- x86 Assembly -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#if defined (__i386__) || defined (__x86_64__) + +.globl _HasAVX + +_HasAVX: + mov $1, %eax + cpuid + and $0x018000000, %ecx + cmp $0x018000000, %ecx + jne not_supported + mov $0, %ecx +.byte 0x0f, 0x01, 0xd0 // xgetbv, for those assemblers that don't know it + and $0x06, %eax + cmp $0x06, %eax + jne not_supported + mov $1, %eax + jmp done +not_supported: + mov $0, %eax +done: + ret + +#endif \ No newline at end of file Modified: lldb/trunk/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.cpp?rev=135331&r1=135330&r2=135331&view=diff ============================================================================== --- lldb/trunk/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.cpp (original) +++ lldb/trunk/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.cpp Fri Jul 15 19:49:19 2011 @@ -330,7 +330,7 @@ { if (DEBUG_FPU_REGS) { - if (HasAVX() || FORCE_AVX_REGS) + if (CPUHasAVX() || FORCE_AVX_REGS) { m_state.context.fpu.avx.__fpu_reserved[0] = -1; m_state.context.fpu.avx.__fpu_reserved[1] = -1; @@ -460,7 +460,7 @@ } else { - if (HasAVX() || FORCE_AVX_REGS) + if (CPUHasAVX() || FORCE_AVX_REGS) { mach_msg_type_number_t count = e_regSetWordSizeAVX; m_state.SetError(e_regSetFPU, Read, ::thread_get_state(m_thread->ThreadID(), __i386_AVX_STATE, (thread_state_t)&m_state.context.fpu.avx, &count)); @@ -503,7 +503,7 @@ } else { - if (HasAVX() || FORCE_AVX_REGS) + if (CPUHasAVX() || FORCE_AVX_REGS) m_state.SetError(e_regSetFPU, Write, ::thread_set_state(m_thread->ThreadID(), __i386_AVX_STATE, (thread_state_t)&m_state.context.fpu.avx, e_regSetWordSizeAVX)); else m_state.SetError(e_regSetFPU, Write, ::thread_set_state(m_thread->ThreadID(), __i386_FLOAT_STATE, (thread_state_t)&m_state.context.fpu.no_avx, e_regSetWordSizeFPR)); @@ -813,7 +813,7 @@ DNBArchImplI386::GetRegisterSetInfo(nub_size_t *num_reg_sets) { *num_reg_sets = k_num_register_sets; - if (HasAVX() || FORCE_AVX_REGS) + if (CPUHasAVX() || FORCE_AVX_REGS) return g_reg_sets_avx; else return g_reg_sets_no_avx; @@ -886,7 +886,7 @@ break; case e_regSetFPU: - if (HasAVX() || FORCE_AVX_REGS) + if (CPUHasAVX() || FORCE_AVX_REGS) { switch (reg) { @@ -1033,7 +1033,7 @@ break; case e_regSetFPU: - if (HasAVX() || FORCE_AVX_REGS) + if (CPUHasAVX() || FORCE_AVX_REGS) { switch (reg) { Modified: lldb/trunk/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.h?rev=135331&r1=135330&r2=135331&view=diff ============================================================================== --- lldb/trunk/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.h (original) +++ lldb/trunk/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.h Fri Jul 15 19:49:19 2011 @@ -17,6 +17,7 @@ #if defined (__i386__) || defined (__x86_64__) #include "DNBArch.h" +#include "../HasAVX.h" #include "MachRegisterStatesI386.h" class MachThread; @@ -199,10 +200,10 @@ GetRegisterSetInfo(nub_size_t *num_reg_sets); static bool - HasAVX() + CPUHasAVX() { if (s_has_avx == kAVXUnknown) - s_has_avx = kAVXNotPresent; + s_has_avx = (::HasAVX() ? kAVXPresent : kAVXNotPresent); return (s_has_avx == kAVXPresent); } Modified: lldb/trunk/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.cpp?rev=135331&r1=135330&r2=135331&view=diff ============================================================================== --- lldb/trunk/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.cpp (original) +++ lldb/trunk/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.cpp Fri Jul 15 19:49:19 2011 @@ -213,7 +213,7 @@ if (force || m_state.GetError(e_regSetFPU, Read)) { if (DEBUG_FPU_REGS) { - if (HasAVX() || FORCE_AVX_REGS) + if (CPUHasAVX() || FORCE_AVX_REGS) { m_state.context.fpu.avx.__fpu_reserved[0] = -1; m_state.context.fpu.avx.__fpu_reserved[1] = -1; @@ -365,7 +365,7 @@ } else { - if (HasAVX() || FORCE_AVX_REGS) + if (CPUHasAVX() || FORCE_AVX_REGS) { mach_msg_type_number_t count = e_regSetWordSizeAVX; m_state.SetError(e_regSetFPU, Read, ::thread_get_state(m_thread->ThreadID(), __x86_64_AVX_STATE, (thread_state_t)&m_state.context.fpu.avx, &count)); @@ -427,7 +427,7 @@ } else { - if (HasAVX() || FORCE_AVX_REGS) + if (CPUHasAVX() || FORCE_AVX_REGS) { m_state.SetError(e_regSetFPU, Write, ::thread_set_state(m_thread->ThreadID(), __x86_64_AVX_STATE, (thread_state_t)&m_state.context.fpu.avx, e_regSetWordSizeAVX)); return m_state.GetError(e_regSetFPU, Write); @@ -1013,7 +1013,7 @@ { *num_reg_sets = k_num_register_sets; - if (HasAVX() || FORCE_AVX_REGS) + if (CPUHasAVX() || FORCE_AVX_REGS) return g_reg_sets_avx; else return g_reg_sets_no_avx; @@ -1085,7 +1085,7 @@ break; case e_regSetFPU: - if (HasAVX() || FORCE_AVX_REGS) + if (CPUHasAVX() || FORCE_AVX_REGS) { switch (reg) { @@ -1264,7 +1264,7 @@ break; case e_regSetFPU: - if (HasAVX() || FORCE_AVX_REGS) + if (CPUHasAVX() || FORCE_AVX_REGS) { switch (reg) { Modified: lldb/trunk/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.h?rev=135331&r1=135330&r2=135331&view=diff ============================================================================== --- lldb/trunk/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.h (original) +++ lldb/trunk/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.h Fri Jul 15 19:49:19 2011 @@ -16,6 +16,7 @@ #if defined (__i386__) || defined (__x86_64__) #include "DNBArch.h" +#include "../HasAVX.h" #include "MachRegisterStatesX86_64.h" class MachThread; @@ -206,10 +207,10 @@ GetRegisterSetInfo(nub_size_t *num_reg_sets); static bool - HasAVX() + CPUHasAVX() { if (s_has_avx == kAVXUnknown) - s_has_avx = kAVXNotPresent; + s_has_avx = (::HasAVX() ? kAVXPresent : kAVXNotPresent); return (s_has_avx == kAVXPresent); } From granata.enrico at gmail.com Fri Jul 15 20:22:04 2011 From: granata.enrico at gmail.com (Enrico Granata) Date: Sat, 16 Jul 2011 01:22:04 -0000 Subject: [Lldb-commits] [lldb] r135336 - in /lldb/trunk: include/lldb/Core/ include/lldb/Interpreter/ source/API/ source/Commands/ source/Core/ source/Interpreter/ test/functionalities/data-formatter/data-formatter-skip-summary/ Message-ID: <20110716012204.B8CF4312800A@llvm.org> Author: enrico Date: Fri Jul 15 20:22:04 2011 New Revision: 135336 URL: http://llvm.org/viewvc/llvm-project?rev=135336&view=rev Log: Some descriptive text for the Python script feature: - help type summary add now gives some hints on how to use it frame variable and target variable now have a --no-summary-depth (-Y) option: - simply using -Y without an argument will skip one level of summaries, i.e. your aggregate types will expand their children and display no summary, even if they have one. children will behave normally - using -Y, as in -Y4, -Y7, ..., will skip as many levels of summaries as given by the parameter (obviously, -Y and -Y1 are the same thing). children beneath the given depth level will behave normally -Y0 is the same as omitting the --no-summary-depth parameter entirely This option replaces the defined-but-unimplemented --no-summary Added: lldb/trunk/test/functionalities/data-formatter/data-formatter-skip-summary/ lldb/trunk/test/functionalities/data-formatter/data-formatter-skip-summary/Makefile lldb/trunk/test/functionalities/data-formatter/data-formatter-skip-summary/TestDataFormatterSkipSummary.py lldb/trunk/test/functionalities/data-formatter/data-formatter-skip-summary/main.cpp Modified: lldb/trunk/include/lldb/Core/ValueObject.h lldb/trunk/include/lldb/Interpreter/OptionGroupValueObjectDisplay.h lldb/trunk/source/API/SBValue.cpp lldb/trunk/source/Commands/CommandObjectExpression.cpp lldb/trunk/source/Commands/CommandObjectFrame.cpp lldb/trunk/source/Commands/CommandObjectMemory.cpp lldb/trunk/source/Commands/CommandObjectTarget.cpp lldb/trunk/source/Commands/CommandObjectType.cpp lldb/trunk/source/Core/ValueObject.cpp lldb/trunk/source/Interpreter/OptionGroupValueObjectDisplay.cpp Modified: lldb/trunk/include/lldb/Core/ValueObject.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/ValueObject.h?rev=135336&r1=135335&r2=135336&view=diff ============================================================================== --- lldb/trunk/include/lldb/Core/ValueObject.h (original) +++ lldb/trunk/include/lldb/Core/ValueObject.h Fri Jul 15 20:22:04 2011 @@ -593,7 +593,8 @@ bool use_objc, lldb::DynamicValueType use_dynamic, bool scope_already_checked, - bool flat_output); + bool flat_output, + uint32_t omit_summary_depth); // returns true if this is a char* or a char[] // if it is a char* and check_pointer is true, Modified: lldb/trunk/include/lldb/Interpreter/OptionGroupValueObjectDisplay.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Interpreter/OptionGroupValueObjectDisplay.h?rev=135336&r1=135335&r2=135336&view=diff ============================================================================== --- lldb/trunk/include/lldb/Interpreter/OptionGroupValueObjectDisplay.h (original) +++ lldb/trunk/include/lldb/Interpreter/OptionGroupValueObjectDisplay.h Fri Jul 15 20:22:04 2011 @@ -47,7 +47,7 @@ OptionParsingStarting (CommandInterpreter &interpreter); bool show_types; - bool show_summary; + uint32_t no_summary_depth; bool show_location; bool flat_output; bool use_objc; Modified: lldb/trunk/source/API/SBValue.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/API/SBValue.cpp?rev=135336&r1=135335&r2=135336&view=diff ============================================================================== --- lldb/trunk/source/API/SBValue.cpp (original) +++ lldb/trunk/source/API/SBValue.cpp Fri Jul 15 20:22:04 2011 @@ -658,7 +658,8 @@ use_objc, use_dynamic, scope_already_checked, - flat_output); + flat_output, + 0); } else description.Printf ("No value"); Modified: lldb/trunk/source/Commands/CommandObjectExpression.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectExpression.cpp?rev=135336&r1=135335&r2=135336&view=diff ============================================================================== --- lldb/trunk/source/Commands/CommandObjectExpression.cpp (original) +++ lldb/trunk/source/Commands/CommandObjectExpression.cpp Fri Jul 15 20:22:04 2011 @@ -329,7 +329,8 @@ m_options.print_object, // Print the objective C object? use_dynamic, true, // Scope is already checked. Const results are always in scope. - false); // Don't flatten output + false, // Don't flatten output + 0); // Always use summaries (you might want an option --no-summary like there is for frame variable) if (result) result->SetStatus (eReturnStatusSuccessFinishResult); } Modified: lldb/trunk/source/Commands/CommandObjectFrame.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectFrame.cpp?rev=135336&r1=135335&r2=135336&view=diff ============================================================================== --- lldb/trunk/source/Commands/CommandObjectFrame.cpp (original) +++ lldb/trunk/source/Commands/CommandObjectFrame.cpp Fri Jul 15 20:22:04 2011 @@ -501,7 +501,8 @@ m_varobj_options.use_objc, m_varobj_options.use_dynamic, false, - m_varobj_options.flat_output); + m_varobj_options.flat_output, + m_varobj_options.no_summary_depth); } } } @@ -552,7 +553,8 @@ m_varobj_options.use_objc, m_varobj_options.use_dynamic, false, - m_varobj_options.flat_output); + m_varobj_options.flat_output, + m_varobj_options.no_summary_depth); } else { @@ -642,7 +644,8 @@ m_varobj_options.use_objc, m_varobj_options.use_dynamic, false, - m_varobj_options.flat_output); + m_varobj_options.flat_output, + m_varobj_options.no_summary_depth); } } } Modified: lldb/trunk/source/Commands/CommandObjectMemory.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectMemory.cpp?rev=135336&r1=135335&r2=135336&view=diff ============================================================================== --- lldb/trunk/source/Commands/CommandObjectMemory.cpp (original) +++ lldb/trunk/source/Commands/CommandObjectMemory.cpp Fri Jul 15 20:22:04 2011 @@ -658,7 +658,8 @@ m_varobj_options.use_objc, m_varobj_options.use_dynamic, scope_already_checked, - m_varobj_options.flat_output); + m_varobj_options.flat_output, + 0); } else { Modified: lldb/trunk/source/Commands/CommandObjectTarget.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectTarget.cpp?rev=135336&r1=135335&r2=135336&view=diff ============================================================================== --- lldb/trunk/source/Commands/CommandObjectTarget.cpp (original) +++ lldb/trunk/source/Commands/CommandObjectTarget.cpp Fri Jul 15 20:22:04 2011 @@ -489,7 +489,8 @@ m_varobj_options.use_objc, m_varobj_options.use_dynamic, false, - m_varobj_options.flat_output); + m_varobj_options.flat_output, + m_varobj_options.no_summary_depth); } Modified: lldb/trunk/source/Commands/CommandObjectType.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectType.cpp?rev=135336&r1=135335&r2=135336&view=diff ============================================================================== --- lldb/trunk/source/Commands/CommandObjectType.cpp (original) +++ lldb/trunk/source/Commands/CommandObjectType.cpp Fri Jul 15 20:22:04 2011 @@ -1009,6 +1009,18 @@ "\n" "A command you may definitely want to try if you're doing C++ debugging is:\n" "type summary add -f \"${var._M_dataplus._M_p}\" std::string\n" + "\n" + "You can also add Python summaries, in which case you will use lldb public API to gather information from your variables" + "and elaborate them to a meaningful summary inside a script written in Python. The variable object will be passed to your" + "script as an SBValue object. The following example might help you when starting to use the Python summaries feature:\n" + "type summary add JustADemo -s \"value = valobj.GetChildMemberWithName('value'); return 'My value is ' + value.GetValue();\"\n" + "If you prefer to type your scripts on multiple lines, you will use the -P option and then type your script, ending it with " + "the word DONE on a line by itself to mark you're finished editing your code:\n" + "(lldb)type summary add JustADemo -P\n" + " value = valobj.GetChildMemberWithName('value');\n" + " return 'My value is ' + value.GetValue();\n" + "DONE\n" + "(lldb)" ); } Modified: lldb/trunk/source/Core/ValueObject.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/ValueObject.cpp?rev=135336&r1=135335&r2=135336&view=diff ============================================================================== --- lldb/trunk/source/Core/ValueObject.cpp (original) +++ lldb/trunk/source/Core/ValueObject.cpp Fri Jul 15 20:22:04 2011 @@ -2398,7 +2398,8 @@ bool use_objc, lldb::DynamicValueType use_dynamic, bool scope_already_checked, - bool flat_output + bool flat_output, + uint32_t omit_summary_depth ) { if (valobj) @@ -2458,6 +2459,9 @@ const char *sum_cstr = NULL; SummaryFormat* entry = valobj->GetSummaryFormat().get(); + if (omit_summary_depth > 0) + entry = NULL; + if (err_cstr == NULL) { val_cstr = valobj->GetValueAsCString(); @@ -2474,7 +2478,7 @@ if (print_valobj) { - sum_cstr = valobj->GetSummaryAsCString(); + sum_cstr = (omit_summary_depth == 0) ? valobj->GetSummaryAsCString() : NULL; // We must calculate this value in realtime because entry might alter this variable's value // (e.g. by saying ${var%fmt}) and render precached values useless @@ -2571,7 +2575,8 @@ false, use_dynamic, true, - flat_output); + flat_output, + omit_summary_depth > 1 ? omit_summary_depth - 1 : 0); } } Modified: lldb/trunk/source/Interpreter/OptionGroupValueObjectDisplay.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/OptionGroupValueObjectDisplay.cpp?rev=135336&r1=135335&r2=135336&view=diff ============================================================================== --- lldb/trunk/source/Interpreter/OptionGroupValueObjectDisplay.cpp (original) +++ lldb/trunk/source/Interpreter/OptionGroupValueObjectDisplay.cpp Fri Jul 15 20:22:04 2011 @@ -38,7 +38,7 @@ { LLDB_OPT_SET_1, false, "objc", 'O', no_argument, NULL, 0, eArgTypeNone, "Print as an Objective-C object."}, { LLDB_OPT_SET_1, false, "ptr-depth", 'P', required_argument, NULL, 0, eArgTypeCount, "The number of pointers to be traversed when dumping values (default is zero)."}, { LLDB_OPT_SET_1, false, "show-types", 'T', no_argument, NULL, 0, eArgTypeNone, "Show variable types when dumping values."}, - { LLDB_OPT_SET_1, false, "no-summary", 'Y', no_argument, NULL, 0, eArgTypeNone, "Omit summary information."}, + { LLDB_OPT_SET_1, false, "no-summary-depth",'Y', optional_argument, NULL, 0, eArgTypeCount, "Set a depth for omitting summary information (default is 1)."}, { 0, false, NULL, 0, 0, NULL, NULL, eArgTypeNone, NULL } }; @@ -80,7 +80,6 @@ } break; case 'T': show_types = true; break; - case 'Y': show_summary = false; break; case 'L': show_location= true; break; case 'F': flat_output = true; break; case 'O': use_objc = true; break; @@ -96,6 +95,17 @@ error.SetErrorStringWithFormat("Invalid pointer depth '%s'.\n", option_arg); break; + case 'Y': + if (option_arg) + { + no_summary_depth = Args::StringToUInt32 (option_arg, 0, 0, &success); + if (!success) + error.SetErrorStringWithFormat("Invalid pointer depth '%s'.\n", option_arg); + } + else + no_summary_depth = 1; + break; + default: error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option); break; @@ -107,13 +117,13 @@ void OptionGroupValueObjectDisplay::OptionParsingStarting (CommandInterpreter &interpreter) { - show_types = false; - show_summary = true; - show_location = false; - flat_output = false; - use_objc = false; - max_depth = UINT32_MAX; - ptr_depth = 0; + show_types = false; + no_summary_depth = 0; + show_location = false; + flat_output = false; + use_objc = false; + max_depth = UINT32_MAX; + ptr_depth = 0; Target *target = interpreter.GetExecutionContext().target; if (target != NULL) Added: lldb/trunk/test/functionalities/data-formatter/data-formatter-skip-summary/Makefile URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/data-formatter/data-formatter-skip-summary/Makefile?rev=135336&view=auto ============================================================================== --- lldb/trunk/test/functionalities/data-formatter/data-formatter-skip-summary/Makefile (added) +++ lldb/trunk/test/functionalities/data-formatter/data-formatter-skip-summary/Makefile Fri Jul 15 20:22:04 2011 @@ -0,0 +1,5 @@ +LEVEL = ../../../make + +CXX_SOURCES := main.cpp + +include $(LEVEL)/Makefile.rules Added: lldb/trunk/test/functionalities/data-formatter/data-formatter-skip-summary/TestDataFormatterSkipSummary.py URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/data-formatter/data-formatter-skip-summary/TestDataFormatterSkipSummary.py?rev=135336&view=auto ============================================================================== --- lldb/trunk/test/functionalities/data-formatter/data-formatter-skip-summary/TestDataFormatterSkipSummary.py (added) +++ lldb/trunk/test/functionalities/data-formatter/data-formatter-skip-summary/TestDataFormatterSkipSummary.py Fri Jul 15 20:22:04 2011 @@ -0,0 +1,169 @@ +""" +Test lldb data formatter subsystem. +""" + +import os, time +import unittest2 +import lldb +from lldbtest import * + +class DataFormatterTestCase(TestBase): + + mydir = os.path.join("functionalities", "data-formatter", "data-formatter-skip-summary") + + @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin") + def test_with_dsym_and_run_command(self): + """Test data formatter commands.""" + self.buildDsym() + self.data_formatter_commands() + + def test_with_dwarf_and_run_command(self): + """Test data formatter commands.""" + self.buildDwarf() + self.data_formatter_commands() + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break at. + self.line = line_number('main.cpp', '// Set break point at this line.') + + def data_formatter_commands(self): + """Test that that file and class static variables display correctly.""" + self.runCmd("file a.out", CURRENT_EXECUTABLE_SET) + + self.expect("breakpoint set -f main.cpp -l %d" % self.line, + BREAKPOINT_CREATED, + startstr = "Breakpoint created: 1: file ='main.cpp', line = %d, locations = 1" % + self.line) + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs = ['stopped', + 'stop reason = breakpoint']) + + # This is the function to remove the custom formats in order to have a + # clean slate for the next test case. + def cleanup(): + self.runCmd('type format clear', check=False) + self.runCmd('type summary clear', check=False) + + # Execute the cleanup function during test case tear down. + self.addTearDownHook(cleanup) + + # Setup the summaries for this scenario + self.runCmd("type summary add -f \"${var._M_dataplus._M_p}\" std::string") # This works fine on OSX 10.6.8, if it differs on your implementation, submit a patch to adapt it to your C++ stdlib + self.runCmd("type summary add -f \"Level 1\" \"DeepData_1\"") + self.runCmd("type summary add -f \"Level 2\" \"DeepData_2\" -e") + self.runCmd("type summary add -f \"Level 3\" \"DeepData_3\"") + self.runCmd("type summary add -f \"Level 4\" \"DeepData_4\"") + self.runCmd("type summary add -f \"Level 5\" \"DeepData_5\"") + + # Default case, just print out summaries + self.expect('frame variable', + substrs = ['(DeepData_1) data1 = Level 1', + '(DeepData_2) data2 = Level 2 {', + 'm_child1 = Level 3', + 'm_child2 = Level 3', + 'm_child3 = Level 3', + 'm_child4 = Level 3', + '}']) + + # Skip the default (should be 1) levels of summaries + self.expect('frame variable -Y', + substrs = ['(DeepData_1) data1 = {', + 'm_child1 = 0x', + '}', + '(DeepData_2) data2 = {', + 'm_child1 = Level 3', + 'm_child2 = Level 3', + 'm_child3 = Level 3', + 'm_child4 = Level 3', + '}']) + + # Now skip 2 levels of summaries + self.expect('frame variable -Y2', + substrs = ['(DeepData_1) data1 = {', + 'm_child1 = 0x', + '}', + '(DeepData_2) data2 = {', + 'm_child1 = {', + 'm_child1 = 0x', + 'Level 4', + 'm_child2 = {', + 'm_child3 = {', + '}']) + + # Check that no "Level 3" comes out + self.expect('frame variable data1.m_child1 -Y2', matching=False, + substrs = ['Level 3']) + + # Now expand a pointer with 2 level of skipped summaries + self.expect('frame variable data1.m_child1 -Y2', + substrs = ['(DeepData_2 *) data1.m_child1 = 0x']) + + # Deref and expand said pointer + self.expect('frame variable *data1.m_child1 -Y2', + substrs = ['(DeepData_2) *data1.m_child1 = {', + 'm_child2 = {', + 'm_child1 = 0x', + 'Level 4', + '}']) + + # Expand an expression, skipping 2 layers of summaries + self.expect('frame variable data1.m_child1->m_child2 -Y2', + substrs = ['(DeepData_3) data1.m_child1->m_child2 = {', + 'm_child2 = {', + 'm_child1 = Level 5', + 'm_child2 = Level 5', + 'm_child3 = Level 5', + '}']) + + # Expand same expression, skipping only 1 layer of summaries + self.expect('frame variable data1.m_child1->m_child2 -Y1', + substrs = ['(DeepData_3) data1.m_child1->m_child2 = {', + 'm_child1 = 0x', + 'Level 4', + 'm_child2 = Level 4', + '}']) + + # Expand same expression, skipping 3 layers of summaries + self.expect('frame variable data1.m_child1->m_child2 -Y3', + substrs = ['(DeepData_3) data1.m_child1->m_child2 = {', + 'm_some_text = "Just a test"', + 'm_child2 = {', + 'm_some_text = "Just a test"']) + + # Expand within a standard string (might depend on the implementation of the C++ stdlib you use) + self.expect('frame variable data1.m_child1->m_child2.m_child1.m_child2 -Y2', + substrs = ['(DeepData_5) data1.m_child1->m_child2.m_child1.m_child2 = {', + 'm_some_text = {', + '_M_dataplus = {', + '_M_p = 0x', + '"Just a test"']) + + # Repeat the above, but only skip 1 level of summaries + self.expect('frame variable data1.m_child1->m_child2.m_child1.m_child2 -Y1', + substrs = ['(DeepData_5) data1.m_child1->m_child2.m_child1.m_child2 = {', + 'm_some_text = "Just a test"', + '}']) + + # Change summary and expand, first without -Y then with -Y + self.runCmd("type summary add -f \"${var.m_some_text}\" DeepData_5") + + self.expect('fr var data2.m_child4.m_child2.m_child2', + substrs = ['(DeepData_5) data2.m_child4.m_child2.m_child2 = "Just a test"']) + + self.expect('fr var data2.m_child4.m_child2.m_child2 -Y', + substrs = ['(DeepData_5) data2.m_child4.m_child2.m_child2 = {', + 'm_some_text = "Just a test"', + '}']) + + +if __name__ == '__main__': + import atexit + lldb.SBDebugger.Initialize() + atexit.register(lambda: lldb.SBDebugger.Terminate()) + unittest2.main() Added: lldb/trunk/test/functionalities/data-formatter/data-formatter-skip-summary/main.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/data-formatter/data-formatter-skip-summary/main.cpp?rev=135336&view=auto ============================================================================== --- lldb/trunk/test/functionalities/data-formatter/data-formatter-skip-summary/main.cpp (added) +++ lldb/trunk/test/functionalities/data-formatter/data-formatter-skip-summary/main.cpp Fri Jul 15 20:22:04 2011 @@ -0,0 +1,57 @@ +#include + +struct DeepData_5 +{ + std::string m_some_text; + DeepData_5() : + m_some_text("Just a test") {} +}; + +struct DeepData_4 +{ + DeepData_5 m_child1; + DeepData_5 m_child2; + DeepData_5 m_child3; +}; + +struct DeepData_3 +{ + DeepData_4& m_child1; + DeepData_4 m_child2; + + DeepData_3() : m_child1(* (new DeepData_4())), m_child2(DeepData_4()) {} +}; + +struct DeepData_2 +{ + DeepData_3 m_child1; + DeepData_3 m_child2; + DeepData_3 m_child3; + DeepData_3 m_child4; +}; + +struct DeepData_1 +{ + DeepData_2 *m_child1; + + DeepData_1() : + m_child1(new DeepData_2()) + {} +}; + +/* + type summary add -f "${var._M_dataplus._M_p}" std::string + type summary add -f "Level 1" "DeepData_1" + type summary add -f "Level 2" "DeepData_2" -e + type summary add -f "Level 3" "DeepData_3" + type summary add -f "Level 4" "DeepData_4" + type summary add -f "Level 5" "DeepData_5" + */ + +int main() +{ + DeepData_1 data1; + DeepData_2 data2; + + return 0; // Set break point at this line. +} \ No newline at end of file From gclayton at apple.com Fri Jul 15 22:19:08 2011 From: gclayton at apple.com (Greg Clayton) Date: Sat, 16 Jul 2011 03:19:08 -0000 Subject: [Lldb-commits] [lldb] r135338 - in /lldb/trunk: include/lldb/Core/ConnectionFileDescriptor.h include/lldb/Core/DataExtractor.h include/lldb/Core/StreamBuffer.h include/lldb/Core/StreamString.h include/lldb/lldb-forward.h lldb.xcodeproj/project.pbxproj source/Core/ConnectionFileDescriptor.cpp source/Core/DataExtractor.cpp source/Core/StreamString.cpp source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.h source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp Message-ID: <20110716031909.042AA312800A@llvm.org> Author: gclayton Date: Fri Jul 15 22:19:08 2011 New Revision: 135338 URL: http://llvm.org/viewvc/llvm-project?rev=135338&view=rev Log: Completed more work on the KDP darwin kernel debugging Process plug-in. Implemented connect, disconnect, reattach, version, and hostinfo. Modified the ConnectionFileDescriptor class to be able to handle UDP. Added a new Stream subclass called StreamBuffer that is backed by a llvm::SmallVector for better efficiency. Modified the DataExtractor class to have a static function that can dump hex bytes into a stream. This is currently being used to dump incoming binary packet data in the KDP plug-in. Added: lldb/trunk/include/lldb/Core/StreamBuffer.h Modified: lldb/trunk/include/lldb/Core/ConnectionFileDescriptor.h lldb/trunk/include/lldb/Core/DataExtractor.h lldb/trunk/include/lldb/Core/StreamString.h lldb/trunk/include/lldb/lldb-forward.h lldb/trunk/lldb.xcodeproj/project.pbxproj lldb/trunk/source/Core/ConnectionFileDescriptor.cpp lldb/trunk/source/Core/DataExtractor.cpp lldb/trunk/source/Core/StreamString.cpp lldb/trunk/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp lldb/trunk/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.h lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp Modified: lldb/trunk/include/lldb/Core/ConnectionFileDescriptor.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/ConnectionFileDescriptor.h?rev=135338&r1=135337&r2=135338&view=diff ============================================================================== --- lldb/trunk/include/lldb/Core/ConnectionFileDescriptor.h (original) +++ lldb/trunk/include/lldb/Core/ConnectionFileDescriptor.h Fri Jul 15 22:19:08 2011 @@ -11,6 +11,10 @@ #define liblldb_ConnectionFileDescriptor_h_ // C Includes +#include +#include +#include + // C++ Includes // Other libraries and framework includes // Project includes @@ -75,8 +79,16 @@ lldb::ConnectionStatus Close (int& fd, Error *error); + typedef enum + { + eFDTypeFile, // Other FD requireing read/write + eFDTypeSocket, // Socket requiring send/recv + eFDTypeSocketUDP // Unconnected UDP socket requiring sendto/recvfrom + } FDType; int m_fd; // Socket we use to communicate once conn established - bool m_is_socket; + FDType m_fd_type; + struct sockaddr_storage m_udp_sockaddr; + socklen_t m_udp_sockaddr_len; bool m_should_close_fd; // True if this class should close the file descriptor when it goes away. uint32_t m_socket_timeout_usec; Modified: lldb/trunk/include/lldb/Core/DataExtractor.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/DataExtractor.h?rev=135338&r1=135337&r2=135338&view=diff ============================================================================== --- lldb/trunk/include/lldb/Core/DataExtractor.h (original) +++ lldb/trunk/include/lldb/Core/DataExtractor.h Fri Jul 15 22:19:08 2011 @@ -54,6 +54,11 @@ TypeSLEB128 ///< Format output as SLEB128 numbers } Type; + static void + DumpHexBytes (Stream *s, + const void *src, + size_t src_len, + lldb::addr_t base_addr = LLDB_INVALID_ADDRESS); //------------------------------------------------------------------ /// Default constructor. /// Added: lldb/trunk/include/lldb/Core/StreamBuffer.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/StreamBuffer.h?rev=135338&view=auto ============================================================================== --- lldb/trunk/include/lldb/Core/StreamBuffer.h (added) +++ lldb/trunk/include/lldb/Core/StreamBuffer.h Fri Jul 15 22:19:08 2011 @@ -0,0 +1,83 @@ +//===-- StreamBuffer.h ------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_StreamBuffer_h_ +#define liblldb_StreamBuffer_h_ + +#include +#include +#include "llvm/ADT/SmallVector.h" +#include "lldb/Core/Stream.h" + +namespace lldb_private { + +template +class StreamBuffer : public Stream +{ +public: + StreamBuffer () : + Stream (0, 4, lldb::eByteOrderBig), + m_packet () + { + } + + + StreamBuffer (uint32_t flags, + uint32_t addr_size, + lldb::ByteOrder byte_order) : + Stream (flags, addr_size, byte_order), + m_packet () + { + } + + virtual + ~StreamBuffer () + { + } + + virtual void + Flush () + { + // Nothing to do when flushing a buffer based stream... + } + + virtual int + Write (const void *s, size_t length) + { + if (s && length) + m_packet.append ((const char *)s, ((const char *)s) + length); + return length; + } + + void + Clear() + { + m_packet.clear(); + } + + const char * + GetData () const + { + return m_packet.data(); + } + + size_t + GetSize() const + { + return m_packet.size(); + } + +protected: + llvm::SmallVector m_packet; + +}; + +} // namespace lldb_private + +#endif // #ifndef liblldb_StreamBuffer_h_ Modified: lldb/trunk/include/lldb/Core/StreamString.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/StreamString.h?rev=135338&r1=135337&r2=135338&view=diff ============================================================================== --- lldb/trunk/include/lldb/Core/StreamString.h (original) +++ lldb/trunk/include/lldb/Core/StreamString.h Fri Jul 15 22:19:08 2011 @@ -37,9 +37,6 @@ void Clear(); - void - Dump(FILE *f); - const char * GetData () const; Modified: lldb/trunk/include/lldb/lldb-forward.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/lldb-forward.h?rev=135338&r1=135337&r2=135338&view=diff ============================================================================== --- lldb/trunk/include/lldb/lldb-forward.h (original) +++ lldb/trunk/include/lldb/lldb-forward.h Fri Jul 15 22:19:08 2011 @@ -129,6 +129,7 @@ class StoppointCallbackContext; class StoppointLocation; class Stream; +template class StreamBuffer; class StreamFile; class StreamString; class StringList; Modified: lldb/trunk/lldb.xcodeproj/project.pbxproj URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lldb.xcodeproj/project.pbxproj?rev=135338&r1=135337&r2=135338&view=diff ============================================================================== --- lldb/trunk/lldb.xcodeproj/project.pbxproj (original) +++ lldb/trunk/lldb.xcodeproj/project.pbxproj Fri Jul 15 22:19:08 2011 @@ -638,6 +638,7 @@ 261B5A5311C3F2AD00AABD0A /* SharingPtr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SharingPtr.h; path = include/lldb/Utility/SharingPtr.h; sourceTree = ""; }; 26217930133BC8640083B112 /* lldb-private-types.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "lldb-private-types.h"; path = "include/lldb/lldb-private-types.h"; sourceTree = ""; }; 26217932133BCB850083B112 /* lldb-private-enumerations.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "lldb-private-enumerations.h"; path = "include/lldb/lldb-private-enumerations.h"; sourceTree = ""; }; + 2623096E13D0EFFB006381D9 /* StreamBuffer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = StreamBuffer.h; path = include/lldb/Core/StreamBuffer.h; sourceTree = ""; }; 263664921140A4930075843B /* Debugger.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; name = Debugger.cpp; path = source/Core/Debugger.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; 263664941140A4C10075843B /* Debugger.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = Debugger.h; path = include/lldb/Core/Debugger.h; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; 26368A3B126B697600E8659F /* darwin-debug.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "darwin-debug.cpp"; path = "tools/darwin-debug/darwin-debug.cpp"; sourceTree = ""; }; @@ -2003,6 +2004,7 @@ 26BC7E9110F1B85900F91463 /* Stream.cpp */, 9A4F35111368A54100823F52 /* StreamAsynchronousIO.h */, 9A4F350F1368A51A00823F52 /* StreamAsynchronousIO.cpp */, + 2623096E13D0EFFB006381D9 /* StreamBuffer.h */, 26BC7D7A10F1B77400F91463 /* StreamFile.h */, 26BC7E9210F1B85900F91463 /* StreamFile.cpp */, 26BC7D7B10F1B77400F91463 /* StreamString.h */, Modified: lldb/trunk/source/Core/ConnectionFileDescriptor.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/ConnectionFileDescriptor.cpp?rev=135338&r1=135337&r2=135338&view=diff ============================================================================== --- lldb/trunk/source/Core/ConnectionFileDescriptor.cpp (original) +++ lldb/trunk/source/Core/ConnectionFileDescriptor.cpp Fri Jul 15 22:19:08 2011 @@ -38,33 +38,42 @@ ConnectionFileDescriptor::ConnectionFileDescriptor () : Connection(), m_fd (-1), - m_is_socket (false), + m_fd_type (eFDTypeFile), + m_udp_sockaddr (), + m_udp_sockaddr_len (0), m_should_close_fd (false), m_socket_timeout_usec(0) { + memset (&m_udp_sockaddr, 0, sizeof(m_udp_sockaddr)); + lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION | LIBLLDB_LOG_OBJECT, - "%p ConnectionFileDescriptor::ConnectionFileDescriptor ()", - this); + "%p ConnectionFileDescriptor::ConnectionFileDescriptor ()", + this); } ConnectionFileDescriptor::ConnectionFileDescriptor (int fd, bool owns_fd) : Connection(), m_fd (fd), - m_is_socket (false), + m_fd_type (eFDTypeFile), + m_udp_sockaddr (), + m_udp_sockaddr_len (0), m_should_close_fd (owns_fd), m_socket_timeout_usec(0) { + memset (&m_udp_sockaddr, 0, sizeof(m_udp_sockaddr)); lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION | LIBLLDB_LOG_OBJECT, - "%p ConnectionFileDescriptor::ConnectionFileDescriptor (fd = %i, owns_fd = %i)", - this, fd, owns_fd); + "%p ConnectionFileDescriptor::ConnectionFileDescriptor (fd = %i, owns_fd = %i)", + this, + fd, + owns_fd); } ConnectionFileDescriptor::~ConnectionFileDescriptor () { lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION | LIBLLDB_LOG_OBJECT, - "%p ConnectionFileDescriptor::~ConnectionFileDescriptor ()", - this); + "%p ConnectionFileDescriptor::~ConnectionFileDescriptor ()", + this); Disconnect (NULL); } @@ -78,8 +87,9 @@ ConnectionFileDescriptor::Connect (const char *s, Error *error_ptr) { lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION, - "%p ConnectionFileDescriptor::Connect (url = '%s')", - this, s); + "%p ConnectionFileDescriptor::Connect (url = '%s')", + this, + s); if (s && s[0]) { @@ -134,7 +144,9 @@ // Try and get a socket option from this file descriptor to // see if this is a socket and set m_is_socket accordingly. int resuse; - m_is_socket = GetSocketOption (m_fd, SOL_SOCKET, SO_REUSEADDR, resuse) == 0; + bool is_socket = GetSocketOption (m_fd, SOL_SOCKET, SO_REUSEADDR, resuse) == 0; + if (is_socket) + m_fd_type = eFDTypeSocket; m_should_close_fd = true; return eConnectionStatusSuccess; } @@ -204,28 +216,40 @@ log->Printf ("%p ConnectionFileDescriptor::Read () ::read (fd = %i, dst = %p, dst_len = %zu)...", this, m_fd, dst, dst_len); - if (timeout_usec == UINT32_MAX) - { - if (m_is_socket && SetSocketReceiveTimeout (timeout_usec)) + ssize_t bytes_read = 0; + struct sockaddr_storage from; + socklen_t from_len = sizeof(from); + + switch (m_fd_type) + { + case eFDTypeFile: // Other FD requireing read/write + status = BytesAvailable (timeout_usec, error_ptr); + if (status == eConnectionStatusSuccess) + bytes_read = ::read (m_fd, dst, dst_len); + break; + + case eFDTypeSocket: // Socket requiring send/recv + if (SetSocketReceiveTimeout (timeout_usec)) + { status = eConnectionStatusSuccess; - } - else - { - if (m_is_socket && SetSocketReceiveTimeout (timeout_usec)) + bytes_read = ::recv (m_fd, dst, dst_len, 0); + } + break; + + case eFDTypeSocketUDP: // Unconnected UDP socket requiring sendto/recvfrom + if (SetSocketReceiveTimeout (timeout_usec)) + { status = eConnectionStatusSuccess; - else - status = BytesAvailable (timeout_usec, error_ptr); + ::memset (&from, 0, sizeof(from)); + bytes_read = ::recvfrom (m_fd, dst, dst_len, 0, (struct sockaddr *)&from, &from_len); + } + break; } + if (status != eConnectionStatusSuccess) return 0; Error error; - ssize_t bytes_read; - if (m_is_socket) - bytes_read = ::recv (m_fd, dst, dst_len, 0); - else - bytes_read = ::read (m_fd, dst, dst_len); - if (bytes_read == 0) { error.Clear(); // End-of-file. Do not automatically close; pass along for the end-of-file handlers. @@ -319,10 +343,26 @@ ssize_t bytes_sent = 0; - if (m_is_socket) - bytes_sent = ::send (m_fd, src, src_len, 0); - else - bytes_sent = ::write (m_fd, src, src_len); + switch (m_fd_type) + { + case eFDTypeFile: // Other FD requireing read/write + bytes_sent = ::write (m_fd, src, src_len); + break; + + case eFDTypeSocket: // Socket requiring send/recv + bytes_sent = ::send (m_fd, src, src_len, 0); + break; + + case eFDTypeSocketUDP: // Unconnected UDP socket requiring sendto/recvfrom + assert (m_udp_sockaddr_len != 0); + bytes_sent = ::sendto (m_fd, + src, + src_len, + 0, + (struct sockaddr *)&m_udp_sockaddr, + m_udp_sockaddr_len); + break; + } if (bytes_sent < 0) error.SetErrorToErrno (); @@ -331,12 +371,38 @@ if (log) { - if (m_is_socket) - log->Printf ("%p ConnectionFileDescriptor::Write() ::send (socket = %i, src = %p, src_len = %zu, flags = 0) => %zi (error = %s)", - this, m_fd, src, src_len, bytes_sent, error.AsCString()); - else - log->Printf ("%p ConnectionFileDescriptor::Write() ::write (fd = %i, src = %p, src_len = %zu) => %zi (error = %s)", - this, m_fd, src, src_len, bytes_sent, error.AsCString()); + switch (m_fd_type) + { + case eFDTypeFile: // Other FD requireing read/write + log->Printf ("%p ConnectionFileDescriptor::Write() ::write (fd = %i, src = %p, src_len = %zu) => %zi (error = %s)", + this, + m_fd, + src, + src_len, + bytes_sent, + error.AsCString()); + break; + + case eFDTypeSocket: // Socket requiring send/recv + log->Printf ("%p ConnectionFileDescriptor::Write() ::send (socket = %i, src = %p, src_len = %zu, flags = 0) => %zi (error = %s)", + this, + m_fd, + src, + src_len, + bytes_sent, + error.AsCString()); + break; + + case eFDTypeSocketUDP: // Unconnected UDP socket requiring sendto/recvfrom + log->Printf ("%p ConnectionFileDescriptor::Write() ::sendto (socket = %i, src = %p, src_len = %zu, flags = 0) => %zi (error = %s)", + this, + m_fd, + src, + src_len, + bytes_sent, + error.AsCString()); + break; + } } if (error_ptr) @@ -477,7 +543,7 @@ } fd = -1; } - m_is_socket = false; + m_fd_type = eFDTypeFile; if (success) return eConnectionStatusSuccess; else @@ -490,7 +556,7 @@ ConnectionStatus result = eConnectionStatusError; struct sockaddr_un saddr_un; - m_is_socket = true; + m_fd_type = eFDTypeSocket; int listen_socket = ::socket (AF_UNIX, SOCK_STREAM, 0); if (listen_socket == -1) @@ -537,7 +603,7 @@ ConnectionFileDescriptor::NamedSocketConnect (const char *socket_name, Error *error_ptr) { Close (m_fd, NULL); - m_is_socket = true; + m_fd_type = eFDTypeSocket; // Open the socket that was passed in as an option struct sockaddr_un saddr_un; @@ -576,7 +642,7 @@ this, listen_port_num); Close (m_fd, NULL); - m_is_socket = true; + m_fd_type = eFDTypeSocket; int listen_port = ::socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); if (listen_port == -1) { @@ -640,7 +706,7 @@ "%p ConnectionFileDescriptor::ConnectTCP (host/port = %s)", this, host_and_port); Close (m_fd, NULL); - m_is_socket = true; + m_fd_type = eFDTypeSocket; RegularExpression regex ("([^:]+):([0-9]+)"); if (regex.Execute (host_and_port, 2) == false) @@ -730,7 +796,7 @@ "%p ConnectionFileDescriptor::ConnectUDP (host/port = %s)", this, host_and_port); Close (m_fd, NULL); - m_is_socket = true; + m_fd_type = eFDTypeSocketUDP; RegularExpression regex ("([^:]+):([0-9]+)"); if (regex.Execute (host_and_port, 2) == false) @@ -839,20 +905,27 @@ bool ConnectionFileDescriptor::SetSocketReceiveTimeout (uint32_t timeout_usec) { - if (m_is_socket) + switch (m_fd_type) { - // Check in case timeout for m_fd has already been set to this value - if (timeout_usec == m_socket_timeout_usec) - return true; - //printf ("ConnectionFileDescriptor::SetSocketReceiveTimeout (timeout_usec = %u)\n", timeout_usec); - - struct timeval timeout; - timeout.tv_sec = timeout_usec / TimeValue::MicroSecPerSec; - timeout.tv_usec = timeout_usec % TimeValue::MicroSecPerSec; - if (::setsockopt (m_fd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)) == 0) + case eFDTypeFile: // Other FD requireing read/write + break; + + case eFDTypeSocket: // Socket requiring send/recv + case eFDTypeSocketUDP: // Unconnected UDP socket requiring sendto/recvfrom { - m_socket_timeout_usec = timeout_usec; - return true; + // Check in case timeout for m_fd has already been set to this value + if (timeout_usec == m_socket_timeout_usec) + return true; + //printf ("ConnectionFileDescriptor::SetSocketReceiveTimeout (timeout_usec = %u)\n", timeout_usec); + + struct timeval timeout; + timeout.tv_sec = timeout_usec / TimeValue::MicroSecPerSec; + timeout.tv_usec = timeout_usec % TimeValue::MicroSecPerSec; + if (::setsockopt (m_fd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)) == 0) + { + m_socket_timeout_usec = timeout_usec; + return true; + } } } return false; Modified: lldb/trunk/source/Core/DataExtractor.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/DataExtractor.cpp?rev=135338&r1=135337&r2=135338&view=diff ============================================================================== --- lldb/trunk/source/Core/DataExtractor.cpp (original) +++ lldb/trunk/source/Core/DataExtractor.cpp Fri Jul 15 22:19:08 2011 @@ -1789,4 +1789,19 @@ } } - +void +DataExtractor::DumpHexBytes (Stream *s, + const void *src, + size_t src_len, + addr_t base_addr) +{ + DataExtractor data (src, src_len, eByteOrderLittle, 4); + data.Dump (s, + 0, // Offset into "src" + eFormatBytes, // Dump as hex bytes + 1, // Size of each item is 1 for single bytes + src_len, // Number of bytes + 32, // Num bytes per line + base_addr, // Base address + 0, 0); // Bitfield info +} Modified: lldb/trunk/source/Core/StreamString.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/StreamString.cpp?rev=135338&r1=135337&r2=135338&view=diff ============================================================================== --- lldb/trunk/source/Core/StreamString.cpp (original) +++ lldb/trunk/source/Core/StreamString.cpp Fri Jul 15 22:19:08 2011 @@ -47,14 +47,6 @@ m_packet.clear(); } -void -StreamString::Dump(FILE *f) -{ - int size = GetSize(); - if (size > 0) - fprintf(f, "%*.*s", size, size, m_packet.c_str()); -} - const char * StreamString::GetData () const { Modified: lldb/trunk/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp?rev=135338&r1=135337&r2=135338&view=diff ============================================================================== --- lldb/trunk/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp (original) +++ lldb/trunk/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp Fri Jul 15 22:19:08 2011 @@ -16,14 +16,13 @@ // C++ Includes // Other libraries and framework includes +#include "lldb/Core/DataBufferHeap.h" #include "lldb/Core/DataExtractor.h" #include "lldb/Core/Log.h" -#include "lldb/Core/StreamString.h" #include "lldb/Host/FileSpec.h" #include "lldb/Host/Host.h" #include "lldb/Host/TimeValue.h" #include "lldb/Target/Process.h" -#include "Utility/StringExtractor.h" // Project includes #include "ProcessKDPLog.h" @@ -38,13 +37,19 @@ //---------------------------------------------------------------------- CommunicationKDP::CommunicationKDP (const char *comm_name) : Communication(comm_name), + m_byte_order (eByteOrderLittle), m_packet_timeout (1), m_sequence_mutex (Mutex::eMutexTypeRecursive), m_public_is_running (false), m_private_is_running (false), - m_session_key (0), - m_request_sequence_id (0), - m_exception_sequence_id (0) + m_session_key (0u), + m_request_sequence_id (0u), + m_exception_sequence_id (0u), + m_kdp_version_version (0u), + m_kdp_version_feature (0u), + m_kdp_hostinfo_cpu_mask (0u), + m_kdp_hostinfo_cpu_type (0u), + m_kdp_hostinfo_cpu_subtype (0u) { } @@ -60,27 +65,61 @@ } bool -CommunicationKDP::SendRequestPacket (const StreamString &request_packet) +CommunicationKDP::SendRequestPacket (const PacketStreamType &request_packet) { Mutex::Locker locker(m_sequence_mutex); return SendRequestPacketNoLock (request_packet); } +#if 0 +typedef struct { + uint8_t request; // Either: CommandType | ePacketTypeRequest, or CommandType | ePacketTypeReply + uint8_t sequence; + uint16_t length; // Length of entire packet including this header + uint32_t key; // Session key +} kdp_hdr_t; +#endif + void -CommunicationKDP::MakeRequestPacketHeader (RequestType request_type, - StreamString &request_packet) +CommunicationKDP::MakeRequestPacketHeader (CommandType request_type, + PacketStreamType &request_packet, + uint16_t request_length) { request_packet.Clear(); - request_packet.PutHex32 (request_type); // Set the request type - request_packet.PutHex8 (ePacketTypeRequest); // Set the packet type - request_packet.PutHex8 (++m_request_sequence_id); // Sequence number - request_packet.PutHex16 (0); // Pad1 and Pad2 bytes - request_packet.PutHex32 (m_session_key); // Session key + request_packet.PutHex8 (request_type | ePacketTypeRequest); // Set the request type + request_packet.PutHex8 (m_request_sequence_id++); // Sequence number + request_packet.PutHex16 (request_length); // Length of the packet including this header + request_packet.PutHex32 (m_session_key); // Session key } +bool +CommunicationKDP::SendRequestAndGetReply (const CommandType command, + const uint8_t request_sequence_id, + const PacketStreamType &request_packet, + DataExtractor &reply_packet) +{ + + Mutex::Locker locker(m_sequence_mutex); + if (SendRequestPacketNoLock(request_packet)) + { + if (WaitForPacketWithTimeoutMicroSecondsNoLock (reply_packet, m_packet_timeout)) + { + uint32_t offset = 0; + const uint8_t reply_command = reply_packet.GetU8 (&offset); + const uint8_t reply_sequence_id = reply_packet.GetU8 (&offset); + if ((reply_command & eCommandTypeMask) == command) + { + if (request_sequence_id == reply_sequence_id) + return true; + } + } + } + reply_packet.Clear(); + return false; +} bool -CommunicationKDP::SendRequestPacketNoLock (const StreamString &request_packet) +CommunicationKDP::SendRequestPacketNoLock (const PacketStreamType &request_packet) { if (IsConnected()) { @@ -90,22 +129,11 @@ LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PACKETS)); if (log) { - StreamString log_strm; - DataExtractor data (packet_data, - packet_size, - request_packet.GetByteOrder(), - request_packet.GetAddressByteSize()); - data.Dump (&log_strm, - 0, - eFormatBytes, - 1, - packet_size, - 32, // Num bytes per line - 0, // Base address - 0, - 0); + PacketStreamType log_strm; + + DataExtractor::DumpHexBytes (&log_strm, packet_data, packet_size, 0); - log->Printf("request packet: <%u>\n%s", packet_size, log_strm.GetString().c_str()); + log->Printf("request packet: <%u>\n%s", packet_size, log_strm.GetData()); } ConnectionStatus status = eConnectionStatusSuccess; @@ -137,14 +165,14 @@ } size_t -CommunicationKDP::WaitForPacketWithTimeoutMicroSeconds (StringExtractor &packet, uint32_t timeout_usec) +CommunicationKDP::WaitForPacketWithTimeoutMicroSeconds (DataExtractor &packet, uint32_t timeout_usec) { Mutex::Locker locker(m_sequence_mutex); return WaitForPacketWithTimeoutMicroSecondsNoLock (packet, timeout_usec); } size_t -CommunicationKDP::WaitForPacketWithTimeoutMicroSecondsNoLock (StringExtractor &packet, uint32_t timeout_usec) +CommunicationKDP::WaitForPacketWithTimeoutMicroSecondsNoLock (DataExtractor &packet, uint32_t timeout_usec) { uint8_t buffer[8192]; Error error; @@ -153,7 +181,7 @@ // Check for a packet from our cache first without trying any reading... if (CheckForPacket (NULL, 0, packet)) - return packet.GetStringRef().size(); + return packet.GetByteSize(); bool timed_out = false; while (IsConnected() && !timed_out) @@ -172,7 +200,7 @@ if (bytes_read > 0) { if (CheckForPacket (buffer, bytes_read, packet)) - return packet.GetStringRef().size(); + return packet.GetByteSize(); } else { @@ -199,7 +227,7 @@ } bool -CommunicationKDP::CheckForPacket (const uint8_t *src, size_t src_len, StringExtractor &packet) +CommunicationKDP::CheckForPacket (const uint8_t *src, size_t src_len, DataExtractor &packet) { // Put the packet data into the buffer in a thread safe fashion Mutex::Locker locker(m_bytes_mutex); @@ -210,43 +238,229 @@ { if (log && log->GetVerbose()) { - StreamString s; - log->Printf ("CommunicationKDP::%s adding %u bytes: %.*s", + PacketStreamType log_strm; + DataExtractor::DumpHexBytes (&log_strm, src, src_len, 0); + log->Printf ("CommunicationKDP::%s adding %u bytes: %s", __FUNCTION__, (uint32_t)src_len, - (uint32_t)src_len, - src); + log_strm.GetData()); } m_bytes.append ((const char *)src, src_len); } - // Parse up the packets into gdb remote packets - if (!m_bytes.empty()) + // Make sure we at least have enough bytes for a packet header + const size_t bytes_available = m_bytes.size(); + if (bytes_available >= 8) { - // TODO: Figure out if we have a full packet reply + packet.SetData (&m_bytes[0], bytes_available, m_byte_order); + uint32_t offset = 0; + uint8_t reply_command = packet.GetU8(&offset); + switch (reply_command) + { + case ePacketTypeReply | eCommandTypeConnect: + case ePacketTypeReply | eCommandTypeDisconnect: + case ePacketTypeReply | eCommandTypeHostInfo: + case ePacketTypeReply | eCommandTypeVersion: + case ePacketTypeReply | eCommandTypeMaxBytes: + case ePacketTypeReply | eCommandTypeReadMemory: + case ePacketTypeReply | eCommandTypeWriteMemory: + case ePacketTypeReply | eCommandTypeReadRegisters: + case ePacketTypeReply | eCommandTypeWriteRegisters: + case ePacketTypeReply | eCommandTypeLoad: + case ePacketTypeReply | eCommandTypeImagePath: + case ePacketTypeReply | eCommandTypeSuspend: + case ePacketTypeReply | eCommandTypeResume: + case ePacketTypeReply | eCommandTypeException: + case ePacketTypeReply | eCommandTypeTermination: + case ePacketTypeReply | eCommandTypeBreakpointSet: + case ePacketTypeReply | eCommandTypeBreakpointRemove: + case ePacketTypeReply | eCommandTypeRegions: + case ePacketTypeReply | eCommandTypeReattach: + case ePacketTypeReply | eCommandTypeHostReboot: + case ePacketTypeReply | eCommandTypeReadMemory64: + case ePacketTypeReply | eCommandTypeWriteMemory64: + case ePacketTypeReply | eCommandTypeBreakpointSet64: + case ePacketTypeReply | eCommandTypeBreakpointRemove64: + case ePacketTypeReply | eCommandTypeKernelVersion: + { + offset = 2; + const uint16_t length = packet.GetU16 (&offset); + if (length <= bytes_available) + { + // We have an entire packet ready, we need to copy the data + // bytes into a buffer that will be owned by the packet and + // erase the bytes from our communcation buffer "m_bytes" + packet.SetData (DataBufferSP (new DataBufferHeap (&m_bytes[0], length))); + m_bytes.erase (0, length); + return true; + } + } + break; + + default: + // Unrecognized reply command byte, erase this byte and try to get back on track + if (log) + log->Printf ("CommunicationKDP::%s: tossing junk byte: 0x%2.2x", + __FUNCTION__, + (uint8_t)m_bytes[0]); + m_bytes.erase(0, 1); + break; + } } packet.Clear(); return false; } -CommunicationKDP::ErrorType +bool CommunicationKDP::Connect (uint16_t reply_port, uint16_t exc_port, const char *greeting) { - StreamString request_packet (Stream::eBinary, 4, eByteOrderLittle); - MakeRequestPacketHeader (eRequestTypeConnect, request_packet); + PacketStreamType request_packet (Stream::eBinary, 4, m_byte_order); + if (greeting == NULL) + greeting = ""; + + const CommandType command = eCommandTypeConnect; + // Length is 82 uint16_t and the length of the greeting C string + const uint32_t command_length = 8 + 2 + 2 + ::strlen(greeting); + const uint32_t request_sequence_id = m_request_sequence_id; + MakeRequestPacketHeader (command, request_packet, command_length); request_packet.PutHex16(reply_port); request_packet.PutHex16(exc_port); request_packet.PutCString(greeting); - - return eErrorUnimplemented; + DataExtractor reply_packet; + return SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet); +} + +void +CommunicationKDP::ClearKDPSettings () +{ + m_request_sequence_id = 0; + m_kdp_version_version = 0; + m_kdp_version_feature = 0; + m_kdp_hostinfo_cpu_mask = 0; + m_kdp_hostinfo_cpu_type = 0; + m_kdp_hostinfo_cpu_subtype = 0; +} + +bool +CommunicationKDP::Reattach (uint16_t reply_port) +{ + PacketStreamType request_packet (Stream::eBinary, 4, m_byte_order); + const CommandType command = eCommandTypeReattach; + // Length is 8 bytes for the header plus 2 bytes for the reply UDP port + const uint32_t command_length = 8 + 2; + const uint32_t request_sequence_id = m_request_sequence_id; + MakeRequestPacketHeader (command, request_packet, command_length); + request_packet.PutHex16(reply_port); + DataExtractor reply_packet; + if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet)) + { + // Reset the sequence ID to zero for reattach + ClearKDPSettings (); + uint32_t offset = 4; + m_session_key = reply_packet.GetU32 (&offset); + return true; + } + return false; } -CommunicationKDP::ErrorType +uint32_t +CommunicationKDP::GetVersion () +{ + if (!VersionIsValid()) + SendRequestVersion(); + return m_kdp_version_version; +} + +uint32_t +CommunicationKDP::GetFeatureFlags () +{ + if (!VersionIsValid()) + SendRequestVersion(); + return m_kdp_version_feature; +} + +bool +CommunicationKDP::SendRequestVersion () +{ + PacketStreamType request_packet (Stream::eBinary, 4, m_byte_order); + const CommandType command = eCommandTypeVersion; + const uint32_t command_length = 8; + const uint32_t request_sequence_id = m_request_sequence_id; + MakeRequestPacketHeader (command, request_packet, command_length); + DataExtractor reply_packet; + if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet)) + { + // Reset the sequence ID to zero for reattach + uint32_t offset = 8; + m_kdp_version_version = reply_packet.GetU32 (&offset); + m_kdp_version_feature = reply_packet.GetU32 (&offset); + return true; + } + return false; +} + +uint32_t +CommunicationKDP::GetCPUMask () +{ + if (!HostInfoIsValid()) + SendRequestHostInfo(); + return m_kdp_hostinfo_cpu_mask; +} + +uint32_t +CommunicationKDP::GetCPUType () +{ + if (!HostInfoIsValid()) + SendRequestHostInfo(); + return m_kdp_hostinfo_cpu_type; +} + +uint32_t +CommunicationKDP::GetCPUSubtype () +{ + if (!HostInfoIsValid()) + SendRequestHostInfo(); + return m_kdp_hostinfo_cpu_subtype; +} + +bool +CommunicationKDP::SendRequestHostInfo () +{ + PacketStreamType request_packet (Stream::eBinary, 4, m_byte_order); + const CommandType command = eCommandTypeHostInfo; + const uint32_t command_length = 8; + const uint32_t request_sequence_id = m_request_sequence_id; + MakeRequestPacketHeader (command, request_packet, command_length); + DataExtractor reply_packet; + if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet)) + { + // Reset the sequence ID to zero for reattach + uint32_t offset = 8; + m_kdp_hostinfo_cpu_mask = reply_packet.GetU32 (&offset); + m_kdp_hostinfo_cpu_type = reply_packet.GetU32 (&offset); + m_kdp_hostinfo_cpu_subtype = reply_packet.GetU32 (&offset); + return true; + } + return false; +} + +bool CommunicationKDP::Disconnect () { - return eErrorUnimplemented; + PacketStreamType request_packet (Stream::eBinary, 4, m_byte_order); + const CommandType command = eCommandTypeDisconnect; + const uint32_t command_length = 8; + const uint32_t request_sequence_id = m_request_sequence_id; + MakeRequestPacketHeader (command, request_packet, command_length); + DataExtractor reply_packet; + if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet)) + { + // Are we supposed to get a reply for disconnect? + } + ClearKDPSettings (); + return true; } Modified: lldb/trunk/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.h?rev=135338&r1=135337&r2=135338&view=diff ============================================================================== --- lldb/trunk/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.h (original) +++ lldb/trunk/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.h Fri Jul 15 22:19:08 2011 @@ -20,12 +20,11 @@ #include "lldb/lldb-private.h" #include "lldb/Core/Communication.h" #include "lldb/Core/Listener.h" +#include "lldb/Core/StreamBuffer.h" #include "lldb/Host/Mutex.h" #include "lldb/Host/Predicate.h" #include "lldb/Host/TimeValue.h" -class StringExtractor; - class CommunicationKDP : public lldb_private::Communication { public: @@ -36,49 +35,50 @@ const static uint32_t kMaxPacketSize = 1200; const static uint32_t kMaxDataSize = 1024; - + typedef lldb_private::StreamBuffer<1024> PacketStreamType; typedef enum { - eRequestTypeConnect = 0u, - eRequestTypeDisconnect, - eRequestTypeHostInfo, - eRequestTypeVersion, - eRequestTypeMaxBytes, - eRequestTypeReadMemory, - eRequestTypeWriteMemory, - eRequestTypeReadRegisters, - eRequestTypeWriteRegisters, - eRequestTypeLoad, - eRequestTypeImagePath, - eRequestTypeSuspend, - eRequestTypeResume, - eRequestTypeException, - eRequestTypeTermination, - eRequestTypeBreakpointSet, - eRequestTypeBreakpointRemove, - eRequestTypeRegions, - eRequestTypeReattach, - eRequestTypeHostReboot, - eRequestTypeReadMemory64, - eRequestTypeWriteMemory64, - eRequestTypeBreakpointSet64, - eRequestTypeBreakpointRemove64, - eRequestTypeKernelVersion - } RequestType; + eCommandTypeConnect = 0u, + eCommandTypeDisconnect, + eCommandTypeHostInfo, + eCommandTypeVersion, + eCommandTypeMaxBytes, + eCommandTypeReadMemory, + eCommandTypeWriteMemory, + eCommandTypeReadRegisters, + eCommandTypeWriteRegisters, + eCommandTypeLoad, + eCommandTypeImagePath, + eCommandTypeSuspend, + eCommandTypeResume, + eCommandTypeException, + eCommandTypeTermination, + eCommandTypeBreakpointSet, + eCommandTypeBreakpointRemove, + eCommandTypeRegions, + eCommandTypeReattach, + eCommandTypeHostReboot, + eCommandTypeReadMemory64, + eCommandTypeWriteMemory64, + eCommandTypeBreakpointSet64, + eCommandTypeBreakpointRemove64, + eCommandTypeKernelVersion + } CommandType; - typedef enum + typedef enum { - eErrorSuccess = 0, - eErrorAlreadyConnected, - eErrorPacketToBig, - eErrorInvalidRegisterFlavor, - eErrorUnimplemented - } ErrorType; + KDP_PROTERR_SUCCESS = 0, + KDP_PROTERR_ALREADY_CONNECTED, + KDP_PROTERR_BAD_NBYTES, + KDP_PROTERR_BADFLAVOR + } KDPError; typedef enum { - ePacketTypeRequest = 0u, - ePacketTypeReply = 1u + ePacketTypeRequest = 0x00u, + ePacketTypeReply = 0x80u, + ePacketTypeMask = 0x80u, + eCommandTypeMask = 0x7fu } PacketType; //------------------------------------------------------------------ // Constructors and Destructors @@ -89,11 +89,11 @@ ~CommunicationKDP(); bool - SendRequestPacket (const lldb_private::StreamString &request_packet); + SendRequestPacket (const PacketStreamType &request_packet); // Wait for a packet within 'nsec' seconds size_t - WaitForPacketWithTimeoutMicroSeconds (StringExtractor &response, + WaitForPacketWithTimeoutMicroSeconds (lldb_private::DataExtractor &response, uint32_t usec); bool @@ -102,7 +102,7 @@ bool CheckForPacket (const uint8_t *src, size_t src_len, - StringExtractor &packet); + lldb_private::DataExtractor &packet); bool IsRunning() const { @@ -140,34 +140,81 @@ lldb_private::ProcessLaunchInfo &launch_info); - ErrorType + bool Connect (uint16_t reply_port, uint16_t exc_port, const char *greeting); - ErrorType + bool + Reattach (uint16_t reply_port); + + bool Disconnect (); + + uint32_t + GetVersion (); + + uint32_t + GetFeatureFlags (); + + uint32_t + GetCPUMask (); + + uint32_t + GetCPUType (); + + uint32_t + GetCPUSubtype (); protected: typedef std::list packet_collection; bool - SendRequestPacketNoLock (const lldb_private::StreamString &request_packet); + SendRequestPacketNoLock (const PacketStreamType &request_packet); size_t - WaitForPacketWithTimeoutMicroSecondsNoLock (StringExtractor &response, + WaitForPacketWithTimeoutMicroSecondsNoLock (lldb_private::DataExtractor &response, uint32_t timeout_usec); bool WaitForNotRunningPrivate (const lldb_private::TimeValue *timeout_ptr); void - MakeRequestPacketHeader (RequestType request_type, - lldb_private::StreamString &request_packet); + MakeRequestPacketHeader (CommandType request_type, + PacketStreamType &request_packet, + uint16_t request_length); + bool + SendRequestVersion (); + + + bool + VersionIsValid() const + { + return m_kdp_version_version != 0; + } + + bool + HostInfoIsValid() const + { + return m_kdp_hostinfo_cpu_type != 0; + } + + bool + SendRequestHostInfo (); + + void + ClearKDPSettings (); + + bool + SendRequestAndGetReply (const CommandType command, + const uint8_t request_sequence_id, + const PacketStreamType &request_packet, + lldb_private::DataExtractor &reply_packet); //------------------------------------------------------------------ // Classes that inherit from CommunicationKDP can see and modify these //------------------------------------------------------------------ + lldb::ByteOrder m_byte_order; uint32_t m_packet_timeout; lldb_private::Mutex m_sequence_mutex; // Restrict access to sending/receiving packets to a single thread at a time lldb_private::Predicate m_public_is_running; @@ -175,6 +222,11 @@ uint32_t m_session_key; uint8_t m_request_sequence_id; uint8_t m_exception_sequence_id; + uint32_t m_kdp_version_version; + uint32_t m_kdp_version_feature; + uint32_t m_kdp_hostinfo_cpu_mask; + uint32_t m_kdp_hostinfo_cpu_type; + uint32_t m_kdp_hostinfo_cpu_subtype; private: //------------------------------------------------------------------ // For CommunicationKDP only Modified: lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp?rev=135338&r1=135337&r2=135338&view=diff ============================================================================== --- lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp (original) +++ lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp Fri Jul 15 22:19:08 2011 @@ -63,7 +63,6 @@ if (triple_ref.getOS() == llvm::Triple::Darwin && triple_ref.getVendor() == llvm::Triple::Apple) { - ObjectFile *exe_objfile = exe_module_sp->GetObjectFile(); if (exe_objfile->GetType() == ObjectFile::eTypeExecutable && exe_objfile->GetStrata() == ObjectFile::eStrataKernel) From peter at pcc.me.uk Sat Jul 16 10:58:57 2011 From: peter at pcc.me.uk (Peter Collingbourne) Date: Sat, 16 Jul 2011 15:58:57 -0000 Subject: [Lldb-commits] [lldb] r135346 - /lldb/trunk/include/lldb/Core/InputReader.h Message-ID: <20110716155857.CE8262A6C12C@llvm.org> Author: pcc Date: Sat Jul 16 10:58:57 2011 New Revision: 135346 URL: http://llvm.org/viewvc/llvm-project?rev=135346&view=rev Log: Add missing #include, fixes Linux build Modified: lldb/trunk/include/lldb/Core/InputReader.h Modified: lldb/trunk/include/lldb/Core/InputReader.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/InputReader.h?rev=135346&r1=135345&r2=135346&view=diff ============================================================================== --- lldb/trunk/include/lldb/Core/InputReader.h (original) +++ lldb/trunk/include/lldb/Core/InputReader.h Sat Jul 16 10:58:57 2011 @@ -10,6 +10,8 @@ #ifndef liblldb_InputReader_h_ #define liblldb_InputReader_h_ +#include + #include "lldb/lldb-public.h" #include "lldb/lldb-enumerations.h" #include "lldb/Core/Error.h" From johnny.chen at apple.com Sat Jul 16 13:55:04 2011 From: johnny.chen at apple.com (Johnny Chen) Date: Sat, 16 Jul 2011 11:55:04 -0700 Subject: [Lldb-commits] [PATCH] Begin cleanup to silence G++ warnings In-Reply-To: <4E20A28C.9070402@crhc.illinois.edu> References: <4E20A28C.9070402@crhc.illinois.edu> Message-ID: Hi Matt, Thanks for the patch for silencing G++ warnings. I'll be looking into and applying the patch. For the Python docstrings / SWIG warnings by G++, we have been using clang and have not observed the warnings at all. However, I think I am going to create, for example, a separate SWIG interface file SBTarget.i, to spare the SBTarget.h header file from the Python-specific docstring litter. And .i interface files for other SB API objects will follow. Thanks. Johnny Chen On Jul 15, 2011, at 1:26 PM, Matt Johnson wrote: > Hi all, > This is the beginning of a cleanup effort to reduce the (vast) number of (mostly benign) warnings when compiling LLDB HEAD under G++ 4.5.2 on Ubuntu 11.04. Getting these warnings out of the way makes it much easier to spot more important warnings, if nothing else. The fixes here can be categorized as follows: > > * Use of a signed type as a for loop induction variable, when the loop bound is an unsigned type > * Assigning NULL (a pointer constant) to non-pointer types (e.g., uint32_t, addr_t) > * Declaring class members in one order, and including them in constructor initializer lists in a different order > > There are many more of the above warnings that I haven't gotten to yet, as well as things like the following: > * Python docstrings in e.g. SBTarget.h use a nonstandard gcc preprocessor extension that allows multi-line string literals. > - This causes *tons* of warnings (one per line of the literal, per inclusion of the relevant header). e.g.: > > /media/d2/llvm/tools/lldb/source/Target/../../include/lldb/API/SBTarget.h:23:1: warning: missing terminating " character > /media/d2/llvm/tools/lldb/source/Target/../../include/lldb/API/SBTarget.h:48:1: warning: missing terminating " character > /media/d2/llvm/tools/lldb/source/Target/../../include/lldb/API/SBTarget.h:91:27: warning: missing terminating " character > /media/d2/llvm/tools/lldb/source/Target/../../include/lldb/API/SBTarget.h:164:5: warning: missing terminating " character > /media/d2/llvm/tools/lldb/source/Target/../../include/lldb/API/SBTarget.h:180:27: warning: missing terminating " character > /media/d2/llvm/tools/lldb/source/Target/../../include/lldb/API/SBTarget.h:216:5: warning: missing terminating " character > /media/d2/llvm/tools/lldb/source/Target/../../include/lldb/API/SBTarget.h:224:27: warning: missing terminating " character > /media/d2/llvm/tools/lldb/source/Target/../../include/lldb/API/SBTarget.h:245:5: warning: missing terminating " character > /media/d2/llvm/tools/lldb/source/Target/../../include/lldb/API/SBTarget.h:253:27: warning: missing terminating " character > /media/d2/llvm/tools/lldb/source/Target/../../include/lldb/API/SBTarget.h:277:5: warning: missing terminating " character > /media/d2/llvm/tools/lldb/source/Target/../../include/lldb/API/SBTarget.h:286:27: warning: missing terminating " character > /media/d2/llvm/tools/lldb/source/Target/../../include/lldb/API/SBTarget.h:310:5: warning: missing terminating " character > /media/d2/llvm/tools/lldb/source/Target/../../include/lldb/API/SBTarget.h:334:27: warning: missing terminating " character > /media/d2/llvm/tools/lldb/source/Target/../../include/lldb/API/SBTarget.h:361:5: warning: missing terminating " character > /media/d2/llvm/tools/lldb/source/Target/../../include/lldb/API/SBTarget.h:370:27: warning: missing terminating " character > /media/d2/llvm/tools/lldb/source/Target/../../include/lldb/API/SBTarget.h:386:5: warning: missing terminating " character > > - These literals should be formed like: > > #ifdef SWIG > %feature("docstring", > "Represents the target program running under the debugger.\n" > "\n" > "SBTarget supports module and breakpoint iterations. For example,\n" > ... > > - instead of: > > %feature("docstring", > "Represents the target program running under the debugger. > > SBTarget supports module and breakpoint iterations. For example, > ... > > > * Use of (deprecated) instead of > * Not handling some enum values in a switch statement. e.g., "ClangASTType.cpp:283:12: warning: enumeration value ?UnaryTransform? not handled in switch" > * Defining static helper functions that are never used. e.g., "RegisterContextLinux_x86_64.cpp:408:17: warning: ?unsigned int GetRegSize(unsigned int)? defined but not used" > > Comments welcome. > Best, > Matt > _______________________________________________ > lldb-commits mailing list > lldb-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/lldb-commits From johnny.chen at apple.com Sat Jul 16 16:15:39 2011 From: johnny.chen at apple.com (Johnny Chen) Date: Sat, 16 Jul 2011 21:15:39 -0000 Subject: [Lldb-commits] [lldb] r135355 - in /lldb/trunk: include/lldb/API/SBTarget.h scripts/Python/interface/ scripts/Python/interface/SBTarget.i scripts/Python/modify-python-lldb.py scripts/lldb.swig Message-ID: <20110716211539.DFAB82A6C12C@llvm.org> Author: johnny Date: Sat Jul 16 16:15:39 2011 New Revision: 135355 URL: http://llvm.org/viewvc/llvm-project?rev=135355&view=rev Log: Create an interface file for SBTarget named SBTarget.i which relieves SBTarget.h of the duty of having SWIG docstring features and multiline string literals embedded within. lldb.swig now %include .../SBTarget.i, instead of .../SBTarget.h. Will create other interface files and transition them over. Also update modify-python-lldb.py to better handle the trailing blank line right before the ending '"""' Python docstring delimiter. Added: lldb/trunk/scripts/Python/interface/ lldb/trunk/scripts/Python/interface/SBTarget.i Modified: lldb/trunk/include/lldb/API/SBTarget.h lldb/trunk/scripts/Python/modify-python-lldb.py lldb/trunk/scripts/lldb.swig Modified: lldb/trunk/include/lldb/API/SBTarget.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/API/SBTarget.h?rev=135355&r1=135354&r2=135355&view=diff ============================================================================== --- lldb/trunk/include/lldb/API/SBTarget.h (original) +++ lldb/trunk/include/lldb/API/SBTarget.h Sat Jul 16 16:15:39 2011 @@ -18,41 +18,8 @@ class SBBreakpoint; -#ifdef SWIG -%feature("docstring", -"Represents the target program running under the debugger. - -SBTarget supports module and breakpoint iterations. For example, - - for m in target.module_iter(): - print m - -produces: - -(x86_64) /Volumes/data/lldb/svn/trunk/test/python_api/lldbutil/iter/a.out -(x86_64) /usr/lib/dyld -(x86_64) /usr/lib/libstdc++.6.dylib -(x86_64) /usr/lib/libSystem.B.dylib -(x86_64) /usr/lib/system/libmathCommon.A.dylib -(x86_64) /usr/lib/libSystem.B.dylib(__commpage) - -and, - - for b in target.breakpoint_iter(): - print b - -produces: - -SBBreakpoint: id = 1, file ='main.cpp', line = 66, locations = 1 -SBBreakpoint: id = 2, file ='main.cpp', line = 85, locations = 1 -" - ) SBTarget; -#endif class SBTarget { -#ifdef SWIG - %feature("autodoc", "1"); -#endif public: //------------------------------------------------------------------ // Broadcaster bits. @@ -87,9 +54,6 @@ lldb::SBProcess GetProcess (); -#ifdef SWIG - %feature("docstring", " -#endif //------------------------------------------------------------------ /// Launch a new process. /// @@ -146,23 +110,6 @@ /// @return /// A process object for the newly created process. //------------------------------------------------------------------ -#ifdef SWIG - -For example, - - process = target.Launch(self.dbg.GetListener(), None, None, - None, '/tmp/stdout.txt', None, - None, 0, False, error) - -launches a new process by passing nothing for both the args and the envs -and redirect the standard output of the inferior to the /tmp/stdout.txt -file. It does not specify a working directory so that the debug server -will use its idea of what the current working directory is for the -inferior. Also, we ask the debugger not to stop the inferior at the -entry point. If no breakpoint is specified for the inferior, it should -run to completion if no user interaction is required. - ") Launch; -#endif lldb::SBProcess Launch (SBListener &listener, char const **argv, @@ -176,9 +123,6 @@ lldb::SBError& error); -#ifdef SWIG - %feature("docstring", " -#endif //------------------------------------------------------------------ /// Launch a new process with sensible defaults. /// @@ -205,24 +149,11 @@ /// @return /// A process object for the newly created process. //------------------------------------------------------------------ -#ifdef SWIG - -For example, - - process = target.LaunchSimple(['X', 'Y', 'Z'], None, os.getcwd()) - -launches a new process by passing 'X', 'Y', 'Z' as the args to the -executable. - ") LaunchSimple; -#endif lldb::SBProcess LaunchSimple (const char **argv, const char **envp, const char *working_directory); -#ifdef SWIG - %feature("docstring", " -#endif //------------------------------------------------------------------ /// Attach to process with pid. /// @@ -241,17 +172,11 @@ /// @return /// A process object for the attached process. //------------------------------------------------------------------ -#ifdef SWIG - ") AttachToProcessWithID; -#endif lldb::SBProcess AttachToProcessWithID (SBListener &listener, lldb::pid_t pid, lldb::SBError& error); -#ifdef SWIG - %feature("docstring", " -#endif //------------------------------------------------------------------ /// Attach to process with name. /// @@ -273,18 +198,12 @@ /// @return /// A process object for the attached process. //------------------------------------------------------------------ -#ifdef SWIG - ") AttachToProcessWithName; -#endif lldb::SBProcess AttachToProcessWithName (SBListener &listener, const char *name, bool wait_for, lldb::SBError& error); -#ifdef SWIG - %feature("docstring", " -#endif //------------------------------------------------------------------ /// Connect to a remote debug server with url. /// @@ -306,9 +225,6 @@ /// @return /// A process object for the connected process. //------------------------------------------------------------------ -#ifdef SWIG - ") ConnectRemote; -#endif lldb::SBProcess ConnectRemote (SBListener &listener, const char *url, @@ -330,9 +246,6 @@ lldb::SBModule FindModule (const lldb::SBFileSpec &file_spec); -#ifdef SWIG - %feature("docstring", " -#endif //------------------------------------------------------------------ /// Find functions by name. /// @@ -357,18 +270,12 @@ /// @return /// The number of matches added to \a sc_list. //------------------------------------------------------------------ -#ifdef SWIG - ") FindFunctions; -#endif uint32_t FindFunctions (const char *name, uint32_t name_type_mask, // Logical OR one or more FunctionNameType enum bits bool append, lldb::SBSymbolContextList& sc_list); -#ifdef SWIG - %feature("docstring", " -#endif //------------------------------------------------------------------ /// Find global and static variables by name. /// @@ -382,9 +289,6 @@ /// @return /// A list of matched variables in an SBValueList. //------------------------------------------------------------------ -#ifdef SWIG - ") FindGlobalVariables; -#endif lldb::SBValueList FindGlobalVariables (const char *name, uint32_t max_matches); Added: lldb/trunk/scripts/Python/interface/SBTarget.i URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/scripts/Python/interface/SBTarget.i?rev=135355&view=auto ============================================================================== --- lldb/trunk/scripts/Python/interface/SBTarget.i (added) +++ lldb/trunk/scripts/Python/interface/SBTarget.i Sat Jul 16 16:15:39 2011 @@ -0,0 +1,449 @@ +//===-- SWIG Interface for SBTarget -----------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +namespace lldb { + +%feature("docstring", +"Represents the target program running under the debugger. + +SBTarget supports module and breakpoint iterations. For example, + + for m in target.module_iter(): + print m + +produces: + +(x86_64) /Volumes/data/lldb/svn/trunk/test/python_api/lldbutil/iter/a.out +(x86_64) /usr/lib/dyld +(x86_64) /usr/lib/libstdc++.6.dylib +(x86_64) /usr/lib/libSystem.B.dylib +(x86_64) /usr/lib/system/libmathCommon.A.dylib +(x86_64) /usr/lib/libSystem.B.dylib(__commpage) + +and, + + for b in target.breakpoint_iter(): + print b + +produces: + +SBBreakpoint: id = 1, file ='main.cpp', line = 66, locations = 1 +SBBreakpoint: id = 2, file ='main.cpp', line = 85, locations = 1 +" + ) SBTarget; +class SBTarget +{ + %feature("autodoc", "1"); +public: + //------------------------------------------------------------------ + // Broadcaster bits. + //------------------------------------------------------------------ + enum + { + eBroadcastBitBreakpointChanged = (1 << 0), + eBroadcastBitModulesLoaded = (1 << 1), + eBroadcastBitModulesUnloaded = (1 << 2) + }; + + //------------------------------------------------------------------ + // Constructors + //------------------------------------------------------------------ + SBTarget (); + + SBTarget (const lldb::SBTarget& rhs); + +#ifndef SWIG + const lldb::SBTarget& + operator = (const lldb::SBTarget& rhs); +#endif + + //------------------------------------------------------------------ + // Destructor + //------------------------------------------------------------------ + ~SBTarget(); + + bool + IsValid() const; + + lldb::SBProcess + GetProcess (); + + %feature("docstring", " + //------------------------------------------------------------------ + /// Launch a new process. + /// + /// Launch a new process by spawning a new process using the + /// target object's executable module's file as the file to launch. + /// Arguments are given in \a argv, and the environment variables + /// are in \a envp. Standard input and output files can be + /// optionally re-directed to \a stdin_path, \a stdout_path, and + /// \a stderr_path. + /// + /// @param[in] listener + /// An optional listener that will receive all process events. + /// If \a listener is valid then \a listener will listen to all + /// process events. If not valid, then this target's debugger + /// (SBTarget::GetDebugger()) will listen to all process events. + /// + /// @param[in] argv + /// The argument array. + /// + /// @param[in] envp + /// The environment array. + /// + /// @param[in] launch_flags + /// Flags to modify the launch (@see lldb::LaunchFlags) + /// + /// @param[in] stdin_path + /// The path to use when re-directing the STDIN of the new + /// process. If all stdXX_path arguments are NULL, a pseudo + /// terminal will be used. + /// + /// @param[in] stdout_path + /// The path to use when re-directing the STDOUT of the new + /// process. If all stdXX_path arguments are NULL, a pseudo + /// terminal will be used. + /// + /// @param[in] stderr_path + /// The path to use when re-directing the STDERR of the new + /// process. If all stdXX_path arguments are NULL, a pseudo + /// terminal will be used. + /// + /// @param[in] working_directory + /// The working directory to have the child process run in + /// + /// @param[in] launch_flags + /// Some launch options specified by logical OR'ing + /// lldb::LaunchFlags enumeration values together. + /// + /// @param[in] stop_at_endtry + /// If false do not stop the inferior at the entry point. + /// + /// @param[out] + /// An error object. Contains the reason if there is some failure. + /// + /// @return + /// A process object for the newly created process. + //------------------------------------------------------------------ + + For example, + + process = target.Launch(self.dbg.GetListener(), None, None, + None, '/tmp/stdout.txt', None, + None, 0, False, error) + + launches a new process by passing nothing for both the args and the envs + and redirect the standard output of the inferior to the /tmp/stdout.txt + file. It does not specify a working directory so that the debug server + will use its idea of what the current working directory is for the + inferior. Also, we ask the debugger not to stop the inferior at the + entry point. If no breakpoint is specified for the inferior, it should + run to completion if no user interaction is required. + ") Launch; + lldb::SBProcess + Launch (SBListener &listener, + char const **argv, + char const **envp, + const char *stdin_path, + const char *stdout_path, + const char *stderr_path, + const char *working_directory, + uint32_t launch_flags, // See LaunchFlags + bool stop_at_entry, + lldb::SBError& error); + + %feature("docstring", " + //------------------------------------------------------------------ + /// Launch a new process with sensible defaults. + /// + /// @param[in] argv + /// The argument array. + /// + /// @param[in] envp + /// The environment array. + /// + /// @param[in] working_directory + /// The working directory to have the child process run in + /// + /// Default: listener + /// Set to the target's debugger (SBTarget::GetDebugger()) + /// + /// Default: launch_flags + /// Empty launch flags + /// + /// Default: stdin_path + /// Default: stdout_path + /// Default: stderr_path + /// A pseudo terminal will be used. + /// + /// @return + /// A process object for the newly created process. + //------------------------------------------------------------------ + + For example, + + process = target.LaunchSimple(['X', 'Y', 'Z'], None, os.getcwd()) + + launches a new process by passing 'X', 'Y', 'Z' as the args to the + executable. + ") LaunchSimple; + lldb::SBProcess + LaunchSimple (const char **argv, + const char **envp, + const char *working_directory); + + %feature("docstring", " + //------------------------------------------------------------------ + /// Attach to process with pid. + /// + /// @param[in] listener + /// An optional listener that will receive all process events. + /// If \a listener is valid then \a listener will listen to all + /// process events. If not valid, then this target's debugger + /// (SBTarget::GetDebugger()) will listen to all process events. + /// + /// @param[in] pid + /// The process ID to attach to. + /// + /// @param[out] + /// An error explaining what went wrong if attach fails. + /// + /// @return + /// A process object for the attached process. + //------------------------------------------------------------------ + ") AttachToProcessWithID; + lldb::SBProcess + AttachToProcessWithID (SBListener &listener, + lldb::pid_t pid, + lldb::SBError& error); + + %feature("docstring", " + //------------------------------------------------------------------ + /// Attach to process with name. + /// + /// @param[in] listener + /// An optional listener that will receive all process events. + /// If \a listener is valid then \a listener will listen to all + /// process events. If not valid, then this target's debugger + /// (SBTarget::GetDebugger()) will listen to all process events. + /// + /// @param[in] name + /// Basename of process to attach to. + /// + /// @param[in] wait_for + /// If true wait for a new instance of 'name' to be launched. + /// + /// @param[out] + /// An error explaining what went wrong if attach fails. + /// + /// @return + /// A process object for the attached process. + //------------------------------------------------------------------ + ") AttachToProcessWithName; + lldb::SBProcess + AttachToProcessWithName (SBListener &listener, + const char *name, + bool wait_for, + lldb::SBError& error); + + %feature("docstring", " + //------------------------------------------------------------------ + /// Connect to a remote debug server with url. + /// + /// @param[in] listener + /// An optional listener that will receive all process events. + /// If \a listener is valid then \a listener will listen to all + /// process events. If not valid, then this target's debugger + /// (SBTarget::GetDebugger()) will listen to all process events. + /// + /// @param[in] url + /// The url to connect to, e.g., 'connect://localhost:12345'. + /// + /// @param[in] plugin_name + /// The plugin name to be used; can be NULL. + /// + /// @param[out] + /// An error explaining what went wrong if the connect fails. + /// + /// @return + /// A process object for the connected process. + //------------------------------------------------------------------ + ") ConnectRemote; + lldb::SBProcess + ConnectRemote (SBListener &listener, + const char *url, + const char *plugin_name, + SBError& error); + + lldb::SBFileSpec + GetExecutable (); + + uint32_t + GetNumModules () const; + + lldb::SBModule + GetModuleAtIndex (uint32_t idx); + + lldb::SBDebugger + GetDebugger() const; + + lldb::SBModule + FindModule (const lldb::SBFileSpec &file_spec); + + %feature("docstring", " + //------------------------------------------------------------------ + /// Find functions by name. + /// + /// @param[in] name + /// The name of the function we are looking for. + /// + /// @param[in] name_type_mask + /// A logical OR of one or more FunctionNameType enum bits that + /// indicate what kind of names should be used when doing the + /// lookup. Bits include fully qualified names, base names, + /// C++ methods, or ObjC selectors. + /// See FunctionNameType for more details. + /// + /// @param[in] append + /// If true, any matches will be appended to \a sc_list, else + /// matches replace the contents of \a sc_list. + /// + /// @param[out] sc_list + /// A symbol context list that gets filled in with all of the + /// matches. + /// + /// @return + /// The number of matches added to \a sc_list. + //------------------------------------------------------------------ + ") FindFunctions; + uint32_t + FindFunctions (const char *name, + uint32_t name_type_mask, // Logical OR one or more FunctionNameType enum bits + bool append, + lldb::SBSymbolContextList& sc_list); + + %feature("docstring", " + //------------------------------------------------------------------ + /// Find global and static variables by name. + /// + /// @param[in] name + /// The name of the global or static variable we are looking + /// for. + /// + /// @param[in] max_matches + /// Allow the number of matches to be limited to \a max_matches. + /// + /// @return + /// A list of matched variables in an SBValueList. + //------------------------------------------------------------------ + ") FindGlobalVariables; + lldb::SBValueList + FindGlobalVariables (const char *name, + uint32_t max_matches); + + void + Clear (); + + bool + ResolveLoadAddress (lldb::addr_t vm_addr, + lldb::SBAddress& addr); + + SBSymbolContext + ResolveSymbolContextForAddress (const SBAddress& addr, + uint32_t resolve_scope); + + lldb::SBBreakpoint + BreakpointCreateByLocation (const char *file, uint32_t line); + + lldb::SBBreakpoint + BreakpointCreateByLocation (const lldb::SBFileSpec &file_spec, uint32_t line); + + lldb::SBBreakpoint + BreakpointCreateByName (const char *symbol_name, const char *module_name = NULL); + + lldb::SBBreakpoint + BreakpointCreateByRegex (const char *symbol_name_regex, const char *module_name = NULL); + + lldb::SBBreakpoint + BreakpointCreateByAddress (addr_t address); + + uint32_t + GetNumBreakpoints () const; + + lldb::SBBreakpoint + GetBreakpointAtIndex (uint32_t idx) const; + + bool + BreakpointDelete (break_id_t break_id); + + lldb::SBBreakpoint + FindBreakpointByID (break_id_t break_id); + + bool + EnableAllBreakpoints (); + + bool + DisableAllBreakpoints (); + + bool + DeleteAllBreakpoints (); + + lldb::SBBroadcaster + GetBroadcaster () const; + +#ifndef SWIG + bool + operator == (const lldb::SBTarget &rhs) const; + + bool + operator != (const lldb::SBTarget &rhs) const; + +#endif + +#ifndef SWIG + bool + GetDescription (lldb::SBStream &description, lldb::DescriptionLevel description_level); +#endif + + bool + GetDescription (lldb::SBStream &description, lldb::DescriptionLevel description_level) const; + +protected: + friend class SBAddress; + friend class SBDebugger; + friend class SBFunction; + friend class SBProcess; + friend class SBSymbol; + friend class SBModule; + + //------------------------------------------------------------------ + // Constructors are private, use static Target::Create function to + // create an instance of this class. + //------------------------------------------------------------------ + + SBTarget (const lldb::TargetSP& target_sp); + + void + reset (const lldb::TargetSP& target_sp); + + lldb_private::Target * + operator ->() const; + + lldb_private::Target * + get() const; + +private: + //------------------------------------------------------------------ + // For Target only + //------------------------------------------------------------------ + + lldb::TargetSP m_opaque_sp; +}; + +} // namespace lldb Modified: lldb/trunk/scripts/Python/modify-python-lldb.py URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/scripts/Python/modify-python-lldb.py?rev=135355&r1=135354&r2=135355&view=diff ============================================================================== --- lldb/trunk/scripts/Python/modify-python-lldb.py (original) +++ lldb/trunk/scripts/Python/modify-python-lldb.py Sat Jul 16 16:15:39 2011 @@ -36,9 +36,8 @@ c_endif_swig = "#endif" c_ifdef_swig = "#ifdef SWIG" c_comment_marker = "//------------" -trailing_blank_line = ' ' # The pattern for recognizing the doxygen comment block line. -doxygen_comment_start = re.compile("^\s*( /// ?)") +doxygen_comment_start = re.compile("^\s*(/// ?)") # The demarcation point for turning on/off residue removal state. # When bracketed by the lines, the CLEANUP_DOCSTRING state (see below) is ON. toggle_docstring_cleanup_line = ' """' @@ -150,8 +149,31 @@ frag.write("self.{0}() == other.{0}()".format(list[i])) return frag.getvalue() +class NewContent(StringIO.StringIO): + """Simple facade to keep track of the previous line to be committed.""" + def __init__(self): + StringIO.StringIO.__init__(self) + self.prev_line = None + def add_line(self, a_line): + """Add a line to the content, if there is a previous line, commit it.""" + if self.prev_line != None: + print >> self, self.prev_line + self.prev_line = a_line + def del_line(self): + """Forget about the previous line, do not commit it.""" + self.prev_line = None + def del_blank_line(self): + """Forget about the previous line if it is a blank line.""" + if self.prev_line != None and not self.prev_line.strip(): + self.prev_line = None + def finish(self): + """Call this when you're finished with populating content.""" + if self.prev_line != None: + print >> self, self.prev_line + self.prev_line = None + # The new content will have the iteration protocol defined for our lldb objects. -new_content = StringIO.StringIO() +new_content = NewContent() with open(output_name, 'r') as f_in: content = f_in.read() @@ -200,6 +222,9 @@ # CLEANUP_DOCSTRING state or out of it. if line == toggle_docstring_cleanup_line: if state & CLEANUP_DOCSTRING: + # Special handling of the trailing blank line right before the '"""' + # end docstring marker. + new_content.del_blank_line() state ^= CLEANUP_DOCSTRING else: state |= CLEANUP_DOCSTRING @@ -208,7 +233,7 @@ match = class_pattern.search(line) # Inserts the lldb_iter() definition before the first class definition. if not lldb_iter_defined and match: - print >> new_content, lldb_iter_def + new_content.add_line(lldb_iter_def) lldb_iter_defined = True # If we are at the beginning of the class definitions, prepare to @@ -231,15 +256,15 @@ # # But note that SBTarget has two types of iterations. if cls == "SBTarget": - print >> new_content, module_iter % (d[cls]['module']) - print >> new_content, breakpoint_iter % (d[cls]['breakpoint']) + new_content.add_line(module_iter % (d[cls]['module'])) + new_content.add_line(breakpoint_iter % (d[cls]['breakpoint'])) else: if (state & DEFINING_ITERATOR): - print >> new_content, iter_def % d[cls] - print >> new_content, len_def % d[cls][0] + new_content.add_line(iter_def % d[cls]) + new_content.add_line(len_def % d[cls][0]) if (state & DEFINING_EQUALITY): - print >> new_content, eq_def % (cls, list_to_frag(e[cls])) - print >> new_content, ne_def + new_content.add_line(eq_def % (cls, list_to_frag(e[cls]))) + new_content.add_line(ne_def) # Next state will be NORMAL. state = NORMAL @@ -248,9 +273,10 @@ # Cleanse the lldb.py of the autodoc'ed residues. if c_ifdef_swig in line or c_endif_swig in line: continue - # As well as the comment marker line and trailing blank line. - if c_comment_marker in line or line == trailing_blank_line: + # As well as the comment marker line. + if c_comment_marker in line: continue + # Also remove the '\a ' and '\b 'substrings. line = line.replace('\a ', '') line = line.replace('\b ', '') @@ -272,11 +298,14 @@ # Look for 'def IsValid(*args):', and once located, add implementation # of truth value testing for this object by delegation. if isvalid_pattern.search(line): - print >> new_content, nonzero_def + new_content.add_line(nonzero_def) # Pass the original line of content to new_content. - print >> new_content, line - + new_content.add_line(line) + +# We are finished with recording new content. +new_content.finish() + with open(output_name, 'w') as f_out: f_out.write(new_content.getvalue()) f_out.write("debugger_unique_id = 0\n") Modified: lldb/trunk/scripts/lldb.swig URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/scripts/lldb.swig?rev=135355&r1=135354&r2=135355&view=diff ============================================================================== --- lldb/trunk/scripts/lldb.swig (original) +++ lldb/trunk/scripts/lldb.swig Sat Jul 16 16:15:39 2011 @@ -223,7 +223,7 @@ %include "lldb/API/SBSymbol.h" %include "lldb/API/SBSymbolContext.h" %include "lldb/API/SBSymbolContextList.h" -%include "lldb/API/SBTarget.h" +%include "./Python/interface/SBTarget.i" %include "lldb/API/SBThread.h" %include "lldb/API/SBType.h" %include "lldb/API/SBValue.h" From johnny.chen at apple.com Sat Jul 16 16:27:36 2011 From: johnny.chen at apple.com (Johnny Chen) Date: Sat, 16 Jul 2011 21:27:36 -0000 Subject: [Lldb-commits] [lldb] r135357 - in /lldb/trunk/scripts: Python/interface/SBTarget.i lldb.swig Message-ID: <20110716212736.D0C322A6C12C@llvm.org> Author: johnny Date: Sat Jul 16 16:27:36 2011 New Revision: 135357 URL: http://llvm.org/viewvc/llvm-project?rev=135357&view=rev Log: Have SWIG generate autodoc strings with parameter types for all SB API objects by default. Modified: lldb/trunk/scripts/Python/interface/SBTarget.i lldb/trunk/scripts/lldb.swig Modified: lldb/trunk/scripts/Python/interface/SBTarget.i URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/scripts/Python/interface/SBTarget.i?rev=135357&r1=135356&r2=135357&view=diff ============================================================================== --- lldb/trunk/scripts/Python/interface/SBTarget.i (original) +++ lldb/trunk/scripts/Python/interface/SBTarget.i Sat Jul 16 16:27:36 2011 @@ -39,7 +39,6 @@ ) SBTarget; class SBTarget { - %feature("autodoc", "1"); public: //------------------------------------------------------------------ // Broadcaster bits. Modified: lldb/trunk/scripts/lldb.swig URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/scripts/lldb.swig?rev=135357&r1=135356&r2=135357&view=diff ============================================================================== --- lldb/trunk/scripts/lldb.swig (original) +++ lldb/trunk/scripts/lldb.swig Sat Jul 16 16:27:36 2011 @@ -31,9 +31,11 @@ and a source file location. SBCompileUnit contains SBLineEntry(s)." %enddef -/* The name of the module to be created. */ +// The name of the module to be created. %module(docstring=DOCSTRING) lldb +// Parameter types will be used in the autodoc string. +%feature("autodoc", "1"); /* Typemap definitions, to allow SWIG to properly handle 'char**' data types. */ From gclayton at apple.com Sun Jul 17 15:36:25 2011 From: gclayton at apple.com (Greg Clayton) Date: Sun, 17 Jul 2011 20:36:25 -0000 Subject: [Lldb-commits] [lldb] r135363 - in /lldb/trunk: include/lldb/Core/ include/lldb/Target/ source/ source/Core/ source/Plugins/Process/MacOSX-Kernel/ source/Plugins/Process/MacOSX-User/source/ source/Plugins/Process/gdb-remote/ source/Target/ Message-ID: <20110717203625.CCCBF2A6C12C@llvm.org> Author: gclayton Date: Sun Jul 17 15:36:25 2011 New Revision: 135363 URL: http://llvm.org/viewvc/llvm-project?rev=135363&view=rev Log: Added a boolean to the pure virtual lldb_private::Process::CanDebug(...) method so process plug-ins that are requested by name can answer yes when asked if they can debug a target that might not have any file in the target. Modified the ConnectionFileDescriptor to have both a read and a write file descriptor. This allows us to support UDP, and eventually will allow us to support pipes. The ConnectionFileDescriptor class also has a file descriptor type for each of the read and write file decriptors so we can use the correct read/recv/recvfrom call when reading, or write/send/sendto for writing. Finished up an initial implementation of UDP where you can use the "udp://" URL to specify a host and port to connect to: (lldb) process connect --plugin kdp-remote udp://host:41139 This will cause a ConnectionFileDescriptor to be created that can send UDP packets to "host:41139", and it will also bind to a localhost port that can be given out to receive the connectionless UDP reply. Added the ability to get to the IPv4/IPv6 socket port number from a ConnectionFileDescriptor instance if either file descriptor is a socket. The ProcessKDP can now successfully connect to a remote kernel and detach using the above "processs connect" command!!! So far we have the following packets working: KDP_CONNECT KDP_DISCONNECT KDP_HOSTINFO KDP_VERSION KDP_REATTACH Now that the packets are working, adding new packets will go very quickly. Modified: lldb/trunk/include/lldb/Core/Communication.h lldb/trunk/include/lldb/Core/ConnectionFileDescriptor.h lldb/trunk/include/lldb/Core/DataExtractor.h lldb/trunk/include/lldb/Target/Process.h lldb/trunk/source/Core/ConnectionFileDescriptor.cpp lldb/trunk/source/Core/DataExtractor.cpp lldb/trunk/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp lldb/trunk/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.h lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h lldb/trunk/source/Plugins/Process/MacOSX-User/source/ProcessMacOSX.cpp lldb/trunk/source/Plugins/Process/MacOSX-User/source/ProcessMacOSX.h lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h lldb/trunk/source/Target/Process.cpp lldb/trunk/source/lldb.cpp Modified: lldb/trunk/include/lldb/Core/Communication.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/Communication.h?rev=135363&r1=135362&r2=135363&view=diff ============================================================================== --- lldb/trunk/include/lldb/Core/Communication.h (original) +++ lldb/trunk/include/lldb/Core/Communication.h Sun Jul 17 15:36:25 2011 @@ -167,6 +167,12 @@ bool HasConnection () const; + + lldb_private::Connection * + GetConnection () + { + return m_connection_sp.get(); + } //------------------------------------------------------------------ /// Read bytes from the current connection. /// Modified: lldb/trunk/include/lldb/Core/ConnectionFileDescriptor.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/ConnectionFileDescriptor.h?rev=135363&r1=135362&r2=135363&view=diff ============================================================================== --- lldb/trunk/include/lldb/Core/ConnectionFileDescriptor.h (original) +++ lldb/trunk/include/lldb/Core/ConnectionFileDescriptor.h Sun Jul 17 15:36:25 2011 @@ -56,6 +56,16 @@ lldb::ConnectionStatus &status, Error *error_ptr); + // If the read file descriptor is a socket, then return + // the port number that is being used by the socket. + in_port_t + GetReadPort () const; + + // If the write file descriptor is a socket, then return + // the port number that is being used by the socket. + in_port_t + GetWritePort () const; + protected: lldb::ConnectionStatus @@ -68,7 +78,7 @@ ConnectTCP (const char *host_and_port, Error *error_ptr); lldb::ConnectionStatus - ConnectUDP (const char *host_and_port, Error *error_ptr); + ConnectUDP (const char *args, Error *error_ptr); lldb::ConnectionStatus NamedSocketAccept (const char *socket_name, Error *error_ptr); @@ -85,13 +95,27 @@ eFDTypeSocket, // Socket requiring send/recv eFDTypeSocketUDP // Unconnected UDP socket requiring sendto/recvfrom } FDType; - int m_fd; // Socket we use to communicate once conn established - FDType m_fd_type; - struct sockaddr_storage m_udp_sockaddr; - socklen_t m_udp_sockaddr_len; + + typedef union sockaddr_tag + { + struct sockaddr sa; + struct sockaddr_in sa_ipv4; + struct sockaddr_in6 sa_ipv6; + struct sockaddr_storage sa_storage; + } sockaddr_t; + + + int m_fd_send; + int m_fd_recv; + FDType m_fd_send_type; + FDType m_fd_recv_type; + sockaddr_t m_udp_send_sockaddr; bool m_should_close_fd; // True if this class should close the file descriptor when it goes away. uint32_t m_socket_timeout_usec; + static in_port_t + GetSocketPort (int fd); + static int GetSocketOption(int fd, int level, int option_name, int &option_value); Modified: lldb/trunk/include/lldb/Core/DataExtractor.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/DataExtractor.h?rev=135363&r1=135362&r2=135363&view=diff ============================================================================== --- lldb/trunk/include/lldb/Core/DataExtractor.h (original) +++ lldb/trunk/include/lldb/Core/DataExtractor.h Sun Jul 17 15:36:25 2011 @@ -58,7 +58,8 @@ DumpHexBytes (Stream *s, const void *src, size_t src_len, - lldb::addr_t base_addr = LLDB_INVALID_ADDRESS); + uint32_t bytes_per_line, + lldb::addr_t base_addr); // Pass LLDB_INVALID_ADDRESS to not show address at start of line //------------------------------------------------------------------ /// Default constructor. /// Modified: lldb/trunk/include/lldb/Target/Process.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/Process.h?rev=135363&r1=135362&r2=135363&view=diff ============================================================================== --- lldb/trunk/include/lldb/Target/Process.h (original) +++ lldb/trunk/include/lldb/Target/Process.h Sun Jul 17 15:36:25 2011 @@ -1169,7 +1169,8 @@ /// debug the executable, \b false otherwise. //------------------------------------------------------------------ virtual bool - CanDebug (Target &target) = 0; + CanDebug (Target &target, + bool plugin_specified_by_name) = 0; //------------------------------------------------------------------ Modified: lldb/trunk/source/Core/ConnectionFileDescriptor.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/ConnectionFileDescriptor.cpp?rev=135363&r1=135362&r2=135363&view=diff ============================================================================== --- lldb/trunk/source/Core/ConnectionFileDescriptor.cpp (original) +++ lldb/trunk/source/Core/ConnectionFileDescriptor.cpp Sun Jul 17 15:36:25 2011 @@ -35,61 +35,88 @@ using namespace lldb; using namespace lldb_private; +static bool +DecodeHostAndPort (const char *host_and_port, + std::string &host_str, + std::string &port_str, + int32_t& port, + Error *error_ptr) +{ + RegularExpression regex ("([^:]+):([0-9]+)"); + if (regex.Execute (host_and_port, 2)) + { + if (regex.GetMatchAtIndex (host_and_port, 1, host_str) && + regex.GetMatchAtIndex (host_and_port, 2, port_str)) + { + port = Args::StringToSInt32 (port_str.c_str(), INT32_MIN); + if (port != INT32_MIN) + { + if (error_ptr) + error_ptr->Clear(); + return true; + } + } + } + host_str.clear(); + port_str.clear(); + port = INT32_MIN; + if (error_ptr) + error_ptr->SetErrorStringWithFormat("invalid host:port specification: '%s'", host_and_port); + return false; +} + ConnectionFileDescriptor::ConnectionFileDescriptor () : Connection(), - m_fd (-1), - m_fd_type (eFDTypeFile), - m_udp_sockaddr (), - m_udp_sockaddr_len (0), + m_fd_send (-1), + m_fd_recv (-1), + m_fd_send_type (eFDTypeFile), + m_fd_recv_type (eFDTypeFile), m_should_close_fd (false), m_socket_timeout_usec(0) { - memset (&m_udp_sockaddr, 0, sizeof(m_udp_sockaddr)); + memset (&m_udp_send_sockaddr, 0, sizeof(m_udp_send_sockaddr)); - lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION | LIBLLDB_LOG_OBJECT, - "%p ConnectionFileDescriptor::ConnectionFileDescriptor ()", - this); + LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION | LIBLLDB_LOG_OBJECT)); + if (log) + log->Printf ("%p ConnectionFileDescriptor::ConnectionFileDescriptor ()", this); } ConnectionFileDescriptor::ConnectionFileDescriptor (int fd, bool owns_fd) : Connection(), - m_fd (fd), - m_fd_type (eFDTypeFile), - m_udp_sockaddr (), - m_udp_sockaddr_len (0), + m_fd_send (fd), + m_fd_recv (fd), + m_fd_send_type (eFDTypeFile), + m_fd_recv_type (eFDTypeFile), m_should_close_fd (owns_fd), m_socket_timeout_usec(0) { - memset (&m_udp_sockaddr, 0, sizeof(m_udp_sockaddr)); - lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION | LIBLLDB_LOG_OBJECT, - "%p ConnectionFileDescriptor::ConnectionFileDescriptor (fd = %i, owns_fd = %i)", - this, - fd, - owns_fd); + memset (&m_udp_send_sockaddr, 0, sizeof(m_udp_send_sockaddr)); + LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION | LIBLLDB_LOG_OBJECT)); + if (log) + log->Printf ("%p ConnectionFileDescriptor::ConnectionFileDescriptor (fd = %i, owns_fd = %i)", this, fd, owns_fd); } ConnectionFileDescriptor::~ConnectionFileDescriptor () { - lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION | LIBLLDB_LOG_OBJECT, - "%p ConnectionFileDescriptor::~ConnectionFileDescriptor ()", - this); + LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION | LIBLLDB_LOG_OBJECT)); + if (log) + log->Printf ("%p ConnectionFileDescriptor::~ConnectionFileDescriptor ()", this); Disconnect (NULL); } bool ConnectionFileDescriptor::IsConnected () const { - return m_fd >= 0; + return m_fd_send >= 0 || m_fd_recv >= 0; } ConnectionStatus ConnectionFileDescriptor::Connect (const char *s, Error *error_ptr) { - lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION, - "%p ConnectionFileDescriptor::Connect (url = '%s')", - this, - s); + LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION)); + if (log) + log->Printf ("%p ConnectionFileDescriptor::Connect (url = '%s')", this, s); if (s && s[0]) { @@ -109,9 +136,9 @@ { return ConnectTCP (s + strlen("connect://"), error_ptr); } - else if (strstr(s, "tcp://")) + else if (strstr(s, "tcp-connect://")) { - return ConnectTCP (s + strlen("tcp://"), error_ptr); + return ConnectTCP (s + strlen("tcp-connect://"), error_ptr); } else if (strstr(s, "udp://")) { @@ -123,7 +150,8 @@ // that is already opened (possibly from a service or other source). s += strlen ("fd://"); bool success = false; - m_fd = Args::StringToSInt32 (s, -1, 0, &success); + m_fd_send = m_fd_recv = Args::StringToSInt32 (s, -1, 0, &success); + if (success) { // We have what looks to be a valid file descriptor, but we @@ -131,12 +159,12 @@ // get the flags from the file descriptor and making sure it // isn't a bad fd. errno = 0; - int flags = ::fcntl (m_fd, F_GETFL, 0); + int flags = ::fcntl (m_fd_send, F_GETFL, 0); if (flags == -1 || errno == EBADF) { if (error_ptr) error_ptr->SetErrorStringWithFormat ("stale file descriptor: %s", s); - m_fd = -1; + m_fd_send = m_fd_recv = -1; return eConnectionStatusError; } else @@ -144,9 +172,9 @@ // Try and get a socket option from this file descriptor to // see if this is a socket and set m_is_socket accordingly. int resuse; - bool is_socket = GetSocketOption (m_fd, SOL_SOCKET, SO_REUSEADDR, resuse) == 0; + bool is_socket = GetSocketOption (m_fd_send, SOL_SOCKET, SO_REUSEADDR, resuse) == 0; if (is_socket) - m_fd_type = eFDTypeSocket; + m_fd_send_type = m_fd_recv_type = eFDTypeSocket; m_should_close_fd = true; return eConnectionStatusSuccess; } @@ -154,28 +182,28 @@ if (error_ptr) error_ptr->SetErrorStringWithFormat ("invalid file descriptor: \"fd://%s\"", s); - m_fd = -1; + m_fd_send = m_fd_recv = -1; return eConnectionStatusError; } else if (strstr(s, "file://")) { // file:///PATH const char *path = s + strlen("file://"); - m_fd = ::open (path, O_RDWR); - if (m_fd == -1) + m_fd_send = m_fd_recv = ::open (path, O_RDWR); + if (m_fd_send == -1) { if (error_ptr) error_ptr->SetErrorToErrno(); return eConnectionStatusError; } - int flags = ::fcntl (m_fd, F_GETFL, 0); + int flags = ::fcntl (m_fd_send, F_GETFL, 0); if (flags >= 0) { if ((flags & O_NONBLOCK) == 0) { flags |= O_NONBLOCK; - ::fcntl (m_fd, F_SETFL, flags); + ::fcntl (m_fd_send, F_SETFL, flags); } } m_should_close_fd = true; @@ -193,15 +221,34 @@ ConnectionStatus ConnectionFileDescriptor::Disconnect (Error *error_ptr) { - lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION, - "%p ConnectionFileDescriptor::Disconnect ()", - this); + LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION)); + if (log) + log->Printf ("%p ConnectionFileDescriptor::Disconnect ()", this); if (m_should_close_fd == false) { - m_fd = -1; + m_fd_send = m_fd_recv = -1; return eConnectionStatusSuccess; } - return Close (m_fd, error_ptr); + ConnectionStatus status = eConnectionStatusSuccess; + if (m_fd_send == m_fd_recv) + { + // Both file descriptors are the same, only close one + status = Close (m_fd_send, error_ptr); + m_fd_recv = -1; + } + else + { + // File descriptors are the different, close both if needed + if (m_fd_send >= 0) + status = Close (m_fd_send, error_ptr); + if (m_fd_recv >= 0) + { + ConnectionStatus recv_status = Close (m_fd_recv, error_ptr); + if (status == eConnectionStatusSuccess) + status = recv_status; + } + } + return status; } size_t @@ -214,25 +261,23 @@ LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION)); if (log) log->Printf ("%p ConnectionFileDescriptor::Read () ::read (fd = %i, dst = %p, dst_len = %zu)...", - this, m_fd, dst, dst_len); + this, m_fd_recv, dst, dst_len); ssize_t bytes_read = 0; - struct sockaddr_storage from; - socklen_t from_len = sizeof(from); - switch (m_fd_type) + switch (m_fd_recv_type) { case eFDTypeFile: // Other FD requireing read/write status = BytesAvailable (timeout_usec, error_ptr); if (status == eConnectionStatusSuccess) - bytes_read = ::read (m_fd, dst, dst_len); + bytes_read = ::read (m_fd_recv, dst, dst_len); break; case eFDTypeSocket: // Socket requiring send/recv if (SetSocketReceiveTimeout (timeout_usec)) { status = eConnectionStatusSuccess; - bytes_read = ::recv (m_fd, dst, dst_len, 0); + bytes_read = ::recv (m_fd_recv, dst, dst_len, 0); } break; @@ -240,8 +285,9 @@ if (SetSocketReceiveTimeout (timeout_usec)) { status = eConnectionStatusSuccess; - ::memset (&from, 0, sizeof(from)); - bytes_read = ::recvfrom (m_fd, dst, dst_len, 0, (struct sockaddr *)&from, &from_len); + sockaddr_t from = m_udp_send_sockaddr; + socklen_t from_len = m_udp_send_sockaddr.sa.sa_len; + bytes_read = ::recvfrom (m_fd_recv, dst, dst_len, 0, (struct sockaddr *)&from, &from_len); } break; } @@ -267,7 +313,7 @@ if (log) log->Printf ("%p ConnectionFileDescriptor::Read () ::read (fd = %i, dst = %p, dst_len = %zu) => %zi, error = %s", this, - m_fd, + m_fd_recv, dst, dst_len, bytes_read, @@ -282,7 +328,10 @@ switch (error_value) { case EAGAIN: // The file was marked for non-blocking I/O, and no data were ready to be read. - status = eConnectionStatusSuccess; + if (m_fd_recv_type == eFDTypeSocket || m_fd_recv_type == eFDTypeSocketUDP) + status = eConnectionStatusTimedOut; + else + status = eConnectionStatusSuccess; return 0; case EFAULT: // Buf points outside the allocated address space. @@ -315,9 +364,7 @@ return 0; } -// if (log) -// error->Log(log, "::read ( %i, %p, %zu ) => %i", m_fd, dst, dst_len, bytesread); - Close (m_fd, NULL); + Disconnect (NULL); return 0; } return bytes_read; @@ -343,24 +390,24 @@ ssize_t bytes_sent = 0; - switch (m_fd_type) + switch (m_fd_send_type) { case eFDTypeFile: // Other FD requireing read/write - bytes_sent = ::write (m_fd, src, src_len); + bytes_sent = ::write (m_fd_send, src, src_len); break; case eFDTypeSocket: // Socket requiring send/recv - bytes_sent = ::send (m_fd, src, src_len, 0); + bytes_sent = ::send (m_fd_send, src, src_len, 0); break; case eFDTypeSocketUDP: // Unconnected UDP socket requiring sendto/recvfrom - assert (m_udp_sockaddr_len != 0); - bytes_sent = ::sendto (m_fd, + assert (m_udp_send_sockaddr.sa_storage.ss_family != 0); + bytes_sent = ::sendto (m_fd_send, src, src_len, 0, - (struct sockaddr *)&m_udp_sockaddr, - m_udp_sockaddr_len); + &m_udp_send_sockaddr.sa, + m_udp_send_sockaddr.sa.sa_len); break; } @@ -371,12 +418,12 @@ if (log) { - switch (m_fd_type) + switch (m_fd_send_type) { case eFDTypeFile: // Other FD requireing read/write log->Printf ("%p ConnectionFileDescriptor::Write() ::write (fd = %i, src = %p, src_len = %zu) => %zi (error = %s)", this, - m_fd, + m_fd_send, src, src_len, bytes_sent, @@ -386,7 +433,7 @@ case eFDTypeSocket: // Socket requiring send/recv log->Printf ("%p ConnectionFileDescriptor::Write() ::send (socket = %i, src = %p, src_len = %zu, flags = 0) => %zi (error = %s)", this, - m_fd, + m_fd_send, src, src_len, bytes_sent, @@ -396,7 +443,7 @@ case eFDTypeSocketUDP: // Unconnected UDP socket requiring sendto/recvfrom log->Printf ("%p ConnectionFileDescriptor::Write() ::sendto (socket = %i, src = %p, src_len = %zu, flags = 0) => %zi (error = %s)", this, - m_fd, + m_fd_send, src, src_len, bytes_sent, @@ -427,7 +474,7 @@ break; // Break to close.... } - Close (m_fd, NULL); + Disconnect (NULL); return 0; } @@ -460,16 +507,15 @@ { fd_set read_fds; FD_ZERO (&read_fds); - FD_SET (m_fd, &read_fds); - int nfds = m_fd + 1; + FD_SET (m_fd_recv, &read_fds); + int nfds = m_fd_recv + 1; Error error; - log = lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION); if (log) log->Printf("%p ConnectionFileDescriptor::BytesAvailable() ::select (nfds = %i, fd = %i, NULL, NULL, timeout = %p)...", - this, nfds, m_fd, tv_ptr); + this, nfds, m_fd_recv, tv_ptr); const int num_set_fds = ::select (nfds, &read_fds, NULL, NULL, tv_ptr); if (num_set_fds < 0) @@ -477,10 +523,9 @@ else error.Clear(); - log = lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION); if (log) log->Printf("%p ConnectionFileDescriptor::BytesAvailable() ::select (nfds = %i, fd = %i, NULL, NULL, timeout = %p) => %d, error = %s", - this, nfds, m_fd, tv_ptr, num_set_fds, error.AsCString()); + this, nfds, m_fd_recv, tv_ptr, num_set_fds, error.AsCString()); if (error_ptr) *error_ptr = error; @@ -528,10 +573,9 @@ bool success = true; if (fd >= 0) { - lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION, - "%p ConnectionFileDescriptor::Close (fd = %i)", - this, - fd); + LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION)); + if (log) + log->Printf ("%p ConnectionFileDescriptor::Close (fd = %i)", this,fd); success = ::close (fd) == 0; if (!success && error_ptr) @@ -543,7 +587,7 @@ } fd = -1; } - m_fd_type = eFDTypeFile; + m_fd_send_type = m_fd_recv_type = eFDTypeFile; if (success) return eConnectionStatusSuccess; else @@ -556,7 +600,7 @@ ConnectionStatus result = eConnectionStatusError; struct sockaddr_un saddr_un; - m_fd_type = eFDTypeSocket; + m_fd_send_type = m_fd_recv_type = eFDTypeSocket; int listen_socket = ::socket (AF_UNIX, SOCK_STREAM, 0); if (listen_socket == -1) @@ -577,8 +621,8 @@ { if (::listen (listen_socket, 5) == 0) { - m_fd = ::accept (listen_socket, NULL, 0); - if (m_fd > 0) + m_fd_send = m_fd_recv = ::accept (listen_socket, NULL, 0); + if (m_fd_send > 0) { m_should_close_fd = true; @@ -602,13 +646,13 @@ ConnectionStatus ConnectionFileDescriptor::NamedSocketConnect (const char *socket_name, Error *error_ptr) { - Close (m_fd, NULL); - m_fd_type = eFDTypeSocket; + Disconnect (NULL); + m_fd_send_type = m_fd_recv_type = eFDTypeSocket; // Open the socket that was passed in as an option struct sockaddr_un saddr_un; - m_fd = ::socket (AF_UNIX, SOCK_STREAM, 0); - if (m_fd == -1) + m_fd_send = m_fd_recv = ::socket (AF_UNIX, SOCK_STREAM, 0); + if (m_fd_send == -1) { if (error_ptr) error_ptr->SetErrorToErrno(); @@ -622,11 +666,11 @@ saddr_un.sun_len = SUN_LEN (&saddr_un); #endif - if (::connect (m_fd, (struct sockaddr *)&saddr_un, SUN_LEN (&saddr_un)) < 0) + if (::connect (m_fd_send, (struct sockaddr *)&saddr_un, SUN_LEN (&saddr_un)) < 0) { if (error_ptr) error_ptr->SetErrorToErrno(); - Close (m_fd, NULL); + Disconnect (NULL); return eConnectionStatusError; } if (error_ptr) @@ -637,12 +681,12 @@ ConnectionStatus ConnectionFileDescriptor::SocketListen (uint16_t listen_port_num, Error *error_ptr) { - lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION, - "%p ConnectionFileDescriptor::SocketListen (port = %i)", - this, listen_port_num); + LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION)); + if (log) + log->Printf ("%p ConnectionFileDescriptor::SocketListen (port = %i)", this, listen_port_num); - Close (m_fd, NULL); - m_fd_type = eFDTypeSocket; + Disconnect (NULL); + m_fd_send_type = m_fd_recv_type = eFDTypeSocket; int listen_port = ::socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); if (listen_port == -1) { @@ -678,8 +722,8 @@ return eConnectionStatusError; } - m_fd = ::accept (listen_port, NULL, 0); - if (m_fd == -1) + m_fd_send = m_fd_recv = ::accept (listen_port, NULL, 0); + if (m_fd_send == -1) { if (error_ptr) error_ptr->SetErrorToErrno(); @@ -693,7 +737,7 @@ m_should_close_fd = true; // Keep our TCP packets coming without any delays. - SetSocketOption (m_fd, IPPROTO_TCP, TCP_NODELAY, 1); + SetSocketOption (m_fd_send, IPPROTO_TCP, TCP_NODELAY, 1); if (error_ptr) error_ptr->Clear(); return eConnectionStatusSuccess; @@ -702,39 +746,21 @@ ConnectionStatus ConnectionFileDescriptor::ConnectTCP (const char *host_and_port, Error *error_ptr) { - lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION, - "%p ConnectionFileDescriptor::ConnectTCP (host/port = %s)", - this, host_and_port); - Close (m_fd, NULL); - m_fd_type = eFDTypeSocket; + LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION)); + if (log) + log->Printf ("%p ConnectionFileDescriptor::ConnectTCP (host/port = %s)", this, host_and_port); + Disconnect (NULL); - RegularExpression regex ("([^:]+):([0-9]+)"); - if (regex.Execute (host_and_port, 2) == false) - { - if (error_ptr) - error_ptr->SetErrorStringWithFormat("invalid host:port specification: '%s'", host_and_port); - return eConnectionStatusError; - } + m_fd_send_type = m_fd_recv_type = eFDTypeSocket; std::string host_str; std::string port_str; - if (regex.GetMatchAtIndex (host_and_port, 1, host_str) == false || - regex.GetMatchAtIndex (host_and_port, 2, port_str) == false) - { - if (error_ptr) - error_ptr->SetErrorStringWithFormat("invalid host:port specification '%s'", host_and_port); + int32_t port = INT32_MIN; + if (!DecodeHostAndPort (host_and_port, host_str, port_str, port, error_ptr)) return eConnectionStatusError; - } - int32_t port = Args::StringToSInt32 (port_str.c_str(), INT32_MIN); - if (port == INT32_MIN) - { - if (error_ptr) - error_ptr->SetErrorStringWithFormat("invalid port '%s'", port_str.c_str()); - return eConnectionStatusError; - } // Create the socket - m_fd = ::socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); - if (m_fd == -1) + m_fd_send = m_fd_recv = ::socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (m_fd_send == -1) { if (error_ptr) error_ptr->SetErrorToErrno(); @@ -744,7 +770,7 @@ m_should_close_fd = true; // Enable local address reuse - SetSocketOption (m_fd, SOL_SOCKET, SO_REUSEADDR, 1); + SetSocketOption (m_fd_send, SOL_SOCKET, SO_REUSEADDR, 1); struct sockaddr_in sa; ::memset (&sa, 0, sizeof (sa)); @@ -769,21 +795,23 @@ else error_ptr->SetErrorStringWithFormat("invalid host string: '%s'", host_str.c_str()); } - Close (m_fd, NULL); + Disconnect (NULL); + return eConnectionStatusError; } } - if (-1 == ::connect (m_fd, (const struct sockaddr *)&sa, sizeof(sa))) + if (-1 == ::connect (m_fd_send, (const struct sockaddr *)&sa, sizeof(sa))) { if (error_ptr) error_ptr->SetErrorToErrno(); - Close (m_fd, NULL); + Disconnect (NULL); + return eConnectionStatusError; } // Keep our TCP packets coming without any delays. - SetSocketOption (m_fd, IPPROTO_TCP, TCP_NODELAY, 1); + SetSocketOption (m_fd_send, IPPROTO_TCP, TCP_NODELAY, 1); if (error_ptr) error_ptr->Clear(); return eConnectionStatusSuccess; @@ -792,90 +820,104 @@ ConnectionStatus ConnectionFileDescriptor::ConnectUDP (const char *host_and_port, Error *error_ptr) { - lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION, - "%p ConnectionFileDescriptor::ConnectUDP (host/port = %s)", - this, host_and_port); - Close (m_fd, NULL); - m_fd_type = eFDTypeSocketUDP; + LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION)); + if (log) + log->Printf ("%p ConnectionFileDescriptor::ConnectUDP (host/port = %s)", this, host_and_port); + Disconnect (NULL); + + m_fd_send_type = m_fd_recv_type = eFDTypeSocketUDP; - RegularExpression regex ("([^:]+):([0-9]+)"); - if (regex.Execute (host_and_port, 2) == false) - { - if (error_ptr) - error_ptr->SetErrorStringWithFormat("invalid host:port specification: '%s'", host_and_port); - return eConnectionStatusError; - } std::string host_str; std::string port_str; - if (regex.GetMatchAtIndex (host_and_port, 1, host_str) == false || - regex.GetMatchAtIndex (host_and_port, 2, port_str) == false) + int32_t port = INT32_MIN; + if (!DecodeHostAndPort (host_and_port, host_str, port_str, port, error_ptr)) + return eConnectionStatusError; + + // Setup the receiving end of the UDP connection on this localhost + // on port zero. After we bind to port zero we can read the port. + m_fd_recv = ::socket (AF_INET, SOCK_DGRAM, 0); + if (m_fd_recv == -1) { + // Socket creation failed... if (error_ptr) - error_ptr->SetErrorStringWithFormat("invalid host:port specification '%s'", host_and_port); - return eConnectionStatusError; + error_ptr->SetErrorToErrno(); } - - int32_t port = Args::StringToSInt32 (port_str.c_str(), INT32_MIN); - if (port == INT32_MIN) + else { - if (error_ptr) - error_ptr->SetErrorStringWithFormat("invalid port '%s'", port_str.c_str()); - return eConnectionStatusError; + // Socket was created, now lets bind to the requested port + struct sockaddr_in sin; + ::memset (&sin, 0, sizeof(sin)); + sin.sin_len = sizeof(sin); + sin.sin_family = AF_INET; + sin.sin_port = 0; + sin.sin_addr.s_addr = htonl (INADDR_ANY); + + if (::bind (m_fd_recv, (struct sockaddr *)&sin, sizeof(sin)) == -1) + { + // Bind failed... + if (error_ptr) + error_ptr->SetErrorToErrno(); + Disconnect (NULL); + } } - // Create the socket - m_fd = ::socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP); - if (m_fd == -1) + + if (m_fd_recv == -1) + return eConnectionStatusError; + + // At this point we have setup the recieve port, now we need to + // setup the UDP send socket + + struct addrinfo hints; + struct addrinfo *service_info_list = NULL; + + ::memset (&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET; + hints.ai_socktype = SOCK_DGRAM; + int err = ::getaddrinfo (host_str.c_str(), port_str.c_str(), &hints, &service_info_list); + if (err != 0) { if (error_ptr) - error_ptr->SetErrorToErrno(); - return eConnectionStatusError; + error_ptr->SetErrorStringWithFormat("getaddrinfo(%s, %s, &hints, &info) returned error %i (%s)", + host_str.c_str(), + port_str.c_str(), + err, + gai_strerror(err)); + Disconnect (NULL); + return eConnectionStatusError; } - m_should_close_fd = true; - - // Enable local address reuse - SetSocketOption (m_fd, SOL_SOCKET, SO_REUSEADDR, 1); - - struct sockaddr_in sa; - ::memset (&sa, 0, sizeof (sa)); - sa.sin_family = AF_INET; - sa.sin_port = htons (port); - - int inet_pton_result = ::inet_pton (AF_INET, host_str.c_str(), &sa.sin_addr); - - if (inet_pton_result <= 0) + for (struct addrinfo *service_info_ptr = service_info_list; + service_info_ptr != NULL; + service_info_ptr = service_info_ptr->ai_next) { - struct hostent *host_entry = gethostbyname (host_str.c_str()); - if (host_entry) - host_str = ::inet_ntoa (*(struct in_addr *)*host_entry->h_addr_list); - inet_pton_result = ::inet_pton (AF_INET, host_str.c_str(), &sa.sin_addr); - if (inet_pton_result <= 0) + m_fd_send = ::socket (service_info_ptr->ai_family, + service_info_ptr->ai_socktype, + service_info_ptr->ai_protocol); + + if (m_fd_send != -1) { - - if (error_ptr) - { - if (inet_pton_result == -1) - error_ptr->SetErrorToErrno(); - else - error_ptr->SetErrorStringWithFormat("invalid host string: '%s'", host_str.c_str()); - } - Close (m_fd, NULL); - return eConnectionStatusError; + ::memset (&m_udp_send_sockaddr, 0, sizeof(m_udp_send_sockaddr)); + ::memcpy (&m_udp_send_sockaddr, + service_info_ptr->ai_addr, + service_info_ptr->ai_addrlen); + break; } + else + continue; } - if (-1 == ::connect (m_fd, (const struct sockaddr *)&sa, sizeof(sa))) + :: freeaddrinfo (service_info_list); + + if (m_fd_send == -1) { - if (error_ptr) - error_ptr->SetErrorToErrno(); - Close (m_fd, NULL); + Disconnect (NULL); return eConnectionStatusError; } - - // Keep our TCP packets coming without any delays. - SetSocketOption (m_fd, IPPROTO_TCP, TCP_NODELAY, 1); + if (error_ptr) error_ptr->Clear(); + + m_should_close_fd = true; return eConnectionStatusSuccess; } @@ -905,7 +947,7 @@ bool ConnectionFileDescriptor::SetSocketReceiveTimeout (uint32_t timeout_usec) { - switch (m_fd_type) + switch (m_fd_recv_type) { case eFDTypeFile: // Other FD requireing read/write break; @@ -921,7 +963,7 @@ struct timeval timeout; timeout.tv_sec = timeout_usec / TimeValue::MicroSecPerSec; timeout.tv_usec = timeout_usec % TimeValue::MicroSecPerSec; - if (::setsockopt (m_fd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)) == 0) + if (::setsockopt (m_fd_recv, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)) == 0) { m_socket_timeout_usec = timeout_usec; return true; @@ -931,4 +973,38 @@ return false; } +in_port_t +ConnectionFileDescriptor::GetSocketPort (int fd) +{ + // We bound to port zero, so we need to figure out which port we actually bound to + sockaddr_t sock_addr; + socklen_t sock_addr_len = sizeof (sock_addr); + if (::getsockname (fd, &sock_addr.sa, &sock_addr_len) == 0) + { + switch (sock_addr.sa.sa_family) + { + case AF_INET: return sock_addr.sa_ipv4.sin_port; + case AF_INET6: return sock_addr.sa_ipv6.sin6_port; + } + } + return 0; + +} + +// If the read file descriptor is a socket, then return +// the port number that is being used by the socket. +in_port_t +ConnectionFileDescriptor::GetReadPort () const +{ + return ConnectionFileDescriptor::GetSocketPort (m_fd_recv); +} + +// If the write file descriptor is a socket, then return +// the port number that is being used by the socket. +in_port_t +ConnectionFileDescriptor::GetWritePort () const +{ + return ConnectionFileDescriptor::GetSocketPort (m_fd_send); +} + Modified: lldb/trunk/source/Core/DataExtractor.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/DataExtractor.cpp?rev=135363&r1=135362&r2=135363&view=diff ============================================================================== --- lldb/trunk/source/Core/DataExtractor.cpp (original) +++ lldb/trunk/source/Core/DataExtractor.cpp Sun Jul 17 15:36:25 2011 @@ -1793,6 +1793,7 @@ DataExtractor::DumpHexBytes (Stream *s, const void *src, size_t src_len, + uint32_t bytes_per_line, addr_t base_addr) { DataExtractor data (src, src_len, eByteOrderLittle, 4); @@ -1801,7 +1802,7 @@ eFormatBytes, // Dump as hex bytes 1, // Size of each item is 1 for single bytes src_len, // Number of bytes - 32, // Num bytes per line + bytes_per_line, // Num bytes per line base_addr, // Base address 0, 0); // Bitfield info } Modified: lldb/trunk/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp?rev=135363&r1=135362&r2=135363&view=diff ============================================================================== --- lldb/trunk/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp (original) +++ lldb/trunk/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp Sun Jul 17 15:36:25 2011 @@ -102,7 +102,7 @@ Mutex::Locker locker(m_sequence_mutex); if (SendRequestPacketNoLock(request_packet)) { - if (WaitForPacketWithTimeoutMicroSecondsNoLock (reply_packet, m_packet_timeout)) + if (WaitForPacketWithTimeoutMicroSecondsNoLock (reply_packet, GetPacketTimeoutInMicroSeconds ())) { uint32_t offset = 0; const uint8_t reply_command = reply_packet.GetU8 (&offset); @@ -131,9 +131,11 @@ { PacketStreamType log_strm; - DataExtractor::DumpHexBytes (&log_strm, packet_data, packet_size, 0); + DataExtractor::DumpHexBytes (&log_strm, packet_data, packet_size, UINT32_MAX, LLDB_INVALID_ADDRESS); - log->Printf("request packet: <%u>\n%s", packet_size, log_strm.GetData()); + log->Printf("send kdp-packet: %.*s", + (uint32_t)log_strm.GetSize(), + log_strm.GetData()); } ConnectionStatus status = eConnectionStatusSuccess; @@ -239,7 +241,7 @@ if (log && log->GetVerbose()) { PacketStreamType log_strm; - DataExtractor::DumpHexBytes (&log_strm, src, src_len, 0); + DataExtractor::DumpHexBytes (&log_strm, src, src_len, UINT32_MAX, LLDB_INVALID_ADDRESS); log->Printf ("CommunicationKDP::%s adding %u bytes: %s", __FUNCTION__, (uint32_t)src_len, @@ -292,6 +294,23 @@ // erase the bytes from our communcation buffer "m_bytes" packet.SetData (DataBufferSP (new DataBufferHeap (&m_bytes[0], length))); m_bytes.erase (0, length); + + if (log) + { + PacketStreamType log_strm; + packet.Dump (&log_strm, // Stream to dump to + 0, // Offset into "packet" + eFormatBytes, // Dump as hex bytes + 1, // Size of each item is 1 for single bytes + length, // Number of bytes + UINT32_MAX, // Num bytes per line + LLDB_INVALID_ADDRESS, // Base address + 0, 0); // Bitfield info set to not do anything bitfield related + + log->Printf("recv kdp-packet: %.*s", + (uint32_t)log_strm.GetSize(), + log_strm.GetData()); + } return true; } } @@ -313,22 +332,25 @@ bool -CommunicationKDP::Connect (uint16_t reply_port, - uint16_t exc_port, - const char *greeting) +CommunicationKDP::SendRequestConnect (uint16_t reply_port, + uint16_t exc_port, + const char *greeting) { PacketStreamType request_packet (Stream::eBinary, 4, m_byte_order); if (greeting == NULL) greeting = ""; const CommandType command = eCommandTypeConnect; - // Length is 82 uint16_t and the length of the greeting C string - const uint32_t command_length = 8 + 2 + 2 + ::strlen(greeting); + // Length is 82 uint16_t and the length of the greeting C string with the terminating NULL + const uint32_t command_length = 8 + 2 + 2 + ::strlen(greeting) + 1; const uint32_t request_sequence_id = m_request_sequence_id; MakeRequestPacketHeader (command, request_packet, command_length); - request_packet.PutHex16(reply_port); - request_packet.PutHex16(exc_port); - request_packet.PutCString(greeting); + // Always send connect ports as little endian + request_packet.SetByteOrder (eByteOrderLittle); + request_packet.PutHex16 (reply_port); + request_packet.PutHex16 (exc_port); + request_packet.SetByteOrder (m_byte_order); + request_packet.PutCString (greeting); DataExtractor reply_packet; return SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet); } @@ -345,7 +367,7 @@ } bool -CommunicationKDP::Reattach (uint16_t reply_port) +CommunicationKDP::SendRequestReattach (uint16_t reply_port) { PacketStreamType request_packet (Stream::eBinary, 4, m_byte_order); const CommandType command = eCommandTypeReattach; @@ -353,7 +375,10 @@ const uint32_t command_length = 8 + 2; const uint32_t request_sequence_id = m_request_sequence_id; MakeRequestPacketHeader (command, request_packet, command_length); + // Always send connect ports as little endian + request_packet.SetByteOrder (eByteOrderLittle); request_packet.PutHex16(reply_port); + request_packet.SetByteOrder (m_byte_order); DataExtractor reply_packet; if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet)) { @@ -448,7 +473,7 @@ } bool -CommunicationKDP::Disconnect () +CommunicationKDP::SendRequestDisconnect () { PacketStreamType request_packet (Stream::eBinary, 4, m_byte_order); const CommandType command = eCommandTypeDisconnect; Modified: lldb/trunk/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.h?rev=135363&r1=135362&r2=135363&view=diff ============================================================================== --- lldb/trunk/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.h (original) +++ lldb/trunk/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.h Sun Jul 17 15:36:25 2011 @@ -141,15 +141,15 @@ bool - Connect (uint16_t reply_port, - uint16_t exc_port, - const char *greeting); + SendRequestConnect (uint16_t reply_port, + uint16_t exc_port, + const char *greeting); bool - Reattach (uint16_t reply_port); + SendRequestReattach (uint16_t reply_port); bool - Disconnect (); + SendRequestDisconnect (); uint32_t GetVersion (); Modified: lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp?rev=135363&r1=135362&r2=135363&view=diff ============================================================================== --- lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp (original) +++ lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp Sun Jul 17 15:36:25 2011 @@ -13,6 +13,7 @@ // C++ Includes // Other libraries and framework includes +#include "lldb/Core/ConnectionFileDescriptor.h" #include "lldb/Core/PluginManager.h" #include "lldb/Core/State.h" #include "lldb/Host/Host.h" @@ -53,7 +54,7 @@ } bool -ProcessKDP::CanDebug(Target &target) +ProcessKDP::CanDebug(Target &target, bool plugin_specified_by_name) { // For now we are just making sure the file exists for a given module ModuleSP exe_module_sp(target.GetExecutableModule()); @@ -68,8 +69,10 @@ exe_objfile->GetStrata() == ObjectFile::eStrataKernel) return true; } + return false; } - return false; + // No target executable, assume we can debug if our plug-in was specified by name + return plugin_specified_by_name; } //---------------------------------------------------------------------- @@ -143,7 +146,63 @@ { // TODO: fill in the remote connection to the remote KDP here! Error error; - error.SetErrorString ("attaching to a by process name not supported in kdp-remote plug-in"); + + if (remote_url == NULL || remote_url[0] == '\0') + remote_url = "udp://localhost:41139"; + + std::auto_ptr conn_ap(new ConnectionFileDescriptor()); + if (conn_ap.get()) + { + // Only try once for now. + // TODO: check if we should be retrying? + const uint32_t max_retry_count = 1; + for (uint32_t retry_count = 0; retry_count < max_retry_count; ++retry_count) + { + if (conn_ap->Connect(remote_url, &error) == eConnectionStatusSuccess) + break; + usleep (100000); + } + } + + if (conn_ap->IsConnected()) + { + const uint16_t reply_port = conn_ap->GetReadPort (); + + if (reply_port != 0) + { + m_comm.SetConnection(conn_ap.release()); + + if (m_comm.SendRequestReattach(reply_port)) + { + if (m_comm.SendRequestConnect(reply_port, reply_port, "Greetings from LLDB...")) + { + m_comm.GetVersion(); + uint32_t cpu = m_comm.GetCPUType(); + uint32_t sub = m_comm.GetCPUSubtype(); + ArchSpec kernel_arch; + kernel_arch.SetArchitecture(eArchTypeMachO, cpu, sub); + m_target.SetArchitecture(kernel_arch); + // TODO: thread registers based off of architecture... + } + } + else + { + error.SetErrorString("KDP reattach failed"); + } + } + else + { + error.SetErrorString("invalid reply port from UDP connection"); + } + } + else + { + if (error.Success()) + error.SetErrorStringWithFormat ("failed to connect to '%s'", remote_url); + } + if (error.Fail()) + m_comm.Disconnect(); + return error; } @@ -414,13 +473,19 @@ m_thread_list.DiscardThreadPlans(); - size_t response_size = m_comm.Disconnect (); - if (log) + if (m_comm.IsConnected()) { - if (response_size) - log->PutCString ("ProcessKDP::DoDetach() detach packet sent successfully"); - else - log->PutCString ("ProcessKDP::DoDetach() detach packet send failed"); + + m_comm.SendRequestDisconnect(); + + size_t response_size = m_comm.Disconnect (); + if (log) + { + if (response_size) + log->PutCString ("ProcessKDP::DoDetach() detach packet sent successfully"); + else + log->PutCString ("ProcessKDP::DoDetach() detach packet send failed"); + } } // Sleep for one second to let the process get all detached... StopAsyncThread (); @@ -446,6 +511,8 @@ // Interrupt if our inferior is running... if (m_comm.IsConnected()) { + m_comm.SendRequestDisconnect(); + if (m_public_state.GetValue() == eStateAttaching) { // We are being asked to halt during an attach. We need to just close Modified: lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h?rev=135363&r1=135362&r2=135363&view=diff ============================================================================== --- lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h (original) +++ lldb/trunk/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h Sun Jul 17 15:36:25 2011 @@ -65,7 +65,8 @@ // Check if a given Process //------------------------------------------------------------------ virtual bool - CanDebug (lldb_private::Target &target); + CanDebug (lldb_private::Target &target, + bool plugin_specified_by_name); // virtual uint32_t // ListProcessesMatchingName (const char *name, lldb_private::StringList &matches, std::vector &pids); Modified: lldb/trunk/source/Plugins/Process/MacOSX-User/source/ProcessMacOSX.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/MacOSX-User/source/ProcessMacOSX.cpp?rev=135363&r1=135362&r2=135363&view=diff ============================================================================== --- lldb/trunk/source/Plugins/Process/MacOSX-User/source/ProcessMacOSX.cpp (original) +++ lldb/trunk/source/Plugins/Process/MacOSX-User/source/ProcessMacOSX.cpp Sun Jul 17 15:36:25 2011 @@ -208,7 +208,7 @@ } bool -ProcessMacOSX::CanDebug(Target &target) +ProcessMacOSX::CanDebug(Target &target, bool plugin_specified_by_name) { // For now we are just making sure the file exists for a given module ModuleSP exe_module_sp(target.GetExecutableModule()); Modified: lldb/trunk/source/Plugins/Process/MacOSX-User/source/ProcessMacOSX.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/MacOSX-User/source/ProcessMacOSX.h?rev=135363&r1=135362&r2=135363&view=diff ============================================================================== --- lldb/trunk/source/Plugins/Process/MacOSX-User/source/ProcessMacOSX.h (original) +++ lldb/trunk/source/Plugins/Process/MacOSX-User/source/ProcessMacOSX.h Sun Jul 17 15:36:25 2011 @@ -81,7 +81,8 @@ // Check if a given Process //------------------------------------------------------------------ virtual bool - CanDebug (lldb_private::Target &target); + CanDebug (lldb_private::Target &target, + bool plugin_specified_by_name); //------------------------------------------------------------------ // Creating a new process, or attaching to an existing one Modified: lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp?rev=135363&r1=135362&r2=135363&view=diff ============================================================================== --- lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp (original) +++ lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp Sun Jul 17 15:36:25 2011 @@ -101,7 +101,7 @@ } bool -ProcessGDBRemote::CanDebug(Target &target) +ProcessGDBRemote::CanDebug (Target &target, bool plugin_specified_by_name) { // For now we are just making sure the file exists for a given module ModuleSP exe_module_sp(target.GetExecutableModule()); Modified: lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h?rev=135363&r1=135362&r2=135363&view=diff ============================================================================== --- lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h (original) +++ lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h Sun Jul 17 15:36:25 2011 @@ -66,7 +66,8 @@ // Check if a given Process //------------------------------------------------------------------ virtual bool - CanDebug (lldb_private::Target &target); + CanDebug (lldb_private::Target &target, + bool plugin_specified_by_name); // virtual uint32_t // ListProcessesMatchingName (const char *name, lldb_private::StringList &matches, std::vector &pids); Modified: lldb/trunk/source/Target/Process.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/Process.cpp?rev=135363&r1=135362&r2=135363&view=diff ============================================================================== --- lldb/trunk/source/Target/Process.cpp (original) +++ lldb/trunk/source/Target/Process.cpp Sun Jul 17 15:36:25 2011 @@ -549,7 +549,7 @@ if (create_callback) { std::auto_ptr debugger_ap(create_callback(target, listener)); - if (debugger_ap->CanDebug(target)) + if (debugger_ap->CanDebug(target, true)) return debugger_ap.release(); } } @@ -558,7 +558,7 @@ for (uint32_t idx = 0; (create_callback = PluginManager::GetProcessCreateCallbackAtIndex(idx)) != NULL; ++idx) { std::auto_ptr debugger_ap(create_callback(target, listener)); - if (debugger_ap->CanDebug(target)) + if (debugger_ap->CanDebug(target, false)) return debugger_ap.release(); } } Modified: lldb/trunk/source/lldb.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/lldb.cpp?rev=135363&r1=135362&r2=135363&view=diff ============================================================================== --- lldb/trunk/source/lldb.cpp (original) +++ lldb/trunk/source/lldb.cpp Sun Jul 17 15:36:25 2011 @@ -45,6 +45,7 @@ #include "Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.h" #include "Plugins/ObjectFile/Mach-O/ObjectFileMachO.h" #include "Plugins/Process/MacOSX-User/source/ProcessMacOSX.h" +#include "Plugins/Process/MacOSX-Kernel/ProcessKDP.h" #include "Plugins/Process/gdb-remote/ProcessGDBRemote.h" #include "Plugins/Platform/MacOSX/PlatformMacOSX.h" #include "Plugins/Platform/MacOSX/PlatformRemoteiOS.h" @@ -102,6 +103,7 @@ AppleObjCRuntimeV1::Initialize(); ObjectContainerUniversalMachO::Initialize(); ObjectFileMachO::Initialize(); + ProcessKDP::Initialize(); ProcessGDBRemote::Initialize(); //ProcessMacOSX::Initialize(); SymbolVendorMacOSX::Initialize(); @@ -167,6 +169,7 @@ AppleObjCRuntimeV1::Terminate(); ObjectContainerUniversalMachO::Terminate(); ObjectFileMachO::Terminate(); + ProcessKDP::Terminate(); ProcessGDBRemote::Terminate(); //ProcessMacOSX::Terminate(); SymbolVendorMacOSX::Terminate();