1175645Sjhb/* 2175645Sjhb * Copyright (c) 2004 Marcel Moolenaar 3175645Sjhb * All rights reserved. 4175645Sjhb * 5175645Sjhb * Redistribution and use in source and binary forms, with or without 6175645Sjhb * modification, are permitted provided that the following conditions 7175645Sjhb * are met: 8175645Sjhb * 9175645Sjhb * 1. Redistributions of source code must retain the above copyright 10175645Sjhb * notice, this list of conditions and the following disclaimer. 11175645Sjhb * 2. Redistributions in binary form must reproduce the above copyright 12175645Sjhb * notice, this list of conditions and the following disclaimer in the 13175645Sjhb * documentation and/or other materials provided with the distribution. 14175645Sjhb * 15175645Sjhb * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16175645Sjhb * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17175645Sjhb * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18175645Sjhb * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19175645Sjhb * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20175645Sjhb * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21175645Sjhb * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22175645Sjhb * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23175645Sjhb * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24175645Sjhb * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25175645Sjhb */ 26175645Sjhb 27175645Sjhb#include <sys/cdefs.h> 28175645Sjhb__FBSDID("$FreeBSD$"); 29175645Sjhb 30175645Sjhb#include <sys/param.h> 31175645Sjhb#include <sys/stat.h> 32175809Sjhb#include <fcntl.h> 33175809Sjhb#include <kvm.h> 34175645Sjhb#include <libgen.h> 35175645Sjhb 36175645Sjhb#include <defs.h> 37175809Sjhb#include <command.h> 38175809Sjhb#include <completer.h> 39175809Sjhb#include <environ.h> 40183359Sjhb#include <exec.h> 41175645Sjhb#include <frame-unwind.h> 42175645Sjhb#include <inferior.h> 43175645Sjhb#include <objfiles.h> 44175645Sjhb#include <gdbcore.h> 45175645Sjhb#include <language.h> 46175809Sjhb#include <solist.h> 47175645Sjhb 48175645Sjhb#include "kgdb.h" 49175645Sjhb 50175809Sjhbstruct lm_info { 51175809Sjhb CORE_ADDR base_address; 52175809Sjhb}; 53175774Sjhb 54175774Sjhb/* Offsets of fields in linker_file structure. */ 55175774Sjhbstatic CORE_ADDR off_address, off_filename, off_pathname, off_next; 56175774Sjhb 57175809Sjhb/* KVA of 'linker_path' which corresponds to the kern.module_path sysctl .*/ 58175809Sjhbstatic CORE_ADDR module_path_addr; 59178670Sjhbstatic CORE_ADDR linker_files_addr; 60178670Sjhbstatic CORE_ADDR kernel_file_addr; 61175809Sjhb 62175809Sjhbstatic struct target_so_ops kld_so_ops; 63175809Sjhb 64175645Sjhbstatic int 65175645Sjhbkld_ok (char *path) 66175645Sjhb{ 67175645Sjhb struct stat sb; 68175645Sjhb 69175645Sjhb if (stat(path, &sb) == 0 && S_ISREG(sb.st_mode)) 70175645Sjhb return (1); 71175645Sjhb return (0); 72175645Sjhb} 73175645Sjhb 74175645Sjhb/* 75175774Sjhb * Look for a matching file checking for debug suffixes before the raw file: 76175645Sjhb * - filename + ".debug" (e.g. foo.ko.debug) 77175645Sjhb * - filename (e.g. foo.ko) 78175645Sjhb */ 79175774Sjhbstatic const char *kld_suffixes[] = { 80175774Sjhb ".debug", 81248838Swill ".symbols", 82175774Sjhb "", 83175774Sjhb NULL 84175774Sjhb}; 85175774Sjhb 86175645Sjhbstatic int 87175774Sjhbcheck_kld_path (char *path, size_t path_size) 88175774Sjhb{ 89175774Sjhb const char **suffix; 90175774Sjhb char *ep; 91175774Sjhb 92175774Sjhb ep = path + strlen(path); 93175774Sjhb suffix = kld_suffixes; 94175774Sjhb while (*suffix != NULL) { 95175774Sjhb if (strlcat(path, *suffix, path_size) < path_size) { 96175774Sjhb if (kld_ok(path)) 97175774Sjhb return (1); 98175774Sjhb } 99175774Sjhb 100175774Sjhb /* Restore original path to remove suffix. */ 101175774Sjhb *ep = '\0'; 102175774Sjhb suffix++; 103175774Sjhb } 104175774Sjhb return (0); 105175774Sjhb} 106175774Sjhb 107175774Sjhb/* 108175774Sjhb * Try to find the path for a kld by looking in the kernel's directory and 109175774Sjhb * in the various paths in the module path. 110175774Sjhb */ 111175774Sjhbstatic int 112175645Sjhbfind_kld_path (char *filename, char *path, size_t path_size) 113175645Sjhb{ 114175774Sjhb char *module_path; 115175645Sjhb char *kernel_dir, *module_dir, *cp; 116175774Sjhb int error; 117175645Sjhb 118178670Sjhb if (exec_bfd) { 119178670Sjhb kernel_dir = dirname(bfd_get_filename(exec_bfd)); 120178670Sjhb if (kernel_dir != NULL) { 121178670Sjhb snprintf(path, path_size, "%s/%s", kernel_dir, 122178670Sjhb filename); 123178670Sjhb if (check_kld_path(path, path_size)) 124178670Sjhb return (1); 125178670Sjhb } 126175645Sjhb } 127175774Sjhb if (module_path_addr != 0) { 128175774Sjhb target_read_string(module_path_addr, &module_path, PATH_MAX, 129175774Sjhb &error); 130175774Sjhb if (error == 0) { 131175774Sjhb make_cleanup(xfree, module_path); 132175774Sjhb cp = module_path; 133175774Sjhb while ((module_dir = strsep(&cp, ";")) != NULL) { 134175774Sjhb snprintf(path, path_size, "%s/%s", module_dir, 135175774Sjhb filename); 136175774Sjhb if (check_kld_path(path, path_size)) 137175774Sjhb return (1); 138175774Sjhb } 139175645Sjhb } 140175774Sjhb } 141175645Sjhb return (0); 142175645Sjhb} 143175645Sjhb 144175645Sjhb/* 145175645Sjhb * Read a kernel pointer given a KVA in 'address'. 146175645Sjhb */ 147175645Sjhbstatic CORE_ADDR 148175645Sjhbread_pointer (CORE_ADDR address) 149175645Sjhb{ 150175807Sjhb CORE_ADDR value; 151175645Sjhb 152175807Sjhb if (target_read_memory(address, (char *)&value, TARGET_PTR_BIT / 8) != 153175807Sjhb 0) 154175807Sjhb return (0); 155175807Sjhb return (extract_unsigned_integer(&value, TARGET_PTR_BIT / 8)); 156175645Sjhb} 157175645Sjhb 158175645Sjhb/* 159175645Sjhb * Try to find this kld in the kernel linker's list of linker files. 160175645Sjhb */ 161175645Sjhbstatic int 162175645Sjhbfind_kld_address (char *arg, CORE_ADDR *address) 163175645Sjhb{ 164175774Sjhb CORE_ADDR kld; 165175774Sjhb char *kld_filename; 166175645Sjhb char *filename; 167175774Sjhb int error; 168175645Sjhb 169178670Sjhb if (linker_files_addr == 0 || off_address == 0 || off_filename == 0 || 170178670Sjhb off_next == 0) 171175645Sjhb return (0); 172175645Sjhb 173175645Sjhb filename = basename(arg); 174178670Sjhb for (kld = read_pointer(linker_files_addr); kld != 0; 175175775Sjhb kld = read_pointer(kld + off_next)) { 176175645Sjhb /* Try to read this linker file's filename. */ 177175774Sjhb target_read_string(read_pointer(kld + off_filename), 178175774Sjhb &kld_filename, PATH_MAX, &error); 179175774Sjhb if (error) 180175775Sjhb continue; 181175645Sjhb 182175645Sjhb /* Compare this kld's filename against our passed in name. */ 183175774Sjhb if (strcmp(kld_filename, filename) != 0) { 184175774Sjhb xfree(kld_filename); 185175775Sjhb continue; 186175774Sjhb } 187175774Sjhb xfree(kld_filename); 188175645Sjhb 189175645Sjhb /* 190175645Sjhb * We found a match, use its address as the base 191175645Sjhb * address if we can read it. 192175645Sjhb */ 193175645Sjhb *address = read_pointer(kld + off_address); 194175645Sjhb if (*address == 0) 195175645Sjhb return (0); 196175645Sjhb return (1); 197175645Sjhb } 198175645Sjhb return (0); 199175645Sjhb} 200175645Sjhb 201175645Sjhbstatic void 202210424Savgadjust_section_address (struct section_table *sec, CORE_ADDR *curr_base) 203210424Savg{ 204210424Savg struct bfd_section *asect = sec->the_bfd_section; 205210424Savg bfd *abfd = sec->bfd; 206210424Savg 207210424Savg if ((abfd->flags & (EXEC_P | DYNAMIC)) != 0) { 208210424Savg sec->addr += *curr_base; 209210424Savg sec->endaddr += *curr_base; 210210424Savg return; 211210424Savg } 212210424Savg 213210424Savg *curr_base = align_power(*curr_base, 214210424Savg bfd_get_section_alignment(abfd, asect)); 215210424Savg sec->addr = *curr_base; 216210424Savg sec->endaddr = sec->addr + bfd_section_size(abfd, asect); 217210424Savg *curr_base = sec->endaddr; 218210424Savg} 219210424Savg 220210424Savgstatic void 221178634Sjhbload_kld (char *path, CORE_ADDR base_addr, int from_tty) 222175645Sjhb{ 223183359Sjhb struct section_addr_info *sap; 224183556Sjhb struct section_table *sections = NULL, *sections_end = NULL, *s; 225175645Sjhb struct cleanup *cleanup; 226175645Sjhb bfd *bfd; 227210424Savg CORE_ADDR curr_addr; 228183359Sjhb int i; 229175645Sjhb 230175774Sjhb /* Open the kld. */ 231175645Sjhb bfd = bfd_openr(path, gnutarget); 232175774Sjhb if (bfd == NULL) 233175645Sjhb error("\"%s\": can't open: %s", path, 234175645Sjhb bfd_errmsg(bfd_get_error())); 235175645Sjhb cleanup = make_cleanup_bfd_close(bfd); 236175645Sjhb 237175774Sjhb if (!bfd_check_format(bfd, bfd_object)) 238175645Sjhb error("\%s\": not an object file", path); 239175645Sjhb 240175774Sjhb /* Make sure we have a .text section. */ 241175774Sjhb if (bfd_get_section_by_name (bfd, ".text") == NULL) 242175645Sjhb error("\"%s\": can't find text section", path); 243175645Sjhb 244183359Sjhb /* Build a section table from the bfd and relocate the sections. */ 245183359Sjhb if (build_section_table (bfd, §ions, §ions_end)) 246183359Sjhb error("\"%s\": can't find file sections", path); 247183359Sjhb cleanup = make_cleanup(xfree, sections); 248210424Savg curr_addr = base_addr; 249210424Savg for (s = sections; s < sections_end; s++) 250210424Savg adjust_section_address(s, &curr_addr); 251183359Sjhb 252183359Sjhb /* Build a section addr info to pass to symbol_file_add(). */ 253183359Sjhb sap = build_section_addr_info_from_section_table (sections, 254183359Sjhb sections_end); 255183359Sjhb cleanup = make_cleanup((make_cleanup_ftype *)free_section_addr_info, 256183359Sjhb sap); 257183359Sjhb 258178634Sjhb printf_unfiltered("add symbol table from file \"%s\" at\n", path); 259183359Sjhb for (i = 0; i < sap->num_sections; i++) 260183359Sjhb printf_unfiltered("\t%s_addr = %s\n", sap->other[i].name, 261183359Sjhb local_hex_string(sap->other[i].addr)); 262175774Sjhb 263175774Sjhb if (from_tty && (!query("%s", ""))) 264175774Sjhb error("Not confirmed."); 265175774Sjhb 266183359Sjhb symbol_file_add(path, from_tty, sap, 0, OBJF_USERLOADED); 267175774Sjhb 268175774Sjhb do_cleanups(cleanup); 269175774Sjhb} 270175774Sjhb 271178670Sjhbstatic void 272175774Sjhbkgdb_add_kld_cmd (char *arg, int from_tty) 273175774Sjhb{ 274175774Sjhb char path[PATH_MAX]; 275175774Sjhb CORE_ADDR base_addr; 276175774Sjhb 277178670Sjhb if (!exec_bfd) 278178670Sjhb error("No kernel symbol file"); 279178670Sjhb 280175774Sjhb /* Try to open the raw path to handle absolute paths first. */ 281175774Sjhb snprintf(path, sizeof(path), "%s", arg); 282175774Sjhb if (!check_kld_path(path, sizeof(path))) { 283175774Sjhb 284175774Sjhb /* 285175774Sjhb * If that didn't work, look in the various possible 286175774Sjhb * paths for the module. 287175774Sjhb */ 288175774Sjhb if (!find_kld_path(arg, path, sizeof(path))) { 289175774Sjhb error("Unable to locate kld"); 290175774Sjhb return; 291175774Sjhb } 292175645Sjhb } 293175645Sjhb 294175774Sjhb if (!find_kld_address(arg, &base_addr)) { 295175774Sjhb error("Unable to find kld in kernel"); 296175774Sjhb return; 297175645Sjhb } 298175645Sjhb 299178634Sjhb load_kld(path, base_addr, from_tty); 300175774Sjhb 301175774Sjhb reinit_frame_cache(); 302175774Sjhb} 303175774Sjhb 304175774Sjhbstatic void 305175809Sjhbkld_relocate_section_addresses (struct so_list *so, struct section_table *sec) 306175774Sjhb{ 307210424Savg static CORE_ADDR curr_addr; 308175809Sjhb 309210424Savg if (sec == so->sections) 310210424Savg curr_addr = so->lm_info->base_address; 311210424Savg 312210424Savg adjust_section_address(sec, &curr_addr); 313175774Sjhb} 314175774Sjhb 315175774Sjhbstatic void 316175809Sjhbkld_free_so (struct so_list *so) 317175774Sjhb{ 318175774Sjhb 319175809Sjhb xfree(so->lm_info); 320175809Sjhb} 321175774Sjhb 322175809Sjhbstatic void 323175809Sjhbkld_clear_solib (void) 324175809Sjhb{ 325175809Sjhb} 326175774Sjhb 327175809Sjhbstatic void 328175809Sjhbkld_solib_create_inferior_hook (void) 329175809Sjhb{ 330175809Sjhb} 331175774Sjhb 332175809Sjhbstatic void 333175809Sjhbkld_special_symbol_handling (void) 334175809Sjhb{ 335175809Sjhb} 336175645Sjhb 337175809Sjhbstatic struct so_list * 338175809Sjhbkld_current_sos (void) 339175809Sjhb{ 340175809Sjhb struct so_list *head, **prev, *new; 341175809Sjhb CORE_ADDR kld, kernel; 342175809Sjhb char *path; 343175809Sjhb int error; 344175809Sjhb 345178670Sjhb if (linker_files_addr == 0 || kernel_file_addr == 0 || 346178670Sjhb off_address == 0 || off_filename == 0 || off_next == 0) 347178670Sjhb return (NULL); 348178670Sjhb 349177701Sjhb head = NULL; 350175809Sjhb prev = &head; 351175809Sjhb 352175774Sjhb /* 353175809Sjhb * Walk the list of linker files creating so_list entries for 354175809Sjhb * each non-kernel file. 355175774Sjhb */ 356178670Sjhb kernel = read_pointer(kernel_file_addr); 357178670Sjhb for (kld = read_pointer(linker_files_addr); kld != 0; 358175809Sjhb kld = read_pointer(kld + off_next)) { 359175809Sjhb /* Skip the main kernel file. */ 360175809Sjhb if (kld == kernel) 361175809Sjhb continue; 362175645Sjhb 363175809Sjhb new = xmalloc(sizeof(*new)); 364175809Sjhb memset(new, 0, sizeof(*new)); 365175645Sjhb 366175809Sjhb new->lm_info = xmalloc(sizeof(*new->lm_info)); 367175809Sjhb new->lm_info->base_address = 0; 368175645Sjhb 369175809Sjhb /* Read the base filename and store it in so_original_name. */ 370175809Sjhb target_read_string(read_pointer(kld + off_filename), 371175809Sjhb &path, sizeof(new->so_original_name), &error); 372175809Sjhb if (error != 0) { 373175809Sjhb warning("kld_current_sos: Can't read filename: %s\n", 374175809Sjhb safe_strerror(error)); 375175809Sjhb free_so(new); 376175809Sjhb continue; 377175809Sjhb } 378175809Sjhb strlcpy(new->so_original_name, path, 379175809Sjhb sizeof(new->so_original_name)); 380175809Sjhb xfree(path); 381175809Sjhb 382175809Sjhb /* 383175809Sjhb * Try to read the pathname (if it exists) and store 384175809Sjhb * it in so_name. 385175809Sjhb */ 386248836Swill if (find_kld_path(new->so_original_name, new->so_name, 387248836Swill sizeof(new->so_name))) { 388248836Swill /* we found the kld */; 389248836Swill } else if (off_pathname != 0) { 390175809Sjhb target_read_string(read_pointer(kld + off_pathname), 391175809Sjhb &path, sizeof(new->so_name), &error); 392175809Sjhb if (error != 0) { 393175809Sjhb warning( 394175809Sjhb "kld_current_sos: Can't read pathname for \"%s\": %s\n", 395175809Sjhb new->so_original_name, 396175809Sjhb safe_strerror(error)); 397175809Sjhb strlcpy(new->so_name, new->so_original_name, 398175809Sjhb sizeof(new->so_name)); 399175809Sjhb } else { 400175809Sjhb strlcpy(new->so_name, path, 401175809Sjhb sizeof(new->so_name)); 402175809Sjhb xfree(path); 403175809Sjhb } 404175809Sjhb } else 405175809Sjhb strlcpy(new->so_name, new->so_original_name, 406175809Sjhb sizeof(new->so_name)); 407175809Sjhb 408175809Sjhb /* Read this kld's base address. */ 409175809Sjhb new->lm_info->base_address = read_pointer(kld + off_address); 410175809Sjhb if (new->lm_info->base_address == 0) { 411175809Sjhb warning( 412175809Sjhb "kld_current_sos: Invalid address for kld \"%s\"", 413175809Sjhb new->so_original_name); 414175809Sjhb free_so(new); 415175809Sjhb continue; 416175809Sjhb } 417175809Sjhb 418175809Sjhb /* Append to the list. */ 419175809Sjhb *prev = new; 420175809Sjhb prev = &new->next; 421175809Sjhb } 422175809Sjhb 423175809Sjhb return (head); 424175774Sjhb} 425175645Sjhb 426175774Sjhbstatic int 427175809Sjhbkld_open_symbol_file_object (void *from_ttyp) 428175774Sjhb{ 429175645Sjhb 430175809Sjhb return (0); 431175809Sjhb} 432175774Sjhb 433175809Sjhbstatic int 434175809Sjhbkld_in_dynsym_resolve_code (CORE_ADDR pc) 435175809Sjhb{ 436175809Sjhb 437175809Sjhb return (0); 438175774Sjhb} 439175774Sjhb 440175809Sjhbstatic int 441175809Sjhbkld_find_and_open_solib (char *solib, unsigned o_flags, char **temp_pathname) 442175809Sjhb{ 443175809Sjhb char path[PATH_MAX]; 444175809Sjhb int fd; 445175809Sjhb 446175809Sjhb *temp_pathname = NULL; 447175809Sjhb if (!find_kld_path(solib, path, sizeof(path))) { 448175809Sjhb errno = ENOENT; 449175809Sjhb return (-1); 450175809Sjhb } 451175809Sjhb fd = open(path, o_flags, 0); 452175809Sjhb if (fd >= 0) 453175809Sjhb *temp_pathname = xstrdup(path); 454175809Sjhb return (fd); 455175809Sjhb} 456175809Sjhb 457178670Sjhbvoid 458178670Sjhbkld_new_objfile (struct objfile *objfile) 459178670Sjhb{ 460178670Sjhb 461178670Sjhb if (!have_partial_symbols()) 462178670Sjhb return; 463178670Sjhb 464178670Sjhb /* 465178670Sjhb * Compute offsets of relevant members in struct linker_file 466178670Sjhb * and the addresses of global variables. Don't warn about 467178670Sjhb * kernels that don't have 'pathname' in the linker_file 468178670Sjhb * struct since 6.x kernels don't have it. 469178670Sjhb */ 470178670Sjhb off_address = kgdb_parse("&((struct linker_file *)0)->address"); 471178670Sjhb off_filename = kgdb_parse("&((struct linker_file *)0)->filename"); 472178670Sjhb off_pathname = kgdb_parse_quiet("&((struct linker_file *)0)->pathname"); 473178670Sjhb off_next = kgdb_parse("&((struct linker_file *)0)->link.tqe_next"); 474178670Sjhb module_path_addr = kgdb_parse("linker_path"); 475178670Sjhb linker_files_addr = kgdb_parse("&linker_files.tqh_first"); 476178670Sjhb kernel_file_addr = kgdb_parse("&linker_kernel_file"); 477178670Sjhb} 478178670Sjhb 479175809Sjhbstatic int 480175809Sjhbload_klds_stub (void *arg) 481175809Sjhb{ 482175809Sjhb 483175809Sjhb SOLIB_ADD(NULL, 1, ¤t_target, auto_solib_add); 484175809Sjhb return (0); 485175809Sjhb} 486175809Sjhb 487175774Sjhbvoid 488178670Sjhbkld_init (void) 489175774Sjhb{ 490175774Sjhb 491178670Sjhb catch_errors(load_klds_stub, NULL, NULL, RETURN_MASK_ALL); 492178670Sjhb} 493175774Sjhb 494178670Sjhbvoid 495178670Sjhbinitialize_kld_target(void) 496178670Sjhb{ 497178670Sjhb struct cmd_list_element *c; 498175774Sjhb 499175809Sjhb kld_so_ops.relocate_section_addresses = kld_relocate_section_addresses; 500175809Sjhb kld_so_ops.free_so = kld_free_so; 501175809Sjhb kld_so_ops.clear_solib = kld_clear_solib; 502175809Sjhb kld_so_ops.solib_create_inferior_hook = kld_solib_create_inferior_hook; 503175809Sjhb kld_so_ops.special_symbol_handling = kld_special_symbol_handling; 504175809Sjhb kld_so_ops.current_sos = kld_current_sos; 505175809Sjhb kld_so_ops.open_symbol_file_object = kld_open_symbol_file_object; 506175809Sjhb kld_so_ops.in_dynsym_resolve_code = kld_in_dynsym_resolve_code; 507175809Sjhb kld_so_ops.find_and_open_solib = kld_find_and_open_solib; 508175774Sjhb 509175809Sjhb current_target_so_ops = &kld_so_ops; 510175774Sjhb 511175809Sjhb c = add_com("add-kld", class_files, kgdb_add_kld_cmd, 512175809Sjhb "Usage: add-kld FILE\n\ 513175809SjhbLoad the symbols from the kernel loadable module FILE."); 514175809Sjhb set_cmd_completer(c, filename_completer); 515175645Sjhb} 516