00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056 static char sccsid[] = "@(#) winDumpExts.c 1.2 95/10/03 15:27:34";
00057
00058 #include <windows.h>
00059 #include <stdio.h>
00060 #include <string>
00061 #include <fstream>
00062
00063
00064
00065
00066
00067
00068
00069
00070 int
00071 GetArgcArgv(std::string &s, char **argv)
00072 {
00073 int quote = 0;
00074 int argc = 0;
00075 std::string::iterator bp = s.begin();
00076
00077 while (1) {
00078 while (isspace(*bp)) {
00079 bp++;
00080 }
00081 if (*bp == '\n' || *bp == '\0') {
00082 *bp = '\0';
00083 return argc;
00084 }
00085 if (*bp == '\"') {
00086 quote = 1;
00087 bp++;
00088 }
00089 argv[argc++] = &(*bp);
00090
00091 while (*bp != '\0') {
00092 if (quote) {
00093 if (*bp == '\"') {
00094 quote = 0;
00095 *bp = '\0';
00096 bp++;
00097 break;
00098 }
00099 bp++;
00100 continue;
00101 }
00102 if (isspace(*bp)) {
00103 *bp = '\0';
00104 bp++;
00105 break;
00106 }
00107 bp++;
00108 }
00109 }
00110 }
00111
00112
00113
00114
00115 char * SzStorageClass1[] = {
00116 "NULL","AUTOMATIC","EXTERNAL","STATIC","REGISTER","EXTERNAL_DEF","LABEL",
00117 "UNDEFINED_LABEL","MEMBER_OF_STRUCT","ARGUMENT","STRUCT_TAG",
00118 "MEMBER_OF_UNION","UNION_TAG","TYPE_DEFINITION","UNDEFINED_STATIC",
00119 "ENUM_TAG","MEMBER_OF_ENUM","REGISTER_PARAM","BIT_FIELD"
00120 };
00121
00122
00123
00124
00125 char * SzStorageClass2[] = {
00126 "BLOCK","FUNCTION","END_OF_STRUCT","FILE","SECTION","WEAK_EXTERNAL"
00127 };
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137 PSTR
00138 GetSZStorageClass(BYTE storageClass)
00139 {
00140 if ( storageClass <= IMAGE_SYM_CLASS_BIT_FIELD )
00141 return SzStorageClass1[storageClass];
00142 else if ( (storageClass >= IMAGE_SYM_CLASS_BLOCK)
00143 && (storageClass <= IMAGE_SYM_CLASS_WEAK_EXTERNAL) )
00144 return SzStorageClass2[storageClass-IMAGE_SYM_CLASS_BLOCK];
00145 else
00146 return "???";
00147 }
00148
00149 void AddHex(std::string& buf, long val, bool caps=false)
00150 {
00151 buf += "0x";
00152 int len=buf.length();
00153 while (val) {
00154 char hex = (char)(val & 16);
00155 val = val >> 4;
00156 if (hex<10) hex+='0';
00157 else if (caps) hex+='A'-10;
00158 else hex+='a'-10;
00159 buf.insert(len, hex, 1);
00160 }
00161 }
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174 void
00175 GetSectionName(PIMAGE_SYMBOL pSymbolTable, std::string& buffer)
00176 {
00177 DWORD section;
00178
00179 section = pSymbolTable->SectionNumber;
00180
00181 switch ( (SHORT)section )
00182 {
00183 case IMAGE_SYM_UNDEFINED: if (pSymbolTable->Value) buffer += "COMM"; else buffer += "UNDEF"; break;
00184 case IMAGE_SYM_ABSOLUTE: buffer += "ABS "; break;
00185 case IMAGE_SYM_DEBUG: buffer += "DEBUG"; break;
00186 default: AddHex(buffer, section, true);
00187 }
00188 }
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201 void
00202 GetSectionCharacteristics(PIMAGE_SECTION_HEADER pSectionHeaders, int nSectNum, std::string &buffer)
00203 {
00204 DWORD SectChar;
00205 std::string TempBuf;
00206 buffer.clear();
00207 if (nSectNum > 0) {
00208 SectChar = pSectionHeaders[nSectNum-1].Characteristics;
00209
00210 buffer = " ";
00211 AddHex(buffer, SectChar);
00212 if (SectChar & IMAGE_SCN_CNT_CODE) buffer += " Code";
00213 else if (SectChar & IMAGE_SCN_CNT_INITIALIZED_DATA) buffer += " Init. data";
00214 else if (SectChar & IMAGE_SCN_CNT_UNINITIALIZED_DATA ) buffer += " UnInit data";
00215 else buffer += " Unknow type";
00216
00217 if (SectChar & IMAGE_SCN_MEM_READ) {
00218 buffer += " Read";
00219 if (SectChar & IMAGE_SCN_MEM_WRITE)
00220 buffer += " and Write";
00221 else buffer += " only";
00222 }
00223 else if (SectChar & IMAGE_SCN_MEM_WRITE)
00224 buffer +=" Write only";
00225
00226 }
00227 }
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237 void
00238 DumpSymbolTable(PIMAGE_SYMBOL pSymbolTable, PIMAGE_SECTION_HEADER pSectionHeaders, FILE *fout, unsigned cSymbols)
00239 {
00240 unsigned i;
00241 PSTR stringTable;
00242 std::string sectionName;
00243 std::string sectionCharacter;
00244 int iSectNum;
00245
00246 fprintf(fout, "Symbol Table - %X entries (* = auxillary symbol)\n",
00247 cSymbols);
00248
00249 fprintf(fout,
00250 "Indx Name Value Section cAux Type Storage Character\n"
00251 "---- -------------------- -------- ---------- ----- ------- -------- ---------\n");
00252
00253
00254
00255
00256 stringTable = (PSTR)&pSymbolTable[cSymbols];
00257
00258 for ( i=0; i < cSymbols; i++ ) {
00259 fprintf(fout, "%04X ", i);
00260 if ( pSymbolTable->N.Name.Short != 0 )
00261 fprintf(fout, "%-20.8s", pSymbolTable->N.ShortName);
00262 else
00263 fprintf(fout, "%-20s", stringTable + pSymbolTable->N.Name.Long);
00264
00265 fprintf(fout, " %08X", pSymbolTable->Value);
00266
00267 iSectNum = pSymbolTable->SectionNumber;
00268 GetSectionName(pSymbolTable, sectionName);
00269 fprintf(fout, " sect:%s aux:%X type:%02X st:%s",
00270 sectionName.c_str(),
00271 pSymbolTable->NumberOfAuxSymbols,
00272 pSymbolTable->Type,
00273 GetSZStorageClass(pSymbolTable->StorageClass) );
00274
00275 GetSectionCharacteristics(pSectionHeaders,iSectNum,sectionCharacter);
00276 fprintf(fout," hc: %s \n",sectionCharacter.c_str());
00277 #if 0
00278 if ( pSymbolTable->NumberOfAuxSymbols )
00279 DumpAuxSymbols(pSymbolTable);
00280 #endif
00281
00282
00283
00284
00285 i += pSymbolTable->NumberOfAuxSymbols;
00286 pSymbolTable += pSymbolTable->NumberOfAuxSymbols;
00287 pSymbolTable++;
00288 }
00289 }
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299 void
00300 DumpExternals(PIMAGE_SYMBOL pSymbolTable, FILE *fout, unsigned cSymbols)
00301 {
00302 unsigned i;
00303 PSTR stringTable;
00304 std::string symbol;
00305
00306
00307
00308
00309 stringTable = (PSTR)&pSymbolTable[cSymbols];
00310
00311 for ( i=0; i < cSymbols; i++ ) {
00312 if (pSymbolTable->SectionNumber > 0 && pSymbolTable->Type == 0x20) {
00313 if (pSymbolTable->StorageClass == IMAGE_SYM_CLASS_EXTERNAL) {
00314 if (pSymbolTable->N.Name.Short != 0) {
00315 symbol = "";
00316 symbol.insert(0, (const char *)(pSymbolTable->N.ShortName), 8);
00317 } else {
00318 symbol = stringTable + pSymbolTable->N.Name.Long;
00319 }
00320 std::string::size_type posAt = symbol.find('@');
00321 if (posAt != std::string::npos) symbol.erase(posAt);
00322 #ifndef _MSC_VER
00323 fprintf(fout, "\t%s\n", symbol.c_str());
00324 #else
00325 fprintf(fout, "\t%s\n", symbol.c_str()+1);
00326 #endif
00327 }
00328 }
00329
00330
00331
00332
00333 i += pSymbolTable->NumberOfAuxSymbols;
00334 pSymbolTable += pSymbolTable->NumberOfAuxSymbols;
00335 pSymbolTable++;
00336 }
00337 }
00338
00339
00340
00341
00342 const char* StrNStr(const char* start, const char* find, size_t &size) {
00343 int len;
00344 const char* hint;
00345
00346 if (!start || !find || !size) {
00347 size = 0;
00348 return 0;
00349 }
00350 len = strlen(find);
00351
00352 while (hint = (const char*) memchr(start, find[0], size-len+1)) {
00353 size -= (hint - start);
00354 if (!strncmp(hint, find, len))
00355 return hint;
00356 start = hint + 1;
00357 }
00358
00359 size = 0;
00360 return 0;
00361 }
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371 int
00372 HaveExportedObjects(PIMAGE_FILE_HEADER pImageFileHeader, PIMAGE_SECTION_HEADER pSectionHeaders, FILE *fout)
00373 {
00374 static int fImportFlag = 0;
00375 WORD i;
00376 size_t size;
00377 char foundExports;
00378 const char * rawdata;
00379
00380 PIMAGE_SECTION_HEADER pDirectivesSectionHeader;
00381
00382 if (fImportFlag) return 1;
00383
00384 i = 0;
00385 foundExports = 0;
00386 pDirectivesSectionHeader = 0;
00387 for(i = 0; i < pImageFileHeader->NumberOfSections && !pDirectivesSectionHeader; i++)
00388 if (!strncmp((const char*)&pSectionHeaders[i].Name[0], ".drectve",8))
00389 pDirectivesSectionHeader = &pSectionHeaders[i];
00390 if (!pDirectivesSectionHeader) return 0;
00391
00392 rawdata=(const char*)pImageFileHeader+pDirectivesSectionHeader->PointerToRawData;
00393 if (!pDirectivesSectionHeader->PointerToRawData || !rawdata) return 0;
00394
00395 size = pDirectivesSectionHeader->SizeOfRawData;
00396 const char* posImportFlag = rawdata;
00397 while ((posImportFlag = StrNStr(posImportFlag, " /EXPORT:", size))) {
00398 const char* lookingForDict = posImportFlag + 9;
00399 if (!strncmp(lookingForDict, "_G__cpp_",8) ||
00400 !strncmp(lookingForDict, "_G__set_cpp_",12)) {
00401 posImportFlag = lookingForDict;
00402 continue;
00403 }
00404
00405 const char* lookingForDATA = posImportFlag + 9;
00406 while (*(++lookingForDATA) && *lookingForDATA != ' ');
00407 lookingForDATA -= 5;
00408
00409 if (strncmp(lookingForDATA, ",DATA", 5)) break;
00410 posImportFlag = lookingForDATA + 5;
00411 }
00412 fImportFlag = (int)posImportFlag;
00413 return fImportFlag;
00414 }
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426 void
00427 DumpExternalsObjects(PIMAGE_SYMBOL pSymbolTable, PIMAGE_SECTION_HEADER pSectionHeaders,
00428 FILE *fout, unsigned cSymbols, int fort)
00429 {
00430 unsigned i;
00431 PSTR stringTable;
00432 std::string symbol;
00433 DWORD SectChar;
00434 static int fImportFlag = -1;
00435
00436
00437
00438
00439 stringTable = (PSTR)&pSymbolTable[cSymbols];
00440
00441 for ( i=0; i < cSymbols; i++ ) {
00442 if (pSymbolTable->SectionNumber > 0 && ( pSymbolTable->Type == 0x20 || pSymbolTable->Type == 0x0)) {
00443 if (pSymbolTable->StorageClass == IMAGE_SYM_CLASS_EXTERNAL) {
00444
00445
00446
00447 if (pSymbolTable->N.Name.Short != 0) {
00448 symbol = "";
00449 symbol.insert(0, (const char *)pSymbolTable->N.ShortName, 8);
00450 } else {
00451 symbol = stringTable + pSymbolTable->N.Name.Long;
00452 }
00453
00454 while (isspace(symbol[0])) symbol.erase(0,1);
00455 #ifdef _MSC_VER
00456 if (symbol[0] == '_') symbol.erase(0,1);
00457 if (fort) {
00458 std::string::size_type posAt = symbol.find('@');
00459 if (posAt != std::string::npos) symbol.erase(posAt);
00460 }
00461 #endif
00462 if (fImportFlag) {
00463 fImportFlag = 0;
00464 fprintf(fout,"EXPORTS \n");
00465 }
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475 const char *scalarPrefix = "??_G";
00476 const char *vectorPrefix = "??_E";
00477 if (symbol.compare(0, 4, scalarPrefix) &&
00478 symbol.compare(0, 4, vectorPrefix) &&
00479 symbol.find("real@") == std::string::npos)
00480 {
00481 SectChar = pSectionHeaders[pSymbolTable->SectionNumber-1].Characteristics;
00482 if (!pSymbolTable->Type && (SectChar & IMAGE_SCN_MEM_WRITE)) {
00483
00484 fprintf(fout, "\t%s \t DATA\n", symbol.c_str());
00485 } else {
00486 if ( pSymbolTable->Type || !(SectChar & IMAGE_SCN_MEM_READ)) {
00487 fprintf(fout, "\t%s\n", symbol.c_str());
00488 } else {
00489
00490 }
00491 }
00492 }
00493 }
00494 }
00495 else if (pSymbolTable->SectionNumber == IMAGE_SYM_UNDEFINED && !pSymbolTable->Type && 0){
00496
00497
00498
00499 if (pSymbolTable->StorageClass == IMAGE_SYM_CLASS_EXTERNAL) {
00500 symbol = stringTable + pSymbolTable->N.Name.Long;
00501 while (isspace(symbol[0])) symbol.erase(0,1);
00502 if (symbol[0] == '_') symbol.erase(0,1);
00503 if (!fImportFlag) {
00504 fImportFlag = 1;
00505 fprintf(fout,"IMPORTS \n");
00506 }
00507 fprintf(fout, "\t%s DATA \n", symbol.c_str()+1);
00508 }
00509 }
00510
00511
00512
00513
00514 i += pSymbolTable->NumberOfAuxSymbols;
00515 pSymbolTable += pSymbolTable->NumberOfAuxSymbols;
00516 pSymbolTable++;
00517 }
00518 }
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528 void
00529 DumpObjFile(PIMAGE_FILE_HEADER pImageFileHeader, FILE *fout, int full, int fort)
00530 {
00531 PIMAGE_SYMBOL PCOFFSymbolTable;
00532 PIMAGE_SECTION_HEADER PCOFFSectionHeaders;
00533 DWORD COFFSymbolCount;
00534
00535 PCOFFSymbolTable = (PIMAGE_SYMBOL)
00536 ((DWORD)pImageFileHeader + pImageFileHeader->PointerToSymbolTable);
00537 COFFSymbolCount = pImageFileHeader->NumberOfSymbols;
00538
00539 PCOFFSectionHeaders = (PIMAGE_SECTION_HEADER)
00540 ((DWORD)pImageFileHeader +
00541 IMAGE_SIZEOF_FILE_HEADER +
00542 pImageFileHeader->SizeOfOptionalHeader);
00543
00544
00545 if (full) {
00546 DumpSymbolTable(PCOFFSymbolTable, PCOFFSectionHeaders, fout, COFFSymbolCount);
00547 } else {
00548 int haveExports = HaveExportedObjects(pImageFileHeader, PCOFFSectionHeaders, fout);
00549 if (!haveExports)
00550 DumpExternalsObjects(PCOFFSymbolTable, PCOFFSectionHeaders, fout, COFFSymbolCount, fort);
00551 }
00552 }
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562 void
00563 DumpFile(LPSTR filename, FILE *fout, int full, int fort)
00564 {
00565 HANDLE hFile;
00566 HANDLE hFileMapping;
00567 LPVOID lpFileBase;
00568 PIMAGE_DOS_HEADER dosHeader;
00569
00570 hFile = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL,
00571 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
00572
00573 if (hFile == INVALID_HANDLE_VALUE) {
00574 fprintf(stderr, "Couldn't open file with CreateFile()\n");
00575 return;
00576 }
00577
00578 hFileMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
00579 if (hFileMapping == 0) {
00580 CloseHandle(hFile);
00581 fprintf(stderr, "Couldn't open file mapping with CreateFileMapping()\n");
00582 return;
00583 }
00584
00585 lpFileBase = MapViewOfFile(hFileMapping, FILE_MAP_READ, 0, 0, 0);
00586 if (lpFileBase == 0) {
00587 CloseHandle(hFileMapping);
00588 CloseHandle(hFile);
00589 fprintf(stderr, "Couldn't map view of file with MapViewOfFile()\n");
00590 return;
00591 }
00592
00593 dosHeader = (PIMAGE_DOS_HEADER)lpFileBase;
00594 if (dosHeader->e_magic == IMAGE_DOS_SIGNATURE) {
00595 #if 0
00596 DumpExeFile( dosHeader );
00597 #else
00598 fprintf(stderr, "File is an executable. I don't dump those.\n");
00599 return;
00600 #endif
00601 }
00602
00603 else if ((dosHeader->e_magic == 0x014C) && (dosHeader->e_sp == 0)) {
00604
00605
00606
00607
00608
00609 DumpObjFile((PIMAGE_FILE_HEADER) lpFileBase, fout, full, fort);
00610 } else {
00611 printf("unrecognized file format\n");
00612 }
00613 UnmapViewOfFile(lpFileBase);
00614 CloseHandle(hFileMapping);
00615 CloseHandle(hFile);
00616 }
00617
00618 void
00619 main(int argc, char **argv)
00620 {
00621 std::string cmdline;
00622 int i, arg;
00623 FILE *fout;
00624 int full = 0;
00625 int fort = 0;
00626 char *dllname = "";
00627 char *outfile = NULL;
00628
00629 if (argc < 3) {
00630 Usage:
00631 fprintf(stderr, "Usage: %s ?-o outfile? ?-f(ull)? <dllname> <object filenames> ..\n", argv[0]);
00632 exit(1);
00633 }
00634
00635 arg = 1;
00636 while (argv[arg][0] == '-') {
00637 if (strcmp(argv[arg], "--") == 0) {
00638 arg++;
00639 break;
00640 } else if (strcmp(argv[arg], "-f") == 0) {
00641 full = 1;
00642 } else if (strcmp(argv[arg], "-x") == 0) {
00643 fort = 1;
00644 } else if (strcmp(argv[arg], "-o") == 0) {
00645 arg++;
00646 if (arg == argc) {
00647 goto Usage;
00648 }
00649 outfile = argv[arg];
00650 }
00651 arg++;
00652 }
00653 if (arg == argc) {
00654 goto Usage;
00655 }
00656
00657 if (outfile) {
00658 fout = fopen(outfile, "w+");
00659 if (fout == NULL) {
00660 fprintf(stderr, "Unable to open \'%s\' for writing:\n",
00661 argv[arg]);
00662 perror("");
00663 exit(1);
00664 }
00665 } else {
00666 fout = stdout;
00667 }
00668
00669 if (! full) {
00670 dllname = argv[arg];
00671 arg++;
00672 if (arg == argc) {
00673 goto Usage;
00674 }
00675 fprintf(fout, "LIBRARY %s\n", dllname);
00676 #ifndef _X86_
00677 fprintf(fout, "CODE PRELOAD MOVEABLE DISCARDABLE\n");
00678 fprintf(fout, "DATA PRELOAD MOVEABLE MULTIPLE\n\n");
00679 #endif
00680 }
00681
00682 for (; arg < argc; arg++) {
00683 WIN32_FIND_DATA FindFileData;
00684 HANDLE SearchFile;
00685 if (argv[arg][0] == '@') {
00686 std::ifstream fargs(&argv[arg][1]);
00687 if (!fargs) {
00688 fprintf(stderr, "Unable to open \'%s\' for reading:\n",
00689 argv[arg]);
00690 perror("");
00691 exit(1);
00692 }
00693 char *fargv[1000];
00694 for (i = 0; i < arg; i++) {
00695 cmdline += argv[i];
00696 fargv[i] = argv[i];
00697 }
00698 std::string line;
00699 std::getline(fargs, line);
00700 cmdline += line;
00701 fprintf(stderr, "%s\n", line.c_str());
00702 i += GetArgcArgv(line, &fargv[i]);
00703 argc = i;
00704 argv = fargv;
00705 }
00706
00707
00708
00709 SearchFile = FindFirstFile(argv[arg],&FindFileData);
00710 if (SearchFile == INVALID_HANDLE_VALUE){
00711 fprintf(stderr, "Unable to find \'%s\' for reading:\n",
00712 argv[arg]);
00713 exit(1);
00714 }
00715 else {
00716
00717
00718
00719 TCHAR *filename = argv[arg];
00720 TCHAR path[2048];
00721 int i = strlen(filename);
00722 i--;
00723 while( filename[i] != '\\' && filename[i] != '/' && i >=0) i--;
00724 do
00725 {
00726 if (i >= 0) strncpy( path, filename, i+1);
00727 path[i+1] = '\0';
00728 DumpFile(strcat(path, FindFileData.cFileName), fout, full, fort);
00729 } while (FindNextFile(SearchFile,&FindFileData));
00730
00731
00732 FindClose(SearchFile);
00733 }
00734 }
00735 exit(0);
00736 }