From: Siddhesh Poyarekar Date: Fri, 11 Sep 2020 03:48:10 +0000 (+0530) Subject: [Morello] GOT Relocations X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=a1bdea65c73350a0dbcb1e68aaa0e6454a2dd9a1;p=thirdparty%2Fbinutils-gdb.git [Morello] GOT Relocations - Implement R_MORELLO_LD128_GOT_LO12_NC and emit the correct relocation based on the target register size. - Add R_MORELLO_GLOB_DAT and R_MORELLO_RELATIVE dynamic relocations for GOT entries - Add support for capabilities in GOT GOT slots for capabilities need to be 16 byte to accommodate capabilities. For this purpose, we delay initialising size and alignment of the GOT sections until we have walked all relocs in check_relocs. If we encounter capability relocations during the walk, set the GOT entry size and alignment to account for capabilities or leave it pointer sized otherwise. bfd/ChangeLog: 2020-10-20 Siddhesh Poyarekar * elfnn-aarch64.c (GOT_ENTRY_SIZE): Adjust for C64 relocations. Adjust callers. (GOT_RESERVED_HEADER_SLOTS, GOT_CAP): New macros. (elfNN_aarch64_howto_table): Add R_MORELLO_LD128_GOT_LO12_NC and R_MORELLO_GLOB_DAT. (elf_aarch64_link_hash_table): New member c64_rel. (bfd_elfNN_aarch64_set_options): Initialise it. (cap_meta, c64_get_capsize): New functions. (aarch64_reloc_got_type): Use GOT_CAP. (elfNN_aarch64_final_link_relocate): Add R_MORELLO_LD128_GOT_LO12_NC and R_MORELLO_GLOB_DAT. (aarch64_elf_create_got_section): Move section initialisation into a... (aarch64_elf_init_got_section): ... New function. (elfNN_aarch64_size_dynamic_sections): Call it. (elfNN_aarch64_check_relocs): Add R_MORELLO_LD128_GOT_LO12_NC and R_MORELLO_GLOB_DAT. (elfNN_aarch64_finish_dynamic_symbol): Emit C64 relocations when appropriate. (elfNN_aarch64_got_elt_size): New function. (elfNN_aarch64_got_header_size): Return GOT entry size based on c64_rel. (elf_backend_got_elt_size): New macro. * elfxx-aarch64.c (_bfd_aarch64_elf_put_addend, _bfd_aarch64_elf_resolve_relocation): Add BFD_RELOC_MORELLO_LD128_GOT_LO12_NC. * libbfd.h (bfd_reloc_code_real_names): Add BFD_RELOC_MORELLO_GLOB_DAT and BFD_RELOC_MORELLO_LD128_GOT_LO12_NC. * reloc.c: Likewise. * bfd-in2.h: Regenerate. gas/ChangeLog: 2020-10-20 Siddhesh Poyarekar * config/tc-aarch64.c (parse_operands): Emit C64 relocations for got_lo12. Move old relocation checks from... (md_apply_fix): ... here. * testsuite/gas/aarch64/morello-ldst-reloc.d: Add tests. * testsuite/gas/aarch64/morello-ldst-reloc.s: Likewise. include/ChangeLog: 2020-10-20 Siddhesh Poyarekar * elf/aarch64.h: New relocations R_MORELLO_LD128_GOT_LO12_NC and R_MORELLO_GLOB_DAT. ld/ChangeLog: 2020-10-20 Siddhesh Poyarekar * testsuite/ld-aarch64/emit-relocs-morello-1.d: New file. * testsuite/ld-aarch64/emit-relocs-morello-1.s: New test file. * testsuite/ld-aarch64/aarch64-elf.exp: Add it to test runner. --- diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 2b03b838951..1a7dd20a5c3 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,37 @@ +2020-10-20 Siddhesh Poyarekar + + * elfnn-aarch64.c (GOT_ENTRY_SIZE): Adjust for C64 + relocations. Adjust callers. + (GOT_RESERVED_HEADER_SLOTS, GOT_CAP): New macros. + (elfNN_aarch64_howto_table): Add R_MORELLO_LD128_GOT_LO12_NC + and R_MORELLO_GLOB_DAT. + (elf_aarch64_link_hash_table): New member c64_rel. + (bfd_elfNN_aarch64_set_options): Initialise it. + (cap_meta, c64_get_capsize): New functions. + (aarch64_reloc_got_type): Use GOT_CAP. + (elfNN_aarch64_final_link_relocate): Add + R_MORELLO_LD128_GOT_LO12_NC and R_MORELLO_GLOB_DAT. + (aarch64_elf_create_got_section): Move section initialisation + into a... + (aarch64_elf_init_got_section): ... New function. + (elfNN_aarch64_size_dynamic_sections): Call it. + (elfNN_aarch64_check_relocs): Add R_MORELLO_LD128_GOT_LO12_NC + and R_MORELLO_GLOB_DAT. + (elfNN_aarch64_finish_dynamic_symbol): Emit C64 relocations + when appropriate. + (elfNN_aarch64_got_elt_size): New function. + (elfNN_aarch64_got_header_size): Return GOT entry size based + on c64_rel. + (elf_backend_got_elt_size): New macro. + * elfxx-aarch64.c (_bfd_aarch64_elf_put_addend, + _bfd_aarch64_elf_resolve_relocation): Add + BFD_RELOC_MORELLO_LD128_GOT_LO12_NC. + * libbfd.h (bfd_reloc_code_real_names): Add + BFD_RELOC_MORELLO_GLOB_DAT and + BFD_RELOC_MORELLO_LD128_GOT_LO12_NC. + * reloc.c: Likewise. + * bfd-in2.h: Regenerate. + 2020-10-20 Siddhesh Poyarekar Tamar Christina diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h index ed065af3c7b..5f44b187d56 100644 --- a/bfd/bfd-in2.h +++ b/bfd/bfd-in2.h @@ -5702,6 +5702,11 @@ the GOT entry for this symbol. Used in conjunction with BFD_RELOC_AARCH64_ADR_GOT_PAGE. Valid in LP64 ABI only. */ BFD_RELOC_AARCH64_LD64_GOT_LO12_NC, +/* Unsigned 12 bit byte offset for 128 bit load/store from the page of +the GOT entry for this symbol. Used in conjunction with +BFD_RELOC_MORELLO_ADR_GOT_PAGE. Valid in C64 ABI only. */ + BFD_RELOC_MORELLO_LD128_GOT_LO12_NC, + /* Unsigned 12 bit byte offset for 32 bit load/store from the page of the GOT entry for this symbol. Used in conjunction with BFD_RELOC_AARCH64_ADR_GOT_PAGE. Valid in ILP32 ABI only. */ @@ -5942,6 +5947,9 @@ instructions. */ /* Morello Capability initialization. */ BFD_RELOC_MORELLO_CAPINIT, +/* Morello Capability global data. */ + BFD_RELOC_MORELLO_GLOB_DAT, + /* Morello relative relocation for capabilities. */ BFD_RELOC_MORELLO_RELATIVE, diff --git a/bfd/elfnn-aarch64.c b/bfd/elfnn-aarch64.c index 9d53ca71b59..547b6074d24 100644 --- a/bfd/elfnn-aarch64.c +++ b/bfd/elfnn-aarch64.c @@ -266,8 +266,9 @@ elf_aarch64_link_hash_entry. */ #define RELOC_SIZE(HTAB) (sizeof (ElfNN_External_Rela)) -/* GOT Entry size - 8 bytes in ELF64 and 4 bytes in ELF32. */ -#define GOT_ENTRY_SIZE (ARCH_SIZE / 8) +/* GOT Entry size - 16 bytes in C64, 8 bytes in ELF64 and 4 bytes in ELF32. */ +#define GOT_ENTRY_SIZE(htab) (ARCH_SIZE >> (3 - htab->c64_rel)) +#define GOT_RESERVED_HEADER_SLOTS (3) #define PLT_ENTRY_SIZE (32) #define PLT_SMALL_ENTRY_SIZE (16) #define PLT_TLSDESC_ENTRY_SIZE (32) @@ -283,7 +284,7 @@ #define aarch64_compute_jump_table_size(htab) \ (((htab)->root.srelplt == NULL) ? 0 \ - : (htab)->root.srelplt->reloc_count * GOT_ENTRY_SIZE) + : (htab)->root.srelplt->reloc_count * GOT_ENTRY_SIZE (htab)) /* The first entry in a procedure linkage table looks like this if the distance between the PLTGOT and the PLT is < 4GB use @@ -1148,6 +1149,21 @@ static reloc_howto_type elfNN_aarch64_howto_table[] = 0xff8, /* dst_mask */ FALSE), /* pcrel_offset */ + /* LD128: GOT offset G(S) & 0xff0 */ + HOWTO64 (MORELLO_R (LD128_GOT_LO12_NC), /* type */ + 4, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 12, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + MORELLO_R_STR (LD128_GOT_LO12_NC), /* name */ + FALSE, /* partial_inplace */ + 0xff0, /* src_mask */ + 0xff0, /* dst_mask */ + FALSE), /* pcrel_offset */ + /* LD32: GOT offset G(S) & 0xffc */ HOWTO32 (AARCH64_R (LD32_GOT_LO12_NC), /* type */ 2, /* rightshift */ @@ -2227,7 +2243,21 @@ static reloc_howto_type elfNN_aarch64_howto_table[] = ALL_ONES, /* dst_mask */ FALSE), /* pcrel_offset */ - HOWTO64 (MORELLO_R (RELATIVE), /* type */ + HOWTO64 (MORELLO_R (GLOB_DAT),/* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 64, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + MORELLO_R_STR (GLOB_DAT), /* name */ + TRUE, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + HOWTO64 (MORELLO_R (RELATIVE),/* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 64, /* bitsize */ @@ -2732,6 +2762,7 @@ elfNN_aarch64_mkobject (bfd *abfd) #define GOT_TLS_GD 2 #define GOT_TLS_IE 4 #define GOT_TLSDESC_GD 8 +#define GOT_CAP 16 #define GOT_TLS_GD_ANY_P(type) ((type & GOT_TLS_GD) || (type & GOT_TLSDESC_GD)) @@ -2858,6 +2889,7 @@ struct elf_aarch64_link_hash_table /* Used for capability relocations. */ asection *srelcaps; + int c64_rel; }; /* Create an entry in an AArch64 ELF linker hash table. */ @@ -4974,6 +5006,7 @@ bfd_elfNN_aarch64_set_options (struct bfd *output_bfd, workaround. */ globals->fix_erratum_843419 = fix_erratum_843419; globals->no_apply_dynamic_relocs = no_apply_dynamic_relocs; + globals->c64_rel = 0; BFD_ASSERT (is_aarch64_elf (output_bfd)); elf_aarch64_tdata (output_bfd)->no_enum_size_warning = no_enum_warn; @@ -5141,7 +5174,6 @@ aarch64_reloc_got_type (bfd_reloc_code_real_type r_type) switch (r_type) { case BFD_RELOC_AARCH64_ADR_GOT_PAGE: - case BFD_RELOC_MORELLO_ADR_GOT_PAGE: case BFD_RELOC_AARCH64_GOT_LD_PREL19: case BFD_RELOC_AARCH64_LD32_GOTPAGE_LO14: case BFD_RELOC_AARCH64_LD32_GOT_LO12_NC: @@ -5152,6 +5184,10 @@ aarch64_reloc_got_type (bfd_reloc_code_real_type r_type) case BFD_RELOC_AARCH64_MOVW_GOTOFF_G1: return GOT_NORMAL; + case BFD_RELOC_MORELLO_ADR_GOT_PAGE: + case BFD_RELOC_MORELLO_LD128_GOT_LO12_NC: + return GOT_CAP; + case BFD_RELOC_AARCH64_TLSGD_ADD_LO12_NC: case BFD_RELOC_AARCH64_TLSGD_ADR_PAGE21: case BFD_RELOC_AARCH64_TLSGD_ADR_PREL21: @@ -5961,6 +5997,7 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto, case BFD_RELOC_AARCH64_MOVW_GOTOFF_G1: case BFD_RELOC_AARCH64_LD64_GOTOFF_LO15: case BFD_RELOC_AARCH64_LD64_GOT_LO12_NC: + case BFD_RELOC_MORELLO_LD128_GOT_LO12_NC: base_got = globals->root.sgot; off = h->got.offset; @@ -5979,13 +6016,13 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto, { plt_index = ((h->plt.offset - globals->plt_header_size) / globals->plt_entry_size); - off = (plt_index + 3) * GOT_ENTRY_SIZE; + off = (plt_index + 3) * GOT_ENTRY_SIZE (globals); base_got = globals->root.sgotplt; } else { plt_index = h->plt.offset / globals->plt_entry_size; - off = plt_index * GOT_ENTRY_SIZE; + off = plt_index * GOT_ENTRY_SIZE (globals); base_got = globals->root.igotplt; } @@ -6303,6 +6340,7 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto, case BFD_RELOC_AARCH64_LD32_GOT_LO12_NC: case BFD_RELOC_AARCH64_LD64_GOTPAGE_LO15: case BFD_RELOC_AARCH64_LD64_GOT_LO12_NC: + case BFD_RELOC_MORELLO_LD128_GOT_LO12_NC: case BFD_RELOC_AARCH64_LD64_GOTOFF_LO15: case BFD_RELOC_AARCH64_MOVW_GOTOFF_G0_NC: case BFD_RELOC_AARCH64_MOVW_GOTOFF_G1: @@ -6333,7 +6371,11 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto, /* Record the GOT entry address which will be used when generating RELATIVE relocation. */ if (relative_reloc) - got_entry_addr = value; + { + got_entry_addr = value; + base_got = globals->root.sgot; + off = h->got.offset & ~1; + } if (aarch64_relocation_aginst_gp_p (bfd_r_type)) addend = (globals->root.sgot->output_section->vma @@ -6341,6 +6383,7 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto, value = _bfd_aarch64_elf_resolve_relocation (input_bfd, bfd_r_type, place, value, addend, weak_undef_p); + value |= h->target_internal; } else { @@ -6389,6 +6432,8 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto, value = _bfd_aarch64_elf_resolve_relocation (input_bfd, bfd_r_type, place, value, addend, weak_undef_p); + + value |= sym->st_target_internal; } if (relative_reloc) @@ -6396,13 +6441,34 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto, asection *s; Elf_Internal_Rela outrel; + enum elf_aarch64_reloc_type rtype = AARCH64_R (RELATIVE); + + /* For a C64 relative relocation, also add size and permissions into + the frag. */ + if (bfd_r_type == BFD_RELOC_MORELLO_LD128_GOT_LO12_NC + || bfd_r_type == BFD_RELOC_MORELLO_ADR_GOT_PAGE) + { + bfd_reloc_status_type ret; + + ret = c64_fixup_frag (input_bfd, info, bfd_r_type, sym, h, + sym_sec, base_got->contents + off + 8, + orig_value, 0); + + if (ret != bfd_reloc_continue) + return ret; + + rtype = MORELLO_R (RELATIVE); + outrel.r_addend = 0; + } + else + outrel.r_addend = orig_value; + s = globals->root.srelgot; if (s == NULL) abort (); outrel.r_offset = got_entry_addr; - outrel.r_info = ELFNN_R_INFO (0, AARCH64_R (RELATIVE)); - outrel.r_addend = orig_value; + outrel.r_info = ELFNN_R_INFO (0, rtype); elf_append_rela (output_bfd, s, &outrel); } break; @@ -7344,14 +7410,14 @@ elfNN_aarch64_relocate_section (bfd *output_bfd, base address when invoke runtime TLS resolver. */ bfd_put_NN (output_bfd, 0, globals->root.sgot->contents + off - + GOT_ENTRY_SIZE); + + GOT_ENTRY_SIZE (globals)); } else if (indx == 0) { bfd_put_NN (output_bfd, relocation - dtpoff_base (info), globals->root.sgot->contents + off - + GOT_ENTRY_SIZE); + + GOT_ENTRY_SIZE (globals)); } else { @@ -7364,7 +7430,7 @@ elfNN_aarch64_relocate_section (bfd *output_bfd, rela.r_offset = (globals->root.sgot->output_section->vma + globals->root.sgot->output_offset + off - + GOT_ENTRY_SIZE); + + GOT_ENTRY_SIZE (globals)); loc = globals->root.srelgot->contents; loc += globals->root.srelgot->reloc_count++ @@ -7372,7 +7438,7 @@ elfNN_aarch64_relocate_section (bfd *output_bfd, bfd_elfNN_swap_reloca_out (output_bfd, &rela, loc); bfd_put_NN (output_bfd, (bfd_vma) 0, globals->root.sgot->contents + off - + GOT_ENTRY_SIZE); + + GOT_ENTRY_SIZE (globals)); } } else @@ -7382,7 +7448,7 @@ elfNN_aarch64_relocate_section (bfd *output_bfd, bfd_put_NN (output_bfd, relocation - dtpoff_base (info), globals->root.sgot->contents + off - + GOT_ENTRY_SIZE); + + GOT_ENTRY_SIZE (globals)); } symbol_got_offset_mark (input_bfd, h, r_symndx); @@ -7497,7 +7563,7 @@ elfNN_aarch64_relocate_section (bfd *output_bfd, bfd_put_NN (output_bfd, (bfd_vma) 0, globals->root.sgotplt->contents + off + globals->sgotplt_jump_table_size + - GOT_ENTRY_SIZE); + GOT_ENTRY_SIZE (globals)); } symbol_tlsdesc_got_offset_mark (input_bfd, h, r_symndx); @@ -7925,6 +7991,40 @@ elfNN_aarch64_allocate_local_symbols (bfd *abfd, unsigned number) return TRUE; } +/* Initialise the .got section to hold the global offset table. */ + +static void +aarch64_elf_init_got_section (bfd *abfd, struct bfd_link_info *info) +{ + const struct elf_backend_data *bed = get_elf_backend_data (abfd); + asection *s; + struct elf_aarch64_link_hash_table *globals = elf_aarch64_hash_table (info); + unsigned int align = bed->s->log_file_align + globals->c64_rel; + + if (globals->root.sgot != NULL) + { + bfd_set_section_alignment (globals->root.srelgot, + bed->s->log_file_align); + bfd_set_section_alignment (globals->root.sgot, align); + globals->root.sgot->size += GOT_ENTRY_SIZE (globals); + } + + if (globals->root.igotplt != NULL) + bfd_set_section_alignment (globals->root.igotplt, align); + + s = globals->root.sgot; + + if (globals->root.sgotplt != NULL) + { + bfd_set_section_alignment (globals->root.sgotplt, align); + s = globals->root.sgotplt; + } + + /* The first bit of the global offset table is the header. */ + if (s != NULL) + s->size += bed->got_header_size (info); +} + /* Create the .got section to hold the global offset table. */ static bfd_boolean @@ -7947,17 +8047,14 @@ aarch64_elf_create_got_section (bfd *abfd, struct bfd_link_info *info) ? ".rela.got" : ".rel.got"), (bed->dynamic_sec_flags | SEC_READONLY)); - if (s == NULL - || !bfd_set_section_alignment (s, bed->s->log_file_align)) + if (s == NULL) return FALSE; htab->srelgot = s; s = bfd_make_section_anyway_with_flags (abfd, ".got", flags); - if (s == NULL - || !bfd_set_section_alignment (s, bed->s->log_file_align)) + if (s == NULL) return FALSE; htab->sgot = s; - htab->sgot->size += GOT_ENTRY_SIZE; if (bed->want_got_sym) { @@ -7975,15 +8072,11 @@ aarch64_elf_create_got_section (bfd *abfd, struct bfd_link_info *info) if (bed->want_got_plt) { s = bfd_make_section_anyway_with_flags (abfd, ".got.plt", flags); - if (s == NULL - || !bfd_set_section_alignment (s, bed->s->log_file_align)) + if (s == NULL) return FALSE; htab->sgotplt = s; } - /* The first bit of the global offset table is the header. */ - s->size += bed->got_header_size (info); - return TRUE; } @@ -8110,6 +8203,7 @@ elfNN_aarch64_check_relocs (bfd *abfd, struct bfd_link_info *info, case BFD_RELOC_AARCH64_LD64_GOTOFF_LO15: case BFD_RELOC_AARCH64_LD64_GOTPAGE_LO15: case BFD_RELOC_AARCH64_LD64_GOT_LO12_NC: + case BFD_RELOC_MORELLO_LD128_GOT_LO12_NC: case BFD_RELOC_AARCH64_MOVW_GOTOFF_G0_NC: case BFD_RELOC_AARCH64_MOVW_GOTOFF_G1: case BFD_RELOC_AARCH64_NN: @@ -8305,8 +8399,12 @@ elfNN_aarch64_check_relocs (bfd *abfd, struct bfd_link_info *info, /* RR: We probably want to keep a consistency check that there are no dangling GOT_PAGE relocs. */ - case BFD_RELOC_AARCH64_ADR_GOT_PAGE: case BFD_RELOC_MORELLO_ADR_GOT_PAGE: + case BFD_RELOC_MORELLO_LD128_GOT_LO12_NC: + htab->c64_rel = 1; + /* Fall through. */ + + case BFD_RELOC_AARCH64_ADR_GOT_PAGE: case BFD_RELOC_AARCH64_GOT_LD_PREL19: case BFD_RELOC_AARCH64_LD32_GOTPAGE_LO14: case BFD_RELOC_AARCH64_LD32_GOT_LO12_NC: @@ -8371,7 +8469,8 @@ elfNN_aarch64_check_relocs (bfd *abfd, struct bfd_link_info *info, is a TLS/non-TLS mismatch, based on the symbol type. So just combine any TLS types needed. */ if (old_got_type != GOT_UNKNOWN && old_got_type != GOT_NORMAL - && got_type != GOT_NORMAL) + && got_type != GOT_NORMAL && old_got_type != GOT_CAP + && got_type != GOT_CAP) got_type |= old_got_type; /* If the symbol is accessed by both IE and GD methods, we @@ -8381,7 +8480,10 @@ elfNN_aarch64_check_relocs (bfd *abfd, struct bfd_link_info *info, if ((got_type & GOT_TLS_IE) && GOT_TLS_GD_ANY_P (got_type)) got_type &= ~ (GOT_TLSDESC_GD | GOT_TLS_GD); - if (old_got_type != got_type) + /* GOT_CAP has higher precedence due to higher alignment and size + requirements, so do not overwrite it. XXX This should be + revisited when we add TLS relocations. */ + if (old_got_type != got_type && old_got_type != GOT_CAP) { if (h != NULL) elf_aarch64_hash_entry (h)->got_type = got_type; @@ -8913,7 +9015,7 @@ elfNN_aarch64_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) /* We also need to make an entry in the .got.plt section, which will be placed in the .got section by the linker script. */ - htab->root.sgotplt->size += GOT_ENTRY_SIZE; + htab->root.sgotplt->size += GOT_ENTRY_SIZE (htab); /* We also need to make an entry in the .rela.plt section. */ htab->root.srelplt->size += RELOC_SIZE (htab); @@ -8975,10 +9077,11 @@ elfNN_aarch64_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) if (got_type == GOT_UNKNOWN) { } - else if (got_type == GOT_NORMAL) + else if (got_type == GOT_NORMAL + || got_type == GOT_CAP) { h->got.offset = htab->root.sgot->size; - htab->root.sgot->size += GOT_ENTRY_SIZE; + htab->root.sgot->size += GOT_ENTRY_SIZE (htab); if ((ELF_ST_VISIBILITY (h->other) == STV_DEFAULT || h->root.type != bfd_link_hash_undefweak) && (bfd_link_pic (info) @@ -8998,20 +9101,20 @@ elfNN_aarch64_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) eh->tlsdesc_got_jump_table_offset = (htab->root.sgotplt->size - aarch64_compute_jump_table_size (htab)); - htab->root.sgotplt->size += GOT_ENTRY_SIZE * 2; + htab->root.sgotplt->size += GOT_ENTRY_SIZE (htab) * 2; h->got.offset = (bfd_vma) - 2; } if (got_type & GOT_TLS_GD) { h->got.offset = htab->root.sgot->size; - htab->root.sgot->size += GOT_ENTRY_SIZE * 2; + htab->root.sgot->size += GOT_ENTRY_SIZE (htab) * 2; } if (got_type & GOT_TLS_IE) { h->got.offset = htab->root.sgot->size; - htab->root.sgot->size += GOT_ENTRY_SIZE; + htab->root.sgot->size += GOT_ENTRY_SIZE (htab); } indx = h && h->dynindx != -1 ? h->dynindx : 0; @@ -9178,7 +9281,7 @@ elfNN_aarch64_allocate_ifunc_dynrelocs (struct elf_link_hash_entry *h, &h->dyn_relocs, htab->plt_entry_size, htab->plt_header_size, - GOT_ENTRY_SIZE, + GOT_ENTRY_SIZE (htab), FALSE); return TRUE; } @@ -9206,7 +9309,7 @@ elfNN_aarch64_allocate_local_ifunc_dynrelocs (void **slot, void *inf) though ! */ static bfd_boolean -elfNN_aarch64_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, +elfNN_aarch64_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info) { struct elf_aarch64_link_hash_table *htab; @@ -9232,6 +9335,8 @@ elfNN_aarch64_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, } } + aarch64_elf_init_got_section (output_bfd, info); + /* Set up .got offsets for local syms, and space for local dynamic relocs. */ for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link.next) @@ -9287,21 +9392,22 @@ elfNN_aarch64_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, locals[i].tlsdesc_got_jump_table_offset = (htab->root.sgotplt->size - aarch64_compute_jump_table_size (htab)); - htab->root.sgotplt->size += GOT_ENTRY_SIZE * 2; + htab->root.sgotplt->size += GOT_ENTRY_SIZE (htab) * 2; locals[i].got_offset = (bfd_vma) - 2; } if (got_type & GOT_TLS_GD) { locals[i].got_offset = htab->root.sgot->size; - htab->root.sgot->size += GOT_ENTRY_SIZE * 2; + htab->root.sgot->size += GOT_ENTRY_SIZE (htab) * 2; } if (got_type & GOT_TLS_IE - || got_type & GOT_NORMAL) + || got_type & GOT_NORMAL + || got_type & GOT_CAP) { locals[i].got_offset = htab->root.sgot->size; - htab->root.sgot->size += GOT_ENTRY_SIZE; + htab->root.sgot->size += GOT_ENTRY_SIZE (htab); } if (got_type == GOT_UNKNOWN) @@ -9321,7 +9427,8 @@ elfNN_aarch64_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, htab->root.srelgot->size += RELOC_SIZE (htab) * 2; if (got_type & GOT_TLS_IE - || got_type & GOT_NORMAL) + || got_type & GOT_NORMAL + || got_type & GOT_CAP) htab->root.srelgot->size += RELOC_SIZE (htab); } } @@ -9372,7 +9479,7 @@ elfNN_aarch64_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, htab->root.splt->size += htab->tlsdesc_plt_entry_size; htab->root.tlsdesc_got = htab->root.sgot->size; - htab->root.sgot->size += GOT_ENTRY_SIZE; + htab->root.sgot->size += GOT_ENTRY_SIZE (htab); } } @@ -9542,12 +9649,12 @@ elfNN_aarch64_create_small_pltn_entry (struct elf_link_hash_entry *h, if (plt == htab->root.splt) { plt_index = (h->plt.offset - htab->plt_header_size) / htab->plt_entry_size; - got_offset = (plt_index + 3) * GOT_ENTRY_SIZE; + got_offset = (plt_index + 3) * GOT_ENTRY_SIZE (htab); } else { plt_index = h->plt.offset / htab->plt_entry_size; - got_offset = plt_index * GOT_ENTRY_SIZE; + got_offset = plt_index * GOT_ENTRY_SIZE (htab); } plt_entry = plt->contents + h->plt.offset; @@ -9723,8 +9830,11 @@ elfNN_aarch64_finish_dynamic_symbol (bfd *output_bfd, } } + bfd_boolean is_c64 = elf_aarch64_hash_entry (h)->got_type == GOT_CAP; + if (h->got.offset != (bfd_vma) - 1 - && elf_aarch64_hash_entry (h)->got_type == GOT_NORMAL + && (elf_aarch64_hash_entry (h)->got_type == GOT_NORMAL + || elf_aarch64_hash_entry (h)->got_type == GOT_CAP) /* Undefined weak symbol in static PIE resolves to 0 without any dynamic relocations. */ && !UNDEFWEAK_NO_DYNAMIC_RELOC (info, h)) @@ -9774,10 +9884,18 @@ elfNN_aarch64_finish_dynamic_symbol (bfd *output_bfd, return FALSE; BFD_ASSERT ((h->got.offset & 1) != 0); - rela.r_info = ELFNN_R_INFO (0, AARCH64_R (RELATIVE)); - rela.r_addend = (h->root.u.def.value - + h->root.u.def.section->output_section->vma - + h->root.u.def.section->output_offset); + if (is_c64) + { + rela.r_info = ELFNN_R_INFO (0, MORELLO_R (RELATIVE)); + rela.r_addend = 0; + } + else + { + rela.r_info = ELFNN_R_INFO (0, AARCH64_R (RELATIVE)); + rela.r_addend = (h->root.u.def.value + + h->root.u.def.section->output_section->vma + + h->root.u.def.section->output_offset); + } } else { @@ -9785,7 +9903,9 @@ elfNN_aarch64_finish_dynamic_symbol (bfd *output_bfd, BFD_ASSERT ((h->got.offset & 1) == 0); bfd_put_NN (output_bfd, (bfd_vma) 0, htab->root.sgot->contents + h->got.offset); - rela.r_info = ELFNN_R_INFO (h->dynindx, AARCH64_R (GLOB_DAT)); + rela.r_info = ELFNN_R_INFO (h->dynindx, + (is_c64 ? MORELLO_R (GLOB_DAT) + : AARCH64_R (GLOB_DAT))); rela.r_addend = 0; } @@ -9878,7 +9998,7 @@ elfNN_aarch64_init_small_plt0_entry (bfd *output_bfd ATTRIBUTE_UNUSED, plt_got_2nd_ent = (htab->root.sgotplt->output_section->vma + htab->root.sgotplt->output_offset - + GOT_ENTRY_SIZE * 2); + + GOT_ENTRY_SIZE (htab) * 2); plt_base = htab->root.splt->output_section->vma + htab->root.splt->output_offset; @@ -10070,10 +10190,11 @@ elfNN_aarch64_finish_dynamic_sections (bfd *output_bfd, /* Write GOT[1] and GOT[2], needed for the dynamic linker. */ bfd_put_NN (output_bfd, (bfd_vma) 0, - htab->root.sgotplt->contents + GOT_ENTRY_SIZE); + htab->root.sgotplt->contents + GOT_ENTRY_SIZE (htab)); bfd_put_NN (output_bfd, (bfd_vma) 0, - htab->root.sgotplt->contents + GOT_ENTRY_SIZE * 2); + (htab->root.sgotplt->contents + + GOT_ENTRY_SIZE (htab) * 2)); } if (htab->root.sgot) @@ -10087,12 +10208,12 @@ elfNN_aarch64_finish_dynamic_sections (bfd *output_bfd, } elf_section_data (htab->root.sgotplt->output_section)-> - this_hdr.sh_entsize = GOT_ENTRY_SIZE; + this_hdr.sh_entsize = GOT_ENTRY_SIZE (htab); } if (htab->root.sgot && htab->root.sgot->size > 0) elf_section_data (htab->root.sgot->output_section)->this_hdr.sh_entsize - = GOT_ENTRY_SIZE; + = GOT_ENTRY_SIZE (htab); /* Fill PLT and GOT entries for local STT_GNU_IFUNC symbols. */ htab_traverse (htab->loc_hash_table, @@ -10315,13 +10436,29 @@ aarch64_elfNN_swap_symbol_out (bfd *abfd, bfd_elfNN_swap_symbol_out (abfd, &newsym, cdst, shndx); } +/* Define the size of a GOT element for the generic mid-end. */ + +static bfd_vma +elfNN_aarch64_got_elt_size (bfd *abfd ATTRIBUTE_UNUSED, + struct bfd_link_info *info, + struct elf_link_hash_entry *h ATTRIBUTE_UNUSED, + bfd *ibfd ATTRIBUTE_UNUSED, + unsigned long symndx ATTRIBUTE_UNUSED) +{ + struct elf_aarch64_link_hash_table *htab = elf_aarch64_hash_table (info); + + return GOT_ENTRY_SIZE (htab); +} + /* Define the size of a GOT header, which is the minimum size of the GOT section when one is needed. */ static bfd_vma -elfNN_aarch64_got_header_size (struct bfd_link_info *info ATTRIBUTE_UNUSED) +elfNN_aarch64_got_header_size (struct bfd_link_info *info) { - return GOT_ENTRY_SIZE * 3; + struct elf_aarch64_link_hash_table *htab = elf_aarch64_hash_table (info); + + return GOT_ENTRY_SIZE (htab) * GOT_RESERVED_HEADER_SLOTS; } /* We use this so we can override certain functions @@ -10471,6 +10608,9 @@ const struct elf_size_info elfNN_aarch64_size_info = #define elf_backend_got_header_size \ elfNN_aarch64_got_header_size +#define elf_backend_got_elt_size \ + elfNN_aarch64_got_elt_size + #define elf_backend_can_refcount 1 #define elf_backend_can_gc_sections 1 #define elf_backend_plt_readonly 1 diff --git a/bfd/elfxx-aarch64.c b/bfd/elfxx-aarch64.c index 6a905b92900..cc58c174196 100644 --- a/bfd/elfxx-aarch64.c +++ b/bfd/elfxx-aarch64.c @@ -303,6 +303,7 @@ _bfd_aarch64_elf_put_addend (bfd *abfd, case BFD_RELOC_AARCH64_LD64_GOTOFF_LO15: case BFD_RELOC_AARCH64_LD64_GOTPAGE_LO15: case BFD_RELOC_AARCH64_LD64_GOT_LO12_NC: + case BFD_RELOC_MORELLO_LD128_GOT_LO12_NC: case BFD_RELOC_AARCH64_LDST128_LO12: case BFD_RELOC_AARCH64_LDST16_LO12: case BFD_RELOC_AARCH64_LDST32_LO12: @@ -556,6 +557,7 @@ _bfd_aarch64_elf_resolve_relocation (bfd *input_bfd, case BFD_RELOC_AARCH64_ADD_LO12: case BFD_RELOC_AARCH64_LD32_GOT_LO12_NC: case BFD_RELOC_AARCH64_LD64_GOT_LO12_NC: + case BFD_RELOC_MORELLO_LD128_GOT_LO12_NC: case BFD_RELOC_AARCH64_LDST128_LO12: case BFD_RELOC_AARCH64_LDST16_LO12: case BFD_RELOC_AARCH64_LDST32_LO12: diff --git a/bfd/libbfd.h b/bfd/libbfd.h index 877a6d677c2..c106292175d 100644 --- a/bfd/libbfd.h +++ b/bfd/libbfd.h @@ -3035,6 +3035,7 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@", "BFD_RELOC_AARCH64_ADR_GOT_PAGE", "BFD_RELOC_MORELLO_ADR_GOT_PAGE", "BFD_RELOC_AARCH64_LD64_GOT_LO12_NC", + "BFD_RELOC_MORELLO_LD128_GOT_LO12_NC", "BFD_RELOC_AARCH64_LD32_GOT_LO12_NC", "BFD_RELOC_AARCH64_MOVW_GOTOFF_G0_NC", "BFD_RELOC_AARCH64_MOVW_GOTOFF_G1", @@ -3108,6 +3109,7 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@", "BFD_RELOC_AARCH64_TLSDESC", "BFD_RELOC_AARCH64_IRELATIVE", "BFD_RELOC_MORELLO_CAPINIT", + "BFD_RELOC_MORELLO_GLOB_DAT", "BFD_RELOC_MORELLO_RELATIVE", "BFD_RELOC_AARCH64_RELOC_END", "BFD_RELOC_AARCH64_GAS_INTERNAL_FIXUP", diff --git a/bfd/reloc.c b/bfd/reloc.c index 674d6c4e5f0..a5f64c177ad 100644 --- a/bfd/reloc.c +++ b/bfd/reloc.c @@ -7220,6 +7220,12 @@ ENUMDOC Unsigned 12 bit byte offset for 64 bit load/store from the page of the GOT entry for this symbol. Used in conjunction with BFD_RELOC_AARCH64_ADR_GOT_PAGE. Valid in LP64 ABI only. +ENUM + BFD_RELOC_MORELLO_LD128_GOT_LO12_NC +ENUMDOC + Unsigned 12 bit byte offset for 128 bit load/store from the page of + the GOT entry for this symbol. Used in conjunction with + BFD_RELOC_MORELLO_ADR_GOT_PAGE. Valid in C64 ABI only. ENUM BFD_RELOC_AARCH64_LD32_GOT_LO12_NC ENUMDOC @@ -7533,6 +7539,10 @@ ENUM BFD_RELOC_MORELLO_CAPINIT ENUMDOC Morello Capability initialization. +ENUM + BFD_RELOC_MORELLO_GLOB_DAT +ENUMDOC + Morello Capability global data. ENUM BFD_RELOC_MORELLO_RELATIVE ENUMDOC diff --git a/gas/ChangeLog b/gas/ChangeLog index 86b92bb467a..d0ae46139ca 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,11 @@ +2020-10-20 Siddhesh Poyarekar + + * config/tc-aarch64.c (parse_operands): Emit C64 relocations + for got_lo12. Move old relocation checks from... + (md_apply_fix): ... here. + * testsuite/gas/aarch64/morello-ldst-reloc.d: Add tests. + * testsuite/gas/aarch64/morello-ldst-reloc.s: Likewise. + 2020-10-20 Siddhesh Poyarekar * config/tc-aarch64.c (ldst_lo12_determine_real_reloc_type): diff --git a/gas/config/tc-aarch64.c b/gas/config/tc-aarch64.c index 55e0358bc11..715ac2d2e9b 100644 --- a/gas/config/tc-aarch64.c +++ b/gas/config/tc-aarch64.c @@ -6882,6 +6882,9 @@ addr_uimm: inst.reloc.type = ldst_lo12_determine_real_reloc_type (); } + else if (inst.reloc.type == BFD_RELOC_AARCH64_LD_GOT_LO12_NC + && inst.base.operands[0].qualifier == AARCH64_OPND_QLF_CA) + inst.reloc.flags = FIXUP_F_C64; /* Leave qualifier to be determined by libopcodes. */ break; @@ -8747,9 +8750,12 @@ md_apply_fix (fixS * fixP, valueT * valP, segT seg) case BFD_RELOC_AARCH64_LD_GOT_LO12_NC: /* Should always be exported to object file, see aarch64_force_relocation(). */ - fixP->fx_r_type = (ilp32_p - ? BFD_RELOC_AARCH64_LD32_GOT_LO12_NC - : BFD_RELOC_AARCH64_LD64_GOT_LO12_NC); + if (fixP->tc_fix_data.c64) + fixP->fx_r_type = BFD_RELOC_MORELLO_LD128_GOT_LO12_NC; + else if (ilp32_p) + fixP->fx_r_type = BFD_RELOC_AARCH64_LD32_GOT_LO12_NC; + else + fixP->fx_r_type = BFD_RELOC_AARCH64_LD64_GOT_LO12_NC; gas_assert (!fixP->fx_done); gas_assert (seg->use_rela_p); break; @@ -8772,6 +8778,7 @@ md_apply_fix (fixS * fixP, valueT * valP, segT seg) case BFD_RELOC_AARCH64_LDST32_LO12: case BFD_RELOC_AARCH64_LDST64_LO12: case BFD_RELOC_AARCH64_LDST8_LO12: + case BFD_RELOC_MORELLO_LD128_GOT_LO12_NC: /* Should always be exported to object file, see aarch64_force_relocation(). */ gas_assert (!fixP->fx_done); @@ -8926,6 +8933,7 @@ aarch64_force_relocation (struct fix *fixp) case BFD_RELOC_AARCH64_LD64_GOTOFF_LO15: case BFD_RELOC_AARCH64_LD64_GOTPAGE_LO15: case BFD_RELOC_AARCH64_LD64_GOT_LO12_NC: + case BFD_RELOC_MORELLO_LD128_GOT_LO12_NC: case BFD_RELOC_AARCH64_LDST128_LO12: case BFD_RELOC_AARCH64_LDST16_LO12: case BFD_RELOC_AARCH64_LDST32_LO12: diff --git a/gas/testsuite/gas/aarch64/morello-ldst-reloc.d b/gas/testsuite/gas/aarch64/morello-ldst-reloc.d index 7e4fcf4f079..d2fb08ec9d1 100644 --- a/gas/testsuite/gas/aarch64/morello-ldst-reloc.d +++ b/gas/testsuite/gas/aarch64/morello-ldst-reloc.d @@ -19,3 +19,15 @@ Disassembly of section \.text: .* : .*: 02000000 add c0, c0, #0x0 .*: R_AARCH64_ADD_ABS_LO12_NC ptr + +.* : + .*: 90800002 adrp c2, 0 <_start> + .*: R_MORELLO_ADR_GOT_PAGE \.data\+0x10 + .*: c2400042 ldr c2, \[c2\] + .*: R_MORELLO_LD128_GOT_LO12_NC \.data\+0x10 + .*: 82600042 ldr c2, \[x2\] + .*: R_MORELLO_LD128_GOT_LO12_NC \.data\+0x20 + .*: f9400042 ldr x2, \[c2\] + .*: R_AARCH64_LD64_GOT_LO12_NC \.data\+0x20 + .*: 82600c42 ldr x2, \[x2\] + .*: R_AARCH64_LD64_GOT_LO12_NC \.data\+0x20 diff --git a/gas/testsuite/gas/aarch64/morello-ldst-reloc.s b/gas/testsuite/gas/aarch64/morello-ldst-reloc.s index 2aa4bbe3ec7..513c760576a 100644 --- a/gas/testsuite/gas/aarch64/morello-ldst-reloc.s +++ b/gas/testsuite/gas/aarch64/morello-ldst-reloc.s @@ -6,6 +6,8 @@ cap: .capinit pad .8byte 0x0 .8byte 0x0 +ptr: + .8byte pad .text .globl _start @@ -18,3 +20,10 @@ _start: add: add c0, c0, :lo12:ptr + +f1: + adrp c2, :got:cap + ldr c2, [c2, :got_lo12:cap] + ldr c2, [x2, :got_lo12:ptr] + ldr x2, [c2, :got_lo12:ptr] + ldr x2, [x2, :got_lo12:ptr] diff --git a/include/ChangeLog b/include/ChangeLog index fe301b86158..d50893b0e2b 100644 --- a/include/ChangeLog +++ b/include/ChangeLog @@ -1,3 +1,8 @@ +2020-10-20 Siddhesh Poyarekar + + * elf/aarch64.h: New relocations R_MORELLO_LD128_GOT_LO12_NC + and R_MORELLO_GLOB_DAT. + 2020-10-20 Siddhesh Poyarekar * elf/aarch64.h (R_MORELLO_CAPINIT, R_MORELLO_RELATIVE): New diff --git a/include/elf/aarch64.h b/include/elf/aarch64.h index cbead77370c..3aa27712aa9 100644 --- a/include/elf/aarch64.h +++ b/include/elf/aarch64.h @@ -455,9 +455,12 @@ RELOC_NUMBER (R_MORELLO_ADR_PREL_PG_HI20_NC, 57350) RELOC_NUMBER (R_MORELLO_ADR_GOT_PAGE, 57351) +RELOC_NUMBER (R_MORELLO_LD128_GOT_LO12_NC, 57352) + /* Morello dynamic relocations. */ RELOC_NUMBER (R_MORELLO_CAPINIT, 59392) +RELOC_NUMBER (R_MORELLO_GLOB_DAT, 59393) RELOC_NUMBER (R_MORELLO_RELATIVE, 59395) END_RELOC_NUMBERS (R_AARCH64_end) diff --git a/ld/ChangeLog b/ld/ChangeLog index 803808a8821..b952f416e0c 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,9 @@ +2020-10-20 Siddhesh Poyarekar + + * testsuite/ld-aarch64/emit-relocs-morello-1.d: New file. + * testsuite/ld-aarch64/emit-relocs-morello-1.s: New test file. + * testsuite/ld-aarch64/aarch64-elf.exp: Add it to test runner. + 2020-10-20 Siddhesh Poyarekar * testsuite/ld-aarch64/aarch64-elf.exp: Add test. diff --git a/ld/testsuite/ld-aarch64/aarch64-elf.exp b/ld/testsuite/ld-aarch64/aarch64-elf.exp index bd2590a721c..ac0a998df90 100644 --- a/ld/testsuite/ld-aarch64/aarch64-elf.exp +++ b/ld/testsuite/ld-aarch64/aarch64-elf.exp @@ -237,6 +237,7 @@ run_dump_test_lp64 "emit-relocs-558" run_dump_test_lp64 "emit-relocs-558-overflow" run_dump_test_lp64 "emit-relocs-559" run_dump_test_lp64 "emit-relocs-560" +run_dump_test_lp64 "emit-relocs-morello-1" run_dump_test_lp64 "morello-capinit" diff --git a/ld/testsuite/ld-aarch64/emit-relocs-morello-1.d b/ld/testsuite/ld-aarch64/emit-relocs-morello-1.d new file mode 100644 index 00000000000..ee272150263 --- /dev/null +++ b/ld/testsuite/ld-aarch64/emit-relocs-morello-1.d @@ -0,0 +1,36 @@ +#source: emit-relocs-morello-1.s +#as: -march=morello+c64 +#ld: -pie -static +#objdump: -DR -j .got -j .data -j .text + +.*: file format .* + + +Disassembly of section .text: + +.* <_start>: + .*: c240.800 ldr c0, \[c0, #[0-9af]+\] + +Disassembly of section .got: + +.* <.got>: + .*: [0-9a-f]+ .* + ... + .*: [0-9a-f]+ .* + .*: R_MORELLO_RELATIVE \*ABS\* + .*: 00000000 .* + .*: 00000302 .* + .*: 00000000 .* + +Disassembly of section .data: + +.* : + .*: 00424242 .* + ... + +.* : + .*: [0-9a-f]+ .* + .*: R_MORELLO_RELATIVE \*ABS\* + .*: 00000000 .* + .*: 00000302 .* + .*: 00000000 .* diff --git a/ld/testsuite/ld-aarch64/emit-relocs-morello-1.s b/ld/testsuite/ld-aarch64/emit-relocs-morello-1.s new file mode 100644 index 00000000000..eba7bc1f362 --- /dev/null +++ b/ld/testsuite/ld-aarch64/emit-relocs-morello-1.s @@ -0,0 +1,20 @@ +.data +.global val +val: + .byte 0x42 + .byte 0x42 + .byte 0x42 + .size val, .-val + +.align 4 +.global cap +cap: + .capinit val + .8byte 0 + .8byte 0 + .size cap, .-cap + +.text +.global _start +_start: + ldr c0, [c0, :got_lo12:val]