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", 81175774Sjhb "", 82175774Sjhb NULL 83175774Sjhb}; 84175774Sjhb 85175645Sjhbstatic int 86175774Sjhbcheck_kld_path (char *path, size_t path_size) 87175774Sjhb{ 88175774Sjhb const char **suffix; 89175774Sjhb char *ep; 90175774Sjhb 91175774Sjhb ep = path + strlen(path); 92175774Sjhb suffix = kld_suffixes; 93175774Sjhb while (*suffix != NULL) { 94175774Sjhb if (strlcat(path, *suffix, path_size) < path_size) { 95175774Sjhb if (kld_ok(path)) 96175774Sjhb return (1); 97175774Sjhb } 98175774Sjhb 99175774Sjhb /* Restore original path to remove suffix. */ 100175774Sjhb *ep = '\0'; 101175774Sjhb suffix++; 102175774Sjhb } 103175774Sjhb return (0); 104175774Sjhb} 105175774Sjhb 106175774Sjhb/* 107175774Sjhb * Try to find the path for a kld by looking in the kernel's directory and 108175774Sjhb * in the various paths in the module path. 109175774Sjhb */ 110175774Sjhbstatic int 111175645Sjhbfind_kld_path (char *filename, char *path, size_t path_size) 112175645Sjhb{ 113175774Sjhb char *module_path; 114175645Sjhb char *kernel_dir, *module_dir, *cp; 115175774Sjhb int error; 116175645Sjhb 117178670Sjhb if (exec_bfd) { 118178670Sjhb kernel_dir = dirname(bfd_get_filename(exec_bfd)); 119178670Sjhb if (kernel_dir != NULL) { 120178670Sjhb snprintf(path, path_size, "%s/%s", kernel_dir, 121178670Sjhb filename); 122178670Sjhb if (check_kld_path(path, path_size)) 123178670Sjhb return (1); 124178670Sjhb } 125175645Sjhb } 126175774Sjhb if (module_path_addr != 0) { 127175774Sjhb target_read_string(module_path_addr, &module_path, PATH_MAX, 128175774Sjhb &error); 129175774Sjhb if (error == 0) { 130175774Sjhb make_cleanup(xfree, module_path); 131175774Sjhb cp = module_path; 132175774Sjhb while ((module_dir = strsep(&cp, ";")) != NULL) { 133175774Sjhb snprintf(path, path_size, "%s/%s", module_dir, 134175774Sjhb filename); 135175774Sjhb if (check_kld_path(path, path_size)) 136175774Sjhb return (1); 137175774Sjhb } 138175645Sjhb } 139175774Sjhb } 140175645Sjhb return (0); 141175645Sjhb} 142175645Sjhb 143175645Sjhb/* 144175645Sjhb * Read a kernel pointer given a KVA in 'address'. 145175645Sjhb */ 146175645Sjhbstatic CORE_ADDR 147175645Sjhbread_pointer (CORE_ADDR address) 148175645Sjhb{ 149175807Sjhb CORE_ADDR value; 150175645Sjhb 151175807Sjhb if (target_read_memory(address, (char *)&value, TARGET_PTR_BIT / 8) != 152175807Sjhb 0) 153175807Sjhb return (0); 154175807Sjhb return (extract_unsigned_integer(&value, TARGET_PTR_BIT / 8)); 155175645Sjhb} 156175645Sjhb 157175645Sjhb/* 158175645Sjhb * Try to find this kld in the kernel linker's list of linker files. 159175645Sjhb */ 160175645Sjhbstatic int 161175645Sjhbfind_kld_address (char *arg, CORE_ADDR *address) 162175645Sjhb{ 163175774Sjhb CORE_ADDR kld; 164175774Sjhb char *kld_filename; 165175645Sjhb char *filename; 166175774Sjhb int error; 167175645Sjhb 168178670Sjhb if (linker_files_addr == 0 || off_address == 0 || off_filename == 0 || 169178670Sjhb off_next == 0) 170175645Sjhb return (0); 171175645Sjhb 172175645Sjhb filename = basename(arg); 173178670Sjhb for (kld = read_pointer(linker_files_addr); kld != 0; 174175775Sjhb kld = read_pointer(kld + off_next)) { 175175645Sjhb /* Try to read this linker file's filename. */ 176175774Sjhb target_read_string(read_pointer(kld + off_filename), 177175774Sjhb &kld_filename, PATH_MAX, &error); 178175774Sjhb if (error) 179175775Sjhb continue; 180175645Sjhb 181175645Sjhb /* Compare this kld's filename against our passed in name. */ 182175774Sjhb if (strcmp(kld_filename, filename) != 0) { 183175774Sjhb xfree(kld_filename); 184175775Sjhb continue; 185175774Sjhb } 186175774Sjhb xfree(kld_filename); 187175645Sjhb 188175645Sjhb /* 189175645Sjhb * We found a match, use its address as the base 190175645Sjhb * address if we can read it. 191175645Sjhb */ 192175645Sjhb *address = read_pointer(kld + off_address); 193175645Sjhb if (*address == 0) 194175645Sjhb return (0); 195175645Sjhb return (1); 196175645Sjhb } 197175645Sjhb return (0); 198175645Sjhb} 199175645Sjhb 200175645Sjhbstatic void 201210424Savgadjust_section_address (struct section_table *sec, CORE_ADDR *curr_base) 202210424Savg{ 203210424Savg struct bfd_section *asect = sec->the_bfd_section; 204210424Savg bfd *abfd = sec->bfd; 205210424Savg 206210424Savg if ((abfd->flags & (EXEC_P | DYNAMIC)) != 0) { 207210424Savg sec->addr += *curr_base; 208210424Savg sec->endaddr += *curr_base; 209210424Savg return; 210210424Savg } 211210424Savg 212210424Savg *curr_base = align_power(*curr_base, 213210424Savg bfd_get_section_alignment(abfd, asect)); 214210424Savg sec->addr = *curr_base; 215210424Savg sec->endaddr = sec->addr + bfd_section_size(abfd, asect); 216210424Savg *curr_base = sec->endaddr; 217210424Savg} 218210424Savg 219210424Savgstatic void 220178634Sjhbload_kld (char *path, CORE_ADDR base_addr, int from_tty) 221175645Sjhb{ 222183359Sjhb struct section_addr_info *sap; 223183556Sjhb struct section_table *sections = NULL, *sections_end = NULL, *s; 224175645Sjhb struct cleanup *cleanup; 225175645Sjhb bfd *bfd; 226210424Savg CORE_ADDR curr_addr; 227183359Sjhb int i; 228175645Sjhb 229175774Sjhb /* Open the kld. */ 230175645Sjhb bfd = bfd_openr(path, gnutarget); 231175774Sjhb if (bfd == NULL) 232175645Sjhb error("\"%s\": can't open: %s", path, 233175645Sjhb bfd_errmsg(bfd_get_error())); 234175645Sjhb cleanup = make_cleanup_bfd_close(bfd); 235175645Sjhb 236175774Sjhb if (!bfd_check_format(bfd, bfd_object)) 237175645Sjhb error("\%s\": not an object file", path); 238175645Sjhb 239175774Sjhb /* Make sure we have a .text section. */ 240175774Sjhb if (bfd_get_section_by_name (bfd, ".text") == NULL) 241175645Sjhb error("\"%s\": can't find text section", path); 242175645Sjhb 243183359Sjhb /* Build a section table from the bfd and relocate the sections. */ 244183359Sjhb if (build_section_table (bfd, §ions, §ions_end)) 245183359Sjhb error("\"%s\": can't find file sections", path); 246183359Sjhb cleanup = make_cleanup(xfree, sections); 247210424Savg curr_addr = base_addr; 248210424Savg for (s = sections; s < sections_end; s++) 249210424Savg adjust_section_address(s, &curr_addr); 250183359Sjhb 251183359Sjhb /* Build a section addr info to pass to symbol_file_add(). */ 252183359Sjhb sap = build_section_addr_info_from_section_table (sections, 253183359Sjhb sections_end); 254183359Sjhb cleanup = make_cleanup((make_cleanup_ftype *)free_section_addr_info, 255183359Sjhb sap); 256183359Sjhb 257178634Sjhb printf_unfiltered("add symbol table from file \"%s\" at\n", path); 258183359Sjhb for (i = 0; i < sap->num_sections; i++) 259183359Sjhb printf_unfiltered("\t%s_addr = %s\n", sap->other[i].name, 260183359Sjhb local_hex_string(sap->other[i].addr)); 261175774Sjhb 262175774Sjhb if (from_tty && (!query("%s", ""))) 263175774Sjhb error("Not confirmed."); 264175774Sjhb 265183359Sjhb symbol_file_add(path, from_tty, sap, 0, OBJF_USERLOADED); 266175774Sjhb 267175774Sjhb do_cleanups(cleanup); 268175774Sjhb} 269175774Sjhb 270178670Sjhbstatic void 271175774Sjhbkgdb_add_kld_cmd (char *arg, int from_tty) 272175774Sjhb{ 273175774Sjhb char path[PATH_MAX]; 274175774Sjhb CORE_ADDR base_addr; 275175774Sjhb 276178670Sjhb if (!exec_bfd) 277178670Sjhb error("No kernel symbol file"); 278178670Sjhb 279175774Sjhb /* Try to open the raw path to handle absolute paths first. */ 280175774Sjhb snprintf(path, sizeof(path), "%s", arg); 281175774Sjhb if (!check_kld_path(path, sizeof(path))) { 282175774Sjhb 283175774Sjhb /* 284175774Sjhb * If that didn't work, look in the various possible 285175774Sjhb * paths for the module. 286175774Sjhb */ 287175774Sjhb if (!find_kld_path(arg, path, sizeof(path))) { 288175774Sjhb error("Unable to locate kld"); 289175774Sjhb return; 290175774Sjhb } 291175645Sjhb } 292175645Sjhb 293175774Sjhb if (!find_kld_address(arg, &base_addr)) { 294175774Sjhb error("Unable to find kld in kernel"); 295175774Sjhb return; 296175645Sjhb } 297175645Sjhb 298178634Sjhb load_kld(path, base_addr, from_tty); 299175774Sjhb 300175774Sjhb reinit_frame_cache(); 301175774Sjhb} 302175774Sjhb 303175774Sjhbstatic void 304175809Sjhbkld_relocate_section_addresses (struct so_list *so, struct section_table *sec) 305175774Sjhb{ 306210424Savg static CORE_ADDR curr_addr; 307175809Sjhb 308210424Savg if (sec == so->sections) 309210424Savg curr_addr = so->lm_info->base_address; 310210424Savg 311210424Savg adjust_section_address(sec, &curr_addr); 312175774Sjhb} 313175774Sjhb 314175774Sjhbstatic void 315175809Sjhbkld_free_so (struct so_list *so) 316175774Sjhb{ 317175774Sjhb 318175809Sjhb xfree(so->lm_info); 319175809Sjhb} 320175774Sjhb 321175809Sjhbstatic void 322175809Sjhbkld_clear_solib (void) 323175809Sjhb{ 324175809Sjhb} 325175774Sjhb 326175809Sjhbstatic void 327175809Sjhbkld_solib_create_inferior_hook (void) 328175809Sjhb{ 329175809Sjhb} 330175774Sjhb 331175809Sjhbstatic void 332175809Sjhbkld_special_symbol_handling (void) 333175809Sjhb{ 334175809Sjhb} 335175645Sjhb 336175809Sjhbstatic struct so_list * 337175809Sjhbkld_current_sos (void) 338175809Sjhb{ 339175809Sjhb struct so_list *head, **prev, *new; 340175809Sjhb CORE_ADDR kld, kernel; 341175809Sjhb char *path; 342175809Sjhb int error; 343175809Sjhb 344178670Sjhb if (linker_files_addr == 0 || kernel_file_addr == 0 || 345178670Sjhb off_address == 0 || off_filename == 0 || off_next == 0) 346178670Sjhb return (NULL); 347178670Sjhb 348177701Sjhb head = NULL; 349175809Sjhb prev = &head; 350175809Sjhb 351175774Sjhb /* 352175809Sjhb * Walk the list of linker files creating so_list entries for 353175809Sjhb * each non-kernel file. 354175774Sjhb */ 355178670Sjhb kernel = read_pointer(kernel_file_addr); 356178670Sjhb for (kld = read_pointer(linker_files_addr); kld != 0; 357175809Sjhb kld = read_pointer(kld + off_next)) { 358175809Sjhb /* Skip the main kernel file. */ 359175809Sjhb if (kld == kernel) 360175809Sjhb continue; 361175645Sjhb 362175809Sjhb new = xmalloc(sizeof(*new)); 363175809Sjhb memset(new, 0, sizeof(*new)); 364175645Sjhb 365175809Sjhb new->lm_info = xmalloc(sizeof(*new->lm_info)); 366175809Sjhb new->lm_info->base_address = 0; 367175645Sjhb 368175809Sjhb /* Read the base filename and store it in so_original_name. */ 369175809Sjhb target_read_string(read_pointer(kld + off_filename), 370175809Sjhb &path, sizeof(new->so_original_name), &error); 371175809Sjhb if (error != 0) { 372175809Sjhb warning("kld_current_sos: Can't read filename: %s\n", 373175809Sjhb safe_strerror(error)); 374175809Sjhb free_so(new); 375175809Sjhb continue; 376175809Sjhb } 377175809Sjhb strlcpy(new->so_original_name, path, 378175809Sjhb sizeof(new->so_original_name)); 379175809Sjhb xfree(path); 380175809Sjhb 381175809Sjhb /* 382175809Sjhb * Try to read the pathname (if it exists) and store 383175809Sjhb * it in so_name. 384175809Sjhb */ 385175809Sjhb if (off_pathname != 0) { 386175809Sjhb target_read_string(read_pointer(kld + off_pathname), 387175809Sjhb &path, sizeof(new->so_name), &error); 388175809Sjhb if (error != 0) { 389175809Sjhb warning( 390175809Sjhb "kld_current_sos: Can't read pathname for \"%s\": %s\n", 391175809Sjhb new->so_original_name, 392175809Sjhb safe_strerror(error)); 393175809Sjhb strlcpy(new->so_name, new->so_original_name, 394175809Sjhb sizeof(new->so_name)); 395175809Sjhb } else { 396175809Sjhb strlcpy(new->so_name, path, 397175809Sjhb sizeof(new->so_name)); 398175809Sjhb xfree(path); 399175809Sjhb } 400175809Sjhb } else 401175809Sjhb strlcpy(new->so_name, new->so_original_name, 402175809Sjhb sizeof(new->so_name)); 403175809Sjhb 404175809Sjhb /* Read this kld's base address. */ 405175809Sjhb new->lm_info->base_address = read_pointer(kld + off_address); 406175809Sjhb if (new->lm_info->base_address == 0) { 407175809Sjhb warning( 408175809Sjhb "kld_current_sos: Invalid address for kld \"%s\"", 409175809Sjhb new->so_original_name); 410175809Sjhb free_so(new); 411175809Sjhb continue; 412175809Sjhb } 413175809Sjhb 414175809Sjhb /* Append to the list. */ 415175809Sjhb *prev = new; 416175809Sjhb prev = &new->next; 417175809Sjhb } 418175809Sjhb 419175809Sjhb return (head); 420175774Sjhb} 421175645Sjhb 422175774Sjhbstatic int 423175809Sjhbkld_open_symbol_file_object (void *from_ttyp) 424175774Sjhb{ 425175645Sjhb 426175809Sjhb return (0); 427175809Sjhb} 428175774Sjhb 429175809Sjhbstatic int 430175809Sjhbkld_in_dynsym_resolve_code (CORE_ADDR pc) 431175809Sjhb{ 432175809Sjhb 433175809Sjhb return (0); 434175774Sjhb} 435175774Sjhb 436175809Sjhbstatic int 437175809Sjhbkld_find_and_open_solib (char *solib, unsigned o_flags, char **temp_pathname) 438175809Sjhb{ 439175809Sjhb char path[PATH_MAX]; 440175809Sjhb int fd; 441175809Sjhb 442175809Sjhb *temp_pathname = NULL; 443175809Sjhb if (!find_kld_path(solib, path, sizeof(path))) { 444175809Sjhb errno = ENOENT; 445175809Sjhb return (-1); 446175809Sjhb } 447175809Sjhb fd = open(path, o_flags, 0); 448175809Sjhb if (fd >= 0) 449175809Sjhb *temp_pathname = xstrdup(path); 450175809Sjhb return (fd); 451175809Sjhb} 452175809Sjhb 453178670Sjhbvoid 454178670Sjhbkld_new_objfile (struct objfile *objfile) 455178670Sjhb{ 456178670Sjhb 457178670Sjhb if (!have_partial_symbols()) 458178670Sjhb return; 459178670Sjhb 460178670Sjhb /* 461178670Sjhb * Compute offsets of relevant members in struct linker_file 462178670Sjhb * and the addresses of global variables. Don't warn about 463178670Sjhb * kernels that don't have 'pathname' in the linker_file 464178670Sjhb * struct since 6.x kernels don't have it. 465178670Sjhb */ 466178670Sjhb off_address = kgdb_parse("&((struct linker_file *)0)->address"); 467178670Sjhb off_filename = kgdb_parse("&((struct linker_file *)0)->filename"); 468178670Sjhb off_pathname = kgdb_parse_quiet("&((struct linker_file *)0)->pathname"); 469178670Sjhb off_next = kgdb_parse("&((struct linker_file *)0)->link.tqe_next"); 470178670Sjhb module_path_addr = kgdb_parse("linker_path"); 471178670Sjhb linker_files_addr = kgdb_parse("&linker_files.tqh_first"); 472178670Sjhb kernel_file_addr = kgdb_parse("&linker_kernel_file"); 473178670Sjhb} 474178670Sjhb 475175809Sjhbstatic int 476175809Sjhbload_klds_stub (void *arg) 477175809Sjhb{ 478175809Sjhb 479175809Sjhb SOLIB_ADD(NULL, 1, ¤t_target, auto_solib_add); 480175809Sjhb return (0); 481175809Sjhb} 482175809Sjhb 483175774Sjhbvoid 484178670Sjhbkld_init (void) 485175774Sjhb{ 486175774Sjhb 487178670Sjhb catch_errors(load_klds_stub, NULL, NULL, RETURN_MASK_ALL); 488178670Sjhb} 489175774Sjhb 490178670Sjhbvoid 491178670Sjhbinitialize_kld_target(void) 492178670Sjhb{ 493178670Sjhb struct cmd_list_element *c; 494175774Sjhb 495175809Sjhb kld_so_ops.relocate_section_addresses = kld_relocate_section_addresses; 496175809Sjhb kld_so_ops.free_so = kld_free_so; 497175809Sjhb kld_so_ops.clear_solib = kld_clear_solib; 498175809Sjhb kld_so_ops.solib_create_inferior_hook = kld_solib_create_inferior_hook; 499175809Sjhb kld_so_ops.special_symbol_handling = kld_special_symbol_handling; 500175809Sjhb kld_so_ops.current_sos = kld_current_sos; 501175809Sjhb kld_so_ops.open_symbol_file_object = kld_open_symbol_file_object; 502175809Sjhb kld_so_ops.in_dynsym_resolve_code = kld_in_dynsym_resolve_code; 503175809Sjhb kld_so_ops.find_and_open_solib = kld_find_and_open_solib; 504175774Sjhb 505175809Sjhb current_target_so_ops = &kld_so_ops; 506175774Sjhb 507175809Sjhb c = add_com("add-kld", class_files, kgdb_add_kld_cmd, 508175809Sjhb "Usage: add-kld FILE\n\ 509175809SjhbLoad the symbols from the kernel loadable module FILE."); 510175809Sjhb set_cmd_completer(c, filename_completer); 511175645Sjhb} 512