mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-23 03:29:47 +08:00
* elf64-ppc.c (STFD_FR0_0R1, LFD_FR0_0R1, BLR): Define.
(struct ppc_link_hash_table): Add sfpr. (ppc64_elf_link_hash_table_create): Init it. (ppc64_elf_create_dynamic_sections): Split creation of .stub and .glink out to.. (create_linkage_sections): ..here. Make .sfpr too. (ppc64_elf_check_relocs): Call create_linkage_sections, and set dynobj early. (MIN_SAVE_FPR, MAX_SAVE_FPR): Define. (ppc64_elf_func_desc_adjust): Look for missing ._savef* and ._restf* functions, and create as needed. (func_desc_adjust): Only force_local for shared libs. * emulparams/elf64ppc.sh (OTHER_TEXT_SECTIONS): Define.
This commit is contained in:
@ -1,3 +1,18 @@
|
|||||||
|
2002-02-18 Alan Modra <amodra@bigpond.net.au>
|
||||||
|
|
||||||
|
* elf64-ppc.c (STFD_FR0_0R1, LFD_FR0_0R1, BLR): Define.
|
||||||
|
(struct ppc_link_hash_table): Add sfpr.
|
||||||
|
(ppc64_elf_link_hash_table_create): Init it.
|
||||||
|
(ppc64_elf_create_dynamic_sections): Split creation of .stub and
|
||||||
|
.glink out to..
|
||||||
|
(create_linkage_sections): ..here. Make .sfpr too.
|
||||||
|
(ppc64_elf_check_relocs): Call create_linkage_sections, and set
|
||||||
|
dynobj early.
|
||||||
|
(MIN_SAVE_FPR, MAX_SAVE_FPR): Define.
|
||||||
|
(ppc64_elf_func_desc_adjust): Look for missing ._savef* and
|
||||||
|
._restf* functions, and create as needed.
|
||||||
|
(func_desc_adjust): Only force_local for shared libs.
|
||||||
|
|
||||||
2002-02-18 David O'Brien <obrien@FreeBSD.org>
|
2002-02-18 David O'Brien <obrien@FreeBSD.org>
|
||||||
|
|
||||||
* configure.in: Bump version number post 2.12 branching.
|
* configure.in: Bump version number post 2.12 branching.
|
||||||
|
182
bfd/elf64-ppc.c
182
bfd/elf64-ppc.c
@ -51,6 +51,8 @@ static struct bfd_hash_entry *link_hash_newfunc
|
|||||||
PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));
|
PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));
|
||||||
static struct bfd_link_hash_table *ppc64_elf_link_hash_table_create
|
static struct bfd_link_hash_table *ppc64_elf_link_hash_table_create
|
||||||
PARAMS ((bfd *));
|
PARAMS ((bfd *));
|
||||||
|
static boolean create_linkage_sections
|
||||||
|
PARAMS ((bfd *, struct bfd_link_info *));
|
||||||
static boolean create_got_section
|
static boolean create_got_section
|
||||||
PARAMS ((bfd *, struct bfd_link_info *));
|
PARAMS ((bfd *, struct bfd_link_info *));
|
||||||
static boolean ppc64_elf_create_dynamic_sections
|
static boolean ppc64_elf_create_dynamic_sections
|
||||||
@ -153,6 +155,11 @@ static boolean ppc64_elf_finish_dynamic_sections
|
|||||||
#define LIS_R0_0 0x3c000000 /* lis %r0,0 */
|
#define LIS_R0_0 0x3c000000 /* lis %r0,0 */
|
||||||
#define ORI_R0_R0_0 0x60000000 /* ori %r0,%r0,0 */
|
#define ORI_R0_R0_0 0x60000000 /* ori %r0,%r0,0 */
|
||||||
|
|
||||||
|
/* Instructions to save and restore floating point regs. */
|
||||||
|
#define STFD_FR0_0R1 0xd8010000 /* stfd %fr0,0(%r1) */
|
||||||
|
#define LFD_FR0_0R1 0xc8010000 /* lfd %fr0,0(%r1) */
|
||||||
|
#define BLR 0x4e800020 /* blr */
|
||||||
|
|
||||||
/* Since .opd is an array of descriptors and each entry will end up
|
/* Since .opd is an array of descriptors and each entry will end up
|
||||||
with identical R_PPC64_RELATIVE relocs, there is really no need to
|
with identical R_PPC64_RELATIVE relocs, there is really no need to
|
||||||
propagate .opd relocs; The dynamic linker should be taught to
|
propagate .opd relocs; The dynamic linker should be taught to
|
||||||
@ -1719,6 +1726,7 @@ struct ppc_link_hash_table
|
|||||||
asection *srelbss;
|
asection *srelbss;
|
||||||
asection *sstub;
|
asection *sstub;
|
||||||
asection *sglink;
|
asection *sglink;
|
||||||
|
asection *sfpr;
|
||||||
|
|
||||||
/* Set on error. */
|
/* Set on error. */
|
||||||
int plt_overflow;
|
int plt_overflow;
|
||||||
@ -1790,12 +1798,49 @@ ppc64_elf_link_hash_table_create (abfd)
|
|||||||
htab->srelbss = NULL;
|
htab->srelbss = NULL;
|
||||||
htab->sstub = NULL;
|
htab->sstub = NULL;
|
||||||
htab->sglink = NULL;
|
htab->sglink = NULL;
|
||||||
|
htab->sfpr = NULL;
|
||||||
htab->plt_overflow = 0;
|
htab->plt_overflow = 0;
|
||||||
htab->sym_sec.abfd = NULL;
|
htab->sym_sec.abfd = NULL;
|
||||||
|
|
||||||
return &htab->elf.root;
|
return &htab->elf.root;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Create sections for linker generated code. */
|
||||||
|
|
||||||
|
static boolean
|
||||||
|
create_linkage_sections (dynobj, info)
|
||||||
|
bfd *dynobj;
|
||||||
|
struct bfd_link_info *info;
|
||||||
|
{
|
||||||
|
struct ppc_link_hash_table *htab;
|
||||||
|
flagword flags;
|
||||||
|
|
||||||
|
htab = ppc_hash_table (info);
|
||||||
|
|
||||||
|
/* Create .sfpr for code to save and restore fp regs. */
|
||||||
|
flags = (SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_READONLY
|
||||||
|
| SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_LINKER_CREATED);
|
||||||
|
htab->sfpr = bfd_make_section (dynobj, ".sfpr");
|
||||||
|
if (htab->sfpr == NULL
|
||||||
|
|| ! bfd_set_section_flags (dynobj, htab->sfpr, flags)
|
||||||
|
|| ! bfd_set_section_alignment (dynobj, htab->sfpr, 2))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
/* Create .stub and .glink for global linkage functions. */
|
||||||
|
htab->sstub = bfd_make_section (dynobj, ".stub");
|
||||||
|
if (htab->sstub == NULL
|
||||||
|
|| ! bfd_set_section_flags (dynobj, htab->sstub, flags)
|
||||||
|
|| ! bfd_set_section_alignment (dynobj, htab->sstub, 2))
|
||||||
|
return false;
|
||||||
|
htab->sglink = bfd_make_section (dynobj, ".glink");
|
||||||
|
if (htab->sglink == NULL
|
||||||
|
|| ! bfd_set_section_flags (dynobj, htab->sglink, flags)
|
||||||
|
|| ! bfd_set_section_alignment (dynobj, htab->sglink, 2))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/* Create .got and .rela.got sections in DYNOBJ, and set up
|
/* Create .got and .rela.got sections in DYNOBJ, and set up
|
||||||
shortcuts to them in our hash table. */
|
shortcuts to them in our hash table. */
|
||||||
|
|
||||||
@ -1825,8 +1870,7 @@ create_got_section (dynobj, info)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create the .stub and .glink sections as well as the ordinary
|
/* Create the dynamic sections, and set up shortcuts. */
|
||||||
dynamic sections. */
|
|
||||||
|
|
||||||
static boolean
|
static boolean
|
||||||
ppc64_elf_create_dynamic_sections (dynobj, info)
|
ppc64_elf_create_dynamic_sections (dynobj, info)
|
||||||
@ -1834,7 +1878,6 @@ ppc64_elf_create_dynamic_sections (dynobj, info)
|
|||||||
struct bfd_link_info *info;
|
struct bfd_link_info *info;
|
||||||
{
|
{
|
||||||
struct ppc_link_hash_table *htab;
|
struct ppc_link_hash_table *htab;
|
||||||
flagword flags;
|
|
||||||
|
|
||||||
htab = ppc_hash_table (info);
|
htab = ppc_hash_table (info);
|
||||||
if (!htab->sgot && !create_got_section (dynobj, info))
|
if (!htab->sgot && !create_got_section (dynobj, info))
|
||||||
@ -1853,20 +1896,6 @@ ppc64_elf_create_dynamic_sections (dynobj, info)
|
|||||||
|| (!info->shared && !htab->srelbss))
|
|| (!info->shared && !htab->srelbss))
|
||||||
abort ();
|
abort ();
|
||||||
|
|
||||||
/* Create .stub and .glink for global linkage functions. */
|
|
||||||
flags = (SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_READONLY
|
|
||||||
| SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_LINKER_CREATED);
|
|
||||||
htab->sstub = bfd_make_section (dynobj, ".stub");
|
|
||||||
if (htab->sstub == NULL
|
|
||||||
|| ! bfd_set_section_flags (dynobj, htab->sstub, flags)
|
|
||||||
|| ! bfd_set_section_alignment (dynobj, htab->sstub, 2))
|
|
||||||
return false;
|
|
||||||
htab->sglink = bfd_make_section (dynobj, ".glink");
|
|
||||||
if (htab->sglink == NULL
|
|
||||||
|| ! bfd_set_section_flags (dynobj, htab->sglink, flags)
|
|
||||||
|| ! bfd_set_section_alignment (dynobj, htab->sglink, 3))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1955,6 +1984,12 @@ ppc64_elf_check_relocs (abfd, info, sec, relocs)
|
|||||||
sreloc = NULL;
|
sreloc = NULL;
|
||||||
is_opd = strcmp (bfd_get_section_name (abfd, sec), ".opd") == 0;
|
is_opd = strcmp (bfd_get_section_name (abfd, sec), ".opd") == 0;
|
||||||
|
|
||||||
|
if (htab->elf.dynobj == NULL)
|
||||||
|
htab->elf.dynobj = abfd;
|
||||||
|
if (htab->sfpr == NULL
|
||||||
|
&& !create_linkage_sections (htab->elf.dynobj, info))
|
||||||
|
return false;
|
||||||
|
|
||||||
rel_end = relocs + sec->reloc_count;
|
rel_end = relocs + sec->reloc_count;
|
||||||
for (rel = relocs; rel < rel_end; rel++)
|
for (rel = relocs; rel < rel_end; rel++)
|
||||||
{
|
{
|
||||||
@ -1980,13 +2015,9 @@ ppc64_elf_check_relocs (abfd, info, sec, relocs)
|
|||||||
case R_PPC64_GOT16_LO_DS:
|
case R_PPC64_GOT16_LO_DS:
|
||||||
|
|
||||||
/* This symbol requires a global offset table entry. */
|
/* This symbol requires a global offset table entry. */
|
||||||
if (htab->sgot == NULL)
|
if (htab->sgot == NULL
|
||||||
{
|
&& !create_got_section (htab->elf.dynobj, info))
|
||||||
if (htab->elf.dynobj == NULL)
|
return false;
|
||||||
htab->elf.dynobj = abfd;
|
|
||||||
if (!create_got_section (htab->elf.dynobj, info))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (h != NULL)
|
if (h != NULL)
|
||||||
{
|
{
|
||||||
@ -2197,9 +2228,6 @@ ppc64_elf_check_relocs (abfd, info, sec, relocs)
|
|||||||
bfd_set_error (bfd_error_bad_value);
|
bfd_set_error (bfd_error_bad_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (htab->elf.dynobj == NULL)
|
|
||||||
htab->elf.dynobj = abfd;
|
|
||||||
|
|
||||||
dynobj = htab->elf.dynobj;
|
dynobj = htab->elf.dynobj;
|
||||||
sreloc = bfd_get_section_by_name (dynobj, name);
|
sreloc = bfd_get_section_by_name (dynobj, name);
|
||||||
if (sreloc == NULL)
|
if (sreloc == NULL)
|
||||||
@ -2554,25 +2582,117 @@ func_desc_adjust (h, inf)
|
|||||||
been imported from another library. Function code syms that
|
been imported from another library. Function code syms that
|
||||||
are really in the library we must leave global to prevent the
|
are really in the library we must leave global to prevent the
|
||||||
linker dragging in a definition from a static library. */
|
linker dragging in a definition from a static library. */
|
||||||
force_local = (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0;
|
force_local = ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0
|
||||||
|
&& info->shared);
|
||||||
_bfd_elf_link_hash_hide_symbol (info, h, force_local);
|
_bfd_elf_link_hash_hide_symbol (info, h, force_local);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define MIN_SAVE_FPR 14
|
||||||
|
#define MAX_SAVE_FPR 31
|
||||||
|
|
||||||
/* Called near the start of bfd_elf_size_dynamic_sections. We use
|
/* Called near the start of bfd_elf_size_dynamic_sections. We use
|
||||||
this hook to transfer dynamic linking information gathered so far
|
this hook to a) provide some gcc support functions, and b) transfer
|
||||||
on function code symbol entries, to their corresponding function
|
dynamic linking information gathered so far on function code symbol
|
||||||
descriptor symbol entries. */
|
entries, to their corresponding function descriptor symbol entries. */
|
||||||
static boolean
|
static boolean
|
||||||
ppc64_elf_func_desc_adjust (obfd, info)
|
ppc64_elf_func_desc_adjust (obfd, info)
|
||||||
bfd *obfd ATTRIBUTE_UNUSED;
|
bfd *obfd ATTRIBUTE_UNUSED;
|
||||||
struct bfd_link_info *info;
|
struct bfd_link_info *info;
|
||||||
{
|
{
|
||||||
struct ppc_link_hash_table *htab;
|
struct ppc_link_hash_table *htab;
|
||||||
|
unsigned int lowest_savef = MAX_SAVE_FPR + 2;
|
||||||
|
unsigned int lowest_restf = MAX_SAVE_FPR + 2;
|
||||||
|
unsigned int i;
|
||||||
|
struct elf_link_hash_entry *h;
|
||||||
|
char sym[10];
|
||||||
|
|
||||||
htab = ppc_hash_table (info);
|
htab = ppc_hash_table (info);
|
||||||
|
|
||||||
|
if (htab->sfpr == NULL)
|
||||||
|
/* We don't have any relocs. */
|
||||||
|
return true;
|
||||||
|
|
||||||
|
/* First provide any missing ._savef* and ._restf* functions. */
|
||||||
|
memcpy (sym, "._savef14", 10);
|
||||||
|
for (i = MIN_SAVE_FPR; i <= MAX_SAVE_FPR; i++)
|
||||||
|
{
|
||||||
|
sym[7] = i / 10 + '0';
|
||||||
|
sym[8] = i % 10 + '0';
|
||||||
|
h = elf_link_hash_lookup (&htab->elf, sym, false, false, true);
|
||||||
|
if (h != NULL
|
||||||
|
&& h->root.type == bfd_link_hash_undefined)
|
||||||
|
{
|
||||||
|
if (lowest_savef > i)
|
||||||
|
lowest_savef = i;
|
||||||
|
h->root.type = bfd_link_hash_defined;
|
||||||
|
h->root.u.def.section = htab->sfpr;
|
||||||
|
h->root.u.def.value = (i - lowest_savef) * 4;
|
||||||
|
h->type = STT_FUNC;
|
||||||
|
h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
|
||||||
|
_bfd_elf_link_hash_hide_symbol (info, h, info->shared);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy (sym, "._restf14", 10);
|
||||||
|
for (i = MIN_SAVE_FPR; i <= MAX_SAVE_FPR; i++)
|
||||||
|
{
|
||||||
|
sym[7] = i / 10 + '0';
|
||||||
|
sym[8] = i % 10 + '0';
|
||||||
|
h = elf_link_hash_lookup (&htab->elf, sym, false, false, true);
|
||||||
|
if (h != NULL
|
||||||
|
&& h->root.type == bfd_link_hash_undefined)
|
||||||
|
{
|
||||||
|
if (lowest_restf > i)
|
||||||
|
lowest_restf = i;
|
||||||
|
h->root.type = bfd_link_hash_defined;
|
||||||
|
h->root.u.def.section = htab->sfpr;
|
||||||
|
h->root.u.def.value = ((MAX_SAVE_FPR + 2 - lowest_savef) * 4
|
||||||
|
+ (i - lowest_restf) * 4);
|
||||||
|
h->type = STT_FUNC;
|
||||||
|
h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
|
||||||
|
_bfd_elf_link_hash_hide_symbol (info, h, info->shared);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
htab->sfpr->_raw_size = ((MAX_SAVE_FPR + 2 - lowest_savef) * 4
|
||||||
|
+ (MAX_SAVE_FPR + 2 - lowest_restf) * 4);
|
||||||
|
|
||||||
|
if (htab->sfpr->_raw_size == 0)
|
||||||
|
{
|
||||||
|
_bfd_strip_section_from_output (info, htab->sfpr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bfd_byte *p = (bfd_byte *) bfd_alloc (htab->elf.dynobj,
|
||||||
|
htab->sfpr->_raw_size);
|
||||||
|
if (p == NULL)
|
||||||
|
return false;
|
||||||
|
htab->sfpr->contents = p;
|
||||||
|
|
||||||
|
for (i = lowest_savef; i <= MAX_SAVE_FPR; i++)
|
||||||
|
{
|
||||||
|
unsigned int fpr = i << 21;
|
||||||
|
unsigned int stackoff = (1 << 16) - (MAX_SAVE_FPR + 1 - i) * 8;
|
||||||
|
bfd_put_32 (htab->elf.dynobj, STFD_FR0_0R1 + fpr + stackoff, p);
|
||||||
|
p += 4;
|
||||||
|
}
|
||||||
|
bfd_put_32 (htab->elf.dynobj, BLR, p);
|
||||||
|
p += 4;
|
||||||
|
|
||||||
|
for (i = lowest_restf; i <= MAX_SAVE_FPR; i++)
|
||||||
|
{
|
||||||
|
unsigned int fpr = i << 21;
|
||||||
|
unsigned int stackoff = (1 << 16) - (MAX_SAVE_FPR + 1 - i) * 8;
|
||||||
|
bfd_put_32 (htab->elf.dynobj, LFD_FR0_0R1 + fpr + stackoff, p);
|
||||||
|
p += 4;
|
||||||
|
}
|
||||||
|
bfd_put_32 (htab->elf.dynobj, BLR, p);
|
||||||
|
p += 4;
|
||||||
|
}
|
||||||
|
|
||||||
elf_link_hash_traverse (&htab->elf, func_desc_adjust, (PTR) info);
|
elf_link_hash_traverse (&htab->elf, func_desc_adjust, (PTR) info);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
|
2002-02-18 Alan Modra <amodra@bigpond.net.au>
|
||||||
|
|
||||||
|
* emulparams/elf64ppc.sh (OTHER_TEXT_SECTIONS): Define.
|
||||||
|
|
||||||
2002-02-18 David O'Brien <obrien@FreeBSD.org>
|
2002-02-18 David O'Brien <obrien@FreeBSD.org>
|
||||||
|
|
||||||
* Makefile.in: Add new files earmelf_fbsd, eelf32ppc_fbsd,
|
* Makefile.in: Add new files earmelf_fbsd, eelf32ppc_fbsd,
|
||||||
|
@ -15,6 +15,7 @@ CTOR_START='PROVIDE (__CTOR_LIST__ = .); PROVIDE (___CTOR_LIST__ = .);'
|
|||||||
CTOR_END='PROVIDE (__CTOR_END__ = .); PROVIDE (___CTOR_END__ = .);'
|
CTOR_END='PROVIDE (__CTOR_END__ = .); PROVIDE (___CTOR_END__ = .);'
|
||||||
DTOR_START='PROVIDE (__DTOR_LIST__ = .); PROVIDE (___DTOR_LIST__ = .);'
|
DTOR_START='PROVIDE (__DTOR_LIST__ = .); PROVIDE (___DTOR_LIST__ = .);'
|
||||||
DTOR_END='PROVIDE (__DTOR_END__ = .); PROVIDE (___DTOR_END__ = .);'
|
DTOR_END='PROVIDE (__DTOR_END__ = .); PROVIDE (___DTOR_END__ = .);'
|
||||||
|
OTHER_TEXT_SECTIONS="*(.sfpr .glink)"
|
||||||
BSS_PLT=
|
BSS_PLT=
|
||||||
OTHER_BSS_SYMBOLS="
|
OTHER_BSS_SYMBOLS="
|
||||||
.tocbss ${RELOCATING-0}${RELOCATING+ALIGN(8)} : { *(.tocbss)}"
|
.tocbss ${RELOCATING-0}${RELOCATING+ALIGN(8)} : { *(.tocbss)}"
|
||||||
|
Reference in New Issue
Block a user