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