|Anonymous | Login | Signup for a new account||2019-02-20 14:45 CET|
|Main | My View | View Issues | Change Log | Roadmap|
|View Issue Details|
|ID||Project||Category||View Status||Date Submitted||Last Update|
|0007133||OCaml||back end (clambda to assembly)||public||2016-01-30 01:39||2016-02-10 15:26|
|Platform||Mac||OS||OS X||OS Version||10.10.1|
|Target Version||4.03.0+dev / +beta1||Fixed in Version||4.03.0+dev / +beta1|
|Summary||0007133: Jump labels in assembly code end up as symbols in the executable on OS X|
|Description||On OS X 10.10.1, the myriad jump labels (of the form .L101:) emitted into the assembly code by ocamlopt are included by the LLVM assembler as symbols into the object file, and thence by the OS X linker (ld64) into the executable. This is undesirable for at least the following reasons:|
- Various native backtrace generators, including the OS X crash log generator and lldb, will interpret each jump label as starting a new function, and show the nearest preceding jump label, instead of the actual function name, in the backtrace.
- This also hurts the lldb experience in other ways. For example, when asking lldb to disassemble a function, it only shows the assembly code up to the first jump label.
- It has space and time costs at build time and at load/run time.
|Steps To Reproduce||Enter the following code into foo.ml:|
let x: unit -> unit = Obj.magic ()
let () = x ()
ocamlopt -o foo -S foo.ml
Load foo into LLDB:
LLDB will stop at the segmentation fault. Ask for a backtrace:
The backtrace will show the current function as foo`.L100 instead of the correct (and more informative) foo`camlFoo__entry .
|Additional Information||The problem is solved by dropping the dot from the jump label names.|
This can be confirmed easily for the abovementioned foo.ml example, as follows:
Generate an assembly code file for foo.ml:
ocamlopt -c -S foo.ml
Edit foo.s and replace each occurrence of .Lnnn by Lnnn (i.e. remove the dots).
Compile the assembly file:
clang -arch x86_64 -c foo.s
Build the executable:
ocamlopt -o foo foo.cmx
Load the executable into LLDB:
Run the executable:
Ask for a backtrace:
Notice that the current function is now correctly identified as foo`camlFoo__entry .
Explanation: the LLVM assembler seems to treat labels that start with the letter 'L' specially: it considers them local to the file and does not emit them as symbols into the object file.
Fix: dropping the dot from the label names is a single-line fix function emit_label in asmcomp/amd64/emit.mlp.
Complication: by itself, the above fix does not work; in particular, programs for which ocamlopt generates jump tables cause the OS X linker (ld64) to fail.
To see this, create file bar.ml with the following contents:
let x: int -> unit = Obj.magic ()
let () =
match (Obj.magic (): int) with
| 0 -> x 1
| 1 -> x 0
| 2 -> x 20
| 3 -> x 30
Generate assembly code for this program into bar.s:
ocamlopt -c -S bar.ml
Edit the assembly code file bar.s: replace each .Lnnn by Lnnn. In vi:
Compile the assembly code file:
clang -c -arch x86_64 bar.s
Build the executable:
ocamlopt -o bar bar.cmx
This produces the following error message:
ld: in section __TEXT,__const reloc 0: X86_64_RELOC_SUBTRACTOR must have r_extern=1 file 'bar.o' for architecture x86_64
Explanation: for the match expression in bar.ml, ocamlopt generates the following jump table into bar.s:
.long .L104 - .L108
.long .L103 - .L108
.long .L102 - .L108
.long .L101 - .L108
After replacing .L by L, the LLVM assembler still generates relocation entries for these subtractions, even though the labels are now local. This is because the labels for the cases (L101, L102, L103 and L104) are in the .text section, whereas the expression occurs in the __TEXT,__const section. The linker fails on this relocation entry mentioning a local label.
Fix: Dropping the .section __TEXT,__const directive fixes the problem. It does not seem to be required (anymore) on OS X.
I have prepared a patch and will create a pull request.
|Tags||No tags attached.|
|I have created pull request 0000450 (https://github.com/ocaml/ocaml/pull/450 [^]).|
Merged in trunk (commit 0a914a4765b8b97f230806706fedc6112a033f77).
|2016-01-30 01:39||bartjacobs||New Issue|
|2016-01-30 01:54||bartjacobs||Note Added: 0015291|
|2016-02-05 13:39||doligez||Status||new => acknowledged|
|2016-02-05 13:39||doligez||Target Version||=> 4.03.0+dev / +beta1|
|2016-02-10 15:26||doligez||Note Added: 0015336|
|2016-02-10 15:26||doligez||Status||acknowledged => closed|
|2016-02-10 15:26||doligez||Resolution||open => fixed|
|2016-02-10 15:26||doligez||Fixed in Version||=> 4.03.0+dev / +beta1|
|2017-02-23 16:35||doligez||Category||OCaml backend (code generation) => Back end (clambda to assembly)|
|2017-02-23 16:44||doligez||Category||Back end (clambda to assembly) => back end (clambda to assembly)|
|Copyright © 2000 - 2011 MantisBT Group|