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