From: Jens Remus Date: Mon, 26 May 2025 18:02:47 +0000 (-0700) Subject: libsframe: handle SFrame FRE start/end IP offsets as unsigned X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=2adbf167cae8812417a38d834e6878540632e0b8;p=thirdparty%2Fbinutils-gdb.git libsframe: handle SFrame FRE start/end IP offsets as unsigned The SFrame FRE start address (fre_start_addr) is defined as unsigned 32-bit integer, as it is an offset from SFrame FDE function start address (sfde_func_start_address) and functions only grow upwards (towards higher addresses). The SFrame FRE start IP offset is a synonym to the SFrame FRE start address. The SFrame FRE end IP offset is either the value of the subsequent FDE start address minus one, if that exists, or the FDE function size minus one otherwise. Both should therefore be handled as unsigned 32-bit integer. In libsframe the "lookup PC" (pc) and SFrame FDE function start address (sfde_func_start_address) are both signed integers, as they are actually offsets from the SFrame section. The unsigned FDE start/end IP offsets may therefore only be safely compared against the offset of the lookup PC from FDE function start address if the FDE function start address is lower or equal to the lookup PC, as this guarantees the offset to be always positive: Given: lookup_pc = pc - sframe_addr sfde_func_start_address = func_start_addr - sframe_addr If the FDE function start address is lower or equal than the lookup PC, which both are signed offsets from SFrame section, then the function start address is also lower or equal to the PC, which are both unsigned: sfde_func_start_address <= lookup_pc func_start_addr - sframe_addr <= pc - sframe_addr func_start_addr <= pc With that the offset of the lookup PC from FDE function start address (lookup_pc - sfde_func_start_address) must always be positive, if FDE function start address is lower or equal to the lookup PC: lookup_pc - sfde_func_start_address = pc - sframe_addr - (func_start_addr - sframe_addr) = pc - func_start_addr libsframe/ * sframe.c (sframe_find_fre): Define and handle start_ip_offset and end_ip_offset as unsigned (same as FRE fre_start_addr). (sframe_fre_check_range_p): Likewise. Define PC offset (from function start address) as unsigned. Signed-off-by: Jens Remus --- diff --git a/libsframe/sframe.c b/libsframe/sframe.c index d03dd5fc5fe..950a6846f04 100644 --- a/libsframe/sframe.c +++ b/libsframe/sframe.c @@ -369,13 +369,13 @@ sframe_decoder_get_funcdesc_at_index (sframe_decoder_ctx *ctx, static bool sframe_fre_check_range_p (sframe_func_desc_entry *fdep, - int32_t start_ip_offset, int32_t end_ip_offset, + uint32_t start_ip_offset, uint32_t end_ip_offset, int32_t pc) { int32_t func_start_addr; uint8_t rep_block_size; uint32_t fde_type; - int32_t pc_offset; + uint32_t pc_offset; bool mask_p; if (!fdep) @@ -386,6 +386,10 @@ sframe_fre_check_range_p (sframe_func_desc_entry *fdep, mask_p = (fde_type == SFRAME_FDE_TYPE_PCMASK); rep_block_size = fdep->sfde_func_rep_size; + if (func_start_addr > pc) + return false; + + /* Given func_start_addr <= pc, pc - func_start_addr must be positive. */ pc_offset = pc - func_start_addr; /* For SFrame FDEs encoding information for repetitive pattern of insns, masking with the rep_block_size is necessary to find the matching FRE. */ @@ -1097,9 +1101,8 @@ sframe_find_fre (sframe_decoder_ctx *ctx, int32_t pc, sframe_frame_row_entry cur_fre; sframe_func_desc_entry *fdep; uint32_t fre_type, i; - int32_t start_ip_offset; int32_t func_start_addr; - int32_t end_ip_offset; + uint32_t start_ip_offset, end_ip_offset; const char *fres; size_t size = 0; int err = 0; @@ -1126,8 +1129,9 @@ sframe_find_fre (sframe_decoder_ctx *ctx, int32_t pc, start_ip_offset = cur_fre.fre_start_addr; end_ip_offset = sframe_fre_get_end_ip_offset (fdep, i, fres + size); - /* Stop search if FRE's start_ip is greater than pc. */ - if ((start_ip_offset + func_start_addr) > pc) + /* Stop search if FRE's start_ip is greater than pc. Given + func_start_addr <= pc, pc - func_start_addr must be positive. */ + if (start_ip_offset > (uint32_t)(pc - func_start_addr)) return sframe_set_errno (&err, SFRAME_ERR_FRE_INVAL); if (sframe_fre_check_range_p (fdep, start_ip_offset, end_ip_offset, pc))