b1302a8159697d110c7fbe6d15fdaf5ab53a4b51
1 /* Implements unwind table entry lookup for AIX (cf. fde-glibc.c).
2 Copyright (C) 2001 Free Software Foundation, Inc.
3 Contributed by Timothy Wall <twall@redhat.com>
5 This file is part of GNU CC.
7 GNU CC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
12 GNU CC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU CC; see the file COPYING. If not, write to
19 the Free Software Foundation, 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
25 #include "unwind-ia64.h"
31 static struct unw_table_entry
*
32 find_fde_for_dso (Elf64_Addr pc
, rt_link_map
*map
,
33 unsigned long* pseg_base
, unsigned long* pgp
)
37 struct unw_table_entry
*f_base
;
40 /* See if PC falls into one of the loaded segments. */
41 for (seg
= map
->l_segments
; seg
; seg
= (rt_segment
*)seg
->s_next
)
43 if (pc
>= seg
->s_map_addr
&& pc
< seg
->s_map_addr
+ seg
->s_mapsz
)
49 /* Search for the entry within the unwind table. */
50 f_base
= (struct unw_table_entry
*) (map
->l_unwind_table
);
51 seg_base
= (Elf64_Addr
) seg
->s_map_addr
;
53 hi
= map
->l_unwind_sz
/ sizeof (struct unw_table_entry
);
57 size_t mid
= (lo
+ hi
) / 2;
58 struct unw_table_entry
*f
= f_base
+ mid
;
60 if (pc
< f
->start_offset
+ seg_base
)
62 else if (pc
>= f
->end_offset
+ seg_base
)
65 /* AIX executables are *always* dynamic. Look up GP for this
67 Elf64_Dyn
*dyn
= map
->l_ld
;
69 for (; dyn
->d_tag
!= DT_NULL
; dyn
++)
71 if (dyn
->d_tag
== DT_PLTGOT
)
73 *pgp
= dyn
->d_un
.d_ptr
;
77 *pseg_base
= seg_base
;
84 /* Return a pointer to the unwind table entry for the function containing
86 struct unw_table_entry
*
87 _Unwind_FindTableEntry (void *pc
, unsigned long *pseg_base
, unsigned long *pgp
)
89 extern rt_r_debug _r_debug
;
90 struct unw_table_entry
*ret
;
91 rt_link_map
*map
= _r_debug
.r_map
; /* address of link map */
93 /* Check the main application first, hoping that most of the user's
94 code is there instead of in some library. */
95 ret
= find_fde_for_dso ((Elf64_Addr
)pc
, map
, pseg_base
, pgp
);
98 /* If we're in the main application, use the current GP value. */
99 register unsigned long gp
__asm__("gp");
104 /* FIXME need a DSO lock mechanism for AIX here, to ensure shared
105 libraries aren't changed while we're examining them. */
107 for (map
= _r_debug
.r_map
; map
; map
= map
->l_next
)
109 /* Skip the main application's entry. */
112 ret
= find_fde_for_dso ((Elf64_Addr
)pc
, map
, pseg_base
, pgp
);
117 /* FIXME need a DSO unlock mechanism for AIX here. */