Don’t unmatch bug patched spans.
[ksplice.git] / objmanip.c
blob18f31779eeaad4b06312e0ad78b7eb53378fd08f
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-2009 Ksplice, Inc.
5 * Authors: Jeff Arnold, Anders Kaseorg, Tim Abbott
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License, version 2.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
18 * 02110-1301, USA.
21 /* objmanip performs various object file manipulations for Ksplice. Its first
22 * two arguments are always an input object file and an output object file.
24 * - keep-new-code: "objmanip <post.o> <out.o> keep-new-code <pre.o> <kid>"
26 * This mode prepares the object file to be installed as a ksplice update. The
27 * kid argument is the ksplice id string for the ksplice update being built.
29 * - keep-old-code: "objmanip <pre.o> <out.o> keep-old-code"
31 * This mode prepares the object file to be used for run-pre matching. This
32 * involves replacing all ELF relocations with ksplice relocations and
33 * writing ksplice_section structures for each ELF text or data section.
35 * - rmsyms mode: "objmanip <in.o> <out.o> rmsyms
37 * In this mode, any ELF relocations involving the list of symbol names given on
38 * standard input are replaced with ksplice relocations. This is used only
39 * for KSPLICE_STANDALONE.
41 * - finalize mode: "objmanip <in.o> <out.o> finalize"
43 * In this mode, any ELF relocations to undefined symbols are replaced with
44 * ksplice relocations.
47 /* Always define KSPLICE_STANDALONE, even if you're using integrated Ksplice.
48 objmanip won't compile without it. */
49 #define KSPLICE_STANDALONE
51 #define _GNU_SOURCE
52 #include "objcommon.h"
53 #include "kmodsrc/ksplice.h"
54 #include "kmodsrc/offsets.h"
55 #include "ksplice-patch/ksplice-patch.h"
56 #include <stdint.h>
57 #include <stdarg.h>
58 #include <stdlib.h>
59 #include <stdio.h>
60 #include <limits.h>
62 #define KSPLICE_SYMBOL_STR "KSPLICE_SYMBOL_"
64 #define symbol_init(sym) *(sym) = (asymbol *)NULL
65 DEFINE_HASH_TYPE(asymbol *, symbol_hash, symbol_hash_init, symbol_hash_free,
66 symbol_hash_lookup, symbol_init);
68 DECLARE_VEC_TYPE(const char *, str_vec);
70 DECLARE_VEC_TYPE(unsigned long, ulong_vec);
72 #define bool_init(b) *(b) = false
73 DEFINE_HASH_TYPE(bool, bool_hash, bool_hash_init, bool_hash_free,
74 bool_hash_lookup, bool_init);
76 #define ulong_init(x) *(x) = 0
77 DEFINE_HASH_TYPE(unsigned long, ulong_hash, ulong_hash_init,
78 ulong_hash_free, ulong_hash_lookup, ulong_init);
80 void do_keep_new_code(struct superbfd *isbfd, const char *pre);
81 void do_keep_old_code(struct superbfd *isbfd);
82 void do_finalize(struct superbfd *isbfd);
83 void do_rmsyms(struct superbfd *isbfd);
85 bool relocs_equal(struct supersect *old_src_ss, struct supersect *new_src_ss,
86 arelent *old_reloc, arelent *new_reloc);
87 bfd_vma non_dst_mask(struct supersect *ss, arelent *reloc);
88 bool all_relocs_equal(struct span *old_span, struct span *new_span);
89 static bool part_of_reloc(struct supersect *ss, unsigned long addr);
90 static bool nonrelocs_equal(struct span *old_span, struct span *new_span);
91 static void handle_section_symbol_renames(struct superbfd *oldsbfd,
92 struct superbfd *newsbfd);
93 static void compute_entry_points(struct superbfd *sbfd);
94 static void copy_patched_entry_points(struct superbfd *oldsbfd,
95 struct superbfd *newsbfd);
97 enum supersect_type supersect_type(struct supersect *ss);
98 void initialize_supersect_types(struct superbfd *sbfd);
99 static void initialize_spans(struct superbfd *sbfd);
100 static void initialize_string_spans(struct supersect *ss);
101 static void initialize_table_spans(struct superbfd *sbfd,
102 struct table_section *s);
103 static void initialize_table_section_spans(struct superbfd *sbfd);
104 static void initialize_ksplice_call_spans(struct supersect *ss);
105 struct span *reloc_target_span(struct supersect *ss, arelent *reloc);
106 static struct span *span_offset_target_span(struct span *span, int offset);
107 static bfd_vma reloc_target_offset(struct supersect *ss, arelent *reloc);
108 struct span *find_span(struct supersect *ss, bfd_size_type address);
109 void remove_unkept_spans(struct superbfd *sbfd);
110 void compute_span_shifts(struct superbfd *sbfd);
111 static struct span *new_span(struct supersect *ss, bfd_vma start, bfd_vma size);
112 static bool is_table_section(const char *name, bool consider_other,
113 bool consider_crc);
114 const struct table_section *get_table_section(const char *name);
115 void mangle_section_name(struct superbfd *sbfd, const char *name);
117 void rm_relocs(struct superbfd *isbfd);
118 void rm_some_relocs(struct supersect *ss);
119 void write_ksplice_reloc(struct supersect *ss, arelent *orig_reloc);
120 static void write_ksplice_reloc_howto(struct supersect *ss, const
121 struct ksplice_reloc_howto *const *addr,
122 reloc_howto_type *howto,
123 enum ksplice_reloc_howto_type type);
124 static void write_ksplice_date_reloc(struct supersect *ss, unsigned long offset,
125 const char *str,
126 enum ksplice_reloc_howto_type type);
127 static void write_ksplice_patch_reloc(struct supersect *ss,
128 const char *sectname, unsigned long *addr,
129 bfd_size_type size, const char *label,
130 long addend);
131 static void write_ksplice_nonreloc_howto(struct supersect *ss,
132 const struct ksplice_reloc_howto
133 *const *addr,
134 enum ksplice_reloc_howto_type type,
135 int size);
136 static void write_date_relocs(struct superbfd *sbfd, const char *str,
137 enum ksplice_reloc_howto_type type);
138 static void write_table_relocs(struct superbfd *sbfd, const char *sectname,
139 enum ksplice_reloc_howto_type type);
140 static void write_ksplice_table_reloc(struct supersect *ss,
141 unsigned long address,
142 const char *label,
143 enum ksplice_reloc_howto_type type);
144 void load_ksplice_symbol_offsets(struct superbfd *sbfd);
145 void write_canary(struct supersect *ss, int offset, bfd_size_type size,
146 bfd_vma dst_mask);
147 static void write_ksplice_section(struct span *span);
148 void write_ksplice_patches(struct superbfd *sbfd, struct span *span);
149 void write_ksplice_patch(struct superbfd *sbfd, struct span *span,
150 const char *label, long offset);
151 void *write_patch_storage(struct supersect *ss, struct ksplice_patch *patch,
152 size_t size, struct supersect **data_ssp);
153 void write_ksplice_deleted_patch(struct superbfd *sbfd, const char *name,
154 const char *label, const char *sectname);
155 static void write_bugline_patches(struct superbfd *sbfd);
156 asymbol **make_undefined_symbolp(struct superbfd *sbfd, const char *name);
157 void filter_table_sections(struct superbfd *isbfd);
158 void filter_table_section(struct superbfd *sbfd, const struct table_section *s);
159 void keep_referenced_sections(struct superbfd *sbfd);
160 void mark_precallable_spans(struct superbfd *sbfd);
161 bfd_boolean copy_object(bfd *ibfd, bfd *obfd);
162 void setup_section(bfd *ibfd, asection *isection, void *obfdarg);
163 static void setup_new_section(bfd *obfd, struct supersect *ss);
164 static void write_section(bfd *obfd, asection *osection, void *arg);
165 static void delete_obsolete_relocs(struct supersect *ss);
166 void mark_symbols_used_in_relocations(bfd *abfd, asection *isection,
167 void *ignored);
168 static void ss_mark_symbols_used_in_relocations(struct supersect *ss);
169 void filter_symbols(bfd *ibfd, bfd *obfd, struct asymbolp_vec *osyms,
170 struct asymbolp_vec *isyms);
171 static bool deleted_table_section_symbol(bfd *abfd, asymbol *sym);
172 struct supersect *__attribute((format(printf, 2, 3)))
173 make_section(struct superbfd *sbfd, const char *fmt, ...);
174 void __attribute__((format(printf, 3, 4)))
175 write_string(struct supersect *ss, const char **addr, const char *fmt, ...);
176 void write_ksplice_export(struct superbfd *sbfd, struct span *span, bool del);
177 void write_reloc(struct supersect *ss, const void *addr, asymbol **symp,
178 bfd_vma offset);
179 arelent *create_reloc(struct supersect *ss, const void *addr, asymbol **symp,
180 bfd_vma offset);
181 static void foreach_symbol_pair(struct superbfd *oldsbfd, struct superbfd *newsbfd,
182 void (*fn)(struct span *old_span,
183 asymbol *oldsym,
184 struct span *new_span,
185 asymbol *newsym));
186 static void check_global_symbols(struct span *old_span, asymbol *oldsym,
187 struct span *new_span, asymbol *newsym);
188 static void match_global_symbols(struct span *old_span, asymbol *oldsym,
189 struct span *new_span, asymbol *newsym);
190 static void match_symbol_spans(struct span *old_span, asymbol *oldsym,
191 struct span *new_span, asymbol *newsym);
192 static void match_table_spans(struct span *old_span, struct span *new_span);
194 static struct span *get_crc_span(struct span *span,
195 const struct table_section *ts);
196 static void foreach_span_pair(struct superbfd *oldsbfd,
197 struct superbfd *newsbfd,
198 void (*fn)(struct span *old_span,
199 struct span *new_span));
200 static void match_spans_by_label(struct span *old_span, struct span *new_span);
201 static void match_string_spans(struct span *old_span, struct span *new_span);
202 static void mark_new_spans(struct superbfd *sbfd);
203 static void handle_deleted_spans(struct superbfd *oldsbfd,
204 struct superbfd *newsbfd);
205 static void unmatch_addr_spans(struct span *old_span, struct span *new_span,
206 const struct table_section *ts);
207 static void compare_matched_spans(struct superbfd *newsbfd);
208 static void compare_spans(struct span *old_span, struct span *new_span);
209 static void update_nonzero_offsets(struct superbfd *sbfd);
210 static void handle_nonzero_offset_relocs(struct supersect *ss);
211 static void keep_span(struct span *span);
213 static void init_objmanip_superbfd(struct superbfd *sbfd);
214 static const char *label_lookup(struct superbfd *sbfd, asymbol *sym);
215 static void label_map_set(struct superbfd *sbfd, const char *oldlabel,
216 const char *label);
217 static void print_label_changes(struct superbfd *sbfd);
218 static void init_label_map(struct superbfd *sbfd);
219 static void change_initial_label(struct span *span, const char *label);
220 static asymbol **symbolp_scan(struct supersect *ss, bfd_vma value);
221 static void init_csyms(struct superbfd *sbfd);
222 static void init_callers(struct superbfd *sbfd);
223 static asymbol *canonical_symbol(struct superbfd *sbfd, asymbol *sym);
224 static asymbol **canonical_symbolp(struct superbfd *sbfd, asymbol *sym);
225 static char *static_local_symbol(struct superbfd *sbfd, asymbol *sym);
226 static char *symbol_label(struct superbfd *sbfd, asymbol *sym);
228 int verbose = 0;
229 #define debug_(sbfd, level, fmt, ...) \
230 do { \
231 if (verbose >= (level)) \
232 printf("%s: " fmt, (sbfd)->abfd->filename, \
233 ## __VA_ARGS__); \
234 } while (0)
235 #define debug0(sbfd, fmt, ...) debug_(sbfd, 0, fmt, ## __VA_ARGS__)
236 #define debug1(sbfd, fmt, ...) debug_(sbfd, 1, fmt, ## __VA_ARGS__)
237 #define err(sbfd, fmt, ...) \
238 do { \
239 fprintf(stderr, "%s: " fmt, (sbfd)->abfd->filename, \
240 ## __VA_ARGS__); \
241 } while (0)
243 struct str_vec delsects;
244 struct asymbolp_vec extract_syms;
245 bool changed;
247 struct ksplice_config *config;
249 const char *modestr, *kid, *finalize_target = NULL;
250 bool write_output = true;
252 struct superbfd *offsets_sbfd = NULL;
254 #define mode(str) strstarts(modestr, str)
256 DECLARE_VEC_TYPE(unsigned long, addr_vec);
257 DEFINE_HASH_TYPE(struct addr_vec, addr_vec_hash,
258 addr_vec_hash_init, addr_vec_hash_free, addr_vec_hash_lookup,
259 vec_init);
260 struct addr_vec_hash system_map;
262 struct bool_hash system_map_written;
263 struct ulong_hash ksplice_symbol_offset;
264 struct ulong_hash ksplice_howto_offset;
265 struct ulong_hash ksplice_string_offset;
267 void load_system_map()
269 const char *config_dir = getenv("KSPLICE_CONFIG_DIR");
270 assert(config_dir);
271 FILE *fp = fopen(strprintf("%s/System.map", config_dir), "r");
272 assert(fp);
273 addr_vec_hash_init(&system_map);
274 unsigned long addr;
275 char type;
276 char *sym;
277 while (fscanf(fp, "%lx %c %as\n", &addr, &type, &sym) == 3)
278 *vec_grow(addr_vec_hash_lookup(&system_map, sym, TRUE),
279 1) = addr;
280 fclose(fp);
283 void load_ksplice_symbol_offsets(struct superbfd *sbfd)
285 asection *sect = bfd_get_section_by_name(sbfd->abfd,
286 ".ksplice_symbols");
287 if (sect == NULL)
288 return;
289 struct supersect *ss = fetch_supersect(sbfd, sect);
291 struct ksplice_symbol *ksym;
292 for (ksym = ss->contents.data;
293 (void *)ksym < ss->contents.data + ss->contents.size; ksym++) {
294 const char *label = read_string(ss, &ksym->label);
295 unsigned long *ksymbol_offp =
296 ulong_hash_lookup(&ksplice_symbol_offset, label, TRUE);
297 *ksymbol_offp = addr_offset(ss, ksym);
301 void load_offsets()
303 char *kmodsrc = getenv("KSPLICE_KMODSRC");
304 assert(kmodsrc != NULL);
305 bfd *offsets_bfd = bfd_openr(strprintf("%s/offsets.o", kmodsrc), NULL);
306 assert(offsets_bfd != NULL);
307 char **matching;
308 assert(bfd_check_format_matches(offsets_bfd, bfd_object, &matching));
309 offsets_sbfd = fetch_superbfd(offsets_bfd);
311 asection *config_sect = bfd_get_section_by_name(offsets_sbfd->abfd,
312 ".ksplice_config");
313 struct supersect *config_ss =
314 fetch_supersect(offsets_sbfd, config_sect);
316 config = config_ss->contents.data;
319 void load_options(struct superbfd *sbfd)
321 asection *sect = bfd_get_section_by_name(sbfd->abfd,
322 ".ksplice_options");
323 if (sect == NULL)
324 return;
325 struct supersect *ss = fetch_supersect(sbfd, sect);
326 const struct ksplice_option *opt;
327 for (opt = ss->contents.data;
328 (void *)opt < ss->contents.data + ss->contents.size; opt++) {
329 if (opt->type == KSPLICE_OPTION_ASSUME_RODATA) {
330 arelent *reloc = find_reloc(ss, &opt->target);
331 assert(reloc != NULL);
332 struct span *span = reloc_target_span(ss, reloc);
333 assert(span != NULL);
334 assert(span->ss->type == SS_TYPE_DATA);
335 assert(span->start == 0 &&
336 span->size == span->ss->contents.size);
337 span->ss->type = SS_TYPE_RODATA;
338 break;
339 } else {
340 err(sbfd, "Unrecognized Ksplice option %d\n",
341 opt->type);
342 DIE;
347 bool matchable_data_section(struct supersect *ss)
349 if (ss->type == SS_TYPE_STRING)
350 return true;
351 if (ss->type == SS_TYPE_RODATA)
352 return true;
353 if (ss->type == SS_TYPE_DATA && ss->relocs.size != 0)
354 return true;
355 if (ss->type == SS_TYPE_EXPORT)
356 return true;
357 if (ss->type == SS_TYPE_BUGTABLE)
358 return true;
359 return false;
362 bool unchangeable_section(struct supersect *ss)
364 if (ss->type == SS_TYPE_DATA)
365 return true;
366 if (ss->type == SS_TYPE_IGNORED && !strstarts(ss->name, ".debug") &&
367 strcmp(ss->name, "__ksymtab_strings") != 0)
368 return true;
369 return false;
372 int main(int argc, char *argv[])
374 if (getenv("KSPLICE_VERBOSE") != NULL)
375 verbose = atoi(getenv("KSPLICE_VERBOSE"));
377 bfd_init();
378 bfd *ibfd = bfd_openr(argv[1], NULL);
379 assert(ibfd);
381 char **matching;
382 if (bfd_check_format_matches(ibfd, bfd_archive, &matching) &&
383 bfd_openr_next_archived_file(ibfd, NULL) == NULL)
384 return 66; /* empty archive */
385 assert(bfd_check_format_matches(ibfd, bfd_object, &matching));
387 const char *output_target = bfd_get_target(ibfd);
389 load_system_map();
390 load_offsets();
392 bool_hash_init(&system_map_written);
393 ulong_hash_init(&ksplice_symbol_offset);
394 ulong_hash_init(&ksplice_howto_offset);
395 ulong_hash_init(&ksplice_string_offset);
397 struct superbfd *isbfd = fetch_superbfd(ibfd);
399 modestr = argv[3];
400 if (mode("finalize"))
401 finalize_target = argv[4];
402 init_objmanip_superbfd(isbfd);
403 if (mode("keep-new-code")) {
404 kid = argv[5];
405 do_keep_new_code(isbfd, argv[4]);
406 } else if (mode("keep-old-code")) {
407 do_keep_old_code(isbfd);
408 } else if (mode("finalize")) {
409 do_finalize(isbfd);
410 } else if (mode("rmsyms")) {
411 do_rmsyms(isbfd);
414 if (write_output) {
415 bfd *obfd = bfd_openw(argv[2], output_target);
416 assert(obfd);
417 copy_object(ibfd, obfd);
418 assert(bfd_close(obfd));
421 if (offsets_sbfd != NULL)
422 assert(bfd_close(offsets_sbfd->abfd));
423 assert(bfd_close(ibfd));
424 return EXIT_SUCCESS;
427 void do_keep_new_code(struct superbfd *isbfd, const char *pre)
429 struct bfd *prebfd = bfd_openr(pre, NULL);
430 assert(prebfd != NULL);
431 char **matching;
432 assert(bfd_check_format_matches(prebfd, bfd_object, &matching));
434 struct superbfd *presbfd = fetch_superbfd(prebfd);
435 init_objmanip_superbfd(presbfd);
437 foreach_symbol_pair(presbfd, isbfd, match_global_symbols);
438 debug1(isbfd, "Matched global\n");
439 foreach_span_pair(presbfd, isbfd, match_string_spans);
440 debug1(isbfd, "Matched string spans\n");
441 foreach_symbol_pair(presbfd, isbfd, match_symbol_spans);
442 debug1(isbfd, "Matched by name\n");
443 foreach_span_pair(presbfd, isbfd, match_spans_by_label);
444 debug1(isbfd, "Matched by label\n");
445 foreach_span_pair(presbfd, isbfd, match_table_spans);
446 debug1(isbfd, "Matched table spans\n");
448 do {
449 changed = false;
450 compare_matched_spans(isbfd);
451 update_nonzero_offsets(isbfd);
452 mark_new_spans(isbfd);
453 } while (changed);
454 vec_init(&delsects);
456 foreach_symbol_pair(presbfd, isbfd, check_global_symbols);
458 handle_deleted_spans(presbfd, isbfd);
459 handle_section_symbol_renames(presbfd, isbfd);
461 copy_patched_entry_points(presbfd, isbfd);
463 assert(bfd_close(prebfd));
465 do {
466 changed = false;
467 mark_precallable_spans(isbfd);
468 } while (changed);
470 asection *sect;
471 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
472 struct supersect *ss = fetch_supersect(isbfd, sect);
473 ss->keep = false;
474 struct span *span;
475 for (span = ss->spans.data;
476 span < ss->spans.data + ss->spans.size; span++) {
477 if (strstarts(ss->name, ".ksplice_options"))
478 span->keep = false;
479 else if (span->new || span->patch || span->datapatch)
480 keep_span(span);
481 else
482 span->keep = false;
483 if (span->patch && span->precallable) {
484 err(isbfd, "Patched span %s can be reached "
485 "by a precall function\n", span->label);
486 DIE;
491 print_label_changes(isbfd);
493 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
494 struct supersect *ss = fetch_supersect(isbfd, sect);
495 struct span *span;
496 for (span = ss->spans.data;
497 span < ss->spans.data + ss->spans.size; span++) {
498 if (span->patch || span->bugpatch || span->datapatch)
499 debug0(isbfd, "Patching span %s\n",
500 span->label);
504 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
505 struct supersect *ss = fetch_supersect(isbfd, sect);
506 struct span *span;
507 for (span = ss->spans.data;
508 span < ss->spans.data + ss->spans.size; span++) {
509 if (span->new)
510 debug0(isbfd, "New span %s\n", span->label);
514 write_output = false;
515 const char **sectname;
516 for (sectname = delsects.data;
517 sectname < delsects.data + delsects.size; sectname++) {
518 write_output = true;
519 debug0(isbfd, "Deleted section: %s\n", *sectname);
522 filter_table_sections(isbfd);
524 compute_span_shifts(isbfd);
526 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
527 struct supersect *ss = fetch_supersect(isbfd, sect);
528 if (ss->type == SS_TYPE_KSPLICE_CALL)
529 continue;
530 struct span *span;
531 for (span = ss->spans.data;
532 span < ss->spans.data + ss->spans.size; span++) {
533 if (span->keep)
534 write_output = true;
535 if (span->patch || span->new || span->datapatch)
536 write_ksplice_section(span);
537 if (span->patch || span->datapatch)
538 write_ksplice_patches(isbfd, span);
539 if (ss->type == SS_TYPE_EXPORT && span->new)
540 write_ksplice_export(isbfd, span, false);
544 write_bugline_patches(isbfd);
545 rm_relocs(isbfd);
546 remove_unkept_spans(isbfd);
549 void do_keep_old_code(struct superbfd *isbfd)
551 asection *sect;
552 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
553 struct supersect *ss = fetch_supersect(isbfd, sect);
554 ss->keep = false;
555 struct span *span;
556 for (span = ss->spans.data;
557 span < ss->spans.data + ss->spans.size; span++) {
558 span->keep = false;
559 if (ss->type == SS_TYPE_TEXT &&
560 !strstarts(ss->name, ".fixup"))
561 keep_span(span);
562 if (ss->type == SS_TYPE_EXPORT)
563 keep_span(span);
567 asymbol **symp;
568 for (symp = isbfd->syms.data;
569 symp < isbfd->syms.data + isbfd->syms.size; symp++) {
570 asymbol *sym = *symp;
571 if (!bfd_is_const_section(sym->section) &&
572 (sym->flags & BSF_GLOBAL) != 0) {
573 struct supersect *sym_ss =
574 fetch_supersect(isbfd, sym->section);
575 if (sym->value == sym_ss->contents.size)
576 continue;
577 struct span *span = find_span(sym_ss, sym->value);
578 assert(span != NULL);
579 if (sym_ss->type != SS_TYPE_IGNORED)
580 keep_span(span);
584 do {
585 changed = false;
586 keep_referenced_sections(isbfd);
587 } while (changed);
589 filter_table_sections(isbfd);
590 compute_span_shifts(isbfd);
592 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
593 struct supersect *ss = fetch_supersect(isbfd, sect);
594 asymbol *sym = canonical_symbol(isbfd, sect->symbol);
595 if (sym == NULL)
596 continue;
597 if ((sym->flags & BSF_WEAK) != 0)
598 continue;
599 if (bfd_get_section_size(sect) == 0)
600 continue;
601 if (!ss->keep)
602 continue;
603 if (ss->type != SS_TYPE_TEXT && !matchable_data_section(ss))
604 continue;
606 struct span *span;
607 for (span = ss->spans.data;
608 span < ss->spans.data + ss->spans.size; span++) {
609 if (span->keep)
610 write_ksplice_section(span);
614 write_table_relocs(isbfd, "__bug_table", KSPLICE_HOWTO_BUG);
615 write_table_relocs(isbfd, "__ex_table", KSPLICE_HOWTO_EXTABLE);
616 rm_relocs(isbfd);
617 remove_unkept_spans(isbfd);
619 mangle_section_name(isbfd, "__markers");
620 mangle_section_name(isbfd, "__ex_table");
621 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
622 struct supersect *ss = fetch_supersect(isbfd, sect);
623 if (ss->type == SS_TYPE_EXPORT)
624 mangle_section_name(isbfd, ss->name);
628 void do_finalize(struct superbfd *isbfd)
630 load_ksplice_symbol_offsets(isbfd);
631 asection *sect;
632 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
633 struct supersect *ss = fetch_supersect(isbfd, sect);
634 if (ss->type == SS_TYPE_EXIT) {
635 struct span *span;
636 for (span = ss->spans.data;
637 span < ss->spans.data + ss->spans.size; span++)
638 span->keep = false;
639 ss->keep = false;
642 write_date_relocs(isbfd, "<{DATE...}>", KSPLICE_HOWTO_DATE);
643 write_date_relocs(isbfd, "<{TIME}>", KSPLICE_HOWTO_TIME);
644 rm_relocs(isbfd);
647 void do_rmsyms(struct superbfd *isbfd)
649 asection *extract_sect = bfd_get_section_by_name(isbfd->abfd,
650 ".ksplice_extract");
651 if (extract_sect != NULL) {
652 struct supersect *extract_ss = fetch_supersect(isbfd,
653 extract_sect);
654 arelent **relocp;
655 for (relocp = extract_ss->relocs.data;
656 relocp < extract_ss->relocs.data + extract_ss->relocs.size;
657 relocp++) {
658 asymbol *sym = *(*relocp)->sym_ptr_ptr;
659 if (bfd_is_und_section(sym->section)) {
660 debug1(isbfd, "extracting symbol %s\n",
661 sym->name);
662 *vec_grow(&extract_syms, 1) = sym;
667 rm_relocs(isbfd);
670 void match_spans(struct span *old_span, struct span *new_span)
672 struct superbfd *sbfd = new_span->ss->parent;
673 if (old_span->match == new_span && new_span->match == old_span)
674 return;
675 if (old_span->match != NULL) {
676 err(sbfd, "Matching conflict: old %s: %s != %s\n",
677 old_span->label, old_span->match->label, new_span->label);
678 DIE;
680 if (new_span->match != NULL) {
681 err(sbfd, "Matching conflict: new %s: %s != %s\n",
682 new_span->label, new_span->match->label, old_span->label);
683 DIE;
685 old_span->match = new_span;
686 new_span->match = old_span;
687 debug1(sbfd, "Matched old %s to new %s\n", old_span->label,
688 new_span->label);
689 if (old_span->ss->type != new_span->ss->type &&
690 old_span->ss->type == new_span->ss->orig_type)
691 old_span->ss->type = new_span->ss->type;
693 const struct table_section *ts = get_table_section(old_span->ss->name);
694 if (ts == NULL || !ts->has_addr || ts->other_sect == NULL)
695 return;
696 struct span *old_sym_span =
697 span_offset_target_span(old_span, ts->other_offset);
698 struct span *new_sym_span =
699 span_offset_target_span(new_span, ts->other_offset);
700 assert(old_sym_span != NULL && new_sym_span != NULL);
701 match_spans(old_sym_span, new_sym_span);
704 static void match_global_symbols(struct span *old_span, asymbol *oldsym,
705 struct span *new_span, asymbol *newsym)
707 if ((oldsym->flags & BSF_GLOBAL) == 0 ||
708 (newsym->flags & BSF_GLOBAL) == 0)
709 return;
710 match_spans(old_span, new_span);
713 static void check_global_symbols(struct span *old_span, asymbol *oldsym,
714 struct span *new_span, asymbol *newsym)
716 if ((oldsym->flags & BSF_GLOBAL) == 0 ||
717 (newsym->flags & BSF_GLOBAL) == 0)
718 return;
719 if (old_span->ss->type == SS_TYPE_IGNORED)
720 return;
721 if (old_span->match != new_span || new_span->match != old_span) {
722 err(new_span->ss->parent, "Global symbol span mismatch: %s "
723 "%s/%s\n", oldsym->name, old_span->label, new_span->label);
724 DIE;
728 static void foreach_symbol_pair(struct superbfd *oldsbfd, struct superbfd *newsbfd,
729 void (*fn)(struct span *old_span,
730 asymbol *oldsym,
731 struct span *new_span,
732 asymbol *newsym))
734 asymbol **oldsymp, **newsymp;
735 for (oldsymp = oldsbfd->syms.data;
736 oldsymp < oldsbfd->syms.data + oldsbfd->syms.size; oldsymp++) {
737 asymbol *oldsym = *oldsymp;
738 if (bfd_is_const_section(oldsym->section))
739 continue;
740 for (newsymp = newsbfd->syms.data;
741 newsymp < newsbfd->syms.data + newsbfd->syms.size;
742 newsymp++) {
743 asymbol *newsym = *newsymp;
744 if (bfd_is_const_section(newsym->section))
745 continue;
746 if (strcmp(oldsym->name, newsym->name) != 0)
747 continue;
749 struct supersect *old_ss =
750 fetch_supersect(oldsbfd, oldsym->section);
751 struct supersect *new_ss =
752 fetch_supersect(newsbfd, newsym->section);
753 if ((old_ss->type != new_ss->type &&
754 old_ss->type != new_ss->orig_type) ||
755 old_ss->type == SS_TYPE_SPECIAL ||
756 old_ss->type == SS_TYPE_EXPORT)
757 continue;
759 struct span *old_span =
760 find_span(old_ss, oldsym->value);
761 struct span *new_span =
762 find_span(new_ss, newsym->value);
763 if (old_span == NULL) {
764 err(oldsbfd, "Could not find span for %s\n",
765 oldsym->name);
766 DIE;
768 if (new_span == NULL) {
769 err(newsbfd, "Could not find span for %s\n",
770 newsym->name);
771 DIE;
773 fn(old_span, oldsym, new_span, newsym);
778 static void match_symbol_spans(struct span *old_span, asymbol *oldsym,
779 struct span *new_span, asymbol *newsym)
781 if ((oldsym->flags & BSF_DEBUGGING) != 0 ||
782 (newsym->flags & BSF_DEBUGGING) != 0)
783 return;
784 if (old_span->ss->type == SS_TYPE_SPECIAL)
785 return;
786 if (static_local_symbol(old_span->ss->parent, oldsym) ||
787 static_local_symbol(new_span->ss->parent, newsym))
788 return;
789 if (old_span->match == NULL && new_span->match == NULL)
790 match_spans(old_span, new_span);
793 static void match_spans_by_label(struct span *old_span, struct span *new_span)
795 if (old_span->ss->type == SS_TYPE_STRING ||
796 (is_table_section(old_span->ss->name, true, false) &&
797 !is_table_section(old_span->ss->name, false, false)))
798 return;
799 if (strcmp(old_span->label, new_span->label) == 0)
800 match_spans(old_span, new_span);
803 static void match_string_spans(struct span *old_span, struct span *new_span)
805 if (old_span->ss->type != SS_TYPE_STRING ||
806 strcmp(old_span->ss->name, new_span->ss->name) != 0)
807 return;
808 if (strcmp((char *)old_span->ss->contents.data + old_span->start,
809 (char *)new_span->ss->contents.data + new_span->start) == 0)
810 match_spans(old_span, new_span);
813 static void foreach_span_pair(struct superbfd *oldsbfd,
814 struct superbfd *newsbfd,
815 void (*fn)(struct span *old_span,
816 struct span *new_span))
818 asection *oldsect, *newsect;
819 struct supersect *oldss, *newss;
820 struct span *old_span, *new_span;
821 for (newsect = newsbfd->abfd->sections; newsect != NULL;
822 newsect = newsect->next) {
823 newss = fetch_supersect(newsbfd, newsect);
824 for (oldsect = oldsbfd->abfd->sections; oldsect != NULL;
825 oldsect = oldsect->next) {
826 oldss = fetch_supersect(oldsbfd, oldsect);
827 if (oldss->type != newss->type)
828 continue;
829 for (new_span = newss->spans.data;
830 new_span < newss->spans.data + newss->spans.size;
831 new_span++) {
832 for (old_span = oldss->spans.data;
833 old_span < oldss->spans.data +
834 oldss->spans.size; old_span++)
835 fn(old_span, new_span);
841 static void mark_new_spans(struct superbfd *sbfd)
843 asection *sect;
844 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
845 struct supersect *ss = fetch_supersect(sbfd, sect);
846 if (ss->type == SS_TYPE_SPECIAL || ss->type == SS_TYPE_IGNORED)
847 continue;
848 struct span *span;
849 for (span = ss->spans.data;
850 span < ss->spans.data + ss->spans.size; span++) {
851 if (span->match == NULL)
852 span->new = true;
857 static void handle_deleted_spans(struct superbfd *oldsbfd,
858 struct superbfd *newsbfd)
860 asection *sect;
861 for (sect = oldsbfd->abfd->sections; sect != NULL; sect = sect->next) {
862 struct supersect *ss = fetch_supersect(oldsbfd, sect);
863 struct span *span;
864 for (span = ss->spans.data;
865 span < ss->spans.data + ss->spans.size; span++) {
866 if (span->match != NULL)
867 continue;
868 if (ss->type == SS_TYPE_EXPORT) {
869 *vec_grow(&delsects, 1) = span->label;
870 write_ksplice_export(newsbfd, span, true);
871 } else if (ss->type == SS_TYPE_TEXT) {
872 *vec_grow(&delsects, 1) = span->label;
873 if (span->symbol == NULL)
874 DIE;
875 write_ksplice_deleted_patch
876 (newsbfd, span->symbol->name, span->label,
877 span->ss->name);
883 static void handle_nonzero_offset_relocs(struct supersect *ss)
885 struct span *address_span, *target_span;
886 arelent **relocp;
887 for (relocp = ss->relocs.data;
888 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
889 arelent *reloc = *relocp;
890 address_span = find_span(ss, reloc->address);
891 if (!address_span->new && !address_span->patch)
892 continue;
894 asymbol *sym = *reloc->sym_ptr_ptr;
895 if (bfd_is_const_section(sym->section))
896 continue;
897 bfd_vma offset = reloc_target_offset(ss, reloc);
898 target_span = reloc_target_span(ss, reloc);
899 if (sym->value + offset == target_span->start)
900 continue;
902 if (target_span->ss->type != SS_TYPE_TEXT)
903 continue;
904 if (target_span->patch)
905 continue;
907 target_span->patch = true;
908 changed = true;
909 debug1(ss->parent, "Changing %s because a relocation from sect "
910 "%s has a nonzero offset %lx+%lx into it\n",
911 target_span->label, ss->name, (unsigned long)sym->value,
912 (unsigned long)offset);
916 static void update_nonzero_offsets(struct superbfd *sbfd)
918 asection *sect;
919 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
920 struct supersect *ss = fetch_supersect(sbfd, sect);
921 if (ss->type == SS_TYPE_SPECIAL || ss->type == SS_TYPE_IGNORED)
922 continue;
923 handle_nonzero_offset_relocs(ss);
927 static void unmatch_addr_spans(struct span *old_span, struct span *new_span,
928 const struct table_section *ts)
930 struct span *old_sym_span =
931 span_offset_target_span(old_span, ts->addr_offset);
932 struct span *new_sym_span =
933 span_offset_target_span(new_span, ts->addr_offset);
934 assert(old_sym_span != NULL && new_sym_span != NULL);
935 if (old_sym_span->match == new_sym_span &&
936 new_sym_span->match == old_sym_span &&
937 !(new_sym_span->patch && new_sym_span->ss->type == SS_TYPE_TEXT)) {
938 if (old_sym_span->ss->type == SS_TYPE_TEXT) {
939 debug1(new_span->ss->parent, "Patching %s due "
940 "to relocations from special section %s\n",
941 new_sym_span->label, new_span->label);
942 new_sym_span->patch = true;
943 } else {
944 debug1(new_span->ss->parent, "Unmatching %s and %s due "
945 "to relocations from special section %s/%s\n",
946 old_sym_span->label, new_sym_span->label,
947 old_span->label, new_span->label);
948 old_sym_span->match = NULL;
949 new_sym_span->match = NULL;
951 changed = true;
955 static void compare_spans(struct span *old_span, struct span *new_span)
957 struct superbfd *newsbfd = new_span->ss->parent;
959 bool nonrelocs_match = nonrelocs_equal(old_span, new_span);
960 bool relocs_match = all_relocs_equal(old_span, new_span);
961 if (nonrelocs_match && relocs_match) {
962 const struct table_section *ts =
963 get_table_section(old_span->ss->name);
964 if (ts != NULL && ts->crc_sect != NULL) {
965 struct span *old_crc_span = get_crc_span(old_span, ts);
966 struct span *new_crc_span = get_crc_span(new_span, ts);
967 assert(old_crc_span != NULL);
968 assert(new_crc_span != NULL);
969 if (old_crc_span->match != new_crc_span ||
970 new_crc_span->match != old_crc_span) {
971 debug1(newsbfd, "Unmatching %s and %s due to "
972 "nonmatching CRCs\n", old_span->label,
973 new_span->label);
974 old_span->match = NULL;
975 new_span->match = NULL;
978 return;
980 if (old_span->ss->type == SS_TYPE_BUGTABLE &&
981 new_span->ss->type == SS_TYPE_BUGTABLE && relocs_match) {
982 if (new_span->bugpatch)
983 return;
984 debug1(newsbfd, "Changing %s due to nonmatching line numbers\n",
985 new_span->label);
986 new_span->bugpatch = true;
987 return;
990 char *reason;
991 if (new_span->contents_size != old_span->contents_size)
992 reason = "differing sizes";
993 else if (!nonrelocs_match)
994 reason = "differing contents";
995 else
996 reason = "differing relocations";
998 if (new_span->ss->type == SS_TYPE_TEXT) {
999 if (new_span->patch)
1000 return;
1001 new_span->patch = true;
1002 debug1(newsbfd, "Changing %s due to %s\n", new_span->label,
1003 reason);
1004 } else if (new_span->ss->type == SS_TYPE_RODATA &&
1005 new_span->contents_size == old_span->contents_size) {
1006 if (new_span->datapatch)
1007 return;
1008 new_span->datapatch = true;
1009 debug1(newsbfd, "Changing %s in-place due to %s\n",
1010 new_span->label, reason);
1011 } else if (new_span->ss->type == SS_TYPE_STRING &&
1012 old_span->ss->type == SS_TYPE_STRING && relocs_match &&
1013 strcmp(new_span->ss->contents.data + new_span->start,
1014 old_span->ss->contents.data + old_span->start) == 0) {
1015 return;
1016 } else {
1017 debug1(newsbfd, "Unmatching %s and %s due to %s\n",
1018 old_span->label, new_span->label, reason);
1019 new_span->bugpatch = false;
1020 new_span->match = NULL;
1021 old_span->match = NULL;
1022 if (old_span->ss->type == SS_TYPE_SPECIAL) {
1023 const struct table_section *ts =
1024 get_table_section(old_span->ss->name);
1025 if (ts != NULL && ts->has_addr)
1026 unmatch_addr_spans(old_span, new_span, ts);
1029 changed = true;
1030 if (unchangeable_section(new_span->ss))
1031 err(newsbfd, "warning: ignoring change to nonpatchable "
1032 "section %s\n", new_span->ss->name);
1035 static void compare_matched_spans(struct superbfd *newsbfd)
1037 asection *sect;
1038 for (sect = newsbfd->abfd->sections; sect != NULL; sect = sect->next) {
1039 struct supersect *ss = fetch_supersect(newsbfd, sect);
1040 struct span *span;
1041 for (span = ss->spans.data;
1042 span < ss->spans.data + ss->spans.size; span++) {
1043 if (span->match == NULL)
1044 continue;
1045 compare_spans(span->match, span);
1050 static void handle_section_symbol_renames(struct superbfd *oldsbfd,
1051 struct superbfd *newsbfd)
1053 asection *sect;
1054 struct span *span;
1055 for (sect = newsbfd->abfd->sections; sect != NULL; sect = sect->next) {
1056 struct supersect *ss = fetch_supersect(newsbfd, sect);
1057 for (span = ss->spans.data;
1058 span < ss->spans.data + ss->spans.size; span++) {
1059 if (span->match == NULL)
1060 continue;
1061 if (strcmp(span->label, span->match->label) == 0)
1062 continue;
1063 if (strcmp(span->orig_label, span->label) != 0 &&
1064 strcmp(span->label, span->match->label) != 0)
1065 DIE;
1066 if (span->symbol != NULL)
1067 label_map_set(newsbfd, span->label,
1068 span->match->label);
1069 span->label = span->match->label;
1074 static void copy_patched_entry_points(struct superbfd *oldsbfd,
1075 struct superbfd *newsbfd)
1077 asection *sect;
1078 struct span *span;
1079 for (sect = newsbfd->abfd->sections; sect != NULL; sect = sect->next) {
1080 struct supersect *ss = fetch_supersect(newsbfd, sect);
1081 for (span = ss->spans.data;
1082 span < ss->spans.data + ss->spans.size; span++) {
1083 if (!span->patch)
1084 continue;
1085 assert(span->match != NULL);
1086 vec_init(&span->pre_entry_points);
1088 struct entry_point *entry;
1089 for (entry = span->match->entry_points.data;
1090 entry < span->match->entry_points.data +
1091 span->match->entry_points.size;
1092 entry++) {
1093 struct entry_point *e =
1094 vec_grow(&span->pre_entry_points, 1);
1095 e->name = entry->name != NULL ?
1096 strdup(entry->name) : NULL;
1097 e->label = strdup(entry->label);
1098 e->offset = entry->offset;
1099 e->symbol = NULL;
1105 static int compare_entry_points(const void *va, const void *vb)
1107 const struct entry_point *a = va, *b = vb;
1108 if (a->offset < b->offset)
1109 return -1;
1110 else if (a->offset > b->offset)
1111 return 1;
1112 else
1113 return 0;
1116 static void compute_entry_points(struct superbfd *sbfd)
1118 asymbol **symp;
1119 for (symp = sbfd->syms.data; symp < sbfd->syms.data + sbfd->syms.size;
1120 symp++) {
1121 asymbol *sym = *symp;
1122 if (bfd_is_const_section(sym->section))
1123 continue;
1124 struct supersect *old_ss = fetch_supersect(sbfd, sym->section);
1125 if ((sym->flags & BSF_GLOBAL) == 0)
1126 continue;
1127 struct span *span = find_span(old_ss, sym->value);
1128 struct entry_point *e = vec_grow(&span->entry_points, 1);
1129 e->label = sym->name;
1130 e->name = sym->name;
1131 e->offset = sym->value - span->start;
1132 e->symbol = sym;
1135 asection *sect;
1136 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
1137 struct supersect *ss = fetch_supersect(sbfd, sect);
1138 struct span *span;
1139 for (span = ss->spans.data;
1140 span < ss->spans.data + ss->spans.size; span++) {
1141 /* First make sure that 0 appears as an entry point */
1142 bool found_zero = false;
1143 struct entry_point *entry;
1144 for (entry = span->entry_points.data;
1145 entry < span->entry_points.data +
1146 span->entry_points.size;
1147 entry++) {
1148 if (entry->offset == 0)
1149 found_zero = true;
1151 if (!found_zero) {
1152 struct entry_point *e =
1153 vec_grow(&span->entry_points, 1);
1154 e->label = span->label;
1155 e->name = NULL;
1156 e->offset = 0;
1157 e->symbol = span->symbol;
1160 qsort(span->entry_points.data, span->entry_points.size,
1161 sizeof(*span->entry_points.data),
1162 compare_entry_points);
1167 static bool part_of_reloc(struct supersect *ss, unsigned long addr)
1169 arelent **relocp;
1170 for (relocp = ss->relocs.data;
1171 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
1172 arelent *reloc = *relocp;
1173 if (addr >= reloc->address &&
1174 addr < reloc->address + bfd_get_reloc_size(reloc->howto))
1175 return true;
1177 return false;
1180 static bool nonrelocs_equal(struct span *old_span, struct span *new_span)
1182 int i;
1183 struct supersect *old_ss = old_span->ss, *new_ss = new_span->ss;
1184 if (old_span->contents_size != new_span->contents_size)
1185 return false;
1186 const unsigned char *old = old_ss->contents.data + old_span->start;
1187 const unsigned char *new = new_ss->contents.data + new_span->start;
1188 for (i = 0; i < old_span->contents_size; i++) {
1189 if (old[i] != new[i] &&
1190 !(part_of_reloc(old_ss, i + old_span->start) &&
1191 part_of_reloc(new_ss, i + new_span->start)))
1192 return false;
1194 return true;
1197 bool relocs_equal(struct supersect *old_src_ss, struct supersect *new_src_ss,
1198 arelent *old_reloc, arelent *new_reloc)
1200 struct superbfd *oldsbfd = old_src_ss->parent;
1201 struct superbfd *newsbfd = new_src_ss->parent;
1202 struct span *old_addr_span = find_span(old_src_ss, old_reloc->address);
1203 struct span *new_addr_span = find_span(new_src_ss, new_reloc->address);
1205 if (old_reloc->address - old_addr_span->start !=
1206 new_reloc->address - new_addr_span->start) {
1207 debug1(newsbfd, "Section %s/%s has reloc address mismatch at "
1208 "%lx\n", old_src_ss->name, new_src_ss->name,
1209 (unsigned long)old_reloc->address);
1210 return false;
1213 if (old_reloc->howto != new_reloc->howto) {
1214 debug1(newsbfd, "Section %s/%s has howto type mismatch at "
1215 "%lx\n", old_src_ss->name, new_src_ss->name,
1216 (unsigned long)old_reloc->address);
1217 return false;
1220 if (non_dst_mask(old_src_ss, old_reloc) !=
1221 non_dst_mask(new_src_ss, new_reloc)) {
1222 debug1(newsbfd, "Section %s/%s has contents mismatch at %lx\n",
1223 old_src_ss->name, new_src_ss->name,
1224 (unsigned long)old_reloc->address);
1225 return false;
1228 asymbol *old_sym = *old_reloc->sym_ptr_ptr;
1229 asymbol *new_sym = *new_reloc->sym_ptr_ptr;
1230 asection *old_sect = old_sym->section;
1231 asection *new_sect = new_sym->section;
1233 bfd_vma old_offset = reloc_target_offset(old_src_ss, old_reloc);
1234 bfd_vma new_offset = reloc_target_offset(new_src_ss, new_reloc);
1236 if (bfd_is_und_section(old_sect) || bfd_is_und_section(new_sect)) {
1237 if (!bfd_is_und_section(new_sect) && old_offset != 0 &&
1238 fetch_supersect(newsbfd, new_sect)->type == SS_TYPE_TEXT)
1239 return false;
1241 if (!bfd_is_und_section(new_sect) && new_offset != 0 &&
1242 fetch_supersect(oldsbfd, old_sect)->type == SS_TYPE_TEXT)
1243 return false;
1245 return strcmp(old_sym->name, new_sym->name) == 0 &&
1246 old_offset == new_offset;
1249 if (bfd_is_abs_section(old_sect) && bfd_is_abs_section(new_sect)) {
1250 if (old_sym->value + old_offset == new_sym->value + new_offset)
1251 return true;
1252 debug1(newsbfd, "Differing relocations from %s/%s to ABS "
1253 "section: %lx/%lx\n", old_addr_span->label,
1254 new_addr_span->label,
1255 (unsigned long)(old_sym->value + old_offset),
1256 (unsigned long)(new_sym->value + new_offset));
1257 return false;
1260 if (bfd_is_const_section(old_sect) || bfd_is_const_section(new_sect))
1261 DIE;
1263 struct supersect *old_ss = fetch_supersect(oldsbfd, old_sect);
1264 struct supersect *new_ss = fetch_supersect(newsbfd, new_sect);
1265 struct span *old_span = reloc_target_span(old_src_ss, old_reloc);
1266 struct span *new_span = reloc_target_span(new_src_ss, new_reloc);
1268 if (old_span->match != new_span || new_span->match != old_span) {
1269 debug1(newsbfd, "Nonmatching relocs from %s to %s/%s\n",
1270 new_src_ss->name, old_span->label, new_span->label);
1271 return false;
1274 if (old_sym->value + old_offset - old_span->start !=
1275 new_sym->value + new_offset - new_span->start) {
1276 debug1(newsbfd, "Offsets to %s/%s differ between %s "
1277 "and %s: %lx+%lx/%lx+%lx\n", old_ss->name,
1278 new_ss->name, old_src_ss->name, new_src_ss->name,
1279 (unsigned long)old_sym->value, (unsigned long)old_offset,
1280 (unsigned long)new_sym->value,
1281 (unsigned long)new_offset);
1282 return false;
1285 if ((old_sym->value + old_offset - old_span->start != 0 ||
1286 new_sym->value + new_offset - new_span->start != 0) &&
1287 new_span->patch) {
1288 debug1(newsbfd, "Relocation from %s to nonzero offsets "
1289 "%lx+%lx/%lx+%lx in changed section %s\n",
1290 new_src_ss->name, (unsigned long)old_sym->value,
1291 (unsigned long)old_offset, (unsigned long)new_sym->value,
1292 (unsigned long)new_offset, new_sym->section->name);
1293 return false;
1295 return true;
1298 bool all_relocs_equal(struct span *old_span, struct span *new_span)
1300 struct supersect *old_ss = old_span->ss, *new_ss = new_span->ss;
1301 arelent **old_relocp, **new_relocp;
1303 for (old_relocp = old_ss->relocs.data;
1304 old_relocp < old_ss->relocs.data + old_ss->relocs.size;
1305 old_relocp++) {
1306 if (find_span(old_ss, (*old_relocp)->address) == old_span)
1307 break;
1310 for (new_relocp = new_ss->relocs.data;
1311 new_relocp < new_ss->relocs.data + new_ss->relocs.size;
1312 new_relocp++) {
1313 if (find_span(new_ss, (*new_relocp)->address) == new_span)
1314 break;
1317 for (; old_relocp < old_ss->relocs.data + old_ss->relocs.size &&
1318 find_span(old_ss, (*old_relocp)->address) == old_span &&
1319 new_relocp < new_ss->relocs.data + new_ss->relocs.size &&
1320 find_span(new_ss, (*new_relocp)->address) == new_span;
1321 old_relocp++, new_relocp++) {
1322 if (!relocs_equal(old_ss, new_ss, *old_relocp, *new_relocp))
1323 return false;
1326 if ((old_relocp < old_ss->relocs.data + old_ss->relocs.size &&
1327 find_span(old_ss, (*old_relocp)->address) == old_span) ||
1328 (new_relocp < new_ss->relocs.data + new_ss->relocs.size &&
1329 find_span(new_ss, (*new_relocp)->address) == new_span)) {
1330 debug1(new_ss->parent, "Different reloc count between %s and "
1331 "%s\n", old_span->label, new_span->label);
1332 return false;
1335 return true;
1338 bfd_vma non_dst_mask(struct supersect *ss, arelent *reloc)
1340 int bits = bfd_get_reloc_size(reloc->howto) * 8;
1341 void *address = ss->contents.data + reloc->address;
1342 bfd_vma x = bfd_get(bits, ss->parent->abfd, address);
1343 return x & ~reloc->howto->dst_mask;
1346 void rm_relocs(struct superbfd *isbfd)
1348 asection *p;
1349 for (p = isbfd->abfd->sections; p != NULL; p = p->next) {
1350 struct supersect *ss = fetch_supersect(isbfd, p);
1351 bool remove_relocs = ss->keep;
1353 if (mode("keep") && ss->type == SS_TYPE_SPECIAL)
1354 remove_relocs = false;
1356 if (ss->type == SS_TYPE_KSPLICE ||
1357 ss->type == SS_TYPE_KSPLICE_CALL)
1358 remove_relocs = false;
1359 if (mode("finalize") &&
1360 (strstarts(ss->name, ".ksplice_patches") ||
1361 strstarts(ss->name, ".ksplice_relocs")))
1362 remove_relocs = true;
1364 if (remove_relocs)
1365 rm_some_relocs(ss);
1369 void rm_some_relocs(struct supersect *ss)
1371 struct arelentp_vec orig_relocs;
1372 vec_move(&orig_relocs, &ss->relocs);
1374 arelent **relocp;
1375 for (relocp = orig_relocs.data;
1376 relocp < orig_relocs.data + orig_relocs.size; relocp++) {
1377 bool rm_reloc = false;
1378 asymbol *sym_ptr = *(*relocp)->sym_ptr_ptr;
1380 if (mode("rmsyms") && bfd_is_und_section(sym_ptr->section)) {
1381 asymbol **esymp;
1382 for (esymp = extract_syms.data;
1383 esymp < extract_syms.data + extract_syms.size;
1384 esymp++) {
1385 if (sym_ptr == *esymp) {
1386 rm_reloc = true;
1387 break;
1392 if (mode("keep"))
1393 rm_reloc = true;
1395 if (mode("keep-new-code")) {
1396 if (bfd_is_const_section(sym_ptr->section)) {
1397 rm_reloc = false;
1398 } else {
1399 bfd_vma offset = reloc_target_offset(ss, *relocp);
1400 struct span *target_span =
1401 reloc_target_span(ss, *relocp);
1402 if (target_span->new ||
1403 (target_span->ss->type == SS_TYPE_TEXT &&
1404 sym_ptr->value + offset !=
1405 target_span->start))
1406 rm_reloc = false;
1409 const struct table_section *ts =
1410 get_table_section(ss->name);
1411 if (ts != NULL && ts->has_addr &&
1412 ((*relocp)->address % ts->entry_size ==
1413 ts->addr_offset ||
1414 (*relocp)->address % ts->entry_size ==
1415 ts->other_offset))
1416 rm_reloc = false;
1419 if (mode("finalize") && bfd_is_und_section(sym_ptr->section))
1420 rm_reloc = true;
1422 if (strcmp(sym_ptr->name, "mcount") == 0 &&
1423 bfd_is_und_section(sym_ptr->section))
1424 rm_reloc = false;
1426 if (!find_span(ss, (*relocp)->address)->keep)
1427 rm_reloc = false;
1429 if (rm_reloc)
1430 write_ksplice_reloc(ss, *relocp);
1431 else
1432 *vec_grow(&ss->relocs, 1) = *relocp;
1436 struct supersect *make_section(struct superbfd *sbfd, const char *fmt, ...)
1438 va_list ap;
1439 va_start(ap, fmt);
1440 char *name = vstrprintf(fmt, ap);
1441 va_end(ap);
1443 asection *sect = bfd_get_section_by_name(sbfd->abfd, name);
1444 if (sect != NULL)
1445 return fetch_supersect(sbfd, sect);
1446 else
1447 return new_supersect(sbfd, name);
1450 arelent *create_reloc(struct supersect *ss, const void *addr, asymbol **symp,
1451 bfd_vma offset)
1453 bfd_reloc_code_real_type code;
1454 switch (bfd_arch_bits_per_address(ss->parent->abfd)) {
1455 case 32:
1456 code = BFD_RELOC_32;
1457 break;
1458 case 64:
1459 code = BFD_RELOC_64;
1460 break;
1461 default:
1462 DIE;
1465 arelent *reloc = malloc(sizeof(*reloc));
1466 reloc->sym_ptr_ptr = symp;
1467 reloc->address = addr_offset(ss, addr);
1468 reloc->howto = bfd_reloc_type_lookup(ss->parent->abfd, code);
1469 reloc->addend = offset;
1470 return reloc;
1473 void write_reloc(struct supersect *ss, const void *addr, asymbol **symp,
1474 bfd_vma offset)
1476 *vec_grow(&ss->new_relocs, 1) = create_reloc(ss, addr, symp, offset);
1479 void write_string(struct supersect *ss, const char **addr, const char *fmt, ...)
1481 va_list ap;
1482 struct supersect *str_ss = make_section(ss->parent, ".ksplice_str");
1483 char *str;
1484 va_start(ap, fmt);
1485 int len = vasprintf(&str, fmt, ap);
1486 assert(len >= 0);
1487 va_end(ap);
1489 unsigned long *str_offp = ulong_hash_lookup(&ksplice_string_offset, str,
1490 FALSE);
1491 if (str_offp == NULL) {
1492 char *buf = sect_grow(str_ss, len + 1, char);
1493 memcpy(buf, str, len + 1);
1494 str_offp = ulong_hash_lookup(&ksplice_string_offset, str, TRUE);
1495 *str_offp = addr_offset(str_ss, buf);
1498 write_reloc(ss, addr, &str_ss->symbol, *str_offp);
1501 void lookup_system_map(struct addr_vec *addrs, const char *name, long offset)
1503 struct addr_vec *map_addrs =
1504 addr_vec_hash_lookup(&system_map, name, FALSE);
1505 if (map_addrs == NULL)
1506 return;
1508 unsigned long *addr, *map_addr;
1509 for (map_addr = map_addrs->data;
1510 map_addr < map_addrs->data + map_addrs->size; map_addr++) {
1511 for (addr = addrs->data; addr < addrs->data + addrs->size;
1512 addr++) {
1513 if (*addr == *map_addr + offset)
1514 break;
1516 if (addr < addrs->data + addrs->size)
1517 continue;
1518 *vec_grow(addrs, 1) = *map_addr + offset;
1522 void compute_system_map_array(struct superbfd *sbfd, struct addr_vec *addrs,
1523 asymbol *sym)
1525 if (bfd_is_abs_section(sym->section)) {
1526 *vec_grow(addrs, 1) = sym->value;
1527 } else if (bfd_is_und_section(sym->section)) {
1528 lookup_system_map(addrs, sym->name, 0);
1529 } else if (!bfd_is_const_section(sym->section)) {
1530 asymbol **gsymp;
1531 for (gsymp = sbfd->syms.data;
1532 gsymp < sbfd->syms.data + sbfd->syms.size; gsymp++) {
1533 asymbol *gsym = *gsymp;
1534 if ((gsym->flags & BSF_DEBUGGING) == 0 &&
1535 gsym->section == sym->section)
1536 lookup_system_map(addrs, gsym->name,
1537 sym->value - gsym->value);
1542 void write_ksplice_system_map(struct superbfd *sbfd, asymbol *sym,
1543 const char *label)
1545 bool *done = bool_hash_lookup(&system_map_written, label, TRUE);
1546 if (*done)
1547 return;
1548 *done = true;
1550 struct addr_vec addrs;
1551 vec_init(&addrs);
1553 compute_system_map_array(sbfd, &addrs, sym);
1554 if (addrs.size != 0) {
1555 struct supersect *smap_ss =
1556 make_section(sbfd, ".ksplice_system_map");
1557 struct ksplice_system_map *smap =
1558 sect_grow(smap_ss, 1, struct ksplice_system_map);
1559 write_string(smap_ss, &smap->label, "%s", label);
1561 struct supersect *array_ss = make_section(sbfd,
1562 ".ksplice_array");
1563 void *buf = sect_grow(array_ss, addrs.size,
1564 typeof(*addrs.data));
1565 memcpy(buf, addrs.data, addrs.size * sizeof(*addrs.data));
1566 smap->nr_candidates = addrs.size;
1567 write_reloc(smap_ss, &smap->candidates, &array_ss->symbol,
1568 addr_offset(array_ss, buf));
1570 vec_free(&addrs);
1573 void write_ksplice_symbol_backend(struct supersect *ss,
1574 struct ksplice_symbol *const *addr,
1575 asymbol *sym, const char *label,
1576 const char *name)
1578 struct supersect *ksymbol_ss = make_section(ss->parent,
1579 ".ksplice_symbols");
1580 struct ksplice_symbol *ksymbol;
1581 unsigned long *ksymbol_offp;
1583 ksymbol_offp = ulong_hash_lookup(&ksplice_symbol_offset, label, FALSE);
1584 if (ksymbol_offp != NULL) {
1585 write_reloc(ss, addr, &ksymbol_ss->symbol, *ksymbol_offp);
1586 return;
1588 ksymbol = sect_grow(ksymbol_ss, 1, struct ksplice_symbol);
1589 ksymbol_offp = ulong_hash_lookup(&ksplice_symbol_offset, label, TRUE);
1590 *ksymbol_offp = addr_offset(ksymbol_ss, ksymbol);
1592 write_reloc(ss, addr, &ksymbol_ss->symbol, *ksymbol_offp);
1593 write_string(ksymbol_ss, &ksymbol->label, "%s", label);
1594 if (name != NULL) {
1595 write_string(ksymbol_ss, &ksymbol->name, "%s", name);
1596 write_ksplice_system_map(ksymbol_ss->parent, sym, label);
1600 void write_ksplice_symbol(struct supersect *ss,
1601 struct ksplice_symbol *const *addr,
1602 asymbol *sym, struct span *span,
1603 const char *addstr_sect)
1605 const char *label, *name;
1606 if (span != NULL && span->start != 0)
1607 label = span->label;
1608 else
1609 label = label_lookup(ss->parent, sym);
1611 asymbol *gsym = canonical_symbol(ss->parent, sym);
1612 if (strcmp(addstr_sect, "") != 0)
1613 name = NULL;
1614 else if (bfd_is_und_section(sym->section))
1615 name = sym->name;
1616 else if (bfd_is_const_section(sym->section))
1617 name = NULL;
1618 else if (span != NULL && span->symbol == NULL)
1619 name = NULL;
1620 else if (gsym == NULL || (gsym->flags & BSF_SECTION_SYM) != 0)
1621 name = NULL;
1622 else
1623 name = gsym->name;
1625 write_ksplice_symbol_backend(ss, addr, sym,
1626 strprintf("%s%s", addstr_sect, label),
1627 name);
1630 void write_ksplice_reloc(struct supersect *ss, arelent *orig_reloc)
1632 asymbol *sym_ptr = *orig_reloc->sym_ptr_ptr;
1633 bfd_vma reloc_addend = reloc_offset(ss, orig_reloc);
1634 bfd_vma target_addend = reloc_target_offset(ss, orig_reloc);
1635 unsigned long *repladdr = ss->contents.data + orig_reloc->address;
1637 if (mode("finalize") && strstarts(ss->name, ".ksplice_patches")) {
1638 *repladdr = 0;
1639 return;
1641 if (mode("finalize") && strstarts(ss->name, ".ksplice_relocs")) {
1642 assert(strstarts(sym_ptr->name, KSPLICE_SYMBOL_STR));
1643 asymbol fake_sym;
1644 fake_sym.name = sym_ptr->name + strlen(KSPLICE_SYMBOL_STR);
1645 fake_sym.section = bfd_und_section_ptr;
1646 fake_sym.value = 0;
1647 fake_sym.flags = 0;
1649 write_ksplice_symbol_backend
1650 (ss, (struct ksplice_symbol **)repladdr, &fake_sym,
1651 fake_sym.name, fake_sym.name);
1652 return;
1655 struct span *span = reloc_target_span(ss, orig_reloc);
1656 if (span == ss->spans.data && span->start != target_addend)
1657 span = NULL;
1658 write_canary(ss, orig_reloc->address,
1659 bfd_get_reloc_size(orig_reloc->howto),
1660 orig_reloc->howto->dst_mask);
1662 struct supersect *kreloc_ss =
1663 make_section(ss->parent, ".ksplice_relocs%s", ss->name);
1664 struct ksplice_reloc *kreloc = sect_grow(kreloc_ss, 1,
1665 struct ksplice_reloc);
1667 struct span *address_span = find_span(ss, orig_reloc->address);
1668 write_reloc(kreloc_ss, &kreloc->blank_addr,
1669 &ss->symbol, orig_reloc->address + address_span->shift);
1670 if (bfd_is_und_section(sym_ptr->section) && mode("keep")) {
1671 char *name = strprintf(KSPLICE_SYMBOL_STR "%s", sym_ptr->name);
1672 asymbol **symp = make_undefined_symbolp(ss->parent, name);
1673 write_reloc(kreloc_ss, &kreloc->symbol, symp, 0);
1674 } else {
1675 write_ksplice_symbol(kreloc_ss, &kreloc->symbol, sym_ptr, span,
1676 "");
1678 if (span != NULL && span->start != 0) {
1679 reloc_addend += sym_ptr->value - span->start;
1680 target_addend += sym_ptr->value - span->start;
1682 kreloc->insn_addend = reloc_addend - target_addend;
1683 kreloc->target_addend = target_addend;
1684 write_ksplice_reloc_howto(kreloc_ss, &kreloc->howto, orig_reloc->howto,
1685 KSPLICE_HOWTO_RELOC);
1688 static void write_ksplice_reloc_howto(struct supersect *ss, const
1689 struct ksplice_reloc_howto *const *addr,
1690 reloc_howto_type *howto,
1691 enum ksplice_reloc_howto_type type)
1693 struct supersect *khowto_ss = make_section(ss->parent,
1694 ".ksplice_reloc_howtos");
1695 struct ksplice_reloc_howto *khowto;
1696 unsigned long *khowto_offp;
1698 khowto_offp = ulong_hash_lookup(&ksplice_howto_offset, howto->name,
1699 FALSE);
1700 if (khowto_offp != NULL) {
1701 write_reloc(ss, addr, &khowto_ss->symbol, *khowto_offp);
1702 return;
1704 khowto = sect_grow(khowto_ss, 1, struct ksplice_reloc_howto);
1705 khowto_offp = ulong_hash_lookup(&ksplice_howto_offset, howto->name,
1706 TRUE);
1707 *khowto_offp = addr_offset(khowto_ss, khowto);
1709 khowto->type = type;
1710 khowto->pcrel = howto->pc_relative;
1711 khowto->size = bfd_get_reloc_size(howto);
1712 khowto->dst_mask = howto->dst_mask;
1713 khowto->rightshift = howto->rightshift;
1714 khowto->signed_addend =
1715 (howto->complain_on_overflow == complain_overflow_signed) ||
1716 (howto->complain_on_overflow == complain_overflow_bitfield);
1717 write_reloc(ss, addr, &khowto_ss->symbol, *khowto_offp);
1720 #define CANARY(x, canary) ((x & ~howto->dst_mask) | (canary & howto->dst_mask))
1722 void write_canary(struct supersect *ss, int offset, bfd_size_type size,
1723 bfd_vma dst_mask)
1725 int bits = size * 8;
1726 void *address = ss->contents.data + offset;
1727 bfd_vma x = bfd_get(bits, ss->parent->abfd, address);
1728 x = (x & ~dst_mask) | ((bfd_vma)KSPLICE_CANARY & dst_mask);
1729 bfd_put(bits, ss->parent->abfd, x, address);
1732 static void write_date_relocs(struct superbfd *sbfd, const char *str,
1733 enum ksplice_reloc_howto_type type)
1735 asection *sect;
1736 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
1737 struct supersect *ss = fetch_supersect(sbfd, sect);
1738 if (ss->type != SS_TYPE_STRING && ss->type != SS_TYPE_RODATA)
1739 continue;
1740 void *ptr;
1741 struct span *span;
1742 for (span = ss->spans.data;
1743 span < ss->spans.data + ss->spans.size; span++) {
1744 if (!span->keep)
1745 continue;
1746 for (ptr = ss->contents.data + span->start;
1747 ptr + strlen(str) < ss->contents.data +
1748 span->start + span->contents_size; ptr++) {
1749 if (strcmp((const char *)ptr, str) == 0)
1750 write_ksplice_date_reloc
1751 (ss, addr_offset(ss, ptr), str,
1752 type);
1758 static void write_ksplice_date_reloc(struct supersect *ss, unsigned long offset,
1759 const char *str,
1760 enum ksplice_reloc_howto_type type)
1762 struct supersect *kreloc_ss;
1763 kreloc_ss = make_section(ss->parent, ".ksplice_relocs%s", ss->name);
1764 struct ksplice_reloc *kreloc = sect_grow(kreloc_ss, 1,
1765 struct ksplice_reloc);
1767 const char *filename = ss->parent->abfd->filename;
1768 char *c = strstr(filename, ".KSPLICE");
1769 int flen = (c == NULL ? strlen(filename) : c - filename);
1771 write_ksplice_symbol_backend(kreloc_ss, &kreloc->symbol, NULL,
1772 strprintf("%s<%.*s>", str, flen, filename),
1773 NULL);
1775 struct span *span = find_span(ss, offset);
1776 write_reloc(kreloc_ss, &kreloc->blank_addr, &ss->symbol,
1777 offset + span->shift);
1778 write_ksplice_nonreloc_howto(kreloc_ss, &kreloc->howto, type,
1779 strlen(str));
1782 static void write_table_relocs(struct superbfd *sbfd, const char *sectname,
1783 enum ksplice_reloc_howto_type type)
1785 asection *sect = bfd_get_section_by_name(sbfd->abfd, sectname);
1786 if (sect == NULL)
1787 return;
1788 struct supersect *ss = fetch_supersect(sbfd, sect);
1790 const struct table_section *s = get_table_section(sectname);
1791 if (s == NULL)
1792 DIE;
1794 void *entry;
1795 for (entry = ss->contents.data;
1796 entry < ss->contents.data + ss->contents.size;
1797 entry += s->entry_size) {
1798 struct span *span = find_span(ss, addr_offset(ss, entry));
1799 assert(span != NULL);
1800 if (!span->keep)
1801 continue;
1803 arelent *reloc = find_reloc(ss, entry + s->addr_offset);
1804 assert(reloc != NULL);
1805 asymbol *sym = *reloc->sym_ptr_ptr;
1806 assert(!bfd_is_const_section(sym->section));
1807 struct supersect *sym_ss = fetch_supersect(sbfd, sym->section);
1808 unsigned long addr = sym->value +
1809 reloc_target_offset(ss, reloc);
1810 write_ksplice_table_reloc(sym_ss, addr, span->label, type);
1814 static void write_ksplice_table_reloc(struct supersect *ss,
1815 unsigned long address,
1816 const char *label,
1817 enum ksplice_reloc_howto_type type)
1819 struct supersect *kreloc_ss;
1820 kreloc_ss = make_section(ss->parent, ".ksplice_relocs%s", ss->name);
1821 struct ksplice_reloc *kreloc = sect_grow(kreloc_ss, 1,
1822 struct ksplice_reloc);
1823 struct span *span = find_span(ss, address);
1824 assert(span != NULL);
1826 write_ksplice_symbol_backend(kreloc_ss, &kreloc->symbol, NULL,
1827 label, NULL);
1828 write_reloc(kreloc_ss, &kreloc->blank_addr, &ss->symbol,
1829 address + span->shift);
1830 write_ksplice_nonreloc_howto(kreloc_ss, &kreloc->howto, type, 0);
1833 static void write_ksplice_nonreloc_howto(struct supersect *ss,
1834 const struct ksplice_reloc_howto
1835 *const *addr,
1836 enum ksplice_reloc_howto_type type,
1837 int size)
1839 struct supersect *khowto_ss =
1840 make_section(ss->parent, ".ksplice_reloc_howtos");
1841 struct ksplice_reloc_howto *khowto =
1842 sect_grow(khowto_ss, 1, struct ksplice_reloc_howto);
1844 khowto->type = type;
1845 khowto->size = size;
1846 khowto->pcrel = 0;
1847 khowto->dst_mask = 0;
1848 khowto->rightshift = 0;
1849 khowto->signed_addend = 0;
1850 write_reloc(ss, addr, &khowto_ss->symbol,
1851 addr_offset(khowto_ss, khowto));
1854 static void write_ksplice_symbol_reloc(struct supersect *ss,
1855 const char *sectname,
1856 unsigned long *addr, asymbol *sym,
1857 const char *label, const char *name)
1859 struct supersect *kreloc_ss;
1860 kreloc_ss = make_section(ss->parent, ".ksplice_relocs%s", sectname);
1861 struct ksplice_reloc *kreloc = sect_grow(kreloc_ss, 1,
1862 struct ksplice_reloc);
1864 write_ksplice_symbol_backend(kreloc_ss, &kreloc->symbol, sym, label,
1865 name);
1866 write_reloc(kreloc_ss, &kreloc->blank_addr, &ss->symbol,
1867 addr_offset(ss, addr));
1868 write_ksplice_nonreloc_howto(kreloc_ss, &kreloc->howto,
1869 KSPLICE_HOWTO_SYMBOL, 0);
1872 static void write_ksplice_section(struct span *span)
1874 struct supersect *ss = span->ss;
1875 const char *sectname = span->ss->name;
1876 const struct table_section *ts = get_table_section(ss->name);
1878 if (ts != NULL && ts->has_addr) {
1879 arelent *reloc = find_reloc(ss, ss->contents.data + span->start
1880 + ts->addr_offset);
1881 assert(reloc != NULL);
1882 asymbol *rsym = *reloc->sym_ptr_ptr;
1883 assert(!bfd_is_const_section(rsym->section));
1884 sectname = rsym->section->name;
1887 struct supersect *ksect_ss =
1888 make_section(ss->parent, ".ksplice_sections%s", sectname);
1889 struct ksplice_section *ksect = sect_grow(ksect_ss, 1,
1890 struct ksplice_section);
1891 asymbol *sym = span->symbol == NULL ? ss->symbol : span->symbol;
1893 write_ksplice_symbol(ksect_ss, &ksect->symbol, sym, span,
1894 mode("keep-new-code") ? "(post)" : "");
1895 ksect->size = span->size;
1896 ksect->flags = 0;
1898 if (ss->type == SS_TYPE_RODATA || ss->type == SS_TYPE_STRING ||
1899 ss->type == SS_TYPE_EXPORT || ss->type == SS_TYPE_BUGTABLE)
1900 ksect->flags |= KSPLICE_SECTION_RODATA;
1901 if (ss->type == SS_TYPE_DATA)
1902 ksect->flags |= KSPLICE_SECTION_DATA;
1903 if (ss->type == SS_TYPE_TEXT)
1904 ksect->flags |= KSPLICE_SECTION_TEXT;
1905 assert(ksect->flags != 0);
1907 if (ss->type == SS_TYPE_STRING)
1908 ksect->flags |= KSPLICE_SECTION_STRING;
1910 write_reloc(ksect_ss, &ksect->address, &ss->symbol,
1911 span->start + span->shift);
1913 if (mode("keep-old-code")) {
1914 /* Write ksplice_symbols for all the entry points */
1915 struct entry_point *entry;
1916 for (entry = span->entry_points.data;
1917 entry < span->entry_points.data + span->entry_points.size;
1918 entry++)
1919 write_ksplice_symbol_reloc
1920 (span->ss, sectname, span->ss->contents.data +
1921 span->start + span->shift + entry->offset,
1922 entry->symbol, entry->label, entry->name);
1926 static void write_ksplice_patch_reloc(struct supersect *ss,
1927 const char *sectname, unsigned long *addr,
1928 bfd_size_type size, const char *label,
1929 long addend)
1931 struct supersect *kreloc_ss;
1932 kreloc_ss = make_section(ss->parent, ".ksplice_relocs%s", sectname);
1933 struct ksplice_reloc *kreloc = sect_grow(kreloc_ss, 1,
1934 struct ksplice_reloc);
1936 write_canary(ss, addr_offset(ss, addr), size, -1);
1937 write_ksplice_symbol_backend(kreloc_ss, &kreloc->symbol, NULL,
1938 label, NULL);
1939 write_reloc(kreloc_ss, &kreloc->blank_addr, &ss->symbol,
1940 addr_offset(ss, addr));
1941 reloc_howto_type *howto =
1942 bfd_reloc_type_lookup(ss->parent->abfd,
1943 PASTE(BFD_RELOC_, LONG_BIT));
1944 write_ksplice_reloc_howto(kreloc_ss, &kreloc->howto, howto,
1945 KSPLICE_HOWTO_RELOC);
1946 kreloc->target_addend = addend;
1947 kreloc->insn_addend = 0;
1950 /* Assumes symbol is global, aka only one symbol of that name */
1951 static asymbol *name_to_symbol(struct superbfd *sbfd, const char *name)
1953 if (name == NULL)
1954 return NULL;
1956 asymbol **symp;
1957 for (symp = sbfd->syms.data;
1958 symp < sbfd->syms.data + sbfd->syms.size; symp++) {
1959 asymbol *sym = *symp;
1960 if (strcmp(name, sym->name) == 0 &&
1961 ((sym->flags & BSF_GLOBAL) != 0 ||
1962 bfd_is_und_section(sym->section)))
1963 return sym;
1965 return NULL;
1968 void write_ksplice_patches(struct superbfd *sbfd, struct span *span)
1970 if (span->datapatch) {
1971 write_ksplice_patch(sbfd, span, span->label, 0);
1972 return;
1975 assert(span->patch);
1977 long prev_offset = LONG_MIN;
1978 asymbol *prev_sym = NULL;
1979 const char *prev_label = NULL;
1980 struct entry_point *entry;
1981 for (entry = span->pre_entry_points.data;
1982 entry < span->pre_entry_points.data + span->pre_entry_points.size;
1983 entry++) {
1984 asymbol *sym = name_to_symbol(sbfd, entry->name);
1986 if (entry->offset != prev_offset) {
1987 debug1(sbfd, "entry point: %s(%s) %lx\n", entry->label,
1988 entry->name, entry->offset);
1990 if (prev_offset + MAX_TRAMPOLINE_SIZE > entry->offset) {
1991 err(sbfd,
1992 "Overlapping trampolines: %s %lx/%lx\n",
1993 span->label, prev_offset, entry->offset);
1994 DIE;
1997 long target_offset = 0;
1998 if (sym != NULL)
1999 target_offset = sym->value - span->start;
2000 write_ksplice_patch(sbfd, span, entry->label,
2001 target_offset);
2002 prev_offset = entry->offset;
2003 prev_sym = NULL;
2006 if (prev_sym == NULL) {
2007 prev_sym = sym;
2008 prev_label = entry->label;
2009 } else if (sym != NULL &&
2010 (prev_sym->section != sym->section ||
2011 prev_sym->value != sym->value)) {
2012 err(sbfd, "Splitting global symbols in the middle of a "
2013 "span: %s+%lx != %s+%lx!\n",
2014 prev_label, (unsigned long)prev_sym->value,
2015 entry->label, (unsigned long)sym->value);
2016 DIE;
2020 if (prev_offset + MAX_TRAMPOLINE_SIZE > span->size) {
2021 err(sbfd, "Trampoline ends outside span: %s %lx/%lx\n",
2022 span->label, prev_offset, (unsigned long)span->size);
2023 DIE;
2027 void write_ksplice_patch(struct superbfd *sbfd, struct span *span,
2028 const char *label, long offset)
2030 struct supersect *kpatch_ss =
2031 make_section(sbfd, ".ksplice_patches%s", span->ss->name);
2032 struct ksplice_patch *kpatch = sect_grow(kpatch_ss, 1,
2033 struct ksplice_patch);
2035 write_ksplice_patch_reloc(kpatch_ss, span->ss->name, &kpatch->oldaddr,
2036 sizeof(kpatch->oldaddr), label, 0);
2037 if (span->ss->type == SS_TYPE_TEXT) {
2038 kpatch->type = KSPLICE_PATCH_TEXT;
2039 write_patch_storage(kpatch_ss, kpatch, MAX_TRAMPOLINE_SIZE,
2040 NULL);
2041 } else {
2042 kpatch->type = KSPLICE_PATCH_DATA;
2043 kpatch->size = span->contents_size;
2044 struct supersect *data_ss =
2045 make_section(sbfd, ".ksplice_patch_data");
2046 write_reloc(kpatch_ss, &kpatch->contents, &span->ss->symbol,
2047 span->start + span->shift);
2048 char *saved = sect_do_grow(data_ss, 1, span->contents_size, 1);
2049 write_reloc(kpatch_ss, &kpatch->saved, &data_ss->symbol,
2050 addr_offset(data_ss, saved));
2052 write_reloc(kpatch_ss, &kpatch->repladdr, &span->ss->symbol,
2053 span->start + span->shift + offset);
2056 asymbol **make_undefined_symbolp(struct superbfd *sbfd, const char *name)
2058 asymbol **symp;
2059 for (symp = sbfd->syms.data; symp < sbfd->syms.data + sbfd->syms.size;
2060 symp++) {
2061 asymbol *sym = *symp;
2062 if (strcmp(name, sym->name) == 0 &&
2063 bfd_is_und_section(sym->section))
2064 return symp;
2066 asymbol ***sympp;
2067 for (sympp = sbfd->new_syms.data;
2068 sympp < sbfd->new_syms.data + sbfd->new_syms.size; sympp++) {
2069 asymbol **symp = *sympp;
2070 asymbol *sym = *symp;
2071 if (strcmp(name, sym->name) == 0 &&
2072 bfd_is_und_section(sym->section))
2073 return symp;
2076 symp = malloc(sizeof(*symp));
2077 *symp = bfd_make_empty_symbol(sbfd->abfd);
2078 asymbol *sym = *symp;
2079 sym->name = name;
2080 sym->section = bfd_und_section_ptr;
2081 sym->flags = 0;
2082 sym->value = 0;
2083 *vec_grow(&sbfd->new_syms, 1) = symp;
2084 return symp;
2087 void write_ksplice_deleted_patch(struct superbfd *sbfd, const char *name,
2088 const char *label, const char *sectname)
2090 struct supersect *kpatch_ss =
2091 make_section(sbfd, ".ksplice_patches%s", sectname);
2092 struct ksplice_patch *kpatch = sect_grow(kpatch_ss, 1,
2093 struct ksplice_patch);
2095 write_ksplice_patch_reloc(kpatch_ss, sectname, &kpatch->oldaddr,
2096 sizeof(kpatch->oldaddr), label, 0);
2097 kpatch->type = KSPLICE_PATCH_TEXT;
2098 asymbol **symp = make_undefined_symbolp(sbfd, strdup(name));
2099 write_reloc(kpatch_ss, &kpatch->repladdr, symp, 0);
2100 write_patch_storage(kpatch_ss, kpatch, MAX_TRAMPOLINE_SIZE, NULL);
2103 void write_ksplice_export(struct superbfd *sbfd, struct span *span, bool del)
2105 struct supersect *kpatch_ss = make_section(sbfd, ".ksplice_patches");
2106 struct ksplice_patch *kpatch = sect_grow(kpatch_ss, 1,
2107 struct ksplice_patch);
2108 struct supersect *data_ss;
2110 const struct table_section *ts = get_table_section(span->ss->name);
2111 assert(ts != NULL);
2112 const char **addr =
2113 span->ss->contents.data + span->start + ts->other_offset;
2114 const char *symname = read_string(span->ss, addr);
2116 char *oldname, *newname;
2117 if (del) {
2118 oldname = strprintf("%s:%s", span->ss->name, symname);
2119 newname = strprintf("DISABLED_%s_%s", symname, kid);
2120 } else {
2121 oldname = strprintf("%s:DISABLED_%s_%s", span->ss->name,
2122 symname, kid);
2123 newname = strprintf("%s", symname);
2124 write_string(span->ss, addr, "DISABLED_%s_%s", symname, kid);
2127 write_ksplice_patch_reloc(kpatch_ss, "", &kpatch->oldaddr,
2128 sizeof(kpatch->oldaddr), oldname,
2129 ts->other_offset);
2130 kpatch->type = KSPLICE_PATCH_EXPORT;
2131 const char **namep = write_patch_storage(kpatch_ss, kpatch,
2132 sizeof(newname), &data_ss);
2133 write_string(data_ss, namep, "%s", newname);
2136 void filter_table_sections(struct superbfd *isbfd)
2138 struct supersect *tables_ss =
2139 fetch_supersect(offsets_sbfd,
2140 bfd_get_section_by_name(offsets_sbfd->abfd,
2141 ".ksplice_table_sections"));
2142 const struct table_section *ts;
2143 for (ts = tables_ss->contents.data;
2144 (void *)ts < tables_ss->contents.data + tables_ss->contents.size;
2145 ts++) {
2146 struct table_section s = *ts;
2147 s.sect = read_string(tables_ss, &ts->sect);
2148 s.other_sect = read_string(tables_ss, &ts->other_sect);
2149 s.crc_sect = read_string(tables_ss, &ts->crc_sect);
2150 filter_table_section(isbfd, &s);
2154 void filter_table_section(struct superbfd *sbfd, const struct table_section *s)
2156 asection *isection = bfd_get_section_by_name(sbfd->abfd, s->sect);
2157 if (isection == NULL)
2158 return;
2159 struct supersect *ss = fetch_supersect(sbfd, isection);
2161 void *entry;
2162 for (entry = ss->contents.data;
2163 entry < ss->contents.data + ss->contents.size;
2164 entry += s->entry_size) {
2165 struct span *span = find_span(ss, addr_offset(ss, entry));
2166 assert(span != NULL);
2168 if (s->has_addr) {
2169 struct span *sym_span =
2170 span_offset_target_span(span, s->addr_offset);
2171 assert(sym_span != NULL);
2172 if (sym_span->keep)
2173 keep_span(span);
2176 if (s->other_sect != NULL) {
2177 struct span *sym_span =
2178 span_offset_target_span(span, s->other_offset);
2179 assert(sym_span != NULL);
2180 if (span->keep)
2181 keep_span(sym_span);
2184 if (s->crc_sect != NULL) {
2185 struct span *crc_span = get_crc_span(span, s);
2186 assert(crc_span != NULL);
2187 if (span->keep && mode("keep-new-code"))
2188 keep_span(crc_span);
2193 static void match_table_spans(struct span *old_span, struct span *new_span)
2195 const struct table_section *ts = get_table_section(old_span->ss->name);
2197 if (strcmp(old_span->ss->name, new_span->ss->name) != 0)
2198 return;
2199 if (ts == NULL || old_span->ss->type != SS_TYPE_SPECIAL ||
2200 new_span->ss->type != SS_TYPE_SPECIAL)
2201 return;
2202 if (old_span->match != NULL || new_span->match != NULL)
2203 return;
2205 if (ts->has_addr) {
2206 void *old_entry = old_span->ss->contents.data + old_span->start;
2207 void *new_entry = new_span->ss->contents.data + new_span->start;
2208 arelent *old_reloc =
2209 find_reloc(old_span->ss, old_entry + ts->addr_offset);
2210 arelent *new_reloc =
2211 find_reloc(new_span->ss, new_entry + ts->addr_offset);
2212 assert(old_reloc != NULL && new_reloc != NULL);
2213 struct span *old_sym_span =
2214 reloc_target_span(old_span->ss, old_reloc);
2215 struct span *new_sym_span =
2216 reloc_target_span(new_span->ss, new_reloc);
2217 assert(old_sym_span != NULL && new_sym_span != NULL);
2218 if (old_sym_span->match == new_sym_span &&
2219 new_sym_span->match == old_sym_span &&
2220 old_reloc->address - old_sym_span->start ==
2221 new_reloc->address - new_sym_span->start)
2222 match_spans(old_span, new_span);
2226 static struct span *get_crc_span(struct span *span,
2227 const struct table_section *ts)
2229 void *entry = span->ss->contents.data + span->start;
2230 asection *crc_sect = bfd_get_section_by_name(span->ss->parent->abfd,
2231 ts->crc_sect);
2232 if (crc_sect == NULL)
2233 return NULL;
2234 struct supersect *crc_ss = fetch_supersect(span->ss->parent, crc_sect);
2235 if (crc_ss == NULL)
2236 return NULL;
2237 struct span *crc_span = find_span(crc_ss, addr_offset(span->ss, entry) /
2238 ts->entry_size * ts->crc_size);
2239 return crc_span;
2242 void mark_precallable_spans(struct superbfd *sbfd)
2244 asection *sect;
2245 struct supersect *ss, *sym_ss;
2246 struct span *address_span, *target_span;
2247 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2248 ss = fetch_supersect(sbfd, sect);
2249 arelent **relocp;
2250 if (ss->type == SS_TYPE_SPECIAL)
2251 continue;
2252 for (relocp = ss->relocs.data;
2253 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
2254 asymbol *sym = *(*relocp)->sym_ptr_ptr;
2255 address_span = find_span(ss, (*relocp)->address);
2256 if (!address_span->precallable)
2257 continue;
2258 target_span = reloc_target_span(ss, *relocp);
2259 if (target_span == NULL || target_span->keep)
2260 continue;
2261 sym_ss = fetch_supersect(sbfd, sym->section);
2262 if (sym_ss->type == SS_TYPE_IGNORED)
2263 continue;
2264 target_span->precallable = true;
2265 changed = true;
2270 void keep_referenced_sections(struct superbfd *sbfd)
2272 asection *sect;
2273 struct supersect *ss, *sym_ss;
2274 struct span *address_span, *target_span;
2275 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2276 ss = fetch_supersect(sbfd, sect);
2277 arelent **relocp;
2278 if (ss->type == SS_TYPE_SPECIAL)
2279 continue;
2280 for (relocp = ss->relocs.data;
2281 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
2282 asymbol *sym = *(*relocp)->sym_ptr_ptr;
2283 address_span = find_span(ss, (*relocp)->address);
2284 if (!address_span->keep)
2285 continue;
2286 target_span = reloc_target_span(ss, *relocp);
2287 if (target_span == NULL || target_span->keep)
2288 continue;
2289 sym_ss = fetch_supersect(sbfd, sym->section);
2290 if (sym_ss->type == SS_TYPE_IGNORED)
2291 continue;
2292 keep_span(target_span);
2293 changed = true;
2298 void copy_symbols(struct asymbolp_vec *osyms, struct asymbolpp_vec *isyms)
2300 asymbol ***sympp;
2301 for (sympp = isyms->data; sympp < isyms->data + isyms->size; sympp++)
2302 *vec_grow(osyms, 1) = **sympp;
2305 /* Modified function from GNU Binutils objcopy.c */
2306 bfd_boolean copy_object(bfd *ibfd, bfd *obfd)
2308 assert(bfd_set_format(obfd, bfd_get_format(ibfd)));
2310 bfd_vma start = bfd_get_start_address(ibfd);
2312 flagword flags = bfd_get_file_flags(ibfd);
2313 flags &= bfd_applicable_file_flags(obfd);
2315 assert(bfd_set_start_address(obfd, start)
2316 && bfd_set_file_flags(obfd, flags));
2318 enum bfd_architecture iarch = bfd_get_arch(ibfd);
2319 unsigned int imach = bfd_get_mach(ibfd);
2320 assert(bfd_set_arch_mach(obfd, iarch, imach));
2321 assert(bfd_set_format(obfd, bfd_get_format(ibfd)));
2323 /* BFD mandates that all output sections be created and sizes set before
2324 any output is done. Thus, we traverse all sections multiple times. */
2325 bfd_map_over_sections(ibfd, setup_section, obfd);
2327 struct supersect *new_supersects = fetch_superbfd(ibfd)->new_supersects;
2328 struct supersect *ss;
2329 for (ss = new_supersects; ss != NULL; ss = ss->next)
2330 setup_new_section(obfd, ss);
2332 /* Mark symbols used in output relocations so that they
2333 are kept, even if they are local labels or static symbols.
2335 Note we iterate over the input sections examining their
2336 relocations since the relocations for the output sections
2337 haven't been set yet. mark_symbols_used_in_relocations will
2338 ignore input sections which have no corresponding output
2339 section. */
2341 bfd_map_over_sections(ibfd, mark_symbols_used_in_relocations, NULL);
2342 for (ss = new_supersects; ss != NULL; ss = ss->next)
2343 ss_mark_symbols_used_in_relocations(ss);
2344 struct asymbolp_vec osyms;
2345 vec_init(&osyms);
2346 filter_symbols(ibfd, obfd, &osyms, &fetch_superbfd(ibfd)->syms);
2347 copy_symbols(&osyms, &fetch_superbfd(ibfd)->new_syms);
2349 bfd_set_symtab(obfd, osyms.data, osyms.size);
2351 /* This has to happen after the symbol table has been set. */
2352 bfd_map_over_sections(obfd, write_section, NULL);
2354 /* Allow the BFD backend to copy any private data it understands
2355 from the input BFD to the output BFD. This is done last to
2356 permit the routine to look at the filtered symbol table, which is
2357 important for the ECOFF code at least. */
2358 assert(bfd_copy_private_bfd_data(ibfd, obfd));
2360 return TRUE;
2363 /* Modified function from GNU Binutils objcopy.c */
2364 void setup_section(bfd *ibfd, asection *isection, void *obfdarg)
2366 struct superbfd *isbfd = fetch_superbfd(ibfd);
2367 struct supersect *ss = fetch_supersect(isbfd, isection);
2368 bfd *obfd = obfdarg;
2369 bfd_vma vma;
2371 if (!ss->keep)
2372 return;
2374 asection *osection = bfd_make_section_anyway(obfd, ss->name);
2375 assert(osection != NULL);
2377 osection->userdata = ss;
2378 bfd_set_section_flags(obfd, osection, ss->flags);
2379 ss->symbol = osection->symbol;
2380 assert(bfd_set_section_size(obfd, osection, ss->contents.size));
2382 vma = bfd_section_vma(ibfd, isection);
2383 assert(bfd_set_section_vma(obfd, osection, vma));
2385 osection->lma = isection->lma;
2386 assert(bfd_set_section_alignment(obfd, osection, ss->alignment));
2387 osection->entsize = ss->entsize;
2388 osection->output_section = osection;
2389 osection->output_offset = 0;
2390 isection->output_section = osection;
2391 isection->output_offset = 0;
2392 return;
2395 void setup_new_section(bfd *obfd, struct supersect *ss)
2397 asection *osection = bfd_make_section_anyway(obfd, ss->name);
2398 assert(osection != NULL);
2399 bfd_set_section_flags(obfd, osection, ss->flags);
2401 osection->userdata = ss;
2402 ss->symbol = osection->symbol;
2403 assert(bfd_set_section_size(obfd, osection, ss->contents.size));
2404 assert(bfd_set_section_vma(obfd, osection, 0));
2406 osection->lma = 0;
2407 assert(bfd_set_section_alignment(obfd, osection, ss->alignment));
2408 osection->entsize = ss->entsize;
2409 osection->output_section = osection;
2410 osection->output_offset = 0;
2413 static int compare_reloc_addresses(const void *aptr, const void *bptr)
2415 const arelent *const *a = aptr, *const *b = bptr;
2416 return (*a)->address - (*b)->address;
2419 static void delete_obsolete_relocs(struct supersect *ss)
2421 if (ss->new_relocs.size == 0)
2422 return;
2424 qsort(ss->relocs.data, ss->relocs.size, sizeof(*ss->relocs.data),
2425 compare_reloc_addresses);
2426 qsort(ss->new_relocs.data, ss->new_relocs.size,
2427 sizeof(*ss->new_relocs.data), compare_reloc_addresses);
2429 struct arelentp_vec orig_relocs;
2430 vec_move(&orig_relocs, &ss->relocs);
2432 arelent **relocp, **new_relocp = ss->new_relocs.data;
2433 for (relocp = orig_relocs.data;
2434 relocp < orig_relocs.data + orig_relocs.size; relocp++) {
2435 while (new_relocp < ss->new_relocs.data + ss->new_relocs.size &&
2436 (*new_relocp)->address < (*relocp)->address)
2437 new_relocp++;
2438 arelent *reloc = *relocp, *new_reloc = *new_relocp;
2439 if (new_relocp == ss->new_relocs.data + ss->new_relocs.size ||
2440 reloc->address != new_reloc->address)
2441 *vec_grow(&ss->relocs, 1) = reloc;
2445 void write_section(bfd *obfd, asection *osection, void *arg)
2447 struct supersect *ss = osection->userdata;
2449 if ((ss->flags & SEC_GROUP) != 0 || ss->contents.size == 0)
2450 return;
2452 delete_obsolete_relocs(ss);
2454 arelent **relocp;
2455 char *error_message;
2456 for (relocp = ss->new_relocs.data;
2457 relocp < ss->new_relocs.data + ss->new_relocs.size; relocp++) {
2458 bfd_vma val;
2459 if (bfd_get_arch(obfd) == bfd_arch_arm)
2460 val = osection->use_rela_p ? 0 : (*relocp)->addend;
2461 else
2462 val = 0;
2463 bfd_put(bfd_get_reloc_size((*relocp)->howto) * 8, obfd, val,
2464 ss->contents.data + (*relocp)->address);
2465 if (bfd_install_relocation(obfd, *relocp, ss->contents.data,
2466 0, osection, &error_message) !=
2467 bfd_reloc_ok) {
2468 err(ss->parent, "ksplice: error installing reloc: %s",
2469 error_message);
2470 DIE;
2472 if (mode("finalize")) {
2473 /* Check that all our sections will be allocated */
2474 asymbol *sym = *((*relocp)->sym_ptr_ptr);
2475 if (!bfd_is_const_section(sym->section)) {
2476 struct supersect *sym_ss =
2477 fetch_supersect(ss->parent, sym->section);
2478 assert((sym_ss->flags & SEC_ALLOC) != 0);
2482 memcpy(vec_grow(&ss->relocs, ss->new_relocs.size), ss->new_relocs.data,
2483 ss->new_relocs.size * sizeof(*ss->new_relocs.data));
2485 bfd_set_reloc(obfd, osection,
2486 ss->relocs.size == 0 ? NULL : ss->relocs.data,
2487 ss->relocs.size);
2489 if (ss->flags & SEC_HAS_CONTENTS)
2490 assert(bfd_set_section_contents
2491 (obfd, osection, ss->contents.data, 0,
2492 ss->contents.size));
2495 /* Modified function from GNU Binutils objcopy.c
2497 * Mark all the symbols which will be used in output relocations with
2498 * the BSF_KEEP flag so that those symbols will not be stripped.
2500 * Ignore relocations which will not appear in the output file.
2502 void mark_symbols_used_in_relocations(bfd *abfd, asection *isection,
2503 void *ignored)
2505 struct superbfd *sbfd = fetch_superbfd(abfd);
2506 if (isection->output_section == NULL)
2507 return;
2509 struct supersect *ss = fetch_supersect(sbfd, isection);
2510 ss_mark_symbols_used_in_relocations(ss);
2513 void ss_mark_symbols_used_in_relocations(struct supersect *ss)
2515 /* Examine each symbol used in a relocation. If it's not one of the
2516 special bfd section symbols, then mark it with BSF_KEEP. */
2517 arelent **relocp;
2518 for (relocp = ss->relocs.data;
2519 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
2520 asymbol *sym = *(*relocp)->sym_ptr_ptr;
2521 if (!(bfd_is_const_section(sym->section) &&
2522 sym == sym->section->symbol))
2523 sym->flags |= BSF_KEEP;
2525 for (relocp = ss->new_relocs.data;
2526 relocp < ss->new_relocs.data + ss->new_relocs.size; relocp++) {
2527 asymbol *sym = *(*relocp)->sym_ptr_ptr;
2528 if (!(bfd_is_const_section(sym->section) &&
2529 sym == sym->section->symbol))
2530 sym->flags |= BSF_KEEP;
2534 static bool deleted_table_section_symbol(bfd *abfd, asymbol *sym)
2536 struct superbfd *sbfd = fetch_superbfd(abfd);
2537 if (bfd_is_const_section(sym->section))
2538 return false;
2539 struct supersect *ss = fetch_supersect(sbfd, sym->section);
2541 asymbol **symp;
2542 for (symp = ss->syms.data; symp < ss->syms.data + ss->syms.size; symp++) {
2543 if (sym == *symp)
2544 break;
2546 return symp >= ss->syms.data + ss->syms.size &&
2547 (sym->flags & BSF_SECTION_SYM) == 0;
2550 void filter_symbols(bfd *ibfd, bfd *obfd, struct asymbolp_vec *osyms,
2551 struct asymbolp_vec *isyms)
2553 asymbol **symp;
2554 struct superbfd *sbfd = fetch_superbfd(ibfd);
2555 for (symp = isyms->data; symp < isyms->data + isyms->size; symp++) {
2556 asymbol *sym = *symp;
2557 struct supersect *sym_ss = NULL;
2558 struct span *sym_span = NULL;
2559 if (!bfd_is_const_section(sym->section)) {
2560 sym_ss = fetch_supersect(sbfd, sym->section);
2561 sym_span = find_span(sym_ss, sym->value);
2564 if (mode("keep") && (sym->flags & BSF_GLOBAL) != 0 &&
2565 !(mode("keep-new-code") && sym_span != NULL &&
2566 sym_span->new))
2567 sym->flags = (sym->flags & ~BSF_GLOBAL) | BSF_LOCAL;
2569 if (mode("finalize") && (sym->flags & BSF_GLOBAL) != 0)
2570 sym->flags = (sym->flags & ~BSF_GLOBAL) | BSF_LOCAL;
2572 bool keep = bfd_is_const_section(sym->section) ||
2573 (sym_ss->keep && (sym->flags & BSF_SECTION_SYM) != 0) ||
2574 (sym_span != NULL && sym_span->keep);
2575 if (bfd_is_und_section(sym->section) &&
2576 (sym->flags & BSF_KEEP) == 0)
2577 keep = false;
2578 if (bfd_is_abs_section(sym->section) &&
2579 (sym->flags & BSF_KEEP) == 0 &&
2580 (sym->flags & BSF_FILE) == 0)
2581 keep = false;
2582 if (deleted_table_section_symbol(ibfd, sym))
2583 keep = false;
2585 if (mode("keep-old-code") && sym_ss != NULL &&
2586 sym_ss->type == SS_TYPE_EXPORT)
2587 keep = false;
2589 if (keep) {
2590 if (sym_ss != NULL && !sym_ss->keep) {
2591 err(sbfd, "Kept symbol %s in unkept section "
2592 "%s\n", sym->name, sym->section->name);
2593 DIE;
2595 *vec_grow(osyms, 1) = sym;
2600 static bool is_table_section(const char *name, bool consider_other,
2601 bool consider_crc)
2603 struct supersect *tables_ss =
2604 fetch_supersect(offsets_sbfd,
2605 bfd_get_section_by_name(offsets_sbfd->abfd,
2606 ".ksplice_table_sections"));
2607 const struct table_section *ts;
2608 for (ts = tables_ss->contents.data;
2609 (void *)ts < tables_ss->contents.data + tables_ss->contents.size;
2610 ts++) {
2611 if (strcmp(name, read_string(tables_ss, &ts->sect)) == 0)
2612 return true;
2613 const char *osect_name = read_string(tables_ss,
2614 &ts->other_sect);
2615 if (consider_other && osect_name != NULL &&
2616 strcmp(name, osect_name) == 0)
2617 return true;
2618 const char *crc_name = read_string(tables_ss, &ts->crc_sect);
2619 if (consider_crc && crc_name != NULL &&
2620 strcmp(name, crc_name) == 0)
2621 return true;
2623 return false;
2626 const struct table_section *get_table_section(const char *name)
2628 struct supersect *tables_ss =
2629 fetch_supersect(offsets_sbfd,
2630 bfd_get_section_by_name(offsets_sbfd->abfd,
2631 ".ksplice_table_sections"));
2632 const struct table_section *ts;
2633 for (ts = tables_ss->contents.data;
2634 (void *)ts < tables_ss->contents.data + tables_ss->contents.size;
2635 ts++) {
2636 if (strcmp(name, read_string(tables_ss, &ts->sect)) == 0) {
2637 if (ts->entry_contents_size != 0)
2638 assert(align(ts->entry_contents_size,
2639 ts->entry_align) ==
2640 ts->entry_size);
2641 struct table_section *ns = malloc(sizeof(*ns));
2642 *ns = *ts;
2643 ns->sect = read_string(tables_ss, &ts->sect);
2644 ns->crc_sect = read_string(tables_ss, &ts->crc_sect);
2645 ns->other_sect =
2646 read_string(tables_ss, &ts->other_sect);
2647 return ns;
2650 return NULL;
2653 enum supersect_type supersect_type(struct supersect *ss)
2655 if (mode("finalize") &&
2656 strcmp(finalize_target, "vmlinux") == 0 &&
2657 (strstarts(ss->name, ".ksplice_relocs.exit") ||
2658 strstarts(ss->name, ".ksplice_sections.exit") ||
2659 strstarts(ss->name, ".ksplice_patches.exit")))
2660 return SS_TYPE_EXIT;
2661 if (strstarts(ss->name, ".ksplice_call"))
2662 return SS_TYPE_KSPLICE_CALL;
2663 if (strstarts(ss->name, ".ksplice_extract"))
2664 return SS_TYPE_KSPLICE_EXTRACT;
2665 if (strstarts(ss->name, ".ksplice_options"))
2666 return SS_TYPE_SPECIAL;
2667 if (strstarts(ss->name, ".ksplice"))
2668 return SS_TYPE_KSPLICE;
2670 if (strstarts(ss->name, ".init"))
2671 return SS_TYPE_IGNORED;
2672 if (strstarts(ss->name, ".security_initcall.init"))
2673 return SS_TYPE_IGNORED;
2674 if (strstarts(ss->name, ".con_initcall.init"))
2675 return SS_TYPE_IGNORED;
2676 if (strstarts(ss->name, ".x86cpuvendor.init"))
2677 return SS_TYPE_IGNORED;
2678 if (strstarts(ss->name, ".early_param.init"))
2679 return SS_TYPE_IGNORED;
2680 if (strstarts(ss->name, ".taglist.init"))
2681 return SS_TYPE_IGNORED;
2682 if (strstarts(ss->name, ".arch.info.init"))
2683 return SS_TYPE_IGNORED;
2684 if (strstarts(ss->name, ".proc.info.init"))
2685 return SS_TYPE_IGNORED;
2686 /* .pci_fixup_* sections really should be treated as global rodata
2687 referenced only from quirks.c */
2688 if (strstarts(ss->name, ".pci_fixup_"))
2689 return SS_TYPE_IGNORED;
2690 /* .builtin_fw sections are similar to .pci_fixup */
2691 if (strstarts(ss->name, ".builtin_fw"))
2692 return SS_TYPE_IGNORED;
2693 /* same for .tracedata */
2694 if (strstarts(ss->name, ".tracedata"))
2695 return SS_TYPE_IGNORED;
2696 if (strstarts(ss->name, ".debug"))
2697 return SS_TYPE_IGNORED;
2698 /* .eh_frame should probably be discarded, not ignored */
2699 if (strstarts(ss->name, ".eh_frame"))
2700 return SS_TYPE_IGNORED;
2701 if (config->ignore_devinit && strstarts(ss->name, ".devinit"))
2702 return SS_TYPE_IGNORED;
2703 if (config->ignore_meminit && strstarts(ss->name, ".meminit"))
2704 return SS_TYPE_IGNORED;
2705 if (config->ignore_cpuinit && strstarts(ss->name, ".cpuinit"))
2706 return SS_TYPE_IGNORED;
2707 if (config->ignore_devinit && strstarts(ss->name, ".devexit"))
2708 return SS_TYPE_IGNORED;
2709 if (config->ignore_meminit && strstarts(ss->name, ".memexit"))
2710 return SS_TYPE_IGNORED;
2711 if (config->ignore_cpuinit && strstarts(ss->name, ".cpuexit"))
2712 return SS_TYPE_IGNORED;
2713 if (strstarts(ss->name, ".vgetcpu_mode") ||
2714 strstarts(ss->name, ".jiffies") ||
2715 strstarts(ss->name, ".wall_jiffies") ||
2716 strstarts(ss->name, ".vxtime") ||
2717 strstarts(ss->name, ".sys_tz") ||
2718 strstarts(ss->name, ".sysctl_vsyscall") ||
2719 strstarts(ss->name, ".xtime") ||
2720 strstarts(ss->name, ".xtime_lock") ||
2721 strstarts(ss->name, ".vsyscall"))
2722 return SS_TYPE_IGNORED;
2723 if (strstarts(ss->name, ".vdso"))
2724 return SS_TYPE_IGNORED;
2726 if (strstarts(ss->name, ".exit.text"))
2727 return SS_TYPE_TEXT;
2728 if (strstarts(ss->name, ".exit.data"))
2729 return SS_TYPE_DATA;
2731 if (strstarts(ss->name, ".text") ||
2732 strstarts(ss->name, ".kernel.text") ||
2733 strstarts(ss->name, ".devinit.text") ||
2734 strstarts(ss->name, ".meminit.text") ||
2735 strstarts(ss->name, ".cpuinit.text") ||
2736 strstarts(ss->name, ".devexit.text") ||
2737 strstarts(ss->name, ".memexit.text") ||
2738 strstarts(ss->name, ".cpuexit.text") ||
2739 strstarts(ss->name, ".ref.text") ||
2740 strstarts(ss->name, ".spinlock.text") ||
2741 strstarts(ss->name, ".kprobes.text") ||
2742 strstarts(ss->name, ".sched.text") ||
2743 strstarts(ss->name, ".entry.text") || /* OpenVZ */
2744 (mode("keep-old-code") && strstarts(ss->name, ".fixup")))
2745 return SS_TYPE_TEXT;
2747 int n = -1;
2748 if (sscanf(ss->name, ".rodata.str%*u.%*u%n", &n) >= 0 &&
2749 n == strlen(ss->name))
2750 return ss->entsize == 1 ? SS_TYPE_STRING : SS_TYPE_RODATA;
2752 if (strstarts(ss->name, ".rodata") ||
2753 strstarts(ss->name, ".kernel.rodata") ||
2754 strstarts(ss->name, ".devinit.rodata") ||
2755 strstarts(ss->name, ".meminit.rodata") ||
2756 strstarts(ss->name, ".cpuinit.rodata") ||
2757 strstarts(ss->name, ".devexit.rodata") ||
2758 strstarts(ss->name, ".memexit.rodata") ||
2759 strstarts(ss->name, ".cpuexit.rodata") ||
2760 strstarts(ss->name, ".ref.rodata") ||
2761 strstarts(ss->name, "__markers_strings") ||
2762 (mode("keep-old-code") && strstarts(ss->name, "__ex_table")))
2763 return SS_TYPE_RODATA;
2765 if (strstarts(ss->name, ".bss"))
2766 return SS_TYPE_DATA;
2768 /* Ignore .data.percpu sections */
2769 if (strstarts(ss->name, ".data.percpu") ||
2770 strstarts(ss->name, ".kernel.data.percpu") ||
2771 strstarts(ss->name, ".data..percpu"))
2772 return SS_TYPE_IGNORED;
2773 if (strstarts(ss->name, ".data") ||
2774 strstarts(ss->name, ".kernel.data") ||
2775 strstarts(ss->name, ".devinit.data") ||
2776 strstarts(ss->name, ".cpuinit.data") ||
2777 strstarts(ss->name, ".meminit.data") ||
2778 strstarts(ss->name, ".devexit.data") ||
2779 strstarts(ss->name, ".memexit.data") ||
2780 strstarts(ss->name, ".cpuexit.data") ||
2781 strstarts(ss->name, ".ref.data") ||
2782 strstarts(ss->name, "__markers"))
2783 return SS_TYPE_DATA;
2785 /* We replace all the ksymtab strings, so delete them */
2786 if (strcmp(ss->name, "__ksymtab_strings") == 0)
2787 return SS_TYPE_STRING;
2788 if (strstarts(ss->name, "__ksymtab"))
2789 return SS_TYPE_EXPORT;
2791 if (strstarts(ss->name, "__bug_table"))
2792 return SS_TYPE_BUGTABLE;
2794 if (is_table_section(ss->name, true, true))
2795 return SS_TYPE_SPECIAL;
2797 if (strstarts(ss->name, ".ARM."))
2798 return SS_TYPE_SPECIAL;
2800 if (strstarts(ss->name, ".note"))
2801 return SS_TYPE_IGNORED;
2802 if (strstarts(ss->name, ".comment"))
2803 return SS_TYPE_IGNORED;
2804 if (strstarts(ss->name, "__param"))
2805 return SS_TYPE_IGNORED;
2806 if (strstarts(ss->name, "__obsparm"))
2807 return SS_TYPE_IGNORED;
2808 if (strstarts(ss->name, ".exitcall.exit"))
2809 return SS_TYPE_IGNORED;
2810 if (strstarts(ss->name, ".modinfo"))
2811 return SS_TYPE_IGNORED;
2813 return SS_TYPE_UNKNOWN;
2816 void initialize_supersect_types(struct superbfd *sbfd)
2818 asection *sect;
2819 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2820 struct supersect *ss = fetch_supersect(sbfd, sect);
2821 ss->type = supersect_type(ss);
2822 ss->orig_type = ss->type;
2823 if (ss->type == SS_TYPE_UNKNOWN) {
2824 err(sbfd, "Unknown section type: %s\n", ss->name);
2825 DIE;
2830 static void init_label_map(struct superbfd *sbfd)
2832 struct label_map *map;
2834 vec_init(&sbfd->maps);
2835 init_csyms(sbfd);
2836 init_callers(sbfd);
2838 struct symbol_hash csyms;
2839 symbol_hash_init(&csyms);
2841 asymbol **symp;
2842 for (symp = sbfd->syms.data;
2843 symp < sbfd->syms.data + sbfd->syms.size; symp++) {
2844 asymbol *csym = canonical_symbol(sbfd, *symp);
2845 if (csym == NULL)
2846 continue;
2847 char *key = strprintf("%p", csym);
2848 asymbol **csymp = symbol_hash_lookup(&csyms, key, TRUE);
2849 free(key);
2850 if (*csymp != NULL)
2851 continue;
2852 *csymp = csym;
2854 map = vec_grow(&sbfd->maps, 1);
2855 map->csym = csym;
2856 map->count = 0;
2857 map->label = symbol_label(sbfd, csym);
2860 struct label_mapp_hash label_maps;
2861 label_mapp_hash_init(&label_maps);
2862 for (map = sbfd->maps.data;
2863 map < sbfd->maps.data + sbfd->maps.size; map++) {
2864 struct label_map **mapp =
2865 label_mapp_hash_lookup(&label_maps, map->label, TRUE);
2866 if (*mapp == NULL) {
2867 *mapp = map;
2868 continue;
2871 struct label_map *first_map = *mapp;
2872 if (first_map->count == 0)
2873 first_map->label = strprintf("%s~%d", map->label, 0);
2874 map->label = strprintf("%s~%d", map->label, ++first_map->count);
2877 label_mapp_hash_init(&sbfd->maps_hash);
2878 for (map = sbfd->maps.data;
2879 map < sbfd->maps.data + sbfd->maps.size; map++) {
2880 char *key = strprintf("%p", map->csym);
2881 struct label_map **mapp =
2882 label_mapp_hash_lookup(&sbfd->maps_hash, key, TRUE);
2883 free(key);
2884 *mapp = map;
2885 map->orig_label = map->label;
2889 static const char *label_lookup(struct superbfd *sbfd, asymbol *sym)
2891 asymbol *csym = canonical_symbol(sbfd, sym);
2892 char *key = strprintf("%p", csym);
2893 struct label_map **mapp =
2894 label_mapp_hash_lookup(&sbfd->maps_hash, key, FALSE);
2895 free(key);
2896 if (mapp == NULL)
2897 DIE;
2898 return (*mapp)->label;
2901 static void print_label_changes(struct superbfd *sbfd)
2903 asection *sect;
2904 struct span *span;
2905 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2906 struct supersect *ss = fetch_supersect(sbfd, sect);
2907 for (span = ss->spans.data;
2908 span < ss->spans.data + ss->spans.size; span++) {
2909 if (strcmp(span->label, span->orig_label) != 0)
2910 debug1(sbfd, "Label change: %s -> %s\n",
2911 span->label, span->orig_label);
2916 static void label_map_set(struct superbfd *sbfd, const char *oldlabel,
2917 const char *label)
2919 struct label_map *map;
2920 for (map = sbfd->maps.data;
2921 map < sbfd->maps.data + sbfd->maps.size; map++) {
2922 if (strcmp(map->orig_label, oldlabel) == 0) {
2923 if (strcmp(map->orig_label, map->label) != 0 &&
2924 strcmp(map->label, label) != 0)
2925 DIE;
2926 map->label = label;
2927 return;
2930 DIE;
2933 static void change_initial_label(struct span *span, const char *label)
2935 struct superbfd *sbfd = span->ss->parent;
2936 span->label = label;
2937 span->orig_label = label;
2938 if (span->symbol) {
2939 asymbol *csym = canonical_symbol(sbfd, span->symbol);
2940 char *key = strprintf("%p", csym);
2941 struct label_map **mapp =
2942 label_mapp_hash_lookup(&sbfd->maps_hash, key, FALSE);
2943 free(key);
2944 assert(mapp);
2945 (*mapp)->label = span->label;
2946 (*mapp)->orig_label = span->orig_label;
2947 span->symbol = NULL;
2951 static void init_callers(struct superbfd *sbfd)
2953 string_hash_init(&sbfd->callers);
2954 asection *sect;
2955 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2956 struct supersect *ss = fetch_supersect(sbfd, sect);
2957 arelent **relocp;
2958 for (relocp = ss->relocs.data;
2959 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
2960 asymbol *sym = *(*relocp)->sym_ptr_ptr;
2961 unsigned long val =
2962 sym->value + reloc_target_offset(ss, *relocp);
2963 char *key = strprintf("%s+%lx", sym->section->name,
2964 val);
2965 const char **ret = string_hash_lookup(&sbfd->callers,
2966 key, TRUE);
2967 free(key);
2968 asymbol *csym = canonical_symbol(sbfd, sect->symbol);
2969 if (*ret != NULL)
2970 *ret = "*multiple_callers*";
2971 else if (static_local_symbol(sbfd, csym))
2972 *ret = static_local_symbol(sbfd, csym);
2973 else
2974 *ret = sect->name;
2979 static const char *find_caller(struct supersect *ss, asymbol *sym)
2981 char *key = strprintf("%s+%lx", sym->section->name,
2982 (unsigned long)sym->value);
2983 const char **ret = string_hash_lookup(&ss->parent->callers, key, FALSE);
2984 free(key);
2986 if (ret == NULL)
2987 return "*no_caller*";
2988 return *ret;
2991 static void init_csyms(struct superbfd *sbfd)
2993 asymbolpp_hash_init(&sbfd->csyms);
2995 asymbol **symp;
2996 for (symp = sbfd->syms.data; symp < sbfd->syms.data + sbfd->syms.size;
2997 symp++) {
2998 asymbol *sym = *symp;
2999 if ((sym->flags & BSF_DEBUGGING) != 0)
3000 continue;
3001 char *key = strprintf("%s+%lx", sym->section->name,
3002 (unsigned long)sym->value);
3003 asymbol ***csympp = asymbolpp_hash_lookup(&sbfd->csyms, key,
3004 TRUE);
3005 free(key);
3006 if (*csympp == NULL) {
3007 *csympp = symp;
3008 continue;
3010 asymbol *csym = **csympp;
3011 if ((csym->flags & BSF_GLOBAL) != 0)
3012 continue;
3013 if ((sym->flags & BSF_GLOBAL) != 0)
3014 *csympp = symp;
3018 static asymbol **symbolp_scan(struct supersect *ss, bfd_vma value)
3020 char *key = strprintf("%s+%lx", ss->name, (unsigned long)value);
3021 asymbol ***csympp =
3022 asymbolpp_hash_lookup(&ss->parent->csyms, key, FALSE);
3023 free(key);
3024 if (csympp != NULL)
3025 return *csympp;
3027 /* For section symbols of sections containing no symbols, return the
3028 section symbol that relocations are generated against */
3029 if (value == 0)
3030 return &ss->symbol;
3031 return NULL;
3034 static asymbol **canonical_symbolp(struct superbfd *sbfd, asymbol *sym)
3036 if (bfd_is_const_section(sym->section)) {
3037 asymbol **csymp;
3038 for (csymp = sbfd->syms.data;
3039 csymp < sbfd->syms.data + sbfd->syms.size; csymp++) {
3040 if (sym == *csymp)
3041 return csymp;
3043 return NULL;
3045 return symbolp_scan(fetch_supersect(sbfd, sym->section), sym->value);
3048 static asymbol *canonical_symbol(struct superbfd *sbfd, asymbol *sym)
3050 if (bfd_is_const_section(sym->section))
3051 return sym;
3052 asymbol **symp = canonical_symbolp(sbfd, sym);
3053 return symp != NULL ? *symp : NULL;
3056 static char *static_local_symbol(struct superbfd *sbfd, asymbol *sym)
3058 struct supersect *ss = fetch_supersect(sbfd, sym->section);
3059 if ((sym->flags & BSF_LOCAL) == 0 || (sym->flags & BSF_OBJECT) == 0)
3060 return NULL;
3061 char *dot = strrchr(sym->name, '.');
3062 if (dot == NULL || dot[1 + strspn(dot + 1, "0123546789")] != '\0')
3063 return NULL;
3064 char *basename = strndup(sym->name, dot - sym->name);
3066 /* Handle C.123.12345 symbols */
3067 dot = strrchr(basename, '.');
3068 if (dot != NULL && dot[1 + strspn(dot + 1, "0123546789")] == '\0')
3069 basename = strndup(basename, dot - basename);
3070 const char *caller;
3071 if (strcmp(basename, "__func__") == 0 ||
3072 strcmp(basename, "__PRETTY_FUNCTION__") == 0)
3073 caller = (const char *)ss->contents.data + sym->value;
3074 else
3075 caller = find_caller(ss, sym);
3076 return strprintf("%s<%s>", basename, caller);
3079 static char *symbol_label(struct superbfd *sbfd, asymbol *sym)
3081 const char *filename = sbfd->abfd->filename;
3082 char *c = strstr(filename, ".KSPLICE");
3083 int flen = (c == NULL ? strlen(filename) : c - filename);
3085 char *label;
3086 if (bfd_is_und_section(sym->section) || (sym->flags & BSF_GLOBAL) != 0) {
3087 label = strdup(sym->name);
3088 } else if (bfd_is_const_section(sym->section)) {
3089 label = strprintf("%s<%.*s>", sym->name, flen, filename);
3090 } else {
3091 asymbol *gsym = canonical_symbol(sbfd, sym);
3093 if (gsym == NULL)
3094 label = strprintf("%s+%lx<%.*s>",
3095 sym->section->name,
3096 (unsigned long)sym->value,
3097 flen, filename);
3098 else if ((gsym->flags & BSF_GLOBAL) != 0)
3099 label = strdup(gsym->name);
3100 else if (static_local_symbol(sbfd, gsym))
3101 label = strprintf("%s+%lx<%.*s>",
3102 static_local_symbol(sbfd, gsym),
3103 (unsigned long)sym->value,
3104 flen, filename);
3105 else
3106 label = strprintf("%s<%.*s>",
3107 gsym->name, flen, filename);
3110 return label;
3113 static void keep_span(struct span *span)
3115 span->keep = true;
3116 span->ss->keep = true;
3119 static struct span *new_span(struct supersect *ss, bfd_vma start, bfd_vma size)
3121 struct span *span = vec_grow(&ss->spans, 1);
3122 span->size = size;
3123 span->contents_size = size;
3124 span->start = start;
3125 span->ss = ss;
3126 span->keep = true;
3127 span->new = false;
3128 span->patch = false;
3129 span->bugpatch = false;
3130 span->datapatch = false;
3131 span->precallable = strstarts(ss->name, ".ksplice_call_pre_apply") ||
3132 strstarts(ss->name, ".ksplice_call_check_apply") ||
3133 strstarts(ss->name, ".ksplice_call_fail_apply") ||
3134 strstarts(ss->name, ".ksplice_call_post_remove");
3135 span->match = NULL;
3136 vec_init(&span->entry_points);
3137 span->shift = 0;
3138 asymbol **symp = symbolp_scan(ss, span->start);
3139 if (symp != NULL) {
3140 span->symbol = *symp;
3141 span->label = label_lookup(ss->parent, span->symbol);
3142 } else {
3143 span->symbol = NULL;
3144 const char *label = label_lookup(ss->parent, ss->symbol);
3145 if (span->start != 0)
3146 span->label = strprintf("%s<span:%lx>", label,
3147 (unsigned long)span->start);
3148 else
3149 span->label = label;
3151 span->orig_label = span->label;
3152 return span;
3155 static void initialize_string_spans(struct supersect *ss)
3157 const char *str;
3158 for (str = ss->contents.data;
3159 (void *)str < ss->contents.data + ss->contents.size;) {
3160 bfd_vma start = (unsigned long)str -
3161 (unsigned long)ss->contents.data;
3162 bfd_vma size = strlen(str) + 1;
3163 bfd_vma contents_size = size;
3164 while ((start + size) % (1 << ss->alignment) != 0 &&
3165 start + size < ss->contents.size) {
3166 /* Some string sections, like __ksymtab_strings, only
3167 align some strings with the declared alignment */
3168 if (str[size] != '\0')
3169 break;
3170 size++;
3172 struct span *span = new_span(ss, start, size);
3173 span->contents_size = contents_size;
3174 str += size;
3178 static int compare_ulongs(const void *va, const void *vb)
3180 const unsigned long *a = va, *b = vb;
3181 return *a - *b;
3184 static void initialize_table_spans(struct superbfd *sbfd,
3185 struct table_section *s)
3187 asection *isection = bfd_get_section_by_name(sbfd->abfd, s->sect);
3188 if (isection == NULL)
3189 return;
3190 struct supersect *ss = fetch_supersect(sbfd, isection);
3191 if (ss->alignment < ffs(s->entry_align) - 1)
3192 ss->alignment = ffs(s->entry_align) - 1;
3194 asection *other_sect = NULL;
3195 if (s->other_sect != NULL)
3196 other_sect = bfd_get_section_by_name(sbfd->abfd, s->other_sect);
3197 struct supersect *other_ss = NULL;
3198 if (other_sect != NULL)
3199 other_ss = fetch_supersect(sbfd, other_sect);
3201 asection *crc_sect = NULL;
3202 if (s->crc_sect != NULL)
3203 crc_sect = bfd_get_section_by_name(sbfd->abfd, s->crc_sect);
3204 struct supersect *crc_ss = NULL;
3205 if (crc_sect != NULL)
3206 crc_ss = fetch_supersect(sbfd, crc_sect);
3208 struct ulong_vec offsets;
3209 vec_init(&offsets);
3211 void *entry;
3212 for (entry = ss->contents.data;
3213 entry < ss->contents.data + ss->contents.size;
3214 entry += s->entry_size) {
3215 struct span *span = new_span(ss, addr_offset(ss, entry),
3216 s->entry_size);
3217 if (s->entry_contents_size != 0)
3218 span->contents_size = s->entry_contents_size;
3219 if ((span->symbol == NULL ||
3220 (span->symbol->flags & BSF_SECTION_SYM) != 0) &&
3221 s->has_addr) {
3222 arelent *reloc = find_reloc(ss, entry + s->addr_offset);
3223 assert(reloc);
3224 struct span *target_span = reloc_target_span(ss, reloc);
3225 assert(target_span);
3226 asymbol *sym = *reloc->sym_ptr_ptr;
3227 unsigned long val = sym->value +
3228 reloc_target_offset(ss, reloc) -
3229 (target_span->start + target_span->shift);
3230 char *label = strprintf("%s<target:%s+%lx>", ss->name,
3231 target_span->label, val);
3232 change_initial_label(span, label);
3235 if (other_sect != NULL) {
3236 asymbol *sym;
3237 bfd_vma offset = read_reloc(ss, entry + s->other_offset,
3238 sizeof(void *), &sym);
3239 if (sym->section == other_sect) {
3240 assert(offset >= 0 &&
3241 offset < other_ss->contents.size);
3242 *vec_grow(&offsets, 1) = offset;
3246 if (crc_sect != NULL)
3247 new_span(crc_ss, addr_offset(ss, entry) / s->entry_size
3248 * s->crc_size, s->crc_size);
3250 if (ss->type == SS_TYPE_EXPORT) {
3251 const char *symname = read_string(ss, entry +
3252 s->other_offset);
3253 char *label = strprintf("%s:%s", ss->name, symname);
3254 change_initial_label(span, label);
3258 if (other_sect == NULL)
3259 return;
3261 *vec_grow(&offsets, 1) = 0;
3262 qsort(offsets.data, offsets.size, sizeof(*offsets.data),
3263 compare_ulongs);
3264 *vec_grow(&offsets, 1) = other_ss->contents.size;
3266 unsigned long *off;
3267 for (off = offsets.data; off < offsets.data + offsets.size - 1; off++) {
3268 if (*off != *(off + 1))
3269 new_span(other_ss, *off, *(off + 1) - *off);
3273 static void initialize_table_section_spans(struct superbfd *sbfd)
3275 struct supersect *tables_ss =
3276 fetch_supersect(offsets_sbfd,
3277 bfd_get_section_by_name(offsets_sbfd->abfd,
3278 ".ksplice_table_sections"));
3279 const struct table_section *ts;
3280 struct table_section s;
3281 for (ts = tables_ss->contents.data;
3282 (void *)ts < tables_ss->contents.data + tables_ss->contents.size;
3283 ts++) {
3284 s = *ts;
3285 s.sect = read_string(tables_ss, &ts->sect);
3286 s.other_sect = read_string(tables_ss, &ts->other_sect);
3287 s.crc_sect = read_string(tables_ss, &ts->crc_sect);
3288 initialize_table_spans(sbfd, &s);
3292 static void initialize_ksplice_call_spans(struct supersect *ss)
3294 arelent **relocp;
3295 for (relocp = ss->relocs.data;
3296 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
3297 arelent *reloc = *relocp;
3298 new_span(ss, reloc->address, bfd_get_reloc_size(reloc->howto));
3299 /* the span labels should already be unique */
3303 static void initialize_spans(struct superbfd *sbfd)
3305 asection *sect;
3306 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
3307 if (is_table_section(sect->name, true, true) && mode("keep"))
3308 continue;
3310 struct supersect *ss = fetch_supersect(sbfd, sect);
3311 if (ss->type == SS_TYPE_STRING)
3312 initialize_string_spans(ss);
3313 else if (ss->type == SS_TYPE_KSPLICE_CALL)
3314 initialize_ksplice_call_spans(ss);
3315 else
3316 new_span(ss, 0, ss->contents.size);
3318 if (mode("keep"))
3319 initialize_table_section_spans(sbfd);
3322 /* Returns the span pointed to by the relocation at span->start + offset */
3323 static struct span *span_offset_target_span(struct span *span, int offset)
3325 void *entry = span->ss->contents.data + span->start;
3326 arelent *reloc = find_reloc(span->ss, entry + offset);
3327 if (reloc == NULL)
3328 return NULL;
3329 return reloc_target_span(span->ss, reloc);
3332 struct span *reloc_target_span(struct supersect *ss, arelent *reloc)
3334 asymbol *sym_ptr = *reloc->sym_ptr_ptr;
3335 if (bfd_is_const_section(sym_ptr->section))
3336 return NULL;
3338 bfd_vma addend = sym_ptr->value + reloc_target_offset(ss, reloc);
3339 struct supersect *sym_ss =
3340 fetch_supersect(ss->parent, sym_ptr->section);
3341 struct span *span, *target_span = sym_ss->spans.data;
3342 for (span = sym_ss->spans.data;
3343 span < sym_ss->spans.data + sym_ss->spans.size; span++) {
3344 if (addend >= span->start && addend < span->start + span->size)
3345 target_span = span;
3347 return target_span;
3350 static bfd_vma reloc_target_offset(struct supersect *ss, arelent *reloc)
3352 bfd_vma offset = reloc_offset(ss, reloc);
3353 if (reloc->howto->pc_relative) {
3354 if ((ss->flags & SEC_CODE) != 0)
3355 return offset + bfd_get_reloc_size(reloc->howto);
3357 const struct table_section *ts = get_table_section(ss->name);
3358 if (ts != NULL && ts->relative_addr &&
3359 reloc->address % ts->entry_size == ts->addr_offset)
3360 return offset - ts->addr_offset;
3361 if (ts != NULL && ts->relative_other &&
3362 reloc->address % ts->entry_size == ts->other_offset)
3363 return offset - ts->other_offset;
3365 DIE;
3367 return offset;
3370 struct span *find_span(struct supersect *ss, bfd_size_type address)
3372 struct span *span;
3373 for (span = ss->spans.data; span < ss->spans.data + ss->spans.size;
3374 span++) {
3375 if (address >= span->start &&
3376 address < span->start + span->size)
3377 return span;
3379 /* Deal with empty BSS sections */
3380 if (ss->contents.size == 0 && ss->spans.size > 0)
3381 return ss->spans.data;
3382 /* Deal with section end pointers */
3383 if (address == ss->contents.size && ss->spans.size == 1)
3384 return ss->spans.data;
3385 return NULL;
3388 void compute_span_shifts(struct superbfd *sbfd)
3390 asection *sect;
3391 struct span *span;
3392 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
3393 struct supersect *ss = fetch_supersect(sbfd, sect);
3394 if (!ss->keep)
3395 continue;
3396 bfd_size_type offset = 0;
3397 for (span = ss->spans.data;
3398 span < ss->spans.data + ss->spans.size; span++) {
3399 if (!span->keep)
3400 continue;
3401 span->shift = offset - span->start;
3402 offset += span->size;
3407 void remove_unkept_spans(struct superbfd *sbfd)
3409 asection *sect;
3410 struct span *span;
3411 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
3412 struct supersect *ss = fetch_supersect(sbfd, sect);
3413 delete_obsolete_relocs(ss);
3414 struct arelentp_vec orig_relocs;
3415 vec_move(&orig_relocs, &ss->relocs);
3416 arelent **relocp, *reloc;
3417 for (relocp = orig_relocs.data;
3418 relocp < orig_relocs.data + orig_relocs.size; relocp++) {
3419 reloc = *relocp;
3420 asymbol *sym = *reloc->sym_ptr_ptr;
3421 span = reloc_target_span(ss, reloc);
3422 if ((span != NULL && span->keep && span->shift == 0) ||
3423 bfd_is_const_section(sym->section)) {
3424 *vec_grow(&ss->relocs, 1) = reloc;
3425 continue;
3427 struct supersect *sym_ss =
3428 fetch_supersect(sbfd, sym->section);
3429 if (span != NULL && (sym->flags & BSF_SECTION_SYM) == 0
3430 && find_span(sym_ss, sym->value) != span) {
3431 err(sbfd, "Spans for symbol %s and relocation "
3432 "target do not match in sect %s\n",
3433 sym->name, sym_ss->name);
3434 DIE;
3436 if (span != NULL && span->keep) {
3437 arelent *new_reloc = malloc(sizeof(*new_reloc));
3438 *new_reloc = *reloc;
3439 new_reloc->addend = reloc_offset(ss, reloc);
3440 new_reloc->addend += span->shift;
3441 *vec_grow(&ss->new_relocs, 1) = new_reloc;
3446 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
3447 struct supersect *ss = fetch_supersect(sbfd, sect), orig_ss;
3448 if (!ss->keep)
3449 continue;
3450 supersect_move(&orig_ss, ss);
3451 vec_init(&ss->spans);
3452 for (span = orig_ss.spans.data;
3453 span < orig_ss.spans.data + orig_ss.spans.size; span++) {
3454 if (!span->keep)
3455 continue;
3456 struct span *new_span = vec_grow(&ss->spans, 1);
3457 *new_span = *span;
3458 new_span->start = span->start + span->shift;
3459 new_span->shift = 0;
3460 sect_copy(ss, sect_do_grow(ss, 1, span->size, 1),
3461 &orig_ss, orig_ss.contents.data + span->start,
3462 span->size);
3467 static void init_objmanip_superbfd(struct superbfd *sbfd)
3469 init_label_map(sbfd);
3470 initialize_supersect_types(sbfd);
3471 initialize_spans(sbfd);
3472 load_options(sbfd);
3473 compute_entry_points(sbfd);
3476 void mangle_section_name(struct superbfd *sbfd, const char *name)
3478 asection *sect = bfd_get_section_by_name(sbfd->abfd, name);
3479 if (sect == NULL)
3480 return;
3481 struct supersect *ss = fetch_supersect(sbfd, sect);
3482 ss->name = strprintf(".ksplice_pre.%s", ss->name);
3485 static void write_bugline_patches(struct superbfd *sbfd)
3487 const struct table_section *ts = get_table_section("__bug_table");
3488 asection *sect = bfd_get_section_by_name(sbfd->abfd, "__bug_table");
3489 if (sect == NULL)
3490 return;
3491 struct supersect *ss = fetch_supersect(sbfd, sect);
3492 assert(ts != NULL);
3494 void *entry;
3495 for (entry = ss->contents.data;
3496 entry < ss->contents.data + ss->contents.size;
3497 entry += ts->entry_size) {
3498 struct span *span = find_span(ss, addr_offset(ss, entry));
3499 assert(span != NULL);
3500 if (!span->bugpatch)
3501 continue;
3502 arelent *reloc = find_reloc(ss, entry + ts->addr_offset);
3503 assert(reloc != NULL);
3504 asymbol *sym = *reloc->sym_ptr_ptr;
3505 assert(!bfd_is_const_section(sym->section));
3506 struct supersect *kpatch_ss =
3507 make_section(sbfd, ".ksplice_patches%s",
3508 sym->section->name);
3510 bfd_vma offset, start = 0;
3511 for (offset = 0; offset <= span->size; offset++) {
3512 if (offset != span->size &&
3513 !part_of_reloc(ss, span->start + offset))
3514 continue;
3515 if (start == offset) {
3516 start++;
3517 continue;
3519 /* an interval of non-relocations just passed */
3520 struct ksplice_patch *kpatch =
3521 sect_grow(kpatch_ss, 1, struct ksplice_patch);
3522 write_ksplice_patch_reloc
3523 (kpatch_ss, sym->section->name, &kpatch->oldaddr,
3524 sizeof(kpatch->oldaddr), span->label, start);
3526 char *data = write_patch_storage(kpatch_ss, kpatch,
3527 offset - start, NULL);
3528 memcpy(data, entry + start, offset - start);
3529 kpatch->type = KSPLICE_PATCH_DATA;
3530 start = offset + 1;
3535 void *write_patch_storage(struct supersect *ss, struct ksplice_patch *kpatch,
3536 size_t size, struct supersect **data_ssp)
3538 struct supersect *data_ss = make_section(ss->parent,
3539 ".ksplice_patch_data");
3540 char *saved = sect_do_grow(data_ss, 1, size, 1);
3541 write_reloc(ss, &kpatch->saved, &data_ss->symbol,
3542 addr_offset(data_ss, saved));
3543 char *data = sect_do_grow(data_ss, 1, size, 1);
3544 write_reloc(ss, &kpatch->contents, &data_ss->symbol,
3545 addr_offset(data_ss, data));
3546 kpatch->size = size;
3547 if (data_ssp != NULL)
3548 *data_ssp = data_ss;
3549 return data;