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

use GROUP for Elf code COMDATs #6564

Merged
merged 1 commit into from
Apr 1, 2017
Merged

Conversation

WalterBright
Copy link
Member

I don't know what the "doesn't work" means anymore, so turn this on to flush out any problems, because the ".text." results in concatenation, not pick one.

@WalterBright
Copy link
Member Author

@klickverbot @ibuclaw please weigh in on this.

@WalterBright
Copy link
Member Author

This one is for code, #6560 is for data. They are separate pulls because of git bisect.

@@ -1687,8 +1687,8 @@ STATIC void setup_comdat(Symbol *s)
if (tyfunc(s->ty()))
{
//s->Sfl = FLcode; // was FLoncecode
//prefix = ".gnu.linkonce.t"; // doesn't work, despite documentation
prefix = ".text."; // undocumented, but works
prefix = ".gnu.linkonce.t"; // doesn't work, despite documentation
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You might want to update the comment. ;)

@dnadlinger
Copy link
Member

@WalterBright: I never looked into .gnu.linkonce.* myself in any detail. I know that it crops up from inside glibc, but LLVM doesn't ever seem to emit it. All I can suggest is to try it out and then pay close attention to linker issues in the pre-release process. In particular, it would be wise to test on several versions of ld.bfd and gold (e.g. both on Ubuntu 14.04 and 16.10). When rolling out --gc-sections support for LDC, I made the experience that even those linker versions actually used in the wild differ significantly in their bugs when it comes to lesser-used features.

@dnadlinger
Copy link
Member

(I assume you are aware that COMDAT-like functionality is usually implemented using section groups on Linux/ELF?)

@WalterBright
Copy link
Member Author

Error is:

/usr/bin/ld: generated/linux/debug/32/unittest/libphobos2-ut.so: Too many sections: 112885 (>= 65280)

Anyone know how to do COMDATs on Elf? Googling hasn't been helpful.

@dnadlinger
Copy link
Member

dnadlinger commented Feb 23, 2017

Use a section group (SHT_GROUP) with the discard flag set (GRP_COMDAT).

@WalterBright
Copy link
Member Author

@klickverbot can you please send me a .o file with a GRP_COMDAT in it? I haven't been able to generate one.

@dnadlinger
Copy link
Member

dnadlinger commented Feb 23, 2017

This archive contains a simple example of a C++ template function as compiled by recent Clang on Linux.

$ llvm-readobj -elf-section-groups foo.o

File: foo.o
Format: ELF64-x86-64
Arch: x86_64
AddressSize: 64bit
LoadName:
Groups {
  Group {
    Name: .group (21)
    Index: 4
    Type: COMDAT (0x1)
    Signature: _Z3barIiEiT_
    Section(s) in group [
      .text._Z3barIiEiT_ (5)
    ]
  }
}

@dnadlinger
Copy link
Member

(Perhaps I misunderstand what you are asking for? I haven't looked at DMD's codegen in a while.)

@WalterBright
Copy link
Member Author

WalterBright commented Feb 23, 2017

Please send me the .o file itself, not a dump of it. Thanks! (Or the C++ source file. I was having trouble getting clang++ to emit these things.)

@dnadlinger
Copy link
Member

The last post contains a link.

@WalterBright
Copy link
Member Author

Thank you. Will investigate.

@WalterBright
Copy link
Member Author

Ah, I found out where I was going wrong. My elf dumper wasn't printing the GROUP bit.

@andralex
Copy link
Member

So what's the verdict here? Does this help or not?

@andralex
Copy link
Member

andralex commented Feb 24, 2017

FWIW I just tried this branch to build phobos unittests and got:

/usr/bin/ld: generated/linux/release/64/unittest/libphobos2-ut.so: Too many sections: 112159 (>= 65280)
/usr/bin/ld: final link failed: Nonrepresentable section on output

@MartinNowak
Copy link
Member

More info on COMDAT/section groups Airs – Ian Lance Taylor » Linkers part 15
We're already using section groups in the ELF backend, see dmd/elfobj.c:3180 and dmd/elfobj.c:3477
Also useful Section Groups.

@MartinNowak
Copy link
Member

Typical example of where sections groups are needed, functions in text and EH tables in relro data.

@WalterBright WalterBright force-pushed the code-linkonce branch 2 times, most recently from 79562b7 to 10987c2 Compare February 25, 2017 02:03
@WalterBright WalterBright changed the title use linkonce for Elf code COMDATs use GROUP for Elf code COMDATs Feb 25, 2017
@WalterBright
Copy link
Member Author

Ok, I completely revised it to use GROUPs. It's only for code at the moment, I'll do it for data if this succeeds.

@WalterBright WalterBright force-pushed the code-linkonce branch 4 times, most recently from 3bf65cb to 27e2a9e Compare February 25, 2017 09:11
@andralex
Copy link
Member

@WalterBright what is the differential size of libphobos_ut.so?

*/
const char *p = cpp_mangle(s);
IDXSTR namidx = Obj::addstr(symtab_strings, p);
IDXSYM info = elf_addsym(namidx, 0, 0, STT_FUNC, STB_WEAK, comdatidx);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just spent more than an hour on this, but I'm skeptical whether it could work out to squeeze the comdat group into setup_comdat.
It's already messy to prepone the symbol definition here (and still repeat it in Obj::comdat/func_start or wherever)
Even after making that already entangled code work somehow, it does not put other data that belongs to that function into the comdat group.
Eventually I ended up with a linker error complaining about a sth. in .rodata referencing a function in a discarded section.

`.text._D3std6format18__T10FormatSpecTaZ10FormatSpec6fillUpMFNaNfZv' referenced in section `.rodata' of generated/linux/debug/64/unittest/std/path.o: defined in discarded section `.text._D3std6format18__T10FormatSpecTaZ10FormatSpec6fillUpMFNaNfZv[_D3std6format18__T10FormatSpecTaZ10FormatSpec6fillUpMFNaNfZv]' of generated/linux/debug/64/unittest/std/path.o

Maybe that is a bug in my changes. But OTOH we'd also want to add EH tables into a function's COMDAT group.
How about we open that group (similar to func_start) and add the function as signature symbol after everything was emitted.
Not sure whether related symbols are all emitted with the function though.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm curious why you're getting that error. I'm getting a different one, from both the autotester and my setup at home, where cppa in the test suite is crashing. I spent several hours on that last night and am still not able to determine the cause. It's maddening.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Finally tracked it down. Agony! Added explanation in the comments.

@MartinNowak
Copy link
Member

I'm curious why you're getting that error. I'm getting a different one, from both the autotester and my setup at home

As said, I eventually ended up w/ that error after making the comdat groups work w/ a few hacks. The auto-tester has been showing the same errors all the time already.
https://auto-tester.puremagic.com/show-run.ghtml?projectid=1&runid=2418919&isPull=true
https://auto-tester.puremagic.com/show-run.ghtml?projectid=1&runid=2414934&isPull=true

Essentially the linker complains that it has data/code relocations in an object file that point to code sections in the same object file that are being discarded (due to duplicates in other object files).
What needs to happen is to make all data/code that belongs to a function part of the same COMDAT group. That applies to EH and jump tables.

@WalterBright WalterBright force-pushed the code-linkonce branch 9 times, most recently from 7239743 to d0d3d02 Compare March 19, 2017 07:48
@WalterBright
Copy link
Member Author

@MartinNowak Things are working now, except for failing with a timeout on FreeBSD, 32 and 64 bit. Can you please check if it is hanging or not? I don't have a FreeBSD machine here - and FreeBSD should behave identically with Linux as far as the Elf object file format goes.

@WalterBright
Copy link
Member Author

ping @MartinNowak

@PetarKirov
Copy link
Member

PetarKirov commented Mar 27, 2017

@WalterBright FreeBSD_32 actually fails with a linker error:

../dmd/src/dmd -conf= -I../druntime/import  -w -dip25 -m32 -fPIC -O -release -shared -unittest -ofgenerated/freebsd/release/32/unittest/libphobos2-ut.so generated/freebsd/release/32/unittest/std/array.o generated/freebsd/release/32/unittest/std/ascii.o generated/freebsd/release/32/unittest/std/base64.o generated/freebsd/release/32/unittest/std/bigint.o generated/freebsd/release/32/unittest/std/bitmanip.o generated/freebsd/release/32/unittest/std/compiler.o generated/freebsd/release/32/unittest/std/complex.o generated/freebsd/release/32/unittest/std/concurrency.o generated/freebsd/release/32/unittest/std/conv.o generated/freebsd/release/32/unittest/std/csv.o generated/freebsd/release/32/unittest/std/datetime.o generated/freebsd/release/32/unittest/std/demangle.o generated/freebsd/release/32/unittest/std/encoding.o generated/freebsd/release/32/unittest/std/exception.o generated/freebsd/release/32/unittest/std/file.o generated/freebsd/release/32/unittest/std/format.o generated/freebsd/release/32/unittest/std/functional.o generated/freebsd/release/32/unittest/std/getopt.o generated/freebsd/release/32/unittest/std/json.o generated/freebsd/release/32/unittest/std/math.o generated/freebsd/release/32/unittest/std/mathspecial.o generated/freebsd/release/32/unittest/std/meta.o generated/freebsd/release/32/unittest/std/mmfile.o generated/freebsd/release/32/unittest/std/numeric.o generated/freebsd/release/32/unittest/std/outbuffer.o generated/freebsd/release/32/unittest/std/parallelism.o generated/freebsd/release/32/unittest/std/path.o generated/freebsd/release/32/unittest/std/process.o generated/freebsd/release/32/unittest/std/random.o generated/freebsd/release/32/unittest/std/signals.o generated/freebsd/release/32/unittest/std/socket.o generated/freebsd/release/32/unittest/std/stdint.o generated/freebsd/release/32/unittest/std/stdio.o generated/freebsd/release/32/unittest/std/string.o generated/freebsd/release/32/unittest/std/system.o generated/freebsd/release/32/unittest/std/traits.o generated/freebsd/release/32/unittest/std/typecons.o generated/freebsd/release/32/unittest/std/typetuple.o generated/freebsd/release/32/unittest/std/uni.o generated/freebsd/release/32/unittest/std/uri.o generated/freebsd/release/32/unittest/std/utf.o generated/freebsd/release/32/unittest/std/uuid.o generated/freebsd/release/32/unittest/std/variant.o generated/freebsd/release/32/unittest/std/xml.o generated/freebsd/release/32/unittest/std/zip.o generated/freebsd/release/32/unittest/std/zlib.o generated/freebsd/release/32/unittest/std/algorithm/comparison.o generated/freebsd/release/32/unittest/std/algorithm/iteration.o generated/freebsd/release/32/unittest/std/algorithm/mutation.o generated/freebsd/release/32/unittest/std/algorithm/package.o generated/freebsd/release/32/unittest/std/algorithm/searching.o generated/freebsd/release/32/unittest/std/algorithm/setops.o generated/freebsd/release/32/unittest/std/algorithm/sorting.o generated/freebsd/release/32/unittest/std/container/array.o generated/freebsd/release/32/unittest/std/container/binaryheap.o generated/freebsd/release/32/unittest/std/container/dlist.o generated/freebsd/release/32/unittest/std/container/package.o generated/freebsd/release/32/unittest/std/container/rbtree.o generated/freebsd/release/32/unittest/std/container/slist.o generated/freebsd/release/32/unittest/std/container/util.o generated/freebsd/release/32/unittest/std/digest/crc.o generated/freebsd/release/32/unittest/std/digest/digest.o generated/freebsd/release/32/unittest/std/digest/hmac.o generated/freebsd/release/32/unittest/std/digest/md.o generated/freebsd/release/32/unittest/std/digest/murmurhash.o generated/freebsd/release/32/unittest/std/digest/ripemd.o generated/freebsd/release/32/unittest/std/digest/sha.o generated/freebsd/release/32/unittest/std/experimental/allocator/common.o generated/freebsd/release/32/unittest/std/experimental/allocator/gc_allocator.o generated/freebsd/release/32/unittest/std/experimental/allocator/mallocator.o generated/freebsd/release/32/unittest/std/experimental/allocator/mmap_allocator.o generated/freebsd/release/32/unittest/std/experimental/allocator/package.o generated/freebsd/release/32/unittest/std/experimental/allocator/showcase.o generated/freebsd/release/32/unittest/std/experimental/allocator/typed.o generated/freebsd/release/32/unittest/std/experimental/allocator/building_blocks/affix_allocator.o generated/freebsd/release/32/unittest/std/experimental/allocator/building_blocks/allocator_list.o generated/freebsd/release/32/unittest/std/experimental/allocator/building_blocks/bucketizer.o generated/freebsd/release/32/unittest/std/experimental/allocator/building_blocks/fallback_allocator.o generated/freebsd/release/32/unittest/std/experimental/allocator/building_blocks/free_list.o generated/freebsd/release/32/unittest/std/experimental/allocator/building_blocks/free_tree.o generated/freebsd/release/32/unittest/std/experimental/allocator/building_blocks/bitmapped_block.o generated/freebsd/release/32/unittest/std/experimental/allocator/building_blocks/kernighan_ritchie.o generated/freebsd/release/32/unittest/std/experimental/allocator/building_blocks/null_allocator.o generated/freebsd/release/32/unittest/std/experimental/allocator/building_blocks/package.o generated/freebsd/release/32/unittest/std/experimental/allocator/building_blocks/quantizer.o generated/freebsd/release/32/unittest/std/experimental/allocator/building_blocks/region.o generated/freebsd/release/32/unittest/std/experimental/allocator/building_blocks/scoped_allocator.o generated/freebsd/release/32/unittest/std/experimental/allocator/building_blocks/segregator.o generated/freebsd/release/32/unittest/std/experimental/allocator/building_blocks/stats_collector.o generated/freebsd/release/32/unittest/std/experimental/logger/core.o generated/freebsd/release/32/unittest/std/experimental/logger/filelogger.o generated/freebsd/release/32/unittest/std/experimental/logger/nulllogger.o generated/freebsd/release/32/unittest/std/experimental/logger/multilogger.o generated/freebsd/release/32/unittest/std/experimental/logger/package.o generated/freebsd/release/32/unittest/std/net/curl.o generated/freebsd/release/32/unittest/std/net/isemail.o generated/freebsd/release/32/unittest/std/experimental/checkedint.o generated/freebsd/release/32/unittest/std/experimental/typecons.o generated/freebsd/release/32/unittest/std/range/interfaces.o generated/freebsd/release/32/unittest/std/range/package.o generated/freebsd/release/32/unittest/std/range/primitives.o generated/freebsd/release/32/unittest/std/regex/package.o generated/freebsd/release/32/unittest/std/regex/internal/generator.o generated/freebsd/release/32/unittest/std/regex/internal/ir.o generated/freebsd/release/32/unittest/std/regex/internal/parser.o generated/freebsd/release/32/unittest/std/regex/internal/backtracking.o generated/freebsd/release/32/unittest/std/regex/internal/tests.o generated/freebsd/release/32/unittest/std/regex/internal/thompson.o generated/freebsd/release/32/unittest/std/regex/internal/kickstart.o generated/freebsd/release/32/unittest/std/c/linux/linux.o generated/freebsd/release/32/unittest/std/c/linux/socket.o generated/freebsd/release/32/unittest/std/c/windows/com.o generated/freebsd/release/32/unittest/std/c/windows/stat.o generated/freebsd/release/32/unittest/std/c/windows/windows.o generated/freebsd/release/32/unittest/std/c/windows/winsock.o generated/freebsd/release/32/unittest/std/windows/charset.o generated/freebsd/release/32/unittest/std/windows/iunknown.o generated/freebsd/release/32/unittest/std/windows/syserror.o generated/freebsd/release/32/unittest/etc/c/curl.o generated/freebsd/release/32/unittest/etc/c/odbc/sql.o generated/freebsd/release/32/unittest/etc/c/odbc/sqlext.o generated/freebsd/release/32/unittest/etc/c/odbc/sqltypes.o generated/freebsd/release/32/unittest/etc/c/odbc/sqlucode.o generated/freebsd/release/32/unittest/etc/c/sqlite3.o generated/freebsd/release/32/unittest/etc/c/zlib.o generated/freebsd/release/32/unittest/std/c/fenv.o generated/freebsd/release/32/unittest/std/c/locale.o generated/freebsd/release/32/unittest/std/c/math.o generated/freebsd/release/32/unittest/std/c/process.o generated/freebsd/release/32/unittest/std/c/stdarg.o generated/freebsd/release/32/unittest/std/c/stddef.o generated/freebsd/release/32/unittest/std/c/stdio.o generated/freebsd/release/32/unittest/std/c/stdlib.o generated/freebsd/release/32/unittest/std/c/string.o generated/freebsd/release/32/unittest/std/c/time.o generated/freebsd/release/32/unittest/std/c/wcharh.o generated/freebsd/release/32/unittest/std/algorithm/internal.o generated/freebsd/release/32/unittest/std/concurrencybase.o generated/freebsd/release/32/unittest/std/internal/cstring.o generated/freebsd/release/32/unittest/std/internal/digest/sha_SSSE3.o generated/freebsd/release/32/unittest/std/internal/encodinginit.o generated/freebsd/release/32/unittest/std/internal/math/biguintcore.o generated/freebsd/release/32/unittest/std/internal/math/biguintnoasm.o generated/freebsd/release/32/unittest/std/internal/math/biguintx86.o generated/freebsd/release/32/unittest/std/internal/math/errorfunction.o generated/freebsd/release/32/unittest/std/internal/math/gammafunction.o generated/freebsd/release/32/unittest/std/internal/processinit.o generated/freebsd/release/32/unittest/std/internal/scopebuffer.o generated/freebsd/release/32/unittest/std/internal/test/dummyrange.o generated/freebsd/release/32/unittest/std/internal/unicode_comp.o generated/freebsd/release/32/unittest/std/internal/unicode_decomp.o generated/freebsd/release/32/unittest/std/internal/unicode_grapheme.o generated/freebsd/release/32/unittest/std/internal/unicode_norm.o generated/freebsd/release/32/unittest/std/internal/unicode_tables.o generated/freebsd/release/32/unittest/std/stdiobase.o generated/freebsd/release/32/etc/c/zlib/adler32.o generated/freebsd/release/32/etc/c/zlib/compress.o generated/freebsd/release/32/etc/c/zlib/crc32.o generated/freebsd/release/32/etc/c/zlib/deflate.o generated/freebsd/release/32/etc/c/zlib/gzclose.o generated/freebsd/release/32/etc/c/zlib/gzlib.o generated/freebsd/release/32/etc/c/zlib/gzread.o generated/freebsd/release/32/etc/c/zlib/gzwrite.o generated/freebsd/release/32/etc/c/zlib/infback.o generated/freebsd/release/32/etc/c/zlib/inffast.o generated/freebsd/release/32/etc/c/zlib/inflate.o generated/freebsd/release/32/etc/c/zlib/inftrees.o generated/freebsd/release/32/etc/c/zlib/trees.o generated/freebsd/release/32/etc/c/zlib/uncompr.o generated/freebsd/release/32/etc/c/zlib/zutil.o ../druntime/generated/freebsd/release/32/libdruntime.so.a  -defaultlib= -debuglib=
/usr/bin/ld: BFD 2.15 [FreeBSD] 2004-05-23 internal error, aborting at /usr/src/gnu/usr.bin/binutils/libbfd/../../../../contrib/binutils/bfd/elfcode.h line 213 in bfd_elf32_swap_symbol_out

/usr/bin/ld: Please report this bug.

Error: linker exited with status 1
posix.mak:349: recipe for target 'generated/freebsd/debug/32/unittest/libphobos2-ut.so' failed
gmake[1]: *** [generated/freebsd/debug/32/unittest/libphobos2-ut.so] Error 1
gmake[1]: Leaving directory '/home/braddr/sandbox/at-client/pull-2458887-FreeBSD_32/phobos'
posix.mak:275: recipe for target 'unittest-debug' failed
gmake: *** [unittest-debug] Error 2
gmake: *** Waiting for unfinished jobs....
/usr/bin/ld: BFD 2.15 [FreeBSD] 2004-05-23 internal error, aborting at /usr/src/gnu/usr.bin/binutils/libbfd/../../../../contrib/binutils/bfd/elfcode.h line 213 in bfd_elf32_swap_symbol_out

/usr/bin/ld: Please report this bug.

Error: linker exited with status 1
posix.mak:349: recipe for target 'generated/freebsd/release/32/unittest/libphobos2-ut.so' failed
gmake[1]: *** [generated/freebsd/release/32/unittest/libphobos2-ut.so] Error 1
gmake[1]: Leaving directory '/home/braddr/sandbox/at-client/pull-2458887-FreeBSD_32/phobos'
posix.mak:275: recipe for target 'unittest-release' failed
gmake: *** [unittest-release] Error 2

Some related bug reports:

@WalterBright
Copy link
Member Author

It was timing out before, now it is giving an error report. Hmm. Looks like I may have to build myself a FreeBSD box to figure this out.

@WalterBright
Copy link
Member Author

I've disabled this code for FreeBSD for the time being. It'll have to wait until I build a FreeBSD machine so I can figure out what is going wrong there, in the meantime, we can gain experience with this on Linux.

@WalterBright
Copy link
Member Author

@MartinNowak can we pull this into the beta?

@WalterBright
Copy link
Member Author

I built a new computer and installed FreeBSD 11.0 on it (the latest). It does not fail with the linker internal error. The installed ld -v command gives:

GNU ld 2.17.50 [FreeBSD] 2007-07-03

whereas the one in the autotester is:

/usr/bin/ld: BFD 2.15 [FreeBSD] 2004-05-23

Can we upgrade the linker in the autotester? Do we care about working with the old linker?
ping @braddr @MartinNowak

@andralex andralex merged commit 87b166f into dlang:master Apr 1, 2017
@WalterBright WalterBright deleted the code-linkonce branch April 2, 2017 10:33
@MartinNowak
Copy link
Member

@MartinNowak can we pull this into the beta?

Should've targetted stable and use maybe milestones to land in the beta. Don't think last minute additions before a release are a good idea either.

Copy link
Member

@MartinNowak MartinNowak left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, glad we have this working now :).

@WalterBright
Copy link
Member Author

Don't think last minute additions before a release are a good idea either.

I don't either. This change is a bit risky, and needs a longer testing period.

@MartinNowak
Copy link
Member

MartinNowak commented Apr 21, 2017


/* Get section index of the comdat
*/
IDXSEC comdatidx = section_cnt + 1;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug Issue 17338 – [Reg 2.075] link failure unsupported symbol section 0xff01 happens because you're guessing the section index here, but forgot to account for extended section indices (SHT_SYMTAB_SHNDX) once section_cnt reaches SHN_LORESERVE.
I'd opt for using the newly added addSectionToComdat for the comdat itself, after it was actually written out to it's section (and has a correct section number).

@llucenic
Copy link
Contributor

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 this pull request may close these issues.

6 participants