This is the mail archive of the
java@gcc.gnu.org
mailing list for the Java project.
Re: Interpreter/libffi ARM Porting
- From: "Craig A. Vanderborgh" <craigv at voxware dot com>
- To: Andrew Haley <aph at redhat dot com>
- Cc: java at gcc dot gnu dot org
- Date: Wed, 16 Jun 2004 17:02:30 -0400
- Subject: Re: Interpreter/libffi ARM Porting
- Organization: voxware incorporated
- References: <16592.28676.975738.816767@cuddles.cambridge.redhat.com>
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