trgt.c revision 175416
1/* 2 * Copyright (c) 2004 Marcel Moolenaar 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27#include <sys/cdefs.h> 28__FBSDID("$FreeBSD: head/gnu/usr.bin/gdb/kgdb/trgt.c 175416 2008-01-17 21:43:12Z jhb $"); 29 30#include <sys/param.h> 31#include <sys/proc.h> 32#include <sys/stat.h> 33#include <sys/sysctl.h> 34#include <sys/user.h> 35#include <libgen.h> 36#include <kvm.h> 37#include <string.h> 38 39#include <defs.h> 40#include <command.h> 41#include <frame-unwind.h> 42#include <gdbthread.h> 43#include <inferior.h> 44#include <regcache.h> 45#include <target.h> 46#include <objfiles.h> 47#include <gdbcore.h> 48#include <language.h> 49 50#include "kgdb.h" 51 52static struct target_ops kgdb_trgt_ops; 53 54#define KERNOFF (kgdb_kernbase ()) 55#define INKERNEL(x) ((x) >= KERNOFF) 56 57static CORE_ADDR 58kgdb_kernbase (void) 59{ 60 static CORE_ADDR kernbase; 61 struct minimal_symbol *sym; 62 63 if (kernbase == 0) { 64 sym = lookup_minimal_symbol ("kernbase", NULL, NULL); 65 if (sym == NULL) { 66 kernbase = KERNBASE; 67 } else { 68 kernbase = SYMBOL_VALUE_ADDRESS (sym); 69 } 70 } 71 return kernbase; 72} 73 74static char * 75kgdb_trgt_extra_thread_info(struct thread_info *ti) 76{ 77 static char buf[64]; 78 char *p, *s; 79 80 p = buf + snprintf(buf, sizeof(buf), "PID=%d", ptid_get_pid(ti->ptid)); 81 s = kgdb_thr_extra_thread_info(ptid_get_tid(ti->ptid)); 82 if (s != NULL) 83 snprintf(p, sizeof(buf) - (p - buf), ": %s", s); 84 return (buf); 85} 86 87static void 88kgdb_trgt_files_info(struct target_ops *target) 89{ 90 struct target_ops *tb; 91 92 tb = find_target_beneath(target); 93 if (tb->to_files_info != NULL) 94 tb->to_files_info(tb); 95} 96 97static void 98kgdb_trgt_find_new_threads(void) 99{ 100 struct target_ops *tb; 101 102 if (kvm != NULL) 103 return; 104 105 tb = find_target_beneath(&kgdb_trgt_ops); 106 if (tb->to_find_new_threads != NULL) 107 tb->to_find_new_threads(); 108} 109 110static char * 111kgdb_trgt_pid_to_str(ptid_t ptid) 112{ 113 static char buf[33]; 114 115 snprintf(buf, sizeof(buf), "Thread %ld", ptid_get_tid(ptid)); 116 return (buf); 117} 118 119static int 120kgdb_trgt_thread_alive(ptid_t ptid) 121{ 122 return (kgdb_thr_lookup_tid(ptid_get_tid(ptid)) != NULL); 123} 124 125static int 126kgdb_trgt_xfer_memory(CORE_ADDR memaddr, char *myaddr, int len, int write, 127 struct mem_attrib *attrib, struct target_ops *target) 128{ 129 struct target_ops *tb; 130 131 if (kvm != NULL) { 132 if (len == 0) 133 return (0); 134 if (!write) 135 return (kvm_read(kvm, memaddr, myaddr, len)); 136 else 137 return (kvm_write(kvm, memaddr, myaddr, len)); 138 } 139 tb = find_target_beneath(target); 140 return (tb->to_xfer_memory(memaddr, myaddr, len, write, attrib, tb)); 141} 142 143static void 144kgdb_switch_to_thread(struct kthr *thr) 145{ 146 if (thr->tid == ptid_get_tid(inferior_ptid)) 147 return; 148 149 inferior_ptid = ptid_build(thr->pid, 0, thr->tid); 150 flush_cached_frames (); 151 registers_changed (); 152 stop_pc = read_pc (); 153 select_frame (get_current_frame ()); 154} 155 156static void 157kgdb_set_proc_cmd (char *arg, int from_tty) 158{ 159 CORE_ADDR addr; 160 struct kthr *thr; 161 162 if (!arg) 163 error_no_arg ("proc address for the new context"); 164 165 if (kvm == NULL) 166 error ("no kernel core file"); 167 168 addr = (CORE_ADDR) parse_and_eval_address (arg); 169 170 if (!INKERNEL (addr)) { 171 thr = kgdb_thr_lookup_pid((int)addr); 172 if (thr == NULL) 173 error ("invalid pid"); 174 } else { 175 thr = kgdb_thr_lookup_paddr(addr); 176 if (thr == NULL) 177 error("invalid proc address"); 178 } 179 kgdb_switch_to_thread(thr); 180} 181 182static void 183kgdb_set_tid_cmd (char *arg, int from_tty) 184{ 185 CORE_ADDR addr; 186 struct kthr *thr; 187 188 if (!arg) 189 error_no_arg ("TID or thread address for the new context"); 190 191 if (kvm == NULL) 192 error ("no kernel core file"); 193 194 addr = (CORE_ADDR) parse_and_eval_address (arg); 195 196 if (!INKERNEL (addr)) { 197 thr = kgdb_thr_lookup_tid((int)addr); 198 if (thr == NULL) 199 error ("invalid TID"); 200 } else { 201 thr = kgdb_thr_lookup_taddr(addr); 202 if (thr == NULL) 203 error("invalid thread address"); 204 } 205 kgdb_switch_to_thread(thr); 206} 207 208static int 209kld_ok (char *path) 210{ 211 struct stat sb; 212 213 if (stat(path, &sb) == 0 && S_ISREG(sb.st_mode)) 214 return (1); 215 return (0); 216} 217 218/* 219 * Look for a matching file in the following order: 220 * - filename + ".symbols" (e.g. foo.ko.symbols) 221 * - filename + ".debug" (e.g. foo.ko.debug) 222 * - filename (e.g. foo.ko) 223 * - dirname(kernel) + filename + ".symbols" (e.g. /boot/kernel/foo.ko.symbols) 224 * - dirname(kernel) + filename + ".debug" (e.g. /boot/kernel/foo.ko.debug) 225 * - dirname(kernel) + filename (e.g. /boot/kernel/foo.ko) 226 * - iterate over each path in the module path looking for: 227 * - dir + filename + ".symbols" (e.g. /boot/modules/foo.ko.symbols) 228 * - dir + filename + ".debug" (e.g. /boot/modules/foo.ko.debug) 229 * - dir + filename (e.g. /boot/modules/foo.ko) 230 */ 231static int 232find_kld_path (char *filename, char *path, size_t path_size) 233{ 234 CORE_ADDR module_path_addr; 235 char module_path[PATH_MAX]; 236 char *kernel_dir, *module_dir, *cp; 237 238 snprintf(path, path_size, "%s.symbols", filename); 239 if (kld_ok(path)) 240 return (1); 241 snprintf(path, path_size, "%s.debug", filename); 242 if (kld_ok(path)) 243 return (1); 244 snprintf(path, path_size, "%s", filename); 245 if (kld_ok(path)) 246 return (1); 247 kernel_dir = dirname(kernel); 248 if (kernel_dir != NULL) { 249 snprintf(path, path_size, "%s/%s.symbols", kernel_dir, 250 filename); 251 if (kld_ok(path)) 252 return (1); 253 snprintf(path, path_size, "%s/%s.debug", kernel_dir, filename); 254 if (kld_ok(path)) 255 return (1); 256 snprintf(path, path_size, "%s/%s", kernel_dir, filename); 257 if (kld_ok(path)) 258 return (1); 259 } 260 module_path_addr = kgdb_parse("linker_path"); 261 if (module_path_addr != 0 && 262 kvm_read(kvm, module_path_addr, module_path, sizeof(module_path)) == 263 sizeof(module_path)) { 264 module_path[PATH_MAX - 1] = '\0'; 265 cp = module_path; 266 while ((module_dir = strsep(&cp, ";")) != NULL) { 267 snprintf(path, path_size, "%s/%s.symbols", module_dir, 268 filename); 269 if (kld_ok(path)) 270 return (1); 271 snprintf(path, path_size, "%s/%s.debug", module_dir, 272 filename); 273 if (kld_ok(path)) 274 return (1); 275 snprintf(path, path_size, "%s/%s", module_dir, 276 filename); 277 if (kld_ok(path)) 278 return (1); 279 } 280 } 281 return (0); 282} 283 284/* 285 * Read a kernel pointer given a KVA in 'address'. 286 */ 287static CORE_ADDR 288read_pointer (CORE_ADDR address) 289{ 290 union { 291 uint32_t d32; 292 uint64_t d64; 293 } val; 294 295 switch (TARGET_PTR_BIT) { 296 case 32: 297 if (kvm_read(kvm, address, &val.d32, sizeof(val.d32)) != 298 sizeof(val.d32)) 299 return (0); 300 return (val.d32); 301 case 64: 302 if (kvm_read(kvm, address, &val.d64, sizeof(val.d64)) != 303 sizeof(val.d64)) 304 return (0); 305 return (val.d64); 306 default: 307 return (0); 308 } 309} 310 311/* 312 * Try to find this kld in the kernel linker's list of linker files. 313 */ 314static int 315find_kld_address (char *arg, CORE_ADDR *address) 316{ 317 CORE_ADDR kld, filename_addr; 318 CORE_ADDR off_address, off_filename, off_next; 319 char kld_filename[PATH_MAX]; 320 char *filename; 321 size_t filelen; 322 323 /* Compute offsets of relevant members in struct linker_file. */ 324 off_address = kgdb_parse("&((struct linker_file *)0)->address"); 325 off_filename = kgdb_parse("&((struct linker_file *)0)->filename"); 326 off_next = kgdb_parse("&((struct linker_file *)0)->link.tqe_next"); 327 if (off_address == 0 || off_filename == 0 || off_next == 0) 328 return (0); 329 330 filename = basename(arg); 331 filelen = strlen(filename) + 1; 332 kld = kgdb_parse("linker_files.tqh_first"); 333 while (kld != 0) { 334 /* Try to read this linker file's filename. */ 335 filename_addr = read_pointer(kld + off_filename); 336 if (filename_addr == 0) 337 goto next_kld; 338 if (kvm_read(kvm, filename_addr, kld_filename, filelen) != 339 filelen) 340 goto next_kld; 341 342 /* Compare this kld's filename against our passed in name. */ 343 if (kld_filename[filelen - 1] != '\0') 344 goto next_kld; 345 if (strcmp(kld_filename, filename) != 0) 346 goto next_kld; 347 348 /* 349 * We found a match, use its address as the base 350 * address if we can read it. 351 */ 352 *address = read_pointer(kld + off_address); 353 if (*address == 0) 354 return (0); 355 return (1); 356 357 next_kld: 358 kld = read_pointer(kld + off_next); 359 } 360 return (0); 361} 362 363static void 364add_section(struct section_addr_info *section_addrs, int *sect_indexp, 365 char *name, CORE_ADDR address) 366{ 367 int sect_index; 368 369 sect_index = *sect_indexp; 370 section_addrs->other[sect_index].name = name; 371 section_addrs->other[sect_index].addr = address; 372 printf_unfiltered("\t%s_addr = %s\n", name, 373 local_hex_string(address)); 374 sect_index++; 375 *sect_indexp = sect_index; 376} 377 378static void 379kgdb_add_kld_cmd (char *arg, int from_tty) 380{ 381 struct section_addr_info *section_addrs; 382 struct cleanup *cleanup; 383 char path[PATH_MAX]; 384 asection *sect; 385 CORE_ADDR base_addr; 386 bfd *bfd; 387 CORE_ADDR text_addr, data_addr, bss_addr, rodata_addr; 388 int sect_count, sect_index; 389 390 if (!find_kld_path(arg, path, sizeof(path))) { 391 error("unable to locate kld"); 392 return; 393 } 394 395 if (!find_kld_address(arg, &base_addr)) { 396 error("unable to find kld in kernel"); 397 return; 398 } 399 400 /* Open the kld and find the offsets of the various sections. */ 401 bfd = bfd_openr(path, gnutarget); 402 if (bfd == NULL) { 403 error("\"%s\": can't open: %s", path, 404 bfd_errmsg(bfd_get_error())); 405 return; 406 } 407 cleanup = make_cleanup_bfd_close(bfd); 408 409 if (!bfd_check_format(bfd, bfd_object)) { 410 do_cleanups(cleanup); 411 error("\%s\": not an object file", path); 412 return; 413 } 414 415 data_addr = bss_addr = rodata_addr = 0; 416 sect = bfd_get_section_by_name (bfd, ".text"); 417 if (sect == NULL) { 418 do_cleanups(cleanup); 419 error("\"%s\": can't find text section", path); 420 return; 421 } 422 text_addr = bfd_get_section_vma(bfd, sect); 423 sect_count = 1; 424 425 /* Save the offsets of relevant sections. */ 426 sect = bfd_get_section_by_name (bfd, ".data"); 427 if (sect != NULL) { 428 data_addr = bfd_get_section_vma(bfd, sect); 429 sect_count++; 430 } 431 432 sect = bfd_get_section_by_name (bfd, ".bss"); 433 if (sect != NULL) { 434 bss_addr = bfd_get_section_vma(bfd, sect); 435 sect_count++; 436 } 437 438 sect = bfd_get_section_by_name (bfd, ".rodata"); 439 if (sect != NULL) { 440 rodata_addr = bfd_get_section_vma(bfd, sect); 441 sect_count++; 442 } 443 444 do_cleanups(cleanup); 445 446 printf_unfiltered("add symbol table from file \"%s\" at\n", path); 447 448 /* Build a section table for symbol_file_add(). */ 449 section_addrs = alloc_section_addr_info(sect_count); 450 cleanup = make_cleanup(xfree, section_addrs); 451 sect_index = 0; 452 add_section(section_addrs, §_index, ".text", base_addr + text_addr); 453 if (data_addr != 0) 454 add_section(section_addrs, §_index, ".data", 455 base_addr + data_addr); 456 if (bss_addr != 0) 457 add_section(section_addrs, §_index, ".bss", 458 base_addr + bss_addr); 459 if (rodata_addr != 0) 460 add_section(section_addrs, §_index, ".rodata", 461 base_addr + rodata_addr); 462 463 symbol_file_add(path, from_tty, section_addrs, 0, OBJF_USERLOADED); 464 465 reinit_frame_cache(); 466 467 do_cleanups(cleanup); 468} 469 470void 471kgdb_target(void) 472{ 473 struct kthr *kt; 474 struct thread_info *ti; 475 476 kgdb_trgt_ops.to_magic = OPS_MAGIC; 477 kgdb_trgt_ops.to_shortname = "kernel"; 478 kgdb_trgt_ops.to_longname = "kernel core files."; 479 kgdb_trgt_ops.to_doc = "Kernel core files."; 480 kgdb_trgt_ops.to_stratum = thread_stratum; 481 kgdb_trgt_ops.to_has_memory = 1; 482 kgdb_trgt_ops.to_has_registers = 1; 483 kgdb_trgt_ops.to_has_stack = 1; 484 485 kgdb_trgt_ops.to_extra_thread_info = kgdb_trgt_extra_thread_info; 486 kgdb_trgt_ops.to_fetch_registers = kgdb_trgt_fetch_registers; 487 kgdb_trgt_ops.to_files_info = kgdb_trgt_files_info; 488 kgdb_trgt_ops.to_find_new_threads = kgdb_trgt_find_new_threads; 489 kgdb_trgt_ops.to_pid_to_str = kgdb_trgt_pid_to_str; 490 kgdb_trgt_ops.to_store_registers = kgdb_trgt_store_registers; 491 kgdb_trgt_ops.to_thread_alive = kgdb_trgt_thread_alive; 492 kgdb_trgt_ops.to_xfer_memory = kgdb_trgt_xfer_memory; 493 add_target(&kgdb_trgt_ops); 494 push_target(&kgdb_trgt_ops); 495 496 kt = kgdb_thr_first(); 497 while (kt != NULL) { 498 ti = add_thread(ptid_build(kt->pid, 0, kt->tid)); 499 kt = kgdb_thr_next(kt); 500 } 501 if (curkthr != 0) 502 inferior_ptid = ptid_build(curkthr->pid, 0, curkthr->tid); 503 add_com ("proc", class_obscure, kgdb_set_proc_cmd, 504 "Set current process context"); 505 add_com ("tid", class_obscure, kgdb_set_tid_cmd, 506 "Set current thread context"); 507 add_com ("add-kld", class_files, kgdb_add_kld_cmd, 508 "Usage: add-kld FILE\n\ 509Load the symbols from the kernel loadable module FILE."); 510} 511