PowerPC changes
This commit is contained in:
parent
590662481c
commit
b10f8e5e5c
@ -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
|
||||
|
@ -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");
|
||||
|
Loading…
x
Reference in New Issue
Block a user