Bug 27891 - maintenance selftest fail when an executable is loaded
Summary: maintenance selftest fail when an executable is loaded
Status: RESOLVED FIXED
Alias: None
Product: gdb
Classification: Unclassified
Component: gdb (show other bugs)
Version: HEAD
: P2 normal
Target Milestone: 12.1
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2021-05-20 13:21 UTC by Andrew Burgess
Modified: 2021-09-13 19:45 UTC (History)
3 users (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:
Project(s) to access:
ssh public key:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Andrew Burgess 2021-05-20 13:21:05 UTC
I built GDB with --enable-targets=all, and am running on an x86-64 GNU/Linux host.  If I start GDB and load an executable (for example GDB itself), and then run 'maint selftest', I see 1 failure.

In contrast, if I start GDB and don't load an executable, I see 0 failures.

Here's the error(s) that I see:

 Running selftest print_one_insn.
 Self test failed: arch arm: self-test failed at ../../src/gdb/disasm-selftests.c:165
 Self test failed: arch armv2: self-test failed at ../../src/gdb/disasm-selftests.c:165
 Self test failed: arch armv2a: self-test failed at ../../src/gdb/disasm-selftests.c:165
 Self test failed: arch armv3: self-test failed at ../../src/gdb/disasm-selftests.c:165
 Self test failed: arch armv3m: self-test failed at ../../src/gdb/disasm-selftests.c:165
 Self test failed: arch armv4: self-test failed at ../../src/gdb/disasm-selftests.c:165
 Self test failed: arch armv4t: self-test failed at ../../src/gdb/disasm-selftests.c:165
 Self test failed: arch armv5: self-test failed at ../../src/gdb/disasm-selftests.c:165
 Self test failed: arch armv5t: self-test failed at ../../src/gdb/disasm-selftests.c:165
 Self test failed: arch armv5te: self-test failed at ../../src/gdb/disasm-selftests.c:165
 Self test failed: arch xscale: self-test failed at ../../src/gdb/disasm-selftests.c:165
 Self test failed: arch ep9312: self-test failed at ../../src/gdb/disasm-selftests.c:165
 Self test failed: arch iwmmxt: self-test failed at ../../src/gdb/disasm-selftests.c:165
 Self test failed: arch iwmmxt2: self-test failed at ../../src/gdb/disasm-selftests.c:165
 Self test failed: arch armv5tej: self-test failed at ../../src/gdb/disasm-selftests.c:165
 Self test failed: arch armv6: self-test failed at ../../src/gdb/disasm-selftests.c:165
 Self test failed: arch armv6kz: self-test failed at ../../src/gdb/disasm-selftests.c:165
 Self test failed: arch armv6t2: self-test failed at ../../src/gdb/disasm-selftests.c:165
 Self test failed: arch armv6k: self-test failed at ../../src/gdb/disasm-selftests.c:165
 Self test failed: arch armv7: self-test failed at ../../src/gdb/disasm-selftests.c:165
 Self test failed: arch armv6-m: self-test failed at ../../src/gdb/disasm-selftests.c:165
 Self test failed: arch armv6s-m: self-test failed at ../../src/gdb/disasm-selftests.c:165
 Self test failed: arch armv7e-m: self-test failed at ../../src/gdb/disasm-selftests.c:165
 Self test failed: arch armv8-a: self-test failed at ../../src/gdb/disasm-selftests.c:165
 Self test failed: arch armv8-r: self-test failed at ../../src/gdb/disasm-selftests.c:165
 Self test failed: arch armv8-m.base: self-test failed at ../../src/gdb/disasm-selftests.c:165
 Self test failed: arch armv8-m.main: self-test failed at ../../src/gdb/disasm-selftests.c:165
 Self test failed: arch armv8.1-m.main: self-test failed at ../../src/gdb/disasm-selftests.c:165
 Self test failed: arch arm_any: self-test failed at ../../src/gdb/disasm-selftests.c:165
 warning: A handler for the OS ABI "GNU/Linux" is not built into this configuration
 of GDB.  Attempting to continue with the default cris:common_v10_v32 settings.
 
 Self test failed: self-test failed at ../../src/gdb/selftest-arch.c:85

I had a quick look and it appears that the ARM disassembler gets into a state where it thinks it is disassembling in thumb mode.  When there is no executable loaded this is not the case.
Comment 1 Tom de Vries 2021-09-13 10:32:12 UTC
(In reply to Andrew Burgess from comment #0)
>  Self test failed: arch armv8.1-m.main: self-test failed at
> ../../src/gdb/disasm-selftests.c:165

The first error I run into is this one, and I've debugged it.

1. With exec.

In gdb_print_insn_arm, we run into this and set info->flags |= USER_SPECIFIED_MACHINE_TYPE:
...
  /* GDB is able to get bfd_mach from the exe_bfd, info->mach is                              
     accurate, so mark USER_SPECIFIED_MACHINE_TYPE bit.  Otherwise,                           
     opcodes/arm-dis.c:print_insn reset info->mach, and it will trigger                       
     the assert on the mismatch of info->mach and                                             
     bfd_get_mach (current_program_space->exec_bfd ()) in                                     
     default_print_insn.  */
  if (current_program_space->exec_bfd () != NULL)
    info->flags |= USER_SPECIFIED_MACHINE_TYPE;
...
and consequently we don't do this in print_insn:
...
      if ((info->flags & USER_SPECIFIED_MACHINE_TYPE) == 0)
          info->mach = bfd_mach_arm_unknown;
...
so we end up doing this in select_arm_features:
...
    case bfd_mach_arm_8_1M_MAIN:
      ARM_SET_FEATURES (ARM_ARCH_V8_1M_MAIN);
      arm_feature_set mve_all
        = ARM_FEATURE_CORE_HIGH (ARM_EXT2_MVE | ARM_EXT2_MVE_FP);
      ARM_MERGE_FEATURE_SETS (arch_fset, arch_fset, mve_all);
      force_thumb = 1;
      break;
...

With force_thumb set, we disassemble only two bytes, and the selftest fails.

2. Without exec.

- in gdb_print_insn_arm, we don't set
  info->flags |= USER_SPECIFIED_MACHINE_TYPE.
- in print_insn, we do bfd_mach_arm_unknown
- in select_arm_features, we don't set force_thumb

Without force_thumb set, we disassemble four bytes, and the selftest passes.
Comment 2 Tom de Vries 2021-09-13 11:23:23 UTC
(In reply to Tom de Vries from comment #1)
>   if (current_program_space->exec_bfd () != NULL)
>     info->flags |= USER_SPECIFIED_MACHINE_TYPE;
> ...

This seems incorrect, given that exec arch can be different from the disassembly arch.

This fixes that:
...
diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c
index e4e7aec4e1c..ab6999ae209 100644
--- a/gdb/arm-tdep.c
+++ b/gdb/arm-tdep.c
@@ -7727,7 +7727,9 @@ gdb_print_insn_arm (bfd_vma memaddr, disassemble_info *info)
      the assert on the mismatch of info->mach and
      bfd_get_mach (current_program_space->exec_bfd ()) in
      default_print_insn.  */
-  if (current_program_space->exec_bfd () != NULL)
+  if (current_program_space->exec_bfd () != NULL
+      && (current_program_space->exec_bfd ()->arch_info
+         == gdbarch_bfd_arch_info (gdbarch)))
     info->flags |= USER_SPECIFIED_MACHINE_TYPE;
 
   return default_print_insn (memaddr, info);
...
and consequently the unit test passes for me (not building with --all-targets though) with and without exec.
Comment 3 Luis Machado 2021-09-13 12:14:08 UTC
Looks OK with the usual NULL -> nullptr fixed.

Thanks for the patch.
Comment 4 Tom de Vries 2021-09-13 19:43:32 UTC
(In reply to Luis Machado from comment #3)
> Looks OK with the usual NULL -> nullptr fixed.
> 
> Thanks for the patch.

Oops, I forgot to update that before committing.  Oh well...
Comment 5 Luis Machado 2021-09-13 19:45:55 UTC
Not a big deal. I'm sure we'll revisit these constants again in the future.