-#define show_allnames 0
-
/* dlltool.c -- tool to generate stuff for PE style DLLs
- Copyright (C) 1995 Free Software Foundation, Inc.
+ Copyright (C) 1995, 96, 1997 Free Software Foundation, Inc.
This file is part of GNU Binutils.
DLLs to run on a system which understands PE format image files.
(eg, Windows NT)
+ See "Peering Inside the PE: A Tour of the Win32 Portable Executable
+ File Format", MSJ 1994, Volume 9 for more information.
+ Also see "Microsoft Portable Executable and Common Object File Format,
+ Specification 4.1" for more information.
+
A DLL contains an export table which contains the information
which the runtime loader needs to tie up references from a
referencing program.
*/
+/* .idata section description
+
+ The .idata section is the import table. It is a collection of several
+ subsections used to keep the pieces for each dll together: .idata$[234567].
+ IE: Each dll's .idata$2's are catenated together, each .idata$3's, etc.
+
+ .idata$2 = Import Directory Table
+ = array of IMAGE_IMPORT_DESCRIPTOR's.
+
+ DWORD Characteristics; - pointer to .idata$4
+ DWORD TimeDateStamp; - currently always 0
+ DWORD ForwarderChain; - currently always 0
+ DWORD Name; - pointer to dll's name
+ PIMAGE_THUNK_DATA FirstThunk; - pointer to .idata$5
+
+ .idata$3 = null terminating entry for .idata$2.
+
+ .idata$4 = Import Lookup Table
+ = array of array of pointers to hint name table.
+ There is one for each dll being imported from, and each dll's set is
+ terminated by a trailing NULL.
+
+ .idata$5 = Import Address Table
+ = array of array of pointers to hint name table.
+ There is one for each dll being imported from, and each dll's set is
+ terminated by a trailing NULL.
+ Initially, this table is identical to the Import Lookup Table. However,
+ at load time, the loader overwrites the entries with the address of the
+ function.
+
+ .idata$6 = Hint Name Table
+ = Array of { short, asciz } entries, one for each imported function.
+ The `short' is the function's ordinal number.
+
+ .idata$7 = dll name (eg: "kernel32.dll"). (.idata$6 for ppc)
+*/
+
+/* AIX requires this to be the first thing in the file. */
+#ifndef __GNUC__
+# ifdef _AIX
+ #pragma alloca
+#endif
+#endif
+
+#define show_allnames 0
+
#define PAGE_SIZE 4096
#define PAGE_MASK (-PAGE_SIZE)
#include "bfd.h"
#include "bucomm.h"
#include "getopt.h"
#include "demangle.h"
+#include "dlltool.h"
+
#include <ctype.h>
+#include <time.h>
+
#ifdef HAVE_SYS_WAIT_H
#include <sys/wait.h>
#else
#endif
#endif
+#ifdef HAVE_VFORK_H
+#include <vfork.h>
+#endif
-
-char *as_name = "as";
+static char *as_name = "as";
static int no_idata4;
static int no_idata5;
static int add_underscore = 0;
static int dontdeltemps = 0;
-int yyparse();
-int yydebug;
static char *def_file;
static char *program_name;
-char *strrchr ();
-char *strdup ();
static int machine;
-int killat;
+static int killat;
static int verbose;
-FILE *output_def;
-FILE *base_file;
+static FILE *output_def;
+static FILE *base_file;
#ifdef DLLTOOL_ARM
-static char *mname = "arm";
+static const char *mname = "arm";
#endif
#ifdef DLLTOOL_I386
-static char *mname = "i386";
+static const char *mname = "i386";
#endif
#ifdef DLLTOOL_PPC
-static char *mname = "ppc";
+static const char *mname = "ppc";
#endif
#define PATHMAX 250 /* What's the right name for this ? */
/* This bit of assemly does jmp * ....
s set how_jtab_roff to mark where the 32bit abs branch should go */
-unsigned char i386_jtab[] = { 0xff, 0x25, 0x00, 0x00, 0x00, 0x00, 0x90, 0x90};
+static const unsigned char i386_jtab[] =
+{
+ 0xff, 0x25, 0x00, 0x00, 0x00, 0x00, 0x90, 0x90
+};
+static const unsigned char arm_jtab[] =
+{
+ 0x00, 0xc0, 0x9f, 0xe5,
+ 0x00, 0xf0, 0x9c, 0xe5,
+ 0, 0, 0, 0
+};
-unsigned char arm_jtab[] = { 0x00, 0xc0, 0x9f, 0xe5,
- 0x00, 0xf0, 0x9c, 0xe5,
- 0, 0, 0, 0};
-/* If I understand what is going on here, this will need more for ppc
- support, but this lets the program start. Kim Knuttila (krk@cygnus.com) */
+/* This is the glue sequence for PowerPC PE. There is a */
+/* tocrel16-tocdefn reloc against the first instruction. */
+/* We also need a IMGLUE reloc against the glue function */
+/* to restore the toc saved by the third instruction in */
+/* the glue. */
+static const unsigned char ppc_jtab[] =
+{
+ 0x00, 0x00, 0x62, 0x81, /* lwz r11,0(r2) */
+ /* Reloc TOCREL16 __imp_xxx */
+ 0x00, 0x00, 0x8B, 0x81, /* lwz r12,0(r11) */
+ 0x04, 0x00, 0x41, 0x90, /* stw r2,4(r1) */
+ 0xA6, 0x03, 0x89, 0x7D, /* mtctr r12 */
+ 0x04, 0x00, 0x4B, 0x80, /* lwz r2,4(r11) */
+ 0x20, 0x04, 0x80, 0x4E /* bctr */
+};
-unsigned char ppc_jtab[] = { 0xff, 0x25, 0x00, 0x00, 0x00, 0x00, 0x90, 0x90};
+#ifdef DLLTOOL_PPC
+/* the glue instruction, picks up the toc from the stw in */
+/* the above code: "lwz r2,4(r1)" */
+static bfd_vma ppc_glue_insn = 0x80410004;
+#endif
+
+static char outfile[PATHMAX];
-char outfile[PATHMAX];
struct mac
{
- char *type;
- char *how_byte;
- char *how_short;
- char *how_long;
- char *how_asciz;
- char *how_comment;
- char *how_jump;
- char *how_global;
- char *how_space;
- char *how_align_short;
- char *how_align_long;
- char *how_bfd_target;
+ const char *type;
+ const char *how_byte;
+ const char *how_short;
+ const char *how_long;
+ const char *how_asciz;
+ const char *how_comment;
+ const char *how_jump;
+ const char *how_global;
+ const char *how_space;
+ const char *how_align_short;
+ const char *how_align_long;
+ const char *how_bfd_target;
enum bfd_architecture how_bfd_arch;
- unsigned char *how_jtab;
+ const unsigned char *how_jtab;
int how_jtab_size; /* size of the jtab entry */
int how_jtab_roff; /* offset into it for the ind 32 reloc into idata 5 */
- }
-mtable[]
-=
+ };
+
+static const struct mac mtable[] =
{
{
#define MARM 0
{
#define MPPC 2
"ppc", ".byte", ".short", ".long", ".asciz", "#", "jmp *", ".global", ".space", ".align\t2",".align\t4","pe-powerpcle",bfd_arch_powerpc,
- ppc_jtab,sizeof(ppc_jtab),2,
+ ppc_jtab,sizeof(ppc_jtab),0,
}
,
{ 0}
};
+typedef struct dlist
+{
+ char *text;
+ struct dlist *next;
+}
+dlist_type;
+
+typedef struct export
+ {
+ const char *name;
+ const char *internal_name;
+ int ordinal;
+ int constant;
+ int noname;
+ int hint;
+ struct export *next;
+ }
+export_type;
-char *
+static const char *rvaafter PARAMS ((int));
+static const char *rvabefore PARAMS ((int));
+static const char *asm_prefix PARAMS ((int));
+static void run PARAMS ((const char *, char *));
+static void basenames PARAMS ((bfd *));
+static void scan_open_obj_file PARAMS ((bfd *));
+static void scan_obj_file PARAMS ((const char *));
+static void dump_def_info PARAMS ((FILE *));
+static int sfunc PARAMS ((const void *, const void *));
+static void flush_page PARAMS ((FILE *, long *, int, int));
+static void gen_def_file PARAMS ((void));
+static void gen_exp_file PARAMS ((void));
+static const char *xlate PARAMS ((const char *));
+static void dump_iat PARAMS ((FILE *, export_type *));
+static char *make_label PARAMS ((const char *, const char *));
+static bfd *make_one_lib_file PARAMS ((export_type *, int));
+static bfd *make_head PARAMS ((void));
+static bfd *make_tail PARAMS ((void));
+static void gen_lib_file PARAMS ((void));
+static int pfunc PARAMS ((const void *, const void *));
+static int nfunc PARAMS ((const void *, const void *));
+static void remove_null_names PARAMS ((export_type **));
+static void dtab PARAMS ((export_type **));
+static void process_duplicates PARAMS ((export_type **));
+static void fill_ordinals PARAMS ((export_type **));
+static int alphafunc PARAMS ((const void *, const void *));
+static void mangle_defs PARAMS ((void));
+static void usage PARAMS ((FILE *, int));
+
+static const char *
rvaafter (machine)
int machine;
{
case MPPC:
return "";
}
-return "";
+ return "";
}
-char *
+static const char *
rvabefore (machine)
int machine;
{
case MPPC:
return ".rva\t";
}
-return "";
+ return "";
}
-char *
+static const char *
asm_prefix (machine)
-int machine;
+ int machine;
{
switch (machine)
{
case MPPC:
return "";
}
-return "";
+ return "";
}
+
#define ASM_BYTE mtable[machine].how_byte
#define ASM_SHORT mtable[machine].how_short
#define ASM_LONG mtable[machine].how_long
#define HOW_JTAB_ROFF mtable[machine].how_jtab_roff
static char **oav;
-
-FILE *yyin; /* communications with flex */
-extern int linenumber;
void
process_def_file (name)
- char *name;
+ const char *name;
{
FILE *f = fopen (name, FOPEN_RT);
if (!f)
/* Communications with the parser */
-
-typedef struct dlist
-{
- char *text;
- struct dlist *next;
-}
-dlist_type;
-
-typedef struct export
- {
- char *name;
- char *internal_name;
- int ordinal;
- int constant;
- int noname;
- int hint;
- struct export *next;
- }
-export_type;
-
-static char *d_name; /* Arg to NAME or LIBRARY */
+static const char *d_name; /* Arg to NAME or LIBRARY */
static int d_nfuncs; /* Number of functions exported */
static int d_named_nfuncs; /* Number of named functions exported */
static int d_low_ord; /* Lowest ordinal index */
static int d_is_exe;
int
-yyerror ()
+yyerror (err)
+ const char *err;
{
fprintf (stderr, "%s: Syntax error in def file %s:%d\n",
program_name, def_file, linenumber);
void
def_exports (name, internal_name, ordinal, noname, constant)
- char *name;
- char *internal_name;
+ const char *name;
+ const char *internal_name;
int ordinal;
int noname;
int constant;
d_nfuncs++;
}
-
void
def_name (name, base)
- char *name;
+ const char *name;
int base;
{
if (verbose)
void
def_library (name, base)
- char *name;
+ const char *name;
int base;
{
if (verbose)
void
def_description (desc)
- char *desc;
+ const char *desc;
{
dlist_type *d = (dlist_type *) xmalloc (sizeof (dlist_type));
- d->text = strdup (desc);
+ d->text = xstrdup (desc);
d->next = d_list;
d_list = d;
}
char *dir;
{
dlist_type *d = (dlist_type *) xmalloc (sizeof (dlist_type));
- d->text = strdup (dir);
+ d->text = xstrdup (dir);
d->next = a_list;
a_list = d;
}
sprintf (b, "-stack 0x%x,0x%x ", reserve, commit);
else
sprintf (b, "-stack 0x%x ", reserve);
- new_directive (strdup (b));
+ new_directive (xstrdup (b));
}
void
sprintf (b, "-heap 0x%x,0x%x ", reserve, commit);
else
sprintf (b, "-heap 0x%x ", reserve);
- new_directive (strdup (b));
+ new_directive (xstrdup (b));
}
-
void
def_import (internal, module, entry)
- char *internal;
- char *module;
- char *entry;
+ const char *internal;
+ const char *module;
+ const char *entry;
{
if (verbose)
fprintf (stderr, "%s: IMPORTS are ignored", program_name);
void
def_version (major, minor)
-int major;
-int minor;
+ int major;
+ int minor;
{
printf ("VERSION %d.%d\n", major, minor);
}
-
void
def_section (name, attr)
- char *name;
+ const char *name;
int attr;
{
char buf[200];
*d++ = 'S';
*d++ = 0;
sprintf (buf, "-attr %s %s", name, atts);
- new_directive (strdup (buf));
+ new_directive (xstrdup (buf));
}
+
void
def_code (attr)
int attr;
def_section ("DATA", attr);
}
-
/**********************************************************************/
-void
+static void
run (what, args)
- char *what;
+ const char *what;
char *args;
{
char *s;
int pid;
int i;
- char **argv;
- extern char **environ;
+ const char **argv;
+
if (verbose)
fprintf (stderr, "%s %s\n", what, args);
break;
*s++ = 0;
}
- argv[i++] = 0;
-
+ argv[i++] = NULL;
pid = vfork ();
if (pid == 0)
{
- execvp (what, argv);
+ execvp (what, (char **) argv);
fprintf (stderr, "%s: can't exec %s\n", program_name, what);
exit (1);
}
basenames (abfd)
bfd *abfd;
{
-
-
-
-
}
-void
+static void
scan_open_obj_file (abfd)
bfd *abfd;
{
char *c;
p += 8;
name = p;
- while (*p != ' ' && *p != '-' && p < e)
+ while (p < e && *p != ' ' && *p != '-')
p++;
c = xmalloc (p - name + 1);
memcpy (c, name, p - name);
c[p - name] = 0;
- def_exports (c, 0, -1, 0);
+ /* FIXME: The 5th arg is for the `constant' field.
+ What should it be? Not that it matters since it's not
+ currently useful. */
+ def_exports (c, 0, -1, 0, 0);
}
else
p++;
if (verbose)
fprintf (stderr, "%s: Done readin\n",
program_name);
-
}
-
-void
+static void
scan_obj_file (filename)
- char *filename;
+ const char *filename;
{
bfd *f = bfd_openr (filename, 0);
/**********************************************************************/
-
-
-void
+static void
dump_def_info (f)
FILE *f;
{
exp->constant ? "CONSTANT" : "");
}
}
+
/* Generate the .exp file */
-int
+static int
sfunc (a, b)
- long *a;
- long *b;
+ const void *a;
+ const void *b;
{
- return *a - *b;
+ return *(const long *) a - *(const long *) b;
}
-
-
static void
flush_page (f, need, page_addr, on_page)
FILE *f;
- int *need;
+ long *need;
int page_addr;
int on_page;
{
ASM_C);
for (i = 0; i < on_page; i++)
{
- fprintf (f, "\t%s\t0x%x\n", ASM_SHORT, (need[i] - page_addr) | 0x3000);
+ fprintf (f, "\t%s\t0x%lx\n", ASM_SHORT, (need[i] - page_addr) | 0x3000);
}
/* And padding */
if (on_page & 1)
fprintf (f, "\t%s\t0x%x\n", ASM_SHORT, 0 | 0x0000);
-
}
-
-void
+static void
gen_def_file ()
{
int i;
cplus_demangle (exp->internal_name, DMGL_ANSI | DMGL_PARAMS));
}
}
-void
+
+static void
gen_exp_file ()
{
FILE *f;
{
fprintf (f, "\t.section .edata\n\n");
fprintf (f, "\t%s 0 %s Allways 0\n", ASM_LONG, ASM_C);
- fprintf (f, "\t%s 0x%x %s Time and date\n", ASM_LONG, time(0),ASM_C);
+ fprintf (f, "\t%s 0x%lx %s Time and date\n", ASM_LONG, (long) time(0),
+ ASM_C);
fprintf (f, "\t%s 0 %s Major and Minor version\n", ASM_LONG, ASM_C);
fprintf (f, "\t%sname%s %s Ptr to name of dll\n", ASM_RVA_BEFORE, ASM_RVA_AFTER, ASM_C);
fprintf (f, "\t%s %d %s Starting ordinal of exports\n", ASM_LONG, d_low_ord, ASM_C);
fseek (base_file, 0, SEEK_END);
numbytes = ftell (base_file);
fseek (base_file, 0, SEEK_SET);
- copy = malloc (numbytes);
+ copy = xmalloc (numbytes);
fread (copy, 1, numbytes, base_file);
num_entries = numbytes / sizeof (long);
fprintf (f, "\t.section\t.reloc\n");
if (num_entries)
{
-
int src;
int dst = 0;
int last = -1;
}
}
-static char *
-xlate (char *name)
+static const char *
+xlate (name)
+ const char *name;
{
if (add_underscore)
{
- char *copy = malloc (strlen (name) + 2);
+ char *copy = xmalloc (strlen (name) + 2);
copy[0] = '_';
strcpy (copy + 1, name);
name = copy;
/**********************************************************************/
-static void dump_iat (f, exp)
-FILE *f;
-export_type *exp;
+static void
+dump_iat (f, exp)
+ FILE *f;
+ export_type *exp;
{
if (exp->noname && !show_allnames )
{
}
}
-
-
typedef struct
{
int id;
const char *name;
int flags;
+ int align;
asection *sec;
asymbol *sym;
asymbol **sympp;
unsigned char *data;
} sinfo;
+#ifndef DLLTOOL_PPC
#define TEXT 0
#define DATA 1
#define IDATA5 4
#define IDATA4 5
#define IDATA6 6
+
#define NSECS 7
static sinfo secdata[NSECS] =
{
- { TEXT, ".text", SEC_CODE | SEC_HAS_CONTENTS},
- { DATA, ".data", SEC_DATA},
- { BSS,".bss" },
- { IDATA7, ".idata$7",SEC_HAS_CONTENTS},
- { IDATA5, ".idata$5", SEC_HAS_CONTENTS},
- { IDATA4, ".idata$4", SEC_HAS_CONTENTS},
- { IDATA6,".idata$6", SEC_HAS_CONTENTS}
+ { TEXT, ".text", SEC_CODE | SEC_HAS_CONTENTS, 2},
+ { DATA, ".data", SEC_DATA, 2},
+ { BSS, ".bss", 0, 2},
+ { IDATA7, ".idata$7", SEC_HAS_CONTENTS, 2},
+ { IDATA5, ".idata$5", SEC_HAS_CONTENTS, 2},
+ { IDATA4, ".idata$4", SEC_HAS_CONTENTS, 2},
+ { IDATA6, ".idata$6", SEC_HAS_CONTENTS, 1}
+};
+
+#else
+
+/* Sections numbered to make the order the same as other PowerPC NT */
+/* compilers. This also keeps funny alignment thingies from happening. */
+#define TEXT 0
+#define PDATA 1
+#define RDATA 2
+#define IDATA5 3
+#define IDATA4 4
+#define IDATA6 5
+#define IDATA7 6
+#define DATA 7
+#define BSS 8
+#define NSECS 9
+static sinfo secdata[NSECS] =
+{
+ { TEXT, ".text", SEC_CODE | SEC_HAS_CONTENTS, 3},
+ { PDATA, ".pdata", SEC_HAS_CONTENTS, 2},
+ { RDATA, ".reldata", SEC_HAS_CONTENTS, 2},
+ { IDATA5, ".idata$5", SEC_HAS_CONTENTS, 2},
+ { IDATA4, ".idata$4", SEC_HAS_CONTENTS, 2},
+ { IDATA6, ".idata$6", SEC_HAS_CONTENTS, 1},
+ { IDATA7, ".idata$7", SEC_HAS_CONTENTS, 2},
+ { DATA, ".data", SEC_DATA, 2},
+ { BSS, ".bss", 0, 2}
};
+
+#endif
+
/*
This is what we're trying to make
ID2: .short 2
.asciz "GetFileVersionInfoSizeW"
+
+For the PowerPC, here's the variation on the above scheme:
+
+# Rather than a simple "jmp *", the code to get to the dll function
+# looks like:
+ .text
+ lwz r11,[tocv]__imp_function_name(r2)
+# RELOC: 00000000 TOCREL16,TOCDEFN __imp_function_name
+ lwz r12,0(r11)
+ stw r2,4(r1)
+ mtctr r12
+ lwz r2,4(r11)
+ bctr
*/
-static char *make_label (prefix, name)
-const char *prefix;
-const char *name;
+static char *
+make_label (prefix, name)
+ const char *prefix;
+ const char *name;
{
int len = strlen (ASM_PREFIX) + strlen (prefix) + strlen (name);
char *copy = xmalloc (len +1 );
strcat (copy, name);
return copy;
}
+
static bfd *
make_one_lib_file (exp, i)
-export_type *exp;
-int i;
+ export_type *exp;
+ int i;
{
if (0)
{
asymbol *iname;
asymbol *iname_lab;
asymbol **iname_lab_pp;
- asymbol *ptrs[NSECS+3+1]; /* one symbol for each section, 2 extra + a null */
+ asymbol **iname_pp;
+
+ /* Extra Symbols for PPC */
+#ifdef DLLTOOL_PPC
+#define EXTRA 2
+#else
+#define EXTRA 0
+#endif
+
+#ifdef DLLTOOL_PPC
+ asymbol **fn_pp;
+ asymbol **toc_pp;
+#endif
+
+ /* one symbol for each section, 2 extra + a null */
+ asymbol *ptrs[NSECS+3+EXTRA+1];
char *outname = xmalloc (10);
int oidx = 0;
abfd = bfd_openw (outname, HOW_BFD_TARGET);
if (!abfd)
{
- fprintf (stderr, "%s: bfd_open failed open output file %s\n", program_name, outname);
+ fprintf (stderr, "%s: bfd_open failed open output file %s\n",
+ program_name, outname);
exit (1);
}
bfd_set_arch_mach (abfd, HOW_BFD_ARCH, 0);
+ /* First make symbols for the sections */
for (i = 0; i < NSECS; i++)
{
sinfo *si = secdata + i;
bfd_set_section_flags (abfd,
si->sec,
si->flags);
+
+ bfd_set_section_alignment(abfd, si->sec, si->align);
si->sec->output_section = si->sec;
- si->sym = bfd_make_empty_symbol(abfd);
+ si->sym = bfd_make_empty_symbol(abfd);
si->sym->name = si->sec->name;
si->sym->section = si->sec;
si->sym->flags = BSF_LOCAL;
exp_label = bfd_make_empty_symbol(abfd);
exp_label->name = make_label ("",exp->name);
- exp_label->section = secdata[TEXT].sec;
+
+ /* On PowerPC, the function name points to a descriptor in the
+ rdata section, the first element of which is a pointer to the
+ code (..function_name), and the second points to the .toc
+ */
+#ifdef DLLTOOL_PPC
+ if (machine == MPPC)
+ exp_label->section = secdata[RDATA].sec;
+ else
+#endif
+ exp_label->section = secdata[TEXT].sec;
+
exp_label->flags = BSF_GLOBAL;
exp_label->value = 0;
ptrs[oidx++] = exp_label;
iname = bfd_make_empty_symbol(abfd);
-
iname->name = make_label ("__imp_", exp->name);
-
iname->section = secdata[IDATA5].sec;
iname->flags = BSF_GLOBAL;
iname->value = 0;
iname_lab->value = 0;
+ iname_pp = ptrs + oidx;
ptrs[oidx++] = iname;
+
iname_lab_pp = ptrs + oidx;
ptrs[oidx++] = iname_lab;
+
+#ifdef DLLTOOL_PPC
+ /* The symbol refering to the code (.text) */
+ {
+ asymbol *function_name;
+
+ function_name = bfd_make_empty_symbol(abfd);
+ function_name->name = make_label ("..", exp->name);
+ function_name->section = secdata[TEXT].sec;
+ function_name->flags = BSF_GLOBAL;
+ function_name->value = 0;
+
+ fn_pp = ptrs + oidx;
+ ptrs[oidx++] = function_name;
+ }
+
+ /* The .toc symbol */
+ {
+ asymbol *toc_symbol; /* The .toc symbol */
+
+ toc_symbol = bfd_make_empty_symbol(abfd);
+ toc_symbol->name = make_label (".", "toc");
+ toc_symbol->section = (asection *)&bfd_und_section;
+ toc_symbol->flags = BSF_GLOBAL;
+ toc_symbol->value = 0;
+
+ toc_pp = ptrs + oidx;
+ ptrs[oidx++] = toc_symbol;
+ }
+#endif
+
ptrs[oidx] = 0;
for (i = 0; i < NSECS; i++)
rpp[1] = 0;
rel->address = HOW_JTAB_ROFF;
rel->addend = 0;
- rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
- rel->sym_ptr_ptr = secdata[IDATA5].sympp;
+
+ if (machine == MPPC)
+ {
+ rel->howto = bfd_reloc_type_lookup (abfd,
+ BFD_RELOC_16_GOTOFF);
+ rel->sym_ptr_ptr = iname_pp;
+ }
+ else
+ {
+ rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
+ rel->sym_ptr_ptr = secdata[IDATA5].sympp;
+ }
sec->orelocation = rpp;
sec->reloc_count = 1;
break;
/* An idata$4 or idata$5 is one word long, and has an
rva to idata$6 */
-
si->data = xmalloc (4);
si->size = 4;
rpp[0] = rel;
rel->address = 0;
rel->addend = 0;
- rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
+ rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_RVA);
rel->sym_ptr_ptr = iname_lab_pp;
sec->orelocation = rpp;
sec->reloc_count = 1;
break;
+
+#ifdef DLLTOOL_PPC
+ case PDATA:
+ {
+ /* The .pdata section is 5 words long. */
+ /* Think of it as: */
+ /* struct */
+ /* { */
+ /* bfd_vma BeginAddress, [0x00] */
+ /* EndAddress, [0x04] */
+ /* ExceptionHandler, [0x08] */
+ /* HandlerData, [0x0c] */
+ /* PrologEndAddress; [0x10] */
+ /* }; */
+
+ /* So this pdata section setups up this as a glue linkage to
+ a dll routine. There are a number of house keeping things
+ we need to do:
+
+ 1. In the name of glue trickery, the ADDR32 relocs for 0,
+ 4, and 0x10 are set to point to the same place:
+ "..function_name".
+ 2. There is one more reloc needed in the pdata section.
+ The actual glue instruction to restore the toc on
+ return is saved as the offset in an IMGLUE reloc.
+ So we need a total of four relocs for this section.
+
+ 3. Lastly, the HandlerData field is set to 0x03, to indicate
+ that this is a glue routine.
+ */
+ arelent *imglue, *ba_rel, *ea_rel, *pea_rel;
+
+ /* alignment must be set to 2**2 or you get extra stuff */
+ bfd_set_section_alignment(abfd, sec, 2);
+
+ si->size = 4 * 5;
+ si->data =xmalloc(4 * 5);
+ memset (si->data, 0, si->size);
+ rpp = xmalloc (sizeof (arelent *) * 5);
+ rpp[0] = imglue = xmalloc (sizeof (arelent));
+ rpp[1] = ba_rel = xmalloc (sizeof (arelent));
+ rpp[2] = ea_rel = xmalloc (sizeof (arelent));
+ rpp[3] = pea_rel = xmalloc (sizeof (arelent));
+ rpp[4] = 0;
+
+ /* stick the toc reload instruction in the glue reloc */
+ bfd_put_32(abfd, ppc_glue_insn, (char *) &imglue->address);
+
+ imglue->addend = 0;
+ imglue->howto = bfd_reloc_type_lookup (abfd,
+ BFD_RELOC_32_GOTOFF);
+ imglue->sym_ptr_ptr = fn_pp;
+
+ ba_rel->address = 0;
+ ba_rel->addend = 0;
+ ba_rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
+ ba_rel->sym_ptr_ptr = fn_pp;
+
+ bfd_put_32(abfd, 0x18, si->data + 0x04);
+ ea_rel->address = 4;
+ ea_rel->addend = 0;
+ ea_rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
+ ea_rel->sym_ptr_ptr = fn_pp;
+
+ /* mark it as glue */
+ bfd_put_32(abfd, 0x03, si->data + 0x0c);
+
+ /* mark the prolog end address */
+ bfd_put_32(abfd, 0x0D, si->data + 0x10);
+ pea_rel->address = 0x10;
+ pea_rel->addend = 0;
+ pea_rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
+ pea_rel->sym_ptr_ptr = fn_pp;
+
+ sec->orelocation = rpp;
+ sec->reloc_count = 4;
+ break;
+ }
+ case RDATA:
+ /* Each external function in a PowerPC PE file has a two word
+ descriptor consisting of:
+ 1. The address of the code.
+ 2. The address of the appropriate .toc
+ We use relocs to build this.
+ */
+
+ si->size = 8;
+ si->data = xmalloc (8);
+ memset (si->data, 0, si->size);
+
+ rpp = xmalloc (sizeof (arelent *) * 3);
+ rpp[0] = rel = xmalloc (sizeof (arelent));
+ rpp[1] = xmalloc (sizeof (arelent));
+ rpp[2] = 0;
+
+ rel->address = 0;
+ rel->addend = 0;
+ rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
+ rel->sym_ptr_ptr = fn_pp;
+
+ rel = rpp[1];
+
+ rel->address = 4;
+ rel->addend = 0;
+ rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
+ rel->sym_ptr_ptr = toc_pp;
+
+ sec->orelocation = rpp;
+ sec->reloc_count = 2;
+ break;
+#endif /* DLLTOOL_PPC */
}
}
for (i = 0; i < NSECS; i++)
{
sinfo *si = secdata + i;
+
bfd_set_section_size (abfd, si->sec, si->size);
bfd_set_section_vma (abfd, si->sec, vma);
+
/* vma += si->size;*/
}
}
for (i = 0; i < NSECS; i++)
{
sinfo *si = secdata + i;
+
if (i == IDATA5 && no_idata5)
continue;
}
-
-static
-bfd *
-make_head()
+static bfd *
+make_head ()
{
FILE * f = fopen ("dh.s", FOPEN_WT);
return bfd_openr ("dh.o", HOW_BFD_TARGET);
}
-static
-bfd * make_tail()
+static bfd *
+make_tail ()
{
FILE * f = fopen ("dt.s", FOPEN_WT);
- fprintf (f, "\t.section .idata$7\n");
- fprintf (f, "\t%s\t__%s_iname\n", ASM_GLOBAL, imp_name_lab);
- fprintf (f, "__%s_iname:\t%s\t\"%s\"\n",
- imp_name_lab, ASM_TEXT, dll_name);
if (!no_idata4)
{
fprintf (f, "\t.section .idata$5\n");
fprintf (f, "\t%s\t0\n", ASM_LONG);
}
+
+#ifdef DLLTOOL_PPC
+ /* Normally, we need to see a null descriptor built in idata$3 to
+ act as the terminator for the list. The ideal way, I suppose,
+ would be to mark this section as a comdat type 2 section, so
+ only one would appear in the final .exe (if our linker supported
+ comdat, that is) or cause it to be inserted by something else (say
+ crt0)
+ */
+
+ fprintf (f, "\t.section .idata$3\n");
+ fprintf (f, "\t%s\t0\n", ASM_LONG);
+ fprintf (f, "\t%s\t0\n", ASM_LONG);
+ fprintf (f, "\t%s\t0\n", ASM_LONG);
+ fprintf (f, "\t%s\t0\n", ASM_LONG);
+ fprintf (f, "\t%s\t0\n", ASM_LONG);
+#endif
+
+#ifdef DLLTOOL_PPC
+ /* Other PowerPC NT compilers use idata$6 for the dllname, so I
+ do too. Original, huh? */
+ fprintf (f, "\t.section .idata$6\n");
+#else
+ fprintf (f, "\t.section .idata$7\n");
+#endif
+
+ fprintf (f, "\t%s\t__%s_iname\n", ASM_GLOBAL, imp_name_lab);
+ fprintf (f, "__%s_iname:\t%s\t\"%s\"\n",
+ imp_name_lab, ASM_TEXT, dll_name);
+
fclose (f);
sprintf (outfile, "-o dt.o dt.s");
/* Run through the information gathered from the .o files and the
.def file and work out the best stuff */
-int
+static int
pfunc (a, b)
- void *a;
- void *b;
+ const void *a;
+ const void *b;
{
export_type *ap = *(export_type **) a;
export_type *bp = *(export_type **) b;
return (ap->ordinal - bp->ordinal);
}
-
-int
+static int
nfunc (a, b)
- void *a;
- void *b;
+ const void *a;
+ const void *b;
{
export_type *ap = *(export_type **) a;
export_type *bp = *(export_type **) b;
return (strcmp (ap->name, bp->name));
}
-static
-void
+static void
remove_null_names (ptr)
export_type **ptr;
{
fill_ordinals (d_export_vec)
export_type **d_export_vec;
{
- int lowest = 0;
-
+ int lowest = -1;
int i;
char *ptr;
+ int size = 65536;
+
qsort (d_export_vec, d_nfuncs, sizeof (export_type *), pfunc);
/* fill in the unset ordinals with ones from our range */
- ptr = (char *) malloc (65536);
+ ptr = (char *) xmalloc (size);
- memset (ptr, 0, 65536);
+ memset (ptr, 0, size);
/* Mark in our large vector all the numbers that are taken */
for (i = 0; i < d_nfuncs; i++)
if (d_export_vec[i]->ordinal != -1)
{
ptr[d_export_vec[i]->ordinal] = 1;
- if (lowest == 0)
- lowest = d_export_vec[i]->ordinal;
+ if (lowest == -1 || d_export_vec[i]->ordinal < lowest)
+ {
+ lowest = d_export_vec[i]->ordinal;
+ }
}
}
/* Start at 1 for compatibility with MS toolchain. */
- if (lowest == 0)
+ if (lowest == -1)
lowest = 1;
+ /* Now fill in ordinals where the user wants us to choose. */
for (i = 0; i < d_nfuncs; i++)
{
if (d_export_vec[i]->ordinal == -1)
{
- int j;
- for (j = lowest; j < 65536; j++)
+ register int j;
+
+ /* First try within or after any user supplied range. */
+ for (j = lowest; j < size; j++)
if (ptr[j] == 0)
{
ptr[j] = 1;
goto done;
}
- for (j = 1; j < lowest; j++)
+ /* Then try before the range. */
+ for (j = lowest; j >0; j--)
if (ptr[j] == 0)
{
ptr[j] = 1;
goto done;
}
done:;
-
}
}
qsort (d_export_vec, d_nfuncs, sizeof (export_type *), pfunc);
-
- /* Work out the lowest ordinal number */
- if (d_export_vec[0])
- d_low_ord = d_export_vec[0]->ordinal;
+ /* Work out the lowest and highest ordinal numbers. */
if (d_nfuncs)
{
+ if (d_export_vec[0])
+ d_low_ord = d_export_vec[0]->ordinal;
if (d_export_vec[d_nfuncs-1])
d_high_ord = d_export_vec[d_nfuncs-1]->ordinal;
}
}
-int alphafunc(av,bv)
-void *av;
-void *bv;
+static int
+alphafunc (av,bv)
+ const void *av;
+ const void *bv;
{
- export_type **a = av;
- export_type **b = bv;
+ const export_type **a = (const export_type **) av;
+ const export_type **b = (const export_type **) bv;
return strcmp ((*a)->name, (*b)->name);
}
-void
+static void
mangle_defs ()
{
/* First work out the minimum ordinal chosen */
}
-
-
-
-
-
/**********************************************************************/
-void
+static void
usage (file, status)
FILE *file;
int status;
#define OPTION_NO_IDATA4 'x'
#define OPTION_NO_IDATA5 'c'
-static struct option long_options[] =
+static const struct option long_options[] =
{
{"nodelete", no_argument, NULL, 'n'},
{"dllname", required_argument, NULL, 'D'},
{0}
};
-
-
int
main (ac, av)
int ac;
verbose = 1;
break;
case 'y':
+#if 0
+ /* We don't currently define YYDEBUG when building
+ defparse.y. */
yydebug = 1;
+#endif
break;
case 'U':
add_underscore = 1;
optind++;
}
-
mangle_defs ();
if (exp_name)
{
/* Make imp_name safe for use as a label. */
char *p;
- imp_name_lab = strdup (imp_name);
- for (p = imp_name_lab; *p; *p++)
+
+ imp_name_lab = xstrdup (imp_name);
+ for (p = imp_name_lab; *p; p++)
{
if (!isalpha (*p) && !isdigit (*p))
*p = '_';