xref: /trunk/main/soltools/ldump/ldump.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
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