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