1 /* Copyright (C) 2008 Anders Kaseorg <andersk@mit.edu>,
2 * Tim Abbott <tabbott@mit.edu>,
3 * Jeffrey Brian Arnold <jbarnold@mit.edu>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License, version 2.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
19 /* Always define KSPLICE_STANDALONE, even if you're using integrated Ksplice.
20 inspect won't compile without it. */
21 #define KSPLICE_STANDALONE
24 #include "objcommon.h"
25 #include "kmodsrc/ksplice.h"
28 char *str_pointer(struct supersect
*ss
, void *const *addr
);
30 struct kreloc_section
{
32 const struct ksplice_reloc
*reloc
;
35 #define kreloc_section_init(ks) *(ks) = NULL
36 DEFINE_HASH_TYPE(struct kreloc_section
*, kreloc_section_hash
,
37 kreloc_section_hash_init
, kreloc_section_hash_free
,
38 kreloc_section_hash_lookup
, kreloc_section_init
);
39 struct kreloc_section_hash ksplice_relocs
;
41 char *str_ulong_vec(struct supersect
*ss
, const unsigned long *const *datap
,
42 const unsigned long *sizep
)
44 struct supersect
*data_ss
;
45 const unsigned long *data
=
46 read_pointer(ss
, (void *const *)datap
, &data_ss
);
47 unsigned long size
= read_num(ss
, sizep
);
51 FILE *fp
= open_memstream(&buf
, &bufsize
);
54 for (i
= 0; i
< size
; ++i
)
55 fprintf(fp
, "%lx ", read_num(data_ss
, &data
[i
]));
61 static const struct ksplice_reloc
*
62 find_ksplice_reloc(struct supersect
*ss
, void *const *addr
,
63 struct supersect
**reloc_ss
)
65 char *key
= strprintf("%p", addr
);
66 struct kreloc_section
**ksp
=
67 kreloc_section_hash_lookup(&ksplice_relocs
, key
, FALSE
);
71 *reloc_ss
= (*ksp
)->ss
;
75 char *str_ksplice_symbol(struct supersect
*ss
,
76 const struct ksplice_symbol
*ksymbol
)
78 return strprintf("%s (%s)",
79 read_string(ss
, &ksymbol
->label
),
80 read_string(ss
, &ksymbol
->name
));
83 char *str_ksplice_symbolp(struct supersect
*ptr_ss
,
84 struct ksplice_symbol
*const *ksymbolp
)
87 bfd_vma offset
= read_reloc(ptr_ss
, ksymbolp
, sizeof(*ksymbolp
), &sym
);
88 if (bfd_is_const_section(sym
->section
))
89 return strprintf("*(%s)",
90 str_pointer(ptr_ss
, (void *const *)ksymbolp
));
91 struct supersect
*ksymbol_ss
= fetch_supersect(ptr_ss
->parent
,
93 return str_ksplice_symbol(ksymbol_ss
, ksymbol_ss
->contents
.data
+
97 char *str_pointer(struct supersect
*ss
, void *const *addr
)
100 struct supersect
*kreloc_ss
;
101 const struct ksplice_reloc
*kreloc
=
102 find_ksplice_reloc(ss
, addr
, &kreloc_ss
);
103 if (kreloc
== NULL
) {
104 bfd_vma offset
= read_reloc(ss
, addr
, sizeof(*addr
), &sym
);
105 return strprintf("%s+%lx", sym
->name
, (unsigned long)offset
);
107 return strprintf("[%s]+%lx",
108 str_ksplice_symbolp(kreloc_ss
,
110 kreloc
->target_addend
);
114 static const char *str_howto_type(const struct ksplice_reloc_howto
*howto
)
116 switch (howto
->type
) {
117 case KSPLICE_HOWTO_RELOC
:
119 case KSPLICE_HOWTO_RELOC_PATCH
:
120 return "reloc(patch)";
121 case KSPLICE_HOWTO_TIME
:
123 case KSPLICE_HOWTO_DATE
:
125 case KSPLICE_HOWTO_BUG
:
127 case KSPLICE_HOWTO_EXTABLE
:
134 void show_ksplice_reloc(struct supersect
*ss
,
135 const struct ksplice_reloc
*kreloc
)
137 struct supersect
*khowto_ss
;
138 const struct ksplice_reloc_howto
*khowto
=
139 read_pointer(ss
, (void *const *)&kreloc
->howto
, &khowto_ss
);
140 printf(" blank_addr: %s size: %x\n"
143 " insn_addend: %lx\n"
144 " target_addend: %lx\n"
145 " pcrel: %x dst_mask: %lx rightshift: %x signed_addend: %x\n"
147 str_pointer(ss
, (void *const *)&kreloc
->blank_addr
),
148 read_num(khowto_ss
, &khowto
->size
),
149 str_howto_type(khowto
),
150 str_ksplice_symbolp(ss
, &kreloc
->symbol
),
151 read_num(ss
, &kreloc
->insn_addend
),
152 read_num(ss
, &kreloc
->target_addend
),
153 read_num(khowto_ss
, &khowto
->pcrel
),
154 read_num(khowto_ss
, &khowto
->dst_mask
),
155 read_num(khowto_ss
, &khowto
->rightshift
),
156 read_num(khowto_ss
, &khowto
->signed_addend
));
159 void show_ksplice_relocs(struct supersect
*kreloc_ss
)
161 const struct ksplice_reloc
*kreloc
;
162 for (kreloc
= kreloc_ss
->contents
.data
; (void *)kreloc
<
163 kreloc_ss
->contents
.data
+ kreloc_ss
->contents
.size
; kreloc
++)
164 show_ksplice_reloc(kreloc_ss
, kreloc
);
167 void show_ksplice_section_flags(const struct ksplice_section
*ksect
)
170 if (ksect
->flags
& KSPLICE_SECTION_RODATA
)
172 if (ksect
->flags
& KSPLICE_SECTION_TEXT
)
174 if (ksect
->flags
& KSPLICE_SECTION_DATA
)
179 void show_ksplice_section(struct supersect
*ss
,
180 const struct ksplice_section
*ksect
)
182 printf(" symbol: %s\n"
183 " address: %s size: %lx\n",
184 str_ksplice_symbolp(ss
, &ksect
->symbol
),
185 str_pointer(ss
, (void *const *)&ksect
->address
),
186 read_num(ss
, &ksect
->size
));
187 show_ksplice_section_flags(ksect
);
191 void show_ksplice_sections(struct supersect
*ksect_ss
)
193 struct ksplice_section
*ksect
;
194 for (ksect
= ksect_ss
->contents
.data
; (void *)ksect
<
195 ksect_ss
->contents
.data
+ ksect_ss
->contents
.size
; ksect
++)
196 show_ksplice_section(ksect_ss
, ksect
);
199 const char *str_ksplice_patch_type(struct supersect
*ss
,
200 const struct ksplice_patch
*kpatch
)
202 const unsigned short *line
;
203 const char *const *strp
;
204 struct supersect
*data_ss
;
205 switch(kpatch
->type
) {
206 case KSPLICE_PATCH_TEXT
:
207 return strprintf("text\n repladdr: %s", str_pointer
208 (ss
, (void *const *)&kpatch
->repladdr
));
209 case KSPLICE_PATCH_BUGLINE
:
210 line
= read_pointer(ss
, &kpatch
->contents
, NULL
);
211 return strprintf("bugline\n line: %hx", *line
);
212 case KSPLICE_PATCH_DATA
:
213 return strprintf("data\n size: %x", kpatch
->size
);
214 case KSPLICE_PATCH_EXPORT
:
215 strp
= read_pointer(ss
, &kpatch
->contents
, &data_ss
);
216 return strprintf("export\n newname: %s",
217 read_string(data_ss
, strp
));
223 void show_ksplice_patch(struct supersect
*ss
,
224 const struct ksplice_patch
*kpatch
)
228 str_ksplice_patch_type(ss
, kpatch
),
229 str_pointer(ss
, (void *const *)&kpatch
->oldaddr
));
232 void show_ksplice_patches(struct supersect
*kpatch_ss
)
234 const struct ksplice_patch
*kpatch
;
235 for (kpatch
= kpatch_ss
->contents
.data
; (void *)kpatch
<
236 kpatch_ss
->contents
.data
+ kpatch_ss
->contents
.size
; kpatch
++)
237 show_ksplice_patch(kpatch_ss
, kpatch
);
240 void show_ksplice_call(struct supersect
*ss
, void *const *kcall
)
242 printf("%s\n", str_pointer(ss
, kcall
));
245 void show_ksplice_calls(struct supersect
*kcall_ss
)
248 for (kcall
= kcall_ss
->contents
.data
; (void *)kcall
<
249 kcall_ss
->contents
.data
+ kcall_ss
->contents
.size
; kcall
++)
250 show_ksplice_call(kcall_ss
, kcall
);
253 void show_ksplice_system_map(struct supersect
*ss
,
254 const struct ksplice_system_map
*smap
)
257 read_string(ss
, &smap
->label
),
258 str_ulong_vec(ss
, &smap
->candidates
, &smap
->nr_candidates
));
261 void show_ksplice_system_maps(struct supersect
*smap_ss
)
263 const struct ksplice_system_map
*smap
;
264 for (smap
= smap_ss
->contents
.data
;
265 (void *)smap
< smap_ss
->contents
.data
+ smap_ss
->contents
.size
;
267 show_ksplice_system_map(smap_ss
, smap
);
270 struct inspect_section
{
273 const char *notfound
;
274 void (*show
)(struct supersect
*ss
);
277 const struct inspect_section inspect_sections
[] = {
279 .prefix
= ".ksplice_init_relocs",
280 .header
= "KSPLICE INIT RELOCATIONS",
281 .notfound
= "No ksplice init relocations.\n",
282 .show
= show_ksplice_relocs
,
285 .prefix
= ".ksplice_relocs",
286 .header
= "KSPLICE RELOCATIONS",
287 .notfound
= "No ksplice relocations.\n",
288 .show
= show_ksplice_relocs
,
291 .prefix
= ".ksplice_sections",
292 .header
= "KSPLICE SECTIONS",
293 .notfound
= "No ksplice sections.\n",
294 .show
= show_ksplice_sections
,
297 .prefix
= ".ksplice_patches",
298 .header
= "KSPLICE PATCHES",
299 .notfound
= "No ksplice patches.\n",
300 .show
= show_ksplice_patches
,
303 .prefix
= ".ksplice_call",
304 .header
= "KSPLICE CALLS",
305 .notfound
= "No ksplice calls.\n",
306 .show
= show_ksplice_calls
,
309 .prefix
= ".ksplice_system_map",
310 .header
= "KSPLICE SYSTEM.MAP",
311 .notfound
= "No ksplice System.map.\n",
312 .show
= show_ksplice_system_maps
,
314 }, *const inspect_sections_end
= *(&inspect_sections
+ 1);
316 static void load_ksplice_reloc_offsets(struct superbfd
*sbfd
)
318 kreloc_section_hash_init(&ksplice_relocs
);
321 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
322 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
323 if (!starts_with(ss
->name
, ".ksplice_relocs") &&
324 !starts_with(ss
->name
, ".ksplice_init_relocs"))
326 struct ksplice_reloc
*kreloc
;
327 for (kreloc
= ss
->contents
.data
;
328 (void *)kreloc
< ss
->contents
.data
+ ss
->contents
.size
;
330 struct supersect
*sym_ss
;
332 read_pointer(ss
, (void *const *)&kreloc
->blank_addr
,
334 char *key
= strprintf("%p", ptr
);
335 struct kreloc_section
*ks
, **ksp
=
336 kreloc_section_hash_lookup(&ksplice_relocs
, key
,
339 assert(*ksp
== NULL
);
340 ks
= malloc(sizeof(*ks
));
348 static void show_inspect_section(struct superbfd
*sbfd
,
349 const struct inspect_section
*isect
)
353 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
354 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
355 if (starts_with(ss
->name
, isect
->prefix
) &&
356 ss
->contents
.size
!= 0) {
357 printf("%s IN [%s]:\n", isect
->header
, sect
->name
);
363 printf("%s", isect
->notfound
);
367 int main(int argc
, char *argv
[])
373 ibfd
= bfd_openr(argv
[1], NULL
);
377 assert(bfd_check_format_matches(ibfd
, bfd_object
, &matching
));
379 struct superbfd
*sbfd
= fetch_superbfd(ibfd
);
380 load_ksplice_reloc_offsets(sbfd
);
381 const struct inspect_section
*isect
;
382 for (isect
= inspect_sections
; isect
< inspect_sections_end
; isect
++)
383 show_inspect_section(sbfd
, isect
);