Bug 21559

Summary: ../../gdb/regcache.c:1087: internal-error: void regcache_raw_supply(regcache, int, const void): Assertion `regnum >= 0 && regnum < regcache->descr->nr_raw_registers' failed.
Product: gdb Reporter: Andrew Paprocki <andrew>
Component: gdbAssignee: Not yet assigned to anyone <unassigned>
Status: RESOLVED FIXED    
Severity: critical CC: eldar.abusalimov, jeremip11, pedro
Priority: P2    
Version: 8.0   
Target Milestone: 8.1   
Host: Target:
Build: Last reconfirmed:

Description Andrew Paprocki 2017-06-08 22:47:07 UTC
Running gdb 8.0 on a RHEL6 VM:

$ uname -a
Linux hostname 2.6.32-504.38.1.el6.x86_64 #1 SMP Sun Oct 4 13:43:08 EDT 2015 x86_64 x86_64 x86_64 GNU/Linux

Produced the following output:

../../gdb/regcache.c:1087: internal-error: void regcache_raw_supply(regcache, int, const void): Assertion `regnum >= 0 && regnum < regcache->descr->nr_raw_registers' failed.
A problem internal to GDB has been detected,
further debugging may prove unreliable.
Quit this debugging session? (y or n) [answered Y; input not from terminal]

Dumping the stack from the core file produces:

(gdb) where
#0  0x0000003fc3e32625 in raise () from /lib64/libc.so.6
#1  0x0000003fc3e33e05 in abort () from /lib64/libc.so.6
#2  0x000000000078267e in dump_core() ()
#3  0x0000000000782af7 in internal_vproblem(internal_problem*, char const*, int, char const*, __va_list_tag*) ()
#4  0x0000000000782b6f in internal_verror(char const*, int, char const*, __va_list_tag*) ()
#5  0x0000000000641e26 in internal_error(char const*, int, char const*, ...) ()
#6  0x0000000000712883 in regcache_raw_supply(regcache*, int, void const*) ()
#7  0x000000000046c6f8 in amd64_linux_fetch_inferior_registers(target_ops*, regcache*, int) ()
#8  0x0000000000754802 in delegate_fetch_registers(target_ops*, regcache*, int) ()
#9  0x0000000000768aa8 in target_fetch_registers(regcache*, int) ()
#10 0x0000000000479622 in ps_lgetregs ()
#11 0x00007f1f6252fb58 in __td_ta_lookup_th_unique () from /lib64/libthread_db.so.1
#12 0x00007f1f6252fd8a in td_ta_map_lwp2thr () from /lib64/libthread_db.so.1
#13 0x0000000000479c7c in thread_from_lwp(ptid_t) ()
#14 0x000000000047a4b1 in try_thread_db_load_1(thread_db_info*) ()
#15 0x000000000047a7df in try_thread_db_load(char const*, int) ()
#16 0x000000000047aab1 in try_thread_db_load_from_sdir() ()
#17 0x000000000047acbf in thread_db_load_search() ()
#18 0x000000000047ae41 in thread_db_load() ()
#19 0x000000000047af72 in check_for_thread_db() ()
#20 0x000000000047b007 in thread_db_new_objfile(objfile*) ()
#21 0x00000000006e2434 in observer_new_objfile_notification_stub(void const*, void const*) ()
#22 0x00000000006e1802 in generic_observer_notify(observer_list*, void const*) ()
#23 0x00000000006e24c7 in observer_notify_new_objfile(objfile*) ()
#24 0x000000000073c478 in symbol_file_add_with_addrs(bfd*, char const*, enum_flags<symfile_add_flag>, section_addr_info*, enum_flags<objfile_flag>, objfile*) ()
#25 0x000000000073c61e in symbol_file_add_from_bfd(bfd*, char const*, enum_flags<symfile_add_flag>, section_addr_info*, enum_flags<objfile_flag>, objfile*)
    ()
#26 0x0000000000721c66 in solib_read_symbols(so_list*, enum_flags<symfile_add_flag>) ()
#27 0x0000000000722490 in solib_add(char const*, int, int) ()
#28 0x0000000000458a77 in enable_break(svr4_info*, int) ()
#29 0x000000000045a655 in svr4_solib_create_inferior_hook(int) ()
#30 0x0000000000722e70 in solib_create_inferior_hook(int) ()
#31 0x000000000068e11e in post_create_inferior(target_ops*, int) ()
#32 0x00000000006920a0 in setup_inferior(int) ()
#33 0x00000000006920e6 in attach_post_wait(char const*, int, attach_post_wait_mode) ()
#34 0x00000000006922af in attach_command_continuation(void*, int) ()
#35 0x00000000005d4556 in do_my_continuations_1(continuation**, int) ()
#36 0x00000000005d45e1 in do_my_continuations(continuation**, int) ()
#37 0x00000000005d46d9 in do_all_inferior_continuations(int) ()
#38 0x000000000068b4a5 in inferior_event_handler(inferior_event_type, void*) ()
#39 0x000000000069be0e in fetch_inferior_event(void*) ()
#40 0x000000000068b43f in inferior_event_handler(inferior_event_type, void*) ()
#41 0x00000000006a653e in infrun_async_inferior_event_handler(void*) ()
#42 0x000000000064c4e3 in check_async_event_handlers() ()
#43 0x000000000064ae53 in gdb_do_one_event() ()
#44 0x000000000064aefa in start_event_loop() ()
#45 0x00000000006c1cbb in captured_command_loop(void*) ()
#46 0x000000000064e9ef in catch_errors(int (*)(void*), void*, char const*, return_mask) ()
#47 0x00000000006c30d0 in captured_main(void*) ()
#48 0x00000000006c30f9 in gdb_main(captured_main_args*) ()
#49 0x000000000040a817 in main ()

(gdb) up
#6  0x0000000000712883 in regcache_raw_supply(regcache*, int, void const*) ()
(gdb) info registers
rax            0x0      0
rbx            0x2a648  173640
rcx            0xffffffffffffffff       -1
rdx            0x6      6
rsi            0x2a8ed  174317
rdi            0x2a8ed  174317
rbp            0x7ffe49d38630   0x7ffe49d38630
rsp            0x7ffe49d38600   0x7ffe49d38600
r8             0xffffffff       4294967295
r9             0x7f1f63a70700   139772792604416
r10            0x8      8
r11            0x206    518
r12            0x7ffe49d39720   140730137024288
r13            0x7ffe49d39500   140730137023744
r14            0x0      0
r15            0x0      0
rip            0x712883 0x712883 <regcache_raw_supply(regcache*, int, void const*)+135>
eflags         0x206    [ PF IF ]
cs             0x33     51
ss             0x2b     43
ds             0x0      0
es             0x0      0
fs             0x0      0
gs             0x0      0
Comment 1 Andrew Paprocki 2017-06-08 22:59:04 UTC
The bug appears to be here:

#ifndef HAVE_STRUCT_USER_REGS_STRUCT_FS_BASE
      {
        /* PTRACE_ARCH_PRCTL is obsolete since 2.6.25, where the
           fs_base and gs_base fields of user_regs_struct can be
           used directly.  */
        unsigned long base;

        if (regnum == -1 || regnum == AMD64_FSBASE_REGNUM)
          {
            if (ptrace (PTRACE_ARCH_PRCTL, tid, &base, ARCH_GET_FS) < 0)
              perror_with_name (_("Couldn't get segment register fs_base"));

            regcache_raw_supply (regcache, AMD64_FSBASE_REGNUM, &base);
          }

        if (regnum == -1 || regnum == AMD64_GSBASE_REGNUM)
          {
            if (ptrace (PTRACE_ARCH_PRCTL, tid, &base, ARCH_GET_GS) < 0)
              perror_with_name (_("Couldn't get segment register gs_base"));

            regcache_raw_supply (regcache, AMD64_GSBASE_REGNUM, &base);
          }
      }
#endif


This code must be getting hit because the binary was built on a RHEL5 system with 2.6.18 kernel.

The reg cache does not allow the pseudo registers into the cache:

  /* Construct a strictly RAW register cache.  Don't allow pseudo's
     into the register cache.  */
  descr->nr_raw_registers = gdbarch_num_regs (gdbarch);
  descr->sizeof_raw_register_status = gdbarch_num_regs (gdbarch);
Comment 3 Andrew Paprocki 2017-06-09 01:48:58 UTC
It should be noted that modifying `configure` to force on `HAVE_STRUCT_USER_REGS_STRUCT_FS_BASE` and `HAVE_STRUCT_USER_REGS_STRUCT_GS_BASE` fixes this issue. For some reason the `configure` tests for `fs_base` and `gs_base` fail even though `sys/user.h` on RHEL5 has the fields defined in `user_regs_struct`.
Comment 4 Sourceware Commits 2018-01-17 13:11:23 UTC
The master branch has been updated by Pedro Alves <palves@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=f517c1805ac50c64c2dbb086c16b3bcf33b15a89

commit f517c1805ac50c64c2dbb086c16b3bcf33b15a89
Author: Eldar Abusalimov <eldar.abusalimov@jetbrains.com>
Date:   Mon Jan 15 16:57:42 2018 +0300

    configure: Fix test for fs_base/gs_base in <sys/user.h>
    
    Make <sys/types.h> be included prior to including <sys/user.h>.
    
    glibc versions older than 2.14 use __uintNN_t types within certain
    structures defined in <sys/user.h> probably assuming these types are
    defined prior to including the header. This results in the following
    `configure` feature test compilation error that makes it think that
    `struct user_regs_struct` doesn't have `fs_base`/`gs_base` fields,
    althouh it does.
    
        configure:13617: checking for struct user_regs_struct.fs_base
        configure:13617: gcc -c -g -O2 -I/linux/include conftest.c >&5
        In file included from conftest.c:158:0:
        /usr/include/sys/user.h:32:3: error: unknown type name '__uint16_t'
           __uint16_t  cwd;
           ^
        /usr/include/sys/user.h:33:3: error: unknown type name '__uint16_t'
           __uint16_t  swd;
           ^
        /usr/include/sys/user.h:34:3: error: unknown type name '__uint16_t'
           __uint16_t  ftw;
           ^
        /usr/include/sys/user.h:35:3: error: unknown type name '__uint16_t'
           __uint16_t  fop;
           ^
        /usr/include/sys/user.h:36:3: error: unknown type name '__uint64_t'
           __uint64_t  rip;
           ^
        /usr/include/sys/user.h:37:3: error: unknown type name '__uint64_t'
           __uint64_t  rdp;
           ^
        /usr/include/sys/user.h:38:3: error: unknown type name '__uint32_t'
           __uint32_t  mxcsr;
           ^
        /usr/include/sys/user.h:39:3: error: unknown type name '__uint32_t'
           __uint32_t  mxcr_mask;
           ^
        /usr/include/sys/user.h:40:3: error: unknown type name '__uint32_t'
           __uint32_t  st_space[32];   /* 8*16 bytes for each FP-reg = 128 bytes */
           ^
        /usr/include/sys/user.h:41:3: error: unknown type name '__uint32_t'
           __uint32_t  xmm_space[64];  /* 16*16 bytes for each XMM-reg = 256 bytes */
           ^
        /usr/include/sys/user.h:42:3: error: unknown type name '__uint32_t'
           __uint32_t  padding[24];
           ^
        configure:13617: $? = 1
        configure: failed program was:
        | /* confdefs.h */
        ...
        | /* end confdefs.h.  */
        | #include <sys/user.h>
        |
        | int
        | main ()
        | {
        | static struct user_regs_struct ac_aggr;
        | if (ac_aggr.fs_base)
        | return 0;
        |   ;
        |   return 0;
        | }
    
    Recent glibc versions don't use typedef'ed int types in <sys/user.h>,
    thus allowing it to be included as is
    (glibc commit d79a9c949c84e7f0ba33e87447c47af833e9f11a).
    However there're still some distros alive that use older glibc,
    for instance, RHEL/CentOS 6 package glibc 2.12.
    
    Also affects PR gdb/21559:
    
        ../../gdb/regcache.c:1087: internal-error: void regcache_raw_supply(regcache, int, const void): Assertion `regnum >= 0 && regnum < regcache->descr->nr_raw_registers' failed.
    
    As noted by Andrew Paprocki, who submitted the PR
    (https://sourceware.org/bugzilla/show_bug.cgi?id=21559#c3):
    
        > It should be noted that modifying `configure` to force on
        > `HAVE_STRUCT_USER_REGS_STRUCT_FS_BASE` and
        > `HAVE_STRUCT_USER_REGS_STRUCT_GS_BASE` fixes this issue. For some
        > reason the `configure` tests for `fs_base` and `gs_base` fail
        > even though `sys/user.h` on RHEL5 has the fields defined in
        > `user_regs_struct`.
    
    Note that this patch does NOT fix the root cause of PR gdb/21559,
    although now that `configure` properly detects the presence of the
    fields and sets HAVE_XXX accordingly, the execution takes another
    path, which doesn't lead to the assertion failure in question.
    
    gdb/ChangeLog:
    2018-01-17  Eldar Abusalimov  <eldar.abusalimov@jetbrains.com>
    
    	PR gdb/21559
    	* configure.ac: Include <sys/types.h> prior to <sys/user.h> when
    	checking for fs_base/gs_base fields in struct user_regs_struct.
    	* configure: Regenerate.
    
    gdb/gdbserver/ChangeLog:
    2018-01-17  Eldar Abusalimov  <eldar.abusalimov@jetbrains.com>
    
    	PR gdb/21559
    	* configure.ac: Include <sys/types.h> prior to <sys/user.h> when
    	checking for fs_base/gs_base fields in struct user_regs_struct.
    	* configure: Regenerate.
Comment 5 Sourceware Commits 2018-01-17 13:14:00 UTC
The gdb-8.1-branch branch has been updated by Pedro Alves <palves@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=6949085e3eaef536b2c76252452ec3e63e9f112c

commit 6949085e3eaef536b2c76252452ec3e63e9f112c
Author: Eldar Abusalimov <eldar.abusalimov@jetbrains.com>
Date:   Wed Jan 17 13:13:15 2018 +0000

    configure: Fix test for fs_base/gs_base in <sys/user.h>
    
    Make <sys/types.h> be included prior to including <sys/user.h>.
    
    glibc versions older than 2.14 use __uintNN_t types within certain
    structures defined in <sys/user.h> probably assuming these types are
    defined prior to including the header. This results in the following
    `configure` feature test compilation error that makes it think that
    `struct user_regs_struct` doesn't have `fs_base`/`gs_base` fields,
    althouh it does.
    
        configure:13617: checking for struct user_regs_struct.fs_base
        configure:13617: gcc -c -g -O2 -I/linux/include conftest.c >&5
        In file included from conftest.c:158:0:
        /usr/include/sys/user.h:32:3: error: unknown type name '__uint16_t'
           __uint16_t  cwd;
           ^
        /usr/include/sys/user.h:33:3: error: unknown type name '__uint16_t'
           __uint16_t  swd;
           ^
        /usr/include/sys/user.h:34:3: error: unknown type name '__uint16_t'
           __uint16_t  ftw;
           ^
        /usr/include/sys/user.h:35:3: error: unknown type name '__uint16_t'
           __uint16_t  fop;
           ^
        /usr/include/sys/user.h:36:3: error: unknown type name '__uint64_t'
           __uint64_t  rip;
           ^
        /usr/include/sys/user.h:37:3: error: unknown type name '__uint64_t'
           __uint64_t  rdp;
           ^
        /usr/include/sys/user.h:38:3: error: unknown type name '__uint32_t'
           __uint32_t  mxcsr;
           ^
        /usr/include/sys/user.h:39:3: error: unknown type name '__uint32_t'
           __uint32_t  mxcr_mask;
           ^
        /usr/include/sys/user.h:40:3: error: unknown type name '__uint32_t'
           __uint32_t  st_space[32];   /* 8*16 bytes for each FP-reg = 128 bytes */
           ^
        /usr/include/sys/user.h:41:3: error: unknown type name '__uint32_t'
           __uint32_t  xmm_space[64];  /* 16*16 bytes for each XMM-reg = 256 bytes */
           ^
        /usr/include/sys/user.h:42:3: error: unknown type name '__uint32_t'
           __uint32_t  padding[24];
           ^
        configure:13617: $? = 1
        configure: failed program was:
        | /* confdefs.h */
        ...
        | /* end confdefs.h.  */
        | #include <sys/user.h>
        |
        | int
        | main ()
        | {
        | static struct user_regs_struct ac_aggr;
        | if (ac_aggr.fs_base)
        | return 0;
        |   ;
        |   return 0;
        | }
    
    Recent glibc versions don't use typedef'ed int types in <sys/user.h>,
    thus allowing it to be included as is
    (glibc commit d79a9c949c84e7f0ba33e87447c47af833e9f11a).
    However there're still some distros alive that use older glibc,
    for instance, RHEL/CentOS 6 package glibc 2.12.
    
    Also affects PR gdb/21559:
    
        ../../gdb/regcache.c:1087: internal-error: void regcache_raw_supply(regcache, int, const void): Assertion `regnum >= 0 && regnum < regcache->descr->nr_raw_registers' failed.
    
    As noted by Andrew Paprocki, who submitted the PR
    (https://sourceware.org/bugzilla/show_bug.cgi?id=21559#c3):
    
        > It should be noted that modifying `configure` to force on
        > `HAVE_STRUCT_USER_REGS_STRUCT_FS_BASE` and
        > `HAVE_STRUCT_USER_REGS_STRUCT_GS_BASE` fixes this issue. For some
        > reason the `configure` tests for `fs_base` and `gs_base` fail
        > even though `sys/user.h` on RHEL5 has the fields defined in
        > `user_regs_struct`.
    
    Note that this patch does NOT fix the root cause of PR gdb/21559,
    although now that `configure` properly detects the presence of the
    fields and sets HAVE_XXX accordingly, the execution takes another
    path, which doesn't lead to the assertion failure in question.
    
    gdb/ChangeLog:
    2018-01-17  Eldar Abusalimov  <eldar.abusalimov@jetbrains.com>
    
    	PR gdb/21559
    	* configure.ac: Include <sys/types.h> prior to <sys/user.h> when
    	checking for fs_base/gs_base fields in struct user_regs_struct.
    	* configure: Regenerate.
    
    gdb/gdbserver/ChangeLog:
    2018-01-17  Eldar Abusalimov  <eldar.abusalimov@jetbrains.com>
    
    	PR gdb/21559
    	* configure.ac: Include <sys/types.h> prior to <sys/user.h> when
    	checking for fs_base/gs_base fields in struct user_regs_struct.
    	* configure: Regenerate.
Comment 6 Pedro Alves 2018-01-17 13:17:36 UTC
Fix merged.  Thanks.
Comment 7 Eldar Abusalimov 2018-01-17 16:38:17 UTC
(In reply to Pedro Alves from comment #6)
> Fix merged.  Thanks.

Pedro, I'm not sure we should actually close this ticket. The merged patch makes the issue go away indeed, however it doesn't fix the root cause of the assertion failure, I'm afraid.

> Note that this patch does NOT fix the root cause of PR gdb/21559,
> although now that `configure` properly detects the presence of the
> fields and sets HAVE_XXX accordingly, the execution takes another
> path, which doesn't lead to the assertion failure in question.