diff options
author | Nelson Chu <nelson@rivosinc.com> | 2023-03-25 08:41:11 +0800 |
---|---|---|
committer | Nelson Chu <nelson@rivosinc.com> | 2023-03-30 07:40:02 +0800 |
commit | 23068b02d3a6743658110c7662178fdebbe2ac6a (patch) | |
tree | fc44873b1f3c23c36c214916978456ee4b2d1c24 | |
parent | 2fc3b8a4cb8439fc53975c4e70336d76e3ddc531 (diff) | |
download | binutils-23068b02d3a6743658110c7662178fdebbe2ac6a.zip binutils-23068b02d3a6743658110c7662178fdebbe2ac6a.tar.gz binutils-23068b02d3a6743658110c7662178fdebbe2ac6a.tar.bz2 |
RISC-V: Extract the ld code which are too complicated, and may be reused.
These types of codes are different for each target, I am not sure what are the
best for RISC-V, so extract them out may be more easy to compare what's the
difference.
bfd/
* elfnn-riscv.c (RISCV_NEED_DYNAMIC_RELOC): New defined. Extracted
from riscv_elf_check_relocs, to see if dynamic reloc is needed for the
specific relocation.
(RISCV_GENERATE_DYNAMIC_RELOC): New defined. Extracted from
riscv_elf_relocate_section, to see if R_RISCV_32/64 need to generate
dynamic relocation.
(RISCV_COPY_INPUT_RELOC): New defined. Extracted from
riscv_elf_relocate_section, to see if R_RISCV_32/64 need to copy itslef
tp output file.
(RISCV_RESOLVED_LOCALLY): New defined. Extracted from
riscv_elf_relocate_section, to see if R_RISCV_GOT_HI20 can be resolved
locally.
-rw-r--r-- | bfd/elfnn-riscv.c | 156 |
1 files changed, 82 insertions, 74 deletions
diff --git a/bfd/elfnn-riscv.c b/bfd/elfnn-riscv.c index 1200e6b..59e949a 100644 --- a/bfd/elfnn-riscv.c +++ b/bfd/elfnn-riscv.c @@ -38,6 +38,79 @@ #define CHAR_BIT 8 #endif +/* True if dynamic relocation is needed. If we are creating a shared library, + and this is a reloc against a global symbol, or a non PC relative reloc + against a local symbol, then we need to copy the reloc into the shared + library. However, if we are linking with -Bsymbolic, we do not need to + copy a reloc against a global symbol which is defined in an object we are + including in the link (i.e., DEF_REGULAR is set). + + At this point we have not seen all the input files, so it is possible that + DEF_REGULAR is not set now but will be set later (it is never cleared). + In case of a weak definition, DEF_REGULAR may be cleared later by a strong + definition in a shared library. We account for that possibility below by + storing information in the relocs_copied field of the hash table entry. + A similar situation occurs when creating shared libraries and symbol + visibility changes render the symbol local. + + If on the other hand, we are creating an executable, we may need to keep + relocations for symbols satisfied by a dynamic library if we manage to + avoid copy relocs for the symbol. + + Generate dynamic pointer relocation against STT_GNU_IFUNC symbol in the + non-code section (R_RISCV_32/R_RISCV_64). */ +#define RISCV_NEED_DYNAMIC_RELOC(PCREL, INFO, H, SEC) \ + ((bfd_link_pic (INFO) \ + && ((SEC)->flags & SEC_ALLOC) != 0 \ + && (!(PCREL) \ + || ((H) != NULL \ + && (!(INFO)->symbolic \ + || (H)->root.type == bfd_link_hash_defweak \ + || !(H)->def_regular)))) \ + || (!bfd_link_pic (INFO) \ + && ((SEC)->flags & SEC_ALLOC) != 0 \ + && (H) != NULL \ + && ((H)->root.type == bfd_link_hash_defweak \ + || !(H)->def_regular)) \ + || (!bfd_link_pic (INFO) \ + && (H) != NULL \ + && (H)->type == STT_GNU_IFUNC \ + && ((SEC)->flags & SEC_CODE) == 0)) + +/* True if dynamic relocation should be generated. */ +#define RISCV_GENERATE_DYNAMIC_RELOC(PCREL, INFO, H, RESOLVED_TO_ZERO) \ + ((bfd_link_pic (INFO) \ + && ((H) == NULL \ + || (ELF_ST_VISIBILITY ((H)->other) == STV_DEFAULT && !(RESOLVED_TO_ZERO)) \ + || (H)->root.type != bfd_link_hash_undefweak) \ + && (!(PCREL) \ + || !SYMBOL_CALLS_LOCAL ((INFO), (H)))) \ + || (!bfd_link_pic (INFO) \ + && (H) != NULL \ + && (H)->dynindx != -1 \ + && !(H)->non_got_ref \ + && (((H)->def_dynamic && !(H)->def_regular) \ + || (H)->root.type == bfd_link_hash_undefweak \ + || (H)->root.type == bfd_link_hash_undefined))) + +/* True if this input relocation should be copied to output. H->dynindx + may be -1 if this symbol was marked to become local. */ +#define RISCV_COPY_INPUT_RELOC(INFO, H) \ + ((H) != NULL \ + && (H)->dynindx != -1 \ + && (!bfd_link_pic (INFO) \ + || !SYMBOLIC_BIND ((INFO), (H)) \ + || !(H)->def_regular)) + +/* True if this is actually a static link, or it is a -Bsymbolic link + and the symbol is defined locally, or the symbol was forced to be + local because of a version file. */ +#define RISCV_RESOLVED_LOCALLY(INFO, H) \ + (!WILL_CALL_FINISH_DYNAMIC_SYMBOL (elf_hash_table (INFO)->dynamic_sections_created, \ + bfd_link_pic (INFO), (H)) \ + || (bfd_link_pic (INFO) \ + && SYMBOL_REFERENCES_LOCAL ((INFO), (H)))) + /* Internal relocations used exclusively by the relaxation pass. */ #define R_RISCV_DELETE (R_RISCV_max + 1) @@ -835,48 +908,8 @@ riscv_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, } } - /* If we are creating a shared library, and this is a reloc - against a global symbol, or a non PC relative reloc - against a local symbol, then we need to copy the reloc - into the shared library. However, if we are linking with - -Bsymbolic, we do not need to copy a reloc against a - global symbol which is defined in an object we are - including in the link (i.e., DEF_REGULAR is set). At - this point we have not seen all the input files, so it is - possible that DEF_REGULAR is not set now but will be set - later (it is never cleared). In case of a weak definition, - DEF_REGULAR may be cleared later by a strong definition in - a shared library. We account for that possibility below by - storing information in the relocs_copied field of the hash - table entry. A similar situation occurs when creating - shared libraries and symbol visibility changes render the - symbol local. - - If on the other hand, we are creating an executable, we - may need to keep relocations for symbols satisfied by a - dynamic library if we manage to avoid copy relocs for the - symbol. - - Generate dynamic pointer relocation against STT_GNU_IFUNC - symbol in the non-code section (R_RISCV_32/R_RISCV_64). */ - reloc_howto_type * r = riscv_elf_rtype_to_howto (abfd, r_type); - - if ((bfd_link_pic (info) - && (sec->flags & SEC_ALLOC) != 0 - && ((r != NULL && !r->pc_relative) - || (h != NULL - && (!info->symbolic - || h->root.type == bfd_link_hash_defweak - || !h->def_regular)))) - || (!bfd_link_pic (info) - && (sec->flags & SEC_ALLOC) != 0 - && h != NULL - && (h->root.type == bfd_link_hash_defweak - || !h->def_regular)) - || (!bfd_link_pic (info) - && h != NULL - && h->type == STT_GNU_IFUNC - && (sec->flags & SEC_CODE) == 0)) + reloc_howto_type *r = riscv_elf_rtype_to_howto (abfd, r_type); + if (RISCV_NEED_DYNAMIC_RELOC (r->pc_relative, info, h, sec)) { struct elf_dyn_relocs *p; struct elf_dyn_relocs **head; @@ -2329,23 +2362,14 @@ riscv_elf_relocate_section (bfd *output_bfd, case R_RISCV_GOT_HI20: if (h != NULL) { - bool dyn, pic; - off = h->got.offset; BFD_ASSERT (off != (bfd_vma) -1); - dyn = elf_hash_table (info)->dynamic_sections_created; - pic = bfd_link_pic (info); - if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, pic, h) - || (pic && SYMBOL_REFERENCES_LOCAL (info, h))) + if (RISCV_RESOLVED_LOCALLY (info, h)) { - /* This is actually a static link, or it is a - -Bsymbolic link and the symbol is defined - locally, or the symbol was forced to be local - because of a version file. We must initialize - this entry in the global offset table. Since the - offset must always be a multiple of the word size, - we use the least significant bit to record whether + /* We must initialize this entry in the global offset table. + Since the offset must always be a multiple of the word + size, we use the least significant bit to record whether we have initialized it already. When doing a dynamic link, we create a .rela.got @@ -2610,21 +2634,8 @@ riscv_elf_relocate_section (bfd *output_bfd, if ((input_section->flags & SEC_ALLOC) == 0) break; - if ((bfd_link_pic (info) - && (h == NULL - || (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT - && !resolved_to_zero) - || h->root.type != bfd_link_hash_undefweak) - && (!howto->pc_relative - || !SYMBOL_CALLS_LOCAL (info, h))) - || (!bfd_link_pic (info) - && h != NULL - && h->dynindx != -1 - && !h->non_got_ref - && ((h->def_dynamic - && !h->def_regular) - || h->root.type == bfd_link_hash_undefweak - || h->root.type == bfd_link_hash_undefined))) + if (RISCV_GENERATE_DYNAMIC_RELOC (howto->pc_relative, info, h, + resolved_to_zero)) { Elf_Internal_Rela outrel; asection *sreloc; @@ -2643,10 +2654,7 @@ riscv_elf_relocate_section (bfd *output_bfd, if (skip_dynamic_relocation) memset (&outrel, 0, sizeof outrel); - else if (h != NULL && h->dynindx != -1 - && !(bfd_link_pic (info) - && SYMBOLIC_BIND (info, h) - && h->def_regular)) + else if (RISCV_COPY_INPUT_RELOC (info, h)) { outrel.r_info = ELFNN_R_INFO (h->dynindx, r_type); outrel.r_addend = rel->r_addend; |