Mantis Bug Tracker

View Issue Details Jump to Notes ] Issue History ] Print ]
IDProjectCategoryView StatusDate SubmittedLast Update
0005268OCamlOCaml generalpublic2011-05-17 20:112012-12-30 22:36
Reporterbrendan 
Assigned Todoligez 
PrioritynormalSeveritycrashReproducibilityalways
StatusresolvedResolutionno change required 
PlatformOSOS Version
Product Version3.12.0 
Target VersionFixed in Version 
Summary0005268: Cannot build on Mac OS X 32-bit with Xcode 4.0.2
DescriptionOcaml 3.12.0 builds fine on Mac OS X (10.6.7) with Xcode 4.0.2 in 64-bit mode. Attempting to build it in 32-bit mode results in:

../ocamlcompopt.sh -nostdlib unix.cmxa -g -I stdlib -I ../otherlibs/unix ocamlbuild/ocamlbuild_executor.cmx ocamlbuild/ocamlbuild_pack.cmx ocamlbuild/ocamlbuild_unix_plugin.cmx ocamlbuild/ocamlbuild.cmx -o ocamlbuild/ocamlbuild.native
ld: in ocamlbuild/ocamlbuild_pack.o, in section __DATA,__data reloc 1: sectionForAddress(0x4028458) address not in any section for architecture i386

I've tried -cc "gcc-4.0 -m32" -as "as -arch i386" -aspp "gcc-4.0 -m32 -c" as well as gcc-4.2
TagsNo tags attached.
Attached Files? file icon discard_printf.s [^] (1,741 bytes) 2011-06-01 14:44

- Relationships

-  Notes
(0005940)
jhowarth (reporter)
2011-05-31 15:10

The darwin linker developer had the following observations on this problem...


The problem is in ocamlbuild_pack.o. There is a wacky relocation:

[/tmp/ocaml_bug]> otool -rv ocamlbuild_pack.o | grep -A4 'Relocation information (__DATA,__data)'
Relocation information (__DATA,__data) 10621 entries
address pcrel length extern type scattered symbolnum/value
000000c0 False long False VANILLA False 1 (__TEXT,__text)
000000dc False long n/a SECTDIF True 0x04028458
         False long n/a PAIR True 0x00028450
[/tmp/ocaml_bug]> size -l ocamlbuild_pack.o


Segment : 301288 (vmaddr 0x0 fileoff 424)
        Section (__TEXT, __text): 164654 (addr 0x0 offset 424)
        Section (__IMPORT, __pointers): 68 (addr 0x28330 offset 165080)
        Section (__DATA, __data): 136564 (addr 0x28374 offset 165148)
        total 301286
total 301288
[/tmp/ocaml_bug]>

The reloc 0xDC bytes into the __DATA/__data section references 0x04028458 which you can see (via size -l output) is not a valid address in the object file.

Interestingly, if you lop of the high bit (to become 0x00028458), the address is valid. Is this a single bit error somewhere?

...later analyzing the component object files making up ocamlbuild_pack.o, he observed...


[/tmp/ocaml_bug_pt2]> otool -rv discard_printf.o
discard_printf.o:
Relocation information (__TEXT,__text) 4 entries
address pcrel length extern type scattered symbolnum/value
00000039 False long False VANILLA False 2 (__DATA,__data)
00000034 False long False VANILLA False 2 (__DATA,__data)
0000001c True long True VANILLA False _camlFormat__ifprintf_1768
00000017 False long True VANILLA False _camlFormat
Relocation information (__DATA,__data) 4 entries
address pcrel length extern type scattered symbolnum/value
00000028 False long n/a LOCSDIF True 0x00000078

         False long n/a PAIR True 0x00000070
0000001c False long False VANILLA False 1 (__TEXT,__text)
0000000c False long False VANILLA False 1 (__TEXT,__text)

[/tmp/ocaml_bug_pt2]> otool -s __DATA __data discard_printf.o
discard_printf.o:
Contents of (__DATA,__data) section
00000048 00 04 00 00 00 00 00 00 f7 08 00 00 10 00 00 00
00000058 03 00 00 00 00 00 00 00 01 00 00 00 20 00 00 00
00000068 11 00 01 00 00 00 00 00 08 00 00 04 91 f1 00 00
00000078 6f 63 61 6d 6c 62 75 69 6c 64 2f 64 69 73 63 61
00000088 72 64 5f 70 72 69 6e 74 66 2e 6d 6c 00 00 00 00
[/tmp/ocaml_bug_pt2]>

The issue is at _camlOcamlbuild_pack__Discard_printf__frametable + 16. There is a sect-diff reloc at that address (0x70 = __data + 0x28). The problem is the content
+(in bold above) is 0x0400008.
(0005948)
jhowarth (reporter)
2011-06-01 14:42

Further analysis of the offending discard_printf.o by adding -S to ../ocamlcompopt.sh and executing...

[MacPro-2:ocaml-3.12.0-2/ocaml-3.12.0/_build] root# ../ocamlcompopt.sh -nostdlib -c -g -annot -rectypes -warn-error A -w L -w R -w Z -I ../otherlibs/unix -for-pack Ocamlbuild_pack -I ocamlbuild -I stdlib -o ocamlbuild/discard_printf.cmx ocamlbuild/discard_printf.ml

...by the darwin linker maintainer is that...


The issue is this:

        .align 2
        .long L200000 - . + 0x4000000 #<--- what is it trying to do here?
        .long 0xf191
L200000:
        .ascii "ocamlbuild/discard_printf.ml\0"

The label L200000 is 8 bytes ahead, and (.) means current location, so (L200000 - . ) means 8. But the assembler does not know this a assembly time constant, so passes it on to the linker. The linker bug is in handling a degenerate relocation which is the difference of the same location plus a huge constant.
(0005949)
jhowarth (reporter)
2011-06-01 14:45

Uploaded assembly file for discard_printf.s from i386 darwin which contains the offending assembly.
(0005964)
jeffsco (reporter)
2011-06-03 05:27

I'm trying to build a 32-bit version of 3.12.0 under Xcode 4.0.2, and I see the same problem exactly. I'd love to see this problem resolved. I'm running OCaml code in the iPhone Simulator, for which I need 32-bit code. In the meantime I'll downgrade to previous Xcode (3.2.5), which seems to be working.
(0005965)
jhowarth (reporter)
2011-06-03 18:08

Am I correct to assume that it is impossible to get ocamlopt to produce a preprocessed source file rather than just the assembly file? I was hoping a preprocessed source file would contain clues to why...

        .align 2
        .long L200000 - . + 0x4000000 #<--- what is it trying to do here?
        .long 0xf191
L200000:
        .ascii "ocamlbuild/discard_printf.ml\0"

this is present in the generated assembly.
(0005967)
xleroy (administrator)
2011-06-04 09:57

I very much hope this regression in Xcode will be fixed, since we have here a useful idiom that has been working flawlessy with earlier versions of Xcode and indeed with any other assembler/linker combination we've tested on other systems.

FYI, "what it is trying to do here" is to store debugging information that is carefully packed in a 64-bit word according to the pseudo-C-struct-with-bitfields below:

struct debuginfo {
  int flags: 2;
  int filename_offset: 24;
  int char_end: 10;
  int char_start: 8;
  int lineno: 20;
};

The "filename_offset" field encodes a pointer to a string literal, but to save bits it contains the difference between the string literal and the beginning of the struct. In pseudo-C again, the debugging info 'file "foo.ml", line 15, characters 25-65' would be initialized as follows:

char filename[] = "foo.ml";

struct debuginfo dbg1 = {
  0,
  (char *) &dbg1 - filename;
  65,
  25,
  15
};

In assembly, that gives:

dbg1:
    .long filename - . + 0x4000000
    .long 0xf191
filename:
    .ascii "foo.ml"

Two things surprise me in the explanations given in previous notes:
1- that the difference "Lfilename - ." is not computed immediately by the assembler (it certainly can compute it!)
2- that it makes a difference to the linker that the offset "+ 0x4000000" is big or small: shouldn't any 32-bit integer be accepted here?
(0005980)
jhowarth (reporter)
2011-06-05 01:24

The response from the darwin linker developer was...

It is a linker bug. I've already fixed it. It may just take awhile to make it way into a release.

There is a work around, the assembly could be changed to:

dbg1:
   .set Ldelta, Lfilename - .
   .long Ldelta + 0x4000000
   .long 0xf191
Lfilename:
   .ascii "foo.ml"

The .set directive forces the delta value to be computed at assembly time.
(0005989)
xleroy (administrator)
2011-06-07 19:34

Thanks for the info.

> There is a work around [...] The .set directive forces the delta value to be computed at assembly time.

That's good to know. Would it make a difference if Lfilename was defined *before* "Lfilename - . + 0x40000000" is computed? That would be easy to arrange and might help reducing the number of relocs on other platforms as well. (Wild guess.)
(0006002)
xleroy (administrator)
2011-06-11 10:43

A follow-up on the two workarounds proposed so far:

1- Define Lfilename *before* "Lfilename - . + 0x40000000" is computed.
Not so easy to arrange as I thought. (Sign issues, forcing more extensive changes that I can do in time for the next release.)

2- Use ".set Ldelta, Lfilename - . ; .long Ldelta + 0x4000000".
Doesn't work with Xcode 3.2: Ldelta is always set to 8 no matter how far ahead Lfilename is.

So I'm afraid we are stuck for the moment. The few OCaml users who need to compile it in 32 bits under MacOS X will have to wait for an upgrade to XCode 4.0.2 or downgrade to an earlier version of XCode.
(0006078)
doligez (administrator)
2011-08-03 17:45
edited on: 2011-08-03 17:46

It looks like Apple fixed their linker: OCaml 3.12.1 works on Mac OS 10.7 (Lion) with XCode 4.1 after applying the patch found in PR#4863.

(0008673)
Pascal Cuoq (reporter)
2012-12-30 22:36

Thanks everyone involved in this report for documenting the trail.

For whoever will pass next, if, say, you have tasted the command-line tools for Snow Leopard (https://github.com/kennethreitz/osx-gcc-installer/ [^] ) and are loath to download the four and a half Gigabytes that is Xcode 3.2.6, solution 2 in comment 0006002 can be implemented in OCaml 4.00.1 with the patch below.

OCaml 4.00.1, thus patched, compiled with the command-line tools at https://github.com/downloads/kennethreitz/osx-gcc-installer/GCC-10.6.pkg [^] , works fine to the best of my testing.

macbook:ocaml-4.00.1 pascal$ diff -u asmcomp/i386/emit.mlp{~,}
--- asmcomp/i386/emit.mlp~ 2012-07-30 20:59:07.000000000 +0200
+++ asmcomp/i386/emit.mlp 2012-12-30 21:51:57.000000000 +0100
@@ -1020,7 +1020,7 @@
       efa_word = (fun n -> ` .long {emit_int n}\n`);
       efa_align = emit_align;
       efa_label_rel = (fun lbl ofs ->
- ` .long {emit_label lbl} - . + {emit_int32 ofs}\n`);
+ ` .set Ldelta, {emit_label lbl} - . \n .long Ldelta + {emit_int32 ofs}\n`);
       efa_def_label = (fun l -> `{emit_label l}:\n`);
       efa_string = (fun s ->
         let s = s ^ "\000" in

- Issue History
Date Modified Username Field Change
2011-05-17 20:11 brendan New Issue
2011-05-20 14:30 doligez Status new => assigned
2011-05-20 14:30 doligez Assigned To => doligez
2011-05-31 15:10 jhowarth Note Added: 0005940
2011-06-01 14:42 jhowarth Note Added: 0005948
2011-06-01 14:44 jhowarth File Added: discard_printf.s
2011-06-01 14:45 jhowarth Note Added: 0005949
2011-06-03 05:27 jeffsco Note Added: 0005964
2011-06-03 18:08 jhowarth Note Added: 0005965
2011-06-04 09:57 xleroy Note Added: 0005967
2011-06-05 01:24 jhowarth Note Added: 0005980
2011-06-07 19:34 xleroy Note Added: 0005989
2011-06-11 10:43 xleroy Note Added: 0006002
2011-08-03 17:45 doligez Note Added: 0006078
2011-08-03 17:46 doligez Note Edited: 0006078
2011-08-03 17:46 doligez Status assigned => resolved
2011-08-03 17:46 doligez Resolution open => no change required
2012-12-30 22:36 Pascal Cuoq Note Added: 0008673


Copyright © 2000 - 2011 MantisBT Group
Powered by Mantis Bugtracker