[PATCH,V3 4/6] libsframe: correct binary search for SFrame FDE

Indu Bhagat indu.bhagat@oracle.com
Mon May 26 05:08:34 GMT 2025


From: Jens Remus <jremus@linux.ibm.com>

sframe_get_funcdesc_with_addr_internal erroneously returns the last FDE,
if its function start address is lower than the searched for address.

Simplify the binary search for a SFrame FDE for a given address.  Only
return an FDE, if the searched for address is within the bounds of the
FDE function start address and function size.

libsframe/
	* sframe.c (sframe_get_funcdesc_with_addr_internal): Correct
	binary search for SFrame FDE.

libsframe/testsuite/
	* libsframe.find/plt-findfre-1.c: Add test for out of range
	PLT6.

Signed-off-by: Jens Remus <jremus@linux.ibm.com>

---
[Changes in V3]
  - Adjust the check for unsigned arithmetic.
[End of changes in V3]

[New in V2]
---
 libsframe/sframe.c                              | 17 +++++++----------
 .../testsuite/libsframe.find/plt-findfre-1.c    |  4 ++++
 2 files changed, 11 insertions(+), 10 deletions(-)

diff --git a/libsframe/sframe.c b/libsframe/sframe.c
index c1bc692829a..d16305d629b 100644
--- a/libsframe/sframe.c
+++ b/libsframe/sframe.c
@@ -1023,7 +1023,7 @@ sframe_get_funcdesc_with_addr_internal (sframe_decoder_ctx *ctx, int32_t addr,
 {
   sframe_header *dhp;
   sframe_func_desc_entry *fdp;
-  int low, high, cnt;
+  int low, high;
 
   if (ctx == NULL)
     return sframe_ret_set_errno (errp, SFRAME_ERR_INVAL);
@@ -1041,22 +1041,19 @@ sframe_get_funcdesc_with_addr_internal (sframe_decoder_ctx *ctx, int32_t addr,
   fdp = (sframe_func_desc_entry *) ctx->sfd_funcdesc;
   low = 0;
   high = dhp->sfh_num_fdes;
-  cnt = high;
   while (low <= high)
     {
       int mid = low + (high - low) / 2;
 
-      if (fdp[mid].sfde_func_start_address == addr)
+      /* Given sfde_func_start_address <= addr,
+	 addr - sfde_func_start_address must be positive.  */
+      if (fdp[mid].sfde_func_start_address <= addr
+	  && ((uint32_t)(addr - fdp[mid].sfde_func_start_address)
+	      < fdp[mid].sfde_func_size))
 	return fdp + mid;
 
       if (fdp[mid].sfde_func_start_address < addr)
-	{
-	  if (mid == (cnt - 1)) 	/* Check if it's the last one.  */
-	    return fdp + (cnt - 1);
-	  else if (fdp[mid+1].sfde_func_start_address > addr)
-	    return fdp + mid;
-	  low = mid + 1;
-	}
+	low = mid + 1;
       else
 	high = mid - 1;
     }
diff --git a/libsframe/testsuite/libsframe.find/plt-findfre-1.c b/libsframe/testsuite/libsframe.find/plt-findfre-1.c
index 60037fd67ea..89ca4661922 100644
--- a/libsframe/testsuite/libsframe.find/plt-findfre-1.c
+++ b/libsframe/testsuite/libsframe.find/plt-findfre-1.c
@@ -128,6 +128,10 @@ void test_plt_findfre (uint32_t plt_vaddr, uint32_t sframe_vaddr)
   TEST ("plt-findfre-1: Find last FRE in PLT4",
 	(err == 0 && sframe_fre_get_cfa_offset (dctx, &frep, &err) == 0x3));
 
+  /* Find no FRE for out of range PLT6.  */
+  err = sframe_find_fre (dctx, (plt_vaddr + 16*5 + 0x0 - sframe_vaddr), &frep);
+  TEST ("plt-findfre-1: Find no FRE for out of range PLT6", err != 0);
+
   sframe_encoder_free (&ectx);
   sframe_decoder_free (&dctx);
 }
-- 
2.43.0



More information about the Binutils mailing list