You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
214 lines
7.3 KiB
214 lines
7.3 KiB
// dump2def.cxx - Written and placed in public domain by Jeffrey Walton |
|
// Create a module definitions file from a dumpbin file. |
|
// dump2def can be used to create a list of exports from |
|
// a static library. Then, the exports can used to build |
|
// a dynamic link library with the same exports. |
|
// |
|
// If you wish to compile this source file using cl.exe, then: |
|
// cl.exe /DNDEBUG /Oi /Oy /O2 /Zi /TP /GR /EHsc /MT dump2def.cxx |
|
// |
|
// The intended workflow in Crypto++ is: |
|
// |
|
// 1. Open a Developer Prompt |
|
// 2. CD to cryptopp/ directory |
|
// 3. nmake /f cryptest.nmake cryptopp.dll |
|
// |
|
// The cryptopp.dll recipe first builds cryptlib.lib. Then it calls |
|
// dumpbin.exe to export all symbols from cryptlib.lib and writes them |
|
// to cryptopp.dump. The recipe then calls dump2def.exe to create a |
|
// module definition file. Finally, the recipe builds cryptopp.dll |
|
// using the module definition file cryptopp.def. The linker creates |
|
// the import lib cryptopp.lib and export cryptopp.exp automatically. |
|
// |
|
// This is only "half the problem solved" for those who wish to use |
|
// a DLL. The program must import the import lib cryptopp.lib. Then |
|
// the program must ensure the library headers export the symbol or |
|
// class with CRYPTOPP_DLL. CRYPTOPP_DLL is only present on some classes |
|
// because the FIPS module only allowed approved algorithms like AES and |
|
// SHA. Other classes like Base64Encoder and HexEncoder lack CRYPTOPP_DLL. |
|
// |
|
// CRYPTOPP_DLL simply adds declspec(dllimport) when CRYPTOPP_IMPORTS is |
|
// defined. The limitation of requiring declspec(dllimport) is imposed by |
|
// Microsoft. Microsoft does not allow a program to "import everything". |
|
// |
|
// If you would like to read more about the FIPS module and the pain it |
|
// causes then see https://www.cryptopp.com/wiki/FIPS_DLL. In fact we |
|
// recommend you delete the CryptDll and DllTest projects from the |
|
// Visual Studio solution file. |
|
|
|
#include <iostream> |
|
#include <fstream> |
|
#include <sstream> |
|
#include <string> |
|
#include <vector> |
|
#include <set> |
|
|
|
// Friendly name |
|
#define LIBRARY_DESC "Crypto++ Library" |
|
typedef std::set<std::string> SymbolMap; |
|
|
|
const int ErrorSuccess = 0; |
|
const int ErrorDumpExtension = 1; |
|
const int ErrorTooFewOpts = 2; |
|
const int ErrorTooManyOpts = 3; |
|
const int ErrorOpenInputFailed = 4; |
|
const int ErrorOpenOutputFailed = 5; |
|
const int ErrorReadException = 6; |
|
const int ErrorWriteException = 7; |
|
|
|
void PrintHelpAndExit(int code) |
|
{ |
|
std::cout << "dump2def - create a module definitions file from a dumpbin file" << std::endl; |
|
std::cout << " Written and placed in public domain by Jeffrey Walton" << std::endl; |
|
std::cout << std::endl; |
|
|
|
switch (code) |
|
{ |
|
case ErrorDumpExtension: |
|
std::cout << "Error: input file is missing \".dump\" extension.\n" << std::endl; |
|
break; |
|
case ErrorTooFewOpts: |
|
std::cout << "Error: Too few options were supplied.\n" << std::endl; |
|
break; |
|
case ErrorTooManyOpts: |
|
std::cout << "Error: Too many options were supplied.\n" << std::endl; |
|
break; |
|
case ErrorOpenInputFailed: |
|
std::cout << "Error: Failed to open input file.\n" << std::endl; |
|
break; |
|
case ErrorOpenOutputFailed: |
|
std::cout << "Error: Failed to open output file.\n" << std::endl; |
|
break; |
|
default: |
|
;; |
|
} |
|
|
|
std::cout << "Usage: " << std::endl; |
|
|
|
std::cout << " dump2def <infile>" << std::endl; |
|
std::cout << " - Create a def file from <infile> and write it to a file with" << std::endl; |
|
std::cout << " the same name as <infile> but using the .def extension" << std::endl; |
|
|
|
std::cout << " dump2def <infile> <outfile>" << std::endl; |
|
std::cout << " - Create a def file from <infile> and write it to <outfile>" << std::endl; |
|
|
|
std::exit((code == ErrorSuccess ? 0 : 1)); |
|
} |
|
|
|
int main(int argc, char* argv[]) |
|
{ |
|
// ******************** Handle Options ******************** // |
|
|
|
// Convenience item |
|
std::vector<std::string> opts; |
|
for (size_t i=0; i<argc; ++i) |
|
opts.push_back(argv[i]); |
|
|
|
// Look for help |
|
std::string opt = (opts.size() > 1 ? opts[1].substr(0,2) : ""); |
|
if (opt == "/h" || opt == "-h" || opt == "/?" || opt == "-?") |
|
PrintHelpAndExit(ErrorSuccess); |
|
|
|
// Add <outfile> as needed |
|
if (opts.size() == 2) |
|
{ |
|
std::string outfile = opts[1]; |
|
std::string::size_type pos = outfile.length() < 5 ? std::string::npos : outfile.length() - 5; |
|
if (pos == std::string::npos || outfile.substr(pos) != ".dump") |
|
PrintHelpAndExit(ErrorDumpExtension); |
|
|
|
outfile.replace(pos, 5, ".def"); |
|
opts.push_back(outfile); |
|
} |
|
|
|
// Check or exit |
|
if (opts.size() < 2) |
|
PrintHelpAndExit(ErrorTooFewOpts); |
|
if (opts.size() > 3) |
|
PrintHelpAndExit(ErrorTooManyOpts); |
|
|
|
// ******************** Read MAP file ******************** // |
|
|
|
SymbolMap symbols; |
|
|
|
try |
|
{ |
|
std::ifstream infile(opts[1].c_str()); |
|
|
|
if (infile.is_open() == false) |
|
PrintHelpAndExit(ErrorOpenInputFailed); |
|
|
|
std::string::size_type pos; |
|
std::string line; |
|
|
|
// Find start of the symbol table |
|
while (std::getline(infile, line)) |
|
{ |
|
pos = line.find("public symbols"); |
|
if (pos == std::string::npos) { continue; } |
|
|
|
// Eat the whitespace after the table heading |
|
infile >> std::ws; |
|
break; |
|
} |
|
|
|
while (std::getline(infile, line)) |
|
{ |
|
// End of table |
|
if (line.empty()) { break; } |
|
|
|
std::istringstream iss(line); |
|
std::string address, symbol; |
|
iss >> address >> symbol; |
|
|
|
symbols.insert(symbol); |
|
} |
|
} |
|
catch (const std::exception& ex) |
|
{ |
|
std::cerr << "Unexpected exception:" << std::endl; |
|
std::cerr << ex.what() << std::endl; |
|
std::cerr << std::endl; |
|
|
|
PrintHelpAndExit(ErrorReadException); |
|
} |
|
|
|
// ******************** Write DEF file ******************** // |
|
|
|
try |
|
{ |
|
std::ofstream outfile(opts[2].c_str()); |
|
|
|
if (outfile.is_open() == false) |
|
PrintHelpAndExit(ErrorOpenOutputFailed); |
|
|
|
// Library name, cryptopp.dll |
|
std::string name = opts[2]; |
|
std::string::size_type pos = name.find_last_of("."); |
|
|
|
if (pos != std::string::npos) |
|
name.erase(pos); |
|
|
|
outfile << "LIBRARY " << name << std::endl; |
|
outfile << "DESCRIPTION \"" << LIBRARY_DESC << "\"" << std::endl; |
|
outfile << "EXPORTS" << std::endl; |
|
outfile << std::endl; |
|
|
|
outfile << "\t;; " << symbols.size() << " symbols" << std::endl; |
|
|
|
// Symbols from our object files |
|
SymbolMap::const_iterator it = symbols.begin(); |
|
for ( ; it != symbols.end(); ++it) |
|
outfile << "\t" << *it << std::endl; |
|
} |
|
catch (const std::exception& ex) |
|
{ |
|
std::cerr << "Unexpected exception:" << std::endl; |
|
std::cerr << ex.what() << std::endl; |
|
std::cerr << std::endl; |
|
|
|
PrintHelpAndExit(ErrorWriteException); |
|
} |
|
|
|
return 0; |
|
}
|
|
|