Never inline init_symbol_arrays, to avoid conflicting stack garbage.
[ksplice.git] / objmanip.c
blob4474acbf6c3642b52c7de4955ff2e8effd0d0f31
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);
94 enum supersect_type supersect_type(struct supersect *ss);
95 void initialize_supersect_types(struct superbfd *sbfd);
96 static void initialize_spans(struct superbfd *sbfd);
97 static void initialize_string_spans(struct supersect *ss);
98 static void initialize_table_spans(struct superbfd *sbfd,
99 struct table_section *s);
100 static void initialize_table_section_spans(struct superbfd *sbfd);
101 static void initialize_ksplice_call_spans(struct supersect *ss);
102 struct span *reloc_target_span(struct supersect *ss, arelent *reloc);
103 static struct span *span_offset_target_span(struct span *span, int offset);
104 static bfd_vma reloc_target_offset(struct supersect *ss, arelent *reloc);
105 struct span *find_span(struct supersect *ss, bfd_size_type address);
106 void remove_unkept_spans(struct superbfd *sbfd);
107 void compute_span_shifts(struct superbfd *sbfd);
108 static struct span *new_span(struct supersect *ss, bfd_vma start, bfd_vma size);
109 static bool is_table_section(const char *name, bool consider_other,
110 bool consider_crc);
111 const struct table_section *get_table_section(const char *name);
112 void mangle_section_name(struct superbfd *sbfd, const char *name);
114 void rm_relocs(struct superbfd *isbfd);
115 void rm_some_relocs(struct supersect *ss);
116 void write_ksplice_reloc(struct supersect *ss, arelent *orig_reloc);
117 static void write_ksplice_reloc_howto(struct supersect *ss, const
118 struct ksplice_reloc_howto *const *addr,
119 reloc_howto_type *howto,
120 enum ksplice_reloc_howto_type type);
121 static void write_ksplice_date_reloc(struct supersect *ss, unsigned long offset,
122 const char *str,
123 enum ksplice_reloc_howto_type type);
124 static void write_ksplice_patch_reloc(struct supersect *ss,
125 const char *sectname, unsigned long *addr,
126 bfd_size_type size, const char *label,
127 long addend);
128 static void write_ksplice_nonreloc_howto(struct supersect *ss,
129 const struct ksplice_reloc_howto
130 *const *addr,
131 enum ksplice_reloc_howto_type type,
132 int size);
133 static void write_date_relocs(struct superbfd *sbfd, const char *str,
134 enum ksplice_reloc_howto_type type);
135 static void write_table_relocs(struct superbfd *sbfd, const char *sectname,
136 enum ksplice_reloc_howto_type type);
137 static void write_ksplice_table_reloc(struct supersect *ss,
138 unsigned long address,
139 const char *label,
140 enum ksplice_reloc_howto_type type);
141 void load_ksplice_symbol_offsets(struct superbfd *sbfd);
142 void write_canary(struct supersect *ss, int offset, bfd_size_type size,
143 bfd_vma dst_mask);
144 static void write_ksplice_section(struct span *span);
145 void write_ksplice_patch(struct superbfd *sbfd, struct span *span);
146 void *write_patch_storage(struct supersect *ss, struct ksplice_patch *patch,
147 size_t size, struct supersect **data_ssp);
148 void write_ksplice_deleted_patch(struct superbfd *sbfd, const char *name,
149 const char *label, const char *sectname);
150 static void write_bugline_patches(struct superbfd *sbfd);
151 asymbol **make_undefined_symbolp(struct superbfd *sbfd, const char *name);
152 void filter_table_sections(struct superbfd *isbfd);
153 void filter_table_section(struct superbfd *sbfd, const struct table_section *s);
154 void keep_referenced_sections(struct superbfd *sbfd);
155 void mark_precallable_spans(struct superbfd *sbfd);
156 bfd_boolean copy_object(bfd *ibfd, bfd *obfd);
157 void setup_section(bfd *ibfd, asection *isection, void *obfdarg);
158 static void setup_new_section(bfd *obfd, struct supersect *ss);
159 static void write_section(bfd *obfd, asection *osection, void *arg);
160 static void delete_obsolete_relocs(struct supersect *ss);
161 void mark_symbols_used_in_relocations(bfd *abfd, asection *isection,
162 void *ignored);
163 static void ss_mark_symbols_used_in_relocations(struct supersect *ss);
164 void filter_symbols(bfd *ibfd, bfd *obfd, struct asymbolp_vec *osyms,
165 struct asymbolp_vec *isyms);
166 static bool deleted_table_section_symbol(bfd *abfd, asymbol *sym);
167 void read_str_set(struct str_vec *strs);
168 bool str_in_set(const char *str, const struct str_vec *strs);
169 struct supersect *__attribute((format(printf, 2, 3)))
170 make_section(struct superbfd *sbfd, const char *fmt, ...);
171 void __attribute__((format(printf, 3, 4)))
172 write_string(struct supersect *ss, const char **addr, const char *fmt, ...);
173 void write_ksplice_export(struct superbfd *sbfd, struct span *span, bool del);
174 void write_reloc(struct supersect *ss, const void *addr, asymbol **symp,
175 bfd_vma offset);
176 arelent *create_reloc(struct supersect *ss, const void *addr, asymbol **symp,
177 bfd_vma offset);
178 static void foreach_symbol_pair(struct superbfd *oldsbfd, struct superbfd *newsbfd,
179 void (*fn)(struct span *old_span,
180 asymbol *oldsym,
181 struct span *new_span,
182 asymbol *newsym));
183 static void check_global_symbols(struct span *old_span, asymbol *oldsym,
184 struct span *new_span, asymbol *newsym);
185 static void match_global_symbols(struct span *old_span, asymbol *oldsym,
186 struct span *new_span, asymbol *newsym);
187 static void match_symbol_spans(struct span *old_span, asymbol *oldsym,
188 struct span *new_span, asymbol *newsym);
189 static void match_table_spans(struct span *old_span, struct span *new_span);
191 static struct span *get_crc_span(struct span *span,
192 const struct table_section *ts);
193 static void foreach_span_pair(struct superbfd *oldsbfd,
194 struct superbfd *newsbfd,
195 void (*fn)(struct span *old_span,
196 struct span *new_span));
197 static void match_spans_by_label(struct span *old_span, struct span *new_span);
198 static void match_string_spans(struct span *old_span, struct span *new_span);
199 static void mark_new_spans(struct superbfd *sbfd);
200 static void handle_deleted_spans(struct superbfd *oldsbfd,
201 struct superbfd *newsbfd);
202 static void unmatch_addr_spans(struct span *old_span, struct span *new_span,
203 const struct table_section *ts);
204 static void compare_matched_spans(struct superbfd *newsbfd);
205 static void compare_spans(struct span *old_span, struct span *new_span);
206 static void update_nonzero_offsets(struct superbfd *sbfd);
207 static void handle_nonzero_offset_relocs(struct supersect *ss);
208 static void keep_span(struct span *span);
210 static void init_objmanip_superbfd(struct superbfd *sbfd);
211 static const char *label_lookup(struct superbfd *sbfd, asymbol *sym);
212 static void label_map_set(struct superbfd *sbfd, const char *oldlabel,
213 const char *label);
214 static void print_label_changes(struct superbfd *sbfd);
215 static void init_label_map(struct superbfd *sbfd);
216 static void change_initial_label(struct span *span, const char *label);
217 static asymbol **symbolp_scan(struct supersect *ss, bfd_vma value);
218 static void init_csyms(struct superbfd *sbfd);
219 static void init_callers(struct superbfd *sbfd);
220 static asymbol *canonical_symbol(struct superbfd *sbfd, asymbol *sym);
221 static asymbol **canonical_symbolp(struct superbfd *sbfd, asymbol *sym);
222 static char *static_local_symbol(struct superbfd *sbfd, asymbol *sym);
223 static char *symbol_label(struct superbfd *sbfd, asymbol *sym);
225 int verbose = 0;
226 #define debug_(sbfd, level, fmt, ...) \
227 do { \
228 if (verbose >= (level)) \
229 printf("%s: " fmt, (sbfd)->abfd->filename, \
230 ## __VA_ARGS__); \
231 } while (0)
232 #define debug0(sbfd, fmt, ...) debug_(sbfd, 0, fmt, ## __VA_ARGS__)
233 #define debug1(sbfd, fmt, ...) debug_(sbfd, 1, fmt, ## __VA_ARGS__)
234 #define err(sbfd, fmt, ...) \
235 do { \
236 fprintf(stderr, "%s: " fmt, (sbfd)->abfd->filename, \
237 ## __VA_ARGS__); \
238 } while (0)
240 struct str_vec delsects, rmsyms;
241 bool changed;
243 struct ksplice_config *config;
245 const char *modestr, *kid, *finalize_target = NULL;
246 bool write_output = true;
248 struct superbfd *offsets_sbfd = NULL;
250 #define mode(str) strstarts(modestr, str)
252 DECLARE_VEC_TYPE(unsigned long, addr_vec);
253 DEFINE_HASH_TYPE(struct addr_vec, addr_vec_hash,
254 addr_vec_hash_init, addr_vec_hash_free, addr_vec_hash_lookup,
255 vec_init);
256 struct addr_vec_hash system_map;
258 struct bool_hash system_map_written;
259 struct ulong_hash ksplice_symbol_offset;
260 struct ulong_hash ksplice_howto_offset;
261 struct ulong_hash ksplice_string_offset;
263 void load_system_map()
265 const char *config_dir = getenv("KSPLICE_CONFIG_DIR");
266 assert(config_dir);
267 FILE *fp = fopen(strprintf("%s/System.map", config_dir), "r");
268 assert(fp);
269 addr_vec_hash_init(&system_map);
270 unsigned long addr;
271 char type;
272 char *sym;
273 while (fscanf(fp, "%lx %c %as\n", &addr, &type, &sym) == 3)
274 *vec_grow(addr_vec_hash_lookup(&system_map, sym, TRUE),
275 1) = addr;
276 fclose(fp);
279 void load_ksplice_symbol_offsets(struct superbfd *sbfd)
281 asection *sect = bfd_get_section_by_name(sbfd->abfd,
282 ".ksplice_symbols");
283 if (sect == NULL)
284 return;
285 struct supersect *ss = fetch_supersect(sbfd, sect);
287 struct ksplice_symbol *ksym;
288 for (ksym = ss->contents.data;
289 (void *)ksym < ss->contents.data + ss->contents.size; ksym++) {
290 const char *label = read_string(ss, &ksym->label);
291 unsigned long *ksymbol_offp =
292 ulong_hash_lookup(&ksplice_symbol_offset, label, TRUE);
293 *ksymbol_offp = addr_offset(ss, ksym);
297 void load_offsets()
299 char *kmodsrc = getenv("KSPLICE_KMODSRC");
300 assert(kmodsrc != NULL);
301 bfd *offsets_bfd = bfd_openr(strprintf("%s/offsets.o", kmodsrc), NULL);
302 assert(offsets_bfd != NULL);
303 char **matching;
304 assert(bfd_check_format_matches(offsets_bfd, bfd_object, &matching));
305 offsets_sbfd = fetch_superbfd(offsets_bfd);
307 asection *config_sect = bfd_get_section_by_name(offsets_sbfd->abfd,
308 ".ksplice_config");
309 struct supersect *config_ss =
310 fetch_supersect(offsets_sbfd, config_sect);
312 config = config_ss->contents.data;
315 void load_options(struct superbfd *sbfd)
317 asection *sect = bfd_get_section_by_name(sbfd->abfd,
318 ".ksplice_options");
319 if (sect == NULL)
320 return;
321 struct supersect *ss = fetch_supersect(sbfd, sect);
322 const struct ksplice_option *opt;
323 for (opt = ss->contents.data;
324 (void *)opt < ss->contents.data + ss->contents.size; opt++) {
325 if (opt->type == KSPLICE_OPTION_ASSUME_RODATA) {
326 arelent *reloc = find_reloc(ss, &opt->target);
327 struct span *span = reloc_target_span(ss, reloc);
328 assert(span != NULL);
329 assert(span->ss->type == SS_TYPE_DATA);
330 assert(span->start == 0 &&
331 span->size == span->ss->contents.size);
332 span->ss->type = SS_TYPE_RODATA;
333 break;
334 } else {
335 err(sbfd, "Unrecognized Ksplice option %d\n",
336 opt->type);
337 DIE;
342 bool matchable_data_section(struct supersect *ss)
344 if (ss->type == SS_TYPE_STRING)
345 return true;
346 if (ss->type == SS_TYPE_RODATA)
347 return true;
348 if (ss->type == SS_TYPE_DATA && ss->relocs.size != 0)
349 return true;
350 if (ss->type == SS_TYPE_EXPORT)
351 return true;
352 return false;
355 bool unchangeable_section(struct supersect *ss)
357 if (ss->type == SS_TYPE_DATA)
358 return true;
359 if (ss->type == SS_TYPE_IGNORED && !strstarts(ss->name, ".debug") &&
360 strcmp(ss->name, "__ksymtab_strings") != 0)
361 return true;
362 return false;
365 int main(int argc, char *argv[])
367 if (getenv("KSPLICE_VERBOSE") != NULL)
368 verbose = atoi(getenv("KSPLICE_VERBOSE"));
370 bfd_init();
371 bfd *ibfd = bfd_openr(argv[1], NULL);
372 assert(ibfd);
374 char **matching;
375 if (bfd_check_format_matches(ibfd, bfd_archive, &matching) &&
376 bfd_openr_next_archived_file(ibfd, NULL) == NULL)
377 return 66; /* empty archive */
378 assert(bfd_check_format_matches(ibfd, bfd_object, &matching));
380 const char *output_target = bfd_get_target(ibfd);
382 load_system_map();
383 load_offsets();
385 bool_hash_init(&system_map_written);
386 ulong_hash_init(&ksplice_symbol_offset);
387 ulong_hash_init(&ksplice_howto_offset);
388 ulong_hash_init(&ksplice_string_offset);
390 struct superbfd *isbfd = fetch_superbfd(ibfd);
392 modestr = argv[3];
393 if (mode("finalize"))
394 finalize_target = argv[4];
395 init_objmanip_superbfd(isbfd);
396 if (mode("keep-new-code")) {
397 kid = argv[5];
398 do_keep_new_code(isbfd, argv[4]);
399 } else if (mode("keep-old-code")) {
400 do_keep_old_code(isbfd);
401 } else if (mode("finalize")) {
402 do_finalize(isbfd);
403 } else if (mode("rmsyms")) {
404 do_rmsyms(isbfd);
407 if (write_output) {
408 bfd *obfd = bfd_openw(argv[2], output_target);
409 assert(obfd);
410 copy_object(ibfd, obfd);
411 assert(bfd_close(obfd));
414 if (offsets_sbfd != NULL)
415 assert(bfd_close(offsets_sbfd->abfd));
416 assert(bfd_close(ibfd));
417 return EXIT_SUCCESS;
420 void do_keep_new_code(struct superbfd *isbfd, const char *pre)
422 struct bfd *prebfd = bfd_openr(pre, NULL);
423 assert(prebfd != NULL);
424 char **matching;
425 assert(bfd_check_format_matches(prebfd, bfd_object, &matching));
427 struct superbfd *presbfd = fetch_superbfd(prebfd);
428 init_objmanip_superbfd(presbfd);
430 foreach_symbol_pair(presbfd, isbfd, match_global_symbols);
431 debug1(isbfd, "Matched global\n");
432 foreach_span_pair(presbfd, isbfd, match_string_spans);
433 debug1(isbfd, "Matched string spans\n");
434 foreach_symbol_pair(presbfd, isbfd, match_symbol_spans);
435 debug1(isbfd, "Matched by name\n");
436 foreach_span_pair(presbfd, isbfd, match_spans_by_label);
437 debug1(isbfd, "Matched by label\n");
438 foreach_span_pair(presbfd, isbfd, match_table_spans);
439 debug1(isbfd, "Matched table spans\n");
441 do {
442 changed = false;
443 compare_matched_spans(isbfd);
444 update_nonzero_offsets(isbfd);
445 mark_new_spans(isbfd);
446 } while (changed);
447 vec_init(&delsects);
449 foreach_symbol_pair(presbfd, isbfd, check_global_symbols);
451 handle_deleted_spans(presbfd, isbfd);
452 handle_section_symbol_renames(presbfd, isbfd);
454 assert(bfd_close(prebfd));
456 do {
457 changed = false;
458 mark_precallable_spans(isbfd);
459 } while (changed);
461 asection *sect;
462 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
463 struct supersect *ss = fetch_supersect(isbfd, sect);
464 ss->keep = false;
465 struct span *span;
466 for (span = ss->spans.data;
467 span < ss->spans.data + ss->spans.size; span++) {
468 if (strstarts(ss->name, ".ksplice_options"))
469 span->keep = false;
470 else if (span->new || span->patch || span->datapatch)
471 keep_span(span);
472 else
473 span->keep = false;
474 if (span->patch && span->precallable) {
475 err(isbfd, "Patched span %s can be reached "
476 "by a precall function\n", span->label);
477 DIE;
482 print_label_changes(isbfd);
484 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
485 struct supersect *ss = fetch_supersect(isbfd, sect);
486 struct span *span;
487 for (span = ss->spans.data;
488 span < ss->spans.data + ss->spans.size; span++) {
489 if (span->patch || span->bugpatch || span->datapatch)
490 debug0(isbfd, "Patching span %s\n",
491 span->label);
495 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
496 struct supersect *ss = fetch_supersect(isbfd, sect);
497 struct span *span;
498 for (span = ss->spans.data;
499 span < ss->spans.data + ss->spans.size; span++) {
500 if (span->new)
501 debug0(isbfd, "New span %s\n", span->label);
505 write_output = false;
506 const char **sectname;
507 for (sectname = delsects.data;
508 sectname < delsects.data + delsects.size; sectname++) {
509 write_output = true;
510 debug0(isbfd, "Deleted section: %s\n", *sectname);
513 filter_table_sections(isbfd);
515 compute_span_shifts(isbfd);
517 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
518 struct supersect *ss = fetch_supersect(isbfd, sect);
519 if (ss->type == SS_TYPE_KSPLICE_CALL)
520 continue;
521 struct span *span;
522 for (span = ss->spans.data;
523 span < ss->spans.data + ss->spans.size; span++) {
524 if (span->keep)
525 write_output = true;
526 if (span->patch || span->new || span->datapatch)
527 write_ksplice_section(span);
528 if (span->patch || span->datapatch)
529 write_ksplice_patch(isbfd, span);
530 if (ss->type == SS_TYPE_EXPORT && span->new)
531 write_ksplice_export(isbfd, span, false);
535 write_bugline_patches(isbfd);
536 rm_relocs(isbfd);
537 remove_unkept_spans(isbfd);
540 void do_keep_old_code(struct superbfd *isbfd)
542 asection *sect;
543 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
544 struct supersect *ss = fetch_supersect(isbfd, sect);
545 ss->keep = false;
546 struct span *span;
547 for (span = ss->spans.data;
548 span < ss->spans.data + ss->spans.size; span++) {
549 span->keep = false;
550 if (ss->type == SS_TYPE_TEXT &&
551 !strstarts(ss->name, ".fixup"))
552 keep_span(span);
553 if (ss->type == SS_TYPE_EXPORT)
554 keep_span(span);
558 asymbol **symp;
559 for (symp = isbfd->syms.data;
560 symp < isbfd->syms.data + isbfd->syms.size; symp++) {
561 asymbol *sym = *symp;
562 if (!bfd_is_const_section(sym->section) &&
563 (sym->flags & BSF_GLOBAL) != 0) {
564 struct supersect *sym_ss =
565 fetch_supersect(isbfd, sym->section);
566 if (sym->value == sym_ss->contents.size)
567 continue;
568 struct span *span = find_span(sym_ss, sym->value);
569 assert(span != NULL);
570 if (sym_ss->type != SS_TYPE_IGNORED)
571 keep_span(span);
575 do {
576 changed = false;
577 keep_referenced_sections(isbfd);
578 } while (changed);
580 filter_table_sections(isbfd);
581 compute_span_shifts(isbfd);
583 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
584 struct supersect *ss = fetch_supersect(isbfd, sect);
585 asymbol *sym = canonical_symbol(isbfd, sect->symbol);
586 if (sym == NULL)
587 continue;
588 if ((sym->flags & BSF_WEAK) != 0)
589 continue;
590 if (bfd_get_section_size(sect) == 0)
591 continue;
592 if (!ss->keep)
593 continue;
594 if (ss->type != SS_TYPE_TEXT && !matchable_data_section(ss))
595 continue;
597 struct span *span;
598 for (span = ss->spans.data;
599 span < ss->spans.data + ss->spans.size; span++) {
600 if (span->keep)
601 write_ksplice_section(span);
605 write_table_relocs(isbfd, "__bug_table", KSPLICE_HOWTO_BUG);
606 write_table_relocs(isbfd, "__ex_table", KSPLICE_HOWTO_EXTABLE);
607 rm_relocs(isbfd);
608 remove_unkept_spans(isbfd);
610 mangle_section_name(isbfd, "__markers");
611 mangle_section_name(isbfd, "__ex_table");
612 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
613 struct supersect *ss = fetch_supersect(isbfd, sect);
614 if (ss->type == SS_TYPE_EXPORT)
615 mangle_section_name(isbfd, ss->name);
619 void do_finalize(struct superbfd *isbfd)
621 load_ksplice_symbol_offsets(isbfd);
622 asection *sect;
623 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
624 struct supersect *ss = fetch_supersect(isbfd, sect);
625 if (ss->type == SS_TYPE_EXIT) {
626 struct span *span;
627 for (span = ss->spans.data;
628 span < ss->spans.data + ss->spans.size; span++)
629 span->keep = false;
630 ss->keep = false;
633 write_date_relocs(isbfd, "<{DATE...}>", KSPLICE_HOWTO_DATE);
634 write_date_relocs(isbfd, "<{TIME}>", KSPLICE_HOWTO_TIME);
635 rm_relocs(isbfd);
638 void do_rmsyms(struct superbfd *isbfd)
640 read_str_set(&rmsyms);
641 rm_relocs(isbfd);
644 void match_spans(struct span *old_span, struct span *new_span)
646 struct superbfd *sbfd = new_span->ss->parent;
647 if (old_span->match == new_span && new_span->match == old_span)
648 return;
649 if (old_span->match != NULL) {
650 err(sbfd, "Matching conflict: old %s: %s != %s\n",
651 old_span->label, old_span->match->label, new_span->label);
652 DIE;
654 if (new_span->match != NULL) {
655 err(sbfd, "Matching conflict: new %s: %s != %s\n",
656 new_span->label, new_span->match->label, old_span->label);
657 DIE;
659 old_span->match = new_span;
660 new_span->match = old_span;
661 debug1(sbfd, "Matched old %s to new %s\n", old_span->label,
662 new_span->label);
663 if (old_span->ss->type != new_span->ss->type &&
664 old_span->ss->type == new_span->ss->orig_type)
665 old_span->ss->type = new_span->ss->type;
667 const struct table_section *ts = get_table_section(old_span->ss->name);
668 if (ts == NULL || !ts->has_addr || ts->other_sect == NULL)
669 return;
670 struct span *old_sym_span =
671 span_offset_target_span(old_span, ts->other_offset);
672 struct span *new_sym_span =
673 span_offset_target_span(new_span, ts->other_offset);
674 assert(old_sym_span != NULL && new_sym_span != NULL);
675 match_spans(old_sym_span, new_sym_span);
678 static void match_global_symbols(struct span *old_span, asymbol *oldsym,
679 struct span *new_span, asymbol *newsym)
681 if ((oldsym->flags & BSF_GLOBAL) == 0 ||
682 (newsym->flags & BSF_GLOBAL) == 0)
683 return;
684 match_spans(old_span, new_span);
687 static void check_global_symbols(struct span *old_span, asymbol *oldsym,
688 struct span *new_span, asymbol *newsym)
690 if ((oldsym->flags & BSF_GLOBAL) == 0 ||
691 (newsym->flags & BSF_GLOBAL) == 0)
692 return;
693 if (old_span->ss->type == SS_TYPE_IGNORED)
694 return;
695 if (old_span->match != new_span || new_span->match != old_span) {
696 err(new_span->ss->parent, "Global symbol span mismatch: %s "
697 "%s/%s\n", oldsym->name, old_span->ss->name,
698 new_span->ss->name);
699 DIE;
703 static void foreach_symbol_pair(struct superbfd *oldsbfd, struct superbfd *newsbfd,
704 void (*fn)(struct span *old_span,
705 asymbol *oldsym,
706 struct span *new_span,
707 asymbol *newsym))
709 asymbol **oldsymp, **newsymp;
710 for (oldsymp = oldsbfd->syms.data;
711 oldsymp < oldsbfd->syms.data + oldsbfd->syms.size; oldsymp++) {
712 asymbol *oldsym = *oldsymp;
713 if (bfd_is_const_section(oldsym->section))
714 continue;
715 for (newsymp = newsbfd->syms.data;
716 newsymp < newsbfd->syms.data + newsbfd->syms.size;
717 newsymp++) {
718 asymbol *newsym = *newsymp;
719 if (bfd_is_const_section(newsym->section))
720 continue;
721 if (strcmp(oldsym->name, newsym->name) != 0)
722 continue;
724 struct supersect *old_ss =
725 fetch_supersect(oldsbfd, oldsym->section);
726 struct supersect *new_ss =
727 fetch_supersect(newsbfd, newsym->section);
728 if ((old_ss->type != new_ss->type &&
729 old_ss->type != new_ss->orig_type) ||
730 old_ss->type == SS_TYPE_SPECIAL ||
731 old_ss->type == SS_TYPE_EXPORT)
732 continue;
734 struct span *old_span =
735 find_span(old_ss, oldsym->value);
736 struct span *new_span =
737 find_span(new_ss, newsym->value);
738 if (old_span == NULL) {
739 err(oldsbfd, "Could not find span for %s\n",
740 oldsym->name);
741 DIE;
743 if (new_span == NULL) {
744 err(newsbfd, "Could not find span for %s\n",
745 newsym->name);
746 DIE;
748 fn(old_span, oldsym, new_span, newsym);
753 static void match_symbol_spans(struct span *old_span, asymbol *oldsym,
754 struct span *new_span, asymbol *newsym)
756 if ((oldsym->flags & BSF_DEBUGGING) != 0 ||
757 (newsym->flags & BSF_DEBUGGING) != 0)
758 return;
759 if (old_span->ss->type == SS_TYPE_SPECIAL)
760 return;
761 if (static_local_symbol(old_span->ss->parent, oldsym) ||
762 static_local_symbol(new_span->ss->parent, newsym))
763 return;
764 if (old_span->match == NULL && new_span->match == NULL)
765 match_spans(old_span, new_span);
768 static void match_spans_by_label(struct span *old_span, struct span *new_span)
770 if (old_span->ss->type == SS_TYPE_STRING ||
771 (is_table_section(old_span->ss->name, true, false) &&
772 !is_table_section(old_span->ss->name, false, false)))
773 return;
774 if (strcmp(old_span->label, new_span->label) == 0)
775 match_spans(old_span, new_span);
778 static void match_string_spans(struct span *old_span, struct span *new_span)
780 if (old_span->ss->type != SS_TYPE_STRING ||
781 strcmp(old_span->ss->name, new_span->ss->name) != 0)
782 return;
783 if (strcmp((char *)old_span->ss->contents.data + old_span->start,
784 (char *)new_span->ss->contents.data + new_span->start) == 0)
785 match_spans(old_span, new_span);
788 static void foreach_span_pair(struct superbfd *oldsbfd,
789 struct superbfd *newsbfd,
790 void (*fn)(struct span *old_span,
791 struct span *new_span))
793 asection *oldsect, *newsect;
794 struct supersect *oldss, *newss;
795 struct span *old_span, *new_span;
796 for (newsect = newsbfd->abfd->sections; newsect != NULL;
797 newsect = newsect->next) {
798 newss = fetch_supersect(newsbfd, newsect);
799 for (oldsect = oldsbfd->abfd->sections; oldsect != NULL;
800 oldsect = oldsect->next) {
801 oldss = fetch_supersect(oldsbfd, oldsect);
802 if (oldss->type != newss->type)
803 continue;
804 for (new_span = newss->spans.data;
805 new_span < newss->spans.data + newss->spans.size;
806 new_span++) {
807 for (old_span = oldss->spans.data;
808 old_span < oldss->spans.data +
809 oldss->spans.size; old_span++)
810 fn(old_span, new_span);
816 static void mark_new_spans(struct superbfd *sbfd)
818 asection *sect;
819 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
820 struct supersect *ss = fetch_supersect(sbfd, sect);
821 if (ss->type == SS_TYPE_SPECIAL || ss->type == SS_TYPE_IGNORED)
822 continue;
823 struct span *span;
824 for (span = ss->spans.data;
825 span < ss->spans.data + ss->spans.size; span++) {
826 if (span->match == NULL && !span->bugpatch)
827 span->new = true;
832 static void handle_deleted_spans(struct superbfd *oldsbfd,
833 struct superbfd *newsbfd)
835 asection *sect;
836 for (sect = oldsbfd->abfd->sections; sect != NULL; sect = sect->next) {
837 struct supersect *ss = fetch_supersect(oldsbfd, sect);
838 struct span *span;
839 for (span = ss->spans.data;
840 span < ss->spans.data + ss->spans.size; span++) {
841 if (span->match != NULL)
842 continue;
843 if (ss->type == SS_TYPE_EXPORT) {
844 *vec_grow(&delsects, 1) = span->label;
845 write_ksplice_export(newsbfd, span, true);
846 } else if (ss->type == SS_TYPE_TEXT) {
847 *vec_grow(&delsects, 1) = span->label;
848 if (span->symbol == NULL)
849 DIE;
850 write_ksplice_deleted_patch
851 (newsbfd, span->symbol->name, span->label,
852 span->ss->name);
858 static void handle_nonzero_offset_relocs(struct supersect *ss)
860 struct span *address_span, *target_span;
861 arelent **relocp;
862 for (relocp = ss->relocs.data;
863 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
864 arelent *reloc = *relocp;
865 address_span = find_span(ss, reloc->address);
866 if (!address_span->new && !address_span->patch)
867 continue;
869 asymbol *sym = *reloc->sym_ptr_ptr;
870 if (bfd_is_const_section(sym->section))
871 continue;
872 bfd_vma offset = reloc_target_offset(ss, reloc);
873 target_span = reloc_target_span(ss, reloc);
874 if (sym->value + offset == target_span->start)
875 continue;
877 if (target_span->ss->type != SS_TYPE_TEXT)
878 continue;
879 if (target_span->patch)
880 continue;
882 target_span->patch = true;
883 changed = true;
884 debug1(ss->parent, "Changing %s because a relocation from sect "
885 "%s has a nonzero offset %lx+%lx into it\n",
886 target_span->label, ss->name, (unsigned long)sym->value,
887 (unsigned long)offset);
891 static void update_nonzero_offsets(struct superbfd *sbfd)
893 asection *sect;
894 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
895 struct supersect *ss = fetch_supersect(sbfd, sect);
896 if (ss->type == SS_TYPE_SPECIAL || ss->type == SS_TYPE_IGNORED)
897 continue;
898 handle_nonzero_offset_relocs(ss);
902 static void unmatch_addr_spans(struct span *old_span, struct span *new_span,
903 const struct table_section *ts)
905 struct span *old_sym_span =
906 span_offset_target_span(old_span, ts->addr_offset);
907 struct span *new_sym_span =
908 span_offset_target_span(new_span, ts->addr_offset);
909 assert(old_sym_span != NULL && new_sym_span != NULL);
910 if (old_sym_span->match == new_sym_span &&
911 new_sym_span->match == old_sym_span &&
912 !(new_sym_span->patch && new_sym_span->ss->type == SS_TYPE_TEXT)) {
913 if (old_sym_span->ss->type == SS_TYPE_TEXT) {
914 debug1(new_span->ss->parent, "Patching %s due "
915 "to relocations from special section %s\n",
916 new_sym_span->label, new_span->label);
917 new_sym_span->patch = true;
918 } else {
919 debug1(new_span->ss->parent, "Unmatching %s and %s due "
920 "to relocations from special section %s/%s\n",
921 old_sym_span->label, new_sym_span->label,
922 old_span->label, new_span->label);
923 old_sym_span->match = NULL;
924 new_sym_span->match = NULL;
926 changed = true;
930 static void compare_spans(struct span *old_span, struct span *new_span)
932 struct superbfd *newsbfd = new_span->ss->parent;
934 bool nonrelocs_match = nonrelocs_equal(old_span, new_span);
935 bool relocs_match = all_relocs_equal(old_span, new_span);
936 if (nonrelocs_match && relocs_match) {
937 const struct table_section *ts =
938 get_table_section(old_span->ss->name);
939 if (ts != NULL && ts->crc_sect != NULL) {
940 struct span *old_crc_span = get_crc_span(old_span, ts);
941 struct span *new_crc_span = get_crc_span(new_span, ts);
942 assert(old_crc_span != NULL);
943 assert(new_crc_span != NULL);
944 if (old_crc_span->match != new_crc_span ||
945 new_crc_span->match != old_crc_span) {
946 debug1(newsbfd, "Unmatching %s and %s due to "
947 "nonmatching CRCs\n", old_span->label,
948 new_span->label);
949 old_span->match = NULL;
950 new_span->match = NULL;
953 return;
955 if (strcmp(old_span->ss->name, "__bug_table") == 0 &&
956 strcmp(new_span->ss->name, "__bug_table") == 0 && relocs_match) {
957 debug1(newsbfd, "Changing %s due to nonmatching line numbers\n",
958 new_span->label);
959 new_span->match = NULL;
960 old_span->match = NULL;
961 new_span->bugpatch = true;
962 return;
965 char *reason;
966 if (new_span->contents_size != old_span->contents_size)
967 reason = "differing sizes";
968 else if (!nonrelocs_match)
969 reason = "differing contents";
970 else
971 reason = "differing relocations";
973 if (new_span->ss->type == SS_TYPE_TEXT) {
974 if (new_span->patch)
975 return;
976 new_span->patch = true;
977 debug1(newsbfd, "Changing %s due to %s\n", new_span->label,
978 reason);
979 } else if (new_span->ss->type == SS_TYPE_RODATA &&
980 new_span->contents_size == old_span->contents_size) {
981 if (new_span->datapatch)
982 return;
983 new_span->datapatch = true;
984 debug1(newsbfd, "Changing %s in-place due to %s\n",
985 new_span->label, reason);
986 } else if (new_span->ss->type == SS_TYPE_STRING &&
987 old_span->ss->type == SS_TYPE_STRING && relocs_match &&
988 strcmp(new_span->ss->contents.data + new_span->start,
989 old_span->ss->contents.data + old_span->start) == 0) {
990 return;
991 } else {
992 debug1(newsbfd, "Unmatching %s and %s due to %s\n",
993 old_span->label, new_span->label, reason);
994 new_span->match = NULL;
995 old_span->match = NULL;
996 if (old_span->ss->type == SS_TYPE_SPECIAL) {
997 const struct table_section *ts =
998 get_table_section(old_span->ss->name);
999 if (ts != NULL && ts->has_addr)
1000 unmatch_addr_spans(old_span, new_span, ts);
1003 changed = true;
1004 if (unchangeable_section(new_span->ss))
1005 err(newsbfd, "warning: ignoring change to nonpatchable "
1006 "section %s\n", new_span->ss->name);
1009 static void compare_matched_spans(struct superbfd *newsbfd)
1011 asection *sect;
1012 for (sect = newsbfd->abfd->sections; sect != NULL; sect = sect->next) {
1013 struct supersect *ss = fetch_supersect(newsbfd, sect);
1014 struct span *span;
1015 for (span = ss->spans.data;
1016 span < ss->spans.data + ss->spans.size; span++) {
1017 if (span->match == NULL)
1018 continue;
1019 compare_spans(span->match, span);
1024 static void handle_section_symbol_renames(struct superbfd *oldsbfd,
1025 struct superbfd *newsbfd)
1027 asection *sect;
1028 struct span *span;
1029 for (sect = newsbfd->abfd->sections; sect != NULL; sect = sect->next) {
1030 struct supersect *ss = fetch_supersect(newsbfd, sect);
1031 for (span = ss->spans.data;
1032 span < ss->spans.data + ss->spans.size; span++) {
1033 if (span->match == NULL)
1034 continue;
1035 if (strcmp(span->label, span->match->label) == 0)
1036 continue;
1037 if (strcmp(span->orig_label, span->label) != 0 &&
1038 strcmp(span->label, span->match->label) != 0)
1039 DIE;
1040 if (span->symbol != NULL)
1041 label_map_set(newsbfd, span->label,
1042 span->match->label);
1043 span->label = span->match->label;
1048 static bool part_of_reloc(struct supersect *ss, unsigned long addr)
1050 arelent **relocp;
1051 for (relocp = ss->relocs.data;
1052 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
1053 arelent *reloc = *relocp;
1054 if (addr >= reloc->address &&
1055 addr < reloc->address + bfd_get_reloc_size(reloc->howto))
1056 return true;
1058 return false;
1061 static bool nonrelocs_equal(struct span *old_span, struct span *new_span)
1063 int i;
1064 struct supersect *old_ss = old_span->ss, *new_ss = new_span->ss;
1065 if (old_span->contents_size != new_span->contents_size)
1066 return false;
1067 const unsigned char *old = old_ss->contents.data + old_span->start;
1068 const unsigned char *new = new_ss->contents.data + new_span->start;
1069 for (i = 0; i < old_span->contents_size; i++) {
1070 if (old[i] != new[i] &&
1071 !(part_of_reloc(old_ss, i + old_span->start) &&
1072 part_of_reloc(new_ss, i + new_span->start)))
1073 return false;
1075 return true;
1078 bool relocs_equal(struct supersect *old_src_ss, struct supersect *new_src_ss,
1079 arelent *old_reloc, arelent *new_reloc)
1081 struct superbfd *oldsbfd = old_src_ss->parent;
1082 struct superbfd *newsbfd = new_src_ss->parent;
1083 struct span *old_addr_span = find_span(old_src_ss, old_reloc->address);
1084 struct span *new_addr_span = find_span(new_src_ss, new_reloc->address);
1086 if (old_reloc->address - old_addr_span->start !=
1087 new_reloc->address - new_addr_span->start) {
1088 debug1(newsbfd, "Section %s/%s has reloc address mismatch at "
1089 "%lx\n", old_src_ss->name, new_src_ss->name,
1090 (unsigned long)old_reloc->address);
1091 return false;
1094 if (old_reloc->howto != new_reloc->howto) {
1095 debug1(newsbfd, "Section %s/%s has howto type mismatch at "
1096 "%lx\n", old_src_ss->name, new_src_ss->name,
1097 (unsigned long)old_reloc->address);
1098 return false;
1101 if (non_dst_mask(old_src_ss, old_reloc) !=
1102 non_dst_mask(new_src_ss, new_reloc)) {
1103 debug1(newsbfd, "Section %s/%s has contents mismatch at %lx\n",
1104 old_src_ss->name, new_src_ss->name,
1105 (unsigned long)old_reloc->address);
1106 return false;
1109 asymbol *old_sym = *old_reloc->sym_ptr_ptr;
1110 asymbol *new_sym = *new_reloc->sym_ptr_ptr;
1111 asection *old_sect = old_sym->section;
1112 asection *new_sect = new_sym->section;
1114 bfd_vma old_offset = reloc_target_offset(old_src_ss, old_reloc);
1115 bfd_vma new_offset = reloc_target_offset(new_src_ss, new_reloc);
1117 if (bfd_is_und_section(old_sect) || bfd_is_und_section(new_sect)) {
1118 if (!bfd_is_und_section(new_sect) && old_offset != 0 &&
1119 fetch_supersect(newsbfd, new_sect)->type == SS_TYPE_TEXT)
1120 return false;
1122 if (!bfd_is_und_section(new_sect) && new_offset != 0 &&
1123 fetch_supersect(oldsbfd, old_sect)->type == SS_TYPE_TEXT)
1124 return false;
1126 return strcmp(old_sym->name, new_sym->name) == 0 &&
1127 old_offset == new_offset;
1130 if (bfd_is_abs_section(old_sect) && bfd_is_abs_section(new_sect)) {
1131 if (old_sym->value + old_offset == new_sym->value + new_offset)
1132 return true;
1133 debug1(newsbfd, "Differing relocations from %s/%s to ABS "
1134 "section: %lx/%lx\n", old_addr_span->label,
1135 new_addr_span->label,
1136 (unsigned long)(old_sym->value + old_offset),
1137 (unsigned long)(new_sym->value + new_offset));
1138 return false;
1141 if (bfd_is_const_section(old_sect) || bfd_is_const_section(new_sect))
1142 DIE;
1144 struct supersect *old_ss = fetch_supersect(oldsbfd, old_sect);
1145 struct supersect *new_ss = fetch_supersect(newsbfd, new_sect);
1146 struct span *old_span = reloc_target_span(old_src_ss, old_reloc);
1147 struct span *new_span = reloc_target_span(new_src_ss, new_reloc);
1149 if (old_span->match != new_span || new_span->match != old_span) {
1150 debug1(newsbfd, "Nonmatching relocs from %s to %s/%s\n",
1151 new_src_ss->name, old_span->label, new_span->label);
1152 return false;
1155 if (old_sym->value + old_offset - old_span->start !=
1156 new_sym->value + new_offset - new_span->start) {
1157 debug1(newsbfd, "Offsets to %s/%s differ between %s "
1158 "and %s: %lx+%lx/%lx+%lx\n", old_ss->name,
1159 new_ss->name, old_src_ss->name, new_src_ss->name,
1160 (unsigned long)old_sym->value, (unsigned long)old_offset,
1161 (unsigned long)new_sym->value,
1162 (unsigned long)new_offset);
1163 return false;
1166 if ((old_sym->value + old_offset - old_span->start != 0 ||
1167 new_sym->value + new_offset - new_span->start != 0) &&
1168 new_span->patch) {
1169 debug1(newsbfd, "Relocation from %s to nonzero offsets "
1170 "%lx+%lx/%lx+%lx in changed section %s\n",
1171 new_src_ss->name, (unsigned long)old_sym->value,
1172 (unsigned long)old_offset, (unsigned long)new_sym->value,
1173 (unsigned long)new_offset, new_sym->section->name);
1174 return false;
1176 return true;
1179 bool all_relocs_equal(struct span *old_span, struct span *new_span)
1181 struct supersect *old_ss = old_span->ss, *new_ss = new_span->ss;
1182 arelent **old_relocp, **new_relocp;
1184 for (old_relocp = old_ss->relocs.data;
1185 old_relocp < old_ss->relocs.data + old_ss->relocs.size;
1186 old_relocp++) {
1187 if (find_span(old_ss, (*old_relocp)->address) == old_span)
1188 break;
1191 for (new_relocp = new_ss->relocs.data;
1192 new_relocp < new_ss->relocs.data + new_ss->relocs.size;
1193 new_relocp++) {
1194 if (find_span(new_ss, (*new_relocp)->address) == new_span)
1195 break;
1198 for (; old_relocp < old_ss->relocs.data + old_ss->relocs.size &&
1199 find_span(old_ss, (*old_relocp)->address) == old_span &&
1200 new_relocp < new_ss->relocs.data + new_ss->relocs.size &&
1201 find_span(new_ss, (*new_relocp)->address) == new_span;
1202 old_relocp++, new_relocp++) {
1203 if (!relocs_equal(old_ss, new_ss, *old_relocp, *new_relocp))
1204 return false;
1207 if ((old_relocp < old_ss->relocs.data + old_ss->relocs.size &&
1208 find_span(old_ss, (*old_relocp)->address) == old_span) ||
1209 (new_relocp < new_ss->relocs.data + new_ss->relocs.size &&
1210 find_span(new_ss, (*new_relocp)->address) == new_span)) {
1211 debug1(new_ss->parent, "Different reloc count between %s and "
1212 "%s\n", old_span->label, new_span->label);
1213 return false;
1216 return true;
1219 bfd_vma non_dst_mask(struct supersect *ss, arelent *reloc)
1221 int bits = bfd_get_reloc_size(reloc->howto) * 8;
1222 void *address = ss->contents.data + reloc->address;
1223 bfd_vma x = bfd_get(bits, ss->parent->abfd, address);
1224 return x & ~reloc->howto->dst_mask;
1227 void rm_relocs(struct superbfd *isbfd)
1229 asection *p;
1230 for (p = isbfd->abfd->sections; p != NULL; p = p->next) {
1231 struct supersect *ss = fetch_supersect(isbfd, p);
1232 bool remove_relocs = ss->keep;
1234 if (mode("keep") && ss->type == SS_TYPE_SPECIAL)
1235 remove_relocs = false;
1237 if (ss->type == SS_TYPE_KSPLICE ||
1238 ss->type == SS_TYPE_KSPLICE_CALL)
1239 remove_relocs = false;
1240 if (mode("finalize") &&
1241 (strstarts(ss->name, ".ksplice_patches") ||
1242 strstarts(ss->name, ".ksplice_relocs")))
1243 remove_relocs = true;
1245 if (remove_relocs)
1246 rm_some_relocs(ss);
1250 void rm_some_relocs(struct supersect *ss)
1252 struct arelentp_vec orig_relocs;
1253 vec_move(&orig_relocs, &ss->relocs);
1255 arelent **relocp;
1256 for (relocp = orig_relocs.data;
1257 relocp < orig_relocs.data + orig_relocs.size; relocp++) {
1258 bool rm_reloc = false;
1259 asymbol *sym_ptr = *(*relocp)->sym_ptr_ptr;
1261 if (mode("rmsyms") && str_in_set(sym_ptr->name, &rmsyms) &&
1262 bfd_is_und_section(sym_ptr->section))
1263 rm_reloc = true;
1265 if (mode("keep"))
1266 rm_reloc = true;
1268 if (mode("keep-new-code")) {
1269 if (bfd_is_const_section(sym_ptr->section)) {
1270 rm_reloc = false;
1271 } else {
1272 bfd_vma offset = reloc_target_offset(ss, *relocp);
1273 struct span *target_span =
1274 reloc_target_span(ss, *relocp);
1275 if (target_span->new ||
1276 (target_span->ss->type == SS_TYPE_TEXT &&
1277 sym_ptr->value + offset !=
1278 target_span->start))
1279 rm_reloc = false;
1282 const struct table_section *ts =
1283 get_table_section(ss->name);
1284 if (ts != NULL && ts->has_addr &&
1285 ((*relocp)->address % ts->entry_size ==
1286 ts->addr_offset ||
1287 (*relocp)->address % ts->entry_size ==
1288 ts->other_offset))
1289 rm_reloc = false;
1292 if (mode("finalize") && bfd_is_und_section(sym_ptr->section))
1293 rm_reloc = true;
1295 if (strcmp(sym_ptr->name, "mcount") == 0 &&
1296 bfd_is_und_section(sym_ptr->section))
1297 rm_reloc = false;
1299 if (!find_span(ss, (*relocp)->address)->keep)
1300 rm_reloc = false;
1302 if (rm_reloc)
1303 write_ksplice_reloc(ss, *relocp);
1304 else
1305 *vec_grow(&ss->relocs, 1) = *relocp;
1309 struct supersect *make_section(struct superbfd *sbfd, const char *fmt, ...)
1311 va_list ap;
1312 va_start(ap, fmt);
1313 char *name = vstrprintf(fmt, ap);
1314 va_end(ap);
1316 asection *sect = bfd_get_section_by_name(sbfd->abfd, name);
1317 if (sect != NULL)
1318 return fetch_supersect(sbfd, sect);
1319 else
1320 return new_supersect(sbfd, name);
1323 arelent *create_reloc(struct supersect *ss, const void *addr, asymbol **symp,
1324 bfd_vma offset)
1326 bfd_reloc_code_real_type code;
1327 switch (bfd_arch_bits_per_address(ss->parent->abfd)) {
1328 case 32:
1329 code = BFD_RELOC_32;
1330 break;
1331 case 64:
1332 code = BFD_RELOC_64;
1333 break;
1334 default:
1335 DIE;
1338 arelent *reloc = malloc(sizeof(*reloc));
1339 reloc->sym_ptr_ptr = symp;
1340 reloc->address = addr_offset(ss, addr);
1341 reloc->howto = bfd_reloc_type_lookup(ss->parent->abfd, code);
1342 reloc->addend = offset;
1343 return reloc;
1346 void write_reloc(struct supersect *ss, const void *addr, asymbol **symp,
1347 bfd_vma offset)
1349 *vec_grow(&ss->new_relocs, 1) = create_reloc(ss, addr, symp, offset);
1352 void write_string(struct supersect *ss, const char **addr, const char *fmt, ...)
1354 va_list ap;
1355 struct supersect *str_ss = make_section(ss->parent, ".ksplice_str");
1356 char *str;
1357 va_start(ap, fmt);
1358 int len = vasprintf(&str, fmt, ap);
1359 assert(len >= 0);
1360 va_end(ap);
1362 unsigned long *str_offp = ulong_hash_lookup(&ksplice_string_offset, str,
1363 FALSE);
1364 if (str_offp == NULL) {
1365 char *buf = sect_grow(str_ss, len + 1, char);
1366 memcpy(buf, str, len + 1);
1367 str_offp = ulong_hash_lookup(&ksplice_string_offset, str, TRUE);
1368 *str_offp = addr_offset(str_ss, buf);
1371 write_reloc(ss, addr, &str_ss->symbol, *str_offp);
1374 void lookup_system_map(struct addr_vec *addrs, const char *name, long offset)
1376 struct addr_vec *map_addrs =
1377 addr_vec_hash_lookup(&system_map, name, FALSE);
1378 if (map_addrs == NULL)
1379 return;
1381 unsigned long *addr, *map_addr;
1382 for (map_addr = map_addrs->data;
1383 map_addr < map_addrs->data + map_addrs->size; map_addr++) {
1384 for (addr = addrs->data; addr < addrs->data + addrs->size;
1385 addr++) {
1386 if (*addr == *map_addr + offset)
1387 break;
1389 if (addr < addrs->data + addrs->size)
1390 continue;
1391 *vec_grow(addrs, 1) = *map_addr + offset;
1395 void compute_system_map_array(struct superbfd *sbfd, struct addr_vec *addrs,
1396 asymbol *sym)
1398 if (bfd_is_abs_section(sym->section)) {
1399 *vec_grow(addrs, 1) = sym->value;
1400 } else if (bfd_is_und_section(sym->section)) {
1401 lookup_system_map(addrs, sym->name, 0);
1402 } else if (!bfd_is_const_section(sym->section)) {
1403 asymbol **gsymp;
1404 for (gsymp = sbfd->syms.data;
1405 gsymp < sbfd->syms.data + sbfd->syms.size; gsymp++) {
1406 asymbol *gsym = *gsymp;
1407 if ((gsym->flags & BSF_DEBUGGING) == 0 &&
1408 gsym->section == sym->section)
1409 lookup_system_map(addrs, gsym->name,
1410 sym->value - gsym->value);
1415 void write_ksplice_system_map(struct superbfd *sbfd, asymbol *sym,
1416 const char *label)
1418 bool *done = bool_hash_lookup(&system_map_written, label, TRUE);
1419 if (*done)
1420 return;
1421 *done = true;
1423 struct addr_vec addrs;
1424 vec_init(&addrs);
1426 compute_system_map_array(sbfd, &addrs, sym);
1427 if (addrs.size != 0) {
1428 struct supersect *smap_ss =
1429 make_section(sbfd, ".ksplice_system_map");
1430 struct ksplice_system_map *smap =
1431 sect_grow(smap_ss, 1, struct ksplice_system_map);
1432 write_string(smap_ss, &smap->label, "%s", label);
1434 struct supersect *array_ss = make_section(sbfd,
1435 ".ksplice_array");
1436 void *buf = sect_grow(array_ss, addrs.size,
1437 typeof(*addrs.data));
1438 memcpy(buf, addrs.data, addrs.size * sizeof(*addrs.data));
1439 smap->nr_candidates = addrs.size;
1440 write_reloc(smap_ss, &smap->candidates, &array_ss->symbol,
1441 addr_offset(array_ss, buf));
1443 vec_free(&addrs);
1446 void write_ksplice_symbol_backend(struct supersect *ss,
1447 struct ksplice_symbol *const *addr,
1448 asymbol *sym, const char *label,
1449 const char *name)
1451 struct supersect *ksymbol_ss = make_section(ss->parent,
1452 ".ksplice_symbols");
1453 struct ksplice_symbol *ksymbol;
1454 unsigned long *ksymbol_offp;
1456 ksymbol_offp = ulong_hash_lookup(&ksplice_symbol_offset, label, FALSE);
1457 if (ksymbol_offp != NULL) {
1458 write_reloc(ss, addr, &ksymbol_ss->symbol, *ksymbol_offp);
1459 return;
1461 ksymbol = sect_grow(ksymbol_ss, 1, struct ksplice_symbol);
1462 ksymbol_offp = ulong_hash_lookup(&ksplice_symbol_offset, label, TRUE);
1463 *ksymbol_offp = addr_offset(ksymbol_ss, ksymbol);
1465 write_reloc(ss, addr, &ksymbol_ss->symbol, *ksymbol_offp);
1466 write_string(ksymbol_ss, &ksymbol->label, "%s", label);
1467 if (name != NULL) {
1468 write_string(ksymbol_ss, &ksymbol->name, "%s", name);
1469 write_ksplice_system_map(ksymbol_ss->parent, sym, label);
1473 void write_ksplice_symbol(struct supersect *ss,
1474 struct ksplice_symbol *const *addr,
1475 asymbol *sym, struct span *span,
1476 const char *addstr_sect)
1478 const char *label, *name;
1479 if (span != NULL && span->start != 0)
1480 label = span->label;
1481 else
1482 label = label_lookup(ss->parent, sym);
1484 asymbol *gsym = canonical_symbol(ss->parent, sym);
1485 if (strcmp(addstr_sect, "") != 0)
1486 name = NULL;
1487 else if (bfd_is_und_section(sym->section))
1488 name = sym->name;
1489 else if (bfd_is_const_section(sym->section))
1490 name = NULL;
1491 else if (span != NULL && span->symbol == NULL)
1492 name = NULL;
1493 else if (gsym == NULL || (gsym->flags & BSF_SECTION_SYM) != 0)
1494 name = NULL;
1495 else
1496 name = gsym->name;
1498 write_ksplice_symbol_backend(ss, addr, sym,
1499 strprintf("%s%s", addstr_sect, label),
1500 name);
1503 void write_ksplice_reloc(struct supersect *ss, arelent *orig_reloc)
1505 asymbol *sym_ptr = *orig_reloc->sym_ptr_ptr;
1506 bfd_vma reloc_addend = reloc_offset(ss, orig_reloc);
1507 bfd_vma target_addend = reloc_target_offset(ss, orig_reloc);
1508 unsigned long *repladdr = ss->contents.data + orig_reloc->address;
1510 if (mode("finalize") && strstarts(ss->name, ".ksplice_patches")) {
1511 *repladdr = 0;
1512 return;
1514 if (mode("finalize") && strstarts(ss->name, ".ksplice_relocs")) {
1515 assert(strstarts(sym_ptr->name, KSPLICE_SYMBOL_STR));
1516 asymbol fake_sym;
1517 fake_sym.name = sym_ptr->name + strlen(KSPLICE_SYMBOL_STR);
1518 fake_sym.section = bfd_und_section_ptr;
1519 fake_sym.value = 0;
1520 fake_sym.flags = 0;
1522 write_ksplice_symbol_backend
1523 (ss, (struct ksplice_symbol **)repladdr, &fake_sym,
1524 fake_sym.name, fake_sym.name);
1525 return;
1528 struct span *span = reloc_target_span(ss, orig_reloc);
1529 if (span == ss->spans.data && span->start != target_addend)
1530 span = NULL;
1531 write_canary(ss, orig_reloc->address,
1532 bfd_get_reloc_size(orig_reloc->howto),
1533 orig_reloc->howto->dst_mask);
1535 struct supersect *kreloc_ss;
1536 if (mode("rmsyms"))
1537 kreloc_ss = make_section(ss->parent, ".ksplice_init_relocs");
1538 else
1539 kreloc_ss = make_section(ss->parent, ".ksplice_relocs%s",
1540 ss->name);
1541 struct ksplice_reloc *kreloc = sect_grow(kreloc_ss, 1,
1542 struct ksplice_reloc);
1544 struct span *address_span = find_span(ss, orig_reloc->address);
1545 write_reloc(kreloc_ss, &kreloc->blank_addr,
1546 &ss->symbol, orig_reloc->address + address_span->shift);
1547 if (bfd_is_und_section(sym_ptr->section) && mode("keep")) {
1548 char *name = strprintf(KSPLICE_SYMBOL_STR "%s", sym_ptr->name);
1549 asymbol **symp = make_undefined_symbolp(ss->parent, name);
1550 write_reloc(kreloc_ss, &kreloc->symbol, symp, 0);
1551 } else {
1552 write_ksplice_symbol(kreloc_ss, &kreloc->symbol, sym_ptr, span,
1553 "");
1555 if (span != NULL && span->start != 0) {
1556 reloc_addend += sym_ptr->value - span->start;
1557 target_addend += sym_ptr->value - span->start;
1559 kreloc->insn_addend = reloc_addend - target_addend;
1560 kreloc->target_addend = target_addend;
1561 write_ksplice_reloc_howto(kreloc_ss, &kreloc->howto, orig_reloc->howto,
1562 KSPLICE_HOWTO_RELOC);
1565 static void write_ksplice_reloc_howto(struct supersect *ss, const
1566 struct ksplice_reloc_howto *const *addr,
1567 reloc_howto_type *howto,
1568 enum ksplice_reloc_howto_type type)
1570 struct supersect *khowto_ss = make_section(ss->parent,
1571 ".ksplice_reloc_howtos");
1572 struct ksplice_reloc_howto *khowto;
1573 unsigned long *khowto_offp;
1575 khowto_offp = ulong_hash_lookup(&ksplice_howto_offset, howto->name,
1576 FALSE);
1577 if (khowto_offp != NULL) {
1578 write_reloc(ss, addr, &khowto_ss->symbol, *khowto_offp);
1579 return;
1581 khowto = sect_grow(khowto_ss, 1, struct ksplice_reloc_howto);
1582 khowto_offp = ulong_hash_lookup(&ksplice_howto_offset, howto->name,
1583 TRUE);
1584 *khowto_offp = addr_offset(khowto_ss, khowto);
1586 khowto->type = type;
1587 khowto->pcrel = howto->pc_relative;
1588 khowto->size = bfd_get_reloc_size(howto);
1589 khowto->dst_mask = howto->dst_mask;
1590 khowto->rightshift = howto->rightshift;
1591 khowto->signed_addend =
1592 (howto->complain_on_overflow == complain_overflow_signed) ||
1593 (howto->complain_on_overflow == complain_overflow_bitfield);
1594 write_reloc(ss, addr, &khowto_ss->symbol, *khowto_offp);
1597 #define CANARY(x, canary) ((x & ~howto->dst_mask) | (canary & howto->dst_mask))
1599 void write_canary(struct supersect *ss, int offset, bfd_size_type size,
1600 bfd_vma dst_mask)
1602 int bits = size * 8;
1603 void *address = ss->contents.data + offset;
1604 bfd_vma x = bfd_get(bits, ss->parent->abfd, address);
1605 x = (x & ~dst_mask) | ((bfd_vma)KSPLICE_CANARY & dst_mask);
1606 bfd_put(bits, ss->parent->abfd, x, address);
1609 static void write_date_relocs(struct superbfd *sbfd, const char *str,
1610 enum ksplice_reloc_howto_type type)
1612 asection *sect;
1613 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
1614 struct supersect *ss = fetch_supersect(sbfd, sect);
1615 if (ss->type != SS_TYPE_STRING && ss->type != SS_TYPE_RODATA)
1616 continue;
1617 void *ptr;
1618 struct span *span;
1619 for (span = ss->spans.data;
1620 span < ss->spans.data + ss->spans.size; span++) {
1621 if (!span->keep)
1622 continue;
1623 for (ptr = ss->contents.data + span->start;
1624 ptr + strlen(str) < ss->contents.data +
1625 span->start + span->contents_size; ptr++) {
1626 if (strcmp((const char *)ptr, str) == 0)
1627 write_ksplice_date_reloc
1628 (ss, addr_offset(ss, ptr), str,
1629 type);
1635 static void write_ksplice_date_reloc(struct supersect *ss, unsigned long offset,
1636 const char *str,
1637 enum ksplice_reloc_howto_type type)
1639 struct supersect *kreloc_ss;
1640 kreloc_ss = make_section(ss->parent, ".ksplice_relocs%s", ss->name);
1641 struct ksplice_reloc *kreloc = sect_grow(kreloc_ss, 1,
1642 struct ksplice_reloc);
1644 const char *filename = ss->parent->abfd->filename;
1645 char *c = strstr(filename, ".KSPLICE");
1646 int flen = (c == NULL ? strlen(filename) : c - filename);
1648 write_ksplice_symbol_backend(kreloc_ss, &kreloc->symbol, NULL,
1649 strprintf("%s<%.*s>", str, flen, filename),
1650 NULL);
1652 struct span *span = find_span(ss, offset);
1653 write_reloc(kreloc_ss, &kreloc->blank_addr, &ss->symbol,
1654 offset + span->shift);
1655 write_ksplice_nonreloc_howto(kreloc_ss, &kreloc->howto, type,
1656 strlen(str));
1659 static void write_table_relocs(struct superbfd *sbfd, const char *sectname,
1660 enum ksplice_reloc_howto_type type)
1662 asection *sect = bfd_get_section_by_name(sbfd->abfd, sectname);
1663 if (sect == NULL)
1664 return;
1665 struct supersect *ss = fetch_supersect(sbfd, sect);
1667 const struct table_section *s = get_table_section(sectname);
1668 if (s == NULL)
1669 DIE;
1671 void *entry;
1672 for (entry = ss->contents.data;
1673 entry < ss->contents.data + ss->contents.size;
1674 entry += s->entry_size) {
1675 struct span *span = find_span(ss, addr_offset(ss, entry));
1676 assert(span != NULL);
1677 if (!span->keep)
1678 continue;
1680 arelent *reloc = find_reloc(ss, entry + s->addr_offset);
1681 assert(reloc != NULL);
1682 asymbol *sym = *reloc->sym_ptr_ptr;
1683 assert(!bfd_is_const_section(sym->section));
1684 struct supersect *sym_ss = fetch_supersect(sbfd, sym->section);
1685 unsigned long addr = sym->value +
1686 reloc_target_offset(ss, reloc);
1687 write_ksplice_table_reloc(sym_ss, addr, span->label, type);
1691 static void write_ksplice_table_reloc(struct supersect *ss,
1692 unsigned long address,
1693 const char *label,
1694 enum ksplice_reloc_howto_type type)
1696 struct supersect *kreloc_ss;
1697 kreloc_ss = make_section(ss->parent, ".ksplice_relocs%s", ss->name);
1698 struct ksplice_reloc *kreloc = sect_grow(kreloc_ss, 1,
1699 struct ksplice_reloc);
1700 struct span *span = find_span(ss, address);
1701 assert(span != NULL);
1703 write_ksplice_symbol_backend(kreloc_ss, &kreloc->symbol, NULL,
1704 label, NULL);
1705 write_reloc(kreloc_ss, &kreloc->blank_addr, &ss->symbol,
1706 address + span->shift);
1707 write_ksplice_nonreloc_howto(kreloc_ss, &kreloc->howto, type, 0);
1710 static void write_ksplice_nonreloc_howto(struct supersect *ss,
1711 const struct ksplice_reloc_howto
1712 *const *addr,
1713 enum ksplice_reloc_howto_type type,
1714 int size)
1716 struct supersect *khowto_ss =
1717 make_section(ss->parent, ".ksplice_reloc_howtos");
1718 struct ksplice_reloc_howto *khowto =
1719 sect_grow(khowto_ss, 1, struct ksplice_reloc_howto);
1721 khowto->type = type;
1722 khowto->size = size;
1723 khowto->pcrel = 0;
1724 khowto->dst_mask = 0;
1725 khowto->rightshift = 0;
1726 khowto->signed_addend = 0;
1727 write_reloc(ss, addr, &khowto_ss->symbol,
1728 addr_offset(khowto_ss, khowto));
1731 static void write_ksplice_section(struct span *span)
1733 struct supersect *ss = span->ss;
1734 const char *sectname = span->ss->name;
1735 const struct table_section *ts = get_table_section(ss->name);
1737 if (ts != NULL && ts->has_addr) {
1738 arelent *reloc = find_reloc(ss, ss->contents.data + span->start
1739 + ts->addr_offset);
1740 assert(reloc != NULL);
1741 asymbol *rsym = *reloc->sym_ptr_ptr;
1742 assert(!bfd_is_const_section(rsym->section));
1743 sectname = rsym->section->name;
1746 struct supersect *ksect_ss =
1747 make_section(ss->parent, ".ksplice_sections%s", sectname);
1748 struct ksplice_section *ksect = sect_grow(ksect_ss, 1,
1749 struct ksplice_section);
1750 asymbol *sym = span->symbol == NULL ? ss->symbol : span->symbol;
1752 write_ksplice_symbol(ksect_ss, &ksect->symbol, sym, span,
1753 mode("keep-new-code") ? "(post)" : "");
1754 ksect->size = span->size;
1755 ksect->flags = 0;
1757 if (ss->type == SS_TYPE_RODATA || ss->type == SS_TYPE_STRING ||
1758 ss->type == SS_TYPE_EXPORT)
1759 ksect->flags |= KSPLICE_SECTION_RODATA;
1760 if (ss->type == SS_TYPE_DATA)
1761 ksect->flags |= KSPLICE_SECTION_DATA;
1762 if (ss->type == SS_TYPE_TEXT)
1763 ksect->flags |= KSPLICE_SECTION_TEXT;
1764 assert(ksect->flags != 0);
1766 if (ss->type == SS_TYPE_STRING)
1767 ksect->flags |= KSPLICE_SECTION_STRING;
1769 write_reloc(ksect_ss, &ksect->address, &ss->symbol,
1770 span->start + span->shift);
1773 static void write_ksplice_patch_reloc(struct supersect *ss,
1774 const char *sectname, unsigned long *addr,
1775 bfd_size_type size, const char *label,
1776 long addend)
1778 struct supersect *kreloc_ss;
1779 kreloc_ss = make_section(ss->parent, ".ksplice_relocs%s", sectname);
1780 struct ksplice_reloc *kreloc = sect_grow(kreloc_ss, 1,
1781 struct ksplice_reloc);
1783 write_canary(ss, addr_offset(ss, addr), size, -1);
1784 write_ksplice_symbol_backend(kreloc_ss, &kreloc->symbol, NULL,
1785 label, NULL);
1786 write_reloc(kreloc_ss, &kreloc->blank_addr, &ss->symbol,
1787 addr_offset(ss, addr));
1788 reloc_howto_type *howto =
1789 bfd_reloc_type_lookup(ss->parent->abfd,
1790 PASTE(BFD_RELOC_, LONG_BIT));
1791 write_ksplice_reloc_howto(kreloc_ss, &kreloc->howto, howto,
1792 KSPLICE_HOWTO_RELOC);
1793 kreloc->target_addend = addend;
1794 kreloc->insn_addend = 0;
1797 void write_ksplice_patch(struct superbfd *sbfd, struct span *span)
1799 struct supersect *kpatch_ss =
1800 make_section(sbfd, ".ksplice_patches%s", span->ss->name);
1801 struct ksplice_patch *kpatch = sect_grow(kpatch_ss, 1,
1802 struct ksplice_patch);
1804 write_ksplice_patch_reloc(kpatch_ss, span->ss->name, &kpatch->oldaddr,
1805 sizeof(kpatch->oldaddr), span->label, 0);
1806 if (span->ss->type == SS_TYPE_TEXT) {
1807 kpatch->type = KSPLICE_PATCH_TEXT;
1808 write_patch_storage(kpatch_ss, kpatch, MAX_TRAMPOLINE_SIZE,
1809 NULL);
1810 } else {
1811 kpatch->type = KSPLICE_PATCH_DATA;
1812 kpatch->size = span->contents_size;
1813 struct supersect *data_ss =
1814 make_section(sbfd, ".ksplice_patch_data");
1815 write_reloc(kpatch_ss, &kpatch->contents, &span->ss->symbol,
1816 span->start + span->shift);
1817 char *saved = sect_do_grow(data_ss, 1, span->contents_size, 1);
1818 write_reloc(kpatch_ss, &kpatch->saved, &data_ss->symbol,
1819 addr_offset(data_ss, saved));
1821 write_reloc(kpatch_ss, &kpatch->repladdr, &span->ss->symbol,
1822 span->start + span->shift);
1825 asymbol **make_undefined_symbolp(struct superbfd *sbfd, const char *name)
1827 asymbol **symp;
1828 for (symp = sbfd->syms.data; symp < sbfd->syms.data + sbfd->syms.size;
1829 symp++) {
1830 asymbol *sym = *symp;
1831 if (strcmp(name, sym->name) == 0 &&
1832 bfd_is_und_section(sym->section))
1833 return symp;
1835 asymbol ***sympp;
1836 for (sympp = sbfd->new_syms.data;
1837 sympp < sbfd->new_syms.data + sbfd->new_syms.size; sympp++) {
1838 asymbol **symp = *sympp;
1839 asymbol *sym = *symp;
1840 if (strcmp(name, sym->name) == 0 &&
1841 bfd_is_und_section(sym->section))
1842 return symp;
1845 symp = malloc(sizeof(*symp));
1846 *symp = bfd_make_empty_symbol(sbfd->abfd);
1847 asymbol *sym = *symp;
1848 sym->name = name;
1849 sym->section = bfd_und_section_ptr;
1850 sym->flags = 0;
1851 sym->value = 0;
1852 *vec_grow(&sbfd->new_syms, 1) = symp;
1853 return symp;
1856 void write_ksplice_deleted_patch(struct superbfd *sbfd, const char *name,
1857 const char *label, const char *sectname)
1859 struct supersect *kpatch_ss =
1860 make_section(sbfd, ".ksplice_patches%s", sectname);
1861 struct ksplice_patch *kpatch = sect_grow(kpatch_ss, 1,
1862 struct ksplice_patch);
1864 write_ksplice_patch_reloc(kpatch_ss, sectname, &kpatch->oldaddr,
1865 sizeof(kpatch->oldaddr), label, 0);
1866 kpatch->type = KSPLICE_PATCH_TEXT;
1867 asymbol **symp = make_undefined_symbolp(sbfd, strdup(name));
1868 write_reloc(kpatch_ss, &kpatch->repladdr, symp, 0);
1869 write_patch_storage(kpatch_ss, kpatch, MAX_TRAMPOLINE_SIZE, NULL);
1872 void write_ksplice_export(struct superbfd *sbfd, struct span *span, bool del)
1874 struct supersect *kpatch_ss = make_section(sbfd, ".ksplice_patches");
1875 struct ksplice_patch *kpatch = sect_grow(kpatch_ss, 1,
1876 struct ksplice_patch);
1877 struct supersect *data_ss;
1879 const struct table_section *ts = get_table_section(span->ss->name);
1880 assert(ts != NULL);
1881 const char **addr =
1882 span->ss->contents.data + span->start + ts->other_offset;
1883 const char *symname = read_string(span->ss, addr);
1885 char *oldname, *newname;
1886 if (del) {
1887 oldname = strprintf("%s:%s", span->ss->name, symname);
1888 newname = strprintf("DISABLED_%s_%s", symname, kid);
1889 } else {
1890 oldname = strprintf("%s:DISABLED_%s_%s", span->ss->name,
1891 symname, kid);
1892 newname = strprintf("%s", symname);
1893 write_string(span->ss, addr, "DISABLED_%s_%s", symname, kid);
1896 write_ksplice_patch_reloc(kpatch_ss, "", &kpatch->oldaddr,
1897 sizeof(kpatch->oldaddr), oldname,
1898 ts->other_offset);
1899 kpatch->type = KSPLICE_PATCH_EXPORT;
1900 const char **namep = write_patch_storage(kpatch_ss, kpatch,
1901 sizeof(newname), &data_ss);
1902 write_string(data_ss, namep, "%s", newname);
1905 void filter_table_sections(struct superbfd *isbfd)
1907 struct supersect *tables_ss =
1908 fetch_supersect(offsets_sbfd,
1909 bfd_get_section_by_name(offsets_sbfd->abfd,
1910 ".ksplice_table_sections"));
1911 const struct table_section *ts;
1912 for (ts = tables_ss->contents.data;
1913 (void *)ts < tables_ss->contents.data + tables_ss->contents.size;
1914 ts++) {
1915 struct table_section s = *ts;
1916 s.sect = read_string(tables_ss, &ts->sect);
1917 s.other_sect = read_string(tables_ss, &ts->other_sect);
1918 s.crc_sect = read_string(tables_ss, &ts->crc_sect);
1919 filter_table_section(isbfd, &s);
1923 void filter_table_section(struct superbfd *sbfd, const struct table_section *s)
1925 asection *isection = bfd_get_section_by_name(sbfd->abfd, s->sect);
1926 if (isection == NULL)
1927 return;
1928 struct supersect *ss = fetch_supersect(sbfd, isection);
1930 void *entry;
1931 for (entry = ss->contents.data;
1932 entry < ss->contents.data + ss->contents.size;
1933 entry += s->entry_size) {
1934 struct span *span = find_span(ss, addr_offset(ss, entry));
1935 assert(span != NULL);
1937 if (s->has_addr) {
1938 struct span *sym_span =
1939 span_offset_target_span(span, s->addr_offset);
1940 assert(sym_span != NULL);
1941 if (sym_span->keep)
1942 keep_span(span);
1945 if (s->other_sect != NULL) {
1946 struct span *sym_span =
1947 span_offset_target_span(span, s->other_offset);
1948 assert(sym_span != NULL);
1949 if (span->keep)
1950 keep_span(sym_span);
1953 if (s->crc_sect != NULL) {
1954 struct span *crc_span = get_crc_span(span, s);
1955 assert(crc_span != NULL);
1956 if (span->keep && mode("keep-new-code"))
1957 keep_span(crc_span);
1962 static void match_table_spans(struct span *old_span, struct span *new_span)
1964 const struct table_section *ts = get_table_section(old_span->ss->name);
1966 if (strcmp(old_span->ss->name, new_span->ss->name) != 0)
1967 return;
1968 if (ts == NULL || old_span->ss->type != SS_TYPE_SPECIAL ||
1969 new_span->ss->type != SS_TYPE_SPECIAL)
1970 return;
1971 if (old_span->match != NULL || new_span->match != NULL)
1972 return;
1974 if (ts->has_addr) {
1975 void *old_entry = old_span->ss->contents.data + old_span->start;
1976 void *new_entry = new_span->ss->contents.data + new_span->start;
1977 arelent *old_reloc =
1978 find_reloc(old_span->ss, old_entry + ts->addr_offset);
1979 arelent *new_reloc =
1980 find_reloc(new_span->ss, new_entry + ts->addr_offset);
1981 assert(old_reloc != NULL && new_reloc != NULL);
1982 struct span *old_sym_span =
1983 reloc_target_span(old_span->ss, old_reloc);
1984 struct span *new_sym_span =
1985 reloc_target_span(new_span->ss, new_reloc);
1986 assert(old_sym_span != NULL && new_sym_span != NULL);
1987 if (old_sym_span->match == new_sym_span &&
1988 new_sym_span->match == old_sym_span &&
1989 old_reloc->address - old_sym_span->start ==
1990 new_reloc->address - new_sym_span->start)
1991 match_spans(old_span, new_span);
1995 static struct span *get_crc_span(struct span *span,
1996 const struct table_section *ts)
1998 void *entry = span->ss->contents.data + span->start;
1999 asection *crc_sect = bfd_get_section_by_name(span->ss->parent->abfd,
2000 ts->crc_sect);
2001 if (crc_sect == NULL)
2002 return NULL;
2003 struct supersect *crc_ss = fetch_supersect(span->ss->parent, crc_sect);
2004 if (crc_ss == NULL)
2005 return NULL;
2006 struct span *crc_span = find_span(crc_ss, addr_offset(span->ss, entry) /
2007 ts->entry_size * ts->crc_size);
2008 return crc_span;
2011 void mark_precallable_spans(struct superbfd *sbfd)
2013 asection *sect;
2014 struct supersect *ss, *sym_ss;
2015 struct span *address_span, *target_span;
2016 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2017 ss = fetch_supersect(sbfd, sect);
2018 arelent **relocp;
2019 if (ss->type == SS_TYPE_SPECIAL)
2020 continue;
2021 for (relocp = ss->relocs.data;
2022 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
2023 asymbol *sym = *(*relocp)->sym_ptr_ptr;
2024 address_span = find_span(ss, (*relocp)->address);
2025 if (!address_span->precallable)
2026 continue;
2027 target_span = reloc_target_span(ss, *relocp);
2028 if (target_span == NULL || target_span->keep)
2029 continue;
2030 sym_ss = fetch_supersect(sbfd, sym->section);
2031 if (sym_ss->type == SS_TYPE_IGNORED)
2032 continue;
2033 target_span->precallable = true;
2034 changed = true;
2039 void keep_referenced_sections(struct superbfd *sbfd)
2041 asection *sect;
2042 struct supersect *ss, *sym_ss;
2043 struct span *address_span, *target_span;
2044 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2045 ss = fetch_supersect(sbfd, sect);
2046 arelent **relocp;
2047 if (ss->type == SS_TYPE_SPECIAL)
2048 continue;
2049 for (relocp = ss->relocs.data;
2050 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
2051 asymbol *sym = *(*relocp)->sym_ptr_ptr;
2052 address_span = find_span(ss, (*relocp)->address);
2053 if (!address_span->keep)
2054 continue;
2055 target_span = reloc_target_span(ss, *relocp);
2056 if (target_span == NULL || target_span->keep)
2057 continue;
2058 sym_ss = fetch_supersect(sbfd, sym->section);
2059 if (sym_ss->type == SS_TYPE_IGNORED)
2060 continue;
2061 keep_span(target_span);
2062 changed = true;
2067 void copy_symbols(struct asymbolp_vec *osyms, struct asymbolpp_vec *isyms)
2069 asymbol ***sympp;
2070 for (sympp = isyms->data; sympp < isyms->data + isyms->size; sympp++)
2071 *vec_grow(osyms, 1) = **sympp;
2074 /* Modified function from GNU Binutils objcopy.c */
2075 bfd_boolean copy_object(bfd *ibfd, bfd *obfd)
2077 assert(bfd_set_format(obfd, bfd_get_format(ibfd)));
2079 bfd_vma start = bfd_get_start_address(ibfd);
2081 flagword flags = bfd_get_file_flags(ibfd);
2082 flags &= bfd_applicable_file_flags(obfd);
2084 assert(bfd_set_start_address(obfd, start)
2085 && bfd_set_file_flags(obfd, flags));
2087 enum bfd_architecture iarch = bfd_get_arch(ibfd);
2088 unsigned int imach = bfd_get_mach(ibfd);
2089 assert(bfd_set_arch_mach(obfd, iarch, imach));
2090 assert(bfd_set_format(obfd, bfd_get_format(ibfd)));
2092 /* BFD mandates that all output sections be created and sizes set before
2093 any output is done. Thus, we traverse all sections multiple times. */
2094 bfd_map_over_sections(ibfd, setup_section, obfd);
2096 struct supersect *new_supersects = fetch_superbfd(ibfd)->new_supersects;
2097 struct supersect *ss;
2098 for (ss = new_supersects; ss != NULL; ss = ss->next)
2099 setup_new_section(obfd, ss);
2101 /* Mark symbols used in output relocations so that they
2102 are kept, even if they are local labels or static symbols.
2104 Note we iterate over the input sections examining their
2105 relocations since the relocations for the output sections
2106 haven't been set yet. mark_symbols_used_in_relocations will
2107 ignore input sections which have no corresponding output
2108 section. */
2110 bfd_map_over_sections(ibfd, mark_symbols_used_in_relocations, NULL);
2111 for (ss = new_supersects; ss != NULL; ss = ss->next)
2112 ss_mark_symbols_used_in_relocations(ss);
2113 struct asymbolp_vec osyms;
2114 vec_init(&osyms);
2115 filter_symbols(ibfd, obfd, &osyms, &fetch_superbfd(ibfd)->syms);
2116 copy_symbols(&osyms, &fetch_superbfd(ibfd)->new_syms);
2118 bfd_set_symtab(obfd, osyms.data, osyms.size);
2120 /* This has to happen after the symbol table has been set. */
2121 bfd_map_over_sections(obfd, write_section, NULL);
2123 /* Allow the BFD backend to copy any private data it understands
2124 from the input BFD to the output BFD. This is done last to
2125 permit the routine to look at the filtered symbol table, which is
2126 important for the ECOFF code at least. */
2127 assert(bfd_copy_private_bfd_data(ibfd, obfd));
2129 return TRUE;
2132 /* Modified function from GNU Binutils objcopy.c */
2133 void setup_section(bfd *ibfd, asection *isection, void *obfdarg)
2135 struct superbfd *isbfd = fetch_superbfd(ibfd);
2136 struct supersect *ss = fetch_supersect(isbfd, isection);
2137 bfd *obfd = obfdarg;
2138 bfd_vma vma;
2140 if (!ss->keep)
2141 return;
2143 asection *osection = bfd_make_section_anyway(obfd, ss->name);
2144 assert(osection != NULL);
2146 osection->userdata = ss;
2147 bfd_set_section_flags(obfd, osection, ss->flags);
2148 ss->symbol = osection->symbol;
2149 assert(bfd_set_section_size(obfd, osection, ss->contents.size));
2151 vma = bfd_section_vma(ibfd, isection);
2152 assert(bfd_set_section_vma(obfd, osection, vma));
2154 osection->lma = isection->lma;
2155 assert(bfd_set_section_alignment(obfd, osection, ss->alignment));
2156 osection->entsize = ss->entsize;
2157 osection->output_section = osection;
2158 osection->output_offset = 0;
2159 isection->output_section = osection;
2160 isection->output_offset = 0;
2161 return;
2164 void setup_new_section(bfd *obfd, struct supersect *ss)
2166 asection *osection = bfd_make_section_anyway(obfd, ss->name);
2167 assert(osection != NULL);
2168 bfd_set_section_flags(obfd, osection, ss->flags);
2170 osection->userdata = ss;
2171 ss->symbol = osection->symbol;
2172 assert(bfd_set_section_size(obfd, osection, ss->contents.size));
2173 assert(bfd_set_section_vma(obfd, osection, 0));
2175 osection->lma = 0;
2176 assert(bfd_set_section_alignment(obfd, osection, ss->alignment));
2177 osection->entsize = ss->entsize;
2178 osection->output_section = osection;
2179 osection->output_offset = 0;
2182 static int compare_reloc_addresses(const void *aptr, const void *bptr)
2184 const arelent *const *a = aptr, *const *b = bptr;
2185 return (*a)->address - (*b)->address;
2188 static void delete_obsolete_relocs(struct supersect *ss)
2190 if (ss->new_relocs.size == 0)
2191 return;
2193 qsort(ss->relocs.data, ss->relocs.size, sizeof(*ss->relocs.data),
2194 compare_reloc_addresses);
2195 qsort(ss->new_relocs.data, ss->new_relocs.size,
2196 sizeof(*ss->new_relocs.data), compare_reloc_addresses);
2198 struct arelentp_vec orig_relocs;
2199 vec_move(&orig_relocs, &ss->relocs);
2201 arelent **relocp, **new_relocp = ss->new_relocs.data;
2202 for (relocp = orig_relocs.data;
2203 relocp < orig_relocs.data + orig_relocs.size; relocp++) {
2204 while (new_relocp < ss->new_relocs.data + ss->new_relocs.size &&
2205 (*new_relocp)->address < (*relocp)->address)
2206 new_relocp++;
2207 arelent *reloc = *relocp, *new_reloc = *new_relocp;
2208 if (new_relocp == ss->new_relocs.data + ss->new_relocs.size ||
2209 reloc->address != new_reloc->address)
2210 *vec_grow(&ss->relocs, 1) = reloc;
2214 void write_section(bfd *obfd, asection *osection, void *arg)
2216 struct supersect *ss = osection->userdata;
2218 if ((ss->flags & SEC_GROUP) != 0 || ss->contents.size == 0)
2219 return;
2221 delete_obsolete_relocs(ss);
2223 arelent **relocp;
2224 char *error_message;
2225 for (relocp = ss->new_relocs.data;
2226 relocp < ss->new_relocs.data + ss->new_relocs.size; relocp++) {
2227 bfd_vma val;
2228 if (bfd_get_arch(obfd) == bfd_arch_arm)
2229 val = osection->use_rela_p ? 0 : (*relocp)->addend;
2230 else
2231 val = 0;
2232 bfd_put(bfd_get_reloc_size((*relocp)->howto) * 8, obfd, val,
2233 ss->contents.data + (*relocp)->address);
2234 if (bfd_install_relocation(obfd, *relocp, ss->contents.data,
2235 0, osection, &error_message) !=
2236 bfd_reloc_ok) {
2237 err(ss->parent, "ksplice: error installing reloc: %s",
2238 error_message);
2239 DIE;
2241 if (mode("finalize")) {
2242 /* Check that all our sections will be allocated */
2243 asymbol *sym = *((*relocp)->sym_ptr_ptr);
2244 if (!bfd_is_const_section(sym->section)) {
2245 struct supersect *sym_ss =
2246 fetch_supersect(ss->parent, sym->section);
2247 assert((sym_ss->flags & SEC_ALLOC) != 0);
2251 memcpy(vec_grow(&ss->relocs, ss->new_relocs.size), ss->new_relocs.data,
2252 ss->new_relocs.size * sizeof(*ss->new_relocs.data));
2254 bfd_set_reloc(obfd, osection,
2255 ss->relocs.size == 0 ? NULL : ss->relocs.data,
2256 ss->relocs.size);
2258 if (ss->flags & SEC_HAS_CONTENTS)
2259 assert(bfd_set_section_contents
2260 (obfd, osection, ss->contents.data, 0,
2261 ss->contents.size));
2264 /* Modified function from GNU Binutils objcopy.c
2266 * Mark all the symbols which will be used in output relocations with
2267 * the BSF_KEEP flag so that those symbols will not be stripped.
2269 * Ignore relocations which will not appear in the output file.
2271 void mark_symbols_used_in_relocations(bfd *abfd, asection *isection,
2272 void *ignored)
2274 struct superbfd *sbfd = fetch_superbfd(abfd);
2275 if (isection->output_section == NULL)
2276 return;
2278 struct supersect *ss = fetch_supersect(sbfd, isection);
2279 ss_mark_symbols_used_in_relocations(ss);
2282 void ss_mark_symbols_used_in_relocations(struct supersect *ss)
2284 /* Examine each symbol used in a relocation. If it's not one of the
2285 special bfd section symbols, then mark it with BSF_KEEP. */
2286 arelent **relocp;
2287 for (relocp = ss->relocs.data;
2288 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
2289 asymbol *sym = *(*relocp)->sym_ptr_ptr;
2290 if (!(bfd_is_const_section(sym->section) &&
2291 sym == sym->section->symbol))
2292 sym->flags |= BSF_KEEP;
2294 for (relocp = ss->new_relocs.data;
2295 relocp < ss->new_relocs.data + ss->new_relocs.size; relocp++) {
2296 asymbol *sym = *(*relocp)->sym_ptr_ptr;
2297 if (!(bfd_is_const_section(sym->section) &&
2298 sym == sym->section->symbol))
2299 sym->flags |= BSF_KEEP;
2303 static bool deleted_table_section_symbol(bfd *abfd, asymbol *sym)
2305 struct superbfd *sbfd = fetch_superbfd(abfd);
2306 if (bfd_is_const_section(sym->section))
2307 return false;
2308 struct supersect *ss = fetch_supersect(sbfd, sym->section);
2310 asymbol **symp;
2311 for (symp = ss->syms.data; symp < ss->syms.data + ss->syms.size; symp++) {
2312 if (sym == *symp)
2313 break;
2315 return symp >= ss->syms.data + ss->syms.size &&
2316 (sym->flags & BSF_SECTION_SYM) == 0;
2319 void filter_symbols(bfd *ibfd, bfd *obfd, struct asymbolp_vec *osyms,
2320 struct asymbolp_vec *isyms)
2322 asymbol **symp;
2323 struct superbfd *sbfd = fetch_superbfd(ibfd);
2324 for (symp = isyms->data; symp < isyms->data + isyms->size; symp++) {
2325 asymbol *sym = *symp;
2326 struct supersect *sym_ss = NULL;
2327 struct span *sym_span = NULL;
2328 if (!bfd_is_const_section(sym->section)) {
2329 sym_ss = fetch_supersect(sbfd, sym->section);
2330 sym_span = find_span(sym_ss, sym->value);
2333 if (mode("keep") && (sym->flags & BSF_GLOBAL) != 0 &&
2334 !(mode("keep-new-code") && sym_span != NULL &&
2335 sym_span->new))
2336 sym->flags = (sym->flags & ~BSF_GLOBAL) | BSF_LOCAL;
2338 if (mode("finalize") && (sym->flags & BSF_GLOBAL) != 0)
2339 sym->flags = (sym->flags & ~BSF_GLOBAL) | BSF_LOCAL;
2341 bool keep = bfd_is_const_section(sym->section) ||
2342 (sym_ss->keep && (sym->flags & BSF_SECTION_SYM) != 0) ||
2343 (sym_span != NULL && sym_span->keep);
2344 if (bfd_is_und_section(sym->section) &&
2345 (sym->flags & BSF_KEEP) == 0)
2346 keep = false;
2347 if (bfd_is_abs_section(sym->section) &&
2348 (sym->flags & BSF_KEEP) == 0 &&
2349 (sym->flags & BSF_FILE) == 0)
2350 keep = false;
2351 if (deleted_table_section_symbol(ibfd, sym))
2352 keep = false;
2354 if (mode("keep-old-code") && sym_ss != NULL &&
2355 sym_ss->type == SS_TYPE_EXPORT)
2356 keep = false;
2358 if (keep) {
2359 if (sym_ss != NULL && !sym_ss->keep) {
2360 err(sbfd, "Kept symbol %s in unkept section "
2361 "%s\n", sym->name, sym->section->name);
2362 DIE;
2364 *vec_grow(osyms, 1) = sym;
2369 void read_str_set(struct str_vec *strs)
2371 char *buf = NULL;
2372 size_t n = 0;
2373 assert(getline(&buf, &n, stdin) >= 0);
2374 vec_init(strs);
2375 char *saveptr;
2376 while (1) {
2377 char *str = strtok_r(buf, " \n", &saveptr);
2378 buf = NULL;
2379 if (str == NULL)
2380 break;
2381 *vec_grow(strs, 1) = str;
2385 bool str_in_set(const char *str, const struct str_vec *strs)
2387 const char **strp;
2388 for (strp = strs->data; strp < strs->data + strs->size; strp++) {
2389 if (strcmp(str, *strp) == 0)
2390 return true;
2392 return false;
2395 static bool is_table_section(const char *name, bool consider_other,
2396 bool consider_crc)
2398 struct supersect *tables_ss =
2399 fetch_supersect(offsets_sbfd,
2400 bfd_get_section_by_name(offsets_sbfd->abfd,
2401 ".ksplice_table_sections"));
2402 const struct table_section *ts;
2403 for (ts = tables_ss->contents.data;
2404 (void *)ts < tables_ss->contents.data + tables_ss->contents.size;
2405 ts++) {
2406 if (strcmp(name, read_string(tables_ss, &ts->sect)) == 0)
2407 return true;
2408 const char *osect_name = read_string(tables_ss,
2409 &ts->other_sect);
2410 if (consider_other && osect_name != NULL &&
2411 strcmp(name, osect_name) == 0)
2412 return true;
2413 const char *crc_name = read_string(tables_ss, &ts->crc_sect);
2414 if (consider_crc && crc_name != NULL &&
2415 strcmp(name, crc_name) == 0)
2416 return true;
2418 return false;
2421 const struct table_section *get_table_section(const char *name)
2423 struct supersect *tables_ss =
2424 fetch_supersect(offsets_sbfd,
2425 bfd_get_section_by_name(offsets_sbfd->abfd,
2426 ".ksplice_table_sections"));
2427 const struct table_section *ts;
2428 for (ts = tables_ss->contents.data;
2429 (void *)ts < tables_ss->contents.data + tables_ss->contents.size;
2430 ts++) {
2431 if (strcmp(name, read_string(tables_ss, &ts->sect)) == 0) {
2432 if (ts->entry_contents_size != 0)
2433 assert(align(ts->entry_contents_size,
2434 ts->entry_align) ==
2435 ts->entry_size);
2436 struct table_section *ns = malloc(sizeof(*ns));
2437 *ns = *ts;
2438 ns->sect = read_string(tables_ss, &ts->sect);
2439 ns->crc_sect = read_string(tables_ss, &ts->crc_sect);
2440 ns->other_sect =
2441 read_string(tables_ss, &ts->other_sect);
2442 return ns;
2445 return NULL;
2448 enum supersect_type supersect_type(struct supersect *ss)
2450 if (mode("finalize") &&
2451 strcmp(finalize_target, "vmlinux") == 0 &&
2452 (strstarts(ss->name, ".ksplice_relocs.exit") ||
2453 strstarts(ss->name, ".ksplice_sections.exit") ||
2454 strstarts(ss->name, ".ksplice_patches.exit")))
2455 return SS_TYPE_EXIT;
2456 if (strstarts(ss->name, ".ksplice_call"))
2457 return SS_TYPE_KSPLICE_CALL;
2458 if (strstarts(ss->name, ".ksplice_options"))
2459 return SS_TYPE_SPECIAL;
2460 if (strstarts(ss->name, ".ksplice"))
2461 return SS_TYPE_KSPLICE;
2463 if (strstarts(ss->name, ".init"))
2464 return SS_TYPE_IGNORED;
2465 if (strstarts(ss->name, ".security_initcall.init"))
2466 return SS_TYPE_IGNORED;
2467 if (strstarts(ss->name, ".con_initcall.init"))
2468 return SS_TYPE_IGNORED;
2469 if (strstarts(ss->name, ".x86cpuvendor.init"))
2470 return SS_TYPE_IGNORED;
2471 if (strstarts(ss->name, ".early_param.init"))
2472 return SS_TYPE_IGNORED;
2473 if (strstarts(ss->name, ".taglist.init"))
2474 return SS_TYPE_IGNORED;
2475 if (strstarts(ss->name, ".arch.info.init"))
2476 return SS_TYPE_IGNORED;
2477 if (strstarts(ss->name, ".proc.info.init"))
2478 return SS_TYPE_IGNORED;
2479 /* .pci_fixup_* sections really should be treated as global rodata
2480 referenced only from quirks.c */
2481 if (strstarts(ss->name, ".pci_fixup_"))
2482 return SS_TYPE_IGNORED;
2483 /* .builtin_fw sections are similar to .pci_fixup */
2484 if (strstarts(ss->name, ".builtin_fw"))
2485 return SS_TYPE_IGNORED;
2486 /* same for .tracedata */
2487 if (strstarts(ss->name, ".tracedata"))
2488 return SS_TYPE_IGNORED;
2489 if (strstarts(ss->name, ".debug"))
2490 return SS_TYPE_IGNORED;
2491 /* .eh_frame should probably be discarded, not ignored */
2492 if (strstarts(ss->name, ".eh_frame"))
2493 return SS_TYPE_IGNORED;
2494 if (config->ignore_devinit && strstarts(ss->name, ".devinit"))
2495 return SS_TYPE_IGNORED;
2496 if (config->ignore_meminit && strstarts(ss->name, ".meminit"))
2497 return SS_TYPE_IGNORED;
2498 if (config->ignore_cpuinit && strstarts(ss->name, ".cpuinit"))
2499 return SS_TYPE_IGNORED;
2500 if (config->ignore_devinit && strstarts(ss->name, ".devexit"))
2501 return SS_TYPE_IGNORED;
2502 if (config->ignore_meminit && strstarts(ss->name, ".memexit"))
2503 return SS_TYPE_IGNORED;
2504 if (config->ignore_cpuinit && strstarts(ss->name, ".cpuexit"))
2505 return SS_TYPE_IGNORED;
2506 if (strstarts(ss->name, ".vgetcpu_mode") ||
2507 strstarts(ss->name, ".jiffies") ||
2508 strstarts(ss->name, ".wall_jiffies") ||
2509 strstarts(ss->name, ".vxtime") ||
2510 strstarts(ss->name, ".sys_tz") ||
2511 strstarts(ss->name, ".sysctl_vsyscall") ||
2512 strstarts(ss->name, ".xtime") ||
2513 strstarts(ss->name, ".xtime_lock") ||
2514 strstarts(ss->name, ".vsyscall"))
2515 return SS_TYPE_IGNORED;
2516 if (strstarts(ss->name, ".vdso"))
2517 return SS_TYPE_IGNORED;
2519 if (strstarts(ss->name, ".exit.text"))
2520 return SS_TYPE_TEXT;
2521 if (strstarts(ss->name, ".exit.data"))
2522 return SS_TYPE_DATA;
2524 if (strstarts(ss->name, ".text") ||
2525 strstarts(ss->name, ".kernel.text") ||
2526 strstarts(ss->name, ".devinit.text") ||
2527 strstarts(ss->name, ".meminit.text") ||
2528 strstarts(ss->name, ".cpuinit.text") ||
2529 strstarts(ss->name, ".devexit.text") ||
2530 strstarts(ss->name, ".memexit.text") ||
2531 strstarts(ss->name, ".cpuexit.text") ||
2532 strstarts(ss->name, ".ref.text") ||
2533 strstarts(ss->name, ".spinlock.text") ||
2534 strstarts(ss->name, ".kprobes.text") ||
2535 strstarts(ss->name, ".sched.text") ||
2536 strstarts(ss->name, ".entry.text") || /* OpenVZ */
2537 (mode("keep-old-code") && strstarts(ss->name, ".fixup")))
2538 return SS_TYPE_TEXT;
2540 int n = -1;
2541 if (sscanf(ss->name, ".rodata.str%*u.%*u%n", &n) >= 0 &&
2542 n == strlen(ss->name))
2543 return ss->entsize == 1 ? SS_TYPE_STRING : SS_TYPE_RODATA;
2545 if (strstarts(ss->name, ".rodata") ||
2546 strstarts(ss->name, ".kernel.rodata") ||
2547 strstarts(ss->name, ".devinit.rodata") ||
2548 strstarts(ss->name, ".meminit.rodata") ||
2549 strstarts(ss->name, ".cpuinit.rodata") ||
2550 strstarts(ss->name, ".devexit.rodata") ||
2551 strstarts(ss->name, ".memexit.rodata") ||
2552 strstarts(ss->name, ".cpuexit.rodata") ||
2553 strstarts(ss->name, ".ref.rodata") ||
2554 strstarts(ss->name, "__markers_strings") ||
2555 strstarts(ss->name, "__bug_table") ||
2556 (mode("keep-old-code") && strstarts(ss->name, "__ex_table")))
2557 return SS_TYPE_RODATA;
2559 if (strstarts(ss->name, ".bss"))
2560 return SS_TYPE_DATA;
2562 /* Ignore .data.percpu sections */
2563 if (strstarts(ss->name, ".data.percpu") ||
2564 strstarts(ss->name, ".kernel.data.percpu") ||
2565 strstarts(ss->name, ".data..percpu"))
2566 return SS_TYPE_IGNORED;
2567 if (strstarts(ss->name, ".data") ||
2568 strstarts(ss->name, ".kernel.data") ||
2569 strstarts(ss->name, ".devinit.data") ||
2570 strstarts(ss->name, ".cpuinit.data") ||
2571 strstarts(ss->name, ".meminit.data") ||
2572 strstarts(ss->name, ".devexit.data") ||
2573 strstarts(ss->name, ".memexit.data") ||
2574 strstarts(ss->name, ".cpuexit.data") ||
2575 strstarts(ss->name, ".ref.data") ||
2576 strstarts(ss->name, "__markers"))
2577 return SS_TYPE_DATA;
2579 /* We replace all the ksymtab strings, so delete them */
2580 if (strcmp(ss->name, "__ksymtab_strings") == 0)
2581 return SS_TYPE_STRING;
2582 if (strstarts(ss->name, "__ksymtab"))
2583 return SS_TYPE_EXPORT;
2585 if (is_table_section(ss->name, true, true))
2586 return SS_TYPE_SPECIAL;
2588 if (strstarts(ss->name, ".ARM."))
2589 return SS_TYPE_SPECIAL;
2591 if (strstarts(ss->name, ".note"))
2592 return SS_TYPE_IGNORED;
2593 if (strstarts(ss->name, ".comment"))
2594 return SS_TYPE_IGNORED;
2595 if (strstarts(ss->name, "__param"))
2596 return SS_TYPE_IGNORED;
2597 if (strstarts(ss->name, ".exitcall.exit"))
2598 return SS_TYPE_IGNORED;
2599 if (strstarts(ss->name, ".modinfo"))
2600 return SS_TYPE_IGNORED;
2602 return SS_TYPE_UNKNOWN;
2605 void initialize_supersect_types(struct superbfd *sbfd)
2607 asection *sect;
2608 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2609 struct supersect *ss = fetch_supersect(sbfd, sect);
2610 ss->type = supersect_type(ss);
2611 ss->orig_type = ss->type;
2612 if (ss->type == SS_TYPE_UNKNOWN) {
2613 err(sbfd, "Unknown section type: %s\n", ss->name);
2614 DIE;
2619 static void init_label_map(struct superbfd *sbfd)
2621 struct label_map *map;
2623 vec_init(&sbfd->maps);
2624 init_csyms(sbfd);
2625 init_callers(sbfd);
2627 struct symbol_hash csyms;
2628 symbol_hash_init(&csyms);
2630 asymbol **symp;
2631 for (symp = sbfd->syms.data;
2632 symp < sbfd->syms.data + sbfd->syms.size; symp++) {
2633 asymbol *csym = canonical_symbol(sbfd, *symp);
2634 if (csym == NULL)
2635 continue;
2636 char *key = strprintf("%p", csym);
2637 asymbol **csymp = symbol_hash_lookup(&csyms, key, TRUE);
2638 free(key);
2639 if (*csymp != NULL)
2640 continue;
2641 *csymp = csym;
2643 map = vec_grow(&sbfd->maps, 1);
2644 map->csym = csym;
2645 map->count = 0;
2646 map->label = symbol_label(sbfd, csym);
2649 struct label_mapp_hash label_maps;
2650 label_mapp_hash_init(&label_maps);
2651 for (map = sbfd->maps.data;
2652 map < sbfd->maps.data + sbfd->maps.size; map++) {
2653 struct label_map **mapp =
2654 label_mapp_hash_lookup(&label_maps, map->label, TRUE);
2655 if (*mapp == NULL) {
2656 *mapp = map;
2657 continue;
2660 struct label_map *first_map = *mapp;
2661 if (first_map->count == 0)
2662 first_map->label = strprintf("%s~%d", map->label, 0);
2663 map->label = strprintf("%s~%d", map->label, ++first_map->count);
2666 label_mapp_hash_init(&sbfd->maps_hash);
2667 for (map = sbfd->maps.data;
2668 map < sbfd->maps.data + sbfd->maps.size; map++) {
2669 char *key = strprintf("%p", map->csym);
2670 struct label_map **mapp =
2671 label_mapp_hash_lookup(&sbfd->maps_hash, key, TRUE);
2672 free(key);
2673 *mapp = map;
2674 map->orig_label = map->label;
2678 static const char *label_lookup(struct superbfd *sbfd, asymbol *sym)
2680 asymbol *csym = canonical_symbol(sbfd, sym);
2681 char *key = strprintf("%p", csym);
2682 struct label_map **mapp =
2683 label_mapp_hash_lookup(&sbfd->maps_hash, key, FALSE);
2684 free(key);
2685 if (mapp == NULL)
2686 DIE;
2687 return (*mapp)->label;
2690 static void print_label_changes(struct superbfd *sbfd)
2692 asection *sect;
2693 struct span *span;
2694 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2695 struct supersect *ss = fetch_supersect(sbfd, sect);
2696 for (span = ss->spans.data;
2697 span < ss->spans.data + ss->spans.size; span++) {
2698 if (strcmp(span->label, span->orig_label) != 0)
2699 debug1(sbfd, "Label change: %s -> %s\n",
2700 span->label, span->orig_label);
2705 static void label_map_set(struct superbfd *sbfd, const char *oldlabel,
2706 const char *label)
2708 struct label_map *map;
2709 for (map = sbfd->maps.data;
2710 map < sbfd->maps.data + sbfd->maps.size; map++) {
2711 if (strcmp(map->orig_label, oldlabel) == 0) {
2712 if (strcmp(map->orig_label, map->label) != 0 &&
2713 strcmp(map->label, label) != 0)
2714 DIE;
2715 map->label = label;
2716 return;
2719 DIE;
2722 static void change_initial_label(struct span *span, const char *label)
2724 struct superbfd *sbfd = span->ss->parent;
2725 span->label = label;
2726 span->orig_label = label;
2727 if (span->symbol) {
2728 asymbol *csym = canonical_symbol(sbfd, span->symbol);
2729 char *key = strprintf("%p", csym);
2730 struct label_map **mapp =
2731 label_mapp_hash_lookup(&sbfd->maps_hash, key, FALSE);
2732 free(key);
2733 assert(mapp);
2734 (*mapp)->label = span->label;
2735 (*mapp)->orig_label = span->orig_label;
2736 span->symbol = NULL;
2740 static void init_callers(struct superbfd *sbfd)
2742 string_hash_init(&sbfd->callers);
2743 asection *sect;
2744 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2745 struct supersect *ss = fetch_supersect(sbfd, sect);
2746 arelent **relocp;
2747 for (relocp = ss->relocs.data;
2748 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
2749 asymbol *sym = *(*relocp)->sym_ptr_ptr;
2750 unsigned long val =
2751 sym->value + reloc_target_offset(ss, *relocp);
2752 char *key = strprintf("%s+%lx", sym->section->name,
2753 val);
2754 const char **ret = string_hash_lookup(&sbfd->callers,
2755 key, TRUE);
2756 free(key);
2757 asymbol *csym = canonical_symbol(sbfd, sect->symbol);
2758 if (*ret != NULL)
2759 *ret = "*multiple_callers*";
2760 else if (static_local_symbol(sbfd, csym))
2761 *ret = static_local_symbol(sbfd, csym);
2762 else
2763 *ret = sect->name;
2768 static const char *find_caller(struct supersect *ss, asymbol *sym)
2770 char *key = strprintf("%s+%lx", sym->section->name,
2771 (unsigned long)sym->value);
2772 const char **ret = string_hash_lookup(&ss->parent->callers, key, FALSE);
2773 free(key);
2775 if (ret == NULL)
2776 return "*no_caller*";
2777 return *ret;
2780 static void init_csyms(struct superbfd *sbfd)
2782 asymbolpp_hash_init(&sbfd->csyms);
2784 asymbol **symp;
2785 for (symp = sbfd->syms.data; symp < sbfd->syms.data + sbfd->syms.size;
2786 symp++) {
2787 asymbol *sym = *symp;
2788 if ((sym->flags & BSF_DEBUGGING) != 0)
2789 continue;
2790 char *key = strprintf("%s+%lx", sym->section->name,
2791 (unsigned long)sym->value);
2792 asymbol ***csympp = asymbolpp_hash_lookup(&sbfd->csyms, key,
2793 TRUE);
2794 free(key);
2795 if (*csympp == NULL) {
2796 *csympp = symp;
2797 continue;
2799 asymbol *csym = **csympp;
2800 if ((csym->flags & BSF_GLOBAL) != 0)
2801 continue;
2802 if ((sym->flags & BSF_GLOBAL) != 0)
2803 *csympp = symp;
2807 static asymbol **symbolp_scan(struct supersect *ss, bfd_vma value)
2809 char *key = strprintf("%s+%lx", ss->name, (unsigned long)value);
2810 asymbol ***csympp =
2811 asymbolpp_hash_lookup(&ss->parent->csyms, key, FALSE);
2812 free(key);
2813 if (csympp != NULL)
2814 return *csympp;
2816 /* For section symbols of sections containing no symbols, return the
2817 section symbol that relocations are generated against */
2818 if (value == 0)
2819 return &ss->symbol;
2820 return NULL;
2823 static asymbol **canonical_symbolp(struct superbfd *sbfd, asymbol *sym)
2825 if (bfd_is_const_section(sym->section)) {
2826 asymbol **csymp;
2827 for (csymp = sbfd->syms.data;
2828 csymp < sbfd->syms.data + sbfd->syms.size; csymp++) {
2829 if (sym == *csymp)
2830 return csymp;
2832 return NULL;
2834 return symbolp_scan(fetch_supersect(sbfd, sym->section), sym->value);
2837 static asymbol *canonical_symbol(struct superbfd *sbfd, asymbol *sym)
2839 if (bfd_is_const_section(sym->section))
2840 return sym;
2841 asymbol **symp = canonical_symbolp(sbfd, sym);
2842 return symp != NULL ? *symp : NULL;
2845 static char *static_local_symbol(struct superbfd *sbfd, asymbol *sym)
2847 struct supersect *ss = fetch_supersect(sbfd, sym->section);
2848 if ((sym->flags & BSF_LOCAL) == 0 || (sym->flags & BSF_OBJECT) == 0)
2849 return NULL;
2850 char *dot = strrchr(sym->name, '.');
2851 if (dot == NULL || dot[1 + strspn(dot + 1, "0123546789")] != '\0')
2852 return NULL;
2853 char *basename = strndup(sym->name, dot - sym->name);
2855 /* Handle C.123.12345 symbols */
2856 dot = strrchr(basename, '.');
2857 if (dot != NULL && dot[1 + strspn(dot + 1, "0123546789")] == '\0')
2858 basename = strndup(basename, dot - basename);
2859 const char *caller;
2860 if (strcmp(basename, "__func__") == 0 ||
2861 strcmp(basename, "__PRETTY_FUNCTION__") == 0)
2862 caller = (const char *)ss->contents.data + sym->value;
2863 else
2864 caller = find_caller(ss, sym);
2865 return strprintf("%s<%s>", basename, caller);
2868 static char *symbol_label(struct superbfd *sbfd, asymbol *sym)
2870 const char *filename = sbfd->abfd->filename;
2871 char *c = strstr(filename, ".KSPLICE");
2872 int flen = (c == NULL ? strlen(filename) : c - filename);
2874 char *label;
2875 if (bfd_is_und_section(sym->section) || (sym->flags & BSF_GLOBAL) != 0) {
2876 label = strdup(sym->name);
2877 } else if (bfd_is_const_section(sym->section)) {
2878 label = strprintf("%s<%.*s>", sym->name, flen, filename);
2879 } else {
2880 asymbol *gsym = canonical_symbol(sbfd, sym);
2882 if (gsym == NULL)
2883 label = strprintf("%s+%lx<%.*s>",
2884 sym->section->name,
2885 (unsigned long)sym->value,
2886 flen, filename);
2887 else if ((gsym->flags & BSF_GLOBAL) != 0)
2888 label = strdup(gsym->name);
2889 else if (static_local_symbol(sbfd, gsym))
2890 label = strprintf("%s+%lx<%.*s>",
2891 static_local_symbol(sbfd, gsym),
2892 (unsigned long)sym->value,
2893 flen, filename);
2894 else
2895 label = strprintf("%s<%.*s>",
2896 gsym->name, flen, filename);
2899 return label;
2902 static void keep_span(struct span *span)
2904 span->keep = true;
2905 span->ss->keep = true;
2908 static struct span *new_span(struct supersect *ss, bfd_vma start, bfd_vma size)
2910 struct span *span = vec_grow(&ss->spans, 1);
2911 span->size = size;
2912 span->contents_size = size;
2913 span->start = start;
2914 span->ss = ss;
2915 span->keep = true;
2916 span->new = false;
2917 span->patch = false;
2918 span->bugpatch = false;
2919 span->datapatch = false;
2920 span->precallable = strstarts(ss->name, ".ksplice_call_pre_apply") ||
2921 strstarts(ss->name, ".ksplice_call_check_apply") ||
2922 strstarts(ss->name, ".ksplice_call_fail_apply") ||
2923 strstarts(ss->name, ".ksplice_call_post_remove");
2924 span->match = NULL;
2925 span->shift = 0;
2926 asymbol **symp = symbolp_scan(ss, span->start);
2927 if (symp != NULL) {
2928 span->symbol = *symp;
2929 span->label = label_lookup(ss->parent, span->symbol);
2930 } else {
2931 span->symbol = NULL;
2932 const char *label = label_lookup(ss->parent, ss->symbol);
2933 if (span->start != 0)
2934 span->label = strprintf("%s<span:%lx>", label,
2935 (unsigned long)span->start);
2936 else
2937 span->label = label;
2939 span->orig_label = span->label;
2940 return span;
2943 static void initialize_string_spans(struct supersect *ss)
2945 const char *str;
2946 for (str = ss->contents.data;
2947 (void *)str < ss->contents.data + ss->contents.size;) {
2948 bfd_vma start = (unsigned long)str -
2949 (unsigned long)ss->contents.data;
2950 bfd_vma size = strlen(str) + 1;
2951 bfd_vma contents_size = size;
2952 while ((start + size) % (1 << ss->alignment) != 0 &&
2953 start + size < ss->contents.size) {
2954 /* Some string sections, like __ksymtab_strings, only
2955 align some strings with the declared alignment */
2956 if (str[size] != '\0')
2957 break;
2958 size++;
2960 struct span *span = new_span(ss, start, size);
2961 span->contents_size = contents_size;
2962 str += size;
2966 static int compare_ulongs(const void *va, const void *vb)
2968 const unsigned long *a = va, *b = vb;
2969 return *a - *b;
2972 static void initialize_table_spans(struct superbfd *sbfd,
2973 struct table_section *s)
2975 asection *isection = bfd_get_section_by_name(sbfd->abfd, s->sect);
2976 if (isection == NULL)
2977 return;
2978 struct supersect *ss = fetch_supersect(sbfd, isection);
2979 if (ss->alignment < ffs(s->entry_align) - 1)
2980 ss->alignment = ffs(s->entry_align) - 1;
2982 asection *other_sect = NULL;
2983 if (s->other_sect != NULL)
2984 other_sect = bfd_get_section_by_name(sbfd->abfd, s->other_sect);
2985 struct supersect *other_ss = NULL;
2986 if (other_sect != NULL)
2987 other_ss = fetch_supersect(sbfd, other_sect);
2989 asection *crc_sect = NULL;
2990 if (s->crc_sect != NULL)
2991 crc_sect = bfd_get_section_by_name(sbfd->abfd, s->crc_sect);
2992 struct supersect *crc_ss = NULL;
2993 if (crc_sect != NULL)
2994 crc_ss = fetch_supersect(sbfd, crc_sect);
2996 struct ulong_vec offsets;
2997 vec_init(&offsets);
2999 void *entry;
3000 for (entry = ss->contents.data;
3001 entry < ss->contents.data + ss->contents.size;
3002 entry += s->entry_size) {
3003 struct span *span = new_span(ss, addr_offset(ss, entry),
3004 s->entry_size);
3005 if (s->entry_contents_size != 0)
3006 span->contents_size = s->entry_contents_size;
3007 if ((span->symbol == NULL ||
3008 (span->symbol->flags & BSF_SECTION_SYM) != 0) &&
3009 s->has_addr) {
3010 arelent *reloc = find_reloc(ss, entry + s->addr_offset);
3011 assert(reloc);
3012 struct span *target_span = reloc_target_span(ss, reloc);
3013 assert(target_span);
3014 asymbol *sym = *reloc->sym_ptr_ptr;
3015 unsigned long val = sym->value +
3016 reloc_target_offset(ss, reloc) -
3017 (target_span->start + target_span->shift);
3018 char *label = strprintf("%s<target:%s+%lx>", ss->name,
3019 target_span->label, val);
3020 change_initial_label(span, label);
3023 if (other_sect != NULL) {
3024 asymbol *sym;
3025 bfd_vma offset = read_reloc(ss, entry + s->other_offset,
3026 sizeof(void *), &sym);
3027 if (sym->section == other_sect) {
3028 assert(offset >= 0 &&
3029 offset < other_ss->contents.size);
3030 *vec_grow(&offsets, 1) = offset;
3034 if (crc_sect != NULL)
3035 new_span(crc_ss, addr_offset(ss, entry) / s->entry_size
3036 * s->crc_size, s->crc_size);
3038 if (ss->type == SS_TYPE_EXPORT) {
3039 const char *symname = read_string(ss, entry +
3040 s->other_offset);
3041 char *label = strprintf("%s:%s", ss->name, symname);
3042 change_initial_label(span, label);
3046 if (other_sect == NULL)
3047 return;
3049 *vec_grow(&offsets, 1) = 0;
3050 qsort(offsets.data, offsets.size, sizeof(*offsets.data),
3051 compare_ulongs);
3052 *vec_grow(&offsets, 1) = other_ss->contents.size;
3054 unsigned long *off;
3055 for (off = offsets.data; off < offsets.data + offsets.size - 1; off++) {
3056 if (*off != *(off + 1))
3057 new_span(other_ss, *off, *(off + 1) - *off);
3061 static void initialize_table_section_spans(struct superbfd *sbfd)
3063 struct supersect *tables_ss =
3064 fetch_supersect(offsets_sbfd,
3065 bfd_get_section_by_name(offsets_sbfd->abfd,
3066 ".ksplice_table_sections"));
3067 const struct table_section *ts;
3068 struct table_section s;
3069 for (ts = tables_ss->contents.data;
3070 (void *)ts < tables_ss->contents.data + tables_ss->contents.size;
3071 ts++) {
3072 s = *ts;
3073 s.sect = read_string(tables_ss, &ts->sect);
3074 s.other_sect = read_string(tables_ss, &ts->other_sect);
3075 s.crc_sect = read_string(tables_ss, &ts->crc_sect);
3076 initialize_table_spans(sbfd, &s);
3080 static void initialize_ksplice_call_spans(struct supersect *ss)
3082 arelent **relocp;
3083 for (relocp = ss->relocs.data;
3084 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
3085 arelent *reloc = *relocp;
3086 new_span(ss, reloc->address, bfd_get_reloc_size(reloc->howto));
3087 /* the span labels should already be unique */
3091 static void initialize_spans(struct superbfd *sbfd)
3093 asection *sect;
3094 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
3095 if (is_table_section(sect->name, true, true) && mode("keep"))
3096 continue;
3098 struct supersect *ss = fetch_supersect(sbfd, sect);
3099 if (ss->type == SS_TYPE_STRING)
3100 initialize_string_spans(ss);
3101 else if (ss->type == SS_TYPE_KSPLICE_CALL)
3102 initialize_ksplice_call_spans(ss);
3103 else
3104 new_span(ss, 0, ss->contents.size);
3106 if (mode("keep"))
3107 initialize_table_section_spans(sbfd);
3110 /* Returns the span pointed to by the relocation at span->start + offset */
3111 static struct span *span_offset_target_span(struct span *span, int offset)
3113 void *entry = span->ss->contents.data + span->start;
3114 arelent *reloc = find_reloc(span->ss, entry + offset);
3115 if (reloc == NULL)
3116 return NULL;
3117 return reloc_target_span(span->ss, reloc);
3120 struct span *reloc_target_span(struct supersect *ss, arelent *reloc)
3122 asymbol *sym_ptr = *reloc->sym_ptr_ptr;
3123 if (bfd_is_const_section(sym_ptr->section))
3124 return NULL;
3126 bfd_vma addend = sym_ptr->value + reloc_target_offset(ss, reloc);
3127 struct supersect *sym_ss =
3128 fetch_supersect(ss->parent, sym_ptr->section);
3129 struct span *span, *target_span = sym_ss->spans.data;
3130 for (span = sym_ss->spans.data;
3131 span < sym_ss->spans.data + sym_ss->spans.size; span++) {
3132 if (addend >= span->start && addend < span->start + span->size)
3133 target_span = span;
3135 return target_span;
3138 static bfd_vma reloc_target_offset(struct supersect *ss, arelent *reloc)
3140 bfd_vma offset = reloc_offset(ss, reloc);
3141 if (reloc->howto->pc_relative) {
3142 if ((ss->flags & SEC_CODE) != 0)
3143 return offset + bfd_get_reloc_size(reloc->howto);
3145 const struct table_section *ts = get_table_section(ss->name);
3146 if (ts != NULL && ts->relative_addr &&
3147 reloc->address % ts->entry_size == ts->addr_offset)
3148 return offset - ts->addr_offset;
3149 if (ts != NULL && ts->relative_other &&
3150 reloc->address % ts->entry_size == ts->other_offset)
3151 return offset - ts->other_offset;
3153 DIE;
3155 return offset;
3158 struct span *find_span(struct supersect *ss, bfd_size_type address)
3160 struct span *span;
3161 for (span = ss->spans.data; span < ss->spans.data + ss->spans.size;
3162 span++) {
3163 if (address >= span->start &&
3164 address < span->start + span->size)
3165 return span;
3167 /* Deal with empty BSS sections */
3168 if (ss->contents.size == 0 && ss->spans.size > 0)
3169 return ss->spans.data;
3170 /* Deal with section end pointers */
3171 if (address == ss->contents.size && ss->spans.size == 1)
3172 return ss->spans.data;
3173 return NULL;
3176 void compute_span_shifts(struct superbfd *sbfd)
3178 asection *sect;
3179 struct span *span;
3180 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
3181 struct supersect *ss = fetch_supersect(sbfd, sect);
3182 if (!ss->keep)
3183 continue;
3184 bfd_size_type offset = 0;
3185 for (span = ss->spans.data;
3186 span < ss->spans.data + ss->spans.size; span++) {
3187 if (!span->keep)
3188 continue;
3189 span->shift = offset - span->start;
3190 offset += span->size;
3195 void remove_unkept_spans(struct superbfd *sbfd)
3197 asection *sect;
3198 struct span *span;
3199 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
3200 struct supersect *ss = fetch_supersect(sbfd, sect);
3201 delete_obsolete_relocs(ss);
3202 struct arelentp_vec orig_relocs;
3203 vec_move(&orig_relocs, &ss->relocs);
3204 arelent **relocp, *reloc;
3205 for (relocp = orig_relocs.data;
3206 relocp < orig_relocs.data + orig_relocs.size; relocp++) {
3207 reloc = *relocp;
3208 asymbol *sym = *reloc->sym_ptr_ptr;
3209 span = reloc_target_span(ss, reloc);
3210 if ((span != NULL && span->keep && span->shift == 0) ||
3211 bfd_is_const_section(sym->section)) {
3212 *vec_grow(&ss->relocs, 1) = reloc;
3213 continue;
3215 struct supersect *sym_ss =
3216 fetch_supersect(sbfd, sym->section);
3217 if (span != NULL && (sym->flags & BSF_SECTION_SYM) == 0
3218 && find_span(sym_ss, sym->value) != span) {
3219 err(sbfd, "Spans for symbol %s and relocation "
3220 "target do not match in sect %s\n",
3221 sym->name, sym_ss->name);
3222 DIE;
3224 if (span != NULL && span->keep) {
3225 arelent *new_reloc = malloc(sizeof(*new_reloc));
3226 *new_reloc = *reloc;
3227 new_reloc->addend = reloc_offset(ss, reloc);
3228 new_reloc->addend += span->shift;
3229 *vec_grow(&ss->new_relocs, 1) = new_reloc;
3234 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
3235 struct supersect *ss = fetch_supersect(sbfd, sect), orig_ss;
3236 if (!ss->keep)
3237 continue;
3238 supersect_move(&orig_ss, ss);
3239 vec_init(&ss->spans);
3240 for (span = orig_ss.spans.data;
3241 span < orig_ss.spans.data + orig_ss.spans.size; span++) {
3242 if (!span->keep)
3243 continue;
3244 struct span *new_span = vec_grow(&ss->spans, 1);
3245 *new_span = *span;
3246 new_span->start = span->start + span->shift;
3247 new_span->shift = 0;
3248 sect_copy(ss, sect_do_grow(ss, 1, span->size, 1),
3249 &orig_ss, orig_ss.contents.data + span->start,
3250 span->size);
3255 static void init_objmanip_superbfd(struct superbfd *sbfd)
3257 init_label_map(sbfd);
3258 initialize_supersect_types(sbfd);
3259 initialize_spans(sbfd);
3260 load_options(sbfd);
3263 void mangle_section_name(struct superbfd *sbfd, const char *name)
3265 asection *sect = bfd_get_section_by_name(sbfd->abfd, name);
3266 if (sect == NULL)
3267 return;
3268 struct supersect *ss = fetch_supersect(sbfd, sect);
3269 ss->name = strprintf(".ksplice_pre.%s", ss->name);
3272 static void write_bugline_patches(struct superbfd *sbfd)
3274 const struct table_section *ts = get_table_section("__bug_table");
3275 asection *sect = bfd_get_section_by_name(sbfd->abfd, "__bug_table");
3276 if (sect == NULL)
3277 return;
3278 struct supersect *ss = fetch_supersect(sbfd, sect);
3279 assert(ts != NULL);
3281 void *entry;
3282 for (entry = ss->contents.data;
3283 entry < ss->contents.data + ss->contents.size;
3284 entry += ts->entry_size) {
3285 struct span *span = find_span(ss, addr_offset(ss, entry));
3286 assert(span != NULL);
3287 if (!span->bugpatch)
3288 continue;
3289 arelent *reloc = find_reloc(ss, entry + ts->addr_offset);
3290 assert(reloc != NULL);
3291 asymbol *sym = *reloc->sym_ptr_ptr;
3292 assert(!bfd_is_const_section(sym->section));
3293 struct supersect *kpatch_ss =
3294 make_section(sbfd, ".ksplice_patches%s",
3295 sym->section->name);
3297 bfd_vma offset, start = 0;
3298 for (offset = 0; offset <= span->size; offset++) {
3299 if (offset != span->size &&
3300 !part_of_reloc(ss, span->start + offset))
3301 continue;
3302 if (start == offset) {
3303 start++;
3304 continue;
3306 /* an interval of non-relocations just passed */
3307 struct ksplice_patch *kpatch =
3308 sect_grow(kpatch_ss, 1, struct ksplice_patch);
3309 write_ksplice_patch_reloc
3310 (kpatch_ss, sym->section->name, &kpatch->oldaddr,
3311 sizeof(kpatch->oldaddr), span->label, start);
3313 char *data = write_patch_storage(kpatch_ss, kpatch,
3314 offset - start, NULL);
3315 memcpy(data, entry + start, offset - start);
3316 kpatch->type = KSPLICE_PATCH_DATA;
3317 start = offset + 1;
3322 void *write_patch_storage(struct supersect *ss, struct ksplice_patch *kpatch,
3323 size_t size, struct supersect **data_ssp)
3325 struct supersect *data_ss = make_section(ss->parent,
3326 ".ksplice_patch_data");
3327 char *saved = sect_do_grow(data_ss, 1, size, 1);
3328 write_reloc(ss, &kpatch->saved, &data_ss->symbol,
3329 addr_offset(data_ss, saved));
3330 char *data = sect_do_grow(data_ss, 1, size, 1);
3331 write_reloc(ss, &kpatch->contents, &data_ss->symbol,
3332 addr_offset(data_ss, data));
3333 kpatch->size = size;
3334 if (data_ssp != NULL)
3335 *data_ssp = data_ss;
3336 return data;