Test CONFIG_FUNCTION_TRACER instead of CONFIG_FTRACE.
[ksplice.git] / objmanip.c
blob9f72726c505a69c4ca23c57014bd0178e6aba62d
1 /* This file is based in part on objcopy.c from GNU Binutils v2.17.
3 * Copyright (C) 1991-2006 Free Software Foundation, Inc.
4 * Copyright (C) 2007-2009 Ksplice, Inc.
5 * Authors: Jeff Arnold, Anders Kaseorg, Tim Abbott
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License, version 2.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
18 * 02110-1301, USA.
21 /* objmanip performs various object file manipulations for Ksplice. Its first
22 * two arguments are always an input object file and an output object file.
24 * - keep-new-code: "objmanip <post.o> <out.o> keep-new-code <pre.o> <kid>"
26 * This mode prepares the object file to be installed as a ksplice update. The
27 * kid argument is the ksplice id string for the ksplice update being built.
29 * - keep-old-code: "objmanip <pre.o> <out.o> keep-old-code"
31 * This mode prepares the object file to be used for run-pre matching. This
32 * involves replacing all ELF relocations with ksplice relocations and
33 * writing ksplice_section structures for each ELF text or data section.
35 * - rmsyms mode: "objmanip <in.o> <out.o> rmsyms
37 * In this mode, any ELF relocations involving the list of symbol names given on
38 * standard input are replaced with ksplice relocations. This is used only
39 * for KSPLICE_STANDALONE.
41 * - finalize mode: "objmanip <in.o> <out.o> finalize"
43 * In this mode, any ELF relocations to undefined symbols are replaced with
44 * ksplice relocations.
47 /* Always define KSPLICE_STANDALONE, even if you're using integrated Ksplice.
48 objmanip won't compile without it. */
49 #define KSPLICE_STANDALONE
51 #define _GNU_SOURCE
52 #include "objcommon.h"
53 #include "kmodsrc/ksplice.h"
54 #include "kmodsrc/offsets.h"
55 #include "ksplice-patch/ksplice-patch.h"
56 #include <stdint.h>
57 #include <stdarg.h>
58 #include <stdlib.h>
59 #include <stdio.h>
60 #include <limits.h>
62 #define KSPLICE_SYMBOL_STR "KSPLICE_SYMBOL_"
64 #define symbol_init(sym) *(sym) = (asymbol *)NULL
65 DEFINE_HASH_TYPE(asymbol *, symbol_hash, symbol_hash_init, symbol_hash_free,
66 symbol_hash_lookup, symbol_init);
68 DECLARE_VEC_TYPE(const char *, str_vec);
70 DECLARE_VEC_TYPE(unsigned long, ulong_vec);
72 #define bool_init(b) *(b) = false
73 DEFINE_HASH_TYPE(bool, bool_hash, bool_hash_init, bool_hash_free,
74 bool_hash_lookup, bool_init);
76 #define ulong_init(x) *(x) = 0
77 DEFINE_HASH_TYPE(unsigned long, ulong_hash, ulong_hash_init,
78 ulong_hash_free, ulong_hash_lookup, ulong_init);
80 void do_keep_new_code(struct superbfd *isbfd, const char *pre);
81 void do_keep_old_code(struct superbfd *isbfd);
82 void do_finalize(struct superbfd *isbfd);
83 void do_rmsyms(struct superbfd *isbfd);
85 bool relocs_equal(struct supersect *old_src_ss, struct supersect *new_src_ss,
86 arelent *old_reloc, arelent *new_reloc);
87 bfd_vma non_dst_mask(struct supersect *ss, arelent *reloc);
88 bool all_relocs_equal(struct span *old_span, struct span *new_span);
89 static bool part_of_reloc(struct supersect *ss, unsigned long addr);
90 static bool nonrelocs_equal(struct span *old_span, struct span *new_span);
91 static void handle_section_symbol_renames(struct superbfd *oldsbfd,
92 struct superbfd *newsbfd);
93 static void compute_entry_points(struct superbfd *sbfd);
94 static void copy_patched_entry_points(struct superbfd *oldsbfd,
95 struct superbfd *newsbfd);
97 enum supersect_type supersect_type(struct supersect *ss);
98 void initialize_supersect_types(struct superbfd *sbfd);
99 static void initialize_spans(struct superbfd *sbfd);
100 static void initialize_string_spans(struct supersect *ss);
101 static void initialize_table_spans(struct superbfd *sbfd,
102 struct table_section *s);
103 static void initialize_table_section_spans(struct superbfd *sbfd);
104 static void initialize_ksplice_call_spans(struct supersect *ss);
105 struct span *reloc_target_span(struct supersect *ss, arelent *reloc);
106 static struct span *span_offset_target_span(struct span *span, int offset);
107 static bfd_vma reloc_target_offset(struct supersect *ss, arelent *reloc);
108 struct span *find_span(struct supersect *ss, bfd_size_type address);
109 void remove_unkept_spans(struct superbfd *sbfd);
110 void compute_span_shifts(struct superbfd *sbfd);
111 static struct span *new_span(struct supersect *ss, bfd_vma start, bfd_vma size);
112 static bool is_table_section(const char *name, bool consider_other,
113 bool consider_crc);
114 const struct table_section *get_table_section(const char *name);
115 void mangle_section_name(struct superbfd *sbfd, const char *name);
117 void rm_relocs(struct superbfd *isbfd);
118 void rm_some_relocs(struct supersect *ss);
119 void write_ksplice_reloc(struct supersect *ss, arelent *orig_reloc);
120 static void write_ksplice_reloc_howto(struct supersect *ss, const
121 struct ksplice_reloc_howto *const *addr,
122 reloc_howto_type *howto,
123 enum ksplice_reloc_howto_type type);
124 static void write_ksplice_date_reloc(struct supersect *ss, unsigned long offset,
125 const char *str,
126 enum ksplice_reloc_howto_type type);
127 static void write_ksplice_patch_reloc(struct supersect *ss,
128 const char *sectname, unsigned long *addr,
129 bfd_size_type size, const char *label,
130 long addend);
131 static void write_ksplice_nonreloc_howto(struct supersect *ss,
132 const struct ksplice_reloc_howto
133 *const *addr,
134 enum ksplice_reloc_howto_type type,
135 int size);
136 static void write_date_relocs(struct superbfd *sbfd, const char *str,
137 enum ksplice_reloc_howto_type type);
138 static void write_table_relocs(struct superbfd *sbfd, const char *sectname,
139 enum ksplice_reloc_howto_type type);
140 static void write_ksplice_table_reloc(struct supersect *ss,
141 unsigned long address,
142 const char *label,
143 enum ksplice_reloc_howto_type type);
144 void load_ksplice_symbol_offsets(struct superbfd *sbfd);
145 void write_canary(struct supersect *ss, int offset, bfd_size_type size,
146 bfd_vma dst_mask);
147 static void write_ksplice_section(struct span *span);
148 void write_ksplice_patches(struct superbfd *sbfd, struct span *span);
149 void write_ksplice_patch(struct superbfd *sbfd, struct span *span,
150 const char *label, long offset);
151 void *write_patch_storage(struct supersect *ss, struct ksplice_patch *patch,
152 size_t size, struct supersect **data_ssp);
153 void write_ksplice_deleted_patch(struct superbfd *sbfd, const char *name,
154 const char *label, const char *sectname,
155 long offset);
156 static void write_bugline_patches(struct superbfd *sbfd);
157 asymbol **make_undefined_symbolp(struct superbfd *sbfd, const char *name);
158 void filter_table_sections(struct superbfd *isbfd);
159 void filter_table_section(struct superbfd *sbfd, const struct table_section *s);
160 void keep_referenced_sections(struct superbfd *sbfd);
161 void mark_precallable_spans(struct superbfd *sbfd);
162 bfd_boolean copy_object(bfd *ibfd, bfd *obfd);
163 void setup_section(bfd *ibfd, asection *isection, void *obfdarg);
164 static void setup_new_section(bfd *obfd, struct supersect *ss);
165 static void write_section(bfd *obfd, asection *osection, void *arg);
166 static void delete_obsolete_relocs(struct supersect *ss);
167 void mark_symbols_used_in_relocations(bfd *abfd, asection *isection,
168 void *ignored);
169 static void ss_mark_symbols_used_in_relocations(struct supersect *ss);
170 void filter_symbols(bfd *ibfd, bfd *obfd, struct asymbolp_vec *osyms,
171 struct asymbolp_vec *isyms);
172 static bool deleted_table_section_symbol(bfd *abfd, asymbol *sym);
173 struct supersect *__attribute((format(printf, 2, 3)))
174 make_section(struct superbfd *sbfd, const char *fmt, ...);
175 void __attribute__((format(printf, 3, 4)))
176 write_string(struct supersect *ss, const char **addr, const char *fmt, ...);
177 void write_ksplice_export(struct superbfd *sbfd, struct span *span, bool del);
178 void write_reloc(struct supersect *ss, const void *addr, asymbol **symp,
179 bfd_vma offset);
180 arelent *create_reloc(struct supersect *ss, const void *addr, asymbol **symp,
181 bfd_vma offset);
182 static void foreach_symbol_pair(struct superbfd *oldsbfd, struct superbfd *newsbfd,
183 void (*fn)(struct span *old_span,
184 asymbol *oldsym,
185 struct span *new_span,
186 asymbol *newsym));
187 static void check_global_symbols(struct span *old_span, asymbol *oldsym,
188 struct span *new_span, asymbol *newsym);
189 static void match_global_symbols(struct span *old_span, asymbol *oldsym,
190 struct span *new_span, asymbol *newsym);
191 static void match_symbol_spans(struct span *old_span, asymbol *oldsym,
192 struct span *new_span, asymbol *newsym);
193 static void match_table_spans(struct span *old_span, struct span *new_span);
194 static void match_other_spans(struct span *old_span, struct span *new_span);
196 static struct span *get_crc_span(struct span *span,
197 const struct table_section *ts);
198 static void foreach_span_pair(struct superbfd *oldsbfd,
199 struct superbfd *newsbfd,
200 void (*fn)(struct span *old_span,
201 struct span *new_span));
202 static void match_spans_by_label(struct span *old_span, struct span *new_span);
203 static void match_string_spans(struct span *old_span, struct span *new_span);
204 static void mark_new_spans(struct superbfd *sbfd);
205 static void handle_deleted_spans(struct superbfd *oldsbfd,
206 struct superbfd *newsbfd);
207 static void unmatch_addr_spans(struct span *old_span, struct span *new_span,
208 const struct table_section *ts);
209 static void compare_matched_spans(struct superbfd *newsbfd);
210 static void compare_spans(struct span *old_span, struct span *new_span);
211 static void update_nonzero_offsets(struct superbfd *sbfd);
212 static void handle_nonzero_offset_relocs(struct supersect *ss);
213 static void keep_span(struct span *span);
215 static void init_objmanip_superbfd(struct superbfd *sbfd);
216 static const char *label_lookup(struct superbfd *sbfd, asymbol *sym);
217 static void label_map_set(struct superbfd *sbfd, const char *oldlabel,
218 const char *label);
219 static void print_label_changes(struct superbfd *sbfd);
220 static void init_label_map(struct superbfd *sbfd);
221 static void change_initial_label(struct span *span, const char *label);
222 static asymbol **symbolp_scan(struct supersect *ss, bfd_vma value);
223 static void init_csyms(struct superbfd *sbfd);
224 static void init_callers(struct superbfd *sbfd);
225 static asymbol *canonical_symbol(struct superbfd *sbfd, asymbol *sym);
226 static asymbol **canonical_symbolp(struct superbfd *sbfd, asymbol *sym);
227 static char *static_local_symbol(struct superbfd *sbfd, asymbol *sym);
228 static char *symbol_label(struct superbfd *sbfd, asymbol *sym);
230 int verbose = 0;
231 #define debug_(sbfd, level, fmt, ...) \
232 do { \
233 if (verbose >= (level)) \
234 printf("%s: " fmt, (sbfd)->abfd->filename, \
235 ## __VA_ARGS__); \
236 } while (0)
237 #define debug0(sbfd, fmt, ...) debug_(sbfd, 0, fmt, ## __VA_ARGS__)
238 #define debug1(sbfd, fmt, ...) debug_(sbfd, 1, fmt, ## __VA_ARGS__)
239 #define err(sbfd, fmt, ...) \
240 do { \
241 fprintf(stderr, "%s: " fmt, (sbfd)->abfd->filename, \
242 ## __VA_ARGS__); \
243 } while (0)
245 struct str_vec delsects;
246 struct asymbolp_vec extract_syms;
247 bool changed;
249 struct ksplice_config *config;
251 const char *modestr, *kid, *finalize_target = NULL;
252 bool write_output = true;
254 struct superbfd *offsets_sbfd = NULL;
256 #define mode(str) strstarts(modestr, str)
258 DECLARE_VEC_TYPE(unsigned long, addr_vec);
259 DEFINE_HASH_TYPE(struct addr_vec, addr_vec_hash,
260 addr_vec_hash_init, addr_vec_hash_free, addr_vec_hash_lookup,
261 vec_init);
262 struct addr_vec_hash system_map;
264 struct bool_hash system_map_written;
265 struct ulong_hash ksplice_symbol_offset;
266 struct ulong_hash ksplice_howto_offset;
267 struct ulong_hash ksplice_string_offset;
269 void load_system_map()
271 const char *config_dir = getenv("KSPLICE_CONFIG_DIR");
272 assert(config_dir);
273 FILE *fp = fopen(strprintf("%s/System.map", config_dir), "r");
274 assert(fp);
275 addr_vec_hash_init(&system_map);
276 unsigned long addr;
277 char type;
278 char *sym;
279 while (fscanf(fp, "%lx %c %as\n", &addr, &type, &sym) == 3)
280 *vec_grow(addr_vec_hash_lookup(&system_map, sym, TRUE),
281 1) = addr;
282 fclose(fp);
285 void load_ksplice_symbol_offsets(struct superbfd *sbfd)
287 asection *sect = bfd_get_section_by_name(sbfd->abfd,
288 ".ksplice_symbols");
289 if (sect == NULL)
290 return;
291 struct supersect *ss = fetch_supersect(sbfd, sect);
293 struct ksplice_symbol *ksym;
294 for (ksym = ss->contents.data;
295 (void *)ksym < ss->contents.data + ss->contents.size; ksym++) {
296 const char *label = read_string(ss, &ksym->label);
297 unsigned long *ksymbol_offp =
298 ulong_hash_lookup(&ksplice_symbol_offset, label, TRUE);
299 *ksymbol_offp = addr_offset(ss, ksym);
303 void load_offsets()
305 char *kmodsrc = getenv("KSPLICE_KMODSRC");
306 assert(kmodsrc != NULL);
307 bfd *offsets_bfd = bfd_openr(strprintf("%s/offsets.o", kmodsrc), NULL);
308 assert(offsets_bfd != NULL);
309 char **matching;
310 assert(bfd_check_format_matches(offsets_bfd, bfd_object, &matching));
311 offsets_sbfd = fetch_superbfd(offsets_bfd);
313 asection *config_sect = bfd_get_section_by_name(offsets_sbfd->abfd,
314 ".ksplice_config");
315 struct supersect *config_ss =
316 fetch_supersect(offsets_sbfd, config_sect);
318 config = config_ss->contents.data;
321 void load_options(struct superbfd *sbfd)
323 asection *sect = bfd_get_section_by_name(sbfd->abfd,
324 ".ksplice_options");
325 if (sect == NULL)
326 return;
327 struct supersect *ss = fetch_supersect(sbfd, sect);
328 const struct ksplice_option *opt;
329 for (opt = ss->contents.data;
330 (void *)opt < ss->contents.data + ss->contents.size; opt++) {
331 if (opt->type == KSPLICE_OPTION_ASSUME_RODATA) {
332 arelent *reloc = find_reloc(ss, &opt->target);
333 assert(reloc != NULL);
334 struct span *span = reloc_target_span(ss, reloc);
335 assert(span != NULL);
336 assert(span->ss->type == SS_TYPE_DATA);
337 assert(span->start == 0 &&
338 span->size == span->ss->contents.size);
339 span->ss->type = SS_TYPE_RODATA;
340 } else if (opt->type == KSPLICE_OPTION_MATCH_DATA_EARLY) {
341 arelent *reloc = find_reloc(ss, &opt->target);
342 assert(reloc != NULL);
343 struct span *span = reloc_target_span(ss, reloc);
344 assert(span != NULL);
345 assert(span->ss->type == SS_TYPE_DATA);
346 assert(span->start == 0 &&
347 span->size == span->ss->contents.size);
348 span->ss->match_data_early = true;
349 } else {
350 err(sbfd, "Unrecognized Ksplice option %d\n",
351 opt->type);
352 DIE;
357 bool matchable_data_section(struct supersect *ss)
359 if (ss->type == SS_TYPE_STRING)
360 return true;
361 if (ss->type == SS_TYPE_RODATA)
362 return true;
363 if (ss->type == SS_TYPE_DATA && ss->relocs.size != 0)
364 return true;
365 if (ss->type == SS_TYPE_EXPORT)
366 return true;
367 if (ss->type == SS_TYPE_BUGTABLE)
368 return true;
369 return false;
372 bool unchangeable_section(struct supersect *ss)
374 if (ss->type == SS_TYPE_DATA)
375 return true;
376 if (ss->type == SS_TYPE_IGNORED && !strstarts(ss->name, ".debug") &&
377 strcmp(ss->name, "__ksymtab_strings") != 0)
378 return true;
379 return false;
382 int main(int argc, char *argv[])
384 if (getenv("KSPLICE_VERBOSE") != NULL)
385 verbose = atoi(getenv("KSPLICE_VERBOSE"));
387 bfd_init();
388 bfd *ibfd = bfd_openr(argv[1], NULL);
389 assert(ibfd);
391 char **matching;
392 if (bfd_check_format_matches(ibfd, bfd_archive, &matching) &&
393 bfd_openr_next_archived_file(ibfd, NULL) == NULL)
394 return 66; /* empty archive */
395 assert(bfd_check_format_matches(ibfd, bfd_object, &matching));
397 const char *output_target = bfd_get_target(ibfd);
399 load_system_map();
400 load_offsets();
402 bool_hash_init(&system_map_written);
403 ulong_hash_init(&ksplice_symbol_offset);
404 ulong_hash_init(&ksplice_howto_offset);
405 ulong_hash_init(&ksplice_string_offset);
407 struct superbfd *isbfd = fetch_superbfd(ibfd);
409 modestr = argv[3];
410 if (mode("finalize"))
411 finalize_target = argv[4];
412 init_objmanip_superbfd(isbfd);
413 if (mode("keep-new-code")) {
414 kid = argv[5];
415 do_keep_new_code(isbfd, argv[4]);
416 } else if (mode("keep-old-code")) {
417 do_keep_old_code(isbfd);
418 } else if (mode("finalize")) {
419 do_finalize(isbfd);
420 } else if (mode("rmsyms")) {
421 do_rmsyms(isbfd);
424 if (write_output) {
425 bfd *obfd = bfd_openw(argv[2], output_target);
426 assert(obfd);
427 copy_object(ibfd, obfd);
428 assert(bfd_close(obfd));
431 if (offsets_sbfd != NULL)
432 assert(bfd_close(offsets_sbfd->abfd));
433 assert(bfd_close(ibfd));
434 return EXIT_SUCCESS;
437 void do_keep_new_code(struct superbfd *isbfd, const char *pre)
439 struct bfd *prebfd = bfd_openr(pre, NULL);
440 assert(prebfd != NULL);
441 char **matching;
442 assert(bfd_check_format_matches(prebfd, bfd_object, &matching));
444 struct superbfd *presbfd = fetch_superbfd(prebfd);
445 init_objmanip_superbfd(presbfd);
447 foreach_symbol_pair(presbfd, isbfd, match_global_symbols);
448 debug1(isbfd, "Matched global\n");
449 foreach_span_pair(presbfd, isbfd, match_string_spans);
450 debug1(isbfd, "Matched string spans\n");
451 foreach_symbol_pair(presbfd, isbfd, match_symbol_spans);
452 debug1(isbfd, "Matched by name\n");
453 foreach_span_pair(presbfd, isbfd, match_spans_by_label);
454 debug1(isbfd, "Matched by label\n");
455 foreach_span_pair(presbfd, isbfd, match_table_spans);
456 debug1(isbfd, "Matched table spans\n");
457 foreach_span_pair(presbfd, isbfd, match_other_spans);
458 debug1(isbfd, "Matched other spans\n");
460 do {
461 changed = false;
462 compare_matched_spans(isbfd);
463 update_nonzero_offsets(isbfd);
464 mark_new_spans(isbfd);
465 } while (changed);
466 vec_init(&delsects);
468 foreach_symbol_pair(presbfd, isbfd, check_global_symbols);
470 handle_deleted_spans(presbfd, isbfd);
471 handle_section_symbol_renames(presbfd, isbfd);
473 copy_patched_entry_points(presbfd, isbfd);
475 assert(bfd_close(prebfd));
477 do {
478 changed = false;
479 mark_precallable_spans(isbfd);
480 } while (changed);
482 asection *sect;
483 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
484 struct supersect *ss = fetch_supersect(isbfd, sect);
485 ss->keep = false;
486 struct span *span;
487 for (span = ss->spans.data;
488 span < ss->spans.data + ss->spans.size; span++) {
489 if (strstarts(ss->name, ".ksplice_options"))
490 span->keep = false;
491 else if (span->new || span->patch || span->datapatch)
492 keep_span(span);
493 else
494 span->keep = false;
495 if (span->patch && span->precallable) {
496 err(isbfd, "Patched span %s can be reached "
497 "by a precall function\n", span->label);
498 DIE;
503 print_label_changes(isbfd);
505 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
506 struct supersect *ss = fetch_supersect(isbfd, sect);
507 struct span *span;
508 for (span = ss->spans.data;
509 span < ss->spans.data + ss->spans.size; span++) {
510 if (span->patch || span->bugpatch || span->datapatch)
511 debug0(isbfd, "Patching span %s\n",
512 span->label);
516 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
517 struct supersect *ss = fetch_supersect(isbfd, sect);
518 struct span *span;
519 for (span = ss->spans.data;
520 span < ss->spans.data + ss->spans.size; span++) {
521 if (span->new)
522 debug0(isbfd, "New span %s\n", span->label);
526 write_output = false;
527 const char **sectname;
528 for (sectname = delsects.data;
529 sectname < delsects.data + delsects.size; sectname++) {
530 write_output = true;
531 debug0(isbfd, "Deleted section: %s\n", *sectname);
534 filter_table_sections(isbfd);
536 compute_span_shifts(isbfd);
538 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
539 struct supersect *ss = fetch_supersect(isbfd, sect);
540 if (ss->type == SS_TYPE_KSPLICE_CALL)
541 continue;
542 struct span *span;
543 for (span = ss->spans.data;
544 span < ss->spans.data + ss->spans.size; span++) {
545 if (span->keep || span->bugpatch)
546 write_output = true;
547 if (span->patch || span->new || span->datapatch)
548 write_ksplice_section(span);
549 if (span->patch || span->datapatch)
550 write_ksplice_patches(isbfd, span);
551 if (ss->type == SS_TYPE_EXPORT && span->new)
552 write_ksplice_export(isbfd, span, false);
556 write_bugline_patches(isbfd);
557 rm_relocs(isbfd);
558 remove_unkept_spans(isbfd);
561 void do_keep_old_code(struct superbfd *isbfd)
563 asection *sect;
564 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
565 struct supersect *ss = fetch_supersect(isbfd, sect);
566 ss->keep = false;
567 struct span *span;
568 for (span = ss->spans.data;
569 span < ss->spans.data + ss->spans.size; span++) {
570 span->keep = false;
571 if (ss->type == SS_TYPE_TEXT &&
572 !strstarts(ss->name, ".fixup"))
573 keep_span(span);
574 if (ss->type == SS_TYPE_EXPORT)
575 keep_span(span);
579 asymbol **symp;
580 for (symp = isbfd->syms.data;
581 symp < isbfd->syms.data + isbfd->syms.size; symp++) {
582 asymbol *sym = *symp;
583 if (!bfd_is_const_section(sym->section) &&
584 (sym->flags & BSF_GLOBAL) != 0) {
585 struct supersect *sym_ss =
586 fetch_supersect(isbfd, sym->section);
587 if (sym->value == sym_ss->contents.size)
588 continue;
589 struct span *span = find_span(sym_ss, sym->value);
590 assert(span != NULL);
591 if (sym_ss->type != SS_TYPE_IGNORED)
592 keep_span(span);
596 do {
597 changed = false;
598 keep_referenced_sections(isbfd);
599 } while (changed);
601 filter_table_sections(isbfd);
602 compute_span_shifts(isbfd);
604 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
605 struct supersect *ss = fetch_supersect(isbfd, sect);
606 asymbol *sym = canonical_symbol(isbfd, sect->symbol);
607 if (sym == NULL)
608 continue;
609 if ((sym->flags & BSF_WEAK) != 0)
610 continue;
611 if (bfd_get_section_size(sect) == 0)
612 continue;
613 if (!ss->keep)
614 continue;
615 if (ss->type != SS_TYPE_TEXT && !matchable_data_section(ss))
616 continue;
618 struct span *span;
619 for (span = ss->spans.data;
620 span < ss->spans.data + ss->spans.size; span++) {
621 if (span->keep)
622 write_ksplice_section(span);
626 write_table_relocs(isbfd, "__bug_table", KSPLICE_HOWTO_BUG);
627 write_table_relocs(isbfd, "__ex_table", KSPLICE_HOWTO_EXTABLE);
628 rm_relocs(isbfd);
629 remove_unkept_spans(isbfd);
631 mangle_section_name(isbfd, "__markers");
632 mangle_section_name(isbfd, "__tracepoints");
633 mangle_section_name(isbfd, "__ex_table");
634 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
635 struct supersect *ss = fetch_supersect(isbfd, sect);
636 if (ss->type == SS_TYPE_EXPORT)
637 mangle_section_name(isbfd, ss->name);
641 void do_finalize(struct superbfd *isbfd)
643 load_ksplice_symbol_offsets(isbfd);
644 asection *sect;
645 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
646 struct supersect *ss = fetch_supersect(isbfd, sect);
647 if (ss->type == SS_TYPE_EXIT) {
648 struct span *span;
649 for (span = ss->spans.data;
650 span < ss->spans.data + ss->spans.size; span++)
651 span->keep = false;
652 ss->keep = false;
655 write_date_relocs(isbfd, "<{DATE...}>", KSPLICE_HOWTO_DATE);
656 write_date_relocs(isbfd, "<{TIME}>", KSPLICE_HOWTO_TIME);
657 rm_relocs(isbfd);
660 void do_rmsyms(struct superbfd *isbfd)
662 asection *extract_sect = bfd_get_section_by_name(isbfd->abfd,
663 ".ksplice_extract");
664 if (extract_sect != NULL) {
665 struct supersect *extract_ss = fetch_supersect(isbfd,
666 extract_sect);
667 arelent **relocp;
668 for (relocp = extract_ss->relocs.data;
669 relocp < extract_ss->relocs.data + extract_ss->relocs.size;
670 relocp++) {
671 asymbol *sym = *(*relocp)->sym_ptr_ptr;
672 if (bfd_is_und_section(sym->section)) {
673 debug1(isbfd, "extracting symbol %s\n",
674 sym->name);
675 *vec_grow(&extract_syms, 1) = sym;
680 rm_relocs(isbfd);
683 void match_spans(struct span *old_span, struct span *new_span)
685 struct superbfd *sbfd = new_span->ss->parent;
686 if (old_span->match == new_span && new_span->match == old_span)
687 return;
688 if (old_span->match != NULL) {
689 err(sbfd, "Matching conflict: old %s: %s != %s\n",
690 old_span->label, old_span->match->label, new_span->label);
691 DIE;
693 if (new_span->match != NULL) {
694 err(sbfd, "Matching conflict: new %s: %s != %s\n",
695 new_span->label, new_span->match->label, old_span->label);
696 DIE;
698 old_span->match = new_span;
699 new_span->match = old_span;
700 debug1(sbfd, "Matched old %s to new %s\n", old_span->label,
701 new_span->label);
702 if (old_span->ss->type != new_span->ss->type &&
703 old_span->ss->type == new_span->ss->orig_type)
704 old_span->ss->type = new_span->ss->type;
706 const struct table_section *ts = get_table_section(old_span->ss->name);
707 if (ts == NULL || !ts->has_addr || ts->other_sect == NULL)
708 return;
709 struct span *old_sym_span =
710 span_offset_target_span(old_span, ts->other_offset);
711 struct span *new_sym_span =
712 span_offset_target_span(new_span, ts->other_offset);
713 assert(old_sym_span != NULL && new_sym_span != NULL);
714 match_spans(old_sym_span, new_sym_span);
717 void unmatch_span(struct span *old_span)
719 struct span *new_span = old_span->match;
720 old_span->match = NULL;
721 new_span->match = NULL;
723 new_span->bugpatch = false;
725 if (old_span->ss->type == SS_TYPE_SPECIAL) {
726 const struct table_section *ts =
727 get_table_section(old_span->ss->name);
728 if (ts != NULL && ts->has_addr)
729 unmatch_addr_spans(old_span, new_span, ts);
732 new_span->patch = false;
733 new_span->bugpatch = false;
734 new_span->datapatch = false;
736 changed = true;
739 static void match_global_symbols(struct span *old_span, asymbol *oldsym,
740 struct span *new_span, asymbol *newsym)
742 if (newsym == NULL ||
743 (oldsym->flags & BSF_GLOBAL) == 0 ||
744 (newsym->flags & BSF_GLOBAL) == 0)
745 return;
746 match_spans(old_span, new_span);
749 static void check_global_symbols(struct span *old_span, asymbol *oldsym,
750 struct span *new_span, asymbol *newsym)
752 if ((oldsym->flags & BSF_GLOBAL) == 0 ||
753 (newsym != NULL && (newsym->flags & BSF_GLOBAL) == 0))
754 return;
755 if (old_span->ss->type == SS_TYPE_IGNORED)
756 return;
757 if (old_span->match != new_span) {
758 if (new_span != NULL)
759 err(new_span->ss->parent,
760 "Global symbol span mismatch: %s %s/%s\n",
761 oldsym->name, old_span->label, new_span->label);
762 else
763 err(old_span->ss->parent,
764 "Global symbol span mismatch: %s %s/NULL\n",
765 oldsym->name, old_span->label);
766 DIE;
770 static void foreach_symbol_pair(struct superbfd *oldsbfd, struct superbfd *newsbfd,
771 void (*fn)(struct span *old_span,
772 asymbol *oldsym,
773 struct span *new_span,
774 asymbol *newsym))
776 asymbol **oldsymp, **newsymp;
777 for (oldsymp = oldsbfd->syms.data;
778 oldsymp < oldsbfd->syms.data + oldsbfd->syms.size; oldsymp++) {
779 asymbol *oldsym = *oldsymp;
780 if ((oldsym->flags & BSF_DEBUGGING) != 0 ||
781 bfd_is_const_section(oldsym->section))
782 continue;
784 struct supersect *old_ss =
785 fetch_supersect(oldsbfd, oldsym->section);
786 if (old_ss->type == SS_TYPE_SPECIAL ||
787 old_ss->type == SS_TYPE_EXPORT)
788 continue;
790 struct span *old_span = find_span(old_ss, oldsym->value);
791 if (old_span == NULL) {
792 err(oldsbfd, "Could not find span for %s\n",
793 oldsym->name);
794 DIE;
797 bool found = false;
799 for (newsymp = newsbfd->syms.data;
800 newsymp < newsbfd->syms.data + newsbfd->syms.size;
801 newsymp++) {
802 asymbol *newsym = *newsymp;
803 if ((newsym->flags & BSF_DEBUGGING) != 0 ||
804 bfd_is_const_section(newsym->section))
805 continue;
806 if (strcmp(oldsym->name, newsym->name) != 0)
807 continue;
809 struct supersect *new_ss =
810 fetch_supersect(newsbfd, newsym->section);
811 if (old_ss->type != new_ss->type &&
812 old_ss->type != new_ss->orig_type)
813 continue;
815 assert(!found);
816 found = true;
818 struct span *new_span =
819 find_span(new_ss, newsym->value);
820 if (new_span == NULL) {
821 err(newsbfd, "Could not find span for %s\n",
822 newsym->name);
823 DIE;
825 fn(old_span, oldsym, new_span, newsym);
828 if (!found)
829 fn(old_span, oldsym, NULL, NULL);
833 static void match_symbol_spans(struct span *old_span, asymbol *oldsym,
834 struct span *new_span, asymbol *newsym)
836 if (newsym == NULL)
837 return;
838 if (old_span->ss->type == SS_TYPE_SPECIAL)
839 return;
840 if (static_local_symbol(old_span->ss->parent, oldsym) ||
841 static_local_symbol(new_span->ss->parent, newsym))
842 return;
843 if (old_span->match == NULL && new_span->match == NULL)
844 match_spans(old_span, new_span);
847 static void match_spans_by_label(struct span *old_span, struct span *new_span)
849 if (old_span->ss->type == SS_TYPE_STRING ||
850 (is_table_section(old_span->ss->name, true, false) &&
851 !is_table_section(old_span->ss->name, false, false)))
852 return;
853 if (strcmp(old_span->label, new_span->label) == 0)
854 match_spans(old_span, new_span);
857 static void match_string_spans(struct span *old_span, struct span *new_span)
859 if (old_span->ss->type != SS_TYPE_STRING ||
860 strcmp(old_span->ss->name, new_span->ss->name) != 0)
861 return;
862 if (strcmp((char *)old_span->ss->contents.data + old_span->start,
863 (char *)new_span->ss->contents.data + new_span->start) == 0)
864 match_spans(old_span, new_span);
867 static void foreach_span_pair(struct superbfd *oldsbfd,
868 struct superbfd *newsbfd,
869 void (*fn)(struct span *old_span,
870 struct span *new_span))
872 asection *oldsect, *newsect;
873 struct supersect *oldss, *newss;
874 struct span *old_span, *new_span;
875 for (newsect = newsbfd->abfd->sections; newsect != NULL;
876 newsect = newsect->next) {
877 newss = fetch_supersect(newsbfd, newsect);
878 for (oldsect = oldsbfd->abfd->sections; oldsect != NULL;
879 oldsect = oldsect->next) {
880 oldss = fetch_supersect(oldsbfd, oldsect);
881 if (oldss->type != newss->type)
882 continue;
883 for (new_span = newss->spans.data;
884 new_span < newss->spans.data + newss->spans.size;
885 new_span++) {
886 for (old_span = oldss->spans.data;
887 old_span < oldss->spans.data +
888 oldss->spans.size; old_span++)
889 fn(old_span, new_span);
895 static void mark_new_spans(struct superbfd *sbfd)
897 asection *sect;
898 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
899 struct supersect *ss = fetch_supersect(sbfd, sect);
900 if (ss->type == SS_TYPE_SPECIAL || ss->type == SS_TYPE_IGNORED)
901 continue;
902 struct span *span;
903 for (span = ss->spans.data;
904 span < ss->spans.data + ss->spans.size; span++) {
905 if (span->match == NULL)
906 span->new = true;
911 static void handle_deleted_spans(struct superbfd *oldsbfd,
912 struct superbfd *newsbfd)
914 asection *sect;
915 for (sect = oldsbfd->abfd->sections; sect != NULL; sect = sect->next) {
916 struct supersect *ss = fetch_supersect(oldsbfd, sect);
917 struct span *span;
918 for (span = ss->spans.data;
919 span < ss->spans.data + ss->spans.size; span++) {
920 if (span->match != NULL)
921 continue;
922 if (ss->type == SS_TYPE_EXPORT) {
923 *vec_grow(&delsects, 1) = span->label;
924 write_ksplice_export(newsbfd, span, true);
925 } else if (ss->type == SS_TYPE_TEXT) {
926 *vec_grow(&delsects, 1) = span->label;
927 if (span->symbol == NULL)
928 DIE;
929 write_ksplice_deleted_patch
930 (newsbfd, span->symbol->name, span->label,
931 span->ss->name, 0);
937 static void handle_nonzero_offset_relocs(struct supersect *ss)
939 struct span *address_span, *target_span;
940 arelent **relocp;
941 for (relocp = ss->relocs.data;
942 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
943 arelent *reloc = *relocp;
944 address_span = find_span(ss, reloc->address);
945 if (!address_span->new && !address_span->patch)
946 continue;
948 asymbol *sym = *reloc->sym_ptr_ptr;
949 if (bfd_is_const_section(sym->section))
950 continue;
951 bfd_vma offset = reloc_target_offset(ss, reloc);
952 target_span = reloc_target_span(ss, reloc);
953 if (sym->value + offset == target_span->start)
954 continue;
956 if (target_span->ss->type != SS_TYPE_TEXT)
957 continue;
958 if (target_span->patch)
959 continue;
961 target_span->patch = true;
962 changed = true;
963 debug1(ss->parent, "Changing %s because a relocation from sect "
964 "%s has a nonzero offset %lx+%lx into it\n",
965 target_span->label, ss->name, (unsigned long)sym->value,
966 (unsigned long)offset);
970 static void update_nonzero_offsets(struct superbfd *sbfd)
972 asection *sect;
973 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
974 struct supersect *ss = fetch_supersect(sbfd, sect);
975 if (ss->type == SS_TYPE_SPECIAL || ss->type == SS_TYPE_IGNORED)
976 continue;
977 handle_nonzero_offset_relocs(ss);
981 static void unmatch_addr_spans(struct span *old_span, struct span *new_span,
982 const struct table_section *ts)
984 struct span *old_sym_span =
985 span_offset_target_span(old_span, ts->addr_offset);
986 struct span *new_sym_span =
987 span_offset_target_span(new_span, ts->addr_offset);
988 assert(old_sym_span != NULL && new_sym_span != NULL);
989 if (old_sym_span->match == new_sym_span &&
990 new_sym_span->match == old_sym_span &&
991 !(new_sym_span->patch && new_sym_span->ss->type == SS_TYPE_TEXT)) {
992 if (old_sym_span->ss->type == SS_TYPE_TEXT) {
993 debug1(new_span->ss->parent, "Patching %s due "
994 "to relocations from special section %s\n",
995 new_sym_span->label, new_span->label);
996 new_sym_span->patch = true;
997 } else {
998 debug1(new_span->ss->parent, "Unmatching %s and %s due "
999 "to relocations from special section %s/%s\n",
1000 old_sym_span->label, new_sym_span->label,
1001 old_span->label, new_span->label);
1002 unmatch_span(old_sym_span);
1004 changed = true;
1008 static void compare_spans(struct span *old_span, struct span *new_span)
1010 struct superbfd *newsbfd = new_span->ss->parent;
1012 bool nonrelocs_match = nonrelocs_equal(old_span, new_span);
1013 bool relocs_match = all_relocs_equal(old_span, new_span);
1014 if (nonrelocs_match && relocs_match) {
1015 const struct table_section *ts =
1016 get_table_section(old_span->ss->name);
1017 if (ts != NULL && ts->crc_sect != NULL) {
1018 struct span *old_crc_span = get_crc_span(old_span, ts);
1019 struct span *new_crc_span = get_crc_span(new_span, ts);
1020 assert(old_crc_span != NULL);
1021 assert(new_crc_span != NULL);
1022 if (old_crc_span->match != new_crc_span ||
1023 new_crc_span->match != old_crc_span) {
1024 debug1(newsbfd, "Unmatching %s and %s due to "
1025 "nonmatching CRCs\n", old_span->label,
1026 new_span->label);
1027 unmatch_span(old_span);
1030 return;
1033 char *reason;
1034 if (new_span->contents_size != old_span->contents_size)
1035 reason = "differing sizes";
1036 else if (!nonrelocs_match)
1037 reason = "differing contents";
1038 else
1039 reason = "differing relocations";
1041 if (new_span->ss->type == SS_TYPE_TEXT) {
1042 if (new_span->patch)
1043 return;
1044 new_span->patch = true;
1045 debug1(newsbfd, "Changing %s due to %s\n", new_span->label,
1046 reason);
1047 } else if (old_span->ss->type == SS_TYPE_BUGTABLE &&
1048 new_span->ss->type == SS_TYPE_BUGTABLE && relocs_match) {
1049 if (new_span->bugpatch)
1050 return;
1051 debug1(newsbfd, "Changing %s due to %s\n",
1052 new_span->label, reason);
1053 new_span->bugpatch = true;
1054 } else if (new_span->ss->type == SS_TYPE_RODATA &&
1055 new_span->contents_size == old_span->contents_size) {
1056 if (new_span->datapatch)
1057 return;
1058 new_span->datapatch = true;
1059 debug1(newsbfd, "Changing %s in-place due to %s\n",
1060 new_span->label, reason);
1061 } else if (new_span->ss->type == SS_TYPE_STRING &&
1062 old_span->ss->type == SS_TYPE_STRING && relocs_match &&
1063 strcmp(new_span->ss->contents.data + new_span->start,
1064 old_span->ss->contents.data + old_span->start) == 0) {
1065 return;
1066 } else {
1067 debug1(newsbfd, "Unmatching %s and %s due to %s\n",
1068 old_span->label, new_span->label, reason);
1069 unmatch_span(old_span);
1071 changed = true;
1072 if (unchangeable_section(new_span->ss))
1073 err(newsbfd, "warning: ignoring change to nonpatchable "
1074 "section %s\n", new_span->ss->name);
1077 static void compare_matched_spans(struct superbfd *newsbfd)
1079 asection *sect;
1080 for (sect = newsbfd->abfd->sections; sect != NULL; sect = sect->next) {
1081 struct supersect *ss = fetch_supersect(newsbfd, sect);
1082 struct span *span;
1083 for (span = ss->spans.data;
1084 span < ss->spans.data + ss->spans.size; span++) {
1085 if (span->match == NULL)
1086 continue;
1087 compare_spans(span->match, span);
1092 static void handle_section_symbol_renames(struct superbfd *oldsbfd,
1093 struct superbfd *newsbfd)
1095 asection *sect;
1096 struct span *span;
1097 for (sect = newsbfd->abfd->sections; sect != NULL; sect = sect->next) {
1098 struct supersect *ss = fetch_supersect(newsbfd, sect);
1099 for (span = ss->spans.data;
1100 span < ss->spans.data + ss->spans.size; span++) {
1101 if (span->match == NULL)
1102 continue;
1103 if (strcmp(span->label, span->match->label) == 0)
1104 continue;
1105 if (strcmp(span->orig_label, span->label) != 0 &&
1106 strcmp(span->label, span->match->label) != 0)
1107 DIE;
1108 if (span->symbol != NULL)
1109 label_map_set(newsbfd, span->label,
1110 span->match->label);
1111 span->label = span->match->label;
1116 static void copy_patched_entry_points(struct superbfd *oldsbfd,
1117 struct superbfd *newsbfd)
1119 asection *sect;
1120 struct span *span;
1121 for (sect = newsbfd->abfd->sections; sect != NULL; sect = sect->next) {
1122 struct supersect *ss = fetch_supersect(newsbfd, sect);
1123 for (span = ss->spans.data;
1124 span < ss->spans.data + ss->spans.size; span++) {
1125 if (!span->patch)
1126 continue;
1127 assert(span->match != NULL);
1128 vec_init(&span->pre_entry_points);
1130 struct entry_point *entry;
1131 for (entry = span->match->entry_points.data;
1132 entry < span->match->entry_points.data +
1133 span->match->entry_points.size;
1134 entry++) {
1135 struct entry_point *e =
1136 vec_grow(&span->pre_entry_points, 1);
1137 e->name = entry->name != NULL ?
1138 strdup(entry->name) : NULL;
1139 e->label = strdup(entry->label);
1140 e->offset = entry->offset;
1141 e->symbol = NULL;
1147 static int compare_entry_points(const void *va, const void *vb)
1149 const struct entry_point *a = va, *b = vb;
1150 if (a->offset < b->offset)
1151 return -1;
1152 else if (a->offset > b->offset)
1153 return 1;
1154 else
1155 return 0;
1158 static void compute_entry_points(struct superbfd *sbfd)
1160 asymbol **symp;
1161 for (symp = sbfd->syms.data; symp < sbfd->syms.data + sbfd->syms.size;
1162 symp++) {
1163 asymbol *sym = *symp;
1164 if (bfd_is_const_section(sym->section))
1165 continue;
1166 struct supersect *old_ss = fetch_supersect(sbfd, sym->section);
1167 if ((sym->flags & BSF_GLOBAL) == 0)
1168 continue;
1169 struct span *span = find_span(old_ss, sym->value);
1170 struct entry_point *e = vec_grow(&span->entry_points, 1);
1171 e->label = sym->name;
1172 e->name = sym->name;
1173 e->offset = sym->value - span->start;
1174 e->symbol = sym;
1177 asection *sect;
1178 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
1179 struct supersect *ss = fetch_supersect(sbfd, sect);
1180 struct span *span;
1181 for (span = ss->spans.data;
1182 span < ss->spans.data + ss->spans.size; span++) {
1183 /* First make sure that 0 appears as an entry point */
1184 bool found_zero = false;
1185 struct entry_point *entry;
1186 for (entry = span->entry_points.data;
1187 entry < span->entry_points.data +
1188 span->entry_points.size;
1189 entry++) {
1190 if (entry->offset == 0)
1191 found_zero = true;
1193 if (!found_zero) {
1194 struct entry_point *e =
1195 vec_grow(&span->entry_points, 1);
1196 e->label = span->label;
1197 e->name = NULL;
1198 e->offset = 0;
1199 e->symbol = span->symbol;
1202 qsort(span->entry_points.data, span->entry_points.size,
1203 sizeof(*span->entry_points.data),
1204 compare_entry_points);
1209 static bool part_of_reloc(struct supersect *ss, unsigned long addr)
1211 arelent **relocp;
1212 for (relocp = ss->relocs.data;
1213 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
1214 arelent *reloc = *relocp;
1215 if (addr >= reloc->address &&
1216 addr < reloc->address + bfd_get_reloc_size(reloc->howto))
1217 return true;
1219 return false;
1222 static bool nonrelocs_equal(struct span *old_span, struct span *new_span)
1224 int i;
1225 struct supersect *old_ss = old_span->ss, *new_ss = new_span->ss;
1226 if (old_span->contents_size != new_span->contents_size)
1227 return false;
1228 const unsigned char *old = old_ss->contents.data + old_span->start;
1229 const unsigned char *new = new_ss->contents.data + new_span->start;
1230 for (i = 0; i < old_span->contents_size; i++) {
1231 if (old[i] != new[i] &&
1232 !(part_of_reloc(old_ss, i + old_span->start) &&
1233 part_of_reloc(new_ss, i + new_span->start)))
1234 return false;
1236 return true;
1239 bool relocs_equal(struct supersect *old_src_ss, struct supersect *new_src_ss,
1240 arelent *old_reloc, arelent *new_reloc)
1242 struct superbfd *oldsbfd = old_src_ss->parent;
1243 struct superbfd *newsbfd = new_src_ss->parent;
1244 struct span *old_addr_span = find_span(old_src_ss, old_reloc->address);
1245 struct span *new_addr_span = find_span(new_src_ss, new_reloc->address);
1247 if (old_reloc->address - old_addr_span->start !=
1248 new_reloc->address - new_addr_span->start) {
1249 debug1(newsbfd, "Section %s/%s has reloc address mismatch at "
1250 "%lx\n", old_src_ss->name, new_src_ss->name,
1251 (unsigned long)old_reloc->address);
1252 return false;
1255 if (old_reloc->howto != new_reloc->howto) {
1256 debug1(newsbfd, "Section %s/%s has howto type mismatch at "
1257 "%lx\n", old_src_ss->name, new_src_ss->name,
1258 (unsigned long)old_reloc->address);
1259 return false;
1262 if (non_dst_mask(old_src_ss, old_reloc) !=
1263 non_dst_mask(new_src_ss, new_reloc)) {
1264 debug1(newsbfd, "Section %s/%s has contents mismatch at %lx\n",
1265 old_src_ss->name, new_src_ss->name,
1266 (unsigned long)old_reloc->address);
1267 return false;
1270 asymbol *old_sym = *old_reloc->sym_ptr_ptr;
1271 asymbol *new_sym = *new_reloc->sym_ptr_ptr;
1272 asection *old_sect = old_sym->section;
1273 asection *new_sect = new_sym->section;
1275 bfd_vma old_offset = reloc_target_offset(old_src_ss, old_reloc);
1276 bfd_vma new_offset = reloc_target_offset(new_src_ss, new_reloc);
1278 if (bfd_is_und_section(old_sect) || bfd_is_und_section(new_sect)) {
1279 if (!bfd_is_und_section(new_sect) && old_offset != 0 &&
1280 fetch_supersect(newsbfd, new_sect)->type == SS_TYPE_TEXT)
1281 return false;
1283 if (!bfd_is_und_section(old_sect) && new_offset != 0 &&
1284 fetch_supersect(oldsbfd, old_sect)->type == SS_TYPE_TEXT)
1285 return false;
1287 return strcmp(old_sym->name, new_sym->name) == 0 &&
1288 old_offset == new_offset;
1291 if (bfd_is_abs_section(old_sect) && bfd_is_abs_section(new_sect)) {
1292 if (old_sym->value + old_offset == new_sym->value + new_offset)
1293 return true;
1294 debug1(newsbfd, "Differing relocations from %s/%s to ABS "
1295 "section: %lx/%lx\n", old_addr_span->label,
1296 new_addr_span->label,
1297 (unsigned long)(old_sym->value + old_offset),
1298 (unsigned long)(new_sym->value + new_offset));
1299 return false;
1302 if (bfd_is_const_section(old_sect) || bfd_is_const_section(new_sect))
1303 DIE;
1305 struct supersect *old_ss = fetch_supersect(oldsbfd, old_sect);
1306 struct supersect *new_ss = fetch_supersect(newsbfd, new_sect);
1307 struct span *old_span = reloc_target_span(old_src_ss, old_reloc);
1308 struct span *new_span = reloc_target_span(new_src_ss, new_reloc);
1310 if (old_span->match != new_span || new_span->match != old_span) {
1311 debug1(newsbfd, "Nonmatching relocs from %s to %s/%s\n",
1312 new_src_ss->name, old_span->label, new_span->label);
1313 return false;
1316 if (old_sym->value + old_offset - old_span->start !=
1317 new_sym->value + new_offset - new_span->start) {
1318 debug1(newsbfd, "Offsets to %s/%s differ between %s "
1319 "and %s: %lx+%lx/%lx+%lx\n", old_ss->name,
1320 new_ss->name, old_src_ss->name, new_src_ss->name,
1321 (unsigned long)old_sym->value, (unsigned long)old_offset,
1322 (unsigned long)new_sym->value,
1323 (unsigned long)new_offset);
1324 return false;
1327 if ((old_sym->value + old_offset - old_span->start != 0 ||
1328 new_sym->value + new_offset - new_span->start != 0) &&
1329 new_span->patch) {
1330 debug1(newsbfd, "Relocation from %s to nonzero offsets "
1331 "%lx+%lx/%lx+%lx in changed section %s\n",
1332 new_src_ss->name, (unsigned long)old_sym->value,
1333 (unsigned long)old_offset, (unsigned long)new_sym->value,
1334 (unsigned long)new_offset, new_sym->section->name);
1335 return false;
1337 return true;
1340 bool all_relocs_equal(struct span *old_span, struct span *new_span)
1342 struct supersect *old_ss = old_span->ss, *new_ss = new_span->ss;
1343 arelent **old_relocp, **new_relocp;
1345 for (old_relocp = old_ss->relocs.data;
1346 old_relocp < old_ss->relocs.data + old_ss->relocs.size;
1347 old_relocp++) {
1348 if (find_span(old_ss, (*old_relocp)->address) == old_span)
1349 break;
1352 for (new_relocp = new_ss->relocs.data;
1353 new_relocp < new_ss->relocs.data + new_ss->relocs.size;
1354 new_relocp++) {
1355 if (find_span(new_ss, (*new_relocp)->address) == new_span)
1356 break;
1359 for (; old_relocp < old_ss->relocs.data + old_ss->relocs.size &&
1360 find_span(old_ss, (*old_relocp)->address) == old_span &&
1361 new_relocp < new_ss->relocs.data + new_ss->relocs.size &&
1362 find_span(new_ss, (*new_relocp)->address) == new_span;
1363 old_relocp++, new_relocp++) {
1364 if (!relocs_equal(old_ss, new_ss, *old_relocp, *new_relocp))
1365 return false;
1368 if ((old_relocp < old_ss->relocs.data + old_ss->relocs.size &&
1369 find_span(old_ss, (*old_relocp)->address) == old_span) ||
1370 (new_relocp < new_ss->relocs.data + new_ss->relocs.size &&
1371 find_span(new_ss, (*new_relocp)->address) == new_span)) {
1372 debug1(new_ss->parent, "Different reloc count between %s and "
1373 "%s\n", old_span->label, new_span->label);
1374 return false;
1377 return true;
1380 bfd_vma non_dst_mask(struct supersect *ss, arelent *reloc)
1382 int bits = bfd_get_reloc_size(reloc->howto) * 8;
1383 void *address = ss->contents.data + reloc->address;
1384 bfd_vma x = bfd_get(bits, ss->parent->abfd, address);
1385 return x & ~reloc->howto->dst_mask;
1388 void rm_relocs(struct superbfd *isbfd)
1390 asection *p;
1391 for (p = isbfd->abfd->sections; p != NULL; p = p->next) {
1392 struct supersect *ss = fetch_supersect(isbfd, p);
1393 bool remove_relocs = ss->keep;
1395 if (mode("keep") && ss->type == SS_TYPE_SPECIAL)
1396 remove_relocs = false;
1398 if (ss->type == SS_TYPE_KSPLICE ||
1399 ss->type == SS_TYPE_KSPLICE_CALL)
1400 remove_relocs = false;
1401 if (mode("finalize") &&
1402 (strstarts(ss->name, ".ksplice_patches") ||
1403 strstarts(ss->name, ".ksplice_relocs")))
1404 remove_relocs = true;
1406 if (remove_relocs)
1407 rm_some_relocs(ss);
1411 void rm_some_relocs(struct supersect *ss)
1413 struct arelentp_vec orig_relocs;
1414 vec_move(&orig_relocs, &ss->relocs);
1416 arelent **relocp;
1417 for (relocp = orig_relocs.data;
1418 relocp < orig_relocs.data + orig_relocs.size; relocp++) {
1419 bool rm_reloc = false;
1420 asymbol *sym_ptr = *(*relocp)->sym_ptr_ptr;
1422 if (mode("rmsyms") && bfd_is_und_section(sym_ptr->section)) {
1423 asymbol **esymp;
1424 for (esymp = extract_syms.data;
1425 esymp < extract_syms.data + extract_syms.size;
1426 esymp++) {
1427 if (sym_ptr == *esymp) {
1428 rm_reloc = true;
1429 break;
1434 if (mode("keep"))
1435 rm_reloc = true;
1437 if (mode("keep-new-code")) {
1438 if (bfd_is_const_section(sym_ptr->section)) {
1439 rm_reloc = false;
1440 } else {
1441 bfd_vma offset = reloc_target_offset(ss, *relocp);
1442 struct span *target_span =
1443 reloc_target_span(ss, *relocp);
1444 if (target_span->new ||
1445 (target_span->ss->type == SS_TYPE_TEXT &&
1446 sym_ptr->value + offset !=
1447 target_span->start))
1448 rm_reloc = false;
1451 const struct table_section *ts =
1452 get_table_section(ss->name);
1453 if (ts != NULL && ts->has_addr &&
1454 ((*relocp)->address % ts->entry_size ==
1455 ts->addr_offset ||
1456 (*relocp)->address % ts->entry_size ==
1457 ts->other_offset))
1458 rm_reloc = false;
1461 if (mode("finalize") && bfd_is_und_section(sym_ptr->section))
1462 rm_reloc = true;
1464 if (strcmp(sym_ptr->name, "mcount") == 0 &&
1465 bfd_is_und_section(sym_ptr->section))
1466 rm_reloc = false;
1468 if (!find_span(ss, (*relocp)->address)->keep)
1469 rm_reloc = false;
1471 if (rm_reloc)
1472 write_ksplice_reloc(ss, *relocp);
1473 else
1474 *vec_grow(&ss->relocs, 1) = *relocp;
1478 struct supersect *make_section(struct superbfd *sbfd, const char *fmt, ...)
1480 va_list ap;
1481 va_start(ap, fmt);
1482 char *name = vstrprintf(fmt, ap);
1483 va_end(ap);
1485 asection *sect = bfd_get_section_by_name(sbfd->abfd, name);
1486 if (sect != NULL)
1487 return fetch_supersect(sbfd, sect);
1488 else
1489 return new_supersect(sbfd, name);
1492 arelent *create_reloc(struct supersect *ss, const void *addr, asymbol **symp,
1493 bfd_vma offset)
1495 bfd_reloc_code_real_type code;
1496 switch (bfd_arch_bits_per_address(ss->parent->abfd)) {
1497 case 32:
1498 code = BFD_RELOC_32;
1499 break;
1500 case 64:
1501 code = BFD_RELOC_64;
1502 break;
1503 default:
1504 DIE;
1507 arelent *reloc = malloc(sizeof(*reloc));
1508 reloc->sym_ptr_ptr = symp;
1509 reloc->address = addr_offset(ss, addr);
1510 reloc->howto = bfd_reloc_type_lookup(ss->parent->abfd, code);
1511 reloc->addend = offset;
1512 return reloc;
1515 void write_reloc(struct supersect *ss, const void *addr, asymbol **symp,
1516 bfd_vma offset)
1518 *vec_grow(&ss->new_relocs, 1) = create_reloc(ss, addr, symp, offset);
1521 void write_string(struct supersect *ss, const char **addr, const char *fmt, ...)
1523 va_list ap;
1524 struct supersect *str_ss = make_section(ss->parent, ".ksplice_str");
1525 char *str;
1526 va_start(ap, fmt);
1527 int len = vasprintf(&str, fmt, ap);
1528 assert(len >= 0);
1529 va_end(ap);
1531 unsigned long *str_offp = ulong_hash_lookup(&ksplice_string_offset, str,
1532 FALSE);
1533 if (str_offp == NULL) {
1534 char *buf = sect_grow(str_ss, len + 1, char);
1535 memcpy(buf, str, len + 1);
1536 str_offp = ulong_hash_lookup(&ksplice_string_offset, str, TRUE);
1537 *str_offp = addr_offset(str_ss, buf);
1540 write_reloc(ss, addr, &str_ss->symbol, *str_offp);
1543 void lookup_system_map(struct addr_vec *addrs, const char *name, long offset)
1545 struct addr_vec *map_addrs =
1546 addr_vec_hash_lookup(&system_map, name, FALSE);
1547 if (map_addrs == NULL)
1548 return;
1550 unsigned long *addr, *map_addr;
1551 for (map_addr = map_addrs->data;
1552 map_addr < map_addrs->data + map_addrs->size; map_addr++) {
1553 for (addr = addrs->data; addr < addrs->data + addrs->size;
1554 addr++) {
1555 if (*addr == *map_addr + offset)
1556 break;
1558 if (addr < addrs->data + addrs->size)
1559 continue;
1560 *vec_grow(addrs, 1) = *map_addr + offset;
1564 void compute_system_map_array(struct superbfd *sbfd, struct addr_vec *addrs,
1565 asymbol *sym)
1567 if (bfd_is_abs_section(sym->section)) {
1568 *vec_grow(addrs, 1) = sym->value;
1569 } else if (bfd_is_und_section(sym->section)) {
1570 lookup_system_map(addrs, sym->name, 0);
1571 } else if (!bfd_is_const_section(sym->section)) {
1572 asymbol **gsymp;
1573 for (gsymp = sbfd->syms.data;
1574 gsymp < sbfd->syms.data + sbfd->syms.size; gsymp++) {
1575 asymbol *gsym = *gsymp;
1576 if ((gsym->flags & BSF_DEBUGGING) == 0 &&
1577 gsym->section == sym->section)
1578 lookup_system_map(addrs, gsym->name,
1579 sym->value - gsym->value);
1584 void write_ksplice_system_map(struct superbfd *sbfd, asymbol *sym,
1585 const char *label)
1587 bool *done = bool_hash_lookup(&system_map_written, label, TRUE);
1588 if (*done)
1589 return;
1590 *done = true;
1592 struct addr_vec addrs;
1593 vec_init(&addrs);
1595 compute_system_map_array(sbfd, &addrs, sym);
1596 if (addrs.size != 0) {
1597 struct supersect *smap_ss =
1598 make_section(sbfd, ".ksplice_system_map");
1599 struct ksplice_system_map *smap =
1600 sect_grow(smap_ss, 1, struct ksplice_system_map);
1601 write_string(smap_ss, &smap->label, "%s", label);
1603 struct supersect *array_ss = make_section(sbfd,
1604 ".ksplice_array");
1605 void *buf = sect_grow(array_ss, addrs.size,
1606 typeof(*addrs.data));
1607 memcpy(buf, addrs.data, addrs.size * sizeof(*addrs.data));
1608 smap->nr_candidates = addrs.size;
1609 write_reloc(smap_ss, &smap->candidates, &array_ss->symbol,
1610 addr_offset(array_ss, buf));
1612 vec_free(&addrs);
1615 void write_ksplice_symbol_backend(struct supersect *ss,
1616 struct ksplice_symbol *const *addr,
1617 asymbol *sym, const char *label,
1618 const char *name)
1620 struct supersect *ksymbol_ss = make_section(ss->parent,
1621 ".ksplice_symbols");
1622 struct ksplice_symbol *ksymbol;
1623 unsigned long *ksymbol_offp;
1625 ksymbol_offp = ulong_hash_lookup(&ksplice_symbol_offset, label, FALSE);
1626 if (ksymbol_offp != NULL) {
1627 write_reloc(ss, addr, &ksymbol_ss->symbol, *ksymbol_offp);
1628 return;
1630 ksymbol = sect_grow(ksymbol_ss, 1, struct ksplice_symbol);
1631 ksymbol_offp = ulong_hash_lookup(&ksplice_symbol_offset, label, TRUE);
1632 *ksymbol_offp = addr_offset(ksymbol_ss, ksymbol);
1634 write_reloc(ss, addr, &ksymbol_ss->symbol, *ksymbol_offp);
1635 write_string(ksymbol_ss, &ksymbol->label, "%s", label);
1636 if (name != NULL) {
1637 write_string(ksymbol_ss, &ksymbol->name, "%s", name);
1638 write_ksplice_system_map(ksymbol_ss->parent, sym, label);
1642 void write_ksplice_symbol(struct supersect *ss,
1643 struct ksplice_symbol *const *addr,
1644 asymbol *sym, struct span *span,
1645 const char *addstr_sect)
1647 const char *label, *name;
1648 if (span != NULL && span->start != 0)
1649 label = span->label;
1650 else
1651 label = label_lookup(ss->parent, sym);
1653 asymbol *gsym = canonical_symbol(ss->parent, sym);
1654 if (strcmp(addstr_sect, "") != 0)
1655 name = NULL;
1656 else if (bfd_is_und_section(sym->section))
1657 name = sym->name;
1658 else if (bfd_is_const_section(sym->section))
1659 name = NULL;
1660 else if (span != NULL && span->symbol == NULL)
1661 name = NULL;
1662 else if (gsym == NULL || (gsym->flags & BSF_SECTION_SYM) != 0)
1663 name = NULL;
1664 else
1665 name = gsym->name;
1667 write_ksplice_symbol_backend(ss, addr, sym,
1668 strprintf("%s%s", addstr_sect, label),
1669 name);
1672 void write_ksplice_reloc(struct supersect *ss, arelent *orig_reloc)
1674 asymbol *sym_ptr = *orig_reloc->sym_ptr_ptr;
1675 bfd_vma reloc_addend = reloc_offset(ss, orig_reloc);
1676 bfd_vma target_addend = reloc_target_offset(ss, orig_reloc);
1677 unsigned long *repladdr = ss->contents.data + orig_reloc->address;
1679 if (mode("finalize") && strstarts(ss->name, ".ksplice_patches")) {
1680 *repladdr = 0;
1681 return;
1683 if (mode("finalize") && strstarts(ss->name, ".ksplice_relocs")) {
1684 assert(strstarts(sym_ptr->name, KSPLICE_SYMBOL_STR));
1685 asymbol fake_sym;
1686 fake_sym.name = sym_ptr->name + strlen(KSPLICE_SYMBOL_STR);
1687 fake_sym.section = bfd_und_section_ptr;
1688 fake_sym.value = 0;
1689 fake_sym.flags = 0;
1691 write_ksplice_symbol_backend
1692 (ss, (struct ksplice_symbol **)repladdr, &fake_sym,
1693 fake_sym.name, fake_sym.name);
1694 return;
1697 struct span *span = reloc_target_span(ss, orig_reloc);
1698 if (span == ss->spans.data && span->start != target_addend)
1699 span = NULL;
1700 write_canary(ss, orig_reloc->address,
1701 bfd_get_reloc_size(orig_reloc->howto),
1702 orig_reloc->howto->dst_mask);
1704 struct supersect *kreloc_ss =
1705 make_section(ss->parent, ".ksplice_relocs%s", ss->name);
1706 struct ksplice_reloc *kreloc = sect_grow(kreloc_ss, 1,
1707 struct ksplice_reloc);
1709 struct span *address_span = find_span(ss, orig_reloc->address);
1710 write_reloc(kreloc_ss, &kreloc->blank_addr,
1711 &ss->symbol, orig_reloc->address + address_span->shift);
1712 if (bfd_is_und_section(sym_ptr->section) && mode("keep")) {
1713 char *name = strprintf(KSPLICE_SYMBOL_STR "%s", sym_ptr->name);
1714 asymbol **symp = make_undefined_symbolp(ss->parent, name);
1715 write_reloc(kreloc_ss, &kreloc->symbol, symp, 0);
1716 } else {
1717 write_ksplice_symbol(kreloc_ss, &kreloc->symbol, sym_ptr, span,
1718 "");
1720 if (span != NULL && span->start != 0) {
1721 reloc_addend += sym_ptr->value - span->start;
1722 target_addend += sym_ptr->value - span->start;
1724 kreloc->insn_addend = reloc_addend - target_addend;
1725 kreloc->target_addend = target_addend;
1726 write_ksplice_reloc_howto(kreloc_ss, &kreloc->howto, orig_reloc->howto,
1727 KSPLICE_HOWTO_RELOC);
1730 static void write_ksplice_reloc_howto(struct supersect *ss, const
1731 struct ksplice_reloc_howto *const *addr,
1732 reloc_howto_type *howto,
1733 enum ksplice_reloc_howto_type type)
1735 struct supersect *khowto_ss = make_section(ss->parent,
1736 ".ksplice_reloc_howtos");
1737 struct ksplice_reloc_howto *khowto;
1738 unsigned long *khowto_offp;
1740 khowto_offp = ulong_hash_lookup(&ksplice_howto_offset, howto->name,
1741 FALSE);
1742 if (khowto_offp != NULL) {
1743 write_reloc(ss, addr, &khowto_ss->symbol, *khowto_offp);
1744 return;
1746 khowto = sect_grow(khowto_ss, 1, struct ksplice_reloc_howto);
1747 khowto_offp = ulong_hash_lookup(&ksplice_howto_offset, howto->name,
1748 TRUE);
1749 *khowto_offp = addr_offset(khowto_ss, khowto);
1751 khowto->type = type;
1752 khowto->pcrel = howto->pc_relative;
1753 khowto->size = bfd_get_reloc_size(howto);
1754 khowto->dst_mask = howto->dst_mask;
1755 khowto->rightshift = howto->rightshift;
1756 khowto->signed_addend =
1757 (howto->complain_on_overflow == complain_overflow_signed) ||
1758 (howto->complain_on_overflow == complain_overflow_bitfield);
1759 write_reloc(ss, addr, &khowto_ss->symbol, *khowto_offp);
1762 #define CANARY(x, canary) ((x & ~howto->dst_mask) | (canary & howto->dst_mask))
1764 void write_canary(struct supersect *ss, int offset, bfd_size_type size,
1765 bfd_vma dst_mask)
1767 int bits = size * 8;
1768 void *address = ss->contents.data + offset;
1769 bfd_vma x = bfd_get(bits, ss->parent->abfd, address);
1770 x = (x & ~dst_mask) | ((bfd_vma)KSPLICE_CANARY & dst_mask);
1771 bfd_put(bits, ss->parent->abfd, x, address);
1774 static void write_date_relocs(struct superbfd *sbfd, const char *str,
1775 enum ksplice_reloc_howto_type type)
1777 asection *sect;
1778 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
1779 struct supersect *ss = fetch_supersect(sbfd, sect);
1780 if (ss->type != SS_TYPE_STRING && ss->type != SS_TYPE_RODATA)
1781 continue;
1782 void *ptr;
1783 struct span *span;
1784 for (span = ss->spans.data;
1785 span < ss->spans.data + ss->spans.size; span++) {
1786 if (!span->keep)
1787 continue;
1788 for (ptr = ss->contents.data + span->start;
1789 ptr + strlen(str) < ss->contents.data +
1790 span->start + span->contents_size; ptr++) {
1791 if (strcmp((const char *)ptr, str) == 0)
1792 write_ksplice_date_reloc
1793 (ss, addr_offset(ss, ptr), str,
1794 type);
1800 static void write_ksplice_date_reloc(struct supersect *ss, unsigned long offset,
1801 const char *str,
1802 enum ksplice_reloc_howto_type type)
1804 struct supersect *kreloc_ss;
1805 kreloc_ss = make_section(ss->parent, ".ksplice_relocs%s", ss->name);
1806 struct ksplice_reloc *kreloc = sect_grow(kreloc_ss, 1,
1807 struct ksplice_reloc);
1809 const char *filename = ss->parent->abfd->filename;
1810 char *c = strstr(filename, ".KSPLICE");
1811 int flen = (c == NULL ? strlen(filename) : c - filename);
1813 write_ksplice_symbol_backend(kreloc_ss, &kreloc->symbol, NULL,
1814 strprintf("%s<%.*s>", str, flen, filename),
1815 NULL);
1817 struct span *span = find_span(ss, offset);
1818 write_reloc(kreloc_ss, &kreloc->blank_addr, &ss->symbol,
1819 offset + span->shift);
1820 write_ksplice_nonreloc_howto(kreloc_ss, &kreloc->howto, type,
1821 strlen(str));
1824 static void write_table_relocs(struct superbfd *sbfd, const char *sectname,
1825 enum ksplice_reloc_howto_type type)
1827 asection *sect = bfd_get_section_by_name(sbfd->abfd, sectname);
1828 if (sect == NULL)
1829 return;
1830 struct supersect *ss = fetch_supersect(sbfd, sect);
1832 const struct table_section *s = get_table_section(sectname);
1833 if (s == NULL)
1834 DIE;
1836 void *entry;
1837 for (entry = ss->contents.data;
1838 entry < ss->contents.data + ss->contents.size;
1839 entry += s->entry_size) {
1840 struct span *span = find_span(ss, addr_offset(ss, entry));
1841 assert(span != NULL);
1842 if (!span->keep)
1843 continue;
1845 arelent *reloc = find_reloc(ss, entry + s->addr_offset);
1846 assert(reloc != NULL);
1847 asymbol *sym = *reloc->sym_ptr_ptr;
1848 assert(!bfd_is_const_section(sym->section));
1849 struct supersect *sym_ss = fetch_supersect(sbfd, sym->section);
1850 unsigned long addr = sym->value +
1851 reloc_target_offset(ss, reloc);
1852 write_ksplice_table_reloc(sym_ss, addr, span->label, type);
1856 static void write_ksplice_table_reloc(struct supersect *ss,
1857 unsigned long address,
1858 const char *label,
1859 enum ksplice_reloc_howto_type type)
1861 struct supersect *kreloc_ss;
1862 kreloc_ss = make_section(ss->parent, ".ksplice_relocs%s", ss->name);
1863 struct ksplice_reloc *kreloc = sect_grow(kreloc_ss, 1,
1864 struct ksplice_reloc);
1865 struct span *span = find_span(ss, address);
1866 assert(span != NULL);
1868 write_ksplice_symbol_backend(kreloc_ss, &kreloc->symbol, NULL,
1869 label, NULL);
1870 write_reloc(kreloc_ss, &kreloc->blank_addr, &ss->symbol,
1871 address + span->shift);
1872 write_ksplice_nonreloc_howto(kreloc_ss, &kreloc->howto, type, 0);
1875 static void write_ksplice_nonreloc_howto(struct supersect *ss,
1876 const struct ksplice_reloc_howto
1877 *const *addr,
1878 enum ksplice_reloc_howto_type type,
1879 int size)
1881 struct supersect *khowto_ss =
1882 make_section(ss->parent, ".ksplice_reloc_howtos");
1883 struct ksplice_reloc_howto *khowto =
1884 sect_grow(khowto_ss, 1, struct ksplice_reloc_howto);
1886 khowto->type = type;
1887 khowto->size = size;
1888 khowto->pcrel = 0;
1889 khowto->dst_mask = 0;
1890 khowto->rightshift = 0;
1891 khowto->signed_addend = 0;
1892 write_reloc(ss, addr, &khowto_ss->symbol,
1893 addr_offset(khowto_ss, khowto));
1896 static void write_ksplice_symbol_reloc(struct supersect *ss,
1897 const char *sectname,
1898 unsigned long *addr, asymbol *sym,
1899 const char *label, const char *name)
1901 struct supersect *kreloc_ss;
1902 kreloc_ss = make_section(ss->parent, ".ksplice_relocs%s", sectname);
1903 struct ksplice_reloc *kreloc = sect_grow(kreloc_ss, 1,
1904 struct ksplice_reloc);
1906 write_ksplice_symbol_backend(kreloc_ss, &kreloc->symbol, sym, label,
1907 name);
1908 write_reloc(kreloc_ss, &kreloc->blank_addr, &ss->symbol,
1909 addr_offset(ss, addr));
1910 write_ksplice_nonreloc_howto(kreloc_ss, &kreloc->howto,
1911 KSPLICE_HOWTO_SYMBOL, 0);
1914 static void write_ksplice_section(struct span *span)
1916 struct supersect *ss = span->ss;
1917 const char *sectname = span->ss->name;
1918 const struct table_section *ts = get_table_section(ss->name);
1920 if (ts != NULL && ts->has_addr) {
1921 arelent *reloc = find_reloc(ss, ss->contents.data + span->start
1922 + ts->addr_offset);
1923 assert(reloc != NULL);
1924 asymbol *rsym = *reloc->sym_ptr_ptr;
1925 assert(!bfd_is_const_section(rsym->section));
1926 sectname = rsym->section->name;
1929 struct supersect *ksect_ss =
1930 make_section(ss->parent, ".ksplice_sections%s", sectname);
1931 struct ksplice_section *ksect = sect_grow(ksect_ss, 1,
1932 struct ksplice_section);
1933 asymbol *sym = span->symbol == NULL ? ss->symbol : span->symbol;
1935 write_ksplice_symbol(ksect_ss, &ksect->symbol, sym, span,
1936 mode("keep-new-code") ? "(post)" : "");
1937 ksect->size = span->size;
1938 ksect->flags = 0;
1940 if (ss->type == SS_TYPE_RODATA || ss->type == SS_TYPE_STRING ||
1941 ss->type == SS_TYPE_EXPORT || ss->type == SS_TYPE_BUGTABLE)
1942 ksect->flags |= KSPLICE_SECTION_RODATA;
1943 if (ss->type == SS_TYPE_DATA)
1944 ksect->flags |= KSPLICE_SECTION_DATA;
1945 if (ss->type == SS_TYPE_TEXT)
1946 ksect->flags |= KSPLICE_SECTION_TEXT;
1947 assert(ksect->flags != 0);
1949 if (ss->type == SS_TYPE_STRING)
1950 ksect->flags |= KSPLICE_SECTION_STRING;
1951 if (ss->match_data_early)
1952 ksect->flags |= KSPLICE_SECTION_MATCH_DATA_EARLY;
1954 write_reloc(ksect_ss, &ksect->address, &ss->symbol,
1955 span->start + span->shift);
1957 if (mode("keep-old-code")) {
1958 /* Write ksplice_symbols for all the entry points */
1959 struct entry_point *entry;
1960 for (entry = span->entry_points.data;
1961 entry < span->entry_points.data + span->entry_points.size;
1962 entry++)
1963 write_ksplice_symbol_reloc
1964 (span->ss, sectname, span->ss->contents.data +
1965 span->start + span->shift + entry->offset,
1966 entry->symbol, entry->label, entry->name);
1970 static void write_ksplice_patch_reloc(struct supersect *ss,
1971 const char *sectname, unsigned long *addr,
1972 bfd_size_type size, const char *label,
1973 long addend)
1975 struct supersect *kreloc_ss;
1976 kreloc_ss = make_section(ss->parent, ".ksplice_relocs%s", sectname);
1977 struct ksplice_reloc *kreloc = sect_grow(kreloc_ss, 1,
1978 struct ksplice_reloc);
1980 write_canary(ss, addr_offset(ss, addr), size, -1);
1981 write_ksplice_symbol_backend(kreloc_ss, &kreloc->symbol, NULL,
1982 label, NULL);
1983 write_reloc(kreloc_ss, &kreloc->blank_addr, &ss->symbol,
1984 addr_offset(ss, addr));
1985 reloc_howto_type *howto =
1986 bfd_reloc_type_lookup(ss->parent->abfd,
1987 PASTE(BFD_RELOC_, LONG_BIT));
1988 write_ksplice_reloc_howto(kreloc_ss, &kreloc->howto, howto,
1989 KSPLICE_HOWTO_RELOC);
1990 kreloc->target_addend = addend;
1991 kreloc->insn_addend = 0;
1994 /* Assumes symbol is global, aka only one symbol of that name */
1995 static asymbol *name_to_symbol(struct superbfd *sbfd, const char *name)
1997 if (name == NULL)
1998 return NULL;
2000 asymbol **symp;
2001 for (symp = sbfd->syms.data;
2002 symp < sbfd->syms.data + sbfd->syms.size; symp++) {
2003 asymbol *sym = *symp;
2004 if (strcmp(name, sym->name) == 0 &&
2005 ((sym->flags & BSF_GLOBAL) != 0 ||
2006 bfd_is_und_section(sym->section)))
2007 return sym;
2009 return NULL;
2012 void write_ksplice_patches(struct superbfd *sbfd, struct span *span)
2014 if (span->datapatch) {
2015 write_ksplice_patch(sbfd, span, span->label, 0);
2016 return;
2019 assert(span->patch);
2021 long prev_offset = LONG_MIN;
2022 asymbol *prev_sym = NULL;
2023 const char *prev_label = NULL;
2024 struct entry_point *entry;
2025 for (entry = span->pre_entry_points.data;
2026 entry < span->pre_entry_points.data + span->pre_entry_points.size;
2027 entry++) {
2028 asymbol *sym = name_to_symbol(sbfd, entry->name);
2029 if (sym == NULL && entry->offset != 0) {
2030 /* Since it was global, name and label are the same */
2031 write_ksplice_deleted_patch
2032 (sbfd, entry->label, entry->label, span->ss->name,
2033 entry->offset);
2034 } else if (entry->offset != prev_offset) {
2035 debug1(sbfd, "entry point: %s(%s) %lx\n", entry->label,
2036 entry->name, entry->offset);
2038 if (prev_offset + MAX_TRAMPOLINE_SIZE > entry->offset) {
2039 err(sbfd,
2040 "Overlapping trampolines: %s %lx/%lx\n",
2041 span->label, prev_offset, entry->offset);
2042 DIE;
2045 long target_offset = 0;
2046 if (sym != NULL)
2047 target_offset = sym->value - span->start;
2048 write_ksplice_patch(sbfd, span, entry->label,
2049 target_offset);
2050 prev_offset = entry->offset;
2051 prev_sym = NULL;
2054 if (prev_sym == NULL) {
2055 prev_sym = sym;
2056 prev_label = entry->label;
2057 } else if (sym != NULL &&
2058 (prev_sym->section != sym->section ||
2059 prev_sym->value != sym->value)) {
2060 err(sbfd, "Splitting global symbols in the middle of a "
2061 "span: %s+%lx != %s+%lx!\n",
2062 prev_label, (unsigned long)prev_sym->value,
2063 entry->label, (unsigned long)sym->value);
2064 DIE;
2068 if (prev_offset + MAX_TRAMPOLINE_SIZE > span->size) {
2069 err(sbfd, "Trampoline ends outside span: %s %lx/%lx\n",
2070 span->label, prev_offset, (unsigned long)span->size);
2071 DIE;
2075 void write_ksplice_patch(struct superbfd *sbfd, struct span *span,
2076 const char *label, long offset)
2078 struct supersect *kpatch_ss =
2079 make_section(sbfd, ".ksplice_patches%s", span->ss->name);
2080 struct ksplice_patch *kpatch = sect_grow(kpatch_ss, 1,
2081 struct ksplice_patch);
2083 write_ksplice_patch_reloc(kpatch_ss, span->ss->name, &kpatch->oldaddr,
2084 sizeof(kpatch->oldaddr), label, 0);
2085 if (span->ss->type == SS_TYPE_TEXT) {
2086 kpatch->type = KSPLICE_PATCH_TEXT;
2087 write_patch_storage(kpatch_ss, kpatch, MAX_TRAMPOLINE_SIZE,
2088 NULL);
2089 } else {
2090 kpatch->type = KSPLICE_PATCH_DATA;
2091 kpatch->size = span->contents_size;
2092 struct supersect *data_ss =
2093 make_section(sbfd, ".ksplice_patch_data");
2094 write_reloc(kpatch_ss, &kpatch->contents, &span->ss->symbol,
2095 span->start + span->shift);
2096 char *saved = sect_do_grow(data_ss, 1, span->contents_size, 1);
2097 write_reloc(kpatch_ss, &kpatch->saved, &data_ss->symbol,
2098 addr_offset(data_ss, saved));
2100 write_reloc(kpatch_ss, &kpatch->repladdr, &span->ss->symbol,
2101 span->start + span->shift + offset);
2104 asymbol **make_undefined_symbolp(struct superbfd *sbfd, const char *name)
2106 asymbol **symp;
2107 for (symp = sbfd->syms.data; symp < sbfd->syms.data + sbfd->syms.size;
2108 symp++) {
2109 asymbol *sym = *symp;
2110 if (strcmp(name, sym->name) == 0 &&
2111 bfd_is_und_section(sym->section))
2112 return symp;
2114 asymbol ***sympp;
2115 for (sympp = sbfd->new_syms.data;
2116 sympp < sbfd->new_syms.data + sbfd->new_syms.size; sympp++) {
2117 asymbol **symp = *sympp;
2118 asymbol *sym = *symp;
2119 if (strcmp(name, sym->name) == 0 &&
2120 bfd_is_und_section(sym->section))
2121 return symp;
2124 symp = malloc(sizeof(*symp));
2125 *symp = bfd_make_empty_symbol(sbfd->abfd);
2126 asymbol *sym = *symp;
2127 sym->name = name;
2128 sym->section = bfd_und_section_ptr;
2129 sym->flags = 0;
2130 sym->value = 0;
2131 *vec_grow(&sbfd->new_syms, 1) = symp;
2132 return symp;
2135 void write_ksplice_deleted_patch(struct superbfd *sbfd, const char *name,
2136 const char *label, const char *sectname,
2137 long offset)
2139 struct supersect *kpatch_ss =
2140 make_section(sbfd, ".ksplice_patches%s", sectname);
2141 struct ksplice_patch *kpatch = sect_grow(kpatch_ss, 1,
2142 struct ksplice_patch);
2144 write_ksplice_patch_reloc(kpatch_ss, sectname, &kpatch->oldaddr,
2145 sizeof(kpatch->oldaddr), label, 0);
2146 kpatch->type = KSPLICE_PATCH_TEXT;
2147 asymbol **symp = make_undefined_symbolp(sbfd, strdup(name));
2148 write_reloc(kpatch_ss, &kpatch->repladdr, symp, offset);
2149 write_patch_storage(kpatch_ss, kpatch, MAX_TRAMPOLINE_SIZE, NULL);
2152 void write_ksplice_export(struct superbfd *sbfd, struct span *span, bool del)
2154 struct supersect *kpatch_ss = make_section(sbfd, ".ksplice_patches");
2155 struct ksplice_patch *kpatch = sect_grow(kpatch_ss, 1,
2156 struct ksplice_patch);
2157 struct supersect *data_ss;
2159 const struct table_section *ts = get_table_section(span->ss->name);
2160 assert(ts != NULL);
2161 const char **addr =
2162 span->ss->contents.data + span->start + ts->other_offset;
2163 const char *symname = read_string(span->ss, addr);
2165 char *oldname, *newname;
2166 if (del) {
2167 oldname = strprintf("%s:%s", span->ss->name, symname);
2168 newname = strprintf("DISABLED_%s_%s", symname, kid);
2169 } else {
2170 oldname = strprintf("%s:DISABLED_%s_%s", span->ss->name,
2171 symname, kid);
2172 newname = strprintf("%s", symname);
2173 write_string(span->ss, addr, "DISABLED_%s_%s", symname, kid);
2176 write_ksplice_patch_reloc(kpatch_ss, "", &kpatch->oldaddr,
2177 sizeof(kpatch->oldaddr), oldname,
2178 ts->other_offset);
2179 kpatch->type = KSPLICE_PATCH_EXPORT;
2180 const char **namep = write_patch_storage(kpatch_ss, kpatch,
2181 sizeof(newname), &data_ss);
2182 write_string(data_ss, namep, "%s", newname);
2185 void filter_table_sections(struct superbfd *isbfd)
2187 struct supersect *tables_ss =
2188 fetch_supersect(offsets_sbfd,
2189 bfd_get_section_by_name(offsets_sbfd->abfd,
2190 ".ksplice_table_sections"));
2191 const struct table_section *ts;
2192 for (ts = tables_ss->contents.data;
2193 (void *)ts < tables_ss->contents.data + tables_ss->contents.size;
2194 ts++) {
2195 struct table_section s = *ts;
2196 s.sect = read_string(tables_ss, &ts->sect);
2197 s.other_sect = read_string(tables_ss, &ts->other_sect);
2198 s.crc_sect = read_string(tables_ss, &ts->crc_sect);
2199 filter_table_section(isbfd, &s);
2203 void filter_table_section(struct superbfd *sbfd, const struct table_section *s)
2205 asection *isection = bfd_get_section_by_name(sbfd->abfd, s->sect);
2206 if (isection == NULL)
2207 return;
2208 struct supersect *ss = fetch_supersect(sbfd, isection);
2210 void *entry;
2211 for (entry = ss->contents.data;
2212 entry < ss->contents.data + ss->contents.size;
2213 entry += s->entry_size) {
2214 struct span *span = find_span(ss, addr_offset(ss, entry));
2215 assert(span != NULL);
2217 if (s->has_addr) {
2218 struct span *sym_span =
2219 span_offset_target_span(span, s->addr_offset);
2220 assert(sym_span != NULL);
2221 if (sym_span->keep)
2222 keep_span(span);
2225 if (s->other_sect != NULL) {
2226 struct span *sym_span =
2227 span_offset_target_span(span, s->other_offset);
2228 assert(sym_span != NULL);
2229 if (span->keep)
2230 keep_span(sym_span);
2233 if (s->crc_sect != NULL) {
2234 struct span *crc_span = get_crc_span(span, s);
2235 assert(crc_span != NULL);
2236 if (span->keep && mode("keep-new-code"))
2237 keep_span(crc_span);
2242 static void match_other_spans(struct span *old_span, struct span *new_span)
2244 const struct table_section *ts = get_table_section(old_span->ss->name);
2245 if (ts == NULL)
2246 return;
2248 if (old_span->match == new_span && new_span->match == old_span &&
2249 ts->other_sect != NULL) {
2250 void *old_entry = old_span->ss->contents.data + old_span->start;
2251 void *new_entry = new_span->ss->contents.data + new_span->start;
2252 arelent *old_reloc =
2253 find_reloc(old_span->ss, old_entry + ts->other_offset);
2254 arelent *new_reloc =
2255 find_reloc(new_span->ss, new_entry + ts->other_offset);
2256 assert(old_reloc != NULL && new_reloc != NULL);
2257 struct span *old_other_span =
2258 reloc_target_span(old_span->ss, old_reloc);
2259 struct span *new_other_span =
2260 reloc_target_span(new_span->ss, new_reloc);
2261 assert(old_other_span != NULL && new_other_span != NULL);
2262 match_spans(old_other_span, new_other_span);
2266 static void match_table_spans(struct span *old_span, struct span *new_span)
2268 const struct table_section *ts = get_table_section(old_span->ss->name);
2270 if (strcmp(old_span->ss->name, new_span->ss->name) != 0)
2271 return;
2272 if (ts == NULL || old_span->ss->type != SS_TYPE_SPECIAL ||
2273 new_span->ss->type != SS_TYPE_SPECIAL)
2274 return;
2275 if (old_span->match != NULL || new_span->match != NULL)
2276 return;
2278 if (ts->has_addr) {
2279 void *old_entry = old_span->ss->contents.data + old_span->start;
2280 void *new_entry = new_span->ss->contents.data + new_span->start;
2281 arelent *old_reloc =
2282 find_reloc(old_span->ss, old_entry + ts->addr_offset);
2283 arelent *new_reloc =
2284 find_reloc(new_span->ss, new_entry + ts->addr_offset);
2285 assert(old_reloc != NULL && new_reloc != NULL);
2286 struct span *old_sym_span =
2287 reloc_target_span(old_span->ss, old_reloc);
2288 struct span *new_sym_span =
2289 reloc_target_span(new_span->ss, new_reloc);
2290 assert(old_sym_span != NULL && new_sym_span != NULL);
2291 if (old_sym_span->match == new_sym_span &&
2292 new_sym_span->match == old_sym_span &&
2293 old_reloc->address - old_sym_span->start ==
2294 new_reloc->address - new_sym_span->start)
2295 match_spans(old_span, new_span);
2299 static struct span *get_crc_span(struct span *span,
2300 const struct table_section *ts)
2302 void *entry = span->ss->contents.data + span->start;
2303 asection *crc_sect = bfd_get_section_by_name(span->ss->parent->abfd,
2304 ts->crc_sect);
2305 if (crc_sect == NULL)
2306 return NULL;
2307 struct supersect *crc_ss = fetch_supersect(span->ss->parent, crc_sect);
2308 if (crc_ss == NULL)
2309 return NULL;
2310 struct span *crc_span = find_span(crc_ss, addr_offset(span->ss, entry) /
2311 ts->entry_size * ts->crc_size);
2312 return crc_span;
2315 void mark_precallable_spans(struct superbfd *sbfd)
2317 asection *sect;
2318 struct supersect *ss, *sym_ss;
2319 struct span *address_span, *target_span;
2320 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2321 ss = fetch_supersect(sbfd, sect);
2322 arelent **relocp;
2323 if (ss->type == SS_TYPE_SPECIAL)
2324 continue;
2325 for (relocp = ss->relocs.data;
2326 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
2327 asymbol *sym = *(*relocp)->sym_ptr_ptr;
2328 address_span = find_span(ss, (*relocp)->address);
2329 if (!address_span->precallable)
2330 continue;
2331 target_span = reloc_target_span(ss, *relocp);
2332 if (target_span == NULL || target_span->keep)
2333 continue;
2334 sym_ss = fetch_supersect(sbfd, sym->section);
2335 if (sym_ss->type == SS_TYPE_IGNORED)
2336 continue;
2337 target_span->precallable = true;
2338 changed = true;
2343 void keep_referenced_sections(struct superbfd *sbfd)
2345 asection *sect;
2346 struct supersect *ss, *sym_ss;
2347 struct span *address_span, *target_span;
2348 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2349 ss = fetch_supersect(sbfd, sect);
2350 arelent **relocp;
2351 if (ss->type == SS_TYPE_SPECIAL)
2352 continue;
2353 for (relocp = ss->relocs.data;
2354 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
2355 asymbol *sym = *(*relocp)->sym_ptr_ptr;
2356 address_span = find_span(ss, (*relocp)->address);
2357 if (!address_span->keep)
2358 continue;
2359 target_span = reloc_target_span(ss, *relocp);
2360 if (target_span == NULL || target_span->keep)
2361 continue;
2362 sym_ss = fetch_supersect(sbfd, sym->section);
2363 if (sym_ss->type == SS_TYPE_IGNORED)
2364 continue;
2365 keep_span(target_span);
2366 changed = true;
2371 void copy_symbols(struct asymbolp_vec *osyms, struct asymbolpp_vec *isyms)
2373 asymbol ***sympp;
2374 for (sympp = isyms->data; sympp < isyms->data + isyms->size; sympp++)
2375 *vec_grow(osyms, 1) = **sympp;
2378 /* Modified function from GNU Binutils objcopy.c */
2379 bfd_boolean copy_object(bfd *ibfd, bfd *obfd)
2381 assert(bfd_set_format(obfd, bfd_get_format(ibfd)));
2383 bfd_vma start = bfd_get_start_address(ibfd);
2385 flagword flags = bfd_get_file_flags(ibfd);
2386 flags &= bfd_applicable_file_flags(obfd);
2388 assert(bfd_set_start_address(obfd, start)
2389 && bfd_set_file_flags(obfd, flags));
2391 enum bfd_architecture iarch = bfd_get_arch(ibfd);
2392 unsigned int imach = bfd_get_mach(ibfd);
2393 assert(bfd_set_arch_mach(obfd, iarch, imach));
2394 assert(bfd_set_format(obfd, bfd_get_format(ibfd)));
2396 /* BFD mandates that all output sections be created and sizes set before
2397 any output is done. Thus, we traverse all sections multiple times. */
2398 bfd_map_over_sections(ibfd, setup_section, obfd);
2400 struct supersect *new_supersects = fetch_superbfd(ibfd)->new_supersects;
2401 struct supersect *ss;
2402 for (ss = new_supersects; ss != NULL; ss = ss->next)
2403 setup_new_section(obfd, ss);
2405 /* Mark symbols used in output relocations so that they
2406 are kept, even if they are local labels or static symbols.
2408 Note we iterate over the input sections examining their
2409 relocations since the relocations for the output sections
2410 haven't been set yet. mark_symbols_used_in_relocations will
2411 ignore input sections which have no corresponding output
2412 section. */
2414 bfd_map_over_sections(ibfd, mark_symbols_used_in_relocations, NULL);
2415 for (ss = new_supersects; ss != NULL; ss = ss->next)
2416 ss_mark_symbols_used_in_relocations(ss);
2417 struct asymbolp_vec osyms;
2418 vec_init(&osyms);
2419 filter_symbols(ibfd, obfd, &osyms, &fetch_superbfd(ibfd)->syms);
2420 copy_symbols(&osyms, &fetch_superbfd(ibfd)->new_syms);
2422 bfd_set_symtab(obfd, osyms.data, osyms.size);
2424 /* This has to happen after the symbol table has been set. */
2425 bfd_map_over_sections(obfd, write_section, NULL);
2427 /* Allow the BFD backend to copy any private data it understands
2428 from the input BFD to the output BFD. This is done last to
2429 permit the routine to look at the filtered symbol table, which is
2430 important for the ECOFF code at least. */
2431 assert(bfd_copy_private_bfd_data(ibfd, obfd));
2433 return TRUE;
2436 /* Modified function from GNU Binutils objcopy.c */
2437 void setup_section(bfd *ibfd, asection *isection, void *obfdarg)
2439 struct superbfd *isbfd = fetch_superbfd(ibfd);
2440 struct supersect *ss = fetch_supersect(isbfd, isection);
2441 bfd *obfd = obfdarg;
2442 bfd_vma vma;
2444 if (!ss->keep)
2445 return;
2447 asection *osection = bfd_make_section_anyway(obfd, ss->name);
2448 assert(osection != NULL);
2450 osection->userdata = ss;
2451 bfd_set_section_flags(obfd, osection, ss->flags);
2452 ss->symbol = osection->symbol;
2453 assert(bfd_set_section_size(obfd, osection, ss->contents.size));
2455 vma = bfd_section_vma(ibfd, isection);
2456 assert(bfd_set_section_vma(obfd, osection, vma));
2458 osection->lma = isection->lma;
2459 assert(bfd_set_section_alignment(obfd, osection, ss->alignment));
2460 osection->entsize = ss->entsize;
2461 osection->output_section = osection;
2462 osection->output_offset = 0;
2463 isection->output_section = osection;
2464 isection->output_offset = 0;
2465 return;
2468 void setup_new_section(bfd *obfd, struct supersect *ss)
2470 asection *osection = bfd_make_section_anyway(obfd, ss->name);
2471 assert(osection != NULL);
2472 bfd_set_section_flags(obfd, osection, ss->flags);
2474 osection->userdata = ss;
2475 ss->symbol = osection->symbol;
2476 assert(bfd_set_section_size(obfd, osection, ss->contents.size));
2477 assert(bfd_set_section_vma(obfd, osection, 0));
2479 osection->lma = 0;
2480 assert(bfd_set_section_alignment(obfd, osection, ss->alignment));
2481 osection->entsize = ss->entsize;
2482 osection->output_section = osection;
2483 osection->output_offset = 0;
2486 static int compare_reloc_addresses(const void *aptr, const void *bptr)
2488 const arelent *const *a = aptr, *const *b = bptr;
2489 return (*a)->address - (*b)->address;
2492 static void delete_obsolete_relocs(struct supersect *ss)
2494 if (ss->new_relocs.size == 0)
2495 return;
2497 qsort(ss->relocs.data, ss->relocs.size, sizeof(*ss->relocs.data),
2498 compare_reloc_addresses);
2499 qsort(ss->new_relocs.data, ss->new_relocs.size,
2500 sizeof(*ss->new_relocs.data), compare_reloc_addresses);
2502 struct arelentp_vec orig_relocs;
2503 vec_move(&orig_relocs, &ss->relocs);
2505 arelent **relocp, **new_relocp = ss->new_relocs.data;
2506 for (relocp = orig_relocs.data;
2507 relocp < orig_relocs.data + orig_relocs.size; relocp++) {
2508 while (new_relocp < ss->new_relocs.data + ss->new_relocs.size &&
2509 (*new_relocp)->address < (*relocp)->address)
2510 new_relocp++;
2511 arelent *reloc = *relocp, *new_reloc = *new_relocp;
2512 if (new_relocp == ss->new_relocs.data + ss->new_relocs.size ||
2513 reloc->address != new_reloc->address)
2514 *vec_grow(&ss->relocs, 1) = reloc;
2518 void write_section(bfd *obfd, asection *osection, void *arg)
2520 struct supersect *ss = osection->userdata;
2522 if ((ss->flags & SEC_GROUP) != 0 || ss->contents.size == 0)
2523 return;
2525 delete_obsolete_relocs(ss);
2527 arelent **relocp;
2528 char *error_message;
2529 for (relocp = ss->new_relocs.data;
2530 relocp < ss->new_relocs.data + ss->new_relocs.size; relocp++) {
2531 bfd_vma val;
2532 if (bfd_get_arch(obfd) == bfd_arch_arm)
2533 val = osection->use_rela_p ? 0 : (*relocp)->addend;
2534 else
2535 val = 0;
2536 bfd_put(bfd_get_reloc_size((*relocp)->howto) * 8, obfd, val,
2537 ss->contents.data + (*relocp)->address);
2538 if (bfd_install_relocation(obfd, *relocp, ss->contents.data,
2539 0, osection, &error_message) !=
2540 bfd_reloc_ok) {
2541 err(ss->parent, "ksplice: error installing reloc: %s",
2542 error_message);
2543 DIE;
2545 if (mode("finalize")) {
2546 /* Check that all our sections will be allocated */
2547 asymbol *sym = *((*relocp)->sym_ptr_ptr);
2548 if (!bfd_is_const_section(sym->section)) {
2549 struct supersect *sym_ss =
2550 fetch_supersect(ss->parent, sym->section);
2551 assert((sym_ss->flags & SEC_ALLOC) != 0);
2555 memcpy(vec_grow(&ss->relocs, ss->new_relocs.size), ss->new_relocs.data,
2556 ss->new_relocs.size * sizeof(*ss->new_relocs.data));
2558 bfd_set_reloc(obfd, osection,
2559 ss->relocs.size == 0 ? NULL : ss->relocs.data,
2560 ss->relocs.size);
2562 if (ss->flags & SEC_HAS_CONTENTS)
2563 assert(bfd_set_section_contents
2564 (obfd, osection, ss->contents.data, 0,
2565 ss->contents.size));
2568 /* Modified function from GNU Binutils objcopy.c
2570 * Mark all the symbols which will be used in output relocations with
2571 * the BSF_KEEP flag so that those symbols will not be stripped.
2573 * Ignore relocations which will not appear in the output file.
2575 void mark_symbols_used_in_relocations(bfd *abfd, asection *isection,
2576 void *ignored)
2578 struct superbfd *sbfd = fetch_superbfd(abfd);
2579 if (isection->output_section == NULL)
2580 return;
2582 struct supersect *ss = fetch_supersect(sbfd, isection);
2583 ss_mark_symbols_used_in_relocations(ss);
2586 void ss_mark_symbols_used_in_relocations(struct supersect *ss)
2588 /* Examine each symbol used in a relocation. If it's not one of the
2589 special bfd section symbols, then mark it with BSF_KEEP. */
2590 arelent **relocp;
2591 for (relocp = ss->relocs.data;
2592 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
2593 asymbol *sym = *(*relocp)->sym_ptr_ptr;
2594 if (!(bfd_is_const_section(sym->section) &&
2595 sym == sym->section->symbol))
2596 sym->flags |= BSF_KEEP;
2598 for (relocp = ss->new_relocs.data;
2599 relocp < ss->new_relocs.data + ss->new_relocs.size; relocp++) {
2600 asymbol *sym = *(*relocp)->sym_ptr_ptr;
2601 if (!(bfd_is_const_section(sym->section) &&
2602 sym == sym->section->symbol))
2603 sym->flags |= BSF_KEEP;
2607 static bool deleted_table_section_symbol(bfd *abfd, asymbol *sym)
2609 struct superbfd *sbfd = fetch_superbfd(abfd);
2610 if (bfd_is_const_section(sym->section))
2611 return false;
2612 struct supersect *ss = fetch_supersect(sbfd, sym->section);
2614 asymbol **symp;
2615 for (symp = ss->syms.data; symp < ss->syms.data + ss->syms.size; symp++) {
2616 if (sym == *symp)
2617 break;
2619 return symp >= ss->syms.data + ss->syms.size &&
2620 (sym->flags & BSF_SECTION_SYM) == 0;
2623 void filter_symbols(bfd *ibfd, bfd *obfd, struct asymbolp_vec *osyms,
2624 struct asymbolp_vec *isyms)
2626 asymbol **symp;
2627 struct superbfd *sbfd = fetch_superbfd(ibfd);
2628 for (symp = isyms->data; symp < isyms->data + isyms->size; symp++) {
2629 asymbol *sym = *symp;
2630 struct supersect *sym_ss = NULL;
2631 struct span *sym_span = NULL;
2632 if (!bfd_is_const_section(sym->section)) {
2633 sym_ss = fetch_supersect(sbfd, sym->section);
2634 sym_span = find_span(sym_ss, sym->value);
2637 if (mode("keep") && (sym->flags & BSF_GLOBAL) != 0 &&
2638 !(mode("keep-new-code") && sym_span != NULL &&
2639 sym_span->new))
2640 sym->flags = (sym->flags & ~BSF_GLOBAL) | BSF_LOCAL;
2642 if (mode("finalize") && (sym->flags & BSF_GLOBAL) != 0)
2643 sym->flags = (sym->flags & ~BSF_GLOBAL) | BSF_LOCAL;
2645 bool keep = bfd_is_const_section(sym->section) ||
2646 (sym_ss->keep && (sym->flags & BSF_SECTION_SYM) != 0) ||
2647 (sym_span != NULL && sym_span->keep);
2648 if (bfd_is_und_section(sym->section) &&
2649 (sym->flags & BSF_KEEP) == 0)
2650 keep = false;
2651 if (bfd_is_abs_section(sym->section) &&
2652 (sym->flags & BSF_KEEP) == 0 &&
2653 (sym->flags & BSF_FILE) == 0)
2654 keep = false;
2655 if (deleted_table_section_symbol(ibfd, sym))
2656 keep = false;
2658 if (mode("keep-old-code") && sym_ss != NULL &&
2659 sym_ss->type == SS_TYPE_EXPORT)
2660 keep = false;
2662 if (keep) {
2663 if (sym_ss != NULL && !sym_ss->keep) {
2664 err(sbfd, "Kept symbol %s in unkept section "
2665 "%s\n", sym->name, sym->section->name);
2666 DIE;
2668 *vec_grow(osyms, 1) = sym;
2673 static bool is_table_section(const char *name, bool consider_other,
2674 bool consider_crc)
2676 struct supersect *tables_ss =
2677 fetch_supersect(offsets_sbfd,
2678 bfd_get_section_by_name(offsets_sbfd->abfd,
2679 ".ksplice_table_sections"));
2680 const struct table_section *ts;
2681 for (ts = tables_ss->contents.data;
2682 (void *)ts < tables_ss->contents.data + tables_ss->contents.size;
2683 ts++) {
2684 if (strcmp(name, read_string(tables_ss, &ts->sect)) == 0)
2685 return true;
2686 const char *osect_name = read_string(tables_ss,
2687 &ts->other_sect);
2688 if (consider_other && osect_name != NULL &&
2689 strcmp(name, osect_name) == 0)
2690 return true;
2691 const char *crc_name = read_string(tables_ss, &ts->crc_sect);
2692 if (consider_crc && crc_name != NULL &&
2693 strcmp(name, crc_name) == 0)
2694 return true;
2696 return false;
2699 const struct table_section *get_table_section(const char *name)
2701 struct supersect *tables_ss =
2702 fetch_supersect(offsets_sbfd,
2703 bfd_get_section_by_name(offsets_sbfd->abfd,
2704 ".ksplice_table_sections"));
2705 const struct table_section *ts;
2706 for (ts = tables_ss->contents.data;
2707 (void *)ts < tables_ss->contents.data + tables_ss->contents.size;
2708 ts++) {
2709 if (strcmp(name, read_string(tables_ss, &ts->sect)) == 0) {
2710 if (ts->entry_contents_size != 0)
2711 assert(align(ts->entry_contents_size,
2712 ts->entry_align) ==
2713 ts->entry_size);
2714 struct table_section *ns = malloc(sizeof(*ns));
2715 *ns = *ts;
2716 ns->sect = read_string(tables_ss, &ts->sect);
2717 ns->crc_sect = read_string(tables_ss, &ts->crc_sect);
2718 ns->other_sect =
2719 read_string(tables_ss, &ts->other_sect);
2720 return ns;
2723 return NULL;
2726 enum supersect_type supersect_type(struct supersect *ss)
2728 if (mode("finalize") &&
2729 strcmp(finalize_target, "vmlinux") == 0 &&
2730 (strstarts(ss->name, ".ksplice_relocs.exit") ||
2731 strstarts(ss->name, ".ksplice_sections.exit") ||
2732 strstarts(ss->name, ".ksplice_patches.exit")))
2733 return SS_TYPE_EXIT;
2734 if (strstarts(ss->name, ".ksplice_call"))
2735 return SS_TYPE_KSPLICE_CALL;
2736 if (strstarts(ss->name, ".ksplice_extract"))
2737 return SS_TYPE_KSPLICE_EXTRACT;
2738 if (strstarts(ss->name, ".ksplice_options"))
2739 return SS_TYPE_SPECIAL;
2740 if (strstarts(ss->name, ".ksplice"))
2741 return SS_TYPE_KSPLICE;
2743 if (strstarts(ss->name, ".init"))
2744 return SS_TYPE_IGNORED;
2745 if (strstarts(ss->name, ".security_initcall.init"))
2746 return SS_TYPE_IGNORED;
2747 if (strstarts(ss->name, ".con_initcall.init"))
2748 return SS_TYPE_IGNORED;
2749 if (strstarts(ss->name, ".x86cpuvendor.init"))
2750 return SS_TYPE_IGNORED;
2751 if (strstarts(ss->name, ".early_param.init"))
2752 return SS_TYPE_IGNORED;
2753 if (strstarts(ss->name, ".taglist.init"))
2754 return SS_TYPE_IGNORED;
2755 if (strstarts(ss->name, ".x86_cpu_dev.init"))
2756 return SS_TYPE_IGNORED;
2757 if (strstarts(ss->name, ".arch.info.init"))
2758 return SS_TYPE_IGNORED;
2759 if (strstarts(ss->name, ".proc.info.init"))
2760 return SS_TYPE_IGNORED;
2761 /* .pci_fixup_* sections really should be treated as global rodata
2762 referenced only from quirks.c */
2763 if (strstarts(ss->name, ".pci_fixup_"))
2764 return SS_TYPE_IGNORED;
2765 /* .builtin_fw sections are similar to .pci_fixup */
2766 if (strstarts(ss->name, ".builtin_fw"))
2767 return SS_TYPE_IGNORED;
2768 /* same for .tracedata */
2769 if (strstarts(ss->name, ".tracedata"))
2770 return SS_TYPE_IGNORED;
2771 if (strstarts(ss->name, ".debug"))
2772 return SS_TYPE_IGNORED;
2773 /* .eh_frame should probably be discarded, not ignored */
2774 if (strstarts(ss->name, ".eh_frame"))
2775 return SS_TYPE_IGNORED;
2776 if (config->ignore_devinit && strstarts(ss->name, ".devinit"))
2777 return SS_TYPE_IGNORED;
2778 if (config->ignore_meminit && strstarts(ss->name, ".meminit"))
2779 return SS_TYPE_IGNORED;
2780 if (config->ignore_cpuinit && strstarts(ss->name, ".cpuinit"))
2781 return SS_TYPE_IGNORED;
2782 if (config->ignore_devinit && strstarts(ss->name, ".devexit"))
2783 return SS_TYPE_IGNORED;
2784 if (config->ignore_meminit && strstarts(ss->name, ".memexit"))
2785 return SS_TYPE_IGNORED;
2786 if (config->ignore_cpuinit && strstarts(ss->name, ".cpuexit"))
2787 return SS_TYPE_IGNORED;
2788 if (strstarts(ss->name, ".vgetcpu_mode") ||
2789 strstarts(ss->name, ".jiffies") ||
2790 strstarts(ss->name, ".wall_jiffies") ||
2791 strstarts(ss->name, ".vxtime") ||
2792 strstarts(ss->name, ".sys_tz") ||
2793 strstarts(ss->name, ".sysctl_vsyscall") ||
2794 strstarts(ss->name, ".xtime") ||
2795 strstarts(ss->name, ".xtime_lock") ||
2796 strstarts(ss->name, ".vsyscall"))
2797 return SS_TYPE_IGNORED;
2798 if (strstarts(ss->name, ".vdso"))
2799 return SS_TYPE_IGNORED;
2801 if (strstarts(ss->name, ".exit.text"))
2802 return SS_TYPE_TEXT;
2803 if (strstarts(ss->name, ".exit.data"))
2804 return SS_TYPE_DATA;
2806 if (strstarts(ss->name, ".text") ||
2807 strstarts(ss->name, ".kernel.text") ||
2808 strstarts(ss->name, ".devinit.text") ||
2809 strstarts(ss->name, ".meminit.text") ||
2810 strstarts(ss->name, ".cpuinit.text") ||
2811 strstarts(ss->name, ".devexit.text") ||
2812 strstarts(ss->name, ".memexit.text") ||
2813 strstarts(ss->name, ".cpuexit.text") ||
2814 strstarts(ss->name, ".ref.text") ||
2815 strstarts(ss->name, ".spinlock.text") ||
2816 strstarts(ss->name, ".kprobes.text") ||
2817 strstarts(ss->name, ".sched.text") ||
2818 strstarts(ss->name, ".entry.text") || /* OpenVZ */
2819 (mode("keep-old-code") && strstarts(ss->name, ".fixup")))
2820 return SS_TYPE_TEXT;
2822 int n = -1;
2823 if (sscanf(ss->name, ".rodata.str%*u.%*u%n", &n) >= 0 &&
2824 n == strlen(ss->name))
2825 return ss->entsize == 1 ? SS_TYPE_STRING : SS_TYPE_RODATA;
2827 if (strstarts(ss->name, ".rodata") ||
2828 strstarts(ss->name, ".kernel.rodata") ||
2829 strstarts(ss->name, ".devinit.rodata") ||
2830 strstarts(ss->name, ".meminit.rodata") ||
2831 strstarts(ss->name, ".cpuinit.rodata") ||
2832 strstarts(ss->name, ".devexit.rodata") ||
2833 strstarts(ss->name, ".memexit.rodata") ||
2834 strstarts(ss->name, ".cpuexit.rodata") ||
2835 strstarts(ss->name, ".ref.rodata") ||
2836 strstarts(ss->name, "__tracepoints_strings") ||
2837 strstarts(ss->name, "__markers_strings") ||
2838 (mode("keep-old-code") && strstarts(ss->name, "__ex_table")))
2839 return SS_TYPE_RODATA;
2841 if (strstarts(ss->name, ".bss"))
2842 return SS_TYPE_DATA;
2844 /* Ignore .data.percpu sections */
2845 if (strstarts(ss->name, ".data.percpu") ||
2846 strstarts(ss->name, ".kernel.data.percpu") ||
2847 strstarts(ss->name, ".data..percpu"))
2848 return SS_TYPE_IGNORED;
2849 if (strstarts(ss->name, ".data") ||
2850 strstarts(ss->name, ".kernel.data") ||
2851 strstarts(ss->name, ".devinit.data") ||
2852 strstarts(ss->name, ".cpuinit.data") ||
2853 strstarts(ss->name, ".meminit.data") ||
2854 strstarts(ss->name, ".devexit.data") ||
2855 strstarts(ss->name, ".memexit.data") ||
2856 strstarts(ss->name, ".cpuexit.data") ||
2857 strstarts(ss->name, ".ref.data") ||
2858 strstarts(ss->name, "__tracepoints") ||
2859 strstarts(ss->name, "__markers"))
2860 return SS_TYPE_DATA;
2862 /* We replace all the ksymtab strings, so delete them */
2863 if (strcmp(ss->name, "__ksymtab_strings") == 0)
2864 return SS_TYPE_STRING;
2865 if (strstarts(ss->name, "__ksymtab"))
2866 return SS_TYPE_EXPORT;
2868 if (strstarts(ss->name, "__bug_table"))
2869 return SS_TYPE_BUGTABLE;
2871 if (is_table_section(ss->name, true, true))
2872 return SS_TYPE_SPECIAL;
2874 if (strstarts(ss->name, ".ARM."))
2875 return SS_TYPE_SPECIAL;
2877 if (strstarts(ss->name, ".note"))
2878 return SS_TYPE_IGNORED;
2879 if (strstarts(ss->name, ".comment"))
2880 return SS_TYPE_IGNORED;
2881 if (strstarts(ss->name, "__param"))
2882 return SS_TYPE_IGNORED;
2883 if (strstarts(ss->name, "__obsparm"))
2884 return SS_TYPE_IGNORED;
2885 if (strstarts(ss->name, ".exitcall.exit"))
2886 return SS_TYPE_IGNORED;
2887 if (strstarts(ss->name, ".modinfo"))
2888 return SS_TYPE_IGNORED;
2890 return SS_TYPE_UNKNOWN;
2893 void initialize_supersect_types(struct superbfd *sbfd)
2895 asection *sect;
2896 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2897 struct supersect *ss = fetch_supersect(sbfd, sect);
2898 ss->type = supersect_type(ss);
2899 ss->orig_type = ss->type;
2900 if (ss->type == SS_TYPE_UNKNOWN) {
2901 err(sbfd, "Unknown section type: %s\n", ss->name);
2902 DIE;
2907 static void init_label_map(struct superbfd *sbfd)
2909 struct label_map *map;
2911 vec_init(&sbfd->maps);
2912 init_csyms(sbfd);
2913 init_callers(sbfd);
2915 struct symbol_hash csyms;
2916 symbol_hash_init(&csyms);
2918 asymbol **symp;
2919 for (symp = sbfd->syms.data;
2920 symp < sbfd->syms.data + sbfd->syms.size; symp++) {
2921 asymbol *csym = canonical_symbol(sbfd, *symp);
2922 if (csym == NULL)
2923 continue;
2924 char *key = strprintf("%p", csym);
2925 asymbol **csymp = symbol_hash_lookup(&csyms, key, TRUE);
2926 free(key);
2927 if (*csymp != NULL)
2928 continue;
2929 *csymp = csym;
2931 map = vec_grow(&sbfd->maps, 1);
2932 map->csym = csym;
2933 map->count = 0;
2934 map->label = symbol_label(sbfd, csym);
2937 struct label_mapp_hash label_maps;
2938 label_mapp_hash_init(&label_maps);
2939 for (map = sbfd->maps.data;
2940 map < sbfd->maps.data + sbfd->maps.size; map++) {
2941 struct label_map **mapp =
2942 label_mapp_hash_lookup(&label_maps, map->label, TRUE);
2943 if (*mapp == NULL) {
2944 *mapp = map;
2945 continue;
2948 struct label_map *first_map = *mapp;
2949 if (first_map->count == 0)
2950 first_map->label = strprintf("%s~%d", map->label, 0);
2951 map->label = strprintf("%s~%d", map->label, ++first_map->count);
2954 label_mapp_hash_init(&sbfd->maps_hash);
2955 for (map = sbfd->maps.data;
2956 map < sbfd->maps.data + sbfd->maps.size; map++) {
2957 char *key = strprintf("%p", map->csym);
2958 struct label_map **mapp =
2959 label_mapp_hash_lookup(&sbfd->maps_hash, key, TRUE);
2960 free(key);
2961 *mapp = map;
2962 map->orig_label = map->label;
2966 static const char *label_lookup(struct superbfd *sbfd, asymbol *sym)
2968 asymbol *csym = canonical_symbol(sbfd, sym);
2969 char *key = strprintf("%p", csym);
2970 struct label_map **mapp =
2971 label_mapp_hash_lookup(&sbfd->maps_hash, key, FALSE);
2972 free(key);
2973 if (mapp == NULL)
2974 DIE;
2975 return (*mapp)->label;
2978 static void print_label_changes(struct superbfd *sbfd)
2980 asection *sect;
2981 struct span *span;
2982 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2983 struct supersect *ss = fetch_supersect(sbfd, sect);
2984 for (span = ss->spans.data;
2985 span < ss->spans.data + ss->spans.size; span++) {
2986 if (strcmp(span->label, span->orig_label) != 0)
2987 debug1(sbfd, "Label change: %s -> %s\n",
2988 span->label, span->orig_label);
2993 static void label_map_set(struct superbfd *sbfd, const char *oldlabel,
2994 const char *label)
2996 struct label_map *map;
2997 for (map = sbfd->maps.data;
2998 map < sbfd->maps.data + sbfd->maps.size; map++) {
2999 if (strcmp(map->orig_label, oldlabel) == 0) {
3000 if (strcmp(map->orig_label, map->label) != 0 &&
3001 strcmp(map->label, label) != 0)
3002 DIE;
3003 map->label = label;
3004 return;
3007 DIE;
3010 static void change_initial_label(struct span *span, const char *label)
3012 struct superbfd *sbfd = span->ss->parent;
3013 span->label = label;
3014 span->orig_label = label;
3015 if (span->symbol) {
3016 asymbol *csym = canonical_symbol(sbfd, span->symbol);
3017 char *key = strprintf("%p", csym);
3018 struct label_map **mapp =
3019 label_mapp_hash_lookup(&sbfd->maps_hash, key, FALSE);
3020 free(key);
3021 assert(mapp);
3022 (*mapp)->label = span->label;
3023 (*mapp)->orig_label = span->orig_label;
3024 span->symbol = NULL;
3028 static void init_callers(struct superbfd *sbfd)
3030 string_hash_init(&sbfd->callers);
3031 asection *sect;
3032 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
3033 struct supersect *ss = fetch_supersect(sbfd, sect);
3034 arelent **relocp;
3035 for (relocp = ss->relocs.data;
3036 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
3037 asymbol *sym = *(*relocp)->sym_ptr_ptr;
3038 unsigned long val =
3039 sym->value + reloc_target_offset(ss, *relocp);
3040 char *key = strprintf("%s+%lx", sym->section->name,
3041 val);
3042 const char **ret = string_hash_lookup(&sbfd->callers,
3043 key, TRUE);
3044 free(key);
3045 asymbol *csym = canonical_symbol(sbfd, sect->symbol);
3046 if (*ret != NULL)
3047 *ret = "*multiple_callers*";
3048 else if (static_local_symbol(sbfd, csym))
3049 *ret = static_local_symbol(sbfd, csym);
3050 else
3051 *ret = sect->name;
3056 static const char *find_caller(struct supersect *ss, asymbol *sym)
3058 char *key = strprintf("%s+%lx", sym->section->name,
3059 (unsigned long)sym->value);
3060 const char **ret = string_hash_lookup(&ss->parent->callers, key, FALSE);
3061 free(key);
3063 if (ret == NULL)
3064 return "*no_caller*";
3065 return *ret;
3068 static void init_csyms(struct superbfd *sbfd)
3070 asymbolpp_hash_init(&sbfd->csyms);
3072 asymbol **symp;
3073 for (symp = sbfd->syms.data; symp < sbfd->syms.data + sbfd->syms.size;
3074 symp++) {
3075 asymbol *sym = *symp;
3076 if ((sym->flags & BSF_DEBUGGING) != 0)
3077 continue;
3078 char *key = strprintf("%s+%lx", sym->section->name,
3079 (unsigned long)sym->value);
3080 asymbol ***csympp = asymbolpp_hash_lookup(&sbfd->csyms, key,
3081 TRUE);
3082 free(key);
3083 if (*csympp == NULL) {
3084 *csympp = symp;
3085 continue;
3087 asymbol *csym = **csympp;
3088 if ((csym->flags & BSF_GLOBAL) != 0)
3089 continue;
3090 if ((sym->flags & BSF_GLOBAL) != 0)
3091 *csympp = symp;
3095 static asymbol **symbolp_scan(struct supersect *ss, bfd_vma value)
3097 char *key = strprintf("%s+%lx", ss->name, (unsigned long)value);
3098 asymbol ***csympp =
3099 asymbolpp_hash_lookup(&ss->parent->csyms, key, FALSE);
3100 free(key);
3101 if (csympp != NULL)
3102 return *csympp;
3104 /* For section symbols of sections containing no symbols, return the
3105 section symbol that relocations are generated against */
3106 if (value == 0)
3107 return &ss->symbol;
3108 return NULL;
3111 static asymbol **canonical_symbolp(struct superbfd *sbfd, asymbol *sym)
3113 if (bfd_is_const_section(sym->section)) {
3114 asymbol **csymp;
3115 for (csymp = sbfd->syms.data;
3116 csymp < sbfd->syms.data + sbfd->syms.size; csymp++) {
3117 if (sym == *csymp)
3118 return csymp;
3120 return NULL;
3122 return symbolp_scan(fetch_supersect(sbfd, sym->section), sym->value);
3125 static asymbol *canonical_symbol(struct superbfd *sbfd, asymbol *sym)
3127 if (bfd_is_const_section(sym->section))
3128 return sym;
3129 asymbol **symp = canonical_symbolp(sbfd, sym);
3130 return symp != NULL ? *symp : NULL;
3133 static char *static_local_symbol(struct superbfd *sbfd, asymbol *sym)
3135 struct supersect *ss = fetch_supersect(sbfd, sym->section);
3136 if ((sym->flags & BSF_LOCAL) == 0 || (sym->flags & BSF_OBJECT) == 0)
3137 return NULL;
3138 char *dot = strrchr(sym->name, '.');
3139 if (dot == NULL || dot[1 + strspn(dot + 1, "0123546789")] != '\0')
3140 return NULL;
3141 char *basename = strndup(sym->name, dot - sym->name);
3143 /* Handle C.123.12345 symbols */
3144 dot = strrchr(basename, '.');
3145 if (dot != NULL && dot[1 + strspn(dot + 1, "0123546789")] == '\0')
3146 basename = strndup(basename, dot - basename);
3147 const char *caller;
3148 if (strcmp(basename, "__func__") == 0 ||
3149 strcmp(basename, "__PRETTY_FUNCTION__") == 0)
3150 caller = (const char *)ss->contents.data + sym->value;
3151 else
3152 caller = find_caller(ss, sym);
3153 return strprintf("%s<%s>", basename, caller);
3156 static char *symbol_label(struct superbfd *sbfd, asymbol *sym)
3158 const char *filename = sbfd->abfd->filename;
3159 char *c = strstr(filename, ".KSPLICE");
3160 int flen = (c == NULL ? strlen(filename) : c - filename);
3162 char *label;
3163 if (bfd_is_und_section(sym->section) || (sym->flags & BSF_GLOBAL) != 0) {
3164 label = strdup(sym->name);
3165 } else if (bfd_is_const_section(sym->section)) {
3166 label = strprintf("%s<%.*s>", sym->name, flen, filename);
3167 } else {
3168 asymbol *gsym = canonical_symbol(sbfd, sym);
3170 if (gsym == NULL)
3171 label = strprintf("%s+%lx<%.*s>",
3172 sym->section->name,
3173 (unsigned long)sym->value,
3174 flen, filename);
3175 else if ((gsym->flags & BSF_GLOBAL) != 0)
3176 label = strdup(gsym->name);
3177 else if (static_local_symbol(sbfd, gsym))
3178 label = strprintf("%s+%lx<%.*s>",
3179 static_local_symbol(sbfd, gsym),
3180 (unsigned long)sym->value,
3181 flen, filename);
3182 else
3183 label = strprintf("%s<%.*s>",
3184 gsym->name, flen, filename);
3187 return label;
3190 static void keep_span(struct span *span)
3192 span->keep = true;
3193 span->ss->keep = true;
3196 static struct span *new_span(struct supersect *ss, bfd_vma start, bfd_vma size)
3198 struct span *span = vec_grow(&ss->spans, 1);
3199 span->size = size;
3200 span->contents_size = size;
3201 span->start = start;
3202 span->ss = ss;
3203 span->keep = true;
3204 span->new = false;
3205 span->patch = false;
3206 span->bugpatch = false;
3207 span->datapatch = false;
3208 span->precallable = strstarts(ss->name, ".ksplice_call_pre_apply") ||
3209 strstarts(ss->name, ".ksplice_call_check_apply") ||
3210 strstarts(ss->name, ".ksplice_call_fail_apply") ||
3211 strstarts(ss->name, ".ksplice_call_post_remove");
3212 span->match = NULL;
3213 vec_init(&span->entry_points);
3214 span->shift = 0;
3215 asymbol **symp = symbolp_scan(ss, span->start);
3216 if (symp != NULL) {
3217 span->symbol = *symp;
3218 span->label = label_lookup(ss->parent, span->symbol);
3219 } else {
3220 span->symbol = NULL;
3221 const char *label = label_lookup(ss->parent, ss->symbol);
3222 if (span->start != 0)
3223 span->label = strprintf("%s<span:%lx>", label,
3224 (unsigned long)span->start);
3225 else
3226 span->label = label;
3228 span->orig_label = span->label;
3229 return span;
3232 static void initialize_string_spans(struct supersect *ss)
3234 const char *str;
3235 for (str = ss->contents.data;
3236 (void *)str < ss->contents.data + ss->contents.size;) {
3237 bfd_vma start = (unsigned long)str -
3238 (unsigned long)ss->contents.data;
3239 bfd_vma size = strlen(str) + 1;
3240 bfd_vma contents_size = size;
3241 while ((start + size) % (1 << ss->alignment) != 0 &&
3242 start + size < ss->contents.size) {
3243 /* Some string sections, like __ksymtab_strings, only
3244 align some strings with the declared alignment */
3245 if (str[size] != '\0')
3246 break;
3247 size++;
3249 struct span *span = new_span(ss, start, size);
3250 span->contents_size = contents_size;
3251 str += size;
3255 static int compare_ulongs(const void *va, const void *vb)
3257 const unsigned long *a = va, *b = vb;
3258 return *a - *b;
3261 static void initialize_table_spans(struct superbfd *sbfd,
3262 struct table_section *s)
3264 asection *isection = bfd_get_section_by_name(sbfd->abfd, s->sect);
3265 if (isection == NULL)
3266 return;
3267 struct supersect *ss = fetch_supersect(sbfd, isection);
3268 if (ss->alignment < ffs(s->entry_align) - 1)
3269 ss->alignment = ffs(s->entry_align) - 1;
3271 asection *other_sect = NULL;
3272 if (s->other_sect != NULL)
3273 other_sect = bfd_get_section_by_name(sbfd->abfd, s->other_sect);
3274 struct supersect *other_ss = NULL;
3275 if (other_sect != NULL)
3276 other_ss = fetch_supersect(sbfd, other_sect);
3278 asection *crc_sect = NULL;
3279 if (s->crc_sect != NULL)
3280 crc_sect = bfd_get_section_by_name(sbfd->abfd, s->crc_sect);
3281 struct supersect *crc_ss = NULL;
3282 if (crc_sect != NULL)
3283 crc_ss = fetch_supersect(sbfd, crc_sect);
3285 struct ulong_vec offsets;
3286 vec_init(&offsets);
3288 void *entry;
3289 for (entry = ss->contents.data;
3290 entry < ss->contents.data + ss->contents.size;
3291 entry += s->entry_size) {
3292 struct span *span = new_span(ss, addr_offset(ss, entry),
3293 s->entry_size);
3294 if (s->entry_contents_size != 0)
3295 span->contents_size = s->entry_contents_size;
3296 if ((span->symbol == NULL ||
3297 (span->symbol->flags & BSF_SECTION_SYM) != 0) &&
3298 s->has_addr) {
3299 arelent *reloc = find_reloc(ss, entry + s->addr_offset);
3300 assert(reloc);
3301 struct span *target_span = reloc_target_span(ss, reloc);
3302 assert(target_span);
3303 asymbol *sym = *reloc->sym_ptr_ptr;
3304 unsigned long val = sym->value +
3305 reloc_target_offset(ss, reloc) -
3306 (target_span->start + target_span->shift);
3307 char *label = strprintf("%s<target:%s+%lx>", ss->name,
3308 target_span->label, val);
3309 change_initial_label(span, label);
3312 if (other_sect != NULL) {
3313 asymbol *sym;
3314 bfd_vma offset = read_reloc(ss, entry + s->other_offset,
3315 sizeof(void *), &sym);
3316 if (sym->section == other_sect) {
3317 assert(offset >= 0 &&
3318 offset < other_ss->contents.size);
3319 *vec_grow(&offsets, 1) = offset;
3323 if (crc_sect != NULL)
3324 new_span(crc_ss, addr_offset(ss, entry) / s->entry_size
3325 * s->crc_size, s->crc_size);
3327 if (ss->type == SS_TYPE_EXPORT) {
3328 const char *symname = read_string(ss, entry +
3329 s->other_offset);
3330 char *label = strprintf("%s:%s", ss->name, symname);
3331 change_initial_label(span, label);
3335 if (other_sect == NULL)
3336 return;
3338 *vec_grow(&offsets, 1) = 0;
3339 qsort(offsets.data, offsets.size, sizeof(*offsets.data),
3340 compare_ulongs);
3341 *vec_grow(&offsets, 1) = other_ss->contents.size;
3343 unsigned long *off;
3344 for (off = offsets.data; off < offsets.data + offsets.size - 1; off++) {
3345 if (*off != *(off + 1))
3346 new_span(other_ss, *off, *(off + 1) - *off);
3350 static void initialize_table_section_spans(struct superbfd *sbfd)
3352 struct supersect *tables_ss =
3353 fetch_supersect(offsets_sbfd,
3354 bfd_get_section_by_name(offsets_sbfd->abfd,
3355 ".ksplice_table_sections"));
3356 const struct table_section *ts;
3357 struct table_section s;
3358 for (ts = tables_ss->contents.data;
3359 (void *)ts < tables_ss->contents.data + tables_ss->contents.size;
3360 ts++) {
3361 s = *ts;
3362 s.sect = read_string(tables_ss, &ts->sect);
3363 s.other_sect = read_string(tables_ss, &ts->other_sect);
3364 s.crc_sect = read_string(tables_ss, &ts->crc_sect);
3365 initialize_table_spans(sbfd, &s);
3369 static void initialize_ksplice_call_spans(struct supersect *ss)
3371 arelent **relocp;
3372 for (relocp = ss->relocs.data;
3373 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
3374 arelent *reloc = *relocp;
3375 new_span(ss, reloc->address, bfd_get_reloc_size(reloc->howto));
3376 /* the span labels should already be unique */
3380 static void initialize_spans(struct superbfd *sbfd)
3382 asection *sect;
3383 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
3384 if (is_table_section(sect->name, true, true) && mode("keep"))
3385 continue;
3387 struct supersect *ss = fetch_supersect(sbfd, sect);
3388 if (ss->type == SS_TYPE_STRING)
3389 initialize_string_spans(ss);
3390 else if (ss->type == SS_TYPE_KSPLICE_CALL)
3391 initialize_ksplice_call_spans(ss);
3392 else
3393 new_span(ss, 0, ss->contents.size);
3395 if (mode("keep"))
3396 initialize_table_section_spans(sbfd);
3399 /* Returns the span pointed to by the relocation at span->start + offset */
3400 static struct span *span_offset_target_span(struct span *span, int offset)
3402 void *entry = span->ss->contents.data + span->start;
3403 arelent *reloc = find_reloc(span->ss, entry + offset);
3404 if (reloc == NULL)
3405 return NULL;
3406 return reloc_target_span(span->ss, reloc);
3409 struct span *reloc_target_span(struct supersect *ss, arelent *reloc)
3411 asymbol *sym_ptr = *reloc->sym_ptr_ptr;
3412 if (bfd_is_const_section(sym_ptr->section))
3413 return NULL;
3415 bfd_vma addend = sym_ptr->value;
3416 if ((sym_ptr->flags & BSF_SECTION_SYM) != 0)
3417 addend += reloc_target_offset(ss, reloc);
3419 struct supersect *sym_ss =
3420 fetch_supersect(ss->parent, sym_ptr->section);
3421 struct span *span, *target_span = sym_ss->spans.data;
3422 for (span = sym_ss->spans.data;
3423 span < sym_ss->spans.data + sym_ss->spans.size; span++) {
3424 if (addend >= span->start && addend < span->start + span->size)
3425 target_span = span;
3427 return target_span;
3430 static bfd_vma reloc_target_offset(struct supersect *ss, arelent *reloc)
3432 bfd_vma offset = reloc_offset(ss, reloc);
3433 if (reloc->howto->pc_relative) {
3434 if ((ss->flags & SEC_CODE) != 0)
3435 return offset + bfd_get_reloc_size(reloc->howto);
3437 const struct table_section *ts = get_table_section(ss->name);
3438 if (ts != NULL && ts->relative_addr &&
3439 reloc->address % ts->entry_size == ts->addr_offset)
3440 return offset - ts->addr_offset;
3441 if (ts != NULL && ts->relative_other &&
3442 reloc->address % ts->entry_size == ts->other_offset)
3443 return offset - ts->other_offset;
3445 DIE;
3447 return offset;
3450 struct span *find_span(struct supersect *ss, bfd_size_type address)
3452 struct span *span;
3453 for (span = ss->spans.data; span < ss->spans.data + ss->spans.size;
3454 span++) {
3455 if (address >= span->start &&
3456 address < span->start + span->size)
3457 return span;
3459 /* Deal with empty BSS sections */
3460 if (ss->contents.size == 0 && ss->spans.size > 0)
3461 return ss->spans.data;
3462 /* Deal with section end pointers */
3463 if (address == ss->contents.size && ss->spans.size == 1)
3464 return ss->spans.data;
3465 return NULL;
3468 void compute_span_shifts(struct superbfd *sbfd)
3470 asection *sect;
3471 struct span *span;
3472 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
3473 struct supersect *ss = fetch_supersect(sbfd, sect);
3474 if (!ss->keep)
3475 continue;
3476 bfd_size_type offset = 0;
3477 for (span = ss->spans.data;
3478 span < ss->spans.data + ss->spans.size; span++) {
3479 if (!span->keep)
3480 continue;
3481 span->shift = offset - span->start;
3482 offset += span->size;
3487 void remove_unkept_spans(struct superbfd *sbfd)
3489 asection *sect;
3490 struct span *span;
3491 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
3492 struct supersect *ss = fetch_supersect(sbfd, sect);
3493 delete_obsolete_relocs(ss);
3494 struct arelentp_vec orig_relocs;
3495 vec_move(&orig_relocs, &ss->relocs);
3496 arelent **relocp, *reloc;
3497 for (relocp = orig_relocs.data;
3498 relocp < orig_relocs.data + orig_relocs.size; relocp++) {
3499 reloc = *relocp;
3500 asymbol *sym = *reloc->sym_ptr_ptr;
3501 span = reloc_target_span(ss, reloc);
3502 if ((span != NULL && span->keep && span->shift == 0) ||
3503 bfd_is_const_section(sym->section)) {
3504 *vec_grow(&ss->relocs, 1) = reloc;
3505 continue;
3507 struct supersect *sym_ss =
3508 fetch_supersect(sbfd, sym->section);
3509 if (span != NULL && (sym->flags & BSF_SECTION_SYM) == 0
3510 && find_span(sym_ss, sym->value) != span) {
3511 err(sbfd, "Spans for symbol %s and relocation "
3512 "target do not match in sect %s\n",
3513 sym->name, sym_ss->name);
3514 DIE;
3516 if (span != NULL && span->keep) {
3517 arelent *new_reloc = malloc(sizeof(*new_reloc));
3518 *new_reloc = *reloc;
3519 new_reloc->addend = reloc_offset(ss, reloc);
3520 new_reloc->addend += span->shift;
3521 *vec_grow(&ss->new_relocs, 1) = new_reloc;
3526 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
3527 struct supersect *ss = fetch_supersect(sbfd, sect), orig_ss;
3528 if (!ss->keep)
3529 continue;
3530 supersect_move(&orig_ss, ss);
3531 vec_init(&ss->spans);
3532 for (span = orig_ss.spans.data;
3533 span < orig_ss.spans.data + orig_ss.spans.size; span++) {
3534 if (!span->keep)
3535 continue;
3536 struct span *new_span = vec_grow(&ss->spans, 1);
3537 *new_span = *span;
3538 new_span->start = span->start + span->shift;
3539 new_span->shift = 0;
3540 sect_copy(ss, sect_do_grow(ss, 1, span->size, 1),
3541 &orig_ss, orig_ss.contents.data + span->start,
3542 span->size);
3547 static void init_objmanip_superbfd(struct superbfd *sbfd)
3549 init_label_map(sbfd);
3550 initialize_supersect_types(sbfd);
3551 initialize_spans(sbfd);
3552 load_options(sbfd);
3553 compute_entry_points(sbfd);
3556 void mangle_section_name(struct superbfd *sbfd, const char *name)
3558 asection *sect = bfd_get_section_by_name(sbfd->abfd, name);
3559 if (sect == NULL)
3560 return;
3561 struct supersect *ss = fetch_supersect(sbfd, sect);
3562 ss->name = strprintf(".ksplice_pre.%s", ss->name);
3565 static void write_bugline_patches(struct superbfd *sbfd)
3567 const struct table_section *ts = get_table_section("__bug_table");
3568 asection *sect = bfd_get_section_by_name(sbfd->abfd, "__bug_table");
3569 if (sect == NULL)
3570 return;
3571 struct supersect *ss = fetch_supersect(sbfd, sect);
3572 assert(ts != NULL);
3574 void *entry;
3575 for (entry = ss->contents.data;
3576 entry < ss->contents.data + ss->contents.size;
3577 entry += ts->entry_size) {
3578 struct span *span = find_span(ss, addr_offset(ss, entry));
3579 assert(span != NULL);
3580 if (!span->bugpatch)
3581 continue;
3582 arelent *reloc = find_reloc(ss, entry + ts->addr_offset);
3583 assert(reloc != NULL);
3584 asymbol *sym = *reloc->sym_ptr_ptr;
3585 assert(!bfd_is_const_section(sym->section));
3586 struct supersect *kpatch_ss =
3587 make_section(sbfd, ".ksplice_patches%s",
3588 sym->section->name);
3590 bfd_vma offset, start = 0;
3591 for (offset = 0; offset <= span->size; offset++) {
3592 if (offset != span->size &&
3593 !part_of_reloc(ss, span->start + offset))
3594 continue;
3595 if (start == offset) {
3596 start++;
3597 continue;
3599 /* an interval of non-relocations just passed */
3600 struct ksplice_patch *kpatch =
3601 sect_grow(kpatch_ss, 1, struct ksplice_patch);
3602 write_ksplice_patch_reloc
3603 (kpatch_ss, sym->section->name, &kpatch->oldaddr,
3604 sizeof(kpatch->oldaddr), span->label, start);
3606 char *data = write_patch_storage(kpatch_ss, kpatch,
3607 offset - start, NULL);
3608 memcpy(data, entry + start, offset - start);
3609 kpatch->type = KSPLICE_PATCH_DATA;
3610 start = offset + 1;
3615 void *write_patch_storage(struct supersect *ss, struct ksplice_patch *kpatch,
3616 size_t size, struct supersect **data_ssp)
3618 struct supersect *data_ss = make_section(ss->parent,
3619 ".ksplice_patch_data");
3620 char *saved = sect_do_grow(data_ss, 1, size, 1);
3621 write_reloc(ss, &kpatch->saved, &data_ss->symbol,
3622 addr_offset(data_ss, saved));
3623 char *data = sect_do_grow(data_ss, 1, size, 1);
3624 write_reloc(ss, &kpatch->contents, &data_ss->symbol,
3625 addr_offset(data_ss, data));
3626 kpatch->size = size;
3627 if (data_ssp != NULL)
3628 *data_ssp = data_ss;
3629 return data;