xref: /trunk/main/sal/typesconfig/typesconfig.c (revision 86e1cf34)
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