kld.c revision 177701
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: head/gnu/usr.bin/gdb/kgdb/kld.c 177701 2008-03-29 03:48:06Z jhb $"); 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> 40175645Sjhb#include <frame-unwind.h> 41175645Sjhb#include <inferior.h> 42175645Sjhb#include <objfiles.h> 43175645Sjhb#include <gdbcore.h> 44175645Sjhb#include <language.h> 45175809Sjhb#include <solist.h> 46175645Sjhb 47175645Sjhb#include "kgdb.h" 48175645Sjhb 49175809Sjhbstruct lm_info { 50175809Sjhb CORE_ADDR base_address; 51175809Sjhb}; 52175774Sjhb 53175774Sjhb/* Offsets of fields in linker_file structure. */ 54175774Sjhbstatic CORE_ADDR off_address, off_filename, off_pathname, off_next; 55175774Sjhb 56175809Sjhb/* KVA of 'linker_path' which corresponds to the kern.module_path sysctl .*/ 57175809Sjhbstatic CORE_ADDR module_path_addr; 58175809Sjhb 59175809Sjhbstatic struct target_so_ops kld_so_ops; 60175809Sjhb 61175645Sjhbstatic int 62175645Sjhbkld_ok (char *path) 63175645Sjhb{ 64175645Sjhb struct stat sb; 65175645Sjhb 66175645Sjhb if (stat(path, &sb) == 0 && S_ISREG(sb.st_mode)) 67175645Sjhb return (1); 68175645Sjhb return (0); 69175645Sjhb} 70175645Sjhb 71175645Sjhb/* 72175774Sjhb * Look for a matching file checking for debug suffixes before the raw file: 73175645Sjhb * - filename + ".symbols" (e.g. foo.ko.symbols) 74175645Sjhb * - filename + ".debug" (e.g. foo.ko.debug) 75175645Sjhb * - filename (e.g. foo.ko) 76175645Sjhb */ 77175774Sjhbstatic const char *kld_suffixes[] = { 78175774Sjhb ".debug", 79175774Sjhb "", 80175774Sjhb NULL 81175774Sjhb}; 82175774Sjhb 83175645Sjhbstatic int 84175774Sjhbcheck_kld_path (char *path, size_t path_size) 85175774Sjhb{ 86175774Sjhb const char **suffix; 87175774Sjhb char *ep; 88175774Sjhb 89175774Sjhb ep = path + strlen(path); 90175774Sjhb suffix = kld_suffixes; 91175774Sjhb while (*suffix != NULL) { 92175774Sjhb if (strlcat(path, *suffix, path_size) < path_size) { 93175774Sjhb if (kld_ok(path)) 94175774Sjhb return (1); 95175774Sjhb } 96175774Sjhb 97175774Sjhb /* Restore original path to remove suffix. */ 98175774Sjhb *ep = '\0'; 99175774Sjhb suffix++; 100175774Sjhb } 101175774Sjhb return (0); 102175774Sjhb} 103175774Sjhb 104175774Sjhb/* 105175774Sjhb * Try to find the path for a kld by looking in the kernel's directory and 106175774Sjhb * in the various paths in the module path. 107175774Sjhb */ 108175774Sjhbstatic int 109175645Sjhbfind_kld_path (char *filename, char *path, size_t path_size) 110175645Sjhb{ 111175774Sjhb char *module_path; 112175645Sjhb char *kernel_dir, *module_dir, *cp; 113175774Sjhb int error; 114175645Sjhb 115175645Sjhb kernel_dir = dirname(kernel); 116175645Sjhb if (kernel_dir != NULL) { 117175645Sjhb snprintf(path, path_size, "%s/%s", kernel_dir, filename); 118175774Sjhb if (check_kld_path(path, path_size)) 119175645Sjhb return (1); 120175645Sjhb } 121175774Sjhb if (module_path_addr != 0) { 122175774Sjhb target_read_string(module_path_addr, &module_path, PATH_MAX, 123175774Sjhb &error); 124175774Sjhb if (error == 0) { 125175774Sjhb make_cleanup(xfree, module_path); 126175774Sjhb cp = module_path; 127175774Sjhb while ((module_dir = strsep(&cp, ";")) != NULL) { 128175774Sjhb snprintf(path, path_size, "%s/%s", module_dir, 129175774Sjhb filename); 130175774Sjhb if (check_kld_path(path, path_size)) 131175774Sjhb return (1); 132175774Sjhb } 133175645Sjhb } 134175774Sjhb } 135175645Sjhb return (0); 136175645Sjhb} 137175645Sjhb 138175645Sjhb/* 139175645Sjhb * Read a kernel pointer given a KVA in 'address'. 140175645Sjhb */ 141175645Sjhbstatic CORE_ADDR 142175645Sjhbread_pointer (CORE_ADDR address) 143175645Sjhb{ 144175807Sjhb CORE_ADDR value; 145175645Sjhb 146175807Sjhb if (target_read_memory(address, (char *)&value, TARGET_PTR_BIT / 8) != 147175807Sjhb 0) 148175807Sjhb return (0); 149175807Sjhb return (extract_unsigned_integer(&value, TARGET_PTR_BIT / 8)); 150175645Sjhb} 151175645Sjhb 152175645Sjhb/* 153175645Sjhb * Try to find this kld in the kernel linker's list of linker files. 154175645Sjhb */ 155175645Sjhbstatic int 156175645Sjhbfind_kld_address (char *arg, CORE_ADDR *address) 157175645Sjhb{ 158175774Sjhb CORE_ADDR kld; 159175774Sjhb char *kld_filename; 160175645Sjhb char *filename; 161175774Sjhb int error; 162175645Sjhb 163175645Sjhb if (off_address == 0 || off_filename == 0 || off_next == 0) 164175645Sjhb return (0); 165175645Sjhb 166175645Sjhb filename = basename(arg); 167175775Sjhb for (kld = kgdb_parse("linker_files.tqh_first"); kld != 0; 168175775Sjhb kld = read_pointer(kld + off_next)) { 169175645Sjhb /* Try to read this linker file's filename. */ 170175774Sjhb target_read_string(read_pointer(kld + off_filename), 171175774Sjhb &kld_filename, PATH_MAX, &error); 172175774Sjhb if (error) 173175775Sjhb continue; 174175645Sjhb 175175645Sjhb /* Compare this kld's filename against our passed in name. */ 176175774Sjhb if (strcmp(kld_filename, filename) != 0) { 177175774Sjhb xfree(kld_filename); 178175775Sjhb continue; 179175774Sjhb } 180175774Sjhb xfree(kld_filename); 181175645Sjhb 182175645Sjhb /* 183175645Sjhb * We found a match, use its address as the base 184175645Sjhb * address if we can read it. 185175645Sjhb */ 186175645Sjhb *address = read_pointer(kld + off_address); 187175645Sjhb if (*address == 0) 188175645Sjhb return (0); 189175645Sjhb return (1); 190175645Sjhb } 191175645Sjhb return (0); 192175645Sjhb} 193175645Sjhb 194175774Sjhbstruct add_section_info { 195175774Sjhb struct section_addr_info *section_addrs; 196175774Sjhb int sect_index; 197175774Sjhb CORE_ADDR base_addr; 198175774Sjhb int add_kld_command; 199175774Sjhb}; 200175774Sjhb 201175645Sjhbstatic void 202175774Sjhbadd_section (bfd *bfd, asection *sect, void *arg) 203175645Sjhb{ 204175774Sjhb struct add_section_info *asi = arg; 205175774Sjhb CORE_ADDR address; 206175774Sjhb char *name; 207175645Sjhb 208175774Sjhb /* Ignore non-resident sections. */ 209175774Sjhb if ((bfd_get_section_flags(bfd, sect) & (SEC_ALLOC | SEC_LOAD)) == 0) 210175774Sjhb return; 211175774Sjhb 212175774Sjhb name = xstrdup(bfd_get_section_name(bfd, sect)); 213175774Sjhb make_cleanup(xfree, name); 214175774Sjhb address = asi->base_addr + bfd_get_section_vma(bfd, sect); 215175774Sjhb asi->section_addrs->other[asi->sect_index].name = name; 216175774Sjhb asi->section_addrs->other[asi->sect_index].addr = address; 217175774Sjhb asi->section_addrs->other[asi->sect_index].sectindex = sect->index; 218175774Sjhb if (asi->add_kld_command) 219175774Sjhb printf_unfiltered("\t%s_addr = %s\n", name, 220175774Sjhb local_hex_string(address)); 221175774Sjhb asi->sect_index++; 222175645Sjhb} 223175645Sjhb 224175774Sjhbstatic void 225175774Sjhbload_kld (char *path, CORE_ADDR base_addr, int from_tty, int add_kld_command) 226175645Sjhb{ 227175774Sjhb struct add_section_info asi; 228175645Sjhb struct cleanup *cleanup; 229175645Sjhb bfd *bfd; 230175645Sjhb 231175774Sjhb /* Open the kld. */ 232175645Sjhb bfd = bfd_openr(path, gnutarget); 233175774Sjhb if (bfd == NULL) 234175645Sjhb error("\"%s\": can't open: %s", path, 235175645Sjhb bfd_errmsg(bfd_get_error())); 236175645Sjhb cleanup = make_cleanup_bfd_close(bfd); 237175645Sjhb 238175774Sjhb if (!bfd_check_format(bfd, bfd_object)) 239175645Sjhb error("\%s\": not an object file", path); 240175645Sjhb 241175774Sjhb /* Make sure we have a .text section. */ 242175774Sjhb if (bfd_get_section_by_name (bfd, ".text") == NULL) 243175645Sjhb error("\"%s\": can't find text section", path); 244175645Sjhb 245175774Sjhb if (add_kld_command) 246175774Sjhb printf_unfiltered("add symbol table from file \"%s\" at\n", 247175774Sjhb path); 248175774Sjhb 249175774Sjhb /* Build a section table for symbol_file_add() from the bfd sections. */ 250175774Sjhb asi.section_addrs = alloc_section_addr_info(bfd_count_sections(bfd)); 251175774Sjhb cleanup = make_cleanup(xfree, asi.section_addrs); 252175774Sjhb asi.sect_index = 0; 253175774Sjhb asi.base_addr = base_addr; 254175774Sjhb asi.add_kld_command = add_kld_command; 255175774Sjhb bfd_map_over_sections(bfd, add_section, &asi); 256175774Sjhb 257175774Sjhb if (from_tty && (!query("%s", ""))) 258175774Sjhb error("Not confirmed."); 259175774Sjhb 260175774Sjhb symbol_file_add(path, from_tty, asi.section_addrs, 0, 261175774Sjhb add_kld_command ? OBJF_USERLOADED : 0); 262175774Sjhb 263175774Sjhb do_cleanups(cleanup); 264175774Sjhb} 265175774Sjhb 266175774Sjhbvoid 267175774Sjhbkgdb_add_kld_cmd (char *arg, int from_tty) 268175774Sjhb{ 269175774Sjhb char path[PATH_MAX]; 270175774Sjhb CORE_ADDR base_addr; 271175774Sjhb 272175774Sjhb /* Try to open the raw path to handle absolute paths first. */ 273175774Sjhb snprintf(path, sizeof(path), "%s", arg); 274175774Sjhb if (!check_kld_path(path, sizeof(path))) { 275175774Sjhb 276175774Sjhb /* 277175774Sjhb * If that didn't work, look in the various possible 278175774Sjhb * paths for the module. 279175774Sjhb */ 280175774Sjhb if (!find_kld_path(arg, path, sizeof(path))) { 281175774Sjhb error("Unable to locate kld"); 282175774Sjhb return; 283175774Sjhb } 284175645Sjhb } 285175645Sjhb 286175774Sjhb if (!find_kld_address(arg, &base_addr)) { 287175774Sjhb error("Unable to find kld in kernel"); 288175774Sjhb return; 289175645Sjhb } 290175645Sjhb 291175774Sjhb load_kld(path, base_addr, from_tty, 1); 292175774Sjhb 293175774Sjhb reinit_frame_cache(); 294175774Sjhb} 295175774Sjhb 296175774Sjhbstatic void 297175809Sjhbkld_relocate_section_addresses (struct so_list *so, struct section_table *sec) 298175774Sjhb{ 299175809Sjhb 300175809Sjhb sec->addr += so->lm_info->base_address; 301175809Sjhb sec->endaddr += so->lm_info->base_address; 302175774Sjhb} 303175774Sjhb 304175774Sjhbstatic void 305175809Sjhbkld_free_so (struct so_list *so) 306175774Sjhb{ 307175774Sjhb 308175809Sjhb xfree(so->lm_info); 309175809Sjhb} 310175774Sjhb 311175809Sjhbstatic void 312175809Sjhbkld_clear_solib (void) 313175809Sjhb{ 314175809Sjhb} 315175774Sjhb 316175809Sjhbstatic void 317175809Sjhbkld_solib_create_inferior_hook (void) 318175809Sjhb{ 319175809Sjhb} 320175774Sjhb 321175809Sjhbstatic void 322175809Sjhbkld_special_symbol_handling (void) 323175809Sjhb{ 324175809Sjhb} 325175645Sjhb 326175809Sjhbstatic struct so_list * 327175809Sjhbkld_current_sos (void) 328175809Sjhb{ 329175809Sjhb struct so_list *head, **prev, *new; 330175809Sjhb CORE_ADDR kld, kernel; 331175809Sjhb char *path; 332175809Sjhb int error; 333175809Sjhb 334177701Sjhb head = NULL; 335175809Sjhb prev = &head; 336175809Sjhb 337175774Sjhb /* 338175809Sjhb * Walk the list of linker files creating so_list entries for 339175809Sjhb * each non-kernel file. 340175774Sjhb */ 341175809Sjhb kernel = kgdb_parse("linker_kernel_file"); 342175809Sjhb for (kld = kgdb_parse("linker_files.tqh_first"); kld != 0; 343175809Sjhb kld = read_pointer(kld + off_next)) { 344175809Sjhb /* Skip the main kernel file. */ 345175809Sjhb if (kld == kernel) 346175809Sjhb continue; 347175645Sjhb 348175809Sjhb new = xmalloc(sizeof(*new)); 349175809Sjhb memset(new, 0, sizeof(*new)); 350175645Sjhb 351175809Sjhb new->lm_info = xmalloc(sizeof(*new->lm_info)); 352175809Sjhb new->lm_info->base_address = 0; 353175645Sjhb 354175809Sjhb /* Read the base filename and store it in so_original_name. */ 355175809Sjhb target_read_string(read_pointer(kld + off_filename), 356175809Sjhb &path, sizeof(new->so_original_name), &error); 357175809Sjhb if (error != 0) { 358175809Sjhb warning("kld_current_sos: Can't read filename: %s\n", 359175809Sjhb safe_strerror(error)); 360175809Sjhb free_so(new); 361175809Sjhb continue; 362175809Sjhb } 363175809Sjhb strlcpy(new->so_original_name, path, 364175809Sjhb sizeof(new->so_original_name)); 365175809Sjhb xfree(path); 366175809Sjhb 367175809Sjhb /* 368175809Sjhb * Try to read the pathname (if it exists) and store 369175809Sjhb * it in so_name. 370175809Sjhb */ 371175809Sjhb if (off_pathname != 0) { 372175809Sjhb target_read_string(read_pointer(kld + off_pathname), 373175809Sjhb &path, sizeof(new->so_name), &error); 374175809Sjhb if (error != 0) { 375175809Sjhb warning( 376175809Sjhb "kld_current_sos: Can't read pathname for \"%s\": %s\n", 377175809Sjhb new->so_original_name, 378175809Sjhb safe_strerror(error)); 379175809Sjhb strlcpy(new->so_name, new->so_original_name, 380175809Sjhb sizeof(new->so_name)); 381175809Sjhb } else { 382175809Sjhb strlcpy(new->so_name, path, 383175809Sjhb sizeof(new->so_name)); 384175809Sjhb xfree(path); 385175809Sjhb } 386175809Sjhb } else 387175809Sjhb strlcpy(new->so_name, new->so_original_name, 388175809Sjhb sizeof(new->so_name)); 389175809Sjhb 390175809Sjhb /* Read this kld's base address. */ 391175809Sjhb new->lm_info->base_address = read_pointer(kld + off_address); 392175809Sjhb if (new->lm_info->base_address == 0) { 393175809Sjhb warning( 394175809Sjhb "kld_current_sos: Invalid address for kld \"%s\"", 395175809Sjhb new->so_original_name); 396175809Sjhb free_so(new); 397175809Sjhb continue; 398175809Sjhb } 399175809Sjhb 400175809Sjhb /* Append to the list. */ 401175809Sjhb *prev = new; 402175809Sjhb prev = &new->next; 403175809Sjhb } 404175809Sjhb 405175809Sjhb return (head); 406175774Sjhb} 407175645Sjhb 408175774Sjhbstatic int 409175809Sjhbkld_open_symbol_file_object (void *from_ttyp) 410175774Sjhb{ 411175645Sjhb 412175809Sjhb return (0); 413175809Sjhb} 414175774Sjhb 415175809Sjhbstatic int 416175809Sjhbkld_in_dynsym_resolve_code (CORE_ADDR pc) 417175809Sjhb{ 418175809Sjhb 419175809Sjhb return (0); 420175774Sjhb} 421175774Sjhb 422175809Sjhbstatic int 423175809Sjhbkld_find_and_open_solib (char *solib, unsigned o_flags, char **temp_pathname) 424175809Sjhb{ 425175809Sjhb char path[PATH_MAX]; 426175809Sjhb int fd; 427175809Sjhb 428175809Sjhb *temp_pathname = NULL; 429175809Sjhb if (!find_kld_path(solib, path, sizeof(path))) { 430175809Sjhb errno = ENOENT; 431175809Sjhb return (-1); 432175809Sjhb } 433175809Sjhb fd = open(path, o_flags, 0); 434175809Sjhb if (fd >= 0) 435175809Sjhb *temp_pathname = xstrdup(path); 436175809Sjhb return (fd); 437175809Sjhb} 438175809Sjhb 439175809Sjhbstatic int 440175809Sjhbload_klds_stub (void *arg) 441175809Sjhb{ 442175809Sjhb 443175809Sjhb SOLIB_ADD(NULL, 1, ¤t_target, auto_solib_add); 444175809Sjhb return (0); 445175809Sjhb} 446175809Sjhb 447175774Sjhbvoid 448175809Sjhbkgdb_kld_init (void) 449175774Sjhb{ 450175809Sjhb struct cmd_list_element *c; 451175774Sjhb 452175774Sjhb /* Compute offsets of relevant members in struct linker_file. */ 453175774Sjhb off_address = kgdb_parse("&((struct linker_file *)0)->address"); 454175774Sjhb off_filename = kgdb_parse("&((struct linker_file *)0)->filename"); 455175774Sjhb off_pathname = kgdb_parse("&((struct linker_file *)0)->pathname"); 456175774Sjhb off_next = kgdb_parse("&((struct linker_file *)0)->link.tqe_next"); 457175774Sjhb if (off_address == 0 || off_filename == 0 || off_next == 0) 458175774Sjhb return; 459175774Sjhb 460175809Sjhb module_path_addr = kgdb_parse("linker_path"); 461175774Sjhb 462175809Sjhb kld_so_ops.relocate_section_addresses = kld_relocate_section_addresses; 463175809Sjhb kld_so_ops.free_so = kld_free_so; 464175809Sjhb kld_so_ops.clear_solib = kld_clear_solib; 465175809Sjhb kld_so_ops.solib_create_inferior_hook = kld_solib_create_inferior_hook; 466175809Sjhb kld_so_ops.special_symbol_handling = kld_special_symbol_handling; 467175809Sjhb kld_so_ops.current_sos = kld_current_sos; 468175809Sjhb kld_so_ops.open_symbol_file_object = kld_open_symbol_file_object; 469175809Sjhb kld_so_ops.in_dynsym_resolve_code = kld_in_dynsym_resolve_code; 470175809Sjhb kld_so_ops.find_and_open_solib = kld_find_and_open_solib; 471175774Sjhb 472175809Sjhb current_target_so_ops = &kld_so_ops; 473175774Sjhb 474175809Sjhb catch_errors(load_klds_stub, NULL, NULL, RETURN_MASK_ALL); 475175809Sjhb 476175809Sjhb c = add_com("add-kld", class_files, kgdb_add_kld_cmd, 477175809Sjhb "Usage: add-kld FILE\n\ 478175809SjhbLoad the symbols from the kernel loadable module FILE."); 479175809Sjhb set_cmd_completer(c, filename_completer); 480175645Sjhb} 481