Issues on Sframe on LoongArch with Link Time Relexation

Huang Pei huangpei@loongson.cn
Thu Sep 25 08:05:09 GMT 2025


On Sun, Sep 21, 2025 at 08:01:03AM -0700, Indu Bhagat wrote:
> On 9/20/25 2:26 AM, Huang Pei wrote:
> > On Thu, Sep 18, 2025 at 10:45:24AM -0700, Indu wrote:
> > > On 2025-09-18 6:00 a.m., Huang Pei wrote:
> > > > Hi, everyone,
> > > > 
> > > > when I try to add Sframe support for LoongArch, it occurred to me
> > > > that the current implementation assumed no code relaxation during
> > > > link editing, which causes two issues:
> > > > 
> > > > +. ld triggered the "sframe_assert" from "sframe_decoder_get_fre",
> > > > since the sfde_func_size (with R_LOONGARCH_{ADD32,SUB32}) is not
> > > > resolved at the time because of link time relaxation.(This may
> > > > not be an issue on RISC-V).
> > > > 
> > > 
> > Hi Indu,
> > > Hi Huang,
> > > 
> > > SFrame merging is done after section relocation.  The
> > > _bfd_elf_merge_section_sframe () expects relocated section contents.  So if
> > > you are adding the R_LOONGARCH_{ADD32,SUB32}, this should have been
> > > resolved.
> > > 
> > Yes, it is.
> > > What sframe_assert are you hitting in sframe_decoder_get_fre ? It could be
> > > because of some emission problem in gas/sframe/loongaarch..
> > > 
> > 
> > sframe_assert hit on line 1336 of elf-sframe.c
> > ...
> > 1331           /* Although a stricter sanity check on fre_start_addr like:
> > 1332                if (fdep->sfde_func_size)
> > 1333                  sframe_assert (frep->fre_start_addr < fdep->sfde_func_size);
> > 1334              is more suitable, some code has been seen to not abide by it.  See
> > 1335              PR libsframe/33131.  */
> > 1336           sframe_assert (ifre.fre_start_addr <= fdep->sfde_func_size);
> > 1337
> > 1338          sframe_frame_row_entry_copy (fre, &ifre);
> > 1339
> > 1340          return 0;
> > 1341        }
> > ....
> > 
> > here is what happend:
> > 
> > + sfde_function_size is relocated because of link time relaxation, so
> >    "sframe_decoder_get_fre(sfd_ctx,...)" within
> >    "_bfd_elf_merge_section_sframe"
> >    get 0 from sfde_func_size just like sfde_func_start_addr
> > 
> > + "_bfd_elf_merge_section_sframe" handled the relocated
> > sfde_func_start_addr, but missing updating sfde_func_size both in sfd_ctx
> > and sfe_ctx
> > 
> 
> Yeah, SFrame section data is stitched together from the relocated contents
> as you see in _bfd_elf_merge_section_sframe.
> 
> I see that is getting unwieldy in case of linker relaxations.
> 
> I dont have a solution for this ATM.
> 
> > > (Another thing that strikes me is that so far, SFrame sections have only had
> > > the PCREL relocations for SFrame FDE start addr, now if there are more
> > > relocations like R_LOONGARCH_{ADD32,SUB32} etc, some code adjustments may be
> > > necessary...)
> > > 
> > Yep, it hit loongarch and riscv(I guess)
> > 
> > > What all relaxations are done by ld for loongarch ?  If there is a list
> > > somewhere that will be helpful. As insns change, we will need to make sure
> > > the IP offsets in the 'SFrame FRE start addr offsets' data are still
> > > correct.
> > > 
> 
> How about this issue ?
> 

lu12i.w + ori -> ori
lu12i.w + ori + lu3i.d + lu52i.d ->ori
lu12i.w + add.d + addi.d -> addi.d
pcalau12i + addi.d -> pcaddi
pcaddu18i + jirl -> b/bl
pcalau12i + addi.d + ld.d + jirl -> pcalau12i + ld.d 

relax decrease code size, but may cause other section size changed.

> > > > +. relax "rs_sframe" is not safe any more within gas, it need
> > > > relocs on sfre_start_address, and delayed until link editing.
> > > > 
> > > 
> > > The "rs_sframe" fragments in gas are handling two optimizations:
> > > 
> > >    /* We are dealing with two different kind of fragments here which need
> > >       to be fixed up:
> > >         - first, FRE start address in each FRE, and
> > >         - second, Function info in each FDE (function info stores the FRE
> > > type)
> > >       The two kind of fragments can be differentiated based on the opcode
> > >       of the symbol.  */
> > > 
> > > Basically, we are finding out what is the max size of a function/code block
> > > between .cfi_startproc and .cfi_endproc, and then use that information to
> > > decide how many bytes are minimally needed to encode the data values of
> > > 'SFrame FRE start addr offsets', and the same information then is used to
> > > fix up the relevant bits in 'FDE->sfde_func_info'.
> > > 
> > > In presence of relaxation, the function size will not increase, will it ?
> > Function size will NOT inscrease.
> > > Can you elaborate on why "rs_sframe" handling is not safe in presence in
> > > case of relaxation?
> > 
> > Let's say, the function size is just 256+12 = 268,
> > 
> > without no relaxation, the rs_sframe handling will give 16bit for
> > sfre_start_addr
> > 
> > with link time relaxation done, the function size may be shrinked into
> > 252, now 8bit is enough, and the fre start addr after the shrink should be
> > decreased accordingly, and that is the problem.
> > 
> 
> Right.  So this is an size optimization, which will be missed in these few
> corner cases.  IMO, its okay to skip it, and let the fre start addr be of
> larger size than the minimum necessary.
> 
> > > 
> > > > -mno-relax(and -mthin-add-sub) in LoongArch gas can work around two
> > > > issues, but any advice if not?
> > > > 
> > 
> 
> Ideally I would not go the route of not being able to support ld relaxations
> together with SFrame.  (I am traveling abit this week, will get back to you
> soon).
> 
> Meanwhile, what about the issue above related to reflecting change in PC
> offsets in SFrame FRE start addr when insns are edited.
> 
Let's assume the code fragment in a function shrinked by 4 byte, and its
fre is fre[N], then

+ fre[N+1]'s start addr should shrink 4 bytes.

+ func size in func desc entry should shrink 4 bytes too.
> Thanks



More information about the Binutils mailing list