Use a binary search to speed up bulk kallsyms lookups.
[ksplice.git] / objmanip.c
blob829c65c7ba309a7ba028d90e5c83feb91483d526
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 struct supersect *ss;
70 DECLARE_VEC_TYPE(struct export, export_vec);
72 DECLARE_VEC_TYPE(const char *, str_vec);
74 struct export_desc {
75 const char *export_type;
76 bool deletion;
77 struct str_vec names;
78 struct supersect *sym_ss;
79 struct supersect *crc_ss;
81 DECLARE_VEC_TYPE(struct export_desc, export_desc_vec);
83 #define bool_init(b) *(b) = false
84 DEFINE_HASH_TYPE(bool, bool_hash, bool_hash_init, bool_hash_free,
85 bool_hash_lookup, bool_init);
87 #define ulong_init(x) *(x) = 0
88 DEFINE_HASH_TYPE(unsigned long, ulong_hash, ulong_hash_init,
89 ulong_hash_free, ulong_hash_lookup, ulong_init);
91 void do_keep_primary(struct superbfd *isbfd, const char *pre);
92 void do_keep_helper(struct superbfd *isbfd);
93 void do_finalize(struct superbfd *isbfd);
94 void do_rmsyms(struct superbfd *isbfd);
96 struct export_vec *get_export_syms(struct superbfd *sbfd);
97 void compare_exported_symbols(struct superbfd *oldsbfd,
98 struct superbfd *newsbfd, bool deletion);
99 struct export_desc *new_export_desc(struct supersect *ss, bool deletion);
100 bool relocs_equal(struct supersect *old_src_ss, struct supersect *new_src_ss,
101 arelent *old_reloc, arelent *new_reloc);
102 bool all_relocs_equal(struct supersect *old_ss, struct supersect *new_ss);
103 static bool part_of_reloc(struct supersect *ss, unsigned long addr);
104 static bool nonrelocs_equal(struct supersect *old_ss, struct supersect *new_ss);
105 static void handle_section_symbol_renames(struct superbfd *oldsbfd,
106 struct superbfd *newsbfd);
108 enum supersect_type supersect_type(struct supersect *ss);
109 void initialize_supersect_types(struct superbfd *sbfd);
110 static void initialize_spans(struct superbfd *sbfd);
111 static void initialize_string_spans(struct supersect *ss);
112 struct span *reloc_target_span(struct supersect *ss, arelent *reloc);
113 struct span *reloc_address_span(struct supersect *ss, arelent *reloc);
114 void remove_unkept_spans(struct superbfd *sbfd);
115 void compute_span_shifts(struct superbfd *sbfd);
116 static struct span *new_span(struct supersect *ss, bfd_vma start, bfd_vma size);
117 bool is_table_section(const char *name, bool consider_other);
119 void rm_relocs(struct superbfd *isbfd);
120 void rm_some_relocs(struct supersect *ss);
121 void write_ksplice_reloc(struct supersect *ss, arelent *orig_reloc);
122 void blot_section(struct supersect *ss, int offset, reloc_howto_type *howto);
123 static void write_ksplice_section(struct span *span);
124 void write_ksplice_patch(struct superbfd *sbfd, const char *sectname);
125 void write_ksplice_deleted_patch(struct superbfd *sbfd, const char *name,
126 const char *label);
127 void filter_table_sections(struct superbfd *isbfd);
128 void filter_table_section(struct superbfd *sbfd, const struct table_section *s);
129 void keep_referenced_sections(struct superbfd *sbfd);
130 bfd_boolean copy_object(bfd *ibfd, bfd *obfd);
131 void setup_section(bfd *ibfd, asection *isection, void *obfdarg);
132 static void setup_new_section(bfd *obfd, struct supersect *ss);
133 static void write_section(bfd *obfd, asection *osection, void *arg);
134 static void delete_obsolete_relocs(struct supersect *ss);
135 void mark_symbols_used_in_relocations(bfd *abfd, asection *isection,
136 void *ignored);
137 static void ss_mark_symbols_used_in_relocations(struct supersect *ss);
138 void filter_symbols(bfd *ibfd, bfd *obfd, struct asymbolp_vec *osyms,
139 struct asymbolp_vec *isyms);
140 static bool deleted_table_section_symbol(bfd *abfd, asymbol *sym);
141 void read_str_set(struct str_vec *strs);
142 bool str_in_set(const char *str, const struct str_vec *strs);
143 struct supersect *make_section(struct superbfd *sbfd, const char *name);
144 void __attribute__((format(printf, 3, 4)))
145 write_string(struct supersect *ss, const char **addr, const char *fmt, ...);
146 void rm_some_exports(struct superbfd *isbfd, const struct export_desc *ed);
147 void write_ksplice_export(struct superbfd *sbfd, const char *symname,
148 const char *export_type, bool del);
149 void write_reloc(struct supersect *ss, const void *addr, asymbol **symp,
150 bfd_vma offset);
151 arelent *create_reloc(struct supersect *ss, const void *addr, asymbol **symp,
152 bfd_vma offset);
153 static void match_global_symbol_sections(struct superbfd *oldsbfd,
154 struct superbfd *newsbfd);
155 static void match_sections_by_name(struct superbfd *oldsbfd,
156 struct superbfd *newsbfd);
157 static void match_sections_by_label(struct superbfd *oldsbfd,
158 struct superbfd *newsbfd);
159 static void mark_new_sections(struct superbfd *sbfd);
160 static void handle_deleted_sections(struct superbfd *oldsbfd,
161 struct superbfd *newsbfd);
162 static void compare_matched_sections(struct superbfd *sbfd);
163 static void update_nonzero_offsets(struct superbfd *sbfd);
164 static void handle_nonzero_offset_relocs(struct supersect *ss);
166 static const char *label_lookup(struct superbfd *sbfd, asymbol *sym);
167 static void print_label_map(struct superbfd *sbfd);
168 static void label_map_set(struct superbfd *sbfd, const char *oldlabel,
169 const char *label);
170 static void init_label_map(struct superbfd *sbfd);
171 static asymbol **symbolp_scan(struct supersect *ss, bfd_vma value);
172 static void init_csyms(struct superbfd *sbfd);
173 static void init_callers(struct superbfd *sbfd);
174 static asymbol *canonical_symbol(struct superbfd *sbfd, asymbol *sym);
175 static asymbol **canonical_symbolp(struct superbfd *sbfd, asymbol *sym);
176 static char *static_local_symbol(struct superbfd *sbfd, asymbol *sym);
177 static char *symbol_label(struct superbfd *sbfd, asymbol *sym);
179 int verbose = 0;
180 #define debug_(sbfd, level, fmt, ...) \
181 do { \
182 if (verbose >= (level)) \
183 printf("%s: " fmt, (sbfd)->abfd->filename, \
184 ## __VA_ARGS__); \
185 } while (0)
186 #define debug0(sbfd, fmt, ...) debug_(sbfd, 0, fmt, ## __VA_ARGS__)
187 #define debug1(sbfd, fmt, ...) debug_(sbfd, 1, fmt, ## __VA_ARGS__)
188 #define err(sbfd, fmt, ...) \
189 do { \
190 fprintf(stderr, "%s: " fmt, (sbfd)->abfd->filename, \
191 ## __VA_ARGS__); \
192 } while (0)
194 struct str_vec delsects, rmsyms;
195 struct export_desc_vec exports;
196 bool changed;
198 struct ksplice_config *config;
200 const char *modestr, *kid;
202 struct superbfd *offsets_sbfd = NULL;
204 #define mode(str) starts_with(modestr, str)
206 DECLARE_VEC_TYPE(unsigned long, addr_vec);
207 DEFINE_HASH_TYPE(struct addr_vec, addr_vec_hash,
208 addr_vec_hash_init, addr_vec_hash_free, addr_vec_hash_lookup,
209 vec_init);
210 struct addr_vec_hash system_map;
212 struct bool_hash system_map_written;
213 struct ulong_hash ksplice_symbol_offset;
214 struct ulong_hash ksplice_string_offset;
216 void load_system_map()
218 const char *config_dir = getenv("KSPLICE_CONFIG_DIR");
219 assert(config_dir);
220 char *file;
221 assert(asprintf(&file, "%s/System.map", config_dir) >= 0);
222 FILE *fp = fopen(file, "r");
223 assert(fp);
224 addr_vec_hash_init(&system_map);
225 unsigned long addr;
226 char type;
227 char *sym;
228 while (fscanf(fp, "%lx %c %as\n", &addr, &type, &sym) == 3)
229 *vec_grow(addr_vec_hash_lookup(&system_map, sym, TRUE),
230 1) = addr;
231 fclose(fp);
234 void load_offsets()
236 char *kmodsrc = getenv("KSPLICE_KMODSRC"), *offsets_file;
237 assert(kmodsrc != NULL);
238 assert(asprintf(&offsets_file, "%s/offsets.o", kmodsrc) >= 0);
239 bfd *offsets_bfd = bfd_openr(offsets_file, NULL);
240 assert(offsets_bfd != NULL);
241 char **matching;
242 assert(bfd_check_format_matches(offsets_bfd, bfd_object, &matching));
243 offsets_sbfd = fetch_superbfd(offsets_bfd);
245 asection *config_sect = bfd_get_section_by_name(offsets_sbfd->abfd,
246 ".ksplice_config");
247 struct supersect *config_ss =
248 fetch_supersect(offsets_sbfd, config_sect);
250 config = config_ss->contents.data;
253 bool matchable_data_section(struct supersect *ss)
255 if (ss->type == SS_TYPE_STRING)
256 return true;
257 if (ss->type == SS_TYPE_RODATA)
258 return true;
259 if (ss->type == SS_TYPE_DATA && ss->relocs.size != 0)
260 return true;
261 return false;
264 bool unchangeable_section(struct supersect *ss)
266 if (ss->type == SS_TYPE_DATA)
267 return true;
268 if (ss->type == SS_TYPE_IGNORED && !starts_with(ss->name, ".debug") &&
269 strcmp(ss->name, "__ksymtab_strings") != 0)
270 return true;
271 return false;
274 int main(int argc, char *argv[])
276 if (getenv("KSPLICE_VERBOSE") != NULL)
277 verbose = atoi(getenv("KSPLICE_VERBOSE"));
279 bfd_init();
280 bfd *ibfd = bfd_openr(argv[1], NULL);
281 assert(ibfd);
283 char **matching;
284 assert(bfd_check_format_matches(ibfd, bfd_object, &matching));
286 const char *output_target = bfd_get_target(ibfd);
287 bfd *obfd = bfd_openw(argv[2], output_target);
288 assert(obfd);
290 struct superbfd *isbfd = fetch_superbfd(ibfd);
291 init_label_map(isbfd);
293 bool_hash_init(&system_map_written);
294 ulong_hash_init(&ksplice_symbol_offset);
295 ulong_hash_init(&ksplice_string_offset);
297 modestr = argv[3];
298 if (mode("keep-primary")) {
299 kid = argv[5];
300 do_keep_primary(isbfd, argv[4]);
301 } else if (mode("keep-helper")) {
302 do_keep_helper(isbfd);
303 } else if (mode("finalize")) {
304 do_finalize(isbfd);
305 } else if (mode("rmsyms")) {
306 do_rmsyms(isbfd);
309 copy_object(ibfd, obfd);
311 if (offsets_sbfd != NULL)
312 assert(bfd_close(offsets_sbfd->abfd));
313 assert(bfd_close(obfd));
314 assert(bfd_close(ibfd));
315 return EXIT_SUCCESS;
318 void do_keep_primary(struct superbfd *isbfd, const char *pre)
320 struct bfd *prebfd = bfd_openr(pre, NULL);
321 assert(prebfd != NULL);
322 char **matching;
323 assert(bfd_check_format_matches(prebfd, bfd_object, &matching));
325 struct superbfd *presbfd = fetch_superbfd(prebfd);
326 init_label_map(presbfd);
327 load_system_map();
328 load_offsets();
329 initialize_supersect_types(isbfd);
330 initialize_supersect_types(presbfd);
332 match_global_symbol_sections(presbfd, isbfd);
333 debug1(isbfd, "Matched global\n");
334 match_sections_by_name(presbfd, isbfd);
335 debug1(isbfd, "Matched by name\n");
336 match_sections_by_label(presbfd, isbfd);
337 debug1(isbfd, "Matched by label\n");
339 do {
340 changed = false;
341 compare_matched_sections(isbfd);
342 update_nonzero_offsets(isbfd);
343 mark_new_sections(isbfd);
344 } while (changed);
345 vec_init(&delsects);
347 handle_deleted_sections(presbfd, isbfd);
348 handle_section_symbol_renames(presbfd, isbfd);
350 vec_init(&exports);
351 compare_exported_symbols(presbfd, isbfd, false);
352 compare_exported_symbols(isbfd, presbfd, true);
354 initialize_spans(isbfd);
355 initialize_spans(presbfd);
356 asection *sect;
357 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
358 struct supersect *ss = fetch_supersect(isbfd, sect);
359 if (ss->type != SS_TYPE_STRING)
360 continue;
361 asection *oldsect = bfd_get_section_by_name(prebfd, sect->name);
362 if (oldsect == NULL)
363 continue;
364 struct supersect *old_ss = fetch_supersect(presbfd, oldsect);
365 struct span *span, *old_span;
366 for (span = ss->spans.data;
367 span < ss->spans.data + ss->spans.size; span++) {
368 span->new = true;
369 for (old_span = old_ss->spans.data;
370 old_span < old_ss->spans.data + old_ss->spans.size;
371 old_span++) {
372 if (strcmp((char *)ss->contents.data +
373 span->start,
374 (char *)old_ss->contents.data +
375 old_span->start) == 0) {
376 if (!span->new)
377 DIE;
378 span->label = old_span->label;
379 span->new = false;
384 assert(bfd_close(prebfd));
386 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
387 struct supersect *ss = fetch_supersect(isbfd, sect);
388 ss->keep = false;
389 if (ss->type == SS_TYPE_STRING || ss->type == SS_TYPE_SPECIAL ||
390 ss->type == SS_TYPE_EXPORT)
391 ss->keep = true;
392 if (ss->new || ss->patch)
393 ss->keep = true;
396 print_label_map(isbfd);
398 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
399 struct supersect *ss = fetch_supersect(isbfd, sect);
400 if (ss->patch)
401 debug0(isbfd, "Patching section: %s\n", sect->name);
404 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
405 struct supersect *ss = fetch_supersect(isbfd, sect);
406 if (ss->new)
407 debug0(isbfd, "New section: %s\n", sect->name);
410 const char **sectname;
411 for (sectname = delsects.data;
412 sectname < delsects.data + delsects.size; sectname++)
413 debug0(isbfd, "Deleted section: %s\n", *sectname);
415 const struct export_desc *ed;
416 for (ed = exports.data; ed < exports.data + exports.size; ed++) {
417 const char **symname;
418 for (symname = ed->names.data;
419 symname < ed->names.data + ed->names.size; symname++)
420 debug0(isbfd, "Export %s (%s): %s\n",
421 ed->deletion ? "deletion" : "addition",
422 ed->export_type, *symname);
425 struct span *span;
426 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
427 struct supersect *ss = fetch_supersect(isbfd, sect);
428 for (span = ss->spans.data;
429 span < ss->spans.data + ss->spans.size; span++)
430 span->keep = ss->keep;
433 filter_table_sections(isbfd);
434 for (ed = exports.data; ed < exports.data + exports.size; ed++) {
435 const char **symname;
436 for (symname = ed->names.data;
437 symname < ed->names.data + ed->names.size; symname++)
438 write_ksplice_export(isbfd, *symname,
439 ed->export_type, ed->deletion);
440 if (!ed->deletion)
441 rm_some_exports(isbfd, ed);
444 compute_span_shifts(isbfd);
446 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
447 struct supersect *ss = fetch_supersect(isbfd, sect);
448 if (!ss->patch && !ss->new)
449 continue;
451 struct span *span;
452 for (span = ss->spans.data;
453 span < ss->spans.data + ss->spans.size; span++)
454 write_ksplice_section(span);
456 if (ss->patch)
457 write_ksplice_patch(isbfd, sect->name);
460 rm_relocs(isbfd);
461 remove_unkept_spans(isbfd);
464 void do_keep_helper(struct superbfd *isbfd)
466 load_system_map();
467 load_offsets();
468 initialize_supersect_types(isbfd);
469 initialize_spans(isbfd);
471 asection *sect;
472 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
473 struct supersect *ss = fetch_supersect(isbfd, sect);
474 ss->keep = false;
475 if (ss->type == SS_TYPE_SPECIAL || ss->type == SS_TYPE_TEXT)
476 ss->keep = true;
479 asymbol **symp;
480 for (symp = isbfd->syms.data;
481 symp < isbfd->syms.data + isbfd->syms.size; symp++) {
482 asymbol *sym = *symp;
483 if (!bfd_is_const_section(sym->section) &&
484 (sym->flags & BSF_GLOBAL) != 0) {
485 struct supersect *sym_ss =
486 fetch_supersect(isbfd, sym->section);
487 if (sym_ss->type != SS_TYPE_IGNORED)
488 sym_ss->keep = true;
492 struct span *span;
493 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
494 struct supersect *ss = fetch_supersect(isbfd, sect);
495 for (span = ss->spans.data;
496 span < ss->spans.data + ss->spans.size; span++)
497 span->keep = ss->keep;
500 do {
501 changed = false;
502 keep_referenced_sections(isbfd);
503 } while (changed);
505 filter_table_sections(isbfd);
506 compute_span_shifts(isbfd);
508 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
509 struct supersect *ss = fetch_supersect(isbfd, sect);
510 asymbol *sym = canonical_symbol(isbfd, sect->symbol);
511 if (sym == NULL)
512 continue;
513 if ((sym->flags & BSF_WEAK) != 0)
514 continue;
515 if (bfd_get_section_size(sect) == 0)
516 continue;
517 if (!ss->keep)
518 continue;
519 if (ss->type != SS_TYPE_TEXT && !matchable_data_section(ss))
520 continue;
522 struct span *span;
523 for (span = ss->spans.data;
524 span < ss->spans.data + ss->spans.size; span++) {
525 if (span->keep)
526 write_ksplice_section(span);
530 rm_relocs(isbfd);
531 remove_unkept_spans(isbfd);
534 void do_finalize(struct superbfd *isbfd)
536 load_system_map();
537 load_offsets();
538 initialize_supersect_types(isbfd);
539 initialize_spans(isbfd);
540 rm_relocs(isbfd);
543 void do_rmsyms(struct superbfd *isbfd)
545 read_str_set(&rmsyms);
546 load_system_map();
547 load_offsets();
548 initialize_supersect_types(isbfd);
549 initialize_spans(isbfd);
550 rm_relocs(isbfd);
553 struct export_vec *get_export_syms(struct superbfd *sbfd)
555 asection *sect;
556 struct export_vec *exports;
557 exports = malloc(sizeof(*exports));
558 assert(exports != NULL);
559 vec_init(exports);
561 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
562 if (!starts_with(sect->name, "__ksymtab") ||
563 ends_with(sect->name, "_strings"))
564 continue;
565 struct supersect *ss = fetch_supersect(sbfd, sect);
566 struct kernel_symbol *sym;
567 assert(ss->contents.size * 2 == ss->relocs.size *
568 sizeof(struct kernel_symbol));
569 for (sym = ss->contents.data;
570 (void *)sym < ss->contents.data + ss->contents.size;
571 sym++) {
572 struct export *exp = vec_grow(exports, 1);
573 exp->name =
574 read_string(ss, (const char *const *)&sym->name);
575 exp->ss = ss;
578 return exports;
581 struct export_desc *new_export_desc(struct supersect *ss, bool deletion)
583 struct export_desc *ed = vec_grow(&exports, 1);
584 ed->deletion = deletion;
585 vec_init(&ed->names);
586 ed->export_type = strdup(ss->name) + strlen("__ksymtab");
587 ed->sym_ss = ss;
588 char *crc_sect_name;
589 assert(asprintf(&crc_sect_name, "__kcrctab%s", ed->export_type) >= 0);
590 asection *crc_sect =
591 bfd_get_section_by_name(ss->parent->abfd, crc_sect_name);
592 if (crc_sect == NULL)
593 ed->crc_ss = NULL;
594 else
595 ed->crc_ss = fetch_supersect(ss->parent, crc_sect);
596 return ed;
599 void compare_exported_symbols(struct superbfd *oldsbfd,
600 struct superbfd *newsbfd, bool deletion)
602 struct export_vec *new_exports, *old_exports;
603 new_exports = get_export_syms(newsbfd);
604 if (new_exports == NULL)
605 return;
606 old_exports = get_export_syms(oldsbfd);
607 struct export *old, *new;
608 struct supersect *last_ss = NULL;
609 struct export_desc *ed = NULL;
610 for (new = new_exports->data; new < new_exports->data +
611 new_exports->size; new++) {
612 bool found = false;
613 if (old_exports != NULL) {
614 for (old = old_exports->data; old < old_exports->data +
615 old_exports->size; old++) {
616 if (strcmp(new->name, old->name) == 0 &&
617 strcmp(new->ss->name, old->ss->name) == 0) {
618 found = true;
619 break;
623 if (last_ss != new->ss) {
624 last_ss = new->ss;
625 ed = new_export_desc(new->ss, deletion);
627 if (!found)
628 *vec_grow(&ed->names, 1) = new->name;
632 void match_sections(struct supersect *oldss, struct supersect *newss)
634 if (oldss->match == newss && newss->match == oldss)
635 return;
636 if (oldss->match != NULL) {
637 err(newss->parent, "Matching conflict: old %s: %s != %s\n",
638 oldss->name, oldss->match->name, newss->name);
639 DIE;
641 if (newss->match != NULL) {
642 err(newss->parent, "Matching conflict: new %s: %s != %s\n",
643 newss->name, newss->match->name, oldss->name);
644 DIE;
646 oldss->match = newss;
647 newss->match = oldss;
648 debug1(newss->parent, "Matched old %s to new %s\n",
649 oldss->name, newss->name);
652 static void match_global_symbol_sections(struct superbfd *oldsbfd,
653 struct superbfd *newsbfd)
655 asymbol **oldsymp, **newsymp;
656 for (oldsymp = oldsbfd->syms.data;
657 oldsymp < oldsbfd->syms.data + oldsbfd->syms.size; oldsymp++) {
658 asymbol *oldsym = *oldsymp;
659 if ((oldsym->flags & BSF_GLOBAL) == 0 ||
660 bfd_is_const_section(oldsym->section))
661 continue;
662 for (newsymp = newsbfd->syms.data;
663 newsymp < newsbfd->syms.data + newsbfd->syms.size;
664 newsymp++) {
665 asymbol *newsym = *newsymp;
666 if ((newsym->flags & BSF_GLOBAL) == 0 ||
667 bfd_is_const_section(oldsym->section))
668 continue;
669 if (strcmp(oldsym->name, newsym->name) != 0)
670 continue;
671 struct supersect *oldss =
672 fetch_supersect(oldsbfd, oldsym->section);
673 struct supersect *newss =
674 fetch_supersect(newsbfd, newsym->section);
675 match_sections(oldss, newss);
680 static void match_sections_by_name(struct superbfd *oldsbfd,
681 struct superbfd *newsbfd)
683 asection *newp, *oldp;
684 for (newp = newsbfd->abfd->sections; newp != NULL; newp = newp->next) {
685 struct supersect *newss = fetch_supersect(newsbfd, newp);
686 oldp = bfd_get_section_by_name(oldsbfd->abfd, newp->name);
687 if (oldp == NULL || newss->type == SS_TYPE_STRING ||
688 newss->type == SS_TYPE_SPECIAL ||
689 newss->type == SS_TYPE_EXPORT)
690 continue;
691 if (static_local_symbol(newsbfd,
692 canonical_symbol(newsbfd,
693 newp->symbol)))
694 continue;
696 struct supersect *oldss = fetch_supersect(oldsbfd, oldp);
697 match_sections(oldss, newss);
701 static void match_sections_by_label(struct superbfd *oldsbfd,
702 struct superbfd *newsbfd)
704 asection *oldsect, *newsect;
705 struct supersect *oldss, *newss;
706 for (newsect = newsbfd->abfd->sections; newsect != NULL;
707 newsect = newsect->next) {
708 newss = fetch_supersect(newsbfd, newsect);
709 if (newss->type == SS_TYPE_STRING ||
710 newss->type == SS_TYPE_SPECIAL ||
711 newss->type == SS_TYPE_EXPORT)
712 continue;
713 for (oldsect = oldsbfd->abfd->sections; oldsect != NULL;
714 oldsect = oldsect->next) {
715 if (strcmp(label_lookup(newsbfd, newsect->symbol),
716 label_lookup(oldsbfd, oldsect->symbol)) != 0)
717 continue;
718 oldss = fetch_supersect(oldsbfd, oldsect);
719 match_sections(oldss, newss);
724 static void mark_new_sections(struct superbfd *sbfd)
726 asection *sect;
727 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
728 struct supersect *ss = fetch_supersect(sbfd, sect);
729 if (ss->type == SS_TYPE_STRING || ss->type == SS_TYPE_SPECIAL ||
730 ss->type == SS_TYPE_IGNORED || ss->type == SS_TYPE_EXPORT)
731 continue;
732 if (ss->match == NULL)
733 ss->new = true;
737 static void handle_deleted_sections(struct superbfd *oldsbfd,
738 struct superbfd *newsbfd)
740 asection *sect;
741 for (sect = oldsbfd->abfd->sections; sect != NULL; sect = sect->next) {
742 struct supersect *ss = fetch_supersect(oldsbfd, sect);
743 if (ss->type != SS_TYPE_TEXT)
744 continue;
745 if (ss->match != NULL)
746 continue;
747 const char *label = label_lookup(oldsbfd, sect->symbol);
748 *vec_grow(&delsects, 1) = label;
749 asymbol *csym = canonical_symbol(oldsbfd, sect->symbol);
750 write_ksplice_deleted_patch(newsbfd, csym->name, label);
754 static void handle_nonzero_offset_relocs(struct supersect *ss)
756 int i;
757 for (i = 0; i < ss->relocs.size; i++) {
758 asymbol *sym = *ss->relocs.data[i]->sym_ptr_ptr;
759 bfd_vma offset = get_reloc_offset(ss, ss->relocs.data[i], true);
760 if (sym->value + offset == 0)
761 continue;
762 if (bfd_is_const_section(sym->section))
763 continue;
764 struct supersect *sym_ss = fetch_supersect(ss->parent,
765 sym->section);
766 if (sym_ss->type != SS_TYPE_TEXT)
767 continue;
768 if (!sym_ss->patch) {
769 changed = true;
770 debug1(ss->parent,
771 "Changing %s because a relocation from sect %s "
772 "has a nonzero offset %lx+%lx into it\n",
773 sym_ss->name, ss->name,
774 (unsigned long)sym->value,
775 (unsigned long)offset);
777 sym_ss->patch = true;
781 static void update_nonzero_offsets(struct superbfd *sbfd)
783 asection *sect;
784 struct supersect *ss;
786 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
787 ss = fetch_supersect(sbfd, sect);
788 if (ss->new || ss->patch)
789 handle_nonzero_offset_relocs(ss);
793 static void compare_matched_sections(struct superbfd *newsbfd)
795 asection *newp;
796 struct supersect *old_ss, *new_ss;
797 for (newp = newsbfd->abfd->sections; newp != NULL; newp = newp->next) {
798 new_ss = fetch_supersect(newsbfd, newp);
799 if (new_ss->match == NULL)
800 continue;
801 old_ss = new_ss->match;
803 if (nonrelocs_equal(old_ss, new_ss) &&
804 all_relocs_equal(old_ss, new_ss))
805 continue;
807 char *reason;
808 if (new_ss->contents.size != old_ss->contents.size)
809 reason = "differing sizes";
810 else if (memcmp(new_ss->contents.data, old_ss->contents.data,
811 new_ss->contents.size) != 0)
812 reason = "differing contents";
813 else
814 reason = "differing relocations";
815 if (new_ss->type == SS_TYPE_TEXT) {
816 if (new_ss->patch)
817 continue;
818 new_ss->patch = true;
819 debug1(newsbfd, "Changing %s due to %s\n", new_ss->name,
820 reason);
821 } else {
822 debug1(newsbfd, "Unmatching %s and %s due to %s\n",
823 old_ss->name, new_ss->name, reason);
824 new_ss->match = NULL;
825 old_ss->match = NULL;
827 changed = true;
828 if (unchangeable_section(new_ss))
829 err(newsbfd, "warning: ignoring change to nonpatchable "
830 "section %s\n", new_ss->name);
834 static void handle_section_symbol_renames(struct superbfd *oldsbfd,
835 struct superbfd *newsbfd)
837 asection *newp, *oldp;
838 for (newp = newsbfd->abfd->sections; newp != NULL; newp = newp->next) {
839 struct supersect *newss = fetch_supersect(newsbfd, newp);
840 if (newss->match == NULL)
841 continue;
842 oldp = bfd_get_section_by_name(oldsbfd->abfd,
843 newss->match->name);
844 if (oldp == NULL)
845 continue;
847 const char *old_label = label_lookup(oldsbfd, oldp->symbol);
848 const char *new_label = label_lookup(newsbfd, newp->symbol);
850 if (strcmp(old_label, new_label) == 0)
851 continue;
852 label_map_set(newsbfd, new_label, old_label);
856 static bool part_of_reloc(struct supersect *ss, unsigned long addr)
858 arelent **relocp;
859 for (relocp = ss->relocs.data;
860 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
861 arelent *reloc = *relocp;
862 if (addr >= reloc->address &&
863 addr < reloc->address + reloc->howto->size)
864 return true;
866 return false;
869 static bool nonrelocs_equal(struct supersect *old_ss, struct supersect *new_ss)
871 int i;
872 if (old_ss->contents.size != new_ss->contents.size)
873 return false;
874 const unsigned char *old = old_ss->contents.data;
875 const unsigned char *new = new_ss->contents.data;
876 for (i = 0; i < old_ss->contents.size; i++) {
877 if (old[i] != new[i] &&
878 !(part_of_reloc(old_ss, i) && part_of_reloc(new_ss, i)))
879 return false;
881 return true;
884 bool relocs_equal(struct supersect *old_src_ss, struct supersect *new_src_ss,
885 arelent *old_reloc, arelent *new_reloc)
887 if (old_reloc->address != new_reloc->address)
888 return false;
890 struct superbfd *oldsbfd = old_src_ss->parent;
891 struct superbfd *newsbfd = new_src_ss->parent;
892 asymbol *old_sym = *old_reloc->sym_ptr_ptr;
893 asymbol *new_sym = *new_reloc->sym_ptr_ptr;
894 asection *old_sect = old_sym->section;
895 asection *new_sect = new_sym->section;
897 bfd_vma old_offset = get_reloc_offset(old_src_ss, old_reloc, true);
898 bfd_vma new_offset = get_reloc_offset(new_src_ss, new_reloc, true);
900 if (bfd_is_und_section(old_sect) || bfd_is_und_section(new_sect)) {
901 if (!bfd_is_und_section(new_sect) && old_offset != 0 &&
902 fetch_supersect(newsbfd, new_sect)->type == SS_TYPE_TEXT)
903 return false;
905 if (!bfd_is_und_section(new_sect) && new_offset != 0 &&
906 fetch_supersect(oldsbfd, old_sect)->type == SS_TYPE_TEXT)
907 return false;
909 return strcmp(old_sym->name, new_sym->name) == 0 &&
910 old_offset == new_offset;
913 if (bfd_is_const_section(old_sect) || bfd_is_const_section(new_sect))
914 DIE;
916 struct supersect *old_ss = fetch_supersect(oldsbfd, old_sect);
917 struct supersect *new_ss = fetch_supersect(newsbfd, new_sect);
919 if (old_ss->type == SS_TYPE_STRING &&
920 /* check it's not an out-of-range relocation to a string;
921 we'll just compare entire sections for them */
922 !(old_offset >= old_ss->contents.size ||
923 new_offset >= new_ss->contents.size)) {
924 if (strcmp(old_ss->contents.data + old_sym->value + old_offset,
925 new_ss->contents.data + new_sym->value + new_offset)
926 != 0) {
927 debug0(newsbfd, "Section %s/%s has string difference "
928 "\"%s\"/\"%s\"\n", old_src_ss->name,
929 new_src_ss->name,
930 (const char *)(old_ss->contents.data +
931 old_sym->value + old_offset),
932 (const char *)(new_ss->contents.data +
933 new_sym->value + new_offset));
934 debug1(newsbfd, "Strings differ between %s and %s\n",
935 old_src_ss->name, new_src_ss->name);
936 return false;
938 return true;
941 if (old_ss->match != new_ss || new_ss->match != old_ss) {
942 debug1(newsbfd, "Nonmatching relocs from %s to %s/%s\n",
943 new_src_ss->name, new_ss->name, old_ss->name);
944 return false;
947 if (old_sym->value + old_offset != new_sym->value + new_offset) {
948 debug1(newsbfd, "Offsets to %s/%s differ between %s "
949 "and %s: %lx+%lx/%lx+%lx\n", old_ss->name,
950 new_ss->name, old_src_ss->name, new_src_ss->name,
951 (unsigned long)old_sym->value, (unsigned long)old_offset,
952 (unsigned long)new_sym->value,
953 (unsigned long)new_offset);
954 return false;
957 if ((old_sym->value + old_offset != 0 ||
958 new_sym->value + new_offset != 0) && new_ss->patch) {
959 debug1(newsbfd, "Relocation from %s to nonzero offsets "
960 "%lx+%lx/%lx+%lx in changed section %s\n",
961 new_src_ss->name, (unsigned long)old_sym->value,
962 (unsigned long)old_offset, (unsigned long)new_sym->value,
963 (unsigned long)new_offset, new_sym->section->name);
964 return false;
966 return true;
969 bool all_relocs_equal(struct supersect *old_ss, struct supersect *new_ss)
971 if (old_ss->relocs.size != new_ss->relocs.size) {
972 debug1(new_ss->parent, "Different reloc count between %s and "
973 "%s\n", old_ss->name, new_ss->name);
974 return false;
977 int i;
978 for (i = 0; i < old_ss->relocs.size; i++) {
979 if (!relocs_equal(old_ss, new_ss, old_ss->relocs.data[i],
980 new_ss->relocs.data[i]))
981 return false;
984 return true;
987 void rm_some_exports(struct superbfd *sbfd, const struct export_desc *ed)
989 struct supersect *ss = ed->sym_ss;
990 struct supersect *crc_ss = ed->crc_ss;
991 if (crc_ss != NULL)
992 assert(ss->contents.size * sizeof(unsigned long) ==
993 crc_ss->contents.size * sizeof(struct kernel_symbol));
995 struct kernel_symbol *ksym;
996 unsigned long *crc = NULL;
997 if (crc_ss != NULL)
998 crc = crc_ss->contents.data;
999 struct span *span, *crc_span;
1000 for (ksym = ss->contents.data;
1001 (void *)ksym < ss->contents.data + ss->contents.size;
1002 ksym++, crc++) {
1003 asymbol *sym;
1004 read_reloc(ss, &ksym->value, sizeof(ksym->value), &sym);
1005 span = new_span(ss, addr_offset(ss, ksym), sizeof(*ksym));
1006 span->keep = str_in_set(sym->name, &ed->names);
1008 if (crc_ss != NULL) {
1009 crc_span = new_span(crc_ss, addr_offset(crc_ss, crc),
1010 sizeof(*crc));
1011 crc_span->keep = span->keep;
1014 if (span->keep) {
1015 /* Replace name with a mangled name */
1016 write_string(ss, (const char **)&ksym->name,
1017 "DISABLED_%s_%s", sym->name, kid);
1022 void rm_relocs(struct superbfd *isbfd)
1024 asection *p;
1025 for (p = isbfd->abfd->sections; p != NULL; p = p->next) {
1026 struct supersect *ss = fetch_supersect(isbfd, p);
1027 if ((mode("keep") && ss->type == SS_TYPE_SPECIAL) ||
1028 ss->type == SS_TYPE_KSPLICE)
1029 continue;
1030 if (ss->keep || mode("rmsyms"))
1031 rm_some_relocs(ss);
1033 if (mode("finalize")) {
1034 p = bfd_get_section_by_name(isbfd->abfd, ".ksplice_patches");
1035 if (p != NULL) {
1036 struct supersect *ss = fetch_supersect(isbfd, p);
1037 rm_some_relocs(ss);
1042 void rm_some_relocs(struct supersect *ss)
1044 struct arelentp_vec orig_relocs;
1045 vec_move(&orig_relocs, &ss->relocs);
1047 arelent **relocp;
1048 for (relocp = orig_relocs.data;
1049 relocp < orig_relocs.data + orig_relocs.size; relocp++) {
1050 bool rm_reloc = false;
1051 asymbol *sym_ptr = *(*relocp)->sym_ptr_ptr;
1053 if (mode("rmsyms") && str_in_set(sym_ptr->name, &rmsyms) &&
1054 bfd_is_und_section(sym_ptr->section))
1055 rm_reloc = true;
1057 if (mode("keep"))
1058 rm_reloc = true;
1060 if (mode("keep-primary") &&
1061 (bfd_is_const_section(sym_ptr->section) ||
1062 fetch_supersect(ss->parent, sym_ptr->section)->new ||
1063 reloc_target_span(ss, *relocp)->new ||
1064 !reloc_address_span(ss, *relocp)->keep))
1065 rm_reloc = false;
1067 if (mode("finalize") && bfd_is_und_section(sym_ptr->section))
1068 rm_reloc = true;
1070 if (strcmp(sym_ptr->name, "mcount") == 0 &&
1071 bfd_is_und_section(sym_ptr->section))
1072 rm_reloc = false;
1074 if (rm_reloc)
1075 write_ksplice_reloc(ss, *relocp);
1076 else
1077 *vec_grow(&ss->relocs, 1) = *relocp;
1081 struct supersect *make_section(struct superbfd *sbfd, const char *name)
1083 asection *sect = bfd_get_section_by_name(sbfd->abfd, name);
1084 if (sect != NULL)
1085 return fetch_supersect(sbfd, sect);
1086 else
1087 return new_supersect(sbfd, name);
1090 arelent *create_reloc(struct supersect *ss, const void *addr, asymbol **symp,
1091 bfd_vma offset)
1093 bfd_reloc_code_real_type code;
1094 switch (bfd_arch_bits_per_address(ss->parent->abfd)) {
1095 case 32:
1096 code = BFD_RELOC_32;
1097 break;
1098 case 64:
1099 code = BFD_RELOC_64;
1100 break;
1101 default:
1102 DIE;
1105 arelent *reloc = malloc(sizeof(*reloc));
1106 reloc->sym_ptr_ptr = symp;
1107 reloc->address = addr_offset(ss, addr);
1108 reloc->howto = bfd_reloc_type_lookup(ss->parent->abfd, code);
1109 reloc->addend = offset;
1110 return reloc;
1113 void write_reloc(struct supersect *ss, const void *addr, asymbol **symp,
1114 bfd_vma offset)
1116 *vec_grow(&ss->new_relocs, 1) = create_reloc(ss, addr, symp, offset);
1119 void write_string(struct supersect *ss, const char **addr, const char *fmt, ...)
1121 va_list ap;
1122 struct supersect *str_ss = make_section(ss->parent, ".ksplice_str");
1123 char *str;
1124 va_start(ap, fmt);
1125 int len = vasprintf(&str, fmt, ap);
1126 assert(len >= 0);
1127 va_end(ap);
1129 unsigned long *str_offp = ulong_hash_lookup(&ksplice_string_offset, str,
1130 FALSE);
1131 if (str_offp == NULL) {
1132 char *buf = sect_grow(str_ss, len + 1, char);
1133 memcpy(buf, str, len + 1);
1134 str_offp = ulong_hash_lookup(&ksplice_string_offset, str, TRUE);
1135 *str_offp = addr_offset(str_ss, buf);
1138 write_reloc(ss, addr, &str_ss->symbol, *str_offp);
1141 void lookup_system_map(struct addr_vec *addrs, const char *name, long offset)
1143 struct addr_vec *map_addrs =
1144 addr_vec_hash_lookup(&system_map, name, FALSE);
1145 if (map_addrs == NULL)
1146 return;
1148 unsigned long *addr, *map_addr;
1149 for (map_addr = map_addrs->data;
1150 map_addr < map_addrs->data + map_addrs->size; map_addr++) {
1151 for (addr = addrs->data; addr < addrs->data + addrs->size;
1152 addr++) {
1153 if (*addr == *map_addr + offset)
1154 break;
1156 if (addr < addrs->data + addrs->size)
1157 continue;
1158 *vec_grow(addrs, 1) = *map_addr + offset;
1162 void write_system_map_array(struct superbfd *sbfd, struct supersect *ss,
1163 const unsigned long **sym_addrs,
1164 unsigned long *num_sym_addrs, asymbol *sym)
1166 struct addr_vec addrs;
1167 vec_init(&addrs);
1169 if (bfd_is_abs_section(sym->section)) {
1170 *vec_grow(&addrs, 1) = sym->value;
1171 } else if (bfd_is_und_section(sym->section)) {
1172 lookup_system_map(&addrs, sym->name, 0);
1173 } else if (!bfd_is_const_section(sym->section)) {
1174 asymbol **gsymp;
1175 for (gsymp = sbfd->syms.data;
1176 gsymp < sbfd->syms.data + sbfd->syms.size; gsymp++) {
1177 asymbol *gsym = *gsymp;
1178 if ((gsym->flags & BSF_DEBUGGING) == 0 &&
1179 gsym->section == sym->section)
1180 lookup_system_map(&addrs, gsym->name,
1181 sym->value - gsym->value);
1185 *num_sym_addrs = addrs.size;
1186 if (addrs.size != 0) {
1187 struct supersect *array_ss = make_section(sbfd,
1188 ".ksplice_array");
1189 void *buf = sect_grow(array_ss, addrs.size,
1190 typeof(*addrs.data));
1191 memcpy(buf, addrs.data, addrs.size * sizeof(*addrs.data));
1192 write_reloc(ss, sym_addrs, &array_ss->symbol,
1193 addr_offset(array_ss, buf));
1194 } else {
1195 *sym_addrs = NULL;
1198 vec_free(&addrs);
1201 void write_ksplice_system_map(struct superbfd *sbfd, asymbol *sym,
1202 const char *addstr_sect)
1204 struct supersect *smap_ss = make_section(sbfd, ".ksplice_system_map");
1205 struct ksplice_system_map *smap;
1206 const char *label = label_lookup(sbfd, sym);
1208 bool *done = bool_hash_lookup(&system_map_written, label, TRUE);
1209 if (*done)
1210 return;
1211 *done = true;
1213 smap = sect_grow(smap_ss, 1, struct ksplice_system_map);
1215 write_system_map_array(sbfd, smap_ss, &smap->candidates,
1216 &smap->nr_candidates, sym);
1217 write_string(smap_ss, &smap->label, "%s%s", label, addstr_sect);
1220 void write_ksplice_symbol(struct supersect *ss,
1221 const struct ksplice_symbol *const *addr,
1222 asymbol *sym, struct span *span,
1223 const char *addstr_sect)
1225 struct supersect *ksymbol_ss = make_section(ss->parent,
1226 ".ksplice_symbols");
1227 struct ksplice_symbol *ksymbol;
1228 unsigned long *ksymbol_offp;
1229 const char *label;
1230 char *output;
1231 if (span != NULL && span->start != 0)
1232 label = span->label;
1233 else
1234 label = label_lookup(ss->parent, sym);
1235 assert(asprintf(&output, "%s%s", label, addstr_sect) >= 0);
1237 ksymbol_offp = ulong_hash_lookup(&ksplice_symbol_offset, output, FALSE);
1238 if (ksymbol_offp != NULL) {
1239 write_reloc(ss, addr, &ksymbol_ss->symbol, *ksymbol_offp);
1240 return;
1242 ksymbol = sect_grow(ksymbol_ss, 1, struct ksplice_symbol);
1243 ksymbol_offp = ulong_hash_lookup(&ksplice_symbol_offset, output, TRUE);
1244 *ksymbol_offp = addr_offset(ksymbol_ss, ksymbol);
1246 write_reloc(ss, addr, &ksymbol_ss->symbol, *ksymbol_offp);
1247 write_string(ksymbol_ss, &ksymbol->label, "%s", output);
1249 if (span != NULL && span->symbol == NULL) {
1250 ksymbol->name = NULL;
1251 return;
1254 write_ksplice_system_map(ksymbol_ss->parent, sym, addstr_sect);
1256 if (bfd_is_und_section(sym->section) || (sym->flags & BSF_GLOBAL) != 0) {
1257 write_string(ksymbol_ss, &ksymbol->name, "%s", sym->name);
1258 } else if (bfd_is_const_section(sym->section)) {
1259 ksymbol->name = NULL;
1260 } else {
1261 asymbol *gsym = canonical_symbol(ss->parent, sym);
1263 if (gsym == NULL || (gsym->flags & BSF_SECTION_SYM) != 0)
1264 ksymbol->name = NULL;
1265 else
1266 write_string(ksymbol_ss, &ksymbol->name, "%s",
1267 gsym->name);
1271 void write_ksplice_reloc(struct supersect *ss, arelent *orig_reloc)
1273 asymbol *sym_ptr = *orig_reloc->sym_ptr_ptr;
1274 reloc_howto_type *howto = orig_reloc->howto;
1275 bfd_vma addend = get_reloc_offset(ss, orig_reloc, false);
1277 if (mode("finalize") && starts_with(ss->name, ".ksplice_patches")) {
1278 unsigned long *repladdr =
1279 ss->contents.data + orig_reloc->address;
1280 *repladdr = 0;
1281 return;
1284 struct span *span = reloc_target_span(ss, orig_reloc);
1285 if (span == ss->spans.data && span->start != addend)
1286 span = NULL;
1287 blot_section(ss, orig_reloc->address, howto);
1289 struct supersect *kreloc_ss = make_section(ss->parent,
1290 mode("rmsyms") ?
1291 ".ksplice_init_relocs" :
1292 ".ksplice_relocs");
1293 struct ksplice_reloc *kreloc = sect_grow(kreloc_ss, 1,
1294 struct ksplice_reloc);
1296 struct span *address_span = reloc_address_span(ss, orig_reloc);
1297 write_reloc(kreloc_ss, &kreloc->blank_addr,
1298 &ss->symbol, orig_reloc->address + address_span->shift);
1299 write_ksplice_symbol(kreloc_ss, &kreloc->symbol, sym_ptr, span, "");
1300 kreloc->pcrel = howto->pc_relative;
1301 if (span != NULL && span->start != 0)
1302 addend += sym_ptr->value - span->start;
1303 kreloc->addend = addend;
1304 kreloc->size = bfd_get_reloc_size(howto);
1305 kreloc->dst_mask = howto->dst_mask;
1306 kreloc->rightshift = howto->rightshift;
1307 kreloc->signed_addend =
1308 (howto->complain_on_overflow == complain_overflow_signed) ||
1309 (howto->complain_on_overflow == complain_overflow_bitfield);
1312 #define CANARY(x, canary) ((x & ~howto->dst_mask) | (canary & howto->dst_mask))
1314 void blot_section(struct supersect *ss, int offset, reloc_howto_type *howto)
1316 int bits = bfd_get_reloc_size(howto) * 8;
1317 void *address = ss->contents.data + offset;
1318 bfd_vma x = bfd_get(bits, ss->parent->abfd, address);
1319 x = (x & ~howto->dst_mask) |
1320 ((bfd_vma)KSPLICE_CANARY & howto->dst_mask);
1321 bfd_put(bits, ss->parent->abfd, x, address);
1324 static void write_ksplice_section(struct span *span)
1326 struct supersect *ss = span->ss;
1327 struct supersect *ksect_ss =
1328 make_section(ss->parent, ".ksplice_sections");
1329 struct ksplice_section *ksect = sect_grow(ksect_ss, 1,
1330 struct ksplice_section);
1331 asymbol *sym = span->symbol == NULL ? ss->symbol : span->symbol;
1333 write_ksplice_symbol(ksect_ss, &ksect->symbol, sym, span,
1334 mode("keep-primary") ? "(post)" : "");
1335 ksect->size = span->size;
1336 ksect->flags = 0;
1338 if (ss->type == SS_TYPE_RODATA || ss->type == SS_TYPE_STRING)
1339 ksect->flags |= KSPLICE_SECTION_RODATA;
1340 if (ss->type == SS_TYPE_DATA)
1341 ksect->flags |= KSPLICE_SECTION_DATA;
1342 if (ss->type == SS_TYPE_TEXT)
1343 ksect->flags |= KSPLICE_SECTION_TEXT;
1344 assert(ksect->flags != 0);
1345 write_reloc(ksect_ss, &ksect->address, &ss->symbol,
1346 span->start + span->shift);
1349 void write_ksplice_patch(struct superbfd *sbfd, const char *sectname)
1351 struct supersect *kpatch_ss = make_section(sbfd, ".ksplice_patches");
1352 struct ksplice_patch *kpatch = sect_grow(kpatch_ss, 1,
1353 struct ksplice_patch);
1354 asection *sect = bfd_get_section_by_name(sbfd->abfd, sectname);
1355 assert(sect != NULL);
1357 write_string(kpatch_ss, &kpatch->label, "%s",
1358 label_lookup(sbfd, sect->symbol));
1359 write_reloc(kpatch_ss, &kpatch->repladdr, &sect->symbol, 0);
1362 void write_ksplice_deleted_patch(struct superbfd *sbfd, const char *name,
1363 const char *label)
1365 struct supersect *kpatch_ss = make_section(sbfd, ".ksplice_patches");
1366 struct ksplice_patch *kpatch = sect_grow(kpatch_ss, 1,
1367 struct ksplice_patch);
1369 write_string(kpatch_ss, &kpatch->label, "%s", label);
1370 asymbol **symp;
1371 for (symp = sbfd->syms.data; symp < sbfd->syms.data + sbfd->syms.size;
1372 symp++) {
1373 asymbol *sym = *symp;
1374 if (bfd_is_und_section(sym->section) &&
1375 strcmp(name, sym->name) == 0)
1376 break;
1378 if (symp >= sbfd->syms.data + sbfd->syms.size) {
1379 symp = malloc(sizeof(*symp));
1380 *symp = bfd_make_empty_symbol(sbfd->abfd);
1381 asymbol *sym = *symp;
1382 sym->name = strdup(name);
1383 sym->section = bfd_und_section_ptr;
1384 sym->flags = 0;
1385 sym->value = 0;
1386 *vec_grow(&sbfd->new_syms, 1) = symp;
1388 write_reloc(kpatch_ss, &kpatch->repladdr, symp, 0);
1391 void write_ksplice_export(struct superbfd *sbfd, const char *symname,
1392 const char *export_type, bool del)
1394 struct supersect *export_ss = make_section(sbfd, ".ksplice_exports");
1395 struct ksplice_export *exp = sect_grow(export_ss, 1,
1396 struct ksplice_export);
1398 if (del) {
1399 write_string(export_ss, &exp->name, "%s", symname);
1400 write_string(export_ss, &exp->new_name, "DISABLED_%s_%s",
1401 symname, kid);
1402 } else {
1403 write_string(export_ss, &exp->new_name, "%s", symname);
1404 write_string(export_ss, &exp->name, "DISABLED_%s_%s", symname,
1405 kid);
1409 struct fixup_entry {
1410 bfd_vma offset;
1411 bool used;
1413 DECLARE_VEC_TYPE(struct fixup_entry, fixup_entry_vec);
1415 int compare_fixups(const void *aptr, const void *bptr)
1417 const struct fixup_entry *a = aptr, *b = bptr;
1418 if (a->offset < b->offset)
1419 return -1;
1420 else if (a->offset > b->offset)
1421 return 1;
1422 else
1423 return (int)a->used - (int)b->used;
1426 void filter_table_sections(struct superbfd *isbfd)
1428 struct supersect *tables_ss =
1429 fetch_supersect(offsets_sbfd,
1430 bfd_get_section_by_name(offsets_sbfd->abfd,
1431 ".ksplice_table_sections"));
1432 const struct table_section *ts;
1433 for (ts = tables_ss->contents.data;
1434 (void *)ts < tables_ss->contents.data + tables_ss->contents.size;
1435 ts++) {
1436 struct table_section s = *ts;
1437 s.sect = read_string(tables_ss, &ts->sect);
1438 s.other_sect = read_string(tables_ss, &ts->other_sect);
1439 filter_table_section(isbfd, &s);
1443 void filter_table_section(struct superbfd *sbfd, const struct table_section *s)
1445 asection *isection = bfd_get_section_by_name(sbfd->abfd, s->sect);
1446 if (isection == NULL)
1447 return;
1448 asection *fixup_sect = NULL;
1449 if (s->other_sect != NULL)
1450 fixup_sect = bfd_get_section_by_name(sbfd->abfd, s->other_sect);
1452 struct supersect *ss = fetch_supersect(sbfd, isection);
1453 if (ss->alignment < ffs(s->entry_align) - 1)
1454 ss->alignment = ffs(s->entry_align) - 1;
1456 struct supersect *fixup_ss = NULL;
1457 if (fixup_sect != NULL)
1458 fixup_ss = fetch_supersect(sbfd, fixup_sect);
1460 struct fixup_entry_vec fixups;
1461 vec_init(&fixups);
1463 void *entry;
1464 for (entry = ss->contents.data;
1465 entry < ss->contents.data + ss->contents.size;
1466 entry += s->entry_size) {
1467 asymbol *sym, *fixup_sym;
1468 read_reloc(ss, entry + s->addr_offset, sizeof(void *), &sym);
1470 struct span *span = new_span(ss, addr_offset(ss, entry),
1471 s->entry_size);
1472 struct supersect *sym_ss = fetch_supersect(sbfd, sym->section);
1473 span->keep = sym_ss->keep;
1475 struct fixup_entry *f;
1476 if (fixup_sect != NULL) {
1477 bfd_vma fixup_offset =
1478 read_reloc(ss, entry + s->other_offset,
1479 sizeof(void *), &fixup_sym);
1480 if (fixup_sym->section == fixup_sect) {
1481 assert(fixup_offset < fixup_ss->contents.size);
1482 f = vec_grow(&fixups, 1);
1483 f->offset = fixup_offset;
1484 f->used = span->keep;
1489 if (fixup_sect == NULL)
1490 return;
1492 qsort(fixups.data, fixups.size, sizeof(*fixups.data), compare_fixups);
1493 *vec_grow(&fixups, 1) = (struct fixup_entry)
1494 { .offset = fixup_ss->contents.size, .used = false };
1496 struct fixup_entry *f;
1497 for (f = fixups.data; f < fixups.data + fixups.size - 1; f++) {
1498 struct span *span = new_span(fixup_ss, f->offset,
1499 (f + 1)->offset - f->offset);
1500 span->keep = f->used;
1504 void keep_referenced_sections(struct superbfd *sbfd)
1506 asection *sect;
1507 struct supersect *ss, *sym_ss;
1508 struct span *address_span, *target_span;
1509 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
1510 ss = fetch_supersect(sbfd, sect);
1511 arelent **relocp;
1512 if (ss->type == SS_TYPE_SPECIAL || ss->type == SS_TYPE_EXPORT)
1513 continue;
1514 for (relocp = ss->relocs.data;
1515 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
1516 asymbol *sym = *(*relocp)->sym_ptr_ptr;
1517 address_span = reloc_address_span(ss, *relocp);
1518 if (!address_span->keep)
1519 continue;
1520 target_span = reloc_target_span(ss, *relocp);
1521 if (target_span == NULL || target_span->keep)
1522 continue;
1523 sym_ss = fetch_supersect(sbfd, sym->section);
1524 if (sym_ss->type == SS_TYPE_IGNORED)
1525 continue;
1526 target_span->keep = true;
1527 sym_ss->keep = true;
1528 changed = true;
1533 void copy_symbols(struct asymbolp_vec *osyms, struct asymbolpp_vec *isyms)
1535 asymbol ***sympp;
1536 for (sympp = isyms->data; sympp < isyms->data + isyms->size; sympp++)
1537 *vec_grow(osyms, 1) = **sympp;
1540 /* Modified function from GNU Binutils objcopy.c */
1541 bfd_boolean copy_object(bfd *ibfd, bfd *obfd)
1543 assert(bfd_set_format(obfd, bfd_get_format(ibfd)));
1545 bfd_vma start = bfd_get_start_address(ibfd);
1547 flagword flags = bfd_get_file_flags(ibfd);
1548 flags &= bfd_applicable_file_flags(obfd);
1550 assert(bfd_set_start_address(obfd, start)
1551 && bfd_set_file_flags(obfd, flags));
1553 enum bfd_architecture iarch = bfd_get_arch(ibfd);
1554 unsigned int imach = bfd_get_mach(ibfd);
1555 assert(bfd_set_arch_mach(obfd, iarch, imach));
1556 assert(bfd_set_format(obfd, bfd_get_format(ibfd)));
1558 /* BFD mandates that all output sections be created and sizes set before
1559 any output is done. Thus, we traverse all sections multiple times. */
1560 bfd_map_over_sections(ibfd, setup_section, obfd);
1562 struct supersect *new_supersects = fetch_superbfd(ibfd)->new_supersects;
1563 struct supersect *ss;
1564 for (ss = new_supersects; ss != NULL; ss = ss->next)
1565 setup_new_section(obfd, ss);
1567 /* Mark symbols used in output relocations so that they
1568 are kept, even if they are local labels or static symbols.
1570 Note we iterate over the input sections examining their
1571 relocations since the relocations for the output sections
1572 haven't been set yet. mark_symbols_used_in_relocations will
1573 ignore input sections which have no corresponding output
1574 section. */
1576 bfd_map_over_sections(ibfd, mark_symbols_used_in_relocations, NULL);
1577 for (ss = new_supersects; ss != NULL; ss = ss->next)
1578 ss_mark_symbols_used_in_relocations(ss);
1579 struct asymbolp_vec osyms;
1580 vec_init(&osyms);
1581 filter_symbols(ibfd, obfd, &osyms, &fetch_superbfd(ibfd)->syms);
1582 copy_symbols(&osyms, &fetch_superbfd(ibfd)->new_syms);
1584 bfd_set_symtab(obfd, osyms.data, osyms.size);
1586 /* This has to happen after the symbol table has been set. */
1587 bfd_map_over_sections(obfd, write_section, NULL);
1589 /* Allow the BFD backend to copy any private data it understands
1590 from the input BFD to the output BFD. This is done last to
1591 permit the routine to look at the filtered symbol table, which is
1592 important for the ECOFF code at least. */
1593 assert(bfd_copy_private_bfd_data(ibfd, obfd));
1595 return TRUE;
1598 /* Modified function from GNU Binutils objcopy.c */
1599 void setup_section(bfd *ibfd, asection *isection, void *obfdarg)
1601 struct superbfd *isbfd = fetch_superbfd(ibfd);
1602 struct supersect *ss = fetch_supersect(isbfd, isection);
1603 bfd *obfd = obfdarg;
1604 bfd_vma vma;
1606 if (!ss->keep)
1607 return;
1609 asection *osection = bfd_make_section_anyway(obfd, isection->name);
1610 assert(osection != NULL);
1612 osection->userdata = ss;
1613 bfd_set_section_flags(obfd, osection, ss->flags);
1614 ss->symbol = osection->symbol;
1615 assert(bfd_set_section_size(obfd, osection, ss->contents.size));
1617 vma = bfd_section_vma(ibfd, isection);
1618 assert(bfd_set_section_vma(obfd, osection, vma));
1620 osection->lma = isection->lma;
1621 assert(bfd_set_section_alignment(obfd, osection, ss->alignment));
1622 osection->entsize = isection->entsize;
1623 osection->output_section = osection;
1624 osection->output_offset = 0;
1625 isection->output_section = osection;
1626 isection->output_offset = 0;
1627 return;
1630 void setup_new_section(bfd *obfd, struct supersect *ss)
1632 asection *osection = bfd_make_section_anyway(obfd, ss->name);
1633 assert(osection != NULL);
1634 bfd_set_section_flags(obfd, osection, ss->flags);
1636 osection->userdata = ss;
1637 ss->symbol = osection->symbol;
1638 assert(bfd_set_section_size(obfd, osection, ss->contents.size));
1639 assert(bfd_set_section_vma(obfd, osection, 0));
1641 osection->lma = 0;
1642 assert(bfd_set_section_alignment(obfd, osection, ss->alignment));
1643 osection->entsize = 0;
1644 osection->output_section = osection;
1645 osection->output_offset = 0;
1648 static int compare_reloc_addresses(const void *aptr, const void *bptr)
1650 const arelent *const *a = aptr, *const *b = bptr;
1651 return (*a)->address - (*b)->address;
1654 static void delete_obsolete_relocs(struct supersect *ss)
1656 if (ss->new_relocs.size == 0)
1657 return;
1659 qsort(ss->relocs.data, ss->relocs.size, sizeof(*ss->relocs.data),
1660 compare_reloc_addresses);
1661 qsort(ss->new_relocs.data, ss->new_relocs.size,
1662 sizeof(*ss->new_relocs.data), compare_reloc_addresses);
1664 struct arelentp_vec orig_relocs;
1665 vec_move(&orig_relocs, &ss->relocs);
1667 arelent **relocp, **new_relocp = ss->new_relocs.data;
1668 for (relocp = orig_relocs.data;
1669 relocp < orig_relocs.data + orig_relocs.size; relocp++) {
1670 while (new_relocp < ss->new_relocs.data + ss->new_relocs.size &&
1671 (*new_relocp)->address < (*relocp)->address)
1672 new_relocp++;
1673 arelent *reloc = *relocp, *new_reloc = *new_relocp;
1674 if (new_relocp == ss->new_relocs.data + ss->new_relocs.size ||
1675 reloc->address != new_reloc->address)
1676 *vec_grow(&ss->relocs, 1) = reloc;
1680 void write_section(bfd *obfd, asection *osection, void *arg)
1682 struct supersect *ss = osection->userdata;
1684 if ((ss->flags & SEC_GROUP) != 0 || ss->contents.size == 0)
1685 return;
1687 delete_obsolete_relocs(ss);
1689 arelent **relocp;
1690 char *error_message;
1691 for (relocp = ss->new_relocs.data;
1692 relocp < ss->new_relocs.data + ss->new_relocs.size; relocp++) {
1693 bfd_vma val;
1694 if (bfd_get_arch(obfd) == bfd_arch_arm)
1695 val = osection->use_rela_p ? 0 : (*relocp)->addend;
1696 else
1697 val = 0;
1698 bfd_put(bfd_get_reloc_size((*relocp)->howto) * 8, obfd, val,
1699 ss->contents.data + (*relocp)->address);
1700 if (bfd_install_relocation(obfd, *relocp, ss->contents.data,
1701 0, osection, &error_message) !=
1702 bfd_reloc_ok) {
1703 err(ss->parent, "ksplice: error installing reloc: %s",
1704 error_message);
1705 DIE;
1708 memcpy(vec_grow(&ss->relocs, ss->new_relocs.size), ss->new_relocs.data,
1709 ss->new_relocs.size * sizeof(*ss->new_relocs.data));
1711 bfd_set_reloc(obfd, osection,
1712 ss->relocs.size == 0 ? NULL : ss->relocs.data,
1713 ss->relocs.size);
1715 if (ss->flags & SEC_HAS_CONTENTS)
1716 assert(bfd_set_section_contents
1717 (obfd, osection, ss->contents.data, 0,
1718 ss->contents.size));
1721 /* Modified function from GNU Binutils objcopy.c
1723 * Mark all the symbols which will be used in output relocations with
1724 * the BSF_KEEP flag so that those symbols will not be stripped.
1726 * Ignore relocations which will not appear in the output file.
1728 void mark_symbols_used_in_relocations(bfd *abfd, asection *isection,
1729 void *ignored)
1731 struct superbfd *sbfd = fetch_superbfd(abfd);
1732 if (isection->output_section == NULL)
1733 return;
1735 struct supersect *ss = fetch_supersect(sbfd, isection);
1736 ss_mark_symbols_used_in_relocations(ss);
1739 void ss_mark_symbols_used_in_relocations(struct supersect *ss)
1741 /* Examine each symbol used in a relocation. If it's not one of the
1742 special bfd section symbols, then mark it with BSF_KEEP. */
1743 arelent **relocp;
1744 for (relocp = ss->relocs.data;
1745 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
1746 asymbol *sym = *(*relocp)->sym_ptr_ptr;
1747 if (!(bfd_is_const_section(sym->section) &&
1748 sym == sym->section->symbol))
1749 sym->flags |= BSF_KEEP;
1751 for (relocp = ss->new_relocs.data;
1752 relocp < ss->new_relocs.data + ss->new_relocs.size; relocp++) {
1753 asymbol *sym = *(*relocp)->sym_ptr_ptr;
1754 if (!(bfd_is_const_section(sym->section) &&
1755 sym == sym->section->symbol))
1756 sym->flags |= BSF_KEEP;
1760 static bool deleted_table_section_symbol(bfd *abfd, asymbol *sym)
1762 struct superbfd *sbfd = fetch_superbfd(abfd);
1763 if (bfd_is_const_section(sym->section))
1764 return false;
1765 struct supersect *ss = fetch_supersect(sbfd, sym->section);
1767 asymbol **symp;
1768 for (symp = ss->syms.data; symp < ss->syms.data + ss->syms.size; symp++) {
1769 if (sym == *symp)
1770 break;
1772 return symp >= ss->syms.data + ss->syms.size;
1775 /* Modified function from GNU Binutils objcopy.c
1777 * Choose which symbol entries to copy.
1778 * We don't copy in place, because that confuses the relocs.
1779 * Return the number of symbols to print.
1781 void filter_symbols(bfd *ibfd, bfd *obfd, struct asymbolp_vec *osyms,
1782 struct asymbolp_vec *isyms)
1784 asymbol **symp;
1785 struct superbfd *sbfd = fetch_superbfd(ibfd);
1786 for (symp = isyms->data; symp < isyms->data + isyms->size; symp++) {
1787 asymbol *sym = *symp;
1788 struct supersect *sym_ss = NULL;
1789 if (!bfd_is_const_section(sym->section))
1790 sym_ss = fetch_supersect(sbfd, sym->section);
1792 bool keep = false;
1794 if (mode("keep") && (sym->flags & BSF_GLOBAL) != 0 &&
1795 !(mode("keep-primary") && sym_ss != NULL && sym_ss->new))
1796 sym->flags = (sym->flags & ~BSF_GLOBAL) | BSF_LOCAL;
1798 if (mode("finalize") && (sym->flags & BSF_GLOBAL) != 0)
1799 sym->flags = (sym->flags & ~BSF_GLOBAL) | BSF_LOCAL;
1801 if ((sym->flags & BSF_KEEP) != 0 /* Used in relocation. */
1802 || ((sym->flags & BSF_SECTION_SYM) != 0 && sym_ss != NULL &&
1803 sym_ss->keep))
1804 keep = true;
1805 else if ((sym->flags & (BSF_GLOBAL | BSF_WEAK)) != 0 &&
1806 sym_ss != NULL && sym_ss->keep)
1807 keep = true;
1809 if (deleted_table_section_symbol(ibfd, sym))
1810 keep = false;
1812 if (bfd_is_com_section(sym->section))
1813 keep = false;
1815 if (mode("rmsyms"))
1816 keep = !str_in_set(sym->name, &rmsyms);
1818 if (keep) {
1819 if (sym_ss != NULL && !sym_ss->keep) {
1820 err(sbfd, "Kept symbol %s in unkept section "
1821 "%s\n", sym->name, sym->section->name);
1822 DIE;
1824 *vec_grow(osyms, 1) = sym;
1829 void read_str_set(struct str_vec *strs)
1831 char *buf = NULL;
1832 size_t n = 0;
1833 assert(getline(&buf, &n, stdin) >= 0);
1834 vec_init(strs);
1835 char *saveptr;
1836 while (1) {
1837 char *str = strtok_r(buf, " \n", &saveptr);
1838 buf = NULL;
1839 if (str == NULL)
1840 break;
1841 *vec_grow(strs, 1) = str;
1845 bool str_in_set(const char *str, const struct str_vec *strs)
1847 const char **strp;
1848 for (strp = strs->data; strp < strs->data + strs->size; strp++) {
1849 if (strcmp(str, *strp) == 0)
1850 return true;
1852 return false;
1855 bool is_table_section(const char *name, bool consider_other)
1857 struct supersect *tables_ss =
1858 fetch_supersect(offsets_sbfd,
1859 bfd_get_section_by_name(offsets_sbfd->abfd,
1860 ".ksplice_table_sections"));
1861 const struct table_section *ts;
1862 for (ts = tables_ss->contents.data;
1863 (void *)ts < tables_ss->contents.data + tables_ss->contents.size;
1864 ts++) {
1865 if (strcmp(name, read_string(tables_ss, &ts->sect)) == 0)
1866 return true;
1867 const char *osect_name = read_string(tables_ss,
1868 &ts->other_sect);
1869 if (consider_other && osect_name != NULL &&
1870 strcmp(name, osect_name) == 0)
1871 return true;
1873 return false;
1876 enum supersect_type supersect_type(struct supersect *ss)
1878 if (starts_with(ss->name, ".ksplice"))
1879 return SS_TYPE_KSPLICE;
1881 if (starts_with(ss->name, ".init"))
1882 return SS_TYPE_IGNORED;
1883 if (starts_with(ss->name, ".security_initcall.init"))
1884 return SS_TYPE_IGNORED;
1885 if (starts_with(ss->name, ".con_initcall.init"))
1886 return SS_TYPE_IGNORED;
1887 if (starts_with(ss->name, ".x86cpuvendor.init"))
1888 return SS_TYPE_IGNORED;
1889 if (starts_with(ss->name, ".early_param.init"))
1890 return SS_TYPE_IGNORED;
1891 if (starts_with(ss->name, ".taglist.init"))
1892 return SS_TYPE_IGNORED;
1893 if (starts_with(ss->name, ".arch.info.init"))
1894 return SS_TYPE_IGNORED;
1895 if (starts_with(ss->name, ".proc.info.init"))
1896 return SS_TYPE_IGNORED;
1897 /* .pci_fixup_* sections really should be treated as global rodata
1898 referenced only from quirks.c */
1899 if (starts_with(ss->name, ".pci_fixup_"))
1900 return SS_TYPE_IGNORED;
1901 /* .builtin_fw sections are similar to .pci_fixup */
1902 if (starts_with(ss->name, ".builtin_fw"))
1903 return SS_TYPE_IGNORED;
1904 /* same for .tracedata */
1905 if (starts_with(ss->name, ".tracedata"))
1906 return SS_TYPE_IGNORED;
1907 if (starts_with(ss->name, ".debug"))
1908 return SS_TYPE_IGNORED;
1909 /* .eh_frame should probably be discarded, not ignored */
1910 if (starts_with(ss->name, ".eh_frame"))
1911 return SS_TYPE_IGNORED;
1912 if (config->ignore_devinit && starts_with(ss->name, ".devinit"))
1913 return SS_TYPE_IGNORED;
1914 if (config->ignore_meminit && starts_with(ss->name, ".meminit"))
1915 return SS_TYPE_IGNORED;
1916 if (config->ignore_cpuinit && starts_with(ss->name, ".cpuinit"))
1917 return SS_TYPE_IGNORED;
1918 if (config->ignore_devinit && starts_with(ss->name, ".devexit"))
1919 return SS_TYPE_IGNORED;
1920 if (config->ignore_meminit && starts_with(ss->name, ".memexit"))
1921 return SS_TYPE_IGNORED;
1922 if (config->ignore_cpuinit && starts_with(ss->name, ".cpuexit"))
1923 return SS_TYPE_IGNORED;
1924 if (starts_with(ss->name, ".vgetcpu_mode") ||
1925 starts_with(ss->name, ".jiffies") ||
1926 starts_with(ss->name, ".wall_jiffies") ||
1927 starts_with(ss->name, ".vxtime") ||
1928 starts_with(ss->name, ".sys_tz") ||
1929 starts_with(ss->name, ".sysctl_vsyscall") ||
1930 starts_with(ss->name, ".xtime") ||
1931 starts_with(ss->name, ".xtime_lock") ||
1932 starts_with(ss->name, ".vsyscall"))
1933 return SS_TYPE_IGNORED;
1934 if (starts_with(ss->name, ".vdso"))
1935 return SS_TYPE_IGNORED;
1937 if (bfd_get_section_by_name(ss->parent->abfd, ".exitcall.exit") == NULL) {
1938 if (starts_with(ss->name, ".exit.text"))
1939 return SS_TYPE_TEXT;
1940 if (starts_with(ss->name, ".exit.data"))
1941 return SS_TYPE_DATA;
1942 } else if (starts_with(ss->name, ".exit.text") ||
1943 starts_with(ss->name, ".exit.data"))
1944 return SS_TYPE_IGNORED;
1946 if (starts_with(ss->name, ".text") ||
1947 starts_with(ss->name, ".kernel.text") ||
1948 starts_with(ss->name, ".devinit.text") ||
1949 starts_with(ss->name, ".meminit.text") ||
1950 starts_with(ss->name, ".cpuinit.text") ||
1951 starts_with(ss->name, ".devexit.text") ||
1952 starts_with(ss->name, ".memexit.text") ||
1953 starts_with(ss->name, ".cpuexit.text") ||
1954 starts_with(ss->name, ".ref.text") ||
1955 starts_with(ss->name, ".spinlock.text") ||
1956 starts_with(ss->name, ".kprobes.text") ||
1957 starts_with(ss->name, ".sched.text"))
1958 return SS_TYPE_TEXT;
1960 int n = -1;
1961 if (sscanf(ss->name, ".rodata.str%*u.%*u%n", &n) >= 0 &&
1962 n == strlen(ss->name))
1963 return SS_TYPE_STRING;
1965 if (starts_with(ss->name, ".rodata") ||
1966 starts_with(ss->name, ".kernel.rodata") ||
1967 starts_with(ss->name, ".devinit.rodata") ||
1968 starts_with(ss->name, ".meminit.rodata") ||
1969 starts_with(ss->name, ".cpuinit.rodata") ||
1970 starts_with(ss->name, ".devexit.rodata") ||
1971 starts_with(ss->name, ".memexit.rodata") ||
1972 starts_with(ss->name, ".cpuexit.rodata") ||
1973 starts_with(ss->name, ".ref.rodata") ||
1974 starts_with(ss->name, "__markers_strings"))
1975 return SS_TYPE_RODATA;
1977 if (starts_with(ss->name, ".bss"))
1978 return SS_TYPE_DATA;
1980 /* Ignore .data.percpu sections */
1981 if (starts_with(ss->name, ".data.percpu") ||
1982 starts_with(ss->name, ".kernel.data.percpu"))
1983 return SS_TYPE_IGNORED;
1984 if (starts_with(ss->name, ".data") ||
1985 starts_with(ss->name, ".kernel.data") ||
1986 starts_with(ss->name, ".devinit.data") ||
1987 starts_with(ss->name, ".cpuinit.data") ||
1988 starts_with(ss->name, ".meminit.data") ||
1989 starts_with(ss->name, ".devexit.data") ||
1990 starts_with(ss->name, ".memexit.data") ||
1991 starts_with(ss->name, ".cpuexit.data") ||
1992 starts_with(ss->name, ".ref.data") ||
1993 starts_with(ss->name, "__markers"))
1994 return SS_TYPE_DATA;
1996 /* We replace all the ksymtab strings, so delete them */
1997 if (strcmp(ss->name, "__ksymtab_strings") == 0)
1998 return SS_TYPE_IGNORED;
1999 if (starts_with(ss->name, "__ksymtab"))
2000 return SS_TYPE_EXPORT;
2001 if (starts_with(ss->name, "__kcrctab"))
2002 return SS_TYPE_EXPORT;
2004 if (is_table_section(ss->name, true))
2005 return SS_TYPE_SPECIAL;
2007 if (starts_with(ss->name, ".ARM."))
2008 return SS_TYPE_SPECIAL;
2010 if (starts_with(ss->name, ".note"))
2011 return SS_TYPE_IGNORED;
2012 if (starts_with(ss->name, ".comment"))
2013 return SS_TYPE_IGNORED;
2014 if (starts_with(ss->name, "__param"))
2015 return SS_TYPE_IGNORED;
2016 if (starts_with(ss->name, ".exitcall.exit"))
2017 return SS_TYPE_IGNORED;
2018 if (starts_with(ss->name, ".modinfo"))
2019 return SS_TYPE_IGNORED;
2021 return SS_TYPE_UNKNOWN;
2024 void initialize_supersect_types(struct superbfd *sbfd)
2026 asection *sect;
2027 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2028 struct supersect *ss = fetch_supersect(sbfd, sect);
2029 ss->type = supersect_type(ss);
2030 if (ss->type == SS_TYPE_UNKNOWN) {
2031 err(sbfd, "Unknown section type: %s\n", ss->name);
2032 DIE;
2037 static void init_label_map(struct superbfd *sbfd)
2039 struct label_map *map;
2041 vec_init(&sbfd->maps);
2042 init_csyms(sbfd);
2043 init_callers(sbfd);
2045 struct symbol_hash csyms;
2046 symbol_hash_init(&csyms);
2048 asymbol **symp;
2049 for (symp = sbfd->syms.data;
2050 symp < sbfd->syms.data + sbfd->syms.size; symp++) {
2051 asymbol *csym = canonical_symbol(sbfd, *symp);
2052 if (csym == NULL)
2053 continue;
2054 char *key;
2055 assert(asprintf(&key, "%p", csym) >= 0);
2056 asymbol **csymp = symbol_hash_lookup(&csyms, key, TRUE);
2057 free(key);
2058 if (*csymp != NULL)
2059 continue;
2060 *csymp = csym;
2062 map = vec_grow(&sbfd->maps, 1);
2063 map->csym = csym;
2064 map->count = 0;
2065 map->label = symbol_label(sbfd, csym);
2068 struct label_mapp_hash label_maps;
2069 label_mapp_hash_init(&label_maps);
2070 for (map = sbfd->maps.data;
2071 map < sbfd->maps.data + sbfd->maps.size; map++) {
2072 struct label_map **mapp =
2073 label_mapp_hash_lookup(&label_maps, map->label, TRUE);
2074 if (*mapp == NULL) {
2075 *mapp = map;
2076 continue;
2079 struct label_map *first_map = *mapp;
2080 char *buf;
2081 if (first_map->count == 0) {
2082 assert(asprintf(&buf, "%s~%d", map->label, 0) >= 0);
2083 first_map->label = buf;
2085 first_map->count++;
2086 assert(asprintf(&buf, "%s~%d", map->label, first_map->count)
2087 >= 0);
2088 map->label = buf;
2091 label_mapp_hash_init(&sbfd->maps_hash);
2092 for (map = sbfd->maps.data;
2093 map < sbfd->maps.data + sbfd->maps.size; map++) {
2094 char *key;
2095 assert(asprintf(&key, "%p", map->csym) >= 0);
2096 struct label_map **mapp =
2097 label_mapp_hash_lookup(&sbfd->maps_hash, key, TRUE);
2098 free(key);
2099 *mapp = map;
2100 map->orig_label = map->label;
2104 static const char *label_lookup(struct superbfd *sbfd, asymbol *sym)
2106 asymbol *csym = canonical_symbol(sbfd, sym);
2107 char *key;
2108 assert(asprintf(&key, "%p", csym) >= 0);
2109 struct label_map **mapp =
2110 label_mapp_hash_lookup(&sbfd->maps_hash, key, FALSE);
2111 free(key);
2112 if (mapp == NULL)
2113 DIE;
2114 return (*mapp)->label;
2117 static void print_label_map(struct superbfd *sbfd)
2119 struct label_map *map;
2120 for (map = sbfd->maps.data;
2121 map < sbfd->maps.data + sbfd->maps.size; map++) {
2122 if (strcmp(map->orig_label, map->label) == 0)
2123 continue;
2124 debug1(sbfd, "Label change: %s -> %s\n",
2125 map->label, map->orig_label);
2129 static void label_map_set(struct superbfd *sbfd, const char *oldlabel,
2130 const char *label)
2132 struct label_map *map;
2133 for (map = sbfd->maps.data;
2134 map < sbfd->maps.data + sbfd->maps.size; map++) {
2135 if (strcmp(map->orig_label, oldlabel) == 0) {
2136 if (strcmp(map->orig_label, map->label) != 0 &&
2137 strcmp(map->label, label) != 0)
2138 DIE;
2139 map->label = label;
2140 return;
2143 DIE;
2146 static void init_callers(struct superbfd *sbfd)
2148 string_hash_init(&sbfd->callers);
2149 asection *sect;
2150 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2151 struct supersect *ss = fetch_supersect(sbfd, sect);
2152 arelent **relocp;
2153 for (relocp = ss->relocs.data;
2154 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
2155 asymbol *sym = *(*relocp)->sym_ptr_ptr;
2156 unsigned long val =
2157 sym->value + get_reloc_offset(ss, *relocp, true);
2158 char *key;
2159 assert(asprintf(&key, "%s+%lx", sym->section->name,
2160 val) >= 0);
2161 const char **ret = string_hash_lookup(&sbfd->callers,
2162 key, TRUE);
2163 free(key);
2164 if (*ret == NULL)
2165 *ret = sect->name;
2166 else
2167 *ret = "*multiple_callers*";
2172 static const char *find_caller(struct supersect *ss, asymbol *sym)
2174 char *key;
2175 assert(asprintf(&key, "%s+%lx", sym->section->name,
2176 (unsigned long)sym->value) >= 0);
2177 const char **ret = string_hash_lookup(&ss->parent->callers, key, FALSE);
2178 free(key);
2180 if (ret == NULL)
2181 return "*no_caller*";
2182 return *ret;
2185 static void init_csyms(struct superbfd *sbfd)
2187 asymbolpp_hash_init(&sbfd->csyms);
2189 asymbol **symp;
2190 for (symp = sbfd->syms.data; symp < sbfd->syms.data + sbfd->syms.size;
2191 symp++) {
2192 asymbol *sym = *symp;
2193 if ((sym->flags & BSF_DEBUGGING) != 0)
2194 continue;
2195 char *key;
2196 assert(asprintf(&key, "%s+%lx", sym->section->name,
2197 (unsigned long)sym->value) >= 0);
2198 asymbol ***csympp = asymbolpp_hash_lookup(&sbfd->csyms, key,
2199 TRUE);
2200 free(key);
2201 if (*csympp == NULL) {
2202 *csympp = symp;
2203 continue;
2205 asymbol *csym = **csympp;
2206 if ((csym->flags & BSF_GLOBAL) != 0)
2207 continue;
2208 if ((sym->flags & BSF_GLOBAL) != 0)
2209 *csympp = symp;
2213 static asymbol **symbolp_scan(struct supersect *ss, bfd_vma value)
2215 char *key;
2216 assert(asprintf(&key, "%s+%lx", ss->name, (unsigned long)value) >= 0);
2217 asymbol ***csympp =
2218 asymbolpp_hash_lookup(&ss->parent->csyms, key, FALSE);
2219 free(key);
2220 if (csympp != NULL)
2221 return *csympp;
2223 /* For section symbols of sections containing no symbols, return the
2224 section symbol that relocations are generated against */
2225 if (value == 0)
2226 return &ss->symbol;
2227 return NULL;
2230 static asymbol **canonical_symbolp(struct superbfd *sbfd, asymbol *sym)
2232 if (bfd_is_const_section(sym->section)) {
2233 asymbol **csymp;
2234 for (csymp = sbfd->syms.data;
2235 csymp < sbfd->syms.data + sbfd->syms.size; csymp++) {
2236 if (sym == *csymp)
2237 return csymp;
2239 return NULL;
2241 return symbolp_scan(fetch_supersect(sbfd, sym->section), sym->value);
2244 static asymbol *canonical_symbol(struct superbfd *sbfd, asymbol *sym)
2246 if (bfd_is_const_section(sym->section))
2247 return sym;
2248 asymbol **symp = canonical_symbolp(sbfd, sym);
2249 return symp != NULL ? *symp : NULL;
2252 static char *static_local_symbol(struct superbfd *sbfd, asymbol *sym)
2254 struct supersect *ss = fetch_supersect(sbfd, sym->section);
2255 if ((sym->flags & BSF_LOCAL) == 0 || (sym->flags & BSF_OBJECT) == 0)
2256 return NULL;
2257 char *dot = strrchr(sym->name, '.');
2258 if (dot == NULL || dot[1 + strspn(dot + 1, "0123546789")] != '\0')
2259 return NULL;
2260 char *basename = strndup(sym->name, dot - sym->name);
2261 char *mangled_name;
2262 if (strcmp(basename, "__func__") == 0 ||
2263 strcmp(basename, "__PRETTY_FUNCTION__") == 0)
2264 assert(asprintf(&mangled_name, "%s<%s>", basename,
2265 (char *)ss->contents.data + sym->value) >= 0);
2266 else
2267 assert(asprintf(&mangled_name, "%s<%s>", basename,
2268 find_caller(ss, sym)) >= 0);
2269 return mangled_name;
2272 static char *symbol_label(struct superbfd *sbfd, asymbol *sym)
2274 const char *filename = sbfd->abfd->filename;
2275 char *c = strstr(filename, ".KSPLICE");
2276 int flen = (c == NULL ? strlen(filename) : c - filename);
2278 char *label;
2279 if (bfd_is_und_section(sym->section) || (sym->flags & BSF_GLOBAL) != 0) {
2280 label = strdup(sym->name);
2281 } else if (bfd_is_const_section(sym->section)) {
2282 assert(asprintf(&label, "%s<%.*s>",
2283 sym->name, flen, filename) >= 0);
2284 } else {
2285 asymbol *gsym = canonical_symbol(sbfd, sym);
2287 if (gsym == NULL)
2288 assert(asprintf(&label, "%s+%lx<%.*s>",
2289 sym->section->name,
2290 (unsigned long)sym->value,
2291 flen, filename) >= 0);
2292 else if ((gsym->flags & BSF_GLOBAL) != 0)
2293 label = strdup(gsym->name);
2294 else if (static_local_symbol(sbfd, gsym))
2295 assert(asprintf(&label, "%s+%lx<%.*s>",
2296 static_local_symbol(sbfd, gsym),
2297 (unsigned long)sym->value,
2298 flen, filename) >= 0);
2299 else
2300 assert(asprintf(&label, "%s<%.*s>",
2301 gsym->name, flen, filename) >= 0);
2304 return label;
2307 static struct span *new_span(struct supersect *ss, bfd_vma start, bfd_vma size)
2309 struct span *span = vec_grow(&ss->spans, 1);
2310 span->size = size;
2311 span->start = start;
2312 span->ss = ss;
2313 span->keep = false;
2314 span->new = false;
2315 span->shift = 0;
2316 asymbol **symp = symbolp_scan(ss, span->start);
2317 if (symp != NULL) {
2318 span->symbol = *symp;
2319 span->label = label_lookup(ss->parent, span->symbol);
2320 } else {
2321 span->symbol = NULL;
2322 const char *label = label_lookup(ss->parent, ss->symbol);
2323 if (span->start != 0) {
2324 char *buf;
2325 assert(asprintf(&buf, "%s<span:%lx>", label,
2326 (unsigned long)span->start) >= 0);
2327 span->label = buf;
2328 } else {
2329 span->label = label;
2332 return span;
2335 static void initialize_string_spans(struct supersect *ss)
2337 const char *str;
2338 for (str = ss->contents.data;
2339 (void *)str < ss->contents.data + ss->contents.size;) {
2340 bfd_vma start = (unsigned long)str -
2341 (unsigned long)ss->contents.data;
2342 bfd_vma size = strlen(str) + 1;
2343 while ((start + size) % (1 << ss->alignment) != 0 &&
2344 start + size < ss->contents.size) {
2345 if (str[size] != '\0')
2346 DIE;
2347 size++;
2349 new_span(ss, start, size);
2350 str += size;
2354 static void initialize_spans(struct superbfd *sbfd)
2356 asection *sect;
2357 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2358 struct supersect *ss = fetch_supersect(sbfd, sect);
2359 if (ss->type == SS_TYPE_STRING)
2360 initialize_string_spans(ss);
2361 else if (!mode("keep") || (ss->type != SS_TYPE_SPECIAL &&
2362 ss->type != SS_TYPE_EXPORT))
2363 new_span(ss, 0, ss->contents.size);
2367 struct span *reloc_target_span(struct supersect *ss, arelent *reloc)
2369 asymbol *sym_ptr = *reloc->sym_ptr_ptr;
2370 if (bfd_is_const_section(sym_ptr->section))
2371 return NULL;
2373 bfd_vma addend = get_reloc_offset(ss, reloc, true) + sym_ptr->value;
2374 struct supersect *sym_ss =
2375 fetch_supersect(ss->parent, sym_ptr->section);
2376 struct span *span, *target_span = sym_ss->spans.data;
2377 for (span = sym_ss->spans.data;
2378 span < sym_ss->spans.data + sym_ss->spans.size; span++) {
2379 if (addend >= span->start && addend < span->start + span->size)
2380 target_span = span;
2382 return target_span;
2385 struct span *reloc_address_span(struct supersect *ss, arelent *reloc)
2387 struct span *span;
2388 for (span = ss->spans.data; span < ss->spans.data + ss->spans.size;
2389 span++) {
2390 if (reloc->address >= span->start &&
2391 reloc->address < span->start + span->size)
2392 return span;
2394 return NULL;
2397 void compute_span_shifts(struct superbfd *sbfd)
2399 asection *sect;
2400 struct span *span;
2401 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2402 struct supersect *ss = fetch_supersect(sbfd, sect);
2403 if (!ss->keep)
2404 continue;
2405 bfd_size_type offset = 0;
2406 for (span = ss->spans.data;
2407 span < ss->spans.data + ss->spans.size; span++) {
2408 if (!span->keep)
2409 continue;
2410 span->shift = offset - span->start;
2411 offset += span->size;
2416 void remove_unkept_spans(struct superbfd *sbfd)
2418 asection *sect;
2419 struct span *span;
2420 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2421 struct supersect *ss = fetch_supersect(sbfd, sect);
2422 struct arelentp_vec orig_relocs;
2423 vec_move(&orig_relocs, &ss->relocs);
2424 arelent **relocp, *reloc;
2425 for (relocp = orig_relocs.data;
2426 relocp < orig_relocs.data + orig_relocs.size; relocp++) {
2427 reloc = *relocp;
2428 asymbol *sym = *reloc->sym_ptr_ptr;
2429 span = reloc_target_span(ss, reloc);
2430 if ((span != NULL && span->keep && span->shift == 0) ||
2431 bfd_is_const_section(sym->section)) {
2432 *vec_grow(&ss->relocs, 1) = reloc;
2433 continue;
2435 if (span != NULL && span->keep) {
2436 arelent *new_reloc = malloc(sizeof(*new_reloc));
2437 *new_reloc = *reloc;
2438 new_reloc->addend =
2439 get_reloc_offset(ss, reloc, false);
2440 new_reloc->addend += span->shift;
2441 *vec_grow(&ss->new_relocs, 1) = new_reloc;
2446 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2447 struct supersect *ss = fetch_supersect(sbfd, sect), orig_ss;
2448 if (!ss->keep)
2449 continue;
2450 supersect_move(&orig_ss, ss);
2451 vec_init(&ss->spans);
2452 for (span = orig_ss.spans.data;
2453 span < orig_ss.spans.data + orig_ss.spans.size; span++) {
2454 if (!span->keep)
2455 continue;
2456 struct span *new_span = vec_grow(&ss->spans, 1);
2457 *new_span = *span;
2458 new_span->start = span->start + span->shift;
2459 new_span->shift = 0;
2460 sect_copy(ss, sect_do_grow(ss, 1, span->size, 1),
2461 &orig_ss, orig_ss.contents.data + span->start,
2462 span->size);