Fix crash with DW_FORM_implicit_const
[binutils-gdb.git] / gdb / ppc-linux-tdep.c
index ed154fd4a637e60250640a113f032ef1695ea05e..784dafa59dbf31f79e409e4ec037560f107c1922 100644 (file)
@@ -1,6 +1,6 @@
 /* Target-dependent code for GDB, the GNU debugger.
 
-   Copyright (C) 1986-2022 Free Software Foundation, Inc.
+   Copyright (C) 1986-2023 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -62,6 +62,7 @@
 #include "user-regs.h"
 #include <ctype.h>
 #include "elf-bfd.h"
+#include "producer.h"
 
 #include "features/rs6000/powerpc-32l.c"
 #include "features/rs6000/powerpc-altivec32l.c"
@@ -249,11 +250,18 @@ ppc_linux_memory_remove_breakpoint (struct gdbarch *gdbarch,
 static enum return_value_convention
 ppc_linux_return_value (struct gdbarch *gdbarch, struct value *function,
                        struct type *valtype, struct regcache *regcache,
-                       gdb_byte *readbuf, const gdb_byte *writebuf)
+                       struct value **read_value, const gdb_byte *writebuf)
 {  
+  gdb_byte *readbuf = nullptr;
+  if (read_value != nullptr)
+    {
+      *read_value = value::allocate (valtype);
+      readbuf = (*read_value)->contents_raw ().data ();
+    }
+
   if ((valtype->code () == TYPE_CODE_STRUCT
        || valtype->code () == TYPE_CODE_UNION)
-      && !((TYPE_LENGTH (valtype) == 16 || TYPE_LENGTH (valtype) == 8)
+      && !((valtype->length () == 16 || valtype->length () == 8)
           && valtype->is_vector ()))
     return RETURN_VALUE_STRUCT_CONVENTION;
   else
@@ -328,7 +336,7 @@ powerpc_linux_in_dynsym_resolve_code (CORE_ADDR pc)
    stub sequence.  */
 
 static CORE_ADDR
-ppc_skip_trampoline_code (struct frame_info *frame, CORE_ADDR pc)
+ppc_skip_trampoline_code (frame_info_ptr frame, CORE_ADDR pc)
 {
   unsigned int insnbuf[POWERPC32_PLT_CHECK_LEN];
   struct gdbarch *gdbarch = get_frame_arch (frame);
@@ -1159,7 +1167,7 @@ ppc_linux_iterate_over_regset_sections (struct gdbarch *gdbarch,
 }
 
 static void
-ppc_linux_sigtramp_cache (struct frame_info *this_frame,
+ppc_linux_sigtramp_cache (frame_info_ptr this_frame,
                          struct trad_frame_cache *this_cache,
                          CORE_ADDR func, LONGEST offset,
                          int bias)
@@ -1231,7 +1239,7 @@ ppc_linux_sigtramp_cache (struct frame_info *this_frame,
 
 static void
 ppc32_linux_sigaction_cache_init (const struct tramp_frame *self,
-                                 struct frame_info *this_frame,
+                                 frame_info_ptr this_frame,
                                  struct trad_frame_cache *this_cache,
                                  CORE_ADDR func)
 {
@@ -1243,7 +1251,7 @@ ppc32_linux_sigaction_cache_init (const struct tramp_frame *self,
 
 static void
 ppc64_linux_sigaction_cache_init (const struct tramp_frame *self,
-                                 struct frame_info *this_frame,
+                                 frame_info_ptr this_frame,
                                  struct trad_frame_cache *this_cache,
                                  CORE_ADDR func)
 {
@@ -1255,7 +1263,7 @@ ppc64_linux_sigaction_cache_init (const struct tramp_frame *self,
 
 static void
 ppc32_linux_sighandler_cache_init (const struct tramp_frame *self,
-                                  struct frame_info *this_frame,
+                                  frame_info_ptr this_frame,
                                   struct trad_frame_cache *this_cache,
                                   CORE_ADDR func)
 {
@@ -1267,7 +1275,7 @@ ppc32_linux_sighandler_cache_init (const struct tramp_frame *self,
 
 static void
 ppc64_linux_sighandler_cache_init (const struct tramp_frame *self,
-                                  struct frame_info *this_frame,
+                                  frame_info_ptr this_frame,
                                   struct trad_frame_cache *this_cache,
                                   CORE_ADDR func)
 {
@@ -1400,6 +1408,8 @@ ppc_canonicalize_syscall (int syscall, int wordsize)
       else
        result = gdb_sys_fstatat64;
     }
+  else if (syscall == 317)
+    result = gdb_sys_pipe2;
   else if (syscall == 336)
     result = gdb_sys_recv;
   else if (syscall == 337)
@@ -1599,7 +1609,8 @@ ppc_linux_core_read_description (struct gdbarch *gdbarch,
   if (vsx)
     features.vsx = true;
 
-  CORE_ADDR hwcap = linux_get_hwcap (target);
+  gdb::optional<gdb::byte_vector> auxv = target_read_auxv_raw (target);
+  CORE_ADDR hwcap = linux_get_hwcap (auxv, target, gdbarch);
 
   features.isa205 = ppc_linux_has_isa205 (hwcap);
 
@@ -1629,6 +1640,11 @@ ppc_linux_core_read_description (struct gdbarch *gdbarch,
 static void
 ppc_elfv2_elf_make_msymbol_special (asymbol *sym, struct minimal_symbol *msym)
 {
+  if ((sym->flags & BSF_SYNTHETIC) != 0)
+    /* ELFv2 synthetic symbols (the PLT stubs and the __glink_PLTresolve
+       trampoline) do not have a local entry point.  */
+    return;
+
   elf_symbol_type *elf_sym = (elf_symbol_type *)sym;
 
   /* If the symbol is marked as having a local entry point, set a target
@@ -1887,7 +1903,7 @@ ppc_init_linux_record_tdep (struct linux_record_tdep *record_tdep,
       record_tdep->size_time_t = 4;
     }
   else
-    internal_error (__FILE__, __LINE__, _("unexpected wordsize"));
+    internal_error (_("unexpected wordsize"));
 
   /* These values are the second argument of system call "sys_fcntl"
      and "sys_fcntl64".  They are obtained from Linux Kernel source.  */
@@ -1991,6 +2007,38 @@ ppc_floatformat_for_type (struct gdbarch *gdbarch,
   return default_floatformat_for_type (gdbarch, name, len);
 }
 
+static bool
+linux_dwarf2_omit_typedef_p (struct type *target_type,
+                            const char *producer, const char *name)
+{
+  int gcc_major, gcc_minor;
+
+  if (producer_is_gcc (producer, &gcc_major, &gcc_minor))
+    {
+      if ((target_type->code () == TYPE_CODE_FLT
+          || target_type->code () == TYPE_CODE_COMPLEX)
+         && (strcmp (name, "long double") == 0
+             || strcmp (name, "complex long double") == 0))
+       {
+         /* IEEE 128-bit floating point and IBM long double are two
+            encodings for 128-bit values.  The DWARF debug data can't
+            distinguish between them.  See bugzilla:
+            https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104194
+
+            A GCC hack was introduced to still allow the debugger to identify
+            the case where "long double" uses the IEEE 128-bit floating point
+            format: GCC will emit a bogus DWARF type record pretending that
+            "long double" is a typedef alias for the _Float128 type.
+
+            This hack should not be visible to the GDB user, so we replace
+            this bogus typedef by a normal floating-point type, copying the
+            format information from the target type of the bogus typedef.  */
+         return true;
+       }
+    }
+  return false;
+}
+
 /* Specify the powerpc64le target triplet.
    This can be variations of
        ppc64le-{distro}-linux-gcc
@@ -2068,6 +2116,9 @@ ppc_linux_init_abi (struct gdbarch_info info,
   /* Support for floating-point data type variants.  */
   set_gdbarch_floatformat_for_type (gdbarch, ppc_floatformat_for_type);
 
+  /* Support for replacing typedef record.  */
+  set_gdbarch_dwarf2_omit_typedef_p (gdbarch, linux_dwarf2_omit_typedef_p);
+
   /* Handle inferior calls during interrupted system calls.  */
   set_gdbarch_write_pc (gdbarch, ppc_linux_write_pc);
 
@@ -2094,7 +2145,8 @@ ppc_linux_init_abi (struct gdbarch_info info,
         (well ignoring vectors that is).  When this was corrected, it
         wasn't fixed for GNU/Linux native platform.  Use the
         PowerOpen struct convention.  */
-      set_gdbarch_return_value (gdbarch, ppc_linux_return_value);
+      set_gdbarch_return_value_as_value (gdbarch, ppc_linux_return_value);
+      set_gdbarch_return_value (gdbarch, nullptr);
 
       set_gdbarch_memory_remove_breakpoint (gdbarch,
                                            ppc_linux_memory_remove_breakpoint);