From 765e60a947ca5f615e6c1e7307e7cce2b8d0d695 Mon Sep 17 00:00:00 2001 From: Steve Chamberlain Date: Wed, 14 Jun 1995 20:28:36 +0000 Subject: [PATCH] Wed Jun 14 13:27:22 1995 Steve Chamberlain * deflex.l, defparse.y, dlltool.c: New files. * Makefile.in, configure.in: Support for them. Mon Jun 12 11:27:54 1995 Steve Chamberlain * sysdump.c: Include sysdep.h (main): Open input with FOPEN_RB. binutils/7137 --- binutils/.Sanitize | 3 + binutils/ChangeLog | 10 + binutils/defparse.y | 135 ++++++ binutils/dlltool.c | 1016 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 1164 insertions(+) create mode 100644 binutils/defparse.y create mode 100644 binutils/dlltool.c diff --git a/binutils/.Sanitize b/binutils/.Sanitize index df81854d05d..197cced3beb 100644 --- a/binutils/.Sanitize +++ b/binutils/.Sanitize @@ -45,6 +45,9 @@ config configure.bat configure.in cxxfilt.man +dlltool.c +defparse.y +deflex.l filemode.c gmalloc.c is-ranlib.c diff --git a/binutils/ChangeLog b/binutils/ChangeLog index 04840a87eed..86610908ec7 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,3 +1,13 @@ +Wed Jun 14 13:27:22 1995 Steve Chamberlain + + * deflex.l, defparse.y, dlltool.c: New files. + * Makefile.in, configure.in: Support for them. + +Mon Jun 12 11:27:54 1995 Steve Chamberlain + + * sysdump.c: Include sysdep.h + (main): Open input with FOPEN_RB. binutils/7137 + Fri Jun 9 17:26:11 1995 Michael Meissner * objdump.c (wide_output): New flag variable. diff --git a/binutils/defparse.y b/binutils/defparse.y new file mode 100644 index 00000000000..4a9ca394450 --- /dev/null +++ b/binutils/defparse.y @@ -0,0 +1,135 @@ +{ +/* defparse.y - parser for .def files */ + +/* Copyright (C) 1995 Free Software Foundation, Inc. + +This file is part of GNU Binutils. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + + +%union { + char *id; + int number; +char *string; +}; + +%token NAME, LIBRARY, DESCRIPTION, STACKSIZE, HEAPSIZE, CODE, DATA +%token SECTIONS, EXPORTS, IMPORTS, VERSION, BASE, CONSTANT +%token READ WRITE EXECUTE SHARED NONAME +%token ID +%token STRING +%token NUMBER +%type opt_base opt_ordinal opt_NONAME opt_CONSTANT attr attr_list opt_number +%type opt_name opt_equal_name + +%% + +start: start command + | command + ; + +command: + NAME opt_name opt_base { def_name ($2, $3); } + | LIBRARY opt_name opt_base { def_library ($2, $3); } + | EXPORTS explist + | DESCRIPTION STRING { def_description ($2);} + | STACKSIZE NUMBER opt_number { def_stacksize ($2, $3);} + | HEAPSIZE NUMBER opt_number { def_heapsize ($2, $3);} + | CODE attr_list { def_code ($2);} + | DATA attr_list { def_data ($2);} + | SECTIONS seclist + | IMPORTS implist + | VERSION NUMBER { def_version ($2,0);} + | VERSION NUMBER '.' NUMBER { def_version ($2,$4);} + ; + + +explist: + explist expline + | expline + ; + +expline: + ID opt_equal_name opt_ordinal opt_NONAME opt_CONSTANT + { def_exports ($1, $2, $3, $4, $5);} + ; +implist: + implist impline + | impline + ; + +impline: + ID '=' ID '.' ID { def_import ($1,$3,$5);} + | ID '.' ID { def_import (0, $1,$3);} + ; +seclist: + seclist secline + | secline + ; + +secline: + ID attr_list { def_section ($1,$2);} + ; + +attr_list: + attr_list opt_comma attr + | attr + ; + +opt_comma: + ',' + | + ; +opt_number: ',' NUMBER { $$=$2;} + | { $$=-1;} + ; + +attr: + READ { $$ = 1;} + | WRITE { $$ = 2;} + | EXECUTE { $$=4;} + | SHARED { $$=8;} + ; + +opt_CONSTANT: + CONSTANT {$$=1;} + | {$$=0;} + ; +opt_NONAME: + NONAME {$$=1;} + | {$$=0;} + ; + +opt_name: ID { $$ =$1; } + | { $$=""; } + ; + +opt_ordinal: + '@' NUMBER { $$=$2;} + | { $$=-1;} + ; + +opt_equal_name: + '=' ID { $$ = $2; } + | { $$ = 0; } + ; + +opt_base: BASE '=' NUMBER { $$= $3;} + | { $$=-1;} + ; + + + diff --git a/binutils/dlltool.c b/binutils/dlltool.c new file mode 100644 index 00000000000..69fe91f23e4 --- /dev/null +++ b/binutils/dlltool.c @@ -0,0 +1,1016 @@ +/* dlltool.c -- tool to generate stuff for PE style DLLs + Copyright (C) 1995 Free Software Foundation, Inc. + + This file is part of GNU Binutils. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + + +/* + This program allows you to build the files necessary to create + DLLs to run on a system which understands PE format image files. + (eg, Windows NT) + + A DLL contains an export table which contains the information + which the runtime loader needs to tie up references from a + referencing program. + + The export table is generated by this program by reading + in a .DEF file or scanning the .a and .o files which will be in the + DLL. A .o file can contain information in special ".drective" sections + with export information. + + A DEF file contains any number of the following commands: + + + NAME [ , ] + The result is going to be .EXE + + LIBRARY [ , ] + The result is going to be .DLL + + EXPORTS ( [ = ] [ @ ] [ NONAME ] [CONSTANT] ) * + Declares name1 as an exported symbol from the + DLL, with optional ordinal number + + IMPORTS ( [ = ] . ) * + Ignored for compatibility + + DESCRIPTION + Puts into output .exp file in the .rdata section + + [STACKSIZE|HEAPSIZE] [ , ] + Generates --stack|--heap , + in the output .drective section. The linker will + see this and act upon it. + + [CODE|DATA] + + SECTIONS ( + )* + = READ | WRITE | EXECUTE | SHARED + Generates --attr in the output + .drective section. The linker will see this and act + upon it. + + + A -export: in a .drective section in an input .o or .a + file to this program is equivalent to a EXPORTS + in a .DEF file. + + + + The program generates output files with the prefix supplied + on the command line, or in the def file, or taken from the first + supplied argument. + + The output files are .exp.s and .lib.s + + The .exp.s file contains the information necessary to export + the routines in the DLL. The .lib.s file contains the information + necessary to use the DLL's routines from a referencing program. + + + +Example: + +file1.c: + asm (".section .drectve"); + asm (".ascii \"-export:adef\""); + + adef(char *s) + { + printf("hello from the dll %s\n",s); + } + + bdef(char *s) + { + printf("hello from the dll and the other entry point %s\n",s); + } + +file2.c: + asm (".section .drectve"); + asm (".ascii \"-export:cdef\""); + asm (".ascii \"-export:ddef\""); + cdef(char *s) + { + printf("hello from the dll %s\n",s); + } + + ddef(char *s) + { + printf("hello from the dll and the other entry point %s\n",s); + } + + printf() + { + return 9; + } + +main.c + + main() + { + cdef(); + } + +thedll.def + + LIBRARY thedll + HEAPSIZE 0x40000, 0x2000 + EXPORTS bdef @ 20 + cdef @ 30 NONAME + + SECTIONS donkey READ WRITE + aardvark EXECUTE + + +# compile up the parts of the dll + +gcc -c file1.c +gcc -c file2.c + +# put them in a library (you don't have to, you +# could name all the .os on the dlltool line) + +ar qcv thedll.in file1.o file2.o +ranlib thedll.in + +# run this tool over the library and the def file +./dlltool -o thedll -d thedll.def thedll.in + +# build the export table for the dll +as -o thedll.exp thedll.exp.s +# build the dll with the library with file1.o, file2.o and the export table +ld -o thedll.dll thedll.exp thedll.in + +# build the import table for the executable +as -o thedll.lib thedll.lib.s + +# build the mainline +gcc -c themain.c + +# link the executable with the import library +ld -e main -Tthemain.ld -o themain.exe themain.o thedll.lib + + +*/ + +#include +#include +#include +#include "getopt.h" +#include "bfd.h" +int yydebug; +char *def_file; +char *program_name; +char *strrchr (); +char *outfile_prefix; +char *xmalloc (); +char *strdup (); + +static int machine; + +#ifdef DLLTOOL_ARM +static char *mname = "arm"; +#endif + +#ifdef DLLTOOL_I386 +static char *mname = "i386"; +#endif + +struct mac +{ + char *type; + char *how_byte; + char *how_short; + char *how_long; + char *how_asciz; + char *how_comment; + char *how_jump; + char *how_global; + char *how_space; +} mtable[] += {{"arm",".byte",".short",".long",".asciz","@","bl",".global",".space"}, + {"i386",".byte",".short",".long",".asciz",";","jmp",".global",".space"}, + 0}; + +#define ASM_BYTE mtable[machine].how_byte +#define ASM_SHORT mtable[machine].how_short +#define ASM_LONG mtable[machine].how_long +#define ASM_TEXT mtable[machine].how_asciz +#define ASM_C mtable[machine].how_comment +#define ASM_JUMP mtable[machine].how_jump +#define ASM_GLOBAL mtable[machine].how_global +#define ASM_SPACE mtable[machine].how_space + +#define PATHMAX 250 /* What's the right name for this ? */ +static char **oav; + +int i; + +FILE *yyin; /* communications with flex */ +extern int linenumber; +void +process_def_file (name) + char *name; +{ + FILE *f = fopen (name, "r"); + if (!f) + { + fprintf (stderr, "Can't open def file %s\n", name); + exit (1); + } + + yyin = f; + + yyparse (); +} + +/**********************************************************************/ + +/* Communications with the parser */ + + +typedef struct dlist +{ + char *text; + struct dlist *next; +} dlist_type; + +typedef struct export +{ + char *name; + char *equal; + int ordinal; + int constant; + int noname; + struct export *next; +} +export_type; + +static char *d_name; /* Arg to NAME or LIBRARY */ +static int d_nfuncs; /* Number of functions exported */ +static int d_ord; /* Base ordinal index */ +static export_type *d_exports; /*list of exported functions */ +static char *d_suffix = "dll"; +static dlist_type *d_list; /* Descriptions */ +static dlist_type *a_list; /* Stuff to go in directives */ + +static int d_is_dll; +static int d_is_exe; + +yyerror () +{ + fprintf (stderr, "Syntax error in def file %s:%d\n", + def_file, linenumber); +} + +void +def_exports (name, equal, ordinal, noname, constant) + char *name; + char *equal; + int ordinal; + int noname; + int constant; +{ + struct export *p = (struct export *) xmalloc (sizeof (*p)); + + p->name = name; + p->equal = equal; + p->ordinal = ordinal; + p->constant = constant; + p->noname = noname; + p->next = d_exports; + d_exports = p; + d_nfuncs++; + + + printf ("EXPORTS %s", name); + if (equal) + printf ("=%s", equal); + if (ordinal > 0) + printf ("@%d", ordinal); + if (constant) + printf (" CONSTANT"); + printf ("\n"); +} + +void +def_name (name, base) + char *name; + int base; +{ + printf ("NAME %s base %x\n", name, base); + if (d_is_dll) + { + fprintf (stderr, "Can't have LIBRARY and NAME\n"); + } + d_name = name; + if (strchr (d_name, '.')) + d_suffix = strdup (strchr (d_name, '.') + 1); + d_is_exe = 1; +} + +void +def_library (name, base) + char *name; + int base; +{ + printf ("LIBRARY %s base %x\n", name, base); + if (d_is_exe) + { + fprintf (stderr, "Can't have LIBRARY and NAME\n"); + } + d_name = name; + if (strchr (d_name, '.')) + d_suffix = strdup (strchr (d_name, '.') + 1); + d_is_dll = 1; +} + +void +def_description (desc) + char *desc; +{ + dlist_type *d = (dlist_type *)xmalloc(sizeof(dlist_type)); + d->text = strdup (desc); + d->next = d_list; + d_list = d; +} + +void new_directive(dir) +char *dir; +{ + dlist_type *d = (dlist_type *)xmalloc(sizeof(dlist_type)); + d->text = strdup (dir); + d->next = a_list; + a_list = d; +} + +void +def_stacksize (reserve, commit) + int reserve; + int commit; +{ + char b[200]; + if (commit>0) + sprintf (b,"-stack 0x%x,0x%x ", reserve, commit); + else + sprintf (b,"-stack 0x%x ", reserve); + new_directive (strdup(b)); +} + +void +def_heapsize (reserve, commit) + int reserve; + int commit; +{ + char b[200]; + if (commit>0) + sprintf (b,"-heap 0x%x,0x%x ", reserve, commit); + else + sprintf (b,"-heap 0x%x ", reserve); + new_directive (strdup(b)); +} + + +void +def_import (internal, module, entry) + char *internal; + char *module; + char *entry; +{ + fprintf (stderr, "IMPORTS are ignored"); +} + +void +def_version (major, minor) +{ + printf ("VERSION %d.%d\n", major, minor); +} + + +void +def_section (name, attr) + char *name; + int attr; +{ + char buf[200]; + char atts[5]; + char *d = atts; + if (attr & 1) + *d++= 'R'; + + if (attr & 2) + *d++ = 'W'; + if (attr & 4) + *d++ = 'X'; + if (attr & 8) + *d++ = 'S'; + *d++ = 0; + sprintf (buf, "-attr %s %s", name, atts); + new_directive (strdup(buf)); +} +void +def_code (attr) + int attr; +{ + +def_section ("CODE", attr); +} + +void +def_data (attr) + int attr; +{ + def_section ("DATA",attr); +} + + +/**********************************************************************/ + +void +scan_open_obj_file (abfd) + bfd *abfd; +{ + /* Look for .drectives */ + asection *s = bfd_get_section_by_name (abfd, ".drectve"); + if (s) + { + int size = bfd_get_section_size_before_reloc (s); + char *buf = xmalloc (size); + char *p; + char *e; + bfd_get_section_contents (abfd, s, buf, 0, size); + printf ("Sucking in info from %s\n", + bfd_get_filename (abfd)); + + /* Search for -export: strings */ + p = buf; + e = buf + size; + while (p < e) + { + if (p[0] == '-' + && strncmp (p, "-export:", 8) == 0) + { + char *name; + char *c; + p += 8; + name = p; + while (*p != ' ' && *p != '-' && p < e) + p++; + c = xmalloc (p - name + 1); + memcpy (c, name, p - name); + c[p - name] = 0; + def_exports (c, 0, -1, 0); + } + else + p++; + } + free (buf); + } +} + + +void +scan_obj_file (filename) + char *filename; +{ + bfd *f = bfd_openr (filename, 0); + + if (!f) + { + fprintf (stderr, "Unable to open object file %s\n", filename); + exit (1); + } + if (bfd_check_format (f, bfd_archive)) + { + bfd *arfile = bfd_openr_next_archived_file (f, 0); + while (arfile) + { + if (bfd_check_format (arfile, bfd_object)) + scan_open_obj_file (arfile); + bfd_close (arfile); + arfile = bfd_openr_next_archived_file (f, arfile); + } + } + + if (bfd_check_format (f, bfd_object)) + { + scan_open_obj_file (f); + } + + bfd_close (f); +} + +/**********************************************************************/ + + +/* return the bit of the name before the last . */ + +static +char * +prefix (name) + char *name; +{ + char *res = strdup (name); + char *p = strrchr (res, '.'); + if (p) + *p = 0; + return res; +} + +void +dump_def_info (f) +FILE *f; +{ + int i; + export_type *exp; + fprintf(f,"%s ", ASM_C); + for (i= 0; oav[i]; i++) + fprintf(f,"%s ", oav[i]); + fprintf(f,"\n"); + for (i = 0, exp = d_exports; exp; i++, exp = exp->next) + { + fprintf (f, "%s %d %s @ %d %s%s\n", + ASM_C, + i, + exp->name, exp->ordinal, + exp->noname ? "NONAME " : "", + exp->constant ? "CONSTANT" : ""); + } +} +/* Generate the .exp file */ + + +void +gen_exp_file () +{ + FILE *f; + char outfile[PATHMAX]; + int i; + export_type *exp; + dlist_type *dl; + sprintf (outfile, "%s.exp.s", outfile_prefix); + + f = fopen (outfile, "w"); + if (!f) + { + fprintf (stderr, "Unable to open output file %s\n", outfile); + exit (1); + } + dump_def_info (f); + fprintf (f, "\t.section .edata\n\n"); + fprintf (f, "\t%s 0 %s Allways 0\n", ASM_LONG, ASM_C); + fprintf (f, "\t%s %d %s Time and date\n", ASM_LONG, time (0), ASM_C); + fprintf (f, "\t%s 0 %s Major and Minor version\n", ASM_LONG, ASM_C); + fprintf (f, "\t%s name %s Ptr to name of dll\n", ASM_LONG, ASM_C); + fprintf (f, "\t%s %d %s Starting ordinal of exports\n", ASM_LONG, d_ord, ASM_C); + fprintf (f, "\t%s The next field is documented as being the number of functions\n", ASM_C); + fprintf (f, "\t%s yet it doesn't look like that in real PE dlls\n", ASM_C); + fprintf (f, "\t%s But it shouldn't be a problem, causes there's\n", ASM_C); + fprintf (f, "\t%s always the number of names field\n", ASM_C); + fprintf (f, "\t%s %d %s Number of functions\n", ASM_LONG, d_nfuncs, ASM_C); + fprintf (f, "\t%s %d %s Number of names\n", ASM_LONG, d_nfuncs, ASM_C); + fprintf (f, "\t%s afuncs %s Address of functions\n", ASM_LONG, ASM_C); + fprintf (f, "\t%s anames %s Address of names\n", ASM_LONG, ASM_C); + fprintf (f, "\t%s anords %s Address of ordinals\n", ASM_LONG, ASM_C); + + fprintf (f, "name: %s \"%s.%s\"\n", ASM_TEXT, outfile_prefix, d_suffix); + + fprintf (f, "afuncs:\n"); + i = d_ord; + for (exp = d_exports; exp; exp = exp->next) + { + if (exp->ordinal != i) + { + fprintf (f, "\t%s\t%d\t@ %d..%d missing\n", ASM_SPACE, + (exp->ordinal - i) * 4, + i, exp->ordinal - 1); + i = exp->ordinal; + } + fprintf (f, "\t%s %s\t%s %d\n", ASM_LONG, exp->name, ASM_C, exp->ordinal); + i++; + } + + + fprintf (f, "anames:\n"); + for (i = 0, exp = d_exports; exp; i++, exp = exp->next) + if (exp->noname) + fprintf (f, "\t%s 0\t%sNoname\n", ASM_LONG, ASM_C); + else + fprintf (f, "\t%s n%d\n", ASM_LONG, i); + + fprintf (f, "anords:\n"); + for (exp = d_exports; exp; exp = exp->next) + fprintf (f, "\t%s %d\n", ASM_SHORT, exp->ordinal - d_ord); + + for (i = 0, exp = d_exports; exp; i++, exp = exp->next) + if (exp->noname) + fprintf (f, "@n%d: %s \"%s\"\n", i, ASM_TEXT, exp->name); + else + fprintf (f, "n%d: %s \"%s\"\n", i, ASM_TEXT, exp->name); + + + if (a_list) + { + fprintf(f,"\t.section .drectve\n"); + for (dl = a_list; dl; dl = dl->next) + { + fprintf (f,"\t%s\t\"%s\"\n", ASM_TEXT, dl->text); + } + } + if (d_list) + { + fprintf(f,"\t.section .rdata\n"); + for (dl = d_list; dl; dl = dl->next) + { + char *p; + int l; + /* We dont output as ascii 'cause there can + be quote characters in the string */ + + l = 0; + for (p = dl->text; *p; p++) { + if (l == 0) + fprintf(f,"\t%s\t", ASM_BYTE); + else + fprintf(f,","); + fprintf(f,"%d", *p); + if (p[1] == 0) { + fprintf(f,",0\n"); + break; + } + if (++l == 10) { + fprintf(f,"\n"); + l = 0; + } + } + } + } + fclose (f); +} + +/**********************************************************************/ +gen_lib_file () +{ + char outfile[PATHMAX]; + int i; + FILE *f; + export_type *exp; + + sprintf (outfile, "%s.lib.s", outfile_prefix); + + f = fopen (outfile, "w"); + if (!f) + { + fprintf (stderr, "Unable to open output file %s\n", outfile); + exit (1); + } + + + dump_def_info (f); + fprintf (f, "\t.text\n"); + fprintf (f, "%s Thunk table\n", ASM_C); + for (i = 0, exp = d_exports; exp; i++, exp = exp->next) + { + fprintf (f, "\t%s\t%s\n", ASM_GLOBAL, exp->name); + fprintf (f, "\t%s\t__imp__%s\n", ASM_GLOBAL, exp->name); + } + + for (i = 0, exp = d_exports; exp; i++, exp = exp->next) + { + fprintf (f, "%s:\t%s\t__imp__%s\n", exp->name, ASM_JUMP, exp->name); + } + + + fprintf (f, "%s IMAGE_IMPORT_DESCRIPTOR\n", ASM_C); + fprintf (f, "\t.section .idata$2\n"); + fprintf (f, "\t%s\thname\t%s Ptr to image import by name list\n", ASM_LONG, ASM_C); + fprintf (f, "\t%s\t%d\t%s time\n", ASM_LONG, time (0), ASM_C); + fprintf (f, "\t%s\t0\t%s Forwarder chain\n", ASM_LONG, ASM_C); + fprintf (f, "\t%s\tiname\t%s imported dll's name\n", ASM_LONG, ASM_C); + fprintf (f, "\t%s\tfthunk\t%s pointer to firstthunk\n", ASM_LONG, ASM_C); + + fprintf (f, "\n%s Loader modifies this\n", ASM_C); + fprintf (f, "\t.section .idata$5\n"); + fprintf (f, "fthunk:\n"); + for (i = 0, exp = d_exports; exp; i++, exp = exp->next) + { + fprintf (f, "__imp__%s:\n", exp->name); + fprintf (f, "\t%s\tID%d\n", ASM_LONG, i); + } + + fprintf (f, "\n%s Hint name array\n", ASM_C); + fprintf (f, "\t.section .idata$4\n"); + fprintf (f, "hname:\n"); + for (i = 0, exp = d_exports; exp; i++, exp = exp->next) + { + fprintf (f, "\t%s\tID%d\n", ASM_LONG, i); + } + + fprintf (f, "%s Hint/name array storage and import dll name\n", ASM_C); + fprintf (f, "\t.section .idata$6\n"); + + for (i = 0, exp = d_exports; exp; i++, exp = exp->next) + { + fprintf (f, "ID%d:\t%s\t%d\n", i, ASM_SHORT, exp->ordinal); + fprintf (f, "\t%s\t\"%s\"\n", ASM_TEXT, exp->name); + } + + fprintf (f, "iname:\t%s\t\"%s.%s\"\n", ASM_TEXT, outfile_prefix, d_suffix); + fclose (f); +} +/**********************************************************************/ + +/* Run through the information gathered from the .o files and the + .def file and work out the best stuff */ +int +pfunc (a, b) + void *a; + void *b; +{ + export_type *ap = *(export_type **) a; + export_type *bp = *(export_type **) b; + if (ap->ordinal == bp->ordinal) + return 0; + + /* unset ordinals go to the bottom */ + if (ap->ordinal == -1) + return 1; + if (bp->ordinal == -1) + return -1; + return (ap->ordinal - bp->ordinal); +} + + +int +nfunc (a, b) + void *a; + void *b; +{ + export_type *ap = *(export_type **) a; + export_type *bp = *(export_type **) b; + + return (strcmp (ap->name, bp->name)); +} + +static +void +remove_null_names (ptr) + export_type **ptr; +{ + int src; + int dst; + for (dst = src = 0; src < d_nfuncs; src++) + { + if (ptr[src]) + { + ptr[dst] = ptr[src]; + dst++; + } + } + d_nfuncs = dst; +} + +static void +dtab (ptr) + export_type **ptr; +{ +#ifdef SACDEBUG + int i; + for (i = 0; i < d_nfuncs; i++) + { + if (ptr[i]) + { + printf ("%d %s @ %d %s%s\n", + i, ptr[i]->name, ptr[i]->ordinal, + ptr[i]->noname ? "NONAME " : "", + ptr[i]->constant ? "CONSTANT" : ""); + } + else + printf ("empty\n"); + } +#endif +} + +static void +process_duplicates (d_export_vec) + export_type **d_export_vec; +{ + int more = 1; + + while (more) + { + more = 0; + /* Remove duplicates */ + qsort (d_export_vec, d_nfuncs, sizeof (export_type *), nfunc); + + dtab (d_export_vec); + for (i = 0; i < d_nfuncs - 1; i++) + { + if (strcmp (d_export_vec[i]->name, + d_export_vec[i + 1]->name) == 0) + { + + export_type *a = d_export_vec[i]; + export_type *b = d_export_vec[i + 1]; + + more = 1; + + fprintf (stderr, "warning, ignoring duplicate EXPORT %s\n", + a->name); + if (a->ordinal != -1 + && b->ordinal != -1) + { + + fprintf (stderr, "Error, duplicate EXPORT with oridinals %s\n", + a->name); + exit (1); + } + /* Merge attributes */ + b->ordinal = a->ordinal > 0 ? a->ordinal : b->ordinal; + b->constant |= a->constant; + b->noname |= a->noname; + d_export_vec[i] = 0; + } + + dtab (d_export_vec); + remove_null_names (d_export_vec); + dtab (d_export_vec); + } + } +} + +static void +fill_ordinals (d_export_vec) + export_type **d_export_vec; +{ + int lowest = 0; + qsort (d_export_vec, d_nfuncs, sizeof (export_type *), pfunc); + + /* fill in the unset ordinals with ones from the minimum */ + for (i = 0; i < d_nfuncs; i++) + { + if (d_export_vec[i]->ordinal == -1) + { + d_export_vec[i]->ordinal = lowest++; + } + else + { + if (lowest == d_export_vec[i]->ordinal) + { + fprintf (stderr, "Warning, Duplicate ordinal %s @ %d\n", + d_export_vec[i]->name, + d_export_vec[i]->ordinal); + } + lowest = d_export_vec[i]->ordinal + 1; + } + } + + /* Work out the lowest ordinal number */ + if (d_export_vec[0]) + d_ord = d_export_vec[0]->ordinal; +} +void +mangle_defs () +{ + /* First work out the minimum ordinal chosen */ + + export_type *exp; + int lowest = 0; + int i; + export_type **d_export_vec + = (export_type **) xmalloc (sizeof (export_type *) * d_nfuncs); + + for (i = 0, exp = d_exports; exp; i++, exp = exp->next) + { + d_export_vec[i] = exp; + } + + process_duplicates (d_export_vec); + fill_ordinals (d_export_vec); + + /* Put back the list in the new order */ + d_exports = 0; + for (i = d_nfuncs - 1; i >= 0; i--) + { + d_export_vec[i]->next = d_exports; + d_exports = d_export_vec[i]; + } +} + + +/**********************************************************************/ + +void +usage (file, status) + FILE *file; + int status; +{ + fprintf (file, "Usage %s [-m|--machine machine] [-o outprefix] [-d|--def deffile] [--def deffile]\n", program_name); + exit (status); +} + +static struct option long_options[] = +{ + {"def", required_argument, NULL, 'd'}, + {"help", no_argument, NULL, 'h'}, + {"machine", required_argument, NULL, 'm'}, + 0 +}; + +int +main (ac, av) + int ac; + char **av; +{ + int c; + char *firstarg = 0; + program_name = av[0]; + oav = av; + + while ((c = getopt_long (ac, av, "h?m:o:Dd:", long_options, 0)) != EOF) + { + switch (c) + { + case 'h': + case '?': + usage(stderr,0); + break; + case 'm': + mname = optarg; + break; + case 'o': + outfile_prefix = optarg; + break; + case 'D': + yydebug = 1; + break; + case 'd': + def_file = optarg; + break; + default: + usage (stderr, 1); + } + } + + + for (i = 0; mtable[i].type; i++) + { + if (strcmp (mtable[i].type, mname) == 0) + break; + } + + if (!mtable[i].type) + { + fprintf(stderr,"Machine not supported\n"); + exit(1); + } + machine = i; + + + if (def_file) + { + + process_def_file (def_file); + } + while (optind < ac) + { + if (!firstarg) + firstarg = av[optind]; + scan_obj_file (av[optind]); + optind++; + } + + if (!outfile_prefix) + { + if (d_name) + outfile_prefix = d_name; + else if (def_file) + outfile_prefix = def_file; + else if (firstarg) + outfile_prefix = firstarg; + else + { + fprintf (stderr, "No way to create an output filename\n"); + exit (1); + } + } + outfile_prefix = prefix (outfile_prefix); + + mangle_defs (); + gen_exp_file (); + gen_lib_file (); + return 0; +} -- 2.30.2