• R/O
  • HTTP
  • SSH
  • HTTPS

提交

標籤
無標籤

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

GNU Binutils with patches for OS216


Commit MetaInfo

修訂699e91f4e1d62b56ad9cce10c0220c7aae524ebb (tree)
時間2017-03-17 01:01:48
作者Philipp Rudo <prudo@linu...>
CommiterAndreas Arnez

Log Message

Add kernel module support for linux-kernel target

This patch implements module support for the new linux-kernel target by
adding a target_so_ops. In addition this patch adds handling for kernel
virtual addresses. This is necessary because kernel modules, unlike
task_structs, live in kernel virtual address space. Thus addresses need
to be translated before they can be read from. We achieve this by adding
an implementation for the targets to_xfer_partial hook, which translates
the addresses before passing them down to the target beneath.

gdb/ChangeLog:

    • lk-modules.h: New file.
    • lk-modules.c: New file.
    • lk-low.h (lk_hook_is_kvaddr, lk_hook_vtop)
      (lk_hook_get_module_text_offset): New arch dependent hooks.
      (sturct lk_private_hooks): Add new hooks.
      (LK_MODULES_NAME_LEN, LK_UTS_NAME_LEN): New define.
    • lk-low.c (lk-modules.h): New include.
      (lk_kvtop, restore_current_target, lk_xfer_partial): New functions.
      (lk_init_private_data): Declare needed debug symbols.
      (lk_try_push_target): Assert for new hooks and set solib_ops.
      (init_linux_kernel_ops): Add implementation for to_xfer_partial.
    • solib.c (get_solib_search_path): New function.
    • solib.h (get_solib_search_path): New export.
    • Makefile.in (SFILES, ALLDEPFILES): Add lk-modules.c.
      (HFILES_NO_SRCDIR): Add lk-modules.h.
      (ALL_TARGET_OBS): Add lk-modules.o.
    • configure.tgt (lk_target_obs): Add lk-modules.o.

Change Summary

差異

--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -819,6 +819,7 @@ ALL_TARGET_OBS = \
819819 linux-tdep.o \
820820 lk-lists.o \
821821 lk-low.o \
822+ lk-modules.o \
822823 lm32-tdep.o \
823824 m32c-tdep.o \
824825 m32r-linux-tdep.o \
@@ -1107,6 +1108,7 @@ SFILES = \
11071108 linespec.c \
11081109 lk-lists.c \
11091110 lk-low.c \
1111+ lk-modules.c \
11101112 location.c \
11111113 m2-exp.y \
11121114 m2-lang.c \
@@ -1356,6 +1358,7 @@ HFILES_NO_SRCDIR = \
13561358 linux-tdep.h \
13571359 lk-lists.h \
13581360 lk-low.h \
1361+ lk-modules.h \
13591362 location.h \
13601363 m2-lang.h \
13611364 m32r-tdep.h \
@@ -2555,6 +2558,7 @@ ALLDEPFILES = \
25552558 linux-tdep.c \
25562559 lk-lists.c \
25572560 lk-low.c \
2561+ lk-modules.c \
25582562 lm32-tdep.c \
25592563 m32r-linux-nat.c \
25602564 m32r-linux-tdep.c \
--- a/gdb/configure.tgt
+++ b/gdb/configure.tgt
@@ -36,7 +36,7 @@ esac
3636
3737 # List of objectfiles for Linux kernel support. To be included into *-linux*
3838 # targets wich support Linux kernel debugging.
39-lk_target_obs="lk-lists.o lk-low.o"
39+lk_target_obs="lk-lists.o lk-low.o lk-modules.o"
4040
4141 # map target info into gdb names.
4242
--- a/gdb/lk-low.c
+++ b/gdb/lk-low.c
@@ -29,6 +29,7 @@
2929 #include "inferior.h"
3030 #include "lk-lists.h"
3131 #include "lk-low.h"
32+#include "lk-modules.h"
3233 #include "objfiles.h"
3334 #include "observer.h"
3435 #include "solib.h"
@@ -536,6 +537,46 @@ lk_thread_name (struct target_ops *target, struct thread_info *ti)
536537 return buf;
537538 }
538539
540+/* Translate a kernel virtual address ADDR to a physical address. */
541+
542+CORE_ADDR
543+lk_kvtop (CORE_ADDR addr)
544+{
545+ CORE_ADDR pgd = lk_read_addr (LK_ADDR (init_mm)
546+ + LK_OFFSET (mm_struct, pgd));
547+ return LK_HOOK->vtop (pgd, addr);
548+}
549+
550+/* Restore current_target to TARGET. */
551+static void
552+restore_current_target (void *target)
553+{
554+ current_target.beneath = (struct target_ops *) target;
555+}
556+
557+/* Function for targets to_xfer_partial hook. */
558+
559+enum target_xfer_status
560+lk_xfer_partial (struct target_ops *ops, enum target_object object,
561+ const char *annex, gdb_byte *readbuf,
562+ const gdb_byte *writebuf, ULONGEST offset, ULONGEST len,
563+ ULONGEST *xfered_len)
564+{
565+ enum target_xfer_status ret_val;
566+ struct cleanup *old_chain = make_cleanup (restore_current_target, ops);
567+
568+ current_target.beneath = ops->beneath;
569+
570+ if (LK_HOOK->is_kvaddr (offset))
571+ offset = lk_kvtop (offset);
572+
573+ ret_val = ops->beneath->to_xfer_partial (ops->beneath, object, annex,
574+ readbuf, writebuf, offset, len,
575+ xfered_len);
576+ do_cleanups (old_chain);
577+ return ret_val;
578+}
579+
539580 /* Functions to initialize and free target_ops and its private data. As well
540581 as functions for targets to_open/close/detach hooks. */
541582
@@ -571,6 +612,9 @@ lk_init_private ()
571612 /* Initialize architecture independent private data. Must be called
572613 _after_ symbol tables were initialized. */
573614
615+/* FIXME: throw error more fine-grained. */
616+/* FIXME: make independent of compile options. */
617+
574618 static void
575619 lk_init_private_data ()
576620 {
@@ -591,10 +635,61 @@ lk_init_private_data ()
591635
592636 LK_DECLARE_FIELD (cpumask, bits);
593637
638+ LK_DECLARE_FIELD (mm_struct, pgd);
639+
640+ LK_DECLARE_FIELD (pgd_t, pgd);
641+
642+ LK_DECLARE_FIELD (module, list);
643+ LK_DECLARE_FIELD (module, name);
644+ LK_DECLARE_FIELD (module, source_list);
645+ LK_DECLARE_FIELD (module, arch);
646+ LK_DECLARE_FIELD (module, init);
647+ LK_DECLARE_FIELD (module, percpu);
648+ LK_DECLARE_FIELD (module, percpu_size);
649+
650+ /* Module offset moved to new struct module_layout with linux 4.5.
651+ It must be checked in code which of this fields exist. */
652+ if (LK_DECLARE_FIELD_SILENT (module_layout, base)) /* linux 4.5+ */
653+ {
654+ LK_DECLARE_FIELD (module, init_layout);
655+ LK_DECLARE_FIELD (module, core_layout);
656+
657+ LK_DECLARE_FIELD (module_layout, size);
658+ LK_DECLARE_FIELD (module_layout, text_size);
659+ LK_DECLARE_FIELD (module_layout, ro_size);
660+ }
661+ else if (LK_DECLARE_FIELD_SILENT (module, module_core)) /* linux -4.4 */
662+ {
663+ LK_DECLARE_FIELD (module, init_size);
664+ LK_DECLARE_FIELD (module, core_size);
665+
666+ LK_DECLARE_FIELD (module, core_text_size);
667+ LK_DECLARE_FIELD (module, core_ro_size);
668+ }
669+ else
670+ {
671+ error (_("Could not find module base. Aborting."));
672+ }
673+
674+ LK_DECLARE_FIELD (module_use, source_list);
675+ LK_DECLARE_FIELD (module_use, source);
676+
677+ LK_DECLARE_FIELD (uts_namespace, name);
678+
679+ LK_DECLARE_STRUCT_ALIAS (new_utsname, utsname);
680+ LK_DECLARE_STRUCT_ALIAS (old_utsname, utsname);
681+ LK_DECLARE_STRUCT_ALIAS (oldold_utsname, utsname);
682+ if (LK_STRUCT (utsname) == NULL)
683+ error (_("Could not find struct utsname. Aborting."));
684+ LK_DECLARE_FIELD (utsname, version);
685+ LK_DECLARE_FIELD (utsname, release);
686+
594687 LK_DECLARE_ADDR (init_task);
595688 LK_DECLARE_ADDR (runqueues);
596689 LK_DECLARE_ADDR (__per_cpu_offset);
597690 LK_DECLARE_ADDR (init_mm);
691+ LK_DECLARE_ADDR (modules);
692+ LK_DECLARE_ADDR (init_uts_ns);
598693
599694 LK_DECLARE_ADDR_ALIAS (__cpu_online_mask, cpu_online_mask); /* linux 4.5+ */
600695 LK_DECLARE_ADDR_ALIAS (cpu_online_bits, cpu_online_mask); /* linux -4.4 */
@@ -693,12 +788,17 @@ lk_try_push_target ()
693788 gdbarch_lk_init_private (gdbarch);
694789 /* Check for required arch hooks. */
695790 gdb_assert (LK_HOOK->get_registers);
791+ gdb_assert (LK_HOOK->is_kvaddr);
792+ gdb_assert (LK_HOOK->vtop);
793+ gdb_assert (LK_HOOK->get_module_text_offset);
696794
697795 lk_init_ptid_map ();
698796 lk_update_thread_list (linux_kernel_ops);
699797
700798 if (!target_is_pushed (linux_kernel_ops))
701799 push_target (linux_kernel_ops);
800+
801+ set_solib_ops (gdbarch, lk_modules_so_ops);
702802 }
703803
704804 /* Function for targets to_open hook. */
@@ -811,6 +911,7 @@ init_linux_kernel_ops (void)
811911 t->to_update_thread_list = lk_update_thread_list;
812912 t->to_pid_to_str = lk_pid_to_str;
813913 t->to_thread_name = lk_thread_name;
914+ t->to_xfer_partial = lk_xfer_partial;
814915
815916 t->to_stratum = thread_stratum;
816917 t->to_magic = OPS_MAGIC;
--- a/gdb/lk-low.h
+++ b/gdb/lk-low.h
@@ -27,6 +27,8 @@ extern struct target_ops *linux_kernel_ops;
2727 /* Copy constants defined in Linux kernel. */
2828 #define LK_TASK_COMM_LEN 16
2929 #define LK_BITS_PER_BYTE 8
30+#define LK_MODULE_NAME_LEN 56
31+#define LK_UTS_NAME_LEN 64
3032
3133 /* Definitions used in linux kernel target. */
3234 #define LK_CPU_INVAL -1U
@@ -204,6 +206,19 @@ typedef void (*lk_hook_get_registers) (CORE_ADDR task,
204206 struct regcache *regcache,
205207 int regnum);
206208
209+/* Hook to check if address ADDR is a kernel virtual address.
210+ NOTE: This hook is called in the context of target beneath. */
211+typedef int (*lk_hook_is_kvaddr) (CORE_ADDR addr);
212+
213+/* Hook to translate virtual adress ADDR to a pysical address using page
214+ table located at PGD.
215+ NOTE: This hook is called in the context of target beneath. */
216+typedef CORE_ADDR (*lk_hook_vtop) (CORE_ADDR addr, CORE_ADDR pgd);
217+
218+/* Hook to get the offset between a modules base and the start of its
219+ .text section. */
220+typedef CORE_ADDR (*lk_hook_get_module_text_offset) (CORE_ADDR mod);
221+
207222 /* Hook to return the per_cpu_offset of cpu CPU. Only architectures that
208223 do not use the __per_cpu_offset array to determin the offset have to
209224 supply this hook. */
@@ -218,6 +233,15 @@ struct lk_private_hooks
218233 /* required */
219234 lk_hook_get_registers get_registers;
220235
236+ /* required */
237+ lk_hook_is_kvaddr is_kvaddr;
238+
239+ /* required */
240+ lk_hook_vtop vtop;
241+
242+ /* reqired */
243+ lk_hook_get_module_text_offset get_module_text_offset;
244+
221245 /* optional, required if __per_cpu_offset array is not used to determine
222246 offset. */
223247 lk_hook_get_percpu_offset get_percpu_offset;
--- /dev/null
+++ b/gdb/lk-modules.c
@@ -0,0 +1,412 @@
1+/* Handle Linux kernel modules as shared libraries.
2+
3+ Copyright (C) 2016 Free Software Foundation, Inc.
4+
5+ This file is part of GDB.
6+
7+ This program is free software; you can redistribute it and/or modify
8+ it under the terms of the GNU General Public License as published by
9+ the Free Software Foundation; either version 3 of the License, or
10+ (at your option) any later version.
11+
12+ This program is distributed in the hope that it will be useful,
13+ but WITHOUT ANY WARRANTY; without even the implied warranty of
14+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+ GNU General Public License for more details.
16+
17+ You should have received a copy of the GNU General Public License
18+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
19+
20+#include "defs.h"
21+
22+#include "common/filestuff.h"
23+#include "filenames.h"
24+#include "gdbcmd.h"
25+#include "gdbcore.h"
26+#include "gdb_regex.h"
27+#include "lk-lists.h"
28+#include "lk-low.h"
29+#include "lk-modules.h"
30+#include "objfiles.h"
31+#include "observer.h"
32+#include "readline/readline.h"
33+#include "solib.h"
34+#include "solist.h"
35+#include "utils.h"
36+
37+#include <unordered_map>
38+#include <string>
39+
40+struct target_so_ops *lk_modules_so_ops = NULL;
41+
42+/* Info for single section type. */
43+
44+struct lm_info_sec
45+{
46+ CORE_ADDR start;
47+ CORE_ADDR offset;
48+ unsigned int size;
49+};
50+
51+/* Link map info to include in an allocated so_list entry. */
52+
53+struct lm_info
54+{
55+ CORE_ADDR base;
56+ unsigned int size;
57+
58+ struct lm_info_sec text;
59+ struct lm_info_sec init_text;
60+ struct lm_info_sec ro_data;
61+ struct lm_info_sec rw_data;
62+ struct lm_info_sec percpu;
63+};
64+
65+/* Check if debug info for module NAME are loaded. */
66+
67+bool
68+lk_modules_debug_info_loaded (const std::string &name)
69+{
70+ struct so_list *so;
71+
72+ for (so = master_so_list (); so; so = so->next)
73+ {
74+ if (name == so->so_original_name)
75+ return (so->symbols_loaded && objfile_has_symbols (so->objfile));
76+ }
77+
78+ return false;
79+}
80+
81+/* Replace tags, like '$release', with corresponding data in
82+ solib_search_path.
83+
84+ Known tags:
85+ $release Linux kernel release, same as 'uname -r'
86+
87+ Returns the expanded path. */
88+
89+static std::string
90+lk_modules_expand_search_path ()
91+{
92+ char release[LK_UTS_NAME_LEN + 1];
93+ CORE_ADDR utsname;
94+
95+ utsname = LK_ADDR (init_uts_ns) + LK_OFFSET (uts_namespace, name);
96+ read_memory_string (utsname + LK_OFFSET (utsname, release),
97+ release, LK_UTS_NAME_LEN);
98+ release[LK_UTS_NAME_LEN] = '\0';
99+
100+ std::string search_path = get_solib_search_path ();
101+ substitute_path_component (search_path, "$release", release);
102+
103+ return search_path;
104+}
105+
106+/* With kernel modules there is the problem that the kernel only stores
107+ the modules name but not the path from wich it was loaded from.
108+ Thus we need to map the name to a path GDB can read from. We use file
109+ modules.order to do so. It is created by kbuild containing the order in
110+ which the modules appear in the Makefile and is also used by modprobe.
111+ The drawback of this method is that it needs the modules.order file and
112+ all relative paths, starting from <solib-search-path>, must be exactly the
113+ same as decribed in it. */
114+
115+/* Open file <solib-search-path>/modules.order and return its file
116+ pointer. */
117+
118+FILE *
119+lk_modules_open_mod_order ()
120+{
121+ FILE *mod_order;
122+ std::string filename = concat_path (lk_modules_expand_search_path (),
123+ "modules.order");
124+ mod_order = gdb_fopen_cloexec (filename.c_str (), "r");
125+
126+ if (!mod_order)
127+ {
128+ error (_("\
129+Can not find file module.order at %s \
130+to load module symbol files.\n\
131+Please check if solib-search-path is set correctly."),
132+ filename.c_str ());
133+ }
134+
135+ return mod_order;
136+}
137+
138+/* Build map between module name and path to binary file by reading file
139+ modules.order. Returns unordered_map with module name as key and its
140+ path as value. */
141+
142+std::unordered_map<std::string, std::string>
143+lk_modules_build_path_map ()
144+{
145+ std::unordered_map<std::string, std::string> umap;
146+ FILE *mod_order;
147+ struct cleanup *old_chain;
148+ char line[SO_NAME_MAX_PATH_SIZE + 1];
149+
150+ mod_order = lk_modules_open_mod_order ();
151+ old_chain = make_cleanup_fclose (mod_order);
152+
153+ line[SO_NAME_MAX_PATH_SIZE] = '\0';
154+ std::string search_path = lk_modules_expand_search_path ();
155+ while (fgets (line, SO_NAME_MAX_PATH_SIZE, mod_order))
156+ {
157+ /* Remove trailing newline. */
158+ line[strlen (line) - 1] = '\0';
159+
160+ std::string name = lbasename (line);
161+
162+ /* 3 = strlen (".ko"). */
163+ if (!endswith (name.c_str (), ".ko")
164+ || name.length () >= LK_MODULE_NAME_LEN + 3)
165+ continue;
166+
167+ name = name.substr (0, name.length () - 3);
168+
169+ /* Kernel modules are named after the files they are stored in with
170+ all minus '-' replaced by underscore '_'. Do the same to enable
171+ mapping. */
172+ for (size_t p = name.find('-'); p != std::string::npos;
173+ p = name.find ('-', p + 1))
174+ name[p] = '_';
175+
176+ umap[name] = concat_path(search_path, line);
177+ }
178+
179+ do_cleanups (old_chain);
180+ return umap;
181+}
182+
183+/* Allocate and fill a copy of struct lm_info for module at address MOD. */
184+
185+struct lm_info *
186+lk_modules_read_lm_info (CORE_ADDR mod)
187+{
188+ struct lm_info *lmi = XNEW (struct lm_info);
189+ struct cleanup *old_chain = make_cleanup (xfree, lmi);
190+
191+ if (LK_FIELD (module, module_core)) /* linux -4.4 */
192+ {
193+ lmi->base = lk_read_addr (mod + LK_OFFSET (module, module_core));
194+ lmi->size = lk_read_addr (mod + LK_OFFSET (module, core_size));
195+
196+ lmi->text.start = lmi->base;
197+ lmi->text.offset = LK_HOOK->get_module_text_offset (mod);
198+ lmi->text.size = lk_read_uint (mod + LK_OFFSET (module, core_text_size));
199+
200+ lmi->ro_data.start = lmi->base + lmi->text.size;
201+ lmi->ro_data.offset = 0;
202+ lmi->ro_data.size = lk_read_uint (mod + LK_OFFSET (module,
203+ core_ro_size));
204+ }
205+ else /* linux 4.5+ */
206+ {
207+ CORE_ADDR mod_core = mod + LK_OFFSET (module, core_layout);
208+
209+ lmi->base = lk_read_addr (mod_core
210+ + LK_OFFSET (module_layout, base));
211+ lmi->size = lk_read_uint (mod_core
212+ + LK_OFFSET (module_layout, size));
213+
214+ lmi->text.start = lmi->base;
215+ lmi->text.offset = LK_HOOK->get_module_text_offset (mod);
216+ lmi->text.size = lk_read_uint (mod_core
217+ + LK_OFFSET (module_layout, text_size));
218+
219+ lmi->ro_data.start = lmi->base + lmi->text.size;
220+ lmi->ro_data.offset = 0;
221+ lmi->ro_data.size = lk_read_uint (mod_core
222+ + LK_OFFSET (module_layout, ro_size));
223+ }
224+
225+ lmi->rw_data.start = lmi->base + lmi->ro_data.size;
226+ lmi->rw_data.offset = 0;
227+ lmi->rw_data.size = lmi->size - lmi->ro_data.size;
228+
229+ lmi->init_text.start = lk_read_addr (mod + LK_OFFSET (module, init));
230+ lmi->init_text.offset = 0;
231+
232+ lmi->percpu.start = lk_read_addr (mod + LK_OFFSET (module, percpu));
233+ lmi->percpu.size = lk_read_uint (mod + LK_OFFSET (module, percpu_size));
234+ lmi->percpu.offset = 0;
235+
236+ discard_cleanups (old_chain);
237+ return lmi;
238+}
239+
240+/* Function for current_sos hook. */
241+
242+struct so_list *
243+lk_modules_current_sos (void)
244+{
245+ CORE_ADDR modules, next;
246+ FILE *mod_order;
247+ struct so_list *list = NULL;
248+ std::unordered_map<std::string, std::string> umap;
249+
250+ umap = lk_modules_build_path_map ();
251+ modules = LK_ADDR (modules);
252+ lk_list_for_each (next, modules, module, list)
253+ {
254+ char name[LK_MODULE_NAME_LEN];
255+ CORE_ADDR mod, name_addr;
256+
257+ mod = LK_CONTAINER_OF (next, module, list);
258+ name_addr = mod + LK_OFFSET (module, name);
259+ read_memory_string (name_addr, name, LK_MODULE_NAME_LEN);
260+
261+ if (umap.count (name))
262+ {
263+ struct so_list *newso = XCNEW (struct so_list);
264+
265+ newso->next = list;
266+ list = newso;
267+ newso->lm_info = lk_modules_read_lm_info (mod);
268+ strncpy (newso->so_original_name, name, SO_NAME_MAX_PATH_SIZE);
269+ strncpy (newso->so_name, umap[name].c_str (), SO_NAME_MAX_PATH_SIZE);
270+ newso->pspace = current_program_space;
271+ }
272+ }
273+
274+ return list;
275+}
276+
277+/* Relocate target_section SEC to section type LMI_SEC. Helper function for
278+ lk_modules_relocate_section_addresses. */
279+
280+void
281+lk_modules_relocate_sec (struct target_section *sec,
282+ struct lm_info_sec *lmi_sec)
283+{
284+ unsigned int alignment = 1;
285+
286+ alignment = 1 << sec->the_bfd_section->alignment_power;
287+
288+ /* Adjust offset to section alignment. */
289+ if (lmi_sec->offset % alignment != 0)
290+ lmi_sec->offset += alignment - (lmi_sec->offset % alignment);
291+
292+ sec->addr += lmi_sec->start + lmi_sec->offset;
293+ sec->endaddr += lmi_sec->start + lmi_sec->offset;
294+ lmi_sec->offset += sec->endaddr - sec->addr;
295+}
296+
297+/* Function for relocate_section_addresses hook. */
298+
299+void
300+lk_modules_relocate_section_addresses (struct so_list *so,
301+ struct target_section *sec)
302+{
303+ struct lm_info *lmi = so->lm_info;
304+ unsigned int flags = sec->the_bfd_section->flags;
305+ const char *name = sec->the_bfd_section->name;
306+
307+ if (streq (name, ".modinfo") || streq (name, "__versions"))
308+ return;
309+
310+ /* FIXME: Make dependent on module state, i.e. only map .init sections if
311+ * state is MODULE_STATE_COMING. */
312+ if (startswith (name, ".init"))
313+ lk_modules_relocate_sec (sec, &lmi->init_text);
314+ else if (endswith (name, ".percpu"))
315+ lk_modules_relocate_sec (sec, &lmi->percpu);
316+ else if (flags & SEC_CODE)
317+ lk_modules_relocate_sec (sec, &lmi->text);
318+ else if (flags & SEC_READONLY)
319+ lk_modules_relocate_sec (sec, &lmi->ro_data);
320+ else if (flags & SEC_ALLOC)
321+ lk_modules_relocate_sec (sec, &lmi->rw_data);
322+
323+ /* Set address range to be displayed with info shared.
324+ size = text + (ro + rw) data without .init sections. */
325+ if (so->addr_low == so->addr_high)
326+ {
327+ so->addr_low = lmi->base;
328+ so->addr_high = lmi->base + lmi->size;
329+ }
330+}
331+
332+/* Function for free_so hook. */
333+
334+void
335+lk_modules_free_so (struct so_list *so)
336+{
337+ xfree (so->lm_info);
338+}
339+
340+/* Function for clear_so hook. */
341+
342+void
343+lk_modules_clear_so (struct so_list *so)
344+{
345+ if (so->lm_info != NULL)
346+ memset (so->lm_info, 0, sizeof (struct lm_info));
347+}
348+
349+/* Function for clear_solib hook. */
350+
351+void
352+lk_modules_clear_solib ()
353+{
354+ /* Nothing to do. */
355+}
356+
357+/* Function for clear_create_inferior_hook hook. */
358+
359+void
360+lk_modules_create_inferior_hook (int from_tty)
361+{
362+ /* Nothing to do. */
363+}
364+
365+/* Function for clear_create_inferior_hook hook. */
366+
367+int
368+lk_modules_in_dynsym_resolve_code (CORE_ADDR pc)
369+{
370+ return 0;
371+}
372+
373+/* Function for same hook. */
374+
375+int
376+lk_modules_same (struct so_list *gdb, struct so_list *inf)
377+{
378+ return streq (gdb->so_name, inf->so_name);
379+}
380+
381+/* Initialize linux modules solib target. */
382+
383+void
384+init_lk_modules_so_ops (void)
385+{
386+ struct target_so_ops *t;
387+
388+ if (lk_modules_so_ops != NULL)
389+ return;
390+
391+ t = XCNEW (struct target_so_ops);
392+ t->relocate_section_addresses = lk_modules_relocate_section_addresses;
393+ t->free_so = lk_modules_free_so;
394+ t->clear_so = lk_modules_clear_so;
395+ t->clear_solib = lk_modules_clear_solib;
396+ t->solib_create_inferior_hook = lk_modules_create_inferior_hook;
397+ t->current_sos = lk_modules_current_sos;
398+ t->bfd_open = solib_bfd_open;
399+ t->in_dynsym_resolve_code = lk_modules_in_dynsym_resolve_code;
400+ t->same = lk_modules_same;
401+
402+ lk_modules_so_ops = t;
403+}
404+
405+/* Provide a prototype to silence -Wmissing-prototypes. */
406+extern initialize_file_ftype _initialize_lk_modules;
407+
408+void
409+_initialize_lk_modules (void)
410+{
411+ init_lk_modules_so_ops ();
412+}
--- /dev/null
+++ b/gdb/lk-modules.h
@@ -0,0 +1,29 @@
1+/* Handle kernel modules as shared libraries.
2+
3+ Copyright (C) 2016 Free Software Foundation, Inc.
4+
5+ This file is part of GDB.
6+
7+ This program is free software; you can redistribute it and/or modify
8+ it under the terms of the GNU General Public License as published by
9+ the Free Software Foundation; either version 3 of the License, or
10+ (at your option) any later version.
11+
12+ This program is distributed in the hope that it will be useful,
13+ but WITHOUT ANY WARRANTY; without even the implied warranty of
14+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+ GNU General Public License for more details.
16+
17+ You should have received a copy of the GNU General Public License
18+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
19+
20+#ifndef __LK_MODULES_H__
21+#define __LK_MODULES_H__
22+
23+extern struct target_so_ops *lk_modules_so_ops;
24+
25+/* Check if debug info for module NAME are loaded. Needed by lsmod command. */
26+
27+extern bool lk_modules_debug_info_loaded (const std::string &name);
28+
29+#endif /* __LK_MODULES_H__ */
--- a/gdb/solib.c
+++ b/gdb/solib.c
@@ -107,6 +107,14 @@ show_solib_search_path (struct ui_file *file, int from_tty,
107107 value);
108108 }
109109
110+/* see solib.h. */
111+
112+const char *
113+get_solib_search_path ()
114+{
115+ return solib_search_path ? solib_search_path : "";
116+}
117+
110118 /* Same as HAVE_DOS_BASED_FILE_SYSTEM, but useable as an rvalue. */
111119 #if (HAVE_DOS_BASED_FILE_SYSTEM)
112120 # define DOS_BASED_FILE_SYSTEM 1
--- a/gdb/solib.h
+++ b/gdb/solib.h
@@ -28,6 +28,11 @@ struct program_space;
2828
2929 #include "symfile-add-flags.h"
3030
31+/* Returns the solib_search_path. The returned string is malloc'ed and must be
32+ freed by the caller. */
33+
34+extern const char *get_solib_search_path ();
35+
3136 /* Called when we free all symtabs, to free the shared library information
3237 as well. */
3338