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 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_soltools.hxx" 30 31 #include <string.h> 32 #include <direct.h> 33 #include <stdio.h> 34 #include <stdlib.h> 35 36 #include "ldump.hxx" 37 #include "hashtbl.hxx" 38 39 #define MAXSYM 65536 40 #define MAXBASE 98304 41 #define MAX_MAN 4096 42 43 int bFilter = 0; 44 int bLdump3 = 0; 45 int bUseDirectives = 0; 46 int bVerbose = 0; 47 int bExportByName = 0; 48 49 class ExportSet : public HashTable 50 { 51 public: 52 ExportSet 53 ( 54 unsigned long lSize, 55 double dMaxLoadFactor = HashTable::m_defMaxLoadFactor, 56 double dGrowFactor = HashTable::m_defDefGrowFactor 57 ) 58 : HashTable(lSize,false,dMaxLoadFactor,dGrowFactor) {} 59 60 virtual ~ExportSet() {} 61 62 LibExport * Find (char * const& Key) const 63 { return (LibExport *) HashTable::Find((char *) Key); } 64 65 bool Insert (char * const& Key, LibExport * Object) 66 { return HashTable::Insert((char *) Key, (void*) Object); } 67 68 LibExport * Delete (char * const&Key) 69 { return (LibExport *) HashTable::Delete ((char *) Key); } 70 }; 71 72 LibDump::LibDump( char *cFileName, int bExportByName ) 73 : cBName( NULL ), 74 cAPrefix( NULL ), 75 cLibName( NULL ), 76 cFilterName( NULL ), 77 cModName( NULL ) 78 { 79 fprintf( stderr, "LIB-NT File Dumper v4.00 (C) 2000 Sun Microsystems, Inc.\n\n" ); 80 fprintf( stderr, "%s ", cFileName ); 81 82 bExportName = bExportByName; 83 84 unsigned long nSlots = 0xfffff; 85 pBaseTab = new ExportSet( nSlots ); 86 pIndexTab = new ExportSet( nSlots ); 87 pFilterLines = new char * [MAXFILT]; 88 CheckLibrary(cFileName); 89 bBase = 0; 90 bAll = false; 91 nDefStart = 0; 92 nBaseLines = 0; 93 nFilterLines = 0; 94 bDef = true; 95 cAPrefix = new char[ 1 ]; 96 cAPrefix[ 0 ] = 0; 97 if (!bExportName) 98 CheckDataBase(); 99 } 100 101 bool LibDump::Dump() 102 { 103 FILE *pList; 104 char aBuf[MAX_MAN]; 105 int nLen; 106 char aName[MAX_MAN]; 107 108 pList = fopen( cLibName, "rb"); 109 if (!pList) 110 DumpError(10); 111 112 // forget about offset when working on linker directives 113 if ( !bUseDirectives ) 114 { 115 // calculating offset for name section 116 unsigned char TmpBuffer[4]; 117 fread( TmpBuffer, 1, 4, pList); 118 // anzahl bigendian mal laenge + ueberspringen der naechsten laengenangabe 119 unsigned long nOffSet = (unsigned long) ( TmpBuffer[2] * 256 + TmpBuffer[3] ) * 4 + 4; 120 fseek( pList, (long) nOffSet, 0); 121 } 122 123 char aTmpBuf[4096]; 124 // reading file containing symbols 125 while( !feof( pList ) ) 126 { 127 int i = 0; 128 if ( !bUseDirectives ) 129 { 130 // symbol komplett einlesen 131 for (;;) 132 { 133 int c = fgetc( pList ); 134 if ( c == '\0' ) 135 { 136 break; 137 } 138 if ( ((c >= 33) && (c <= 126)) && ( c!=40 && c!=41) ) 139 aBuf[i] = static_cast< char >(c); 140 else 141 { 142 aBuf[0] = '\0'; 143 break; 144 } 145 i++; 146 } 147 // Namen found 148 aBuf[i] = '\0'; 149 } 150 else 151 { 152 fgets( aTmpBuf, 4096, pList ); 153 char * pEnd = 0; 154 char *pFound = 0; 155 aBuf[0] = '\0'; 156 pFound = strchr( aTmpBuf, 'E' ); 157 while ( pFound ) 158 { 159 if ( strncmp( "EXPORT:", pFound, 7) == 0 ) 160 { 161 pFound += 7; 162 pEnd = strchr( pFound, ','); 163 if ( pEnd ) 164 *pEnd = '\0'; 165 strncpy( aBuf, pFound, strlen( pFound)); 166 aBuf[ strlen( pFound) ] = '\0'; 167 // fprintf( stderr, "\n--- %s\n", aBuf); 168 break; 169 } 170 else 171 { 172 pFound++; 173 pFound = strchr( pFound, 'E' ); 174 } 175 } 176 } 177 178 if ((aBuf[0] =='?') || !strncmp(aBuf, "__CT",4)) 179 { 180 nLen = (int) strlen(aBuf); 181 memset( aName, 0, sizeof( aName ) ); 182 int nName = 0; 183 for( i = 0; i < nLen; i++ ) 184 { 185 if ( (aBuf[i] != '\n') && (aBuf[i] != '\r') ) 186 { 187 aName[nName] = aBuf[i]; 188 nName++; 189 } 190 } 191 // und raus damit 192 PrintSym( aName, bExportByName ); 193 } 194 else if ( bAll == true ) 195 { 196 int nPreLen = (int) strlen( cAPrefix ); 197 198 nLen = (int) strlen(aBuf); 199 memset( aName, 0, sizeof( aName ) ); 200 int nName = 0; 201 202 for( i = 0; i < nLen; i++ ) 203 { 204 if ( (aBuf[i] != '\n') && (aBuf[i] != '\r') ) 205 { 206 aName[nName] = aBuf[i]; 207 nName++; 208 } 209 } 210 //fprintf( stderr, "Gefundenen Prefix : %s %d \n", aTmpBuf, nPreLen ); 211 // den ersten _ raus 212 nLen = (int) strlen(aName); 213 if (aName[0] == '_') 214 strcpy( aBuf , &aName[1] ); 215 strncpy ( aTmpBuf, aBuf, (size_t) nPreLen ); 216 aTmpBuf[nPreLen] = '\0'; 217 if ( !strcmp( aTmpBuf, cAPrefix )) 218 { 219 if ( bLdump3 ) { 220 int nChar = '@'; 221 char *pNeu = strchr( aBuf, nChar ); 222 int nPos = pNeu - aBuf + 1; 223 if ( nPos > 0 ) 224 { 225 char aOldBuf[MAX_MAN]; 226 strcpy( aOldBuf, aBuf ); 227 char pChar[MAX_MAN]; 228 strncpy( pChar, aBuf, (size_t) (nPos -1) ); 229 pChar[nPos-1] = '\0'; 230 strcpy( aBuf, pChar ); 231 strcat( aBuf, "=" ); 232 strcat( aBuf, aOldBuf ); 233 strcpy( pChar, "" ); 234 } 235 } 236 // und raus damit 237 PrintSym( aBuf, true ); 238 } 239 } 240 } 241 fclose(pList); 242 return true; 243 } 244 245 bool LibDump::ReadFilter( char * cFilterName ) 246 { 247 FILE* pfFilter = 0; 248 char aBuf[MAX_MAN]; 249 char* pStr; 250 int nLen; 251 252 pfFilter = fopen( cFilterName, "r" ); 253 254 if ( !pfFilter ) 255 { 256 ::bFilter = 0; 257 DumpError( 500 ); 258 } 259 260 while( fgets( aBuf, MAX_MAN, pfFilter ) != 0 ) 261 { 262 nLen = (int) strlen(aBuf); 263 pStr = new char[(unsigned int) nLen]; 264 if ( !pStr ) 265 DumpError( 98 ); 266 memcpy( pStr, aBuf, (unsigned int) nLen ); 267 if ( *(pStr+nLen-1) == '\n' ) 268 *(pStr+nLen-1) = '\0'; 269 pFilterLines[nFilterLines] = pStr; 270 nFilterLines++; 271 if ( nFilterLines >= MAXFILT ) 272 DumpError( 510 ); 273 } 274 275 fclose( pfFilter ); 276 return true; 277 } 278 279 bool LibDump::PrintSym(char *pName, bool bName ) 280 { 281 LibExport *pData; 282 283 284 // Filter auswerten 285 if ( Filter( pName ) ) 286 { 287 if ( strlen( pName ) > 3 ) 288 { 289 if ( bDef ) 290 { 291 if (!bBase) 292 if (bExportName) { 293 fprintf( stdout, "\t%s\n", pName ); 294 } else { 295 fprintf( stdout, "\t%s\t\t@%lu\n", pName, nDefStart ); 296 } 297 else 298 { 299 pData = pBaseTab->Find( pName ); 300 if ( pData ) 301 { 302 pData->bExport = true; 303 if ( bName ) 304 pData->bByName = true; 305 else 306 pData->bByName = false; 307 if ( bVerbose ) 308 fprintf(stderr,"."); 309 } 310 else 311 { 312 // neuen Export eintragen 313 pData = new LibExport; 314 pData->cExportName = new char[ strlen( pName ) + 1 ]; 315 strcpy( pData->cExportName, pName ); 316 pData->nOrdinal = nBaseLines++; 317 pData->bExport = true; 318 if ( bName ) 319 pData->bByName = true; 320 else 321 pData->bByName = false; 322 pBaseTab->Insert( pData->cExportName, pData ); 323 char *cBuffer = new char[ 30 ]; 324 sprintf( cBuffer, "%lu", pData->nOrdinal ); 325 pIndexTab->Insert( cBuffer, pData ); 326 delete [] cBuffer; 327 if ( bVerbose ) 328 fprintf(stderr,"n"); 329 } 330 } 331 } 332 else 333 printf( "%s\n", pName ); 334 nDefStart++; 335 } 336 } 337 return true; 338 } 339 340 bool LibDump::IsFromAnonymousNamespace (char *pExportName) { 341 char* pattern1 = "@?A0x"; 342 343 if (strstr(pExportName, pattern1)) { 344 return true; 345 }; 346 return false; 347 }; 348 349 bool LibDump::Filter(char *pExportName) 350 { 351 unsigned long i; 352 char pTest[256]; 353 354 // filter out symbols from anonymous namespaces 355 if (IsFromAnonymousNamespace (pExportName)) 356 return false; 357 358 // Kein Filter gesetzt 359 if ( ::bFilter == 0 ) 360 return true; 361 362 for ( i=0; i<nFilterLines; i++ ) 363 { 364 //Zum vergleichen mu� das Plus abgeschnitteb werden 365 if(pFilterLines[i][0] != '+') 366 { 367 if ( strstr( pExportName, pFilterLines[i])) 368 return false; 369 } 370 else 371 { 372 strcpy(pTest,&pFilterLines[i][1]); 373 if ( strstr( pExportName, pTest)) 374 return true; 375 } 376 } 377 return true; 378 } 379 380 bool LibDump::SetFilter(char * cFilterName) 381 { 382 ReadFilter( cFilterName ); 383 return true; 384 } 385 386 bool LibDump::CheckLibrary(char * cName) 387 { 388 delete [] cLibName; 389 cLibName = new char[ strlen( cName ) + 1 ]; 390 strcpy( cLibName, cName ); 391 return true; 392 } 393 394 bool LibDump::ReadDataBase() 395 { 396 FILE* pfBase = 0; 397 char aBuf[MAX_MAN]; 398 char* pStr; 399 char cBuffer[ 30 ]; 400 int nLen; 401 LibExport *pData; 402 403 pfBase = fopen( cBName, "r" ); 404 405 if ( !pfBase ) 406 { 407 bBase = 0; 408 DumpError( 600 ); 409 } 410 411 bool bRet = true; 412 while( fgets( aBuf, MAX_MAN, pfBase ) != 0 ) 413 { 414 nLen = (int) strlen(aBuf); 415 pStr = new char[(unsigned int) nLen]; 416 if ( !pStr ) 417 DumpError( 98 ); 418 memcpy( pStr, aBuf, (size_t) nLen ); 419 if ( *(pStr+nLen-1) == '\n' ) 420 *(pStr+nLen-1) = '\0'; 421 pData = new LibExport; 422 pData->cExportName = pStr; 423 pData->nOrdinal = nBaseLines; 424 pData->bExport=false; 425 426 if (pBaseTab->Insert(pData->cExportName, pData ) == NULL) 427 bRet = false; 428 ltoa( (long) pData->nOrdinal, cBuffer, 10 ); 429 if (pIndexTab->Insert( cBuffer, pData ) == NULL) 430 bRet = false; 431 nBaseLines++; 432 if ( nBaseLines >= MAXBASE ) 433 DumpError( 610 ); 434 } 435 fclose( pfBase ); 436 return bRet; 437 } 438 439 class ExportSetIter : public HashTableIterator 440 { 441 public: 442 ExportSetIter(HashTable const& aTable) 443 : HashTableIterator(aTable) {} 444 445 LibExport * GetFirst() 446 { return (LibExport *)HashTableIterator::GetFirst(); } 447 LibExport * GetNext() 448 { return (LibExport *)HashTableIterator::GetNext(); } 449 LibExport * GetLast() 450 { return (LibExport *)HashTableIterator::GetLast(); } 451 LibExport * GetPrev() 452 { return (LibExport *)HashTableIterator::GetPrev(); } 453 454 private: 455 void operator =(ExportSetIter &); // not defined 456 }; 457 458 bool LibDump::PrintDataBase() 459 { 460 if (bExportName) 461 return true; 462 FILE *pFp; 463 pFp = fopen (cBName,"w+"); 464 if (!pFp) 465 fprintf( stderr, "Error opening DataBase File\n" ); 466 467 LibExport *pData; 468 for ( unsigned long i=0; i < nBaseLines+10; i++ ) 469 { 470 char * cBuffer = new char[ 30 ]; 471 sprintf( cBuffer, "%lu", i ); 472 pData = pIndexTab->Find( cBuffer ); 473 delete [] cBuffer; 474 if ( pData ) 475 fprintf(pFp,"%s\n",pData->cExportName); 476 } 477 fclose(pFp); 478 return true; 479 } 480 481 bool LibDump::PrintDefFile() 482 { 483 #ifdef FAST 484 ExportSetIter aIterator( *pBaseTab ); 485 for ( LibExport *pData = aIterator.GetFirst(); pData != NULL; 486 pData = aIterator.GetNext() ) 487 { 488 if ( pData->bExport ) 489 { 490 if ( pData->bByName ) 491 { 492 fprintf(stdout,"\t%s\n", 493 pData->sExportName.GetBuffer()); 494 } 495 else 496 { 497 fprintf(stdout,"\t%s\t\t@%d NONAME\n", 498 pData->sExportName.GetBuffer(), pData->nOrdinal+nBegin); 499 } 500 } 501 } 502 #else 503 // sortiert nach Ordinals; 504 LibExport *pData; 505 for ( unsigned long i=0; i<nBaseLines+1; i++) 506 { 507 char * cBuffer = new char[ 30 ]; 508 sprintf( cBuffer, "%lu", i ); 509 pData = pIndexTab->Find( cBuffer ); 510 delete [] cBuffer; 511 if ( pData ) 512 if ( pData->bExport ) 513 { 514 if ( pData->bByName ) 515 { 516 if ( strlen( pData->cExportName )) 517 fprintf(stdout,"\t%s\n", 518 pData->cExportName); 519 } 520 else 521 { 522 if ( strlen( pData->cExportName )) 523 fprintf(stdout,"\t%s\t\t@%d NONAME\n", 524 pData->cExportName, pData->nOrdinal+nBegin); 525 } 526 } 527 } 528 #endif 529 return true; 530 } 531 532 bool LibDump::CheckDataBase() 533 { 534 // existiert eine Datenbasis ? 535 if (!bBase) 536 { 537 cBName = new char[ 2048 ]; 538 char *pTmp = "defs\\"; 539 540 FILE *fp; 541 #ifdef OS2 542 _mkdir ("defs", 0777); 543 #else 544 _mkdir ("defs"); 545 #endif 546 strcpy(cBName,pTmp); 547 #ifdef OS2 548 strcat(cBName,"gcc"); 549 #else 550 strcat(cBName,getenv ("COMP_ENV")); 551 #endif 552 553 fp = fopen (cBName,"r"); 554 if (fp) 555 { 556 bBase = true; 557 } 558 else 559 { 560 fp = fopen (cBName,"w+"); 561 bBase = true; 562 } 563 fclose (fp); 564 } 565 // lese Datenbasis ! 566 if (bBase) 567 { 568 ReadDataBase(); 569 } 570 return true; 571 } 572 573 LibDump::~LibDump() 574 { 575 delete [] cBName; 576 delete [] cAPrefix; 577 // delete [] cLibName; 578 delete [] cFilterName; 579 delete [] cModName; 580 } 581 582 void LibDump::SetCExport( char* pName ) 583 { 584 delete [] cAPrefix; 585 cAPrefix = new char[ strlen( pName ) + 1 ]; 586 strcpy( cAPrefix, pName );bAll = true; 587 } 588 589 //****************************************************************** 590 //* Error() - Gibt Fehlermeldumg aus 591 //****************************************************************** 592 593 void LibDump::DumpError( unsigned long n ) 594 { 595 char *p; 596 597 switch (n) 598 { 599 case 1: p = "Input error in library file"; break; 600 case 2: p = "Position error in library file (no THEADR set)"; break; 601 case 3: p = "Overflow of symbol table"; break; 602 #ifdef WNT 603 case 10: p = "EXP file not found"; break; 604 case 11: p = "No valid EXP file"; break; 605 #else 606 case 10: p = "Library file not found"; break; 607 case 11: p = "No valid library file"; break; 608 #endif 609 case 98: p = "Out of memory"; break; 610 case 99: p = "LDUMP [-LD3] [-D] [-N] [-A] [-E nn] [-F name] Filename[.LIB]\n" 611 "-LD3 : Supports feature set of ldump3 (default: ldump/ldump2)\n" 612 "-A : all symbols (default: only C++)\n" 613 "-E nn : gerenration of export table beginning with number nn\n" 614 "-F name: Filter file\n" 615 "-D : file contains \"dumpbin\" directives\n" 616 "-N : export by name\n" 617 "-V : be verbose\n"; break; 618 case 500: p = "Unable to open filter file\n"; break; 619 case 510: p = "Overflow of filter table\n"; break; 620 case 600: p = "Unable to open base database file\n"; break; 621 case 610: p = "Overflow in base database table\n"; break; 622 default: p = "Unspecified error"; 623 } 624 fprintf( stdout, "%s\n", p ); 625 exit (1); 626 } 627 628 /********************************************************************* 629 Test Funktionen 630 *********************************************************************/ 631 632 633 void usage() 634 { 635 LibDump::DumpError(99); 636 } 637 638 #define STATE_NON 0x0000 639 #define STATE_BEGIN 0x0001 640 #define STATE_FILTER 0x0002 641 #define STATE_CEXPORT 0x0003 642 643 int 644 #ifdef WNT 645 __cdecl 646 #endif 647 main( int argc, char **argv ) 648 { 649 char *pLibName = NULL, *pFilterName = NULL, *pCExport= NULL; 650 unsigned short nBegin=1; 651 652 unsigned short nState = STATE_NON; 653 654 if ( argc == 1 ) { 655 usage(); 656 } 657 658 for ( int i = 1; i < argc; i++ ) { 659 if (( !strcmp( argv[ i ], "-H" )) || 660 ( !strcmp( argv[ i ], "-h" )) || 661 ( !strcmp( argv[ i ], "-?" ))) 662 { 663 usage(); 664 } 665 else if (( !strcmp( argv[ i ], "-LD3" )) || 666 ( !strcmp( argv[ i ], "-Ld3" )) || 667 ( !strcmp( argv[ i ], "-ld3" )) || 668 ( !strcmp( argv[ i ], "-lD3" ))) 669 { 670 if ( nState != STATE_NON ) { 671 usage(); 672 } 673 bLdump3 = 1; 674 } 675 else if (( !strcmp( argv[ i ], "-E" )) || ( !strcmp( argv[ i ], "-e" ))) { 676 if ( nState != STATE_NON ) { 677 usage(); 678 } 679 nState = STATE_BEGIN; 680 } 681 else if (( !strcmp( argv[ i ], "-F" )) || ( !strcmp( argv[ i ], "-f" ))) { 682 if ( nState != STATE_NON ) { 683 usage(); 684 } 685 nState = STATE_FILTER; 686 } 687 else if (( !strcmp( argv[ i ], "-A" )) || ( !strcmp( argv[ i ], "-a" ))) { 688 if ( nState != STATE_NON ) { 689 usage(); 690 } 691 nState = STATE_CEXPORT; 692 pCExport = new char[ 1 ]; 693 pCExport[ 0 ] = 0; 694 } 695 else if (( !strcmp( argv[ i ], "-D" )) || ( !strcmp( argv[ i ], "-d" ))) { 696 if ( nState != STATE_NON ) { 697 usage(); 698 } 699 bUseDirectives = 1; 700 } 701 else if (( !strcmp( argv[ i ], "-N" )) || ( !strcmp( argv[ i ], "-n" ))) { 702 if ( nState != STATE_NON ) { 703 usage(); 704 } 705 bExportByName = 1; 706 } 707 else if (( !strcmp( argv[ i ], "-V" )) || ( !strcmp( argv[ i ], "-v" ))) { 708 if ( nState != STATE_NON ) { 709 usage(); 710 } 711 bVerbose = 1; 712 } 713 else { 714 switch ( nState ) { 715 case STATE_BEGIN: 716 nBegin = static_cast< unsigned short >(atoi( argv[ i ] )); 717 nState = STATE_NON; 718 break; 719 case STATE_FILTER: 720 pFilterName = new char[ strlen( argv[ i ] ) + 1 ]; 721 strcpy( pFilterName, argv[ i ] ); 722 bFilter = 1; 723 nState = STATE_NON; 724 break; 725 case STATE_CEXPORT: 726 delete [] pCExport; 727 pCExport = new char[ strlen( argv[ i ] ) + 1 ]; 728 strcpy( pCExport, argv[ i ] ); 729 nState = STATE_NON; 730 break; 731 default: 732 pLibName = new char[ strlen( argv[ i ] ) + 1 ]; 733 strcpy( pLibName, argv[ i ] ); 734 break; 735 } 736 } 737 } 738 739 if ( !pLibName ) { 740 usage(); 741 } 742 743 LibDump *pDump = new LibDump( pLibName, bExportByName ); 744 pDump->SetBeginExport(nBegin); 745 if ( bFilter != 0 ) 746 pDump->SetFilter( pFilterName ); 747 if ( pCExport ) 748 pDump->SetCExport( pCExport ); 749 else { 750 char *pEmpty = ""; 751 pDump->SetCExport( pEmpty ); 752 } 753 pDump->Dump(); 754 pDump->PrintDefFile(); 755 pDump->PrintDataBase(); 756 delete pDump; 757 return 0; 758 } 759