diff options
author | Indu Bhagat <indu.bhagat@oracle.com> | 2023-06-29 16:29:09 -0700 |
---|---|---|
committer | Indu Bhagat <indu.bhagat@oracle.com> | 2023-06-29 16:31:58 -0700 |
commit | ce9a87252cdf383e1ad3016b7dbc12e9294e3851 (patch) | |
tree | 2ed51b4aff49737ab2053e6e430025ce5730830c /libsframe | |
parent | 9f71b60bd45a93e25ea8dd3d8dc47f9ebd7d00d1 (diff) | |
download | fsf-binutils-gdb-ce9a87252cdf383e1ad3016b7dbc12e9294e3851.zip fsf-binutils-gdb-ce9a87252cdf383e1ad3016b7dbc12e9294e3851.tar.gz fsf-binutils-gdb-ce9a87252cdf383e1ad3016b7dbc12e9294e3851.tar.bz2 |
sframe: bfd: gas: ld: format bump to SFrame version 2
SFrame version 2 encodes the size of repetitive insn block explicitly
in the format. Add information in the SFrame FDE to convey the size
of the block of repeating instructions. This information is used only
for SFrame FDEs of type SFRAME_FDE_TYPE_PCMASK.
Introduce two extra bytes for padding: this ensures that the memory
accesses to the members of the SFrame Frame Descriptor Entry (FDE) are
naturally aligned.
gas generates SFrame section with version SFRAME_VERSION_2 by default.
libsframe provides two new APIs to:
- get an SFrame FDE data from the decoder context, and
- add an SFrame FDE to the encoder context.
The additional argument (for rep_block_size) is useful for SFrame FDEs
where FDE type is SFRAME_FDE_TYPE_PCMASK.
The linker will generate the output SFrame sections in the
SFRAME_VERSION_2 format. If the input sections offered to the linker
are not all in the SFRAME_VERSION_2 format, the linker issues an error
to the user.
objdump/readelf will show the following message to the user if .sframe
section in SFRAME_VERSION_1 format is seen:
"No further information can be displayed. SFrame version not
supported."
In other words, like the rest of the binutils, only the current SFrame
format version, i.e., SFRAME_VERSION_2 is supported by the textual dump
facilities.
bfd/
* elf-sframe.c (_bfd_elf_merge_section_sframe): Generate an
output SFrame section with version SFRAME_VERSION_2. Also,
error out if the SFrame sections do not all have
SFRAME_VERSION_2.
* elfxx-x86.c (_bfd_x86_elf_create_sframe_plt): Generate SFrame
section for plt entries with version SFRAME_VERSION_2.
gas/
* gen-sframe.c (sframe_set_version): Update to SFRAME_VERSION_2.
(output_sframe): Likewise.
gas/testsuite/
* gas/cfi-sframe/cfi-sframe-aarch64-1.d: Use SFRAME_VERSION_2.
* gas/cfi-sframe/cfi-sframe-aarch64-2.d: Likewise.
* gas/cfi-sframe/cfi-sframe-aarch64-pac-ab-key-1.d: Likewise.
* gas/cfi-sframe/cfi-sframe-common-1.d: Likewise.
* gas/cfi-sframe/cfi-sframe-common-2.d: Likewise.
* gas/cfi-sframe/cfi-sframe-common-3.d: Likewise.
* gas/cfi-sframe/cfi-sframe-common-4.d: Likewise.
* gas/cfi-sframe/cfi-sframe-common-5.d: Likewise.
* gas/cfi-sframe/cfi-sframe-common-6.d: Likewise.
* gas/cfi-sframe/cfi-sframe-common-7.d: Likewise.
* gas/cfi-sframe/cfi-sframe-common-8.d: Likewise.
* gas/cfi-sframe/cfi-sframe-x86_64-1.d: Likewise.
* gas/cfi-sframe/common-empty-1.d: Likewise.
* gas/cfi-sframe/common-empty-2.d: Likewise.
* gas/cfi-sframe/common-empty-3.d: Likewise.
ld/testsuite/
* ld-aarch64/sframe-simple-1.d: Adjust for SFRAME_VERSION_2.
* ld-x86-64/sframe-plt-1.d: Likewise.
* ld-x86-64/sframe-simple-1.d: Likewise.
libsframe/
* libsframe.ver: Add the new APIs.
* sframe.c (sframe_decoder_get_funcdesc_v2): New definition.
(sframe_encoder_add_funcdesc_v2): Likewise.
(sframe_header_sanity_check_p): Include SFRAME_VERSION_2.
(sframe_fre_check_range_p): Get rep_block_size info from SFrame
FDE.
* sframe-dump.c (dump_sframe_header): Add support for
SFRAME_VERSION_2.
(dump_sframe): Inform user if SFrame section in SFRAME_VERSION_1
format is seen.
libsframe/testsuite/
* libsframe.decode/DATA-BE: Regenerated data file.
* libsframe.decode/DATA1: Likewise.
* libsframe.decode/DATA2: Likewise.
* libsframe.find/plt-findfre-1.c: Use new API in the testcase.
include/
* sframe.h: Add member to encode size of the code block of
repeating instructions. Add 2 bytes of padding.
* sframe-api.h (sframe_decoder_get_funcdesc_v2): New
declaration.
(sframe_encoder_add_funcdesc_v2): Likewise.
Diffstat (limited to 'libsframe')
-rw-r--r-- | libsframe/libsframe.ver | 2 | ||||
-rw-r--r-- | libsframe/sframe-dump.c | 42 | ||||
-rw-r--r-- | libsframe/sframe.c | 74 | ||||
-rw-r--r-- | libsframe/testsuite/libsframe.decode/DATA-BE | bin | 64 -> 67 bytes | |||
-rw-r--r-- | libsframe/testsuite/libsframe.decode/DATA1 | bin | 60 -> 63 bytes | |||
-rw-r--r-- | libsframe/testsuite/libsframe.decode/DATA2 | bin | 92 -> 98 bytes | |||
-rw-r--r-- | libsframe/testsuite/libsframe.find/plt-findfre-1.c | 2 |
7 files changed, 98 insertions, 22 deletions
diff --git a/libsframe/libsframe.ver b/libsframe/libsframe.ver index 3e2a569..57f5fb6 100644 --- a/libsframe/libsframe.ver +++ b/libsframe/libsframe.ver @@ -20,6 +20,7 @@ LIBSFRAME_1.0 { sframe_find_fre; sframe_decoder_get_num_fidx; sframe_decoder_get_funcdesc; + sframe_decoder_get_funcdesc_v2; sframe_decoder_get_fre; sframe_encode; sframe_encoder_free; @@ -29,6 +30,7 @@ LIBSFRAME_1.0 { sframe_encoder_get_num_fidx; sframe_encoder_add_fre; sframe_encoder_add_funcdesc; + sframe_encoder_add_funcdesc_v2; sframe_encoder_write; dump_sframe; sframe_errmsg; diff --git a/libsframe/sframe-dump.c b/libsframe/sframe-dump.c index 4799652..bb83528 100644 --- a/libsframe/sframe-dump.c +++ b/libsframe/sframe-dump.c @@ -43,27 +43,33 @@ is_sframe_abi_arch_aarch64 (sframe_decoder_ctx *sfd_ctx) static void dump_sframe_header (sframe_decoder_ctx *sfd_ctx) { - const char *verstr = NULL; + uint8_t ver; + uint8_t flags; + char *flags_str; + const char *ver_str = NULL; const sframe_header *header = &(sfd_ctx->sfd_header); /* Prepare SFrame section version string. */ const char *version_names[] = { "NULL", - "SFRAME_VERSION_1" }; - unsigned char ver = header->sfh_preamble.sfp_version; + "SFRAME_VERSION_1", + "SFRAME_VERSION_2" }; + + /* PS: Keep SFRAME_HEADER_FLAGS_STR_MAX_LEN in sync if adding more members to + this array. */ + const char *flag_names[] + = { "SFRAME_F_FDE_SORTED", + "SFRAME_F_FRAME_POINTER" }; + + ver = sframe_decoder_get_version (sfd_ctx); if (ver <= SFRAME_VERSION) - verstr = version_names[ver]; + ver_str = version_names[ver]; /* Prepare SFrame section flags string. */ - unsigned char flags = header->sfh_preamble.sfp_flags; - char *flags_str - = (char*) calloc (sizeof (char), SFRAME_HEADER_FLAGS_STR_MAX_LEN); + flags = header->sfh_preamble.sfp_flags; + flags_str = (char*) calloc (sizeof (char), SFRAME_HEADER_FLAGS_STR_MAX_LEN); if (flags) { - const char *flag_names[] - = { "SFRAME_F_FDE_SORTED", - "SFRAME_F_FRAME_POINTER" }; - unsigned char flags = header->sfh_preamble.sfp_flags; if (flags & SFRAME_F_FDE_SORTED) strcpy (flags_str, flag_names[0]); if (flags & SFRAME_F_FRAME_POINTER) @@ -80,9 +86,9 @@ dump_sframe_header (sframe_decoder_ctx *sfd_ctx) printf ("\n"); printf (" %s :\n", subsec_name); printf ("\n"); - printf (" Version: %s\n", verstr); + printf (" Version: %s\n", ver_str); printf (" Flags: %s\n", flags_str); - printf (" Num FDEs: %d\n", header->sfh_num_fdes); + printf (" Num FDEs: %d\n", sframe_decoder_get_num_fidx (sfd_ctx)); printf (" Num FREs: %d\n", header->sfh_num_fres); free (flags_str); @@ -203,6 +209,14 @@ dump_sframe_functions (sframe_decoder_ctx *sfd_ctx, uint64_t sec_addr) void dump_sframe (sframe_decoder_ctx *sfd_ctx, uint64_t sec_addr) { + uint8_t ver; + dump_sframe_header (sfd_ctx); - dump_sframe_functions (sfd_ctx, sec_addr); + + ver = sframe_decoder_get_version (sfd_ctx); + if (ver == SFRAME_VERSION) + dump_sframe_functions (sfd_ctx, sec_addr); + else + printf ("\n No further information can be displayed. %s", + "SFrame version not supported\n"); } diff --git a/libsframe/sframe.c b/libsframe/sframe.c index cb73a0c..95da010 100644 --- a/libsframe/sframe.c +++ b/libsframe/sframe.c @@ -206,9 +206,10 @@ sframe_header_sanity_check_p (sframe_header *hp) { unsigned char all_flags = SFRAME_F_FDE_SORTED | SFRAME_F_FRAME_POINTER; /* Check preamble is valid. */ - if ((hp->sfh_preamble.sfp_magic != SFRAME_MAGIC) - || (hp->sfh_preamble.sfp_version != SFRAME_VERSION) - || ((hp->sfh_preamble.sfp_flags | all_flags) != all_flags)) + if (hp->sfh_preamble.sfp_magic != SFRAME_MAGIC + || (hp->sfh_preamble.sfp_version != SFRAME_VERSION_1 + && hp->sfh_preamble.sfp_version != SFRAME_VERSION_2) + || (hp->sfh_preamble.sfp_flags | all_flags) != all_flags) return false; /* Check offsets are valid. */ @@ -373,16 +374,13 @@ sframe_fre_check_range_p (sframe_func_desc_entry *fdep, { int32_t start_ip, end_ip; int32_t func_start_addr; - uint32_t rep_block_size; + uint8_t rep_block_size; uint32_t fde_type; int32_t masked_pc; bool mask_p; bool ret; ret = false; - /* FIXME - the rep_block_size should be encoded in the format somehow. For - AMD64, each pltN entry stub in .plt is 16 bytes. */ - rep_block_size = 16; if (!fdep) return ret; @@ -390,6 +388,7 @@ sframe_fre_check_range_p (sframe_func_desc_entry *fdep, func_start_addr = fdep->sfde_func_start_address; fde_type = sframe_get_fde_type (fdep); mask_p = (fde_type == SFRAME_FDE_TYPE_PCMASK); + rep_block_size = fdep->sfde_func_rep_size; if (!mask_p) { @@ -1208,6 +1207,36 @@ sframe_decoder_get_funcdesc (sframe_decoder_ctx *ctx, return 0; } +int +sframe_decoder_get_funcdesc_v2 (sframe_decoder_ctx *dctx, + unsigned int i, + uint32_t *num_fres, + uint32_t *func_size, + int32_t *func_start_address, + unsigned char *func_info, + uint8_t *rep_block_size) +{ + sframe_func_desc_entry *fdp; + int err = 0; + + if (dctx == NULL || func_start_address == NULL + || num_fres == NULL || func_size == NULL + || sframe_decoder_get_version (dctx) == SFRAME_VERSION_1) + return sframe_set_errno (&err, SFRAME_ERR_INVAL); + + fdp = sframe_decoder_get_funcdesc_at_index (dctx, i); + + if (fdp == NULL) + return sframe_set_errno (&err, SFRAME_ERR_FDE_NOTFOUND); + + *num_fres = fdp->sfde_func_num_fres; + *func_start_address = fdp->sfde_func_start_address; + *func_size = fdp->sfde_func_size; + *func_info = fdp->sfde_func_info; + *rep_block_size = fdp->sfde_func_rep_size; + + return 0; +} /* Get the FRE_IDX'th FRE of the function at FUNC_IDX'th function descriptor entry in the SFrame decoder CTX. Returns error code as applicable. */ @@ -1579,6 +1608,37 @@ bad: return -1; } +/* Add a new function descriptor entry with START_ADDR, FUNC_SIZE, FUNC_INFO + and REP_BLOCK_SIZE to the encoder. + + This API is valid only for SFrame format version 2. */ + +int +sframe_encoder_add_funcdesc_v2 (sframe_encoder_ctx *encoder, + int32_t start_addr, + uint32_t func_size, + unsigned char func_info, + uint8_t rep_block_size, + uint32_t num_fres __attribute__ ((unused))) +{ + sf_fde_tbl *fd_info; + int err; + + if (encoder == NULL + || sframe_encoder_get_version (encoder) == SFRAME_VERSION_1) + return sframe_set_errno (&err, SFRAME_ERR_INVAL); + + err = sframe_encoder_add_funcdesc (encoder, start_addr, func_size, func_info, + num_fres); + if (err) + return SFRAME_ERR; + + fd_info = encoder->sfe_funcdesc; + fd_info->entry[fd_info->count-1].sfde_func_rep_size = rep_block_size; + + return 0; +} + static int sframe_sort_funcdesc (sframe_encoder_ctx *encoder) { diff --git a/libsframe/testsuite/libsframe.decode/DATA-BE b/libsframe/testsuite/libsframe.decode/DATA-BE Binary files differindex 3e19ff4..b31b905 100644 --- a/libsframe/testsuite/libsframe.decode/DATA-BE +++ b/libsframe/testsuite/libsframe.decode/DATA-BE diff --git a/libsframe/testsuite/libsframe.decode/DATA1 b/libsframe/testsuite/libsframe.decode/DATA1 Binary files differindex 2b3ef8e..1e67539 100644 --- a/libsframe/testsuite/libsframe.decode/DATA1 +++ b/libsframe/testsuite/libsframe.decode/DATA1 diff --git a/libsframe/testsuite/libsframe.decode/DATA2 b/libsframe/testsuite/libsframe.decode/DATA2 Binary files differindex 68fc2d2..472f736 100644 --- a/libsframe/testsuite/libsframe.decode/DATA2 +++ b/libsframe/testsuite/libsframe.decode/DATA2 diff --git a/libsframe/testsuite/libsframe.find/plt-findfre-1.c b/libsframe/testsuite/libsframe.find/plt-findfre-1.c index f6f4fd7..cc6e239 100644 --- a/libsframe/testsuite/libsframe.find/plt-findfre-1.c +++ b/libsframe/testsuite/libsframe.find/plt-findfre-1.c @@ -42,7 +42,7 @@ add_plt_fde1 (sframe_encoder_ctx *ectx, int idx) unsigned char finfo = sframe_fde_create_func_info (SFRAME_FRE_TYPE_ADDR1, SFRAME_FDE_TYPE_PCMASK); /* 5 pltN entries of 16 bytes each. */ - err = sframe_encoder_add_funcdesc (ectx, 0x1000, 16*5, finfo, 3); + err = sframe_encoder_add_funcdesc_v2 (ectx, 0x1000, 16*5, finfo, 16, 3); if (err == -1) return err; |