| Attached Files | embedded-caml-debug.diff [^] (13,950 bytes) 2009-04-02 19:32 [Show Content] [Hide Content]Index: debugger/Makefile.shared
===================================================================
--- debugger/Makefile.shared (revision 178)
+++ debugger/Makefile.shared (revision 183)
@@ -60,11 +60,11 @@
pos.cmo \
checkpoints.cmo \
events.cmo \
+ program_loading.cmo \
symbols.cmo \
breakpoints.cmo \
trap_barrier.cmo \
history.cmo \
- program_loading.cmo \
printval.cmo \
show_source.cmo \
time_travel.cmo \
Index: debugger/symbols.ml
===================================================================
--- debugger/symbols.ml (revision 178)
+++ debugger/symbols.ml (revision 183)
@@ -17,6 +17,7 @@
open Instruct
open Debugger_config (* Toplevel *)
+open Program_loading
let modules =
ref ([] : string list)
@@ -61,6 +62,17 @@
List.iter (relocate_event orig) evl;
eventlists := evl :: !eventlists
done;
+ begin try
+ ignore (Bytesections.seek_section ic "CODE")
+ with Not_found ->
+ (* Debug info file - activate manual loading mode *)
+ let rec find = function
+ [] -> assert false
+ | (mode,lfun)::tl ->
+ if mode = "manual" then set_launching_function lfun else find tl
+ in
+ find loading_modes
+ end;
close_in_noerr ic;
!eventlists
Index: bytecomp/bytelink.ml
===================================================================
--- bytecomp/bytelink.ml (revision 178)
+++ bytecomp/bytelink.ml (revision 183)
@@ -381,7 +381,14 @@
let link_bytecode_as_c tolink outfile =
let outchan = open_out outfile in
- try
+ let cds_file =
+ if !Clflags.debug then
+ let basename = Filename.chop_extension outfile in
+ (if Filename.is_relative basename
+ then Filename.concat (Sys.getcwd ()) basename
+ else basename) ^ ".cds"
+ else "" in
+ begin try
(* The bytecode *)
output_string outchan "#include <caml/mlvalues.h>\n";
output_string outchan "\
@@ -393,8 +400,11 @@
output_string outchan "static int caml_code[] = {\n";
Symtable.init();
Consistbl.clear crc_interfaces;
- let output_fun = output_code_string outchan
- and currpos_fun () = 0 in
+ let currpos = ref 0 in
+ let output_fun code =
+ output_code_string outchan code;
+ currpos := !currpos + String.length code
+ and currpos_fun () = !currpos in
List.iter (link_file output_fun currpos_fun) tolink;
(* The final STOP instruction *)
Printf.fprintf outchan "\n0x%x};\n\n" Opcodes.opSTOP;
@@ -414,6 +424,10 @@
output_string outchan "\n};\n\n";
(* The table of primitives *)
Symtable.output_primitive_table outchan;
+ (* cds file name *)
+ output_string outchan "\nstatic char caml_cds_file[] = {\n";
+ output_data_string outchan cds_file;
+ output_string outchan "0\n};\n\n";
(* The entry point *)
output_string outchan "\n
void caml_startup(char ** argv)
@@ -421,12 +435,34 @@
caml_startup_code(caml_code, sizeof(caml_code),
caml_data, sizeof(caml_data),
caml_sections, sizeof(caml_sections),
+ caml_cds_file,
argv);
}\n";
close_out outchan
with x ->
close_out outchan;
raise x
+ end;
+ if cds_file != "" then
+ try
+ remove_file cds_file; (* avoid permission problems *)
+ let outchan =
+ open_out_gen [Open_wronly; Open_trunc; Open_creat; Open_binary]
+ 0o777 cds_file in
+ Bytesections.init_record outchan;
+ (* The map of global identifiers *)
+ Symtable.output_global_map outchan;
+ Bytesections.record outchan "SYMB";
+ (* Debug info *)
+ output_debug_info outchan;
+ Bytesections.record outchan "DBUG";
+ (* The table of contents and the trailer *)
+ Bytesections.write_toc_and_trailer outchan;
+ close_out outchan
+ with x ->
+ close_out outchan;
+ remove_file cds_file;
+ raise x
(* Build a custom runtime *)
Index: byterun/win32.c
===================================================================
--- byterun/win32.c (revision 178)
+++ byterun/win32.c (revision 183)
@@ -374,6 +374,16 @@
return 0;
}
+int caml_executable_name(char * name, int name_len)
+{
+ DWORD retcode;
+
+ retcode = GetModuleFileName(NULL, name, name_len);
+ if (retcode == 0 || retcode >= name_len) return -1;
+ name[retcode] = 0;
+ return 0;
+}
+
#ifndef NATIVE_CODE
/* Set up a new thread for control-C emulation and termination */
Index: byterun/osdeps.h
===================================================================
--- byterun/osdeps.h (revision 178)
+++ byterun/osdeps.h (revision 183)
@@ -63,8 +63,10 @@
Return 0 on success, -1 on error; set errno in the case of error. */
extern int caml_read_directory(char * dirname, struct ext_table * contents);
-#ifdef __linux__
-/* Recover executable name from /proc/self/exe if possible */
+#if defined(__linux__) || defined(_WIN32)
+/* Recover executable name if possible
+ from /proc/self/exe (linux) or
+ from GetModuleFileName() (Windows) */
extern int caml_executable_name(char * name, int name_len);
#endif
Index: byterun/startup.c
===================================================================
--- byterun/startup.c (revision 178)
+++ byterun/startup.c (revision 183)
@@ -101,14 +101,20 @@
}
int caml_attempt_open(char **name, struct exec_trailer *trail,
- int do_open_script)
+ int do_open_script, int do_search_exe_in_path)
{
char * truename;
int fd;
int err;
char buf [2];
- truename = caml_search_exe_in_path(*name);
+ if (!do_search_exe_in_path) {
+ truename = caml_search_exe_in_path(*name);
+ }
+ else {
+ truename = caml_stat_alloc(strlen(*name)+1);
+ strcpy(truename, *name);
+ }
*name = truename;
caml_gc_message(0x100, "Opening bytecode executable %s\n",
(uintnat) truename);
@@ -176,7 +182,7 @@
int32 caml_seek_section(int fd, struct exec_trailer *trail, char *name)
{
int32 len = caml_seek_optional_section(fd, trail, name);
- if (len == -1)
+ if (len == -1)
caml_fatal_error_arg("Fatal_error: section `%s' is missing\n", name);
return len;
}
@@ -358,13 +364,13 @@
if (caml_executable_name(proc_self_exe, sizeof(proc_self_exe)) == 0)
exe_name = proc_self_exe;
#endif
- fd = caml_attempt_open(&exe_name, &trail, 0);
+ fd = caml_attempt_open(&exe_name, &trail, 0, 0);
if (fd < 0) {
pos = parse_command_line(argv);
if (argv[pos] == 0)
caml_fatal_error("No bytecode file specified.\n");
exe_name = argv[pos];
- fd = caml_attempt_open(&exe_name, &trail, 1);
+ fd = caml_attempt_open(&exe_name, &trail, 1, 0);
switch(fd) {
case FILE_NOT_FOUND:
caml_fatal_error_arg("Fatal error: cannot find file %s\n", argv[pos]);
@@ -436,6 +442,7 @@
code_t code, asize_t code_size,
char *data, asize_t data_size,
char *section_table, asize_t section_table_size,
+ char *cds_name,
char **argv)
{
value res;
@@ -445,6 +452,7 @@
#ifdef DEBUG
caml_verb_gc = 63;
#endif
+ caml_cds_name = cds_name;
parse_camlrunparam();
caml_external_raise = NULL;
/* Initialize the abstract machine */
@@ -454,8 +462,17 @@
init_atoms();
/* Initialize the interpreter */
caml_interprete(NULL, 0);
+ /* Initialize the debugger, if needed */
+ caml_debugger_init();
/* Load the code */
caml_start_code = code;
+ caml_code_size = code_size;
+ if (caml_debugger_in_use) {
+ int len, i;
+ len = code_size / sizeof(opcode_t);
+ caml_saved_code = (unsigned char *) caml_stat_alloc(len);
+ for (i = 0; i < len; i++) caml_saved_code[i] = caml_start_code[i];
+ }
#ifdef THREADED_CODE
caml_thread_code(caml_start_code, code_size);
#endif
@@ -472,7 +489,16 @@
/* Run the code */
caml_init_exceptions();
caml_sys_init("", argv);
+ /* Execute the program */
+ caml_debugger(PROGRAM_START);
res = caml_interprete(caml_start_code, code_size);
- if (Is_exception_result(res))
- caml_fatal_uncaught_exception(Extract_exception(res));
+ if (Is_exception_result(res)) {
+ caml_exn_bucket = Extract_exception(res);
+ if (caml_debugger_in_use) {
+ caml_extern_sp = &caml_exn_bucket; /* The debugger needs the
+ exception value.*/
+ caml_debugger(UNCAUGHT_EXC);
+ }
+ caml_fatal_uncaught_exception(caml_exn_bucket);
+ }
}
Index: byterun/startup.h
===================================================================
--- byterun/startup.h (revision 178)
+++ byterun/startup.h (revision 183)
@@ -25,12 +25,13 @@
code_t code, asize_t code_size,
char *data, asize_t data_size,
char *section_table, asize_t section_table_size,
+ char *cds_name,
char **argv);
enum { FILE_NOT_FOUND = -1, BAD_BYTECODE = -2 };
extern int caml_attempt_open(char **name, struct exec_trailer *trail,
- int do_open_script);
+ int do_open_script, int do_search_exe_in_path);
extern void caml_read_section_descriptors(int fd, struct exec_trailer *trail);
extern int32 caml_seek_optional_section(int fd, struct exec_trailer *trail,
char *name);
Index: byterun/sys.c
===================================================================
--- byterun/sys.c (revision 178)
+++ byterun/sys.c (revision 183)
@@ -212,6 +212,7 @@
}
char * caml_exe_name;
+char * caml_cds_name;
static char ** caml_main_argv;
CAMLprim value caml_sys_get_argv(value unit)
Index: byterun/backtrace.c
===================================================================
--- byterun/backtrace.c (revision 178)
+++ byterun/backtrace.c (revision 183)
@@ -17,7 +17,9 @@
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include <fcntl.h>
+#include <sys/stat.h>
#include "config.h"
#ifdef HAS_UNISTD
#include <unistd.h>
@@ -34,7 +36,20 @@
#include "stacks.h"
#include "sys.h"
#include "backtrace.h"
+#include "osdeps.h"
+#if !defined (_WIN32) && !macintosh
+#include <sys/param.h>
+#endif
+
+#ifndef PATH_MAX
+#ifdef MAXPATHLEN
+#define PATH_MAX MAXPATHLEN
+#else
+#define PATH_MAX 512
+#endif
+#endif
+
CAMLexport int caml_backtrace_active = 0;
CAMLexport int caml_backtrace_pos = 0;
CAMLexport code_t * caml_backtrace_buffer = NULL;
@@ -116,10 +131,82 @@
}
}
-/* Read the debugging info contained in the current bytecode executable.
- Return a Caml array of Caml lists of debug_event records in "events",
- or Val_false on failure. */
+/* Search for the debugging info in a bytecode file */
+static int open_debug_info(char * file_name, int * pfd, int do_search_in_path)
+{
+ char * name;
+ struct exec_trailer trail;
+
+ name = file_name;
+ *pfd = caml_attempt_open(&name, &trail, 1, do_search_in_path);
+ caml_stat_free(name);
+ if (*pfd < 0) return -1;
+ caml_read_section_descriptors(*pfd, &trail);
+ if (caml_seek_optional_section(*pfd, &trail, "DBUG") == -1) {
+ close(*pfd);
+ return -1;
+ }
+ else return 0;
+}
+
+/* Search for the debugging info in the separate .cds file */
+
+static int open_debug_info_cds(char * cds_name, int * pfd)
+{
+ char full_name[PATH_MAX];
+ char base_name[PATH_MAX];
+ char * p;
+ struct ext_table path;
+ char * tofree;
+
+ /* Search by the absolute path */
+ if (open_debug_info(cds_name, pfd, 1) == 0) return 0;
+
+ /* Find base name in cds_name */
+ p = cds_name + strlen(cds_name) - 1;
+ for (/*nothing*/; p >= cds_name; --p) {
+ if (*p == '\\' || *p == '/'){
+ ++p;
+ break;
+ }
+ }
+ strncpy(base_name, p, sizeof(full_name));
+
+#if defined(__linux__) || defined(_WIN32)
+ /* Search in the process' directory */
+ if (caml_executable_name(full_name, sizeof(full_name)) == 0){
+ /* Strip file name from the process path */
+ p = full_name + strlen(full_name) - 1;
+ for (/*nothing*/; p >= full_name; --p) {
+ if (*p == '\\' || *p == '/'){
+ *(p + 1) = '\0';
+ break;
+ }
+ }
+ /* Merge with the base name */
+ strncat(full_name, base_name, sizeof(full_name));
+ if (open_debug_info(full_name, pfd, 1) == 0) return 0;
+ }
+#endif
+
+ /* Search by the environment variable */
+ caml_ext_table_init(&path, 8);
+ tofree = caml_decompose_path(&path, getenv("CAML_SYMBOL_PATH"));
+ p = caml_search_in_path(&path, base_name);
+ strncpy(full_name, p, sizeof(full_name));
+ caml_stat_free(p);
+ caml_stat_free(tofree);
+ caml_ext_table_free(&path, 0);
+ if (open_debug_info(full_name, pfd, 1) == 0) return 0;
+
+ return -1;
+}
+
+/* Read the debugging info contained in the separate .cds file or in the
+ current bytecode executable. Return a Caml array of Caml lists of
+ debug_event records in "events", or Val_false on failure. */
+
#ifndef O_BINARY
#define O_BINARY 0
#endif
@@ -128,21 +215,17 @@
{
CAMLparam0();
CAMLlocal1(events);
- char * exec_name;
int fd;
- struct exec_trailer trail;
struct channel * chan;
uint32 num_events, orig, i;
value evl, l;
- exec_name = caml_exe_name;
- fd = caml_attempt_open(&exec_name, &trail, 1);
- if (fd < 0) CAMLreturn(Val_false);
- caml_read_section_descriptors(fd, &trail);
- if (caml_seek_optional_section(fd, &trail, "DBUG") == -1) {
- close(fd);
- CAMLreturn(Val_false);
+ if (caml_cds_name != NULL){
+ if (open_debug_info_cds(caml_cds_name, &fd)) CAMLreturn(Val_false);
}
+ else {
+ if (open_debug_info(caml_exe_name, &fd, 0)) CAMLreturn(Val_false);
+ }
chan = caml_open_descriptor_in(fd);
num_events = caml_getword(chan);
events = caml_alloc(num_events, 0);
Index: byterun/sys.h
===================================================================
--- byterun/sys.h (revision 178)
+++ byterun/sys.h (revision 183)
@@ -26,5 +26,6 @@
CAMLextern value caml_sys_exit (value);
extern char * caml_exe_name;
+extern char * caml_cds_name;
#endif /* CAML_SYS_H */
embedded-caml-debug2.diff [^] (14,036 bytes) 2009-04-03 11:35 [Show Content] [Hide Content]Index: debugger/Makefile.shared
===================================================================
--- debugger/Makefile.shared (revision 178)
+++ debugger/Makefile.shared (revision 185)
@@ -60,11 +60,11 @@
pos.cmo \
checkpoints.cmo \
events.cmo \
+ program_loading.cmo \
symbols.cmo \
breakpoints.cmo \
trap_barrier.cmo \
history.cmo \
- program_loading.cmo \
printval.cmo \
show_source.cmo \
time_travel.cmo \
Index: debugger/symbols.ml
===================================================================
--- debugger/symbols.ml (revision 178)
+++ debugger/symbols.ml (revision 185)
@@ -17,6 +17,7 @@
open Instruct
open Debugger_config (* Toplevel *)
+open Program_loading
let modules =
ref ([] : string list)
@@ -61,6 +62,17 @@
List.iter (relocate_event orig) evl;
eventlists := evl :: !eventlists
done;
+ begin try
+ ignore (Bytesections.seek_section ic "CODE")
+ with Not_found ->
+ (* Debug info file - activate manual loading mode *)
+ let rec find = function
+ [] -> assert false
+ | (mode,lfun)::tl ->
+ if mode = "manual" then set_launching_function lfun else find tl
+ in
+ find loading_modes
+ end;
close_in_noerr ic;
!eventlists
Index: bytecomp/bytelink.ml
===================================================================
--- bytecomp/bytelink.ml (revision 178)
+++ bytecomp/bytelink.ml (revision 185)
@@ -381,7 +381,14 @@
let link_bytecode_as_c tolink outfile =
let outchan = open_out outfile in
- try
+ let cds_file =
+ if !Clflags.debug then
+ let basename = Filename.chop_extension outfile in
+ (if Filename.is_relative basename
+ then Filename.concat (Sys.getcwd ()) basename
+ else basename) ^ ".cds"
+ else "" in
+ begin try
(* The bytecode *)
output_string outchan "#include <caml/mlvalues.h>\n";
output_string outchan "\
@@ -393,8 +400,11 @@
output_string outchan "static int caml_code[] = {\n";
Symtable.init();
Consistbl.clear crc_interfaces;
- let output_fun = output_code_string outchan
- and currpos_fun () = 0 in
+ let currpos = ref 0 in
+ let output_fun code =
+ output_code_string outchan code;
+ currpos := !currpos + String.length code
+ and currpos_fun () = !currpos in
List.iter (link_file output_fun currpos_fun) tolink;
(* The final STOP instruction *)
Printf.fprintf outchan "\n0x%x};\n\n" Opcodes.opSTOP;
@@ -414,6 +424,10 @@
output_string outchan "\n};\n\n";
(* The table of primitives *)
Symtable.output_primitive_table outchan;
+ (* cds file name *)
+ output_string outchan "\nstatic char caml_cds_file[] = {\n";
+ output_data_string outchan cds_file;
+ output_string outchan "0\n};\n\n";
(* The entry point *)
output_string outchan "\n
void caml_startup(char ** argv)
@@ -421,12 +435,34 @@
caml_startup_code(caml_code, sizeof(caml_code),
caml_data, sizeof(caml_data),
caml_sections, sizeof(caml_sections),
+ caml_cds_file,
argv);
}\n";
close_out outchan
with x ->
close_out outchan;
raise x
+ end;
+ if cds_file != "" then
+ try
+ remove_file cds_file; (* avoid permission problems *)
+ let outchan =
+ open_out_gen [Open_wronly; Open_trunc; Open_creat; Open_binary]
+ 0o777 cds_file in
+ Bytesections.init_record outchan;
+ (* The map of global identifiers *)
+ Symtable.output_global_map outchan;
+ Bytesections.record outchan "SYMB";
+ (* Debug info *)
+ output_debug_info outchan;
+ Bytesections.record outchan "DBUG";
+ (* The table of contents and the trailer *)
+ Bytesections.write_toc_and_trailer outchan;
+ close_out outchan
+ with x ->
+ close_out outchan;
+ remove_file cds_file;
+ raise x
(* Build a custom runtime *)
Index: byterun/win32.c
===================================================================
--- byterun/win32.c (revision 178)
+++ byterun/win32.c (revision 185)
@@ -374,6 +374,16 @@
return 0;
}
+int caml_executable_name(char * name, int name_len)
+{
+ DWORD retcode;
+
+ retcode = GetModuleFileName(NULL, name, name_len);
+ if (retcode == 0 || retcode >= name_len) return -1;
+ name[retcode] = 0;
+ return 0;
+}
+
#ifndef NATIVE_CODE
/* Set up a new thread for control-C emulation and termination */
Index: byterun/osdeps.h
===================================================================
--- byterun/osdeps.h (revision 178)
+++ byterun/osdeps.h (revision 185)
@@ -63,8 +63,10 @@
Return 0 on success, -1 on error; set errno in the case of error. */
extern int caml_read_directory(char * dirname, struct ext_table * contents);
-#ifdef __linux__
-/* Recover executable name from /proc/self/exe if possible */
+#if defined(__linux__) || defined(_WIN32)
+/* Recover executable name if possible
+ from /proc/self/exe (linux) or
+ from GetModuleFileName() (Windows) */
extern int caml_executable_name(char * name, int name_len);
#endif
Index: byterun/startup.c
===================================================================
--- byterun/startup.c (revision 178)
+++ byterun/startup.c (revision 185)
@@ -101,14 +101,20 @@
}
int caml_attempt_open(char **name, struct exec_trailer *trail,
- int do_open_script)
+ int do_open_script, int do_search_exe_in_path)
{
char * truename;
int fd;
int err;
char buf [2];
- truename = caml_search_exe_in_path(*name);
+ if (!do_search_exe_in_path) {
+ truename = caml_search_exe_in_path(*name);
+ }
+ else {
+ truename = caml_stat_alloc(strlen(*name)+1);
+ strcpy(truename, *name);
+ }
*name = truename;
caml_gc_message(0x100, "Opening bytecode executable %s\n",
(uintnat) truename);
@@ -176,7 +182,7 @@
int32 caml_seek_section(int fd, struct exec_trailer *trail, char *name)
{
int32 len = caml_seek_optional_section(fd, trail, name);
- if (len == -1)
+ if (len == -1)
caml_fatal_error_arg("Fatal_error: section `%s' is missing\n", name);
return len;
}
@@ -358,13 +364,13 @@
if (caml_executable_name(proc_self_exe, sizeof(proc_self_exe)) == 0)
exe_name = proc_self_exe;
#endif
- fd = caml_attempt_open(&exe_name, &trail, 0);
+ fd = caml_attempt_open(&exe_name, &trail, 0, 0);
if (fd < 0) {
pos = parse_command_line(argv);
if (argv[pos] == 0)
caml_fatal_error("No bytecode file specified.\n");
exe_name = argv[pos];
- fd = caml_attempt_open(&exe_name, &trail, 1);
+ fd = caml_attempt_open(&exe_name, &trail, 1, 0);
switch(fd) {
case FILE_NOT_FOUND:
caml_fatal_error_arg("Fatal error: cannot find file %s\n", argv[pos]);
@@ -436,6 +442,7 @@
code_t code, asize_t code_size,
char *data, asize_t data_size,
char *section_table, asize_t section_table_size,
+ char *cds_name,
char **argv)
{
value res;
@@ -445,6 +452,7 @@
#ifdef DEBUG
caml_verb_gc = 63;
#endif
+ caml_cds_name = cds_name;
parse_camlrunparam();
caml_external_raise = NULL;
/* Initialize the abstract machine */
@@ -454,8 +462,17 @@
init_atoms();
/* Initialize the interpreter */
caml_interprete(NULL, 0);
+ /* Initialize the debugger, if needed */
+ caml_debugger_init();
/* Load the code */
caml_start_code = code;
+ caml_code_size = code_size;
+ if (caml_debugger_in_use) {
+ int len, i;
+ len = code_size / sizeof(opcode_t);
+ caml_saved_code = (unsigned char *) caml_stat_alloc(len);
+ for (i = 0; i < len; i++) caml_saved_code[i] = caml_start_code[i];
+ }
#ifdef THREADED_CODE
caml_thread_code(caml_start_code, code_size);
#endif
@@ -472,7 +489,16 @@
/* Run the code */
caml_init_exceptions();
caml_sys_init("", argv);
+ /* Execute the program */
+ caml_debugger(PROGRAM_START);
res = caml_interprete(caml_start_code, code_size);
- if (Is_exception_result(res))
- caml_fatal_uncaught_exception(Extract_exception(res));
+ if (Is_exception_result(res)) {
+ caml_exn_bucket = Extract_exception(res);
+ if (caml_debugger_in_use) {
+ caml_extern_sp = &caml_exn_bucket; /* The debugger needs the
+ exception value.*/
+ caml_debugger(UNCAUGHT_EXC);
+ }
+ caml_fatal_uncaught_exception(caml_exn_bucket);
+ }
}
Index: byterun/startup.h
===================================================================
--- byterun/startup.h (revision 178)
+++ byterun/startup.h (revision 185)
@@ -25,12 +25,13 @@
code_t code, asize_t code_size,
char *data, asize_t data_size,
char *section_table, asize_t section_table_size,
+ char *cds_name,
char **argv);
enum { FILE_NOT_FOUND = -1, BAD_BYTECODE = -2 };
extern int caml_attempt_open(char **name, struct exec_trailer *trail,
- int do_open_script);
+ int do_open_script, int do_search_exe_in_path);
extern void caml_read_section_descriptors(int fd, struct exec_trailer *trail);
extern int32 caml_seek_optional_section(int fd, struct exec_trailer *trail,
char *name);
Index: byterun/sys.c
===================================================================
--- byterun/sys.c (revision 178)
+++ byterun/sys.c (revision 185)
@@ -212,6 +212,7 @@
}
char * caml_exe_name;
+char * caml_cds_name;
static char ** caml_main_argv;
CAMLprim value caml_sys_get_argv(value unit)
Index: byterun/backtrace.c
===================================================================
--- byterun/backtrace.c (revision 178)
+++ byterun/backtrace.c (revision 185)
@@ -17,7 +17,9 @@
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include <fcntl.h>
+#include <sys/stat.h>
#include "config.h"
#ifdef HAS_UNISTD
#include <unistd.h>
@@ -34,7 +36,20 @@
#include "stacks.h"
#include "sys.h"
#include "backtrace.h"
+#include "osdeps.h"
+#if !defined (_WIN32) && !macintosh
+#include <sys/param.h>
+#endif
+
+#ifndef PATH_MAX
+#ifdef MAXPATHLEN
+#define PATH_MAX MAXPATHLEN
+#else
+#define PATH_MAX 512
+#endif
+#endif
+
CAMLexport int caml_backtrace_active = 0;
CAMLexport int caml_backtrace_pos = 0;
CAMLexport code_t * caml_backtrace_buffer = NULL;
@@ -116,10 +131,85 @@
}
}
-/* Read the debugging info contained in the current bytecode executable.
- Return a Caml array of Caml lists of debug_event records in "events",
- or Val_false on failure. */
+/* Search for the debugging info in a bytecode file */
+static int open_debug_info(char * file_name, int * pfd, int do_search_in_path)
+{
+ char * name;
+ struct exec_trailer trail;
+
+ name = file_name;
+ *pfd = caml_attempt_open(&name, &trail, 1, do_search_in_path);
+ caml_stat_free(name);
+ if (*pfd < 0) return -1;
+ caml_read_section_descriptors(*pfd, &trail);
+ if (caml_seek_optional_section(*pfd, &trail, "DBUG") == -1) {
+ close(*pfd);
+ return -1;
+ }
+ else return 0;
+}
+
+/* Search for the debugging info in the separate .cds file */
+
+static int open_debug_info_cds(char * cds_name, int * pfd)
+{
+ char full_name[PATH_MAX];
+ char base_name[PATH_MAX];
+ char * p;
+ struct ext_table path;
+ char * tofree;
+
+ /* Check if compiled with the debug info */
+ if (*cds_name == '\0') return -1;
+
+ /* Search by the absolute path */
+ if (open_debug_info(cds_name, pfd, 1) == 0) return 0;
+
+ /* Find base name in cds_name */
+ p = cds_name + strlen(cds_name) - 1;
+ for (/*nothing*/; p >= cds_name; --p) {
+ if (*p == '\\' || *p == '/'){
+ ++p;
+ break;
+ }
+ }
+ strncpy(base_name, p, sizeof(full_name));
+
+#if defined(__linux__) || defined(_WIN32)
+ /* Search in the process' directory */
+ if (caml_executable_name(full_name, sizeof(full_name)) == 0){
+ /* Strip file name from the process path */
+ p = full_name + strlen(full_name) - 1;
+ for (/*nothing*/; p >= full_name; --p) {
+ if (*p == '\\' || *p == '/'){
+ *(p + 1) = '\0';
+ break;
+ }
+ }
+ /* Merge with the base name */
+ strncat(full_name, base_name, sizeof(full_name));
+ if (open_debug_info(full_name, pfd, 1) == 0) return 0;
+ }
+#endif
+
+ /* Search by the environment variable */
+ caml_ext_table_init(&path, 8);
+ tofree = caml_decompose_path(&path, getenv("CAML_SYMBOL_PATH"));
+ p = caml_search_in_path(&path, base_name);
+ strncpy(full_name, p, sizeof(full_name));
+ caml_stat_free(p);
+ caml_stat_free(tofree);
+ caml_ext_table_free(&path, 0);
+ if (open_debug_info(full_name, pfd, 1) == 0) return 0;
+
+ return -1;
+}
+
+/* Read the debugging info contained in the separate .cds file or in the
+ current bytecode executable. Return a Caml array of Caml lists of
+ debug_event records in "events", or Val_false on failure. */
+
#ifndef O_BINARY
#define O_BINARY 0
#endif
@@ -128,21 +218,17 @@
{
CAMLparam0();
CAMLlocal1(events);
- char * exec_name;
int fd;
- struct exec_trailer trail;
struct channel * chan;
uint32 num_events, orig, i;
value evl, l;
- exec_name = caml_exe_name;
- fd = caml_attempt_open(&exec_name, &trail, 1);
- if (fd < 0) CAMLreturn(Val_false);
- caml_read_section_descriptors(fd, &trail);
- if (caml_seek_optional_section(fd, &trail, "DBUG") == -1) {
- close(fd);
- CAMLreturn(Val_false);
+ if (caml_cds_name != NULL){
+ if (open_debug_info_cds(caml_cds_name, &fd)) CAMLreturn(Val_false);
}
+ else {
+ if (open_debug_info(caml_exe_name, &fd, 0)) CAMLreturn(Val_false);
+ }
chan = caml_open_descriptor_in(fd);
num_events = caml_getword(chan);
events = caml_alloc(num_events, 0);
Index: byterun/sys.h
===================================================================
--- byterun/sys.h (revision 178)
+++ byterun/sys.h (revision 185)
@@ -26,5 +26,6 @@
CAMLextern value caml_sys_exit (value);
extern char * caml_exe_name;
+extern char * caml_cds_name;
#endif /* CAML_SYS_H */
embedded-caml-debug3.diff [^] (14,834 bytes) 2009-05-05 11:50 [Show Content] [Hide Content]Index: debugger/Makefile.shared
===================================================================
--- debugger/Makefile.shared (revision 178)
+++ debugger/Makefile.shared (revision 202)
@@ -60,11 +60,11 @@
pos.cmo \
checkpoints.cmo \
events.cmo \
+ program_loading.cmo \
symbols.cmo \
breakpoints.cmo \
trap_barrier.cmo \
history.cmo \
- program_loading.cmo \
printval.cmo \
show_source.cmo \
time_travel.cmo \
Index: debugger/symbols.ml
===================================================================
--- debugger/symbols.ml (revision 178)
+++ debugger/symbols.ml (revision 202)
@@ -17,6 +17,7 @@
open Instruct
open Debugger_config (* Toplevel *)
+open Program_loading
let modules =
ref ([] : string list)
@@ -61,6 +62,17 @@
List.iter (relocate_event orig) evl;
eventlists := evl :: !eventlists
done;
+ begin try
+ ignore (Bytesections.seek_section ic "CODE")
+ with Not_found ->
+ (* Debug info file - activate manual loading mode *)
+ let rec find = function
+ [] -> assert false
+ | (mode,lfun)::tl ->
+ if mode = "manual" then set_launching_function lfun else find tl
+ in
+ find loading_modes
+ end;
close_in_noerr ic;
!eventlists
Index: bytecomp/bytelink.ml
===================================================================
--- bytecomp/bytelink.ml (revision 178)
+++ bytecomp/bytelink.ml (revision 202)
@@ -58,7 +58,7 @@
end
(* A note on ccobj ordering:
- - Clflags.ccobjs is in reverse order w.r.t. what was given on the
+ - Clflags.ccobjs is in reverse order w.r.t. what was given on the
ocamlc command line;
- l.lib_ccobjs is also in reverse order w.r.t. what was given on the
ocamlc -a command line when the library was created;
@@ -381,7 +381,14 @@
let link_bytecode_as_c tolink outfile =
let outchan = open_out outfile in
- try
+ let cds_file =
+ if !Clflags.debug then
+ let basename = Filename.chop_extension outfile in
+ (if Filename.is_relative basename
+ then Filename.concat (Sys.getcwd ()) basename
+ else basename) ^ ".cds"
+ else "" in
+ begin try
(* The bytecode *)
output_string outchan "#include <caml/mlvalues.h>\n";
output_string outchan "\
@@ -389,12 +396,16 @@
code_t code, asize_t code_size,
char *data, asize_t data_size,
char *section_table, asize_t section_table_size,
+ char *cds_name,
char **argv);\n";
output_string outchan "static int caml_code[] = {\n";
Symtable.init();
Consistbl.clear crc_interfaces;
- let output_fun = output_code_string outchan
- and currpos_fun () = 0 in
+ let currpos = ref 0 in
+ let output_fun code =
+ output_code_string outchan code;
+ currpos := !currpos + String.length code
+ and currpos_fun () = !currpos in
List.iter (link_file output_fun currpos_fun) tolink;
(* The final STOP instruction *)
Printf.fprintf outchan "\n0x%x};\n\n" Opcodes.opSTOP;
@@ -414,6 +425,10 @@
output_string outchan "\n};\n\n";
(* The table of primitives *)
Symtable.output_primitive_table outchan;
+ (* cds file name *)
+ output_string outchan "\nstatic char caml_cds_file[] = {\n";
+ output_data_string outchan cds_file;
+ output_string outchan "0\n};\n\n";
(* The entry point *)
output_string outchan "\n
void caml_startup(char ** argv)
@@ -421,17 +436,39 @@
caml_startup_code(caml_code, sizeof(caml_code),
caml_data, sizeof(caml_data),
caml_sections, sizeof(caml_sections),
+ caml_cds_file,
argv);
}\n";
close_out outchan
with x ->
close_out outchan;
raise x
+ end;
+ if cds_file <> "" then
+ try
+ remove_file cds_file; (* avoid permission problems *)
+ let outchan =
+ open_out_gen [Open_wronly; Open_trunc; Open_creat; Open_binary]
+ 0o777 cds_file in
+ Bytesections.init_record outchan;
+ (* The map of global identifiers *)
+ Symtable.output_global_map outchan;
+ Bytesections.record outchan "SYMB";
+ (* Debug info *)
+ output_debug_info outchan;
+ Bytesections.record outchan "DBUG";
+ (* The table of contents and the trailer *)
+ Bytesections.write_toc_and_trailer outchan;
+ close_out outchan
+ with x ->
+ close_out outchan;
+ remove_file cds_file;
+ raise x
(* Build a custom runtime *)
let build_custom_runtime prim_name exec_name =
- Ccomp.call_linker Ccomp.Exe exec_name
+ Ccomp.call_linker Ccomp.Exe exec_name
([prim_name] @ List.rev !Clflags.ccobjs @ ["-lcamlrun"])
Config.bytecomp_c_libraries
Index: byterun/win32.c
===================================================================
--- byterun/win32.c (revision 178)
+++ byterun/win32.c (revision 202)
@@ -374,6 +374,16 @@
return 0;
}
+int caml_executable_name(char * name, int name_len)
+{
+ DWORD retcode;
+
+ retcode = GetModuleFileName(NULL, name, name_len);
+ if (retcode == 0 || retcode >= name_len) return -1;
+ name[retcode] = 0;
+ return 0;
+}
+
#ifndef NATIVE_CODE
/* Set up a new thread for control-C emulation and termination */
Index: byterun/osdeps.h
===================================================================
--- byterun/osdeps.h (revision 178)
+++ byterun/osdeps.h (revision 202)
@@ -63,8 +63,10 @@
Return 0 on success, -1 on error; set errno in the case of error. */
extern int caml_read_directory(char * dirname, struct ext_table * contents);
-#ifdef __linux__
-/* Recover executable name from /proc/self/exe if possible */
+#if defined(__linux__) || defined(_WIN32)
+/* Recover executable name if possible
+ from /proc/self/exe (linux) or
+ from GetModuleFileName() (Windows) */
extern int caml_executable_name(char * name, int name_len);
#endif
Index: byterun/startup.c
===================================================================
--- byterun/startup.c (revision 178)
+++ byterun/startup.c (revision 202)
@@ -101,14 +101,20 @@
}
int caml_attempt_open(char **name, struct exec_trailer *trail,
- int do_open_script)
+ int do_open_script, int do_search_exe_in_path)
{
char * truename;
int fd;
int err;
char buf [2];
- truename = caml_search_exe_in_path(*name);
+ if (!do_search_exe_in_path) {
+ truename = caml_search_exe_in_path(*name);
+ }
+ else {
+ truename = caml_stat_alloc(strlen(*name)+1);
+ strcpy(truename, *name);
+ }
*name = truename;
caml_gc_message(0x100, "Opening bytecode executable %s\n",
(uintnat) truename);
@@ -176,7 +182,7 @@
int32 caml_seek_section(int fd, struct exec_trailer *trail, char *name)
{
int32 len = caml_seek_optional_section(fd, trail, name);
- if (len == -1)
+ if (len == -1)
caml_fatal_error_arg("Fatal_error: section `%s' is missing\n", name);
return len;
}
@@ -358,13 +364,13 @@
if (caml_executable_name(proc_self_exe, sizeof(proc_self_exe)) == 0)
exe_name = proc_self_exe;
#endif
- fd = caml_attempt_open(&exe_name, &trail, 0);
+ fd = caml_attempt_open(&exe_name, &trail, 0, 0);
if (fd < 0) {
pos = parse_command_line(argv);
if (argv[pos] == 0)
caml_fatal_error("No bytecode file specified.\n");
exe_name = argv[pos];
- fd = caml_attempt_open(&exe_name, &trail, 1);
+ fd = caml_attempt_open(&exe_name, &trail, 1, 0);
switch(fd) {
case FILE_NOT_FOUND:
caml_fatal_error_arg("Fatal error: cannot find file %s\n", argv[pos]);
@@ -436,6 +442,7 @@
code_t code, asize_t code_size,
char *data, asize_t data_size,
char *section_table, asize_t section_table_size,
+ char *cds_name,
char **argv)
{
value res;
@@ -445,6 +452,7 @@
#ifdef DEBUG
caml_verb_gc = 63;
#endif
+ caml_cds_name = cds_name;
parse_camlrunparam();
caml_external_raise = NULL;
/* Initialize the abstract machine */
@@ -454,8 +462,17 @@
init_atoms();
/* Initialize the interpreter */
caml_interprete(NULL, 0);
+ /* Initialize the debugger, if needed */
+ caml_debugger_init();
/* Load the code */
caml_start_code = code;
+ caml_code_size = code_size;
+ if (caml_debugger_in_use) {
+ int len, i;
+ len = code_size / sizeof(opcode_t);
+ caml_saved_code = (unsigned char *) caml_stat_alloc(len);
+ for (i = 0; i < len; i++) caml_saved_code[i] = caml_start_code[i];
+ }
#ifdef THREADED_CODE
caml_thread_code(caml_start_code, code_size);
#endif
@@ -472,7 +489,16 @@
/* Run the code */
caml_init_exceptions();
caml_sys_init("", argv);
+ /* Execute the program */
+ caml_debugger(PROGRAM_START);
res = caml_interprete(caml_start_code, code_size);
- if (Is_exception_result(res))
- caml_fatal_uncaught_exception(Extract_exception(res));
+ if (Is_exception_result(res)) {
+ caml_exn_bucket = Extract_exception(res);
+ if (caml_debugger_in_use) {
+ caml_extern_sp = &caml_exn_bucket; /* The debugger needs the
+ exception value.*/
+ caml_debugger(UNCAUGHT_EXC);
+ }
+ caml_fatal_uncaught_exception(caml_exn_bucket);
+ }
}
Index: byterun/startup.h
===================================================================
--- byterun/startup.h (revision 178)
+++ byterun/startup.h (revision 202)
@@ -25,12 +25,13 @@
code_t code, asize_t code_size,
char *data, asize_t data_size,
char *section_table, asize_t section_table_size,
+ char *cds_name,
char **argv);
enum { FILE_NOT_FOUND = -1, BAD_BYTECODE = -2 };
extern int caml_attempt_open(char **name, struct exec_trailer *trail,
- int do_open_script);
+ int do_open_script, int do_search_exe_in_path);
extern void caml_read_section_descriptors(int fd, struct exec_trailer *trail);
extern int32 caml_seek_optional_section(int fd, struct exec_trailer *trail,
char *name);
Index: byterun/sys.c
===================================================================
--- byterun/sys.c (revision 178)
+++ byterun/sys.c (revision 202)
@@ -212,6 +212,7 @@
}
char * caml_exe_name;
+char * caml_cds_name;
static char ** caml_main_argv;
CAMLprim value caml_sys_get_argv(value unit)
Index: byterun/backtrace.c
===================================================================
--- byterun/backtrace.c (revision 178)
+++ byterun/backtrace.c (revision 202)
@@ -17,7 +17,9 @@
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include <fcntl.h>
+#include <sys/stat.h>
#include "config.h"
#ifdef HAS_UNISTD
#include <unistd.h>
@@ -34,7 +36,20 @@
#include "stacks.h"
#include "sys.h"
#include "backtrace.h"
+#include "osdeps.h"
+#if !defined (_WIN32) && !macintosh
+#include <sys/param.h>
+#endif
+
+#ifndef PATH_MAX
+#ifdef MAXPATHLEN
+#define PATH_MAX MAXPATHLEN
+#else
+#define PATH_MAX 512
+#endif
+#endif
+
CAMLexport int caml_backtrace_active = 0;
CAMLexport int caml_backtrace_pos = 0;
CAMLexport code_t * caml_backtrace_buffer = NULL;
@@ -116,10 +131,85 @@
}
}
-/* Read the debugging info contained in the current bytecode executable.
- Return a Caml array of Caml lists of debug_event records in "events",
- or Val_false on failure. */
+/* Search for the debugging info in a bytecode file */
+static int open_debug_info(char * file_name, int * pfd, int do_search_in_path)
+{
+ char * name;
+ struct exec_trailer trail;
+
+ name = file_name;
+ *pfd = caml_attempt_open(&name, &trail, 1, do_search_in_path);
+ caml_stat_free(name);
+ if (*pfd < 0) return -1;
+ caml_read_section_descriptors(*pfd, &trail);
+ if (caml_seek_optional_section(*pfd, &trail, "DBUG") == -1) {
+ close(*pfd);
+ return -1;
+ }
+ else return 0;
+}
+
+/* Search for the debugging info in the separate .cds file */
+
+static int open_debug_info_cds(char * cds_name, int * pfd)
+{
+ char full_name[PATH_MAX];
+ char base_name[PATH_MAX];
+ char * p;
+ struct ext_table path;
+ char * tofree;
+
+ /* Check if compiled with the debug info */
+ if (*cds_name == '\0') return -1;
+
+ /* Search by the absolute path */
+ if (open_debug_info(cds_name, pfd, 1) == 0) return 0;
+
+ /* Find base name in cds_name */
+ p = cds_name + strlen(cds_name) - 1;
+ for (/*nothing*/; p >= cds_name; --p) {
+ if (*p == '\\' || *p == '/'){
+ ++p;
+ break;
+ }
+ }
+ strncpy(base_name, p, sizeof(full_name));
+
+#if defined(__linux__) || defined(_WIN32)
+ /* Search in the process' directory */
+ if (caml_executable_name(full_name, sizeof(full_name)) == 0){
+ /* Strip file name from the process path */
+ p = full_name + strlen(full_name) - 1;
+ for (/*nothing*/; p >= full_name; --p) {
+ if (*p == '\\' || *p == '/'){
+ *(p + 1) = '\0';
+ break;
+ }
+ }
+ /* Merge with the base name */
+ strncat(full_name, base_name, sizeof(full_name));
+ if (open_debug_info(full_name, pfd, 1) == 0) return 0;
+ }
+#endif
+
+ /* Search by the environment variable */
+ caml_ext_table_init(&path, 8);
+ tofree = caml_decompose_path(&path, getenv("CAML_SYMBOL_PATH"));
+ p = caml_search_in_path(&path, base_name);
+ strncpy(full_name, p, sizeof(full_name));
+ caml_stat_free(p);
+ caml_stat_free(tofree);
+ caml_ext_table_free(&path, 0);
+ if (open_debug_info(full_name, pfd, 1) == 0) return 0;
+
+ return -1;
+}
+
+/* Read the debugging info contained in the separate .cds file or in the
+ current bytecode executable. Return a Caml array of Caml lists of
+ debug_event records in "events", or Val_false on failure. */
+
#ifndef O_BINARY
#define O_BINARY 0
#endif
@@ -128,21 +218,17 @@
{
CAMLparam0();
CAMLlocal1(events);
- char * exec_name;
int fd;
- struct exec_trailer trail;
struct channel * chan;
uint32 num_events, orig, i;
value evl, l;
- exec_name = caml_exe_name;
- fd = caml_attempt_open(&exec_name, &trail, 1);
- if (fd < 0) CAMLreturn(Val_false);
- caml_read_section_descriptors(fd, &trail);
- if (caml_seek_optional_section(fd, &trail, "DBUG") == -1) {
- close(fd);
- CAMLreturn(Val_false);
+ if (caml_cds_name != NULL){
+ if (open_debug_info_cds(caml_cds_name, &fd)) CAMLreturn(Val_false);
}
+ else {
+ if (open_debug_info(caml_exe_name, &fd, 0)) CAMLreturn(Val_false);
+ }
chan = caml_open_descriptor_in(fd);
num_events = caml_getword(chan);
events = caml_alloc(num_events, 0);
Index: byterun/sys.h
===================================================================
--- byterun/sys.h (revision 178)
+++ byterun/sys.h (revision 202)
@@ -26,5 +26,6 @@
CAMLextern value caml_sys_exit (value);
extern char * caml_exe_name;
+extern char * caml_cds_name;
#endif /* CAML_SYS_H */
|