[v3] LoongArch: Fix the issue of excessive relocation generated by IE

Message ID 20240328114927.930243-1-cailulu@loongson.cn
State New
Headers
Series [v3] LoongArch: Fix the issue of excessive relocation generated by IE |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_binutils_build--master-arm success Testing passed
linaro-tcwg-bot/tcwg_binutils_build--master-aarch64 success Testing passed
linaro-tcwg-bot/tcwg_binutils_check--master-aarch64 success Testing passed
linaro-tcwg-bot/tcwg_binutils_check--master-arm success Testing passed

Commit Message

Lulu Cai March 28, 2024, 11:49 a.m. UTC
  Currently, whether GD and IE generate dynamic relocation is
determined by SYMBOL_REFERENCES_LOCAL and bfd_link_executable.
This results in dynamic relocations still being generated in some
situations where dynamic relocations are not necessary (such as
the undefined weak symbol in static links).

We use RLARCH_TLS_GD_IE_NEED_DYN_RELOC macros to determine whether
GD/IE needs dynamic relocation. If GD/IE requires dynamic relocation,
set need_reloc to true and indx to be a dynamic index.

At the same time, some test cases were modified to use regular
expression matching instead of complete disassembly matching.

---
Changes from v1:
* A simpler way of calculating ie offset and desc offset is used.

* On LoongArch, the static tls and the dynamic tls use the same offset
  calculation method, so tlsoff_base is added for offset calculation
  of gd/desc/ie.

v1 link: https://sourceware.org/pipermail/binutils/2024-January/132071.html

---
Changes form v2:
* Variable and function names have been modified for easier understanding.

v2 link: https://sourceware.org/pipermail/binutils/2024-March/133139.html
---
 bfd/elfnn-loongarch.c                       | 179 ++++++++++----------
 ld/testsuite/ld-loongarch-elf/desc-ie.d     |   4 +-
 ld/testsuite/ld-loongarch-elf/tlsdesc-dso.d |  94 +++++-----
 3 files changed, 142 insertions(+), 135 deletions(-)
  

Comments

Xi Ruoyao June 19, 2024, 5:02 a.m. UTC | #1
On Thu, 2024-03-28 at 19:49 +0800, Lulu Cai wrote:
> Currently, whether GD and IE generate dynamic relocation is
> determined by SYMBOL_REFERENCES_LOCAL and bfd_link_executable.
> This results in dynamic relocations still being generated in some
> situations where dynamic relocations are not necessary (such as
> the undefined weak symbol in static links).
> 
> We use RLARCH_TLS_GD_IE_NEED_DYN_RELOC macros to determine whether
> GD/IE needs dynamic relocation. If GD/IE requires dynamic relocation,
> set need_reloc to true and indx to be a dynamic index.
> 
> At the same time, some test cases were modified to use regular
> expression matching instead of complete disassembly matching.

Hi,

The change has caused ld to emit some R_LARCH_NONE for many Glibc shared
libraries.  I'm investigating the issue...

> ---
> Changes from v1:
> * A simpler way of calculating ie offset and desc offset is used.
> 
> * On LoongArch, the static tls and the dynamic tls use the same offset
>   calculation method, so tlsoff_base is added for offset calculation
>   of gd/desc/ie.
> 
> v1 link:
> https://sourceware.org/pipermail/binutils/2024-January/132071.html
> 
> ---
> Changes form v2:
> * Variable and function names have been modified for easier
> understanding.
> 
> v2 link:
> https://sourceware.org/pipermail/binutils/2024-March/133139.html
> ---
>  bfd/elfnn-loongarch.c                       | 179 ++++++++++---------
> -
>  ld/testsuite/ld-loongarch-elf/desc-ie.d     |   4 +-
>  ld/testsuite/ld-loongarch-elf/tlsdesc-dso.d |  94 +++++-----
>  3 files changed, 142 insertions(+), 135 deletions(-)
> 
> diff --git a/bfd/elfnn-loongarch.c b/bfd/elfnn-loongarch.c
> index 6c5a9c5c0de..39a133465f6 100644
> --- a/bfd/elfnn-loongarch.c
> +++ b/bfd/elfnn-loongarch.c
> @@ -159,6 +159,27 @@ struct loongarch_elf_link_hash_table
>     || (R_TYPE) == R_LARCH_TLS_LE64_LO20	  \
>     || (R_TYPE) == R_LARCH_TLS_LE64_HI12)
>  
> +/* If TLS GD/IE need dynamic relocations, INDX will be the dynamic
> indx,
> +   and set NEED_RELOC to true used in allocate_dynrelocs and
> +   loongarch_elf_relocate_section for TLS GD/IE.  */
> +#define LARCH_TLS_GD_IE_NEED_DYN_RELOC(INFO, DYN, H, INDX,
> NEED_RELOC) \
> +  do \
> +    { \
> +      if ((H) != NULL \
> +	  && (H)->dynindx != -1 \
> +	  && WILL_CALL_FINISH_DYNAMIC_SYMBOL ((DYN), \
> +				    bfd_link_pic (INFO), (H))) \
> +      (INDX) = (H)->dynindx; \
> +      if (((H) == NULL \
> +	    || ELF_ST_VISIBILITY ((H)->other) == STV_DEFAULT \
> +	    || (H)->root.type != bfd_link_hash_undefweak) \
> +	    && (!bfd_link_executable (INFO) \
> +	      || (INDX) != 0)) \
> +      (NEED_RELOC) = true; \
> +    } \
> +    while (0)
> +
> +
>  /* Generate a PLT header.  */
>  
>  static bool
> @@ -1294,40 +1315,24 @@ allocate_dynrelocs (struct elf_link_hash_entry
> *h, void *inf)
>        h->got.offset = s->size;
>        if (tls_type & (GOT_TLS_GD | GOT_TLS_IE | GOT_TLS_GDESC))
>  	{
> +	  int indx = 0;
> +	  bool need_reloc = false;
> +	  LARCH_TLS_GD_IE_NEED_DYN_RELOC (info, dyn, h, indx,
> +					need_reloc);
>  	  /* TLS_GD needs two dynamic relocs and two GOT slots.  */
>  	  if (tls_type & GOT_TLS_GD)
>  	    {
>  	      s->size += 2 * GOT_ENTRY_SIZE;
> -	      if (bfd_link_executable (info))
> -		{
> -		  /* Link exe and not defined local.  */
> -		  if (!SYMBOL_REFERENCES_LOCAL (info, h))
> -		    htab->elf.srelgot->size += 2 * sizeof
> (ElfNN_External_Rela);
> -		}
> -	      else
> -		{
> -		  if (SYMBOL_REFERENCES_LOCAL (info, h))
> -		    htab->elf.srelgot->size += sizeof
> (ElfNN_External_Rela);
> -		  else
> -		    htab->elf.srelgot->size += 2 * sizeof
> (ElfNN_External_Rela);
> -		}
> +	      if (need_reloc)
> +		htab->elf.srelgot->size += 2 * sizeof
> (ElfNN_External_Rela);
>  	    }
>  
>  	  /* TLS_IE needs one dynamic reloc and one GOT slot.  */
>  	  if (tls_type & GOT_TLS_IE)
>  	    {
>  	      s->size += GOT_ENTRY_SIZE;
> -
> -	      if (bfd_link_executable (info))
> -		{
> -		  /* Link exe and not defined local.  */
> -		  if (!SYMBOL_REFERENCES_LOCAL (info, h))
> -		    htab->elf.srelgot->size += sizeof
> (ElfNN_External_Rela);
> -		}
> -	      else
> -		{
> -		  htab->elf.srelgot->size += sizeof
> (ElfNN_External_Rela);
> -		}
> +	      if (need_reloc)
> +		htab->elf.srelgot->size += 2 * sizeof
> (ElfNN_External_Rela);
>  	    }
>  
>  	  /* TLS_DESC needs one dynamic reloc and two GOT slot.  */
> @@ -2568,13 +2573,18 @@ loongarch_reloc_is_fatal (struct bfd_link_info
> *info,
>    })
>  
>  
> +/* Compute the tp/dtp offset of a tls symbol.
> +   It is dtp offset in dynamic tls model (gd/ld) and tp
> +   offset in static tls model (ie/le). Both offsets are
> +   calculated the same way on LoongArch, so the same
> +   function is used.  */
>  static bfd_vma
> -tls_dtpoff_base (struct bfd_link_info *info)
> +tlsoff (struct bfd_link_info *info, bfd_vma addr)
>  {
>    /* If tls_sec is NULL, we should have signalled an error already. 
> */
>    if (elf_hash_table (info)->tls_sec == NULL)
>      return 0;
> -  return elf_hash_table (info)->tls_sec->vma;
> +  return addr - elf_hash_table (info)->tls_sec->vma;
>  }
>  
>  
> @@ -2908,7 +2918,7 @@ loongarch_elf_relocate_section (bfd *output_bfd,
> struct bfd_link_info *info,
>  			  is_undefweak, name, "TLS section not be
> created");
>  		}
>  	      else
> -		relocation -= elf_hash_table (info)->tls_sec->vma;
> +		relocation = tlsoff (info, relocation);
>  	    }
>  	  else
>  	    {
> @@ -3434,7 +3444,7 @@ loongarch_elf_relocate_section (bfd *output_bfd,
> struct bfd_link_info *info,
>  
>  	case R_LARCH_TLS_LE_HI20_R:
>  	  relocation += rel->r_addend;
> -	  relocation -= elf_hash_table (info)->tls_sec->vma;
> +	  relocation = tlsoff (info, relocation);
>  	  RELOCATE_TLS_TP32_HI20 (relocation);
>  	  break;
>  
> @@ -3617,7 +3627,7 @@ loongarch_elf_relocate_section (bfd *output_bfd,
> struct bfd_link_info *info,
>  	  BFD_ASSERT (resolved_local && elf_hash_table (info)-
> >tls_sec);
>  
>  	  relocation += rel->r_addend;
> -	  relocation -= elf_hash_table (info)->tls_sec->vma;
> +	  relocation = tlsoff (info, relocation);
>  	  break;
>  
>  	/* TLS IE LD/GD process separately is troublesome.
> @@ -3672,71 +3682,72 @@ loongarch_elf_relocate_section (bfd
> *output_bfd, struct bfd_link_info *info,
>  	  /* If a tls variable is accessed in multiple ways, GD uses
>  	     the first two slots of GOT, desc follows with two slots,
>  	     and IE uses one slot at the end.  */
> -	  desc_off = 0;
> -	  if (GOT_TLS_GD_BOTH_P (tls_type))
> -	    desc_off = 2 * GOT_ENTRY_SIZE;
> -
> -	  ie_off = 0;
> -	  if (GOT_TLS_GD_BOTH_P (tls_type) && (tls_type &
> GOT_TLS_IE))
> -	    ie_off = 4 * GOT_ENTRY_SIZE;
> -	  else if (GOT_TLS_GD_ANY_P (tls_type) && (tls_type &
> GOT_TLS_IE))
> -	    ie_off = 2 * GOT_ENTRY_SIZE;
> +	  off = 0;
> +	  if (tls_type & GOT_TLS_GD)
> +	    off += 2 * GOT_ENTRY_SIZE;
> +	  desc_off = off;
> +	  if (tls_type & GOT_TLS_GDESC)
> +	    off += 2 * GOT_ENTRY_SIZE;
> +	  ie_off = off;
>  
>  	  if ((got_off & 1) == 0)
>  	    {
>  	      Elf_Internal_Rela rela;
>  	      asection *relgot = htab->elf.srelgot;
> -	      bfd_vma tls_block_off = 0;
>  
> -	      if (SYMBOL_REFERENCES_LOCAL (info, h))
> -		{
> -		  BFD_ASSERT (elf_hash_table (info)->tls_sec);
> -		  tls_block_off = relocation
> -		      - elf_hash_table (info)->tls_sec->vma;
> -		}
> +	      int indx = 0;
> +	      bool need_reloc = false;
> +	      LARCH_TLS_GD_IE_NEED_DYN_RELOC (info, is_dyn, h, indx,
> +					      need_reloc);
>  
>  	      if (tls_type & GOT_TLS_GD)
>  		{
> -		  rela.r_offset = sec_addr (got) + got_off;
> -		  rela.r_addend = 0;
> -		  if (SYMBOL_REFERENCES_LOCAL (info, h))
> +		  if (need_reloc)
>  		    {
> -		      /* Local sym, used in exec, set module id 1. 
> */
> -		      if (bfd_link_executable (info))
> -			bfd_put_NN (output_bfd, 1, got->contents +
> got_off);
> +		  /* Dynamic resolved Module ID.  */
> +		      rela.r_offset = sec_addr (got) + got_off;
> +		      rela.r_addend = 0;
> +		      rela.r_info = ELFNN_R_INFO
> (indx,R_LARCH_TLS_DTPMODNN);
> +		      bfd_put_NN (output_bfd, 0, got->contents +
> got_off);
> +		      loongarch_elf_append_rela (output_bfd, relgot,
> &rela);
> +
> +		      if (indx == 0)
> +			{
> +			  /* Local symbol, tp offset has been known. 
> */
> +			  BFD_ASSERT (! unresolved_reloc);
> +			  bfd_put_NN (output_bfd,
> +			      tlsoff (info, relocation),
> +			      (got->contents + got_off +
> GOT_ENTRY_SIZE));
> +			}
>  		      else
>  			{
> -			  rela.r_info = ELFNN_R_INFO (0,
> R_LARCH_TLS_DTPMODNN);
> +			  /* Dynamic resolved block offset.  */
> +			  bfd_put_NN (output_bfd, 0,
> +			      got->contents + got_off +
> GOT_ENTRY_SIZE);
> +			  rela.r_info = ELFNN_R_INFO (indx,
> +						R_LARCH_TLS_DTPRELNN)
> ;
> +			  rela.r_offset += GOT_ENTRY_SIZE;
>  			  loongarch_elf_append_rela (output_bfd,
> relgot, &rela);
>  			}
> -
> -		      bfd_put_NN (output_bfd, tls_block_off,
> -				  got->contents + got_off +
> GOT_ENTRY_SIZE);
>  		    }
> -		  /* Dynamic resolved.  */
>  		  else
>  		    {
> -		      /* Dynamic relocate module id.  */
> -		      rela.r_info = ELFNN_R_INFO (h->dynindx,
> -						 
> R_LARCH_TLS_DTPMODNN);
> -		      loongarch_elf_append_rela (output_bfd, relgot,
> &rela);
> -
> -		      /* Dynamic relocate offset of block.  */
> -		      rela.r_offset += GOT_ENTRY_SIZE;
> -		      rela.r_info = ELFNN_R_INFO (h->dynindx,
> -						 
> R_LARCH_TLS_DTPRELNN);
> -		      loongarch_elf_append_rela (output_bfd, relgot,
> &rela);
> +		      /* In a static link or an executable link with
> the symbol
> +			 binding locally.  Mark it as belonging to
> module 1.  */
> +		      bfd_put_NN (output_bfd, 1, got->contents +
> got_off);
> +		      bfd_put_NN (output_bfd, tlsoff (info,
> relocation),
> +			  got->contents + got_off + GOT_ENTRY_SIZE);
>  		    }
>  		}
>  	      if (tls_type & GOT_TLS_GDESC)
>  		{
>  		  /* Unless it is a static link, DESC always emits a
>  		     dynamic relocation.  */
> -		  int indx = h && h->dynindx != -1 ? h->dynindx : 0;
> +		  indx = h && h->dynindx != -1 ? h->dynindx : 0;
>  		  rela.r_offset = sec_addr (got) + got_off +
> desc_off;
>  		  rela.r_addend = 0;
>  		  if (indx == 0)
> -		    rela.r_addend = relocation - tls_dtpoff_base
> (info);
> +		    rela.r_addend = tlsoff (info, relocation);
>  
>  		  rela.r_info = ELFNN_R_INFO (indx,
> R_LARCH_TLS_DESCNN);
>  		  loongarch_elf_append_rela (output_bfd, relgot,
> &rela);
> @@ -3745,28 +3756,24 @@ loongarch_elf_relocate_section (bfd
> *output_bfd, struct bfd_link_info *info,
>  		}
>  	      if (tls_type & GOT_TLS_IE)
>  		{
> -		  rela.r_offset = sec_addr (got) + got_off + ie_off;
> -		  if (SYMBOL_REFERENCES_LOCAL (info, h))
> +		  if (need_reloc)
>  		    {
> -		      /* Local sym, used in exec, set module id 1. 
> */
> -		      if (!bfd_link_executable (info))
> -			{
> -			  rela.r_info = ELFNN_R_INFO (0,
> R_LARCH_TLS_TPRELNN);
> -			  rela.r_addend = tls_block_off;
> -			  loongarch_elf_append_rela (output_bfd,
> relgot, &rela);
> -			}
> +		      bfd_put_NN (output_bfd, 0,
> +			  got->contents + got_off + ie_off);
> +		      rela.r_offset = sec_addr (got) + got_off +
> ie_off;
> +		      rela.r_addend = 0;
>  
> -		      bfd_put_NN (output_bfd, tls_block_off,
> -				  got->contents + got_off + ie_off);
> +		      if (indx == 0)
> +			rela.r_addend = tlsoff (info, relocation);
> +		      rela.r_info = ELFNN_R_INFO (indx,
> R_LARCH_TLS_TPRELNN);
> +		      loongarch_elf_append_rela (output_bfd, relgot,
> &rela);
>  		    }
> -		  /* Dynamic resolved.  */
>  		  else
>  		    {
> -		      /* Dynamic relocate offset of block.  */
> -		      rela.r_info = ELFNN_R_INFO (h->dynindx,
> -						 
> R_LARCH_TLS_TPRELNN);
> -		      rela.r_addend = 0;
> -		      loongarch_elf_append_rela (output_bfd, relgot,
> &rela);
> +		      /* In a static link or an executable link with
> the symbol
> +			 bindinglocally, compute offset directly.  */
> +		      bfd_put_NN (output_bfd, tlsoff (info,
> relocation),
> +			  got->contents + got_off + ie_off);
>  		    }
>  		}
>  	    }
> @@ -3805,7 +3812,7 @@ loongarch_elf_relocate_section (bfd *output_bfd,
> struct bfd_link_info *info,
>  
>  	    tls_type = _bfd_loongarch_elf_tls_type (input_bfd, h,
> r_symndx);
>  	    /* Use both TLS_GD and TLS_DESC.  */
> -	    if ((tls_type & GOT_TLS_GD) && (tls_type &
> GOT_TLS_GDESC))
> +	    if (GOT_TLS_GD_BOTH_P (tls_type))
>  	      relocation += 2 * GOT_ENTRY_SIZE;
>  
>  	    if (r_type == R_LARCH_TLS_DESC64_PC_LO20)
> diff --git a/ld/testsuite/ld-loongarch-elf/desc-ie.d
> b/ld/testsuite/ld-loongarch-elf/desc-ie.d
> index e1f49e2d556..c833b233d42 100644
> --- a/ld/testsuite/ld-loongarch-elf/desc-ie.d
> +++ b/ld/testsuite/ld-loongarch-elf/desc-ie.d
> @@ -9,6 +9,6 @@ Disassembly of section .text:
>  
>  [0-9a-f]+ <fn1>:
>   +[0-9a-f]+:	1a000084 	pcalau12i   	\$a0, .*
> - +[0-9a-f]+:	28cca084 	ld.d        	\$a0, \$a0, .*
> + +[0-9a-f]+:	28cd0084 	ld.d        	\$a0, \$a0, .*
>   +[0-9a-f]+:	1a000084 	pcalau12i   	\$a0, .*
> - +[0-9a-f]+:	28cca084 	ld.d        	\$a0, \$a0, .*
> + +[0-9a-f]+:	28cd0084 	ld.d        	\$a0, \$a0, .*
> diff --git a/ld/testsuite/ld-loongarch-elf/tlsdesc-dso.d
> b/ld/testsuite/ld-loongarch-elf/tlsdesc-dso.d
> index 84ea97e076b..8f66302f1cf 100644
> --- a/ld/testsuite/ld-loongarch-elf/tlsdesc-dso.d
> +++ b/ld/testsuite/ld-loongarch-elf/tlsdesc-dso.d
> @@ -8,53 +8,53 @@
>  
>  Disassembly of section .text:
>  
> -0+448 <fun_gl1>:
> - 448:	18021584 	pcaddi      	\$a0, 4268
> - 44c:	1a000084 	pcalau12i   	\$a0, 4
> - 450:	28dc2084 	ld.d        	\$a0, \$a0, 1800
> - 454:	18021364 	pcaddi      	\$a0, 4251
> - 458:	180213c4 	pcaddi      	\$a0, 4254
> - 45c:	28c00081 	ld.d        	\$ra, \$a0, 0
> - 460:	4c000021 	jirl        	\$ra, \$ra, 0
> - 464:	1a000084 	pcalau12i   	\$a0, 4
> - 468:	28dae084 	ld.d        	\$a0, \$a0, 1720
> - 46c:	1a000084 	pcalau12i   	\$a0, 4
> - 470:	28dae084 	ld.d        	\$a0, \$a0, 1720
> - 474:	18021364 	pcaddi      	\$a0, 4251
> - 478:	18021344 	pcaddi      	\$a0, 4250
> - 47c:	28c00081 	ld.d        	\$ra, \$a0, 0
> - 480:	4c000021 	jirl        	\$ra, \$ra, 0
> - 484:	1a000084 	pcalau12i   	\$a0, 4
> - 488:	28dbc084 	ld.d        	\$a0, \$a0, 1776
> +[0-9a-f]+ <fun_gl1>:
> + +[0-9a-f]+:	18021584 	pcaddi      	\$a0, 4268
> + +[0-9a-f]+:	1a000084 	pcalau12i   	\$a0, 4
> + +[0-9a-f]+:	28dd4084 	ld.d        	\$a0, \$a0, 1872
> + +[0-9a-f]+:	18021364 	pcaddi      	\$a0, 4251
> + +[0-9a-f]+:	180213c4 	pcaddi      	\$a0, 4254
> + +[0-9a-f]+:	28c00081 	ld.d        	\$ra, \$a0, 0
> + +[0-9a-f]+:	4c000021 	jirl        	\$ra, \$ra, 0
> + +[0-9a-f]+:	1a000084 	pcalau12i   	\$a0, 4
> + +[0-9a-f]+:	28dc0084 	ld.d        	\$a0, \$a0, 1792
> + +[0-9a-f]+:	1a000084 	pcalau12i   	\$a0, 4
> + +[0-9a-f]+:	28dc0084 	ld.d        	\$a0, \$a0, 1792
> + +[0-9a-f]+:	18021364 	pcaddi      	\$a0, 4251
> + +[0-9a-f]+:	180213c4 	pcaddi      	\$a0, 4254
> + +[0-9a-f]+:	28c00081 	ld.d        	\$ra, \$a0, 0
> + +[0-9a-f]+:	4c000021 	jirl        	\$ra, \$ra, 0
> + +[0-9a-f]+:	1a000084 	pcalau12i   	\$a0, 4
> + +[0-9a-f]+:	28dce084 	ld.d        	\$a0, \$a0, 1848
>  
> -0+48c <fun_lo>:
> - 48c:	1a000084 	pcalau12i   	\$a0, 4
> - 490:	28d98084 	ld.d        	\$a0, \$a0, 1632
> - 494:	18020de4 	pcaddi      	\$a0, 4207
> - 498:	18020f04 	pcaddi      	\$a0, 4216
> - 49c:	28c00081 	ld.d        	\$ra, \$a0, 0
> - 4a0:	4c000021 	jirl        	\$ra, \$ra, 0
> - 4a4:	18020e24 	pcaddi      	\$a0, 4209
> - 4a8:	1a000084 	pcalau12i   	\$a0, 4
> - 4ac:	28da2084 	ld.d        	\$a0, \$a0, 1672
> - 4b0:	1a000084 	pcalau12i   	\$a0, 4
> - 4b4:	28da2084 	ld.d        	\$a0, \$a0, 1672
> - 4b8:	18020ec4 	pcaddi      	\$a0, 4214
> - 4bc:	28c00081 	ld.d        	\$ra, \$a0, 0
> - 4c0:	4c000021 	jirl        	\$ra, \$ra, 0
> - 4c4:	18020e64 	pcaddi      	\$a0, 4211
> - 4c8:	1a000084 	pcalau12i   	\$a0, 4
> - 4cc:	28da8084 	ld.d        	\$a0, \$a0, 1696
> +[0-9a-f]+ <fun_lo>:
> + +[0-9a-f]+:	1a000084 	pcalau12i   	\$a0, 4
> + +[0-9a-f]+:	28daa084 	ld.d        	\$a0, \$a0, 1704
> + +[0-9a-f]+:	18020de4 	pcaddi      	\$a0, 4207
> + +[0-9a-f]+:	18020f04 	pcaddi      	\$a0, 4216
> + +[0-9a-f]+:	28c00081 	ld.d        	\$ra, \$a0, 0
> + +[0-9a-f]+:	4c000021 	jirl        	\$ra, \$ra, 0
> + +[0-9a-f]+:	18020e24 	pcaddi      	\$a0, 4209
> + +[0-9a-f]+:	1a000084 	pcalau12i   	\$a0, 4
> + +[0-9a-f]+:	28db4084 	ld.d        	\$a0, \$a0, 1744
> + +[0-9a-f]+:	1a000084 	pcalau12i   	\$a0, 4
> + +[0-9a-f]+:	28db4084 	ld.d        	\$a0, \$a0, 1744
> + +[0-9a-f]+:	18020f44 	pcaddi      	\$a0, 4218
> + +[0-9a-f]+:	28c00081 	ld.d        	\$ra, \$a0, 0
> + +[0-9a-f]+:	4c000021 	jirl        	\$ra, \$ra, 0
> + +[0-9a-f]+:	18020e64 	pcaddi      	\$a0, 4211
> + +[0-9a-f]+:	1a000084 	pcalau12i   	\$a0, 4
> + +[0-9a-f]+:	28dba084 	ld.d        	\$a0, \$a0, 1768
>  
> -0+4d0 <fun_external>:
> - 4d0:	18020ec4 	pcaddi      	\$a0, 4214
> - 4d4:	28c00081 	ld.d        	\$ra, \$a0, 0
> - 4d8:	4c000021 	jirl        	\$ra, \$ra, 0
> +[0-9a-f]+ <fun_external>:
> + +[0-9a-f]+:	18020ec4 	pcaddi      	\$a0, 4214
> + +[0-9a-f]+:	28c00081 	ld.d        	\$ra, \$a0, 0
> + +[0-9a-f]+:	4c000021 	jirl        	\$ra, \$ra, 0
>  
> -0+4dc <fun_hidden>:
> - 4dc:	18021224 	pcaddi      	\$a0, 4241
> - 4e0:	28c00081 	ld.d        	\$ra, \$a0, 0
> - 4e4:	4c000021 	jirl        	\$ra, \$ra, 0
> - 4e8:	18021144 	pcaddi      	\$a0, 4234
> - 4ec:	28c00081 	ld.d        	\$ra, \$a0, 0
> - 4f0:	4c000021 	jirl        	\$ra, \$ra, 0
> +[0-9a-f]+ <fun_hidden>:
> + +[0-9a-f]+:	18021224 	pcaddi      	\$a0, 4241
> + +[0-9a-f]+:	28c00081 	ld.d        	\$ra, \$a0, 0
> + +[0-9a-f]+:	4c000021 	jirl        	\$ra, \$ra, 0
> + +[0-9a-f]+:	18021144 	pcaddi      	\$a0, 4234
> + +[0-9a-f]+:	28c00081 	ld.d        	\$ra, \$a0, 0
> + +[0-9a-f]+:	4c000021 	jirl        	\$ra, \$ra, 0
  
Xi Ruoyao June 19, 2024, 6:06 a.m. UTC | #2
On Wed, 2024-06-19 at 13:02 +0800, Xi Ruoyao wrote:
> On Thu, 2024-03-28 at 19:49 +0800, Lulu Cai wrote:
> > Currently, whether GD and IE generate dynamic relocation is
> > determined by SYMBOL_REFERENCES_LOCAL and bfd_link_executable.
> > This results in dynamic relocations still being generated in some
> > situations where dynamic relocations are not necessary (such as
> > the undefined weak symbol in static links).
> > 
> > We use RLARCH_TLS_GD_IE_NEED_DYN_RELOC macros to determine whether
> > GD/IE needs dynamic relocation. If GD/IE requires dynamic relocation,
> > set need_reloc to true and indx to be a dynamic index.
> > 
> > At the same time, some test cases were modified to use regular
> > expression matching instead of complete disassembly matching.
> 
> Hi,
> 
> The change has caused ld to emit some R_LARCH_NONE for many Glibc shared
> libraries.  I'm investigating the issue...

https://sourceware.org/pipermail/binutils/2024-June/134902.html
  

Patch

diff --git a/bfd/elfnn-loongarch.c b/bfd/elfnn-loongarch.c
index 6c5a9c5c0de..39a133465f6 100644
--- a/bfd/elfnn-loongarch.c
+++ b/bfd/elfnn-loongarch.c
@@ -159,6 +159,27 @@  struct loongarch_elf_link_hash_table
    || (R_TYPE) == R_LARCH_TLS_LE64_LO20	  \
    || (R_TYPE) == R_LARCH_TLS_LE64_HI12)
 
+/* If TLS GD/IE need dynamic relocations, INDX will be the dynamic indx,
+   and set NEED_RELOC to true used in allocate_dynrelocs and
+   loongarch_elf_relocate_section for TLS GD/IE.  */
+#define LARCH_TLS_GD_IE_NEED_DYN_RELOC(INFO, DYN, H, INDX, NEED_RELOC) \
+  do \
+    { \
+      if ((H) != NULL \
+	  && (H)->dynindx != -1 \
+	  && WILL_CALL_FINISH_DYNAMIC_SYMBOL ((DYN), \
+				    bfd_link_pic (INFO), (H))) \
+      (INDX) = (H)->dynindx; \
+      if (((H) == NULL \
+	    || ELF_ST_VISIBILITY ((H)->other) == STV_DEFAULT \
+	    || (H)->root.type != bfd_link_hash_undefweak) \
+	    && (!bfd_link_executable (INFO) \
+	      || (INDX) != 0)) \
+      (NEED_RELOC) = true; \
+    } \
+    while (0)
+
+
 /* Generate a PLT header.  */
 
 static bool
@@ -1294,40 +1315,24 @@  allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
       h->got.offset = s->size;
       if (tls_type & (GOT_TLS_GD | GOT_TLS_IE | GOT_TLS_GDESC))
 	{
+	  int indx = 0;
+	  bool need_reloc = false;
+	  LARCH_TLS_GD_IE_NEED_DYN_RELOC (info, dyn, h, indx,
+					need_reloc);
 	  /* TLS_GD needs two dynamic relocs and two GOT slots.  */
 	  if (tls_type & GOT_TLS_GD)
 	    {
 	      s->size += 2 * GOT_ENTRY_SIZE;
-	      if (bfd_link_executable (info))
-		{
-		  /* Link exe and not defined local.  */
-		  if (!SYMBOL_REFERENCES_LOCAL (info, h))
-		    htab->elf.srelgot->size += 2 * sizeof (ElfNN_External_Rela);
-		}
-	      else
-		{
-		  if (SYMBOL_REFERENCES_LOCAL (info, h))
-		    htab->elf.srelgot->size += sizeof (ElfNN_External_Rela);
-		  else
-		    htab->elf.srelgot->size += 2 * sizeof (ElfNN_External_Rela);
-		}
+	      if (need_reloc)
+		htab->elf.srelgot->size += 2 * sizeof (ElfNN_External_Rela);
 	    }
 
 	  /* TLS_IE needs one dynamic reloc and one GOT slot.  */
 	  if (tls_type & GOT_TLS_IE)
 	    {
 	      s->size += GOT_ENTRY_SIZE;
-
-	      if (bfd_link_executable (info))
-		{
-		  /* Link exe and not defined local.  */
-		  if (!SYMBOL_REFERENCES_LOCAL (info, h))
-		    htab->elf.srelgot->size += sizeof (ElfNN_External_Rela);
-		}
-	      else
-		{
-		  htab->elf.srelgot->size += sizeof (ElfNN_External_Rela);
-		}
+	      if (need_reloc)
+		htab->elf.srelgot->size += 2 * sizeof (ElfNN_External_Rela);
 	    }
 
 	  /* TLS_DESC needs one dynamic reloc and two GOT slot.  */
@@ -2568,13 +2573,18 @@  loongarch_reloc_is_fatal (struct bfd_link_info *info,
   })
 
 
+/* Compute the tp/dtp offset of a tls symbol.
+   It is dtp offset in dynamic tls model (gd/ld) and tp
+   offset in static tls model (ie/le). Both offsets are
+   calculated the same way on LoongArch, so the same
+   function is used.  */
 static bfd_vma
-tls_dtpoff_base (struct bfd_link_info *info)
+tlsoff (struct bfd_link_info *info, bfd_vma addr)
 {
   /* If tls_sec is NULL, we should have signalled an error already.  */
   if (elf_hash_table (info)->tls_sec == NULL)
     return 0;
-  return elf_hash_table (info)->tls_sec->vma;
+  return addr - elf_hash_table (info)->tls_sec->vma;
 }
 
 
@@ -2908,7 +2918,7 @@  loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
 			  is_undefweak, name, "TLS section not be created");
 		}
 	      else
-		relocation -= elf_hash_table (info)->tls_sec->vma;
+		relocation = tlsoff (info, relocation);
 	    }
 	  else
 	    {
@@ -3434,7 +3444,7 @@  loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
 
 	case R_LARCH_TLS_LE_HI20_R:
 	  relocation += rel->r_addend;
-	  relocation -= elf_hash_table (info)->tls_sec->vma;
+	  relocation = tlsoff (info, relocation);
 	  RELOCATE_TLS_TP32_HI20 (relocation);
 	  break;
 
@@ -3617,7 +3627,7 @@  loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
 	  BFD_ASSERT (resolved_local && elf_hash_table (info)->tls_sec);
 
 	  relocation += rel->r_addend;
-	  relocation -= elf_hash_table (info)->tls_sec->vma;
+	  relocation = tlsoff (info, relocation);
 	  break;
 
 	/* TLS IE LD/GD process separately is troublesome.
@@ -3672,71 +3682,72 @@  loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
 	  /* If a tls variable is accessed in multiple ways, GD uses
 	     the first two slots of GOT, desc follows with two slots,
 	     and IE uses one slot at the end.  */
-	  desc_off = 0;
-	  if (GOT_TLS_GD_BOTH_P (tls_type))
-	    desc_off = 2 * GOT_ENTRY_SIZE;
-
-	  ie_off = 0;
-	  if (GOT_TLS_GD_BOTH_P (tls_type) && (tls_type & GOT_TLS_IE))
-	    ie_off = 4 * GOT_ENTRY_SIZE;
-	  else if (GOT_TLS_GD_ANY_P (tls_type) && (tls_type & GOT_TLS_IE))
-	    ie_off = 2 * GOT_ENTRY_SIZE;
+	  off = 0;
+	  if (tls_type & GOT_TLS_GD)
+	    off += 2 * GOT_ENTRY_SIZE;
+	  desc_off = off;
+	  if (tls_type & GOT_TLS_GDESC)
+	    off += 2 * GOT_ENTRY_SIZE;
+	  ie_off = off;
 
 	  if ((got_off & 1) == 0)
 	    {
 	      Elf_Internal_Rela rela;
 	      asection *relgot = htab->elf.srelgot;
-	      bfd_vma tls_block_off = 0;
 
-	      if (SYMBOL_REFERENCES_LOCAL (info, h))
-		{
-		  BFD_ASSERT (elf_hash_table (info)->tls_sec);
-		  tls_block_off = relocation
-		      - elf_hash_table (info)->tls_sec->vma;
-		}
+	      int indx = 0;
+	      bool need_reloc = false;
+	      LARCH_TLS_GD_IE_NEED_DYN_RELOC (info, is_dyn, h, indx,
+					      need_reloc);
 
 	      if (tls_type & GOT_TLS_GD)
 		{
-		  rela.r_offset = sec_addr (got) + got_off;
-		  rela.r_addend = 0;
-		  if (SYMBOL_REFERENCES_LOCAL (info, h))
+		  if (need_reloc)
 		    {
-		      /* Local sym, used in exec, set module id 1.  */
-		      if (bfd_link_executable (info))
-			bfd_put_NN (output_bfd, 1, got->contents + got_off);
+		  /* Dynamic resolved Module ID.  */
+		      rela.r_offset = sec_addr (got) + got_off;
+		      rela.r_addend = 0;
+		      rela.r_info = ELFNN_R_INFO (indx,R_LARCH_TLS_DTPMODNN);
+		      bfd_put_NN (output_bfd, 0, got->contents + got_off);
+		      loongarch_elf_append_rela (output_bfd, relgot, &rela);
+
+		      if (indx == 0)
+			{
+			  /* Local symbol, tp offset has been known.  */
+			  BFD_ASSERT (! unresolved_reloc);
+			  bfd_put_NN (output_bfd,
+			      tlsoff (info, relocation),
+			      (got->contents + got_off + GOT_ENTRY_SIZE));
+			}
 		      else
 			{
-			  rela.r_info = ELFNN_R_INFO (0, R_LARCH_TLS_DTPMODNN);
+			  /* Dynamic resolved block offset.  */
+			  bfd_put_NN (output_bfd, 0,
+			      got->contents + got_off + GOT_ENTRY_SIZE);
+			  rela.r_info = ELFNN_R_INFO (indx,
+						R_LARCH_TLS_DTPRELNN);
+			  rela.r_offset += GOT_ENTRY_SIZE;
 			  loongarch_elf_append_rela (output_bfd, relgot, &rela);
 			}
-
-		      bfd_put_NN (output_bfd, tls_block_off,
-				  got->contents + got_off + GOT_ENTRY_SIZE);
 		    }
-		  /* Dynamic resolved.  */
 		  else
 		    {
-		      /* Dynamic relocate module id.  */
-		      rela.r_info = ELFNN_R_INFO (h->dynindx,
-						  R_LARCH_TLS_DTPMODNN);
-		      loongarch_elf_append_rela (output_bfd, relgot, &rela);
-
-		      /* Dynamic relocate offset of block.  */
-		      rela.r_offset += GOT_ENTRY_SIZE;
-		      rela.r_info = ELFNN_R_INFO (h->dynindx,
-						  R_LARCH_TLS_DTPRELNN);
-		      loongarch_elf_append_rela (output_bfd, relgot, &rela);
+		      /* In a static link or an executable link with the symbol
+			 binding locally.  Mark it as belonging to module 1.  */
+		      bfd_put_NN (output_bfd, 1, got->contents + got_off);
+		      bfd_put_NN (output_bfd, tlsoff (info, relocation),
+			  got->contents + got_off + GOT_ENTRY_SIZE);
 		    }
 		}
 	      if (tls_type & GOT_TLS_GDESC)
 		{
 		  /* Unless it is a static link, DESC always emits a
 		     dynamic relocation.  */
-		  int indx = h && h->dynindx != -1 ? h->dynindx : 0;
+		  indx = h && h->dynindx != -1 ? h->dynindx : 0;
 		  rela.r_offset = sec_addr (got) + got_off + desc_off;
 		  rela.r_addend = 0;
 		  if (indx == 0)
-		    rela.r_addend = relocation - tls_dtpoff_base (info);
+		    rela.r_addend = tlsoff (info, relocation);
 
 		  rela.r_info = ELFNN_R_INFO (indx, R_LARCH_TLS_DESCNN);
 		  loongarch_elf_append_rela (output_bfd, relgot, &rela);
@@ -3745,28 +3756,24 @@  loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
 		}
 	      if (tls_type & GOT_TLS_IE)
 		{
-		  rela.r_offset = sec_addr (got) + got_off + ie_off;
-		  if (SYMBOL_REFERENCES_LOCAL (info, h))
+		  if (need_reloc)
 		    {
-		      /* Local sym, used in exec, set module id 1.  */
-		      if (!bfd_link_executable (info))
-			{
-			  rela.r_info = ELFNN_R_INFO (0, R_LARCH_TLS_TPRELNN);
-			  rela.r_addend = tls_block_off;
-			  loongarch_elf_append_rela (output_bfd, relgot, &rela);
-			}
+		      bfd_put_NN (output_bfd, 0,
+			  got->contents + got_off + ie_off);
+		      rela.r_offset = sec_addr (got) + got_off + ie_off;
+		      rela.r_addend = 0;
 
-		      bfd_put_NN (output_bfd, tls_block_off,
-				  got->contents + got_off + ie_off);
+		      if (indx == 0)
+			rela.r_addend = tlsoff (info, relocation);
+		      rela.r_info = ELFNN_R_INFO (indx, R_LARCH_TLS_TPRELNN);
+		      loongarch_elf_append_rela (output_bfd, relgot, &rela);
 		    }
-		  /* Dynamic resolved.  */
 		  else
 		    {
-		      /* Dynamic relocate offset of block.  */
-		      rela.r_info = ELFNN_R_INFO (h->dynindx,
-						  R_LARCH_TLS_TPRELNN);
-		      rela.r_addend = 0;
-		      loongarch_elf_append_rela (output_bfd, relgot, &rela);
+		      /* In a static link or an executable link with the symbol
+			 bindinglocally, compute offset directly.  */
+		      bfd_put_NN (output_bfd, tlsoff (info, relocation),
+			  got->contents + got_off + ie_off);
 		    }
 		}
 	    }
@@ -3805,7 +3812,7 @@  loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
 
 	    tls_type = _bfd_loongarch_elf_tls_type (input_bfd, h, r_symndx);
 	    /* Use both TLS_GD and TLS_DESC.  */
-	    if ((tls_type & GOT_TLS_GD) && (tls_type & GOT_TLS_GDESC))
+	    if (GOT_TLS_GD_BOTH_P (tls_type))
 	      relocation += 2 * GOT_ENTRY_SIZE;
 
 	    if (r_type == R_LARCH_TLS_DESC64_PC_LO20)
diff --git a/ld/testsuite/ld-loongarch-elf/desc-ie.d b/ld/testsuite/ld-loongarch-elf/desc-ie.d
index e1f49e2d556..c833b233d42 100644
--- a/ld/testsuite/ld-loongarch-elf/desc-ie.d
+++ b/ld/testsuite/ld-loongarch-elf/desc-ie.d
@@ -9,6 +9,6 @@  Disassembly of section .text:
 
 [0-9a-f]+ <fn1>:
  +[0-9a-f]+:	1a000084 	pcalau12i   	\$a0, .*
- +[0-9a-f]+:	28cca084 	ld.d        	\$a0, \$a0, .*
+ +[0-9a-f]+:	28cd0084 	ld.d        	\$a0, \$a0, .*
  +[0-9a-f]+:	1a000084 	pcalau12i   	\$a0, .*
- +[0-9a-f]+:	28cca084 	ld.d        	\$a0, \$a0, .*
+ +[0-9a-f]+:	28cd0084 	ld.d        	\$a0, \$a0, .*
diff --git a/ld/testsuite/ld-loongarch-elf/tlsdesc-dso.d b/ld/testsuite/ld-loongarch-elf/tlsdesc-dso.d
index 84ea97e076b..8f66302f1cf 100644
--- a/ld/testsuite/ld-loongarch-elf/tlsdesc-dso.d
+++ b/ld/testsuite/ld-loongarch-elf/tlsdesc-dso.d
@@ -8,53 +8,53 @@ 
 
 Disassembly of section .text:
 
-0+448 <fun_gl1>:
- 448:	18021584 	pcaddi      	\$a0, 4268
- 44c:	1a000084 	pcalau12i   	\$a0, 4
- 450:	28dc2084 	ld.d        	\$a0, \$a0, 1800
- 454:	18021364 	pcaddi      	\$a0, 4251
- 458:	180213c4 	pcaddi      	\$a0, 4254
- 45c:	28c00081 	ld.d        	\$ra, \$a0, 0
- 460:	4c000021 	jirl        	\$ra, \$ra, 0
- 464:	1a000084 	pcalau12i   	\$a0, 4
- 468:	28dae084 	ld.d        	\$a0, \$a0, 1720
- 46c:	1a000084 	pcalau12i   	\$a0, 4
- 470:	28dae084 	ld.d        	\$a0, \$a0, 1720
- 474:	18021364 	pcaddi      	\$a0, 4251
- 478:	18021344 	pcaddi      	\$a0, 4250
- 47c:	28c00081 	ld.d        	\$ra, \$a0, 0
- 480:	4c000021 	jirl        	\$ra, \$ra, 0
- 484:	1a000084 	pcalau12i   	\$a0, 4
- 488:	28dbc084 	ld.d        	\$a0, \$a0, 1776
+[0-9a-f]+ <fun_gl1>:
+ +[0-9a-f]+:	18021584 	pcaddi      	\$a0, 4268
+ +[0-9a-f]+:	1a000084 	pcalau12i   	\$a0, 4
+ +[0-9a-f]+:	28dd4084 	ld.d        	\$a0, \$a0, 1872
+ +[0-9a-f]+:	18021364 	pcaddi      	\$a0, 4251
+ +[0-9a-f]+:	180213c4 	pcaddi      	\$a0, 4254
+ +[0-9a-f]+:	28c00081 	ld.d        	\$ra, \$a0, 0
+ +[0-9a-f]+:	4c000021 	jirl        	\$ra, \$ra, 0
+ +[0-9a-f]+:	1a000084 	pcalau12i   	\$a0, 4
+ +[0-9a-f]+:	28dc0084 	ld.d        	\$a0, \$a0, 1792
+ +[0-9a-f]+:	1a000084 	pcalau12i   	\$a0, 4
+ +[0-9a-f]+:	28dc0084 	ld.d        	\$a0, \$a0, 1792
+ +[0-9a-f]+:	18021364 	pcaddi      	\$a0, 4251
+ +[0-9a-f]+:	180213c4 	pcaddi      	\$a0, 4254
+ +[0-9a-f]+:	28c00081 	ld.d        	\$ra, \$a0, 0
+ +[0-9a-f]+:	4c000021 	jirl        	\$ra, \$ra, 0
+ +[0-9a-f]+:	1a000084 	pcalau12i   	\$a0, 4
+ +[0-9a-f]+:	28dce084 	ld.d        	\$a0, \$a0, 1848
 
-0+48c <fun_lo>:
- 48c:	1a000084 	pcalau12i   	\$a0, 4
- 490:	28d98084 	ld.d        	\$a0, \$a0, 1632
- 494:	18020de4 	pcaddi      	\$a0, 4207
- 498:	18020f04 	pcaddi      	\$a0, 4216
- 49c:	28c00081 	ld.d        	\$ra, \$a0, 0
- 4a0:	4c000021 	jirl        	\$ra, \$ra, 0
- 4a4:	18020e24 	pcaddi      	\$a0, 4209
- 4a8:	1a000084 	pcalau12i   	\$a0, 4
- 4ac:	28da2084 	ld.d        	\$a0, \$a0, 1672
- 4b0:	1a000084 	pcalau12i   	\$a0, 4
- 4b4:	28da2084 	ld.d        	\$a0, \$a0, 1672
- 4b8:	18020ec4 	pcaddi      	\$a0, 4214
- 4bc:	28c00081 	ld.d        	\$ra, \$a0, 0
- 4c0:	4c000021 	jirl        	\$ra, \$ra, 0
- 4c4:	18020e64 	pcaddi      	\$a0, 4211
- 4c8:	1a000084 	pcalau12i   	\$a0, 4
- 4cc:	28da8084 	ld.d        	\$a0, \$a0, 1696
+[0-9a-f]+ <fun_lo>:
+ +[0-9a-f]+:	1a000084 	pcalau12i   	\$a0, 4
+ +[0-9a-f]+:	28daa084 	ld.d        	\$a0, \$a0, 1704
+ +[0-9a-f]+:	18020de4 	pcaddi      	\$a0, 4207
+ +[0-9a-f]+:	18020f04 	pcaddi      	\$a0, 4216
+ +[0-9a-f]+:	28c00081 	ld.d        	\$ra, \$a0, 0
+ +[0-9a-f]+:	4c000021 	jirl        	\$ra, \$ra, 0
+ +[0-9a-f]+:	18020e24 	pcaddi      	\$a0, 4209
+ +[0-9a-f]+:	1a000084 	pcalau12i   	\$a0, 4
+ +[0-9a-f]+:	28db4084 	ld.d        	\$a0, \$a0, 1744
+ +[0-9a-f]+:	1a000084 	pcalau12i   	\$a0, 4
+ +[0-9a-f]+:	28db4084 	ld.d        	\$a0, \$a0, 1744
+ +[0-9a-f]+:	18020f44 	pcaddi      	\$a0, 4218
+ +[0-9a-f]+:	28c00081 	ld.d        	\$ra, \$a0, 0
+ +[0-9a-f]+:	4c000021 	jirl        	\$ra, \$ra, 0
+ +[0-9a-f]+:	18020e64 	pcaddi      	\$a0, 4211
+ +[0-9a-f]+:	1a000084 	pcalau12i   	\$a0, 4
+ +[0-9a-f]+:	28dba084 	ld.d        	\$a0, \$a0, 1768
 
-0+4d0 <fun_external>:
- 4d0:	18020ec4 	pcaddi      	\$a0, 4214
- 4d4:	28c00081 	ld.d        	\$ra, \$a0, 0
- 4d8:	4c000021 	jirl        	\$ra, \$ra, 0
+[0-9a-f]+ <fun_external>:
+ +[0-9a-f]+:	18020ec4 	pcaddi      	\$a0, 4214
+ +[0-9a-f]+:	28c00081 	ld.d        	\$ra, \$a0, 0
+ +[0-9a-f]+:	4c000021 	jirl        	\$ra, \$ra, 0
 
-0+4dc <fun_hidden>:
- 4dc:	18021224 	pcaddi      	\$a0, 4241
- 4e0:	28c00081 	ld.d        	\$ra, \$a0, 0
- 4e4:	4c000021 	jirl        	\$ra, \$ra, 0
- 4e8:	18021144 	pcaddi      	\$a0, 4234
- 4ec:	28c00081 	ld.d        	\$ra, \$a0, 0
- 4f0:	4c000021 	jirl        	\$ra, \$ra, 0
+[0-9a-f]+ <fun_hidden>:
+ +[0-9a-f]+:	18021224 	pcaddi      	\$a0, 4241
+ +[0-9a-f]+:	28c00081 	ld.d        	\$ra, \$a0, 0
+ +[0-9a-f]+:	4c000021 	jirl        	\$ra, \$ra, 0
+ +[0-9a-f]+:	18021144 	pcaddi      	\$a0, 4234
+ +[0-9a-f]+:	28c00081 	ld.d        	\$ra, \$a0, 0
+ +[0-9a-f]+:	4c000021 	jirl        	\$ra, \$ra, 0