From: Bill Moyer Date: Tue, 28 Apr 1998 17:36:17 +0000 (+0000) Subject: dlltool.c: Added support for IMPORTS. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=a4e5fd18f93ddbd61b254aaab3407a449a82fc1e;p=binutils-gdb.git dlltool.c: Added support for IMPORTS. dlltool.h: Redefined declaration of def_import(). defparse.y: Redefined IMPORT rule. --- diff --git a/binutils/defparse.y b/binutils/defparse.y index 21b68765598..44b7a2aba06 100644 --- a/binutils/defparse.y +++ b/binutils/defparse.y @@ -29,7 +29,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ }; %token NAME, LIBRARY, DESCRIPTION, STACKSIZE, HEAPSIZE, CODE, DATA -%token SECTIONS, EXPORTS, IMPORTS, VERSION, BASE, CONSTANT +%token SECTIONS, EXPORTS, IMPORTS, VERSIONK, BASE, CONSTANT %token READ WRITE EXECUTE SHARED NONAME %token ID %token NUMBER @@ -54,14 +54,15 @@ command: | DATA attr_list { def_data ($2);} | SECTIONS seclist | IMPORTS implist - | VERSION NUMBER { def_version ($2,0);} - | VERSION NUMBER '.' NUMBER { def_version ($2,$4);} + | VERSIONK NUMBER { def_version ($2,0);} + | VERSIONK NUMBER '.' NUMBER { def_version ($2,$4);} ; explist: - explist expline + /* EMPTY */ | expline + | explist expline ; expline: @@ -74,9 +75,16 @@ implist: ; impline: - ID '=' ID '.' ID { def_import ($1,$3,$5);} - | ID '.' ID { def_import (0, $1,$3);} - ; + ID '=' ID '.' ID '.' ID { def_import ($1,$3,$5,$7, 0); } + | ID '=' ID '.' ID '.' NUMBER { def_import ($1,$3,$5, 0,$7); } + | ID '=' ID '.' ID { def_import ($1,$3, 0,$5, 0); } + | ID '=' ID '.' NUMBER { def_import ($1,$3, 0, 0,$5); } + | ID '.' ID '.' ID { def_import ( 0,$1,$3,$5, 0); } + | ID '.' ID '.' NUMBER { def_import ( 0,$1,$3, 0,$5); } + | ID '.' ID { def_import ( 0,$1, 0,$3, 0); } + | ID '.' NUMBER { def_import ( 0,$1, 0, 0,$3); } +; + seclist: seclist secline | secline diff --git a/binutils/dlltool.c b/binutils/dlltool.c index 07d5ec68e8e..3eb268db286 100644 --- a/binutils/dlltool.c +++ b/binutils/dlltool.c @@ -254,6 +254,50 @@ #endif /* defined (_WIN32) && ! defined (__CYGWIN32__) */ #endif /* ! HAVE_SYS_WAIT_H */ +/* ifunc and ihead data structures: ttk@cygnus.com 1997 + When IMPORT declarations are encountered in a .def file the + function import information is stored in a structure referenced + by the global variable "(iheadtype*) import_list". The struc- + ture is a linked list containing the names of the dll files + each function is imported from and a linked list of functions + being imported from that dll file. This roughly parallels the + structure of the .idata section in the PE object file. + The contents of .def file are interpreted from within the + process__def_file() function. Every time an IMPORT declaration + is encountered, it is broken up into its component parts and + passed to def_import(). import_list is initialized to NULL in + function main(). + */ + +typedef struct ifunct + { + char *name; /* name of function being imported */ + int ord; /* two-byte ordinal value associated with function */ + struct ifunct *next; + } +ifunctype; + +typedef struct iheadt + { + char *dllname; /* name of dll file imported from */ + long nfuncs; /* number of functions in list */ + struct ifunct *funchead; /* first function in list */ + struct ifunct *functail; /* last function in list */ + struct iheadt *next; /* next dll file in list */ + } +iheadtype; + +/* ignore_imports: if true, IMPORT declarations are ignored + and no .import section will be created. + import_list: structure containing all import information as + defined in .def file (qv "ihead structure"). + nheads: count of number of dll files recorded in import_list. + */ + +static boolean ignore_imports = false; +static iheadtype *import_list = NULL; +static long nheads; + static char *as_name = "as"; static int no_idata4; @@ -492,6 +536,9 @@ asm_prefix (machine) #define HOW_JTAB_ROFF mtable[machine].how_jtab_roff static char **oav; +FILE *yyin; /* communications with flex */ +extern int linenumber; + void process_def_file (name) const char *name; @@ -607,40 +654,151 @@ new_directive (dir) } void -def_stacksize (reserve, commit) +def_heapsize (reserve, commit) int reserve; int commit; { char b[200]; if (commit > 0) - sprintf (b, "-stack 0x%x,0x%x ", reserve, commit); + sprintf (b, "-heap 0x%x,0x%x ", reserve, commit); else - sprintf (b, "-stack 0x%x ", reserve); + sprintf (b, "-heap 0x%x ", reserve); new_directive (xstrdup (b)); } void -def_heapsize (reserve, commit) +def_stacksize (reserve, commit) int reserve; int commit; { char b[200]; if (commit > 0) - sprintf (b, "-heap 0x%x,0x%x ", reserve, commit); + sprintf (b, "-stack 0x%x,0x%x ", reserve, commit); else - sprintf (b, "-heap 0x%x ", reserve); + sprintf (b, "-stack 0x%x ", reserve); new_directive (xstrdup (b)); } -void -def_import (internal, module, entry) - const char *internal; - const char *module; - const char *entry; -{ - if (verbose) - fprintf (stderr, _("%s: IMPORTS are ignored"), program_name); -} +/* append_import() simply adds the given import definition + to the global import_list. It is used by def_import(). + */ +void +append_import (symbol_name, dll_name, func_ordinal) + char *symbol_name; + char *dll_name; + char *func_ordinal; + { + iheadtype *headptr; + + if (import_list == NULL) + { + import_list = xmalloc (sizeof (iheadtype)); + import_list->dllname = xstrdup (dll_name); + import_list->nfuncs = 1; + import_list->funchead = xmalloc (sizeof (ifunctype)); + import_list->functail = import_list->funchead; + import_list->next = NULL; + import_list->functail->name = xstrdup (symbol_name); + import_list->functail->ord = atoi (func_ordinal); + import_list->functail->next = NULL; + return; + } /* END of case import_list == NULL */ + headptr = import_list; + while ((strcmp (headptr->dllname,dll_name)) + && (headptr->next != NULL)) + headptr = headptr->next; + if (!strcmp (headptr->dllname, dll_name)) + { + headptr->functail->next = xmalloc (sizeof (ifunctype)); + headptr->functail = headptr->functail->next; + headptr->functail->ord = atoi (func_ordinal); + headptr->functail->name = xstrdup (symbol_name); + headptr->functail->next = NULL; + headptr->nfuncs++; + } + else + { /* this dll doesn't already have entry */ + headptr->next = xmalloc (sizeof (iheadtype)); + headptr = headptr->next; + headptr->dllname = xstrdup (dll_name); + headptr->nfuncs = 1; + headptr->funchead = xmalloc (sizeof (ifunctype)); + headptr->functail = headptr->funchead; + headptr->next = NULL; + headptr->functail->name = xstrdup (symbol_name); + headptr->functail->ord = atoi (func_ordinal); + headptr->functail->next = NULL; + } /* END of if..else clause */ + } /* END of function append_import */ + +/* def_import() is called from within defparse.y when an + IMPORT declaration is encountered. Depending on the + form of the declaration, the module name may or may not + need ".dll" to be appended to it, the name of the func- + tion may be stored in internal or entry, and there may + or may not be an ordinal value associated with it. + The interface between def_import() and append_import() + is a bit convoluted because append_import() was written + to handle a simpler case of IMPORT declaration and I + didn't have the time to rewrite it. + */ + +/* A note regarding the parse modes: + In yyparse.y we have to accept import declarations which + follow any one of the following forms: + = . + = . + . + . + Furthermore, the dll's name may or may not end with ".dll", + which complicates the parsing a little. Normally the dll's + name is passed to def_import() in the "module" parameter, + but when it ends with ".dll" it gets passed in "module" sans + ".dll" and that needs to be reappended. + + def_import() gets five parameters: + app_name - the name of the function in the application, if + present, or NULL if not present. + module - the name of the dll, possibly sans extension (ie, '.dll'). + dllext - the extension of the dll, if present, NULL if not present. + entry - the name of the function in the dll, if present, or NULL. + ord_val - the numerical tag of the function in the dll, if present, + or NULL. Exactly one of or must be + present (ie, not NULL). + */ + +void +def_import (app_name, module, dllext, entry, ord_val) + char *app_name; + char *module; + char *dllext; + char *entry; + int ord_val; /* two-byte value */ + { + char *application_name; + char *module_name; + char *entry_name; + char ord_string[7]; + char zero_str[1] = { 0 }; + + sprintf (ord_string, "%d", ord_val); + if (entry) + application_name = entry; + else + if (app_name) + application_name = app_name; + else + application_name = zero_str; + if (dllext) + { + module_name = (char*) alloca (strlen (module) + strlen(dllext) + 2); + sprintf (module_name, "%s.%s", module, dllext); + } + else + module_name = module; + entry_name = ord_string; + append_import (application_name, module_name, entry_name); + } /* END of function def_import */ void def_version (major, minor) @@ -941,11 +1099,141 @@ gen_def_file () } } +/* generate_idata_ofile() generates the portable assembly source code + for the idata sections. It may be passed an open FILE* or a NULL. + In the former case it appends the source code to the end of the + file and returns NULL. In the latter case it creates a file named + doi.s, assembles it to doi.o, opens doi.o as a bfd, and returns the + bfd*. generate_idata_ofile() is currently used in the former manner + in gen_exp_file(). + */ + +bfd * +generate_idata_ofile ( fd ) + FILE *fd; + { + FILE *filvar; + int result; + iheadtype *headptr; + ifunctype *funcptr; + int headindex; + int funcindex; + char as_args[16]; + + if (fd != NULL) + filvar = fd; + else + filvar = fopen ("doi.s", "w"); + if (!filvar) + { + fprintf (stderr, "%s: Can't open doi.s\n", program_name); + return ((bfd*)-1); + } + fprintf (filvar, "%s Import data sections\n", ASM_C); + fprintf (filvar, "\n\t.section\t.idata$2\n"); + fprintf (filvar, "\t%s\tdoi_idata\n", ASM_GLOBAL); + fprintf (filvar, "doi_idata:\n"); + + nheads = 0; + for (headptr = import_list; headptr != NULL; headptr = headptr->next) + { + fprintf (filvar, "\t%slistone%d%s\t%s %s\n", + ASM_RVA_BEFORE, (int)nheads, ASM_RVA_AFTER, + ASM_C, headptr->dllname); + fprintf (filvar, "\t%s\t0\n", ASM_LONG); + fprintf (filvar, "\t%s\t0\n", ASM_LONG); + fprintf (filvar, "\t%sdllname%d%s\n", + ASM_RVA_BEFORE, (int)nheads, ASM_RVA_AFTER); + fprintf (filvar, "\t%slisttwo%d%s\n\n", + ASM_RVA_BEFORE, (int)nheads, ASM_RVA_AFTER); + nheads++; + } /* END of headptr for-loop */ + + fprintf (filvar, "\t%s\t0\n", ASM_LONG); /* NULL record at */ + fprintf (filvar, "\t%s\t0\n", ASM_LONG); /* end of idata$2 */ + fprintf (filvar, "\t%s\t0\n", ASM_LONG); /* section */ + fprintf (filvar, "\t%s\t0\n", ASM_LONG); + fprintf (filvar, "\t%s\t0\n", ASM_LONG); + + fprintf (filvar, "\n\t.section\t.idata$4\n"); + headindex = 0; + for (headptr = import_list; headptr != NULL; headptr = headptr->next) + { + fprintf (filvar, "listone%d:\n", headindex); + for ( funcindex = 0; funcindex < headptr->nfuncs; funcindex++ ) + fprintf (filvar, "\t%sfuncptr%d_%d%s\n", + ASM_RVA_BEFORE, headindex, funcindex, ASM_RVA_AFTER); + fprintf (filvar,"\t%s\t0\n", ASM_LONG); /* NULL terminating list */ + headindex++; + } /* END of headptr for loop */ + + fprintf (filvar, "\n\t.section\t.idata$5\n"); + headindex = 0; + for (headptr = import_list; headptr != NULL; headptr = headptr->next) + { + fprintf (filvar, "listtwo%d:\n", headindex); + for ( funcindex = 0; funcindex < headptr->nfuncs; funcindex++ ) + fprintf (filvar, "\t%sfuncptr%d_%d%s\n", + ASM_RVA_BEFORE, headindex, funcindex, ASM_RVA_AFTER); + fprintf (filvar,"\t%s\t0\n", ASM_LONG); /* NULL terminating list */ + headindex++; + } /* END of headptr for-loop */ + + fprintf (filvar, "\n\t.section\t.idata$6\n"); + headindex = 0; + for (headptr = import_list; headptr != NULL; headptr = headptr->next) + { + funcindex = 0; + for (funcptr = headptr->funchead; funcptr != NULL; + funcptr = funcptr->next) + { + fprintf (filvar,"funcptr%d_%d:\n",headindex,funcindex); + fprintf (filvar,"\t%s\t%d\n",ASM_SHORT,((funcptr->ord) & 0xFFFF)); + fprintf (filvar,"\t%s\t%c%s%c\n",ASM_TEXT,'"',funcptr->name,'"'); + fprintf (filvar,"\t%s\t0\n",ASM_BYTE); + funcindex++; + } /* END of funcptr for loop */ + headindex++; + } /* END of headptr for loop */ + + fprintf (filvar, "\n\t.section\t.idata$7\n"); + headindex = 0; + for (headptr = import_list; headptr != NULL; headptr = headptr->next) + { + fprintf (filvar,"dllname%d:\n",headindex); + fprintf (filvar,"\t%s\t%c%s%c\n",ASM_TEXT,'"',headptr->dllname,'"'); + fprintf (filvar,"\t%s\t0\n",ASM_BYTE); + headindex++; + } /* END of headptr for loop */ + + if (fd == NULL) + { + result = fclose (filvar); + if ( result ) + { + fprintf (stderr, "%s: Can't close doi.s\n", program_name); + return ((bfd*) -1); + } /* END of if clause */ + sprintf (as_args, "-o doi.o doi.s"); + run (as_name, as_args); + + if (dontdeltemps == 0) + { + sprintf (outfile, "doi.s"); + unlink (outfile); + } + return (bfd_openr ("doi.o", HOW_BFD_TARGET)); + } /* END of if clause */ + else + return NULL; + } /* END of function generate_idata_ofile() */ + static void gen_exp_file () { FILE *f; int i; + bfd *result; export_type *exp; dlist_type *dl; @@ -1164,6 +1452,14 @@ gen_exp_file () } } + result = generate_idata_ofile (f); + if ( result != NULL ) + { + fprintf (stderr, "%s: error writing idata section\n", + program_name); + exit (1); + } + fclose (f); /* assemble the file */ @@ -2402,7 +2698,7 @@ main (ac, av) if (!dll_name && exp_name) { - char len = strlen (exp_name) + 5; + int len = strlen (exp_name) + 5; dll_name = xmalloc (len); strcpy (dll_name, exp_name); strcat (dll_name, ".dll"); diff --git a/binutils/dlltool.h b/binutils/dlltool.h index 48e880b7ca2..106645ac078 100644 --- a/binutils/dlltool.h +++ b/binutils/dlltool.h @@ -24,9 +24,10 @@ extern void def_code PARAMS ((int)); extern void def_data PARAMS ((int)); extern void def_description PARAMS ((const char *)); -extern void def_exports PARAMS ((const char *, const char *, int, int, int)); +extern void def_exports + PARAMS ((const char *, const char *, int, int, int, int)); extern void def_heapsize PARAMS ((int, int)); -extern void def_import PARAMS ((const char *, const char *, const char *)); +extern void def_import PARAMS ((char *, char *, char *, char *, int)); extern void def_library PARAMS ((const char *, int)); extern void def_name PARAMS ((const char *, int)); extern void def_section PARAMS ((const char *, int));