Opened 3 years ago

Closed 3 years ago

Last modified 10 months ago

#7603 closed bug (invalid)

Bad magic in static (FFI) object (7.6.1 for x86_64-apple-darwin)

Reported by: morabbin Owned by:
Priority: normal Milestone:
Component: Compiler Version: 7.6.1
Keywords: Cc:
Operating System: MacOS X Architecture: x86_64 (amd64)
Type of failure: Compile-time crash Test Case:
Blocked By: Blocking:
Related Tickets: #7628 Differential Revisions:

Description

When spraying HOC (Haskell to Objective-C) for bitrot, I encountered a GHC panic during the loading of some FFI.

Judging by the log below, it looks like this is during a TH execution, so the problem may be bitrot in this code wrt TH. Quite happy to dig further myself if pointed in the right direction.

Orac:~/work/hoc-read-only/hoc $ cabal build
Compiling HOC_cbits...
Building HOC-1.0...
Preprocessing library HOC-1.0...
[16 of 31] Compiling HOC.Invocation   ( HOC/HOC/Invocation.hs, dist/build/HOC/Invocation.o )

HOC/HOC/Invocation.hs:14:1:
    Unacceptable argument type in foreign declaration: FFICif
    When checking declaration:
      foreign import ccall safe "static Invocation.h callWithExceptions" c_callWithExceptions
        :: FFICif
           -> FunPtr a -> Ptr b -> Ptr (Ptr ()) -> IO (Ptr ObjCObject)
Orac:~/work/hoc-read-only/hoc $ cabal build
Compiling HOC_cbits...
Building HOC-1.0...
Preprocessing library HOC-1.0...
[ 7 of 31] Compiling HOC.FFICallInterface ( HOC/HOC/FFICallInterface.hs, dist/build/HOC/FFICallInterface.o )
[ 8 of 31] Compiling HOC.Arguments    ( HOC/HOC/Arguments.hs, dist/build/HOC/Arguments.o ) [HOC.FFICallInterface changed]
[11 of 31] Compiling HOC.CStruct      ( HOC/HOC/CStruct.hs, dist/build/HOC/CStruct.o ) [HOC.FFICallInterface changed]
[13 of 31] Compiling HOC.ID           ( HOC/HOC/ID.hs, dist/build/HOC/ID.o ) [HOC.FFICallInterface changed]
[16 of 31] Compiling HOC.Invocation   ( HOC/HOC/Invocation.hs, dist/build/HOC/Invocation.o )
[17 of 31] Compiling HOC.ExternFunctions ( HOC/HOC/ExternFunctions.hs, dist/build/HOC/ExternFunctions.o )

HOC/HOC/ExternFunctions.hs:77:34:
    Ambiguous occurrence `unsafePerformIO'
    It could refer to either `Foreign.unsafePerformIO',
                             imported from `Foreign' at HOC/HOC/ExternFunctions.hs:10:1-14
                          or `System.IO.Unsafe.unsafePerformIO',
                             imported from `System.IO.Unsafe' at HOC/HOC/ExternFunctions.hs:11:1-23
                             (and originally defined in `GHC.IO')
Orac:~/work/hoc-read-only/hoc $ cabal build
Compiling HOC_cbits...
Building HOC-1.0...
Preprocessing library HOC-1.0...
[17 of 31] Compiling HOC.ExternFunctions ( HOC/HOC/ExternFunctions.hs, dist/build/HOC/ExternFunctions.o )
[18 of 31] Compiling HOC.StdArgumentTypes ( HOC/HOC/StdArgumentTypes.hs, dist/build/HOC/StdArgumentTypes.o )
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
Loading package array-0.4.0.1 ... linking ... done.
Loading package deepseq-1.3.0.1 ... linking ... done.
Loading package containers-0.5.0.0 ... linking ... done.
Loading package pretty-1.1.1.0 ... linking ... done.
Loading package template-haskell ... linking ... done.
Loading package syb-0.3.7 ... linking ... done.
Loading package bytestring-0.10.0.0 ... linking ... done.
Loading package transformers-0.3.0.0 ... linking ... done.
Loading package mtl-2.1.2 ... linking ... done.
Loading package text-0.11.2.3 ... linking ... done.
Loading package parsec-3.1.3 ... linking ... done.
Loading package old-locale-1.0.0.5 ... linking ... done.
Loading package old-time-1.1.0.1 ... linking ... done.
Loading package fgl-5.4.2.4 ... linking ... done.
Loading package filepath-1.3.0.1 ... linking ... done.
Loading package time-1.4.0.1 ... linking ... done.
Loading package unix-2.6.0.0 ... linking ... done.
Loading package directory-1.2.0.0 ... linking ... done.
Loading package binary-0.5.1.1 ... linking ... done.
Loading package HUnit-1.2.5.1 ... linking ... done.
Loading object (static) dist/build/HOC_cbits.o ... ghc: dist/build/HOC_cbits.o: Bad magic. Expected: feedfacf, got: feedface.

ghc: panic! (the 'impossible' happened)
  (GHC version 7.6.1 for x86_64-apple-darwin):
	loadObj "dist/build/HOC_cbits.o": failed

Please report this as a GHC bug:  http://www.haskell.org/ghc/reportabug

Change History (7)

comment:1 Changed 3 years ago by thoughtpolice

Template Haskell is not the problem.

The Mach-O file format has a special 'magic number' in the head of all object files to identify them; the runtime linker then checks this magic number for sanity, when it loads object files at runtime.

The definition of the Mach-O format and some relative constants is here. We see:

/*
 * The 32-bit mach header appears at the very beginning of the object file for
 * 32-bit architectures.
 */
struct mach_header {
	uint32_t	magic;		/* mach magic number identifier */
	...
};

/* Constant for the magic field of the mach_header (32-bit architectures) */
#define	MH_MAGIC	0xfeedface	/* the mach magic number */
#define MH_CIGAM	0xcefaedfe	/* NXSwapInt(MH_MAGIC) */

/*
 * The 64-bit mach header appears at the very beginning of object files for
 * 64-bit architectures.
 */
struct mach_header_64 {
	uint32_t	magic;		/* mach magic number identifier */
	...
};

/* Constant for the magic field of the mach_header_64 (64-bit architectures) */
#define MH_MAGIC_64 0xfeedfacf /* the 64-bit mach magic number */
#define MH_CIGAM_64 0xcffaedfe /* NXSwapInt(MH_MAGIC_64) */

In a nutshell, this means your HOC_cbits was compiled as a 32-bit object file, but your GHC is 64bit. Therefore, loading the C bits is impossible. You likely need to recompile it properly (I don't know how the HOC binding takes care of this, but it's probably worth looking around in any makefiles if they exist, or something.) So I don't think this has anything to do with GHC.

(I am also a little confused by the output you pasted. I assume in-between every cabal build step you fixed the errors?)

comment:2 Changed 3 years ago by morabbin

Thanks, that makes sense (and is easy to fix).

Can we do better than a panic in this situation (or similar ones)?

Re the output; I clumsily pasted too much (only the final cabal build was relevant).

comment:3 Changed 3 years ago by morabbin

  • Resolution set to invalid
  • Status changed from new to closed

Not a GHC bug; closing as invalid.

comment:4 Changed 3 years ago by thoughtpolice

It's certainly possible we could give a more sane error message (for example, it should be easy to see when you have 0xfeedface but wanted 0xfeedfacf on OS X, that you accidentally have a 32bit object instead of a 64bit one.)

But not panicing when we see this occur is not possible. GHC must do dynamic linking and invoke that code at runtime when you use template haskell - if the object file is invalid, and the object file must be linked to resolve some symbols how else can we proceed but to abort?

If you would like GHC to give a more sane error message in cases like this, feel free to submit a patch. The relevant code here is in loadObj inside the file rts/Linker.c in the source tree - it should be easy to add better errors for some cases like this, and it would certainly help elucidate the problem.

comment:5 Changed 3 years ago by morabbin

I see that we must abort, absolutely. I meant something more informative, along the lines of your last para, so I will certainly have a look.

comment:6 Changed 3 years ago by thoughtpolice

Thanks!

When you are done, please create a new ticket here, attach the patch and set the status to 'patch.' Someone will review and merge when appropriate.

If it's small enough, you can also probably get away with emailing ghc-devs@… asking for a review - but a ticket ensures it won't just be dropped on the floor and always has a trail.

comment:7 Changed 10 months ago by thomie

  • difficulty set to Unknown

The error message has been improved in #7628.

Note: See TracTickets for help on using tickets.