File: gccimpgen.cpp

package info (click to toggle)
mpich2 1.2.1.1-5
  • links: PTS, VCS
  • area: main
  • in suites: squeeze
  • size: 73,904 kB
  • ctags: 65,947
  • sloc: ansic: 343,583; makefile: 55,174; java: 34,959; sh: 27,558; perl: 17,355; cpp: 10,472; python: 9,649; f90: 5,753; fortran: 5,128; cs: 4,019; csh: 152; xml: 91; php: 8
file content (132 lines) | stat: -rw-r--r-- 4,934 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
/* -*- Mode: C++; c-basic-offset:4 ; -*- */
/*  
 *  (C) 2001 by Argonne National Laboratory.
 *      See COPYRIGHT in top-level directory.
 */

#include <windows.h>
#include <stdio.h>
#include <time.h>

/* This function returns a pointer to the section header containing the RVA. Return NULL on error */
template <typename NTHeaderType> static inline PIMAGE_SECTION_HEADER GetSecHeader(DWORD rva, NTHeaderType* pNTHeader)
{
    PIMAGE_SECTION_HEADER section;
    section = IMAGE_FIRST_SECTION(pNTHeader);
    for (int i=0; i < pNTHeader->FileHeader.NumberOfSections; i++, section++){
		DWORD size = section->Misc.VirtualSize;
        DWORD secRVA = section->VirtualAddress;
        if((secRVA <= rva)  && (rva < (secRVA+size))){
            return section;
        }
    }
    return NULL;
}

/* This function returns the real address from the RVA. Returns NULL on error */
template <typename NTHeaderType> static inline LPVOID GetRealAddrFromRVA(DWORD rva, NTHeaderType* pNTHeader, PBYTE imageBase )
{
	PIMAGE_SECTION_HEADER pSectionHdr = GetSecHeader(rva, pNTHeader);
	if (!pSectionHdr){
		return NULL;
    }
    /* Since we map the DLL manually we need to calculate mapShift to get the real addr */
	INT mapShift = (INT)(pSectionHdr->VirtualAddress - pSectionHdr->PointerToRawData);

	return (PVOID)(imageBase + rva - mapShift);
}

/* This function reads the exported symbols from a dll/exe and prints a DLL definition file, compatible with gcc,
   with those symbols.
    INPUT:
        pImageBase  : Pointer to the base of the dll image, offset = 0
        pNTHeader   : Pointer to the NT header (32-bit/64-bit) section of image.
*/
template <typename NTHeaderType> void PrintDefFileWithExpSymbols(PBYTE pImageBase, NTHeaderType *pNTHeader)
{
    /* Export Section RVA */
    DWORD expSecRVA = pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;

    /* From RVA get the real addrs for the various components of the exports section */
    PIMAGE_EXPORT_DIRECTORY pExportDir = (PIMAGE_EXPORT_DIRECTORY )GetRealAddrFromRVA(expSecRVA, pNTHeader, pImageBase);
    PDWORD pszFuncNames =	(PDWORD ) GetRealAddrFromRVA( pExportDir->AddressOfNames, pNTHeader, pImageBase );

    printf("EXPORTS\n");

    for (unsigned int i=0; i < pExportDir->NumberOfFunctions; i++){
        /* FIXME: Assumes that the current DLL does not have ordinal nums */
        if(i < pExportDir->NumberOfNames){
            /* Ordinal numbers start at 1 - not 0*/
            printf("\t%s @ %d ;\n", GetRealAddrFromRVA(pszFuncNames[i], pNTHeader, pImageBase), i+1);
        }
        else{
            break;
        }
    }
}

static void HelpUsage(char *exe_name)
{
    printf("Usage: %s <DLLNAME>\n", exe_name);
    printf("\t\t The tool reads the export section from <DLLNAME> and prints the definition file for gcc to stdout\n");
}

int main(int argc, char *argv[])
{
    HANDLE hFile, hFileMapping;
    LPVOID lpFileBase;
    PIMAGE_DOS_HEADER   pImgHeader;
    PIMAGE_NT_HEADERS   pImgNTHeader;
    PIMAGE_NT_HEADERS64 pImgNTHeader64;

    if((argc < 2) || (strcmp(argv[1], "/?") == 0) || (strcmp(argv[1], "--help") == 0)){
        HelpUsage(argv[0]);
        exit(1);
    }
    
    /* Open the DLL and map it to memory */
    hFile = CreateFile(argv[1], GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
    if(hFile == INVALID_HANDLE_VALUE){
        printf("Unable to open dll, %s\n", argv[1]);
        exit(-1);
    }
    
    hFileMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
    if(hFileMapping == 0){
        CloseHandle(hFile);
        printf("Cannot open file mapping for dll, %s\n", argv[1]);
        exit(-1);
    }

    lpFileBase = MapViewOfFile(hFileMapping, FILE_MAP_READ, 0, 0, 0);
    if(lpFileBase == 0){
        CloseHandle(hFileMapping);
        CloseHandle(hFile);
        printf("Cannot map view of dll, %s\n", argv[1]);
        exit(-1);
    }

    /* pImgHeader points to the MS-DOS HEADER section, offset=0, of dll */
    pImgHeader = (PIMAGE_DOS_HEADER )lpFileBase;
    
    /* pImgNTHeader points to the NT HEADER section of the dll, pImgHeader + <File address of new exe header> */
    pImgNTHeader = (PIMAGE_NT_HEADERS )((DWORD_PTR )pImgHeader + (DWORD_PTR )pImgHeader->e_lfanew);

    /* In the case of the 64-bit dlls, the Optional header section within NT header has 64-bit fields */
    pImgNTHeader64 = (PIMAGE_NT_HEADERS64) pImgNTHeader;

    /* The Magic number is always a WORD. This number is used to determine if the dll is 32-bit or 64-bit */
    if(pImgNTHeader->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC){
        /* 64-bit dll */
        PrintDefFileWithExpSymbols((PBYTE )pImgHeader, pImgNTHeader64);
    }
    else{
        /* 32-bit dll */
        PrintDefFileWithExpSymbols((PBYTE )pImgHeader, pImgNTHeader);
    }

    UnmapViewOfFile(lpFileBase);
    CloseHandle(hFileMapping);
    CloseHandle(hFile);
}