Crash on launch involving a branch table, weak bindings, and no-pic
| Originator: | ryan.brown | ||
| Number: | rdar://27696860 | Date Originated: | 2016-08-04 |
| Status: | Open | Resolved: | |
| Product: | Developer Tools | Product Version: | Xcode 5.0 (possibly before) - Xcode 8.0 |
| Classification: | Reproducible: | Always |
Summary:
Minimal test case:
https://gist.github.com/ryb-ableton/7720a07dd58a9c9a683c5778ccf4c5e3
Real-world test case using Boost.Regex:
https://gist.github.com/ryb-ableton/01ec990172284cf4471ec4d7a13cec48
The bug involves:
- Compiling for i386.
- Using -mdynamic-no-pic and -Wl,-read_only_relocs,suppress to build a dylib.
- A template member function with a switch statement that generates a branch table.
- Taking the address of the function from multiple locations (e.g two dylibs or a dylib and the executable).
The crash happens because dyld writes to memory from the read-only __TEXT segment while binding weak symbols. The weak bindings here make the member function's address consistent everywhere. dyld doesn't make the __TEXT segment writable prior to making weak bindings (in ImageLoader::weakBind()), unlike for rebasing (ImageLoaderMachO::doRebase()).
Steps to Reproduce:
1- Download the minimal test case above
2- Run `make && make check`
To build the Boost test case you need to download Boost – see the commands in the Makefile.
Expected Results:
No crash.
Actual Results:
Crash while launching the test executable:
+ 293, stop reason = EXC_BAD_ACCESS (code=2, address=0x3f7a)
* frame #0: 0x8fe139bf dyld`ImageLoaderMachO::bindLocation(ImageLoader::LinkContext const&, unsigned long, unsigned long, ImageLoader const*, unsigned char, char const*, long, char const*) + 293
frame #1: 0x8fe1cd5e dyld`ImageLoaderMachOCompressed::updateUsesCoalIterator(ImageLoader::CoalIterator&, unsigned long, ImageLoader*, ImageLoader::LinkContext const&) + 478
frame #2: 0x8fe0fb99 dyld`ImageLoader::weakBind(ImageLoader::LinkContext const&) + 1011
frame #3: 0x8fe05c37 dyld`dyld::_main(macho_header const*, unsigned long, int, char const**, char const**, char const**, unsigned long*) + 3498
frame #4: 0x8fe01231 dyld`dyldbootstrap::start(macho_header const*, int, char const**, long, macho_header const*, unsigned long*) + 427
frame #5: 0x8fe01047 dyld`_dyld_start + 71
Version:
Xcode 5.0 (possibly before) - Xcode 8.0
Notes:
The crash does not occur if jump tables are suppressed using -fno-jump-tables. This option is available on llvm HEAD, but is not yet in Apple's clang.
Comments
Please note: Reports posted here will not necessarily be seen by Apple. All problems should be submitted at bugreport.apple.com before they are posted here. Please only post information for Radars that you have filed yourself, and please do not include Apple confidential information in your posts. Thank you!