This patch supports Zalasr extension(load-acquire/store-release) instructions.
https://github.com/riscv/riscv-zalasr
bfd/ChangeLog:
* elfxx-riscv.c (riscv_multi_subset_supports): New ext.
(riscv_multi_subset_supports_ext): Ditto.
gas/ChangeLog:
* NEWS: Support Zalasr extension.
* testsuite/gas/riscv/march-help.l: New ext.
* testsuite/gas/riscv/zalasr.d: New test.
* testsuite/gas/riscv/zalasr.s: New test.
include/ChangeLog:
* opcode/riscv-opc.h (MATCH_LBA): New match opcode.
(MASK_LBA): New mask opcode.
(MATCH_LHA): New match opcode.
(MASK_LHA): New mask opcode.
(MATCH_LWA): New match opcode.
(MASK_LWA): New mask opcode.
(MATCH_LDA): New match opcode.
(MASK_LDA): New mask opcode.
(MATCH_SBR): New match opcode.
(MASK_SBR): New mask opcode.
(MATCH_SHR): New match opcode.
(MASK_SHR): New mask opcode.
(MATCH_SWR): New match opcode.
(MASK_SWR): New mask opcode.
(MATCH_SDR): New match opcode.
(MASK_SDR): New mask opcode.
(DECLARE_INSN): New insn declare.
* opcode/riscv.h (enum riscv_insn_class): New ext.
opcodes/ChangeLog:
* riscv-opc.c: New instructions def.
Rename the Arm AEABI CPU architecture tag constants and macro definitions to include the
profile suffix for A-profile architectures. This makes the naming
consistent with existing v8-R and v8-M tag names, while preserving the
existing numeric tag values.
Update BFD, GAS and Gold usage accordingly, including attribute combination
tables, architecture checks, and mach selection.
Replace QLF_NIL with QLF_UNUSED for qualifier sequence list padding.
This splits apart distinct qualifier meanings, and simplifies detection
of empty qualifier sequences.
Some uses of AARCH64_OPND_QLF_NIL actually represent an unknown operand
qualifier. The F_STRICT flag was added to disable the wild card
behaviour for most SVE instructions, but this just makes the code less
consistent and more confusing.
Add a new qualifer to indicate that the real qualifier is currently
unknown, and use this in any place where we need the wildcard behaviour
(and in a few other places where UNKNOWN is more descriptive than NIL).
For consistency (and as an extra check during development), change the
default qualifier value during parsing to AARCH64_OPND_QLF_ERR, and add
explicit qualifier assignments to each non-failure code path.
Add fallback handling for an invalid choice of opd0_qlf, instead of
hitting an assert when trying to use X registers in byte or half
instructions.
Additionally, simplify the code by inlining the relevant parts of
aarch64_get_expected_qualifer, and by deducing the array index directly
from the qualifier enum values (instead of looking up the element size
and computing its log).
This makes aarch64_get_expected_qualifier unused, so remove it.
Add a new opcode flag F_REQUIRES_SP and use that to enforce the
requirement for at least one SP operand in the mov (to/from SP) opcode.
This requirement was the only reason for the existence of the QLF_SP and
QLF_WSP qualifiers. Delete them, and remove the confusing code that
would switch between SP and non-SP qualifiers in the middle of qualifier
matching.
During review, a question was "where are those numbers that you are
adding defined". Add some URLs pointing to the source of truth for
those numbers.
Change-Id: I11b7cb351a9b818fca66a532bfcd27286ec0ddfd
AMDGPU code object V6 adds the EF_AMDGPU_GENERIC_VERSION_V field.
Decode it when decoding the e_flags value for amdgpu.
The output for such generic GFX targets will look like:
$ readelf -h gpu.elf
ELF Header:
...
Flags: 0x1000151, gfx9-generic, xnack any, generic v1
----------
...
... indicating that this ELF has the "generic code object v1" flag.
Change-Id: I0cb8014fc23150e16f43ab98adb3832ede253c88
Co-Authored-By: Simon Marchi <simon.marchi@efficios.com>
This patch updates the list of supported AMDGPU architectures in bfd/
binutils/ and include/elf/.
The following architectures have been added:
- gfx942
- gfx950
- gfx1150
- gfx1151
- gfx1152
- gfx1153
- gfx1200
- gfx1201
- gfx1250
The canonical source for these numbers is:
https://llvm.org/docs/AMDGPUUsage.html#amdgpu-ef-amdgpu-mach-table
Co-Authored-By: Laurent Morichetti <laurent.morichetti@amd.com>
Co-Authored-By: Simon Marchi <simon.marchi@efficios.com>
Co-Authored-By: Olu Ogunbowale <oogunbow@amd.com>
Co-Authored-By: Shahab Vahedi <shahab.vahedi@amd.com>
Co-Authored-By: Anurag Kumar <AnuragKumar.Vulisha@amd.com>
Change-Id: I80e76c8ec98b725937fe445883fae707097ec2b7
After commit 5c3261b0e8 there was no need for this flag. Remove it
and tidy places that used it.
include/
* bfdlink.h (struct bfd_link_info): Delete
check_relocs_after_open_input.
ld/
* emultempl/aarch64elf.em (before_parse): Don't set
link_info.check_relocs_after_open_input.
* emultempl/armelf.em (before_parse): Likewise.
* emultempl/elf.em (before_parse): Likewise.
* emultempl/scoreelf.em (before_parse): Likewise.
* emultempl/mmix-elfnmmo.em (mmix_before_parse): Delete.
(LDEMUL_BEFORE_PARSE): Don't define.
* emultempl/mmixelf.em (elfmmix_before_parse): Call elf.em
before_parse.
* ldlang.c (lang_check_relocs): Don't test
link_info.check_relocs_after_open_input.
The CRn and CRm operands of sysp were unnecessarily constrained to the
ranges C8-C9 and C0-C7. This constraint has been removed from the
architecture spec, and was never implemented in LLVM, so remove it here
as well.
Additionally, add some more tests to cover the full range of valid sysp
operands, including omitting the pair of optional operands.
These accept either r or w prefix registers during assembly
(pseudoc dialect), while disassembling canonically as r registers.
This eliminates the need for duplicate opcode table entries for
instructions that accept both w and r register forms.
Signed-off-by: Vineet Gupta <vineet.gupta@linux.dev>
This patch removes the constraint that a CTF_F_ARRNELEMS flag has to be
present in order to reverse the elements of an array when dumping. The
flag was never added to GCC, and having this requirement causes more
problems than it solves. A quick recap of the issue:
Given an array int foo[1][2][3], the expected graph is:
int foo[1][2][3] -> int foo[2][3] -> int foo[3] -> int foo
Prior to GCC PR114186, the emitted graph would be:
int foo[1][2][3] -> int foo[1][2] -> int foo[1] -> int foo
Following GCC PR114186, before the libctf fix, the output was:
int foo[3][2][1] -> int foo[3][2] -> int foo[3] -> int foo
So the underlying type graph was correct, but the ordering of elements
was incorrect.
With this fix, we emit correct ordering of the type graph, with no
requirements for the compiler to signal that it has GCC PR114186.
include/
* ctf.h (CTF_F_ARRNELEMS): Delete.
(CTF_F_MAX): Adjust.
libctf/
* ctf-decl.c (ctf_decl_push): Act as if CTF_F_ARRNELEMS is
always set.
* ctf-dump.c (ctf_dump_header): No longer dump its value.
* testsuite/libctf-lookup/multidim-array.c: No longer detect
compilers not emitting this flag (none do).
It looks like assuming _GL_WINDOWS_STAT_INODES is 1 is likely our best
option. See gnulib/m4/windows-stat-inodes.m4. Note that this doesn't
really make SAME_INODE usable on windows hosts as a number of the
likely filesystems (FAT, HPFS, or NTFS) don't support st_ino.
* same-inode.h (SAME_INODE <_WIN32>): Remove _GL_WINDOWS_STAT_INODES
test. Assume it is true.
With commit:
commit f829773772
Date: Tue Mar 25 13:30:32 2025 +0000
Delete the ARM sub-directory of the SIM directory.
the arm simulator was removed from the sim/ directory. GDB has now
been updated to remove its support for the arm simulator, and as a
result, this header file is no longer used by anyone. Lets delete it.
There should be no user visible changes after this commit.
Approved-By: Tom Tromey <tom@tromey.com>
The BPF "may_goto" instruction is a special sort of conditional jump
where the condition is determined by the BPF runtime. That is, it is
a no-op until the runtime decides otherwise.
For normal asm syntax, the mnemonic "jcond" is chosen in keeping with
the style of following the opcode definitions in the Linux kernel uapi
BPF headers.
This instruction is not currently emitted by GCC, but it can be inserted
into BPF programs via macros defined in the Linux kernel.
PR gas/32176
include/
* opcode/bpf.h (BPF_CODE_JCOND): New.
(bpf_insn_id): Add BPF_INSN_JCOND.
opcodes/
* bpf-opc.c: Add entry for BPF_INSN_JCOND.
gas/testsuite/
* gas/bpf/bpf.exp: Run new dump tests.
* gas/bpf/jcond-be-pseudoc.d: New.
* gas/bpf/jcond-be.d: New.
* gas/bpf/jcond-pseudoc.d: New.
* gas/bpf/jcond-pseudoc.s: New.
* gas/bpf/jcond.d: New.
* gas/bpf/jcond.s: New.
The existing SFrame V3 macros for Flexible FDEs used the term 'OFFSET'
to refer to the data word encoding control/register data word. This can
be confusing, as the control data word (register ID, dereference flags)
is distinct from a stack offset.
This patch renames these macros to use 'CTRLWORD' to better reflect
their purpose. It also updates the assembler and libsframe dumper to
use the new nomenclature.
No functional change.
Reviewed-by: Jens Remus <jremus@linux.ibm.com>
gas/
* gen-sframe.c (sframe_get_fre_dataword_size): Use
SFRAME_V3_FLEX_FDE_CTRLWORD_ENCODE.
(output_sframe_row_entry_datawords): Likewise.
include/
* sframe.h (SFRAME_V3_FLEX_FDE_REG_ENCODE): Rename from ..
(SFRAME_V3_FLEX_FDE_CTRLWORD_ENCODE): .. to.
(SFRAME_V3_FLEX_FDE_CTRLWORD_REGNUM): Rename from
SFRAME_V3_FLEX_FDE_OFFSET_REG_NUM to this.
(SFRAME_V3_FLEX_FDE_CTRLWORD_DEREF_P): Rename from
SFRAME_V3_FLEX_FDE_OFFSET_REG_DEREF_P to this.
(SFRAME_V3_FLEX_FDE_CTRLWORD_REG_P): Rename from
SFRAME_V3_FLEX_FDE_OFFSET_REG_P to this.
(SFRAME_V3_FRE_RA_UNDEFINED_P): Add new V3 macro.
libsframe/
* sframe-dump.c (dump_sframe_func_fres_flex): Update all
callers to use the new CTRLWORD macros.
libsframe/testsuite/
* libsframe.decode/be-flipping-v3.c: Use renamed macros.
TLBI Domains feature changes TLBI and TLBIP system instructions.
For all TLBIP *E1IS*, TLBIP *E1OS*, TLBIP *E2IS* and TLBIP *E2OS*
instructions that are currently dependent on FEAT_D128 (+d128),
will also be available with FEAT_TLBID (+tlbid).
TLBI Domains feature changes TLBI and TLBIP system instructions.
For the TLBI instruction with optional register argument
<Rt> == 0b1111, with FEAT_TLBID enabled they are permitted to
have an Rt value which is not 0b11111 and this is allowed for
all the TLBI instructions with a <type> of ALLE1*, ALLE2*,
VMALL*, VMALLS12* or VMALLWS2* and a <shareability> of IS or OS.
This patch add support for FEAT_TLBID feature, which is enabled
by new +tlbid option.
This patch is the first patch to align libsframe with the terminology
change of moving from 'offset' to 'data word'. With the introduction of
flexible FDE type SFRAME_FDE_TYPE_FLEX, the variable-length data
following an SFrame FRE header can now represent signed offsets or
unsigned control data. Consequently, 'data word' is adopted as the more
generic term.
This change updates the names used in the user-facing
sframe_frame_row_entry structure. While some API function names remain
unchanged to preserve existing contracts, the underlying data buffers
and size macros now reflect the data word' terminology.
libsframe is a tricky spot for such a terminology change: some of APIs
are still used to read (may be followed by endian swap) for dumping
SFrame V2 sections in textual format. Some classic examples are
sframe_decode_fre, and flip_fre (both are static functions). But moving
forward, using the term 'data word' for such APIs and their internal too
may be better. Subsequent commits will achieve just that.
include/
* sframe-api.h (MAX_NUM_DATAWORDS): Rename from
MAX_NUM_STACK_OFFSETS.
(MAX_DATAWORD_BYTES): Rename from MAX_OFFSET_BYTES.
(struct sframe_frame_row_entry): Rename fre_offsets to
fre_datawords.
libsframe/
* sframe.c (sframe_fre_sanity_check_p): Use MAX_NUM_DATAWORDS.
(sframe_get_fre_offset): Update internal pointers to use
'offsets' and access fre_datawords.
(sframe_get_fre_udata): Rename local variables to
dataword_cnt/dataword_size and update to use
SFRAME_FRE_DATAWORD_* constants.
(sframe_decode_fre): Use fre_datawords and MAX_DATAWORD_BYTES.
(sframe_encoder_add_fre): Use fre_datawords.
(sframe_encoder_write_fre): Use fre_datawords.
In SFrame V3, with the addition of flexible FDE type, the
variable-length array of bytes trailing the SFrame FRE header are no
longer exclusively interpreted as signed offsets. This data can now
include unsigned control data, unsigned padding word data or signed
offset data. Consequently, using the term "offsets" to describe this
trailing data is inaccurate and can be confusing.
This patch switches the terminology to 'Data Word' across the assembler
and the SFrame header file. Note that, the term 'Word' is used
colloquially here, the actual size (1, 2, or 4 bytes) remains determined
by the applicable bits in the FRE info byte.
gas/
* gen-sframe.c: Rename SFrame FRE 'offset' to 'data word'.
include/
* sframe.h (SFRAME_FRE_DATAWORD_1B, SFRAME_FRE_DATAWORD_2B,
SFRAME_FRE_DATAWORD_4B): New constants.
(struct sframe_fre_info): Update bitfield documentation.
(SFRAME_V3_FRE_DATAWORD_COUNT): New macro.
(SFRAME_V3_FRE_DATAWORD_SIZE): New macro.
This patch adds the parsing logic for Object Attributes v2 (OAv2), enabling
Gas to interpret and process these attributes correctly. It also updates the
AArch64 backend to utilize the new parsing capabilities, and handle the new
AArch64-specific directives.
This patch relies on the abstractions introduced in the previous patch to
store the data. Its scope is limited to parsing the new assembly directives,
checking the inputs, and storing the data into the relevant OAv2 abstractions.
Note that, for now, the new parsing capabilities are only available for AArch64.
Even if the implementation was splitted into a generic part available in
gas/config/obj-elf.c, and an AArch64-specific one in gas/config/tc-aarch64.c,
the lack of GNU generic directives to handle OAv2 prevented the capability
from being exposed to others backends.
** GNU assembler interface for aeabi subsections
OAv2 introduced two new directives for AArch64:
- .aeabi_subsection name, comprehension, encoding
Create or switch the current subsection to 'name'.
Comprehension values can be 'required' or 'optional'.
Encoding values are limited for now to 'ULEB128', and 'NTBS'
The comprehension and encoding are mandatory arguments on the first
declaration of the subsection, but become optional for subsequent
ones.
- .aeabi_attribute tag, value
Set 'tag' to 'value' in the current subsection.
Tag can either be an integer, or one of the defined symbols in the backend.
The usage of those directives will error if the following requirements
are breached:
- If the subsection X has been previously declared, the comprehension and
encoding parameters of the current .aeabi_subsection that redeclares X
have to match with the previous declaration. If those parameters are
omited, no check is performed.
- The type of the value set via .aeabi_attribute has to align with
the current subsection.
- If the tag N has already been declared for the current subsection, a
later assignment to tag N is tolerated only if the newly set value is
equal to the former one. This check is stricter than needed. Ideally,
the tag N's values should be merged together, and an error should be
raised only if an incompatibility is detected. Because the attributes
are set in one chunk by GCC, there is no real use case for such a merge.
The new parsing code is enabled/disabled via the TC_OBJ_ATTR_v1 and
TC_OBJ_ATTR_v2 defines, and supports the following configurations:
- enable both OAv1 and OAv2 parsing. This is currently used by no
target, but is useful for migration from OAv1 to OAv2.
- enable OAv1 parsing only. This is used by all targets supporting OAs
except for AArch64.
- enable OAv2 parsing only. This is only used by AArch64.
** Regarding the implementation
The logic of OAv1 does not always keep separated the different data processing
steps: parsing, convertion to internal abstractions, error checking and further
processing (if any) on those abstractions, and their serialization into the
object files.
This patch takes into account the specifities of syntax for OAv1 and OAv2, but
mutualize as much as possible the common behavior so that the same methods can
be used for parsing the OAv1 and OAv2 directives.
However, the mutualization of the code is limited by a different internal model
for OAv1 and OAv2. Even if it is technically feaseable to have only one middle
-end for OAv1, OAv2 and even GNU properties, sharing the same data model to
perform the merge logic with the same code, it is a significant amount of work.
This extra work was not considered as a part of this new feature, so this patch
series will stick with the minimum of mutualization as possible.
Co-Authored-By: Matthieu Longo <matthieu.longo@arm.com>
Since glibc 2.39, containing commit 3ab9b88 ("powerpc: Add HWCAP3/HWCAP4 data
to TCB for Power Architecture."), glibc's elf/elf.h contains constants
AT_HWCAP3/AT_HWCAP4.
Add these in elf/common.h.
Approved-By: Simon Marchi <simon.marchi@efficios.com>
This patch adds support for MLB invalidate (MLBI) instruction.
Syntax: MLBI <mlbi_op>{, <Xt>}
This instruction is an alias to "SYS #4, C7, C0, #<op2>{, <Xt>}"
and MLBI being the preferred disassembly.
The following list of MLBI operations are supported in this patch for the
MLBI instructions enabled by "+mpamv2"
* alle1
* vmalle1
* vpide1
* vpmge1
This commit amalgamates a patch set proposed by Jens Remus to enable the
SFrame Version 3 Flexible FDE Type (SFRAME_FDE_TYPE_FLEX) generation for
the s390x ABI.
Previously, s390x relied on architecture-specific encoding (shifting register
numbers into offset fields) to represent register recovery rules. This limited
the complexity of CFI that could be supported. With Flex FDE enabled:
- s390x can now represent .cfi_def_cfa using non-SP/FP registers.
- The architecture-specific function s390_sframe_xlate_do_register () in GAS
is replaced by the generic Flex FDE generation path.
- The SFrame V3 specific macros for s390x register encoding are removed
from libsframe/include, as the generic Flex FDE format handles explicit
register columns natively.
The testsuite is updated to replace negative tests (which asserted
warnings or empty SFrame generation for these patterns) with positive
tests verifying valid Flex FDE generation.
Co-authored-by: Jens Remus <jremus@linux.ibm.com>
gas/
* config/tc-s390.c (s390_support_flex_fde_p): Return true to
enable Flex FDE generation.
* gen-sframe.c (s390_sframe_xlate_do_register): Disable s390x
specific implementation.
(sframe_xlate_do_register): Invoke generic Flex FDE path now
that flex FDE generation is supported.
gas/testsuite/
* gas/cfi-sframe/cfi-sframe-s390x-err-1.d: Removed.
* gas/cfi-sframe/cfi-sframe-s390x-err-1.s: Moved to...
* gas/cfi-sframe/cfi-sframe-s390x-non-spfp-cfa-1.s: ...here.
* gas/cfi-sframe/cfi-sframe-s390x-err-2.d: Removed.
* gas/cfi-sframe/cfi-sframe-s390x-err-2.s: Moved to...
* gas/cfi-sframe/cfi-sframe-s390x-non-spfp-cfa-2.s: ...here.
* gas/cfi-sframe/cfi-sframe-s390x-fpra-register-1.d: Update to
expect Flex FDE output.
* gas/cfi-sframe/cfi-sframe-s390x-fpra-register-2.d: Likewise.
* gas/cfi-sframe/cfi-sframe.exp: Run renamed tests.
include/
* sframe.h (SFRAME_V3_S390X_OFFSET_IS_REGNUM): Remove.
(SFRAME_V3_S390X_OFFSET_ENCODE_REGNUM): Remove.
(SFRAME_V3_S390X_OFFSET_DECODE_REGNUM): Remove.
libsframe/
* sframe-dump.c (sframe_s390x_offset_regnum_p): Return false
for SFrame V3.
(sframe_s390x_offset_decode_regnum): Remove V3 support.
SFrame V3 has 8 precious flag bits, two of which are being used. More
flag byte (s) can be added to the auxiliary header when it comes to
that. But for now, it may be worthwhile to use the 8-bits frugally.
SFRAME_F_FRAME_POINTER flag bit was added with the intention of marking
binaries built with frame-pointer preserved. A stack tracer could then
use this information, to unambiguously ascertain whether frame-pointer
based stack traces will be precise. But such a marking of binary will
ideally be done by the linker, and at the moment adding such a framework
is not justified for such small gain. The outcome of this is that
SFRAME_F_FRAME_POINTER is never set in SFrame V2 binaries.
Remove the definition SFRAME_F_FRAME_POINTER for SFrame V3. The
relinquished bit can be used (in future format incarnations) when
reading/dumping SFrame V2 sections are no longer supported by consumers.
Changing the values of existing flags, e.g.,
SFRAME_F_FDE_FUNC_START_PCREL, is not being done for V3, to avoid
version-specific flag bit reading (albeit doable) in consumers.
Related changes to the specification are done in a subsequent commit.
include/
* sframe.h (SFRAME_V3_F_ALL_FLAGS): Remove
SFRAME_F_FRAME_POINTER from the set of V3 flags.
libsframe/
* sframe-dump.c (dump_sframe_header_flags): Add a comment for
clarity.
Add a new command line option --discard-sframe to the linker.
This option allows users to prevent the linker from generating an output
.sframe section.
The rationale for this option is: Consider the case when say, the distro
is shipped with SFrame sections in the installed binaries/libraries. A
user application using these installed libraries, but not enabling
.sframe for itself just yet, will see an output .sframe corresponding to
the pulled in libraries. This is "partial" .sframe information for the
application. Adding such an option to the linker, gives user a way to
turn off the .sframe section completely without relying on a linker
script.
Previously, the existing --no-ld-generated-unwind-info option
controlled whether (not just .eh_frame for PLT entries, but also) SFrame
for PLT entries. The new command line option,
--discard-sframe now decouples SFrame from other unwind
formats (like .eh_frame), allowing for more control over the output
binary's SFrame data.
The option is added for architectures that currently support SFrame:
AArch64, s390x, and x86_64.
bfd/
* elf-sframe.c (_bfd_elf_parse_sframe): Mark with SEC_EXCLUDE if
--discard-sframe is in effect.
* elf64-s390.c (elf_s390_create_dynamic_sections): Use
discard_sframe to guard .sframe section creation.
* elfxx-x86.c (_bfd_x86_elf_link_setup_gnu_properties): Likewise.
include/
* bfdlink.h (struct bfd_link_info): Add discard_sframe bitfield.
ld/
* ldlex.h (enum option_values): Add OPTION_NO_LD_SFRAME_INFO.
* lexsup.c (elf_sframe_list_options): New function.
(ld_list_options): Add sframe_info argument. Update callers.
* ld.texi: Update documentation.
* emulparams/sframe-info.sh: New file.
* emultempl/aarch64elf.em: Add --discard-sframe option
listing and handling.
* emulparams/elf64_s390.sh: Likewise.
* emulparams/elf_x86_64.sh: Likewise.
* Makefile.am: Update to handle sframe-info.sh and new list options.
* configure.ac: Handle SFRAME_INFO target variable.
* Makefile.in: Regenerate.
* configure: Regenerate.
ld/testsuite/
* ld-x86-64/x86-64.exp: New test.
* ld-x86-64/sframe-command-line-1.d: New test.
* ld-aarch64/aarch64-elf.exp: New test.
* ld-s390/s390.exp: New test.
* ld-x86-64/x86-64.exp: New test.
* ld-aarch64/sframe-command-line-1.d: New test.
* ld-s390/sframe-command-line-1.d: New test.
* ld-x86-64/sframe-command-line-1.d: New test.
This patch introduces a structural change to the SFrame V3 format. It
shifts the SFrame Function Descriptor Entry (FDE) (a physical entity in
SFrame V2) into a conceptual one in SFrame V3, such that an FDE is now
split into two distinct parts to optimize the binary search table and
data organization:
- FDE Index (sframe_func_desc_idx_v3): This structure contains the
essential indexing information: the function start address offset,
function size in bytes, and the offset to the SFrame FDE
attribute/Frame Row Entries (FREs) area for the function.
- FDE Attributes (sframe_func_desc_attr_v3): The metadata regarding the
function (number and size of FREs, FDE type, and repetition block
size etc.) is moved to a new structure.
On-Disk Layout: In V3, the "Attributes" are now stored immediately
preceding the SFrame FREs for that function. The sfde_func_start_fre_off
now points to the attr structure, and the actual FREs follow immediately
after. IOW, the "Attributes" are now moved to the FRE sub-section,
located immediately preceding the FREs for the respective function.
The above layout has the advantage that:
a) its cleaner with separation between the index elements vs other data
b) the index has better cache locality (by virtue of it being smaller
than the layout in SFrame V2).
c) As the format evolves, the guarantees of alignment for FDE index
are easier to maintain. FDE attr, being in the SFrame FRE
sub-section, carry no guarantees of alignment.
This had been previously suggested and communicated in an earlier
discussion on binutils mailling list
https://inbox.sourceware.org/binutils/29b1f7b0-61ea-410c-8aca-d5dd6115e668@oracle.com/
The read/write paths in sframe.c are updated to account for this split.
sframe_fde_tbl_init now requires access to the FRE buffer to populate
the internal FDE table, as the attributes are no longer resident in the
FDE section.
flip_sframe is refactored into version-specific handlers (_v2 and _v3)
because the endian-swapping logic now differs significantly. In V3, the
iterator must jump from the FDE table to the FRE section to swap the
attributes.
Lastly, the two entities generating SFrame sections (GAS and GNU ld)
both now must _not_ set the sfde_func_start_fre_off to zero, when the
number of FREs is zero. This is because now there will be some valid
attr data at that location.
Backward Compatibility: Due to the need to support readelf/objdump for
SFrame V2 sections, the patch explicitly maintains V2 support via
separate code paths (e.g., flip_sframe_fdes_with_fres_v2)
Note about alignment: Now that the sframe_func_desc_idx_v3 is refactored
out of the conceptual SFrame FDE, SFrame FDE index member elements are
at aligned boundaries again. The alignment property for SFrame FDE was
broken from an ealier patch "[08/36] sframe: gas: libsframe: use
uint16_t for num_fres of FDE" up until this one.
include/
* sframe.h (sframe_func_desc_entry_v3): Remove sfde_func_num_fres,
sfde_func_info, sfde_func_info2, and sfde_func_rep_size. Rename
to sframe_func_desc_idx_v3.
(sframe_func_desc_attr_v3): New SFrame FDE attribute structure.
libsframe/
* sframe.c (sframe_fde_tbl_init): Add argument for FRE buffer.
Read attributes from the FRE section for V3.
(flip_fde_desc): Rename from flip_fde. Check size against
sframe_func_desc_entry_v3.
(flip_fde_attr_v3): New function.
(sframe_decode_fde_desc_v2): New function extracted from
sframe_decode_fde.
(sframe_decode_fde_desc_v3): New function.
(sframe_decode_fde_attr_v3): New function.
(flip_sframe_fdes_with_fres_v2): New function for V2 flipping.
(flip_sframe_fdes_with_fres_v3): New function for V3 flipping.
(flip_sframe): Dispatch to version-specific flip functions.
(sframe_decode): Pass FRE buffer to sframe_fde_tbl_init.
(sframe_decoder_get_offsetof_fde_start_addr): Adjust for subset
of sframe_func_desc_entry_v3 restructured into
sframe_func_desc_idx_v3.
(sframe_encoder_get_offsetof_fde_start_addr): Likewise.
(sframe_find_fre): Skip attribute size to find FREs in V3.
(sframe_decoder_get_fre): Likewise.
(sframe_decoder_get_fres_buf): Likewise.
(sframe_encoder_add_fre): Add attribute size to byte count.
(sframe_encoder_add_fres_buf): Read attributes from buffer.
(sframe_encoder_write_fde): Write only FDE index fields.
(sframe_encoder_write_func_attr): New function.
(sframe_encoder_write_sframe): Write FDE attributes before FREs.
gas/
* gen-sframe.c (output_sframe_funcdesc): Do not reset
sfde_func_start_fre_off to zero when zero num FREs.
(output_sframe_func_desc_attr): New refactored out function.
(output_sframe_internal): Invoke output_sframe_func_desc_attr.
libsframe/testsuite/
* libsframe.decode/DATA2: Regenerate data file.
At link time, in _bfd_elf_merge_section_sframe (), it suffices to bring
over the all per-function stack trace metadata (all FREs) as a blob into
the SFrame encoder object. There is no need to "decode" each SFrame
FRE, only to add them in a serial fashion.
This is an optimization, and not directly related to any SFrame V3
related changes to the specification. This should also bring us a step
closer to supporting SFrame for targets which use linker relaxations.
Removing the need to decode the input FREs can allow the linker to
simply use the available set of FREs from (relocated) contents. To
support targets using linker relaxations in SFrame, other changes in the
SFrame parse functionality time may also be necessary, but this brings
us just a step closer.
Add two new APIs to accomplish this:
- sframe_decoder_get_fres_buf, and
- sframe_encoder_add_fres_buf
bfd/
* elf-sframe.c (_bfd_elf_merge_section_sframe): Get all FRE data
and add it all in bulk.
libsframe/
* libsframe.ver: Add new APIs.
* sframe.c (sframe_buf_fre_entry_size): New internal API to get
size of one SFrame FRE at the indicated buffer location, without
fully "decoding" the SFrame FRE.
(sframe_decoder_get_fres_buf): New definition.
(sframe_encoder_add_fres_buf): New definition.
include/
* sframe-api.h (sframe_decoder_get_fres_buf): New declaration.
(sframe_encoder_add_fres_buf): New declaration.
For FDE type SFRAME_FDE_TYPE_FLEX, the offsets are not only laid out
differently, they also have different encoding:
- first data item is of unsigned type, it indicates the "Control Word"
- second data item is of signed type, it indicates the "Offset Word"
(The usage of "Word" above is colloquial, does not indicate a machine word of
a specific size.)
Adjust the APIs in libsframe to get stack frame offsets by adding a new
argument type. Also add a new API to read the data items as unsigned
types of the specified size: sframe_get_fre_udata.
At the moment, like the generation routines in GAS, the textual dump
routines in sframe-dump.c are also unaware of the FDE type
SFRAME_FDE_TYPE_FLEX. In the next commits, these capabilities will be
added.
include/
* sframe-api.h (MAX_NUM_STACK_OFFSETS): Increase the number of
stack offsets to 6 to accommodate the FDE type
SFRAME_FDE_TYPE_FLEX.
(sframe_get_fre_udata): New declaration.
(sframe_fre_get_cfa_offset): Add new arg.
(sframe_fre_get_fp_offset): Likewise.
(sframe_fre_get_ra_offset): Likewise.
libsframe/
* libsframe/sframe-dump.c (dump_sframe_func_with_fres): Pass
SFRAME_FDE_TYPE_DEFAULT for FDE type.
* sframe.c (sframe_fre_get_cfa_offset): Handle FDE type.
(sframe_fre_get_fp_offset): Likewise.
(sframe_fre_get_ra_offset): Likewise.
* libsframe/libsframe.ver: Add new API sframe_get_fre_udata.
libsframe/testsuite/
* libsframe.find/findfre-1.c: Pass SFRAME_FDE_TYPE_DEFAULT for
FDE type.
* libsframe.find/findfunc-1.c: Likewise.
* libsframe.find/plt-findfre-1.c: Likewise.
* libsframe.find/plt-findfre-2.c: Likewise.
In SFrame V2, we did use the the term 'FDE Type' for the two designated
'PC Type' for the SFrame FDEs (SFRAME_FDE_TYPE_PCINC,
SFRAME_FDE_TYPE_PCMASK). In hindsight, 'FDE Type' was an inappropriate
term for the said intent. Fix this terminology by defining two new
constants:
- SFRAME_V3_FDE_PCTYPE_MASK
- SFRAME_V3_FDE_PCTYPE_INC
The old constants from V2 (SFRAME_FDE_TYPE_PCINC,
SFRAME_FDE_TYPE_PCMASK) remain, but are now unused in the codebase.
The term 'FDE Type' should be used for the actual FDE Types. In a
subsequent commit, we will add SFRAME_FDE_TYPE_FLEX FDE Type for SFrame
V3.
bfd/
* elf64-s390.c (_bfd_s390_elf_create_sframe_plt): Rename
inappropriate SFRAME_FDE_TYPE_PCINC to SFRAME_V3_FDE_PCTYPE_INC.
* elfxx-x86.c (_bfd_x86_elf_create_sframe_plt): Likewise. Also
rename inappropriate SFRAME_FDE_TYPE_PCMASK to
SFRAME_V3_FDE_PCTYPE_MASK.
gas/
* gen-sframe.c (output_sframe_funcdesc): Likewise.
* sframe-opt.c (sframe_convert_frag): Likewise.
libsframe/
* sframe-dump.c (dump_sframe_func_with_fres): Likewise.
* sframe.c (sframe_fre_check_range_p): Likewise.
(sframe_fde_create_func_info): Likewise.
libsframe/testsuite/
* libsframe.encode/encode-1.c: Likewise.
* libsframe.find/findfre-1.c: Likewise.
* libsframe.find/findfunc-1.c: Likewise.
* libsframe.find/plt-findfre-1.c: Likewise.
* libsframe.find/plt-findfre-2.c: Likewise.
In SFrame V2, the FDE representation caters to the most common cases of
stack trace metadata:
- CFA is SP/FP based,
- FP/RA offsets, if present are CFA based (except some cases in s390x
where reg can be encoded).
Introduce an additional FDE type SFRAME_FDE_TYPE_FLEX, which can encode
a more flexible set of CFA, FP and RA recovery rules. Some of the
patterns supported include:
- CFA may be non-SP/FP based.
- CFA, FP may encode dereferencing of register after offset adjustment
- RA may be in a non-default register.
The important bit here is that since SFrame does not track all
callee-saved registers, the above-mentioned recovery rules must only be
done for topmost frames (by the stack tracer).
Adding a new FDE type does have implications for a stack tracer in that
it needs to:
- Check the FDE type before interpreting the variable length bytes
trailing the SFrame FRE header as stack offsets.
- If the FDE type is SFRAME_FDE_TYPE_FLEX, and the
recovery rules employ the use of any non-SP/FP based register, the
stack tracer must proceed only if it is the topmost frame on stack.
For CFA, RA, and FP, up to two "offsets" may be used. The two offsets
represent the information as follows:
- (minimum 8-bit) offset1 to encode register like:
(regnum << 3) | unused << 2 | deref << 1 | reg_p (=1)
- offset2 to encode offset: offset
reg_p = 1 indicates a register, reg_p = 0 indicates CFA.
The offsets are in the usual order: CFA, RA, FP if present.
For example, for FP/RA tracking,
a) If the reg is REG1 for FP/RA tracking,
- Encoding:
+ offset1 to encode register: (REG1 << 3) | unused << 2 | deref << 1 | reg_p (=1)
+ offset2 to encode offset: offset
- Action:
+ if deref, FP/RA = \*(REG1 + offset) (e.g., seen for FP recovery
with certain DRAP patterns on x86_64)
+ if no deref, FP/RA = REG1 + offset
b) If the reg is CFA for FP/RA tracking,
- Encoding:
+ [=Effectively Padding] offset1 to encode register:
(( 0 << 3 ) | unused << 2 | 0 << 1 | reg_p (=0))
+ offset2 to encode offset: offset
- Action:
+ if deref, FP/RA = *(CFA + offset)
+ if no deref, FP/RA = CFA + offset (pattern shouldnt be seen for
RA)
Next for CFA tracking,
- Action:
+ if deref, CFA = *(reg + offset) (e.g., seen for CFA recovery in
some stack realignment patterns on AMD64)
+ if no deref, CFA = reg + offset (e.g., for .cfi_def_cfa 2, 8, or
.cfi_def_cfa 10, 0)
Expected usage of this FDE type is quite low (DRAP on x86_64).
NB: In SFrame V2, we did use the the term 'FDE Type' for the two
designated 'PC Type' for the SFrame FDEs (SFRAME_FDE_TYPE_PCINC,
SFRAME_FDE_TYPE_PCMASK). In hindsight, 'FDE Type' was inappropriate
term. In a subsequent commit, we will fix this terminology for SFrame
V3.
include/
* sframe.h (SFRAME_FDE_TYPE_FLEX): New SFrame FDE type.
(SFRAME_V3_FDE_TYPE_MASK): New constant definition.
(SFRAME_V3_FDE_TYPE): New macro definition.
(SFRAME_V3_SET_FDE_TYPE): Likewise.
(SFRAME_V3_FLEX_FDE_REG_ENCODE): Macro to encode register in the
SFrame offset data.
(SFRAME_V3_FLEX_FDE_OFFSET_REG_NUM): New definition.
(SFRAME_V3_FLEX_FDE_OFFSET_REG_DEREF_P): Likewise.
(SFRAME_V3_FLEX_FDE_OFFSET_REG_P): Likewise.
The existing field func_info (in the SFrame FDE) is used to convey important
information around the encoding and interpretation of the rest of the
stack trace data for the respective SFrame FDE: the SFrame FRE type,
SFrame FDE PC type, etc.
Currently there is 1 bit left for AArch64, and 2 bits for AMD64, s390x
(and other future ABIs to be supported). Provision some additional
space now (specifically an additional 8-bits) for future needs for V3
and beyond.
Compared to V2, this now increases the size of SFrame FDE by 1 byte in
V3. In this patch, the additional func_info2 byte is not used
functionally yet. Hence, rather mechanical changes in libsframe, bfd
and libsframe/testsuite accompany. We will put func_info2 into use in a
later patch by reserving 5 of these bits for SFrame FDE types.
With the addition of a new byte for additional func info (func_info2),
add a new arg to allow usecases like textual dumper to get all data
members in one API: sframe_decoder_get_funcdesc_v3. To keep the APIs
symmetric looking, add new arg to sframe_encoder_add_funcdesc_v3 too.
Since bfd uses these APIs, carry out the mechanical change in the
respective APIs too. And of course, the testsuite which exercises these
APIs.
bfd/
* elf-sframe.c (_bfd_elf_merge_section_sframe): Get and set
func_info2.
* elf64-s390.c (_bfd_s390_elf_create_sframe_plt): Pass 0 for
func_info2 for SFrame FDE for PLT.
* elfxx-x86.c (_bfd_x86_elf_create_sframe_plt): Likewise.
gas/
* gen-sframe.c (output_sframe_funcdesc): Emit the uint8_t for
func_info2.
libsframe/
* sframe-dump.c (dump_sframe_func_with_fres):
* sframe.c (sframe_fde_tbl_init): Handle the new additional
member.
(sframe_encoder_write_fde): Likewise.
* sframe.c (sframe_decoder_get_funcdesc_v3): Update func_info2.
libsframe/testsuite/
* libsframe.decode/DATA2: Update data file with SFrame section
data.
* libsframe.encode/encode-1.c: Pass 0 for func_info2 arg.
* libsframe.find/findfre-1.c: Likewise.
* libsframe.find/findfunc-1.c: Likewise.
* libsframe.find/plt-findfre-1.c: Likewise.
* libsframe.find/plt-findfre-2.c: Likewise.
include/
* sframe.h: Add new uint8_t sfde_func_info2 to
sframe_func_desc_entry_v3.
* sframe-api.h (sframe_decoder_get_funcdesc_v3): New arg.
(sframe_encoder_add_funcdesc_v3): Likewise.