Makefile.ksplice: Rewrite ksplice-cow-check as a wrapper function.
[ksplice.git] / objmanip.c
blobb34ba20d030c04a9d3a79d03f94e12c5986658fb
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 } else {
341 err(sbfd, "Unrecognized Ksplice option %d\n",
342 opt->type);
343 DIE;
348 bool matchable_data_section(struct supersect *ss)
350 if (ss->type == SS_TYPE_STRING)
351 return true;
352 if (ss->type == SS_TYPE_RODATA)
353 return true;
354 if (ss->type == SS_TYPE_DATA && ss->relocs.size != 0)
355 return true;
356 if (ss->type == SS_TYPE_EXPORT)
357 return true;
358 if (ss->type == SS_TYPE_BUGTABLE)
359 return true;
360 return false;
363 bool unchangeable_section(struct supersect *ss)
365 if (ss->type == SS_TYPE_DATA)
366 return true;
367 if (ss->type == SS_TYPE_IGNORED && !strstarts(ss->name, ".debug") &&
368 strcmp(ss->name, "__ksymtab_strings") != 0)
369 return true;
370 return false;
373 int main(int argc, char *argv[])
375 if (getenv("KSPLICE_VERBOSE") != NULL)
376 verbose = atoi(getenv("KSPLICE_VERBOSE"));
378 bfd_init();
379 bfd *ibfd = bfd_openr(argv[1], NULL);
380 assert(ibfd);
382 char **matching;
383 if (bfd_check_format_matches(ibfd, bfd_archive, &matching) &&
384 bfd_openr_next_archived_file(ibfd, NULL) == NULL)
385 return 66; /* empty archive */
386 assert(bfd_check_format_matches(ibfd, bfd_object, &matching));
388 const char *output_target = bfd_get_target(ibfd);
390 load_system_map();
391 load_offsets();
393 bool_hash_init(&system_map_written);
394 ulong_hash_init(&ksplice_symbol_offset);
395 ulong_hash_init(&ksplice_howto_offset);
396 ulong_hash_init(&ksplice_string_offset);
398 struct superbfd *isbfd = fetch_superbfd(ibfd);
400 modestr = argv[3];
401 if (mode("finalize"))
402 finalize_target = argv[4];
403 init_objmanip_superbfd(isbfd);
404 if (mode("keep-new-code")) {
405 kid = argv[5];
406 do_keep_new_code(isbfd, argv[4]);
407 } else if (mode("keep-old-code")) {
408 do_keep_old_code(isbfd);
409 } else if (mode("finalize")) {
410 do_finalize(isbfd);
411 } else if (mode("rmsyms")) {
412 do_rmsyms(isbfd);
415 if (write_output) {
416 bfd *obfd = bfd_openw(argv[2], output_target);
417 assert(obfd);
418 copy_object(ibfd, obfd);
419 assert(bfd_close(obfd));
422 if (offsets_sbfd != NULL)
423 assert(bfd_close(offsets_sbfd->abfd));
424 assert(bfd_close(ibfd));
425 return EXIT_SUCCESS;
428 void do_keep_new_code(struct superbfd *isbfd, const char *pre)
430 struct bfd *prebfd = bfd_openr(pre, NULL);
431 assert(prebfd != NULL);
432 char **matching;
433 assert(bfd_check_format_matches(prebfd, bfd_object, &matching));
435 struct superbfd *presbfd = fetch_superbfd(prebfd);
436 init_objmanip_superbfd(presbfd);
438 foreach_symbol_pair(presbfd, isbfd, match_global_symbols);
439 debug1(isbfd, "Matched global\n");
440 foreach_span_pair(presbfd, isbfd, match_string_spans);
441 debug1(isbfd, "Matched string spans\n");
442 foreach_symbol_pair(presbfd, isbfd, match_symbol_spans);
443 debug1(isbfd, "Matched by name\n");
444 foreach_span_pair(presbfd, isbfd, match_spans_by_label);
445 debug1(isbfd, "Matched by label\n");
446 foreach_span_pair(presbfd, isbfd, match_table_spans);
447 debug1(isbfd, "Matched table spans\n");
448 foreach_span_pair(presbfd, isbfd, match_other_spans);
449 debug1(isbfd, "Matched other spans\n");
451 do {
452 changed = false;
453 compare_matched_spans(isbfd);
454 update_nonzero_offsets(isbfd);
455 mark_new_spans(isbfd);
456 } while (changed);
457 vec_init(&delsects);
459 foreach_symbol_pair(presbfd, isbfd, check_global_symbols);
461 handle_deleted_spans(presbfd, isbfd);
462 handle_section_symbol_renames(presbfd, isbfd);
464 copy_patched_entry_points(presbfd, isbfd);
466 assert(bfd_close(prebfd));
468 do {
469 changed = false;
470 mark_precallable_spans(isbfd);
471 } while (changed);
473 asection *sect;
474 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
475 struct supersect *ss = fetch_supersect(isbfd, sect);
476 ss->keep = false;
477 struct span *span;
478 for (span = ss->spans.data;
479 span < ss->spans.data + ss->spans.size; span++) {
480 if (strstarts(ss->name, ".ksplice_options"))
481 span->keep = false;
482 else if (span->new || span->patch || span->datapatch)
483 keep_span(span);
484 else
485 span->keep = false;
486 if (span->patch && span->precallable) {
487 err(isbfd, "Patched span %s can be reached "
488 "by a precall function\n", span->label);
489 DIE;
494 print_label_changes(isbfd);
496 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
497 struct supersect *ss = fetch_supersect(isbfd, sect);
498 struct span *span;
499 for (span = ss->spans.data;
500 span < ss->spans.data + ss->spans.size; span++) {
501 if (span->patch || span->bugpatch || span->datapatch)
502 debug0(isbfd, "Patching span %s\n",
503 span->label);
507 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
508 struct supersect *ss = fetch_supersect(isbfd, sect);
509 struct span *span;
510 for (span = ss->spans.data;
511 span < ss->spans.data + ss->spans.size; span++) {
512 if (span->new)
513 debug0(isbfd, "New span %s\n", span->label);
517 write_output = false;
518 const char **sectname;
519 for (sectname = delsects.data;
520 sectname < delsects.data + delsects.size; sectname++) {
521 write_output = true;
522 debug0(isbfd, "Deleted section: %s\n", *sectname);
525 filter_table_sections(isbfd);
527 compute_span_shifts(isbfd);
529 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
530 struct supersect *ss = fetch_supersect(isbfd, sect);
531 if (ss->type == SS_TYPE_KSPLICE_CALL)
532 continue;
533 struct span *span;
534 for (span = ss->spans.data;
535 span < ss->spans.data + ss->spans.size; span++) {
536 if (span->keep || span->bugpatch)
537 write_output = true;
538 if (span->patch || span->new || span->datapatch)
539 write_ksplice_section(span);
540 if (span->patch || span->datapatch)
541 write_ksplice_patches(isbfd, span);
542 if (ss->type == SS_TYPE_EXPORT && span->new)
543 write_ksplice_export(isbfd, span, false);
547 write_bugline_patches(isbfd);
548 rm_relocs(isbfd);
549 remove_unkept_spans(isbfd);
552 void do_keep_old_code(struct superbfd *isbfd)
554 asection *sect;
555 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
556 struct supersect *ss = fetch_supersect(isbfd, sect);
557 ss->keep = false;
558 struct span *span;
559 for (span = ss->spans.data;
560 span < ss->spans.data + ss->spans.size; span++) {
561 span->keep = false;
562 if (ss->type == SS_TYPE_TEXT &&
563 !strstarts(ss->name, ".fixup"))
564 keep_span(span);
565 if (ss->type == SS_TYPE_EXPORT)
566 keep_span(span);
570 asymbol **symp;
571 for (symp = isbfd->syms.data;
572 symp < isbfd->syms.data + isbfd->syms.size; symp++) {
573 asymbol *sym = *symp;
574 if (!bfd_is_const_section(sym->section) &&
575 (sym->flags & BSF_GLOBAL) != 0) {
576 struct supersect *sym_ss =
577 fetch_supersect(isbfd, sym->section);
578 if (sym->value == sym_ss->contents.size)
579 continue;
580 struct span *span = find_span(sym_ss, sym->value);
581 assert(span != NULL);
582 if (sym_ss->type != SS_TYPE_IGNORED)
583 keep_span(span);
587 do {
588 changed = false;
589 keep_referenced_sections(isbfd);
590 } while (changed);
592 filter_table_sections(isbfd);
593 compute_span_shifts(isbfd);
595 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
596 struct supersect *ss = fetch_supersect(isbfd, sect);
597 asymbol *sym = canonical_symbol(isbfd, sect->symbol);
598 if (sym == NULL)
599 continue;
600 if ((sym->flags & BSF_WEAK) != 0)
601 continue;
602 if (bfd_get_section_size(sect) == 0)
603 continue;
604 if (!ss->keep)
605 continue;
606 if (ss->type != SS_TYPE_TEXT && !matchable_data_section(ss))
607 continue;
609 struct span *span;
610 for (span = ss->spans.data;
611 span < ss->spans.data + ss->spans.size; span++) {
612 if (span->keep)
613 write_ksplice_section(span);
617 write_table_relocs(isbfd, "__bug_table", KSPLICE_HOWTO_BUG);
618 write_table_relocs(isbfd, "__ex_table", KSPLICE_HOWTO_EXTABLE);
619 rm_relocs(isbfd);
620 remove_unkept_spans(isbfd);
622 mangle_section_name(isbfd, "__markers");
623 mangle_section_name(isbfd, "__tracepoints");
624 mangle_section_name(isbfd, "__ex_table");
625 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
626 struct supersect *ss = fetch_supersect(isbfd, sect);
627 if (ss->type == SS_TYPE_EXPORT)
628 mangle_section_name(isbfd, ss->name);
632 void do_finalize(struct superbfd *isbfd)
634 load_ksplice_symbol_offsets(isbfd);
635 asection *sect;
636 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
637 struct supersect *ss = fetch_supersect(isbfd, sect);
638 if (ss->type == SS_TYPE_EXIT) {
639 struct span *span;
640 for (span = ss->spans.data;
641 span < ss->spans.data + ss->spans.size; span++)
642 span->keep = false;
643 ss->keep = false;
646 write_date_relocs(isbfd, "<{DATE...}>", KSPLICE_HOWTO_DATE);
647 write_date_relocs(isbfd, "<{TIME}>", KSPLICE_HOWTO_TIME);
648 rm_relocs(isbfd);
651 void do_rmsyms(struct superbfd *isbfd)
653 asection *extract_sect = bfd_get_section_by_name(isbfd->abfd,
654 ".ksplice_extract");
655 if (extract_sect != NULL) {
656 struct supersect *extract_ss = fetch_supersect(isbfd,
657 extract_sect);
658 arelent **relocp;
659 for (relocp = extract_ss->relocs.data;
660 relocp < extract_ss->relocs.data + extract_ss->relocs.size;
661 relocp++) {
662 asymbol *sym = *(*relocp)->sym_ptr_ptr;
663 if (bfd_is_und_section(sym->section)) {
664 debug1(isbfd, "extracting symbol %s\n",
665 sym->name);
666 *vec_grow(&extract_syms, 1) = sym;
671 rm_relocs(isbfd);
674 void match_spans(struct span *old_span, struct span *new_span)
676 struct superbfd *sbfd = new_span->ss->parent;
677 if (old_span->match == new_span && new_span->match == old_span)
678 return;
679 if (old_span->match != NULL) {
680 err(sbfd, "Matching conflict: old %s: %s != %s\n",
681 old_span->label, old_span->match->label, new_span->label);
682 DIE;
684 if (new_span->match != NULL) {
685 err(sbfd, "Matching conflict: new %s: %s != %s\n",
686 new_span->label, new_span->match->label, old_span->label);
687 DIE;
689 old_span->match = new_span;
690 new_span->match = old_span;
691 debug1(sbfd, "Matched old %s to new %s\n", old_span->label,
692 new_span->label);
693 if (old_span->ss->type != new_span->ss->type &&
694 old_span->ss->type == new_span->ss->orig_type)
695 old_span->ss->type = new_span->ss->type;
697 const struct table_section *ts = get_table_section(old_span->ss->name);
698 if (ts == NULL || !ts->has_addr || ts->other_sect == NULL)
699 return;
700 struct span *old_sym_span =
701 span_offset_target_span(old_span, ts->other_offset);
702 struct span *new_sym_span =
703 span_offset_target_span(new_span, ts->other_offset);
704 assert(old_sym_span != NULL && new_sym_span != NULL);
705 match_spans(old_sym_span, new_sym_span);
708 void unmatch_span(struct span *old_span)
710 struct span *new_span = old_span->match;
711 old_span->match = NULL;
712 new_span->match = NULL;
714 new_span->bugpatch = false;
716 if (old_span->ss->type == SS_TYPE_SPECIAL) {
717 const struct table_section *ts =
718 get_table_section(old_span->ss->name);
719 if (ts != NULL && ts->has_addr)
720 unmatch_addr_spans(old_span, new_span, ts);
723 new_span->patch = false;
724 new_span->bugpatch = false;
725 new_span->datapatch = false;
727 changed = true;
730 static void match_global_symbols(struct span *old_span, asymbol *oldsym,
731 struct span *new_span, asymbol *newsym)
733 if (newsym == NULL ||
734 (oldsym->flags & BSF_GLOBAL) == 0 ||
735 (newsym->flags & BSF_GLOBAL) == 0)
736 return;
737 match_spans(old_span, new_span);
740 static void check_global_symbols(struct span *old_span, asymbol *oldsym,
741 struct span *new_span, asymbol *newsym)
743 if ((oldsym->flags & BSF_GLOBAL) == 0 ||
744 (newsym != NULL && (newsym->flags & BSF_GLOBAL) == 0))
745 return;
746 if (old_span->ss->type == SS_TYPE_IGNORED)
747 return;
748 if (old_span->match != new_span) {
749 if (new_span != NULL)
750 err(new_span->ss->parent,
751 "Global symbol span mismatch: %s %s/%s\n",
752 oldsym->name, old_span->label, new_span->label);
753 else
754 err(old_span->ss->parent,
755 "Global symbol span mismatch: %s %s/NULL\n",
756 oldsym->name, old_span->label);
757 DIE;
761 static void foreach_symbol_pair(struct superbfd *oldsbfd, struct superbfd *newsbfd,
762 void (*fn)(struct span *old_span,
763 asymbol *oldsym,
764 struct span *new_span,
765 asymbol *newsym))
767 asymbol **oldsymp, **newsymp;
768 for (oldsymp = oldsbfd->syms.data;
769 oldsymp < oldsbfd->syms.data + oldsbfd->syms.size; oldsymp++) {
770 asymbol *oldsym = *oldsymp;
771 if ((oldsym->flags & BSF_DEBUGGING) != 0 ||
772 bfd_is_const_section(oldsym->section))
773 continue;
775 struct supersect *old_ss =
776 fetch_supersect(oldsbfd, oldsym->section);
777 if (old_ss->type == SS_TYPE_SPECIAL ||
778 old_ss->type == SS_TYPE_EXPORT)
779 continue;
781 struct span *old_span = find_span(old_ss, oldsym->value);
782 if (old_span == NULL) {
783 err(oldsbfd, "Could not find span for %s\n",
784 oldsym->name);
785 DIE;
788 bool found = false;
790 for (newsymp = newsbfd->syms.data;
791 newsymp < newsbfd->syms.data + newsbfd->syms.size;
792 newsymp++) {
793 asymbol *newsym = *newsymp;
794 if ((newsym->flags & BSF_DEBUGGING) != 0 ||
795 bfd_is_const_section(newsym->section))
796 continue;
797 if (strcmp(oldsym->name, newsym->name) != 0)
798 continue;
800 struct supersect *new_ss =
801 fetch_supersect(newsbfd, newsym->section);
802 if (old_ss->type != new_ss->type &&
803 old_ss->type != new_ss->orig_type)
804 continue;
806 assert(!found);
807 found = true;
809 struct span *new_span =
810 find_span(new_ss, newsym->value);
811 if (new_span == NULL) {
812 err(newsbfd, "Could not find span for %s\n",
813 newsym->name);
814 DIE;
816 fn(old_span, oldsym, new_span, newsym);
819 if (!found)
820 fn(old_span, oldsym, NULL, NULL);
824 static void match_symbol_spans(struct span *old_span, asymbol *oldsym,
825 struct span *new_span, asymbol *newsym)
827 if (newsym == NULL)
828 return;
829 if (old_span->ss->type == SS_TYPE_SPECIAL)
830 return;
831 if (static_local_symbol(old_span->ss->parent, oldsym) ||
832 static_local_symbol(new_span->ss->parent, newsym))
833 return;
834 if (old_span->match == NULL && new_span->match == NULL)
835 match_spans(old_span, new_span);
838 static void match_spans_by_label(struct span *old_span, struct span *new_span)
840 if (old_span->ss->type == SS_TYPE_STRING ||
841 (is_table_section(old_span->ss->name, true, false) &&
842 !is_table_section(old_span->ss->name, false, false)))
843 return;
844 if (strcmp(old_span->label, new_span->label) == 0)
845 match_spans(old_span, new_span);
848 static void match_string_spans(struct span *old_span, struct span *new_span)
850 if (old_span->ss->type != SS_TYPE_STRING ||
851 strcmp(old_span->ss->name, new_span->ss->name) != 0)
852 return;
853 if (strcmp((char *)old_span->ss->contents.data + old_span->start,
854 (char *)new_span->ss->contents.data + new_span->start) == 0)
855 match_spans(old_span, new_span);
858 static void foreach_span_pair(struct superbfd *oldsbfd,
859 struct superbfd *newsbfd,
860 void (*fn)(struct span *old_span,
861 struct span *new_span))
863 asection *oldsect, *newsect;
864 struct supersect *oldss, *newss;
865 struct span *old_span, *new_span;
866 for (newsect = newsbfd->abfd->sections; newsect != NULL;
867 newsect = newsect->next) {
868 newss = fetch_supersect(newsbfd, newsect);
869 for (oldsect = oldsbfd->abfd->sections; oldsect != NULL;
870 oldsect = oldsect->next) {
871 oldss = fetch_supersect(oldsbfd, oldsect);
872 if (oldss->type != newss->type)
873 continue;
874 for (new_span = newss->spans.data;
875 new_span < newss->spans.data + newss->spans.size;
876 new_span++) {
877 for (old_span = oldss->spans.data;
878 old_span < oldss->spans.data +
879 oldss->spans.size; old_span++)
880 fn(old_span, new_span);
886 static void mark_new_spans(struct superbfd *sbfd)
888 asection *sect;
889 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
890 struct supersect *ss = fetch_supersect(sbfd, sect);
891 if (ss->type == SS_TYPE_SPECIAL || ss->type == SS_TYPE_IGNORED)
892 continue;
893 struct span *span;
894 for (span = ss->spans.data;
895 span < ss->spans.data + ss->spans.size; span++) {
896 if (span->match == NULL)
897 span->new = true;
902 static void handle_deleted_spans(struct superbfd *oldsbfd,
903 struct superbfd *newsbfd)
905 asection *sect;
906 for (sect = oldsbfd->abfd->sections; sect != NULL; sect = sect->next) {
907 struct supersect *ss = fetch_supersect(oldsbfd, sect);
908 struct span *span;
909 for (span = ss->spans.data;
910 span < ss->spans.data + ss->spans.size; span++) {
911 if (span->match != NULL)
912 continue;
913 if (ss->type == SS_TYPE_EXPORT) {
914 *vec_grow(&delsects, 1) = span->label;
915 write_ksplice_export(newsbfd, span, true);
916 } else if (ss->type == SS_TYPE_TEXT) {
917 *vec_grow(&delsects, 1) = span->label;
918 if (span->symbol == NULL)
919 DIE;
920 write_ksplice_deleted_patch
921 (newsbfd, span->symbol->name, span->label,
922 span->ss->name, 0);
928 static void handle_nonzero_offset_relocs(struct supersect *ss)
930 struct span *address_span, *target_span;
931 arelent **relocp;
932 for (relocp = ss->relocs.data;
933 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
934 arelent *reloc = *relocp;
935 address_span = find_span(ss, reloc->address);
936 if (!address_span->new && !address_span->patch)
937 continue;
939 asymbol *sym = *reloc->sym_ptr_ptr;
940 if (bfd_is_const_section(sym->section))
941 continue;
942 bfd_vma offset = reloc_target_offset(ss, reloc);
943 target_span = reloc_target_span(ss, reloc);
944 if (sym->value + offset == target_span->start)
945 continue;
947 if (target_span->ss->type != SS_TYPE_TEXT)
948 continue;
949 if (target_span->patch)
950 continue;
952 target_span->patch = true;
953 changed = true;
954 debug1(ss->parent, "Changing %s because a relocation from sect "
955 "%s has a nonzero offset %lx+%lx into it\n",
956 target_span->label, ss->name, (unsigned long)sym->value,
957 (unsigned long)offset);
961 static void update_nonzero_offsets(struct superbfd *sbfd)
963 asection *sect;
964 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
965 struct supersect *ss = fetch_supersect(sbfd, sect);
966 if (ss->type == SS_TYPE_SPECIAL || ss->type == SS_TYPE_IGNORED)
967 continue;
968 handle_nonzero_offset_relocs(ss);
972 static void unmatch_addr_spans(struct span *old_span, struct span *new_span,
973 const struct table_section *ts)
975 struct span *old_sym_span =
976 span_offset_target_span(old_span, ts->addr_offset);
977 struct span *new_sym_span =
978 span_offset_target_span(new_span, ts->addr_offset);
979 assert(old_sym_span != NULL && new_sym_span != NULL);
980 if (old_sym_span->match == new_sym_span &&
981 new_sym_span->match == old_sym_span &&
982 !(new_sym_span->patch && new_sym_span->ss->type == SS_TYPE_TEXT)) {
983 if (old_sym_span->ss->type == SS_TYPE_TEXT) {
984 debug1(new_span->ss->parent, "Patching %s due "
985 "to relocations from special section %s\n",
986 new_sym_span->label, new_span->label);
987 new_sym_span->patch = true;
988 } else {
989 debug1(new_span->ss->parent, "Unmatching %s and %s due "
990 "to relocations from special section %s/%s\n",
991 old_sym_span->label, new_sym_span->label,
992 old_span->label, new_span->label);
993 unmatch_span(old_sym_span);
995 changed = true;
999 static void compare_spans(struct span *old_span, struct span *new_span)
1001 struct superbfd *newsbfd = new_span->ss->parent;
1003 bool nonrelocs_match = nonrelocs_equal(old_span, new_span);
1004 bool relocs_match = all_relocs_equal(old_span, new_span);
1005 if (nonrelocs_match && relocs_match) {
1006 const struct table_section *ts =
1007 get_table_section(old_span->ss->name);
1008 if (ts != NULL && ts->crc_sect != NULL) {
1009 struct span *old_crc_span = get_crc_span(old_span, ts);
1010 struct span *new_crc_span = get_crc_span(new_span, ts);
1011 assert(old_crc_span != NULL);
1012 assert(new_crc_span != NULL);
1013 if (old_crc_span->match != new_crc_span ||
1014 new_crc_span->match != old_crc_span) {
1015 debug1(newsbfd, "Unmatching %s and %s due to "
1016 "nonmatching CRCs\n", old_span->label,
1017 new_span->label);
1018 unmatch_span(old_span);
1021 return;
1024 char *reason;
1025 if (new_span->contents_size != old_span->contents_size)
1026 reason = "differing sizes";
1027 else if (!nonrelocs_match)
1028 reason = "differing contents";
1029 else
1030 reason = "differing relocations";
1032 if (new_span->ss->type == SS_TYPE_TEXT) {
1033 if (new_span->patch)
1034 return;
1035 new_span->patch = true;
1036 debug1(newsbfd, "Changing %s due to %s\n", new_span->label,
1037 reason);
1038 } else if (old_span->ss->type == SS_TYPE_BUGTABLE &&
1039 new_span->ss->type == SS_TYPE_BUGTABLE && relocs_match) {
1040 if (new_span->bugpatch)
1041 return;
1042 debug1(newsbfd, "Changing %s due to %s\n",
1043 new_span->label, reason);
1044 new_span->bugpatch = true;
1045 } else if (new_span->ss->type == SS_TYPE_RODATA &&
1046 new_span->contents_size == old_span->contents_size) {
1047 if (new_span->datapatch)
1048 return;
1049 new_span->datapatch = true;
1050 debug1(newsbfd, "Changing %s in-place due to %s\n",
1051 new_span->label, reason);
1052 } else if (new_span->ss->type == SS_TYPE_STRING &&
1053 old_span->ss->type == SS_TYPE_STRING && relocs_match &&
1054 strcmp(new_span->ss->contents.data + new_span->start,
1055 old_span->ss->contents.data + old_span->start) == 0) {
1056 return;
1057 } else {
1058 debug1(newsbfd, "Unmatching %s and %s due to %s\n",
1059 old_span->label, new_span->label, reason);
1060 unmatch_span(old_span);
1062 changed = true;
1063 if (unchangeable_section(new_span->ss))
1064 err(newsbfd, "warning: ignoring change to nonpatchable "
1065 "section %s\n", new_span->ss->name);
1068 static void compare_matched_spans(struct superbfd *newsbfd)
1070 asection *sect;
1071 for (sect = newsbfd->abfd->sections; sect != NULL; sect = sect->next) {
1072 struct supersect *ss = fetch_supersect(newsbfd, sect);
1073 struct span *span;
1074 for (span = ss->spans.data;
1075 span < ss->spans.data + ss->spans.size; span++) {
1076 if (span->match == NULL)
1077 continue;
1078 compare_spans(span->match, span);
1083 static void handle_section_symbol_renames(struct superbfd *oldsbfd,
1084 struct superbfd *newsbfd)
1086 asection *sect;
1087 struct span *span;
1088 for (sect = newsbfd->abfd->sections; sect != NULL; sect = sect->next) {
1089 struct supersect *ss = fetch_supersect(newsbfd, sect);
1090 for (span = ss->spans.data;
1091 span < ss->spans.data + ss->spans.size; span++) {
1092 if (span->match == NULL)
1093 continue;
1094 if (strcmp(span->label, span->match->label) == 0)
1095 continue;
1096 if (strcmp(span->orig_label, span->label) != 0 &&
1097 strcmp(span->label, span->match->label) != 0)
1098 DIE;
1099 if (span->symbol != NULL)
1100 label_map_set(newsbfd, span->label,
1101 span->match->label);
1102 span->label = span->match->label;
1107 static void copy_patched_entry_points(struct superbfd *oldsbfd,
1108 struct superbfd *newsbfd)
1110 asection *sect;
1111 struct span *span;
1112 for (sect = newsbfd->abfd->sections; sect != NULL; sect = sect->next) {
1113 struct supersect *ss = fetch_supersect(newsbfd, sect);
1114 for (span = ss->spans.data;
1115 span < ss->spans.data + ss->spans.size; span++) {
1116 if (!span->patch)
1117 continue;
1118 assert(span->match != NULL);
1119 vec_init(&span->pre_entry_points);
1121 struct entry_point *entry;
1122 for (entry = span->match->entry_points.data;
1123 entry < span->match->entry_points.data +
1124 span->match->entry_points.size;
1125 entry++) {
1126 struct entry_point *e =
1127 vec_grow(&span->pre_entry_points, 1);
1128 e->name = entry->name != NULL ?
1129 strdup(entry->name) : NULL;
1130 e->label = strdup(entry->label);
1131 e->offset = entry->offset;
1132 e->symbol = NULL;
1138 static int compare_entry_points(const void *va, const void *vb)
1140 const struct entry_point *a = va, *b = vb;
1141 if (a->offset < b->offset)
1142 return -1;
1143 else if (a->offset > b->offset)
1144 return 1;
1145 else
1146 return 0;
1149 static void compute_entry_points(struct superbfd *sbfd)
1151 asymbol **symp;
1152 for (symp = sbfd->syms.data; symp < sbfd->syms.data + sbfd->syms.size;
1153 symp++) {
1154 asymbol *sym = *symp;
1155 if (bfd_is_const_section(sym->section))
1156 continue;
1157 struct supersect *old_ss = fetch_supersect(sbfd, sym->section);
1158 if ((sym->flags & BSF_GLOBAL) == 0)
1159 continue;
1160 struct span *span = find_span(old_ss, sym->value);
1161 struct entry_point *e = vec_grow(&span->entry_points, 1);
1162 e->label = sym->name;
1163 e->name = sym->name;
1164 e->offset = sym->value - span->start;
1165 e->symbol = sym;
1168 asection *sect;
1169 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
1170 struct supersect *ss = fetch_supersect(sbfd, sect);
1171 struct span *span;
1172 for (span = ss->spans.data;
1173 span < ss->spans.data + ss->spans.size; span++) {
1174 /* First make sure that 0 appears as an entry point */
1175 bool found_zero = false;
1176 struct entry_point *entry;
1177 for (entry = span->entry_points.data;
1178 entry < span->entry_points.data +
1179 span->entry_points.size;
1180 entry++) {
1181 if (entry->offset == 0)
1182 found_zero = true;
1184 if (!found_zero) {
1185 struct entry_point *e =
1186 vec_grow(&span->entry_points, 1);
1187 e->label = span->label;
1188 e->name = NULL;
1189 e->offset = 0;
1190 e->symbol = span->symbol;
1193 qsort(span->entry_points.data, span->entry_points.size,
1194 sizeof(*span->entry_points.data),
1195 compare_entry_points);
1200 static bool part_of_reloc(struct supersect *ss, unsigned long addr)
1202 arelent **relocp;
1203 for (relocp = ss->relocs.data;
1204 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
1205 arelent *reloc = *relocp;
1206 if (addr >= reloc->address &&
1207 addr < reloc->address + bfd_get_reloc_size(reloc->howto))
1208 return true;
1210 return false;
1213 static bool nonrelocs_equal(struct span *old_span, struct span *new_span)
1215 int i;
1216 struct supersect *old_ss = old_span->ss, *new_ss = new_span->ss;
1217 if (old_span->contents_size != new_span->contents_size)
1218 return false;
1219 const unsigned char *old = old_ss->contents.data + old_span->start;
1220 const unsigned char *new = new_ss->contents.data + new_span->start;
1221 for (i = 0; i < old_span->contents_size; i++) {
1222 if (old[i] != new[i] &&
1223 !(part_of_reloc(old_ss, i + old_span->start) &&
1224 part_of_reloc(new_ss, i + new_span->start)))
1225 return false;
1227 return true;
1230 bool relocs_equal(struct supersect *old_src_ss, struct supersect *new_src_ss,
1231 arelent *old_reloc, arelent *new_reloc)
1233 struct superbfd *oldsbfd = old_src_ss->parent;
1234 struct superbfd *newsbfd = new_src_ss->parent;
1235 struct span *old_addr_span = find_span(old_src_ss, old_reloc->address);
1236 struct span *new_addr_span = find_span(new_src_ss, new_reloc->address);
1238 if (old_reloc->address - old_addr_span->start !=
1239 new_reloc->address - new_addr_span->start) {
1240 debug1(newsbfd, "Section %s/%s has reloc address mismatch at "
1241 "%lx\n", old_src_ss->name, new_src_ss->name,
1242 (unsigned long)old_reloc->address);
1243 return false;
1246 if (old_reloc->howto != new_reloc->howto) {
1247 debug1(newsbfd, "Section %s/%s has howto type mismatch at "
1248 "%lx\n", old_src_ss->name, new_src_ss->name,
1249 (unsigned long)old_reloc->address);
1250 return false;
1253 if (non_dst_mask(old_src_ss, old_reloc) !=
1254 non_dst_mask(new_src_ss, new_reloc)) {
1255 debug1(newsbfd, "Section %s/%s has contents mismatch at %lx\n",
1256 old_src_ss->name, new_src_ss->name,
1257 (unsigned long)old_reloc->address);
1258 return false;
1261 asymbol *old_sym = *old_reloc->sym_ptr_ptr;
1262 asymbol *new_sym = *new_reloc->sym_ptr_ptr;
1263 asection *old_sect = old_sym->section;
1264 asection *new_sect = new_sym->section;
1266 bfd_vma old_offset = reloc_target_offset(old_src_ss, old_reloc);
1267 bfd_vma new_offset = reloc_target_offset(new_src_ss, new_reloc);
1269 if (bfd_is_und_section(old_sect) || bfd_is_und_section(new_sect)) {
1270 if (!bfd_is_und_section(new_sect) && old_offset != 0 &&
1271 fetch_supersect(newsbfd, new_sect)->type == SS_TYPE_TEXT)
1272 return false;
1274 if (!bfd_is_und_section(old_sect) && new_offset != 0 &&
1275 fetch_supersect(oldsbfd, old_sect)->type == SS_TYPE_TEXT)
1276 return false;
1278 return strcmp(old_sym->name, new_sym->name) == 0 &&
1279 old_offset == new_offset;
1282 if (bfd_is_abs_section(old_sect) && bfd_is_abs_section(new_sect)) {
1283 if (old_sym->value + old_offset == new_sym->value + new_offset)
1284 return true;
1285 debug1(newsbfd, "Differing relocations from %s/%s to ABS "
1286 "section: %lx/%lx\n", old_addr_span->label,
1287 new_addr_span->label,
1288 (unsigned long)(old_sym->value + old_offset),
1289 (unsigned long)(new_sym->value + new_offset));
1290 return false;
1293 if (bfd_is_const_section(old_sect) || bfd_is_const_section(new_sect))
1294 DIE;
1296 struct supersect *old_ss = fetch_supersect(oldsbfd, old_sect);
1297 struct supersect *new_ss = fetch_supersect(newsbfd, new_sect);
1298 struct span *old_span = reloc_target_span(old_src_ss, old_reloc);
1299 struct span *new_span = reloc_target_span(new_src_ss, new_reloc);
1301 if (old_span->match != new_span || new_span->match != old_span) {
1302 debug1(newsbfd, "Nonmatching relocs from %s to %s/%s\n",
1303 new_src_ss->name, old_span->label, new_span->label);
1304 return false;
1307 if (old_sym->value + old_offset - old_span->start !=
1308 new_sym->value + new_offset - new_span->start) {
1309 debug1(newsbfd, "Offsets to %s/%s differ between %s "
1310 "and %s: %lx+%lx/%lx+%lx\n", old_ss->name,
1311 new_ss->name, old_src_ss->name, new_src_ss->name,
1312 (unsigned long)old_sym->value, (unsigned long)old_offset,
1313 (unsigned long)new_sym->value,
1314 (unsigned long)new_offset);
1315 return false;
1318 if ((old_sym->value + old_offset - old_span->start != 0 ||
1319 new_sym->value + new_offset - new_span->start != 0) &&
1320 new_span->patch) {
1321 debug1(newsbfd, "Relocation from %s to nonzero offsets "
1322 "%lx+%lx/%lx+%lx in changed section %s\n",
1323 new_src_ss->name, (unsigned long)old_sym->value,
1324 (unsigned long)old_offset, (unsigned long)new_sym->value,
1325 (unsigned long)new_offset, new_sym->section->name);
1326 return false;
1328 return true;
1331 bool all_relocs_equal(struct span *old_span, struct span *new_span)
1333 struct supersect *old_ss = old_span->ss, *new_ss = new_span->ss;
1334 arelent **old_relocp, **new_relocp;
1336 for (old_relocp = old_ss->relocs.data;
1337 old_relocp < old_ss->relocs.data + old_ss->relocs.size;
1338 old_relocp++) {
1339 if (find_span(old_ss, (*old_relocp)->address) == old_span)
1340 break;
1343 for (new_relocp = new_ss->relocs.data;
1344 new_relocp < new_ss->relocs.data + new_ss->relocs.size;
1345 new_relocp++) {
1346 if (find_span(new_ss, (*new_relocp)->address) == new_span)
1347 break;
1350 for (; old_relocp < old_ss->relocs.data + old_ss->relocs.size &&
1351 find_span(old_ss, (*old_relocp)->address) == old_span &&
1352 new_relocp < new_ss->relocs.data + new_ss->relocs.size &&
1353 find_span(new_ss, (*new_relocp)->address) == new_span;
1354 old_relocp++, new_relocp++) {
1355 if (!relocs_equal(old_ss, new_ss, *old_relocp, *new_relocp))
1356 return false;
1359 if ((old_relocp < old_ss->relocs.data + old_ss->relocs.size &&
1360 find_span(old_ss, (*old_relocp)->address) == old_span) ||
1361 (new_relocp < new_ss->relocs.data + new_ss->relocs.size &&
1362 find_span(new_ss, (*new_relocp)->address) == new_span)) {
1363 debug1(new_ss->parent, "Different reloc count between %s and "
1364 "%s\n", old_span->label, new_span->label);
1365 return false;
1368 return true;
1371 bfd_vma non_dst_mask(struct supersect *ss, arelent *reloc)
1373 int bits = bfd_get_reloc_size(reloc->howto) * 8;
1374 void *address = ss->contents.data + reloc->address;
1375 bfd_vma x = bfd_get(bits, ss->parent->abfd, address);
1376 return x & ~reloc->howto->dst_mask;
1379 void rm_relocs(struct superbfd *isbfd)
1381 asection *p;
1382 for (p = isbfd->abfd->sections; p != NULL; p = p->next) {
1383 struct supersect *ss = fetch_supersect(isbfd, p);
1384 bool remove_relocs = ss->keep;
1386 if (mode("keep") && ss->type == SS_TYPE_SPECIAL)
1387 remove_relocs = false;
1389 if (ss->type == SS_TYPE_KSPLICE ||
1390 ss->type == SS_TYPE_KSPLICE_CALL)
1391 remove_relocs = false;
1392 if (mode("finalize") &&
1393 (strstarts(ss->name, ".ksplice_patches") ||
1394 strstarts(ss->name, ".ksplice_relocs")))
1395 remove_relocs = true;
1397 if (remove_relocs)
1398 rm_some_relocs(ss);
1402 void rm_some_relocs(struct supersect *ss)
1404 struct arelentp_vec orig_relocs;
1405 vec_move(&orig_relocs, &ss->relocs);
1407 arelent **relocp;
1408 for (relocp = orig_relocs.data;
1409 relocp < orig_relocs.data + orig_relocs.size; relocp++) {
1410 bool rm_reloc = false;
1411 asymbol *sym_ptr = *(*relocp)->sym_ptr_ptr;
1413 if (mode("rmsyms") && bfd_is_und_section(sym_ptr->section)) {
1414 asymbol **esymp;
1415 for (esymp = extract_syms.data;
1416 esymp < extract_syms.data + extract_syms.size;
1417 esymp++) {
1418 if (sym_ptr == *esymp) {
1419 rm_reloc = true;
1420 break;
1425 if (mode("keep"))
1426 rm_reloc = true;
1428 if (mode("keep-new-code")) {
1429 if (bfd_is_const_section(sym_ptr->section)) {
1430 rm_reloc = false;
1431 } else {
1432 bfd_vma offset = reloc_target_offset(ss, *relocp);
1433 struct span *target_span =
1434 reloc_target_span(ss, *relocp);
1435 if (target_span->new ||
1436 (target_span->ss->type == SS_TYPE_TEXT &&
1437 sym_ptr->value + offset !=
1438 target_span->start))
1439 rm_reloc = false;
1442 const struct table_section *ts =
1443 get_table_section(ss->name);
1444 if (ts != NULL && ts->has_addr &&
1445 ((*relocp)->address % ts->entry_size ==
1446 ts->addr_offset ||
1447 (*relocp)->address % ts->entry_size ==
1448 ts->other_offset))
1449 rm_reloc = false;
1452 if (mode("finalize") && bfd_is_und_section(sym_ptr->section))
1453 rm_reloc = true;
1455 if (strcmp(sym_ptr->name, "mcount") == 0 &&
1456 bfd_is_und_section(sym_ptr->section))
1457 rm_reloc = false;
1459 if (!find_span(ss, (*relocp)->address)->keep)
1460 rm_reloc = false;
1462 if (rm_reloc)
1463 write_ksplice_reloc(ss, *relocp);
1464 else
1465 *vec_grow(&ss->relocs, 1) = *relocp;
1469 struct supersect *make_section(struct superbfd *sbfd, const char *fmt, ...)
1471 va_list ap;
1472 va_start(ap, fmt);
1473 char *name = vstrprintf(fmt, ap);
1474 va_end(ap);
1476 asection *sect = bfd_get_section_by_name(sbfd->abfd, name);
1477 if (sect != NULL)
1478 return fetch_supersect(sbfd, sect);
1479 else
1480 return new_supersect(sbfd, name);
1483 arelent *create_reloc(struct supersect *ss, const void *addr, asymbol **symp,
1484 bfd_vma offset)
1486 bfd_reloc_code_real_type code;
1487 switch (bfd_arch_bits_per_address(ss->parent->abfd)) {
1488 case 32:
1489 code = BFD_RELOC_32;
1490 break;
1491 case 64:
1492 code = BFD_RELOC_64;
1493 break;
1494 default:
1495 DIE;
1498 arelent *reloc = malloc(sizeof(*reloc));
1499 reloc->sym_ptr_ptr = symp;
1500 reloc->address = addr_offset(ss, addr);
1501 reloc->howto = bfd_reloc_type_lookup(ss->parent->abfd, code);
1502 reloc->addend = offset;
1503 return reloc;
1506 void write_reloc(struct supersect *ss, const void *addr, asymbol **symp,
1507 bfd_vma offset)
1509 *vec_grow(&ss->new_relocs, 1) = create_reloc(ss, addr, symp, offset);
1512 void write_string(struct supersect *ss, const char **addr, const char *fmt, ...)
1514 va_list ap;
1515 struct supersect *str_ss = make_section(ss->parent, ".ksplice_str");
1516 char *str;
1517 va_start(ap, fmt);
1518 int len = vasprintf(&str, fmt, ap);
1519 assert(len >= 0);
1520 va_end(ap);
1522 unsigned long *str_offp = ulong_hash_lookup(&ksplice_string_offset, str,
1523 FALSE);
1524 if (str_offp == NULL) {
1525 char *buf = sect_grow(str_ss, len + 1, char);
1526 memcpy(buf, str, len + 1);
1527 str_offp = ulong_hash_lookup(&ksplice_string_offset, str, TRUE);
1528 *str_offp = addr_offset(str_ss, buf);
1531 write_reloc(ss, addr, &str_ss->symbol, *str_offp);
1534 void lookup_system_map(struct addr_vec *addrs, const char *name, long offset)
1536 struct addr_vec *map_addrs =
1537 addr_vec_hash_lookup(&system_map, name, FALSE);
1538 if (map_addrs == NULL)
1539 return;
1541 unsigned long *addr, *map_addr;
1542 for (map_addr = map_addrs->data;
1543 map_addr < map_addrs->data + map_addrs->size; map_addr++) {
1544 for (addr = addrs->data; addr < addrs->data + addrs->size;
1545 addr++) {
1546 if (*addr == *map_addr + offset)
1547 break;
1549 if (addr < addrs->data + addrs->size)
1550 continue;
1551 *vec_grow(addrs, 1) = *map_addr + offset;
1555 void compute_system_map_array(struct superbfd *sbfd, struct addr_vec *addrs,
1556 asymbol *sym)
1558 if (bfd_is_abs_section(sym->section)) {
1559 *vec_grow(addrs, 1) = sym->value;
1560 } else if (bfd_is_und_section(sym->section)) {
1561 lookup_system_map(addrs, sym->name, 0);
1562 } else if (!bfd_is_const_section(sym->section)) {
1563 asymbol **gsymp;
1564 for (gsymp = sbfd->syms.data;
1565 gsymp < sbfd->syms.data + sbfd->syms.size; gsymp++) {
1566 asymbol *gsym = *gsymp;
1567 if ((gsym->flags & BSF_DEBUGGING) == 0 &&
1568 gsym->section == sym->section)
1569 lookup_system_map(addrs, gsym->name,
1570 sym->value - gsym->value);
1575 void write_ksplice_system_map(struct superbfd *sbfd, asymbol *sym,
1576 const char *label)
1578 bool *done = bool_hash_lookup(&system_map_written, label, TRUE);
1579 if (*done)
1580 return;
1581 *done = true;
1583 struct addr_vec addrs;
1584 vec_init(&addrs);
1586 compute_system_map_array(sbfd, &addrs, sym);
1587 if (addrs.size != 0) {
1588 struct supersect *smap_ss =
1589 make_section(sbfd, ".ksplice_system_map");
1590 struct ksplice_system_map *smap =
1591 sect_grow(smap_ss, 1, struct ksplice_system_map);
1592 write_string(smap_ss, &smap->label, "%s", label);
1594 struct supersect *array_ss = make_section(sbfd,
1595 ".ksplice_array");
1596 void *buf = sect_grow(array_ss, addrs.size,
1597 typeof(*addrs.data));
1598 memcpy(buf, addrs.data, addrs.size * sizeof(*addrs.data));
1599 smap->nr_candidates = addrs.size;
1600 write_reloc(smap_ss, &smap->candidates, &array_ss->symbol,
1601 addr_offset(array_ss, buf));
1603 vec_free(&addrs);
1606 void write_ksplice_symbol_backend(struct supersect *ss,
1607 struct ksplice_symbol *const *addr,
1608 asymbol *sym, const char *label,
1609 const char *name)
1611 struct supersect *ksymbol_ss = make_section(ss->parent,
1612 ".ksplice_symbols");
1613 struct ksplice_symbol *ksymbol;
1614 unsigned long *ksymbol_offp;
1616 ksymbol_offp = ulong_hash_lookup(&ksplice_symbol_offset, label, FALSE);
1617 if (ksymbol_offp != NULL) {
1618 write_reloc(ss, addr, &ksymbol_ss->symbol, *ksymbol_offp);
1619 return;
1621 ksymbol = sect_grow(ksymbol_ss, 1, struct ksplice_symbol);
1622 ksymbol_offp = ulong_hash_lookup(&ksplice_symbol_offset, label, TRUE);
1623 *ksymbol_offp = addr_offset(ksymbol_ss, ksymbol);
1625 write_reloc(ss, addr, &ksymbol_ss->symbol, *ksymbol_offp);
1626 write_string(ksymbol_ss, &ksymbol->label, "%s", label);
1627 if (name != NULL) {
1628 write_string(ksymbol_ss, &ksymbol->name, "%s", name);
1629 write_ksplice_system_map(ksymbol_ss->parent, sym, label);
1633 void write_ksplice_symbol(struct supersect *ss,
1634 struct ksplice_symbol *const *addr,
1635 asymbol *sym, struct span *span,
1636 const char *addstr_sect)
1638 const char *label, *name;
1639 if (span != NULL && span->start != 0)
1640 label = span->label;
1641 else
1642 label = label_lookup(ss->parent, sym);
1644 asymbol *gsym = canonical_symbol(ss->parent, sym);
1645 if (strcmp(addstr_sect, "") != 0)
1646 name = NULL;
1647 else if (bfd_is_und_section(sym->section))
1648 name = sym->name;
1649 else if (bfd_is_const_section(sym->section))
1650 name = NULL;
1651 else if (span != NULL && span->symbol == NULL)
1652 name = NULL;
1653 else if (gsym == NULL || (gsym->flags & BSF_SECTION_SYM) != 0)
1654 name = NULL;
1655 else
1656 name = gsym->name;
1658 write_ksplice_symbol_backend(ss, addr, sym,
1659 strprintf("%s%s", addstr_sect, label),
1660 name);
1663 void write_ksplice_reloc(struct supersect *ss, arelent *orig_reloc)
1665 asymbol *sym_ptr = *orig_reloc->sym_ptr_ptr;
1666 bfd_vma reloc_addend = reloc_offset(ss, orig_reloc);
1667 bfd_vma target_addend = reloc_target_offset(ss, orig_reloc);
1668 unsigned long *repladdr = ss->contents.data + orig_reloc->address;
1670 if (mode("finalize") && strstarts(ss->name, ".ksplice_patches")) {
1671 *repladdr = 0;
1672 return;
1674 if (mode("finalize") && strstarts(ss->name, ".ksplice_relocs")) {
1675 assert(strstarts(sym_ptr->name, KSPLICE_SYMBOL_STR));
1676 asymbol fake_sym;
1677 fake_sym.name = sym_ptr->name + strlen(KSPLICE_SYMBOL_STR);
1678 fake_sym.section = bfd_und_section_ptr;
1679 fake_sym.value = 0;
1680 fake_sym.flags = 0;
1682 write_ksplice_symbol_backend
1683 (ss, (struct ksplice_symbol **)repladdr, &fake_sym,
1684 fake_sym.name, fake_sym.name);
1685 return;
1688 struct span *span = reloc_target_span(ss, orig_reloc);
1689 if (span == ss->spans.data && span->start != target_addend)
1690 span = NULL;
1691 write_canary(ss, orig_reloc->address,
1692 bfd_get_reloc_size(orig_reloc->howto),
1693 orig_reloc->howto->dst_mask);
1695 struct supersect *kreloc_ss =
1696 make_section(ss->parent, ".ksplice_relocs%s", ss->name);
1697 struct ksplice_reloc *kreloc = sect_grow(kreloc_ss, 1,
1698 struct ksplice_reloc);
1700 struct span *address_span = find_span(ss, orig_reloc->address);
1701 write_reloc(kreloc_ss, &kreloc->blank_addr,
1702 &ss->symbol, orig_reloc->address + address_span->shift);
1703 if (bfd_is_und_section(sym_ptr->section) && mode("keep")) {
1704 char *name = strprintf(KSPLICE_SYMBOL_STR "%s", sym_ptr->name);
1705 asymbol **symp = make_undefined_symbolp(ss->parent, name);
1706 write_reloc(kreloc_ss, &kreloc->symbol, symp, 0);
1707 } else {
1708 write_ksplice_symbol(kreloc_ss, &kreloc->symbol, sym_ptr, span,
1709 "");
1711 if (span != NULL && span->start != 0) {
1712 reloc_addend += sym_ptr->value - span->start;
1713 target_addend += sym_ptr->value - span->start;
1715 kreloc->insn_addend = reloc_addend - target_addend;
1716 kreloc->target_addend = target_addend;
1717 write_ksplice_reloc_howto(kreloc_ss, &kreloc->howto, orig_reloc->howto,
1718 KSPLICE_HOWTO_RELOC);
1721 static void write_ksplice_reloc_howto(struct supersect *ss, const
1722 struct ksplice_reloc_howto *const *addr,
1723 reloc_howto_type *howto,
1724 enum ksplice_reloc_howto_type type)
1726 struct supersect *khowto_ss = make_section(ss->parent,
1727 ".ksplice_reloc_howtos");
1728 struct ksplice_reloc_howto *khowto;
1729 unsigned long *khowto_offp;
1731 khowto_offp = ulong_hash_lookup(&ksplice_howto_offset, howto->name,
1732 FALSE);
1733 if (khowto_offp != NULL) {
1734 write_reloc(ss, addr, &khowto_ss->symbol, *khowto_offp);
1735 return;
1737 khowto = sect_grow(khowto_ss, 1, struct ksplice_reloc_howto);
1738 khowto_offp = ulong_hash_lookup(&ksplice_howto_offset, howto->name,
1739 TRUE);
1740 *khowto_offp = addr_offset(khowto_ss, khowto);
1742 khowto->type = type;
1743 khowto->pcrel = howto->pc_relative;
1744 khowto->size = bfd_get_reloc_size(howto);
1745 khowto->dst_mask = howto->dst_mask;
1746 khowto->rightshift = howto->rightshift;
1747 khowto->signed_addend =
1748 (howto->complain_on_overflow == complain_overflow_signed) ||
1749 (howto->complain_on_overflow == complain_overflow_bitfield);
1750 write_reloc(ss, addr, &khowto_ss->symbol, *khowto_offp);
1753 #define CANARY(x, canary) ((x & ~howto->dst_mask) | (canary & howto->dst_mask))
1755 void write_canary(struct supersect *ss, int offset, bfd_size_type size,
1756 bfd_vma dst_mask)
1758 int bits = size * 8;
1759 void *address = ss->contents.data + offset;
1760 bfd_vma x = bfd_get(bits, ss->parent->abfd, address);
1761 x = (x & ~dst_mask) | ((bfd_vma)KSPLICE_CANARY & dst_mask);
1762 bfd_put(bits, ss->parent->abfd, x, address);
1765 static void write_date_relocs(struct superbfd *sbfd, const char *str,
1766 enum ksplice_reloc_howto_type type)
1768 asection *sect;
1769 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
1770 struct supersect *ss = fetch_supersect(sbfd, sect);
1771 if (ss->type != SS_TYPE_STRING && ss->type != SS_TYPE_RODATA)
1772 continue;
1773 void *ptr;
1774 struct span *span;
1775 for (span = ss->spans.data;
1776 span < ss->spans.data + ss->spans.size; span++) {
1777 if (!span->keep)
1778 continue;
1779 for (ptr = ss->contents.data + span->start;
1780 ptr + strlen(str) < ss->contents.data +
1781 span->start + span->contents_size; ptr++) {
1782 if (strcmp((const char *)ptr, str) == 0)
1783 write_ksplice_date_reloc
1784 (ss, addr_offset(ss, ptr), str,
1785 type);
1791 static void write_ksplice_date_reloc(struct supersect *ss, unsigned long offset,
1792 const char *str,
1793 enum ksplice_reloc_howto_type type)
1795 struct supersect *kreloc_ss;
1796 kreloc_ss = make_section(ss->parent, ".ksplice_relocs%s", ss->name);
1797 struct ksplice_reloc *kreloc = sect_grow(kreloc_ss, 1,
1798 struct ksplice_reloc);
1800 const char *filename = ss->parent->abfd->filename;
1801 char *c = strstr(filename, ".KSPLICE");
1802 int flen = (c == NULL ? strlen(filename) : c - filename);
1804 write_ksplice_symbol_backend(kreloc_ss, &kreloc->symbol, NULL,
1805 strprintf("%s<%.*s>", str, flen, filename),
1806 NULL);
1808 struct span *span = find_span(ss, offset);
1809 write_reloc(kreloc_ss, &kreloc->blank_addr, &ss->symbol,
1810 offset + span->shift);
1811 write_ksplice_nonreloc_howto(kreloc_ss, &kreloc->howto, type,
1812 strlen(str));
1815 static void write_table_relocs(struct superbfd *sbfd, const char *sectname,
1816 enum ksplice_reloc_howto_type type)
1818 asection *sect = bfd_get_section_by_name(sbfd->abfd, sectname);
1819 if (sect == NULL)
1820 return;
1821 struct supersect *ss = fetch_supersect(sbfd, sect);
1823 const struct table_section *s = get_table_section(sectname);
1824 if (s == NULL)
1825 DIE;
1827 void *entry;
1828 for (entry = ss->contents.data;
1829 entry < ss->contents.data + ss->contents.size;
1830 entry += s->entry_size) {
1831 struct span *span = find_span(ss, addr_offset(ss, entry));
1832 assert(span != NULL);
1833 if (!span->keep)
1834 continue;
1836 arelent *reloc = find_reloc(ss, entry + s->addr_offset);
1837 assert(reloc != NULL);
1838 asymbol *sym = *reloc->sym_ptr_ptr;
1839 assert(!bfd_is_const_section(sym->section));
1840 struct supersect *sym_ss = fetch_supersect(sbfd, sym->section);
1841 unsigned long addr = sym->value +
1842 reloc_target_offset(ss, reloc);
1843 write_ksplice_table_reloc(sym_ss, addr, span->label, type);
1847 static void write_ksplice_table_reloc(struct supersect *ss,
1848 unsigned long address,
1849 const char *label,
1850 enum ksplice_reloc_howto_type type)
1852 struct supersect *kreloc_ss;
1853 kreloc_ss = make_section(ss->parent, ".ksplice_relocs%s", ss->name);
1854 struct ksplice_reloc *kreloc = sect_grow(kreloc_ss, 1,
1855 struct ksplice_reloc);
1856 struct span *span = find_span(ss, address);
1857 assert(span != NULL);
1859 write_ksplice_symbol_backend(kreloc_ss, &kreloc->symbol, NULL,
1860 label, NULL);
1861 write_reloc(kreloc_ss, &kreloc->blank_addr, &ss->symbol,
1862 address + span->shift);
1863 write_ksplice_nonreloc_howto(kreloc_ss, &kreloc->howto, type, 0);
1866 static void write_ksplice_nonreloc_howto(struct supersect *ss,
1867 const struct ksplice_reloc_howto
1868 *const *addr,
1869 enum ksplice_reloc_howto_type type,
1870 int size)
1872 struct supersect *khowto_ss =
1873 make_section(ss->parent, ".ksplice_reloc_howtos");
1874 struct ksplice_reloc_howto *khowto =
1875 sect_grow(khowto_ss, 1, struct ksplice_reloc_howto);
1877 khowto->type = type;
1878 khowto->size = size;
1879 khowto->pcrel = 0;
1880 khowto->dst_mask = 0;
1881 khowto->rightshift = 0;
1882 khowto->signed_addend = 0;
1883 write_reloc(ss, addr, &khowto_ss->symbol,
1884 addr_offset(khowto_ss, khowto));
1887 static void write_ksplice_symbol_reloc(struct supersect *ss,
1888 const char *sectname,
1889 unsigned long *addr, asymbol *sym,
1890 const char *label, const char *name)
1892 struct supersect *kreloc_ss;
1893 kreloc_ss = make_section(ss->parent, ".ksplice_relocs%s", sectname);
1894 struct ksplice_reloc *kreloc = sect_grow(kreloc_ss, 1,
1895 struct ksplice_reloc);
1897 write_ksplice_symbol_backend(kreloc_ss, &kreloc->symbol, sym, label,
1898 name);
1899 write_reloc(kreloc_ss, &kreloc->blank_addr, &ss->symbol,
1900 addr_offset(ss, addr));
1901 write_ksplice_nonreloc_howto(kreloc_ss, &kreloc->howto,
1902 KSPLICE_HOWTO_SYMBOL, 0);
1905 static void write_ksplice_section(struct span *span)
1907 struct supersect *ss = span->ss;
1908 const char *sectname = span->ss->name;
1909 const struct table_section *ts = get_table_section(ss->name);
1911 if (ts != NULL && ts->has_addr) {
1912 arelent *reloc = find_reloc(ss, ss->contents.data + span->start
1913 + ts->addr_offset);
1914 assert(reloc != NULL);
1915 asymbol *rsym = *reloc->sym_ptr_ptr;
1916 assert(!bfd_is_const_section(rsym->section));
1917 sectname = rsym->section->name;
1920 struct supersect *ksect_ss =
1921 make_section(ss->parent, ".ksplice_sections%s", sectname);
1922 struct ksplice_section *ksect = sect_grow(ksect_ss, 1,
1923 struct ksplice_section);
1924 asymbol *sym = span->symbol == NULL ? ss->symbol : span->symbol;
1926 write_ksplice_symbol(ksect_ss, &ksect->symbol, sym, span,
1927 mode("keep-new-code") ? "(post)" : "");
1928 ksect->size = span->size;
1929 ksect->flags = 0;
1931 if (ss->type == SS_TYPE_RODATA || ss->type == SS_TYPE_STRING ||
1932 ss->type == SS_TYPE_EXPORT || ss->type == SS_TYPE_BUGTABLE)
1933 ksect->flags |= KSPLICE_SECTION_RODATA;
1934 if (ss->type == SS_TYPE_DATA)
1935 ksect->flags |= KSPLICE_SECTION_DATA;
1936 if (ss->type == SS_TYPE_TEXT)
1937 ksect->flags |= KSPLICE_SECTION_TEXT;
1938 assert(ksect->flags != 0);
1940 if (ss->type == SS_TYPE_STRING)
1941 ksect->flags |= KSPLICE_SECTION_STRING;
1943 write_reloc(ksect_ss, &ksect->address, &ss->symbol,
1944 span->start + span->shift);
1946 if (mode("keep-old-code")) {
1947 /* Write ksplice_symbols for all the entry points */
1948 struct entry_point *entry;
1949 for (entry = span->entry_points.data;
1950 entry < span->entry_points.data + span->entry_points.size;
1951 entry++)
1952 write_ksplice_symbol_reloc
1953 (span->ss, sectname, span->ss->contents.data +
1954 span->start + span->shift + entry->offset,
1955 entry->symbol, entry->label, entry->name);
1959 static void write_ksplice_patch_reloc(struct supersect *ss,
1960 const char *sectname, unsigned long *addr,
1961 bfd_size_type size, const char *label,
1962 long addend)
1964 struct supersect *kreloc_ss;
1965 kreloc_ss = make_section(ss->parent, ".ksplice_relocs%s", sectname);
1966 struct ksplice_reloc *kreloc = sect_grow(kreloc_ss, 1,
1967 struct ksplice_reloc);
1969 write_canary(ss, addr_offset(ss, addr), size, -1);
1970 write_ksplice_symbol_backend(kreloc_ss, &kreloc->symbol, NULL,
1971 label, NULL);
1972 write_reloc(kreloc_ss, &kreloc->blank_addr, &ss->symbol,
1973 addr_offset(ss, addr));
1974 reloc_howto_type *howto =
1975 bfd_reloc_type_lookup(ss->parent->abfd,
1976 PASTE(BFD_RELOC_, LONG_BIT));
1977 write_ksplice_reloc_howto(kreloc_ss, &kreloc->howto, howto,
1978 KSPLICE_HOWTO_RELOC);
1979 kreloc->target_addend = addend;
1980 kreloc->insn_addend = 0;
1983 /* Assumes symbol is global, aka only one symbol of that name */
1984 static asymbol *name_to_symbol(struct superbfd *sbfd, const char *name)
1986 if (name == NULL)
1987 return NULL;
1989 asymbol **symp;
1990 for (symp = sbfd->syms.data;
1991 symp < sbfd->syms.data + sbfd->syms.size; symp++) {
1992 asymbol *sym = *symp;
1993 if (strcmp(name, sym->name) == 0 &&
1994 ((sym->flags & BSF_GLOBAL) != 0 ||
1995 bfd_is_und_section(sym->section)))
1996 return sym;
1998 return NULL;
2001 void write_ksplice_patches(struct superbfd *sbfd, struct span *span)
2003 if (span->datapatch) {
2004 write_ksplice_patch(sbfd, span, span->label, 0);
2005 return;
2008 assert(span->patch);
2010 long prev_offset = LONG_MIN;
2011 asymbol *prev_sym = NULL;
2012 const char *prev_label = NULL;
2013 struct entry_point *entry;
2014 for (entry = span->pre_entry_points.data;
2015 entry < span->pre_entry_points.data + span->pre_entry_points.size;
2016 entry++) {
2017 asymbol *sym = name_to_symbol(sbfd, entry->name);
2018 if (sym == NULL && entry->offset != 0) {
2019 /* Since it was global, name and label are the same */
2020 write_ksplice_deleted_patch
2021 (sbfd, entry->label, entry->label, span->ss->name,
2022 entry->offset);
2023 } else if (entry->offset != prev_offset) {
2024 debug1(sbfd, "entry point: %s(%s) %lx\n", entry->label,
2025 entry->name, entry->offset);
2027 if (prev_offset + MAX_TRAMPOLINE_SIZE > entry->offset) {
2028 err(sbfd,
2029 "Overlapping trampolines: %s %lx/%lx\n",
2030 span->label, prev_offset, entry->offset);
2031 DIE;
2034 long target_offset = 0;
2035 if (sym != NULL)
2036 target_offset = sym->value - span->start;
2037 write_ksplice_patch(sbfd, span, entry->label,
2038 target_offset);
2039 prev_offset = entry->offset;
2040 prev_sym = NULL;
2043 if (prev_sym == NULL) {
2044 prev_sym = sym;
2045 prev_label = entry->label;
2046 } else if (sym != NULL &&
2047 (prev_sym->section != sym->section ||
2048 prev_sym->value != sym->value)) {
2049 err(sbfd, "Splitting global symbols in the middle of a "
2050 "span: %s+%lx != %s+%lx!\n",
2051 prev_label, (unsigned long)prev_sym->value,
2052 entry->label, (unsigned long)sym->value);
2053 DIE;
2057 if (prev_offset + MAX_TRAMPOLINE_SIZE > span->size) {
2058 err(sbfd, "Trampoline ends outside span: %s %lx/%lx\n",
2059 span->label, prev_offset, (unsigned long)span->size);
2060 DIE;
2064 void write_ksplice_patch(struct superbfd *sbfd, struct span *span,
2065 const char *label, long offset)
2067 struct supersect *kpatch_ss =
2068 make_section(sbfd, ".ksplice_patches%s", span->ss->name);
2069 struct ksplice_patch *kpatch = sect_grow(kpatch_ss, 1,
2070 struct ksplice_patch);
2072 write_ksplice_patch_reloc(kpatch_ss, span->ss->name, &kpatch->oldaddr,
2073 sizeof(kpatch->oldaddr), label, 0);
2074 if (span->ss->type == SS_TYPE_TEXT) {
2075 kpatch->type = KSPLICE_PATCH_TEXT;
2076 write_patch_storage(kpatch_ss, kpatch, MAX_TRAMPOLINE_SIZE,
2077 NULL);
2078 } else {
2079 kpatch->type = KSPLICE_PATCH_DATA;
2080 kpatch->size = span->contents_size;
2081 struct supersect *data_ss =
2082 make_section(sbfd, ".ksplice_patch_data");
2083 write_reloc(kpatch_ss, &kpatch->contents, &span->ss->symbol,
2084 span->start + span->shift);
2085 char *saved = sect_do_grow(data_ss, 1, span->contents_size, 1);
2086 write_reloc(kpatch_ss, &kpatch->saved, &data_ss->symbol,
2087 addr_offset(data_ss, saved));
2089 write_reloc(kpatch_ss, &kpatch->repladdr, &span->ss->symbol,
2090 span->start + span->shift + offset);
2093 asymbol **make_undefined_symbolp(struct superbfd *sbfd, const char *name)
2095 asymbol **symp;
2096 for (symp = sbfd->syms.data; symp < sbfd->syms.data + sbfd->syms.size;
2097 symp++) {
2098 asymbol *sym = *symp;
2099 if (strcmp(name, sym->name) == 0 &&
2100 bfd_is_und_section(sym->section))
2101 return symp;
2103 asymbol ***sympp;
2104 for (sympp = sbfd->new_syms.data;
2105 sympp < sbfd->new_syms.data + sbfd->new_syms.size; sympp++) {
2106 asymbol **symp = *sympp;
2107 asymbol *sym = *symp;
2108 if (strcmp(name, sym->name) == 0 &&
2109 bfd_is_und_section(sym->section))
2110 return symp;
2113 symp = malloc(sizeof(*symp));
2114 *symp = bfd_make_empty_symbol(sbfd->abfd);
2115 asymbol *sym = *symp;
2116 sym->name = name;
2117 sym->section = bfd_und_section_ptr;
2118 sym->flags = 0;
2119 sym->value = 0;
2120 *vec_grow(&sbfd->new_syms, 1) = symp;
2121 return symp;
2124 void write_ksplice_deleted_patch(struct superbfd *sbfd, const char *name,
2125 const char *label, const char *sectname,
2126 long offset)
2128 struct supersect *kpatch_ss =
2129 make_section(sbfd, ".ksplice_patches%s", sectname);
2130 struct ksplice_patch *kpatch = sect_grow(kpatch_ss, 1,
2131 struct ksplice_patch);
2133 write_ksplice_patch_reloc(kpatch_ss, sectname, &kpatch->oldaddr,
2134 sizeof(kpatch->oldaddr), label, 0);
2135 kpatch->type = KSPLICE_PATCH_TEXT;
2136 asymbol **symp = make_undefined_symbolp(sbfd, strdup(name));
2137 write_reloc(kpatch_ss, &kpatch->repladdr, symp, offset);
2138 write_patch_storage(kpatch_ss, kpatch, MAX_TRAMPOLINE_SIZE, NULL);
2141 void write_ksplice_export(struct superbfd *sbfd, struct span *span, bool del)
2143 struct supersect *kpatch_ss = make_section(sbfd, ".ksplice_patches");
2144 struct ksplice_patch *kpatch = sect_grow(kpatch_ss, 1,
2145 struct ksplice_patch);
2146 struct supersect *data_ss;
2148 const struct table_section *ts = get_table_section(span->ss->name);
2149 assert(ts != NULL);
2150 const char **addr =
2151 span->ss->contents.data + span->start + ts->other_offset;
2152 const char *symname = read_string(span->ss, addr);
2154 char *oldname, *newname;
2155 if (del) {
2156 oldname = strprintf("%s:%s", span->ss->name, symname);
2157 newname = strprintf("DISABLED_%s_%s", symname, kid);
2158 } else {
2159 oldname = strprintf("%s:DISABLED_%s_%s", span->ss->name,
2160 symname, kid);
2161 newname = strprintf("%s", symname);
2162 write_string(span->ss, addr, "DISABLED_%s_%s", symname, kid);
2165 write_ksplice_patch_reloc(kpatch_ss, "", &kpatch->oldaddr,
2166 sizeof(kpatch->oldaddr), oldname,
2167 ts->other_offset);
2168 kpatch->type = KSPLICE_PATCH_EXPORT;
2169 const char **namep = write_patch_storage(kpatch_ss, kpatch,
2170 sizeof(newname), &data_ss);
2171 write_string(data_ss, namep, "%s", newname);
2174 void filter_table_sections(struct superbfd *isbfd)
2176 struct supersect *tables_ss =
2177 fetch_supersect(offsets_sbfd,
2178 bfd_get_section_by_name(offsets_sbfd->abfd,
2179 ".ksplice_table_sections"));
2180 const struct table_section *ts;
2181 for (ts = tables_ss->contents.data;
2182 (void *)ts < tables_ss->contents.data + tables_ss->contents.size;
2183 ts++) {
2184 struct table_section s = *ts;
2185 s.sect = read_string(tables_ss, &ts->sect);
2186 s.other_sect = read_string(tables_ss, &ts->other_sect);
2187 s.crc_sect = read_string(tables_ss, &ts->crc_sect);
2188 filter_table_section(isbfd, &s);
2192 void filter_table_section(struct superbfd *sbfd, const struct table_section *s)
2194 asection *isection = bfd_get_section_by_name(sbfd->abfd, s->sect);
2195 if (isection == NULL)
2196 return;
2197 struct supersect *ss = fetch_supersect(sbfd, isection);
2199 void *entry;
2200 for (entry = ss->contents.data;
2201 entry < ss->contents.data + ss->contents.size;
2202 entry += s->entry_size) {
2203 struct span *span = find_span(ss, addr_offset(ss, entry));
2204 assert(span != NULL);
2206 if (s->has_addr) {
2207 struct span *sym_span =
2208 span_offset_target_span(span, s->addr_offset);
2209 assert(sym_span != NULL);
2210 if (sym_span->keep)
2211 keep_span(span);
2214 if (s->other_sect != NULL) {
2215 struct span *sym_span =
2216 span_offset_target_span(span, s->other_offset);
2217 assert(sym_span != NULL);
2218 if (span->keep)
2219 keep_span(sym_span);
2222 if (s->crc_sect != NULL) {
2223 struct span *crc_span = get_crc_span(span, s);
2224 assert(crc_span != NULL);
2225 if (span->keep && mode("keep-new-code"))
2226 keep_span(crc_span);
2231 static void match_other_spans(struct span *old_span, struct span *new_span)
2233 const struct table_section *ts = get_table_section(old_span->ss->name);
2234 if (ts == NULL)
2235 return;
2237 if (old_span->match == new_span && new_span->match == old_span &&
2238 ts->other_sect != NULL) {
2239 void *old_entry = old_span->ss->contents.data + old_span->start;
2240 void *new_entry = new_span->ss->contents.data + new_span->start;
2241 arelent *old_reloc =
2242 find_reloc(old_span->ss, old_entry + ts->other_offset);
2243 arelent *new_reloc =
2244 find_reloc(new_span->ss, new_entry + ts->other_offset);
2245 assert(old_reloc != NULL && new_reloc != NULL);
2246 struct span *old_other_span =
2247 reloc_target_span(old_span->ss, old_reloc);
2248 struct span *new_other_span =
2249 reloc_target_span(new_span->ss, new_reloc);
2250 assert(old_other_span != NULL && new_other_span != NULL);
2251 match_spans(old_other_span, new_other_span);
2255 static void match_table_spans(struct span *old_span, struct span *new_span)
2257 const struct table_section *ts = get_table_section(old_span->ss->name);
2259 if (strcmp(old_span->ss->name, new_span->ss->name) != 0)
2260 return;
2261 if (ts == NULL || old_span->ss->type != SS_TYPE_SPECIAL ||
2262 new_span->ss->type != SS_TYPE_SPECIAL)
2263 return;
2264 if (old_span->match != NULL || new_span->match != NULL)
2265 return;
2267 if (ts->has_addr) {
2268 void *old_entry = old_span->ss->contents.data + old_span->start;
2269 void *new_entry = new_span->ss->contents.data + new_span->start;
2270 arelent *old_reloc =
2271 find_reloc(old_span->ss, old_entry + ts->addr_offset);
2272 arelent *new_reloc =
2273 find_reloc(new_span->ss, new_entry + ts->addr_offset);
2274 assert(old_reloc != NULL && new_reloc != NULL);
2275 struct span *old_sym_span =
2276 reloc_target_span(old_span->ss, old_reloc);
2277 struct span *new_sym_span =
2278 reloc_target_span(new_span->ss, new_reloc);
2279 assert(old_sym_span != NULL && new_sym_span != NULL);
2280 if (old_sym_span->match == new_sym_span &&
2281 new_sym_span->match == old_sym_span &&
2282 old_reloc->address - old_sym_span->start ==
2283 new_reloc->address - new_sym_span->start)
2284 match_spans(old_span, new_span);
2288 static struct span *get_crc_span(struct span *span,
2289 const struct table_section *ts)
2291 void *entry = span->ss->contents.data + span->start;
2292 asection *crc_sect = bfd_get_section_by_name(span->ss->parent->abfd,
2293 ts->crc_sect);
2294 if (crc_sect == NULL)
2295 return NULL;
2296 struct supersect *crc_ss = fetch_supersect(span->ss->parent, crc_sect);
2297 if (crc_ss == NULL)
2298 return NULL;
2299 struct span *crc_span = find_span(crc_ss, addr_offset(span->ss, entry) /
2300 ts->entry_size * ts->crc_size);
2301 return crc_span;
2304 void mark_precallable_spans(struct superbfd *sbfd)
2306 asection *sect;
2307 struct supersect *ss, *sym_ss;
2308 struct span *address_span, *target_span;
2309 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2310 ss = fetch_supersect(sbfd, sect);
2311 arelent **relocp;
2312 if (ss->type == SS_TYPE_SPECIAL)
2313 continue;
2314 for (relocp = ss->relocs.data;
2315 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
2316 asymbol *sym = *(*relocp)->sym_ptr_ptr;
2317 address_span = find_span(ss, (*relocp)->address);
2318 if (!address_span->precallable)
2319 continue;
2320 target_span = reloc_target_span(ss, *relocp);
2321 if (target_span == NULL || target_span->keep)
2322 continue;
2323 sym_ss = fetch_supersect(sbfd, sym->section);
2324 if (sym_ss->type == SS_TYPE_IGNORED)
2325 continue;
2326 target_span->precallable = true;
2327 changed = true;
2332 void keep_referenced_sections(struct superbfd *sbfd)
2334 asection *sect;
2335 struct supersect *ss, *sym_ss;
2336 struct span *address_span, *target_span;
2337 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2338 ss = fetch_supersect(sbfd, sect);
2339 arelent **relocp;
2340 if (ss->type == SS_TYPE_SPECIAL)
2341 continue;
2342 for (relocp = ss->relocs.data;
2343 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
2344 asymbol *sym = *(*relocp)->sym_ptr_ptr;
2345 address_span = find_span(ss, (*relocp)->address);
2346 if (!address_span->keep)
2347 continue;
2348 target_span = reloc_target_span(ss, *relocp);
2349 if (target_span == NULL || target_span->keep)
2350 continue;
2351 sym_ss = fetch_supersect(sbfd, sym->section);
2352 if (sym_ss->type == SS_TYPE_IGNORED)
2353 continue;
2354 keep_span(target_span);
2355 changed = true;
2360 void copy_symbols(struct asymbolp_vec *osyms, struct asymbolpp_vec *isyms)
2362 asymbol ***sympp;
2363 for (sympp = isyms->data; sympp < isyms->data + isyms->size; sympp++)
2364 *vec_grow(osyms, 1) = **sympp;
2367 /* Modified function from GNU Binutils objcopy.c */
2368 bfd_boolean copy_object(bfd *ibfd, bfd *obfd)
2370 assert(bfd_set_format(obfd, bfd_get_format(ibfd)));
2372 bfd_vma start = bfd_get_start_address(ibfd);
2374 flagword flags = bfd_get_file_flags(ibfd);
2375 flags &= bfd_applicable_file_flags(obfd);
2377 assert(bfd_set_start_address(obfd, start)
2378 && bfd_set_file_flags(obfd, flags));
2380 enum bfd_architecture iarch = bfd_get_arch(ibfd);
2381 unsigned int imach = bfd_get_mach(ibfd);
2382 assert(bfd_set_arch_mach(obfd, iarch, imach));
2383 assert(bfd_set_format(obfd, bfd_get_format(ibfd)));
2385 /* BFD mandates that all output sections be created and sizes set before
2386 any output is done. Thus, we traverse all sections multiple times. */
2387 bfd_map_over_sections(ibfd, setup_section, obfd);
2389 struct supersect *new_supersects = fetch_superbfd(ibfd)->new_supersects;
2390 struct supersect *ss;
2391 for (ss = new_supersects; ss != NULL; ss = ss->next)
2392 setup_new_section(obfd, ss);
2394 /* Mark symbols used in output relocations so that they
2395 are kept, even if they are local labels or static symbols.
2397 Note we iterate over the input sections examining their
2398 relocations since the relocations for the output sections
2399 haven't been set yet. mark_symbols_used_in_relocations will
2400 ignore input sections which have no corresponding output
2401 section. */
2403 bfd_map_over_sections(ibfd, mark_symbols_used_in_relocations, NULL);
2404 for (ss = new_supersects; ss != NULL; ss = ss->next)
2405 ss_mark_symbols_used_in_relocations(ss);
2406 struct asymbolp_vec osyms;
2407 vec_init(&osyms);
2408 filter_symbols(ibfd, obfd, &osyms, &fetch_superbfd(ibfd)->syms);
2409 copy_symbols(&osyms, &fetch_superbfd(ibfd)->new_syms);
2411 bfd_set_symtab(obfd, osyms.data, osyms.size);
2413 /* This has to happen after the symbol table has been set. */
2414 bfd_map_over_sections(obfd, write_section, NULL);
2416 /* Allow the BFD backend to copy any private data it understands
2417 from the input BFD to the output BFD. This is done last to
2418 permit the routine to look at the filtered symbol table, which is
2419 important for the ECOFF code at least. */
2420 assert(bfd_copy_private_bfd_data(ibfd, obfd));
2422 return TRUE;
2425 /* Modified function from GNU Binutils objcopy.c */
2426 void setup_section(bfd *ibfd, asection *isection, void *obfdarg)
2428 struct superbfd *isbfd = fetch_superbfd(ibfd);
2429 struct supersect *ss = fetch_supersect(isbfd, isection);
2430 bfd *obfd = obfdarg;
2431 bfd_vma vma;
2433 if (!ss->keep)
2434 return;
2436 asection *osection = bfd_make_section_anyway(obfd, ss->name);
2437 assert(osection != NULL);
2439 osection->userdata = ss;
2440 bfd_set_section_flags(obfd, osection, ss->flags);
2441 ss->symbol = osection->symbol;
2442 assert(bfd_set_section_size(obfd, osection, ss->contents.size));
2444 vma = bfd_section_vma(ibfd, isection);
2445 assert(bfd_set_section_vma(obfd, osection, vma));
2447 osection->lma = isection->lma;
2448 assert(bfd_set_section_alignment(obfd, osection, ss->alignment));
2449 osection->entsize = ss->entsize;
2450 osection->output_section = osection;
2451 osection->output_offset = 0;
2452 isection->output_section = osection;
2453 isection->output_offset = 0;
2454 return;
2457 void setup_new_section(bfd *obfd, struct supersect *ss)
2459 asection *osection = bfd_make_section_anyway(obfd, ss->name);
2460 assert(osection != NULL);
2461 bfd_set_section_flags(obfd, osection, ss->flags);
2463 osection->userdata = ss;
2464 ss->symbol = osection->symbol;
2465 assert(bfd_set_section_size(obfd, osection, ss->contents.size));
2466 assert(bfd_set_section_vma(obfd, osection, 0));
2468 osection->lma = 0;
2469 assert(bfd_set_section_alignment(obfd, osection, ss->alignment));
2470 osection->entsize = ss->entsize;
2471 osection->output_section = osection;
2472 osection->output_offset = 0;
2475 static int compare_reloc_addresses(const void *aptr, const void *bptr)
2477 const arelent *const *a = aptr, *const *b = bptr;
2478 return (*a)->address - (*b)->address;
2481 static void delete_obsolete_relocs(struct supersect *ss)
2483 if (ss->new_relocs.size == 0)
2484 return;
2486 qsort(ss->relocs.data, ss->relocs.size, sizeof(*ss->relocs.data),
2487 compare_reloc_addresses);
2488 qsort(ss->new_relocs.data, ss->new_relocs.size,
2489 sizeof(*ss->new_relocs.data), compare_reloc_addresses);
2491 struct arelentp_vec orig_relocs;
2492 vec_move(&orig_relocs, &ss->relocs);
2494 arelent **relocp, **new_relocp = ss->new_relocs.data;
2495 for (relocp = orig_relocs.data;
2496 relocp < orig_relocs.data + orig_relocs.size; relocp++) {
2497 while (new_relocp < ss->new_relocs.data + ss->new_relocs.size &&
2498 (*new_relocp)->address < (*relocp)->address)
2499 new_relocp++;
2500 arelent *reloc = *relocp, *new_reloc = *new_relocp;
2501 if (new_relocp == ss->new_relocs.data + ss->new_relocs.size ||
2502 reloc->address != new_reloc->address)
2503 *vec_grow(&ss->relocs, 1) = reloc;
2507 void write_section(bfd *obfd, asection *osection, void *arg)
2509 struct supersect *ss = osection->userdata;
2511 if ((ss->flags & SEC_GROUP) != 0 || ss->contents.size == 0)
2512 return;
2514 delete_obsolete_relocs(ss);
2516 arelent **relocp;
2517 char *error_message;
2518 for (relocp = ss->new_relocs.data;
2519 relocp < ss->new_relocs.data + ss->new_relocs.size; relocp++) {
2520 bfd_vma val;
2521 if (bfd_get_arch(obfd) == bfd_arch_arm)
2522 val = osection->use_rela_p ? 0 : (*relocp)->addend;
2523 else
2524 val = 0;
2525 bfd_put(bfd_get_reloc_size((*relocp)->howto) * 8, obfd, val,
2526 ss->contents.data + (*relocp)->address);
2527 if (bfd_install_relocation(obfd, *relocp, ss->contents.data,
2528 0, osection, &error_message) !=
2529 bfd_reloc_ok) {
2530 err(ss->parent, "ksplice: error installing reloc: %s",
2531 error_message);
2532 DIE;
2534 if (mode("finalize")) {
2535 /* Check that all our sections will be allocated */
2536 asymbol *sym = *((*relocp)->sym_ptr_ptr);
2537 if (!bfd_is_const_section(sym->section)) {
2538 struct supersect *sym_ss =
2539 fetch_supersect(ss->parent, sym->section);
2540 assert((sym_ss->flags & SEC_ALLOC) != 0);
2544 memcpy(vec_grow(&ss->relocs, ss->new_relocs.size), ss->new_relocs.data,
2545 ss->new_relocs.size * sizeof(*ss->new_relocs.data));
2547 bfd_set_reloc(obfd, osection,
2548 ss->relocs.size == 0 ? NULL : ss->relocs.data,
2549 ss->relocs.size);
2551 if (ss->flags & SEC_HAS_CONTENTS)
2552 assert(bfd_set_section_contents
2553 (obfd, osection, ss->contents.data, 0,
2554 ss->contents.size));
2557 /* Modified function from GNU Binutils objcopy.c
2559 * Mark all the symbols which will be used in output relocations with
2560 * the BSF_KEEP flag so that those symbols will not be stripped.
2562 * Ignore relocations which will not appear in the output file.
2564 void mark_symbols_used_in_relocations(bfd *abfd, asection *isection,
2565 void *ignored)
2567 struct superbfd *sbfd = fetch_superbfd(abfd);
2568 if (isection->output_section == NULL)
2569 return;
2571 struct supersect *ss = fetch_supersect(sbfd, isection);
2572 ss_mark_symbols_used_in_relocations(ss);
2575 void ss_mark_symbols_used_in_relocations(struct supersect *ss)
2577 /* Examine each symbol used in a relocation. If it's not one of the
2578 special bfd section symbols, then mark it with BSF_KEEP. */
2579 arelent **relocp;
2580 for (relocp = ss->relocs.data;
2581 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
2582 asymbol *sym = *(*relocp)->sym_ptr_ptr;
2583 if (!(bfd_is_const_section(sym->section) &&
2584 sym == sym->section->symbol))
2585 sym->flags |= BSF_KEEP;
2587 for (relocp = ss->new_relocs.data;
2588 relocp < ss->new_relocs.data + ss->new_relocs.size; relocp++) {
2589 asymbol *sym = *(*relocp)->sym_ptr_ptr;
2590 if (!(bfd_is_const_section(sym->section) &&
2591 sym == sym->section->symbol))
2592 sym->flags |= BSF_KEEP;
2596 static bool deleted_table_section_symbol(bfd *abfd, asymbol *sym)
2598 struct superbfd *sbfd = fetch_superbfd(abfd);
2599 if (bfd_is_const_section(sym->section))
2600 return false;
2601 struct supersect *ss = fetch_supersect(sbfd, sym->section);
2603 asymbol **symp;
2604 for (symp = ss->syms.data; symp < ss->syms.data + ss->syms.size; symp++) {
2605 if (sym == *symp)
2606 break;
2608 return symp >= ss->syms.data + ss->syms.size &&
2609 (sym->flags & BSF_SECTION_SYM) == 0;
2612 void filter_symbols(bfd *ibfd, bfd *obfd, struct asymbolp_vec *osyms,
2613 struct asymbolp_vec *isyms)
2615 asymbol **symp;
2616 struct superbfd *sbfd = fetch_superbfd(ibfd);
2617 for (symp = isyms->data; symp < isyms->data + isyms->size; symp++) {
2618 asymbol *sym = *symp;
2619 struct supersect *sym_ss = NULL;
2620 struct span *sym_span = NULL;
2621 if (!bfd_is_const_section(sym->section)) {
2622 sym_ss = fetch_supersect(sbfd, sym->section);
2623 sym_span = find_span(sym_ss, sym->value);
2626 if (mode("keep") && (sym->flags & BSF_GLOBAL) != 0 &&
2627 !(mode("keep-new-code") && sym_span != NULL &&
2628 sym_span->new))
2629 sym->flags = (sym->flags & ~BSF_GLOBAL) | BSF_LOCAL;
2631 if (mode("finalize") && (sym->flags & BSF_GLOBAL) != 0)
2632 sym->flags = (sym->flags & ~BSF_GLOBAL) | BSF_LOCAL;
2634 bool keep = bfd_is_const_section(sym->section) ||
2635 (sym_ss->keep && (sym->flags & BSF_SECTION_SYM) != 0) ||
2636 (sym_span != NULL && sym_span->keep);
2637 if (bfd_is_und_section(sym->section) &&
2638 (sym->flags & BSF_KEEP) == 0)
2639 keep = false;
2640 if (bfd_is_abs_section(sym->section) &&
2641 (sym->flags & BSF_KEEP) == 0 &&
2642 (sym->flags & BSF_FILE) == 0)
2643 keep = false;
2644 if (deleted_table_section_symbol(ibfd, sym))
2645 keep = false;
2647 if (mode("keep-old-code") && sym_ss != NULL &&
2648 sym_ss->type == SS_TYPE_EXPORT)
2649 keep = false;
2651 if (keep) {
2652 if (sym_ss != NULL && !sym_ss->keep) {
2653 err(sbfd, "Kept symbol %s in unkept section "
2654 "%s\n", sym->name, sym->section->name);
2655 DIE;
2657 *vec_grow(osyms, 1) = sym;
2662 static bool is_table_section(const char *name, bool consider_other,
2663 bool consider_crc)
2665 struct supersect *tables_ss =
2666 fetch_supersect(offsets_sbfd,
2667 bfd_get_section_by_name(offsets_sbfd->abfd,
2668 ".ksplice_table_sections"));
2669 const struct table_section *ts;
2670 for (ts = tables_ss->contents.data;
2671 (void *)ts < tables_ss->contents.data + tables_ss->contents.size;
2672 ts++) {
2673 if (strcmp(name, read_string(tables_ss, &ts->sect)) == 0)
2674 return true;
2675 const char *osect_name = read_string(tables_ss,
2676 &ts->other_sect);
2677 if (consider_other && osect_name != NULL &&
2678 strcmp(name, osect_name) == 0)
2679 return true;
2680 const char *crc_name = read_string(tables_ss, &ts->crc_sect);
2681 if (consider_crc && crc_name != NULL &&
2682 strcmp(name, crc_name) == 0)
2683 return true;
2685 return false;
2688 const struct table_section *get_table_section(const char *name)
2690 struct supersect *tables_ss =
2691 fetch_supersect(offsets_sbfd,
2692 bfd_get_section_by_name(offsets_sbfd->abfd,
2693 ".ksplice_table_sections"));
2694 const struct table_section *ts;
2695 for (ts = tables_ss->contents.data;
2696 (void *)ts < tables_ss->contents.data + tables_ss->contents.size;
2697 ts++) {
2698 if (strcmp(name, read_string(tables_ss, &ts->sect)) == 0) {
2699 if (ts->entry_contents_size != 0)
2700 assert(align(ts->entry_contents_size,
2701 ts->entry_align) ==
2702 ts->entry_size);
2703 struct table_section *ns = malloc(sizeof(*ns));
2704 *ns = *ts;
2705 ns->sect = read_string(tables_ss, &ts->sect);
2706 ns->crc_sect = read_string(tables_ss, &ts->crc_sect);
2707 ns->other_sect =
2708 read_string(tables_ss, &ts->other_sect);
2709 return ns;
2712 return NULL;
2715 enum supersect_type supersect_type(struct supersect *ss)
2717 if (mode("finalize") &&
2718 strcmp(finalize_target, "vmlinux") == 0 &&
2719 (strstarts(ss->name, ".ksplice_relocs.exit") ||
2720 strstarts(ss->name, ".ksplice_sections.exit") ||
2721 strstarts(ss->name, ".ksplice_patches.exit")))
2722 return SS_TYPE_EXIT;
2723 if (strstarts(ss->name, ".ksplice_call"))
2724 return SS_TYPE_KSPLICE_CALL;
2725 if (strstarts(ss->name, ".ksplice_extract"))
2726 return SS_TYPE_KSPLICE_EXTRACT;
2727 if (strstarts(ss->name, ".ksplice_options"))
2728 return SS_TYPE_SPECIAL;
2729 if (strstarts(ss->name, ".ksplice"))
2730 return SS_TYPE_KSPLICE;
2732 if (strstarts(ss->name, ".init"))
2733 return SS_TYPE_IGNORED;
2734 if (strstarts(ss->name, ".security_initcall.init"))
2735 return SS_TYPE_IGNORED;
2736 if (strstarts(ss->name, ".con_initcall.init"))
2737 return SS_TYPE_IGNORED;
2738 if (strstarts(ss->name, ".x86cpuvendor.init"))
2739 return SS_TYPE_IGNORED;
2740 if (strstarts(ss->name, ".early_param.init"))
2741 return SS_TYPE_IGNORED;
2742 if (strstarts(ss->name, ".taglist.init"))
2743 return SS_TYPE_IGNORED;
2744 if (strstarts(ss->name, ".x86_cpu_dev.init"))
2745 return SS_TYPE_IGNORED;
2746 if (strstarts(ss->name, ".arch.info.init"))
2747 return SS_TYPE_IGNORED;
2748 if (strstarts(ss->name, ".proc.info.init"))
2749 return SS_TYPE_IGNORED;
2750 /* .pci_fixup_* sections really should be treated as global rodata
2751 referenced only from quirks.c */
2752 if (strstarts(ss->name, ".pci_fixup_"))
2753 return SS_TYPE_IGNORED;
2754 /* .builtin_fw sections are similar to .pci_fixup */
2755 if (strstarts(ss->name, ".builtin_fw"))
2756 return SS_TYPE_IGNORED;
2757 /* same for .tracedata */
2758 if (strstarts(ss->name, ".tracedata"))
2759 return SS_TYPE_IGNORED;
2760 if (strstarts(ss->name, ".debug"))
2761 return SS_TYPE_IGNORED;
2762 /* .eh_frame should probably be discarded, not ignored */
2763 if (strstarts(ss->name, ".eh_frame"))
2764 return SS_TYPE_IGNORED;
2765 if (config->ignore_devinit && strstarts(ss->name, ".devinit"))
2766 return SS_TYPE_IGNORED;
2767 if (config->ignore_meminit && strstarts(ss->name, ".meminit"))
2768 return SS_TYPE_IGNORED;
2769 if (config->ignore_cpuinit && strstarts(ss->name, ".cpuinit"))
2770 return SS_TYPE_IGNORED;
2771 if (config->ignore_devinit && strstarts(ss->name, ".devexit"))
2772 return SS_TYPE_IGNORED;
2773 if (config->ignore_meminit && strstarts(ss->name, ".memexit"))
2774 return SS_TYPE_IGNORED;
2775 if (config->ignore_cpuinit && strstarts(ss->name, ".cpuexit"))
2776 return SS_TYPE_IGNORED;
2777 if (strstarts(ss->name, ".vgetcpu_mode") ||
2778 strstarts(ss->name, ".jiffies") ||
2779 strstarts(ss->name, ".wall_jiffies") ||
2780 strstarts(ss->name, ".vxtime") ||
2781 strstarts(ss->name, ".sys_tz") ||
2782 strstarts(ss->name, ".sysctl_vsyscall") ||
2783 strstarts(ss->name, ".xtime") ||
2784 strstarts(ss->name, ".xtime_lock") ||
2785 strstarts(ss->name, ".vsyscall"))
2786 return SS_TYPE_IGNORED;
2787 if (strstarts(ss->name, ".vdso"))
2788 return SS_TYPE_IGNORED;
2790 if (strstarts(ss->name, ".exit.text"))
2791 return SS_TYPE_TEXT;
2792 if (strstarts(ss->name, ".exit.data"))
2793 return SS_TYPE_DATA;
2795 if (strstarts(ss->name, ".text") ||
2796 strstarts(ss->name, ".kernel.text") ||
2797 strstarts(ss->name, ".devinit.text") ||
2798 strstarts(ss->name, ".meminit.text") ||
2799 strstarts(ss->name, ".cpuinit.text") ||
2800 strstarts(ss->name, ".devexit.text") ||
2801 strstarts(ss->name, ".memexit.text") ||
2802 strstarts(ss->name, ".cpuexit.text") ||
2803 strstarts(ss->name, ".ref.text") ||
2804 strstarts(ss->name, ".spinlock.text") ||
2805 strstarts(ss->name, ".kprobes.text") ||
2806 strstarts(ss->name, ".sched.text") ||
2807 strstarts(ss->name, ".entry.text") || /* OpenVZ */
2808 (mode("keep-old-code") && strstarts(ss->name, ".fixup")))
2809 return SS_TYPE_TEXT;
2811 int n = -1;
2812 if (sscanf(ss->name, ".rodata.str%*u.%*u%n", &n) >= 0 &&
2813 n == strlen(ss->name))
2814 return ss->entsize == 1 ? SS_TYPE_STRING : SS_TYPE_RODATA;
2816 if (strstarts(ss->name, ".rodata") ||
2817 strstarts(ss->name, ".kernel.rodata") ||
2818 strstarts(ss->name, ".devinit.rodata") ||
2819 strstarts(ss->name, ".meminit.rodata") ||
2820 strstarts(ss->name, ".cpuinit.rodata") ||
2821 strstarts(ss->name, ".devexit.rodata") ||
2822 strstarts(ss->name, ".memexit.rodata") ||
2823 strstarts(ss->name, ".cpuexit.rodata") ||
2824 strstarts(ss->name, ".ref.rodata") ||
2825 strstarts(ss->name, "__tracepoints_strings") ||
2826 strstarts(ss->name, "__markers_strings") ||
2827 (mode("keep-old-code") && strstarts(ss->name, "__ex_table")))
2828 return SS_TYPE_RODATA;
2830 if (strstarts(ss->name, ".bss"))
2831 return SS_TYPE_DATA;
2833 /* Ignore .data.percpu sections */
2834 if (strstarts(ss->name, ".data.percpu") ||
2835 strstarts(ss->name, ".kernel.data.percpu") ||
2836 strstarts(ss->name, ".data..percpu"))
2837 return SS_TYPE_IGNORED;
2838 if (strstarts(ss->name, ".data") ||
2839 strstarts(ss->name, ".kernel.data") ||
2840 strstarts(ss->name, ".devinit.data") ||
2841 strstarts(ss->name, ".cpuinit.data") ||
2842 strstarts(ss->name, ".meminit.data") ||
2843 strstarts(ss->name, ".devexit.data") ||
2844 strstarts(ss->name, ".memexit.data") ||
2845 strstarts(ss->name, ".cpuexit.data") ||
2846 strstarts(ss->name, ".ref.data") ||
2847 strstarts(ss->name, "__tracepoints") ||
2848 strstarts(ss->name, "__markers"))
2849 return SS_TYPE_DATA;
2851 /* We replace all the ksymtab strings, so delete them */
2852 if (strcmp(ss->name, "__ksymtab_strings") == 0)
2853 return SS_TYPE_STRING;
2854 if (strstarts(ss->name, "__ksymtab"))
2855 return SS_TYPE_EXPORT;
2857 if (strstarts(ss->name, "__bug_table"))
2858 return SS_TYPE_BUGTABLE;
2860 if (is_table_section(ss->name, true, true))
2861 return SS_TYPE_SPECIAL;
2863 if (strstarts(ss->name, ".ARM."))
2864 return SS_TYPE_SPECIAL;
2866 if (strstarts(ss->name, ".note"))
2867 return SS_TYPE_IGNORED;
2868 if (strstarts(ss->name, ".comment"))
2869 return SS_TYPE_IGNORED;
2870 if (strstarts(ss->name, "__param"))
2871 return SS_TYPE_IGNORED;
2872 if (strstarts(ss->name, "__obsparm"))
2873 return SS_TYPE_IGNORED;
2874 if (strstarts(ss->name, ".exitcall.exit"))
2875 return SS_TYPE_IGNORED;
2876 if (strstarts(ss->name, ".modinfo"))
2877 return SS_TYPE_IGNORED;
2879 return SS_TYPE_UNKNOWN;
2882 void initialize_supersect_types(struct superbfd *sbfd)
2884 asection *sect;
2885 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2886 struct supersect *ss = fetch_supersect(sbfd, sect);
2887 ss->type = supersect_type(ss);
2888 ss->orig_type = ss->type;
2889 if (ss->type == SS_TYPE_UNKNOWN) {
2890 err(sbfd, "Unknown section type: %s\n", ss->name);
2891 DIE;
2896 static void init_label_map(struct superbfd *sbfd)
2898 struct label_map *map;
2900 vec_init(&sbfd->maps);
2901 init_csyms(sbfd);
2902 init_callers(sbfd);
2904 struct symbol_hash csyms;
2905 symbol_hash_init(&csyms);
2907 asymbol **symp;
2908 for (symp = sbfd->syms.data;
2909 symp < sbfd->syms.data + sbfd->syms.size; symp++) {
2910 asymbol *csym = canonical_symbol(sbfd, *symp);
2911 if (csym == NULL)
2912 continue;
2913 char *key = strprintf("%p", csym);
2914 asymbol **csymp = symbol_hash_lookup(&csyms, key, TRUE);
2915 free(key);
2916 if (*csymp != NULL)
2917 continue;
2918 *csymp = csym;
2920 map = vec_grow(&sbfd->maps, 1);
2921 map->csym = csym;
2922 map->count = 0;
2923 map->label = symbol_label(sbfd, csym);
2926 struct label_mapp_hash label_maps;
2927 label_mapp_hash_init(&label_maps);
2928 for (map = sbfd->maps.data;
2929 map < sbfd->maps.data + sbfd->maps.size; map++) {
2930 struct label_map **mapp =
2931 label_mapp_hash_lookup(&label_maps, map->label, TRUE);
2932 if (*mapp == NULL) {
2933 *mapp = map;
2934 continue;
2937 struct label_map *first_map = *mapp;
2938 if (first_map->count == 0)
2939 first_map->label = strprintf("%s~%d", map->label, 0);
2940 map->label = strprintf("%s~%d", map->label, ++first_map->count);
2943 label_mapp_hash_init(&sbfd->maps_hash);
2944 for (map = sbfd->maps.data;
2945 map < sbfd->maps.data + sbfd->maps.size; map++) {
2946 char *key = strprintf("%p", map->csym);
2947 struct label_map **mapp =
2948 label_mapp_hash_lookup(&sbfd->maps_hash, key, TRUE);
2949 free(key);
2950 *mapp = map;
2951 map->orig_label = map->label;
2955 static const char *label_lookup(struct superbfd *sbfd, asymbol *sym)
2957 asymbol *csym = canonical_symbol(sbfd, sym);
2958 char *key = strprintf("%p", csym);
2959 struct label_map **mapp =
2960 label_mapp_hash_lookup(&sbfd->maps_hash, key, FALSE);
2961 free(key);
2962 if (mapp == NULL)
2963 DIE;
2964 return (*mapp)->label;
2967 static void print_label_changes(struct superbfd *sbfd)
2969 asection *sect;
2970 struct span *span;
2971 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2972 struct supersect *ss = fetch_supersect(sbfd, sect);
2973 for (span = ss->spans.data;
2974 span < ss->spans.data + ss->spans.size; span++) {
2975 if (strcmp(span->label, span->orig_label) != 0)
2976 debug1(sbfd, "Label change: %s -> %s\n",
2977 span->label, span->orig_label);
2982 static void label_map_set(struct superbfd *sbfd, const char *oldlabel,
2983 const char *label)
2985 struct label_map *map;
2986 for (map = sbfd->maps.data;
2987 map < sbfd->maps.data + sbfd->maps.size; map++) {
2988 if (strcmp(map->orig_label, oldlabel) == 0) {
2989 if (strcmp(map->orig_label, map->label) != 0 &&
2990 strcmp(map->label, label) != 0)
2991 DIE;
2992 map->label = label;
2993 return;
2996 DIE;
2999 static void change_initial_label(struct span *span, const char *label)
3001 struct superbfd *sbfd = span->ss->parent;
3002 span->label = label;
3003 span->orig_label = label;
3004 if (span->symbol) {
3005 asymbol *csym = canonical_symbol(sbfd, span->symbol);
3006 char *key = strprintf("%p", csym);
3007 struct label_map **mapp =
3008 label_mapp_hash_lookup(&sbfd->maps_hash, key, FALSE);
3009 free(key);
3010 assert(mapp);
3011 (*mapp)->label = span->label;
3012 (*mapp)->orig_label = span->orig_label;
3013 span->symbol = NULL;
3017 static void init_callers(struct superbfd *sbfd)
3019 string_hash_init(&sbfd->callers);
3020 asection *sect;
3021 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
3022 struct supersect *ss = fetch_supersect(sbfd, sect);
3023 arelent **relocp;
3024 for (relocp = ss->relocs.data;
3025 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
3026 asymbol *sym = *(*relocp)->sym_ptr_ptr;
3027 unsigned long val =
3028 sym->value + reloc_target_offset(ss, *relocp);
3029 char *key = strprintf("%s+%lx", sym->section->name,
3030 val);
3031 const char **ret = string_hash_lookup(&sbfd->callers,
3032 key, TRUE);
3033 free(key);
3034 asymbol *csym = canonical_symbol(sbfd, sect->symbol);
3035 if (*ret != NULL)
3036 *ret = "*multiple_callers*";
3037 else if (static_local_symbol(sbfd, csym))
3038 *ret = static_local_symbol(sbfd, csym);
3039 else
3040 *ret = sect->name;
3045 static const char *find_caller(struct supersect *ss, asymbol *sym)
3047 char *key = strprintf("%s+%lx", sym->section->name,
3048 (unsigned long)sym->value);
3049 const char **ret = string_hash_lookup(&ss->parent->callers, key, FALSE);
3050 free(key);
3052 if (ret == NULL)
3053 return "*no_caller*";
3054 return *ret;
3057 static void init_csyms(struct superbfd *sbfd)
3059 asymbolpp_hash_init(&sbfd->csyms);
3061 asymbol **symp;
3062 for (symp = sbfd->syms.data; symp < sbfd->syms.data + sbfd->syms.size;
3063 symp++) {
3064 asymbol *sym = *symp;
3065 if ((sym->flags & BSF_DEBUGGING) != 0)
3066 continue;
3067 char *key = strprintf("%s+%lx", sym->section->name,
3068 (unsigned long)sym->value);
3069 asymbol ***csympp = asymbolpp_hash_lookup(&sbfd->csyms, key,
3070 TRUE);
3071 free(key);
3072 if (*csympp == NULL) {
3073 *csympp = symp;
3074 continue;
3076 asymbol *csym = **csympp;
3077 if ((csym->flags & BSF_GLOBAL) != 0)
3078 continue;
3079 if ((sym->flags & BSF_GLOBAL) != 0)
3080 *csympp = symp;
3084 static asymbol **symbolp_scan(struct supersect *ss, bfd_vma value)
3086 char *key = strprintf("%s+%lx", ss->name, (unsigned long)value);
3087 asymbol ***csympp =
3088 asymbolpp_hash_lookup(&ss->parent->csyms, key, FALSE);
3089 free(key);
3090 if (csympp != NULL)
3091 return *csympp;
3093 /* For section symbols of sections containing no symbols, return the
3094 section symbol that relocations are generated against */
3095 if (value == 0)
3096 return &ss->symbol;
3097 return NULL;
3100 static asymbol **canonical_symbolp(struct superbfd *sbfd, asymbol *sym)
3102 if (bfd_is_const_section(sym->section)) {
3103 asymbol **csymp;
3104 for (csymp = sbfd->syms.data;
3105 csymp < sbfd->syms.data + sbfd->syms.size; csymp++) {
3106 if (sym == *csymp)
3107 return csymp;
3109 return NULL;
3111 return symbolp_scan(fetch_supersect(sbfd, sym->section), sym->value);
3114 static asymbol *canonical_symbol(struct superbfd *sbfd, asymbol *sym)
3116 if (bfd_is_const_section(sym->section))
3117 return sym;
3118 asymbol **symp = canonical_symbolp(sbfd, sym);
3119 return symp != NULL ? *symp : NULL;
3122 static char *static_local_symbol(struct superbfd *sbfd, asymbol *sym)
3124 struct supersect *ss = fetch_supersect(sbfd, sym->section);
3125 if ((sym->flags & BSF_LOCAL) == 0 || (sym->flags & BSF_OBJECT) == 0)
3126 return NULL;
3127 char *dot = strrchr(sym->name, '.');
3128 if (dot == NULL || dot[1 + strspn(dot + 1, "0123546789")] != '\0')
3129 return NULL;
3130 char *basename = strndup(sym->name, dot - sym->name);
3132 /* Handle C.123.12345 symbols */
3133 dot = strrchr(basename, '.');
3134 if (dot != NULL && dot[1 + strspn(dot + 1, "0123546789")] == '\0')
3135 basename = strndup(basename, dot - basename);
3136 const char *caller;
3137 if (strcmp(basename, "__func__") == 0 ||
3138 strcmp(basename, "__PRETTY_FUNCTION__") == 0)
3139 caller = (const char *)ss->contents.data + sym->value;
3140 else
3141 caller = find_caller(ss, sym);
3142 return strprintf("%s<%s>", basename, caller);
3145 static char *symbol_label(struct superbfd *sbfd, asymbol *sym)
3147 const char *filename = sbfd->abfd->filename;
3148 char *c = strstr(filename, ".KSPLICE");
3149 int flen = (c == NULL ? strlen(filename) : c - filename);
3151 char *label;
3152 if (bfd_is_und_section(sym->section) || (sym->flags & BSF_GLOBAL) != 0) {
3153 label = strdup(sym->name);
3154 } else if (bfd_is_const_section(sym->section)) {
3155 label = strprintf("%s<%.*s>", sym->name, flen, filename);
3156 } else {
3157 asymbol *gsym = canonical_symbol(sbfd, sym);
3159 if (gsym == NULL)
3160 label = strprintf("%s+%lx<%.*s>",
3161 sym->section->name,
3162 (unsigned long)sym->value,
3163 flen, filename);
3164 else if ((gsym->flags & BSF_GLOBAL) != 0)
3165 label = strdup(gsym->name);
3166 else if (static_local_symbol(sbfd, gsym))
3167 label = strprintf("%s+%lx<%.*s>",
3168 static_local_symbol(sbfd, gsym),
3169 (unsigned long)sym->value,
3170 flen, filename);
3171 else
3172 label = strprintf("%s<%.*s>",
3173 gsym->name, flen, filename);
3176 return label;
3179 static void keep_span(struct span *span)
3181 span->keep = true;
3182 span->ss->keep = true;
3185 static struct span *new_span(struct supersect *ss, bfd_vma start, bfd_vma size)
3187 struct span *span = vec_grow(&ss->spans, 1);
3188 span->size = size;
3189 span->contents_size = size;
3190 span->start = start;
3191 span->ss = ss;
3192 span->keep = true;
3193 span->new = false;
3194 span->patch = false;
3195 span->bugpatch = false;
3196 span->datapatch = false;
3197 span->precallable = strstarts(ss->name, ".ksplice_call_pre_apply") ||
3198 strstarts(ss->name, ".ksplice_call_check_apply") ||
3199 strstarts(ss->name, ".ksplice_call_fail_apply") ||
3200 strstarts(ss->name, ".ksplice_call_post_remove");
3201 span->match = NULL;
3202 vec_init(&span->entry_points);
3203 span->shift = 0;
3204 asymbol **symp = symbolp_scan(ss, span->start);
3205 if (symp != NULL) {
3206 span->symbol = *symp;
3207 span->label = label_lookup(ss->parent, span->symbol);
3208 } else {
3209 span->symbol = NULL;
3210 const char *label = label_lookup(ss->parent, ss->symbol);
3211 if (span->start != 0)
3212 span->label = strprintf("%s<span:%lx>", label,
3213 (unsigned long)span->start);
3214 else
3215 span->label = label;
3217 span->orig_label = span->label;
3218 return span;
3221 static void initialize_string_spans(struct supersect *ss)
3223 const char *str;
3224 for (str = ss->contents.data;
3225 (void *)str < ss->contents.data + ss->contents.size;) {
3226 bfd_vma start = (unsigned long)str -
3227 (unsigned long)ss->contents.data;
3228 bfd_vma size = strlen(str) + 1;
3229 bfd_vma contents_size = size;
3230 while ((start + size) % (1 << ss->alignment) != 0 &&
3231 start + size < ss->contents.size) {
3232 /* Some string sections, like __ksymtab_strings, only
3233 align some strings with the declared alignment */
3234 if (str[size] != '\0')
3235 break;
3236 size++;
3238 struct span *span = new_span(ss, start, size);
3239 span->contents_size = contents_size;
3240 str += size;
3244 static int compare_ulongs(const void *va, const void *vb)
3246 const unsigned long *a = va, *b = vb;
3247 return *a - *b;
3250 static void initialize_table_spans(struct superbfd *sbfd,
3251 struct table_section *s)
3253 asection *isection = bfd_get_section_by_name(sbfd->abfd, s->sect);
3254 if (isection == NULL)
3255 return;
3256 struct supersect *ss = fetch_supersect(sbfd, isection);
3257 if (ss->alignment < ffs(s->entry_align) - 1)
3258 ss->alignment = ffs(s->entry_align) - 1;
3260 asection *other_sect = NULL;
3261 if (s->other_sect != NULL)
3262 other_sect = bfd_get_section_by_name(sbfd->abfd, s->other_sect);
3263 struct supersect *other_ss = NULL;
3264 if (other_sect != NULL)
3265 other_ss = fetch_supersect(sbfd, other_sect);
3267 asection *crc_sect = NULL;
3268 if (s->crc_sect != NULL)
3269 crc_sect = bfd_get_section_by_name(sbfd->abfd, s->crc_sect);
3270 struct supersect *crc_ss = NULL;
3271 if (crc_sect != NULL)
3272 crc_ss = fetch_supersect(sbfd, crc_sect);
3274 struct ulong_vec offsets;
3275 vec_init(&offsets);
3277 void *entry;
3278 for (entry = ss->contents.data;
3279 entry < ss->contents.data + ss->contents.size;
3280 entry += s->entry_size) {
3281 struct span *span = new_span(ss, addr_offset(ss, entry),
3282 s->entry_size);
3283 if (s->entry_contents_size != 0)
3284 span->contents_size = s->entry_contents_size;
3285 if ((span->symbol == NULL ||
3286 (span->symbol->flags & BSF_SECTION_SYM) != 0) &&
3287 s->has_addr) {
3288 arelent *reloc = find_reloc(ss, entry + s->addr_offset);
3289 assert(reloc);
3290 struct span *target_span = reloc_target_span(ss, reloc);
3291 assert(target_span);
3292 asymbol *sym = *reloc->sym_ptr_ptr;
3293 unsigned long val = sym->value +
3294 reloc_target_offset(ss, reloc) -
3295 (target_span->start + target_span->shift);
3296 char *label = strprintf("%s<target:%s+%lx>", ss->name,
3297 target_span->label, val);
3298 change_initial_label(span, label);
3301 if (other_sect != NULL) {
3302 asymbol *sym;
3303 bfd_vma offset = read_reloc(ss, entry + s->other_offset,
3304 sizeof(void *), &sym);
3305 if (sym->section == other_sect) {
3306 assert(offset >= 0 &&
3307 offset < other_ss->contents.size);
3308 *vec_grow(&offsets, 1) = offset;
3312 if (crc_sect != NULL)
3313 new_span(crc_ss, addr_offset(ss, entry) / s->entry_size
3314 * s->crc_size, s->crc_size);
3316 if (ss->type == SS_TYPE_EXPORT) {
3317 const char *symname = read_string(ss, entry +
3318 s->other_offset);
3319 char *label = strprintf("%s:%s", ss->name, symname);
3320 change_initial_label(span, label);
3324 if (other_sect == NULL)
3325 return;
3327 *vec_grow(&offsets, 1) = 0;
3328 qsort(offsets.data, offsets.size, sizeof(*offsets.data),
3329 compare_ulongs);
3330 *vec_grow(&offsets, 1) = other_ss->contents.size;
3332 unsigned long *off;
3333 for (off = offsets.data; off < offsets.data + offsets.size - 1; off++) {
3334 if (*off != *(off + 1))
3335 new_span(other_ss, *off, *(off + 1) - *off);
3339 static void initialize_table_section_spans(struct superbfd *sbfd)
3341 struct supersect *tables_ss =
3342 fetch_supersect(offsets_sbfd,
3343 bfd_get_section_by_name(offsets_sbfd->abfd,
3344 ".ksplice_table_sections"));
3345 const struct table_section *ts;
3346 struct table_section s;
3347 for (ts = tables_ss->contents.data;
3348 (void *)ts < tables_ss->contents.data + tables_ss->contents.size;
3349 ts++) {
3350 s = *ts;
3351 s.sect = read_string(tables_ss, &ts->sect);
3352 s.other_sect = read_string(tables_ss, &ts->other_sect);
3353 s.crc_sect = read_string(tables_ss, &ts->crc_sect);
3354 initialize_table_spans(sbfd, &s);
3358 static void initialize_ksplice_call_spans(struct supersect *ss)
3360 arelent **relocp;
3361 for (relocp = ss->relocs.data;
3362 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
3363 arelent *reloc = *relocp;
3364 new_span(ss, reloc->address, bfd_get_reloc_size(reloc->howto));
3365 /* the span labels should already be unique */
3369 static void initialize_spans(struct superbfd *sbfd)
3371 asection *sect;
3372 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
3373 if (is_table_section(sect->name, true, true) && mode("keep"))
3374 continue;
3376 struct supersect *ss = fetch_supersect(sbfd, sect);
3377 if (ss->type == SS_TYPE_STRING)
3378 initialize_string_spans(ss);
3379 else if (ss->type == SS_TYPE_KSPLICE_CALL)
3380 initialize_ksplice_call_spans(ss);
3381 else
3382 new_span(ss, 0, ss->contents.size);
3384 if (mode("keep"))
3385 initialize_table_section_spans(sbfd);
3388 /* Returns the span pointed to by the relocation at span->start + offset */
3389 static struct span *span_offset_target_span(struct span *span, int offset)
3391 void *entry = span->ss->contents.data + span->start;
3392 arelent *reloc = find_reloc(span->ss, entry + offset);
3393 if (reloc == NULL)
3394 return NULL;
3395 return reloc_target_span(span->ss, reloc);
3398 struct span *reloc_target_span(struct supersect *ss, arelent *reloc)
3400 asymbol *sym_ptr = *reloc->sym_ptr_ptr;
3401 if (bfd_is_const_section(sym_ptr->section))
3402 return NULL;
3404 bfd_vma addend = sym_ptr->value;
3405 if ((sym_ptr->flags & BSF_SECTION_SYM) != 0)
3406 addend += reloc_target_offset(ss, reloc);
3408 struct supersect *sym_ss =
3409 fetch_supersect(ss->parent, sym_ptr->section);
3410 struct span *span, *target_span = sym_ss->spans.data;
3411 for (span = sym_ss->spans.data;
3412 span < sym_ss->spans.data + sym_ss->spans.size; span++) {
3413 if (addend >= span->start && addend < span->start + span->size)
3414 target_span = span;
3416 return target_span;
3419 static bfd_vma reloc_target_offset(struct supersect *ss, arelent *reloc)
3421 bfd_vma offset = reloc_offset(ss, reloc);
3422 if (reloc->howto->pc_relative) {
3423 if ((ss->flags & SEC_CODE) != 0)
3424 return offset + bfd_get_reloc_size(reloc->howto);
3426 const struct table_section *ts = get_table_section(ss->name);
3427 if (ts != NULL && ts->relative_addr &&
3428 reloc->address % ts->entry_size == ts->addr_offset)
3429 return offset - ts->addr_offset;
3430 if (ts != NULL && ts->relative_other &&
3431 reloc->address % ts->entry_size == ts->other_offset)
3432 return offset - ts->other_offset;
3434 DIE;
3436 return offset;
3439 struct span *find_span(struct supersect *ss, bfd_size_type address)
3441 struct span *span;
3442 for (span = ss->spans.data; span < ss->spans.data + ss->spans.size;
3443 span++) {
3444 if (address >= span->start &&
3445 address < span->start + span->size)
3446 return span;
3448 /* Deal with empty BSS sections */
3449 if (ss->contents.size == 0 && ss->spans.size > 0)
3450 return ss->spans.data;
3451 /* Deal with section end pointers */
3452 if (address == ss->contents.size && ss->spans.size == 1)
3453 return ss->spans.data;
3454 return NULL;
3457 void compute_span_shifts(struct superbfd *sbfd)
3459 asection *sect;
3460 struct span *span;
3461 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
3462 struct supersect *ss = fetch_supersect(sbfd, sect);
3463 if (!ss->keep)
3464 continue;
3465 bfd_size_type offset = 0;
3466 for (span = ss->spans.data;
3467 span < ss->spans.data + ss->spans.size; span++) {
3468 if (!span->keep)
3469 continue;
3470 span->shift = offset - span->start;
3471 offset += span->size;
3476 void remove_unkept_spans(struct superbfd *sbfd)
3478 asection *sect;
3479 struct span *span;
3480 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
3481 struct supersect *ss = fetch_supersect(sbfd, sect);
3482 delete_obsolete_relocs(ss);
3483 struct arelentp_vec orig_relocs;
3484 vec_move(&orig_relocs, &ss->relocs);
3485 arelent **relocp, *reloc;
3486 for (relocp = orig_relocs.data;
3487 relocp < orig_relocs.data + orig_relocs.size; relocp++) {
3488 reloc = *relocp;
3489 asymbol *sym = *reloc->sym_ptr_ptr;
3490 span = reloc_target_span(ss, reloc);
3491 if ((span != NULL && span->keep && span->shift == 0) ||
3492 bfd_is_const_section(sym->section)) {
3493 *vec_grow(&ss->relocs, 1) = reloc;
3494 continue;
3496 struct supersect *sym_ss =
3497 fetch_supersect(sbfd, sym->section);
3498 if (span != NULL && (sym->flags & BSF_SECTION_SYM) == 0
3499 && find_span(sym_ss, sym->value) != span) {
3500 err(sbfd, "Spans for symbol %s and relocation "
3501 "target do not match in sect %s\n",
3502 sym->name, sym_ss->name);
3503 DIE;
3505 if (span != NULL && span->keep) {
3506 arelent *new_reloc = malloc(sizeof(*new_reloc));
3507 *new_reloc = *reloc;
3508 new_reloc->addend = reloc_offset(ss, reloc);
3509 new_reloc->addend += span->shift;
3510 *vec_grow(&ss->new_relocs, 1) = new_reloc;
3515 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
3516 struct supersect *ss = fetch_supersect(sbfd, sect), orig_ss;
3517 if (!ss->keep)
3518 continue;
3519 supersect_move(&orig_ss, ss);
3520 vec_init(&ss->spans);
3521 for (span = orig_ss.spans.data;
3522 span < orig_ss.spans.data + orig_ss.spans.size; span++) {
3523 if (!span->keep)
3524 continue;
3525 struct span *new_span = vec_grow(&ss->spans, 1);
3526 *new_span = *span;
3527 new_span->start = span->start + span->shift;
3528 new_span->shift = 0;
3529 sect_copy(ss, sect_do_grow(ss, 1, span->size, 1),
3530 &orig_ss, orig_ss.contents.data + span->start,
3531 span->size);
3536 static void init_objmanip_superbfd(struct superbfd *sbfd)
3538 init_label_map(sbfd);
3539 initialize_supersect_types(sbfd);
3540 initialize_spans(sbfd);
3541 load_options(sbfd);
3542 compute_entry_points(sbfd);
3545 void mangle_section_name(struct superbfd *sbfd, const char *name)
3547 asection *sect = bfd_get_section_by_name(sbfd->abfd, name);
3548 if (sect == NULL)
3549 return;
3550 struct supersect *ss = fetch_supersect(sbfd, sect);
3551 ss->name = strprintf(".ksplice_pre.%s", ss->name);
3554 static void write_bugline_patches(struct superbfd *sbfd)
3556 const struct table_section *ts = get_table_section("__bug_table");
3557 asection *sect = bfd_get_section_by_name(sbfd->abfd, "__bug_table");
3558 if (sect == NULL)
3559 return;
3560 struct supersect *ss = fetch_supersect(sbfd, sect);
3561 assert(ts != NULL);
3563 void *entry;
3564 for (entry = ss->contents.data;
3565 entry < ss->contents.data + ss->contents.size;
3566 entry += ts->entry_size) {
3567 struct span *span = find_span(ss, addr_offset(ss, entry));
3568 assert(span != NULL);
3569 if (!span->bugpatch)
3570 continue;
3571 arelent *reloc = find_reloc(ss, entry + ts->addr_offset);
3572 assert(reloc != NULL);
3573 asymbol *sym = *reloc->sym_ptr_ptr;
3574 assert(!bfd_is_const_section(sym->section));
3575 struct supersect *kpatch_ss =
3576 make_section(sbfd, ".ksplice_patches%s",
3577 sym->section->name);
3579 bfd_vma offset, start = 0;
3580 for (offset = 0; offset <= span->size; offset++) {
3581 if (offset != span->size &&
3582 !part_of_reloc(ss, span->start + offset))
3583 continue;
3584 if (start == offset) {
3585 start++;
3586 continue;
3588 /* an interval of non-relocations just passed */
3589 struct ksplice_patch *kpatch =
3590 sect_grow(kpatch_ss, 1, struct ksplice_patch);
3591 write_ksplice_patch_reloc
3592 (kpatch_ss, sym->section->name, &kpatch->oldaddr,
3593 sizeof(kpatch->oldaddr), span->label, start);
3595 char *data = write_patch_storage(kpatch_ss, kpatch,
3596 offset - start, NULL);
3597 memcpy(data, entry + start, offset - start);
3598 kpatch->type = KSPLICE_PATCH_DATA;
3599 start = offset + 1;
3604 void *write_patch_storage(struct supersect *ss, struct ksplice_patch *kpatch,
3605 size_t size, struct supersect **data_ssp)
3607 struct supersect *data_ss = make_section(ss->parent,
3608 ".ksplice_patch_data");
3609 char *saved = sect_do_grow(data_ss, 1, size, 1);
3610 write_reloc(ss, &kpatch->saved, &data_ss->symbol,
3611 addr_offset(data_ss, saved));
3612 char *data = sect_do_grow(data_ss, 1, size, 1);
3613 write_reloc(ss, &kpatch->contents, &data_ss->symbol,
3614 addr_offset(data_ss, data));
3615 kpatch->size = size;
3616 if (data_ssp != NULL)
3617 *data_ssp = data_ss;
3618 return data;