[PATCH v2] elf: Fix localplt.awk for DT_RELR-enabled builds (BZ 31978)
Carlos O'Donell
carlos@redhat.com
Fri Jul 19 20:35:41 GMT 2024
On 7/16/24 6:57 AM, Adhemerval Zanella wrote:
> For each input readelf output, localplt.awk parses each 'Relocation
> section' entry, checks its offset against the dynamic section entry, and
> saves each DT_JMPREL, DT_RELA, and DT_REL offset value it finds. After
> all lines are read, the script checks if any segment offset differed
> from 0, meaning at least one 'Relocation section' was matched.
>
> However, if the shared object was built with RELR support and the static
> linker could place all the relocation on DT_RELR, there would be no
> DT_JMPREL, DT_RELA, and DT_REL entries; only a DT_RELR.
Agreed, as is the case in ppc64le today.
>
> For the current three ABIs that support (aarch64, x86, and powerpc64),
> the powerpc64 ld.so shows the behavior above. Both x86_64 and aarch64
> show extra relocations on '.rela.dyn', which makes the script check to
> succeed.
>
> This patch fixes by handling DT_RELR, where the offset is checked
> against the dynamic section entries and if the shared object contains an
> entry it means that there are no extra PLT entries (since all
> relocations are relative).
>
> It fixes the elf/check-localplt failure on powerpc.
>
> Checked with a build/check for aarch64-linux-gnu, x86_64-linux-gnu,
> i686-linux-gnu, arm-linux-gnueabihf, s390x-linux-gnu, powerpc-linux-gnu,
> powerpc64-linux-gnu, and powerpc64le-linux-gnu.
LGTM. Nice to add full DT_RELR support for this.
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
> ---
> scripts/localplt.awk | 16 +++++++++++++++-
> 1 file changed, 15 insertions(+), 1 deletion(-)
>
> diff --git a/scripts/localplt.awk b/scripts/localplt.awk
> index fe79ca01ab..621ae7d8e8 100644
> --- a/scripts/localplt.awk
> +++ b/scripts/localplt.awk
> @@ -10,7 +10,8 @@ BEGIN {
> }
>
> FILENAME != lastfile {
> - if (lastfile && jmprel_offset == 0 && rela_offset == 0 && rel_offset == 0) {
> + if (lastfile && jmprel_offset == 0 && rela_offset == 0 && rel_offset == 0 \
> + && relr_offset == 0) {
OK. All of the *_offset variable must be zero to trigger the failure, which
would mean we didn't find any of them. Any one of them being non-zero is good
enough.
> print FILENAME ": *** failed to find expected output (readelf -WSdr)";
> result = 2;
> }
> @@ -22,6 +23,7 @@ FILENAME != lastfile {
> jmprel_offset = 0;
> rela_offset = 0;
> rel_offset = 0;
> + relr_offset = 0;
OK. Set relr_offset to zero.
> pltrelsz = -1;
> delete section_offset_by_address;
> }
> @@ -77,6 +79,8 @@ in_relocs && relocs_offset == rel_offset && NF >= 5 {
> }
> }
>
> +# No need to handle DT_RELR (all packed relocations are relative).
OK.
> +
> in_relocs { next }
>
> $1 == "Relocation" && $2 == "section" && $5 == "offset" {
> @@ -121,4 +125,14 @@ $2 == "(REL)" {
> }
> next
> }
> +
> +$2 == "(RELR)" {
OK. Matches binutils/readelf.c "RELR" output for DT_RELR.
> + relr_addr = strtonum($3);
> + if (relr_addr in section_offset_by_address) {
> + relr_offset = section_offset_by_address[relr_addr];
> + } else {
> + print FILENAME ": *** DT_RELR does not match any section's address";
> + result = 2;
> + }
OK.
> +}
> END { exit(result) }
--
Cheers,
Carlos.
More information about the Libc-alpha
mailing list