Ticket #7621 (new bug)

Opened 4 months ago

Last modified 2 months ago

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

Reported by: singpolyma Owned by:
Priority: normal Milestone: 7.8.1
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 Difficulty: Unknown
Test Case: Blocked By:
Blocking: #7610 Related Tickets:

Description

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  http://www.haskell.org/pipermail/ghc-devs/2013-January/000005.html 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

unregistered-arm-llvm-hack.patch Download (1.3 KB) - added by singpolyma 4 months ago.

Change History

Changed 4 months ago by singpolyma

Changed 4 months ago by singpolyma

Core file from a similar run and crash, too big to upload to Trac so I put it at  https://singpolyma.net/ghc/7621-Main.core.xz

Changed 4 months ago by dterei

  • blocking 7610 added

Changed 4 months ago by simonmar

  • difficulty set to Unknown
  • os changed from Unknown/Multiple to QNX

Changed 4 months ago by simonmar

  • milestone set to 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.

Changed 4 months ago by simonmar

  • status changed from new to infoneeded

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

Changed 4 months ago by singpolyma

  • keywords unregisterised added; unregistered removed
  • status changed from infoneeded to new

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

Changed 4 months ago by singpolyma

  • version changed from 7.6.1 to 7.7

Changed 4 months 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.

Changed 4 months ago by simonmar

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

Changed 3 months 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 */
			ffi_closure_free(closure);

		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.

Changed 3 months ago by psycotica0

  • cc 0@… added

Changed 2 months ago by igloo

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

Note: See TracTickets for help on using tickets.