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 *************************************************************************/ 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 *************************************************************************/ 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 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 *************************************************************************/ 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 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 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 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 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 *************************************************************************/ 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 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 *************************************************************************/ 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 } 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 *************************************************************************/ 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 *************************************************************************/ 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 *************************************************************************/ 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, becuase 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 *************************************************************************/ 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 *************************************************************************/ 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 ************************************************************************/ 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