1132624Smarcel/* 2132624Smarcel * Copyright (c) 2004 Marcel Moolenaar 3132624Smarcel * All rights reserved. 4132624Smarcel * 5132624Smarcel * Redistribution and use in source and binary forms, with or without 6132624Smarcel * modification, are permitted provided that the following conditions 7132624Smarcel * are met: 8132624Smarcel * 9132624Smarcel * 1. Redistributions of source code must retain the above copyright 10132624Smarcel * notice, this list of conditions and the following disclaimer. 11132624Smarcel * 2. Redistributions in binary form must reproduce the above copyright 12132624Smarcel * notice, this list of conditions and the following disclaimer in the 13132624Smarcel * documentation and/or other materials provided with the distribution. 14132624Smarcel * 15132624Smarcel * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16132624Smarcel * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17132624Smarcel * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18132624Smarcel * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19132624Smarcel * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20132624Smarcel * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21132624Smarcel * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22132624Smarcel * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23132624Smarcel * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24132624Smarcel * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25132624Smarcel */ 26132624Smarcel 27132624Smarcel#include <sys/cdefs.h> 28132624Smarcel__FBSDID("$FreeBSD$"); 29132624Smarcel 30142151Skan#include <sys/param.h> 31142151Skan#include <sys/proc.h> 32142151Skan#include <sys/sysctl.h> 33142151Skan#include <sys/user.h> 34175808Sjhb#include <err.h> 35178670Sjhb#include <fcntl.h> 36132624Smarcel#include <kvm.h> 37132624Smarcel 38132624Smarcel#include <defs.h> 39178670Sjhb#include <readline/readline.h> 40178670Sjhb#include <readline/tilde.h> 41142151Skan#include <command.h> 42175808Sjhb#include <exec.h> 43149954Smarcel#include <frame-unwind.h> 44178713Sjhb#include <gdb.h> 45178670Sjhb#include <gdbcore.h> 46132624Smarcel#include <gdbthread.h> 47132624Smarcel#include <inferior.h> 48178670Sjhb#include <language.h> 49142151Skan#include <regcache.h> 50178670Sjhb#include <solib.h> 51132624Smarcel#include <target.h> 52178713Sjhb#include <ui-out.h> 53132624Smarcel 54142151Skan#include "kgdb.h" 55142151Skan 56246893Smarcelstatic CORE_ADDR stoppcbs; 57246893Smarcel 58178670Sjhbstatic void kgdb_core_cleanup(void *); 59178670Sjhb 60178670Sjhbstatic char *vmcore; 61132624Smarcelstatic struct target_ops kgdb_trgt_ops; 62132624Smarcel 63178670Sjhbkvm_t *kvm; 64178670Sjhbstatic char kvm_err[_POSIX2_LINE_MAX]; 65175808Sjhb 66163439Sjhb#define KERNOFF (kgdb_kernbase ()) 67286305Skib#define PINKERNEL(x) ((x) >= KERNOFF) 68163439Sjhb 69163439Sjhbstatic CORE_ADDR 70163439Sjhbkgdb_kernbase (void) 71163439Sjhb{ 72163439Sjhb static CORE_ADDR kernbase; 73163439Sjhb struct minimal_symbol *sym; 74163439Sjhb 75163439Sjhb if (kernbase == 0) { 76163439Sjhb sym = lookup_minimal_symbol ("kernbase", NULL, NULL); 77163439Sjhb if (sym == NULL) { 78163439Sjhb kernbase = KERNBASE; 79163439Sjhb } else { 80163439Sjhb kernbase = SYMBOL_VALUE_ADDRESS (sym); 81163439Sjhb } 82163439Sjhb } 83163439Sjhb return kernbase; 84163439Sjhb} 85163439Sjhb 86178670Sjhbstatic void 87178670Sjhbkgdb_trgt_open(char *filename, int from_tty) 88178670Sjhb{ 89178670Sjhb struct cleanup *old_chain; 90178670Sjhb struct thread_info *ti; 91178670Sjhb struct kthr *kt; 92178670Sjhb kvm_t *nkvm; 93178670Sjhb char *temp; 94178670Sjhb int ontop; 95178670Sjhb 96178670Sjhb target_preopen (from_tty); 97178670Sjhb if (!filename) 98178670Sjhb error ("No vmcore file specified."); 99178670Sjhb if (!exec_bfd) 100178670Sjhb error ("Can't open a vmcore without a kernel"); 101178670Sjhb 102178670Sjhb filename = tilde_expand (filename); 103178670Sjhb if (filename[0] != '/') { 104178670Sjhb temp = concat (current_directory, "/", filename, NULL); 105178670Sjhb xfree(filename); 106178670Sjhb filename = temp; 107178670Sjhb } 108178670Sjhb 109178670Sjhb old_chain = make_cleanup (xfree, filename); 110178670Sjhb 111178670Sjhb nkvm = kvm_openfiles(bfd_get_filename(exec_bfd), filename, NULL, 112178670Sjhb write_files ? O_RDWR : O_RDONLY, kvm_err); 113178670Sjhb if (nkvm == NULL) 114178670Sjhb error ("Failed to open vmcore: %s", kvm_err); 115178670Sjhb 116178670Sjhb /* Don't free the filename now and close any previous vmcore. */ 117178670Sjhb discard_cleanups(old_chain); 118178670Sjhb unpush_target(&kgdb_trgt_ops); 119178670Sjhb 120178670Sjhb kvm = nkvm; 121178670Sjhb vmcore = filename; 122178670Sjhb old_chain = make_cleanup(kgdb_core_cleanup, NULL); 123178670Sjhb 124178670Sjhb ontop = !push_target (&kgdb_trgt_ops); 125178670Sjhb discard_cleanups (old_chain); 126178670Sjhb 127178670Sjhb kgdb_dmesg(); 128178670Sjhb 129178670Sjhb init_thread_list(); 130178670Sjhb kt = kgdb_thr_init(); 131178670Sjhb while (kt != NULL) { 132178713Sjhb ti = add_thread(pid_to_ptid(kt->tid)); 133178670Sjhb kt = kgdb_thr_next(kt); 134178670Sjhb } 135178670Sjhb if (curkthr != 0) 136178713Sjhb inferior_ptid = pid_to_ptid(curkthr->tid); 137178670Sjhb 138178670Sjhb if (ontop) { 139178670Sjhb /* XXX: fetch registers? */ 140178670Sjhb kld_init(); 141178670Sjhb flush_cached_frames(); 142178670Sjhb select_frame (get_current_frame()); 143178670Sjhb print_stack_frame(get_selected_frame(), 144178670Sjhb frame_relative_level(get_selected_frame()), 1); 145178670Sjhb } else 146178670Sjhb warning( 147178670Sjhb "you won't be able to access this vmcore until you terminate\n\ 148178670Sjhbyour %s; do ``info files''", target_longname); 149178670Sjhb} 150178670Sjhb 151178670Sjhbstatic void 152178670Sjhbkgdb_trgt_close(int quitting) 153178670Sjhb{ 154178670Sjhb 155178670Sjhb if (kvm != NULL) { 156178670Sjhb inferior_ptid = null_ptid; 157178670Sjhb CLEAR_SOLIB(); 158178670Sjhb if (kvm_close(kvm) != 0) 159178670Sjhb warning("cannot close \"%s\": %s", vmcore, 160178670Sjhb kvm_geterr(kvm)); 161178670Sjhb kvm = NULL; 162178670Sjhb xfree(vmcore); 163178670Sjhb vmcore = NULL; 164178670Sjhb if (kgdb_trgt_ops.to_sections) { 165178670Sjhb xfree(kgdb_trgt_ops.to_sections); 166178670Sjhb kgdb_trgt_ops.to_sections = NULL; 167178670Sjhb kgdb_trgt_ops.to_sections_end = NULL; 168178670Sjhb } 169178670Sjhb } 170178670Sjhb} 171178670Sjhb 172178670Sjhbstatic void 173178670Sjhbkgdb_core_cleanup(void *arg) 174178670Sjhb{ 175178670Sjhb 176178670Sjhb kgdb_trgt_close(0); 177178670Sjhb} 178178670Sjhb 179178670Sjhbstatic void 180178670Sjhbkgdb_trgt_detach(char *args, int from_tty) 181178670Sjhb{ 182178670Sjhb 183178670Sjhb if (args) 184178670Sjhb error ("Too many arguments"); 185178670Sjhb unpush_target(&kgdb_trgt_ops); 186178670Sjhb reinit_frame_cache(); 187178670Sjhb if (from_tty) 188178670Sjhb printf_filtered("No vmcore file now.\n"); 189178670Sjhb} 190178670Sjhb 191148802Smarcelstatic char * 192148802Smarcelkgdb_trgt_extra_thread_info(struct thread_info *ti) 193148802Smarcel{ 194142151Skan 195178713Sjhb return (kgdb_thr_extra_thread_info(ptid_get_pid(ti->ptid))); 196142151Skan} 197142151Skan 198148802Smarcelstatic void 199148802Smarcelkgdb_trgt_files_info(struct target_ops *target) 200132624Smarcel{ 201148802Smarcel 202178670Sjhb printf_filtered ("\t`%s', ", vmcore); 203178670Sjhb wrap_here (" "); 204178670Sjhb printf_filtered ("file type %s.\n", "FreeBSD kernel vmcore"); 205132624Smarcel} 206132624Smarcel 207132624Smarcelstatic void 208132624Smarcelkgdb_trgt_find_new_threads(void) 209132624Smarcel{ 210148802Smarcel struct target_ops *tb; 211148802Smarcel 212148802Smarcel if (kvm != NULL) 213148802Smarcel return; 214148802Smarcel 215148802Smarcel tb = find_target_beneath(&kgdb_trgt_ops); 216148802Smarcel if (tb->to_find_new_threads != NULL) 217148802Smarcel tb->to_find_new_threads(); 218132624Smarcel} 219132624Smarcel 220132624Smarcelstatic char * 221132624Smarcelkgdb_trgt_pid_to_str(ptid_t ptid) 222132624Smarcel{ 223142151Skan static char buf[33]; 224132624Smarcel 225178713Sjhb snprintf(buf, sizeof(buf), "Thread %d", ptid_get_pid(ptid)); 226132624Smarcel return (buf); 227132624Smarcel} 228132624Smarcel 229132624Smarcelstatic int 230132624Smarcelkgdb_trgt_thread_alive(ptid_t ptid) 231132624Smarcel{ 232178713Sjhb return (kgdb_thr_lookup_tid(ptid_get_pid(ptid)) != NULL); 233132624Smarcel} 234132624Smarcel 235132624Smarcelstatic int 236132624Smarcelkgdb_trgt_xfer_memory(CORE_ADDR memaddr, char *myaddr, int len, int write, 237148802Smarcel struct mem_attrib *attrib, struct target_ops *target) 238132624Smarcel{ 239148802Smarcel struct target_ops *tb; 240132624Smarcel 241148802Smarcel if (kvm != NULL) { 242148802Smarcel if (len == 0) 243148802Smarcel return (0); 244148802Smarcel if (!write) 245148802Smarcel return (kvm_read(kvm, memaddr, myaddr, len)); 246148802Smarcel else 247148802Smarcel return (kvm_write(kvm, memaddr, myaddr, len)); 248142151Skan } 249148802Smarcel tb = find_target_beneath(target); 250148802Smarcel return (tb->to_xfer_memory(memaddr, myaddr, len, write, attrib, tb)); 251142151Skan} 252142151Skan 253178670Sjhbstatic int 254178670Sjhbkgdb_trgt_ignore_breakpoints(CORE_ADDR addr, char *contents) 255178670Sjhb{ 256178670Sjhb 257178670Sjhb return 0; 258178670Sjhb} 259178670Sjhb 260163439Sjhbstatic void 261178713Sjhbkgdb_switch_to_thread(int tid) 262163439Sjhb{ 263178713Sjhb char buf[16]; 264178713Sjhb int thread_id; 265163439Sjhb 266178713Sjhb thread_id = pid_to_thread_id(pid_to_ptid(tid)); 267178713Sjhb if (thread_id == 0) 268178713Sjhb error ("invalid tid"); 269178713Sjhb snprintf(buf, sizeof(buf), "%d", thread_id); 270178713Sjhb gdb_thread_select(uiout, buf); 271163439Sjhb} 272163439Sjhb 273163439Sjhbstatic void 274163439Sjhbkgdb_set_proc_cmd (char *arg, int from_tty) 275163439Sjhb{ 276163439Sjhb CORE_ADDR addr; 277163439Sjhb struct kthr *thr; 278163439Sjhb 279163439Sjhb if (!arg) 280163439Sjhb error_no_arg ("proc address for the new context"); 281163439Sjhb 282163439Sjhb if (kvm == NULL) 283178713Sjhb error ("only supported for core file target"); 284163439Sjhb 285163439Sjhb addr = (CORE_ADDR) parse_and_eval_address (arg); 286163439Sjhb 287286305Skib if (!PINKERNEL (addr)) { 288163439Sjhb thr = kgdb_thr_lookup_pid((int)addr); 289163439Sjhb if (thr == NULL) 290163439Sjhb error ("invalid pid"); 291163439Sjhb } else { 292163439Sjhb thr = kgdb_thr_lookup_paddr(addr); 293163439Sjhb if (thr == NULL) 294163439Sjhb error("invalid proc address"); 295163439Sjhb } 296178713Sjhb kgdb_switch_to_thread(thr->tid); 297163439Sjhb} 298163439Sjhb 299163439Sjhbstatic void 300163439Sjhbkgdb_set_tid_cmd (char *arg, int from_tty) 301163439Sjhb{ 302163439Sjhb CORE_ADDR addr; 303163439Sjhb struct kthr *thr; 304163439Sjhb 305163439Sjhb if (!arg) 306163439Sjhb error_no_arg ("TID or thread address for the new context"); 307163439Sjhb 308163439Sjhb addr = (CORE_ADDR) parse_and_eval_address (arg); 309163439Sjhb 310286305Skib if (kvm != NULL && PINKERNEL (addr)) { 311163439Sjhb thr = kgdb_thr_lookup_taddr(addr); 312163439Sjhb if (thr == NULL) 313163439Sjhb error("invalid thread address"); 314178713Sjhb addr = thr->tid; 315163439Sjhb } 316178713Sjhb kgdb_switch_to_thread(addr); 317163439Sjhb} 318163439Sjhb 319178670Sjhbint fbsdcoreops_suppress_target = 1; 320178670Sjhb 321132624Smarcelvoid 322178670Sjhbinitialize_kgdb_target(void) 323132624Smarcel{ 324132624Smarcel 325132624Smarcel kgdb_trgt_ops.to_magic = OPS_MAGIC; 326132624Smarcel kgdb_trgt_ops.to_shortname = "kernel"; 327178670Sjhb kgdb_trgt_ops.to_longname = "kernel core dump file"; 328178670Sjhb kgdb_trgt_ops.to_doc = 329178670Sjhb "Use a vmcore file as a target. Specify the filename of the vmcore file."; 330178670Sjhb kgdb_trgt_ops.to_stratum = core_stratum; 331132624Smarcel kgdb_trgt_ops.to_has_memory = 1; 332132624Smarcel kgdb_trgt_ops.to_has_registers = 1; 333132624Smarcel kgdb_trgt_ops.to_has_stack = 1; 334132624Smarcel 335178670Sjhb kgdb_trgt_ops.to_open = kgdb_trgt_open; 336178670Sjhb kgdb_trgt_ops.to_close = kgdb_trgt_close; 337178670Sjhb kgdb_trgt_ops.to_attach = find_default_attach; 338178670Sjhb kgdb_trgt_ops.to_detach = kgdb_trgt_detach; 339132624Smarcel kgdb_trgt_ops.to_extra_thread_info = kgdb_trgt_extra_thread_info; 340132624Smarcel kgdb_trgt_ops.to_fetch_registers = kgdb_trgt_fetch_registers; 341148802Smarcel kgdb_trgt_ops.to_files_info = kgdb_trgt_files_info; 342132624Smarcel kgdb_trgt_ops.to_find_new_threads = kgdb_trgt_find_new_threads; 343132624Smarcel kgdb_trgt_ops.to_pid_to_str = kgdb_trgt_pid_to_str; 344132624Smarcel kgdb_trgt_ops.to_store_registers = kgdb_trgt_store_registers; 345132624Smarcel kgdb_trgt_ops.to_thread_alive = kgdb_trgt_thread_alive; 346132624Smarcel kgdb_trgt_ops.to_xfer_memory = kgdb_trgt_xfer_memory; 347178670Sjhb kgdb_trgt_ops.to_insert_breakpoint = kgdb_trgt_ignore_breakpoints; 348178670Sjhb kgdb_trgt_ops.to_remove_breakpoint = kgdb_trgt_ignore_breakpoints; 349175808Sjhb 350132624Smarcel add_target(&kgdb_trgt_ops); 351132624Smarcel 352163439Sjhb add_com ("proc", class_obscure, kgdb_set_proc_cmd, 353163439Sjhb "Set current process context"); 354163439Sjhb add_com ("tid", class_obscure, kgdb_set_tid_cmd, 355163439Sjhb "Set current thread context"); 356132624Smarcel} 357246893Smarcel 358246893SmarcelCORE_ADDR 359246893Smarcelkgdb_trgt_stop_pcb(u_int cpuid, u_int pcbsz) 360246893Smarcel{ 361246893Smarcel static int once = 0; 362246893Smarcel 363246893Smarcel if (stoppcbs == 0 && !once) { 364246893Smarcel once = 1; 365246893Smarcel stoppcbs = kgdb_lookup("stoppcbs"); 366246893Smarcel } 367246893Smarcel if (stoppcbs == 0) 368246893Smarcel return 0; 369246893Smarcel 370246893Smarcel return (stoppcbs + pcbsz * cpuid); 371246893Smarcel} 372