Don't keep unused absolute section symbols.
[ksplice.git] / objmanip.c
blob7cac692c60caae7c1e19defa9517f4c4121c0c0e
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-2008 Ksplice, Inc.
5 * Authors: Jeff Arnold, Anders Kaseorg, Tim Abbott
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License, version 2.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
18 * 02110-1301, USA.
21 /* objmanip performs various object file manipulations for Ksplice. Its first
22 * two arguments are always an input object file and an output object file.
24 * - keep-primary: "objmanip <post.o> <out.o> keep-primary <pre.o> <kid>"
26 * This mode prepares the object file to be installed as a ksplice update. The
27 * kid argument is the ksplice id string for the ksplice update being built.
29 * - keep-helper: "objmanip <pre.o> <out.o> keep-helper"
31 * This mode prepares the object file to be used for run-pre matching. This
32 * involves replacing all ELF relocations with ksplice relocations and
33 * writing ksplice_section structures for each ELF text or data section.
35 * - rmsyms mode: "objmanip <in.o> <out.o> rmsyms
37 * In this mode, any ELF relocations involving the list of symbol names given on
38 * standard input are replaced with ksplice relocations. This is used only
39 * for KSPLICE_STANDALONE.
41 * - finalize mode: "objmanip <in.o> <out.o> finalize"
43 * In this mode, any ELF relocations to undefined symbols are replaced with
44 * ksplice relocations.
47 /* Always define KSPLICE_STANDALONE, even if you're using integrated Ksplice.
48 objmanip won't compile without it. */
49 #define KSPLICE_STANDALONE
51 #define _GNU_SOURCE
52 #include "objcommon.h"
53 #include "kmodsrc/ksplice.h"
54 #include "kmodsrc/offsets.h"
55 #include "ksplice-patch/ksplice-patch.h"
56 #include <stdint.h>
57 #include <stdarg.h>
58 #include <stdlib.h>
59 #include <stdio.h>
60 #include <limits.h>
62 #define KSPLICE_SYMBOL_STR "KSPLICE_SYMBOL_"
64 #define symbol_init(sym) *(sym) = (asymbol *)NULL
65 DEFINE_HASH_TYPE(asymbol *, symbol_hash, symbol_hash_init, symbol_hash_free,
66 symbol_hash_lookup, symbol_init);
68 DECLARE_VEC_TYPE(const char *, str_vec);
70 DECLARE_VEC_TYPE(unsigned long, ulong_vec);
72 #define bool_init(b) *(b) = false
73 DEFINE_HASH_TYPE(bool, bool_hash, bool_hash_init, bool_hash_free,
74 bool_hash_lookup, bool_init);
76 #define ulong_init(x) *(x) = 0
77 DEFINE_HASH_TYPE(unsigned long, ulong_hash, ulong_hash_init,
78 ulong_hash_free, ulong_hash_lookup, ulong_init);
80 void do_keep_primary(struct superbfd *isbfd, const char *pre);
81 void do_keep_helper(struct superbfd *isbfd);
82 void do_finalize(struct superbfd *isbfd);
83 void do_rmsyms(struct superbfd *isbfd);
85 bool relocs_equal(struct supersect *old_src_ss, struct supersect *new_src_ss,
86 arelent *old_reloc, arelent *new_reloc);
87 bfd_vma non_dst_mask(struct supersect *ss, arelent *reloc);
88 bool all_relocs_equal(struct span *old_span, struct span *new_span);
89 static bool part_of_reloc(struct supersect *ss, unsigned long addr);
90 static bool nonrelocs_equal(struct span *old_span, struct span *new_span);
91 static void handle_section_symbol_renames(struct superbfd *oldsbfd,
92 struct superbfd *newsbfd);
94 enum supersect_type supersect_type(struct supersect *ss);
95 void initialize_supersect_types(struct superbfd *sbfd);
96 static void initialize_spans(struct superbfd *sbfd);
97 static void initialize_string_spans(struct supersect *ss);
98 static void initialize_table_spans(struct superbfd *sbfd,
99 struct table_section *s);
100 static void initialize_table_section_spans(struct superbfd *sbfd);
101 static void initialize_ksplice_call_spans(struct supersect *ss);
102 struct span *reloc_target_span(struct supersect *ss, arelent *reloc);
103 struct span *find_span(struct supersect *ss, bfd_size_type address);
104 void remove_unkept_spans(struct superbfd *sbfd);
105 void compute_span_shifts(struct superbfd *sbfd);
106 static struct span *new_span(struct supersect *ss, bfd_vma start, bfd_vma size);
107 bool is_table_section(const char *name, bool consider_other);
108 const struct table_section *get_table_section(const char *name);
109 void mangle_section_name(struct superbfd *sbfd, const char *name);
111 void rm_relocs(struct superbfd *isbfd);
112 void rm_some_relocs(struct supersect *ss);
113 void write_ksplice_reloc(struct supersect *ss, arelent *orig_reloc);
114 static void write_ksplice_reloc_howto(struct supersect *ss, const
115 struct ksplice_reloc_howto *const *addr,
116 reloc_howto_type *howto,
117 enum ksplice_reloc_howto_type type);
118 static void write_ksplice_date_reloc(struct supersect *ss, unsigned long offset,
119 const char *str,
120 enum ksplice_reloc_howto_type type);
121 static void write_ksplice_patch_reloc(struct supersect *ss,
122 const char *sectname, unsigned long *addr,
123 bfd_size_type size, const char *label,
124 long addend);
125 static void write_ksplice_nonreloc_howto(struct supersect *ss,
126 const struct ksplice_reloc_howto
127 *const *addr,
128 enum ksplice_reloc_howto_type type,
129 int size);
130 static void write_date_relocs(struct superbfd *sbfd, const char *str,
131 enum ksplice_reloc_howto_type type);
132 static void write_table_relocs(struct superbfd *sbfd, const char *sectname,
133 enum ksplice_reloc_howto_type type);
134 static void write_ksplice_table_reloc(struct supersect *ss,
135 unsigned long address,
136 const char *label,
137 enum ksplice_reloc_howto_type type);
138 void load_ksplice_symbol_offsets(struct superbfd *sbfd);
139 void write_canary(struct supersect *ss, int offset, bfd_size_type size,
140 bfd_vma dst_mask);
141 static void write_ksplice_section(struct span *span);
142 void write_ksplice_patch(struct superbfd *sbfd, struct span *span);
143 void *write_patch_storage(struct supersect *ss, struct ksplice_patch *patch,
144 size_t size, struct supersect **data_ssp);
145 void write_ksplice_deleted_patch(struct superbfd *sbfd, const char *name,
146 const char *label, const char *sectname);
147 static void write_bugline_patches(struct superbfd *sbfd);
148 asymbol **make_undefined_symbolp(struct superbfd *sbfd, const char *name);
149 void filter_table_sections(struct superbfd *isbfd);
150 void filter_table_section(struct superbfd *sbfd, const struct table_section *s);
151 void keep_referenced_sections(struct superbfd *sbfd);
152 void mark_precallable_spans(struct superbfd *sbfd);
153 bfd_boolean copy_object(bfd *ibfd, bfd *obfd);
154 void setup_section(bfd *ibfd, asection *isection, void *obfdarg);
155 static void setup_new_section(bfd *obfd, struct supersect *ss);
156 static void write_section(bfd *obfd, asection *osection, void *arg);
157 static void delete_obsolete_relocs(struct supersect *ss);
158 void mark_symbols_used_in_relocations(bfd *abfd, asection *isection,
159 void *ignored);
160 static void ss_mark_symbols_used_in_relocations(struct supersect *ss);
161 void filter_symbols(bfd *ibfd, bfd *obfd, struct asymbolp_vec *osyms,
162 struct asymbolp_vec *isyms);
163 static bool deleted_table_section_symbol(bfd *abfd, asymbol *sym);
164 void read_str_set(struct str_vec *strs);
165 bool str_in_set(const char *str, const struct str_vec *strs);
166 struct supersect *__attribute((format(printf, 2, 3)))
167 make_section(struct superbfd *sbfd, const char *fmt, ...);
168 void __attribute__((format(printf, 3, 4)))
169 write_string(struct supersect *ss, const char **addr, const char *fmt, ...);
170 void write_ksplice_export(struct superbfd *sbfd, struct span *span, bool del);
171 void write_reloc(struct supersect *ss, const void *addr, asymbol **symp,
172 bfd_vma offset);
173 arelent *create_reloc(struct supersect *ss, const void *addr, asymbol **symp,
174 bfd_vma offset);
175 static void foreach_symbol_pair(struct superbfd *oldsbfd, struct superbfd *newsbfd,
176 void (*fn)(struct span *old_span,
177 asymbol *oldsym,
178 struct span *new_span,
179 asymbol *newsym));
180 static void check_global_symbols(struct span *old_span, asymbol *oldsym,
181 struct span *new_span, asymbol *newsym);
182 static void match_global_symbols(struct span *old_span, asymbol *oldsym,
183 struct span *new_span, asymbol *newsym);
184 static void match_symbol_spans(struct span *old_span, asymbol *oldsym,
185 struct span *new_span, asymbol *newsym);
187 static struct span *get_crc_span(struct span *span,
188 const struct table_section *ts);
189 static void foreach_span_pair(struct superbfd *oldsbfd,
190 struct superbfd *newsbfd,
191 void (*fn)(struct span *old_span,
192 struct span *new_span));
193 static void match_spans_by_label(struct span *old_span, struct span *new_span);
194 static void match_string_spans(struct span *old_span, struct span *new_span);
195 static void mark_new_spans(struct superbfd *sbfd);
196 static void handle_deleted_spans(struct superbfd *oldsbfd,
197 struct superbfd *newsbfd);
198 static void compare_matched_spans(struct superbfd *newsbfd);
199 static void compare_spans(struct span *old_span, struct span *new_span);
200 static void update_nonzero_offsets(struct superbfd *sbfd);
201 static void handle_nonzero_offset_relocs(struct supersect *ss);
202 static void keep_span(struct span *span);
204 static void init_objmanip_superbfd(struct superbfd *sbfd);
205 static const char *label_lookup(struct superbfd *sbfd, asymbol *sym);
206 static void label_map_set(struct superbfd *sbfd, const char *oldlabel,
207 const char *label);
208 static void print_label_changes(struct superbfd *sbfd);
209 static void init_label_map(struct superbfd *sbfd);
210 static void change_initial_label(struct span *span, const char *label);
211 static asymbol **symbolp_scan(struct supersect *ss, bfd_vma value);
212 static void init_csyms(struct superbfd *sbfd);
213 static void init_callers(struct superbfd *sbfd);
214 static asymbol *canonical_symbol(struct superbfd *sbfd, asymbol *sym);
215 static asymbol **canonical_symbolp(struct superbfd *sbfd, asymbol *sym);
216 static char *static_local_symbol(struct superbfd *sbfd, asymbol *sym);
217 static char *symbol_label(struct superbfd *sbfd, asymbol *sym);
219 int verbose = 0;
220 #define debug_(sbfd, level, fmt, ...) \
221 do { \
222 if (verbose >= (level)) \
223 printf("%s: " fmt, (sbfd)->abfd->filename, \
224 ## __VA_ARGS__); \
225 } while (0)
226 #define debug0(sbfd, fmt, ...) debug_(sbfd, 0, fmt, ## __VA_ARGS__)
227 #define debug1(sbfd, fmt, ...) debug_(sbfd, 1, fmt, ## __VA_ARGS__)
228 #define err(sbfd, fmt, ...) \
229 do { \
230 fprintf(stderr, "%s: " fmt, (sbfd)->abfd->filename, \
231 ## __VA_ARGS__); \
232 } while (0)
234 struct str_vec delsects, rmsyms;
235 bool changed;
237 struct ksplice_config *config;
239 const char *modestr, *kid, *finalize_target = NULL;
240 bool write_output = true;
242 struct superbfd *offsets_sbfd = NULL;
244 #define mode(str) starts_with(modestr, str)
246 DECLARE_VEC_TYPE(unsigned long, addr_vec);
247 DEFINE_HASH_TYPE(struct addr_vec, addr_vec_hash,
248 addr_vec_hash_init, addr_vec_hash_free, addr_vec_hash_lookup,
249 vec_init);
250 struct addr_vec_hash system_map;
252 struct bool_hash system_map_written;
253 struct ulong_hash ksplice_symbol_offset;
254 struct ulong_hash ksplice_howto_offset;
255 struct ulong_hash ksplice_string_offset;
257 void load_system_map()
259 const char *config_dir = getenv("KSPLICE_CONFIG_DIR");
260 assert(config_dir);
261 FILE *fp = fopen(strprintf("%s/System.map", config_dir), "r");
262 assert(fp);
263 addr_vec_hash_init(&system_map);
264 unsigned long addr;
265 char type;
266 char *sym;
267 while (fscanf(fp, "%lx %c %as\n", &addr, &type, &sym) == 3)
268 *vec_grow(addr_vec_hash_lookup(&system_map, sym, TRUE),
269 1) = addr;
270 fclose(fp);
273 void load_ksplice_symbol_offsets(struct superbfd *sbfd)
275 asection *sect = bfd_get_section_by_name(sbfd->abfd,
276 ".ksplice_symbols");
277 if (sect == NULL)
278 return;
279 struct supersect *ss = fetch_supersect(sbfd, sect);
281 struct ksplice_symbol *ksym;
282 for (ksym = ss->contents.data;
283 (void *)ksym < ss->contents.data + ss->contents.size; ksym++) {
284 const char *label = read_string(ss, &ksym->label);
285 unsigned long *ksymbol_offp =
286 ulong_hash_lookup(&ksplice_symbol_offset, label, TRUE);
287 *ksymbol_offp = addr_offset(ss, ksym);
291 void load_offsets()
293 char *kmodsrc = getenv("KSPLICE_KMODSRC");
294 assert(kmodsrc != NULL);
295 bfd *offsets_bfd = bfd_openr(strprintf("%s/offsets.o", kmodsrc), NULL);
296 assert(offsets_bfd != NULL);
297 char **matching;
298 assert(bfd_check_format_matches(offsets_bfd, bfd_object, &matching));
299 offsets_sbfd = fetch_superbfd(offsets_bfd);
301 asection *config_sect = bfd_get_section_by_name(offsets_sbfd->abfd,
302 ".ksplice_config");
303 struct supersect *config_ss =
304 fetch_supersect(offsets_sbfd, config_sect);
306 config = config_ss->contents.data;
309 void load_options(struct superbfd *sbfd)
311 asection *sect = bfd_get_section_by_name(sbfd->abfd,
312 ".ksplice_options");
313 if (sect == NULL)
314 return;
315 struct supersect *ss = fetch_supersect(sbfd, sect);
316 const struct ksplice_option *opt;
317 for (opt = ss->contents.data;
318 (void *)opt < ss->contents.data + ss->contents.size; opt++) {
319 if (opt->type == KSPLICE_OPTION_ASSUME_RODATA) {
320 arelent *reloc = find_reloc(ss, &opt->target);
321 struct span *span = reloc_target_span(ss, reloc);
322 assert(span != NULL);
323 assert(span->ss->type == SS_TYPE_DATA);
324 assert(span->start == 0 &&
325 span->size == span->ss->contents.size);
326 span->ss->type = SS_TYPE_RODATA;
327 break;
328 } else {
329 err(sbfd, "Unrecognized Ksplice option %d\n",
330 opt->type);
331 DIE;
336 bool matchable_data_section(struct supersect *ss)
338 if (ss->type == SS_TYPE_STRING)
339 return true;
340 if (ss->type == SS_TYPE_RODATA)
341 return true;
342 if (ss->type == SS_TYPE_DATA && ss->relocs.size != 0)
343 return true;
344 if (ss->type == SS_TYPE_EXPORT)
345 return true;
346 return false;
349 bool unchangeable_section(struct supersect *ss)
351 if (ss->type == SS_TYPE_DATA)
352 return true;
353 if (ss->type == SS_TYPE_IGNORED && !starts_with(ss->name, ".debug") &&
354 strcmp(ss->name, "__ksymtab_strings") != 0)
355 return true;
356 return false;
359 int main(int argc, char *argv[])
361 if (getenv("KSPLICE_VERBOSE") != NULL)
362 verbose = atoi(getenv("KSPLICE_VERBOSE"));
364 bfd_init();
365 bfd *ibfd = bfd_openr(argv[1], NULL);
366 assert(ibfd);
368 char **matching;
369 assert(bfd_check_format_matches(ibfd, bfd_object, &matching));
371 const char *output_target = bfd_get_target(ibfd);
373 load_system_map();
374 load_offsets();
376 bool_hash_init(&system_map_written);
377 ulong_hash_init(&ksplice_symbol_offset);
378 ulong_hash_init(&ksplice_howto_offset);
379 ulong_hash_init(&ksplice_string_offset);
381 struct superbfd *isbfd = fetch_superbfd(ibfd);
383 modestr = argv[3];
384 if (mode("finalize"))
385 finalize_target = argv[4];
386 init_objmanip_superbfd(isbfd);
387 if (mode("keep-primary")) {
388 kid = argv[5];
389 do_keep_primary(isbfd, argv[4]);
390 } else if (mode("keep-helper")) {
391 do_keep_helper(isbfd);
392 } else if (mode("finalize")) {
393 do_finalize(isbfd);
394 } else if (mode("rmsyms")) {
395 do_rmsyms(isbfd);
398 if (write_output) {
399 bfd *obfd = bfd_openw(argv[2], output_target);
400 assert(obfd);
401 copy_object(ibfd, obfd);
402 assert(bfd_close(obfd));
405 if (offsets_sbfd != NULL)
406 assert(bfd_close(offsets_sbfd->abfd));
407 assert(bfd_close(ibfd));
408 return EXIT_SUCCESS;
411 void do_keep_primary(struct superbfd *isbfd, const char *pre)
413 struct bfd *prebfd = bfd_openr(pre, NULL);
414 assert(prebfd != NULL);
415 char **matching;
416 assert(bfd_check_format_matches(prebfd, bfd_object, &matching));
418 struct superbfd *presbfd = fetch_superbfd(prebfd);
419 init_objmanip_superbfd(presbfd);
421 foreach_symbol_pair(presbfd, isbfd, match_global_symbols);
422 debug1(isbfd, "Matched global\n");
423 foreach_span_pair(presbfd, isbfd, match_string_spans);
424 debug1(isbfd, "Matched string spans\n");
425 foreach_symbol_pair(presbfd, isbfd, match_symbol_spans);
426 debug1(isbfd, "Matched by name\n");
427 foreach_span_pair(presbfd, isbfd, match_spans_by_label);
428 debug1(isbfd, "Matched by label\n");
430 do {
431 changed = false;
432 compare_matched_spans(isbfd);
433 update_nonzero_offsets(isbfd);
434 mark_new_spans(isbfd);
435 } while (changed);
436 vec_init(&delsects);
438 foreach_symbol_pair(presbfd, isbfd, check_global_symbols);
440 handle_deleted_spans(presbfd, isbfd);
441 handle_section_symbol_renames(presbfd, isbfd);
443 assert(bfd_close(prebfd));
445 do {
446 changed = false;
447 mark_precallable_spans(isbfd);
448 } while (changed);
450 asection *sect;
451 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
452 struct supersect *ss = fetch_supersect(isbfd, sect);
453 ss->keep = false;
454 struct span *span;
455 for (span = ss->spans.data;
456 span < ss->spans.data + ss->spans.size; span++) {
457 if (starts_with(ss->name, ".ksplice_options"))
458 span->keep = false;
459 else if (span->new || span->patch || span->datapatch)
460 keep_span(span);
461 else
462 span->keep = false;
463 if (span->patch && span->precallable) {
464 err(isbfd, "Patched span %s can be reached "
465 "by a precall function\n", span->label);
466 DIE;
471 print_label_changes(isbfd);
473 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
474 struct supersect *ss = fetch_supersect(isbfd, sect);
475 struct span *span;
476 for (span = ss->spans.data;
477 span < ss->spans.data + ss->spans.size; span++) {
478 if (span->patch || span->bugpatch || span->datapatch)
479 debug0(isbfd, "Patching span %s\n",
480 span->label);
484 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
485 struct supersect *ss = fetch_supersect(isbfd, sect);
486 struct span *span;
487 for (span = ss->spans.data;
488 span < ss->spans.data + ss->spans.size; span++) {
489 if (span->new)
490 debug0(isbfd, "New span %s\n", span->label);
494 write_output = false;
495 const char **sectname;
496 for (sectname = delsects.data;
497 sectname < delsects.data + delsects.size; sectname++) {
498 write_output = true;
499 debug0(isbfd, "Deleted section: %s\n", *sectname);
502 filter_table_sections(isbfd);
504 compute_span_shifts(isbfd);
506 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
507 struct supersect *ss = fetch_supersect(isbfd, sect);
508 if (ss->type == SS_TYPE_KSPLICE_CALL)
509 continue;
510 struct span *span;
511 for (span = ss->spans.data;
512 span < ss->spans.data + ss->spans.size; span++) {
513 if (span->keep)
514 write_output = true;
515 if (span->patch || span->new || span->datapatch)
516 write_ksplice_section(span);
517 if (span->patch || span->datapatch)
518 write_ksplice_patch(isbfd, span);
519 if (ss->type == SS_TYPE_EXPORT && span->new)
520 write_ksplice_export(isbfd, span, false);
524 write_bugline_patches(isbfd);
525 rm_relocs(isbfd);
526 remove_unkept_spans(isbfd);
529 void do_keep_helper(struct superbfd *isbfd)
531 asection *sect;
532 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
533 struct supersect *ss = fetch_supersect(isbfd, sect);
534 ss->keep = false;
535 struct span *span;
536 for (span = ss->spans.data;
537 span < ss->spans.data + ss->spans.size; span++) {
538 span->keep = false;
539 if (ss->type == SS_TYPE_TEXT &&
540 !starts_with(ss->name, ".fixup"))
541 keep_span(span);
542 if (ss->type == SS_TYPE_EXPORT)
543 keep_span(span);
547 asymbol **symp;
548 for (symp = isbfd->syms.data;
549 symp < isbfd->syms.data + isbfd->syms.size; symp++) {
550 asymbol *sym = *symp;
551 if (!bfd_is_const_section(sym->section) &&
552 (sym->flags & BSF_GLOBAL) != 0) {
553 struct supersect *sym_ss =
554 fetch_supersect(isbfd, sym->section);
555 if (sym->value == sym_ss->contents.size)
556 continue;
557 struct span *span = find_span(sym_ss, sym->value);
558 assert(span != NULL);
559 if (sym_ss->type != SS_TYPE_IGNORED)
560 keep_span(span);
564 do {
565 changed = false;
566 keep_referenced_sections(isbfd);
567 } while (changed);
569 filter_table_sections(isbfd);
570 compute_span_shifts(isbfd);
572 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
573 struct supersect *ss = fetch_supersect(isbfd, sect);
574 asymbol *sym = canonical_symbol(isbfd, sect->symbol);
575 if (sym == NULL)
576 continue;
577 if ((sym->flags & BSF_WEAK) != 0)
578 continue;
579 if (bfd_get_section_size(sect) == 0)
580 continue;
581 if (!ss->keep)
582 continue;
583 if (ss->type != SS_TYPE_TEXT && !matchable_data_section(ss))
584 continue;
586 struct span *span;
587 for (span = ss->spans.data;
588 span < ss->spans.data + ss->spans.size; span++) {
589 if (span->keep)
590 write_ksplice_section(span);
594 write_table_relocs(isbfd, "__bug_table", KSPLICE_HOWTO_BUG);
595 write_table_relocs(isbfd, "__ex_table", KSPLICE_HOWTO_EXTABLE);
596 rm_relocs(isbfd);
597 remove_unkept_spans(isbfd);
599 mangle_section_name(isbfd, "__markers");
600 mangle_section_name(isbfd, "__ex_table");
601 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
602 struct supersect *ss = fetch_supersect(isbfd, sect);
603 if (ss->type == SS_TYPE_EXPORT)
604 mangle_section_name(isbfd, ss->name);
608 void do_finalize(struct superbfd *isbfd)
610 load_ksplice_symbol_offsets(isbfd);
611 asection *sect;
612 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
613 struct supersect *ss = fetch_supersect(isbfd, sect);
614 if (ss->type == SS_TYPE_EXIT) {
615 struct span *span;
616 for (span = ss->spans.data;
617 span < ss->spans.data + ss->spans.size; span++)
618 span->keep = false;
619 ss->keep = false;
622 write_date_relocs(isbfd, "<{DATE...}>", KSPLICE_HOWTO_DATE);
623 write_date_relocs(isbfd, "<{TIME}>", KSPLICE_HOWTO_TIME);
624 rm_relocs(isbfd);
627 void do_rmsyms(struct superbfd *isbfd)
629 read_str_set(&rmsyms);
630 rm_relocs(isbfd);
633 void match_spans(struct span *old_span, struct span *new_span)
635 struct superbfd *sbfd = new_span->ss->parent;
636 if (old_span->match == new_span && new_span->match == old_span)
637 return;
638 if (old_span->match != NULL) {
639 err(sbfd, "Matching conflict: old %s: %s != %s\n",
640 old_span->label, old_span->match->label, new_span->label);
641 DIE;
643 if (new_span->match != NULL) {
644 err(sbfd, "Matching conflict: new %s: %s != %s\n",
645 new_span->label, new_span->match->label, old_span->label);
646 DIE;
648 old_span->match = new_span;
649 new_span->match = old_span;
650 debug1(sbfd, "Matched old %s to new %s\n", old_span->label,
651 new_span->label);
652 if (old_span->ss->type != new_span->ss->type &&
653 old_span->ss->type == new_span->ss->orig_type)
654 old_span->ss->type = new_span->ss->type;
657 static void match_global_symbols(struct span *old_span, asymbol *oldsym,
658 struct span *new_span, asymbol *newsym)
660 if ((oldsym->flags & BSF_GLOBAL) == 0 ||
661 (newsym->flags & BSF_GLOBAL) == 0)
662 return;
663 match_spans(old_span, new_span);
666 static void check_global_symbols(struct span *old_span, asymbol *oldsym,
667 struct span *new_span, asymbol *newsym)
669 if ((oldsym->flags & BSF_GLOBAL) == 0 ||
670 (newsym->flags & BSF_GLOBAL) == 0)
671 return;
672 if (old_span->ss->type == SS_TYPE_IGNORED)
673 return;
674 if (old_span->match != new_span || new_span->match != old_span) {
675 err(new_span->ss->parent, "Global symbol span mismatch: %s "
676 "%s/%s\n", oldsym->name, old_span->ss->name,
677 new_span->ss->name);
678 DIE;
682 static void foreach_symbol_pair(struct superbfd *oldsbfd, struct superbfd *newsbfd,
683 void (*fn)(struct span *old_span,
684 asymbol *oldsym,
685 struct span *new_span,
686 asymbol *newsym))
688 asymbol **oldsymp, **newsymp;
689 for (oldsymp = oldsbfd->syms.data;
690 oldsymp < oldsbfd->syms.data + oldsbfd->syms.size; oldsymp++) {
691 asymbol *oldsym = *oldsymp;
692 if (bfd_is_const_section(oldsym->section))
693 continue;
694 for (newsymp = newsbfd->syms.data;
695 newsymp < newsbfd->syms.data + newsbfd->syms.size;
696 newsymp++) {
697 asymbol *newsym = *newsymp;
698 if (bfd_is_const_section(newsym->section))
699 continue;
700 if (strcmp(oldsym->name, newsym->name) != 0)
701 continue;
703 struct supersect *old_ss =
704 fetch_supersect(oldsbfd, oldsym->section);
705 struct supersect *new_ss =
706 fetch_supersect(newsbfd, newsym->section);
707 if ((old_ss->type != new_ss->type &&
708 old_ss->type != new_ss->orig_type) ||
709 old_ss->type == SS_TYPE_SPECIAL ||
710 old_ss->type == SS_TYPE_EXPORT)
711 continue;
713 struct span *old_span =
714 find_span(old_ss, oldsym->value);
715 struct span *new_span =
716 find_span(new_ss, newsym->value);
717 if (old_span == NULL) {
718 err(oldsbfd, "Could not find span for %s\n",
719 oldsym->name);
720 DIE;
722 if (new_span == NULL) {
723 err(newsbfd, "Could not find span for %s\n",
724 newsym->name);
725 DIE;
727 fn(old_span, oldsym, new_span, newsym);
732 static void match_symbol_spans(struct span *old_span, asymbol *oldsym,
733 struct span *new_span, asymbol *newsym)
735 if ((oldsym->flags & BSF_DEBUGGING) != 0 ||
736 (newsym->flags & BSF_DEBUGGING) != 0)
737 return;
738 if (old_span->ss->type == SS_TYPE_SPECIAL)
739 return;
740 if (static_local_symbol(old_span->ss->parent, oldsym) ||
741 static_local_symbol(new_span->ss->parent, newsym))
742 return;
743 if (old_span->match == NULL && new_span->match == NULL)
744 match_spans(old_span, new_span);
747 static void match_spans_by_label(struct span *old_span, struct span *new_span)
749 if (old_span->ss->type == SS_TYPE_STRING)
750 return;
751 if (strcmp(old_span->label, new_span->label) == 0)
752 match_spans(old_span, new_span);
755 static void match_string_spans(struct span *old_span, struct span *new_span)
757 if (old_span->ss->type != SS_TYPE_STRING ||
758 strcmp(old_span->ss->name, new_span->ss->name) != 0)
759 return;
760 if (strcmp((char *)old_span->ss->contents.data + old_span->start,
761 (char *)new_span->ss->contents.data + new_span->start) == 0)
762 match_spans(old_span, new_span);
765 static void foreach_span_pair(struct superbfd *oldsbfd,
766 struct superbfd *newsbfd,
767 void (*fn)(struct span *old_span,
768 struct span *new_span))
770 asection *oldsect, *newsect;
771 struct supersect *oldss, *newss;
772 struct span *old_span, *new_span;
773 for (newsect = newsbfd->abfd->sections; newsect != NULL;
774 newsect = newsect->next) {
775 newss = fetch_supersect(newsbfd, newsect);
776 if (newss->type == SS_TYPE_SPECIAL)
777 continue;
778 for (oldsect = oldsbfd->abfd->sections; oldsect != NULL;
779 oldsect = oldsect->next) {
780 oldss = fetch_supersect(oldsbfd, oldsect);
781 if (oldss->type != newss->type)
782 continue;
783 for (new_span = newss->spans.data;
784 new_span < newss->spans.data + newss->spans.size;
785 new_span++) {
786 for (old_span = oldss->spans.data;
787 old_span < oldss->spans.data +
788 oldss->spans.size; old_span++)
789 fn(old_span, new_span);
795 static void mark_new_spans(struct superbfd *sbfd)
797 asection *sect;
798 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
799 struct supersect *ss = fetch_supersect(sbfd, sect);
800 if (ss->type == SS_TYPE_SPECIAL || ss->type == SS_TYPE_IGNORED)
801 continue;
802 struct span *span;
803 for (span = ss->spans.data;
804 span < ss->spans.data + ss->spans.size; span++) {
805 if (span->match == NULL && !span->bugpatch)
806 span->new = true;
811 static void handle_deleted_spans(struct superbfd *oldsbfd,
812 struct superbfd *newsbfd)
814 asection *sect;
815 for (sect = oldsbfd->abfd->sections; sect != NULL; sect = sect->next) {
816 struct supersect *ss = fetch_supersect(oldsbfd, sect);
817 struct span *span;
818 for (span = ss->spans.data;
819 span < ss->spans.data + ss->spans.size; span++) {
820 if (span->match != NULL)
821 continue;
822 if (ss->type == SS_TYPE_EXPORT) {
823 *vec_grow(&delsects, 1) = span->label;
824 write_ksplice_export(newsbfd, span, true);
825 } else if (ss->type == SS_TYPE_TEXT) {
826 *vec_grow(&delsects, 1) = span->label;
827 if (span->symbol == NULL)
828 DIE;
829 write_ksplice_deleted_patch
830 (newsbfd, span->symbol->name, span->label,
831 span->ss->name);
837 static void handle_nonzero_offset_relocs(struct supersect *ss)
839 struct span *address_span, *target_span;
840 arelent **relocp;
841 for (relocp = ss->relocs.data;
842 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
843 arelent *reloc = *relocp;
844 address_span = find_span(ss, reloc->address);
845 if (!address_span->new && !address_span->patch)
846 continue;
848 asymbol *sym = *reloc->sym_ptr_ptr;
849 if (bfd_is_const_section(sym->section))
850 continue;
851 bfd_vma offset = get_reloc_offset(ss, reloc, true);
852 target_span = reloc_target_span(ss, reloc);
853 if (sym->value + offset == target_span->start)
854 continue;
856 if (target_span->ss->type != SS_TYPE_TEXT)
857 continue;
858 if (target_span->patch)
859 continue;
861 target_span->patch = true;
862 changed = true;
863 debug1(ss->parent, "Changing %s because a relocation from sect "
864 "%s has a nonzero offset %lx+%lx into it\n",
865 target_span->label, ss->name, (unsigned long)sym->value,
866 (unsigned long)offset);
870 static void update_nonzero_offsets(struct superbfd *sbfd)
872 asection *sect;
873 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
874 struct supersect *ss = fetch_supersect(sbfd, sect);
875 if (ss->type == SS_TYPE_SPECIAL || ss->type == SS_TYPE_IGNORED)
876 continue;
877 handle_nonzero_offset_relocs(ss);
881 static void compare_spans(struct span *old_span, struct span *new_span)
883 struct superbfd *newsbfd = new_span->ss->parent;
885 bool nonrelocs_match = nonrelocs_equal(old_span, new_span);
886 bool relocs_match = all_relocs_equal(old_span, new_span);
887 if (nonrelocs_match && relocs_match)
888 return;
889 if (strcmp(old_span->ss->name, "__bug_table") == 0 &&
890 strcmp(new_span->ss->name, "__bug_table") == 0 && relocs_match) {
891 debug1(newsbfd, "Changing %s due to nonmatching line numbers\n",
892 new_span->label);
893 new_span->match = NULL;
894 old_span->match = NULL;
895 new_span->bugpatch = true;
896 return;
899 char *reason;
900 if (new_span->contents_size != old_span->contents_size)
901 reason = "differing sizes";
902 else if (!nonrelocs_match)
903 reason = "differing contents";
904 else
905 reason = "differing relocations";
907 if (new_span->ss->type == SS_TYPE_TEXT) {
908 if (new_span->patch)
909 return;
910 new_span->patch = true;
911 debug1(newsbfd, "Changing %s due to %s\n", new_span->label,
912 reason);
913 } else if (new_span->ss->type == SS_TYPE_RODATA &&
914 new_span->contents_size == old_span->contents_size) {
915 if (new_span->datapatch)
916 return;
917 new_span->datapatch = true;
918 debug1(newsbfd, "Changing %s in-place due to %s\n",
919 new_span->label, reason);
920 } else if (new_span->ss->type == SS_TYPE_STRING &&
921 old_span->ss->type == SS_TYPE_STRING && relocs_match &&
922 strcmp(new_span->ss->contents.data + new_span->start,
923 old_span->ss->contents.data + old_span->start) == 0) {
924 return;
925 } else {
926 debug1(newsbfd, "Unmatching %s and %s due to %s\n",
927 old_span->label, new_span->label, reason);
928 new_span->match = NULL;
929 old_span->match = NULL;
931 changed = true;
932 if (unchangeable_section(new_span->ss))
933 err(newsbfd, "warning: ignoring change to nonpatchable "
934 "section %s\n", new_span->ss->name);
937 static void compare_matched_spans(struct superbfd *newsbfd)
939 asection *sect;
940 for (sect = newsbfd->abfd->sections; sect != NULL; sect = sect->next) {
941 struct supersect *ss = fetch_supersect(newsbfd, sect);
942 struct span *span;
943 for (span = ss->spans.data;
944 span < ss->spans.data + ss->spans.size; span++) {
945 if (span->match == NULL)
946 continue;
947 compare_spans(span->match, span);
952 static void handle_section_symbol_renames(struct superbfd *oldsbfd,
953 struct superbfd *newsbfd)
955 asection *sect;
956 struct span *span;
957 for (sect = newsbfd->abfd->sections; sect != NULL; sect = sect->next) {
958 struct supersect *ss = fetch_supersect(newsbfd, sect);
959 for (span = ss->spans.data;
960 span < ss->spans.data + ss->spans.size; span++) {
961 if (span->match == NULL)
962 continue;
963 if (strcmp(span->label, span->match->label) == 0)
964 continue;
965 if (strcmp(span->orig_label, span->label) != 0 &&
966 strcmp(span->label, span->match->label) != 0)
967 DIE;
968 if (span->symbol != NULL)
969 label_map_set(newsbfd, span->label,
970 span->match->label);
971 span->label = span->match->label;
976 static bool part_of_reloc(struct supersect *ss, unsigned long addr)
978 arelent **relocp;
979 for (relocp = ss->relocs.data;
980 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
981 arelent *reloc = *relocp;
982 if (addr >= reloc->address &&
983 addr < reloc->address + reloc->howto->size)
984 return true;
986 return false;
989 static bool nonrelocs_equal(struct span *old_span, struct span *new_span)
991 int i;
992 struct supersect *old_ss = old_span->ss, *new_ss = new_span->ss;
993 if (old_span->contents_size != new_span->contents_size)
994 return false;
995 const unsigned char *old = old_ss->contents.data + old_span->start;
996 const unsigned char *new = new_ss->contents.data + new_span->start;
997 for (i = 0; i < old_span->contents_size; i++) {
998 if (old[i] != new[i] &&
999 !(part_of_reloc(old_ss, i + old_span->start) &&
1000 part_of_reloc(new_ss, i + new_span->start)))
1001 return false;
1003 return true;
1006 bool relocs_equal(struct supersect *old_src_ss, struct supersect *new_src_ss,
1007 arelent *old_reloc, arelent *new_reloc)
1009 struct superbfd *oldsbfd = old_src_ss->parent;
1010 struct superbfd *newsbfd = new_src_ss->parent;
1011 struct span *old_addr_span = find_span(old_src_ss, old_reloc->address);
1012 struct span *new_addr_span = find_span(new_src_ss, new_reloc->address);
1014 if (old_reloc->address - old_addr_span->start !=
1015 new_reloc->address - new_addr_span->start) {
1016 debug1(newsbfd, "Section %s/%s has reloc address mismatch at "
1017 "%lx\n", old_src_ss->name, new_src_ss->name,
1018 (unsigned long)old_reloc->address);
1019 return false;
1022 if (old_reloc->howto != new_reloc->howto) {
1023 debug1(newsbfd, "Section %s/%s has howto type mismatch at "
1024 "%lx\n", old_src_ss->name, new_src_ss->name,
1025 (unsigned long)old_reloc->address);
1026 return false;
1029 if (non_dst_mask(old_src_ss, old_reloc) !=
1030 non_dst_mask(new_src_ss, new_reloc)) {
1031 debug1(newsbfd, "Section %s/%s has contents mismatch at %lx\n",
1032 old_src_ss->name, new_src_ss->name,
1033 (unsigned long)old_reloc->address);
1034 return false;
1037 asymbol *old_sym = *old_reloc->sym_ptr_ptr;
1038 asymbol *new_sym = *new_reloc->sym_ptr_ptr;
1039 asection *old_sect = old_sym->section;
1040 asection *new_sect = new_sym->section;
1042 bfd_vma old_offset = get_reloc_offset(old_src_ss, old_reloc, true);
1043 bfd_vma new_offset = get_reloc_offset(new_src_ss, new_reloc, true);
1045 if (bfd_is_und_section(old_sect) || bfd_is_und_section(new_sect)) {
1046 if (!bfd_is_und_section(new_sect) && old_offset != 0 &&
1047 fetch_supersect(newsbfd, new_sect)->type == SS_TYPE_TEXT)
1048 return false;
1050 if (!bfd_is_und_section(new_sect) && new_offset != 0 &&
1051 fetch_supersect(oldsbfd, old_sect)->type == SS_TYPE_TEXT)
1052 return false;
1054 return strcmp(old_sym->name, new_sym->name) == 0 &&
1055 old_offset == new_offset;
1058 if (bfd_is_abs_section(old_sect) && bfd_is_abs_section(new_sect)) {
1059 if (old_offset + old_sym->value == new_offset + new_sym->value)
1060 return true;
1061 debug1(newsbfd, "Differing relocations from %s/%s to ABS "
1062 "section: %lx/%lx\n", old_addr_span->label,
1063 new_addr_span->label,
1064 (unsigned long)(old_offset + old_sym->value),
1065 (unsigned long)(new_offset + new_sym->value));
1066 return false;
1069 if (bfd_is_const_section(old_sect) || bfd_is_const_section(new_sect))
1070 DIE;
1072 struct supersect *old_ss = fetch_supersect(oldsbfd, old_sect);
1073 struct supersect *new_ss = fetch_supersect(newsbfd, new_sect);
1074 struct span *old_span = reloc_target_span(old_src_ss, old_reloc);
1075 struct span *new_span = reloc_target_span(new_src_ss, new_reloc);
1077 if (old_span->match != new_span || new_span->match != old_span) {
1078 debug1(newsbfd, "Nonmatching relocs from %s to %s/%s\n",
1079 new_src_ss->name, old_span->label, new_span->label);
1080 return false;
1083 if (old_sym->value + old_offset - old_span->start !=
1084 new_sym->value + new_offset - new_span->start) {
1085 debug1(newsbfd, "Offsets to %s/%s differ between %s "
1086 "and %s: %lx+%lx/%lx+%lx\n", old_ss->name,
1087 new_ss->name, old_src_ss->name, new_src_ss->name,
1088 (unsigned long)old_sym->value, (unsigned long)old_offset,
1089 (unsigned long)new_sym->value,
1090 (unsigned long)new_offset);
1091 return false;
1094 if ((old_sym->value + old_offset - old_span->start != 0 ||
1095 new_sym->value + new_offset - new_span->start != 0) &&
1096 new_span->patch) {
1097 debug1(newsbfd, "Relocation from %s to nonzero offsets "
1098 "%lx+%lx/%lx+%lx in changed section %s\n",
1099 new_src_ss->name, (unsigned long)old_sym->value,
1100 (unsigned long)old_offset, (unsigned long)new_sym->value,
1101 (unsigned long)new_offset, new_sym->section->name);
1102 return false;
1104 return true;
1107 bool all_relocs_equal(struct span *old_span, struct span *new_span)
1109 struct supersect *old_ss = old_span->ss, *new_ss = new_span->ss;
1110 arelent **old_relocp, **new_relocp;
1112 for (old_relocp = old_ss->relocs.data;
1113 old_relocp < old_ss->relocs.data + old_ss->relocs.size;
1114 old_relocp++) {
1115 if (find_span(old_ss, (*old_relocp)->address) == old_span)
1116 break;
1119 for (new_relocp = new_ss->relocs.data;
1120 new_relocp < new_ss->relocs.data + new_ss->relocs.size;
1121 new_relocp++) {
1122 if (find_span(new_ss, (*new_relocp)->address) == new_span)
1123 break;
1126 for (; old_relocp < old_ss->relocs.data + old_ss->relocs.size &&
1127 find_span(old_ss, (*old_relocp)->address) == old_span &&
1128 new_relocp < new_ss->relocs.data + new_ss->relocs.size &&
1129 find_span(new_ss, (*new_relocp)->address) == new_span;
1130 old_relocp++, new_relocp++) {
1131 if (!relocs_equal(old_ss, new_ss, *old_relocp, *new_relocp))
1132 return false;
1135 if ((old_relocp < old_ss->relocs.data + old_ss->relocs.size &&
1136 find_span(old_ss, (*old_relocp)->address) == old_span) ||
1137 (new_relocp < new_ss->relocs.data + new_ss->relocs.size &&
1138 find_span(new_ss, (*new_relocp)->address) == new_span)) {
1139 debug1(new_ss->parent, "Different reloc count between %s and "
1140 "%s\n", old_span->label, new_span->label);
1141 return false;
1144 return true;
1147 bfd_vma non_dst_mask(struct supersect *ss, arelent *reloc)
1149 int bits = bfd_get_reloc_size(reloc->howto) * 8;
1150 void *address = ss->contents.data + reloc->address;
1151 bfd_vma x = bfd_get(bits, ss->parent->abfd, address);
1152 return x & ~reloc->howto->dst_mask;
1155 void rm_relocs(struct superbfd *isbfd)
1157 asection *p;
1158 for (p = isbfd->abfd->sections; p != NULL; p = p->next) {
1159 struct supersect *ss = fetch_supersect(isbfd, p);
1160 bool remove_relocs = ss->keep;
1162 if (mode("keep") && ss->type == SS_TYPE_SPECIAL)
1163 remove_relocs = false;
1165 if (ss->type == SS_TYPE_KSPLICE ||
1166 ss->type == SS_TYPE_KSPLICE_CALL)
1167 remove_relocs = false;
1168 if (mode("finalize") &&
1169 (starts_with(ss->name, ".ksplice_patches") ||
1170 starts_with(ss->name, ".ksplice_relocs")))
1171 remove_relocs = true;
1173 if (remove_relocs)
1174 rm_some_relocs(ss);
1178 void rm_some_relocs(struct supersect *ss)
1180 struct arelentp_vec orig_relocs;
1181 vec_move(&orig_relocs, &ss->relocs);
1183 arelent **relocp;
1184 for (relocp = orig_relocs.data;
1185 relocp < orig_relocs.data + orig_relocs.size; relocp++) {
1186 bool rm_reloc = false;
1187 asymbol *sym_ptr = *(*relocp)->sym_ptr_ptr;
1189 if (mode("rmsyms") && str_in_set(sym_ptr->name, &rmsyms) &&
1190 bfd_is_und_section(sym_ptr->section))
1191 rm_reloc = true;
1193 if (mode("keep"))
1194 rm_reloc = true;
1196 if (mode("keep-primary") &&
1197 (bfd_is_const_section(sym_ptr->section) ||
1198 reloc_target_span(ss, *relocp)->new))
1199 rm_reloc = false;
1201 if (mode("keep-primary")) {
1202 const struct table_section *ts =
1203 get_table_section(ss->name);
1204 if (ts != NULL && ts->has_addr &&
1205 ((*relocp)->address % ts->entry_size ==
1206 ts->addr_offset ||
1207 (*relocp)->address % ts->entry_size ==
1208 ts->other_offset))
1209 rm_reloc = false;
1212 if (mode("finalize") && bfd_is_und_section(sym_ptr->section))
1213 rm_reloc = true;
1215 if (strcmp(sym_ptr->name, "mcount") == 0 &&
1216 bfd_is_und_section(sym_ptr->section))
1217 rm_reloc = false;
1219 if (!find_span(ss, (*relocp)->address)->keep)
1220 rm_reloc = false;
1222 if (rm_reloc)
1223 write_ksplice_reloc(ss, *relocp);
1224 else
1225 *vec_grow(&ss->relocs, 1) = *relocp;
1229 struct supersect *make_section(struct superbfd *sbfd, const char *fmt, ...)
1231 va_list ap;
1232 va_start(ap, fmt);
1233 char *name = vstrprintf(fmt, ap);
1234 va_end(ap);
1236 asection *sect = bfd_get_section_by_name(sbfd->abfd, name);
1237 if (sect != NULL)
1238 return fetch_supersect(sbfd, sect);
1239 else
1240 return new_supersect(sbfd, name);
1243 arelent *create_reloc(struct supersect *ss, const void *addr, asymbol **symp,
1244 bfd_vma offset)
1246 bfd_reloc_code_real_type code;
1247 switch (bfd_arch_bits_per_address(ss->parent->abfd)) {
1248 case 32:
1249 code = BFD_RELOC_32;
1250 break;
1251 case 64:
1252 code = BFD_RELOC_64;
1253 break;
1254 default:
1255 DIE;
1258 arelent *reloc = malloc(sizeof(*reloc));
1259 reloc->sym_ptr_ptr = symp;
1260 reloc->address = addr_offset(ss, addr);
1261 reloc->howto = bfd_reloc_type_lookup(ss->parent->abfd, code);
1262 reloc->addend = offset;
1263 return reloc;
1266 void write_reloc(struct supersect *ss, const void *addr, asymbol **symp,
1267 bfd_vma offset)
1269 *vec_grow(&ss->new_relocs, 1) = create_reloc(ss, addr, symp, offset);
1272 void write_string(struct supersect *ss, const char **addr, const char *fmt, ...)
1274 va_list ap;
1275 struct supersect *str_ss = make_section(ss->parent, ".ksplice_str");
1276 char *str;
1277 va_start(ap, fmt);
1278 int len = vasprintf(&str, fmt, ap);
1279 assert(len >= 0);
1280 va_end(ap);
1282 unsigned long *str_offp = ulong_hash_lookup(&ksplice_string_offset, str,
1283 FALSE);
1284 if (str_offp == NULL) {
1285 char *buf = sect_grow(str_ss, len + 1, char);
1286 memcpy(buf, str, len + 1);
1287 str_offp = ulong_hash_lookup(&ksplice_string_offset, str, TRUE);
1288 *str_offp = addr_offset(str_ss, buf);
1291 write_reloc(ss, addr, &str_ss->symbol, *str_offp);
1294 void lookup_system_map(struct addr_vec *addrs, const char *name, long offset)
1296 struct addr_vec *map_addrs =
1297 addr_vec_hash_lookup(&system_map, name, FALSE);
1298 if (map_addrs == NULL)
1299 return;
1301 unsigned long *addr, *map_addr;
1302 for (map_addr = map_addrs->data;
1303 map_addr < map_addrs->data + map_addrs->size; map_addr++) {
1304 for (addr = addrs->data; addr < addrs->data + addrs->size;
1305 addr++) {
1306 if (*addr == *map_addr + offset)
1307 break;
1309 if (addr < addrs->data + addrs->size)
1310 continue;
1311 *vec_grow(addrs, 1) = *map_addr + offset;
1315 void compute_system_map_array(struct superbfd *sbfd, struct addr_vec *addrs,
1316 asymbol *sym)
1318 if (bfd_is_abs_section(sym->section)) {
1319 *vec_grow(addrs, 1) = sym->value;
1320 } else if (bfd_is_und_section(sym->section)) {
1321 lookup_system_map(addrs, sym->name, 0);
1322 } else if (!bfd_is_const_section(sym->section)) {
1323 asymbol **gsymp;
1324 for (gsymp = sbfd->syms.data;
1325 gsymp < sbfd->syms.data + sbfd->syms.size; gsymp++) {
1326 asymbol *gsym = *gsymp;
1327 if ((gsym->flags & BSF_DEBUGGING) == 0 &&
1328 gsym->section == sym->section)
1329 lookup_system_map(addrs, gsym->name,
1330 sym->value - gsym->value);
1335 void write_ksplice_system_map(struct superbfd *sbfd, asymbol *sym,
1336 const char *label)
1338 bool *done = bool_hash_lookup(&system_map_written, label, TRUE);
1339 if (*done)
1340 return;
1341 *done = true;
1343 struct addr_vec addrs;
1344 vec_init(&addrs);
1346 compute_system_map_array(sbfd, &addrs, sym);
1347 if (addrs.size != 0) {
1348 struct supersect *smap_ss =
1349 make_section(sbfd, ".ksplice_system_map");
1350 struct ksplice_system_map *smap =
1351 sect_grow(smap_ss, 1, struct ksplice_system_map);
1352 write_string(smap_ss, &smap->label, "%s", label);
1354 struct supersect *array_ss = make_section(sbfd,
1355 ".ksplice_array");
1356 void *buf = sect_grow(array_ss, addrs.size,
1357 typeof(*addrs.data));
1358 memcpy(buf, addrs.data, addrs.size * sizeof(*addrs.data));
1359 smap->nr_candidates = addrs.size;
1360 write_reloc(smap_ss, &smap->candidates, &array_ss->symbol,
1361 addr_offset(array_ss, buf));
1363 vec_free(&addrs);
1366 void write_ksplice_symbol_backend(struct supersect *ss,
1367 struct ksplice_symbol *const *addr,
1368 asymbol *sym, const char *label,
1369 const char *name)
1371 struct supersect *ksymbol_ss = make_section(ss->parent,
1372 ".ksplice_symbols");
1373 struct ksplice_symbol *ksymbol;
1374 unsigned long *ksymbol_offp;
1376 ksymbol_offp = ulong_hash_lookup(&ksplice_symbol_offset, label, FALSE);
1377 if (ksymbol_offp != NULL) {
1378 write_reloc(ss, addr, &ksymbol_ss->symbol, *ksymbol_offp);
1379 return;
1381 ksymbol = sect_grow(ksymbol_ss, 1, struct ksplice_symbol);
1382 ksymbol_offp = ulong_hash_lookup(&ksplice_symbol_offset, label, TRUE);
1383 *ksymbol_offp = addr_offset(ksymbol_ss, ksymbol);
1385 write_reloc(ss, addr, &ksymbol_ss->symbol, *ksymbol_offp);
1386 write_string(ksymbol_ss, &ksymbol->label, "%s", label);
1387 if (name != NULL) {
1388 write_string(ksymbol_ss, &ksymbol->name, "%s", name);
1389 write_ksplice_system_map(ksymbol_ss->parent, sym, label);
1393 void write_ksplice_symbol(struct supersect *ss,
1394 struct ksplice_symbol *const *addr,
1395 asymbol *sym, struct span *span,
1396 const char *addstr_sect)
1398 const char *label, *name;
1399 if (span != NULL && span->start != 0)
1400 label = span->label;
1401 else
1402 label = label_lookup(ss->parent, sym);
1404 asymbol *gsym = canonical_symbol(ss->parent, sym);
1405 if (strcmp(addstr_sect, "") != 0)
1406 name = NULL;
1407 else if (bfd_is_und_section(sym->section))
1408 name = sym->name;
1409 else if (bfd_is_const_section(sym->section))
1410 name = NULL;
1411 else if (span != NULL && span->symbol == NULL)
1412 name = NULL;
1413 else if (gsym == NULL || (gsym->flags & BSF_SECTION_SYM) != 0)
1414 name = NULL;
1415 else
1416 name = gsym->name;
1418 write_ksplice_symbol_backend(ss, addr, sym,
1419 strprintf("%s%s", addstr_sect, label),
1420 name);
1423 void write_ksplice_reloc(struct supersect *ss, arelent *orig_reloc)
1425 asymbol *sym_ptr = *orig_reloc->sym_ptr_ptr;
1426 bfd_vma reloc_addend = get_reloc_offset(ss, orig_reloc, false);
1427 bfd_vma target_addend = get_reloc_offset(ss, orig_reloc, true);
1428 unsigned long *repladdr = ss->contents.data + orig_reloc->address;
1430 if (mode("finalize") && starts_with(ss->name, ".ksplice_patches")) {
1431 *repladdr = 0;
1432 return;
1434 if (mode("finalize") && starts_with(ss->name, ".ksplice_relocs")) {
1435 assert(starts_with(sym_ptr->name, KSPLICE_SYMBOL_STR));
1436 asymbol fake_sym;
1437 fake_sym.name = sym_ptr->name + strlen(KSPLICE_SYMBOL_STR);
1438 fake_sym.section = bfd_und_section_ptr;
1439 fake_sym.value = 0;
1440 fake_sym.flags = 0;
1442 write_ksplice_symbol_backend
1443 (ss, (struct ksplice_symbol **)repladdr, &fake_sym,
1444 fake_sym.name, fake_sym.name);
1445 return;
1448 struct span *span = reloc_target_span(ss, orig_reloc);
1449 if (span == ss->spans.data && span->start != target_addend)
1450 span = NULL;
1451 write_canary(ss, orig_reloc->address,
1452 bfd_get_reloc_size(orig_reloc->howto),
1453 orig_reloc->howto->dst_mask);
1455 struct supersect *kreloc_ss;
1456 if (mode("rmsyms"))
1457 kreloc_ss = make_section(ss->parent, ".ksplice_init_relocs");
1458 else
1459 kreloc_ss = make_section(ss->parent, ".ksplice_relocs%s",
1460 ss->name);
1461 struct ksplice_reloc *kreloc = sect_grow(kreloc_ss, 1,
1462 struct ksplice_reloc);
1464 struct span *address_span = find_span(ss, orig_reloc->address);
1465 write_reloc(kreloc_ss, &kreloc->blank_addr,
1466 &ss->symbol, orig_reloc->address + address_span->shift);
1467 if (bfd_is_und_section(sym_ptr->section) && mode("keep")) {
1468 char *name = strprintf(KSPLICE_SYMBOL_STR "%s", sym_ptr->name);
1469 asymbol **symp = make_undefined_symbolp(ss->parent, name);
1470 write_reloc(kreloc_ss, &kreloc->symbol, symp, 0);
1471 } else {
1472 write_ksplice_symbol(kreloc_ss, &kreloc->symbol, sym_ptr, span,
1473 "");
1475 if (span != NULL && span->start != 0) {
1476 reloc_addend += sym_ptr->value - span->start;
1477 target_addend += sym_ptr->value - span->start;
1479 kreloc->insn_addend = reloc_addend - target_addend;
1480 kreloc->target_addend = target_addend;
1481 write_ksplice_reloc_howto(kreloc_ss, &kreloc->howto, orig_reloc->howto,
1482 KSPLICE_HOWTO_RELOC);
1485 static void write_ksplice_reloc_howto(struct supersect *ss, const
1486 struct ksplice_reloc_howto *const *addr,
1487 reloc_howto_type *howto,
1488 enum ksplice_reloc_howto_type type)
1490 struct supersect *khowto_ss = make_section(ss->parent,
1491 ".ksplice_reloc_howtos");
1492 struct ksplice_reloc_howto *khowto;
1493 unsigned long *khowto_offp;
1495 khowto_offp = ulong_hash_lookup(&ksplice_howto_offset, howto->name,
1496 FALSE);
1497 if (khowto_offp != NULL) {
1498 write_reloc(ss, addr, &khowto_ss->symbol, *khowto_offp);
1499 return;
1501 khowto = sect_grow(khowto_ss, 1, struct ksplice_reloc_howto);
1502 khowto_offp = ulong_hash_lookup(&ksplice_howto_offset, howto->name,
1503 TRUE);
1504 *khowto_offp = addr_offset(khowto_ss, khowto);
1506 khowto->type = type;
1507 khowto->pcrel = howto->pc_relative;
1508 khowto->size = bfd_get_reloc_size(howto);
1509 khowto->dst_mask = howto->dst_mask;
1510 khowto->rightshift = howto->rightshift;
1511 khowto->signed_addend =
1512 (howto->complain_on_overflow == complain_overflow_signed) ||
1513 (howto->complain_on_overflow == complain_overflow_bitfield);
1514 write_reloc(ss, addr, &khowto_ss->symbol, *khowto_offp);
1517 #define CANARY(x, canary) ((x & ~howto->dst_mask) | (canary & howto->dst_mask))
1519 void write_canary(struct supersect *ss, int offset, bfd_size_type size,
1520 bfd_vma dst_mask)
1522 int bits = size * 8;
1523 void *address = ss->contents.data + offset;
1524 bfd_vma x = bfd_get(bits, ss->parent->abfd, address);
1525 x = (x & ~dst_mask) | ((bfd_vma)KSPLICE_CANARY & dst_mask);
1526 bfd_put(bits, ss->parent->abfd, x, address);
1529 static void write_date_relocs(struct superbfd *sbfd, const char *str,
1530 enum ksplice_reloc_howto_type type)
1532 asection *sect;
1533 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
1534 struct supersect *ss = fetch_supersect(sbfd, sect);
1535 if (ss->type != SS_TYPE_STRING && ss->type != SS_TYPE_RODATA)
1536 continue;
1537 void *ptr;
1538 struct span *span;
1539 for (span = ss->spans.data;
1540 span < ss->spans.data + ss->spans.size; span++) {
1541 if (!span->keep)
1542 continue;
1543 for (ptr = ss->contents.data + span->start;
1544 ptr + strlen(str) < ss->contents.data +
1545 span->start + span->contents_size; ptr++) {
1546 if (strcmp((const char *)ptr, str) == 0)
1547 write_ksplice_date_reloc
1548 (ss, addr_offset(ss, ptr), str,
1549 type);
1555 static void write_ksplice_date_reloc(struct supersect *ss, unsigned long offset,
1556 const char *str,
1557 enum ksplice_reloc_howto_type type)
1559 struct supersect *kreloc_ss;
1560 kreloc_ss = make_section(ss->parent, ".ksplice_relocs%s", ss->name);
1561 struct ksplice_reloc *kreloc = sect_grow(kreloc_ss, 1,
1562 struct ksplice_reloc);
1564 const char *filename = ss->parent->abfd->filename;
1565 char *c = strstr(filename, ".KSPLICE");
1566 int flen = (c == NULL ? strlen(filename) : c - filename);
1568 write_ksplice_symbol_backend(kreloc_ss, &kreloc->symbol, NULL,
1569 strprintf("%s<%.*s>", str, flen, filename),
1570 NULL);
1572 struct span *span = find_span(ss, offset);
1573 write_reloc(kreloc_ss, &kreloc->blank_addr, &ss->symbol,
1574 offset + span->shift);
1575 write_ksplice_nonreloc_howto(kreloc_ss, &kreloc->howto, type,
1576 strlen(str));
1579 static void write_table_relocs(struct superbfd *sbfd, const char *sectname,
1580 enum ksplice_reloc_howto_type type)
1582 asection *sect = bfd_get_section_by_name(sbfd->abfd, sectname);
1583 if (sect == NULL)
1584 return;
1585 struct supersect *ss = fetch_supersect(sbfd, sect);
1587 const struct table_section *s = get_table_section(sectname);
1588 if (s == NULL)
1589 DIE;
1591 void *entry;
1592 for (entry = ss->contents.data;
1593 entry < ss->contents.data + ss->contents.size;
1594 entry += s->entry_size) {
1595 struct span *span = find_span(ss, addr_offset(ss, entry));
1596 assert(span != NULL);
1597 if (!span->keep)
1598 continue;
1600 arelent *reloc = find_reloc(ss, entry + s->addr_offset);
1601 assert(reloc != NULL);
1602 asymbol *sym = *reloc->sym_ptr_ptr;
1603 assert(!bfd_is_const_section(sym->section));
1604 struct supersect *sym_ss = fetch_supersect(sbfd, sym->section);
1605 unsigned long addr = get_reloc_offset(ss, reloc, true) +
1606 sym->value;
1607 write_ksplice_table_reloc(sym_ss, addr, span->label, type);
1611 static void write_ksplice_table_reloc(struct supersect *ss,
1612 unsigned long address,
1613 const char *label,
1614 enum ksplice_reloc_howto_type type)
1616 struct supersect *kreloc_ss;
1617 kreloc_ss = make_section(ss->parent, ".ksplice_relocs%s", ss->name);
1618 struct ksplice_reloc *kreloc = sect_grow(kreloc_ss, 1,
1619 struct ksplice_reloc);
1620 struct span *span = find_span(ss, address);
1621 assert(span != NULL);
1623 write_ksplice_symbol_backend(kreloc_ss, &kreloc->symbol, NULL,
1624 label, NULL);
1625 write_reloc(kreloc_ss, &kreloc->blank_addr, &ss->symbol,
1626 address + span->shift);
1627 write_ksplice_nonreloc_howto(kreloc_ss, &kreloc->howto, type, 0);
1630 static void write_ksplice_nonreloc_howto(struct supersect *ss,
1631 const struct ksplice_reloc_howto
1632 *const *addr,
1633 enum ksplice_reloc_howto_type type,
1634 int size)
1636 struct supersect *khowto_ss =
1637 make_section(ss->parent, ".ksplice_reloc_howtos");
1638 struct ksplice_reloc_howto *khowto =
1639 sect_grow(khowto_ss, 1, struct ksplice_reloc_howto);
1641 khowto->type = type;
1642 khowto->size = size;
1643 khowto->pcrel = 0;
1644 khowto->dst_mask = 0;
1645 khowto->rightshift = 0;
1646 khowto->signed_addend = 0;
1647 write_reloc(ss, addr, &khowto_ss->symbol,
1648 addr_offset(khowto_ss, khowto));
1651 static void write_ksplice_section(struct span *span)
1653 struct supersect *ss = span->ss;
1654 const char *sectname = span->ss->name;
1655 const struct table_section *ts = get_table_section(ss->name);
1657 if (ts != NULL && ts->has_addr) {
1658 arelent *reloc = find_reloc(ss, ss->contents.data + span->start
1659 + ts->addr_offset);
1660 assert(reloc != NULL);
1661 asymbol *rsym = *reloc->sym_ptr_ptr;
1662 assert(!bfd_is_const_section(rsym->section));
1663 sectname = rsym->section->name;
1666 struct supersect *ksect_ss =
1667 make_section(ss->parent, ".ksplice_sections%s", sectname);
1668 struct ksplice_section *ksect = sect_grow(ksect_ss, 1,
1669 struct ksplice_section);
1670 asymbol *sym = span->symbol == NULL ? ss->symbol : span->symbol;
1672 write_ksplice_symbol(ksect_ss, &ksect->symbol, sym, span,
1673 mode("keep-primary") ? "(post)" : "");
1674 ksect->size = span->size;
1675 ksect->flags = 0;
1677 if (ss->type == SS_TYPE_RODATA || ss->type == SS_TYPE_STRING ||
1678 ss->type == SS_TYPE_EXPORT)
1679 ksect->flags |= KSPLICE_SECTION_RODATA;
1680 if (ss->type == SS_TYPE_DATA)
1681 ksect->flags |= KSPLICE_SECTION_DATA;
1682 if (ss->type == SS_TYPE_TEXT)
1683 ksect->flags |= KSPLICE_SECTION_TEXT;
1684 assert(ksect->flags != 0);
1686 if (ss->type == SS_TYPE_STRING)
1687 ksect->flags |= KSPLICE_SECTION_STRING;
1689 write_reloc(ksect_ss, &ksect->address, &ss->symbol,
1690 span->start + span->shift);
1693 static void write_ksplice_patch_reloc(struct supersect *ss,
1694 const char *sectname, unsigned long *addr,
1695 bfd_size_type size, const char *label,
1696 long addend)
1698 struct supersect *kreloc_ss;
1699 kreloc_ss = make_section(ss->parent, ".ksplice_relocs%s", sectname);
1700 struct ksplice_reloc *kreloc = sect_grow(kreloc_ss, 1,
1701 struct ksplice_reloc);
1703 write_canary(ss, addr_offset(ss, addr), size, -1);
1704 write_ksplice_symbol_backend(kreloc_ss, &kreloc->symbol, NULL,
1705 label, NULL);
1706 write_reloc(kreloc_ss, &kreloc->blank_addr, &ss->symbol,
1707 addr_offset(ss, addr));
1708 reloc_howto_type *howto =
1709 bfd_reloc_type_lookup(ss->parent->abfd,
1710 PASTE(BFD_RELOC_, LONG_BIT));
1711 write_ksplice_reloc_howto(kreloc_ss, &kreloc->howto, howto,
1712 KSPLICE_HOWTO_RELOC);
1713 kreloc->target_addend = addend;
1714 kreloc->insn_addend = 0;
1717 void write_ksplice_patch(struct superbfd *sbfd, struct span *span)
1719 struct supersect *kpatch_ss =
1720 make_section(sbfd, ".ksplice_patches%s", span->ss->name);
1721 struct ksplice_patch *kpatch = sect_grow(kpatch_ss, 1,
1722 struct ksplice_patch);
1724 write_ksplice_patch_reloc(kpatch_ss, span->ss->name, &kpatch->oldaddr,
1725 sizeof(kpatch->oldaddr), span->label, 0);
1726 if (span->ss->type == SS_TYPE_TEXT) {
1727 kpatch->type = KSPLICE_PATCH_TEXT;
1728 write_patch_storage(kpatch_ss, kpatch, MAX_TRAMPOLINE_SIZE,
1729 NULL);
1730 } else {
1731 kpatch->type = KSPLICE_PATCH_DATA;
1732 kpatch->size = span->contents_size;
1733 struct supersect *data_ss =
1734 make_section(sbfd, ".ksplice_patch_data");
1735 write_reloc(kpatch_ss, &kpatch->contents, &span->ss->symbol,
1736 span->start + span->shift);
1737 char *saved = sect_do_grow(data_ss, 1, span->contents_size, 1);
1738 write_reloc(kpatch_ss, &kpatch->saved, &data_ss->symbol,
1739 addr_offset(data_ss, saved));
1741 write_reloc(kpatch_ss, &kpatch->repladdr, &span->ss->symbol,
1742 span->start + span->shift);
1745 asymbol **make_undefined_symbolp(struct superbfd *sbfd, const char *name)
1747 asymbol **symp;
1748 for (symp = sbfd->syms.data; symp < sbfd->syms.data + sbfd->syms.size;
1749 symp++) {
1750 asymbol *sym = *symp;
1751 if (strcmp(name, sym->name) == 0 &&
1752 bfd_is_und_section(sym->section))
1753 return symp;
1755 asymbol ***sympp;
1756 for (sympp = sbfd->new_syms.data;
1757 sympp < sbfd->new_syms.data + sbfd->new_syms.size; sympp++) {
1758 asymbol **symp = *sympp;
1759 asymbol *sym = *symp;
1760 if (strcmp(name, sym->name) == 0 &&
1761 bfd_is_und_section(sym->section))
1762 return symp;
1765 symp = malloc(sizeof(*symp));
1766 *symp = bfd_make_empty_symbol(sbfd->abfd);
1767 asymbol *sym = *symp;
1768 sym->name = name;
1769 sym->section = bfd_und_section_ptr;
1770 sym->flags = 0;
1771 sym->value = 0;
1772 *vec_grow(&sbfd->new_syms, 1) = symp;
1773 return symp;
1776 void write_ksplice_deleted_patch(struct superbfd *sbfd, const char *name,
1777 const char *label, const char *sectname)
1779 struct supersect *kpatch_ss =
1780 make_section(sbfd, ".ksplice_patches%s", sectname);
1781 struct ksplice_patch *kpatch = sect_grow(kpatch_ss, 1,
1782 struct ksplice_patch);
1784 write_ksplice_patch_reloc(kpatch_ss, sectname, &kpatch->oldaddr,
1785 sizeof(kpatch->oldaddr), label, 0);
1786 kpatch->type = KSPLICE_PATCH_TEXT;
1787 asymbol **symp = make_undefined_symbolp(sbfd, strdup(name));
1788 write_reloc(kpatch_ss, &kpatch->repladdr, symp, 0);
1789 write_patch_storage(kpatch_ss, kpatch, MAX_TRAMPOLINE_SIZE, NULL);
1792 void write_ksplice_export(struct superbfd *sbfd, struct span *span, bool del)
1794 struct supersect *kpatch_ss = make_section(sbfd, ".ksplice_patches");
1795 struct ksplice_patch *kpatch = sect_grow(kpatch_ss, 1,
1796 struct ksplice_patch);
1797 struct supersect *data_ss;
1799 const struct table_section *ts = get_table_section(span->ss->name);
1800 assert(ts != NULL);
1801 const char **addr =
1802 span->ss->contents.data + span->start + ts->other_offset;
1803 const char *symname = read_string(span->ss, addr);
1805 char *oldname, *newname;
1806 if (del) {
1807 oldname = strprintf("%s:%s", span->ss->name, symname);
1808 newname = strprintf("DISABLED_%s_%s", symname, kid);
1809 } else {
1810 oldname = strprintf("%s:DISABLED_%s_%s", span->ss->name,
1811 symname, kid);
1812 newname = strprintf("%s", symname);
1813 write_string(span->ss, addr, "DISABLED_%s_%s", symname, kid);
1816 write_ksplice_patch_reloc(kpatch_ss, "", &kpatch->oldaddr,
1817 sizeof(kpatch->oldaddr), oldname,
1818 ts->other_offset);
1819 kpatch->type = KSPLICE_PATCH_EXPORT;
1820 const char **namep = write_patch_storage(kpatch_ss, kpatch,
1821 sizeof(newname), &data_ss);
1822 write_string(data_ss, namep, "%s", newname);
1825 void filter_table_sections(struct superbfd *isbfd)
1827 struct supersect *tables_ss =
1828 fetch_supersect(offsets_sbfd,
1829 bfd_get_section_by_name(offsets_sbfd->abfd,
1830 ".ksplice_table_sections"));
1831 const struct table_section *ts;
1832 for (ts = tables_ss->contents.data;
1833 (void *)ts < tables_ss->contents.data + tables_ss->contents.size;
1834 ts++) {
1835 struct table_section s = *ts;
1836 s.sect = read_string(tables_ss, &ts->sect);
1837 s.other_sect = read_string(tables_ss, &ts->other_sect);
1838 s.crc_sect = read_string(tables_ss, &ts->crc_sect);
1839 filter_table_section(isbfd, &s);
1843 void filter_table_section(struct superbfd *sbfd, const struct table_section *s)
1845 asection *isection = bfd_get_section_by_name(sbfd->abfd, s->sect);
1846 if (isection == NULL)
1847 return;
1848 struct supersect *ss = fetch_supersect(sbfd, isection);
1850 void *entry;
1851 for (entry = ss->contents.data;
1852 entry < ss->contents.data + ss->contents.size;
1853 entry += s->entry_size) {
1854 struct span *span = find_span(ss, addr_offset(ss, entry));
1855 assert(span != NULL);
1857 if (s->has_addr) {
1858 arelent *reloc = find_reloc(ss, entry + s->addr_offset);
1859 assert(reloc != NULL);
1860 struct span *sym_span = reloc_target_span(ss, reloc);
1861 if (sym_span->keep)
1862 keep_span(span);
1865 if (s->other_sect != NULL) {
1866 arelent *reloc =
1867 find_reloc(ss, entry + s->other_offset);
1868 assert(reloc != NULL);
1869 struct span *sym_span = reloc_target_span(ss, reloc);
1870 if (span->keep)
1871 keep_span(sym_span);
1874 if (s->crc_sect != NULL) {
1875 struct span *crc_span = get_crc_span(span, s);
1876 assert(crc_span != NULL);
1877 if (span->keep && mode("keep-primary"))
1878 keep_span(crc_span);
1883 static struct span *get_crc_span(struct span *span,
1884 const struct table_section *ts)
1886 void *entry = span->ss->contents.data + span->start;
1887 asection *crc_sect = bfd_get_section_by_name(span->ss->parent->abfd,
1888 ts->crc_sect);
1889 if (crc_sect == NULL)
1890 return NULL;
1891 struct supersect *crc_ss = fetch_supersect(span->ss->parent, crc_sect);
1892 if (crc_ss == NULL)
1893 return NULL;
1894 struct span *crc_span = find_span(crc_ss, addr_offset(span->ss, entry) /
1895 ts->entry_size * ts->crc_size);
1896 return crc_span;
1899 void mark_precallable_spans(struct superbfd *sbfd)
1901 asection *sect;
1902 struct supersect *ss, *sym_ss;
1903 struct span *address_span, *target_span;
1904 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
1905 ss = fetch_supersect(sbfd, sect);
1906 arelent **relocp;
1907 if (ss->type == SS_TYPE_SPECIAL)
1908 continue;
1909 for (relocp = ss->relocs.data;
1910 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
1911 asymbol *sym = *(*relocp)->sym_ptr_ptr;
1912 address_span = find_span(ss, (*relocp)->address);
1913 if (!address_span->precallable)
1914 continue;
1915 target_span = reloc_target_span(ss, *relocp);
1916 if (target_span == NULL || target_span->keep)
1917 continue;
1918 sym_ss = fetch_supersect(sbfd, sym->section);
1919 if (sym_ss->type == SS_TYPE_IGNORED)
1920 continue;
1921 target_span->precallable = true;
1922 changed = true;
1927 void keep_referenced_sections(struct superbfd *sbfd)
1929 asection *sect;
1930 struct supersect *ss, *sym_ss;
1931 struct span *address_span, *target_span;
1932 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
1933 ss = fetch_supersect(sbfd, sect);
1934 arelent **relocp;
1935 if (ss->type == SS_TYPE_SPECIAL)
1936 continue;
1937 for (relocp = ss->relocs.data;
1938 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
1939 asymbol *sym = *(*relocp)->sym_ptr_ptr;
1940 address_span = find_span(ss, (*relocp)->address);
1941 if (!address_span->keep)
1942 continue;
1943 target_span = reloc_target_span(ss, *relocp);
1944 if (target_span == NULL || target_span->keep)
1945 continue;
1946 sym_ss = fetch_supersect(sbfd, sym->section);
1947 if (sym_ss->type == SS_TYPE_IGNORED)
1948 continue;
1949 keep_span(target_span);
1950 changed = true;
1955 void copy_symbols(struct asymbolp_vec *osyms, struct asymbolpp_vec *isyms)
1957 asymbol ***sympp;
1958 for (sympp = isyms->data; sympp < isyms->data + isyms->size; sympp++)
1959 *vec_grow(osyms, 1) = **sympp;
1962 /* Modified function from GNU Binutils objcopy.c */
1963 bfd_boolean copy_object(bfd *ibfd, bfd *obfd)
1965 assert(bfd_set_format(obfd, bfd_get_format(ibfd)));
1967 bfd_vma start = bfd_get_start_address(ibfd);
1969 flagword flags = bfd_get_file_flags(ibfd);
1970 flags &= bfd_applicable_file_flags(obfd);
1972 assert(bfd_set_start_address(obfd, start)
1973 && bfd_set_file_flags(obfd, flags));
1975 enum bfd_architecture iarch = bfd_get_arch(ibfd);
1976 unsigned int imach = bfd_get_mach(ibfd);
1977 assert(bfd_set_arch_mach(obfd, iarch, imach));
1978 assert(bfd_set_format(obfd, bfd_get_format(ibfd)));
1980 /* BFD mandates that all output sections be created and sizes set before
1981 any output is done. Thus, we traverse all sections multiple times. */
1982 bfd_map_over_sections(ibfd, setup_section, obfd);
1984 struct supersect *new_supersects = fetch_superbfd(ibfd)->new_supersects;
1985 struct supersect *ss;
1986 for (ss = new_supersects; ss != NULL; ss = ss->next)
1987 setup_new_section(obfd, ss);
1989 /* Mark symbols used in output relocations so that they
1990 are kept, even if they are local labels or static symbols.
1992 Note we iterate over the input sections examining their
1993 relocations since the relocations for the output sections
1994 haven't been set yet. mark_symbols_used_in_relocations will
1995 ignore input sections which have no corresponding output
1996 section. */
1998 bfd_map_over_sections(ibfd, mark_symbols_used_in_relocations, NULL);
1999 for (ss = new_supersects; ss != NULL; ss = ss->next)
2000 ss_mark_symbols_used_in_relocations(ss);
2001 struct asymbolp_vec osyms;
2002 vec_init(&osyms);
2003 filter_symbols(ibfd, obfd, &osyms, &fetch_superbfd(ibfd)->syms);
2004 copy_symbols(&osyms, &fetch_superbfd(ibfd)->new_syms);
2006 bfd_set_symtab(obfd, osyms.data, osyms.size);
2008 /* This has to happen after the symbol table has been set. */
2009 bfd_map_over_sections(obfd, write_section, NULL);
2011 /* Allow the BFD backend to copy any private data it understands
2012 from the input BFD to the output BFD. This is done last to
2013 permit the routine to look at the filtered symbol table, which is
2014 important for the ECOFF code at least. */
2015 assert(bfd_copy_private_bfd_data(ibfd, obfd));
2017 return TRUE;
2020 /* Modified function from GNU Binutils objcopy.c */
2021 void setup_section(bfd *ibfd, asection *isection, void *obfdarg)
2023 struct superbfd *isbfd = fetch_superbfd(ibfd);
2024 struct supersect *ss = fetch_supersect(isbfd, isection);
2025 bfd *obfd = obfdarg;
2026 bfd_vma vma;
2028 if (!ss->keep)
2029 return;
2031 asection *osection = bfd_make_section_anyway(obfd, ss->name);
2032 assert(osection != NULL);
2034 osection->userdata = ss;
2035 bfd_set_section_flags(obfd, osection, ss->flags);
2036 ss->symbol = osection->symbol;
2037 assert(bfd_set_section_size(obfd, osection, ss->contents.size));
2039 vma = bfd_section_vma(ibfd, isection);
2040 assert(bfd_set_section_vma(obfd, osection, vma));
2042 osection->lma = isection->lma;
2043 assert(bfd_set_section_alignment(obfd, osection, ss->alignment));
2044 osection->entsize = ss->entsize;
2045 osection->output_section = osection;
2046 osection->output_offset = 0;
2047 isection->output_section = osection;
2048 isection->output_offset = 0;
2049 return;
2052 void setup_new_section(bfd *obfd, struct supersect *ss)
2054 asection *osection = bfd_make_section_anyway(obfd, ss->name);
2055 assert(osection != NULL);
2056 bfd_set_section_flags(obfd, osection, ss->flags);
2058 osection->userdata = ss;
2059 ss->symbol = osection->symbol;
2060 assert(bfd_set_section_size(obfd, osection, ss->contents.size));
2061 assert(bfd_set_section_vma(obfd, osection, 0));
2063 osection->lma = 0;
2064 assert(bfd_set_section_alignment(obfd, osection, ss->alignment));
2065 osection->entsize = ss->entsize;
2066 osection->output_section = osection;
2067 osection->output_offset = 0;
2070 static int compare_reloc_addresses(const void *aptr, const void *bptr)
2072 const arelent *const *a = aptr, *const *b = bptr;
2073 return (*a)->address - (*b)->address;
2076 static void delete_obsolete_relocs(struct supersect *ss)
2078 if (ss->new_relocs.size == 0)
2079 return;
2081 qsort(ss->relocs.data, ss->relocs.size, sizeof(*ss->relocs.data),
2082 compare_reloc_addresses);
2083 qsort(ss->new_relocs.data, ss->new_relocs.size,
2084 sizeof(*ss->new_relocs.data), compare_reloc_addresses);
2086 struct arelentp_vec orig_relocs;
2087 vec_move(&orig_relocs, &ss->relocs);
2089 arelent **relocp, **new_relocp = ss->new_relocs.data;
2090 for (relocp = orig_relocs.data;
2091 relocp < orig_relocs.data + orig_relocs.size; relocp++) {
2092 while (new_relocp < ss->new_relocs.data + ss->new_relocs.size &&
2093 (*new_relocp)->address < (*relocp)->address)
2094 new_relocp++;
2095 arelent *reloc = *relocp, *new_reloc = *new_relocp;
2096 if (new_relocp == ss->new_relocs.data + ss->new_relocs.size ||
2097 reloc->address != new_reloc->address)
2098 *vec_grow(&ss->relocs, 1) = reloc;
2102 void write_section(bfd *obfd, asection *osection, void *arg)
2104 struct supersect *ss = osection->userdata;
2106 if ((ss->flags & SEC_GROUP) != 0 || ss->contents.size == 0)
2107 return;
2109 delete_obsolete_relocs(ss);
2111 arelent **relocp;
2112 char *error_message;
2113 for (relocp = ss->new_relocs.data;
2114 relocp < ss->new_relocs.data + ss->new_relocs.size; relocp++) {
2115 bfd_vma val;
2116 if (bfd_get_arch(obfd) == bfd_arch_arm)
2117 val = osection->use_rela_p ? 0 : (*relocp)->addend;
2118 else
2119 val = 0;
2120 bfd_put(bfd_get_reloc_size((*relocp)->howto) * 8, obfd, val,
2121 ss->contents.data + (*relocp)->address);
2122 if (bfd_install_relocation(obfd, *relocp, ss->contents.data,
2123 0, osection, &error_message) !=
2124 bfd_reloc_ok) {
2125 err(ss->parent, "ksplice: error installing reloc: %s",
2126 error_message);
2127 DIE;
2130 memcpy(vec_grow(&ss->relocs, ss->new_relocs.size), ss->new_relocs.data,
2131 ss->new_relocs.size * sizeof(*ss->new_relocs.data));
2133 bfd_set_reloc(obfd, osection,
2134 ss->relocs.size == 0 ? NULL : ss->relocs.data,
2135 ss->relocs.size);
2137 if (ss->flags & SEC_HAS_CONTENTS)
2138 assert(bfd_set_section_contents
2139 (obfd, osection, ss->contents.data, 0,
2140 ss->contents.size));
2143 /* Modified function from GNU Binutils objcopy.c
2145 * Mark all the symbols which will be used in output relocations with
2146 * the BSF_KEEP flag so that those symbols will not be stripped.
2148 * Ignore relocations which will not appear in the output file.
2150 void mark_symbols_used_in_relocations(bfd *abfd, asection *isection,
2151 void *ignored)
2153 struct superbfd *sbfd = fetch_superbfd(abfd);
2154 if (isection->output_section == NULL)
2155 return;
2157 struct supersect *ss = fetch_supersect(sbfd, isection);
2158 ss_mark_symbols_used_in_relocations(ss);
2161 void ss_mark_symbols_used_in_relocations(struct supersect *ss)
2163 /* Examine each symbol used in a relocation. If it's not one of the
2164 special bfd section symbols, then mark it with BSF_KEEP. */
2165 arelent **relocp;
2166 for (relocp = ss->relocs.data;
2167 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
2168 asymbol *sym = *(*relocp)->sym_ptr_ptr;
2169 if (!(bfd_is_const_section(sym->section) &&
2170 sym == sym->section->symbol))
2171 sym->flags |= BSF_KEEP;
2173 for (relocp = ss->new_relocs.data;
2174 relocp < ss->new_relocs.data + ss->new_relocs.size; relocp++) {
2175 asymbol *sym = *(*relocp)->sym_ptr_ptr;
2176 if (!(bfd_is_const_section(sym->section) &&
2177 sym == sym->section->symbol))
2178 sym->flags |= BSF_KEEP;
2182 static bool deleted_table_section_symbol(bfd *abfd, asymbol *sym)
2184 struct superbfd *sbfd = fetch_superbfd(abfd);
2185 if (bfd_is_const_section(sym->section))
2186 return false;
2187 struct supersect *ss = fetch_supersect(sbfd, sym->section);
2189 asymbol **symp;
2190 for (symp = ss->syms.data; symp < ss->syms.data + ss->syms.size; symp++) {
2191 if (sym == *symp)
2192 break;
2194 return symp >= ss->syms.data + ss->syms.size &&
2195 (sym->flags & BSF_SECTION_SYM) == 0;
2198 void filter_symbols(bfd *ibfd, bfd *obfd, struct asymbolp_vec *osyms,
2199 struct asymbolp_vec *isyms)
2201 asymbol **symp;
2202 struct superbfd *sbfd = fetch_superbfd(ibfd);
2203 for (symp = isyms->data; symp < isyms->data + isyms->size; symp++) {
2204 asymbol *sym = *symp;
2205 struct supersect *sym_ss = NULL;
2206 struct span *sym_span = NULL;
2207 if (!bfd_is_const_section(sym->section)) {
2208 sym_ss = fetch_supersect(sbfd, sym->section);
2209 sym_span = find_span(sym_ss, sym->value);
2212 if (mode("keep") && (sym->flags & BSF_GLOBAL) != 0 &&
2213 !(mode("keep-primary") && sym_span != NULL &&
2214 sym_span->new))
2215 sym->flags = (sym->flags & ~BSF_GLOBAL) | BSF_LOCAL;
2217 if (mode("finalize") && (sym->flags & BSF_GLOBAL) != 0)
2218 sym->flags = (sym->flags & ~BSF_GLOBAL) | BSF_LOCAL;
2220 bool keep = bfd_is_const_section(sym->section) ||
2221 (sym_ss->keep && (sym->flags & BSF_SECTION_SYM) != 0) ||
2222 (sym_span != NULL && sym_span->keep);
2223 if (bfd_is_und_section(sym->section) &&
2224 (sym->flags & BSF_KEEP) == 0)
2225 keep = false;
2226 if (bfd_is_abs_section(sym->section) &&
2227 (sym->flags & BSF_KEEP) == 0 &&
2228 (sym->flags & BSF_FILE) == 0)
2229 keep = false;
2230 if (deleted_table_section_symbol(ibfd, sym))
2231 keep = false;
2233 if (mode("keep-helper") && sym_ss != NULL &&
2234 sym_ss->type == SS_TYPE_EXPORT)
2235 keep = false;
2237 if (keep) {
2238 if (sym_ss != NULL && !sym_ss->keep) {
2239 err(sbfd, "Kept symbol %s in unkept section "
2240 "%s\n", sym->name, sym->section->name);
2241 DIE;
2243 *vec_grow(osyms, 1) = sym;
2248 void read_str_set(struct str_vec *strs)
2250 char *buf = NULL;
2251 size_t n = 0;
2252 assert(getline(&buf, &n, stdin) >= 0);
2253 vec_init(strs);
2254 char *saveptr;
2255 while (1) {
2256 char *str = strtok_r(buf, " \n", &saveptr);
2257 buf = NULL;
2258 if (str == NULL)
2259 break;
2260 *vec_grow(strs, 1) = str;
2264 bool str_in_set(const char *str, const struct str_vec *strs)
2266 const char **strp;
2267 for (strp = strs->data; strp < strs->data + strs->size; strp++) {
2268 if (strcmp(str, *strp) == 0)
2269 return true;
2271 return false;
2274 bool is_table_section(const char *name, bool consider_other)
2276 struct supersect *tables_ss =
2277 fetch_supersect(offsets_sbfd,
2278 bfd_get_section_by_name(offsets_sbfd->abfd,
2279 ".ksplice_table_sections"));
2280 const struct table_section *ts;
2281 for (ts = tables_ss->contents.data;
2282 (void *)ts < tables_ss->contents.data + tables_ss->contents.size;
2283 ts++) {
2284 if (strcmp(name, read_string(tables_ss, &ts->sect)) == 0)
2285 return true;
2286 const char *osect_name = read_string(tables_ss,
2287 &ts->other_sect);
2288 if (consider_other && osect_name != NULL &&
2289 strcmp(name, osect_name) == 0)
2290 return true;
2291 const char *crc_name = read_string(tables_ss, &ts->crc_sect);
2292 if (consider_other && crc_name != NULL &&
2293 strcmp(name, crc_name) == 0)
2294 return true;
2296 return false;
2299 const struct table_section *get_table_section(const char *name)
2301 struct supersect *tables_ss =
2302 fetch_supersect(offsets_sbfd,
2303 bfd_get_section_by_name(offsets_sbfd->abfd,
2304 ".ksplice_table_sections"));
2305 const struct table_section *ts;
2306 for (ts = tables_ss->contents.data;
2307 (void *)ts < tables_ss->contents.data + tables_ss->contents.size;
2308 ts++) {
2309 if (strcmp(name, read_string(tables_ss, &ts->sect)) == 0) {
2310 if (ts->entry_contents_size != 0)
2311 assert(align(ts->entry_contents_size,
2312 ts->entry_align) ==
2313 ts->entry_size);
2314 struct table_section *ns = malloc(sizeof(*ns));
2315 *ns = *ts;
2316 ns->sect = read_string(tables_ss, &ts->sect);
2317 ns->crc_sect = read_string(tables_ss, &ts->crc_sect);
2318 ns->other_sect =
2319 read_string(tables_ss, &ts->other_sect);
2320 return ns;
2323 return NULL;
2326 enum supersect_type supersect_type(struct supersect *ss)
2328 if (mode("finalize") &&
2329 strcmp(finalize_target, "vmlinux") == 0 &&
2330 (starts_with(ss->name, ".ksplice_relocs.exit") ||
2331 starts_with(ss->name, ".ksplice_sections.exit") ||
2332 starts_with(ss->name, ".ksplice_patches.exit")))
2333 return SS_TYPE_EXIT;
2334 if (starts_with(ss->name, ".ksplice_call"))
2335 return SS_TYPE_KSPLICE_CALL;
2336 if (starts_with(ss->name, ".ksplice_options"))
2337 return SS_TYPE_SPECIAL;
2338 if (starts_with(ss->name, ".ksplice"))
2339 return SS_TYPE_KSPLICE;
2341 if (starts_with(ss->name, ".init"))
2342 return SS_TYPE_IGNORED;
2343 if (starts_with(ss->name, ".security_initcall.init"))
2344 return SS_TYPE_IGNORED;
2345 if (starts_with(ss->name, ".con_initcall.init"))
2346 return SS_TYPE_IGNORED;
2347 if (starts_with(ss->name, ".x86cpuvendor.init"))
2348 return SS_TYPE_IGNORED;
2349 if (starts_with(ss->name, ".early_param.init"))
2350 return SS_TYPE_IGNORED;
2351 if (starts_with(ss->name, ".taglist.init"))
2352 return SS_TYPE_IGNORED;
2353 if (starts_with(ss->name, ".arch.info.init"))
2354 return SS_TYPE_IGNORED;
2355 if (starts_with(ss->name, ".proc.info.init"))
2356 return SS_TYPE_IGNORED;
2357 /* .pci_fixup_* sections really should be treated as global rodata
2358 referenced only from quirks.c */
2359 if (starts_with(ss->name, ".pci_fixup_"))
2360 return SS_TYPE_IGNORED;
2361 /* .builtin_fw sections are similar to .pci_fixup */
2362 if (starts_with(ss->name, ".builtin_fw"))
2363 return SS_TYPE_IGNORED;
2364 /* same for .tracedata */
2365 if (starts_with(ss->name, ".tracedata"))
2366 return SS_TYPE_IGNORED;
2367 if (starts_with(ss->name, ".debug"))
2368 return SS_TYPE_IGNORED;
2369 /* .eh_frame should probably be discarded, not ignored */
2370 if (starts_with(ss->name, ".eh_frame"))
2371 return SS_TYPE_IGNORED;
2372 if (config->ignore_devinit && starts_with(ss->name, ".devinit"))
2373 return SS_TYPE_IGNORED;
2374 if (config->ignore_meminit && starts_with(ss->name, ".meminit"))
2375 return SS_TYPE_IGNORED;
2376 if (config->ignore_cpuinit && starts_with(ss->name, ".cpuinit"))
2377 return SS_TYPE_IGNORED;
2378 if (config->ignore_devinit && starts_with(ss->name, ".devexit"))
2379 return SS_TYPE_IGNORED;
2380 if (config->ignore_meminit && starts_with(ss->name, ".memexit"))
2381 return SS_TYPE_IGNORED;
2382 if (config->ignore_cpuinit && starts_with(ss->name, ".cpuexit"))
2383 return SS_TYPE_IGNORED;
2384 if (starts_with(ss->name, ".vgetcpu_mode") ||
2385 starts_with(ss->name, ".jiffies") ||
2386 starts_with(ss->name, ".wall_jiffies") ||
2387 starts_with(ss->name, ".vxtime") ||
2388 starts_with(ss->name, ".sys_tz") ||
2389 starts_with(ss->name, ".sysctl_vsyscall") ||
2390 starts_with(ss->name, ".xtime") ||
2391 starts_with(ss->name, ".xtime_lock") ||
2392 starts_with(ss->name, ".vsyscall"))
2393 return SS_TYPE_IGNORED;
2394 if (starts_with(ss->name, ".vdso"))
2395 return SS_TYPE_IGNORED;
2397 if (starts_with(ss->name, ".exit.text"))
2398 return SS_TYPE_TEXT;
2399 if (starts_with(ss->name, ".exit.data"))
2400 return SS_TYPE_DATA;
2402 if (starts_with(ss->name, ".text") ||
2403 starts_with(ss->name, ".kernel.text") ||
2404 starts_with(ss->name, ".devinit.text") ||
2405 starts_with(ss->name, ".meminit.text") ||
2406 starts_with(ss->name, ".cpuinit.text") ||
2407 starts_with(ss->name, ".devexit.text") ||
2408 starts_with(ss->name, ".memexit.text") ||
2409 starts_with(ss->name, ".cpuexit.text") ||
2410 starts_with(ss->name, ".ref.text") ||
2411 starts_with(ss->name, ".spinlock.text") ||
2412 starts_with(ss->name, ".kprobes.text") ||
2413 starts_with(ss->name, ".sched.text") ||
2414 (mode("keep-helper") && starts_with(ss->name, ".fixup")))
2415 return SS_TYPE_TEXT;
2417 int n = -1;
2418 if (sscanf(ss->name, ".rodata.str%*u.%*u%n", &n) >= 0 &&
2419 n == strlen(ss->name))
2420 return ss->entsize == 1 ? SS_TYPE_STRING : SS_TYPE_RODATA;
2422 if (starts_with(ss->name, ".rodata") ||
2423 starts_with(ss->name, ".kernel.rodata") ||
2424 starts_with(ss->name, ".devinit.rodata") ||
2425 starts_with(ss->name, ".meminit.rodata") ||
2426 starts_with(ss->name, ".cpuinit.rodata") ||
2427 starts_with(ss->name, ".devexit.rodata") ||
2428 starts_with(ss->name, ".memexit.rodata") ||
2429 starts_with(ss->name, ".cpuexit.rodata") ||
2430 starts_with(ss->name, ".ref.rodata") ||
2431 starts_with(ss->name, "__markers_strings") ||
2432 starts_with(ss->name, "__bug_table") ||
2433 (mode("keep-helper") && starts_with(ss->name, "__ex_table")))
2434 return SS_TYPE_RODATA;
2436 if (starts_with(ss->name, ".bss"))
2437 return SS_TYPE_DATA;
2439 /* Ignore .data.percpu sections */
2440 if (starts_with(ss->name, ".data.percpu") ||
2441 starts_with(ss->name, ".kernel.data.percpu"))
2442 return SS_TYPE_IGNORED;
2443 if (starts_with(ss->name, ".data") ||
2444 starts_with(ss->name, ".kernel.data") ||
2445 starts_with(ss->name, ".devinit.data") ||
2446 starts_with(ss->name, ".cpuinit.data") ||
2447 starts_with(ss->name, ".meminit.data") ||
2448 starts_with(ss->name, ".devexit.data") ||
2449 starts_with(ss->name, ".memexit.data") ||
2450 starts_with(ss->name, ".cpuexit.data") ||
2451 starts_with(ss->name, ".ref.data") ||
2452 starts_with(ss->name, "__markers"))
2453 return SS_TYPE_DATA;
2455 /* We replace all the ksymtab strings, so delete them */
2456 if (strcmp(ss->name, "__ksymtab_strings") == 0)
2457 return SS_TYPE_STRING;
2458 if (starts_with(ss->name, "__ksymtab"))
2459 return SS_TYPE_EXPORT;
2460 if (starts_with(ss->name, "__kcrctab"))
2461 return SS_TYPE_SPECIAL;
2463 if (is_table_section(ss->name, true))
2464 return SS_TYPE_SPECIAL;
2466 if (starts_with(ss->name, ".ARM."))
2467 return SS_TYPE_SPECIAL;
2469 if (starts_with(ss->name, ".note"))
2470 return SS_TYPE_IGNORED;
2471 if (starts_with(ss->name, ".comment"))
2472 return SS_TYPE_IGNORED;
2473 if (starts_with(ss->name, "__param"))
2474 return SS_TYPE_IGNORED;
2475 if (starts_with(ss->name, ".exitcall.exit"))
2476 return SS_TYPE_IGNORED;
2477 if (starts_with(ss->name, ".modinfo"))
2478 return SS_TYPE_IGNORED;
2480 return SS_TYPE_UNKNOWN;
2483 void initialize_supersect_types(struct superbfd *sbfd)
2485 asection *sect;
2486 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2487 struct supersect *ss = fetch_supersect(sbfd, sect);
2488 ss->type = supersect_type(ss);
2489 ss->orig_type = ss->type;
2490 if (ss->type == SS_TYPE_UNKNOWN) {
2491 err(sbfd, "Unknown section type: %s\n", ss->name);
2492 DIE;
2497 static void init_label_map(struct superbfd *sbfd)
2499 struct label_map *map;
2501 vec_init(&sbfd->maps);
2502 init_csyms(sbfd);
2503 init_callers(sbfd);
2505 struct symbol_hash csyms;
2506 symbol_hash_init(&csyms);
2508 asymbol **symp;
2509 for (symp = sbfd->syms.data;
2510 symp < sbfd->syms.data + sbfd->syms.size; symp++) {
2511 asymbol *csym = canonical_symbol(sbfd, *symp);
2512 if (csym == NULL)
2513 continue;
2514 char *key = strprintf("%p", csym);
2515 asymbol **csymp = symbol_hash_lookup(&csyms, key, TRUE);
2516 free(key);
2517 if (*csymp != NULL)
2518 continue;
2519 *csymp = csym;
2521 map = vec_grow(&sbfd->maps, 1);
2522 map->csym = csym;
2523 map->count = 0;
2524 map->label = symbol_label(sbfd, csym);
2527 struct label_mapp_hash label_maps;
2528 label_mapp_hash_init(&label_maps);
2529 for (map = sbfd->maps.data;
2530 map < sbfd->maps.data + sbfd->maps.size; map++) {
2531 struct label_map **mapp =
2532 label_mapp_hash_lookup(&label_maps, map->label, TRUE);
2533 if (*mapp == NULL) {
2534 *mapp = map;
2535 continue;
2538 struct label_map *first_map = *mapp;
2539 if (first_map->count == 0)
2540 first_map->label = strprintf("%s~%d", map->label, 0);
2541 map->label = strprintf("%s~%d", map->label, ++first_map->count);
2544 label_mapp_hash_init(&sbfd->maps_hash);
2545 for (map = sbfd->maps.data;
2546 map < sbfd->maps.data + sbfd->maps.size; map++) {
2547 char *key = strprintf("%p", map->csym);
2548 struct label_map **mapp =
2549 label_mapp_hash_lookup(&sbfd->maps_hash, key, TRUE);
2550 free(key);
2551 *mapp = map;
2552 map->orig_label = map->label;
2556 static const char *label_lookup(struct superbfd *sbfd, asymbol *sym)
2558 asymbol *csym = canonical_symbol(sbfd, sym);
2559 char *key = strprintf("%p", csym);
2560 struct label_map **mapp =
2561 label_mapp_hash_lookup(&sbfd->maps_hash, key, FALSE);
2562 free(key);
2563 if (mapp == NULL)
2564 DIE;
2565 return (*mapp)->label;
2568 static void print_label_changes(struct superbfd *sbfd)
2570 asection *sect;
2571 struct span *span;
2572 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2573 struct supersect *ss = fetch_supersect(sbfd, sect);
2574 for (span = ss->spans.data;
2575 span < ss->spans.data + ss->spans.size; span++) {
2576 if (strcmp(span->label, span->orig_label) != 0)
2577 debug1(sbfd, "Label change: %s -> %s\n",
2578 span->label, span->orig_label);
2583 static void label_map_set(struct superbfd *sbfd, const char *oldlabel,
2584 const char *label)
2586 struct label_map *map;
2587 for (map = sbfd->maps.data;
2588 map < sbfd->maps.data + sbfd->maps.size; map++) {
2589 if (strcmp(map->orig_label, oldlabel) == 0) {
2590 if (strcmp(map->orig_label, map->label) != 0 &&
2591 strcmp(map->label, label) != 0)
2592 DIE;
2593 map->label = label;
2594 return;
2597 DIE;
2600 static void change_initial_label(struct span *span, const char *label)
2602 struct superbfd *sbfd = span->ss->parent;
2603 span->label = label;
2604 span->orig_label = label;
2605 if (span->symbol) {
2606 asymbol *csym = canonical_symbol(sbfd, span->symbol);
2607 char *key = strprintf("%p", csym);
2608 struct label_map **mapp =
2609 label_mapp_hash_lookup(&sbfd->maps_hash, key, FALSE);
2610 free(key);
2611 assert(mapp);
2612 (*mapp)->label = span->label;
2613 (*mapp)->orig_label = span->orig_label;
2614 span->symbol = NULL;
2618 static void init_callers(struct superbfd *sbfd)
2620 string_hash_init(&sbfd->callers);
2621 asection *sect;
2622 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2623 struct supersect *ss = fetch_supersect(sbfd, sect);
2624 arelent **relocp;
2625 for (relocp = ss->relocs.data;
2626 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
2627 asymbol *sym = *(*relocp)->sym_ptr_ptr;
2628 unsigned long val =
2629 sym->value + get_reloc_offset(ss, *relocp, true);
2630 char *key = strprintf("%s+%lx", sym->section->name,
2631 val);
2632 const char **ret = string_hash_lookup(&sbfd->callers,
2633 key, TRUE);
2634 free(key);
2635 asymbol *csym = canonical_symbol(sbfd, sect->symbol);
2636 if (*ret != NULL)
2637 *ret = "*multiple_callers*";
2638 else if (static_local_symbol(sbfd, csym))
2639 *ret = static_local_symbol(sbfd, csym);
2640 else
2641 *ret = sect->name;
2646 static const char *find_caller(struct supersect *ss, asymbol *sym)
2648 char *key = strprintf("%s+%lx", sym->section->name,
2649 (unsigned long)sym->value);
2650 const char **ret = string_hash_lookup(&ss->parent->callers, key, FALSE);
2651 free(key);
2653 if (ret == NULL)
2654 return "*no_caller*";
2655 return *ret;
2658 static void init_csyms(struct superbfd *sbfd)
2660 asymbolpp_hash_init(&sbfd->csyms);
2662 asymbol **symp;
2663 for (symp = sbfd->syms.data; symp < sbfd->syms.data + sbfd->syms.size;
2664 symp++) {
2665 asymbol *sym = *symp;
2666 if ((sym->flags & BSF_DEBUGGING) != 0)
2667 continue;
2668 char *key = strprintf("%s+%lx", sym->section->name,
2669 (unsigned long)sym->value);
2670 asymbol ***csympp = asymbolpp_hash_lookup(&sbfd->csyms, key,
2671 TRUE);
2672 free(key);
2673 if (*csympp == NULL) {
2674 *csympp = symp;
2675 continue;
2677 asymbol *csym = **csympp;
2678 if ((csym->flags & BSF_GLOBAL) != 0)
2679 continue;
2680 if ((sym->flags & BSF_GLOBAL) != 0)
2681 *csympp = symp;
2685 static asymbol **symbolp_scan(struct supersect *ss, bfd_vma value)
2687 char *key = strprintf("%s+%lx", ss->name, (unsigned long)value);
2688 asymbol ***csympp =
2689 asymbolpp_hash_lookup(&ss->parent->csyms, key, FALSE);
2690 free(key);
2691 if (csympp != NULL)
2692 return *csympp;
2694 /* For section symbols of sections containing no symbols, return the
2695 section symbol that relocations are generated against */
2696 if (value == 0)
2697 return &ss->symbol;
2698 return NULL;
2701 static asymbol **canonical_symbolp(struct superbfd *sbfd, asymbol *sym)
2703 if (bfd_is_const_section(sym->section)) {
2704 asymbol **csymp;
2705 for (csymp = sbfd->syms.data;
2706 csymp < sbfd->syms.data + sbfd->syms.size; csymp++) {
2707 if (sym == *csymp)
2708 return csymp;
2710 return NULL;
2712 return symbolp_scan(fetch_supersect(sbfd, sym->section), sym->value);
2715 static asymbol *canonical_symbol(struct superbfd *sbfd, asymbol *sym)
2717 if (bfd_is_const_section(sym->section))
2718 return sym;
2719 asymbol **symp = canonical_symbolp(sbfd, sym);
2720 return symp != NULL ? *symp : NULL;
2723 static char *static_local_symbol(struct superbfd *sbfd, asymbol *sym)
2725 struct supersect *ss = fetch_supersect(sbfd, sym->section);
2726 if ((sym->flags & BSF_LOCAL) == 0 || (sym->flags & BSF_OBJECT) == 0)
2727 return NULL;
2728 char *dot = strrchr(sym->name, '.');
2729 if (dot == NULL || dot[1 + strspn(dot + 1, "0123546789")] != '\0')
2730 return NULL;
2731 char *basename = strndup(sym->name, dot - sym->name);
2733 /* Handle C.123.12345 symbols */
2734 dot = strrchr(basename, '.');
2735 if (dot != NULL && dot[1 + strspn(dot + 1, "0123546789")] == '\0')
2736 basename = strndup(basename, dot - basename);
2737 const char *caller;
2738 if (strcmp(basename, "__func__") == 0 ||
2739 strcmp(basename, "__PRETTY_FUNCTION__") == 0)
2740 caller = (const char *)ss->contents.data + sym->value;
2741 else
2742 caller = find_caller(ss, sym);
2743 return strprintf("%s<%s>", basename, caller);
2746 static char *symbol_label(struct superbfd *sbfd, asymbol *sym)
2748 const char *filename = sbfd->abfd->filename;
2749 char *c = strstr(filename, ".KSPLICE");
2750 int flen = (c == NULL ? strlen(filename) : c - filename);
2752 char *label;
2753 if (bfd_is_und_section(sym->section) || (sym->flags & BSF_GLOBAL) != 0) {
2754 label = strdup(sym->name);
2755 } else if (bfd_is_const_section(sym->section)) {
2756 label = strprintf("%s<%.*s>", sym->name, flen, filename);
2757 } else {
2758 asymbol *gsym = canonical_symbol(sbfd, sym);
2760 if (gsym == NULL)
2761 label = strprintf("%s+%lx<%.*s>",
2762 sym->section->name,
2763 (unsigned long)sym->value,
2764 flen, filename);
2765 else if ((gsym->flags & BSF_GLOBAL) != 0)
2766 label = strdup(gsym->name);
2767 else if (static_local_symbol(sbfd, gsym))
2768 label = strprintf("%s+%lx<%.*s>",
2769 static_local_symbol(sbfd, gsym),
2770 (unsigned long)sym->value,
2771 flen, filename);
2772 else
2773 label = strprintf("%s<%.*s>",
2774 gsym->name, flen, filename);
2777 return label;
2780 static void keep_span(struct span *span)
2782 span->keep = true;
2783 span->ss->keep = true;
2786 static struct span *new_span(struct supersect *ss, bfd_vma start, bfd_vma size)
2788 struct span *span = vec_grow(&ss->spans, 1);
2789 span->size = size;
2790 span->contents_size = size;
2791 span->start = start;
2792 span->ss = ss;
2793 span->keep = true;
2794 span->new = false;
2795 span->patch = false;
2796 span->bugpatch = false;
2797 span->datapatch = false;
2798 span->precallable = starts_with(ss->name, ".ksplice_call_pre_apply") ||
2799 starts_with(ss->name, ".ksplice_call_check_apply") ||
2800 starts_with(ss->name, ".ksplice_call_fail_apply") ||
2801 starts_with(ss->name, ".ksplice_call_post_remove");
2802 span->match = NULL;
2803 span->shift = 0;
2804 asymbol **symp = symbolp_scan(ss, span->start);
2805 if (symp != NULL) {
2806 span->symbol = *symp;
2807 span->label = label_lookup(ss->parent, span->symbol);
2808 } else {
2809 span->symbol = NULL;
2810 const char *label = label_lookup(ss->parent, ss->symbol);
2811 if (span->start != 0)
2812 span->label = strprintf("%s<span:%lx>", label,
2813 (unsigned long)span->start);
2814 else
2815 span->label = label;
2817 span->orig_label = span->label;
2818 return span;
2821 static void initialize_string_spans(struct supersect *ss)
2823 const char *str;
2824 for (str = ss->contents.data;
2825 (void *)str < ss->contents.data + ss->contents.size;) {
2826 bfd_vma start = (unsigned long)str -
2827 (unsigned long)ss->contents.data;
2828 bfd_vma size = strlen(str) + 1;
2829 bfd_vma contents_size = size;
2830 while ((start + size) % (1 << ss->alignment) != 0 &&
2831 start + size < ss->contents.size) {
2832 /* Some string sections, like __ksymtab_strings, only
2833 align some strings with the declared alignment */
2834 if (str[size] != '\0')
2835 break;
2836 size++;
2838 struct span *span = new_span(ss, start, size);
2839 span->contents_size = contents_size;
2840 str += size;
2844 static int compare_ulongs(const void *va, const void *vb)
2846 const unsigned long *a = va, *b = vb;
2847 return *a - *b;
2850 static void initialize_table_spans(struct superbfd *sbfd,
2851 struct table_section *s)
2853 asection *isection = bfd_get_section_by_name(sbfd->abfd, s->sect);
2854 if (isection == NULL)
2855 return;
2856 struct supersect *ss = fetch_supersect(sbfd, isection);
2857 if (ss->alignment < ffs(s->entry_align) - 1)
2858 ss->alignment = ffs(s->entry_align) - 1;
2860 asection *other_sect = NULL;
2861 if (s->other_sect != NULL)
2862 other_sect = bfd_get_section_by_name(sbfd->abfd, s->other_sect);
2863 struct supersect *other_ss = NULL;
2864 if (other_sect != NULL)
2865 other_ss = fetch_supersect(sbfd, other_sect);
2867 asection *crc_sect = NULL;
2868 if (s->crc_sect != NULL)
2869 crc_sect = bfd_get_section_by_name(sbfd->abfd, s->crc_sect);
2870 struct supersect *crc_ss = NULL;
2871 if (crc_sect != NULL)
2872 crc_ss = fetch_supersect(sbfd, crc_sect);
2874 struct ulong_vec offsets;
2875 vec_init(&offsets);
2877 void *entry;
2878 for (entry = ss->contents.data;
2879 entry < ss->contents.data + ss->contents.size;
2880 entry += s->entry_size) {
2881 struct span *span = new_span(ss, addr_offset(ss, entry),
2882 s->entry_size);
2883 if (s->entry_contents_size != 0)
2884 span->contents_size = s->entry_contents_size;
2885 if ((span->symbol == NULL ||
2886 (span->symbol->flags & BSF_SECTION_SYM) != 0) &&
2887 s->has_addr) {
2888 arelent *reloc = find_reloc(ss, entry + s->addr_offset);
2889 assert(reloc);
2890 struct span *target_span = reloc_target_span(ss, reloc);
2891 assert(target_span);
2892 asymbol *sym = *reloc->sym_ptr_ptr;
2893 unsigned long val = get_reloc_offset(ss, reloc, true) +
2894 sym->value - (target_span->start +
2895 target_span->shift);
2896 char *label = strprintf("%s<target:%s+%lx>", ss->name,
2897 target_span->label, val);
2898 change_initial_label(span, label);
2901 if (other_sect != NULL) {
2902 asymbol *sym;
2903 bfd_vma offset = read_reloc(ss, entry + s->other_offset,
2904 sizeof(void *), &sym);
2905 if (sym->section == other_sect) {
2906 assert(offset >= 0 &&
2907 offset < other_ss->contents.size);
2908 *vec_grow(&offsets, 1) = offset;
2912 if (crc_sect != NULL)
2913 new_span(crc_ss, addr_offset(ss, entry) / s->entry_size
2914 * s->crc_size, s->crc_size);
2916 if (ss->type == SS_TYPE_EXPORT) {
2917 const char *symname = read_string(ss, entry +
2918 s->other_offset);
2919 char *label = strprintf("%s:%s", ss->name, symname);
2920 change_initial_label(span, label);
2924 if (other_sect == NULL)
2925 return;
2927 *vec_grow(&offsets, 1) = 0;
2928 qsort(offsets.data, offsets.size, sizeof(*offsets.data),
2929 compare_ulongs);
2930 *vec_grow(&offsets, 1) = other_ss->contents.size;
2932 unsigned long *off;
2933 for (off = offsets.data; off < offsets.data + offsets.size - 1; off++) {
2934 if (*off != *(off + 1))
2935 new_span(other_ss, *off, *(off + 1) - *off);
2939 static void initialize_table_section_spans(struct superbfd *sbfd)
2941 struct supersect *tables_ss =
2942 fetch_supersect(offsets_sbfd,
2943 bfd_get_section_by_name(offsets_sbfd->abfd,
2944 ".ksplice_table_sections"));
2945 const struct table_section *ts;
2946 struct table_section s;
2947 for (ts = tables_ss->contents.data;
2948 (void *)ts < tables_ss->contents.data + tables_ss->contents.size;
2949 ts++) {
2950 s = *ts;
2951 s.sect = read_string(tables_ss, &ts->sect);
2952 s.other_sect = read_string(tables_ss, &ts->other_sect);
2953 s.crc_sect = read_string(tables_ss, &ts->crc_sect);
2954 initialize_table_spans(sbfd, &s);
2958 static void initialize_ksplice_call_spans(struct supersect *ss)
2960 arelent **relocp;
2961 for (relocp = ss->relocs.data;
2962 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
2963 arelent *reloc = *relocp;
2964 new_span(ss, reloc->address, bfd_get_reloc_size(reloc->howto));
2965 /* the span labels should already be unique */
2969 static void initialize_spans(struct superbfd *sbfd)
2971 asection *sect;
2972 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2973 if (is_table_section(sect->name, true) && mode("keep"))
2974 continue;
2976 struct supersect *ss = fetch_supersect(sbfd, sect);
2977 if (ss->type == SS_TYPE_STRING)
2978 initialize_string_spans(ss);
2979 else if (ss->type == SS_TYPE_KSPLICE_CALL)
2980 initialize_ksplice_call_spans(ss);
2981 else
2982 new_span(ss, 0, ss->contents.size);
2984 if (mode("keep"))
2985 initialize_table_section_spans(sbfd);
2988 struct span *reloc_target_span(struct supersect *ss, arelent *reloc)
2990 asymbol *sym_ptr = *reloc->sym_ptr_ptr;
2991 if (bfd_is_const_section(sym_ptr->section))
2992 return NULL;
2994 bfd_vma addend = get_reloc_offset(ss, reloc, true) + sym_ptr->value;
2995 struct supersect *sym_ss =
2996 fetch_supersect(ss->parent, sym_ptr->section);
2997 struct span *span, *target_span = sym_ss->spans.data;
2998 for (span = sym_ss->spans.data;
2999 span < sym_ss->spans.data + sym_ss->spans.size; span++) {
3000 if (addend >= span->start && addend < span->start + span->size)
3001 target_span = span;
3003 return target_span;
3006 struct span *find_span(struct supersect *ss, bfd_size_type address)
3008 struct span *span;
3009 for (span = ss->spans.data; span < ss->spans.data + ss->spans.size;
3010 span++) {
3011 if (address >= span->start &&
3012 address < span->start + span->size)
3013 return span;
3015 /* Deal with empty BSS sections */
3016 if (ss->contents.size == 0 && ss->spans.size > 0)
3017 return ss->spans.data;
3018 return NULL;
3021 void compute_span_shifts(struct superbfd *sbfd)
3023 asection *sect;
3024 struct span *span;
3025 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
3026 struct supersect *ss = fetch_supersect(sbfd, sect);
3027 if (!ss->keep)
3028 continue;
3029 bfd_size_type offset = 0;
3030 for (span = ss->spans.data;
3031 span < ss->spans.data + ss->spans.size; span++) {
3032 if (!span->keep)
3033 continue;
3034 span->shift = offset - span->start;
3035 offset += span->size;
3040 void remove_unkept_spans(struct superbfd *sbfd)
3042 asection *sect;
3043 struct span *span;
3044 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
3045 struct supersect *ss = fetch_supersect(sbfd, sect);
3046 delete_obsolete_relocs(ss);
3047 struct arelentp_vec orig_relocs;
3048 vec_move(&orig_relocs, &ss->relocs);
3049 arelent **relocp, *reloc;
3050 for (relocp = orig_relocs.data;
3051 relocp < orig_relocs.data + orig_relocs.size; relocp++) {
3052 reloc = *relocp;
3053 asymbol *sym = *reloc->sym_ptr_ptr;
3054 span = reloc_target_span(ss, reloc);
3055 if ((span != NULL && span->keep && span->shift == 0) ||
3056 bfd_is_const_section(sym->section)) {
3057 *vec_grow(&ss->relocs, 1) = reloc;
3058 continue;
3060 struct supersect *sym_ss =
3061 fetch_supersect(sbfd, sym->section);
3062 if (span != NULL && (sym->flags & BSF_SECTION_SYM) == 0
3063 && find_span(sym_ss, sym->value) != span) {
3064 err(sbfd, "Spans for symbol %s and relocation "
3065 "target do not match in sect %s\n",
3066 sym->name, sym_ss->name);
3067 DIE;
3069 if (span != NULL && span->keep) {
3070 arelent *new_reloc = malloc(sizeof(*new_reloc));
3071 *new_reloc = *reloc;
3072 new_reloc->addend =
3073 get_reloc_offset(ss, reloc, false);
3074 new_reloc->addend += span->shift;
3075 *vec_grow(&ss->new_relocs, 1) = new_reloc;
3080 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
3081 struct supersect *ss = fetch_supersect(sbfd, sect), orig_ss;
3082 if (!ss->keep)
3083 continue;
3084 supersect_move(&orig_ss, ss);
3085 vec_init(&ss->spans);
3086 for (span = orig_ss.spans.data;
3087 span < orig_ss.spans.data + orig_ss.spans.size; span++) {
3088 if (!span->keep)
3089 continue;
3090 struct span *new_span = vec_grow(&ss->spans, 1);
3091 *new_span = *span;
3092 new_span->start = span->start + span->shift;
3093 new_span->shift = 0;
3094 sect_copy(ss, sect_do_grow(ss, 1, span->size, 1),
3095 &orig_ss, orig_ss.contents.data + span->start,
3096 span->size);
3101 static void init_objmanip_superbfd(struct superbfd *sbfd)
3103 init_label_map(sbfd);
3104 initialize_supersect_types(sbfd);
3105 initialize_spans(sbfd);
3106 load_options(sbfd);
3109 void mangle_section_name(struct superbfd *sbfd, const char *name)
3111 asection *sect = bfd_get_section_by_name(sbfd->abfd, name);
3112 if (sect == NULL)
3113 return;
3114 struct supersect *ss = fetch_supersect(sbfd, sect);
3115 ss->name = strprintf(".ksplice_pre.%s", ss->name);
3118 static void write_bugline_patches(struct superbfd *sbfd)
3120 const struct table_section *ts = get_table_section("__bug_table");
3121 asection *sect = bfd_get_section_by_name(sbfd->abfd, "__bug_table");
3122 if (sect == NULL)
3123 return;
3124 struct supersect *ss = fetch_supersect(sbfd, sect);
3125 assert(ts != NULL);
3127 void *entry;
3128 for (entry = ss->contents.data;
3129 entry < ss->contents.data + ss->contents.size;
3130 entry += ts->entry_size) {
3131 struct span *span = find_span(ss, addr_offset(ss, entry));
3132 assert(span != NULL);
3133 if (!span->bugpatch)
3134 continue;
3135 arelent *reloc = find_reloc(ss, entry + ts->addr_offset);
3136 assert(reloc != NULL);
3137 asymbol *sym = *reloc->sym_ptr_ptr;
3138 assert(!bfd_is_const_section(sym->section));
3140 struct supersect *kpatch_ss =
3141 make_section(sbfd, ".ksplice_patches%s",
3142 sym->section->name);
3143 struct ksplice_patch *kpatch =
3144 sect_grow(kpatch_ss, 1, struct ksplice_patch);
3145 write_ksplice_patch_reloc
3146 (kpatch_ss, sym->section->name, &kpatch->oldaddr,
3147 sizeof(kpatch->oldaddr), span->label, ts->other_offset);
3149 unsigned short *line =
3150 write_patch_storage(kpatch_ss, kpatch, sizeof(*line), NULL);
3151 *line = *(unsigned short *)(entry + ts->other_offset);
3152 kpatch->type = KSPLICE_PATCH_BUGLINE;
3156 void *write_patch_storage(struct supersect *ss, struct ksplice_patch *kpatch,
3157 size_t size, struct supersect **data_ssp)
3159 struct supersect *data_ss = make_section(ss->parent,
3160 ".ksplice_patch_data");
3161 char *saved = sect_do_grow(data_ss, 1, size, 1);
3162 write_reloc(ss, &kpatch->saved, &data_ss->symbol,
3163 addr_offset(data_ss, saved));
3164 char *data = sect_do_grow(data_ss, 1, size, 1);
3165 write_reloc(ss, &kpatch->contents, &data_ss->symbol,
3166 addr_offset(data_ss, data));
3167 kpatch->size = size;
3168 if (data_ssp != NULL)
3169 *data_ssp = data_ss;
3170 return data;