]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
gas: ld: sframe: fix RELA r_offset handling
authorIndu Bhagat <indu.bhagat@oracle.com>
Fri, 28 Feb 2025 06:01:40 +0000 (22:01 -0800)
committerIndu Bhagat <indu.bhagat@oracle.com>
Sat, 8 Mar 2025 04:44:51 +0000 (20:44 -0800)
In SFrame V2, SFrame function descriptor entry is a 32-bit signed
integer (sfde_func_start_address) which is meant to indicate the start
PC of the function.  According to the specification, it intends to hold
the offset of the start PC of the function from the
_start_of_the_SFrame_section_.  This value can then be used by
stacktracers to simply do:

   sframe_find_fre ( pc - sframe_vaddr)

when looking up SFrame stack trace data corresponding to the program
counter (pc).

In the current implementation, however, GAS is actually emitting a
PC-relative RELA such that sfde_func_start_address is the offset of the
start PC of the function from the _start_of_the_SFrame_FDE_.  ld.bfd
was then fixing up the value by adjusting the final values by r_offset

Co-Authored-By: Jens Remus <jremus@linux.ibm.com>
bfd/
        * elf-sframe.c (_bfd_elf_merge_section_sframe): Do not fixup
SFrame FDE function start address.
        * elfxx-x86.c (_bfd_x86_elf_finish_dynamic_sections): Likewise
for PLT entries.
gas/
        * gen-sframe.c (output_sframe_funcdesc): New argument for SFrame
section start.
        (output_sframe_internal): New symbol for SFrame section start.
include/
* sframe.h: Fix incorrect comment.

bfd/elf-sframe.c
bfd/elfxx-x86.c
gas/gen-sframe.c
include/sframe.h

index 67ed874e02524e9fb9ce69221305eeb50c488634..a5958464536c963a19bf27051ae87dc87d01eabf 100644 (file)
@@ -429,7 +429,7 @@ _bfd_elf_merge_section_sframe (bfd *abfd,
       uint32_t func_size = 0;
       unsigned char func_info = 0;
       unsigned int r_offset = 0;
-      bool pltn_reloc_by_hand = false;
+      bool pltn_reloc = false;
       unsigned int pltn_r_offset = 0;
       uint8_t rep_block_size = 0;
 
@@ -465,6 +465,7 @@ _bfd_elf_merge_section_sframe (bfd *abfd,
                     of PLT_SFRAME_FDE_START_OFFSET is also set to the
                     same.  */
                  r_offset = sframe_decoder_get_hdr_size (sfd_ctx);
+
                  /* For any further SFrame FDEs, the generator has already put
                     in an offset in place of sfde_func_start_address of the
                     corresponding FDE.  We will use it by hand to relocate.  */
@@ -472,19 +473,16 @@ _bfd_elf_merge_section_sframe (bfd *abfd,
                    {
                      pltn_r_offset
                        = r_offset + (i * sizeof (sframe_func_desc_entry));
-                     pltn_reloc_by_hand = true;
+                     pltn_reloc = true;
                    }
                }
 
              /* Get the SFrame FDE function start address after relocation.  */
              address = sframe_read_value (abfd, contents, r_offset, 4);
-             if (pltn_reloc_by_hand)
+             if (pltn_reloc)
                address += sframe_read_value (abfd, contents,
                                              pltn_r_offset, 4);
-             address += (sec->output_offset + r_offset);
-
-             /* FIXME For testing only. Cleanup later.  */
-             // address += (sec->output_section->vma);
+             address += sec->output_offset;
 
              func_start_addr = address;
            }
index 6ea41f29af1f1664894bf8d1961a7dea51aefff1..465b5cb118ce3bfd8cd72b7b509ebf341e03c088 100644 (file)
@@ -2986,8 +2986,7 @@ _bfd_x86_elf_finish_dynamic_sections (bfd *output_bfd,
        {
          bfd_vma plt_start = htab->elf.splt->output_section->vma;
          bfd_vma sframe_start = htab->plt_sframe->output_section->vma
-                                  + htab->plt_sframe->output_offset
-                                  + PLT_SFRAME_FDE_START_OFFSET;
+                                  + htab->plt_sframe->output_offset;
 #if 0 /* FIXME Testing only. Remove before review.  */
          bfd_vma test_value = (plt_start - sframe_start)
            + htab->plt_sframe->output_section->vma
@@ -3020,8 +3019,7 @@ _bfd_x86_elf_finish_dynamic_sections (bfd *output_bfd,
          bfd_vma plt_start = htab->plt_second->output_section->vma;
          bfd_vma sframe_start
            = (htab->plt_second_sframe->output_section->vma
-              + htab->plt_second_sframe->output_offset
-              + PLT_SFRAME_FDE_START_OFFSET);
+              + htab->plt_second_sframe->output_offset);
 #if 0 /* FIXME Testing only. Remove before review.  */
          bfd_vma test_value = (plt_start - sframe_start)
            + htab->plt_second_sframe->output_section->vma
@@ -3054,8 +3052,7 @@ _bfd_x86_elf_finish_dynamic_sections (bfd *output_bfd,
          bfd_vma plt_start = htab->plt_got->output_section->vma;
          bfd_vma sframe_start
            = (htab->plt_got_sframe->output_section->vma
-              + htab->plt_got_sframe->output_offset
-              + PLT_SFRAME_FDE_START_OFFSET);
+              + htab->plt_got_sframe->output_offset);
          bfd_put_signed_32 (dynobj, plt_start - sframe_start,
                             htab->plt_got_sframe->contents
                             + PLT_SFRAME_FDE_START_OFFSET);
index 947faf366d3d2dd40450f535c737068438c1ce5f..10afcf35448f953e254f1305760e337a63a46ea8 100644 (file)
@@ -608,7 +608,8 @@ output_sframe_row_entry (symbolS *fde_start_addr,
 }
 
 static void
-output_sframe_funcdesc (symbolS *start_of_fre_section,
+output_sframe_funcdesc (symbolS *sframe_start,
+                       symbolS *start_of_fre_section,
                        symbolS *fre_symbol,
                        struct sframe_func_entry *sframe_fde)
 {
@@ -624,7 +625,7 @@ output_sframe_funcdesc (symbolS *start_of_fre_section,
   /* Start address of the function.  */
   exp.X_op = O_subtract;
   exp.X_add_symbol = dw_fde_start_addrS; /* to location.  */
-  exp.X_op_symbol = symbol_temp_new_now (); /* from location.  */
+  exp.X_op_symbol = sframe_start; /* from location.  */
   exp.X_add_number = 0;
   emit_expr (&exp, addr_size);
 
@@ -683,6 +684,8 @@ output_sframe_internal (void)
   int fixed_ra_offset = SFRAME_CFA_FIXED_RA_INVALID;
   unsigned int addr_size;
 
+  symbolS *sframe_start = symbol_temp_new_now ();
+
   addr_size = SFRAME_RELOC_SIZE;
 
   /* The function descriptor entries as dumped by the assembler are not
@@ -766,7 +769,7 @@ output_sframe_internal (void)
   i = 0;
   for (sframe_fde = all_sframe_fdes; sframe_fde; sframe_fde = sframe_fde->next)
     {
-      output_sframe_funcdesc (start_of_fre_section,
+      output_sframe_funcdesc (sframe_start, start_of_fre_section,
                              fre_symbols[i], sframe_fde);
       i += sframe_fde->num_fres;
     }
@@ -1767,7 +1770,6 @@ void
 output_sframe (segT sframe_seg)
 {
   (void) sframe_seg;
-
   /* Setup the version specific access functions.  */
   sframe_set_version (SFRAME_VERSION_2);
 
index a965e23bdd1817e4eef513bd126de0f6f542de18..6c3152f61213635c44eb55ce79dbc65d7ec3671c 100644 (file)
@@ -174,7 +174,7 @@ typedef struct sframe_header
 typedef struct sframe_func_desc_entry
 {
   /* Function start address.  Encoded as a signed offset, relative to the
-     beginning of the current FDE.  */
+     beginning of the SFrame section.  */
   int32_t sfde_func_start_address;
   /* Size of the function in bytes.  */
   uint32_t sfde_func_size;