BinaryFileFactory.cpp

Go to the documentation of this file.
00001 /* File: BinaryFileFactory.cpp
00002  * Desc: This file contains the implementation of the factory function
00003  * BinaryFile::getInstanceFor(), and also BinaryFile::Load()
00004  * 
00005  * This function determines the type of a binary and loads the appropriate
00006  * loader class dynamically.
00007 */
00008 
00009 #ifndef _WIN32
00010 #include <dlfcn.h>
00011 #else
00012 #include <windows.h>            // include before types.h: name collision of NO_ADDRESS and WinSock.h
00013 #endif
00014 
00015 #include "BinaryFile.h"
00016 #include "ElfBinaryFile.h"
00017 #include "Win32BinaryFile.h"
00018 #include "PalmBinaryFile.h"
00019 #include "HpSomBinaryFile.h"
00020 #include "ExeBinaryFile.h"
00021 #include "config.h"             // For HOST_OSX_10_2 etc
00022 
00023 #include <iostream>
00024 
00025 BinaryFile *BinaryFileFactory::Load( const char *sName )
00026 {
00027     BinaryFile *pBF = getInstanceFor( sName );
00028     if( pBF == NULL ) {
00029         std::cerr << "unrecognised binary file format.\n";
00030         return NULL;
00031     }
00032     if( pBF->RealLoad( sName ) == 0 ) {
00033         fprintf( stderr, "Loading '%s' failed\n", sName );
00034         delete pBF;
00035         return NULL;
00036     }
00037 pBF->getTextLimits();
00038     return pBF;
00039 }
00040 
00041 #define TESTMAGIC2(buf,off,a,b)     (buf[off] == a && buf[off+1] == b)
00042 #define TESTMAGIC4(buf,off,a,b,c,d) (buf[off] == a && buf[off+1] == b && \
00043                                      buf[off+2] == c && buf[off+3] == d)
00044 
00045 // Declare a pointer to a constructor function; returns a BinaryFile*
00046 typedef BinaryFile* (*constructFcn)();
00047 
00048 BinaryFile* BinaryFileFactory::getInstanceFor( const char *sName ) {
00049     FILE *f;
00050     unsigned char buf[64];
00051     std::string libName;
00052     BinaryFile *res = NULL;
00053 
00054     f = fopen (sName, "rb");
00055     if( f == NULL ) {
00056         fprintf(stderr, "Unable to open binary file: %s\n", sName );
00057         return NULL;
00058     }
00059     fread (buf, sizeof(buf), 1, f);
00060     if( TESTMAGIC4(buf,0, '\177','E','L','F') ) {
00061         /* ELF Binary */
00062         libName = "ElfBinaryFile";
00063     } else if( TESTMAGIC2( buf,0, 'M','Z' ) ) { /* DOS-based file */
00064         int peoff = LMMH(buf[0x3C]);
00065         if( peoff != 0 && fseek(f, peoff, SEEK_SET) != -1 ) {
00066             fread( buf, 4, 1, f );
00067             if( TESTMAGIC4( buf,0, 'P','E',0,0 ) ) {
00068                 /* Win32 Binary */
00069                 libName = "Win32BinaryFile";
00070             } else if( TESTMAGIC2( buf,0, 'N','E' ) ) {
00071                 /* Win16 / Old OS/2 Binary */
00072             } else if( TESTMAGIC2( buf,0, 'L','E' ) ) {
00073                 /* Win32 VxD (Linear Executable) or DOS4GW app */
00074                 libName = "DOS4GWBinaryFile";
00075             } else if( TESTMAGIC2( buf,0, 'L','X' ) ) {
00076                 /* New OS/2 Binary */
00077             }
00078         }
00079         /* Assume MS-DOS Real-mode binary. */
00080         if( libName.size() == 0 )
00081             libName = "ExeBinaryFile";
00082     } else if( TESTMAGIC4( buf,0x3C, 'a','p','p','l' ) ||
00083                TESTMAGIC4( buf,0x3C, 'p','a','n','l' ) ) {
00084         /* PRC Palm-pilot binary */
00085         libName = "PalmBinaryFile";
00086     } else if( buf[0] == 0xfe && buf[1] == 0xed && buf[2] == 0xfa && buf[3] == 0xce ) {
00087         /* Mach-O Mac OS-X binary */
00088         libName = "MachOBinaryFile";
00089 #ifdef __CYGWIN__
00090         fprintf(stderr, "Sorry, Cygwin-hosted Boomerang cannot compile the MachOBinaryFile module at present"
00091             "\n");
00092         fclose(f);
00093         return NULL;
00094 #endif
00095     } else if( buf[0] == 0x02 && buf[2] == 0x01 &&
00096                (buf[1] == 0x10 || buf[1] == 0x0B) &&
00097                (buf[3] == 0x07 || buf[3] == 0x08 || buf[4] == 0x0B) ) {
00098         /* HP Som binary (last as it's not really particularly good magic) */
00099         libName = "HpSomBinaryFile";
00100     } else {
00101         fprintf( stderr, "Unrecognised binary file\n" );
00102         fclose(f);
00103         return NULL;
00104     }
00105     
00106 // Load the specific loader library
00107 #ifndef _WIN32      // Cygwin, Unix/Linux
00108     libName = std::string("lib/lib") + libName;
00109 #ifdef  __CYGWIN__
00110     libName += ".dll";      // Cygwin wants .dll, but is otherwise like Unix
00111 #else
00112 #if HOST_OSX
00113     libName += ".dylib";
00114 #else
00115     libName += ".so";
00116 #endif
00117 #endif
00118     dlHandle = dlopen(libName.c_str(), RTLD_LAZY);
00119     if (dlHandle == NULL) {
00120         fprintf( stderr, "Could not open dynamic loader library %s\n", libName.c_str());
00121         fprintf( stderr, "%s\n", dlerror());
00122         fclose(f);
00123         return NULL;
00124     }
00125     // Use the handle to find the "construct" function
00126 #if 0   // HOST_OSX_10_2    // Not sure when the underscore is really needed
00127 #define UNDERSCORE "_"      // Only OSX 10.2 seems to need this underscore
00128 #else
00129 #define UNDERSCORE
00130 #endif
00131     constructFcn pFcn = (constructFcn) dlsym(dlHandle, UNDERSCORE "construct");
00132 #else                       // Else MSVC, MinGW
00133     libName += ".dll";      // Example: ElfBinaryFile.dll (same dir as boomerang.exe)
00134 #ifdef __MINGW32__
00135     libName = "lib/lib" + libName;
00136 #endif
00137     hModule = LoadLibraryA(libName.c_str());
00138     if(hModule == NULL) {
00139         int err = GetLastError();
00140         fprintf( stderr, "Could not open dynamic loader library %s (error #%d)\n", libName.c_str(), err);
00141         fclose(f);
00142         return NULL;
00143     }
00144     // Use the handle to find the "construct" function
00145     constructFcn pFcn = (constructFcn) GetProcAddress((HINSTANCE)hModule, "construct");
00146 #endif
00147 
00148     if (pFcn == NULL) {
00149         fprintf( stderr, "Loader library %s does not have a construct function\n", libName.c_str());
00150 #ifndef _WIN32
00151         fprintf( stderr, "dlerror returns %s\n", dlerror());
00152 #endif
00153         fclose(f);
00154         return NULL;
00155     }
00156     // Call the construct function
00157     res = (*pFcn)();
00158     fclose(f);
00159     return res;
00160 }
00161 
00162 void BinaryFileFactory::UnLoad() {
00163 #ifdef _WIN32
00164     FreeLibrary((HINSTANCE)hModule);
00165 #else
00166     dlclose(dlHandle);                  // Especially important for Mac OS X
00167 #endif
00168 }

Generated on Tue Sep 19 21:18:14 2006 for Boomerang by  doxygen 1.4.6