forked from Imagelibrary/binutils-gdb
bfd/
* xcofflink.c (xcoff_link_create_extra_sections): Don't create a .loader section for relocatable links. (xcoff_need_ldrel_p): New function. (xcoff_mark): Use it. (bfd_xcoff_link_count_reloc): Only count loader relocs if there's a loader section. (xcoff_build_ldsym): New function, split out from... (xcoff_build_ldsyms): ...here. Rename to... (xcoff_post_gc_symbol): ...this. Only export symbols, and only call xcoff_build_ldsym, if there's a loader section. (xcoff_build_loader_section): New function, extracted verbatim from... (bfd_xcoff_size_dynamic_sections): ...here. Only call it if there's a loader section. Only add an __rtinit loader symbol if there's a loader section. Update after above name change. (xcoff_symbol_section, xcoff_create_ldrel): New functions. (bfd_link_input_bfd): Use xcoff_need_ldrel_p, xcoff_symbol_section and xcoff_create_ldrel. (xcoff_write_global_symbol): Use xcoff_create_ldrel. (xcoff_reloc_link_order): Likewise, but only call it if there's a loader section. Use xcoff_symbol_section. (_bfd_xcoff_bfd_final_link): Only use fdinfo.ldrel and fdinfo.ldsym if there's a loader section. ld/testsuite/ * ld-powerpc/aix-rel-1.s, ld-powerpc/aix-rel-1.od: New test. * ld-powerpc/aix52.exp: Run it.
This commit is contained in:
794
bfd/xcofflink.c
794
bfd/xcofflink.c
@@ -814,7 +814,8 @@ xcoff_link_create_extra_sections (bfd * abfd, struct bfd_link_info *info)
|
||||
won't work if we're producing an XCOFF output file with no
|
||||
XCOFF input files. FIXME. */
|
||||
|
||||
if (xcoff_hash_table (info)->loader_section == NULL)
|
||||
if (!info->relocatable
|
||||
&& xcoff_hash_table (info)->loader_section == NULL)
|
||||
{
|
||||
asection *lsec;
|
||||
flagword flags = SEC_HAS_CONTENTS | SEC_IN_MEMORY;
|
||||
@@ -2409,6 +2410,59 @@ xcoff_auto_export_p (struct xcoff_link_hash_entry *h,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Return true if relocation REL needs to be copied to the .loader section.
|
||||
If REL is against a global symbol, H is that symbol, otherwise it
|
||||
is null. */
|
||||
|
||||
static bfd_boolean
|
||||
xcoff_need_ldrel_p (struct bfd_link_info *info, struct internal_reloc *rel,
|
||||
struct xcoff_link_hash_entry *h)
|
||||
{
|
||||
if (!xcoff_hash_table (info)->loader_section)
|
||||
return FALSE;
|
||||
|
||||
switch (rel->r_type)
|
||||
{
|
||||
case R_TOC:
|
||||
case R_GL:
|
||||
case R_TCL:
|
||||
case R_TRL:
|
||||
case R_TRLA:
|
||||
/* We should never need a .loader reloc for a TOC-relative reloc. */
|
||||
return FALSE;
|
||||
|
||||
default:
|
||||
/* In this case, relocations against defined symbols can be resolved
|
||||
statically. */
|
||||
if (h == NULL
|
||||
|| h->root.type == bfd_link_hash_defined
|
||||
|| h->root.type == bfd_link_hash_defweak
|
||||
|| h->root.type == bfd_link_hash_common)
|
||||
return FALSE;
|
||||
|
||||
/* We will always provide a local definition of function symbols,
|
||||
even if we don't have one yet. */
|
||||
if ((h->flags & XCOFF_CALLED) != 0)
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
|
||||
case R_POS:
|
||||
case R_NEG:
|
||||
case R_RL:
|
||||
case R_RLA:
|
||||
/* Absolute relocations against absolute symbols can be
|
||||
resolved statically. */
|
||||
if (h != NULL
|
||||
&& (h->root.type == bfd_link_hash_defined
|
||||
|| h->root.type == bfd_link_hash_defweak)
|
||||
&& bfd_is_abs_section (h->root.u.def.section))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Mark a symbol as not being garbage, including the section in which
|
||||
it is defined. */
|
||||
|
||||
@@ -2681,39 +2735,11 @@ xcoff_mark (struct bfd_link_info *info, asection *sec)
|
||||
|
||||
/* See if this reloc needs to be copied into the .loader
|
||||
section. */
|
||||
switch (rel->r_type)
|
||||
if (xcoff_need_ldrel_p (info, rel, h))
|
||||
{
|
||||
default:
|
||||
if (h == NULL
|
||||
|| h->root.type == bfd_link_hash_defined
|
||||
|| h->root.type == bfd_link_hash_defweak
|
||||
|| h->root.type == bfd_link_hash_common
|
||||
/* We will always provide a local definition of
|
||||
function symbols. */
|
||||
|| (h->flags & XCOFF_CALLED) != 0)
|
||||
break;
|
||||
/* Fall through. */
|
||||
case R_POS:
|
||||
case R_NEG:
|
||||
case R_RL:
|
||||
case R_RLA:
|
||||
if (h != NULL
|
||||
&& (h->root.type == bfd_link_hash_defined
|
||||
|| h->root.type == bfd_link_hash_defweak)
|
||||
&& bfd_is_abs_section (h->root.u.def.section))
|
||||
break;
|
||||
++xcoff_hash_table (info)->ldrel_count;
|
||||
if (h != NULL)
|
||||
h->flags |= XCOFF_LDREL;
|
||||
break;
|
||||
case R_TOC:
|
||||
case R_GL:
|
||||
case R_TCL:
|
||||
case R_TRL:
|
||||
case R_TRLA:
|
||||
/* We should never need a .loader reloc for a TOC
|
||||
relative reloc. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2941,8 +2967,12 @@ bfd_xcoff_link_count_reloc (bfd *output_bfd,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
h->flags |= XCOFF_REF_REGULAR | XCOFF_LDREL;
|
||||
++xcoff_hash_table (info)->ldrel_count;
|
||||
h->flags |= XCOFF_REF_REGULAR;
|
||||
if (xcoff_hash_table (info)->loader_section)
|
||||
{
|
||||
h->flags |= XCOFF_LDREL;
|
||||
++xcoff_hash_table (info)->ldrel_count;
|
||||
}
|
||||
|
||||
/* Mark the symbol to avoid garbage collection. */
|
||||
if (! xcoff_mark_symbol (info, h))
|
||||
@@ -3024,101 +3054,34 @@ xcoff_final_definition_p (bfd *input_bfd, struct xcoff_link_hash_entry *h,
|
||||
}
|
||||
}
|
||||
|
||||
/* See if H should have a loader symbol associated with it. */
|
||||
|
||||
static bfd_boolean
|
||||
xcoff_build_ldsyms (struct xcoff_link_hash_entry *h, void * p)
|
||||
xcoff_build_ldsym (struct xcoff_loader_info *ldinfo,
|
||||
struct xcoff_link_hash_entry *h)
|
||||
{
|
||||
struct xcoff_loader_info *ldinfo = (struct xcoff_loader_info *) p;
|
||||
bfd_size_type amt;
|
||||
|
||||
if (h->root.type == bfd_link_hash_warning)
|
||||
h = (struct xcoff_link_hash_entry *) h->root.u.i.link;
|
||||
|
||||
/* __rtinit, this symbol has special handling. */
|
||||
if (h->flags & XCOFF_RTINIT)
|
||||
return TRUE;
|
||||
|
||||
/* If this is a final link, and the symbol was defined as a common
|
||||
symbol in a regular object file, and there was no definition in
|
||||
any dynamic object, then the linker will have allocated space for
|
||||
the symbol in a common section but the XCOFF_DEF_REGULAR flag
|
||||
will not have been set. */
|
||||
if (h->root.type == bfd_link_hash_defined
|
||||
&& (h->flags & XCOFF_DEF_REGULAR) == 0
|
||||
&& (h->flags & XCOFF_REF_REGULAR) != 0
|
||||
&& (h->flags & XCOFF_DEF_DYNAMIC) == 0
|
||||
&& (bfd_is_abs_section (h->root.u.def.section)
|
||||
|| (h->root.u.def.section->owner->flags & DYNAMIC) == 0))
|
||||
h->flags |= XCOFF_DEF_REGULAR;
|
||||
|
||||
/* If all defined symbols should be exported, mark them now. We
|
||||
don't want to export the actual functions, just the function
|
||||
descriptors. */
|
||||
if (xcoff_auto_export_p (h, ldinfo->auto_export_flags))
|
||||
h->flags |= XCOFF_EXPORT;
|
||||
|
||||
/* We don't want to garbage collect symbols which are not defined in
|
||||
XCOFF files. This is a convenient place to mark them. */
|
||||
if (xcoff_hash_table (ldinfo->info)->gc
|
||||
&& (h->flags & XCOFF_MARK) == 0
|
||||
&& (h->root.type == bfd_link_hash_defined
|
||||
|| h->root.type == bfd_link_hash_defweak)
|
||||
&& (h->root.u.def.section->owner == NULL
|
||||
|| (h->root.u.def.section->owner->xvec
|
||||
!= ldinfo->info->output_bfd->xvec)))
|
||||
h->flags |= XCOFF_MARK;
|
||||
|
||||
/* If this symbol is exported, but not defined, we need to try to
|
||||
define it. */
|
||||
/* Warn if this symbol is exported but not defined. */
|
||||
if ((h->flags & XCOFF_EXPORT) != 0
|
||||
&& (h->flags & XCOFF_WAS_UNDEFINED) != 0)
|
||||
{
|
||||
(*_bfd_error_handler)
|
||||
(_("warning: attempt to export undefined symbol `%s'"),
|
||||
h->root.root.string);
|
||||
h->ldsym = NULL;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* If this is still a common symbol, and it wasn't garbage
|
||||
collected, we need to actually allocate space for it in the .bss
|
||||
section. */
|
||||
if (h->root.type == bfd_link_hash_common
|
||||
&& (! xcoff_hash_table (ldinfo->info)->gc
|
||||
|| (h->flags & XCOFF_MARK) != 0)
|
||||
&& h->root.u.c.p->section->size == 0)
|
||||
{
|
||||
BFD_ASSERT (bfd_is_com_section (h->root.u.c.p->section));
|
||||
h->root.u.c.p->section->size = h->root.u.c.size;
|
||||
}
|
||||
|
||||
/* We need to add a symbol to the .loader section if it is mentioned
|
||||
in a reloc which we are copying to the .loader section and it was
|
||||
not defined or common, or if it is the entry point, or if it is
|
||||
being exported. */
|
||||
|
||||
if (((h->flags & XCOFF_LDREL) == 0
|
||||
|| h->root.type == bfd_link_hash_defined
|
||||
|| h->root.type == bfd_link_hash_defweak
|
||||
|| h->root.type == bfd_link_hash_common)
|
||||
&& (h->flags & XCOFF_ENTRY) == 0
|
||||
&& (h->flags & XCOFF_EXPORT) == 0)
|
||||
{
|
||||
h->ldsym = NULL;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* We don't need to add this symbol if we did garbage collection and
|
||||
we did not mark this symbol. */
|
||||
if (xcoff_hash_table (ldinfo->info)->gc
|
||||
&& (h->flags & XCOFF_MARK) == 0)
|
||||
{
|
||||
h->ldsym = NULL;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* We may have already processed this symbol due to the recursive
|
||||
call above. */
|
||||
if ((h->flags & XCOFF_BUILT_LDSYM) != 0)
|
||||
return TRUE;
|
||||
|
||||
/* We need to add this symbol to the .loader symbols. */
|
||||
@@ -3151,6 +3114,71 @@ xcoff_build_ldsyms (struct xcoff_link_hash_entry *h, void * p)
|
||||
return FALSE;
|
||||
|
||||
h->flags |= XCOFF_BUILT_LDSYM;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* An xcoff_htab_traverse callback that is called for each symbol
|
||||
once garbage collection is complete. */
|
||||
|
||||
static bfd_boolean
|
||||
xcoff_post_gc_symbol (struct xcoff_link_hash_entry *h, void * p)
|
||||
{
|
||||
struct xcoff_loader_info *ldinfo = (struct xcoff_loader_info *) p;
|
||||
|
||||
if (h->root.type == bfd_link_hash_warning)
|
||||
h = (struct xcoff_link_hash_entry *) h->root.u.i.link;
|
||||
|
||||
/* __rtinit, this symbol has special handling. */
|
||||
if (h->flags & XCOFF_RTINIT)
|
||||
return TRUE;
|
||||
|
||||
/* If this is a final link, and the symbol was defined as a common
|
||||
symbol in a regular object file, and there was no definition in
|
||||
any dynamic object, then the linker will have allocated space for
|
||||
the symbol in a common section but the XCOFF_DEF_REGULAR flag
|
||||
will not have been set. */
|
||||
if (h->root.type == bfd_link_hash_defined
|
||||
&& (h->flags & XCOFF_DEF_REGULAR) == 0
|
||||
&& (h->flags & XCOFF_REF_REGULAR) != 0
|
||||
&& (h->flags & XCOFF_DEF_DYNAMIC) == 0
|
||||
&& (bfd_is_abs_section (h->root.u.def.section)
|
||||
|| (h->root.u.def.section->owner->flags & DYNAMIC) == 0))
|
||||
h->flags |= XCOFF_DEF_REGULAR;
|
||||
|
||||
/* We don't want to garbage collect symbols which are not defined in
|
||||
XCOFF files. This is a convenient place to mark them. */
|
||||
if (xcoff_hash_table (ldinfo->info)->gc
|
||||
&& (h->flags & XCOFF_MARK) == 0
|
||||
&& (h->root.type == bfd_link_hash_defined
|
||||
|| h->root.type == bfd_link_hash_defweak)
|
||||
&& (h->root.u.def.section->owner == NULL
|
||||
|| (h->root.u.def.section->owner->xvec
|
||||
!= ldinfo->info->output_bfd->xvec)))
|
||||
h->flags |= XCOFF_MARK;
|
||||
|
||||
/* Skip discarded symbols. */
|
||||
if (xcoff_hash_table (ldinfo->info)->gc
|
||||
&& (h->flags & XCOFF_MARK) == 0)
|
||||
return TRUE;
|
||||
|
||||
/* If this is still a common symbol, and it wasn't garbage
|
||||
collected, we need to actually allocate space for it in the .bss
|
||||
section. */
|
||||
if (h->root.type == bfd_link_hash_common
|
||||
&& h->root.u.c.p->section->size == 0)
|
||||
{
|
||||
BFD_ASSERT (bfd_is_com_section (h->root.u.c.p->section));
|
||||
h->root.u.c.p->section->size = h->root.u.c.size;
|
||||
}
|
||||
|
||||
if (xcoff_hash_table (ldinfo->info)->loader_section)
|
||||
{
|
||||
if (xcoff_auto_export_p (h, ldinfo->auto_export_flags))
|
||||
h->flags |= XCOFF_EXPORT;
|
||||
|
||||
if (!xcoff_build_ldsym (ldinfo, h))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@@ -3246,6 +3274,119 @@ xcoff_keep_symbol_p (struct bfd_link_info *info, bfd *input_bfd,
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Lay out the .loader section, filling in the header and the import paths.
|
||||
LIBPATH is as for bfd_xcoff_size_dynamic_sections. */
|
||||
|
||||
static bfd_boolean
|
||||
xcoff_build_loader_section (struct xcoff_loader_info *ldinfo,
|
||||
const char *libpath)
|
||||
{
|
||||
bfd *output_bfd;
|
||||
struct xcoff_link_hash_table *htab;
|
||||
struct internal_ldhdr *ldhdr;
|
||||
struct xcoff_import_file *fl;
|
||||
bfd_size_type stoff;
|
||||
size_t impsize, impcount;
|
||||
asection *lsec;
|
||||
char *out;
|
||||
|
||||
/* Work out the size of the import file names. Each import file ID
|
||||
consists of three null terminated strings: the path, the file
|
||||
name, and the archive member name. The first entry in the list
|
||||
of names is the path to use to find objects, which the linker has
|
||||
passed in as the libpath argument. For some reason, the path
|
||||
entry in the other import file names appears to always be empty. */
|
||||
output_bfd = ldinfo->output_bfd;
|
||||
htab = xcoff_hash_table (ldinfo->info);
|
||||
impsize = strlen (libpath) + 3;
|
||||
impcount = 1;
|
||||
for (fl = htab->imports; fl != NULL; fl = fl->next)
|
||||
{
|
||||
++impcount;
|
||||
impsize += (strlen (fl->path)
|
||||
+ strlen (fl->file)
|
||||
+ strlen (fl->member)
|
||||
+ 3);
|
||||
}
|
||||
|
||||
/* Set up the .loader section header. */
|
||||
ldhdr = &htab->ldhdr;
|
||||
ldhdr->l_version = bfd_xcoff_ldhdr_version(output_bfd);
|
||||
ldhdr->l_nsyms = ldinfo->ldsym_count;
|
||||
ldhdr->l_nreloc = htab->ldrel_count;
|
||||
ldhdr->l_istlen = impsize;
|
||||
ldhdr->l_nimpid = impcount;
|
||||
ldhdr->l_impoff = (bfd_xcoff_ldhdrsz (output_bfd)
|
||||
+ ldhdr->l_nsyms * bfd_xcoff_ldsymsz (output_bfd)
|
||||
+ ldhdr->l_nreloc * bfd_xcoff_ldrelsz (output_bfd));
|
||||
ldhdr->l_stlen = ldinfo->string_size;
|
||||
stoff = ldhdr->l_impoff + impsize;
|
||||
if (ldinfo->string_size == 0)
|
||||
ldhdr->l_stoff = 0;
|
||||
else
|
||||
ldhdr->l_stoff = stoff;
|
||||
|
||||
/* 64 bit elements to ldhdr
|
||||
The swap out routine for 32 bit will ignore them.
|
||||
Nothing fancy, symbols come after the header and relocs come
|
||||
after symbols. */
|
||||
ldhdr->l_symoff = bfd_xcoff_ldhdrsz (output_bfd);
|
||||
ldhdr->l_rldoff = (bfd_xcoff_ldhdrsz (output_bfd)
|
||||
+ ldhdr->l_nsyms * bfd_xcoff_ldsymsz (output_bfd));
|
||||
|
||||
/* We now know the final size of the .loader section. Allocate
|
||||
space for it. */
|
||||
lsec = htab->loader_section;
|
||||
lsec->size = stoff + ldhdr->l_stlen;
|
||||
lsec->contents = bfd_zalloc (output_bfd, lsec->size);
|
||||
if (lsec->contents == NULL)
|
||||
return FALSE;
|
||||
|
||||
/* Set up the header. */
|
||||
bfd_xcoff_swap_ldhdr_out (output_bfd, ldhdr, lsec->contents);
|
||||
|
||||
/* Set up the import file names. */
|
||||
out = (char *) lsec->contents + ldhdr->l_impoff;
|
||||
strcpy (out, libpath);
|
||||
out += strlen (libpath) + 1;
|
||||
*out++ = '\0';
|
||||
*out++ = '\0';
|
||||
for (fl = htab->imports; fl != NULL; fl = fl->next)
|
||||
{
|
||||
const char *s;
|
||||
|
||||
s = fl->path;
|
||||
while ((*out++ = *s++) != '\0')
|
||||
;
|
||||
s = fl->file;
|
||||
while ((*out++ = *s++) != '\0')
|
||||
;
|
||||
s = fl->member;
|
||||
while ((*out++ = *s++) != '\0')
|
||||
;
|
||||
}
|
||||
|
||||
BFD_ASSERT ((bfd_size_type) ((bfd_byte *) out - lsec->contents) == stoff);
|
||||
|
||||
/* Set up the symbol string table. */
|
||||
if (ldinfo->string_size > 0)
|
||||
{
|
||||
memcpy (out, ldinfo->strings, ldinfo->string_size);
|
||||
free (ldinfo->strings);
|
||||
ldinfo->strings = NULL;
|
||||
}
|
||||
|
||||
/* We can't set up the symbol table or the relocs yet, because we
|
||||
don't yet know the final position of the various sections. The
|
||||
.loader symbols are written out when the corresponding normal
|
||||
symbols are written out in xcoff_link_input_bfd or
|
||||
xcoff_write_global_symbol. The .loader relocs are written out
|
||||
when the corresponding normal relocs are handled in
|
||||
xcoff_link_input_bfd. */
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Build the .loader section. This is called by the XCOFF linker
|
||||
emulation before_allocation routine. We must set the size of the
|
||||
.loader section before the linker lays out the output file.
|
||||
@@ -3277,14 +3418,8 @@ bfd_xcoff_size_dynamic_sections (bfd *output_bfd,
|
||||
asection **special_sections,
|
||||
bfd_boolean rtld)
|
||||
{
|
||||
asection *lsec;
|
||||
struct xcoff_loader_info ldinfo;
|
||||
int i;
|
||||
size_t impsize, impcount;
|
||||
struct xcoff_import_file *fl;
|
||||
struct internal_ldhdr *ldhdr;
|
||||
bfd_size_type stoff;
|
||||
char *out;
|
||||
asection *sec;
|
||||
bfd *sub;
|
||||
struct bfd_strtab_hash *debug_strtab;
|
||||
@@ -3316,7 +3451,8 @@ bfd_xcoff_size_dynamic_sections (bfd *output_bfd,
|
||||
xcoff_hash_table (info)->rtld = rtld;
|
||||
|
||||
/* __rtinit */
|
||||
if (info->init_function || info->fini_function || rtld)
|
||||
if (xcoff_hash_table (info)->loader_section
|
||||
&& (info->init_function || info->fini_function || rtld))
|
||||
{
|
||||
struct xcoff_link_hash_entry *hsym;
|
||||
struct internal_ldsym *ldsym;
|
||||
@@ -3432,103 +3568,15 @@ bfd_xcoff_size_dynamic_sections (bfd *output_bfd,
|
||||
/* I'm not sure what to do in this bizarre case. */
|
||||
return TRUE;
|
||||
|
||||
xcoff_link_hash_traverse (xcoff_hash_table (info), xcoff_build_ldsyms,
|
||||
xcoff_link_hash_traverse (xcoff_hash_table (info), xcoff_post_gc_symbol,
|
||||
(void *) &ldinfo);
|
||||
if (ldinfo.failed)
|
||||
goto error_return;
|
||||
|
||||
/* Work out the size of the import file names. Each import file ID
|
||||
consists of three null terminated strings: the path, the file
|
||||
name, and the archive member name. The first entry in the list
|
||||
of names is the path to use to find objects, which the linker has
|
||||
passed in as the libpath argument. For some reason, the path
|
||||
entry in the other import file names appears to always be empty. */
|
||||
impsize = strlen (libpath) + 3;
|
||||
impcount = 1;
|
||||
for (fl = xcoff_hash_table (info)->imports; fl != NULL; fl = fl->next)
|
||||
{
|
||||
++impcount;
|
||||
impsize += (strlen (fl->path)
|
||||
+ strlen (fl->file)
|
||||
+ strlen (fl->member)
|
||||
+ 3);
|
||||
}
|
||||
|
||||
/* Set up the .loader section header. */
|
||||
ldhdr = &xcoff_hash_table (info)->ldhdr;
|
||||
ldhdr->l_version = bfd_xcoff_ldhdr_version(output_bfd);
|
||||
ldhdr->l_nsyms = ldinfo.ldsym_count;
|
||||
ldhdr->l_nreloc = xcoff_hash_table (info)->ldrel_count;
|
||||
ldhdr->l_istlen = impsize;
|
||||
ldhdr->l_nimpid = impcount;
|
||||
ldhdr->l_impoff = (bfd_xcoff_ldhdrsz(output_bfd)
|
||||
+ ldhdr->l_nsyms * bfd_xcoff_ldsymsz(output_bfd)
|
||||
+ ldhdr->l_nreloc * bfd_xcoff_ldrelsz(output_bfd));
|
||||
ldhdr->l_stlen = ldinfo.string_size;
|
||||
stoff = ldhdr->l_impoff + impsize;
|
||||
if (ldinfo.string_size == 0)
|
||||
ldhdr->l_stoff = 0;
|
||||
else
|
||||
ldhdr->l_stoff = stoff;
|
||||
|
||||
/* 64 bit elements to ldhdr
|
||||
The swap out routine for 32 bit will ignore them.
|
||||
Nothing fancy, symbols come after the header and relocs come
|
||||
after symbols. */
|
||||
ldhdr->l_symoff = bfd_xcoff_ldhdrsz (output_bfd);
|
||||
ldhdr->l_rldoff = (bfd_xcoff_ldhdrsz (output_bfd)
|
||||
+ ldhdr->l_nsyms * bfd_xcoff_ldsymsz (output_bfd));
|
||||
|
||||
/* We now know the final size of the .loader section. Allocate
|
||||
space for it. */
|
||||
lsec = xcoff_hash_table (info)->loader_section;
|
||||
lsec->size = stoff + ldhdr->l_stlen;
|
||||
lsec->contents = bfd_zalloc (output_bfd, lsec->size);
|
||||
if (lsec->contents == NULL)
|
||||
if (xcoff_hash_table (info)->loader_section
|
||||
&& !xcoff_build_loader_section (&ldinfo, libpath))
|
||||
goto error_return;
|
||||
|
||||
/* Set up the header. */
|
||||
bfd_xcoff_swap_ldhdr_out (output_bfd, ldhdr, lsec->contents);
|
||||
|
||||
/* Set up the import file names. */
|
||||
out = (char *) lsec->contents + ldhdr->l_impoff;
|
||||
strcpy (out, libpath);
|
||||
out += strlen (libpath) + 1;
|
||||
*out++ = '\0';
|
||||
*out++ = '\0';
|
||||
for (fl = xcoff_hash_table (info)->imports; fl != NULL; fl = fl->next)
|
||||
{
|
||||
const char *s;
|
||||
|
||||
s = fl->path;
|
||||
while ((*out++ = *s++) != '\0')
|
||||
;
|
||||
s = fl->file;
|
||||
while ((*out++ = *s++) != '\0')
|
||||
;
|
||||
s = fl->member;
|
||||
while ((*out++ = *s++) != '\0')
|
||||
;
|
||||
}
|
||||
|
||||
BFD_ASSERT ((bfd_size_type) ((bfd_byte *) out - lsec->contents) == stoff);
|
||||
|
||||
/* Set up the symbol string table. */
|
||||
if (ldinfo.string_size > 0)
|
||||
{
|
||||
memcpy (out, ldinfo.strings, ldinfo.string_size);
|
||||
free (ldinfo.strings);
|
||||
ldinfo.strings = NULL;
|
||||
}
|
||||
|
||||
/* We can't set up the symbol table or the relocs yet, because we
|
||||
don't yet know the final position of the various sections. The
|
||||
.loader symbols are written out when the corresponding normal
|
||||
symbols are written out in xcoff_link_input_bfd or
|
||||
xcoff_write_global_symbol. The .loader relocs are written out
|
||||
when the corresponding normal relocs are handled in
|
||||
xcoff_link_input_bfd. */
|
||||
|
||||
/* Allocate space for the magic sections. */
|
||||
sec = xcoff_hash_table (info)->linkage_section;
|
||||
if (sec->size > 0)
|
||||
@@ -3743,6 +3791,91 @@ bfd_xcoff_link_generate_rtinit (bfd *abfd,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Return the section that defines H. Return null if no section does. */
|
||||
|
||||
static asection *
|
||||
xcoff_symbol_section (struct xcoff_link_hash_entry *h)
|
||||
{
|
||||
switch (h->root.type)
|
||||
{
|
||||
case bfd_link_hash_defined:
|
||||
case bfd_link_hash_defweak:
|
||||
return h->root.u.def.section;
|
||||
|
||||
case bfd_link_hash_common:
|
||||
return h->root.u.c.p->section;
|
||||
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Add a .loader relocation for input relocation IREL. If the loader
|
||||
relocation should be against an output section, HSEC points to the
|
||||
input section that IREL is against, otherwise HSEC is null. H is the
|
||||
symbol that IREL is against, or null if it isn't against a global symbol.
|
||||
REFERENCE_BFD is the bfd to use in error messages about the relocation. */
|
||||
|
||||
static bfd_boolean
|
||||
xcoff_create_ldrel (bfd *output_bfd, struct xcoff_final_link_info *finfo,
|
||||
asection *output_section, bfd *reference_bfd,
|
||||
struct internal_reloc *irel, asection *hsec,
|
||||
struct xcoff_link_hash_entry *h)
|
||||
{
|
||||
struct internal_ldrel ldrel;
|
||||
|
||||
ldrel.l_vaddr = irel->r_vaddr;
|
||||
if (hsec != NULL)
|
||||
{
|
||||
const char *secname;
|
||||
|
||||
secname = hsec->output_section->name;
|
||||
if (strcmp (secname, ".text") == 0)
|
||||
ldrel.l_symndx = 0;
|
||||
else if (strcmp (secname, ".data") == 0)
|
||||
ldrel.l_symndx = 1;
|
||||
else if (strcmp (secname, ".bss") == 0)
|
||||
ldrel.l_symndx = 2;
|
||||
else
|
||||
{
|
||||
(*_bfd_error_handler)
|
||||
(_("%B: loader reloc in unrecognized section `%s'"),
|
||||
reference_bfd, secname);
|
||||
bfd_set_error (bfd_error_nonrepresentable_section);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
else if (h != NULL)
|
||||
{
|
||||
if (h->ldindx < 0)
|
||||
{
|
||||
(*_bfd_error_handler)
|
||||
(_("%B: `%s' in loader reloc but not loader sym"),
|
||||
reference_bfd, h->root.root.string);
|
||||
bfd_set_error (bfd_error_bad_value);
|
||||
return FALSE;
|
||||
}
|
||||
ldrel.l_symndx = h->ldindx;
|
||||
}
|
||||
else
|
||||
ldrel.l_symndx = -(bfd_size_type) 1;
|
||||
|
||||
ldrel.l_rtype = (irel->r_size << 8) | irel->r_type;
|
||||
ldrel.l_rsecnm = output_section->target_index;
|
||||
if (xcoff_hash_table (finfo->info)->textro
|
||||
&& strcmp (output_section->name, ".text") == 0)
|
||||
{
|
||||
(*_bfd_error_handler)
|
||||
(_("%B: loader reloc in read-only section %A"),
|
||||
reference_bfd, output_section);
|
||||
bfd_set_error (bfd_error_invalid_operation);
|
||||
return FALSE;
|
||||
}
|
||||
bfd_xcoff_swap_ldrel_out (output_bfd, &ldrel, finfo->ldrel);
|
||||
finfo->ldrel += bfd_xcoff_ldrelsz (output_bfd);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Link an input file into the linker output file. This function
|
||||
handles all the sections and relocations of the input file at once. */
|
||||
|
||||
@@ -4455,7 +4588,6 @@ xcoff_link_input_bfd (struct xcoff_final_link_info *finfo,
|
||||
for (; irel < irelend; irel++, rel_hash++)
|
||||
{
|
||||
struct xcoff_link_hash_entry *h = NULL;
|
||||
struct internal_ldrel ldrel;
|
||||
|
||||
*rel_hash = NULL;
|
||||
|
||||
@@ -4588,97 +4720,20 @@ xcoff_link_input_bfd (struct xcoff_final_link_info *finfo,
|
||||
}
|
||||
}
|
||||
|
||||
switch (irel->r_type)
|
||||
if (xcoff_need_ldrel_p (finfo->info, irel, h))
|
||||
{
|
||||
default:
|
||||
if (h == NULL
|
||||
|| h->root.type == bfd_link_hash_defined
|
||||
|| h->root.type == bfd_link_hash_defweak
|
||||
|| h->root.type == bfd_link_hash_common)
|
||||
break;
|
||||
/* Fall through. */
|
||||
case R_POS:
|
||||
case R_NEG:
|
||||
case R_RL:
|
||||
case R_RLA:
|
||||
if (h != NULL
|
||||
&& (h->root.type == bfd_link_hash_defined
|
||||
|| h->root.type == bfd_link_hash_defweak)
|
||||
&& bfd_is_abs_section (h->root.u.def.section))
|
||||
break;
|
||||
/* This reloc needs to be copied into the .loader
|
||||
section. */
|
||||
ldrel.l_vaddr = irel->r_vaddr;
|
||||
asection *sec;
|
||||
|
||||
if (r_symndx == -1)
|
||||
ldrel.l_symndx = -(bfd_size_type ) 1;
|
||||
else if (h == NULL
|
||||
|| (h->root.type == bfd_link_hash_defined
|
||||
|| h->root.type == bfd_link_hash_defweak
|
||||
|| h->root.type == bfd_link_hash_common))
|
||||
{
|
||||
asection *sec;
|
||||
|
||||
if (h == NULL)
|
||||
sec = xcoff_data (input_bfd)->csects[r_symndx];
|
||||
else if (h->root.type == bfd_link_hash_common)
|
||||
sec = h->root.u.c.p->section;
|
||||
else
|
||||
sec = h->root.u.def.section;
|
||||
sec = sec->output_section;
|
||||
|
||||
if (strcmp (sec->name, ".text") == 0)
|
||||
ldrel.l_symndx = 0;
|
||||
else if (strcmp (sec->name, ".data") == 0)
|
||||
ldrel.l_symndx = 1;
|
||||
else if (strcmp (sec->name, ".bss") == 0)
|
||||
ldrel.l_symndx = 2;
|
||||
else
|
||||
{
|
||||
(*_bfd_error_handler)
|
||||
(_("%B: loader reloc in unrecognized section `%A'"),
|
||||
input_bfd, sec);
|
||||
bfd_set_error (bfd_error_nonrepresentable_section);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
sec = NULL;
|
||||
else if (h == NULL)
|
||||
sec = xcoff_data (input_bfd)->csects[r_symndx];
|
||||
else
|
||||
{
|
||||
if (h->ldindx < 0)
|
||||
{
|
||||
(*_bfd_error_handler)
|
||||
(_("%B: `%s' in loader reloc but not loader sym"),
|
||||
input_bfd,
|
||||
h->root.root.string);
|
||||
bfd_set_error (bfd_error_bad_value);
|
||||
return FALSE;
|
||||
}
|
||||
ldrel.l_symndx = h->ldindx;
|
||||
}
|
||||
ldrel.l_rtype = (irel->r_size << 8) | irel->r_type;
|
||||
ldrel.l_rsecnm = o->output_section->target_index;
|
||||
if (xcoff_hash_table (finfo->info)->textro
|
||||
&& strcmp (o->output_section->name, ".text") == 0)
|
||||
{
|
||||
(*_bfd_error_handler)
|
||||
(_("%B: loader reloc in read-only section %A"),
|
||||
input_bfd, o->output_section);
|
||||
bfd_set_error (bfd_error_invalid_operation);
|
||||
return FALSE;
|
||||
}
|
||||
bfd_xcoff_swap_ldrel_out (output_bfd, &ldrel,
|
||||
finfo->ldrel);
|
||||
|
||||
finfo->ldrel += bfd_xcoff_ldrelsz(output_bfd);
|
||||
break;
|
||||
|
||||
case R_TOC:
|
||||
case R_GL:
|
||||
case R_TCL:
|
||||
case R_TRL:
|
||||
case R_TRLA:
|
||||
/* We should never need a .loader reloc for a TOC
|
||||
relative reloc. */
|
||||
break;
|
||||
sec = xcoff_symbol_section (h);
|
||||
if (!xcoff_create_ldrel (output_bfd, finfo,
|
||||
o->output_section, input_bfd,
|
||||
irel, sec, h))
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5035,7 +5090,6 @@ xcoff_write_global_symbol (struct xcoff_link_hash_entry *h, void * inf)
|
||||
asection *osec;
|
||||
int oindx;
|
||||
struct internal_reloc *irel;
|
||||
struct internal_ldrel ldrel;
|
||||
struct internal_syment irsym;
|
||||
union internal_auxent iraux;
|
||||
|
||||
@@ -5088,12 +5142,9 @@ xcoff_write_global_symbol (struct xcoff_link_hash_entry *h, void * inf)
|
||||
finfo->section_info[oindx].rel_hashes[osec->reloc_count] = NULL;
|
||||
++osec->reloc_count;
|
||||
|
||||
ldrel.l_vaddr = irel->r_vaddr;
|
||||
ldrel.l_symndx = h->ldindx;
|
||||
ldrel.l_rtype = (irel->r_size << 8) | R_POS;
|
||||
ldrel.l_rsecnm = oindx;
|
||||
bfd_xcoff_swap_ldrel_out (output_bfd, &ldrel, finfo->ldrel);
|
||||
finfo->ldrel += bfd_xcoff_ldrelsz(output_bfd);
|
||||
if (!xcoff_create_ldrel (output_bfd, finfo, osec,
|
||||
output_bfd, irel, NULL, h))
|
||||
return FALSE;
|
||||
|
||||
/* We need to emit a symbol to define a csect which holds
|
||||
the reloc. */
|
||||
@@ -5159,7 +5210,6 @@ xcoff_write_global_symbol (struct xcoff_link_hash_entry *h, void * inf)
|
||||
struct xcoff_link_hash_entry *hentry;
|
||||
asection *esec;
|
||||
struct internal_reloc *irel;
|
||||
struct internal_ldrel ldrel;
|
||||
asection *tsec;
|
||||
unsigned int reloc_size, byte_size;
|
||||
|
||||
@@ -5197,26 +5247,9 @@ xcoff_write_global_symbol (struct xcoff_link_hash_entry *h, void * inf)
|
||||
finfo->section_info[oindx].rel_hashes[osec->reloc_count] = NULL;
|
||||
++osec->reloc_count;
|
||||
|
||||
ldrel.l_vaddr = irel->r_vaddr;
|
||||
if (strcmp (esec->output_section->name, ".text") == 0)
|
||||
ldrel.l_symndx = 0;
|
||||
else if (strcmp (esec->output_section->name, ".data") == 0)
|
||||
ldrel.l_symndx = 1;
|
||||
else if (strcmp (esec->output_section->name, ".bss") == 0)
|
||||
ldrel.l_symndx = 2;
|
||||
else
|
||||
{
|
||||
(*_bfd_error_handler)
|
||||
(_("%s: loader reloc in unrecognized section `%s'"),
|
||||
bfd_get_filename (output_bfd),
|
||||
esec->output_section->name);
|
||||
bfd_set_error (bfd_error_nonrepresentable_section);
|
||||
return FALSE;
|
||||
}
|
||||
ldrel.l_rtype = (reloc_size << 8) | R_POS;
|
||||
ldrel.l_rsecnm = oindx;
|
||||
bfd_xcoff_swap_ldrel_out (output_bfd, &ldrel, finfo->ldrel);
|
||||
finfo->ldrel += bfd_xcoff_ldrelsz(output_bfd);
|
||||
if (!xcoff_create_ldrel (output_bfd, finfo, osec,
|
||||
output_bfd, irel, esec, NULL))
|
||||
return FALSE;
|
||||
|
||||
/* There are three items to write out,
|
||||
the address of the code
|
||||
@@ -5259,26 +5292,9 @@ xcoff_write_global_symbol (struct xcoff_link_hash_entry *h, void * inf)
|
||||
finfo->section_info[oindx].rel_hashes[osec->reloc_count] = NULL;
|
||||
++osec->reloc_count;
|
||||
|
||||
ldrel.l_vaddr = irel->r_vaddr;
|
||||
if (strcmp (tsec->output_section->name, ".text") == 0)
|
||||
ldrel.l_symndx = 0;
|
||||
else if (strcmp (tsec->output_section->name, ".data") == 0)
|
||||
ldrel.l_symndx = 1;
|
||||
else if (strcmp (tsec->output_section->name, ".bss") == 0)
|
||||
ldrel.l_symndx = 2;
|
||||
else
|
||||
{
|
||||
(*_bfd_error_handler)
|
||||
(_("%s: loader reloc in unrecognized section `%s'"),
|
||||
bfd_get_filename (output_bfd),
|
||||
tsec->output_section->name);
|
||||
bfd_set_error (bfd_error_nonrepresentable_section);
|
||||
return FALSE;
|
||||
}
|
||||
ldrel.l_rtype = (reloc_size << 8) | R_POS;
|
||||
ldrel.l_rsecnm = oindx;
|
||||
bfd_xcoff_swap_ldrel_out (output_bfd, &ldrel, finfo->ldrel);
|
||||
finfo->ldrel += bfd_xcoff_ldrelsz(output_bfd);
|
||||
if (!xcoff_create_ldrel (output_bfd, finfo, osec,
|
||||
output_bfd, irel, tsec, NULL))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (h->indx >= 0 || finfo->info->strip == strip_all)
|
||||
@@ -5440,7 +5456,6 @@ xcoff_reloc_link_order (bfd *output_bfd,
|
||||
bfd_vma addend;
|
||||
struct internal_reloc *irel;
|
||||
struct xcoff_link_hash_entry **rel_hash_ptr;
|
||||
struct internal_ldrel ldrel;
|
||||
|
||||
if (link_order->type == bfd_section_reloc_link_order)
|
||||
/* We need to somehow locate a symbol in the right section. The
|
||||
@@ -5468,22 +5483,12 @@ xcoff_reloc_link_order (bfd *output_bfd,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (h->root.type == bfd_link_hash_common)
|
||||
{
|
||||
hsec = h->root.u.c.p->section;
|
||||
hval = 0;
|
||||
}
|
||||
else if (h->root.type == bfd_link_hash_defined
|
||||
|| h->root.type == bfd_link_hash_defweak)
|
||||
{
|
||||
hsec = h->root.u.def.section;
|
||||
hval = h->root.u.def.value;
|
||||
}
|
||||
hsec = xcoff_symbol_section (h);
|
||||
if (h->root.type == bfd_link_hash_defined
|
||||
|| h->root.type == bfd_link_hash_defweak)
|
||||
hval = h->root.u.def.value;
|
||||
else
|
||||
{
|
||||
hsec = NULL;
|
||||
hval = 0;
|
||||
}
|
||||
hval = 0;
|
||||
|
||||
addend = link_order->u.reloc.p->addend;
|
||||
if (hsec != NULL)
|
||||
@@ -5558,48 +5563,12 @@ xcoff_reloc_link_order (bfd *output_bfd,
|
||||
++output_section->reloc_count;
|
||||
|
||||
/* Now output the reloc to the .loader section. */
|
||||
|
||||
ldrel.l_vaddr = irel->r_vaddr;
|
||||
|
||||
if (hsec != NULL)
|
||||
if (xcoff_hash_table (finfo->info)->loader_section)
|
||||
{
|
||||
const char *secname;
|
||||
|
||||
secname = hsec->output_section->name;
|
||||
|
||||
if (strcmp (secname, ".text") == 0)
|
||||
ldrel.l_symndx = 0;
|
||||
else if (strcmp (secname, ".data") == 0)
|
||||
ldrel.l_symndx = 1;
|
||||
else if (strcmp (secname, ".bss") == 0)
|
||||
ldrel.l_symndx = 2;
|
||||
else
|
||||
{
|
||||
(*_bfd_error_handler)
|
||||
(_("%s: loader reloc in unrecognized section `%s'"),
|
||||
bfd_get_filename (output_bfd), secname);
|
||||
bfd_set_error (bfd_error_nonrepresentable_section);
|
||||
return FALSE;
|
||||
}
|
||||
if (!xcoff_create_ldrel (output_bfd, finfo, output_section,
|
||||
output_bfd, irel, hsec, h))
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (h->ldindx < 0)
|
||||
{
|
||||
(*_bfd_error_handler)
|
||||
(_("%s: `%s' in loader reloc but not loader sym"),
|
||||
bfd_get_filename (output_bfd),
|
||||
h->root.root.string);
|
||||
bfd_set_error (bfd_error_bad_value);
|
||||
return FALSE;
|
||||
}
|
||||
ldrel.l_symndx = h->ldindx;
|
||||
}
|
||||
|
||||
ldrel.l_rtype = (irel->r_size << 8) | irel->r_type;
|
||||
ldrel.l_rsecnm = output_section->target_index;
|
||||
bfd_xcoff_swap_ldrel_out (output_bfd, &ldrel, finfo->ldrel);
|
||||
finfo->ldrel += bfd_xcoff_ldrelsz(output_bfd);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@@ -5646,12 +5615,20 @@ _bfd_xcoff_bfd_final_link (bfd *abfd, struct bfd_link_info *info)
|
||||
finfo.contents = NULL;
|
||||
finfo.external_relocs = NULL;
|
||||
|
||||
finfo.ldsym = (xcoff_hash_table (info)->loader_section->contents
|
||||
+ bfd_xcoff_ldhdrsz (abfd));
|
||||
finfo.ldrel = (xcoff_hash_table (info)->loader_section->contents
|
||||
+ bfd_xcoff_ldhdrsz(abfd)
|
||||
+ (xcoff_hash_table (info)->ldhdr.l_nsyms
|
||||
* bfd_xcoff_ldsymsz(abfd)));
|
||||
if (xcoff_hash_table (info)->loader_section)
|
||||
{
|
||||
finfo.ldsym = (xcoff_hash_table (info)->loader_section->contents
|
||||
+ bfd_xcoff_ldhdrsz (abfd));
|
||||
finfo.ldrel = (xcoff_hash_table (info)->loader_section->contents
|
||||
+ bfd_xcoff_ldhdrsz (abfd)
|
||||
+ (xcoff_hash_table (info)->ldhdr.l_nsyms
|
||||
* bfd_xcoff_ldsymsz (abfd)));
|
||||
}
|
||||
else
|
||||
{
|
||||
finfo.ldsym = NULL;
|
||||
finfo.ldrel = NULL;
|
||||
}
|
||||
|
||||
xcoff_data (abfd)->coff.link_info = info;
|
||||
|
||||
@@ -6138,13 +6115,16 @@ _bfd_xcoff_bfd_final_link (bfd *abfd, struct bfd_link_info *info)
|
||||
}
|
||||
|
||||
/* Write out the loader section contents. */
|
||||
BFD_ASSERT ((bfd_byte *) finfo.ldrel
|
||||
== (xcoff_hash_table (info)->loader_section->contents
|
||||
+ xcoff_hash_table (info)->ldhdr.l_impoff));
|
||||
o = xcoff_hash_table (info)->loader_section;
|
||||
if (! bfd_set_section_contents (abfd, o->output_section, o->contents,
|
||||
(file_ptr) o->output_offset, o->size))
|
||||
goto error_return;
|
||||
if (o)
|
||||
{
|
||||
BFD_ASSERT ((bfd_byte *) finfo.ldrel
|
||||
== (xcoff_hash_table (info)->loader_section->contents
|
||||
+ xcoff_hash_table (info)->ldhdr.l_impoff));
|
||||
if (!bfd_set_section_contents (abfd, o->output_section, o->contents,
|
||||
(file_ptr) o->output_offset, o->size))
|
||||
goto error_return;
|
||||
}
|
||||
|
||||
/* Write out the magic sections. */
|
||||
o = xcoff_hash_table (info)->linkage_section;
|
||||
|
||||
22
ld/testsuite/ld-powerpc/aix-rel-1.od
Normal file
22
ld/testsuite/ld-powerpc/aix-rel-1.od
Normal file
@@ -0,0 +1,22 @@
|
||||
|
||||
.*
|
||||
|
||||
# It doesn't matter whether .text, .bss and .debug are listed, as long as
|
||||
# they're empty. The important thing is that .loader shouldn't appear
|
||||
# at all.
|
||||
Sections:
|
||||
*Idx Name * Size .*
|
||||
*0 \.text * 0+0 .*
|
||||
*ALLOC, LOAD, CODE
|
||||
*1 \.data * 0+8 .*
|
||||
*CONTENTS, ALLOC, LOAD, RELOC, DATA
|
||||
*2 \.bss * 0+0 .*
|
||||
*ALLOC
|
||||
*3 \.debug * 0+0 .*
|
||||
|
||||
RELOCATION RECORDS FOR \[\.data\]:
|
||||
OFFSET * TYPE * VALUE
|
||||
0+0 R_POS(|_32) * \.puts
|
||||
0+4 R_POS(|_32) * foobar
|
||||
|
||||
|
||||
5
ld/testsuite/ld-powerpc/aix-rel-1.s
Normal file
5
ld/testsuite/ld-powerpc/aix-rel-1.s
Normal file
@@ -0,0 +1,5 @@
|
||||
.globl foo
|
||||
.csect foo[RW]
|
||||
foo:
|
||||
.long .puts
|
||||
.long foobar
|
||||
@@ -171,6 +171,10 @@ set aix52tests {
|
||||
{{objdump -d aix-glink-2-SIZE.dd}}
|
||||
"aix-glink-2"}
|
||||
|
||||
{"Relocatable test 1" "-r"
|
||||
"" {aix-rel-1.s}
|
||||
{{objdump -hr aix-rel-1.od}} "aix-rel-1.ro"}
|
||||
|
||||
{"Weak test 1 (rel)" "-r"
|
||||
"" {aix-weak-1a.s aix-weak-1b.s}
|
||||
{{nm {} aix-weak-1-rel.nd} {objdump -h aix-weak-1-rel.hd}}
|
||||
|
||||
Reference in New Issue
Block a user