foreach_symbol_pair: Skip debugging symbols.
[ksplice.git] / objmanip.c
blobe355a557a76c3309e3ff04ac41251ca7f0f993ce
1 /* This file is based in part on objcopy.c from GNU Binutils v2.17.
3 * Copyright (C) 1991-2006 Free Software Foundation, Inc.
4 * Copyright (C) 2007-2009 Ksplice, Inc.
5 * Authors: Jeff Arnold, Anders Kaseorg, Tim Abbott
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License, version 2.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
18 * 02110-1301, USA.
21 /* objmanip performs various object file manipulations for Ksplice. Its first
22 * two arguments are always an input object file and an output object file.
24 * - keep-new-code: "objmanip <post.o> <out.o> keep-new-code <pre.o> <kid>"
26 * This mode prepares the object file to be installed as a ksplice update. The
27 * kid argument is the ksplice id string for the ksplice update being built.
29 * - keep-old-code: "objmanip <pre.o> <out.o> keep-old-code"
31 * This mode prepares the object file to be used for run-pre matching. This
32 * involves replacing all ELF relocations with ksplice relocations and
33 * writing ksplice_section structures for each ELF text or data section.
35 * - rmsyms mode: "objmanip <in.o> <out.o> rmsyms
37 * In this mode, any ELF relocations involving the list of symbol names given on
38 * standard input are replaced with ksplice relocations. This is used only
39 * for KSPLICE_STANDALONE.
41 * - finalize mode: "objmanip <in.o> <out.o> finalize"
43 * In this mode, any ELF relocations to undefined symbols are replaced with
44 * ksplice relocations.
47 /* Always define KSPLICE_STANDALONE, even if you're using integrated Ksplice.
48 objmanip won't compile without it. */
49 #define KSPLICE_STANDALONE
51 #define _GNU_SOURCE
52 #include "objcommon.h"
53 #include "kmodsrc/ksplice.h"
54 #include "kmodsrc/offsets.h"
55 #include "ksplice-patch/ksplice-patch.h"
56 #include <stdint.h>
57 #include <stdarg.h>
58 #include <stdlib.h>
59 #include <stdio.h>
60 #include <limits.h>
62 #define KSPLICE_SYMBOL_STR "KSPLICE_SYMBOL_"
64 #define symbol_init(sym) *(sym) = (asymbol *)NULL
65 DEFINE_HASH_TYPE(asymbol *, symbol_hash, symbol_hash_init, symbol_hash_free,
66 symbol_hash_lookup, symbol_init);
68 DECLARE_VEC_TYPE(const char *, str_vec);
70 DECLARE_VEC_TYPE(unsigned long, ulong_vec);
72 #define bool_init(b) *(b) = false
73 DEFINE_HASH_TYPE(bool, bool_hash, bool_hash_init, bool_hash_free,
74 bool_hash_lookup, bool_init);
76 #define ulong_init(x) *(x) = 0
77 DEFINE_HASH_TYPE(unsigned long, ulong_hash, ulong_hash_init,
78 ulong_hash_free, ulong_hash_lookup, ulong_init);
80 void do_keep_new_code(struct superbfd *isbfd, const char *pre);
81 void do_keep_old_code(struct superbfd *isbfd);
82 void do_finalize(struct superbfd *isbfd);
83 void do_rmsyms(struct superbfd *isbfd);
85 bool relocs_equal(struct supersect *old_src_ss, struct supersect *new_src_ss,
86 arelent *old_reloc, arelent *new_reloc);
87 bfd_vma non_dst_mask(struct supersect *ss, arelent *reloc);
88 bool all_relocs_equal(struct span *old_span, struct span *new_span);
89 static bool part_of_reloc(struct supersect *ss, unsigned long addr);
90 static bool nonrelocs_equal(struct span *old_span, struct span *new_span);
91 static void handle_section_symbol_renames(struct superbfd *oldsbfd,
92 struct superbfd *newsbfd);
93 static void compute_entry_points(struct superbfd *sbfd);
94 static void copy_patched_entry_points(struct superbfd *oldsbfd,
95 struct superbfd *newsbfd);
97 enum supersect_type supersect_type(struct supersect *ss);
98 void initialize_supersect_types(struct superbfd *sbfd);
99 static void initialize_spans(struct superbfd *sbfd);
100 static void initialize_string_spans(struct supersect *ss);
101 static void initialize_table_spans(struct superbfd *sbfd,
102 struct table_section *s);
103 static void initialize_table_section_spans(struct superbfd *sbfd);
104 static void initialize_ksplice_call_spans(struct supersect *ss);
105 struct span *reloc_target_span(struct supersect *ss, arelent *reloc);
106 static struct span *span_offset_target_span(struct span *span, int offset);
107 static bfd_vma reloc_target_offset(struct supersect *ss, arelent *reloc);
108 struct span *find_span(struct supersect *ss, bfd_size_type address);
109 void remove_unkept_spans(struct superbfd *sbfd);
110 void compute_span_shifts(struct superbfd *sbfd);
111 static struct span *new_span(struct supersect *ss, bfd_vma start, bfd_vma size);
112 static bool is_table_section(const char *name, bool consider_other,
113 bool consider_crc);
114 const struct table_section *get_table_section(const char *name);
115 void mangle_section_name(struct superbfd *sbfd, const char *name);
117 void rm_relocs(struct superbfd *isbfd);
118 void rm_some_relocs(struct supersect *ss);
119 void write_ksplice_reloc(struct supersect *ss, arelent *orig_reloc);
120 static void write_ksplice_reloc_howto(struct supersect *ss, const
121 struct ksplice_reloc_howto *const *addr,
122 reloc_howto_type *howto,
123 enum ksplice_reloc_howto_type type);
124 static void write_ksplice_date_reloc(struct supersect *ss, unsigned long offset,
125 const char *str,
126 enum ksplice_reloc_howto_type type);
127 static void write_ksplice_patch_reloc(struct supersect *ss,
128 const char *sectname, unsigned long *addr,
129 bfd_size_type size, const char *label,
130 long addend);
131 static void write_ksplice_nonreloc_howto(struct supersect *ss,
132 const struct ksplice_reloc_howto
133 *const *addr,
134 enum ksplice_reloc_howto_type type,
135 int size);
136 static void write_date_relocs(struct superbfd *sbfd, const char *str,
137 enum ksplice_reloc_howto_type type);
138 static void write_table_relocs(struct superbfd *sbfd, const char *sectname,
139 enum ksplice_reloc_howto_type type);
140 static void write_ksplice_table_reloc(struct supersect *ss,
141 unsigned long address,
142 const char *label,
143 enum ksplice_reloc_howto_type type);
144 void load_ksplice_symbol_offsets(struct superbfd *sbfd);
145 void write_canary(struct supersect *ss, int offset, bfd_size_type size,
146 bfd_vma dst_mask);
147 static void write_ksplice_section(struct span *span);
148 void write_ksplice_patches(struct superbfd *sbfd, struct span *span);
149 void write_ksplice_patch(struct superbfd *sbfd, struct span *span,
150 const char *label, long offset);
151 void *write_patch_storage(struct supersect *ss, struct ksplice_patch *patch,
152 size_t size, struct supersect **data_ssp);
153 void write_ksplice_deleted_patch(struct superbfd *sbfd, const char *name,
154 const char *label, const char *sectname);
155 static void write_bugline_patches(struct superbfd *sbfd);
156 asymbol **make_undefined_symbolp(struct superbfd *sbfd, const char *name);
157 void filter_table_sections(struct superbfd *isbfd);
158 void filter_table_section(struct superbfd *sbfd, const struct table_section *s);
159 void keep_referenced_sections(struct superbfd *sbfd);
160 void mark_precallable_spans(struct superbfd *sbfd);
161 bfd_boolean copy_object(bfd *ibfd, bfd *obfd);
162 void setup_section(bfd *ibfd, asection *isection, void *obfdarg);
163 static void setup_new_section(bfd *obfd, struct supersect *ss);
164 static void write_section(bfd *obfd, asection *osection, void *arg);
165 static void delete_obsolete_relocs(struct supersect *ss);
166 void mark_symbols_used_in_relocations(bfd *abfd, asection *isection,
167 void *ignored);
168 static void ss_mark_symbols_used_in_relocations(struct supersect *ss);
169 void filter_symbols(bfd *ibfd, bfd *obfd, struct asymbolp_vec *osyms,
170 struct asymbolp_vec *isyms);
171 static bool deleted_table_section_symbol(bfd *abfd, asymbol *sym);
172 struct supersect *__attribute((format(printf, 2, 3)))
173 make_section(struct superbfd *sbfd, const char *fmt, ...);
174 void __attribute__((format(printf, 3, 4)))
175 write_string(struct supersect *ss, const char **addr, const char *fmt, ...);
176 void write_ksplice_export(struct superbfd *sbfd, struct span *span, bool del);
177 void write_reloc(struct supersect *ss, const void *addr, asymbol **symp,
178 bfd_vma offset);
179 arelent *create_reloc(struct supersect *ss, const void *addr, asymbol **symp,
180 bfd_vma offset);
181 static void foreach_symbol_pair(struct superbfd *oldsbfd, struct superbfd *newsbfd,
182 void (*fn)(struct span *old_span,
183 asymbol *oldsym,
184 struct span *new_span,
185 asymbol *newsym));
186 static void check_global_symbols(struct span *old_span, asymbol *oldsym,
187 struct span *new_span, asymbol *newsym);
188 static void match_global_symbols(struct span *old_span, asymbol *oldsym,
189 struct span *new_span, asymbol *newsym);
190 static void match_symbol_spans(struct span *old_span, asymbol *oldsym,
191 struct span *new_span, asymbol *newsym);
192 static void match_table_spans(struct span *old_span, struct span *new_span);
194 static struct span *get_crc_span(struct span *span,
195 const struct table_section *ts);
196 static void foreach_span_pair(struct superbfd *oldsbfd,
197 struct superbfd *newsbfd,
198 void (*fn)(struct span *old_span,
199 struct span *new_span));
200 static void match_spans_by_label(struct span *old_span, struct span *new_span);
201 static void match_string_spans(struct span *old_span, struct span *new_span);
202 static void mark_new_spans(struct superbfd *sbfd);
203 static void handle_deleted_spans(struct superbfd *oldsbfd,
204 struct superbfd *newsbfd);
205 static void unmatch_addr_spans(struct span *old_span, struct span *new_span,
206 const struct table_section *ts);
207 static void compare_matched_spans(struct superbfd *newsbfd);
208 static void compare_spans(struct span *old_span, struct span *new_span);
209 static void update_nonzero_offsets(struct superbfd *sbfd);
210 static void handle_nonzero_offset_relocs(struct supersect *ss);
211 static void keep_span(struct span *span);
213 static void init_objmanip_superbfd(struct superbfd *sbfd);
214 static const char *label_lookup(struct superbfd *sbfd, asymbol *sym);
215 static void label_map_set(struct superbfd *sbfd, const char *oldlabel,
216 const char *label);
217 static void print_label_changes(struct superbfd *sbfd);
218 static void init_label_map(struct superbfd *sbfd);
219 static void change_initial_label(struct span *span, const char *label);
220 static asymbol **symbolp_scan(struct supersect *ss, bfd_vma value);
221 static void init_csyms(struct superbfd *sbfd);
222 static void init_callers(struct superbfd *sbfd);
223 static asymbol *canonical_symbol(struct superbfd *sbfd, asymbol *sym);
224 static asymbol **canonical_symbolp(struct superbfd *sbfd, asymbol *sym);
225 static char *static_local_symbol(struct superbfd *sbfd, asymbol *sym);
226 static char *symbol_label(struct superbfd *sbfd, asymbol *sym);
228 int verbose = 0;
229 #define debug_(sbfd, level, fmt, ...) \
230 do { \
231 if (verbose >= (level)) \
232 printf("%s: " fmt, (sbfd)->abfd->filename, \
233 ## __VA_ARGS__); \
234 } while (0)
235 #define debug0(sbfd, fmt, ...) debug_(sbfd, 0, fmt, ## __VA_ARGS__)
236 #define debug1(sbfd, fmt, ...) debug_(sbfd, 1, fmt, ## __VA_ARGS__)
237 #define err(sbfd, fmt, ...) \
238 do { \
239 fprintf(stderr, "%s: " fmt, (sbfd)->abfd->filename, \
240 ## __VA_ARGS__); \
241 } while (0)
243 struct str_vec delsects;
244 struct asymbolp_vec extract_syms;
245 bool changed;
247 struct ksplice_config *config;
249 const char *modestr, *kid, *finalize_target = NULL;
250 bool write_output = true;
252 struct superbfd *offsets_sbfd = NULL;
254 #define mode(str) strstarts(modestr, str)
256 DECLARE_VEC_TYPE(unsigned long, addr_vec);
257 DEFINE_HASH_TYPE(struct addr_vec, addr_vec_hash,
258 addr_vec_hash_init, addr_vec_hash_free, addr_vec_hash_lookup,
259 vec_init);
260 struct addr_vec_hash system_map;
262 struct bool_hash system_map_written;
263 struct ulong_hash ksplice_symbol_offset;
264 struct ulong_hash ksplice_howto_offset;
265 struct ulong_hash ksplice_string_offset;
267 void load_system_map()
269 const char *config_dir = getenv("KSPLICE_CONFIG_DIR");
270 assert(config_dir);
271 FILE *fp = fopen(strprintf("%s/System.map", config_dir), "r");
272 assert(fp);
273 addr_vec_hash_init(&system_map);
274 unsigned long addr;
275 char type;
276 char *sym;
277 while (fscanf(fp, "%lx %c %as\n", &addr, &type, &sym) == 3)
278 *vec_grow(addr_vec_hash_lookup(&system_map, sym, TRUE),
279 1) = addr;
280 fclose(fp);
283 void load_ksplice_symbol_offsets(struct superbfd *sbfd)
285 asection *sect = bfd_get_section_by_name(sbfd->abfd,
286 ".ksplice_symbols");
287 if (sect == NULL)
288 return;
289 struct supersect *ss = fetch_supersect(sbfd, sect);
291 struct ksplice_symbol *ksym;
292 for (ksym = ss->contents.data;
293 (void *)ksym < ss->contents.data + ss->contents.size; ksym++) {
294 const char *label = read_string(ss, &ksym->label);
295 unsigned long *ksymbol_offp =
296 ulong_hash_lookup(&ksplice_symbol_offset, label, TRUE);
297 *ksymbol_offp = addr_offset(ss, ksym);
301 void load_offsets()
303 char *kmodsrc = getenv("KSPLICE_KMODSRC");
304 assert(kmodsrc != NULL);
305 bfd *offsets_bfd = bfd_openr(strprintf("%s/offsets.o", kmodsrc), NULL);
306 assert(offsets_bfd != NULL);
307 char **matching;
308 assert(bfd_check_format_matches(offsets_bfd, bfd_object, &matching));
309 offsets_sbfd = fetch_superbfd(offsets_bfd);
311 asection *config_sect = bfd_get_section_by_name(offsets_sbfd->abfd,
312 ".ksplice_config");
313 struct supersect *config_ss =
314 fetch_supersect(offsets_sbfd, config_sect);
316 config = config_ss->contents.data;
319 void load_options(struct superbfd *sbfd)
321 asection *sect = bfd_get_section_by_name(sbfd->abfd,
322 ".ksplice_options");
323 if (sect == NULL)
324 return;
325 struct supersect *ss = fetch_supersect(sbfd, sect);
326 const struct ksplice_option *opt;
327 for (opt = ss->contents.data;
328 (void *)opt < ss->contents.data + ss->contents.size; opt++) {
329 if (opt->type == KSPLICE_OPTION_ASSUME_RODATA) {
330 arelent *reloc = find_reloc(ss, &opt->target);
331 assert(reloc != NULL);
332 struct span *span = reloc_target_span(ss, reloc);
333 assert(span != NULL);
334 assert(span->ss->type == SS_TYPE_DATA);
335 assert(span->start == 0 &&
336 span->size == span->ss->contents.size);
337 span->ss->type = SS_TYPE_RODATA;
338 break;
339 } else {
340 err(sbfd, "Unrecognized Ksplice option %d\n",
341 opt->type);
342 DIE;
347 bool matchable_data_section(struct supersect *ss)
349 if (ss->type == SS_TYPE_STRING)
350 return true;
351 if (ss->type == SS_TYPE_RODATA)
352 return true;
353 if (ss->type == SS_TYPE_DATA && ss->relocs.size != 0)
354 return true;
355 if (ss->type == SS_TYPE_EXPORT)
356 return true;
357 if (ss->type == SS_TYPE_BUGTABLE)
358 return true;
359 return false;
362 bool unchangeable_section(struct supersect *ss)
364 if (ss->type == SS_TYPE_DATA)
365 return true;
366 if (ss->type == SS_TYPE_IGNORED && !strstarts(ss->name, ".debug") &&
367 strcmp(ss->name, "__ksymtab_strings") != 0)
368 return true;
369 return false;
372 int main(int argc, char *argv[])
374 if (getenv("KSPLICE_VERBOSE") != NULL)
375 verbose = atoi(getenv("KSPLICE_VERBOSE"));
377 bfd_init();
378 bfd *ibfd = bfd_openr(argv[1], NULL);
379 assert(ibfd);
381 char **matching;
382 if (bfd_check_format_matches(ibfd, bfd_archive, &matching) &&
383 bfd_openr_next_archived_file(ibfd, NULL) == NULL)
384 return 66; /* empty archive */
385 assert(bfd_check_format_matches(ibfd, bfd_object, &matching));
387 const char *output_target = bfd_get_target(ibfd);
389 load_system_map();
390 load_offsets();
392 bool_hash_init(&system_map_written);
393 ulong_hash_init(&ksplice_symbol_offset);
394 ulong_hash_init(&ksplice_howto_offset);
395 ulong_hash_init(&ksplice_string_offset);
397 struct superbfd *isbfd = fetch_superbfd(ibfd);
399 modestr = argv[3];
400 if (mode("finalize"))
401 finalize_target = argv[4];
402 init_objmanip_superbfd(isbfd);
403 if (mode("keep-new-code")) {
404 kid = argv[5];
405 do_keep_new_code(isbfd, argv[4]);
406 } else if (mode("keep-old-code")) {
407 do_keep_old_code(isbfd);
408 } else if (mode("finalize")) {
409 do_finalize(isbfd);
410 } else if (mode("rmsyms")) {
411 do_rmsyms(isbfd);
414 if (write_output) {
415 bfd *obfd = bfd_openw(argv[2], output_target);
416 assert(obfd);
417 copy_object(ibfd, obfd);
418 assert(bfd_close(obfd));
421 if (offsets_sbfd != NULL)
422 assert(bfd_close(offsets_sbfd->abfd));
423 assert(bfd_close(ibfd));
424 return EXIT_SUCCESS;
427 void do_keep_new_code(struct superbfd *isbfd, const char *pre)
429 struct bfd *prebfd = bfd_openr(pre, NULL);
430 assert(prebfd != NULL);
431 char **matching;
432 assert(bfd_check_format_matches(prebfd, bfd_object, &matching));
434 struct superbfd *presbfd = fetch_superbfd(prebfd);
435 init_objmanip_superbfd(presbfd);
437 foreach_symbol_pair(presbfd, isbfd, match_global_symbols);
438 debug1(isbfd, "Matched global\n");
439 foreach_span_pair(presbfd, isbfd, match_string_spans);
440 debug1(isbfd, "Matched string spans\n");
441 foreach_symbol_pair(presbfd, isbfd, match_symbol_spans);
442 debug1(isbfd, "Matched by name\n");
443 foreach_span_pair(presbfd, isbfd, match_spans_by_label);
444 debug1(isbfd, "Matched by label\n");
445 foreach_span_pair(presbfd, isbfd, match_table_spans);
446 debug1(isbfd, "Matched table spans\n");
448 do {
449 changed = false;
450 compare_matched_spans(isbfd);
451 update_nonzero_offsets(isbfd);
452 mark_new_spans(isbfd);
453 } while (changed);
454 vec_init(&delsects);
456 foreach_symbol_pair(presbfd, isbfd, check_global_symbols);
458 handle_deleted_spans(presbfd, isbfd);
459 handle_section_symbol_renames(presbfd, isbfd);
461 copy_patched_entry_points(presbfd, isbfd);
463 assert(bfd_close(prebfd));
465 do {
466 changed = false;
467 mark_precallable_spans(isbfd);
468 } while (changed);
470 asection *sect;
471 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
472 struct supersect *ss = fetch_supersect(isbfd, sect);
473 ss->keep = false;
474 struct span *span;
475 for (span = ss->spans.data;
476 span < ss->spans.data + ss->spans.size; span++) {
477 if (strstarts(ss->name, ".ksplice_options"))
478 span->keep = false;
479 else if (span->new || span->patch || span->datapatch)
480 keep_span(span);
481 else
482 span->keep = false;
483 if (span->patch && span->precallable) {
484 err(isbfd, "Patched span %s can be reached "
485 "by a precall function\n", span->label);
486 DIE;
491 print_label_changes(isbfd);
493 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
494 struct supersect *ss = fetch_supersect(isbfd, sect);
495 struct span *span;
496 for (span = ss->spans.data;
497 span < ss->spans.data + ss->spans.size; span++) {
498 if (span->patch || span->bugpatch || span->datapatch)
499 debug0(isbfd, "Patching span %s\n",
500 span->label);
504 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
505 struct supersect *ss = fetch_supersect(isbfd, sect);
506 struct span *span;
507 for (span = ss->spans.data;
508 span < ss->spans.data + ss->spans.size; span++) {
509 if (span->new)
510 debug0(isbfd, "New span %s\n", span->label);
514 write_output = false;
515 const char **sectname;
516 for (sectname = delsects.data;
517 sectname < delsects.data + delsects.size; sectname++) {
518 write_output = true;
519 debug0(isbfd, "Deleted section: %s\n", *sectname);
522 filter_table_sections(isbfd);
524 compute_span_shifts(isbfd);
526 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
527 struct supersect *ss = fetch_supersect(isbfd, sect);
528 if (ss->type == SS_TYPE_KSPLICE_CALL)
529 continue;
530 struct span *span;
531 for (span = ss->spans.data;
532 span < ss->spans.data + ss->spans.size; span++) {
533 if (span->keep)
534 write_output = true;
535 if (span->patch || span->new || span->datapatch)
536 write_ksplice_section(span);
537 if (span->patch || span->datapatch)
538 write_ksplice_patches(isbfd, span);
539 if (ss->type == SS_TYPE_EXPORT && span->new)
540 write_ksplice_export(isbfd, span, false);
544 write_bugline_patches(isbfd);
545 rm_relocs(isbfd);
546 remove_unkept_spans(isbfd);
549 void do_keep_old_code(struct superbfd *isbfd)
551 asection *sect;
552 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
553 struct supersect *ss = fetch_supersect(isbfd, sect);
554 ss->keep = false;
555 struct span *span;
556 for (span = ss->spans.data;
557 span < ss->spans.data + ss->spans.size; span++) {
558 span->keep = false;
559 if (ss->type == SS_TYPE_TEXT &&
560 !strstarts(ss->name, ".fixup"))
561 keep_span(span);
562 if (ss->type == SS_TYPE_EXPORT)
563 keep_span(span);
567 asymbol **symp;
568 for (symp = isbfd->syms.data;
569 symp < isbfd->syms.data + isbfd->syms.size; symp++) {
570 asymbol *sym = *symp;
571 if (!bfd_is_const_section(sym->section) &&
572 (sym->flags & BSF_GLOBAL) != 0) {
573 struct supersect *sym_ss =
574 fetch_supersect(isbfd, sym->section);
575 if (sym->value == sym_ss->contents.size)
576 continue;
577 struct span *span = find_span(sym_ss, sym->value);
578 assert(span != NULL);
579 if (sym_ss->type != SS_TYPE_IGNORED)
580 keep_span(span);
584 do {
585 changed = false;
586 keep_referenced_sections(isbfd);
587 } while (changed);
589 filter_table_sections(isbfd);
590 compute_span_shifts(isbfd);
592 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
593 struct supersect *ss = fetch_supersect(isbfd, sect);
594 asymbol *sym = canonical_symbol(isbfd, sect->symbol);
595 if (sym == NULL)
596 continue;
597 if ((sym->flags & BSF_WEAK) != 0)
598 continue;
599 if (bfd_get_section_size(sect) == 0)
600 continue;
601 if (!ss->keep)
602 continue;
603 if (ss->type != SS_TYPE_TEXT && !matchable_data_section(ss))
604 continue;
606 struct span *span;
607 for (span = ss->spans.data;
608 span < ss->spans.data + ss->spans.size; span++) {
609 if (span->keep)
610 write_ksplice_section(span);
614 write_table_relocs(isbfd, "__bug_table", KSPLICE_HOWTO_BUG);
615 write_table_relocs(isbfd, "__ex_table", KSPLICE_HOWTO_EXTABLE);
616 rm_relocs(isbfd);
617 remove_unkept_spans(isbfd);
619 mangle_section_name(isbfd, "__markers");
620 mangle_section_name(isbfd, "__ex_table");
621 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
622 struct supersect *ss = fetch_supersect(isbfd, sect);
623 if (ss->type == SS_TYPE_EXPORT)
624 mangle_section_name(isbfd, ss->name);
628 void do_finalize(struct superbfd *isbfd)
630 load_ksplice_symbol_offsets(isbfd);
631 asection *sect;
632 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
633 struct supersect *ss = fetch_supersect(isbfd, sect);
634 if (ss->type == SS_TYPE_EXIT) {
635 struct span *span;
636 for (span = ss->spans.data;
637 span < ss->spans.data + ss->spans.size; span++)
638 span->keep = false;
639 ss->keep = false;
642 write_date_relocs(isbfd, "<{DATE...}>", KSPLICE_HOWTO_DATE);
643 write_date_relocs(isbfd, "<{TIME}>", KSPLICE_HOWTO_TIME);
644 rm_relocs(isbfd);
647 void do_rmsyms(struct superbfd *isbfd)
649 asection *extract_sect = bfd_get_section_by_name(isbfd->abfd,
650 ".ksplice_extract");
651 if (extract_sect != NULL) {
652 struct supersect *extract_ss = fetch_supersect(isbfd,
653 extract_sect);
654 arelent **relocp;
655 for (relocp = extract_ss->relocs.data;
656 relocp < extract_ss->relocs.data + extract_ss->relocs.size;
657 relocp++) {
658 asymbol *sym = *(*relocp)->sym_ptr_ptr;
659 if (bfd_is_und_section(sym->section)) {
660 debug1(isbfd, "extracting symbol %s\n",
661 sym->name);
662 *vec_grow(&extract_syms, 1) = sym;
667 rm_relocs(isbfd);
670 void match_spans(struct span *old_span, struct span *new_span)
672 struct superbfd *sbfd = new_span->ss->parent;
673 if (old_span->match == new_span && new_span->match == old_span)
674 return;
675 if (old_span->match != NULL) {
676 err(sbfd, "Matching conflict: old %s: %s != %s\n",
677 old_span->label, old_span->match->label, new_span->label);
678 DIE;
680 if (new_span->match != NULL) {
681 err(sbfd, "Matching conflict: new %s: %s != %s\n",
682 new_span->label, new_span->match->label, old_span->label);
683 DIE;
685 old_span->match = new_span;
686 new_span->match = old_span;
687 debug1(sbfd, "Matched old %s to new %s\n", old_span->label,
688 new_span->label);
689 if (old_span->ss->type != new_span->ss->type &&
690 old_span->ss->type == new_span->ss->orig_type)
691 old_span->ss->type = new_span->ss->type;
693 const struct table_section *ts = get_table_section(old_span->ss->name);
694 if (ts == NULL || !ts->has_addr || ts->other_sect == NULL)
695 return;
696 struct span *old_sym_span =
697 span_offset_target_span(old_span, ts->other_offset);
698 struct span *new_sym_span =
699 span_offset_target_span(new_span, ts->other_offset);
700 assert(old_sym_span != NULL && new_sym_span != NULL);
701 match_spans(old_sym_span, new_sym_span);
704 void unmatch_span(struct span *old_span)
706 struct span *new_span = old_span->match;
707 old_span->match = NULL;
708 new_span->match = NULL;
710 new_span->bugpatch = false;
712 if (old_span->ss->type == SS_TYPE_SPECIAL) {
713 const struct table_section *ts =
714 get_table_section(old_span->ss->name);
715 if (ts != NULL && ts->has_addr)
716 unmatch_addr_spans(old_span, new_span, ts);
719 new_span->patch = false;
720 new_span->bugpatch = false;
721 new_span->datapatch = false;
723 changed = true;
726 static void match_global_symbols(struct span *old_span, asymbol *oldsym,
727 struct span *new_span, asymbol *newsym)
729 if ((oldsym->flags & BSF_GLOBAL) == 0 ||
730 (newsym->flags & BSF_GLOBAL) == 0)
731 return;
732 match_spans(old_span, new_span);
735 static void check_global_symbols(struct span *old_span, asymbol *oldsym,
736 struct span *new_span, asymbol *newsym)
738 if ((oldsym->flags & BSF_GLOBAL) == 0 ||
739 (newsym->flags & BSF_GLOBAL) == 0)
740 return;
741 if (old_span->ss->type == SS_TYPE_IGNORED)
742 return;
743 if (old_span->match != new_span || new_span->match != old_span) {
744 err(new_span->ss->parent, "Global symbol span mismatch: %s "
745 "%s/%s\n", oldsym->name, old_span->label, new_span->label);
746 DIE;
750 static void foreach_symbol_pair(struct superbfd *oldsbfd, struct superbfd *newsbfd,
751 void (*fn)(struct span *old_span,
752 asymbol *oldsym,
753 struct span *new_span,
754 asymbol *newsym))
756 asymbol **oldsymp, **newsymp;
757 for (oldsymp = oldsbfd->syms.data;
758 oldsymp < oldsbfd->syms.data + oldsbfd->syms.size; oldsymp++) {
759 asymbol *oldsym = *oldsymp;
760 if ((oldsym->flags & BSF_DEBUGGING) != 0 ||
761 bfd_is_const_section(oldsym->section))
762 continue;
764 struct supersect *old_ss =
765 fetch_supersect(oldsbfd, oldsym->section);
766 if (old_ss->type == SS_TYPE_SPECIAL ||
767 old_ss->type == SS_TYPE_EXPORT)
768 continue;
770 struct span *old_span = find_span(old_ss, oldsym->value);
771 if (old_span == NULL) {
772 err(oldsbfd, "Could not find span for %s\n",
773 oldsym->name);
774 DIE;
777 for (newsymp = newsbfd->syms.data;
778 newsymp < newsbfd->syms.data + newsbfd->syms.size;
779 newsymp++) {
780 asymbol *newsym = *newsymp;
781 if ((newsym->flags & BSF_DEBUGGING) != 0 ||
782 bfd_is_const_section(newsym->section))
783 continue;
784 if (strcmp(oldsym->name, newsym->name) != 0)
785 continue;
787 struct supersect *new_ss =
788 fetch_supersect(newsbfd, newsym->section);
789 if (old_ss->type != new_ss->type &&
790 old_ss->type != new_ss->orig_type)
791 continue;
793 struct span *new_span =
794 find_span(new_ss, newsym->value);
795 if (new_span == NULL) {
796 err(newsbfd, "Could not find span for %s\n",
797 newsym->name);
798 DIE;
800 fn(old_span, oldsym, new_span, newsym);
805 static void match_symbol_spans(struct span *old_span, asymbol *oldsym,
806 struct span *new_span, asymbol *newsym)
808 if (old_span->ss->type == SS_TYPE_SPECIAL)
809 return;
810 if (static_local_symbol(old_span->ss->parent, oldsym) ||
811 static_local_symbol(new_span->ss->parent, newsym))
812 return;
813 if (old_span->match == NULL && new_span->match == NULL)
814 match_spans(old_span, new_span);
817 static void match_spans_by_label(struct span *old_span, struct span *new_span)
819 if (old_span->ss->type == SS_TYPE_STRING ||
820 (is_table_section(old_span->ss->name, true, false) &&
821 !is_table_section(old_span->ss->name, false, false)))
822 return;
823 if (strcmp(old_span->label, new_span->label) == 0)
824 match_spans(old_span, new_span);
827 static void match_string_spans(struct span *old_span, struct span *new_span)
829 if (old_span->ss->type != SS_TYPE_STRING ||
830 strcmp(old_span->ss->name, new_span->ss->name) != 0)
831 return;
832 if (strcmp((char *)old_span->ss->contents.data + old_span->start,
833 (char *)new_span->ss->contents.data + new_span->start) == 0)
834 match_spans(old_span, new_span);
837 static void foreach_span_pair(struct superbfd *oldsbfd,
838 struct superbfd *newsbfd,
839 void (*fn)(struct span *old_span,
840 struct span *new_span))
842 asection *oldsect, *newsect;
843 struct supersect *oldss, *newss;
844 struct span *old_span, *new_span;
845 for (newsect = newsbfd->abfd->sections; newsect != NULL;
846 newsect = newsect->next) {
847 newss = fetch_supersect(newsbfd, newsect);
848 for (oldsect = oldsbfd->abfd->sections; oldsect != NULL;
849 oldsect = oldsect->next) {
850 oldss = fetch_supersect(oldsbfd, oldsect);
851 if (oldss->type != newss->type)
852 continue;
853 for (new_span = newss->spans.data;
854 new_span < newss->spans.data + newss->spans.size;
855 new_span++) {
856 for (old_span = oldss->spans.data;
857 old_span < oldss->spans.data +
858 oldss->spans.size; old_span++)
859 fn(old_span, new_span);
865 static void mark_new_spans(struct superbfd *sbfd)
867 asection *sect;
868 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
869 struct supersect *ss = fetch_supersect(sbfd, sect);
870 if (ss->type == SS_TYPE_SPECIAL || ss->type == SS_TYPE_IGNORED)
871 continue;
872 struct span *span;
873 for (span = ss->spans.data;
874 span < ss->spans.data + ss->spans.size; span++) {
875 if (span->match == NULL)
876 span->new = true;
881 static void handle_deleted_spans(struct superbfd *oldsbfd,
882 struct superbfd *newsbfd)
884 asection *sect;
885 for (sect = oldsbfd->abfd->sections; sect != NULL; sect = sect->next) {
886 struct supersect *ss = fetch_supersect(oldsbfd, sect);
887 struct span *span;
888 for (span = ss->spans.data;
889 span < ss->spans.data + ss->spans.size; span++) {
890 if (span->match != NULL)
891 continue;
892 if (ss->type == SS_TYPE_EXPORT) {
893 *vec_grow(&delsects, 1) = span->label;
894 write_ksplice_export(newsbfd, span, true);
895 } else if (ss->type == SS_TYPE_TEXT) {
896 *vec_grow(&delsects, 1) = span->label;
897 if (span->symbol == NULL)
898 DIE;
899 write_ksplice_deleted_patch
900 (newsbfd, span->symbol->name, span->label,
901 span->ss->name);
907 static void handle_nonzero_offset_relocs(struct supersect *ss)
909 struct span *address_span, *target_span;
910 arelent **relocp;
911 for (relocp = ss->relocs.data;
912 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
913 arelent *reloc = *relocp;
914 address_span = find_span(ss, reloc->address);
915 if (!address_span->new && !address_span->patch)
916 continue;
918 asymbol *sym = *reloc->sym_ptr_ptr;
919 if (bfd_is_const_section(sym->section))
920 continue;
921 bfd_vma offset = reloc_target_offset(ss, reloc);
922 target_span = reloc_target_span(ss, reloc);
923 if (sym->value + offset == target_span->start)
924 continue;
926 if (target_span->ss->type != SS_TYPE_TEXT)
927 continue;
928 if (target_span->patch)
929 continue;
931 target_span->patch = true;
932 changed = true;
933 debug1(ss->parent, "Changing %s because a relocation from sect "
934 "%s has a nonzero offset %lx+%lx into it\n",
935 target_span->label, ss->name, (unsigned long)sym->value,
936 (unsigned long)offset);
940 static void update_nonzero_offsets(struct superbfd *sbfd)
942 asection *sect;
943 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
944 struct supersect *ss = fetch_supersect(sbfd, sect);
945 if (ss->type == SS_TYPE_SPECIAL || ss->type == SS_TYPE_IGNORED)
946 continue;
947 handle_nonzero_offset_relocs(ss);
951 static void unmatch_addr_spans(struct span *old_span, struct span *new_span,
952 const struct table_section *ts)
954 struct span *old_sym_span =
955 span_offset_target_span(old_span, ts->addr_offset);
956 struct span *new_sym_span =
957 span_offset_target_span(new_span, ts->addr_offset);
958 assert(old_sym_span != NULL && new_sym_span != NULL);
959 if (old_sym_span->match == new_sym_span &&
960 new_sym_span->match == old_sym_span &&
961 !(new_sym_span->patch && new_sym_span->ss->type == SS_TYPE_TEXT)) {
962 if (old_sym_span->ss->type == SS_TYPE_TEXT) {
963 debug1(new_span->ss->parent, "Patching %s due "
964 "to relocations from special section %s\n",
965 new_sym_span->label, new_span->label);
966 new_sym_span->patch = true;
967 } else {
968 debug1(new_span->ss->parent, "Unmatching %s and %s due "
969 "to relocations from special section %s/%s\n",
970 old_sym_span->label, new_sym_span->label,
971 old_span->label, new_span->label);
972 unmatch_span(old_sym_span);
974 changed = true;
978 static void compare_spans(struct span *old_span, struct span *new_span)
980 struct superbfd *newsbfd = new_span->ss->parent;
982 bool nonrelocs_match = nonrelocs_equal(old_span, new_span);
983 bool relocs_match = all_relocs_equal(old_span, new_span);
984 if (nonrelocs_match && relocs_match) {
985 const struct table_section *ts =
986 get_table_section(old_span->ss->name);
987 if (ts != NULL && ts->crc_sect != NULL) {
988 struct span *old_crc_span = get_crc_span(old_span, ts);
989 struct span *new_crc_span = get_crc_span(new_span, ts);
990 assert(old_crc_span != NULL);
991 assert(new_crc_span != NULL);
992 if (old_crc_span->match != new_crc_span ||
993 new_crc_span->match != old_crc_span) {
994 debug1(newsbfd, "Unmatching %s and %s due to "
995 "nonmatching CRCs\n", old_span->label,
996 new_span->label);
997 unmatch_span(old_span);
1000 return;
1003 char *reason;
1004 if (new_span->contents_size != old_span->contents_size)
1005 reason = "differing sizes";
1006 else if (!nonrelocs_match)
1007 reason = "differing contents";
1008 else
1009 reason = "differing relocations";
1011 if (new_span->ss->type == SS_TYPE_TEXT) {
1012 if (new_span->patch)
1013 return;
1014 new_span->patch = true;
1015 debug1(newsbfd, "Changing %s due to %s\n", new_span->label,
1016 reason);
1017 } else if (old_span->ss->type == SS_TYPE_BUGTABLE &&
1018 new_span->ss->type == SS_TYPE_BUGTABLE && relocs_match) {
1019 if (new_span->bugpatch)
1020 return;
1021 debug1(newsbfd, "Changing %s due to %s\n",
1022 new_span->label, reason);
1023 new_span->bugpatch = true;
1024 } else if (new_span->ss->type == SS_TYPE_RODATA &&
1025 new_span->contents_size == old_span->contents_size) {
1026 if (new_span->datapatch)
1027 return;
1028 new_span->datapatch = true;
1029 debug1(newsbfd, "Changing %s in-place due to %s\n",
1030 new_span->label, reason);
1031 } else if (new_span->ss->type == SS_TYPE_STRING &&
1032 old_span->ss->type == SS_TYPE_STRING && relocs_match &&
1033 strcmp(new_span->ss->contents.data + new_span->start,
1034 old_span->ss->contents.data + old_span->start) == 0) {
1035 return;
1036 } else {
1037 debug1(newsbfd, "Unmatching %s and %s due to %s\n",
1038 old_span->label, new_span->label, reason);
1039 unmatch_span(old_span);
1041 changed = true;
1042 if (unchangeable_section(new_span->ss))
1043 err(newsbfd, "warning: ignoring change to nonpatchable "
1044 "section %s\n", new_span->ss->name);
1047 static void compare_matched_spans(struct superbfd *newsbfd)
1049 asection *sect;
1050 for (sect = newsbfd->abfd->sections; sect != NULL; sect = sect->next) {
1051 struct supersect *ss = fetch_supersect(newsbfd, sect);
1052 struct span *span;
1053 for (span = ss->spans.data;
1054 span < ss->spans.data + ss->spans.size; span++) {
1055 if (span->match == NULL)
1056 continue;
1057 compare_spans(span->match, span);
1062 static void handle_section_symbol_renames(struct superbfd *oldsbfd,
1063 struct superbfd *newsbfd)
1065 asection *sect;
1066 struct span *span;
1067 for (sect = newsbfd->abfd->sections; sect != NULL; sect = sect->next) {
1068 struct supersect *ss = fetch_supersect(newsbfd, sect);
1069 for (span = ss->spans.data;
1070 span < ss->spans.data + ss->spans.size; span++) {
1071 if (span->match == NULL)
1072 continue;
1073 if (strcmp(span->label, span->match->label) == 0)
1074 continue;
1075 if (strcmp(span->orig_label, span->label) != 0 &&
1076 strcmp(span->label, span->match->label) != 0)
1077 DIE;
1078 if (span->symbol != NULL)
1079 label_map_set(newsbfd, span->label,
1080 span->match->label);
1081 span->label = span->match->label;
1086 static void copy_patched_entry_points(struct superbfd *oldsbfd,
1087 struct superbfd *newsbfd)
1089 asection *sect;
1090 struct span *span;
1091 for (sect = newsbfd->abfd->sections; sect != NULL; sect = sect->next) {
1092 struct supersect *ss = fetch_supersect(newsbfd, sect);
1093 for (span = ss->spans.data;
1094 span < ss->spans.data + ss->spans.size; span++) {
1095 if (!span->patch)
1096 continue;
1097 assert(span->match != NULL);
1098 vec_init(&span->pre_entry_points);
1100 struct entry_point *entry;
1101 for (entry = span->match->entry_points.data;
1102 entry < span->match->entry_points.data +
1103 span->match->entry_points.size;
1104 entry++) {
1105 struct entry_point *e =
1106 vec_grow(&span->pre_entry_points, 1);
1107 e->name = entry->name != NULL ?
1108 strdup(entry->name) : NULL;
1109 e->label = strdup(entry->label);
1110 e->offset = entry->offset;
1111 e->symbol = NULL;
1117 static int compare_entry_points(const void *va, const void *vb)
1119 const struct entry_point *a = va, *b = vb;
1120 if (a->offset < b->offset)
1121 return -1;
1122 else if (a->offset > b->offset)
1123 return 1;
1124 else
1125 return 0;
1128 static void compute_entry_points(struct superbfd *sbfd)
1130 asymbol **symp;
1131 for (symp = sbfd->syms.data; symp < sbfd->syms.data + sbfd->syms.size;
1132 symp++) {
1133 asymbol *sym = *symp;
1134 if (bfd_is_const_section(sym->section))
1135 continue;
1136 struct supersect *old_ss = fetch_supersect(sbfd, sym->section);
1137 if ((sym->flags & BSF_GLOBAL) == 0)
1138 continue;
1139 struct span *span = find_span(old_ss, sym->value);
1140 struct entry_point *e = vec_grow(&span->entry_points, 1);
1141 e->label = sym->name;
1142 e->name = sym->name;
1143 e->offset = sym->value - span->start;
1144 e->symbol = sym;
1147 asection *sect;
1148 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
1149 struct supersect *ss = fetch_supersect(sbfd, sect);
1150 struct span *span;
1151 for (span = ss->spans.data;
1152 span < ss->spans.data + ss->spans.size; span++) {
1153 /* First make sure that 0 appears as an entry point */
1154 bool found_zero = false;
1155 struct entry_point *entry;
1156 for (entry = span->entry_points.data;
1157 entry < span->entry_points.data +
1158 span->entry_points.size;
1159 entry++) {
1160 if (entry->offset == 0)
1161 found_zero = true;
1163 if (!found_zero) {
1164 struct entry_point *e =
1165 vec_grow(&span->entry_points, 1);
1166 e->label = span->label;
1167 e->name = NULL;
1168 e->offset = 0;
1169 e->symbol = span->symbol;
1172 qsort(span->entry_points.data, span->entry_points.size,
1173 sizeof(*span->entry_points.data),
1174 compare_entry_points);
1179 static bool part_of_reloc(struct supersect *ss, unsigned long addr)
1181 arelent **relocp;
1182 for (relocp = ss->relocs.data;
1183 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
1184 arelent *reloc = *relocp;
1185 if (addr >= reloc->address &&
1186 addr < reloc->address + bfd_get_reloc_size(reloc->howto))
1187 return true;
1189 return false;
1192 static bool nonrelocs_equal(struct span *old_span, struct span *new_span)
1194 int i;
1195 struct supersect *old_ss = old_span->ss, *new_ss = new_span->ss;
1196 if (old_span->contents_size != new_span->contents_size)
1197 return false;
1198 const unsigned char *old = old_ss->contents.data + old_span->start;
1199 const unsigned char *new = new_ss->contents.data + new_span->start;
1200 for (i = 0; i < old_span->contents_size; i++) {
1201 if (old[i] != new[i] &&
1202 !(part_of_reloc(old_ss, i + old_span->start) &&
1203 part_of_reloc(new_ss, i + new_span->start)))
1204 return false;
1206 return true;
1209 bool relocs_equal(struct supersect *old_src_ss, struct supersect *new_src_ss,
1210 arelent *old_reloc, arelent *new_reloc)
1212 struct superbfd *oldsbfd = old_src_ss->parent;
1213 struct superbfd *newsbfd = new_src_ss->parent;
1214 struct span *old_addr_span = find_span(old_src_ss, old_reloc->address);
1215 struct span *new_addr_span = find_span(new_src_ss, new_reloc->address);
1217 if (old_reloc->address - old_addr_span->start !=
1218 new_reloc->address - new_addr_span->start) {
1219 debug1(newsbfd, "Section %s/%s has reloc address mismatch at "
1220 "%lx\n", old_src_ss->name, new_src_ss->name,
1221 (unsigned long)old_reloc->address);
1222 return false;
1225 if (old_reloc->howto != new_reloc->howto) {
1226 debug1(newsbfd, "Section %s/%s has howto type mismatch at "
1227 "%lx\n", old_src_ss->name, new_src_ss->name,
1228 (unsigned long)old_reloc->address);
1229 return false;
1232 if (non_dst_mask(old_src_ss, old_reloc) !=
1233 non_dst_mask(new_src_ss, new_reloc)) {
1234 debug1(newsbfd, "Section %s/%s has contents mismatch at %lx\n",
1235 old_src_ss->name, new_src_ss->name,
1236 (unsigned long)old_reloc->address);
1237 return false;
1240 asymbol *old_sym = *old_reloc->sym_ptr_ptr;
1241 asymbol *new_sym = *new_reloc->sym_ptr_ptr;
1242 asection *old_sect = old_sym->section;
1243 asection *new_sect = new_sym->section;
1245 bfd_vma old_offset = reloc_target_offset(old_src_ss, old_reloc);
1246 bfd_vma new_offset = reloc_target_offset(new_src_ss, new_reloc);
1248 if (bfd_is_und_section(old_sect) || bfd_is_und_section(new_sect)) {
1249 if (!bfd_is_und_section(new_sect) && old_offset != 0 &&
1250 fetch_supersect(newsbfd, new_sect)->type == SS_TYPE_TEXT)
1251 return false;
1253 if (!bfd_is_und_section(new_sect) && new_offset != 0 &&
1254 fetch_supersect(oldsbfd, old_sect)->type == SS_TYPE_TEXT)
1255 return false;
1257 return strcmp(old_sym->name, new_sym->name) == 0 &&
1258 old_offset == new_offset;
1261 if (bfd_is_abs_section(old_sect) && bfd_is_abs_section(new_sect)) {
1262 if (old_sym->value + old_offset == new_sym->value + new_offset)
1263 return true;
1264 debug1(newsbfd, "Differing relocations from %s/%s to ABS "
1265 "section: %lx/%lx\n", old_addr_span->label,
1266 new_addr_span->label,
1267 (unsigned long)(old_sym->value + old_offset),
1268 (unsigned long)(new_sym->value + new_offset));
1269 return false;
1272 if (bfd_is_const_section(old_sect) || bfd_is_const_section(new_sect))
1273 DIE;
1275 struct supersect *old_ss = fetch_supersect(oldsbfd, old_sect);
1276 struct supersect *new_ss = fetch_supersect(newsbfd, new_sect);
1277 struct span *old_span = reloc_target_span(old_src_ss, old_reloc);
1278 struct span *new_span = reloc_target_span(new_src_ss, new_reloc);
1280 if (old_span->match != new_span || new_span->match != old_span) {
1281 debug1(newsbfd, "Nonmatching relocs from %s to %s/%s\n",
1282 new_src_ss->name, old_span->label, new_span->label);
1283 return false;
1286 if (old_sym->value + old_offset - old_span->start !=
1287 new_sym->value + new_offset - new_span->start) {
1288 debug1(newsbfd, "Offsets to %s/%s differ between %s "
1289 "and %s: %lx+%lx/%lx+%lx\n", old_ss->name,
1290 new_ss->name, old_src_ss->name, new_src_ss->name,
1291 (unsigned long)old_sym->value, (unsigned long)old_offset,
1292 (unsigned long)new_sym->value,
1293 (unsigned long)new_offset);
1294 return false;
1297 if ((old_sym->value + old_offset - old_span->start != 0 ||
1298 new_sym->value + new_offset - new_span->start != 0) &&
1299 new_span->patch) {
1300 debug1(newsbfd, "Relocation from %s to nonzero offsets "
1301 "%lx+%lx/%lx+%lx in changed section %s\n",
1302 new_src_ss->name, (unsigned long)old_sym->value,
1303 (unsigned long)old_offset, (unsigned long)new_sym->value,
1304 (unsigned long)new_offset, new_sym->section->name);
1305 return false;
1307 return true;
1310 bool all_relocs_equal(struct span *old_span, struct span *new_span)
1312 struct supersect *old_ss = old_span->ss, *new_ss = new_span->ss;
1313 arelent **old_relocp, **new_relocp;
1315 for (old_relocp = old_ss->relocs.data;
1316 old_relocp < old_ss->relocs.data + old_ss->relocs.size;
1317 old_relocp++) {
1318 if (find_span(old_ss, (*old_relocp)->address) == old_span)
1319 break;
1322 for (new_relocp = new_ss->relocs.data;
1323 new_relocp < new_ss->relocs.data + new_ss->relocs.size;
1324 new_relocp++) {
1325 if (find_span(new_ss, (*new_relocp)->address) == new_span)
1326 break;
1329 for (; old_relocp < old_ss->relocs.data + old_ss->relocs.size &&
1330 find_span(old_ss, (*old_relocp)->address) == old_span &&
1331 new_relocp < new_ss->relocs.data + new_ss->relocs.size &&
1332 find_span(new_ss, (*new_relocp)->address) == new_span;
1333 old_relocp++, new_relocp++) {
1334 if (!relocs_equal(old_ss, new_ss, *old_relocp, *new_relocp))
1335 return false;
1338 if ((old_relocp < old_ss->relocs.data + old_ss->relocs.size &&
1339 find_span(old_ss, (*old_relocp)->address) == old_span) ||
1340 (new_relocp < new_ss->relocs.data + new_ss->relocs.size &&
1341 find_span(new_ss, (*new_relocp)->address) == new_span)) {
1342 debug1(new_ss->parent, "Different reloc count between %s and "
1343 "%s\n", old_span->label, new_span->label);
1344 return false;
1347 return true;
1350 bfd_vma non_dst_mask(struct supersect *ss, arelent *reloc)
1352 int bits = bfd_get_reloc_size(reloc->howto) * 8;
1353 void *address = ss->contents.data + reloc->address;
1354 bfd_vma x = bfd_get(bits, ss->parent->abfd, address);
1355 return x & ~reloc->howto->dst_mask;
1358 void rm_relocs(struct superbfd *isbfd)
1360 asection *p;
1361 for (p = isbfd->abfd->sections; p != NULL; p = p->next) {
1362 struct supersect *ss = fetch_supersect(isbfd, p);
1363 bool remove_relocs = ss->keep;
1365 if (mode("keep") && ss->type == SS_TYPE_SPECIAL)
1366 remove_relocs = false;
1368 if (ss->type == SS_TYPE_KSPLICE ||
1369 ss->type == SS_TYPE_KSPLICE_CALL)
1370 remove_relocs = false;
1371 if (mode("finalize") &&
1372 (strstarts(ss->name, ".ksplice_patches") ||
1373 strstarts(ss->name, ".ksplice_relocs")))
1374 remove_relocs = true;
1376 if (remove_relocs)
1377 rm_some_relocs(ss);
1381 void rm_some_relocs(struct supersect *ss)
1383 struct arelentp_vec orig_relocs;
1384 vec_move(&orig_relocs, &ss->relocs);
1386 arelent **relocp;
1387 for (relocp = orig_relocs.data;
1388 relocp < orig_relocs.data + orig_relocs.size; relocp++) {
1389 bool rm_reloc = false;
1390 asymbol *sym_ptr = *(*relocp)->sym_ptr_ptr;
1392 if (mode("rmsyms") && bfd_is_und_section(sym_ptr->section)) {
1393 asymbol **esymp;
1394 for (esymp = extract_syms.data;
1395 esymp < extract_syms.data + extract_syms.size;
1396 esymp++) {
1397 if (sym_ptr == *esymp) {
1398 rm_reloc = true;
1399 break;
1404 if (mode("keep"))
1405 rm_reloc = true;
1407 if (mode("keep-new-code")) {
1408 if (bfd_is_const_section(sym_ptr->section)) {
1409 rm_reloc = false;
1410 } else {
1411 bfd_vma offset = reloc_target_offset(ss, *relocp);
1412 struct span *target_span =
1413 reloc_target_span(ss, *relocp);
1414 if (target_span->new ||
1415 (target_span->ss->type == SS_TYPE_TEXT &&
1416 sym_ptr->value + offset !=
1417 target_span->start))
1418 rm_reloc = false;
1421 const struct table_section *ts =
1422 get_table_section(ss->name);
1423 if (ts != NULL && ts->has_addr &&
1424 ((*relocp)->address % ts->entry_size ==
1425 ts->addr_offset ||
1426 (*relocp)->address % ts->entry_size ==
1427 ts->other_offset))
1428 rm_reloc = false;
1431 if (mode("finalize") && bfd_is_und_section(sym_ptr->section))
1432 rm_reloc = true;
1434 if (strcmp(sym_ptr->name, "mcount") == 0 &&
1435 bfd_is_und_section(sym_ptr->section))
1436 rm_reloc = false;
1438 if (!find_span(ss, (*relocp)->address)->keep)
1439 rm_reloc = false;
1441 if (rm_reloc)
1442 write_ksplice_reloc(ss, *relocp);
1443 else
1444 *vec_grow(&ss->relocs, 1) = *relocp;
1448 struct supersect *make_section(struct superbfd *sbfd, const char *fmt, ...)
1450 va_list ap;
1451 va_start(ap, fmt);
1452 char *name = vstrprintf(fmt, ap);
1453 va_end(ap);
1455 asection *sect = bfd_get_section_by_name(sbfd->abfd, name);
1456 if (sect != NULL)
1457 return fetch_supersect(sbfd, sect);
1458 else
1459 return new_supersect(sbfd, name);
1462 arelent *create_reloc(struct supersect *ss, const void *addr, asymbol **symp,
1463 bfd_vma offset)
1465 bfd_reloc_code_real_type code;
1466 switch (bfd_arch_bits_per_address(ss->parent->abfd)) {
1467 case 32:
1468 code = BFD_RELOC_32;
1469 break;
1470 case 64:
1471 code = BFD_RELOC_64;
1472 break;
1473 default:
1474 DIE;
1477 arelent *reloc = malloc(sizeof(*reloc));
1478 reloc->sym_ptr_ptr = symp;
1479 reloc->address = addr_offset(ss, addr);
1480 reloc->howto = bfd_reloc_type_lookup(ss->parent->abfd, code);
1481 reloc->addend = offset;
1482 return reloc;
1485 void write_reloc(struct supersect *ss, const void *addr, asymbol **symp,
1486 bfd_vma offset)
1488 *vec_grow(&ss->new_relocs, 1) = create_reloc(ss, addr, symp, offset);
1491 void write_string(struct supersect *ss, const char **addr, const char *fmt, ...)
1493 va_list ap;
1494 struct supersect *str_ss = make_section(ss->parent, ".ksplice_str");
1495 char *str;
1496 va_start(ap, fmt);
1497 int len = vasprintf(&str, fmt, ap);
1498 assert(len >= 0);
1499 va_end(ap);
1501 unsigned long *str_offp = ulong_hash_lookup(&ksplice_string_offset, str,
1502 FALSE);
1503 if (str_offp == NULL) {
1504 char *buf = sect_grow(str_ss, len + 1, char);
1505 memcpy(buf, str, len + 1);
1506 str_offp = ulong_hash_lookup(&ksplice_string_offset, str, TRUE);
1507 *str_offp = addr_offset(str_ss, buf);
1510 write_reloc(ss, addr, &str_ss->symbol, *str_offp);
1513 void lookup_system_map(struct addr_vec *addrs, const char *name, long offset)
1515 struct addr_vec *map_addrs =
1516 addr_vec_hash_lookup(&system_map, name, FALSE);
1517 if (map_addrs == NULL)
1518 return;
1520 unsigned long *addr, *map_addr;
1521 for (map_addr = map_addrs->data;
1522 map_addr < map_addrs->data + map_addrs->size; map_addr++) {
1523 for (addr = addrs->data; addr < addrs->data + addrs->size;
1524 addr++) {
1525 if (*addr == *map_addr + offset)
1526 break;
1528 if (addr < addrs->data + addrs->size)
1529 continue;
1530 *vec_grow(addrs, 1) = *map_addr + offset;
1534 void compute_system_map_array(struct superbfd *sbfd, struct addr_vec *addrs,
1535 asymbol *sym)
1537 if (bfd_is_abs_section(sym->section)) {
1538 *vec_grow(addrs, 1) = sym->value;
1539 } else if (bfd_is_und_section(sym->section)) {
1540 lookup_system_map(addrs, sym->name, 0);
1541 } else if (!bfd_is_const_section(sym->section)) {
1542 asymbol **gsymp;
1543 for (gsymp = sbfd->syms.data;
1544 gsymp < sbfd->syms.data + sbfd->syms.size; gsymp++) {
1545 asymbol *gsym = *gsymp;
1546 if ((gsym->flags & BSF_DEBUGGING) == 0 &&
1547 gsym->section == sym->section)
1548 lookup_system_map(addrs, gsym->name,
1549 sym->value - gsym->value);
1554 void write_ksplice_system_map(struct superbfd *sbfd, asymbol *sym,
1555 const char *label)
1557 bool *done = bool_hash_lookup(&system_map_written, label, TRUE);
1558 if (*done)
1559 return;
1560 *done = true;
1562 struct addr_vec addrs;
1563 vec_init(&addrs);
1565 compute_system_map_array(sbfd, &addrs, sym);
1566 if (addrs.size != 0) {
1567 struct supersect *smap_ss =
1568 make_section(sbfd, ".ksplice_system_map");
1569 struct ksplice_system_map *smap =
1570 sect_grow(smap_ss, 1, struct ksplice_system_map);
1571 write_string(smap_ss, &smap->label, "%s", label);
1573 struct supersect *array_ss = make_section(sbfd,
1574 ".ksplice_array");
1575 void *buf = sect_grow(array_ss, addrs.size,
1576 typeof(*addrs.data));
1577 memcpy(buf, addrs.data, addrs.size * sizeof(*addrs.data));
1578 smap->nr_candidates = addrs.size;
1579 write_reloc(smap_ss, &smap->candidates, &array_ss->symbol,
1580 addr_offset(array_ss, buf));
1582 vec_free(&addrs);
1585 void write_ksplice_symbol_backend(struct supersect *ss,
1586 struct ksplice_symbol *const *addr,
1587 asymbol *sym, const char *label,
1588 const char *name)
1590 struct supersect *ksymbol_ss = make_section(ss->parent,
1591 ".ksplice_symbols");
1592 struct ksplice_symbol *ksymbol;
1593 unsigned long *ksymbol_offp;
1595 ksymbol_offp = ulong_hash_lookup(&ksplice_symbol_offset, label, FALSE);
1596 if (ksymbol_offp != NULL) {
1597 write_reloc(ss, addr, &ksymbol_ss->symbol, *ksymbol_offp);
1598 return;
1600 ksymbol = sect_grow(ksymbol_ss, 1, struct ksplice_symbol);
1601 ksymbol_offp = ulong_hash_lookup(&ksplice_symbol_offset, label, TRUE);
1602 *ksymbol_offp = addr_offset(ksymbol_ss, ksymbol);
1604 write_reloc(ss, addr, &ksymbol_ss->symbol, *ksymbol_offp);
1605 write_string(ksymbol_ss, &ksymbol->label, "%s", label);
1606 if (name != NULL) {
1607 write_string(ksymbol_ss, &ksymbol->name, "%s", name);
1608 write_ksplice_system_map(ksymbol_ss->parent, sym, label);
1612 void write_ksplice_symbol(struct supersect *ss,
1613 struct ksplice_symbol *const *addr,
1614 asymbol *sym, struct span *span,
1615 const char *addstr_sect)
1617 const char *label, *name;
1618 if (span != NULL && span->start != 0)
1619 label = span->label;
1620 else
1621 label = label_lookup(ss->parent, sym);
1623 asymbol *gsym = canonical_symbol(ss->parent, sym);
1624 if (strcmp(addstr_sect, "") != 0)
1625 name = NULL;
1626 else if (bfd_is_und_section(sym->section))
1627 name = sym->name;
1628 else if (bfd_is_const_section(sym->section))
1629 name = NULL;
1630 else if (span != NULL && span->symbol == NULL)
1631 name = NULL;
1632 else if (gsym == NULL || (gsym->flags & BSF_SECTION_SYM) != 0)
1633 name = NULL;
1634 else
1635 name = gsym->name;
1637 write_ksplice_symbol_backend(ss, addr, sym,
1638 strprintf("%s%s", addstr_sect, label),
1639 name);
1642 void write_ksplice_reloc(struct supersect *ss, arelent *orig_reloc)
1644 asymbol *sym_ptr = *orig_reloc->sym_ptr_ptr;
1645 bfd_vma reloc_addend = reloc_offset(ss, orig_reloc);
1646 bfd_vma target_addend = reloc_target_offset(ss, orig_reloc);
1647 unsigned long *repladdr = ss->contents.data + orig_reloc->address;
1649 if (mode("finalize") && strstarts(ss->name, ".ksplice_patches")) {
1650 *repladdr = 0;
1651 return;
1653 if (mode("finalize") && strstarts(ss->name, ".ksplice_relocs")) {
1654 assert(strstarts(sym_ptr->name, KSPLICE_SYMBOL_STR));
1655 asymbol fake_sym;
1656 fake_sym.name = sym_ptr->name + strlen(KSPLICE_SYMBOL_STR);
1657 fake_sym.section = bfd_und_section_ptr;
1658 fake_sym.value = 0;
1659 fake_sym.flags = 0;
1661 write_ksplice_symbol_backend
1662 (ss, (struct ksplice_symbol **)repladdr, &fake_sym,
1663 fake_sym.name, fake_sym.name);
1664 return;
1667 struct span *span = reloc_target_span(ss, orig_reloc);
1668 if (span == ss->spans.data && span->start != target_addend)
1669 span = NULL;
1670 write_canary(ss, orig_reloc->address,
1671 bfd_get_reloc_size(orig_reloc->howto),
1672 orig_reloc->howto->dst_mask);
1674 struct supersect *kreloc_ss =
1675 make_section(ss->parent, ".ksplice_relocs%s", ss->name);
1676 struct ksplice_reloc *kreloc = sect_grow(kreloc_ss, 1,
1677 struct ksplice_reloc);
1679 struct span *address_span = find_span(ss, orig_reloc->address);
1680 write_reloc(kreloc_ss, &kreloc->blank_addr,
1681 &ss->symbol, orig_reloc->address + address_span->shift);
1682 if (bfd_is_und_section(sym_ptr->section) && mode("keep")) {
1683 char *name = strprintf(KSPLICE_SYMBOL_STR "%s", sym_ptr->name);
1684 asymbol **symp = make_undefined_symbolp(ss->parent, name);
1685 write_reloc(kreloc_ss, &kreloc->symbol, symp, 0);
1686 } else {
1687 write_ksplice_symbol(kreloc_ss, &kreloc->symbol, sym_ptr, span,
1688 "");
1690 if (span != NULL && span->start != 0) {
1691 reloc_addend += sym_ptr->value - span->start;
1692 target_addend += sym_ptr->value - span->start;
1694 kreloc->insn_addend = reloc_addend - target_addend;
1695 kreloc->target_addend = target_addend;
1696 write_ksplice_reloc_howto(kreloc_ss, &kreloc->howto, orig_reloc->howto,
1697 KSPLICE_HOWTO_RELOC);
1700 static void write_ksplice_reloc_howto(struct supersect *ss, const
1701 struct ksplice_reloc_howto *const *addr,
1702 reloc_howto_type *howto,
1703 enum ksplice_reloc_howto_type type)
1705 struct supersect *khowto_ss = make_section(ss->parent,
1706 ".ksplice_reloc_howtos");
1707 struct ksplice_reloc_howto *khowto;
1708 unsigned long *khowto_offp;
1710 khowto_offp = ulong_hash_lookup(&ksplice_howto_offset, howto->name,
1711 FALSE);
1712 if (khowto_offp != NULL) {
1713 write_reloc(ss, addr, &khowto_ss->symbol, *khowto_offp);
1714 return;
1716 khowto = sect_grow(khowto_ss, 1, struct ksplice_reloc_howto);
1717 khowto_offp = ulong_hash_lookup(&ksplice_howto_offset, howto->name,
1718 TRUE);
1719 *khowto_offp = addr_offset(khowto_ss, khowto);
1721 khowto->type = type;
1722 khowto->pcrel = howto->pc_relative;
1723 khowto->size = bfd_get_reloc_size(howto);
1724 khowto->dst_mask = howto->dst_mask;
1725 khowto->rightshift = howto->rightshift;
1726 khowto->signed_addend =
1727 (howto->complain_on_overflow == complain_overflow_signed) ||
1728 (howto->complain_on_overflow == complain_overflow_bitfield);
1729 write_reloc(ss, addr, &khowto_ss->symbol, *khowto_offp);
1732 #define CANARY(x, canary) ((x & ~howto->dst_mask) | (canary & howto->dst_mask))
1734 void write_canary(struct supersect *ss, int offset, bfd_size_type size,
1735 bfd_vma dst_mask)
1737 int bits = size * 8;
1738 void *address = ss->contents.data + offset;
1739 bfd_vma x = bfd_get(bits, ss->parent->abfd, address);
1740 x = (x & ~dst_mask) | ((bfd_vma)KSPLICE_CANARY & dst_mask);
1741 bfd_put(bits, ss->parent->abfd, x, address);
1744 static void write_date_relocs(struct superbfd *sbfd, const char *str,
1745 enum ksplice_reloc_howto_type type)
1747 asection *sect;
1748 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
1749 struct supersect *ss = fetch_supersect(sbfd, sect);
1750 if (ss->type != SS_TYPE_STRING && ss->type != SS_TYPE_RODATA)
1751 continue;
1752 void *ptr;
1753 struct span *span;
1754 for (span = ss->spans.data;
1755 span < ss->spans.data + ss->spans.size; span++) {
1756 if (!span->keep)
1757 continue;
1758 for (ptr = ss->contents.data + span->start;
1759 ptr + strlen(str) < ss->contents.data +
1760 span->start + span->contents_size; ptr++) {
1761 if (strcmp((const char *)ptr, str) == 0)
1762 write_ksplice_date_reloc
1763 (ss, addr_offset(ss, ptr), str,
1764 type);
1770 static void write_ksplice_date_reloc(struct supersect *ss, unsigned long offset,
1771 const char *str,
1772 enum ksplice_reloc_howto_type type)
1774 struct supersect *kreloc_ss;
1775 kreloc_ss = make_section(ss->parent, ".ksplice_relocs%s", ss->name);
1776 struct ksplice_reloc *kreloc = sect_grow(kreloc_ss, 1,
1777 struct ksplice_reloc);
1779 const char *filename = ss->parent->abfd->filename;
1780 char *c = strstr(filename, ".KSPLICE");
1781 int flen = (c == NULL ? strlen(filename) : c - filename);
1783 write_ksplice_symbol_backend(kreloc_ss, &kreloc->symbol, NULL,
1784 strprintf("%s<%.*s>", str, flen, filename),
1785 NULL);
1787 struct span *span = find_span(ss, offset);
1788 write_reloc(kreloc_ss, &kreloc->blank_addr, &ss->symbol,
1789 offset + span->shift);
1790 write_ksplice_nonreloc_howto(kreloc_ss, &kreloc->howto, type,
1791 strlen(str));
1794 static void write_table_relocs(struct superbfd *sbfd, const char *sectname,
1795 enum ksplice_reloc_howto_type type)
1797 asection *sect = bfd_get_section_by_name(sbfd->abfd, sectname);
1798 if (sect == NULL)
1799 return;
1800 struct supersect *ss = fetch_supersect(sbfd, sect);
1802 const struct table_section *s = get_table_section(sectname);
1803 if (s == NULL)
1804 DIE;
1806 void *entry;
1807 for (entry = ss->contents.data;
1808 entry < ss->contents.data + ss->contents.size;
1809 entry += s->entry_size) {
1810 struct span *span = find_span(ss, addr_offset(ss, entry));
1811 assert(span != NULL);
1812 if (!span->keep)
1813 continue;
1815 arelent *reloc = find_reloc(ss, entry + s->addr_offset);
1816 assert(reloc != NULL);
1817 asymbol *sym = *reloc->sym_ptr_ptr;
1818 assert(!bfd_is_const_section(sym->section));
1819 struct supersect *sym_ss = fetch_supersect(sbfd, sym->section);
1820 unsigned long addr = sym->value +
1821 reloc_target_offset(ss, reloc);
1822 write_ksplice_table_reloc(sym_ss, addr, span->label, type);
1826 static void write_ksplice_table_reloc(struct supersect *ss,
1827 unsigned long address,
1828 const char *label,
1829 enum ksplice_reloc_howto_type type)
1831 struct supersect *kreloc_ss;
1832 kreloc_ss = make_section(ss->parent, ".ksplice_relocs%s", ss->name);
1833 struct ksplice_reloc *kreloc = sect_grow(kreloc_ss, 1,
1834 struct ksplice_reloc);
1835 struct span *span = find_span(ss, address);
1836 assert(span != NULL);
1838 write_ksplice_symbol_backend(kreloc_ss, &kreloc->symbol, NULL,
1839 label, NULL);
1840 write_reloc(kreloc_ss, &kreloc->blank_addr, &ss->symbol,
1841 address + span->shift);
1842 write_ksplice_nonreloc_howto(kreloc_ss, &kreloc->howto, type, 0);
1845 static void write_ksplice_nonreloc_howto(struct supersect *ss,
1846 const struct ksplice_reloc_howto
1847 *const *addr,
1848 enum ksplice_reloc_howto_type type,
1849 int size)
1851 struct supersect *khowto_ss =
1852 make_section(ss->parent, ".ksplice_reloc_howtos");
1853 struct ksplice_reloc_howto *khowto =
1854 sect_grow(khowto_ss, 1, struct ksplice_reloc_howto);
1856 khowto->type = type;
1857 khowto->size = size;
1858 khowto->pcrel = 0;
1859 khowto->dst_mask = 0;
1860 khowto->rightshift = 0;
1861 khowto->signed_addend = 0;
1862 write_reloc(ss, addr, &khowto_ss->symbol,
1863 addr_offset(khowto_ss, khowto));
1866 static void write_ksplice_symbol_reloc(struct supersect *ss,
1867 const char *sectname,
1868 unsigned long *addr, asymbol *sym,
1869 const char *label, const char *name)
1871 struct supersect *kreloc_ss;
1872 kreloc_ss = make_section(ss->parent, ".ksplice_relocs%s", sectname);
1873 struct ksplice_reloc *kreloc = sect_grow(kreloc_ss, 1,
1874 struct ksplice_reloc);
1876 write_ksplice_symbol_backend(kreloc_ss, &kreloc->symbol, sym, label,
1877 name);
1878 write_reloc(kreloc_ss, &kreloc->blank_addr, &ss->symbol,
1879 addr_offset(ss, addr));
1880 write_ksplice_nonreloc_howto(kreloc_ss, &kreloc->howto,
1881 KSPLICE_HOWTO_SYMBOL, 0);
1884 static void write_ksplice_section(struct span *span)
1886 struct supersect *ss = span->ss;
1887 const char *sectname = span->ss->name;
1888 const struct table_section *ts = get_table_section(ss->name);
1890 if (ts != NULL && ts->has_addr) {
1891 arelent *reloc = find_reloc(ss, ss->contents.data + span->start
1892 + ts->addr_offset);
1893 assert(reloc != NULL);
1894 asymbol *rsym = *reloc->sym_ptr_ptr;
1895 assert(!bfd_is_const_section(rsym->section));
1896 sectname = rsym->section->name;
1899 struct supersect *ksect_ss =
1900 make_section(ss->parent, ".ksplice_sections%s", sectname);
1901 struct ksplice_section *ksect = sect_grow(ksect_ss, 1,
1902 struct ksplice_section);
1903 asymbol *sym = span->symbol == NULL ? ss->symbol : span->symbol;
1905 write_ksplice_symbol(ksect_ss, &ksect->symbol, sym, span,
1906 mode("keep-new-code") ? "(post)" : "");
1907 ksect->size = span->size;
1908 ksect->flags = 0;
1910 if (ss->type == SS_TYPE_RODATA || ss->type == SS_TYPE_STRING ||
1911 ss->type == SS_TYPE_EXPORT || ss->type == SS_TYPE_BUGTABLE)
1912 ksect->flags |= KSPLICE_SECTION_RODATA;
1913 if (ss->type == SS_TYPE_DATA)
1914 ksect->flags |= KSPLICE_SECTION_DATA;
1915 if (ss->type == SS_TYPE_TEXT)
1916 ksect->flags |= KSPLICE_SECTION_TEXT;
1917 assert(ksect->flags != 0);
1919 if (ss->type == SS_TYPE_STRING)
1920 ksect->flags |= KSPLICE_SECTION_STRING;
1922 write_reloc(ksect_ss, &ksect->address, &ss->symbol,
1923 span->start + span->shift);
1925 if (mode("keep-old-code")) {
1926 /* Write ksplice_symbols for all the entry points */
1927 struct entry_point *entry;
1928 for (entry = span->entry_points.data;
1929 entry < span->entry_points.data + span->entry_points.size;
1930 entry++)
1931 write_ksplice_symbol_reloc
1932 (span->ss, sectname, span->ss->contents.data +
1933 span->start + span->shift + entry->offset,
1934 entry->symbol, entry->label, entry->name);
1938 static void write_ksplice_patch_reloc(struct supersect *ss,
1939 const char *sectname, unsigned long *addr,
1940 bfd_size_type size, const char *label,
1941 long addend)
1943 struct supersect *kreloc_ss;
1944 kreloc_ss = make_section(ss->parent, ".ksplice_relocs%s", sectname);
1945 struct ksplice_reloc *kreloc = sect_grow(kreloc_ss, 1,
1946 struct ksplice_reloc);
1948 write_canary(ss, addr_offset(ss, addr), size, -1);
1949 write_ksplice_symbol_backend(kreloc_ss, &kreloc->symbol, NULL,
1950 label, NULL);
1951 write_reloc(kreloc_ss, &kreloc->blank_addr, &ss->symbol,
1952 addr_offset(ss, addr));
1953 reloc_howto_type *howto =
1954 bfd_reloc_type_lookup(ss->parent->abfd,
1955 PASTE(BFD_RELOC_, LONG_BIT));
1956 write_ksplice_reloc_howto(kreloc_ss, &kreloc->howto, howto,
1957 KSPLICE_HOWTO_RELOC);
1958 kreloc->target_addend = addend;
1959 kreloc->insn_addend = 0;
1962 /* Assumes symbol is global, aka only one symbol of that name */
1963 static asymbol *name_to_symbol(struct superbfd *sbfd, const char *name)
1965 if (name == NULL)
1966 return NULL;
1968 asymbol **symp;
1969 for (symp = sbfd->syms.data;
1970 symp < sbfd->syms.data + sbfd->syms.size; symp++) {
1971 asymbol *sym = *symp;
1972 if (strcmp(name, sym->name) == 0 &&
1973 ((sym->flags & BSF_GLOBAL) != 0 ||
1974 bfd_is_und_section(sym->section)))
1975 return sym;
1977 return NULL;
1980 void write_ksplice_patches(struct superbfd *sbfd, struct span *span)
1982 if (span->datapatch) {
1983 write_ksplice_patch(sbfd, span, span->label, 0);
1984 return;
1987 assert(span->patch);
1989 long prev_offset = LONG_MIN;
1990 asymbol *prev_sym = NULL;
1991 const char *prev_label = NULL;
1992 struct entry_point *entry;
1993 for (entry = span->pre_entry_points.data;
1994 entry < span->pre_entry_points.data + span->pre_entry_points.size;
1995 entry++) {
1996 asymbol *sym = name_to_symbol(sbfd, entry->name);
1998 if (entry->offset != prev_offset) {
1999 debug1(sbfd, "entry point: %s(%s) %lx\n", entry->label,
2000 entry->name, entry->offset);
2002 if (prev_offset + MAX_TRAMPOLINE_SIZE > entry->offset) {
2003 err(sbfd,
2004 "Overlapping trampolines: %s %lx/%lx\n",
2005 span->label, prev_offset, entry->offset);
2006 DIE;
2009 long target_offset = 0;
2010 if (sym != NULL)
2011 target_offset = sym->value - span->start;
2012 write_ksplice_patch(sbfd, span, entry->label,
2013 target_offset);
2014 prev_offset = entry->offset;
2015 prev_sym = NULL;
2018 if (prev_sym == NULL) {
2019 prev_sym = sym;
2020 prev_label = entry->label;
2021 } else if (sym != NULL &&
2022 (prev_sym->section != sym->section ||
2023 prev_sym->value != sym->value)) {
2024 err(sbfd, "Splitting global symbols in the middle of a "
2025 "span: %s+%lx != %s+%lx!\n",
2026 prev_label, (unsigned long)prev_sym->value,
2027 entry->label, (unsigned long)sym->value);
2028 DIE;
2032 if (prev_offset + MAX_TRAMPOLINE_SIZE > span->size) {
2033 err(sbfd, "Trampoline ends outside span: %s %lx/%lx\n",
2034 span->label, prev_offset, (unsigned long)span->size);
2035 DIE;
2039 void write_ksplice_patch(struct superbfd *sbfd, struct span *span,
2040 const char *label, long offset)
2042 struct supersect *kpatch_ss =
2043 make_section(sbfd, ".ksplice_patches%s", span->ss->name);
2044 struct ksplice_patch *kpatch = sect_grow(kpatch_ss, 1,
2045 struct ksplice_patch);
2047 write_ksplice_patch_reloc(kpatch_ss, span->ss->name, &kpatch->oldaddr,
2048 sizeof(kpatch->oldaddr), label, 0);
2049 if (span->ss->type == SS_TYPE_TEXT) {
2050 kpatch->type = KSPLICE_PATCH_TEXT;
2051 write_patch_storage(kpatch_ss, kpatch, MAX_TRAMPOLINE_SIZE,
2052 NULL);
2053 } else {
2054 kpatch->type = KSPLICE_PATCH_DATA;
2055 kpatch->size = span->contents_size;
2056 struct supersect *data_ss =
2057 make_section(sbfd, ".ksplice_patch_data");
2058 write_reloc(kpatch_ss, &kpatch->contents, &span->ss->symbol,
2059 span->start + span->shift);
2060 char *saved = sect_do_grow(data_ss, 1, span->contents_size, 1);
2061 write_reloc(kpatch_ss, &kpatch->saved, &data_ss->symbol,
2062 addr_offset(data_ss, saved));
2064 write_reloc(kpatch_ss, &kpatch->repladdr, &span->ss->symbol,
2065 span->start + span->shift + offset);
2068 asymbol **make_undefined_symbolp(struct superbfd *sbfd, const char *name)
2070 asymbol **symp;
2071 for (symp = sbfd->syms.data; symp < sbfd->syms.data + sbfd->syms.size;
2072 symp++) {
2073 asymbol *sym = *symp;
2074 if (strcmp(name, sym->name) == 0 &&
2075 bfd_is_und_section(sym->section))
2076 return symp;
2078 asymbol ***sympp;
2079 for (sympp = sbfd->new_syms.data;
2080 sympp < sbfd->new_syms.data + sbfd->new_syms.size; sympp++) {
2081 asymbol **symp = *sympp;
2082 asymbol *sym = *symp;
2083 if (strcmp(name, sym->name) == 0 &&
2084 bfd_is_und_section(sym->section))
2085 return symp;
2088 symp = malloc(sizeof(*symp));
2089 *symp = bfd_make_empty_symbol(sbfd->abfd);
2090 asymbol *sym = *symp;
2091 sym->name = name;
2092 sym->section = bfd_und_section_ptr;
2093 sym->flags = 0;
2094 sym->value = 0;
2095 *vec_grow(&sbfd->new_syms, 1) = symp;
2096 return symp;
2099 void write_ksplice_deleted_patch(struct superbfd *sbfd, const char *name,
2100 const char *label, const char *sectname)
2102 struct supersect *kpatch_ss =
2103 make_section(sbfd, ".ksplice_patches%s", sectname);
2104 struct ksplice_patch *kpatch = sect_grow(kpatch_ss, 1,
2105 struct ksplice_patch);
2107 write_ksplice_patch_reloc(kpatch_ss, sectname, &kpatch->oldaddr,
2108 sizeof(kpatch->oldaddr), label, 0);
2109 kpatch->type = KSPLICE_PATCH_TEXT;
2110 asymbol **symp = make_undefined_symbolp(sbfd, strdup(name));
2111 write_reloc(kpatch_ss, &kpatch->repladdr, symp, 0);
2112 write_patch_storage(kpatch_ss, kpatch, MAX_TRAMPOLINE_SIZE, NULL);
2115 void write_ksplice_export(struct superbfd *sbfd, struct span *span, bool del)
2117 struct supersect *kpatch_ss = make_section(sbfd, ".ksplice_patches");
2118 struct ksplice_patch *kpatch = sect_grow(kpatch_ss, 1,
2119 struct ksplice_patch);
2120 struct supersect *data_ss;
2122 const struct table_section *ts = get_table_section(span->ss->name);
2123 assert(ts != NULL);
2124 const char **addr =
2125 span->ss->contents.data + span->start + ts->other_offset;
2126 const char *symname = read_string(span->ss, addr);
2128 char *oldname, *newname;
2129 if (del) {
2130 oldname = strprintf("%s:%s", span->ss->name, symname);
2131 newname = strprintf("DISABLED_%s_%s", symname, kid);
2132 } else {
2133 oldname = strprintf("%s:DISABLED_%s_%s", span->ss->name,
2134 symname, kid);
2135 newname = strprintf("%s", symname);
2136 write_string(span->ss, addr, "DISABLED_%s_%s", symname, kid);
2139 write_ksplice_patch_reloc(kpatch_ss, "", &kpatch->oldaddr,
2140 sizeof(kpatch->oldaddr), oldname,
2141 ts->other_offset);
2142 kpatch->type = KSPLICE_PATCH_EXPORT;
2143 const char **namep = write_patch_storage(kpatch_ss, kpatch,
2144 sizeof(newname), &data_ss);
2145 write_string(data_ss, namep, "%s", newname);
2148 void filter_table_sections(struct superbfd *isbfd)
2150 struct supersect *tables_ss =
2151 fetch_supersect(offsets_sbfd,
2152 bfd_get_section_by_name(offsets_sbfd->abfd,
2153 ".ksplice_table_sections"));
2154 const struct table_section *ts;
2155 for (ts = tables_ss->contents.data;
2156 (void *)ts < tables_ss->contents.data + tables_ss->contents.size;
2157 ts++) {
2158 struct table_section s = *ts;
2159 s.sect = read_string(tables_ss, &ts->sect);
2160 s.other_sect = read_string(tables_ss, &ts->other_sect);
2161 s.crc_sect = read_string(tables_ss, &ts->crc_sect);
2162 filter_table_section(isbfd, &s);
2166 void filter_table_section(struct superbfd *sbfd, const struct table_section *s)
2168 asection *isection = bfd_get_section_by_name(sbfd->abfd, s->sect);
2169 if (isection == NULL)
2170 return;
2171 struct supersect *ss = fetch_supersect(sbfd, isection);
2173 void *entry;
2174 for (entry = ss->contents.data;
2175 entry < ss->contents.data + ss->contents.size;
2176 entry += s->entry_size) {
2177 struct span *span = find_span(ss, addr_offset(ss, entry));
2178 assert(span != NULL);
2180 if (s->has_addr) {
2181 struct span *sym_span =
2182 span_offset_target_span(span, s->addr_offset);
2183 assert(sym_span != NULL);
2184 if (sym_span->keep)
2185 keep_span(span);
2188 if (s->other_sect != NULL) {
2189 struct span *sym_span =
2190 span_offset_target_span(span, s->other_offset);
2191 assert(sym_span != NULL);
2192 if (span->keep)
2193 keep_span(sym_span);
2196 if (s->crc_sect != NULL) {
2197 struct span *crc_span = get_crc_span(span, s);
2198 assert(crc_span != NULL);
2199 if (span->keep && mode("keep-new-code"))
2200 keep_span(crc_span);
2205 static void match_table_spans(struct span *old_span, struct span *new_span)
2207 const struct table_section *ts = get_table_section(old_span->ss->name);
2209 if (strcmp(old_span->ss->name, new_span->ss->name) != 0)
2210 return;
2211 if (ts == NULL || old_span->ss->type != SS_TYPE_SPECIAL ||
2212 new_span->ss->type != SS_TYPE_SPECIAL)
2213 return;
2214 if (old_span->match != NULL || new_span->match != NULL)
2215 return;
2217 if (ts->has_addr) {
2218 void *old_entry = old_span->ss->contents.data + old_span->start;
2219 void *new_entry = new_span->ss->contents.data + new_span->start;
2220 arelent *old_reloc =
2221 find_reloc(old_span->ss, old_entry + ts->addr_offset);
2222 arelent *new_reloc =
2223 find_reloc(new_span->ss, new_entry + ts->addr_offset);
2224 assert(old_reloc != NULL && new_reloc != NULL);
2225 struct span *old_sym_span =
2226 reloc_target_span(old_span->ss, old_reloc);
2227 struct span *new_sym_span =
2228 reloc_target_span(new_span->ss, new_reloc);
2229 assert(old_sym_span != NULL && new_sym_span != NULL);
2230 if (old_sym_span->match == new_sym_span &&
2231 new_sym_span->match == old_sym_span &&
2232 old_reloc->address - old_sym_span->start ==
2233 new_reloc->address - new_sym_span->start)
2234 match_spans(old_span, new_span);
2238 static struct span *get_crc_span(struct span *span,
2239 const struct table_section *ts)
2241 void *entry = span->ss->contents.data + span->start;
2242 asection *crc_sect = bfd_get_section_by_name(span->ss->parent->abfd,
2243 ts->crc_sect);
2244 if (crc_sect == NULL)
2245 return NULL;
2246 struct supersect *crc_ss = fetch_supersect(span->ss->parent, crc_sect);
2247 if (crc_ss == NULL)
2248 return NULL;
2249 struct span *crc_span = find_span(crc_ss, addr_offset(span->ss, entry) /
2250 ts->entry_size * ts->crc_size);
2251 return crc_span;
2254 void mark_precallable_spans(struct superbfd *sbfd)
2256 asection *sect;
2257 struct supersect *ss, *sym_ss;
2258 struct span *address_span, *target_span;
2259 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2260 ss = fetch_supersect(sbfd, sect);
2261 arelent **relocp;
2262 if (ss->type == SS_TYPE_SPECIAL)
2263 continue;
2264 for (relocp = ss->relocs.data;
2265 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
2266 asymbol *sym = *(*relocp)->sym_ptr_ptr;
2267 address_span = find_span(ss, (*relocp)->address);
2268 if (!address_span->precallable)
2269 continue;
2270 target_span = reloc_target_span(ss, *relocp);
2271 if (target_span == NULL || target_span->keep)
2272 continue;
2273 sym_ss = fetch_supersect(sbfd, sym->section);
2274 if (sym_ss->type == SS_TYPE_IGNORED)
2275 continue;
2276 target_span->precallable = true;
2277 changed = true;
2282 void keep_referenced_sections(struct superbfd *sbfd)
2284 asection *sect;
2285 struct supersect *ss, *sym_ss;
2286 struct span *address_span, *target_span;
2287 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2288 ss = fetch_supersect(sbfd, sect);
2289 arelent **relocp;
2290 if (ss->type == SS_TYPE_SPECIAL)
2291 continue;
2292 for (relocp = ss->relocs.data;
2293 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
2294 asymbol *sym = *(*relocp)->sym_ptr_ptr;
2295 address_span = find_span(ss, (*relocp)->address);
2296 if (!address_span->keep)
2297 continue;
2298 target_span = reloc_target_span(ss, *relocp);
2299 if (target_span == NULL || target_span->keep)
2300 continue;
2301 sym_ss = fetch_supersect(sbfd, sym->section);
2302 if (sym_ss->type == SS_TYPE_IGNORED)
2303 continue;
2304 keep_span(target_span);
2305 changed = true;
2310 void copy_symbols(struct asymbolp_vec *osyms, struct asymbolpp_vec *isyms)
2312 asymbol ***sympp;
2313 for (sympp = isyms->data; sympp < isyms->data + isyms->size; sympp++)
2314 *vec_grow(osyms, 1) = **sympp;
2317 /* Modified function from GNU Binutils objcopy.c */
2318 bfd_boolean copy_object(bfd *ibfd, bfd *obfd)
2320 assert(bfd_set_format(obfd, bfd_get_format(ibfd)));
2322 bfd_vma start = bfd_get_start_address(ibfd);
2324 flagword flags = bfd_get_file_flags(ibfd);
2325 flags &= bfd_applicable_file_flags(obfd);
2327 assert(bfd_set_start_address(obfd, start)
2328 && bfd_set_file_flags(obfd, flags));
2330 enum bfd_architecture iarch = bfd_get_arch(ibfd);
2331 unsigned int imach = bfd_get_mach(ibfd);
2332 assert(bfd_set_arch_mach(obfd, iarch, imach));
2333 assert(bfd_set_format(obfd, bfd_get_format(ibfd)));
2335 /* BFD mandates that all output sections be created and sizes set before
2336 any output is done. Thus, we traverse all sections multiple times. */
2337 bfd_map_over_sections(ibfd, setup_section, obfd);
2339 struct supersect *new_supersects = fetch_superbfd(ibfd)->new_supersects;
2340 struct supersect *ss;
2341 for (ss = new_supersects; ss != NULL; ss = ss->next)
2342 setup_new_section(obfd, ss);
2344 /* Mark symbols used in output relocations so that they
2345 are kept, even if they are local labels or static symbols.
2347 Note we iterate over the input sections examining their
2348 relocations since the relocations for the output sections
2349 haven't been set yet. mark_symbols_used_in_relocations will
2350 ignore input sections which have no corresponding output
2351 section. */
2353 bfd_map_over_sections(ibfd, mark_symbols_used_in_relocations, NULL);
2354 for (ss = new_supersects; ss != NULL; ss = ss->next)
2355 ss_mark_symbols_used_in_relocations(ss);
2356 struct asymbolp_vec osyms;
2357 vec_init(&osyms);
2358 filter_symbols(ibfd, obfd, &osyms, &fetch_superbfd(ibfd)->syms);
2359 copy_symbols(&osyms, &fetch_superbfd(ibfd)->new_syms);
2361 bfd_set_symtab(obfd, osyms.data, osyms.size);
2363 /* This has to happen after the symbol table has been set. */
2364 bfd_map_over_sections(obfd, write_section, NULL);
2366 /* Allow the BFD backend to copy any private data it understands
2367 from the input BFD to the output BFD. This is done last to
2368 permit the routine to look at the filtered symbol table, which is
2369 important for the ECOFF code at least. */
2370 assert(bfd_copy_private_bfd_data(ibfd, obfd));
2372 return TRUE;
2375 /* Modified function from GNU Binutils objcopy.c */
2376 void setup_section(bfd *ibfd, asection *isection, void *obfdarg)
2378 struct superbfd *isbfd = fetch_superbfd(ibfd);
2379 struct supersect *ss = fetch_supersect(isbfd, isection);
2380 bfd *obfd = obfdarg;
2381 bfd_vma vma;
2383 if (!ss->keep)
2384 return;
2386 asection *osection = bfd_make_section_anyway(obfd, ss->name);
2387 assert(osection != NULL);
2389 osection->userdata = ss;
2390 bfd_set_section_flags(obfd, osection, ss->flags);
2391 ss->symbol = osection->symbol;
2392 assert(bfd_set_section_size(obfd, osection, ss->contents.size));
2394 vma = bfd_section_vma(ibfd, isection);
2395 assert(bfd_set_section_vma(obfd, osection, vma));
2397 osection->lma = isection->lma;
2398 assert(bfd_set_section_alignment(obfd, osection, ss->alignment));
2399 osection->entsize = ss->entsize;
2400 osection->output_section = osection;
2401 osection->output_offset = 0;
2402 isection->output_section = osection;
2403 isection->output_offset = 0;
2404 return;
2407 void setup_new_section(bfd *obfd, struct supersect *ss)
2409 asection *osection = bfd_make_section_anyway(obfd, ss->name);
2410 assert(osection != NULL);
2411 bfd_set_section_flags(obfd, osection, ss->flags);
2413 osection->userdata = ss;
2414 ss->symbol = osection->symbol;
2415 assert(bfd_set_section_size(obfd, osection, ss->contents.size));
2416 assert(bfd_set_section_vma(obfd, osection, 0));
2418 osection->lma = 0;
2419 assert(bfd_set_section_alignment(obfd, osection, ss->alignment));
2420 osection->entsize = ss->entsize;
2421 osection->output_section = osection;
2422 osection->output_offset = 0;
2425 static int compare_reloc_addresses(const void *aptr, const void *bptr)
2427 const arelent *const *a = aptr, *const *b = bptr;
2428 return (*a)->address - (*b)->address;
2431 static void delete_obsolete_relocs(struct supersect *ss)
2433 if (ss->new_relocs.size == 0)
2434 return;
2436 qsort(ss->relocs.data, ss->relocs.size, sizeof(*ss->relocs.data),
2437 compare_reloc_addresses);
2438 qsort(ss->new_relocs.data, ss->new_relocs.size,
2439 sizeof(*ss->new_relocs.data), compare_reloc_addresses);
2441 struct arelentp_vec orig_relocs;
2442 vec_move(&orig_relocs, &ss->relocs);
2444 arelent **relocp, **new_relocp = ss->new_relocs.data;
2445 for (relocp = orig_relocs.data;
2446 relocp < orig_relocs.data + orig_relocs.size; relocp++) {
2447 while (new_relocp < ss->new_relocs.data + ss->new_relocs.size &&
2448 (*new_relocp)->address < (*relocp)->address)
2449 new_relocp++;
2450 arelent *reloc = *relocp, *new_reloc = *new_relocp;
2451 if (new_relocp == ss->new_relocs.data + ss->new_relocs.size ||
2452 reloc->address != new_reloc->address)
2453 *vec_grow(&ss->relocs, 1) = reloc;
2457 void write_section(bfd *obfd, asection *osection, void *arg)
2459 struct supersect *ss = osection->userdata;
2461 if ((ss->flags & SEC_GROUP) != 0 || ss->contents.size == 0)
2462 return;
2464 delete_obsolete_relocs(ss);
2466 arelent **relocp;
2467 char *error_message;
2468 for (relocp = ss->new_relocs.data;
2469 relocp < ss->new_relocs.data + ss->new_relocs.size; relocp++) {
2470 bfd_vma val;
2471 if (bfd_get_arch(obfd) == bfd_arch_arm)
2472 val = osection->use_rela_p ? 0 : (*relocp)->addend;
2473 else
2474 val = 0;
2475 bfd_put(bfd_get_reloc_size((*relocp)->howto) * 8, obfd, val,
2476 ss->contents.data + (*relocp)->address);
2477 if (bfd_install_relocation(obfd, *relocp, ss->contents.data,
2478 0, osection, &error_message) !=
2479 bfd_reloc_ok) {
2480 err(ss->parent, "ksplice: error installing reloc: %s",
2481 error_message);
2482 DIE;
2484 if (mode("finalize")) {
2485 /* Check that all our sections will be allocated */
2486 asymbol *sym = *((*relocp)->sym_ptr_ptr);
2487 if (!bfd_is_const_section(sym->section)) {
2488 struct supersect *sym_ss =
2489 fetch_supersect(ss->parent, sym->section);
2490 assert((sym_ss->flags & SEC_ALLOC) != 0);
2494 memcpy(vec_grow(&ss->relocs, ss->new_relocs.size), ss->new_relocs.data,
2495 ss->new_relocs.size * sizeof(*ss->new_relocs.data));
2497 bfd_set_reloc(obfd, osection,
2498 ss->relocs.size == 0 ? NULL : ss->relocs.data,
2499 ss->relocs.size);
2501 if (ss->flags & SEC_HAS_CONTENTS)
2502 assert(bfd_set_section_contents
2503 (obfd, osection, ss->contents.data, 0,
2504 ss->contents.size));
2507 /* Modified function from GNU Binutils objcopy.c
2509 * Mark all the symbols which will be used in output relocations with
2510 * the BSF_KEEP flag so that those symbols will not be stripped.
2512 * Ignore relocations which will not appear in the output file.
2514 void mark_symbols_used_in_relocations(bfd *abfd, asection *isection,
2515 void *ignored)
2517 struct superbfd *sbfd = fetch_superbfd(abfd);
2518 if (isection->output_section == NULL)
2519 return;
2521 struct supersect *ss = fetch_supersect(sbfd, isection);
2522 ss_mark_symbols_used_in_relocations(ss);
2525 void ss_mark_symbols_used_in_relocations(struct supersect *ss)
2527 /* Examine each symbol used in a relocation. If it's not one of the
2528 special bfd section symbols, then mark it with BSF_KEEP. */
2529 arelent **relocp;
2530 for (relocp = ss->relocs.data;
2531 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
2532 asymbol *sym = *(*relocp)->sym_ptr_ptr;
2533 if (!(bfd_is_const_section(sym->section) &&
2534 sym == sym->section->symbol))
2535 sym->flags |= BSF_KEEP;
2537 for (relocp = ss->new_relocs.data;
2538 relocp < ss->new_relocs.data + ss->new_relocs.size; relocp++) {
2539 asymbol *sym = *(*relocp)->sym_ptr_ptr;
2540 if (!(bfd_is_const_section(sym->section) &&
2541 sym == sym->section->symbol))
2542 sym->flags |= BSF_KEEP;
2546 static bool deleted_table_section_symbol(bfd *abfd, asymbol *sym)
2548 struct superbfd *sbfd = fetch_superbfd(abfd);
2549 if (bfd_is_const_section(sym->section))
2550 return false;
2551 struct supersect *ss = fetch_supersect(sbfd, sym->section);
2553 asymbol **symp;
2554 for (symp = ss->syms.data; symp < ss->syms.data + ss->syms.size; symp++) {
2555 if (sym == *symp)
2556 break;
2558 return symp >= ss->syms.data + ss->syms.size &&
2559 (sym->flags & BSF_SECTION_SYM) == 0;
2562 void filter_symbols(bfd *ibfd, bfd *obfd, struct asymbolp_vec *osyms,
2563 struct asymbolp_vec *isyms)
2565 asymbol **symp;
2566 struct superbfd *sbfd = fetch_superbfd(ibfd);
2567 for (symp = isyms->data; symp < isyms->data + isyms->size; symp++) {
2568 asymbol *sym = *symp;
2569 struct supersect *sym_ss = NULL;
2570 struct span *sym_span = NULL;
2571 if (!bfd_is_const_section(sym->section)) {
2572 sym_ss = fetch_supersect(sbfd, sym->section);
2573 sym_span = find_span(sym_ss, sym->value);
2576 if (mode("keep") && (sym->flags & BSF_GLOBAL) != 0 &&
2577 !(mode("keep-new-code") && sym_span != NULL &&
2578 sym_span->new))
2579 sym->flags = (sym->flags & ~BSF_GLOBAL) | BSF_LOCAL;
2581 if (mode("finalize") && (sym->flags & BSF_GLOBAL) != 0)
2582 sym->flags = (sym->flags & ~BSF_GLOBAL) | BSF_LOCAL;
2584 bool keep = bfd_is_const_section(sym->section) ||
2585 (sym_ss->keep && (sym->flags & BSF_SECTION_SYM) != 0) ||
2586 (sym_span != NULL && sym_span->keep);
2587 if (bfd_is_und_section(sym->section) &&
2588 (sym->flags & BSF_KEEP) == 0)
2589 keep = false;
2590 if (bfd_is_abs_section(sym->section) &&
2591 (sym->flags & BSF_KEEP) == 0 &&
2592 (sym->flags & BSF_FILE) == 0)
2593 keep = false;
2594 if (deleted_table_section_symbol(ibfd, sym))
2595 keep = false;
2597 if (mode("keep-old-code") && sym_ss != NULL &&
2598 sym_ss->type == SS_TYPE_EXPORT)
2599 keep = false;
2601 if (keep) {
2602 if (sym_ss != NULL && !sym_ss->keep) {
2603 err(sbfd, "Kept symbol %s in unkept section "
2604 "%s\n", sym->name, sym->section->name);
2605 DIE;
2607 *vec_grow(osyms, 1) = sym;
2612 static bool is_table_section(const char *name, bool consider_other,
2613 bool consider_crc)
2615 struct supersect *tables_ss =
2616 fetch_supersect(offsets_sbfd,
2617 bfd_get_section_by_name(offsets_sbfd->abfd,
2618 ".ksplice_table_sections"));
2619 const struct table_section *ts;
2620 for (ts = tables_ss->contents.data;
2621 (void *)ts < tables_ss->contents.data + tables_ss->contents.size;
2622 ts++) {
2623 if (strcmp(name, read_string(tables_ss, &ts->sect)) == 0)
2624 return true;
2625 const char *osect_name = read_string(tables_ss,
2626 &ts->other_sect);
2627 if (consider_other && osect_name != NULL &&
2628 strcmp(name, osect_name) == 0)
2629 return true;
2630 const char *crc_name = read_string(tables_ss, &ts->crc_sect);
2631 if (consider_crc && crc_name != NULL &&
2632 strcmp(name, crc_name) == 0)
2633 return true;
2635 return false;
2638 const struct table_section *get_table_section(const char *name)
2640 struct supersect *tables_ss =
2641 fetch_supersect(offsets_sbfd,
2642 bfd_get_section_by_name(offsets_sbfd->abfd,
2643 ".ksplice_table_sections"));
2644 const struct table_section *ts;
2645 for (ts = tables_ss->contents.data;
2646 (void *)ts < tables_ss->contents.data + tables_ss->contents.size;
2647 ts++) {
2648 if (strcmp(name, read_string(tables_ss, &ts->sect)) == 0) {
2649 if (ts->entry_contents_size != 0)
2650 assert(align(ts->entry_contents_size,
2651 ts->entry_align) ==
2652 ts->entry_size);
2653 struct table_section *ns = malloc(sizeof(*ns));
2654 *ns = *ts;
2655 ns->sect = read_string(tables_ss, &ts->sect);
2656 ns->crc_sect = read_string(tables_ss, &ts->crc_sect);
2657 ns->other_sect =
2658 read_string(tables_ss, &ts->other_sect);
2659 return ns;
2662 return NULL;
2665 enum supersect_type supersect_type(struct supersect *ss)
2667 if (mode("finalize") &&
2668 strcmp(finalize_target, "vmlinux") == 0 &&
2669 (strstarts(ss->name, ".ksplice_relocs.exit") ||
2670 strstarts(ss->name, ".ksplice_sections.exit") ||
2671 strstarts(ss->name, ".ksplice_patches.exit")))
2672 return SS_TYPE_EXIT;
2673 if (strstarts(ss->name, ".ksplice_call"))
2674 return SS_TYPE_KSPLICE_CALL;
2675 if (strstarts(ss->name, ".ksplice_extract"))
2676 return SS_TYPE_KSPLICE_EXTRACT;
2677 if (strstarts(ss->name, ".ksplice_options"))
2678 return SS_TYPE_SPECIAL;
2679 if (strstarts(ss->name, ".ksplice"))
2680 return SS_TYPE_KSPLICE;
2682 if (strstarts(ss->name, ".init"))
2683 return SS_TYPE_IGNORED;
2684 if (strstarts(ss->name, ".security_initcall.init"))
2685 return SS_TYPE_IGNORED;
2686 if (strstarts(ss->name, ".con_initcall.init"))
2687 return SS_TYPE_IGNORED;
2688 if (strstarts(ss->name, ".x86cpuvendor.init"))
2689 return SS_TYPE_IGNORED;
2690 if (strstarts(ss->name, ".early_param.init"))
2691 return SS_TYPE_IGNORED;
2692 if (strstarts(ss->name, ".taglist.init"))
2693 return SS_TYPE_IGNORED;
2694 if (strstarts(ss->name, ".arch.info.init"))
2695 return SS_TYPE_IGNORED;
2696 if (strstarts(ss->name, ".proc.info.init"))
2697 return SS_TYPE_IGNORED;
2698 /* .pci_fixup_* sections really should be treated as global rodata
2699 referenced only from quirks.c */
2700 if (strstarts(ss->name, ".pci_fixup_"))
2701 return SS_TYPE_IGNORED;
2702 /* .builtin_fw sections are similar to .pci_fixup */
2703 if (strstarts(ss->name, ".builtin_fw"))
2704 return SS_TYPE_IGNORED;
2705 /* same for .tracedata */
2706 if (strstarts(ss->name, ".tracedata"))
2707 return SS_TYPE_IGNORED;
2708 if (strstarts(ss->name, ".debug"))
2709 return SS_TYPE_IGNORED;
2710 /* .eh_frame should probably be discarded, not ignored */
2711 if (strstarts(ss->name, ".eh_frame"))
2712 return SS_TYPE_IGNORED;
2713 if (config->ignore_devinit && strstarts(ss->name, ".devinit"))
2714 return SS_TYPE_IGNORED;
2715 if (config->ignore_meminit && strstarts(ss->name, ".meminit"))
2716 return SS_TYPE_IGNORED;
2717 if (config->ignore_cpuinit && strstarts(ss->name, ".cpuinit"))
2718 return SS_TYPE_IGNORED;
2719 if (config->ignore_devinit && strstarts(ss->name, ".devexit"))
2720 return SS_TYPE_IGNORED;
2721 if (config->ignore_meminit && strstarts(ss->name, ".memexit"))
2722 return SS_TYPE_IGNORED;
2723 if (config->ignore_cpuinit && strstarts(ss->name, ".cpuexit"))
2724 return SS_TYPE_IGNORED;
2725 if (strstarts(ss->name, ".vgetcpu_mode") ||
2726 strstarts(ss->name, ".jiffies") ||
2727 strstarts(ss->name, ".wall_jiffies") ||
2728 strstarts(ss->name, ".vxtime") ||
2729 strstarts(ss->name, ".sys_tz") ||
2730 strstarts(ss->name, ".sysctl_vsyscall") ||
2731 strstarts(ss->name, ".xtime") ||
2732 strstarts(ss->name, ".xtime_lock") ||
2733 strstarts(ss->name, ".vsyscall"))
2734 return SS_TYPE_IGNORED;
2735 if (strstarts(ss->name, ".vdso"))
2736 return SS_TYPE_IGNORED;
2738 if (strstarts(ss->name, ".exit.text"))
2739 return SS_TYPE_TEXT;
2740 if (strstarts(ss->name, ".exit.data"))
2741 return SS_TYPE_DATA;
2743 if (strstarts(ss->name, ".text") ||
2744 strstarts(ss->name, ".kernel.text") ||
2745 strstarts(ss->name, ".devinit.text") ||
2746 strstarts(ss->name, ".meminit.text") ||
2747 strstarts(ss->name, ".cpuinit.text") ||
2748 strstarts(ss->name, ".devexit.text") ||
2749 strstarts(ss->name, ".memexit.text") ||
2750 strstarts(ss->name, ".cpuexit.text") ||
2751 strstarts(ss->name, ".ref.text") ||
2752 strstarts(ss->name, ".spinlock.text") ||
2753 strstarts(ss->name, ".kprobes.text") ||
2754 strstarts(ss->name, ".sched.text") ||
2755 strstarts(ss->name, ".entry.text") || /* OpenVZ */
2756 (mode("keep-old-code") && strstarts(ss->name, ".fixup")))
2757 return SS_TYPE_TEXT;
2759 int n = -1;
2760 if (sscanf(ss->name, ".rodata.str%*u.%*u%n", &n) >= 0 &&
2761 n == strlen(ss->name))
2762 return ss->entsize == 1 ? SS_TYPE_STRING : SS_TYPE_RODATA;
2764 if (strstarts(ss->name, ".rodata") ||
2765 strstarts(ss->name, ".kernel.rodata") ||
2766 strstarts(ss->name, ".devinit.rodata") ||
2767 strstarts(ss->name, ".meminit.rodata") ||
2768 strstarts(ss->name, ".cpuinit.rodata") ||
2769 strstarts(ss->name, ".devexit.rodata") ||
2770 strstarts(ss->name, ".memexit.rodata") ||
2771 strstarts(ss->name, ".cpuexit.rodata") ||
2772 strstarts(ss->name, ".ref.rodata") ||
2773 strstarts(ss->name, "__markers_strings") ||
2774 (mode("keep-old-code") && strstarts(ss->name, "__ex_table")))
2775 return SS_TYPE_RODATA;
2777 if (strstarts(ss->name, ".bss"))
2778 return SS_TYPE_DATA;
2780 /* Ignore .data.percpu sections */
2781 if (strstarts(ss->name, ".data.percpu") ||
2782 strstarts(ss->name, ".kernel.data.percpu") ||
2783 strstarts(ss->name, ".data..percpu"))
2784 return SS_TYPE_IGNORED;
2785 if (strstarts(ss->name, ".data") ||
2786 strstarts(ss->name, ".kernel.data") ||
2787 strstarts(ss->name, ".devinit.data") ||
2788 strstarts(ss->name, ".cpuinit.data") ||
2789 strstarts(ss->name, ".meminit.data") ||
2790 strstarts(ss->name, ".devexit.data") ||
2791 strstarts(ss->name, ".memexit.data") ||
2792 strstarts(ss->name, ".cpuexit.data") ||
2793 strstarts(ss->name, ".ref.data") ||
2794 strstarts(ss->name, "__markers"))
2795 return SS_TYPE_DATA;
2797 /* We replace all the ksymtab strings, so delete them */
2798 if (strcmp(ss->name, "__ksymtab_strings") == 0)
2799 return SS_TYPE_STRING;
2800 if (strstarts(ss->name, "__ksymtab"))
2801 return SS_TYPE_EXPORT;
2803 if (strstarts(ss->name, "__bug_table"))
2804 return SS_TYPE_BUGTABLE;
2806 if (is_table_section(ss->name, true, true))
2807 return SS_TYPE_SPECIAL;
2809 if (strstarts(ss->name, ".ARM."))
2810 return SS_TYPE_SPECIAL;
2812 if (strstarts(ss->name, ".note"))
2813 return SS_TYPE_IGNORED;
2814 if (strstarts(ss->name, ".comment"))
2815 return SS_TYPE_IGNORED;
2816 if (strstarts(ss->name, "__param"))
2817 return SS_TYPE_IGNORED;
2818 if (strstarts(ss->name, "__obsparm"))
2819 return SS_TYPE_IGNORED;
2820 if (strstarts(ss->name, ".exitcall.exit"))
2821 return SS_TYPE_IGNORED;
2822 if (strstarts(ss->name, ".modinfo"))
2823 return SS_TYPE_IGNORED;
2825 return SS_TYPE_UNKNOWN;
2828 void initialize_supersect_types(struct superbfd *sbfd)
2830 asection *sect;
2831 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2832 struct supersect *ss = fetch_supersect(sbfd, sect);
2833 ss->type = supersect_type(ss);
2834 ss->orig_type = ss->type;
2835 if (ss->type == SS_TYPE_UNKNOWN) {
2836 err(sbfd, "Unknown section type: %s\n", ss->name);
2837 DIE;
2842 static void init_label_map(struct superbfd *sbfd)
2844 struct label_map *map;
2846 vec_init(&sbfd->maps);
2847 init_csyms(sbfd);
2848 init_callers(sbfd);
2850 struct symbol_hash csyms;
2851 symbol_hash_init(&csyms);
2853 asymbol **symp;
2854 for (symp = sbfd->syms.data;
2855 symp < sbfd->syms.data + sbfd->syms.size; symp++) {
2856 asymbol *csym = canonical_symbol(sbfd, *symp);
2857 if (csym == NULL)
2858 continue;
2859 char *key = strprintf("%p", csym);
2860 asymbol **csymp = symbol_hash_lookup(&csyms, key, TRUE);
2861 free(key);
2862 if (*csymp != NULL)
2863 continue;
2864 *csymp = csym;
2866 map = vec_grow(&sbfd->maps, 1);
2867 map->csym = csym;
2868 map->count = 0;
2869 map->label = symbol_label(sbfd, csym);
2872 struct label_mapp_hash label_maps;
2873 label_mapp_hash_init(&label_maps);
2874 for (map = sbfd->maps.data;
2875 map < sbfd->maps.data + sbfd->maps.size; map++) {
2876 struct label_map **mapp =
2877 label_mapp_hash_lookup(&label_maps, map->label, TRUE);
2878 if (*mapp == NULL) {
2879 *mapp = map;
2880 continue;
2883 struct label_map *first_map = *mapp;
2884 if (first_map->count == 0)
2885 first_map->label = strprintf("%s~%d", map->label, 0);
2886 map->label = strprintf("%s~%d", map->label, ++first_map->count);
2889 label_mapp_hash_init(&sbfd->maps_hash);
2890 for (map = sbfd->maps.data;
2891 map < sbfd->maps.data + sbfd->maps.size; map++) {
2892 char *key = strprintf("%p", map->csym);
2893 struct label_map **mapp =
2894 label_mapp_hash_lookup(&sbfd->maps_hash, key, TRUE);
2895 free(key);
2896 *mapp = map;
2897 map->orig_label = map->label;
2901 static const char *label_lookup(struct superbfd *sbfd, asymbol *sym)
2903 asymbol *csym = canonical_symbol(sbfd, sym);
2904 char *key = strprintf("%p", csym);
2905 struct label_map **mapp =
2906 label_mapp_hash_lookup(&sbfd->maps_hash, key, FALSE);
2907 free(key);
2908 if (mapp == NULL)
2909 DIE;
2910 return (*mapp)->label;
2913 static void print_label_changes(struct superbfd *sbfd)
2915 asection *sect;
2916 struct span *span;
2917 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2918 struct supersect *ss = fetch_supersect(sbfd, sect);
2919 for (span = ss->spans.data;
2920 span < ss->spans.data + ss->spans.size; span++) {
2921 if (strcmp(span->label, span->orig_label) != 0)
2922 debug1(sbfd, "Label change: %s -> %s\n",
2923 span->label, span->orig_label);
2928 static void label_map_set(struct superbfd *sbfd, const char *oldlabel,
2929 const char *label)
2931 struct label_map *map;
2932 for (map = sbfd->maps.data;
2933 map < sbfd->maps.data + sbfd->maps.size; map++) {
2934 if (strcmp(map->orig_label, oldlabel) == 0) {
2935 if (strcmp(map->orig_label, map->label) != 0 &&
2936 strcmp(map->label, label) != 0)
2937 DIE;
2938 map->label = label;
2939 return;
2942 DIE;
2945 static void change_initial_label(struct span *span, const char *label)
2947 struct superbfd *sbfd = span->ss->parent;
2948 span->label = label;
2949 span->orig_label = label;
2950 if (span->symbol) {
2951 asymbol *csym = canonical_symbol(sbfd, span->symbol);
2952 char *key = strprintf("%p", csym);
2953 struct label_map **mapp =
2954 label_mapp_hash_lookup(&sbfd->maps_hash, key, FALSE);
2955 free(key);
2956 assert(mapp);
2957 (*mapp)->label = span->label;
2958 (*mapp)->orig_label = span->orig_label;
2959 span->symbol = NULL;
2963 static void init_callers(struct superbfd *sbfd)
2965 string_hash_init(&sbfd->callers);
2966 asection *sect;
2967 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2968 struct supersect *ss = fetch_supersect(sbfd, sect);
2969 arelent **relocp;
2970 for (relocp = ss->relocs.data;
2971 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
2972 asymbol *sym = *(*relocp)->sym_ptr_ptr;
2973 unsigned long val =
2974 sym->value + reloc_target_offset(ss, *relocp);
2975 char *key = strprintf("%s+%lx", sym->section->name,
2976 val);
2977 const char **ret = string_hash_lookup(&sbfd->callers,
2978 key, TRUE);
2979 free(key);
2980 asymbol *csym = canonical_symbol(sbfd, sect->symbol);
2981 if (*ret != NULL)
2982 *ret = "*multiple_callers*";
2983 else if (static_local_symbol(sbfd, csym))
2984 *ret = static_local_symbol(sbfd, csym);
2985 else
2986 *ret = sect->name;
2991 static const char *find_caller(struct supersect *ss, asymbol *sym)
2993 char *key = strprintf("%s+%lx", sym->section->name,
2994 (unsigned long)sym->value);
2995 const char **ret = string_hash_lookup(&ss->parent->callers, key, FALSE);
2996 free(key);
2998 if (ret == NULL)
2999 return "*no_caller*";
3000 return *ret;
3003 static void init_csyms(struct superbfd *sbfd)
3005 asymbolpp_hash_init(&sbfd->csyms);
3007 asymbol **symp;
3008 for (symp = sbfd->syms.data; symp < sbfd->syms.data + sbfd->syms.size;
3009 symp++) {
3010 asymbol *sym = *symp;
3011 if ((sym->flags & BSF_DEBUGGING) != 0)
3012 continue;
3013 char *key = strprintf("%s+%lx", sym->section->name,
3014 (unsigned long)sym->value);
3015 asymbol ***csympp = asymbolpp_hash_lookup(&sbfd->csyms, key,
3016 TRUE);
3017 free(key);
3018 if (*csympp == NULL) {
3019 *csympp = symp;
3020 continue;
3022 asymbol *csym = **csympp;
3023 if ((csym->flags & BSF_GLOBAL) != 0)
3024 continue;
3025 if ((sym->flags & BSF_GLOBAL) != 0)
3026 *csympp = symp;
3030 static asymbol **symbolp_scan(struct supersect *ss, bfd_vma value)
3032 char *key = strprintf("%s+%lx", ss->name, (unsigned long)value);
3033 asymbol ***csympp =
3034 asymbolpp_hash_lookup(&ss->parent->csyms, key, FALSE);
3035 free(key);
3036 if (csympp != NULL)
3037 return *csympp;
3039 /* For section symbols of sections containing no symbols, return the
3040 section symbol that relocations are generated against */
3041 if (value == 0)
3042 return &ss->symbol;
3043 return NULL;
3046 static asymbol **canonical_symbolp(struct superbfd *sbfd, asymbol *sym)
3048 if (bfd_is_const_section(sym->section)) {
3049 asymbol **csymp;
3050 for (csymp = sbfd->syms.data;
3051 csymp < sbfd->syms.data + sbfd->syms.size; csymp++) {
3052 if (sym == *csymp)
3053 return csymp;
3055 return NULL;
3057 return symbolp_scan(fetch_supersect(sbfd, sym->section), sym->value);
3060 static asymbol *canonical_symbol(struct superbfd *sbfd, asymbol *sym)
3062 if (bfd_is_const_section(sym->section))
3063 return sym;
3064 asymbol **symp = canonical_symbolp(sbfd, sym);
3065 return symp != NULL ? *symp : NULL;
3068 static char *static_local_symbol(struct superbfd *sbfd, asymbol *sym)
3070 struct supersect *ss = fetch_supersect(sbfd, sym->section);
3071 if ((sym->flags & BSF_LOCAL) == 0 || (sym->flags & BSF_OBJECT) == 0)
3072 return NULL;
3073 char *dot = strrchr(sym->name, '.');
3074 if (dot == NULL || dot[1 + strspn(dot + 1, "0123546789")] != '\0')
3075 return NULL;
3076 char *basename = strndup(sym->name, dot - sym->name);
3078 /* Handle C.123.12345 symbols */
3079 dot = strrchr(basename, '.');
3080 if (dot != NULL && dot[1 + strspn(dot + 1, "0123546789")] == '\0')
3081 basename = strndup(basename, dot - basename);
3082 const char *caller;
3083 if (strcmp(basename, "__func__") == 0 ||
3084 strcmp(basename, "__PRETTY_FUNCTION__") == 0)
3085 caller = (const char *)ss->contents.data + sym->value;
3086 else
3087 caller = find_caller(ss, sym);
3088 return strprintf("%s<%s>", basename, caller);
3091 static char *symbol_label(struct superbfd *sbfd, asymbol *sym)
3093 const char *filename = sbfd->abfd->filename;
3094 char *c = strstr(filename, ".KSPLICE");
3095 int flen = (c == NULL ? strlen(filename) : c - filename);
3097 char *label;
3098 if (bfd_is_und_section(sym->section) || (sym->flags & BSF_GLOBAL) != 0) {
3099 label = strdup(sym->name);
3100 } else if (bfd_is_const_section(sym->section)) {
3101 label = strprintf("%s<%.*s>", sym->name, flen, filename);
3102 } else {
3103 asymbol *gsym = canonical_symbol(sbfd, sym);
3105 if (gsym == NULL)
3106 label = strprintf("%s+%lx<%.*s>",
3107 sym->section->name,
3108 (unsigned long)sym->value,
3109 flen, filename);
3110 else if ((gsym->flags & BSF_GLOBAL) != 0)
3111 label = strdup(gsym->name);
3112 else if (static_local_symbol(sbfd, gsym))
3113 label = strprintf("%s+%lx<%.*s>",
3114 static_local_symbol(sbfd, gsym),
3115 (unsigned long)sym->value,
3116 flen, filename);
3117 else
3118 label = strprintf("%s<%.*s>",
3119 gsym->name, flen, filename);
3122 return label;
3125 static void keep_span(struct span *span)
3127 span->keep = true;
3128 span->ss->keep = true;
3131 static struct span *new_span(struct supersect *ss, bfd_vma start, bfd_vma size)
3133 struct span *span = vec_grow(&ss->spans, 1);
3134 span->size = size;
3135 span->contents_size = size;
3136 span->start = start;
3137 span->ss = ss;
3138 span->keep = true;
3139 span->new = false;
3140 span->patch = false;
3141 span->bugpatch = false;
3142 span->datapatch = false;
3143 span->precallable = strstarts(ss->name, ".ksplice_call_pre_apply") ||
3144 strstarts(ss->name, ".ksplice_call_check_apply") ||
3145 strstarts(ss->name, ".ksplice_call_fail_apply") ||
3146 strstarts(ss->name, ".ksplice_call_post_remove");
3147 span->match = NULL;
3148 vec_init(&span->entry_points);
3149 span->shift = 0;
3150 asymbol **symp = symbolp_scan(ss, span->start);
3151 if (symp != NULL) {
3152 span->symbol = *symp;
3153 span->label = label_lookup(ss->parent, span->symbol);
3154 } else {
3155 span->symbol = NULL;
3156 const char *label = label_lookup(ss->parent, ss->symbol);
3157 if (span->start != 0)
3158 span->label = strprintf("%s<span:%lx>", label,
3159 (unsigned long)span->start);
3160 else
3161 span->label = label;
3163 span->orig_label = span->label;
3164 return span;
3167 static void initialize_string_spans(struct supersect *ss)
3169 const char *str;
3170 for (str = ss->contents.data;
3171 (void *)str < ss->contents.data + ss->contents.size;) {
3172 bfd_vma start = (unsigned long)str -
3173 (unsigned long)ss->contents.data;
3174 bfd_vma size = strlen(str) + 1;
3175 bfd_vma contents_size = size;
3176 while ((start + size) % (1 << ss->alignment) != 0 &&
3177 start + size < ss->contents.size) {
3178 /* Some string sections, like __ksymtab_strings, only
3179 align some strings with the declared alignment */
3180 if (str[size] != '\0')
3181 break;
3182 size++;
3184 struct span *span = new_span(ss, start, size);
3185 span->contents_size = contents_size;
3186 str += size;
3190 static int compare_ulongs(const void *va, const void *vb)
3192 const unsigned long *a = va, *b = vb;
3193 return *a - *b;
3196 static void initialize_table_spans(struct superbfd *sbfd,
3197 struct table_section *s)
3199 asection *isection = bfd_get_section_by_name(sbfd->abfd, s->sect);
3200 if (isection == NULL)
3201 return;
3202 struct supersect *ss = fetch_supersect(sbfd, isection);
3203 if (ss->alignment < ffs(s->entry_align) - 1)
3204 ss->alignment = ffs(s->entry_align) - 1;
3206 asection *other_sect = NULL;
3207 if (s->other_sect != NULL)
3208 other_sect = bfd_get_section_by_name(sbfd->abfd, s->other_sect);
3209 struct supersect *other_ss = NULL;
3210 if (other_sect != NULL)
3211 other_ss = fetch_supersect(sbfd, other_sect);
3213 asection *crc_sect = NULL;
3214 if (s->crc_sect != NULL)
3215 crc_sect = bfd_get_section_by_name(sbfd->abfd, s->crc_sect);
3216 struct supersect *crc_ss = NULL;
3217 if (crc_sect != NULL)
3218 crc_ss = fetch_supersect(sbfd, crc_sect);
3220 struct ulong_vec offsets;
3221 vec_init(&offsets);
3223 void *entry;
3224 for (entry = ss->contents.data;
3225 entry < ss->contents.data + ss->contents.size;
3226 entry += s->entry_size) {
3227 struct span *span = new_span(ss, addr_offset(ss, entry),
3228 s->entry_size);
3229 if (s->entry_contents_size != 0)
3230 span->contents_size = s->entry_contents_size;
3231 if ((span->symbol == NULL ||
3232 (span->symbol->flags & BSF_SECTION_SYM) != 0) &&
3233 s->has_addr) {
3234 arelent *reloc = find_reloc(ss, entry + s->addr_offset);
3235 assert(reloc);
3236 struct span *target_span = reloc_target_span(ss, reloc);
3237 assert(target_span);
3238 asymbol *sym = *reloc->sym_ptr_ptr;
3239 unsigned long val = sym->value +
3240 reloc_target_offset(ss, reloc) -
3241 (target_span->start + target_span->shift);
3242 char *label = strprintf("%s<target:%s+%lx>", ss->name,
3243 target_span->label, val);
3244 change_initial_label(span, label);
3247 if (other_sect != NULL) {
3248 asymbol *sym;
3249 bfd_vma offset = read_reloc(ss, entry + s->other_offset,
3250 sizeof(void *), &sym);
3251 if (sym->section == other_sect) {
3252 assert(offset >= 0 &&
3253 offset < other_ss->contents.size);
3254 *vec_grow(&offsets, 1) = offset;
3258 if (crc_sect != NULL)
3259 new_span(crc_ss, addr_offset(ss, entry) / s->entry_size
3260 * s->crc_size, s->crc_size);
3262 if (ss->type == SS_TYPE_EXPORT) {
3263 const char *symname = read_string(ss, entry +
3264 s->other_offset);
3265 char *label = strprintf("%s:%s", ss->name, symname);
3266 change_initial_label(span, label);
3270 if (other_sect == NULL)
3271 return;
3273 *vec_grow(&offsets, 1) = 0;
3274 qsort(offsets.data, offsets.size, sizeof(*offsets.data),
3275 compare_ulongs);
3276 *vec_grow(&offsets, 1) = other_ss->contents.size;
3278 unsigned long *off;
3279 for (off = offsets.data; off < offsets.data + offsets.size - 1; off++) {
3280 if (*off != *(off + 1))
3281 new_span(other_ss, *off, *(off + 1) - *off);
3285 static void initialize_table_section_spans(struct superbfd *sbfd)
3287 struct supersect *tables_ss =
3288 fetch_supersect(offsets_sbfd,
3289 bfd_get_section_by_name(offsets_sbfd->abfd,
3290 ".ksplice_table_sections"));
3291 const struct table_section *ts;
3292 struct table_section s;
3293 for (ts = tables_ss->contents.data;
3294 (void *)ts < tables_ss->contents.data + tables_ss->contents.size;
3295 ts++) {
3296 s = *ts;
3297 s.sect = read_string(tables_ss, &ts->sect);
3298 s.other_sect = read_string(tables_ss, &ts->other_sect);
3299 s.crc_sect = read_string(tables_ss, &ts->crc_sect);
3300 initialize_table_spans(sbfd, &s);
3304 static void initialize_ksplice_call_spans(struct supersect *ss)
3306 arelent **relocp;
3307 for (relocp = ss->relocs.data;
3308 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
3309 arelent *reloc = *relocp;
3310 new_span(ss, reloc->address, bfd_get_reloc_size(reloc->howto));
3311 /* the span labels should already be unique */
3315 static void initialize_spans(struct superbfd *sbfd)
3317 asection *sect;
3318 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
3319 if (is_table_section(sect->name, true, true) && mode("keep"))
3320 continue;
3322 struct supersect *ss = fetch_supersect(sbfd, sect);
3323 if (ss->type == SS_TYPE_STRING)
3324 initialize_string_spans(ss);
3325 else if (ss->type == SS_TYPE_KSPLICE_CALL)
3326 initialize_ksplice_call_spans(ss);
3327 else
3328 new_span(ss, 0, ss->contents.size);
3330 if (mode("keep"))
3331 initialize_table_section_spans(sbfd);
3334 /* Returns the span pointed to by the relocation at span->start + offset */
3335 static struct span *span_offset_target_span(struct span *span, int offset)
3337 void *entry = span->ss->contents.data + span->start;
3338 arelent *reloc = find_reloc(span->ss, entry + offset);
3339 if (reloc == NULL)
3340 return NULL;
3341 return reloc_target_span(span->ss, reloc);
3344 struct span *reloc_target_span(struct supersect *ss, arelent *reloc)
3346 asymbol *sym_ptr = *reloc->sym_ptr_ptr;
3347 if (bfd_is_const_section(sym_ptr->section))
3348 return NULL;
3350 bfd_vma addend = sym_ptr->value + reloc_target_offset(ss, reloc);
3351 struct supersect *sym_ss =
3352 fetch_supersect(ss->parent, sym_ptr->section);
3353 struct span *span, *target_span = sym_ss->spans.data;
3354 for (span = sym_ss->spans.data;
3355 span < sym_ss->spans.data + sym_ss->spans.size; span++) {
3356 if (addend >= span->start && addend < span->start + span->size)
3357 target_span = span;
3359 return target_span;
3362 static bfd_vma reloc_target_offset(struct supersect *ss, arelent *reloc)
3364 bfd_vma offset = reloc_offset(ss, reloc);
3365 if (reloc->howto->pc_relative) {
3366 if ((ss->flags & SEC_CODE) != 0)
3367 return offset + bfd_get_reloc_size(reloc->howto);
3369 const struct table_section *ts = get_table_section(ss->name);
3370 if (ts != NULL && ts->relative_addr &&
3371 reloc->address % ts->entry_size == ts->addr_offset)
3372 return offset - ts->addr_offset;
3373 if (ts != NULL && ts->relative_other &&
3374 reloc->address % ts->entry_size == ts->other_offset)
3375 return offset - ts->other_offset;
3377 DIE;
3379 return offset;
3382 struct span *find_span(struct supersect *ss, bfd_size_type address)
3384 struct span *span;
3385 for (span = ss->spans.data; span < ss->spans.data + ss->spans.size;
3386 span++) {
3387 if (address >= span->start &&
3388 address < span->start + span->size)
3389 return span;
3391 /* Deal with empty BSS sections */
3392 if (ss->contents.size == 0 && ss->spans.size > 0)
3393 return ss->spans.data;
3394 /* Deal with section end pointers */
3395 if (address == ss->contents.size && ss->spans.size == 1)
3396 return ss->spans.data;
3397 return NULL;
3400 void compute_span_shifts(struct superbfd *sbfd)
3402 asection *sect;
3403 struct span *span;
3404 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
3405 struct supersect *ss = fetch_supersect(sbfd, sect);
3406 if (!ss->keep)
3407 continue;
3408 bfd_size_type offset = 0;
3409 for (span = ss->spans.data;
3410 span < ss->spans.data + ss->spans.size; span++) {
3411 if (!span->keep)
3412 continue;
3413 span->shift = offset - span->start;
3414 offset += span->size;
3419 void remove_unkept_spans(struct superbfd *sbfd)
3421 asection *sect;
3422 struct span *span;
3423 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
3424 struct supersect *ss = fetch_supersect(sbfd, sect);
3425 delete_obsolete_relocs(ss);
3426 struct arelentp_vec orig_relocs;
3427 vec_move(&orig_relocs, &ss->relocs);
3428 arelent **relocp, *reloc;
3429 for (relocp = orig_relocs.data;
3430 relocp < orig_relocs.data + orig_relocs.size; relocp++) {
3431 reloc = *relocp;
3432 asymbol *sym = *reloc->sym_ptr_ptr;
3433 span = reloc_target_span(ss, reloc);
3434 if ((span != NULL && span->keep && span->shift == 0) ||
3435 bfd_is_const_section(sym->section)) {
3436 *vec_grow(&ss->relocs, 1) = reloc;
3437 continue;
3439 struct supersect *sym_ss =
3440 fetch_supersect(sbfd, sym->section);
3441 if (span != NULL && (sym->flags & BSF_SECTION_SYM) == 0
3442 && find_span(sym_ss, sym->value) != span) {
3443 err(sbfd, "Spans for symbol %s and relocation "
3444 "target do not match in sect %s\n",
3445 sym->name, sym_ss->name);
3446 DIE;
3448 if (span != NULL && span->keep) {
3449 arelent *new_reloc = malloc(sizeof(*new_reloc));
3450 *new_reloc = *reloc;
3451 new_reloc->addend = reloc_offset(ss, reloc);
3452 new_reloc->addend += span->shift;
3453 *vec_grow(&ss->new_relocs, 1) = new_reloc;
3458 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
3459 struct supersect *ss = fetch_supersect(sbfd, sect), orig_ss;
3460 if (!ss->keep)
3461 continue;
3462 supersect_move(&orig_ss, ss);
3463 vec_init(&ss->spans);
3464 for (span = orig_ss.spans.data;
3465 span < orig_ss.spans.data + orig_ss.spans.size; span++) {
3466 if (!span->keep)
3467 continue;
3468 struct span *new_span = vec_grow(&ss->spans, 1);
3469 *new_span = *span;
3470 new_span->start = span->start + span->shift;
3471 new_span->shift = 0;
3472 sect_copy(ss, sect_do_grow(ss, 1, span->size, 1),
3473 &orig_ss, orig_ss.contents.data + span->start,
3474 span->size);
3479 static void init_objmanip_superbfd(struct superbfd *sbfd)
3481 init_label_map(sbfd);
3482 initialize_supersect_types(sbfd);
3483 initialize_spans(sbfd);
3484 load_options(sbfd);
3485 compute_entry_points(sbfd);
3488 void mangle_section_name(struct superbfd *sbfd, const char *name)
3490 asection *sect = bfd_get_section_by_name(sbfd->abfd, name);
3491 if (sect == NULL)
3492 return;
3493 struct supersect *ss = fetch_supersect(sbfd, sect);
3494 ss->name = strprintf(".ksplice_pre.%s", ss->name);
3497 static void write_bugline_patches(struct superbfd *sbfd)
3499 const struct table_section *ts = get_table_section("__bug_table");
3500 asection *sect = bfd_get_section_by_name(sbfd->abfd, "__bug_table");
3501 if (sect == NULL)
3502 return;
3503 struct supersect *ss = fetch_supersect(sbfd, sect);
3504 assert(ts != NULL);
3506 void *entry;
3507 for (entry = ss->contents.data;
3508 entry < ss->contents.data + ss->contents.size;
3509 entry += ts->entry_size) {
3510 struct span *span = find_span(ss, addr_offset(ss, entry));
3511 assert(span != NULL);
3512 if (!span->bugpatch)
3513 continue;
3514 arelent *reloc = find_reloc(ss, entry + ts->addr_offset);
3515 assert(reloc != NULL);
3516 asymbol *sym = *reloc->sym_ptr_ptr;
3517 assert(!bfd_is_const_section(sym->section));
3518 struct supersect *kpatch_ss =
3519 make_section(sbfd, ".ksplice_patches%s",
3520 sym->section->name);
3522 bfd_vma offset, start = 0;
3523 for (offset = 0; offset <= span->size; offset++) {
3524 if (offset != span->size &&
3525 !part_of_reloc(ss, span->start + offset))
3526 continue;
3527 if (start == offset) {
3528 start++;
3529 continue;
3531 /* an interval of non-relocations just passed */
3532 struct ksplice_patch *kpatch =
3533 sect_grow(kpatch_ss, 1, struct ksplice_patch);
3534 write_ksplice_patch_reloc
3535 (kpatch_ss, sym->section->name, &kpatch->oldaddr,
3536 sizeof(kpatch->oldaddr), span->label, start);
3538 char *data = write_patch_storage(kpatch_ss, kpatch,
3539 offset - start, NULL);
3540 memcpy(data, entry + start, offset - start);
3541 kpatch->type = KSPLICE_PATCH_DATA;
3542 start = offset + 1;
3547 void *write_patch_storage(struct supersect *ss, struct ksplice_patch *kpatch,
3548 size_t size, struct supersect **data_ssp)
3550 struct supersect *data_ss = make_section(ss->parent,
3551 ".ksplice_patch_data");
3552 char *saved = sect_do_grow(data_ss, 1, size, 1);
3553 write_reloc(ss, &kpatch->saved, &data_ss->symbol,
3554 addr_offset(data_ss, saved));
3555 char *data = sect_do_grow(data_ss, 1, size, 1);
3556 write_reloc(ss, &kpatch->contents, &data_ss->symbol,
3557 addr_offset(data_ss, data));
3558 kpatch->size = size;
3559 if (data_ssp != NULL)
3560 *data_ssp = data_ss;
3561 return data;