werat created this revision. werat added reviewers: labath, jingham, jasonmolenda. Herald added a project: All. werat requested review of this revision. Herald added a project: LLDB. Herald added a subscriber: lldb-commits.
DW_OP_skip/DW_OP_bra can move offset to the end of the data, which means that this was the last instruction to execute and the interpreter should terminate. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D130285 Files: lldb/source/Expression/DWARFExpression.cpp lldb/unittests/Expression/DWARFExpressionTest.cpp Index: lldb/unittests/Expression/DWARFExpressionTest.cpp =================================================================== --- lldb/unittests/Expression/DWARFExpressionTest.cpp +++ lldb/unittests/Expression/DWARFExpressionTest.cpp @@ -131,6 +131,25 @@ llvm::HasValue(0xffff010101010101)); } +TEST(DWARFExpression, DW_OP_skip) { + EXPECT_THAT_EXPECTED(Evaluate({DW_OP_const1u, 0x42, DW_OP_skip, 0x02, 0x00, + DW_OP_const1u, 0xff}), + llvm::HasValue(0x42)); +} + +TEST(DWARFExpression, DW_OP_bra) { + EXPECT_THAT_EXPECTED( + // clang-format off + Evaluate({ + DW_OP_const1u, 0x42, // push 0x42 + DW_OP_const1u, 0x1, // push 0x1 + DW_OP_bra, 0x02, 0x00, // if 0x1 > 0, then skip 0x0002 opcodes + DW_OP_const1u, 0xff, // push 0xff + }), + // clang-format on + llvm::HasValue(0x42)); +} + TEST(DWARFExpression, DW_OP_convert) { /// Auxiliary debug info. const char *yamldata = R"( Index: lldb/source/Expression/DWARFExpression.cpp =================================================================== --- lldb/source/Expression/DWARFExpression.cpp +++ lldb/source/Expression/DWARFExpression.cpp @@ -1655,11 +1655,16 @@ case DW_OP_skip: { int16_t skip_offset = (int16_t)opcodes.GetU16(&offset); lldb::offset_t new_offset = offset + skip_offset; - if (opcodes.ValidOffset(new_offset)) + // New offset can point at the end of the data, in this case we should + // terminate the DWARF expression evaluation (will happen in the loop + // condition). + if (new_offset <= opcodes.GetByteSize()) offset = new_offset; else { if (error_ptr) - error_ptr->SetErrorString("Invalid opcode offset in DW_OP_skip."); + error_ptr->SetErrorStringWithFormatv( + "Invalid opcode offset in DW_OP_skip: {0}+({1}) > {2}", offset, + skip_offset, opcodes.GetByteSize()); return false; } } break; @@ -1684,11 +1689,16 @@ Scalar zero(0); if (tmp.ResolveValue(exe_ctx) != zero) { lldb::offset_t new_offset = offset + bra_offset; - if (opcodes.ValidOffset(new_offset)) + // New offset can point at the end of the data, in this case we should + // terminate the DWARF expression evaluation (will happen in the loop + // condition). + if (new_offset <= opcodes.GetByteSize()) offset = new_offset; else { if (error_ptr) - error_ptr->SetErrorString("Invalid opcode offset in DW_OP_bra."); + error_ptr->SetErrorStringWithFormatv( + "Invalid opcode offset in DW_OP_bra: {0}+({1}) > {2}", offset, + bra_offset, opcodes.GetByteSize()); return false; } }
Index: lldb/unittests/Expression/DWARFExpressionTest.cpp =================================================================== --- lldb/unittests/Expression/DWARFExpressionTest.cpp +++ lldb/unittests/Expression/DWARFExpressionTest.cpp @@ -131,6 +131,25 @@ llvm::HasValue(0xffff010101010101)); } +TEST(DWARFExpression, DW_OP_skip) { + EXPECT_THAT_EXPECTED(Evaluate({DW_OP_const1u, 0x42, DW_OP_skip, 0x02, 0x00, + DW_OP_const1u, 0xff}), + llvm::HasValue(0x42)); +} + +TEST(DWARFExpression, DW_OP_bra) { + EXPECT_THAT_EXPECTED( + // clang-format off + Evaluate({ + DW_OP_const1u, 0x42, // push 0x42 + DW_OP_const1u, 0x1, // push 0x1 + DW_OP_bra, 0x02, 0x00, // if 0x1 > 0, then skip 0x0002 opcodes + DW_OP_const1u, 0xff, // push 0xff + }), + // clang-format on + llvm::HasValue(0x42)); +} + TEST(DWARFExpression, DW_OP_convert) { /// Auxiliary debug info. const char *yamldata = R"( Index: lldb/source/Expression/DWARFExpression.cpp =================================================================== --- lldb/source/Expression/DWARFExpression.cpp +++ lldb/source/Expression/DWARFExpression.cpp @@ -1655,11 +1655,16 @@ case DW_OP_skip: { int16_t skip_offset = (int16_t)opcodes.GetU16(&offset); lldb::offset_t new_offset = offset + skip_offset; - if (opcodes.ValidOffset(new_offset)) + // New offset can point at the end of the data, in this case we should + // terminate the DWARF expression evaluation (will happen in the loop + // condition). + if (new_offset <= opcodes.GetByteSize()) offset = new_offset; else { if (error_ptr) - error_ptr->SetErrorString("Invalid opcode offset in DW_OP_skip."); + error_ptr->SetErrorStringWithFormatv( + "Invalid opcode offset in DW_OP_skip: {0}+({1}) > {2}", offset, + skip_offset, opcodes.GetByteSize()); return false; } } break; @@ -1684,11 +1689,16 @@ Scalar zero(0); if (tmp.ResolveValue(exe_ctx) != zero) { lldb::offset_t new_offset = offset + bra_offset; - if (opcodes.ValidOffset(new_offset)) + // New offset can point at the end of the data, in this case we should + // terminate the DWARF expression evaluation (will happen in the loop + // condition). + if (new_offset <= opcodes.GetByteSize()) offset = new_offset; else { if (error_ptr) - error_ptr->SetErrorString("Invalid opcode offset in DW_OP_bra."); + error_ptr->SetErrorStringWithFormatv( + "Invalid opcode offset in DW_OP_bra: {0}+({1}) > {2}", offset, + bra_offset, opcodes.GetByteSize()); return false; } }
_______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits