Index: lldb/source/Expression/DWARFExpression.cpp =================================================================== --- lldb/source/Expression/DWARFExpression.cpp +++ lldb/source/Expression/DWARFExpression.cpp @@ -952,9 +952,59 @@ !is_signed)); }; + enum LocationDescriptionKind { Empty, Memory, Register, Implicit, Composite }; + LocationDescriptionKind dwarf4_location_description_kind = Empty; + auto classifyLocationDescription = [&](uint8_t op) { + switch (op) { + case DW_OP_reg0: + case DW_OP_reg1: + case DW_OP_reg2: + case DW_OP_reg3: + case DW_OP_reg4: + case DW_OP_reg5: + case DW_OP_reg6: + case DW_OP_reg7: + case DW_OP_reg8: + case DW_OP_reg9: + case DW_OP_reg10: + case DW_OP_reg11: + case DW_OP_reg12: + case DW_OP_reg13: + case DW_OP_reg14: + case DW_OP_reg15: + case DW_OP_reg16: + case DW_OP_reg17: + case DW_OP_reg18: + case DW_OP_reg19: + case DW_OP_reg20: + case DW_OP_reg21: + case DW_OP_reg22: + case DW_OP_reg23: + case DW_OP_reg24: + case DW_OP_reg25: + case DW_OP_reg26: + case DW_OP_reg27: + case DW_OP_reg28: + case DW_OP_reg29: + case DW_OP_reg30: + case DW_OP_reg31: + case DW_OP_regx: + dwarf4_location_description_kind = Register; + break; + case DW_OP_implicit_value: + case DW_OP_stack_value: + case DW_OP_implicit_pointer: + dwarf4_location_description_kind = Implicit; + break; + default: + dwarf4_location_description_kind = Memory; + } + }; + while (opcodes.ValidOffset(offset)) { const lldb::offset_t op_offset = offset; const uint8_t op = opcodes.GetU8(&offset); + classifyLocationDescription(op); if (log && log->GetVerbose()) { size_t count = stack.size(); @@ -2567,25 +2617,57 @@ // or DW_OP_bit_piece opcodes if (pieces.GetBuffer().GetByteSize()) { result = pieces; - } else { - if (error_ptr) - error_ptr->SetErrorString("Stack empty after evaluation."); - return false; + return true; } - } else { - if (log && log->GetVerbose()) { - size_t count = stack.size(); - LLDB_LOGF(log, "Stack after operation has %" PRIu64 " values:", - (uint64_t)count); - for (size_t i = 0; i < count; ++i) { - StreamString new_value; - new_value.Printf("[%" PRIu64 "]", (uint64_t)i); - stack[i].Dump(&new_value); - LLDB_LOGF(log, " %s", new_value.GetData()); - } + if (error_ptr) + error_ptr->SetErrorString("Stack empty after evaluation."); + return false; + } + + // Note that this function is conflating DWARF expressions with + // DWARF location descriptions. Perhaps it would be better to define + // a wrapper for DWARFExpresssion::Eval() that deals with DWARF + // location descriptions (which consist of one or more DWARF + // expressions). But doing this would mean we'd also need factor the + // handling of DW_OP_(bit_)piece out of this function. + if (dwarf_cu && dwarf_cu->GetVersion() >= 4) { + const char *log_msg = "DWARF location description kind: %s"; + switch (dwarf4_location_description_kind) { + case Empty: // FIXME: This would be suspicious. Add some error handling. + LLDB_LOGF(log, log_msg, "Empty"); + break; + case Memory: + LLDB_LOGF(log, log_msg, "Memory"); + if (stack.back().GetValueType() == Value::ValueType::Scalar) + stack.back().SetValueType(Value::ValueType::LoadAddress); + break; + case Register: + LLDB_LOGF(log, log_msg, "Register"); + stack.back().SetValueType(Value::ValueType::Scalar); + break; + case Implicit: + LLDB_LOGF(log, log_msg, "Implicit"); + if (stack.back().GetValueType() == Value::ValueType::LoadAddress) + stack.back().SetValueType(Value::ValueType::Scalar); + break; + case Composite: + LLDB_LOGF(log, log_msg, "Composite"); + break; + } + } + + if (log && log->GetVerbose()) { + size_t count = stack.size(); + LLDB_LOGF(log, + "Stack after operation has %" PRIu64 " values:", (uint64_t)count); + for (size_t i = 0; i < count; ++i) { + StreamString new_value; + new_value.Printf("[%" PRIu64 "]", (uint64_t)i); + stack[i].Dump(&new_value); + LLDB_LOGF(log, " %s", new_value.GetData()); } - result = stack.back(); } + result = stack.back(); return true; // Return true on success } Index: lldb/unittests/Expression/DWARFExpressionTest.cpp =================================================================== --- lldb/unittests/Expression/DWARFExpressionTest.cpp +++ lldb/unittests/Expression/DWARFExpressionTest.cpp @@ -213,42 +213,45 @@ // // Leave as is. - EXPECT_THAT_EXPECTED(t.Eval({DW_OP_const4u, 0x11, 0x22, 0x33, 0x44, // - DW_OP_convert, offs_uint32_t}), - llvm::HasValue(GetScalar(64, 0x44332211, not_signed))); + EXPECT_THAT_EXPECTED( + t.Eval({DW_OP_const4u, 0x11, 0x22, 0x33, 0x44, // + DW_OP_convert, offs_uint32_t, DW_OP_stack_value}), + llvm::HasValue(GetScalar(64, 0x44332211, not_signed))); // Zero-extend to 64 bits. - EXPECT_THAT_EXPECTED(t.Eval({DW_OP_const4u, 0x11, 0x22, 0x33, 0x44, // - DW_OP_convert, offs_uint64_t}), - llvm::HasValue(GetScalar(64, 0x44332211, not_signed))); + EXPECT_THAT_EXPECTED( + t.Eval({DW_OP_const4u, 0x11, 0x22, 0x33, 0x44, // + DW_OP_convert, offs_uint64_t, DW_OP_stack_value}), + llvm::HasValue(GetScalar(64, 0x44332211, not_signed))); // Sign-extend to 64 bits. EXPECT_THAT_EXPECTED( t.Eval({DW_OP_const4s, 0xcc, 0xdd, 0xee, 0xff, // - DW_OP_convert, offs_sint64_t}), + DW_OP_convert, offs_sint64_t, DW_OP_stack_value}), llvm::HasValue(GetScalar(64, 0xffffffffffeeddcc, is_signed))); // Sign-extend, then truncate. - EXPECT_THAT_EXPECTED(t.Eval({DW_OP_const4s, 0xcc, 0xdd, 0xee, 0xff, // - DW_OP_convert, offs_sint64_t, // - DW_OP_convert, offs_uint32_t}), - llvm::HasValue(GetScalar(32, 0xffeeddcc, not_signed))); + EXPECT_THAT_EXPECTED( + t.Eval({DW_OP_const4s, 0xcc, 0xdd, 0xee, 0xff, // + DW_OP_convert, offs_sint64_t, // + DW_OP_convert, offs_uint32_t, DW_OP_stack_value}), + llvm::HasValue(GetScalar(32, 0xffeeddcc, not_signed))); // Truncate to default unspecified (pointer-sized) type. EXPECT_THAT_EXPECTED(t.Eval({DW_OP_const4s, 0xcc, 0xdd, 0xee, 0xff, // DW_OP_convert, offs_sint64_t, // - DW_OP_convert, 0x00}), + DW_OP_convert, 0x00, DW_OP_stack_value}), llvm::HasValue(GetScalar(32, 0xffeeddcc, not_signed))); // Truncate to 8 bits. - EXPECT_THAT_EXPECTED( - t.Eval({DW_OP_const4s, 'A', 'B', 'C', 'D', DW_OP_convert, offs_uchar}), - llvm::HasValue(GetScalar(8, 'A', not_signed))); + EXPECT_THAT_EXPECTED(t.Eval({DW_OP_const4s, 'A', 'B', 'C', 'D', DW_OP_convert, + offs_uchar, DW_OP_stack_value}), + llvm::HasValue(GetScalar(8, 'A', not_signed))); // Also truncate to 8 bits. - EXPECT_THAT_EXPECTED( - t.Eval({DW_OP_const4s, 'A', 'B', 'C', 'D', DW_OP_convert, offs_schar}), - llvm::HasValue(GetScalar(8, 'A', is_signed))); + EXPECT_THAT_EXPECTED(t.Eval({DW_OP_const4s, 'A', 'B', 'C', 'D', DW_OP_convert, + offs_schar, DW_OP_stack_value}), + llvm::HasValue(GetScalar(8, 'A', is_signed))); // // Errors. @@ -354,4 +357,13 @@ // Evaluate returns LLDB_INVALID_ADDRESS for all load addresses. EXPECT_THAT_EXPECTED(Evaluate({DW_OP_lit4, DW_OP_deref}, {}, {}, &exe_ctx), llvm::HasValue(Scalar(LLDB_INVALID_ADDRESS))); + // Memory location: *(*0x4). + // Evaluate returns LLDB_INVALID_ADDRESS for all load addresses. + EXPECT_THAT_EXPECTED(Evaluate({DW_OP_lit4}, {}, {}, &exe_ctx), + llvm::HasValue(Scalar(4))); + // Memory location: *(*0x4). + // Evaluate returns LLDB_INVALID_ADDRESS for all load addresses. + EXPECT_THAT_EXPECTED( + Evaluate({DW_OP_lit4, DW_OP_deref, DW_OP_stack_value}, {}, {}, &exe_ctx), + llvm::HasValue(GetScalar(32, 0x07060504, false))); }