1 // $Header$
2 //
3 // Copyright (C) 2000 - 2003, by
4 //
5 // Carlo Wood, Run on IRC <carlo@alinoe.com>
6 // RSA-1024 0x624ACAD5 1997-01-26                    Sign & Encrypt
7 // Fingerprint16 = 32 EC A7 B6 AC DB 65 A6  F6 F6 55 DD 1C DC FF 61
8 //
9 // This file may be distributed under the terms of the Q Public License
10 // version 1.0 as appearing in the file LICENSE.QPL included in the
11 // packaging of this file.
12 //
13 
14 #include "sys.h"
15 #include <libcwd/debug.h>
16 #include <iostream>
17 
18 #if !CW_RECURSIVE_BUILTIN_RETURN_ADDRESS
19 static void* return_address[6];
20 #define store_call_address(i) return_address[i] = __builtin_return_address(0)
21 #define START _start
22 extern "C" int START();
23 #endif
24 
25 #ifdef CW_FRAME_ADDRESS_OFFSET
frame_return_address(unsigned int frame)26 static void* frame_return_address(unsigned int frame)
27 {
28   void* frame_ptr = __builtin_frame_address(0);
29 #if CW_FRAME_ADDRESS_OFFSET == 0
30   ++frame;
31 #endif
32   do
33   {
34     void** frame_ptr_ptr = reinterpret_cast<void**>(frame_ptr) + CW_FRAME_ADDRESS_OFFSET;
35     if (frame-- == 0)
36       return frame_ptr_ptr[1];
37     frame_ptr = *frame_ptr_ptr;
38   }
39   while (frame_ptr);
40   return NULL;
41 }
42 #endif
43 
libcwd_bfd_test3(void)44 void libcwd_bfd_test3(void)
45 {
46 #if CWDEBUG_LOCATION
47   for (int i = 0; i <= 5; ++i)
48   {
49     void* retadr;
50 
51     switch (i)
52     {
53 #if CW_RECURSIVE_BUILTIN_RETURN_ADDRESS
54       case 1:
55         retadr = __builtin_return_address(1);
56 	break;
57       case 2:
58         retadr = __builtin_return_address(2);
59 	break;
60       case 3:
61         retadr = __builtin_return_address(3);
62 	break;
63       case 4:
64         retadr = __builtin_return_address(4);
65 	break;
66       case 5:
67         retadr = __builtin_return_address(5);
68 	break;
69 #else
70       case 1:
71       case 2:
72       case 3:
73       case 4:
74         retadr = return_address[i];
75 	break;
76       case 5:
77         retadr = (char*)&START + 10;	// Whatever...
78         break;
79 #endif
80       default:
81         retadr = __builtin_return_address(0);
82 	break;
83     }
84 
85 #if CWDEBUG_LOCATION
86     libcwd::location_ct loc((char*)retadr + libcwd::builtin_return_address_offset);
87     Dout(dc::notice, "called from " << loc);
88 
89 #ifdef CW_FRAME_ADDRESS_OFFSET
90     if (i < 5 && frame_return_address(i) != retadr)
91       DoutFatal(dc::fatal, "frame_return_address(" << i << ") returns " <<
92           libcwd::location_ct((char*)frame_return_address(i) + builtin_return_address_offset) << "!");
93 #endif
94 
95     if (!loc.is_known() || strcmp(loc.mangled_function_name(), "__libc_start_main") == 0)
96       break;
97 #else // !CWDEBUG_LOCATION
98 #ifdef CW_FRAME_ADDRESS_OFFSET
99     if (i < 5 && frame_return_address(i) != retadr)
100       DoutFatal(dc::fatal, "frame_return_address(" << i << ") returns " << frame_return_address(i) << '!');
101 #endif
102 #endif
103   }
104 #endif
105 }
106 
libcwd_bfd_test2(void)107 void libcwd_bfd_test2(void)
108 {
109 #if !CW_RECURSIVE_BUILTIN_RETURN_ADDRESS
110   store_call_address(1);
111 #endif
112   libcwd_bfd_test3();
113 }
114 
libcwd_bfd_test1(void)115 void libcwd_bfd_test1(void)
116 {
117 #if !CW_RECURSIVE_BUILTIN_RETURN_ADDRESS
118   store_call_address(2);
119 #endif
120   libcwd_bfd_test2();
121 }
122 
libcwd_bfd_test(void)123 void libcwd_bfd_test(void)
124 {
125 #if !CW_RECURSIVE_BUILTIN_RETURN_ADDRESS
126   store_call_address(3);
127 #endif
128   libcwd_bfd_test1();
129 }
130 
131 MAIN_FUNCTION
132 { PREFIX_CODE
133 #if !CWDEBUG_LOCATION
134   DoutFatal(dc::fatal, "Expected Failure.");
135 #endif
136 
137   Debug( check_configuration() );
138 
139   // Select channels
140   ForAllDebugChannels( if (debugChannel.is_on()) debugChannel.off(); );
141 #if !defined(__sun__) || !defined(__svr4__)
142   Debug( dc::warning.on() );	// On Solaris we fail to find the start of libdl
143 #endif
144 #if CWDEBUG_LOCATION
145   Debug( dc::bfd.on() );
146 #endif
147   Debug( dc::notice.on() );
148   Debug( dc::system.on() );
149 #ifndef THREADTEST
150   // Write debug output to cout
151   Debug( libcw_do.set_ostream(&std::cout) );
152 #endif
153   // Turn debug object on
154   Debug( libcw_do.on() );
155 #if CWDEBUG_LOCATION
156   // Choose location format
157   Debug( location_format(show_objectfile|show_function) );
158 #endif
159 
160   // Run test
161 #if !CW_RECURSIVE_BUILTIN_RETURN_ADDRESS
162   store_call_address(4);
163 #endif
164   libcwd_bfd_test();
165 
166   Dout(dc::notice, "Program end");
167 
168   Debug( libcw_do.off() );
169 
170   EXIT(0);
171 }
172