1 /* @(#)getfp.c	1.21 21/04/28 Copyright 1988-2021 J. Schilling */
2 /*
3  *	Get frame pointer
4  *
5  *	Copyright (c) 1988-2021 J. Schilling
6  */
7 /*
8  * The contents of this file are subject to the terms of the
9  * Common Development and Distribution License, Version 1.0 only
10  * (the "License").  You may not use this file except in compliance
11  * with the License.
12  *
13  * See the file CDDL.Schily.txt in this distribution for details.
14  * A copy of the CDDL is also available via the Internet at
15  * http://www.opensource.org/licenses/cddl1.txt
16  *
17  * When distributing Covered Code, include this CDDL HEADER in each
18  * file and include the License file CDDL.Schily.txt from this distribution.
19  */
20 
21 #include <schily/mconfig.h>
22 #include <schily/standard.h>
23 #include <schily/schily.h>
24 
25 #ifndef	IS_AVOFFSET
26 /*
27  * We usually don't like to compile a getfp() that returns junk data in case
28  * we cannot scan the stack.
29  * The only way to find this out is by including avoffset.h. Unfortunately, we
30  * need to be able to use getfp() from avoffset.c in order to check if the
31  * return value is usable or junk. To be able to do this, we include getfp.c
32  * from avoffset.c and define IS_AVOFFSET before.
33  */
34 #include <schily/avoffset.h>
35 
36 #if	!defined(AV_OFFSET) || !defined(FP_INDIR)
37 #	ifdef	HAVE_SCANSTACK
38 #	undef	HAVE_SCANSTACK
39 #	endif
40 #endif
41 #endif
42 
43 #ifdef	HAVE_SCANSTACK
44 #include <schily/stkframe.h>
45 
46 #define	MAXWINDOWS	32
47 #define	NWINDOWS	7
48 
49 #if defined(sparc) && defined(__GNUC__)
50 #	define	FP_OFF		0x10	/* some strange things on sparc gcc */
51 #else
52 #	define	FP_OFF		0
53 #endif
54 
55 #if defined(__clang__) || \
56 	(defined(__GNUC__) && \
57 	    ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ > 7)))
58 #define	ATTRIBUTE_NO_SANITIZE_ADDRESS	__attribute__((no_sanitize_address))
59 #else
60 #define	ATTRIBUTE_NO_SANITIZE_ADDRESS
61 #endif
62 
63 EXPORT	void	**___fpoff	__PR((char *cp));
64 
65 ATTRIBUTE_NO_SANITIZE_ADDRESS
66 __NO_INL__
67 EXPORT void **
getfp()68 getfp()
69 {
70 		long	**dummy[1];
71 
72 #ifdef	sparc
73 	flush_reg_windows(MAXWINDOWS-2);
74 #endif
75 	return ((void **)((struct frame *)___fpoff((char *)&dummy[0]))->fr_savfp);
76 }
77 
78 #ifdef	sparc
79 __NO_INL__
80 EXPORT int
flush_reg_windows(n)81 flush_reg_windows(n)
82 	int	n;
83 {
84 	if (--n > 0)
85 		flush_reg_windows(n);
86 	return (0);
87 }
88 #endif
89 
90 #else	/* HAVE_SCANSTACK */
91 
92 EXPORT void **
getfp()93 getfp()
94 {
95 	raisecond("getfp", 0);
96 	return ((void **)0);
97 }
98 
99 #endif	/* HAVE_SCANSTACK */
100