[Ada] Add a symbol lookup cache
[deliverable/binutils-gdb.git] / gdb / ppc-linux-tdep.c
index 0fc6fe03b9c891657a78cfd2d52fd0223ebfd406..6d3b2d8d4aa7e514edd4339a8d5fe616ec683c3f 100644 (file)
@@ -1,6 +1,6 @@
 /* Target-dependent code for GDB, the GNU debugger.
 
-   Copyright (C) 1986-2013 Free Software Foundation, Inc.
+   Copyright (C) 1986-2014 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -44,6 +44,7 @@
 #include "observer.h"
 #include "auxv.h"
 #include "elf/common.h"
+#include "elf/ppc64.h"
 #include "exceptions.h"
 #include "arch-utils.h"
 #include "spu-tdep.h"
@@ -332,7 +333,7 @@ static struct ppc_insn_pattern powerpc32_plt_stub_so[] =
 static int
 powerpc_linux_in_dynsym_resolve_code (CORE_ADDR pc)
 {
-  struct minimal_symbol *sym;
+  struct bound_minimal_symbol sym;
 
   /* Check whether PC is in the dynamic linker.  This also checks
      whether it is in the .plt section, used by non-PIC executables.  */
@@ -341,9 +342,10 @@ powerpc_linux_in_dynsym_resolve_code (CORE_ADDR pc)
 
   /* Check if we are in the resolver.  */
   sym = lookup_minimal_symbol_by_pc (pc);
-  if (sym != NULL
-      && (strcmp (SYMBOL_LINKAGE_NAME (sym), "__glink") == 0
-         || strcmp (SYMBOL_LINKAGE_NAME (sym), "__glink_PLTresolve") == 0))
+  if (sym.minsym != NULL
+      && (strcmp (SYMBOL_LINKAGE_NAME (sym.minsym), "__glink") == 0
+         || strcmp (SYMBOL_LINKAGE_NAME (sym.minsym),
+                    "__glink_PLTresolve") == 0))
     return 1;
 
   return 0;
@@ -354,13 +356,13 @@ powerpc_linux_in_dynsym_resolve_code (CORE_ADDR pc)
 static CORE_ADDR
 ppc_skip_trampoline_code (struct frame_info *frame, CORE_ADDR pc)
 {
-  int insnbuf[POWERPC32_PLT_STUB_LEN];
+  unsigned int insnbuf[POWERPC32_PLT_STUB_LEN];
   struct gdbarch *gdbarch = get_frame_arch (frame);
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
   CORE_ADDR target = 0;
 
-  if (ppc_insns_match_pattern (pc, powerpc32_plt_stub, insnbuf))
+  if (ppc_insns_match_pattern (frame, pc, powerpc32_plt_stub, insnbuf))
     {
       /* Insn pattern is
                lis   r11, xxxx
@@ -372,7 +374,7 @@ ppc_skip_trampoline_code (struct frame_info *frame, CORE_ADDR pc)
       target = read_memory_unsigned_integer (target, 4, byte_order);
     }
 
-  if (ppc_insns_match_pattern (pc, powerpc32_plt_stub_so, insnbuf))
+  if (ppc_insns_match_pattern (frame, pc, powerpc32_plt_stub_so, insnbuf))
     {
       /* Insn pattern is
                lwz   r11, xxxx(r30)
@@ -875,6 +877,55 @@ ppc_linux_core_read_description (struct gdbarch *gdbarch,
     }
 }
 
+
+/* Implementation of `gdbarch_elf_make_msymbol_special', as defined in
+   gdbarch.h.  This implementation is used for the ELFv2 ABI only.  */
+
+static void
+ppc_elfv2_elf_make_msymbol_special (asymbol *sym, struct minimal_symbol *msym)
+{
+  elf_symbol_type *elf_sym = (elf_symbol_type *)sym;
+
+  /* If the symbol is marked as having a local entry point, set a target
+     flag in the msymbol.  We currently only support local entry point
+     offsets of 8 bytes, which is the only entry point offset ever used
+     by current compilers.  If/when other offsets are ever used, we will
+     have to use additional target flag bits to store them.  */
+  switch (PPC64_LOCAL_ENTRY_OFFSET (elf_sym->internal_elf_sym.st_other))
+    {
+    default:
+      break;
+    case 8:
+      MSYMBOL_TARGET_FLAG_1 (msym) = 1;
+      break;
+    }
+}
+
+/* Implementation of `gdbarch_skip_entrypoint', as defined in
+   gdbarch.h.  This implementation is used for the ELFv2 ABI only.  */
+
+static CORE_ADDR
+ppc_elfv2_skip_entrypoint (struct gdbarch *gdbarch, CORE_ADDR pc)
+{
+  struct bound_minimal_symbol fun;
+  int local_entry_offset = 0;
+
+  fun = lookup_minimal_symbol_by_pc (pc);
+  if (fun.minsym == NULL)
+    return pc;
+
+  /* See ppc_elfv2_elf_make_msymbol_special for how local entry point
+     offset values are encoded.  */
+  if (MSYMBOL_TARGET_FLAG_1 (fun.minsym))
+    local_entry_offset = 8;
+
+  if (SYMBOL_VALUE_ADDRESS (fun.minsym) <= pc
+      && pc < SYMBOL_VALUE_ADDRESS (fun.minsym) + local_entry_offset)
+    return SYMBOL_VALUE_ADDRESS (fun.minsym) + local_entry_offset;
+
+  return pc;
+}
+
 /* Implementation of `gdbarch_stap_is_single_operand', as defined in
    gdbarch.h.  */
 
@@ -1244,6 +1295,11 @@ ppc_linux_init_abi (struct gdbarch_info info,
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
   struct tdesc_arch_data *tdesc_data = (void *) info.tdep_info;
+  static const char *const stap_integer_prefixes[] = { "i", NULL };
+  static const char *const stap_register_indirection_prefixes[] = { "(",
+                                                                   NULL };
+  static const char *const stap_register_indirection_suffixes[] = { ")",
+                                                                   NULL };
 
   linux_init_abi (info, gdbarch);
 
@@ -1262,9 +1318,11 @@ ppc_linux_init_abi (struct gdbarch_info info,
   set_gdbarch_get_syscall_number (gdbarch, ppc_linux_get_syscall_number);
 
   /* SystemTap functions.  */
-  set_gdbarch_stap_integer_prefix (gdbarch, "i");
-  set_gdbarch_stap_register_indirection_prefix (gdbarch, "(");
-  set_gdbarch_stap_register_indirection_suffix (gdbarch, ")");
+  set_gdbarch_stap_integer_prefixes (gdbarch, stap_integer_prefixes);
+  set_gdbarch_stap_register_indirection_prefixes (gdbarch,
+                                         stap_register_indirection_prefixes);
+  set_gdbarch_stap_register_indirection_suffixes (gdbarch,
+                                         stap_register_indirection_suffixes);
   set_gdbarch_stap_gdb_register_prefix (gdbarch, "r");
   set_gdbarch_stap_is_single_operand (gdbarch, ppc_stap_is_single_operand);
   set_gdbarch_stap_parse_special_token (gdbarch,
@@ -1331,13 +1389,23 @@ ppc_linux_init_abi (struct gdbarch_info info,
   
   if (tdep->wordsize == 8)
     {
-      /* Handle PPC GNU/Linux 64-bit function pointers (which are really
-        function descriptors).  */
-      set_gdbarch_convert_from_func_ptr_addr
-       (gdbarch, ppc64_convert_from_func_ptr_addr);
+      if (tdep->elf_abi == POWERPC_ELF_V1)
+       {
+         /* Handle PPC GNU/Linux 64-bit function pointers (which are really
+            function descriptors).  */
+         set_gdbarch_convert_from_func_ptr_addr
+           (gdbarch, ppc64_convert_from_func_ptr_addr);
+
+         set_gdbarch_elf_make_msymbol_special
+           (gdbarch, ppc64_elf_make_msymbol_special);
+       }
+      else
+       {
+         set_gdbarch_elf_make_msymbol_special
+           (gdbarch, ppc_elfv2_elf_make_msymbol_special);
 
-      set_gdbarch_elf_make_msymbol_special (gdbarch,
-                                           ppc64_elf_make_msymbol_special);
+         set_gdbarch_skip_entrypoint (gdbarch, ppc_elfv2_skip_entrypoint);
+       }
 
       /* Shared library handling.  */
       set_gdbarch_skip_trampoline_code (gdbarch, ppc64_skip_trampoline_code);
This page took 0.027155 seconds and 4 git commands to generate.