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