summaryrefslogtreecommitdiff
path: root/gas/sframe-opt.c
diff options
context:
space:
mode:
authorIndu Bhagat <indu.bhagat@oracle.com>2022-12-09 10:25:14 -0800
committerIndu Bhagat <indu.bhagat@oracle.com>2022-12-09 10:25:14 -0800
commit989aabcb564dccc7804f174fc582b0639357a9bb (patch)
tree0601a91e7efe876b93b4055cd3ca6691ad2ee1ec /gas/sframe-opt.c
parent3f107464e35cf63a529358a1c240821b30c35d2b (diff)
downloadbinutils-gdb-989aabcb564dccc7804f174fc582b0639357a9bb.tar.gz
gas: sframe: fine tune the fragment fixup for SFrame func info
SFrame function info is an unsigned 8-bit field comprising of the following (from LSB to MSB): - 4-bits: FRE type - 1-bit: FRE start address encoding - 3-bits: Unused At the moment, the most-significat 4-bits are zero (The FRE start address encoding of SFRAME_FDE_TYPE_PCINC has a value of zero, and the upper 3-bits are unused). So the current implementation works without this patch. To be precise, however, the fragment fixup logic is meant to fixup only the least-significant 4-bits (i.e., only the FRE type needs to be updated according to the function size). This patch makes the gas implementation a bit more resilient: In the future, when the format does evolve to make use of the currently unused 3-bits in various ways, the values in those 3-bits can be propagated unchanged while the fragment fixup continues to update the lowermost 4-bits to indicate the selected FRE type. ChangeLog: * gas/gen-sframe.c (create_func_info_exp): New definition. (output_sframe_funcdesc): Call create_func_info_exp. * gas/sframe-opt.c (sframe_estimate_size_before_relax): The associated fragment uses O_modulus now. (sframe_convert_frag): Adjust the fragment fixup code according to the new composite exp.
Diffstat (limited to 'gas/sframe-opt.c')
-rw-r--r--gas/sframe-opt.c34
1 files changed, 24 insertions, 10 deletions
diff --git a/gas/sframe-opt.c b/gas/sframe-opt.c
index 6901aa82a77..f08a424fd88 100644
--- a/gas/sframe-opt.c
+++ b/gas/sframe-opt.c
@@ -40,10 +40,10 @@ sframe_estimate_size_before_relax (fragS *frag)
The two kind of fragments can be differentiated based on the opcode
of the symbol. */
exp = symbol_get_value_expression (frag->fr_symbol);
- gas_assert ((exp->X_op == O_subtract) || (exp->X_op == O_absent));
+ gas_assert ((exp->X_op == O_modulus) || (exp->X_op == O_absent));
/* Fragment for function info in an SFrame FDE will always write
only one byte. */
- if (exp->X_op == O_subtract)
+ if (exp->X_op == O_modulus)
ret = 1;
/* Fragment for the start address in an SFrame FRE may write out
1/2/4 bytes depending on the value of the diff. */
@@ -92,8 +92,12 @@ sframe_convert_frag (fragS *frag)
offsetT fsize;
offsetT diff;
offsetT value;
- unsigned char func_info = SFRAME_FRE_TYPE_ADDR4;
+
+ offsetT rest_of_data;
+ uint8_t fde_type, fre_type;
+
expressionS *exp;
+ symbolS *dataS;
symbolS *fsizeS, *diffS;
/* We are dealing with two different kind of fragments here which need
@@ -103,19 +107,29 @@ sframe_convert_frag (fragS *frag)
The two kind of fragments can be differentiated based on the opcode
of the symbol. */
exp = symbol_get_value_expression (frag->fr_symbol);
- gas_assert ((exp->X_op == O_subtract) || (exp->X_op == O_absent));
+ gas_assert ((exp->X_op == O_modulus) || (exp->X_op == O_absent));
/* Fragment for function info in an SFrame FDE. */
- if (exp->X_op == O_subtract)
+ if (exp->X_op == O_modulus)
{
- fsizeS = frag->fr_symbol;
+ /* Gather the existing value of the rest of the data except
+ the fre_type. */
+ dataS = exp->X_add_symbol;
+ rest_of_data = (symbol_get_value_expression(dataS))->X_add_number;
+ fde_type = SFRAME_V1_FUNC_FDE_TYPE (rest_of_data);
+ gas_assert (fde_type == SFRAME_FDE_TYPE_PCINC);
+
+ /* Calculate the applicable fre_type. */
+ fsizeS = exp->X_op_symbol;
fsize = resolve_symbol_value (fsizeS);
if (fsize < SFRAME_FRE_TYPE_ADDR1_LIMIT)
- func_info = SFRAME_FRE_TYPE_ADDR1;
+ fre_type = SFRAME_FRE_TYPE_ADDR1;
else if (fsize < SFRAME_FRE_TYPE_ADDR2_LIMIT)
- func_info = SFRAME_FRE_TYPE_ADDR2;
+ fre_type = SFRAME_FRE_TYPE_ADDR2;
else
- func_info = SFRAME_FRE_TYPE_ADDR4;
- value = func_info;
+ fre_type = SFRAME_FRE_TYPE_ADDR4;
+
+ /* Create the new function info. */
+ value = SFRAME_V1_FUNC_INFO (fde_type, fre_type);
frag->fr_literal[frag->fr_fix] = value;
}