[llvm] r211500 - Stop producing func.eh symbols on Darwin.

Iain Sandoe iain at codesourcery.com
Sat Jul 19 00:55:47 PDT 2014

Hi Nick, Rafael,

On 19 Jul 2014, at 00:29, Nick Kledzik wrote:

> I’ve been looking at __eh_frame processing today for lld so this is fresh in my mind.
> Some background
> ------------------------
> For MacOSX 10.6, we (Apple) rolled out “compact unwind  info” as a way to reduce the size and runtime cost of C++ exceptions.  But because the transition of gcc->llvmgcc->clang was in progress, we did not get compiler support for this.  Instead the linker interpreted any dwarf unwind info it saw and if it seemed safe, converted that to compact unwind.  
> Now that Apple uses just clang which can generate compact unwind, we want to get the linker out of the business of interpreting dwarf unwind info.  But if the linker just stopped doing the conversion, existing .o files (i.e. in archives) would regress.  So, instead the linker checks if the compact unwind section exists (__LD,__compact_unwind).  If not, it is an old .o file and the linker should convert any dwarf unwind info.  If the linker sees both compact unwind and dwarf unwind for a function, it picks the compact unwind and discards the dwarf. 
> The linker can parse the __eh_frame section because it is a well known format.  The linker does not need any labels in the section because the size of each CFI chunk is encoded in the chunk header.  The linker does not need relocations because it can interpret the bytes in each CFI that “point” to the CFI or function. How the linker does this is if the __eh_frame section has no relocations, it just parses the section as-is.  If there are relocations, it makes a copy of the section and has a special case piece of code to “apply” the relocations to the copy, then parses that.
> Current problem
> ----------------------
> The issue Steven is looking at is that various optimizations have been added to LLVM to remove the .eh labels and remove the relocations.  But the current state is busted for x86_64 when -mmacosx-version-min=10.5 (or earlier).  The .eh labels are gone (good), but the relocations are still used.  But because the labels are gone, the usual SUBSTRACTOR/UNSIGNED external relocation pair cannot be used.  The relocations that are used is a combination that the mini dwarf interpreter in ld64 cannot handle.
> I suspect that the code in LLVM which suppressed the relocations on the __eh_frame section is disabled for older OS (when there might be an older linker).  That same check should be done for the removal of the .eh labels.  In other words:
> for 10.5 and earlier:  Have .eh labels and relocations on __eh_frame

FWIW, upstream GCC does not emit the .eh symbols when generating code for 10.5 (ld64-85.2.1**), and has not for a long time.  However it does ensure that a linker-visible symbol marks the __eh_frame start.  This saves the .eh symbols but still provides the necessary information to generate valid subtraction relocs.  Of course, on upstream GCC, the eh frames are being emitted as tables - and the equivalent scheme might not be so easy to achieve with .cfi_xxx.

This strategy corresponds to the ld from XCode 3.1.4 and has been well-exercised for a number of years.

For earlier OSX, upstream GCC still emits the .eh labels (although I'm not aware of anyone actually testing anything earlier than 10.4).

I guess, that if we want to be able to generate objects that can be linked by the XCode 2.5 linker, then we'd need to keep this pattern.

Note1: that, regardless of ld64 support, other tools like, nmm, ranlib etc. will be broken by the macosx_version_min load command (which is now placed in MH_OBJECTS, regardless of the target OSX version).

Note2: It would be nice to get the target linker version (which is available in CompilerInvocation) passed to the back end so that we can do codegen based on the requirements of the linker, rather than guessing from the target OSX version.  Then if someone really wants to generate objects / convenience libs that can be consumed by XCode 3.1.4/2.5 they can put -mtarget-linker on the command line.  If they just want to generate an exe that will run on the earlier system, then they can take advantage of whatever up-to-date linker capabilites are present.


** this assumes that it's a reasonable constraint to require the developer to use the latest official XCode release for a given platform.

> for 10.6 and later:  Have no .eh labels and no relocations on __eh_frame
> -Nick
> On Jul 17, 2014, at 2:23 PM, Steven Wu <stevenwu at apple.com> wrote:
>> Hi Rafael
>> I don’t know if you are expecting this, but this commit breaks the old x86_64 OS X systems (10.5 and below) which need __eh_frame. It will failed to compile any programs for old OS X (with “-mmacosx-version-min” flag). I attached two simple test cases which give slightly different error messages:
>> $ clang -arch x86_64 -Os -mmacosx-version-min=10.4 test_case.c -o test.o
>> ld: sectionForAddress(0xFFFFFFFFFF91969F) address not in any section file '/var/folders/cg/pyj86ks15y74w3hkwhm_zltm0000gp/T/test_case-cd1eb6.o' for architecture x86_64
>> clang-3.5: error: linker command failed with exit code 1 (use -v to see invocation)
>> $ clang -arch x86_64 -Os -mmacosx-version-min=10.4 test_case2.c -o test
>> ld: symbol index out of range file '/var/folders/cg/pyj86ks15y74w3hkwhm_zltm0000gp/T/test_case2-9a07c6.o' for architecture x86_64
>> clang-3.5: error: linker command failed with exit code 1 (use -v to see invocation)
>> The reason of the failure is that the OS X linker cannot recognize the generated relocations in __eh_frame. The current clang will create relocation section looks like:
>> Relocation information (__TEXT,__eh_frame) 4 entries
>> address  pcrel length extern type    scattered symbolnum/value
>> 00000048 False quad   False  SUB     False     2 (__TEXT,__eh_frame)
>> 00000048 False quad   True   UNSIGND False     _main
>> 00000020 False quad   False  SUB     False     2 (__TEXT,__eh_frame)
>> 00000020 False quad   True   UNSIGND False     _foo
>> But the linker is expecting either a pair of SUB/UNSIGNED relocations in eh_frame (for old systems) or no relocations (for new systems). A fix might just be remove all the relocations in eh_frame. I CCed Nick in this thread, so Nick correct me if I am wrong.
>> Thanks
>> Steven
>> <test_case.c>
>> <test_case2.c>
>>> Author: rafael
>>> Date: Mon Jun 23 10:13:23 2014
>>> New Revision: 211500
>>> URL: 
>>> http://llvm.org/viewvc/llvm-project?rev=211500&view=rev
>>> Log:
>>> Stop producing func.eh symbols on Darwin.
>>> According Nick Kledzik (
>>> http://llvm.org/bugs/show_bug.cgi?id=19430#c2
>>> ):
>>> "... mach-o no longer needs names in the __eh_frame section (and has not for
>>> years)."
>>> Iain Sandoe confirms it is also unnecessary for their old darwin support.
>>> Removed:
>>>     llvm/trunk/test/MC/MachO/eh-symbols.s
>>> Modified:
>>>     llvm/trunk/include/llvm/MC/MCObjectFileInfo.h
>>>     llvm/trunk/lib/MC/MCDwarf.cpp
>>>     llvm/trunk/lib/MC/MCObjectFileInfo.cpp
>>>     llvm/trunk/test/MC/MachO/eh-frame-reloc.s
>>> Modified: llvm/trunk/include/llvm/MC/MCObjectFileInfo.h
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits

More information about the llvm-commits mailing list