321 lines
8.3 KiB
C++
321 lines
8.3 KiB
C++
|
#include <windows.h>
|
||
|
#include <stdio.h>
|
||
|
#include <string>
|
||
|
#include <set>
|
||
|
#include <iostream>
|
||
|
#include <algorithm>
|
||
|
#include <dbghelp.h>
|
||
|
|
||
|
#define F_USE_USH_NAME 0x000001
|
||
|
#define F_OUT_DIFF 0x000002
|
||
|
#define F_OUT_USH 0x000004
|
||
|
#define F_OUT_WCH 0x000008
|
||
|
#define F_OUT_IDEN 0x000010
|
||
|
#define F_OUT_DNAME 0x000020
|
||
|
#define F_OUT_ALL 0x00001e
|
||
|
using namespace std;
|
||
|
|
||
|
int flags = 0;
|
||
|
|
||
|
enum Ext { none, lib, dll};
|
||
|
char tmp[512];
|
||
|
|
||
|
Ext FindExt(const char *Fname)
|
||
|
{
|
||
|
Fname = strrchr(Fname, '.');
|
||
|
if ( Fname == NULL)
|
||
|
return none;
|
||
|
else if ( !stricmp(Fname, ".Lib"))
|
||
|
return lib;
|
||
|
else if ( !stricmp(Fname, ".Dll"))
|
||
|
return dll;
|
||
|
else
|
||
|
return none;
|
||
|
}
|
||
|
|
||
|
|
||
|
char *filter(char* ch, Ext fext)
|
||
|
{
|
||
|
char *str = strchr(ch, '?');
|
||
|
return str == NULL ? ch: str;
|
||
|
}
|
||
|
|
||
|
|
||
|
const char* setflags(int argc, char *argv[])
|
||
|
{
|
||
|
const char *Fname = NULL;
|
||
|
for (int i = 1; i < argc; i++)
|
||
|
{
|
||
|
if (argv[i][0] == '-' || argv[i][0] == '/')
|
||
|
{
|
||
|
for ( int j = 1; argv[i][j] != '\0'; j++)
|
||
|
{
|
||
|
switch (argv[i][j])
|
||
|
{
|
||
|
case 'u':
|
||
|
case 'U':
|
||
|
flags |= F_OUT_USH;
|
||
|
break;
|
||
|
case 'w':
|
||
|
case 'W':
|
||
|
flags |= F_OUT_WCH;
|
||
|
break;
|
||
|
case 'd':
|
||
|
case 'D':
|
||
|
flags |= F_OUT_DNAME;
|
||
|
break;
|
||
|
case 'i':
|
||
|
case 'I':
|
||
|
flags |= F_OUT_IDEN;
|
||
|
break;
|
||
|
case 'x':
|
||
|
case 'X':
|
||
|
flags |= F_USE_USH_NAME;
|
||
|
break;
|
||
|
default:
|
||
|
return NULL;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (!Fname)
|
||
|
Fname = argv[i];
|
||
|
else
|
||
|
return NULL;
|
||
|
}
|
||
|
}
|
||
|
if (!(flags & F_OUT_USH) && !(flags & F_OUT_WCH) && !(flags & F_OUT_IDEN))
|
||
|
flags |= F_OUT_ALL;
|
||
|
return Fname;
|
||
|
}
|
||
|
|
||
|
|
||
|
void print(string st)
|
||
|
{
|
||
|
if ( flags & F_OUT_DNAME)
|
||
|
{
|
||
|
if (UnDecorateSymbolName( st.c_str(), tmp, 511, 0))
|
||
|
cout << tmp << '\n';
|
||
|
else
|
||
|
cout << st << '\n';
|
||
|
} else {
|
||
|
cout << st << '\n';
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int funccmp(const char *func1, const char *func2)
|
||
|
{
|
||
|
while (*func1 != 0 && *func2 != 0)
|
||
|
{
|
||
|
if ( *func1 == *func2)
|
||
|
func1++, func2++;
|
||
|
else if ( func1 == strstr(func1, "_W") &&
|
||
|
func2 == strstr(func2, "G"))
|
||
|
func1 += sizeof("_W"), func2 += sizeof("G");
|
||
|
else if ( func2 == strstr(func2, "_W") &&
|
||
|
func1 == strstr(func1, "G"))
|
||
|
func2 += sizeof("_W"), func1 += sizeof("G");
|
||
|
else
|
||
|
break;
|
||
|
}
|
||
|
if (*func1 < *func2)
|
||
|
return -1;
|
||
|
else if (*func1 > *func2)
|
||
|
return 1;
|
||
|
else
|
||
|
return 0;
|
||
|
}
|
||
|
int Funccmp(const char *func1, const char *func2)
|
||
|
{
|
||
|
static char tmp1[512];
|
||
|
UnDecorateSymbolName(func1, tmp, 511, 0);
|
||
|
UnDecorateSymbolName(func2, tmp1, 511, 0);
|
||
|
func1 = tmp;
|
||
|
func2 = tmp1;
|
||
|
|
||
|
if (strstr(tmp, "wchar_t") || strstr(tmp, "unsigned short"))
|
||
|
return 11;
|
||
|
else if (strstr(tmp1, "wchar_t") || strstr(tmp1, "unsigned short"))
|
||
|
return 22;
|
||
|
|
||
|
while (*func1 != 0 && *func2 != 0)
|
||
|
{
|
||
|
if ( *func1 == *func2)
|
||
|
func1++, func2++;
|
||
|
else if ( func1 == strstr(func1, "wchar_t") &&
|
||
|
func2 == strstr(func2, "unsigned short"))
|
||
|
func1 += sizeof("wchar_t"), func2 += sizeof("unsigned short");
|
||
|
else if ( func2 == strstr(func2, "wchar_t") &&
|
||
|
func1 == strstr(func1, "unsigned short"))
|
||
|
func2 += sizeof("wchar_t"), func1 += sizeof("unsigned short");
|
||
|
else
|
||
|
break;
|
||
|
}
|
||
|
if (*func1 < *func2)
|
||
|
return -1;
|
||
|
else if (*func1 > *func2)
|
||
|
return 1;
|
||
|
else
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
int main(int argc, char *argv[])
|
||
|
{
|
||
|
FILE *phDumpbin;
|
||
|
Ext Fext;
|
||
|
const char *Fname;
|
||
|
int StripLine, i, result;
|
||
|
char ExeName[256];
|
||
|
char TmpStr[512];
|
||
|
char *tch;
|
||
|
set<string> Sdiff, Wdiff, Iden;
|
||
|
|
||
|
|
||
|
if (!(Fname = setflags(argc, argv)))
|
||
|
{
|
||
|
cout << "Usage : wsfdiff -[options] filename" << endl;
|
||
|
cout << "-x -X: Use unsigned char as data type in identical functions" << endl;
|
||
|
cout << "-u -U: Print diff with unsigned short version" << endl;
|
||
|
cout << "-w -W: Print diff with wchar_t version" << endl;
|
||
|
cout << "-i -I: Print Identical function" << endl;
|
||
|
cout << "-d -D: UnDname the function names" << endl;
|
||
|
cout << "filename can only have be .lib or .dll" << endl;
|
||
|
return -1;
|
||
|
}
|
||
|
strcpy(ExeName, "dumpbin ");
|
||
|
switch (Fext = FindExt(Fname))
|
||
|
{
|
||
|
case dll:
|
||
|
strcat(ExeName, "-exports ");
|
||
|
break;
|
||
|
case lib:
|
||
|
strcat(ExeName, "-linkermember ");
|
||
|
break;
|
||
|
case none:
|
||
|
return -1;
|
||
|
}
|
||
|
strcat(ExeName, Fname);
|
||
|
phDumpbin = _popen(ExeName, "r");
|
||
|
|
||
|
//Strip header
|
||
|
if (Fext == dll)
|
||
|
StripLine = 19;
|
||
|
else
|
||
|
StripLine = 18;
|
||
|
|
||
|
for ( i = 0; i < StripLine; i++)
|
||
|
{
|
||
|
fgets(TmpStr, 511, phDumpbin);
|
||
|
cerr << TmpStr;
|
||
|
}
|
||
|
set<string>::iterator spos, wpos;
|
||
|
while (fgets(TmpStr, 511, phDumpbin))
|
||
|
{
|
||
|
tch = filter(TmpStr, Fext);
|
||
|
tch[strlen(tch) -1] = '\0';
|
||
|
UnDecorateSymbolName(tch, tmp, 511, 0);
|
||
|
if (strstr (tmp, "wchar_t"))
|
||
|
{
|
||
|
spos = Sdiff.begin();
|
||
|
result = -1;
|
||
|
while(spos != Sdiff.end())
|
||
|
{
|
||
|
switch(result = funccmp(tch, (*spos).c_str()))
|
||
|
{
|
||
|
case 1:
|
||
|
++spos;
|
||
|
break;
|
||
|
case 0:
|
||
|
if (flags & F_USE_USH_NAME)
|
||
|
Iden.insert(*spos);
|
||
|
else
|
||
|
Iden.insert(string(tch));
|
||
|
Sdiff.erase(spos);
|
||
|
break;
|
||
|
}
|
||
|
if ( result != 1)
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
if (result != 0)
|
||
|
Wdiff.insert(string(tch));
|
||
|
} else if ( strstr(tmp, "unsigned short"))
|
||
|
{
|
||
|
spos = Wdiff.begin();
|
||
|
result = -1;
|
||
|
while(spos != Wdiff.end())
|
||
|
{
|
||
|
switch(result = funccmp(tch, (*spos).c_str()))
|
||
|
{
|
||
|
case 1:
|
||
|
++spos;
|
||
|
break;
|
||
|
case 0:
|
||
|
if (flags & F_USE_USH_NAME)
|
||
|
Iden.insert(string(tch));
|
||
|
else
|
||
|
Iden.insert(*spos);
|
||
|
Wdiff.erase(spos);
|
||
|
break;
|
||
|
}
|
||
|
if ( result != 1)
|
||
|
break;
|
||
|
}
|
||
|
if (result != 0)
|
||
|
Sdiff.insert(string(tch));
|
||
|
}
|
||
|
}
|
||
|
// final checks for diffs and validity
|
||
|
for ( wpos = Wdiff.begin(), spos = Sdiff.begin();
|
||
|
spos != Sdiff.end() && wpos != Wdiff.end();)
|
||
|
{
|
||
|
switch(Funccmp((*wpos).c_str(), (*spos).c_str()))
|
||
|
{
|
||
|
case 0:
|
||
|
if (flags & F_USE_USH_NAME)
|
||
|
Iden.insert(*spos);
|
||
|
else
|
||
|
Iden.insert(*wpos);
|
||
|
spos = Sdiff.erase(spos);
|
||
|
wpos = Wdiff.erase(wpos);
|
||
|
break;
|
||
|
case 1:
|
||
|
++spos;
|
||
|
break;
|
||
|
case -1:
|
||
|
++wpos;
|
||
|
break;
|
||
|
case 11:
|
||
|
wpos = Wdiff.erase(wpos);
|
||
|
break;
|
||
|
case 22:
|
||
|
spos = Sdiff.erase(spos);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( flags & F_OUT_USH)
|
||
|
{
|
||
|
cout << "Only Unsigned Short version " << Sdiff.size() << '\n';
|
||
|
for_each (Sdiff.begin(), Sdiff.end(), print);
|
||
|
cout <<"-----------------------------------------------------------\n";
|
||
|
}
|
||
|
|
||
|
if ( flags & F_OUT_WCH)
|
||
|
{
|
||
|
cout << "Only wchar_t versions " << Wdiff.size() << '\n';
|
||
|
for_each (Wdiff.begin(), Wdiff.end(), print);
|
||
|
cout <<"-----------------------------------------------------------\n";
|
||
|
}
|
||
|
|
||
|
if ( flags & F_OUT_IDEN)
|
||
|
{
|
||
|
cout <<"Both the versions are present " << Iden.size() << '\n';
|
||
|
for_each (Iden.begin(), Iden.end(), print );
|
||
|
cout <<"-----------------------------------------------------------\n";
|
||
|
}
|
||
|
return 1;
|
||
|
}
|