[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
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
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
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
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
On Mon, Aug 31, 2026 at 04:23:58PM +0800, mengqinggang wrote:
> Thanks! Just to confirm, can this patch be merged?
Yes.
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.
>
@@ -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. */
@@ -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. */
@@ -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
@@ -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))
@@ -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);
@@ -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)
@@ -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)
@@ -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. */
@@ -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
{
@@ -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 .*
#...
@@ -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:
@@ -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 .*
#...
@@ -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 .*
#...
@@ -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:
@@ -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 *.*
@@ -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 *.*
@@ -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 *.*
@@ -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 *.*
@@ -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 *.*
@@ -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 *.*
@@ -31,7 +31,6 @@ if { ![istarget s390*-*-*] } {
|| [istarget cr16-*-*]
|| [istarget crx-*-*]
|| [istarget ft32*-*]
- || [istarget loongarch*-*-*]
|| [istarget mn10*-*-*]
|| [istarget msp430-*-*]
|| [istarget nds32*-*-*]
new file mode 100644
@@ -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
new file mode 100644
@@ -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
new file mode 100644
@@ -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