Actually throw an error if libbfd is not found.
[ksplice.git] / objmanip.c
blob083516eed21a3f4193a7d2813bb49864b58eace9
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 struct str_vec delsects, rmsyms;
162 struct export_desc_vec exports;
163 bool changed;
165 struct ksplice_config *config;
167 const char *modestr, *kid;
169 struct superbfd *offsets_sbfd = NULL;
171 #define mode(str) starts_with(modestr, str)
173 DECLARE_VEC_TYPE(unsigned long, addr_vec);
174 DEFINE_HASH_TYPE(struct addr_vec, addr_vec_hash,
175 addr_vec_hash_init, addr_vec_hash_free, addr_vec_hash_lookup,
176 vec_init);
177 struct addr_vec_hash system_map;
179 struct bool_hash system_map_written;
180 struct ulong_hash ksplice_symbol_offset;
181 struct ulong_hash ksplice_string_offset;
183 void load_system_map()
185 const char *config_dir = getenv("KSPLICE_CONFIG_DIR");
186 assert(config_dir);
187 char *file;
188 assert(asprintf(&file, "%s/System.map", config_dir) >= 0);
189 FILE *fp = fopen(file, "r");
190 assert(fp);
191 addr_vec_hash_init(&system_map);
192 unsigned long addr;
193 char type;
194 char *sym;
195 while (fscanf(fp, "%lx %c %as\n", &addr, &type, &sym) == 3)
196 *vec_grow(addr_vec_hash_lookup(&system_map, sym, TRUE),
197 1) = addr;
198 fclose(fp);
201 void load_offsets()
203 char *kmodsrc = getenv("KSPLICE_KMODSRC"), *offsets_file;
204 assert(kmodsrc != NULL);
205 assert(asprintf(&offsets_file, "%s/offsets.o", kmodsrc) >= 0);
206 bfd *offsets_bfd = bfd_openr(offsets_file, NULL);
207 assert(offsets_bfd != NULL);
208 char **matching;
209 assert(bfd_check_format_matches(offsets_bfd, bfd_object, &matching));
210 offsets_sbfd = fetch_superbfd(offsets_bfd);
212 asection *config_sect = bfd_get_section_by_name(offsets_sbfd->abfd,
213 ".ksplice_config");
214 struct supersect *config_ss =
215 fetch_supersect(offsets_sbfd, config_sect);
217 config = config_ss->contents.data;
220 bool matchable_data_section(struct supersect *ss)
222 if (ss->type == SS_TYPE_RODATA)
223 return true;
224 if (ss->type == SS_TYPE_DATA && ss->relocs.size != 0)
225 return true;
226 return false;
229 bool unchangeable_section(struct supersect *ss)
231 if (ss->type == SS_TYPE_DATA)
232 return true;
233 if (ss->type == SS_TYPE_IGNORED && !starts_with(ss->name, ".debug"))
234 return true;
235 return false;
238 int main(int argc, char *argv[])
240 bfd_init();
241 bfd *ibfd = bfd_openr(argv[1], NULL);
242 assert(ibfd);
244 char **matching;
245 assert(bfd_check_format_matches(ibfd, bfd_object, &matching));
247 const char *output_target = bfd_get_target(ibfd);
248 bfd *obfd = bfd_openw(argv[2], output_target);
249 assert(obfd);
251 struct superbfd *isbfd = fetch_superbfd(ibfd);
253 bool_hash_init(&system_map_written);
254 ulong_hash_init(&ksplice_symbol_offset);
255 ulong_hash_init(&ksplice_string_offset);
257 modestr = argv[3];
258 if (mode("keep-primary")) {
259 kid = argv[5];
260 do_keep_primary(isbfd, argv[4]);
261 } else if (mode("keep-helper")) {
262 do_keep_helper(isbfd);
263 } else if (mode("finalize")) {
264 do_finalize(isbfd);
265 } else if (mode("rmsyms")) {
266 do_rmsyms(isbfd);
269 copy_object(ibfd, obfd);
271 if (offsets_sbfd != NULL)
272 assert(bfd_close(offsets_sbfd->abfd));
273 assert(bfd_close(obfd));
274 assert(bfd_close(ibfd));
275 return EXIT_SUCCESS;
278 void do_keep_primary(struct superbfd *isbfd, const char *pre)
280 struct bfd *prebfd = bfd_openr(pre, NULL);
281 assert(prebfd != NULL);
282 char **matching;
283 assert(bfd_check_format_matches(prebfd, bfd_object, &matching));
285 struct superbfd *presbfd = fetch_superbfd(prebfd);
286 load_system_map();
287 load_offsets();
288 initialize_supersect_types(isbfd);
289 initialize_supersect_types(presbfd);
291 match_global_symbol_sections(presbfd, isbfd);
292 printf("Matched global\n");
293 match_sections_by_name(presbfd, isbfd);
294 printf("Matched by name\n");
295 match_sections_by_label(presbfd, isbfd);
296 printf("Matched by label\n");
297 match_sections_by_contents(presbfd, isbfd);
298 printf("Matched by contents\n");
300 do {
301 changed = false;
302 compare_matched_sections(isbfd);
303 update_nonzero_offsets(isbfd);
304 mark_new_sections(isbfd);
305 } while (changed);
306 vec_init(&delsects);
308 handle_deleted_sections(presbfd, isbfd);
309 handle_section_symbol_renames(presbfd, isbfd);
311 vec_init(&exports);
312 compare_exported_symbols(presbfd, isbfd, "");
313 compare_exported_symbols(isbfd, presbfd, "del_");
315 assert(bfd_close(prebfd));
317 asection *sect;
318 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
319 struct supersect *ss = fetch_supersect(isbfd, sect);
320 ss->keep = false;
321 if (ss->type == SS_TYPE_STRING || ss->type == SS_TYPE_SPECIAL ||
322 ss->type == SS_TYPE_EXPORT)
323 ss->keep = true;
324 if (ss->new || ss->patch)
325 ss->keep = true;
328 const char **sectname;
329 printf("Label name changes:\n");
330 print_label_map(isbfd);
332 printf("Changed text sections:\n");
333 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
334 struct supersect *ss = fetch_supersect(isbfd, sect);
335 if (ss->patch)
336 printf(" %s\n", sect->name);
339 printf("New sections:\n");
340 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
341 struct supersect *ss = fetch_supersect(isbfd, sect);
342 if (ss->new)
343 printf(" %s\n", sect->name);
345 if (delsects.size != 0) {
346 printf("Deleted section names:\n");
347 for (sectname = delsects.data;
348 sectname < delsects.data + delsects.size; sectname++)
349 printf(" %s\n", *sectname);
351 const struct export_desc *ed;
352 for (ed = exports.data; ed < exports.data + exports.size; ed++) {
353 const char **symname;
354 bool del = starts_with(ed->sectname, "del___ksymtab");
355 const char *export_type = ed->sectname + strlen("__ksymtab");
356 if (del)
357 export_type += strlen("_del");
358 for (symname = ed->names.data;
359 symname < ed->names.data + ed->names.size; symname++)
360 printf("Export %s(%s): %s\n",
361 del ? "deletion" : "addition",
362 export_type, *symname);
365 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
366 struct supersect *ss = fetch_supersect(isbfd, sect);
367 if (!ss->patch && !ss->new)
368 continue;
369 asymbol **symp = canonical_symbolp(isbfd, sect->symbol);
370 if (symp == NULL)
371 DIE;
372 write_ksplice_section(isbfd, symp);
373 if (ss->patch)
374 write_ksplice_patch(isbfd, sect->name);
377 for (ed = exports.data; ed < exports.data + exports.size; ed++) {
378 if (starts_with(ed->sectname, "del___ksymtab")) {
379 const char *export_type =
380 ed->sectname + strlen("del___ksymtab");
381 const char **symname;
382 for (symname = ed->names.data;
383 symname < ed->names.data + ed->names.size;
384 symname++)
385 write_ksplice_export(isbfd, *symname,
386 export_type, true);
387 } else {
388 rm_some_exports(isbfd, ed);
392 rm_relocs(isbfd);
393 filter_table_sections(isbfd);
396 void do_keep_helper(struct superbfd *isbfd)
398 load_system_map();
399 load_offsets();
400 initialize_supersect_types(isbfd);
402 asection *sect;
403 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
404 struct supersect *ss = fetch_supersect(isbfd, sect);
405 ss->keep = false;
406 if (ss->type == SS_TYPE_STRING || ss->type == SS_TYPE_SPECIAL ||
407 ss->type == SS_TYPE_TEXT)
408 ss->keep = true;
410 do {
411 changed = false;
412 bfd_map_over_sections(isbfd->abfd, keep_if_referenced, NULL);
413 } while (changed);
415 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
416 struct supersect *ss = fetch_supersect(isbfd, sect);
417 asymbol **symp = canonical_symbolp(isbfd, sect->symbol);
418 if (symp == NULL)
419 continue;
420 asymbol *sym = *symp;
421 if ((sym->flags & BSF_WEAK) != 0)
422 continue;
423 if (bfd_get_section_size(sect) == 0)
424 continue;
425 if (ss->keep && (ss->type == SS_TYPE_TEXT ||
426 matchable_data_section(ss)))
427 write_ksplice_section(isbfd, symp);
430 rm_relocs(isbfd);
431 filter_table_sections(isbfd);
434 void do_finalize(struct superbfd *isbfd)
436 load_system_map();
437 load_offsets();
438 initialize_supersect_types(isbfd);
439 rm_relocs(isbfd);
442 void do_rmsyms(struct superbfd *isbfd)
444 read_str_set(&rmsyms);
445 load_system_map();
446 load_offsets();
447 initialize_supersect_types(isbfd);
448 rm_relocs(isbfd);
451 struct export_vec *get_export_syms(struct superbfd *sbfd)
453 asection *sect;
454 struct export_vec *exports;
455 exports = malloc(sizeof(*exports));
456 assert(exports != NULL);
457 vec_init(exports);
459 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
460 if (!starts_with(sect->name, "__ksymtab") ||
461 ends_with(sect->name, "_strings"))
462 continue;
463 struct supersect *ss = fetch_supersect(sbfd, sect);
464 struct kernel_symbol *sym;
465 assert(ss->contents.size * 2 == ss->relocs.size *
466 sizeof(struct kernel_symbol));
467 for (sym = ss->contents.data;
468 (void *)sym < ss->contents.data + ss->contents.size;
469 sym++) {
470 struct export *exp = vec_grow(exports, 1);
471 exp->name =
472 read_string(ss, (const char *const *)&sym->name);
473 exp->sect = sect;
476 return exports;
479 void compare_exported_symbols(struct superbfd *oldsbfd,
480 struct superbfd *newsbfd, char *addstr)
482 struct export_vec *new_exports, *old_exports;
483 new_exports = get_export_syms(newsbfd);
484 if (new_exports == NULL)
485 return;
486 old_exports = get_export_syms(oldsbfd);
487 struct export *old, *new;
488 asection *last_sect = NULL;
489 struct export_desc *ed;
490 for (new = new_exports->data; new < new_exports->data +
491 new_exports->size; new++) {
492 bool found = false;
493 if (old_exports != NULL) {
494 for (old = old_exports->data; old < old_exports->data +
495 old_exports->size; old++) {
496 if (strcmp(new->name, old->name) == 0 &&
497 strcmp(new->sect->name, old->sect->name)
498 == 0) {
499 found = true;
500 break;
504 if (last_sect != new->sect) {
505 last_sect = new->sect;
506 ed = vec_grow(&exports, 1);
507 char *sectname;
508 assert(asprintf(&sectname, "%s%s", addstr,
509 new->sect->name) >= 0);
510 ed->sectname = sectname;
511 vec_init(&ed->names);
513 if (!found)
514 *vec_grow(&ed->names, 1) = new->name;
518 void match_sections(struct supersect *oldss, struct supersect *newss)
520 if (oldss->match == newss && newss->match == oldss)
521 return;
522 if (oldss->match != NULL) {
523 fprintf(stderr, "Matching conflict: old %s: %s != %s\n",
524 oldss->name, oldss->match->name, newss->name);
525 DIE;
527 if (newss->match != NULL) {
528 fprintf(stderr, "Matching conflict: new %s: %s != %s\n",
529 newss->name, newss->match->name, oldss->name);
530 DIE;
532 oldss->match = newss;
533 newss->match = oldss;
534 printf("Matched old %s to new %s\n", oldss->name, newss->name);
537 static void match_global_symbol_sections(struct superbfd *oldsbfd,
538 struct superbfd *newsbfd)
540 asymbol **oldsymp, **newsymp;
541 for (oldsymp = oldsbfd->syms.data;
542 oldsymp < oldsbfd->syms.data + oldsbfd->syms.size; oldsymp++) {
543 asymbol *oldsym = *oldsymp;
544 if ((oldsym->flags & BSF_GLOBAL) == 0 ||
545 bfd_is_const_section(oldsym->section))
546 continue;
547 for (newsymp = newsbfd->syms.data;
548 newsymp < newsbfd->syms.data + newsbfd->syms.size;
549 newsymp++) {
550 asymbol *newsym = *newsymp;
551 if ((newsym->flags & BSF_GLOBAL) == 0 ||
552 bfd_is_const_section(oldsym->section))
553 continue;
554 if (strcmp(oldsym->name, newsym->name) != 0)
555 continue;
556 struct supersect *oldss =
557 fetch_supersect(oldsbfd, oldsym->section);
558 struct supersect *newss =
559 fetch_supersect(newsbfd, newsym->section);
560 match_sections(oldss, newss);
565 static void match_sections_by_name(struct superbfd *oldsbfd,
566 struct superbfd *newsbfd)
568 asection *newp, *oldp;
569 for (newp = newsbfd->abfd->sections; newp != NULL; newp = newp->next) {
570 struct supersect *newss = fetch_supersect(newsbfd, newp);
571 oldp = bfd_get_section_by_name(oldsbfd->abfd, newp->name);
572 if (oldp == NULL || newss->type == SS_TYPE_STRING ||
573 newss->type == SS_TYPE_SPECIAL ||
574 newss->type == SS_TYPE_EXPORT)
575 continue;
576 if (static_local_symbol(newsbfd,
577 canonical_symbol(newsbfd,
578 newp->symbol)))
579 continue;
581 struct supersect *oldss = fetch_supersect(oldsbfd, oldp);
582 match_sections(oldss, newss);
586 static void match_sections_by_label(struct superbfd *oldsbfd,
587 struct superbfd *newsbfd)
589 asection *oldsect, *newsect;
590 struct supersect *oldss, *newss;
591 for (newsect = newsbfd->abfd->sections; newsect != NULL;
592 newsect = newsect->next) {
593 newss = fetch_supersect(newsbfd, newsect);
594 if (newss->type == SS_TYPE_STRING ||
595 newss->type == SS_TYPE_SPECIAL ||
596 newss->type == SS_TYPE_EXPORT)
597 continue;
598 for (oldsect = oldsbfd->abfd->sections; oldsect != NULL;
599 oldsect = oldsect->next) {
600 if (strcmp(label_lookup(newsbfd, newsect->symbol),
601 label_lookup(oldsbfd, oldsect->symbol)) != 0)
602 continue;
603 oldss = fetch_supersect(oldsbfd, oldsect);
604 match_sections(oldss, newss);
609 static void match_sections_by_contents(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_RODATA)
618 continue;
619 for (oldsect = oldsbfd->abfd->sections; oldsect != NULL;
620 oldsect = oldsect->next) {
621 oldss = fetch_supersect(oldsbfd, oldsect);
622 if (oldss->type != SS_TYPE_RODATA)
623 continue;
624 if (oldss->relocs.size != 0 || newss->relocs.size != 0)
625 continue;
626 if (oldss->contents.size != newss->contents.size)
627 continue;
628 if (memcmp(oldss->contents.data, newss->contents.data,
629 oldss->contents.size) != 0)
630 continue;
631 match_sections(oldss, newss);
636 static void mark_new_sections(struct superbfd *sbfd)
638 asection *sect;
639 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
640 struct supersect *ss = fetch_supersect(sbfd, sect);
641 if (ss->type == SS_TYPE_STRING || ss->type == SS_TYPE_SPECIAL ||
642 ss->type == SS_TYPE_IGNORED || ss->type == SS_TYPE_EXPORT)
643 continue;
644 if (ss->match == NULL)
645 ss->new = true;
649 static void handle_deleted_sections(struct superbfd *oldsbfd,
650 struct superbfd *newsbfd)
652 asection *sect;
653 for (sect = oldsbfd->abfd->sections; sect != NULL; sect = sect->next) {
654 struct supersect *ss = fetch_supersect(oldsbfd, sect);
655 if (ss->type != SS_TYPE_TEXT)
656 continue;
657 if (ss->match != NULL)
658 continue;
659 const char *label = label_lookup(oldsbfd, sect->symbol);
660 *vec_grow(&delsects, 1) = label;
661 asymbol *csym = canonical_symbol(oldsbfd, sect->symbol);
662 write_ksplice_deleted_patch(newsbfd, csym->name, label);
666 static void handle_nonzero_offset_relocs(struct supersect *ss)
668 int i;
669 for (i = 0; i < ss->relocs.size; i++) {
670 asymbol *sym = *ss->relocs.data[i]->sym_ptr_ptr;
671 bfd_vma offset = get_reloc_offset(ss, ss->relocs.data[i], true);
672 if (sym->value + offset == 0)
673 continue;
674 if (bfd_is_const_section(sym->section))
675 continue;
676 struct supersect *sym_ss = fetch_supersect(ss->parent,
677 sym->section);
678 if (sym_ss->type != SS_TYPE_TEXT)
679 continue;
680 if (!sym_ss->patch) {
681 changed = true;
682 printf("Changing %s because a relocation from sect %s "
683 "has a nonzero offset %lx+%lx into it\n",
684 sym_ss->name, ss->name,
685 (unsigned long)sym->value,
686 (unsigned long)offset);
688 sym_ss->patch = true;
692 static void update_nonzero_offsets(struct superbfd *sbfd)
694 asection *sect;
695 struct supersect *ss;
697 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
698 ss = fetch_supersect(sbfd, sect);
699 if (ss->new || ss->patch)
700 handle_nonzero_offset_relocs(ss);
704 static void compare_matched_sections(struct superbfd *newsbfd)
706 asection *newp;
707 struct supersect *old_ss, *new_ss;
708 for (newp = newsbfd->abfd->sections; newp != NULL; newp = newp->next) {
709 new_ss = fetch_supersect(newsbfd, newp);
710 if (new_ss->match == NULL)
711 continue;
712 old_ss = new_ss->match;
714 if (nonrelocs_equal(old_ss, new_ss) &&
715 relocs_equal(old_ss, new_ss))
716 continue;
717 if (new_ss->type == SS_TYPE_TEXT) {
718 if (new_ss->patch)
719 continue;
720 new_ss->patch = true;
721 printf("Changing %s due to ", new_ss->name);
722 } else {
723 printf("Unmatching %s and %s due to ", old_ss->name,
724 new_ss->name);
725 new_ss->match = NULL;
726 old_ss->match = NULL;
728 if (new_ss->contents.size != old_ss->contents.size)
729 printf("differing sizes\n");
730 else if (memcmp(new_ss->contents.data, old_ss->contents.data,
731 new_ss->contents.size) != 0)
732 printf("differing contents\n");
733 else
734 printf("differing relocations\n");
735 changed = true;
736 if (unchangeable_section(new_ss))
737 fprintf(stderr, "WARNING: ignoring change to "
738 "nonpatchable section %s\n", new_ss->name);
742 static void handle_section_symbol_renames(struct superbfd *oldsbfd,
743 struct superbfd *newsbfd)
745 asection *newp, *oldp;
746 for (newp = newsbfd->abfd->sections; newp != NULL; newp = newp->next) {
747 struct supersect *newss = fetch_supersect(newsbfd, newp);
748 if (newss->match == NULL)
749 continue;
750 oldp = bfd_get_section_by_name(oldsbfd->abfd,
751 newss->match->name);
752 if (oldp == NULL)
753 continue;
755 const char *old_label = label_lookup(oldsbfd, oldp->symbol);
756 const char *new_label = label_lookup(newsbfd, newp->symbol);
758 if (strcmp(old_label, new_label) == 0)
759 continue;
760 label_map_set(newsbfd, new_label, old_label);
764 static bool part_of_reloc(struct supersect *ss, unsigned long addr)
766 arelent **relocp;
767 for (relocp = ss->relocs.data;
768 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
769 arelent *reloc = *relocp;
770 if (addr >= reloc->address &&
771 addr < reloc->address + reloc->howto->size)
772 return true;
774 return false;
777 static bool nonrelocs_equal(struct supersect *old_ss, struct supersect *new_ss)
779 int i;
780 if (old_ss->contents.size != new_ss->contents.size)
781 return false;
782 const unsigned char *old = old_ss->contents.data;
783 const unsigned char *new = new_ss->contents.data;
784 for (i = 0; i < old_ss->contents.size; i++) {
785 if (old[i] != new[i] &&
786 !(part_of_reloc(old_ss, i) && part_of_reloc(new_ss, i)))
787 return false;
789 return true;
793 * relocs_equal checks to see whether the old section and the new section
794 * reference different read-only data in their relocations -- if a hard-coded
795 * string has been changed between the old file and the new file, relocs_equal
796 * will detect the difference.
798 bool relocs_equal(struct supersect *old_ss, struct supersect *new_ss)
800 int i;
801 struct superbfd *oldsbfd = old_ss->parent;
802 struct superbfd *newsbfd = new_ss->parent;
804 if (old_ss->relocs.size != new_ss->relocs.size) {
805 printf("Different reloc count between %s and %s\n",
806 old_ss->name, new_ss->name);
807 return false;
810 for (i = 0; i < old_ss->relocs.size; i++) {
811 struct supersect *ro_old_ss, *ro_new_ss;
813 asymbol *old_sym = *old_ss->relocs.data[i]->sym_ptr_ptr;
814 asymbol *new_sym = *new_ss->relocs.data[i]->sym_ptr_ptr;
816 bfd_vma old_offset =
817 get_reloc_offset(old_ss, old_ss->relocs.data[i], true);
818 bfd_vma new_offset =
819 get_reloc_offset(new_ss, new_ss->relocs.data[i], true);
821 if (bfd_is_und_section(old_sym->section) ||
822 bfd_is_und_section(new_sym->section)) {
823 if (!bfd_is_und_section(new_sym->section) &&
824 fetch_supersect(newsbfd, new_sym->section)->type
825 == SS_TYPE_TEXT && old_offset != 0)
826 return false;
828 if (!bfd_is_und_section(old_sym->section) &&
829 fetch_supersect(oldsbfd, old_sym->section)->type
830 == SS_TYPE_TEXT && new_offset != 0)
831 return false;
833 if (strcmp(old_sym->name, new_sym->name) == 0 &&
834 old_offset == new_offset)
835 continue;
836 return false;
839 if (bfd_is_const_section(old_sym->section) ||
840 bfd_is_const_section(new_sym->section))
841 DIE;
843 ro_old_ss = fetch_supersect(oldsbfd, old_sym->section);
844 ro_new_ss = fetch_supersect(newsbfd, new_sym->section);
846 if (ro_old_ss->type == SS_TYPE_STRING &&
847 /* check it's not an out-of-range relocation to a string;
848 we'll just compare entire sections for them */
849 !(old_offset >= ro_old_ss->contents.size ||
850 new_offset >= ro_new_ss->contents.size)) {
851 if (strcmp(ro_old_ss->contents.data + old_sym->value +
852 old_offset,
853 ro_new_ss->contents.data + new_sym->value +
854 new_offset) != 0) {
855 printf("Strings differ between %s and %s\n",
856 old_ss->name, new_ss->name);
857 return false;
859 continue;
862 if (ro_old_ss->match != ro_new_ss ||
863 ro_new_ss->match != ro_old_ss) {
864 printf("Nonmatching relocs from %s to %s/%s\n",
865 new_ss->name, ro_new_ss->name, ro_old_ss->name);
866 return false;
869 if (old_sym->value + old_offset != new_sym->value + new_offset) {
870 printf("Offsets to %s/%s differ between %s and %s: "
871 "%lx+%lx/%lx+%lx\n", ro_old_ss->name,
872 ro_new_ss->name, old_ss->name, new_ss->name,
873 (unsigned long)old_sym->value,
874 (unsigned long)old_offset,
875 (unsigned long)new_sym->value,
876 (unsigned long)new_offset);
877 return false;
880 if ((old_sym->value + old_offset != 0 ||
881 new_sym->value + new_offset != 0) && ro_new_ss->patch) {
882 printf("Relocation from %s to nonzero offsets %lx+%lx/"
883 "%lx+%lx in changed section %s\n", new_ss->name,
884 (unsigned long)old_sym->value,
885 (unsigned long)old_offset,
886 (unsigned long)new_sym->value,
887 (unsigned long)new_offset,
888 new_sym->section->name);
889 return false;
893 return true;
896 void rm_some_exports(struct superbfd *isbfd, const struct export_desc *ed)
898 assert(starts_with(ed->sectname, "__ksymtab"));
899 const char *export_type = ed->sectname + strlen("__ksymtab");
900 asection *sym_sect = bfd_get_section_by_name(isbfd->abfd, ed->sectname);
901 assert(sym_sect != NULL);
902 char *export_crc_name;
903 assert(asprintf(&export_crc_name, "__kcrctab%s", export_type) >= 0);
904 asection *crc_sect = bfd_get_section_by_name(isbfd->abfd,
905 export_crc_name);
906 struct supersect *ss, *crc_ss = NULL;
907 ss = fetch_supersect(isbfd, sym_sect);
908 if (crc_sect != NULL)
909 crc_ss = fetch_supersect(isbfd, crc_sect);
911 if (crc_ss != NULL)
912 assert(ss->contents.size * sizeof(unsigned long) ==
913 crc_ss->contents.size * sizeof(struct kernel_symbol));
915 struct supersect orig_ss, orig_crc_ss;
916 supersect_move(&orig_ss, ss);
917 if (crc_ss != NULL)
918 supersect_move(&orig_crc_ss, crc_ss);
920 struct kernel_symbol *orig_ksym;
921 unsigned long *orig_crc;
922 for (orig_ksym = orig_ss.contents.data,
923 orig_crc = orig_crc_ss.contents.data;
924 (void *)orig_ksym < orig_ss.contents.data + orig_ss.contents.size;
925 orig_ksym++, orig_crc++) {
926 asymbol *sym;
927 read_reloc(&orig_ss, &orig_ksym->value,
928 sizeof(orig_ksym->value), &sym);
929 if (!str_in_set(sym->name, &ed->names))
930 continue;
932 struct kernel_symbol *ksym = sect_grow(ss, 1, typeof(*ksym));
933 sect_copy(ss, &ksym->value, &orig_ss, &orig_ksym->value, 1);
934 /* Replace name with a mangled name */
935 write_ksplice_export(ss->parent, sym->name, export_type, false);
936 write_string(ss, (const char **)&ksym->name,
937 "DISABLED_%s_%s", sym->name, kid);
939 if (crc_ss != NULL)
940 sect_copy(crc_ss,
941 sect_grow(crc_ss, 1, typeof(*orig_crc)),
942 &orig_crc_ss, orig_crc, 1);
946 void rm_relocs(struct superbfd *isbfd)
948 asection *p;
949 for (p = isbfd->abfd->sections; p != NULL; p = p->next) {
950 struct supersect *ss = fetch_supersect(isbfd, p);
951 if (ss->type == SS_TYPE_SPECIAL || ss->type == SS_TYPE_KSPLICE)
952 continue;
953 if (ss->keep || mode("rmsyms"))
954 rm_some_relocs(ss);
956 if (mode("finalize")) {
957 p = bfd_get_section_by_name(isbfd->abfd, ".ksplice_patches");
958 if (p != NULL) {
959 struct supersect *ss = fetch_supersect(isbfd, p);
960 rm_some_relocs(ss);
965 void rm_some_relocs(struct supersect *ss)
967 struct arelentp_vec orig_relocs;
968 vec_move(&orig_relocs, &ss->relocs);
970 arelent **relocp;
971 for (relocp = orig_relocs.data;
972 relocp < orig_relocs.data + orig_relocs.size; relocp++) {
973 bool rm_reloc = false;
974 asymbol *sym_ptr = *(*relocp)->sym_ptr_ptr;
976 if (mode("rmsyms") && str_in_set(sym_ptr->name, &rmsyms) &&
977 bfd_is_und_section(sym_ptr->section))
978 rm_reloc = true;
980 if (mode("keep"))
981 rm_reloc = true;
983 if (mode("keep-primary") &&
984 (bfd_is_const_section(sym_ptr->section) ||
985 fetch_supersect(ss->parent, sym_ptr->section)->new ||
986 fetch_supersect(ss->parent, sym_ptr->section)->type ==
987 SS_TYPE_STRING))
988 rm_reloc = false;
990 if (mode("finalize") && bfd_is_und_section(sym_ptr->section))
991 rm_reloc = true;
993 if (rm_reloc)
994 write_ksplice_reloc(ss, *relocp);
995 else
996 *vec_grow(&ss->relocs, 1) = *relocp;
1000 struct supersect *make_section(struct superbfd *sbfd, const char *name)
1002 asection *sect = bfd_get_section_by_name(sbfd->abfd, name);
1003 if (sect != NULL)
1004 return fetch_supersect(sbfd, sect);
1005 else
1006 return new_supersect(sbfd, name);
1009 arelent *create_reloc(struct supersect *ss, const void *addr, asymbol **symp,
1010 bfd_vma offset)
1012 bfd_reloc_code_real_type code;
1013 switch (bfd_arch_bits_per_address(ss->parent->abfd)) {
1014 case 32:
1015 code = BFD_RELOC_32;
1016 break;
1017 case 64:
1018 code = BFD_RELOC_64;
1019 break;
1020 default:
1021 DIE;
1024 arelent *reloc = malloc(sizeof(*reloc));
1025 reloc->sym_ptr_ptr = symp;
1026 reloc->address = addr - ss->contents.data;
1027 reloc->howto = bfd_reloc_type_lookup(ss->parent->abfd, code);
1028 reloc->addend = offset;
1029 return reloc;
1032 void write_reloc(struct supersect *ss, const void *addr, asymbol **symp,
1033 bfd_vma offset)
1035 arelent *new_reloc = create_reloc(ss, addr, symp, offset), **relocp;
1036 for (relocp = ss->relocs.data;
1037 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
1038 if ((*relocp)->address == new_reloc->address) {
1039 memmove(relocp,
1040 relocp + 1,
1041 (void *)(ss->relocs.data + ss->relocs.size) -
1042 (void *)(relocp + 1));
1043 ss->relocs.size--;
1044 relocp--;
1047 *vec_grow(&ss->new_relocs, 1) = new_reloc;
1050 void write_string(struct supersect *ss, const char **addr, const char *fmt, ...)
1052 va_list ap;
1053 struct supersect *str_ss = make_section(ss->parent, ".ksplice_str");
1054 char *str;
1055 va_start(ap, fmt);
1056 int len = vasprintf(&str, fmt, ap);
1057 assert(len >= 0);
1058 va_end(ap);
1060 unsigned long *str_offp = ulong_hash_lookup(&ksplice_string_offset, str,
1061 FALSE);
1062 if (str_offp == NULL) {
1063 char *buf = sect_grow(str_ss, len + 1, char);
1064 memcpy(buf, str, len + 1);
1065 str_offp = ulong_hash_lookup(&ksplice_string_offset, str, TRUE);
1066 *str_offp = (void *)buf - str_ss->contents.data;
1069 write_reloc(ss, addr, &str_ss->symbol, *str_offp);
1072 void lookup_system_map(struct addr_vec *addrs, const char *name, long offset)
1074 struct addr_vec *map_addrs =
1075 addr_vec_hash_lookup(&system_map, name, FALSE);
1076 if (map_addrs == NULL)
1077 return;
1079 unsigned long *addr, *map_addr;
1080 for (map_addr = map_addrs->data;
1081 map_addr < map_addrs->data + map_addrs->size; map_addr++) {
1082 for (addr = addrs->data; addr < addrs->data + addrs->size;
1083 addr++) {
1084 if (*addr == *map_addr + offset)
1085 break;
1087 if (addr < addrs->data + addrs->size)
1088 continue;
1089 *vec_grow(addrs, 1) = *map_addr + offset;
1093 void write_system_map_array(struct superbfd *sbfd, struct supersect *ss,
1094 const unsigned long **sym_addrs,
1095 unsigned long *num_sym_addrs, asymbol *sym)
1097 struct addr_vec addrs;
1098 vec_init(&addrs);
1100 if (bfd_is_abs_section(sym->section)) {
1101 *vec_grow(&addrs, 1) = sym->value;
1102 } else if (bfd_is_und_section(sym->section)) {
1103 lookup_system_map(&addrs, sym->name, 0);
1104 } else if (!bfd_is_const_section(sym->section)) {
1105 asymbol **gsymp;
1106 for (gsymp = sbfd->syms.data;
1107 gsymp < sbfd->syms.data + sbfd->syms.size; gsymp++) {
1108 asymbol *gsym = *gsymp;
1109 if ((gsym->flags & BSF_DEBUGGING) == 0 &&
1110 gsym->section == sym->section)
1111 lookup_system_map(&addrs, gsym->name,
1112 sym->value - gsym->value);
1116 *num_sym_addrs = addrs.size;
1117 if (addrs.size != 0) {
1118 struct supersect *array_ss = make_section(sbfd,
1119 ".ksplice_array");
1120 void *buf = sect_grow(array_ss, addrs.size,
1121 typeof(*addrs.data));
1122 memcpy(buf, addrs.data, addrs.size * sizeof(*addrs.data));
1123 write_reloc(ss, sym_addrs, &array_ss->symbol,
1124 buf - array_ss->contents.data);
1125 } else {
1126 *sym_addrs = NULL;
1129 vec_free(&addrs);
1132 void write_ksplice_system_map(struct superbfd *sbfd, asymbol *sym,
1133 const char *addstr_sect)
1135 struct supersect *smap_ss = make_section(sbfd, ".ksplice_system_map");
1136 struct ksplice_system_map *smap;
1137 const char *label = label_lookup(sbfd, sym);
1139 bool *done = bool_hash_lookup(&system_map_written, label, TRUE);
1140 if (*done)
1141 return;
1142 *done = true;
1144 smap = sect_grow(smap_ss, 1, struct ksplice_system_map);
1146 write_system_map_array(sbfd, smap_ss, &smap->candidates,
1147 &smap->nr_candidates, sym);
1148 write_string(smap_ss, &smap->label, "%s%s", label, addstr_sect);
1151 void write_ksplice_symbol(struct supersect *ss,
1152 const struct ksplice_symbol *const *addr,
1153 asymbol *sym, const char *addstr_sect)
1155 struct supersect *ksymbol_ss = make_section(ss->parent,
1156 ".ksplice_symbols");
1157 struct ksplice_symbol *ksymbol;
1158 unsigned long *ksymbol_offp;
1159 const char *label = label_lookup(ss->parent, sym);
1160 char *output;
1161 assert(asprintf(&output, "%s%s", label, addstr_sect) >= 0);
1163 ksymbol_offp = ulong_hash_lookup(&ksplice_symbol_offset, output, FALSE);
1164 if (ksymbol_offp != NULL) {
1165 write_reloc(ss, addr, &ksymbol_ss->symbol, *ksymbol_offp);
1166 return;
1168 ksymbol = sect_grow(ksymbol_ss, 1, struct ksplice_symbol);
1169 ksymbol_offp = ulong_hash_lookup(&ksplice_symbol_offset, output, TRUE);
1170 *ksymbol_offp = (void *)ksymbol - ksymbol_ss->contents.data;
1172 if (bfd_is_und_section(sym->section) || (sym->flags & BSF_GLOBAL) != 0) {
1173 write_string(ksymbol_ss, &ksymbol->name, "%s", sym->name);
1174 } else if (bfd_is_const_section(sym->section)) {
1175 ksymbol->name = NULL;
1176 } else {
1177 asymbol *gsym = canonical_symbol(ss->parent, sym);
1179 if (gsym == NULL || (gsym->flags & BSF_SECTION_SYM) != 0)
1180 ksymbol->name = NULL;
1181 else
1182 write_string(ksymbol_ss, &ksymbol->name, "%s",
1183 gsym->name);
1186 write_string(ksymbol_ss, &ksymbol->label, "%s%s", label, addstr_sect);
1188 write_ksplice_system_map(ksymbol_ss->parent, sym, addstr_sect);
1190 write_reloc(ss, addr, &ksymbol_ss->symbol, *ksymbol_offp);
1193 void write_ksplice_reloc(struct supersect *ss, arelent *orig_reloc)
1195 asymbol *sym_ptr = *orig_reloc->sym_ptr_ptr;
1196 reloc_howto_type *howto = orig_reloc->howto;
1197 bfd_vma addend = get_reloc_offset(ss, orig_reloc, false);
1199 if (mode("finalize") && starts_with(ss->name, ".ksplice_patches")) {
1200 unsigned long *repladdr =
1201 ss->contents.data + orig_reloc->address;
1202 *repladdr = 0;
1203 return;
1206 blot_section(ss, orig_reloc->address, howto);
1208 struct supersect *kreloc_ss = make_section(ss->parent,
1209 mode("rmsyms") ?
1210 ".ksplice_init_relocs" :
1211 ".ksplice_relocs");
1212 struct ksplice_reloc *kreloc = sect_grow(kreloc_ss, 1,
1213 struct ksplice_reloc);
1215 write_reloc(kreloc_ss, &kreloc->blank_addr,
1216 &ss->symbol, orig_reloc->address);
1217 kreloc->blank_offset = (unsigned long)orig_reloc->address;
1218 write_ksplice_symbol(kreloc_ss, &kreloc->symbol, sym_ptr, "");
1219 kreloc->pcrel = howto->pc_relative;
1220 kreloc->addend = addend;
1221 kreloc->size = bfd_get_reloc_size(howto);
1222 kreloc->dst_mask = howto->dst_mask;
1223 kreloc->rightshift = howto->rightshift;
1224 kreloc->signed_addend =
1225 (howto->complain_on_overflow == complain_overflow_signed) ||
1226 (howto->complain_on_overflow == complain_overflow_bitfield);
1229 #define CANARY(x, canary) ((x & ~howto->dst_mask) | (canary & howto->dst_mask))
1231 void blot_section(struct supersect *ss, int offset, reloc_howto_type *howto)
1233 int bits = bfd_get_reloc_size(howto) * 8;
1234 void *address = ss->contents.data + offset;
1235 bfd_vma x = bfd_get(bits, ss->parent->abfd, address);
1236 x = (x & ~howto->dst_mask) |
1237 ((bfd_vma)KSPLICE_CANARY & howto->dst_mask);
1238 bfd_put(bits, ss->parent->abfd, x, address);
1241 void write_ksplice_section(struct superbfd *sbfd, asymbol **symp)
1243 asymbol *sym = *symp;
1244 struct supersect *ksect_ss = make_section(sbfd, ".ksplice_sections");
1245 struct ksplice_section *ksect = sect_grow(ksect_ss, 1,
1246 struct ksplice_section);
1248 write_ksplice_symbol(ksect_ss, &ksect->symbol, sym,
1249 mode("keep-primary") ? "(post)" : "");
1250 ksect->size = bfd_get_section_size(sym->section);
1251 ksect->flags = 0;
1252 struct supersect *sym_ss = fetch_supersect(sbfd, sym->section);
1253 if (sym_ss->type == SS_TYPE_RODATA)
1254 ksect->flags |= KSPLICE_SECTION_RODATA;
1255 if (sym_ss->type == SS_TYPE_DATA)
1256 ksect->flags |= KSPLICE_SECTION_DATA;
1257 if (sym_ss->type == SS_TYPE_TEXT)
1258 ksect->flags |= KSPLICE_SECTION_TEXT;
1259 assert(ksect->flags != 0);
1260 write_reloc(ksect_ss, &ksect->address, symp, 0);
1263 void write_ksplice_patch(struct superbfd *sbfd, const char *sectname)
1265 struct supersect *kpatch_ss = make_section(sbfd, ".ksplice_patches");
1266 struct ksplice_patch *kpatch = sect_grow(kpatch_ss, 1,
1267 struct ksplice_patch);
1268 asection *sect = bfd_get_section_by_name(sbfd->abfd, sectname);
1269 assert(sect != NULL);
1271 write_string(kpatch_ss, &kpatch->label, "%s",
1272 label_lookup(sbfd, sect->symbol));
1273 write_reloc(kpatch_ss, &kpatch->repladdr, &sect->symbol, 0);
1276 void write_ksplice_deleted_patch(struct superbfd *sbfd, const char *name,
1277 const char *label)
1279 struct supersect *kpatch_ss = make_section(sbfd, ".ksplice_patches");
1280 struct ksplice_patch *kpatch = sect_grow(kpatch_ss, 1,
1281 struct ksplice_patch);
1283 write_string(kpatch_ss, &kpatch->label, "%s", label);
1284 asymbol **symp;
1285 for (symp = sbfd->syms.data; symp < sbfd->syms.data + sbfd->syms.size;
1286 symp++) {
1287 asymbol *sym = *symp;
1288 if (bfd_is_und_section(sym->section) &&
1289 strcmp(name, sym->name) == 0)
1290 break;
1292 if (symp >= sbfd->syms.data + sbfd->syms.size) {
1293 symp = malloc(sizeof(*symp));
1294 *symp = bfd_make_empty_symbol(sbfd->abfd);
1295 asymbol *sym = *symp;
1296 sym->name = strdup(name);
1297 sym->section = bfd_und_section_ptr;
1298 sym->flags = 0;
1299 sym->value = 0;
1300 *vec_grow(&sbfd->new_syms, 1) = symp;
1302 write_reloc(kpatch_ss, &kpatch->repladdr, symp, 0);
1305 void write_ksplice_export(struct superbfd *sbfd, const char *symname,
1306 const char *export_type, bool del)
1308 struct supersect *export_ss = make_section(sbfd, ".ksplice_exports");
1309 struct ksplice_export *exp = sect_grow(export_ss, 1,
1310 struct ksplice_export);
1312 if (del) {
1313 write_string(export_ss, &exp->name, "%s", symname);
1314 write_string(export_ss, &exp->new_name, "DISABLED_%s_%s",
1315 symname, kid);
1316 } else {
1317 write_string(export_ss, &exp->new_name, "%s", symname);
1318 write_string(export_ss, &exp->name, "DISABLED_%s_%s", symname,
1319 kid);
1323 struct fixup_entry {
1324 bfd_vma offset;
1325 bool used;
1326 bfd_vma ex_offset;
1328 DECLARE_VEC_TYPE(struct fixup_entry, fixup_entry_vec);
1330 int compare_fixups(const void *aptr, const void *bptr)
1332 const struct fixup_entry *a = aptr, *b = bptr;
1333 if (a->offset < b->offset)
1334 return -1;
1335 else if (a->offset > b->offset)
1336 return 1;
1337 else
1338 return (int)a->used - (int)b->used;
1341 void filter_table_sections(struct superbfd *isbfd)
1343 struct supersect *tables_ss =
1344 fetch_supersect(offsets_sbfd,
1345 bfd_get_section_by_name(offsets_sbfd->abfd,
1346 ".ksplice_table_sections"));
1347 const struct table_section *ts;
1348 for (ts = tables_ss->contents.data;
1349 (void *)ts < tables_ss->contents.data + tables_ss->contents.size;
1350 ts++) {
1351 struct table_section s = *ts;
1352 s.sect = read_string(tables_ss, &ts->sect);
1353 s.other_sect = read_string(tables_ss, &ts->other_sect);
1354 filter_table_section(isbfd, &s);
1358 void filter_table_section(struct superbfd *sbfd, const struct table_section *s)
1360 asection *isection = bfd_get_section_by_name(sbfd->abfd, s->sect);
1361 if (isection == NULL)
1362 return;
1363 asection *fixup_sect = NULL;
1364 if (s->other_sect != NULL)
1365 fixup_sect = bfd_get_section_by_name(sbfd->abfd, s->other_sect);
1367 struct supersect *ss = fetch_supersect(sbfd, isection), orig_ss;
1368 supersect_move(&orig_ss, ss);
1370 struct supersect *fixup_ss = NULL;
1371 if (fixup_sect != NULL)
1372 fixup_ss = fetch_supersect(sbfd, fixup_sect);
1374 struct fixup_entry_vec fixups;
1375 vec_init(&fixups);
1377 void *orig_entry;
1378 for (orig_entry = orig_ss.contents.data;
1379 orig_entry < orig_ss.contents.data + orig_ss.contents.size;
1380 orig_entry += s->entry_size) {
1381 asymbol *sym, *fixup_sym;
1382 read_reloc(&orig_ss, orig_entry + s->addr_offset,
1383 sizeof(void *), &sym);
1385 struct fixup_entry *f;
1386 if (fixup_sect != NULL) {
1387 bfd_vma fixup_offset =
1388 read_reloc(&orig_ss, orig_entry + s->other_offset,
1389 sizeof(void *), &fixup_sym);
1390 if (fixup_sym->section == fixup_sect) {
1391 assert(fixup_offset < fixup_ss->contents.size);
1392 f = vec_grow(&fixups, 1);
1393 f->offset = fixup_offset;
1394 f->used = false;
1398 struct supersect *sym_ss = fetch_supersect(sbfd, sym->section);
1399 if (!sym_ss->keep)
1400 continue;
1402 if (fixup_sect != NULL && fixup_sym->section == fixup_sect) {
1403 f->used = true;
1404 f->ex_offset = ss->contents.size + s->other_offset;
1406 sect_copy(ss, sect_do_grow(ss, 1, s->entry_size,
1407 s->entry_align),
1408 &orig_ss, orig_entry, s->entry_size);
1411 if (fixup_sect == NULL)
1412 return;
1414 struct supersect orig_fixup_ss;
1415 supersect_move(&orig_fixup_ss, fixup_ss);
1417 qsort(fixups.data, fixups.size, sizeof(*fixups.data), compare_fixups);
1418 *vec_grow(&fixups, 1) = (struct fixup_entry)
1419 { .offset = orig_fixup_ss.contents.size, .used = false };
1421 struct fixup_entry *f;
1422 for (f = fixups.data; f < fixups.data + fixups.size - 1; f++) {
1423 if (!f->used)
1424 continue;
1425 write_reloc(ss, ss->contents.data + f->ex_offset,
1426 &fixup_ss->symbol, fixup_ss->contents.size);
1427 sect_copy(fixup_ss,
1428 sect_grow(fixup_ss, (f + 1)->offset - f->offset,
1429 unsigned char),
1430 &orig_fixup_ss,
1431 orig_fixup_ss.contents.data + f->offset,
1432 (f + 1)->offset - f->offset);
1436 void keep_if_referenced(bfd *abfd, asection *sect, void *ignored)
1438 struct superbfd *sbfd = fetch_superbfd(abfd);
1439 struct supersect *ss = fetch_supersect(sbfd, sect);
1440 if (ss->keep || ss->type == SS_TYPE_IGNORED)
1441 return;
1443 asymbol **symp;
1444 for (symp = sbfd->syms.data;
1445 symp < sbfd->syms.data + sbfd->syms.size; symp++) {
1446 asymbol *sym = *symp;
1447 if (sym->section == sect && (sym->flags & BSF_GLOBAL) != 0) {
1448 ss->keep = true;
1449 changed = true;
1450 return;
1454 bfd_map_over_sections(abfd, check_for_ref_to_section, sect);
1457 void check_for_ref_to_section(bfd *abfd, asection *looking_at,
1458 void *looking_for)
1460 struct superbfd *sbfd = fetch_superbfd(abfd);
1461 struct supersect *ss = fetch_supersect(sbfd, looking_at);
1462 struct supersect *for_ss = fetch_supersect(sbfd,
1463 (asection *)looking_for);
1464 if (!ss->keep || ss->type == SS_TYPE_STRING ||
1465 ss->type == SS_TYPE_SPECIAL || ss->type == SS_TYPE_EXPORT)
1466 return;
1468 arelent **relocp;
1469 for (relocp = ss->relocs.data;
1470 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
1471 asymbol *sym = *(*relocp)->sym_ptr_ptr;
1472 if (sym->section != (asection *)looking_for)
1473 continue;
1474 for_ss->keep = true;
1475 changed = true;
1476 return;
1480 void copy_symbols(struct asymbolp_vec *osyms, struct asymbolpp_vec *isyms)
1482 asymbol ***sympp;
1483 for (sympp = isyms->data; sympp < isyms->data + isyms->size; sympp++)
1484 *vec_grow(osyms, 1) = **sympp;
1487 /* Modified function from GNU Binutils objcopy.c */
1488 bfd_boolean copy_object(bfd *ibfd, bfd *obfd)
1490 assert(bfd_set_format(obfd, bfd_get_format(ibfd)));
1492 bfd_vma start = bfd_get_start_address(ibfd);
1494 flagword flags = bfd_get_file_flags(ibfd);
1495 flags &= bfd_applicable_file_flags(obfd);
1497 assert(bfd_set_start_address(obfd, start)
1498 && bfd_set_file_flags(obfd, flags));
1500 enum bfd_architecture iarch = bfd_get_arch(ibfd);
1501 unsigned int imach = bfd_get_mach(ibfd);
1502 assert(bfd_set_arch_mach(obfd, iarch, imach));
1503 assert(bfd_set_format(obfd, bfd_get_format(ibfd)));
1505 /* BFD mandates that all output sections be created and sizes set before
1506 any output is done. Thus, we traverse all sections multiple times. */
1507 bfd_map_over_sections(ibfd, setup_section, obfd);
1509 struct supersect *new_supersects = fetch_superbfd(ibfd)->new_supersects;
1510 struct supersect *ss;
1511 for (ss = new_supersects; ss != NULL; ss = ss->next)
1512 setup_new_section(obfd, ss);
1514 /* Mark symbols used in output relocations so that they
1515 are kept, even if they are local labels or static symbols.
1517 Note we iterate over the input sections examining their
1518 relocations since the relocations for the output sections
1519 haven't been set yet. mark_symbols_used_in_relocations will
1520 ignore input sections which have no corresponding output
1521 section. */
1523 bfd_map_over_sections(ibfd, mark_symbols_used_in_relocations, NULL);
1524 for (ss = new_supersects; ss != NULL; ss = ss->next)
1525 ss_mark_symbols_used_in_relocations(ss);
1526 struct asymbolp_vec osyms;
1527 vec_init(&osyms);
1528 filter_symbols(ibfd, obfd, &osyms, &fetch_superbfd(ibfd)->syms);
1529 copy_symbols(&osyms, &fetch_superbfd(ibfd)->new_syms);
1531 bfd_set_symtab(obfd, osyms.data, osyms.size);
1533 /* This has to happen after the symbol table has been set. */
1534 bfd_map_over_sections(obfd, write_section, NULL);
1536 /* Allow the BFD backend to copy any private data it understands
1537 from the input BFD to the output BFD. This is done last to
1538 permit the routine to look at the filtered symbol table, which is
1539 important for the ECOFF code at least. */
1540 assert(bfd_copy_private_bfd_data(ibfd, obfd));
1542 return TRUE;
1545 /* Modified function from GNU Binutils objcopy.c */
1546 void setup_section(bfd *ibfd, asection *isection, void *obfdarg)
1548 struct superbfd *isbfd = fetch_superbfd(ibfd);
1549 struct supersect *ss = fetch_supersect(isbfd, isection);
1550 bfd *obfd = obfdarg;
1551 bfd_vma vma;
1553 if (!ss->keep)
1554 return;
1556 asection *osection = bfd_make_section_anyway(obfd, isection->name);
1557 assert(osection != NULL);
1559 osection->userdata = ss;
1560 bfd_set_section_flags(obfd, osection, ss->flags);
1561 ss->symbol = osection->symbol;
1562 assert(bfd_set_section_size(obfd, osection, ss->contents.size));
1564 vma = bfd_section_vma(ibfd, isection);
1565 assert(bfd_set_section_vma(obfd, osection, vma));
1567 osection->lma = isection->lma;
1568 assert(bfd_set_section_alignment(obfd, osection, ss->alignment));
1569 osection->entsize = isection->entsize;
1570 osection->output_section = osection;
1571 osection->output_offset = 0;
1572 isection->output_section = osection;
1573 isection->output_offset = 0;
1574 return;
1577 void setup_new_section(bfd *obfd, struct supersect *ss)
1579 asection *osection = bfd_make_section_anyway(obfd, ss->name);
1580 assert(osection != NULL);
1581 bfd_set_section_flags(obfd, osection, ss->flags);
1583 osection->userdata = ss;
1584 ss->symbol = osection->symbol;
1585 assert(bfd_set_section_size(obfd, osection, ss->contents.size));
1586 assert(bfd_set_section_vma(obfd, osection, 0));
1588 osection->lma = 0;
1589 assert(bfd_set_section_alignment(obfd, osection, ss->alignment));
1590 osection->entsize = 0;
1591 osection->output_section = osection;
1592 osection->output_offset = 0;
1595 void write_section(bfd *obfd, asection *osection, void *arg)
1597 struct supersect *ss = osection->userdata;
1599 if ((ss->flags & SEC_GROUP) != 0 || ss->contents.size == 0)
1600 return;
1602 arelent **relocp;
1603 char *error_message;
1604 for (relocp = ss->new_relocs.data;
1605 relocp < ss->new_relocs.data + ss->new_relocs.size; relocp++) {
1606 bfd_vma val;
1607 if (bfd_get_arch(obfd) == bfd_arch_arm)
1608 val = osection->use_rela_p ? 0 : (*relocp)->addend;
1609 else
1610 val = 0;
1611 bfd_put(bfd_get_reloc_size((*relocp)->howto) * 8, obfd, val,
1612 ss->contents.data + (*relocp)->address);
1613 if (bfd_install_relocation(obfd, *relocp, ss->contents.data,
1614 0, osection, &error_message) !=
1615 bfd_reloc_ok) {
1616 fprintf(stderr, "ksplice: error installing reloc: %s",
1617 error_message);
1618 DIE;
1621 memcpy(vec_grow(&ss->relocs, ss->new_relocs.size), ss->new_relocs.data,
1622 ss->new_relocs.size * sizeof(*ss->new_relocs.data));
1624 bfd_set_reloc(obfd, osection,
1625 ss->relocs.size == 0 ? NULL : ss->relocs.data,
1626 ss->relocs.size);
1628 if (ss->flags & SEC_HAS_CONTENTS)
1629 assert(bfd_set_section_contents
1630 (obfd, osection, ss->contents.data, 0,
1631 ss->contents.size));
1634 /* Modified function from GNU Binutils objcopy.c
1636 * Mark all the symbols which will be used in output relocations with
1637 * the BSF_KEEP flag so that those symbols will not be stripped.
1639 * Ignore relocations which will not appear in the output file.
1641 void mark_symbols_used_in_relocations(bfd *abfd, asection *isection,
1642 void *ignored)
1644 struct superbfd *sbfd = fetch_superbfd(abfd);
1645 if (isection->output_section == NULL)
1646 return;
1648 struct supersect *ss = fetch_supersect(sbfd, isection);
1649 ss_mark_symbols_used_in_relocations(ss);
1652 void ss_mark_symbols_used_in_relocations(struct supersect *ss)
1654 /* Examine each symbol used in a relocation. If it's not one of the
1655 special bfd section symbols, then mark it with BSF_KEEP. */
1656 arelent **relocp;
1657 for (relocp = ss->relocs.data;
1658 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
1659 asymbol *sym = *(*relocp)->sym_ptr_ptr;
1660 if (!(bfd_is_const_section(sym->section) &&
1661 sym == sym->section->symbol))
1662 sym->flags |= BSF_KEEP;
1664 for (relocp = ss->new_relocs.data;
1665 relocp < ss->new_relocs.data + ss->new_relocs.size; relocp++) {
1666 asymbol *sym = *(*relocp)->sym_ptr_ptr;
1667 if (!(bfd_is_const_section(sym->section) &&
1668 sym == sym->section->symbol))
1669 sym->flags |= BSF_KEEP;
1673 static bool deleted_table_section_symbol(bfd *abfd, asymbol *sym)
1675 struct superbfd *sbfd = fetch_superbfd(abfd);
1676 if (bfd_is_const_section(sym->section))
1677 return false;
1678 struct supersect *ss = fetch_supersect(sbfd, sym->section);
1680 asymbol **symp;
1681 for (symp = ss->syms.data; symp < ss->syms.data + ss->syms.size; symp++) {
1682 if (sym == *symp)
1683 break;
1685 return symp >= ss->syms.data + ss->syms.size;
1688 /* Modified function from GNU Binutils objcopy.c
1690 * Choose which symbol entries to copy.
1691 * We don't copy in place, because that confuses the relocs.
1692 * Return the number of symbols to print.
1694 void filter_symbols(bfd *ibfd, bfd *obfd, struct asymbolp_vec *osyms,
1695 struct asymbolp_vec *isyms)
1697 asymbol **symp;
1698 struct superbfd *sbfd = fetch_superbfd(ibfd);
1699 for (symp = isyms->data; symp < isyms->data + isyms->size; symp++) {
1700 asymbol *sym = *symp;
1701 struct supersect *sym_ss = NULL;
1702 if (!bfd_is_const_section(sym->section))
1703 sym_ss = fetch_supersect(sbfd, sym->section);
1705 bool keep = false;
1707 if (mode("keep") && (sym->flags & BSF_GLOBAL) != 0 &&
1708 !(mode("keep-primary") && sym_ss != NULL && sym_ss->new))
1709 sym->flags = (sym->flags & ~BSF_GLOBAL) | BSF_LOCAL;
1711 if (mode("finalize") && (sym->flags & BSF_GLOBAL) != 0)
1712 sym->flags = (sym->flags & ~BSF_GLOBAL) | BSF_LOCAL;
1714 if ((sym->flags & BSF_KEEP) != 0 /* Used in relocation. */
1715 || ((sym->flags & BSF_SECTION_SYM) != 0 && sym_ss != NULL &&
1716 sym_ss->keep))
1717 keep = true;
1718 else if ((sym->flags & (BSF_GLOBAL | BSF_WEAK)) != 0 &&
1719 sym_ss != NULL && sym_ss->keep)
1720 keep = true;
1721 else if (mode("keep-primary") &&
1722 starts_with(sym->section->name, "__ksymtab"))
1723 keep = true;
1725 if (deleted_table_section_symbol(ibfd, sym))
1726 keep = false;
1728 if (bfd_is_com_section(sym->section))
1729 keep = false;
1731 if (mode("rmsyms"))
1732 keep = !str_in_set(sym->name, &rmsyms);
1734 if (keep) {
1735 assert(sym_ss == NULL || sym_ss->keep);
1736 *vec_grow(osyms, 1) = sym;
1741 void read_str_set(struct str_vec *strs)
1743 char *buf = NULL;
1744 size_t n = 0;
1745 assert(getline(&buf, &n, stdin) >= 0);
1746 vec_init(strs);
1747 char *saveptr;
1748 while (1) {
1749 char *str = strtok_r(buf, " \n", &saveptr);
1750 buf = NULL;
1751 if (str == NULL)
1752 break;
1753 *vec_grow(strs, 1) = str;
1757 bool str_in_set(const char *str, const struct str_vec *strs)
1759 const char **strp;
1760 for (strp = strs->data; strp < strs->data + strs->size; strp++) {
1761 if (strcmp(str, *strp) == 0)
1762 return true;
1764 return false;
1767 bool is_table_section(const char *name, bool consider_other)
1769 struct supersect *tables_ss =
1770 fetch_supersect(offsets_sbfd,
1771 bfd_get_section_by_name(offsets_sbfd->abfd,
1772 ".ksplice_table_sections"));
1773 const struct table_section *ts;
1774 for (ts = tables_ss->contents.data;
1775 (void *)ts < tables_ss->contents.data + tables_ss->contents.size;
1776 ts++) {
1777 if (strcmp(name, read_string(tables_ss, &ts->sect)) == 0)
1778 return true;
1779 const char *osect_name = read_string(tables_ss,
1780 &ts->other_sect);
1781 if (consider_other && osect_name != NULL &&
1782 strcmp(name, osect_name) == 0)
1783 return true;
1785 return false;
1788 enum supersect_type supersect_type(struct supersect *ss)
1790 if (starts_with(ss->name, ".ksplice"))
1791 return SS_TYPE_KSPLICE;
1793 if (starts_with(ss->name, ".init"))
1794 return SS_TYPE_IGNORED;
1795 if (starts_with(ss->name, ".security_initcall.init"))
1796 return SS_TYPE_IGNORED;
1797 if (starts_with(ss->name, ".con_initcall.init"))
1798 return SS_TYPE_IGNORED;
1799 if (starts_with(ss->name, ".x86cpuvendor.init"))
1800 return SS_TYPE_IGNORED;
1801 if (starts_with(ss->name, ".early_param.init"))
1802 return SS_TYPE_IGNORED;
1803 if (starts_with(ss->name, ".taglist.init"))
1804 return SS_TYPE_IGNORED;
1805 if (starts_with(ss->name, ".arch.info.init"))
1806 return SS_TYPE_IGNORED;
1807 if (starts_with(ss->name, ".proc.info.init"))
1808 return SS_TYPE_IGNORED;
1809 /* .pci_fixup_* sections really should be treated as global rodata
1810 referenced only from quirks.c */
1811 if (starts_with(ss->name, ".pci_fixup_"))
1812 return SS_TYPE_IGNORED;
1813 /* .builtin_fw sections are similar to .pci_fixup */
1814 if (starts_with(ss->name, ".builtin_fw"))
1815 return SS_TYPE_IGNORED;
1816 /* same for .tracedata */
1817 if (starts_with(ss->name, ".tracedata"))
1818 return SS_TYPE_IGNORED;
1819 if (starts_with(ss->name, ".debug"))
1820 return SS_TYPE_IGNORED;
1821 /* .eh_frame should probably be discarded, not ignored */
1822 if (starts_with(ss->name, ".eh_frame"))
1823 return SS_TYPE_IGNORED;
1824 if (config->ignore_devinit && starts_with(ss->name, ".devinit"))
1825 return SS_TYPE_IGNORED;
1826 if (config->ignore_meminit && starts_with(ss->name, ".meminit"))
1827 return SS_TYPE_IGNORED;
1828 if (config->ignore_cpuinit && starts_with(ss->name, ".cpuinit"))
1829 return SS_TYPE_IGNORED;
1830 if (config->ignore_devinit && starts_with(ss->name, ".devexit"))
1831 return SS_TYPE_IGNORED;
1832 if (config->ignore_meminit && starts_with(ss->name, ".memexit"))
1833 return SS_TYPE_IGNORED;
1834 if (config->ignore_cpuinit && starts_with(ss->name, ".cpuexit"))
1835 return SS_TYPE_IGNORED;
1836 if (starts_with(ss->name, ".vgetcpu_mode") ||
1837 starts_with(ss->name, ".jiffies") ||
1838 starts_with(ss->name, ".wall_jiffies") ||
1839 starts_with(ss->name, ".vxtime") ||
1840 starts_with(ss->name, ".sys_tz") ||
1841 starts_with(ss->name, ".sysctl_vsyscall") ||
1842 starts_with(ss->name, ".xtime") ||
1843 starts_with(ss->name, ".xtime_lock") ||
1844 starts_with(ss->name, ".vsyscall"))
1845 return SS_TYPE_IGNORED;
1846 if (starts_with(ss->name, ".vdso"))
1847 return SS_TYPE_IGNORED;
1849 if (bfd_get_section_by_name(ss->parent->abfd, ".exitcall.exit") == NULL) {
1850 if (starts_with(ss->name, ".exit.text"))
1851 return SS_TYPE_TEXT;
1852 if (starts_with(ss->name, ".exit.data"))
1853 return SS_TYPE_DATA;
1854 } else if (starts_with(ss->name, ".exit.text") ||
1855 starts_with(ss->name, ".exit.data"))
1856 return SS_TYPE_IGNORED;
1858 if (starts_with(ss->name, ".text") ||
1859 starts_with(ss->name, ".kernel.text") ||
1860 starts_with(ss->name, ".devinit.text") ||
1861 starts_with(ss->name, ".meminit.text") ||
1862 starts_with(ss->name, ".cpuinit.text") ||
1863 starts_with(ss->name, ".devexit.text") ||
1864 starts_with(ss->name, ".memexit.text") ||
1865 starts_with(ss->name, ".cpuexit.text") ||
1866 starts_with(ss->name, ".ref.text") ||
1867 starts_with(ss->name, ".spinlock.text") ||
1868 starts_with(ss->name, ".kprobes.text") ||
1869 starts_with(ss->name, ".sched.text"))
1870 return SS_TYPE_TEXT;
1872 int n = -1;
1873 if (sscanf(ss->name, ".rodata.str%*u.%*u%n", &n) >= 0 &&
1874 n == strlen(ss->name))
1875 return SS_TYPE_STRING;
1877 if (starts_with(ss->name, ".rodata") ||
1878 starts_with(ss->name, ".kernel.rodata") ||
1879 starts_with(ss->name, ".devinit.rodata") ||
1880 starts_with(ss->name, ".meminit.rodata") ||
1881 starts_with(ss->name, ".cpuinit.rodata") ||
1882 starts_with(ss->name, ".devexit.rodata") ||
1883 starts_with(ss->name, ".memexit.rodata") ||
1884 starts_with(ss->name, ".cpuexit.rodata") ||
1885 starts_with(ss->name, ".ref.rodata") ||
1886 starts_with(ss->name, "__markers_strings"))
1887 return SS_TYPE_RODATA;
1889 if (starts_with(ss->name, ".bss"))
1890 return SS_TYPE_DATA;
1892 /* Ignore .data.percpu sections */
1893 if (starts_with(ss->name, ".data.percpu") ||
1894 starts_with(ss->name, ".kernel.data.percpu"))
1895 return SS_TYPE_IGNORED;
1896 if (starts_with(ss->name, ".data") ||
1897 starts_with(ss->name, ".kernel.data") ||
1898 starts_with(ss->name, ".devinit.data") ||
1899 starts_with(ss->name, ".cpuinit.data") ||
1900 starts_with(ss->name, ".meminit.data") ||
1901 starts_with(ss->name, ".devexit.data") ||
1902 starts_with(ss->name, ".memexit.data") ||
1903 starts_with(ss->name, ".cpuexit.data") ||
1904 starts_with(ss->name, ".ref.data") ||
1905 starts_with(ss->name, "__markers"))
1906 return SS_TYPE_DATA;
1908 if (starts_with(ss->name, "__ksymtab"))
1909 return SS_TYPE_EXPORT;
1910 if (starts_with(ss->name, "__kcrctab"))
1911 return SS_TYPE_EXPORT;
1913 if (is_table_section(ss->name, true))
1914 return SS_TYPE_SPECIAL;
1916 if (starts_with(ss->name, ".ARM."))
1917 return SS_TYPE_SPECIAL;
1919 if (starts_with(ss->name, ".note"))
1920 return SS_TYPE_IGNORED;
1921 if (starts_with(ss->name, ".comment"))
1922 return SS_TYPE_IGNORED;
1923 if (starts_with(ss->name, "__param"))
1924 return SS_TYPE_IGNORED;
1925 if (starts_with(ss->name, ".exitcall.exit"))
1926 return SS_TYPE_IGNORED;
1927 if (starts_with(ss->name, ".modinfo"))
1928 return SS_TYPE_IGNORED;
1930 return SS_TYPE_UNKNOWN;
1933 void initialize_supersect_types(struct superbfd *sbfd)
1935 asection *sect;
1936 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
1937 struct supersect *ss = fetch_supersect(sbfd, sect);
1938 ss->type = supersect_type(ss);
1939 if (ss->type == SS_TYPE_UNKNOWN) {
1940 fprintf(stderr, "Unknown section type: %s\n", ss->name);
1941 DIE;