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