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