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 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
ReadFilter(char * cFilterName)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
PrintSym(char * pName,bool bName)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
IsFromAnonymousNamespace(char * pExportName)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
Filter(char * pExportName)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
SetFilter(char * cFilterName)376 bool LibDump::SetFilter(char * cFilterName)
377 {
378 ReadFilter( cFilterName );
379 return true;
380 }
381
CheckLibrary(char * cName)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
ReadDataBase()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:
ExportSetIter(HashTable const & aTable)438 ExportSetIter(HashTable const& aTable)
439 : HashTableIterator(aTable) {}
440
GetFirst()441 LibExport * GetFirst()
442 { return (LibExport *)HashTableIterator::GetFirst(); }
GetNext()443 LibExport * GetNext()
444 { return (LibExport *)HashTableIterator::GetNext(); }
GetLast()445 LibExport * GetLast()
446 { return (LibExport *)HashTableIterator::GetLast(); }
GetPrev()447 LibExport * GetPrev()
448 { return (LibExport *)HashTableIterator::GetPrev(); }
449
450 private:
451 void operator =(ExportSetIter &); // not defined
452 };
453
PrintDataBase()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
PrintDefFile()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
CheckDataBase()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
~LibDump()569 LibDump::~LibDump()
570 {
571 delete [] cBName;
572 delete [] cAPrefix;
573 // delete [] cLibName;
574 delete [] cFilterName;
575 delete [] cModName;
576 }
577
SetCExport(char * pName)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
DumpError(unsigned long n)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
usage()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
main(int argc,char ** argv)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