23f98cc5f58de62790a08ecfae11b19486e43bc5
[deliverable/binutils-gdb.git] / binutils / dlltool.c
1 #define show_allnames 0
2
3 /* dlltool.c -- tool to generate stuff for PE style DLLs
4 Copyright (C) 1995 Free Software Foundation, Inc.
5
6 This file is part of GNU Binutils.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
21
22
23 /*
24 This program allows you to build the files necessary to create
25 DLLs to run on a system which understands PE format image files.
26 (eg, Windows NT)
27
28 A DLL contains an export table which contains the information
29 which the runtime loader needs to tie up references from a
30 referencing program.
31
32 The export table is generated by this program by reading
33 in a .DEF file or scanning the .a and .o files which will be in the
34 DLL. A .o file can contain information in special ".drectve" sections
35 with export information.
36
37 A DEF file contains any number of the following commands:
38
39
40 NAME <name> [ , <base> ]
41 The result is going to be <name>.EXE
42
43 LIBRARY <name> [ , <base> ]
44 The result is going to be <name>.DLL
45
46 EXPORTS ( <name1> [ = <name2> ] [ @ <integer> ] [ NONAME ] [CONSTANT] ) *
47 Declares name1 as an exported symbol from the
48 DLL, with optional ordinal number <integer>
49
50 IMPORTS ( [ <name> = ] <name> . <name> ) *
51 Ignored for compatibility
52
53 DESCRIPTION <string>
54 Puts <string> into output .exp file in the .rdata section
55
56 [STACKSIZE|HEAPSIZE] <number-reserve> [ , <number-commit> ]
57 Generates --stack|--heap <number-reserve>,<number-commit>
58 in the output .drectve section. The linker will
59 see this and act upon it.
60
61 [CODE|DATA] <attr>+
62 SECTIONS ( <sectionname> <attr>+ )*
63 <attr> = READ | WRITE | EXECUTE | SHARED
64 Generates --attr <sectionname> <attr> in the output
65 .drectve section. The linker will see this and act
66 upon it.
67
68
69 A -export:<name> in a .drectve section in an input .o or .a
70 file to this program is equivalent to a EXPORTS <name>
71 in a .DEF file.
72
73
74
75 The program generates output files with the prefix supplied
76 on the command line, or in the def file, or taken from the first
77 supplied argument.
78
79 The .exp.s file contains the information necessary to export
80 the routines in the DLL. The .lib.s file contains the information
81 necessary to use the DLL's routines from a referencing program.
82
83
84
85 Example:
86
87 file1.c:
88 asm (".section .drectve");
89 asm (".ascii \"-export:adef\"");
90
91 adef(char *s)
92 {
93 printf("hello from the dll %s\n",s);
94 }
95
96 bdef(char *s)
97 {
98 printf("hello from the dll and the other entry point %s\n",s);
99 }
100
101 file2.c:
102 asm (".section .drectve");
103 asm (".ascii \"-export:cdef\"");
104 asm (".ascii \"-export:ddef\"");
105 cdef(char *s)
106 {
107 printf("hello from the dll %s\n",s);
108 }
109
110 ddef(char *s)
111 {
112 printf("hello from the dll and the other entry point %s\n",s);
113 }
114
115 printf()
116 {
117 return 9;
118 }
119
120 main.c
121
122 main()
123 {
124 cdef();
125 }
126
127 thedll.def
128
129 LIBRARY thedll
130 HEAPSIZE 0x40000, 0x2000
131 EXPORTS bdef @ 20
132 cdef @ 30 NONAME
133
134 SECTIONS donkey READ WRITE
135 aardvark EXECUTE
136
137
138 # compile up the parts of the dll
139
140 gcc -c file1.c
141 gcc -c file2.c
142
143 # put them in a library (you don't have to, you
144 # could name all the .os on the dlltool line)
145
146 ar qcv thedll.in file1.o file2.o
147 ranlib thedll.in
148
149 # run this tool over the library and the def file
150 ./dlltool --def thedll.def --output-exp thedll.o --output-lib thedll.a
151
152 # build the dll with the library with file1.o, file2.o and the export table
153 ld -o thedll.dll thedll.o thedll.in
154
155 # build the mainline
156 gcc -c themain.c
157
158 # link the executable with the import library
159 ld -e main -Tthemain.ld -o themain.exe themain.o thedll.a
160
161 */
162
163 #define PAGE_SIZE 4096
164 #define PAGE_MASK (-PAGE_SIZE)
165 #include "bfd.h"
166 #include "libiberty.h"
167 #include "bucomm.h"
168 #include "getopt.h"
169 #include <sys/types.h>
170 #include "demangle.h"
171 #include <ctype.h>
172 #ifdef HAVE_SYS_WAIT_H
173 #include <sys/wait.h>
174 #else
175 #ifndef WIFEXITED
176 #define WIFEXITED(w) (((w)&0377) == 0)
177 #endif
178 #ifndef WIFSIGNALED
179 #define WIFSIGNALED(w) (((w)&0377) != 0177 && ((w)&~0377) == 0)
180 #endif
181 #ifndef WTERMSIG
182 #define WTERMSIG(w) ((w) & 0177)
183 #endif
184 #ifndef WEXITSTATUS
185 #define WEXITSTATUS(w) (((w) >> 8) & 0377)
186 #endif
187 #endif
188
189
190
191 char *as_name = "as";
192
193 static int no_idata4;
194 static int no_idata5;
195 static char *exp_name;
196 static char *imp_name;
197 static char *head_label;
198 static char *imp_name_lab;
199 static char *dll_name;
200
201 static int add_indirect = 0;
202 static int add_underscore = 0;
203 static int dontdeltemps = 0;
204
205 int yyparse();
206 int yydebug;
207 static char *def_file;
208
209 static char *program_name;
210 char *strrchr ();
211 char *strdup ();
212
213 static int machine;
214 int killat;
215 static int verbose;
216 FILE *output_def;
217 FILE *base_file;
218 #ifdef DLLTOOL_ARM
219 static char *mname = "arm";
220 #endif
221
222 #ifdef DLLTOOL_I386
223 static char *mname = "i386";
224 #endif
225 #define PATHMAX 250 /* What's the right name for this ? */
226
227 /* This bit of assemly does jmp * ....
228 s set how_jtab_roff to mark where the 32bit abs branch should go */
229 unsigned char i386_jtab[] = { 0xff, 0x25, 0x00, 0x00, 0x00, 0x00, 0x90, 0x90};
230
231
232 unsigned char arm_jtab[] = { 0x00, 0xc0, 0x9f, 0xe5,
233 0x00, 0xf0, 0x9c, 0xe5,
234 0, 0, 0, 0};
235 char outfile[PATHMAX];
236 struct mac
237 {
238 char *type;
239 char *how_byte;
240 char *how_short;
241 char *how_long;
242 char *how_asciz;
243 char *how_comment;
244 char *how_jump;
245 char *how_global;
246 char *how_space;
247 char *how_align_short;
248 char *how_align_long;
249 char *how_bfd_target;
250 enum bfd_architecture how_bfd_arch;
251 unsigned char *how_jtab;
252 int how_jtab_size; /* size of the jtab entry */
253 int how_jtab_roff; /* offset into it for the ind 32 reloc into idata 5 */
254 }
255 mtable[]
256 =
257 {
258 {
259 #define MARM 0
260 "arm", ".byte", ".short", ".long", ".asciz", "@",
261 "ldr\tip,[pc]\n\tldr\tpc,[ip]\n\t.long",
262 ".global", ".space", ".align\t2",".align\t4","pe-arm-little", bfd_arch_arm,
263 arm_jtab, sizeof(arm_jtab),8
264 }
265 ,
266 {
267 #define M386 1
268 "i386", ".byte", ".short", ".long", ".asciz", "#", "jmp *", ".global", ".space", ".align\t2",".align\t4","pe-i386",bfd_arch_i386,
269 i386_jtab,sizeof(i386_jtab),2,
270 }
271 ,
272 { 0}
273 };
274
275
276 char *
277 rvaafter (machine)
278 int machine;
279 {
280 switch (machine)
281 {
282 case MARM:
283 return "";
284 case M386:
285 return "";
286 }
287 return "";
288 }
289
290 char *
291 rvabefore (machine)
292 int machine;
293 {
294 switch (machine)
295 {
296 case MARM:
297 return ".rva\t";
298 case M386:
299 return ".rva\t";
300 }
301 return "";
302 }
303
304 char *
305 asm_prefix (machine)
306 int machine;
307 {
308 switch (machine)
309 {
310 case MARM:
311 return "";
312 case M386:
313 return "_";
314 }
315 return "";
316 }
317 #define ASM_BYTE mtable[machine].how_byte
318 #define ASM_SHORT mtable[machine].how_short
319 #define ASM_LONG mtable[machine].how_long
320 #define ASM_TEXT mtable[machine].how_asciz
321 #define ASM_C mtable[machine].how_comment
322 #define ASM_JUMP mtable[machine].how_jump
323 #define ASM_GLOBAL mtable[machine].how_global
324 #define ASM_SPACE mtable[machine].how_space
325 #define ASM_ALIGN_SHORT mtable[machine].how_align_short
326 #define ASM_RVA_BEFORE rvabefore(machine)
327 #define ASM_RVA_AFTER rvaafter(machine)
328 #define ASM_PREFIX asm_prefix(machine)
329 #define ASM_ALIGN_LONG mtable[machine].how_align_long
330 #define HOW_BFD_TARGET 0 /* always default*/
331 #define HOW_BFD_ARCH mtable[machine].how_bfd_arch
332 #define HOW_JTAB mtable[machine].how_jtab
333 #define HOW_JTAB_SIZE mtable[machine].how_jtab_size
334 #define HOW_JTAB_ROFF mtable[machine].how_jtab_roff
335 static char **oav;
336
337
338 FILE *yyin; /* communications with flex */
339 extern int linenumber;
340 void
341 process_def_file (name)
342 char *name;
343 {
344 FILE *f = fopen (name, "r");
345 if (!f)
346 {
347 fprintf (stderr, "%s: Can't open def file %s\n", program_name, name);
348 exit (1);
349 }
350
351 yyin = f;
352
353 yyparse ();
354 }
355
356 /**********************************************************************/
357
358 /* Communications with the parser */
359
360
361 typedef struct dlist
362 {
363 char *text;
364 struct dlist *next;
365 }
366 dlist_type;
367
368 typedef struct export
369 {
370 char *name;
371 char *internal_name;
372 int ordinal;
373 int constant;
374 int noname;
375 int hint;
376 struct export *next;
377 }
378 export_type;
379
380 static char *d_name; /* Arg to NAME or LIBRARY */
381 static int d_nfuncs; /* Number of functions exported */
382 static int d_named_nfuncs; /* Number of named functions exported */
383 static int d_low_ord; /* Lowest ordinal index */
384 static int d_high_ord; /* Highest ordinal index */
385 static export_type *d_exports; /*list of exported functions */
386 static export_type **d_exports_lexically; /* vector of exported functions in alpha order */
387 static dlist_type *d_list; /* Descriptions */
388 static dlist_type *a_list; /* Stuff to go in directives */
389
390 static int d_is_dll;
391 static int d_is_exe;
392
393 int
394 yyerror ()
395 {
396 fprintf (stderr, "%s: Syntax error in def file %s:%d\n",
397 program_name, def_file, linenumber);
398 return 0;
399 }
400
401 void
402 def_exports (name, internal_name, ordinal, noname, constant)
403 char *name;
404 char *internal_name;
405 int ordinal;
406 int noname;
407 int constant;
408 {
409 struct export *p = (struct export *) xmalloc (sizeof (*p));
410
411 p->name = name;
412 p->internal_name = internal_name ? internal_name : name;
413 p->ordinal = ordinal;
414 p->constant = constant;
415 p->noname = noname;
416 p->next = d_exports;
417 d_exports = p;
418 d_nfuncs++;
419 }
420
421
422 void
423 def_name (name, base)
424 char *name;
425 int base;
426 {
427 if (verbose)
428 fprintf (stderr, "%s NAME %s base %x\n", program_name, name, base);
429 if (d_is_dll)
430 {
431 fprintf (stderr, "Can't have LIBRARY and NAME\n");
432 }
433 d_name = name;
434 d_is_exe = 1;
435 }
436
437 void
438 def_library (name, base)
439 char *name;
440 int base;
441 {
442 if (verbose)
443 printf ("%s: LIBRARY %s base %x\n", program_name, name, base);
444 if (d_is_exe)
445 {
446 fprintf (stderr, "%s: Can't have LIBRARY and NAME\n", program_name);
447 }
448 d_name = name;
449 d_is_dll = 1;
450 }
451
452 void
453 def_description (desc)
454 char *desc;
455 {
456 dlist_type *d = (dlist_type *) xmalloc (sizeof (dlist_type));
457 d->text = strdup (desc);
458 d->next = d_list;
459 d_list = d;
460 }
461
462 void
463 new_directive (dir)
464 char *dir;
465 {
466 dlist_type *d = (dlist_type *) xmalloc (sizeof (dlist_type));
467 d->text = strdup (dir);
468 d->next = a_list;
469 a_list = d;
470 }
471
472 void
473 def_stacksize (reserve, commit)
474 int reserve;
475 int commit;
476 {
477 char b[200];
478 if (commit > 0)
479 sprintf (b, "-stack 0x%x,0x%x ", reserve, commit);
480 else
481 sprintf (b, "-stack 0x%x ", reserve);
482 new_directive (strdup (b));
483 }
484
485 void
486 def_heapsize (reserve, commit)
487 int reserve;
488 int commit;
489 {
490 char b[200];
491 if (commit > 0)
492 sprintf (b, "-heap 0x%x,0x%x ", reserve, commit);
493 else
494 sprintf (b, "-heap 0x%x ", reserve);
495 new_directive (strdup (b));
496 }
497
498
499 void
500 def_import (internal, module, entry)
501 char *internal;
502 char *module;
503 char *entry;
504 {
505 if (verbose)
506 fprintf (stderr, "%s: IMPORTS are ignored", program_name);
507 }
508
509 void
510 def_version (major, minor)
511 int major;
512 int minor;
513 {
514 printf ("VERSION %d.%d\n", major, minor);
515 }
516
517
518 void
519 def_section (name, attr)
520 char *name;
521 int attr;
522 {
523 char buf[200];
524 char atts[5];
525 char *d = atts;
526 if (attr & 1)
527 *d++ = 'R';
528
529 if (attr & 2)
530 *d++ = 'W';
531 if (attr & 4)
532 *d++ = 'X';
533 if (attr & 8)
534 *d++ = 'S';
535 *d++ = 0;
536 sprintf (buf, "-attr %s %s", name, atts);
537 new_directive (strdup (buf));
538 }
539 void
540 def_code (attr)
541 int attr;
542 {
543
544 def_section ("CODE", attr);
545 }
546
547 void
548 def_data (attr)
549 int attr;
550 {
551 def_section ("DATA", attr);
552 }
553
554
555 /**********************************************************************/
556
557 void
558 run (what, args)
559 char *what;
560 char *args;
561 {
562 char *s;
563 int pid;
564 int i;
565 char **argv;
566 extern char **environ;
567 if (verbose)
568 fprintf (stderr, "%s %s\n", what, args);
569
570 /* Count the args */
571 i = 0;
572 for (s = args; *s; s++)
573 if (*s == ' ')
574 i++;
575 i++;
576 argv = alloca (sizeof (char *) * (i + 3));
577 i = 0;
578 argv[i++] = what;
579 s = args;
580 while (1)
581 {
582 argv[i++] = s;
583 while (*s != ' ' && *s != 0)
584 s++;
585 if (*s == 0)
586 break;
587 *s++ = 0;
588 }
589 argv[i++] = 0;
590
591
592 pid = vfork ();
593
594 if (pid == 0)
595 {
596 execvp (what, argv);
597 fprintf (stderr, "%s: can't exec %s\n", program_name, what);
598 exit (1);
599 }
600 else if (pid == -1)
601 {
602 extern int errno;
603 fprintf (stderr, "%s: vfork failed, %d\n", program_name, errno);
604 exit (1);
605 }
606 else
607 {
608 int status;
609 waitpid (pid, &status, 0);
610 if (status)
611 {
612 if (WIFSIGNALED (status))
613 {
614 fprintf (stderr, "%s: %s %s terminated with signal %d\n",
615 program_name, what, args, WTERMSIG (status));
616 exit (1);
617 }
618
619 if (WIFEXITED (status))
620 {
621 fprintf (stderr, "%s: %s %s terminated with exit status %d\n",
622 program_name, what, args, WEXITSTATUS (status));
623 exit (1);
624 }
625 }
626 }
627 }
628
629 /* read in and block out the base relocations */
630 static void
631 basenames (abfd)
632 bfd *abfd;
633 {
634
635
636
637
638 }
639
640 void
641 scan_open_obj_file (abfd)
642 bfd *abfd;
643 {
644 /* Look for .drectve's */
645 asection *s = bfd_get_section_by_name (abfd, ".drectve");
646 if (s)
647 {
648 int size = bfd_get_section_size_before_reloc (s);
649 char *buf = xmalloc (size);
650 char *p;
651 char *e;
652 bfd_get_section_contents (abfd, s, buf, 0, size);
653 if (verbose)
654 fprintf (stderr, "%s: Sucking in info from %s\n",
655 program_name,
656 bfd_get_filename (abfd));
657
658 /* Search for -export: strings */
659 p = buf;
660 e = buf + size;
661 while (p < e)
662 {
663 if (p[0] == '-'
664 && strncmp (p, "-export:", 8) == 0)
665 {
666 char *name;
667 char *c;
668 p += 8;
669 name = p;
670 while (*p != ' ' && *p != '-' && p < e)
671 p++;
672 c = xmalloc (p - name + 1);
673 memcpy (c, name, p - name);
674 c[p - name] = 0;
675 def_exports (c, 0, -1, 0);
676 }
677 else
678 p++;
679 }
680 free (buf);
681 }
682
683 basenames (abfd);
684
685 if (verbose)
686 fprintf (stderr, "%s: Done readin\n",
687 program_name);
688
689 }
690
691
692 void
693 scan_obj_file (filename)
694 char *filename;
695 {
696 bfd *f = bfd_openr (filename, 0);
697
698 if (!f)
699 {
700 fprintf (stderr, "%s: Unable to open object file %s\n",
701 program_name,
702 filename);
703 exit (1);
704 }
705 if (bfd_check_format (f, bfd_archive))
706 {
707 bfd *arfile = bfd_openr_next_archived_file (f, 0);
708 while (arfile)
709 {
710 if (bfd_check_format (arfile, bfd_object))
711 scan_open_obj_file (arfile);
712 bfd_close (arfile);
713 arfile = bfd_openr_next_archived_file (f, arfile);
714 }
715 }
716 else if (bfd_check_format (f, bfd_object))
717 {
718 scan_open_obj_file (f);
719 }
720
721 bfd_close (f);
722 }
723
724 /**********************************************************************/
725
726
727
728 void
729 dump_def_info (f)
730 FILE *f;
731 {
732 int i;
733 export_type *exp;
734 fprintf (f, "%s ", ASM_C);
735 for (i = 0; oav[i]; i++)
736 fprintf (f, "%s ", oav[i]);
737 fprintf (f, "\n");
738 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
739 {
740 fprintf (f, "%s %d = %s %s @ %d %s%s\n",
741 ASM_C,
742 i,
743 exp->name,
744 exp->internal_name,
745 exp->ordinal,
746 exp->noname ? "NONAME " : "",
747 exp->constant ? "CONSTANT" : "");
748 }
749 }
750 /* Generate the .exp file */
751
752 int
753 sfunc (a, b)
754 long *a;
755 long *b;
756 {
757 return *a - *b;
758 }
759
760
761
762 static void
763 flush_page (f, need, page_addr, on_page)
764 FILE *f;
765 int *need;
766 int page_addr;
767 int on_page;
768 {
769 int i;
770
771 /* Flush this page */
772 fprintf (f, "\t%s\t0x%08x\t%s Starting RVA for chunk\n",
773 ASM_LONG,
774 page_addr,
775 ASM_C);
776 fprintf (f, "\t%s\t0x%x\t%s Size of block\n",
777 ASM_LONG,
778 (on_page * 2) + (on_page & 1) * 2 + 8,
779 ASM_C);
780 for (i = 0; i < on_page; i++)
781 {
782 fprintf (f, "\t%s\t0x%x\n", ASM_SHORT, (need[i] - page_addr) | 0x3000);
783 }
784 /* And padding */
785 if (on_page & 1)
786 fprintf (f, "\t%s\t0x%x\n", ASM_SHORT, 0 | 0x0000);
787
788 }
789
790
791 void
792 gen_def_file ()
793 {
794 int i;
795 export_type *exp;
796
797 fprintf (output_def, ";");
798 for (i = 0; oav[i]; i++)
799 fprintf (output_def, " %s", oav[i]);
800
801 fprintf (output_def, "\nEXPORTS\n");
802
803 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
804 {
805 char *quote = strchr (exp->name, '.') ? "\"" : "";
806 fprintf (output_def, "\t%s%s%s @ %d%s ; %s\n",
807 quote,
808 exp->name,
809 quote,
810 exp->ordinal,
811 exp->noname ? " NONAME" : "",
812 cplus_demangle (exp->internal_name, DMGL_ANSI | DMGL_PARAMS));
813 }
814 }
815 void
816 gen_exp_file ()
817 {
818 FILE *f;
819 int i;
820 export_type *exp;
821 dlist_type *dl;
822
823
824 sprintf (outfile, "t%s", exp_name);
825
826 if (verbose)
827 fprintf (stderr, "%s: Generate exp file %s\n",
828 program_name, exp_name);
829
830 f = fopen (outfile, "w");
831 if (!f)
832 {
833 fprintf (stderr, "%s: Unable to open output file %s\n", program_name, outfile);
834 exit (1);
835 }
836 if (verbose)
837 {
838 fprintf (stderr, "%s: Opened file %s\n",
839 program_name, outfile);
840 }
841
842 dump_def_info (f);
843 if (d_exports)
844 {
845 fprintf (f, "\t.section .edata\n\n");
846 fprintf (f, "\t%s 0 %s Allways 0\n", ASM_LONG, ASM_C);
847 fprintf (f, "\t%s 0x%x %s Time and date\n", ASM_LONG, time(0),ASM_C);
848 fprintf (f, "\t%s 0 %s Major and Minor version\n", ASM_LONG, ASM_C);
849 fprintf (f, "\t%sname%s %s Ptr to name of dll\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
850 fprintf (f, "\t%s %d %s Starting ordinal of exports\n", ASM_LONG, d_low_ord, ASM_C);
851
852
853 fprintf (f, "\t%s %d %s Number of functions\n", ASM_LONG, d_high_ord - d_low_ord + 1, ASM_C);
854 fprintf(f,"\t%s named funcs %d, low ord %d, high ord %d\n",
855 ASM_C,
856 d_named_nfuncs, d_low_ord, d_high_ord);
857 fprintf (f, "\t%s %d %s Number of names\n", ASM_LONG,
858 show_allnames ? d_high_ord - d_low_ord + 1 : d_named_nfuncs, ASM_C);
859 fprintf (f, "\t%safuncs%s %s Address of functions\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
860
861 fprintf (f, "\t%sanames%s %s Address of Name Pointer Table\n",
862 ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
863
864 fprintf (f, "\t%sanords%s %s Address of ordinals\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
865
866 fprintf (f, "name: %s \"%s\"\n", ASM_TEXT, dll_name);
867
868
869 fprintf(f,"%s Export address Table\n", ASM_C);
870 fprintf(f,"\t%s\n", ASM_ALIGN_LONG);
871 fprintf (f, "afuncs:\n");
872 i = d_low_ord;
873
874 for (exp = d_exports; exp; exp = exp->next)
875 {
876 if (exp->ordinal != i)
877 {
878 #if 0
879 fprintf (f, "\t%s\t%d\t%s %d..%d missing\n",
880 ASM_SPACE,
881 (exp->ordinal - i) * 4,
882 ASM_C,
883 i, exp->ordinal - 1);
884 i = exp->ordinal;
885 #endif
886 while (i < exp->ordinal)
887 {
888 fprintf(f,"\t%s\t0\n", ASM_LONG);
889 i++;
890 }
891 }
892 fprintf (f, "\t%s%s%s%s\t%s %d\n", ASM_RVA_BEFORE,
893 ASM_PREFIX,
894 exp->internal_name, ASM_RVA_AFTER, ASM_C, exp->ordinal);
895 i++;
896 }
897
898 fprintf (f,"%s Export Name Pointer Table\n", ASM_C);
899 fprintf (f, "anames:\n");
900
901 for (i = 0; (exp = d_exports_lexically[i]); i++)
902 {
903 if (!exp->noname || show_allnames)
904 fprintf (f, "\t%sn%d%s\n", ASM_RVA_BEFORE, exp->ordinal, ASM_RVA_AFTER);
905 }
906
907 fprintf (f,"%s Export Oridinal Table\n", ASM_C);
908 fprintf (f, "anords:\n");
909 for (i = 0; (exp = d_exports_lexically[i]); i++)
910 {
911 if (!exp->noname || show_allnames)
912 fprintf (f, "\t%s %d\n", ASM_SHORT, exp->ordinal - d_low_ord);
913 }
914
915 fprintf(f,"%s Export Name Table\n", ASM_C);
916 for (i = 0; (exp = d_exports_lexically[i]); i++)
917 if (!exp->noname || show_allnames)
918 fprintf (f, "n%d: %s \"%s\"\n", exp->ordinal, ASM_TEXT, exp->name);
919
920 if (a_list)
921 {
922 fprintf (f, "\t.section .drectve\n");
923 for (dl = a_list; dl; dl = dl->next)
924 {
925 fprintf (f, "\t%s\t\"%s\"\n", ASM_TEXT, dl->text);
926 }
927 }
928 if (d_list)
929 {
930 fprintf (f, "\t.section .rdata\n");
931 for (dl = d_list; dl; dl = dl->next)
932 {
933 char *p;
934 int l;
935 /* We dont output as ascii 'cause there can
936 be quote characters in the string */
937
938 l = 0;
939 for (p = dl->text; *p; p++)
940 {
941 if (l == 0)
942 fprintf (f, "\t%s\t", ASM_BYTE);
943 else
944 fprintf (f, ",");
945 fprintf (f, "%d", *p);
946 if (p[1] == 0)
947 {
948 fprintf (f, ",0\n");
949 break;
950 }
951 if (++l == 10)
952 {
953 fprintf (f, "\n");
954 l = 0;
955 }
956 }
957 }
958 }
959 }
960
961
962 /* Add to the output file a way of getting to the exported names
963 without using the import library. */
964 if (add_indirect)
965 {
966 fprintf (f, "\t.section\t.rdata\n");
967 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
968 if (!exp->noname || show_allnames)
969 {
970 fprintf (f, "\t%s\t__imp_%s\n", ASM_GLOBAL, exp->name);
971 fprintf (f, "__imp_%s:\n", exp->name);
972 fprintf (f, "\t%s\t%s\n", ASM_LONG, exp->name);
973 }
974 }
975
976 /* Dump the reloc section if a base file is provided */
977 if (base_file)
978 {
979 int addr;
980 long need[PAGE_SIZE];
981 long page_addr;
982 int numbytes;
983 int num_entries;
984 long *copy;
985 int j;
986 int on_page;
987 fprintf (f, "\t.section\t.init\n");
988 fprintf (f, "lab:\n");
989
990 fseek (base_file, 0, SEEK_END);
991 numbytes = ftell (base_file);
992 fseek (base_file, 0, SEEK_SET);
993 copy = malloc (numbytes);
994 fread (copy, 1, numbytes, base_file);
995 num_entries = numbytes / sizeof (long);
996
997
998 fprintf (f, "\t.section\t.reloc\n");
999 if (num_entries)
1000 {
1001
1002 int src;
1003 int dst = 0;
1004 int last = -1;
1005 qsort (copy, num_entries, sizeof (long), sfunc);
1006 /* Delete duplcates */
1007 for (src = 0; src < num_entries; src++)
1008 {
1009 if (last != copy[src])
1010 last = copy[dst++] = copy[src];
1011 }
1012 num_entries = dst;
1013 addr = copy[0];
1014 page_addr = addr & PAGE_MASK; /* work out the page addr */
1015 on_page = 0;
1016 for (j = 0; j < num_entries; j++)
1017 {
1018 addr = copy[j];
1019 if ((addr & PAGE_MASK) != page_addr)
1020 {
1021 flush_page (f, need, page_addr, on_page);
1022 on_page = 0;
1023 page_addr = addr & PAGE_MASK;
1024 }
1025 need[on_page++] = addr;
1026 }
1027 flush_page (f, need, page_addr, on_page);
1028
1029 /* fprintf (f, "\t%s\t0,0\t%s End\n", ASM_LONG, ASM_C);*/
1030 }
1031 }
1032
1033 fclose (f);
1034
1035 /* assemble the file */
1036 sprintf (outfile, "-o %s t%s", exp_name, exp_name);
1037 run (as_name, outfile);
1038 if (dontdeltemps == 0)
1039 {
1040 sprintf (outfile, "t%s", exp_name);
1041 unlink (outfile);
1042 }
1043 }
1044
1045 static char *
1046 xlate (char *name)
1047 {
1048 if (add_underscore)
1049 {
1050 char *copy = malloc (strlen (name) + 2);
1051 copy[0] = '_';
1052 strcpy (copy + 1, name);
1053 name = copy;
1054 }
1055
1056 if (killat)
1057 {
1058 char *p;
1059 p = strchr (name, '@');
1060 if (p)
1061 *p = 0;
1062 }
1063 return name;
1064 }
1065
1066 /**********************************************************************/
1067
1068 static void dump_iat (f, exp)
1069 FILE *f;
1070 export_type *exp;
1071 {
1072 if (exp->noname && !show_allnames )
1073 {
1074 fprintf (f, "\t%s\t0x%08x\n",
1075 ASM_LONG,
1076 exp->ordinal | 0x80000000); /* hint or orindal ?? */
1077 }
1078 else
1079 {
1080 fprintf (f, "\t%sID%d%s\n", ASM_RVA_BEFORE,
1081 exp->ordinal,
1082 ASM_RVA_AFTER);
1083 }
1084 }
1085
1086
1087
1088 typedef struct
1089 {
1090 int id;
1091 const char *name;
1092 int flags;
1093 asection *sec;
1094 asymbol *sym;
1095 asymbol **sympp;
1096 int size;
1097 unsigned char *data;
1098 } sinfo;
1099
1100
1101 #define TEXT 0
1102 #define DATA 1
1103 #define BSS 2
1104 #define IDATA7 3
1105 #define IDATA5 4
1106 #define IDATA4 5
1107 #define IDATA6 6
1108 #define NSECS 7
1109
1110 static sinfo secdata[NSECS] =
1111 {
1112 { TEXT, ".text", SEC_CODE | SEC_HAS_CONTENTS},
1113 { DATA, ".data", SEC_DATA},
1114 { BSS,".bss" },
1115 { IDATA7, ".idata$7",SEC_HAS_CONTENTS},
1116 { IDATA5, ".idata$5", SEC_HAS_CONTENTS},
1117 { IDATA4, ".idata$4", SEC_HAS_CONTENTS},
1118 { IDATA6,".idata$6", SEC_HAS_CONTENTS}
1119
1120
1121 };
1122 /*
1123 This is what we're trying to make
1124
1125 .text
1126 .global _GetFileVersionInfoSizeW@8
1127 .global __imp_GetFileVersionInfoSizeW@8
1128 _GetFileVersionInfoSizeW@8:
1129 jmp * __imp_GetFileVersionInfoSizeW@8
1130 .section .idata$7 # To force loading of head
1131 .long __version_a_head
1132 # Import Address Table
1133 .section .idata$5
1134 __imp_GetFileVersionInfoSizeW@8:
1135 .rva ID2
1136
1137 # Import Lookup Table
1138 .section .idata$4
1139 .rva ID2
1140 # Hint/Name table
1141 .section .idata$6
1142 ID2: .short 2
1143 .asciz "GetFileVersionInfoSizeW"
1144
1145 */
1146
1147 static char *make_label (prefix, name)
1148 const char *prefix;
1149 const char *name;
1150 {
1151 int len = strlen (ASM_PREFIX) + strlen (prefix) + strlen (name);
1152 char *copy = xmalloc (len +1 );
1153 strcpy (copy, ASM_PREFIX);
1154 strcat (copy, prefix);
1155 strcat (copy, name);
1156 return copy;
1157 }
1158 static bfd *
1159 make_one_lib_file (exp, i)
1160 export_type *exp;
1161 int i;
1162 {
1163 if (0)
1164 {
1165 FILE *f;
1166 char *prefix="d";
1167 sprintf (outfile, "%ss%d.s", prefix, i);
1168 f = fopen (outfile, "w");
1169 fprintf (f, "\t.text\n");
1170 fprintf (f, "\t%s\t%s%s\n", ASM_GLOBAL, ASM_PREFIX, exp->name);
1171 fprintf (f, "\t%s\t__imp_%s\n", ASM_GLOBAL, exp->name);
1172 fprintf (f, "%s%s:\n\t%s\t__imp_%s\n", ASM_PREFIX,
1173 exp->name, ASM_JUMP, exp->name);
1174
1175 fprintf (f, "\t.section\t.idata$7\t%s To force loading of head\n", ASM_C);
1176 fprintf (f, "\t%s\t%s\n", ASM_LONG, head_label);
1177
1178
1179 fprintf (f,"%s Import Address Table\n", ASM_C);
1180
1181 fprintf (f, "\t.section .idata$5\n");
1182 fprintf (f, "__imp_%s:\n", exp->name);
1183
1184 dump_iat (f, exp);
1185
1186 fprintf (f, "\n%s Import Lookup Table\n", ASM_C);
1187 fprintf (f, "\t.section .idata$4\n");
1188
1189 dump_iat (f, exp);
1190
1191 if(!exp->noname || show_allnames)
1192 {
1193 fprintf (f, "%s Hint/Name table\n", ASM_C);
1194 fprintf (f, "\t.section .idata$6\n");
1195 fprintf (f, "ID%d:\t%s\t%d\n", exp->ordinal, ASM_SHORT, exp->hint);
1196 fprintf (f, "\t%s\t\"%s\"\n", ASM_TEXT, xlate (exp->name));
1197 }
1198
1199 fclose (f);
1200
1201
1202 sprintf (outfile, "-o %ss%d.o %ss%d.s", prefix, i, prefix, i);
1203
1204 run (as_name, outfile);
1205
1206 }
1207 else
1208 {
1209
1210 bfd *abfd;
1211
1212 asymbol *exp_label;
1213 asymbol *iname;
1214 asymbol *iname_lab;
1215 asymbol **iname_lab_pp;
1216 asymbol *ptrs[NSECS+3+1]; /* one symbol for each section, 2 extra + a null */
1217
1218 char *outname = xmalloc (10);
1219 int oidx = 0;
1220 sprintf (outname, "ds%d.o", i);
1221 abfd = bfd_openw (outname, HOW_BFD_TARGET);
1222 if (!abfd)
1223 {
1224 fprintf (stderr, "%s: bfd_open failed open output file %s\n", program_name, outname);
1225 exit (1);
1226 }
1227
1228 bfd_set_format (abfd, bfd_object);
1229 bfd_set_arch_mach (abfd, HOW_BFD_ARCH, 0);
1230
1231
1232 for (i = 0; i < NSECS; i++)
1233 {
1234 sinfo *si = secdata + i;
1235 if (si->id != i)
1236 abort();
1237 si->sec = bfd_make_section_old_way (abfd, si->name);
1238 bfd_set_section_flags (abfd,
1239 si->sec,
1240 si->flags);
1241 si->sec->output_section = si->sec;
1242 si->sym = bfd_make_empty_symbol(abfd);
1243 si->sym->name = si->sec->name;
1244 si->sym->section = si->sec;
1245 si->sym->flags = BSF_LOCAL;
1246 si->sym->value = 0;
1247 ptrs[oidx] = si->sym;
1248 si->sympp = ptrs + oidx;
1249
1250 oidx++;
1251 }
1252
1253 exp_label = bfd_make_empty_symbol(abfd);
1254 exp_label->name = make_label ("",exp->name);
1255 exp_label->section = secdata[TEXT].sec;
1256 exp_label->flags = BSF_GLOBAL;
1257 exp_label->value = 0;
1258
1259 ptrs[oidx++] = exp_label;
1260
1261 iname = bfd_make_empty_symbol(abfd);
1262
1263 iname->name = make_label ("__imp_", exp->name);
1264
1265 iname->section = secdata[IDATA5].sec;
1266 iname->flags = BSF_GLOBAL;
1267 iname->value = 0;
1268
1269
1270 iname_lab = bfd_make_empty_symbol(abfd);
1271
1272 iname_lab->name = head_label;
1273 iname_lab->section = (asection *)&bfd_und_section;
1274 iname_lab->flags = 0;
1275 iname_lab->value = 0;
1276
1277
1278 ptrs[oidx++] = iname;
1279 iname_lab_pp = ptrs + oidx;
1280 ptrs[oidx++] = iname_lab;
1281 ptrs[oidx] = 0;
1282
1283 for (i = 0; i < NSECS; i++)
1284 {
1285 sinfo *si = secdata + i;
1286 asection *sec = si->sec;
1287 arelent *rel;
1288 arelent **rpp;
1289
1290 switch (i)
1291 {
1292 case TEXT:
1293 si->size = HOW_JTAB_SIZE;
1294 si->data = xmalloc (HOW_JTAB_SIZE);
1295 memcpy (si->data, HOW_JTAB, HOW_JTAB_SIZE);
1296
1297 /* add the reloc into idata$5 */
1298 rel = xmalloc (sizeof (arelent));
1299 rpp = xmalloc (sizeof (arelent *) * 2);
1300 rpp[0] = rel;
1301 rpp[1] = 0;
1302 rel->address = HOW_JTAB_ROFF;
1303 rel->addend = 0;
1304 rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
1305 rel->sym_ptr_ptr = secdata[IDATA5].sympp;
1306 sec->orelocation = rpp;
1307 sec->reloc_count = 1;
1308 break;
1309 case IDATA4:
1310 case IDATA5:
1311 /* An idata$4 or idata$5 is one word long, and has an
1312 rva to idata$6 */
1313
1314
1315 si->data = xmalloc (4);
1316 si->size = 4;
1317
1318 if (exp->noname)
1319 {
1320 si->data[0] = exp->ordinal ;
1321 si->data[1] = exp->ordinal >> 8;
1322 si->data[2] = exp->ordinal >> 16;
1323 si->data[3] = 0x80;
1324 }
1325 else
1326 {
1327 sec->reloc_count = 1;
1328 memset (si->data, 0, si->size);
1329 rel = xmalloc (sizeof (arelent));
1330 rpp = xmalloc (sizeof (arelent *) * 2);
1331 rpp[0] = rel;
1332 rpp[1] = 0;
1333 rel->address = 0;
1334 rel->addend = 0;
1335 rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_RVA);
1336 rel->sym_ptr_ptr = secdata[IDATA6].sympp;
1337 sec->orelocation = rpp;
1338 }
1339
1340 break;
1341
1342 case IDATA6:
1343 if (!exp->noname)
1344 {
1345 int idx = exp->hint + 1;
1346 si->size = strlen (xlate (exp->name)) + 3;
1347 si->data = xmalloc (si->size);
1348 si->data[0] = idx & 0xff;
1349 si->data[1] = idx >> 8;
1350 strcpy (si->data + 2, xlate (exp->name));
1351 }
1352 break;
1353 case IDATA7:
1354 si->size = 4;
1355 si->data =xmalloc(4);
1356 memset (si->data, 0, si->size);
1357 rel = xmalloc (sizeof (arelent));
1358 rpp = xmalloc (sizeof (arelent *) * 2);
1359 rpp[0] = rel;
1360 rel->address = 0;
1361 rel->addend = 0;
1362 rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
1363 rel->sym_ptr_ptr = iname_lab_pp;
1364 sec->orelocation = rpp;
1365 sec->reloc_count = 1;
1366 break;
1367 }
1368 }
1369
1370 {
1371 bfd_vma vma = 0;
1372 /* Size up all the sections */
1373 for (i = 0; i < NSECS; i++)
1374 {
1375 sinfo *si = secdata + i;
1376 bfd_set_section_size (abfd, si->sec, si->size);
1377 bfd_set_section_vma (abfd, si->sec, vma);
1378 /* vma += si->size;*/
1379 }
1380 }
1381 /* Write them out */
1382 for (i = 0; i < NSECS; i++)
1383 {
1384 sinfo *si = secdata + i;
1385 if (i == IDATA5 && no_idata5)
1386 continue;
1387
1388 if (i == IDATA4 && no_idata4)
1389 continue;
1390
1391 bfd_set_section_contents (abfd, si->sec,
1392 si->data, 0,
1393 si->size);
1394 }
1395
1396 bfd_set_symtab (abfd, ptrs, oidx);
1397 bfd_close (abfd);
1398 abfd = bfd_openr (outname, HOW_BFD_TARGET);
1399 return abfd;
1400 }
1401
1402 }
1403
1404
1405 static
1406 bfd *
1407 make_head()
1408 {
1409 FILE * f = fopen ("dh.s", "w");
1410
1411 fprintf (f, "%s IMAGE_IMPORT_DESCRIPTOR\n", ASM_C);
1412 fprintf (f, "\t.section .idata$2\n");
1413
1414 fprintf(f,"\t%s\t%s\n", ASM_GLOBAL,head_label);
1415
1416 fprintf (f, "%s:\n", head_label);
1417
1418 fprintf (f, "\t%shname%s\t%sPtr to image import by name list\n",
1419 ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
1420
1421 fprintf (f, "\t%sthis should be the timestamp, but NT sometimes\n", ASM_C);
1422 fprintf (f, "\t%sdoesn't load DLLs when this is set.\n", ASM_C);
1423 fprintf (f, "\t%s\t0\t%s loaded time\n", ASM_LONG, ASM_C);
1424 fprintf (f, "\t%s\t0\t%s Forwarder chain\n", ASM_LONG, ASM_C);
1425 fprintf (f, "\t%s__%s_iname%s\t%s imported dll's name\n",
1426 ASM_RVA_BEFORE,
1427 imp_name_lab,
1428 ASM_RVA_AFTER,
1429 ASM_C);
1430 fprintf (f, "\t%sfthunk%s\t%s pointer to firstthunk\n",
1431 ASM_RVA_BEFORE,
1432 ASM_RVA_AFTER, ASM_C);
1433
1434 fprintf (f, "%sStuff for compatibility\n", ASM_C);
1435
1436 if (!no_idata5)
1437 {
1438 fprintf (f, "\t.section\t.idata$5\n");
1439 fprintf (f, "\t%s\t0\n", ASM_LONG);
1440 fprintf (f, "fthunk:\n");
1441 }
1442 if (!no_idata4)
1443 {
1444 fprintf (f, "\t.section\t.idata$4\n");
1445
1446 fprintf (f, "\t%s\t0\n", ASM_LONG);
1447 fprintf (f, "\t.section .idata$4\n");
1448 fprintf (f, "hname:\n");
1449 }
1450 fclose (f);
1451
1452 sprintf (outfile, "-o dh.o dh.s");
1453 run (as_name, outfile);
1454
1455 return bfd_openr ("dh.o", HOW_BFD_TARGET);
1456 }
1457
1458 static
1459 bfd * make_tail()
1460 {
1461 FILE * f = fopen ("dt.s", "w");
1462 fprintf (f, "\t.section .idata$7\n");
1463 fprintf (f, "\t%s\t__%s_iname\n", ASM_GLOBAL, imp_name_lab);
1464 fprintf (f, "__%s_iname:\t%s\t\"%s\"\n",
1465 imp_name_lab, ASM_TEXT, dll_name);
1466
1467 if (!no_idata4)
1468 {
1469 fprintf (f, "\t.section .idata$4\n");
1470 fprintf (f, "\t%s\t0\n", ASM_LONG);
1471 }
1472 if (!no_idata5)
1473 {
1474 fprintf (f, "\t.section .idata$5\n");
1475 fprintf (f, "\t%s\t0\n", ASM_LONG);
1476 }
1477 fclose (f);
1478
1479 sprintf (outfile, "-o dt.o dt.s");
1480 run (as_name, outfile);
1481 return bfd_openr ("dt.o", HOW_BFD_TARGET);
1482 }
1483
1484 static void
1485 gen_lib_file ()
1486 {
1487 int i;
1488 export_type *exp;
1489 bfd *ar_head;
1490 bfd *ar_tail;
1491 bfd *outarch;
1492 bfd * head = 0;
1493
1494 unlink (imp_name);
1495
1496 outarch = bfd_openw (imp_name, HOW_BFD_TARGET);
1497
1498 if (!outarch)
1499 {
1500 fprintf (stderr, "%s: Can't open .lib file %s\n", program_name, imp_name);
1501 exit (1);
1502 }
1503 bfd_set_format (outarch, bfd_archive);
1504 outarch->has_armap = 1;
1505
1506 /* Work out a reasonable size of things to put onto one line. */
1507
1508
1509
1510 ar_head = make_head ();
1511 ar_tail = make_tail();
1512
1513 for (i = 0; (exp = d_exports_lexically[i]); i++)
1514 {
1515 bfd *n = make_one_lib_file (exp, i);
1516 n->next = head;
1517 head = n;
1518 }
1519
1520
1521 /* Now stick them all into the archive */
1522
1523 ar_head->next = head;
1524 ar_tail->next = ar_head;
1525 head = ar_tail;
1526
1527 bfd_set_archive_head (outarch, head);
1528 bfd_close (outarch);
1529
1530 /* Delete all the temp files */
1531
1532 if (dontdeltemps == 0)
1533 {
1534 sprintf (outfile, "dh.o");
1535 unlink (outfile);
1536 sprintf (outfile, "dh.s");
1537 unlink (outfile);
1538 sprintf (outfile, "dt.o");
1539 unlink (outfile);
1540 sprintf (outfile, "dt.s");
1541 unlink (outfile);
1542 }
1543
1544 if (dontdeltemps < 2)
1545 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
1546 {
1547 sprintf (outfile, "ds%d.o",i);
1548 unlink (outfile);
1549 }
1550
1551 }
1552 /**********************************************************************/
1553
1554 /* Run through the information gathered from the .o files and the
1555 .def file and work out the best stuff */
1556 int
1557 pfunc (a, b)
1558 void *a;
1559 void *b;
1560 {
1561 export_type *ap = *(export_type **) a;
1562 export_type *bp = *(export_type **) b;
1563 if (ap->ordinal == bp->ordinal)
1564 return 0;
1565
1566 /* unset ordinals go to the bottom */
1567 if (ap->ordinal == -1)
1568 return 1;
1569 if (bp->ordinal == -1)
1570 return -1;
1571 return (ap->ordinal - bp->ordinal);
1572 }
1573
1574
1575 int
1576 nfunc (a, b)
1577 void *a;
1578 void *b;
1579 {
1580 export_type *ap = *(export_type **) a;
1581 export_type *bp = *(export_type **) b;
1582
1583 return (strcmp (ap->name, bp->name));
1584 }
1585
1586 static
1587 void
1588 remove_null_names (ptr)
1589 export_type **ptr;
1590 {
1591 int src;
1592 int dst;
1593 for (dst = src = 0; src < d_nfuncs; src++)
1594 {
1595 if (ptr[src])
1596 {
1597 ptr[dst] = ptr[src];
1598 dst++;
1599 }
1600 }
1601 d_nfuncs = dst;
1602 }
1603
1604 static void
1605 dtab (ptr)
1606 export_type **ptr;
1607 {
1608 #ifdef SACDEBUG
1609 int i;
1610 for (i = 0; i < d_nfuncs; i++)
1611 {
1612 if (ptr[i])
1613 {
1614 printf ("%d %s @ %d %s%s\n",
1615 i, ptr[i]->name, ptr[i]->ordinal,
1616 ptr[i]->noname ? "NONAME " : "",
1617 ptr[i]->constant ? "CONSTANT" : "");
1618 }
1619 else
1620 printf ("empty\n");
1621 }
1622 #endif
1623 }
1624
1625 static void
1626 process_duplicates (d_export_vec)
1627 export_type **d_export_vec;
1628 {
1629 int more = 1;
1630 int i;
1631 while (more)
1632 {
1633
1634 more = 0;
1635 /* Remove duplicates */
1636 qsort (d_export_vec, d_nfuncs, sizeof (export_type *), nfunc);
1637
1638 dtab (d_export_vec);
1639 for (i = 0; i < d_nfuncs - 1; i++)
1640 {
1641 if (strcmp (d_export_vec[i]->name,
1642 d_export_vec[i + 1]->name) == 0)
1643 {
1644
1645 export_type *a = d_export_vec[i];
1646 export_type *b = d_export_vec[i + 1];
1647
1648 more = 1;
1649 if (verbose)
1650 fprintf (stderr, "Warning, ignoring duplicate EXPORT %s %d,%d\n",
1651 a->name,
1652 a->ordinal,
1653 b->ordinal);
1654 if (a->ordinal != -1
1655 && b->ordinal != -1)
1656 {
1657
1658 fprintf (stderr, "Error, duplicate EXPORT with oridinals %s\n",
1659 a->name);
1660 exit (1);
1661 }
1662 /* Merge attributes */
1663 b->ordinal = a->ordinal > 0 ? a->ordinal : b->ordinal;
1664 b->constant |= a->constant;
1665 b->noname |= a->noname;
1666 d_export_vec[i] = 0;
1667 }
1668
1669 dtab (d_export_vec);
1670 remove_null_names (d_export_vec);
1671 dtab (d_export_vec);
1672 }
1673 }
1674
1675
1676 /* Count the names */
1677 for (i = 0; i < d_nfuncs; i++)
1678 {
1679 if (!d_export_vec[i]->noname)
1680 d_named_nfuncs++;
1681 }
1682 }
1683
1684 static void
1685 fill_ordinals (d_export_vec)
1686 export_type **d_export_vec;
1687 {
1688 int lowest = 0;
1689
1690 int i;
1691 char *ptr;
1692 qsort (d_export_vec, d_nfuncs, sizeof (export_type *), pfunc);
1693
1694 /* fill in the unset ordinals with ones from our range */
1695
1696 ptr = (char *) malloc (65536);
1697
1698 memset (ptr, 65536, 0);
1699
1700 /* Mark in our large vector all the numbers that are taken */
1701 for (i = 0; i < d_nfuncs; i++)
1702 {
1703 if (d_export_vec[i]->ordinal != -1)
1704 {
1705 ptr[d_export_vec[i]->ordinal] = 1;
1706 if (lowest == 0)
1707 lowest = d_export_vec[i]->ordinal;
1708 }
1709 }
1710
1711 for (i = 0; i < d_nfuncs; i++)
1712 {
1713 if (d_export_vec[i]->ordinal == -1)
1714 {
1715 int j;
1716 for (j = lowest; j < 65536; j++)
1717 if (ptr[j] == 0)
1718 {
1719 ptr[j] = 1;
1720 d_export_vec[i]->ordinal = j;
1721 goto done;
1722 }
1723
1724 for (j = 1; j < lowest; j++)
1725 if (ptr[j] == 0)
1726 {
1727 ptr[j] = 1;
1728 d_export_vec[i]->ordinal = j;
1729 goto done;
1730 }
1731 done:;
1732
1733 }
1734 }
1735
1736 free (ptr);
1737
1738 /* And resort */
1739
1740 qsort (d_export_vec, d_nfuncs, sizeof (export_type *), pfunc);
1741
1742
1743 /* Work out the lowest ordinal number */
1744 if (d_export_vec[0])
1745 d_low_ord = d_export_vec[0]->ordinal;
1746 if (d_nfuncs)
1747 {
1748 if (d_export_vec[d_nfuncs-1])
1749 d_high_ord = d_export_vec[d_nfuncs-1]->ordinal;
1750 }
1751 }
1752
1753 int alphafunc(av,bv)
1754 void *av;
1755 void *bv;
1756 {
1757 export_type **a = av;
1758 export_type **b = bv;
1759
1760 return strcmp ((*a)->name, (*b)->name);
1761 }
1762
1763 void
1764 mangle_defs ()
1765 {
1766 /* First work out the minimum ordinal chosen */
1767
1768 export_type *exp;
1769
1770 int i;
1771 int hint = 0;
1772 export_type **d_export_vec
1773 = (export_type **) xmalloc (sizeof (export_type *) * d_nfuncs);
1774
1775 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
1776 {
1777 d_export_vec[i] = exp;
1778 }
1779
1780 process_duplicates (d_export_vec);
1781 fill_ordinals (d_export_vec);
1782
1783 /* Put back the list in the new order */
1784 d_exports = 0;
1785 for (i = d_nfuncs - 1; i >= 0; i--)
1786 {
1787 d_export_vec[i]->next = d_exports;
1788 d_exports = d_export_vec[i];
1789 }
1790
1791 /* Build list in alpha order */
1792 d_exports_lexically = (export_type **)xmalloc (sizeof(export_type *)*(d_nfuncs+1));
1793
1794 for (i = 0, exp = d_exports; exp; i++, exp = exp->next)
1795 {
1796 d_exports_lexically[i] = exp;
1797 }
1798 d_exports_lexically[i] = 0;
1799
1800 qsort (d_exports_lexically, i, sizeof (export_type *), alphafunc);
1801
1802 /* Fill exp entries with their hint values */
1803
1804 for (i = 0; i < d_nfuncs; i++)
1805 {
1806 if (!d_exports_lexically[i]->noname || show_allnames)
1807 d_exports_lexically[i]->hint = hint++;
1808 }
1809
1810 }
1811
1812
1813
1814
1815
1816
1817 /**********************************************************************/
1818
1819 void
1820 usage (file, status)
1821 FILE *file;
1822 int status;
1823 {
1824 fprintf (file, "Usage %s <options> <object-files>\n", program_name);
1825 fprintf (file, " --machine <machine>\n");
1826 fprintf (file, " --output-exp <outname> Generate export file.\n");
1827 fprintf (file, " --output-lib <outname> Generate input library.\n");
1828 fprintf (file, " --add-indirect Add dll indirects to export file.\n");
1829 fprintf (file, " --dllname <name> Name of input dll to put into output lib.\n");
1830 fprintf (file, " --def <deffile> Name input .def file\n");
1831 fprintf (file, " --output-def <deffile> Name output .def file\n");
1832 fprintf (file, " --base-file <basefile> Read linker generated base file\n");
1833 fprintf (file, " --no-idata4 Don't generate idata$4 section\n");
1834 fprintf (file, " --no-idata5 Don't generate idata$5 section\n");
1835 fprintf (file, " -v Verbose\n");
1836 fprintf (file, " -U Add underscores to .lib\n");
1837 fprintf (file, " -k Kill @<n> from exported names\n");
1838 fprintf (file, " --as <name> Use <name> for assembler\n");
1839 fprintf (file, " --nodelete Keep temp files.\n");
1840 exit (status);
1841 }
1842
1843 #define OPTION_NO_IDATA4 'x'
1844 #define OPTION_NO_IDATA5 'c'
1845 static struct option long_options[] =
1846 {
1847 {"nodelete", no_argument, NULL, 'n'},
1848 {"dllname", required_argument, NULL, 'D'},
1849 {"no-idata4", no_argument, NULL, OPTION_NO_IDATA4},
1850 {"no-idata5", no_argument, NULL, OPTION_NO_IDATA5},
1851 {"output-exp", required_argument, NULL, 'e'},
1852 {"output-def", required_argument, NULL, 'z'},
1853 {"output-lib", required_argument, NULL, 'l'},
1854 {"def", required_argument, NULL, 'd'},
1855 {"add-underscore", no_argument, NULL, 'U'},
1856 {"killat", no_argument, NULL, 'k'},
1857 {"help", no_argument, NULL, 'h'},
1858 {"machine", required_argument, NULL, 'm'},
1859 {"add-indirect", no_argument, NULL, 'a'},
1860 {"base-file", required_argument, NULL, 'b'},
1861 {"as", required_argument, NULL, 'S'},
1862 {0}
1863 };
1864
1865
1866
1867 int
1868 main (ac, av)
1869 int ac;
1870 char **av;
1871 {
1872 int c;
1873 int i;
1874 char *firstarg = 0;
1875 program_name = av[0];
1876 oav = av;
1877
1878 while ((c = getopt_long (ac, av, "xcz:S:R:A:puaD:l:e:nkvbUh?m:yd:", long_options, 0))
1879 != EOF)
1880 {
1881 switch (c)
1882 {
1883 case OPTION_NO_IDATA4:
1884 no_idata4 = 1;
1885 break;
1886 case OPTION_NO_IDATA5:
1887 no_idata5 = 1;
1888 break;
1889 case 'S':
1890 as_name = optarg;
1891 break;
1892
1893 /* ignored for compatibility */
1894 case 'u':
1895 break;
1896 case 'a':
1897 add_indirect = 1;
1898 break;
1899 case 'z':
1900 output_def = fopen (optarg, "w");
1901 break;
1902 case 'D':
1903 dll_name = optarg;
1904 break;
1905 case 'l':
1906 imp_name = optarg;
1907 break;
1908 case 'e':
1909 exp_name = optarg;
1910 break;
1911 case 'h':
1912 case '?':
1913 usage (stderr, 0);
1914 break;
1915 case 'm':
1916 mname = optarg;
1917 break;
1918 case 'v':
1919 verbose = 1;
1920 break;
1921 case 'y':
1922 yydebug = 1;
1923 break;
1924 case 'U':
1925 add_underscore = 1;
1926 break;
1927 case 'k':
1928 killat = 1;
1929 break;
1930 case 'd':
1931 def_file = optarg;
1932 break;
1933 case 'n':
1934 dontdeltemps++;
1935 break;
1936 case 'b':
1937 base_file = fopen (optarg, "r");
1938 if (!base_file)
1939 {
1940 fprintf (stderr, "%s: Unable to open base-file %s\n",
1941 av[0],
1942 optarg);
1943 exit (1);
1944 }
1945 break;
1946 default:
1947 usage (stderr, 1);
1948 }
1949 }
1950
1951
1952 for (i = 0; mtable[i].type; i++)
1953 {
1954 if (strcmp (mtable[i].type, mname) == 0)
1955 break;
1956 }
1957
1958 if (!mtable[i].type)
1959 {
1960 fprintf (stderr, "Machine not supported\n");
1961 exit (1);
1962 }
1963 machine = i;
1964
1965
1966 if (!dll_name && exp_name)
1967 {
1968 char len = strlen (exp_name) + 5;
1969 dll_name = xmalloc (len);
1970 strcpy (dll_name, exp_name);
1971 strcat (dll_name, ".dll");
1972 }
1973
1974 if (def_file)
1975 {
1976 process_def_file (def_file);
1977 }
1978 while (optind < ac)
1979 {
1980 if (!firstarg)
1981 firstarg = av[optind];
1982 scan_obj_file (av[optind]);
1983 optind++;
1984 }
1985
1986
1987 mangle_defs ();
1988
1989 if (exp_name)
1990 gen_exp_file ();
1991 if (imp_name)
1992 {
1993 /* Make imp_name safe for use as a label. */
1994 char *p;
1995 imp_name_lab = strdup (imp_name);
1996 for (p = imp_name_lab; *p; *p++)
1997 {
1998 if (!isalpha (*p) && !isdigit (*p))
1999 *p = '_';
2000 }
2001 head_label = make_label("_head_", imp_name_lab);
2002 gen_lib_file ();
2003 }
2004 if (output_def)
2005 gen_def_file ();
2006
2007 return 0;
2008 }
This page took 0.09901 seconds and 3 git commands to generate.