aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/ia64
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2001-08-09 18:22:23 +0200
committerJakub Jelinek <jakub@gcc.gnu.org>2001-08-09 18:22:23 +0200
commita734f2a306418b3d017f8f42ff11296b5c857652 (patch)
tree6e023229408bf79d99040381ec3f27f51744d580 /gcc/config/ia64
parent21d936870387dc6253c88346d357ff230ed50806 (diff)
downloadgcc-a734f2a306418b3d017f8f42ff11296b5c857652.zip
gcc-a734f2a306418b3d017f8f42ff11296b5c857652.tar.gz
gcc-a734f2a306418b3d017f8f42ff11296b5c857652.tar.bz2
fde-glibc.c: Require glibc 2.2.4+ headers.
* 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. From-SVN: r44742
Diffstat (limited to 'gcc/config/ia64')
-rw-r--r--gcc/config/ia64/crtbegin.asm32
-rw-r--r--gcc/config/ia64/fde-glibc.c117
2 files changed, 51 insertions, 98 deletions
diff --git a/gcc/config/ia64/crtbegin.asm b/gcc/config/ia64/crtbegin.asm
index 1568337..ac2f86b 100644
--- a/gcc/config/ia64/crtbegin.asm
+++ b/gcc/config/ia64/crtbegin.asm
@@ -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#
diff --git a/gcc/config/ia64/fde-glibc.c b/gcc/config/ia64/fde-glibc.c
index 7dd6984..c663f58 100644
--- a/gcc/config/ia64/fde-glibc.c
+++ b/gcc/config/ia64/fde-glibc.c
@@ -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.
@@ -28,57 +28,61 @@
/* 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;
}