1f17ea84bSSimon Schubert /*
2f17ea84bSSimon Schubert * Copyright (c) 2004 Marcel Moolenaar
3f17ea84bSSimon Schubert * All rights reserved.
4f17ea84bSSimon Schubert *
5f17ea84bSSimon Schubert * Redistribution and use in source and binary forms, with or without
6f17ea84bSSimon Schubert * modification, are permitted provided that the following conditions
7f17ea84bSSimon Schubert * are met:
8f17ea84bSSimon Schubert *
9f17ea84bSSimon Schubert * 1. Redistributions of source code must retain the above copyright
10f17ea84bSSimon Schubert * notice, this list of conditions and the following disclaimer.
11f17ea84bSSimon Schubert * 2. Redistributions in binary form must reproduce the above copyright
12f17ea84bSSimon Schubert * notice, this list of conditions and the following disclaimer in the
13f17ea84bSSimon Schubert * documentation and/or other materials provided with the distribution.
14f17ea84bSSimon Schubert *
15f17ea84bSSimon Schubert * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16f17ea84bSSimon Schubert * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17f17ea84bSSimon Schubert * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18f17ea84bSSimon Schubert * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19f17ea84bSSimon Schubert * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20f17ea84bSSimon Schubert * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21f17ea84bSSimon Schubert * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22f17ea84bSSimon Schubert * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23f17ea84bSSimon Schubert * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24f17ea84bSSimon Schubert * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25f17ea84bSSimon Schubert *
26a938cc15SJohn Marino * $FreeBSD: src/gnu/usr.bin/gdb/kgdb/kld.c, svn 210424 2010/07/23 avg $
27f17ea84bSSimon Schubert */
28f17ea84bSSimon Schubert
29f17ea84bSSimon Schubert #include <sys/param.h>
30f17ea84bSSimon Schubert #include <sys/stat.h>
31f17ea84bSSimon Schubert #include <fcntl.h>
32f17ea84bSSimon Schubert #include <kvm.h>
33f17ea84bSSimon Schubert #include <libgen.h>
34f17ea84bSSimon Schubert
35f17ea84bSSimon Schubert #include <defs.h>
36f17ea84bSSimon Schubert #include <command.h>
37f17ea84bSSimon Schubert #include <completer.h>
38f17ea84bSSimon Schubert #include <environ.h>
39f17ea84bSSimon Schubert #include <exec.h>
40f17ea84bSSimon Schubert #include <frame-unwind.h>
41f17ea84bSSimon Schubert #include <inferior.h>
42f17ea84bSSimon Schubert #include <objfiles.h>
43f17ea84bSSimon Schubert #include <gdbcore.h>
44f17ea84bSSimon Schubert #include <language.h>
45f17ea84bSSimon Schubert #include <solist.h>
46f17ea84bSSimon Schubert #include <arch-utils.h>
47f17ea84bSSimon Schubert #include <solib.h>
48f17ea84bSSimon Schubert #include <exceptions.h>
49f17ea84bSSimon Schubert #include <observer.h>
50f17ea84bSSimon Schubert
51f17ea84bSSimon Schubert #include "kgdb.h"
52f17ea84bSSimon Schubert
53f17ea84bSSimon Schubert struct lm_info {
54f17ea84bSSimon Schubert CORE_ADDR base_address;
55f17ea84bSSimon Schubert };
56f17ea84bSSimon Schubert
57f17ea84bSSimon Schubert /* Offsets of fields in linker_file structure. */
58f17ea84bSSimon Schubert static CORE_ADDR off_address, off_filename, off_pathname, off_next;
59f17ea84bSSimon Schubert
60f17ea84bSSimon Schubert /* KVA of 'linker_path' which corresponds to the kern.module_path sysctl .*/
61f17ea84bSSimon Schubert static CORE_ADDR module_path_addr;
62f17ea84bSSimon Schubert static CORE_ADDR linker_files_addr;
63f17ea84bSSimon Schubert static CORE_ADDR kernel_file_addr;
64f17ea84bSSimon Schubert
65f17ea84bSSimon Schubert static struct target_so_ops kld_so_ops;
66f17ea84bSSimon Schubert
67f17ea84bSSimon Schubert static int
kld_ok(char * path)68f17ea84bSSimon Schubert kld_ok (char *path)
69f17ea84bSSimon Schubert {
70f17ea84bSSimon Schubert struct stat sb;
71f17ea84bSSimon Schubert
72f17ea84bSSimon Schubert if (stat(path, &sb) == 0 && S_ISREG(sb.st_mode))
73f17ea84bSSimon Schubert return (1);
74f17ea84bSSimon Schubert return (0);
75f17ea84bSSimon Schubert }
76f17ea84bSSimon Schubert
77f17ea84bSSimon Schubert /*
78f17ea84bSSimon Schubert * Look for a matching file checking for debug suffixes before the raw file:
79f17ea84bSSimon Schubert * - filename + ".debug" (e.g. foo.ko.debug)
80f17ea84bSSimon Schubert * - filename (e.g. foo.ko)
81f17ea84bSSimon Schubert */
82f17ea84bSSimon Schubert static const char *kld_suffixes[] = {
83f17ea84bSSimon Schubert ".debug",
84f17ea84bSSimon Schubert "",
85f17ea84bSSimon Schubert NULL
86f17ea84bSSimon Schubert };
87f17ea84bSSimon Schubert
88f17ea84bSSimon Schubert static int
check_kld_path(char * path,size_t path_size)89f17ea84bSSimon Schubert check_kld_path (char *path, size_t path_size)
90f17ea84bSSimon Schubert {
91f17ea84bSSimon Schubert const char **suffix;
92f17ea84bSSimon Schubert char *ep;
93f17ea84bSSimon Schubert
94f17ea84bSSimon Schubert ep = path + strlen(path);
95f17ea84bSSimon Schubert suffix = kld_suffixes;
96f17ea84bSSimon Schubert while (*suffix != NULL) {
97f17ea84bSSimon Schubert if (strlcat(path, *suffix, path_size) < path_size) {
98f17ea84bSSimon Schubert if (kld_ok(path))
99f17ea84bSSimon Schubert return (1);
100f17ea84bSSimon Schubert }
101f17ea84bSSimon Schubert
102f17ea84bSSimon Schubert /* Restore original path to remove suffix. */
103f17ea84bSSimon Schubert *ep = '\0';
104f17ea84bSSimon Schubert suffix++;
105f17ea84bSSimon Schubert }
106f17ea84bSSimon Schubert return (0);
107f17ea84bSSimon Schubert }
108f17ea84bSSimon Schubert
109f17ea84bSSimon Schubert /*
110f17ea84bSSimon Schubert * Try to find the path for a kld by looking in the kernel's directory and
111f17ea84bSSimon Schubert * in the various paths in the module path.
112f17ea84bSSimon Schubert */
113f17ea84bSSimon Schubert static int
find_kld_path(char * filename,char * path,size_t path_size)114f17ea84bSSimon Schubert find_kld_path (char *filename, char *path, size_t path_size)
115f17ea84bSSimon Schubert {
116f17ea84bSSimon Schubert char *module_path;
117f17ea84bSSimon Schubert char *kernel_dir, *module_dir, *cp;
118f17ea84bSSimon Schubert int error;
119f17ea84bSSimon Schubert
120f17ea84bSSimon Schubert if (exec_bfd) {
121f17ea84bSSimon Schubert kernel_dir = dirname(bfd_get_filename(exec_bfd));
122f17ea84bSSimon Schubert if (kernel_dir != NULL) {
123f17ea84bSSimon Schubert snprintf(path, path_size, "%s/%s", kernel_dir,
124f17ea84bSSimon Schubert filename);
125f17ea84bSSimon Schubert if (check_kld_path(path, path_size))
126f17ea84bSSimon Schubert return (1);
127f17ea84bSSimon Schubert }
128f17ea84bSSimon Schubert }
129f17ea84bSSimon Schubert if (module_path_addr != 0) {
130f17ea84bSSimon Schubert target_read_string(module_path_addr, &module_path, PATH_MAX,
131f17ea84bSSimon Schubert &error);
132f17ea84bSSimon Schubert if (error == 0) {
133f17ea84bSSimon Schubert make_cleanup(xfree, module_path);
134f17ea84bSSimon Schubert cp = module_path;
135f17ea84bSSimon Schubert while ((module_dir = strsep(&cp, ";")) != NULL) {
136f17ea84bSSimon Schubert snprintf(path, path_size, "%s/%s", module_dir,
137f17ea84bSSimon Schubert filename);
138f17ea84bSSimon Schubert if (check_kld_path(path, path_size))
139f17ea84bSSimon Schubert return (1);
140f17ea84bSSimon Schubert }
141f17ea84bSSimon Schubert }
142f17ea84bSSimon Schubert }
143f17ea84bSSimon Schubert return (0);
144f17ea84bSSimon Schubert }
145f17ea84bSSimon Schubert
146f17ea84bSSimon Schubert /*
147f17ea84bSSimon Schubert * Read a kernel pointer given a KVA in 'address'.
148f17ea84bSSimon Schubert */
149f17ea84bSSimon Schubert static CORE_ADDR
read_pointer(CORE_ADDR address)150f17ea84bSSimon Schubert read_pointer (CORE_ADDR address)
151f17ea84bSSimon Schubert {
152f17ea84bSSimon Schubert struct gdbarch *arch = get_current_arch();
153f17ea84bSSimon Schubert enum bfd_endian byte_order = gdbarch_byte_order(arch);
154f17ea84bSSimon Schubert gdb_byte buf[sizeof(ULONGEST)];
155f17ea84bSSimon Schubert int ptrsz;
156f17ea84bSSimon Schubert
157f17ea84bSSimon Schubert ptrsz = gdbarch_ptr_bit(arch) / 8;
158f17ea84bSSimon Schubert
159f17ea84bSSimon Schubert if (target_read_memory(address, buf, ptrsz) != 0)
160f17ea84bSSimon Schubert return (0);
161f17ea84bSSimon Schubert return (extract_unsigned_integer(buf, ptrsz, byte_order));
162f17ea84bSSimon Schubert }
163f17ea84bSSimon Schubert
164f17ea84bSSimon Schubert /*
165f17ea84bSSimon Schubert * Try to find this kld in the kernel linker's list of linker files.
166f17ea84bSSimon Schubert */
167f17ea84bSSimon Schubert static int
find_kld_address(char * arg,CORE_ADDR * address)168f17ea84bSSimon Schubert find_kld_address (char *arg, CORE_ADDR *address)
169f17ea84bSSimon Schubert {
170f17ea84bSSimon Schubert CORE_ADDR kld;
171f17ea84bSSimon Schubert char *kld_filename;
172f17ea84bSSimon Schubert char *filename;
173f17ea84bSSimon Schubert int error;
174f17ea84bSSimon Schubert
175f17ea84bSSimon Schubert if (linker_files_addr == 0 || off_address == 0 || off_filename == 0 ||
176f17ea84bSSimon Schubert off_next == 0)
177f17ea84bSSimon Schubert return (0);
178f17ea84bSSimon Schubert
179f17ea84bSSimon Schubert filename = basename(arg);
180f17ea84bSSimon Schubert for (kld = read_pointer(linker_files_addr); kld != 0;
181f17ea84bSSimon Schubert kld = read_pointer(kld + off_next)) {
182f17ea84bSSimon Schubert /* Try to read this linker file's filename. */
183f17ea84bSSimon Schubert target_read_string(read_pointer(kld + off_filename),
184f17ea84bSSimon Schubert &kld_filename, PATH_MAX, &error);
185f17ea84bSSimon Schubert if (error)
186f17ea84bSSimon Schubert continue;
187f17ea84bSSimon Schubert
188f17ea84bSSimon Schubert /* Compare this kld's filename against our passed in name. */
189f17ea84bSSimon Schubert if (strcmp(kld_filename, filename) != 0) {
190f17ea84bSSimon Schubert xfree(kld_filename);
191f17ea84bSSimon Schubert continue;
192f17ea84bSSimon Schubert }
193f17ea84bSSimon Schubert xfree(kld_filename);
194f17ea84bSSimon Schubert
195f17ea84bSSimon Schubert /*
196f17ea84bSSimon Schubert * We found a match, use its address as the base
197f17ea84bSSimon Schubert * address if we can read it.
198f17ea84bSSimon Schubert */
199f17ea84bSSimon Schubert *address = read_pointer(kld + off_address);
200f17ea84bSSimon Schubert if (*address == 0)
201f17ea84bSSimon Schubert return (0);
202f17ea84bSSimon Schubert return (1);
203f17ea84bSSimon Schubert }
204f17ea84bSSimon Schubert return (0);
205f17ea84bSSimon Schubert }
206f17ea84bSSimon Schubert
207f17ea84bSSimon Schubert static void
adjust_section_address(struct target_section * sec,CORE_ADDR * curr_base)208a938cc15SJohn Marino adjust_section_address (struct target_section *sec, CORE_ADDR *curr_base)
209a938cc15SJohn Marino {
210a938cc15SJohn Marino struct bfd_section *asect = sec->the_bfd_section;
211a938cc15SJohn Marino bfd *abfd = sec->bfd;
212a938cc15SJohn Marino
213a938cc15SJohn Marino if ((abfd->flags & (EXEC_P | DYNAMIC)) != 0) {
214a938cc15SJohn Marino sec->addr += *curr_base;
215a938cc15SJohn Marino sec->endaddr += *curr_base;
216a938cc15SJohn Marino return;
217a938cc15SJohn Marino }
218a938cc15SJohn Marino
219a938cc15SJohn Marino *curr_base = align_power(*curr_base,
220a938cc15SJohn Marino bfd_get_section_alignment(abfd, asect));
221a938cc15SJohn Marino sec->addr = *curr_base;
222a938cc15SJohn Marino sec->endaddr = sec->addr + bfd_section_size(abfd, asect);
223a938cc15SJohn Marino *curr_base = sec->endaddr;
224a938cc15SJohn Marino }
225a938cc15SJohn Marino
226a938cc15SJohn Marino static void
load_kld(char * path,CORE_ADDR base_addr,int from_tty)227f17ea84bSSimon Schubert load_kld (char *path, CORE_ADDR base_addr, int from_tty)
228f17ea84bSSimon Schubert {
229f17ea84bSSimon Schubert struct section_addr_info *sap;
230f17ea84bSSimon Schubert struct target_section *sections = NULL, *sections_end = NULL, *s;
231f17ea84bSSimon Schubert struct cleanup *cleanup;
232f17ea84bSSimon Schubert bfd *bfd;
233a938cc15SJohn Marino CORE_ADDR curr_addr;
234f17ea84bSSimon Schubert int i;
235f17ea84bSSimon Schubert
236f17ea84bSSimon Schubert /* Open the kld. */
237f17ea84bSSimon Schubert bfd = bfd_openr(path, gnutarget);
238f17ea84bSSimon Schubert if (bfd == NULL)
239f17ea84bSSimon Schubert error("\"%s\": can't open: %s", path,
240f17ea84bSSimon Schubert bfd_errmsg(bfd_get_error()));
241c33252afSJohn Marino cleanup = make_cleanup_bfd_unref(bfd);
242f17ea84bSSimon Schubert
243f17ea84bSSimon Schubert if (!bfd_check_format(bfd, bfd_object))
244*ecacb8afSSascha Wildner error("\"%s\": not an object file", path);
245f17ea84bSSimon Schubert
246f17ea84bSSimon Schubert /* Make sure we have a .text section. */
247f17ea84bSSimon Schubert if (bfd_get_section_by_name (bfd, ".text") == NULL)
248f17ea84bSSimon Schubert error("\"%s\": can't find text section", path);
249f17ea84bSSimon Schubert
250f17ea84bSSimon Schubert /* Build a section table from the bfd and relocate the sections. */
251f17ea84bSSimon Schubert if (build_section_table (bfd, §ions, §ions_end))
252f17ea84bSSimon Schubert error("\"%s\": can't find file sections", path);
253f17ea84bSSimon Schubert cleanup = make_cleanup(xfree, sections);
254a938cc15SJohn Marino curr_addr = base_addr;
255a938cc15SJohn Marino for (s = sections; s < sections_end; s++)
256a938cc15SJohn Marino adjust_section_address(s, &curr_addr);
257f17ea84bSSimon Schubert
258f17ea84bSSimon Schubert /* Build a section addr info to pass to symbol_file_add(). */
259f17ea84bSSimon Schubert sap = build_section_addr_info_from_section_table (sections,
260f17ea84bSSimon Schubert sections_end);
261f17ea84bSSimon Schubert cleanup = make_cleanup((make_cleanup_ftype *)free_section_addr_info,
262f17ea84bSSimon Schubert sap);
263f17ea84bSSimon Schubert
264f17ea84bSSimon Schubert printf_unfiltered("add symbol table from file \"%s\" at\n", path);
265f17ea84bSSimon Schubert for (i = 0; i < sap->num_sections; i++)
266f17ea84bSSimon Schubert printf_unfiltered("\t%s_addr = %s\n", sap->other[i].name,
267f17ea84bSSimon Schubert hex_string(sap->other[i].addr));
268f17ea84bSSimon Schubert
269f17ea84bSSimon Schubert if (from_tty && (!query("%s", "")))
270f17ea84bSSimon Schubert error("Not confirmed.");
271f17ea84bSSimon Schubert
272f17ea84bSSimon Schubert symbol_file_add(path, from_tty ? SYMFILE_VERBOSE : 0, sap, OBJF_USERLOADED);
273f17ea84bSSimon Schubert
274f17ea84bSSimon Schubert do_cleanups(cleanup);
275f17ea84bSSimon Schubert }
276f17ea84bSSimon Schubert
277f17ea84bSSimon Schubert static void
kgdb_add_kld_cmd(char * arg,int from_tty)278f17ea84bSSimon Schubert kgdb_add_kld_cmd (char *arg, int from_tty)
279f17ea84bSSimon Schubert {
280f17ea84bSSimon Schubert char path[PATH_MAX];
281f17ea84bSSimon Schubert CORE_ADDR base_addr;
282f17ea84bSSimon Schubert
283f17ea84bSSimon Schubert if (!exec_bfd)
284f17ea84bSSimon Schubert error("No kernel symbol file");
285f17ea84bSSimon Schubert
286f17ea84bSSimon Schubert /* Try to open the raw path to handle absolute paths first. */
287f17ea84bSSimon Schubert snprintf(path, sizeof(path), "%s", arg);
288f17ea84bSSimon Schubert if (!check_kld_path(path, sizeof(path))) {
289f17ea84bSSimon Schubert
290f17ea84bSSimon Schubert /*
291f17ea84bSSimon Schubert * If that didn't work, look in the various possible
292f17ea84bSSimon Schubert * paths for the module.
293f17ea84bSSimon Schubert */
294f17ea84bSSimon Schubert if (!find_kld_path(arg, path, sizeof(path))) {
295f17ea84bSSimon Schubert error("Unable to locate kld");
296f17ea84bSSimon Schubert return;
297f17ea84bSSimon Schubert }
298f17ea84bSSimon Schubert }
299f17ea84bSSimon Schubert
300f17ea84bSSimon Schubert if (!find_kld_address(arg, &base_addr)) {
301f17ea84bSSimon Schubert error("Unable to find kld in kernel");
302f17ea84bSSimon Schubert return;
303f17ea84bSSimon Schubert }
304f17ea84bSSimon Schubert
305f17ea84bSSimon Schubert load_kld(path, base_addr, from_tty);
306f17ea84bSSimon Schubert
307f17ea84bSSimon Schubert reinit_frame_cache();
308f17ea84bSSimon Schubert }
309f17ea84bSSimon Schubert
310f17ea84bSSimon Schubert static void
kld_relocate_section_addresses(struct so_list * so,struct target_section * sec)311f17ea84bSSimon Schubert kld_relocate_section_addresses (struct so_list *so, struct target_section *sec)
312f17ea84bSSimon Schubert {
313a938cc15SJohn Marino static CORE_ADDR curr_addr;
314f17ea84bSSimon Schubert
315a938cc15SJohn Marino if (sec == so->sections)
316a938cc15SJohn Marino curr_addr = so->lm_info->base_address;
317a938cc15SJohn Marino
318a938cc15SJohn Marino adjust_section_address(sec, &curr_addr);
319f17ea84bSSimon Schubert }
320f17ea84bSSimon Schubert
321f17ea84bSSimon Schubert static void
kld_free_so(struct so_list * so)322f17ea84bSSimon Schubert kld_free_so (struct so_list *so)
323f17ea84bSSimon Schubert {
324f17ea84bSSimon Schubert
325f17ea84bSSimon Schubert xfree(so->lm_info);
326f17ea84bSSimon Schubert }
327f17ea84bSSimon Schubert
328f17ea84bSSimon Schubert static void
kld_clear_solib(void)329f17ea84bSSimon Schubert kld_clear_solib (void)
330f17ea84bSSimon Schubert {
331f17ea84bSSimon Schubert }
332f17ea84bSSimon Schubert
333f17ea84bSSimon Schubert static void
kld_solib_create_inferior_hook(int from_tty)334a938cc15SJohn Marino kld_solib_create_inferior_hook (int from_tty)
335f17ea84bSSimon Schubert {
336f17ea84bSSimon Schubert }
337f17ea84bSSimon Schubert
338f17ea84bSSimon Schubert static void
kld_special_symbol_handling(void)339f17ea84bSSimon Schubert kld_special_symbol_handling (void)
340f17ea84bSSimon Schubert {
341f17ea84bSSimon Schubert }
342f17ea84bSSimon Schubert
343f17ea84bSSimon Schubert static struct so_list *
kld_current_sos(void)344f17ea84bSSimon Schubert kld_current_sos (void)
345f17ea84bSSimon Schubert {
346f17ea84bSSimon Schubert struct so_list *head, **prev, *new;
347f17ea84bSSimon Schubert CORE_ADDR kld, kernel;
348f17ea84bSSimon Schubert char *path;
349f17ea84bSSimon Schubert int error;
350f17ea84bSSimon Schubert
351f17ea84bSSimon Schubert if (linker_files_addr == 0 || kernel_file_addr == 0 ||
352f17ea84bSSimon Schubert off_address == 0 || off_filename == 0 || off_next == 0)
353f17ea84bSSimon Schubert return (NULL);
354f17ea84bSSimon Schubert
355f17ea84bSSimon Schubert head = NULL;
356f17ea84bSSimon Schubert prev = &head;
357f17ea84bSSimon Schubert
358f17ea84bSSimon Schubert /*
359f17ea84bSSimon Schubert * Walk the list of linker files creating so_list entries for
360f17ea84bSSimon Schubert * each non-kernel file.
361f17ea84bSSimon Schubert */
362f17ea84bSSimon Schubert kernel = read_pointer(kernel_file_addr);
363f17ea84bSSimon Schubert for (kld = read_pointer(linker_files_addr); kld != 0;
364f17ea84bSSimon Schubert kld = read_pointer(kld + off_next)) {
365f17ea84bSSimon Schubert /* Skip the main kernel file. */
366f17ea84bSSimon Schubert if (kld == kernel)
367f17ea84bSSimon Schubert continue;
368f17ea84bSSimon Schubert
369f17ea84bSSimon Schubert new = xmalloc(sizeof(*new));
370f17ea84bSSimon Schubert memset(new, 0, sizeof(*new));
371f17ea84bSSimon Schubert
372f17ea84bSSimon Schubert new->lm_info = xmalloc(sizeof(*new->lm_info));
373f17ea84bSSimon Schubert new->lm_info->base_address = 0;
374f17ea84bSSimon Schubert
375f17ea84bSSimon Schubert /* Read the base filename and store it in so_original_name. */
376f17ea84bSSimon Schubert target_read_string(read_pointer(kld + off_filename),
377f17ea84bSSimon Schubert &path, sizeof(new->so_original_name), &error);
378f17ea84bSSimon Schubert if (error != 0) {
379f17ea84bSSimon Schubert warning("kld_current_sos: Can't read filename: %s\n",
380f17ea84bSSimon Schubert safe_strerror(error));
381f17ea84bSSimon Schubert free_so(new);
382f17ea84bSSimon Schubert continue;
383f17ea84bSSimon Schubert }
384f17ea84bSSimon Schubert strlcpy(new->so_original_name, path,
385f17ea84bSSimon Schubert sizeof(new->so_original_name));
386f17ea84bSSimon Schubert xfree(path);
387f17ea84bSSimon Schubert
388f17ea84bSSimon Schubert /*
389f17ea84bSSimon Schubert * Try to read the pathname (if it exists) and store
390f17ea84bSSimon Schubert * it in so_name.
391f17ea84bSSimon Schubert */
392f17ea84bSSimon Schubert if (off_pathname != 0) {
393f17ea84bSSimon Schubert target_read_string(read_pointer(kld + off_pathname),
394f17ea84bSSimon Schubert &path, sizeof(new->so_name), &error);
395f17ea84bSSimon Schubert if (error != 0) {
396f17ea84bSSimon Schubert warning(
397f17ea84bSSimon Schubert "kld_current_sos: Can't read pathname for \"%s\": %s\n",
398f17ea84bSSimon Schubert new->so_original_name,
399f17ea84bSSimon Schubert safe_strerror(error));
400f17ea84bSSimon Schubert strlcpy(new->so_name, new->so_original_name,
401f17ea84bSSimon Schubert sizeof(new->so_name));
402f17ea84bSSimon Schubert } else {
403f17ea84bSSimon Schubert strlcpy(new->so_name, path,
404f17ea84bSSimon Schubert sizeof(new->so_name));
405f17ea84bSSimon Schubert xfree(path);
406f17ea84bSSimon Schubert }
407f17ea84bSSimon Schubert } else
408f17ea84bSSimon Schubert strlcpy(new->so_name, new->so_original_name,
409f17ea84bSSimon Schubert sizeof(new->so_name));
410f17ea84bSSimon Schubert
411f17ea84bSSimon Schubert /* Read this kld's base address. */
412f17ea84bSSimon Schubert new->lm_info->base_address = read_pointer(kld + off_address);
413f17ea84bSSimon Schubert if (new->lm_info->base_address == 0) {
414f17ea84bSSimon Schubert warning(
415f17ea84bSSimon Schubert "kld_current_sos: Invalid address for kld \"%s\"",
416f17ea84bSSimon Schubert new->so_original_name);
417f17ea84bSSimon Schubert free_so(new);
418f17ea84bSSimon Schubert continue;
419f17ea84bSSimon Schubert }
420f17ea84bSSimon Schubert
421f17ea84bSSimon Schubert /* Append to the list. */
422f17ea84bSSimon Schubert *prev = new;
423f17ea84bSSimon Schubert prev = &new->next;
424f17ea84bSSimon Schubert }
425f17ea84bSSimon Schubert
426f17ea84bSSimon Schubert return (head);
427f17ea84bSSimon Schubert }
428f17ea84bSSimon Schubert
429f17ea84bSSimon Schubert static int
kld_open_symbol_file_object(void * from_ttyp)430f17ea84bSSimon Schubert kld_open_symbol_file_object (void *from_ttyp)
431f17ea84bSSimon Schubert {
432f17ea84bSSimon Schubert
433f17ea84bSSimon Schubert return (0);
434f17ea84bSSimon Schubert }
435f17ea84bSSimon Schubert
436f17ea84bSSimon Schubert static int
kld_in_dynsym_resolve_code(CORE_ADDR pc)437f17ea84bSSimon Schubert kld_in_dynsym_resolve_code (CORE_ADDR pc)
438f17ea84bSSimon Schubert {
439f17ea84bSSimon Schubert
440f17ea84bSSimon Schubert return (0);
441f17ea84bSSimon Schubert }
442f17ea84bSSimon Schubert
443f17ea84bSSimon Schubert static int
kld_find_and_open_solib(char * solib,unsigned o_flags,char ** temp_pathname)444f17ea84bSSimon Schubert kld_find_and_open_solib (char *solib, unsigned o_flags, char **temp_pathname)
445f17ea84bSSimon Schubert {
446f17ea84bSSimon Schubert char path[PATH_MAX];
447f17ea84bSSimon Schubert int fd;
448f17ea84bSSimon Schubert
449f17ea84bSSimon Schubert *temp_pathname = NULL;
450f17ea84bSSimon Schubert if (!find_kld_path(solib, path, sizeof(path))) {
451f17ea84bSSimon Schubert errno = ENOENT;
452f17ea84bSSimon Schubert return (-1);
453f17ea84bSSimon Schubert }
454f17ea84bSSimon Schubert fd = open(path, o_flags, 0);
455f17ea84bSSimon Schubert if (fd >= 0)
456f17ea84bSSimon Schubert *temp_pathname = xstrdup(path);
457f17ea84bSSimon Schubert return (fd);
458f17ea84bSSimon Schubert }
459f17ea84bSSimon Schubert
460f17ea84bSSimon Schubert void
kld_new_objfile(struct objfile * objfile)461f17ea84bSSimon Schubert kld_new_objfile (struct objfile *objfile)
462f17ea84bSSimon Schubert {
463f17ea84bSSimon Schubert
464f17ea84bSSimon Schubert if (!have_partial_symbols())
465f17ea84bSSimon Schubert return;
466f17ea84bSSimon Schubert
467f17ea84bSSimon Schubert /*
468f17ea84bSSimon Schubert * Compute offsets of relevant members in struct linker_file
469f17ea84bSSimon Schubert * and the addresses of global variables. Don't warn about
470f17ea84bSSimon Schubert * kernels that don't have 'pathname' in the linker_file
471f17ea84bSSimon Schubert * struct since 6.x kernels don't have it.
472f17ea84bSSimon Schubert */
473f17ea84bSSimon Schubert off_address = kgdb_parse("&((struct linker_file *)0)->address");
474f17ea84bSSimon Schubert off_filename = kgdb_parse("&((struct linker_file *)0)->filename");
475f17ea84bSSimon Schubert off_pathname = kgdb_parse_quiet("&((struct linker_file *)0)->pathname");
476f17ea84bSSimon Schubert off_next = kgdb_parse("&((struct linker_file *)0)->link.tqe_next");
477f17ea84bSSimon Schubert module_path_addr = kgdb_parse("linker_path");
478f17ea84bSSimon Schubert linker_files_addr = kgdb_parse("&linker_files.tqh_first");
479f17ea84bSSimon Schubert kernel_file_addr = kgdb_parse("&linker_kernel_file");
480f17ea84bSSimon Schubert }
481f17ea84bSSimon Schubert
482f17ea84bSSimon Schubert static int
load_klds_stub(void * arg)483f17ea84bSSimon Schubert load_klds_stub (void *arg)
484f17ea84bSSimon Schubert {
485f17ea84bSSimon Schubert
486f17ea84bSSimon Schubert solib_add(NULL, 1, ¤t_target, auto_solib_add);
487f17ea84bSSimon Schubert return (0);
488f17ea84bSSimon Schubert }
489f17ea84bSSimon Schubert
490f17ea84bSSimon Schubert void
kld_init(struct gdbarch * kgdbarch)491c33252afSJohn Marino kld_init (struct gdbarch *kgdbarch)
492f17ea84bSSimon Schubert {
493f17ea84bSSimon Schubert /* XXX hack, needs to go into an abi init function */
494c33252afSJohn Marino set_solib_ops(kgdbarch, &kld_so_ops);
495f17ea84bSSimon Schubert
496f17ea84bSSimon Schubert kld_new_objfile(NULL);
497f17ea84bSSimon Schubert catch_errors(load_klds_stub, NULL, NULL, RETURN_MASK_ALL);
498f17ea84bSSimon Schubert observer_attach_new_objfile(kld_new_objfile);
499f17ea84bSSimon Schubert }
500f17ea84bSSimon Schubert
501f17ea84bSSimon Schubert void
initialize_kld_target(void)502f17ea84bSSimon Schubert initialize_kld_target(void)
503f17ea84bSSimon Schubert {
504f17ea84bSSimon Schubert struct cmd_list_element *c;
505f17ea84bSSimon Schubert
506f17ea84bSSimon Schubert kld_so_ops.relocate_section_addresses = kld_relocate_section_addresses;
507f17ea84bSSimon Schubert kld_so_ops.free_so = kld_free_so;
508f17ea84bSSimon Schubert kld_so_ops.clear_solib = kld_clear_solib;
509f17ea84bSSimon Schubert kld_so_ops.solib_create_inferior_hook = kld_solib_create_inferior_hook;
510f17ea84bSSimon Schubert kld_so_ops.special_symbol_handling = kld_special_symbol_handling;
511f17ea84bSSimon Schubert kld_so_ops.current_sos = kld_current_sos;
512f17ea84bSSimon Schubert kld_so_ops.open_symbol_file_object = kld_open_symbol_file_object;
513f17ea84bSSimon Schubert kld_so_ops.in_dynsym_resolve_code = kld_in_dynsym_resolve_code;
514f17ea84bSSimon Schubert kld_so_ops.find_and_open_solib = kld_find_and_open_solib;
515f17ea84bSSimon Schubert kld_so_ops.bfd_open = solib_bfd_open;
516f17ea84bSSimon Schubert
517f17ea84bSSimon Schubert c = add_com("add-kld", class_files, kgdb_add_kld_cmd,
518f17ea84bSSimon Schubert "Usage: add-kld FILE\n\
519f17ea84bSSimon Schubert Load the symbols from the kernel loadable module FILE.");
520f17ea84bSSimon Schubert set_cmd_completer(c, filename_completer);
521f17ea84bSSimon Schubert }
522