aboutsummaryrefslogtreecommitdiff
path: root/bfd/xcofflink.c
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@airs.com>1995-11-20 19:57:30 +0000
committerIan Lance Taylor <ian@airs.com>1995-11-20 19:57:30 +0000
commitb5403ad75475a885a050a070de97e640ff3add44 (patch)
treef4a6ce6898ed4e0fc776c2b60b783d2102d41efb /bfd/xcofflink.c
parente7b6403a67d83ad3e478f99addefdbe2e5e5f379 (diff)
downloadgdb-b5403ad75475a885a050a070de97e640ff3add44.zip
gdb-b5403ad75475a885a050a070de97e640ff3add44.tar.gz
gdb-b5403ad75475a885a050a070de97e640ff3add44.tar.bz2
* xcofflink.c (xcoff_link_input_bfd): Adjust the TOC anchor value
if it is not large enough to accomodate the entire TOC area with signed 16 bit offsets. (xcoff_write_global_symbol): Handle negative TOC offsets in global linkage code. (_bfd_ppc_xcoff_relocate_section): Adjust relocations against a TOC anchor to use the TOC value used in the output file.
Diffstat (limited to 'bfd/xcofflink.c')
-rw-r--r--bfd/xcofflink.c49
1 files changed, 38 insertions, 11 deletions
diff --git a/bfd/xcofflink.c b/bfd/xcofflink.c
index d91e341..78a2a44 100644
--- a/bfd/xcofflink.c
+++ b/bfd/xcofflink.c
@@ -2477,7 +2477,7 @@ bfd_xcoff_export_symbol (output_bfd, info, harg, syscall)
char *fnname;
struct xcoff_link_hash_entry *hfn;
- fnname = (char *) malloc (strlen (h->root.root.string + 2));
+ fnname = (char *) malloc (strlen (h->root.root.string) + 2);
if (fnname == NULL)
{
bfd_set_error (bfd_error_no_memory);
@@ -4011,12 +4011,33 @@ xcoff_link_input_bfd (finfo, input_bfd)
skip = true;
else
{
+ bfd_vma tocval, tocend;
+
+ tocval = ((*csectpp)->output_section->vma
+ + (*csectpp)->output_offset
+ + isym.n_value
+ - (*csectpp)->vma);
+ /* We want to find out if tocval is a good value to use
+ as the TOC anchor--that is, whether we can access all
+ of the TOC using a 16 bit offset from tocval. This
+ test assumes that the TOC comes at the end of the
+ output section, as it does in the default linker
+ script. If the TOC anchor is too far into the .toc
+ section, the relocation routine will report
+ overflows. */
+ tocend = ((*csectpp)->output_section->vma
+ + (*csectpp)->output_section->_raw_size);
+ if (tocval + 0x8000 < tocend)
+ {
+ bfd_vma tocadd;
+
+ tocadd = tocend - (tocval + 0x8000);
+ tocval += tocadd;
+ isym.n_value += tocadd;
+ }
+
finfo->toc_symindx = output_index;
- xcoff_data (finfo->output_bfd)->toc =
- ((*csectpp)->output_section->vma
- + (*csectpp)->output_offset
- + isym.n_value
- - (*csectpp)->vma);
+ xcoff_data (finfo->output_bfd)->toc = tocval;
xcoff_data (finfo->output_bfd)->toc_section =
(*csectpp)->output_section;
require = true;
@@ -4993,7 +5014,7 @@ xcoff_write_global_symbol (h, p)
- xcoff_data (output_bfd)->toc);
if ((h->descriptor->flags & XCOFF_SET_TOC) != 0)
tocoff += h->descriptor->u.toc_offset;
- bfd_put_32 (output_bfd, XCOFF_GLINK_FIRST | tocoff, p);
+ bfd_put_32 (output_bfd, XCOFF_GLINK_FIRST | (tocoff & 0xffff), p);
for (i = 0, p += 4;
i < sizeof xcoff_glink_code / sizeof xcoff_glink_code[0];
i++, p += 4)
@@ -5568,10 +5589,16 @@ _bfd_ppc_xcoff_relocate_section (output_bfd, info, input_bfd,
else
{
sec = sections[symndx];
- val = (sec->output_section->vma
- + sec->output_offset
- + sym->n_value
- - sec->vma);
+ /* Hack to make sure we use the right TOC anchor value
+ if this reloc is against the TOC anchor. */
+ if (sec->name[3] == '0'
+ && strcmp (sec->name, ".tc0") == 0)
+ val = xcoff_data (output_bfd)->toc;
+ else
+ val = (sec->output_section->vma
+ + sec->output_offset
+ + sym->n_value
+ - sec->vma);
}
}
else