Do not write Ksplice relocations to the middle of a patched section.
[ksplice.git] / objmanip.c
blob99b8e3be0514928298191cceec77d403d7314f6d
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-primary: "objmanip <post.o> <out.o> keep-primary <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-helper: "objmanip <pre.o> <out.o> keep-helper"
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_primary(struct superbfd *isbfd, const char *pre);
81 void do_keep_helper(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);
94 enum supersect_type supersect_type(struct supersect *ss);
95 void initialize_supersect_types(struct superbfd *sbfd);
96 static void initialize_spans(struct superbfd *sbfd);
97 static void initialize_string_spans(struct supersect *ss);
98 static void initialize_table_spans(struct superbfd *sbfd,
99 struct table_section *s);
100 static void initialize_table_section_spans(struct superbfd *sbfd);
101 static void initialize_ksplice_call_spans(struct supersect *ss);
102 struct span *reloc_target_span(struct supersect *ss, arelent *reloc);
103 static struct span *span_offset_target_span(struct span *span, int offset);
104 struct span *find_span(struct supersect *ss, bfd_size_type address);
105 void remove_unkept_spans(struct superbfd *sbfd);
106 void compute_span_shifts(struct superbfd *sbfd);
107 static struct span *new_span(struct supersect *ss, bfd_vma start, bfd_vma size);
108 static bool is_table_section(const char *name, bool consider_other,
109 bool consider_crc);
110 const struct table_section *get_table_section(const char *name);
111 void mangle_section_name(struct superbfd *sbfd, const char *name);
113 void rm_relocs(struct superbfd *isbfd);
114 void rm_some_relocs(struct supersect *ss);
115 void write_ksplice_reloc(struct supersect *ss, arelent *orig_reloc);
116 static void write_ksplice_reloc_howto(struct supersect *ss, const
117 struct ksplice_reloc_howto *const *addr,
118 reloc_howto_type *howto,
119 enum ksplice_reloc_howto_type type);
120 static void write_ksplice_date_reloc(struct supersect *ss, unsigned long offset,
121 const char *str,
122 enum ksplice_reloc_howto_type type);
123 static void write_ksplice_patch_reloc(struct supersect *ss,
124 const char *sectname, unsigned long *addr,
125 bfd_size_type size, const char *label,
126 long addend);
127 static void write_ksplice_nonreloc_howto(struct supersect *ss,
128 const struct ksplice_reloc_howto
129 *const *addr,
130 enum ksplice_reloc_howto_type type,
131 int size);
132 static void write_date_relocs(struct superbfd *sbfd, const char *str,
133 enum ksplice_reloc_howto_type type);
134 static void write_table_relocs(struct superbfd *sbfd, const char *sectname,
135 enum ksplice_reloc_howto_type type);
136 static void write_ksplice_table_reloc(struct supersect *ss,
137 unsigned long address,
138 const char *label,
139 enum ksplice_reloc_howto_type type);
140 void load_ksplice_symbol_offsets(struct superbfd *sbfd);
141 void write_canary(struct supersect *ss, int offset, bfd_size_type size,
142 bfd_vma dst_mask);
143 static void write_ksplice_section(struct span *span);
144 void write_ksplice_patch(struct superbfd *sbfd, struct span *span);
145 void *write_patch_storage(struct supersect *ss, struct ksplice_patch *patch,
146 size_t size, struct supersect **data_ssp);
147 void write_ksplice_deleted_patch(struct superbfd *sbfd, const char *name,
148 const char *label, const char *sectname);
149 static void write_bugline_patches(struct superbfd *sbfd);
150 asymbol **make_undefined_symbolp(struct superbfd *sbfd, const char *name);
151 void filter_table_sections(struct superbfd *isbfd);
152 void filter_table_section(struct superbfd *sbfd, const struct table_section *s);
153 void keep_referenced_sections(struct superbfd *sbfd);
154 void mark_precallable_spans(struct superbfd *sbfd);
155 bfd_boolean copy_object(bfd *ibfd, bfd *obfd);
156 void setup_section(bfd *ibfd, asection *isection, void *obfdarg);
157 static void setup_new_section(bfd *obfd, struct supersect *ss);
158 static void write_section(bfd *obfd, asection *osection, void *arg);
159 static void delete_obsolete_relocs(struct supersect *ss);
160 void mark_symbols_used_in_relocations(bfd *abfd, asection *isection,
161 void *ignored);
162 static void ss_mark_symbols_used_in_relocations(struct supersect *ss);
163 void filter_symbols(bfd *ibfd, bfd *obfd, struct asymbolp_vec *osyms,
164 struct asymbolp_vec *isyms);
165 static bool deleted_table_section_symbol(bfd *abfd, asymbol *sym);
166 void read_str_set(struct str_vec *strs);
167 bool str_in_set(const char *str, const struct str_vec *strs);
168 struct supersect *__attribute((format(printf, 2, 3)))
169 make_section(struct superbfd *sbfd, const char *fmt, ...);
170 void __attribute__((format(printf, 3, 4)))
171 write_string(struct supersect *ss, const char **addr, const char *fmt, ...);
172 void write_ksplice_export(struct superbfd *sbfd, struct span *span, bool del);
173 void write_reloc(struct supersect *ss, const void *addr, asymbol **symp,
174 bfd_vma offset);
175 arelent *create_reloc(struct supersect *ss, const void *addr, asymbol **symp,
176 bfd_vma offset);
177 static void foreach_symbol_pair(struct superbfd *oldsbfd, struct superbfd *newsbfd,
178 void (*fn)(struct span *old_span,
179 asymbol *oldsym,
180 struct span *new_span,
181 asymbol *newsym));
182 static void check_global_symbols(struct span *old_span, asymbol *oldsym,
183 struct span *new_span, asymbol *newsym);
184 static void match_global_symbols(struct span *old_span, asymbol *oldsym,
185 struct span *new_span, asymbol *newsym);
186 static void match_symbol_spans(struct span *old_span, asymbol *oldsym,
187 struct span *new_span, asymbol *newsym);
188 static void match_table_spans(struct span *old_span, struct span *new_span);
190 static struct span *get_crc_span(struct span *span,
191 const struct table_section *ts);
192 static void foreach_span_pair(struct superbfd *oldsbfd,
193 struct superbfd *newsbfd,
194 void (*fn)(struct span *old_span,
195 struct span *new_span));
196 static void match_spans_by_label(struct span *old_span, struct span *new_span);
197 static void match_string_spans(struct span *old_span, struct span *new_span);
198 static void mark_new_spans(struct superbfd *sbfd);
199 static void handle_deleted_spans(struct superbfd *oldsbfd,
200 struct superbfd *newsbfd);
201 static void unmatch_addr_spans(struct span *old_span, struct span *new_span,
202 const struct table_section *ts);
203 static void compare_matched_spans(struct superbfd *newsbfd);
204 static void compare_spans(struct span *old_span, struct span *new_span);
205 static void update_nonzero_offsets(struct superbfd *sbfd);
206 static void handle_nonzero_offset_relocs(struct supersect *ss);
207 static void keep_span(struct span *span);
209 static void init_objmanip_superbfd(struct superbfd *sbfd);
210 static const char *label_lookup(struct superbfd *sbfd, asymbol *sym);
211 static void label_map_set(struct superbfd *sbfd, const char *oldlabel,
212 const char *label);
213 static void print_label_changes(struct superbfd *sbfd);
214 static void init_label_map(struct superbfd *sbfd);
215 static void change_initial_label(struct span *span, const char *label);
216 static asymbol **symbolp_scan(struct supersect *ss, bfd_vma value);
217 static void init_csyms(struct superbfd *sbfd);
218 static void init_callers(struct superbfd *sbfd);
219 static asymbol *canonical_symbol(struct superbfd *sbfd, asymbol *sym);
220 static asymbol **canonical_symbolp(struct superbfd *sbfd, asymbol *sym);
221 static char *static_local_symbol(struct superbfd *sbfd, asymbol *sym);
222 static char *symbol_label(struct superbfd *sbfd, asymbol *sym);
224 int verbose = 0;
225 #define debug_(sbfd, level, fmt, ...) \
226 do { \
227 if (verbose >= (level)) \
228 printf("%s: " fmt, (sbfd)->abfd->filename, \
229 ## __VA_ARGS__); \
230 } while (0)
231 #define debug0(sbfd, fmt, ...) debug_(sbfd, 0, fmt, ## __VA_ARGS__)
232 #define debug1(sbfd, fmt, ...) debug_(sbfd, 1, fmt, ## __VA_ARGS__)
233 #define err(sbfd, fmt, ...) \
234 do { \
235 fprintf(stderr, "%s: " fmt, (sbfd)->abfd->filename, \
236 ## __VA_ARGS__); \
237 } while (0)
239 struct str_vec delsects, rmsyms;
240 bool changed;
242 struct ksplice_config *config;
244 const char *modestr, *kid, *finalize_target = NULL;
245 bool write_output = true;
247 struct superbfd *offsets_sbfd = NULL;
249 #define mode(str) starts_with(modestr, str)
251 DECLARE_VEC_TYPE(unsigned long, addr_vec);
252 DEFINE_HASH_TYPE(struct addr_vec, addr_vec_hash,
253 addr_vec_hash_init, addr_vec_hash_free, addr_vec_hash_lookup,
254 vec_init);
255 struct addr_vec_hash system_map;
257 struct bool_hash system_map_written;
258 struct ulong_hash ksplice_symbol_offset;
259 struct ulong_hash ksplice_howto_offset;
260 struct ulong_hash ksplice_string_offset;
262 void load_system_map()
264 const char *config_dir = getenv("KSPLICE_CONFIG_DIR");
265 assert(config_dir);
266 FILE *fp = fopen(strprintf("%s/System.map", config_dir), "r");
267 assert(fp);
268 addr_vec_hash_init(&system_map);
269 unsigned long addr;
270 char type;
271 char *sym;
272 while (fscanf(fp, "%lx %c %as\n", &addr, &type, &sym) == 3)
273 *vec_grow(addr_vec_hash_lookup(&system_map, sym, TRUE),
274 1) = addr;
275 fclose(fp);
278 void load_ksplice_symbol_offsets(struct superbfd *sbfd)
280 asection *sect = bfd_get_section_by_name(sbfd->abfd,
281 ".ksplice_symbols");
282 if (sect == NULL)
283 return;
284 struct supersect *ss = fetch_supersect(sbfd, sect);
286 struct ksplice_symbol *ksym;
287 for (ksym = ss->contents.data;
288 (void *)ksym < ss->contents.data + ss->contents.size; ksym++) {
289 const char *label = read_string(ss, &ksym->label);
290 unsigned long *ksymbol_offp =
291 ulong_hash_lookup(&ksplice_symbol_offset, label, TRUE);
292 *ksymbol_offp = addr_offset(ss, ksym);
296 void load_offsets()
298 char *kmodsrc = getenv("KSPLICE_KMODSRC");
299 assert(kmodsrc != NULL);
300 bfd *offsets_bfd = bfd_openr(strprintf("%s/offsets.o", kmodsrc), NULL);
301 assert(offsets_bfd != NULL);
302 char **matching;
303 assert(bfd_check_format_matches(offsets_bfd, bfd_object, &matching));
304 offsets_sbfd = fetch_superbfd(offsets_bfd);
306 asection *config_sect = bfd_get_section_by_name(offsets_sbfd->abfd,
307 ".ksplice_config");
308 struct supersect *config_ss =
309 fetch_supersect(offsets_sbfd, config_sect);
311 config = config_ss->contents.data;
314 void load_options(struct superbfd *sbfd)
316 asection *sect = bfd_get_section_by_name(sbfd->abfd,
317 ".ksplice_options");
318 if (sect == NULL)
319 return;
320 struct supersect *ss = fetch_supersect(sbfd, sect);
321 const struct ksplice_option *opt;
322 for (opt = ss->contents.data;
323 (void *)opt < ss->contents.data + ss->contents.size; opt++) {
324 if (opt->type == KSPLICE_OPTION_ASSUME_RODATA) {
325 arelent *reloc = find_reloc(ss, &opt->target);
326 struct span *span = reloc_target_span(ss, reloc);
327 assert(span != NULL);
328 assert(span->ss->type == SS_TYPE_DATA);
329 assert(span->start == 0 &&
330 span->size == span->ss->contents.size);
331 span->ss->type = SS_TYPE_RODATA;
332 break;
333 } else {
334 err(sbfd, "Unrecognized Ksplice option %d\n",
335 opt->type);
336 DIE;
341 bool matchable_data_section(struct supersect *ss)
343 if (ss->type == SS_TYPE_STRING)
344 return true;
345 if (ss->type == SS_TYPE_RODATA)
346 return true;
347 if (ss->type == SS_TYPE_DATA && ss->relocs.size != 0)
348 return true;
349 if (ss->type == SS_TYPE_EXPORT)
350 return true;
351 return false;
354 bool unchangeable_section(struct supersect *ss)
356 if (ss->type == SS_TYPE_DATA)
357 return true;
358 if (ss->type == SS_TYPE_IGNORED && !starts_with(ss->name, ".debug") &&
359 strcmp(ss->name, "__ksymtab_strings") != 0)
360 return true;
361 return false;
364 int main(int argc, char *argv[])
366 if (getenv("KSPLICE_VERBOSE") != NULL)
367 verbose = atoi(getenv("KSPLICE_VERBOSE"));
369 bfd_init();
370 bfd *ibfd = bfd_openr(argv[1], NULL);
371 assert(ibfd);
373 char **matching;
374 assert(bfd_check_format_matches(ibfd, bfd_object, &matching));
376 const char *output_target = bfd_get_target(ibfd);
378 load_system_map();
379 load_offsets();
381 bool_hash_init(&system_map_written);
382 ulong_hash_init(&ksplice_symbol_offset);
383 ulong_hash_init(&ksplice_howto_offset);
384 ulong_hash_init(&ksplice_string_offset);
386 struct superbfd *isbfd = fetch_superbfd(ibfd);
388 modestr = argv[3];
389 if (mode("finalize"))
390 finalize_target = argv[4];
391 init_objmanip_superbfd(isbfd);
392 if (mode("keep-primary")) {
393 kid = argv[5];
394 do_keep_primary(isbfd, argv[4]);
395 } else if (mode("keep-helper")) {
396 do_keep_helper(isbfd);
397 } else if (mode("finalize")) {
398 do_finalize(isbfd);
399 } else if (mode("rmsyms")) {
400 do_rmsyms(isbfd);
403 if (write_output) {
404 bfd *obfd = bfd_openw(argv[2], output_target);
405 assert(obfd);
406 copy_object(ibfd, obfd);
407 assert(bfd_close(obfd));
410 if (offsets_sbfd != NULL)
411 assert(bfd_close(offsets_sbfd->abfd));
412 assert(bfd_close(ibfd));
413 return EXIT_SUCCESS;
416 void do_keep_primary(struct superbfd *isbfd, const char *pre)
418 struct bfd *prebfd = bfd_openr(pre, NULL);
419 assert(prebfd != NULL);
420 char **matching;
421 assert(bfd_check_format_matches(prebfd, bfd_object, &matching));
423 struct superbfd *presbfd = fetch_superbfd(prebfd);
424 init_objmanip_superbfd(presbfd);
426 foreach_symbol_pair(presbfd, isbfd, match_global_symbols);
427 debug1(isbfd, "Matched global\n");
428 foreach_span_pair(presbfd, isbfd, match_string_spans);
429 debug1(isbfd, "Matched string spans\n");
430 foreach_symbol_pair(presbfd, isbfd, match_symbol_spans);
431 debug1(isbfd, "Matched by name\n");
432 foreach_span_pair(presbfd, isbfd, match_spans_by_label);
433 debug1(isbfd, "Matched by label\n");
434 foreach_span_pair(presbfd, isbfd, match_table_spans);
435 debug1(isbfd, "Matched table spans\n");
437 do {
438 changed = false;
439 compare_matched_spans(isbfd);
440 update_nonzero_offsets(isbfd);
441 mark_new_spans(isbfd);
442 } while (changed);
443 vec_init(&delsects);
445 foreach_symbol_pair(presbfd, isbfd, check_global_symbols);
447 handle_deleted_spans(presbfd, isbfd);
448 handle_section_symbol_renames(presbfd, isbfd);
450 assert(bfd_close(prebfd));
452 do {
453 changed = false;
454 mark_precallable_spans(isbfd);
455 } while (changed);
457 asection *sect;
458 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
459 struct supersect *ss = fetch_supersect(isbfd, sect);
460 ss->keep = false;
461 struct span *span;
462 for (span = ss->spans.data;
463 span < ss->spans.data + ss->spans.size; span++) {
464 if (starts_with(ss->name, ".ksplice_options"))
465 span->keep = false;
466 else if (span->new || span->patch || span->datapatch)
467 keep_span(span);
468 else
469 span->keep = false;
470 if (span->patch && span->precallable) {
471 err(isbfd, "Patched span %s can be reached "
472 "by a precall function\n", span->label);
473 DIE;
478 print_label_changes(isbfd);
480 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
481 struct supersect *ss = fetch_supersect(isbfd, sect);
482 struct span *span;
483 for (span = ss->spans.data;
484 span < ss->spans.data + ss->spans.size; span++) {
485 if (span->patch || span->bugpatch || span->datapatch)
486 debug0(isbfd, "Patching span %s\n",
487 span->label);
491 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
492 struct supersect *ss = fetch_supersect(isbfd, sect);
493 struct span *span;
494 for (span = ss->spans.data;
495 span < ss->spans.data + ss->spans.size; span++) {
496 if (span->new)
497 debug0(isbfd, "New span %s\n", span->label);
501 write_output = false;
502 const char **sectname;
503 for (sectname = delsects.data;
504 sectname < delsects.data + delsects.size; sectname++) {
505 write_output = true;
506 debug0(isbfd, "Deleted section: %s\n", *sectname);
509 filter_table_sections(isbfd);
511 compute_span_shifts(isbfd);
513 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
514 struct supersect *ss = fetch_supersect(isbfd, sect);
515 if (ss->type == SS_TYPE_KSPLICE_CALL)
516 continue;
517 struct span *span;
518 for (span = ss->spans.data;
519 span < ss->spans.data + ss->spans.size; span++) {
520 if (span->keep)
521 write_output = true;
522 if (span->patch || span->new || span->datapatch)
523 write_ksplice_section(span);
524 if (span->patch || span->datapatch)
525 write_ksplice_patch(isbfd, span);
526 if (ss->type == SS_TYPE_EXPORT && span->new)
527 write_ksplice_export(isbfd, span, false);
531 write_bugline_patches(isbfd);
532 rm_relocs(isbfd);
533 remove_unkept_spans(isbfd);
536 void do_keep_helper(struct superbfd *isbfd)
538 asection *sect;
539 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
540 struct supersect *ss = fetch_supersect(isbfd, sect);
541 ss->keep = false;
542 struct span *span;
543 for (span = ss->spans.data;
544 span < ss->spans.data + ss->spans.size; span++) {
545 span->keep = false;
546 if (ss->type == SS_TYPE_TEXT &&
547 !starts_with(ss->name, ".fixup"))
548 keep_span(span);
549 if (ss->type == SS_TYPE_EXPORT)
550 keep_span(span);
554 asymbol **symp;
555 for (symp = isbfd->syms.data;
556 symp < isbfd->syms.data + isbfd->syms.size; symp++) {
557 asymbol *sym = *symp;
558 if (!bfd_is_const_section(sym->section) &&
559 (sym->flags & BSF_GLOBAL) != 0) {
560 struct supersect *sym_ss =
561 fetch_supersect(isbfd, sym->section);
562 if (sym->value == sym_ss->contents.size)
563 continue;
564 struct span *span = find_span(sym_ss, sym->value);
565 assert(span != NULL);
566 if (sym_ss->type != SS_TYPE_IGNORED)
567 keep_span(span);
571 do {
572 changed = false;
573 keep_referenced_sections(isbfd);
574 } while (changed);
576 filter_table_sections(isbfd);
577 compute_span_shifts(isbfd);
579 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
580 struct supersect *ss = fetch_supersect(isbfd, sect);
581 asymbol *sym = canonical_symbol(isbfd, sect->symbol);
582 if (sym == NULL)
583 continue;
584 if ((sym->flags & BSF_WEAK) != 0)
585 continue;
586 if (bfd_get_section_size(sect) == 0)
587 continue;
588 if (!ss->keep)
589 continue;
590 if (ss->type != SS_TYPE_TEXT && !matchable_data_section(ss))
591 continue;
593 struct span *span;
594 for (span = ss->spans.data;
595 span < ss->spans.data + ss->spans.size; span++) {
596 if (span->keep)
597 write_ksplice_section(span);
601 write_table_relocs(isbfd, "__bug_table", KSPLICE_HOWTO_BUG);
602 write_table_relocs(isbfd, "__ex_table", KSPLICE_HOWTO_EXTABLE);
603 rm_relocs(isbfd);
604 remove_unkept_spans(isbfd);
606 mangle_section_name(isbfd, "__markers");
607 mangle_section_name(isbfd, "__ex_table");
608 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
609 struct supersect *ss = fetch_supersect(isbfd, sect);
610 if (ss->type == SS_TYPE_EXPORT)
611 mangle_section_name(isbfd, ss->name);
615 void do_finalize(struct superbfd *isbfd)
617 load_ksplice_symbol_offsets(isbfd);
618 asection *sect;
619 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
620 struct supersect *ss = fetch_supersect(isbfd, sect);
621 if (ss->type == SS_TYPE_EXIT) {
622 struct span *span;
623 for (span = ss->spans.data;
624 span < ss->spans.data + ss->spans.size; span++)
625 span->keep = false;
626 ss->keep = false;
629 write_date_relocs(isbfd, "<{DATE...}>", KSPLICE_HOWTO_DATE);
630 write_date_relocs(isbfd, "<{TIME}>", KSPLICE_HOWTO_TIME);
631 rm_relocs(isbfd);
634 void do_rmsyms(struct superbfd *isbfd)
636 read_str_set(&rmsyms);
637 rm_relocs(isbfd);
640 void match_spans(struct span *old_span, struct span *new_span)
642 struct superbfd *sbfd = new_span->ss->parent;
643 if (old_span->match == new_span && new_span->match == old_span)
644 return;
645 if (old_span->match != NULL) {
646 err(sbfd, "Matching conflict: old %s: %s != %s\n",
647 old_span->label, old_span->match->label, new_span->label);
648 DIE;
650 if (new_span->match != NULL) {
651 err(sbfd, "Matching conflict: new %s: %s != %s\n",
652 new_span->label, new_span->match->label, old_span->label);
653 DIE;
655 old_span->match = new_span;
656 new_span->match = old_span;
657 debug1(sbfd, "Matched old %s to new %s\n", old_span->label,
658 new_span->label);
659 if (old_span->ss->type != new_span->ss->type &&
660 old_span->ss->type == new_span->ss->orig_type)
661 old_span->ss->type = new_span->ss->type;
663 const struct table_section *ts = get_table_section(old_span->ss->name);
664 if (ts == NULL || !ts->has_addr || ts->other_sect == NULL)
665 return;
666 struct span *old_sym_span =
667 span_offset_target_span(old_span, ts->other_offset);
668 struct span *new_sym_span =
669 span_offset_target_span(new_span, ts->other_offset);
670 assert(old_sym_span != NULL && new_sym_span != NULL);
671 match_spans(old_sym_span, new_sym_span);
674 static void match_global_symbols(struct span *old_span, asymbol *oldsym,
675 struct span *new_span, asymbol *newsym)
677 if ((oldsym->flags & BSF_GLOBAL) == 0 ||
678 (newsym->flags & BSF_GLOBAL) == 0)
679 return;
680 match_spans(old_span, new_span);
683 static void check_global_symbols(struct span *old_span, asymbol *oldsym,
684 struct span *new_span, asymbol *newsym)
686 if ((oldsym->flags & BSF_GLOBAL) == 0 ||
687 (newsym->flags & BSF_GLOBAL) == 0)
688 return;
689 if (old_span->ss->type == SS_TYPE_IGNORED)
690 return;
691 if (old_span->match != new_span || new_span->match != old_span) {
692 err(new_span->ss->parent, "Global symbol span mismatch: %s "
693 "%s/%s\n", oldsym->name, old_span->ss->name,
694 new_span->ss->name);
695 DIE;
699 static void foreach_symbol_pair(struct superbfd *oldsbfd, struct superbfd *newsbfd,
700 void (*fn)(struct span *old_span,
701 asymbol *oldsym,
702 struct span *new_span,
703 asymbol *newsym))
705 asymbol **oldsymp, **newsymp;
706 for (oldsymp = oldsbfd->syms.data;
707 oldsymp < oldsbfd->syms.data + oldsbfd->syms.size; oldsymp++) {
708 asymbol *oldsym = *oldsymp;
709 if (bfd_is_const_section(oldsym->section))
710 continue;
711 for (newsymp = newsbfd->syms.data;
712 newsymp < newsbfd->syms.data + newsbfd->syms.size;
713 newsymp++) {
714 asymbol *newsym = *newsymp;
715 if (bfd_is_const_section(newsym->section))
716 continue;
717 if (strcmp(oldsym->name, newsym->name) != 0)
718 continue;
720 struct supersect *old_ss =
721 fetch_supersect(oldsbfd, oldsym->section);
722 struct supersect *new_ss =
723 fetch_supersect(newsbfd, newsym->section);
724 if ((old_ss->type != new_ss->type &&
725 old_ss->type != new_ss->orig_type) ||
726 old_ss->type == SS_TYPE_SPECIAL ||
727 old_ss->type == SS_TYPE_EXPORT)
728 continue;
730 struct span *old_span =
731 find_span(old_ss, oldsym->value);
732 struct span *new_span =
733 find_span(new_ss, newsym->value);
734 if (old_span == NULL) {
735 err(oldsbfd, "Could not find span for %s\n",
736 oldsym->name);
737 DIE;
739 if (new_span == NULL) {
740 err(newsbfd, "Could not find span for %s\n",
741 newsym->name);
742 DIE;
744 fn(old_span, oldsym, new_span, newsym);
749 static void match_symbol_spans(struct span *old_span, asymbol *oldsym,
750 struct span *new_span, asymbol *newsym)
752 if ((oldsym->flags & BSF_DEBUGGING) != 0 ||
753 (newsym->flags & BSF_DEBUGGING) != 0)
754 return;
755 if (old_span->ss->type == SS_TYPE_SPECIAL)
756 return;
757 if (static_local_symbol(old_span->ss->parent, oldsym) ||
758 static_local_symbol(new_span->ss->parent, newsym))
759 return;
760 if (old_span->match == NULL && new_span->match == NULL)
761 match_spans(old_span, new_span);
764 static void match_spans_by_label(struct span *old_span, struct span *new_span)
766 if (old_span->ss->type == SS_TYPE_STRING ||
767 (is_table_section(old_span->ss->name, true, false) &&
768 !is_table_section(old_span->ss->name, false, false)))
769 return;
770 if (strcmp(old_span->label, new_span->label) == 0)
771 match_spans(old_span, new_span);
774 static void match_string_spans(struct span *old_span, struct span *new_span)
776 if (old_span->ss->type != SS_TYPE_STRING ||
777 strcmp(old_span->ss->name, new_span->ss->name) != 0)
778 return;
779 if (strcmp((char *)old_span->ss->contents.data + old_span->start,
780 (char *)new_span->ss->contents.data + new_span->start) == 0)
781 match_spans(old_span, new_span);
784 static void foreach_span_pair(struct superbfd *oldsbfd,
785 struct superbfd *newsbfd,
786 void (*fn)(struct span *old_span,
787 struct span *new_span))
789 asection *oldsect, *newsect;
790 struct supersect *oldss, *newss;
791 struct span *old_span, *new_span;
792 for (newsect = newsbfd->abfd->sections; newsect != NULL;
793 newsect = newsect->next) {
794 newss = fetch_supersect(newsbfd, newsect);
795 for (oldsect = oldsbfd->abfd->sections; oldsect != NULL;
796 oldsect = oldsect->next) {
797 oldss = fetch_supersect(oldsbfd, oldsect);
798 if (oldss->type != newss->type)
799 continue;
800 for (new_span = newss->spans.data;
801 new_span < newss->spans.data + newss->spans.size;
802 new_span++) {
803 for (old_span = oldss->spans.data;
804 old_span < oldss->spans.data +
805 oldss->spans.size; old_span++)
806 fn(old_span, new_span);
812 static void mark_new_spans(struct superbfd *sbfd)
814 asection *sect;
815 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
816 struct supersect *ss = fetch_supersect(sbfd, sect);
817 if (ss->type == SS_TYPE_SPECIAL || ss->type == SS_TYPE_IGNORED)
818 continue;
819 struct span *span;
820 for (span = ss->spans.data;
821 span < ss->spans.data + ss->spans.size; span++) {
822 if (span->match == NULL && !span->bugpatch)
823 span->new = true;
828 static void handle_deleted_spans(struct superbfd *oldsbfd,
829 struct superbfd *newsbfd)
831 asection *sect;
832 for (sect = oldsbfd->abfd->sections; sect != NULL; sect = sect->next) {
833 struct supersect *ss = fetch_supersect(oldsbfd, sect);
834 struct span *span;
835 for (span = ss->spans.data;
836 span < ss->spans.data + ss->spans.size; span++) {
837 if (span->match != NULL)
838 continue;
839 if (ss->type == SS_TYPE_EXPORT) {
840 *vec_grow(&delsects, 1) = span->label;
841 write_ksplice_export(newsbfd, span, true);
842 } else if (ss->type == SS_TYPE_TEXT) {
843 *vec_grow(&delsects, 1) = span->label;
844 if (span->symbol == NULL)
845 DIE;
846 write_ksplice_deleted_patch
847 (newsbfd, span->symbol->name, span->label,
848 span->ss->name);
854 static void handle_nonzero_offset_relocs(struct supersect *ss)
856 struct span *address_span, *target_span;
857 arelent **relocp;
858 for (relocp = ss->relocs.data;
859 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
860 arelent *reloc = *relocp;
861 address_span = find_span(ss, reloc->address);
862 if (!address_span->new && !address_span->patch)
863 continue;
865 asymbol *sym = *reloc->sym_ptr_ptr;
866 if (bfd_is_const_section(sym->section))
867 continue;
868 bfd_vma offset = get_reloc_offset(ss, reloc, true);
869 target_span = reloc_target_span(ss, reloc);
870 if (sym->value + offset == target_span->start)
871 continue;
873 if (target_span->ss->type != SS_TYPE_TEXT)
874 continue;
875 if (target_span->patch)
876 continue;
878 target_span->patch = true;
879 changed = true;
880 debug1(ss->parent, "Changing %s because a relocation from sect "
881 "%s has a nonzero offset %lx+%lx into it\n",
882 target_span->label, ss->name, (unsigned long)sym->value,
883 (unsigned long)offset);
887 static void update_nonzero_offsets(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 handle_nonzero_offset_relocs(ss);
898 static void unmatch_addr_spans(struct span *old_span, struct span *new_span,
899 const struct table_section *ts)
901 struct span *old_sym_span =
902 span_offset_target_span(old_span, ts->addr_offset);
903 struct span *new_sym_span =
904 span_offset_target_span(new_span, ts->addr_offset);
905 assert(old_sym_span != NULL && new_sym_span != NULL);
906 if (old_sym_span->match == new_sym_span &&
907 new_sym_span->match == old_sym_span &&
908 !(new_sym_span->patch && new_sym_span->ss->type == SS_TYPE_TEXT)) {
909 if (old_sym_span->ss->type == SS_TYPE_TEXT) {
910 debug1(new_span->ss->parent, "Patching %s due "
911 "to relocations from special section %s\n",
912 new_sym_span->label, new_span->label);
913 new_sym_span->patch = true;
914 } else {
915 debug1(new_span->ss->parent, "Unmatching %s and %s due "
916 "to relocations from special section %s/%s\n",
917 old_sym_span->label, new_sym_span->label,
918 old_span->label, new_span->label);
919 old_sym_span->match = NULL;
920 new_sym_span->match = NULL;
922 changed = true;
926 static void compare_spans(struct span *old_span, struct span *new_span)
928 struct superbfd *newsbfd = new_span->ss->parent;
930 bool nonrelocs_match = nonrelocs_equal(old_span, new_span);
931 bool relocs_match = all_relocs_equal(old_span, new_span);
932 if (nonrelocs_match && relocs_match) {
933 const struct table_section *ts =
934 get_table_section(old_span->ss->name);
935 if (ts != NULL && ts->crc_sect != NULL) {
936 struct span *old_crc_span = get_crc_span(old_span, ts);
937 struct span *new_crc_span = get_crc_span(new_span, ts);
938 assert(old_crc_span != NULL);
939 assert(new_crc_span != NULL);
940 if (old_crc_span->match != new_crc_span ||
941 new_crc_span->match != old_crc_span) {
942 debug1(newsbfd, "Unmatching %s and %s due to "
943 "nonmatching CRCs\n", old_span->label,
944 new_span->label);
945 old_span->match = NULL;
946 new_span->match = NULL;
949 return;
951 if (strcmp(old_span->ss->name, "__bug_table") == 0 &&
952 strcmp(new_span->ss->name, "__bug_table") == 0 && relocs_match) {
953 debug1(newsbfd, "Changing %s due to nonmatching line numbers\n",
954 new_span->label);
955 new_span->match = NULL;
956 old_span->match = NULL;
957 new_span->bugpatch = true;
958 return;
961 char *reason;
962 if (new_span->contents_size != old_span->contents_size)
963 reason = "differing sizes";
964 else if (!nonrelocs_match)
965 reason = "differing contents";
966 else
967 reason = "differing relocations";
969 if (new_span->ss->type == SS_TYPE_TEXT) {
970 if (new_span->patch)
971 return;
972 new_span->patch = true;
973 debug1(newsbfd, "Changing %s due to %s\n", new_span->label,
974 reason);
975 } else if (new_span->ss->type == SS_TYPE_RODATA &&
976 new_span->contents_size == old_span->contents_size) {
977 if (new_span->datapatch)
978 return;
979 new_span->datapatch = true;
980 debug1(newsbfd, "Changing %s in-place due to %s\n",
981 new_span->label, reason);
982 } else if (new_span->ss->type == SS_TYPE_STRING &&
983 old_span->ss->type == SS_TYPE_STRING && relocs_match &&
984 strcmp(new_span->ss->contents.data + new_span->start,
985 old_span->ss->contents.data + old_span->start) == 0) {
986 return;
987 } else {
988 debug1(newsbfd, "Unmatching %s and %s due to %s\n",
989 old_span->label, new_span->label, reason);
990 new_span->match = NULL;
991 old_span->match = NULL;
992 if (old_span->ss->type == SS_TYPE_SPECIAL) {
993 const struct table_section *ts =
994 get_table_section(old_span->ss->name);
995 if (ts != NULL && ts->has_addr)
996 unmatch_addr_spans(old_span, new_span, ts);
999 changed = true;
1000 if (unchangeable_section(new_span->ss))
1001 err(newsbfd, "warning: ignoring change to nonpatchable "
1002 "section %s\n", new_span->ss->name);
1005 static void compare_matched_spans(struct superbfd *newsbfd)
1007 asection *sect;
1008 for (sect = newsbfd->abfd->sections; sect != NULL; sect = sect->next) {
1009 struct supersect *ss = fetch_supersect(newsbfd, sect);
1010 struct span *span;
1011 for (span = ss->spans.data;
1012 span < ss->spans.data + ss->spans.size; span++) {
1013 if (span->match == NULL)
1014 continue;
1015 compare_spans(span->match, span);
1020 static void handle_section_symbol_renames(struct superbfd *oldsbfd,
1021 struct superbfd *newsbfd)
1023 asection *sect;
1024 struct span *span;
1025 for (sect = newsbfd->abfd->sections; sect != NULL; sect = sect->next) {
1026 struct supersect *ss = fetch_supersect(newsbfd, sect);
1027 for (span = ss->spans.data;
1028 span < ss->spans.data + ss->spans.size; span++) {
1029 if (span->match == NULL)
1030 continue;
1031 if (strcmp(span->label, span->match->label) == 0)
1032 continue;
1033 if (strcmp(span->orig_label, span->label) != 0 &&
1034 strcmp(span->label, span->match->label) != 0)
1035 DIE;
1036 if (span->symbol != NULL)
1037 label_map_set(newsbfd, span->label,
1038 span->match->label);
1039 span->label = span->match->label;
1044 static bool part_of_reloc(struct supersect *ss, unsigned long addr)
1046 arelent **relocp;
1047 for (relocp = ss->relocs.data;
1048 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
1049 arelent *reloc = *relocp;
1050 if (addr >= reloc->address &&
1051 addr < reloc->address + reloc->howto->size)
1052 return true;
1054 return false;
1057 static bool nonrelocs_equal(struct span *old_span, struct span *new_span)
1059 int i;
1060 struct supersect *old_ss = old_span->ss, *new_ss = new_span->ss;
1061 if (old_span->contents_size != new_span->contents_size)
1062 return false;
1063 const unsigned char *old = old_ss->contents.data + old_span->start;
1064 const unsigned char *new = new_ss->contents.data + new_span->start;
1065 for (i = 0; i < old_span->contents_size; i++) {
1066 if (old[i] != new[i] &&
1067 !(part_of_reloc(old_ss, i + old_span->start) &&
1068 part_of_reloc(new_ss, i + new_span->start)))
1069 return false;
1071 return true;
1074 bool relocs_equal(struct supersect *old_src_ss, struct supersect *new_src_ss,
1075 arelent *old_reloc, arelent *new_reloc)
1077 struct superbfd *oldsbfd = old_src_ss->parent;
1078 struct superbfd *newsbfd = new_src_ss->parent;
1079 struct span *old_addr_span = find_span(old_src_ss, old_reloc->address);
1080 struct span *new_addr_span = find_span(new_src_ss, new_reloc->address);
1082 if (old_reloc->address - old_addr_span->start !=
1083 new_reloc->address - new_addr_span->start) {
1084 debug1(newsbfd, "Section %s/%s has reloc address mismatch at "
1085 "%lx\n", old_src_ss->name, new_src_ss->name,
1086 (unsigned long)old_reloc->address);
1087 return false;
1090 if (old_reloc->howto != new_reloc->howto) {
1091 debug1(newsbfd, "Section %s/%s has howto type mismatch at "
1092 "%lx\n", old_src_ss->name, new_src_ss->name,
1093 (unsigned long)old_reloc->address);
1094 return false;
1097 if (non_dst_mask(old_src_ss, old_reloc) !=
1098 non_dst_mask(new_src_ss, new_reloc)) {
1099 debug1(newsbfd, "Section %s/%s has contents mismatch at %lx\n",
1100 old_src_ss->name, new_src_ss->name,
1101 (unsigned long)old_reloc->address);
1102 return false;
1105 asymbol *old_sym = *old_reloc->sym_ptr_ptr;
1106 asymbol *new_sym = *new_reloc->sym_ptr_ptr;
1107 asection *old_sect = old_sym->section;
1108 asection *new_sect = new_sym->section;
1110 bfd_vma old_offset = get_reloc_offset(old_src_ss, old_reloc, true);
1111 bfd_vma new_offset = get_reloc_offset(new_src_ss, new_reloc, true);
1113 if (bfd_is_und_section(old_sect) || bfd_is_und_section(new_sect)) {
1114 if (!bfd_is_und_section(new_sect) && old_offset != 0 &&
1115 fetch_supersect(newsbfd, new_sect)->type == SS_TYPE_TEXT)
1116 return false;
1118 if (!bfd_is_und_section(new_sect) && new_offset != 0 &&
1119 fetch_supersect(oldsbfd, old_sect)->type == SS_TYPE_TEXT)
1120 return false;
1122 return strcmp(old_sym->name, new_sym->name) == 0 &&
1123 old_offset == new_offset;
1126 if (bfd_is_abs_section(old_sect) && bfd_is_abs_section(new_sect)) {
1127 if (old_offset + old_sym->value == new_offset + new_sym->value)
1128 return true;
1129 debug1(newsbfd, "Differing relocations from %s/%s to ABS "
1130 "section: %lx/%lx\n", old_addr_span->label,
1131 new_addr_span->label,
1132 (unsigned long)(old_offset + old_sym->value),
1133 (unsigned long)(new_offset + new_sym->value));
1134 return false;
1137 if (bfd_is_const_section(old_sect) || bfd_is_const_section(new_sect))
1138 DIE;
1140 struct supersect *old_ss = fetch_supersect(oldsbfd, old_sect);
1141 struct supersect *new_ss = fetch_supersect(newsbfd, new_sect);
1142 struct span *old_span = reloc_target_span(old_src_ss, old_reloc);
1143 struct span *new_span = reloc_target_span(new_src_ss, new_reloc);
1145 if (old_span->match != new_span || new_span->match != old_span) {
1146 debug1(newsbfd, "Nonmatching relocs from %s to %s/%s\n",
1147 new_src_ss->name, old_span->label, new_span->label);
1148 return false;
1151 if (old_sym->value + old_offset - old_span->start !=
1152 new_sym->value + new_offset - new_span->start) {
1153 debug1(newsbfd, "Offsets to %s/%s differ between %s "
1154 "and %s: %lx+%lx/%lx+%lx\n", old_ss->name,
1155 new_ss->name, old_src_ss->name, new_src_ss->name,
1156 (unsigned long)old_sym->value, (unsigned long)old_offset,
1157 (unsigned long)new_sym->value,
1158 (unsigned long)new_offset);
1159 return false;
1162 if ((old_sym->value + old_offset - old_span->start != 0 ||
1163 new_sym->value + new_offset - new_span->start != 0) &&
1164 new_span->patch) {
1165 debug1(newsbfd, "Relocation from %s to nonzero offsets "
1166 "%lx+%lx/%lx+%lx in changed section %s\n",
1167 new_src_ss->name, (unsigned long)old_sym->value,
1168 (unsigned long)old_offset, (unsigned long)new_sym->value,
1169 (unsigned long)new_offset, new_sym->section->name);
1170 return false;
1172 return true;
1175 bool all_relocs_equal(struct span *old_span, struct span *new_span)
1177 struct supersect *old_ss = old_span->ss, *new_ss = new_span->ss;
1178 arelent **old_relocp, **new_relocp;
1180 for (old_relocp = old_ss->relocs.data;
1181 old_relocp < old_ss->relocs.data + old_ss->relocs.size;
1182 old_relocp++) {
1183 if (find_span(old_ss, (*old_relocp)->address) == old_span)
1184 break;
1187 for (new_relocp = new_ss->relocs.data;
1188 new_relocp < new_ss->relocs.data + new_ss->relocs.size;
1189 new_relocp++) {
1190 if (find_span(new_ss, (*new_relocp)->address) == new_span)
1191 break;
1194 for (; old_relocp < old_ss->relocs.data + old_ss->relocs.size &&
1195 find_span(old_ss, (*old_relocp)->address) == old_span &&
1196 new_relocp < new_ss->relocs.data + new_ss->relocs.size &&
1197 find_span(new_ss, (*new_relocp)->address) == new_span;
1198 old_relocp++, new_relocp++) {
1199 if (!relocs_equal(old_ss, new_ss, *old_relocp, *new_relocp))
1200 return false;
1203 if ((old_relocp < old_ss->relocs.data + old_ss->relocs.size &&
1204 find_span(old_ss, (*old_relocp)->address) == old_span) ||
1205 (new_relocp < new_ss->relocs.data + new_ss->relocs.size &&
1206 find_span(new_ss, (*new_relocp)->address) == new_span)) {
1207 debug1(new_ss->parent, "Different reloc count between %s and "
1208 "%s\n", old_span->label, new_span->label);
1209 return false;
1212 return true;
1215 bfd_vma non_dst_mask(struct supersect *ss, arelent *reloc)
1217 int bits = bfd_get_reloc_size(reloc->howto) * 8;
1218 void *address = ss->contents.data + reloc->address;
1219 bfd_vma x = bfd_get(bits, ss->parent->abfd, address);
1220 return x & ~reloc->howto->dst_mask;
1223 void rm_relocs(struct superbfd *isbfd)
1225 asection *p;
1226 for (p = isbfd->abfd->sections; p != NULL; p = p->next) {
1227 struct supersect *ss = fetch_supersect(isbfd, p);
1228 bool remove_relocs = ss->keep;
1230 if (mode("keep") && ss->type == SS_TYPE_SPECIAL)
1231 remove_relocs = false;
1233 if (ss->type == SS_TYPE_KSPLICE ||
1234 ss->type == SS_TYPE_KSPLICE_CALL)
1235 remove_relocs = false;
1236 if (mode("finalize") &&
1237 (starts_with(ss->name, ".ksplice_patches") ||
1238 starts_with(ss->name, ".ksplice_relocs")))
1239 remove_relocs = true;
1241 if (remove_relocs)
1242 rm_some_relocs(ss);
1246 void rm_some_relocs(struct supersect *ss)
1248 struct arelentp_vec orig_relocs;
1249 vec_move(&orig_relocs, &ss->relocs);
1251 arelent **relocp;
1252 for (relocp = orig_relocs.data;
1253 relocp < orig_relocs.data + orig_relocs.size; relocp++) {
1254 bool rm_reloc = false;
1255 asymbol *sym_ptr = *(*relocp)->sym_ptr_ptr;
1257 if (mode("rmsyms") && str_in_set(sym_ptr->name, &rmsyms) &&
1258 bfd_is_und_section(sym_ptr->section))
1259 rm_reloc = true;
1261 if (mode("keep"))
1262 rm_reloc = true;
1264 if (mode("keep-primary")) {
1265 if (bfd_is_const_section(sym_ptr->section)) {
1266 rm_reloc = false;
1267 } else {
1268 bfd_vma offset = get_reloc_offset(ss, *relocp,
1269 true);
1270 struct span *target_span =
1271 reloc_target_span(ss, *relocp);
1272 if (target_span->new ||
1273 (target_span->ss->type == SS_TYPE_TEXT &&
1274 sym_ptr->value + offset !=
1275 target_span->start))
1276 rm_reloc = false;
1279 const struct table_section *ts =
1280 get_table_section(ss->name);
1281 if (ts != NULL && ts->has_addr &&
1282 ((*relocp)->address % ts->entry_size ==
1283 ts->addr_offset ||
1284 (*relocp)->address % ts->entry_size ==
1285 ts->other_offset))
1286 rm_reloc = false;
1289 if (mode("finalize") && bfd_is_und_section(sym_ptr->section))
1290 rm_reloc = true;
1292 if (strcmp(sym_ptr->name, "mcount") == 0 &&
1293 bfd_is_und_section(sym_ptr->section))
1294 rm_reloc = false;
1296 if (!find_span(ss, (*relocp)->address)->keep)
1297 rm_reloc = false;
1299 if (rm_reloc)
1300 write_ksplice_reloc(ss, *relocp);
1301 else
1302 *vec_grow(&ss->relocs, 1) = *relocp;
1306 struct supersect *make_section(struct superbfd *sbfd, const char *fmt, ...)
1308 va_list ap;
1309 va_start(ap, fmt);
1310 char *name = vstrprintf(fmt, ap);
1311 va_end(ap);
1313 asection *sect = bfd_get_section_by_name(sbfd->abfd, name);
1314 if (sect != NULL)
1315 return fetch_supersect(sbfd, sect);
1316 else
1317 return new_supersect(sbfd, name);
1320 arelent *create_reloc(struct supersect *ss, const void *addr, asymbol **symp,
1321 bfd_vma offset)
1323 bfd_reloc_code_real_type code;
1324 switch (bfd_arch_bits_per_address(ss->parent->abfd)) {
1325 case 32:
1326 code = BFD_RELOC_32;
1327 break;
1328 case 64:
1329 code = BFD_RELOC_64;
1330 break;
1331 default:
1332 DIE;
1335 arelent *reloc = malloc(sizeof(*reloc));
1336 reloc->sym_ptr_ptr = symp;
1337 reloc->address = addr_offset(ss, addr);
1338 reloc->howto = bfd_reloc_type_lookup(ss->parent->abfd, code);
1339 reloc->addend = offset;
1340 return reloc;
1343 void write_reloc(struct supersect *ss, const void *addr, asymbol **symp,
1344 bfd_vma offset)
1346 *vec_grow(&ss->new_relocs, 1) = create_reloc(ss, addr, symp, offset);
1349 void write_string(struct supersect *ss, const char **addr, const char *fmt, ...)
1351 va_list ap;
1352 struct supersect *str_ss = make_section(ss->parent, ".ksplice_str");
1353 char *str;
1354 va_start(ap, fmt);
1355 int len = vasprintf(&str, fmt, ap);
1356 assert(len >= 0);
1357 va_end(ap);
1359 unsigned long *str_offp = ulong_hash_lookup(&ksplice_string_offset, str,
1360 FALSE);
1361 if (str_offp == NULL) {
1362 char *buf = sect_grow(str_ss, len + 1, char);
1363 memcpy(buf, str, len + 1);
1364 str_offp = ulong_hash_lookup(&ksplice_string_offset, str, TRUE);
1365 *str_offp = addr_offset(str_ss, buf);
1368 write_reloc(ss, addr, &str_ss->symbol, *str_offp);
1371 void lookup_system_map(struct addr_vec *addrs, const char *name, long offset)
1373 struct addr_vec *map_addrs =
1374 addr_vec_hash_lookup(&system_map, name, FALSE);
1375 if (map_addrs == NULL)
1376 return;
1378 unsigned long *addr, *map_addr;
1379 for (map_addr = map_addrs->data;
1380 map_addr < map_addrs->data + map_addrs->size; map_addr++) {
1381 for (addr = addrs->data; addr < addrs->data + addrs->size;
1382 addr++) {
1383 if (*addr == *map_addr + offset)
1384 break;
1386 if (addr < addrs->data + addrs->size)
1387 continue;
1388 *vec_grow(addrs, 1) = *map_addr + offset;
1392 void compute_system_map_array(struct superbfd *sbfd, struct addr_vec *addrs,
1393 asymbol *sym)
1395 if (bfd_is_abs_section(sym->section)) {
1396 *vec_grow(addrs, 1) = sym->value;
1397 } else if (bfd_is_und_section(sym->section)) {
1398 lookup_system_map(addrs, sym->name, 0);
1399 } else if (!bfd_is_const_section(sym->section)) {
1400 asymbol **gsymp;
1401 for (gsymp = sbfd->syms.data;
1402 gsymp < sbfd->syms.data + sbfd->syms.size; gsymp++) {
1403 asymbol *gsym = *gsymp;
1404 if ((gsym->flags & BSF_DEBUGGING) == 0 &&
1405 gsym->section == sym->section)
1406 lookup_system_map(addrs, gsym->name,
1407 sym->value - gsym->value);
1412 void write_ksplice_system_map(struct superbfd *sbfd, asymbol *sym,
1413 const char *label)
1415 bool *done = bool_hash_lookup(&system_map_written, label, TRUE);
1416 if (*done)
1417 return;
1418 *done = true;
1420 struct addr_vec addrs;
1421 vec_init(&addrs);
1423 compute_system_map_array(sbfd, &addrs, sym);
1424 if (addrs.size != 0) {
1425 struct supersect *smap_ss =
1426 make_section(sbfd, ".ksplice_system_map");
1427 struct ksplice_system_map *smap =
1428 sect_grow(smap_ss, 1, struct ksplice_system_map);
1429 write_string(smap_ss, &smap->label, "%s", label);
1431 struct supersect *array_ss = make_section(sbfd,
1432 ".ksplice_array");
1433 void *buf = sect_grow(array_ss, addrs.size,
1434 typeof(*addrs.data));
1435 memcpy(buf, addrs.data, addrs.size * sizeof(*addrs.data));
1436 smap->nr_candidates = addrs.size;
1437 write_reloc(smap_ss, &smap->candidates, &array_ss->symbol,
1438 addr_offset(array_ss, buf));
1440 vec_free(&addrs);
1443 void write_ksplice_symbol_backend(struct supersect *ss,
1444 struct ksplice_symbol *const *addr,
1445 asymbol *sym, const char *label,
1446 const char *name)
1448 struct supersect *ksymbol_ss = make_section(ss->parent,
1449 ".ksplice_symbols");
1450 struct ksplice_symbol *ksymbol;
1451 unsigned long *ksymbol_offp;
1453 ksymbol_offp = ulong_hash_lookup(&ksplice_symbol_offset, label, FALSE);
1454 if (ksymbol_offp != NULL) {
1455 write_reloc(ss, addr, &ksymbol_ss->symbol, *ksymbol_offp);
1456 return;
1458 ksymbol = sect_grow(ksymbol_ss, 1, struct ksplice_symbol);
1459 ksymbol_offp = ulong_hash_lookup(&ksplice_symbol_offset, label, TRUE);
1460 *ksymbol_offp = addr_offset(ksymbol_ss, ksymbol);
1462 write_reloc(ss, addr, &ksymbol_ss->symbol, *ksymbol_offp);
1463 write_string(ksymbol_ss, &ksymbol->label, "%s", label);
1464 if (name != NULL) {
1465 write_string(ksymbol_ss, &ksymbol->name, "%s", name);
1466 write_ksplice_system_map(ksymbol_ss->parent, sym, label);
1470 void write_ksplice_symbol(struct supersect *ss,
1471 struct ksplice_symbol *const *addr,
1472 asymbol *sym, struct span *span,
1473 const char *addstr_sect)
1475 const char *label, *name;
1476 if (span != NULL && span->start != 0)
1477 label = span->label;
1478 else
1479 label = label_lookup(ss->parent, sym);
1481 asymbol *gsym = canonical_symbol(ss->parent, sym);
1482 if (strcmp(addstr_sect, "") != 0)
1483 name = NULL;
1484 else if (bfd_is_und_section(sym->section))
1485 name = sym->name;
1486 else if (bfd_is_const_section(sym->section))
1487 name = NULL;
1488 else if (span != NULL && span->symbol == NULL)
1489 name = NULL;
1490 else if (gsym == NULL || (gsym->flags & BSF_SECTION_SYM) != 0)
1491 name = NULL;
1492 else
1493 name = gsym->name;
1495 write_ksplice_symbol_backend(ss, addr, sym,
1496 strprintf("%s%s", addstr_sect, label),
1497 name);
1500 void write_ksplice_reloc(struct supersect *ss, arelent *orig_reloc)
1502 asymbol *sym_ptr = *orig_reloc->sym_ptr_ptr;
1503 bfd_vma reloc_addend = get_reloc_offset(ss, orig_reloc, false);
1504 bfd_vma target_addend = get_reloc_offset(ss, orig_reloc, true);
1505 unsigned long *repladdr = ss->contents.data + orig_reloc->address;
1507 if (mode("finalize") && starts_with(ss->name, ".ksplice_patches")) {
1508 *repladdr = 0;
1509 return;
1511 if (mode("finalize") && starts_with(ss->name, ".ksplice_relocs")) {
1512 assert(starts_with(sym_ptr->name, KSPLICE_SYMBOL_STR));
1513 asymbol fake_sym;
1514 fake_sym.name = sym_ptr->name + strlen(KSPLICE_SYMBOL_STR);
1515 fake_sym.section = bfd_und_section_ptr;
1516 fake_sym.value = 0;
1517 fake_sym.flags = 0;
1519 write_ksplice_symbol_backend
1520 (ss, (struct ksplice_symbol **)repladdr, &fake_sym,
1521 fake_sym.name, fake_sym.name);
1522 return;
1525 struct span *span = reloc_target_span(ss, orig_reloc);
1526 if (span == ss->spans.data && span->start != target_addend)
1527 span = NULL;
1528 write_canary(ss, orig_reloc->address,
1529 bfd_get_reloc_size(orig_reloc->howto),
1530 orig_reloc->howto->dst_mask);
1532 struct supersect *kreloc_ss;
1533 if (mode("rmsyms"))
1534 kreloc_ss = make_section(ss->parent, ".ksplice_init_relocs");
1535 else
1536 kreloc_ss = make_section(ss->parent, ".ksplice_relocs%s",
1537 ss->name);
1538 struct ksplice_reloc *kreloc = sect_grow(kreloc_ss, 1,
1539 struct ksplice_reloc);
1541 struct span *address_span = find_span(ss, orig_reloc->address);
1542 write_reloc(kreloc_ss, &kreloc->blank_addr,
1543 &ss->symbol, orig_reloc->address + address_span->shift);
1544 if (bfd_is_und_section(sym_ptr->section) && mode("keep")) {
1545 char *name = strprintf(KSPLICE_SYMBOL_STR "%s", sym_ptr->name);
1546 asymbol **symp = make_undefined_symbolp(ss->parent, name);
1547 write_reloc(kreloc_ss, &kreloc->symbol, symp, 0);
1548 } else {
1549 write_ksplice_symbol(kreloc_ss, &kreloc->symbol, sym_ptr, span,
1550 "");
1552 if (span != NULL && span->start != 0) {
1553 reloc_addend += sym_ptr->value - span->start;
1554 target_addend += sym_ptr->value - span->start;
1556 kreloc->insn_addend = reloc_addend - target_addend;
1557 kreloc->target_addend = target_addend;
1558 write_ksplice_reloc_howto(kreloc_ss, &kreloc->howto, orig_reloc->howto,
1559 KSPLICE_HOWTO_RELOC);
1562 static void write_ksplice_reloc_howto(struct supersect *ss, const
1563 struct ksplice_reloc_howto *const *addr,
1564 reloc_howto_type *howto,
1565 enum ksplice_reloc_howto_type type)
1567 struct supersect *khowto_ss = make_section(ss->parent,
1568 ".ksplice_reloc_howtos");
1569 struct ksplice_reloc_howto *khowto;
1570 unsigned long *khowto_offp;
1572 khowto_offp = ulong_hash_lookup(&ksplice_howto_offset, howto->name,
1573 FALSE);
1574 if (khowto_offp != NULL) {
1575 write_reloc(ss, addr, &khowto_ss->symbol, *khowto_offp);
1576 return;
1578 khowto = sect_grow(khowto_ss, 1, struct ksplice_reloc_howto);
1579 khowto_offp = ulong_hash_lookup(&ksplice_howto_offset, howto->name,
1580 TRUE);
1581 *khowto_offp = addr_offset(khowto_ss, khowto);
1583 khowto->type = type;
1584 khowto->pcrel = howto->pc_relative;
1585 khowto->size = bfd_get_reloc_size(howto);
1586 khowto->dst_mask = howto->dst_mask;
1587 khowto->rightshift = howto->rightshift;
1588 khowto->signed_addend =
1589 (howto->complain_on_overflow == complain_overflow_signed) ||
1590 (howto->complain_on_overflow == complain_overflow_bitfield);
1591 write_reloc(ss, addr, &khowto_ss->symbol, *khowto_offp);
1594 #define CANARY(x, canary) ((x & ~howto->dst_mask) | (canary & howto->dst_mask))
1596 void write_canary(struct supersect *ss, int offset, bfd_size_type size,
1597 bfd_vma dst_mask)
1599 int bits = size * 8;
1600 void *address = ss->contents.data + offset;
1601 bfd_vma x = bfd_get(bits, ss->parent->abfd, address);
1602 x = (x & ~dst_mask) | ((bfd_vma)KSPLICE_CANARY & dst_mask);
1603 bfd_put(bits, ss->parent->abfd, x, address);
1606 static void write_date_relocs(struct superbfd *sbfd, const char *str,
1607 enum ksplice_reloc_howto_type type)
1609 asection *sect;
1610 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
1611 struct supersect *ss = fetch_supersect(sbfd, sect);
1612 if (ss->type != SS_TYPE_STRING && ss->type != SS_TYPE_RODATA)
1613 continue;
1614 void *ptr;
1615 struct span *span;
1616 for (span = ss->spans.data;
1617 span < ss->spans.data + ss->spans.size; span++) {
1618 if (!span->keep)
1619 continue;
1620 for (ptr = ss->contents.data + span->start;
1621 ptr + strlen(str) < ss->contents.data +
1622 span->start + span->contents_size; ptr++) {
1623 if (strcmp((const char *)ptr, str) == 0)
1624 write_ksplice_date_reloc
1625 (ss, addr_offset(ss, ptr), str,
1626 type);
1632 static void write_ksplice_date_reloc(struct supersect *ss, unsigned long offset,
1633 const char *str,
1634 enum ksplice_reloc_howto_type type)
1636 struct supersect *kreloc_ss;
1637 kreloc_ss = make_section(ss->parent, ".ksplice_relocs%s", ss->name);
1638 struct ksplice_reloc *kreloc = sect_grow(kreloc_ss, 1,
1639 struct ksplice_reloc);
1641 const char *filename = ss->parent->abfd->filename;
1642 char *c = strstr(filename, ".KSPLICE");
1643 int flen = (c == NULL ? strlen(filename) : c - filename);
1645 write_ksplice_symbol_backend(kreloc_ss, &kreloc->symbol, NULL,
1646 strprintf("%s<%.*s>", str, flen, filename),
1647 NULL);
1649 struct span *span = find_span(ss, offset);
1650 write_reloc(kreloc_ss, &kreloc->blank_addr, &ss->symbol,
1651 offset + span->shift);
1652 write_ksplice_nonreloc_howto(kreloc_ss, &kreloc->howto, type,
1653 strlen(str));
1656 static void write_table_relocs(struct superbfd *sbfd, const char *sectname,
1657 enum ksplice_reloc_howto_type type)
1659 asection *sect = bfd_get_section_by_name(sbfd->abfd, sectname);
1660 if (sect == NULL)
1661 return;
1662 struct supersect *ss = fetch_supersect(sbfd, sect);
1664 const struct table_section *s = get_table_section(sectname);
1665 if (s == NULL)
1666 DIE;
1668 void *entry;
1669 for (entry = ss->contents.data;
1670 entry < ss->contents.data + ss->contents.size;
1671 entry += s->entry_size) {
1672 struct span *span = find_span(ss, addr_offset(ss, entry));
1673 assert(span != NULL);
1674 if (!span->keep)
1675 continue;
1677 arelent *reloc = find_reloc(ss, entry + s->addr_offset);
1678 assert(reloc != NULL);
1679 asymbol *sym = *reloc->sym_ptr_ptr;
1680 assert(!bfd_is_const_section(sym->section));
1681 struct supersect *sym_ss = fetch_supersect(sbfd, sym->section);
1682 unsigned long addr = get_reloc_offset(ss, reloc, true) +
1683 sym->value;
1684 write_ksplice_table_reloc(sym_ss, addr, span->label, type);
1688 static void write_ksplice_table_reloc(struct supersect *ss,
1689 unsigned long address,
1690 const char *label,
1691 enum ksplice_reloc_howto_type type)
1693 struct supersect *kreloc_ss;
1694 kreloc_ss = make_section(ss->parent, ".ksplice_relocs%s", ss->name);
1695 struct ksplice_reloc *kreloc = sect_grow(kreloc_ss, 1,
1696 struct ksplice_reloc);
1697 struct span *span = find_span(ss, address);
1698 assert(span != NULL);
1700 write_ksplice_symbol_backend(kreloc_ss, &kreloc->symbol, NULL,
1701 label, NULL);
1702 write_reloc(kreloc_ss, &kreloc->blank_addr, &ss->symbol,
1703 address + span->shift);
1704 write_ksplice_nonreloc_howto(kreloc_ss, &kreloc->howto, type, 0);
1707 static void write_ksplice_nonreloc_howto(struct supersect *ss,
1708 const struct ksplice_reloc_howto
1709 *const *addr,
1710 enum ksplice_reloc_howto_type type,
1711 int size)
1713 struct supersect *khowto_ss =
1714 make_section(ss->parent, ".ksplice_reloc_howtos");
1715 struct ksplice_reloc_howto *khowto =
1716 sect_grow(khowto_ss, 1, struct ksplice_reloc_howto);
1718 khowto->type = type;
1719 khowto->size = size;
1720 khowto->pcrel = 0;
1721 khowto->dst_mask = 0;
1722 khowto->rightshift = 0;
1723 khowto->signed_addend = 0;
1724 write_reloc(ss, addr, &khowto_ss->symbol,
1725 addr_offset(khowto_ss, khowto));
1728 static void write_ksplice_section(struct span *span)
1730 struct supersect *ss = span->ss;
1731 const char *sectname = span->ss->name;
1732 const struct table_section *ts = get_table_section(ss->name);
1734 if (ts != NULL && ts->has_addr) {
1735 arelent *reloc = find_reloc(ss, ss->contents.data + span->start
1736 + ts->addr_offset);
1737 assert(reloc != NULL);
1738 asymbol *rsym = *reloc->sym_ptr_ptr;
1739 assert(!bfd_is_const_section(rsym->section));
1740 sectname = rsym->section->name;
1743 struct supersect *ksect_ss =
1744 make_section(ss->parent, ".ksplice_sections%s", sectname);
1745 struct ksplice_section *ksect = sect_grow(ksect_ss, 1,
1746 struct ksplice_section);
1747 asymbol *sym = span->symbol == NULL ? ss->symbol : span->symbol;
1749 write_ksplice_symbol(ksect_ss, &ksect->symbol, sym, span,
1750 mode("keep-primary") ? "(post)" : "");
1751 ksect->size = span->size;
1752 ksect->flags = 0;
1754 if (ss->type == SS_TYPE_RODATA || ss->type == SS_TYPE_STRING ||
1755 ss->type == SS_TYPE_EXPORT)
1756 ksect->flags |= KSPLICE_SECTION_RODATA;
1757 if (ss->type == SS_TYPE_DATA)
1758 ksect->flags |= KSPLICE_SECTION_DATA;
1759 if (ss->type == SS_TYPE_TEXT)
1760 ksect->flags |= KSPLICE_SECTION_TEXT;
1761 assert(ksect->flags != 0);
1763 if (ss->type == SS_TYPE_STRING)
1764 ksect->flags |= KSPLICE_SECTION_STRING;
1766 write_reloc(ksect_ss, &ksect->address, &ss->symbol,
1767 span->start + span->shift);
1770 static void write_ksplice_patch_reloc(struct supersect *ss,
1771 const char *sectname, unsigned long *addr,
1772 bfd_size_type size, const char *label,
1773 long addend)
1775 struct supersect *kreloc_ss;
1776 kreloc_ss = make_section(ss->parent, ".ksplice_relocs%s", sectname);
1777 struct ksplice_reloc *kreloc = sect_grow(kreloc_ss, 1,
1778 struct ksplice_reloc);
1780 write_canary(ss, addr_offset(ss, addr), size, -1);
1781 write_ksplice_symbol_backend(kreloc_ss, &kreloc->symbol, NULL,
1782 label, NULL);
1783 write_reloc(kreloc_ss, &kreloc->blank_addr, &ss->symbol,
1784 addr_offset(ss, addr));
1785 reloc_howto_type *howto =
1786 bfd_reloc_type_lookup(ss->parent->abfd,
1787 PASTE(BFD_RELOC_, LONG_BIT));
1788 write_ksplice_reloc_howto(kreloc_ss, &kreloc->howto, howto,
1789 KSPLICE_HOWTO_RELOC);
1790 kreloc->target_addend = addend;
1791 kreloc->insn_addend = 0;
1794 void write_ksplice_patch(struct superbfd *sbfd, struct span *span)
1796 struct supersect *kpatch_ss =
1797 make_section(sbfd, ".ksplice_patches%s", span->ss->name);
1798 struct ksplice_patch *kpatch = sect_grow(kpatch_ss, 1,
1799 struct ksplice_patch);
1801 write_ksplice_patch_reloc(kpatch_ss, span->ss->name, &kpatch->oldaddr,
1802 sizeof(kpatch->oldaddr), span->label, 0);
1803 if (span->ss->type == SS_TYPE_TEXT) {
1804 kpatch->type = KSPLICE_PATCH_TEXT;
1805 write_patch_storage(kpatch_ss, kpatch, MAX_TRAMPOLINE_SIZE,
1806 NULL);
1807 } else {
1808 kpatch->type = KSPLICE_PATCH_DATA;
1809 kpatch->size = span->contents_size;
1810 struct supersect *data_ss =
1811 make_section(sbfd, ".ksplice_patch_data");
1812 write_reloc(kpatch_ss, &kpatch->contents, &span->ss->symbol,
1813 span->start + span->shift);
1814 char *saved = sect_do_grow(data_ss, 1, span->contents_size, 1);
1815 write_reloc(kpatch_ss, &kpatch->saved, &data_ss->symbol,
1816 addr_offset(data_ss, saved));
1818 write_reloc(kpatch_ss, &kpatch->repladdr, &span->ss->symbol,
1819 span->start + span->shift);
1822 asymbol **make_undefined_symbolp(struct superbfd *sbfd, const char *name)
1824 asymbol **symp;
1825 for (symp = sbfd->syms.data; symp < sbfd->syms.data + sbfd->syms.size;
1826 symp++) {
1827 asymbol *sym = *symp;
1828 if (strcmp(name, sym->name) == 0 &&
1829 bfd_is_und_section(sym->section))
1830 return symp;
1832 asymbol ***sympp;
1833 for (sympp = sbfd->new_syms.data;
1834 sympp < sbfd->new_syms.data + sbfd->new_syms.size; sympp++) {
1835 asymbol **symp = *sympp;
1836 asymbol *sym = *symp;
1837 if (strcmp(name, sym->name) == 0 &&
1838 bfd_is_und_section(sym->section))
1839 return symp;
1842 symp = malloc(sizeof(*symp));
1843 *symp = bfd_make_empty_symbol(sbfd->abfd);
1844 asymbol *sym = *symp;
1845 sym->name = name;
1846 sym->section = bfd_und_section_ptr;
1847 sym->flags = 0;
1848 sym->value = 0;
1849 *vec_grow(&sbfd->new_syms, 1) = symp;
1850 return symp;
1853 void write_ksplice_deleted_patch(struct superbfd *sbfd, const char *name,
1854 const char *label, const char *sectname)
1856 struct supersect *kpatch_ss =
1857 make_section(sbfd, ".ksplice_patches%s", sectname);
1858 struct ksplice_patch *kpatch = sect_grow(kpatch_ss, 1,
1859 struct ksplice_patch);
1861 write_ksplice_patch_reloc(kpatch_ss, sectname, &kpatch->oldaddr,
1862 sizeof(kpatch->oldaddr), label, 0);
1863 kpatch->type = KSPLICE_PATCH_TEXT;
1864 asymbol **symp = make_undefined_symbolp(sbfd, strdup(name));
1865 write_reloc(kpatch_ss, &kpatch->repladdr, symp, 0);
1866 write_patch_storage(kpatch_ss, kpatch, MAX_TRAMPOLINE_SIZE, NULL);
1869 void write_ksplice_export(struct superbfd *sbfd, struct span *span, bool del)
1871 struct supersect *kpatch_ss = make_section(sbfd, ".ksplice_patches");
1872 struct ksplice_patch *kpatch = sect_grow(kpatch_ss, 1,
1873 struct ksplice_patch);
1874 struct supersect *data_ss;
1876 const struct table_section *ts = get_table_section(span->ss->name);
1877 assert(ts != NULL);
1878 const char **addr =
1879 span->ss->contents.data + span->start + ts->other_offset;
1880 const char *symname = read_string(span->ss, addr);
1882 char *oldname, *newname;
1883 if (del) {
1884 oldname = strprintf("%s:%s", span->ss->name, symname);
1885 newname = strprintf("DISABLED_%s_%s", symname, kid);
1886 } else {
1887 oldname = strprintf("%s:DISABLED_%s_%s", span->ss->name,
1888 symname, kid);
1889 newname = strprintf("%s", symname);
1890 write_string(span->ss, addr, "DISABLED_%s_%s", symname, kid);
1893 write_ksplice_patch_reloc(kpatch_ss, "", &kpatch->oldaddr,
1894 sizeof(kpatch->oldaddr), oldname,
1895 ts->other_offset);
1896 kpatch->type = KSPLICE_PATCH_EXPORT;
1897 const char **namep = write_patch_storage(kpatch_ss, kpatch,
1898 sizeof(newname), &data_ss);
1899 write_string(data_ss, namep, "%s", newname);
1902 void filter_table_sections(struct superbfd *isbfd)
1904 struct supersect *tables_ss =
1905 fetch_supersect(offsets_sbfd,
1906 bfd_get_section_by_name(offsets_sbfd->abfd,
1907 ".ksplice_table_sections"));
1908 const struct table_section *ts;
1909 for (ts = tables_ss->contents.data;
1910 (void *)ts < tables_ss->contents.data + tables_ss->contents.size;
1911 ts++) {
1912 struct table_section s = *ts;
1913 s.sect = read_string(tables_ss, &ts->sect);
1914 s.other_sect = read_string(tables_ss, &ts->other_sect);
1915 s.crc_sect = read_string(tables_ss, &ts->crc_sect);
1916 filter_table_section(isbfd, &s);
1920 void filter_table_section(struct superbfd *sbfd, const struct table_section *s)
1922 asection *isection = bfd_get_section_by_name(sbfd->abfd, s->sect);
1923 if (isection == NULL)
1924 return;
1925 struct supersect *ss = fetch_supersect(sbfd, isection);
1927 void *entry;
1928 for (entry = ss->contents.data;
1929 entry < ss->contents.data + ss->contents.size;
1930 entry += s->entry_size) {
1931 struct span *span = find_span(ss, addr_offset(ss, entry));
1932 assert(span != NULL);
1934 if (s->has_addr) {
1935 struct span *sym_span =
1936 span_offset_target_span(span, s->addr_offset);
1937 assert(sym_span != NULL);
1938 if (sym_span->keep)
1939 keep_span(span);
1942 if (s->other_sect != NULL) {
1943 struct span *sym_span =
1944 span_offset_target_span(span, s->other_offset);
1945 assert(sym_span != NULL);
1946 if (span->keep)
1947 keep_span(sym_span);
1950 if (s->crc_sect != NULL) {
1951 struct span *crc_span = get_crc_span(span, s);
1952 assert(crc_span != NULL);
1953 if (span->keep && mode("keep-primary"))
1954 keep_span(crc_span);
1959 static void match_table_spans(struct span *old_span, struct span *new_span)
1961 const struct table_section *ts = get_table_section(old_span->ss->name);
1963 if (strcmp(old_span->ss->name, new_span->ss->name) != 0)
1964 return;
1965 if (ts == NULL || old_span->ss->type != SS_TYPE_SPECIAL ||
1966 new_span->ss->type != SS_TYPE_SPECIAL)
1967 return;
1968 if (old_span->match != NULL || new_span->match != NULL)
1969 return;
1971 if (ts->has_addr) {
1972 void *old_entry = old_span->ss->contents.data + old_span->start;
1973 void *new_entry = new_span->ss->contents.data + new_span->start;
1974 arelent *old_reloc =
1975 find_reloc(old_span->ss, old_entry + ts->addr_offset);
1976 arelent *new_reloc =
1977 find_reloc(new_span->ss, new_entry + ts->addr_offset);
1978 assert(old_reloc != NULL && new_reloc != NULL);
1979 struct span *old_sym_span =
1980 reloc_target_span(old_span->ss, old_reloc);
1981 struct span *new_sym_span =
1982 reloc_target_span(new_span->ss, new_reloc);
1983 assert(old_sym_span != NULL && new_sym_span != NULL);
1984 if (old_sym_span->match == new_sym_span &&
1985 new_sym_span->match == old_sym_span &&
1986 old_reloc->address - old_sym_span->start ==
1987 new_reloc->address - new_sym_span->start)
1988 match_spans(old_span, new_span);
1992 static struct span *get_crc_span(struct span *span,
1993 const struct table_section *ts)
1995 void *entry = span->ss->contents.data + span->start;
1996 asection *crc_sect = bfd_get_section_by_name(span->ss->parent->abfd,
1997 ts->crc_sect);
1998 if (crc_sect == NULL)
1999 return NULL;
2000 struct supersect *crc_ss = fetch_supersect(span->ss->parent, crc_sect);
2001 if (crc_ss == NULL)
2002 return NULL;
2003 struct span *crc_span = find_span(crc_ss, addr_offset(span->ss, entry) /
2004 ts->entry_size * ts->crc_size);
2005 return crc_span;
2008 void mark_precallable_spans(struct superbfd *sbfd)
2010 asection *sect;
2011 struct supersect *ss, *sym_ss;
2012 struct span *address_span, *target_span;
2013 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2014 ss = fetch_supersect(sbfd, sect);
2015 arelent **relocp;
2016 if (ss->type == SS_TYPE_SPECIAL)
2017 continue;
2018 for (relocp = ss->relocs.data;
2019 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
2020 asymbol *sym = *(*relocp)->sym_ptr_ptr;
2021 address_span = find_span(ss, (*relocp)->address);
2022 if (!address_span->precallable)
2023 continue;
2024 target_span = reloc_target_span(ss, *relocp);
2025 if (target_span == NULL || target_span->keep)
2026 continue;
2027 sym_ss = fetch_supersect(sbfd, sym->section);
2028 if (sym_ss->type == SS_TYPE_IGNORED)
2029 continue;
2030 target_span->precallable = true;
2031 changed = true;
2036 void keep_referenced_sections(struct superbfd *sbfd)
2038 asection *sect;
2039 struct supersect *ss, *sym_ss;
2040 struct span *address_span, *target_span;
2041 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2042 ss = fetch_supersect(sbfd, sect);
2043 arelent **relocp;
2044 if (ss->type == SS_TYPE_SPECIAL)
2045 continue;
2046 for (relocp = ss->relocs.data;
2047 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
2048 asymbol *sym = *(*relocp)->sym_ptr_ptr;
2049 address_span = find_span(ss, (*relocp)->address);
2050 if (!address_span->keep)
2051 continue;
2052 target_span = reloc_target_span(ss, *relocp);
2053 if (target_span == NULL || target_span->keep)
2054 continue;
2055 sym_ss = fetch_supersect(sbfd, sym->section);
2056 if (sym_ss->type == SS_TYPE_IGNORED)
2057 continue;
2058 keep_span(target_span);
2059 changed = true;
2064 void copy_symbols(struct asymbolp_vec *osyms, struct asymbolpp_vec *isyms)
2066 asymbol ***sympp;
2067 for (sympp = isyms->data; sympp < isyms->data + isyms->size; sympp++)
2068 *vec_grow(osyms, 1) = **sympp;
2071 /* Modified function from GNU Binutils objcopy.c */
2072 bfd_boolean copy_object(bfd *ibfd, bfd *obfd)
2074 assert(bfd_set_format(obfd, bfd_get_format(ibfd)));
2076 bfd_vma start = bfd_get_start_address(ibfd);
2078 flagword flags = bfd_get_file_flags(ibfd);
2079 flags &= bfd_applicable_file_flags(obfd);
2081 assert(bfd_set_start_address(obfd, start)
2082 && bfd_set_file_flags(obfd, flags));
2084 enum bfd_architecture iarch = bfd_get_arch(ibfd);
2085 unsigned int imach = bfd_get_mach(ibfd);
2086 assert(bfd_set_arch_mach(obfd, iarch, imach));
2087 assert(bfd_set_format(obfd, bfd_get_format(ibfd)));
2089 /* BFD mandates that all output sections be created and sizes set before
2090 any output is done. Thus, we traverse all sections multiple times. */
2091 bfd_map_over_sections(ibfd, setup_section, obfd);
2093 struct supersect *new_supersects = fetch_superbfd(ibfd)->new_supersects;
2094 struct supersect *ss;
2095 for (ss = new_supersects; ss != NULL; ss = ss->next)
2096 setup_new_section(obfd, ss);
2098 /* Mark symbols used in output relocations so that they
2099 are kept, even if they are local labels or static symbols.
2101 Note we iterate over the input sections examining their
2102 relocations since the relocations for the output sections
2103 haven't been set yet. mark_symbols_used_in_relocations will
2104 ignore input sections which have no corresponding output
2105 section. */
2107 bfd_map_over_sections(ibfd, mark_symbols_used_in_relocations, NULL);
2108 for (ss = new_supersects; ss != NULL; ss = ss->next)
2109 ss_mark_symbols_used_in_relocations(ss);
2110 struct asymbolp_vec osyms;
2111 vec_init(&osyms);
2112 filter_symbols(ibfd, obfd, &osyms, &fetch_superbfd(ibfd)->syms);
2113 copy_symbols(&osyms, &fetch_superbfd(ibfd)->new_syms);
2115 bfd_set_symtab(obfd, osyms.data, osyms.size);
2117 /* This has to happen after the symbol table has been set. */
2118 bfd_map_over_sections(obfd, write_section, NULL);
2120 /* Allow the BFD backend to copy any private data it understands
2121 from the input BFD to the output BFD. This is done last to
2122 permit the routine to look at the filtered symbol table, which is
2123 important for the ECOFF code at least. */
2124 assert(bfd_copy_private_bfd_data(ibfd, obfd));
2126 return TRUE;
2129 /* Modified function from GNU Binutils objcopy.c */
2130 void setup_section(bfd *ibfd, asection *isection, void *obfdarg)
2132 struct superbfd *isbfd = fetch_superbfd(ibfd);
2133 struct supersect *ss = fetch_supersect(isbfd, isection);
2134 bfd *obfd = obfdarg;
2135 bfd_vma vma;
2137 if (!ss->keep)
2138 return;
2140 asection *osection = bfd_make_section_anyway(obfd, ss->name);
2141 assert(osection != NULL);
2143 osection->userdata = ss;
2144 bfd_set_section_flags(obfd, osection, ss->flags);
2145 ss->symbol = osection->symbol;
2146 assert(bfd_set_section_size(obfd, osection, ss->contents.size));
2148 vma = bfd_section_vma(ibfd, isection);
2149 assert(bfd_set_section_vma(obfd, osection, vma));
2151 osection->lma = isection->lma;
2152 assert(bfd_set_section_alignment(obfd, osection, ss->alignment));
2153 osection->entsize = ss->entsize;
2154 osection->output_section = osection;
2155 osection->output_offset = 0;
2156 isection->output_section = osection;
2157 isection->output_offset = 0;
2158 return;
2161 void setup_new_section(bfd *obfd, struct supersect *ss)
2163 asection *osection = bfd_make_section_anyway(obfd, ss->name);
2164 assert(osection != NULL);
2165 bfd_set_section_flags(obfd, osection, ss->flags);
2167 osection->userdata = ss;
2168 ss->symbol = osection->symbol;
2169 assert(bfd_set_section_size(obfd, osection, ss->contents.size));
2170 assert(bfd_set_section_vma(obfd, osection, 0));
2172 osection->lma = 0;
2173 assert(bfd_set_section_alignment(obfd, osection, ss->alignment));
2174 osection->entsize = ss->entsize;
2175 osection->output_section = osection;
2176 osection->output_offset = 0;
2179 static int compare_reloc_addresses(const void *aptr, const void *bptr)
2181 const arelent *const *a = aptr, *const *b = bptr;
2182 return (*a)->address - (*b)->address;
2185 static void delete_obsolete_relocs(struct supersect *ss)
2187 if (ss->new_relocs.size == 0)
2188 return;
2190 qsort(ss->relocs.data, ss->relocs.size, sizeof(*ss->relocs.data),
2191 compare_reloc_addresses);
2192 qsort(ss->new_relocs.data, ss->new_relocs.size,
2193 sizeof(*ss->new_relocs.data), compare_reloc_addresses);
2195 struct arelentp_vec orig_relocs;
2196 vec_move(&orig_relocs, &ss->relocs);
2198 arelent **relocp, **new_relocp = ss->new_relocs.data;
2199 for (relocp = orig_relocs.data;
2200 relocp < orig_relocs.data + orig_relocs.size; relocp++) {
2201 while (new_relocp < ss->new_relocs.data + ss->new_relocs.size &&
2202 (*new_relocp)->address < (*relocp)->address)
2203 new_relocp++;
2204 arelent *reloc = *relocp, *new_reloc = *new_relocp;
2205 if (new_relocp == ss->new_relocs.data + ss->new_relocs.size ||
2206 reloc->address != new_reloc->address)
2207 *vec_grow(&ss->relocs, 1) = reloc;
2211 void write_section(bfd *obfd, asection *osection, void *arg)
2213 struct supersect *ss = osection->userdata;
2215 if ((ss->flags & SEC_GROUP) != 0 || ss->contents.size == 0)
2216 return;
2218 delete_obsolete_relocs(ss);
2220 arelent **relocp;
2221 char *error_message;
2222 for (relocp = ss->new_relocs.data;
2223 relocp < ss->new_relocs.data + ss->new_relocs.size; relocp++) {
2224 bfd_vma val;
2225 if (bfd_get_arch(obfd) == bfd_arch_arm)
2226 val = osection->use_rela_p ? 0 : (*relocp)->addend;
2227 else
2228 val = 0;
2229 bfd_put(bfd_get_reloc_size((*relocp)->howto) * 8, obfd, val,
2230 ss->contents.data + (*relocp)->address);
2231 if (bfd_install_relocation(obfd, *relocp, ss->contents.data,
2232 0, osection, &error_message) !=
2233 bfd_reloc_ok) {
2234 err(ss->parent, "ksplice: error installing reloc: %s",
2235 error_message);
2236 DIE;
2239 memcpy(vec_grow(&ss->relocs, ss->new_relocs.size), ss->new_relocs.data,
2240 ss->new_relocs.size * sizeof(*ss->new_relocs.data));
2242 bfd_set_reloc(obfd, osection,
2243 ss->relocs.size == 0 ? NULL : ss->relocs.data,
2244 ss->relocs.size);
2246 if (ss->flags & SEC_HAS_CONTENTS)
2247 assert(bfd_set_section_contents
2248 (obfd, osection, ss->contents.data, 0,
2249 ss->contents.size));
2252 /* Modified function from GNU Binutils objcopy.c
2254 * Mark all the symbols which will be used in output relocations with
2255 * the BSF_KEEP flag so that those symbols will not be stripped.
2257 * Ignore relocations which will not appear in the output file.
2259 void mark_symbols_used_in_relocations(bfd *abfd, asection *isection,
2260 void *ignored)
2262 struct superbfd *sbfd = fetch_superbfd(abfd);
2263 if (isection->output_section == NULL)
2264 return;
2266 struct supersect *ss = fetch_supersect(sbfd, isection);
2267 ss_mark_symbols_used_in_relocations(ss);
2270 void ss_mark_symbols_used_in_relocations(struct supersect *ss)
2272 /* Examine each symbol used in a relocation. If it's not one of the
2273 special bfd section symbols, then mark it with BSF_KEEP. */
2274 arelent **relocp;
2275 for (relocp = ss->relocs.data;
2276 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
2277 asymbol *sym = *(*relocp)->sym_ptr_ptr;
2278 if (!(bfd_is_const_section(sym->section) &&
2279 sym == sym->section->symbol))
2280 sym->flags |= BSF_KEEP;
2282 for (relocp = ss->new_relocs.data;
2283 relocp < ss->new_relocs.data + ss->new_relocs.size; relocp++) {
2284 asymbol *sym = *(*relocp)->sym_ptr_ptr;
2285 if (!(bfd_is_const_section(sym->section) &&
2286 sym == sym->section->symbol))
2287 sym->flags |= BSF_KEEP;
2291 static bool deleted_table_section_symbol(bfd *abfd, asymbol *sym)
2293 struct superbfd *sbfd = fetch_superbfd(abfd);
2294 if (bfd_is_const_section(sym->section))
2295 return false;
2296 struct supersect *ss = fetch_supersect(sbfd, sym->section);
2298 asymbol **symp;
2299 for (symp = ss->syms.data; symp < ss->syms.data + ss->syms.size; symp++) {
2300 if (sym == *symp)
2301 break;
2303 return symp >= ss->syms.data + ss->syms.size &&
2304 (sym->flags & BSF_SECTION_SYM) == 0;
2307 void filter_symbols(bfd *ibfd, bfd *obfd, struct asymbolp_vec *osyms,
2308 struct asymbolp_vec *isyms)
2310 asymbol **symp;
2311 struct superbfd *sbfd = fetch_superbfd(ibfd);
2312 for (symp = isyms->data; symp < isyms->data + isyms->size; symp++) {
2313 asymbol *sym = *symp;
2314 struct supersect *sym_ss = NULL;
2315 struct span *sym_span = NULL;
2316 if (!bfd_is_const_section(sym->section)) {
2317 sym_ss = fetch_supersect(sbfd, sym->section);
2318 sym_span = find_span(sym_ss, sym->value);
2321 if (mode("keep") && (sym->flags & BSF_GLOBAL) != 0 &&
2322 !(mode("keep-primary") && sym_span != NULL &&
2323 sym_span->new))
2324 sym->flags = (sym->flags & ~BSF_GLOBAL) | BSF_LOCAL;
2326 if (mode("finalize") && (sym->flags & BSF_GLOBAL) != 0)
2327 sym->flags = (sym->flags & ~BSF_GLOBAL) | BSF_LOCAL;
2329 bool keep = bfd_is_const_section(sym->section) ||
2330 (sym_ss->keep && (sym->flags & BSF_SECTION_SYM) != 0) ||
2331 (sym_span != NULL && sym_span->keep);
2332 if (bfd_is_und_section(sym->section) &&
2333 (sym->flags & BSF_KEEP) == 0)
2334 keep = false;
2335 if (bfd_is_abs_section(sym->section) &&
2336 (sym->flags & BSF_KEEP) == 0 &&
2337 (sym->flags & BSF_FILE) == 0)
2338 keep = false;
2339 if (deleted_table_section_symbol(ibfd, sym))
2340 keep = false;
2342 if (mode("keep-helper") && sym_ss != NULL &&
2343 sym_ss->type == SS_TYPE_EXPORT)
2344 keep = false;
2346 if (keep) {
2347 if (sym_ss != NULL && !sym_ss->keep) {
2348 err(sbfd, "Kept symbol %s in unkept section "
2349 "%s\n", sym->name, sym->section->name);
2350 DIE;
2352 *vec_grow(osyms, 1) = sym;
2357 void read_str_set(struct str_vec *strs)
2359 char *buf = NULL;
2360 size_t n = 0;
2361 assert(getline(&buf, &n, stdin) >= 0);
2362 vec_init(strs);
2363 char *saveptr;
2364 while (1) {
2365 char *str = strtok_r(buf, " \n", &saveptr);
2366 buf = NULL;
2367 if (str == NULL)
2368 break;
2369 *vec_grow(strs, 1) = str;
2373 bool str_in_set(const char *str, const struct str_vec *strs)
2375 const char **strp;
2376 for (strp = strs->data; strp < strs->data + strs->size; strp++) {
2377 if (strcmp(str, *strp) == 0)
2378 return true;
2380 return false;
2383 static bool is_table_section(const char *name, bool consider_other,
2384 bool consider_crc)
2386 struct supersect *tables_ss =
2387 fetch_supersect(offsets_sbfd,
2388 bfd_get_section_by_name(offsets_sbfd->abfd,
2389 ".ksplice_table_sections"));
2390 const struct table_section *ts;
2391 for (ts = tables_ss->contents.data;
2392 (void *)ts < tables_ss->contents.data + tables_ss->contents.size;
2393 ts++) {
2394 if (strcmp(name, read_string(tables_ss, &ts->sect)) == 0)
2395 return true;
2396 const char *osect_name = read_string(tables_ss,
2397 &ts->other_sect);
2398 if (consider_other && osect_name != NULL &&
2399 strcmp(name, osect_name) == 0)
2400 return true;
2401 const char *crc_name = read_string(tables_ss, &ts->crc_sect);
2402 if (consider_crc && crc_name != NULL &&
2403 strcmp(name, crc_name) == 0)
2404 return true;
2406 return false;
2409 const struct table_section *get_table_section(const char *name)
2411 struct supersect *tables_ss =
2412 fetch_supersect(offsets_sbfd,
2413 bfd_get_section_by_name(offsets_sbfd->abfd,
2414 ".ksplice_table_sections"));
2415 const struct table_section *ts;
2416 for (ts = tables_ss->contents.data;
2417 (void *)ts < tables_ss->contents.data + tables_ss->contents.size;
2418 ts++) {
2419 if (strcmp(name, read_string(tables_ss, &ts->sect)) == 0) {
2420 if (ts->entry_contents_size != 0)
2421 assert(align(ts->entry_contents_size,
2422 ts->entry_align) ==
2423 ts->entry_size);
2424 struct table_section *ns = malloc(sizeof(*ns));
2425 *ns = *ts;
2426 ns->sect = read_string(tables_ss, &ts->sect);
2427 ns->crc_sect = read_string(tables_ss, &ts->crc_sect);
2428 ns->other_sect =
2429 read_string(tables_ss, &ts->other_sect);
2430 return ns;
2433 return NULL;
2436 enum supersect_type supersect_type(struct supersect *ss)
2438 if (mode("finalize") &&
2439 strcmp(finalize_target, "vmlinux") == 0 &&
2440 (starts_with(ss->name, ".ksplice_relocs.exit") ||
2441 starts_with(ss->name, ".ksplice_sections.exit") ||
2442 starts_with(ss->name, ".ksplice_patches.exit")))
2443 return SS_TYPE_EXIT;
2444 if (starts_with(ss->name, ".ksplice_call"))
2445 return SS_TYPE_KSPLICE_CALL;
2446 if (starts_with(ss->name, ".ksplice_options"))
2447 return SS_TYPE_SPECIAL;
2448 if (starts_with(ss->name, ".ksplice"))
2449 return SS_TYPE_KSPLICE;
2451 if (starts_with(ss->name, ".init"))
2452 return SS_TYPE_IGNORED;
2453 if (starts_with(ss->name, ".security_initcall.init"))
2454 return SS_TYPE_IGNORED;
2455 if (starts_with(ss->name, ".con_initcall.init"))
2456 return SS_TYPE_IGNORED;
2457 if (starts_with(ss->name, ".x86cpuvendor.init"))
2458 return SS_TYPE_IGNORED;
2459 if (starts_with(ss->name, ".early_param.init"))
2460 return SS_TYPE_IGNORED;
2461 if (starts_with(ss->name, ".taglist.init"))
2462 return SS_TYPE_IGNORED;
2463 if (starts_with(ss->name, ".arch.info.init"))
2464 return SS_TYPE_IGNORED;
2465 if (starts_with(ss->name, ".proc.info.init"))
2466 return SS_TYPE_IGNORED;
2467 /* .pci_fixup_* sections really should be treated as global rodata
2468 referenced only from quirks.c */
2469 if (starts_with(ss->name, ".pci_fixup_"))
2470 return SS_TYPE_IGNORED;
2471 /* .builtin_fw sections are similar to .pci_fixup */
2472 if (starts_with(ss->name, ".builtin_fw"))
2473 return SS_TYPE_IGNORED;
2474 /* same for .tracedata */
2475 if (starts_with(ss->name, ".tracedata"))
2476 return SS_TYPE_IGNORED;
2477 if (starts_with(ss->name, ".debug"))
2478 return SS_TYPE_IGNORED;
2479 /* .eh_frame should probably be discarded, not ignored */
2480 if (starts_with(ss->name, ".eh_frame"))
2481 return SS_TYPE_IGNORED;
2482 if (config->ignore_devinit && starts_with(ss->name, ".devinit"))
2483 return SS_TYPE_IGNORED;
2484 if (config->ignore_meminit && starts_with(ss->name, ".meminit"))
2485 return SS_TYPE_IGNORED;
2486 if (config->ignore_cpuinit && starts_with(ss->name, ".cpuinit"))
2487 return SS_TYPE_IGNORED;
2488 if (config->ignore_devinit && starts_with(ss->name, ".devexit"))
2489 return SS_TYPE_IGNORED;
2490 if (config->ignore_meminit && starts_with(ss->name, ".memexit"))
2491 return SS_TYPE_IGNORED;
2492 if (config->ignore_cpuinit && starts_with(ss->name, ".cpuexit"))
2493 return SS_TYPE_IGNORED;
2494 if (starts_with(ss->name, ".vgetcpu_mode") ||
2495 starts_with(ss->name, ".jiffies") ||
2496 starts_with(ss->name, ".wall_jiffies") ||
2497 starts_with(ss->name, ".vxtime") ||
2498 starts_with(ss->name, ".sys_tz") ||
2499 starts_with(ss->name, ".sysctl_vsyscall") ||
2500 starts_with(ss->name, ".xtime") ||
2501 starts_with(ss->name, ".xtime_lock") ||
2502 starts_with(ss->name, ".vsyscall"))
2503 return SS_TYPE_IGNORED;
2504 if (starts_with(ss->name, ".vdso"))
2505 return SS_TYPE_IGNORED;
2507 if (starts_with(ss->name, ".exit.text"))
2508 return SS_TYPE_TEXT;
2509 if (starts_with(ss->name, ".exit.data"))
2510 return SS_TYPE_DATA;
2512 if (starts_with(ss->name, ".text") ||
2513 starts_with(ss->name, ".kernel.text") ||
2514 starts_with(ss->name, ".devinit.text") ||
2515 starts_with(ss->name, ".meminit.text") ||
2516 starts_with(ss->name, ".cpuinit.text") ||
2517 starts_with(ss->name, ".devexit.text") ||
2518 starts_with(ss->name, ".memexit.text") ||
2519 starts_with(ss->name, ".cpuexit.text") ||
2520 starts_with(ss->name, ".ref.text") ||
2521 starts_with(ss->name, ".spinlock.text") ||
2522 starts_with(ss->name, ".kprobes.text") ||
2523 starts_with(ss->name, ".sched.text") ||
2524 (mode("keep-helper") && starts_with(ss->name, ".fixup")))
2525 return SS_TYPE_TEXT;
2527 int n = -1;
2528 if (sscanf(ss->name, ".rodata.str%*u.%*u%n", &n) >= 0 &&
2529 n == strlen(ss->name))
2530 return ss->entsize == 1 ? SS_TYPE_STRING : SS_TYPE_RODATA;
2532 if (starts_with(ss->name, ".rodata") ||
2533 starts_with(ss->name, ".kernel.rodata") ||
2534 starts_with(ss->name, ".devinit.rodata") ||
2535 starts_with(ss->name, ".meminit.rodata") ||
2536 starts_with(ss->name, ".cpuinit.rodata") ||
2537 starts_with(ss->name, ".devexit.rodata") ||
2538 starts_with(ss->name, ".memexit.rodata") ||
2539 starts_with(ss->name, ".cpuexit.rodata") ||
2540 starts_with(ss->name, ".ref.rodata") ||
2541 starts_with(ss->name, "__markers_strings") ||
2542 starts_with(ss->name, "__bug_table") ||
2543 (mode("keep-helper") && starts_with(ss->name, "__ex_table")))
2544 return SS_TYPE_RODATA;
2546 if (starts_with(ss->name, ".bss"))
2547 return SS_TYPE_DATA;
2549 /* Ignore .data.percpu sections */
2550 if (starts_with(ss->name, ".data.percpu") ||
2551 starts_with(ss->name, ".kernel.data.percpu"))
2552 return SS_TYPE_IGNORED;
2553 if (starts_with(ss->name, ".data") ||
2554 starts_with(ss->name, ".kernel.data") ||
2555 starts_with(ss->name, ".devinit.data") ||
2556 starts_with(ss->name, ".cpuinit.data") ||
2557 starts_with(ss->name, ".meminit.data") ||
2558 starts_with(ss->name, ".devexit.data") ||
2559 starts_with(ss->name, ".memexit.data") ||
2560 starts_with(ss->name, ".cpuexit.data") ||
2561 starts_with(ss->name, ".ref.data") ||
2562 starts_with(ss->name, "__markers"))
2563 return SS_TYPE_DATA;
2565 /* We replace all the ksymtab strings, so delete them */
2566 if (strcmp(ss->name, "__ksymtab_strings") == 0)
2567 return SS_TYPE_STRING;
2568 if (starts_with(ss->name, "__ksymtab"))
2569 return SS_TYPE_EXPORT;
2571 if (is_table_section(ss->name, true, true))
2572 return SS_TYPE_SPECIAL;
2574 if (starts_with(ss->name, ".ARM."))
2575 return SS_TYPE_SPECIAL;
2577 if (starts_with(ss->name, ".note"))
2578 return SS_TYPE_IGNORED;
2579 if (starts_with(ss->name, ".comment"))
2580 return SS_TYPE_IGNORED;
2581 if (starts_with(ss->name, "__param"))
2582 return SS_TYPE_IGNORED;
2583 if (starts_with(ss->name, ".exitcall.exit"))
2584 return SS_TYPE_IGNORED;
2585 if (starts_with(ss->name, ".modinfo"))
2586 return SS_TYPE_IGNORED;
2588 return SS_TYPE_UNKNOWN;
2591 void initialize_supersect_types(struct superbfd *sbfd)
2593 asection *sect;
2594 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2595 struct supersect *ss = fetch_supersect(sbfd, sect);
2596 ss->type = supersect_type(ss);
2597 ss->orig_type = ss->type;
2598 if (ss->type == SS_TYPE_UNKNOWN) {
2599 err(sbfd, "Unknown section type: %s\n", ss->name);
2600 DIE;
2605 static void init_label_map(struct superbfd *sbfd)
2607 struct label_map *map;
2609 vec_init(&sbfd->maps);
2610 init_csyms(sbfd);
2611 init_callers(sbfd);
2613 struct symbol_hash csyms;
2614 symbol_hash_init(&csyms);
2616 asymbol **symp;
2617 for (symp = sbfd->syms.data;
2618 symp < sbfd->syms.data + sbfd->syms.size; symp++) {
2619 asymbol *csym = canonical_symbol(sbfd, *symp);
2620 if (csym == NULL)
2621 continue;
2622 char *key = strprintf("%p", csym);
2623 asymbol **csymp = symbol_hash_lookup(&csyms, key, TRUE);
2624 free(key);
2625 if (*csymp != NULL)
2626 continue;
2627 *csymp = csym;
2629 map = vec_grow(&sbfd->maps, 1);
2630 map->csym = csym;
2631 map->count = 0;
2632 map->label = symbol_label(sbfd, csym);
2635 struct label_mapp_hash label_maps;
2636 label_mapp_hash_init(&label_maps);
2637 for (map = sbfd->maps.data;
2638 map < sbfd->maps.data + sbfd->maps.size; map++) {
2639 struct label_map **mapp =
2640 label_mapp_hash_lookup(&label_maps, map->label, TRUE);
2641 if (*mapp == NULL) {
2642 *mapp = map;
2643 continue;
2646 struct label_map *first_map = *mapp;
2647 if (first_map->count == 0)
2648 first_map->label = strprintf("%s~%d", map->label, 0);
2649 map->label = strprintf("%s~%d", map->label, ++first_map->count);
2652 label_mapp_hash_init(&sbfd->maps_hash);
2653 for (map = sbfd->maps.data;
2654 map < sbfd->maps.data + sbfd->maps.size; map++) {
2655 char *key = strprintf("%p", map->csym);
2656 struct label_map **mapp =
2657 label_mapp_hash_lookup(&sbfd->maps_hash, key, TRUE);
2658 free(key);
2659 *mapp = map;
2660 map->orig_label = map->label;
2664 static const char *label_lookup(struct superbfd *sbfd, asymbol *sym)
2666 asymbol *csym = canonical_symbol(sbfd, sym);
2667 char *key = strprintf("%p", csym);
2668 struct label_map **mapp =
2669 label_mapp_hash_lookup(&sbfd->maps_hash, key, FALSE);
2670 free(key);
2671 if (mapp == NULL)
2672 DIE;
2673 return (*mapp)->label;
2676 static void print_label_changes(struct superbfd *sbfd)
2678 asection *sect;
2679 struct span *span;
2680 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2681 struct supersect *ss = fetch_supersect(sbfd, sect);
2682 for (span = ss->spans.data;
2683 span < ss->spans.data + ss->spans.size; span++) {
2684 if (strcmp(span->label, span->orig_label) != 0)
2685 debug1(sbfd, "Label change: %s -> %s\n",
2686 span->label, span->orig_label);
2691 static void label_map_set(struct superbfd *sbfd, const char *oldlabel,
2692 const char *label)
2694 struct label_map *map;
2695 for (map = sbfd->maps.data;
2696 map < sbfd->maps.data + sbfd->maps.size; map++) {
2697 if (strcmp(map->orig_label, oldlabel) == 0) {
2698 if (strcmp(map->orig_label, map->label) != 0 &&
2699 strcmp(map->label, label) != 0)
2700 DIE;
2701 map->label = label;
2702 return;
2705 DIE;
2708 static void change_initial_label(struct span *span, const char *label)
2710 struct superbfd *sbfd = span->ss->parent;
2711 span->label = label;
2712 span->orig_label = label;
2713 if (span->symbol) {
2714 asymbol *csym = canonical_symbol(sbfd, span->symbol);
2715 char *key = strprintf("%p", csym);
2716 struct label_map **mapp =
2717 label_mapp_hash_lookup(&sbfd->maps_hash, key, FALSE);
2718 free(key);
2719 assert(mapp);
2720 (*mapp)->label = span->label;
2721 (*mapp)->orig_label = span->orig_label;
2722 span->symbol = NULL;
2726 static void init_callers(struct superbfd *sbfd)
2728 string_hash_init(&sbfd->callers);
2729 asection *sect;
2730 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2731 struct supersect *ss = fetch_supersect(sbfd, sect);
2732 arelent **relocp;
2733 for (relocp = ss->relocs.data;
2734 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
2735 asymbol *sym = *(*relocp)->sym_ptr_ptr;
2736 unsigned long val =
2737 sym->value + get_reloc_offset(ss, *relocp, true);
2738 char *key = strprintf("%s+%lx", sym->section->name,
2739 val);
2740 const char **ret = string_hash_lookup(&sbfd->callers,
2741 key, TRUE);
2742 free(key);
2743 asymbol *csym = canonical_symbol(sbfd, sect->symbol);
2744 if (*ret != NULL)
2745 *ret = "*multiple_callers*";
2746 else if (static_local_symbol(sbfd, csym))
2747 *ret = static_local_symbol(sbfd, csym);
2748 else
2749 *ret = sect->name;
2754 static const char *find_caller(struct supersect *ss, asymbol *sym)
2756 char *key = strprintf("%s+%lx", sym->section->name,
2757 (unsigned long)sym->value);
2758 const char **ret = string_hash_lookup(&ss->parent->callers, key, FALSE);
2759 free(key);
2761 if (ret == NULL)
2762 return "*no_caller*";
2763 return *ret;
2766 static void init_csyms(struct superbfd *sbfd)
2768 asymbolpp_hash_init(&sbfd->csyms);
2770 asymbol **symp;
2771 for (symp = sbfd->syms.data; symp < sbfd->syms.data + sbfd->syms.size;
2772 symp++) {
2773 asymbol *sym = *symp;
2774 if ((sym->flags & BSF_DEBUGGING) != 0)
2775 continue;
2776 char *key = strprintf("%s+%lx", sym->section->name,
2777 (unsigned long)sym->value);
2778 asymbol ***csympp = asymbolpp_hash_lookup(&sbfd->csyms, key,
2779 TRUE);
2780 free(key);
2781 if (*csympp == NULL) {
2782 *csympp = symp;
2783 continue;
2785 asymbol *csym = **csympp;
2786 if ((csym->flags & BSF_GLOBAL) != 0)
2787 continue;
2788 if ((sym->flags & BSF_GLOBAL) != 0)
2789 *csympp = symp;
2793 static asymbol **symbolp_scan(struct supersect *ss, bfd_vma value)
2795 char *key = strprintf("%s+%lx", ss->name, (unsigned long)value);
2796 asymbol ***csympp =
2797 asymbolpp_hash_lookup(&ss->parent->csyms, key, FALSE);
2798 free(key);
2799 if (csympp != NULL)
2800 return *csympp;
2802 /* For section symbols of sections containing no symbols, return the
2803 section symbol that relocations are generated against */
2804 if (value == 0)
2805 return &ss->symbol;
2806 return NULL;
2809 static asymbol **canonical_symbolp(struct superbfd *sbfd, asymbol *sym)
2811 if (bfd_is_const_section(sym->section)) {
2812 asymbol **csymp;
2813 for (csymp = sbfd->syms.data;
2814 csymp < sbfd->syms.data + sbfd->syms.size; csymp++) {
2815 if (sym == *csymp)
2816 return csymp;
2818 return NULL;
2820 return symbolp_scan(fetch_supersect(sbfd, sym->section), sym->value);
2823 static asymbol *canonical_symbol(struct superbfd *sbfd, asymbol *sym)
2825 if (bfd_is_const_section(sym->section))
2826 return sym;
2827 asymbol **symp = canonical_symbolp(sbfd, sym);
2828 return symp != NULL ? *symp : NULL;
2831 static char *static_local_symbol(struct superbfd *sbfd, asymbol *sym)
2833 struct supersect *ss = fetch_supersect(sbfd, sym->section);
2834 if ((sym->flags & BSF_LOCAL) == 0 || (sym->flags & BSF_OBJECT) == 0)
2835 return NULL;
2836 char *dot = strrchr(sym->name, '.');
2837 if (dot == NULL || dot[1 + strspn(dot + 1, "0123546789")] != '\0')
2838 return NULL;
2839 char *basename = strndup(sym->name, dot - sym->name);
2841 /* Handle C.123.12345 symbols */
2842 dot = strrchr(basename, '.');
2843 if (dot != NULL && dot[1 + strspn(dot + 1, "0123546789")] == '\0')
2844 basename = strndup(basename, dot - basename);
2845 const char *caller;
2846 if (strcmp(basename, "__func__") == 0 ||
2847 strcmp(basename, "__PRETTY_FUNCTION__") == 0)
2848 caller = (const char *)ss->contents.data + sym->value;
2849 else
2850 caller = find_caller(ss, sym);
2851 return strprintf("%s<%s>", basename, caller);
2854 static char *symbol_label(struct superbfd *sbfd, asymbol *sym)
2856 const char *filename = sbfd->abfd->filename;
2857 char *c = strstr(filename, ".KSPLICE");
2858 int flen = (c == NULL ? strlen(filename) : c - filename);
2860 char *label;
2861 if (bfd_is_und_section(sym->section) || (sym->flags & BSF_GLOBAL) != 0) {
2862 label = strdup(sym->name);
2863 } else if (bfd_is_const_section(sym->section)) {
2864 label = strprintf("%s<%.*s>", sym->name, flen, filename);
2865 } else {
2866 asymbol *gsym = canonical_symbol(sbfd, sym);
2868 if (gsym == NULL)
2869 label = strprintf("%s+%lx<%.*s>",
2870 sym->section->name,
2871 (unsigned long)sym->value,
2872 flen, filename);
2873 else if ((gsym->flags & BSF_GLOBAL) != 0)
2874 label = strdup(gsym->name);
2875 else if (static_local_symbol(sbfd, gsym))
2876 label = strprintf("%s+%lx<%.*s>",
2877 static_local_symbol(sbfd, gsym),
2878 (unsigned long)sym->value,
2879 flen, filename);
2880 else
2881 label = strprintf("%s<%.*s>",
2882 gsym->name, flen, filename);
2885 return label;
2888 static void keep_span(struct span *span)
2890 span->keep = true;
2891 span->ss->keep = true;
2894 static struct span *new_span(struct supersect *ss, bfd_vma start, bfd_vma size)
2896 struct span *span = vec_grow(&ss->spans, 1);
2897 span->size = size;
2898 span->contents_size = size;
2899 span->start = start;
2900 span->ss = ss;
2901 span->keep = true;
2902 span->new = false;
2903 span->patch = false;
2904 span->bugpatch = false;
2905 span->datapatch = false;
2906 span->precallable = starts_with(ss->name, ".ksplice_call_pre_apply") ||
2907 starts_with(ss->name, ".ksplice_call_check_apply") ||
2908 starts_with(ss->name, ".ksplice_call_fail_apply") ||
2909 starts_with(ss->name, ".ksplice_call_post_remove");
2910 span->match = NULL;
2911 span->shift = 0;
2912 asymbol **symp = symbolp_scan(ss, span->start);
2913 if (symp != NULL) {
2914 span->symbol = *symp;
2915 span->label = label_lookup(ss->parent, span->symbol);
2916 } else {
2917 span->symbol = NULL;
2918 const char *label = label_lookup(ss->parent, ss->symbol);
2919 if (span->start != 0)
2920 span->label = strprintf("%s<span:%lx>", label,
2921 (unsigned long)span->start);
2922 else
2923 span->label = label;
2925 span->orig_label = span->label;
2926 return span;
2929 static void initialize_string_spans(struct supersect *ss)
2931 const char *str;
2932 for (str = ss->contents.data;
2933 (void *)str < ss->contents.data + ss->contents.size;) {
2934 bfd_vma start = (unsigned long)str -
2935 (unsigned long)ss->contents.data;
2936 bfd_vma size = strlen(str) + 1;
2937 bfd_vma contents_size = size;
2938 while ((start + size) % (1 << ss->alignment) != 0 &&
2939 start + size < ss->contents.size) {
2940 /* Some string sections, like __ksymtab_strings, only
2941 align some strings with the declared alignment */
2942 if (str[size] != '\0')
2943 break;
2944 size++;
2946 struct span *span = new_span(ss, start, size);
2947 span->contents_size = contents_size;
2948 str += size;
2952 static int compare_ulongs(const void *va, const void *vb)
2954 const unsigned long *a = va, *b = vb;
2955 return *a - *b;
2958 static void initialize_table_spans(struct superbfd *sbfd,
2959 struct table_section *s)
2961 asection *isection = bfd_get_section_by_name(sbfd->abfd, s->sect);
2962 if (isection == NULL)
2963 return;
2964 struct supersect *ss = fetch_supersect(sbfd, isection);
2965 if (ss->alignment < ffs(s->entry_align) - 1)
2966 ss->alignment = ffs(s->entry_align) - 1;
2968 asection *other_sect = NULL;
2969 if (s->other_sect != NULL)
2970 other_sect = bfd_get_section_by_name(sbfd->abfd, s->other_sect);
2971 struct supersect *other_ss = NULL;
2972 if (other_sect != NULL)
2973 other_ss = fetch_supersect(sbfd, other_sect);
2975 asection *crc_sect = NULL;
2976 if (s->crc_sect != NULL)
2977 crc_sect = bfd_get_section_by_name(sbfd->abfd, s->crc_sect);
2978 struct supersect *crc_ss = NULL;
2979 if (crc_sect != NULL)
2980 crc_ss = fetch_supersect(sbfd, crc_sect);
2982 struct ulong_vec offsets;
2983 vec_init(&offsets);
2985 void *entry;
2986 for (entry = ss->contents.data;
2987 entry < ss->contents.data + ss->contents.size;
2988 entry += s->entry_size) {
2989 struct span *span = new_span(ss, addr_offset(ss, entry),
2990 s->entry_size);
2991 if (s->entry_contents_size != 0)
2992 span->contents_size = s->entry_contents_size;
2993 if ((span->symbol == NULL ||
2994 (span->symbol->flags & BSF_SECTION_SYM) != 0) &&
2995 s->has_addr) {
2996 arelent *reloc = find_reloc(ss, entry + s->addr_offset);
2997 assert(reloc);
2998 struct span *target_span = reloc_target_span(ss, reloc);
2999 assert(target_span);
3000 asymbol *sym = *reloc->sym_ptr_ptr;
3001 unsigned long val = get_reloc_offset(ss, reloc, true) +
3002 sym->value - (target_span->start +
3003 target_span->shift);
3004 char *label = strprintf("%s<target:%s+%lx>", ss->name,
3005 target_span->label, val);
3006 change_initial_label(span, label);
3009 if (other_sect != NULL) {
3010 asymbol *sym;
3011 bfd_vma offset = read_reloc(ss, entry + s->other_offset,
3012 sizeof(void *), &sym);
3013 if (sym->section == other_sect) {
3014 assert(offset >= 0 &&
3015 offset < other_ss->contents.size);
3016 *vec_grow(&offsets, 1) = offset;
3020 if (crc_sect != NULL)
3021 new_span(crc_ss, addr_offset(ss, entry) / s->entry_size
3022 * s->crc_size, s->crc_size);
3024 if (ss->type == SS_TYPE_EXPORT) {
3025 const char *symname = read_string(ss, entry +
3026 s->other_offset);
3027 char *label = strprintf("%s:%s", ss->name, symname);
3028 change_initial_label(span, label);
3032 if (other_sect == NULL)
3033 return;
3035 *vec_grow(&offsets, 1) = 0;
3036 qsort(offsets.data, offsets.size, sizeof(*offsets.data),
3037 compare_ulongs);
3038 *vec_grow(&offsets, 1) = other_ss->contents.size;
3040 unsigned long *off;
3041 for (off = offsets.data; off < offsets.data + offsets.size - 1; off++) {
3042 if (*off != *(off + 1))
3043 new_span(other_ss, *off, *(off + 1) - *off);
3047 static void initialize_table_section_spans(struct superbfd *sbfd)
3049 struct supersect *tables_ss =
3050 fetch_supersect(offsets_sbfd,
3051 bfd_get_section_by_name(offsets_sbfd->abfd,
3052 ".ksplice_table_sections"));
3053 const struct table_section *ts;
3054 struct table_section s;
3055 for (ts = tables_ss->contents.data;
3056 (void *)ts < tables_ss->contents.data + tables_ss->contents.size;
3057 ts++) {
3058 s = *ts;
3059 s.sect = read_string(tables_ss, &ts->sect);
3060 s.other_sect = read_string(tables_ss, &ts->other_sect);
3061 s.crc_sect = read_string(tables_ss, &ts->crc_sect);
3062 initialize_table_spans(sbfd, &s);
3066 static void initialize_ksplice_call_spans(struct supersect *ss)
3068 arelent **relocp;
3069 for (relocp = ss->relocs.data;
3070 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
3071 arelent *reloc = *relocp;
3072 new_span(ss, reloc->address, bfd_get_reloc_size(reloc->howto));
3073 /* the span labels should already be unique */
3077 static void initialize_spans(struct superbfd *sbfd)
3079 asection *sect;
3080 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
3081 if (is_table_section(sect->name, true, true) && mode("keep"))
3082 continue;
3084 struct supersect *ss = fetch_supersect(sbfd, sect);
3085 if (ss->type == SS_TYPE_STRING)
3086 initialize_string_spans(ss);
3087 else if (ss->type == SS_TYPE_KSPLICE_CALL)
3088 initialize_ksplice_call_spans(ss);
3089 else
3090 new_span(ss, 0, ss->contents.size);
3092 if (mode("keep"))
3093 initialize_table_section_spans(sbfd);
3096 /* Returns the span pointed to by the relocation at span->start + offset */
3097 static struct span *span_offset_target_span(struct span *span, int offset)
3099 void *entry = span->ss->contents.data + span->start;
3100 arelent *reloc = find_reloc(span->ss, entry + offset);
3101 if (reloc == NULL)
3102 return NULL;
3103 struct span *sym_span = reloc_target_span(span->ss, reloc);
3104 if (sym_span == NULL)
3105 return NULL;
3106 return sym_span;
3109 struct span *reloc_target_span(struct supersect *ss, arelent *reloc)
3111 asymbol *sym_ptr = *reloc->sym_ptr_ptr;
3112 if (bfd_is_const_section(sym_ptr->section))
3113 return NULL;
3115 bfd_vma addend = get_reloc_offset(ss, reloc, true) + sym_ptr->value;
3116 struct supersect *sym_ss =
3117 fetch_supersect(ss->parent, sym_ptr->section);
3118 struct span *span, *target_span = sym_ss->spans.data;
3119 for (span = sym_ss->spans.data;
3120 span < sym_ss->spans.data + sym_ss->spans.size; span++) {
3121 if (addend >= span->start && addend < span->start + span->size)
3122 target_span = span;
3124 return target_span;
3127 struct span *find_span(struct supersect *ss, bfd_size_type address)
3129 struct span *span;
3130 for (span = ss->spans.data; span < ss->spans.data + ss->spans.size;
3131 span++) {
3132 if (address >= span->start &&
3133 address < span->start + span->size)
3134 return span;
3136 /* Deal with empty BSS sections */
3137 if (ss->contents.size == 0 && ss->spans.size > 0)
3138 return ss->spans.data;
3139 return NULL;
3142 void compute_span_shifts(struct superbfd *sbfd)
3144 asection *sect;
3145 struct span *span;
3146 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
3147 struct supersect *ss = fetch_supersect(sbfd, sect);
3148 if (!ss->keep)
3149 continue;
3150 bfd_size_type offset = 0;
3151 for (span = ss->spans.data;
3152 span < ss->spans.data + ss->spans.size; span++) {
3153 if (!span->keep)
3154 continue;
3155 span->shift = offset - span->start;
3156 offset += span->size;
3161 void remove_unkept_spans(struct superbfd *sbfd)
3163 asection *sect;
3164 struct span *span;
3165 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
3166 struct supersect *ss = fetch_supersect(sbfd, sect);
3167 delete_obsolete_relocs(ss);
3168 struct arelentp_vec orig_relocs;
3169 vec_move(&orig_relocs, &ss->relocs);
3170 arelent **relocp, *reloc;
3171 for (relocp = orig_relocs.data;
3172 relocp < orig_relocs.data + orig_relocs.size; relocp++) {
3173 reloc = *relocp;
3174 asymbol *sym = *reloc->sym_ptr_ptr;
3175 span = reloc_target_span(ss, reloc);
3176 if ((span != NULL && span->keep && span->shift == 0) ||
3177 bfd_is_const_section(sym->section)) {
3178 *vec_grow(&ss->relocs, 1) = reloc;
3179 continue;
3181 struct supersect *sym_ss =
3182 fetch_supersect(sbfd, sym->section);
3183 if (span != NULL && (sym->flags & BSF_SECTION_SYM) == 0
3184 && find_span(sym_ss, sym->value) != span) {
3185 err(sbfd, "Spans for symbol %s and relocation "
3186 "target do not match in sect %s\n",
3187 sym->name, sym_ss->name);
3188 DIE;
3190 if (span != NULL && span->keep) {
3191 arelent *new_reloc = malloc(sizeof(*new_reloc));
3192 *new_reloc = *reloc;
3193 new_reloc->addend =
3194 get_reloc_offset(ss, reloc, false);
3195 new_reloc->addend += span->shift;
3196 *vec_grow(&ss->new_relocs, 1) = new_reloc;
3201 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
3202 struct supersect *ss = fetch_supersect(sbfd, sect), orig_ss;
3203 if (!ss->keep)
3204 continue;
3205 supersect_move(&orig_ss, ss);
3206 vec_init(&ss->spans);
3207 for (span = orig_ss.spans.data;
3208 span < orig_ss.spans.data + orig_ss.spans.size; span++) {
3209 if (!span->keep)
3210 continue;
3211 struct span *new_span = vec_grow(&ss->spans, 1);
3212 *new_span = *span;
3213 new_span->start = span->start + span->shift;
3214 new_span->shift = 0;
3215 sect_copy(ss, sect_do_grow(ss, 1, span->size, 1),
3216 &orig_ss, orig_ss.contents.data + span->start,
3217 span->size);
3222 static void init_objmanip_superbfd(struct superbfd *sbfd)
3224 init_label_map(sbfd);
3225 initialize_supersect_types(sbfd);
3226 initialize_spans(sbfd);
3227 load_options(sbfd);
3230 void mangle_section_name(struct superbfd *sbfd, const char *name)
3232 asection *sect = bfd_get_section_by_name(sbfd->abfd, name);
3233 if (sect == NULL)
3234 return;
3235 struct supersect *ss = fetch_supersect(sbfd, sect);
3236 ss->name = strprintf(".ksplice_pre.%s", ss->name);
3239 static void write_bugline_patches(struct superbfd *sbfd)
3241 const struct table_section *ts = get_table_section("__bug_table");
3242 asection *sect = bfd_get_section_by_name(sbfd->abfd, "__bug_table");
3243 if (sect == NULL)
3244 return;
3245 struct supersect *ss = fetch_supersect(sbfd, sect);
3246 assert(ts != NULL);
3248 void *entry;
3249 for (entry = ss->contents.data;
3250 entry < ss->contents.data + ss->contents.size;
3251 entry += ts->entry_size) {
3252 struct span *span = find_span(ss, addr_offset(ss, entry));
3253 assert(span != NULL);
3254 if (!span->bugpatch)
3255 continue;
3256 arelent *reloc = find_reloc(ss, entry + ts->addr_offset);
3257 assert(reloc != NULL);
3258 asymbol *sym = *reloc->sym_ptr_ptr;
3259 assert(!bfd_is_const_section(sym->section));
3261 struct supersect *kpatch_ss =
3262 make_section(sbfd, ".ksplice_patches%s",
3263 sym->section->name);
3264 struct ksplice_patch *kpatch =
3265 sect_grow(kpatch_ss, 1, struct ksplice_patch);
3266 write_ksplice_patch_reloc
3267 (kpatch_ss, sym->section->name, &kpatch->oldaddr,
3268 sizeof(kpatch->oldaddr), span->label, ts->other_offset);
3270 unsigned short *line =
3271 write_patch_storage(kpatch_ss, kpatch, sizeof(*line), NULL);
3272 *line = *(unsigned short *)(entry + ts->other_offset);
3273 kpatch->type = KSPLICE_PATCH_BUGLINE;
3277 void *write_patch_storage(struct supersect *ss, struct ksplice_patch *kpatch,
3278 size_t size, struct supersect **data_ssp)
3280 struct supersect *data_ss = make_section(ss->parent,
3281 ".ksplice_patch_data");
3282 char *saved = sect_do_grow(data_ss, 1, size, 1);
3283 write_reloc(ss, &kpatch->saved, &data_ss->symbol,
3284 addr_offset(data_ss, saved));
3285 char *data = sect_do_grow(data_ss, 1, size, 1);
3286 write_reloc(ss, &kpatch->contents, &data_ss->symbol,
3287 addr_offset(data_ss, data));
3288 kpatch->size = size;
3289 if (data_ssp != NULL)
3290 *data_ssp = data_ss;
3291 return data;