* nm.c (HAVE_SBRK): Define execpt on amigados and WINDOWS_NT.
[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
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> ]
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"
175int yydebug;
176char *def_file;
177char *program_name;
178char *strrchr ();
179char *outfile_prefix;
180char *xmalloc ();
181char *strdup ();
182
183static int machine;
6f2d3212 184int suckunderscore;
00289839 185int killat;
6f2d3212
SC
186static int verbose;
187FILE *base_file;
765e60a9 188#ifdef DLLTOOL_ARM
6f2d3212 189static char *mname = "arm";
765e60a9
SC
190#endif
191
192#ifdef DLLTOOL_I386
6f2d3212 193static char *mname = "i386";
765e60a9 194#endif
6f2d3212 195#define PATHMAX 250 /* What's the right name for this ? */
765e60a9 196
6f2d3212 197char outfile[PATHMAX];
765e60a9 198struct mac
6f2d3212
SC
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 }
210mtable[]
211=
765e60a9 212{
6f2d3212
SC
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};
765e60a9
SC
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
6f2d3212 233
765e60a9
SC
234static char **oav;
235
236int i;
237
238FILE *yyin; /* communications with flex */
239extern int linenumber;
240void
241process_def_file (name)
242 char *name;
243{
244 FILE *f = fopen (name, "r");
245 if (!f)
246 {
6f2d3212 247 fprintf (stderr, "%s: Can't open def file %s\n", program_name, name);
765e60a9
SC
248 exit (1);
249 }
250
251 yyin = f;
252
253 yyparse ();
254}
255
256/**********************************************************************/
257
258/* Communications with the parser */
259
260
261typedef struct dlist
262{
263 char *text;
264 struct dlist *next;
6f2d3212
SC
265}
266dlist_type;
765e60a9
SC
267
268typedef struct export
6f2d3212
SC
269 {
270 char *name;
271 char *internal_name;
272 int ordinal;
273 int constant;
274 int noname;
275 struct export *next;
276 }
765e60a9
SC
277export_type;
278
279static char *d_name; /* Arg to NAME or LIBRARY */
280static int d_nfuncs; /* Number of functions exported */
281static int d_ord; /* Base ordinal index */
282static export_type *d_exports; /*list of exported functions */
283static char *d_suffix = "dll";
6f2d3212
SC
284static dlist_type *d_list; /* Descriptions */
285static dlist_type *a_list; /* Stuff to go in directives */
765e60a9
SC
286
287static int d_is_dll;
288static int d_is_exe;
289
290yyerror ()
291{
6f2d3212
SC
292 fprintf (stderr, "%s: Syntax error in def file %s:%d\n",
293 program_name, def_file, linenumber);
765e60a9
SC
294}
295
296void
b990c244 297def_exports (name, internal_name, ordinal, noname, constant)
765e60a9 298 char *name;
b990c244 299 char *internal_name;
765e60a9
SC
300 int ordinal;
301 int noname;
302 int constant;
303{
304 struct export *p = (struct export *) xmalloc (sizeof (*p));
305
306 p->name = name;
b990c244 307 p->internal_name = internal_name ? internal_name : name;
765e60a9
SC
308 p->ordinal = ordinal;
309 p->constant = constant;
310 p->noname = noname;
311 p->next = d_exports;
312 d_exports = p;
313 d_nfuncs++;
765e60a9
SC
314}
315
6f2d3212 316
765e60a9
SC
317void
318def_name (name, base)
319 char *name;
320 int base;
321{
6f2d3212
SC
322 if (verbose)
323 fprintf (stderr, "%s NAME %s base %x\n", program_name, name, base);
765e60a9
SC
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
334void
335def_library (name, base)
336 char *name;
337 int base;
338{
6f2d3212
SC
339 if (verbose)
340 printf ("%s: LIBRARY %s base %x\n", program_name, name, base);
765e60a9
SC
341 if (d_is_exe)
342 {
6f2d3212 343 fprintf (stderr, "%s: Can't have LIBRARY and NAME\n", program_name);
765e60a9
SC
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
351void
352def_description (desc)
353 char *desc;
354{
6f2d3212 355 dlist_type *d = (dlist_type *) xmalloc (sizeof (dlist_type));
765e60a9
SC
356 d->text = strdup (desc);
357 d->next = d_list;
358 d_list = d;
359}
360
6f2d3212
SC
361void
362new_directive (dir)
363 char *dir;
765e60a9 364{
6f2d3212 365 dlist_type *d = (dlist_type *) xmalloc (sizeof (dlist_type));
765e60a9
SC
366 d->text = strdup (dir);
367 d->next = a_list;
368 a_list = d;
369}
370
371void
372def_stacksize (reserve, commit)
373 int reserve;
374 int commit;
375{
376 char b[200];
6f2d3212
SC
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));
765e60a9
SC
382}
383
384void
385def_heapsize (reserve, commit)
386 int reserve;
387 int commit;
388{
389 char b[200];
6f2d3212
SC
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));
765e60a9
SC
395}
396
397
398void
399def_import (internal, module, entry)
400 char *internal;
401 char *module;
402 char *entry;
403{
6f2d3212
SC
404 if (verbose)
405 fprintf (stderr, "%s: IMPORTS are ignored", program_name);
765e60a9
SC
406}
407
408void
409def_version (major, minor)
410{
411 printf ("VERSION %d.%d\n", major, minor);
412}
413
414
415void
416def_section (name, attr)
417 char *name;
418 int attr;
419{
420 char buf[200];
6f2d3212 421 char atts[5];
765e60a9
SC
422 char *d = atts;
423 if (attr & 1)
6f2d3212 424 *d++ = 'R';
765e60a9
SC
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);
6f2d3212 434 new_directive (strdup (buf));
765e60a9
SC
435}
436void
437def_code (attr)
438 int attr;
439{
440
6f2d3212 441 def_section ("CODE", attr);
765e60a9
SC
442}
443
444void
445def_data (attr)
446 int attr;
447{
6f2d3212 448 def_section ("DATA", attr);
765e60a9
SC
449}
450
451
452/**********************************************************************/
453
6f2d3212
SC
454/* read in and block out the base relocations */
455static void
456basenames (abfd)
457 bfd *abfd;
458{
459
460
461
462
463}
464
765e60a9
SC
465void
466scan_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);
6f2d3212
SC
478 if (verbose)
479 fprintf (stderr, "%s: Sucking in info from %s\n",
480 program_name,
481 bfd_get_filename (abfd));
765e60a9
SC
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 }
6f2d3212
SC
507
508 basenames (abfd);
509
510 if (verbose)
511 fprintf (stderr, "%s: Done readin\n",
512 program_name);
513
765e60a9
SC
514}
515
516
517void
518scan_obj_file (filename)
519 char *filename;
520{
521 bfd *f = bfd_openr (filename, 0);
522
523 if (!f)
524 {
6f2d3212
SC
525 fprintf (stderr, "%s: Unable to open object file %s\n",
526 program_name,
527 filename);
765e60a9
SC
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
555static
556char *
557prefix (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
567void
568dump_def_info (f)
6f2d3212 569 FILE *f;
765e60a9
SC
570{
571 int i;
572 export_type *exp;
6f2d3212
SC
573 fprintf (f, "%s ", ASM_C);
574 for (i = 0; oav[i]; i++)
575 fprintf (f, "%s ", oav[i]);
576 fprintf (f, "\n");
765e60a9
SC
577 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
578 {
b990c244 579 fprintf (f, "%s %d = %s %s @ %d %s%s\n",
765e60a9
SC
580 ASM_C,
581 i,
6f2d3212
SC
582 exp->name,
583 exp->internal_name,
b990c244 584 exp->ordinal,
765e60a9
SC
585 exp->noname ? "NONAME " : "",
586 exp->constant ? "CONSTANT" : "");
587 }
588}
589/* Generate the .exp file */
590
6f2d3212
SC
591int
592sfunc (a, b)
593 long *a;
594 long *b;
595{
596 return *a - *b;
597}
598
599static void
600flush_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
765e60a9
SC
626
627void
628gen_exp_file ()
629{
630 FILE *f;
765e60a9
SC
631 int i;
632 export_type *exp;
633 dlist_type *dl;
6f2d3212
SC
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);
765e60a9
SC
641
642 f = fopen (outfile, "w");
643 if (!f)
644 {
6f2d3212 645 fprintf (stderr, "%s: Unable to open output file %s\n", program_name, outfile);
765e60a9
SC
646 exit (1);
647 }
6f2d3212
SC
648 if (verbose)
649 {
650 fprintf (stderr, "%s: Opened file %s\n",
651 program_name, outfile);
652 }
653
765e60a9
SC
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 {
6f2d3212
SC
677#if 0
678 /* This seems necessary in the doc, but in real
679 life it's not used.. */
765e60a9
SC
680 if (exp->ordinal != i)
681 {
6f2d3212 682 fprintf (f, "%s\t%s\t%d\t@ %d..%d missing\n", ASM_C, ASM_SPACE,
765e60a9
SC
683 (exp->ordinal - i) * 4,
684 i, exp->ordinal - 1);
685 i = exp->ordinal;
686 }
6f2d3212 687#endif
b990c244 688 fprintf (f, "\t%s %s\t%s %d\n", ASM_LONG, exp->internal_name, ASM_C, exp->ordinal);
765e60a9
SC
689 i++;
690 }
691
692
693 fprintf (f, "anames:\n");
694 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
6f2d3212
SC
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 }
765e60a9
SC
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
6f2d3212
SC
717 if (had_noname)
718 fprintf (f, "nNoname: %s \"__noname__\"\n", ASM_TEXT);
765e60a9
SC
719
720 if (a_list)
721 {
6f2d3212 722 fprintf (f, "\t.section .drectve\n");
765e60a9
SC
723 for (dl = a_list; dl; dl = dl->next)
724 {
6f2d3212 725 fprintf (f, "\t%s\t\"%s\"\n", ASM_TEXT, dl->text);
765e60a9
SC
726 }
727 }
6f2d3212 728 if (d_list)
765e60a9 729 {
6f2d3212 730 fprintf (f, "\t.section .rdata\n");
765e60a9
SC
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;
6f2d3212
SC
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 }
765e60a9 756 }
6f2d3212
SC
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;
765e60a9 792 }
6f2d3212 793 need[on_page++] = addr;
765e60a9 794 }
6f2d3212 795 flush_page (f, need, page_addr, on_page);
765e60a9 796 }
6f2d3212 797
765e60a9
SC
798 fclose (f);
799}
800
6f2d3212
SC
801static char *
802xlate (char *name)
803{
00289839 804
6f2d3212
SC
805 if (!suckunderscore)
806 return name;
807
808 if (name[0] == '_')
809 name++;
00289839
SC
810 if (killat) {
811 char *p;
812 p = strchr (name, '@');
813 if (p)
814 *p = 0;
815 }
6f2d3212
SC
816 return name;
817}
818
765e60a9
SC
819/**********************************************************************/
820gen_lib_file ()
821{
765e60a9
SC
822 int i;
823 FILE *f;
824 export_type *exp;
825
6f2d3212 826 sprintf (outfile, "%s-lib.s", outfile_prefix);
765e60a9
SC
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);
6f2d3212 842 fprintf (f, "\t%s\t__imp_%s\n", ASM_GLOBAL, exp->name);
765e60a9
SC
843 }
844
845 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
846 {
6f2d3212 847 fprintf (f, "%s:\t%s\t__imp_%s\n", exp->name, ASM_JUMP, exp->name);
765e60a9
SC
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
6f2d3212
SC
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
765e60a9
SC
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 {
6f2d3212 877 fprintf (f, "__imp_%s:\n", exp->name);
765e60a9
SC
878 fprintf (f, "\t%s\tID%d\n", ASM_LONG, i);
879 }
6f2d3212 880 fprintf (f, "\t%s\t0\n", ASM_LONG);
765e60a9
SC
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
6f2d3212 890 fprintf (f, "\t%s\t0\n", ASM_LONG);
765e60a9
SC
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);
6f2d3212 897 fprintf (f, "\t%s\t\"%s\"\n", ASM_TEXT, xlate (exp->name));
765e60a9 898 }
6f2d3212 899 fprintf (f, "\t%s\t0\n", ASM_LONG);
765e60a9
SC
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 */
907int
908pfunc (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
926int
927nfunc (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
937static
938void
939remove_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
955static void
956dtab (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
976static void
977process_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;
6f2d3212
SC
999 if (verbose)
1000 fprintf (stderr, "Warning, ignoring duplicate EXPORT %s %d,%d\n",
1001 a->name,
1002 a->ordinal,
1003 b->ordinal);
765e60a9
SC
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
1026static void
1027fill_ordinals (d_export_vec)
1028 export_type **d_export_vec;
1029{
1030 int lowest = 0;
6f2d3212
SC
1031 int unset = 0;
1032 char *ptr;
765e60a9
SC
1033 qsort (d_export_vec, d_nfuncs, sizeof (export_type *), pfunc);
1034
6f2d3212
SC
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 */
765e60a9
SC
1042 for (i = 0; i < d_nfuncs; i++)
1043 {
6f2d3212 1044 if (d_export_vec[i]->ordinal != -1)
765e60a9 1045 {
6f2d3212
SC
1046 ptr[d_export_vec[i]->ordinal] = 1;
1047 if (lowest == 0)
1048 lowest = d_export_vec[i]->ordinal;
765e60a9 1049 }
6f2d3212
SC
1050 }
1051
1052 for (i = 0; i < d_nfuncs; i++)
1053 {
1054 if (d_export_vec[i]->ordinal == -1)
765e60a9 1055 {
6f2d3212
SC
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
765e60a9
SC
1074 }
1075 }
1076
6f2d3212
SC
1077 free (ptr);
1078
1079 /* And resort */
1080
1081 qsort (d_export_vec, d_nfuncs, sizeof (export_type *), pfunc);
1082
765e60a9
SC
1083 /* Work out the lowest ordinal number */
1084 if (d_export_vec[0])
1085 d_ord = d_export_vec[0]->ordinal;
1086}
1087void
1088mangle_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
1118void
1119usage (file, status)
1120 FILE *file;
1121 int status;
1122{
6f2d3212
SC
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");
00289839
SC
1132 fprintf (file, "\t -u Remove leading underscore from .lib\n");
1133 fprintf (file, "\t -k Kill @<n> from exported names\n");
765e60a9
SC
1134 exit (status);
1135}
1136
1137static struct option long_options[] =
1138{
1139 {"def", required_argument, NULL, 'd'},
6f2d3212 1140 {"underscore", no_argument, NULL, 'u'},
00289839 1141 {"killat", no_argument, NULL, 'k'},
765e60a9
SC
1142 {"help", no_argument, NULL, 'h'},
1143 {"machine", required_argument, NULL, 'm'},
6f2d3212 1144 {"base-file", required_argument, NULL, 'b'},
765e60a9
SC
1145 0
1146};
1147
1148int
1149main (ac, av)
1150 int ac;
1151 char **av;
1152{
1153 int c;
1154 char *firstarg = 0;
1155 program_name = av[0];
1156 oav = av;
6f2d3212 1157
00289839 1158 while ((c = getopt_long (ac, av, "kvbuh?m:o:Dd:", long_options, 0)) != EOF)
765e60a9
SC
1159 {
1160 switch (c)
1161 {
1162 case 'h':
1163 case '?':
6f2d3212 1164 usage (stderr, 0);
765e60a9
SC
1165 break;
1166 case 'm':
1167 mname = optarg;
1168 break;
1169 case 'o':
1170 outfile_prefix = optarg;
1171 break;
6f2d3212
SC
1172 case 'v':
1173 verbose = 1;
1174 break;
765e60a9
SC
1175 case 'D':
1176 yydebug = 1;
1177 break;
6f2d3212
SC
1178 case 'u':
1179 suckunderscore = 1;
1180 break;
00289839
SC
1181 case 'k':
1182 killat = 1;
1183 break;
765e60a9
SC
1184 case 'd':
1185 def_file = optarg;
1186 break;
6f2d3212
SC
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;
765e60a9
SC
1197 default:
1198 usage (stderr, 1);
1199 }
1200 }
1201
1202
6f2d3212 1203 for (i = 0; mtable[i].type; i++)
765e60a9
SC
1204 {
1205 if (strcmp (mtable[i].type, mname) == 0)
1206 break;
1207 }
1208
6f2d3212 1209 if (!mtable[i].type)
765e60a9 1210 {
6f2d3212
SC
1211 fprintf (stderr, "Machine not supported\n");
1212 exit (1);
765e60a9
SC
1213 }
1214 machine = i;
1215
1216
1217 if (def_file)
1218 {
765e60a9
SC
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
6f2d3212
SC
1245 if (verbose)
1246 fprintf (stderr, "%s: Outfile prefix is %s\n",
1247 program_name, outfile_prefix);
765e60a9 1248 mangle_defs ();
6f2d3212 1249
765e60a9 1250 gen_exp_file ();
6f2d3212
SC
1251
1252
765e60a9 1253 gen_lib_file ();
6f2d3212 1254
765e60a9
SC
1255 return 0;
1256}
This page took 0.075863 seconds and 4 git commands to generate.