Ksplice 0.9.6.
[ksplice.git] / objmanip.c
blob53e4a9c7150aba11ab72ff0ca658ca8b83b3c792
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 (bfd_is_const_section(sym_ptr->section) ||
1266 reloc_target_span(ss, *relocp)->new))
1267 rm_reloc = false;
1269 if (mode("keep-primary")) {
1270 const struct table_section *ts =
1271 get_table_section(ss->name);
1272 if (ts != NULL && ts->has_addr &&
1273 ((*relocp)->address % ts->entry_size ==
1274 ts->addr_offset ||
1275 (*relocp)->address % ts->entry_size ==
1276 ts->other_offset))
1277 rm_reloc = false;
1280 if (mode("finalize") && bfd_is_und_section(sym_ptr->section))
1281 rm_reloc = true;
1283 if (strcmp(sym_ptr->name, "mcount") == 0 &&
1284 bfd_is_und_section(sym_ptr->section))
1285 rm_reloc = false;
1287 if (!find_span(ss, (*relocp)->address)->keep)
1288 rm_reloc = false;
1290 if (rm_reloc)
1291 write_ksplice_reloc(ss, *relocp);
1292 else
1293 *vec_grow(&ss->relocs, 1) = *relocp;
1297 struct supersect *make_section(struct superbfd *sbfd, const char *fmt, ...)
1299 va_list ap;
1300 va_start(ap, fmt);
1301 char *name = vstrprintf(fmt, ap);
1302 va_end(ap);
1304 asection *sect = bfd_get_section_by_name(sbfd->abfd, name);
1305 if (sect != NULL)
1306 return fetch_supersect(sbfd, sect);
1307 else
1308 return new_supersect(sbfd, name);
1311 arelent *create_reloc(struct supersect *ss, const void *addr, asymbol **symp,
1312 bfd_vma offset)
1314 bfd_reloc_code_real_type code;
1315 switch (bfd_arch_bits_per_address(ss->parent->abfd)) {
1316 case 32:
1317 code = BFD_RELOC_32;
1318 break;
1319 case 64:
1320 code = BFD_RELOC_64;
1321 break;
1322 default:
1323 DIE;
1326 arelent *reloc = malloc(sizeof(*reloc));
1327 reloc->sym_ptr_ptr = symp;
1328 reloc->address = addr_offset(ss, addr);
1329 reloc->howto = bfd_reloc_type_lookup(ss->parent->abfd, code);
1330 reloc->addend = offset;
1331 return reloc;
1334 void write_reloc(struct supersect *ss, const void *addr, asymbol **symp,
1335 bfd_vma offset)
1337 *vec_grow(&ss->new_relocs, 1) = create_reloc(ss, addr, symp, offset);
1340 void write_string(struct supersect *ss, const char **addr, const char *fmt, ...)
1342 va_list ap;
1343 struct supersect *str_ss = make_section(ss->parent, ".ksplice_str");
1344 char *str;
1345 va_start(ap, fmt);
1346 int len = vasprintf(&str, fmt, ap);
1347 assert(len >= 0);
1348 va_end(ap);
1350 unsigned long *str_offp = ulong_hash_lookup(&ksplice_string_offset, str,
1351 FALSE);
1352 if (str_offp == NULL) {
1353 char *buf = sect_grow(str_ss, len + 1, char);
1354 memcpy(buf, str, len + 1);
1355 str_offp = ulong_hash_lookup(&ksplice_string_offset, str, TRUE);
1356 *str_offp = addr_offset(str_ss, buf);
1359 write_reloc(ss, addr, &str_ss->symbol, *str_offp);
1362 void lookup_system_map(struct addr_vec *addrs, const char *name, long offset)
1364 struct addr_vec *map_addrs =
1365 addr_vec_hash_lookup(&system_map, name, FALSE);
1366 if (map_addrs == NULL)
1367 return;
1369 unsigned long *addr, *map_addr;
1370 for (map_addr = map_addrs->data;
1371 map_addr < map_addrs->data + map_addrs->size; map_addr++) {
1372 for (addr = addrs->data; addr < addrs->data + addrs->size;
1373 addr++) {
1374 if (*addr == *map_addr + offset)
1375 break;
1377 if (addr < addrs->data + addrs->size)
1378 continue;
1379 *vec_grow(addrs, 1) = *map_addr + offset;
1383 void compute_system_map_array(struct superbfd *sbfd, struct addr_vec *addrs,
1384 asymbol *sym)
1386 if (bfd_is_abs_section(sym->section)) {
1387 *vec_grow(addrs, 1) = sym->value;
1388 } else if (bfd_is_und_section(sym->section)) {
1389 lookup_system_map(addrs, sym->name, 0);
1390 } else if (!bfd_is_const_section(sym->section)) {
1391 asymbol **gsymp;
1392 for (gsymp = sbfd->syms.data;
1393 gsymp < sbfd->syms.data + sbfd->syms.size; gsymp++) {
1394 asymbol *gsym = *gsymp;
1395 if ((gsym->flags & BSF_DEBUGGING) == 0 &&
1396 gsym->section == sym->section)
1397 lookup_system_map(addrs, gsym->name,
1398 sym->value - gsym->value);
1403 void write_ksplice_system_map(struct superbfd *sbfd, asymbol *sym,
1404 const char *label)
1406 bool *done = bool_hash_lookup(&system_map_written, label, TRUE);
1407 if (*done)
1408 return;
1409 *done = true;
1411 struct addr_vec addrs;
1412 vec_init(&addrs);
1414 compute_system_map_array(sbfd, &addrs, sym);
1415 if (addrs.size != 0) {
1416 struct supersect *smap_ss =
1417 make_section(sbfd, ".ksplice_system_map");
1418 struct ksplice_system_map *smap =
1419 sect_grow(smap_ss, 1, struct ksplice_system_map);
1420 write_string(smap_ss, &smap->label, "%s", label);
1422 struct supersect *array_ss = make_section(sbfd,
1423 ".ksplice_array");
1424 void *buf = sect_grow(array_ss, addrs.size,
1425 typeof(*addrs.data));
1426 memcpy(buf, addrs.data, addrs.size * sizeof(*addrs.data));
1427 smap->nr_candidates = addrs.size;
1428 write_reloc(smap_ss, &smap->candidates, &array_ss->symbol,
1429 addr_offset(array_ss, buf));
1431 vec_free(&addrs);
1434 void write_ksplice_symbol_backend(struct supersect *ss,
1435 struct ksplice_symbol *const *addr,
1436 asymbol *sym, const char *label,
1437 const char *name)
1439 struct supersect *ksymbol_ss = make_section(ss->parent,
1440 ".ksplice_symbols");
1441 struct ksplice_symbol *ksymbol;
1442 unsigned long *ksymbol_offp;
1444 ksymbol_offp = ulong_hash_lookup(&ksplice_symbol_offset, label, FALSE);
1445 if (ksymbol_offp != NULL) {
1446 write_reloc(ss, addr, &ksymbol_ss->symbol, *ksymbol_offp);
1447 return;
1449 ksymbol = sect_grow(ksymbol_ss, 1, struct ksplice_symbol);
1450 ksymbol_offp = ulong_hash_lookup(&ksplice_symbol_offset, label, TRUE);
1451 *ksymbol_offp = addr_offset(ksymbol_ss, ksymbol);
1453 write_reloc(ss, addr, &ksymbol_ss->symbol, *ksymbol_offp);
1454 write_string(ksymbol_ss, &ksymbol->label, "%s", label);
1455 if (name != NULL) {
1456 write_string(ksymbol_ss, &ksymbol->name, "%s", name);
1457 write_ksplice_system_map(ksymbol_ss->parent, sym, label);
1461 void write_ksplice_symbol(struct supersect *ss,
1462 struct ksplice_symbol *const *addr,
1463 asymbol *sym, struct span *span,
1464 const char *addstr_sect)
1466 const char *label, *name;
1467 if (span != NULL && span->start != 0)
1468 label = span->label;
1469 else
1470 label = label_lookup(ss->parent, sym);
1472 asymbol *gsym = canonical_symbol(ss->parent, sym);
1473 if (strcmp(addstr_sect, "") != 0)
1474 name = NULL;
1475 else if (bfd_is_und_section(sym->section))
1476 name = sym->name;
1477 else if (bfd_is_const_section(sym->section))
1478 name = NULL;
1479 else if (span != NULL && span->symbol == NULL)
1480 name = NULL;
1481 else if (gsym == NULL || (gsym->flags & BSF_SECTION_SYM) != 0)
1482 name = NULL;
1483 else
1484 name = gsym->name;
1486 write_ksplice_symbol_backend(ss, addr, sym,
1487 strprintf("%s%s", addstr_sect, label),
1488 name);
1491 void write_ksplice_reloc(struct supersect *ss, arelent *orig_reloc)
1493 asymbol *sym_ptr = *orig_reloc->sym_ptr_ptr;
1494 bfd_vma reloc_addend = get_reloc_offset(ss, orig_reloc, false);
1495 bfd_vma target_addend = get_reloc_offset(ss, orig_reloc, true);
1496 unsigned long *repladdr = ss->contents.data + orig_reloc->address;
1498 if (mode("finalize") && starts_with(ss->name, ".ksplice_patches")) {
1499 *repladdr = 0;
1500 return;
1502 if (mode("finalize") && starts_with(ss->name, ".ksplice_relocs")) {
1503 assert(starts_with(sym_ptr->name, KSPLICE_SYMBOL_STR));
1504 asymbol fake_sym;
1505 fake_sym.name = sym_ptr->name + strlen(KSPLICE_SYMBOL_STR);
1506 fake_sym.section = bfd_und_section_ptr;
1507 fake_sym.value = 0;
1508 fake_sym.flags = 0;
1510 write_ksplice_symbol_backend
1511 (ss, (struct ksplice_symbol **)repladdr, &fake_sym,
1512 fake_sym.name, fake_sym.name);
1513 return;
1516 struct span *span = reloc_target_span(ss, orig_reloc);
1517 if (span == ss->spans.data && span->start != target_addend)
1518 span = NULL;
1519 write_canary(ss, orig_reloc->address,
1520 bfd_get_reloc_size(orig_reloc->howto),
1521 orig_reloc->howto->dst_mask);
1523 struct supersect *kreloc_ss;
1524 if (mode("rmsyms"))
1525 kreloc_ss = make_section(ss->parent, ".ksplice_init_relocs");
1526 else
1527 kreloc_ss = make_section(ss->parent, ".ksplice_relocs%s",
1528 ss->name);
1529 struct ksplice_reloc *kreloc = sect_grow(kreloc_ss, 1,
1530 struct ksplice_reloc);
1532 struct span *address_span = find_span(ss, orig_reloc->address);
1533 write_reloc(kreloc_ss, &kreloc->blank_addr,
1534 &ss->symbol, orig_reloc->address + address_span->shift);
1535 if (bfd_is_und_section(sym_ptr->section) && mode("keep")) {
1536 char *name = strprintf(KSPLICE_SYMBOL_STR "%s", sym_ptr->name);
1537 asymbol **symp = make_undefined_symbolp(ss->parent, name);
1538 write_reloc(kreloc_ss, &kreloc->symbol, symp, 0);
1539 } else {
1540 write_ksplice_symbol(kreloc_ss, &kreloc->symbol, sym_ptr, span,
1541 "");
1543 if (span != NULL && span->start != 0) {
1544 reloc_addend += sym_ptr->value - span->start;
1545 target_addend += sym_ptr->value - span->start;
1547 kreloc->insn_addend = reloc_addend - target_addend;
1548 kreloc->target_addend = target_addend;
1549 write_ksplice_reloc_howto(kreloc_ss, &kreloc->howto, orig_reloc->howto,
1550 KSPLICE_HOWTO_RELOC);
1553 static void write_ksplice_reloc_howto(struct supersect *ss, const
1554 struct ksplice_reloc_howto *const *addr,
1555 reloc_howto_type *howto,
1556 enum ksplice_reloc_howto_type type)
1558 struct supersect *khowto_ss = make_section(ss->parent,
1559 ".ksplice_reloc_howtos");
1560 struct ksplice_reloc_howto *khowto;
1561 unsigned long *khowto_offp;
1563 khowto_offp = ulong_hash_lookup(&ksplice_howto_offset, howto->name,
1564 FALSE);
1565 if (khowto_offp != NULL) {
1566 write_reloc(ss, addr, &khowto_ss->symbol, *khowto_offp);
1567 return;
1569 khowto = sect_grow(khowto_ss, 1, struct ksplice_reloc_howto);
1570 khowto_offp = ulong_hash_lookup(&ksplice_howto_offset, howto->name,
1571 TRUE);
1572 *khowto_offp = addr_offset(khowto_ss, khowto);
1574 khowto->type = type;
1575 khowto->pcrel = howto->pc_relative;
1576 khowto->size = bfd_get_reloc_size(howto);
1577 khowto->dst_mask = howto->dst_mask;
1578 khowto->rightshift = howto->rightshift;
1579 khowto->signed_addend =
1580 (howto->complain_on_overflow == complain_overflow_signed) ||
1581 (howto->complain_on_overflow == complain_overflow_bitfield);
1582 write_reloc(ss, addr, &khowto_ss->symbol, *khowto_offp);
1585 #define CANARY(x, canary) ((x & ~howto->dst_mask) | (canary & howto->dst_mask))
1587 void write_canary(struct supersect *ss, int offset, bfd_size_type size,
1588 bfd_vma dst_mask)
1590 int bits = size * 8;
1591 void *address = ss->contents.data + offset;
1592 bfd_vma x = bfd_get(bits, ss->parent->abfd, address);
1593 x = (x & ~dst_mask) | ((bfd_vma)KSPLICE_CANARY & dst_mask);
1594 bfd_put(bits, ss->parent->abfd, x, address);
1597 static void write_date_relocs(struct superbfd *sbfd, const char *str,
1598 enum ksplice_reloc_howto_type type)
1600 asection *sect;
1601 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
1602 struct supersect *ss = fetch_supersect(sbfd, sect);
1603 if (ss->type != SS_TYPE_STRING && ss->type != SS_TYPE_RODATA)
1604 continue;
1605 void *ptr;
1606 struct span *span;
1607 for (span = ss->spans.data;
1608 span < ss->spans.data + ss->spans.size; span++) {
1609 if (!span->keep)
1610 continue;
1611 for (ptr = ss->contents.data + span->start;
1612 ptr + strlen(str) < ss->contents.data +
1613 span->start + span->contents_size; ptr++) {
1614 if (strcmp((const char *)ptr, str) == 0)
1615 write_ksplice_date_reloc
1616 (ss, addr_offset(ss, ptr), str,
1617 type);
1623 static void write_ksplice_date_reloc(struct supersect *ss, unsigned long offset,
1624 const char *str,
1625 enum ksplice_reloc_howto_type type)
1627 struct supersect *kreloc_ss;
1628 kreloc_ss = make_section(ss->parent, ".ksplice_relocs%s", ss->name);
1629 struct ksplice_reloc *kreloc = sect_grow(kreloc_ss, 1,
1630 struct ksplice_reloc);
1632 const char *filename = ss->parent->abfd->filename;
1633 char *c = strstr(filename, ".KSPLICE");
1634 int flen = (c == NULL ? strlen(filename) : c - filename);
1636 write_ksplice_symbol_backend(kreloc_ss, &kreloc->symbol, NULL,
1637 strprintf("%s<%.*s>", str, flen, filename),
1638 NULL);
1640 struct span *span = find_span(ss, offset);
1641 write_reloc(kreloc_ss, &kreloc->blank_addr, &ss->symbol,
1642 offset + span->shift);
1643 write_ksplice_nonreloc_howto(kreloc_ss, &kreloc->howto, type,
1644 strlen(str));
1647 static void write_table_relocs(struct superbfd *sbfd, const char *sectname,
1648 enum ksplice_reloc_howto_type type)
1650 asection *sect = bfd_get_section_by_name(sbfd->abfd, sectname);
1651 if (sect == NULL)
1652 return;
1653 struct supersect *ss = fetch_supersect(sbfd, sect);
1655 const struct table_section *s = get_table_section(sectname);
1656 if (s == NULL)
1657 DIE;
1659 void *entry;
1660 for (entry = ss->contents.data;
1661 entry < ss->contents.data + ss->contents.size;
1662 entry += s->entry_size) {
1663 struct span *span = find_span(ss, addr_offset(ss, entry));
1664 assert(span != NULL);
1665 if (!span->keep)
1666 continue;
1668 arelent *reloc = find_reloc(ss, entry + s->addr_offset);
1669 assert(reloc != NULL);
1670 asymbol *sym = *reloc->sym_ptr_ptr;
1671 assert(!bfd_is_const_section(sym->section));
1672 struct supersect *sym_ss = fetch_supersect(sbfd, sym->section);
1673 unsigned long addr = get_reloc_offset(ss, reloc, true) +
1674 sym->value;
1675 write_ksplice_table_reloc(sym_ss, addr, span->label, type);
1679 static void write_ksplice_table_reloc(struct supersect *ss,
1680 unsigned long address,
1681 const char *label,
1682 enum ksplice_reloc_howto_type type)
1684 struct supersect *kreloc_ss;
1685 kreloc_ss = make_section(ss->parent, ".ksplice_relocs%s", ss->name);
1686 struct ksplice_reloc *kreloc = sect_grow(kreloc_ss, 1,
1687 struct ksplice_reloc);
1688 struct span *span = find_span(ss, address);
1689 assert(span != NULL);
1691 write_ksplice_symbol_backend(kreloc_ss, &kreloc->symbol, NULL,
1692 label, NULL);
1693 write_reloc(kreloc_ss, &kreloc->blank_addr, &ss->symbol,
1694 address + span->shift);
1695 write_ksplice_nonreloc_howto(kreloc_ss, &kreloc->howto, type, 0);
1698 static void write_ksplice_nonreloc_howto(struct supersect *ss,
1699 const struct ksplice_reloc_howto
1700 *const *addr,
1701 enum ksplice_reloc_howto_type type,
1702 int size)
1704 struct supersect *khowto_ss =
1705 make_section(ss->parent, ".ksplice_reloc_howtos");
1706 struct ksplice_reloc_howto *khowto =
1707 sect_grow(khowto_ss, 1, struct ksplice_reloc_howto);
1709 khowto->type = type;
1710 khowto->size = size;
1711 khowto->pcrel = 0;
1712 khowto->dst_mask = 0;
1713 khowto->rightshift = 0;
1714 khowto->signed_addend = 0;
1715 write_reloc(ss, addr, &khowto_ss->symbol,
1716 addr_offset(khowto_ss, khowto));
1719 static void write_ksplice_section(struct span *span)
1721 struct supersect *ss = span->ss;
1722 const char *sectname = span->ss->name;
1723 const struct table_section *ts = get_table_section(ss->name);
1725 if (ts != NULL && ts->has_addr) {
1726 arelent *reloc = find_reloc(ss, ss->contents.data + span->start
1727 + ts->addr_offset);
1728 assert(reloc != NULL);
1729 asymbol *rsym = *reloc->sym_ptr_ptr;
1730 assert(!bfd_is_const_section(rsym->section));
1731 sectname = rsym->section->name;
1734 struct supersect *ksect_ss =
1735 make_section(ss->parent, ".ksplice_sections%s", sectname);
1736 struct ksplice_section *ksect = sect_grow(ksect_ss, 1,
1737 struct ksplice_section);
1738 asymbol *sym = span->symbol == NULL ? ss->symbol : span->symbol;
1740 write_ksplice_symbol(ksect_ss, &ksect->symbol, sym, span,
1741 mode("keep-primary") ? "(post)" : "");
1742 ksect->size = span->size;
1743 ksect->flags = 0;
1745 if (ss->type == SS_TYPE_RODATA || ss->type == SS_TYPE_STRING ||
1746 ss->type == SS_TYPE_EXPORT)
1747 ksect->flags |= KSPLICE_SECTION_RODATA;
1748 if (ss->type == SS_TYPE_DATA)
1749 ksect->flags |= KSPLICE_SECTION_DATA;
1750 if (ss->type == SS_TYPE_TEXT)
1751 ksect->flags |= KSPLICE_SECTION_TEXT;
1752 assert(ksect->flags != 0);
1754 if (ss->type == SS_TYPE_STRING)
1755 ksect->flags |= KSPLICE_SECTION_STRING;
1757 write_reloc(ksect_ss, &ksect->address, &ss->symbol,
1758 span->start + span->shift);
1761 static void write_ksplice_patch_reloc(struct supersect *ss,
1762 const char *sectname, unsigned long *addr,
1763 bfd_size_type size, const char *label,
1764 long addend)
1766 struct supersect *kreloc_ss;
1767 kreloc_ss = make_section(ss->parent, ".ksplice_relocs%s", sectname);
1768 struct ksplice_reloc *kreloc = sect_grow(kreloc_ss, 1,
1769 struct ksplice_reloc);
1771 write_canary(ss, addr_offset(ss, addr), size, -1);
1772 write_ksplice_symbol_backend(kreloc_ss, &kreloc->symbol, NULL,
1773 label, NULL);
1774 write_reloc(kreloc_ss, &kreloc->blank_addr, &ss->symbol,
1775 addr_offset(ss, addr));
1776 reloc_howto_type *howto =
1777 bfd_reloc_type_lookup(ss->parent->abfd,
1778 PASTE(BFD_RELOC_, LONG_BIT));
1779 write_ksplice_reloc_howto(kreloc_ss, &kreloc->howto, howto,
1780 KSPLICE_HOWTO_RELOC);
1781 kreloc->target_addend = addend;
1782 kreloc->insn_addend = 0;
1785 void write_ksplice_patch(struct superbfd *sbfd, struct span *span)
1787 struct supersect *kpatch_ss =
1788 make_section(sbfd, ".ksplice_patches%s", span->ss->name);
1789 struct ksplice_patch *kpatch = sect_grow(kpatch_ss, 1,
1790 struct ksplice_patch);
1792 write_ksplice_patch_reloc(kpatch_ss, span->ss->name, &kpatch->oldaddr,
1793 sizeof(kpatch->oldaddr), span->label, 0);
1794 if (span->ss->type == SS_TYPE_TEXT) {
1795 kpatch->type = KSPLICE_PATCH_TEXT;
1796 write_patch_storage(kpatch_ss, kpatch, MAX_TRAMPOLINE_SIZE,
1797 NULL);
1798 } else {
1799 kpatch->type = KSPLICE_PATCH_DATA;
1800 kpatch->size = span->contents_size;
1801 struct supersect *data_ss =
1802 make_section(sbfd, ".ksplice_patch_data");
1803 write_reloc(kpatch_ss, &kpatch->contents, &span->ss->symbol,
1804 span->start + span->shift);
1805 char *saved = sect_do_grow(data_ss, 1, span->contents_size, 1);
1806 write_reloc(kpatch_ss, &kpatch->saved, &data_ss->symbol,
1807 addr_offset(data_ss, saved));
1809 write_reloc(kpatch_ss, &kpatch->repladdr, &span->ss->symbol,
1810 span->start + span->shift);
1813 asymbol **make_undefined_symbolp(struct superbfd *sbfd, const char *name)
1815 asymbol **symp;
1816 for (symp = sbfd->syms.data; symp < sbfd->syms.data + sbfd->syms.size;
1817 symp++) {
1818 asymbol *sym = *symp;
1819 if (strcmp(name, sym->name) == 0 &&
1820 bfd_is_und_section(sym->section))
1821 return symp;
1823 asymbol ***sympp;
1824 for (sympp = sbfd->new_syms.data;
1825 sympp < sbfd->new_syms.data + sbfd->new_syms.size; sympp++) {
1826 asymbol **symp = *sympp;
1827 asymbol *sym = *symp;
1828 if (strcmp(name, sym->name) == 0 &&
1829 bfd_is_und_section(sym->section))
1830 return symp;
1833 symp = malloc(sizeof(*symp));
1834 *symp = bfd_make_empty_symbol(sbfd->abfd);
1835 asymbol *sym = *symp;
1836 sym->name = name;
1837 sym->section = bfd_und_section_ptr;
1838 sym->flags = 0;
1839 sym->value = 0;
1840 *vec_grow(&sbfd->new_syms, 1) = symp;
1841 return symp;
1844 void write_ksplice_deleted_patch(struct superbfd *sbfd, const char *name,
1845 const char *label, const char *sectname)
1847 struct supersect *kpatch_ss =
1848 make_section(sbfd, ".ksplice_patches%s", sectname);
1849 struct ksplice_patch *kpatch = sect_grow(kpatch_ss, 1,
1850 struct ksplice_patch);
1852 write_ksplice_patch_reloc(kpatch_ss, sectname, &kpatch->oldaddr,
1853 sizeof(kpatch->oldaddr), label, 0);
1854 kpatch->type = KSPLICE_PATCH_TEXT;
1855 asymbol **symp = make_undefined_symbolp(sbfd, strdup(name));
1856 write_reloc(kpatch_ss, &kpatch->repladdr, symp, 0);
1857 write_patch_storage(kpatch_ss, kpatch, MAX_TRAMPOLINE_SIZE, NULL);
1860 void write_ksplice_export(struct superbfd *sbfd, struct span *span, bool del)
1862 struct supersect *kpatch_ss = make_section(sbfd, ".ksplice_patches");
1863 struct ksplice_patch *kpatch = sect_grow(kpatch_ss, 1,
1864 struct ksplice_patch);
1865 struct supersect *data_ss;
1867 const struct table_section *ts = get_table_section(span->ss->name);
1868 assert(ts != NULL);
1869 const char **addr =
1870 span->ss->contents.data + span->start + ts->other_offset;
1871 const char *symname = read_string(span->ss, addr);
1873 char *oldname, *newname;
1874 if (del) {
1875 oldname = strprintf("%s:%s", span->ss->name, symname);
1876 newname = strprintf("DISABLED_%s_%s", symname, kid);
1877 } else {
1878 oldname = strprintf("%s:DISABLED_%s_%s", span->ss->name,
1879 symname, kid);
1880 newname = strprintf("%s", symname);
1881 write_string(span->ss, addr, "DISABLED_%s_%s", symname, kid);
1884 write_ksplice_patch_reloc(kpatch_ss, "", &kpatch->oldaddr,
1885 sizeof(kpatch->oldaddr), oldname,
1886 ts->other_offset);
1887 kpatch->type = KSPLICE_PATCH_EXPORT;
1888 const char **namep = write_patch_storage(kpatch_ss, kpatch,
1889 sizeof(newname), &data_ss);
1890 write_string(data_ss, namep, "%s", newname);
1893 void filter_table_sections(struct superbfd *isbfd)
1895 struct supersect *tables_ss =
1896 fetch_supersect(offsets_sbfd,
1897 bfd_get_section_by_name(offsets_sbfd->abfd,
1898 ".ksplice_table_sections"));
1899 const struct table_section *ts;
1900 for (ts = tables_ss->contents.data;
1901 (void *)ts < tables_ss->contents.data + tables_ss->contents.size;
1902 ts++) {
1903 struct table_section s = *ts;
1904 s.sect = read_string(tables_ss, &ts->sect);
1905 s.other_sect = read_string(tables_ss, &ts->other_sect);
1906 s.crc_sect = read_string(tables_ss, &ts->crc_sect);
1907 filter_table_section(isbfd, &s);
1911 void filter_table_section(struct superbfd *sbfd, const struct table_section *s)
1913 asection *isection = bfd_get_section_by_name(sbfd->abfd, s->sect);
1914 if (isection == NULL)
1915 return;
1916 struct supersect *ss = fetch_supersect(sbfd, isection);
1918 void *entry;
1919 for (entry = ss->contents.data;
1920 entry < ss->contents.data + ss->contents.size;
1921 entry += s->entry_size) {
1922 struct span *span = find_span(ss, addr_offset(ss, entry));
1923 assert(span != NULL);
1925 if (s->has_addr) {
1926 struct span *sym_span =
1927 span_offset_target_span(span, s->addr_offset);
1928 assert(sym_span != NULL);
1929 if (sym_span->keep)
1930 keep_span(span);
1933 if (s->other_sect != NULL) {
1934 struct span *sym_span =
1935 span_offset_target_span(span, s->other_offset);
1936 assert(sym_span != NULL);
1937 if (span->keep)
1938 keep_span(sym_span);
1941 if (s->crc_sect != NULL) {
1942 struct span *crc_span = get_crc_span(span, s);
1943 assert(crc_span != NULL);
1944 if (span->keep && mode("keep-primary"))
1945 keep_span(crc_span);
1950 static void match_table_spans(struct span *old_span, struct span *new_span)
1952 const struct table_section *ts = get_table_section(old_span->ss->name);
1954 if (strcmp(old_span->ss->name, new_span->ss->name) != 0)
1955 return;
1956 if (ts == NULL || old_span->ss->type != SS_TYPE_SPECIAL ||
1957 new_span->ss->type != SS_TYPE_SPECIAL)
1958 return;
1959 if (old_span->match != NULL || new_span->match != NULL)
1960 return;
1962 if (ts->has_addr) {
1963 void *old_entry = old_span->ss->contents.data + old_span->start;
1964 void *new_entry = new_span->ss->contents.data + new_span->start;
1965 arelent *old_reloc =
1966 find_reloc(old_span->ss, old_entry + ts->addr_offset);
1967 arelent *new_reloc =
1968 find_reloc(new_span->ss, new_entry + ts->addr_offset);
1969 assert(old_reloc != NULL && new_reloc != NULL);
1970 struct span *old_sym_span =
1971 reloc_target_span(old_span->ss, old_reloc);
1972 struct span *new_sym_span =
1973 reloc_target_span(new_span->ss, new_reloc);
1974 assert(old_sym_span != NULL && new_sym_span != NULL);
1975 if (old_sym_span->match == new_sym_span &&
1976 new_sym_span->match == old_sym_span &&
1977 old_reloc->address - old_sym_span->start ==
1978 new_reloc->address - new_sym_span->start)
1979 match_spans(old_span, new_span);
1983 static struct span *get_crc_span(struct span *span,
1984 const struct table_section *ts)
1986 void *entry = span->ss->contents.data + span->start;
1987 asection *crc_sect = bfd_get_section_by_name(span->ss->parent->abfd,
1988 ts->crc_sect);
1989 if (crc_sect == NULL)
1990 return NULL;
1991 struct supersect *crc_ss = fetch_supersect(span->ss->parent, crc_sect);
1992 if (crc_ss == NULL)
1993 return NULL;
1994 struct span *crc_span = find_span(crc_ss, addr_offset(span->ss, entry) /
1995 ts->entry_size * ts->crc_size);
1996 return crc_span;
1999 void mark_precallable_spans(struct superbfd *sbfd)
2001 asection *sect;
2002 struct supersect *ss, *sym_ss;
2003 struct span *address_span, *target_span;
2004 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2005 ss = fetch_supersect(sbfd, sect);
2006 arelent **relocp;
2007 if (ss->type == SS_TYPE_SPECIAL)
2008 continue;
2009 for (relocp = ss->relocs.data;
2010 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
2011 asymbol *sym = *(*relocp)->sym_ptr_ptr;
2012 address_span = find_span(ss, (*relocp)->address);
2013 if (!address_span->precallable)
2014 continue;
2015 target_span = reloc_target_span(ss, *relocp);
2016 if (target_span == NULL || target_span->keep)
2017 continue;
2018 sym_ss = fetch_supersect(sbfd, sym->section);
2019 if (sym_ss->type == SS_TYPE_IGNORED)
2020 continue;
2021 target_span->precallable = true;
2022 changed = true;
2027 void keep_referenced_sections(struct superbfd *sbfd)
2029 asection *sect;
2030 struct supersect *ss, *sym_ss;
2031 struct span *address_span, *target_span;
2032 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2033 ss = fetch_supersect(sbfd, sect);
2034 arelent **relocp;
2035 if (ss->type == SS_TYPE_SPECIAL)
2036 continue;
2037 for (relocp = ss->relocs.data;
2038 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
2039 asymbol *sym = *(*relocp)->sym_ptr_ptr;
2040 address_span = find_span(ss, (*relocp)->address);
2041 if (!address_span->keep)
2042 continue;
2043 target_span = reloc_target_span(ss, *relocp);
2044 if (target_span == NULL || target_span->keep)
2045 continue;
2046 sym_ss = fetch_supersect(sbfd, sym->section);
2047 if (sym_ss->type == SS_TYPE_IGNORED)
2048 continue;
2049 keep_span(target_span);
2050 changed = true;
2055 void copy_symbols(struct asymbolp_vec *osyms, struct asymbolpp_vec *isyms)
2057 asymbol ***sympp;
2058 for (sympp = isyms->data; sympp < isyms->data + isyms->size; sympp++)
2059 *vec_grow(osyms, 1) = **sympp;
2062 /* Modified function from GNU Binutils objcopy.c */
2063 bfd_boolean copy_object(bfd *ibfd, bfd *obfd)
2065 assert(bfd_set_format(obfd, bfd_get_format(ibfd)));
2067 bfd_vma start = bfd_get_start_address(ibfd);
2069 flagword flags = bfd_get_file_flags(ibfd);
2070 flags &= bfd_applicable_file_flags(obfd);
2072 assert(bfd_set_start_address(obfd, start)
2073 && bfd_set_file_flags(obfd, flags));
2075 enum bfd_architecture iarch = bfd_get_arch(ibfd);
2076 unsigned int imach = bfd_get_mach(ibfd);
2077 assert(bfd_set_arch_mach(obfd, iarch, imach));
2078 assert(bfd_set_format(obfd, bfd_get_format(ibfd)));
2080 /* BFD mandates that all output sections be created and sizes set before
2081 any output is done. Thus, we traverse all sections multiple times. */
2082 bfd_map_over_sections(ibfd, setup_section, obfd);
2084 struct supersect *new_supersects = fetch_superbfd(ibfd)->new_supersects;
2085 struct supersect *ss;
2086 for (ss = new_supersects; ss != NULL; ss = ss->next)
2087 setup_new_section(obfd, ss);
2089 /* Mark symbols used in output relocations so that they
2090 are kept, even if they are local labels or static symbols.
2092 Note we iterate over the input sections examining their
2093 relocations since the relocations for the output sections
2094 haven't been set yet. mark_symbols_used_in_relocations will
2095 ignore input sections which have no corresponding output
2096 section. */
2098 bfd_map_over_sections(ibfd, mark_symbols_used_in_relocations, NULL);
2099 for (ss = new_supersects; ss != NULL; ss = ss->next)
2100 ss_mark_symbols_used_in_relocations(ss);
2101 struct asymbolp_vec osyms;
2102 vec_init(&osyms);
2103 filter_symbols(ibfd, obfd, &osyms, &fetch_superbfd(ibfd)->syms);
2104 copy_symbols(&osyms, &fetch_superbfd(ibfd)->new_syms);
2106 bfd_set_symtab(obfd, osyms.data, osyms.size);
2108 /* This has to happen after the symbol table has been set. */
2109 bfd_map_over_sections(obfd, write_section, NULL);
2111 /* Allow the BFD backend to copy any private data it understands
2112 from the input BFD to the output BFD. This is done last to
2113 permit the routine to look at the filtered symbol table, which is
2114 important for the ECOFF code at least. */
2115 assert(bfd_copy_private_bfd_data(ibfd, obfd));
2117 return TRUE;
2120 /* Modified function from GNU Binutils objcopy.c */
2121 void setup_section(bfd *ibfd, asection *isection, void *obfdarg)
2123 struct superbfd *isbfd = fetch_superbfd(ibfd);
2124 struct supersect *ss = fetch_supersect(isbfd, isection);
2125 bfd *obfd = obfdarg;
2126 bfd_vma vma;
2128 if (!ss->keep)
2129 return;
2131 asection *osection = bfd_make_section_anyway(obfd, ss->name);
2132 assert(osection != NULL);
2134 osection->userdata = ss;
2135 bfd_set_section_flags(obfd, osection, ss->flags);
2136 ss->symbol = osection->symbol;
2137 assert(bfd_set_section_size(obfd, osection, ss->contents.size));
2139 vma = bfd_section_vma(ibfd, isection);
2140 assert(bfd_set_section_vma(obfd, osection, vma));
2142 osection->lma = isection->lma;
2143 assert(bfd_set_section_alignment(obfd, osection, ss->alignment));
2144 osection->entsize = ss->entsize;
2145 osection->output_section = osection;
2146 osection->output_offset = 0;
2147 isection->output_section = osection;
2148 isection->output_offset = 0;
2149 return;
2152 void setup_new_section(bfd *obfd, struct supersect *ss)
2154 asection *osection = bfd_make_section_anyway(obfd, ss->name);
2155 assert(osection != NULL);
2156 bfd_set_section_flags(obfd, osection, ss->flags);
2158 osection->userdata = ss;
2159 ss->symbol = osection->symbol;
2160 assert(bfd_set_section_size(obfd, osection, ss->contents.size));
2161 assert(bfd_set_section_vma(obfd, osection, 0));
2163 osection->lma = 0;
2164 assert(bfd_set_section_alignment(obfd, osection, ss->alignment));
2165 osection->entsize = ss->entsize;
2166 osection->output_section = osection;
2167 osection->output_offset = 0;
2170 static int compare_reloc_addresses(const void *aptr, const void *bptr)
2172 const arelent *const *a = aptr, *const *b = bptr;
2173 return (*a)->address - (*b)->address;
2176 static void delete_obsolete_relocs(struct supersect *ss)
2178 if (ss->new_relocs.size == 0)
2179 return;
2181 qsort(ss->relocs.data, ss->relocs.size, sizeof(*ss->relocs.data),
2182 compare_reloc_addresses);
2183 qsort(ss->new_relocs.data, ss->new_relocs.size,
2184 sizeof(*ss->new_relocs.data), compare_reloc_addresses);
2186 struct arelentp_vec orig_relocs;
2187 vec_move(&orig_relocs, &ss->relocs);
2189 arelent **relocp, **new_relocp = ss->new_relocs.data;
2190 for (relocp = orig_relocs.data;
2191 relocp < orig_relocs.data + orig_relocs.size; relocp++) {
2192 while (new_relocp < ss->new_relocs.data + ss->new_relocs.size &&
2193 (*new_relocp)->address < (*relocp)->address)
2194 new_relocp++;
2195 arelent *reloc = *relocp, *new_reloc = *new_relocp;
2196 if (new_relocp == ss->new_relocs.data + ss->new_relocs.size ||
2197 reloc->address != new_reloc->address)
2198 *vec_grow(&ss->relocs, 1) = reloc;
2202 void write_section(bfd *obfd, asection *osection, void *arg)
2204 struct supersect *ss = osection->userdata;
2206 if ((ss->flags & SEC_GROUP) != 0 || ss->contents.size == 0)
2207 return;
2209 delete_obsolete_relocs(ss);
2211 arelent **relocp;
2212 char *error_message;
2213 for (relocp = ss->new_relocs.data;
2214 relocp < ss->new_relocs.data + ss->new_relocs.size; relocp++) {
2215 bfd_vma val;
2216 if (bfd_get_arch(obfd) == bfd_arch_arm)
2217 val = osection->use_rela_p ? 0 : (*relocp)->addend;
2218 else
2219 val = 0;
2220 bfd_put(bfd_get_reloc_size((*relocp)->howto) * 8, obfd, val,
2221 ss->contents.data + (*relocp)->address);
2222 if (bfd_install_relocation(obfd, *relocp, ss->contents.data,
2223 0, osection, &error_message) !=
2224 bfd_reloc_ok) {
2225 err(ss->parent, "ksplice: error installing reloc: %s",
2226 error_message);
2227 DIE;
2230 memcpy(vec_grow(&ss->relocs, ss->new_relocs.size), ss->new_relocs.data,
2231 ss->new_relocs.size * sizeof(*ss->new_relocs.data));
2233 bfd_set_reloc(obfd, osection,
2234 ss->relocs.size == 0 ? NULL : ss->relocs.data,
2235 ss->relocs.size);
2237 if (ss->flags & SEC_HAS_CONTENTS)
2238 assert(bfd_set_section_contents
2239 (obfd, osection, ss->contents.data, 0,
2240 ss->contents.size));
2243 /* Modified function from GNU Binutils objcopy.c
2245 * Mark all the symbols which will be used in output relocations with
2246 * the BSF_KEEP flag so that those symbols will not be stripped.
2248 * Ignore relocations which will not appear in the output file.
2250 void mark_symbols_used_in_relocations(bfd *abfd, asection *isection,
2251 void *ignored)
2253 struct superbfd *sbfd = fetch_superbfd(abfd);
2254 if (isection->output_section == NULL)
2255 return;
2257 struct supersect *ss = fetch_supersect(sbfd, isection);
2258 ss_mark_symbols_used_in_relocations(ss);
2261 void ss_mark_symbols_used_in_relocations(struct supersect *ss)
2263 /* Examine each symbol used in a relocation. If it's not one of the
2264 special bfd section symbols, then mark it with BSF_KEEP. */
2265 arelent **relocp;
2266 for (relocp = ss->relocs.data;
2267 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
2268 asymbol *sym = *(*relocp)->sym_ptr_ptr;
2269 if (!(bfd_is_const_section(sym->section) &&
2270 sym == sym->section->symbol))
2271 sym->flags |= BSF_KEEP;
2273 for (relocp = ss->new_relocs.data;
2274 relocp < ss->new_relocs.data + ss->new_relocs.size; relocp++) {
2275 asymbol *sym = *(*relocp)->sym_ptr_ptr;
2276 if (!(bfd_is_const_section(sym->section) &&
2277 sym == sym->section->symbol))
2278 sym->flags |= BSF_KEEP;
2282 static bool deleted_table_section_symbol(bfd *abfd, asymbol *sym)
2284 struct superbfd *sbfd = fetch_superbfd(abfd);
2285 if (bfd_is_const_section(sym->section))
2286 return false;
2287 struct supersect *ss = fetch_supersect(sbfd, sym->section);
2289 asymbol **symp;
2290 for (symp = ss->syms.data; symp < ss->syms.data + ss->syms.size; symp++) {
2291 if (sym == *symp)
2292 break;
2294 return symp >= ss->syms.data + ss->syms.size &&
2295 (sym->flags & BSF_SECTION_SYM) == 0;
2298 void filter_symbols(bfd *ibfd, bfd *obfd, struct asymbolp_vec *osyms,
2299 struct asymbolp_vec *isyms)
2301 asymbol **symp;
2302 struct superbfd *sbfd = fetch_superbfd(ibfd);
2303 for (symp = isyms->data; symp < isyms->data + isyms->size; symp++) {
2304 asymbol *sym = *symp;
2305 struct supersect *sym_ss = NULL;
2306 struct span *sym_span = NULL;
2307 if (!bfd_is_const_section(sym->section)) {
2308 sym_ss = fetch_supersect(sbfd, sym->section);
2309 sym_span = find_span(sym_ss, sym->value);
2312 if (mode("keep") && (sym->flags & BSF_GLOBAL) != 0 &&
2313 !(mode("keep-primary") && sym_span != NULL &&
2314 sym_span->new))
2315 sym->flags = (sym->flags & ~BSF_GLOBAL) | BSF_LOCAL;
2317 if (mode("finalize") && (sym->flags & BSF_GLOBAL) != 0)
2318 sym->flags = (sym->flags & ~BSF_GLOBAL) | BSF_LOCAL;
2320 bool keep = bfd_is_const_section(sym->section) ||
2321 (sym_ss->keep && (sym->flags & BSF_SECTION_SYM) != 0) ||
2322 (sym_span != NULL && sym_span->keep);
2323 if (bfd_is_und_section(sym->section) &&
2324 (sym->flags & BSF_KEEP) == 0)
2325 keep = false;
2326 if (bfd_is_abs_section(sym->section) &&
2327 (sym->flags & BSF_KEEP) == 0 &&
2328 (sym->flags & BSF_FILE) == 0)
2329 keep = false;
2330 if (deleted_table_section_symbol(ibfd, sym))
2331 keep = false;
2333 if (mode("keep-helper") && sym_ss != NULL &&
2334 sym_ss->type == SS_TYPE_EXPORT)
2335 keep = false;
2337 if (keep) {
2338 if (sym_ss != NULL && !sym_ss->keep) {
2339 err(sbfd, "Kept symbol %s in unkept section "
2340 "%s\n", sym->name, sym->section->name);
2341 DIE;
2343 *vec_grow(osyms, 1) = sym;
2348 void read_str_set(struct str_vec *strs)
2350 char *buf = NULL;
2351 size_t n = 0;
2352 assert(getline(&buf, &n, stdin) >= 0);
2353 vec_init(strs);
2354 char *saveptr;
2355 while (1) {
2356 char *str = strtok_r(buf, " \n", &saveptr);
2357 buf = NULL;
2358 if (str == NULL)
2359 break;
2360 *vec_grow(strs, 1) = str;
2364 bool str_in_set(const char *str, const struct str_vec *strs)
2366 const char **strp;
2367 for (strp = strs->data; strp < strs->data + strs->size; strp++) {
2368 if (strcmp(str, *strp) == 0)
2369 return true;
2371 return false;
2374 static bool is_table_section(const char *name, bool consider_other,
2375 bool consider_crc)
2377 struct supersect *tables_ss =
2378 fetch_supersect(offsets_sbfd,
2379 bfd_get_section_by_name(offsets_sbfd->abfd,
2380 ".ksplice_table_sections"));
2381 const struct table_section *ts;
2382 for (ts = tables_ss->contents.data;
2383 (void *)ts < tables_ss->contents.data + tables_ss->contents.size;
2384 ts++) {
2385 if (strcmp(name, read_string(tables_ss, &ts->sect)) == 0)
2386 return true;
2387 const char *osect_name = read_string(tables_ss,
2388 &ts->other_sect);
2389 if (consider_other && osect_name != NULL &&
2390 strcmp(name, osect_name) == 0)
2391 return true;
2392 const char *crc_name = read_string(tables_ss, &ts->crc_sect);
2393 if (consider_crc && crc_name != NULL &&
2394 strcmp(name, crc_name) == 0)
2395 return true;
2397 return false;
2400 const struct table_section *get_table_section(const char *name)
2402 struct supersect *tables_ss =
2403 fetch_supersect(offsets_sbfd,
2404 bfd_get_section_by_name(offsets_sbfd->abfd,
2405 ".ksplice_table_sections"));
2406 const struct table_section *ts;
2407 for (ts = tables_ss->contents.data;
2408 (void *)ts < tables_ss->contents.data + tables_ss->contents.size;
2409 ts++) {
2410 if (strcmp(name, read_string(tables_ss, &ts->sect)) == 0) {
2411 if (ts->entry_contents_size != 0)
2412 assert(align(ts->entry_contents_size,
2413 ts->entry_align) ==
2414 ts->entry_size);
2415 struct table_section *ns = malloc(sizeof(*ns));
2416 *ns = *ts;
2417 ns->sect = read_string(tables_ss, &ts->sect);
2418 ns->crc_sect = read_string(tables_ss, &ts->crc_sect);
2419 ns->other_sect =
2420 read_string(tables_ss, &ts->other_sect);
2421 return ns;
2424 return NULL;
2427 enum supersect_type supersect_type(struct supersect *ss)
2429 if (mode("finalize") &&
2430 strcmp(finalize_target, "vmlinux") == 0 &&
2431 (starts_with(ss->name, ".ksplice_relocs.exit") ||
2432 starts_with(ss->name, ".ksplice_sections.exit") ||
2433 starts_with(ss->name, ".ksplice_patches.exit")))
2434 return SS_TYPE_EXIT;
2435 if (starts_with(ss->name, ".ksplice_call"))
2436 return SS_TYPE_KSPLICE_CALL;
2437 if (starts_with(ss->name, ".ksplice_options"))
2438 return SS_TYPE_SPECIAL;
2439 if (starts_with(ss->name, ".ksplice"))
2440 return SS_TYPE_KSPLICE;
2442 if (starts_with(ss->name, ".init"))
2443 return SS_TYPE_IGNORED;
2444 if (starts_with(ss->name, ".security_initcall.init"))
2445 return SS_TYPE_IGNORED;
2446 if (starts_with(ss->name, ".con_initcall.init"))
2447 return SS_TYPE_IGNORED;
2448 if (starts_with(ss->name, ".x86cpuvendor.init"))
2449 return SS_TYPE_IGNORED;
2450 if (starts_with(ss->name, ".early_param.init"))
2451 return SS_TYPE_IGNORED;
2452 if (starts_with(ss->name, ".taglist.init"))
2453 return SS_TYPE_IGNORED;
2454 if (starts_with(ss->name, ".arch.info.init"))
2455 return SS_TYPE_IGNORED;
2456 if (starts_with(ss->name, ".proc.info.init"))
2457 return SS_TYPE_IGNORED;
2458 /* .pci_fixup_* sections really should be treated as global rodata
2459 referenced only from quirks.c */
2460 if (starts_with(ss->name, ".pci_fixup_"))
2461 return SS_TYPE_IGNORED;
2462 /* .builtin_fw sections are similar to .pci_fixup */
2463 if (starts_with(ss->name, ".builtin_fw"))
2464 return SS_TYPE_IGNORED;
2465 /* same for .tracedata */
2466 if (starts_with(ss->name, ".tracedata"))
2467 return SS_TYPE_IGNORED;
2468 if (starts_with(ss->name, ".debug"))
2469 return SS_TYPE_IGNORED;
2470 /* .eh_frame should probably be discarded, not ignored */
2471 if (starts_with(ss->name, ".eh_frame"))
2472 return SS_TYPE_IGNORED;
2473 if (config->ignore_devinit && starts_with(ss->name, ".devinit"))
2474 return SS_TYPE_IGNORED;
2475 if (config->ignore_meminit && starts_with(ss->name, ".meminit"))
2476 return SS_TYPE_IGNORED;
2477 if (config->ignore_cpuinit && starts_with(ss->name, ".cpuinit"))
2478 return SS_TYPE_IGNORED;
2479 if (config->ignore_devinit && starts_with(ss->name, ".devexit"))
2480 return SS_TYPE_IGNORED;
2481 if (config->ignore_meminit && starts_with(ss->name, ".memexit"))
2482 return SS_TYPE_IGNORED;
2483 if (config->ignore_cpuinit && starts_with(ss->name, ".cpuexit"))
2484 return SS_TYPE_IGNORED;
2485 if (starts_with(ss->name, ".vgetcpu_mode") ||
2486 starts_with(ss->name, ".jiffies") ||
2487 starts_with(ss->name, ".wall_jiffies") ||
2488 starts_with(ss->name, ".vxtime") ||
2489 starts_with(ss->name, ".sys_tz") ||
2490 starts_with(ss->name, ".sysctl_vsyscall") ||
2491 starts_with(ss->name, ".xtime") ||
2492 starts_with(ss->name, ".xtime_lock") ||
2493 starts_with(ss->name, ".vsyscall"))
2494 return SS_TYPE_IGNORED;
2495 if (starts_with(ss->name, ".vdso"))
2496 return SS_TYPE_IGNORED;
2498 if (starts_with(ss->name, ".exit.text"))
2499 return SS_TYPE_TEXT;
2500 if (starts_with(ss->name, ".exit.data"))
2501 return SS_TYPE_DATA;
2503 if (starts_with(ss->name, ".text") ||
2504 starts_with(ss->name, ".kernel.text") ||
2505 starts_with(ss->name, ".devinit.text") ||
2506 starts_with(ss->name, ".meminit.text") ||
2507 starts_with(ss->name, ".cpuinit.text") ||
2508 starts_with(ss->name, ".devexit.text") ||
2509 starts_with(ss->name, ".memexit.text") ||
2510 starts_with(ss->name, ".cpuexit.text") ||
2511 starts_with(ss->name, ".ref.text") ||
2512 starts_with(ss->name, ".spinlock.text") ||
2513 starts_with(ss->name, ".kprobes.text") ||
2514 starts_with(ss->name, ".sched.text") ||
2515 (mode("keep-helper") && starts_with(ss->name, ".fixup")))
2516 return SS_TYPE_TEXT;
2518 int n = -1;
2519 if (sscanf(ss->name, ".rodata.str%*u.%*u%n", &n) >= 0 &&
2520 n == strlen(ss->name))
2521 return ss->entsize == 1 ? SS_TYPE_STRING : SS_TYPE_RODATA;
2523 if (starts_with(ss->name, ".rodata") ||
2524 starts_with(ss->name, ".kernel.rodata") ||
2525 starts_with(ss->name, ".devinit.rodata") ||
2526 starts_with(ss->name, ".meminit.rodata") ||
2527 starts_with(ss->name, ".cpuinit.rodata") ||
2528 starts_with(ss->name, ".devexit.rodata") ||
2529 starts_with(ss->name, ".memexit.rodata") ||
2530 starts_with(ss->name, ".cpuexit.rodata") ||
2531 starts_with(ss->name, ".ref.rodata") ||
2532 starts_with(ss->name, "__markers_strings") ||
2533 starts_with(ss->name, "__bug_table") ||
2534 (mode("keep-helper") && starts_with(ss->name, "__ex_table")))
2535 return SS_TYPE_RODATA;
2537 if (starts_with(ss->name, ".bss"))
2538 return SS_TYPE_DATA;
2540 /* Ignore .data.percpu sections */
2541 if (starts_with(ss->name, ".data.percpu") ||
2542 starts_with(ss->name, ".kernel.data.percpu"))
2543 return SS_TYPE_IGNORED;
2544 if (starts_with(ss->name, ".data") ||
2545 starts_with(ss->name, ".kernel.data") ||
2546 starts_with(ss->name, ".devinit.data") ||
2547 starts_with(ss->name, ".cpuinit.data") ||
2548 starts_with(ss->name, ".meminit.data") ||
2549 starts_with(ss->name, ".devexit.data") ||
2550 starts_with(ss->name, ".memexit.data") ||
2551 starts_with(ss->name, ".cpuexit.data") ||
2552 starts_with(ss->name, ".ref.data") ||
2553 starts_with(ss->name, "__markers"))
2554 return SS_TYPE_DATA;
2556 /* We replace all the ksymtab strings, so delete them */
2557 if (strcmp(ss->name, "__ksymtab_strings") == 0)
2558 return SS_TYPE_STRING;
2559 if (starts_with(ss->name, "__ksymtab"))
2560 return SS_TYPE_EXPORT;
2562 if (is_table_section(ss->name, true, true))
2563 return SS_TYPE_SPECIAL;
2565 if (starts_with(ss->name, ".ARM."))
2566 return SS_TYPE_SPECIAL;
2568 if (starts_with(ss->name, ".note"))
2569 return SS_TYPE_IGNORED;
2570 if (starts_with(ss->name, ".comment"))
2571 return SS_TYPE_IGNORED;
2572 if (starts_with(ss->name, "__param"))
2573 return SS_TYPE_IGNORED;
2574 if (starts_with(ss->name, ".exitcall.exit"))
2575 return SS_TYPE_IGNORED;
2576 if (starts_with(ss->name, ".modinfo"))
2577 return SS_TYPE_IGNORED;
2579 return SS_TYPE_UNKNOWN;
2582 void initialize_supersect_types(struct superbfd *sbfd)
2584 asection *sect;
2585 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2586 struct supersect *ss = fetch_supersect(sbfd, sect);
2587 ss->type = supersect_type(ss);
2588 ss->orig_type = ss->type;
2589 if (ss->type == SS_TYPE_UNKNOWN) {
2590 err(sbfd, "Unknown section type: %s\n", ss->name);
2591 DIE;
2596 static void init_label_map(struct superbfd *sbfd)
2598 struct label_map *map;
2600 vec_init(&sbfd->maps);
2601 init_csyms(sbfd);
2602 init_callers(sbfd);
2604 struct symbol_hash csyms;
2605 symbol_hash_init(&csyms);
2607 asymbol **symp;
2608 for (symp = sbfd->syms.data;
2609 symp < sbfd->syms.data + sbfd->syms.size; symp++) {
2610 asymbol *csym = canonical_symbol(sbfd, *symp);
2611 if (csym == NULL)
2612 continue;
2613 char *key = strprintf("%p", csym);
2614 asymbol **csymp = symbol_hash_lookup(&csyms, key, TRUE);
2615 free(key);
2616 if (*csymp != NULL)
2617 continue;
2618 *csymp = csym;
2620 map = vec_grow(&sbfd->maps, 1);
2621 map->csym = csym;
2622 map->count = 0;
2623 map->label = symbol_label(sbfd, csym);
2626 struct label_mapp_hash label_maps;
2627 label_mapp_hash_init(&label_maps);
2628 for (map = sbfd->maps.data;
2629 map < sbfd->maps.data + sbfd->maps.size; map++) {
2630 struct label_map **mapp =
2631 label_mapp_hash_lookup(&label_maps, map->label, TRUE);
2632 if (*mapp == NULL) {
2633 *mapp = map;
2634 continue;
2637 struct label_map *first_map = *mapp;
2638 if (first_map->count == 0)
2639 first_map->label = strprintf("%s~%d", map->label, 0);
2640 map->label = strprintf("%s~%d", map->label, ++first_map->count);
2643 label_mapp_hash_init(&sbfd->maps_hash);
2644 for (map = sbfd->maps.data;
2645 map < sbfd->maps.data + sbfd->maps.size; map++) {
2646 char *key = strprintf("%p", map->csym);
2647 struct label_map **mapp =
2648 label_mapp_hash_lookup(&sbfd->maps_hash, key, TRUE);
2649 free(key);
2650 *mapp = map;
2651 map->orig_label = map->label;
2655 static const char *label_lookup(struct superbfd *sbfd, asymbol *sym)
2657 asymbol *csym = canonical_symbol(sbfd, sym);
2658 char *key = strprintf("%p", csym);
2659 struct label_map **mapp =
2660 label_mapp_hash_lookup(&sbfd->maps_hash, key, FALSE);
2661 free(key);
2662 if (mapp == NULL)
2663 DIE;
2664 return (*mapp)->label;
2667 static void print_label_changes(struct superbfd *sbfd)
2669 asection *sect;
2670 struct span *span;
2671 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2672 struct supersect *ss = fetch_supersect(sbfd, sect);
2673 for (span = ss->spans.data;
2674 span < ss->spans.data + ss->spans.size; span++) {
2675 if (strcmp(span->label, span->orig_label) != 0)
2676 debug1(sbfd, "Label change: %s -> %s\n",
2677 span->label, span->orig_label);
2682 static void label_map_set(struct superbfd *sbfd, const char *oldlabel,
2683 const char *label)
2685 struct label_map *map;
2686 for (map = sbfd->maps.data;
2687 map < sbfd->maps.data + sbfd->maps.size; map++) {
2688 if (strcmp(map->orig_label, oldlabel) == 0) {
2689 if (strcmp(map->orig_label, map->label) != 0 &&
2690 strcmp(map->label, label) != 0)
2691 DIE;
2692 map->label = label;
2693 return;
2696 DIE;
2699 static void change_initial_label(struct span *span, const char *label)
2701 struct superbfd *sbfd = span->ss->parent;
2702 span->label = label;
2703 span->orig_label = label;
2704 if (span->symbol) {
2705 asymbol *csym = canonical_symbol(sbfd, span->symbol);
2706 char *key = strprintf("%p", csym);
2707 struct label_map **mapp =
2708 label_mapp_hash_lookup(&sbfd->maps_hash, key, FALSE);
2709 free(key);
2710 assert(mapp);
2711 (*mapp)->label = span->label;
2712 (*mapp)->orig_label = span->orig_label;
2713 span->symbol = NULL;
2717 static void init_callers(struct superbfd *sbfd)
2719 string_hash_init(&sbfd->callers);
2720 asection *sect;
2721 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2722 struct supersect *ss = fetch_supersect(sbfd, sect);
2723 arelent **relocp;
2724 for (relocp = ss->relocs.data;
2725 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
2726 asymbol *sym = *(*relocp)->sym_ptr_ptr;
2727 unsigned long val =
2728 sym->value + get_reloc_offset(ss, *relocp, true);
2729 char *key = strprintf("%s+%lx", sym->section->name,
2730 val);
2731 const char **ret = string_hash_lookup(&sbfd->callers,
2732 key, TRUE);
2733 free(key);
2734 asymbol *csym = canonical_symbol(sbfd, sect->symbol);
2735 if (*ret != NULL)
2736 *ret = "*multiple_callers*";
2737 else if (static_local_symbol(sbfd, csym))
2738 *ret = static_local_symbol(sbfd, csym);
2739 else
2740 *ret = sect->name;
2745 static const char *find_caller(struct supersect *ss, asymbol *sym)
2747 char *key = strprintf("%s+%lx", sym->section->name,
2748 (unsigned long)sym->value);
2749 const char **ret = string_hash_lookup(&ss->parent->callers, key, FALSE);
2750 free(key);
2752 if (ret == NULL)
2753 return "*no_caller*";
2754 return *ret;
2757 static void init_csyms(struct superbfd *sbfd)
2759 asymbolpp_hash_init(&sbfd->csyms);
2761 asymbol **symp;
2762 for (symp = sbfd->syms.data; symp < sbfd->syms.data + sbfd->syms.size;
2763 symp++) {
2764 asymbol *sym = *symp;
2765 if ((sym->flags & BSF_DEBUGGING) != 0)
2766 continue;
2767 char *key = strprintf("%s+%lx", sym->section->name,
2768 (unsigned long)sym->value);
2769 asymbol ***csympp = asymbolpp_hash_lookup(&sbfd->csyms, key,
2770 TRUE);
2771 free(key);
2772 if (*csympp == NULL) {
2773 *csympp = symp;
2774 continue;
2776 asymbol *csym = **csympp;
2777 if ((csym->flags & BSF_GLOBAL) != 0)
2778 continue;
2779 if ((sym->flags & BSF_GLOBAL) != 0)
2780 *csympp = symp;
2784 static asymbol **symbolp_scan(struct supersect *ss, bfd_vma value)
2786 char *key = strprintf("%s+%lx", ss->name, (unsigned long)value);
2787 asymbol ***csympp =
2788 asymbolpp_hash_lookup(&ss->parent->csyms, key, FALSE);
2789 free(key);
2790 if (csympp != NULL)
2791 return *csympp;
2793 /* For section symbols of sections containing no symbols, return the
2794 section symbol that relocations are generated against */
2795 if (value == 0)
2796 return &ss->symbol;
2797 return NULL;
2800 static asymbol **canonical_symbolp(struct superbfd *sbfd, asymbol *sym)
2802 if (bfd_is_const_section(sym->section)) {
2803 asymbol **csymp;
2804 for (csymp = sbfd->syms.data;
2805 csymp < sbfd->syms.data + sbfd->syms.size; csymp++) {
2806 if (sym == *csymp)
2807 return csymp;
2809 return NULL;
2811 return symbolp_scan(fetch_supersect(sbfd, sym->section), sym->value);
2814 static asymbol *canonical_symbol(struct superbfd *sbfd, asymbol *sym)
2816 if (bfd_is_const_section(sym->section))
2817 return sym;
2818 asymbol **symp = canonical_symbolp(sbfd, sym);
2819 return symp != NULL ? *symp : NULL;
2822 static char *static_local_symbol(struct superbfd *sbfd, asymbol *sym)
2824 struct supersect *ss = fetch_supersect(sbfd, sym->section);
2825 if ((sym->flags & BSF_LOCAL) == 0 || (sym->flags & BSF_OBJECT) == 0)
2826 return NULL;
2827 char *dot = strrchr(sym->name, '.');
2828 if (dot == NULL || dot[1 + strspn(dot + 1, "0123546789")] != '\0')
2829 return NULL;
2830 char *basename = strndup(sym->name, dot - sym->name);
2832 /* Handle C.123.12345 symbols */
2833 dot = strrchr(basename, '.');
2834 if (dot != NULL && dot[1 + strspn(dot + 1, "0123546789")] == '\0')
2835 basename = strndup(basename, dot - basename);
2836 const char *caller;
2837 if (strcmp(basename, "__func__") == 0 ||
2838 strcmp(basename, "__PRETTY_FUNCTION__") == 0)
2839 caller = (const char *)ss->contents.data + sym->value;
2840 else
2841 caller = find_caller(ss, sym);
2842 return strprintf("%s<%s>", basename, caller);
2845 static char *symbol_label(struct superbfd *sbfd, asymbol *sym)
2847 const char *filename = sbfd->abfd->filename;
2848 char *c = strstr(filename, ".KSPLICE");
2849 int flen = (c == NULL ? strlen(filename) : c - filename);
2851 char *label;
2852 if (bfd_is_und_section(sym->section) || (sym->flags & BSF_GLOBAL) != 0) {
2853 label = strdup(sym->name);
2854 } else if (bfd_is_const_section(sym->section)) {
2855 label = strprintf("%s<%.*s>", sym->name, flen, filename);
2856 } else {
2857 asymbol *gsym = canonical_symbol(sbfd, sym);
2859 if (gsym == NULL)
2860 label = strprintf("%s+%lx<%.*s>",
2861 sym->section->name,
2862 (unsigned long)sym->value,
2863 flen, filename);
2864 else if ((gsym->flags & BSF_GLOBAL) != 0)
2865 label = strdup(gsym->name);
2866 else if (static_local_symbol(sbfd, gsym))
2867 label = strprintf("%s+%lx<%.*s>",
2868 static_local_symbol(sbfd, gsym),
2869 (unsigned long)sym->value,
2870 flen, filename);
2871 else
2872 label = strprintf("%s<%.*s>",
2873 gsym->name, flen, filename);
2876 return label;
2879 static void keep_span(struct span *span)
2881 span->keep = true;
2882 span->ss->keep = true;
2885 static struct span *new_span(struct supersect *ss, bfd_vma start, bfd_vma size)
2887 struct span *span = vec_grow(&ss->spans, 1);
2888 span->size = size;
2889 span->contents_size = size;
2890 span->start = start;
2891 span->ss = ss;
2892 span->keep = true;
2893 span->new = false;
2894 span->patch = false;
2895 span->bugpatch = false;
2896 span->datapatch = false;
2897 span->precallable = starts_with(ss->name, ".ksplice_call_pre_apply") ||
2898 starts_with(ss->name, ".ksplice_call_check_apply") ||
2899 starts_with(ss->name, ".ksplice_call_fail_apply") ||
2900 starts_with(ss->name, ".ksplice_call_post_remove");
2901 span->match = NULL;
2902 span->shift = 0;
2903 asymbol **symp = symbolp_scan(ss, span->start);
2904 if (symp != NULL) {
2905 span->symbol = *symp;
2906 span->label = label_lookup(ss->parent, span->symbol);
2907 } else {
2908 span->symbol = NULL;
2909 const char *label = label_lookup(ss->parent, ss->symbol);
2910 if (span->start != 0)
2911 span->label = strprintf("%s<span:%lx>", label,
2912 (unsigned long)span->start);
2913 else
2914 span->label = label;
2916 span->orig_label = span->label;
2917 return span;
2920 static void initialize_string_spans(struct supersect *ss)
2922 const char *str;
2923 for (str = ss->contents.data;
2924 (void *)str < ss->contents.data + ss->contents.size;) {
2925 bfd_vma start = (unsigned long)str -
2926 (unsigned long)ss->contents.data;
2927 bfd_vma size = strlen(str) + 1;
2928 bfd_vma contents_size = size;
2929 while ((start + size) % (1 << ss->alignment) != 0 &&
2930 start + size < ss->contents.size) {
2931 /* Some string sections, like __ksymtab_strings, only
2932 align some strings with the declared alignment */
2933 if (str[size] != '\0')
2934 break;
2935 size++;
2937 struct span *span = new_span(ss, start, size);
2938 span->contents_size = contents_size;
2939 str += size;
2943 static int compare_ulongs(const void *va, const void *vb)
2945 const unsigned long *a = va, *b = vb;
2946 return *a - *b;
2949 static void initialize_table_spans(struct superbfd *sbfd,
2950 struct table_section *s)
2952 asection *isection = bfd_get_section_by_name(sbfd->abfd, s->sect);
2953 if (isection == NULL)
2954 return;
2955 struct supersect *ss = fetch_supersect(sbfd, isection);
2956 if (ss->alignment < ffs(s->entry_align) - 1)
2957 ss->alignment = ffs(s->entry_align) - 1;
2959 asection *other_sect = NULL;
2960 if (s->other_sect != NULL)
2961 other_sect = bfd_get_section_by_name(sbfd->abfd, s->other_sect);
2962 struct supersect *other_ss = NULL;
2963 if (other_sect != NULL)
2964 other_ss = fetch_supersect(sbfd, other_sect);
2966 asection *crc_sect = NULL;
2967 if (s->crc_sect != NULL)
2968 crc_sect = bfd_get_section_by_name(sbfd->abfd, s->crc_sect);
2969 struct supersect *crc_ss = NULL;
2970 if (crc_sect != NULL)
2971 crc_ss = fetch_supersect(sbfd, crc_sect);
2973 struct ulong_vec offsets;
2974 vec_init(&offsets);
2976 void *entry;
2977 for (entry = ss->contents.data;
2978 entry < ss->contents.data + ss->contents.size;
2979 entry += s->entry_size) {
2980 struct span *span = new_span(ss, addr_offset(ss, entry),
2981 s->entry_size);
2982 if (s->entry_contents_size != 0)
2983 span->contents_size = s->entry_contents_size;
2984 if ((span->symbol == NULL ||
2985 (span->symbol->flags & BSF_SECTION_SYM) != 0) &&
2986 s->has_addr) {
2987 arelent *reloc = find_reloc(ss, entry + s->addr_offset);
2988 assert(reloc);
2989 struct span *target_span = reloc_target_span(ss, reloc);
2990 assert(target_span);
2991 asymbol *sym = *reloc->sym_ptr_ptr;
2992 unsigned long val = get_reloc_offset(ss, reloc, true) +
2993 sym->value - (target_span->start +
2994 target_span->shift);
2995 char *label = strprintf("%s<target:%s+%lx>", ss->name,
2996 target_span->label, val);
2997 change_initial_label(span, label);
3000 if (other_sect != NULL) {
3001 asymbol *sym;
3002 bfd_vma offset = read_reloc(ss, entry + s->other_offset,
3003 sizeof(void *), &sym);
3004 if (sym->section == other_sect) {
3005 assert(offset >= 0 &&
3006 offset < other_ss->contents.size);
3007 *vec_grow(&offsets, 1) = offset;
3011 if (crc_sect != NULL)
3012 new_span(crc_ss, addr_offset(ss, entry) / s->entry_size
3013 * s->crc_size, s->crc_size);
3015 if (ss->type == SS_TYPE_EXPORT) {
3016 const char *symname = read_string(ss, entry +
3017 s->other_offset);
3018 char *label = strprintf("%s:%s", ss->name, symname);
3019 change_initial_label(span, label);
3023 if (other_sect == NULL)
3024 return;
3026 *vec_grow(&offsets, 1) = 0;
3027 qsort(offsets.data, offsets.size, sizeof(*offsets.data),
3028 compare_ulongs);
3029 *vec_grow(&offsets, 1) = other_ss->contents.size;
3031 unsigned long *off;
3032 for (off = offsets.data; off < offsets.data + offsets.size - 1; off++) {
3033 if (*off != *(off + 1))
3034 new_span(other_ss, *off, *(off + 1) - *off);
3038 static void initialize_table_section_spans(struct superbfd *sbfd)
3040 struct supersect *tables_ss =
3041 fetch_supersect(offsets_sbfd,
3042 bfd_get_section_by_name(offsets_sbfd->abfd,
3043 ".ksplice_table_sections"));
3044 const struct table_section *ts;
3045 struct table_section s;
3046 for (ts = tables_ss->contents.data;
3047 (void *)ts < tables_ss->contents.data + tables_ss->contents.size;
3048 ts++) {
3049 s = *ts;
3050 s.sect = read_string(tables_ss, &ts->sect);
3051 s.other_sect = read_string(tables_ss, &ts->other_sect);
3052 s.crc_sect = read_string(tables_ss, &ts->crc_sect);
3053 initialize_table_spans(sbfd, &s);
3057 static void initialize_ksplice_call_spans(struct supersect *ss)
3059 arelent **relocp;
3060 for (relocp = ss->relocs.data;
3061 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
3062 arelent *reloc = *relocp;
3063 new_span(ss, reloc->address, bfd_get_reloc_size(reloc->howto));
3064 /* the span labels should already be unique */
3068 static void initialize_spans(struct superbfd *sbfd)
3070 asection *sect;
3071 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
3072 if (is_table_section(sect->name, true, true) && mode("keep"))
3073 continue;
3075 struct supersect *ss = fetch_supersect(sbfd, sect);
3076 if (ss->type == SS_TYPE_STRING)
3077 initialize_string_spans(ss);
3078 else if (ss->type == SS_TYPE_KSPLICE_CALL)
3079 initialize_ksplice_call_spans(ss);
3080 else
3081 new_span(ss, 0, ss->contents.size);
3083 if (mode("keep"))
3084 initialize_table_section_spans(sbfd);
3087 /* Returns the span pointed to by the relocation at span->start + offset */
3088 static struct span *span_offset_target_span(struct span *span, int offset)
3090 void *entry = span->ss->contents.data + span->start;
3091 arelent *reloc = find_reloc(span->ss, entry + offset);
3092 if (reloc == NULL)
3093 return NULL;
3094 struct span *sym_span = reloc_target_span(span->ss, reloc);
3095 if (sym_span == NULL)
3096 return NULL;
3097 return sym_span;
3100 struct span *reloc_target_span(struct supersect *ss, arelent *reloc)
3102 asymbol *sym_ptr = *reloc->sym_ptr_ptr;
3103 if (bfd_is_const_section(sym_ptr->section))
3104 return NULL;
3106 bfd_vma addend = get_reloc_offset(ss, reloc, true) + sym_ptr->value;
3107 struct supersect *sym_ss =
3108 fetch_supersect(ss->parent, sym_ptr->section);
3109 struct span *span, *target_span = sym_ss->spans.data;
3110 for (span = sym_ss->spans.data;
3111 span < sym_ss->spans.data + sym_ss->spans.size; span++) {
3112 if (addend >= span->start && addend < span->start + span->size)
3113 target_span = span;
3115 return target_span;
3118 struct span *find_span(struct supersect *ss, bfd_size_type address)
3120 struct span *span;
3121 for (span = ss->spans.data; span < ss->spans.data + ss->spans.size;
3122 span++) {
3123 if (address >= span->start &&
3124 address < span->start + span->size)
3125 return span;
3127 /* Deal with empty BSS sections */
3128 if (ss->contents.size == 0 && ss->spans.size > 0)
3129 return ss->spans.data;
3130 return NULL;
3133 void compute_span_shifts(struct superbfd *sbfd)
3135 asection *sect;
3136 struct span *span;
3137 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
3138 struct supersect *ss = fetch_supersect(sbfd, sect);
3139 if (!ss->keep)
3140 continue;
3141 bfd_size_type offset = 0;
3142 for (span = ss->spans.data;
3143 span < ss->spans.data + ss->spans.size; span++) {
3144 if (!span->keep)
3145 continue;
3146 span->shift = offset - span->start;
3147 offset += span->size;
3152 void remove_unkept_spans(struct superbfd *sbfd)
3154 asection *sect;
3155 struct span *span;
3156 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
3157 struct supersect *ss = fetch_supersect(sbfd, sect);
3158 delete_obsolete_relocs(ss);
3159 struct arelentp_vec orig_relocs;
3160 vec_move(&orig_relocs, &ss->relocs);
3161 arelent **relocp, *reloc;
3162 for (relocp = orig_relocs.data;
3163 relocp < orig_relocs.data + orig_relocs.size; relocp++) {
3164 reloc = *relocp;
3165 asymbol *sym = *reloc->sym_ptr_ptr;
3166 span = reloc_target_span(ss, reloc);
3167 if ((span != NULL && span->keep && span->shift == 0) ||
3168 bfd_is_const_section(sym->section)) {
3169 *vec_grow(&ss->relocs, 1) = reloc;
3170 continue;
3172 struct supersect *sym_ss =
3173 fetch_supersect(sbfd, sym->section);
3174 if (span != NULL && (sym->flags & BSF_SECTION_SYM) == 0
3175 && find_span(sym_ss, sym->value) != span) {
3176 err(sbfd, "Spans for symbol %s and relocation "
3177 "target do not match in sect %s\n",
3178 sym->name, sym_ss->name);
3179 DIE;
3181 if (span != NULL && span->keep) {
3182 arelent *new_reloc = malloc(sizeof(*new_reloc));
3183 *new_reloc = *reloc;
3184 new_reloc->addend =
3185 get_reloc_offset(ss, reloc, false);
3186 new_reloc->addend += span->shift;
3187 *vec_grow(&ss->new_relocs, 1) = new_reloc;
3192 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
3193 struct supersect *ss = fetch_supersect(sbfd, sect), orig_ss;
3194 if (!ss->keep)
3195 continue;
3196 supersect_move(&orig_ss, ss);
3197 vec_init(&ss->spans);
3198 for (span = orig_ss.spans.data;
3199 span < orig_ss.spans.data + orig_ss.spans.size; span++) {
3200 if (!span->keep)
3201 continue;
3202 struct span *new_span = vec_grow(&ss->spans, 1);
3203 *new_span = *span;
3204 new_span->start = span->start + span->shift;
3205 new_span->shift = 0;
3206 sect_copy(ss, sect_do_grow(ss, 1, span->size, 1),
3207 &orig_ss, orig_ss.contents.data + span->start,
3208 span->size);
3213 static void init_objmanip_superbfd(struct superbfd *sbfd)
3215 init_label_map(sbfd);
3216 initialize_supersect_types(sbfd);
3217 initialize_spans(sbfd);
3218 load_options(sbfd);
3221 void mangle_section_name(struct superbfd *sbfd, const char *name)
3223 asection *sect = bfd_get_section_by_name(sbfd->abfd, name);
3224 if (sect == NULL)
3225 return;
3226 struct supersect *ss = fetch_supersect(sbfd, sect);
3227 ss->name = strprintf(".ksplice_pre.%s", ss->name);
3230 static void write_bugline_patches(struct superbfd *sbfd)
3232 const struct table_section *ts = get_table_section("__bug_table");
3233 asection *sect = bfd_get_section_by_name(sbfd->abfd, "__bug_table");
3234 if (sect == NULL)
3235 return;
3236 struct supersect *ss = fetch_supersect(sbfd, sect);
3237 assert(ts != NULL);
3239 void *entry;
3240 for (entry = ss->contents.data;
3241 entry < ss->contents.data + ss->contents.size;
3242 entry += ts->entry_size) {
3243 struct span *span = find_span(ss, addr_offset(ss, entry));
3244 assert(span != NULL);
3245 if (!span->bugpatch)
3246 continue;
3247 arelent *reloc = find_reloc(ss, entry + ts->addr_offset);
3248 assert(reloc != NULL);
3249 asymbol *sym = *reloc->sym_ptr_ptr;
3250 assert(!bfd_is_const_section(sym->section));
3252 struct supersect *kpatch_ss =
3253 make_section(sbfd, ".ksplice_patches%s",
3254 sym->section->name);
3255 struct ksplice_patch *kpatch =
3256 sect_grow(kpatch_ss, 1, struct ksplice_patch);
3257 write_ksplice_patch_reloc
3258 (kpatch_ss, sym->section->name, &kpatch->oldaddr,
3259 sizeof(kpatch->oldaddr), span->label, ts->other_offset);
3261 unsigned short *line =
3262 write_patch_storage(kpatch_ss, kpatch, sizeof(*line), NULL);
3263 *line = *(unsigned short *)(entry + ts->other_offset);
3264 kpatch->type = KSPLICE_PATCH_BUGLINE;
3268 void *write_patch_storage(struct supersect *ss, struct ksplice_patch *kpatch,
3269 size_t size, struct supersect **data_ssp)
3271 struct supersect *data_ss = make_section(ss->parent,
3272 ".ksplice_patch_data");
3273 char *saved = sect_do_grow(data_ss, 1, size, 1);
3274 write_reloc(ss, &kpatch->saved, &data_ss->symbol,
3275 addr_offset(data_ss, saved));
3276 char *data = sect_do_grow(data_ss, 1, size, 1);
3277 write_reloc(ss, &kpatch->contents, &data_ss->symbol,
3278 addr_offset(data_ss, data));
3279 kpatch->size = size;
3280 if (data_ssp != NULL)
3281 *data_ssp = data_ss;
3282 return data;