[v1] LoongArch: Use less DW_LNS_fixed_advance_pc

Message ID 20260819034135.4182729-1-mengqinggang@loongson.cn
State New
Headers
Series [v1] LoongArch: Use less DW_LNS_fixed_advance_pc |

Checks

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

Commit Message

mengqinggang Aug. 19, 2026, 3:41 a.m. UTC
  If DWARF2_USE_FIXED_ADVANCE_PC is nonzero, use the DW_LNS_fixed_advance_pc
opcode; otherwise, use special opcodes.

Add FROM symbol and TO symbol parameters for finer-grained control.

Use special opcodes when no linker-relaxable instructions between two symbols;
otherwise, use DW_LNS_fixed_advance_pc opcodes.

Add a new macro DWARF2_USE_FIXED_ADVANCE_PC_FRAG to avoid unnecessary calls
to symbol_get_value_expression on other targets.
---
Changes in V1 (based on Alan's feedback):
- Delete the first DWARF2_USE_FIXED_ADVANCE_PC and always call
  resolve_symbol_value with finalize_syms zero in dwarf2dbg_convert_frag.
- Add a new macro DWARF2_USE_FIXED_ADVANCE_PC_FRAG to avoid unnecessary
  calls to symbol_get_value_expression on other targets.

 gas/config/tc-h8300.h                         |  2 +-
 gas/config/tc-loongarch.c                     | 25 ++++++++++
 gas/config/tc-loongarch.h                     | 10 +++-
 gas/config/tc-msp430.h                        |  2 +-
 gas/config/tc-nds32.h                         |  2 +-
 gas/config/tc-riscv.h                         |  2 +-
 gas/config/tc-rl78.h                          |  2 +-
 gas/config/tc-xtensa.h                        |  2 +-
 gas/dwarf2dbg.c                               | 49 ++++++++++---------
 gas/testsuite/gas/elf/dwarf-5-irp.d           |  3 +-
 gas/testsuite/gas/elf/dwarf-5-loc0.d          |  3 +-
 gas/testsuite/gas/elf/dwarf-5-macro-include.d |  2 +-
 gas/testsuite/gas/elf/dwarf-5-macro.d         |  2 +-
 gas/testsuite/gas/elf/dwarf2-11.d             |  3 +-
 gas/testsuite/gas/elf/dwarf2-15.d             |  3 +-
 gas/testsuite/gas/elf/dwarf2-16.d             |  3 +-
 gas/testsuite/gas/elf/dwarf2-17.d             |  3 +-
 gas/testsuite/gas/elf/dwarf2-18.d             |  3 +-
 gas/testsuite/gas/elf/dwarf2-19.d             |  3 +-
 gas/testsuite/gas/elf/dwarf2-5.d              |  3 +-
 gas/testsuite/gas/lns/lns.exp                 |  1 -
 .../relax-debug-line-opcode-norelax.d         | 10 ++++
 .../gas/loongarch/relax-debug-line-opcode.d   | 25 ++++++++++
 .../gas/loongarch/relax-debug-line-opcode.s   | 15 ++++++
 24 files changed, 125 insertions(+), 53 deletions(-)
 create mode 100644 gas/testsuite/gas/loongarch/relax-debug-line-opcode-norelax.d
 create mode 100644 gas/testsuite/gas/loongarch/relax-debug-line-opcode.d
 create mode 100644 gas/testsuite/gas/loongarch/relax-debug-line-opcode.s
  

Comments

mengqinggang Aug. 26, 2026, 6:38 a.m. UTC | #1
Gentle ping.


在 2026/8/19 11:41, mengqinggang 写道:
> If DWARF2_USE_FIXED_ADVANCE_PC is nonzero, use the DW_LNS_fixed_advance_pc
> opcode; otherwise, use special opcodes.
>
> Add FROM symbol and TO symbol parameters for finer-grained control.
>
> Use special opcodes when no linker-relaxable instructions between two symbols;
> otherwise, use DW_LNS_fixed_advance_pc opcodes.
>
> Add a new macro DWARF2_USE_FIXED_ADVANCE_PC_FRAG to avoid unnecessary calls
> to symbol_get_value_expression on other targets.
> ---
> Changes in V1 (based on Alan's feedback):
> - Delete the first DWARF2_USE_FIXED_ADVANCE_PC and always call
>    resolve_symbol_value with finalize_syms zero in dwarf2dbg_convert_frag.
> - Add a new macro DWARF2_USE_FIXED_ADVANCE_PC_FRAG to avoid unnecessary
>    calls to symbol_get_value_expression on other targets.
>
>   gas/config/tc-h8300.h                         |  2 +-
>   gas/config/tc-loongarch.c                     | 25 ++++++++++
>   gas/config/tc-loongarch.h                     | 10 +++-
>   gas/config/tc-msp430.h                        |  2 +-
>   gas/config/tc-nds32.h                         |  2 +-
>   gas/config/tc-riscv.h                         |  2 +-
>   gas/config/tc-rl78.h                          |  2 +-
>   gas/config/tc-xtensa.h                        |  2 +-
>   gas/dwarf2dbg.c                               | 49 ++++++++++---------
>   gas/testsuite/gas/elf/dwarf-5-irp.d           |  3 +-
>   gas/testsuite/gas/elf/dwarf-5-loc0.d          |  3 +-
>   gas/testsuite/gas/elf/dwarf-5-macro-include.d |  2 +-
>   gas/testsuite/gas/elf/dwarf-5-macro.d         |  2 +-
>   gas/testsuite/gas/elf/dwarf2-11.d             |  3 +-
>   gas/testsuite/gas/elf/dwarf2-15.d             |  3 +-
>   gas/testsuite/gas/elf/dwarf2-16.d             |  3 +-
>   gas/testsuite/gas/elf/dwarf2-17.d             |  3 +-
>   gas/testsuite/gas/elf/dwarf2-18.d             |  3 +-
>   gas/testsuite/gas/elf/dwarf2-19.d             |  3 +-
>   gas/testsuite/gas/elf/dwarf2-5.d              |  3 +-
>   gas/testsuite/gas/lns/lns.exp                 |  1 -
>   .../relax-debug-line-opcode-norelax.d         | 10 ++++
>   .../gas/loongarch/relax-debug-line-opcode.d   | 25 ++++++++++
>   .../gas/loongarch/relax-debug-line-opcode.s   | 15 ++++++
>   24 files changed, 125 insertions(+), 53 deletions(-)
>   create mode 100644 gas/testsuite/gas/loongarch/relax-debug-line-opcode-norelax.d
>   create mode 100644 gas/testsuite/gas/loongarch/relax-debug-line-opcode.d
>   create mode 100644 gas/testsuite/gas/loongarch/relax-debug-line-opcode.s
>
> diff --git a/gas/config/tc-h8300.h b/gas/config/tc-h8300.h
> index c4689d37b12..66664553a24 100644
> --- a/gas/config/tc-h8300.h
> +++ b/gas/config/tc-h8300.h
> @@ -46,7 +46,7 @@ struct internal_reloc;
>   
>   /* Minimum instruction is of 16 bits.  */
>   #define DWARF2_LINE_MIN_INSN_LENGTH 2
> -#define DWARF2_USE_FIXED_ADVANCE_PC 0
> +#define DWARF2_USE_FIXED_ADVANCE_PC(FROM, TO) 0
>   
>   /* Provide mappings from the original H8 COFF relocation names to
>      their corresponding BFD relocation names.  */
> diff --git a/gas/config/tc-loongarch.c b/gas/config/tc-loongarch.c
> index bd7d8dabb7a..e02881761fe 100644
> --- a/gas/config/tc-loongarch.c
> +++ b/gas/config/tc-loongarch.c
> @@ -1644,6 +1644,31 @@ _loongarch_force_relocation_sub_same (segT sec,
>     return true;
>   }
>   
> +/* Use DW_LNS_fixed_advance_pc with relocations if there are linker-relaxable
> +   instructions between from and to symbols. Otherwise, use special opcodes
> +   without relocations.  */
> +bool
> +loongarch_fixed_advance_pc (symbolS *from, symbolS *to)
> +{
> +  segT fromsec = S_GET_SEGMENT (from);
> +  segT tosec = S_GET_SEGMENT (to);
> +  if (fromsec != tosec)
> +    return false;
> +  fragS *fromfrag = symbol_get_frag (from);
> +  fragS *tofrag = symbol_get_frag (to);
> +  return _loongarch_force_relocation_sub_same (fromsec, fromfrag, tofrag);
> +}
> +
> +/* Similar to loongarch_fixed_advance_pc, used for frag.  */
> +bool
> +loongarch_fixed_advance_pc_frag (fragS *frag)
> +{
> +  expressionS *exp = symbol_get_value_expression (frag->fr_symbol);
> +
> +  if (exp->X_op != O_subtract)
> +    return false;
> +  return loongarch_fixed_advance_pc (exp->X_op_symbol, exp->X_add_symbol);
> +}
>   
>   /* Postpone text-section label subtraction calculation until linking,
>      since linker relaxations might change the deltas.  */
> diff --git a/gas/config/tc-loongarch.h b/gas/config/tc-loongarch.h
> index 146844e772e..1f11f9cef46 100644
> --- a/gas/config/tc-loongarch.h
> +++ b/gas/config/tc-loongarch.h
> @@ -101,8 +101,14 @@ extern bool loongarch_force_relocation_sub_same(struct fix *, asection *);
>   #define MD_APPLY_SYM_VALUE(FIX) 0
>   
>   #define TARGET_USE_CFIPOP 1
> -/* Adjust debug_line after relaxation.  */
> -#define DWARF2_USE_FIXED_ADVANCE_PC   1
> +
> +extern bool loongarch_fixed_advance_pc (symbolS *, symbolS *);
> +#define DWARF2_USE_FIXED_ADVANCE_PC(FROM, TO) \
> +  loongarch_fixed_advance_pc (FROM, TO)
> +
> +extern bool loongarch_fixed_advance_pc_frag (fragS *);
> +#define DWARF2_USE_FIXED_ADVANCE_PC_FRAG(FRAG) \
> +  loongarch_fixed_advance_pc_frag (FRAG)
>   
>   /* FDE Data Alignment Factor.
>      FDE Code Alignment Factor (DWARF2_LINE_MIN_INSN_LENGTH) should be 1
> diff --git a/gas/config/tc-msp430.h b/gas/config/tc-msp430.h
> index fe202abc713..f9b6c1e588c 100644
> --- a/gas/config/tc-msp430.h
> +++ b/gas/config/tc-msp430.h
> @@ -168,7 +168,7 @@ extern bool msp430_allow_local_subtract (expressionS *, expressionS *, segT);
>      so don't report errors at this point.  */
>   #define TC_VALIDATE_FIX_SUB(FIX, SEG) 1
>   
> -#define DWARF2_USE_FIXED_ADVANCE_PC 1
> +#define DWARF2_USE_FIXED_ADVANCE_PC(FROM, TO) 1
>   
>   #define TC_LINKRELAX_FIXUP(seg) ((seg->flags & SEC_CODE) || (seg->flags & SEC_DEBUGGING))
>   
> diff --git a/gas/config/tc-nds32.h b/gas/config/tc-nds32.h
> index 432d46d9fb1..49a1bead095 100644
> --- a/gas/config/tc-nds32.h
> +++ b/gas/config/tc-nds32.h
> @@ -77,7 +77,7 @@ extern bool nds32_allow_local_subtract (expressionS *, expressionS *, segT);
>   #define md_allow_local_subtract(lhs,rhs,sect)	nds32_allow_local_subtract (lhs, rhs, sect)
>   
>   /* dwarf2dbg.c.  */
> -#define DWARF2_USE_FIXED_ADVANCE_PC		1
> +#define DWARF2_USE_FIXED_ADVANCE_PC(FROM, TO)	1
>   
>   /* write.c.  */
>   extern long nds32_pcrel_from_section (struct fix *, segT);
> diff --git a/gas/config/tc-riscv.h b/gas/config/tc-riscv.h
> index d695db83477..7518d2a70f7 100644
> --- a/gas/config/tc-riscv.h
> +++ b/gas/config/tc-riscv.h
> @@ -135,7 +135,7 @@ extern void riscv_elf_section_change_hook (void);
>   extern void riscv_elf_final_processing (void);
>   
>   /* Adjust debug_line after relaxation.  */
> -#define DWARF2_USE_FIXED_ADVANCE_PC 1
> +#define DWARF2_USE_FIXED_ADVANCE_PC(FROM, TO) 1
>   
>   #define md_parse_name(name, exp, mode, c) \
>     riscv_parse_name (name, exp, mode)
> diff --git a/gas/config/tc-rl78.h b/gas/config/tc-rl78.h
> index 9761d509aa1..fb54a2e8da7 100644
> --- a/gas/config/tc-rl78.h
> +++ b/gas/config/tc-rl78.h
> @@ -94,6 +94,6 @@ extern void rl78_elf_final_processing (void);
>      || ((SEC)->flags & SEC_DEBUGGING) != 0	\
>      || TC_FORCE_RELOCATION (FIX))
>   
> -#define DWARF2_USE_FIXED_ADVANCE_PC 1
> +#define DWARF2_USE_FIXED_ADVANCE_PC(FROM, TO) 1
>   
>   #define TC_FORCE_RELOCATION(FIX) (linkrelax)
> diff --git a/gas/config/tc-xtensa.h b/gas/config/tc-xtensa.h
> index 64d735144d7..d6ddac738fe 100644
> --- a/gas/config/tc-xtensa.h
> +++ b/gas/config/tc-xtensa.h
> @@ -419,7 +419,7 @@ extern void xtensa_init (int, char **);
>   #define SUB_SEGMENT_ALIGN(SEG, FRCHAIN) 0
>   
>   /* Use line number format that is amenable to linker relaxation.  */
> -#define DWARF2_USE_FIXED_ADVANCE_PC (linkrelax != 0)
> +#define DWARF2_USE_FIXED_ADVANCE_PC(FROM, TO) (linkrelax != 0)
>   
>   
>   /* Resource reservation info functions.  */
> diff --git a/gas/dwarf2dbg.c b/gas/dwarf2dbg.c
> index a1ceab4e428..c899eecd26b 100644
> --- a/gas/dwarf2dbg.c
> +++ b/gas/dwarf2dbg.c
> @@ -112,7 +112,13 @@
>      opcodes and variable-length operands cannot be used.  If this macro is
>      nonzero, use the DW_LNS_fixed_advance_pc opcode instead.  */
>   #ifndef DWARF2_USE_FIXED_ADVANCE_PC
> -# define DWARF2_USE_FIXED_ADVANCE_PC	linkrelax
> +# define DWARF2_USE_FIXED_ADVANCE_PC(FROM, TO)	linkrelax
> +#endif
> +
> +/* Similar to DWARF2_USE_FIXED_ADVANCE_PC, used for frag.  */
> +#ifndef DWARF2_USE_FIXED_ADVANCE_PC_FRAG
> +# define DWARF2_USE_FIXED_ADVANCE_PC_FRAG(FRAG) \
> +	 DWARF2_USE_FIXED_ADVANCE_PC (0, 0)
>   #endif
>   
>   /* First special line opcode - leave room for the standard opcodes.
> @@ -1898,7 +1904,7 @@ relax_inc_line_addr (int line_delta, symbolS *to_sym, symbolS *from_sym)
>   
>     /* The maximum size of the frag is the line delta with a maximum
>        sized address delta.  */
> -  if (DWARF2_USE_FIXED_ADVANCE_PC)
> +  if (DWARF2_USE_FIXED_ADVANCE_PC (from_sym, to_sym))
>       max_chars = size_fixed_inc_line_addr (line_delta,
>   					  -DWARF2_LINE_MIN_INSN_LENGTH);
>     else
> @@ -1919,7 +1925,7 @@ dwarf2dbg_estimate_size_before_relax (fragS *frag)
>     int size;
>   
>     addr_delta = resolve_symbol_value (frag->fr_symbol);
> -  if (DWARF2_USE_FIXED_ADVANCE_PC)
> +  if (DWARF2_USE_FIXED_ADVANCE_PC_FRAG (frag))
>       size = size_fixed_inc_line_addr (frag->fr_offset, addr_delta);
>     else
>       size = size_inc_line_addr (frag->fr_offset, addr_delta);
> @@ -1953,31 +1959,25 @@ dwarf2dbg_convert_frag (fragS *frag)
>   {
>     offsetT addr_diff;
>   
> -  if (DWARF2_USE_FIXED_ADVANCE_PC)
> -    {
> -      /* If linker relaxation is enabled then the distance between the two
> -	 symbols in the frag->fr_symbol expression might change.  Hence we
> -	 cannot rely upon the value computed by resolve_symbol_value.
> -	 Instead we leave the expression unfinalized and allow
> -	 emit_fixed_inc_line_addr to create a fixup (which later becomes a
> -	 relocation) that will allow the linker to correctly compute the
> -	 actual address difference.  We have to use a fixed line advance for
> -	 this as we cannot (easily) relocate leb128 encoded values.  */
> -      int saved_finalize_syms = finalize_syms;
> -
> -      finalize_syms = 0;
> -      addr_diff = resolve_symbol_value (frag->fr_symbol);
> -      finalize_syms = saved_finalize_syms;
> -    }
> -  else
> -    addr_diff = resolve_symbol_value (frag->fr_symbol);
> +  /* If linker relaxation is enabled then the distance between the two
> +     symbols in the frag->fr_symbol expression might change.  Hence we
> +     cannot rely upon the value computed by resolve_symbol_value.
> +     Instead we leave the expression unfinalized and allow
> +     emit_fixed_inc_line_addr to create a fixup (which later becomes a
> +     relocation) that will allow the linker to correctly compute the
> +     actual address difference.  We have to use a fixed line advance for
> +     this as we cannot (easily) relocate leb128 encoded values.  */
> +  int saved_finalize_syms = finalize_syms;
> +  finalize_syms = 0;
> +  addr_diff = resolve_symbol_value (frag->fr_symbol);
> +  finalize_syms = saved_finalize_syms;
>   
>     /* fr_var carries the max_chars that we created the fragment with.
>        fr_subtype carries the current expected length.  We must, of
>        course, have allocated enough memory earlier.  */
>     gas_assert (frag->fr_var >= (int) frag->fr_subtype);
>   
> -  if (DWARF2_USE_FIXED_ADVANCE_PC)
> +  if (DWARF2_USE_FIXED_ADVANCE_PC_FRAG (frag))
>       emit_fixed_inc_line_addr (frag->fr_offset, addr_diff, frag,
>   			      frag->fr_literal + frag->fr_fix,
>   			      frag->fr_subtype);
> @@ -2110,7 +2110,8 @@ process_entries (segT seg, struct line_entry *e)
>   	  out_set_addr (lab);
>   	  out_inc_line_addr (line_delta, 0);
>   	}
> -      else if (frag == last_frag && ! DWARF2_USE_FIXED_ADVANCE_PC)
> +      else if (frag == last_frag
> +	       && ! DWARF2_USE_FIXED_ADVANCE_PC (last_lab, lab))
>   	out_inc_line_addr (line_delta, frag_ofs - last_frag_ofs);
>         else
>   	relax_inc_line_addr (line_delta, lab, last_lab);
> @@ -2127,7 +2128,7 @@ process_entries (segT seg, struct line_entry *e)
>     /* Emit a DW_LNE_end_sequence for the end of the section.  */
>     frag = last_frag_for_seg (seg);
>     frag_ofs = get_frag_fix (frag, seg);
> -  if (frag == last_frag && ! DWARF2_USE_FIXED_ADVANCE_PC)
> +  if (frag == last_frag && ! DWARF2_USE_FIXED_ADVANCE_PC (last_lab, lab))
>       out_inc_line_addr (INT_MAX, frag_ofs - last_frag_ofs);
>     else
>       {
> diff --git a/gas/testsuite/gas/elf/dwarf-5-irp.d b/gas/testsuite/gas/elf/dwarf-5-irp.d
> index a4f01355db3..781b2a32aaa 100644
> --- a/gas/testsuite/gas/elf/dwarf-5-irp.d
> +++ b/gas/testsuite/gas/elf/dwarf-5-irp.d
> @@ -5,8 +5,7 @@
>   # The bfin target does not allow .subsection with an equated symbol as operand.
>   # The d30v target emits sufficiently different debug info, apparently also covering padding it inserts.
>   # The riscv targets do not support the subtraction of symbols.
> -# The loongarch targets do not support the subtraction of symbols.
> -#xfail: am33*-* bfin-* cr16-* crx-* d30v-* ft32-* loongarch*-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
> +#xfail: am33*-* bfin-* cr16-* crx-* d30v-* ft32-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
>   
>   Raw dump of debug contents .*
>   #...
> diff --git a/gas/testsuite/gas/elf/dwarf-5-loc0.d b/gas/testsuite/gas/elf/dwarf-5-loc0.d
> index 9338271c0eb..9439d103b1f 100644
> --- a/gas/testsuite/gas/elf/dwarf-5-loc0.d
> +++ b/gas/testsuite/gas/elf/dwarf-5-loc0.d
> @@ -3,8 +3,7 @@
>   #name: DWARF5 .loc 0
>   # The am33 cr16 crx ft32 mn10 msp430 nds32 and rl78 targets do not evaluate the subtraction of symbols at assembly time.
>   # The riscv targets do not support the subtraction of symbols.
> -# The loongarch targets do not support the subtraction of symbols.
> -#xfail: am3*-* cr16-* crx-* ft32*-* loongarch*-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
> +#xfail: am3*-* cr16-* crx-* ft32*-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
>   
>   Contents of the \.debug_line section:
>   
> diff --git a/gas/testsuite/gas/elf/dwarf-5-macro-include.d b/gas/testsuite/gas/elf/dwarf-5-macro-include.d
> index c39425aa8c9..32ea6386992 100644
> --- a/gas/testsuite/gas/elf/dwarf-5-macro-include.d
> +++ b/gas/testsuite/gas/elf/dwarf-5-macro-include.d
> @@ -4,7 +4,7 @@
>   # The am33 cr16 crx ft32 mn10* msp430 nds32* and rl78 targets do not evaluate the subtraction of symbols at assembly time.
>   # The d30v target emits sufficiently different debug info, apparently also covering padding it inserts.
>   # The riscv targets do not support the subtraction of symbols.
> -#xfail: am33*-* cr16-* crx-* d30v-* ft32-* loongarch*-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
> +#xfail: am33*-* cr16-* crx-* d30v-* ft32-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
>   
>   Raw dump of debug contents .*
>   #...
> diff --git a/gas/testsuite/gas/elf/dwarf-5-macro.d b/gas/testsuite/gas/elf/dwarf-5-macro.d
> index b2613bd1c16..794e17a575e 100644
> --- a/gas/testsuite/gas/elf/dwarf-5-macro.d
> +++ b/gas/testsuite/gas/elf/dwarf-5-macro.d
> @@ -4,7 +4,7 @@
>   # The am33 cr16 crx ft32 mn10* msp430 nds32* and rl78 targets do not evaluate the subtraction of symbols at assembly time.
>   # The d30v target emits sufficiently different debug info, apparently also covering padding it inserts.
>   # The riscv targets do not support the subtraction of symbols.
> -#xfail: am33*-* cr16-* crx-* d30v-* ft32-* loongarch*-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
> +#xfail: am33*-* cr16-* crx-* d30v-* ft32-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
>   
>   Raw dump of debug contents .*
>   #...
> diff --git a/gas/testsuite/gas/elf/dwarf2-11.d b/gas/testsuite/gas/elf/dwarf2-11.d
> index 44f5cd18ec6..2c30e55c695 100644
> --- a/gas/testsuite/gas/elf/dwarf2-11.d
> +++ b/gas/testsuite/gas/elf/dwarf2-11.d
> @@ -3,8 +3,7 @@
>   #name: DWARF2 11
>   # The am33 cr16 crx ft32 mn10 msp430 nds32 and rl78 targets do not evaluate the subtraction of symbols at assembly time.
>   # The riscv targets do not support the subtraction of symbols.
> -# The loongarch targets do not support the subtraction of symbols.
> -#xfail: am3*-* cr16-* crx-* ft32*-* loongarch*-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
> +#xfail: am3*-* cr16-* crx-* ft32*-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
>   
>   Contents of the \.debug_line section:
>   
> diff --git a/gas/testsuite/gas/elf/dwarf2-15.d b/gas/testsuite/gas/elf/dwarf2-15.d
> index 3ec9f2785a7..939c61598cb 100644
> --- a/gas/testsuite/gas/elf/dwarf2-15.d
> +++ b/gas/testsuite/gas/elf/dwarf2-15.d
> @@ -3,8 +3,7 @@
>   #name: DWARF2 15
>   # The am33 cr16 crx ft32 mn10 msp430 nds32 and rl78 targets do not evaluate the subtraction of symbols at assembly time.
>   # The riscv targets do not support the subtraction of symbols.
> -# The loongarch targets do not support the subtraction of symbols.
> -#xfail: am3*-* cr16-* crx-* ft32*-* loongarch*-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
> +#xfail: am3*-* cr16-* crx-* ft32*-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
>   
>   Hex dump of section '\.rodata':
>     0x00000000 01 *.*
> diff --git a/gas/testsuite/gas/elf/dwarf2-16.d b/gas/testsuite/gas/elf/dwarf2-16.d
> index 32b57763137..8e35d493619 100644
> --- a/gas/testsuite/gas/elf/dwarf2-16.d
> +++ b/gas/testsuite/gas/elf/dwarf2-16.d
> @@ -4,8 +4,7 @@
>   # The am33 cr16 crx ft32 mn10 msp430 nds32 and rl78 targets do not evaluate the subtraction of symbols at assembly time.
>   # The mep target tries to relay code sections which breaks symbolic view computations.
>   # The riscv targets do not support the subtraction of symbols.
> -# The loongarch targets do not support the subtraction of symbols.
> -#xfail: am3*-* cr16-* crx-* ft32*-* mep-* loongarch*-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
> +#xfail: am3*-* cr16-* crx-* ft32*-* mep-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
>   
>   Hex dump of section '\.rodata':
>     0x00000000 01 *.*
> diff --git a/gas/testsuite/gas/elf/dwarf2-17.d b/gas/testsuite/gas/elf/dwarf2-17.d
> index 4c2f2e3999e..881477cf95b 100644
> --- a/gas/testsuite/gas/elf/dwarf2-17.d
> +++ b/gas/testsuite/gas/elf/dwarf2-17.d
> @@ -4,8 +4,7 @@
>   # The am33 cr16 crx ft32 mn10 msp430 nds32 and rl78 targets do not evaluate the subtraction of symbols at assembly time.
>   # The mep target tries to relay code sections which breaks symbolic view computations.
>   # The riscv targets do not support the subtraction of symbols.
> -# The loongarch targets do not support the subtraction of symbols.
> -#xfail: am3*-* cr16-* crx-* ft32*-* loongarch*-* mep-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
> +#xfail: am3*-* cr16-* crx-* ft32*-* mep-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
>   
>   Hex dump of section '\.rodata':
>     0x00000000 00 *.*
> diff --git a/gas/testsuite/gas/elf/dwarf2-18.d b/gas/testsuite/gas/elf/dwarf2-18.d
> index 18157c634a5..fbaebaa9019 100644
> --- a/gas/testsuite/gas/elf/dwarf2-18.d
> +++ b/gas/testsuite/gas/elf/dwarf2-18.d
> @@ -3,8 +3,7 @@
>   #name: DWARF2 18
>   # The am33 cr16 crx ft32 mn10 msp430 nds32 and rl78 targets do not evaluate the subtraction of symbols at assembly time.
>   # The riscv targets do not support the subtraction of symbols.
> -# The loongarch targets do not support the subtraction of symbols.
> -#xfail: am3*-* cr16-* crx-* ft32*-* loongarch*-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
> +#xfail: am3*-* cr16-* crx-* ft32*-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
>   
>   Hex dump of section '\.rodata':
>     0x00000000 0100 *.*
> diff --git a/gas/testsuite/gas/elf/dwarf2-19.d b/gas/testsuite/gas/elf/dwarf2-19.d
> index 133294affe7..55d0caf4cb1 100644
> --- a/gas/testsuite/gas/elf/dwarf2-19.d
> +++ b/gas/testsuite/gas/elf/dwarf2-19.d
> @@ -4,8 +4,7 @@
>   # The am33 cr16 crx ft32 mn10 msp430 nds32 and rl78 targets do not evaluate the subtraction of symbols at assembly time.
>   # The mep targets turns some view computations into complex relocations.
>   # The riscv targets do not support the subtraction of symbols.
> -# The loongarch targets do not support the subtraction of symbols.
> -#xfail: am3*-* cr16-* crx-* ft32*-* mep-* loongarch*-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
> +#xfail: am3*-* cr16-* crx-* ft32*-* mep-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
>   
>   Hex dump of section '\.rodata':
>     0x00000000 01000102 *.*
> diff --git a/gas/testsuite/gas/elf/dwarf2-5.d b/gas/testsuite/gas/elf/dwarf2-5.d
> index 1dd65732c50..bf1eeb5bbfd 100644
> --- a/gas/testsuite/gas/elf/dwarf2-5.d
> +++ b/gas/testsuite/gas/elf/dwarf2-5.d
> @@ -4,8 +4,7 @@
>   # The am33 cr16 crx ft32 mn10 msp430 nds32 and rl78 targets do not evaluate the subtraction of symbols at assembly time.
>   # The mep target tries to relay code sections which breaks symbolic view computations.
>   # The riscv targets do not support the subtraction of symbols.
> -# The loongarch targets do not support the subtraction of symbols.
> -#xfail: am3*-* cr16-* crx-* ft32*-* loongarch*-* mep-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
> +#xfail: am3*-* cr16-* crx-* ft32*-* mep-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
>   
>   Hex dump of section '\.rodata':
>     0x00000000 01010201 010203 *.*
> diff --git a/gas/testsuite/gas/lns/lns.exp b/gas/testsuite/gas/lns/lns.exp
> index 7a92c54a260..58c2235b628 100644
> --- a/gas/testsuite/gas/lns/lns.exp
> +++ b/gas/testsuite/gas/lns/lns.exp
> @@ -31,7 +31,6 @@ if { ![istarget s390*-*-*] } {
>   	 || [istarget cr16-*-*]
>   	 || [istarget crx-*-*]
>   	 || [istarget ft32*-*]
> -	 || [istarget loongarch*-*-*]
>   	 || [istarget mn10*-*-*]
>   	 || [istarget msp430-*-*]
>   	 || [istarget nds32*-*-*]
> diff --git a/gas/testsuite/gas/loongarch/relax-debug-line-opcode-norelax.d b/gas/testsuite/gas/loongarch/relax-debug-line-opcode-norelax.d
> new file mode 100644
> index 00000000000..c8be41feb82
> --- /dev/null
> +++ b/gas/testsuite/gas/loongarch/relax-debug-line-opcode-norelax.d
> @@ -0,0 +1,10 @@
> +#source: relax-debug-line-opcode.s
> +#as: -mno-relax
> +#readelf: -W -wl
> +
> +#...
> +.*  Special opcode 62: advance Address by 4 to 0x4 and Line by 1 to 11
> +.*  Special opcode 118: advance Address by 8 to 0xc and Line by 1 to 12
> +.*  Special opcode 62: advance Address by 4 to 0x10 and Line by 1 to 13
> +.*  Special opcode 118: advance Address by 8 to 0x18 and Line by 1 to 14
> +#pass
> diff --git a/gas/testsuite/gas/loongarch/relax-debug-line-opcode.d b/gas/testsuite/gas/loongarch/relax-debug-line-opcode.d
> new file mode 100644
> index 00000000000..9c707d97747
> --- /dev/null
> +++ b/gas/testsuite/gas/loongarch/relax-debug-line-opcode.d
> @@ -0,0 +1,25 @@
> +#source: relax-debug-line-opcode.s
> +#as: -mrelax
> +#readelf: -r -wl -W
> +
> +#...
> +Relocation section '\.rela\.debug_line' at offset .* contains 7 entries:
> +#...
> +.*R_LARCH_ADD16[ 	]+[0-9]+.*
> +.*R_LARCH_SUB16[ 	]+[0-9]+.*
> +.*R_LARCH_ADD16[ 	]+[0-9]+.*
> +.*R_LARCH_SUB16[ 	]+[0-9]+.*
> +#...
> +Raw dump of debug contents of section \.debug_line:
> +#...
> +.*  Special opcode 62: advance Address by 4 to 0x4 and Line by 1 to 11
> +.*  Advance Line by 1 to 12
> +.*  Advance PC by fixed size amount [0-9]+ to 0x[0-9a-f]+
> +.*  Copy .*
> +.*  Special opcode 62: advance Address by 4 to 0x10 and Line by 1 to 13
> +.*  Advance Line by 1 to 14
> +.*  Advance PC by fixed size amount [0-9]+ to 0x[0-9a-f]+
> +.*  Copy .*
> +.*  Advance PC by [0-9]+ to 0x[0-9a-f]+
> +.*  Extended opcode 1: End of Sequence
> +#pass
> diff --git a/gas/testsuite/gas/loongarch/relax-debug-line-opcode.s b/gas/testsuite/gas/loongarch/relax-debug-line-opcode.s
> new file mode 100644
> index 00000000000..276a823373c
> --- /dev/null
> +++ b/gas/testsuite/gas/loongarch/relax-debug-line-opcode.s
> @@ -0,0 +1,15 @@
> +  # Test DWARF line encoding around linker-relaxable instructions.
> +  .file 0 "test"
> +  .text
> +  .loc 0 10 0
> +  nop		# special opcode
> +  .loc 0 11 0
> +  call36 func	# -mrelax: DW_LNS_fixed_advance_pc; -mno-relax: special opcode.
> +  .loc 0 12 0
> +  nop		# special opcode
> +  .loc 0 13 0
> +  call36 func	# -mrelax: DW_LNS_fixed_advance_pc; -mno-relax: special opcode.
> +  .loc 0 14 0
> +  nop		# Advance PC
> +
> +.section .debug_line, "", @progbits
  
Alan Modra Aug. 26, 2026, 1:05 p.m. UTC | #2
On Wed, Aug 26, 2026 at 02:38:53PM +0800, mengqinggang wrote:
> Gentle ping.

OK.

> 在 2026/8/19 11:41, mengqinggang 写道:
> > If DWARF2_USE_FIXED_ADVANCE_PC is nonzero, use the DW_LNS_fixed_advance_pc
> > opcode; otherwise, use special opcodes.
> > 
> > Add FROM symbol and TO symbol parameters for finer-grained control.
> > 
> > Use special opcodes when no linker-relaxable instructions between two symbols;
> > otherwise, use DW_LNS_fixed_advance_pc opcodes.
> > 
> > Add a new macro DWARF2_USE_FIXED_ADVANCE_PC_FRAG to avoid unnecessary calls
> > to symbol_get_value_expression on other targets.
> > ---
> > Changes in V1 (based on Alan's feedback):
> > - Delete the first DWARF2_USE_FIXED_ADVANCE_PC and always call
> >    resolve_symbol_value with finalize_syms zero in dwarf2dbg_convert_frag.
> > - Add a new macro DWARF2_USE_FIXED_ADVANCE_PC_FRAG to avoid unnecessary
> >    calls to symbol_get_value_expression on other targets.
> > 
> >   gas/config/tc-h8300.h                         |  2 +-
> >   gas/config/tc-loongarch.c                     | 25 ++++++++++
> >   gas/config/tc-loongarch.h                     | 10 +++-
> >   gas/config/tc-msp430.h                        |  2 +-
> >   gas/config/tc-nds32.h                         |  2 +-
> >   gas/config/tc-riscv.h                         |  2 +-
> >   gas/config/tc-rl78.h                          |  2 +-
> >   gas/config/tc-xtensa.h                        |  2 +-
> >   gas/dwarf2dbg.c                               | 49 ++++++++++---------
> >   gas/testsuite/gas/elf/dwarf-5-irp.d           |  3 +-
> >   gas/testsuite/gas/elf/dwarf-5-loc0.d          |  3 +-
> >   gas/testsuite/gas/elf/dwarf-5-macro-include.d |  2 +-
> >   gas/testsuite/gas/elf/dwarf-5-macro.d         |  2 +-
> >   gas/testsuite/gas/elf/dwarf2-11.d             |  3 +-
> >   gas/testsuite/gas/elf/dwarf2-15.d             |  3 +-
> >   gas/testsuite/gas/elf/dwarf2-16.d             |  3 +-
> >   gas/testsuite/gas/elf/dwarf2-17.d             |  3 +-
> >   gas/testsuite/gas/elf/dwarf2-18.d             |  3 +-
> >   gas/testsuite/gas/elf/dwarf2-19.d             |  3 +-
> >   gas/testsuite/gas/elf/dwarf2-5.d              |  3 +-
> >   gas/testsuite/gas/lns/lns.exp                 |  1 -
> >   .../relax-debug-line-opcode-norelax.d         | 10 ++++
> >   .../gas/loongarch/relax-debug-line-opcode.d   | 25 ++++++++++
> >   .../gas/loongarch/relax-debug-line-opcode.s   | 15 ++++++
> >   24 files changed, 125 insertions(+), 53 deletions(-)
> >   create mode 100644 gas/testsuite/gas/loongarch/relax-debug-line-opcode-norelax.d
> >   create mode 100644 gas/testsuite/gas/loongarch/relax-debug-line-opcode.d
> >   create mode 100644 gas/testsuite/gas/loongarch/relax-debug-line-opcode.s
> > 
> > diff --git a/gas/config/tc-h8300.h b/gas/config/tc-h8300.h
> > index c4689d37b12..66664553a24 100644
> > --- a/gas/config/tc-h8300.h
> > +++ b/gas/config/tc-h8300.h
> > @@ -46,7 +46,7 @@ struct internal_reloc;
> >   /* Minimum instruction is of 16 bits.  */
> >   #define DWARF2_LINE_MIN_INSN_LENGTH 2
> > -#define DWARF2_USE_FIXED_ADVANCE_PC 0
> > +#define DWARF2_USE_FIXED_ADVANCE_PC(FROM, TO) 0
> >   /* Provide mappings from the original H8 COFF relocation names to
> >      their corresponding BFD relocation names.  */
> > diff --git a/gas/config/tc-loongarch.c b/gas/config/tc-loongarch.c
> > index bd7d8dabb7a..e02881761fe 100644
> > --- a/gas/config/tc-loongarch.c
> > +++ b/gas/config/tc-loongarch.c
> > @@ -1644,6 +1644,31 @@ _loongarch_force_relocation_sub_same (segT sec,
> >     return true;
> >   }
> > +/* Use DW_LNS_fixed_advance_pc with relocations if there are linker-relaxable
> > +   instructions between from and to symbols. Otherwise, use special opcodes
> > +   without relocations.  */
> > +bool
> > +loongarch_fixed_advance_pc (symbolS *from, symbolS *to)
> > +{
> > +  segT fromsec = S_GET_SEGMENT (from);
> > +  segT tosec = S_GET_SEGMENT (to);
> > +  if (fromsec != tosec)
> > +    return false;
> > +  fragS *fromfrag = symbol_get_frag (from);
> > +  fragS *tofrag = symbol_get_frag (to);
> > +  return _loongarch_force_relocation_sub_same (fromsec, fromfrag, tofrag);
> > +}
> > +
> > +/* Similar to loongarch_fixed_advance_pc, used for frag.  */
> > +bool
> > +loongarch_fixed_advance_pc_frag (fragS *frag)
> > +{
> > +  expressionS *exp = symbol_get_value_expression (frag->fr_symbol);
> > +
> > +  if (exp->X_op != O_subtract)
> > +    return false;
> > +  return loongarch_fixed_advance_pc (exp->X_op_symbol, exp->X_add_symbol);
> > +}
> >   /* Postpone text-section label subtraction calculation until linking,
> >      since linker relaxations might change the deltas.  */
> > diff --git a/gas/config/tc-loongarch.h b/gas/config/tc-loongarch.h
> > index 146844e772e..1f11f9cef46 100644
> > --- a/gas/config/tc-loongarch.h
> > +++ b/gas/config/tc-loongarch.h
> > @@ -101,8 +101,14 @@ extern bool loongarch_force_relocation_sub_same(struct fix *, asection *);
> >   #define MD_APPLY_SYM_VALUE(FIX) 0
> >   #define TARGET_USE_CFIPOP 1
> > -/* Adjust debug_line after relaxation.  */
> > -#define DWARF2_USE_FIXED_ADVANCE_PC   1
> > +
> > +extern bool loongarch_fixed_advance_pc (symbolS *, symbolS *);
> > +#define DWARF2_USE_FIXED_ADVANCE_PC(FROM, TO) \
> > +  loongarch_fixed_advance_pc (FROM, TO)
> > +
> > +extern bool loongarch_fixed_advance_pc_frag (fragS *);
> > +#define DWARF2_USE_FIXED_ADVANCE_PC_FRAG(FRAG) \
> > +  loongarch_fixed_advance_pc_frag (FRAG)
> >   /* FDE Data Alignment Factor.
> >      FDE Code Alignment Factor (DWARF2_LINE_MIN_INSN_LENGTH) should be 1
> > diff --git a/gas/config/tc-msp430.h b/gas/config/tc-msp430.h
> > index fe202abc713..f9b6c1e588c 100644
> > --- a/gas/config/tc-msp430.h
> > +++ b/gas/config/tc-msp430.h
> > @@ -168,7 +168,7 @@ extern bool msp430_allow_local_subtract (expressionS *, expressionS *, segT);
> >      so don't report errors at this point.  */
> >   #define TC_VALIDATE_FIX_SUB(FIX, SEG) 1
> > -#define DWARF2_USE_FIXED_ADVANCE_PC 1
> > +#define DWARF2_USE_FIXED_ADVANCE_PC(FROM, TO) 1
> >   #define TC_LINKRELAX_FIXUP(seg) ((seg->flags & SEC_CODE) || (seg->flags & SEC_DEBUGGING))
> > diff --git a/gas/config/tc-nds32.h b/gas/config/tc-nds32.h
> > index 432d46d9fb1..49a1bead095 100644
> > --- a/gas/config/tc-nds32.h
> > +++ b/gas/config/tc-nds32.h
> > @@ -77,7 +77,7 @@ extern bool nds32_allow_local_subtract (expressionS *, expressionS *, segT);
> >   #define md_allow_local_subtract(lhs,rhs,sect)	nds32_allow_local_subtract (lhs, rhs, sect)
> >   /* dwarf2dbg.c.  */
> > -#define DWARF2_USE_FIXED_ADVANCE_PC		1
> > +#define DWARF2_USE_FIXED_ADVANCE_PC(FROM, TO)	1
> >   /* write.c.  */
> >   extern long nds32_pcrel_from_section (struct fix *, segT);
> > diff --git a/gas/config/tc-riscv.h b/gas/config/tc-riscv.h
> > index d695db83477..7518d2a70f7 100644
> > --- a/gas/config/tc-riscv.h
> > +++ b/gas/config/tc-riscv.h
> > @@ -135,7 +135,7 @@ extern void riscv_elf_section_change_hook (void);
> >   extern void riscv_elf_final_processing (void);
> >   /* Adjust debug_line after relaxation.  */
> > -#define DWARF2_USE_FIXED_ADVANCE_PC 1
> > +#define DWARF2_USE_FIXED_ADVANCE_PC(FROM, TO) 1
> >   #define md_parse_name(name, exp, mode, c) \
> >     riscv_parse_name (name, exp, mode)
> > diff --git a/gas/config/tc-rl78.h b/gas/config/tc-rl78.h
> > index 9761d509aa1..fb54a2e8da7 100644
> > --- a/gas/config/tc-rl78.h
> > +++ b/gas/config/tc-rl78.h
> > @@ -94,6 +94,6 @@ extern void rl78_elf_final_processing (void);
> >      || ((SEC)->flags & SEC_DEBUGGING) != 0	\
> >      || TC_FORCE_RELOCATION (FIX))
> > -#define DWARF2_USE_FIXED_ADVANCE_PC 1
> > +#define DWARF2_USE_FIXED_ADVANCE_PC(FROM, TO) 1
> >   #define TC_FORCE_RELOCATION(FIX) (linkrelax)
> > diff --git a/gas/config/tc-xtensa.h b/gas/config/tc-xtensa.h
> > index 64d735144d7..d6ddac738fe 100644
> > --- a/gas/config/tc-xtensa.h
> > +++ b/gas/config/tc-xtensa.h
> > @@ -419,7 +419,7 @@ extern void xtensa_init (int, char **);
> >   #define SUB_SEGMENT_ALIGN(SEG, FRCHAIN) 0
> >   /* Use line number format that is amenable to linker relaxation.  */
> > -#define DWARF2_USE_FIXED_ADVANCE_PC (linkrelax != 0)
> > +#define DWARF2_USE_FIXED_ADVANCE_PC(FROM, TO) (linkrelax != 0)
> >   /* Resource reservation info functions.  */
> > diff --git a/gas/dwarf2dbg.c b/gas/dwarf2dbg.c
> > index a1ceab4e428..c899eecd26b 100644
> > --- a/gas/dwarf2dbg.c
> > +++ b/gas/dwarf2dbg.c
> > @@ -112,7 +112,13 @@
> >      opcodes and variable-length operands cannot be used.  If this macro is
> >      nonzero, use the DW_LNS_fixed_advance_pc opcode instead.  */
> >   #ifndef DWARF2_USE_FIXED_ADVANCE_PC
> > -# define DWARF2_USE_FIXED_ADVANCE_PC	linkrelax
> > +# define DWARF2_USE_FIXED_ADVANCE_PC(FROM, TO)	linkrelax
> > +#endif
> > +
> > +/* Similar to DWARF2_USE_FIXED_ADVANCE_PC, used for frag.  */
> > +#ifndef DWARF2_USE_FIXED_ADVANCE_PC_FRAG
> > +# define DWARF2_USE_FIXED_ADVANCE_PC_FRAG(FRAG) \
> > +	 DWARF2_USE_FIXED_ADVANCE_PC (0, 0)
> >   #endif
> >   /* First special line opcode - leave room for the standard opcodes.
> > @@ -1898,7 +1904,7 @@ relax_inc_line_addr (int line_delta, symbolS *to_sym, symbolS *from_sym)
> >     /* The maximum size of the frag is the line delta with a maximum
> >        sized address delta.  */
> > -  if (DWARF2_USE_FIXED_ADVANCE_PC)
> > +  if (DWARF2_USE_FIXED_ADVANCE_PC (from_sym, to_sym))
> >       max_chars = size_fixed_inc_line_addr (line_delta,
> >   					  -DWARF2_LINE_MIN_INSN_LENGTH);
> >     else
> > @@ -1919,7 +1925,7 @@ dwarf2dbg_estimate_size_before_relax (fragS *frag)
> >     int size;
> >     addr_delta = resolve_symbol_value (frag->fr_symbol);
> > -  if (DWARF2_USE_FIXED_ADVANCE_PC)
> > +  if (DWARF2_USE_FIXED_ADVANCE_PC_FRAG (frag))
> >       size = size_fixed_inc_line_addr (frag->fr_offset, addr_delta);
> >     else
> >       size = size_inc_line_addr (frag->fr_offset, addr_delta);
> > @@ -1953,31 +1959,25 @@ dwarf2dbg_convert_frag (fragS *frag)
> >   {
> >     offsetT addr_diff;
> > -  if (DWARF2_USE_FIXED_ADVANCE_PC)
> > -    {
> > -      /* If linker relaxation is enabled then the distance between the two
> > -	 symbols in the frag->fr_symbol expression might change.  Hence we
> > -	 cannot rely upon the value computed by resolve_symbol_value.
> > -	 Instead we leave the expression unfinalized and allow
> > -	 emit_fixed_inc_line_addr to create a fixup (which later becomes a
> > -	 relocation) that will allow the linker to correctly compute the
> > -	 actual address difference.  We have to use a fixed line advance for
> > -	 this as we cannot (easily) relocate leb128 encoded values.  */
> > -      int saved_finalize_syms = finalize_syms;
> > -
> > -      finalize_syms = 0;
> > -      addr_diff = resolve_symbol_value (frag->fr_symbol);
> > -      finalize_syms = saved_finalize_syms;
> > -    }
> > -  else
> > -    addr_diff = resolve_symbol_value (frag->fr_symbol);
> > +  /* If linker relaxation is enabled then the distance between the two
> > +     symbols in the frag->fr_symbol expression might change.  Hence we
> > +     cannot rely upon the value computed by resolve_symbol_value.
> > +     Instead we leave the expression unfinalized and allow
> > +     emit_fixed_inc_line_addr to create a fixup (which later becomes a
> > +     relocation) that will allow the linker to correctly compute the
> > +     actual address difference.  We have to use a fixed line advance for
> > +     this as we cannot (easily) relocate leb128 encoded values.  */
> > +  int saved_finalize_syms = finalize_syms;
> > +  finalize_syms = 0;
> > +  addr_diff = resolve_symbol_value (frag->fr_symbol);
> > +  finalize_syms = saved_finalize_syms;
> >     /* fr_var carries the max_chars that we created the fragment with.
> >        fr_subtype carries the current expected length.  We must, of
> >        course, have allocated enough memory earlier.  */
> >     gas_assert (frag->fr_var >= (int) frag->fr_subtype);
> > -  if (DWARF2_USE_FIXED_ADVANCE_PC)
> > +  if (DWARF2_USE_FIXED_ADVANCE_PC_FRAG (frag))
> >       emit_fixed_inc_line_addr (frag->fr_offset, addr_diff, frag,
> >   			      frag->fr_literal + frag->fr_fix,
> >   			      frag->fr_subtype);
> > @@ -2110,7 +2110,8 @@ process_entries (segT seg, struct line_entry *e)
> >   	  out_set_addr (lab);
> >   	  out_inc_line_addr (line_delta, 0);
> >   	}
> > -      else if (frag == last_frag && ! DWARF2_USE_FIXED_ADVANCE_PC)
> > +      else if (frag == last_frag
> > +	       && ! DWARF2_USE_FIXED_ADVANCE_PC (last_lab, lab))
> >   	out_inc_line_addr (line_delta, frag_ofs - last_frag_ofs);
> >         else
> >   	relax_inc_line_addr (line_delta, lab, last_lab);
> > @@ -2127,7 +2128,7 @@ process_entries (segT seg, struct line_entry *e)
> >     /* Emit a DW_LNE_end_sequence for the end of the section.  */
> >     frag = last_frag_for_seg (seg);
> >     frag_ofs = get_frag_fix (frag, seg);
> > -  if (frag == last_frag && ! DWARF2_USE_FIXED_ADVANCE_PC)
> > +  if (frag == last_frag && ! DWARF2_USE_FIXED_ADVANCE_PC (last_lab, lab))
> >       out_inc_line_addr (INT_MAX, frag_ofs - last_frag_ofs);
> >     else
> >       {
> > diff --git a/gas/testsuite/gas/elf/dwarf-5-irp.d b/gas/testsuite/gas/elf/dwarf-5-irp.d
> > index a4f01355db3..781b2a32aaa 100644
> > --- a/gas/testsuite/gas/elf/dwarf-5-irp.d
> > +++ b/gas/testsuite/gas/elf/dwarf-5-irp.d
> > @@ -5,8 +5,7 @@
> >   # The bfin target does not allow .subsection with an equated symbol as operand.
> >   # The d30v target emits sufficiently different debug info, apparently also covering padding it inserts.
> >   # The riscv targets do not support the subtraction of symbols.
> > -# The loongarch targets do not support the subtraction of symbols.
> > -#xfail: am33*-* bfin-* cr16-* crx-* d30v-* ft32-* loongarch*-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
> > +#xfail: am33*-* bfin-* cr16-* crx-* d30v-* ft32-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
> >   Raw dump of debug contents .*
> >   #...
> > diff --git a/gas/testsuite/gas/elf/dwarf-5-loc0.d b/gas/testsuite/gas/elf/dwarf-5-loc0.d
> > index 9338271c0eb..9439d103b1f 100644
> > --- a/gas/testsuite/gas/elf/dwarf-5-loc0.d
> > +++ b/gas/testsuite/gas/elf/dwarf-5-loc0.d
> > @@ -3,8 +3,7 @@
> >   #name: DWARF5 .loc 0
> >   # The am33 cr16 crx ft32 mn10 msp430 nds32 and rl78 targets do not evaluate the subtraction of symbols at assembly time.
> >   # The riscv targets do not support the subtraction of symbols.
> > -# The loongarch targets do not support the subtraction of symbols.
> > -#xfail: am3*-* cr16-* crx-* ft32*-* loongarch*-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
> > +#xfail: am3*-* cr16-* crx-* ft32*-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
> >   Contents of the \.debug_line section:
> > diff --git a/gas/testsuite/gas/elf/dwarf-5-macro-include.d b/gas/testsuite/gas/elf/dwarf-5-macro-include.d
> > index c39425aa8c9..32ea6386992 100644
> > --- a/gas/testsuite/gas/elf/dwarf-5-macro-include.d
> > +++ b/gas/testsuite/gas/elf/dwarf-5-macro-include.d
> > @@ -4,7 +4,7 @@
> >   # The am33 cr16 crx ft32 mn10* msp430 nds32* and rl78 targets do not evaluate the subtraction of symbols at assembly time.
> >   # The d30v target emits sufficiently different debug info, apparently also covering padding it inserts.
> >   # The riscv targets do not support the subtraction of symbols.
> > -#xfail: am33*-* cr16-* crx-* d30v-* ft32-* loongarch*-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
> > +#xfail: am33*-* cr16-* crx-* d30v-* ft32-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
> >   Raw dump of debug contents .*
> >   #...
> > diff --git a/gas/testsuite/gas/elf/dwarf-5-macro.d b/gas/testsuite/gas/elf/dwarf-5-macro.d
> > index b2613bd1c16..794e17a575e 100644
> > --- a/gas/testsuite/gas/elf/dwarf-5-macro.d
> > +++ b/gas/testsuite/gas/elf/dwarf-5-macro.d
> > @@ -4,7 +4,7 @@
> >   # The am33 cr16 crx ft32 mn10* msp430 nds32* and rl78 targets do not evaluate the subtraction of symbols at assembly time.
> >   # The d30v target emits sufficiently different debug info, apparently also covering padding it inserts.
> >   # The riscv targets do not support the subtraction of symbols.
> > -#xfail: am33*-* cr16-* crx-* d30v-* ft32-* loongarch*-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
> > +#xfail: am33*-* cr16-* crx-* d30v-* ft32-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
> >   Raw dump of debug contents .*
> >   #...
> > diff --git a/gas/testsuite/gas/elf/dwarf2-11.d b/gas/testsuite/gas/elf/dwarf2-11.d
> > index 44f5cd18ec6..2c30e55c695 100644
> > --- a/gas/testsuite/gas/elf/dwarf2-11.d
> > +++ b/gas/testsuite/gas/elf/dwarf2-11.d
> > @@ -3,8 +3,7 @@
> >   #name: DWARF2 11
> >   # The am33 cr16 crx ft32 mn10 msp430 nds32 and rl78 targets do not evaluate the subtraction of symbols at assembly time.
> >   # The riscv targets do not support the subtraction of symbols.
> > -# The loongarch targets do not support the subtraction of symbols.
> > -#xfail: am3*-* cr16-* crx-* ft32*-* loongarch*-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
> > +#xfail: am3*-* cr16-* crx-* ft32*-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
> >   Contents of the \.debug_line section:
> > diff --git a/gas/testsuite/gas/elf/dwarf2-15.d b/gas/testsuite/gas/elf/dwarf2-15.d
> > index 3ec9f2785a7..939c61598cb 100644
> > --- a/gas/testsuite/gas/elf/dwarf2-15.d
> > +++ b/gas/testsuite/gas/elf/dwarf2-15.d
> > @@ -3,8 +3,7 @@
> >   #name: DWARF2 15
> >   # The am33 cr16 crx ft32 mn10 msp430 nds32 and rl78 targets do not evaluate the subtraction of symbols at assembly time.
> >   # The riscv targets do not support the subtraction of symbols.
> > -# The loongarch targets do not support the subtraction of symbols.
> > -#xfail: am3*-* cr16-* crx-* ft32*-* loongarch*-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
> > +#xfail: am3*-* cr16-* crx-* ft32*-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
> >   Hex dump of section '\.rodata':
> >     0x00000000 01 *.*
> > diff --git a/gas/testsuite/gas/elf/dwarf2-16.d b/gas/testsuite/gas/elf/dwarf2-16.d
> > index 32b57763137..8e35d493619 100644
> > --- a/gas/testsuite/gas/elf/dwarf2-16.d
> > +++ b/gas/testsuite/gas/elf/dwarf2-16.d
> > @@ -4,8 +4,7 @@
> >   # The am33 cr16 crx ft32 mn10 msp430 nds32 and rl78 targets do not evaluate the subtraction of symbols at assembly time.
> >   # The mep target tries to relay code sections which breaks symbolic view computations.
> >   # The riscv targets do not support the subtraction of symbols.
> > -# The loongarch targets do not support the subtraction of symbols.
> > -#xfail: am3*-* cr16-* crx-* ft32*-* mep-* loongarch*-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
> > +#xfail: am3*-* cr16-* crx-* ft32*-* mep-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
> >   Hex dump of section '\.rodata':
> >     0x00000000 01 *.*
> > diff --git a/gas/testsuite/gas/elf/dwarf2-17.d b/gas/testsuite/gas/elf/dwarf2-17.d
> > index 4c2f2e3999e..881477cf95b 100644
> > --- a/gas/testsuite/gas/elf/dwarf2-17.d
> > +++ b/gas/testsuite/gas/elf/dwarf2-17.d
> > @@ -4,8 +4,7 @@
> >   # The am33 cr16 crx ft32 mn10 msp430 nds32 and rl78 targets do not evaluate the subtraction of symbols at assembly time.
> >   # The mep target tries to relay code sections which breaks symbolic view computations.
> >   # The riscv targets do not support the subtraction of symbols.
> > -# The loongarch targets do not support the subtraction of symbols.
> > -#xfail: am3*-* cr16-* crx-* ft32*-* loongarch*-* mep-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
> > +#xfail: am3*-* cr16-* crx-* ft32*-* mep-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
> >   Hex dump of section '\.rodata':
> >     0x00000000 00 *.*
> > diff --git a/gas/testsuite/gas/elf/dwarf2-18.d b/gas/testsuite/gas/elf/dwarf2-18.d
> > index 18157c634a5..fbaebaa9019 100644
> > --- a/gas/testsuite/gas/elf/dwarf2-18.d
> > +++ b/gas/testsuite/gas/elf/dwarf2-18.d
> > @@ -3,8 +3,7 @@
> >   #name: DWARF2 18
> >   # The am33 cr16 crx ft32 mn10 msp430 nds32 and rl78 targets do not evaluate the subtraction of symbols at assembly time.
> >   # The riscv targets do not support the subtraction of symbols.
> > -# The loongarch targets do not support the subtraction of symbols.
> > -#xfail: am3*-* cr16-* crx-* ft32*-* loongarch*-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
> > +#xfail: am3*-* cr16-* crx-* ft32*-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
> >   Hex dump of section '\.rodata':
> >     0x00000000 0100 *.*
> > diff --git a/gas/testsuite/gas/elf/dwarf2-19.d b/gas/testsuite/gas/elf/dwarf2-19.d
> > index 133294affe7..55d0caf4cb1 100644
> > --- a/gas/testsuite/gas/elf/dwarf2-19.d
> > +++ b/gas/testsuite/gas/elf/dwarf2-19.d
> > @@ -4,8 +4,7 @@
> >   # The am33 cr16 crx ft32 mn10 msp430 nds32 and rl78 targets do not evaluate the subtraction of symbols at assembly time.
> >   # The mep targets turns some view computations into complex relocations.
> >   # The riscv targets do not support the subtraction of symbols.
> > -# The loongarch targets do not support the subtraction of symbols.
> > -#xfail: am3*-* cr16-* crx-* ft32*-* mep-* loongarch*-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
> > +#xfail: am3*-* cr16-* crx-* ft32*-* mep-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
> >   Hex dump of section '\.rodata':
> >     0x00000000 01000102 *.*
> > diff --git a/gas/testsuite/gas/elf/dwarf2-5.d b/gas/testsuite/gas/elf/dwarf2-5.d
> > index 1dd65732c50..bf1eeb5bbfd 100644
> > --- a/gas/testsuite/gas/elf/dwarf2-5.d
> > +++ b/gas/testsuite/gas/elf/dwarf2-5.d
> > @@ -4,8 +4,7 @@
> >   # The am33 cr16 crx ft32 mn10 msp430 nds32 and rl78 targets do not evaluate the subtraction of symbols at assembly time.
> >   # The mep target tries to relay code sections which breaks symbolic view computations.
> >   # The riscv targets do not support the subtraction of symbols.
> > -# The loongarch targets do not support the subtraction of symbols.
> > -#xfail: am3*-* cr16-* crx-* ft32*-* loongarch*-* mep-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
> > +#xfail: am3*-* cr16-* crx-* ft32*-* mep-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
> >   Hex dump of section '\.rodata':
> >     0x00000000 01010201 010203 *.*
> > diff --git a/gas/testsuite/gas/lns/lns.exp b/gas/testsuite/gas/lns/lns.exp
> > index 7a92c54a260..58c2235b628 100644
> > --- a/gas/testsuite/gas/lns/lns.exp
> > +++ b/gas/testsuite/gas/lns/lns.exp
> > @@ -31,7 +31,6 @@ if { ![istarget s390*-*-*] } {
> >   	 || [istarget cr16-*-*]
> >   	 || [istarget crx-*-*]
> >   	 || [istarget ft32*-*]
> > -	 || [istarget loongarch*-*-*]
> >   	 || [istarget mn10*-*-*]
> >   	 || [istarget msp430-*-*]
> >   	 || [istarget nds32*-*-*]
> > diff --git a/gas/testsuite/gas/loongarch/relax-debug-line-opcode-norelax.d b/gas/testsuite/gas/loongarch/relax-debug-line-opcode-norelax.d
> > new file mode 100644
> > index 00000000000..c8be41feb82
> > --- /dev/null
> > +++ b/gas/testsuite/gas/loongarch/relax-debug-line-opcode-norelax.d
> > @@ -0,0 +1,10 @@
> > +#source: relax-debug-line-opcode.s
> > +#as: -mno-relax
> > +#readelf: -W -wl
> > +
> > +#...
> > +.*  Special opcode 62: advance Address by 4 to 0x4 and Line by 1 to 11
> > +.*  Special opcode 118: advance Address by 8 to 0xc and Line by 1 to 12
> > +.*  Special opcode 62: advance Address by 4 to 0x10 and Line by 1 to 13
> > +.*  Special opcode 118: advance Address by 8 to 0x18 and Line by 1 to 14
> > +#pass
> > diff --git a/gas/testsuite/gas/loongarch/relax-debug-line-opcode.d b/gas/testsuite/gas/loongarch/relax-debug-line-opcode.d
> > new file mode 100644
> > index 00000000000..9c707d97747
> > --- /dev/null
> > +++ b/gas/testsuite/gas/loongarch/relax-debug-line-opcode.d
> > @@ -0,0 +1,25 @@
> > +#source: relax-debug-line-opcode.s
> > +#as: -mrelax
> > +#readelf: -r -wl -W
> > +
> > +#...
> > +Relocation section '\.rela\.debug_line' at offset .* contains 7 entries:
> > +#...
> > +.*R_LARCH_ADD16[ 	]+[0-9]+.*
> > +.*R_LARCH_SUB16[ 	]+[0-9]+.*
> > +.*R_LARCH_ADD16[ 	]+[0-9]+.*
> > +.*R_LARCH_SUB16[ 	]+[0-9]+.*
> > +#...
> > +Raw dump of debug contents of section \.debug_line:
> > +#...
> > +.*  Special opcode 62: advance Address by 4 to 0x4 and Line by 1 to 11
> > +.*  Advance Line by 1 to 12
> > +.*  Advance PC by fixed size amount [0-9]+ to 0x[0-9a-f]+
> > +.*  Copy .*
> > +.*  Special opcode 62: advance Address by 4 to 0x10 and Line by 1 to 13
> > +.*  Advance Line by 1 to 14
> > +.*  Advance PC by fixed size amount [0-9]+ to 0x[0-9a-f]+
> > +.*  Copy .*
> > +.*  Advance PC by [0-9]+ to 0x[0-9a-f]+
> > +.*  Extended opcode 1: End of Sequence
> > +#pass
> > diff --git a/gas/testsuite/gas/loongarch/relax-debug-line-opcode.s b/gas/testsuite/gas/loongarch/relax-debug-line-opcode.s
> > new file mode 100644
> > index 00000000000..276a823373c
> > --- /dev/null
> > +++ b/gas/testsuite/gas/loongarch/relax-debug-line-opcode.s
> > @@ -0,0 +1,15 @@
> > +  # Test DWARF line encoding around linker-relaxable instructions.
> > +  .file 0 "test"
> > +  .text
> > +  .loc 0 10 0
> > +  nop		# special opcode
> > +  .loc 0 11 0
> > +  call36 func	# -mrelax: DW_LNS_fixed_advance_pc; -mno-relax: special opcode.
> > +  .loc 0 12 0
> > +  nop		# special opcode
> > +  .loc 0 13 0
> > +  call36 func	# -mrelax: DW_LNS_fixed_advance_pc; -mno-relax: special opcode.
> > +  .loc 0 14 0
> > +  nop		# Advance PC
> > +
> > +.section .debug_line, "", @progbits
  
mengqinggang Aug. 31, 2026, 8:23 a.m. UTC | #3
Hi Alan,

Thanks! Just to confirm, can this patch be merged?


在 2026/8/26 21:05, Alan Modra 写道:
> On Wed, Aug 26, 2026 at 02:38:53PM +0800, mengqinggang wrote:
>> Gentle ping.
> OK.
>
>> 在 2026/8/19 11:41, mengqinggang 写道:
>>> If DWARF2_USE_FIXED_ADVANCE_PC is nonzero, use the DW_LNS_fixed_advance_pc
>>> opcode; otherwise, use special opcodes.
>>>
>>> Add FROM symbol and TO symbol parameters for finer-grained control.
>>>
>>> Use special opcodes when no linker-relaxable instructions between two symbols;
>>> otherwise, use DW_LNS_fixed_advance_pc opcodes.
>>>
>>> Add a new macro DWARF2_USE_FIXED_ADVANCE_PC_FRAG to avoid unnecessary calls
>>> to symbol_get_value_expression on other targets.
>>> ---
>>> Changes in V1 (based on Alan's feedback):
>>> - Delete the first DWARF2_USE_FIXED_ADVANCE_PC and always call
>>>     resolve_symbol_value with finalize_syms zero in dwarf2dbg_convert_frag.
>>> - Add a new macro DWARF2_USE_FIXED_ADVANCE_PC_FRAG to avoid unnecessary
>>>     calls to symbol_get_value_expression on other targets.
>>>
>>>    gas/config/tc-h8300.h                         |  2 +-
>>>    gas/config/tc-loongarch.c                     | 25 ++++++++++
>>>    gas/config/tc-loongarch.h                     | 10 +++-
>>>    gas/config/tc-msp430.h                        |  2 +-
>>>    gas/config/tc-nds32.h                         |  2 +-
>>>    gas/config/tc-riscv.h                         |  2 +-
>>>    gas/config/tc-rl78.h                          |  2 +-
>>>    gas/config/tc-xtensa.h                        |  2 +-
>>>    gas/dwarf2dbg.c                               | 49 ++++++++++---------
>>>    gas/testsuite/gas/elf/dwarf-5-irp.d           |  3 +-
>>>    gas/testsuite/gas/elf/dwarf-5-loc0.d          |  3 +-
>>>    gas/testsuite/gas/elf/dwarf-5-macro-include.d |  2 +-
>>>    gas/testsuite/gas/elf/dwarf-5-macro.d         |  2 +-
>>>    gas/testsuite/gas/elf/dwarf2-11.d             |  3 +-
>>>    gas/testsuite/gas/elf/dwarf2-15.d             |  3 +-
>>>    gas/testsuite/gas/elf/dwarf2-16.d             |  3 +-
>>>    gas/testsuite/gas/elf/dwarf2-17.d             |  3 +-
>>>    gas/testsuite/gas/elf/dwarf2-18.d             |  3 +-
>>>    gas/testsuite/gas/elf/dwarf2-19.d             |  3 +-
>>>    gas/testsuite/gas/elf/dwarf2-5.d              |  3 +-
>>>    gas/testsuite/gas/lns/lns.exp                 |  1 -
>>>    .../relax-debug-line-opcode-norelax.d         | 10 ++++
>>>    .../gas/loongarch/relax-debug-line-opcode.d   | 25 ++++++++++
>>>    .../gas/loongarch/relax-debug-line-opcode.s   | 15 ++++++
>>>    24 files changed, 125 insertions(+), 53 deletions(-)
>>>    create mode 100644 gas/testsuite/gas/loongarch/relax-debug-line-opcode-norelax.d
>>>    create mode 100644 gas/testsuite/gas/loongarch/relax-debug-line-opcode.d
>>>    create mode 100644 gas/testsuite/gas/loongarch/relax-debug-line-opcode.s
>>>
>>> diff --git a/gas/config/tc-h8300.h b/gas/config/tc-h8300.h
>>> index c4689d37b12..66664553a24 100644
>>> --- a/gas/config/tc-h8300.h
>>> +++ b/gas/config/tc-h8300.h
>>> @@ -46,7 +46,7 @@ struct internal_reloc;
>>>    /* Minimum instruction is of 16 bits.  */
>>>    #define DWARF2_LINE_MIN_INSN_LENGTH 2
>>> -#define DWARF2_USE_FIXED_ADVANCE_PC 0
>>> +#define DWARF2_USE_FIXED_ADVANCE_PC(FROM, TO) 0
>>>    /* Provide mappings from the original H8 COFF relocation names to
>>>       their corresponding BFD relocation names.  */
>>> diff --git a/gas/config/tc-loongarch.c b/gas/config/tc-loongarch.c
>>> index bd7d8dabb7a..e02881761fe 100644
>>> --- a/gas/config/tc-loongarch.c
>>> +++ b/gas/config/tc-loongarch.c
>>> @@ -1644,6 +1644,31 @@ _loongarch_force_relocation_sub_same (segT sec,
>>>      return true;
>>>    }
>>> +/* Use DW_LNS_fixed_advance_pc with relocations if there are linker-relaxable
>>> +   instructions between from and to symbols. Otherwise, use special opcodes
>>> +   without relocations.  */
>>> +bool
>>> +loongarch_fixed_advance_pc (symbolS *from, symbolS *to)
>>> +{
>>> +  segT fromsec = S_GET_SEGMENT (from);
>>> +  segT tosec = S_GET_SEGMENT (to);
>>> +  if (fromsec != tosec)
>>> +    return false;
>>> +  fragS *fromfrag = symbol_get_frag (from);
>>> +  fragS *tofrag = symbol_get_frag (to);
>>> +  return _loongarch_force_relocation_sub_same (fromsec, fromfrag, tofrag);
>>> +}
>>> +
>>> +/* Similar to loongarch_fixed_advance_pc, used for frag.  */
>>> +bool
>>> +loongarch_fixed_advance_pc_frag (fragS *frag)
>>> +{
>>> +  expressionS *exp = symbol_get_value_expression (frag->fr_symbol);
>>> +
>>> +  if (exp->X_op != O_subtract)
>>> +    return false;
>>> +  return loongarch_fixed_advance_pc (exp->X_op_symbol, exp->X_add_symbol);
>>> +}
>>>    /* Postpone text-section label subtraction calculation until linking,
>>>       since linker relaxations might change the deltas.  */
>>> diff --git a/gas/config/tc-loongarch.h b/gas/config/tc-loongarch.h
>>> index 146844e772e..1f11f9cef46 100644
>>> --- a/gas/config/tc-loongarch.h
>>> +++ b/gas/config/tc-loongarch.h
>>> @@ -101,8 +101,14 @@ extern bool loongarch_force_relocation_sub_same(struct fix *, asection *);
>>>    #define MD_APPLY_SYM_VALUE(FIX) 0
>>>    #define TARGET_USE_CFIPOP 1
>>> -/* Adjust debug_line after relaxation.  */
>>> -#define DWARF2_USE_FIXED_ADVANCE_PC   1
>>> +
>>> +extern bool loongarch_fixed_advance_pc (symbolS *, symbolS *);
>>> +#define DWARF2_USE_FIXED_ADVANCE_PC(FROM, TO) \
>>> +  loongarch_fixed_advance_pc (FROM, TO)
>>> +
>>> +extern bool loongarch_fixed_advance_pc_frag (fragS *);
>>> +#define DWARF2_USE_FIXED_ADVANCE_PC_FRAG(FRAG) \
>>> +  loongarch_fixed_advance_pc_frag (FRAG)
>>>    /* FDE Data Alignment Factor.
>>>       FDE Code Alignment Factor (DWARF2_LINE_MIN_INSN_LENGTH) should be 1
>>> diff --git a/gas/config/tc-msp430.h b/gas/config/tc-msp430.h
>>> index fe202abc713..f9b6c1e588c 100644
>>> --- a/gas/config/tc-msp430.h
>>> +++ b/gas/config/tc-msp430.h
>>> @@ -168,7 +168,7 @@ extern bool msp430_allow_local_subtract (expressionS *, expressionS *, segT);
>>>       so don't report errors at this point.  */
>>>    #define TC_VALIDATE_FIX_SUB(FIX, SEG) 1
>>> -#define DWARF2_USE_FIXED_ADVANCE_PC 1
>>> +#define DWARF2_USE_FIXED_ADVANCE_PC(FROM, TO) 1
>>>    #define TC_LINKRELAX_FIXUP(seg) ((seg->flags & SEC_CODE) || (seg->flags & SEC_DEBUGGING))
>>> diff --git a/gas/config/tc-nds32.h b/gas/config/tc-nds32.h
>>> index 432d46d9fb1..49a1bead095 100644
>>> --- a/gas/config/tc-nds32.h
>>> +++ b/gas/config/tc-nds32.h
>>> @@ -77,7 +77,7 @@ extern bool nds32_allow_local_subtract (expressionS *, expressionS *, segT);
>>>    #define md_allow_local_subtract(lhs,rhs,sect)	nds32_allow_local_subtract (lhs, rhs, sect)
>>>    /* dwarf2dbg.c.  */
>>> -#define DWARF2_USE_FIXED_ADVANCE_PC		1
>>> +#define DWARF2_USE_FIXED_ADVANCE_PC(FROM, TO)	1
>>>    /* write.c.  */
>>>    extern long nds32_pcrel_from_section (struct fix *, segT);
>>> diff --git a/gas/config/tc-riscv.h b/gas/config/tc-riscv.h
>>> index d695db83477..7518d2a70f7 100644
>>> --- a/gas/config/tc-riscv.h
>>> +++ b/gas/config/tc-riscv.h
>>> @@ -135,7 +135,7 @@ extern void riscv_elf_section_change_hook (void);
>>>    extern void riscv_elf_final_processing (void);
>>>    /* Adjust debug_line after relaxation.  */
>>> -#define DWARF2_USE_FIXED_ADVANCE_PC 1
>>> +#define DWARF2_USE_FIXED_ADVANCE_PC(FROM, TO) 1
>>>    #define md_parse_name(name, exp, mode, c) \
>>>      riscv_parse_name (name, exp, mode)
>>> diff --git a/gas/config/tc-rl78.h b/gas/config/tc-rl78.h
>>> index 9761d509aa1..fb54a2e8da7 100644
>>> --- a/gas/config/tc-rl78.h
>>> +++ b/gas/config/tc-rl78.h
>>> @@ -94,6 +94,6 @@ extern void rl78_elf_final_processing (void);
>>>       || ((SEC)->flags & SEC_DEBUGGING) != 0	\
>>>       || TC_FORCE_RELOCATION (FIX))
>>> -#define DWARF2_USE_FIXED_ADVANCE_PC 1
>>> +#define DWARF2_USE_FIXED_ADVANCE_PC(FROM, TO) 1
>>>    #define TC_FORCE_RELOCATION(FIX) (linkrelax)
>>> diff --git a/gas/config/tc-xtensa.h b/gas/config/tc-xtensa.h
>>> index 64d735144d7..d6ddac738fe 100644
>>> --- a/gas/config/tc-xtensa.h
>>> +++ b/gas/config/tc-xtensa.h
>>> @@ -419,7 +419,7 @@ extern void xtensa_init (int, char **);
>>>    #define SUB_SEGMENT_ALIGN(SEG, FRCHAIN) 0
>>>    /* Use line number format that is amenable to linker relaxation.  */
>>> -#define DWARF2_USE_FIXED_ADVANCE_PC (linkrelax != 0)
>>> +#define DWARF2_USE_FIXED_ADVANCE_PC(FROM, TO) (linkrelax != 0)
>>>    /* Resource reservation info functions.  */
>>> diff --git a/gas/dwarf2dbg.c b/gas/dwarf2dbg.c
>>> index a1ceab4e428..c899eecd26b 100644
>>> --- a/gas/dwarf2dbg.c
>>> +++ b/gas/dwarf2dbg.c
>>> @@ -112,7 +112,13 @@
>>>       opcodes and variable-length operands cannot be used.  If this macro is
>>>       nonzero, use the DW_LNS_fixed_advance_pc opcode instead.  */
>>>    #ifndef DWARF2_USE_FIXED_ADVANCE_PC
>>> -# define DWARF2_USE_FIXED_ADVANCE_PC	linkrelax
>>> +# define DWARF2_USE_FIXED_ADVANCE_PC(FROM, TO)	linkrelax
>>> +#endif
>>> +
>>> +/* Similar to DWARF2_USE_FIXED_ADVANCE_PC, used for frag.  */
>>> +#ifndef DWARF2_USE_FIXED_ADVANCE_PC_FRAG
>>> +# define DWARF2_USE_FIXED_ADVANCE_PC_FRAG(FRAG) \
>>> +	 DWARF2_USE_FIXED_ADVANCE_PC (0, 0)
>>>    #endif
>>>    /* First special line opcode - leave room for the standard opcodes.
>>> @@ -1898,7 +1904,7 @@ relax_inc_line_addr (int line_delta, symbolS *to_sym, symbolS *from_sym)
>>>      /* The maximum size of the frag is the line delta with a maximum
>>>         sized address delta.  */
>>> -  if (DWARF2_USE_FIXED_ADVANCE_PC)
>>> +  if (DWARF2_USE_FIXED_ADVANCE_PC (from_sym, to_sym))
>>>        max_chars = size_fixed_inc_line_addr (line_delta,
>>>    					  -DWARF2_LINE_MIN_INSN_LENGTH);
>>>      else
>>> @@ -1919,7 +1925,7 @@ dwarf2dbg_estimate_size_before_relax (fragS *frag)
>>>      int size;
>>>      addr_delta = resolve_symbol_value (frag->fr_symbol);
>>> -  if (DWARF2_USE_FIXED_ADVANCE_PC)
>>> +  if (DWARF2_USE_FIXED_ADVANCE_PC_FRAG (frag))
>>>        size = size_fixed_inc_line_addr (frag->fr_offset, addr_delta);
>>>      else
>>>        size = size_inc_line_addr (frag->fr_offset, addr_delta);
>>> @@ -1953,31 +1959,25 @@ dwarf2dbg_convert_frag (fragS *frag)
>>>    {
>>>      offsetT addr_diff;
>>> -  if (DWARF2_USE_FIXED_ADVANCE_PC)
>>> -    {
>>> -      /* If linker relaxation is enabled then the distance between the two
>>> -	 symbols in the frag->fr_symbol expression might change.  Hence we
>>> -	 cannot rely upon the value computed by resolve_symbol_value.
>>> -	 Instead we leave the expression unfinalized and allow
>>> -	 emit_fixed_inc_line_addr to create a fixup (which later becomes a
>>> -	 relocation) that will allow the linker to correctly compute the
>>> -	 actual address difference.  We have to use a fixed line advance for
>>> -	 this as we cannot (easily) relocate leb128 encoded values.  */
>>> -      int saved_finalize_syms = finalize_syms;
>>> -
>>> -      finalize_syms = 0;
>>> -      addr_diff = resolve_symbol_value (frag->fr_symbol);
>>> -      finalize_syms = saved_finalize_syms;
>>> -    }
>>> -  else
>>> -    addr_diff = resolve_symbol_value (frag->fr_symbol);
>>> +  /* If linker relaxation is enabled then the distance between the two
>>> +     symbols in the frag->fr_symbol expression might change.  Hence we
>>> +     cannot rely upon the value computed by resolve_symbol_value.
>>> +     Instead we leave the expression unfinalized and allow
>>> +     emit_fixed_inc_line_addr to create a fixup (which later becomes a
>>> +     relocation) that will allow the linker to correctly compute the
>>> +     actual address difference.  We have to use a fixed line advance for
>>> +     this as we cannot (easily) relocate leb128 encoded values.  */
>>> +  int saved_finalize_syms = finalize_syms;
>>> +  finalize_syms = 0;
>>> +  addr_diff = resolve_symbol_value (frag->fr_symbol);
>>> +  finalize_syms = saved_finalize_syms;
>>>      /* fr_var carries the max_chars that we created the fragment with.
>>>         fr_subtype carries the current expected length.  We must, of
>>>         course, have allocated enough memory earlier.  */
>>>      gas_assert (frag->fr_var >= (int) frag->fr_subtype);
>>> -  if (DWARF2_USE_FIXED_ADVANCE_PC)
>>> +  if (DWARF2_USE_FIXED_ADVANCE_PC_FRAG (frag))
>>>        emit_fixed_inc_line_addr (frag->fr_offset, addr_diff, frag,
>>>    			      frag->fr_literal + frag->fr_fix,
>>>    			      frag->fr_subtype);
>>> @@ -2110,7 +2110,8 @@ process_entries (segT seg, struct line_entry *e)
>>>    	  out_set_addr (lab);
>>>    	  out_inc_line_addr (line_delta, 0);
>>>    	}
>>> -      else if (frag == last_frag && ! DWARF2_USE_FIXED_ADVANCE_PC)
>>> +      else if (frag == last_frag
>>> +	       && ! DWARF2_USE_FIXED_ADVANCE_PC (last_lab, lab))
>>>    	out_inc_line_addr (line_delta, frag_ofs - last_frag_ofs);
>>>          else
>>>    	relax_inc_line_addr (line_delta, lab, last_lab);
>>> @@ -2127,7 +2128,7 @@ process_entries (segT seg, struct line_entry *e)
>>>      /* Emit a DW_LNE_end_sequence for the end of the section.  */
>>>      frag = last_frag_for_seg (seg);
>>>      frag_ofs = get_frag_fix (frag, seg);
>>> -  if (frag == last_frag && ! DWARF2_USE_FIXED_ADVANCE_PC)
>>> +  if (frag == last_frag && ! DWARF2_USE_FIXED_ADVANCE_PC (last_lab, lab))
>>>        out_inc_line_addr (INT_MAX, frag_ofs - last_frag_ofs);
>>>      else
>>>        {
>>> diff --git a/gas/testsuite/gas/elf/dwarf-5-irp.d b/gas/testsuite/gas/elf/dwarf-5-irp.d
>>> index a4f01355db3..781b2a32aaa 100644
>>> --- a/gas/testsuite/gas/elf/dwarf-5-irp.d
>>> +++ b/gas/testsuite/gas/elf/dwarf-5-irp.d
>>> @@ -5,8 +5,7 @@
>>>    # The bfin target does not allow .subsection with an equated symbol as operand.
>>>    # The d30v target emits sufficiently different debug info, apparently also covering padding it inserts.
>>>    # The riscv targets do not support the subtraction of symbols.
>>> -# The loongarch targets do not support the subtraction of symbols.
>>> -#xfail: am33*-* bfin-* cr16-* crx-* d30v-* ft32-* loongarch*-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
>>> +#xfail: am33*-* bfin-* cr16-* crx-* d30v-* ft32-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
>>>    Raw dump of debug contents .*
>>>    #...
>>> diff --git a/gas/testsuite/gas/elf/dwarf-5-loc0.d b/gas/testsuite/gas/elf/dwarf-5-loc0.d
>>> index 9338271c0eb..9439d103b1f 100644
>>> --- a/gas/testsuite/gas/elf/dwarf-5-loc0.d
>>> +++ b/gas/testsuite/gas/elf/dwarf-5-loc0.d
>>> @@ -3,8 +3,7 @@
>>>    #name: DWARF5 .loc 0
>>>    # The am33 cr16 crx ft32 mn10 msp430 nds32 and rl78 targets do not evaluate the subtraction of symbols at assembly time.
>>>    # The riscv targets do not support the subtraction of symbols.
>>> -# The loongarch targets do not support the subtraction of symbols.
>>> -#xfail: am3*-* cr16-* crx-* ft32*-* loongarch*-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
>>> +#xfail: am3*-* cr16-* crx-* ft32*-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
>>>    Contents of the \.debug_line section:
>>> diff --git a/gas/testsuite/gas/elf/dwarf-5-macro-include.d b/gas/testsuite/gas/elf/dwarf-5-macro-include.d
>>> index c39425aa8c9..32ea6386992 100644
>>> --- a/gas/testsuite/gas/elf/dwarf-5-macro-include.d
>>> +++ b/gas/testsuite/gas/elf/dwarf-5-macro-include.d
>>> @@ -4,7 +4,7 @@
>>>    # The am33 cr16 crx ft32 mn10* msp430 nds32* and rl78 targets do not evaluate the subtraction of symbols at assembly time.
>>>    # The d30v target emits sufficiently different debug info, apparently also covering padding it inserts.
>>>    # The riscv targets do not support the subtraction of symbols.
>>> -#xfail: am33*-* cr16-* crx-* d30v-* ft32-* loongarch*-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
>>> +#xfail: am33*-* cr16-* crx-* d30v-* ft32-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
>>>    Raw dump of debug contents .*
>>>    #...
>>> diff --git a/gas/testsuite/gas/elf/dwarf-5-macro.d b/gas/testsuite/gas/elf/dwarf-5-macro.d
>>> index b2613bd1c16..794e17a575e 100644
>>> --- a/gas/testsuite/gas/elf/dwarf-5-macro.d
>>> +++ b/gas/testsuite/gas/elf/dwarf-5-macro.d
>>> @@ -4,7 +4,7 @@
>>>    # The am33 cr16 crx ft32 mn10* msp430 nds32* and rl78 targets do not evaluate the subtraction of symbols at assembly time.
>>>    # The d30v target emits sufficiently different debug info, apparently also covering padding it inserts.
>>>    # The riscv targets do not support the subtraction of symbols.
>>> -#xfail: am33*-* cr16-* crx-* d30v-* ft32-* loongarch*-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
>>> +#xfail: am33*-* cr16-* crx-* d30v-* ft32-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
>>>    Raw dump of debug contents .*
>>>    #...
>>> diff --git a/gas/testsuite/gas/elf/dwarf2-11.d b/gas/testsuite/gas/elf/dwarf2-11.d
>>> index 44f5cd18ec6..2c30e55c695 100644
>>> --- a/gas/testsuite/gas/elf/dwarf2-11.d
>>> +++ b/gas/testsuite/gas/elf/dwarf2-11.d
>>> @@ -3,8 +3,7 @@
>>>    #name: DWARF2 11
>>>    # The am33 cr16 crx ft32 mn10 msp430 nds32 and rl78 targets do not evaluate the subtraction of symbols at assembly time.
>>>    # The riscv targets do not support the subtraction of symbols.
>>> -# The loongarch targets do not support the subtraction of symbols.
>>> -#xfail: am3*-* cr16-* crx-* ft32*-* loongarch*-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
>>> +#xfail: am3*-* cr16-* crx-* ft32*-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
>>>    Contents of the \.debug_line section:
>>> diff --git a/gas/testsuite/gas/elf/dwarf2-15.d b/gas/testsuite/gas/elf/dwarf2-15.d
>>> index 3ec9f2785a7..939c61598cb 100644
>>> --- a/gas/testsuite/gas/elf/dwarf2-15.d
>>> +++ b/gas/testsuite/gas/elf/dwarf2-15.d
>>> @@ -3,8 +3,7 @@
>>>    #name: DWARF2 15
>>>    # The am33 cr16 crx ft32 mn10 msp430 nds32 and rl78 targets do not evaluate the subtraction of symbols at assembly time.
>>>    # The riscv targets do not support the subtraction of symbols.
>>> -# The loongarch targets do not support the subtraction of symbols.
>>> -#xfail: am3*-* cr16-* crx-* ft32*-* loongarch*-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
>>> +#xfail: am3*-* cr16-* crx-* ft32*-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
>>>    Hex dump of section '\.rodata':
>>>      0x00000000 01 *.*
>>> diff --git a/gas/testsuite/gas/elf/dwarf2-16.d b/gas/testsuite/gas/elf/dwarf2-16.d
>>> index 32b57763137..8e35d493619 100644
>>> --- a/gas/testsuite/gas/elf/dwarf2-16.d
>>> +++ b/gas/testsuite/gas/elf/dwarf2-16.d
>>> @@ -4,8 +4,7 @@
>>>    # The am33 cr16 crx ft32 mn10 msp430 nds32 and rl78 targets do not evaluate the subtraction of symbols at assembly time.
>>>    # The mep target tries to relay code sections which breaks symbolic view computations.
>>>    # The riscv targets do not support the subtraction of symbols.
>>> -# The loongarch targets do not support the subtraction of symbols.
>>> -#xfail: am3*-* cr16-* crx-* ft32*-* mep-* loongarch*-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
>>> +#xfail: am3*-* cr16-* crx-* ft32*-* mep-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
>>>    Hex dump of section '\.rodata':
>>>      0x00000000 01 *.*
>>> diff --git a/gas/testsuite/gas/elf/dwarf2-17.d b/gas/testsuite/gas/elf/dwarf2-17.d
>>> index 4c2f2e3999e..881477cf95b 100644
>>> --- a/gas/testsuite/gas/elf/dwarf2-17.d
>>> +++ b/gas/testsuite/gas/elf/dwarf2-17.d
>>> @@ -4,8 +4,7 @@
>>>    # The am33 cr16 crx ft32 mn10 msp430 nds32 and rl78 targets do not evaluate the subtraction of symbols at assembly time.
>>>    # The mep target tries to relay code sections which breaks symbolic view computations.
>>>    # The riscv targets do not support the subtraction of symbols.
>>> -# The loongarch targets do not support the subtraction of symbols.
>>> -#xfail: am3*-* cr16-* crx-* ft32*-* loongarch*-* mep-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
>>> +#xfail: am3*-* cr16-* crx-* ft32*-* mep-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
>>>    Hex dump of section '\.rodata':
>>>      0x00000000 00 *.*
>>> diff --git a/gas/testsuite/gas/elf/dwarf2-18.d b/gas/testsuite/gas/elf/dwarf2-18.d
>>> index 18157c634a5..fbaebaa9019 100644
>>> --- a/gas/testsuite/gas/elf/dwarf2-18.d
>>> +++ b/gas/testsuite/gas/elf/dwarf2-18.d
>>> @@ -3,8 +3,7 @@
>>>    #name: DWARF2 18
>>>    # The am33 cr16 crx ft32 mn10 msp430 nds32 and rl78 targets do not evaluate the subtraction of symbols at assembly time.
>>>    # The riscv targets do not support the subtraction of symbols.
>>> -# The loongarch targets do not support the subtraction of symbols.
>>> -#xfail: am3*-* cr16-* crx-* ft32*-* loongarch*-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
>>> +#xfail: am3*-* cr16-* crx-* ft32*-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
>>>    Hex dump of section '\.rodata':
>>>      0x00000000 0100 *.*
>>> diff --git a/gas/testsuite/gas/elf/dwarf2-19.d b/gas/testsuite/gas/elf/dwarf2-19.d
>>> index 133294affe7..55d0caf4cb1 100644
>>> --- a/gas/testsuite/gas/elf/dwarf2-19.d
>>> +++ b/gas/testsuite/gas/elf/dwarf2-19.d
>>> @@ -4,8 +4,7 @@
>>>    # The am33 cr16 crx ft32 mn10 msp430 nds32 and rl78 targets do not evaluate the subtraction of symbols at assembly time.
>>>    # The mep targets turns some view computations into complex relocations.
>>>    # The riscv targets do not support the subtraction of symbols.
>>> -# The loongarch targets do not support the subtraction of symbols.
>>> -#xfail: am3*-* cr16-* crx-* ft32*-* mep-* loongarch*-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
>>> +#xfail: am3*-* cr16-* crx-* ft32*-* mep-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
>>>    Hex dump of section '\.rodata':
>>>      0x00000000 01000102 *.*
>>> diff --git a/gas/testsuite/gas/elf/dwarf2-5.d b/gas/testsuite/gas/elf/dwarf2-5.d
>>> index 1dd65732c50..bf1eeb5bbfd 100644
>>> --- a/gas/testsuite/gas/elf/dwarf2-5.d
>>> +++ b/gas/testsuite/gas/elf/dwarf2-5.d
>>> @@ -4,8 +4,7 @@
>>>    # The am33 cr16 crx ft32 mn10 msp430 nds32 and rl78 targets do not evaluate the subtraction of symbols at assembly time.
>>>    # The mep target tries to relay code sections which breaks symbolic view computations.
>>>    # The riscv targets do not support the subtraction of symbols.
>>> -# The loongarch targets do not support the subtraction of symbols.
>>> -#xfail: am3*-* cr16-* crx-* ft32*-* loongarch*-* mep-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
>>> +#xfail: am3*-* cr16-* crx-* ft32*-* mep-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
>>>    Hex dump of section '\.rodata':
>>>      0x00000000 01010201 010203 *.*
>>> diff --git a/gas/testsuite/gas/lns/lns.exp b/gas/testsuite/gas/lns/lns.exp
>>> index 7a92c54a260..58c2235b628 100644
>>> --- a/gas/testsuite/gas/lns/lns.exp
>>> +++ b/gas/testsuite/gas/lns/lns.exp
>>> @@ -31,7 +31,6 @@ if { ![istarget s390*-*-*] } {
>>>    	 || [istarget cr16-*-*]
>>>    	 || [istarget crx-*-*]
>>>    	 || [istarget ft32*-*]
>>> -	 || [istarget loongarch*-*-*]
>>>    	 || [istarget mn10*-*-*]
>>>    	 || [istarget msp430-*-*]
>>>    	 || [istarget nds32*-*-*]
>>> diff --git a/gas/testsuite/gas/loongarch/relax-debug-line-opcode-norelax.d b/gas/testsuite/gas/loongarch/relax-debug-line-opcode-norelax.d
>>> new file mode 100644
>>> index 00000000000..c8be41feb82
>>> --- /dev/null
>>> +++ b/gas/testsuite/gas/loongarch/relax-debug-line-opcode-norelax.d
>>> @@ -0,0 +1,10 @@
>>> +#source: relax-debug-line-opcode.s
>>> +#as: -mno-relax
>>> +#readelf: -W -wl
>>> +
>>> +#...
>>> +.*  Special opcode 62: advance Address by 4 to 0x4 and Line by 1 to 11
>>> +.*  Special opcode 118: advance Address by 8 to 0xc and Line by 1 to 12
>>> +.*  Special opcode 62: advance Address by 4 to 0x10 and Line by 1 to 13
>>> +.*  Special opcode 118: advance Address by 8 to 0x18 and Line by 1 to 14
>>> +#pass
>>> diff --git a/gas/testsuite/gas/loongarch/relax-debug-line-opcode.d b/gas/testsuite/gas/loongarch/relax-debug-line-opcode.d
>>> new file mode 100644
>>> index 00000000000..9c707d97747
>>> --- /dev/null
>>> +++ b/gas/testsuite/gas/loongarch/relax-debug-line-opcode.d
>>> @@ -0,0 +1,25 @@
>>> +#source: relax-debug-line-opcode.s
>>> +#as: -mrelax
>>> +#readelf: -r -wl -W
>>> +
>>> +#...
>>> +Relocation section '\.rela\.debug_line' at offset .* contains 7 entries:
>>> +#...
>>> +.*R_LARCH_ADD16[ 	]+[0-9]+.*
>>> +.*R_LARCH_SUB16[ 	]+[0-9]+.*
>>> +.*R_LARCH_ADD16[ 	]+[0-9]+.*
>>> +.*R_LARCH_SUB16[ 	]+[0-9]+.*
>>> +#...
>>> +Raw dump of debug contents of section \.debug_line:
>>> +#...
>>> +.*  Special opcode 62: advance Address by 4 to 0x4 and Line by 1 to 11
>>> +.*  Advance Line by 1 to 12
>>> +.*  Advance PC by fixed size amount [0-9]+ to 0x[0-9a-f]+
>>> +.*  Copy .*
>>> +.*  Special opcode 62: advance Address by 4 to 0x10 and Line by 1 to 13
>>> +.*  Advance Line by 1 to 14
>>> +.*  Advance PC by fixed size amount [0-9]+ to 0x[0-9a-f]+
>>> +.*  Copy .*
>>> +.*  Advance PC by [0-9]+ to 0x[0-9a-f]+
>>> +.*  Extended opcode 1: End of Sequence
>>> +#pass
>>> diff --git a/gas/testsuite/gas/loongarch/relax-debug-line-opcode.s b/gas/testsuite/gas/loongarch/relax-debug-line-opcode.s
>>> new file mode 100644
>>> index 00000000000..276a823373c
>>> --- /dev/null
>>> +++ b/gas/testsuite/gas/loongarch/relax-debug-line-opcode.s
>>> @@ -0,0 +1,15 @@
>>> +  # Test DWARF line encoding around linker-relaxable instructions.
>>> +  .file 0 "test"
>>> +  .text
>>> +  .loc 0 10 0
>>> +  nop		# special opcode
>>> +  .loc 0 11 0
>>> +  call36 func	# -mrelax: DW_LNS_fixed_advance_pc; -mno-relax: special opcode.
>>> +  .loc 0 12 0
>>> +  nop		# special opcode
>>> +  .loc 0 13 0
>>> +  call36 func	# -mrelax: DW_LNS_fixed_advance_pc; -mno-relax: special opcode.
>>> +  .loc 0 14 0
>>> +  nop		# Advance PC
>>> +
>>> +.section .debug_line, "", @progbits
  
Alan Modra Aug. 31, 2026, 11:52 a.m. UTC | #4
On Mon, Aug 31, 2026 at 04:23:58PM +0800, mengqinggang wrote:
> Thanks! Just to confirm, can this patch be merged?

Yes.
  
mengqinggang Sept. 1, 2026, 1:42 a.m. UTC | #5
Thanks, applied.


在 2026/8/31 19:52, Alan Modra 写道:
> On Mon, Aug 31, 2026 at 04:23:58PM +0800, mengqinggang wrote:
>> Thanks! Just to confirm, can this patch be merged?
> Yes.
>
  

Patch

diff --git a/gas/config/tc-h8300.h b/gas/config/tc-h8300.h
index c4689d37b12..66664553a24 100644
--- a/gas/config/tc-h8300.h
+++ b/gas/config/tc-h8300.h
@@ -46,7 +46,7 @@  struct internal_reloc;
 
 /* Minimum instruction is of 16 bits.  */
 #define DWARF2_LINE_MIN_INSN_LENGTH 2
-#define DWARF2_USE_FIXED_ADVANCE_PC 0
+#define DWARF2_USE_FIXED_ADVANCE_PC(FROM, TO) 0
 
 /* Provide mappings from the original H8 COFF relocation names to
    their corresponding BFD relocation names.  */
diff --git a/gas/config/tc-loongarch.c b/gas/config/tc-loongarch.c
index bd7d8dabb7a..e02881761fe 100644
--- a/gas/config/tc-loongarch.c
+++ b/gas/config/tc-loongarch.c
@@ -1644,6 +1644,31 @@  _loongarch_force_relocation_sub_same (segT sec,
   return true;
 }
 
+/* Use DW_LNS_fixed_advance_pc with relocations if there are linker-relaxable
+   instructions between from and to symbols. Otherwise, use special opcodes
+   without relocations.  */
+bool
+loongarch_fixed_advance_pc (symbolS *from, symbolS *to)
+{
+  segT fromsec = S_GET_SEGMENT (from);
+  segT tosec = S_GET_SEGMENT (to);
+  if (fromsec != tosec)
+    return false;
+  fragS *fromfrag = symbol_get_frag (from);
+  fragS *tofrag = symbol_get_frag (to);
+  return _loongarch_force_relocation_sub_same (fromsec, fromfrag, tofrag);
+}
+
+/* Similar to loongarch_fixed_advance_pc, used for frag.  */
+bool
+loongarch_fixed_advance_pc_frag (fragS *frag)
+{
+  expressionS *exp = symbol_get_value_expression (frag->fr_symbol);
+
+  if (exp->X_op != O_subtract)
+    return false;
+  return loongarch_fixed_advance_pc (exp->X_op_symbol, exp->X_add_symbol);
+}
 
 /* Postpone text-section label subtraction calculation until linking,
    since linker relaxations might change the deltas.  */
diff --git a/gas/config/tc-loongarch.h b/gas/config/tc-loongarch.h
index 146844e772e..1f11f9cef46 100644
--- a/gas/config/tc-loongarch.h
+++ b/gas/config/tc-loongarch.h
@@ -101,8 +101,14 @@  extern bool loongarch_force_relocation_sub_same(struct fix *, asection *);
 #define MD_APPLY_SYM_VALUE(FIX) 0
 
 #define TARGET_USE_CFIPOP 1
-/* Adjust debug_line after relaxation.  */
-#define DWARF2_USE_FIXED_ADVANCE_PC   1
+
+extern bool loongarch_fixed_advance_pc (symbolS *, symbolS *);
+#define DWARF2_USE_FIXED_ADVANCE_PC(FROM, TO) \
+  loongarch_fixed_advance_pc (FROM, TO)
+
+extern bool loongarch_fixed_advance_pc_frag (fragS *);
+#define DWARF2_USE_FIXED_ADVANCE_PC_FRAG(FRAG) \
+  loongarch_fixed_advance_pc_frag (FRAG)
 
 /* FDE Data Alignment Factor.
    FDE Code Alignment Factor (DWARF2_LINE_MIN_INSN_LENGTH) should be 1
diff --git a/gas/config/tc-msp430.h b/gas/config/tc-msp430.h
index fe202abc713..f9b6c1e588c 100644
--- a/gas/config/tc-msp430.h
+++ b/gas/config/tc-msp430.h
@@ -168,7 +168,7 @@  extern bool msp430_allow_local_subtract (expressionS *, expressionS *, segT);
    so don't report errors at this point.  */
 #define TC_VALIDATE_FIX_SUB(FIX, SEG) 1
 
-#define DWARF2_USE_FIXED_ADVANCE_PC 1
+#define DWARF2_USE_FIXED_ADVANCE_PC(FROM, TO) 1
 
 #define TC_LINKRELAX_FIXUP(seg) ((seg->flags & SEC_CODE) || (seg->flags & SEC_DEBUGGING))
 
diff --git a/gas/config/tc-nds32.h b/gas/config/tc-nds32.h
index 432d46d9fb1..49a1bead095 100644
--- a/gas/config/tc-nds32.h
+++ b/gas/config/tc-nds32.h
@@ -77,7 +77,7 @@  extern bool nds32_allow_local_subtract (expressionS *, expressionS *, segT);
 #define md_allow_local_subtract(lhs,rhs,sect)	nds32_allow_local_subtract (lhs, rhs, sect)
 
 /* dwarf2dbg.c.  */
-#define DWARF2_USE_FIXED_ADVANCE_PC		1
+#define DWARF2_USE_FIXED_ADVANCE_PC(FROM, TO)	1
 
 /* write.c.  */
 extern long nds32_pcrel_from_section (struct fix *, segT);
diff --git a/gas/config/tc-riscv.h b/gas/config/tc-riscv.h
index d695db83477..7518d2a70f7 100644
--- a/gas/config/tc-riscv.h
+++ b/gas/config/tc-riscv.h
@@ -135,7 +135,7 @@  extern void riscv_elf_section_change_hook (void);
 extern void riscv_elf_final_processing (void);
 
 /* Adjust debug_line after relaxation.  */
-#define DWARF2_USE_FIXED_ADVANCE_PC 1
+#define DWARF2_USE_FIXED_ADVANCE_PC(FROM, TO) 1
 
 #define md_parse_name(name, exp, mode, c) \
   riscv_parse_name (name, exp, mode)
diff --git a/gas/config/tc-rl78.h b/gas/config/tc-rl78.h
index 9761d509aa1..fb54a2e8da7 100644
--- a/gas/config/tc-rl78.h
+++ b/gas/config/tc-rl78.h
@@ -94,6 +94,6 @@  extern void rl78_elf_final_processing (void);
    || ((SEC)->flags & SEC_DEBUGGING) != 0	\
    || TC_FORCE_RELOCATION (FIX))
 
-#define DWARF2_USE_FIXED_ADVANCE_PC 1
+#define DWARF2_USE_FIXED_ADVANCE_PC(FROM, TO) 1
 
 #define TC_FORCE_RELOCATION(FIX) (linkrelax)
diff --git a/gas/config/tc-xtensa.h b/gas/config/tc-xtensa.h
index 64d735144d7..d6ddac738fe 100644
--- a/gas/config/tc-xtensa.h
+++ b/gas/config/tc-xtensa.h
@@ -419,7 +419,7 @@  extern void xtensa_init (int, char **);
 #define SUB_SEGMENT_ALIGN(SEG, FRCHAIN) 0
 
 /* Use line number format that is amenable to linker relaxation.  */
-#define DWARF2_USE_FIXED_ADVANCE_PC (linkrelax != 0)
+#define DWARF2_USE_FIXED_ADVANCE_PC(FROM, TO) (linkrelax != 0)
 
 
 /* Resource reservation info functions.  */
diff --git a/gas/dwarf2dbg.c b/gas/dwarf2dbg.c
index a1ceab4e428..c899eecd26b 100644
--- a/gas/dwarf2dbg.c
+++ b/gas/dwarf2dbg.c
@@ -112,7 +112,13 @@ 
    opcodes and variable-length operands cannot be used.  If this macro is
    nonzero, use the DW_LNS_fixed_advance_pc opcode instead.  */
 #ifndef DWARF2_USE_FIXED_ADVANCE_PC
-# define DWARF2_USE_FIXED_ADVANCE_PC	linkrelax
+# define DWARF2_USE_FIXED_ADVANCE_PC(FROM, TO)	linkrelax
+#endif
+
+/* Similar to DWARF2_USE_FIXED_ADVANCE_PC, used for frag.  */
+#ifndef DWARF2_USE_FIXED_ADVANCE_PC_FRAG
+# define DWARF2_USE_FIXED_ADVANCE_PC_FRAG(FRAG) \
+	 DWARF2_USE_FIXED_ADVANCE_PC (0, 0)
 #endif
 
 /* First special line opcode - leave room for the standard opcodes.
@@ -1898,7 +1904,7 @@  relax_inc_line_addr (int line_delta, symbolS *to_sym, symbolS *from_sym)
 
   /* The maximum size of the frag is the line delta with a maximum
      sized address delta.  */
-  if (DWARF2_USE_FIXED_ADVANCE_PC)
+  if (DWARF2_USE_FIXED_ADVANCE_PC (from_sym, to_sym))
     max_chars = size_fixed_inc_line_addr (line_delta,
 					  -DWARF2_LINE_MIN_INSN_LENGTH);
   else
@@ -1919,7 +1925,7 @@  dwarf2dbg_estimate_size_before_relax (fragS *frag)
   int size;
 
   addr_delta = resolve_symbol_value (frag->fr_symbol);
-  if (DWARF2_USE_FIXED_ADVANCE_PC)
+  if (DWARF2_USE_FIXED_ADVANCE_PC_FRAG (frag))
     size = size_fixed_inc_line_addr (frag->fr_offset, addr_delta);
   else
     size = size_inc_line_addr (frag->fr_offset, addr_delta);
@@ -1953,31 +1959,25 @@  dwarf2dbg_convert_frag (fragS *frag)
 {
   offsetT addr_diff;
 
-  if (DWARF2_USE_FIXED_ADVANCE_PC)
-    {
-      /* If linker relaxation is enabled then the distance between the two
-	 symbols in the frag->fr_symbol expression might change.  Hence we
-	 cannot rely upon the value computed by resolve_symbol_value.
-	 Instead we leave the expression unfinalized and allow
-	 emit_fixed_inc_line_addr to create a fixup (which later becomes a
-	 relocation) that will allow the linker to correctly compute the
-	 actual address difference.  We have to use a fixed line advance for
-	 this as we cannot (easily) relocate leb128 encoded values.  */
-      int saved_finalize_syms = finalize_syms;
-
-      finalize_syms = 0;
-      addr_diff = resolve_symbol_value (frag->fr_symbol);
-      finalize_syms = saved_finalize_syms;
-    }
-  else
-    addr_diff = resolve_symbol_value (frag->fr_symbol);
+  /* If linker relaxation is enabled then the distance between the two
+     symbols in the frag->fr_symbol expression might change.  Hence we
+     cannot rely upon the value computed by resolve_symbol_value.
+     Instead we leave the expression unfinalized and allow
+     emit_fixed_inc_line_addr to create a fixup (which later becomes a
+     relocation) that will allow the linker to correctly compute the
+     actual address difference.  We have to use a fixed line advance for
+     this as we cannot (easily) relocate leb128 encoded values.  */
+  int saved_finalize_syms = finalize_syms;
+  finalize_syms = 0;
+  addr_diff = resolve_symbol_value (frag->fr_symbol);
+  finalize_syms = saved_finalize_syms;
 
   /* fr_var carries the max_chars that we created the fragment with.
      fr_subtype carries the current expected length.  We must, of
      course, have allocated enough memory earlier.  */
   gas_assert (frag->fr_var >= (int) frag->fr_subtype);
 
-  if (DWARF2_USE_FIXED_ADVANCE_PC)
+  if (DWARF2_USE_FIXED_ADVANCE_PC_FRAG (frag))
     emit_fixed_inc_line_addr (frag->fr_offset, addr_diff, frag,
 			      frag->fr_literal + frag->fr_fix,
 			      frag->fr_subtype);
@@ -2110,7 +2110,8 @@  process_entries (segT seg, struct line_entry *e)
 	  out_set_addr (lab);
 	  out_inc_line_addr (line_delta, 0);
 	}
-      else if (frag == last_frag && ! DWARF2_USE_FIXED_ADVANCE_PC)
+      else if (frag == last_frag
+	       && ! DWARF2_USE_FIXED_ADVANCE_PC (last_lab, lab))
 	out_inc_line_addr (line_delta, frag_ofs - last_frag_ofs);
       else
 	relax_inc_line_addr (line_delta, lab, last_lab);
@@ -2127,7 +2128,7 @@  process_entries (segT seg, struct line_entry *e)
   /* Emit a DW_LNE_end_sequence for the end of the section.  */
   frag = last_frag_for_seg (seg);
   frag_ofs = get_frag_fix (frag, seg);
-  if (frag == last_frag && ! DWARF2_USE_FIXED_ADVANCE_PC)
+  if (frag == last_frag && ! DWARF2_USE_FIXED_ADVANCE_PC (last_lab, lab))
     out_inc_line_addr (INT_MAX, frag_ofs - last_frag_ofs);
   else
     {
diff --git a/gas/testsuite/gas/elf/dwarf-5-irp.d b/gas/testsuite/gas/elf/dwarf-5-irp.d
index a4f01355db3..781b2a32aaa 100644
--- a/gas/testsuite/gas/elf/dwarf-5-irp.d
+++ b/gas/testsuite/gas/elf/dwarf-5-irp.d
@@ -5,8 +5,7 @@ 
 # The bfin target does not allow .subsection with an equated symbol as operand.
 # The d30v target emits sufficiently different debug info, apparently also covering padding it inserts.
 # The riscv targets do not support the subtraction of symbols.
-# The loongarch targets do not support the subtraction of symbols.
-#xfail: am33*-* bfin-* cr16-* crx-* d30v-* ft32-* loongarch*-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
+#xfail: am33*-* bfin-* cr16-* crx-* d30v-* ft32-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
 
 Raw dump of debug contents .*
 #...
diff --git a/gas/testsuite/gas/elf/dwarf-5-loc0.d b/gas/testsuite/gas/elf/dwarf-5-loc0.d
index 9338271c0eb..9439d103b1f 100644
--- a/gas/testsuite/gas/elf/dwarf-5-loc0.d
+++ b/gas/testsuite/gas/elf/dwarf-5-loc0.d
@@ -3,8 +3,7 @@ 
 #name: DWARF5 .loc 0
 # The am33 cr16 crx ft32 mn10 msp430 nds32 and rl78 targets do not evaluate the subtraction of symbols at assembly time.
 # The riscv targets do not support the subtraction of symbols.
-# The loongarch targets do not support the subtraction of symbols.
-#xfail: am3*-* cr16-* crx-* ft32*-* loongarch*-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
+#xfail: am3*-* cr16-* crx-* ft32*-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
 
 Contents of the \.debug_line section:
 
diff --git a/gas/testsuite/gas/elf/dwarf-5-macro-include.d b/gas/testsuite/gas/elf/dwarf-5-macro-include.d
index c39425aa8c9..32ea6386992 100644
--- a/gas/testsuite/gas/elf/dwarf-5-macro-include.d
+++ b/gas/testsuite/gas/elf/dwarf-5-macro-include.d
@@ -4,7 +4,7 @@ 
 # The am33 cr16 crx ft32 mn10* msp430 nds32* and rl78 targets do not evaluate the subtraction of symbols at assembly time.
 # The d30v target emits sufficiently different debug info, apparently also covering padding it inserts.
 # The riscv targets do not support the subtraction of symbols.
-#xfail: am33*-* cr16-* crx-* d30v-* ft32-* loongarch*-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
+#xfail: am33*-* cr16-* crx-* d30v-* ft32-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
 
 Raw dump of debug contents .*
 #...
diff --git a/gas/testsuite/gas/elf/dwarf-5-macro.d b/gas/testsuite/gas/elf/dwarf-5-macro.d
index b2613bd1c16..794e17a575e 100644
--- a/gas/testsuite/gas/elf/dwarf-5-macro.d
+++ b/gas/testsuite/gas/elf/dwarf-5-macro.d
@@ -4,7 +4,7 @@ 
 # The am33 cr16 crx ft32 mn10* msp430 nds32* and rl78 targets do not evaluate the subtraction of symbols at assembly time.
 # The d30v target emits sufficiently different debug info, apparently also covering padding it inserts.
 # The riscv targets do not support the subtraction of symbols.
-#xfail: am33*-* cr16-* crx-* d30v-* ft32-* loongarch*-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
+#xfail: am33*-* cr16-* crx-* d30v-* ft32-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
 
 Raw dump of debug contents .*
 #...
diff --git a/gas/testsuite/gas/elf/dwarf2-11.d b/gas/testsuite/gas/elf/dwarf2-11.d
index 44f5cd18ec6..2c30e55c695 100644
--- a/gas/testsuite/gas/elf/dwarf2-11.d
+++ b/gas/testsuite/gas/elf/dwarf2-11.d
@@ -3,8 +3,7 @@ 
 #name: DWARF2 11
 # The am33 cr16 crx ft32 mn10 msp430 nds32 and rl78 targets do not evaluate the subtraction of symbols at assembly time.
 # The riscv targets do not support the subtraction of symbols.
-# The loongarch targets do not support the subtraction of symbols.
-#xfail: am3*-* cr16-* crx-* ft32*-* loongarch*-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
+#xfail: am3*-* cr16-* crx-* ft32*-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
 
 Contents of the \.debug_line section:
 
diff --git a/gas/testsuite/gas/elf/dwarf2-15.d b/gas/testsuite/gas/elf/dwarf2-15.d
index 3ec9f2785a7..939c61598cb 100644
--- a/gas/testsuite/gas/elf/dwarf2-15.d
+++ b/gas/testsuite/gas/elf/dwarf2-15.d
@@ -3,8 +3,7 @@ 
 #name: DWARF2 15
 # The am33 cr16 crx ft32 mn10 msp430 nds32 and rl78 targets do not evaluate the subtraction of symbols at assembly time.
 # The riscv targets do not support the subtraction of symbols.
-# The loongarch targets do not support the subtraction of symbols.
-#xfail: am3*-* cr16-* crx-* ft32*-* loongarch*-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
+#xfail: am3*-* cr16-* crx-* ft32*-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
 
 Hex dump of section '\.rodata':
   0x00000000 01 *.*
diff --git a/gas/testsuite/gas/elf/dwarf2-16.d b/gas/testsuite/gas/elf/dwarf2-16.d
index 32b57763137..8e35d493619 100644
--- a/gas/testsuite/gas/elf/dwarf2-16.d
+++ b/gas/testsuite/gas/elf/dwarf2-16.d
@@ -4,8 +4,7 @@ 
 # The am33 cr16 crx ft32 mn10 msp430 nds32 and rl78 targets do not evaluate the subtraction of symbols at assembly time.
 # The mep target tries to relay code sections which breaks symbolic view computations.
 # The riscv targets do not support the subtraction of symbols.
-# The loongarch targets do not support the subtraction of symbols.
-#xfail: am3*-* cr16-* crx-* ft32*-* mep-* loongarch*-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
+#xfail: am3*-* cr16-* crx-* ft32*-* mep-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
 
 Hex dump of section '\.rodata':
   0x00000000 01 *.*
diff --git a/gas/testsuite/gas/elf/dwarf2-17.d b/gas/testsuite/gas/elf/dwarf2-17.d
index 4c2f2e3999e..881477cf95b 100644
--- a/gas/testsuite/gas/elf/dwarf2-17.d
+++ b/gas/testsuite/gas/elf/dwarf2-17.d
@@ -4,8 +4,7 @@ 
 # The am33 cr16 crx ft32 mn10 msp430 nds32 and rl78 targets do not evaluate the subtraction of symbols at assembly time.
 # The mep target tries to relay code sections which breaks symbolic view computations.
 # The riscv targets do not support the subtraction of symbols.
-# The loongarch targets do not support the subtraction of symbols.
-#xfail: am3*-* cr16-* crx-* ft32*-* loongarch*-* mep-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
+#xfail: am3*-* cr16-* crx-* ft32*-* mep-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
 
 Hex dump of section '\.rodata':
   0x00000000 00 *.*
diff --git a/gas/testsuite/gas/elf/dwarf2-18.d b/gas/testsuite/gas/elf/dwarf2-18.d
index 18157c634a5..fbaebaa9019 100644
--- a/gas/testsuite/gas/elf/dwarf2-18.d
+++ b/gas/testsuite/gas/elf/dwarf2-18.d
@@ -3,8 +3,7 @@ 
 #name: DWARF2 18
 # The am33 cr16 crx ft32 mn10 msp430 nds32 and rl78 targets do not evaluate the subtraction of symbols at assembly time.
 # The riscv targets do not support the subtraction of symbols.
-# The loongarch targets do not support the subtraction of symbols.
-#xfail: am3*-* cr16-* crx-* ft32*-* loongarch*-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
+#xfail: am3*-* cr16-* crx-* ft32*-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
 
 Hex dump of section '\.rodata':
   0x00000000 0100 *.*
diff --git a/gas/testsuite/gas/elf/dwarf2-19.d b/gas/testsuite/gas/elf/dwarf2-19.d
index 133294affe7..55d0caf4cb1 100644
--- a/gas/testsuite/gas/elf/dwarf2-19.d
+++ b/gas/testsuite/gas/elf/dwarf2-19.d
@@ -4,8 +4,7 @@ 
 # The am33 cr16 crx ft32 mn10 msp430 nds32 and rl78 targets do not evaluate the subtraction of symbols at assembly time.
 # The mep targets turns some view computations into complex relocations.
 # The riscv targets do not support the subtraction of symbols.
-# The loongarch targets do not support the subtraction of symbols.
-#xfail: am3*-* cr16-* crx-* ft32*-* mep-* loongarch*-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
+#xfail: am3*-* cr16-* crx-* ft32*-* mep-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
 
 Hex dump of section '\.rodata':
   0x00000000 01000102 *.*
diff --git a/gas/testsuite/gas/elf/dwarf2-5.d b/gas/testsuite/gas/elf/dwarf2-5.d
index 1dd65732c50..bf1eeb5bbfd 100644
--- a/gas/testsuite/gas/elf/dwarf2-5.d
+++ b/gas/testsuite/gas/elf/dwarf2-5.d
@@ -4,8 +4,7 @@ 
 # The am33 cr16 crx ft32 mn10 msp430 nds32 and rl78 targets do not evaluate the subtraction of symbols at assembly time.
 # The mep target tries to relay code sections which breaks symbolic view computations.
 # The riscv targets do not support the subtraction of symbols.
-# The loongarch targets do not support the subtraction of symbols.
-#xfail: am3*-* cr16-* crx-* ft32*-* loongarch*-* mep-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
+#xfail: am3*-* cr16-* crx-* ft32*-* mep-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
 
 Hex dump of section '\.rodata':
   0x00000000 01010201 010203 *.*
diff --git a/gas/testsuite/gas/lns/lns.exp b/gas/testsuite/gas/lns/lns.exp
index 7a92c54a260..58c2235b628 100644
--- a/gas/testsuite/gas/lns/lns.exp
+++ b/gas/testsuite/gas/lns/lns.exp
@@ -31,7 +31,6 @@  if { ![istarget s390*-*-*] } {
 	 || [istarget cr16-*-*]
 	 || [istarget crx-*-*]
 	 || [istarget ft32*-*]
-	 || [istarget loongarch*-*-*]
 	 || [istarget mn10*-*-*]
 	 || [istarget msp430-*-*]
 	 || [istarget nds32*-*-*]
diff --git a/gas/testsuite/gas/loongarch/relax-debug-line-opcode-norelax.d b/gas/testsuite/gas/loongarch/relax-debug-line-opcode-norelax.d
new file mode 100644
index 00000000000..c8be41feb82
--- /dev/null
+++ b/gas/testsuite/gas/loongarch/relax-debug-line-opcode-norelax.d
@@ -0,0 +1,10 @@ 
+#source: relax-debug-line-opcode.s
+#as: -mno-relax
+#readelf: -W -wl
+
+#...
+.*  Special opcode 62: advance Address by 4 to 0x4 and Line by 1 to 11
+.*  Special opcode 118: advance Address by 8 to 0xc and Line by 1 to 12
+.*  Special opcode 62: advance Address by 4 to 0x10 and Line by 1 to 13
+.*  Special opcode 118: advance Address by 8 to 0x18 and Line by 1 to 14
+#pass
diff --git a/gas/testsuite/gas/loongarch/relax-debug-line-opcode.d b/gas/testsuite/gas/loongarch/relax-debug-line-opcode.d
new file mode 100644
index 00000000000..9c707d97747
--- /dev/null
+++ b/gas/testsuite/gas/loongarch/relax-debug-line-opcode.d
@@ -0,0 +1,25 @@ 
+#source: relax-debug-line-opcode.s
+#as: -mrelax
+#readelf: -r -wl -W
+
+#...
+Relocation section '\.rela\.debug_line' at offset .* contains 7 entries:
+#...
+.*R_LARCH_ADD16[ 	]+[0-9]+.*
+.*R_LARCH_SUB16[ 	]+[0-9]+.*
+.*R_LARCH_ADD16[ 	]+[0-9]+.*
+.*R_LARCH_SUB16[ 	]+[0-9]+.*
+#...
+Raw dump of debug contents of section \.debug_line:
+#...
+.*  Special opcode 62: advance Address by 4 to 0x4 and Line by 1 to 11
+.*  Advance Line by 1 to 12
+.*  Advance PC by fixed size amount [0-9]+ to 0x[0-9a-f]+
+.*  Copy .*
+.*  Special opcode 62: advance Address by 4 to 0x10 and Line by 1 to 13
+.*  Advance Line by 1 to 14
+.*  Advance PC by fixed size amount [0-9]+ to 0x[0-9a-f]+
+.*  Copy .*
+.*  Advance PC by [0-9]+ to 0x[0-9a-f]+
+.*  Extended opcode 1: End of Sequence
+#pass
diff --git a/gas/testsuite/gas/loongarch/relax-debug-line-opcode.s b/gas/testsuite/gas/loongarch/relax-debug-line-opcode.s
new file mode 100644
index 00000000000..276a823373c
--- /dev/null
+++ b/gas/testsuite/gas/loongarch/relax-debug-line-opcode.s
@@ -0,0 +1,15 @@ 
+  # Test DWARF line encoding around linker-relaxable instructions.
+  .file 0 "test"
+  .text
+  .loc 0 10 0
+  nop		# special opcode
+  .loc 0 11 0
+  call36 func	# -mrelax: DW_LNS_fixed_advance_pc; -mno-relax: special opcode.
+  .loc 0 12 0
+  nop		# special opcode
+  .loc 0 13 0
+  call36 func	# -mrelax: DW_LNS_fixed_advance_pc; -mno-relax: special opcode.
+  .loc 0 14 0
+  nop		# Advance PC
+
+.section .debug_line, "", @progbits