undo: clean up even if sysfs already gone
[ksplice.git] / objmanip.c
blobfe0ecca55682028e525371c39cfd4e3e56120e85
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 long offset);
156 static void write_bugline_patches(struct superbfd *sbfd);
157 asymbol **make_undefined_symbolp(struct superbfd *sbfd, const char *name);
158 void filter_table_sections(struct superbfd *isbfd);
159 void filter_table_section(struct superbfd *sbfd, const struct table_section *s);
160 void keep_referenced_sections(struct superbfd *sbfd);
161 void mark_precallable_spans(struct superbfd *sbfd);
162 bfd_boolean copy_object(bfd *ibfd, bfd *obfd);
163 void setup_section(bfd *ibfd, asection *isection, void *obfdarg);
164 static void setup_new_section(bfd *obfd, struct supersect *ss);
165 static void write_section(bfd *obfd, asection *osection, void *arg);
166 static void delete_obsolete_relocs(struct supersect *ss);
167 void mark_symbols_used_in_relocations(bfd *abfd, asection *isection,
168 void *ignored);
169 static void ss_mark_symbols_used_in_relocations(struct supersect *ss);
170 void filter_symbols(bfd *ibfd, bfd *obfd, struct asymbolp_vec *osyms,
171 struct asymbolp_vec *isyms);
172 static bool deleted_table_section_symbol(bfd *abfd, asymbol *sym);
173 struct supersect *__attribute((format(printf, 2, 3)))
174 make_section(struct superbfd *sbfd, const char *fmt, ...);
175 void __attribute__((format(printf, 3, 4)))
176 write_string(struct supersect *ss, const char **addr, const char *fmt, ...);
177 void write_ksplice_export(struct superbfd *sbfd, struct span *span, bool del);
178 void write_reloc(struct supersect *ss, const void *addr, asymbol **symp,
179 bfd_vma offset);
180 arelent *create_reloc(struct supersect *ss, const void *addr, asymbol **symp,
181 bfd_vma offset);
182 static void foreach_symbol_pair(struct superbfd *oldsbfd, struct superbfd *newsbfd,
183 void (*fn)(struct span *old_span,
184 asymbol *oldsym,
185 struct span *new_span,
186 asymbol *newsym));
187 static void check_global_symbols(struct span *old_span, asymbol *oldsym,
188 struct span *new_span, asymbol *newsym);
189 static void match_global_symbols(struct span *old_span, asymbol *oldsym,
190 struct span *new_span, asymbol *newsym);
191 static void match_symbol_spans(struct span *old_span, asymbol *oldsym,
192 struct span *new_span, asymbol *newsym);
193 static void match_table_spans(struct span *old_span, struct span *new_span);
194 static void match_other_spans(struct span *old_span, struct span *new_span);
196 static struct span *get_crc_span(struct span *span,
197 const struct table_section *ts);
198 static void foreach_span_pair(struct superbfd *oldsbfd,
199 struct superbfd *newsbfd,
200 void (*fn)(struct span *old_span,
201 struct span *new_span));
202 static void match_spans_by_label(struct span *old_span, struct span *new_span);
203 static void match_string_spans(struct span *old_span, struct span *new_span);
204 static void mark_new_spans(struct superbfd *sbfd);
205 static void handle_deleted_spans(struct superbfd *oldsbfd,
206 struct superbfd *newsbfd);
207 static void unmatch_addr_spans(struct span *old_span, struct span *new_span,
208 const struct table_section *ts);
209 static void compare_matched_spans(struct superbfd *newsbfd);
210 static void compare_spans(struct span *old_span, struct span *new_span);
211 static void update_nonzero_offsets(struct superbfd *sbfd);
212 static void handle_nonzero_offset_relocs(struct supersect *ss);
213 static void keep_span(struct span *span);
215 static void init_objmanip_superbfd(struct superbfd *sbfd);
216 static const char *label_lookup(struct superbfd *sbfd, asymbol *sym);
217 static void label_map_set(struct superbfd *sbfd, const char *oldlabel,
218 const char *label);
219 static void print_label_changes(struct superbfd *sbfd);
220 static void init_label_map(struct superbfd *sbfd);
221 static void change_initial_label(struct span *span, const char *label);
222 static asymbol **symbolp_scan(struct supersect *ss, bfd_vma value);
223 static void init_csyms(struct superbfd *sbfd);
224 static void init_callers(struct superbfd *sbfd);
225 static asymbol *canonical_symbol(struct superbfd *sbfd, asymbol *sym);
226 static asymbol **canonical_symbolp(struct superbfd *sbfd, asymbol *sym);
227 static char *static_local_symbol(struct superbfd *sbfd, asymbol *sym);
228 static char *symbol_label(struct superbfd *sbfd, asymbol *sym);
230 int verbose = 0;
231 #define debug_(sbfd, level, fmt, ...) \
232 do { \
233 if (verbose >= (level)) \
234 printf("%s: " fmt, (sbfd)->abfd->filename, \
235 ## __VA_ARGS__); \
236 } while (0)
237 #define debug0(sbfd, fmt, ...) debug_(sbfd, 0, fmt, ## __VA_ARGS__)
238 #define debug1(sbfd, fmt, ...) debug_(sbfd, 1, fmt, ## __VA_ARGS__)
239 #define err(sbfd, fmt, ...) \
240 do { \
241 fprintf(stderr, "%s: " fmt, (sbfd)->abfd->filename, \
242 ## __VA_ARGS__); \
243 } while (0)
245 struct str_vec delsects;
246 struct asymbolp_vec extract_syms;
247 bool changed;
249 struct ksplice_config *config;
251 const char *modestr, *kid, *finalize_target = NULL;
252 bool write_output = true;
254 struct superbfd *offsets_sbfd = NULL;
256 #define mode(str) strstarts(modestr, str)
258 DECLARE_VEC_TYPE(unsigned long, addr_vec);
259 DEFINE_HASH_TYPE(struct addr_vec, addr_vec_hash,
260 addr_vec_hash_init, addr_vec_hash_free, addr_vec_hash_lookup,
261 vec_init);
262 struct addr_vec_hash system_map;
264 struct bool_hash system_map_written;
265 struct ulong_hash ksplice_symbol_offset;
266 struct ulong_hash ksplice_howto_offset;
267 struct ulong_hash ksplice_string_offset;
269 void load_system_map()
271 const char *config_dir = getenv("KSPLICE_CONFIG_DIR");
272 assert(config_dir);
273 FILE *fp = fopen(strprintf("%s/System.map", config_dir), "r");
274 assert(fp);
275 addr_vec_hash_init(&system_map);
276 unsigned long addr;
277 char type;
278 char *sym;
279 while (fscanf(fp, "%lx %c %as\n", &addr, &type, &sym) == 3)
280 *vec_grow(addr_vec_hash_lookup(&system_map, sym, TRUE),
281 1) = addr;
282 fclose(fp);
285 void load_ksplice_symbol_offsets(struct superbfd *sbfd)
287 asection *sect = bfd_get_section_by_name(sbfd->abfd,
288 ".ksplice_symbols");
289 if (sect == NULL)
290 return;
291 struct supersect *ss = fetch_supersect(sbfd, sect);
293 struct ksplice_symbol *ksym;
294 for (ksym = ss->contents.data;
295 (void *)ksym < ss->contents.data + ss->contents.size; ksym++) {
296 const char *label = read_string(ss, &ksym->label);
297 unsigned long *ksymbol_offp =
298 ulong_hash_lookup(&ksplice_symbol_offset, label, TRUE);
299 *ksymbol_offp = addr_offset(ss, ksym);
303 void load_offsets()
305 char *kmodsrc = getenv("KSPLICE_KMODSRC");
306 assert(kmodsrc != NULL);
307 bfd *offsets_bfd = bfd_openr(strprintf("%s/offsets.o", kmodsrc), NULL);
308 assert(offsets_bfd != NULL);
309 char **matching;
310 assert(bfd_check_format_matches(offsets_bfd, bfd_object, &matching));
311 offsets_sbfd = fetch_superbfd(offsets_bfd);
313 asection *config_sect = bfd_get_section_by_name(offsets_sbfd->abfd,
314 ".ksplice_config");
315 struct supersect *config_ss =
316 fetch_supersect(offsets_sbfd, config_sect);
318 config = config_ss->contents.data;
321 void load_options(struct superbfd *sbfd)
323 asection *sect = bfd_get_section_by_name(sbfd->abfd,
324 ".ksplice_options");
325 if (sect == NULL)
326 return;
327 struct supersect *ss = fetch_supersect(sbfd, sect);
328 const struct ksplice_option *opt;
329 for (opt = ss->contents.data;
330 (void *)opt < ss->contents.data + ss->contents.size; opt++) {
331 if (opt->type == KSPLICE_OPTION_ASSUME_RODATA) {
332 arelent *reloc = find_reloc(ss, &opt->target);
333 assert(reloc != NULL);
334 struct span *span = reloc_target_span(ss, reloc);
335 assert(span != NULL);
336 assert(span->ss->type == SS_TYPE_DATA);
337 assert(span->start == 0 &&
338 span->size == span->ss->contents.size);
339 span->ss->type = SS_TYPE_RODATA;
340 break;
341 } else {
342 err(sbfd, "Unrecognized Ksplice option %d\n",
343 opt->type);
344 DIE;
349 bool matchable_data_section(struct supersect *ss)
351 if (ss->type == SS_TYPE_STRING)
352 return true;
353 if (ss->type == SS_TYPE_RODATA)
354 return true;
355 if (ss->type == SS_TYPE_DATA && ss->relocs.size != 0)
356 return true;
357 if (ss->type == SS_TYPE_EXPORT)
358 return true;
359 if (ss->type == SS_TYPE_BUGTABLE)
360 return true;
361 return false;
364 bool unchangeable_section(struct supersect *ss)
366 if (ss->type == SS_TYPE_DATA)
367 return true;
368 if (ss->type == SS_TYPE_IGNORED && !strstarts(ss->name, ".debug") &&
369 strcmp(ss->name, "__ksymtab_strings") != 0)
370 return true;
371 return false;
374 int main(int argc, char *argv[])
376 if (getenv("KSPLICE_VERBOSE") != NULL)
377 verbose = atoi(getenv("KSPLICE_VERBOSE"));
379 bfd_init();
380 bfd *ibfd = bfd_openr(argv[1], NULL);
381 assert(ibfd);
383 char **matching;
384 if (bfd_check_format_matches(ibfd, bfd_archive, &matching) &&
385 bfd_openr_next_archived_file(ibfd, NULL) == NULL)
386 return 66; /* empty archive */
387 assert(bfd_check_format_matches(ibfd, bfd_object, &matching));
389 const char *output_target = bfd_get_target(ibfd);
391 load_system_map();
392 load_offsets();
394 bool_hash_init(&system_map_written);
395 ulong_hash_init(&ksplice_symbol_offset);
396 ulong_hash_init(&ksplice_howto_offset);
397 ulong_hash_init(&ksplice_string_offset);
399 struct superbfd *isbfd = fetch_superbfd(ibfd);
401 modestr = argv[3];
402 if (mode("finalize"))
403 finalize_target = argv[4];
404 init_objmanip_superbfd(isbfd);
405 if (mode("keep-new-code")) {
406 kid = argv[5];
407 do_keep_new_code(isbfd, argv[4]);
408 } else if (mode("keep-old-code")) {
409 do_keep_old_code(isbfd);
410 } else if (mode("finalize")) {
411 do_finalize(isbfd);
412 } else if (mode("rmsyms")) {
413 do_rmsyms(isbfd);
416 if (write_output) {
417 bfd *obfd = bfd_openw(argv[2], output_target);
418 assert(obfd);
419 copy_object(ibfd, obfd);
420 assert(bfd_close(obfd));
423 if (offsets_sbfd != NULL)
424 assert(bfd_close(offsets_sbfd->abfd));
425 assert(bfd_close(ibfd));
426 return EXIT_SUCCESS;
429 void do_keep_new_code(struct superbfd *isbfd, const char *pre)
431 struct bfd *prebfd = bfd_openr(pre, NULL);
432 assert(prebfd != NULL);
433 char **matching;
434 assert(bfd_check_format_matches(prebfd, bfd_object, &matching));
436 struct superbfd *presbfd = fetch_superbfd(prebfd);
437 init_objmanip_superbfd(presbfd);
439 foreach_symbol_pair(presbfd, isbfd, match_global_symbols);
440 debug1(isbfd, "Matched global\n");
441 foreach_span_pair(presbfd, isbfd, match_string_spans);
442 debug1(isbfd, "Matched string spans\n");
443 foreach_symbol_pair(presbfd, isbfd, match_symbol_spans);
444 debug1(isbfd, "Matched by name\n");
445 foreach_span_pair(presbfd, isbfd, match_spans_by_label);
446 debug1(isbfd, "Matched by label\n");
447 foreach_span_pair(presbfd, isbfd, match_table_spans);
448 debug1(isbfd, "Matched table spans\n");
449 foreach_span_pair(presbfd, isbfd, match_other_spans);
450 debug1(isbfd, "Matched other spans\n");
452 do {
453 changed = false;
454 compare_matched_spans(isbfd);
455 update_nonzero_offsets(isbfd);
456 mark_new_spans(isbfd);
457 } while (changed);
458 vec_init(&delsects);
460 foreach_symbol_pair(presbfd, isbfd, check_global_symbols);
462 handle_deleted_spans(presbfd, isbfd);
463 handle_section_symbol_renames(presbfd, isbfd);
465 copy_patched_entry_points(presbfd, isbfd);
467 assert(bfd_close(prebfd));
469 do {
470 changed = false;
471 mark_precallable_spans(isbfd);
472 } while (changed);
474 asection *sect;
475 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
476 struct supersect *ss = fetch_supersect(isbfd, sect);
477 ss->keep = false;
478 struct span *span;
479 for (span = ss->spans.data;
480 span < ss->spans.data + ss->spans.size; span++) {
481 if (strstarts(ss->name, ".ksplice_options"))
482 span->keep = false;
483 else if (span->new || span->patch || span->datapatch)
484 keep_span(span);
485 else
486 span->keep = false;
487 if (span->patch && span->precallable) {
488 err(isbfd, "Patched span %s can be reached "
489 "by a precall function\n", span->label);
490 DIE;
495 print_label_changes(isbfd);
497 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
498 struct supersect *ss = fetch_supersect(isbfd, sect);
499 struct span *span;
500 for (span = ss->spans.data;
501 span < ss->spans.data + ss->spans.size; span++) {
502 if (span->patch || span->bugpatch || span->datapatch)
503 debug0(isbfd, "Patching span %s\n",
504 span->label);
508 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
509 struct supersect *ss = fetch_supersect(isbfd, sect);
510 struct span *span;
511 for (span = ss->spans.data;
512 span < ss->spans.data + ss->spans.size; span++) {
513 if (span->new)
514 debug0(isbfd, "New span %s\n", span->label);
518 write_output = false;
519 const char **sectname;
520 for (sectname = delsects.data;
521 sectname < delsects.data + delsects.size; sectname++) {
522 write_output = true;
523 debug0(isbfd, "Deleted section: %s\n", *sectname);
526 filter_table_sections(isbfd);
528 compute_span_shifts(isbfd);
530 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
531 struct supersect *ss = fetch_supersect(isbfd, sect);
532 if (ss->type == SS_TYPE_KSPLICE_CALL)
533 continue;
534 struct span *span;
535 for (span = ss->spans.data;
536 span < ss->spans.data + ss->spans.size; span++) {
537 if (span->keep)
538 write_output = true;
539 if (span->patch || span->new || span->datapatch)
540 write_ksplice_section(span);
541 if (span->patch || span->datapatch)
542 write_ksplice_patches(isbfd, span);
543 if (ss->type == SS_TYPE_EXPORT && span->new)
544 write_ksplice_export(isbfd, span, false);
548 write_bugline_patches(isbfd);
549 rm_relocs(isbfd);
550 remove_unkept_spans(isbfd);
553 void do_keep_old_code(struct superbfd *isbfd)
555 asection *sect;
556 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
557 struct supersect *ss = fetch_supersect(isbfd, sect);
558 ss->keep = false;
559 struct span *span;
560 for (span = ss->spans.data;
561 span < ss->spans.data + ss->spans.size; span++) {
562 span->keep = false;
563 if (ss->type == SS_TYPE_TEXT &&
564 !strstarts(ss->name, ".fixup"))
565 keep_span(span);
566 if (ss->type == SS_TYPE_EXPORT)
567 keep_span(span);
571 asymbol **symp;
572 for (symp = isbfd->syms.data;
573 symp < isbfd->syms.data + isbfd->syms.size; symp++) {
574 asymbol *sym = *symp;
575 if (!bfd_is_const_section(sym->section) &&
576 (sym->flags & BSF_GLOBAL) != 0) {
577 struct supersect *sym_ss =
578 fetch_supersect(isbfd, sym->section);
579 if (sym->value == sym_ss->contents.size)
580 continue;
581 struct span *span = find_span(sym_ss, sym->value);
582 assert(span != NULL);
583 if (sym_ss->type != SS_TYPE_IGNORED)
584 keep_span(span);
588 do {
589 changed = false;
590 keep_referenced_sections(isbfd);
591 } while (changed);
593 filter_table_sections(isbfd);
594 compute_span_shifts(isbfd);
596 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
597 struct supersect *ss = fetch_supersect(isbfd, sect);
598 asymbol *sym = canonical_symbol(isbfd, sect->symbol);
599 if (sym == NULL)
600 continue;
601 if ((sym->flags & BSF_WEAK) != 0)
602 continue;
603 if (bfd_get_section_size(sect) == 0)
604 continue;
605 if (!ss->keep)
606 continue;
607 if (ss->type != SS_TYPE_TEXT && !matchable_data_section(ss))
608 continue;
610 struct span *span;
611 for (span = ss->spans.data;
612 span < ss->spans.data + ss->spans.size; span++) {
613 if (span->keep)
614 write_ksplice_section(span);
618 write_table_relocs(isbfd, "__bug_table", KSPLICE_HOWTO_BUG);
619 write_table_relocs(isbfd, "__ex_table", KSPLICE_HOWTO_EXTABLE);
620 rm_relocs(isbfd);
621 remove_unkept_spans(isbfd);
623 mangle_section_name(isbfd, "__markers");
624 mangle_section_name(isbfd, "__tracepoints");
625 mangle_section_name(isbfd, "__ex_table");
626 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
627 struct supersect *ss = fetch_supersect(isbfd, sect);
628 if (ss->type == SS_TYPE_EXPORT)
629 mangle_section_name(isbfd, ss->name);
633 void do_finalize(struct superbfd *isbfd)
635 load_ksplice_symbol_offsets(isbfd);
636 asection *sect;
637 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
638 struct supersect *ss = fetch_supersect(isbfd, sect);
639 if (ss->type == SS_TYPE_EXIT) {
640 struct span *span;
641 for (span = ss->spans.data;
642 span < ss->spans.data + ss->spans.size; span++)
643 span->keep = false;
644 ss->keep = false;
647 write_date_relocs(isbfd, "<{DATE...}>", KSPLICE_HOWTO_DATE);
648 write_date_relocs(isbfd, "<{TIME}>", KSPLICE_HOWTO_TIME);
649 rm_relocs(isbfd);
652 void do_rmsyms(struct superbfd *isbfd)
654 asection *extract_sect = bfd_get_section_by_name(isbfd->abfd,
655 ".ksplice_extract");
656 if (extract_sect != NULL) {
657 struct supersect *extract_ss = fetch_supersect(isbfd,
658 extract_sect);
659 arelent **relocp;
660 for (relocp = extract_ss->relocs.data;
661 relocp < extract_ss->relocs.data + extract_ss->relocs.size;
662 relocp++) {
663 asymbol *sym = *(*relocp)->sym_ptr_ptr;
664 if (bfd_is_und_section(sym->section)) {
665 debug1(isbfd, "extracting symbol %s\n",
666 sym->name);
667 *vec_grow(&extract_syms, 1) = sym;
672 rm_relocs(isbfd);
675 void match_spans(struct span *old_span, struct span *new_span)
677 struct superbfd *sbfd = new_span->ss->parent;
678 if (old_span->match == new_span && new_span->match == old_span)
679 return;
680 if (old_span->match != NULL) {
681 err(sbfd, "Matching conflict: old %s: %s != %s\n",
682 old_span->label, old_span->match->label, new_span->label);
683 DIE;
685 if (new_span->match != NULL) {
686 err(sbfd, "Matching conflict: new %s: %s != %s\n",
687 new_span->label, new_span->match->label, old_span->label);
688 DIE;
690 old_span->match = new_span;
691 new_span->match = old_span;
692 debug1(sbfd, "Matched old %s to new %s\n", old_span->label,
693 new_span->label);
694 if (old_span->ss->type != new_span->ss->type &&
695 old_span->ss->type == new_span->ss->orig_type)
696 old_span->ss->type = new_span->ss->type;
698 const struct table_section *ts = get_table_section(old_span->ss->name);
699 if (ts == NULL || !ts->has_addr || ts->other_sect == NULL)
700 return;
701 struct span *old_sym_span =
702 span_offset_target_span(old_span, ts->other_offset);
703 struct span *new_sym_span =
704 span_offset_target_span(new_span, ts->other_offset);
705 assert(old_sym_span != NULL && new_sym_span != NULL);
706 match_spans(old_sym_span, new_sym_span);
709 void unmatch_span(struct span *old_span)
711 struct span *new_span = old_span->match;
712 old_span->match = NULL;
713 new_span->match = NULL;
715 new_span->bugpatch = false;
717 if (old_span->ss->type == SS_TYPE_SPECIAL) {
718 const struct table_section *ts =
719 get_table_section(old_span->ss->name);
720 if (ts != NULL && ts->has_addr)
721 unmatch_addr_spans(old_span, new_span, ts);
724 new_span->patch = false;
725 new_span->bugpatch = false;
726 new_span->datapatch = false;
728 changed = true;
731 static void match_global_symbols(struct span *old_span, asymbol *oldsym,
732 struct span *new_span, asymbol *newsym)
734 if (newsym == NULL ||
735 (oldsym->flags & BSF_GLOBAL) == 0 ||
736 (newsym->flags & BSF_GLOBAL) == 0)
737 return;
738 match_spans(old_span, new_span);
741 static void check_global_symbols(struct span *old_span, asymbol *oldsym,
742 struct span *new_span, asymbol *newsym)
744 if ((oldsym->flags & BSF_GLOBAL) == 0 ||
745 (newsym != NULL && (newsym->flags & BSF_GLOBAL) == 0))
746 return;
747 if (old_span->ss->type == SS_TYPE_IGNORED)
748 return;
749 if (old_span->match != new_span) {
750 if (new_span != NULL)
751 err(new_span->ss->parent,
752 "Global symbol span mismatch: %s %s/%s\n",
753 oldsym->name, old_span->label, new_span->label);
754 else
755 err(old_span->ss->parent,
756 "Global symbol span mismatch: %s %s/NULL\n",
757 oldsym->name, old_span->label);
758 DIE;
762 static void foreach_symbol_pair(struct superbfd *oldsbfd, struct superbfd *newsbfd,
763 void (*fn)(struct span *old_span,
764 asymbol *oldsym,
765 struct span *new_span,
766 asymbol *newsym))
768 asymbol **oldsymp, **newsymp;
769 for (oldsymp = oldsbfd->syms.data;
770 oldsymp < oldsbfd->syms.data + oldsbfd->syms.size; oldsymp++) {
771 asymbol *oldsym = *oldsymp;
772 if ((oldsym->flags & BSF_DEBUGGING) != 0 ||
773 bfd_is_const_section(oldsym->section))
774 continue;
776 struct supersect *old_ss =
777 fetch_supersect(oldsbfd, oldsym->section);
778 if (old_ss->type == SS_TYPE_SPECIAL ||
779 old_ss->type == SS_TYPE_EXPORT)
780 continue;
782 struct span *old_span = find_span(old_ss, oldsym->value);
783 if (old_span == NULL) {
784 err(oldsbfd, "Could not find span for %s\n",
785 oldsym->name);
786 DIE;
789 bool found = false;
791 for (newsymp = newsbfd->syms.data;
792 newsymp < newsbfd->syms.data + newsbfd->syms.size;
793 newsymp++) {
794 asymbol *newsym = *newsymp;
795 if ((newsym->flags & BSF_DEBUGGING) != 0 ||
796 bfd_is_const_section(newsym->section))
797 continue;
798 if (strcmp(oldsym->name, newsym->name) != 0)
799 continue;
801 struct supersect *new_ss =
802 fetch_supersect(newsbfd, newsym->section);
803 if (old_ss->type != new_ss->type &&
804 old_ss->type != new_ss->orig_type)
805 continue;
807 assert(!found);
808 found = true;
810 struct span *new_span =
811 find_span(new_ss, newsym->value);
812 if (new_span == NULL) {
813 err(newsbfd, "Could not find span for %s\n",
814 newsym->name);
815 DIE;
817 fn(old_span, oldsym, new_span, newsym);
820 if (!found)
821 fn(old_span, oldsym, NULL, NULL);
825 static void match_symbol_spans(struct span *old_span, asymbol *oldsym,
826 struct span *new_span, asymbol *newsym)
828 if (newsym == NULL)
829 return;
830 if (old_span->ss->type == SS_TYPE_SPECIAL)
831 return;
832 if (static_local_symbol(old_span->ss->parent, oldsym) ||
833 static_local_symbol(new_span->ss->parent, newsym))
834 return;
835 if (old_span->match == NULL && new_span->match == NULL)
836 match_spans(old_span, new_span);
839 static void match_spans_by_label(struct span *old_span, struct span *new_span)
841 if (old_span->ss->type == SS_TYPE_STRING ||
842 (is_table_section(old_span->ss->name, true, false) &&
843 !is_table_section(old_span->ss->name, false, false)))
844 return;
845 if (strcmp(old_span->label, new_span->label) == 0)
846 match_spans(old_span, new_span);
849 static void match_string_spans(struct span *old_span, struct span *new_span)
851 if (old_span->ss->type != SS_TYPE_STRING ||
852 strcmp(old_span->ss->name, new_span->ss->name) != 0)
853 return;
854 if (strcmp((char *)old_span->ss->contents.data + old_span->start,
855 (char *)new_span->ss->contents.data + new_span->start) == 0)
856 match_spans(old_span, new_span);
859 static void foreach_span_pair(struct superbfd *oldsbfd,
860 struct superbfd *newsbfd,
861 void (*fn)(struct span *old_span,
862 struct span *new_span))
864 asection *oldsect, *newsect;
865 struct supersect *oldss, *newss;
866 struct span *old_span, *new_span;
867 for (newsect = newsbfd->abfd->sections; newsect != NULL;
868 newsect = newsect->next) {
869 newss = fetch_supersect(newsbfd, newsect);
870 for (oldsect = oldsbfd->abfd->sections; oldsect != NULL;
871 oldsect = oldsect->next) {
872 oldss = fetch_supersect(oldsbfd, oldsect);
873 if (oldss->type != newss->type)
874 continue;
875 for (new_span = newss->spans.data;
876 new_span < newss->spans.data + newss->spans.size;
877 new_span++) {
878 for (old_span = oldss->spans.data;
879 old_span < oldss->spans.data +
880 oldss->spans.size; old_span++)
881 fn(old_span, new_span);
887 static void mark_new_spans(struct superbfd *sbfd)
889 asection *sect;
890 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
891 struct supersect *ss = fetch_supersect(sbfd, sect);
892 if (ss->type == SS_TYPE_SPECIAL || ss->type == SS_TYPE_IGNORED)
893 continue;
894 struct span *span;
895 for (span = ss->spans.data;
896 span < ss->spans.data + ss->spans.size; span++) {
897 if (span->match == NULL)
898 span->new = true;
903 static void handle_deleted_spans(struct superbfd *oldsbfd,
904 struct superbfd *newsbfd)
906 asection *sect;
907 for (sect = oldsbfd->abfd->sections; sect != NULL; sect = sect->next) {
908 struct supersect *ss = fetch_supersect(oldsbfd, sect);
909 struct span *span;
910 for (span = ss->spans.data;
911 span < ss->spans.data + ss->spans.size; span++) {
912 if (span->match != NULL)
913 continue;
914 if (ss->type == SS_TYPE_EXPORT) {
915 *vec_grow(&delsects, 1) = span->label;
916 write_ksplice_export(newsbfd, span, true);
917 } else if (ss->type == SS_TYPE_TEXT) {
918 *vec_grow(&delsects, 1) = span->label;
919 if (span->symbol == NULL)
920 DIE;
921 write_ksplice_deleted_patch
922 (newsbfd, span->symbol->name, span->label,
923 span->ss->name, 0);
929 static void handle_nonzero_offset_relocs(struct supersect *ss)
931 struct span *address_span, *target_span;
932 arelent **relocp;
933 for (relocp = ss->relocs.data;
934 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
935 arelent *reloc = *relocp;
936 address_span = find_span(ss, reloc->address);
937 if (!address_span->new && !address_span->patch)
938 continue;
940 asymbol *sym = *reloc->sym_ptr_ptr;
941 if (bfd_is_const_section(sym->section))
942 continue;
943 bfd_vma offset = reloc_target_offset(ss, reloc);
944 target_span = reloc_target_span(ss, reloc);
945 if (sym->value + offset == target_span->start)
946 continue;
948 if (target_span->ss->type != SS_TYPE_TEXT)
949 continue;
950 if (target_span->patch)
951 continue;
953 target_span->patch = true;
954 changed = true;
955 debug1(ss->parent, "Changing %s because a relocation from sect "
956 "%s has a nonzero offset %lx+%lx into it\n",
957 target_span->label, ss->name, (unsigned long)sym->value,
958 (unsigned long)offset);
962 static void update_nonzero_offsets(struct superbfd *sbfd)
964 asection *sect;
965 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
966 struct supersect *ss = fetch_supersect(sbfd, sect);
967 if (ss->type == SS_TYPE_SPECIAL || ss->type == SS_TYPE_IGNORED)
968 continue;
969 handle_nonzero_offset_relocs(ss);
973 static void unmatch_addr_spans(struct span *old_span, struct span *new_span,
974 const struct table_section *ts)
976 struct span *old_sym_span =
977 span_offset_target_span(old_span, ts->addr_offset);
978 struct span *new_sym_span =
979 span_offset_target_span(new_span, ts->addr_offset);
980 assert(old_sym_span != NULL && new_sym_span != NULL);
981 if (old_sym_span->match == new_sym_span &&
982 new_sym_span->match == old_sym_span &&
983 !(new_sym_span->patch && new_sym_span->ss->type == SS_TYPE_TEXT)) {
984 if (old_sym_span->ss->type == SS_TYPE_TEXT) {
985 debug1(new_span->ss->parent, "Patching %s due "
986 "to relocations from special section %s\n",
987 new_sym_span->label, new_span->label);
988 new_sym_span->patch = true;
989 } else {
990 debug1(new_span->ss->parent, "Unmatching %s and %s due "
991 "to relocations from special section %s/%s\n",
992 old_sym_span->label, new_sym_span->label,
993 old_span->label, new_span->label);
994 unmatch_span(old_sym_span);
996 changed = true;
1000 static void compare_spans(struct span *old_span, struct span *new_span)
1002 struct superbfd *newsbfd = new_span->ss->parent;
1004 bool nonrelocs_match = nonrelocs_equal(old_span, new_span);
1005 bool relocs_match = all_relocs_equal(old_span, new_span);
1006 if (nonrelocs_match && relocs_match) {
1007 const struct table_section *ts =
1008 get_table_section(old_span->ss->name);
1009 if (ts != NULL && ts->crc_sect != NULL) {
1010 struct span *old_crc_span = get_crc_span(old_span, ts);
1011 struct span *new_crc_span = get_crc_span(new_span, ts);
1012 assert(old_crc_span != NULL);
1013 assert(new_crc_span != NULL);
1014 if (old_crc_span->match != new_crc_span ||
1015 new_crc_span->match != old_crc_span) {
1016 debug1(newsbfd, "Unmatching %s and %s due to "
1017 "nonmatching CRCs\n", old_span->label,
1018 new_span->label);
1019 unmatch_span(old_span);
1022 return;
1025 char *reason;
1026 if (new_span->contents_size != old_span->contents_size)
1027 reason = "differing sizes";
1028 else if (!nonrelocs_match)
1029 reason = "differing contents";
1030 else
1031 reason = "differing relocations";
1033 if (new_span->ss->type == SS_TYPE_TEXT) {
1034 if (new_span->patch)
1035 return;
1036 new_span->patch = true;
1037 debug1(newsbfd, "Changing %s due to %s\n", new_span->label,
1038 reason);
1039 } else if (old_span->ss->type == SS_TYPE_BUGTABLE &&
1040 new_span->ss->type == SS_TYPE_BUGTABLE && relocs_match) {
1041 if (new_span->bugpatch)
1042 return;
1043 debug1(newsbfd, "Changing %s due to %s\n",
1044 new_span->label, reason);
1045 new_span->bugpatch = true;
1046 } else if (new_span->ss->type == SS_TYPE_RODATA &&
1047 new_span->contents_size == old_span->contents_size) {
1048 if (new_span->datapatch)
1049 return;
1050 new_span->datapatch = true;
1051 debug1(newsbfd, "Changing %s in-place due to %s\n",
1052 new_span->label, reason);
1053 } else if (new_span->ss->type == SS_TYPE_STRING &&
1054 old_span->ss->type == SS_TYPE_STRING && relocs_match &&
1055 strcmp(new_span->ss->contents.data + new_span->start,
1056 old_span->ss->contents.data + old_span->start) == 0) {
1057 return;
1058 } else {
1059 debug1(newsbfd, "Unmatching %s and %s due to %s\n",
1060 old_span->label, new_span->label, reason);
1061 unmatch_span(old_span);
1063 changed = true;
1064 if (unchangeable_section(new_span->ss))
1065 err(newsbfd, "warning: ignoring change to nonpatchable "
1066 "section %s\n", new_span->ss->name);
1069 static void compare_matched_spans(struct superbfd *newsbfd)
1071 asection *sect;
1072 for (sect = newsbfd->abfd->sections; sect != NULL; sect = sect->next) {
1073 struct supersect *ss = fetch_supersect(newsbfd, sect);
1074 struct span *span;
1075 for (span = ss->spans.data;
1076 span < ss->spans.data + ss->spans.size; span++) {
1077 if (span->match == NULL)
1078 continue;
1079 compare_spans(span->match, span);
1084 static void handle_section_symbol_renames(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->match == NULL)
1094 continue;
1095 if (strcmp(span->label, span->match->label) == 0)
1096 continue;
1097 if (strcmp(span->orig_label, span->label) != 0 &&
1098 strcmp(span->label, span->match->label) != 0)
1099 DIE;
1100 if (span->symbol != NULL)
1101 label_map_set(newsbfd, span->label,
1102 span->match->label);
1103 span->label = span->match->label;
1108 static void copy_patched_entry_points(struct superbfd *oldsbfd,
1109 struct superbfd *newsbfd)
1111 asection *sect;
1112 struct span *span;
1113 for (sect = newsbfd->abfd->sections; sect != NULL; sect = sect->next) {
1114 struct supersect *ss = fetch_supersect(newsbfd, sect);
1115 for (span = ss->spans.data;
1116 span < ss->spans.data + ss->spans.size; span++) {
1117 if (!span->patch)
1118 continue;
1119 assert(span->match != NULL);
1120 vec_init(&span->pre_entry_points);
1122 struct entry_point *entry;
1123 for (entry = span->match->entry_points.data;
1124 entry < span->match->entry_points.data +
1125 span->match->entry_points.size;
1126 entry++) {
1127 struct entry_point *e =
1128 vec_grow(&span->pre_entry_points, 1);
1129 e->name = entry->name != NULL ?
1130 strdup(entry->name) : NULL;
1131 e->label = strdup(entry->label);
1132 e->offset = entry->offset;
1133 e->symbol = NULL;
1139 static int compare_entry_points(const void *va, const void *vb)
1141 const struct entry_point *a = va, *b = vb;
1142 if (a->offset < b->offset)
1143 return -1;
1144 else if (a->offset > b->offset)
1145 return 1;
1146 else
1147 return 0;
1150 static void compute_entry_points(struct superbfd *sbfd)
1152 asymbol **symp;
1153 for (symp = sbfd->syms.data; symp < sbfd->syms.data + sbfd->syms.size;
1154 symp++) {
1155 asymbol *sym = *symp;
1156 if (bfd_is_const_section(sym->section))
1157 continue;
1158 struct supersect *old_ss = fetch_supersect(sbfd, sym->section);
1159 if ((sym->flags & BSF_GLOBAL) == 0)
1160 continue;
1161 struct span *span = find_span(old_ss, sym->value);
1162 struct entry_point *e = vec_grow(&span->entry_points, 1);
1163 e->label = sym->name;
1164 e->name = sym->name;
1165 e->offset = sym->value - span->start;
1166 e->symbol = sym;
1169 asection *sect;
1170 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
1171 struct supersect *ss = fetch_supersect(sbfd, sect);
1172 struct span *span;
1173 for (span = ss->spans.data;
1174 span < ss->spans.data + ss->spans.size; span++) {
1175 /* First make sure that 0 appears as an entry point */
1176 bool found_zero = false;
1177 struct entry_point *entry;
1178 for (entry = span->entry_points.data;
1179 entry < span->entry_points.data +
1180 span->entry_points.size;
1181 entry++) {
1182 if (entry->offset == 0)
1183 found_zero = true;
1185 if (!found_zero) {
1186 struct entry_point *e =
1187 vec_grow(&span->entry_points, 1);
1188 e->label = span->label;
1189 e->name = NULL;
1190 e->offset = 0;
1191 e->symbol = span->symbol;
1194 qsort(span->entry_points.data, span->entry_points.size,
1195 sizeof(*span->entry_points.data),
1196 compare_entry_points);
1201 static bool part_of_reloc(struct supersect *ss, unsigned long addr)
1203 arelent **relocp;
1204 for (relocp = ss->relocs.data;
1205 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
1206 arelent *reloc = *relocp;
1207 if (addr >= reloc->address &&
1208 addr < reloc->address + bfd_get_reloc_size(reloc->howto))
1209 return true;
1211 return false;
1214 static bool nonrelocs_equal(struct span *old_span, struct span *new_span)
1216 int i;
1217 struct supersect *old_ss = old_span->ss, *new_ss = new_span->ss;
1218 if (old_span->contents_size != new_span->contents_size)
1219 return false;
1220 const unsigned char *old = old_ss->contents.data + old_span->start;
1221 const unsigned char *new = new_ss->contents.data + new_span->start;
1222 for (i = 0; i < old_span->contents_size; i++) {
1223 if (old[i] != new[i] &&
1224 !(part_of_reloc(old_ss, i + old_span->start) &&
1225 part_of_reloc(new_ss, i + new_span->start)))
1226 return false;
1228 return true;
1231 bool relocs_equal(struct supersect *old_src_ss, struct supersect *new_src_ss,
1232 arelent *old_reloc, arelent *new_reloc)
1234 struct superbfd *oldsbfd = old_src_ss->parent;
1235 struct superbfd *newsbfd = new_src_ss->parent;
1236 struct span *old_addr_span = find_span(old_src_ss, old_reloc->address);
1237 struct span *new_addr_span = find_span(new_src_ss, new_reloc->address);
1239 if (old_reloc->address - old_addr_span->start !=
1240 new_reloc->address - new_addr_span->start) {
1241 debug1(newsbfd, "Section %s/%s has reloc address mismatch at "
1242 "%lx\n", old_src_ss->name, new_src_ss->name,
1243 (unsigned long)old_reloc->address);
1244 return false;
1247 if (old_reloc->howto != new_reloc->howto) {
1248 debug1(newsbfd, "Section %s/%s has howto type mismatch at "
1249 "%lx\n", old_src_ss->name, new_src_ss->name,
1250 (unsigned long)old_reloc->address);
1251 return false;
1254 if (non_dst_mask(old_src_ss, old_reloc) !=
1255 non_dst_mask(new_src_ss, new_reloc)) {
1256 debug1(newsbfd, "Section %s/%s has contents mismatch at %lx\n",
1257 old_src_ss->name, new_src_ss->name,
1258 (unsigned long)old_reloc->address);
1259 return false;
1262 asymbol *old_sym = *old_reloc->sym_ptr_ptr;
1263 asymbol *new_sym = *new_reloc->sym_ptr_ptr;
1264 asection *old_sect = old_sym->section;
1265 asection *new_sect = new_sym->section;
1267 bfd_vma old_offset = reloc_target_offset(old_src_ss, old_reloc);
1268 bfd_vma new_offset = reloc_target_offset(new_src_ss, new_reloc);
1270 if (bfd_is_und_section(old_sect) || bfd_is_und_section(new_sect)) {
1271 if (!bfd_is_und_section(new_sect) && old_offset != 0 &&
1272 fetch_supersect(newsbfd, new_sect)->type == SS_TYPE_TEXT)
1273 return false;
1275 if (!bfd_is_und_section(new_sect) && new_offset != 0 &&
1276 fetch_supersect(oldsbfd, old_sect)->type == SS_TYPE_TEXT)
1277 return false;
1279 return strcmp(old_sym->name, new_sym->name) == 0 &&
1280 old_offset == new_offset;
1283 if (bfd_is_abs_section(old_sect) && bfd_is_abs_section(new_sect)) {
1284 if (old_sym->value + old_offset == new_sym->value + new_offset)
1285 return true;
1286 debug1(newsbfd, "Differing relocations from %s/%s to ABS "
1287 "section: %lx/%lx\n", old_addr_span->label,
1288 new_addr_span->label,
1289 (unsigned long)(old_sym->value + old_offset),
1290 (unsigned long)(new_sym->value + new_offset));
1291 return false;
1294 if (bfd_is_const_section(old_sect) || bfd_is_const_section(new_sect))
1295 DIE;
1297 struct supersect *old_ss = fetch_supersect(oldsbfd, old_sect);
1298 struct supersect *new_ss = fetch_supersect(newsbfd, new_sect);
1299 struct span *old_span = reloc_target_span(old_src_ss, old_reloc);
1300 struct span *new_span = reloc_target_span(new_src_ss, new_reloc);
1302 if (old_span->match != new_span || new_span->match != old_span) {
1303 debug1(newsbfd, "Nonmatching relocs from %s to %s/%s\n",
1304 new_src_ss->name, old_span->label, new_span->label);
1305 return false;
1308 if (old_sym->value + old_offset - old_span->start !=
1309 new_sym->value + new_offset - new_span->start) {
1310 debug1(newsbfd, "Offsets to %s/%s differ between %s "
1311 "and %s: %lx+%lx/%lx+%lx\n", old_ss->name,
1312 new_ss->name, old_src_ss->name, new_src_ss->name,
1313 (unsigned long)old_sym->value, (unsigned long)old_offset,
1314 (unsigned long)new_sym->value,
1315 (unsigned long)new_offset);
1316 return false;
1319 if ((old_sym->value + old_offset - old_span->start != 0 ||
1320 new_sym->value + new_offset - new_span->start != 0) &&
1321 new_span->patch) {
1322 debug1(newsbfd, "Relocation from %s to nonzero offsets "
1323 "%lx+%lx/%lx+%lx in changed section %s\n",
1324 new_src_ss->name, (unsigned long)old_sym->value,
1325 (unsigned long)old_offset, (unsigned long)new_sym->value,
1326 (unsigned long)new_offset, new_sym->section->name);
1327 return false;
1329 return true;
1332 bool all_relocs_equal(struct span *old_span, struct span *new_span)
1334 struct supersect *old_ss = old_span->ss, *new_ss = new_span->ss;
1335 arelent **old_relocp, **new_relocp;
1337 for (old_relocp = old_ss->relocs.data;
1338 old_relocp < old_ss->relocs.data + old_ss->relocs.size;
1339 old_relocp++) {
1340 if (find_span(old_ss, (*old_relocp)->address) == old_span)
1341 break;
1344 for (new_relocp = new_ss->relocs.data;
1345 new_relocp < new_ss->relocs.data + new_ss->relocs.size;
1346 new_relocp++) {
1347 if (find_span(new_ss, (*new_relocp)->address) == new_span)
1348 break;
1351 for (; old_relocp < old_ss->relocs.data + old_ss->relocs.size &&
1352 find_span(old_ss, (*old_relocp)->address) == old_span &&
1353 new_relocp < new_ss->relocs.data + new_ss->relocs.size &&
1354 find_span(new_ss, (*new_relocp)->address) == new_span;
1355 old_relocp++, new_relocp++) {
1356 if (!relocs_equal(old_ss, new_ss, *old_relocp, *new_relocp))
1357 return false;
1360 if ((old_relocp < old_ss->relocs.data + old_ss->relocs.size &&
1361 find_span(old_ss, (*old_relocp)->address) == old_span) ||
1362 (new_relocp < new_ss->relocs.data + new_ss->relocs.size &&
1363 find_span(new_ss, (*new_relocp)->address) == new_span)) {
1364 debug1(new_ss->parent, "Different reloc count between %s and "
1365 "%s\n", old_span->label, new_span->label);
1366 return false;
1369 return true;
1372 bfd_vma non_dst_mask(struct supersect *ss, arelent *reloc)
1374 int bits = bfd_get_reloc_size(reloc->howto) * 8;
1375 void *address = ss->contents.data + reloc->address;
1376 bfd_vma x = bfd_get(bits, ss->parent->abfd, address);
1377 return x & ~reloc->howto->dst_mask;
1380 void rm_relocs(struct superbfd *isbfd)
1382 asection *p;
1383 for (p = isbfd->abfd->sections; p != NULL; p = p->next) {
1384 struct supersect *ss = fetch_supersect(isbfd, p);
1385 bool remove_relocs = ss->keep;
1387 if (mode("keep") && ss->type == SS_TYPE_SPECIAL)
1388 remove_relocs = false;
1390 if (ss->type == SS_TYPE_KSPLICE ||
1391 ss->type == SS_TYPE_KSPLICE_CALL)
1392 remove_relocs = false;
1393 if (mode("finalize") &&
1394 (strstarts(ss->name, ".ksplice_patches") ||
1395 strstarts(ss->name, ".ksplice_relocs")))
1396 remove_relocs = true;
1398 if (remove_relocs)
1399 rm_some_relocs(ss);
1403 void rm_some_relocs(struct supersect *ss)
1405 struct arelentp_vec orig_relocs;
1406 vec_move(&orig_relocs, &ss->relocs);
1408 arelent **relocp;
1409 for (relocp = orig_relocs.data;
1410 relocp < orig_relocs.data + orig_relocs.size; relocp++) {
1411 bool rm_reloc = false;
1412 asymbol *sym_ptr = *(*relocp)->sym_ptr_ptr;
1414 if (mode("rmsyms") && bfd_is_und_section(sym_ptr->section)) {
1415 asymbol **esymp;
1416 for (esymp = extract_syms.data;
1417 esymp < extract_syms.data + extract_syms.size;
1418 esymp++) {
1419 if (sym_ptr == *esymp) {
1420 rm_reloc = true;
1421 break;
1426 if (mode("keep"))
1427 rm_reloc = true;
1429 if (mode("keep-new-code")) {
1430 if (bfd_is_const_section(sym_ptr->section)) {
1431 rm_reloc = false;
1432 } else {
1433 bfd_vma offset = reloc_target_offset(ss, *relocp);
1434 struct span *target_span =
1435 reloc_target_span(ss, *relocp);
1436 if (target_span->new ||
1437 (target_span->ss->type == SS_TYPE_TEXT &&
1438 sym_ptr->value + offset !=
1439 target_span->start))
1440 rm_reloc = false;
1443 const struct table_section *ts =
1444 get_table_section(ss->name);
1445 if (ts != NULL && ts->has_addr &&
1446 ((*relocp)->address % ts->entry_size ==
1447 ts->addr_offset ||
1448 (*relocp)->address % ts->entry_size ==
1449 ts->other_offset))
1450 rm_reloc = false;
1453 if (mode("finalize") && bfd_is_und_section(sym_ptr->section))
1454 rm_reloc = true;
1456 if (strcmp(sym_ptr->name, "mcount") == 0 &&
1457 bfd_is_und_section(sym_ptr->section))
1458 rm_reloc = false;
1460 if (!find_span(ss, (*relocp)->address)->keep)
1461 rm_reloc = false;
1463 if (rm_reloc)
1464 write_ksplice_reloc(ss, *relocp);
1465 else
1466 *vec_grow(&ss->relocs, 1) = *relocp;
1470 struct supersect *make_section(struct superbfd *sbfd, const char *fmt, ...)
1472 va_list ap;
1473 va_start(ap, fmt);
1474 char *name = vstrprintf(fmt, ap);
1475 va_end(ap);
1477 asection *sect = bfd_get_section_by_name(sbfd->abfd, name);
1478 if (sect != NULL)
1479 return fetch_supersect(sbfd, sect);
1480 else
1481 return new_supersect(sbfd, name);
1484 arelent *create_reloc(struct supersect *ss, const void *addr, asymbol **symp,
1485 bfd_vma offset)
1487 bfd_reloc_code_real_type code;
1488 switch (bfd_arch_bits_per_address(ss->parent->abfd)) {
1489 case 32:
1490 code = BFD_RELOC_32;
1491 break;
1492 case 64:
1493 code = BFD_RELOC_64;
1494 break;
1495 default:
1496 DIE;
1499 arelent *reloc = malloc(sizeof(*reloc));
1500 reloc->sym_ptr_ptr = symp;
1501 reloc->address = addr_offset(ss, addr);
1502 reloc->howto = bfd_reloc_type_lookup(ss->parent->abfd, code);
1503 reloc->addend = offset;
1504 return reloc;
1507 void write_reloc(struct supersect *ss, const void *addr, asymbol **symp,
1508 bfd_vma offset)
1510 *vec_grow(&ss->new_relocs, 1) = create_reloc(ss, addr, symp, offset);
1513 void write_string(struct supersect *ss, const char **addr, const char *fmt, ...)
1515 va_list ap;
1516 struct supersect *str_ss = make_section(ss->parent, ".ksplice_str");
1517 char *str;
1518 va_start(ap, fmt);
1519 int len = vasprintf(&str, fmt, ap);
1520 assert(len >= 0);
1521 va_end(ap);
1523 unsigned long *str_offp = ulong_hash_lookup(&ksplice_string_offset, str,
1524 FALSE);
1525 if (str_offp == NULL) {
1526 char *buf = sect_grow(str_ss, len + 1, char);
1527 memcpy(buf, str, len + 1);
1528 str_offp = ulong_hash_lookup(&ksplice_string_offset, str, TRUE);
1529 *str_offp = addr_offset(str_ss, buf);
1532 write_reloc(ss, addr, &str_ss->symbol, *str_offp);
1535 void lookup_system_map(struct addr_vec *addrs, const char *name, long offset)
1537 struct addr_vec *map_addrs =
1538 addr_vec_hash_lookup(&system_map, name, FALSE);
1539 if (map_addrs == NULL)
1540 return;
1542 unsigned long *addr, *map_addr;
1543 for (map_addr = map_addrs->data;
1544 map_addr < map_addrs->data + map_addrs->size; map_addr++) {
1545 for (addr = addrs->data; addr < addrs->data + addrs->size;
1546 addr++) {
1547 if (*addr == *map_addr + offset)
1548 break;
1550 if (addr < addrs->data + addrs->size)
1551 continue;
1552 *vec_grow(addrs, 1) = *map_addr + offset;
1556 void compute_system_map_array(struct superbfd *sbfd, struct addr_vec *addrs,
1557 asymbol *sym)
1559 if (bfd_is_abs_section(sym->section)) {
1560 *vec_grow(addrs, 1) = sym->value;
1561 } else if (bfd_is_und_section(sym->section)) {
1562 lookup_system_map(addrs, sym->name, 0);
1563 } else if (!bfd_is_const_section(sym->section)) {
1564 asymbol **gsymp;
1565 for (gsymp = sbfd->syms.data;
1566 gsymp < sbfd->syms.data + sbfd->syms.size; gsymp++) {
1567 asymbol *gsym = *gsymp;
1568 if ((gsym->flags & BSF_DEBUGGING) == 0 &&
1569 gsym->section == sym->section)
1570 lookup_system_map(addrs, gsym->name,
1571 sym->value - gsym->value);
1576 void write_ksplice_system_map(struct superbfd *sbfd, asymbol *sym,
1577 const char *label)
1579 bool *done = bool_hash_lookup(&system_map_written, label, TRUE);
1580 if (*done)
1581 return;
1582 *done = true;
1584 struct addr_vec addrs;
1585 vec_init(&addrs);
1587 compute_system_map_array(sbfd, &addrs, sym);
1588 if (addrs.size != 0) {
1589 struct supersect *smap_ss =
1590 make_section(sbfd, ".ksplice_system_map");
1591 struct ksplice_system_map *smap =
1592 sect_grow(smap_ss, 1, struct ksplice_system_map);
1593 write_string(smap_ss, &smap->label, "%s", label);
1595 struct supersect *array_ss = make_section(sbfd,
1596 ".ksplice_array");
1597 void *buf = sect_grow(array_ss, addrs.size,
1598 typeof(*addrs.data));
1599 memcpy(buf, addrs.data, addrs.size * sizeof(*addrs.data));
1600 smap->nr_candidates = addrs.size;
1601 write_reloc(smap_ss, &smap->candidates, &array_ss->symbol,
1602 addr_offset(array_ss, buf));
1604 vec_free(&addrs);
1607 void write_ksplice_symbol_backend(struct supersect *ss,
1608 struct ksplice_symbol *const *addr,
1609 asymbol *sym, const char *label,
1610 const char *name)
1612 struct supersect *ksymbol_ss = make_section(ss->parent,
1613 ".ksplice_symbols");
1614 struct ksplice_symbol *ksymbol;
1615 unsigned long *ksymbol_offp;
1617 ksymbol_offp = ulong_hash_lookup(&ksplice_symbol_offset, label, FALSE);
1618 if (ksymbol_offp != NULL) {
1619 write_reloc(ss, addr, &ksymbol_ss->symbol, *ksymbol_offp);
1620 return;
1622 ksymbol = sect_grow(ksymbol_ss, 1, struct ksplice_symbol);
1623 ksymbol_offp = ulong_hash_lookup(&ksplice_symbol_offset, label, TRUE);
1624 *ksymbol_offp = addr_offset(ksymbol_ss, ksymbol);
1626 write_reloc(ss, addr, &ksymbol_ss->symbol, *ksymbol_offp);
1627 write_string(ksymbol_ss, &ksymbol->label, "%s", label);
1628 if (name != NULL) {
1629 write_string(ksymbol_ss, &ksymbol->name, "%s", name);
1630 write_ksplice_system_map(ksymbol_ss->parent, sym, label);
1634 void write_ksplice_symbol(struct supersect *ss,
1635 struct ksplice_symbol *const *addr,
1636 asymbol *sym, struct span *span,
1637 const char *addstr_sect)
1639 const char *label, *name;
1640 if (span != NULL && span->start != 0)
1641 label = span->label;
1642 else
1643 label = label_lookup(ss->parent, sym);
1645 asymbol *gsym = canonical_symbol(ss->parent, sym);
1646 if (strcmp(addstr_sect, "") != 0)
1647 name = NULL;
1648 else if (bfd_is_und_section(sym->section))
1649 name = sym->name;
1650 else if (bfd_is_const_section(sym->section))
1651 name = NULL;
1652 else if (span != NULL && span->symbol == NULL)
1653 name = NULL;
1654 else if (gsym == NULL || (gsym->flags & BSF_SECTION_SYM) != 0)
1655 name = NULL;
1656 else
1657 name = gsym->name;
1659 write_ksplice_symbol_backend(ss, addr, sym,
1660 strprintf("%s%s", addstr_sect, label),
1661 name);
1664 void write_ksplice_reloc(struct supersect *ss, arelent *orig_reloc)
1666 asymbol *sym_ptr = *orig_reloc->sym_ptr_ptr;
1667 bfd_vma reloc_addend = reloc_offset(ss, orig_reloc);
1668 bfd_vma target_addend = reloc_target_offset(ss, orig_reloc);
1669 unsigned long *repladdr = ss->contents.data + orig_reloc->address;
1671 if (mode("finalize") && strstarts(ss->name, ".ksplice_patches")) {
1672 *repladdr = 0;
1673 return;
1675 if (mode("finalize") && strstarts(ss->name, ".ksplice_relocs")) {
1676 assert(strstarts(sym_ptr->name, KSPLICE_SYMBOL_STR));
1677 asymbol fake_sym;
1678 fake_sym.name = sym_ptr->name + strlen(KSPLICE_SYMBOL_STR);
1679 fake_sym.section = bfd_und_section_ptr;
1680 fake_sym.value = 0;
1681 fake_sym.flags = 0;
1683 write_ksplice_symbol_backend
1684 (ss, (struct ksplice_symbol **)repladdr, &fake_sym,
1685 fake_sym.name, fake_sym.name);
1686 return;
1689 struct span *span = reloc_target_span(ss, orig_reloc);
1690 if (span == ss->spans.data && span->start != target_addend)
1691 span = NULL;
1692 write_canary(ss, orig_reloc->address,
1693 bfd_get_reloc_size(orig_reloc->howto),
1694 orig_reloc->howto->dst_mask);
1696 struct supersect *kreloc_ss =
1697 make_section(ss->parent, ".ksplice_relocs%s", ss->name);
1698 struct ksplice_reloc *kreloc = sect_grow(kreloc_ss, 1,
1699 struct ksplice_reloc);
1701 struct span *address_span = find_span(ss, orig_reloc->address);
1702 write_reloc(kreloc_ss, &kreloc->blank_addr,
1703 &ss->symbol, orig_reloc->address + address_span->shift);
1704 if (bfd_is_und_section(sym_ptr->section) && mode("keep")) {
1705 char *name = strprintf(KSPLICE_SYMBOL_STR "%s", sym_ptr->name);
1706 asymbol **symp = make_undefined_symbolp(ss->parent, name);
1707 write_reloc(kreloc_ss, &kreloc->symbol, symp, 0);
1708 } else {
1709 write_ksplice_symbol(kreloc_ss, &kreloc->symbol, sym_ptr, span,
1710 "");
1712 if (span != NULL && span->start != 0) {
1713 reloc_addend += sym_ptr->value - span->start;
1714 target_addend += sym_ptr->value - span->start;
1716 kreloc->insn_addend = reloc_addend - target_addend;
1717 kreloc->target_addend = target_addend;
1718 write_ksplice_reloc_howto(kreloc_ss, &kreloc->howto, orig_reloc->howto,
1719 KSPLICE_HOWTO_RELOC);
1722 static void write_ksplice_reloc_howto(struct supersect *ss, const
1723 struct ksplice_reloc_howto *const *addr,
1724 reloc_howto_type *howto,
1725 enum ksplice_reloc_howto_type type)
1727 struct supersect *khowto_ss = make_section(ss->parent,
1728 ".ksplice_reloc_howtos");
1729 struct ksplice_reloc_howto *khowto;
1730 unsigned long *khowto_offp;
1732 khowto_offp = ulong_hash_lookup(&ksplice_howto_offset, howto->name,
1733 FALSE);
1734 if (khowto_offp != NULL) {
1735 write_reloc(ss, addr, &khowto_ss->symbol, *khowto_offp);
1736 return;
1738 khowto = sect_grow(khowto_ss, 1, struct ksplice_reloc_howto);
1739 khowto_offp = ulong_hash_lookup(&ksplice_howto_offset, howto->name,
1740 TRUE);
1741 *khowto_offp = addr_offset(khowto_ss, khowto);
1743 khowto->type = type;
1744 khowto->pcrel = howto->pc_relative;
1745 khowto->size = bfd_get_reloc_size(howto);
1746 khowto->dst_mask = howto->dst_mask;
1747 khowto->rightshift = howto->rightshift;
1748 khowto->signed_addend =
1749 (howto->complain_on_overflow == complain_overflow_signed) ||
1750 (howto->complain_on_overflow == complain_overflow_bitfield);
1751 write_reloc(ss, addr, &khowto_ss->symbol, *khowto_offp);
1754 #define CANARY(x, canary) ((x & ~howto->dst_mask) | (canary & howto->dst_mask))
1756 void write_canary(struct supersect *ss, int offset, bfd_size_type size,
1757 bfd_vma dst_mask)
1759 int bits = size * 8;
1760 void *address = ss->contents.data + offset;
1761 bfd_vma x = bfd_get(bits, ss->parent->abfd, address);
1762 x = (x & ~dst_mask) | ((bfd_vma)KSPLICE_CANARY & dst_mask);
1763 bfd_put(bits, ss->parent->abfd, x, address);
1766 static void write_date_relocs(struct superbfd *sbfd, const char *str,
1767 enum ksplice_reloc_howto_type type)
1769 asection *sect;
1770 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
1771 struct supersect *ss = fetch_supersect(sbfd, sect);
1772 if (ss->type != SS_TYPE_STRING && ss->type != SS_TYPE_RODATA)
1773 continue;
1774 void *ptr;
1775 struct span *span;
1776 for (span = ss->spans.data;
1777 span < ss->spans.data + ss->spans.size; span++) {
1778 if (!span->keep)
1779 continue;
1780 for (ptr = ss->contents.data + span->start;
1781 ptr + strlen(str) < ss->contents.data +
1782 span->start + span->contents_size; ptr++) {
1783 if (strcmp((const char *)ptr, str) == 0)
1784 write_ksplice_date_reloc
1785 (ss, addr_offset(ss, ptr), str,
1786 type);
1792 static void write_ksplice_date_reloc(struct supersect *ss, unsigned long offset,
1793 const char *str,
1794 enum ksplice_reloc_howto_type type)
1796 struct supersect *kreloc_ss;
1797 kreloc_ss = make_section(ss->parent, ".ksplice_relocs%s", ss->name);
1798 struct ksplice_reloc *kreloc = sect_grow(kreloc_ss, 1,
1799 struct ksplice_reloc);
1801 const char *filename = ss->parent->abfd->filename;
1802 char *c = strstr(filename, ".KSPLICE");
1803 int flen = (c == NULL ? strlen(filename) : c - filename);
1805 write_ksplice_symbol_backend(kreloc_ss, &kreloc->symbol, NULL,
1806 strprintf("%s<%.*s>", str, flen, filename),
1807 NULL);
1809 struct span *span = find_span(ss, offset);
1810 write_reloc(kreloc_ss, &kreloc->blank_addr, &ss->symbol,
1811 offset + span->shift);
1812 write_ksplice_nonreloc_howto(kreloc_ss, &kreloc->howto, type,
1813 strlen(str));
1816 static void write_table_relocs(struct superbfd *sbfd, const char *sectname,
1817 enum ksplice_reloc_howto_type type)
1819 asection *sect = bfd_get_section_by_name(sbfd->abfd, sectname);
1820 if (sect == NULL)
1821 return;
1822 struct supersect *ss = fetch_supersect(sbfd, sect);
1824 const struct table_section *s = get_table_section(sectname);
1825 if (s == NULL)
1826 DIE;
1828 void *entry;
1829 for (entry = ss->contents.data;
1830 entry < ss->contents.data + ss->contents.size;
1831 entry += s->entry_size) {
1832 struct span *span = find_span(ss, addr_offset(ss, entry));
1833 assert(span != NULL);
1834 if (!span->keep)
1835 continue;
1837 arelent *reloc = find_reloc(ss, entry + s->addr_offset);
1838 assert(reloc != NULL);
1839 asymbol *sym = *reloc->sym_ptr_ptr;
1840 assert(!bfd_is_const_section(sym->section));
1841 struct supersect *sym_ss = fetch_supersect(sbfd, sym->section);
1842 unsigned long addr = sym->value +
1843 reloc_target_offset(ss, reloc);
1844 write_ksplice_table_reloc(sym_ss, addr, span->label, type);
1848 static void write_ksplice_table_reloc(struct supersect *ss,
1849 unsigned long address,
1850 const char *label,
1851 enum ksplice_reloc_howto_type type)
1853 struct supersect *kreloc_ss;
1854 kreloc_ss = make_section(ss->parent, ".ksplice_relocs%s", ss->name);
1855 struct ksplice_reloc *kreloc = sect_grow(kreloc_ss, 1,
1856 struct ksplice_reloc);
1857 struct span *span = find_span(ss, address);
1858 assert(span != NULL);
1860 write_ksplice_symbol_backend(kreloc_ss, &kreloc->symbol, NULL,
1861 label, NULL);
1862 write_reloc(kreloc_ss, &kreloc->blank_addr, &ss->symbol,
1863 address + span->shift);
1864 write_ksplice_nonreloc_howto(kreloc_ss, &kreloc->howto, type, 0);
1867 static void write_ksplice_nonreloc_howto(struct supersect *ss,
1868 const struct ksplice_reloc_howto
1869 *const *addr,
1870 enum ksplice_reloc_howto_type type,
1871 int size)
1873 struct supersect *khowto_ss =
1874 make_section(ss->parent, ".ksplice_reloc_howtos");
1875 struct ksplice_reloc_howto *khowto =
1876 sect_grow(khowto_ss, 1, struct ksplice_reloc_howto);
1878 khowto->type = type;
1879 khowto->size = size;
1880 khowto->pcrel = 0;
1881 khowto->dst_mask = 0;
1882 khowto->rightshift = 0;
1883 khowto->signed_addend = 0;
1884 write_reloc(ss, addr, &khowto_ss->symbol,
1885 addr_offset(khowto_ss, khowto));
1888 static void write_ksplice_symbol_reloc(struct supersect *ss,
1889 const char *sectname,
1890 unsigned long *addr, asymbol *sym,
1891 const char *label, const char *name)
1893 struct supersect *kreloc_ss;
1894 kreloc_ss = make_section(ss->parent, ".ksplice_relocs%s", sectname);
1895 struct ksplice_reloc *kreloc = sect_grow(kreloc_ss, 1,
1896 struct ksplice_reloc);
1898 write_ksplice_symbol_backend(kreloc_ss, &kreloc->symbol, sym, label,
1899 name);
1900 write_reloc(kreloc_ss, &kreloc->blank_addr, &ss->symbol,
1901 addr_offset(ss, addr));
1902 write_ksplice_nonreloc_howto(kreloc_ss, &kreloc->howto,
1903 KSPLICE_HOWTO_SYMBOL, 0);
1906 static void write_ksplice_section(struct span *span)
1908 struct supersect *ss = span->ss;
1909 const char *sectname = span->ss->name;
1910 const struct table_section *ts = get_table_section(ss->name);
1912 if (ts != NULL && ts->has_addr) {
1913 arelent *reloc = find_reloc(ss, ss->contents.data + span->start
1914 + ts->addr_offset);
1915 assert(reloc != NULL);
1916 asymbol *rsym = *reloc->sym_ptr_ptr;
1917 assert(!bfd_is_const_section(rsym->section));
1918 sectname = rsym->section->name;
1921 struct supersect *ksect_ss =
1922 make_section(ss->parent, ".ksplice_sections%s", sectname);
1923 struct ksplice_section *ksect = sect_grow(ksect_ss, 1,
1924 struct ksplice_section);
1925 asymbol *sym = span->symbol == NULL ? ss->symbol : span->symbol;
1927 write_ksplice_symbol(ksect_ss, &ksect->symbol, sym, span,
1928 mode("keep-new-code") ? "(post)" : "");
1929 ksect->size = span->size;
1930 ksect->flags = 0;
1932 if (ss->type == SS_TYPE_RODATA || ss->type == SS_TYPE_STRING ||
1933 ss->type == SS_TYPE_EXPORT || ss->type == SS_TYPE_BUGTABLE)
1934 ksect->flags |= KSPLICE_SECTION_RODATA;
1935 if (ss->type == SS_TYPE_DATA)
1936 ksect->flags |= KSPLICE_SECTION_DATA;
1937 if (ss->type == SS_TYPE_TEXT)
1938 ksect->flags |= KSPLICE_SECTION_TEXT;
1939 assert(ksect->flags != 0);
1941 if (ss->type == SS_TYPE_STRING)
1942 ksect->flags |= KSPLICE_SECTION_STRING;
1944 write_reloc(ksect_ss, &ksect->address, &ss->symbol,
1945 span->start + span->shift);
1947 if (mode("keep-old-code")) {
1948 /* Write ksplice_symbols for all the entry points */
1949 struct entry_point *entry;
1950 for (entry = span->entry_points.data;
1951 entry < span->entry_points.data + span->entry_points.size;
1952 entry++)
1953 write_ksplice_symbol_reloc
1954 (span->ss, sectname, span->ss->contents.data +
1955 span->start + span->shift + entry->offset,
1956 entry->symbol, entry->label, entry->name);
1960 static void write_ksplice_patch_reloc(struct supersect *ss,
1961 const char *sectname, unsigned long *addr,
1962 bfd_size_type size, const char *label,
1963 long addend)
1965 struct supersect *kreloc_ss;
1966 kreloc_ss = make_section(ss->parent, ".ksplice_relocs%s", sectname);
1967 struct ksplice_reloc *kreloc = sect_grow(kreloc_ss, 1,
1968 struct ksplice_reloc);
1970 write_canary(ss, addr_offset(ss, addr), size, -1);
1971 write_ksplice_symbol_backend(kreloc_ss, &kreloc->symbol, NULL,
1972 label, NULL);
1973 write_reloc(kreloc_ss, &kreloc->blank_addr, &ss->symbol,
1974 addr_offset(ss, addr));
1975 reloc_howto_type *howto =
1976 bfd_reloc_type_lookup(ss->parent->abfd,
1977 PASTE(BFD_RELOC_, LONG_BIT));
1978 write_ksplice_reloc_howto(kreloc_ss, &kreloc->howto, howto,
1979 KSPLICE_HOWTO_RELOC);
1980 kreloc->target_addend = addend;
1981 kreloc->insn_addend = 0;
1984 /* Assumes symbol is global, aka only one symbol of that name */
1985 static asymbol *name_to_symbol(struct superbfd *sbfd, const char *name)
1987 if (name == NULL)
1988 return NULL;
1990 asymbol **symp;
1991 for (symp = sbfd->syms.data;
1992 symp < sbfd->syms.data + sbfd->syms.size; symp++) {
1993 asymbol *sym = *symp;
1994 if (strcmp(name, sym->name) == 0 &&
1995 ((sym->flags & BSF_GLOBAL) != 0 ||
1996 bfd_is_und_section(sym->section)))
1997 return sym;
1999 return NULL;
2002 void write_ksplice_patches(struct superbfd *sbfd, struct span *span)
2004 if (span->datapatch) {
2005 write_ksplice_patch(sbfd, span, span->label, 0);
2006 return;
2009 assert(span->patch);
2011 long prev_offset = LONG_MIN;
2012 asymbol *prev_sym = NULL;
2013 const char *prev_label = NULL;
2014 struct entry_point *entry;
2015 for (entry = span->pre_entry_points.data;
2016 entry < span->pre_entry_points.data + span->pre_entry_points.size;
2017 entry++) {
2018 asymbol *sym = name_to_symbol(sbfd, entry->name);
2019 if (sym == NULL && entry->offset != 0) {
2020 /* Since it was global, name and label are the same */
2021 write_ksplice_deleted_patch
2022 (sbfd, entry->label, entry->label, span->ss->name,
2023 entry->offset);
2024 } else if (entry->offset != prev_offset) {
2025 debug1(sbfd, "entry point: %s(%s) %lx\n", entry->label,
2026 entry->name, entry->offset);
2028 if (prev_offset + MAX_TRAMPOLINE_SIZE > entry->offset) {
2029 err(sbfd,
2030 "Overlapping trampolines: %s %lx/%lx\n",
2031 span->label, prev_offset, entry->offset);
2032 DIE;
2035 long target_offset = 0;
2036 if (sym != NULL)
2037 target_offset = sym->value - span->start;
2038 write_ksplice_patch(sbfd, span, entry->label,
2039 target_offset);
2040 prev_offset = entry->offset;
2041 prev_sym = NULL;
2044 if (prev_sym == NULL) {
2045 prev_sym = sym;
2046 prev_label = entry->label;
2047 } else if (sym != NULL &&
2048 (prev_sym->section != sym->section ||
2049 prev_sym->value != sym->value)) {
2050 err(sbfd, "Splitting global symbols in the middle of a "
2051 "span: %s+%lx != %s+%lx!\n",
2052 prev_label, (unsigned long)prev_sym->value,
2053 entry->label, (unsigned long)sym->value);
2054 DIE;
2058 if (prev_offset + MAX_TRAMPOLINE_SIZE > span->size) {
2059 err(sbfd, "Trampoline ends outside span: %s %lx/%lx\n",
2060 span->label, prev_offset, (unsigned long)span->size);
2061 DIE;
2065 void write_ksplice_patch(struct superbfd *sbfd, struct span *span,
2066 const char *label, long offset)
2068 struct supersect *kpatch_ss =
2069 make_section(sbfd, ".ksplice_patches%s", span->ss->name);
2070 struct ksplice_patch *kpatch = sect_grow(kpatch_ss, 1,
2071 struct ksplice_patch);
2073 write_ksplice_patch_reloc(kpatch_ss, span->ss->name, &kpatch->oldaddr,
2074 sizeof(kpatch->oldaddr), label, 0);
2075 if (span->ss->type == SS_TYPE_TEXT) {
2076 kpatch->type = KSPLICE_PATCH_TEXT;
2077 write_patch_storage(kpatch_ss, kpatch, MAX_TRAMPOLINE_SIZE,
2078 NULL);
2079 } else {
2080 kpatch->type = KSPLICE_PATCH_DATA;
2081 kpatch->size = span->contents_size;
2082 struct supersect *data_ss =
2083 make_section(sbfd, ".ksplice_patch_data");
2084 write_reloc(kpatch_ss, &kpatch->contents, &span->ss->symbol,
2085 span->start + span->shift);
2086 char *saved = sect_do_grow(data_ss, 1, span->contents_size, 1);
2087 write_reloc(kpatch_ss, &kpatch->saved, &data_ss->symbol,
2088 addr_offset(data_ss, saved));
2090 write_reloc(kpatch_ss, &kpatch->repladdr, &span->ss->symbol,
2091 span->start + span->shift + offset);
2094 asymbol **make_undefined_symbolp(struct superbfd *sbfd, const char *name)
2096 asymbol **symp;
2097 for (symp = sbfd->syms.data; symp < sbfd->syms.data + sbfd->syms.size;
2098 symp++) {
2099 asymbol *sym = *symp;
2100 if (strcmp(name, sym->name) == 0 &&
2101 bfd_is_und_section(sym->section))
2102 return symp;
2104 asymbol ***sympp;
2105 for (sympp = sbfd->new_syms.data;
2106 sympp < sbfd->new_syms.data + sbfd->new_syms.size; sympp++) {
2107 asymbol **symp = *sympp;
2108 asymbol *sym = *symp;
2109 if (strcmp(name, sym->name) == 0 &&
2110 bfd_is_und_section(sym->section))
2111 return symp;
2114 symp = malloc(sizeof(*symp));
2115 *symp = bfd_make_empty_symbol(sbfd->abfd);
2116 asymbol *sym = *symp;
2117 sym->name = name;
2118 sym->section = bfd_und_section_ptr;
2119 sym->flags = 0;
2120 sym->value = 0;
2121 *vec_grow(&sbfd->new_syms, 1) = symp;
2122 return symp;
2125 void write_ksplice_deleted_patch(struct superbfd *sbfd, const char *name,
2126 const char *label, const char *sectname,
2127 long offset)
2129 struct supersect *kpatch_ss =
2130 make_section(sbfd, ".ksplice_patches%s", sectname);
2131 struct ksplice_patch *kpatch = sect_grow(kpatch_ss, 1,
2132 struct ksplice_patch);
2134 write_ksplice_patch_reloc(kpatch_ss, sectname, &kpatch->oldaddr,
2135 sizeof(kpatch->oldaddr), label, 0);
2136 kpatch->type = KSPLICE_PATCH_TEXT;
2137 asymbol **symp = make_undefined_symbolp(sbfd, strdup(name));
2138 write_reloc(kpatch_ss, &kpatch->repladdr, symp, offset);
2139 write_patch_storage(kpatch_ss, kpatch, MAX_TRAMPOLINE_SIZE, NULL);
2142 void write_ksplice_export(struct superbfd *sbfd, struct span *span, bool del)
2144 struct supersect *kpatch_ss = make_section(sbfd, ".ksplice_patches");
2145 struct ksplice_patch *kpatch = sect_grow(kpatch_ss, 1,
2146 struct ksplice_patch);
2147 struct supersect *data_ss;
2149 const struct table_section *ts = get_table_section(span->ss->name);
2150 assert(ts != NULL);
2151 const char **addr =
2152 span->ss->contents.data + span->start + ts->other_offset;
2153 const char *symname = read_string(span->ss, addr);
2155 char *oldname, *newname;
2156 if (del) {
2157 oldname = strprintf("%s:%s", span->ss->name, symname);
2158 newname = strprintf("DISABLED_%s_%s", symname, kid);
2159 } else {
2160 oldname = strprintf("%s:DISABLED_%s_%s", span->ss->name,
2161 symname, kid);
2162 newname = strprintf("%s", symname);
2163 write_string(span->ss, addr, "DISABLED_%s_%s", symname, kid);
2166 write_ksplice_patch_reloc(kpatch_ss, "", &kpatch->oldaddr,
2167 sizeof(kpatch->oldaddr), oldname,
2168 ts->other_offset);
2169 kpatch->type = KSPLICE_PATCH_EXPORT;
2170 const char **namep = write_patch_storage(kpatch_ss, kpatch,
2171 sizeof(newname), &data_ss);
2172 write_string(data_ss, namep, "%s", newname);
2175 void filter_table_sections(struct superbfd *isbfd)
2177 struct supersect *tables_ss =
2178 fetch_supersect(offsets_sbfd,
2179 bfd_get_section_by_name(offsets_sbfd->abfd,
2180 ".ksplice_table_sections"));
2181 const struct table_section *ts;
2182 for (ts = tables_ss->contents.data;
2183 (void *)ts < tables_ss->contents.data + tables_ss->contents.size;
2184 ts++) {
2185 struct table_section s = *ts;
2186 s.sect = read_string(tables_ss, &ts->sect);
2187 s.other_sect = read_string(tables_ss, &ts->other_sect);
2188 s.crc_sect = read_string(tables_ss, &ts->crc_sect);
2189 filter_table_section(isbfd, &s);
2193 void filter_table_section(struct superbfd *sbfd, const struct table_section *s)
2195 asection *isection = bfd_get_section_by_name(sbfd->abfd, s->sect);
2196 if (isection == NULL)
2197 return;
2198 struct supersect *ss = fetch_supersect(sbfd, isection);
2200 void *entry;
2201 for (entry = ss->contents.data;
2202 entry < ss->contents.data + ss->contents.size;
2203 entry += s->entry_size) {
2204 struct span *span = find_span(ss, addr_offset(ss, entry));
2205 assert(span != NULL);
2207 if (s->has_addr) {
2208 struct span *sym_span =
2209 span_offset_target_span(span, s->addr_offset);
2210 assert(sym_span != NULL);
2211 if (sym_span->keep)
2212 keep_span(span);
2215 if (s->other_sect != NULL) {
2216 struct span *sym_span =
2217 span_offset_target_span(span, s->other_offset);
2218 assert(sym_span != NULL);
2219 if (span->keep)
2220 keep_span(sym_span);
2223 if (s->crc_sect != NULL) {
2224 struct span *crc_span = get_crc_span(span, s);
2225 assert(crc_span != NULL);
2226 if (span->keep && mode("keep-new-code"))
2227 keep_span(crc_span);
2232 static void match_other_spans(struct span *old_span, struct span *new_span)
2234 const struct table_section *ts = get_table_section(old_span->ss->name);
2235 if (ts == NULL)
2236 return;
2238 if (old_span->match == new_span && new_span->match == old_span &&
2239 ts->other_sect != NULL) {
2240 void *old_entry = old_span->ss->contents.data + old_span->start;
2241 void *new_entry = new_span->ss->contents.data + new_span->start;
2242 arelent *old_reloc =
2243 find_reloc(old_span->ss, old_entry + ts->other_offset);
2244 arelent *new_reloc =
2245 find_reloc(new_span->ss, new_entry + ts->other_offset);
2246 assert(old_reloc != NULL && new_reloc != NULL);
2247 struct span *old_other_span =
2248 reloc_target_span(old_span->ss, old_reloc);
2249 struct span *new_other_span =
2250 reloc_target_span(new_span->ss, new_reloc);
2251 assert(old_other_span != NULL && new_other_span != NULL);
2252 match_spans(old_other_span, new_other_span);
2256 static void match_table_spans(struct span *old_span, struct span *new_span)
2258 const struct table_section *ts = get_table_section(old_span->ss->name);
2260 if (strcmp(old_span->ss->name, new_span->ss->name) != 0)
2261 return;
2262 if (ts == NULL || old_span->ss->type != SS_TYPE_SPECIAL ||
2263 new_span->ss->type != SS_TYPE_SPECIAL)
2264 return;
2265 if (old_span->match != NULL || new_span->match != NULL)
2266 return;
2268 if (ts->has_addr) {
2269 void *old_entry = old_span->ss->contents.data + old_span->start;
2270 void *new_entry = new_span->ss->contents.data + new_span->start;
2271 arelent *old_reloc =
2272 find_reloc(old_span->ss, old_entry + ts->addr_offset);
2273 arelent *new_reloc =
2274 find_reloc(new_span->ss, new_entry + ts->addr_offset);
2275 assert(old_reloc != NULL && new_reloc != NULL);
2276 struct span *old_sym_span =
2277 reloc_target_span(old_span->ss, old_reloc);
2278 struct span *new_sym_span =
2279 reloc_target_span(new_span->ss, new_reloc);
2280 assert(old_sym_span != NULL && new_sym_span != NULL);
2281 if (old_sym_span->match == new_sym_span &&
2282 new_sym_span->match == old_sym_span &&
2283 old_reloc->address - old_sym_span->start ==
2284 new_reloc->address - new_sym_span->start)
2285 match_spans(old_span, new_span);
2289 static struct span *get_crc_span(struct span *span,
2290 const struct table_section *ts)
2292 void *entry = span->ss->contents.data + span->start;
2293 asection *crc_sect = bfd_get_section_by_name(span->ss->parent->abfd,
2294 ts->crc_sect);
2295 if (crc_sect == NULL)
2296 return NULL;
2297 struct supersect *crc_ss = fetch_supersect(span->ss->parent, crc_sect);
2298 if (crc_ss == NULL)
2299 return NULL;
2300 struct span *crc_span = find_span(crc_ss, addr_offset(span->ss, entry) /
2301 ts->entry_size * ts->crc_size);
2302 return crc_span;
2305 void mark_precallable_spans(struct superbfd *sbfd)
2307 asection *sect;
2308 struct supersect *ss, *sym_ss;
2309 struct span *address_span, *target_span;
2310 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2311 ss = fetch_supersect(sbfd, sect);
2312 arelent **relocp;
2313 if (ss->type == SS_TYPE_SPECIAL)
2314 continue;
2315 for (relocp = ss->relocs.data;
2316 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
2317 asymbol *sym = *(*relocp)->sym_ptr_ptr;
2318 address_span = find_span(ss, (*relocp)->address);
2319 if (!address_span->precallable)
2320 continue;
2321 target_span = reloc_target_span(ss, *relocp);
2322 if (target_span == NULL || target_span->keep)
2323 continue;
2324 sym_ss = fetch_supersect(sbfd, sym->section);
2325 if (sym_ss->type == SS_TYPE_IGNORED)
2326 continue;
2327 target_span->precallable = true;
2328 changed = true;
2333 void keep_referenced_sections(struct superbfd *sbfd)
2335 asection *sect;
2336 struct supersect *ss, *sym_ss;
2337 struct span *address_span, *target_span;
2338 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2339 ss = fetch_supersect(sbfd, sect);
2340 arelent **relocp;
2341 if (ss->type == SS_TYPE_SPECIAL)
2342 continue;
2343 for (relocp = ss->relocs.data;
2344 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
2345 asymbol *sym = *(*relocp)->sym_ptr_ptr;
2346 address_span = find_span(ss, (*relocp)->address);
2347 if (!address_span->keep)
2348 continue;
2349 target_span = reloc_target_span(ss, *relocp);
2350 if (target_span == NULL || target_span->keep)
2351 continue;
2352 sym_ss = fetch_supersect(sbfd, sym->section);
2353 if (sym_ss->type == SS_TYPE_IGNORED)
2354 continue;
2355 keep_span(target_span);
2356 changed = true;
2361 void copy_symbols(struct asymbolp_vec *osyms, struct asymbolpp_vec *isyms)
2363 asymbol ***sympp;
2364 for (sympp = isyms->data; sympp < isyms->data + isyms->size; sympp++)
2365 *vec_grow(osyms, 1) = **sympp;
2368 /* Modified function from GNU Binutils objcopy.c */
2369 bfd_boolean copy_object(bfd *ibfd, bfd *obfd)
2371 assert(bfd_set_format(obfd, bfd_get_format(ibfd)));
2373 bfd_vma start = bfd_get_start_address(ibfd);
2375 flagword flags = bfd_get_file_flags(ibfd);
2376 flags &= bfd_applicable_file_flags(obfd);
2378 assert(bfd_set_start_address(obfd, start)
2379 && bfd_set_file_flags(obfd, flags));
2381 enum bfd_architecture iarch = bfd_get_arch(ibfd);
2382 unsigned int imach = bfd_get_mach(ibfd);
2383 assert(bfd_set_arch_mach(obfd, iarch, imach));
2384 assert(bfd_set_format(obfd, bfd_get_format(ibfd)));
2386 /* BFD mandates that all output sections be created and sizes set before
2387 any output is done. Thus, we traverse all sections multiple times. */
2388 bfd_map_over_sections(ibfd, setup_section, obfd);
2390 struct supersect *new_supersects = fetch_superbfd(ibfd)->new_supersects;
2391 struct supersect *ss;
2392 for (ss = new_supersects; ss != NULL; ss = ss->next)
2393 setup_new_section(obfd, ss);
2395 /* Mark symbols used in output relocations so that they
2396 are kept, even if they are local labels or static symbols.
2398 Note we iterate over the input sections examining their
2399 relocations since the relocations for the output sections
2400 haven't been set yet. mark_symbols_used_in_relocations will
2401 ignore input sections which have no corresponding output
2402 section. */
2404 bfd_map_over_sections(ibfd, mark_symbols_used_in_relocations, NULL);
2405 for (ss = new_supersects; ss != NULL; ss = ss->next)
2406 ss_mark_symbols_used_in_relocations(ss);
2407 struct asymbolp_vec osyms;
2408 vec_init(&osyms);
2409 filter_symbols(ibfd, obfd, &osyms, &fetch_superbfd(ibfd)->syms);
2410 copy_symbols(&osyms, &fetch_superbfd(ibfd)->new_syms);
2412 bfd_set_symtab(obfd, osyms.data, osyms.size);
2414 /* This has to happen after the symbol table has been set. */
2415 bfd_map_over_sections(obfd, write_section, NULL);
2417 /* Allow the BFD backend to copy any private data it understands
2418 from the input BFD to the output BFD. This is done last to
2419 permit the routine to look at the filtered symbol table, which is
2420 important for the ECOFF code at least. */
2421 assert(bfd_copy_private_bfd_data(ibfd, obfd));
2423 return TRUE;
2426 /* Modified function from GNU Binutils objcopy.c */
2427 void setup_section(bfd *ibfd, asection *isection, void *obfdarg)
2429 struct superbfd *isbfd = fetch_superbfd(ibfd);
2430 struct supersect *ss = fetch_supersect(isbfd, isection);
2431 bfd *obfd = obfdarg;
2432 bfd_vma vma;
2434 if (!ss->keep)
2435 return;
2437 asection *osection = bfd_make_section_anyway(obfd, ss->name);
2438 assert(osection != NULL);
2440 osection->userdata = ss;
2441 bfd_set_section_flags(obfd, osection, ss->flags);
2442 ss->symbol = osection->symbol;
2443 assert(bfd_set_section_size(obfd, osection, ss->contents.size));
2445 vma = bfd_section_vma(ibfd, isection);
2446 assert(bfd_set_section_vma(obfd, osection, vma));
2448 osection->lma = isection->lma;
2449 assert(bfd_set_section_alignment(obfd, osection, ss->alignment));
2450 osection->entsize = ss->entsize;
2451 osection->output_section = osection;
2452 osection->output_offset = 0;
2453 isection->output_section = osection;
2454 isection->output_offset = 0;
2455 return;
2458 void setup_new_section(bfd *obfd, struct supersect *ss)
2460 asection *osection = bfd_make_section_anyway(obfd, ss->name);
2461 assert(osection != NULL);
2462 bfd_set_section_flags(obfd, osection, ss->flags);
2464 osection->userdata = ss;
2465 ss->symbol = osection->symbol;
2466 assert(bfd_set_section_size(obfd, osection, ss->contents.size));
2467 assert(bfd_set_section_vma(obfd, osection, 0));
2469 osection->lma = 0;
2470 assert(bfd_set_section_alignment(obfd, osection, ss->alignment));
2471 osection->entsize = ss->entsize;
2472 osection->output_section = osection;
2473 osection->output_offset = 0;
2476 static int compare_reloc_addresses(const void *aptr, const void *bptr)
2478 const arelent *const *a = aptr, *const *b = bptr;
2479 return (*a)->address - (*b)->address;
2482 static void delete_obsolete_relocs(struct supersect *ss)
2484 if (ss->new_relocs.size == 0)
2485 return;
2487 qsort(ss->relocs.data, ss->relocs.size, sizeof(*ss->relocs.data),
2488 compare_reloc_addresses);
2489 qsort(ss->new_relocs.data, ss->new_relocs.size,
2490 sizeof(*ss->new_relocs.data), compare_reloc_addresses);
2492 struct arelentp_vec orig_relocs;
2493 vec_move(&orig_relocs, &ss->relocs);
2495 arelent **relocp, **new_relocp = ss->new_relocs.data;
2496 for (relocp = orig_relocs.data;
2497 relocp < orig_relocs.data + orig_relocs.size; relocp++) {
2498 while (new_relocp < ss->new_relocs.data + ss->new_relocs.size &&
2499 (*new_relocp)->address < (*relocp)->address)
2500 new_relocp++;
2501 arelent *reloc = *relocp, *new_reloc = *new_relocp;
2502 if (new_relocp == ss->new_relocs.data + ss->new_relocs.size ||
2503 reloc->address != new_reloc->address)
2504 *vec_grow(&ss->relocs, 1) = reloc;
2508 void write_section(bfd *obfd, asection *osection, void *arg)
2510 struct supersect *ss = osection->userdata;
2512 if ((ss->flags & SEC_GROUP) != 0 || ss->contents.size == 0)
2513 return;
2515 delete_obsolete_relocs(ss);
2517 arelent **relocp;
2518 char *error_message;
2519 for (relocp = ss->new_relocs.data;
2520 relocp < ss->new_relocs.data + ss->new_relocs.size; relocp++) {
2521 bfd_vma val;
2522 if (bfd_get_arch(obfd) == bfd_arch_arm)
2523 val = osection->use_rela_p ? 0 : (*relocp)->addend;
2524 else
2525 val = 0;
2526 bfd_put(bfd_get_reloc_size((*relocp)->howto) * 8, obfd, val,
2527 ss->contents.data + (*relocp)->address);
2528 if (bfd_install_relocation(obfd, *relocp, ss->contents.data,
2529 0, osection, &error_message) !=
2530 bfd_reloc_ok) {
2531 err(ss->parent, "ksplice: error installing reloc: %s",
2532 error_message);
2533 DIE;
2535 if (mode("finalize")) {
2536 /* Check that all our sections will be allocated */
2537 asymbol *sym = *((*relocp)->sym_ptr_ptr);
2538 if (!bfd_is_const_section(sym->section)) {
2539 struct supersect *sym_ss =
2540 fetch_supersect(ss->parent, sym->section);
2541 assert((sym_ss->flags & SEC_ALLOC) != 0);
2545 memcpy(vec_grow(&ss->relocs, ss->new_relocs.size), ss->new_relocs.data,
2546 ss->new_relocs.size * sizeof(*ss->new_relocs.data));
2548 bfd_set_reloc(obfd, osection,
2549 ss->relocs.size == 0 ? NULL : ss->relocs.data,
2550 ss->relocs.size);
2552 if (ss->flags & SEC_HAS_CONTENTS)
2553 assert(bfd_set_section_contents
2554 (obfd, osection, ss->contents.data, 0,
2555 ss->contents.size));
2558 /* Modified function from GNU Binutils objcopy.c
2560 * Mark all the symbols which will be used in output relocations with
2561 * the BSF_KEEP flag so that those symbols will not be stripped.
2563 * Ignore relocations which will not appear in the output file.
2565 void mark_symbols_used_in_relocations(bfd *abfd, asection *isection,
2566 void *ignored)
2568 struct superbfd *sbfd = fetch_superbfd(abfd);
2569 if (isection->output_section == NULL)
2570 return;
2572 struct supersect *ss = fetch_supersect(sbfd, isection);
2573 ss_mark_symbols_used_in_relocations(ss);
2576 void ss_mark_symbols_used_in_relocations(struct supersect *ss)
2578 /* Examine each symbol used in a relocation. If it's not one of the
2579 special bfd section symbols, then mark it with BSF_KEEP. */
2580 arelent **relocp;
2581 for (relocp = ss->relocs.data;
2582 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
2583 asymbol *sym = *(*relocp)->sym_ptr_ptr;
2584 if (!(bfd_is_const_section(sym->section) &&
2585 sym == sym->section->symbol))
2586 sym->flags |= BSF_KEEP;
2588 for (relocp = ss->new_relocs.data;
2589 relocp < ss->new_relocs.data + ss->new_relocs.size; relocp++) {
2590 asymbol *sym = *(*relocp)->sym_ptr_ptr;
2591 if (!(bfd_is_const_section(sym->section) &&
2592 sym == sym->section->symbol))
2593 sym->flags |= BSF_KEEP;
2597 static bool deleted_table_section_symbol(bfd *abfd, asymbol *sym)
2599 struct superbfd *sbfd = fetch_superbfd(abfd);
2600 if (bfd_is_const_section(sym->section))
2601 return false;
2602 struct supersect *ss = fetch_supersect(sbfd, sym->section);
2604 asymbol **symp;
2605 for (symp = ss->syms.data; symp < ss->syms.data + ss->syms.size; symp++) {
2606 if (sym == *symp)
2607 break;
2609 return symp >= ss->syms.data + ss->syms.size &&
2610 (sym->flags & BSF_SECTION_SYM) == 0;
2613 void filter_symbols(bfd *ibfd, bfd *obfd, struct asymbolp_vec *osyms,
2614 struct asymbolp_vec *isyms)
2616 asymbol **symp;
2617 struct superbfd *sbfd = fetch_superbfd(ibfd);
2618 for (symp = isyms->data; symp < isyms->data + isyms->size; symp++) {
2619 asymbol *sym = *symp;
2620 struct supersect *sym_ss = NULL;
2621 struct span *sym_span = NULL;
2622 if (!bfd_is_const_section(sym->section)) {
2623 sym_ss = fetch_supersect(sbfd, sym->section);
2624 sym_span = find_span(sym_ss, sym->value);
2627 if (mode("keep") && (sym->flags & BSF_GLOBAL) != 0 &&
2628 !(mode("keep-new-code") && sym_span != NULL &&
2629 sym_span->new))
2630 sym->flags = (sym->flags & ~BSF_GLOBAL) | BSF_LOCAL;
2632 if (mode("finalize") && (sym->flags & BSF_GLOBAL) != 0)
2633 sym->flags = (sym->flags & ~BSF_GLOBAL) | BSF_LOCAL;
2635 bool keep = bfd_is_const_section(sym->section) ||
2636 (sym_ss->keep && (sym->flags & BSF_SECTION_SYM) != 0) ||
2637 (sym_span != NULL && sym_span->keep);
2638 if (bfd_is_und_section(sym->section) &&
2639 (sym->flags & BSF_KEEP) == 0)
2640 keep = false;
2641 if (bfd_is_abs_section(sym->section) &&
2642 (sym->flags & BSF_KEEP) == 0 &&
2643 (sym->flags & BSF_FILE) == 0)
2644 keep = false;
2645 if (deleted_table_section_symbol(ibfd, sym))
2646 keep = false;
2648 if (mode("keep-old-code") && sym_ss != NULL &&
2649 sym_ss->type == SS_TYPE_EXPORT)
2650 keep = false;
2652 if (keep) {
2653 if (sym_ss != NULL && !sym_ss->keep) {
2654 err(sbfd, "Kept symbol %s in unkept section "
2655 "%s\n", sym->name, sym->section->name);
2656 DIE;
2658 *vec_grow(osyms, 1) = sym;
2663 static bool is_table_section(const char *name, bool consider_other,
2664 bool consider_crc)
2666 struct supersect *tables_ss =
2667 fetch_supersect(offsets_sbfd,
2668 bfd_get_section_by_name(offsets_sbfd->abfd,
2669 ".ksplice_table_sections"));
2670 const struct table_section *ts;
2671 for (ts = tables_ss->contents.data;
2672 (void *)ts < tables_ss->contents.data + tables_ss->contents.size;
2673 ts++) {
2674 if (strcmp(name, read_string(tables_ss, &ts->sect)) == 0)
2675 return true;
2676 const char *osect_name = read_string(tables_ss,
2677 &ts->other_sect);
2678 if (consider_other && osect_name != NULL &&
2679 strcmp(name, osect_name) == 0)
2680 return true;
2681 const char *crc_name = read_string(tables_ss, &ts->crc_sect);
2682 if (consider_crc && crc_name != NULL &&
2683 strcmp(name, crc_name) == 0)
2684 return true;
2686 return false;
2689 const struct table_section *get_table_section(const char *name)
2691 struct supersect *tables_ss =
2692 fetch_supersect(offsets_sbfd,
2693 bfd_get_section_by_name(offsets_sbfd->abfd,
2694 ".ksplice_table_sections"));
2695 const struct table_section *ts;
2696 for (ts = tables_ss->contents.data;
2697 (void *)ts < tables_ss->contents.data + tables_ss->contents.size;
2698 ts++) {
2699 if (strcmp(name, read_string(tables_ss, &ts->sect)) == 0) {
2700 if (ts->entry_contents_size != 0)
2701 assert(align(ts->entry_contents_size,
2702 ts->entry_align) ==
2703 ts->entry_size);
2704 struct table_section *ns = malloc(sizeof(*ns));
2705 *ns = *ts;
2706 ns->sect = read_string(tables_ss, &ts->sect);
2707 ns->crc_sect = read_string(tables_ss, &ts->crc_sect);
2708 ns->other_sect =
2709 read_string(tables_ss, &ts->other_sect);
2710 return ns;
2713 return NULL;
2716 enum supersect_type supersect_type(struct supersect *ss)
2718 if (mode("finalize") &&
2719 strcmp(finalize_target, "vmlinux") == 0 &&
2720 (strstarts(ss->name, ".ksplice_relocs.exit") ||
2721 strstarts(ss->name, ".ksplice_sections.exit") ||
2722 strstarts(ss->name, ".ksplice_patches.exit")))
2723 return SS_TYPE_EXIT;
2724 if (strstarts(ss->name, ".ksplice_call"))
2725 return SS_TYPE_KSPLICE_CALL;
2726 if (strstarts(ss->name, ".ksplice_extract"))
2727 return SS_TYPE_KSPLICE_EXTRACT;
2728 if (strstarts(ss->name, ".ksplice_options"))
2729 return SS_TYPE_SPECIAL;
2730 if (strstarts(ss->name, ".ksplice"))
2731 return SS_TYPE_KSPLICE;
2733 if (strstarts(ss->name, ".init"))
2734 return SS_TYPE_IGNORED;
2735 if (strstarts(ss->name, ".security_initcall.init"))
2736 return SS_TYPE_IGNORED;
2737 if (strstarts(ss->name, ".con_initcall.init"))
2738 return SS_TYPE_IGNORED;
2739 if (strstarts(ss->name, ".x86cpuvendor.init"))
2740 return SS_TYPE_IGNORED;
2741 if (strstarts(ss->name, ".early_param.init"))
2742 return SS_TYPE_IGNORED;
2743 if (strstarts(ss->name, ".taglist.init"))
2744 return SS_TYPE_IGNORED;
2745 if (strstarts(ss->name, ".arch.info.init"))
2746 return SS_TYPE_IGNORED;
2747 if (strstarts(ss->name, ".proc.info.init"))
2748 return SS_TYPE_IGNORED;
2749 /* .pci_fixup_* sections really should be treated as global rodata
2750 referenced only from quirks.c */
2751 if (strstarts(ss->name, ".pci_fixup_"))
2752 return SS_TYPE_IGNORED;
2753 /* .builtin_fw sections are similar to .pci_fixup */
2754 if (strstarts(ss->name, ".builtin_fw"))
2755 return SS_TYPE_IGNORED;
2756 /* same for .tracedata */
2757 if (strstarts(ss->name, ".tracedata"))
2758 return SS_TYPE_IGNORED;
2759 if (strstarts(ss->name, ".debug"))
2760 return SS_TYPE_IGNORED;
2761 /* .eh_frame should probably be discarded, not ignored */
2762 if (strstarts(ss->name, ".eh_frame"))
2763 return SS_TYPE_IGNORED;
2764 if (config->ignore_devinit && strstarts(ss->name, ".devinit"))
2765 return SS_TYPE_IGNORED;
2766 if (config->ignore_meminit && strstarts(ss->name, ".meminit"))
2767 return SS_TYPE_IGNORED;
2768 if (config->ignore_cpuinit && strstarts(ss->name, ".cpuinit"))
2769 return SS_TYPE_IGNORED;
2770 if (config->ignore_devinit && strstarts(ss->name, ".devexit"))
2771 return SS_TYPE_IGNORED;
2772 if (config->ignore_meminit && strstarts(ss->name, ".memexit"))
2773 return SS_TYPE_IGNORED;
2774 if (config->ignore_cpuinit && strstarts(ss->name, ".cpuexit"))
2775 return SS_TYPE_IGNORED;
2776 if (strstarts(ss->name, ".vgetcpu_mode") ||
2777 strstarts(ss->name, ".jiffies") ||
2778 strstarts(ss->name, ".wall_jiffies") ||
2779 strstarts(ss->name, ".vxtime") ||
2780 strstarts(ss->name, ".sys_tz") ||
2781 strstarts(ss->name, ".sysctl_vsyscall") ||
2782 strstarts(ss->name, ".xtime") ||
2783 strstarts(ss->name, ".xtime_lock") ||
2784 strstarts(ss->name, ".vsyscall"))
2785 return SS_TYPE_IGNORED;
2786 if (strstarts(ss->name, ".vdso"))
2787 return SS_TYPE_IGNORED;
2789 if (strstarts(ss->name, ".exit.text"))
2790 return SS_TYPE_TEXT;
2791 if (strstarts(ss->name, ".exit.data"))
2792 return SS_TYPE_DATA;
2794 if (strstarts(ss->name, ".text") ||
2795 strstarts(ss->name, ".kernel.text") ||
2796 strstarts(ss->name, ".devinit.text") ||
2797 strstarts(ss->name, ".meminit.text") ||
2798 strstarts(ss->name, ".cpuinit.text") ||
2799 strstarts(ss->name, ".devexit.text") ||
2800 strstarts(ss->name, ".memexit.text") ||
2801 strstarts(ss->name, ".cpuexit.text") ||
2802 strstarts(ss->name, ".ref.text") ||
2803 strstarts(ss->name, ".spinlock.text") ||
2804 strstarts(ss->name, ".kprobes.text") ||
2805 strstarts(ss->name, ".sched.text") ||
2806 strstarts(ss->name, ".entry.text") || /* OpenVZ */
2807 (mode("keep-old-code") && strstarts(ss->name, ".fixup")))
2808 return SS_TYPE_TEXT;
2810 int n = -1;
2811 if (sscanf(ss->name, ".rodata.str%*u.%*u%n", &n) >= 0 &&
2812 n == strlen(ss->name))
2813 return ss->entsize == 1 ? SS_TYPE_STRING : SS_TYPE_RODATA;
2815 if (strstarts(ss->name, ".rodata") ||
2816 strstarts(ss->name, ".kernel.rodata") ||
2817 strstarts(ss->name, ".devinit.rodata") ||
2818 strstarts(ss->name, ".meminit.rodata") ||
2819 strstarts(ss->name, ".cpuinit.rodata") ||
2820 strstarts(ss->name, ".devexit.rodata") ||
2821 strstarts(ss->name, ".memexit.rodata") ||
2822 strstarts(ss->name, ".cpuexit.rodata") ||
2823 strstarts(ss->name, ".ref.rodata") ||
2824 strstarts(ss->name, "__tracepoints_strings") ||
2825 strstarts(ss->name, "__markers_strings") ||
2826 (mode("keep-old-code") && strstarts(ss->name, "__ex_table")))
2827 return SS_TYPE_RODATA;
2829 if (strstarts(ss->name, ".bss"))
2830 return SS_TYPE_DATA;
2832 /* Ignore .data.percpu sections */
2833 if (strstarts(ss->name, ".data.percpu") ||
2834 strstarts(ss->name, ".kernel.data.percpu") ||
2835 strstarts(ss->name, ".data..percpu"))
2836 return SS_TYPE_IGNORED;
2837 if (strstarts(ss->name, ".data") ||
2838 strstarts(ss->name, ".kernel.data") ||
2839 strstarts(ss->name, ".devinit.data") ||
2840 strstarts(ss->name, ".cpuinit.data") ||
2841 strstarts(ss->name, ".meminit.data") ||
2842 strstarts(ss->name, ".devexit.data") ||
2843 strstarts(ss->name, ".memexit.data") ||
2844 strstarts(ss->name, ".cpuexit.data") ||
2845 strstarts(ss->name, ".ref.data") ||
2846 strstarts(ss->name, "__tracepoints") ||
2847 strstarts(ss->name, "__markers"))
2848 return SS_TYPE_DATA;
2850 /* We replace all the ksymtab strings, so delete them */
2851 if (strcmp(ss->name, "__ksymtab_strings") == 0)
2852 return SS_TYPE_STRING;
2853 if (strstarts(ss->name, "__ksymtab"))
2854 return SS_TYPE_EXPORT;
2856 if (strstarts(ss->name, "__bug_table"))
2857 return SS_TYPE_BUGTABLE;
2859 if (is_table_section(ss->name, true, true))
2860 return SS_TYPE_SPECIAL;
2862 if (strstarts(ss->name, ".ARM."))
2863 return SS_TYPE_SPECIAL;
2865 if (strstarts(ss->name, ".note"))
2866 return SS_TYPE_IGNORED;
2867 if (strstarts(ss->name, ".comment"))
2868 return SS_TYPE_IGNORED;
2869 if (strstarts(ss->name, "__param"))
2870 return SS_TYPE_IGNORED;
2871 if (strstarts(ss->name, "__obsparm"))
2872 return SS_TYPE_IGNORED;
2873 if (strstarts(ss->name, ".exitcall.exit"))
2874 return SS_TYPE_IGNORED;
2875 if (strstarts(ss->name, ".modinfo"))
2876 return SS_TYPE_IGNORED;
2878 return SS_TYPE_UNKNOWN;
2881 void initialize_supersect_types(struct superbfd *sbfd)
2883 asection *sect;
2884 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2885 struct supersect *ss = fetch_supersect(sbfd, sect);
2886 ss->type = supersect_type(ss);
2887 ss->orig_type = ss->type;
2888 if (ss->type == SS_TYPE_UNKNOWN) {
2889 err(sbfd, "Unknown section type: %s\n", ss->name);
2890 DIE;
2895 static void init_label_map(struct superbfd *sbfd)
2897 struct label_map *map;
2899 vec_init(&sbfd->maps);
2900 init_csyms(sbfd);
2901 init_callers(sbfd);
2903 struct symbol_hash csyms;
2904 symbol_hash_init(&csyms);
2906 asymbol **symp;
2907 for (symp = sbfd->syms.data;
2908 symp < sbfd->syms.data + sbfd->syms.size; symp++) {
2909 asymbol *csym = canonical_symbol(sbfd, *symp);
2910 if (csym == NULL)
2911 continue;
2912 char *key = strprintf("%p", csym);
2913 asymbol **csymp = symbol_hash_lookup(&csyms, key, TRUE);
2914 free(key);
2915 if (*csymp != NULL)
2916 continue;
2917 *csymp = csym;
2919 map = vec_grow(&sbfd->maps, 1);
2920 map->csym = csym;
2921 map->count = 0;
2922 map->label = symbol_label(sbfd, csym);
2925 struct label_mapp_hash label_maps;
2926 label_mapp_hash_init(&label_maps);
2927 for (map = sbfd->maps.data;
2928 map < sbfd->maps.data + sbfd->maps.size; map++) {
2929 struct label_map **mapp =
2930 label_mapp_hash_lookup(&label_maps, map->label, TRUE);
2931 if (*mapp == NULL) {
2932 *mapp = map;
2933 continue;
2936 struct label_map *first_map = *mapp;
2937 if (first_map->count == 0)
2938 first_map->label = strprintf("%s~%d", map->label, 0);
2939 map->label = strprintf("%s~%d", map->label, ++first_map->count);
2942 label_mapp_hash_init(&sbfd->maps_hash);
2943 for (map = sbfd->maps.data;
2944 map < sbfd->maps.data + sbfd->maps.size; map++) {
2945 char *key = strprintf("%p", map->csym);
2946 struct label_map **mapp =
2947 label_mapp_hash_lookup(&sbfd->maps_hash, key, TRUE);
2948 free(key);
2949 *mapp = map;
2950 map->orig_label = map->label;
2954 static const char *label_lookup(struct superbfd *sbfd, asymbol *sym)
2956 asymbol *csym = canonical_symbol(sbfd, sym);
2957 char *key = strprintf("%p", csym);
2958 struct label_map **mapp =
2959 label_mapp_hash_lookup(&sbfd->maps_hash, key, FALSE);
2960 free(key);
2961 if (mapp == NULL)
2962 DIE;
2963 return (*mapp)->label;
2966 static void print_label_changes(struct superbfd *sbfd)
2968 asection *sect;
2969 struct span *span;
2970 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2971 struct supersect *ss = fetch_supersect(sbfd, sect);
2972 for (span = ss->spans.data;
2973 span < ss->spans.data + ss->spans.size; span++) {
2974 if (strcmp(span->label, span->orig_label) != 0)
2975 debug1(sbfd, "Label change: %s -> %s\n",
2976 span->label, span->orig_label);
2981 static void label_map_set(struct superbfd *sbfd, const char *oldlabel,
2982 const char *label)
2984 struct label_map *map;
2985 for (map = sbfd->maps.data;
2986 map < sbfd->maps.data + sbfd->maps.size; map++) {
2987 if (strcmp(map->orig_label, oldlabel) == 0) {
2988 if (strcmp(map->orig_label, map->label) != 0 &&
2989 strcmp(map->label, label) != 0)
2990 DIE;
2991 map->label = label;
2992 return;
2995 DIE;
2998 static void change_initial_label(struct span *span, const char *label)
3000 struct superbfd *sbfd = span->ss->parent;
3001 span->label = label;
3002 span->orig_label = label;
3003 if (span->symbol) {
3004 asymbol *csym = canonical_symbol(sbfd, span->symbol);
3005 char *key = strprintf("%p", csym);
3006 struct label_map **mapp =
3007 label_mapp_hash_lookup(&sbfd->maps_hash, key, FALSE);
3008 free(key);
3009 assert(mapp);
3010 (*mapp)->label = span->label;
3011 (*mapp)->orig_label = span->orig_label;
3012 span->symbol = NULL;
3016 static void init_callers(struct superbfd *sbfd)
3018 string_hash_init(&sbfd->callers);
3019 asection *sect;
3020 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
3021 struct supersect *ss = fetch_supersect(sbfd, sect);
3022 arelent **relocp;
3023 for (relocp = ss->relocs.data;
3024 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
3025 asymbol *sym = *(*relocp)->sym_ptr_ptr;
3026 unsigned long val =
3027 sym->value + reloc_target_offset(ss, *relocp);
3028 char *key = strprintf("%s+%lx", sym->section->name,
3029 val);
3030 const char **ret = string_hash_lookup(&sbfd->callers,
3031 key, TRUE);
3032 free(key);
3033 asymbol *csym = canonical_symbol(sbfd, sect->symbol);
3034 if (*ret != NULL)
3035 *ret = "*multiple_callers*";
3036 else if (static_local_symbol(sbfd, csym))
3037 *ret = static_local_symbol(sbfd, csym);
3038 else
3039 *ret = sect->name;
3044 static const char *find_caller(struct supersect *ss, asymbol *sym)
3046 char *key = strprintf("%s+%lx", sym->section->name,
3047 (unsigned long)sym->value);
3048 const char **ret = string_hash_lookup(&ss->parent->callers, key, FALSE);
3049 free(key);
3051 if (ret == NULL)
3052 return "*no_caller*";
3053 return *ret;
3056 static void init_csyms(struct superbfd *sbfd)
3058 asymbolpp_hash_init(&sbfd->csyms);
3060 asymbol **symp;
3061 for (symp = sbfd->syms.data; symp < sbfd->syms.data + sbfd->syms.size;
3062 symp++) {
3063 asymbol *sym = *symp;
3064 if ((sym->flags & BSF_DEBUGGING) != 0)
3065 continue;
3066 char *key = strprintf("%s+%lx", sym->section->name,
3067 (unsigned long)sym->value);
3068 asymbol ***csympp = asymbolpp_hash_lookup(&sbfd->csyms, key,
3069 TRUE);
3070 free(key);
3071 if (*csympp == NULL) {
3072 *csympp = symp;
3073 continue;
3075 asymbol *csym = **csympp;
3076 if ((csym->flags & BSF_GLOBAL) != 0)
3077 continue;
3078 if ((sym->flags & BSF_GLOBAL) != 0)
3079 *csympp = symp;
3083 static asymbol **symbolp_scan(struct supersect *ss, bfd_vma value)
3085 char *key = strprintf("%s+%lx", ss->name, (unsigned long)value);
3086 asymbol ***csympp =
3087 asymbolpp_hash_lookup(&ss->parent->csyms, key, FALSE);
3088 free(key);
3089 if (csympp != NULL)
3090 return *csympp;
3092 /* For section symbols of sections containing no symbols, return the
3093 section symbol that relocations are generated against */
3094 if (value == 0)
3095 return &ss->symbol;
3096 return NULL;
3099 static asymbol **canonical_symbolp(struct superbfd *sbfd, asymbol *sym)
3101 if (bfd_is_const_section(sym->section)) {
3102 asymbol **csymp;
3103 for (csymp = sbfd->syms.data;
3104 csymp < sbfd->syms.data + sbfd->syms.size; csymp++) {
3105 if (sym == *csymp)
3106 return csymp;
3108 return NULL;
3110 return symbolp_scan(fetch_supersect(sbfd, sym->section), sym->value);
3113 static asymbol *canonical_symbol(struct superbfd *sbfd, asymbol *sym)
3115 if (bfd_is_const_section(sym->section))
3116 return sym;
3117 asymbol **symp = canonical_symbolp(sbfd, sym);
3118 return symp != NULL ? *symp : NULL;
3121 static char *static_local_symbol(struct superbfd *sbfd, asymbol *sym)
3123 struct supersect *ss = fetch_supersect(sbfd, sym->section);
3124 if ((sym->flags & BSF_LOCAL) == 0 || (sym->flags & BSF_OBJECT) == 0)
3125 return NULL;
3126 char *dot = strrchr(sym->name, '.');
3127 if (dot == NULL || dot[1 + strspn(dot + 1, "0123546789")] != '\0')
3128 return NULL;
3129 char *basename = strndup(sym->name, dot - sym->name);
3131 /* Handle C.123.12345 symbols */
3132 dot = strrchr(basename, '.');
3133 if (dot != NULL && dot[1 + strspn(dot + 1, "0123546789")] == '\0')
3134 basename = strndup(basename, dot - basename);
3135 const char *caller;
3136 if (strcmp(basename, "__func__") == 0 ||
3137 strcmp(basename, "__PRETTY_FUNCTION__") == 0)
3138 caller = (const char *)ss->contents.data + sym->value;
3139 else
3140 caller = find_caller(ss, sym);
3141 return strprintf("%s<%s>", basename, caller);
3144 static char *symbol_label(struct superbfd *sbfd, asymbol *sym)
3146 const char *filename = sbfd->abfd->filename;
3147 char *c = strstr(filename, ".KSPLICE");
3148 int flen = (c == NULL ? strlen(filename) : c - filename);
3150 char *label;
3151 if (bfd_is_und_section(sym->section) || (sym->flags & BSF_GLOBAL) != 0) {
3152 label = strdup(sym->name);
3153 } else if (bfd_is_const_section(sym->section)) {
3154 label = strprintf("%s<%.*s>", sym->name, flen, filename);
3155 } else {
3156 asymbol *gsym = canonical_symbol(sbfd, sym);
3158 if (gsym == NULL)
3159 label = strprintf("%s+%lx<%.*s>",
3160 sym->section->name,
3161 (unsigned long)sym->value,
3162 flen, filename);
3163 else if ((gsym->flags & BSF_GLOBAL) != 0)
3164 label = strdup(gsym->name);
3165 else if (static_local_symbol(sbfd, gsym))
3166 label = strprintf("%s+%lx<%.*s>",
3167 static_local_symbol(sbfd, gsym),
3168 (unsigned long)sym->value,
3169 flen, filename);
3170 else
3171 label = strprintf("%s<%.*s>",
3172 gsym->name, flen, filename);
3175 return label;
3178 static void keep_span(struct span *span)
3180 span->keep = true;
3181 span->ss->keep = true;
3184 static struct span *new_span(struct supersect *ss, bfd_vma start, bfd_vma size)
3186 struct span *span = vec_grow(&ss->spans, 1);
3187 span->size = size;
3188 span->contents_size = size;
3189 span->start = start;
3190 span->ss = ss;
3191 span->keep = true;
3192 span->new = false;
3193 span->patch = false;
3194 span->bugpatch = false;
3195 span->datapatch = false;
3196 span->precallable = strstarts(ss->name, ".ksplice_call_pre_apply") ||
3197 strstarts(ss->name, ".ksplice_call_check_apply") ||
3198 strstarts(ss->name, ".ksplice_call_fail_apply") ||
3199 strstarts(ss->name, ".ksplice_call_post_remove");
3200 span->match = NULL;
3201 vec_init(&span->entry_points);
3202 span->shift = 0;
3203 asymbol **symp = symbolp_scan(ss, span->start);
3204 if (symp != NULL) {
3205 span->symbol = *symp;
3206 span->label = label_lookup(ss->parent, span->symbol);
3207 } else {
3208 span->symbol = NULL;
3209 const char *label = label_lookup(ss->parent, ss->symbol);
3210 if (span->start != 0)
3211 span->label = strprintf("%s<span:%lx>", label,
3212 (unsigned long)span->start);
3213 else
3214 span->label = label;
3216 span->orig_label = span->label;
3217 return span;
3220 static void initialize_string_spans(struct supersect *ss)
3222 const char *str;
3223 for (str = ss->contents.data;
3224 (void *)str < ss->contents.data + ss->contents.size;) {
3225 bfd_vma start = (unsigned long)str -
3226 (unsigned long)ss->contents.data;
3227 bfd_vma size = strlen(str) + 1;
3228 bfd_vma contents_size = size;
3229 while ((start + size) % (1 << ss->alignment) != 0 &&
3230 start + size < ss->contents.size) {
3231 /* Some string sections, like __ksymtab_strings, only
3232 align some strings with the declared alignment */
3233 if (str[size] != '\0')
3234 break;
3235 size++;
3237 struct span *span = new_span(ss, start, size);
3238 span->contents_size = contents_size;
3239 str += size;
3243 static int compare_ulongs(const void *va, const void *vb)
3245 const unsigned long *a = va, *b = vb;
3246 return *a - *b;
3249 static void initialize_table_spans(struct superbfd *sbfd,
3250 struct table_section *s)
3252 asection *isection = bfd_get_section_by_name(sbfd->abfd, s->sect);
3253 if (isection == NULL)
3254 return;
3255 struct supersect *ss = fetch_supersect(sbfd, isection);
3256 if (ss->alignment < ffs(s->entry_align) - 1)
3257 ss->alignment = ffs(s->entry_align) - 1;
3259 asection *other_sect = NULL;
3260 if (s->other_sect != NULL)
3261 other_sect = bfd_get_section_by_name(sbfd->abfd, s->other_sect);
3262 struct supersect *other_ss = NULL;
3263 if (other_sect != NULL)
3264 other_ss = fetch_supersect(sbfd, other_sect);
3266 asection *crc_sect = NULL;
3267 if (s->crc_sect != NULL)
3268 crc_sect = bfd_get_section_by_name(sbfd->abfd, s->crc_sect);
3269 struct supersect *crc_ss = NULL;
3270 if (crc_sect != NULL)
3271 crc_ss = fetch_supersect(sbfd, crc_sect);
3273 struct ulong_vec offsets;
3274 vec_init(&offsets);
3276 void *entry;
3277 for (entry = ss->contents.data;
3278 entry < ss->contents.data + ss->contents.size;
3279 entry += s->entry_size) {
3280 struct span *span = new_span(ss, addr_offset(ss, entry),
3281 s->entry_size);
3282 if (s->entry_contents_size != 0)
3283 span->contents_size = s->entry_contents_size;
3284 if ((span->symbol == NULL ||
3285 (span->symbol->flags & BSF_SECTION_SYM) != 0) &&
3286 s->has_addr) {
3287 arelent *reloc = find_reloc(ss, entry + s->addr_offset);
3288 assert(reloc);
3289 struct span *target_span = reloc_target_span(ss, reloc);
3290 assert(target_span);
3291 asymbol *sym = *reloc->sym_ptr_ptr;
3292 unsigned long val = sym->value +
3293 reloc_target_offset(ss, reloc) -
3294 (target_span->start + target_span->shift);
3295 char *label = strprintf("%s<target:%s+%lx>", ss->name,
3296 target_span->label, val);
3297 change_initial_label(span, label);
3300 if (other_sect != NULL) {
3301 asymbol *sym;
3302 bfd_vma offset = read_reloc(ss, entry + s->other_offset,
3303 sizeof(void *), &sym);
3304 if (sym->section == other_sect) {
3305 assert(offset >= 0 &&
3306 offset < other_ss->contents.size);
3307 *vec_grow(&offsets, 1) = offset;
3311 if (crc_sect != NULL)
3312 new_span(crc_ss, addr_offset(ss, entry) / s->entry_size
3313 * s->crc_size, s->crc_size);
3315 if (ss->type == SS_TYPE_EXPORT) {
3316 const char *symname = read_string(ss, entry +
3317 s->other_offset);
3318 char *label = strprintf("%s:%s", ss->name, symname);
3319 change_initial_label(span, label);
3323 if (other_sect == NULL)
3324 return;
3326 *vec_grow(&offsets, 1) = 0;
3327 qsort(offsets.data, offsets.size, sizeof(*offsets.data),
3328 compare_ulongs);
3329 *vec_grow(&offsets, 1) = other_ss->contents.size;
3331 unsigned long *off;
3332 for (off = offsets.data; off < offsets.data + offsets.size - 1; off++) {
3333 if (*off != *(off + 1))
3334 new_span(other_ss, *off, *(off + 1) - *off);
3338 static void initialize_table_section_spans(struct superbfd *sbfd)
3340 struct supersect *tables_ss =
3341 fetch_supersect(offsets_sbfd,
3342 bfd_get_section_by_name(offsets_sbfd->abfd,
3343 ".ksplice_table_sections"));
3344 const struct table_section *ts;
3345 struct table_section s;
3346 for (ts = tables_ss->contents.data;
3347 (void *)ts < tables_ss->contents.data + tables_ss->contents.size;
3348 ts++) {
3349 s = *ts;
3350 s.sect = read_string(tables_ss, &ts->sect);
3351 s.other_sect = read_string(tables_ss, &ts->other_sect);
3352 s.crc_sect = read_string(tables_ss, &ts->crc_sect);
3353 initialize_table_spans(sbfd, &s);
3357 static void initialize_ksplice_call_spans(struct supersect *ss)
3359 arelent **relocp;
3360 for (relocp = ss->relocs.data;
3361 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
3362 arelent *reloc = *relocp;
3363 new_span(ss, reloc->address, bfd_get_reloc_size(reloc->howto));
3364 /* the span labels should already be unique */
3368 static void initialize_spans(struct superbfd *sbfd)
3370 asection *sect;
3371 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
3372 if (is_table_section(sect->name, true, true) && mode("keep"))
3373 continue;
3375 struct supersect *ss = fetch_supersect(sbfd, sect);
3376 if (ss->type == SS_TYPE_STRING)
3377 initialize_string_spans(ss);
3378 else if (ss->type == SS_TYPE_KSPLICE_CALL)
3379 initialize_ksplice_call_spans(ss);
3380 else
3381 new_span(ss, 0, ss->contents.size);
3383 if (mode("keep"))
3384 initialize_table_section_spans(sbfd);
3387 /* Returns the span pointed to by the relocation at span->start + offset */
3388 static struct span *span_offset_target_span(struct span *span, int offset)
3390 void *entry = span->ss->contents.data + span->start;
3391 arelent *reloc = find_reloc(span->ss, entry + offset);
3392 if (reloc == NULL)
3393 return NULL;
3394 return reloc_target_span(span->ss, reloc);
3397 struct span *reloc_target_span(struct supersect *ss, arelent *reloc)
3399 asymbol *sym_ptr = *reloc->sym_ptr_ptr;
3400 if (bfd_is_const_section(sym_ptr->section))
3401 return NULL;
3403 bfd_vma addend = sym_ptr->value + reloc_target_offset(ss, reloc);
3404 struct supersect *sym_ss =
3405 fetch_supersect(ss->parent, sym_ptr->section);
3406 struct span *span, *target_span = sym_ss->spans.data;
3407 for (span = sym_ss->spans.data;
3408 span < sym_ss->spans.data + sym_ss->spans.size; span++) {
3409 if (addend >= span->start && addend < span->start + span->size)
3410 target_span = span;
3412 return target_span;
3415 static bfd_vma reloc_target_offset(struct supersect *ss, arelent *reloc)
3417 bfd_vma offset = reloc_offset(ss, reloc);
3418 if (reloc->howto->pc_relative) {
3419 if ((ss->flags & SEC_CODE) != 0)
3420 return offset + bfd_get_reloc_size(reloc->howto);
3422 const struct table_section *ts = get_table_section(ss->name);
3423 if (ts != NULL && ts->relative_addr &&
3424 reloc->address % ts->entry_size == ts->addr_offset)
3425 return offset - ts->addr_offset;
3426 if (ts != NULL && ts->relative_other &&
3427 reloc->address % ts->entry_size == ts->other_offset)
3428 return offset - ts->other_offset;
3430 DIE;
3432 return offset;
3435 struct span *find_span(struct supersect *ss, bfd_size_type address)
3437 struct span *span;
3438 for (span = ss->spans.data; span < ss->spans.data + ss->spans.size;
3439 span++) {
3440 if (address >= span->start &&
3441 address < span->start + span->size)
3442 return span;
3444 /* Deal with empty BSS sections */
3445 if (ss->contents.size == 0 && ss->spans.size > 0)
3446 return ss->spans.data;
3447 /* Deal with section end pointers */
3448 if (address == ss->contents.size && ss->spans.size == 1)
3449 return ss->spans.data;
3450 return NULL;
3453 void compute_span_shifts(struct superbfd *sbfd)
3455 asection *sect;
3456 struct span *span;
3457 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
3458 struct supersect *ss = fetch_supersect(sbfd, sect);
3459 if (!ss->keep)
3460 continue;
3461 bfd_size_type offset = 0;
3462 for (span = ss->spans.data;
3463 span < ss->spans.data + ss->spans.size; span++) {
3464 if (!span->keep)
3465 continue;
3466 span->shift = offset - span->start;
3467 offset += span->size;
3472 void remove_unkept_spans(struct superbfd *sbfd)
3474 asection *sect;
3475 struct span *span;
3476 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
3477 struct supersect *ss = fetch_supersect(sbfd, sect);
3478 delete_obsolete_relocs(ss);
3479 struct arelentp_vec orig_relocs;
3480 vec_move(&orig_relocs, &ss->relocs);
3481 arelent **relocp, *reloc;
3482 for (relocp = orig_relocs.data;
3483 relocp < orig_relocs.data + orig_relocs.size; relocp++) {
3484 reloc = *relocp;
3485 asymbol *sym = *reloc->sym_ptr_ptr;
3486 span = reloc_target_span(ss, reloc);
3487 if ((span != NULL && span->keep && span->shift == 0) ||
3488 bfd_is_const_section(sym->section)) {
3489 *vec_grow(&ss->relocs, 1) = reloc;
3490 continue;
3492 struct supersect *sym_ss =
3493 fetch_supersect(sbfd, sym->section);
3494 if (span != NULL && (sym->flags & BSF_SECTION_SYM) == 0
3495 && find_span(sym_ss, sym->value) != span) {
3496 err(sbfd, "Spans for symbol %s and relocation "
3497 "target do not match in sect %s\n",
3498 sym->name, sym_ss->name);
3499 DIE;
3501 if (span != NULL && span->keep) {
3502 arelent *new_reloc = malloc(sizeof(*new_reloc));
3503 *new_reloc = *reloc;
3504 new_reloc->addend = reloc_offset(ss, reloc);
3505 new_reloc->addend += span->shift;
3506 *vec_grow(&ss->new_relocs, 1) = new_reloc;
3511 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
3512 struct supersect *ss = fetch_supersect(sbfd, sect), orig_ss;
3513 if (!ss->keep)
3514 continue;
3515 supersect_move(&orig_ss, ss);
3516 vec_init(&ss->spans);
3517 for (span = orig_ss.spans.data;
3518 span < orig_ss.spans.data + orig_ss.spans.size; span++) {
3519 if (!span->keep)
3520 continue;
3521 struct span *new_span = vec_grow(&ss->spans, 1);
3522 *new_span = *span;
3523 new_span->start = span->start + span->shift;
3524 new_span->shift = 0;
3525 sect_copy(ss, sect_do_grow(ss, 1, span->size, 1),
3526 &orig_ss, orig_ss.contents.data + span->start,
3527 span->size);
3532 static void init_objmanip_superbfd(struct superbfd *sbfd)
3534 init_label_map(sbfd);
3535 initialize_supersect_types(sbfd);
3536 initialize_spans(sbfd);
3537 load_options(sbfd);
3538 compute_entry_points(sbfd);
3541 void mangle_section_name(struct superbfd *sbfd, const char *name)
3543 asection *sect = bfd_get_section_by_name(sbfd->abfd, name);
3544 if (sect == NULL)
3545 return;
3546 struct supersect *ss = fetch_supersect(sbfd, sect);
3547 ss->name = strprintf(".ksplice_pre.%s", ss->name);
3550 static void write_bugline_patches(struct superbfd *sbfd)
3552 const struct table_section *ts = get_table_section("__bug_table");
3553 asection *sect = bfd_get_section_by_name(sbfd->abfd, "__bug_table");
3554 if (sect == NULL)
3555 return;
3556 struct supersect *ss = fetch_supersect(sbfd, sect);
3557 assert(ts != NULL);
3559 void *entry;
3560 for (entry = ss->contents.data;
3561 entry < ss->contents.data + ss->contents.size;
3562 entry += ts->entry_size) {
3563 struct span *span = find_span(ss, addr_offset(ss, entry));
3564 assert(span != NULL);
3565 if (!span->bugpatch)
3566 continue;
3567 arelent *reloc = find_reloc(ss, entry + ts->addr_offset);
3568 assert(reloc != NULL);
3569 asymbol *sym = *reloc->sym_ptr_ptr;
3570 assert(!bfd_is_const_section(sym->section));
3571 struct supersect *kpatch_ss =
3572 make_section(sbfd, ".ksplice_patches%s",
3573 sym->section->name);
3575 bfd_vma offset, start = 0;
3576 for (offset = 0; offset <= span->size; offset++) {
3577 if (offset != span->size &&
3578 !part_of_reloc(ss, span->start + offset))
3579 continue;
3580 if (start == offset) {
3581 start++;
3582 continue;
3584 /* an interval of non-relocations just passed */
3585 struct ksplice_patch *kpatch =
3586 sect_grow(kpatch_ss, 1, struct ksplice_patch);
3587 write_ksplice_patch_reloc
3588 (kpatch_ss, sym->section->name, &kpatch->oldaddr,
3589 sizeof(kpatch->oldaddr), span->label, start);
3591 char *data = write_patch_storage(kpatch_ss, kpatch,
3592 offset - start, NULL);
3593 memcpy(data, entry + start, offset - start);
3594 kpatch->type = KSPLICE_PATCH_DATA;
3595 start = offset + 1;
3600 void *write_patch_storage(struct supersect *ss, struct ksplice_patch *kpatch,
3601 size_t size, struct supersect **data_ssp)
3603 struct supersect *data_ss = make_section(ss->parent,
3604 ".ksplice_patch_data");
3605 char *saved = sect_do_grow(data_ss, 1, size, 1);
3606 write_reloc(ss, &kpatch->saved, &data_ss->symbol,
3607 addr_offset(data_ss, saved));
3608 char *data = sect_do_grow(data_ss, 1, size, 1);
3609 write_reloc(ss, &kpatch->contents, &data_ss->symbol,
3610 addr_offset(data_ss, data));
3611 kpatch->size = size;
3612 if (data_ssp != NULL)
3613 *data_ssp = data_ss;
3614 return data;