Index: lldb/packages/Python/lldbsuite/test/functionalities/optimized_code/Makefile =================================================================== --- /dev/null +++ lldb/packages/Python/lldbsuite/test/functionalities/optimized_code/Makefile @@ -0,0 +1,3 @@ +CXX_SOURCES := main.cpp +CXXFLAGS_EXTRAS := -O2 +include Makefile.rules Index: lldb/packages/Python/lldbsuite/test/functionalities/optimized_code/TestNoASanExceptionAfterEvalOP_piece.py =================================================================== --- /dev/null +++ lldb/packages/Python/lldbsuite/test/functionalities/optimized_code/TestNoASanExceptionAfterEvalOP_piece.py @@ -0,0 +1,4 @@ +from lldbsuite.test import lldbinline +from lldbsuite.test import decorators + +lldbinline.MakeInlineTest(__file__, globals()) Index: lldb/packages/Python/lldbsuite/test/functionalities/optimized_code/main.cpp =================================================================== --- /dev/null +++ lldb/packages/Python/lldbsuite/test/functionalities/optimized_code/main.cpp @@ -0,0 +1,31 @@ +// This is a regression test that checks whether lldb can inspect the variables +// in this program without triggering an ASan exception. + +__attribute__((noinline, optnone)) int use(int x) { return x; } + +volatile int sink; + +struct S1 { + int f1; + int *f2; +}; + +struct S2 { + char a, b; + int pad; + S2(int x) { + a = x & 0xff; + b = x & 0xff00; + } +}; + +int main() { + S1 v1; + v1.f1 = sink; + v1.f2 = nullptr; + sink++; //% self.expect("frame variable v1", substrs=["S1"]) + S2 v2(v1.f1); + sink += use(v2.a); //% self.expect("frame variable v2", substrs=["S2"]) + sink += use(v2.pad); //% self.expect("frame variable v2", substrs=["S2"]) + return 0; +} Index: lldb/source/Core/Value.cpp =================================================================== --- lldb/source/Core/Value.cpp +++ lldb/source/Core/Value.cpp @@ -533,13 +533,24 @@ uint8_t *dst = const_cast(data.PeekData(0, byte_size)); if (dst != nullptr) { if (address_type == eAddressTypeHost) { + // Don't read more of the Value than what the host has been able to + // actually evaluate. The buffer size may be less than the size prescribed + // by the type. E.g. this can happen when an expression containing + // DW_OP_piece doesn't describe the whole object. + byte_size = GetBuffer().GetByteSize(); + // The address is an address in this process, so just copy it. if (address == 0) { error.SetErrorStringWithFormat( "trying to read from host address of 0."); return error; } - memcpy(dst, reinterpret_cast(address), byte_size); + + // Only copy if we have something to copy: otherwise, we still want to + // return a buffer of the appropriate size. Note that we ought to find a + // way to represent undefined bits and use that instead of printing 0's. + if (byte_size) + memcpy(dst, reinterpret_cast(address), byte_size); } else if ((address_type == eAddressTypeLoad) || (address_type == eAddressTypeFile)) { if (file_so_addr.IsValid()) { Index: lldb/test/Shell/SymbolFile/DWARF/DW_OP_piece-smaller-than-struct.s =================================================================== --- /dev/null +++ lldb/test/Shell/SymbolFile/DWARF/DW_OP_piece-smaller-than-struct.s @@ -0,0 +1,110 @@ +# RUN: llvm-mc -filetype=obj -o %t -triple x86_64-pc-linux %s +# RUN: %lldb %t -o "target variable reset" -b | FileCheck %s + +# CHECK: (lldb) target variable reset +# CHECK: (auto_reset) reset = { +# CHECK: ptr = 0x{{0+$}} +# Note: We need to find some way to represent "prev" as unknown/undefined. +# CHECK: prev = false +# CHECK: } + + .section .debug_abbrev,"",@progbits + .byte 1 # Abbreviation Code + .byte 17 # DW_TAG_compile_unit + .byte 1 # DW_CHILDREN_yes + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 2 # Abbreviation Code + .byte 52 # DW_TAG_variable + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 8 # DW_FORM_string + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 2 # DW_AT_location + .byte 24 # DW_FORM_exprloc + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 3 # Abbreviation Code + .byte 36 # DW_TAG_base_type + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 8 # DW_FORM_string + .byte 62 # DW_AT_encoding + .byte 11 # DW_FORM_data1 + .byte 11 # DW_AT_byte_size + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 4 # Abbreviation Code + .byte 19 # DW_TAG_structure_type + .byte 1 # DW_CHILDREN_yes + .byte 3 # DW_AT_name + .byte 8 # DW_FORM_string + .byte 11 # DW_AT_byte_size + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 5 # Abbreviation Code + .byte 13 # DW_TAG_member + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 8 # DW_FORM_string + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 56 # DW_AT_data_member_location + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 6 # Abbreviation Code + .byte 15 # DW_TAG_pointer_type + .byte 0 # DW_CHILDREN_no + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 0 # EOM(3) + + .section .debug_info,"",@progbits +.Lcu_begin0: + .long .Lcu_end-.Lcu_start # Length of Unit +.Lcu_start: + .short 4 # DWARF version number + .long .debug_abbrev # Offset Into Abbrev. Section + .byte 8 # Address Size (in bytes) + .byte 1 # Abbrev [1] 0xb:0x6c DW_TAG_compile_unit +.Lbool: + .byte 3 # Abbrev [3] 0x33:0x7 DW_TAG_base_type + .asciz "bool" # DW_AT_name + .byte 2 # DW_AT_encoding + .byte 1 # DW_AT_byte_size + .byte 2 # Abbrev [2] 0x3a:0x15 DW_TAG_variable + .asciz "reset" # DW_AT_name + .long .Lstruct # DW_AT_type + .byte 2f-1f # DW_AT_location +1: + .byte 0xe # DW_OP_constu + .quad 0xdeadbeefbaadf00d + .byte 0x9f # DW_OP_stack_value + .byte 0x93 # DW_OP_piece + .uleb128 8 + # Note: Only the first 8 bytes of the struct are described. +2: +.Lstruct: + .byte 4 # Abbrev [4] 0x4f:0x22 DW_TAG_structure_type + .asciz "auto_reset" # DW_AT_name + .byte 16 # DW_AT_byte_size + .byte 5 # Abbrev [5] 0x58:0xc DW_TAG_member + .asciz "ptr" # DW_AT_name + .long .Lbool_ptr # DW_AT_type + .byte 0 # DW_AT_data_member_location + .byte 5 # Abbrev [5] 0x64:0xc DW_TAG_member + .asciz "prev" # DW_AT_name + .long .Lbool # DW_AT_type + .byte 8 # DW_AT_data_member_location + .byte 0 # End Of Children Mark +.Lbool_ptr: + .byte 6 # Abbrev [6] 0x71:0x5 DW_TAG_pointer_type + .long .Lbool # DW_AT_type + .byte 0 # End Of Children Mark +.Lcu_end: