* ar.c: (print_contents.c, extract_file, do_quick_append):
[deliverable/binutils-gdb.git] / binutils / dlltool.c
1 /* dlltool.c -- tool to generate stuff for PE style DLLs
2 Copyright (C) 1995 Free Software Foundation, Inc.
3
4 This file is part of GNU Binutils.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20
21 /*
22 This program allows you to build the files necessary to create
23 DLLs to run on a system which understands PE format image files.
24 (eg, Windows NT)
25
26 A DLL contains an export table which contains the information
27 which the runtime loader needs to tie up references from a
28 referencing program.
29
30 The export table is generated by this program by reading
31 in a .DEF file or scanning the .a and .o files which will be in the
32 DLL. A .o file can contain information in special ".drective" sections
33 with export information.
34
35 A DEF file contains any number of the following commands:
36
37
38 NAME <name> [ , <base> ]
39 The result is going to be <name>.EXE
40
41 LIBRARY <name> [ , <base> ]
42 The result is going to be <name>.DLL
43
44 EXPORTS ( <name1> [ = <name2> ] [ @ <integer> ] [ NONAME ] [CONSTANT] ) *
45 Declares name1 as an exported symbol from the
46 DLL, with optional ordinal number <integer>
47
48 IMPORTS ( [ <name> = ] <name> . <name> ) *
49 Ignored for compatibility
50
51 DESCRIPTION <string>
52 Puts <string> into output .exp file in the .rdata section
53
54 [STACKSIZE|HEAPSIZE] <number-reserve> [ , <number-commit> ]
55 Generates --stack|--heap <number-reserve>,<number-commit>
56 in the output .drective section. The linker will
57 see this and act upon it.
58
59 [CODE|DATA] <attr>+
60 SECTIONS ( <sectionname> <attr>+ )*
61 <attr> = READ | WRITE | EXECUTE | SHARED
62 Generates --attr <sectionname> <attr> in the output
63 .drective section. The linker will see this and act
64 upon it.
65
66
67 A -export:<name> in a .drective section in an input .o or .a
68 file to this program is equivalent to a EXPORTS <name>
69 in a .DEF file.
70
71
72
73 The program generates output files with the prefix supplied
74 on the command line, or in the def file, or taken from the first
75 supplied argument.
76
77 The output files are <prefix>-exp.s and <prefix>-lib.s
78
79 The .exp.s file contains the information necessary to export
80 the routines in the DLL. The .lib.s file contains the information
81 necessary to use the DLL's routines from a referencing program.
82
83
84
85 Example:
86
87 file1.c:
88 asm (".section .drectve");
89 asm (".ascii \"-export:adef\"");
90
91 adef(char *s)
92 {
93 printf("hello from the dll %s\n",s);
94 }
95
96 bdef(char *s)
97 {
98 printf("hello from the dll and the other entry point %s\n",s);
99 }
100
101 file2.c:
102 asm (".section .drectve");
103 asm (".ascii \"-export:cdef\"");
104 asm (".ascii \"-export:ddef\"");
105 cdef(char *s)
106 {
107 printf("hello from the dll %s\n",s);
108 }
109
110 ddef(char *s)
111 {
112 printf("hello from the dll and the other entry point %s\n",s);
113 }
114
115 printf()
116 {
117 return 9;
118 }
119
120 main.c
121
122 main()
123 {
124 cdef();
125 }
126
127 thedll.def
128
129 LIBRARY thedll
130 HEAPSIZE 0x40000, 0x2000
131 EXPORTS bdef @ 20
132 cdef @ 30 NONAME
133
134 SECTIONS donkey READ WRITE
135 aardvark EXECUTE
136
137
138 # compile up the parts of the dll
139
140 gcc -c file1.c
141 gcc -c file2.c
142
143 # put them in a library (you don't have to, you
144 # could name all the .os on the dlltool line)
145
146 ar qcv thedll.in file1.o file2.o
147 ranlib thedll.in
148
149 # run this tool over the library and the def file
150 ./dlltool -o thedll -d thedll.def thedll.in
151
152 # build the export table for the dll
153 as -o thedll.exp thedll-exp.s
154 # build the dll with the library with file1.o, file2.o and the export table
155 ld -o thedll.dll thedll.exp thedll.in
156
157 # build the import table for the executable
158 as -o thedll.lib thedll-lib.s
159
160 # build the mainline
161 gcc -c themain.c
162
163 # link the executable with the import library
164 ld -e main -Tthemain.ld -o themain.exe themain.o thedll.lib
165
166 */
167
168 #define PAGE_SIZE 4096
169 #define PAGE_MASK (-PAGE_SIZE)
170 #include <stdio.h>
171 #include <stdlib.h>
172 #include <string.h>
173 #include "getopt.h"
174 #include "bfd.h"
175 int yydebug;
176 char *def_file;
177 char *program_name;
178 char *strrchr ();
179 char *outfile_prefix;
180 char *xmalloc ();
181 char *strdup ();
182
183 static int machine;
184 int suckunderscore;
185 static int verbose;
186 FILE *base_file;
187 #ifdef DLLTOOL_ARM
188 static char *mname = "arm";
189 #endif
190
191 #ifdef DLLTOOL_I386
192 static char *mname = "i386";
193 #endif
194 #define PATHMAX 250 /* What's the right name for this ? */
195
196 char outfile[PATHMAX];
197 struct mac
198 {
199 char *type;
200 char *how_byte;
201 char *how_short;
202 char *how_long;
203 char *how_asciz;
204 char *how_comment;
205 char *how_jump;
206 char *how_global;
207 char *how_space;
208 }
209 mtable[]
210 =
211 {
212 {
213 "arm", ".byte", ".short", ".long", ".asciz", "@", "ldr\tip,[pc]\n\tldr\tpc,[ip]\n\t.long", ".global", ".space"
214 }
215 ,
216 {
217 "i386", ".byte", ".short", ".long", ".asciz", "#", "jmp *", ".global", ".space"
218 }
219 ,
220 0
221 };
222
223 #define ASM_BYTE mtable[machine].how_byte
224 #define ASM_SHORT mtable[machine].how_short
225 #define ASM_LONG mtable[machine].how_long
226 #define ASM_TEXT mtable[machine].how_asciz
227 #define ASM_C mtable[machine].how_comment
228 #define ASM_JUMP mtable[machine].how_jump
229 #define ASM_GLOBAL mtable[machine].how_global
230 #define ASM_SPACE mtable[machine].how_space
231
232
233 static char **oav;
234
235 int i;
236
237 FILE *yyin; /* communications with flex */
238 extern int linenumber;
239 void
240 process_def_file (name)
241 char *name;
242 {
243 FILE *f = fopen (name, "r");
244 if (!f)
245 {
246 fprintf (stderr, "%s: Can't open def file %s\n", program_name, name);
247 exit (1);
248 }
249
250 yyin = f;
251
252 yyparse ();
253 }
254
255 /**********************************************************************/
256
257 /* Communications with the parser */
258
259
260 typedef struct dlist
261 {
262 char *text;
263 struct dlist *next;
264 }
265 dlist_type;
266
267 typedef struct export
268 {
269 char *name;
270 char *internal_name;
271 int ordinal;
272 int constant;
273 int noname;
274 struct export *next;
275 }
276 export_type;
277
278 static char *d_name; /* Arg to NAME or LIBRARY */
279 static int d_nfuncs; /* Number of functions exported */
280 static int d_ord; /* Base ordinal index */
281 static export_type *d_exports; /*list of exported functions */
282 static char *d_suffix = "dll";
283 static dlist_type *d_list; /* Descriptions */
284 static dlist_type *a_list; /* Stuff to go in directives */
285
286 static int d_is_dll;
287 static int d_is_exe;
288
289 yyerror ()
290 {
291 fprintf (stderr, "%s: Syntax error in def file %s:%d\n",
292 program_name, def_file, linenumber);
293 }
294
295 void
296 def_exports (name, internal_name, ordinal, noname, constant)
297 char *name;
298 char *internal_name;
299 int ordinal;
300 int noname;
301 int constant;
302 {
303 struct export *p = (struct export *) xmalloc (sizeof (*p));
304
305 p->name = name;
306 p->internal_name = internal_name ? internal_name : name;
307 p->ordinal = ordinal;
308 p->constant = constant;
309 p->noname = noname;
310 p->next = d_exports;
311 d_exports = p;
312 d_nfuncs++;
313 }
314
315
316 void
317 def_name (name, base)
318 char *name;
319 int base;
320 {
321 if (verbose)
322 fprintf (stderr, "%s NAME %s base %x\n", program_name, name, base);
323 if (d_is_dll)
324 {
325 fprintf (stderr, "Can't have LIBRARY and NAME\n");
326 }
327 d_name = name;
328 if (strchr (d_name, '.'))
329 d_suffix = strdup (strchr (d_name, '.') + 1);
330 d_is_exe = 1;
331 }
332
333 void
334 def_library (name, base)
335 char *name;
336 int base;
337 {
338 if (verbose)
339 printf ("%s: LIBRARY %s base %x\n", program_name, name, base);
340 if (d_is_exe)
341 {
342 fprintf (stderr, "%s: Can't have LIBRARY and NAME\n", program_name);
343 }
344 d_name = name;
345 if (strchr (d_name, '.'))
346 d_suffix = strdup (strchr (d_name, '.') + 1);
347 d_is_dll = 1;
348 }
349
350 void
351 def_description (desc)
352 char *desc;
353 {
354 dlist_type *d = (dlist_type *) xmalloc (sizeof (dlist_type));
355 d->text = strdup (desc);
356 d->next = d_list;
357 d_list = d;
358 }
359
360 void
361 new_directive (dir)
362 char *dir;
363 {
364 dlist_type *d = (dlist_type *) xmalloc (sizeof (dlist_type));
365 d->text = strdup (dir);
366 d->next = a_list;
367 a_list = d;
368 }
369
370 void
371 def_stacksize (reserve, commit)
372 int reserve;
373 int commit;
374 {
375 char b[200];
376 if (commit > 0)
377 sprintf (b, "-stack 0x%x,0x%x ", reserve, commit);
378 else
379 sprintf (b, "-stack 0x%x ", reserve);
380 new_directive (strdup (b));
381 }
382
383 void
384 def_heapsize (reserve, commit)
385 int reserve;
386 int commit;
387 {
388 char b[200];
389 if (commit > 0)
390 sprintf (b, "-heap 0x%x,0x%x ", reserve, commit);
391 else
392 sprintf (b, "-heap 0x%x ", reserve);
393 new_directive (strdup (b));
394 }
395
396
397 void
398 def_import (internal, module, entry)
399 char *internal;
400 char *module;
401 char *entry;
402 {
403 if (verbose)
404 fprintf (stderr, "%s: IMPORTS are ignored", program_name);
405 }
406
407 void
408 def_version (major, minor)
409 {
410 printf ("VERSION %d.%d\n", major, minor);
411 }
412
413
414 void
415 def_section (name, attr)
416 char *name;
417 int attr;
418 {
419 char buf[200];
420 char atts[5];
421 char *d = atts;
422 if (attr & 1)
423 *d++ = 'R';
424
425 if (attr & 2)
426 *d++ = 'W';
427 if (attr & 4)
428 *d++ = 'X';
429 if (attr & 8)
430 *d++ = 'S';
431 *d++ = 0;
432 sprintf (buf, "-attr %s %s", name, atts);
433 new_directive (strdup (buf));
434 }
435 void
436 def_code (attr)
437 int attr;
438 {
439
440 def_section ("CODE", attr);
441 }
442
443 void
444 def_data (attr)
445 int attr;
446 {
447 def_section ("DATA", attr);
448 }
449
450
451 /**********************************************************************/
452
453 /* read in and block out the base relocations */
454 static void
455 basenames (abfd)
456 bfd *abfd;
457 {
458
459
460
461
462 }
463
464 void
465 scan_open_obj_file (abfd)
466 bfd *abfd;
467 {
468 /* Look for .drectives */
469 asection *s = bfd_get_section_by_name (abfd, ".drectve");
470 if (s)
471 {
472 int size = bfd_get_section_size_before_reloc (s);
473 char *buf = xmalloc (size);
474 char *p;
475 char *e;
476 bfd_get_section_contents (abfd, s, buf, 0, size);
477 if (verbose)
478 fprintf (stderr, "%s: Sucking in info from %s\n",
479 program_name,
480 bfd_get_filename (abfd));
481
482 /* Search for -export: strings */
483 p = buf;
484 e = buf + size;
485 while (p < e)
486 {
487 if (p[0] == '-'
488 && strncmp (p, "-export:", 8) == 0)
489 {
490 char *name;
491 char *c;
492 p += 8;
493 name = p;
494 while (*p != ' ' && *p != '-' && p < e)
495 p++;
496 c = xmalloc (p - name + 1);
497 memcpy (c, name, p - name);
498 c[p - name] = 0;
499 def_exports (c, 0, -1, 0);
500 }
501 else
502 p++;
503 }
504 free (buf);
505 }
506
507 basenames (abfd);
508
509 if (verbose)
510 fprintf (stderr, "%s: Done readin\n",
511 program_name);
512
513 }
514
515
516 void
517 scan_obj_file (filename)
518 char *filename;
519 {
520 bfd *f = bfd_openr (filename, 0);
521
522 if (!f)
523 {
524 fprintf (stderr, "%s: Unable to open object file %s\n",
525 program_name,
526 filename);
527 exit (1);
528 }
529 if (bfd_check_format (f, bfd_archive))
530 {
531 bfd *arfile = bfd_openr_next_archived_file (f, 0);
532 while (arfile)
533 {
534 if (bfd_check_format (arfile, bfd_object))
535 scan_open_obj_file (arfile);
536 bfd_close (arfile);
537 arfile = bfd_openr_next_archived_file (f, arfile);
538 }
539 }
540
541 if (bfd_check_format (f, bfd_object))
542 {
543 scan_open_obj_file (f);
544 }
545
546 bfd_close (f);
547 }
548
549 /**********************************************************************/
550
551
552 /* return the bit of the name before the last . */
553
554 static
555 char *
556 prefix (name)
557 char *name;
558 {
559 char *res = strdup (name);
560 char *p = strrchr (res, '.');
561 if (p)
562 *p = 0;
563 return res;
564 }
565
566 void
567 dump_def_info (f)
568 FILE *f;
569 {
570 int i;
571 export_type *exp;
572 fprintf (f, "%s ", ASM_C);
573 for (i = 0; oav[i]; i++)
574 fprintf (f, "%s ", oav[i]);
575 fprintf (f, "\n");
576 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
577 {
578 fprintf (f, "%s %d = %s %s @ %d %s%s\n",
579 ASM_C,
580 i,
581 exp->name,
582 exp->internal_name,
583 exp->ordinal,
584 exp->noname ? "NONAME " : "",
585 exp->constant ? "CONSTANT" : "");
586 }
587 }
588 /* Generate the .exp file */
589
590 int
591 sfunc (a, b)
592 long *a;
593 long *b;
594 {
595 return *a - *b;
596 }
597
598 static void
599 flush_page (f, need, page_addr, on_page)
600 FILE *f;
601 long *need;
602 long page_addr;
603 int on_page;
604 {
605 int i;
606 /* Flush this page */
607 fprintf (f, "\t%s\t0x%x\t%s Starting RVA for chunk\n",
608 ASM_LONG,
609 page_addr,
610 ASM_C);
611 fprintf (f, "\t%s\t0x%x\t%s Size of block\n",
612 ASM_LONG,
613 (on_page * 2) + (on_page & 1) * 2 + 8,
614 ASM_C);
615 for (i = 0; i < on_page; i++)
616 {
617 fprintf (f, "\t%s\t0x%x\n", ASM_SHORT, need[i] - page_addr | 0x3000);
618 }
619 /* And padding */
620 if (on_page & 1)
621 fprintf (f, "\t%s\t0x%x\n", ASM_SHORT, 0 | 0x0000);
622
623 }
624
625
626 void
627 gen_exp_file ()
628 {
629 FILE *f;
630 int i;
631 export_type *exp;
632 dlist_type *dl;
633 int had_noname = 0;
634
635 sprintf (outfile, "%s-exp.s", outfile_prefix);
636
637 if (verbose)
638 fprintf (stderr, "%s: Generate exp file %s\n",
639 program_name, outfile_prefix);
640
641 f = fopen (outfile, "w");
642 if (!f)
643 {
644 fprintf (stderr, "%s: Unable to open output file %s\n", program_name, outfile);
645 exit (1);
646 }
647 if (verbose)
648 {
649 fprintf (stderr, "%s: Opened file %s\n",
650 program_name, outfile);
651 }
652
653 dump_def_info (f);
654 fprintf (f, "\t.section .edata\n\n");
655 fprintf (f, "\t%s 0 %s Allways 0\n", ASM_LONG, ASM_C);
656 fprintf (f, "\t%s %d %s Time and date\n", ASM_LONG, time (0), ASM_C);
657 fprintf (f, "\t%s 0 %s Major and Minor version\n", ASM_LONG, ASM_C);
658 fprintf (f, "\t%s name %s Ptr to name of dll\n", ASM_LONG, ASM_C);
659 fprintf (f, "\t%s %d %s Starting ordinal of exports\n", ASM_LONG, d_ord, ASM_C);
660 fprintf (f, "\t%s The next field is documented as being the number of functions\n", ASM_C);
661 fprintf (f, "\t%s yet it doesn't look like that in real PE dlls\n", ASM_C);
662 fprintf (f, "\t%s But it shouldn't be a problem, causes there's\n", ASM_C);
663 fprintf (f, "\t%s always the number of names field\n", ASM_C);
664 fprintf (f, "\t%s %d %s Number of functions\n", ASM_LONG, d_nfuncs, ASM_C);
665 fprintf (f, "\t%s %d %s Number of names\n", ASM_LONG, d_nfuncs, ASM_C);
666 fprintf (f, "\t%s afuncs %s Address of functions\n", ASM_LONG, ASM_C);
667 fprintf (f, "\t%s anames %s Address of names\n", ASM_LONG, ASM_C);
668 fprintf (f, "\t%s anords %s Address of ordinals\n", ASM_LONG, ASM_C);
669
670 fprintf (f, "name: %s \"%s.%s\"\n", ASM_TEXT, outfile_prefix, d_suffix);
671
672 fprintf (f, "afuncs:\n");
673 i = d_ord;
674 for (exp = d_exports; exp; exp = exp->next)
675 {
676 #if 0
677 /* This seems necessary in the doc, but in real
678 life it's not used.. */
679 if (exp->ordinal != i)
680 {
681 fprintf (f, "%s\t%s\t%d\t@ %d..%d missing\n", ASM_C, ASM_SPACE,
682 (exp->ordinal - i) * 4,
683 i, exp->ordinal - 1);
684 i = exp->ordinal;
685 }
686 #endif
687 fprintf (f, "\t%s %s\t%s %d\n", ASM_LONG, exp->internal_name, ASM_C, exp->ordinal);
688 i++;
689 }
690
691
692 fprintf (f, "anames:\n");
693 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
694 {
695 if (exp->noname)
696 {
697 had_noname = 1;
698 fprintf (f, "\t%s nNoname\n", ASM_LONG, ASM_C);
699 }
700 else
701 {
702 fprintf (f, "\t%s n%d\n", ASM_LONG, i);
703 }
704 }
705
706 fprintf (f, "anords:\n");
707 for (exp = d_exports; exp; exp = exp->next)
708 fprintf (f, "\t%s %d\n", ASM_SHORT, exp->ordinal - d_ord);
709
710 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
711 if (exp->noname)
712 fprintf (f, "@n%d: %s \"%s\"\n", i, ASM_TEXT, exp->name);
713 else
714 fprintf (f, "n%d: %s \"%s\"\n", i, ASM_TEXT, exp->name);
715
716 if (had_noname)
717 fprintf (f, "nNoname: %s \"__noname__\"\n", ASM_TEXT);
718
719 if (a_list)
720 {
721 fprintf (f, "\t.section .drectve\n");
722 for (dl = a_list; dl; dl = dl->next)
723 {
724 fprintf (f, "\t%s\t\"%s\"\n", ASM_TEXT, dl->text);
725 }
726 }
727 if (d_list)
728 {
729 fprintf (f, "\t.section .rdata\n");
730 for (dl = d_list; dl; dl = dl->next)
731 {
732 char *p;
733 int l;
734 /* We dont output as ascii 'cause there can
735 be quote characters in the string */
736
737 l = 0;
738 for (p = dl->text; *p; p++)
739 {
740 if (l == 0)
741 fprintf (f, "\t%s\t", ASM_BYTE);
742 else
743 fprintf (f, ",");
744 fprintf (f, "%d", *p);
745 if (p[1] == 0)
746 {
747 fprintf (f, ",0\n");
748 break;
749 }
750 if (++l == 10)
751 {
752 fprintf (f, "\n");
753 l = 0;
754 }
755 }
756 }
757 }
758
759 /* Dump the reloc section if a base file is provided */
760 if (base_file)
761 {
762 int addr;
763 long need[PAGE_SIZE];
764 long page_addr;
765 int numbytes;
766 int num_entries;
767 long *copy;
768 int j;
769 int on_page;
770 fprintf (f, "\t.section\t.reloc\n");
771 fseek (base_file, 0, SEEK_END);
772 numbytes = ftell (base_file);
773 fseek (base_file, 0, SEEK_SET);
774 copy = malloc (numbytes);
775 fread (copy, 1, numbytes, base_file);
776 num_entries = numbytes / sizeof (long);
777
778 qsort (copy, num_entries, sizeof (long), sfunc);
779
780 addr = copy[0];
781 page_addr = addr & PAGE_MASK; /* work out the page addr */
782 on_page = 0;
783 for (j = 0; j < num_entries; j++)
784 {
785 addr = copy[j];
786 if ((addr & PAGE_MASK) != page_addr)
787 {
788 flush_page (f, need, page_addr, on_page);
789 on_page = 0;
790 page_addr = addr & PAGE_MASK;
791 }
792 need[on_page++] = addr;
793 }
794 flush_page (f, need, page_addr, on_page);
795 }
796
797 fclose (f);
798 }
799
800 static char *
801 xlate (char *name)
802 {
803 char *p;
804 if (!suckunderscore)
805 return name;
806
807 if (name[0] == '_')
808 name++;
809 p = strchr (name, '@');
810 if (p)
811 *p = 0;
812 return name;
813 }
814
815 /**********************************************************************/
816 gen_lib_file ()
817 {
818 int i;
819 FILE *f;
820 export_type *exp;
821
822 sprintf (outfile, "%s-lib.s", outfile_prefix);
823
824 f = fopen (outfile, "w");
825 if (!f)
826 {
827 fprintf (stderr, "Unable to open output file %s\n", outfile);
828 exit (1);
829 }
830
831
832 dump_def_info (f);
833 fprintf (f, "\t.text\n");
834 fprintf (f, "%s Thunk table\n", ASM_C);
835 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
836 {
837 fprintf (f, "\t%s\t%s\n", ASM_GLOBAL, exp->name);
838 fprintf (f, "\t%s\t__imp_%s\n", ASM_GLOBAL, exp->name);
839 }
840
841 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
842 {
843 fprintf (f, "%s:\t%s\t__imp_%s\n", exp->name, ASM_JUMP, exp->name);
844 }
845
846
847 fprintf (f, "%s IMAGE_IMPORT_DESCRIPTOR\n", ASM_C);
848 fprintf (f, "\t.section .idata$2\n");
849 fprintf (f, "\t%s\thname\t%s Ptr to image import by name list\n", ASM_LONG, ASM_C);
850 fprintf (f, "\t%s\t%d\t%s time\n", ASM_LONG, time (0), ASM_C);
851 fprintf (f, "\t%s\t0\t%s Forwarder chain\n", ASM_LONG, ASM_C);
852 fprintf (f, "\t%s\tiname\t%s imported dll's name\n", ASM_LONG, ASM_C);
853 fprintf (f, "\t%s\tfthunk\t%s pointer to firstthunk\n", ASM_LONG, ASM_C);
854
855 fprintf (f, "%sStuff for compatibility\n", ASM_C);
856 fprintf (f, "\t.section\t.idata$3\n");
857 fprintf (f, "\t%s\t0\n", ASM_LONG);
858 fprintf (f, "\t%s\t0\n", ASM_LONG);
859 fprintf (f, "\t%s\t0\n", ASM_LONG);
860 fprintf (f, "\t%s\t0\n", ASM_LONG);
861 fprintf (f, "\t%s\t0\n", ASM_LONG);
862 fprintf (f, "\t.section\t.idata$5\n");
863 fprintf (f, "\t%s\t0\n", ASM_LONG);
864
865 fprintf (f, "\t.section\t.idata$4\n");
866 fprintf (f, "\t%s\t0\n", ASM_LONG);
867
868 fprintf (f, "\n%s Loader modifies this\n", ASM_C);
869 fprintf (f, "\t.section .idata$5\n");
870 fprintf (f, "fthunk:\n");
871 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
872 {
873 fprintf (f, "__imp_%s:\n", exp->name);
874 fprintf (f, "\t%s\tID%d\n", ASM_LONG, i);
875 }
876 fprintf (f, "\t%s\t0\n", ASM_LONG);
877
878 fprintf (f, "\n%s Hint name array\n", ASM_C);
879 fprintf (f, "\t.section .idata$4\n");
880 fprintf (f, "hname:\n");
881 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
882 {
883 fprintf (f, "\t%s\tID%d\n", ASM_LONG, i);
884 }
885
886 fprintf (f, "\t%s\t0\n", ASM_LONG);
887 fprintf (f, "%s Hint/name array storage and import dll name\n", ASM_C);
888 fprintf (f, "\t.section .idata$6\n");
889
890 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
891 {
892 fprintf (f, "ID%d:\t%s\t%d\n", i, ASM_SHORT, exp->ordinal);
893 fprintf (f, "\t%s\t\"%s\"\n", ASM_TEXT, xlate (exp->name));
894 }
895 fprintf (f, "\t%s\t0\n", ASM_LONG);
896 fprintf (f, "iname:\t%s\t\"%s.%s\"\n", ASM_TEXT, outfile_prefix, d_suffix);
897 fclose (f);
898 }
899 /**********************************************************************/
900
901 /* Run through the information gathered from the .o files and the
902 .def file and work out the best stuff */
903 int
904 pfunc (a, b)
905 void *a;
906 void *b;
907 {
908 export_type *ap = *(export_type **) a;
909 export_type *bp = *(export_type **) b;
910 if (ap->ordinal == bp->ordinal)
911 return 0;
912
913 /* unset ordinals go to the bottom */
914 if (ap->ordinal == -1)
915 return 1;
916 if (bp->ordinal == -1)
917 return -1;
918 return (ap->ordinal - bp->ordinal);
919 }
920
921
922 int
923 nfunc (a, b)
924 void *a;
925 void *b;
926 {
927 export_type *ap = *(export_type **) a;
928 export_type *bp = *(export_type **) b;
929
930 return (strcmp (ap->name, bp->name));
931 }
932
933 static
934 void
935 remove_null_names (ptr)
936 export_type **ptr;
937 {
938 int src;
939 int dst;
940 for (dst = src = 0; src < d_nfuncs; src++)
941 {
942 if (ptr[src])
943 {
944 ptr[dst] = ptr[src];
945 dst++;
946 }
947 }
948 d_nfuncs = dst;
949 }
950
951 static void
952 dtab (ptr)
953 export_type **ptr;
954 {
955 #ifdef SACDEBUG
956 int i;
957 for (i = 0; i < d_nfuncs; i++)
958 {
959 if (ptr[i])
960 {
961 printf ("%d %s @ %d %s%s\n",
962 i, ptr[i]->name, ptr[i]->ordinal,
963 ptr[i]->noname ? "NONAME " : "",
964 ptr[i]->constant ? "CONSTANT" : "");
965 }
966 else
967 printf ("empty\n");
968 }
969 #endif
970 }
971
972 static void
973 process_duplicates (d_export_vec)
974 export_type **d_export_vec;
975 {
976 int more = 1;
977
978 while (more)
979 {
980 more = 0;
981 /* Remove duplicates */
982 qsort (d_export_vec, d_nfuncs, sizeof (export_type *), nfunc);
983
984 dtab (d_export_vec);
985 for (i = 0; i < d_nfuncs - 1; i++)
986 {
987 if (strcmp (d_export_vec[i]->name,
988 d_export_vec[i + 1]->name) == 0)
989 {
990
991 export_type *a = d_export_vec[i];
992 export_type *b = d_export_vec[i + 1];
993
994 more = 1;
995 if (verbose)
996 fprintf (stderr, "Warning, ignoring duplicate EXPORT %s %d,%d\n",
997 a->name,
998 a->ordinal,
999 b->ordinal);
1000 if (a->ordinal != -1
1001 && b->ordinal != -1)
1002 {
1003
1004 fprintf (stderr, "Error, duplicate EXPORT with oridinals %s\n",
1005 a->name);
1006 exit (1);
1007 }
1008 /* Merge attributes */
1009 b->ordinal = a->ordinal > 0 ? a->ordinal : b->ordinal;
1010 b->constant |= a->constant;
1011 b->noname |= a->noname;
1012 d_export_vec[i] = 0;
1013 }
1014
1015 dtab (d_export_vec);
1016 remove_null_names (d_export_vec);
1017 dtab (d_export_vec);
1018 }
1019 }
1020 }
1021
1022 static void
1023 fill_ordinals (d_export_vec)
1024 export_type **d_export_vec;
1025 {
1026 int lowest = 0;
1027 int unset = 0;
1028 char *ptr;
1029 qsort (d_export_vec, d_nfuncs, sizeof (export_type *), pfunc);
1030
1031 /* fill in the unset ordinals with ones from our range */
1032
1033 ptr = (char *) malloc (65536);
1034
1035 memset (ptr, 65536, 0);
1036
1037 /* Mark in our large vector all the numbers that are taken */
1038 for (i = 0; i < d_nfuncs; i++)
1039 {
1040 if (d_export_vec[i]->ordinal != -1)
1041 {
1042 ptr[d_export_vec[i]->ordinal] = 1;
1043 if (lowest == 0)
1044 lowest = d_export_vec[i]->ordinal;
1045 }
1046 }
1047
1048 for (i = 0; i < d_nfuncs; i++)
1049 {
1050 if (d_export_vec[i]->ordinal == -1)
1051 {
1052 int j;
1053 for (j = lowest; j < 65536; j++)
1054 if (ptr[j] == 0)
1055 {
1056 ptr[j] = 1;
1057 d_export_vec[i]->ordinal = j;
1058 goto done;
1059 }
1060
1061 for (j = 1; j < lowest; j++)
1062 if (ptr[j] == 0)
1063 {
1064 ptr[j] = 1;
1065 d_export_vec[i]->ordinal = j;
1066 goto done;
1067 }
1068 done:;
1069
1070 }
1071 }
1072
1073 free (ptr);
1074
1075 /* And resort */
1076
1077 qsort (d_export_vec, d_nfuncs, sizeof (export_type *), pfunc);
1078
1079 /* Work out the lowest ordinal number */
1080 if (d_export_vec[0])
1081 d_ord = d_export_vec[0]->ordinal;
1082 }
1083 void
1084 mangle_defs ()
1085 {
1086 /* First work out the minimum ordinal chosen */
1087
1088 export_type *exp;
1089 int lowest = 0;
1090 int i;
1091 export_type **d_export_vec
1092 = (export_type **) xmalloc (sizeof (export_type *) * d_nfuncs);
1093
1094 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
1095 {
1096 d_export_vec[i] = exp;
1097 }
1098
1099 process_duplicates (d_export_vec);
1100 fill_ordinals (d_export_vec);
1101
1102 /* Put back the list in the new order */
1103 d_exports = 0;
1104 for (i = d_nfuncs - 1; i >= 0; i--)
1105 {
1106 d_export_vec[i]->next = d_exports;
1107 d_exports = d_export_vec[i];
1108 }
1109 }
1110
1111
1112 /**********************************************************************/
1113
1114 void
1115 usage (file, status)
1116 FILE *file;
1117 int status;
1118 {
1119 fprintf (file, "Usage %s <options> <object-files>\n", program_name);
1120 fprintf (file, "\t -m <machine> Generate code for <machine>\n");
1121 fprintf (file, "\t --machine <machine>\n");
1122 fprintf (file, "\t -o <outprefix> Set output prefix\n");
1123 fprintf (file, "\t -d <deffile> Name input .def file\n");
1124 fprintf (file, "\t --def <deffile> \n");
1125 fprintf (file, "\t --base-file <basefile> Read linker generated base file\n");
1126 fprintf (file, "\t -b <basefile> \n");
1127 fprintf (file, "\t -v Verbose\n");
1128
1129 exit (status);
1130 }
1131
1132 static struct option long_options[] =
1133 {
1134 {"def", required_argument, NULL, 'd'},
1135 {"underscore", no_argument, NULL, 'u'},
1136 {"help", no_argument, NULL, 'h'},
1137 {"machine", required_argument, NULL, 'm'},
1138 {"base-file", required_argument, NULL, 'b'},
1139 0
1140 };
1141
1142 int
1143 main (ac, av)
1144 int ac;
1145 char **av;
1146 {
1147 int c;
1148 char *firstarg = 0;
1149 program_name = av[0];
1150 oav = av;
1151
1152 while ((c = getopt_long (ac, av, "vbuh?m:o:Dd:", long_options, 0)) != EOF)
1153 {
1154 switch (c)
1155 {
1156 case 'h':
1157 case '?':
1158 usage (stderr, 0);
1159 break;
1160 case 'm':
1161 mname = optarg;
1162 break;
1163 case 'o':
1164 outfile_prefix = optarg;
1165 break;
1166 case 'v':
1167 verbose = 1;
1168 break;
1169 case 'D':
1170 yydebug = 1;
1171 break;
1172 case 'u':
1173 suckunderscore = 1;
1174 break;
1175 case 'd':
1176 def_file = optarg;
1177 break;
1178 case 'b':
1179 base_file = fopen (optarg, "r");
1180 if (!base_file)
1181 {
1182 fprintf (stderr, "%s: Unable to open base-file %s\n",
1183 av[0],
1184 optarg);
1185 exit (1);
1186 }
1187 break;
1188 default:
1189 usage (stderr, 1);
1190 }
1191 }
1192
1193
1194 for (i = 0; mtable[i].type; i++)
1195 {
1196 if (strcmp (mtable[i].type, mname) == 0)
1197 break;
1198 }
1199
1200 if (!mtable[i].type)
1201 {
1202 fprintf (stderr, "Machine not supported\n");
1203 exit (1);
1204 }
1205 machine = i;
1206
1207
1208 if (def_file)
1209 {
1210 process_def_file (def_file);
1211 }
1212 while (optind < ac)
1213 {
1214 if (!firstarg)
1215 firstarg = av[optind];
1216 scan_obj_file (av[optind]);
1217 optind++;
1218 }
1219
1220 if (!outfile_prefix)
1221 {
1222 if (d_name)
1223 outfile_prefix = d_name;
1224 else if (def_file)
1225 outfile_prefix = def_file;
1226 else if (firstarg)
1227 outfile_prefix = firstarg;
1228 else
1229 {
1230 fprintf (stderr, "No way to create an output filename\n");
1231 exit (1);
1232 }
1233 }
1234 outfile_prefix = prefix (outfile_prefix);
1235
1236 if (verbose)
1237 fprintf (stderr, "%s: Outfile prefix is %s\n",
1238 program_name, outfile_prefix);
1239 mangle_defs ();
1240
1241 gen_exp_file ();
1242
1243
1244 gen_lib_file ();
1245
1246 return 0;
1247 }
This page took 0.058413 seconds and 5 git commands to generate.