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