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

Jump labels in assembly code end up as symbols in the executable on OS X #7133

Closed
vicuna opened this Issue Jan 30, 2016 · 2 comments

Comments

Projects
None yet
1 participant
@vicuna
Copy link
Collaborator

commented Jan 30, 2016

Original bug ID: 7133
Reporter: bartjacobs
Status: closed (set by @damiendoligez on 2016-02-10T14:26:25Z)
Resolution: fixed
Priority: low
Severity: tweak
Platform: Mac
OS: OS X
OS Version: 10.10.1
Version: 4.02.3
Target version: 4.03.0+dev / +beta1
Fixed in version: 4.03.0+dev / +beta1
Category: back end (clambda to assembly)

Bug 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 ()

Build foo:

ocamlopt -o foo -S foo.ml

Load foo into LLDB:

lldb ./foo

Run it

run

LLDB will stop at the segmentation fault. Ask for a backtrace:

bt

The backtrace will show the current function as foo.L100 instead of the correct (and more informative) foocamlFoo__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:

lldb ./foo

Run the executable:

run

Ask for a backtrace:

bt

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:

:1,$s/\.L/L/g
:wq

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:

    .section __TEXT,__const
    .align  2

.L108:
.long .L104 - .L108
.long .L103 - .L108
.long .L102 - .L108
.long .L101 - .L108
.text
.L104:

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.

@vicuna

This comment has been minimized.

Copy link
Collaborator Author

commented Jan 30, 2016

Comment author: bartjacobs

I have created pull request #450 (#450).

@vicuna

This comment has been minimized.

Copy link
Collaborator Author

commented Feb 10, 2016

Comment author: @damiendoligez

Merged in trunk (commit 0a914a4).

Thanks.

@vicuna vicuna closed this Feb 10, 2016

@vicuna vicuna added the back-end label Mar 14, 2019

@vicuna vicuna added this to the 4.03.0 milestone Mar 14, 2019

@vicuna vicuna added the bug label Mar 20, 2019

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.