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, &sections, &sections_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, &current_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