ld: bfd: sframe: Update section size also for relocatable links
For relocatable links the output .sframe section size may be wrong.
This can be observed when dumping the SFrame information from the x86-64
sframe-reloc-1 test:
When running the x86-64 test cross build on a big-endian system, such
as s390x, objdump and readelf fail to dump the SFrame information with
the following error message:
Error: SFrame decode failure: Buffer does not contain SFrame data.
This is because the following check in flip_sframe() fails, which gets
only invoked if the endianness of the SFrame data is different from the
host system one:
/* All FDEs and FREs must have been endian flipped by now. */
if ((j != ihp->sfh_num_fres) || (bytes_flipped != (buf_size - hdrsz)))
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
NEWS: sframe: mention new semantics for SFrame FDE function start addr
The SFrame FDE's function start address is always emitted as follows by
GAS and ld: it is the offset of the start PC of the respective function
from the FDE field itself.
GAS and ld will emit a flag SFRAME_F_FDE_FUNC_START_ADDR_PCREL set to 1
when emitting the field in this encoding.
binutils/
* NEWS: Announce the change of encoding for SFrame FDE func
start addr field.
Indu Bhagat [Thu, 6 Feb 2025 21:38:04 +0000 (13:38 -0800)]
ld: bfd: sframe: fix incorrect r_offset in RELA entries
PR/32666 Incorrect .rela.sframe when using ld -r
Input SFrame sections are merged using _bfd_elf_merge_section_sframe (),
which clubs all SFrame FDEs together in one blob and all SFrame FREs in
another. This, of course, means the offset of an SFrame FDE in the output
section cannot be simply derived from the output_offset of the sections.
Fix this by providing _bfd_elf_sframe_section_offset () which returns
the new offset of the SFrame FDE in the merged SFrame section.
Unlike EH_Frame sections, which also use the _bfd_elf_section_offset (),
to update the r_offset, SFrame sections have distinct merging semantics.
In case of SFrame, the SFrame FDE will not simply sit at location
"sec->output_offset + offset of SFrame FDE in sec". Recall that information
layout in an SFrame section is as follows:
SFrame Header
SFrame FDE 1
SFrame FDE 2
...
SFrame FDEn
SFrame FREs (Frame Row Entries)
Note how the SFrame FDEs and SFrame FREs are clubber together in groups
of their own.
Next, also note how the elf_link_input_bfd () does a:
irela->r_offset += o->output_offset;
This, however, needs to be avoided for SFrame sections because the
placement of all FDEs is at the beginning of the section. So, rather than
conditionalizing this as follows:
if (o->sec_info_type != SEC_INFO_TYPE_SFRAME)
irela->r_offset += o->output_offset;
the implementation in _bfd_elf_sframe_section_offset () does a reverse
adjustment, so that the generic parts of the linking process in
elf_link_input_bfd () are not made to do SFrame specific adjustments.
Add a new enum to track the current state of the SFrame input section
during the linking process (SFRAME_SEC_DECODED, SFRAME_SEC_MERGED) for
each input SFrame section. This is then used to assert an assumption
that _bfd_elf_sframe_section_offset () is being used on an input SFrame
sections which have not been merged (via
_bfd_elf_merge_section_sframe ()) yet.
bfd/
* elf-bfd.h: New declaration.
* elf-sframe.c (_bfd_elf_sframe_section_offset): New definition.
* elf.c (_bfd_elf_section_offset): Adjust offset if SFrame
section.
ld/testsuite/
* ld-x86-64/x86-64.exp: New test.
* ld-x86-64/sframe-reloc-1.d: New test.
---
Notes:
This patch was previously reviewed.
https://inbox.sourceware.org/binutils/d914ea1f-6c11-4ef5-ac15-404fd7afd26d@suse.com/
There was a comment on moving this
if (o->sec_info_type != SEC_INFO_TYPE_SFRAME)
irela->r_offset += o->output_offset;
to inside the _bfd_elf_sframe_section_offset () or keep it in
elf_link_input_bfd () with some code comments. Although, I think
keeping it deliberatly out of _bfd_elf_sframe_section_offset () was
clearer as that helped keep the contract of _bfd_elf_section_offset ()
symmetrical across section types. That said, taking the overall
opinions shared in the previous review, I have moved the stub inside
_bfd_elf_sframe_section_offset (). But if opinions have changed, I am
happy to bring the conditional back to elf_link_input_bfd ().
Indu Bhagat [Mon, 26 May 2025 22:06:31 +0000 (15:06 -0700)]
bfd: gas: ld: libsframe: adopt new encoding for FDE func start addr field
This patch convenes a set of changes in bfd, gas, ld, libsframe towards
moving to the new encoding for the 'sfde_func_start_address' field in
SFrame FDE.
First, gas must now mark all SFrame sections with the new flag
SFRAME_F_FDE_FUNC_START_ADDR_PCREL. gas was already emitting the field
in the said encoding.
* gas/gen-sframe.c (output_sframe_internal): Emit the flag
SFRAME_F_FDE_FUNC_START_ADDR_PCREL.
Similarly for ld, adopt the new semantics of sfde_func_start_address
consistently. This means:
- When merging SFrame sections, check that all input SFrame sections
have the SFRAME_F_FDE_FUNC_START_ADDR_PCREL flag set. If the check
fails, ld errors out.
- When merging SFrame sections, keep even the in-memory contents of
the FDE function start address (buffer passed to libsframe
sframe_encoder_write () for writing out) are encoded in the new
semantics. While it is, in theory, possible that instead of doing this
change here, we adjust the value of sfde_func_start_address at the final
write (sframe_encoder_write) time. But latter is not favorable for
maintenanance and may be generally confusing for developers.
- When creating SFrame for PLT entries, emit flag
SFRAME_F_FDE_FUNC_START_ADDR_PCREL.
bfd/
* elf-sframe.c (_bfd_elf_merge_section_sframe): Check for flag
SFRAME_F_FDE_FUNC_START_ADDR_PCREL set for all input bfds. If
not, error out. Also, adopt the new semantics of function start
address encoding.
* bfd/elfxx-x86.c (_bfd_x86_elf_create_sframe_plt): Emit flag
SFRAME_F_FDE_FUNC_START_ADDR_PCREL.
Next, for dumping SFrame sections, now that we are emitting the same
encoding in GAS, non-relocatable and relocatable SFrame links, it is the
time to set relocate to TRUE in debug_displays[].
binutils/
* dwarf.c (struct dwarf_section_display): Allow sframe sections
to now be relocated.
gas/testsuite/
* gas/cfi-sframe/cfi-sframe-aarch64-pac-ab-key-1.d: Update the
test. Relocatable SFrame sections now display non-zero value
(appropriate function start address).
Now, as the SFrame sections on-disk and in-memory use the new semantics of
sfde_func_start_address encoding (i.e., function start address is the
offset from the sfde_func_start_address field to the start PC), the
calculation to make it human readable (i.e., relatable to the addresses
in .text sections) needs adjustment.
libsframe/
* sframe-dump.c (dump_sframe_func_with_fres): Adjust the
function start address for dumping.
Now that both the emission of the new encoding, and the relocation of
sections before dumping them is in place, it is time to adjust the
testcases.
Naturally, the change of semantics for 'SFrame FDE function start address'
has consequences on the implementation in libsframe. As per the new
semantics:
- Function start address in the SFrame FDE (sfde_func_start_address)
is an offset from the FDE function start address field to the start
PC of the associated function.
Note that, the libsframe library brings the SFrame section contents into
its own memory to create a sframe_decoder_ctx object via sframe_decode
(). Many internal and user-interfacing APIs then use sframe_decoder_ctx
object to interact and fulfill the work.
In context of changing semantics for sfde_func_start_address, following
relevant examples may help understand the impact:
- sframe_find_fre () finds a the SFrame stack trace data (SFrame FRE)
given a lookup offset (offset of lookup_pc from the start of SFrame
section). Now that the sfde_func_start_address includes the
distance from the sfde_func_start_address field to the start of
SFrame section itself, the comparison checks of
sfde_func_start_address with the incoming lookup offset need
adjustment.
- Some internal functions (sframe_get_funcdesc_with_addr_internal ()
finds SFrame FDE by using binary seach comparing
sfde_func_start_address fields, etc.) need adjustments.
- sframe_encoder_write () sorts the SFrame FDEs before writing out
the SFrame data. Sorting of SFrame FDE via the internal function
sframe_sort_funcdesc() needs adjustments: the new encoding of
sfde_func_start_address means the distances are not from the same
anchor, so cannot be sorted directly.
This patch takes the approach of adding a new internal function:
- sframe_decoder_get_secrel_func_start_addr (): This function returns
the offset of the start PC of the function from the start of SFrame
section, i.e., it gives a section-relative offset.
As the sframe_decoder_get_secrel_func_start_addr () API needs the value
of the function index in the FDE list, another internal API needs
sframe_fre_check_range_p () adjustments too.
Sorting the FDEs (via sframe_sort_funcdesc ()) is done by first bringing
all offsets in sfde_func_start_address relative to start of SFrame
section, followed by sorting, and then readjusting the offsets accroding
to the new position in the FDE list.
TBD:
- Version bump libsframe. The change in encoding of
sfde_func_start_address means the APIs sframe_encoder_add_funcdesc ()
and sframe_find_fre () etc. are now backwards incompatible with previous
releases. If this change is backported, we need to reserve a version
bump for a backport too I think.
libsframe/
* sframe.c (sframe_decoder_get_secrel_func_start_addr): New
static function.
(sframe_fre_check_range_p): Adjust the interface a bit.
(sframe_get_funcdesc_with_addr_internal): Use
sframe_decoder_get_secrel_func_start_addr () when comparing
sfde_func_start_address with user input offset.
(sframe_find_fre): Adopt the new semantics.
(sframe_sort_funcdesc): Likewise.
For the libsframe testsuite, use the new encoding for FDE func start
addr: distance between the FDE sfde_func_start_address field and the
start PC of the function itself.
Use SFRAME_F_FDE_FUNC_START_ADDR_PCREL flag, though the sframe_encode ()
interface in libsframe applies no sanity checks for the encoding itself.
libsframe/testsuite/
* libsframe.find/findfre-1.c: Adjust to use the new
SFRAME_F_FDE_FUNC_START_ADDR_PCREL specific encoding.
* libsframe.find/findfunc-1.c: Likewise.
* libsframe.find/plt-findfre-1.c: Likewise.
Indu Bhagat [Mon, 26 May 2025 22:05:26 +0000 (15:05 -0700)]
objdump, readelf: sframe: apply relocations before textual dump
PR libsframe/32589 - function start address is zero in SFrame section dump
Currently, readelf and objdump display the SFrame sections in ET_REL
object files with function start addresses of each function as 0. This
makes it difficult to correlate SFrame stack trace information with the
individual functions in the object file.
For objdump, use the dump_dwarf () interface to dump SFrame section.
Similarly, for readelf, use the display_debug_section () interface to
dump SFrame section. These existing interfaces (for DWARF debug
sections) already support relocating the section contents before
dumping, so lets use them for SFrame sections as well.
When adding a new entry for SFrame in debug_option_table[], use char
'nil' and the option name of "sframe-internal-only". This is done so
that there is no additional (unnecessary) user-exposed ways of dumping
SFrame sections. Additionally, we explicitly disallow the
"sframe-internal-only" from external/user input in --dwarf (objdump).
Similarly, "sframe-internal-only" is explicitly matched and disallowed
from --debug-dump (readelf).
For objdump and readelf, we continue to keep the same error messaging as
earlier:
$ objdump --sframe=sframe bubble_sort.o
...
No sframe section present
$ objdump --sframe=.sfram bubble_sort.o
...
No .sfram section present
$ objdump --sframe=sframe-internal-only sort
...
No sframe-internal-only section present
Similarly for readelf:
$ readelf --sframe= bubble_sort.o
readelf: Error: Section name must be provided
$ readelf --sframe=.sfram bubble_sort.o
readelf: Warning: Section '.sfram' was not dumped because it does not exist
$ readelf --sframe=sframe bubble_sort.o
readelf: Warning: Section 'sframe' was not dumped because it does not exist
PS: Note how this patch adds a new entry to debug_displays[] with a
relocate value set to FALSE. This will be set to TRUE in a subsequent
patch ("bfd: gas: ld: libsframe: emit func start addr field as an offset
from FDE") when fixes are made to emit the value of the
'sfde_func_start_address' field in the new encoding
SFRAME_F_FDE_FUNC_START_ADDR_PCREL across gas and ld.
binutils/
* dwarf.c (display_sframe): New definition.
(dwarf_select_sections_all): Enable SFrame section too.
(struct dwarf_section_display): Add entry for SFrame section.
* dwarf.h (enum dwarf_section_display_enum): Add enumerator for
SFrame.
* objdump.c (dump_section_sframe): Remove.
(dump_sframe_section): Add new definition.
(dump_bfd): Use dump_sframe_section.
* binutils/readelf.c (dump_section_as_sframe): Remove.
---
This patch was previously reviewed at part of other series previously:
https://inbox.sourceware.org/binutils/20250308073853.78738-3-indu.bhagat@oracle.com/
The review comments have been addressed in this patch. The setting of
relocate to FALSE for the new record is the new diff.
Indu Bhagat [Tue, 27 May 2025 05:12:53 +0000 (22:12 -0700)]
doc: sframe: add documentation for SFRAME_F_FDE_FUNC_START_ADDR_PCREL
Also, update the section "Changes from Version 1 to Version 2" to
include the specification of the new flag
SFRAME_F_FDE_FUNC_START_ADDR_PCREL as an errata release to the SFrame
Version 2 specification.
libsframe/doc/
* sframe-spec.texi: Add details about the new flag.
include: libsframe: define new flag SFRAME_F_FDE_FUNC_START_ADDR_PCREL
Add a new flag SFRAME_F_FDE_FUNC_START_ADDR_PCREL to SFrame stack trace
format. If set, this flag indicates that the function start address
field (sfde_func_start_address) is the offset to the function start
address from the SFrame FDE function start address field itself.
Such an encoding is friendlier to the exisitng PC-REL relocations
available in the ABIs supported in SFrame: AMD64 (R_X86_64_PC32) and
AArch64 (R_AARCH64_PREL32). In subsequent patches, we will make the
implementation in gas and ld to both:
- emit the values in the same (above-mentioned) encoding uniformly.
- set the flag SFRAME_F_FDE_FUNC_START_ADDR_PCREL in the SFrame header
for consumers to be able to distinguish.
include/
* sframe.h (SFRAME_F_FDE_FUNC_START_ADDR_PCREL): New definition.
libsframe/
* sframe-dump.c (MAX_NUM_FLAGS, flags_helper): Update to include
the new flag.
* sframe.c (sframe_header_sanity_check_p): Use uint8_t.
Indu Bhagat [Thu, 22 May 2025 22:24:47 +0000 (15:24 -0700)]
include: libsframe: add APIs for offsetof FDE func start addr field
These APIs will be later used by the linker to arrange SFrame FDEs in
the output SFrame section.
include/
* sframe-api.h (sframe_decoder_get_offsetof_fde_start_addr): New
declaration.
(sframe_encoder_get_offsetof_fde_start_addr): Likewise.
libsframe/
* libsframe.ver: List the new APIs.
* sframe.c (sframe_decoder_get_offsetof_fde_start_addr): New
definition.
(sframe_encoder_get_offsetof_fde_start_addr): Likewise.
Indu Bhagat [Wed, 21 May 2025 04:22:21 +0000 (21:22 -0700)]
libsframe: refactor code for dumping section flags
To prepare code for accommodating new flag additions easily as the
format evolves.
libsframe/
* sframe-dump.c (SFRAME_HEADER_FLAGS_STR_MAX_LEN): Rename from.
(struct dump_flags_helper): New helper struct definition.
(dump_sframe_header_flags): .. to here. New definition.
(SFRAME_FLAGS_STR_MAX_LEN): Rename to.
(MAX_NUM_FLAGS): New definition.
(dump_sframe_header): Move some implementation from here ..
include: libsframe: add APIs for SFrame header flags
Add new APIs, one each for getting flags from the SFrame decoder and
SFrame encoder context objects respectively.
These will later be used by the linker to uniformly access the flags,
given the SFrame decoder and SFrame encoder objects.
Use the new API, where applicable, within libsframe.
include/
* sframe-api.h (sframe_decoder_get_flags): New declaration.
(sframe_encoder_get_flags): Likewise.
libsframe/
* libsframe.ver: List new APIs.
* sframe.c (sframe_decoder_get_flags): New definition.
(sframe_encoder_get_flags): Likewise.
(sframe_get_funcdesc_with_addr_internal): Use the new API.
(sframe_encoder_get_flags): Likewise.
(sframe_encoder_write_sframe): Likewise.
gdb/testsuite: Clarify -lbl option in gdb_test_multiple
I was a bit confused about the -lbl option in gdb_test_multiple, and needed
to read its implementation to determine that it would be useful for my
needs. Explicitly mention what the option does and why it's useful to
hopefully help other developers.
Reviewed-By: Keith Seitz <keiths@redhat.com> Approved-By: Andrew Burgess <aburgess@redhat.com>
gdb/testsuite: Fix flakiness in gdb.base/default.exp
The Linaro CI runs the GDB testsuite using the read1 tool, which
significantly increases the time it takes DejaGNU to read inferior output.
On top of that sometimes the test machine has higher than normal load,
which causes tests to run even slower.
Because gdb.base/default.exp tests some verbose commands such as "info
set", it sometimes times out while waiting for the complete command
output when running in the Linaro CI environment.
Fix this problem by consuming each line of output from the most verbose
commands with gdb_test_multiple's -lbl (line-by-line) option — which
causes DejaGNU to reset the timeout after each match — and also by
breaking up regular expressions that try to match more than 2000
characters (the default Expect buffer size) in one go into multiple
matches.
Some tests use the same regular expression, so I created a procedure for
them. This is the case for "i" / "info", "info set" / "show", and "set
print" tests.
The tests for "show print" don't actually test their output, so this
patch improves them by checking some lines of the output.
Reviewed-By: Keith Seitz <keiths@redhat.com> Approved-By: Andrew Burgess <aburgess@redhat.com>
Alan Modra [Mon, 26 May 2025 02:16:05 +0000 (11:46 +0930)]
ALPHA_R_OP_STORE
In commit db4ab410dec3 I rewrote OP_STORE handling to support writing
near the end of a section. The rewrite had some bugs, fixed in commit 3e02c4891dcb. However I wasn't entirely happy with the code writing
the bitfield:
- it doesn't support 64-bit fields with a bit offset,
- the code is duplicated and inelegant,
- the stack ought to be popped whenever seeing one of these relocs,
even if the reloc can't be applied.
This patch fixes all of the above.
In addition, it is clear from the OP_STORE description in the ABI that
a 64-bit field is encoded as 0 in r_size, so I've decoded that in
alpha_ecoff_swap_reloc_in. The aborts there are not appropriate as
they can be triggered by user input (fuzzed object files). Also,
stack underflow wasn't checked in alpha_relocate_section.
* coff-alpha.c (alpha_ecoff_swap_reloc_in): Replace aborts
with asserts. Decode ALPHA_R_OP_STORE r_size of zero.
(write_bit_field): New function.
(alpha_ecoff_get_relocated_section_contents): Use it.
(alpha_relocate_section): Here too. Catch stack underflow.
Jens Remus [Mon, 26 May 2025 18:02:47 +0000 (11:02 -0700)]
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:
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.
Jens Remus [Mon, 26 May 2025 18:02:29 +0000 (11:02 -0700)]
libsframe: stop search for SFrame FRE if its start IP is greater than PC
The SFrame FREs for an SFrame FDE are sorted on their start address.
Therefore the linear search for a matching SFrame FRE can be stopped,
if its start address is greater than the searched for PC.
libsframe/
* sframe.c (sframe_find_fre): Stop search if FRE's start IP is
greater than PC.
Jens Remus [Mon, 26 May 2025 18:01:14 +0000 (11:01 -0700)]
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.
Indu Bhagat [Mon, 26 May 2025 17:54:06 +0000 (10:54 -0700)]
libsframe: fix issue finding FRE in PCMASK type SFrame FDEs
SFrame FDEs of type SFRAME_FDE_TYPE_PCMASK are used for repetitive code
patterns, e.g., pltN entries. For SFrame FDEs of type
SFRAME_FDE_TYPE_PCMASK, sframe_fre_check_range_p erroneously tested the
given PC instead of the masked PC offset from function start address.
Therefore it only worked correctly by chance, e.g., if the function start
address was aligned on the repetition block size.
For regular SFrame FDEs the PC offset from function start address must
be within a SFrame FRE's start IP offset and end IP offset. For SFrame
FDEs of type SFRAME_FDE_TYPE_PCMASK, the masked PC offset must be within
that range.
SFrame FRE start/end IP offsets are relative to the SFrame FDE function
start address. For regular SFrame FDEs, the PC offset from function
start address must be within a SFrame FRE's start IP offset and end IP
offset. For SFRAME_FDE_TYPE_PCMASK type FDEs, the masked PC offset must
be within that range.
Exercise the testcase for a variety of placements; without the fix some
of these tests will fail. Also, make the testcase itself easier to
follow by adding appropriate vars where applicable.
libsframe/
* sframe.c (sframe_fre_check_range_p): Fix logic for
SFRAME_FDE_TYPE_PCMASK type FDE.
libsframe/testsuite/
* libsframe.find/plt-findfre-1.c: Adjust the test for a variety
of placements of .sframe and .plt.
if (uia < uib)
return true;
if (uia > uib)
return false;
...
we compare pointers to struct program_space, which gives unstable sorting
results.
The assumption is that this doesn't matter, but as PR32202 demonstrates,
sometimes it does.
While PR32202 is fixed elsewhere, it seems like a good idea to stabilize this
comparison, because it comes at a small cost and possibly prevents
hard-to-reproduce user-visible ordering issues.
Fix this by comparing the program space IDs instead of the pointers.
Likewise in compare_msymbols.
Tested on x86_64-linux.
Reviewed-By: Guinevere Larsen <guinevere@redhat.com> Approved-By: Andrew Burgess <aburgess@redhat.com>
Tom de Vries [Mon, 26 May 2025 13:15:31 +0000 (15:15 +0200)]
[gdb/breakpoints] Stabilize info breakpoints output
With test-case gdb.multi/pending-bp-del-inferior.exp, occasionally I run into:
...
(gdb) info breakpoints^M
Num Type Disp Enb Address What^M
3 dprintf keep y <MULTIPLE> ^M
printf "in foo"^M
3.1 y 0x004004dc in foo at $c:21 inf 2^M
3.2 y 0x004004dc in foo at $c:21 inf 1^M
(gdb) FAIL: $exp: bp_pending=false: info breakpoints before inferior removal
...
The FAIL happens because the test-case expects:
- breakpoint location 3.1 to be in inferior 1, and
- breakpoint location 3.2 to be in inferior 2
but it's the other way around.
I managed to reproduce this with a trigger patch in
compare_symbols from gdb/linespec.c:
...
uia = (uintptr_t) a.symbol->symtab ()->compunit ()->objfile ()->pspace ();
uib = (uintptr_t) b.symbol->symtab ()->compunit ()->objfile ()->pspace ();
- if (uia < uib)
+ if (uia > uib)
return true;
- if (uia > uib)
+ if (uia < uib)
return false;
...
The order enforced by compare_symbols shows up in the "info breakpoints"
output because breakpoint::add_location doesn't enforce an ordering for equal
addresses:
...
auto ub = std::upper_bound (m_locations.begin (), m_locations.end (),
loc,
[] (const bp_location &left,
const bp_location &right)
{ return left.address < right.address; });
m_locations.insert (ub, loc);
...
Fix this by using new function bp_location_is_less_than
(forwarding to bp_location_ptr_is_less_than) in breakpoint::add_location.
Tom de Vries [Mon, 26 May 2025 13:15:31 +0000 (15:15 +0200)]
[gdb/breakpoints] Rename bp_location_is_less_than to bp_location_ptr_is_less_than
In breakpoint.c, we have:
...
/* A comparison function for bp_location AP and BP being interfaced to
std::sort. Sort elements primarily by their ADDRESS (no matter what
bl_address_is_meaningful says), secondarily by ordering first
permanent elements and tertiarily just ensuring the array is sorted
stable way despite std::sort being an unstable algorithm. */
static int
bp_location_is_less_than (const bp_location *a, const bp_location *b)
...
There are few problems here:
- the return type is int. While std::sort allows this, because int is
convertible to bool, it's clearer to use bool directly,
- it's not abundantly clear from either function name or comment that we can
use this to sort std::vector<bp_location *> but not
std::vector<bp_location>, and
- the comment mentions AP and BP, but there are no such parameters.
Fix this by:
- changing the return type to bool,
- renaming the function to bp_location_ptr_is_less_than and mentioning
std::vector<bp_location *> in the comment, and
- updating the comment to use the correct parameter names.
Tested on x86_64-linux.
Reviewed-By: Guinevere Larsen <guinevere@redhat.com> Approved-By: Andrew Burgess <aburgess@redhat.com>
Janne Ramstedt [Sun, 25 May 2025 17:17:20 +0000 (20:17 +0300)]
alpha, bfd: Fixes for ALPHA_R_OP_STORE
ALPHA_R_OP_STORE copies one byte too many and also will cause out of
range error when it tries to copy from the end of section. Since
"endbyte" is already rounded to next full byte, there is enough bits
to copy and the additional "+ 1" is erroneous in bytes count. I also
believe size is incorrectly decreased.
Simon Marchi [Fri, 23 May 2025 16:30:52 +0000 (12:30 -0400)]
gdb/solib-svr4: check that solib is SVR4 in tls_maybe_fill_slot and tls_maybe_erase_slot
Functions tls_maybe_fill_slot and tls_maybe_erase_slot blindly assume
that the passe solibs come from solib-svr4. This is not always the
case, because they are called even on the systems where the solib
implementation isn't solib-svr4. Add some checks to return early in
that case.
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=32990
Change-Id: I0a281e1f4826aa1914460c2213f0fae1bdc9af7c Tested-By: Hannes Domani <ssbssa@yahoo.de> Approved-By: Andrew Burgess <aburgess@redhat.com>
Tom de Vries [Sat, 24 May 2025 08:27:12 +0000 (10:27 +0200)]
[gdb/build] Fix unused var in lookup_dwo_unit_in_dwp
On x86_64-linux, with gcc 7.5.0 I ran into a build breaker:
...
gdb/dwarf2/read.c: In function ‘dwo_unit* lookup_dwo_unit_in_dwp()’:
gdb/dwarf2/read.c:7403:22: error: unused variable ‘inserted’ \
[-Werror=unused-variable]
auto [it, inserted] = dwo_unit_set.emplace (std::move (dwo_unit));
^
...
Simon Marchi [Fri, 23 May 2025 18:00:29 +0000 (14:00 -0400)]
gdb: include <mutex> in dwarf2/read.h
The buildbot pointed out this compilation failure on AlmaLinux, with g++
8.5.0, which is not seen on more recent systems:
CXX gdbtypes.o
In file included from ../../binutils-gdb/gdb/gdbtypes.c:39:
../../binutils-gdb/gdb/dwarf2/read.h:639:8: error: ‘mutex’ in namespace ‘std’ does not name a type
std::mutex dwo_files_lock;
^~~~~
../../binutils-gdb/gdb/dwarf2/read.h:639:3: note: ‘std::mutex’ is defined in header ‘<mutex>’; did you forget to ‘#include <mutex>’?
../../binutils-gdb/gdb/dwarf2/read.h:35:1:
+#include <mutex>
Tom de Vries [Fri, 23 May 2025 16:54:43 +0000 (18:54 +0200)]
[gdb] Make make-init-c more robust
In commit 2711e4754fc ("Ensure cooked_index_entry self-tests are run"), we
rewrite the function definition of _initialize_dwarf2_entry into a normal
form that allows the make-init-c script to detect it:
...
void _initialize_dwarf2_entry ();
-void _initialize_dwarf2_entry ()
+void
+_initialize_dwarf2_entry ()
...
Update make-init-c to also detect the "void _initialize_dwarf2_entry ()"
variant.
Tested on x86_64-linux, by reverting commit 2711e4754fc, rebuilding and
checking that build/gdb/init.c doesn't change.
Simon Marchi [Mon, 12 May 2025 19:09:45 +0000 (15:09 -0400)]
gdb/dwarf: split dwo_lock in more granular locks
The dwo_lock mutex is used to synchronize access to some dwo/dwp-related
data structures, such as dwarf2_per_bfd::dwo_files and
dwp_file::loaded_{cus,tus}. Right now the scope of the lock is kind of
coarse. It is taken in the top-level lookup_dwo_unit function, and held
while the thread:
- looks up an existing dwo_file in the per-bfd hash table for the given
id/signature
- if there's no existing dwo_file, attempt to find a .dwo file, open
it, build the list of units it contains
- if a new dwo_file was created, insert it in the per-bfd hash table
- look up the desired unit in the dwo_file
And something similar for the dwp code path. This means that two
indexing thread can't read in two dwo files simultaneously. This isn't
ideal in terms of parallelism.
This patch breaks this lock into 3 more fine grained locks:
- one lock to access dwarf2_per_bfd::dwo_files
- one lock to access dwp_file::loaded_{cus,tus}
- one lock in try_open_dwop_file, where we do two operations that
aren't thread safe (bfd_check_format and gdb_bfd_record_inclusion)
Unfortunately I don't see a clear speedup on my computer with 8 threads.
But the change shouldn't hurt, in theory, and hopefully this can be a
piece that helps in making GDB scale better on machines with many cores
(if we ever bump the max number of worker threads).
This patch uses "double-checked locking" to avoid holding the lock(s)
for the whole duration of reading in dwo files. The idea is, when
looking up a dwo with a given name:
- with the lock held, check for an existing dwo_file with that name in
dwarf2_per_bfd::dwo_files, if found return it
- if not found, drop the lock, load the dwo file and create a dwo_file
describing it
- with the lock held, attempt to insert the new dwo_file in
dwarf2_per_bfd::dwo_files. If an entry exists, it means another
thread simultaneously created an equivalent dwo_file, but won the
race. Drop the new dwo_file and use the existing one. The new
dwo_file is automatically deleted, because it is help by a unique_ptr
and the insertion into the unordered_set fails.
Note that it shouldn't normally happen for two threads to look up a dwo
file with the same name, since different units will point to different
dwo files. But it were to happen, we handle it. This way of doing
things allows two threads to read in two different dwo files
simulatenously, which in theory should help get better parallelism. The
same technique is used for dwp_file::loaded_{cus,tus}.
I have some local CI jobs that run the fission and fission-dwp boards,
and I haven't seen regressions. In addition to the regular testing, I
ran a few tests using those boards on a ThreadSanitizer build of GDB.
Change-Id: I625c98b0aa97b47d5ee59fe22a137ad0eafc8c25 Reviewed-By: Andrew Burgess <aburgess@redhat.com>
Simon Marchi [Mon, 12 May 2025 19:09:44 +0000 (15:09 -0400)]
gdb/dwarf: allocate DWP dwarf2_section_info with new
For the same reason as explained in the previous patch (allocations on
obstacks aren't thread-safe), change the allocation of
dwarf2_section_info object for dwo files within dwp files to use "new".
The dwo_file::section object is not always owned by the dwo_file, so
introduce a new "dwo_file::section_holder" object that is only set when
the dwo_file owns the dwarf2_section_info.
Change-Id: I74c4608573c7a435bf3dadb83f96a805d21798a2 Approved-By: Tom Tromey <tom@tromey.com>
Simon Marchi [Mon, 12 May 2025 19:09:43 +0000 (15:09 -0400)]
gdb/dwarf: allocate dwo_unit with new
The following patch reduces the duration where the dwo_lock mutex is
taken. One operation that is not thread safe is the allocation on
dwo_units on the per_bfd obstack:
Tom Tromey [Thu, 8 May 2025 20:04:05 +0000 (14:04 -0600)]
Handle an argument-less operator in the C++ name parser
While debugging a new failure in my long-suffering "search-in-psyms"
series, I found that the C++ name canonicalizer did not handle a case
like "some_name::operator new []". This should remove the space,
resulting in "some_name::operator new[]" -- but does not.
This happens because the parser requires an operator to be followed by
argument types. That is, it's expected.
However, it seems to me that we do want to be able to canonicalize a
name like this. It will appear in the DWARF as a DW_AT_name, and
furthermore it could be entered by the user.
This patch fixes this problem by changing the grammar to supply the
"()" itself, then removing the trailing "()" when changing to string
form (in the functions that matter).
This isn't ideal -- it might miss a very obscure case involving the
gdb extension of providing fully-qualified names for function-local
statics -- but it improves the situation at least.
It's possible a better solution might be to rewrite the name
canonicalizer. I was wondering if this could perhaps be done without
reference to the grammar -- just by examining the tokens. However,
that's much more involved.
Let me know what you think.
Regression tested on x86-64 Fedora 40.
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=32939 Reviewed-By: Keith Seitz <keiths@redhat.com>
Nick Alcock [Mon, 12 May 2025 11:31:00 +0000 (12:31 +0100)]
libctf: archive, open: when opening, always set errp to something
ctf_arc_import_parent, called by the cached-opening machinery used by
ctf_archive_next and archive-wide lookup functions like
ctf_arc_lookup_symbol, has an err-pointer parameter like all other opening
functions. Unfortunately it unconditionally initializes it whenever
provided, even if there was no error, which can lead to its being
initialized to an uninitialized value. This is not technically an
API-contract violation, since we don't define what happens to the error
value except when an error happens, but it is still unpleasant.
Initialize it only when there is an actual error, so we never initialize it
to an uninitialized value.
While we're at it, improve all the opening pathways: on success, set errp to
0, rather than leaving it what it was, reducing the likelihood of
uninitialized error param returns in callers too. (This is inconsistent
with the treatment of ctf_errno(), but the err value being a parameter
passed in from outside makes the divergence acceptable: in open functions,
you're never going to be overwriting some old error value someone might want
to keep around across multiple calls, some of which are successful and some
of which are not.)
Soup up existing tests to verify all this.
Thanks to Bruce McCulloch for the original patch, and Stephen Brennan for
the report.
libctf/
PR libctf/32903
* ctf-archive.c (ctf_arc_open_internal): Zero errp on success.
(ctf_dict_open_sections): Zero errp at the start.
(ctf_arc_import_parent): Intialize err.
* ctf-open.c (ctf_bufopen): Zero errp at the start.
* testsuite/libctf-lookup/add-to-opened.c: Make sure one-element
archive opens update errp.
* testsuite/libctf-writable/ctf-compressed.c: Make sure real archive
opens update errp.
when doing load store switching it wrongly adjusts the address of the
R_SH_USES reloc and not the actual offset from that instruction. This is
an issue if the pc-relative function call relaxation gets done in a
later pass wich will result in overriding the wrong instruction.
Alan Modra [Mon, 19 May 2025 06:37:20 +0000 (16:07 +0930)]
rs_fill_nop and md_generate_nops
Make rs_fill_nop behave like rs_fill in using a repeat count
(fr_offset) to emit fr_var length repeated nop patterns. Besides
being more elegant, this reduces memory required for large .nops
directives.
* as.h (rs_fill_nop): Update comment.
* config/tc-i386.c (i386_generate_nops): Handle rs_fill_nop as
for rs_align_code.
* config/tc-i386.h (MAX_MEM_FOR_RS_SPACE_NOP): Define.
* listing.c (calc_hex): Handle rs_fill_nop as for rs_fill.
* read.c (MAX_MEM_FOR_RS_SPACE_NOP): Define.
(s_nops): Use MAX_MEM_FOR_RS_SPACE_NOP setting up frag.
* write.c (write_contents): Call md_generate_nops for rs_fill_nop
before the fr_fix part is written, so that rs_fill_nop can be
handled as for rs_fill.
Alan Modra [Sat, 17 May 2025 05:41:14 +0000 (15:11 +0930)]
tidy target HANDLE_ALIGN
avr, kvx, metag, mn10300, nds32, v850, visium, and wasm32 targets
defined HANDLE_ALIGN without defining MAX_MEM_FOR_RS_ALIGN_CODE. This
can result in a rather large chunk of memory being allocated. Fix
that by a combination of changing the default allocation to one byte
and/or defining a target MAX_MEM_FOR_RS_ALIGN_CODE.
arm wanted to write out the entire set of nops, and limited allowed
code alignment to 64 bytes to prevent large memory allocations.
Fix that by making use of the fact that rs_align_code frags repeat
fr_var bytes at fr_literal + fr_fix to fill out the required area.
Fix metag, nds32 and kvx too, which it seems copied either arm or x86
in similarly not making use of repeating patterns.
It's worth mentioning that my tidy to kvx changed the order of nop
bundles, placing a short bundle first rather than last.
epiphany was totally broken in that uninitialised data was written out
for any alignment requiring more than three bytes of fill.
ppc created a new frag to handle a branch over a large number of nops.
This saves 4 bytes per rs_align_code frag, and most times the branch
isn't used so it is generally a win for memory usage, but I figured
the extra code complexity wasn't worth it. So that code of mine goes.
visium copied the same scheme, so that goes too.
This leaves x86 as the only target making large allocations for
alignment frags.
* frags.c (MAX_MEM_FOR_RS_ALIGN_CODE): Default to 1.
* config/tc-aarch64.c (aarch64_handle_align): Remove always true
condition.
* config/tc-aarch64.h (MAX_MEM_FOR_RS_ALIGN_CODE): Move to be
adjacent to HANDLE_ALIGN define.
* config/tc-arm.c (arm_handle_align): Allow alignment of more
than MAX_MEM_FOR_RS_ALIGN_CODE bytes. Just write one repeat
of nop pattern to frag.
(arm_frag_align_code): Delete function.
* config/tc-arm.h (MAX_MEM_ALIGNMENT_BYTES): Don't define.
(MAX_MEM_FOR_RS_ALIGN_CODE): Set to 7.
(md_do_align): Don't define.
(arm_frag_align_code): Don't declare.
* config/tc-epiphany.c (epiphany_handle_align): Correct frag
so that nop_pattern repeats rather than random data.
* config/tc-epiphany.h (MAX_MEM_FOR_RS_ALIGN_CODE): Define.
* config/tc-kvx.c (kvx_make_nops): Merge into..
(kvx_handle_align): ..here. Put short nop bundle first,
followed by repeated full nop bundle.
* config/tc-kvx.h (MAX_MEM_FOR_RS_ALIGN_CODE): Define.
* config/tc-m32c.h (HANDLE_ALIGN, MAX_MEM_FOR_RS_ALIGN_CODE):
Don't define.
* config/tc-metag.c (metag_handle_align): Just write one
repeat of nop pattern to frag.
* config/tc-metag.h (MAX_MEM_FOR_RS_ALIGN_CODE): Define.
* config/tc-nds32.c (nds32_handle_align): Just write one
repeat of nop pattern to frag.
* config/tc-nds32.h (MAX_MEM_FOR_RS_ALIGN_CODE): Define.
* config/tc-ppc.c (ppc_handle_align): Don't make a new frag
for branch.
* config/tc-ppc.h (MAX_MEM_FOR_RS_ALIGN_CODE): Increase to 8.
* config/tc-visium.c (visium_handle_align): Don't make a new
frag for branch.
* config/tc-visium.h (MAX_MEM_FOR_RS_ALIGN_CODE): Define.
* config/tc-wasm32.h (HANDLE_ALIGN): Don't define.
* testsuite/gas/epiphany/nop.d,
* testsuite/gas/epiphany/nop.s: New test.
* testsuite/gas/epiphany/allinsn.exp: Run it.
* testsuite/gas/kvx/nop-align.d: Adjust.
Andrew Burgess [Wed, 21 May 2025 09:16:08 +0000 (10:16 +0100)]
gdb: reorder checks in validate_exec_file
While reviewing another patch I was briefly confused by a call to
target_pid_to_exec_file coming from validate_exec_file while attaching
to a process when I had not previously set an executable.
The current order of actions in validate_exec_file is:
1. Get name of current executable.
2. Get name of executable from the current inferior.
3. If either of (1) or (2) return NULL, then there's nothing to
check, early return.
I think it would be cleaner if we instead did this:
1. Get name of current executable.
3. If (1) returned NULL then there's nothing to check, early return.
3. Get name of executable from the current inferior.
4. If (3) returned NULL then there's nothing to check, early return.
This does mean there's an extra step, but I don't think the code is
any more complex really, and we now avoid trying to extract the name
of the executable from the current inferior unless we really need it.
This avoids the target_pid_to_exec_file call that I was seeing, which
for remote targets does avoid a packet round trip (not that I'm
selling this as an "optimisation", just noting the change).
There should be no user visible changes after this commit.
Approved-By: Simon Marchi <simon.marchi@efficios.com>
Tom Tromey [Thu, 22 May 2025 16:46:50 +0000 (10:46 -0600)]
Ensure cooked_index_entry self-tests are run
While looking at code coverage for gdb, I noticed that the
cooked_index_entry self-tests were not run. I tracked this down to a
formatting error in cooked-index-entry.c.
I suspect it might be better to use a macro to define these
initialization functions. That would probably remove the possibility
for this kind of error.
gprofng: fix 32892 source line level information not available with "-g -O2"
gprofng did not read the .debug_rnglists section for dwarf-5.
Another problem was that gprofng ignored DW_AT_abstract_origin
As a result, gprofng skiped Dwarf for all functions declared as:
<1><e18b>: Abbrev Number: 43 (DW_TAG_subprogram)
<e18c> DW_AT_abstract_origin: <0xe168>
<e190> DW_AT_linkage_name: _ZN10Bool_ArrayD2Ev
gprofng/ChangeLog
2025-05-19 Vladimir Mezentsev <vladimir.mezentsev@oracle.com>
PR 32892
* src/Dwarf.cc: Read the .debug_rnglists section.
Support DW_AT_abstract_origin.
* src/Dwarf.h: Likewise.
* src/DwarfLib.cc: Likewise.
* src/DwarfLib.h: Likewise.
* src/LoadObject.cc (dump_functions): Print mangled names for aliases.
* src/Stabs.cc (fixSymtabAlias): Set 'alias' correctly.
* src/Symbol.cc (find_symbols): Add argument where to collect symbols.
* src/Symbol.h: Likewise.
* NEWS: Mention new extensions.
* config/tc-riscv.c (enum riscv_csr_class): New CSR class.
(riscv_csr_address): Add support for Ssccfg.
* testsuite/gas/riscv/csr-version-1p10.d: New test for Ssccfg CSR.
* testsuite/gas/riscv/csr-version-1p10.l: New warning for Ssccfg CSR.
* testsuite/gas/riscv/csr-version-1p11.d: New test for Ssccfg CSR.
* testsuite/gas/riscv/csr-version-1p11.l: New warning for Ssccfg CSR.
* testsuite/gas/riscv/csr-version-1p12.d: New test for Ssccfg CSR.
* testsuite/gas/riscv/csr-version-1p12.l: New warning for Ssccfg CSR.
* testsuite/gas/riscv/csr-version-1p13.d: New test for Ssccfg CSR.
* testsuite/gas/riscv/csr-version-1p13.l: New warning for Ssccfg CSR.
* testsuite/gas/riscv/csr.s: New Ssccfg CSR.
* testsuite/gas/riscv/imply.d: New imply check.
* testsuite/gas/riscv/imply.s: New implies.
* testsuite/gas/riscv/march-help.l: New helping info.
include/ChangeLog:
* opcode/riscv-opc.h (CSR_SCOUNTINHIBIT): New CSR address.
(DECLARE_CSR): Add Ssccfg CSR.
Alan Modra [Wed, 21 May 2025 08:27:04 +0000 (17:57 +0930)]
ubsan: integer overflow in tc-i386.c:offset_in_range
or $9223372036854775808,%eax
runtime error: negation of -9223372036854775808 cannot be represented
in type 'offsetT' (aka 'long'); cast to an unsigned type to negate
this value to itself
* config/tc-i386.c (offset_in_range): Avoid signed overflow.
Tom Tromey [Thu, 10 Apr 2025 15:01:06 +0000 (09:01 -0600)]
Minor spelling fixes in gdb directory
I ran codespell on the gdb directory and fixed a number of minor
problems. In a couple cases I replaced a "gdb spelling" (e.g.,
"readin") with an English one ("reading") where it seemed harmless.
Tom de Vries [Tue, 20 May 2025 09:10:29 +0000 (11:10 +0200)]
[gdb/testsuite] Fix gdb.dwarf2/dw-form-strx-out-of-bounds.exp with make-check-all.sh
I forgot to run test-case gdb.dwarf2/dw-form-strx-out-of-bounds.exp with
make-check-all.sh, and consequently failed to notice that it fails with for
instance target board fission-dwp.
The test-case does:
...
source $srcdir/$subdir/dw-form-strx.exp.tcl
...
and in that tcl file, prepare_for_testing fails, so a -1 is returned, but
that is ignored by the source command.
Fix this by using require, but rather that testing the result of the source
command, communicate success by setting a global variable
prepare_for_testing_done.
Likewise in gdb.dwarf2/dw-form-strx.exp.
Also, the test-case gdb.dwarf2/dw-form-strx-out-of-bounds.exp fails for target
board readnow, because the DWARF error occurs during a different command than
expected.
Fix this by just skipping the test-case in that case.
Tested on x86_64-linux.
Reported-by: Simon Marchi <simark@simark.ca> Approved-By: Tom Tromey <tom@tromey.com>
Tom de Vries [Tue, 20 May 2025 09:05:54 +0000 (11:05 +0200)]
[gdb/testsuite] Fix gdbsever typo
I noticed a typo in the testsuite, twice: gdbsever. Fix these.
Codespell doesn't detect it, so add a new file
gdb/contrib/codespell-dictionary.txt that contains a gdbsever->gdbserver
entry, and update gdb/contrib/setup.cfg to use it.
Andreas Schwab [Wed, 14 May 2025 10:44:08 +0000 (12:44 +0200)]
libiberty: sync with gcc
Import the following commits from GCC as of r16-614-g9d039eff453f77: 31dd621796f libiberty: add ldirname function f3d07779fdb libiberty: Append <libgen.h> to AC_CHECK_DECLS [PR119218]. 90183362524 libiberty, gcc: Add memrchr to libiberty and use it [PR119283]. 43717ee9064 libiberty: Fix off-by-one when collecting range expression
Alan Modra [Tue, 20 May 2025 05:52:13 +0000 (15:22 +0930)]
ubsan: undefined shift in loongarch_elf_add_sub_reloc_uleb128
An oss-fuzz testcase found:
runtime error: shift exponent 140 is too large for 32-bit type 'int'
OK, that's just a completely silly uleb, but we ought to be able to
handle 64 bits here.
* elfxx-loongarch.c (loongarch_elf_add_sub_reloc_uleb128): Formatting.
Don't left shift int. Avoid shifts larger than bits in a bfd_vma.
Simulator testsuite build started failing with host GCC-15:
bits-tst.c:323:1: error: function declaration isn’t a prototype [-Werror=strict-prototypes]
bits-tst.c: In function ‘main’:
bits-tst.c:323:1: error: old-style function definition [-Werror=old-style-definition]
Fix by including string.h to get the required prototypes, and changing
main's declaration to modern C.
Signed-off-by: Dimitar Dimitrov <dimitar@dinux.eu> Approved-By: Tom Tromey <tom@tromey.com>
Alan Modra [Sun, 18 May 2025 10:10:34 +0000 (19:40 +0930)]
ubsan: integer overflow in s_fill
Silence ubsan warning. We don't worry about wrap-around in most
places that adjust abs_section_offset, so don't fuss over an overflow
in the multiplication here.
* read.c (s_fill): Replace "long" vars with offsetT and valueT.
Avoid signed overflow calculating abs_section_offset.
> If vector AMO instructions are supported, then the scalar Zaamo
> instructions (atomic operations from the standard A extension)
> must be present.
Note that using the words like "imply" or "depend" for extensions
weren't a common practice to represent dependencies between extensions
at the time the documentation was created.
The "Zaamo" was not ratified as an extension at the time but this is a
subset of the "A" extension and defines scalar AMO operations (while
"Zvamo" -- NOT in the ratified specification -- defines vector AMO ops).
The important part is that the T-Head/XuanTie's documentation just
states that the "Zvamo" (draft) extension is renamed to "XTheadZvamo".
It means, this implication should have been preserved in some way.
Tsukasa OI [Sun, 18 May 2025 04:35:16 +0000 (04:35 +0000)]
RISC-V: Add implicit dependency to the XTheadVector extension
While this dependency is not directly stated in the documentation,
the XTheadVector extension cannot work without the Zicsr extension
(the documentation does not specify CSR access instruction subset
either as in the Zkr extension or the seed CSR section in the manual).
Also, making an implication to the Zicsr extension is in parity with
the ratified vector extensions (in GNU Binutils, the Zve32x extension --
a dependency of V -- depends on the Zvl32b and Zicsr extensions).
Tsukasa OI [Sun, 18 May 2025 04:35:16 +0000 (04:35 +0000)]
RISC-V: Wider conflicts with the XTheadVector extension
T-Head/XuanTie's "XTheadVector" is based on a draft version of the now
standard vector extensions and it conflicts with not just the "V"
extension but all of its subsets.
This commit makes "XTheadVector" conflict with the "Zve32x" extension,
which is the smallest subset of the standard vector extensions. Still,
a reference to "V" is preserved in the error message
as the documentation suggests:
> Therefore, the XTheadVector extension and the V extension are
> in conflict.
Note that, instructions in the "XTHeadZvamo" extension currently has
no conflicts with other extensions, even after addition of the "Zabha"
extension.
bfd/ChangeLog:
* elfxx-riscv.c (riscv_parse_check_conflicts):
Make "XTheadVector" conflict with not just "V" but its subsets.
gas/ChangeLog:
* testsuite/gas/riscv/x-thead-vector-fail.d: Test a vector
subset "Zve32x" to test failures.
* testsuite/gas/riscv/x-thead-vector-fail.l: Reflect change
in the error message.
Jens Remus [Mon, 19 May 2025 08:38:01 +0000 (10:38 +0200)]
s390: Prevent GOT access rewrite for misaligned symbols
Dereferences of GOT slots with lgrl or lg for global symbols are
rewritten to larl to get get rid of the extra memory access. However
this is invalid for:
- symbols marked for absolute addressing
- symbols at odd addresses (larl can handle only even addresses)
Commit e6213e09ed0e ("S/390: Prevent GOT access rewrite for certain
symbols") added checks for the above. But instead of checking the
address of a symbol for being halfword aligned, it tries to deduce
this from whether the symbol value and section the symbol is defined
in are halfword aligned. The way it is done has two issues:
1. The use of bfd_section_from_elf_index to obtain the section the
symbol is defined in may not return the one that remains in the
output. For instance for COMDAT sections getting deduplicated
the section retrieved using bfd_section_from_elf_index may not be
the same as h->root.u.def.section. If COMDAT sections of same
group signature have different alignment properties the wrong
one may be checked. This may then lead to an erroneous rewrite
of lgrl %rX, sym@GOTENT to larl %rX, sym, although the symbol in
the remaining section is not properly aligned, triggering an
"relocation for misaligned symbol" error at link-time.
This may for instance occur when mixing C++ modules compiled with
GCC and Clang, as GCC emits a 2-byte alignment and Clang a 1-byte
alignment for COMDAT sections containing type information:
Produces (reformatted and reduced):
File Name Off Size ES Flg Lk Inf Al
sample_gcc.o .rodata._ZTS1A 000080 000004 00 AG 0 0 2
sample_clang.o .rodata._ZTS1A 000058 000003 00 AG 0 0 1
2. The symbol may end up at an even address, if both the symbol value
and the section defining the symbol are 1-byte aligned. While this
does not trigger an error, it fails an opportunity to rewrite a GOT
access.
In a Linux Kernel build this causes ~15k GOT accesses using lgrl to
be skipped to be rewritten to larl.
Resolve both issues by simply checking whether the symbol address is
halfword aligned. Do not check the symbol value nor section defining
the symbol for halfword alignment.
bfd/
PR ld/32969
* elf64-s390.c (elf_s390_relocate_section): Only rewrite
lgrl/lg from GOT to larl if symbol address is halfword aligned.
ld/testsuite/
PR ld/32969
* ld-s390/s390.exp (pr32969_64-1, pr32969_64-2): Add tests for
rewrite of GOT access when COMDAT section deduplication is
involved.
* ld-s390/pr32969_64-1.dd: New test for rewrite of GOT access
when COMDAT section deduplication is involved.
* ld-s390/pr32969_64-2.dd: Likewise.
* ld-s390/pr32969a.s: Likewise.
* ld-s390/pr32969b.s: Likewise.
* ld-s390/pr32969c.s: Likewise.
Bug: https://sourceware.org/PR32969 Fixes: e6213e09ed0e ("S/390: Prevent GOT access rewrite for certain symbols") Reported-by: Ilya Leoshkevich <iii@linux.ibm.com> Signed-off-by: Jens Remus <jremus@linux.ibm.com>
Jens Remus [Mon, 19 May 2025 08:38:01 +0000 (10:38 +0200)]
s390: Improve diagnostic for reloc against misaligned sym
Report the BFD in which a misaligned symbol is defined in the error
message. This complements commit 906f69cf65da ("IBM zSystems: Issue
error for *DBL relocs on misaligned symbols"). While at it reword
the error message.
Old error message text (re-wrapped):
<sec-bfd>(<sec>+<off>): misaligned symbol `<sym>' (<addr>) for
relocation <rel>
New error message text (re-wrapped):
<sec-bfd>(<sec>+<off>): relocation <rel> against misaligned symbol
`<sym>' (<addr>) in <sym-bfd>
Note that the linker tests do not require to be updated, as they match
against the pattern ".*misaligned symbol.*", which has not changed in
the error message.
bfd/
PR ld/32969
* elf64-s390.c (elf_s390_relocate_section): Report BFD
in which a misaligned symbol is defined in error message.
Indu Bhagat [Mon, 19 May 2025 07:05:17 +0000 (00:05 -0700)]
gas: sframe: handle .cfi_undefined
Fix PR gas/32952 - sframe: incorrect handling of .cfi_undefined in gas
In context of SFrame generation, it is incorrect to simply ignore all
.cfi_undefined. We may ignore only those .cfi_undefined which are for
registers of no interest (similar to whats done for other CFI
directives).
gas/
* gen-sframe.c (sframe_xlate_do_cfi_undefined): New definition.
(sframe_do_cfi_insn): Handle .cfi_undefined.
gas/testsuite/
* gas/cfi-sframe/cfi-sframe.exp: Add new tests.
* gas/cfi-sframe/cfi-sframe-common-10.d: New test.
* gas/cfi-sframe/cfi-sframe-common-10.s: New test.
* gas/cfi-sframe/cfi-sframe-x86_64-empty-4.d: New test.
* gas/cfi-sframe/cfi-sframe-x86_64-empty-4.s: New test.
Indu Bhagat [Mon, 19 May 2025 07:03:39 +0000 (00:03 -0700)]
gas: sframe: reword diagnostic to address ambiguity
The current warning text of "skipping SFrame FDE" does not unabiguously
indicate that the SFrame FDE is not generated in the output section.
Reword the diagnostic to say "no SFrame FDE emitted" as requested.
Indu Bhagat [Mon, 19 May 2025 07:01:29 +0000 (00:01 -0700)]
gas: sframe: i386: have the backend specify the RA too
To process some CFI directives like .cfi_undefined and .cfi_same_value,
it is necessary for correctness to detect all cases when the register
used is one of SP, FP or RA.
Currently, the backends needed to specify the SFRAME_CFA_RA_REG only in
the case of those ABIs where RA tracking was necessary, e.g. AArch64.
For AMD64, since the return address is always at a fixed offset from the
CFA, RA tracking was disabled.
The backends must now specify the applicable return address register via
SFRAME_CFA_RA_REG. This is necessary so that SFrame generation code can
then properly handle the cases when RA is used like so:
.cfi_undefined <RA>
or,
.cfi_same_value <RA>
Detecting these cases is necessary for correctness. E.g., on AMD64, we
need to skip FDE generation as the above constructs cannot be
represented in SFrame yet.
This change is a prerequisite to fixing the two PRs:
PR gas/32952 - sframe: incorrect handling of .cfi_undefined in gas
PR gas/32953 - sframe: incorrect handling of .cfi_same_value in gas
In the SFrame generation code in gen-sframe.c, instead of using
SFRAME_FRE_RA_TRACKING ifdef's, we now simply rely on the API
sframe_ra_tracking_p () to detect if RA-tracking is enabled for the
target.
While at it, use const variables for x86 backend.
ChangeLog:
* gas/config/tc-i386.c (x86_sframe_cfa_ra_reg): New definition.
* gas/config/tc-i386.h (REG_RA): New definition.
(SFRAME_CFA_RA_REG): New declaration.
* gas/gen-sframe.c (SFRAME_FRE_RA_TRACKING): Remove.
Alan Modra [Fri, 16 May 2025 03:01:39 +0000 (12:31 +0930)]
gas .align limit
At the moment we allow alignment of up to half the address space,
which is stupidly large and results in OOM on x86_64. Change that to
1G alignment in text sections. Also fix the warning message on
exceeding max allowed alignment.
* read.c (TC_ALIGN_LIMIT): Limit to 30 in text sections.
(s_align): Correct "alignment too large" value.