rui314 / mold

Mold: A Modern Linker 🦠
MIT License
14.47k stars 473 forks source link

s390x: .hash table entries should have 8 bytes instead of 4 bytes! #1372

Closed stliibm closed 1 week ago

stliibm commented 1 week ago

A simple test on s390x shows that a .hash table with 4 byte entries is created by mold:

$ gcc -fuse-ld=mold -Wl,--hash-style=sysv -shared -o libXYZ.so XYZ.o
$ readelf -S libXYZ.so | grep -A1 -e "\.hash" -e "\[Nr\]"
  [Nr] Name              Type             Address           Offset
       Size              EntSize          Flags  Link  Info  Align
--
  [ 2] .hash             HASH             0000000000000294  00000294
       0000000000000040  0000000000000004   A       3     0     4

According to the ELF specification, the .hash table contains Elf32_Word objects. But unfortunately on s390x (and also on alpha), Elf64_Word objects are used! Therefore we need a special handling here.

If .hash table is used while execution of the library/binary, it most likely crashs with a segmentation fault.

Here are some references to other projects regarding those 8byte entries:

const struct elf_size_info s390_elf64_size_info = { ... 8, / hash-table entry size. /


- [binutils-gold](https://github.com/bminor/binutils-gdb/blob/master/gold/s390.cc#L863):

Target::Target_info Target_s390<64>::s390_info = { ... 64, // hash_entry_size


- [binutils-readelf](https://github.com/bminor/binutils-gdb/blob/master/binutils/readelf.c#L12114):
  if ((filedata->file_header.e_machine == EM_ALPHA
   || filedata->file_header.e_machine == EM_S390
   || filedata->file_header.e_machine == EM_S390_OLD)
  && filedata->file_header.e_ident[EI_CLASS] == ELFCLASS64)
hash_ent_size = 8;


- lld:
lld currently also uses the wrong 4 byte entries on s390x, but there is already this pull-request:
[Make hashtable entry size configurable #113431](https://github.com/llvm/llvm-project/pull/113431)
rui314 commented 1 week ago

Thank you for your report. The above change should address the issue.

stliibm commented 6 days ago

@rui314 FYI: I've build mold with your commit and checked on s390x:

$ gcc -fuse-ld=mold -Wl,--hash-style=sysv -shared -o libXYZ.so XYZ.o
$ readelf -S libXYZ.so | grep -A1 -e "\.hash" -e "\[Nr\]"
  [Nr] Name              Type             Address           Offset                            
       Size              EntSize          Flags  Link  Info  Align                            
--                                                                                            
  [ 2] .hash             HASH             0000000000000298  00000298
       0000000000000080  0000000000000008   A       3     0     8 

Now I see 8byte entries and a small testprogram runs without segmentation fault. Thanks a lot.

rui314 commented 6 days ago

Thank you for testing. Feel free to submit more bugs if mold doesn't work for s390x.