I hit this while debugging GDB itself. I don't have a small reproducer at the moment, but I have a self-contained easy reproducer using the GDB binary and a core file of it I created. It's a bit too big to attach here so I'll post a link in a follow-up comment. Steps to reproduce: 1. Extract the archive to /tmp/repro 2. Compile GDB with AddressSanitizer 2. Run: $ ./gdb -q -nx --data-directory=data-directory -iex "set sysroot /tmp/repro" /tmp/repro/gdb /tmp/repro/core.3164744 -ex 'p current_inferior_.m_obj.thread_list.m_front.priv' -batch The error I get: ==2087857==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60200009b10f at pc 0x7f7575b843a7 bp 0x7fffbac99b10 sp 0x7fffbac992b8 READ of size 1 at 0x60200009b10f thread T0 #0 0x7f7575b843a6 in __interceptor_memcpy ../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:827 #1 0x124aa6c in memcpy /usr/include/x86_64-linux-gnu/bits/string_fortified.h:34 #2 0x124aa6c in value_contents_copy_raw /home/smarchi/src/binutils-gdb/gdb/value.c:1332 #3 0x1251b95 in value_primitive_field(value*, long, int, type*) /home/smarchi/src/binutils-gdb/gdb/value.c:3096 #4 0x7f4c87 in cp_print_value_fields(value*, ui_file*, int, value_print_options const*, type**, int) /home/smarchi/src/binutils-gdb/gdb/cp-valprint.c:333 #5 0x7f5f75 in cp_print_value /home/smarchi/src/binutils-gdb/gdb/cp-valprint.c:513 #6 0x7f5f75 in cp_print_value_fields(value*, ui_file*, int, value_print_options const*, type**, int) /home/smarchi/src/binutils-gdb/gdb/cp-valprint.c:159 #7 0x7f5f75 in cp_print_value /home/smarchi/src/binutils-gdb/gdb/cp-valprint.c:513 #8 0x7f5f75 in cp_print_value_fields(value*, ui_file*, int, value_print_options const*, type**, int) /home/smarchi/src/binutils-gdb/gdb/cp-valprint.c:159 #9 0x7f5f75 in cp_print_value /home/smarchi/src/binutils-gdb/gdb/cp-valprint.c:513 #10 0x7f5f75 in cp_print_value_fields(value*, ui_file*, int, value_print_options const*, type**, int) /home/smarchi/src/binutils-gdb/gdb/cp-valprint.c:159 #11 0x6faa66 in c_value_print_struct /home/smarchi/src/binutils-gdb/gdb/c-valprint.c:383 #12 0x6faa66 in c_value_print_inner(value*, ui_file*, int, value_print_options const*) /home/smarchi/src/binutils-gdb/gdb/c-valprint.c:438 #13 0x1235c77 in do_val_print /home/smarchi/src/binutils-gdb/gdb/valprint.c:1046 #14 0x7f4cea in cp_print_value_fields(value*, ui_file*, int, value_print_options const*, type**, int) /home/smarchi/src/binutils-gdb/gdb/cp-valprint.c:335 #15 0x7f5f75 in cp_print_value /home/smarchi/src/binutils-gdb/gdb/cp-valprint.c:513 #16 0x7f5f75 in cp_print_value_fields(value*, ui_file*, int, value_print_options const*, type**, int) /home/smarchi/src/binutils-gdb/gdb/cp-valprint.c:159 #17 0x6faa66 in c_value_print_struct /home/smarchi/src/binutils-gdb/gdb/c-valprint.c:383 #18 0x6faa66 in c_value_print_inner(value*, ui_file*, int, value_print_options const*) /home/smarchi/src/binutils-gdb/gdb/c-valprint.c:438 #19 0x1235c77 in do_val_print /home/smarchi/src/binutils-gdb/gdb/valprint.c:1046 #20 0x7f4cea in cp_print_value_fields(value*, ui_file*, int, value_print_options const*, type**, int) /home/smarchi/src/binutils-gdb/gdb/cp-valprint.c:335 #21 0x6faa66 in c_value_print_struct /home/smarchi/src/binutils-gdb/gdb/c-valprint.c:383 #22 0x6faa66 in c_value_print_inner(value*, ui_file*, int, value_print_options const*) /home/smarchi/src/binutils-gdb/gdb/c-valprint.c:438 #23 0x1235c77 in do_val_print /home/smarchi/src/binutils-gdb/gdb/valprint.c:1046 #24 0x6fb4d5 in c_value_print(value*, ui_file*, value_print_options const*) /home/smarchi/src/binutils-gdb/gdb/c-valprint.c:587 #25 0x1236a37 in value_print(value*, ui_file*, value_print_options const*) /home/smarchi/src/binutils-gdb/gdb/valprint.c:1187 #26 0xd7eafe in print_value(value*, value_print_options const&) /home/smarchi/src/binutils-gdb/gdb/printcmd.c:1258 #27 0xd7f00f in print_command_1 /home/smarchi/src/binutils-gdb/gdb/printcmd.c:1344 #28 0x72ad29 in cmd_func(cmd_list_element*, char const*, int) /home/smarchi/src/binutils-gdb/gdb/cli/cli-decode.c:2160 #29 0x10e7464 in execute_command(char const*, int) /home/smarchi/src/binutils-gdb/gdb/top.c:674 #30 0xc4af30 in catch_command_errors /home/smarchi/src/binutils-gdb/gdb/main.c:523 #31 0xc4b204 in execute_cmdargs /home/smarchi/src/binutils-gdb/gdb/main.c:618 #32 0xc503af in captured_main_1 /home/smarchi/src/binutils-gdb/gdb/main.c:1322 #33 0xc5153b in captured_main /home/smarchi/src/binutils-gdb/gdb/main.c:1343 #34 0xc5153b in gdb_main(captured_main_args*) /home/smarchi/src/binutils-gdb/gdb/main.c:1368 #35 0x487ffd in main /home/smarchi/src/binutils-gdb/gdb/gdb.c:32 #36 0x7f7574bac0b2 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x270b2) #37 0x4acdfd in _start (/home/smarchi/build/binutils-gdb-opt/gdb/gdb+0x4acdfd) 0x60200009b10f is located 1 bytes to the left of 8-byte region [0x60200009b110,0x60200009b118) allocated by thread T0 here: #0 0x7f7575bfee17 in __interceptor_calloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:154 #1 0x56b0a0 in xcalloc /home/smarchi/src/binutils-gdb/gdb/alloc.c:100
The archive: https://files.efficios.com/s/ReLYZCHKen7jkBs
For the record: - libstdc++.so comes from Arch Linux package gcc-libs 11.1.0-1 - libc-2.33.so comes from Arch Linux package glibc 2.33-5 libstdc++.so contains debug info.
And the gcc version: $ gcc --version gcc (GCC) 11.1.0 If we look at the value_primitive_field frame, I see: (top-gdb) p offset $5 = -1 which comes from: (top-gdb) p arg_type.main_type.name $6 = 0x621001a80ae0 "std::_Head_base<1, std::default_delete<private_thread_info>, true>" (top-gdb) p arg_type.main_type.flds_bnds.fields[0].loc.bitpos $7 = -8 And indeed, in the DWARF, in the gdb file, I have: 0x000cbdf5: DW_TAG_member DW_AT_name [DW_FORM_strp] ("_M_head_impl") DW_AT_decl_file [DW_FORM_implicit_const] ("/usr/include/c++/11.1.0/tuple") DW_AT_decl_line [DW_FORM_implicit_const] (125) DW_AT_decl_column [DW_FORM_implicit_const] (39) DW_AT_type [DW_FORM_ref4] (0x000cbaff "default_delete<private_thread_info>") DW_AT_data_member_location [DW_FORM_implicit_const] (-1) I don't know if the DW_AT_data_member_location value of -1 is right or not.
Here's a simpler reproducer: --- #include <memory> int main() { std::unique_ptr<int> p(new int); return 0; } --- $ g++ --version g++ (GCC) 11.1.0 $ g++ -g3 -O0 test.cpp $ readelf --debug-dump a.out ... <3><968>: Abbrev Number: 79 (DW_TAG_member) <969> DW_AT_name : (strp) (offset: 0xc42a): _M_head_impl <96d> DW_AT_decl_file : (data1) 4 <96e> DW_AT_decl_line : (data1) 125 <96f> DW_AT_decl_column : (data1) 39 <970> DW_AT_type : (ref4) <0x67e>, default_delete<int> <974> DW_AT_data_member_location: (sdata) -1 ... $ ./gdb -q -nx --data-directory=data-directory ./a.out -ex "b 5" -ex r -ex "p p" <ASan crash like above>
File gcc bug: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101378 The question now (if this is confirmed to be a gcc bug) is how do we do handle this bad debug info. When getting a negative DW_AT_data_member_location, do we just ignore the field, as if it didn't exist? Do we add it, but with an unknown location (a new FIELD_LOC_KIND_UNKNOWN)? So far I have only seen this bug manifest when using std::unique_ptr (the reproducer above), and the DW_AT_data_member_location should have always been 0 instead of -1. So we could have a special case to detect DW_AT_data_member_location, and make it 0 instead. But I don't know if it will always be right.