Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Linking fails with relocation truncated to fit on linux/arm64 #28

Closed
arnetheduck opened this issue May 8, 2024 · 12 comments · Fixed by #29
Closed

Linking fails with relocation truncated to fit on linux/arm64 #28

arnetheduck opened this issue May 8, 2024 · 12 comments · Fixed by #29

Comments

@arnetheduck
Copy link
Contributor

When linking the built files on linux/arm64, we hit a relocation truncation:

/usr/lib/gcc-cross/aarch64-linux-gnu/8/../../../../aarch64-linux-gnu/bin/ld: /home/user/nimbus-eth2/nimcache/release/nimbus_beacon_node/@m..@svendor@snim-ssz-serialization@svendor@shashtree@ssrc@ssha256_armv8_crypto.S.o: in function `hashtree_sha256_sha_x1':
/home/user/nimbus-eth2/vendor/nim-ssz-serialization/vendor/hashtree/src/sha256_armv8_crypto.S:77:(.text+0x8): relocation truncated to fit: R_AARCH64_ADR_PREL_LO21 against `.rodata'
/usr/lib/gcc-cross/aarch64-linux-gnu/8/../../../../aarch64-linux-gnu/bin/ld: /home/user/nimbus-eth2/vendor/nim-ssz-serialization/vendor/hashtree/src/sha256_armv8_crypto.S:78:(.text+0xc): relocation truncated to fit: R_AARCH64_ADR_PREL_LO21 against `.rodata'
/usr/lib/gcc-cross/aarch64-linux-gnu/8/../../../../aarch64-linux-gnu/bin/ld: /home/user/nimbus-eth2/vendor/nim-ssz-serialization/vendor/hashtree/src/sha256_armv8_crypto.S:81:(.text+0x14): relocation truncated to fit: R_AARCH64_ADR_PREL_LO21 against `.rodata'
/usr/lib/gcc-cross/aarch64-linux-gnu/8/../../../../aarch64-linux-gnu/bin/ld: /home/user/nimbus-eth2/nimcache/release/nimbus_beacon_node/@m..@svendor@snim-ssz-serialization@svendor@shashtree@ssrc@ssha256_armv8_neon_x1.S.o: in function `hashtree_sha256_neon_x1':
/home/user/nimbus-eth2/vendor/nim-ssz-serialization/vendor/hashtree/src/sha256_armv8_neon_x1.S:311:(.text+0x10): relocation truncated to fit: R_AARCH64_ADR_PREL_LO21 against `.rodata'
/usr/lib/gcc-cross/aarch64-linux-gnu/8/../../../../aarch64-linux-gnu/bin/ld: /home/user/nimbus-eth2/vendor/nim-ssz-serialization/vendor/hashtree/src/sha256_armv8_neon_x1.S:312:(.text+0x14): relocation truncated to fit: R_AARCH64_ADR_PREL_LO21 against `.rodata'
/usr/lib/gcc-cross/aarch64-linux-gnu/8/../../../../aarch64-linux-gnu/bin/ld: /home/user/nimbus-eth2/vendor/nim-ssz-serialization/vendor/hashtree/src/sha256_armv8_neon_x1.S:321:(.text+0x28): relocation truncated to fit: R_AARCH64_ADR_PREL_LO21 against `.rodata'
/usr/lib/gcc-cross/aarch64-linux-gnu/8/../../../../aarch64-linux-gnu/bin/ld: /home/user/nimbus-eth2/nimcache/release/nimbus_beacon_node/@m..@svendor@snim-ssz-serialization@svendor@shashtree@ssrc@ssha256_armv8_neon_x4.S.o: in function `hashtree_sha256_neon_x4':
/home/user/nimbus-eth2/vendor/nim-ssz-serialization/vendor/hashtree/src/sha256_armv8_neon_x4.S:285:(.text+0x4): relocation truncated to fit: R_AARCH64_ADR_PREL_LO21 against `.rodata'
/usr/lib/gcc-cross/aarch64-linux-gnu/8/../../../../aarch64-linux-gnu/bin/ld: /home/user/nimbus-eth2/vendor/nim-ssz-serialization/vendor/hashtree/src/sha256_armv8_neon_x4.S:286:(.text+0x8): relocation truncated to fit: R_AARCH64_ADR_PREL_LO21 against `.rodata'
/usr/lib/gcc-cross/aarch64-linux-gnu/8/../../../../aarch64-linux-gnu/bin/ld: /home/user/nimbus-eth2/vendor/nim-ssz-serialization/vendor/hashtree/src/sha256_armv8_neon_x4.S:287:(.text+0xc): relocation truncated to fit: R_AARCH64_ADR_PREL_LO21 against `.rodata'
/usr/lib/gcc-cross/aarch64-linux-gnu/8/../../../../aarch64-linux-gnu/bin/ld: /home/user/nimbus-eth2/vendor/nim-ssz-serialization/vendor/hashtree/src/sha256_armv8_neon_x4.S:288:(.text+0x10): relocation truncated to fit: R_AARCH64_ADR_PREL_LO21 against `.rodata'

This looks similar to an issue openssl ran into with assembly code.

arnetheduck added a commit to status-im/nim-ssz-serialization that referenced this issue May 8, 2024
@potuz
Copy link
Collaborator

potuz commented May 8, 2024

Can you provide the full toolchain and execution environment? Is this metal or stimulated? Is this running in docker? I can't reproduce on a RPi yet

@arnetheduck
Copy link
Contributor Author

I have yet to dig into the details, but very broadly, that build is done inside a docker image on linux/amd64 using a cross compiler..

The repro is to do a fresh clone status-im/nimbus-eth2@137d969, then run make dist-arm64a linux machine (which sets up the docker image and cross compiler - it needs to be on a fresh clone or the host and target platforms get mixed up).

@arnetheduck
Copy link
Contributor Author

There's probably an easier way to repro by drilling down into the flags used in that build, I just haven't had time yet for a more thorough investigation

@potuz
Copy link
Collaborator

potuz commented May 8, 2024

Can you link with LDFLAGS += -Wl,-verbose and post the results, or even LDFLAGS += -Wl,-Map=output.map and post the map file? This does not seem to be the same as the openssl issue, it may be as simple as moving the .rodata section closer to text. Unfortunately I need to get a hold on an ARM machine to try myself, you could try the following linker script to see if places rodata closer to text. I'm surprised such a small program triggers relocation on 21 bit masks

SECTIONS
{
  .text : {
    *(.text)
    *(.text.*)
  }

  .rodata : {
    *(.rodata)
    *(.rodata.*)
  }

  .data : {
    *(.data)
    *(SORT_BY_ALIGNMENT(.data.*))
  }
}

`

@potuz
Copy link
Collaborator

potuz commented May 8, 2024

Adding: this doesn't get triggered by cross-compiling on Arch either:

$ CC=aarch64-linux-gnu-gcc AR=aarch64-linux-gnu-ar make
make -C src
make[1]: Entering directory '/home/heluani/Documents/code/ethereum/hashtree/src'
aarch64-linux-gnu-gcc -g -fpic   -c -o sha256_armv8_neon_x4.o sha256_armv8_neon_x4.S
aarch64-linux-gnu-gcc -g -fpic   -c -o sha256_armv8_neon_x1.o sha256_armv8_neon_x1.S
aarch64-linux-gnu-gcc -g -fpic   -c -o sha256_armv8_crypto.o sha256_armv8_crypto.S
aarch64-linux-gnu-gcc -g -Wall -Werror   -c -o hashtree.o hashtree.c
aarch64-linux-gnu-ar rcs libhashtree.a sha256_armv8_neon_x4.o sha256_armv8_neon_x1.o sha256_armv8_crypto.o hashtree.o
make[1]: Leaving directory '/home/heluani/Documents/code/ethereum/hashtree/src'

@barnabasbusa
Copy link

barnabasbusa commented May 8, 2024

@potuz
Copy link
Collaborator

potuz commented May 8, 2024

I'm sorry all I see are nimbus specific compilation scripts and not something related to this library. Can you post me the result of the linking face with the LDFLAGS as above? I can't reproduce this neither natively compiling on ARM nor cross compiling from x86, so it's hard to rule out if this is not Nimbus or Docker related.

@potuz
Copy link
Collaborator

potuz commented May 8, 2024

Update, @barnabasbusa was kind enough to give me access to the same type of box they are using in ethPandaOps, no issue here, clean compile:

root@hashtree-debug:~# git clone https://github.com/prysmaticlabs/hashtree.git
Cloning into 'hashtree'...
remote: Enumerating objects: 319, done.
remote: Counting objects: 100% (172/172), done.
remote: Compressing objects: 100% (110/110), done.
remote: Total 319 (delta 82), reused 102 (delta 40), pack-reused 147
Receiving objects: 100% (319/319), 157.37 KiB | 1.39 MiB/s, done.
Resolving deltas: 100% (179/179), done.
root@hashtree-debug:~# cd hashtree/
root@hashtree-debug:~/hashtree# make
make -C src
make[1]: Entering directory '/root/hashtree/src'
cc -g -fpic   -c -o sha256_armv8_neon_x4.o sha256_armv8_neon_x4.S
cc -g -fpic   -c -o sha256_armv8_neon_x1.o sha256_armv8_neon_x1.S
cc -g -fpic   -c -o sha256_armv8_crypto.o sha256_armv8_crypto.S
cc -g -Wall -Werror   -c -o hashtree.o hashtree.c
ar rcs libhashtree.a sha256_armv8_neon_x4.o sha256_armv8_neon_x1.o sha256_armv8_crypto.o hashtree.o
make[1]: Leaving directory '/root/hashtree/src'

Inclined on closing this issue until I get a reproducible example.

Edit: my guess will be that the Nim compilation takes the .text sections of the library and mixes it with the .text sections of Nimbus, similarly with the .rodata sections, this will definitely cause the relocation warnings since the rodata section will be pushed further from the 21 bit allows for the adr Opcodes the library uses.

arnetheduck added a commit to status-im/nim-ssz-serialization that referenced this issue May 8, 2024
@arnetheduck
Copy link
Contributor Author

Edit: my guess will be that the Nim compilation takes the .text sections of the library and mixes it with the .text sections of Nimbus, similarly with the .rodata sections, this will definitely cause the relocation warnings since the rodata section will be pushed further from the 21 bit allows for the adr Opcodes the library uses.

indeed, we embed the genesis states in the executable which means there's a lot of data in general in there - this is my suspicion as well, that the issue would only be reproducible in large binaries. 21 bits is not a lot in this context.

anyway, I intend to add more compilation info and repros soonish - just needed an open issue to start the documentation process of what's going on.

@arnetheduck
Copy link
Contributor Author

yep, here's an easy repro..

#if defined(__APPLE__)
# define cdecl(s) _##s
#else
# define cdecl(s) s
#endif

#if defined(__linux__)
    .section  .note.GNU-stack, "", @progbits
    .section .rodata,"a",@progbits
#elif defined(__APPLE__)
    .section __TEXT,__const
#elif defined(__WIN32__)
    .section .rdata,"dr"
#else
    .text
#endif

# name_data = start of data
# name_end = end of data (without alignment)
# name = 64-bit pointer to data
# name_size = 64-bit length in bytes

eth2_mainnet_genesis_data:
    .incbin "genesis.ssz"
eth2_mainnet_genesis_end:
    .global cdecl(eth2_mainnet_genesis_size)
    .p2align 3
cdecl(eth2_mainnet_genesis_size):
    .quad    eth2_mainnet_genesis_end - eth2_mainnet_genesis_data

put this file in src as metadata.S together with https://github.com/eth-clients/eth2-networks/blob/master/shared/mainnet/genesis.ssz, then run gcc -shared -o libhashtree.so *.S to repro.

@arnetheduck
Copy link
Contributor Author

gcc test.c -fPIC mainnet.S libhashtree.a similarly fails, using the above example and the static lib built by the makefile.

@potuz
Copy link
Collaborator

potuz commented May 9, 2024

gcc test.c -fPIC mainnet.S libhashtree.a similarly fails, using the above example and the static lib built by the makefile.

This seems to work with gcc test.c -fPIC libhashtree.a mainnet.S so there may be a way to solve this at the linking stage instead of touching the assembly.

potuz added a commit that referenced this issue May 13, 2024
Consumers of the library, if they insert a lot of data between text and
.rodata may hit a relocation issue when linking. Rather than tweaking
the linker, this PR fixes the addressing modes by adding a couple of
cycles when loading symbols allowing them to be separated to 32 bits.

Fixes #28
@potuz potuz closed this as completed in #29 May 23, 2024
potuz added a commit that referenced this issue May 23, 2024
Consumers of the library, if they insert a lot of data between text and
.rodata may hit a relocation issue when linking. Rather than tweaking
the linker, this PR fixes the addressing modes by adding a couple of
cycles when loading symbols allowing them to be separated to 32 bits.

Fixes #28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants