]> CyberLeo.Net >> Repos - FreeBSD/releng/8.1.git/blob - gnu/usr.bin/binutils/gdb/solib-fbsd-kld.c
Copy stable/8 to releng/8.1 in preparation for 8.1-RC1.
[FreeBSD/releng/8.1.git] / gnu / usr.bin / binutils / gdb / solib-fbsd-kld.c
1 /* Handle FreeBSD kernel modules as shared libraries.
2    Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000,
3    2001
4    Free Software Foundation, Inc.
5
6    This file is part of GDB.
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 2 of the License, or
11    (at your option) any later version.
12
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 59 Temple Place - Suite 330,
21    Boston, MA 02111-1307, USA.  */
22
23 /* $FreeBSD$ */
24
25 #include <sys/param.h>
26 #include <sys/queue.h>
27 #include <sys/stat.h>
28 #define _KERNEL
29 #include <sys/linker.h>
30 #undef _KERNEL
31
32 /* XXX, kludge to avoid duplicate definitions while sys/linker.h is used. */
33 #define _ELF_COMMON_H
34
35 #include "defs.h"
36 #include "symtab.h"
37 #include "bfd.h"
38 #include "symfile.h"
39 #include "objfiles.h"
40 #include "gdbcore.h"
41 #include "target.h"
42 #include "inferior.h"
43
44 #include "solist.h"
45
46 struct lm_info
47   {
48      CORE_ADDR address;
49   };
50
51 static int try_modpath (char *buf, int buflen, char *fmt, ...);
52 static char *guess_modpath (char *modname);
53
54 static void
55 kgdb_relocate_section_addresses (struct so_list *so,
56                                  struct section_table *sec)
57 {
58   sec->addr += so->lm_info->address;
59   sec->endaddr += so->lm_info->address;
60 }
61
62 static int
63 kgdb_open_symbol_file_object (void *from_ttyp)
64 {
65   warning ("kgdb_open_symbol_file_object called\n");
66   return 0;
67 }
68
69 static struct so_list *
70 kgdb_current_sos (void)
71 {
72   linker_file_list_t linker_files;
73   struct linker_file lfile;
74   struct minimal_symbol *msymbol;
75   struct linker_file *lfilek;
76   struct so_list *head = NULL;
77   struct so_list **link_ptr = &head;
78
79   CORE_ADDR lfiles_addr;
80
81   msymbol = lookup_minimal_symbol ("linker_files", NULL, symfile_objfile);
82   if (msymbol == NULL || SYMBOL_VALUE_ADDRESS (msymbol) == 0)
83     {
84       warning ("failed to find linker_files symbol\n");
85       return 0;
86     }
87   lfiles_addr = SYMBOL_VALUE_ADDRESS (msymbol);
88   if (target_read_memory (lfiles_addr, (char *)&linker_files,
89                           sizeof (linker_files)))
90     {
91       warning ("failed to read linker_files data\n");
92       return 0;
93     }
94   for (lfilek = TAILQ_FIRST (&linker_files); lfilek != NULL;
95        lfilek = TAILQ_NEXT (&lfile, link))
96    {
97       struct so_list *new;
98       struct cleanup *old_chain;
99       char *buf;
100       int errcode;
101
102       if (target_read_memory ((CORE_ADDR) lfilek, (char *) &lfile,
103           sizeof (lfile)))
104         {
105           warning ("failed to read linker file data at %p\n", lfilek);
106           return 0;
107         }
108       target_read_string ((CORE_ADDR) lfile.filename, &buf,
109                           SO_NAME_MAX_PATH_SIZE - 1, &errcode);
110       if (errcode != 0)
111         {
112           warning ("cannot read linker file pathname: %s\n",
113                    safe_strerror (errcode));
114           return 0;
115         }
116       if (strlen (buf) < 3 || strcmp (&buf[strlen (buf) - 3], ".ko") != 0)
117         {
118           xfree (buf);
119           continue;
120         }
121
122       new = (struct so_list *) xmalloc (sizeof (struct so_list));
123       old_chain = make_cleanup (xfree, new);
124
125       memset (new, 0, sizeof (*new));
126
127       new->lm_info = xmalloc (sizeof (struct lm_info));
128       make_cleanup (xfree, new->lm_info);
129
130       new->lm_info->address = (CORE_ADDR) lfile.address;
131
132       strncpy (new->so_original_name, buf, SO_NAME_MAX_PATH_SIZE - 1);
133       new->so_original_name[SO_NAME_MAX_PATH_SIZE - 1] = '\0';
134       xfree (buf);
135       snprintf (new->so_name, SO_NAME_MAX_PATH_SIZE, "%s",
136                 guess_modpath (new->so_original_name));
137
138       new->next = NULL;
139       *link_ptr = new;
140       link_ptr = &new->next;
141
142       discard_cleanups (old_chain);
143     }
144   return head;
145 }
146
147 static int
148 kgdb_in_dynsym_resolve_code (CORE_ADDR pc)
149 {
150   warning ("kgdb_in_dynsym_resolve_code called\n");
151   return 0;
152 }
153
154 static void
155 kgdb_special_symbol_handling (void)
156 {
157 }
158
159 static void
160 kgdb_solib_create_inferior_hook (void)
161 {
162   struct so_list *inferior_sos;
163
164   inferior_sos = kgdb_current_sos ();
165   if (inferior_sos)
166     {
167       solib_add (NULL, /*from_tty*/0, NULL, auto_solib_add);
168     }
169 }
170
171 static void
172 kgdb_clear_solib (void)
173 {
174 }
175
176 static void
177 kgdb_free_so (struct so_list *so)
178 {
179   xfree (so->lm_info);
180 }
181
182 static int
183 try_modpath (char *buf, int buflen, char *fmt, ...)
184 {
185   struct stat sb;
186   va_list ap;
187
188   va_start (ap, fmt);
189   vsnprintf (buf, buflen, fmt, ap);
190   va_end(ap);
191
192   return (stat (buf, &sb) == 0);
193 }
194
195 static char *
196 guess_modpath (char *modname)
197 {
198   static char buf[2048], moddir[128], syspath[1024];
199   struct minimal_symbol *msymbol;
200   char *kernpath, *objpath, *p, *version;
201   int errcode, n, syspathlen;
202
203   /* Set default module location */
204   snprintf (buf, sizeof (buf), "/boot/kernel/%s", modname);
205
206   /* Guess at the subdirectory off sys/modules. XXX, only sometimes correct */
207   n = strlen (modname);
208   if (n > 3 && strcmp (&modname[n - 3], ".ko") == 0)
209     n -= 3;
210   snprintf (moddir, sizeof (moddir), "%.*s", n, modname);
211
212   /* Try to locate the kernel compile location from version[] */
213   msymbol = lookup_minimal_symbol ("version", NULL, symfile_objfile);
214   if (msymbol == NULL || SYMBOL_VALUE_ADDRESS (msymbol) == 0)
215     {
216       warning("cannot find `version' symbol; using default module path\n");
217       return buf;
218     }
219   target_read_string (SYMBOL_VALUE_ADDRESS (msymbol), &version, 2048, &errcode);
220   if (errcode != 0)
221     {
222       warning ("cannot read `version' string; using default module path: %s\n",
223                safe_strerror (errcode));
224       return buf;
225     }
226
227   /* Find the kernel build path after user@host: on the second line. */
228   if ((p = strchr (version, '\n')) == NULL ||
229       (kernpath = strchr (p, ':')) == NULL ||
230       (p = strchr (kernpath, '\n')) == NULL)
231     {
232       warning ("cannot parse version[]; using default module path\n");
233       xfree (version);
234       return buf;
235     }
236   kernpath++;
237   *p = '\0';
238
239   /*
240    * Find the absolute path to src/sys by skipping back over path
241    * components until we find a "/sys/".
242    */
243   syspathlen = 0;
244   while (p > kernpath && syspathlen == 0)
245     {
246       while (p > kernpath && *p != '/')
247         p--;
248       if (strncmp (p, "/sys/", 5) == 0)
249         syspathlen = p - kernpath + 4;
250       else if (p > kernpath)
251         p--;
252     }
253   if (syspathlen == 0)
254     {
255       warning ("cannot find /sys/ in `%s'; using default module path\n",
256                kernpath);
257       xfree (version);
258       return buf;
259     }
260   /*
261    * For kernels compiled with buildkernel, the object path will have
262    * been prepended to the /sys/ path in `kernpath'.
263    */
264   objpath = getenv ("MAKEOBJDIRPREFIX");
265   if (objpath == NULL)
266     objpath = "/usr/obj";
267   n = strlen (objpath);
268   if (syspathlen > n + 1 && strncmp (kernpath, objpath, n) == 0 &&
269       kernpath[n] == '/')
270     snprintf (syspath, sizeof (syspath), "%.*s", syspathlen - n, kernpath + n);
271   else
272     snprintf (syspath, sizeof (syspath), "%.*s", syspathlen, kernpath);
273
274   /* Now try to find the module file */
275   if (!try_modpath (buf, sizeof (buf), "./%s.debug", modname) &&
276       !try_modpath (buf, sizeof (buf), "./%s", modname) && !try_modpath (buf,
277       sizeof (buf), "%s/modules%s/modules/%s/%s.debug", kernpath, syspath,
278       moddir, modname) && !try_modpath (buf, sizeof (buf),
279       "%s/modules%s/modules/%s/%s", kernpath, syspath, moddir, modname) &&
280       !try_modpath (buf, sizeof (buf), "/boot/kernel/%s.debug", modname) &&
281       !try_modpath (buf, sizeof (buf), "/boot/kernel/%s", modname))
282     {
283       warning ("cannot find file for module %s\n", modname);
284       snprintf (buf, sizeof (buf), "%s", modname);
285     }
286   xfree (version);
287
288   return buf;
289 }
290
291 struct target_so_ops kgdb_so_ops;
292
293 void
294 _initialize_kgdb_solib (void)
295 {
296   kgdb_so_ops.relocate_section_addresses = kgdb_relocate_section_addresses;
297   kgdb_so_ops.free_so = kgdb_free_so;
298   kgdb_so_ops.clear_solib = kgdb_clear_solib;
299   kgdb_so_ops.solib_create_inferior_hook = kgdb_solib_create_inferior_hook;
300   kgdb_so_ops.special_symbol_handling = kgdb_special_symbol_handling;
301   kgdb_so_ops.current_sos = kgdb_current_sos;
302   kgdb_so_ops.open_symbol_file_object = kgdb_open_symbol_file_object;
303   kgdb_so_ops.in_dynsym_resolve_code = kgdb_in_dynsym_resolve_code;
304 }