X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=bfd%2Fcoff-rs6000.c;h=3f0753e5bfc766e5a868a15d57ba10f97925b544;hb=243cf0f69c36c4ee09c3c2b0bc7a97dc16119c51;hp=689f9f5b37a787c52a82ba941fdb30ffa559edcd;hpb=51d29b8cacd75865a9ffc46cffffe1e47c33ccff;p=binutils-gdb.git diff --git a/bfd/coff-rs6000.c b/bfd/coff-rs6000.c index 689f9f5b37a..3f0753e5bfc 100644 --- a/bfd/coff-rs6000.c +++ b/bfd/coff-rs6000.c @@ -1,5 +1,5 @@ /* BFD back-end for IBM RS/6000 "XCOFF" files. - Copyright (C) 1990-2021 Free Software Foundation, Inc. + Copyright (C) 1990-2022 Free Software Foundation, Inc. Written by Metin G. Ozisik, Mimi Phuong-Thao Vo, and John Gilmore. Archive support from Damon A. Permezel. Contributed by IBM Corporation and Cygnus Support. @@ -386,7 +386,7 @@ _bfd_xcoff_copy_private_bfd_data (bfd *ibfd, bfd *obfd) else { sec = coff_section_from_bfd_index (ibfd, ix->sntoc); - if (sec == NULL) + if (sec == NULL || sec->output_section == NULL) ox->sntoc = 0; else ox->sntoc = sec->output_section->target_index; @@ -396,7 +396,7 @@ _bfd_xcoff_copy_private_bfd_data (bfd *ibfd, bfd *obfd) else { sec = coff_section_from_bfd_index (ibfd, ix->snentry); - if (sec == NULL) + if (sec == NULL || sec->output_section == NULL) ox->snentry = 0; else ox->snentry = sec->output_section->target_index; @@ -489,12 +489,13 @@ _bfd_xcoff_swap_aux_in (bfd *abfd, void * ext1, int type ATTRIBUTE_UNUSED, case C_FILE: if (ext->x_file.x_n.x_fname[0] == 0) { - in->x_file.x_n.x_zeroes = 0; - in->x_file.x_n.x_offset = + in->x_file.x_n.x_n.x_zeroes = 0; + in->x_file.x_n.x_n.x_offset = H_GET_32 (abfd, ext->x_file.x_n.x_n.x_offset); } else - memcpy (in->x_file.x_fname, ext->x_file.x_n.x_fname, FILNMLEN); + memcpy (in->x_file.x_n.x_fname, ext->x_file.x_n.x_fname, FILNMLEN); + in->x_file.x_ftype = H_GET_8 (abfd, ext->x_file.x_ftype); break; /* RS/6000 "csect" auxents. @@ -573,14 +574,15 @@ _bfd_xcoff_swap_aux_out (bfd *abfd, void * inp, int type ATTRIBUTE_UNUSED, break; case C_FILE: - if (in->x_file.x_fname[0] == 0) + if (in->x_file.x_n.x_fname[0] == 0) { H_PUT_32 (abfd, 0, ext->x_file.x_n.x_n.x_zeroes); - H_PUT_32 (abfd, in->x_file.x_n.x_offset, + H_PUT_32 (abfd, in->x_file.x_n.x_n.x_offset, ext->x_file.x_n.x_n.x_offset); } else - memcpy (ext->x_file.x_n.x_fname, in->x_file.x_fname, FILNMLEN); + memcpy (ext->x_file.x_n.x_fname, in->x_file.x_n.x_fname, FILNMLEN); + H_PUT_8 (abfd, in->x_file.x_ftype, ext->x_file.x_ftype); break; /* RS/6000 "csect" auxents */ @@ -648,7 +650,7 @@ reloc_howto_type xcoff_howto_table[] = /* 0x00: Standard 32 bit relocation. */ HOWTO (R_POS, /* type */ 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ + 4, /* size */ 32, /* bitsize */ false, /* pc_relative */ 0, /* bitpos */ @@ -663,7 +665,7 @@ reloc_howto_type xcoff_howto_table[] = /* 0x01: 32 bit relocation, but store negative value. */ HOWTO (R_NEG, /* type */ 0, /* rightshift */ - -2, /* size (0 = byte, 1 = short, 2 = long) */ + -4, /* size */ 32, /* bitsize */ false, /* pc_relative */ 0, /* bitpos */ @@ -678,7 +680,7 @@ reloc_howto_type xcoff_howto_table[] = /* 0x02: 32 bit PC relative relocation. */ HOWTO (R_REL, /* type */ 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ + 4, /* size */ 32, /* bitsize */ true, /* pc_relative */ 0, /* bitpos */ @@ -693,7 +695,7 @@ reloc_howto_type xcoff_howto_table[] = /* 0x03: 16 bit TOC relative relocation. */ HOWTO (R_TOC, /* type */ 0, /* rightshift */ - 1, /* size (0 = byte, 1 = short, 2 = long) */ + 2, /* size */ 16, /* bitsize */ false, /* pc_relative */ 0, /* bitpos */ @@ -708,7 +710,7 @@ reloc_howto_type xcoff_howto_table[] = /* 0x04: Same as R_TOC */ HOWTO (R_TRL, /* type */ 0, /* rightshift */ - 1, /* size (0 = byte, 1 = short, 2 = long) */ + 2, /* size */ 16, /* bitsize */ false, /* pc_relative */ 0, /* bitpos */ @@ -723,7 +725,7 @@ reloc_howto_type xcoff_howto_table[] = /* 0x05: External TOC relative symbol. */ HOWTO (R_GL, /* type */ 0, /* rightshift */ - 1, /* size (0 = byte, 1 = short, 2 = long) */ + 2, /* size */ 16, /* bitsize */ false, /* pc_relative */ 0, /* bitpos */ @@ -738,7 +740,7 @@ reloc_howto_type xcoff_howto_table[] = /* 0x06: Local TOC relative symbol. */ HOWTO (R_TCL, /* type */ 0, /* rightshift */ - 1, /* size (0 = byte, 1 = short, 2 = long) */ + 2, /* size */ 16, /* bitsize */ false, /* pc_relative */ 0, /* bitpos */ @@ -755,7 +757,7 @@ reloc_howto_type xcoff_howto_table[] = /* 0x08: Same as R_RBA. */ HOWTO (R_BA, /* type */ 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ + 4, /* size */ 26, /* bitsize */ false, /* pc_relative */ 0, /* bitpos */ @@ -772,7 +774,7 @@ reloc_howto_type xcoff_howto_table[] = /* 0x0a: Same as R_RBR. */ HOWTO (R_BR, /* type */ 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ + 4, /* size */ 26, /* bitsize */ true, /* pc_relative */ 0, /* bitpos */ @@ -789,7 +791,7 @@ reloc_howto_type xcoff_howto_table[] = /* 0x0c: Same as R_POS. */ HOWTO (R_RL, /* type */ 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ + 4, /* size */ 32, /* bitsize */ false, /* pc_relative */ 0, /* bitpos */ @@ -804,7 +806,7 @@ reloc_howto_type xcoff_howto_table[] = /* 0x0d: Same as R_POS. */ HOWTO (R_RLA, /* type */ 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ + 4, /* size */ 32, /* bitsize */ false, /* pc_relative */ 0, /* bitpos */ @@ -821,7 +823,7 @@ reloc_howto_type xcoff_howto_table[] = /* 0x0f: Non-relocating reference. Bitsize is 1 so that r_rsize is 0. */ HOWTO (R_REF, /* type */ 0, /* rightshift */ - 0, /* size (0 = byte, 1 = short, 2 = long) */ + 1, /* size */ 1, /* bitsize */ false, /* pc_relative */ 0, /* bitpos */ @@ -840,7 +842,7 @@ reloc_howto_type xcoff_howto_table[] = /* 0x13: Same as R_TOC. */ HOWTO (R_TRLA, /* type */ 0, /* rightshift */ - 1, /* size (0 = byte, 1 = short, 2 = long) */ + 2, /* size */ 16, /* bitsize */ false, /* pc_relative */ 0, /* bitpos */ @@ -855,7 +857,7 @@ reloc_howto_type xcoff_howto_table[] = /* 0x14: Modifiable relative branch. */ HOWTO (R_RRTBI, /* type */ 1, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ + 4, /* size */ 32, /* bitsize */ false, /* pc_relative */ 0, /* bitpos */ @@ -870,7 +872,7 @@ reloc_howto_type xcoff_howto_table[] = /* 0x15: Modifiable absolute branch. */ HOWTO (R_RRTBA, /* type */ 1, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ + 4, /* size */ 32, /* bitsize */ false, /* pc_relative */ 0, /* bitpos */ @@ -885,7 +887,7 @@ reloc_howto_type xcoff_howto_table[] = /* 0x16: Modifiable call absolute indirect. */ HOWTO (R_CAI, /* type */ 0, /* rightshift */ - 1, /* size (0 = byte, 1 = short, 2 = long) */ + 2, /* size */ 16, /* bitsize */ false, /* pc_relative */ 0, /* bitpos */ @@ -900,7 +902,7 @@ reloc_howto_type xcoff_howto_table[] = /* 0x17: Modifiable call relative. */ HOWTO (R_CREL, /* type */ 0, /* rightshift */ - 1, /* size (0 = byte, 1 = short, 2 = long) */ + 2, /* size */ 16, /* bitsize */ false, /* pc_relative */ 0, /* bitpos */ @@ -915,7 +917,7 @@ reloc_howto_type xcoff_howto_table[] = /* 0x18: Modifiable branch absolute. */ HOWTO (R_RBA, /* type */ 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ + 4, /* size */ 26, /* bitsize */ false, /* pc_relative */ 0, /* bitpos */ @@ -930,7 +932,7 @@ reloc_howto_type xcoff_howto_table[] = /* 0x19: Modifiable branch absolute. */ HOWTO (R_RBAC, /* type */ 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ + 4, /* size */ 32, /* bitsize */ false, /* pc_relative */ 0, /* bitpos */ @@ -945,7 +947,7 @@ reloc_howto_type xcoff_howto_table[] = /* 0x1a: Modifiable branch relative. */ HOWTO (R_RBR, /* type */ 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ + 4, /* size */ 26, /* bitsize */ false, /* pc_relative */ 0, /* bitpos */ @@ -960,7 +962,7 @@ reloc_howto_type xcoff_howto_table[] = /* 0x1b: Modifiable branch absolute. */ HOWTO (R_RBRC, /* type */ 0, /* rightshift */ - 1, /* size (0 = byte, 1 = short, 2 = long) */ + 2, /* size */ 16, /* bitsize */ false, /* pc_relative */ 0, /* bitpos */ @@ -975,7 +977,7 @@ reloc_howto_type xcoff_howto_table[] = /* 0x1c: 16 bit Non modifiable absolute branch. */ HOWTO (R_BA, /* type */ 0, /* rightshift */ - 1, /* size (0 = byte, 1 = short, 2 = long) */ + 2, /* size */ 16, /* bitsize */ false, /* pc_relative */ 0, /* bitpos */ @@ -990,7 +992,7 @@ reloc_howto_type xcoff_howto_table[] = /* 0x1d: Modifiable branch relative. */ HOWTO (R_RBR, /* type */ 0, /* rightshift */ - 1, /* size (0 = byte, 1 = short, 2 = long) */ + 2, /* size */ 16, /* bitsize */ true, /* pc_relative */ 0, /* bitpos */ @@ -1005,7 +1007,7 @@ reloc_howto_type xcoff_howto_table[] = /* 0x1e: Modifiable branch relative. */ HOWTO (R_RBA, /* type */ 0, /* rightshift */ - 1, /* size (0 = byte, 1 = short, 2 = long) */ + 2, /* size */ 16, /* bitsize */ false, /* pc_relative */ 0, /* bitpos */ @@ -1022,7 +1024,7 @@ reloc_howto_type xcoff_howto_table[] = /* 0x20: General-dynamic TLS relocation. */ HOWTO (R_TLS, /* type */ 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ + 4, /* size */ 32, /* bitsize */ false, /* pc_relative */ 0, /* bitpos */ @@ -1037,7 +1039,7 @@ reloc_howto_type xcoff_howto_table[] = /* 0x21: Initial-exec TLS relocation. */ HOWTO (R_TLS_IE, /* type */ 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ + 4, /* size */ 32, /* bitsize */ false, /* pc_relative */ 0, /* bitpos */ @@ -1052,7 +1054,7 @@ reloc_howto_type xcoff_howto_table[] = /* 0x22: Local-dynamic TLS relocation. */ HOWTO (R_TLS_LD, /* type */ 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ + 4, /* size */ 32, /* bitsize */ false, /* pc_relative */ 0, /* bitpos */ @@ -1067,7 +1069,7 @@ reloc_howto_type xcoff_howto_table[] = /* 0x23: Local-exec TLS relocation. */ HOWTO (R_TLS_LE, /* type */ 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ + 4, /* size */ 32, /* bitsize */ false, /* pc_relative */ 0, /* bitpos */ @@ -1082,7 +1084,7 @@ reloc_howto_type xcoff_howto_table[] = /* 0x24: TLS relocation. */ HOWTO (R_TLSM, /* type */ 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ + 4, /* size */ 32, /* bitsize */ false, /* pc_relative */ 0, /* bitpos */ @@ -1098,13 +1100,13 @@ reloc_howto_type xcoff_howto_table[] = /* 0x25: TLS module relocation. */ HOWTO (R_TLSML, /* type */ 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ + 4, /* size */ 32, /* bitsize */ false, /* pc_relative */ 0, /* bitpos */ complain_overflow_bitfield, /* complain_on_overflow */ 0, /* special_function */ - "R_TLSM", /* name */ + "R_TLSML", /* name */ true, /* partial_inplace */ 0xffffffff, /* src_mask */ 0xffffffff, /* dst_mask */ @@ -1124,7 +1126,7 @@ reloc_howto_type xcoff_howto_table[] = /* 0x30: High-order 16 bit TOC relative relocation. */ HOWTO (R_TOCU, /* type */ 16, /* rightshift */ - 1, /* size (0 = byte, 1 = short, 2 = long) */ + 2, /* size */ 16, /* bitsize */ false, /* pc_relative */ 0, /* bitpos */ @@ -1139,7 +1141,7 @@ reloc_howto_type xcoff_howto_table[] = /* 0x31: Low-order 16 bit TOC relative relocation. */ HOWTO (R_TOCL, /* type */ 0, /* rightshift */ - 1, /* size (0 = byte, 1 = short, 2 = long) */ + 2, /* size */ 16, /* bitsize */ false, /* pc_relative */ 0, /* bitpos */ @@ -1669,6 +1671,10 @@ _bfd_xcoff_read_ar_hdr (bfd *abfd) ret->filename = (char *) hdrp + SIZEOF_AR_HDR_BIG; } + /* Size occupied by the header above that covered in the fixed + SIZEOF_AR_HDR or SIZEOF_AR_HDR_BIG. */ + ret->extra_size = namlen + (namlen & 1) + SXCOFFARFMAG; + /* Skip over the XCOFFARFMAG at the end of the file name. */ if (bfd_seek (abfd, (file_ptr) ((namlen & 1) + SXCOFFARFMAG), SEEK_CUR) != 0) return NULL; @@ -1682,6 +1688,7 @@ bfd * _bfd_xcoff_openr_next_archived_file (bfd *archive, bfd *last_file) { file_ptr filestart; + file_ptr laststart, lastend; if (xcoff_ardata (archive) == NULL) { @@ -1692,9 +1699,27 @@ _bfd_xcoff_openr_next_archived_file (bfd *archive, bfd *last_file) if (! xcoff_big_format_p (archive)) { if (last_file == NULL) - filestart = bfd_ardata (archive)->first_file_filepos; + { + filestart = bfd_ardata (archive)->first_file_filepos; + laststart = 0; + lastend = SIZEOF_AR_FILE_HDR; + } else - GET_VALUE_IN_FIELD (filestart, arch_xhdr (last_file)->nextoff, 10); + { + struct areltdata *arel = arch_eltdata (last_file); + + GET_VALUE_IN_FIELD (filestart, arch_xhdr (last_file)->nextoff, 10); + laststart = last_file->proxy_origin; + lastend = laststart + arel->parsed_size; + laststart -= SIZEOF_AR_HDR + arel->extra_size; + } + + /* Sanity check that we aren't pointing into the previous element. */ + if (filestart != 0 && filestart >= laststart && filestart < lastend) + { + bfd_set_error (bfd_error_malformed_archive); + return NULL; + } if (filestart == 0 || EQ_VALUE_IN_FIELD (filestart, xcoff_ardata (archive)->memoff, 10) @@ -1707,9 +1732,27 @@ _bfd_xcoff_openr_next_archived_file (bfd *archive, bfd *last_file) else { if (last_file == NULL) - filestart = bfd_ardata (archive)->first_file_filepos; + { + filestart = bfd_ardata (archive)->first_file_filepos; + laststart = 0; + lastend = SIZEOF_AR_FILE_HDR_BIG; + } else - GET_VALUE_IN_FIELD (filestart, arch_xhdr_big (last_file)->nextoff, 10); + { + struct areltdata *arel = arch_eltdata (last_file); + + GET_VALUE_IN_FIELD (filestart, arch_xhdr_big (last_file)->nextoff, 10); + laststart = last_file->proxy_origin; + lastend = laststart + arel->parsed_size; + laststart -= SIZEOF_AR_HDR_BIG + arel->extra_size; + } + + /* Sanity check that we aren't pointing into the previous element. */ + if (filestart != 0 && filestart >= laststart && filestart < lastend) + { + bfd_set_error (bfd_error_malformed_archive); + return NULL; + } if (filestart == 0 || EQ_VALUE_IN_FIELD (filestart, xcoff_ardata_big (archive)->memoff, 10) @@ -1720,7 +1763,7 @@ _bfd_xcoff_openr_next_archived_file (bfd *archive, bfd *last_file) } } - return _bfd_get_elt_at_filepos (archive, filestart); + return _bfd_get_elt_at_filepos (archive, filestart, NULL); } /* Stat an element in an XCOFF archive. */ @@ -1847,18 +1890,12 @@ xcoff_write_armap_old (bfd *abfd, unsigned int elength ATTRIBUTE_UNUSED, } static char buff20[XCOFFARMAGBIG_ELEMENT_SIZE + 1]; -#if BFD_HOST_64BIT_LONG -#define FMT20 "%-20ld" -#elif defined (__MSVCRT__) -#define FMT20 "%-20I64d" -#else -#define FMT20 "%-20lld" -#endif +#define FMT20 "%-20" PRId64 #define FMT12 "%-12d" #define FMT12_OCTAL "%-12o" #define FMT4 "%-4d" #define PRINT20(d, v) \ - sprintf (buff20, FMT20, (bfd_uint64_t)(v)), \ + sprintf (buff20, FMT20, (uint64_t) (v)), \ memcpy ((void *) (d), buff20, 20) #define PRINT12(d, v) \ @@ -2894,7 +2931,8 @@ xcoff_reloc_type_noop (bfd *input_bfd ATTRIBUTE_UNUSED, bfd_vma val ATTRIBUTE_UNUSED, bfd_vma addend ATTRIBUTE_UNUSED, bfd_vma *relocation ATTRIBUTE_UNUSED, - bfd_byte *contents ATTRIBUTE_UNUSED) + bfd_byte *contents ATTRIBUTE_UNUSED, + struct bfd_link_info *info ATTRIBUTE_UNUSED) { return true; } @@ -2909,7 +2947,8 @@ xcoff_reloc_type_fail (bfd *input_bfd, bfd_vma val ATTRIBUTE_UNUSED, bfd_vma addend ATTRIBUTE_UNUSED, bfd_vma *relocation ATTRIBUTE_UNUSED, - bfd_byte *contents ATTRIBUTE_UNUSED) + bfd_byte *contents ATTRIBUTE_UNUSED, + struct bfd_link_info *info ATTRIBUTE_UNUSED) { _bfd_error_handler /* xgettext: c-format */ @@ -2929,7 +2968,8 @@ xcoff_reloc_type_pos (bfd *input_bfd ATTRIBUTE_UNUSED, bfd_vma val, bfd_vma addend, bfd_vma *relocation, - bfd_byte *contents ATTRIBUTE_UNUSED) + bfd_byte *contents ATTRIBUTE_UNUSED, + struct bfd_link_info *info ATTRIBUTE_UNUSED) { *relocation = val + addend; return true; @@ -2945,7 +2985,8 @@ xcoff_reloc_type_neg (bfd *input_bfd ATTRIBUTE_UNUSED, bfd_vma val, bfd_vma addend, bfd_vma *relocation, - bfd_byte *contents ATTRIBUTE_UNUSED) + bfd_byte *contents ATTRIBUTE_UNUSED, + struct bfd_link_info *info ATTRIBUTE_UNUSED) { *relocation = - val - addend; return true; @@ -2961,7 +3002,8 @@ xcoff_reloc_type_rel (bfd *input_bfd ATTRIBUTE_UNUSED, bfd_vma val, bfd_vma addend, bfd_vma *relocation, - bfd_byte *contents ATTRIBUTE_UNUSED) + bfd_byte *contents ATTRIBUTE_UNUSED, + struct bfd_link_info *info ATTRIBUTE_UNUSED) { howto->pc_relative = true; @@ -2984,7 +3026,8 @@ xcoff_reloc_type_toc (bfd *input_bfd, bfd_vma val, bfd_vma addend ATTRIBUTE_UNUSED, bfd_vma *relocation, - bfd_byte *contents ATTRIBUTE_UNUSED) + bfd_byte *contents ATTRIBUTE_UNUSED, + struct bfd_link_info *info ATTRIBUTE_UNUSED) { struct xcoff_link_hash_entry *h; @@ -3033,7 +3076,8 @@ xcoff_reloc_type_ba (bfd *input_bfd ATTRIBUTE_UNUSED, bfd_vma val, bfd_vma addend, bfd_vma *relocation, - bfd_byte *contents ATTRIBUTE_UNUSED) + bfd_byte *contents ATTRIBUTE_UNUSED, + struct bfd_link_info *info ATTRIBUTE_UNUSED) { howto->src_mask &= ~3; howto->dst_mask = howto->src_mask; @@ -3053,10 +3097,13 @@ xcoff_reloc_type_br (bfd *input_bfd, bfd_vma val, bfd_vma addend, bfd_vma *relocation, - bfd_byte *contents) + bfd_byte *contents, + struct bfd_link_info *info) { struct xcoff_link_hash_entry *h; bfd_vma section_offset; + struct xcoff_stub_hash_entry *stub_entry = NULL; + enum xcoff_stub_type stub_type; if (0 > rel->r_symndx) return false; @@ -3110,6 +3157,27 @@ xcoff_reloc_type_br (bfd *input_bfd, howto->complain_on_overflow = complain_overflow_dont; } + /* Check if a stub is needed. */ + stub_type = bfd_xcoff_type_of_stub (input_section, rel, val, h); + if (stub_type != xcoff_stub_none) + { + asection *stub_csect; + + stub_entry = bfd_xcoff_get_stub_entry (input_section, h, info); + if (stub_entry == NULL) + { + _bfd_error_handler (_("Unable to find the stub entry targeting %s"), + h->root.root.string); + bfd_set_error (bfd_error_bad_value); + return false; + } + + stub_csect = stub_entry->hcsect->root.u.def.section; + val = (stub_entry->stub_offset + + stub_csect->output_section->vma + + stub_csect->output_offset); + } + /* The original PC-relative relocation is biased by -r_vaddr, so adding the value below will give the absolute target address. */ *relocation = val + addend + rel->r_vaddr; @@ -3159,7 +3227,8 @@ xcoff_reloc_type_crel (bfd *input_bfd ATTRIBUTE_UNUSED, bfd_vma val ATTRIBUTE_UNUSED, bfd_vma addend, bfd_vma *relocation, - bfd_byte *contents ATTRIBUTE_UNUSED) + bfd_byte *contents ATTRIBUTE_UNUSED, + struct bfd_link_info *info ATTRIBUTE_UNUSED) { howto->pc_relative = true; howto->src_mask &= ~3; @@ -3184,7 +3253,8 @@ xcoff_reloc_type_tls (bfd *input_bfd ATTRIBUTE_UNUSED, bfd_vma val, bfd_vma addend, bfd_vma *relocation, - bfd_byte *contents ATTRIBUTE_UNUSED) + bfd_byte *contents ATTRIBUTE_UNUSED, + struct bfd_link_info *info ATTRIBUTE_UNUSED) { struct xcoff_link_hash_entry *h; @@ -3193,37 +3263,26 @@ xcoff_reloc_type_tls (bfd *input_bfd ATTRIBUTE_UNUSED, h = obj_xcoff_sym_hashes (input_bfd)[rel->r_symndx]; - /* FIXME: R_TLSML is targeting a internal TOC symbol, which will - make the following checks failing. It should be moved with - R_TLSM bellow once it works. */ + /* R_TLSML is handled by the loader but must be from a + TOC entry targeting itslef. This is already verified in + xcoff_link_add_symbols. + The value must be 0. */ if (howto->type == R_TLSML) { *relocation = 0; return true; } - /* FIXME: h is sometimes null, if the TLS symbol is not exported. */ - if (!h) - { - char vaddr_buf[128]; - - sprintf_vma (vaddr_buf, rel->r_vaddr); - _bfd_error_handler - (_("%pB: TLS relocation at 0x%s over internal symbols (C_HIDEXT) not yet possible\n"), - input_bfd, vaddr_buf); - return false; - } - + /* The target symbol should always be available even if it's not + exported. */ + BFD_ASSERT (h != NULL); /* TLS relocations must target a TLS symbol. */ if (h->smclas != XMC_TL && h->smclas != XMC_UL) { - char vaddr_buf[128]; - - sprintf_vma (vaddr_buf, rel->r_vaddr); _bfd_error_handler - (_("%pB: TLS relocation at 0x%s over non-TLS symbol %s (0x%x)\n"), - input_bfd, vaddr_buf, h->root.root.string, h->smclas); + (_("%pB: TLS relocation at 0x%" PRIx64 " over non-TLS symbol %s (0x%x)\n"), + input_bfd, (uint64_t) rel->r_vaddr, h->root.root.string, h->smclas); return false; } @@ -3234,18 +3293,14 @@ xcoff_reloc_type_tls (bfd *input_bfd ATTRIBUTE_UNUSED, && (h->flags & XCOFF_DEF_DYNAMIC) != 0) || (h->flags & XCOFF_IMPORT) != 0)) { - char vaddr_buf[128]; - - sprintf_vma (vaddr_buf, rel->r_vaddr); _bfd_error_handler - (_("%pB: TLS local relocation at 0x%s over imported symbol %s\n"), - input_bfd, vaddr_buf, h->root.root.string); + (_("%pB: TLS local relocation at 0x%" PRIx64 " over imported symbol %s\n"), + input_bfd, (uint64_t) rel->r_vaddr, h->root.root.string); return false; } - /* R_TLSM and R_TLSML are relocations used by the loader. - The value must be 0. - FIXME: move R_TLSML here. */ + /* R_TLSM are relocations used by the loader. + The value must be 0. */ if (howto->type == R_TLSM) { *relocation = 0; @@ -3578,10 +3633,10 @@ xcoff_complain_overflow_unsigned_func (bfd *input_bfd, R_TLS_LE: Thread-local storage relocation using local-exec model. - R_TLS: + R_TLSM: Tread-local storage relocation used by the loader. - R_TLSM: + R_TLSML: Tread-local storage relocation used by the loader. R_TOCU: @@ -3639,20 +3694,15 @@ xcoff_ppc_relocate_section (bfd *output_bfd, case R_POS: case R_NEG: howto.bitsize = (rel->r_size & 0x1f) + 1; - howto.size = howto.bitsize > 16 ? 2 : 1; + howto.size = HOWTO_RSIZE (howto.bitsize > 16 ? 4 : 2); howto.src_mask = howto.dst_mask = N_ONES (howto.bitsize); break; default: - { - char vaddr_buf[128]; - - sprintf_vma (vaddr_buf, rel->r_vaddr); - _bfd_error_handler - (_("%pB: relocation (%d) at 0x%s has wrong r_rsize (0x%x)\n"), - input_bfd, rel->r_type, vaddr_buf, rel->r_size); - return false; - } + _bfd_error_handler + (_("%pB: relocation (%d) at 0x%" PRIx64 " has wrong r_rsize (0x%x)\n"), + input_bfd, rel->r_type, (uint64_t) rel->r_vaddr, rel->r_size); + return false; } } @@ -3729,7 +3779,7 @@ xcoff_ppc_relocate_section (bfd *output_bfd, if (rel->r_type >= XCOFF_MAX_CALCULATE_RELOCATION || !((*xcoff_calculate_relocation[rel->r_type]) (input_bfd, input_section, output_bfd, rel, sym, &howto, val, - addend, &relocation, contents))) + addend, &relocation, contents, info))) return false; /* address */ @@ -3740,7 +3790,7 @@ xcoff_ppc_relocate_section (bfd *output_bfd, abort (); /* Get the value we are going to relocate. */ - if (1 == howto.size) + if (2 == bfd_get_reloc_size (&howto)) value_to_relocate = bfd_get_16 (input_bfd, location); else value_to_relocate = bfd_get_32 (input_bfd, location); @@ -3787,7 +3837,7 @@ xcoff_ppc_relocate_section (bfd *output_bfd, + relocation) & howto.dst_mask)); /* Put the value back in the object file. */ - if (1 == howto.size) + if (2 == bfd_get_reloc_size (&howto)) bfd_put_16 (input_bfd, value_to_relocate, location); else bfd_put_32 (input_bfd, value_to_relocate, location); @@ -3847,8 +3897,8 @@ _bfd_xcoff_put_ldsymbol_name (bfd *abfd ATTRIBUTE_UNUSED, ldinfo->strings = newstrings; } - bfd_put_16 (ldinfo->output_bfd, (bfd_vma) (len + 1), - ldinfo->strings + ldinfo->string_size); + ldinfo->strings[ldinfo->string_size] = ((len + 1) >> 8) & 0xff; + ldinfo->strings[ldinfo->string_size + 1] = ((len + 1)) & 0xff; strcpy (ldinfo->strings + ldinfo->string_size + 2, name); ldsym->_l._l_l._l_zeroes = 0; ldsym->_l._l_l._l_offset = ldinfo->string_size + 2; @@ -4235,7 +4285,7 @@ xcoff_generate_rtinit (bfd *abfd, const char *init, const char *fini, static reloc_howto_type xcoff_dynamic_reloc = HOWTO (0, /* type */ 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ + 4, /* size */ 32, /* bitsize */ false, /* pc_relative */ 0, /* bitpos */ @@ -4247,6 +4297,34 @@ HOWTO (0, /* type */ 0xffffffff, /* dst_mask */ false); /* pcrel_offset */ +/* Indirect call stub + The first word of the code must be modified by filling in + the correct TOC offset. */ + +static const unsigned long xcoff_stub_indirect_call_code[4] = + { + 0x81820000, /* lwz r12,0(r2) */ + 0x800c0000, /* lwz r0,0(r12) */ + 0x7c0903a6, /* mtctr r0 */ + 0x4e800420, /* bctr */ + }; + +/* Shared call stub + The first word of the code must be modified by filling in + the correct TOC offset. + This is exactly as the glink code but without the traceback, + as it won't be an independent function. */ + +static const unsigned long xcoff_stub_shared_call_code[6] = + { + 0x81820000, /* lwz r12,0(r2) */ + 0x90410014, /* stw r2,20(r1) */ + 0x800c0000, /* lwz r0,0(r12) */ + 0x804c0004, /* lwz r2,4(r12) */ + 0x7c0903a6, /* mtctr r0 */ + 0x4e800420, /* bctr */ + }; + /* glink The first word of global linkage code must be modified by filling in @@ -4463,6 +4541,14 @@ static const struct xcoff_backend_data_rec bfd_xcoff_backend_data = /* rtinit */ 64, /* _xcoff_rtinit_size */ xcoff_generate_rtinit, + + /* Stub indirect call. */ + &xcoff_stub_indirect_call_code[0], + 16, /* _xcoff_stub_indirect_call_size */ + + /* Stub shared call. */ + &xcoff_stub_shared_call_code[0], + 24, /* _xcoff_stub_shared_call_size */ }; /* The transfer vector that leads the outside world to all of the above. */ @@ -4645,6 +4731,14 @@ static const struct xcoff_backend_data_rec bfd_pmac_xcoff_backend_data = /* rtinit */ 0, /* _xcoff_rtinit_size */ xcoff_generate_rtinit, + + /* Stub indirect call. */ + &xcoff_stub_indirect_call_code[0], + 16, /* _xcoff_stub_indirect_call_size */ + + /* Stub shared call. */ + &xcoff_stub_shared_call_code[0], + 24, /* _xcoff_stub_shared_call_size */ }; /* The transfer vector that leads the outside world to all of the above. */