1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <errno.h>
27 #include <string.h>
28
29 #include <unistd.h>
30 #include <sys/types.h>
31
32 #include <stdarg.h>
33
34 #include <signal.h>
35 #include <setjmp.h>
36
37 #define printTypeSize(Type,Name) printf( "sizeof(%s)\t\t= %d\n", Name, (int) sizeof (Type) )
38
39 #define isSignedType(Type) (((Type)-1) < 0)
40 #define printTypeSign(Type,Name) printf( "%s\t\t= %s %s\n", Name, ( isSignedType(Type) ? "signed" : "unsigned" ), Name )
41
42
43 /*************************************************************************
44 |*
45 |* IsBigEndian()
46 |*
47 |* Beschreibung True, wenn CPU BigEndian ist
48 |*
49 |* Ersterstellung EG 26.06.96
50 |* Letzte Aenderung
51 |*
52 *************************************************************************/
IsBigEndian()53 int IsBigEndian()
54 {
55 long l = 1;
56 return ! *(char*)&l;
57 }
58
59 /*************************************************************************
60 |*
61 |* Typdeclarations for memory access test functions
62 |*
63 *************************************************************************/
64 typedef enum { t_char, t_short, t_int, t_long, t_double } Type;
65 typedef int (*TestFunc)( Type, void* );
66
67
68 /*************************************************************************
69 |*
70 |* PrintArgs()
71 |*
72 |* Beschreibung Testfunktion fuer variable Parameter
73 |*
74 |* Ersterstellung EG 26.06.96
75 |* Letzte Aenderung
76 |*
77 *************************************************************************/
PrintArgs(int p,...)78 void PrintArgs( int p, ... )
79 {
80 int value;
81 va_list ap;
82
83 va_start( ap, p );
84
85 printf( "value = %d", p );
86
87 while ( ( value = va_arg(ap, int) ) != 0 )
88 printf( " %d", value );
89
90 printf( "\n" );
91 va_end(ap);
92 }
93
94 /*************************************************************************
95 |*
96 |* SignalHdl()
97 |*
98 |* Beschreibung faengt SIGBUS und SIGSEGV in check() ab
99 |*
100 |* Ersterstellung EG 26.06.96
101 |* Letzte Aenderung
102 |*
103 *************************************************************************/
104
105 static sigjmp_buf jmpbuf;
106 static volatile sig_atomic_t hit;
107
SignalHdl(int sig)108 void SignalHdl( int sig )
109 {
110 (void) sig; // ignored
111 hit = 1;
112 siglongjmp(jmpbuf, 0);
113 }
114
115 /*************************************************************************
116 |*
117 |* check()
118 |*
119 |* Beschreibung Testet MemoryZugriff (read/write)
120 |*
121 |* Ersterstellung EG 26.06.96
122 |* Letzte Aenderung
123 |*
124 *************************************************************************/
check(TestFunc func,Type eT,void * p)125 int check( TestFunc func, Type eT, void* p )
126 {
127 hit = 0;
128 if (sigsetjmp(jmpbuf, 1) == 0) {
129 struct sigaction sa;
130 sa.sa_handler = SignalHdl;
131 sigemptyset(&sa.sa_mask);
132 sa.sa_flags = 0;
133 if (sigaction(SIGBUS, &sa, NULL) != 0 ||
134 sigaction(SIGSEGV, &sa, NULL) != 0)
135 {
136 abort();
137 }
138 func(eT, p);
139 sa.sa_handler = SIG_DFL;
140 if (sigaction(SIGBUS, &sa, NULL) != 0 ||
141 sigaction(SIGSEGV, &sa, NULL) != 0)
142 {
143 abort();
144 }
145 }
146 return hit ? -1 : 0;
147 }
148
149 /*************************************************************************
150 |*
151 |* GetAtAddress()
152 |*
153 |* Beschreibung memory read access
154 |*
155 |* Ersterstellung EG 26.06.96
156 |* Letzte Aenderung
157 |*
158 *************************************************************************/
159 #if defined(IA64) || defined(ARM32) || defined(HPPA) || defined(AXP)
160
forceerror()161 int forceerror()
162 {
163 #if defined(ARM32)
164 // workaround for qemu-user
165 hit = 1;
166 #else
167 raise (SIGBUS);
168 #endif
169 return 1;
170 }
171
GetAtAddress(Type eT,void * p)172 int GetAtAddress( Type eT, void* p )
173 {
174 switch ( eT )
175 {
176 case t_char: return *((char*)p);
177 case t_short: if ((long)p % sizeof(short)) return forceerror(); else return *((short*)p);
178 case t_int: if ((long)p % sizeof(int)) return forceerror(); else return *((int*)p);
179 case t_long: if ((long)p % sizeof(long)) return forceerror(); else return *((long*)p);
180 case t_double: if ((long)p % sizeof(double)) return forceerror(); else return *((double*)p);
181 }
182 abort();
183 }
184
185 #else
186 static int dummy(void* unused);
187
GetAtAddress(Type eT,void * p)188 int GetAtAddress( Type eT, void* p )
189 {
190 switch ( eT )
191 {
192 case t_char: { char x = *(char*)p; return dummy(&x); }
193 case t_short: { short x = *(short*)p; return dummy(&x); }
194 case t_int: { int x = *(int*)p; return dummy(&x); }
195 case t_long: { long x = *(long*)p; return dummy(&x); }
196 case t_double: { double x = *(double*)p; return dummy(&x); }
197 }
198 abort();
199 }
200
dummy(void * unused)201 int dummy(void* unused)
202 {
203 (void)unused;
204 return 0;
205 }
206
207 #endif
208 /*************************************************************************
209 |*
210 |* SetAtAddress()
211 |*
212 |* Beschreibung memory write access
213 |*
214 |* Ersterstellung EG 26.06.96
215 |* Letzte Aenderung
216 |*
217 *************************************************************************/
SetAtAddress(Type eT,void * p)218 int SetAtAddress( Type eT, void* p )
219 {
220 switch ( eT )
221 {
222 case t_char: return *((char*)p) = 0;
223 case t_short: return *((short*)p) = 0;
224 case t_int: return *((int*)p) = 0;
225 case t_long: return *((long*)p) = 0;
226 case t_double: return *((double*)p)= 0;
227 }
228 abort();
229 }
230
TypeName(Type eT)231 char* TypeName( Type eT )
232 {
233 switch ( eT )
234 {
235 case t_char: return "char";
236 case t_short: return "short";
237 case t_int: return "int";
238 case t_long: return "long";
239 case t_double: return "double";
240 }
241 abort();
242 }
243
244 /*************************************************************************
245 |*
246 |* Check(Get|Set)Access()
247 |*
248 |* Beschreibung Testet MemoryZugriff (read/write)
249 |* Zugriffsverletzungen werden abgefangen
250 |*
251 |* Ersterstellung EG 26.06.96
252 |* Letzte Aenderung
253 |*
254 *************************************************************************/
CheckGetAccess(Type eT,void * p)255 int CheckGetAccess( Type eT, void* p )
256 {
257 int b;
258 b = -1 != check( (TestFunc)GetAtAddress, eT, p );
259 #if OSL_DEBUG_LEVEL > 1
260 fprintf( stderr,
261 "%s read %s at %p\n",
262 (b? "can" : "can not" ), TypeName(eT), p );
263 #endif
264 return b;
265 }
CheckSetAccess(Type eT,void * p)266 int CheckSetAccess( Type eT, void* p )
267 {
268 int b;
269
270 b = -1 != check( (TestFunc)SetAtAddress, eT, p );
271 #if OSL_DEBUG_LEVEL > 1
272 fprintf( stderr,
273 "%s write %s at %p\n",
274 (b? "can" : "can not" ), TypeName(eT), p );
275 #endif
276 return b;
277 }
278
279 /*************************************************************************
280 |*
281 |* GetAlignment()
282 |*
283 |* Beschreibung Bestimmt das Alignment verschiedener Typen
284 |*
285 |* Ersterstellung EG 26.06.96
286 |* Letzte Aenderung
287 |*
288 *************************************************************************/
GetAlignment(Type eT)289 int GetAlignment( Type eT )
290 {
291 char a[ 16*8 ];
292 long p = (long)(void*)a;
293 int i;
294
295 /* clear a[...] to set legal value for double access */
296 for ( i = 0; i < 16*8; i++ )
297 a[i] = 0;
298
299 p = ( p + 0xF ) & ~0xF;
300 for ( i = 1; i < 16; i++ )
301 if ( CheckGetAccess( eT, (void*)(p+i) ) )
302 return i;
303 return 0;
304 }
305
306 /*************************************************************************
307 |*
308 |* struct Description
309 |*
310 |* Beschreibung Beschreibt die Parameter der Architektur
311 |*
312 |* Ersterstellung EG 26.06.96
313 |* Letzte Aenderung
314 |*
315 *************************************************************************/
316 struct Description
317 {
318 int bBigEndian;
319 int nAlignment[3]; /* 2,4,8 */
320 };
321
322 /*************************************************************************
323 |*
324 |* Description_Ctor()
325 |*
326 |* Beschreibung Bestimmt die Parameter der Architektur
327 |*
328 |* Ersterstellung EG 26.06.96
329 |* Letzte Aenderung
330 |*
331 *************************************************************************/
Description_Ctor(struct Description * pThis)332 void Description_Ctor( struct Description* pThis )
333 {
334 pThis->bBigEndian = IsBigEndian();
335
336 if ( sizeof(short) != 2 )
337 abort();
338 pThis->nAlignment[0] = GetAlignment( t_short );
339 if ( sizeof(int) != 4 )
340 abort();
341 pThis->nAlignment[1] = GetAlignment( t_int );
342
343 if ( sizeof(long) == 8 )
344 pThis->nAlignment[2] = GetAlignment( t_long );
345 else if ( sizeof(double) == 8 )
346 pThis->nAlignment[2] = GetAlignment( t_double );
347 else
348 abort();
349 }
350
351 /*************************************************************************
352 |*
353 |* Description_Print()
354 |*
355 |* Beschreibung Schreibt die Parameter der Architektur als Header
356 |*
357 |* Ersterstellung EG 26.06.96
358 |* Letzte Aenderung
359 |*
360 *************************************************************************/
Description_Print(struct Description * pThis,char * name)361 void Description_Print( struct Description* pThis, char* name )
362 {
363 int i;
364 FILE* f = fopen( name, "w" );
365 if( ! f ) {
366 fprintf( stderr, "Unable to open file %s: %s\n", name, strerror( errno ) );
367 exit( 99 );
368 }
369 fprintf( f, "/* This file is autogenerated from the 'typesconfig' program\n * in the sal module\n */\n\n" );
370
371 /* Disabled for now in preference to big/little endian defines in <osl/endian.h> fa (2004-03-15) */
372 /* fprintf( f, "#define SAL_TYPES_%s\n", pThis->bBigEndian ? "BIGENDIAN" : "LITTLEENDIAN" ); */
373
374 for ( i = 0; i < 3; i++ )
375 fprintf( f, "#define SAL_TYPES_ALIGNMENT%d\t%d\n", 1 << (i+1), pThis->nAlignment[i] );
376 fprintf( f, "#define SAL_TYPES_SIZEOFSHORT\t%d\n", (int) sizeof( short ) );
377 fprintf( f, "#define SAL_TYPES_SIZEOFINT\t%d\n", (int) sizeof( int ) );
378 fprintf( f, "#define SAL_TYPES_SIZEOFLONG\t%d\n", (int) sizeof( long ) );
379 fprintf( f, "#define SAL_TYPES_SIZEOFLONGLONG\t%d\n", (int) sizeof( long long ) );
380 fprintf( f, "#define SAL_TYPES_SIZEOFPOINTER\t%d\n", (int) sizeof( void* ) );
381
382 /* Disabled for now, because OOo code assumes sizeof(double) == 8 and this is not
383 * likely to change any time soon. fa (2004-03-15)
384 */
385 /* fprintf( f, "#define SAL_TYPES_SIZEOFDOUBLE\t%d\n", sizeof( double ) );*/
386
387 fclose( f );
388 }
389
390 /*************************************************************************
391 |*
392 |* InfoMemoryAccess()
393 |*
394 |* Beschreibung Informeller Bytezugriffstest
395 |*
396 |* Ersterstellung EG 26.06.96
397 |* Letzte Aenderung
398 |*
399 *************************************************************************/
InfoMemoryAccess(char * p)400 void InfoMemoryAccess( char* p )
401 {
402 if ( CheckGetAccess( t_char, p ) )
403 printf( "can read address %p\n", p );
404 else
405 printf( "cannot read address %p\n", p );
406
407 if ( CheckSetAccess( t_char, p ) )
408 printf( "can write address %p\n", p );
409 else
410 printf( "cannot write address %p\n", p );
411 }
412
413 /*************************************************************************
414 |*
415 |* InfoMemoryTypeAccess()
416 |*
417 |* Beschreibung Informeller Zugriffstest verschiedener Typen
418 |*
419 |* Ersterstellung EG 15.08.96
420 |* Letzte Aenderung
421 |*
422 *************************************************************************/
InfoMemoryTypeAccess(Type eT)423 void InfoMemoryTypeAccess( Type eT )
424 {
425 char a[64];
426 int i;
427
428 /* clear a[...] to set legal value for double access */
429 for ( i = 0; i < 64; i++ )
430 a[i] = 0;
431
432 for ( i = 56; i >= 7; i >>= 1 )
433 {
434 if ( CheckGetAccess(eT, (long*)&a[i]) )
435 printf( "Access %s on %i-Aligned Address : OK\n", TypeName(eT), i / 7 );
436 else
437 printf( "Access %s on %i-Aligned Address : ERROR\n", TypeName(eT), i / 7 );
438 }
439 }
440 /************************************************************************
441 *
442 * Use C code to determine the characteristics of the building platform.
443 *
444 ************************************************************************/
main(int argc,char * argv[])445 int main( int argc, char* argv[] )
446 {
447 printTypeSign( char, "char" );
448 printTypeSign( short, "short" );
449 printTypeSign( int, "int" );
450 printTypeSign( long, "long" );
451 printTypeSign( long long, "long long" );
452
453 printTypeSize( short, "short" );
454 printTypeSize( int, "int" );
455 printTypeSize( long, "long" );
456 printTypeSize( long long, "long long" );
457 printTypeSize( float, "float" );
458 printTypeSize( double, "double" );
459 printTypeSize( void *, "void *" );
460
461 if ( IsBigEndian() )
462 printf( "BIGENDIAN (Sparc, RS6000, IP22, IP32, PowerPC(BE))\n" );
463 else
464 printf( "LITTLEENDIAN (Intel, x86-64, PowerPC(LE))\n" );
465
466 /* PrintArgs( 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 ); */
467
468 if ( argc > 1 )
469 {
470 struct Description description;
471 Description_Ctor( &description );
472 Description_Print( &description, argv[1] );
473 }
474 {
475 char* p = NULL;
476 InfoMemoryAccess( p );
477 p = (char*)&p;
478 InfoMemoryAccess( p );
479 InfoMemoryTypeAccess( t_short );
480 InfoMemoryTypeAccess( t_int );
481 InfoMemoryTypeAccess( t_long );
482 InfoMemoryTypeAccess( t_double );
483 }
484
485 exit( 0 );
486 }
487