Date: Sat, 21 Aug 2004 10:35:33 GMT From: David Xu <davidxu@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 60189 for review Message-ID: <200408211035.i7LAZXvA065768@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=60189 Change 60189 by davidxu@davidxu_alona on 2004/08/21 10:34:57 Add code to support .core for threaded program. Affected files ... .. //depot/projects/davidxu_ksedbg/src/gnu/usr.bin/gdb/libgdb/fbsd-threads.c#21 edit Differences ... ==== //depot/projects/davidxu_ksedbg/src/gnu/usr.bin/gdb/libgdb/fbsd-threads.c#21 (text+ko) ==== @@ -27,6 +27,8 @@ #include "thread_db.h" #include "bfd.h" +#include "elf-bfd.h" +#include "gdbcore.h" #include "gdbthread.h" #include "inferior.h" #include "symfile.h" @@ -51,7 +53,12 @@ extern struct target_ops child_ops; /* This module's target vector. */ -static struct target_ops thread_db_ops; +static struct target_ops fbsd_thread_ops; +static struct target_ops fbsd_core_ops; + +/* Saved copy of orignal core_ops */ +static struct target_ops orig_core_ops; +extern struct target_ops core_ops; /* Pointer to the next function on the objfile event chain. */ static void (*target_new_objfile_chain) (struct objfile *objfile); @@ -60,7 +67,9 @@ static int fbsd_thread_present; /* Non-zero if we're using this module's target vector. */ -static int using_thread_db; +static int fbsd_thread_active; + +static int fbsd_thread_core = 0; /* Non-zero if we have to keep this module's target vector active across re-runs. */ @@ -123,7 +132,6 @@ /* Prototypes for local functions. */ static void fbsd_thread_find_new_threads (void); static int fbsd_thread_alive (ptid_t ptid); -static void fbsd_thread_activate(void); /* Building process ids. */ @@ -227,7 +235,7 @@ gdb_assert (IS_LWP (ptid)); - if (using_thread_db) + if (fbsd_thread_active) { err = td_ta_map_lwp2thr_p (thread_agent, GET_LWP (ptid), &th); if (err == TD_OK) @@ -243,11 +251,30 @@ return BUILD_LWP (GET_LWP (ptid), GET_PID (ptid)); } +static void +fbsd_core_get_first_lwp (bfd *abfd, asection *asect, void *obj) +{ + if (strncmp (bfd_section_name (abfd, asect), ".reg/", 5) != 0) + return; + + if (*(lwpid_t *)obj != 0) + return; + + *(lwpid_t *)obj = atoi (bfd_section_name (abfd, asect) + 5); +} + static long get_current_lwp (int pid) { struct ptrace_lwpinfo pl; + lwpid_t lwpid; + if (!target_has_execution) + { + lwpid = 0; + bfd_map_over_sections (core_bfd, fbsd_core_get_first_lwp, &lwpid); + return lwpid; + } if (ptrace (PT_LWPINFO, pid, (caddr_t)&pl, sizeof(pl))) perror_with_name("PT_LWPINFO"); @@ -271,6 +298,27 @@ } static void +fbsd_thread_activate (void) +{ + fbsd_thread_active = 1; + init_thread_list(); + fbsd_thread_find_new_threads (); + get_current_thread (); +} + +static void +fbsd_thread_deactivate (void) +{ + td_ta_delete_p (thread_agent); + + inferior_ptid = pid_to_ptid (proc_handle.pid); + proc_handle.pid = 0; + fbsd_thread_active = 0; + fbsd_thread_present = 0; + init_thread_list (); +} + +static void fbsd_thread_new_objfile (struct objfile *objfile) { td_err_e err; @@ -281,10 +329,10 @@ { /* All symbols have been discarded. If the thread_db target is active, deactivate it now. */ - if (using_thread_db) + if (fbsd_thread_active) { gdb_assert (proc_handle.pid == 0); - using_thread_db = 0; + fbsd_thread_active = 0; } goto quit; @@ -293,7 +341,7 @@ if (!child_suppress_run) goto quit; - if (using_thread_db) + if (fbsd_thread_active) /* Nothing to do. The thread library was already detected and the target vector was already activated. */ goto quit; @@ -318,16 +366,15 @@ /* We can only poke around if there actually is a child process. If there is no child process alive, postpone the steps below until one has been created. */ - if (proc_handle.pid != 0) + if (fbsd_thread_core == 0 && proc_handle.pid != 0) { - push_target(&thread_db_ops); + push_target(&fbsd_thread_ops); fbsd_thread_activate(); } else { td_ta_delete_p(thread_agent); thread_agent = NULL; - printf_filtered("%s postpone processing\n", __func__); } break; @@ -345,23 +392,41 @@ static void fbsd_thread_attach (char *args, int from_tty) { + fbsd_thread_core = 0; + child_ops.to_attach (args, from_tty); - /* Destroy thread info; it's no longer valid. */ - init_thread_list (); + /* Must get symbols from solibs before libthread_db can run! */ + SOLIB_ADD ((char *) 0, from_tty, (struct target_ops *) 0, auto_solib_add); + + if (fbsd_thread_present && !fbsd_thread_active) + push_target(&fbsd_thread_ops); +} - /* The child process is now the actual multi-threaded - program. Snatch its process ID... */ - proc_handle.pid = GET_PID (inferior_ptid); +static void +fbsd_thread_post_attach (int pid) +{ + child_ops.to_post_attach (pid); - /* ...and perform the remaining initialization steps. */ - fbsd_thread_find_new_threads(); - get_current_thread (); + if (fbsd_thread_present && !fbsd_thread_active) + { + proc_handle.pid = GET_PID (inferior_ptid); + fbsd_thread_activate (); + } } static void fbsd_thread_detach (char *args, int from_tty) { + fbsd_thread_deactivate (); + unpush_target (&fbsd_thread_ops); + + /* Clear gdb solib information and symbol file + cache, so that after detach and re-attach, new_objfile + hook will be called */ + + clear_solib(); + symbol_file_clear(0); proc_handle.pid = 0; child_ops.to_detach (args, from_tty); } @@ -401,7 +466,7 @@ GET_THREAD(inferior_ptid)); #endif - if (!using_thread_db) + if (!fbsd_thread_active) { child_ops.to_resume (ptid, step, signo); return; @@ -523,17 +588,32 @@ fbsd_thread_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int write, struct mem_attrib *attrib, struct target_ops *target) { - return child_ops.to_xfer_memory (memaddr, myaddr, len, write, - attrib, target); + int err; + + if (target_has_execution) + err = child_ops.to_xfer_memory (memaddr, myaddr, len, write, attrib, + target); + else + err = orig_core_ops.to_xfer_memory (memaddr, myaddr, len, write, attrib, + target); + + return (err); } static void fbsd_lwp_fetch_registers (int regno) { + struct cleanup *old_chain; gregset_t gregs; fpregset_t fpregs; lwpid_t lwp; + if (!target_has_execution) + { + orig_core_ops.to_fetch_registers (-1); + return; + } + lwp = GET_LWP (inferior_ptid); if (ptrace (PT_GETREGS, lwp, (caddr_t) &gregs, 0) == -1) @@ -679,19 +759,10 @@ } static void -fbsd_thread_activate (void) -{ - using_thread_db = 1; - init_thread_list(); - fbsd_thread_find_new_threads (); - get_current_thread (); -} - -static void fbsd_thread_create_inferior (char *exec_file, char *allargs, char **env) { - if (fbsd_thread_present && !using_thread_db) - push_target(&thread_db_ops); + if (fbsd_thread_present && !fbsd_thread_active) + push_target(&fbsd_thread_ops); child_ops.to_create_inferior (exec_file, allargs, env); } @@ -699,7 +770,7 @@ static void fbsd_thread_post_startup_inferior (ptid_t ptid) { - if (fbsd_thread_present && !using_thread_db) + if (fbsd_thread_present && !fbsd_thread_active) { /* * The child process is now the actual multi-threaded @@ -723,6 +794,23 @@ child_ops.to_mourn_inferior (); } +static void +fbsd_core_check_lwp (bfd *abfd, asection *asect, void *obj) +{ + lwpid_t lwp; + + if (strncmp (bfd_section_name (abfd, asect), ".reg/", 5) != 0) + return; + + /* already found */ + if (*(lwpid_t *)obj == 0) + return; + + lwp = atoi (bfd_section_name (abfd, asect) + 5); + if (*(lwpid_t *)obj == lwp) + *(lwpid_t *)obj = 0; +} + static int fbsd_thread_alive (ptid_t ptid) { @@ -730,6 +818,7 @@ td_thrinfo_t ti; td_err_e err; gregset_t gregs; + lwpid_t lwp; if (IS_THREAD (ptid)) { @@ -753,7 +842,7 @@ return 1; } - if (using_thread_db) + if (fbsd_thread_active) { err = td_ta_map_lwp2thr_p (thread_agent, GET_LWP (ptid), &th); @@ -765,10 +854,23 @@ return 0; } + if (!target_has_execution) + { + lwp = GET_LWP (ptid); + bfd_map_over_sections (core_bfd, fbsd_core_check_lwp, &lwp); + return (lwp == 0); + } + /* check lwp in kernel */ return ptrace (PT_GETREGS, GET_LWP (ptid), (caddr_t)&gregs, 0) == 0; } +static void +fbsd_thread_files_info (struct target_ops *ignore) +{ + child_ops.to_files_info (ignore); +} + static int find_new_threads_callback (const td_thrhandle_t *th_p, void *data) { @@ -784,11 +886,10 @@ if (ti.ti_state == TD_THR_UNKNOWN || ti.ti_state == TD_THR_ZOMBIE) return 0; - ptid = BUILD_THREAD (ti.ti_tid, GET_PID (inferior_ptid)); + ptid = BUILD_THREAD (ti.ti_tid, proc_handle.pid); if (!in_thread_list (ptid)) add_thread (ptid); - return 0; } @@ -797,7 +898,7 @@ { td_err_e err; - if (!using_thread_db) + if (!fbsd_thread_active) return; /* Iterate over all user-space threads to discover new threads. */ @@ -922,42 +1023,136 @@ static void fbsd_thread_tsd_cmd (char *exp, int from_tty) { - if (using_thread_db) + if (fbsd_thread_active) td_ta_tsd_iter_p (thread_agent, tsd_cb, NULL); } +static int +ignore (CORE_ADDR addr, char *contents) +{ + return 0; +} + +static void +fbsd_core_open (char *filename, int from_tty) +{ + int err; + + fbsd_thread_core = 1; + + orig_core_ops.to_open (filename, from_tty); + + if (fbsd_thread_present) + { + err = td_ta_new_p (&proc_handle, &thread_agent); + if (err == TD_OK) + { + proc_handle.pid = elf_tdata (core_bfd)->core_pid; + fbsd_thread_activate (); + } + else + error ("fbsd_core_open: td_open: %s", thread_db_err_str (err)); + } +} + +static void +fbsd_core_close (int quitting) +{ + orig_core_ops.to_close (quitting); +} + +static void +fbsd_core_detach (char *args, int from_tty) +{ + if (fbsd_thread_active) + fbsd_thread_deactivate (); + unpush_target (&fbsd_thread_ops); + orig_core_ops.to_detach (args, from_tty); + + /* Clear gdb solib information and symbol file + cache, so that after detach and re-attach, new_objfile + hook will be called */ + clear_solib(); + symbol_file_clear(0); +} + +static void +fbsd_core_files_info (struct target_ops *ignore) +{ + orig_core_ops.to_files_info (ignore); +} + +static void +init_fbsd_core_ops (void) +{ + fbsd_core_ops.to_shortname = "FreeBSD-core"; + fbsd_core_ops.to_longname = "FreeBSD core thread."; + fbsd_core_ops.to_doc = "FreeBSD thread support for core files."; + fbsd_core_ops.to_open = fbsd_core_open; + fbsd_core_ops.to_close = fbsd_core_close; + fbsd_core_ops.to_attach = 0; + fbsd_core_ops.to_post_attach = 0; + fbsd_core_ops.to_detach = fbsd_core_detach; + /* fbsd_core_ops.to_resume = 0; */ + /* fbsd_core_ops.to_wait = 0; */ + fbsd_core_ops.to_fetch_registers = fbsd_thread_fetch_registers; + /* fbsd_core_ops.to_store_registers = 0; */ + /* fbsd_core_ops.to_prepare_to_store = 0; */ + fbsd_core_ops.to_xfer_memory = fbsd_thread_xfer_memory; + fbsd_core_ops.to_files_info = fbsd_core_files_info; + fbsd_core_ops.to_insert_breakpoint = ignore; + fbsd_core_ops.to_remove_breakpoint = ignore; + /* fbsd_core_ops.to_lookup_symbol = 0; */ + fbsd_core_ops.to_create_inferior = fbsd_thread_create_inferior; + fbsd_core_ops.to_stratum = core_stratum; + fbsd_core_ops.to_has_all_memory = 0; + fbsd_core_ops.to_has_memory = 1; + fbsd_core_ops.to_has_stack = 1; + fbsd_core_ops.to_has_registers = 1; + fbsd_core_ops.to_has_execution = 0; + fbsd_core_ops.to_has_thread_control = tc_none; + fbsd_core_ops.to_thread_alive = fbsd_thread_alive; + fbsd_core_ops.to_pid_to_str = fbsd_thread_pid_to_str; + fbsd_core_ops.to_find_new_threads = fbsd_thread_find_new_threads; + fbsd_core_ops.to_sections = 0; + fbsd_core_ops.to_sections_end = 0; + fbsd_core_ops.to_magic = OPS_MAGIC; +} + static void -init_thread_db_ops (void) +init_fbsd_thread_ops (void) { - thread_db_ops.to_shortname = "multi-thread"; - thread_db_ops.to_longname = "multi-threaded child process."; - thread_db_ops.to_doc = "Threads and pthreads support."; - thread_db_ops.to_attach = fbsd_thread_attach; - thread_db_ops.to_detach = fbsd_thread_detach; - thread_db_ops.to_resume = fbsd_thread_resume; - thread_db_ops.to_wait = fbsd_thread_wait; - thread_db_ops.to_fetch_registers = fbsd_thread_fetch_registers; - thread_db_ops.to_store_registers = fbsd_thread_store_registers; - thread_db_ops.to_xfer_memory = fbsd_thread_xfer_memory; - thread_db_ops.to_kill = fbsd_thread_kill; - thread_db_ops.to_create_inferior = fbsd_thread_create_inferior; - thread_db_ops.to_post_startup_inferior = fbsd_thread_post_startup_inferior; - thread_db_ops.to_mourn_inferior = fbsd_thread_mourn_inferior; - thread_db_ops.to_can_run = fbsd_thread_can_run; - thread_db_ops.to_thread_alive = fbsd_thread_alive; - thread_db_ops.to_find_new_threads = fbsd_thread_find_new_threads; - thread_db_ops.to_pid_to_str = fbsd_thread_pid_to_str; - thread_db_ops.to_stratum = thread_stratum; - thread_db_ops.to_has_thread_control = tc_none; - thread_db_ops.to_has_all_memory = 1; - thread_db_ops.to_has_memory = 1; - thread_db_ops.to_has_stack = 1; - thread_db_ops.to_has_registers = 1; - thread_db_ops.to_has_execution = 1; - thread_db_ops.to_insert_breakpoint = memory_insert_breakpoint; - thread_db_ops.to_remove_breakpoint = memory_remove_breakpoint; - thread_db_ops.to_get_thread_local_address = fbsd_thread_get_local_address; - thread_db_ops.to_magic = OPS_MAGIC; + fbsd_thread_ops.to_shortname = "freebsd-threads"; + fbsd_thread_ops.to_longname = "FreeBSD multithreaded child process."; + fbsd_thread_ops.to_doc = "FreeBSD threads support."; + fbsd_thread_ops.to_attach = fbsd_thread_attach; + fbsd_thread_ops.to_detach = fbsd_thread_detach; + fbsd_thread_ops.to_post_attach = fbsd_thread_post_attach; + fbsd_thread_ops.to_resume = fbsd_thread_resume; + fbsd_thread_ops.to_wait = fbsd_thread_wait; + fbsd_thread_ops.to_fetch_registers = fbsd_thread_fetch_registers; + fbsd_thread_ops.to_store_registers = fbsd_thread_store_registers; + fbsd_thread_ops.to_xfer_memory = fbsd_thread_xfer_memory; + fbsd_thread_ops.to_files_info = fbsd_thread_files_info; + fbsd_thread_ops.to_kill = fbsd_thread_kill; + fbsd_thread_ops.to_create_inferior = fbsd_thread_create_inferior; + fbsd_thread_ops.to_post_startup_inferior = fbsd_thread_post_startup_inferior; + fbsd_thread_ops.to_mourn_inferior = fbsd_thread_mourn_inferior; + fbsd_thread_ops.to_can_run = fbsd_thread_can_run; + fbsd_thread_ops.to_thread_alive = fbsd_thread_alive; + fbsd_thread_ops.to_find_new_threads = fbsd_thread_find_new_threads; + fbsd_thread_ops.to_pid_to_str = fbsd_thread_pid_to_str; + fbsd_thread_ops.to_stratum = thread_stratum; + fbsd_thread_ops.to_has_thread_control = tc_none; + fbsd_thread_ops.to_has_all_memory = 1; + fbsd_thread_ops.to_has_memory = 1; + fbsd_thread_ops.to_has_stack = 1; + fbsd_thread_ops.to_has_registers = 1; + fbsd_thread_ops.to_has_execution = 1; + fbsd_thread_ops.to_insert_breakpoint = memory_insert_breakpoint; + fbsd_thread_ops.to_remove_breakpoint = memory_remove_breakpoint; + fbsd_thread_ops.to_get_thread_local_address = fbsd_thread_get_local_address; + fbsd_thread_ops.to_magic = OPS_MAGIC; } static int @@ -1047,14 +1242,22 @@ return 1; } +/* we suppress the call to add_target of core_ops in corelow because + if there are two targets in the stratum core_stratum, find_core_target + won't know which one to return. see corelow.c for an additonal + comment on coreops_suppress_target. */ + +int coreops_suppress_target = 1; + void _initialize_thread_db (void) { - /* Only initialize the module if we can load libthread_db. */ + init_fbsd_thread_ops (); + init_fbsd_core_ops (); + if (thread_db_load ()) { - init_thread_db_ops (); - add_target (&thread_db_ops); + add_target (&fbsd_thread_ops); /* "thread tsd" command */ add_cmd ("tsd", class_run, fbsd_thread_tsd_cmd, @@ -1062,15 +1265,24 @@ "for the process.\n", &thread_cmd_list); + memcpy (&orig_core_ops, &core_ops, sizeof (struct target_ops)); + memcpy (&core_ops, &fbsd_core_ops, sizeof (struct target_ops)); + add_target (&core_ops); + /* Add ourselves to objfile event chain. */ target_new_objfile_chain = target_new_objfile_hook; target_new_objfile_hook = fbsd_thread_new_objfile; + + child_suppress_run = 1; } else { - printf_filtered("%s: can not load %s.\n", __func__, LIBTHREAD_DB_SO); + fprintf_unfiltered (gdb_stderr, + "[GDB will not be able to debug user-mode threads: %s]\n", dlerror()); + + /* allow the user to debug non-threaded core files */ + add_target (&core_ops); } - child_suppress_run = 1; } /* proc service functions */
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200408211035.i7LAZXvA065768>