root/mpich2/trunk/maint/gccimpgen.cpp @ 4862

Revision 4862, 4.8 KB (checked in by jayesh, 5 months ago)

Get rid of the *hackish* version of import file generator for windows dlls and replace it with an improved - recognizes 64-bit dlls too - version

Line 
1/* -*- Mode: C++; c-basic-offset:4 ; -*- */
2/* 
3 *  (C) 2001 by Argonne National Laboratory.
4 *      See COPYRIGHT in top-level directory.
5 */
6
7#include <windows.h>
8#include <stdio.h>
9#include <time.h>
10
11/* This function returns a pointer to the section header containing the RVA. Return NULL on error */
12template <typename NTHeaderType> static inline PIMAGE_SECTION_HEADER GetSecHeader(DWORD rva, NTHeaderType* pNTHeader)
13{
14    PIMAGE_SECTION_HEADER section;
15    section = IMAGE_FIRST_SECTION(pNTHeader);
16    for (int i=0; i < pNTHeader->FileHeader.NumberOfSections; i++, section++){
17                DWORD size = section->Misc.VirtualSize;
18        DWORD secRVA = section->VirtualAddress;
19        if((secRVA <= rva)  && (rva < (secRVA+size))){
20            return section;
21        }
22    }
23    return NULL;
24}
25
26/* This function returns the real address from the RVA. Returns NULL on error */
27template <typename NTHeaderType> static inline LPVOID GetRealAddrFromRVA(DWORD rva, NTHeaderType* pNTHeader, PBYTE imageBase )
28{
29        PIMAGE_SECTION_HEADER pSectionHdr = GetSecHeader(rva, pNTHeader);
30        if (!pSectionHdr){
31                return NULL;
32    }
33    /* Since we map the DLL manually we need to calculate mapShift to get the real addr */
34        INT mapShift = (INT)(pSectionHdr->VirtualAddress - pSectionHdr->PointerToRawData);
35
36        return (PVOID)(imageBase + rva - mapShift);
37}
38
39/* This function reads the exported symbols from a dll/exe and prints a DLL definition file, compatible with gcc,
40   with those symbols.
41    INPUT:
42        pImageBase  : Pointer to the base of the dll image, offset = 0
43        pNTHeader   : Pointer to the NT header (32-bit/64-bit) section of image.
44*/
45template <typename NTHeaderType> void PrintDefFileWithExpSymbols(PBYTE pImageBase, NTHeaderType *pNTHeader)
46{
47    /* Export Section RVA */
48    DWORD expSecRVA = pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
49
50    /* From RVA get the real addrs for the various components of the exports section */
51    PIMAGE_EXPORT_DIRECTORY pExportDir = (PIMAGE_EXPORT_DIRECTORY )GetRealAddrFromRVA(expSecRVA, pNTHeader, pImageBase);
52    PDWORD pszFuncNames =       (PDWORD ) GetRealAddrFromRVA( pExportDir->AddressOfNames, pNTHeader, pImageBase );
53
54    printf("EXPORTS\n");
55
56    for (unsigned int i=0; i < pExportDir->NumberOfFunctions; i++){
57        /* FIXME: Assumes that the current DLL does not have ordinal nums */
58        if(i < pExportDir->NumberOfNames){
59            /* Ordinal numbers start at 1 - not 0*/
60            printf("\t%s @ %d ;\n", GetRealAddrFromRVA(pszFuncNames[i], pNTHeader, pImageBase), i+1);
61        }
62        else{
63            break;
64        }
65    }
66}
67
68static void HelpUsage(char *exe_name)
69{
70    printf("Usage: %s <DLLNAME>\n", exe_name);
71    printf("\t\t The tool reads the export section from <DLLNAME> and prints the definition file for gcc to stdout\n");
72}
73
74int main(int argc, char *argv[])
75{
76    HANDLE hFile, hFileMapping;
77    LPVOID lpFileBase;
78    PIMAGE_DOS_HEADER   pImgHeader;
79    PIMAGE_NT_HEADERS   pImgNTHeader;
80    PIMAGE_NT_HEADERS64 pImgNTHeader64;
81
82    if((argc < 2) || (strcmp(argv[1], "/?") == 0) || (strcmp(argv[1], "--help") == 0)){
83        HelpUsage(argv[0]);
84        exit(1);
85    }
86   
87    /* Open the DLL and map it to memory */
88    hFile = CreateFile(argv[1], GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
89    if(hFile == INVALID_HANDLE_VALUE){
90        printf("Unable to open dll, %s\n", argv[1]);
91        exit(-1);
92    }
93   
94    hFileMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
95    if(hFileMapping == 0){
96        CloseHandle(hFile);
97        printf("Cannot open file mapping for dll, %s\n", argv[1]);
98        exit(-1);
99    }
100
101    lpFileBase = MapViewOfFile(hFileMapping, FILE_MAP_READ, 0, 0, 0);
102    if(lpFileBase == 0){
103        CloseHandle(hFileMapping);
104        CloseHandle(hFile);
105        printf("Cannot map view of dll, %s\n", argv[1]);
106        exit(-1);
107    }
108
109    /* pImgHeader points to the MS-DOS HEADER section, offset=0, of dll */
110    pImgHeader = (PIMAGE_DOS_HEADER )lpFileBase;
111   
112    /* pImgNTHeader points to the NT HEADER section of the dll, pImgHeader + <File address of new exe header> */
113    pImgNTHeader = (PIMAGE_NT_HEADERS )((DWORD_PTR )pImgHeader + (DWORD_PTR )pImgHeader->e_lfanew);
114
115    /* In the case of the 64-bit dlls, the Optional header section within NT header has 64-bit fields */
116    pImgNTHeader64 = (PIMAGE_NT_HEADERS64) pImgNTHeader;
117
118    /* The Magic number is always a WORD. This number is used to determine if the dll is 32-bit or 64-bit */
119    if(pImgNTHeader->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC){
120        /* 64-bit dll */
121        PrintDefFileWithExpSymbols((PBYTE )pImgHeader, pImgNTHeader64);
122    }
123    else{
124        /* 32-bit dll */
125        PrintDefFileWithExpSymbols((PBYTE )pImgHeader, pImgNTHeader);
126    }
127
128    UnmapViewOfFile(lpFileBase);
129    CloseHandle(hFileMapping);
130    CloseHandle(hFile);
131}
Note: See TracBrowser for help on using the browser.