OSDN Git Service

* config/ia64/fde-glibc.c: Require glibc 2.2.4+ headers.
authorjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 9 Aug 2001 16:22:23 +0000 (16:22 +0000)
committerjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 9 Aug 2001 16:22:23 +0000 (16:22 +0000)
(find_fde_for_dso): Remove.
(_Unwind_IteratePhdrCallback): New.
(_Unwind_FindTableEntry): Use dl_iterate_phdr.
* config/ia64/crtbegin.asm (__ia64_app_header): Remove.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@44742 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/ia64/crtbegin.asm
gcc/config/ia64/fde-glibc.c

index 9fb9dfe..e27d76c 100644 (file)
@@ -1,3 +1,11 @@
+2001-08-09  Jakub Jelinek  <jakub@redhat.com>
+
+       * config/ia64/fde-glibc.c: Require glibc 2.2.4+ headers.
+       (find_fde_for_dso): Remove.
+       (_Unwind_IteratePhdrCallback): New.
+       (_Unwind_FindTableEntry): Use dl_iterate_phdr.
+       * config/ia64/crtbegin.asm (__ia64_app_header): Remove.
+
 Thu Aug  9 11:30:20 2001  Richard Kenner  <kenner@vlsi1.ultra.nyu.edu>
 
        * expr.c (emit_single_push_insn): Only exists ifdef PUSH_ROUNDING.
index 1568337..ac2f86b 100644 (file)
@@ -32,14 +32,6 @@ __DTOR_LIST__:
 dtor_ptr:
        data8   __DTOR_LIST__# + 8
 
-#ifndef SHARED
-       .type __ia64_app_header#,@object
-       .size __ia64_app_header#,8
-       .global __ia64_app_header
-__ia64_app_header:
-       data8   @segrel(.Lsegrel_ref#)
-#endif
-
        /* A handle for __cxa_finalize to manage c++ local destructors.  */
        .global __dso_handle#
        .type __dso_handle#,@object
@@ -85,30 +77,6 @@ __dso_handle:
          ;;
        }
 
-#ifndef SHARED
-/*
- * Fragment of the ELF _init routine that sets up __ia64_app_header
- */
-
-.section .init,"ax","progbits"
-.Lsegrel_ref:
-       { .mmi
-         addl r2 = @gprel(__ia64_app_header), gp
-         mov r16 = ip
-         ;;
-       }
-       { .mmi
-         ld8 r3 = [r2]
-         ;;
-         sub r16 = r16, r3
-         ;;
-       }
-       { .mfb
-         st8 [r2] = r16
-         ;;
-       }
-#endif
-
 .section .text
        .align  16
        .proc   __do_global_dtors_aux#
index 7dd6984..c663f58 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000 Free Software Foundation, Inc.
+/* Copyright (C) 2000, 2001 Free Software Foundation, Inc.
    Contributed by Richard Henderson <rth@cygnus.com>.
 
    This file is part of GNU CC.
 /* Locate the FDE entry for a given address, using glibc ld.so routines
    to avoid register/deregister calls at DSO load/unload.  */
 
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+#include "config.h"
+#include <stddef.h>
 #include <stdlib.h>
 #include <link.h>
-#include <bits/libc-lock.h>
 #include "unwind-ia64.h"
 
+#if __GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 2) \
+    || (__GLIBC__ == 2 && __GLIBC_MINOR__ == 2 && !defined(DT_CONFIG))
+# error You need GLIBC 2.2.4 or later on IA-64 Linux
+#endif
 
-/* Initialized by crtbegin from the main application.  */
-extern Elf64_Ehdr *__ia64_app_header;
-
-/* ??? A redeclaration of the lock in ld.so.  Perhaps this should
-   appear in <link.h> in a new glibc version.  */
-__libc_lock_define (extern, _dl_load_lock)
-
-/* This always exists, even in a static application.  */
-extern struct link_map *_dl_loaded;
+struct unw_ia64_callback_data
+{
+  Elf64_Addr pc;
+  unsigned long *segment_base;
+  unsigned long *gp;
+  struct unw_table_entry *ret;
+};
 
-static struct unw_table_entry *
-find_fde_for_dso (Elf64_Addr pc, Elf64_Ehdr *ehdr,
-                 unsigned long *pseg_base, unsigned long *pgp)
+static int
+_Unwind_IteratePhdrCallback (struct dl_phdr_info *info, size_t size, void *ptr)
 {
-  Elf64_Phdr *phdr, *p_unwind, *p_dynamic;
+  struct unw_ia64_callback_data *data = (struct unw_ia64_callback_data *) ptr;
+  const Elf64_Phdr *phdr, *p_unwind, *p_dynamic;
   long n, match;
   Elf64_Addr load_base, seg_base;
   struct unw_table_entry *f_base, *f;
   size_t lo, hi;
 
-  /* Verify that we are looking at an ELF header.  */
-  if (ehdr->e_ident[0] != 0x7f
-      || ehdr->e_ident[1] != 'E'
-      || ehdr->e_ident[2] != 'L'
-      || ehdr->e_ident[3] != 'F'
-      || ehdr->e_ident[EI_CLASS] != ELFCLASS64
-      || ehdr->e_ident[EI_DATA] != ELFDATA2LSB
-      || ehdr->e_machine != EM_IA_64)
-    abort ();
+  /* Make sure struct dl_phdr_info is at least as big as we need.  */
+  if (size < offsetof (struct dl_phdr_info, dlpi_phnum)
+            + sizeof (info->dlpi_phnum))
+    return -1;
 
   match = 0;
-  phdr = (Elf64_Phdr *)((char *)ehdr + ehdr->e_phoff);
-  load_base = (ehdr->e_type == ET_DYN ? (Elf64_Addr)ehdr : 0);
+  phdr = info->dlpi_phdr;
+  load_base = info->dlpi_addr;
   p_unwind = NULL;
   p_dynamic = NULL;
+  seg_base = ~(Elf64_Addr) 0;
 
   /* See if PC falls into one of the loaded segments.  Find the unwind
      segment at the same time.  */
-  for (n = ehdr->e_phnum; --n >= 0; phdr++)
+  for (n = info->dlpi_phnum; --n >= 0; phdr++)
     {
       if (phdr->p_type == PT_LOAD)
        {
          Elf64_Addr vaddr = phdr->p_vaddr + load_base;
-         if (pc >= vaddr && pc < vaddr + phdr->p_memsz)
+         if (data->pc >= vaddr && data->pc < vaddr + phdr->p_memsz)
            match = 1;
+         if (vaddr < seg_base)
+           seg_base = vaddr;
        }
       else if (phdr->p_type == PT_IA_64_UNWIND)
        p_unwind = phdr;
@@ -86,12 +90,11 @@ find_fde_for_dso (Elf64_Addr pc, Elf64_Ehdr *ehdr,
        p_dynamic = phdr;
     }
   if (!match || !p_unwind)
-    return NULL;
+    return 0;
 
   /* Search for the FDE within the unwind segment.  */
 
   f_base = (struct unw_table_entry *) (p_unwind->p_vaddr + load_base);
-  seg_base = (Elf64_Addr) ehdr;
   lo = 0;
   hi = p_unwind->p_memsz / sizeof (struct unw_table_entry);
 
@@ -100,18 +103,19 @@ find_fde_for_dso (Elf64_Addr pc, Elf64_Ehdr *ehdr,
       size_t mid = (lo + hi) / 2;
 
       f = f_base + mid;
-      if (pc < f->start_offset + seg_base)
+      if (data->pc < f->start_offset + seg_base)
        hi = mid;
-      else if (pc >= f->end_offset + seg_base)
+      else if (data->pc >= f->end_offset + seg_base)
        lo = mid + 1;
       else
         goto found;
     }
-  return NULL;
+  return 0;
 
  found:
-  *pseg_base = seg_base;
-  *pgp = 0;
+  *data->segment_base = seg_base;
+  *data->gp = 0;
+  data->ret = f;
 
   if (p_dynamic)
     {
@@ -121,8 +125,8 @@ find_fde_for_dso (Elf64_Addr pc, Elf64_Ehdr *ehdr,
       for (; dyn->d_tag != DT_NULL ; dyn++)
        if (dyn->d_tag == DT_PLTGOT)
          {
-           /* ??? Glibc seems to have relocated this already.  */
-           *pgp = dyn->d_un.d_ptr;
+           /* On IA-64, _DYNAMIC is writable and GLIBC has relocated it.  */
+           *data->gp = dyn->d_un.d_ptr;
            break;
          }
     }
@@ -131,10 +135,10 @@ find_fde_for_dso (Elf64_Addr pc, Elf64_Ehdr *ehdr,
       /* Otherwise this is a static executable with no _DYNAMIC.
         The gp is constant program-wide.  */
       register unsigned long gp __asm__("gp");
-      *pgp = gp;
+      *data->gp = gp;
     }
 
-  return f;
+  return 1;
 }
 
 /* Return a pointer to the unwind table entry for the function
@@ -144,34 +148,15 @@ struct unw_table_entry *
 _Unwind_FindTableEntry (void *pc, unsigned long *segment_base,
                         unsigned long *gp)
 {
-  struct unw_table_entry *ret;
-  struct link_map *map;
+  struct unw_ia64_callback_data data;
 
-  /* Check the main application first, hoping that most of the user's
-     code is there instead of in some library.  */
-  ret = find_fde_for_dso ((Elf64_Addr)pc, __ia64_app_header,
-                         segment_base, gp);
-  if (ret)
-    return ret;
+  data.pc = (Elf64_Addr) pc;
+  data.segment_base = segment_base;
+  data.gp = gp;
+  data.ret = NULL;
 
-  /* Glibc is probably unique in that we can (with certain restrictions)
-     dynamicly load libraries into staticly linked applications.  Thus
-     we _always_ check _dl_loaded.  */
-
-  __libc_lock_lock (_dl_load_lock);
-
-  for (map = _dl_loaded; map ; map = map->l_next)
-    {
-      /* Skip the main application's entry.  */
-      if (map->l_name[0] == 0)
-       continue;
-      ret = find_fde_for_dso ((Elf64_Addr)pc, (Elf64_Ehdr *)map->l_addr,
-                             segment_base, gp);
-      if (ret)
-       break;
-    }
-
-  __libc_lock_unlock (_dl_load_lock);
+  if (dl_iterate_phdr (_Unwind_IteratePhdrCallback, &data) < 0)
+    return NULL;
 
-  return ret;
+  return data.ret;
 }