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 // A modern MSVC puts its SSE and AVX vector constants into the archive 175 // symbol table as __xmm@<hex>, and __ymm@/__zmm@ for the wider ones, 176 // exactly as every MSVC has done for __real@<hex>. They are merged 177 // COMDAT constants, not exports, and a .def naming one fails to link: 178 // 179 // icharttools.exp : error LNK2001: unresolved external symbol 180 // _xmm@41f00000000000000000000000000000 181 // 182 // The two modules that carry a symbol filter list _real for the same 183 // reason, but most export-all modules carry no filter at all -- ldump 184 // does no filtering when the file is absent -- so this has to be here 185 // rather than in a .flt. VC9 emits none of these, so it is unaffected. 186 if ( !strncmp( aBuf, "__xmm@", 6 ) 187 || !strncmp( aBuf, "__ymm@", 6 ) 188 || !strncmp( aBuf, "__zmm@", 6 ) ) 189 { 190 continue; 191 } 192 193 if ((aBuf[0] =='?') || !strncmp(aBuf, "__CT",4)) 194 { 195 nLen = (int) strlen(aBuf); 196 memset( aName, 0, sizeof( aName ) ); 197 int nName = 0; 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 // und raus damit 207 PrintSym( aName, bExportByName ); 208 } 209 else if ( bAll == true ) 210 { 211 int nPreLen = (int) strlen( cAPrefix ); 212 213 nLen = (int) strlen(aBuf); 214 memset( aName, 0, sizeof( aName ) ); 215 int nName = 0; 216 217 for( i = 0; i < nLen; i++ ) 218 { 219 if ( (aBuf[i] != '\n') && (aBuf[i] != '\r') ) 220 { 221 aName[nName] = aBuf[i]; 222 nName++; 223 } 224 } 225 //fprintf( stderr, "Gefundenen Prefix : %s %d \n", aTmpBuf, nPreLen ); 226 // den ersten _ raus 227 nLen = (int) strlen(aName); 228 if (aName[0] == '_') 229 strcpy( aBuf , &aName[1] ); 230 strncpy ( aTmpBuf, aBuf, (size_t) nPreLen ); 231 aTmpBuf[nPreLen] = '\0'; 232 if ( !strcmp( aTmpBuf, cAPrefix )) 233 { 234 if ( bLdump3 ) { 235 int nChar = '@'; 236 char *pNeu = strchr( aBuf, nChar ); 237 int nPos = pNeu - aBuf + 1; 238 if ( nPos > 0 ) 239 { 240 char aOldBuf[MAX_MAN]; 241 strcpy( aOldBuf, aBuf ); 242 char pChar[MAX_MAN]; 243 strncpy( pChar, aBuf, (size_t) (nPos -1) ); 244 pChar[nPos-1] = '\0'; 245 strcpy( aBuf, pChar ); 246 strcat( aBuf, "=" ); 247 strcat( aBuf, aOldBuf ); 248 strcpy( pChar, "" ); 249 } 250 } 251 // und raus damit 252 PrintSym( aBuf, true ); 253 } 254 } 255 } 256 fclose(pList); 257 return true; 258 } 259 260 bool LibDump::ReadFilter( char * cFilterName ) 261 { 262 FILE* pfFilter = 0; 263 char aBuf[MAX_MAN]; 264 char* pStr; 265 int nLen; 266 267 pfFilter = fopen( cFilterName, "r" ); 268 269 if ( !pfFilter ) 270 { 271 ::bFilter = 0; 272 DumpError( 500 ); 273 } 274 275 while( fgets( aBuf, MAX_MAN, pfFilter ) != 0 ) 276 { 277 nLen = (int) strlen(aBuf); 278 pStr = new char[(unsigned int) nLen]; 279 if ( !pStr ) 280 DumpError( 98 ); 281 memcpy( pStr, aBuf, (unsigned int) nLen ); 282 if ( *(pStr+nLen-1) == '\n' ) 283 *(pStr+nLen-1) = '\0'; 284 pFilterLines[nFilterLines] = pStr; 285 nFilterLines++; 286 if ( nFilterLines >= MAXFILT ) 287 DumpError( 510 ); 288 } 289 290 fclose( pfFilter ); 291 return true; 292 } 293 294 bool LibDump::PrintSym(char *pName, bool bName ) 295 { 296 LibExport *pData; 297 298 299 // Filter auswerten 300 if ( Filter( pName ) ) 301 { 302 if ( strlen( pName ) > 3 ) 303 { 304 if ( bDef ) 305 { 306 if (!bBase) 307 if (bExportName) { 308 fprintf( stdout, "\t%s\n", pName ); 309 } else { 310 fprintf( stdout, "\t%s\t\t@%lu\n", pName, nDefStart ); 311 } 312 else 313 { 314 pData = pBaseTab->Find( pName ); 315 if ( pData ) 316 { 317 pData->bExport = true; 318 if ( bName ) 319 pData->bByName = true; 320 else 321 pData->bByName = false; 322 if ( bVerbose ) 323 fprintf(stderr,"."); 324 } 325 else 326 { 327 // neuen Export eintragen 328 pData = new LibExport; 329 pData->cExportName = new char[ strlen( pName ) + 1 ]; 330 strcpy( pData->cExportName, pName ); 331 pData->nOrdinal = nBaseLines++; 332 pData->bExport = true; 333 if ( bName ) 334 pData->bByName = true; 335 else 336 pData->bByName = false; 337 pBaseTab->Insert( pData->cExportName, pData ); 338 char *cBuffer = new char[ 30 ]; 339 sprintf( cBuffer, "%lu", pData->nOrdinal ); 340 pIndexTab->Insert( cBuffer, pData ); 341 delete [] cBuffer; 342 if ( bVerbose ) 343 fprintf(stderr,"n"); 344 } 345 } 346 } 347 else 348 printf( "%s\n", pName ); 349 nDefStart++; 350 } 351 } 352 return true; 353 } 354 355 bool LibDump::IsFromAnonymousNamespace (char *pExportName) { 356 char* pattern1 = "@?A0x"; 357 358 if (strstr(pExportName, pattern1)) { 359 return true; 360 }; 361 return false; 362 }; 363 364 bool LibDump::Filter(char *pExportName) 365 { 366 unsigned long i; 367 char pTest[256]; 368 369 // filter out symbols from anonymous namespaces 370 if (IsFromAnonymousNamespace (pExportName)) 371 return false; 372 373 // Kein Filter gesetzt 374 if ( ::bFilter == 0 ) 375 return true; 376 377 for ( i=0; i<nFilterLines; i++ ) 378 { 379 //Zum vergleichen mu� das Plus abgeschnitteb werden 380 if(pFilterLines[i][0] != '+') 381 { 382 if ( strstr( pExportName, pFilterLines[i])) 383 return false; 384 } 385 else 386 { 387 strcpy(pTest,&pFilterLines[i][1]); 388 if ( strstr( pExportName, pTest)) 389 return true; 390 } 391 } 392 return true; 393 } 394 395 bool LibDump::SetFilter(char * cFilterName) 396 { 397 ReadFilter( cFilterName ); 398 return true; 399 } 400 401 bool LibDump::CheckLibrary(char * cName) 402 { 403 delete [] cLibName; 404 cLibName = new char[ strlen( cName ) + 1 ]; 405 strcpy( cLibName, cName ); 406 return true; 407 } 408 409 bool LibDump::ReadDataBase() 410 { 411 FILE* pfBase = 0; 412 char aBuf[MAX_MAN]; 413 char* pStr; 414 char cBuffer[ 30 ]; 415 int nLen; 416 LibExport *pData; 417 418 pfBase = fopen( cBName, "r" ); 419 420 if ( !pfBase ) 421 { 422 bBase = 0; 423 DumpError( 600 ); 424 } 425 426 bool bRet = true; 427 while( fgets( aBuf, MAX_MAN, pfBase ) != 0 ) 428 { 429 nLen = (int) strlen(aBuf); 430 pStr = new char[(unsigned int) nLen]; 431 if ( !pStr ) 432 DumpError( 98 ); 433 memcpy( pStr, aBuf, (size_t) nLen ); 434 if ( *(pStr+nLen-1) == '\n' ) 435 *(pStr+nLen-1) = '\0'; 436 pData = new LibExport; 437 pData->cExportName = pStr; 438 pData->nOrdinal = nBaseLines; 439 pData->bExport=false; 440 441 if (pBaseTab->Insert(pData->cExportName, pData ) == NULL) 442 bRet = false; 443 ltoa( (long) pData->nOrdinal, cBuffer, 10 ); 444 if (pIndexTab->Insert( cBuffer, pData ) == NULL) 445 bRet = false; 446 nBaseLines++; 447 if ( nBaseLines >= MAXBASE ) 448 DumpError( 610 ); 449 } 450 fclose( pfBase ); 451 return bRet; 452 } 453 454 class ExportSetIter : public HashTableIterator 455 { 456 public: 457 ExportSetIter(HashTable const& aTable) 458 : HashTableIterator(aTable) {} 459 460 LibExport * GetFirst() 461 { return (LibExport *)HashTableIterator::GetFirst(); } 462 LibExport * GetNext() 463 { return (LibExport *)HashTableIterator::GetNext(); } 464 LibExport * GetLast() 465 { return (LibExport *)HashTableIterator::GetLast(); } 466 LibExport * GetPrev() 467 { return (LibExport *)HashTableIterator::GetPrev(); } 468 469 private: 470 void operator =(ExportSetIter &); // not defined 471 }; 472 473 bool LibDump::PrintDataBase() 474 { 475 if (bExportName) 476 return true; 477 FILE *pFp; 478 pFp = fopen (cBName,"w+"); 479 if (!pFp) 480 fprintf( stderr, "Error opening DataBase File\n" ); 481 482 LibExport *pData; 483 for ( unsigned long i=0; i < nBaseLines+10; i++ ) 484 { 485 char * cBuffer = new char[ 30 ]; 486 sprintf( cBuffer, "%lu", i ); 487 pData = pIndexTab->Find( cBuffer ); 488 delete [] cBuffer; 489 if ( pData ) 490 fprintf(pFp,"%s\n",pData->cExportName); 491 } 492 fclose(pFp); 493 return true; 494 } 495 496 bool LibDump::PrintDefFile() 497 { 498 #ifdef FAST 499 ExportSetIter aIterator( *pBaseTab ); 500 for ( LibExport *pData = aIterator.GetFirst(); pData != NULL; 501 pData = aIterator.GetNext() ) 502 { 503 if ( pData->bExport ) 504 { 505 if ( pData->bByName ) 506 { 507 fprintf(stdout,"\t%s\n", 508 pData->sExportName.GetBuffer()); 509 } 510 else 511 { 512 fprintf(stdout,"\t%s\t\t@%d NONAME\n", 513 pData->sExportName.GetBuffer(), pData->nOrdinal+nBegin); 514 } 515 } 516 } 517 #else 518 // sortiert nach Ordinals; 519 LibExport *pData; 520 for ( unsigned long i=0; i<nBaseLines+1; i++) 521 { 522 char * cBuffer = new char[ 30 ]; 523 sprintf( cBuffer, "%lu", i ); 524 pData = pIndexTab->Find( cBuffer ); 525 delete [] cBuffer; 526 if ( pData ) 527 if ( pData->bExport ) 528 { 529 if ( pData->bByName ) 530 { 531 if ( strlen( pData->cExportName )) 532 fprintf(stdout,"\t%s\n", 533 pData->cExportName); 534 } 535 else 536 { 537 if ( strlen( pData->cExportName )) 538 fprintf(stdout,"\t%s\t\t@%d NONAME\n", 539 pData->cExportName, pData->nOrdinal+nBegin); 540 } 541 } 542 } 543 #endif 544 return true; 545 } 546 547 bool LibDump::CheckDataBase() 548 { 549 // existiert eine Datenbasis ? 550 if (!bBase) 551 { 552 cBName = new char[ 2048 ]; 553 char *pTmp = "defs\\"; 554 555 FILE *fp; 556 #ifdef OS2 557 _mkdir ("defs", 0777); 558 #else 559 _mkdir ("defs"); 560 #endif 561 strcpy(cBName,pTmp); 562 #ifdef OS2 563 strcat(cBName,"gcc"); 564 #else 565 strcat(cBName,getenv ("COMP_ENV")); 566 #endif 567 568 fp = fopen (cBName,"r"); 569 if (fp) 570 { 571 bBase = true; 572 } 573 else 574 { 575 fp = fopen (cBName,"w+"); 576 bBase = true; 577 } 578 fclose (fp); 579 } 580 // lese Datenbasis ! 581 if (bBase) 582 { 583 ReadDataBase(); 584 } 585 return true; 586 } 587 588 LibDump::~LibDump() 589 { 590 delete [] cBName; 591 delete [] cAPrefix; 592 // delete [] cLibName; 593 delete [] cFilterName; 594 delete [] cModName; 595 } 596 597 void LibDump::SetCExport( char* pName ) 598 { 599 delete [] cAPrefix; 600 cAPrefix = new char[ strlen( pName ) + 1 ]; 601 strcpy( cAPrefix, pName );bAll = true; 602 } 603 604 //****************************************************************** 605 //* Error() - Gibt Fehlermeldumg aus 606 //****************************************************************** 607 608 void LibDump::DumpError( unsigned long n ) 609 { 610 char *p; 611 612 switch (n) 613 { 614 case 1: p = "Input error in library file"; break; 615 case 2: p = "Position error in library file (no THEADR set)"; break; 616 case 3: p = "Overflow of symbol table"; break; 617 #ifdef WNT 618 case 10: p = "EXP file not found"; break; 619 case 11: p = "No valid EXP file"; break; 620 #else 621 case 10: p = "Library file not found"; break; 622 case 11: p = "No valid library file"; break; 623 #endif 624 case 98: p = "Out of memory"; break; 625 case 99: p = "LDUMP [-LD3] [-D] [-N] [-A] [-E nn] [-F name] Filename[.LIB]\n" 626 "-LD3 : Supports feature set of ldump3 (default: ldump/ldump2)\n" 627 "-A : all symbols (default: only C++)\n" 628 "-E nn : gerenration of export table beginning with number nn\n" 629 "-F name: Filter file\n" 630 "-D : file contains \"dumpbin\" directives\n" 631 "-N : export by name\n" 632 "-V : be verbose\n"; break; 633 case 500: p = "Unable to open filter file\n"; break; 634 case 510: p = "Overflow of filter table\n"; break; 635 case 600: p = "Unable to open base database file\n"; break; 636 case 610: p = "Overflow in base database table\n"; break; 637 default: p = "Unspecified error"; 638 } 639 fprintf( stdout, "%s\n", p ); 640 exit (1); 641 } 642 643 /********************************************************************* 644 Test Funktionen 645 *********************************************************************/ 646 647 648 void usage() 649 { 650 LibDump::DumpError(99); 651 } 652 653 #define STATE_NON 0x0000 654 #define STATE_BEGIN 0x0001 655 #define STATE_FILTER 0x0002 656 #define STATE_CEXPORT 0x0003 657 658 int 659 #ifdef WNT 660 __cdecl 661 #endif 662 main( int argc, char **argv ) 663 { 664 char *pLibName = NULL, *pFilterName = NULL, *pCExport= NULL; 665 unsigned short nBegin=1; 666 667 unsigned short nState = STATE_NON; 668 669 if ( argc == 1 ) { 670 usage(); 671 } 672 673 for ( int i = 1; i < argc; i++ ) { 674 if (( !strcmp( argv[ i ], "-H" )) || 675 ( !strcmp( argv[ i ], "-h" )) || 676 ( !strcmp( argv[ i ], "-?" ))) 677 { 678 usage(); 679 } 680 else if (( !strcmp( argv[ i ], "-LD3" )) || 681 ( !strcmp( argv[ i ], "-Ld3" )) || 682 ( !strcmp( argv[ i ], "-ld3" )) || 683 ( !strcmp( argv[ i ], "-lD3" ))) 684 { 685 if ( nState != STATE_NON ) { 686 usage(); 687 } 688 bLdump3 = 1; 689 } 690 else if (( !strcmp( argv[ i ], "-E" )) || ( !strcmp( argv[ i ], "-e" ))) { 691 if ( nState != STATE_NON ) { 692 usage(); 693 } 694 nState = STATE_BEGIN; 695 } 696 else if (( !strcmp( argv[ i ], "-F" )) || ( !strcmp( argv[ i ], "-f" ))) { 697 if ( nState != STATE_NON ) { 698 usage(); 699 } 700 nState = STATE_FILTER; 701 } 702 else if (( !strcmp( argv[ i ], "-A" )) || ( !strcmp( argv[ i ], "-a" ))) { 703 if ( nState != STATE_NON ) { 704 usage(); 705 } 706 nState = STATE_CEXPORT; 707 pCExport = new char[ 1 ]; 708 pCExport[ 0 ] = 0; 709 } 710 else if (( !strcmp( argv[ i ], "-D" )) || ( !strcmp( argv[ i ], "-d" ))) { 711 if ( nState != STATE_NON ) { 712 usage(); 713 } 714 bUseDirectives = 1; 715 } 716 else if (( !strcmp( argv[ i ], "-N" )) || ( !strcmp( argv[ i ], "-n" ))) { 717 if ( nState != STATE_NON ) { 718 usage(); 719 } 720 bExportByName = 1; 721 } 722 else if (( !strcmp( argv[ i ], "-V" )) || ( !strcmp( argv[ i ], "-v" ))) { 723 if ( nState != STATE_NON ) { 724 usage(); 725 } 726 bVerbose = 1; 727 } 728 else { 729 switch ( nState ) { 730 case STATE_BEGIN: 731 nBegin = static_cast< unsigned short >(atoi( argv[ i ] )); 732 nState = STATE_NON; 733 break; 734 case STATE_FILTER: 735 pFilterName = new char[ strlen( argv[ i ] ) + 1 ]; 736 strcpy( pFilterName, argv[ i ] ); 737 bFilter = 1; 738 nState = STATE_NON; 739 break; 740 case STATE_CEXPORT: 741 delete [] pCExport; 742 pCExport = new char[ strlen( argv[ i ] ) + 1 ]; 743 strcpy( pCExport, argv[ i ] ); 744 nState = STATE_NON; 745 break; 746 default: 747 pLibName = new char[ strlen( argv[ i ] ) + 1 ]; 748 strcpy( pLibName, argv[ i ] ); 749 break; 750 } 751 } 752 } 753 754 if ( !pLibName ) { 755 usage(); 756 } 757 758 LibDump *pDump = new LibDump( pLibName, bExportByName ); 759 pDump->SetBeginExport(nBegin); 760 if ( bFilter != 0 ) 761 pDump->SetFilter( pFilterName ); 762 if ( pCExport ) 763 pDump->SetCExport( pCExport ); 764 else { 765 char *pEmpty = ""; 766 pDump->SetCExport( pEmpty ); 767 } 768 pDump->Dump(); 769 pDump->PrintDefFile(); 770 pDump->PrintDataBase(); 771 delete pDump; 772 return 0; 773 } 774