xref: /trunk/main/soltools/ldump/ldump.cxx (revision 91144cd0085a7583d2099b982122deb2184ab956)
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:
ExportSet(unsigned long lSize,double dMaxLoadFactor=HashTable::m_defMaxLoadFactor,double dGrowFactor=HashTable::m_defDefGrowFactor)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 
~ExportSet()56     virtual ~ExportSet() {}
57 
Find(char * const & Key) const58     LibExport *  Find (char * const& Key) const
59     { return (LibExport *) HashTable::Find((char *) Key); }
60 
Insert(char * const & Key,LibExport * Object)61     bool Insert (char * const& Key, LibExport * Object)
62     { return HashTable::Insert((char *) Key, (void*) Object); }
63 
Delete(char * const & Key)64     LibExport *  Delete (char * const&Key)
65     { return (LibExport *) HashTable::Delete ((char *) Key); }
66 };
67 
LibDump(char * cFileName,int bExportByName)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 
Dump()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 
ReadFilter(char * cFilterName)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 
PrintSym(char * pName,bool bName)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 
IsFromAnonymousNamespace(char * pExportName)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 
Filter(char * pExportName)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 
SetFilter(char * cFilterName)395 bool LibDump::SetFilter(char * cFilterName)
396 {
397     ReadFilter( cFilterName );
398     return true;
399 }
400 
CheckLibrary(char * cName)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 
ReadDataBase()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:
ExportSetIter(HashTable const & aTable)457     ExportSetIter(HashTable const& aTable)
458         : HashTableIterator(aTable) {}
459 
GetFirst()460     LibExport * GetFirst()
461     { return (LibExport *)HashTableIterator::GetFirst(); }
GetNext()462     LibExport * GetNext()
463     { return (LibExport *)HashTableIterator::GetNext();  }
GetLast()464     LibExport * GetLast()
465     { return (LibExport *)HashTableIterator::GetLast();  }
GetPrev()466     LibExport * GetPrev()
467     { return (LibExport *)HashTableIterator::GetPrev();  }
468 
469 private:
470     void operator =(ExportSetIter &); // not defined
471 };
472 
PrintDataBase()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 
PrintDefFile()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 
CheckDataBase()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 
~LibDump()588 LibDump::~LibDump()
589 {
590     delete [] cBName;
591     delete [] cAPrefix;
592 //  delete [] cLibName;
593     delete [] cFilterName;
594     delete [] cModName;
595 }
596 
SetCExport(char * pName)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 
DumpError(unsigned long n)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 
usage()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
main(int argc,char ** argv)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