Hello all,
I am trying to track down a problem with the frama-c package. It runs normally on i386 and x86_64, but exits immediately with an unhandled exception on arm. It is written in ocaml, which makes debugging difficult. I tried running it under valgrind to see if I could get any clues, but valgrind says:
disInstr(arm): unhandled instruction: 0xEEBA5BEF cond=14(0xE) 27:20=235(0xEB) 4:4=0 3:0=15(0xF) ==23036== valgrind: Unrecognised instruction at address 0x4f2d30. ==23036== at 0x4F2D30: caml_adjust_gc_speed (in /home/jamesjer/rpmbuild/BUILD/frama-c-Fluorine-20130601/bin/toplevel.opt)
A gdb disassembly of the containing function shows that instruction as:
0x004f2d30 <+128>: vcvt.f64.s32 d5, d5, #1
Is that a legal instruction? I'm wondering if I should file a bug against valgrind for not recognizing the instruction, or whether something in the toolchain is emitting an instruction that is not valid for all CPUs in the class Fedora supports.
Thank you for any help you can provide.
On Thu, Aug 08, 2013 at 04:16:49PM -0600, Jerry James wrote:
Hello all,
I am trying to track down a problem with the frama-c package. It runs normally on i386 and x86_64, but exits immediately with an unhandled exception on arm. It is written in ocaml, which makes debugging difficult.
[Sorry for the late response]
GDB should work fine. It certainly works for x86 OCaml programs.
There is a fairly simple relationship between OCaml module + function names and the assembly function names exposed in the DWARF information, with the only caveat being that multiple functions in a single OCaml module are allowed to have the same name (each assembler function will have a number after it, but they are not consecutive). If you get that it's best to try to correlate the assembly output with the function name. The situation recently improved greatly on x86, now that the DWARF info contains source file+line#, but I don't know if that happened for ARM.
OCaml doesn't have a 'main' function as such, but any top level code in any module will be executed at load time. This makes debugging without GDB a pain, but with GDB it's pretty simple. However I've also seen crashes (back when the ppc64 backend had a codegen bug) happen before entering the main OCaml code, and those can be a real pain ...
A final caveat is stack overflows. These can happen if the source is not tail recursive, but the stack on some architectures is larger than on others (ie. you'd see a strange architectural difference). Often you can "fix" these by raising the stack ulimit. In any case, if you are encountering a stack overflow on ARM, then it's a bug that upstream should fix by rewriting the code to be tail recursive or more imperative.
I tried running it under valgrind to see if I could get any clues, but valgrind says:
disInstr(arm): unhandled instruction: 0xEEBA5BEF cond=14(0xE) 27:20=235(0xEB) 4:4=0 3:0=15(0xF) ==23036== valgrind: Unrecognised instruction at address 0x4f2d30. ==23036== at 0x4F2D30: caml_adjust_gc_speed (in /home/jamesjer/rpmbuild/BUILD/frama-c-Fluorine-20130601/bin/toplevel.opt)
A gdb disassembly of the containing function shows that instruction as:
0x004f2d30 <+128>: vcvt.f64.s32 d5, d5, #1
Is that a legal instruction? I'm wondering if I should file a bug against valgrind for not recognizing the instruction, or whether something in the toolchain is emitting an instruction that is not valid for all CPUs in the class Fedora supports.
This might be a problem with the new ARM code generator[a] (ie. an OCaml compiler problem). Things to do would include:
(1) Getting a stack trace from GDB and try to correlate it back to the source code.
(2) Trying to chop down the code to get the minimal program which segfaults.
(3) Contacting Benedikt Meurer or caml-list about it, although it'd be better if we had the results of (1)+(2) in hand before we did this.
Rich.
[a] http://caml.inria.fr/mantis/print_bug_page.php?bug_id=5433
On Wed, Aug 21, 2013 at 1:34 PM, Richard W.M. Jones rjones@redhat.com wrote:
[Sorry for the late response]
Sorry I didn't mention that I solved my problem already!
GDB should work fine. It certainly works for x86 OCaml programs.
There is a fairly simple relationship between OCaml module + function names and the assembly function names exposed in the DWARF information, with the only caveat being that multiple functions in a single OCaml module are allowed to have the same name (each assembler function will have a number after it, but they are not consecutive). If you get that it's best to try to correlate the assembly output with the function name. The situation recently improved greatly on x86, now that the DWARF info contains source file+line#, but I don't know if that happened for ARM.
Ah, yes, a useful debuginfo package is now generated on x86. That's nice. Is there any chance we could start throwing out all the stuff in the ocaml spec files that prevents debuginfo package generation? Or will that cause problems on non-x86 platforms?
As for this bug, it did happen before entering the main OCaml code. By single stepping through assembly code (that was fun), I was able to eventually drop back down into OCaml code, which is where the problem turned out to be (in an initializer). Upstream produced a fix for me, and the package has already been rebuilt with that fix. But even though the code now runs fine and gdb can disassemble the function in question, valgrind still doesn't like that CPU instruction (which has nothing whatever to do with the actual bug, by the way).
Thanks, Richard.
On Thu, Aug 22, 2013 at 03:33:45PM -0600, Jerry James wrote:
On Wed, Aug 21, 2013 at 1:34 PM, Richard W.M. Jones rjones@redhat.com wrote:
[Sorry for the late response]
Sorry I didn't mention that I solved my problem already!
GDB should work fine. It certainly works for x86 OCaml programs.
There is a fairly simple relationship between OCaml module + function names and the assembly function names exposed in the DWARF information, with the only caveat being that multiple functions in a single OCaml module are allowed to have the same name (each assembler function will have a number after it, but they are not consecutive). If you get that it's best to try to correlate the assembly output with the function name. The situation recently improved greatly on x86, now that the DWARF info contains source file+line#, but I don't know if that happened for ARM.
Ah, yes, a useful debuginfo package is now generated on x86. That's nice. Is there any chance we could start throwing out all the stuff in the ocaml spec files that prevents debuginfo package generation? Or will that cause problems on non-x86 platforms?
Yes, this would be a good idea ... I don't think it'll cause problems on non-x86. Worst case it would just produce non-functional debuginfo files there.
As for this bug, it did happen before entering the main OCaml code. By single stepping through assembly code (that was fun), I was able to eventually drop back down into OCaml code, which is where the problem turned out to be (in an initializer). Upstream produced a fix for me, and the package has already been rebuilt with that fix. But even though the code now runs fine and gdb can disassemble the function in question, valgrind still doesn't like that CPU instruction (which has nothing whatever to do with the actual bug, by the way).
I guess a missing emulation of this insn in valgrind, but I'll let people who know more about ARM answer that!
Rich.