1 /* @(#)getfp.c	1.14 03/07/13 Copyright 1988-2003 J. Schilling */
2 /*
3  *	Get frame pointer
4  *
5  *	Copyright (c) 1988-2003 J. Schilling
6  */
7 /*
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2, or (at your option)
11  * any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License along with
19  * this program; see the file COPYING.  If not, write to the Free Software
20  * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21  */
22 
23 #include <mconfig.h>
24 #include <standard.h>
25 #include <schily.h>
26 
27 #ifndef	IS_AVOFFSET
28 /*
29  * We usually don't like to compile a getfp() that returns junk data in case
30  * we cannot scan the stack.
31  * The only way to find this out is by including avoffset.h. Unfortunately, we
32  * need to be able to use getfp() from avoffset.c in order to check if the
33  * return value is usable or junk. To be able to do this, we include getfp.c
34  * from avoffset.c and define IS_AVOFFSET before.
35  */
36 #include <avoffset.h>
37 
38 #if	!defined(AV_OFFSET) || !defined(FP_INDIR)
39 #	ifdef	HAVE_SCANSTACK
40 #	undef	HAVE_SCANSTACK
41 #	endif
42 #endif
43 #endif
44 
45 #ifdef	HAVE_SCANSTACK
46 #include <stkframe.h>
47 
48 #define	MAXWINDOWS	32
49 #define	NWINDOWS	7
50 
51 #if defined(sparc) && defined(__GNUC__)
52 #	define	FP_OFF		0x10	/* some strange things on sparc gcc */
53 #else
54 #	define	FP_OFF		0
55 #endif
56 
57 EXPORT	void	**___fpoff	__PR((char *cp));
58 
59 EXPORT __noinline void **
getfp()60 getfp()
61 {
62 		long	**dummy[1];
63 
64 #ifdef	sparc
65 	flush_reg_windows(MAXWINDOWS-2);
66 #endif
67 	return ((void **)((struct frame *)___fpoff((char *)&dummy[0]))->fr_savfp);
68 }
69 
70 /*
71  * Don't make it static to avoid inline optimization.
72  *
73  * We need this function to fool GCCs check for returning addresses
74  * from outside the functions local address space.
75  */
76 EXPORT __noinline void **
___fpoff(cp)77 ___fpoff(cp)
78 	char	*cp;
79 {
80 	long ***lp;
81 
82 	lp = (long ***)(cp + FP_OFF);
83 	lp++;
84 	return ((void **)lp);
85 }
86 
87 #ifdef	sparc
88 EXPORT int
flush_reg_windows(n)89 flush_reg_windows(n)
90 	int	n;
91 {
92 	if (--n > 0)
93 		flush_reg_windows(n);
94 	return (0);
95 }
96 #endif
97 
98 #endif	/* HAVE_SCANSTACK */
99