Opened 5 years ago

Last modified 22 months ago

#7621 infoneeded bug

Cross-build for QNX ARM smashes stack when using FunPtr wrappers

Reported by: singpolyma Owned by:
Priority: normal Milestone:
Component: Compiler (FFI) Version: 7.7
Keywords: qnx unregisterised cross-compile Cc: nathan.huesken@…, 0@…
Operating System: QNX Architecture: arm
Type of failure: Runtime crash Test Case:
Blocked By: Blocking: #7610
Related Tickets: Differential Rev(s):
Wiki Page:


I have built an unregistered LLVM cross-compiler for arm-unknown-nto-qnx8.0.0eabi, which I finally got to build using the attached patch. Simple programs no longer crash like they do in registered ARM cross-compilers (as reported on mailing list at and other places), however the following code does crash:

{-# LANGUAGE ForeignFunctionInterface #-}
module Main (main) where

import Foreign.Ptr

foreign import ccall "wrapper" wrap_refresh :: ( IO ()) -> IO (FunPtr ( IO ()))

main :: IO ()
main = do
	wrap_refresh (return ())
	return ()

It seems, from experiments, that any code using the "wrapper" imports causes this error:

$ ./Main
*** stack smashing detected ***: Main terminated
Abort (core dumped)

Attachments (1)

unregistered-arm-llvm-hack.patch (1.3 KB) - added by singpolyma 5 years ago.

Download all attachments as: .zip

Change History (18)

Changed 5 years ago by singpolyma

comment:1 Changed 5 years ago by singpolyma

Core file from a similar run and crash, too big to upload to Trac so I put it at

comment:2 Changed 5 years ago by dterei

Blocking: 7610 added

comment:3 Changed 5 years ago by simonmar

difficulty: Unknown
Operating System: Unknown/MultipleQNX

comment:4 Changed 5 years ago by simonmar

Milestone: 7.8.1

Data point: the test case succeeds for me, with an unregisterised build for Raspberry Pi using both the C backend and LLVM. LLVM version 2.9.

comment:5 Changed 5 years ago by simonmar

Status: newinfoneeded

I may have fixed this now, please try again with the latest HEAD.

comment:6 Changed 5 years ago by singpolyma

Keywords: unregisterised added; unregistered removed
Status: infoneedednew

I just build an unregisterised compiler via-C from HEAD (since #7620 is fixed) and it also has this issue.

comment:7 Changed 5 years ago by singpolyma


comment:8 Changed 5 years ago by singpolyma

I just built a registerised QNX ARM cross-compiler with llvm-3.0, and this also occurs on binaries produced by that compiler.

comment:9 Changed 5 years ago by simonmar

Ok, someone will need to debug this then. It could be a problem with libffi.

comment:10 Changed 5 years ago by psycotica0

I've looked into this, and have decided that whether or not GHC is correct, libffi is definitely worong.

The following code works under arm-linux-gnueabi and native, but not under qnx:

#include <stdio.h>
#include <ffi.h>

/* Acts like puts with the file given at time of enclosure. */
void puts_binding(ffi_cif *cif, unsigned int *ret, void* args[],
		FILE *stream)
		*ret = fputs(*(char **)args[0], stream);

		int main()
		ffi_cif cif;
		ffi_type *args[1];
		ffi_closure *closure;

		int (*bound_puts)(char *);
		int rc;

		/* Allocate closure and bound_puts */
			closure = ffi_closure_alloc(sizeof(ffi_closure), &bound_puts);

		if (closure)
				/* Initialize the argument info vectors */
					args[0] = &ffi_type_pointer;

				/* Initialize the cif */
					if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
					// if (ffi_prep_cif(&cif, FFI_VFP, 1,
					// if (ffi_prep_cif(&cif, FFI_SYSV, 1,
								&ffi_type_uint, args) == FFI_OK)
						/* Initialize the closure, setting stream to stdout */
							if (ffi_prep_closure_loc(closure, &cif, puts_binding,
										stdout, bound_puts) == FFI_OK)
								rc = bound_puts("Hello World!");
								/* rc now holds the result of the call to fputs */

		/* Deallocate both closure, and bound_puts */

		return 0;

The formatting's a little off, because I cut and paste it from the libffi documentation. So, that crashes stacks when built with gcc and run on qnx.

I looked into libffi some and found that the problem seems to be in two calls of __clear_cache, which are meant to clear arm's instruction and data caches, since it's doing tricky stuff in there. They appear to be causing trouble, though...

Seems like this person was having the same trouble with Python on QNX

__clear_cache appears to be Linux syscall thing on ARM for this, and while the code is building on QNX, maybe it works differently there, or is broken?

Either way, I think I'll have to work on this with the FFI people unless any of you know what's up.

comment:11 Changed 5 years ago by psycotica0

Cc: 0@… added

comment:12 Changed 5 years ago by igloo

psycotica0, I have no idea. If you're able to sort this out with upstream then that would be great, thanks!

comment:13 Changed 3 years ago by thoughtpolice

Status: newinfoneeded

comment:14 Changed 3 years ago by thoughtpolice


Moving to 7.10.1

comment:15 Changed 3 years ago by thoughtpolice


Moving to 7.12.1 milestone; if you feel this is an error and should be addressed sooner, please move it back to the 7.10.1 milestone.

comment:16 Changed 2 years ago by thoughtpolice


Milestone renamed

comment:17 Changed 22 months ago by bgamari

Milestone: 8.0.1

This seems to have lost momentum.

Note: See TracTickets for help on using tickets.