| 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 */ |
|---|
| 12 | template <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 */ |
|---|
| 27 | template <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 | */ |
|---|
| 45 | template <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 | |
|---|
| 68 | static 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 | |
|---|
| 74 | int 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 | } |
|---|