This is the mail archive of the java@gcc.gnu.org mailing list for the Java project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Interpreter/libffi ARM Porting


Hello Andrew,

Thank you very much for your detailed reply.  I am afraid, however, that
we still need some more help.  I hope that you'll bear with us because
we're on the brink of having a fully operational GCJ interpreter for
arm-elf-linux and arm-wince-pe.  We will of course be sharing these long
overdue results with the GCC community.

Attached is my current sysv.S.  It is compiling and it's working to the
point where ffitest passes and the gcj interpreter runs except for
exception handling.  My test case (run on arm-elf-linux-gij) looks like
this:

class ExceptionTest {
  public static void main(String[] args) {
    System.out.println("Exception test started");

    try {
      throw new Exception("oops");
    } catch (Exception e) {
      System.out.println(e);
      e.printStackTrace();
    }
  }
}

gij is invoked as follows:

netwinder% setenv GC_INITIAL_HEAP_SIZE 3000000
netwinder% gij --cp /home/craigv/exception.jar ExceptionTest
Exception test started
Exception in thread "main" java.lang.NullPointerException
   at catch_segv
(/home/craigv/armlinux/crosstool-0.27/build/arm-elf-linux/gcc-3.3.2-glibc-2.3.2/gcc-3.3.2/libjava/prims.cc:158)
   at ExceptionTest.main(java.lang.String[]) (Unknown Source)

This is the same behavior I had seen before modifying sysv.S along the
lines you suggested.  I instrumented interpret.cc and found that the
interpreter code is throwing my exception and it is being caught in the
catch block in _Jv_Interp::run().  After that it seems that I am getting
a SEGV.  I have not implemented any "arm-signal.h", and so I am
currently using the default handler for SEGV in prims.cc

That is our situation.  I wonder if you might be able to take a quick
look at our sysv.S and see what you think might be missing or wrong. 
Any other suggestions or ideas you might have would be HUGELY
appreciated.

Finally, it would be of great help if you could describe what is
supposed to happen when a checked exception is handled by the
interpreter.  So far I have been able to figure out that the exception
is pushed onto the stack in the catch block and that its instructions
are supposed to be run next.  I am not sure, but I think that it is at
this point that we are getting the segfault.

Thanks in advance,
craig vanderborgh
voxware incorporated

On Wed, 2004-06-16 at 12:06, Andrew Haley wrote:
> Craig A. Vanderborgh writes:
>   > 
>  > What does this do?  Is it related to exception handling in some way?
> Do
>  > we need to have the equivalent thing in our ARM implementation?
> 
> It's the DWARF2 unwinder data.
> Yes.
> Yes.
> 
> You just need to tell the unwinder how to unwind through ffi_call_SYSV.
> 
> See http://www.eagercon.com/dwarf/dwarf-2.0.0.pdf, page 62.
> 
> I suggest you compile a simple function with -fPIC -dA and have a look
> at
> the unwinder data.  On x86, It will look like this:
> 
> int main (int argc, char **argv)
> {
>   printf ("Hello, World!\n");
>   return 0;
> }
> 
> 
> 		.file	"hello.c"
> 		.section	.rodata.str1.1,"aMS",@progbits,1
> 	.LC0:
> 		.string	"Hello, World!"
> 		.text
> 		.align 4
> 	.globl main
> 		.type	main, @function
> 	main:
> 	.LFB12:
> 		# basic block 0
> 		pushl	%ebp
> 	.LCFI0:
> 		movl	%esp, %ebp
> 	.LCFI1:
> 		pushl	%ebx
> 	.LCFI2:
> 		subl	$4, %esp
> 	.LCFI3:
> 		call	__i686.get_pc_thunk.bx
> 		addl	$_GLOBAL_OFFSET_TABLE_, %ebx
> 		andl	$-16, %esp
> 		subl	$16, %esp
> 		leal	.LC0@GOTOFF(%ebx), %eax
> 		movl	%eax, (%esp)
> 		call	puts@PLT
> 		movl	$0, %eax
> 		movl	-4(%ebp), %ebx
> 		leave
> 		ret
> 	.LFE12:
> 		.size	main, .-main
> 	#APP
> 
> Copy this part:
> 
> 		.section	.eh_frame,"a",@progbits
> 	.Lframe1:
> 		.long	.LECIE1-.LSCIE1	# Length of Common Information
> Entry
> 	.LSCIE1:
> 		.long	0x0	# CIE Identifier Tag
> 		.byte	0x1	# CIE Version
> 		.ascii "zR\0"	# CIE Augmentation
> 		.uleb128 0x1	# CIE Code Alignment Factor
> 		.sleb128 -4	# CIE Data Alignment Factor
> 		.byte	0x8	# CIE RA Column
> 		.uleb128 0x1	# Augmentation size
> 		.byte	0x1b	# FDE Encoding (pcrel sdata4)
> 		.byte	0xc	# DW_CFA_def_cfa
> 		.uleb128 0x4
> 		.uleb128 0x4
> 		.byte	0x88	# DW_CFA_offset, column 0x8
> 		.uleb128 0x1
> 		.align 4
> 	.LECIE1:
> 
> This is the part you need to tweak:
> 
> 	.LSFDE1:
> 		.long	.LEFDE1-.LASFDE1	# FDE Length
> 	.LASFDE1:
> 		.long	.LASFDE1-.Lframe1	# FDE CIE offset
> 		.long	.LFB12-.	# FDE initial location
> 		.long	.LFE12-.LFB12	# FDE address range
> 		.uleb128 0x0	# Augmentation size
> 
> Advance PC to LCFI0:
> 
> 		.byte	0x4	# DW_CFA_advance_loc4
> 		.long	.LCFI0-.LFB12
> 
> Call Frame Address is same as previous CFA, but at offset 8:
> 
> 		.byte	0xe	# DW_CFA_def_cfa_offset
> 		.uleb128 0x8
> 
> Call Frame Address is at r5 + offset 8:
> 
> 		.byte	0x85	# DW_CFA_offset, column 0x5
> 		.uleb128 0x2
> 
> Advance PC to LCFI1:
> 
> 		.byte	0x4	# DW_CFA_advance_loc4
> 		.long	.LCFI1-.LCFI0
> 
> Call Frame Address is in r5, same offset as before:
> 
> 		.byte	0xd	# DW_CFA_def_cfa_register
> 		.uleb128 0x5
> 
> Advance PC to LCFI3:
> 
> 		.byte	0x4	# DW_CFA_advance_loc4
> 		.long	.LCFI3-.LCFI1
> 
> Call Frame Address is in r3 + offset 12:
> 
> 		.byte	0x83	# DW_CFA_offset, column 0x3
> 		.uleb128 0x3
> 		.align 4
> 	.LEFDE1:
/* -----------------------------------------------------------------------
   sysv.S - Copyright (c) 1998 Cygnus Solutions
   
   ARM Foreign Function Interface 

   Permission is hereby granted, free of charge, to any person obtaining
   a copy of this software and associated documentation files (the
   ``Software''), to deal in the Software without restriction, including
   without limitation the rights to use, copy, modify, merge, publish,
   distribute, sublicense, and/or sell copies of the Software, and to
   permit persons to whom the Software is furnished to do so, subject to
   the following conditions:

   The above copyright notice and this permission notice shall be included
   in all copies or substantial portions of the Software.

   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
   IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
   OTHER DEALINGS IN THE SOFTWARE.
   ----------------------------------------------------------------------- */

#define LIBFFI_ASM	
#include <ffi.h>
#ifdef HAVE_MACHINE_ASM_H
#include <machine/asm.h>
#else
#ifdef __USER_LABEL_PREFIX__
#define CONCAT1(a, b) CONCAT2(a, b)
#define CONCAT2(a, b) a ## b

/* Use the right prefix for global labels.  */
#define CNAME(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
#else
#define CNAME(x) x
#endif
#define ENTRY(x) .globl CNAME(x); .type CNAME(x),%function; CNAME(x):
#endif

	.globl	ffi_call_SYSV
	.globl ffi_closure_raw_asm_SYSV
	.globl abort
	
.text

	# a1:   ffi_prep_args
	# a2:   &ecif
	# a3:   cif->bytes
	# a4:   fig->flags
	# sp+0: ecif.rvalue
	# sp+4: fn

	# This assumes we are using gas.
ffi_call_SYSV:	
.LFB12:    
	# Save registers
 stmfd sp!, {a1-a4, fp, lr}
	
.LCFI0:
	mov   fp, sp

.LCFI1:
.LCFI3:
	# Make room for all of the new args.
	sub   sp, fp, a3

	# Place all of the ffi_prep_args in position
	mov   ip, a1
	mov   a1, sp
	# a2 already set

	# And call
	mov   lr, pc
	mov   pc, ip

	# move first 4 parameters in registers
	ldr   a1, [sp, #0]
	ldr   a2, [sp, #4]
	ldr   a3, [sp, #8]
 ldr   a4, [sp, #12]

	# and adjust stack
	ldr   ip, [fp, #8]
 cmp   ip, #16
	movge ip, #16
 add   sp, sp, ip

	# call function
	mov   lr, pc
	ldr   pc, [fp, #28]

	# Remove the space we pushed for the args
	mov   sp, fp

	# Load a3 with the pointer to storage for the return value
	ldr   a3, [sp, #24]

	# Load a4 with the return type code (cif.flags)
	ldr   a4, [sp, #12]

	# If the return value pointer is NULL, assume no return value.
	cmp   a3, #0
	beq   epilogue

	# Do nothing if void (rk)
 cmp   a4, #FFI_TYPE_VOID
	beq   epilogue

	# return INT
	cmp   a4, #FFI_TYPE_INT
	streq a1, [a3]
	beq   epilogue

	# return FLOAT
	cmp     a4, #FFI_TYPE_FLOAT
#ifdef __SOFTFP__
	streq	a1, [a3]
#else
	stfeqs  f0, [a3]
#endif
	beq     epilogue

	# return DOUBLE or LONGDOUBLE
	cmp     a4, #FFI_TYPE_DOUBLE
#ifdef __SOFTFP__
	stmeqia	a3, {a1, a2}
#else
	stfeqd  f0, [a3]
#endif
	beq     epilogue

	# added by rk, needed for tests
	cmp     a4, #FFI_TYPE_UINT64
	stmeqia	a3, {a1, a2}
	beq     epilogue

	cmp     a4, #FFI_TYPE_SINT64
	stmeqia	a3, {a1, a2}
	beq     epilogue
		
epilogue:
        ldmfd sp!, {a1-a4, fp, pc}
.LFE12:    
.ffi_call_SYSV_end:
    .size    ffi_call_SYSV,.ffi_call_SYSV_end-ffi_call_SYSV
	
#if 1
	# optimized version with stack fix
	
ffi_closure_raw_asm_SYSV:
	stmfd	sp!, {r4, r5, lr}
	mov	ip, r0
	mov	r2, r1
	ldr	r4, [r0, #40]
	sub	sp, sp, #8
	ldr	r3, [r0, #48]
	mov	r1, sp
	mov	r0, r4
	mov	lr, pc
	# call func
	ldr	pc, [ip, #44]
	ldr	r3, [r4, #20]
	mov	r3, r3, asl #16
	mov	r3, r3, lsr #16
	cmp	r3, #1
	mov	r5, sp
	beq	L71
	cmp	r3, #0
	bne	L72
L66:
	add	sp, sp, #8
	
	#ldmfd	sp!, {r4, r5, pc}
	# NOTE:	 Last reg restored must be greatest, else reorder!!!
	ldmfd	sp!, {r4, r5, lr}
	# fix for the args we pushed in the trampoline
	add     sp, sp, #16
	mov     pc, lr
L72:
	bl	abort
	b	L66
L71:
	ldr r0, [sp]
	b	L66
#endif

.section        .eh_frame
.Lframe1:
    .long   .LECIE1-.LSCIE1
.LSCIE1:
    .long   0x0
    .byte   0x1
    .ascii "zR\0"
    .uleb128 0x1
    .sleb128 -4
    .byte   0x8
    .uleb128 0x1
    .byte   0x1b
    .byte   0xc
    .uleb128 0x4
    .uleb128 0x4
    .byte   0x88
    .uleb128 0x1
    .align 4
.LECIE1:
# This is the part you need to tweak:
    
.LSFDE1:
    .long   .LEFDE1-.LASFDE1
.LASFDE1:
    .long   .LASFDE1-.Lframe1
    .long   .LFB12-.
    .long   .LFE12-.LFB12
    .uleb128 0x0
# Advance PC to LCFI0:
    .byte   0x4 
    .long   .LCFI0-.LFB12
# Call Frame Address is same as previous CFA, but at offset 8:
    .byte   0xe
    .uleb128 0x8
# Call Frame Address is at r5 + offset 8:
    .byte   0x85
    .uleb128 0x2
# Advance PC to LCFI1:
    .byte   0x4
    .long   .LCFI1-.LCFI0
# Call Frame Address is in r5, same offset as before:
    .byte   0xd
    .uleb128 0x5
# Advance PC to LCFI3:
    .byte   0x4
    .long   .LCFI3-.LCFI1
# Call Frame Address is in r3 + offset 12:
    .byte   0x83
    .uleb128 0x3
    .align 4
.LEFDE1:
    .set    .LLFDE1,.LEFDE1-.LSFDE1

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]