[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#627132: New "-custom" binary generation breaks stack backtraces



>>>>> "SG" == Stephane Glondu <glondu@debian.org> writes:

SG> Le 17/05/2011 23:33, Stephen McCamant a ecrit :
SMcC> [...] another suitable workaround from our perspective would be
SMcC> if there was a way to disable the new "-output-obj"-style
SMcC> behavior.

SG> The previous behaviour was compiling a runtime (as with
SG> -make-runtime), a pure bytecode using this runtime (as with
SG> -use-runtime), and concatenating both.

SG> Did you try this way to see if backtraces are still broken?

I hadn't tried anything like this before. Here are two possible
interpretations of your suggestion:

1. I first tried what seemed closest to what you were suggesting
there. With some tweaking this seems to work.

I previously had a command "ocamlc ... -o prog.dbg", and I
tried replacing it with two commands,

ocamlc -make-runtime -o prog.runtime -ccopt -Wl,--export-dynamic ...

and

ocamlc -use-runtime ./prog.runtime ... -o prog.dbg.cbc

This makes prog.dbg.cbc as a "#!..././prog.runtime" executable. So you
can either run prog.dbg.cbc directly, or equivalently "./prog.runtime
prog.dbg.cbc", and they both work including backtraces.

The one trick that wasn't immediately obvious is the "-ccopt
-Wl,--export-dynamic", which tells the linker to make the symbols from
the binary available to libraries subsequently loaded with
dlopen(). If you don't have that, you get an error:

Fatal error: cannot load shared library dllcamlstr
Reason: /usr/lib/ocaml/stublibs/dllcamlstr.so: undefined symbol: caml_string_length

The function is indeed undefined in dllcamlstr.so, but it is defined
in the prog.runtime executable.

So this approach does seem to create two files that together are a
complete replacement from what we used to have in a single file.

Concatenating these two files (first the runtime, then the bytecode)
also works, but it's less convenient because the runtime doesn't know
it has to look at the end of itself for the bytecode: you have to pass
the concatenated program as its own first argument (another trick that
was not immediately obvious to me).

2. Another related thing I tried was taking the ELF executable
compiled with the new "-custom", and appending the bytecode file
generated with -use-runtime to the end. This seems closer to
reproducing a single concatenated file like came from the old
"-custom", with the downside that the executable has two copies of the
bytecode. This generates a program that runs OK, but backtraces still
don't quite work. With "strace", I see the following:

write(2, "Fatal error: exception Failure(\""..., 48Fatal error: exception Failure("int_of_string")
) = 48
stat64("/home/smcc/bin/", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
stat64("/home/smcc/bin/i386/", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
stat64("/bin/", {st_mode=S_IFDIR|0755, st_size=3000, ...}) = 0
stat64("/usr/local/bin/", {st_mode=S_IFDIR|S_ISGID|0775, st_size=48, ...}) = 0
stat64("/usr/bin/", {st_mode=S_IFDIR|0755, st_size=156576, ...}) = 0
stat64("/usr/X11R6/bin/", 0xffffd3d0)   = -1 ENOENT (No such file or directory)
stat64("/usr/sbin/", {st_mode=S_IFDIR|0755, st_size=13464, ...}) = 0
stat64("/sbin/", {st_mode=S_IFDIR|0755, st_size=5568, ...}) = 0
open("", O_RDONLY|O_LARGEFILE)          = -1 ENOENT (No such file or directory)
write(2, "(Program not linked with -g, can"..., 59(Program not linked with -g, cannot print stack backtrace)
) = 59
exit_group(2)                           = ?

I haven't checked the source code for this, but my first guess is that
the program might be trying to find its own executable by looking in
$PATH (/home/smcc/bin through /sbin) and the current directory. The
reason it's currently failing is that it's using "" as the program
name, which is of course incorrect. This maybe would work well enough
if the program used argv[0] instead of "", but using /proc/self/exe
would really be better, IMO.

So in summary, I think (1) is the best work-around so far if one
really wants to have bytecode (for ocamldebug, maybe?), while just
generating native code with -g (Eric Cooper's suggestion) gives you
the other advantages of native code plus backtraces if you're using
3.10 or later.

 -- Stephen



Reply to: