Fix orig_label = label invariant in init_label_map.
[ksplice.git] / objmanip.c
blobb41019fd62f78d5649cd4c3c4625e2598de8eaa3
1 /* This file is based in part on objcopy.c from GNU Binutils v2.17.
3 * Copyright (C) 1991-2006 Free Software Foundation, Inc.
4 * Copyright (C) 2007-2008 Jeffrey Brian Arnold <jbarnold@mit.edu>
5 * Copyright (C) 2008 Anders Kaseorg <andersk@mit.edu>,
6 * Tim Abbott <tabbott@mit.edu>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License, version 2.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
19 * 02110-1301, USA.
22 /* objmanip performs various object file manipulations for Ksplice. Its first
23 * two arguments are always an input object file and an output object file.
25 * - keep-primary: "objmanip <post.o> <out.o> keep-primary <pre.o> <kid>"
27 * This mode prepares the object file to be installed as a ksplice update. The
28 * kid argument is the ksplice id string for the ksplice update being built.
30 * - keep-helper: "objmanip <pre.o> <out.o> keep-helper"
32 * This mode prepares the object file to be used for run-pre matching. This
33 * involves replacing all ELF relocations with ksplice relocations and
34 * writing ksplice_section structures for each ELF text or data section.
36 * - rmsyms mode: "objmanip <in.o> <out.o> rmsyms
38 * In this mode, any ELF relocations involving the list of symbol names given on
39 * standard input are replaced with ksplice relocations. This is used only
40 * for KSPLICE_STANDALONE.
42 * - finalize mode: "objmanip <in.o> <out.o> finalize"
44 * In this mode, any ELF relocations to undefined symbols are replaced with
45 * ksplice relocations.
48 /* Always define KSPLICE_STANDALONE, even if you're using integrated Ksplice.
49 objmanip won't compile without it. */
50 #define KSPLICE_STANDALONE
52 #define _GNU_SOURCE
53 #include "objcommon.h"
54 #include "kmodsrc/ksplice.h"
55 #include "kmodsrc/offsets.h"
56 #include <stdint.h>
57 #include <stdarg.h>
58 #include <stdlib.h>
59 #include <stdio.h>
60 #include <limits.h>
62 #define symbol_init(sym) *(sym) = (asymbol *)NULL
63 DEFINE_HASH_TYPE(asymbol *, symbol_hash, symbol_hash_init, symbol_hash_free,
64 symbol_hash_lookup, symbol_init);
66 struct export {
67 const char *name;
68 asection *sect;
70 DECLARE_VEC_TYPE(struct export, export_vec);
72 DECLARE_VEC_TYPE(const char *, str_vec);
74 struct wsect {
75 asection *sect;
76 struct wsect *next;
79 struct export_desc {
80 const char *sectname;
81 struct str_vec names;
83 DECLARE_VEC_TYPE(struct export_desc, export_desc_vec);
85 #define bool_init(b) *(b) = false
86 DEFINE_HASH_TYPE(bool, bool_hash, bool_hash_init, bool_hash_free,
87 bool_hash_lookup, bool_init);
89 #define ulong_init(x) *(x) = 0
90 DEFINE_HASH_TYPE(unsigned long, ulong_hash, ulong_hash_init,
91 ulong_hash_free, ulong_hash_lookup, ulong_init);
93 void do_keep_primary(struct superbfd *isbfd, const char *pre);
94 void do_keep_helper(struct superbfd *isbfd);
95 void do_finalize(struct superbfd *isbfd);
96 void do_rmsyms(struct superbfd *isbfd);
98 struct export_vec *get_export_syms(struct superbfd *sbfd);
99 void compare_exported_symbols(struct superbfd *oldsbfd,
100 struct superbfd *newsbfd, char *addstr);
101 bool relocs_equal(struct supersect *old_ss, struct supersect *new_ss);
102 static bool part_of_reloc(struct supersect *ss, unsigned long addr);
103 static bool nonrelocs_equal(struct supersect *old_ss, struct supersect *new_ss);
104 static void handle_section_symbol_renames(struct superbfd *oldsbfd,
105 struct superbfd *newsbfd);
107 enum supersect_type supersect_type(struct supersect *ss);
108 void initialize_supersect_types(struct superbfd *sbfd);
109 bool is_table_section(const char *name, bool consider_other);
111 void rm_relocs(struct superbfd *isbfd);
112 void rm_some_relocs(struct supersect *ss);
113 void write_ksplice_reloc(struct supersect *ss, arelent *orig_reloc);
114 void blot_section(struct supersect *ss, int offset, reloc_howto_type *howto);
115 void write_ksplice_section(struct superbfd *sbfd, asymbol **symp);
116 void write_ksplice_patch(struct superbfd *sbfd, const char *sectname);
117 void write_ksplice_deleted_patch(struct superbfd *sbfd, const char *name,
118 const char *label);
119 void filter_table_sections(struct superbfd *isbfd);
120 void filter_table_section(struct superbfd *sbfd, const struct table_section *s);
121 void keep_if_referenced(bfd *abfd, asection *sect, void *ignored);
122 void check_for_ref_to_section(bfd *abfd, asection *looking_at,
123 void *looking_for);
124 bfd_boolean copy_object(bfd *ibfd, bfd *obfd);
125 void setup_section(bfd *ibfd, asection *isection, void *obfdarg);
126 static void setup_new_section(bfd *obfd, struct supersect *ss);
127 static void write_section(bfd *obfd, asection *osection, void *arg);
128 void mark_symbols_used_in_relocations(bfd *abfd, asection *isection,
129 void *ignored);
130 static void ss_mark_symbols_used_in_relocations(struct supersect *ss);
131 void filter_symbols(bfd *ibfd, bfd *obfd, struct asymbolp_vec *osyms,
132 struct asymbolp_vec *isyms);
133 static bool deleted_table_section_symbol(bfd *abfd, asymbol *sym);
134 void read_str_set(struct str_vec *strs);
135 bool str_in_set(const char *str, const struct str_vec *strs);
136 struct supersect *make_section(struct superbfd *sbfd, const char *name);
137 void __attribute__((format(printf, 3, 4)))
138 write_string(struct supersect *ss, const char **addr, const char *fmt, ...);
139 void rm_some_exports(struct superbfd *isbfd, const struct export_desc *ed);
140 void write_ksplice_export(struct superbfd *sbfd, const char *symname,
141 const char *export_type, bool del);
142 void write_reloc(struct supersect *ss, const void *addr, asymbol **symp,
143 bfd_vma offset);
144 arelent *create_reloc(struct supersect *ss, const void *addr, asymbol **symp,
145 bfd_vma offset);
146 static void match_global_symbol_sections(struct superbfd *oldsbfd,
147 struct superbfd *newsbfd);
148 static void match_sections_by_name(struct superbfd *oldsbfd,
149 struct superbfd *newsbfd);
150 static void match_sections_by_contents(struct superbfd *oldsbfd,
151 struct superbfd *newsbfd);
152 static void match_sections_by_label(struct superbfd *oldsbfd,
153 struct superbfd *newsbfd);
154 static void mark_new_sections(struct superbfd *sbfd);
155 static void handle_deleted_sections(struct superbfd *oldsbfd,
156 struct superbfd *newsbfd);
157 static void compare_matched_sections(struct superbfd *sbfd);
158 static void update_nonzero_offsets(struct superbfd *sbfd);
159 static void handle_nonzero_offset_relocs(struct supersect *ss);
161 static const char *label_lookup(struct superbfd *sbfd, asymbol *sym);
162 static void print_label_map(struct superbfd *sbfd);
163 static void label_map_set(struct superbfd *sbfd, const char *oldlabel,
164 const char *label);
165 static void init_label_map(struct superbfd *sbfd);
167 int verbose = 0;
168 #define debug1(fmt, ...) \
169 do { if (verbose >= 1) printf(fmt, ## __VA_ARGS__); } while (0)
171 struct str_vec delsects, rmsyms;
172 struct export_desc_vec exports;
173 bool changed;
175 struct ksplice_config *config;
177 const char *modestr, *kid;
179 struct superbfd *offsets_sbfd = NULL;
181 #define mode(str) starts_with(modestr, str)
183 DECLARE_VEC_TYPE(unsigned long, addr_vec);
184 DEFINE_HASH_TYPE(struct addr_vec, addr_vec_hash,
185 addr_vec_hash_init, addr_vec_hash_free, addr_vec_hash_lookup,
186 vec_init);
187 struct addr_vec_hash system_map;
189 struct bool_hash system_map_written;
190 struct ulong_hash ksplice_symbol_offset;
191 struct ulong_hash ksplice_string_offset;
193 void load_system_map()
195 const char *config_dir = getenv("KSPLICE_CONFIG_DIR");
196 assert(config_dir);
197 char *file;
198 assert(asprintf(&file, "%s/System.map", config_dir) >= 0);
199 FILE *fp = fopen(file, "r");
200 assert(fp);
201 addr_vec_hash_init(&system_map);
202 unsigned long addr;
203 char type;
204 char *sym;
205 while (fscanf(fp, "%lx %c %as\n", &addr, &type, &sym) == 3)
206 *vec_grow(addr_vec_hash_lookup(&system_map, sym, TRUE),
207 1) = addr;
208 fclose(fp);
211 void load_offsets()
213 char *kmodsrc = getenv("KSPLICE_KMODSRC"), *offsets_file;
214 assert(kmodsrc != NULL);
215 assert(asprintf(&offsets_file, "%s/offsets.o", kmodsrc) >= 0);
216 bfd *offsets_bfd = bfd_openr(offsets_file, NULL);
217 assert(offsets_bfd != NULL);
218 char **matching;
219 assert(bfd_check_format_matches(offsets_bfd, bfd_object, &matching));
220 offsets_sbfd = fetch_superbfd(offsets_bfd);
222 asection *config_sect = bfd_get_section_by_name(offsets_sbfd->abfd,
223 ".ksplice_config");
224 struct supersect *config_ss =
225 fetch_supersect(offsets_sbfd, config_sect);
227 config = config_ss->contents.data;
230 bool matchable_data_section(struct supersect *ss)
232 if (ss->type == SS_TYPE_RODATA)
233 return true;
234 if (ss->type == SS_TYPE_DATA && ss->relocs.size != 0)
235 return true;
236 return false;
239 bool unchangeable_section(struct supersect *ss)
241 if (ss->type == SS_TYPE_DATA)
242 return true;
243 if (ss->type == SS_TYPE_IGNORED && !starts_with(ss->name, ".debug"))
244 return true;
245 return false;
248 int main(int argc, char *argv[])
250 if (getenv("KSPLICE_VERBOSE") != NULL)
251 verbose = atoi(getenv("KSPLICE_VERBOSE"));
253 bfd_init();
254 bfd *ibfd = bfd_openr(argv[1], NULL);
255 assert(ibfd);
257 char **matching;
258 assert(bfd_check_format_matches(ibfd, bfd_object, &matching));
260 const char *output_target = bfd_get_target(ibfd);
261 bfd *obfd = bfd_openw(argv[2], output_target);
262 assert(obfd);
264 struct superbfd *isbfd = fetch_superbfd(ibfd);
265 init_label_map(isbfd);
267 bool_hash_init(&system_map_written);
268 ulong_hash_init(&ksplice_symbol_offset);
269 ulong_hash_init(&ksplice_string_offset);
271 modestr = argv[3];
272 if (mode("keep-primary")) {
273 kid = argv[5];
274 do_keep_primary(isbfd, argv[4]);
275 } else if (mode("keep-helper")) {
276 do_keep_helper(isbfd);
277 } else if (mode("finalize")) {
278 do_finalize(isbfd);
279 } else if (mode("rmsyms")) {
280 do_rmsyms(isbfd);
283 copy_object(ibfd, obfd);
285 if (offsets_sbfd != NULL)
286 assert(bfd_close(offsets_sbfd->abfd));
287 assert(bfd_close(obfd));
288 assert(bfd_close(ibfd));
289 return EXIT_SUCCESS;
292 void do_keep_primary(struct superbfd *isbfd, const char *pre)
294 struct bfd *prebfd = bfd_openr(pre, NULL);
295 assert(prebfd != NULL);
296 char **matching;
297 assert(bfd_check_format_matches(prebfd, bfd_object, &matching));
299 struct superbfd *presbfd = fetch_superbfd(prebfd);
300 init_label_map(presbfd);
301 load_system_map();
302 load_offsets();
303 initialize_supersect_types(isbfd);
304 initialize_supersect_types(presbfd);
306 match_global_symbol_sections(presbfd, isbfd);
307 debug1("Matched global\n");
308 match_sections_by_name(presbfd, isbfd);
309 debug1("Matched by name\n");
310 match_sections_by_label(presbfd, isbfd);
311 debug1("Matched by label\n");
312 match_sections_by_contents(presbfd, isbfd);
313 debug1("Matched by contents\n");
315 do {
316 changed = false;
317 compare_matched_sections(isbfd);
318 update_nonzero_offsets(isbfd);
319 mark_new_sections(isbfd);
320 } while (changed);
321 vec_init(&delsects);
323 handle_deleted_sections(presbfd, isbfd);
324 handle_section_symbol_renames(presbfd, isbfd);
326 vec_init(&exports);
327 compare_exported_symbols(presbfd, isbfd, "");
328 compare_exported_symbols(isbfd, presbfd, "del_");
330 assert(bfd_close(prebfd));
332 asection *sect;
333 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
334 struct supersect *ss = fetch_supersect(isbfd, sect);
335 ss->keep = false;
336 if (ss->type == SS_TYPE_STRING || ss->type == SS_TYPE_SPECIAL ||
337 ss->type == SS_TYPE_EXPORT)
338 ss->keep = true;
339 if (ss->new || ss->patch)
340 ss->keep = true;
343 if (verbose >= 0) {
344 const char **sectname;
345 printf("Label name changes:\n");
346 print_label_map(isbfd);
348 printf("Changed text sections:\n");
349 for (sect = isbfd->abfd->sections; sect != NULL;
350 sect = sect->next) {
351 struct supersect *ss = fetch_supersect(isbfd, sect);
352 if (ss->patch)
353 printf(" %s\n", sect->name);
356 printf("New sections:\n");
357 for (sect = isbfd->abfd->sections; sect != NULL;
358 sect = sect->next) {
359 struct supersect *ss = fetch_supersect(isbfd, sect);
360 if (ss->new)
361 printf(" %s\n", sect->name);
363 if (delsects.size != 0) {
364 printf("Deleted section names:\n");
365 for (sectname = delsects.data;
366 sectname < delsects.data + delsects.size;
367 sectname++)
368 printf(" %s\n", *sectname);
370 const struct export_desc *ed;
371 for (ed = exports.data; ed < exports.data + exports.size;
372 ed++) {
373 const char **symname;
374 bool del = starts_with(ed->sectname, "del___ksymtab");
375 const char *export_type =
376 ed->sectname + strlen("__ksymtab");
377 if (del)
378 export_type += strlen("_del");
379 for (symname = ed->names.data;
380 symname < ed->names.data + ed->names.size;
381 symname++)
382 printf("Export %s(%s): %s\n",
383 del ? "deletion" : "addition",
384 export_type, *symname);
388 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
389 struct supersect *ss = fetch_supersect(isbfd, sect);
390 if (!ss->patch && !ss->new)
391 continue;
392 asymbol **symp = canonical_symbolp(isbfd, sect->symbol);
393 if (symp == NULL)
394 DIE;
395 write_ksplice_section(isbfd, symp);
396 if (ss->patch)
397 write_ksplice_patch(isbfd, sect->name);
400 const struct export_desc *ed;
401 for (ed = exports.data; ed < exports.data + exports.size; ed++) {
402 if (starts_with(ed->sectname, "del___ksymtab")) {
403 const char *export_type =
404 ed->sectname + strlen("del___ksymtab");
405 const char **symname;
406 for (symname = ed->names.data;
407 symname < ed->names.data + ed->names.size;
408 symname++)
409 write_ksplice_export(isbfd, *symname,
410 export_type, true);
411 } else {
412 rm_some_exports(isbfd, ed);
416 rm_relocs(isbfd);
417 filter_table_sections(isbfd);
420 void do_keep_helper(struct superbfd *isbfd)
422 load_system_map();
423 load_offsets();
424 initialize_supersect_types(isbfd);
426 asection *sect;
427 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
428 struct supersect *ss = fetch_supersect(isbfd, sect);
429 ss->keep = false;
430 if (ss->type == SS_TYPE_STRING || ss->type == SS_TYPE_SPECIAL ||
431 ss->type == SS_TYPE_TEXT)
432 ss->keep = true;
434 do {
435 changed = false;
436 bfd_map_over_sections(isbfd->abfd, keep_if_referenced, NULL);
437 } while (changed);
439 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
440 struct supersect *ss = fetch_supersect(isbfd, sect);
441 asymbol **symp = canonical_symbolp(isbfd, sect->symbol);
442 if (symp == NULL)
443 continue;
444 asymbol *sym = *symp;
445 if ((sym->flags & BSF_WEAK) != 0)
446 continue;
447 if (bfd_get_section_size(sect) == 0)
448 continue;
449 if (ss->keep && (ss->type == SS_TYPE_TEXT ||
450 matchable_data_section(ss)))
451 write_ksplice_section(isbfd, symp);
454 rm_relocs(isbfd);
455 filter_table_sections(isbfd);
458 void do_finalize(struct superbfd *isbfd)
460 load_system_map();
461 load_offsets();
462 initialize_supersect_types(isbfd);
463 rm_relocs(isbfd);
466 void do_rmsyms(struct superbfd *isbfd)
468 read_str_set(&rmsyms);
469 load_system_map();
470 load_offsets();
471 initialize_supersect_types(isbfd);
472 rm_relocs(isbfd);
475 struct export_vec *get_export_syms(struct superbfd *sbfd)
477 asection *sect;
478 struct export_vec *exports;
479 exports = malloc(sizeof(*exports));
480 assert(exports != NULL);
481 vec_init(exports);
483 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
484 if (!starts_with(sect->name, "__ksymtab") ||
485 ends_with(sect->name, "_strings"))
486 continue;
487 struct supersect *ss = fetch_supersect(sbfd, sect);
488 struct kernel_symbol *sym;
489 assert(ss->contents.size * 2 == ss->relocs.size *
490 sizeof(struct kernel_symbol));
491 for (sym = ss->contents.data;
492 (void *)sym < ss->contents.data + ss->contents.size;
493 sym++) {
494 struct export *exp = vec_grow(exports, 1);
495 exp->name =
496 read_string(ss, (const char *const *)&sym->name);
497 exp->sect = sect;
500 return exports;
503 void compare_exported_symbols(struct superbfd *oldsbfd,
504 struct superbfd *newsbfd, char *addstr)
506 struct export_vec *new_exports, *old_exports;
507 new_exports = get_export_syms(newsbfd);
508 if (new_exports == NULL)
509 return;
510 old_exports = get_export_syms(oldsbfd);
511 struct export *old, *new;
512 asection *last_sect = NULL;
513 struct export_desc *ed;
514 for (new = new_exports->data; new < new_exports->data +
515 new_exports->size; new++) {
516 bool found = false;
517 if (old_exports != NULL) {
518 for (old = old_exports->data; old < old_exports->data +
519 old_exports->size; old++) {
520 if (strcmp(new->name, old->name) == 0 &&
521 strcmp(new->sect->name, old->sect->name)
522 == 0) {
523 found = true;
524 break;
528 if (last_sect != new->sect) {
529 last_sect = new->sect;
530 ed = vec_grow(&exports, 1);
531 char *sectname;
532 assert(asprintf(&sectname, "%s%s", addstr,
533 new->sect->name) >= 0);
534 ed->sectname = sectname;
535 vec_init(&ed->names);
537 if (!found)
538 *vec_grow(&ed->names, 1) = new->name;
542 void match_sections(struct supersect *oldss, struct supersect *newss)
544 if (oldss->match == newss && newss->match == oldss)
545 return;
546 if (oldss->match != NULL) {
547 fprintf(stderr, "Matching conflict: old %s: %s != %s\n",
548 oldss->name, oldss->match->name, newss->name);
549 DIE;
551 if (newss->match != NULL) {
552 fprintf(stderr, "Matching conflict: new %s: %s != %s\n",
553 newss->name, newss->match->name, oldss->name);
554 DIE;
556 oldss->match = newss;
557 newss->match = oldss;
558 debug1("Matched old %s to new %s\n", oldss->name, newss->name);
561 static void match_global_symbol_sections(struct superbfd *oldsbfd,
562 struct superbfd *newsbfd)
564 asymbol **oldsymp, **newsymp;
565 for (oldsymp = oldsbfd->syms.data;
566 oldsymp < oldsbfd->syms.data + oldsbfd->syms.size; oldsymp++) {
567 asymbol *oldsym = *oldsymp;
568 if ((oldsym->flags & BSF_GLOBAL) == 0 ||
569 bfd_is_const_section(oldsym->section))
570 continue;
571 for (newsymp = newsbfd->syms.data;
572 newsymp < newsbfd->syms.data + newsbfd->syms.size;
573 newsymp++) {
574 asymbol *newsym = *newsymp;
575 if ((newsym->flags & BSF_GLOBAL) == 0 ||
576 bfd_is_const_section(oldsym->section))
577 continue;
578 if (strcmp(oldsym->name, newsym->name) != 0)
579 continue;
580 struct supersect *oldss =
581 fetch_supersect(oldsbfd, oldsym->section);
582 struct supersect *newss =
583 fetch_supersect(newsbfd, newsym->section);
584 match_sections(oldss, newss);
589 static void match_sections_by_name(struct superbfd *oldsbfd,
590 struct superbfd *newsbfd)
592 asection *newp, *oldp;
593 for (newp = newsbfd->abfd->sections; newp != NULL; newp = newp->next) {
594 struct supersect *newss = fetch_supersect(newsbfd, newp);
595 oldp = bfd_get_section_by_name(oldsbfd->abfd, newp->name);
596 if (oldp == NULL || newss->type == SS_TYPE_STRING ||
597 newss->type == SS_TYPE_SPECIAL ||
598 newss->type == SS_TYPE_EXPORT)
599 continue;
600 if (static_local_symbol(newsbfd,
601 canonical_symbol(newsbfd,
602 newp->symbol)))
603 continue;
605 struct supersect *oldss = fetch_supersect(oldsbfd, oldp);
606 match_sections(oldss, newss);
610 static void match_sections_by_label(struct superbfd *oldsbfd,
611 struct superbfd *newsbfd)
613 asection *oldsect, *newsect;
614 struct supersect *oldss, *newss;
615 for (newsect = newsbfd->abfd->sections; newsect != NULL;
616 newsect = newsect->next) {
617 newss = fetch_supersect(newsbfd, newsect);
618 if (newss->type == SS_TYPE_STRING ||
619 newss->type == SS_TYPE_SPECIAL ||
620 newss->type == SS_TYPE_EXPORT)
621 continue;
622 for (oldsect = oldsbfd->abfd->sections; oldsect != NULL;
623 oldsect = oldsect->next) {
624 if (strcmp(label_lookup(newsbfd, newsect->symbol),
625 label_lookup(oldsbfd, oldsect->symbol)) != 0)
626 continue;
627 oldss = fetch_supersect(oldsbfd, oldsect);
628 match_sections(oldss, newss);
633 static void match_sections_by_contents(struct superbfd *oldsbfd,
634 struct superbfd *newsbfd)
636 asection *oldsect, *newsect;
637 struct supersect *oldss, *newss;
638 for (newsect = newsbfd->abfd->sections; newsect != NULL;
639 newsect = newsect->next) {
640 newss = fetch_supersect(newsbfd, newsect);
641 if (newss->type != SS_TYPE_RODATA)
642 continue;
643 for (oldsect = oldsbfd->abfd->sections; oldsect != NULL;
644 oldsect = oldsect->next) {
645 oldss = fetch_supersect(oldsbfd, oldsect);
646 if (oldss->type != SS_TYPE_RODATA)
647 continue;
648 if (oldss->relocs.size != 0 || newss->relocs.size != 0)
649 continue;
650 if (oldss->contents.size != newss->contents.size)
651 continue;
652 if (memcmp(oldss->contents.data, newss->contents.data,
653 oldss->contents.size) != 0)
654 continue;
655 match_sections(oldss, newss);
660 static void mark_new_sections(struct superbfd *sbfd)
662 asection *sect;
663 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
664 struct supersect *ss = fetch_supersect(sbfd, sect);
665 if (ss->type == SS_TYPE_STRING || ss->type == SS_TYPE_SPECIAL ||
666 ss->type == SS_TYPE_IGNORED || ss->type == SS_TYPE_EXPORT)
667 continue;
668 if (ss->match == NULL)
669 ss->new = true;
673 static void handle_deleted_sections(struct superbfd *oldsbfd,
674 struct superbfd *newsbfd)
676 asection *sect;
677 for (sect = oldsbfd->abfd->sections; sect != NULL; sect = sect->next) {
678 struct supersect *ss = fetch_supersect(oldsbfd, sect);
679 if (ss->type != SS_TYPE_TEXT)
680 continue;
681 if (ss->match != NULL)
682 continue;
683 const char *label = label_lookup(oldsbfd, sect->symbol);
684 *vec_grow(&delsects, 1) = label;
685 asymbol *csym = canonical_symbol(oldsbfd, sect->symbol);
686 write_ksplice_deleted_patch(newsbfd, csym->name, label);
690 static void handle_nonzero_offset_relocs(struct supersect *ss)
692 int i;
693 for (i = 0; i < ss->relocs.size; i++) {
694 asymbol *sym = *ss->relocs.data[i]->sym_ptr_ptr;
695 bfd_vma offset = get_reloc_offset(ss, ss->relocs.data[i], true);
696 if (sym->value + offset == 0)
697 continue;
698 if (bfd_is_const_section(sym->section))
699 continue;
700 struct supersect *sym_ss = fetch_supersect(ss->parent,
701 sym->section);
702 if (sym_ss->type != SS_TYPE_TEXT)
703 continue;
704 if (!sym_ss->patch) {
705 changed = true;
706 debug1("Changing %s because a relocation from sect %s "
707 "has a nonzero offset %lx+%lx into it\n",
708 sym_ss->name, ss->name,
709 (unsigned long)sym->value,
710 (unsigned long)offset);
712 sym_ss->patch = true;
716 static void update_nonzero_offsets(struct superbfd *sbfd)
718 asection *sect;
719 struct supersect *ss;
721 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
722 ss = fetch_supersect(sbfd, sect);
723 if (ss->new || ss->patch)
724 handle_nonzero_offset_relocs(ss);
728 static void compare_matched_sections(struct superbfd *newsbfd)
730 asection *newp;
731 struct supersect *old_ss, *new_ss;
732 for (newp = newsbfd->abfd->sections; newp != NULL; newp = newp->next) {
733 new_ss = fetch_supersect(newsbfd, newp);
734 if (new_ss->match == NULL)
735 continue;
736 old_ss = new_ss->match;
738 if (nonrelocs_equal(old_ss, new_ss) &&
739 relocs_equal(old_ss, new_ss))
740 continue;
741 if (new_ss->type == SS_TYPE_TEXT) {
742 if (new_ss->patch)
743 continue;
744 new_ss->patch = true;
745 debug1("Changing %s due to ", new_ss->name);
746 } else {
747 debug1("Unmatching %s and %s due to ", old_ss->name,
748 new_ss->name);
749 new_ss->match = NULL;
750 old_ss->match = NULL;
752 if (new_ss->contents.size != old_ss->contents.size)
753 debug1("differing sizes\n");
754 else if (memcmp(new_ss->contents.data, old_ss->contents.data,
755 new_ss->contents.size) != 0)
756 debug1("differing contents\n");
757 else
758 debug1("differing relocations\n");
759 changed = true;
760 if (unchangeable_section(new_ss))
761 fprintf(stderr, "WARNING: ignoring change to "
762 "nonpatchable section %s\n", new_ss->name);
766 static void handle_section_symbol_renames(struct superbfd *oldsbfd,
767 struct superbfd *newsbfd)
769 asection *newp, *oldp;
770 for (newp = newsbfd->abfd->sections; newp != NULL; newp = newp->next) {
771 struct supersect *newss = fetch_supersect(newsbfd, newp);
772 if (newss->match == NULL)
773 continue;
774 oldp = bfd_get_section_by_name(oldsbfd->abfd,
775 newss->match->name);
776 if (oldp == NULL)
777 continue;
779 const char *old_label = label_lookup(oldsbfd, oldp->symbol);
780 const char *new_label = label_lookup(newsbfd, newp->symbol);
782 if (strcmp(old_label, new_label) == 0)
783 continue;
784 label_map_set(newsbfd, new_label, old_label);
788 static bool part_of_reloc(struct supersect *ss, unsigned long addr)
790 arelent **relocp;
791 for (relocp = ss->relocs.data;
792 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
793 arelent *reloc = *relocp;
794 if (addr >= reloc->address &&
795 addr < reloc->address + reloc->howto->size)
796 return true;
798 return false;
801 static bool nonrelocs_equal(struct supersect *old_ss, struct supersect *new_ss)
803 int i;
804 if (old_ss->contents.size != new_ss->contents.size)
805 return false;
806 const unsigned char *old = old_ss->contents.data;
807 const unsigned char *new = new_ss->contents.data;
808 for (i = 0; i < old_ss->contents.size; i++) {
809 if (old[i] != new[i] &&
810 !(part_of_reloc(old_ss, i) && part_of_reloc(new_ss, i)))
811 return false;
813 return true;
817 * relocs_equal checks to see whether the old section and the new section
818 * reference different read-only data in their relocations -- if a hard-coded
819 * string has been changed between the old file and the new file, relocs_equal
820 * will detect the difference.
822 bool relocs_equal(struct supersect *old_ss, struct supersect *new_ss)
824 int i;
825 struct superbfd *oldsbfd = old_ss->parent;
826 struct superbfd *newsbfd = new_ss->parent;
828 if (old_ss->relocs.size != new_ss->relocs.size) {
829 debug1("Different reloc count between %s and %s\n",
830 old_ss->name, new_ss->name);
831 return false;
834 for (i = 0; i < old_ss->relocs.size; i++) {
835 struct supersect *ro_old_ss, *ro_new_ss;
837 asymbol *old_sym = *old_ss->relocs.data[i]->sym_ptr_ptr;
838 asymbol *new_sym = *new_ss->relocs.data[i]->sym_ptr_ptr;
840 bfd_vma old_offset =
841 get_reloc_offset(old_ss, old_ss->relocs.data[i], true);
842 bfd_vma new_offset =
843 get_reloc_offset(new_ss, new_ss->relocs.data[i], true);
845 if (bfd_is_und_section(old_sym->section) ||
846 bfd_is_und_section(new_sym->section)) {
847 if (!bfd_is_und_section(new_sym->section) &&
848 fetch_supersect(newsbfd, new_sym->section)->type
849 == SS_TYPE_TEXT && old_offset != 0)
850 return false;
852 if (!bfd_is_und_section(old_sym->section) &&
853 fetch_supersect(oldsbfd, old_sym->section)->type
854 == SS_TYPE_TEXT && new_offset != 0)
855 return false;
857 if (strcmp(old_sym->name, new_sym->name) == 0 &&
858 old_offset == new_offset)
859 continue;
860 return false;
863 if (bfd_is_const_section(old_sym->section) ||
864 bfd_is_const_section(new_sym->section))
865 DIE;
867 ro_old_ss = fetch_supersect(oldsbfd, old_sym->section);
868 ro_new_ss = fetch_supersect(newsbfd, new_sym->section);
870 if (ro_old_ss->type == SS_TYPE_STRING &&
871 /* check it's not an out-of-range relocation to a string;
872 we'll just compare entire sections for them */
873 !(old_offset >= ro_old_ss->contents.size ||
874 new_offset >= ro_new_ss->contents.size)) {
875 if (strcmp(ro_old_ss->contents.data + old_sym->value +
876 old_offset,
877 ro_new_ss->contents.data + new_sym->value +
878 new_offset) != 0) {
879 debug1("Strings differ between %s and %s\n",
880 old_ss->name, new_ss->name);
881 return false;
883 continue;
886 if (ro_old_ss->match != ro_new_ss ||
887 ro_new_ss->match != ro_old_ss) {
888 debug1("Nonmatching relocs from %s to %s/%s\n",
889 new_ss->name, ro_new_ss->name, ro_old_ss->name);
890 return false;
893 if (old_sym->value + old_offset != new_sym->value + new_offset) {
894 debug1("Offsets to %s/%s differ between %s and %s: "
895 "%lx+%lx/%lx+%lx\n", ro_old_ss->name,
896 ro_new_ss->name, old_ss->name, new_ss->name,
897 (unsigned long)old_sym->value,
898 (unsigned long)old_offset,
899 (unsigned long)new_sym->value,
900 (unsigned long)new_offset);
901 return false;
904 if ((old_sym->value + old_offset != 0 ||
905 new_sym->value + new_offset != 0) && ro_new_ss->patch) {
906 debug1("Relocation from %s to nonzero offsets %lx+%lx/"
907 "%lx+%lx in changed section %s\n", new_ss->name,
908 (unsigned long)old_sym->value,
909 (unsigned long)old_offset,
910 (unsigned long)new_sym->value,
911 (unsigned long)new_offset,
912 new_sym->section->name);
913 return false;
917 return true;
920 void rm_some_exports(struct superbfd *isbfd, const struct export_desc *ed)
922 assert(starts_with(ed->sectname, "__ksymtab"));
923 const char *export_type = ed->sectname + strlen("__ksymtab");
924 asection *sym_sect = bfd_get_section_by_name(isbfd->abfd, ed->sectname);
925 assert(sym_sect != NULL);
926 char *export_crc_name;
927 assert(asprintf(&export_crc_name, "__kcrctab%s", export_type) >= 0);
928 asection *crc_sect = bfd_get_section_by_name(isbfd->abfd,
929 export_crc_name);
930 struct supersect *ss, *crc_ss = NULL;
931 ss = fetch_supersect(isbfd, sym_sect);
932 if (crc_sect != NULL)
933 crc_ss = fetch_supersect(isbfd, crc_sect);
935 if (crc_ss != NULL)
936 assert(ss->contents.size * sizeof(unsigned long) ==
937 crc_ss->contents.size * sizeof(struct kernel_symbol));
939 struct supersect orig_ss, orig_crc_ss;
940 supersect_move(&orig_ss, ss);
941 if (crc_ss != NULL)
942 supersect_move(&orig_crc_ss, crc_ss);
944 struct kernel_symbol *orig_ksym;
945 unsigned long *orig_crc;
946 for (orig_ksym = orig_ss.contents.data,
947 orig_crc = orig_crc_ss.contents.data;
948 (void *)orig_ksym < orig_ss.contents.data + orig_ss.contents.size;
949 orig_ksym++, orig_crc++) {
950 asymbol *sym;
951 read_reloc(&orig_ss, &orig_ksym->value,
952 sizeof(orig_ksym->value), &sym);
953 if (!str_in_set(sym->name, &ed->names))
954 continue;
956 struct kernel_symbol *ksym = sect_grow(ss, 1, typeof(*ksym));
957 sect_copy(ss, &ksym->value, &orig_ss, &orig_ksym->value, 1);
958 /* Replace name with a mangled name */
959 write_ksplice_export(ss->parent, sym->name, export_type, false);
960 write_string(ss, (const char **)&ksym->name,
961 "DISABLED_%s_%s", sym->name, kid);
963 if (crc_ss != NULL)
964 sect_copy(crc_ss,
965 sect_grow(crc_ss, 1, typeof(*orig_crc)),
966 &orig_crc_ss, orig_crc, 1);
970 void rm_relocs(struct superbfd *isbfd)
972 asection *p;
973 for (p = isbfd->abfd->sections; p != NULL; p = p->next) {
974 struct supersect *ss = fetch_supersect(isbfd, p);
975 if ((mode("keep") && ss->type == SS_TYPE_SPECIAL) ||
976 ss->type == SS_TYPE_KSPLICE)
977 continue;
978 if (ss->keep || mode("rmsyms"))
979 rm_some_relocs(ss);
981 if (mode("finalize")) {
982 p = bfd_get_section_by_name(isbfd->abfd, ".ksplice_patches");
983 if (p != NULL) {
984 struct supersect *ss = fetch_supersect(isbfd, p);
985 rm_some_relocs(ss);
990 void rm_some_relocs(struct supersect *ss)
992 struct arelentp_vec orig_relocs;
993 vec_move(&orig_relocs, &ss->relocs);
995 arelent **relocp;
996 for (relocp = orig_relocs.data;
997 relocp < orig_relocs.data + orig_relocs.size; relocp++) {
998 bool rm_reloc = false;
999 asymbol *sym_ptr = *(*relocp)->sym_ptr_ptr;
1001 if (mode("rmsyms") && str_in_set(sym_ptr->name, &rmsyms) &&
1002 bfd_is_und_section(sym_ptr->section))
1003 rm_reloc = true;
1005 if (mode("keep"))
1006 rm_reloc = true;
1008 if (mode("keep-primary") &&
1009 (bfd_is_const_section(sym_ptr->section) ||
1010 fetch_supersect(ss->parent, sym_ptr->section)->new ||
1011 fetch_supersect(ss->parent, sym_ptr->section)->type ==
1012 SS_TYPE_STRING))
1013 rm_reloc = false;
1015 if (mode("finalize") && bfd_is_und_section(sym_ptr->section))
1016 rm_reloc = true;
1018 if (rm_reloc)
1019 write_ksplice_reloc(ss, *relocp);
1020 else
1021 *vec_grow(&ss->relocs, 1) = *relocp;
1025 struct supersect *make_section(struct superbfd *sbfd, const char *name)
1027 asection *sect = bfd_get_section_by_name(sbfd->abfd, name);
1028 if (sect != NULL)
1029 return fetch_supersect(sbfd, sect);
1030 else
1031 return new_supersect(sbfd, name);
1034 arelent *create_reloc(struct supersect *ss, const void *addr, asymbol **symp,
1035 bfd_vma offset)
1037 bfd_reloc_code_real_type code;
1038 switch (bfd_arch_bits_per_address(ss->parent->abfd)) {
1039 case 32:
1040 code = BFD_RELOC_32;
1041 break;
1042 case 64:
1043 code = BFD_RELOC_64;
1044 break;
1045 default:
1046 DIE;
1049 arelent *reloc = malloc(sizeof(*reloc));
1050 reloc->sym_ptr_ptr = symp;
1051 reloc->address = addr - ss->contents.data;
1052 reloc->howto = bfd_reloc_type_lookup(ss->parent->abfd, code);
1053 reloc->addend = offset;
1054 return reloc;
1057 void write_reloc(struct supersect *ss, const void *addr, asymbol **symp,
1058 bfd_vma offset)
1060 arelent *new_reloc = create_reloc(ss, addr, symp, offset), **relocp;
1061 for (relocp = ss->relocs.data;
1062 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
1063 if ((*relocp)->address == new_reloc->address) {
1064 memmove(relocp,
1065 relocp + 1,
1066 (void *)(ss->relocs.data + ss->relocs.size) -
1067 (void *)(relocp + 1));
1068 ss->relocs.size--;
1069 relocp--;
1072 *vec_grow(&ss->new_relocs, 1) = new_reloc;
1075 void write_string(struct supersect *ss, const char **addr, const char *fmt, ...)
1077 va_list ap;
1078 struct supersect *str_ss = make_section(ss->parent, ".ksplice_str");
1079 char *str;
1080 va_start(ap, fmt);
1081 int len = vasprintf(&str, fmt, ap);
1082 assert(len >= 0);
1083 va_end(ap);
1085 unsigned long *str_offp = ulong_hash_lookup(&ksplice_string_offset, str,
1086 FALSE);
1087 if (str_offp == NULL) {
1088 char *buf = sect_grow(str_ss, len + 1, char);
1089 memcpy(buf, str, len + 1);
1090 str_offp = ulong_hash_lookup(&ksplice_string_offset, str, TRUE);
1091 *str_offp = (void *)buf - str_ss->contents.data;
1094 write_reloc(ss, addr, &str_ss->symbol, *str_offp);
1097 void lookup_system_map(struct addr_vec *addrs, const char *name, long offset)
1099 struct addr_vec *map_addrs =
1100 addr_vec_hash_lookup(&system_map, name, FALSE);
1101 if (map_addrs == NULL)
1102 return;
1104 unsigned long *addr, *map_addr;
1105 for (map_addr = map_addrs->data;
1106 map_addr < map_addrs->data + map_addrs->size; map_addr++) {
1107 for (addr = addrs->data; addr < addrs->data + addrs->size;
1108 addr++) {
1109 if (*addr == *map_addr + offset)
1110 break;
1112 if (addr < addrs->data + addrs->size)
1113 continue;
1114 *vec_grow(addrs, 1) = *map_addr + offset;
1118 void write_system_map_array(struct superbfd *sbfd, struct supersect *ss,
1119 const unsigned long **sym_addrs,
1120 unsigned long *num_sym_addrs, asymbol *sym)
1122 struct addr_vec addrs;
1123 vec_init(&addrs);
1125 if (bfd_is_abs_section(sym->section)) {
1126 *vec_grow(&addrs, 1) = sym->value;
1127 } else if (bfd_is_und_section(sym->section)) {
1128 lookup_system_map(&addrs, sym->name, 0);
1129 } else if (!bfd_is_const_section(sym->section)) {
1130 asymbol **gsymp;
1131 for (gsymp = sbfd->syms.data;
1132 gsymp < sbfd->syms.data + sbfd->syms.size; gsymp++) {
1133 asymbol *gsym = *gsymp;
1134 if ((gsym->flags & BSF_DEBUGGING) == 0 &&
1135 gsym->section == sym->section)
1136 lookup_system_map(&addrs, gsym->name,
1137 sym->value - gsym->value);
1141 *num_sym_addrs = addrs.size;
1142 if (addrs.size != 0) {
1143 struct supersect *array_ss = make_section(sbfd,
1144 ".ksplice_array");
1145 void *buf = sect_grow(array_ss, addrs.size,
1146 typeof(*addrs.data));
1147 memcpy(buf, addrs.data, addrs.size * sizeof(*addrs.data));
1148 write_reloc(ss, sym_addrs, &array_ss->symbol,
1149 buf - array_ss->contents.data);
1150 } else {
1151 *sym_addrs = NULL;
1154 vec_free(&addrs);
1157 void write_ksplice_system_map(struct superbfd *sbfd, asymbol *sym,
1158 const char *addstr_sect)
1160 struct supersect *smap_ss = make_section(sbfd, ".ksplice_system_map");
1161 struct ksplice_system_map *smap;
1162 const char *label = label_lookup(sbfd, sym);
1164 bool *done = bool_hash_lookup(&system_map_written, label, TRUE);
1165 if (*done)
1166 return;
1167 *done = true;
1169 smap = sect_grow(smap_ss, 1, struct ksplice_system_map);
1171 write_system_map_array(sbfd, smap_ss, &smap->candidates,
1172 &smap->nr_candidates, sym);
1173 write_string(smap_ss, &smap->label, "%s%s", label, addstr_sect);
1176 void write_ksplice_symbol(struct supersect *ss,
1177 const struct ksplice_symbol *const *addr,
1178 asymbol *sym, const char *addstr_sect)
1180 struct supersect *ksymbol_ss = make_section(ss->parent,
1181 ".ksplice_symbols");
1182 struct ksplice_symbol *ksymbol;
1183 unsigned long *ksymbol_offp;
1184 const char *label = label_lookup(ss->parent, sym);
1185 char *output;
1186 assert(asprintf(&output, "%s%s", label, addstr_sect) >= 0);
1188 ksymbol_offp = ulong_hash_lookup(&ksplice_symbol_offset, output, FALSE);
1189 if (ksymbol_offp != NULL) {
1190 write_reloc(ss, addr, &ksymbol_ss->symbol, *ksymbol_offp);
1191 return;
1193 ksymbol = sect_grow(ksymbol_ss, 1, struct ksplice_symbol);
1194 ksymbol_offp = ulong_hash_lookup(&ksplice_symbol_offset, output, TRUE);
1195 *ksymbol_offp = (void *)ksymbol - ksymbol_ss->contents.data;
1197 if (bfd_is_und_section(sym->section) || (sym->flags & BSF_GLOBAL) != 0) {
1198 write_string(ksymbol_ss, &ksymbol->name, "%s", sym->name);
1199 } else if (bfd_is_const_section(sym->section)) {
1200 ksymbol->name = NULL;
1201 } else {
1202 asymbol *gsym = canonical_symbol(ss->parent, sym);
1204 if (gsym == NULL || (gsym->flags & BSF_SECTION_SYM) != 0)
1205 ksymbol->name = NULL;
1206 else
1207 write_string(ksymbol_ss, &ksymbol->name, "%s",
1208 gsym->name);
1211 write_string(ksymbol_ss, &ksymbol->label, "%s%s", label, addstr_sect);
1213 write_ksplice_system_map(ksymbol_ss->parent, sym, addstr_sect);
1215 write_reloc(ss, addr, &ksymbol_ss->symbol, *ksymbol_offp);
1218 void write_ksplice_reloc(struct supersect *ss, arelent *orig_reloc)
1220 asymbol *sym_ptr = *orig_reloc->sym_ptr_ptr;
1221 reloc_howto_type *howto = orig_reloc->howto;
1222 bfd_vma addend = get_reloc_offset(ss, orig_reloc, false);
1224 if (mode("finalize") && starts_with(ss->name, ".ksplice_patches")) {
1225 unsigned long *repladdr =
1226 ss->contents.data + orig_reloc->address;
1227 *repladdr = 0;
1228 return;
1231 blot_section(ss, orig_reloc->address, howto);
1233 struct supersect *kreloc_ss = make_section(ss->parent,
1234 mode("rmsyms") ?
1235 ".ksplice_init_relocs" :
1236 ".ksplice_relocs");
1237 struct ksplice_reloc *kreloc = sect_grow(kreloc_ss, 1,
1238 struct ksplice_reloc);
1240 write_reloc(kreloc_ss, &kreloc->blank_addr,
1241 &ss->symbol, orig_reloc->address);
1242 kreloc->blank_offset = (unsigned long)orig_reloc->address;
1243 write_ksplice_symbol(kreloc_ss, &kreloc->symbol, sym_ptr, "");
1244 kreloc->pcrel = howto->pc_relative;
1245 kreloc->addend = addend;
1246 kreloc->size = bfd_get_reloc_size(howto);
1247 kreloc->dst_mask = howto->dst_mask;
1248 kreloc->rightshift = howto->rightshift;
1249 kreloc->signed_addend =
1250 (howto->complain_on_overflow == complain_overflow_signed) ||
1251 (howto->complain_on_overflow == complain_overflow_bitfield);
1254 #define CANARY(x, canary) ((x & ~howto->dst_mask) | (canary & howto->dst_mask))
1256 void blot_section(struct supersect *ss, int offset, reloc_howto_type *howto)
1258 int bits = bfd_get_reloc_size(howto) * 8;
1259 void *address = ss->contents.data + offset;
1260 bfd_vma x = bfd_get(bits, ss->parent->abfd, address);
1261 x = (x & ~howto->dst_mask) |
1262 ((bfd_vma)KSPLICE_CANARY & howto->dst_mask);
1263 bfd_put(bits, ss->parent->abfd, x, address);
1266 void write_ksplice_section(struct superbfd *sbfd, asymbol **symp)
1268 asymbol *sym = *symp;
1269 struct supersect *ksect_ss = make_section(sbfd, ".ksplice_sections");
1270 struct ksplice_section *ksect = sect_grow(ksect_ss, 1,
1271 struct ksplice_section);
1273 write_ksplice_symbol(ksect_ss, &ksect->symbol, sym,
1274 mode("keep-primary") ? "(post)" : "");
1275 ksect->size = bfd_get_section_size(sym->section);
1276 ksect->flags = 0;
1277 struct supersect *sym_ss = fetch_supersect(sbfd, sym->section);
1278 if (sym_ss->type == SS_TYPE_RODATA)
1279 ksect->flags |= KSPLICE_SECTION_RODATA;
1280 if (sym_ss->type == SS_TYPE_DATA)
1281 ksect->flags |= KSPLICE_SECTION_DATA;
1282 if (sym_ss->type == SS_TYPE_TEXT)
1283 ksect->flags |= KSPLICE_SECTION_TEXT;
1284 assert(ksect->flags != 0);
1285 write_reloc(ksect_ss, &ksect->address, symp, 0);
1288 void write_ksplice_patch(struct superbfd *sbfd, const char *sectname)
1290 struct supersect *kpatch_ss = make_section(sbfd, ".ksplice_patches");
1291 struct ksplice_patch *kpatch = sect_grow(kpatch_ss, 1,
1292 struct ksplice_patch);
1293 asection *sect = bfd_get_section_by_name(sbfd->abfd, sectname);
1294 assert(sect != NULL);
1296 write_string(kpatch_ss, &kpatch->label, "%s",
1297 label_lookup(sbfd, sect->symbol));
1298 write_reloc(kpatch_ss, &kpatch->repladdr, &sect->symbol, 0);
1301 void write_ksplice_deleted_patch(struct superbfd *sbfd, const char *name,
1302 const char *label)
1304 struct supersect *kpatch_ss = make_section(sbfd, ".ksplice_patches");
1305 struct ksplice_patch *kpatch = sect_grow(kpatch_ss, 1,
1306 struct ksplice_patch);
1308 write_string(kpatch_ss, &kpatch->label, "%s", label);
1309 asymbol **symp;
1310 for (symp = sbfd->syms.data; symp < sbfd->syms.data + sbfd->syms.size;
1311 symp++) {
1312 asymbol *sym = *symp;
1313 if (bfd_is_und_section(sym->section) &&
1314 strcmp(name, sym->name) == 0)
1315 break;
1317 if (symp >= sbfd->syms.data + sbfd->syms.size) {
1318 symp = malloc(sizeof(*symp));
1319 *symp = bfd_make_empty_symbol(sbfd->abfd);
1320 asymbol *sym = *symp;
1321 sym->name = strdup(name);
1322 sym->section = bfd_und_section_ptr;
1323 sym->flags = 0;
1324 sym->value = 0;
1325 *vec_grow(&sbfd->new_syms, 1) = symp;
1327 write_reloc(kpatch_ss, &kpatch->repladdr, symp, 0);
1330 void write_ksplice_export(struct superbfd *sbfd, const char *symname,
1331 const char *export_type, bool del)
1333 struct supersect *export_ss = make_section(sbfd, ".ksplice_exports");
1334 struct ksplice_export *exp = sect_grow(export_ss, 1,
1335 struct ksplice_export);
1337 if (del) {
1338 write_string(export_ss, &exp->name, "%s", symname);
1339 write_string(export_ss, &exp->new_name, "DISABLED_%s_%s",
1340 symname, kid);
1341 } else {
1342 write_string(export_ss, &exp->new_name, "%s", symname);
1343 write_string(export_ss, &exp->name, "DISABLED_%s_%s", symname,
1344 kid);
1348 struct fixup_entry {
1349 bfd_vma offset;
1350 bool used;
1351 bfd_vma ex_offset;
1353 DECLARE_VEC_TYPE(struct fixup_entry, fixup_entry_vec);
1355 int compare_fixups(const void *aptr, const void *bptr)
1357 const struct fixup_entry *a = aptr, *b = bptr;
1358 if (a->offset < b->offset)
1359 return -1;
1360 else if (a->offset > b->offset)
1361 return 1;
1362 else
1363 return (int)a->used - (int)b->used;
1366 void filter_table_sections(struct superbfd *isbfd)
1368 struct supersect *tables_ss =
1369 fetch_supersect(offsets_sbfd,
1370 bfd_get_section_by_name(offsets_sbfd->abfd,
1371 ".ksplice_table_sections"));
1372 const struct table_section *ts;
1373 for (ts = tables_ss->contents.data;
1374 (void *)ts < tables_ss->contents.data + tables_ss->contents.size;
1375 ts++) {
1376 struct table_section s = *ts;
1377 s.sect = read_string(tables_ss, &ts->sect);
1378 s.other_sect = read_string(tables_ss, &ts->other_sect);
1379 filter_table_section(isbfd, &s);
1383 void filter_table_section(struct superbfd *sbfd, const struct table_section *s)
1385 asection *isection = bfd_get_section_by_name(sbfd->abfd, s->sect);
1386 if (isection == NULL)
1387 return;
1388 asection *fixup_sect = NULL;
1389 if (s->other_sect != NULL)
1390 fixup_sect = bfd_get_section_by_name(sbfd->abfd, s->other_sect);
1392 struct supersect *ss = fetch_supersect(sbfd, isection), orig_ss;
1393 supersect_move(&orig_ss, ss);
1395 struct supersect *fixup_ss = NULL;
1396 if (fixup_sect != NULL)
1397 fixup_ss = fetch_supersect(sbfd, fixup_sect);
1399 struct fixup_entry_vec fixups;
1400 vec_init(&fixups);
1402 void *orig_entry;
1403 for (orig_entry = orig_ss.contents.data;
1404 orig_entry < orig_ss.contents.data + orig_ss.contents.size;
1405 orig_entry += s->entry_size) {
1406 asymbol *sym, *fixup_sym;
1407 read_reloc(&orig_ss, orig_entry + s->addr_offset,
1408 sizeof(void *), &sym);
1410 struct fixup_entry *f;
1411 if (fixup_sect != NULL) {
1412 bfd_vma fixup_offset =
1413 read_reloc(&orig_ss, orig_entry + s->other_offset,
1414 sizeof(void *), &fixup_sym);
1415 if (fixup_sym->section == fixup_sect) {
1416 assert(fixup_offset < fixup_ss->contents.size);
1417 f = vec_grow(&fixups, 1);
1418 f->offset = fixup_offset;
1419 f->used = false;
1423 struct supersect *sym_ss = fetch_supersect(sbfd, sym->section);
1424 if (!sym_ss->keep)
1425 continue;
1427 if (fixup_sect != NULL && fixup_sym->section == fixup_sect) {
1428 f->used = true;
1429 f->ex_offset = ss->contents.size + s->other_offset;
1431 sect_copy(ss, sect_do_grow(ss, 1, s->entry_size,
1432 s->entry_align),
1433 &orig_ss, orig_entry, s->entry_size);
1436 if (fixup_sect == NULL)
1437 return;
1439 struct supersect orig_fixup_ss;
1440 supersect_move(&orig_fixup_ss, fixup_ss);
1442 qsort(fixups.data, fixups.size, sizeof(*fixups.data), compare_fixups);
1443 *vec_grow(&fixups, 1) = (struct fixup_entry)
1444 { .offset = orig_fixup_ss.contents.size, .used = false };
1446 struct fixup_entry *f;
1447 for (f = fixups.data; f < fixups.data + fixups.size - 1; f++) {
1448 if (!f->used)
1449 continue;
1450 write_reloc(ss, ss->contents.data + f->ex_offset,
1451 &fixup_ss->symbol, fixup_ss->contents.size);
1452 sect_copy(fixup_ss,
1453 sect_grow(fixup_ss, (f + 1)->offset - f->offset,
1454 unsigned char),
1455 &orig_fixup_ss,
1456 orig_fixup_ss.contents.data + f->offset,
1457 (f + 1)->offset - f->offset);
1461 void keep_if_referenced(bfd *abfd, asection *sect, void *ignored)
1463 struct superbfd *sbfd = fetch_superbfd(abfd);
1464 struct supersect *ss = fetch_supersect(sbfd, sect);
1465 if (ss->keep || ss->type == SS_TYPE_IGNORED)
1466 return;
1468 asymbol **symp;
1469 for (symp = sbfd->syms.data;
1470 symp < sbfd->syms.data + sbfd->syms.size; symp++) {
1471 asymbol *sym = *symp;
1472 if (sym->section == sect && (sym->flags & BSF_GLOBAL) != 0) {
1473 ss->keep = true;
1474 changed = true;
1475 return;
1479 bfd_map_over_sections(abfd, check_for_ref_to_section, sect);
1482 void check_for_ref_to_section(bfd *abfd, asection *looking_at,
1483 void *looking_for)
1485 struct superbfd *sbfd = fetch_superbfd(abfd);
1486 struct supersect *ss = fetch_supersect(sbfd, looking_at);
1487 struct supersect *for_ss = fetch_supersect(sbfd,
1488 (asection *)looking_for);
1489 if (!ss->keep || ss->type == SS_TYPE_STRING ||
1490 ss->type == SS_TYPE_SPECIAL || ss->type == SS_TYPE_EXPORT)
1491 return;
1493 arelent **relocp;
1494 for (relocp = ss->relocs.data;
1495 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
1496 asymbol *sym = *(*relocp)->sym_ptr_ptr;
1497 if (sym->section != (asection *)looking_for)
1498 continue;
1499 for_ss->keep = true;
1500 changed = true;
1501 return;
1505 void copy_symbols(struct asymbolp_vec *osyms, struct asymbolpp_vec *isyms)
1507 asymbol ***sympp;
1508 for (sympp = isyms->data; sympp < isyms->data + isyms->size; sympp++)
1509 *vec_grow(osyms, 1) = **sympp;
1512 /* Modified function from GNU Binutils objcopy.c */
1513 bfd_boolean copy_object(bfd *ibfd, bfd *obfd)
1515 assert(bfd_set_format(obfd, bfd_get_format(ibfd)));
1517 bfd_vma start = bfd_get_start_address(ibfd);
1519 flagword flags = bfd_get_file_flags(ibfd);
1520 flags &= bfd_applicable_file_flags(obfd);
1522 assert(bfd_set_start_address(obfd, start)
1523 && bfd_set_file_flags(obfd, flags));
1525 enum bfd_architecture iarch = bfd_get_arch(ibfd);
1526 unsigned int imach = bfd_get_mach(ibfd);
1527 assert(bfd_set_arch_mach(obfd, iarch, imach));
1528 assert(bfd_set_format(obfd, bfd_get_format(ibfd)));
1530 /* BFD mandates that all output sections be created and sizes set before
1531 any output is done. Thus, we traverse all sections multiple times. */
1532 bfd_map_over_sections(ibfd, setup_section, obfd);
1534 struct supersect *new_supersects = fetch_superbfd(ibfd)->new_supersects;
1535 struct supersect *ss;
1536 for (ss = new_supersects; ss != NULL; ss = ss->next)
1537 setup_new_section(obfd, ss);
1539 /* Mark symbols used in output relocations so that they
1540 are kept, even if they are local labels or static symbols.
1542 Note we iterate over the input sections examining their
1543 relocations since the relocations for the output sections
1544 haven't been set yet. mark_symbols_used_in_relocations will
1545 ignore input sections which have no corresponding output
1546 section. */
1548 bfd_map_over_sections(ibfd, mark_symbols_used_in_relocations, NULL);
1549 for (ss = new_supersects; ss != NULL; ss = ss->next)
1550 ss_mark_symbols_used_in_relocations(ss);
1551 struct asymbolp_vec osyms;
1552 vec_init(&osyms);
1553 filter_symbols(ibfd, obfd, &osyms, &fetch_superbfd(ibfd)->syms);
1554 copy_symbols(&osyms, &fetch_superbfd(ibfd)->new_syms);
1556 bfd_set_symtab(obfd, osyms.data, osyms.size);
1558 /* This has to happen after the symbol table has been set. */
1559 bfd_map_over_sections(obfd, write_section, NULL);
1561 /* Allow the BFD backend to copy any private data it understands
1562 from the input BFD to the output BFD. This is done last to
1563 permit the routine to look at the filtered symbol table, which is
1564 important for the ECOFF code at least. */
1565 assert(bfd_copy_private_bfd_data(ibfd, obfd));
1567 return TRUE;
1570 /* Modified function from GNU Binutils objcopy.c */
1571 void setup_section(bfd *ibfd, asection *isection, void *obfdarg)
1573 struct superbfd *isbfd = fetch_superbfd(ibfd);
1574 struct supersect *ss = fetch_supersect(isbfd, isection);
1575 bfd *obfd = obfdarg;
1576 bfd_vma vma;
1578 if (!ss->keep)
1579 return;
1581 asection *osection = bfd_make_section_anyway(obfd, isection->name);
1582 assert(osection != NULL);
1584 osection->userdata = ss;
1585 bfd_set_section_flags(obfd, osection, ss->flags);
1586 ss->symbol = osection->symbol;
1587 assert(bfd_set_section_size(obfd, osection, ss->contents.size));
1589 vma = bfd_section_vma(ibfd, isection);
1590 assert(bfd_set_section_vma(obfd, osection, vma));
1592 osection->lma = isection->lma;
1593 assert(bfd_set_section_alignment(obfd, osection, ss->alignment));
1594 osection->entsize = isection->entsize;
1595 osection->output_section = osection;
1596 osection->output_offset = 0;
1597 isection->output_section = osection;
1598 isection->output_offset = 0;
1599 return;
1602 void setup_new_section(bfd *obfd, struct supersect *ss)
1604 asection *osection = bfd_make_section_anyway(obfd, ss->name);
1605 assert(osection != NULL);
1606 bfd_set_section_flags(obfd, osection, ss->flags);
1608 osection->userdata = ss;
1609 ss->symbol = osection->symbol;
1610 assert(bfd_set_section_size(obfd, osection, ss->contents.size));
1611 assert(bfd_set_section_vma(obfd, osection, 0));
1613 osection->lma = 0;
1614 assert(bfd_set_section_alignment(obfd, osection, ss->alignment));
1615 osection->entsize = 0;
1616 osection->output_section = osection;
1617 osection->output_offset = 0;
1620 void write_section(bfd *obfd, asection *osection, void *arg)
1622 struct supersect *ss = osection->userdata;
1624 if ((ss->flags & SEC_GROUP) != 0 || ss->contents.size == 0)
1625 return;
1627 arelent **relocp;
1628 char *error_message;
1629 for (relocp = ss->new_relocs.data;
1630 relocp < ss->new_relocs.data + ss->new_relocs.size; relocp++) {
1631 bfd_vma val;
1632 if (bfd_get_arch(obfd) == bfd_arch_arm)
1633 val = osection->use_rela_p ? 0 : (*relocp)->addend;
1634 else
1635 val = 0;
1636 bfd_put(bfd_get_reloc_size((*relocp)->howto) * 8, obfd, val,
1637 ss->contents.data + (*relocp)->address);
1638 if (bfd_install_relocation(obfd, *relocp, ss->contents.data,
1639 0, osection, &error_message) !=
1640 bfd_reloc_ok) {
1641 fprintf(stderr, "ksplice: error installing reloc: %s",
1642 error_message);
1643 DIE;
1646 memcpy(vec_grow(&ss->relocs, ss->new_relocs.size), ss->new_relocs.data,
1647 ss->new_relocs.size * sizeof(*ss->new_relocs.data));
1649 bfd_set_reloc(obfd, osection,
1650 ss->relocs.size == 0 ? NULL : ss->relocs.data,
1651 ss->relocs.size);
1653 if (ss->flags & SEC_HAS_CONTENTS)
1654 assert(bfd_set_section_contents
1655 (obfd, osection, ss->contents.data, 0,
1656 ss->contents.size));
1659 /* Modified function from GNU Binutils objcopy.c
1661 * Mark all the symbols which will be used in output relocations with
1662 * the BSF_KEEP flag so that those symbols will not be stripped.
1664 * Ignore relocations which will not appear in the output file.
1666 void mark_symbols_used_in_relocations(bfd *abfd, asection *isection,
1667 void *ignored)
1669 struct superbfd *sbfd = fetch_superbfd(abfd);
1670 if (isection->output_section == NULL)
1671 return;
1673 struct supersect *ss = fetch_supersect(sbfd, isection);
1674 ss_mark_symbols_used_in_relocations(ss);
1677 void ss_mark_symbols_used_in_relocations(struct supersect *ss)
1679 /* Examine each symbol used in a relocation. If it's not one of the
1680 special bfd section symbols, then mark it with BSF_KEEP. */
1681 arelent **relocp;
1682 for (relocp = ss->relocs.data;
1683 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
1684 asymbol *sym = *(*relocp)->sym_ptr_ptr;
1685 if (!(bfd_is_const_section(sym->section) &&
1686 sym == sym->section->symbol))
1687 sym->flags |= BSF_KEEP;
1689 for (relocp = ss->new_relocs.data;
1690 relocp < ss->new_relocs.data + ss->new_relocs.size; relocp++) {
1691 asymbol *sym = *(*relocp)->sym_ptr_ptr;
1692 if (!(bfd_is_const_section(sym->section) &&
1693 sym == sym->section->symbol))
1694 sym->flags |= BSF_KEEP;
1698 static bool deleted_table_section_symbol(bfd *abfd, asymbol *sym)
1700 struct superbfd *sbfd = fetch_superbfd(abfd);
1701 if (bfd_is_const_section(sym->section))
1702 return false;
1703 struct supersect *ss = fetch_supersect(sbfd, sym->section);
1705 asymbol **symp;
1706 for (symp = ss->syms.data; symp < ss->syms.data + ss->syms.size; symp++) {
1707 if (sym == *symp)
1708 break;
1710 return symp >= ss->syms.data + ss->syms.size;
1713 /* Modified function from GNU Binutils objcopy.c
1715 * Choose which symbol entries to copy.
1716 * We don't copy in place, because that confuses the relocs.
1717 * Return the number of symbols to print.
1719 void filter_symbols(bfd *ibfd, bfd *obfd, struct asymbolp_vec *osyms,
1720 struct asymbolp_vec *isyms)
1722 asymbol **symp;
1723 struct superbfd *sbfd = fetch_superbfd(ibfd);
1724 for (symp = isyms->data; symp < isyms->data + isyms->size; symp++) {
1725 asymbol *sym = *symp;
1726 struct supersect *sym_ss = NULL;
1727 if (!bfd_is_const_section(sym->section))
1728 sym_ss = fetch_supersect(sbfd, sym->section);
1730 bool keep = false;
1732 if (mode("keep") && (sym->flags & BSF_GLOBAL) != 0 &&
1733 !(mode("keep-primary") && sym_ss != NULL && sym_ss->new))
1734 sym->flags = (sym->flags & ~BSF_GLOBAL) | BSF_LOCAL;
1736 if (mode("finalize") && (sym->flags & BSF_GLOBAL) != 0)
1737 sym->flags = (sym->flags & ~BSF_GLOBAL) | BSF_LOCAL;
1739 if ((sym->flags & BSF_KEEP) != 0 /* Used in relocation. */
1740 || ((sym->flags & BSF_SECTION_SYM) != 0 && sym_ss != NULL &&
1741 sym_ss->keep))
1742 keep = true;
1743 else if ((sym->flags & (BSF_GLOBAL | BSF_WEAK)) != 0 &&
1744 sym_ss != NULL && sym_ss->keep)
1745 keep = true;
1746 else if (mode("keep-primary") &&
1747 starts_with(sym->section->name, "__ksymtab"))
1748 keep = true;
1750 if (deleted_table_section_symbol(ibfd, sym))
1751 keep = false;
1753 if (bfd_is_com_section(sym->section))
1754 keep = false;
1756 if (mode("rmsyms"))
1757 keep = !str_in_set(sym->name, &rmsyms);
1759 if (keep) {
1760 assert(sym_ss == NULL || sym_ss->keep);
1761 *vec_grow(osyms, 1) = sym;
1766 void read_str_set(struct str_vec *strs)
1768 char *buf = NULL;
1769 size_t n = 0;
1770 assert(getline(&buf, &n, stdin) >= 0);
1771 vec_init(strs);
1772 char *saveptr;
1773 while (1) {
1774 char *str = strtok_r(buf, " \n", &saveptr);
1775 buf = NULL;
1776 if (str == NULL)
1777 break;
1778 *vec_grow(strs, 1) = str;
1782 bool str_in_set(const char *str, const struct str_vec *strs)
1784 const char **strp;
1785 for (strp = strs->data; strp < strs->data + strs->size; strp++) {
1786 if (strcmp(str, *strp) == 0)
1787 return true;
1789 return false;
1792 bool is_table_section(const char *name, bool consider_other)
1794 struct supersect *tables_ss =
1795 fetch_supersect(offsets_sbfd,
1796 bfd_get_section_by_name(offsets_sbfd->abfd,
1797 ".ksplice_table_sections"));
1798 const struct table_section *ts;
1799 for (ts = tables_ss->contents.data;
1800 (void *)ts < tables_ss->contents.data + tables_ss->contents.size;
1801 ts++) {
1802 if (strcmp(name, read_string(tables_ss, &ts->sect)) == 0)
1803 return true;
1804 const char *osect_name = read_string(tables_ss,
1805 &ts->other_sect);
1806 if (consider_other && osect_name != NULL &&
1807 strcmp(name, osect_name) == 0)
1808 return true;
1810 return false;
1813 enum supersect_type supersect_type(struct supersect *ss)
1815 if (starts_with(ss->name, ".ksplice"))
1816 return SS_TYPE_KSPLICE;
1818 if (starts_with(ss->name, ".init"))
1819 return SS_TYPE_IGNORED;
1820 if (starts_with(ss->name, ".security_initcall.init"))
1821 return SS_TYPE_IGNORED;
1822 if (starts_with(ss->name, ".con_initcall.init"))
1823 return SS_TYPE_IGNORED;
1824 if (starts_with(ss->name, ".x86cpuvendor.init"))
1825 return SS_TYPE_IGNORED;
1826 if (starts_with(ss->name, ".early_param.init"))
1827 return SS_TYPE_IGNORED;
1828 if (starts_with(ss->name, ".taglist.init"))
1829 return SS_TYPE_IGNORED;
1830 if (starts_with(ss->name, ".arch.info.init"))
1831 return SS_TYPE_IGNORED;
1832 if (starts_with(ss->name, ".proc.info.init"))
1833 return SS_TYPE_IGNORED;
1834 /* .pci_fixup_* sections really should be treated as global rodata
1835 referenced only from quirks.c */
1836 if (starts_with(ss->name, ".pci_fixup_"))
1837 return SS_TYPE_IGNORED;
1838 /* .builtin_fw sections are similar to .pci_fixup */
1839 if (starts_with(ss->name, ".builtin_fw"))
1840 return SS_TYPE_IGNORED;
1841 /* same for .tracedata */
1842 if (starts_with(ss->name, ".tracedata"))
1843 return SS_TYPE_IGNORED;
1844 if (starts_with(ss->name, ".debug"))
1845 return SS_TYPE_IGNORED;
1846 /* .eh_frame should probably be discarded, not ignored */
1847 if (starts_with(ss->name, ".eh_frame"))
1848 return SS_TYPE_IGNORED;
1849 if (config->ignore_devinit && starts_with(ss->name, ".devinit"))
1850 return SS_TYPE_IGNORED;
1851 if (config->ignore_meminit && starts_with(ss->name, ".meminit"))
1852 return SS_TYPE_IGNORED;
1853 if (config->ignore_cpuinit && starts_with(ss->name, ".cpuinit"))
1854 return SS_TYPE_IGNORED;
1855 if (config->ignore_devinit && starts_with(ss->name, ".devexit"))
1856 return SS_TYPE_IGNORED;
1857 if (config->ignore_meminit && starts_with(ss->name, ".memexit"))
1858 return SS_TYPE_IGNORED;
1859 if (config->ignore_cpuinit && starts_with(ss->name, ".cpuexit"))
1860 return SS_TYPE_IGNORED;
1861 if (starts_with(ss->name, ".vgetcpu_mode") ||
1862 starts_with(ss->name, ".jiffies") ||
1863 starts_with(ss->name, ".wall_jiffies") ||
1864 starts_with(ss->name, ".vxtime") ||
1865 starts_with(ss->name, ".sys_tz") ||
1866 starts_with(ss->name, ".sysctl_vsyscall") ||
1867 starts_with(ss->name, ".xtime") ||
1868 starts_with(ss->name, ".xtime_lock") ||
1869 starts_with(ss->name, ".vsyscall"))
1870 return SS_TYPE_IGNORED;
1871 if (starts_with(ss->name, ".vdso"))
1872 return SS_TYPE_IGNORED;
1874 if (bfd_get_section_by_name(ss->parent->abfd, ".exitcall.exit") == NULL) {
1875 if (starts_with(ss->name, ".exit.text"))
1876 return SS_TYPE_TEXT;
1877 if (starts_with(ss->name, ".exit.data"))
1878 return SS_TYPE_DATA;
1879 } else if (starts_with(ss->name, ".exit.text") ||
1880 starts_with(ss->name, ".exit.data"))
1881 return SS_TYPE_IGNORED;
1883 if (starts_with(ss->name, ".text") ||
1884 starts_with(ss->name, ".kernel.text") ||
1885 starts_with(ss->name, ".devinit.text") ||
1886 starts_with(ss->name, ".meminit.text") ||
1887 starts_with(ss->name, ".cpuinit.text") ||
1888 starts_with(ss->name, ".devexit.text") ||
1889 starts_with(ss->name, ".memexit.text") ||
1890 starts_with(ss->name, ".cpuexit.text") ||
1891 starts_with(ss->name, ".ref.text") ||
1892 starts_with(ss->name, ".spinlock.text") ||
1893 starts_with(ss->name, ".kprobes.text") ||
1894 starts_with(ss->name, ".sched.text"))
1895 return SS_TYPE_TEXT;
1897 int n = -1;
1898 if (sscanf(ss->name, ".rodata.str%*u.%*u%n", &n) >= 0 &&
1899 n == strlen(ss->name))
1900 return SS_TYPE_STRING;
1902 if (starts_with(ss->name, ".rodata") ||
1903 starts_with(ss->name, ".kernel.rodata") ||
1904 starts_with(ss->name, ".devinit.rodata") ||
1905 starts_with(ss->name, ".meminit.rodata") ||
1906 starts_with(ss->name, ".cpuinit.rodata") ||
1907 starts_with(ss->name, ".devexit.rodata") ||
1908 starts_with(ss->name, ".memexit.rodata") ||
1909 starts_with(ss->name, ".cpuexit.rodata") ||
1910 starts_with(ss->name, ".ref.rodata") ||
1911 starts_with(ss->name, "__markers_strings"))
1912 return SS_TYPE_RODATA;
1914 if (starts_with(ss->name, ".bss"))
1915 return SS_TYPE_DATA;
1917 /* Ignore .data.percpu sections */
1918 if (starts_with(ss->name, ".data.percpu") ||
1919 starts_with(ss->name, ".kernel.data.percpu"))
1920 return SS_TYPE_IGNORED;
1921 if (starts_with(ss->name, ".data") ||
1922 starts_with(ss->name, ".kernel.data") ||
1923 starts_with(ss->name, ".devinit.data") ||
1924 starts_with(ss->name, ".cpuinit.data") ||
1925 starts_with(ss->name, ".meminit.data") ||
1926 starts_with(ss->name, ".devexit.data") ||
1927 starts_with(ss->name, ".memexit.data") ||
1928 starts_with(ss->name, ".cpuexit.data") ||
1929 starts_with(ss->name, ".ref.data") ||
1930 starts_with(ss->name, "__markers"))
1931 return SS_TYPE_DATA;
1933 if (starts_with(ss->name, "__ksymtab"))
1934 return SS_TYPE_EXPORT;
1935 if (starts_with(ss->name, "__kcrctab"))
1936 return SS_TYPE_EXPORT;
1938 if (is_table_section(ss->name, true))
1939 return SS_TYPE_SPECIAL;
1941 if (starts_with(ss->name, ".ARM."))
1942 return SS_TYPE_SPECIAL;
1944 if (starts_with(ss->name, ".note"))
1945 return SS_TYPE_IGNORED;
1946 if (starts_with(ss->name, ".comment"))
1947 return SS_TYPE_IGNORED;
1948 if (starts_with(ss->name, "__param"))
1949 return SS_TYPE_IGNORED;
1950 if (starts_with(ss->name, ".exitcall.exit"))
1951 return SS_TYPE_IGNORED;
1952 if (starts_with(ss->name, ".modinfo"))
1953 return SS_TYPE_IGNORED;
1955 return SS_TYPE_UNKNOWN;
1958 void initialize_supersect_types(struct superbfd *sbfd)
1960 asection *sect;
1961 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
1962 struct supersect *ss = fetch_supersect(sbfd, sect);
1963 ss->type = supersect_type(ss);
1964 if (ss->type == SS_TYPE_UNKNOWN) {
1965 fprintf(stderr, "Unknown section type: %s\n", ss->name);
1966 DIE;
1971 static void init_label_map(struct superbfd *sbfd)
1973 vec_init(&sbfd->maps);
1974 struct label_map *map, *map2;
1976 asymbol **symp;
1977 for (symp = sbfd->syms.data;
1978 symp < sbfd->syms.data + sbfd->syms.size; symp++) {
1979 asymbol *csym = canonical_symbol(sbfd, *symp);
1980 if (csym == NULL)
1981 continue;
1982 for (map = sbfd->maps.data;
1983 map < sbfd->maps.data + sbfd->maps.size; map++) {
1984 if (map->csym == csym)
1985 break;
1987 if (map < sbfd->maps.data + sbfd->maps.size)
1988 continue;
1989 map = vec_grow(&sbfd->maps, 1);
1990 map->csym = csym;
1991 map->count = 0;
1992 map->index = 0;
1993 map->label = symbol_label(sbfd, csym);
1995 for (map = sbfd->maps.data;
1996 map < sbfd->maps.data + sbfd->maps.size; map++) {
1997 for (map2 = sbfd->maps.data;
1998 map2 < sbfd->maps.data + sbfd->maps.size; map2++) {
1999 if (strcmp(map->label, map2->label) != 0)
2000 continue;
2001 map->count++;
2002 if (map2 < map)
2003 map->index++;
2007 for (map = sbfd->maps.data;
2008 map < sbfd->maps.data + sbfd->maps.size; map++) {
2009 if (map->count > 1) {
2010 char *buf;
2011 assert(asprintf(&buf, "%s~%d", map->label,
2012 map->index) >= 0);
2013 map->label = buf;
2015 map->orig_label = map->label;
2019 static const char *label_lookup(struct superbfd *sbfd, asymbol *sym)
2021 struct label_map *map;
2022 asymbol *csym = canonical_symbol(sbfd, sym);
2023 for (map = sbfd->maps.data;
2024 map < sbfd->maps.data + sbfd->maps.size; map++) {
2025 if (csym == map->csym)
2026 return map->label;
2028 return symbol_label(sbfd, sym);
2031 static void print_label_map(struct superbfd *sbfd)
2033 struct label_map *map;
2034 for (map = sbfd->maps.data;
2035 map < sbfd->maps.data + sbfd->maps.size; map++) {
2036 if (strcmp(map->orig_label, map->label) == 0)
2037 continue;
2038 printf(" %s -> %s\n", map->label, map->orig_label);
2042 static void label_map_set(struct superbfd *sbfd, const char *oldlabel,
2043 const char *label)
2045 struct label_map *map;
2046 for (map = sbfd->maps.data;
2047 map < sbfd->maps.data + sbfd->maps.size; map++) {
2048 if (strcmp(map->orig_label, oldlabel) == 0) {
2049 if (strcmp(map->orig_label, map->label) != 0 &&
2050 strcmp(map->label, label) != 0)
2051 DIE;
2052 map->label = label;
2053 return;
2056 DIE;