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