[udis86] Add INVEPT and INVVPID instructions.
[ksplice.git] / objmanip.c
blobc7f968a92d07986e928ed813c10b37b782c63913
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 debug_(sbfd, level, fmt, ...) \
169 do { \
170 if (verbose >= (level)) \
171 printf("%s: " fmt, (sbfd)->abfd->filename, \
172 ## __VA_ARGS__); \
173 } while (0)
174 #define debug0(sbfd, fmt, ...) debug_(sbfd, 0, fmt, ## __VA_ARGS__)
175 #define debug1(sbfd, fmt, ...) debug_(sbfd, 1, fmt, ## __VA_ARGS__)
176 #define err(sbfd, fmt, ...) \
177 do { \
178 fprintf(stderr, "%s: " fmt, (sbfd)->abfd->filename, \
179 ## __VA_ARGS__); \
180 } while (0)
182 struct str_vec delsects, rmsyms;
183 struct export_desc_vec exports;
184 bool changed;
186 struct ksplice_config *config;
188 const char *modestr, *kid;
190 struct superbfd *offsets_sbfd = NULL;
192 #define mode(str) starts_with(modestr, str)
194 DECLARE_VEC_TYPE(unsigned long, addr_vec);
195 DEFINE_HASH_TYPE(struct addr_vec, addr_vec_hash,
196 addr_vec_hash_init, addr_vec_hash_free, addr_vec_hash_lookup,
197 vec_init);
198 struct addr_vec_hash system_map;
200 struct bool_hash system_map_written;
201 struct ulong_hash ksplice_symbol_offset;
202 struct ulong_hash ksplice_string_offset;
204 void load_system_map()
206 const char *config_dir = getenv("KSPLICE_CONFIG_DIR");
207 assert(config_dir);
208 char *file;
209 assert(asprintf(&file, "%s/System.map", config_dir) >= 0);
210 FILE *fp = fopen(file, "r");
211 assert(fp);
212 addr_vec_hash_init(&system_map);
213 unsigned long addr;
214 char type;
215 char *sym;
216 while (fscanf(fp, "%lx %c %as\n", &addr, &type, &sym) == 3)
217 *vec_grow(addr_vec_hash_lookup(&system_map, sym, TRUE),
218 1) = addr;
219 fclose(fp);
222 void load_offsets()
224 char *kmodsrc = getenv("KSPLICE_KMODSRC"), *offsets_file;
225 assert(kmodsrc != NULL);
226 assert(asprintf(&offsets_file, "%s/offsets.o", kmodsrc) >= 0);
227 bfd *offsets_bfd = bfd_openr(offsets_file, NULL);
228 assert(offsets_bfd != NULL);
229 char **matching;
230 assert(bfd_check_format_matches(offsets_bfd, bfd_object, &matching));
231 offsets_sbfd = fetch_superbfd(offsets_bfd);
233 asection *config_sect = bfd_get_section_by_name(offsets_sbfd->abfd,
234 ".ksplice_config");
235 struct supersect *config_ss =
236 fetch_supersect(offsets_sbfd, config_sect);
238 config = config_ss->contents.data;
241 bool matchable_data_section(struct supersect *ss)
243 if (ss->type == SS_TYPE_RODATA)
244 return true;
245 if (ss->type == SS_TYPE_DATA && ss->relocs.size != 0)
246 return true;
247 return false;
250 bool unchangeable_section(struct supersect *ss)
252 if (ss->type == SS_TYPE_DATA)
253 return true;
254 if (ss->type == SS_TYPE_IGNORED && !starts_with(ss->name, ".debug"))
255 return true;
256 return false;
259 int main(int argc, char *argv[])
261 if (getenv("KSPLICE_VERBOSE") != NULL)
262 verbose = atoi(getenv("KSPLICE_VERBOSE"));
264 bfd_init();
265 bfd *ibfd = bfd_openr(argv[1], NULL);
266 assert(ibfd);
268 char **matching;
269 assert(bfd_check_format_matches(ibfd, bfd_object, &matching));
271 const char *output_target = bfd_get_target(ibfd);
272 bfd *obfd = bfd_openw(argv[2], output_target);
273 assert(obfd);
275 struct superbfd *isbfd = fetch_superbfd(ibfd);
276 init_label_map(isbfd);
278 bool_hash_init(&system_map_written);
279 ulong_hash_init(&ksplice_symbol_offset);
280 ulong_hash_init(&ksplice_string_offset);
282 modestr = argv[3];
283 if (mode("keep-primary")) {
284 kid = argv[5];
285 do_keep_primary(isbfd, argv[4]);
286 } else if (mode("keep-helper")) {
287 do_keep_helper(isbfd);
288 } else if (mode("finalize")) {
289 do_finalize(isbfd);
290 } else if (mode("rmsyms")) {
291 do_rmsyms(isbfd);
294 copy_object(ibfd, obfd);
296 if (offsets_sbfd != NULL)
297 assert(bfd_close(offsets_sbfd->abfd));
298 assert(bfd_close(obfd));
299 assert(bfd_close(ibfd));
300 return EXIT_SUCCESS;
303 void do_keep_primary(struct superbfd *isbfd, const char *pre)
305 struct bfd *prebfd = bfd_openr(pre, NULL);
306 assert(prebfd != NULL);
307 char **matching;
308 assert(bfd_check_format_matches(prebfd, bfd_object, &matching));
310 struct superbfd *presbfd = fetch_superbfd(prebfd);
311 init_label_map(presbfd);
312 load_system_map();
313 load_offsets();
314 initialize_supersect_types(isbfd);
315 initialize_supersect_types(presbfd);
317 match_global_symbol_sections(presbfd, isbfd);
318 debug1(isbfd, "Matched global\n");
319 match_sections_by_name(presbfd, isbfd);
320 debug1(isbfd, "Matched by name\n");
321 match_sections_by_label(presbfd, isbfd);
322 debug1(isbfd, "Matched by label\n");
323 match_sections_by_contents(presbfd, isbfd);
324 debug1(isbfd, "Matched by contents\n");
326 do {
327 changed = false;
328 compare_matched_sections(isbfd);
329 update_nonzero_offsets(isbfd);
330 mark_new_sections(isbfd);
331 } while (changed);
332 vec_init(&delsects);
334 handle_deleted_sections(presbfd, isbfd);
335 handle_section_symbol_renames(presbfd, isbfd);
337 vec_init(&exports);
338 compare_exported_symbols(presbfd, isbfd, "");
339 compare_exported_symbols(isbfd, presbfd, "del_");
341 assert(bfd_close(prebfd));
343 asection *sect;
344 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
345 struct supersect *ss = fetch_supersect(isbfd, sect);
346 ss->keep = false;
347 if (ss->type == SS_TYPE_STRING || ss->type == SS_TYPE_SPECIAL ||
348 ss->type == SS_TYPE_EXPORT)
349 ss->keep = true;
350 if (ss->new || ss->patch)
351 ss->keep = true;
354 print_label_map(isbfd);
356 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
357 struct supersect *ss = fetch_supersect(isbfd, sect);
358 if (ss->patch)
359 debug0(isbfd, "Patching section: %s\n", sect->name);
362 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
363 struct supersect *ss = fetch_supersect(isbfd, sect);
364 if (ss->new)
365 debug0(isbfd, "New section: %s\n", sect->name);
368 const char **sectname;
369 for (sectname = delsects.data;
370 sectname < delsects.data + delsects.size; sectname++)
371 debug0(isbfd, "Deleted section: %s\n", *sectname);
373 const struct export_desc *ed;
374 for (ed = exports.data; ed < exports.data + exports.size; ed++) {
375 const char **symname;
376 bool del = starts_with(ed->sectname, "del___ksymtab");
377 const char *export_type = ed->sectname + strlen("__ksymtab");
378 if (del)
379 export_type += strlen("_del");
380 for (symname = ed->names.data;
381 symname < ed->names.data + ed->names.size; symname++)
382 debug0(isbfd, "Export %s (%s): %s\n",
383 del ? "deletion" : "addition",
384 export_type, *symname);
387 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
388 struct supersect *ss = fetch_supersect(isbfd, sect);
389 if (!ss->patch && !ss->new)
390 continue;
391 asymbol **symp = canonical_symbolp(isbfd, sect->symbol);
392 if (symp == NULL)
393 DIE;
394 write_ksplice_section(isbfd, symp);
395 if (ss->patch)
396 write_ksplice_patch(isbfd, sect->name);
399 for (ed = exports.data; ed < exports.data + exports.size; ed++) {
400 if (starts_with(ed->sectname, "del___ksymtab")) {
401 const char *export_type =
402 ed->sectname + strlen("del___ksymtab");
403 const char **symname;
404 for (symname = ed->names.data;
405 symname < ed->names.data + ed->names.size;
406 symname++)
407 write_ksplice_export(isbfd, *symname,
408 export_type, true);
409 } else {
410 rm_some_exports(isbfd, ed);
414 rm_relocs(isbfd);
415 filter_table_sections(isbfd);
418 void do_keep_helper(struct superbfd *isbfd)
420 load_system_map();
421 load_offsets();
422 initialize_supersect_types(isbfd);
424 asection *sect;
425 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
426 struct supersect *ss = fetch_supersect(isbfd, sect);
427 ss->keep = false;
428 if (ss->type == SS_TYPE_STRING || ss->type == SS_TYPE_SPECIAL ||
429 ss->type == SS_TYPE_TEXT)
430 ss->keep = true;
432 do {
433 changed = false;
434 bfd_map_over_sections(isbfd->abfd, keep_if_referenced, NULL);
435 } while (changed);
437 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
438 struct supersect *ss = fetch_supersect(isbfd, sect);
439 asymbol **symp = canonical_symbolp(isbfd, sect->symbol);
440 if (symp == NULL)
441 continue;
442 asymbol *sym = *symp;
443 if ((sym->flags & BSF_WEAK) != 0)
444 continue;
445 if (bfd_get_section_size(sect) == 0)
446 continue;
447 if (ss->keep && (ss->type == SS_TYPE_TEXT ||
448 matchable_data_section(ss)))
449 write_ksplice_section(isbfd, symp);
452 rm_relocs(isbfd);
453 filter_table_sections(isbfd);
456 void do_finalize(struct superbfd *isbfd)
458 load_system_map();
459 load_offsets();
460 initialize_supersect_types(isbfd);
461 rm_relocs(isbfd);
464 void do_rmsyms(struct superbfd *isbfd)
466 read_str_set(&rmsyms);
467 load_system_map();
468 load_offsets();
469 initialize_supersect_types(isbfd);
470 rm_relocs(isbfd);
473 struct export_vec *get_export_syms(struct superbfd *sbfd)
475 asection *sect;
476 struct export_vec *exports;
477 exports = malloc(sizeof(*exports));
478 assert(exports != NULL);
479 vec_init(exports);
481 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
482 if (!starts_with(sect->name, "__ksymtab") ||
483 ends_with(sect->name, "_strings"))
484 continue;
485 struct supersect *ss = fetch_supersect(sbfd, sect);
486 struct kernel_symbol *sym;
487 assert(ss->contents.size * 2 == ss->relocs.size *
488 sizeof(struct kernel_symbol));
489 for (sym = ss->contents.data;
490 (void *)sym < ss->contents.data + ss->contents.size;
491 sym++) {
492 struct export *exp = vec_grow(exports, 1);
493 exp->name =
494 read_string(ss, (const char *const *)&sym->name);
495 exp->sect = sect;
498 return exports;
501 void compare_exported_symbols(struct superbfd *oldsbfd,
502 struct superbfd *newsbfd, char *addstr)
504 struct export_vec *new_exports, *old_exports;
505 new_exports = get_export_syms(newsbfd);
506 if (new_exports == NULL)
507 return;
508 old_exports = get_export_syms(oldsbfd);
509 struct export *old, *new;
510 asection *last_sect = NULL;
511 struct export_desc *ed = NULL;
512 for (new = new_exports->data; new < new_exports->data +
513 new_exports->size; new++) {
514 bool found = false;
515 if (old_exports != NULL) {
516 for (old = old_exports->data; old < old_exports->data +
517 old_exports->size; old++) {
518 if (strcmp(new->name, old->name) == 0 &&
519 strcmp(new->sect->name, old->sect->name)
520 == 0) {
521 found = true;
522 break;
526 if (last_sect != new->sect) {
527 last_sect = new->sect;
528 ed = vec_grow(&exports, 1);
529 char *sectname;
530 assert(asprintf(&sectname, "%s%s", addstr,
531 new->sect->name) >= 0);
532 ed->sectname = sectname;
533 vec_init(&ed->names);
535 if (!found)
536 *vec_grow(&ed->names, 1) = new->name;
540 void match_sections(struct supersect *oldss, struct supersect *newss)
542 if (oldss->match == newss && newss->match == oldss)
543 return;
544 if (oldss->match != NULL) {
545 err(newss->parent, "Matching conflict: old %s: %s != %s\n",
546 oldss->name, oldss->match->name, newss->name);
547 DIE;
549 if (newss->match != NULL) {
550 err(newss->parent, "Matching conflict: new %s: %s != %s\n",
551 newss->name, newss->match->name, oldss->name);
552 DIE;
554 oldss->match = newss;
555 newss->match = oldss;
556 debug1(newss->parent, "Matched old %s to new %s\n",
557 oldss->name, newss->name);
560 static void match_global_symbol_sections(struct superbfd *oldsbfd,
561 struct superbfd *newsbfd)
563 asymbol **oldsymp, **newsymp;
564 for (oldsymp = oldsbfd->syms.data;
565 oldsymp < oldsbfd->syms.data + oldsbfd->syms.size; oldsymp++) {
566 asymbol *oldsym = *oldsymp;
567 if ((oldsym->flags & BSF_GLOBAL) == 0 ||
568 bfd_is_const_section(oldsym->section))
569 continue;
570 for (newsymp = newsbfd->syms.data;
571 newsymp < newsbfd->syms.data + newsbfd->syms.size;
572 newsymp++) {
573 asymbol *newsym = *newsymp;
574 if ((newsym->flags & BSF_GLOBAL) == 0 ||
575 bfd_is_const_section(oldsym->section))
576 continue;
577 if (strcmp(oldsym->name, newsym->name) != 0)
578 continue;
579 struct supersect *oldss =
580 fetch_supersect(oldsbfd, oldsym->section);
581 struct supersect *newss =
582 fetch_supersect(newsbfd, newsym->section);
583 match_sections(oldss, newss);
588 static void match_sections_by_name(struct superbfd *oldsbfd,
589 struct superbfd *newsbfd)
591 asection *newp, *oldp;
592 for (newp = newsbfd->abfd->sections; newp != NULL; newp = newp->next) {
593 struct supersect *newss = fetch_supersect(newsbfd, newp);
594 oldp = bfd_get_section_by_name(oldsbfd->abfd, newp->name);
595 if (oldp == NULL || newss->type == SS_TYPE_STRING ||
596 newss->type == SS_TYPE_SPECIAL ||
597 newss->type == SS_TYPE_EXPORT)
598 continue;
599 if (static_local_symbol(newsbfd,
600 canonical_symbol(newsbfd,
601 newp->symbol)))
602 continue;
604 struct supersect *oldss = fetch_supersect(oldsbfd, oldp);
605 match_sections(oldss, newss);
609 static void match_sections_by_label(struct superbfd *oldsbfd,
610 struct superbfd *newsbfd)
612 asection *oldsect, *newsect;
613 struct supersect *oldss, *newss;
614 for (newsect = newsbfd->abfd->sections; newsect != NULL;
615 newsect = newsect->next) {
616 newss = fetch_supersect(newsbfd, newsect);
617 if (newss->type == SS_TYPE_STRING ||
618 newss->type == SS_TYPE_SPECIAL ||
619 newss->type == SS_TYPE_EXPORT)
620 continue;
621 for (oldsect = oldsbfd->abfd->sections; oldsect != NULL;
622 oldsect = oldsect->next) {
623 if (strcmp(label_lookup(newsbfd, newsect->symbol),
624 label_lookup(oldsbfd, oldsect->symbol)) != 0)
625 continue;
626 oldss = fetch_supersect(oldsbfd, oldsect);
627 match_sections(oldss, newss);
632 static void match_sections_by_contents(struct superbfd *oldsbfd,
633 struct superbfd *newsbfd)
635 asection *oldsect, *newsect;
636 struct supersect *oldss, *newss;
637 for (newsect = newsbfd->abfd->sections; newsect != NULL;
638 newsect = newsect->next) {
639 newss = fetch_supersect(newsbfd, newsect);
640 if (newss->type != SS_TYPE_RODATA)
641 continue;
642 for (oldsect = oldsbfd->abfd->sections; oldsect != NULL;
643 oldsect = oldsect->next) {
644 oldss = fetch_supersect(oldsbfd, oldsect);
645 if (oldss->type != SS_TYPE_RODATA)
646 continue;
647 if (oldss->relocs.size != 0 || newss->relocs.size != 0)
648 continue;
649 if (oldss->contents.size != newss->contents.size)
650 continue;
651 if (memcmp(oldss->contents.data, newss->contents.data,
652 oldss->contents.size) != 0)
653 continue;
654 match_sections(oldss, newss);
659 static void mark_new_sections(struct superbfd *sbfd)
661 asection *sect;
662 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
663 struct supersect *ss = fetch_supersect(sbfd, sect);
664 if (ss->type == SS_TYPE_STRING || ss->type == SS_TYPE_SPECIAL ||
665 ss->type == SS_TYPE_IGNORED || ss->type == SS_TYPE_EXPORT)
666 continue;
667 if (ss->match == NULL)
668 ss->new = true;
672 static void handle_deleted_sections(struct superbfd *oldsbfd,
673 struct superbfd *newsbfd)
675 asection *sect;
676 for (sect = oldsbfd->abfd->sections; sect != NULL; sect = sect->next) {
677 struct supersect *ss = fetch_supersect(oldsbfd, sect);
678 if (ss->type != SS_TYPE_TEXT)
679 continue;
680 if (ss->match != NULL)
681 continue;
682 const char *label = label_lookup(oldsbfd, sect->symbol);
683 *vec_grow(&delsects, 1) = label;
684 asymbol *csym = canonical_symbol(oldsbfd, sect->symbol);
685 write_ksplice_deleted_patch(newsbfd, csym->name, label);
689 static void handle_nonzero_offset_relocs(struct supersect *ss)
691 int i;
692 for (i = 0; i < ss->relocs.size; i++) {
693 asymbol *sym = *ss->relocs.data[i]->sym_ptr_ptr;
694 bfd_vma offset = get_reloc_offset(ss, ss->relocs.data[i], true);
695 if (sym->value + offset == 0)
696 continue;
697 if (bfd_is_const_section(sym->section))
698 continue;
699 struct supersect *sym_ss = fetch_supersect(ss->parent,
700 sym->section);
701 if (sym_ss->type != SS_TYPE_TEXT)
702 continue;
703 if (!sym_ss->patch) {
704 changed = true;
705 debug1(ss->parent,
706 "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;
742 char *reason;
743 if (new_ss->contents.size != old_ss->contents.size)
744 reason = "differing sizes";
745 else if (memcmp(new_ss->contents.data, old_ss->contents.data,
746 new_ss->contents.size) != 0)
747 reason = "differing contents";
748 else
749 reason = "differing relocations";
750 if (new_ss->type == SS_TYPE_TEXT) {
751 if (new_ss->patch)
752 continue;
753 new_ss->patch = true;
754 debug1(newsbfd, "Changing %s due to %s\n", new_ss->name,
755 reason);
756 } else {
757 debug1(newsbfd, "Unmatching %s and %s due to %s\n",
758 old_ss->name, new_ss->name, reason);
759 new_ss->match = NULL;
760 old_ss->match = NULL;
762 changed = true;
763 if (unchangeable_section(new_ss))
764 err(newsbfd, "warning: ignoring change to nonpatchable "
765 "section %s\n", new_ss->name);
769 static void handle_section_symbol_renames(struct superbfd *oldsbfd,
770 struct superbfd *newsbfd)
772 asection *newp, *oldp;
773 for (newp = newsbfd->abfd->sections; newp != NULL; newp = newp->next) {
774 struct supersect *newss = fetch_supersect(newsbfd, newp);
775 if (newss->match == NULL)
776 continue;
777 oldp = bfd_get_section_by_name(oldsbfd->abfd,
778 newss->match->name);
779 if (oldp == NULL)
780 continue;
782 const char *old_label = label_lookup(oldsbfd, oldp->symbol);
783 const char *new_label = label_lookup(newsbfd, newp->symbol);
785 if (strcmp(old_label, new_label) == 0)
786 continue;
787 label_map_set(newsbfd, new_label, old_label);
791 static bool part_of_reloc(struct supersect *ss, unsigned long addr)
793 arelent **relocp;
794 for (relocp = ss->relocs.data;
795 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
796 arelent *reloc = *relocp;
797 if (addr >= reloc->address &&
798 addr < reloc->address + reloc->howto->size)
799 return true;
801 return false;
804 static bool nonrelocs_equal(struct supersect *old_ss, struct supersect *new_ss)
806 int i;
807 if (old_ss->contents.size != new_ss->contents.size)
808 return false;
809 const unsigned char *old = old_ss->contents.data;
810 const unsigned char *new = new_ss->contents.data;
811 for (i = 0; i < old_ss->contents.size; i++) {
812 if (old[i] != new[i] &&
813 !(part_of_reloc(old_ss, i) && part_of_reloc(new_ss, i)))
814 return false;
816 return true;
820 * relocs_equal checks to see whether the old section and the new section
821 * reference different read-only data in their relocations -- if a hard-coded
822 * string has been changed between the old file and the new file, relocs_equal
823 * will detect the difference.
825 bool relocs_equal(struct supersect *old_ss, struct supersect *new_ss)
827 int i;
828 struct superbfd *oldsbfd = old_ss->parent;
829 struct superbfd *newsbfd = new_ss->parent;
831 if (old_ss->relocs.size != new_ss->relocs.size) {
832 debug1(newsbfd, "Different reloc count between %s and %s\n",
833 old_ss->name, new_ss->name);
834 return false;
837 for (i = 0; i < old_ss->relocs.size; i++) {
838 struct supersect *ro_old_ss, *ro_new_ss;
840 asymbol *old_sym = *old_ss->relocs.data[i]->sym_ptr_ptr;
841 asymbol *new_sym = *new_ss->relocs.data[i]->sym_ptr_ptr;
843 bfd_vma old_offset =
844 get_reloc_offset(old_ss, old_ss->relocs.data[i], true);
845 bfd_vma new_offset =
846 get_reloc_offset(new_ss, new_ss->relocs.data[i], true);
848 if (bfd_is_und_section(old_sym->section) ||
849 bfd_is_und_section(new_sym->section)) {
850 if (!bfd_is_und_section(new_sym->section) &&
851 fetch_supersect(newsbfd, new_sym->section)->type
852 == SS_TYPE_TEXT && old_offset != 0)
853 return false;
855 if (!bfd_is_und_section(old_sym->section) &&
856 fetch_supersect(oldsbfd, old_sym->section)->type
857 == SS_TYPE_TEXT && new_offset != 0)
858 return false;
860 if (strcmp(old_sym->name, new_sym->name) == 0 &&
861 old_offset == new_offset)
862 continue;
863 return false;
866 if (bfd_is_const_section(old_sym->section) ||
867 bfd_is_const_section(new_sym->section))
868 DIE;
870 ro_old_ss = fetch_supersect(oldsbfd, old_sym->section);
871 ro_new_ss = fetch_supersect(newsbfd, new_sym->section);
873 if (ro_old_ss->type == SS_TYPE_STRING &&
874 /* check it's not an out-of-range relocation to a string;
875 we'll just compare entire sections for them */
876 !(old_offset >= ro_old_ss->contents.size ||
877 new_offset >= ro_new_ss->contents.size)) {
878 if (strcmp(ro_old_ss->contents.data + old_sym->value +
879 old_offset,
880 ro_new_ss->contents.data + new_sym->value +
881 new_offset) != 0) {
882 debug0(newsbfd, "Section %s/%s has string "
883 "difference \"%s\"/\"%s\"\n",
884 old_ss->name, new_ss->name,
885 (const char *)(ro_old_ss->contents.data +
886 old_sym->value +
887 old_offset),
888 (const char *)(ro_new_ss->contents.data +
889 new_sym->value +
890 new_offset));
891 debug1(newsbfd,
892 "Strings differ between %s and %s\n",
893 old_ss->name, new_ss->name);
894 return false;
896 continue;
899 if (ro_old_ss->match != ro_new_ss ||
900 ro_new_ss->match != ro_old_ss) {
901 debug1(newsbfd, "Nonmatching relocs from %s to %s/%s\n",
902 new_ss->name, ro_new_ss->name, ro_old_ss->name);
903 return false;
906 if (old_sym->value + old_offset != new_sym->value + new_offset) {
907 debug1(newsbfd, "Offsets to %s/%s differ between %s "
908 "and %s: %lx+%lx/%lx+%lx\n", ro_old_ss->name,
909 ro_new_ss->name, old_ss->name, new_ss->name,
910 (unsigned long)old_sym->value,
911 (unsigned long)old_offset,
912 (unsigned long)new_sym->value,
913 (unsigned long)new_offset);
914 return false;
917 if ((old_sym->value + old_offset != 0 ||
918 new_sym->value + new_offset != 0) && ro_new_ss->patch) {
919 debug1(newsbfd, "Relocation from %s to nonzero offsets "
920 "%lx+%lx/%lx+%lx in changed section %s\n",
921 new_ss->name,
922 (unsigned long)old_sym->value,
923 (unsigned long)old_offset,
924 (unsigned long)new_sym->value,
925 (unsigned long)new_offset,
926 new_sym->section->name);
927 return false;
931 return true;
934 void rm_some_exports(struct superbfd *isbfd, const struct export_desc *ed)
936 assert(starts_with(ed->sectname, "__ksymtab"));
937 const char *export_type = ed->sectname + strlen("__ksymtab");
938 asection *sym_sect = bfd_get_section_by_name(isbfd->abfd, ed->sectname);
939 assert(sym_sect != NULL);
940 char *export_crc_name;
941 assert(asprintf(&export_crc_name, "__kcrctab%s", export_type) >= 0);
942 asection *crc_sect = bfd_get_section_by_name(isbfd->abfd,
943 export_crc_name);
944 struct supersect *ss, *crc_ss = NULL;
945 ss = fetch_supersect(isbfd, sym_sect);
946 if (crc_sect != NULL)
947 crc_ss = fetch_supersect(isbfd, crc_sect);
949 if (crc_ss != NULL)
950 assert(ss->contents.size * sizeof(unsigned long) ==
951 crc_ss->contents.size * sizeof(struct kernel_symbol));
953 struct supersect orig_ss, orig_crc_ss;
954 supersect_move(&orig_ss, ss);
955 if (crc_ss != NULL)
956 supersect_move(&orig_crc_ss, crc_ss);
958 struct kernel_symbol *orig_ksym;
959 unsigned long *orig_crc;
960 for (orig_ksym = orig_ss.contents.data,
961 orig_crc = orig_crc_ss.contents.data;
962 (void *)orig_ksym < orig_ss.contents.data + orig_ss.contents.size;
963 orig_ksym++, orig_crc++) {
964 asymbol *sym;
965 read_reloc(&orig_ss, &orig_ksym->value,
966 sizeof(orig_ksym->value), &sym);
967 if (!str_in_set(sym->name, &ed->names))
968 continue;
970 struct kernel_symbol *ksym = sect_grow(ss, 1, typeof(*ksym));
971 sect_copy(ss, &ksym->value, &orig_ss, &orig_ksym->value, 1);
972 /* Replace name with a mangled name */
973 write_ksplice_export(ss->parent, sym->name, export_type, false);
974 write_string(ss, (const char **)&ksym->name,
975 "DISABLED_%s_%s", sym->name, kid);
977 if (crc_ss != NULL)
978 sect_copy(crc_ss,
979 sect_grow(crc_ss, 1, typeof(*orig_crc)),
980 &orig_crc_ss, orig_crc, 1);
984 void rm_relocs(struct superbfd *isbfd)
986 asection *p;
987 for (p = isbfd->abfd->sections; p != NULL; p = p->next) {
988 struct supersect *ss = fetch_supersect(isbfd, p);
989 if ((mode("keep") && ss->type == SS_TYPE_SPECIAL) ||
990 ss->type == SS_TYPE_KSPLICE)
991 continue;
992 if (ss->keep || mode("rmsyms"))
993 rm_some_relocs(ss);
995 if (mode("finalize")) {
996 p = bfd_get_section_by_name(isbfd->abfd, ".ksplice_patches");
997 if (p != NULL) {
998 struct supersect *ss = fetch_supersect(isbfd, p);
999 rm_some_relocs(ss);
1004 void rm_some_relocs(struct supersect *ss)
1006 struct arelentp_vec orig_relocs;
1007 vec_move(&orig_relocs, &ss->relocs);
1009 arelent **relocp;
1010 for (relocp = orig_relocs.data;
1011 relocp < orig_relocs.data + orig_relocs.size; relocp++) {
1012 bool rm_reloc = false;
1013 asymbol *sym_ptr = *(*relocp)->sym_ptr_ptr;
1015 if (mode("rmsyms") && str_in_set(sym_ptr->name, &rmsyms) &&
1016 bfd_is_und_section(sym_ptr->section))
1017 rm_reloc = true;
1019 if (mode("keep"))
1020 rm_reloc = true;
1022 if (mode("keep-primary") &&
1023 (bfd_is_const_section(sym_ptr->section) ||
1024 fetch_supersect(ss->parent, sym_ptr->section)->new ||
1025 fetch_supersect(ss->parent, sym_ptr->section)->type ==
1026 SS_TYPE_STRING))
1027 rm_reloc = false;
1029 if (mode("finalize") && bfd_is_und_section(sym_ptr->section))
1030 rm_reloc = true;
1032 if (rm_reloc)
1033 write_ksplice_reloc(ss, *relocp);
1034 else
1035 *vec_grow(&ss->relocs, 1) = *relocp;
1039 struct supersect *make_section(struct superbfd *sbfd, const char *name)
1041 asection *sect = bfd_get_section_by_name(sbfd->abfd, name);
1042 if (sect != NULL)
1043 return fetch_supersect(sbfd, sect);
1044 else
1045 return new_supersect(sbfd, name);
1048 arelent *create_reloc(struct supersect *ss, const void *addr, asymbol **symp,
1049 bfd_vma offset)
1051 bfd_reloc_code_real_type code;
1052 switch (bfd_arch_bits_per_address(ss->parent->abfd)) {
1053 case 32:
1054 code = BFD_RELOC_32;
1055 break;
1056 case 64:
1057 code = BFD_RELOC_64;
1058 break;
1059 default:
1060 DIE;
1063 arelent *reloc = malloc(sizeof(*reloc));
1064 reloc->sym_ptr_ptr = symp;
1065 reloc->address = addr - ss->contents.data;
1066 reloc->howto = bfd_reloc_type_lookup(ss->parent->abfd, code);
1067 reloc->addend = offset;
1068 return reloc;
1071 void write_reloc(struct supersect *ss, const void *addr, asymbol **symp,
1072 bfd_vma offset)
1074 arelent *new_reloc = create_reloc(ss, addr, symp, offset), **relocp;
1075 for (relocp = ss->relocs.data;
1076 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
1077 if ((*relocp)->address == new_reloc->address) {
1078 memmove(relocp,
1079 relocp + 1,
1080 (void *)(ss->relocs.data + ss->relocs.size) -
1081 (void *)(relocp + 1));
1082 ss->relocs.size--;
1083 relocp--;
1086 *vec_grow(&ss->new_relocs, 1) = new_reloc;
1089 void write_string(struct supersect *ss, const char **addr, const char *fmt, ...)
1091 va_list ap;
1092 struct supersect *str_ss = make_section(ss->parent, ".ksplice_str");
1093 char *str;
1094 va_start(ap, fmt);
1095 int len = vasprintf(&str, fmt, ap);
1096 assert(len >= 0);
1097 va_end(ap);
1099 unsigned long *str_offp = ulong_hash_lookup(&ksplice_string_offset, str,
1100 FALSE);
1101 if (str_offp == NULL) {
1102 char *buf = sect_grow(str_ss, len + 1, char);
1103 memcpy(buf, str, len + 1);
1104 str_offp = ulong_hash_lookup(&ksplice_string_offset, str, TRUE);
1105 *str_offp = (void *)buf - str_ss->contents.data;
1108 write_reloc(ss, addr, &str_ss->symbol, *str_offp);
1111 void lookup_system_map(struct addr_vec *addrs, const char *name, long offset)
1113 struct addr_vec *map_addrs =
1114 addr_vec_hash_lookup(&system_map, name, FALSE);
1115 if (map_addrs == NULL)
1116 return;
1118 unsigned long *addr, *map_addr;
1119 for (map_addr = map_addrs->data;
1120 map_addr < map_addrs->data + map_addrs->size; map_addr++) {
1121 for (addr = addrs->data; addr < addrs->data + addrs->size;
1122 addr++) {
1123 if (*addr == *map_addr + offset)
1124 break;
1126 if (addr < addrs->data + addrs->size)
1127 continue;
1128 *vec_grow(addrs, 1) = *map_addr + offset;
1132 void write_system_map_array(struct superbfd *sbfd, struct supersect *ss,
1133 const unsigned long **sym_addrs,
1134 unsigned long *num_sym_addrs, asymbol *sym)
1136 struct addr_vec addrs;
1137 vec_init(&addrs);
1139 if (bfd_is_abs_section(sym->section)) {
1140 *vec_grow(&addrs, 1) = sym->value;
1141 } else if (bfd_is_und_section(sym->section)) {
1142 lookup_system_map(&addrs, sym->name, 0);
1143 } else if (!bfd_is_const_section(sym->section)) {
1144 asymbol **gsymp;
1145 for (gsymp = sbfd->syms.data;
1146 gsymp < sbfd->syms.data + sbfd->syms.size; gsymp++) {
1147 asymbol *gsym = *gsymp;
1148 if ((gsym->flags & BSF_DEBUGGING) == 0 &&
1149 gsym->section == sym->section)
1150 lookup_system_map(&addrs, gsym->name,
1151 sym->value - gsym->value);
1155 *num_sym_addrs = addrs.size;
1156 if (addrs.size != 0) {
1157 struct supersect *array_ss = make_section(sbfd,
1158 ".ksplice_array");
1159 void *buf = sect_grow(array_ss, addrs.size,
1160 typeof(*addrs.data));
1161 memcpy(buf, addrs.data, addrs.size * sizeof(*addrs.data));
1162 write_reloc(ss, sym_addrs, &array_ss->symbol,
1163 buf - array_ss->contents.data);
1164 } else {
1165 *sym_addrs = NULL;
1168 vec_free(&addrs);
1171 void write_ksplice_system_map(struct superbfd *sbfd, asymbol *sym,
1172 const char *addstr_sect)
1174 struct supersect *smap_ss = make_section(sbfd, ".ksplice_system_map");
1175 struct ksplice_system_map *smap;
1176 const char *label = label_lookup(sbfd, sym);
1178 bool *done = bool_hash_lookup(&system_map_written, label, TRUE);
1179 if (*done)
1180 return;
1181 *done = true;
1183 smap = sect_grow(smap_ss, 1, struct ksplice_system_map);
1185 write_system_map_array(sbfd, smap_ss, &smap->candidates,
1186 &smap->nr_candidates, sym);
1187 write_string(smap_ss, &smap->label, "%s%s", label, addstr_sect);
1190 void write_ksplice_symbol(struct supersect *ss,
1191 const struct ksplice_symbol *const *addr,
1192 asymbol *sym, const char *addstr_sect)
1194 struct supersect *ksymbol_ss = make_section(ss->parent,
1195 ".ksplice_symbols");
1196 struct ksplice_symbol *ksymbol;
1197 unsigned long *ksymbol_offp;
1198 const char *label = label_lookup(ss->parent, sym);
1199 char *output;
1200 assert(asprintf(&output, "%s%s", label, addstr_sect) >= 0);
1202 ksymbol_offp = ulong_hash_lookup(&ksplice_symbol_offset, output, FALSE);
1203 if (ksymbol_offp != NULL) {
1204 write_reloc(ss, addr, &ksymbol_ss->symbol, *ksymbol_offp);
1205 return;
1207 ksymbol = sect_grow(ksymbol_ss, 1, struct ksplice_symbol);
1208 ksymbol_offp = ulong_hash_lookup(&ksplice_symbol_offset, output, TRUE);
1209 *ksymbol_offp = (void *)ksymbol - ksymbol_ss->contents.data;
1211 if (bfd_is_und_section(sym->section) || (sym->flags & BSF_GLOBAL) != 0) {
1212 write_string(ksymbol_ss, &ksymbol->name, "%s", sym->name);
1213 } else if (bfd_is_const_section(sym->section)) {
1214 ksymbol->name = NULL;
1215 } else {
1216 asymbol *gsym = canonical_symbol(ss->parent, sym);
1218 if (gsym == NULL || (gsym->flags & BSF_SECTION_SYM) != 0)
1219 ksymbol->name = NULL;
1220 else
1221 write_string(ksymbol_ss, &ksymbol->name, "%s",
1222 gsym->name);
1225 write_string(ksymbol_ss, &ksymbol->label, "%s%s", label, addstr_sect);
1227 write_ksplice_system_map(ksymbol_ss->parent, sym, addstr_sect);
1229 write_reloc(ss, addr, &ksymbol_ss->symbol, *ksymbol_offp);
1232 void write_ksplice_reloc(struct supersect *ss, arelent *orig_reloc)
1234 asymbol *sym_ptr = *orig_reloc->sym_ptr_ptr;
1235 reloc_howto_type *howto = orig_reloc->howto;
1236 bfd_vma addend = get_reloc_offset(ss, orig_reloc, false);
1238 if (mode("finalize") && starts_with(ss->name, ".ksplice_patches")) {
1239 unsigned long *repladdr =
1240 ss->contents.data + orig_reloc->address;
1241 *repladdr = 0;
1242 return;
1245 blot_section(ss, orig_reloc->address, howto);
1247 struct supersect *kreloc_ss = make_section(ss->parent,
1248 mode("rmsyms") ?
1249 ".ksplice_init_relocs" :
1250 ".ksplice_relocs");
1251 struct ksplice_reloc *kreloc = sect_grow(kreloc_ss, 1,
1252 struct ksplice_reloc);
1254 write_reloc(kreloc_ss, &kreloc->blank_addr,
1255 &ss->symbol, orig_reloc->address);
1256 kreloc->blank_offset = (unsigned long)orig_reloc->address;
1257 write_ksplice_symbol(kreloc_ss, &kreloc->symbol, sym_ptr, "");
1258 kreloc->pcrel = howto->pc_relative;
1259 kreloc->addend = addend;
1260 kreloc->size = bfd_get_reloc_size(howto);
1261 kreloc->dst_mask = howto->dst_mask;
1262 kreloc->rightshift = howto->rightshift;
1263 kreloc->signed_addend =
1264 (howto->complain_on_overflow == complain_overflow_signed) ||
1265 (howto->complain_on_overflow == complain_overflow_bitfield);
1268 #define CANARY(x, canary) ((x & ~howto->dst_mask) | (canary & howto->dst_mask))
1270 void blot_section(struct supersect *ss, int offset, reloc_howto_type *howto)
1272 int bits = bfd_get_reloc_size(howto) * 8;
1273 void *address = ss->contents.data + offset;
1274 bfd_vma x = bfd_get(bits, ss->parent->abfd, address);
1275 x = (x & ~howto->dst_mask) |
1276 ((bfd_vma)KSPLICE_CANARY & howto->dst_mask);
1277 bfd_put(bits, ss->parent->abfd, x, address);
1280 void write_ksplice_section(struct superbfd *sbfd, asymbol **symp)
1282 asymbol *sym = *symp;
1283 struct supersect *ksect_ss = make_section(sbfd, ".ksplice_sections");
1284 struct ksplice_section *ksect = sect_grow(ksect_ss, 1,
1285 struct ksplice_section);
1287 write_ksplice_symbol(ksect_ss, &ksect->symbol, sym,
1288 mode("keep-primary") ? "(post)" : "");
1289 ksect->size = bfd_get_section_size(sym->section);
1290 ksect->flags = 0;
1291 struct supersect *sym_ss = fetch_supersect(sbfd, sym->section);
1292 if (sym_ss->type == SS_TYPE_RODATA)
1293 ksect->flags |= KSPLICE_SECTION_RODATA;
1294 if (sym_ss->type == SS_TYPE_DATA)
1295 ksect->flags |= KSPLICE_SECTION_DATA;
1296 if (sym_ss->type == SS_TYPE_TEXT)
1297 ksect->flags |= KSPLICE_SECTION_TEXT;
1298 assert(ksect->flags != 0);
1299 write_reloc(ksect_ss, &ksect->address, symp, 0);
1302 void write_ksplice_patch(struct superbfd *sbfd, const char *sectname)
1304 struct supersect *kpatch_ss = make_section(sbfd, ".ksplice_patches");
1305 struct ksplice_patch *kpatch = sect_grow(kpatch_ss, 1,
1306 struct ksplice_patch);
1307 asection *sect = bfd_get_section_by_name(sbfd->abfd, sectname);
1308 assert(sect != NULL);
1310 write_string(kpatch_ss, &kpatch->label, "%s",
1311 label_lookup(sbfd, sect->symbol));
1312 write_reloc(kpatch_ss, &kpatch->repladdr, &sect->symbol, 0);
1315 void write_ksplice_deleted_patch(struct superbfd *sbfd, const char *name,
1316 const char *label)
1318 struct supersect *kpatch_ss = make_section(sbfd, ".ksplice_patches");
1319 struct ksplice_patch *kpatch = sect_grow(kpatch_ss, 1,
1320 struct ksplice_patch);
1322 write_string(kpatch_ss, &kpatch->label, "%s", label);
1323 asymbol **symp;
1324 for (symp = sbfd->syms.data; symp < sbfd->syms.data + sbfd->syms.size;
1325 symp++) {
1326 asymbol *sym = *symp;
1327 if (bfd_is_und_section(sym->section) &&
1328 strcmp(name, sym->name) == 0)
1329 break;
1331 if (symp >= sbfd->syms.data + sbfd->syms.size) {
1332 symp = malloc(sizeof(*symp));
1333 *symp = bfd_make_empty_symbol(sbfd->abfd);
1334 asymbol *sym = *symp;
1335 sym->name = strdup(name);
1336 sym->section = bfd_und_section_ptr;
1337 sym->flags = 0;
1338 sym->value = 0;
1339 *vec_grow(&sbfd->new_syms, 1) = symp;
1341 write_reloc(kpatch_ss, &kpatch->repladdr, symp, 0);
1344 void write_ksplice_export(struct superbfd *sbfd, const char *symname,
1345 const char *export_type, bool del)
1347 struct supersect *export_ss = make_section(sbfd, ".ksplice_exports");
1348 struct ksplice_export *exp = sect_grow(export_ss, 1,
1349 struct ksplice_export);
1351 if (del) {
1352 write_string(export_ss, &exp->name, "%s", symname);
1353 write_string(export_ss, &exp->new_name, "DISABLED_%s_%s",
1354 symname, kid);
1355 } else {
1356 write_string(export_ss, &exp->new_name, "%s", symname);
1357 write_string(export_ss, &exp->name, "DISABLED_%s_%s", symname,
1358 kid);
1362 struct fixup_entry {
1363 bfd_vma offset;
1364 bool used;
1365 bfd_vma ex_offset;
1367 DECLARE_VEC_TYPE(struct fixup_entry, fixup_entry_vec);
1369 int compare_fixups(const void *aptr, const void *bptr)
1371 const struct fixup_entry *a = aptr, *b = bptr;
1372 if (a->offset < b->offset)
1373 return -1;
1374 else if (a->offset > b->offset)
1375 return 1;
1376 else
1377 return (int)a->used - (int)b->used;
1380 void filter_table_sections(struct superbfd *isbfd)
1382 struct supersect *tables_ss =
1383 fetch_supersect(offsets_sbfd,
1384 bfd_get_section_by_name(offsets_sbfd->abfd,
1385 ".ksplice_table_sections"));
1386 const struct table_section *ts;
1387 for (ts = tables_ss->contents.data;
1388 (void *)ts < tables_ss->contents.data + tables_ss->contents.size;
1389 ts++) {
1390 struct table_section s = *ts;
1391 s.sect = read_string(tables_ss, &ts->sect);
1392 s.other_sect = read_string(tables_ss, &ts->other_sect);
1393 filter_table_section(isbfd, &s);
1397 void filter_table_section(struct superbfd *sbfd, const struct table_section *s)
1399 asection *isection = bfd_get_section_by_name(sbfd->abfd, s->sect);
1400 if (isection == NULL)
1401 return;
1402 asection *fixup_sect = NULL;
1403 if (s->other_sect != NULL)
1404 fixup_sect = bfd_get_section_by_name(sbfd->abfd, s->other_sect);
1406 struct supersect *ss = fetch_supersect(sbfd, isection), orig_ss;
1407 supersect_move(&orig_ss, ss);
1409 struct supersect *fixup_ss = NULL;
1410 if (fixup_sect != NULL)
1411 fixup_ss = fetch_supersect(sbfd, fixup_sect);
1413 struct fixup_entry_vec fixups;
1414 vec_init(&fixups);
1416 void *orig_entry;
1417 for (orig_entry = orig_ss.contents.data;
1418 orig_entry < orig_ss.contents.data + orig_ss.contents.size;
1419 orig_entry += s->entry_size) {
1420 asymbol *sym, *fixup_sym;
1421 read_reloc(&orig_ss, orig_entry + s->addr_offset,
1422 sizeof(void *), &sym);
1424 struct fixup_entry *f;
1425 if (fixup_sect != NULL) {
1426 bfd_vma fixup_offset =
1427 read_reloc(&orig_ss, orig_entry + s->other_offset,
1428 sizeof(void *), &fixup_sym);
1429 if (fixup_sym->section == fixup_sect) {
1430 assert(fixup_offset < fixup_ss->contents.size);
1431 f = vec_grow(&fixups, 1);
1432 f->offset = fixup_offset;
1433 f->used = false;
1437 struct supersect *sym_ss = fetch_supersect(sbfd, sym->section);
1438 if (!sym_ss->keep)
1439 continue;
1441 if (fixup_sect != NULL && fixup_sym->section == fixup_sect) {
1442 f->used = true;
1443 f->ex_offset = ss->contents.size + s->other_offset;
1445 sect_copy(ss, sect_do_grow(ss, 1, s->entry_size,
1446 s->entry_align),
1447 &orig_ss, orig_entry, s->entry_size);
1450 if (fixup_sect == NULL)
1451 return;
1453 struct supersect orig_fixup_ss;
1454 supersect_move(&orig_fixup_ss, fixup_ss);
1456 qsort(fixups.data, fixups.size, sizeof(*fixups.data), compare_fixups);
1457 *vec_grow(&fixups, 1) = (struct fixup_entry)
1458 { .offset = orig_fixup_ss.contents.size, .used = false };
1460 struct fixup_entry *f;
1461 for (f = fixups.data; f < fixups.data + fixups.size - 1; f++) {
1462 if (!f->used)
1463 continue;
1464 write_reloc(ss, ss->contents.data + f->ex_offset,
1465 &fixup_ss->symbol, fixup_ss->contents.size);
1466 sect_copy(fixup_ss,
1467 sect_grow(fixup_ss, (f + 1)->offset - f->offset,
1468 unsigned char),
1469 &orig_fixup_ss,
1470 orig_fixup_ss.contents.data + f->offset,
1471 (f + 1)->offset - f->offset);
1475 void keep_if_referenced(bfd *abfd, asection *sect, void *ignored)
1477 struct superbfd *sbfd = fetch_superbfd(abfd);
1478 struct supersect *ss = fetch_supersect(sbfd, sect);
1479 if (ss->keep || ss->type == SS_TYPE_IGNORED)
1480 return;
1482 asymbol **symp;
1483 for (symp = sbfd->syms.data;
1484 symp < sbfd->syms.data + sbfd->syms.size; symp++) {
1485 asymbol *sym = *symp;
1486 if (sym->section == sect && (sym->flags & BSF_GLOBAL) != 0) {
1487 ss->keep = true;
1488 changed = true;
1489 return;
1493 bfd_map_over_sections(abfd, check_for_ref_to_section, sect);
1496 void check_for_ref_to_section(bfd *abfd, asection *looking_at,
1497 void *looking_for)
1499 struct superbfd *sbfd = fetch_superbfd(abfd);
1500 struct supersect *ss = fetch_supersect(sbfd, looking_at);
1501 struct supersect *for_ss = fetch_supersect(sbfd,
1502 (asection *)looking_for);
1503 if (!ss->keep || ss->type == SS_TYPE_STRING ||
1504 ss->type == SS_TYPE_SPECIAL || ss->type == SS_TYPE_EXPORT)
1505 return;
1507 arelent **relocp;
1508 for (relocp = ss->relocs.data;
1509 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
1510 asymbol *sym = *(*relocp)->sym_ptr_ptr;
1511 if (sym->section != (asection *)looking_for)
1512 continue;
1513 for_ss->keep = true;
1514 changed = true;
1515 return;
1519 void copy_symbols(struct asymbolp_vec *osyms, struct asymbolpp_vec *isyms)
1521 asymbol ***sympp;
1522 for (sympp = isyms->data; sympp < isyms->data + isyms->size; sympp++)
1523 *vec_grow(osyms, 1) = **sympp;
1526 /* Modified function from GNU Binutils objcopy.c */
1527 bfd_boolean copy_object(bfd *ibfd, bfd *obfd)
1529 assert(bfd_set_format(obfd, bfd_get_format(ibfd)));
1531 bfd_vma start = bfd_get_start_address(ibfd);
1533 flagword flags = bfd_get_file_flags(ibfd);
1534 flags &= bfd_applicable_file_flags(obfd);
1536 assert(bfd_set_start_address(obfd, start)
1537 && bfd_set_file_flags(obfd, flags));
1539 enum bfd_architecture iarch = bfd_get_arch(ibfd);
1540 unsigned int imach = bfd_get_mach(ibfd);
1541 assert(bfd_set_arch_mach(obfd, iarch, imach));
1542 assert(bfd_set_format(obfd, bfd_get_format(ibfd)));
1544 /* BFD mandates that all output sections be created and sizes set before
1545 any output is done. Thus, we traverse all sections multiple times. */
1546 bfd_map_over_sections(ibfd, setup_section, obfd);
1548 struct supersect *new_supersects = fetch_superbfd(ibfd)->new_supersects;
1549 struct supersect *ss;
1550 for (ss = new_supersects; ss != NULL; ss = ss->next)
1551 setup_new_section(obfd, ss);
1553 /* Mark symbols used in output relocations so that they
1554 are kept, even if they are local labels or static symbols.
1556 Note we iterate over the input sections examining their
1557 relocations since the relocations for the output sections
1558 haven't been set yet. mark_symbols_used_in_relocations will
1559 ignore input sections which have no corresponding output
1560 section. */
1562 bfd_map_over_sections(ibfd, mark_symbols_used_in_relocations, NULL);
1563 for (ss = new_supersects; ss != NULL; ss = ss->next)
1564 ss_mark_symbols_used_in_relocations(ss);
1565 struct asymbolp_vec osyms;
1566 vec_init(&osyms);
1567 filter_symbols(ibfd, obfd, &osyms, &fetch_superbfd(ibfd)->syms);
1568 copy_symbols(&osyms, &fetch_superbfd(ibfd)->new_syms);
1570 bfd_set_symtab(obfd, osyms.data, osyms.size);
1572 /* This has to happen after the symbol table has been set. */
1573 bfd_map_over_sections(obfd, write_section, NULL);
1575 /* Allow the BFD backend to copy any private data it understands
1576 from the input BFD to the output BFD. This is done last to
1577 permit the routine to look at the filtered symbol table, which is
1578 important for the ECOFF code at least. */
1579 assert(bfd_copy_private_bfd_data(ibfd, obfd));
1581 return TRUE;
1584 /* Modified function from GNU Binutils objcopy.c */
1585 void setup_section(bfd *ibfd, asection *isection, void *obfdarg)
1587 struct superbfd *isbfd = fetch_superbfd(ibfd);
1588 struct supersect *ss = fetch_supersect(isbfd, isection);
1589 bfd *obfd = obfdarg;
1590 bfd_vma vma;
1592 if (!ss->keep)
1593 return;
1595 asection *osection = bfd_make_section_anyway(obfd, isection->name);
1596 assert(osection != NULL);
1598 osection->userdata = ss;
1599 bfd_set_section_flags(obfd, osection, ss->flags);
1600 ss->symbol = osection->symbol;
1601 assert(bfd_set_section_size(obfd, osection, ss->contents.size));
1603 vma = bfd_section_vma(ibfd, isection);
1604 assert(bfd_set_section_vma(obfd, osection, vma));
1606 osection->lma = isection->lma;
1607 assert(bfd_set_section_alignment(obfd, osection, ss->alignment));
1608 osection->entsize = isection->entsize;
1609 osection->output_section = osection;
1610 osection->output_offset = 0;
1611 isection->output_section = osection;
1612 isection->output_offset = 0;
1613 return;
1616 void setup_new_section(bfd *obfd, struct supersect *ss)
1618 asection *osection = bfd_make_section_anyway(obfd, ss->name);
1619 assert(osection != NULL);
1620 bfd_set_section_flags(obfd, osection, ss->flags);
1622 osection->userdata = ss;
1623 ss->symbol = osection->symbol;
1624 assert(bfd_set_section_size(obfd, osection, ss->contents.size));
1625 assert(bfd_set_section_vma(obfd, osection, 0));
1627 osection->lma = 0;
1628 assert(bfd_set_section_alignment(obfd, osection, ss->alignment));
1629 osection->entsize = 0;
1630 osection->output_section = osection;
1631 osection->output_offset = 0;
1634 void write_section(bfd *obfd, asection *osection, void *arg)
1636 struct supersect *ss = osection->userdata;
1638 if ((ss->flags & SEC_GROUP) != 0 || ss->contents.size == 0)
1639 return;
1641 arelent **relocp;
1642 char *error_message;
1643 for (relocp = ss->new_relocs.data;
1644 relocp < ss->new_relocs.data + ss->new_relocs.size; relocp++) {
1645 bfd_vma val;
1646 if (bfd_get_arch(obfd) == bfd_arch_arm)
1647 val = osection->use_rela_p ? 0 : (*relocp)->addend;
1648 else
1649 val = 0;
1650 bfd_put(bfd_get_reloc_size((*relocp)->howto) * 8, obfd, val,
1651 ss->contents.data + (*relocp)->address);
1652 if (bfd_install_relocation(obfd, *relocp, ss->contents.data,
1653 0, osection, &error_message) !=
1654 bfd_reloc_ok) {
1655 err(ss->parent, "ksplice: error installing reloc: %s",
1656 error_message);
1657 DIE;
1660 memcpy(vec_grow(&ss->relocs, ss->new_relocs.size), ss->new_relocs.data,
1661 ss->new_relocs.size * sizeof(*ss->new_relocs.data));
1663 bfd_set_reloc(obfd, osection,
1664 ss->relocs.size == 0 ? NULL : ss->relocs.data,
1665 ss->relocs.size);
1667 if (ss->flags & SEC_HAS_CONTENTS)
1668 assert(bfd_set_section_contents
1669 (obfd, osection, ss->contents.data, 0,
1670 ss->contents.size));
1673 /* Modified function from GNU Binutils objcopy.c
1675 * Mark all the symbols which will be used in output relocations with
1676 * the BSF_KEEP flag so that those symbols will not be stripped.
1678 * Ignore relocations which will not appear in the output file.
1680 void mark_symbols_used_in_relocations(bfd *abfd, asection *isection,
1681 void *ignored)
1683 struct superbfd *sbfd = fetch_superbfd(abfd);
1684 if (isection->output_section == NULL)
1685 return;
1687 struct supersect *ss = fetch_supersect(sbfd, isection);
1688 ss_mark_symbols_used_in_relocations(ss);
1691 void ss_mark_symbols_used_in_relocations(struct supersect *ss)
1693 /* Examine each symbol used in a relocation. If it's not one of the
1694 special bfd section symbols, then mark it with BSF_KEEP. */
1695 arelent **relocp;
1696 for (relocp = ss->relocs.data;
1697 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
1698 asymbol *sym = *(*relocp)->sym_ptr_ptr;
1699 if (!(bfd_is_const_section(sym->section) &&
1700 sym == sym->section->symbol))
1701 sym->flags |= BSF_KEEP;
1703 for (relocp = ss->new_relocs.data;
1704 relocp < ss->new_relocs.data + ss->new_relocs.size; relocp++) {
1705 asymbol *sym = *(*relocp)->sym_ptr_ptr;
1706 if (!(bfd_is_const_section(sym->section) &&
1707 sym == sym->section->symbol))
1708 sym->flags |= BSF_KEEP;
1712 static bool deleted_table_section_symbol(bfd *abfd, asymbol *sym)
1714 struct superbfd *sbfd = fetch_superbfd(abfd);
1715 if (bfd_is_const_section(sym->section))
1716 return false;
1717 struct supersect *ss = fetch_supersect(sbfd, sym->section);
1719 asymbol **symp;
1720 for (symp = ss->syms.data; symp < ss->syms.data + ss->syms.size; symp++) {
1721 if (sym == *symp)
1722 break;
1724 return symp >= ss->syms.data + ss->syms.size;
1727 /* Modified function from GNU Binutils objcopy.c
1729 * Choose which symbol entries to copy.
1730 * We don't copy in place, because that confuses the relocs.
1731 * Return the number of symbols to print.
1733 void filter_symbols(bfd *ibfd, bfd *obfd, struct asymbolp_vec *osyms,
1734 struct asymbolp_vec *isyms)
1736 asymbol **symp;
1737 struct superbfd *sbfd = fetch_superbfd(ibfd);
1738 for (symp = isyms->data; symp < isyms->data + isyms->size; symp++) {
1739 asymbol *sym = *symp;
1740 struct supersect *sym_ss = NULL;
1741 if (!bfd_is_const_section(sym->section))
1742 sym_ss = fetch_supersect(sbfd, sym->section);
1744 bool keep = false;
1746 if (mode("keep") && (sym->flags & BSF_GLOBAL) != 0 &&
1747 !(mode("keep-primary") && sym_ss != NULL && sym_ss->new))
1748 sym->flags = (sym->flags & ~BSF_GLOBAL) | BSF_LOCAL;
1750 if (mode("finalize") && (sym->flags & BSF_GLOBAL) != 0)
1751 sym->flags = (sym->flags & ~BSF_GLOBAL) | BSF_LOCAL;
1753 if ((sym->flags & BSF_KEEP) != 0 /* Used in relocation. */
1754 || ((sym->flags & BSF_SECTION_SYM) != 0 && sym_ss != NULL &&
1755 sym_ss->keep))
1756 keep = true;
1757 else if ((sym->flags & (BSF_GLOBAL | BSF_WEAK)) != 0 &&
1758 sym_ss != NULL && sym_ss->keep)
1759 keep = true;
1760 else if (mode("keep-primary") &&
1761 starts_with(sym->section->name, "__ksymtab"))
1762 keep = true;
1764 if (deleted_table_section_symbol(ibfd, sym))
1765 keep = false;
1767 if (bfd_is_com_section(sym->section))
1768 keep = false;
1770 if (mode("rmsyms"))
1771 keep = !str_in_set(sym->name, &rmsyms);
1773 if (keep) {
1774 assert(sym_ss == NULL || sym_ss->keep);
1775 *vec_grow(osyms, 1) = sym;
1780 void read_str_set(struct str_vec *strs)
1782 char *buf = NULL;
1783 size_t n = 0;
1784 assert(getline(&buf, &n, stdin) >= 0);
1785 vec_init(strs);
1786 char *saveptr;
1787 while (1) {
1788 char *str = strtok_r(buf, " \n", &saveptr);
1789 buf = NULL;
1790 if (str == NULL)
1791 break;
1792 *vec_grow(strs, 1) = str;
1796 bool str_in_set(const char *str, const struct str_vec *strs)
1798 const char **strp;
1799 for (strp = strs->data; strp < strs->data + strs->size; strp++) {
1800 if (strcmp(str, *strp) == 0)
1801 return true;
1803 return false;
1806 bool is_table_section(const char *name, bool consider_other)
1808 struct supersect *tables_ss =
1809 fetch_supersect(offsets_sbfd,
1810 bfd_get_section_by_name(offsets_sbfd->abfd,
1811 ".ksplice_table_sections"));
1812 const struct table_section *ts;
1813 for (ts = tables_ss->contents.data;
1814 (void *)ts < tables_ss->contents.data + tables_ss->contents.size;
1815 ts++) {
1816 if (strcmp(name, read_string(tables_ss, &ts->sect)) == 0)
1817 return true;
1818 const char *osect_name = read_string(tables_ss,
1819 &ts->other_sect);
1820 if (consider_other && osect_name != NULL &&
1821 strcmp(name, osect_name) == 0)
1822 return true;
1824 return false;
1827 enum supersect_type supersect_type(struct supersect *ss)
1829 if (starts_with(ss->name, ".ksplice"))
1830 return SS_TYPE_KSPLICE;
1832 if (starts_with(ss->name, ".init"))
1833 return SS_TYPE_IGNORED;
1834 if (starts_with(ss->name, ".security_initcall.init"))
1835 return SS_TYPE_IGNORED;
1836 if (starts_with(ss->name, ".con_initcall.init"))
1837 return SS_TYPE_IGNORED;
1838 if (starts_with(ss->name, ".x86cpuvendor.init"))
1839 return SS_TYPE_IGNORED;
1840 if (starts_with(ss->name, ".early_param.init"))
1841 return SS_TYPE_IGNORED;
1842 if (starts_with(ss->name, ".taglist.init"))
1843 return SS_TYPE_IGNORED;
1844 if (starts_with(ss->name, ".arch.info.init"))
1845 return SS_TYPE_IGNORED;
1846 if (starts_with(ss->name, ".proc.info.init"))
1847 return SS_TYPE_IGNORED;
1848 /* .pci_fixup_* sections really should be treated as global rodata
1849 referenced only from quirks.c */
1850 if (starts_with(ss->name, ".pci_fixup_"))
1851 return SS_TYPE_IGNORED;
1852 /* .builtin_fw sections are similar to .pci_fixup */
1853 if (starts_with(ss->name, ".builtin_fw"))
1854 return SS_TYPE_IGNORED;
1855 /* same for .tracedata */
1856 if (starts_with(ss->name, ".tracedata"))
1857 return SS_TYPE_IGNORED;
1858 if (starts_with(ss->name, ".debug"))
1859 return SS_TYPE_IGNORED;
1860 /* .eh_frame should probably be discarded, not ignored */
1861 if (starts_with(ss->name, ".eh_frame"))
1862 return SS_TYPE_IGNORED;
1863 if (config->ignore_devinit && starts_with(ss->name, ".devinit"))
1864 return SS_TYPE_IGNORED;
1865 if (config->ignore_meminit && starts_with(ss->name, ".meminit"))
1866 return SS_TYPE_IGNORED;
1867 if (config->ignore_cpuinit && starts_with(ss->name, ".cpuinit"))
1868 return SS_TYPE_IGNORED;
1869 if (config->ignore_devinit && starts_with(ss->name, ".devexit"))
1870 return SS_TYPE_IGNORED;
1871 if (config->ignore_meminit && starts_with(ss->name, ".memexit"))
1872 return SS_TYPE_IGNORED;
1873 if (config->ignore_cpuinit && starts_with(ss->name, ".cpuexit"))
1874 return SS_TYPE_IGNORED;
1875 if (starts_with(ss->name, ".vgetcpu_mode") ||
1876 starts_with(ss->name, ".jiffies") ||
1877 starts_with(ss->name, ".wall_jiffies") ||
1878 starts_with(ss->name, ".vxtime") ||
1879 starts_with(ss->name, ".sys_tz") ||
1880 starts_with(ss->name, ".sysctl_vsyscall") ||
1881 starts_with(ss->name, ".xtime") ||
1882 starts_with(ss->name, ".xtime_lock") ||
1883 starts_with(ss->name, ".vsyscall"))
1884 return SS_TYPE_IGNORED;
1885 if (starts_with(ss->name, ".vdso"))
1886 return SS_TYPE_IGNORED;
1888 if (bfd_get_section_by_name(ss->parent->abfd, ".exitcall.exit") == NULL) {
1889 if (starts_with(ss->name, ".exit.text"))
1890 return SS_TYPE_TEXT;
1891 if (starts_with(ss->name, ".exit.data"))
1892 return SS_TYPE_DATA;
1893 } else if (starts_with(ss->name, ".exit.text") ||
1894 starts_with(ss->name, ".exit.data"))
1895 return SS_TYPE_IGNORED;
1897 if (starts_with(ss->name, ".text") ||
1898 starts_with(ss->name, ".kernel.text") ||
1899 starts_with(ss->name, ".devinit.text") ||
1900 starts_with(ss->name, ".meminit.text") ||
1901 starts_with(ss->name, ".cpuinit.text") ||
1902 starts_with(ss->name, ".devexit.text") ||
1903 starts_with(ss->name, ".memexit.text") ||
1904 starts_with(ss->name, ".cpuexit.text") ||
1905 starts_with(ss->name, ".ref.text") ||
1906 starts_with(ss->name, ".spinlock.text") ||
1907 starts_with(ss->name, ".kprobes.text") ||
1908 starts_with(ss->name, ".sched.text"))
1909 return SS_TYPE_TEXT;
1911 int n = -1;
1912 if (sscanf(ss->name, ".rodata.str%*u.%*u%n", &n) >= 0 &&
1913 n == strlen(ss->name))
1914 return SS_TYPE_STRING;
1916 if (starts_with(ss->name, ".rodata") ||
1917 starts_with(ss->name, ".kernel.rodata") ||
1918 starts_with(ss->name, ".devinit.rodata") ||
1919 starts_with(ss->name, ".meminit.rodata") ||
1920 starts_with(ss->name, ".cpuinit.rodata") ||
1921 starts_with(ss->name, ".devexit.rodata") ||
1922 starts_with(ss->name, ".memexit.rodata") ||
1923 starts_with(ss->name, ".cpuexit.rodata") ||
1924 starts_with(ss->name, ".ref.rodata") ||
1925 starts_with(ss->name, "__markers_strings"))
1926 return SS_TYPE_RODATA;
1928 if (starts_with(ss->name, ".bss"))
1929 return SS_TYPE_DATA;
1931 /* Ignore .data.percpu sections */
1932 if (starts_with(ss->name, ".data.percpu") ||
1933 starts_with(ss->name, ".kernel.data.percpu"))
1934 return SS_TYPE_IGNORED;
1935 if (starts_with(ss->name, ".data") ||
1936 starts_with(ss->name, ".kernel.data") ||
1937 starts_with(ss->name, ".devinit.data") ||
1938 starts_with(ss->name, ".cpuinit.data") ||
1939 starts_with(ss->name, ".meminit.data") ||
1940 starts_with(ss->name, ".devexit.data") ||
1941 starts_with(ss->name, ".memexit.data") ||
1942 starts_with(ss->name, ".cpuexit.data") ||
1943 starts_with(ss->name, ".ref.data") ||
1944 starts_with(ss->name, "__markers"))
1945 return SS_TYPE_DATA;
1947 if (starts_with(ss->name, "__ksymtab"))
1948 return SS_TYPE_EXPORT;
1949 if (starts_with(ss->name, "__kcrctab"))
1950 return SS_TYPE_EXPORT;
1952 if (is_table_section(ss->name, true))
1953 return SS_TYPE_SPECIAL;
1955 if (starts_with(ss->name, ".ARM."))
1956 return SS_TYPE_SPECIAL;
1958 if (starts_with(ss->name, ".note"))
1959 return SS_TYPE_IGNORED;
1960 if (starts_with(ss->name, ".comment"))
1961 return SS_TYPE_IGNORED;
1962 if (starts_with(ss->name, "__param"))
1963 return SS_TYPE_IGNORED;
1964 if (starts_with(ss->name, ".exitcall.exit"))
1965 return SS_TYPE_IGNORED;
1966 if (starts_with(ss->name, ".modinfo"))
1967 return SS_TYPE_IGNORED;
1969 return SS_TYPE_UNKNOWN;
1972 void initialize_supersect_types(struct superbfd *sbfd)
1974 asection *sect;
1975 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
1976 struct supersect *ss = fetch_supersect(sbfd, sect);
1977 ss->type = supersect_type(ss);
1978 if (ss->type == SS_TYPE_UNKNOWN) {
1979 err(sbfd, "Unknown section type: %s\n", ss->name);
1980 DIE;
1985 static void init_label_map(struct superbfd *sbfd)
1987 vec_init(&sbfd->maps);
1988 struct label_map *map, *map2;
1990 asymbol **symp;
1991 for (symp = sbfd->syms.data;
1992 symp < sbfd->syms.data + sbfd->syms.size; symp++) {
1993 asymbol *csym = canonical_symbol(sbfd, *symp);
1994 if (csym == NULL)
1995 continue;
1996 for (map = sbfd->maps.data;
1997 map < sbfd->maps.data + sbfd->maps.size; map++) {
1998 if (map->csym == csym)
1999 break;
2001 if (map < sbfd->maps.data + sbfd->maps.size)
2002 continue;
2003 map = vec_grow(&sbfd->maps, 1);
2004 map->csym = csym;
2005 map->count = 0;
2006 map->index = 0;
2007 map->label = symbol_label(sbfd, csym);
2009 for (map = sbfd->maps.data;
2010 map < sbfd->maps.data + sbfd->maps.size; map++) {
2011 for (map2 = sbfd->maps.data;
2012 map2 < sbfd->maps.data + sbfd->maps.size; map2++) {
2013 if (strcmp(map->label, map2->label) != 0)
2014 continue;
2015 map->count++;
2016 if (map2 < map)
2017 map->index++;
2021 for (map = sbfd->maps.data;
2022 map < sbfd->maps.data + sbfd->maps.size; map++) {
2023 if (map->count > 1) {
2024 char *buf;
2025 assert(asprintf(&buf, "%s~%d", map->label,
2026 map->index) >= 0);
2027 map->label = buf;
2029 map->orig_label = map->label;
2033 static const char *label_lookup(struct superbfd *sbfd, asymbol *sym)
2035 struct label_map *map;
2036 asymbol *csym = canonical_symbol(sbfd, sym);
2037 for (map = sbfd->maps.data;
2038 map < sbfd->maps.data + sbfd->maps.size; map++) {
2039 if (csym == map->csym)
2040 return map->label;
2042 return symbol_label(sbfd, sym);
2045 static void print_label_map(struct superbfd *sbfd)
2047 struct label_map *map;
2048 for (map = sbfd->maps.data;
2049 map < sbfd->maps.data + sbfd->maps.size; map++) {
2050 if (strcmp(map->orig_label, map->label) == 0)
2051 continue;
2052 debug1(sbfd, "Label change: %s -> %s\n",
2053 map->label, map->orig_label);
2057 static void label_map_set(struct superbfd *sbfd, const char *oldlabel,
2058 const char *label)
2060 struct label_map *map;
2061 for (map = sbfd->maps.data;
2062 map < sbfd->maps.data + sbfd->maps.size; map++) {
2063 if (strcmp(map->orig_label, oldlabel) == 0) {
2064 if (strcmp(map->orig_label, map->label) != 0 &&
2065 strcmp(map->label, label) != 0)
2066 DIE;
2067 map->label = label;
2068 return;
2071 DIE;