Bug 829187
Summary: | ocaml ppc64 backend cannot handle more than around 8 parameters in native C call | ||||||||
---|---|---|---|---|---|---|---|---|---|
Product: | [Fedora] Fedora | Reporter: | Richard W.M. Jones <rjones> | ||||||
Component: | ocaml | Assignee: | Richard W.M. Jones <rjones> | ||||||
Status: | CLOSED RAWHIDE | QA Contact: | Fedora Extras Quality Assurance <extras-qa> | ||||||
Severity: | unspecified | Docs Contact: | |||||||
Priority: | unspecified | ||||||||
Version: | rawhide | CC: | c.david86, dwmw2, fedora-ocaml-list, rjones | ||||||
Target Milestone: | --- | ||||||||
Target Release: | --- | ||||||||
Hardware: | ppc64 | ||||||||
OS: | Unspecified | ||||||||
Whiteboard: | |||||||||
Fixed In Version: | Doc Type: | Bug Fix | |||||||
Doc Text: | Story Points: | --- | |||||||
Clone Of: | Environment: | ||||||||
Last Closed: | 2012-06-06 12:37:20 UTC | Type: | Bug | ||||||
Regression: | --- | Mount Type: | --- | ||||||
Documentation: | --- | CRM: | |||||||
Verified Versions: | Category: | --- | |||||||
oVirt Team: | --- | RHEL 7.3 requirements from Atomic Host: | |||||||
Cloudforms Team: | --- | Target Upstream Version: | |||||||
Embargoed: | |||||||||
Attachments: |
|
Description
Richard W.M. Jones
2012-06-06 07:56:31 UTC
Created attachment 589756 [details]
test_c.c
Created attachment 589757 [details]
test.ml
For additional debugging, use this compile command: ocamlopt.opt -g -ccopt -g test.ml test_c.c -o test Then gdb will show symbols at least in the C part: $ gdb ./test (gdb) break test_c Breakpoint 1 at 0x10004f90: file test_c.c, line 13. (gdb) run Starting program: /tmp/test Breakpoint 1, test_c (v1=3, v2=5, v3=7, v4=9, v5=11, v6=13, v7=15, v8=17, v9=29, v10=31, v11=0, v12=268680544, v13=551014606424, v14=551014385208, v15=551014612784) at test_c.c:13 13 { Missing separate debuginfos, use: debuginfo-install glibc-2.15-37.fc17.ppc64 (gdb) bt #0 test_c (v1=3, v2=5, v3=7, v4=9, v5=11, v6=13, v7=15, v8=17, v9=29, v10=31, v11=0, v12=268680544, v13=551014606424, v14=551014385208, v15=551014612784) at test_c.c:13 #1 0x0000000010018fd8 in .caml_c_call () #2 0x000000001000296c in camlTest__code_begin () #3 0x00000000100023b4 in caml_startup__code_begin () #4 0x000000001001915c in .caml_start_program () #5 0x0000000010019850 in .caml_main () #6 0x0000000010002144 in .main () The registers when caml_c_call is called. Note that according to the ppc64 ABI, r3-r10 carry the first 8 parameters: (gdb) info registers r0 0x100023b4 268444596 r1 0xfffffffeb10 17592186039056 r2 0x1003bd60 268680544 r3 0x3 3 # param 1 r4 0x5 5 # param 2 r5 0x7 7 # param 3 r6 0x9 9 # param 4 r7 0xb 11 # param 5 r8 0xd 13 # param 6 r9 0xf 15 # param 7 r10 0x11 17 # param 8 r11 0x10031e58 268639832 r12 0x10018fa4 268537764 r13 0x804b04cc40 551014419520 r14 0x15 21 r15 0x17 23 r16 0x19 25 r17 0x1b 27 r18 0x1d 29 r19 0x1f 31 r20 0x100309f4 268634612 r21 0x100309dc 268634588 r22 0x13 19 r23 0x1800 6144 r24 0xfffb7fd0f50 17590977892176 r25 0x10004f64 268455780 r26 0x10030a5c 268634716 r27 0x10030a74 268634740 r28 0x10030a8c 268634764 r29 0xfffffffed90 17592186039696 r30 0xfffb7dd1000 17590975795200 r31 0xfffb7fd0f48 17590977892168 pc 0x10018fa4 0x10018fa4 <.caml_c_call> msr 0x900000000002d032 10376293541461807154 cr 0x44000484 1140851844 lr 0x1000296c 0x1000296c <camlTest__code_begin+128> ctr 0x10018fa4 268537764 xer 0x20000000 536870912 orig_r3 0x2 2 trap 0x700 1792 The remaining parameters are passed on the stack (r1 is sp). I have reformatted the output to make the stack layout clearer: (gdb) x/32x 0xfffffffeb10 # stack pointer 0xfffffffeb10: 0x00000fff 0xffffebc0 0x00000000 0x00000000 0xfffffffeb20: 0x00000000 0x00000001 0x00000000 0x00000000 0xfffffffeb30: 0x00000000 0x00000001 0x00000000 0x1003bd60 0xfffffffeb40: 0x00000fff 0xffffebf0 0x00000000 0x10030a74 0xfffffffeb50: 0x00000000 0x10030a8c 0x00000000 0x00000013 # sp+0x48 == param 9 0xfffffffeb60: 0x00000000 0x00000015 # param 10 0x00000000 0x00000017 # param 11 0xfffffffeb70: 0x00000000 0x00000019 # param 12 0x00000000 0x0000001b # param 13 0xfffffffeb80: 0x00000000 0x0000001d # param 14 XXX 0x00000000 0x0000001f # param 15 0xfffffffeb90: 0x00000000 0x00000000 0x00000000 0x1003bd60 0xfffffffeba0: 0x00000080 0x4b07a658 0x00000080 0x4b044638 0xfffffffebb0: 0x00000080 0x4b07bf30 0x00000000 0xffffffff 0xfffffffebc0: 0x00000fff 0xffffec20 0x00000000 0x00000000 0xfffffffebd0: 0x00000000 0x100023b4 0x00000000 0x00000000 0xfffffffebe0: 0x00000000 0x00000000 0x00000000 0x1003bd60 0xfffffffebf0: 0x00000000 0x00000000 0x00000000 0x00000000 0xfffffffec00: 0x00000000 0x00000000 0x00000000 0x00000000 XXX == what the C function thinks is parameter 9. Notes about parameter passing, derived from the ppc64 ABI: http://refspecs.linuxfoundation.org/ELF/ppc64/PPC-elf64abi-1.9.html#PARAM-PASS (1) The parameter save area starts at sp + 0x30 (sp + 48). (2) Although the first 8 parameters are passed in r3-r10, space is still reserved for them in the parameter save area (in case they need to be spilled by the callee). Therefore addresses sp + 0x30 .. sp + 0x6f are reserved, although they are not initialized and therefore contain random data. (3) The parameters 9 onwards should appear at sp + 0x70 onwards. In fact, this is precisely where the C function is looking for them ("XXX" in the comment above). (4) The OCaml part is NOT saving parameters 9+ at the correct location. For some reason it saves them starting at sp + 0x48. Note that pure OCaml programs work fine: $ cat test-ocaml.ml open Printf let test i1 i2 i3 i4 i5 i6 i7 i8 i9 i10 i11 i12 i13 i14 i15 = printf "%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n" i1 i2 i3 i4 i5 i6 i7 i8 i9 i10 i11 i12 i13 i14 i15 let () = test 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 $ ocamlopt.opt test-ocaml.ml -o test-ocaml File "test-ocaml.ml", line 1, characters 0-1: Warning 24: bad source file name: "Test-ocaml" is not a valid module name. $ ./test-ocaml 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 I think I see the problem: The Cextcall/Iextcall code calls Proc.loc_external_arguments. But this function hard codes a parameter offset of 8 (instead of, presumably, 48). Notice the difference is 40, which also happens to be the displacement of the stack arguments from where they are expected to be. http://git.infradead.org/users/dwmw2/ocaml-ppc64.git/blob/HEAD:/asmcomp/power64/proc.ml#l191 I have changed this to 48 and I am recompiling the compiler to see if this makes a difference. Patch: diff --git a/asmcomp/power64/proc.ml b/asmcomp/power64/proc.ml index 67f26ab..119ad93 100644 --- a/asmcomp/power64/proc.ml +++ b/asmcomp/power64/proc.ml @@ -188,7 +188,7 @@ let poweropen_external_conventions first_int last_int let loc_external_arguments = match Config.system with | "rhapsody" -> poweropen_external_conventions 0 7 100 112 - | "elf" | "bsd" -> calling_conventions 0 7 100 107 outgoing 8 + | "elf" | "bsd" -> calling_conventions 0 7 100 107 outgoing 48 | _ -> assert false let extcall_use_push = false Looks good to me; thanks. Fix included in OCaml 3.12.1-11. However this fix hasn't got completely to the bottom of things. I still see a segfault in the libguestfs OCaml bindings, so there is some other issue going on. Will open another bug if required. The other issue I'm seeing appears to be related to an existing bug: https://bugzilla.redhat.com/show_bug.cgi?id=826649#c5 |