Add support for C.123.12345 symbols in static_local_symbol.
[ksplice.git] / inspect.c
blobc75b921e67f1034a4e5c9b029d531b78d0f654fa
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
16 * 02110-1301, USA.
19 /* Always define KSPLICE_STANDALONE, even if you're using integrated Ksplice.
20 inspect won't compile without it. */
21 #define KSPLICE_STANDALONE
23 #define _GNU_SOURCE
24 #include "objcommon.h"
25 #include "kmodsrc/ksplice.h"
26 #include <stdio.h>
28 char *str_pointer(struct supersect *ss, void *const *addr);
30 struct kreloc_section {
31 struct supersect *ss;
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);
49 char *buf = NULL;
50 size_t bufsize = 0;
51 FILE *fp = open_memstream(&buf, &bufsize);
52 fprintf(fp, "[ ");
53 size_t i;
54 for (i = 0; i < size; ++i)
55 fprintf(fp, "%lx ", read_num(data_ss, &data[i]));
56 fprintf(fp, "]");
57 fclose(fp);
58 return buf;
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);
68 free(key);
69 if (ksp == NULL)
70 return NULL;
71 *reloc_ss = (*ksp)->ss;
72 return (*ksp)->reloc;
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)
86 asymbol *sym;
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,
92 sym->section);
93 return str_ksplice_symbol(ksymbol_ss, ksymbol_ss->contents.data +
94 sym->value + offset);
97 char *str_pointer(struct supersect *ss, void *const *addr)
99 asymbol *sym;
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);
106 } else {
107 return strprintf("[%s]+%lx",
108 str_ksplice_symbolp(kreloc_ss,
109 &kreloc->symbol),
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:
118 return "reloc";
119 case KSPLICE_HOWTO_RELOC_PATCH:
120 return "reloc(patch)";
121 case KSPLICE_HOWTO_TIME:
122 return "time";
123 case KSPLICE_HOWTO_DATE:
124 return "date";
125 case KSPLICE_HOWTO_BUG:
126 return "bug";
127 case KSPLICE_HOWTO_EXTABLE:
128 return "extable";
129 default:
130 return "unknown";
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"
141 " type: %s\n"
142 " symbol: %s\n"
143 " insn_addend: %lx\n"
144 " target_addend: %lx\n"
145 " pcrel: %x dst_mask: %lx rightshift: %x signed_addend: %x\n"
146 "\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)
169 printf(" flags:");
170 if (ksect->flags & KSPLICE_SECTION_RODATA)
171 printf(" rodata");
172 if (ksect->flags & KSPLICE_SECTION_TEXT)
173 printf(" text");
174 if (ksect->flags & KSPLICE_SECTION_DATA)
175 printf(" data");
176 printf("\n");
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);
188 printf("\n");
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 switch(kpatch->type) {
203 case KSPLICE_PATCH_TEXT:
204 return strprintf("text\n repladdr: %s", str_pointer
205 (ss, (void *const *)&kpatch->repladdr));
206 case KSPLICE_PATCH_BUGLINE:
207 return strprintf("bugline\n line: %hx",
208 *(unsigned short *)kpatch->trampoline);
209 default:
210 return "unknown";
214 void show_ksplice_patch(struct supersect *ss,
215 const struct ksplice_patch *kpatch)
217 printf(" type: %s\n"
218 " oldaddr: %s\n\n",
219 str_ksplice_patch_type(ss, kpatch),
220 str_pointer(ss, (void *const *)&kpatch->oldaddr));
223 void show_ksplice_patches(struct supersect *kpatch_ss)
225 const struct ksplice_patch *kpatch;
226 for (kpatch = kpatch_ss->contents.data; (void *)kpatch <
227 kpatch_ss->contents.data + kpatch_ss->contents.size; kpatch++)
228 show_ksplice_patch(kpatch_ss, kpatch);
231 void show_ksplice_export(struct supersect *ss, const struct ksplice_export *exp)
233 printf(" name: %s\n"
234 " newname: %s\n"
235 "\n",
236 read_string(ss, &exp->name), read_string(ss, &exp->new_name));
239 void show_ksplice_exports(struct supersect *export_ss)
241 const struct ksplice_export *exp;
242 for (exp = export_ss->contents.data; (void *)exp <
243 export_ss->contents.data + export_ss->contents.size; exp++)
244 show_ksplice_export(export_ss, exp);
247 void show_ksplice_system_map(struct supersect *ss,
248 const struct ksplice_system_map *smap)
250 printf("%s %s\n",
251 read_string(ss, &smap->label),
252 str_ulong_vec(ss, &smap->candidates, &smap->nr_candidates));
255 void show_ksplice_system_maps(struct supersect *smap_ss)
257 const struct ksplice_system_map *smap;
258 for (smap = smap_ss->contents.data;
259 (void *)smap < smap_ss->contents.data + smap_ss->contents.size;
260 smap++)
261 show_ksplice_system_map(smap_ss, smap);
264 struct inspect_section {
265 const char *prefix;
266 const char *header;
267 const char *notfound;
268 void (*show)(struct supersect *ss);
271 const struct inspect_section inspect_sections[] = {
273 .prefix = ".ksplice_init_relocs",
274 .header = "KSPLICE INIT RELOCATIONS",
275 .notfound = "No ksplice init relocations.\n",
276 .show = show_ksplice_relocs,
279 .prefix = ".ksplice_relocs",
280 .header = "KSPLICE RELOCATIONS",
281 .notfound = "No ksplice relocations.\n",
282 .show = show_ksplice_relocs,
285 .prefix = ".ksplice_sections",
286 .header = "KSPLICE SECTIONS",
287 .notfound = "No ksplice sections.\n",
288 .show = show_ksplice_sections,
291 .prefix = ".ksplice_patches",
292 .header = "KSPLICE PATCHES",
293 .notfound = "No ksplice patches.\n",
294 .show = show_ksplice_patches,
297 .prefix = ".ksplice_exports",
298 .header = "KSPLICE EXPORTS",
299 .notfound = "No ksplice exports.\n",
300 .show = show_ksplice_exports,
303 .prefix = ".ksplice_system_map",
304 .header = "KSPLICE SYSTEM.MAP",
305 .notfound = "No ksplice System.map.\n",
306 .show = show_ksplice_system_maps,
308 }, *const inspect_sections_end = *(&inspect_sections + 1);
310 static void load_ksplice_reloc_offsets(struct superbfd *sbfd)
312 kreloc_section_hash_init(&ksplice_relocs);
314 asection *sect;
315 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
316 struct supersect *ss = fetch_supersect(sbfd, sect);
317 if (!starts_with(ss->name, ".ksplice_relocs") &&
318 !starts_with(ss->name, ".ksplice_init_relocs"))
319 continue;
320 struct ksplice_reloc *kreloc;
321 for (kreloc = ss->contents.data;
322 (void *)kreloc < ss->contents.data + ss->contents.size;
323 kreloc++) {
324 struct supersect *sym_ss;
325 const void *ptr =
326 read_pointer(ss, (void *const *)&kreloc->blank_addr,
327 &sym_ss);
328 char *key = strprintf("%p", ptr);
329 struct kreloc_section *ks, **ksp =
330 kreloc_section_hash_lookup(&ksplice_relocs, key,
331 TRUE);
332 free(key);
333 assert(*ksp == NULL);
334 ks = malloc(sizeof(*ks));
335 *ksp = ks;
336 ks->reloc = kreloc;
337 ks->ss = ss;
342 static void show_inspect_section(struct superbfd *sbfd,
343 const struct inspect_section *isect)
345 bool found = false;
346 asection *sect;
347 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
348 struct supersect *ss = fetch_supersect(sbfd, sect);
349 if (starts_with(ss->name, isect->prefix) &&
350 ss->contents.size != 0) {
351 printf("%s IN [%s]:\n", isect->header, sect->name);
352 found = true;
353 isect->show(ss);
356 if (!found)
357 printf("%s", isect->notfound);
358 printf("\n");
361 int main(int argc, char *argv[])
363 bfd *ibfd;
365 assert(argc >= 1);
366 bfd_init();
367 ibfd = bfd_openr(argv[1], NULL);
368 assert(ibfd);
370 char **matching;
371 assert(bfd_check_format_matches(ibfd, bfd_object, &matching));
373 struct superbfd *sbfd = fetch_superbfd(ibfd);
374 load_ksplice_reloc_offsets(sbfd);
375 const struct inspect_section *isect;
376 for (isect = inspect_sections; isect < inspect_sections_end; isect++)
377 show_inspect_section(sbfd, isect);
379 return 0;