Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. /* -------------------------------------------------------------- */
  2. /*
  3.  * tiny_impdef creates an export definition file (.def) from a dll
  4.  * on MS-Windows. Usage: tiny_impdef library.dll [-o outputfile]"
  5.  *
  6.  *  Copyright (c) 2005,2007 grischka
  7.  *
  8.  * This program is free software; you can redistribute it and/or modify
  9.  * it under the terms of the GNU General Public License as published by
  10.  * the Free Software Foundation; either version 2 of the License, or
  11.  * (at your option) any later version.
  12.  *
  13.  * This program is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16.  * GNU General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU General Public License
  19.  * along with this program; if not, write to the Free Software
  20.  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  */
  22.  
  23. #ifndef TINY_IMPDEF_GET_EXPORT_NAMES_ONLY
  24.  
  25. #define WIN32_LEAN_AND_MEAN
  26. #include <windows.h>
  27. #include <stdio.h>
  28. #include <io.h>
  29. #include <malloc.h>
  30.  
  31. char *get_export_names(int fd);
  32. #define tcc_free free
  33. #define tcc_realloc realloc
  34.  
  35. /* extract the basename of a file */
  36. static char *file_basename(const char *name)
  37. {
  38.     const char *p = strchr(name, 0);
  39.     while (p > name
  40.         && p[-1] != '/'
  41.         && p[-1] != '\\'
  42.         )
  43.         --p;
  44.     return (char*)p;
  45. }
  46.  
  47. int main(int argc, char **argv)
  48. {
  49.     int ret, v, i;
  50.     char infile[MAX_PATH];
  51.     char outfile[MAX_PATH];
  52.  
  53.     static const char *ext[] = { ".dll", ".exe", NULL };
  54.     const char *file, **pp;
  55.     char path[MAX_PATH], *p, *q;
  56.     FILE *fp, *op;
  57.  
  58.     infile[0] = 0;
  59.     outfile[0] = 0;
  60.     fp = op = NULL;
  61.     v = 0;
  62.     ret = 1;
  63.     p = NULL;
  64.  
  65.     for (i = 1; i < argc; ++i) {
  66.         const char *a = argv[i];
  67.         if ('-' == a[0]) {
  68.             if (0 == strcmp(a, "-v")) {
  69.                 v = 1;
  70.             } else if (0 == strcmp(a, "-o")) {
  71.                 if (++i == argc)
  72.                     goto usage;
  73.                 strcpy(outfile, argv[i]);
  74.             } else
  75.                 goto usage;
  76.         } else if (0 == infile[0])
  77.             strcpy(infile, a);
  78.         else
  79.             goto usage;
  80.     }
  81.  
  82.     if (0 == infile[0]) {
  83. usage:
  84.         fprintf(stderr,
  85.             "tiny_impdef: create export definition file (.def) from a dll\n"
  86.             "Usage: tiny_impdef library.dll [-o outputfile]\n"
  87.             );
  88.         goto the_end;
  89.     }
  90.  
  91.     if (0 == outfile[0])
  92.     {
  93.         strcpy(outfile, file_basename(infile));
  94.         q = strrchr(outfile, '.');
  95.         if (NULL == q)
  96.             q = strchr(outfile, 0);
  97.         strcpy(q, ".def");
  98.     }
  99.  
  100.     file = infile;
  101.  
  102. #ifdef _WIN32
  103.     pp = ext;
  104.     do if (SearchPath(NULL, file, *pp, sizeof path, path, NULL)) {
  105.        file = path;
  106.        break;
  107.     } while (*pp++);
  108. #endif
  109.  
  110.     fp = fopen(file, "rb");
  111.     if (NULL == fp) {
  112.         fprintf(stderr, "tiny_impdef: no such file: %s\n", infile);
  113.         goto the_end;
  114.     }
  115.     if (v)
  116.         printf("--> %s\n", file);
  117.  
  118.     p = get_export_names(fileno(fp));
  119.     if (NULL == p) {
  120.         fprintf(stderr, "tiny_impdef: could not get exported function names.\n");
  121.         goto the_end;
  122.     }
  123.  
  124.     op = fopen(outfile, "w");
  125.     if (NULL == op) {
  126.         fprintf(stderr, "tiny_impdef: could not create output file: %s\n", outfile);
  127.         goto the_end;
  128.     }
  129.  
  130.     fprintf(op, "LIBRARY %s\n\nEXPORTS\n", file_basename(file));
  131.     for (q = p, i = 0; *q; ++i) {
  132.         fprintf(op, "%s\n", q);
  133.         q += strlen(q) + 1;
  134.     }
  135.  
  136.     if (v) {
  137.         printf("<-- %s\n", outfile);
  138.         printf("%d symbol(s) found\n", i);
  139.     }
  140.  
  141.     ret = 0;
  142.  
  143. the_end:
  144.     if (p)
  145.         free(p);
  146.     if (fp)
  147.         fclose(fp);
  148.     if (op)
  149.         fclose(op);
  150.     return ret;
  151. }
  152.  
  153. int read_mem(int fd, unsigned offset, void *buffer, unsigned len)
  154. {
  155.     lseek(fd, offset, SEEK_SET);
  156.     return len == read(fd, buffer, len);
  157. }
  158.  
  159. /* -------------------------------------------------------------- */
  160.  
  161. #if defined TCC_TARGET_X86_64
  162. # define IMAGE_FILE_MACHINE 0x8664
  163. #elif defined TCC_TARGET_ARM
  164. # define IMAGE_FILE_MACHINE 0x01C0
  165. #elif 1 /* defined TCC_TARGET_I386 */
  166. # define IMAGE_FILE_MACHINE 0x014C
  167. #endif
  168.  
  169. /* -------------------------------------------------------------- */
  170. #endif
  171.  
  172. char *get_export_names(int fd)
  173. {
  174.     int l, i, n, n0;
  175.     char *p;
  176.  
  177.     IMAGE_SECTION_HEADER ish;
  178.     IMAGE_EXPORT_DIRECTORY ied;
  179.     IMAGE_DOS_HEADER dh;
  180.     IMAGE_FILE_HEADER ih;
  181.     DWORD sig, ref, addr, ptr, namep;
  182. #ifdef TCC_TARGET_X86_64
  183.     IMAGE_OPTIONAL_HEADER64 oh;
  184. #else
  185.     IMAGE_OPTIONAL_HEADER32 oh;
  186. #endif
  187.     int pef_hdroffset, opt_hdroffset, sec_hdroffset;
  188.  
  189.     n = n0 = 0;
  190.     p = NULL;
  191.  
  192.     if (!read_mem(fd, 0, &dh, sizeof dh))
  193.         goto the_end;
  194.     if (!read_mem(fd, dh.e_lfanew, &sig, sizeof sig))
  195.         goto the_end;
  196.     if (sig != 0x00004550)
  197.         goto the_end;
  198.     pef_hdroffset = dh.e_lfanew + sizeof sig;
  199.     if (!read_mem(fd, pef_hdroffset, &ih, sizeof ih))
  200.         goto the_end;
  201.     if (IMAGE_FILE_MACHINE != ih.Machine)
  202.         goto the_end;
  203.     opt_hdroffset = pef_hdroffset + sizeof ih;
  204.     sec_hdroffset = opt_hdroffset + sizeof oh;
  205.     if (!read_mem(fd, opt_hdroffset, &oh, sizeof oh))
  206.         goto the_end;
  207.  
  208.     if (IMAGE_DIRECTORY_ENTRY_EXPORT >= oh.NumberOfRvaAndSizes)
  209.         goto the_end;
  210.  
  211.     addr = oh.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
  212.     //printf("addr: %08x\n", addr);
  213.     for (i = 0; i < ih.NumberOfSections; ++i) {
  214.         if (!read_mem(fd, sec_hdroffset + i * sizeof ish, &ish, sizeof ish))
  215.             goto the_end;
  216.         //printf("vaddr: %08x\n", ish.VirtualAddress);
  217.         if (addr >= ish.VirtualAddress && addr < ish.VirtualAddress + ish.SizeOfRawData)
  218.             goto found;
  219.     }
  220.     goto the_end;
  221.  
  222. found:
  223.     ref = ish.VirtualAddress - ish.PointerToRawData;
  224.     if (!read_mem(fd, addr - ref, &ied, sizeof ied))
  225.         goto the_end;
  226.  
  227.     namep = ied.AddressOfNames - ref;
  228.     for (i = 0; i < ied.NumberOfNames; ++i) {
  229.         if (!read_mem(fd, namep, &ptr, sizeof ptr))
  230.             goto the_end;
  231.         namep += sizeof ptr;
  232.         for (l = 0;;) {
  233.             if (n+1 >= n0)
  234.                 p = tcc_realloc(p, n0 = n0 ? n0 * 2 : 256);
  235.             if (!read_mem(fd, ptr - ref + l++, p + n, 1)) {
  236.                 tcc_free(p), p = NULL;
  237.                 goto the_end;
  238.             }
  239.             if (p[n++] == 0)
  240.                 break;
  241.         }
  242.     }
  243.     if (p)
  244.         p[n] = 0;
  245. the_end:
  246.     return p;
  247. }
  248.  
  249. /* -------------------------------------------------------------- */
  250.