Skip to content

Commit

Permalink
RISC-V: Extract the ld code which are too complicated, and may be reu…
Browse files Browse the repository at this point in the history
…sed.

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.
  • Loading branch information
Nelson Chu committed Mar 29, 2023
1 parent 2fc3b8a commit 23068b0
Showing 1 changed file with 82 additions and 74 deletions.
156 changes: 82 additions & 74 deletions bfd/elfnn-riscv.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand Down

0 comments on commit 23068b0

Please sign in to comment.