Avoid scanning through all relocations in write_reloc.
[ksplice.git] / objmanip.c
blob28985d5f6e6e5bfe83ac8b7bf2e023cc694b586a
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 (rm_reloc)
1071 write_ksplice_reloc(ss, *relocp);
1072 else
1073 *vec_grow(&ss->relocs, 1) = *relocp;
1077 struct supersect *make_section(struct superbfd *sbfd, const char *name)
1079 asection *sect = bfd_get_section_by_name(sbfd->abfd, name);
1080 if (sect != NULL)
1081 return fetch_supersect(sbfd, sect);
1082 else
1083 return new_supersect(sbfd, name);
1086 arelent *create_reloc(struct supersect *ss, const void *addr, asymbol **symp,
1087 bfd_vma offset)
1089 bfd_reloc_code_real_type code;
1090 switch (bfd_arch_bits_per_address(ss->parent->abfd)) {
1091 case 32:
1092 code = BFD_RELOC_32;
1093 break;
1094 case 64:
1095 code = BFD_RELOC_64;
1096 break;
1097 default:
1098 DIE;
1101 arelent *reloc = malloc(sizeof(*reloc));
1102 reloc->sym_ptr_ptr = symp;
1103 reloc->address = addr_offset(ss, addr);
1104 reloc->howto = bfd_reloc_type_lookup(ss->parent->abfd, code);
1105 reloc->addend = offset;
1106 return reloc;
1109 void write_reloc(struct supersect *ss, const void *addr, asymbol **symp,
1110 bfd_vma offset)
1112 *vec_grow(&ss->new_relocs, 1) = create_reloc(ss, addr, symp, offset);
1115 void write_string(struct supersect *ss, const char **addr, const char *fmt, ...)
1117 va_list ap;
1118 struct supersect *str_ss = make_section(ss->parent, ".ksplice_str");
1119 char *str;
1120 va_start(ap, fmt);
1121 int len = vasprintf(&str, fmt, ap);
1122 assert(len >= 0);
1123 va_end(ap);
1125 unsigned long *str_offp = ulong_hash_lookup(&ksplice_string_offset, str,
1126 FALSE);
1127 if (str_offp == NULL) {
1128 char *buf = sect_grow(str_ss, len + 1, char);
1129 memcpy(buf, str, len + 1);
1130 str_offp = ulong_hash_lookup(&ksplice_string_offset, str, TRUE);
1131 *str_offp = addr_offset(str_ss, buf);
1134 write_reloc(ss, addr, &str_ss->symbol, *str_offp);
1137 void lookup_system_map(struct addr_vec *addrs, const char *name, long offset)
1139 struct addr_vec *map_addrs =
1140 addr_vec_hash_lookup(&system_map, name, FALSE);
1141 if (map_addrs == NULL)
1142 return;
1144 unsigned long *addr, *map_addr;
1145 for (map_addr = map_addrs->data;
1146 map_addr < map_addrs->data + map_addrs->size; map_addr++) {
1147 for (addr = addrs->data; addr < addrs->data + addrs->size;
1148 addr++) {
1149 if (*addr == *map_addr + offset)
1150 break;
1152 if (addr < addrs->data + addrs->size)
1153 continue;
1154 *vec_grow(addrs, 1) = *map_addr + offset;
1158 void write_system_map_array(struct superbfd *sbfd, struct supersect *ss,
1159 const unsigned long **sym_addrs,
1160 unsigned long *num_sym_addrs, asymbol *sym)
1162 struct addr_vec addrs;
1163 vec_init(&addrs);
1165 if (bfd_is_abs_section(sym->section)) {
1166 *vec_grow(&addrs, 1) = sym->value;
1167 } else if (bfd_is_und_section(sym->section)) {
1168 lookup_system_map(&addrs, sym->name, 0);
1169 } else if (!bfd_is_const_section(sym->section)) {
1170 asymbol **gsymp;
1171 for (gsymp = sbfd->syms.data;
1172 gsymp < sbfd->syms.data + sbfd->syms.size; gsymp++) {
1173 asymbol *gsym = *gsymp;
1174 if ((gsym->flags & BSF_DEBUGGING) == 0 &&
1175 gsym->section == sym->section)
1176 lookup_system_map(&addrs, gsym->name,
1177 sym->value - gsym->value);
1181 *num_sym_addrs = addrs.size;
1182 if (addrs.size != 0) {
1183 struct supersect *array_ss = make_section(sbfd,
1184 ".ksplice_array");
1185 void *buf = sect_grow(array_ss, addrs.size,
1186 typeof(*addrs.data));
1187 memcpy(buf, addrs.data, addrs.size * sizeof(*addrs.data));
1188 write_reloc(ss, sym_addrs, &array_ss->symbol,
1189 addr_offset(array_ss, buf));
1190 } else {
1191 *sym_addrs = NULL;
1194 vec_free(&addrs);
1197 void write_ksplice_system_map(struct superbfd *sbfd, asymbol *sym,
1198 const char *addstr_sect)
1200 struct supersect *smap_ss = make_section(sbfd, ".ksplice_system_map");
1201 struct ksplice_system_map *smap;
1202 const char *label = label_lookup(sbfd, sym);
1204 bool *done = bool_hash_lookup(&system_map_written, label, TRUE);
1205 if (*done)
1206 return;
1207 *done = true;
1209 smap = sect_grow(smap_ss, 1, struct ksplice_system_map);
1211 write_system_map_array(sbfd, smap_ss, &smap->candidates,
1212 &smap->nr_candidates, sym);
1213 write_string(smap_ss, &smap->label, "%s%s", label, addstr_sect);
1216 void write_ksplice_symbol(struct supersect *ss,
1217 const struct ksplice_symbol *const *addr,
1218 asymbol *sym, struct span *span,
1219 const char *addstr_sect)
1221 struct supersect *ksymbol_ss = make_section(ss->parent,
1222 ".ksplice_symbols");
1223 struct ksplice_symbol *ksymbol;
1224 unsigned long *ksymbol_offp;
1225 const char *label;
1226 char *output;
1227 if (span != NULL && span->start != 0)
1228 label = span->label;
1229 else
1230 label = label_lookup(ss->parent, sym);
1231 assert(asprintf(&output, "%s%s", label, addstr_sect) >= 0);
1233 ksymbol_offp = ulong_hash_lookup(&ksplice_symbol_offset, output, FALSE);
1234 if (ksymbol_offp != NULL) {
1235 write_reloc(ss, addr, &ksymbol_ss->symbol, *ksymbol_offp);
1236 return;
1238 ksymbol = sect_grow(ksymbol_ss, 1, struct ksplice_symbol);
1239 ksymbol_offp = ulong_hash_lookup(&ksplice_symbol_offset, output, TRUE);
1240 *ksymbol_offp = addr_offset(ksymbol_ss, ksymbol);
1242 write_reloc(ss, addr, &ksymbol_ss->symbol, *ksymbol_offp);
1243 write_string(ksymbol_ss, &ksymbol->label, "%s", output);
1245 if (span != NULL && span->symbol == NULL) {
1246 ksymbol->name = NULL;
1247 return;
1250 write_ksplice_system_map(ksymbol_ss->parent, sym, addstr_sect);
1252 if (bfd_is_und_section(sym->section) || (sym->flags & BSF_GLOBAL) != 0) {
1253 write_string(ksymbol_ss, &ksymbol->name, "%s", sym->name);
1254 } else if (bfd_is_const_section(sym->section)) {
1255 ksymbol->name = NULL;
1256 } else {
1257 asymbol *gsym = canonical_symbol(ss->parent, sym);
1259 if (gsym == NULL || (gsym->flags & BSF_SECTION_SYM) != 0)
1260 ksymbol->name = NULL;
1261 else
1262 write_string(ksymbol_ss, &ksymbol->name, "%s",
1263 gsym->name);
1267 void write_ksplice_reloc(struct supersect *ss, arelent *orig_reloc)
1269 asymbol *sym_ptr = *orig_reloc->sym_ptr_ptr;
1270 reloc_howto_type *howto = orig_reloc->howto;
1271 bfd_vma addend = get_reloc_offset(ss, orig_reloc, false);
1273 if (mode("finalize") && starts_with(ss->name, ".ksplice_patches")) {
1274 unsigned long *repladdr =
1275 ss->contents.data + orig_reloc->address;
1276 *repladdr = 0;
1277 return;
1280 struct span *span = reloc_target_span(ss, orig_reloc);
1281 if (span == ss->spans.data && span->start != addend)
1282 span = NULL;
1283 blot_section(ss, orig_reloc->address, howto);
1285 struct supersect *kreloc_ss = make_section(ss->parent,
1286 mode("rmsyms") ?
1287 ".ksplice_init_relocs" :
1288 ".ksplice_relocs");
1289 struct ksplice_reloc *kreloc = sect_grow(kreloc_ss, 1,
1290 struct ksplice_reloc);
1292 struct span *address_span = reloc_address_span(ss, orig_reloc);
1293 write_reloc(kreloc_ss, &kreloc->blank_addr,
1294 &ss->symbol, orig_reloc->address + address_span->shift);
1295 write_ksplice_symbol(kreloc_ss, &kreloc->symbol, sym_ptr, span, "");
1296 kreloc->pcrel = howto->pc_relative;
1297 if (span != NULL && span->start != 0)
1298 addend += sym_ptr->value - span->start;
1299 kreloc->addend = addend;
1300 kreloc->size = bfd_get_reloc_size(howto);
1301 kreloc->dst_mask = howto->dst_mask;
1302 kreloc->rightshift = howto->rightshift;
1303 kreloc->signed_addend =
1304 (howto->complain_on_overflow == complain_overflow_signed) ||
1305 (howto->complain_on_overflow == complain_overflow_bitfield);
1308 #define CANARY(x, canary) ((x & ~howto->dst_mask) | (canary & howto->dst_mask))
1310 void blot_section(struct supersect *ss, int offset, reloc_howto_type *howto)
1312 int bits = bfd_get_reloc_size(howto) * 8;
1313 void *address = ss->contents.data + offset;
1314 bfd_vma x = bfd_get(bits, ss->parent->abfd, address);
1315 x = (x & ~howto->dst_mask) |
1316 ((bfd_vma)KSPLICE_CANARY & howto->dst_mask);
1317 bfd_put(bits, ss->parent->abfd, x, address);
1320 static void write_ksplice_section(struct span *span)
1322 struct supersect *ss = span->ss;
1323 struct supersect *ksect_ss =
1324 make_section(ss->parent, ".ksplice_sections");
1325 struct ksplice_section *ksect = sect_grow(ksect_ss, 1,
1326 struct ksplice_section);
1327 asymbol *sym = span->symbol == NULL ? ss->symbol : span->symbol;
1329 write_ksplice_symbol(ksect_ss, &ksect->symbol, sym, span,
1330 mode("keep-primary") ? "(post)" : "");
1331 ksect->size = span->size;
1332 ksect->flags = 0;
1334 if (ss->type == SS_TYPE_RODATA || ss->type == SS_TYPE_STRING)
1335 ksect->flags |= KSPLICE_SECTION_RODATA;
1336 if (ss->type == SS_TYPE_DATA)
1337 ksect->flags |= KSPLICE_SECTION_DATA;
1338 if (ss->type == SS_TYPE_TEXT)
1339 ksect->flags |= KSPLICE_SECTION_TEXT;
1340 assert(ksect->flags != 0);
1341 write_reloc(ksect_ss, &ksect->address, &ss->symbol,
1342 span->start + span->shift);
1345 void write_ksplice_patch(struct superbfd *sbfd, const char *sectname)
1347 struct supersect *kpatch_ss = make_section(sbfd, ".ksplice_patches");
1348 struct ksplice_patch *kpatch = sect_grow(kpatch_ss, 1,
1349 struct ksplice_patch);
1350 asection *sect = bfd_get_section_by_name(sbfd->abfd, sectname);
1351 assert(sect != NULL);
1353 write_string(kpatch_ss, &kpatch->label, "%s",
1354 label_lookup(sbfd, sect->symbol));
1355 write_reloc(kpatch_ss, &kpatch->repladdr, &sect->symbol, 0);
1358 void write_ksplice_deleted_patch(struct superbfd *sbfd, const char *name,
1359 const char *label)
1361 struct supersect *kpatch_ss = make_section(sbfd, ".ksplice_patches");
1362 struct ksplice_patch *kpatch = sect_grow(kpatch_ss, 1,
1363 struct ksplice_patch);
1365 write_string(kpatch_ss, &kpatch->label, "%s", label);
1366 asymbol **symp;
1367 for (symp = sbfd->syms.data; symp < sbfd->syms.data + sbfd->syms.size;
1368 symp++) {
1369 asymbol *sym = *symp;
1370 if (bfd_is_und_section(sym->section) &&
1371 strcmp(name, sym->name) == 0)
1372 break;
1374 if (symp >= sbfd->syms.data + sbfd->syms.size) {
1375 symp = malloc(sizeof(*symp));
1376 *symp = bfd_make_empty_symbol(sbfd->abfd);
1377 asymbol *sym = *symp;
1378 sym->name = strdup(name);
1379 sym->section = bfd_und_section_ptr;
1380 sym->flags = 0;
1381 sym->value = 0;
1382 *vec_grow(&sbfd->new_syms, 1) = symp;
1384 write_reloc(kpatch_ss, &kpatch->repladdr, symp, 0);
1387 void write_ksplice_export(struct superbfd *sbfd, const char *symname,
1388 const char *export_type, bool del)
1390 struct supersect *export_ss = make_section(sbfd, ".ksplice_exports");
1391 struct ksplice_export *exp = sect_grow(export_ss, 1,
1392 struct ksplice_export);
1394 if (del) {
1395 write_string(export_ss, &exp->name, "%s", symname);
1396 write_string(export_ss, &exp->new_name, "DISABLED_%s_%s",
1397 symname, kid);
1398 } else {
1399 write_string(export_ss, &exp->new_name, "%s", symname);
1400 write_string(export_ss, &exp->name, "DISABLED_%s_%s", symname,
1401 kid);
1405 struct fixup_entry {
1406 bfd_vma offset;
1407 bool used;
1409 DECLARE_VEC_TYPE(struct fixup_entry, fixup_entry_vec);
1411 int compare_fixups(const void *aptr, const void *bptr)
1413 const struct fixup_entry *a = aptr, *b = bptr;
1414 if (a->offset < b->offset)
1415 return -1;
1416 else if (a->offset > b->offset)
1417 return 1;
1418 else
1419 return (int)a->used - (int)b->used;
1422 void filter_table_sections(struct superbfd *isbfd)
1424 struct supersect *tables_ss =
1425 fetch_supersect(offsets_sbfd,
1426 bfd_get_section_by_name(offsets_sbfd->abfd,
1427 ".ksplice_table_sections"));
1428 const struct table_section *ts;
1429 for (ts = tables_ss->contents.data;
1430 (void *)ts < tables_ss->contents.data + tables_ss->contents.size;
1431 ts++) {
1432 struct table_section s = *ts;
1433 s.sect = read_string(tables_ss, &ts->sect);
1434 s.other_sect = read_string(tables_ss, &ts->other_sect);
1435 filter_table_section(isbfd, &s);
1439 void filter_table_section(struct superbfd *sbfd, const struct table_section *s)
1441 asection *isection = bfd_get_section_by_name(sbfd->abfd, s->sect);
1442 if (isection == NULL)
1443 return;
1444 asection *fixup_sect = NULL;
1445 if (s->other_sect != NULL)
1446 fixup_sect = bfd_get_section_by_name(sbfd->abfd, s->other_sect);
1448 struct supersect *ss = fetch_supersect(sbfd, isection);
1449 if (ss->alignment < ffs(s->entry_align) - 1)
1450 ss->alignment = ffs(s->entry_align) - 1;
1452 struct supersect *fixup_ss = NULL;
1453 if (fixup_sect != NULL)
1454 fixup_ss = fetch_supersect(sbfd, fixup_sect);
1456 struct fixup_entry_vec fixups;
1457 vec_init(&fixups);
1459 void *entry;
1460 for (entry = ss->contents.data;
1461 entry < ss->contents.data + ss->contents.size;
1462 entry += s->entry_size) {
1463 asymbol *sym, *fixup_sym;
1464 read_reloc(ss, entry + s->addr_offset, sizeof(void *), &sym);
1466 struct span *span = new_span(ss, addr_offset(ss, entry),
1467 s->entry_size);
1468 struct supersect *sym_ss = fetch_supersect(sbfd, sym->section);
1469 span->keep = sym_ss->keep;
1471 struct fixup_entry *f;
1472 if (fixup_sect != NULL) {
1473 bfd_vma fixup_offset =
1474 read_reloc(ss, entry + s->other_offset,
1475 sizeof(void *), &fixup_sym);
1476 if (fixup_sym->section == fixup_sect) {
1477 assert(fixup_offset < fixup_ss->contents.size);
1478 f = vec_grow(&fixups, 1);
1479 f->offset = fixup_offset;
1480 f->used = span->keep;
1485 if (fixup_sect == NULL)
1486 return;
1488 qsort(fixups.data, fixups.size, sizeof(*fixups.data), compare_fixups);
1489 *vec_grow(&fixups, 1) = (struct fixup_entry)
1490 { .offset = fixup_ss->contents.size, .used = false };
1492 struct fixup_entry *f;
1493 for (f = fixups.data; f < fixups.data + fixups.size - 1; f++) {
1494 struct span *span = new_span(fixup_ss, f->offset,
1495 (f + 1)->offset - f->offset);
1496 span->keep = f->used;
1500 void keep_referenced_sections(struct superbfd *sbfd)
1502 asection *sect;
1503 struct supersect *ss, *sym_ss;
1504 struct span *address_span, *target_span;
1505 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
1506 ss = fetch_supersect(sbfd, sect);
1507 arelent **relocp;
1508 if (ss->type == SS_TYPE_SPECIAL || ss->type == SS_TYPE_EXPORT)
1509 continue;
1510 for (relocp = ss->relocs.data;
1511 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
1512 asymbol *sym = *(*relocp)->sym_ptr_ptr;
1513 address_span = reloc_address_span(ss, *relocp);
1514 if (!address_span->keep)
1515 continue;
1516 target_span = reloc_target_span(ss, *relocp);
1517 if (target_span == NULL || target_span->keep)
1518 continue;
1519 sym_ss = fetch_supersect(sbfd, sym->section);
1520 if (sym_ss->type == SS_TYPE_IGNORED)
1521 continue;
1522 target_span->keep = true;
1523 sym_ss->keep = true;
1524 changed = true;
1529 void copy_symbols(struct asymbolp_vec *osyms, struct asymbolpp_vec *isyms)
1531 asymbol ***sympp;
1532 for (sympp = isyms->data; sympp < isyms->data + isyms->size; sympp++)
1533 *vec_grow(osyms, 1) = **sympp;
1536 /* Modified function from GNU Binutils objcopy.c */
1537 bfd_boolean copy_object(bfd *ibfd, bfd *obfd)
1539 assert(bfd_set_format(obfd, bfd_get_format(ibfd)));
1541 bfd_vma start = bfd_get_start_address(ibfd);
1543 flagword flags = bfd_get_file_flags(ibfd);
1544 flags &= bfd_applicable_file_flags(obfd);
1546 assert(bfd_set_start_address(obfd, start)
1547 && bfd_set_file_flags(obfd, flags));
1549 enum bfd_architecture iarch = bfd_get_arch(ibfd);
1550 unsigned int imach = bfd_get_mach(ibfd);
1551 assert(bfd_set_arch_mach(obfd, iarch, imach));
1552 assert(bfd_set_format(obfd, bfd_get_format(ibfd)));
1554 /* BFD mandates that all output sections be created and sizes set before
1555 any output is done. Thus, we traverse all sections multiple times. */
1556 bfd_map_over_sections(ibfd, setup_section, obfd);
1558 struct supersect *new_supersects = fetch_superbfd(ibfd)->new_supersects;
1559 struct supersect *ss;
1560 for (ss = new_supersects; ss != NULL; ss = ss->next)
1561 setup_new_section(obfd, ss);
1563 /* Mark symbols used in output relocations so that they
1564 are kept, even if they are local labels or static symbols.
1566 Note we iterate over the input sections examining their
1567 relocations since the relocations for the output sections
1568 haven't been set yet. mark_symbols_used_in_relocations will
1569 ignore input sections which have no corresponding output
1570 section. */
1572 bfd_map_over_sections(ibfd, mark_symbols_used_in_relocations, NULL);
1573 for (ss = new_supersects; ss != NULL; ss = ss->next)
1574 ss_mark_symbols_used_in_relocations(ss);
1575 struct asymbolp_vec osyms;
1576 vec_init(&osyms);
1577 filter_symbols(ibfd, obfd, &osyms, &fetch_superbfd(ibfd)->syms);
1578 copy_symbols(&osyms, &fetch_superbfd(ibfd)->new_syms);
1580 bfd_set_symtab(obfd, osyms.data, osyms.size);
1582 /* This has to happen after the symbol table has been set. */
1583 bfd_map_over_sections(obfd, write_section, NULL);
1585 /* Allow the BFD backend to copy any private data it understands
1586 from the input BFD to the output BFD. This is done last to
1587 permit the routine to look at the filtered symbol table, which is
1588 important for the ECOFF code at least. */
1589 assert(bfd_copy_private_bfd_data(ibfd, obfd));
1591 return TRUE;
1594 /* Modified function from GNU Binutils objcopy.c */
1595 void setup_section(bfd *ibfd, asection *isection, void *obfdarg)
1597 struct superbfd *isbfd = fetch_superbfd(ibfd);
1598 struct supersect *ss = fetch_supersect(isbfd, isection);
1599 bfd *obfd = obfdarg;
1600 bfd_vma vma;
1602 if (!ss->keep)
1603 return;
1605 asection *osection = bfd_make_section_anyway(obfd, isection->name);
1606 assert(osection != NULL);
1608 osection->userdata = ss;
1609 bfd_set_section_flags(obfd, osection, ss->flags);
1610 ss->symbol = osection->symbol;
1611 assert(bfd_set_section_size(obfd, osection, ss->contents.size));
1613 vma = bfd_section_vma(ibfd, isection);
1614 assert(bfd_set_section_vma(obfd, osection, vma));
1616 osection->lma = isection->lma;
1617 assert(bfd_set_section_alignment(obfd, osection, ss->alignment));
1618 osection->entsize = isection->entsize;
1619 osection->output_section = osection;
1620 osection->output_offset = 0;
1621 isection->output_section = osection;
1622 isection->output_offset = 0;
1623 return;
1626 void setup_new_section(bfd *obfd, struct supersect *ss)
1628 asection *osection = bfd_make_section_anyway(obfd, ss->name);
1629 assert(osection != NULL);
1630 bfd_set_section_flags(obfd, osection, ss->flags);
1632 osection->userdata = ss;
1633 ss->symbol = osection->symbol;
1634 assert(bfd_set_section_size(obfd, osection, ss->contents.size));
1635 assert(bfd_set_section_vma(obfd, osection, 0));
1637 osection->lma = 0;
1638 assert(bfd_set_section_alignment(obfd, osection, ss->alignment));
1639 osection->entsize = 0;
1640 osection->output_section = osection;
1641 osection->output_offset = 0;
1644 static int compare_reloc_addresses(const void *aptr, const void *bptr)
1646 const arelent *const *a = aptr, *const *b = bptr;
1647 return (*a)->address - (*b)->address;
1650 static void delete_obsolete_relocs(struct supersect *ss)
1652 if (ss->new_relocs.size == 0)
1653 return;
1655 qsort(ss->relocs.data, ss->relocs.size, sizeof(*ss->relocs.data),
1656 compare_reloc_addresses);
1657 qsort(ss->new_relocs.data, ss->new_relocs.size,
1658 sizeof(*ss->new_relocs.data), compare_reloc_addresses);
1660 struct arelentp_vec orig_relocs;
1661 vec_move(&orig_relocs, &ss->relocs);
1663 arelent **relocp, **new_relocp = ss->new_relocs.data;
1664 for (relocp = orig_relocs.data;
1665 relocp < orig_relocs.data + orig_relocs.size; relocp++) {
1666 while (new_relocp < ss->new_relocs.data + ss->new_relocs.size &&
1667 (*new_relocp)->address < (*relocp)->address)
1668 new_relocp++;
1669 arelent *reloc = *relocp, *new_reloc = *new_relocp;
1670 if (new_relocp == ss->new_relocs.data + ss->new_relocs.size ||
1671 reloc->address != new_reloc->address)
1672 *vec_grow(&ss->relocs, 1) = reloc;
1676 void write_section(bfd *obfd, asection *osection, void *arg)
1678 struct supersect *ss = osection->userdata;
1680 if ((ss->flags & SEC_GROUP) != 0 || ss->contents.size == 0)
1681 return;
1683 delete_obsolete_relocs(ss);
1685 arelent **relocp;
1686 char *error_message;
1687 for (relocp = ss->new_relocs.data;
1688 relocp < ss->new_relocs.data + ss->new_relocs.size; relocp++) {
1689 bfd_vma val;
1690 if (bfd_get_arch(obfd) == bfd_arch_arm)
1691 val = osection->use_rela_p ? 0 : (*relocp)->addend;
1692 else
1693 val = 0;
1694 bfd_put(bfd_get_reloc_size((*relocp)->howto) * 8, obfd, val,
1695 ss->contents.data + (*relocp)->address);
1696 if (bfd_install_relocation(obfd, *relocp, ss->contents.data,
1697 0, osection, &error_message) !=
1698 bfd_reloc_ok) {
1699 err(ss->parent, "ksplice: error installing reloc: %s",
1700 error_message);
1701 DIE;
1704 memcpy(vec_grow(&ss->relocs, ss->new_relocs.size), ss->new_relocs.data,
1705 ss->new_relocs.size * sizeof(*ss->new_relocs.data));
1707 bfd_set_reloc(obfd, osection,
1708 ss->relocs.size == 0 ? NULL : ss->relocs.data,
1709 ss->relocs.size);
1711 if (ss->flags & SEC_HAS_CONTENTS)
1712 assert(bfd_set_section_contents
1713 (obfd, osection, ss->contents.data, 0,
1714 ss->contents.size));
1717 /* Modified function from GNU Binutils objcopy.c
1719 * Mark all the symbols which will be used in output relocations with
1720 * the BSF_KEEP flag so that those symbols will not be stripped.
1722 * Ignore relocations which will not appear in the output file.
1724 void mark_symbols_used_in_relocations(bfd *abfd, asection *isection,
1725 void *ignored)
1727 struct superbfd *sbfd = fetch_superbfd(abfd);
1728 if (isection->output_section == NULL)
1729 return;
1731 struct supersect *ss = fetch_supersect(sbfd, isection);
1732 ss_mark_symbols_used_in_relocations(ss);
1735 void ss_mark_symbols_used_in_relocations(struct supersect *ss)
1737 /* Examine each symbol used in a relocation. If it's not one of the
1738 special bfd section symbols, then mark it with BSF_KEEP. */
1739 arelent **relocp;
1740 for (relocp = ss->relocs.data;
1741 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
1742 asymbol *sym = *(*relocp)->sym_ptr_ptr;
1743 if (!(bfd_is_const_section(sym->section) &&
1744 sym == sym->section->symbol))
1745 sym->flags |= BSF_KEEP;
1747 for (relocp = ss->new_relocs.data;
1748 relocp < ss->new_relocs.data + ss->new_relocs.size; relocp++) {
1749 asymbol *sym = *(*relocp)->sym_ptr_ptr;
1750 if (!(bfd_is_const_section(sym->section) &&
1751 sym == sym->section->symbol))
1752 sym->flags |= BSF_KEEP;
1756 static bool deleted_table_section_symbol(bfd *abfd, asymbol *sym)
1758 struct superbfd *sbfd = fetch_superbfd(abfd);
1759 if (bfd_is_const_section(sym->section))
1760 return false;
1761 struct supersect *ss = fetch_supersect(sbfd, sym->section);
1763 asymbol **symp;
1764 for (symp = ss->syms.data; symp < ss->syms.data + ss->syms.size; symp++) {
1765 if (sym == *symp)
1766 break;
1768 return symp >= ss->syms.data + ss->syms.size;
1771 /* Modified function from GNU Binutils objcopy.c
1773 * Choose which symbol entries to copy.
1774 * We don't copy in place, because that confuses the relocs.
1775 * Return the number of symbols to print.
1777 void filter_symbols(bfd *ibfd, bfd *obfd, struct asymbolp_vec *osyms,
1778 struct asymbolp_vec *isyms)
1780 asymbol **symp;
1781 struct superbfd *sbfd = fetch_superbfd(ibfd);
1782 for (symp = isyms->data; symp < isyms->data + isyms->size; symp++) {
1783 asymbol *sym = *symp;
1784 struct supersect *sym_ss = NULL;
1785 if (!bfd_is_const_section(sym->section))
1786 sym_ss = fetch_supersect(sbfd, sym->section);
1788 bool keep = false;
1790 if (mode("keep") && (sym->flags & BSF_GLOBAL) != 0 &&
1791 !(mode("keep-primary") && sym_ss != NULL && sym_ss->new))
1792 sym->flags = (sym->flags & ~BSF_GLOBAL) | BSF_LOCAL;
1794 if (mode("finalize") && (sym->flags & BSF_GLOBAL) != 0)
1795 sym->flags = (sym->flags & ~BSF_GLOBAL) | BSF_LOCAL;
1797 if ((sym->flags & BSF_KEEP) != 0 /* Used in relocation. */
1798 || ((sym->flags & BSF_SECTION_SYM) != 0 && sym_ss != NULL &&
1799 sym_ss->keep))
1800 keep = true;
1801 else if ((sym->flags & (BSF_GLOBAL | BSF_WEAK)) != 0 &&
1802 sym_ss != NULL && sym_ss->keep)
1803 keep = true;
1805 if (deleted_table_section_symbol(ibfd, sym))
1806 keep = false;
1808 if (bfd_is_com_section(sym->section))
1809 keep = false;
1811 if (mode("rmsyms"))
1812 keep = !str_in_set(sym->name, &rmsyms);
1814 if (keep) {
1815 if (sym_ss != NULL && !sym_ss->keep) {
1816 err(sbfd, "Kept symbol %s in unkept section "
1817 "%s\n", sym->name, sym->section->name);
1818 DIE;
1820 *vec_grow(osyms, 1) = sym;
1825 void read_str_set(struct str_vec *strs)
1827 char *buf = NULL;
1828 size_t n = 0;
1829 assert(getline(&buf, &n, stdin) >= 0);
1830 vec_init(strs);
1831 char *saveptr;
1832 while (1) {
1833 char *str = strtok_r(buf, " \n", &saveptr);
1834 buf = NULL;
1835 if (str == NULL)
1836 break;
1837 *vec_grow(strs, 1) = str;
1841 bool str_in_set(const char *str, const struct str_vec *strs)
1843 const char **strp;
1844 for (strp = strs->data; strp < strs->data + strs->size; strp++) {
1845 if (strcmp(str, *strp) == 0)
1846 return true;
1848 return false;
1851 bool is_table_section(const char *name, bool consider_other)
1853 struct supersect *tables_ss =
1854 fetch_supersect(offsets_sbfd,
1855 bfd_get_section_by_name(offsets_sbfd->abfd,
1856 ".ksplice_table_sections"));
1857 const struct table_section *ts;
1858 for (ts = tables_ss->contents.data;
1859 (void *)ts < tables_ss->contents.data + tables_ss->contents.size;
1860 ts++) {
1861 if (strcmp(name, read_string(tables_ss, &ts->sect)) == 0)
1862 return true;
1863 const char *osect_name = read_string(tables_ss,
1864 &ts->other_sect);
1865 if (consider_other && osect_name != NULL &&
1866 strcmp(name, osect_name) == 0)
1867 return true;
1869 return false;
1872 enum supersect_type supersect_type(struct supersect *ss)
1874 if (starts_with(ss->name, ".ksplice"))
1875 return SS_TYPE_KSPLICE;
1877 if (starts_with(ss->name, ".init"))
1878 return SS_TYPE_IGNORED;
1879 if (starts_with(ss->name, ".security_initcall.init"))
1880 return SS_TYPE_IGNORED;
1881 if (starts_with(ss->name, ".con_initcall.init"))
1882 return SS_TYPE_IGNORED;
1883 if (starts_with(ss->name, ".x86cpuvendor.init"))
1884 return SS_TYPE_IGNORED;
1885 if (starts_with(ss->name, ".early_param.init"))
1886 return SS_TYPE_IGNORED;
1887 if (starts_with(ss->name, ".taglist.init"))
1888 return SS_TYPE_IGNORED;
1889 if (starts_with(ss->name, ".arch.info.init"))
1890 return SS_TYPE_IGNORED;
1891 if (starts_with(ss->name, ".proc.info.init"))
1892 return SS_TYPE_IGNORED;
1893 /* .pci_fixup_* sections really should be treated as global rodata
1894 referenced only from quirks.c */
1895 if (starts_with(ss->name, ".pci_fixup_"))
1896 return SS_TYPE_IGNORED;
1897 /* .builtin_fw sections are similar to .pci_fixup */
1898 if (starts_with(ss->name, ".builtin_fw"))
1899 return SS_TYPE_IGNORED;
1900 /* same for .tracedata */
1901 if (starts_with(ss->name, ".tracedata"))
1902 return SS_TYPE_IGNORED;
1903 if (starts_with(ss->name, ".debug"))
1904 return SS_TYPE_IGNORED;
1905 /* .eh_frame should probably be discarded, not ignored */
1906 if (starts_with(ss->name, ".eh_frame"))
1907 return SS_TYPE_IGNORED;
1908 if (config->ignore_devinit && starts_with(ss->name, ".devinit"))
1909 return SS_TYPE_IGNORED;
1910 if (config->ignore_meminit && starts_with(ss->name, ".meminit"))
1911 return SS_TYPE_IGNORED;
1912 if (config->ignore_cpuinit && starts_with(ss->name, ".cpuinit"))
1913 return SS_TYPE_IGNORED;
1914 if (config->ignore_devinit && starts_with(ss->name, ".devexit"))
1915 return SS_TYPE_IGNORED;
1916 if (config->ignore_meminit && starts_with(ss->name, ".memexit"))
1917 return SS_TYPE_IGNORED;
1918 if (config->ignore_cpuinit && starts_with(ss->name, ".cpuexit"))
1919 return SS_TYPE_IGNORED;
1920 if (starts_with(ss->name, ".vgetcpu_mode") ||
1921 starts_with(ss->name, ".jiffies") ||
1922 starts_with(ss->name, ".wall_jiffies") ||
1923 starts_with(ss->name, ".vxtime") ||
1924 starts_with(ss->name, ".sys_tz") ||
1925 starts_with(ss->name, ".sysctl_vsyscall") ||
1926 starts_with(ss->name, ".xtime") ||
1927 starts_with(ss->name, ".xtime_lock") ||
1928 starts_with(ss->name, ".vsyscall"))
1929 return SS_TYPE_IGNORED;
1930 if (starts_with(ss->name, ".vdso"))
1931 return SS_TYPE_IGNORED;
1933 if (bfd_get_section_by_name(ss->parent->abfd, ".exitcall.exit") == NULL) {
1934 if (starts_with(ss->name, ".exit.text"))
1935 return SS_TYPE_TEXT;
1936 if (starts_with(ss->name, ".exit.data"))
1937 return SS_TYPE_DATA;
1938 } else if (starts_with(ss->name, ".exit.text") ||
1939 starts_with(ss->name, ".exit.data"))
1940 return SS_TYPE_IGNORED;
1942 if (starts_with(ss->name, ".text") ||
1943 starts_with(ss->name, ".kernel.text") ||
1944 starts_with(ss->name, ".devinit.text") ||
1945 starts_with(ss->name, ".meminit.text") ||
1946 starts_with(ss->name, ".cpuinit.text") ||
1947 starts_with(ss->name, ".devexit.text") ||
1948 starts_with(ss->name, ".memexit.text") ||
1949 starts_with(ss->name, ".cpuexit.text") ||
1950 starts_with(ss->name, ".ref.text") ||
1951 starts_with(ss->name, ".spinlock.text") ||
1952 starts_with(ss->name, ".kprobes.text") ||
1953 starts_with(ss->name, ".sched.text"))
1954 return SS_TYPE_TEXT;
1956 int n = -1;
1957 if (sscanf(ss->name, ".rodata.str%*u.%*u%n", &n) >= 0 &&
1958 n == strlen(ss->name))
1959 return SS_TYPE_STRING;
1961 if (starts_with(ss->name, ".rodata") ||
1962 starts_with(ss->name, ".kernel.rodata") ||
1963 starts_with(ss->name, ".devinit.rodata") ||
1964 starts_with(ss->name, ".meminit.rodata") ||
1965 starts_with(ss->name, ".cpuinit.rodata") ||
1966 starts_with(ss->name, ".devexit.rodata") ||
1967 starts_with(ss->name, ".memexit.rodata") ||
1968 starts_with(ss->name, ".cpuexit.rodata") ||
1969 starts_with(ss->name, ".ref.rodata") ||
1970 starts_with(ss->name, "__markers_strings"))
1971 return SS_TYPE_RODATA;
1973 if (starts_with(ss->name, ".bss"))
1974 return SS_TYPE_DATA;
1976 /* Ignore .data.percpu sections */
1977 if (starts_with(ss->name, ".data.percpu") ||
1978 starts_with(ss->name, ".kernel.data.percpu"))
1979 return SS_TYPE_IGNORED;
1980 if (starts_with(ss->name, ".data") ||
1981 starts_with(ss->name, ".kernel.data") ||
1982 starts_with(ss->name, ".devinit.data") ||
1983 starts_with(ss->name, ".cpuinit.data") ||
1984 starts_with(ss->name, ".meminit.data") ||
1985 starts_with(ss->name, ".devexit.data") ||
1986 starts_with(ss->name, ".memexit.data") ||
1987 starts_with(ss->name, ".cpuexit.data") ||
1988 starts_with(ss->name, ".ref.data") ||
1989 starts_with(ss->name, "__markers"))
1990 return SS_TYPE_DATA;
1992 /* We replace all the ksymtab strings, so delete them */
1993 if (strcmp(ss->name, "__ksymtab_strings") == 0)
1994 return SS_TYPE_IGNORED;
1995 if (starts_with(ss->name, "__ksymtab"))
1996 return SS_TYPE_EXPORT;
1997 if (starts_with(ss->name, "__kcrctab"))
1998 return SS_TYPE_EXPORT;
2000 if (is_table_section(ss->name, true))
2001 return SS_TYPE_SPECIAL;
2003 if (starts_with(ss->name, ".ARM."))
2004 return SS_TYPE_SPECIAL;
2006 if (starts_with(ss->name, ".note"))
2007 return SS_TYPE_IGNORED;
2008 if (starts_with(ss->name, ".comment"))
2009 return SS_TYPE_IGNORED;
2010 if (starts_with(ss->name, "__param"))
2011 return SS_TYPE_IGNORED;
2012 if (starts_with(ss->name, ".exitcall.exit"))
2013 return SS_TYPE_IGNORED;
2014 if (starts_with(ss->name, ".modinfo"))
2015 return SS_TYPE_IGNORED;
2017 return SS_TYPE_UNKNOWN;
2020 void initialize_supersect_types(struct superbfd *sbfd)
2022 asection *sect;
2023 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2024 struct supersect *ss = fetch_supersect(sbfd, sect);
2025 ss->type = supersect_type(ss);
2026 if (ss->type == SS_TYPE_UNKNOWN) {
2027 err(sbfd, "Unknown section type: %s\n", ss->name);
2028 DIE;
2033 static void init_label_map(struct superbfd *sbfd)
2035 struct label_map *map;
2037 vec_init(&sbfd->maps);
2038 init_csyms(sbfd);
2039 init_callers(sbfd);
2041 struct symbol_hash csyms;
2042 symbol_hash_init(&csyms);
2044 asymbol **symp;
2045 for (symp = sbfd->syms.data;
2046 symp < sbfd->syms.data + sbfd->syms.size; symp++) {
2047 asymbol *csym = canonical_symbol(sbfd, *symp);
2048 if (csym == NULL)
2049 continue;
2050 char *key;
2051 assert(asprintf(&key, "%p", csym) >= 0);
2052 asymbol **csymp = symbol_hash_lookup(&csyms, key, TRUE);
2053 free(key);
2054 if (*csymp != NULL)
2055 continue;
2056 *csymp = csym;
2058 map = vec_grow(&sbfd->maps, 1);
2059 map->csym = csym;
2060 map->count = 0;
2061 map->label = symbol_label(sbfd, csym);
2064 struct label_mapp_hash label_maps;
2065 label_mapp_hash_init(&label_maps);
2066 for (map = sbfd->maps.data;
2067 map < sbfd->maps.data + sbfd->maps.size; map++) {
2068 struct label_map **mapp =
2069 label_mapp_hash_lookup(&label_maps, map->label, TRUE);
2070 if (*mapp == NULL) {
2071 *mapp = map;
2072 continue;
2075 struct label_map *first_map = *mapp;
2076 char *buf;
2077 if (first_map->count == 0) {
2078 assert(asprintf(&buf, "%s~%d", map->label, 0) >= 0);
2079 first_map->label = buf;
2081 first_map->count++;
2082 assert(asprintf(&buf, "%s~%d", map->label, first_map->count)
2083 >= 0);
2084 map->label = buf;
2087 label_mapp_hash_init(&sbfd->maps_hash);
2088 for (map = sbfd->maps.data;
2089 map < sbfd->maps.data + sbfd->maps.size; map++) {
2090 char *key;
2091 assert(asprintf(&key, "%p", map->csym) >= 0);
2092 struct label_map **mapp =
2093 label_mapp_hash_lookup(&sbfd->maps_hash, key, TRUE);
2094 free(key);
2095 *mapp = map;
2096 map->orig_label = map->label;
2100 static const char *label_lookup(struct superbfd *sbfd, asymbol *sym)
2102 asymbol *csym = canonical_symbol(sbfd, sym);
2103 char *key;
2104 assert(asprintf(&key, "%p", csym) >= 0);
2105 struct label_map **mapp =
2106 label_mapp_hash_lookup(&sbfd->maps_hash, key, FALSE);
2107 free(key);
2108 if (mapp == NULL)
2109 DIE;
2110 return (*mapp)->label;
2113 static void print_label_map(struct superbfd *sbfd)
2115 struct label_map *map;
2116 for (map = sbfd->maps.data;
2117 map < sbfd->maps.data + sbfd->maps.size; map++) {
2118 if (strcmp(map->orig_label, map->label) == 0)
2119 continue;
2120 debug1(sbfd, "Label change: %s -> %s\n",
2121 map->label, map->orig_label);
2125 static void label_map_set(struct superbfd *sbfd, const char *oldlabel,
2126 const char *label)
2128 struct label_map *map;
2129 for (map = sbfd->maps.data;
2130 map < sbfd->maps.data + sbfd->maps.size; map++) {
2131 if (strcmp(map->orig_label, oldlabel) == 0) {
2132 if (strcmp(map->orig_label, map->label) != 0 &&
2133 strcmp(map->label, label) != 0)
2134 DIE;
2135 map->label = label;
2136 return;
2139 DIE;
2142 static void init_callers(struct superbfd *sbfd)
2144 string_hash_init(&sbfd->callers);
2145 asection *sect;
2146 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2147 struct supersect *ss = fetch_supersect(sbfd, sect);
2148 arelent **relocp;
2149 for (relocp = ss->relocs.data;
2150 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
2151 asymbol *sym = *(*relocp)->sym_ptr_ptr;
2152 unsigned long val =
2153 sym->value + get_reloc_offset(ss, *relocp, true);
2154 char *key;
2155 assert(asprintf(&key, "%s+%lx", sym->section->name,
2156 val) >= 0);
2157 const char **ret = string_hash_lookup(&sbfd->callers,
2158 key, TRUE);
2159 free(key);
2160 if (*ret == NULL)
2161 *ret = sect->name;
2162 else
2163 *ret = "*multiple_callers*";
2168 static const char *find_caller(struct supersect *ss, asymbol *sym)
2170 char *key;
2171 assert(asprintf(&key, "%s+%lx", sym->section->name,
2172 (unsigned long)sym->value) >= 0);
2173 const char **ret = string_hash_lookup(&ss->parent->callers, key, FALSE);
2174 free(key);
2176 if (ret == NULL)
2177 return "*no_caller*";
2178 return *ret;
2181 static void init_csyms(struct superbfd *sbfd)
2183 asymbolpp_hash_init(&sbfd->csyms);
2185 asymbol **symp;
2186 for (symp = sbfd->syms.data; symp < sbfd->syms.data + sbfd->syms.size;
2187 symp++) {
2188 asymbol *sym = *symp;
2189 if ((sym->flags & BSF_DEBUGGING) != 0)
2190 continue;
2191 char *key;
2192 assert(asprintf(&key, "%s+%lx", sym->section->name,
2193 (unsigned long)sym->value) >= 0);
2194 asymbol ***csympp = asymbolpp_hash_lookup(&sbfd->csyms, key,
2195 TRUE);
2196 free(key);
2197 if (*csympp == NULL) {
2198 *csympp = symp;
2199 continue;
2201 asymbol *csym = **csympp;
2202 if ((csym->flags & BSF_GLOBAL) != 0)
2203 continue;
2204 if ((sym->flags & BSF_GLOBAL) != 0)
2205 *csympp = symp;
2209 static asymbol **symbolp_scan(struct supersect *ss, bfd_vma value)
2211 char *key;
2212 assert(asprintf(&key, "%s+%lx", ss->name, (unsigned long)value) >= 0);
2213 asymbol ***csympp =
2214 asymbolpp_hash_lookup(&ss->parent->csyms, key, FALSE);
2215 free(key);
2216 if (csympp != NULL)
2217 return *csympp;
2219 /* For section symbols of sections containing no symbols, return the
2220 section symbol that relocations are generated against */
2221 if (value == 0)
2222 return &ss->symbol;
2223 return NULL;
2226 static asymbol **canonical_symbolp(struct superbfd *sbfd, asymbol *sym)
2228 if (bfd_is_const_section(sym->section)) {
2229 asymbol **csymp;
2230 for (csymp = sbfd->syms.data;
2231 csymp < sbfd->syms.data + sbfd->syms.size; csymp++) {
2232 if (sym == *csymp)
2233 return csymp;
2235 return NULL;
2237 return symbolp_scan(fetch_supersect(sbfd, sym->section), sym->value);
2240 static asymbol *canonical_symbol(struct superbfd *sbfd, asymbol *sym)
2242 if (bfd_is_const_section(sym->section))
2243 return sym;
2244 asymbol **symp = canonical_symbolp(sbfd, sym);
2245 return symp != NULL ? *symp : NULL;
2248 static char *static_local_symbol(struct superbfd *sbfd, asymbol *sym)
2250 struct supersect *ss = fetch_supersect(sbfd, sym->section);
2251 if ((sym->flags & BSF_LOCAL) == 0 || (sym->flags & BSF_OBJECT) == 0)
2252 return NULL;
2253 char *dot = strrchr(sym->name, '.');
2254 if (dot == NULL || dot[1 + strspn(dot + 1, "0123546789")] != '\0')
2255 return NULL;
2256 char *basename = strndup(sym->name, dot - sym->name);
2257 char *mangled_name;
2258 if (strcmp(basename, "__func__") == 0 ||
2259 strcmp(basename, "__PRETTY_FUNCTION__") == 0)
2260 assert(asprintf(&mangled_name, "%s<%s>", basename,
2261 (char *)ss->contents.data + sym->value) >= 0);
2262 else
2263 assert(asprintf(&mangled_name, "%s<%s>", basename,
2264 find_caller(ss, sym)) >= 0);
2265 return mangled_name;
2268 static char *symbol_label(struct superbfd *sbfd, asymbol *sym)
2270 const char *filename = sbfd->abfd->filename;
2271 char *c = strstr(filename, ".KSPLICE");
2272 int flen = (c == NULL ? strlen(filename) : c - filename);
2274 char *label;
2275 if (bfd_is_und_section(sym->section) || (sym->flags & BSF_GLOBAL) != 0) {
2276 label = strdup(sym->name);
2277 } else if (bfd_is_const_section(sym->section)) {
2278 assert(asprintf(&label, "%s<%.*s>",
2279 sym->name, flen, filename) >= 0);
2280 } else {
2281 asymbol *gsym = canonical_symbol(sbfd, sym);
2283 if (gsym == NULL)
2284 assert(asprintf(&label, "%s+%lx<%.*s>",
2285 sym->section->name,
2286 (unsigned long)sym->value,
2287 flen, filename) >= 0);
2288 else if ((gsym->flags & BSF_GLOBAL) != 0)
2289 label = strdup(gsym->name);
2290 else if (static_local_symbol(sbfd, gsym))
2291 assert(asprintf(&label, "%s+%lx<%.*s>",
2292 static_local_symbol(sbfd, gsym),
2293 (unsigned long)sym->value,
2294 flen, filename) >= 0);
2295 else
2296 assert(asprintf(&label, "%s<%.*s>",
2297 gsym->name, flen, filename) >= 0);
2300 return label;
2303 static struct span *new_span(struct supersect *ss, bfd_vma start, bfd_vma size)
2305 struct span *span = vec_grow(&ss->spans, 1);
2306 span->size = size;
2307 span->start = start;
2308 span->ss = ss;
2309 span->keep = false;
2310 span->new = false;
2311 span->shift = 0;
2312 asymbol **symp = symbolp_scan(ss, span->start);
2313 if (symp != NULL) {
2314 span->symbol = *symp;
2315 span->label = label_lookup(ss->parent, span->symbol);
2316 } else {
2317 span->symbol = NULL;
2318 const char *label = label_lookup(ss->parent, ss->symbol);
2319 if (span->start != 0) {
2320 char *buf;
2321 assert(asprintf(&buf, "%s<span:%lx>", label,
2322 (unsigned long)span->start) >= 0);
2323 span->label = buf;
2324 } else {
2325 span->label = label;
2328 return span;
2331 static void initialize_string_spans(struct supersect *ss)
2333 const char *str;
2334 for (str = ss->contents.data;
2335 (void *)str < ss->contents.data + ss->contents.size;) {
2336 bfd_vma start = (unsigned long)str -
2337 (unsigned long)ss->contents.data;
2338 bfd_vma size = strlen(str) + 1;
2339 while ((start + size) % (1 << ss->alignment) != 0 &&
2340 start + size < ss->contents.size) {
2341 if (str[size] != '\0')
2342 DIE;
2343 size++;
2345 new_span(ss, start, size);
2346 str += size;
2350 static void initialize_spans(struct superbfd *sbfd)
2352 asection *sect;
2353 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2354 struct supersect *ss = fetch_supersect(sbfd, sect);
2355 if (ss->type == SS_TYPE_STRING)
2356 initialize_string_spans(ss);
2357 else if (!mode("keep") || (ss->type != SS_TYPE_SPECIAL &&
2358 ss->type != SS_TYPE_EXPORT))
2359 new_span(ss, 0, ss->contents.size);
2363 struct span *reloc_target_span(struct supersect *ss, arelent *reloc)
2365 asymbol *sym_ptr = *reloc->sym_ptr_ptr;
2366 if (bfd_is_const_section(sym_ptr->section))
2367 return NULL;
2369 bfd_vma addend = get_reloc_offset(ss, reloc, true) + sym_ptr->value;
2370 struct supersect *sym_ss =
2371 fetch_supersect(ss->parent, sym_ptr->section);
2372 struct span *span, *target_span = sym_ss->spans.data;
2373 for (span = sym_ss->spans.data;
2374 span < sym_ss->spans.data + sym_ss->spans.size; span++) {
2375 if (addend >= span->start && addend < span->start + span->size)
2376 target_span = span;
2378 return target_span;
2381 struct span *reloc_address_span(struct supersect *ss, arelent *reloc)
2383 struct span *span;
2384 for (span = ss->spans.data; span < ss->spans.data + ss->spans.size;
2385 span++) {
2386 if (reloc->address >= span->start &&
2387 reloc->address < span->start + span->size)
2388 return span;
2390 return NULL;
2393 void compute_span_shifts(struct superbfd *sbfd)
2395 asection *sect;
2396 struct span *span;
2397 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2398 struct supersect *ss = fetch_supersect(sbfd, sect);
2399 if (!ss->keep)
2400 continue;
2401 bfd_size_type offset = 0;
2402 for (span = ss->spans.data;
2403 span < ss->spans.data + ss->spans.size; span++) {
2404 if (!span->keep)
2405 continue;
2406 span->shift = offset - span->start;
2407 offset += span->size;
2412 void remove_unkept_spans(struct superbfd *sbfd)
2414 asection *sect;
2415 struct span *span;
2416 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2417 struct supersect *ss = fetch_supersect(sbfd, sect);
2418 struct arelentp_vec orig_relocs;
2419 vec_move(&orig_relocs, &ss->relocs);
2420 arelent **relocp, *reloc;
2421 for (relocp = orig_relocs.data;
2422 relocp < orig_relocs.data + orig_relocs.size; relocp++) {
2423 reloc = *relocp;
2424 asymbol *sym = *reloc->sym_ptr_ptr;
2425 span = reloc_target_span(ss, reloc);
2426 if ((span != NULL && span->keep && span->shift == 0) ||
2427 bfd_is_const_section(sym->section)) {
2428 *vec_grow(&ss->relocs, 1) = reloc;
2429 continue;
2431 if (span != NULL && span->keep) {
2432 arelent *new_reloc = malloc(sizeof(*new_reloc));
2433 *new_reloc = *reloc;
2434 new_reloc->addend =
2435 get_reloc_offset(ss, reloc, false);
2436 new_reloc->addend += span->shift;
2437 *vec_grow(&ss->new_relocs, 1) = new_reloc;
2442 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2443 struct supersect *ss = fetch_supersect(sbfd, sect), orig_ss;
2444 if (!ss->keep)
2445 continue;
2446 supersect_move(&orig_ss, ss);
2447 vec_init(&ss->spans);
2448 for (span = orig_ss.spans.data;
2449 span < orig_ss.spans.data + orig_ss.spans.size; span++) {
2450 if (!span->keep)
2451 continue;
2452 struct span *new_span = vec_grow(&ss->spans, 1);
2453 *new_span = *span;
2454 new_span->start = span->start + span->shift;
2455 new_span->shift = 0;
2456 sect_copy(ss, sect_do_grow(ss, 1, span->size, 1),
2457 &orig_ss, orig_ss.contents.data + span->start,
2458 span->size);