PowerPC changes

This commit is contained in:
Kim Knuttila 1995-12-01 02:08:19 +00:00
parent 590662481c
commit b10f8e5e5c
2 changed files with 308 additions and 31 deletions

View File

@ -1,3 +1,13 @@
Thu Nov 30 20:26:02 1995 Kim Knuttila <krk@cygnus.com>
* dlltool.c (ppc_jtab): The binary glue for PowerPC dll linkage,
including the return instruction.
sinfo: added a preferred alignment field.
(secdata): section data for the PowerPC version.
(make_one_lib_file): More symbols, More sections (pdata, rdata)
(make_tail): Use idata$6 instead of idata$7 for ppc. Also added a
NULL idata$3 descriptor (temporary).
Tue Nov 28 17:23:44 1995 Doug Evans <dje@canuck.cygnus.com>
* dlltool.c (fill_ordinals): Don't reference d_export_vec if

View File

@ -237,10 +237,27 @@ unsigned char i386_jtab[] = { 0xff, 0x25, 0x00, 0x00, 0x00, 0x00, 0x90, 0x90};
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) */
unsigned char ppc_jtab[] = { 0xff, 0x25, 0x00, 0x00, 0x00, 0x00, 0x90, 0x90};
/* 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. */
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 */
};
/* the glue instruction, picks up the toc from the stw in */
/* the above code: "lwz r2,4(r1)" */
bfd_vma ppc_glue_insn = 0x80410004;
char outfile[PATHMAX];
struct mac
@ -282,7 +299,7 @@ mtable[]
{
#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}
@ -1112,6 +1129,7 @@ typedef struct
int id;
const char *name;
int flags;
int align;
asection *sec;
asymbol *sym;
asymbol **sympp;
@ -1120,6 +1138,8 @@ typedef struct
} sinfo;
#ifndef DLLTOOL_PPC
#define TEXT 0
#define DATA 1
#define BSS 2
@ -1127,20 +1147,54 @@ typedef struct
#define IDATA5 4
#define IDATA4 5
#define IDATA6 6
#define PDATA 7
#define RDATA 8
#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, 3},
{ 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, ".rdata", 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
@ -1164,11 +1218,25 @@ __imp_GetFileVersionInfoSizeW@8:
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 );
@ -1177,10 +1245,11 @@ const char *name;
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)
{
@ -1235,7 +1304,22 @@ int i;
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
asymbol *function_name; /* ".." functionName */
asymbol **fn_pp;
asymbol *toc_symbol; /* The .toc symbol */
asymbol **toc_pp;
/* one symbol for each section, 2 extra + a null */
asymbol *ptrs[NSECS+3+EXTRA+1];
char *outname = xmalloc (10);
int oidx = 0;
@ -1243,7 +1327,8 @@ int i;
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);
}
@ -1251,6 +1336,7 @@ int i;
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;
@ -1260,8 +1346,10 @@ int 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;
@ -1274,16 +1362,23 @@ int i;
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
*/
if (machine == MPPC)
exp_label->section = secdata[RDATA].sec;
else
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;
@ -1297,9 +1392,34 @@ int i;
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) */
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 */
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++)
@ -1323,8 +1443,18 @@ int 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;
@ -1333,7 +1463,6 @@ int i;
/* An idata$4 or idata$5 is one word long, and has an
rva to idata$6 */
si->data = xmalloc (4);
si->size = 4;
@ -1386,6 +1515,115 @@ int i;
sec->orelocation = rpp;
sec->reloc_count = 1;
break;
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;
}
}
@ -1395,8 +1633,10 @@ int i;
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;*/
}
}
@ -1404,6 +1644,7 @@ int i;
for (i = 0; i < NSECS; i++)
{
sinfo *si = secdata + i;
if (i == IDATA5 && no_idata5)
continue;
@ -1424,8 +1665,7 @@ int i;
}
static
bfd *
static bfd *
make_head()
{
FILE * f = fopen ("dh.s", FOPEN_WT);
@ -1477,11 +1717,19 @@ make_head()
return bfd_openr ("dh.o", HOW_BFD_TARGET);
}
static
bfd * make_tail()
static bfd *
make_tail()
{
FILE * f = fopen ("dt.s", FOPEN_WT);
#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);
@ -1496,6 +1744,25 @@ bfd * make_tail()
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
fclose (f);
sprintf (outfile, "-o dt.o dt.s");