1b725ae77Skettenis /* Target-dependent code for HPUX running on PA-RISC, for GDB.
2b725ae77Skettenis
3b725ae77Skettenis Copyright 2002, 2003 Free Software Foundation, Inc.
4b725ae77Skettenis
5b725ae77Skettenis This file is part of GDB.
6b725ae77Skettenis
7b725ae77Skettenis This program is free software; you can redistribute it and/or modify
8b725ae77Skettenis it under the terms of the GNU General Public License as published by
9b725ae77Skettenis the Free Software Foundation; either version 2 of the License, or
10b725ae77Skettenis (at your option) any later version.
11b725ae77Skettenis
12b725ae77Skettenis This program is distributed in the hope that it will be useful,
13b725ae77Skettenis but WITHOUT ANY WARRANTY; without even the implied warranty of
14b725ae77Skettenis MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15b725ae77Skettenis GNU General Public License for more details.
16b725ae77Skettenis
17b725ae77Skettenis You should have received a copy of the GNU General Public License
18b725ae77Skettenis along with this program; if not, write to the Free Software
19b725ae77Skettenis Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
20b725ae77Skettenis
21b725ae77Skettenis #include "defs.h"
22b725ae77Skettenis #include "arch-utils.h"
23b725ae77Skettenis #include "gdbcore.h"
24b725ae77Skettenis #include "osabi.h"
25b725ae77Skettenis #include "gdb_string.h"
26b725ae77Skettenis #include "frame.h"
27*11efff7fSkettenis #include "frame-unwind.h"
28*11efff7fSkettenis #include "trad-frame.h"
29*11efff7fSkettenis #include "symtab.h"
30*11efff7fSkettenis #include "objfiles.h"
31*11efff7fSkettenis #include "inferior.h"
32*11efff7fSkettenis #include "infcall.h"
33*11efff7fSkettenis #include "observer.h"
34*11efff7fSkettenis #include "hppa-tdep.h"
35*11efff7fSkettenis
36*11efff7fSkettenis #include <dl.h>
37*11efff7fSkettenis #include <machine/save_state.h>
38*11efff7fSkettenis
39*11efff7fSkettenis #ifndef offsetof
40*11efff7fSkettenis #define offsetof(TYPE, MEMBER) ((unsigned long) &((TYPE *)0)->MEMBER)
41*11efff7fSkettenis #endif
42b725ae77Skettenis
43b725ae77Skettenis /* Forward declarations. */
44b725ae77Skettenis extern void _initialize_hppa_hpux_tdep (void);
45b725ae77Skettenis extern initialize_file_ftype _initialize_hppa_hpux_tdep;
46b725ae77Skettenis
47*11efff7fSkettenis typedef struct
48*11efff7fSkettenis {
49*11efff7fSkettenis struct minimal_symbol *msym;
50*11efff7fSkettenis CORE_ADDR solib_handle;
51*11efff7fSkettenis CORE_ADDR return_val;
52*11efff7fSkettenis }
53*11efff7fSkettenis args_for_find_stub;
54b725ae77Skettenis
55*11efff7fSkettenis /* Return one if PC is in the call path of a trampoline, else return zero.
56*11efff7fSkettenis
57*11efff7fSkettenis Note we return one for *any* call trampoline (long-call, arg-reloc), not
58*11efff7fSkettenis just shared library trampolines (import, export). */
59*11efff7fSkettenis
60*11efff7fSkettenis static int
hppa32_hpux_in_solib_call_trampoline(CORE_ADDR pc,char * name)61*11efff7fSkettenis hppa32_hpux_in_solib_call_trampoline (CORE_ADDR pc, char *name)
62*11efff7fSkettenis {
63*11efff7fSkettenis struct minimal_symbol *minsym;
64*11efff7fSkettenis struct unwind_table_entry *u;
65*11efff7fSkettenis
66*11efff7fSkettenis /* First see if PC is in one of the two C-library trampolines. */
67*11efff7fSkettenis if (pc == hppa_symbol_address("$$dyncall")
68*11efff7fSkettenis || pc == hppa_symbol_address("_sr4export"))
69*11efff7fSkettenis return 1;
70*11efff7fSkettenis
71*11efff7fSkettenis minsym = lookup_minimal_symbol_by_pc (pc);
72*11efff7fSkettenis if (minsym && strcmp (DEPRECATED_SYMBOL_NAME (minsym), ".stub") == 0)
73*11efff7fSkettenis return 1;
74*11efff7fSkettenis
75*11efff7fSkettenis /* Get the unwind descriptor corresponding to PC, return zero
76*11efff7fSkettenis if no unwind was found. */
77*11efff7fSkettenis u = find_unwind_entry (pc);
78*11efff7fSkettenis if (!u)
79*11efff7fSkettenis return 0;
80*11efff7fSkettenis
81*11efff7fSkettenis /* If this isn't a linker stub, then return now. */
82*11efff7fSkettenis if (u->stub_unwind.stub_type == 0)
83*11efff7fSkettenis return 0;
84*11efff7fSkettenis
85*11efff7fSkettenis /* By definition a long-branch stub is a call stub. */
86*11efff7fSkettenis if (u->stub_unwind.stub_type == LONG_BRANCH)
87*11efff7fSkettenis return 1;
88*11efff7fSkettenis
89*11efff7fSkettenis /* The call and return path execute the same instructions within
90*11efff7fSkettenis an IMPORT stub! So an IMPORT stub is both a call and return
91*11efff7fSkettenis trampoline. */
92*11efff7fSkettenis if (u->stub_unwind.stub_type == IMPORT)
93*11efff7fSkettenis return 1;
94*11efff7fSkettenis
95*11efff7fSkettenis /* Parameter relocation stubs always have a call path and may have a
96*11efff7fSkettenis return path. */
97*11efff7fSkettenis if (u->stub_unwind.stub_type == PARAMETER_RELOCATION
98*11efff7fSkettenis || u->stub_unwind.stub_type == EXPORT)
99*11efff7fSkettenis {
100*11efff7fSkettenis CORE_ADDR addr;
101*11efff7fSkettenis
102*11efff7fSkettenis /* Search forward from the current PC until we hit a branch
103*11efff7fSkettenis or the end of the stub. */
104*11efff7fSkettenis for (addr = pc; addr <= u->region_end; addr += 4)
105*11efff7fSkettenis {
106*11efff7fSkettenis unsigned long insn;
107*11efff7fSkettenis
108*11efff7fSkettenis insn = read_memory_integer (addr, 4);
109*11efff7fSkettenis
110*11efff7fSkettenis /* Does it look like a bl? If so then it's the call path, if
111*11efff7fSkettenis we find a bv or be first, then we're on the return path. */
112*11efff7fSkettenis if ((insn & 0xfc00e000) == 0xe8000000)
113*11efff7fSkettenis return 1;
114*11efff7fSkettenis else if ((insn & 0xfc00e001) == 0xe800c000
115*11efff7fSkettenis || (insn & 0xfc000000) == 0xe0000000)
116*11efff7fSkettenis return 0;
117*11efff7fSkettenis }
118*11efff7fSkettenis
119*11efff7fSkettenis /* Should never happen. */
120*11efff7fSkettenis warning ("Unable to find branch in parameter relocation stub.\n");
121*11efff7fSkettenis return 0;
122*11efff7fSkettenis }
123*11efff7fSkettenis
124*11efff7fSkettenis /* Unknown stub type. For now, just return zero. */
125*11efff7fSkettenis return 0;
126*11efff7fSkettenis }
127*11efff7fSkettenis
128*11efff7fSkettenis static int
hppa64_hpux_in_solib_call_trampoline(CORE_ADDR pc,char * name)129*11efff7fSkettenis hppa64_hpux_in_solib_call_trampoline (CORE_ADDR pc, char *name)
130*11efff7fSkettenis {
131*11efff7fSkettenis /* PA64 has a completely different stub/trampoline scheme. Is it
132*11efff7fSkettenis better? Maybe. It's certainly harder to determine with any
133*11efff7fSkettenis certainty that we are in a stub because we can not refer to the
134*11efff7fSkettenis unwinders to help.
135*11efff7fSkettenis
136*11efff7fSkettenis The heuristic is simple. Try to lookup the current PC value in th
137*11efff7fSkettenis minimal symbol table. If that fails, then assume we are not in a
138*11efff7fSkettenis stub and return.
139*11efff7fSkettenis
140*11efff7fSkettenis Then see if the PC value falls within the section bounds for the
141*11efff7fSkettenis section containing the minimal symbol we found in the first
142*11efff7fSkettenis step. If it does, then assume we are not in a stub and return.
143*11efff7fSkettenis
144*11efff7fSkettenis Finally peek at the instructions to see if they look like a stub. */
145*11efff7fSkettenis struct minimal_symbol *minsym;
146*11efff7fSkettenis asection *sec;
147*11efff7fSkettenis CORE_ADDR addr;
148*11efff7fSkettenis int insn, i;
149*11efff7fSkettenis
150*11efff7fSkettenis minsym = lookup_minimal_symbol_by_pc (pc);
151*11efff7fSkettenis if (! minsym)
152*11efff7fSkettenis return 0;
153*11efff7fSkettenis
154*11efff7fSkettenis sec = SYMBOL_BFD_SECTION (minsym);
155*11efff7fSkettenis
156*11efff7fSkettenis if (bfd_get_section_vma (sec->owner, sec) <= pc
157*11efff7fSkettenis && pc < (bfd_get_section_vma (sec->owner, sec)
158*11efff7fSkettenis + bfd_section_size (sec->owner, sec)))
159*11efff7fSkettenis return 0;
160*11efff7fSkettenis
161*11efff7fSkettenis /* We might be in a stub. Peek at the instructions. Stubs are 3
162*11efff7fSkettenis instructions long. */
163*11efff7fSkettenis insn = read_memory_integer (pc, 4);
164*11efff7fSkettenis
165*11efff7fSkettenis /* Find out where we think we are within the stub. */
166*11efff7fSkettenis if ((insn & 0xffffc00e) == 0x53610000)
167*11efff7fSkettenis addr = pc;
168*11efff7fSkettenis else if ((insn & 0xffffffff) == 0xe820d000)
169*11efff7fSkettenis addr = pc - 4;
170*11efff7fSkettenis else if ((insn & 0xffffc00e) == 0x537b0000)
171*11efff7fSkettenis addr = pc - 8;
172*11efff7fSkettenis else
173*11efff7fSkettenis return 0;
174*11efff7fSkettenis
175*11efff7fSkettenis /* Now verify each insn in the range looks like a stub instruction. */
176*11efff7fSkettenis insn = read_memory_integer (addr, 4);
177*11efff7fSkettenis if ((insn & 0xffffc00e) != 0x53610000)
178*11efff7fSkettenis return 0;
179*11efff7fSkettenis
180*11efff7fSkettenis /* Now verify each insn in the range looks like a stub instruction. */
181*11efff7fSkettenis insn = read_memory_integer (addr + 4, 4);
182*11efff7fSkettenis if ((insn & 0xffffffff) != 0xe820d000)
183*11efff7fSkettenis return 0;
184*11efff7fSkettenis
185*11efff7fSkettenis /* Now verify each insn in the range looks like a stub instruction. */
186*11efff7fSkettenis insn = read_memory_integer (addr + 8, 4);
187*11efff7fSkettenis if ((insn & 0xffffc00e) != 0x537b0000)
188*11efff7fSkettenis return 0;
189*11efff7fSkettenis
190*11efff7fSkettenis /* Looks like a stub. */
191*11efff7fSkettenis return 1;
192*11efff7fSkettenis }
193*11efff7fSkettenis
194*11efff7fSkettenis /* Return one if PC is in the return path of a trampoline, else return zero.
195*11efff7fSkettenis
196*11efff7fSkettenis Note we return one for *any* call trampoline (long-call, arg-reloc), not
197*11efff7fSkettenis just shared library trampolines (import, export). */
198*11efff7fSkettenis
199*11efff7fSkettenis static int
hppa_hpux_in_solib_return_trampoline(CORE_ADDR pc,char * name)200*11efff7fSkettenis hppa_hpux_in_solib_return_trampoline (CORE_ADDR pc, char *name)
201*11efff7fSkettenis {
202*11efff7fSkettenis struct unwind_table_entry *u;
203*11efff7fSkettenis
204*11efff7fSkettenis /* Get the unwind descriptor corresponding to PC, return zero
205*11efff7fSkettenis if no unwind was found. */
206*11efff7fSkettenis u = find_unwind_entry (pc);
207*11efff7fSkettenis if (!u)
208*11efff7fSkettenis return 0;
209*11efff7fSkettenis
210*11efff7fSkettenis /* If this isn't a linker stub or it's just a long branch stub, then
211*11efff7fSkettenis return zero. */
212*11efff7fSkettenis if (u->stub_unwind.stub_type == 0 || u->stub_unwind.stub_type == LONG_BRANCH)
213*11efff7fSkettenis return 0;
214*11efff7fSkettenis
215*11efff7fSkettenis /* The call and return path execute the same instructions within
216*11efff7fSkettenis an IMPORT stub! So an IMPORT stub is both a call and return
217*11efff7fSkettenis trampoline. */
218*11efff7fSkettenis if (u->stub_unwind.stub_type == IMPORT)
219*11efff7fSkettenis return 1;
220*11efff7fSkettenis
221*11efff7fSkettenis /* Parameter relocation stubs always have a call path and may have a
222*11efff7fSkettenis return path. */
223*11efff7fSkettenis if (u->stub_unwind.stub_type == PARAMETER_RELOCATION
224*11efff7fSkettenis || u->stub_unwind.stub_type == EXPORT)
225*11efff7fSkettenis {
226*11efff7fSkettenis CORE_ADDR addr;
227*11efff7fSkettenis
228*11efff7fSkettenis /* Search forward from the current PC until we hit a branch
229*11efff7fSkettenis or the end of the stub. */
230*11efff7fSkettenis for (addr = pc; addr <= u->region_end; addr += 4)
231*11efff7fSkettenis {
232*11efff7fSkettenis unsigned long insn;
233*11efff7fSkettenis
234*11efff7fSkettenis insn = read_memory_integer (addr, 4);
235*11efff7fSkettenis
236*11efff7fSkettenis /* Does it look like a bl? If so then it's the call path, if
237*11efff7fSkettenis we find a bv or be first, then we're on the return path. */
238*11efff7fSkettenis if ((insn & 0xfc00e000) == 0xe8000000)
239*11efff7fSkettenis return 0;
240*11efff7fSkettenis else if ((insn & 0xfc00e001) == 0xe800c000
241*11efff7fSkettenis || (insn & 0xfc000000) == 0xe0000000)
242*11efff7fSkettenis return 1;
243*11efff7fSkettenis }
244*11efff7fSkettenis
245*11efff7fSkettenis /* Should never happen. */
246*11efff7fSkettenis warning ("Unable to find branch in parameter relocation stub.\n");
247*11efff7fSkettenis return 0;
248*11efff7fSkettenis }
249*11efff7fSkettenis
250*11efff7fSkettenis /* Unknown stub type. For now, just return zero. */
251*11efff7fSkettenis return 0;
252*11efff7fSkettenis
253*11efff7fSkettenis }
254*11efff7fSkettenis
255*11efff7fSkettenis /* Figure out if PC is in a trampoline, and if so find out where
256*11efff7fSkettenis the trampoline will jump to. If not in a trampoline, return zero.
257*11efff7fSkettenis
258*11efff7fSkettenis Simple code examination probably is not a good idea since the code
259*11efff7fSkettenis sequences in trampolines can also appear in user code.
260*11efff7fSkettenis
261*11efff7fSkettenis We use unwinds and information from the minimal symbol table to
262*11efff7fSkettenis determine when we're in a trampoline. This won't work for ELF
263*11efff7fSkettenis (yet) since it doesn't create stub unwind entries. Whether or
264*11efff7fSkettenis not ELF will create stub unwinds or normal unwinds for linker
265*11efff7fSkettenis stubs is still being debated.
266*11efff7fSkettenis
267*11efff7fSkettenis This should handle simple calls through dyncall or sr4export,
268*11efff7fSkettenis long calls, argument relocation stubs, and dyncall/sr4export
269*11efff7fSkettenis calling an argument relocation stub. It even handles some stubs
270*11efff7fSkettenis used in dynamic executables. */
271*11efff7fSkettenis
272*11efff7fSkettenis static CORE_ADDR
hppa_hpux_skip_trampoline_code(CORE_ADDR pc)273*11efff7fSkettenis hppa_hpux_skip_trampoline_code (CORE_ADDR pc)
274*11efff7fSkettenis {
275*11efff7fSkettenis long orig_pc = pc;
276*11efff7fSkettenis long prev_inst, curr_inst, loc;
277*11efff7fSkettenis struct minimal_symbol *msym;
278*11efff7fSkettenis struct unwind_table_entry *u;
279*11efff7fSkettenis
280*11efff7fSkettenis /* Addresses passed to dyncall may *NOT* be the actual address
281*11efff7fSkettenis of the function. So we may have to do something special. */
282*11efff7fSkettenis if (pc == hppa_symbol_address("$$dyncall"))
283*11efff7fSkettenis {
284*11efff7fSkettenis pc = (CORE_ADDR) read_register (22);
285*11efff7fSkettenis
286*11efff7fSkettenis /* If bit 30 (counting from the left) is on, then pc is the address of
287*11efff7fSkettenis the PLT entry for this function, not the address of the function
288*11efff7fSkettenis itself. Bit 31 has meaning too, but only for MPE. */
289*11efff7fSkettenis if (pc & 0x2)
290*11efff7fSkettenis pc = (CORE_ADDR) read_memory_integer (pc & ~0x3, TARGET_PTR_BIT / 8);
291*11efff7fSkettenis }
292*11efff7fSkettenis if (pc == hppa_symbol_address("$$dyncall_external"))
293*11efff7fSkettenis {
294*11efff7fSkettenis pc = (CORE_ADDR) read_register (22);
295*11efff7fSkettenis pc = (CORE_ADDR) read_memory_integer (pc & ~0x3, TARGET_PTR_BIT / 8);
296*11efff7fSkettenis }
297*11efff7fSkettenis else if (pc == hppa_symbol_address("_sr4export"))
298*11efff7fSkettenis pc = (CORE_ADDR) (read_register (22));
299*11efff7fSkettenis
300*11efff7fSkettenis /* Get the unwind descriptor corresponding to PC, return zero
301*11efff7fSkettenis if no unwind was found. */
302*11efff7fSkettenis u = find_unwind_entry (pc);
303*11efff7fSkettenis if (!u)
304*11efff7fSkettenis return 0;
305*11efff7fSkettenis
306*11efff7fSkettenis /* If this isn't a linker stub, then return now. */
307*11efff7fSkettenis /* elz: attention here! (FIXME) because of a compiler/linker
308*11efff7fSkettenis error, some stubs which should have a non zero stub_unwind.stub_type
309*11efff7fSkettenis have unfortunately a value of zero. So this function would return here
310*11efff7fSkettenis as if we were not in a trampoline. To fix this, we go look at the partial
311*11efff7fSkettenis symbol information, which reports this guy as a stub.
312*11efff7fSkettenis (FIXME): Unfortunately, we are not that lucky: it turns out that the
313*11efff7fSkettenis partial symbol information is also wrong sometimes. This is because
314*11efff7fSkettenis when it is entered (somread.c::som_symtab_read()) it can happen that
315*11efff7fSkettenis if the type of the symbol (from the som) is Entry, and the symbol is
316*11efff7fSkettenis in a shared library, then it can also be a trampoline. This would
317*11efff7fSkettenis be OK, except that I believe the way they decide if we are ina shared library
318*11efff7fSkettenis does not work. SOOOO..., even if we have a regular function w/o trampolines
319*11efff7fSkettenis its minimal symbol can be assigned type mst_solib_trampoline.
320*11efff7fSkettenis Also, if we find that the symbol is a real stub, then we fix the unwind
321*11efff7fSkettenis descriptor, and define the stub type to be EXPORT.
322*11efff7fSkettenis Hopefully this is correct most of the times. */
323*11efff7fSkettenis if (u->stub_unwind.stub_type == 0)
324*11efff7fSkettenis {
325*11efff7fSkettenis
326*11efff7fSkettenis /* elz: NOTE (FIXME!) once the problem with the unwind information is fixed
327*11efff7fSkettenis we can delete all the code which appears between the lines */
328*11efff7fSkettenis /*--------------------------------------------------------------------------*/
329*11efff7fSkettenis msym = lookup_minimal_symbol_by_pc (pc);
330*11efff7fSkettenis
331*11efff7fSkettenis if (msym == NULL || MSYMBOL_TYPE (msym) != mst_solib_trampoline)
332*11efff7fSkettenis return orig_pc == pc ? 0 : pc & ~0x3;
333*11efff7fSkettenis
334*11efff7fSkettenis else if (msym != NULL && MSYMBOL_TYPE (msym) == mst_solib_trampoline)
335*11efff7fSkettenis {
336*11efff7fSkettenis struct objfile *objfile;
337*11efff7fSkettenis struct minimal_symbol *msymbol;
338*11efff7fSkettenis int function_found = 0;
339*11efff7fSkettenis
340*11efff7fSkettenis /* go look if there is another minimal symbol with the same name as
341*11efff7fSkettenis this one, but with type mst_text. This would happen if the msym
342*11efff7fSkettenis is an actual trampoline, in which case there would be another
343*11efff7fSkettenis symbol with the same name corresponding to the real function */
344*11efff7fSkettenis
345*11efff7fSkettenis ALL_MSYMBOLS (objfile, msymbol)
346*11efff7fSkettenis {
347*11efff7fSkettenis if (MSYMBOL_TYPE (msymbol) == mst_text
348*11efff7fSkettenis && DEPRECATED_STREQ (DEPRECATED_SYMBOL_NAME (msymbol), DEPRECATED_SYMBOL_NAME (msym)))
349*11efff7fSkettenis {
350*11efff7fSkettenis function_found = 1;
351*11efff7fSkettenis break;
352*11efff7fSkettenis }
353*11efff7fSkettenis }
354*11efff7fSkettenis
355*11efff7fSkettenis if (function_found)
356*11efff7fSkettenis /* the type of msym is correct (mst_solib_trampoline), but
357*11efff7fSkettenis the unwind info is wrong, so set it to the correct value */
358*11efff7fSkettenis u->stub_unwind.stub_type = EXPORT;
359*11efff7fSkettenis else
360*11efff7fSkettenis /* the stub type info in the unwind is correct (this is not a
361*11efff7fSkettenis trampoline), but the msym type information is wrong, it
362*11efff7fSkettenis should be mst_text. So we need to fix the msym, and also
363*11efff7fSkettenis get out of this function */
364*11efff7fSkettenis {
365*11efff7fSkettenis MSYMBOL_TYPE (msym) = mst_text;
366*11efff7fSkettenis return orig_pc == pc ? 0 : pc & ~0x3;
367*11efff7fSkettenis }
368*11efff7fSkettenis }
369*11efff7fSkettenis
370*11efff7fSkettenis /*--------------------------------------------------------------------------*/
371*11efff7fSkettenis }
372*11efff7fSkettenis
373*11efff7fSkettenis /* It's a stub. Search for a branch and figure out where it goes.
374*11efff7fSkettenis Note we have to handle multi insn branch sequences like ldil;ble.
375*11efff7fSkettenis Most (all?) other branches can be determined by examining the contents
376*11efff7fSkettenis of certain registers and the stack. */
377*11efff7fSkettenis
378*11efff7fSkettenis loc = pc;
379*11efff7fSkettenis curr_inst = 0;
380*11efff7fSkettenis prev_inst = 0;
381*11efff7fSkettenis while (1)
382*11efff7fSkettenis {
383*11efff7fSkettenis /* Make sure we haven't walked outside the range of this stub. */
384*11efff7fSkettenis if (u != find_unwind_entry (loc))
385*11efff7fSkettenis {
386*11efff7fSkettenis warning ("Unable to find branch in linker stub");
387*11efff7fSkettenis return orig_pc == pc ? 0 : pc & ~0x3;
388*11efff7fSkettenis }
389*11efff7fSkettenis
390*11efff7fSkettenis prev_inst = curr_inst;
391*11efff7fSkettenis curr_inst = read_memory_integer (loc, 4);
392*11efff7fSkettenis
393*11efff7fSkettenis /* Does it look like a branch external using %r1? Then it's the
394*11efff7fSkettenis branch from the stub to the actual function. */
395*11efff7fSkettenis if ((curr_inst & 0xffe0e000) == 0xe0202000)
396*11efff7fSkettenis {
397*11efff7fSkettenis /* Yup. See if the previous instruction loaded
398*11efff7fSkettenis a value into %r1. If so compute and return the jump address. */
399*11efff7fSkettenis if ((prev_inst & 0xffe00000) == 0x20200000)
400*11efff7fSkettenis return (hppa_extract_21 (prev_inst) + hppa_extract_17 (curr_inst)) & ~0x3;
401*11efff7fSkettenis else
402*11efff7fSkettenis {
403*11efff7fSkettenis warning ("Unable to find ldil X,%%r1 before ble Y(%%sr4,%%r1).");
404*11efff7fSkettenis return orig_pc == pc ? 0 : pc & ~0x3;
405*11efff7fSkettenis }
406*11efff7fSkettenis }
407*11efff7fSkettenis
408*11efff7fSkettenis /* Does it look like a be 0(sr0,%r21)? OR
409*11efff7fSkettenis Does it look like a be, n 0(sr0,%r21)? OR
410*11efff7fSkettenis Does it look like a bve (r21)? (this is on PA2.0)
411*11efff7fSkettenis Does it look like a bve, n(r21)? (this is also on PA2.0)
412*11efff7fSkettenis That's the branch from an
413*11efff7fSkettenis import stub to an export stub.
414*11efff7fSkettenis
415*11efff7fSkettenis It is impossible to determine the target of the branch via
416*11efff7fSkettenis simple examination of instructions and/or data (consider
417*11efff7fSkettenis that the address in the plabel may be the address of the
418*11efff7fSkettenis bind-on-reference routine in the dynamic loader).
419*11efff7fSkettenis
420*11efff7fSkettenis So we have try an alternative approach.
421*11efff7fSkettenis
422*11efff7fSkettenis Get the name of the symbol at our current location; it should
423*11efff7fSkettenis be a stub symbol with the same name as the symbol in the
424*11efff7fSkettenis shared library.
425*11efff7fSkettenis
426*11efff7fSkettenis Then lookup a minimal symbol with the same name; we should
427*11efff7fSkettenis get the minimal symbol for the target routine in the shared
428*11efff7fSkettenis library as those take precedence of import/export stubs. */
429*11efff7fSkettenis if ((curr_inst == 0xe2a00000) ||
430*11efff7fSkettenis (curr_inst == 0xe2a00002) ||
431*11efff7fSkettenis (curr_inst == 0xeaa0d000) ||
432*11efff7fSkettenis (curr_inst == 0xeaa0d002))
433*11efff7fSkettenis {
434*11efff7fSkettenis struct minimal_symbol *stubsym, *libsym;
435*11efff7fSkettenis
436*11efff7fSkettenis stubsym = lookup_minimal_symbol_by_pc (loc);
437*11efff7fSkettenis if (stubsym == NULL)
438*11efff7fSkettenis {
439*11efff7fSkettenis warning ("Unable to find symbol for 0x%lx", loc);
440*11efff7fSkettenis return orig_pc == pc ? 0 : pc & ~0x3;
441*11efff7fSkettenis }
442*11efff7fSkettenis
443*11efff7fSkettenis libsym = lookup_minimal_symbol (DEPRECATED_SYMBOL_NAME (stubsym), NULL, NULL);
444*11efff7fSkettenis if (libsym == NULL)
445*11efff7fSkettenis {
446*11efff7fSkettenis warning ("Unable to find library symbol for %s\n",
447*11efff7fSkettenis DEPRECATED_SYMBOL_NAME (stubsym));
448*11efff7fSkettenis return orig_pc == pc ? 0 : pc & ~0x3;
449*11efff7fSkettenis }
450*11efff7fSkettenis
451*11efff7fSkettenis return SYMBOL_VALUE (libsym);
452*11efff7fSkettenis }
453*11efff7fSkettenis
454*11efff7fSkettenis /* Does it look like bl X,%rp or bl X,%r0? Another way to do a
455*11efff7fSkettenis branch from the stub to the actual function. */
456*11efff7fSkettenis /*elz */
457*11efff7fSkettenis else if ((curr_inst & 0xffe0e000) == 0xe8400000
458*11efff7fSkettenis || (curr_inst & 0xffe0e000) == 0xe8000000
459*11efff7fSkettenis || (curr_inst & 0xffe0e000) == 0xe800A000)
460*11efff7fSkettenis return (loc + hppa_extract_17 (curr_inst) + 8) & ~0x3;
461*11efff7fSkettenis
462*11efff7fSkettenis /* Does it look like bv (rp)? Note this depends on the
463*11efff7fSkettenis current stack pointer being the same as the stack
464*11efff7fSkettenis pointer in the stub itself! This is a branch on from the
465*11efff7fSkettenis stub back to the original caller. */
466*11efff7fSkettenis /*else if ((curr_inst & 0xffe0e000) == 0xe840c000) */
467*11efff7fSkettenis else if ((curr_inst & 0xffe0f000) == 0xe840c000)
468*11efff7fSkettenis {
469*11efff7fSkettenis /* Yup. See if the previous instruction loaded
470*11efff7fSkettenis rp from sp - 8. */
471*11efff7fSkettenis if (prev_inst == 0x4bc23ff1)
472*11efff7fSkettenis return (read_memory_integer
473*11efff7fSkettenis (read_register (HPPA_SP_REGNUM) - 8, 4)) & ~0x3;
474*11efff7fSkettenis else
475*11efff7fSkettenis {
476*11efff7fSkettenis warning ("Unable to find restore of %%rp before bv (%%rp).");
477*11efff7fSkettenis return orig_pc == pc ? 0 : pc & ~0x3;
478*11efff7fSkettenis }
479*11efff7fSkettenis }
480*11efff7fSkettenis
481*11efff7fSkettenis /* elz: added this case to capture the new instruction
482*11efff7fSkettenis at the end of the return part of an export stub used by
483*11efff7fSkettenis the PA2.0: BVE, n (rp) */
484*11efff7fSkettenis else if ((curr_inst & 0xffe0f000) == 0xe840d000)
485*11efff7fSkettenis {
486*11efff7fSkettenis return (read_memory_integer
487*11efff7fSkettenis (read_register (HPPA_SP_REGNUM) - 24, TARGET_PTR_BIT / 8)) & ~0x3;
488*11efff7fSkettenis }
489*11efff7fSkettenis
490*11efff7fSkettenis /* What about be,n 0(sr0,%rp)? It's just another way we return to
491*11efff7fSkettenis the original caller from the stub. Used in dynamic executables. */
492*11efff7fSkettenis else if (curr_inst == 0xe0400002)
493*11efff7fSkettenis {
494*11efff7fSkettenis /* The value we jump to is sitting in sp - 24. But that's
495*11efff7fSkettenis loaded several instructions before the be instruction.
496*11efff7fSkettenis I guess we could check for the previous instruction being
497*11efff7fSkettenis mtsp %r1,%sr0 if we want to do sanity checking. */
498*11efff7fSkettenis return (read_memory_integer
499*11efff7fSkettenis (read_register (HPPA_SP_REGNUM) - 24, TARGET_PTR_BIT / 8)) & ~0x3;
500*11efff7fSkettenis }
501*11efff7fSkettenis
502*11efff7fSkettenis /* Haven't found the branch yet, but we're still in the stub.
503*11efff7fSkettenis Keep looking. */
504*11efff7fSkettenis loc += 4;
505*11efff7fSkettenis }
506*11efff7fSkettenis }
507*11efff7fSkettenis
508*11efff7fSkettenis
509*11efff7fSkettenis /* Exception handling support for the HP-UX ANSI C++ compiler.
510*11efff7fSkettenis The compiler (aCC) provides a callback for exception events;
511*11efff7fSkettenis GDB can set a breakpoint on this callback and find out what
512*11efff7fSkettenis exception event has occurred. */
513*11efff7fSkettenis
514*11efff7fSkettenis /* The name of the hook to be set to point to the callback function */
515*11efff7fSkettenis static char HP_ACC_EH_notify_hook[] = "__eh_notify_hook";
516*11efff7fSkettenis /* The name of the function to be used to set the hook value */
517*11efff7fSkettenis static char HP_ACC_EH_set_hook_value[] = "__eh_set_hook_value";
518*11efff7fSkettenis /* The name of the callback function in end.o */
519*11efff7fSkettenis static char HP_ACC_EH_notify_callback[] = "__d_eh_notify_callback";
520*11efff7fSkettenis /* Name of function in end.o on which a break is set (called by above) */
521*11efff7fSkettenis static char HP_ACC_EH_break[] = "__d_eh_break";
522*11efff7fSkettenis /* Name of flag (in end.o) that enables catching throws */
523*11efff7fSkettenis static char HP_ACC_EH_catch_throw[] = "__d_eh_catch_throw";
524*11efff7fSkettenis /* Name of flag (in end.o) that enables catching catching */
525*11efff7fSkettenis static char HP_ACC_EH_catch_catch[] = "__d_eh_catch_catch";
526*11efff7fSkettenis /* The enum used by aCC */
527*11efff7fSkettenis typedef enum
528*11efff7fSkettenis {
529*11efff7fSkettenis __EH_NOTIFY_THROW,
530*11efff7fSkettenis __EH_NOTIFY_CATCH
531*11efff7fSkettenis }
532*11efff7fSkettenis __eh_notification;
533*11efff7fSkettenis
534*11efff7fSkettenis /* Is exception-handling support available with this executable? */
535*11efff7fSkettenis static int hp_cxx_exception_support = 0;
536*11efff7fSkettenis /* Has the initialize function been run? */
537*11efff7fSkettenis static int hp_cxx_exception_support_initialized = 0;
538*11efff7fSkettenis /* Address of __eh_notify_hook */
539*11efff7fSkettenis static CORE_ADDR eh_notify_hook_addr = 0;
540*11efff7fSkettenis /* Address of __d_eh_notify_callback */
541*11efff7fSkettenis static CORE_ADDR eh_notify_callback_addr = 0;
542*11efff7fSkettenis /* Address of __d_eh_break */
543*11efff7fSkettenis static CORE_ADDR eh_break_addr = 0;
544*11efff7fSkettenis /* Address of __d_eh_catch_catch */
545*11efff7fSkettenis static CORE_ADDR eh_catch_catch_addr = 0;
546*11efff7fSkettenis /* Address of __d_eh_catch_throw */
547*11efff7fSkettenis static CORE_ADDR eh_catch_throw_addr = 0;
548*11efff7fSkettenis /* Sal for __d_eh_break */
549*11efff7fSkettenis static struct symtab_and_line *break_callback_sal = 0;
550*11efff7fSkettenis
551*11efff7fSkettenis /* Code in end.c expects __d_pid to be set in the inferior,
552*11efff7fSkettenis otherwise __d_eh_notify_callback doesn't bother to call
553*11efff7fSkettenis __d_eh_break! So we poke the pid into this symbol
554*11efff7fSkettenis ourselves.
555*11efff7fSkettenis 0 => success
556*11efff7fSkettenis 1 => failure */
557b725ae77Skettenis int
setup_d_pid_in_inferior(void)558*11efff7fSkettenis setup_d_pid_in_inferior (void)
559b725ae77Skettenis {
560*11efff7fSkettenis CORE_ADDR anaddr;
561*11efff7fSkettenis struct minimal_symbol *msymbol;
562*11efff7fSkettenis char buf[4]; /* FIXME 32x64? */
563*11efff7fSkettenis
564*11efff7fSkettenis /* Slam the pid of the process into __d_pid; failing is only a warning! */
565*11efff7fSkettenis msymbol = lookup_minimal_symbol ("__d_pid", NULL, symfile_objfile);
566*11efff7fSkettenis if (msymbol == NULL)
567*11efff7fSkettenis {
568*11efff7fSkettenis warning ("Unable to find __d_pid symbol in object file.");
569*11efff7fSkettenis warning ("Suggest linking executable with -g (links in /opt/langtools/lib/end.o).");
570*11efff7fSkettenis return 1;
571b725ae77Skettenis }
572b725ae77Skettenis
573*11efff7fSkettenis anaddr = SYMBOL_VALUE_ADDRESS (msymbol);
574*11efff7fSkettenis store_unsigned_integer (buf, 4, PIDGET (inferior_ptid)); /* FIXME 32x64? */
575*11efff7fSkettenis if (target_write_memory (anaddr, buf, 4)) /* FIXME 32x64? */
576b725ae77Skettenis {
577*11efff7fSkettenis warning ("Unable to write __d_pid");
578*11efff7fSkettenis warning ("Suggest linking executable with -g (links in /opt/langtools/lib/end.o).");
579*11efff7fSkettenis return 1;
580*11efff7fSkettenis }
581*11efff7fSkettenis return 0;
582b725ae77Skettenis }
583b725ae77Skettenis
584*11efff7fSkettenis /* elz: Used to lookup a symbol in the shared libraries.
585*11efff7fSkettenis This function calls shl_findsym, indirectly through a
586*11efff7fSkettenis call to __d_shl_get. __d_shl_get is in end.c, which is always
587*11efff7fSkettenis linked in by the hp compilers/linkers.
588*11efff7fSkettenis The call to shl_findsym cannot be made directly because it needs
589*11efff7fSkettenis to be active in target address space.
590*11efff7fSkettenis inputs: - minimal symbol pointer for the function we want to look up
591*11efff7fSkettenis - address in target space of the descriptor for the library
592*11efff7fSkettenis where we want to look the symbol up.
593*11efff7fSkettenis This address is retrieved using the
594*11efff7fSkettenis som_solib_get_solib_by_pc function (somsolib.c).
595*11efff7fSkettenis output: - real address in the library of the function.
596*11efff7fSkettenis note: the handle can be null, in which case shl_findsym will look for
597*11efff7fSkettenis the symbol in all the loaded shared libraries.
598*11efff7fSkettenis files to look at if you need reference on this stuff:
599*11efff7fSkettenis dld.c, dld_shl_findsym.c
600*11efff7fSkettenis end.c
601*11efff7fSkettenis man entry for shl_findsym */
602*11efff7fSkettenis
603*11efff7fSkettenis CORE_ADDR
find_stub_with_shl_get(struct minimal_symbol * function,CORE_ADDR handle)604*11efff7fSkettenis find_stub_with_shl_get (struct minimal_symbol *function, CORE_ADDR handle)
605b725ae77Skettenis {
606*11efff7fSkettenis struct symbol *get_sym, *symbol2;
607*11efff7fSkettenis struct minimal_symbol *buff_minsym, *msymbol;
608*11efff7fSkettenis struct type *ftype;
609*11efff7fSkettenis struct value **args;
610*11efff7fSkettenis struct value *funcval;
611*11efff7fSkettenis struct value *val;
612*11efff7fSkettenis
613*11efff7fSkettenis int x, namelen, err_value, tmp = -1;
614*11efff7fSkettenis CORE_ADDR endo_buff_addr, value_return_addr, errno_return_addr;
615*11efff7fSkettenis CORE_ADDR stub_addr;
616*11efff7fSkettenis
617*11efff7fSkettenis
618*11efff7fSkettenis args = alloca (sizeof (struct value *) * 8); /* 6 for the arguments and one null one??? */
619*11efff7fSkettenis funcval = find_function_in_inferior ("__d_shl_get");
620*11efff7fSkettenis get_sym = lookup_symbol ("__d_shl_get", NULL, VAR_DOMAIN, NULL, NULL);
621*11efff7fSkettenis buff_minsym = lookup_minimal_symbol ("__buffer", NULL, NULL);
622*11efff7fSkettenis msymbol = lookup_minimal_symbol ("__shldp", NULL, NULL);
623*11efff7fSkettenis symbol2 = lookup_symbol ("__shldp", NULL, VAR_DOMAIN, NULL, NULL);
624*11efff7fSkettenis endo_buff_addr = SYMBOL_VALUE_ADDRESS (buff_minsym);
625*11efff7fSkettenis namelen = strlen (DEPRECATED_SYMBOL_NAME (function));
626*11efff7fSkettenis value_return_addr = endo_buff_addr + namelen;
627*11efff7fSkettenis ftype = check_typedef (SYMBOL_TYPE (get_sym));
628*11efff7fSkettenis
629*11efff7fSkettenis /* do alignment */
630*11efff7fSkettenis if ((x = value_return_addr % 64) != 0)
631*11efff7fSkettenis value_return_addr = value_return_addr + 64 - x;
632*11efff7fSkettenis
633*11efff7fSkettenis errno_return_addr = value_return_addr + 64;
634*11efff7fSkettenis
635*11efff7fSkettenis
636*11efff7fSkettenis /* set up stuff needed by __d_shl_get in buffer in end.o */
637*11efff7fSkettenis
638*11efff7fSkettenis target_write_memory (endo_buff_addr, DEPRECATED_SYMBOL_NAME (function), namelen);
639*11efff7fSkettenis
640*11efff7fSkettenis target_write_memory (value_return_addr, (char *) &tmp, 4);
641*11efff7fSkettenis
642*11efff7fSkettenis target_write_memory (errno_return_addr, (char *) &tmp, 4);
643*11efff7fSkettenis
644*11efff7fSkettenis target_write_memory (SYMBOL_VALUE_ADDRESS (msymbol),
645*11efff7fSkettenis (char *) &handle, 4);
646*11efff7fSkettenis
647*11efff7fSkettenis /* now prepare the arguments for the call */
648*11efff7fSkettenis
649*11efff7fSkettenis args[0] = value_from_longest (TYPE_FIELD_TYPE (ftype, 0), 12);
650*11efff7fSkettenis args[1] = value_from_pointer (TYPE_FIELD_TYPE (ftype, 1), SYMBOL_VALUE_ADDRESS (msymbol));
651*11efff7fSkettenis args[2] = value_from_pointer (TYPE_FIELD_TYPE (ftype, 2), endo_buff_addr);
652*11efff7fSkettenis args[3] = value_from_longest (TYPE_FIELD_TYPE (ftype, 3), TYPE_PROCEDURE);
653*11efff7fSkettenis args[4] = value_from_pointer (TYPE_FIELD_TYPE (ftype, 4), value_return_addr);
654*11efff7fSkettenis args[5] = value_from_pointer (TYPE_FIELD_TYPE (ftype, 5), errno_return_addr);
655*11efff7fSkettenis
656*11efff7fSkettenis /* now call the function */
657*11efff7fSkettenis
658*11efff7fSkettenis val = call_function_by_hand (funcval, 6, args);
659*11efff7fSkettenis
660*11efff7fSkettenis /* now get the results */
661*11efff7fSkettenis
662*11efff7fSkettenis target_read_memory (errno_return_addr, (char *) &err_value, sizeof (err_value));
663*11efff7fSkettenis
664*11efff7fSkettenis target_read_memory (value_return_addr, (char *) &stub_addr, sizeof (stub_addr));
665*11efff7fSkettenis if (stub_addr <= 0)
666*11efff7fSkettenis error ("call to __d_shl_get failed, error code is %d", err_value);
667*11efff7fSkettenis
668*11efff7fSkettenis return (stub_addr);
669b725ae77Skettenis }
670b725ae77Skettenis
671*11efff7fSkettenis /* Cover routine for find_stub_with_shl_get to pass to catch_errors */
672*11efff7fSkettenis static int
cover_find_stub_with_shl_get(void * args_untyped)673*11efff7fSkettenis cover_find_stub_with_shl_get (void *args_untyped)
674b725ae77Skettenis {
675*11efff7fSkettenis args_for_find_stub *args = args_untyped;
676*11efff7fSkettenis args->return_val = find_stub_with_shl_get (args->msym, args->solib_handle);
677*11efff7fSkettenis return 0;
678*11efff7fSkettenis }
679*11efff7fSkettenis
680*11efff7fSkettenis /* Initialize exception catchpoint support by looking for the
681*11efff7fSkettenis necessary hooks/callbacks in end.o, etc., and set the hook value to
682*11efff7fSkettenis point to the required debug function
683*11efff7fSkettenis
684*11efff7fSkettenis Return 0 => failure
685*11efff7fSkettenis 1 => success */
686*11efff7fSkettenis
687*11efff7fSkettenis static int
initialize_hp_cxx_exception_support(void)688*11efff7fSkettenis initialize_hp_cxx_exception_support (void)
689*11efff7fSkettenis {
690*11efff7fSkettenis struct symtabs_and_lines sals;
691*11efff7fSkettenis struct cleanup *old_chain;
692*11efff7fSkettenis struct cleanup *canonical_strings_chain = NULL;
693b725ae77Skettenis int i;
694*11efff7fSkettenis char *addr_start;
695*11efff7fSkettenis char *addr_end = NULL;
696*11efff7fSkettenis char **canonical = (char **) NULL;
697*11efff7fSkettenis int thread = -1;
698*11efff7fSkettenis struct symbol *sym = NULL;
699*11efff7fSkettenis struct minimal_symbol *msym = NULL;
700*11efff7fSkettenis struct objfile *objfile;
701*11efff7fSkettenis asection *shlib_info;
702b725ae77Skettenis
703*11efff7fSkettenis /* Detect and disallow recursion. On HP-UX with aCC, infinite
704*11efff7fSkettenis recursion is a possibility because finding the hook for exception
705*11efff7fSkettenis callbacks involves making a call in the inferior, which means
706*11efff7fSkettenis re-inserting breakpoints which can re-invoke this code */
707*11efff7fSkettenis
708*11efff7fSkettenis static int recurse = 0;
709*11efff7fSkettenis if (recurse > 0)
710b725ae77Skettenis {
711*11efff7fSkettenis hp_cxx_exception_support_initialized = 0;
712*11efff7fSkettenis deprecated_exception_support_initialized = 0;
713*11efff7fSkettenis return 0;
714*11efff7fSkettenis }
715*11efff7fSkettenis
716*11efff7fSkettenis hp_cxx_exception_support = 0;
717*11efff7fSkettenis
718*11efff7fSkettenis /* First check if we have seen any HP compiled objects; if not,
719*11efff7fSkettenis it is very unlikely that HP's idiosyncratic callback mechanism
720*11efff7fSkettenis for exception handling debug support will be available!
721*11efff7fSkettenis This will percolate back up to breakpoint.c, where our callers
722*11efff7fSkettenis will decide to try the g++ exception-handling support instead. */
723*11efff7fSkettenis if (!deprecated_hp_som_som_object_present)
724*11efff7fSkettenis return 0;
725*11efff7fSkettenis
726*11efff7fSkettenis /* We have a SOM executable with SOM debug info; find the hooks */
727*11efff7fSkettenis
728*11efff7fSkettenis /* First look for the notify hook provided by aCC runtime libs */
729*11efff7fSkettenis /* If we find this symbol, we conclude that the executable must
730*11efff7fSkettenis have HP aCC exception support built in. If this symbol is not
731*11efff7fSkettenis found, even though we're a HP SOM-SOM file, we may have been
732*11efff7fSkettenis built with some other compiler (not aCC). This results percolates
733*11efff7fSkettenis back up to our callers in breakpoint.c which can decide to
734*11efff7fSkettenis try the g++ style of exception support instead.
735*11efff7fSkettenis If this symbol is found but the other symbols we require are
736*11efff7fSkettenis not found, there is something weird going on, and g++ support
737*11efff7fSkettenis should *not* be tried as an alternative.
738*11efff7fSkettenis
739*11efff7fSkettenis ASSUMPTION: Only HP aCC code will have __eh_notify_hook defined.
740*11efff7fSkettenis ASSUMPTION: HP aCC and g++ modules cannot be linked together. */
741*11efff7fSkettenis
742*11efff7fSkettenis /* libCsup has this hook; it'll usually be non-debuggable */
743*11efff7fSkettenis msym = lookup_minimal_symbol (HP_ACC_EH_notify_hook, NULL, NULL);
744*11efff7fSkettenis if (msym)
745*11efff7fSkettenis {
746*11efff7fSkettenis eh_notify_hook_addr = SYMBOL_VALUE_ADDRESS (msym);
747*11efff7fSkettenis hp_cxx_exception_support = 1;
748*11efff7fSkettenis }
749b725ae77Skettenis else
750*11efff7fSkettenis {
751*11efff7fSkettenis warning ("Unable to find exception callback hook (%s).", HP_ACC_EH_notify_hook);
752*11efff7fSkettenis warning ("Executable may not have been compiled debuggable with HP aCC.");
753*11efff7fSkettenis warning ("GDB will be unable to intercept exception events.");
754*11efff7fSkettenis eh_notify_hook_addr = 0;
755*11efff7fSkettenis hp_cxx_exception_support = 0;
756*11efff7fSkettenis return 0;
757b725ae77Skettenis }
758b725ae77Skettenis
759*11efff7fSkettenis /* Next look for the notify callback routine in end.o */
760*11efff7fSkettenis /* This is always available in the SOM symbol dictionary if end.o is linked in */
761*11efff7fSkettenis msym = lookup_minimal_symbol (HP_ACC_EH_notify_callback, NULL, NULL);
762*11efff7fSkettenis if (msym)
763b725ae77Skettenis {
764*11efff7fSkettenis eh_notify_callback_addr = SYMBOL_VALUE_ADDRESS (msym);
765*11efff7fSkettenis hp_cxx_exception_support = 1;
766b725ae77Skettenis }
767b725ae77Skettenis else
768*11efff7fSkettenis {
769*11efff7fSkettenis warning ("Unable to find exception callback routine (%s).", HP_ACC_EH_notify_callback);
770*11efff7fSkettenis warning ("Suggest linking executable with -g (links in /opt/langtools/lib/end.o).");
771*11efff7fSkettenis warning ("GDB will be unable to intercept exception events.");
772*11efff7fSkettenis eh_notify_callback_addr = 0;
773*11efff7fSkettenis return 0;
774b725ae77Skettenis }
775*11efff7fSkettenis
776*11efff7fSkettenis #ifndef GDB_TARGET_IS_HPPA_20W
777*11efff7fSkettenis /* Check whether the executable is dynamically linked or archive bound */
778*11efff7fSkettenis /* With an archive-bound executable we can use the raw addresses we find
779*11efff7fSkettenis for the callback function, etc. without modification. For an executable
780*11efff7fSkettenis with shared libraries, we have to do more work to find the plabel, which
781*11efff7fSkettenis can be the target of a call through $$dyncall from the aCC runtime support
782*11efff7fSkettenis library (libCsup) which is linked shared by default by aCC. */
783*11efff7fSkettenis /* This test below was copied from somsolib.c/somread.c. It may not be a very
784*11efff7fSkettenis reliable one to test that an executable is linked shared. pai/1997-07-18 */
785*11efff7fSkettenis shlib_info = bfd_get_section_by_name (symfile_objfile->obfd, "$SHLIB_INFO$");
786*11efff7fSkettenis if (shlib_info && (bfd_section_size (symfile_objfile->obfd, shlib_info) != 0))
787*11efff7fSkettenis {
788*11efff7fSkettenis /* The minsym we have has the local code address, but that's not the
789*11efff7fSkettenis plabel that can be used by an inter-load-module call. */
790*11efff7fSkettenis /* Find solib handle for main image (which has end.o), and use that
791*11efff7fSkettenis and the min sym as arguments to __d_shl_get() (which does the equivalent
792*11efff7fSkettenis of shl_findsym()) to find the plabel. */
793*11efff7fSkettenis
794*11efff7fSkettenis args_for_find_stub args;
795*11efff7fSkettenis static char message[] = "Error while finding exception callback hook:\n";
796*11efff7fSkettenis
797*11efff7fSkettenis args.solib_handle = som_solib_get_solib_by_pc (eh_notify_callback_addr);
798*11efff7fSkettenis args.msym = msym;
799*11efff7fSkettenis args.return_val = 0;
800*11efff7fSkettenis
801*11efff7fSkettenis recurse++;
802*11efff7fSkettenis catch_errors (cover_find_stub_with_shl_get, &args, message,
803*11efff7fSkettenis RETURN_MASK_ALL);
804*11efff7fSkettenis eh_notify_callback_addr = args.return_val;
805*11efff7fSkettenis recurse--;
806*11efff7fSkettenis
807*11efff7fSkettenis deprecated_exception_catchpoints_are_fragile = 1;
808*11efff7fSkettenis
809*11efff7fSkettenis if (!eh_notify_callback_addr)
810*11efff7fSkettenis {
811*11efff7fSkettenis /* We can get here either if there is no plabel in the export list
812*11efff7fSkettenis for the main image, or if something strange happened (?) */
813*11efff7fSkettenis warning ("Couldn't find a plabel (indirect function label) for the exception callback.");
814*11efff7fSkettenis warning ("GDB will not be able to intercept exception events.");
815*11efff7fSkettenis return 0;
816*11efff7fSkettenis }
817*11efff7fSkettenis }
818*11efff7fSkettenis else
819*11efff7fSkettenis deprecated_exception_catchpoints_are_fragile = 0;
820*11efff7fSkettenis #endif
821*11efff7fSkettenis
822*11efff7fSkettenis /* Now, look for the breakpointable routine in end.o */
823*11efff7fSkettenis /* This should also be available in the SOM symbol dict. if end.o linked in */
824*11efff7fSkettenis msym = lookup_minimal_symbol (HP_ACC_EH_break, NULL, NULL);
825*11efff7fSkettenis if (msym)
826*11efff7fSkettenis {
827*11efff7fSkettenis eh_break_addr = SYMBOL_VALUE_ADDRESS (msym);
828*11efff7fSkettenis hp_cxx_exception_support = 1;
829*11efff7fSkettenis }
830*11efff7fSkettenis else
831*11efff7fSkettenis {
832*11efff7fSkettenis warning ("Unable to find exception callback routine to set breakpoint (%s).", HP_ACC_EH_break);
833*11efff7fSkettenis warning ("Suggest linking executable with -g (link in /opt/langtools/lib/end.o).");
834*11efff7fSkettenis warning ("GDB will be unable to intercept exception events.");
835*11efff7fSkettenis eh_break_addr = 0;
836*11efff7fSkettenis return 0;
837*11efff7fSkettenis }
838*11efff7fSkettenis
839*11efff7fSkettenis /* Next look for the catch enable flag provided in end.o */
840*11efff7fSkettenis sym = lookup_symbol (HP_ACC_EH_catch_catch, (struct block *) NULL,
841*11efff7fSkettenis VAR_DOMAIN, 0, (struct symtab **) NULL);
842*11efff7fSkettenis if (sym) /* sometimes present in debug info */
843*11efff7fSkettenis {
844*11efff7fSkettenis eh_catch_catch_addr = SYMBOL_VALUE_ADDRESS (sym);
845*11efff7fSkettenis hp_cxx_exception_support = 1;
846*11efff7fSkettenis }
847*11efff7fSkettenis else
848*11efff7fSkettenis /* otherwise look in SOM symbol dict. */
849*11efff7fSkettenis {
850*11efff7fSkettenis msym = lookup_minimal_symbol (HP_ACC_EH_catch_catch, NULL, NULL);
851*11efff7fSkettenis if (msym)
852*11efff7fSkettenis {
853*11efff7fSkettenis eh_catch_catch_addr = SYMBOL_VALUE_ADDRESS (msym);
854*11efff7fSkettenis hp_cxx_exception_support = 1;
855*11efff7fSkettenis }
856*11efff7fSkettenis else
857*11efff7fSkettenis {
858*11efff7fSkettenis warning ("Unable to enable interception of exception catches.");
859*11efff7fSkettenis warning ("Executable may not have been compiled debuggable with HP aCC.");
860*11efff7fSkettenis warning ("Suggest linking executable with -g (link in /opt/langtools/lib/end.o).");
861*11efff7fSkettenis return 0;
862*11efff7fSkettenis }
863*11efff7fSkettenis }
864*11efff7fSkettenis
865*11efff7fSkettenis /* Next look for the catch enable flag provided end.o */
866*11efff7fSkettenis sym = lookup_symbol (HP_ACC_EH_catch_catch, (struct block *) NULL,
867*11efff7fSkettenis VAR_DOMAIN, 0, (struct symtab **) NULL);
868*11efff7fSkettenis if (sym) /* sometimes present in debug info */
869*11efff7fSkettenis {
870*11efff7fSkettenis eh_catch_throw_addr = SYMBOL_VALUE_ADDRESS (sym);
871*11efff7fSkettenis hp_cxx_exception_support = 1;
872*11efff7fSkettenis }
873*11efff7fSkettenis else
874*11efff7fSkettenis /* otherwise look in SOM symbol dict. */
875*11efff7fSkettenis {
876*11efff7fSkettenis msym = lookup_minimal_symbol (HP_ACC_EH_catch_throw, NULL, NULL);
877*11efff7fSkettenis if (msym)
878*11efff7fSkettenis {
879*11efff7fSkettenis eh_catch_throw_addr = SYMBOL_VALUE_ADDRESS (msym);
880*11efff7fSkettenis hp_cxx_exception_support = 1;
881*11efff7fSkettenis }
882*11efff7fSkettenis else
883*11efff7fSkettenis {
884*11efff7fSkettenis warning ("Unable to enable interception of exception throws.");
885*11efff7fSkettenis warning ("Executable may not have been compiled debuggable with HP aCC.");
886*11efff7fSkettenis warning ("Suggest linking executable with -g (link in /opt/langtools/lib/end.o).");
887*11efff7fSkettenis return 0;
888*11efff7fSkettenis }
889*11efff7fSkettenis }
890*11efff7fSkettenis
891*11efff7fSkettenis /* Set the flags */
892*11efff7fSkettenis hp_cxx_exception_support = 2; /* everything worked so far */
893*11efff7fSkettenis hp_cxx_exception_support_initialized = 1;
894*11efff7fSkettenis deprecated_exception_support_initialized = 1;
895*11efff7fSkettenis
896*11efff7fSkettenis return 1;
897*11efff7fSkettenis }
898*11efff7fSkettenis
899*11efff7fSkettenis /* Target operation for enabling or disabling interception of
900*11efff7fSkettenis exception events.
901*11efff7fSkettenis KIND is either EX_EVENT_THROW or EX_EVENT_CATCH
902*11efff7fSkettenis ENABLE is either 0 (disable) or 1 (enable).
903*11efff7fSkettenis Return value is NULL if no support found;
904*11efff7fSkettenis -1 if something went wrong,
905*11efff7fSkettenis or a pointer to a symtab/line struct if the breakpointable
906*11efff7fSkettenis address was found. */
907*11efff7fSkettenis
908*11efff7fSkettenis struct symtab_and_line *
child_enable_exception_callback(enum exception_event_kind kind,int enable)909*11efff7fSkettenis child_enable_exception_callback (enum exception_event_kind kind, int enable)
910*11efff7fSkettenis {
911*11efff7fSkettenis char buf[4];
912*11efff7fSkettenis
913*11efff7fSkettenis if (!deprecated_exception_support_initialized
914*11efff7fSkettenis || !hp_cxx_exception_support_initialized)
915*11efff7fSkettenis if (!initialize_hp_cxx_exception_support ())
916*11efff7fSkettenis return NULL;
917*11efff7fSkettenis
918*11efff7fSkettenis switch (hp_cxx_exception_support)
919*11efff7fSkettenis {
920*11efff7fSkettenis case 0:
921*11efff7fSkettenis /* Assuming no HP support at all */
922*11efff7fSkettenis return NULL;
923*11efff7fSkettenis case 1:
924*11efff7fSkettenis /* HP support should be present, but something went wrong */
925*11efff7fSkettenis return (struct symtab_and_line *) -1; /* yuck! */
926*11efff7fSkettenis /* there may be other cases in the future */
927*11efff7fSkettenis }
928*11efff7fSkettenis
929*11efff7fSkettenis /* Set the EH hook to point to the callback routine */
930*11efff7fSkettenis store_unsigned_integer (buf, 4, enable ? eh_notify_callback_addr : 0); /* FIXME 32x64 problem */
931*11efff7fSkettenis /* pai: (temp) FIXME should there be a pack operation first? */
932*11efff7fSkettenis if (target_write_memory (eh_notify_hook_addr, buf, 4)) /* FIXME 32x64 problem */
933*11efff7fSkettenis {
934*11efff7fSkettenis warning ("Could not write to target memory for exception event callback.");
935*11efff7fSkettenis warning ("Interception of exception events may not work.");
936*11efff7fSkettenis return (struct symtab_and_line *) -1;
937*11efff7fSkettenis }
938*11efff7fSkettenis if (enable)
939*11efff7fSkettenis {
940*11efff7fSkettenis /* Ensure that __d_pid is set up correctly -- end.c code checks this. :-( */
941*11efff7fSkettenis if (PIDGET (inferior_ptid) > 0)
942*11efff7fSkettenis {
943*11efff7fSkettenis if (setup_d_pid_in_inferior ())
944*11efff7fSkettenis return (struct symtab_and_line *) -1;
945*11efff7fSkettenis }
946*11efff7fSkettenis else
947*11efff7fSkettenis {
948*11efff7fSkettenis warning ("Internal error: Invalid inferior pid? Cannot intercept exception events.");
949*11efff7fSkettenis return (struct symtab_and_line *) -1;
950*11efff7fSkettenis }
951*11efff7fSkettenis }
952*11efff7fSkettenis
953*11efff7fSkettenis switch (kind)
954*11efff7fSkettenis {
955*11efff7fSkettenis case EX_EVENT_THROW:
956*11efff7fSkettenis store_unsigned_integer (buf, 4, enable ? 1 : 0);
957*11efff7fSkettenis if (target_write_memory (eh_catch_throw_addr, buf, 4)) /* FIXME 32x64? */
958*11efff7fSkettenis {
959*11efff7fSkettenis warning ("Couldn't enable exception throw interception.");
960*11efff7fSkettenis return (struct symtab_and_line *) -1;
961*11efff7fSkettenis }
962*11efff7fSkettenis break;
963*11efff7fSkettenis case EX_EVENT_CATCH:
964*11efff7fSkettenis store_unsigned_integer (buf, 4, enable ? 1 : 0);
965*11efff7fSkettenis if (target_write_memory (eh_catch_catch_addr, buf, 4)) /* FIXME 32x64? */
966*11efff7fSkettenis {
967*11efff7fSkettenis warning ("Couldn't enable exception catch interception.");
968*11efff7fSkettenis return (struct symtab_and_line *) -1;
969*11efff7fSkettenis }
970*11efff7fSkettenis break;
971*11efff7fSkettenis default:
972*11efff7fSkettenis error ("Request to enable unknown or unsupported exception event.");
973*11efff7fSkettenis }
974*11efff7fSkettenis
975*11efff7fSkettenis /* Copy break address into new sal struct, malloc'ing if needed. */
976*11efff7fSkettenis if (!break_callback_sal)
977*11efff7fSkettenis {
978*11efff7fSkettenis break_callback_sal = (struct symtab_and_line *) xmalloc (sizeof (struct symtab_and_line));
979*11efff7fSkettenis }
980*11efff7fSkettenis init_sal (break_callback_sal);
981*11efff7fSkettenis break_callback_sal->symtab = NULL;
982*11efff7fSkettenis break_callback_sal->pc = eh_break_addr;
983*11efff7fSkettenis break_callback_sal->line = 0;
984*11efff7fSkettenis break_callback_sal->end = eh_break_addr;
985*11efff7fSkettenis
986*11efff7fSkettenis return break_callback_sal;
987*11efff7fSkettenis }
988*11efff7fSkettenis
989*11efff7fSkettenis /* Record some information about the current exception event */
990*11efff7fSkettenis static struct exception_event_record current_ex_event;
991*11efff7fSkettenis /* Convenience struct */
992*11efff7fSkettenis static struct symtab_and_line null_symtab_and_line =
993*11efff7fSkettenis {NULL, 0, 0, 0};
994*11efff7fSkettenis
995*11efff7fSkettenis /* Report current exception event. Returns a pointer to a record
996*11efff7fSkettenis that describes the kind of the event, where it was thrown from,
997*11efff7fSkettenis and where it will be caught. More information may be reported
998*11efff7fSkettenis in the future */
999*11efff7fSkettenis struct exception_event_record *
child_get_current_exception_event(void)1000*11efff7fSkettenis child_get_current_exception_event (void)
1001*11efff7fSkettenis {
1002*11efff7fSkettenis CORE_ADDR event_kind;
1003*11efff7fSkettenis CORE_ADDR throw_addr;
1004*11efff7fSkettenis CORE_ADDR catch_addr;
1005*11efff7fSkettenis struct frame_info *fi, *curr_frame;
1006*11efff7fSkettenis int level = 1;
1007*11efff7fSkettenis
1008*11efff7fSkettenis curr_frame = get_current_frame ();
1009*11efff7fSkettenis if (!curr_frame)
1010*11efff7fSkettenis return (struct exception_event_record *) NULL;
1011*11efff7fSkettenis
1012*11efff7fSkettenis /* Go up one frame to __d_eh_notify_callback, because at the
1013*11efff7fSkettenis point when this code is executed, there's garbage in the
1014*11efff7fSkettenis arguments of __d_eh_break. */
1015*11efff7fSkettenis fi = find_relative_frame (curr_frame, &level);
1016*11efff7fSkettenis if (level != 0)
1017*11efff7fSkettenis return (struct exception_event_record *) NULL;
1018*11efff7fSkettenis
1019*11efff7fSkettenis select_frame (fi);
1020*11efff7fSkettenis
1021*11efff7fSkettenis /* Read in the arguments */
1022*11efff7fSkettenis /* __d_eh_notify_callback() is called with 3 arguments:
1023*11efff7fSkettenis 1. event kind catch or throw
1024*11efff7fSkettenis 2. the target address if known
1025*11efff7fSkettenis 3. a flag -- not sure what this is. pai/1997-07-17 */
1026*11efff7fSkettenis event_kind = read_register (HPPA_ARG0_REGNUM);
1027*11efff7fSkettenis catch_addr = read_register (HPPA_ARG1_REGNUM);
1028*11efff7fSkettenis
1029*11efff7fSkettenis /* Now go down to a user frame */
1030*11efff7fSkettenis /* For a throw, __d_eh_break is called by
1031*11efff7fSkettenis __d_eh_notify_callback which is called by
1032*11efff7fSkettenis __notify_throw which is called
1033*11efff7fSkettenis from user code.
1034*11efff7fSkettenis For a catch, __d_eh_break is called by
1035*11efff7fSkettenis __d_eh_notify_callback which is called by
1036*11efff7fSkettenis <stackwalking stuff> which is called by
1037*11efff7fSkettenis __throw__<stuff> or __rethrow_<stuff> which is called
1038*11efff7fSkettenis from user code. */
1039*11efff7fSkettenis /* FIXME: Don't use such magic numbers; search for the frames */
1040*11efff7fSkettenis level = (event_kind == EX_EVENT_THROW) ? 3 : 4;
1041*11efff7fSkettenis fi = find_relative_frame (curr_frame, &level);
1042*11efff7fSkettenis if (level != 0)
1043*11efff7fSkettenis return (struct exception_event_record *) NULL;
1044*11efff7fSkettenis
1045*11efff7fSkettenis select_frame (fi);
1046*11efff7fSkettenis throw_addr = get_frame_pc (fi);
1047*11efff7fSkettenis
1048*11efff7fSkettenis /* Go back to original (top) frame */
1049*11efff7fSkettenis select_frame (curr_frame);
1050*11efff7fSkettenis
1051*11efff7fSkettenis current_ex_event.kind = (enum exception_event_kind) event_kind;
1052*11efff7fSkettenis current_ex_event.throw_sal = find_pc_line (throw_addr, 1);
1053*11efff7fSkettenis current_ex_event.catch_sal = find_pc_line (catch_addr, 1);
1054*11efff7fSkettenis
1055*11efff7fSkettenis return ¤t_ex_event;
1056*11efff7fSkettenis }
1057*11efff7fSkettenis
1058*11efff7fSkettenis /* Signal frames. */
1059*11efff7fSkettenis struct hppa_hpux_sigtramp_unwind_cache
1060*11efff7fSkettenis {
1061*11efff7fSkettenis CORE_ADDR base;
1062*11efff7fSkettenis struct trad_frame_saved_reg *saved_regs;
1063*11efff7fSkettenis };
1064*11efff7fSkettenis
1065*11efff7fSkettenis static int hppa_hpux_tramp_reg[] = {
1066*11efff7fSkettenis HPPA_SAR_REGNUM,
1067*11efff7fSkettenis HPPA_PCOQ_HEAD_REGNUM,
1068*11efff7fSkettenis HPPA_PCSQ_HEAD_REGNUM,
1069*11efff7fSkettenis HPPA_PCOQ_TAIL_REGNUM,
1070*11efff7fSkettenis HPPA_PCSQ_TAIL_REGNUM,
1071*11efff7fSkettenis HPPA_EIEM_REGNUM,
1072*11efff7fSkettenis HPPA_IIR_REGNUM,
1073*11efff7fSkettenis HPPA_ISR_REGNUM,
1074*11efff7fSkettenis HPPA_IOR_REGNUM,
1075*11efff7fSkettenis HPPA_IPSW_REGNUM,
1076*11efff7fSkettenis -1,
1077*11efff7fSkettenis HPPA_SR4_REGNUM,
1078*11efff7fSkettenis HPPA_SR4_REGNUM + 1,
1079*11efff7fSkettenis HPPA_SR4_REGNUM + 2,
1080*11efff7fSkettenis HPPA_SR4_REGNUM + 3,
1081*11efff7fSkettenis HPPA_SR4_REGNUM + 4,
1082*11efff7fSkettenis HPPA_SR4_REGNUM + 5,
1083*11efff7fSkettenis HPPA_SR4_REGNUM + 6,
1084*11efff7fSkettenis HPPA_SR4_REGNUM + 7,
1085*11efff7fSkettenis HPPA_RCR_REGNUM,
1086*11efff7fSkettenis HPPA_PID0_REGNUM,
1087*11efff7fSkettenis HPPA_PID1_REGNUM,
1088*11efff7fSkettenis HPPA_CCR_REGNUM,
1089*11efff7fSkettenis HPPA_PID2_REGNUM,
1090*11efff7fSkettenis HPPA_PID3_REGNUM,
1091*11efff7fSkettenis HPPA_TR0_REGNUM,
1092*11efff7fSkettenis HPPA_TR0_REGNUM + 1,
1093*11efff7fSkettenis HPPA_TR0_REGNUM + 2,
1094*11efff7fSkettenis HPPA_CR27_REGNUM
1095*11efff7fSkettenis };
1096*11efff7fSkettenis
1097*11efff7fSkettenis static struct hppa_hpux_sigtramp_unwind_cache *
hppa_hpux_sigtramp_frame_unwind_cache(struct frame_info * next_frame,void ** this_cache)1098*11efff7fSkettenis hppa_hpux_sigtramp_frame_unwind_cache (struct frame_info *next_frame,
1099*11efff7fSkettenis void **this_cache)
1100*11efff7fSkettenis
1101*11efff7fSkettenis {
1102*11efff7fSkettenis struct gdbarch *gdbarch = get_frame_arch (next_frame);
1103*11efff7fSkettenis struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
1104*11efff7fSkettenis struct hppa_hpux_sigtramp_unwind_cache *info;
1105*11efff7fSkettenis unsigned int flag;
1106*11efff7fSkettenis CORE_ADDR sp, scptr;
1107*11efff7fSkettenis int i, incr, off, szoff;
1108*11efff7fSkettenis
1109*11efff7fSkettenis if (*this_cache)
1110*11efff7fSkettenis return *this_cache;
1111*11efff7fSkettenis
1112*11efff7fSkettenis info = FRAME_OBSTACK_ZALLOC (struct hppa_hpux_sigtramp_unwind_cache);
1113*11efff7fSkettenis *this_cache = info;
1114*11efff7fSkettenis info->saved_regs = trad_frame_alloc_saved_regs (next_frame);
1115*11efff7fSkettenis
1116*11efff7fSkettenis sp = frame_unwind_register_unsigned (next_frame, HPPA_SP_REGNUM);
1117*11efff7fSkettenis
1118*11efff7fSkettenis scptr = sp - 1352;
1119*11efff7fSkettenis off = scptr;
1120*11efff7fSkettenis
1121*11efff7fSkettenis /* See /usr/include/machine/save_state.h for the structure of the save_state_t
1122*11efff7fSkettenis structure. */
1123*11efff7fSkettenis
1124*11efff7fSkettenis flag = read_memory_unsigned_integer(scptr, 4);
1125*11efff7fSkettenis
1126*11efff7fSkettenis if (!(flag & 0x40))
1127*11efff7fSkettenis {
1128*11efff7fSkettenis /* Narrow registers. */
1129*11efff7fSkettenis off = scptr + offsetof (save_state_t, ss_narrow);
1130*11efff7fSkettenis incr = 4;
1131*11efff7fSkettenis szoff = 0;
1132*11efff7fSkettenis }
1133*11efff7fSkettenis else
1134*11efff7fSkettenis {
1135*11efff7fSkettenis /* Wide registers. */
1136*11efff7fSkettenis off = scptr + offsetof (save_state_t, ss_wide) + 8;
1137*11efff7fSkettenis incr = 8;
1138*11efff7fSkettenis szoff = (tdep->bytes_per_address == 4 ? 4 : 0);
1139*11efff7fSkettenis }
1140*11efff7fSkettenis
1141*11efff7fSkettenis for (i = 1; i < 32; i++)
1142*11efff7fSkettenis {
1143*11efff7fSkettenis info->saved_regs[HPPA_R0_REGNUM + i].addr = off + szoff;
1144*11efff7fSkettenis off += incr;
1145*11efff7fSkettenis }
1146*11efff7fSkettenis
1147*11efff7fSkettenis for (i = 0;
1148*11efff7fSkettenis i < sizeof(hppa_hpux_tramp_reg) / sizeof(hppa_hpux_tramp_reg[0]);
1149*11efff7fSkettenis i++)
1150*11efff7fSkettenis {
1151*11efff7fSkettenis if (hppa_hpux_tramp_reg[i] > 0)
1152*11efff7fSkettenis info->saved_regs[hppa_hpux_tramp_reg[i]].addr = off + szoff;
1153*11efff7fSkettenis off += incr;
1154*11efff7fSkettenis }
1155*11efff7fSkettenis
1156*11efff7fSkettenis /* TODO: fp regs */
1157*11efff7fSkettenis
1158*11efff7fSkettenis info->base = frame_unwind_register_unsigned (next_frame, HPPA_SP_REGNUM);
1159*11efff7fSkettenis
1160*11efff7fSkettenis return info;
1161*11efff7fSkettenis }
1162*11efff7fSkettenis
1163*11efff7fSkettenis static void
hppa_hpux_sigtramp_frame_this_id(struct frame_info * next_frame,void ** this_prologue_cache,struct frame_id * this_id)1164*11efff7fSkettenis hppa_hpux_sigtramp_frame_this_id (struct frame_info *next_frame,
1165*11efff7fSkettenis void **this_prologue_cache,
1166*11efff7fSkettenis struct frame_id *this_id)
1167*11efff7fSkettenis {
1168*11efff7fSkettenis struct hppa_hpux_sigtramp_unwind_cache *info
1169*11efff7fSkettenis = hppa_hpux_sigtramp_frame_unwind_cache (next_frame, this_prologue_cache);
1170*11efff7fSkettenis *this_id = frame_id_build (info->base, frame_pc_unwind (next_frame));
1171*11efff7fSkettenis }
1172*11efff7fSkettenis
1173*11efff7fSkettenis static void
hppa_hpux_sigtramp_frame_prev_register(struct frame_info * next_frame,void ** this_prologue_cache,int regnum,int * optimizedp,enum lval_type * lvalp,CORE_ADDR * addrp,int * realnump,void * valuep)1174*11efff7fSkettenis hppa_hpux_sigtramp_frame_prev_register (struct frame_info *next_frame,
1175*11efff7fSkettenis void **this_prologue_cache,
1176*11efff7fSkettenis int regnum, int *optimizedp,
1177*11efff7fSkettenis enum lval_type *lvalp,
1178*11efff7fSkettenis CORE_ADDR *addrp,
1179*11efff7fSkettenis int *realnump, void *valuep)
1180*11efff7fSkettenis {
1181*11efff7fSkettenis struct hppa_hpux_sigtramp_unwind_cache *info
1182*11efff7fSkettenis = hppa_hpux_sigtramp_frame_unwind_cache (next_frame, this_prologue_cache);
1183*11efff7fSkettenis hppa_frame_prev_register_helper (next_frame, info->saved_regs, regnum,
1184*11efff7fSkettenis optimizedp, lvalp, addrp, realnump, valuep);
1185*11efff7fSkettenis }
1186*11efff7fSkettenis
1187*11efff7fSkettenis static const struct frame_unwind hppa_hpux_sigtramp_frame_unwind = {
1188*11efff7fSkettenis SIGTRAMP_FRAME,
1189*11efff7fSkettenis hppa_hpux_sigtramp_frame_this_id,
1190*11efff7fSkettenis hppa_hpux_sigtramp_frame_prev_register
1191*11efff7fSkettenis };
1192*11efff7fSkettenis
1193*11efff7fSkettenis static const struct frame_unwind *
hppa_hpux_sigtramp_unwind_sniffer(struct frame_info * next_frame)1194*11efff7fSkettenis hppa_hpux_sigtramp_unwind_sniffer (struct frame_info *next_frame)
1195*11efff7fSkettenis {
1196*11efff7fSkettenis CORE_ADDR pc = frame_pc_unwind (next_frame);
1197*11efff7fSkettenis char *name;
1198*11efff7fSkettenis
1199*11efff7fSkettenis find_pc_partial_function (pc, &name, NULL, NULL);
1200*11efff7fSkettenis
1201*11efff7fSkettenis if (name && strcmp(name, "_sigreturn") == 0)
1202*11efff7fSkettenis return &hppa_hpux_sigtramp_frame_unwind;
1203*11efff7fSkettenis
1204*11efff7fSkettenis return NULL;
1205*11efff7fSkettenis }
1206*11efff7fSkettenis
1207*11efff7fSkettenis static CORE_ADDR
hppa_hpux_som_find_global_pointer(struct value * function)1208*11efff7fSkettenis hppa_hpux_som_find_global_pointer (struct value *function)
1209*11efff7fSkettenis {
1210*11efff7fSkettenis CORE_ADDR faddr;
1211*11efff7fSkettenis
1212*11efff7fSkettenis faddr = value_as_address (function);
1213*11efff7fSkettenis
1214*11efff7fSkettenis /* Is this a plabel? If so, dereference it to get the gp value. */
1215*11efff7fSkettenis if (faddr & 2)
1216*11efff7fSkettenis {
1217*11efff7fSkettenis int status;
1218*11efff7fSkettenis char buf[4];
1219*11efff7fSkettenis
1220*11efff7fSkettenis faddr &= ~3;
1221*11efff7fSkettenis
1222*11efff7fSkettenis status = target_read_memory (faddr + 4, buf, sizeof (buf));
1223*11efff7fSkettenis if (status == 0)
1224*11efff7fSkettenis return extract_unsigned_integer (buf, sizeof (buf));
1225*11efff7fSkettenis }
1226*11efff7fSkettenis
1227*11efff7fSkettenis return som_solib_get_got_by_pc (faddr);
1228*11efff7fSkettenis }
1229*11efff7fSkettenis
1230*11efff7fSkettenis static CORE_ADDR
hppa_hpux_push_dummy_code(struct gdbarch * gdbarch,CORE_ADDR sp,CORE_ADDR funcaddr,int using_gcc,struct value ** args,int nargs,struct type * value_type,CORE_ADDR * real_pc,CORE_ADDR * bp_addr)1231*11efff7fSkettenis hppa_hpux_push_dummy_code (struct gdbarch *gdbarch, CORE_ADDR sp,
1232*11efff7fSkettenis CORE_ADDR funcaddr, int using_gcc,
1233*11efff7fSkettenis struct value **args, int nargs,
1234*11efff7fSkettenis struct type *value_type,
1235*11efff7fSkettenis CORE_ADDR *real_pc, CORE_ADDR *bp_addr)
1236*11efff7fSkettenis {
1237*11efff7fSkettenis /* FIXME: tausq/2004-06-09: This needs much more testing. It is broken
1238*11efff7fSkettenis for pa64, but we should be able to get it to work with a little bit
1239*11efff7fSkettenis of work. gdb-6.1 has a lot of code to handle various cases; I've tried to
1240*11efff7fSkettenis simplify it and avoid compile-time conditionals. */
1241*11efff7fSkettenis
1242*11efff7fSkettenis /* On HPUX, functions in the main executable and in libraries can be located
1243*11efff7fSkettenis in different spaces. In order for us to be able to select the right
1244*11efff7fSkettenis space for the function call, we need to go through an instruction seqeunce
1245*11efff7fSkettenis to select the right space for the target function, call it, and then
1246*11efff7fSkettenis restore the space on return.
1247*11efff7fSkettenis
1248*11efff7fSkettenis There are two helper routines that can be used for this task -- if
1249*11efff7fSkettenis an application is linked with gcc, it will contain a __gcc_plt_call
1250*11efff7fSkettenis helper function. __gcc_plt_call, when passed the entry point of an
1251*11efff7fSkettenis import stub, will do the necessary space setting/restoration for the
1252*11efff7fSkettenis target function.
1253*11efff7fSkettenis
1254*11efff7fSkettenis For programs that are compiled/linked with the HP compiler, a similar
1255*11efff7fSkettenis function called __d_plt_call exists; __d_plt_call expects a PLABEL instead
1256*11efff7fSkettenis of an import stub as an argument.
1257*11efff7fSkettenis
1258*11efff7fSkettenis // *INDENT-OFF*
1259*11efff7fSkettenis To summarize, the call flow is:
1260*11efff7fSkettenis current function -> dummy frame -> __gcc_plt_call (import stub)
1261*11efff7fSkettenis -> target function
1262*11efff7fSkettenis or
1263*11efff7fSkettenis current function -> dummy frame -> __d_plt_call (plabel)
1264*11efff7fSkettenis -> target function
1265*11efff7fSkettenis // *INDENT-ON*
1266*11efff7fSkettenis
1267*11efff7fSkettenis In general the "funcaddr" argument passed to push_dummy_code is the actual
1268*11efff7fSkettenis entry point of the target function. For __gcc_plt_call, we need to
1269*11efff7fSkettenis locate the import stub for the corresponding function. Failing that,
1270*11efff7fSkettenis we construct a dummy "import stub" on the stack to pass as an argument.
1271*11efff7fSkettenis For __d_plt_call, we similarly synthesize a PLABEL on the stack to
1272*11efff7fSkettenis pass to the helper function.
1273*11efff7fSkettenis
1274*11efff7fSkettenis An additional twist is that, in order for us to restore the space register
1275*11efff7fSkettenis to its starting state, we need __gcc_plt_call/__d_plt_call to return
1276*11efff7fSkettenis to the instruction where we started the call. However, if we put
1277*11efff7fSkettenis the breakpoint there, gdb will complain because it will find two
1278*11efff7fSkettenis frames on the stack with the same (sp, pc) (with the dummy frame in
1279*11efff7fSkettenis between). Currently, we set the return pointer to (pc - 4) of the
1280*11efff7fSkettenis current function. FIXME: This is not an ideal solution; possibly if the
1281*11efff7fSkettenis current pc is at the beginning of a page, this will cause a page fault.
1282*11efff7fSkettenis Need to understand this better and figure out a better way to fix it. */
1283*11efff7fSkettenis
1284*11efff7fSkettenis struct minimal_symbol *sym;
1285*11efff7fSkettenis
1286*11efff7fSkettenis /* Nonzero if we will use GCC's PLT call routine. This routine must be
1287*11efff7fSkettenis passed an import stub, not a PLABEL. It is also necessary to get %r19
1288*11efff7fSkettenis before performing the call. (This is done by push_dummy_call.) */
1289*11efff7fSkettenis int use_gcc_plt_call = 1;
1290*11efff7fSkettenis
1291*11efff7fSkettenis /* See if __gcc_plt_call is available; if not we will use the HP version
1292*11efff7fSkettenis instead. */
1293*11efff7fSkettenis sym = lookup_minimal_symbol ("__gcc_plt_call", NULL, NULL);
1294*11efff7fSkettenis if (sym == NULL)
1295*11efff7fSkettenis use_gcc_plt_call = 0;
1296*11efff7fSkettenis
1297*11efff7fSkettenis /* If using __gcc_plt_call, we need to make sure we pass in an import
1298*11efff7fSkettenis stub. funcaddr can be pointing to an export stub or a real function,
1299*11efff7fSkettenis so we try to resolve it to the import stub. */
1300*11efff7fSkettenis if (use_gcc_plt_call)
1301*11efff7fSkettenis {
1302*11efff7fSkettenis struct objfile *objfile;
1303*11efff7fSkettenis struct minimal_symbol *funsym, *stubsym;
1304*11efff7fSkettenis CORE_ADDR stubaddr = 0;
1305*11efff7fSkettenis
1306*11efff7fSkettenis funsym = lookup_minimal_symbol_by_pc (funcaddr);
1307*11efff7fSkettenis if (!funsym)
1308*11efff7fSkettenis error ("Unable to find symbol for target function.\n");
1309*11efff7fSkettenis
1310*11efff7fSkettenis ALL_OBJFILES (objfile)
1311*11efff7fSkettenis {
1312*11efff7fSkettenis stubsym = lookup_minimal_symbol_solib_trampoline
1313*11efff7fSkettenis (SYMBOL_LINKAGE_NAME (funsym), objfile);
1314*11efff7fSkettenis
1315*11efff7fSkettenis if (stubsym)
1316*11efff7fSkettenis {
1317*11efff7fSkettenis struct unwind_table_entry *u;
1318*11efff7fSkettenis
1319*11efff7fSkettenis u = find_unwind_entry (SYMBOL_VALUE (stubsym));
1320*11efff7fSkettenis if (u == NULL
1321*11efff7fSkettenis || (u->stub_unwind.stub_type != IMPORT
1322*11efff7fSkettenis && u->stub_unwind.stub_type != IMPORT_SHLIB))
1323*11efff7fSkettenis continue;
1324*11efff7fSkettenis
1325*11efff7fSkettenis stubaddr = SYMBOL_VALUE (stubsym);
1326*11efff7fSkettenis
1327*11efff7fSkettenis /* If we found an IMPORT stub, then we can stop searching;
1328*11efff7fSkettenis if we found an IMPORT_SHLIB, we want to continue the search
1329*11efff7fSkettenis in the hopes that we will find an IMPORT stub. */
1330*11efff7fSkettenis if (u->stub_unwind.stub_type == IMPORT)
1331*11efff7fSkettenis break;
1332*11efff7fSkettenis }
1333*11efff7fSkettenis }
1334*11efff7fSkettenis
1335*11efff7fSkettenis if (stubaddr != 0)
1336*11efff7fSkettenis {
1337*11efff7fSkettenis /* Argument to __gcc_plt_call is passed in r22. */
1338*11efff7fSkettenis regcache_cooked_write_unsigned (current_regcache, 22, stubaddr);
1339*11efff7fSkettenis }
1340*11efff7fSkettenis else
1341*11efff7fSkettenis {
1342*11efff7fSkettenis /* No import stub found; let's synthesize one. */
1343*11efff7fSkettenis
1344*11efff7fSkettenis /* ldsid %r21, %r1 */
1345*11efff7fSkettenis write_memory_unsigned_integer (sp, 4, 0x02a010a1);
1346*11efff7fSkettenis /* mtsp %r1,%sr0 */
1347*11efff7fSkettenis write_memory_unsigned_integer (sp + 4, 4, 0x00011820);
1348*11efff7fSkettenis /* be 0(%sr0, %r21) */
1349*11efff7fSkettenis write_memory_unsigned_integer (sp + 8, 4, 0xe2a00000);
1350*11efff7fSkettenis /* nop */
1351*11efff7fSkettenis write_memory_unsigned_integer (sp + 12, 4, 0x08000240);
1352*11efff7fSkettenis
1353*11efff7fSkettenis regcache_cooked_write_unsigned (current_regcache, 21, funcaddr);
1354*11efff7fSkettenis regcache_cooked_write_unsigned (current_regcache, 22, sp);
1355*11efff7fSkettenis }
1356*11efff7fSkettenis
1357*11efff7fSkettenis /* We set the breakpoint address and r31 to (close to) where the current
1358*11efff7fSkettenis pc is; when __gcc_plt_call returns, it will restore pcsqh to the
1359*11efff7fSkettenis current value based on this. The -4 is needed for frame unwinding
1360*11efff7fSkettenis to work properly -- we need to land in a different function than
1361*11efff7fSkettenis the current function. */
1362*11efff7fSkettenis *bp_addr = (read_register (HPPA_PCOQ_HEAD_REGNUM) & ~3) - 4;
1363*11efff7fSkettenis regcache_cooked_write_unsigned (current_regcache, 31, *bp_addr);
1364*11efff7fSkettenis
1365*11efff7fSkettenis /* Continue from __gcc_plt_call. */
1366*11efff7fSkettenis *real_pc = SYMBOL_VALUE (sym);
1367*11efff7fSkettenis }
1368*11efff7fSkettenis else
1369*11efff7fSkettenis {
1370*11efff7fSkettenis unsigned int gp;
1371*11efff7fSkettenis
1372*11efff7fSkettenis /* Use __d_plt_call as a fallback; __d_plt_call expects to be called
1373*11efff7fSkettenis with a plabel, so we need to build one. */
1374*11efff7fSkettenis
1375*11efff7fSkettenis sym = lookup_minimal_symbol ("__d_plt_call", NULL, NULL);
1376*11efff7fSkettenis if (sym == NULL)
1377*11efff7fSkettenis error("Can't find an address for __d_plt_call or __gcc_plt_call "
1378*11efff7fSkettenis "trampoline\nSuggest linking executable with -g or compiling "
1379*11efff7fSkettenis "with gcc.");
1380*11efff7fSkettenis
1381*11efff7fSkettenis gp = gdbarch_tdep (gdbarch)->find_global_pointer (funcaddr);
1382*11efff7fSkettenis write_memory_unsigned_integer (sp, 4, funcaddr);
1383*11efff7fSkettenis write_memory_unsigned_integer (sp + 4, 4, gp);
1384*11efff7fSkettenis
1385*11efff7fSkettenis /* plabel is passed in r22 */
1386*11efff7fSkettenis regcache_cooked_write_unsigned (current_regcache, 22, sp);
1387*11efff7fSkettenis }
1388*11efff7fSkettenis
1389*11efff7fSkettenis /* Pushed one stack frame, which has to be 64-byte aligned. */
1390*11efff7fSkettenis sp += 64;
1391*11efff7fSkettenis
1392*11efff7fSkettenis return sp;
1393*11efff7fSkettenis }
1394*11efff7fSkettenis
1395*11efff7fSkettenis static void
hppa_hpux_inferior_created(struct target_ops * objfile,int from_tty)1396*11efff7fSkettenis hppa_hpux_inferior_created (struct target_ops *objfile, int from_tty)
1397*11efff7fSkettenis {
1398*11efff7fSkettenis /* Some HP-UX related globals to clear when a new "main"
1399*11efff7fSkettenis symbol file is loaded. HP-specific. */
1400*11efff7fSkettenis deprecated_hp_som_som_object_present = 0;
1401*11efff7fSkettenis hp_cxx_exception_support_initialized = 0;
1402b725ae77Skettenis }
1403b725ae77Skettenis
1404b725ae77Skettenis static void
hppa_hpux_init_abi(struct gdbarch_info info,struct gdbarch * gdbarch)1405b725ae77Skettenis hppa_hpux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
1406b725ae77Skettenis {
1407*11efff7fSkettenis struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
1408*11efff7fSkettenis
1409*11efff7fSkettenis if (tdep->bytes_per_address == 4)
1410*11efff7fSkettenis set_gdbarch_in_solib_call_trampoline (gdbarch,
1411*11efff7fSkettenis hppa32_hpux_in_solib_call_trampoline);
1412*11efff7fSkettenis else
1413*11efff7fSkettenis set_gdbarch_in_solib_call_trampoline (gdbarch,
1414*11efff7fSkettenis hppa64_hpux_in_solib_call_trampoline);
1415*11efff7fSkettenis
1416*11efff7fSkettenis set_gdbarch_in_solib_return_trampoline (gdbarch,
1417*11efff7fSkettenis hppa_hpux_in_solib_return_trampoline);
1418*11efff7fSkettenis set_gdbarch_skip_trampoline_code (gdbarch, hppa_hpux_skip_trampoline_code);
1419*11efff7fSkettenis
1420*11efff7fSkettenis set_gdbarch_push_dummy_code (gdbarch, hppa_hpux_push_dummy_code);
1421*11efff7fSkettenis set_gdbarch_call_dummy_location (gdbarch, ON_STACK);
1422*11efff7fSkettenis
1423*11efff7fSkettenis frame_unwind_append_sniffer (gdbarch, hppa_hpux_sigtramp_unwind_sniffer);
1424*11efff7fSkettenis
1425*11efff7fSkettenis observer_attach_inferior_created (hppa_hpux_inferior_created);
1426b725ae77Skettenis }
1427b725ae77Skettenis
1428b725ae77Skettenis static void
hppa_hpux_som_init_abi(struct gdbarch_info info,struct gdbarch * gdbarch)1429b725ae77Skettenis hppa_hpux_som_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
1430b725ae77Skettenis {
1431*11efff7fSkettenis struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
1432*11efff7fSkettenis
1433*11efff7fSkettenis tdep->is_elf = 0;
1434*11efff7fSkettenis
1435*11efff7fSkettenis tdep->find_global_pointer = hppa_hpux_som_find_global_pointer;
1436b725ae77Skettenis hppa_hpux_init_abi (info, gdbarch);
1437b725ae77Skettenis }
1438b725ae77Skettenis
1439b725ae77Skettenis static void
hppa_hpux_elf_init_abi(struct gdbarch_info info,struct gdbarch * gdbarch)1440b725ae77Skettenis hppa_hpux_elf_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
1441b725ae77Skettenis {
1442*11efff7fSkettenis struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
1443*11efff7fSkettenis
1444*11efff7fSkettenis tdep->is_elf = 1;
1445b725ae77Skettenis hppa_hpux_init_abi (info, gdbarch);
1446b725ae77Skettenis }
1447b725ae77Skettenis
1448b725ae77Skettenis void
_initialize_hppa_hpux_tdep(void)1449b725ae77Skettenis _initialize_hppa_hpux_tdep (void)
1450b725ae77Skettenis {
1451b725ae77Skettenis gdbarch_register_osabi (bfd_arch_hppa, 0, GDB_OSABI_HPUX_SOM,
1452b725ae77Skettenis hppa_hpux_som_init_abi);
1453b725ae77Skettenis gdbarch_register_osabi (bfd_arch_hppa, bfd_mach_hppa20w, GDB_OSABI_HPUX_ELF,
1454b725ae77Skettenis hppa_hpux_elf_init_abi);
1455b725ae77Skettenis }
1456