forked from Imagelibrary/binutils-gdb
libsframe: correct binary search for SFrame FDE
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>
This commit is contained in:
@@ -1023,7 +1023,7 @@ sframe_get_funcdesc_with_addr_internal (sframe_decoder_ctx *ctx, int32_t addr,
|
|||||||
{
|
{
|
||||||
sframe_header *dhp;
|
sframe_header *dhp;
|
||||||
sframe_func_desc_entry *fdp;
|
sframe_func_desc_entry *fdp;
|
||||||
int low, high, cnt;
|
int low, high;
|
||||||
|
|
||||||
if (ctx == NULL)
|
if (ctx == NULL)
|
||||||
return sframe_ret_set_errno (errp, SFRAME_ERR_INVAL);
|
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;
|
fdp = (sframe_func_desc_entry *) ctx->sfd_funcdesc;
|
||||||
low = 0;
|
low = 0;
|
||||||
high = dhp->sfh_num_fdes;
|
high = dhp->sfh_num_fdes;
|
||||||
cnt = high;
|
|
||||||
while (low <= high)
|
while (low <= high)
|
||||||
{
|
{
|
||||||
int mid = low + (high - low) / 2;
|
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;
|
return fdp + mid;
|
||||||
|
|
||||||
if (fdp[mid].sfde_func_start_address < addr)
|
if (fdp[mid].sfde_func_start_address < addr)
|
||||||
{
|
low = mid + 1;
|
||||||
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;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
high = mid - 1;
|
high = mid - 1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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",
|
TEST ("plt-findfre-1: Find last FRE in PLT4",
|
||||||
(err == 0 && sframe_fre_get_cfa_offset (dctx, &frep, &err) == 0x3));
|
(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_encoder_free (&ectx);
|
||||||
sframe_decoder_free (&dctx);
|
sframe_decoder_free (&dctx);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user