patchelf icon indicating copy to clipboard operation
patchelf copied to clipboard

patchelf should never generate LOAD segments with p_vaddr less than the lowest such address in the original file

Open zackw opened this issue 5 months ago • 4 comments

Describe the bug

Here's the program header table for a NixOS build of busybox for x86-64-linux:

$ readelf -l /nix/store/3v58nb3cwghbi986nia32i4vrksn6ipl-busybox-1.36.1/bin/busybox

Elf file type is EXEC (Executable file)
Entry point 0x408840
There are 14 program headers, starting at offset 64

Program Headers:
  Type           Offset             VirtAddr           PhysAddr
                 FileSiz            MemSiz              Flags  Align
  PHDR           0x0000000000000040 0x0000000000400040 0x0000000000400040
                 0x0000000000000310 0x0000000000000310  R      0x8
  INTERP         0x00000000000003b4 0x00000000004003b4 0x00000000004003b4
                 0x0000000000000053 0x0000000000000053  R      0x1
      [Requesting program interpreter: /nix/store/776irwlgfb65a782cxmyk61pck460fs9-glibc-2.40-66/lib/ld-linux-x86-64.so.2]
  LOAD           0x0000000000000000 0x0000000000400000 0x0000000000400000
                 0x0000000000006fd0 0x0000000000006fd0  R      0x1000
  LOAD           0x0000000000007000 0x0000000000407000 0x0000000000407000
                 0x00000000000cb9e1 0x00000000000cb9e1  R E    0x1000
  LOAD           0x00000000000d3000 0x00000000004d3000 0x00000000004d3000
                 0x0000000000028738 0x0000000000028738  R      0x1000
  LOAD           0x00000000000fc160 0x00000000004fc160 0x00000000004fc160
                 0x00000000000040fb 0x00000000000047a8  RW     0x1000
  DYNAMIC        0x00000000000ff108 0x00000000004ff108 0x00000000004ff108
                 0x0000000000000230 0x0000000000000230  RW     0x8
  NOTE           0x0000000000000350 0x0000000000400350 0x0000000000400350
                 0x0000000000000040 0x0000000000000040  R      0x8
  NOTE           0x0000000000000390 0x0000000000400390 0x0000000000400390
                 0x0000000000000024 0x0000000000000024  R      0x4
  NOTE           0x00000000000fb718 0x00000000004fb718 0x00000000004fb718
                 0x0000000000000020 0x0000000000000020  R      0x4
  GNU_PROPERTY   0x0000000000000350 0x0000000000400350 0x0000000000400350
                 0x0000000000000040 0x0000000000000040  R      0x8
  GNU_EH_FRAME   0x00000000000fb668 0x00000000004fb668 0x00000000004fb668
                 0x000000000000002c 0x000000000000002c  R      0x4
  GNU_STACK      0x0000000000000000 0x0000000000000000 0x0000000000000000
                 0x0000000000000000 0x0000000000000000  RW     0x10
  GNU_RELRO      0x00000000000fc160 0x00000000004fc160 0x00000000004fc160
                 0x0000000000003ea0 0x0000000000003ea0  R      0x1

 Section to Segment mapping:
  Segment Sections...
   00
   01     .interp
   02     .note.gnu.property .note.gnu.build-id .interp .hash .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt
   03     .init .plt .plt.got .text .fini
   04     .rodata .eh_frame_hdr .eh_frame .note.ABI-tag
   05     .init_array .fini_array .data.rel.ro .dynamic .got .data .bss
   06     .dynamic
   07     .note.gnu.property
   08     .note.gnu.build-id
   09     .note.ABI-tag
   10     .note.gnu.property
   11     .eh_frame_hdr
   12
   13     .init_array .fini_array .data.rel.ro .dynamic .got

Note that all the LOAD segments have base virtual addresses at or above 0x400000. This is an informal ABI requirement on x86-64-linux, and many systems are configured to enforce it by setting /proc/sys/vm/mmap_min_addr to 0x400000.

When this binary is processed by patchelf (as part of the build for the "extra-utils" derivation that's used in the NixOS initrd), the result has LOAD segments below 0x400000:

$ readelf -l /nix/store/r0bg4qxspbmfa6rm874ypl465r2ffjjq-extra-utils/bin/busybox

Elf file type is EXEC (Executable file)
Entry point 0x408840
There are 15 program headers, starting at offset 64

Program Headers:
  Type           Offset             VirtAddr           PhysAddr
                 FileSiz            MemSiz              Flags  Align
  PHDR           0x0000000000000040 0x00000000003ff040 0x00000000003ff040
                 0x0000000000000348 0x0000000000000348  R      0x8
  GNU_STACK      0x0000000000001000 0x0000000000000000 0x0000000000000000
                 0x0000000000000000 0x0000000000000000  RW     0x10
  LOAD           0x0000000000000000 0x00000000003ff000 0x00000000003ff000
                 0x0000000000001000 0x0000000000001000  RW     0x1000
  INTERP         0x0000000000000388 0x00000000003ff388 0x00000000003ff388
                 0x0000000000000051 0x0000000000000051  R      0x1
      [Requesting program interpreter: /nix/store/r0bg4qxspbmfa6rm874ypl465r2ffjjq-extra-utils/lib/ld-linux-x86-64.so.2]
  NOTE           0x00000000000003e0 0x00000000003ff3e0 0x00000000003ff3e0
                 0x0000000000000024 0x0000000000000024  R      0x4
  NOTE           0x0000000000000408 0x00000000003ff408 0x00000000003ff408
                 0x0000000000000040 0x0000000000000040  R      0x8
  LOAD           0x0000000000001000 0x0000000000400000 0x0000000000400000
                 0x0000000000006fd0 0x0000000000006fd0  R      0x1000
  GNU_PROPERTY   0x0000000000001350 0x0000000000400350 0x0000000000400350
                 0x0000000000000040 0x0000000000000040  R      0x8
  LOAD           0x0000000000008000 0x0000000000407000 0x0000000000407000
                 0x00000000000cb9e1 0x00000000000cb9e1  R E    0x1000
  LOAD           0x00000000000d4000 0x00000000004d3000 0x00000000004d3000
                 0x0000000000028738 0x0000000000028738  R      0x1000
  GNU_EH_FRAME   0x00000000000fc668 0x00000000004fb668 0x00000000004fb668
                 0x000000000000002c 0x000000000000002c  R      0x4
  NOTE           0x00000000000fc718 0x00000000004fb718 0x00000000004fb718
                 0x0000000000000020 0x0000000000000020  R      0x4
  LOAD           0x00000000000fd160 0x00000000004fc160 0x00000000004fc160
                 0x00000000000040fb 0x00000000000047a8  RW     0x1000
  GNU_RELRO      0x00000000000fd160 0x00000000004fc160 0x00000000004fc160
                 0x0000000000003ea0 0x0000000000003ea0  R      0x1
  DYNAMIC        0x0000000000100108 0x00000000004ff108 0x00000000004ff108
                 0x0000000000000230 0x0000000000000230  RW     0x8

 Section to Segment mapping:
  Segment Sections...
   00
   01
   02     .interp .note.gnu.build-id .note.gnu.property
   03     .interp
   04     .note.gnu.build-id
   05     .note.gnu.property
   06     .hash .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt
   07
   08     .init .plt .plt.got .text .fini
   09     .rodata .eh_frame_hdr .eh_frame .note.ABI-tag
   10     .eh_frame_hdr
   11     .note.ABI-tag
   12     .init_array .fini_array .data.rel.ro .dynamic .got .data .bss
   13     .init_array .fini_array .data.rel.ro .dynamic .got
   14     .dynamic

It appears that patchelf needed extra space for the patched .interp section, and therefore moved it to a lower address in the file, where more space could be found. Because the original file had a LOAD segment covering, among other things, the .interp section, it created a new LOAD segment to cover the relocated .interp section. So far, fine; but it also moved the virtual address of the new segment downward, below 0x400000. That's the problem. This binary will not execute on systems where mmap_min_addr has been set to 0x400000.

$ strace /nix/store/r0bg4qxspbmfa6rm874ypl465r2ffjjq-extra-utils/bin/busybox ash -c 'echo hello world'
execve("/nix/store/r0bg4qxspbmfa6rm874ypl465r2ffjjq-extra-utils/bin/busybox", ["/nix/store/r0bg4qxspbmfa6rm874yp"..., "ash", "-c", "echo hello world"], 0x7fff2d1b1c58 /* 72 vars */) = -1 EPERM (Operation not permitted)
+++ killed by SIGSEGV +++

Steps To Reproduce

On a Linux system with Nix available and the nix command and flakes enabled (it doesn't have to be a NixOS system), set /proc/sys/vm/mmap_min_addr to 0x400000. Create an empty directory. Put this flake in the empty directory.

{
  inputs = {
    nixpkgs.url = "github:zackw/nixpkgs/patch-1";
  };
  outputs = { self, nixpkgs, ... }: {
    nixosConfigurations.demo = nixpkgs.lib.nixosSystem {
      modules = [{
        system.stateVersion = "25.05";
        nix.registry.nixpkgs.flake = nixpkgs;
        nixpkgs.hostPlatform = "x86_64-linux";
        boot.loader.grub.device = "nodev";

        fileSystems."/" = {
          device = "/dev/sda1";
          fsType = "xfs";
        };
      }];
    };
  };
}

Then run this command from within the directory:

nix build "path:${PWD}#nixosConfigurations.demo.config.system.build.toplevel"

You should get a build failure looking like this:

warning: creating lock file '/home/zack/projects/misc/server-configs/argh/flake.lock':
• Added input 'nixpkgs':
    'github:zackw/nixpkgs/b71cc3c93040c10aa61af3ff2e502e04bb7012e2' (2025-09-10)
error: builder for '/nix/store/ji3bx8wfamqskx9blahvgmzyiph6v2ji-extra-utils.drv' failed with exit code 1;
       last 25 log lines:
       > + shift
       > + local 'hooksSlice=failureHooks[@]'
       > + local hook
       [etc]

Then run nix log /nix/store/ji3bx8wfamqskx9blahvgmzyiph6v2ji-extra-utils.drv. Search for the string "testing patched programs". You should see this:

testing patched programs...
+++ /nix/store/r0bg4qxspbmfa6rm874ypl465r2ffjjq-extra-utils/bin/ash -c 'echo hello world'
+++ grep 'hello world'
+ exitHandler
+ exitCode=1
+ set +e
[etc]

And, if you try to run /nix/store/r0bg4qxspbmfa6rm874ypl465r2ffjjq-extra-utils/bin/busybox, it should segfault; contrariwise, /nix/store/3v58nb3cwghbi986nia32i4vrksn6ipl-busybox-1.36.1/busybox should work correctly. You should see the same program header tables as I showed above by running readelf -l on those two binaries.

Expected behavior

patchelf should compute the lowest p_vaddr of all LOAD segments in its input file, and it should take that as a hard lower bound; that is, it should ensure that all LOAD segments in its output have p_vaddr greater than or equal to this hard lower bound. This is only necessary for LOAD segments. This should always be possible, because -- unless there's a bug in the kernel or the dynamic linker -- none of the sections that patchelf needs to modify, need to be loaded at any particular address, and there's no requirement for the p_vaddr values (virtual load addresses) of LOAD segments to be in the same sequence as their p_offset values (locations within the file).

I am not 100% sure about this, but I think it is not necessary for the .interp section (technically the INTERP segment) to be loaded at all. In the original file, the LOAD segment that covers the .interp segment is actually there to cover the .hash section and several more after that, which are used by the dynamic linker and therefore do need to be loaded; it extends all the way down to load address 0x400000 and file offset 0 only because those both have to be page-aligned. The contents of the INTERP segment are read directly out of the file by the kernel (https://elixir.bootlin.com/linux/v6.16.6/source/fs/binfmt_elf.c#L874) and should not be needed after that. However, it looks like several of the other things patchelf can do may involve rewriting sections that do need to be loaded, and the principle applies to them too.

patchelf --version output

patchelf 0.15.2

Additional context

See earlier discussion at https://github.com/NixOS/nixpkgs/issues/441269 .

zackw avatar Sep 11 '25 14:09 zackw

Just a heads up, if you want to figure out the exact version of patchelf that was used in that derivation you could do nix-tree --derivation /nix/store/ji3bx8wfamqskx9blahvgmzyiph6v2ji-extra-utils.drv, hit slash to search, and find patchelf.

dtomvan avatar Sep 11 '25 19:09 dtomvan

@dtomvan Thanks for telling me about nix-tree. It was 0.15.2, brought in via stdenv, nothing weird going on there. (For some reason my store has both 0.15.0 and 0.15.2. It'd be helpful if build logs would start by listing all the inputs used in the derivation.)

zackw avatar Sep 12 '25 14:09 zackw

This looks like the problem I ran into on riscv64-linux in https://github.com/NixOS/nixpkgs/issues/460825.

Program Headers:
  Type           Offset             VirtAddr           PhysAddr
                 FileSiz            MemSiz              Flags  Align
  PHDR           0x0000000000000040 0x000000000000f040 0x000000000000f040
                 0x00000000000002a0 0x00000000000002a0  R      0x8
  RISCV_ATTRIBUT 0x0000000000219e92 0x0000000000000000 0x0000000000000000
                 0x0000000000000057 0x0000000000000000  R      0x1
  GNU_STACK      0x0000000000001000 0x0000000000000000 0x0000000000000000
                 0x0000000000000000 0x0000000000000000  RW     0x10
  LOAD           0x0000000000000000 0x000000000000f000 0x000000000000f000
                 0x0000000000001000 0x0000000000001000  RW     0x1000
  LOAD           0x0000000000001000 0x0000000000010000 0x0000000000010000
                 0x000000000020ded0 0x000000000020ded0  R E    0x1000
  INTERP         0x00000000000142d0 0x00000000000232d0 0x00000000000232d0
                 0x000000000000005c 0x000000000000005c  R      0x1
      [Requesting program interpreter: /nix/store/kg61gdq4svvph0c4pcsf867r8nkbiqs7-bootstrap-tools/lib/ld-linux-riscv64-lp64d.so.1]
  NOTE           0x0000000000014330 0x0000000000023330 0x0000000000023330
                 0x0000000000000020 0x0000000000000020  R      0x4
  GNU_EH_FRAME   0x00000000001c41d8 0x00000000001d31d8 0x00000000001d31d8
                 0x000000000000967c 0x000000000000967c  R      0x4
  LOAD           0x000000000020ef58 0x000000000021ef58 0x000000000021ef58
                 0x000000000000af28 0x00000000000103b8  RW     0x1000
  TLS            0x000000000020ef58 0x000000000021ef58 0x000000000021ef58
                 0x0000000000000000 0x0000000000000010  R      0x8
  GNU_RELRO      0x000000000020ef58 0x000000000021ef58 0x000000000021ef58
                 0x00000000000080a8 0x00000000000080a8  R      0x1
  DYNAMIC        0x0000000000216dd0 0x0000000000226dd0 0x0000000000226dd0
                 0x0000000000000230 0x0000000000000230  RW     0x8

RossComputerGuy avatar Nov 26 '25 15:11 RossComputerGuy

This issue affects anyone who wishes to target the Google Play Store (Android) while deploying native libraries that have been modified by patchelf. Recent changes from Google Play Store requires that native libraries have their page sizes aligned to 16KB. It seems whenever one runs --replace-needed the affected LOAD segment will have its alignment reset to 4KB.

This currently impacts the Qt Multimedia module, on Android. Qt Multimedia relies on FFmpeg. We are able to compile FFmpeg using correct page size, but when modified by patchelf, the alignment is no longer correct. The issue has been reproduced on Android x86_64 binaries, and when booting an app with these libraries, it is rejected by Android. The alignment issue is also reproduced on Android ARM64 binaries, but I was unable to get an Android emulator to reject the libraries.

I have only reproduced this on version 0.17.2, as we are affected by a separate bug on version 0.18.

See Qt bugreport for more info: https://qt-project.atlassian.net/browse/QTBUG-142332

Below is the terminal output of readelf after FFmpeg x86_64 for Android is compiled, before Patchelf is used

nils@nils-ubuntu:~/qtdev/dev/ffmpeg/android-x64-test/latest/lib$ readelf -ld libavformat.so

Elf file type is DYN (Shared object file)
Entry point 0x0
There are 10 program headers, starting at offset 64

Program Headers:
  Type           Offset             VirtAddr           PhysAddr
                 FileSiz            MemSiz              Flags  Align
  PHDR           0x0000000000000040 0x0000000000000040 0x0000000000000040
                 0x0000000000000230 0x0000000000000230  R      0x8
  LOAD           0x0000000000000000 0x0000000000000000 0x0000000000000000
                 0x00000000000b5754 0x00000000000b5754  R      0x4000
  LOAD           0x00000000000b5760 0x00000000000b9760 0x00000000000b9760
                 0x00000000001a0350 0x00000000001a0350  R E    0x4000
  LOAD           0x0000000000255ab0 0x000000000025dab0 0x000000000025dab0
                 0x00000000000318b8 0x0000000000032550  RW     0x4000
  LOAD           0x0000000000287368 0x0000000000293368 0x0000000000293368
                 0x0000000000000000 0x0000000000000058  RW     0x4000
  DYNAMIC        0x0000000000286058 0x000000000028e058 0x000000000028e058
                 0x00000000000001f0 0x00000000000001f0  RW     0x8
  GNU_RELRO      0x0000000000255ab0 0x000000000025dab0 0x000000000025dab0
                 0x00000000000318b8 0x0000000000032550  R      0x1
  GNU_EH_FRAME   0x000000000008692c 0x000000000008692c 0x000000000008692c
                 0x0000000000005a94 0x0000000000005a94  R      0x4
  GNU_STACK      0x0000000000000000 0x0000000000000000 0x0000000000000000
                 0x0000000000000000 0x0000000000000000  RW     0x0
  NOTE           0x0000000000000270 0x0000000000000270 0x0000000000000270
                 0x0000000000000098 0x0000000000000098  R      0x4

 Section to Segment mapping:
  Segment Sections...
   00     
   01     .note.android.ident .dynsym .gnu.version .gnu.version_d .gnu.version_r .gnu.hash .dynstr .rela.dyn .rela.plt .rodata .eh_frame_hdr .eh_frame 
   02     .text .plt 
   03     .data.rel.ro .fini_array .dynamic .got .got.plt .relro_padding 
   04     .bss 
   05     .dynamic 
   06     .data.rel.ro .fini_array .dynamic .got .got.plt .relro_padding 
   07     .eh_frame_hdr 
   08     
   09     .note.android.ident 

Dynamic section at offset 0x286058 contains 31 entries:
  Tag        Type                         Name/Value
 0x0000000000000001 (NEEDED)             Shared library: [libavcodec.so]
 0x0000000000000001 (NEEDED)             Shared library: [libavutil.so]
 0x0000000000000001 (NEEDED)             Shared library: [libm.so]
 0x0000000000000001 (NEEDED)             Shared library: [libz.so]
 0x0000000000000001 (NEEDED)             Shared library: [libssl_3.so]
 0x0000000000000001 (NEEDED)             Shared library: [libcrypto_3.so]
 0x0000000000000001 (NEEDED)             Shared library: [libc.so]
 0x000000000000000e (SONAME)             Library soname: [libavformat.so]
 0x000000000000001e (FLAGS)              SYMBOLIC BIND_NOW
 0x000000006ffffffb (FLAGS_1)            Flags: NOW
 0x0000000000000007 (RELA)               0x7de0
 0x0000000000000008 (RELASZ)             195720 (bytes)
 0x0000000000000009 (RELAENT)            24 (bytes)
 0x000000006ffffff9 (RELACOUNT)          8017
 0x0000000000000017 (JMPREL)             0x37a68
 0x0000000000000002 (PLTRELSZ)           12672 (bytes)
 0x0000000000000003 (PLTGOT)             0x28e2d0
 0x0000000000000014 (PLTREL)             RELA
 0x0000000000000006 (SYMTAB)             0x308
 0x000000000000000b (SYMENT)             24 (bytes)
 0x0000000000000005 (STRTAB)             0x4e3c
 0x000000000000000a (STRSZ)              12192 (bytes)
 0x000000006ffffef5 (GNU_HASH)           0x4a18
 0x000000000000001a (FINI_ARRAY)         0x28e048
 0x000000000000001c (FINI_ARRAYSZ)       16 (bytes)
 0x000000006ffffff0 (VERSYM)             0x43b8
 0x000000006ffffffc (VERDEF)             0x491c
 0x000000006ffffffd (VERDEFNUM)          2
 0x000000006ffffffe (VERNEED)            0x4954
 0x000000006fffffff (VERNEEDNUM)         6
 0x0000000000000000 (NULL)               0x0

Below is the terminal output of readelf after FFmpeg x86_64 for Android is compiled, after Patchelf is used

nils@nils-ubuntu:~/qtdev/dev/ffmpeg/android-x64/latest/lib$ readelf -ld libavformat.so

Elf file type is DYN (Shared object file)
Entry point 0x0
There are 12 program headers, starting at offset 64

Program Headers:
  Type           Offset             VirtAddr           PhysAddr
                 FileSiz            MemSiz              Flags  Align
  PHDR           0x0000000000000040 0x0000000000000040 0x0000000000000040
                 0x00000000000002a0 0x00000000000002a0  R      0x8
  LOAD           0x0000000000000000 0x0000000000000000 0x0000000000000000
                 0x00000000000b5754 0x00000000000b5754  R      0x4000
  GNU_STACK      0x0000000000000000 0x0000000000000000 0x0000000000000000
                 0x0000000000000000 0x0000000000000000  RW     0x0
  GNU_EH_FRAME   0x000000000008692c 0x000000000008692c 0x000000000008692c
                 0x0000000000005a94 0x0000000000005a94  R      0x4
  LOAD           0x00000000000b5760 0x00000000000b9760 0x00000000000b9760
                 0x00000000001a0350 0x00000000001a0350  R E    0x4000
  LOAD           0x0000000000255ab0 0x000000000025dab0 0x000000000025dab0
                 0x00000000000318b8 0x0000000000032550  RW     0x4000
  GNU_RELRO      0x0000000000255ab0 0x000000000025dab0 0x000000000025dab0
                 0x00000000000318b8 0x0000000000032550  R      0x1
  DYNAMIC        0x0000000000286058 0x000000000028e058 0x000000000028e058
                 0x00000000000001f0 0x00000000000001f0  RW     0x8
  LOAD           0x0000000000287368 0x0000000000293368 0x0000000000293368
                 0x0000000000000000 0x0000000000000058  RW     0x4000
  NOTE           0x0000000000288000 0x0000000000294000 0x0000000000294000
                 0x0000000000000098 0x0000000000000098  R      0x4
  LOAD           0x0000000000288000 0x0000000000294000 0x0000000000294000
                 0x0000000000003058 0x0000000000003058  RW     0x1000
  LOAD           0x000000000028c000 0x0000000000298000 0x0000000000298000
                 0x0000000000007098 0x0000000000007098  RW     0x1000

 Section to Segment mapping:
  Segment Sections...
   00     
   01     .gnu.version .gnu.version_d .gnu.version_r .gnu.hash .rela.dyn .rela.plt .rodata .eh_frame_hdr .eh_frame 
   02     
   03     .eh_frame_hdr 
   04     .text .plt 
   05     .data.rel.ro .fini_array .dynamic .got .got.plt .relro_padding 
   06     .data.rel.ro .fini_array .dynamic .got .got.plt .relro_padding 
   07     .dynamic 
   08     .bss 
   09     .note.android.ident 
   10     .note.android.ident 
   11     .dynsym .dynstr 

Dynamic section at offset 0x286058 contains 31 entries:
  Tag        Type                         Name/Value
 0x0000000000000001 (NEEDED)             Shared library: [libavcodec.so]
 0x0000000000000001 (NEEDED)             Shared library: [libavutil.so]
 0x0000000000000001 (NEEDED)             Shared library: [libm.so]
 0x0000000000000001 (NEEDED)             Shared library: [libz.so]
 0x0000000000000001 (NEEDED)             Shared library: [libQt6FFmpegStub-ssl_x86_64.so]
 0x0000000000000001 (NEEDED)             Shared library: [libQt6FFmpegStub-crypto_x86_64.so]
 0x0000000000000001 (NEEDED)             Shared library: [libc.so]
 0x000000000000000e (SONAME)             Library soname: [libavformat.so]
 0x000000000000001e (FLAGS)              SYMBOLIC BIND_NOW
 0x000000006ffffffb (FLAGS_1)            Flags: NOW
 0x0000000000000007 (RELA)               0x7de0
 0x0000000000000008 (RELASZ)             195720 (bytes)
 0x0000000000000009 (RELAENT)            24 (bytes)
 0x000000006ffffff9 (RELACOUNT)          8017
 0x0000000000000017 (JMPREL)             0x37a68
 0x0000000000000002 (PLTRELSZ)           12672 (bytes)
 0x0000000000000003 (PLTGOT)             0x28e2d0
 0x0000000000000014 (PLTREL)             RELA
 0x0000000000000006 (SYMTAB)             0x298000
 0x000000000000000b (SYMENT)             24 (bytes)
 0x0000000000000005 (STRTAB)             0x29c0b0
 0x000000000000000a (STRSZ)              12257 (bytes)
 0x000000006ffffef5 (GNU_HASH)           0x4a18
 0x000000000000001a (FINI_ARRAY)         0x28e048
 0x000000000000001c (FINI_ARRAYSZ)       16 (bytes)
 0x000000006ffffff0 (VERSYM)             0x43b8
 0x000000006ffffffc (VERDEF)             0x491c
 0x000000006ffffffd (VERDEFNUM)          2
 0x000000006ffffffe (VERNEED)            0x4954
 0x000000006fffffff (VERNEEDNUM)         6
 0x0000000000000000 (NULL)               0x0

Didgy74 avatar Dec 29 '25 09:12 Didgy74