Remove patches for unmatched spans.
[ksplice.git] / objmanip.c
blob19a3895c5988abf1b03f9bee5576e82bc7d605fc
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 void unmatch_span(struct span *old_span)
706 struct span *new_span = old_span->match;
707 old_span->match = NULL;
708 new_span->match = NULL;
710 new_span->bugpatch = false;
712 if (old_span->ss->type == SS_TYPE_SPECIAL) {
713 const struct table_section *ts =
714 get_table_section(old_span->ss->name);
715 if (ts != NULL && ts->has_addr)
716 unmatch_addr_spans(old_span, new_span, ts);
719 new_span->patch = false;
720 new_span->bugpatch = false;
721 new_span->datapatch = false;
723 changed = true;
726 static void match_global_symbols(struct span *old_span, asymbol *oldsym,
727 struct span *new_span, asymbol *newsym)
729 if ((oldsym->flags & BSF_GLOBAL) == 0 ||
730 (newsym->flags & BSF_GLOBAL) == 0)
731 return;
732 match_spans(old_span, new_span);
735 static void check_global_symbols(struct span *old_span, asymbol *oldsym,
736 struct span *new_span, asymbol *newsym)
738 if ((oldsym->flags & BSF_GLOBAL) == 0 ||
739 (newsym->flags & BSF_GLOBAL) == 0)
740 return;
741 if (old_span->ss->type == SS_TYPE_IGNORED)
742 return;
743 if (old_span->match != new_span || new_span->match != old_span) {
744 err(new_span->ss->parent, "Global symbol span mismatch: %s "
745 "%s/%s\n", oldsym->name, old_span->label, new_span->label);
746 DIE;
750 static void foreach_symbol_pair(struct superbfd *oldsbfd, struct superbfd *newsbfd,
751 void (*fn)(struct span *old_span,
752 asymbol *oldsym,
753 struct span *new_span,
754 asymbol *newsym))
756 asymbol **oldsymp, **newsymp;
757 for (oldsymp = oldsbfd->syms.data;
758 oldsymp < oldsbfd->syms.data + oldsbfd->syms.size; oldsymp++) {
759 asymbol *oldsym = *oldsymp;
760 if (bfd_is_const_section(oldsym->section))
761 continue;
762 for (newsymp = newsbfd->syms.data;
763 newsymp < newsbfd->syms.data + newsbfd->syms.size;
764 newsymp++) {
765 asymbol *newsym = *newsymp;
766 if (bfd_is_const_section(newsym->section))
767 continue;
768 if (strcmp(oldsym->name, newsym->name) != 0)
769 continue;
771 struct supersect *old_ss =
772 fetch_supersect(oldsbfd, oldsym->section);
773 struct supersect *new_ss =
774 fetch_supersect(newsbfd, newsym->section);
775 if ((old_ss->type != new_ss->type &&
776 old_ss->type != new_ss->orig_type) ||
777 old_ss->type == SS_TYPE_SPECIAL ||
778 old_ss->type == SS_TYPE_EXPORT)
779 continue;
781 struct span *old_span =
782 find_span(old_ss, oldsym->value);
783 struct span *new_span =
784 find_span(new_ss, newsym->value);
785 if (old_span == NULL) {
786 err(oldsbfd, "Could not find span for %s\n",
787 oldsym->name);
788 DIE;
790 if (new_span == NULL) {
791 err(newsbfd, "Could not find span for %s\n",
792 newsym->name);
793 DIE;
795 fn(old_span, oldsym, new_span, newsym);
800 static void match_symbol_spans(struct span *old_span, asymbol *oldsym,
801 struct span *new_span, asymbol *newsym)
803 if ((oldsym->flags & BSF_DEBUGGING) != 0 ||
804 (newsym->flags & BSF_DEBUGGING) != 0)
805 return;
806 if (old_span->ss->type == SS_TYPE_SPECIAL)
807 return;
808 if (static_local_symbol(old_span->ss->parent, oldsym) ||
809 static_local_symbol(new_span->ss->parent, newsym))
810 return;
811 if (old_span->match == NULL && new_span->match == NULL)
812 match_spans(old_span, new_span);
815 static void match_spans_by_label(struct span *old_span, struct span *new_span)
817 if (old_span->ss->type == SS_TYPE_STRING ||
818 (is_table_section(old_span->ss->name, true, false) &&
819 !is_table_section(old_span->ss->name, false, false)))
820 return;
821 if (strcmp(old_span->label, new_span->label) == 0)
822 match_spans(old_span, new_span);
825 static void match_string_spans(struct span *old_span, struct span *new_span)
827 if (old_span->ss->type != SS_TYPE_STRING ||
828 strcmp(old_span->ss->name, new_span->ss->name) != 0)
829 return;
830 if (strcmp((char *)old_span->ss->contents.data + old_span->start,
831 (char *)new_span->ss->contents.data + new_span->start) == 0)
832 match_spans(old_span, new_span);
835 static void foreach_span_pair(struct superbfd *oldsbfd,
836 struct superbfd *newsbfd,
837 void (*fn)(struct span *old_span,
838 struct span *new_span))
840 asection *oldsect, *newsect;
841 struct supersect *oldss, *newss;
842 struct span *old_span, *new_span;
843 for (newsect = newsbfd->abfd->sections; newsect != NULL;
844 newsect = newsect->next) {
845 newss = fetch_supersect(newsbfd, newsect);
846 for (oldsect = oldsbfd->abfd->sections; oldsect != NULL;
847 oldsect = oldsect->next) {
848 oldss = fetch_supersect(oldsbfd, oldsect);
849 if (oldss->type != newss->type)
850 continue;
851 for (new_span = newss->spans.data;
852 new_span < newss->spans.data + newss->spans.size;
853 new_span++) {
854 for (old_span = oldss->spans.data;
855 old_span < oldss->spans.data +
856 oldss->spans.size; old_span++)
857 fn(old_span, new_span);
863 static void mark_new_spans(struct superbfd *sbfd)
865 asection *sect;
866 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
867 struct supersect *ss = fetch_supersect(sbfd, sect);
868 if (ss->type == SS_TYPE_SPECIAL || ss->type == SS_TYPE_IGNORED)
869 continue;
870 struct span *span;
871 for (span = ss->spans.data;
872 span < ss->spans.data + ss->spans.size; span++) {
873 if (span->match == NULL)
874 span->new = true;
879 static void handle_deleted_spans(struct superbfd *oldsbfd,
880 struct superbfd *newsbfd)
882 asection *sect;
883 for (sect = oldsbfd->abfd->sections; sect != NULL; sect = sect->next) {
884 struct supersect *ss = fetch_supersect(oldsbfd, sect);
885 struct span *span;
886 for (span = ss->spans.data;
887 span < ss->spans.data + ss->spans.size; span++) {
888 if (span->match != NULL)
889 continue;
890 if (ss->type == SS_TYPE_EXPORT) {
891 *vec_grow(&delsects, 1) = span->label;
892 write_ksplice_export(newsbfd, span, true);
893 } else if (ss->type == SS_TYPE_TEXT) {
894 *vec_grow(&delsects, 1) = span->label;
895 if (span->symbol == NULL)
896 DIE;
897 write_ksplice_deleted_patch
898 (newsbfd, span->symbol->name, span->label,
899 span->ss->name);
905 static void handle_nonzero_offset_relocs(struct supersect *ss)
907 struct span *address_span, *target_span;
908 arelent **relocp;
909 for (relocp = ss->relocs.data;
910 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
911 arelent *reloc = *relocp;
912 address_span = find_span(ss, reloc->address);
913 if (!address_span->new && !address_span->patch)
914 continue;
916 asymbol *sym = *reloc->sym_ptr_ptr;
917 if (bfd_is_const_section(sym->section))
918 continue;
919 bfd_vma offset = reloc_target_offset(ss, reloc);
920 target_span = reloc_target_span(ss, reloc);
921 if (sym->value + offset == target_span->start)
922 continue;
924 if (target_span->ss->type != SS_TYPE_TEXT)
925 continue;
926 if (target_span->patch)
927 continue;
929 target_span->patch = true;
930 changed = true;
931 debug1(ss->parent, "Changing %s because a relocation from sect "
932 "%s has a nonzero offset %lx+%lx into it\n",
933 target_span->label, ss->name, (unsigned long)sym->value,
934 (unsigned long)offset);
938 static void update_nonzero_offsets(struct superbfd *sbfd)
940 asection *sect;
941 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
942 struct supersect *ss = fetch_supersect(sbfd, sect);
943 if (ss->type == SS_TYPE_SPECIAL || ss->type == SS_TYPE_IGNORED)
944 continue;
945 handle_nonzero_offset_relocs(ss);
949 static void unmatch_addr_spans(struct span *old_span, struct span *new_span,
950 const struct table_section *ts)
952 struct span *old_sym_span =
953 span_offset_target_span(old_span, ts->addr_offset);
954 struct span *new_sym_span =
955 span_offset_target_span(new_span, ts->addr_offset);
956 assert(old_sym_span != NULL && new_sym_span != NULL);
957 if (old_sym_span->match == new_sym_span &&
958 new_sym_span->match == old_sym_span &&
959 !(new_sym_span->patch && new_sym_span->ss->type == SS_TYPE_TEXT)) {
960 if (old_sym_span->ss->type == SS_TYPE_TEXT) {
961 debug1(new_span->ss->parent, "Patching %s due "
962 "to relocations from special section %s\n",
963 new_sym_span->label, new_span->label);
964 new_sym_span->patch = true;
965 } else {
966 debug1(new_span->ss->parent, "Unmatching %s and %s due "
967 "to relocations from special section %s/%s\n",
968 old_sym_span->label, new_sym_span->label,
969 old_span->label, new_span->label);
970 unmatch_span(old_sym_span);
972 changed = true;
976 static void compare_spans(struct span *old_span, struct span *new_span)
978 struct superbfd *newsbfd = new_span->ss->parent;
980 bool nonrelocs_match = nonrelocs_equal(old_span, new_span);
981 bool relocs_match = all_relocs_equal(old_span, new_span);
982 if (nonrelocs_match && relocs_match) {
983 const struct table_section *ts =
984 get_table_section(old_span->ss->name);
985 if (ts != NULL && ts->crc_sect != NULL) {
986 struct span *old_crc_span = get_crc_span(old_span, ts);
987 struct span *new_crc_span = get_crc_span(new_span, ts);
988 assert(old_crc_span != NULL);
989 assert(new_crc_span != NULL);
990 if (old_crc_span->match != new_crc_span ||
991 new_crc_span->match != old_crc_span) {
992 debug1(newsbfd, "Unmatching %s and %s due to "
993 "nonmatching CRCs\n", old_span->label,
994 new_span->label);
995 unmatch_span(old_span);
998 return;
1001 char *reason;
1002 if (new_span->contents_size != old_span->contents_size)
1003 reason = "differing sizes";
1004 else if (!nonrelocs_match)
1005 reason = "differing contents";
1006 else
1007 reason = "differing relocations";
1009 if (new_span->ss->type == SS_TYPE_TEXT) {
1010 if (new_span->patch)
1011 return;
1012 new_span->patch = true;
1013 debug1(newsbfd, "Changing %s due to %s\n", new_span->label,
1014 reason);
1015 } else if (old_span->ss->type == SS_TYPE_BUGTABLE &&
1016 new_span->ss->type == SS_TYPE_BUGTABLE && relocs_match) {
1017 if (new_span->bugpatch)
1018 return;
1019 debug1(newsbfd, "Changing %s due to %s\n",
1020 new_span->label, reason);
1021 new_span->bugpatch = true;
1022 } else if (new_span->ss->type == SS_TYPE_RODATA &&
1023 new_span->contents_size == old_span->contents_size) {
1024 if (new_span->datapatch)
1025 return;
1026 new_span->datapatch = true;
1027 debug1(newsbfd, "Changing %s in-place due to %s\n",
1028 new_span->label, reason);
1029 } else if (new_span->ss->type == SS_TYPE_STRING &&
1030 old_span->ss->type == SS_TYPE_STRING && relocs_match &&
1031 strcmp(new_span->ss->contents.data + new_span->start,
1032 old_span->ss->contents.data + old_span->start) == 0) {
1033 return;
1034 } else {
1035 debug1(newsbfd, "Unmatching %s and %s due to %s\n",
1036 old_span->label, new_span->label, reason);
1037 unmatch_span(old_span);
1039 changed = true;
1040 if (unchangeable_section(new_span->ss))
1041 err(newsbfd, "warning: ignoring change to nonpatchable "
1042 "section %s\n", new_span->ss->name);
1045 static void compare_matched_spans(struct superbfd *newsbfd)
1047 asection *sect;
1048 for (sect = newsbfd->abfd->sections; sect != NULL; sect = sect->next) {
1049 struct supersect *ss = fetch_supersect(newsbfd, sect);
1050 struct span *span;
1051 for (span = ss->spans.data;
1052 span < ss->spans.data + ss->spans.size; span++) {
1053 if (span->match == NULL)
1054 continue;
1055 compare_spans(span->match, span);
1060 static void handle_section_symbol_renames(struct superbfd *oldsbfd,
1061 struct superbfd *newsbfd)
1063 asection *sect;
1064 struct span *span;
1065 for (sect = newsbfd->abfd->sections; sect != NULL; sect = sect->next) {
1066 struct supersect *ss = fetch_supersect(newsbfd, sect);
1067 for (span = ss->spans.data;
1068 span < ss->spans.data + ss->spans.size; span++) {
1069 if (span->match == NULL)
1070 continue;
1071 if (strcmp(span->label, span->match->label) == 0)
1072 continue;
1073 if (strcmp(span->orig_label, span->label) != 0 &&
1074 strcmp(span->label, span->match->label) != 0)
1075 DIE;
1076 if (span->symbol != NULL)
1077 label_map_set(newsbfd, span->label,
1078 span->match->label);
1079 span->label = span->match->label;
1084 static void copy_patched_entry_points(struct superbfd *oldsbfd,
1085 struct superbfd *newsbfd)
1087 asection *sect;
1088 struct span *span;
1089 for (sect = newsbfd->abfd->sections; sect != NULL; sect = sect->next) {
1090 struct supersect *ss = fetch_supersect(newsbfd, sect);
1091 for (span = ss->spans.data;
1092 span < ss->spans.data + ss->spans.size; span++) {
1093 if (!span->patch)
1094 continue;
1095 assert(span->match != NULL);
1096 vec_init(&span->pre_entry_points);
1098 struct entry_point *entry;
1099 for (entry = span->match->entry_points.data;
1100 entry < span->match->entry_points.data +
1101 span->match->entry_points.size;
1102 entry++) {
1103 struct entry_point *e =
1104 vec_grow(&span->pre_entry_points, 1);
1105 e->name = entry->name != NULL ?
1106 strdup(entry->name) : NULL;
1107 e->label = strdup(entry->label);
1108 e->offset = entry->offset;
1109 e->symbol = NULL;
1115 static int compare_entry_points(const void *va, const void *vb)
1117 const struct entry_point *a = va, *b = vb;
1118 if (a->offset < b->offset)
1119 return -1;
1120 else if (a->offset > b->offset)
1121 return 1;
1122 else
1123 return 0;
1126 static void compute_entry_points(struct superbfd *sbfd)
1128 asymbol **symp;
1129 for (symp = sbfd->syms.data; symp < sbfd->syms.data + sbfd->syms.size;
1130 symp++) {
1131 asymbol *sym = *symp;
1132 if (bfd_is_const_section(sym->section))
1133 continue;
1134 struct supersect *old_ss = fetch_supersect(sbfd, sym->section);
1135 if ((sym->flags & BSF_GLOBAL) == 0)
1136 continue;
1137 struct span *span = find_span(old_ss, sym->value);
1138 struct entry_point *e = vec_grow(&span->entry_points, 1);
1139 e->label = sym->name;
1140 e->name = sym->name;
1141 e->offset = sym->value - span->start;
1142 e->symbol = sym;
1145 asection *sect;
1146 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
1147 struct supersect *ss = fetch_supersect(sbfd, sect);
1148 struct span *span;
1149 for (span = ss->spans.data;
1150 span < ss->spans.data + ss->spans.size; span++) {
1151 /* First make sure that 0 appears as an entry point */
1152 bool found_zero = false;
1153 struct entry_point *entry;
1154 for (entry = span->entry_points.data;
1155 entry < span->entry_points.data +
1156 span->entry_points.size;
1157 entry++) {
1158 if (entry->offset == 0)
1159 found_zero = true;
1161 if (!found_zero) {
1162 struct entry_point *e =
1163 vec_grow(&span->entry_points, 1);
1164 e->label = span->label;
1165 e->name = NULL;
1166 e->offset = 0;
1167 e->symbol = span->symbol;
1170 qsort(span->entry_points.data, span->entry_points.size,
1171 sizeof(*span->entry_points.data),
1172 compare_entry_points);
1177 static bool part_of_reloc(struct supersect *ss, unsigned long addr)
1179 arelent **relocp;
1180 for (relocp = ss->relocs.data;
1181 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
1182 arelent *reloc = *relocp;
1183 if (addr >= reloc->address &&
1184 addr < reloc->address + bfd_get_reloc_size(reloc->howto))
1185 return true;
1187 return false;
1190 static bool nonrelocs_equal(struct span *old_span, struct span *new_span)
1192 int i;
1193 struct supersect *old_ss = old_span->ss, *new_ss = new_span->ss;
1194 if (old_span->contents_size != new_span->contents_size)
1195 return false;
1196 const unsigned char *old = old_ss->contents.data + old_span->start;
1197 const unsigned char *new = new_ss->contents.data + new_span->start;
1198 for (i = 0; i < old_span->contents_size; i++) {
1199 if (old[i] != new[i] &&
1200 !(part_of_reloc(old_ss, i + old_span->start) &&
1201 part_of_reloc(new_ss, i + new_span->start)))
1202 return false;
1204 return true;
1207 bool relocs_equal(struct supersect *old_src_ss, struct supersect *new_src_ss,
1208 arelent *old_reloc, arelent *new_reloc)
1210 struct superbfd *oldsbfd = old_src_ss->parent;
1211 struct superbfd *newsbfd = new_src_ss->parent;
1212 struct span *old_addr_span = find_span(old_src_ss, old_reloc->address);
1213 struct span *new_addr_span = find_span(new_src_ss, new_reloc->address);
1215 if (old_reloc->address - old_addr_span->start !=
1216 new_reloc->address - new_addr_span->start) {
1217 debug1(newsbfd, "Section %s/%s has reloc address mismatch at "
1218 "%lx\n", old_src_ss->name, new_src_ss->name,
1219 (unsigned long)old_reloc->address);
1220 return false;
1223 if (old_reloc->howto != new_reloc->howto) {
1224 debug1(newsbfd, "Section %s/%s has howto type mismatch at "
1225 "%lx\n", old_src_ss->name, new_src_ss->name,
1226 (unsigned long)old_reloc->address);
1227 return false;
1230 if (non_dst_mask(old_src_ss, old_reloc) !=
1231 non_dst_mask(new_src_ss, new_reloc)) {
1232 debug1(newsbfd, "Section %s/%s has contents mismatch at %lx\n",
1233 old_src_ss->name, new_src_ss->name,
1234 (unsigned long)old_reloc->address);
1235 return false;
1238 asymbol *old_sym = *old_reloc->sym_ptr_ptr;
1239 asymbol *new_sym = *new_reloc->sym_ptr_ptr;
1240 asection *old_sect = old_sym->section;
1241 asection *new_sect = new_sym->section;
1243 bfd_vma old_offset = reloc_target_offset(old_src_ss, old_reloc);
1244 bfd_vma new_offset = reloc_target_offset(new_src_ss, new_reloc);
1246 if (bfd_is_und_section(old_sect) || bfd_is_und_section(new_sect)) {
1247 if (!bfd_is_und_section(new_sect) && old_offset != 0 &&
1248 fetch_supersect(newsbfd, new_sect)->type == SS_TYPE_TEXT)
1249 return false;
1251 if (!bfd_is_und_section(new_sect) && new_offset != 0 &&
1252 fetch_supersect(oldsbfd, old_sect)->type == SS_TYPE_TEXT)
1253 return false;
1255 return strcmp(old_sym->name, new_sym->name) == 0 &&
1256 old_offset == new_offset;
1259 if (bfd_is_abs_section(old_sect) && bfd_is_abs_section(new_sect)) {
1260 if (old_sym->value + old_offset == new_sym->value + new_offset)
1261 return true;
1262 debug1(newsbfd, "Differing relocations from %s/%s to ABS "
1263 "section: %lx/%lx\n", old_addr_span->label,
1264 new_addr_span->label,
1265 (unsigned long)(old_sym->value + old_offset),
1266 (unsigned long)(new_sym->value + new_offset));
1267 return false;
1270 if (bfd_is_const_section(old_sect) || bfd_is_const_section(new_sect))
1271 DIE;
1273 struct supersect *old_ss = fetch_supersect(oldsbfd, old_sect);
1274 struct supersect *new_ss = fetch_supersect(newsbfd, new_sect);
1275 struct span *old_span = reloc_target_span(old_src_ss, old_reloc);
1276 struct span *new_span = reloc_target_span(new_src_ss, new_reloc);
1278 if (old_span->match != new_span || new_span->match != old_span) {
1279 debug1(newsbfd, "Nonmatching relocs from %s to %s/%s\n",
1280 new_src_ss->name, old_span->label, new_span->label);
1281 return false;
1284 if (old_sym->value + old_offset - old_span->start !=
1285 new_sym->value + new_offset - new_span->start) {
1286 debug1(newsbfd, "Offsets to %s/%s differ between %s "
1287 "and %s: %lx+%lx/%lx+%lx\n", old_ss->name,
1288 new_ss->name, old_src_ss->name, new_src_ss->name,
1289 (unsigned long)old_sym->value, (unsigned long)old_offset,
1290 (unsigned long)new_sym->value,
1291 (unsigned long)new_offset);
1292 return false;
1295 if ((old_sym->value + old_offset - old_span->start != 0 ||
1296 new_sym->value + new_offset - new_span->start != 0) &&
1297 new_span->patch) {
1298 debug1(newsbfd, "Relocation from %s to nonzero offsets "
1299 "%lx+%lx/%lx+%lx in changed section %s\n",
1300 new_src_ss->name, (unsigned long)old_sym->value,
1301 (unsigned long)old_offset, (unsigned long)new_sym->value,
1302 (unsigned long)new_offset, new_sym->section->name);
1303 return false;
1305 return true;
1308 bool all_relocs_equal(struct span *old_span, struct span *new_span)
1310 struct supersect *old_ss = old_span->ss, *new_ss = new_span->ss;
1311 arelent **old_relocp, **new_relocp;
1313 for (old_relocp = old_ss->relocs.data;
1314 old_relocp < old_ss->relocs.data + old_ss->relocs.size;
1315 old_relocp++) {
1316 if (find_span(old_ss, (*old_relocp)->address) == old_span)
1317 break;
1320 for (new_relocp = new_ss->relocs.data;
1321 new_relocp < new_ss->relocs.data + new_ss->relocs.size;
1322 new_relocp++) {
1323 if (find_span(new_ss, (*new_relocp)->address) == new_span)
1324 break;
1327 for (; old_relocp < old_ss->relocs.data + old_ss->relocs.size &&
1328 find_span(old_ss, (*old_relocp)->address) == old_span &&
1329 new_relocp < new_ss->relocs.data + new_ss->relocs.size &&
1330 find_span(new_ss, (*new_relocp)->address) == new_span;
1331 old_relocp++, new_relocp++) {
1332 if (!relocs_equal(old_ss, new_ss, *old_relocp, *new_relocp))
1333 return false;
1336 if ((old_relocp < old_ss->relocs.data + old_ss->relocs.size &&
1337 find_span(old_ss, (*old_relocp)->address) == old_span) ||
1338 (new_relocp < new_ss->relocs.data + new_ss->relocs.size &&
1339 find_span(new_ss, (*new_relocp)->address) == new_span)) {
1340 debug1(new_ss->parent, "Different reloc count between %s and "
1341 "%s\n", old_span->label, new_span->label);
1342 return false;
1345 return true;
1348 bfd_vma non_dst_mask(struct supersect *ss, arelent *reloc)
1350 int bits = bfd_get_reloc_size(reloc->howto) * 8;
1351 void *address = ss->contents.data + reloc->address;
1352 bfd_vma x = bfd_get(bits, ss->parent->abfd, address);
1353 return x & ~reloc->howto->dst_mask;
1356 void rm_relocs(struct superbfd *isbfd)
1358 asection *p;
1359 for (p = isbfd->abfd->sections; p != NULL; p = p->next) {
1360 struct supersect *ss = fetch_supersect(isbfd, p);
1361 bool remove_relocs = ss->keep;
1363 if (mode("keep") && ss->type == SS_TYPE_SPECIAL)
1364 remove_relocs = false;
1366 if (ss->type == SS_TYPE_KSPLICE ||
1367 ss->type == SS_TYPE_KSPLICE_CALL)
1368 remove_relocs = false;
1369 if (mode("finalize") &&
1370 (strstarts(ss->name, ".ksplice_patches") ||
1371 strstarts(ss->name, ".ksplice_relocs")))
1372 remove_relocs = true;
1374 if (remove_relocs)
1375 rm_some_relocs(ss);
1379 void rm_some_relocs(struct supersect *ss)
1381 struct arelentp_vec orig_relocs;
1382 vec_move(&orig_relocs, &ss->relocs);
1384 arelent **relocp;
1385 for (relocp = orig_relocs.data;
1386 relocp < orig_relocs.data + orig_relocs.size; relocp++) {
1387 bool rm_reloc = false;
1388 asymbol *sym_ptr = *(*relocp)->sym_ptr_ptr;
1390 if (mode("rmsyms") && bfd_is_und_section(sym_ptr->section)) {
1391 asymbol **esymp;
1392 for (esymp = extract_syms.data;
1393 esymp < extract_syms.data + extract_syms.size;
1394 esymp++) {
1395 if (sym_ptr == *esymp) {
1396 rm_reloc = true;
1397 break;
1402 if (mode("keep"))
1403 rm_reloc = true;
1405 if (mode("keep-new-code")) {
1406 if (bfd_is_const_section(sym_ptr->section)) {
1407 rm_reloc = false;
1408 } else {
1409 bfd_vma offset = reloc_target_offset(ss, *relocp);
1410 struct span *target_span =
1411 reloc_target_span(ss, *relocp);
1412 if (target_span->new ||
1413 (target_span->ss->type == SS_TYPE_TEXT &&
1414 sym_ptr->value + offset !=
1415 target_span->start))
1416 rm_reloc = false;
1419 const struct table_section *ts =
1420 get_table_section(ss->name);
1421 if (ts != NULL && ts->has_addr &&
1422 ((*relocp)->address % ts->entry_size ==
1423 ts->addr_offset ||
1424 (*relocp)->address % ts->entry_size ==
1425 ts->other_offset))
1426 rm_reloc = false;
1429 if (mode("finalize") && bfd_is_und_section(sym_ptr->section))
1430 rm_reloc = true;
1432 if (strcmp(sym_ptr->name, "mcount") == 0 &&
1433 bfd_is_und_section(sym_ptr->section))
1434 rm_reloc = false;
1436 if (!find_span(ss, (*relocp)->address)->keep)
1437 rm_reloc = false;
1439 if (rm_reloc)
1440 write_ksplice_reloc(ss, *relocp);
1441 else
1442 *vec_grow(&ss->relocs, 1) = *relocp;
1446 struct supersect *make_section(struct superbfd *sbfd, const char *fmt, ...)
1448 va_list ap;
1449 va_start(ap, fmt);
1450 char *name = vstrprintf(fmt, ap);
1451 va_end(ap);
1453 asection *sect = bfd_get_section_by_name(sbfd->abfd, name);
1454 if (sect != NULL)
1455 return fetch_supersect(sbfd, sect);
1456 else
1457 return new_supersect(sbfd, name);
1460 arelent *create_reloc(struct supersect *ss, const void *addr, asymbol **symp,
1461 bfd_vma offset)
1463 bfd_reloc_code_real_type code;
1464 switch (bfd_arch_bits_per_address(ss->parent->abfd)) {
1465 case 32:
1466 code = BFD_RELOC_32;
1467 break;
1468 case 64:
1469 code = BFD_RELOC_64;
1470 break;
1471 default:
1472 DIE;
1475 arelent *reloc = malloc(sizeof(*reloc));
1476 reloc->sym_ptr_ptr = symp;
1477 reloc->address = addr_offset(ss, addr);
1478 reloc->howto = bfd_reloc_type_lookup(ss->parent->abfd, code);
1479 reloc->addend = offset;
1480 return reloc;
1483 void write_reloc(struct supersect *ss, const void *addr, asymbol **symp,
1484 bfd_vma offset)
1486 *vec_grow(&ss->new_relocs, 1) = create_reloc(ss, addr, symp, offset);
1489 void write_string(struct supersect *ss, const char **addr, const char *fmt, ...)
1491 va_list ap;
1492 struct supersect *str_ss = make_section(ss->parent, ".ksplice_str");
1493 char *str;
1494 va_start(ap, fmt);
1495 int len = vasprintf(&str, fmt, ap);
1496 assert(len >= 0);
1497 va_end(ap);
1499 unsigned long *str_offp = ulong_hash_lookup(&ksplice_string_offset, str,
1500 FALSE);
1501 if (str_offp == NULL) {
1502 char *buf = sect_grow(str_ss, len + 1, char);
1503 memcpy(buf, str, len + 1);
1504 str_offp = ulong_hash_lookup(&ksplice_string_offset, str, TRUE);
1505 *str_offp = addr_offset(str_ss, buf);
1508 write_reloc(ss, addr, &str_ss->symbol, *str_offp);
1511 void lookup_system_map(struct addr_vec *addrs, const char *name, long offset)
1513 struct addr_vec *map_addrs =
1514 addr_vec_hash_lookup(&system_map, name, FALSE);
1515 if (map_addrs == NULL)
1516 return;
1518 unsigned long *addr, *map_addr;
1519 for (map_addr = map_addrs->data;
1520 map_addr < map_addrs->data + map_addrs->size; map_addr++) {
1521 for (addr = addrs->data; addr < addrs->data + addrs->size;
1522 addr++) {
1523 if (*addr == *map_addr + offset)
1524 break;
1526 if (addr < addrs->data + addrs->size)
1527 continue;
1528 *vec_grow(addrs, 1) = *map_addr + offset;
1532 void compute_system_map_array(struct superbfd *sbfd, struct addr_vec *addrs,
1533 asymbol *sym)
1535 if (bfd_is_abs_section(sym->section)) {
1536 *vec_grow(addrs, 1) = sym->value;
1537 } else if (bfd_is_und_section(sym->section)) {
1538 lookup_system_map(addrs, sym->name, 0);
1539 } else if (!bfd_is_const_section(sym->section)) {
1540 asymbol **gsymp;
1541 for (gsymp = sbfd->syms.data;
1542 gsymp < sbfd->syms.data + sbfd->syms.size; gsymp++) {
1543 asymbol *gsym = *gsymp;
1544 if ((gsym->flags & BSF_DEBUGGING) == 0 &&
1545 gsym->section == sym->section)
1546 lookup_system_map(addrs, gsym->name,
1547 sym->value - gsym->value);
1552 void write_ksplice_system_map(struct superbfd *sbfd, asymbol *sym,
1553 const char *label)
1555 bool *done = bool_hash_lookup(&system_map_written, label, TRUE);
1556 if (*done)
1557 return;
1558 *done = true;
1560 struct addr_vec addrs;
1561 vec_init(&addrs);
1563 compute_system_map_array(sbfd, &addrs, sym);
1564 if (addrs.size != 0) {
1565 struct supersect *smap_ss =
1566 make_section(sbfd, ".ksplice_system_map");
1567 struct ksplice_system_map *smap =
1568 sect_grow(smap_ss, 1, struct ksplice_system_map);
1569 write_string(smap_ss, &smap->label, "%s", label);
1571 struct supersect *array_ss = make_section(sbfd,
1572 ".ksplice_array");
1573 void *buf = sect_grow(array_ss, addrs.size,
1574 typeof(*addrs.data));
1575 memcpy(buf, addrs.data, addrs.size * sizeof(*addrs.data));
1576 smap->nr_candidates = addrs.size;
1577 write_reloc(smap_ss, &smap->candidates, &array_ss->symbol,
1578 addr_offset(array_ss, buf));
1580 vec_free(&addrs);
1583 void write_ksplice_symbol_backend(struct supersect *ss,
1584 struct ksplice_symbol *const *addr,
1585 asymbol *sym, const char *label,
1586 const char *name)
1588 struct supersect *ksymbol_ss = make_section(ss->parent,
1589 ".ksplice_symbols");
1590 struct ksplice_symbol *ksymbol;
1591 unsigned long *ksymbol_offp;
1593 ksymbol_offp = ulong_hash_lookup(&ksplice_symbol_offset, label, FALSE);
1594 if (ksymbol_offp != NULL) {
1595 write_reloc(ss, addr, &ksymbol_ss->symbol, *ksymbol_offp);
1596 return;
1598 ksymbol = sect_grow(ksymbol_ss, 1, struct ksplice_symbol);
1599 ksymbol_offp = ulong_hash_lookup(&ksplice_symbol_offset, label, TRUE);
1600 *ksymbol_offp = addr_offset(ksymbol_ss, ksymbol);
1602 write_reloc(ss, addr, &ksymbol_ss->symbol, *ksymbol_offp);
1603 write_string(ksymbol_ss, &ksymbol->label, "%s", label);
1604 if (name != NULL) {
1605 write_string(ksymbol_ss, &ksymbol->name, "%s", name);
1606 write_ksplice_system_map(ksymbol_ss->parent, sym, label);
1610 void write_ksplice_symbol(struct supersect *ss,
1611 struct ksplice_symbol *const *addr,
1612 asymbol *sym, struct span *span,
1613 const char *addstr_sect)
1615 const char *label, *name;
1616 if (span != NULL && span->start != 0)
1617 label = span->label;
1618 else
1619 label = label_lookup(ss->parent, sym);
1621 asymbol *gsym = canonical_symbol(ss->parent, sym);
1622 if (strcmp(addstr_sect, "") != 0)
1623 name = NULL;
1624 else if (bfd_is_und_section(sym->section))
1625 name = sym->name;
1626 else if (bfd_is_const_section(sym->section))
1627 name = NULL;
1628 else if (span != NULL && span->symbol == NULL)
1629 name = NULL;
1630 else if (gsym == NULL || (gsym->flags & BSF_SECTION_SYM) != 0)
1631 name = NULL;
1632 else
1633 name = gsym->name;
1635 write_ksplice_symbol_backend(ss, addr, sym,
1636 strprintf("%s%s", addstr_sect, label),
1637 name);
1640 void write_ksplice_reloc(struct supersect *ss, arelent *orig_reloc)
1642 asymbol *sym_ptr = *orig_reloc->sym_ptr_ptr;
1643 bfd_vma reloc_addend = reloc_offset(ss, orig_reloc);
1644 bfd_vma target_addend = reloc_target_offset(ss, orig_reloc);
1645 unsigned long *repladdr = ss->contents.data + orig_reloc->address;
1647 if (mode("finalize") && strstarts(ss->name, ".ksplice_patches")) {
1648 *repladdr = 0;
1649 return;
1651 if (mode("finalize") && strstarts(ss->name, ".ksplice_relocs")) {
1652 assert(strstarts(sym_ptr->name, KSPLICE_SYMBOL_STR));
1653 asymbol fake_sym;
1654 fake_sym.name = sym_ptr->name + strlen(KSPLICE_SYMBOL_STR);
1655 fake_sym.section = bfd_und_section_ptr;
1656 fake_sym.value = 0;
1657 fake_sym.flags = 0;
1659 write_ksplice_symbol_backend
1660 (ss, (struct ksplice_symbol **)repladdr, &fake_sym,
1661 fake_sym.name, fake_sym.name);
1662 return;
1665 struct span *span = reloc_target_span(ss, orig_reloc);
1666 if (span == ss->spans.data && span->start != target_addend)
1667 span = NULL;
1668 write_canary(ss, orig_reloc->address,
1669 bfd_get_reloc_size(orig_reloc->howto),
1670 orig_reloc->howto->dst_mask);
1672 struct supersect *kreloc_ss =
1673 make_section(ss->parent, ".ksplice_relocs%s", ss->name);
1674 struct ksplice_reloc *kreloc = sect_grow(kreloc_ss, 1,
1675 struct ksplice_reloc);
1677 struct span *address_span = find_span(ss, orig_reloc->address);
1678 write_reloc(kreloc_ss, &kreloc->blank_addr,
1679 &ss->symbol, orig_reloc->address + address_span->shift);
1680 if (bfd_is_und_section(sym_ptr->section) && mode("keep")) {
1681 char *name = strprintf(KSPLICE_SYMBOL_STR "%s", sym_ptr->name);
1682 asymbol **symp = make_undefined_symbolp(ss->parent, name);
1683 write_reloc(kreloc_ss, &kreloc->symbol, symp, 0);
1684 } else {
1685 write_ksplice_symbol(kreloc_ss, &kreloc->symbol, sym_ptr, span,
1686 "");
1688 if (span != NULL && span->start != 0) {
1689 reloc_addend += sym_ptr->value - span->start;
1690 target_addend += sym_ptr->value - span->start;
1692 kreloc->insn_addend = reloc_addend - target_addend;
1693 kreloc->target_addend = target_addend;
1694 write_ksplice_reloc_howto(kreloc_ss, &kreloc->howto, orig_reloc->howto,
1695 KSPLICE_HOWTO_RELOC);
1698 static void write_ksplice_reloc_howto(struct supersect *ss, const
1699 struct ksplice_reloc_howto *const *addr,
1700 reloc_howto_type *howto,
1701 enum ksplice_reloc_howto_type type)
1703 struct supersect *khowto_ss = make_section(ss->parent,
1704 ".ksplice_reloc_howtos");
1705 struct ksplice_reloc_howto *khowto;
1706 unsigned long *khowto_offp;
1708 khowto_offp = ulong_hash_lookup(&ksplice_howto_offset, howto->name,
1709 FALSE);
1710 if (khowto_offp != NULL) {
1711 write_reloc(ss, addr, &khowto_ss->symbol, *khowto_offp);
1712 return;
1714 khowto = sect_grow(khowto_ss, 1, struct ksplice_reloc_howto);
1715 khowto_offp = ulong_hash_lookup(&ksplice_howto_offset, howto->name,
1716 TRUE);
1717 *khowto_offp = addr_offset(khowto_ss, khowto);
1719 khowto->type = type;
1720 khowto->pcrel = howto->pc_relative;
1721 khowto->size = bfd_get_reloc_size(howto);
1722 khowto->dst_mask = howto->dst_mask;
1723 khowto->rightshift = howto->rightshift;
1724 khowto->signed_addend =
1725 (howto->complain_on_overflow == complain_overflow_signed) ||
1726 (howto->complain_on_overflow == complain_overflow_bitfield);
1727 write_reloc(ss, addr, &khowto_ss->symbol, *khowto_offp);
1730 #define CANARY(x, canary) ((x & ~howto->dst_mask) | (canary & howto->dst_mask))
1732 void write_canary(struct supersect *ss, int offset, bfd_size_type size,
1733 bfd_vma dst_mask)
1735 int bits = size * 8;
1736 void *address = ss->contents.data + offset;
1737 bfd_vma x = bfd_get(bits, ss->parent->abfd, address);
1738 x = (x & ~dst_mask) | ((bfd_vma)KSPLICE_CANARY & dst_mask);
1739 bfd_put(bits, ss->parent->abfd, x, address);
1742 static void write_date_relocs(struct superbfd *sbfd, const char *str,
1743 enum ksplice_reloc_howto_type type)
1745 asection *sect;
1746 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
1747 struct supersect *ss = fetch_supersect(sbfd, sect);
1748 if (ss->type != SS_TYPE_STRING && ss->type != SS_TYPE_RODATA)
1749 continue;
1750 void *ptr;
1751 struct span *span;
1752 for (span = ss->spans.data;
1753 span < ss->spans.data + ss->spans.size; span++) {
1754 if (!span->keep)
1755 continue;
1756 for (ptr = ss->contents.data + span->start;
1757 ptr + strlen(str) < ss->contents.data +
1758 span->start + span->contents_size; ptr++) {
1759 if (strcmp((const char *)ptr, str) == 0)
1760 write_ksplice_date_reloc
1761 (ss, addr_offset(ss, ptr), str,
1762 type);
1768 static void write_ksplice_date_reloc(struct supersect *ss, unsigned long offset,
1769 const char *str,
1770 enum ksplice_reloc_howto_type type)
1772 struct supersect *kreloc_ss;
1773 kreloc_ss = make_section(ss->parent, ".ksplice_relocs%s", ss->name);
1774 struct ksplice_reloc *kreloc = sect_grow(kreloc_ss, 1,
1775 struct ksplice_reloc);
1777 const char *filename = ss->parent->abfd->filename;
1778 char *c = strstr(filename, ".KSPLICE");
1779 int flen = (c == NULL ? strlen(filename) : c - filename);
1781 write_ksplice_symbol_backend(kreloc_ss, &kreloc->symbol, NULL,
1782 strprintf("%s<%.*s>", str, flen, filename),
1783 NULL);
1785 struct span *span = find_span(ss, offset);
1786 write_reloc(kreloc_ss, &kreloc->blank_addr, &ss->symbol,
1787 offset + span->shift);
1788 write_ksplice_nonreloc_howto(kreloc_ss, &kreloc->howto, type,
1789 strlen(str));
1792 static void write_table_relocs(struct superbfd *sbfd, const char *sectname,
1793 enum ksplice_reloc_howto_type type)
1795 asection *sect = bfd_get_section_by_name(sbfd->abfd, sectname);
1796 if (sect == NULL)
1797 return;
1798 struct supersect *ss = fetch_supersect(sbfd, sect);
1800 const struct table_section *s = get_table_section(sectname);
1801 if (s == NULL)
1802 DIE;
1804 void *entry;
1805 for (entry = ss->contents.data;
1806 entry < ss->contents.data + ss->contents.size;
1807 entry += s->entry_size) {
1808 struct span *span = find_span(ss, addr_offset(ss, entry));
1809 assert(span != NULL);
1810 if (!span->keep)
1811 continue;
1813 arelent *reloc = find_reloc(ss, entry + s->addr_offset);
1814 assert(reloc != NULL);
1815 asymbol *sym = *reloc->sym_ptr_ptr;
1816 assert(!bfd_is_const_section(sym->section));
1817 struct supersect *sym_ss = fetch_supersect(sbfd, sym->section);
1818 unsigned long addr = sym->value +
1819 reloc_target_offset(ss, reloc);
1820 write_ksplice_table_reloc(sym_ss, addr, span->label, type);
1824 static void write_ksplice_table_reloc(struct supersect *ss,
1825 unsigned long address,
1826 const char *label,
1827 enum ksplice_reloc_howto_type type)
1829 struct supersect *kreloc_ss;
1830 kreloc_ss = make_section(ss->parent, ".ksplice_relocs%s", ss->name);
1831 struct ksplice_reloc *kreloc = sect_grow(kreloc_ss, 1,
1832 struct ksplice_reloc);
1833 struct span *span = find_span(ss, address);
1834 assert(span != NULL);
1836 write_ksplice_symbol_backend(kreloc_ss, &kreloc->symbol, NULL,
1837 label, NULL);
1838 write_reloc(kreloc_ss, &kreloc->blank_addr, &ss->symbol,
1839 address + span->shift);
1840 write_ksplice_nonreloc_howto(kreloc_ss, &kreloc->howto, type, 0);
1843 static void write_ksplice_nonreloc_howto(struct supersect *ss,
1844 const struct ksplice_reloc_howto
1845 *const *addr,
1846 enum ksplice_reloc_howto_type type,
1847 int size)
1849 struct supersect *khowto_ss =
1850 make_section(ss->parent, ".ksplice_reloc_howtos");
1851 struct ksplice_reloc_howto *khowto =
1852 sect_grow(khowto_ss, 1, struct ksplice_reloc_howto);
1854 khowto->type = type;
1855 khowto->size = size;
1856 khowto->pcrel = 0;
1857 khowto->dst_mask = 0;
1858 khowto->rightshift = 0;
1859 khowto->signed_addend = 0;
1860 write_reloc(ss, addr, &khowto_ss->symbol,
1861 addr_offset(khowto_ss, khowto));
1864 static void write_ksplice_symbol_reloc(struct supersect *ss,
1865 const char *sectname,
1866 unsigned long *addr, asymbol *sym,
1867 const char *label, const char *name)
1869 struct supersect *kreloc_ss;
1870 kreloc_ss = make_section(ss->parent, ".ksplice_relocs%s", sectname);
1871 struct ksplice_reloc *kreloc = sect_grow(kreloc_ss, 1,
1872 struct ksplice_reloc);
1874 write_ksplice_symbol_backend(kreloc_ss, &kreloc->symbol, sym, label,
1875 name);
1876 write_reloc(kreloc_ss, &kreloc->blank_addr, &ss->symbol,
1877 addr_offset(ss, addr));
1878 write_ksplice_nonreloc_howto(kreloc_ss, &kreloc->howto,
1879 KSPLICE_HOWTO_SYMBOL, 0);
1882 static void write_ksplice_section(struct span *span)
1884 struct supersect *ss = span->ss;
1885 const char *sectname = span->ss->name;
1886 const struct table_section *ts = get_table_section(ss->name);
1888 if (ts != NULL && ts->has_addr) {
1889 arelent *reloc = find_reloc(ss, ss->contents.data + span->start
1890 + ts->addr_offset);
1891 assert(reloc != NULL);
1892 asymbol *rsym = *reloc->sym_ptr_ptr;
1893 assert(!bfd_is_const_section(rsym->section));
1894 sectname = rsym->section->name;
1897 struct supersect *ksect_ss =
1898 make_section(ss->parent, ".ksplice_sections%s", sectname);
1899 struct ksplice_section *ksect = sect_grow(ksect_ss, 1,
1900 struct ksplice_section);
1901 asymbol *sym = span->symbol == NULL ? ss->symbol : span->symbol;
1903 write_ksplice_symbol(ksect_ss, &ksect->symbol, sym, span,
1904 mode("keep-new-code") ? "(post)" : "");
1905 ksect->size = span->size;
1906 ksect->flags = 0;
1908 if (ss->type == SS_TYPE_RODATA || ss->type == SS_TYPE_STRING ||
1909 ss->type == SS_TYPE_EXPORT || ss->type == SS_TYPE_BUGTABLE)
1910 ksect->flags |= KSPLICE_SECTION_RODATA;
1911 if (ss->type == SS_TYPE_DATA)
1912 ksect->flags |= KSPLICE_SECTION_DATA;
1913 if (ss->type == SS_TYPE_TEXT)
1914 ksect->flags |= KSPLICE_SECTION_TEXT;
1915 assert(ksect->flags != 0);
1917 if (ss->type == SS_TYPE_STRING)
1918 ksect->flags |= KSPLICE_SECTION_STRING;
1920 write_reloc(ksect_ss, &ksect->address, &ss->symbol,
1921 span->start + span->shift);
1923 if (mode("keep-old-code")) {
1924 /* Write ksplice_symbols for all the entry points */
1925 struct entry_point *entry;
1926 for (entry = span->entry_points.data;
1927 entry < span->entry_points.data + span->entry_points.size;
1928 entry++)
1929 write_ksplice_symbol_reloc
1930 (span->ss, sectname, span->ss->contents.data +
1931 span->start + span->shift + entry->offset,
1932 entry->symbol, entry->label, entry->name);
1936 static void write_ksplice_patch_reloc(struct supersect *ss,
1937 const char *sectname, unsigned long *addr,
1938 bfd_size_type size, const char *label,
1939 long addend)
1941 struct supersect *kreloc_ss;
1942 kreloc_ss = make_section(ss->parent, ".ksplice_relocs%s", sectname);
1943 struct ksplice_reloc *kreloc = sect_grow(kreloc_ss, 1,
1944 struct ksplice_reloc);
1946 write_canary(ss, addr_offset(ss, addr), size, -1);
1947 write_ksplice_symbol_backend(kreloc_ss, &kreloc->symbol, NULL,
1948 label, NULL);
1949 write_reloc(kreloc_ss, &kreloc->blank_addr, &ss->symbol,
1950 addr_offset(ss, addr));
1951 reloc_howto_type *howto =
1952 bfd_reloc_type_lookup(ss->parent->abfd,
1953 PASTE(BFD_RELOC_, LONG_BIT));
1954 write_ksplice_reloc_howto(kreloc_ss, &kreloc->howto, howto,
1955 KSPLICE_HOWTO_RELOC);
1956 kreloc->target_addend = addend;
1957 kreloc->insn_addend = 0;
1960 /* Assumes symbol is global, aka only one symbol of that name */
1961 static asymbol *name_to_symbol(struct superbfd *sbfd, const char *name)
1963 if (name == NULL)
1964 return NULL;
1966 asymbol **symp;
1967 for (symp = sbfd->syms.data;
1968 symp < sbfd->syms.data + sbfd->syms.size; symp++) {
1969 asymbol *sym = *symp;
1970 if (strcmp(name, sym->name) == 0 &&
1971 ((sym->flags & BSF_GLOBAL) != 0 ||
1972 bfd_is_und_section(sym->section)))
1973 return sym;
1975 return NULL;
1978 void write_ksplice_patches(struct superbfd *sbfd, struct span *span)
1980 if (span->datapatch) {
1981 write_ksplice_patch(sbfd, span, span->label, 0);
1982 return;
1985 assert(span->patch);
1987 long prev_offset = LONG_MIN;
1988 asymbol *prev_sym = NULL;
1989 const char *prev_label = NULL;
1990 struct entry_point *entry;
1991 for (entry = span->pre_entry_points.data;
1992 entry < span->pre_entry_points.data + span->pre_entry_points.size;
1993 entry++) {
1994 asymbol *sym = name_to_symbol(sbfd, entry->name);
1996 if (entry->offset != prev_offset) {
1997 debug1(sbfd, "entry point: %s(%s) %lx\n", entry->label,
1998 entry->name, entry->offset);
2000 if (prev_offset + MAX_TRAMPOLINE_SIZE > entry->offset) {
2001 err(sbfd,
2002 "Overlapping trampolines: %s %lx/%lx\n",
2003 span->label, prev_offset, entry->offset);
2004 DIE;
2007 long target_offset = 0;
2008 if (sym != NULL)
2009 target_offset = sym->value - span->start;
2010 write_ksplice_patch(sbfd, span, entry->label,
2011 target_offset);
2012 prev_offset = entry->offset;
2013 prev_sym = NULL;
2016 if (prev_sym == NULL) {
2017 prev_sym = sym;
2018 prev_label = entry->label;
2019 } else if (sym != NULL &&
2020 (prev_sym->section != sym->section ||
2021 prev_sym->value != sym->value)) {
2022 err(sbfd, "Splitting global symbols in the middle of a "
2023 "span: %s+%lx != %s+%lx!\n",
2024 prev_label, (unsigned long)prev_sym->value,
2025 entry->label, (unsigned long)sym->value);
2026 DIE;
2030 if (prev_offset + MAX_TRAMPOLINE_SIZE > span->size) {
2031 err(sbfd, "Trampoline ends outside span: %s %lx/%lx\n",
2032 span->label, prev_offset, (unsigned long)span->size);
2033 DIE;
2037 void write_ksplice_patch(struct superbfd *sbfd, struct span *span,
2038 const char *label, long offset)
2040 struct supersect *kpatch_ss =
2041 make_section(sbfd, ".ksplice_patches%s", span->ss->name);
2042 struct ksplice_patch *kpatch = sect_grow(kpatch_ss, 1,
2043 struct ksplice_patch);
2045 write_ksplice_patch_reloc(kpatch_ss, span->ss->name, &kpatch->oldaddr,
2046 sizeof(kpatch->oldaddr), label, 0);
2047 if (span->ss->type == SS_TYPE_TEXT) {
2048 kpatch->type = KSPLICE_PATCH_TEXT;
2049 write_patch_storage(kpatch_ss, kpatch, MAX_TRAMPOLINE_SIZE,
2050 NULL);
2051 } else {
2052 kpatch->type = KSPLICE_PATCH_DATA;
2053 kpatch->size = span->contents_size;
2054 struct supersect *data_ss =
2055 make_section(sbfd, ".ksplice_patch_data");
2056 write_reloc(kpatch_ss, &kpatch->contents, &span->ss->symbol,
2057 span->start + span->shift);
2058 char *saved = sect_do_grow(data_ss, 1, span->contents_size, 1);
2059 write_reloc(kpatch_ss, &kpatch->saved, &data_ss->symbol,
2060 addr_offset(data_ss, saved));
2062 write_reloc(kpatch_ss, &kpatch->repladdr, &span->ss->symbol,
2063 span->start + span->shift + offset);
2066 asymbol **make_undefined_symbolp(struct superbfd *sbfd, const char *name)
2068 asymbol **symp;
2069 for (symp = sbfd->syms.data; symp < sbfd->syms.data + sbfd->syms.size;
2070 symp++) {
2071 asymbol *sym = *symp;
2072 if (strcmp(name, sym->name) == 0 &&
2073 bfd_is_und_section(sym->section))
2074 return symp;
2076 asymbol ***sympp;
2077 for (sympp = sbfd->new_syms.data;
2078 sympp < sbfd->new_syms.data + sbfd->new_syms.size; sympp++) {
2079 asymbol **symp = *sympp;
2080 asymbol *sym = *symp;
2081 if (strcmp(name, sym->name) == 0 &&
2082 bfd_is_und_section(sym->section))
2083 return symp;
2086 symp = malloc(sizeof(*symp));
2087 *symp = bfd_make_empty_symbol(sbfd->abfd);
2088 asymbol *sym = *symp;
2089 sym->name = name;
2090 sym->section = bfd_und_section_ptr;
2091 sym->flags = 0;
2092 sym->value = 0;
2093 *vec_grow(&sbfd->new_syms, 1) = symp;
2094 return symp;
2097 void write_ksplice_deleted_patch(struct superbfd *sbfd, const char *name,
2098 const char *label, const char *sectname)
2100 struct supersect *kpatch_ss =
2101 make_section(sbfd, ".ksplice_patches%s", sectname);
2102 struct ksplice_patch *kpatch = sect_grow(kpatch_ss, 1,
2103 struct ksplice_patch);
2105 write_ksplice_patch_reloc(kpatch_ss, sectname, &kpatch->oldaddr,
2106 sizeof(kpatch->oldaddr), label, 0);
2107 kpatch->type = KSPLICE_PATCH_TEXT;
2108 asymbol **symp = make_undefined_symbolp(sbfd, strdup(name));
2109 write_reloc(kpatch_ss, &kpatch->repladdr, symp, 0);
2110 write_patch_storage(kpatch_ss, kpatch, MAX_TRAMPOLINE_SIZE, NULL);
2113 void write_ksplice_export(struct superbfd *sbfd, struct span *span, bool del)
2115 struct supersect *kpatch_ss = make_section(sbfd, ".ksplice_patches");
2116 struct ksplice_patch *kpatch = sect_grow(kpatch_ss, 1,
2117 struct ksplice_patch);
2118 struct supersect *data_ss;
2120 const struct table_section *ts = get_table_section(span->ss->name);
2121 assert(ts != NULL);
2122 const char **addr =
2123 span->ss->contents.data + span->start + ts->other_offset;
2124 const char *symname = read_string(span->ss, addr);
2126 char *oldname, *newname;
2127 if (del) {
2128 oldname = strprintf("%s:%s", span->ss->name, symname);
2129 newname = strprintf("DISABLED_%s_%s", symname, kid);
2130 } else {
2131 oldname = strprintf("%s:DISABLED_%s_%s", span->ss->name,
2132 symname, kid);
2133 newname = strprintf("%s", symname);
2134 write_string(span->ss, addr, "DISABLED_%s_%s", symname, kid);
2137 write_ksplice_patch_reloc(kpatch_ss, "", &kpatch->oldaddr,
2138 sizeof(kpatch->oldaddr), oldname,
2139 ts->other_offset);
2140 kpatch->type = KSPLICE_PATCH_EXPORT;
2141 const char **namep = write_patch_storage(kpatch_ss, kpatch,
2142 sizeof(newname), &data_ss);
2143 write_string(data_ss, namep, "%s", newname);
2146 void filter_table_sections(struct superbfd *isbfd)
2148 struct supersect *tables_ss =
2149 fetch_supersect(offsets_sbfd,
2150 bfd_get_section_by_name(offsets_sbfd->abfd,
2151 ".ksplice_table_sections"));
2152 const struct table_section *ts;
2153 for (ts = tables_ss->contents.data;
2154 (void *)ts < tables_ss->contents.data + tables_ss->contents.size;
2155 ts++) {
2156 struct table_section s = *ts;
2157 s.sect = read_string(tables_ss, &ts->sect);
2158 s.other_sect = read_string(tables_ss, &ts->other_sect);
2159 s.crc_sect = read_string(tables_ss, &ts->crc_sect);
2160 filter_table_section(isbfd, &s);
2164 void filter_table_section(struct superbfd *sbfd, const struct table_section *s)
2166 asection *isection = bfd_get_section_by_name(sbfd->abfd, s->sect);
2167 if (isection == NULL)
2168 return;
2169 struct supersect *ss = fetch_supersect(sbfd, isection);
2171 void *entry;
2172 for (entry = ss->contents.data;
2173 entry < ss->contents.data + ss->contents.size;
2174 entry += s->entry_size) {
2175 struct span *span = find_span(ss, addr_offset(ss, entry));
2176 assert(span != NULL);
2178 if (s->has_addr) {
2179 struct span *sym_span =
2180 span_offset_target_span(span, s->addr_offset);
2181 assert(sym_span != NULL);
2182 if (sym_span->keep)
2183 keep_span(span);
2186 if (s->other_sect != NULL) {
2187 struct span *sym_span =
2188 span_offset_target_span(span, s->other_offset);
2189 assert(sym_span != NULL);
2190 if (span->keep)
2191 keep_span(sym_span);
2194 if (s->crc_sect != NULL) {
2195 struct span *crc_span = get_crc_span(span, s);
2196 assert(crc_span != NULL);
2197 if (span->keep && mode("keep-new-code"))
2198 keep_span(crc_span);
2203 static void match_table_spans(struct span *old_span, struct span *new_span)
2205 const struct table_section *ts = get_table_section(old_span->ss->name);
2207 if (strcmp(old_span->ss->name, new_span->ss->name) != 0)
2208 return;
2209 if (ts == NULL || old_span->ss->type != SS_TYPE_SPECIAL ||
2210 new_span->ss->type != SS_TYPE_SPECIAL)
2211 return;
2212 if (old_span->match != NULL || new_span->match != NULL)
2213 return;
2215 if (ts->has_addr) {
2216 void *old_entry = old_span->ss->contents.data + old_span->start;
2217 void *new_entry = new_span->ss->contents.data + new_span->start;
2218 arelent *old_reloc =
2219 find_reloc(old_span->ss, old_entry + ts->addr_offset);
2220 arelent *new_reloc =
2221 find_reloc(new_span->ss, new_entry + ts->addr_offset);
2222 assert(old_reloc != NULL && new_reloc != NULL);
2223 struct span *old_sym_span =
2224 reloc_target_span(old_span->ss, old_reloc);
2225 struct span *new_sym_span =
2226 reloc_target_span(new_span->ss, new_reloc);
2227 assert(old_sym_span != NULL && new_sym_span != NULL);
2228 if (old_sym_span->match == new_sym_span &&
2229 new_sym_span->match == old_sym_span &&
2230 old_reloc->address - old_sym_span->start ==
2231 new_reloc->address - new_sym_span->start)
2232 match_spans(old_span, new_span);
2236 static struct span *get_crc_span(struct span *span,
2237 const struct table_section *ts)
2239 void *entry = span->ss->contents.data + span->start;
2240 asection *crc_sect = bfd_get_section_by_name(span->ss->parent->abfd,
2241 ts->crc_sect);
2242 if (crc_sect == NULL)
2243 return NULL;
2244 struct supersect *crc_ss = fetch_supersect(span->ss->parent, crc_sect);
2245 if (crc_ss == NULL)
2246 return NULL;
2247 struct span *crc_span = find_span(crc_ss, addr_offset(span->ss, entry) /
2248 ts->entry_size * ts->crc_size);
2249 return crc_span;
2252 void mark_precallable_spans(struct superbfd *sbfd)
2254 asection *sect;
2255 struct supersect *ss, *sym_ss;
2256 struct span *address_span, *target_span;
2257 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2258 ss = fetch_supersect(sbfd, sect);
2259 arelent **relocp;
2260 if (ss->type == SS_TYPE_SPECIAL)
2261 continue;
2262 for (relocp = ss->relocs.data;
2263 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
2264 asymbol *sym = *(*relocp)->sym_ptr_ptr;
2265 address_span = find_span(ss, (*relocp)->address);
2266 if (!address_span->precallable)
2267 continue;
2268 target_span = reloc_target_span(ss, *relocp);
2269 if (target_span == NULL || target_span->keep)
2270 continue;
2271 sym_ss = fetch_supersect(sbfd, sym->section);
2272 if (sym_ss->type == SS_TYPE_IGNORED)
2273 continue;
2274 target_span->precallable = true;
2275 changed = true;
2280 void keep_referenced_sections(struct superbfd *sbfd)
2282 asection *sect;
2283 struct supersect *ss, *sym_ss;
2284 struct span *address_span, *target_span;
2285 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2286 ss = fetch_supersect(sbfd, sect);
2287 arelent **relocp;
2288 if (ss->type == SS_TYPE_SPECIAL)
2289 continue;
2290 for (relocp = ss->relocs.data;
2291 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
2292 asymbol *sym = *(*relocp)->sym_ptr_ptr;
2293 address_span = find_span(ss, (*relocp)->address);
2294 if (!address_span->keep)
2295 continue;
2296 target_span = reloc_target_span(ss, *relocp);
2297 if (target_span == NULL || target_span->keep)
2298 continue;
2299 sym_ss = fetch_supersect(sbfd, sym->section);
2300 if (sym_ss->type == SS_TYPE_IGNORED)
2301 continue;
2302 keep_span(target_span);
2303 changed = true;
2308 void copy_symbols(struct asymbolp_vec *osyms, struct asymbolpp_vec *isyms)
2310 asymbol ***sympp;
2311 for (sympp = isyms->data; sympp < isyms->data + isyms->size; sympp++)
2312 *vec_grow(osyms, 1) = **sympp;
2315 /* Modified function from GNU Binutils objcopy.c */
2316 bfd_boolean copy_object(bfd *ibfd, bfd *obfd)
2318 assert(bfd_set_format(obfd, bfd_get_format(ibfd)));
2320 bfd_vma start = bfd_get_start_address(ibfd);
2322 flagword flags = bfd_get_file_flags(ibfd);
2323 flags &= bfd_applicable_file_flags(obfd);
2325 assert(bfd_set_start_address(obfd, start)
2326 && bfd_set_file_flags(obfd, flags));
2328 enum bfd_architecture iarch = bfd_get_arch(ibfd);
2329 unsigned int imach = bfd_get_mach(ibfd);
2330 assert(bfd_set_arch_mach(obfd, iarch, imach));
2331 assert(bfd_set_format(obfd, bfd_get_format(ibfd)));
2333 /* BFD mandates that all output sections be created and sizes set before
2334 any output is done. Thus, we traverse all sections multiple times. */
2335 bfd_map_over_sections(ibfd, setup_section, obfd);
2337 struct supersect *new_supersects = fetch_superbfd(ibfd)->new_supersects;
2338 struct supersect *ss;
2339 for (ss = new_supersects; ss != NULL; ss = ss->next)
2340 setup_new_section(obfd, ss);
2342 /* Mark symbols used in output relocations so that they
2343 are kept, even if they are local labels or static symbols.
2345 Note we iterate over the input sections examining their
2346 relocations since the relocations for the output sections
2347 haven't been set yet. mark_symbols_used_in_relocations will
2348 ignore input sections which have no corresponding output
2349 section. */
2351 bfd_map_over_sections(ibfd, mark_symbols_used_in_relocations, NULL);
2352 for (ss = new_supersects; ss != NULL; ss = ss->next)
2353 ss_mark_symbols_used_in_relocations(ss);
2354 struct asymbolp_vec osyms;
2355 vec_init(&osyms);
2356 filter_symbols(ibfd, obfd, &osyms, &fetch_superbfd(ibfd)->syms);
2357 copy_symbols(&osyms, &fetch_superbfd(ibfd)->new_syms);
2359 bfd_set_symtab(obfd, osyms.data, osyms.size);
2361 /* This has to happen after the symbol table has been set. */
2362 bfd_map_over_sections(obfd, write_section, NULL);
2364 /* Allow the BFD backend to copy any private data it understands
2365 from the input BFD to the output BFD. This is done last to
2366 permit the routine to look at the filtered symbol table, which is
2367 important for the ECOFF code at least. */
2368 assert(bfd_copy_private_bfd_data(ibfd, obfd));
2370 return TRUE;
2373 /* Modified function from GNU Binutils objcopy.c */
2374 void setup_section(bfd *ibfd, asection *isection, void *obfdarg)
2376 struct superbfd *isbfd = fetch_superbfd(ibfd);
2377 struct supersect *ss = fetch_supersect(isbfd, isection);
2378 bfd *obfd = obfdarg;
2379 bfd_vma vma;
2381 if (!ss->keep)
2382 return;
2384 asection *osection = bfd_make_section_anyway(obfd, ss->name);
2385 assert(osection != NULL);
2387 osection->userdata = ss;
2388 bfd_set_section_flags(obfd, osection, ss->flags);
2389 ss->symbol = osection->symbol;
2390 assert(bfd_set_section_size(obfd, osection, ss->contents.size));
2392 vma = bfd_section_vma(ibfd, isection);
2393 assert(bfd_set_section_vma(obfd, osection, vma));
2395 osection->lma = isection->lma;
2396 assert(bfd_set_section_alignment(obfd, osection, ss->alignment));
2397 osection->entsize = ss->entsize;
2398 osection->output_section = osection;
2399 osection->output_offset = 0;
2400 isection->output_section = osection;
2401 isection->output_offset = 0;
2402 return;
2405 void setup_new_section(bfd *obfd, struct supersect *ss)
2407 asection *osection = bfd_make_section_anyway(obfd, ss->name);
2408 assert(osection != NULL);
2409 bfd_set_section_flags(obfd, osection, ss->flags);
2411 osection->userdata = ss;
2412 ss->symbol = osection->symbol;
2413 assert(bfd_set_section_size(obfd, osection, ss->contents.size));
2414 assert(bfd_set_section_vma(obfd, osection, 0));
2416 osection->lma = 0;
2417 assert(bfd_set_section_alignment(obfd, osection, ss->alignment));
2418 osection->entsize = ss->entsize;
2419 osection->output_section = osection;
2420 osection->output_offset = 0;
2423 static int compare_reloc_addresses(const void *aptr, const void *bptr)
2425 const arelent *const *a = aptr, *const *b = bptr;
2426 return (*a)->address - (*b)->address;
2429 static void delete_obsolete_relocs(struct supersect *ss)
2431 if (ss->new_relocs.size == 0)
2432 return;
2434 qsort(ss->relocs.data, ss->relocs.size, sizeof(*ss->relocs.data),
2435 compare_reloc_addresses);
2436 qsort(ss->new_relocs.data, ss->new_relocs.size,
2437 sizeof(*ss->new_relocs.data), compare_reloc_addresses);
2439 struct arelentp_vec orig_relocs;
2440 vec_move(&orig_relocs, &ss->relocs);
2442 arelent **relocp, **new_relocp = ss->new_relocs.data;
2443 for (relocp = orig_relocs.data;
2444 relocp < orig_relocs.data + orig_relocs.size; relocp++) {
2445 while (new_relocp < ss->new_relocs.data + ss->new_relocs.size &&
2446 (*new_relocp)->address < (*relocp)->address)
2447 new_relocp++;
2448 arelent *reloc = *relocp, *new_reloc = *new_relocp;
2449 if (new_relocp == ss->new_relocs.data + ss->new_relocs.size ||
2450 reloc->address != new_reloc->address)
2451 *vec_grow(&ss->relocs, 1) = reloc;
2455 void write_section(bfd *obfd, asection *osection, void *arg)
2457 struct supersect *ss = osection->userdata;
2459 if ((ss->flags & SEC_GROUP) != 0 || ss->contents.size == 0)
2460 return;
2462 delete_obsolete_relocs(ss);
2464 arelent **relocp;
2465 char *error_message;
2466 for (relocp = ss->new_relocs.data;
2467 relocp < ss->new_relocs.data + ss->new_relocs.size; relocp++) {
2468 bfd_vma val;
2469 if (bfd_get_arch(obfd) == bfd_arch_arm)
2470 val = osection->use_rela_p ? 0 : (*relocp)->addend;
2471 else
2472 val = 0;
2473 bfd_put(bfd_get_reloc_size((*relocp)->howto) * 8, obfd, val,
2474 ss->contents.data + (*relocp)->address);
2475 if (bfd_install_relocation(obfd, *relocp, ss->contents.data,
2476 0, osection, &error_message) !=
2477 bfd_reloc_ok) {
2478 err(ss->parent, "ksplice: error installing reloc: %s",
2479 error_message);
2480 DIE;
2482 if (mode("finalize")) {
2483 /* Check that all our sections will be allocated */
2484 asymbol *sym = *((*relocp)->sym_ptr_ptr);
2485 if (!bfd_is_const_section(sym->section)) {
2486 struct supersect *sym_ss =
2487 fetch_supersect(ss->parent, sym->section);
2488 assert((sym_ss->flags & SEC_ALLOC) != 0);
2492 memcpy(vec_grow(&ss->relocs, ss->new_relocs.size), ss->new_relocs.data,
2493 ss->new_relocs.size * sizeof(*ss->new_relocs.data));
2495 bfd_set_reloc(obfd, osection,
2496 ss->relocs.size == 0 ? NULL : ss->relocs.data,
2497 ss->relocs.size);
2499 if (ss->flags & SEC_HAS_CONTENTS)
2500 assert(bfd_set_section_contents
2501 (obfd, osection, ss->contents.data, 0,
2502 ss->contents.size));
2505 /* Modified function from GNU Binutils objcopy.c
2507 * Mark all the symbols which will be used in output relocations with
2508 * the BSF_KEEP flag so that those symbols will not be stripped.
2510 * Ignore relocations which will not appear in the output file.
2512 void mark_symbols_used_in_relocations(bfd *abfd, asection *isection,
2513 void *ignored)
2515 struct superbfd *sbfd = fetch_superbfd(abfd);
2516 if (isection->output_section == NULL)
2517 return;
2519 struct supersect *ss = fetch_supersect(sbfd, isection);
2520 ss_mark_symbols_used_in_relocations(ss);
2523 void ss_mark_symbols_used_in_relocations(struct supersect *ss)
2525 /* Examine each symbol used in a relocation. If it's not one of the
2526 special bfd section symbols, then mark it with BSF_KEEP. */
2527 arelent **relocp;
2528 for (relocp = ss->relocs.data;
2529 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
2530 asymbol *sym = *(*relocp)->sym_ptr_ptr;
2531 if (!(bfd_is_const_section(sym->section) &&
2532 sym == sym->section->symbol))
2533 sym->flags |= BSF_KEEP;
2535 for (relocp = ss->new_relocs.data;
2536 relocp < ss->new_relocs.data + ss->new_relocs.size; relocp++) {
2537 asymbol *sym = *(*relocp)->sym_ptr_ptr;
2538 if (!(bfd_is_const_section(sym->section) &&
2539 sym == sym->section->symbol))
2540 sym->flags |= BSF_KEEP;
2544 static bool deleted_table_section_symbol(bfd *abfd, asymbol *sym)
2546 struct superbfd *sbfd = fetch_superbfd(abfd);
2547 if (bfd_is_const_section(sym->section))
2548 return false;
2549 struct supersect *ss = fetch_supersect(sbfd, sym->section);
2551 asymbol **symp;
2552 for (symp = ss->syms.data; symp < ss->syms.data + ss->syms.size; symp++) {
2553 if (sym == *symp)
2554 break;
2556 return symp >= ss->syms.data + ss->syms.size &&
2557 (sym->flags & BSF_SECTION_SYM) == 0;
2560 void filter_symbols(bfd *ibfd, bfd *obfd, struct asymbolp_vec *osyms,
2561 struct asymbolp_vec *isyms)
2563 asymbol **symp;
2564 struct superbfd *sbfd = fetch_superbfd(ibfd);
2565 for (symp = isyms->data; symp < isyms->data + isyms->size; symp++) {
2566 asymbol *sym = *symp;
2567 struct supersect *sym_ss = NULL;
2568 struct span *sym_span = NULL;
2569 if (!bfd_is_const_section(sym->section)) {
2570 sym_ss = fetch_supersect(sbfd, sym->section);
2571 sym_span = find_span(sym_ss, sym->value);
2574 if (mode("keep") && (sym->flags & BSF_GLOBAL) != 0 &&
2575 !(mode("keep-new-code") && sym_span != NULL &&
2576 sym_span->new))
2577 sym->flags = (sym->flags & ~BSF_GLOBAL) | BSF_LOCAL;
2579 if (mode("finalize") && (sym->flags & BSF_GLOBAL) != 0)
2580 sym->flags = (sym->flags & ~BSF_GLOBAL) | BSF_LOCAL;
2582 bool keep = bfd_is_const_section(sym->section) ||
2583 (sym_ss->keep && (sym->flags & BSF_SECTION_SYM) != 0) ||
2584 (sym_span != NULL && sym_span->keep);
2585 if (bfd_is_und_section(sym->section) &&
2586 (sym->flags & BSF_KEEP) == 0)
2587 keep = false;
2588 if (bfd_is_abs_section(sym->section) &&
2589 (sym->flags & BSF_KEEP) == 0 &&
2590 (sym->flags & BSF_FILE) == 0)
2591 keep = false;
2592 if (deleted_table_section_symbol(ibfd, sym))
2593 keep = false;
2595 if (mode("keep-old-code") && sym_ss != NULL &&
2596 sym_ss->type == SS_TYPE_EXPORT)
2597 keep = false;
2599 if (keep) {
2600 if (sym_ss != NULL && !sym_ss->keep) {
2601 err(sbfd, "Kept symbol %s in unkept section "
2602 "%s\n", sym->name, sym->section->name);
2603 DIE;
2605 *vec_grow(osyms, 1) = sym;
2610 static bool is_table_section(const char *name, bool consider_other,
2611 bool consider_crc)
2613 struct supersect *tables_ss =
2614 fetch_supersect(offsets_sbfd,
2615 bfd_get_section_by_name(offsets_sbfd->abfd,
2616 ".ksplice_table_sections"));
2617 const struct table_section *ts;
2618 for (ts = tables_ss->contents.data;
2619 (void *)ts < tables_ss->contents.data + tables_ss->contents.size;
2620 ts++) {
2621 if (strcmp(name, read_string(tables_ss, &ts->sect)) == 0)
2622 return true;
2623 const char *osect_name = read_string(tables_ss,
2624 &ts->other_sect);
2625 if (consider_other && osect_name != NULL &&
2626 strcmp(name, osect_name) == 0)
2627 return true;
2628 const char *crc_name = read_string(tables_ss, &ts->crc_sect);
2629 if (consider_crc && crc_name != NULL &&
2630 strcmp(name, crc_name) == 0)
2631 return true;
2633 return false;
2636 const struct table_section *get_table_section(const char *name)
2638 struct supersect *tables_ss =
2639 fetch_supersect(offsets_sbfd,
2640 bfd_get_section_by_name(offsets_sbfd->abfd,
2641 ".ksplice_table_sections"));
2642 const struct table_section *ts;
2643 for (ts = tables_ss->contents.data;
2644 (void *)ts < tables_ss->contents.data + tables_ss->contents.size;
2645 ts++) {
2646 if (strcmp(name, read_string(tables_ss, &ts->sect)) == 0) {
2647 if (ts->entry_contents_size != 0)
2648 assert(align(ts->entry_contents_size,
2649 ts->entry_align) ==
2650 ts->entry_size);
2651 struct table_section *ns = malloc(sizeof(*ns));
2652 *ns = *ts;
2653 ns->sect = read_string(tables_ss, &ts->sect);
2654 ns->crc_sect = read_string(tables_ss, &ts->crc_sect);
2655 ns->other_sect =
2656 read_string(tables_ss, &ts->other_sect);
2657 return ns;
2660 return NULL;
2663 enum supersect_type supersect_type(struct supersect *ss)
2665 if (mode("finalize") &&
2666 strcmp(finalize_target, "vmlinux") == 0 &&
2667 (strstarts(ss->name, ".ksplice_relocs.exit") ||
2668 strstarts(ss->name, ".ksplice_sections.exit") ||
2669 strstarts(ss->name, ".ksplice_patches.exit")))
2670 return SS_TYPE_EXIT;
2671 if (strstarts(ss->name, ".ksplice_call"))
2672 return SS_TYPE_KSPLICE_CALL;
2673 if (strstarts(ss->name, ".ksplice_extract"))
2674 return SS_TYPE_KSPLICE_EXTRACT;
2675 if (strstarts(ss->name, ".ksplice_options"))
2676 return SS_TYPE_SPECIAL;
2677 if (strstarts(ss->name, ".ksplice"))
2678 return SS_TYPE_KSPLICE;
2680 if (strstarts(ss->name, ".init"))
2681 return SS_TYPE_IGNORED;
2682 if (strstarts(ss->name, ".security_initcall.init"))
2683 return SS_TYPE_IGNORED;
2684 if (strstarts(ss->name, ".con_initcall.init"))
2685 return SS_TYPE_IGNORED;
2686 if (strstarts(ss->name, ".x86cpuvendor.init"))
2687 return SS_TYPE_IGNORED;
2688 if (strstarts(ss->name, ".early_param.init"))
2689 return SS_TYPE_IGNORED;
2690 if (strstarts(ss->name, ".taglist.init"))
2691 return SS_TYPE_IGNORED;
2692 if (strstarts(ss->name, ".arch.info.init"))
2693 return SS_TYPE_IGNORED;
2694 if (strstarts(ss->name, ".proc.info.init"))
2695 return SS_TYPE_IGNORED;
2696 /* .pci_fixup_* sections really should be treated as global rodata
2697 referenced only from quirks.c */
2698 if (strstarts(ss->name, ".pci_fixup_"))
2699 return SS_TYPE_IGNORED;
2700 /* .builtin_fw sections are similar to .pci_fixup */
2701 if (strstarts(ss->name, ".builtin_fw"))
2702 return SS_TYPE_IGNORED;
2703 /* same for .tracedata */
2704 if (strstarts(ss->name, ".tracedata"))
2705 return SS_TYPE_IGNORED;
2706 if (strstarts(ss->name, ".debug"))
2707 return SS_TYPE_IGNORED;
2708 /* .eh_frame should probably be discarded, not ignored */
2709 if (strstarts(ss->name, ".eh_frame"))
2710 return SS_TYPE_IGNORED;
2711 if (config->ignore_devinit && strstarts(ss->name, ".devinit"))
2712 return SS_TYPE_IGNORED;
2713 if (config->ignore_meminit && strstarts(ss->name, ".meminit"))
2714 return SS_TYPE_IGNORED;
2715 if (config->ignore_cpuinit && strstarts(ss->name, ".cpuinit"))
2716 return SS_TYPE_IGNORED;
2717 if (config->ignore_devinit && strstarts(ss->name, ".devexit"))
2718 return SS_TYPE_IGNORED;
2719 if (config->ignore_meminit && strstarts(ss->name, ".memexit"))
2720 return SS_TYPE_IGNORED;
2721 if (config->ignore_cpuinit && strstarts(ss->name, ".cpuexit"))
2722 return SS_TYPE_IGNORED;
2723 if (strstarts(ss->name, ".vgetcpu_mode") ||
2724 strstarts(ss->name, ".jiffies") ||
2725 strstarts(ss->name, ".wall_jiffies") ||
2726 strstarts(ss->name, ".vxtime") ||
2727 strstarts(ss->name, ".sys_tz") ||
2728 strstarts(ss->name, ".sysctl_vsyscall") ||
2729 strstarts(ss->name, ".xtime") ||
2730 strstarts(ss->name, ".xtime_lock") ||
2731 strstarts(ss->name, ".vsyscall"))
2732 return SS_TYPE_IGNORED;
2733 if (strstarts(ss->name, ".vdso"))
2734 return SS_TYPE_IGNORED;
2736 if (strstarts(ss->name, ".exit.text"))
2737 return SS_TYPE_TEXT;
2738 if (strstarts(ss->name, ".exit.data"))
2739 return SS_TYPE_DATA;
2741 if (strstarts(ss->name, ".text") ||
2742 strstarts(ss->name, ".kernel.text") ||
2743 strstarts(ss->name, ".devinit.text") ||
2744 strstarts(ss->name, ".meminit.text") ||
2745 strstarts(ss->name, ".cpuinit.text") ||
2746 strstarts(ss->name, ".devexit.text") ||
2747 strstarts(ss->name, ".memexit.text") ||
2748 strstarts(ss->name, ".cpuexit.text") ||
2749 strstarts(ss->name, ".ref.text") ||
2750 strstarts(ss->name, ".spinlock.text") ||
2751 strstarts(ss->name, ".kprobes.text") ||
2752 strstarts(ss->name, ".sched.text") ||
2753 strstarts(ss->name, ".entry.text") || /* OpenVZ */
2754 (mode("keep-old-code") && strstarts(ss->name, ".fixup")))
2755 return SS_TYPE_TEXT;
2757 int n = -1;
2758 if (sscanf(ss->name, ".rodata.str%*u.%*u%n", &n) >= 0 &&
2759 n == strlen(ss->name))
2760 return ss->entsize == 1 ? SS_TYPE_STRING : SS_TYPE_RODATA;
2762 if (strstarts(ss->name, ".rodata") ||
2763 strstarts(ss->name, ".kernel.rodata") ||
2764 strstarts(ss->name, ".devinit.rodata") ||
2765 strstarts(ss->name, ".meminit.rodata") ||
2766 strstarts(ss->name, ".cpuinit.rodata") ||
2767 strstarts(ss->name, ".devexit.rodata") ||
2768 strstarts(ss->name, ".memexit.rodata") ||
2769 strstarts(ss->name, ".cpuexit.rodata") ||
2770 strstarts(ss->name, ".ref.rodata") ||
2771 strstarts(ss->name, "__markers_strings") ||
2772 (mode("keep-old-code") && strstarts(ss->name, "__ex_table")))
2773 return SS_TYPE_RODATA;
2775 if (strstarts(ss->name, ".bss"))
2776 return SS_TYPE_DATA;
2778 /* Ignore .data.percpu sections */
2779 if (strstarts(ss->name, ".data.percpu") ||
2780 strstarts(ss->name, ".kernel.data.percpu") ||
2781 strstarts(ss->name, ".data..percpu"))
2782 return SS_TYPE_IGNORED;
2783 if (strstarts(ss->name, ".data") ||
2784 strstarts(ss->name, ".kernel.data") ||
2785 strstarts(ss->name, ".devinit.data") ||
2786 strstarts(ss->name, ".cpuinit.data") ||
2787 strstarts(ss->name, ".meminit.data") ||
2788 strstarts(ss->name, ".devexit.data") ||
2789 strstarts(ss->name, ".memexit.data") ||
2790 strstarts(ss->name, ".cpuexit.data") ||
2791 strstarts(ss->name, ".ref.data") ||
2792 strstarts(ss->name, "__markers"))
2793 return SS_TYPE_DATA;
2795 /* We replace all the ksymtab strings, so delete them */
2796 if (strcmp(ss->name, "__ksymtab_strings") == 0)
2797 return SS_TYPE_STRING;
2798 if (strstarts(ss->name, "__ksymtab"))
2799 return SS_TYPE_EXPORT;
2801 if (strstarts(ss->name, "__bug_table"))
2802 return SS_TYPE_BUGTABLE;
2804 if (is_table_section(ss->name, true, true))
2805 return SS_TYPE_SPECIAL;
2807 if (strstarts(ss->name, ".ARM."))
2808 return SS_TYPE_SPECIAL;
2810 if (strstarts(ss->name, ".note"))
2811 return SS_TYPE_IGNORED;
2812 if (strstarts(ss->name, ".comment"))
2813 return SS_TYPE_IGNORED;
2814 if (strstarts(ss->name, "__param"))
2815 return SS_TYPE_IGNORED;
2816 if (strstarts(ss->name, "__obsparm"))
2817 return SS_TYPE_IGNORED;
2818 if (strstarts(ss->name, ".exitcall.exit"))
2819 return SS_TYPE_IGNORED;
2820 if (strstarts(ss->name, ".modinfo"))
2821 return SS_TYPE_IGNORED;
2823 return SS_TYPE_UNKNOWN;
2826 void initialize_supersect_types(struct superbfd *sbfd)
2828 asection *sect;
2829 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2830 struct supersect *ss = fetch_supersect(sbfd, sect);
2831 ss->type = supersect_type(ss);
2832 ss->orig_type = ss->type;
2833 if (ss->type == SS_TYPE_UNKNOWN) {
2834 err(sbfd, "Unknown section type: %s\n", ss->name);
2835 DIE;
2840 static void init_label_map(struct superbfd *sbfd)
2842 struct label_map *map;
2844 vec_init(&sbfd->maps);
2845 init_csyms(sbfd);
2846 init_callers(sbfd);
2848 struct symbol_hash csyms;
2849 symbol_hash_init(&csyms);
2851 asymbol **symp;
2852 for (symp = sbfd->syms.data;
2853 symp < sbfd->syms.data + sbfd->syms.size; symp++) {
2854 asymbol *csym = canonical_symbol(sbfd, *symp);
2855 if (csym == NULL)
2856 continue;
2857 char *key = strprintf("%p", csym);
2858 asymbol **csymp = symbol_hash_lookup(&csyms, key, TRUE);
2859 free(key);
2860 if (*csymp != NULL)
2861 continue;
2862 *csymp = csym;
2864 map = vec_grow(&sbfd->maps, 1);
2865 map->csym = csym;
2866 map->count = 0;
2867 map->label = symbol_label(sbfd, csym);
2870 struct label_mapp_hash label_maps;
2871 label_mapp_hash_init(&label_maps);
2872 for (map = sbfd->maps.data;
2873 map < sbfd->maps.data + sbfd->maps.size; map++) {
2874 struct label_map **mapp =
2875 label_mapp_hash_lookup(&label_maps, map->label, TRUE);
2876 if (*mapp == NULL) {
2877 *mapp = map;
2878 continue;
2881 struct label_map *first_map = *mapp;
2882 if (first_map->count == 0)
2883 first_map->label = strprintf("%s~%d", map->label, 0);
2884 map->label = strprintf("%s~%d", map->label, ++first_map->count);
2887 label_mapp_hash_init(&sbfd->maps_hash);
2888 for (map = sbfd->maps.data;
2889 map < sbfd->maps.data + sbfd->maps.size; map++) {
2890 char *key = strprintf("%p", map->csym);
2891 struct label_map **mapp =
2892 label_mapp_hash_lookup(&sbfd->maps_hash, key, TRUE);
2893 free(key);
2894 *mapp = map;
2895 map->orig_label = map->label;
2899 static const char *label_lookup(struct superbfd *sbfd, asymbol *sym)
2901 asymbol *csym = canonical_symbol(sbfd, sym);
2902 char *key = strprintf("%p", csym);
2903 struct label_map **mapp =
2904 label_mapp_hash_lookup(&sbfd->maps_hash, key, FALSE);
2905 free(key);
2906 if (mapp == NULL)
2907 DIE;
2908 return (*mapp)->label;
2911 static void print_label_changes(struct superbfd *sbfd)
2913 asection *sect;
2914 struct span *span;
2915 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2916 struct supersect *ss = fetch_supersect(sbfd, sect);
2917 for (span = ss->spans.data;
2918 span < ss->spans.data + ss->spans.size; span++) {
2919 if (strcmp(span->label, span->orig_label) != 0)
2920 debug1(sbfd, "Label change: %s -> %s\n",
2921 span->label, span->orig_label);
2926 static void label_map_set(struct superbfd *sbfd, const char *oldlabel,
2927 const char *label)
2929 struct label_map *map;
2930 for (map = sbfd->maps.data;
2931 map < sbfd->maps.data + sbfd->maps.size; map++) {
2932 if (strcmp(map->orig_label, oldlabel) == 0) {
2933 if (strcmp(map->orig_label, map->label) != 0 &&
2934 strcmp(map->label, label) != 0)
2935 DIE;
2936 map->label = label;
2937 return;
2940 DIE;
2943 static void change_initial_label(struct span *span, const char *label)
2945 struct superbfd *sbfd = span->ss->parent;
2946 span->label = label;
2947 span->orig_label = label;
2948 if (span->symbol) {
2949 asymbol *csym = canonical_symbol(sbfd, span->symbol);
2950 char *key = strprintf("%p", csym);
2951 struct label_map **mapp =
2952 label_mapp_hash_lookup(&sbfd->maps_hash, key, FALSE);
2953 free(key);
2954 assert(mapp);
2955 (*mapp)->label = span->label;
2956 (*mapp)->orig_label = span->orig_label;
2957 span->symbol = NULL;
2961 static void init_callers(struct superbfd *sbfd)
2963 string_hash_init(&sbfd->callers);
2964 asection *sect;
2965 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2966 struct supersect *ss = fetch_supersect(sbfd, sect);
2967 arelent **relocp;
2968 for (relocp = ss->relocs.data;
2969 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
2970 asymbol *sym = *(*relocp)->sym_ptr_ptr;
2971 unsigned long val =
2972 sym->value + reloc_target_offset(ss, *relocp);
2973 char *key = strprintf("%s+%lx", sym->section->name,
2974 val);
2975 const char **ret = string_hash_lookup(&sbfd->callers,
2976 key, TRUE);
2977 free(key);
2978 asymbol *csym = canonical_symbol(sbfd, sect->symbol);
2979 if (*ret != NULL)
2980 *ret = "*multiple_callers*";
2981 else if (static_local_symbol(sbfd, csym))
2982 *ret = static_local_symbol(sbfd, csym);
2983 else
2984 *ret = sect->name;
2989 static const char *find_caller(struct supersect *ss, asymbol *sym)
2991 char *key = strprintf("%s+%lx", sym->section->name,
2992 (unsigned long)sym->value);
2993 const char **ret = string_hash_lookup(&ss->parent->callers, key, FALSE);
2994 free(key);
2996 if (ret == NULL)
2997 return "*no_caller*";
2998 return *ret;
3001 static void init_csyms(struct superbfd *sbfd)
3003 asymbolpp_hash_init(&sbfd->csyms);
3005 asymbol **symp;
3006 for (symp = sbfd->syms.data; symp < sbfd->syms.data + sbfd->syms.size;
3007 symp++) {
3008 asymbol *sym = *symp;
3009 if ((sym->flags & BSF_DEBUGGING) != 0)
3010 continue;
3011 char *key = strprintf("%s+%lx", sym->section->name,
3012 (unsigned long)sym->value);
3013 asymbol ***csympp = asymbolpp_hash_lookup(&sbfd->csyms, key,
3014 TRUE);
3015 free(key);
3016 if (*csympp == NULL) {
3017 *csympp = symp;
3018 continue;
3020 asymbol *csym = **csympp;
3021 if ((csym->flags & BSF_GLOBAL) != 0)
3022 continue;
3023 if ((sym->flags & BSF_GLOBAL) != 0)
3024 *csympp = symp;
3028 static asymbol **symbolp_scan(struct supersect *ss, bfd_vma value)
3030 char *key = strprintf("%s+%lx", ss->name, (unsigned long)value);
3031 asymbol ***csympp =
3032 asymbolpp_hash_lookup(&ss->parent->csyms, key, FALSE);
3033 free(key);
3034 if (csympp != NULL)
3035 return *csympp;
3037 /* For section symbols of sections containing no symbols, return the
3038 section symbol that relocations are generated against */
3039 if (value == 0)
3040 return &ss->symbol;
3041 return NULL;
3044 static asymbol **canonical_symbolp(struct superbfd *sbfd, asymbol *sym)
3046 if (bfd_is_const_section(sym->section)) {
3047 asymbol **csymp;
3048 for (csymp = sbfd->syms.data;
3049 csymp < sbfd->syms.data + sbfd->syms.size; csymp++) {
3050 if (sym == *csymp)
3051 return csymp;
3053 return NULL;
3055 return symbolp_scan(fetch_supersect(sbfd, sym->section), sym->value);
3058 static asymbol *canonical_symbol(struct superbfd *sbfd, asymbol *sym)
3060 if (bfd_is_const_section(sym->section))
3061 return sym;
3062 asymbol **symp = canonical_symbolp(sbfd, sym);
3063 return symp != NULL ? *symp : NULL;
3066 static char *static_local_symbol(struct superbfd *sbfd, asymbol *sym)
3068 struct supersect *ss = fetch_supersect(sbfd, sym->section);
3069 if ((sym->flags & BSF_LOCAL) == 0 || (sym->flags & BSF_OBJECT) == 0)
3070 return NULL;
3071 char *dot = strrchr(sym->name, '.');
3072 if (dot == NULL || dot[1 + strspn(dot + 1, "0123546789")] != '\0')
3073 return NULL;
3074 char *basename = strndup(sym->name, dot - sym->name);
3076 /* Handle C.123.12345 symbols */
3077 dot = strrchr(basename, '.');
3078 if (dot != NULL && dot[1 + strspn(dot + 1, "0123546789")] == '\0')
3079 basename = strndup(basename, dot - basename);
3080 const char *caller;
3081 if (strcmp(basename, "__func__") == 0 ||
3082 strcmp(basename, "__PRETTY_FUNCTION__") == 0)
3083 caller = (const char *)ss->contents.data + sym->value;
3084 else
3085 caller = find_caller(ss, sym);
3086 return strprintf("%s<%s>", basename, caller);
3089 static char *symbol_label(struct superbfd *sbfd, asymbol *sym)
3091 const char *filename = sbfd->abfd->filename;
3092 char *c = strstr(filename, ".KSPLICE");
3093 int flen = (c == NULL ? strlen(filename) : c - filename);
3095 char *label;
3096 if (bfd_is_und_section(sym->section) || (sym->flags & BSF_GLOBAL) != 0) {
3097 label = strdup(sym->name);
3098 } else if (bfd_is_const_section(sym->section)) {
3099 label = strprintf("%s<%.*s>", sym->name, flen, filename);
3100 } else {
3101 asymbol *gsym = canonical_symbol(sbfd, sym);
3103 if (gsym == NULL)
3104 label = strprintf("%s+%lx<%.*s>",
3105 sym->section->name,
3106 (unsigned long)sym->value,
3107 flen, filename);
3108 else if ((gsym->flags & BSF_GLOBAL) != 0)
3109 label = strdup(gsym->name);
3110 else if (static_local_symbol(sbfd, gsym))
3111 label = strprintf("%s+%lx<%.*s>",
3112 static_local_symbol(sbfd, gsym),
3113 (unsigned long)sym->value,
3114 flen, filename);
3115 else
3116 label = strprintf("%s<%.*s>",
3117 gsym->name, flen, filename);
3120 return label;
3123 static void keep_span(struct span *span)
3125 span->keep = true;
3126 span->ss->keep = true;
3129 static struct span *new_span(struct supersect *ss, bfd_vma start, bfd_vma size)
3131 struct span *span = vec_grow(&ss->spans, 1);
3132 span->size = size;
3133 span->contents_size = size;
3134 span->start = start;
3135 span->ss = ss;
3136 span->keep = true;
3137 span->new = false;
3138 span->patch = false;
3139 span->bugpatch = false;
3140 span->datapatch = false;
3141 span->precallable = strstarts(ss->name, ".ksplice_call_pre_apply") ||
3142 strstarts(ss->name, ".ksplice_call_check_apply") ||
3143 strstarts(ss->name, ".ksplice_call_fail_apply") ||
3144 strstarts(ss->name, ".ksplice_call_post_remove");
3145 span->match = NULL;
3146 vec_init(&span->entry_points);
3147 span->shift = 0;
3148 asymbol **symp = symbolp_scan(ss, span->start);
3149 if (symp != NULL) {
3150 span->symbol = *symp;
3151 span->label = label_lookup(ss->parent, span->symbol);
3152 } else {
3153 span->symbol = NULL;
3154 const char *label = label_lookup(ss->parent, ss->symbol);
3155 if (span->start != 0)
3156 span->label = strprintf("%s<span:%lx>", label,
3157 (unsigned long)span->start);
3158 else
3159 span->label = label;
3161 span->orig_label = span->label;
3162 return span;
3165 static void initialize_string_spans(struct supersect *ss)
3167 const char *str;
3168 for (str = ss->contents.data;
3169 (void *)str < ss->contents.data + ss->contents.size;) {
3170 bfd_vma start = (unsigned long)str -
3171 (unsigned long)ss->contents.data;
3172 bfd_vma size = strlen(str) + 1;
3173 bfd_vma contents_size = size;
3174 while ((start + size) % (1 << ss->alignment) != 0 &&
3175 start + size < ss->contents.size) {
3176 /* Some string sections, like __ksymtab_strings, only
3177 align some strings with the declared alignment */
3178 if (str[size] != '\0')
3179 break;
3180 size++;
3182 struct span *span = new_span(ss, start, size);
3183 span->contents_size = contents_size;
3184 str += size;
3188 static int compare_ulongs(const void *va, const void *vb)
3190 const unsigned long *a = va, *b = vb;
3191 return *a - *b;
3194 static void initialize_table_spans(struct superbfd *sbfd,
3195 struct table_section *s)
3197 asection *isection = bfd_get_section_by_name(sbfd->abfd, s->sect);
3198 if (isection == NULL)
3199 return;
3200 struct supersect *ss = fetch_supersect(sbfd, isection);
3201 if (ss->alignment < ffs(s->entry_align) - 1)
3202 ss->alignment = ffs(s->entry_align) - 1;
3204 asection *other_sect = NULL;
3205 if (s->other_sect != NULL)
3206 other_sect = bfd_get_section_by_name(sbfd->abfd, s->other_sect);
3207 struct supersect *other_ss = NULL;
3208 if (other_sect != NULL)
3209 other_ss = fetch_supersect(sbfd, other_sect);
3211 asection *crc_sect = NULL;
3212 if (s->crc_sect != NULL)
3213 crc_sect = bfd_get_section_by_name(sbfd->abfd, s->crc_sect);
3214 struct supersect *crc_ss = NULL;
3215 if (crc_sect != NULL)
3216 crc_ss = fetch_supersect(sbfd, crc_sect);
3218 struct ulong_vec offsets;
3219 vec_init(&offsets);
3221 void *entry;
3222 for (entry = ss->contents.data;
3223 entry < ss->contents.data + ss->contents.size;
3224 entry += s->entry_size) {
3225 struct span *span = new_span(ss, addr_offset(ss, entry),
3226 s->entry_size);
3227 if (s->entry_contents_size != 0)
3228 span->contents_size = s->entry_contents_size;
3229 if ((span->symbol == NULL ||
3230 (span->symbol->flags & BSF_SECTION_SYM) != 0) &&
3231 s->has_addr) {
3232 arelent *reloc = find_reloc(ss, entry + s->addr_offset);
3233 assert(reloc);
3234 struct span *target_span = reloc_target_span(ss, reloc);
3235 assert(target_span);
3236 asymbol *sym = *reloc->sym_ptr_ptr;
3237 unsigned long val = sym->value +
3238 reloc_target_offset(ss, reloc) -
3239 (target_span->start + target_span->shift);
3240 char *label = strprintf("%s<target:%s+%lx>", ss->name,
3241 target_span->label, val);
3242 change_initial_label(span, label);
3245 if (other_sect != NULL) {
3246 asymbol *sym;
3247 bfd_vma offset = read_reloc(ss, entry + s->other_offset,
3248 sizeof(void *), &sym);
3249 if (sym->section == other_sect) {
3250 assert(offset >= 0 &&
3251 offset < other_ss->contents.size);
3252 *vec_grow(&offsets, 1) = offset;
3256 if (crc_sect != NULL)
3257 new_span(crc_ss, addr_offset(ss, entry) / s->entry_size
3258 * s->crc_size, s->crc_size);
3260 if (ss->type == SS_TYPE_EXPORT) {
3261 const char *symname = read_string(ss, entry +
3262 s->other_offset);
3263 char *label = strprintf("%s:%s", ss->name, symname);
3264 change_initial_label(span, label);
3268 if (other_sect == NULL)
3269 return;
3271 *vec_grow(&offsets, 1) = 0;
3272 qsort(offsets.data, offsets.size, sizeof(*offsets.data),
3273 compare_ulongs);
3274 *vec_grow(&offsets, 1) = other_ss->contents.size;
3276 unsigned long *off;
3277 for (off = offsets.data; off < offsets.data + offsets.size - 1; off++) {
3278 if (*off != *(off + 1))
3279 new_span(other_ss, *off, *(off + 1) - *off);
3283 static void initialize_table_section_spans(struct superbfd *sbfd)
3285 struct supersect *tables_ss =
3286 fetch_supersect(offsets_sbfd,
3287 bfd_get_section_by_name(offsets_sbfd->abfd,
3288 ".ksplice_table_sections"));
3289 const struct table_section *ts;
3290 struct table_section s;
3291 for (ts = tables_ss->contents.data;
3292 (void *)ts < tables_ss->contents.data + tables_ss->contents.size;
3293 ts++) {
3294 s = *ts;
3295 s.sect = read_string(tables_ss, &ts->sect);
3296 s.other_sect = read_string(tables_ss, &ts->other_sect);
3297 s.crc_sect = read_string(tables_ss, &ts->crc_sect);
3298 initialize_table_spans(sbfd, &s);
3302 static void initialize_ksplice_call_spans(struct supersect *ss)
3304 arelent **relocp;
3305 for (relocp = ss->relocs.data;
3306 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
3307 arelent *reloc = *relocp;
3308 new_span(ss, reloc->address, bfd_get_reloc_size(reloc->howto));
3309 /* the span labels should already be unique */
3313 static void initialize_spans(struct superbfd *sbfd)
3315 asection *sect;
3316 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
3317 if (is_table_section(sect->name, true, true) && mode("keep"))
3318 continue;
3320 struct supersect *ss = fetch_supersect(sbfd, sect);
3321 if (ss->type == SS_TYPE_STRING)
3322 initialize_string_spans(ss);
3323 else if (ss->type == SS_TYPE_KSPLICE_CALL)
3324 initialize_ksplice_call_spans(ss);
3325 else
3326 new_span(ss, 0, ss->contents.size);
3328 if (mode("keep"))
3329 initialize_table_section_spans(sbfd);
3332 /* Returns the span pointed to by the relocation at span->start + offset */
3333 static struct span *span_offset_target_span(struct span *span, int offset)
3335 void *entry = span->ss->contents.data + span->start;
3336 arelent *reloc = find_reloc(span->ss, entry + offset);
3337 if (reloc == NULL)
3338 return NULL;
3339 return reloc_target_span(span->ss, reloc);
3342 struct span *reloc_target_span(struct supersect *ss, arelent *reloc)
3344 asymbol *sym_ptr = *reloc->sym_ptr_ptr;
3345 if (bfd_is_const_section(sym_ptr->section))
3346 return NULL;
3348 bfd_vma addend = sym_ptr->value + reloc_target_offset(ss, reloc);
3349 struct supersect *sym_ss =
3350 fetch_supersect(ss->parent, sym_ptr->section);
3351 struct span *span, *target_span = sym_ss->spans.data;
3352 for (span = sym_ss->spans.data;
3353 span < sym_ss->spans.data + sym_ss->spans.size; span++) {
3354 if (addend >= span->start && addend < span->start + span->size)
3355 target_span = span;
3357 return target_span;
3360 static bfd_vma reloc_target_offset(struct supersect *ss, arelent *reloc)
3362 bfd_vma offset = reloc_offset(ss, reloc);
3363 if (reloc->howto->pc_relative) {
3364 if ((ss->flags & SEC_CODE) != 0)
3365 return offset + bfd_get_reloc_size(reloc->howto);
3367 const struct table_section *ts = get_table_section(ss->name);
3368 if (ts != NULL && ts->relative_addr &&
3369 reloc->address % ts->entry_size == ts->addr_offset)
3370 return offset - ts->addr_offset;
3371 if (ts != NULL && ts->relative_other &&
3372 reloc->address % ts->entry_size == ts->other_offset)
3373 return offset - ts->other_offset;
3375 DIE;
3377 return offset;
3380 struct span *find_span(struct supersect *ss, bfd_size_type address)
3382 struct span *span;
3383 for (span = ss->spans.data; span < ss->spans.data + ss->spans.size;
3384 span++) {
3385 if (address >= span->start &&
3386 address < span->start + span->size)
3387 return span;
3389 /* Deal with empty BSS sections */
3390 if (ss->contents.size == 0 && ss->spans.size > 0)
3391 return ss->spans.data;
3392 /* Deal with section end pointers */
3393 if (address == ss->contents.size && ss->spans.size == 1)
3394 return ss->spans.data;
3395 return NULL;
3398 void compute_span_shifts(struct superbfd *sbfd)
3400 asection *sect;
3401 struct span *span;
3402 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
3403 struct supersect *ss = fetch_supersect(sbfd, sect);
3404 if (!ss->keep)
3405 continue;
3406 bfd_size_type offset = 0;
3407 for (span = ss->spans.data;
3408 span < ss->spans.data + ss->spans.size; span++) {
3409 if (!span->keep)
3410 continue;
3411 span->shift = offset - span->start;
3412 offset += span->size;
3417 void remove_unkept_spans(struct superbfd *sbfd)
3419 asection *sect;
3420 struct span *span;
3421 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
3422 struct supersect *ss = fetch_supersect(sbfd, sect);
3423 delete_obsolete_relocs(ss);
3424 struct arelentp_vec orig_relocs;
3425 vec_move(&orig_relocs, &ss->relocs);
3426 arelent **relocp, *reloc;
3427 for (relocp = orig_relocs.data;
3428 relocp < orig_relocs.data + orig_relocs.size; relocp++) {
3429 reloc = *relocp;
3430 asymbol *sym = *reloc->sym_ptr_ptr;
3431 span = reloc_target_span(ss, reloc);
3432 if ((span != NULL && span->keep && span->shift == 0) ||
3433 bfd_is_const_section(sym->section)) {
3434 *vec_grow(&ss->relocs, 1) = reloc;
3435 continue;
3437 struct supersect *sym_ss =
3438 fetch_supersect(sbfd, sym->section);
3439 if (span != NULL && (sym->flags & BSF_SECTION_SYM) == 0
3440 && find_span(sym_ss, sym->value) != span) {
3441 err(sbfd, "Spans for symbol %s and relocation "
3442 "target do not match in sect %s\n",
3443 sym->name, sym_ss->name);
3444 DIE;
3446 if (span != NULL && span->keep) {
3447 arelent *new_reloc = malloc(sizeof(*new_reloc));
3448 *new_reloc = *reloc;
3449 new_reloc->addend = reloc_offset(ss, reloc);
3450 new_reloc->addend += span->shift;
3451 *vec_grow(&ss->new_relocs, 1) = new_reloc;
3456 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
3457 struct supersect *ss = fetch_supersect(sbfd, sect), orig_ss;
3458 if (!ss->keep)
3459 continue;
3460 supersect_move(&orig_ss, ss);
3461 vec_init(&ss->spans);
3462 for (span = orig_ss.spans.data;
3463 span < orig_ss.spans.data + orig_ss.spans.size; span++) {
3464 if (!span->keep)
3465 continue;
3466 struct span *new_span = vec_grow(&ss->spans, 1);
3467 *new_span = *span;
3468 new_span->start = span->start + span->shift;
3469 new_span->shift = 0;
3470 sect_copy(ss, sect_do_grow(ss, 1, span->size, 1),
3471 &orig_ss, orig_ss.contents.data + span->start,
3472 span->size);
3477 static void init_objmanip_superbfd(struct superbfd *sbfd)
3479 init_label_map(sbfd);
3480 initialize_supersect_types(sbfd);
3481 initialize_spans(sbfd);
3482 load_options(sbfd);
3483 compute_entry_points(sbfd);
3486 void mangle_section_name(struct superbfd *sbfd, const char *name)
3488 asection *sect = bfd_get_section_by_name(sbfd->abfd, name);
3489 if (sect == NULL)
3490 return;
3491 struct supersect *ss = fetch_supersect(sbfd, sect);
3492 ss->name = strprintf(".ksplice_pre.%s", ss->name);
3495 static void write_bugline_patches(struct superbfd *sbfd)
3497 const struct table_section *ts = get_table_section("__bug_table");
3498 asection *sect = bfd_get_section_by_name(sbfd->abfd, "__bug_table");
3499 if (sect == NULL)
3500 return;
3501 struct supersect *ss = fetch_supersect(sbfd, sect);
3502 assert(ts != NULL);
3504 void *entry;
3505 for (entry = ss->contents.data;
3506 entry < ss->contents.data + ss->contents.size;
3507 entry += ts->entry_size) {
3508 struct span *span = find_span(ss, addr_offset(ss, entry));
3509 assert(span != NULL);
3510 if (!span->bugpatch)
3511 continue;
3512 arelent *reloc = find_reloc(ss, entry + ts->addr_offset);
3513 assert(reloc != NULL);
3514 asymbol *sym = *reloc->sym_ptr_ptr;
3515 assert(!bfd_is_const_section(sym->section));
3516 struct supersect *kpatch_ss =
3517 make_section(sbfd, ".ksplice_patches%s",
3518 sym->section->name);
3520 bfd_vma offset, start = 0;
3521 for (offset = 0; offset <= span->size; offset++) {
3522 if (offset != span->size &&
3523 !part_of_reloc(ss, span->start + offset))
3524 continue;
3525 if (start == offset) {
3526 start++;
3527 continue;
3529 /* an interval of non-relocations just passed */
3530 struct ksplice_patch *kpatch =
3531 sect_grow(kpatch_ss, 1, struct ksplice_patch);
3532 write_ksplice_patch_reloc
3533 (kpatch_ss, sym->section->name, &kpatch->oldaddr,
3534 sizeof(kpatch->oldaddr), span->label, start);
3536 char *data = write_patch_storage(kpatch_ss, kpatch,
3537 offset - start, NULL);
3538 memcpy(data, entry + start, offset - start);
3539 kpatch->type = KSPLICE_PATCH_DATA;
3540 start = offset + 1;
3545 void *write_patch_storage(struct supersect *ss, struct ksplice_patch *kpatch,
3546 size_t size, struct supersect **data_ssp)
3548 struct supersect *data_ss = make_section(ss->parent,
3549 ".ksplice_patch_data");
3550 char *saved = sect_do_grow(data_ss, 1, size, 1);
3551 write_reloc(ss, &kpatch->saved, &data_ss->symbol,
3552 addr_offset(data_ss, saved));
3553 char *data = sect_do_grow(data_ss, 1, size, 1);
3554 write_reloc(ss, &kpatch->contents, &data_ss->symbol,
3555 addr_offset(data_ss, data));
3556 kpatch->size = size;
3557 if (data_ssp != NULL)
3558 *data_ssp = data_ss;
3559 return data;