Delete ksplice structures for exit sections in the core kernel.
[ksplice.git] / objmanip.c
blobce9663d7e7e7de77b5ae4256f4a8a034c048f611
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 Jeffrey Brian Arnold <jbarnold@mit.edu>
5 * Copyright (C) 2008 Anders Kaseorg <andersk@mit.edu>,
6 * Tim Abbott <tabbott@mit.edu>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License, version 2.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
19 * 02110-1301, USA.
22 /* objmanip performs various object file manipulations for Ksplice. Its first
23 * two arguments are always an input object file and an output object file.
25 * - keep-primary: "objmanip <post.o> <out.o> keep-primary <pre.o> <kid>"
27 * This mode prepares the object file to be installed as a ksplice update. The
28 * kid argument is the ksplice id string for the ksplice update being built.
30 * - keep-helper: "objmanip <pre.o> <out.o> keep-helper"
32 * This mode prepares the object file to be used for run-pre matching. This
33 * involves replacing all ELF relocations with ksplice relocations and
34 * writing ksplice_section structures for each ELF text or data section.
36 * - rmsyms mode: "objmanip <in.o> <out.o> rmsyms
38 * In this mode, any ELF relocations involving the list of symbol names given on
39 * standard input are replaced with ksplice relocations. This is used only
40 * for KSPLICE_STANDALONE.
42 * - finalize mode: "objmanip <in.o> <out.o> finalize"
44 * In this mode, any ELF relocations to undefined symbols are replaced with
45 * ksplice relocations.
48 /* Always define KSPLICE_STANDALONE, even if you're using integrated Ksplice.
49 objmanip won't compile without it. */
50 #define KSPLICE_STANDALONE
52 #define _GNU_SOURCE
53 #include "objcommon.h"
54 #include "kmodsrc/ksplice.h"
55 #include "kmodsrc/offsets.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 struct export {
69 const char *name;
70 struct supersect *ss;
72 DECLARE_VEC_TYPE(struct export, export_vec);
74 DECLARE_VEC_TYPE(const char *, str_vec);
76 DECLARE_VEC_TYPE(unsigned long, ulong_vec);
78 struct export_desc {
79 const char *export_type;
80 bool deletion;
81 struct str_vec names;
82 struct supersect *sym_ss;
83 struct supersect *crc_ss;
85 DECLARE_VEC_TYPE(struct export_desc, export_desc_vec);
87 #define bool_init(b) *(b) = false
88 DEFINE_HASH_TYPE(bool, bool_hash, bool_hash_init, bool_hash_free,
89 bool_hash_lookup, bool_init);
91 #define ulong_init(x) *(x) = 0
92 DEFINE_HASH_TYPE(unsigned long, ulong_hash, ulong_hash_init,
93 ulong_hash_free, ulong_hash_lookup, ulong_init);
95 void do_keep_primary(struct superbfd *isbfd, const char *pre);
96 void do_keep_helper(struct superbfd *isbfd);
97 void do_finalize(struct superbfd *isbfd);
98 void do_rmsyms(struct superbfd *isbfd);
100 struct export_vec *get_export_syms(struct superbfd *sbfd);
101 void compare_exported_symbols(struct superbfd *oldsbfd,
102 struct superbfd *newsbfd, bool deletion);
103 struct export_desc *new_export_desc(struct supersect *ss, bool deletion);
104 bool relocs_equal(struct supersect *old_src_ss, struct supersect *new_src_ss,
105 arelent *old_reloc, arelent *new_reloc);
106 bfd_vma non_dst_mask(struct supersect *ss, arelent *reloc);
107 bool all_relocs_equal(struct span *old_span, struct span *new_span);
108 static bool part_of_reloc(struct supersect *ss, unsigned long addr);
109 static bool nonrelocs_equal(struct span *old_span, struct span *new_span);
110 static void handle_section_symbol_renames(struct superbfd *oldsbfd,
111 struct superbfd *newsbfd);
113 enum supersect_type supersect_type(struct supersect *ss);
114 void initialize_supersect_types(struct superbfd *sbfd);
115 static void initialize_spans(struct superbfd *sbfd);
116 static void initialize_string_spans(struct supersect *ss);
117 static void initialize_table_spans(struct superbfd *sbfd,
118 struct table_section *s);
119 static void initialize_table_section_spans(struct superbfd *sbfd);
120 struct span *reloc_target_span(struct supersect *ss, arelent *reloc);
121 struct span *find_span(struct supersect *ss, bfd_size_type address);
122 void remove_unkept_spans(struct superbfd *sbfd);
123 void compute_span_shifts(struct superbfd *sbfd);
124 static struct span *new_span(struct supersect *ss, bfd_vma start, bfd_vma size);
125 bool is_table_section(const char *name, bool consider_other);
126 void mangle_section_name(struct superbfd *sbfd, const char *name);
128 void rm_relocs(struct superbfd *isbfd);
129 void rm_some_relocs(struct supersect *ss);
130 void write_ksplice_reloc(struct supersect *ss, arelent *orig_reloc);
131 void load_ksplice_symbol_offsets(struct superbfd *sbfd);
132 void blot_section(struct supersect *ss, int offset, reloc_howto_type *howto);
133 static void write_ksplice_section(struct span *span);
134 void write_ksplice_patch(struct superbfd *sbfd, struct span *span);
135 void write_ksplice_deleted_patch(struct superbfd *sbfd, const char *name,
136 const char *label, const char *sectname);
137 asymbol **make_undefined_symbolp(struct superbfd *sbfd, const char *name);
138 void filter_table_sections(struct superbfd *isbfd);
139 void filter_table_section(struct superbfd *sbfd, const struct table_section *s);
140 void keep_referenced_sections(struct superbfd *sbfd);
141 bfd_boolean copy_object(bfd *ibfd, bfd *obfd);
142 void setup_section(bfd *ibfd, asection *isection, void *obfdarg);
143 static void setup_new_section(bfd *obfd, struct supersect *ss);
144 static void write_section(bfd *obfd, asection *osection, void *arg);
145 static void delete_obsolete_relocs(struct supersect *ss);
146 void mark_symbols_used_in_relocations(bfd *abfd, asection *isection,
147 void *ignored);
148 static void ss_mark_symbols_used_in_relocations(struct supersect *ss);
149 void filter_symbols(bfd *ibfd, bfd *obfd, struct asymbolp_vec *osyms,
150 struct asymbolp_vec *isyms);
151 static bool deleted_table_section_symbol(bfd *abfd, asymbol *sym);
152 void read_str_set(struct str_vec *strs);
153 bool str_in_set(const char *str, const struct str_vec *strs);
154 struct supersect *__attribute((format(printf, 2, 3)))
155 make_section(struct superbfd *sbfd, const char *fmt, ...);
156 void __attribute__((format(printf, 3, 4)))
157 write_string(struct supersect *ss, const char **addr, const char *fmt, ...);
158 void rm_some_exports(struct superbfd *isbfd, const struct export_desc *ed);
159 void write_ksplice_export(struct superbfd *sbfd, const char *symname,
160 const char *export_type, bool del);
161 void write_reloc(struct supersect *ss, const void *addr, asymbol **symp,
162 bfd_vma offset);
163 arelent *create_reloc(struct supersect *ss, const void *addr, asymbol **symp,
164 bfd_vma offset);
165 static void foreach_symbol_pair(struct superbfd *oldsbfd, struct superbfd *newsbfd,
166 void (*fn)(struct span *old_span,
167 asymbol *oldsym,
168 struct span *new_span,
169 asymbol *newsym));
170 static void check_global_symbols(struct span *old_span, asymbol *oldsym,
171 struct span *new_span, asymbol *newsym);
172 static void match_global_symbols(struct span *old_span, asymbol *oldsym,
173 struct span *new_span, asymbol *newsym);
174 static void match_symbol_spans(struct span *old_span, asymbol *oldsym,
175 struct span *new_span, asymbol *newsym);
177 static void foreach_span_pair(struct superbfd *oldsbfd,
178 struct superbfd *newsbfd,
179 void (*fn)(struct span *old_span,
180 struct span *new_span));
181 static void match_spans_by_label(struct span *old_span, struct span *new_span);
182 static void match_string_spans(struct span *old_span, struct span *new_span);
183 static void mark_new_spans(struct superbfd *sbfd);
184 static void handle_deleted_spans(struct superbfd *oldsbfd,
185 struct superbfd *newsbfd);
186 static void compare_matched_spans(struct superbfd *newsbfd);
187 static void compare_spans(struct span *old_span, struct span *new_span);
188 static void update_nonzero_offsets(struct superbfd *sbfd);
189 static void handle_nonzero_offset_relocs(struct supersect *ss);
190 static void keep_span(struct span *span);
192 static void init_objmanip_superbfd(struct superbfd *sbfd);
193 static const char *label_lookup(struct superbfd *sbfd, asymbol *sym);
194 static void label_map_set(struct superbfd *sbfd, const char *oldlabel,
195 const char *label);
196 static void print_label_changes(struct superbfd *sbfd);
197 static void init_label_map(struct superbfd *sbfd);
198 static asymbol **symbolp_scan(struct supersect *ss, bfd_vma value);
199 static void init_csyms(struct superbfd *sbfd);
200 static void init_callers(struct superbfd *sbfd);
201 static asymbol *canonical_symbol(struct superbfd *sbfd, asymbol *sym);
202 static asymbol **canonical_symbolp(struct superbfd *sbfd, asymbol *sym);
203 static char *static_local_symbol(struct superbfd *sbfd, asymbol *sym);
204 static char *symbol_label(struct superbfd *sbfd, asymbol *sym);
206 int verbose = 0;
207 #define debug_(sbfd, level, fmt, ...) \
208 do { \
209 if (verbose >= (level)) \
210 printf("%s: " fmt, (sbfd)->abfd->filename, \
211 ## __VA_ARGS__); \
212 } while (0)
213 #define debug0(sbfd, fmt, ...) debug_(sbfd, 0, fmt, ## __VA_ARGS__)
214 #define debug1(sbfd, fmt, ...) debug_(sbfd, 1, fmt, ## __VA_ARGS__)
215 #define err(sbfd, fmt, ...) \
216 do { \
217 fprintf(stderr, "%s: " fmt, (sbfd)->abfd->filename, \
218 ## __VA_ARGS__); \
219 } while (0)
221 struct str_vec delsects, rmsyms;
222 struct export_desc_vec exports;
223 bool changed;
225 struct ksplice_config *config;
227 const char *modestr, *kid, *finalize_target = NULL;
228 bool write_output = true;
230 struct superbfd *offsets_sbfd = NULL;
232 #define mode(str) starts_with(modestr, str)
234 DECLARE_VEC_TYPE(unsigned long, addr_vec);
235 DEFINE_HASH_TYPE(struct addr_vec, addr_vec_hash,
236 addr_vec_hash_init, addr_vec_hash_free, addr_vec_hash_lookup,
237 vec_init);
238 struct addr_vec_hash system_map;
240 struct bool_hash system_map_written;
241 struct ulong_hash ksplice_symbol_offset;
242 struct ulong_hash ksplice_string_offset;
244 void load_system_map()
246 const char *config_dir = getenv("KSPLICE_CONFIG_DIR");
247 assert(config_dir);
248 char *file;
249 assert(asprintf(&file, "%s/System.map", config_dir) >= 0);
250 FILE *fp = fopen(file, "r");
251 assert(fp);
252 addr_vec_hash_init(&system_map);
253 unsigned long addr;
254 char type;
255 char *sym;
256 while (fscanf(fp, "%lx %c %as\n", &addr, &type, &sym) == 3)
257 *vec_grow(addr_vec_hash_lookup(&system_map, sym, TRUE),
258 1) = addr;
259 fclose(fp);
262 void load_ksplice_symbol_offsets(struct superbfd *sbfd)
264 asection *sect = bfd_get_section_by_name(sbfd->abfd,
265 ".ksplice_symbols");
266 if (sect == NULL)
267 return;
268 struct supersect *ss = fetch_supersect(sbfd, sect);
270 struct ksplice_symbol *ksym;
271 for (ksym = ss->contents.data;
272 (void *)ksym < ss->contents.data + ss->contents.size; ksym++) {
273 const char *label = read_string(ss, &ksym->label);
274 unsigned long *ksymbol_offp =
275 ulong_hash_lookup(&ksplice_symbol_offset, label, TRUE);
276 *ksymbol_offp = addr_offset(ss, ksym);
280 void load_offsets()
282 char *kmodsrc = getenv("KSPLICE_KMODSRC"), *offsets_file;
283 assert(kmodsrc != NULL);
284 assert(asprintf(&offsets_file, "%s/offsets.o", kmodsrc) >= 0);
285 bfd *offsets_bfd = bfd_openr(offsets_file, NULL);
286 assert(offsets_bfd != NULL);
287 char **matching;
288 assert(bfd_check_format_matches(offsets_bfd, bfd_object, &matching));
289 offsets_sbfd = fetch_superbfd(offsets_bfd);
291 asection *config_sect = bfd_get_section_by_name(offsets_sbfd->abfd,
292 ".ksplice_config");
293 struct supersect *config_ss =
294 fetch_supersect(offsets_sbfd, config_sect);
296 config = config_ss->contents.data;
299 bool matchable_data_section(struct supersect *ss)
301 if (ss->type == SS_TYPE_STRING)
302 return true;
303 if (ss->type == SS_TYPE_RODATA)
304 return true;
305 if (ss->type == SS_TYPE_DATA && ss->relocs.size != 0)
306 return true;
307 return false;
310 bool unchangeable_section(struct supersect *ss)
312 if (ss->type == SS_TYPE_DATA)
313 return true;
314 if (ss->type == SS_TYPE_IGNORED && !starts_with(ss->name, ".debug") &&
315 strcmp(ss->name, "__ksymtab_strings") != 0)
316 return true;
317 return false;
320 int main(int argc, char *argv[])
322 if (getenv("KSPLICE_VERBOSE") != NULL)
323 verbose = atoi(getenv("KSPLICE_VERBOSE"));
325 bfd_init();
326 bfd *ibfd = bfd_openr(argv[1], NULL);
327 assert(ibfd);
329 char **matching;
330 assert(bfd_check_format_matches(ibfd, bfd_object, &matching));
332 const char *output_target = bfd_get_target(ibfd);
334 load_system_map();
335 load_offsets();
337 bool_hash_init(&system_map_written);
338 ulong_hash_init(&ksplice_symbol_offset);
339 ulong_hash_init(&ksplice_string_offset);
341 struct superbfd *isbfd = fetch_superbfd(ibfd);
343 modestr = argv[3];
344 if (mode("finalize"))
345 finalize_target = argv[4];
346 init_objmanip_superbfd(isbfd);
347 if (mode("keep-primary")) {
348 kid = argv[5];
349 do_keep_primary(isbfd, argv[4]);
350 } else if (mode("keep-helper")) {
351 do_keep_helper(isbfd);
352 } else if (mode("finalize")) {
353 do_finalize(isbfd);
354 } else if (mode("rmsyms")) {
355 do_rmsyms(isbfd);
358 if (write_output) {
359 bfd *obfd = bfd_openw(argv[2], output_target);
360 assert(obfd);
361 copy_object(ibfd, obfd);
362 assert(bfd_close(obfd));
365 if (offsets_sbfd != NULL)
366 assert(bfd_close(offsets_sbfd->abfd));
367 assert(bfd_close(ibfd));
368 return EXIT_SUCCESS;
371 void do_keep_primary(struct superbfd *isbfd, const char *pre)
373 struct bfd *prebfd = bfd_openr(pre, NULL);
374 assert(prebfd != NULL);
375 char **matching;
376 assert(bfd_check_format_matches(prebfd, bfd_object, &matching));
378 struct superbfd *presbfd = fetch_superbfd(prebfd);
379 init_objmanip_superbfd(presbfd);
381 foreach_symbol_pair(presbfd, isbfd, match_global_symbols);
382 debug1(isbfd, "Matched global\n");
383 foreach_span_pair(presbfd, isbfd, match_string_spans);
384 debug1(isbfd, "Matched string spans\n");
385 foreach_symbol_pair(presbfd, isbfd, match_symbol_spans);
386 debug1(isbfd, "Matched by name\n");
387 foreach_span_pair(presbfd, isbfd, match_spans_by_label);
388 debug1(isbfd, "Matched by label\n");
390 do {
391 changed = false;
392 compare_matched_spans(isbfd);
393 update_nonzero_offsets(isbfd);
394 mark_new_spans(isbfd);
395 } while (changed);
396 vec_init(&delsects);
398 foreach_symbol_pair(presbfd, isbfd, check_global_symbols);
400 handle_deleted_spans(presbfd, isbfd);
401 handle_section_symbol_renames(presbfd, isbfd);
403 vec_init(&exports);
404 compare_exported_symbols(presbfd, isbfd, false);
405 compare_exported_symbols(isbfd, presbfd, true);
407 assert(bfd_close(prebfd));
409 asection *sect;
410 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
411 struct supersect *ss = fetch_supersect(isbfd, sect);
412 ss->keep = false;
413 struct span *span;
414 for (span = ss->spans.data;
415 span < ss->spans.data + ss->spans.size; span++) {
416 if (span->new || span->patch)
417 keep_span(span);
421 print_label_changes(isbfd);
423 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
424 struct supersect *ss = fetch_supersect(isbfd, sect);
425 struct span *span;
426 for (span = ss->spans.data;
427 span < ss->spans.data + ss->spans.size; span++) {
428 if (span->patch)
429 debug0(isbfd, "Patching span %s\n",
430 span->label);
434 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
435 struct supersect *ss = fetch_supersect(isbfd, sect);
436 struct span *span;
437 for (span = ss->spans.data;
438 span < ss->spans.data + ss->spans.size; span++) {
439 if (span->new)
440 debug0(isbfd, "New span %s\n", span->label);
444 const char **sectname;
445 for (sectname = delsects.data;
446 sectname < delsects.data + delsects.size; sectname++)
447 debug0(isbfd, "Deleted section: %s\n", *sectname);
449 const struct export_desc *ed;
450 for (ed = exports.data; ed < exports.data + exports.size; ed++) {
451 const char **symname;
452 for (symname = ed->names.data;
453 symname < ed->names.data + ed->names.size; symname++)
454 debug0(isbfd, "Export %s (%s): %s\n",
455 ed->deletion ? "deletion" : "addition",
456 ed->export_type, *symname);
459 filter_table_sections(isbfd);
460 write_output = false;
461 for (ed = exports.data; ed < exports.data + exports.size; ed++) {
462 const char **symname;
463 for (symname = ed->names.data;
464 symname < ed->names.data + ed->names.size; symname++)
465 write_ksplice_export(isbfd, *symname,
466 ed->export_type, ed->deletion);
467 if (ed->deletion)
468 write_output = true;
469 else
470 rm_some_exports(isbfd, ed);
473 compute_span_shifts(isbfd);
475 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
476 struct supersect *ss = fetch_supersect(isbfd, sect);
477 struct span *span;
478 for (span = ss->spans.data;
479 span < ss->spans.data + ss->spans.size; span++) {
480 if (span->keep)
481 write_output = true;
482 if (span->patch || span->new)
483 write_ksplice_section(span);
484 if (span->patch)
485 write_ksplice_patch(isbfd, span);
489 rm_relocs(isbfd);
490 remove_unkept_spans(isbfd);
493 void do_keep_helper(struct superbfd *isbfd)
495 asection *sect;
496 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
497 struct supersect *ss = fetch_supersect(isbfd, sect);
498 ss->keep = ss->type == SS_TYPE_TEXT;
501 asymbol **symp;
502 for (symp = isbfd->syms.data;
503 symp < isbfd->syms.data + isbfd->syms.size; symp++) {
504 asymbol *sym = *symp;
505 if (!bfd_is_const_section(sym->section) &&
506 (sym->flags & BSF_GLOBAL) != 0) {
507 struct supersect *sym_ss =
508 fetch_supersect(isbfd, sym->section);
509 if (sym_ss->type != SS_TYPE_IGNORED)
510 sym_ss->keep = true;
514 struct span *span;
515 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
516 struct supersect *ss = fetch_supersect(isbfd, sect);
517 for (span = ss->spans.data;
518 span < ss->spans.data + ss->spans.size; span++)
519 span->keep = ss->keep;
522 do {
523 changed = false;
524 keep_referenced_sections(isbfd);
525 } while (changed);
527 filter_table_sections(isbfd);
528 compute_span_shifts(isbfd);
530 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
531 struct supersect *ss = fetch_supersect(isbfd, sect);
532 asymbol *sym = canonical_symbol(isbfd, sect->symbol);
533 if (sym == NULL)
534 continue;
535 if ((sym->flags & BSF_WEAK) != 0)
536 continue;
537 if (bfd_get_section_size(sect) == 0)
538 continue;
539 if (!ss->keep)
540 continue;
541 if (ss->type != SS_TYPE_TEXT && !matchable_data_section(ss))
542 continue;
544 struct span *span;
545 for (span = ss->spans.data;
546 span < ss->spans.data + ss->spans.size; span++) {
547 if (span->keep)
548 write_ksplice_section(span);
552 rm_relocs(isbfd);
553 remove_unkept_spans(isbfd);
554 mangle_section_name(isbfd, "__markers");
557 void do_finalize(struct superbfd *isbfd)
559 load_ksplice_symbol_offsets(isbfd);
560 asection *sect;
561 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
562 struct supersect *ss = fetch_supersect(isbfd, sect);
563 if (ss->type == SS_TYPE_EXIT) {
564 struct span *span;
565 for (span = ss->spans.data;
566 span < ss->spans.data + ss->spans.size; span++)
567 span->keep = false;
568 ss->keep = false;
571 rm_relocs(isbfd);
574 void do_rmsyms(struct superbfd *isbfd)
576 read_str_set(&rmsyms);
577 rm_relocs(isbfd);
580 struct export_vec *get_export_syms(struct superbfd *sbfd)
582 asection *sect;
583 struct export_vec *exports;
584 exports = malloc(sizeof(*exports));
585 assert(exports != NULL);
586 vec_init(exports);
588 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
589 if (!starts_with(sect->name, "__ksymtab") ||
590 ends_with(sect->name, "_strings"))
591 continue;
592 struct supersect *ss = fetch_supersect(sbfd, sect);
593 struct kernel_symbol *sym;
594 assert(ss->contents.size * 2 == ss->relocs.size *
595 sizeof(struct kernel_symbol));
596 for (sym = ss->contents.data;
597 (void *)sym < ss->contents.data + ss->contents.size;
598 sym++) {
599 struct export *exp = vec_grow(exports, 1);
600 exp->name =
601 read_string(ss, (const char *const *)&sym->name);
602 exp->ss = ss;
605 return exports;
608 struct export_desc *new_export_desc(struct supersect *ss, bool deletion)
610 struct export_desc *ed = vec_grow(&exports, 1);
611 ed->deletion = deletion;
612 vec_init(&ed->names);
613 ed->export_type = strdup(ss->name) + strlen("__ksymtab");
614 ed->sym_ss = ss;
615 char *crc_sect_name;
616 assert(asprintf(&crc_sect_name, "__kcrctab%s", ed->export_type) >= 0);
617 asection *crc_sect =
618 bfd_get_section_by_name(ss->parent->abfd, crc_sect_name);
619 if (crc_sect == NULL)
620 ed->crc_ss = NULL;
621 else
622 ed->crc_ss = fetch_supersect(ss->parent, crc_sect);
623 return ed;
626 void compare_exported_symbols(struct superbfd *oldsbfd,
627 struct superbfd *newsbfd, bool deletion)
629 struct export_vec *new_exports, *old_exports;
630 new_exports = get_export_syms(newsbfd);
631 if (new_exports == NULL)
632 return;
633 old_exports = get_export_syms(oldsbfd);
634 struct export *old, *new;
635 struct supersect *last_ss = NULL;
636 struct export_desc *ed = NULL;
637 for (new = new_exports->data; new < new_exports->data +
638 new_exports->size; new++) {
639 bool found = false;
640 if (old_exports != NULL) {
641 for (old = old_exports->data; old < old_exports->data +
642 old_exports->size; old++) {
643 if (strcmp(new->name, old->name) == 0 &&
644 strcmp(new->ss->name, old->ss->name) == 0) {
645 found = true;
646 break;
650 if (!found) {
651 if (last_ss != new->ss) {
652 last_ss = new->ss;
653 ed = new_export_desc(new->ss, deletion);
655 *vec_grow(&ed->names, 1) = new->name;
660 void match_spans(struct span *old_span, struct span *new_span)
662 struct superbfd *sbfd = new_span->ss->parent;
663 if (old_span->match == new_span && new_span->match == old_span)
664 return;
665 if (old_span->match != NULL) {
666 err(sbfd, "Matching conflict: old %s: %s != %s\n",
667 old_span->label, old_span->match->label, new_span->label);
668 DIE;
670 if (new_span->match != NULL) {
671 err(sbfd, "Matching conflict: new %s: %s != %s\n",
672 new_span->label, new_span->match->label, old_span->label);
673 DIE;
675 old_span->match = new_span;
676 new_span->match = old_span;
677 debug1(sbfd, "Matched old %s to new %s\n", old_span->label,
678 new_span->label);
681 static void match_global_symbols(struct span *old_span, asymbol *oldsym,
682 struct span *new_span, asymbol *newsym)
684 if ((oldsym->flags & BSF_GLOBAL) == 0 ||
685 (newsym->flags & BSF_GLOBAL) == 0)
686 return;
687 match_spans(old_span, new_span);
690 static void check_global_symbols(struct span *old_span, asymbol *oldsym,
691 struct span *new_span, asymbol *newsym)
693 if ((oldsym->flags & BSF_GLOBAL) == 0 ||
694 (newsym->flags & BSF_GLOBAL) == 0)
695 return;
696 if (old_span->ss->type == SS_TYPE_IGNORED)
697 return;
698 if (old_span->match != new_span || new_span->match != old_span) {
699 err(new_span->ss->parent, "Global symbol span mismatch: %s "
700 "%s/%s\n", oldsym->name, old_span->ss->name,
701 new_span->ss->name);
702 DIE;
706 static void foreach_symbol_pair(struct superbfd *oldsbfd, struct superbfd *newsbfd,
707 void (*fn)(struct span *old_span,
708 asymbol *oldsym,
709 struct span *new_span,
710 asymbol *newsym))
712 asymbol **oldsymp, **newsymp;
713 for (oldsymp = oldsbfd->syms.data;
714 oldsymp < oldsbfd->syms.data + oldsbfd->syms.size; oldsymp++) {
715 asymbol *oldsym = *oldsymp;
716 if (bfd_is_const_section(oldsym->section))
717 continue;
718 for (newsymp = newsbfd->syms.data;
719 newsymp < newsbfd->syms.data + newsbfd->syms.size;
720 newsymp++) {
721 asymbol *newsym = *newsymp;
722 if (bfd_is_const_section(newsym->section))
723 continue;
724 if (strcmp(oldsym->name, newsym->name) != 0)
725 continue;
727 struct supersect *old_ss =
728 fetch_supersect(oldsbfd, oldsym->section);
729 struct supersect *new_ss =
730 fetch_supersect(newsbfd, newsym->section);
731 if (old_ss->type != new_ss->type ||
732 old_ss->type == SS_TYPE_SPECIAL ||
733 old_ss->type == SS_TYPE_EXPORT)
734 continue;
736 struct span *old_span =
737 find_span(old_ss, oldsym->value);
738 struct span *new_span =
739 find_span(new_ss, newsym->value);
740 if (old_span == NULL) {
741 err(oldsbfd, "Could not find span for %s\n",
742 oldsym->name);
743 DIE;
745 if (new_span == NULL) {
746 err(newsbfd, "Could not find span for %s\n",
747 newsym->name);
748 DIE;
750 fn(old_span, oldsym, new_span, newsym);
755 static void match_symbol_spans(struct span *old_span, asymbol *oldsym,
756 struct span *new_span, asymbol *newsym)
758 if ((oldsym->flags & BSF_DEBUGGING) != 0 ||
759 (newsym->flags & BSF_DEBUGGING) != 0)
760 return;
761 if (old_span->ss->type == SS_TYPE_SPECIAL ||
762 old_span->ss->type == SS_TYPE_EXPORT)
763 return;
764 if (static_local_symbol(old_span->ss->parent, oldsym) ||
765 static_local_symbol(new_span->ss->parent, newsym))
766 return;
767 if (old_span->match == NULL && new_span->match == NULL)
768 match_spans(old_span, new_span);
771 static void match_spans_by_label(struct span *old_span, struct span *new_span)
773 if (old_span->ss->type == SS_TYPE_STRING)
774 return;
775 if (strcmp(old_span->label, new_span->label) == 0)
776 match_spans(old_span, new_span);
779 static void match_string_spans(struct span *old_span, struct span *new_span)
781 if (old_span->ss->type != SS_TYPE_STRING ||
782 strcmp(old_span->ss->name, new_span->ss->name) != 0)
783 return;
784 if (strcmp((char *)old_span->ss->contents.data + old_span->start,
785 (char *)new_span->ss->contents.data + new_span->start) == 0)
786 match_spans(old_span, new_span);
789 static void foreach_span_pair(struct superbfd *oldsbfd,
790 struct superbfd *newsbfd,
791 void (*fn)(struct span *old_span,
792 struct span *new_span))
794 asection *oldsect, *newsect;
795 struct supersect *oldss, *newss;
796 struct span *old_span, *new_span;
797 for (newsect = newsbfd->abfd->sections; newsect != NULL;
798 newsect = newsect->next) {
799 newss = fetch_supersect(newsbfd, newsect);
800 if (newss->type == SS_TYPE_SPECIAL ||
801 newss->type == SS_TYPE_EXPORT)
802 continue;
803 for (oldsect = oldsbfd->abfd->sections; oldsect != NULL;
804 oldsect = oldsect->next) {
805 oldss = fetch_supersect(oldsbfd, oldsect);
806 if (oldss->type != newss->type)
807 continue;
808 for (new_span = newss->spans.data;
809 new_span < newss->spans.data + newss->spans.size;
810 new_span++) {
811 for (old_span = oldss->spans.data;
812 old_span < oldss->spans.data +
813 oldss->spans.size; old_span++)
814 fn(old_span, new_span);
820 static void mark_new_spans(struct superbfd *sbfd)
822 asection *sect;
823 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
824 struct supersect *ss = fetch_supersect(sbfd, sect);
825 if (ss->type == SS_TYPE_SPECIAL || ss->type == SS_TYPE_EXPORT ||
826 ss->type == SS_TYPE_IGNORED)
827 continue;
828 struct span *span;
829 for (span = ss->spans.data;
830 span < ss->spans.data + ss->spans.size; span++) {
831 if (span->match == NULL)
832 span->new = true;
837 static void handle_deleted_spans(struct superbfd *oldsbfd,
838 struct superbfd *newsbfd)
840 asection *sect;
841 for (sect = oldsbfd->abfd->sections; sect != NULL; sect = sect->next) {
842 struct supersect *ss = fetch_supersect(oldsbfd, sect);
843 if (ss->type != SS_TYPE_TEXT)
844 continue;
845 struct span *span;
846 for (span = ss->spans.data;
847 span < ss->spans.data + ss->spans.size; span++) {
848 if (span->match != NULL)
849 continue;
850 *vec_grow(&delsects, 1) = span->label;
851 if (span->symbol == NULL)
852 DIE;
853 write_ksplice_deleted_patch(newsbfd, span->symbol->name,
854 span->label,
855 span->ss->name);
860 static void handle_nonzero_offset_relocs(struct supersect *ss)
862 struct span *address_span, *target_span;
863 arelent **relocp;
864 for (relocp = ss->relocs.data;
865 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
866 arelent *reloc = *relocp;
867 address_span = find_span(ss, reloc->address);
868 if (!address_span->new && !address_span->patch)
869 continue;
871 asymbol *sym = *reloc->sym_ptr_ptr;
872 if (bfd_is_const_section(sym->section))
873 continue;
874 bfd_vma offset = get_reloc_offset(ss, reloc, true);
875 target_span = reloc_target_span(ss, reloc);
876 if (sym->value + offset == target_span->start)
877 continue;
879 if (target_span->ss->type != SS_TYPE_TEXT)
880 continue;
881 if (target_span->patch)
882 continue;
884 target_span->patch = true;
885 changed = true;
886 debug1(ss->parent, "Changing %s because a relocation from sect "
887 "%s has a nonzero offset %lx+%lx into it\n",
888 target_span->label, ss->name, (unsigned long)sym->value,
889 (unsigned long)offset);
893 static void update_nonzero_offsets(struct superbfd *sbfd)
895 asection *sect;
896 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
897 struct supersect *ss = fetch_supersect(sbfd, sect);
898 if (ss->type == SS_TYPE_SPECIAL || ss->type == SS_TYPE_EXPORT ||
899 ss->type == SS_TYPE_IGNORED)
900 continue;
901 handle_nonzero_offset_relocs(ss);
905 static void compare_spans(struct span *old_span, struct span *new_span)
907 struct superbfd *newsbfd = new_span->ss->parent;
909 if (nonrelocs_equal(old_span, new_span) &&
910 all_relocs_equal(old_span, new_span))
911 return;
913 char *reason;
914 if (new_span->size != old_span->size)
915 reason = "differing sizes";
916 else if (!nonrelocs_equal(old_span, new_span))
917 reason = "differing contents";
918 else
919 reason = "differing relocations";
921 if (new_span->ss->type == SS_TYPE_TEXT) {
922 if (new_span->patch)
923 return;
924 new_span->patch = true;
925 debug1(newsbfd, "Changing %s due to %s\n", new_span->label,
926 reason);
927 } else {
928 debug1(newsbfd, "Unmatching %s and %s due to %s\n",
929 old_span->label, new_span->label, reason);
930 new_span->match = NULL;
931 old_span->match = NULL;
933 changed = true;
934 if (unchangeable_section(new_span->ss))
935 err(newsbfd, "warning: ignoring change to nonpatchable "
936 "section %s\n", new_span->ss->name);
939 static void compare_matched_spans(struct superbfd *newsbfd)
941 asection *sect;
942 for (sect = newsbfd->abfd->sections; sect != NULL; sect = sect->next) {
943 struct supersect *ss = fetch_supersect(newsbfd, sect);
944 struct span *span;
945 for (span = ss->spans.data;
946 span < ss->spans.data + ss->spans.size; span++) {
947 if (span->match == NULL)
948 continue;
949 compare_spans(span->match, span);
954 static void handle_section_symbol_renames(struct superbfd *oldsbfd,
955 struct superbfd *newsbfd)
957 asection *sect;
958 struct span *span;
959 for (sect = newsbfd->abfd->sections; sect != NULL; sect = sect->next) {
960 struct supersect *ss = fetch_supersect(newsbfd, sect);
961 for (span = ss->spans.data;
962 span < ss->spans.data + ss->spans.size; span++) {
963 if (span->match == NULL)
964 continue;
965 if (strcmp(span->label, span->match->label) == 0)
966 continue;
967 if (strcmp(span->orig_label, span->label) != 0 &&
968 strcmp(span->label, span->match->label) != 0)
969 DIE;
970 if (span->symbol != NULL)
971 label_map_set(newsbfd, span->label,
972 span->match->label);
973 span->label = span->match->label;
978 static bool part_of_reloc(struct supersect *ss, unsigned long addr)
980 arelent **relocp;
981 for (relocp = ss->relocs.data;
982 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
983 arelent *reloc = *relocp;
984 if (addr >= reloc->address &&
985 addr < reloc->address + reloc->howto->size)
986 return true;
988 return false;
991 static bool nonrelocs_equal(struct span *old_span, struct span *new_span)
993 int i;
994 struct supersect *old_ss = old_span->ss, *new_ss = new_span->ss;
995 if (old_span->size != new_span->size)
996 return false;
997 const unsigned char *old = old_ss->contents.data + old_span->start;
998 const unsigned char *new = new_ss->contents.data + new_span->start;
999 for (i = 0; i < old_span->size; i++) {
1000 if (old[i] != new[i] &&
1001 !(part_of_reloc(old_ss, i + old_span->start) &&
1002 part_of_reloc(new_ss, i + new_span->start)))
1003 return false;
1005 return true;
1008 bool relocs_equal(struct supersect *old_src_ss, struct supersect *new_src_ss,
1009 arelent *old_reloc, arelent *new_reloc)
1011 struct superbfd *oldsbfd = old_src_ss->parent;
1012 struct superbfd *newsbfd = new_src_ss->parent;
1013 struct span *old_addr_span = find_span(old_src_ss, old_reloc->address);
1014 struct span *new_addr_span = find_span(new_src_ss, new_reloc->address);
1016 if (old_reloc->address - old_addr_span->start !=
1017 new_reloc->address - new_addr_span->start) {
1018 debug1(newsbfd, "Section %s/%s has reloc address mismatch at "
1019 "%lx\n", old_src_ss->name, new_src_ss->name,
1020 (unsigned long)old_reloc->address);
1021 return false;
1024 if (old_reloc->howto != new_reloc->howto) {
1025 debug1(newsbfd, "Section %s/%s has howto type mismatch at "
1026 "%lx\n", old_src_ss->name, new_src_ss->name,
1027 (unsigned long)old_reloc->address);
1028 return false;
1031 if (non_dst_mask(old_src_ss, old_reloc) !=
1032 non_dst_mask(new_src_ss, new_reloc)) {
1033 debug1(newsbfd, "Section %s/%s has contents mismatch at %lx\n",
1034 old_src_ss->name, new_src_ss->name,
1035 (unsigned long)old_reloc->address);
1036 return false;
1039 asymbol *old_sym = *old_reloc->sym_ptr_ptr;
1040 asymbol *new_sym = *new_reloc->sym_ptr_ptr;
1041 asection *old_sect = old_sym->section;
1042 asection *new_sect = new_sym->section;
1044 bfd_vma old_offset = get_reloc_offset(old_src_ss, old_reloc, true);
1045 bfd_vma new_offset = get_reloc_offset(new_src_ss, new_reloc, true);
1047 if (bfd_is_und_section(old_sect) || bfd_is_und_section(new_sect)) {
1048 if (!bfd_is_und_section(new_sect) && old_offset != 0 &&
1049 fetch_supersect(newsbfd, new_sect)->type == SS_TYPE_TEXT)
1050 return false;
1052 if (!bfd_is_und_section(new_sect) && new_offset != 0 &&
1053 fetch_supersect(oldsbfd, old_sect)->type == SS_TYPE_TEXT)
1054 return false;
1056 return strcmp(old_sym->name, new_sym->name) == 0 &&
1057 old_offset == new_offset;
1060 if (bfd_is_const_section(old_sect) || bfd_is_const_section(new_sect))
1061 DIE;
1063 struct supersect *old_ss = fetch_supersect(oldsbfd, old_sect);
1064 struct supersect *new_ss = fetch_supersect(newsbfd, new_sect);
1065 struct span *old_span = reloc_target_span(old_src_ss, old_reloc);
1066 struct span *new_span = reloc_target_span(new_src_ss, new_reloc);
1068 if (old_span->match != new_span || new_span->match != old_span) {
1069 debug1(newsbfd, "Nonmatching relocs from %s to %s/%s\n",
1070 new_src_ss->name, old_span->label, new_span->label);
1071 return false;
1074 if (old_sym->value + old_offset - old_span->start !=
1075 new_sym->value + new_offset - new_span->start) {
1076 debug1(newsbfd, "Offsets to %s/%s differ between %s "
1077 "and %s: %lx+%lx/%lx+%lx\n", old_ss->name,
1078 new_ss->name, old_src_ss->name, new_src_ss->name,
1079 (unsigned long)old_sym->value, (unsigned long)old_offset,
1080 (unsigned long)new_sym->value,
1081 (unsigned long)new_offset);
1082 return false;
1085 if ((old_sym->value + old_offset - old_span->start != 0 ||
1086 new_sym->value + new_offset - new_span->start != 0) &&
1087 new_span->patch) {
1088 debug1(newsbfd, "Relocation from %s to nonzero offsets "
1089 "%lx+%lx/%lx+%lx in changed section %s\n",
1090 new_src_ss->name, (unsigned long)old_sym->value,
1091 (unsigned long)old_offset, (unsigned long)new_sym->value,
1092 (unsigned long)new_offset, new_sym->section->name);
1093 return false;
1095 return true;
1098 bool all_relocs_equal(struct span *old_span, struct span *new_span)
1100 struct supersect *old_ss = old_span->ss, *new_ss = new_span->ss;
1101 arelent **old_relocp, **new_relocp;
1103 for (old_relocp = old_ss->relocs.data;
1104 old_relocp < old_ss->relocs.data + old_ss->relocs.size;
1105 old_relocp++) {
1106 if (find_span(old_ss, (*old_relocp)->address) == old_span)
1107 break;
1110 for (new_relocp = new_ss->relocs.data;
1111 new_relocp < new_ss->relocs.data + new_ss->relocs.size;
1112 new_relocp++) {
1113 if (find_span(new_ss, (*new_relocp)->address) == new_span)
1114 break;
1117 for (; old_relocp < old_ss->relocs.data + old_ss->relocs.size &&
1118 find_span(old_ss, (*old_relocp)->address) == old_span &&
1119 new_relocp < new_ss->relocs.data + new_ss->relocs.size &&
1120 find_span(new_ss, (*new_relocp)->address) == new_span;
1121 old_relocp++, new_relocp++) {
1122 if (!relocs_equal(old_ss, new_ss, *old_relocp, *new_relocp))
1123 return false;
1126 if ((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 debug1(new_ss->parent, "Different reloc count between %s and "
1131 "%s\n", old_span->label, new_span->label);
1132 return false;
1135 return true;
1138 bfd_vma non_dst_mask(struct supersect *ss, arelent *reloc)
1140 int bits = bfd_get_reloc_size(reloc->howto) * 8;
1141 void *address = ss->contents.data + reloc->address;
1142 bfd_vma x = bfd_get(bits, ss->parent->abfd, address);
1143 return x & ~reloc->howto->dst_mask;
1146 void rm_some_exports(struct superbfd *sbfd, const struct export_desc *ed)
1148 struct supersect *ss = ed->sym_ss;
1149 struct supersect *crc_ss = ed->crc_ss;
1150 if (crc_ss != NULL)
1151 assert(ss->contents.size * sizeof(unsigned long) ==
1152 crc_ss->contents.size * sizeof(struct kernel_symbol));
1154 struct kernel_symbol *ksym;
1155 unsigned long *crc = NULL;
1156 if (crc_ss != NULL)
1157 crc = crc_ss->contents.data;
1158 struct span *span, *crc_span;
1159 for (ksym = ss->contents.data;
1160 (void *)ksym < ss->contents.data + ss->contents.size;
1161 ksym++, crc++) {
1162 asymbol *sym;
1163 read_reloc(ss, &ksym->value, sizeof(ksym->value), &sym);
1164 span = new_span(ss, addr_offset(ss, ksym), sizeof(*ksym));
1165 if (str_in_set(sym->name, &ed->names))
1166 keep_span(span);
1168 if (crc_ss != NULL) {
1169 crc_span = new_span(crc_ss, addr_offset(crc_ss, crc),
1170 sizeof(*crc));
1171 if (span->keep)
1172 keep_span(crc_span);
1175 if (span->keep) {
1176 /* Replace name with a mangled name */
1177 write_string(ss, (const char **)&ksym->name,
1178 "DISABLED_%s_%s", sym->name, kid);
1183 void rm_relocs(struct superbfd *isbfd)
1185 asection *p;
1186 for (p = isbfd->abfd->sections; p != NULL; p = p->next) {
1187 struct supersect *ss = fetch_supersect(isbfd, p);
1188 bool remove_relocs = ss->keep;
1190 if (mode("keep") && ss->type == SS_TYPE_SPECIAL)
1191 remove_relocs = false;
1193 if (ss->type == SS_TYPE_KSPLICE)
1194 remove_relocs = false;
1195 if (mode("finalize") &&
1196 (starts_with(ss->name, ".ksplice_patches") ||
1197 starts_with(ss->name, ".ksplice_relocs")))
1198 remove_relocs = true;
1200 if (remove_relocs)
1201 rm_some_relocs(ss);
1205 void rm_some_relocs(struct supersect *ss)
1207 struct arelentp_vec orig_relocs;
1208 vec_move(&orig_relocs, &ss->relocs);
1210 arelent **relocp;
1211 for (relocp = orig_relocs.data;
1212 relocp < orig_relocs.data + orig_relocs.size; relocp++) {
1213 bool rm_reloc = false;
1214 asymbol *sym_ptr = *(*relocp)->sym_ptr_ptr;
1216 if (mode("rmsyms") && str_in_set(sym_ptr->name, &rmsyms) &&
1217 bfd_is_und_section(sym_ptr->section))
1218 rm_reloc = true;
1220 if (mode("keep"))
1221 rm_reloc = true;
1223 if (mode("keep-primary") &&
1224 (bfd_is_const_section(sym_ptr->section) ||
1225 reloc_target_span(ss, *relocp)->new ||
1226 !find_span(ss, (*relocp)->address)->keep))
1227 rm_reloc = false;
1229 if (mode("finalize") && bfd_is_und_section(sym_ptr->section))
1230 rm_reloc = true;
1232 if (strcmp(sym_ptr->name, "mcount") == 0 &&
1233 bfd_is_und_section(sym_ptr->section))
1234 rm_reloc = false;
1236 if (rm_reloc)
1237 write_ksplice_reloc(ss, *relocp);
1238 else
1239 *vec_grow(&ss->relocs, 1) = *relocp;
1243 struct supersect *make_section(struct superbfd *sbfd, const char *fmt, ...)
1245 va_list ap;
1246 char *name;
1247 va_start(ap, fmt);
1248 assert(vasprintf(&name, fmt, ap) >= 0);
1249 va_end(ap);
1251 asection *sect = bfd_get_section_by_name(sbfd->abfd, name);
1252 if (sect != NULL)
1253 return fetch_supersect(sbfd, sect);
1254 else
1255 return new_supersect(sbfd, name);
1258 arelent *create_reloc(struct supersect *ss, const void *addr, asymbol **symp,
1259 bfd_vma offset)
1261 bfd_reloc_code_real_type code;
1262 switch (bfd_arch_bits_per_address(ss->parent->abfd)) {
1263 case 32:
1264 code = BFD_RELOC_32;
1265 break;
1266 case 64:
1267 code = BFD_RELOC_64;
1268 break;
1269 default:
1270 DIE;
1273 arelent *reloc = malloc(sizeof(*reloc));
1274 reloc->sym_ptr_ptr = symp;
1275 reloc->address = addr_offset(ss, addr);
1276 reloc->howto = bfd_reloc_type_lookup(ss->parent->abfd, code);
1277 reloc->addend = offset;
1278 return reloc;
1281 void write_reloc(struct supersect *ss, const void *addr, asymbol **symp,
1282 bfd_vma offset)
1284 *vec_grow(&ss->new_relocs, 1) = create_reloc(ss, addr, symp, offset);
1287 void write_string(struct supersect *ss, const char **addr, const char *fmt, ...)
1289 va_list ap;
1290 struct supersect *str_ss = make_section(ss->parent, ".ksplice_str");
1291 char *str;
1292 va_start(ap, fmt);
1293 int len = vasprintf(&str, fmt, ap);
1294 assert(len >= 0);
1295 va_end(ap);
1297 unsigned long *str_offp = ulong_hash_lookup(&ksplice_string_offset, str,
1298 FALSE);
1299 if (str_offp == NULL) {
1300 char *buf = sect_grow(str_ss, len + 1, char);
1301 memcpy(buf, str, len + 1);
1302 str_offp = ulong_hash_lookup(&ksplice_string_offset, str, TRUE);
1303 *str_offp = addr_offset(str_ss, buf);
1306 write_reloc(ss, addr, &str_ss->symbol, *str_offp);
1309 void lookup_system_map(struct addr_vec *addrs, const char *name, long offset)
1311 struct addr_vec *map_addrs =
1312 addr_vec_hash_lookup(&system_map, name, FALSE);
1313 if (map_addrs == NULL)
1314 return;
1316 unsigned long *addr, *map_addr;
1317 for (map_addr = map_addrs->data;
1318 map_addr < map_addrs->data + map_addrs->size; map_addr++) {
1319 for (addr = addrs->data; addr < addrs->data + addrs->size;
1320 addr++) {
1321 if (*addr == *map_addr + offset)
1322 break;
1324 if (addr < addrs->data + addrs->size)
1325 continue;
1326 *vec_grow(addrs, 1) = *map_addr + offset;
1330 void compute_system_map_array(struct superbfd *sbfd, struct addr_vec *addrs,
1331 asymbol *sym)
1333 if (bfd_is_abs_section(sym->section)) {
1334 *vec_grow(addrs, 1) = sym->value;
1335 } else if (bfd_is_und_section(sym->section)) {
1336 lookup_system_map(addrs, sym->name, 0);
1337 } else if (!bfd_is_const_section(sym->section)) {
1338 asymbol **gsymp;
1339 for (gsymp = sbfd->syms.data;
1340 gsymp < sbfd->syms.data + sbfd->syms.size; gsymp++) {
1341 asymbol *gsym = *gsymp;
1342 if ((gsym->flags & BSF_DEBUGGING) == 0 &&
1343 gsym->section == sym->section)
1344 lookup_system_map(addrs, gsym->name,
1345 sym->value - gsym->value);
1350 void write_ksplice_system_map(struct superbfd *sbfd, asymbol *sym,
1351 const char *label)
1353 bool *done = bool_hash_lookup(&system_map_written, label, TRUE);
1354 if (*done)
1355 return;
1356 *done = true;
1358 struct addr_vec addrs;
1359 vec_init(&addrs);
1361 compute_system_map_array(sbfd, &addrs, sym);
1362 if (addrs.size != 0) {
1363 struct supersect *smap_ss =
1364 make_section(sbfd, ".ksplice_system_map");
1365 struct ksplice_system_map *smap =
1366 sect_grow(smap_ss, 1, struct ksplice_system_map);
1367 write_string(smap_ss, &smap->label, "%s", label);
1369 struct supersect *array_ss = make_section(sbfd,
1370 ".ksplice_array");
1371 void *buf = sect_grow(array_ss, addrs.size,
1372 typeof(*addrs.data));
1373 memcpy(buf, addrs.data, addrs.size * sizeof(*addrs.data));
1374 smap->nr_candidates = addrs.size;
1375 write_reloc(smap_ss, &smap->candidates, &array_ss->symbol,
1376 addr_offset(array_ss, buf));
1378 vec_free(&addrs);
1381 void write_ksplice_symbol_backend(struct supersect *ss,
1382 struct ksplice_symbol *const *addr,
1383 asymbol *sym, const char *label,
1384 const char *name)
1386 struct supersect *ksymbol_ss = make_section(ss->parent,
1387 ".ksplice_symbols");
1388 struct ksplice_symbol *ksymbol;
1389 unsigned long *ksymbol_offp;
1391 ksymbol_offp = ulong_hash_lookup(&ksplice_symbol_offset, label, FALSE);
1392 if (ksymbol_offp != NULL) {
1393 write_reloc(ss, addr, &ksymbol_ss->symbol, *ksymbol_offp);
1394 return;
1396 ksymbol = sect_grow(ksymbol_ss, 1, struct ksplice_symbol);
1397 ksymbol_offp = ulong_hash_lookup(&ksplice_symbol_offset, label, TRUE);
1398 *ksymbol_offp = addr_offset(ksymbol_ss, ksymbol);
1400 write_reloc(ss, addr, &ksymbol_ss->symbol, *ksymbol_offp);
1401 write_string(ksymbol_ss, &ksymbol->label, "%s", label);
1402 if (name != NULL) {
1403 write_string(ksymbol_ss, &ksymbol->name, "%s", name);
1404 write_ksplice_system_map(ksymbol_ss->parent, sym, label);
1408 void write_ksplice_symbol(struct supersect *ss,
1409 struct ksplice_symbol *const *addr,
1410 asymbol *sym, struct span *span,
1411 const char *addstr_sect)
1413 const char *label, *name;
1414 char *output;
1415 if (span != NULL && span->start != 0)
1416 label = span->label;
1417 else
1418 label = label_lookup(ss->parent, sym);
1420 assert(asprintf(&output, "%s%s", label, addstr_sect) >= 0);
1422 asymbol *gsym = canonical_symbol(ss->parent, sym);
1423 if (strcmp(addstr_sect, "") != 0)
1424 name = NULL;
1425 else if (bfd_is_und_section(sym->section))
1426 name = sym->name;
1427 else if (bfd_is_const_section(sym->section))
1428 name = NULL;
1429 else if (span != NULL && span->symbol == NULL)
1430 name = NULL;
1431 else if (gsym == NULL || (gsym->flags & BSF_SECTION_SYM) != 0)
1432 name = NULL;
1433 else
1434 name = gsym->name;
1436 write_ksplice_symbol_backend(ss, addr, sym, output, name);
1439 void write_ksplice_reloc(struct supersect *ss, arelent *orig_reloc)
1441 asymbol *sym_ptr = *orig_reloc->sym_ptr_ptr;
1442 reloc_howto_type *howto = orig_reloc->howto;
1443 bfd_vma addend = get_reloc_offset(ss, orig_reloc, false);
1444 unsigned long *repladdr = ss->contents.data + orig_reloc->address;
1446 if (mode("finalize") && starts_with(ss->name, ".ksplice_patches")) {
1447 *repladdr = 0;
1448 return;
1450 if (mode("finalize") && starts_with(ss->name, ".ksplice_relocs")) {
1451 assert(starts_with(sym_ptr->name, KSPLICE_SYMBOL_STR));
1452 asymbol fake_sym;
1453 fake_sym.name = sym_ptr->name + strlen(KSPLICE_SYMBOL_STR);
1454 fake_sym.section = bfd_und_section_ptr;
1455 fake_sym.value = 0;
1456 fake_sym.flags = 0;
1458 write_ksplice_symbol_backend
1459 (ss, (struct ksplice_symbol **)repladdr, &fake_sym,
1460 fake_sym.name, fake_sym.name);
1461 return;
1464 struct span *span = reloc_target_span(ss, orig_reloc);
1465 if (span == ss->spans.data && span->start != addend)
1466 span = NULL;
1467 blot_section(ss, orig_reloc->address, howto);
1469 struct supersect *kreloc_ss;
1470 if (mode("rmsyms"))
1471 kreloc_ss = make_section(ss->parent, ".ksplice_init_relocs");
1472 else
1473 kreloc_ss = make_section(ss->parent, ".ksplice_relocs%s",
1474 ss->name);
1475 struct ksplice_reloc *kreloc = sect_grow(kreloc_ss, 1,
1476 struct ksplice_reloc);
1478 struct span *address_span = find_span(ss, orig_reloc->address);
1479 write_reloc(kreloc_ss, &kreloc->blank_addr,
1480 &ss->symbol, orig_reloc->address + address_span->shift);
1481 if (bfd_is_und_section(sym_ptr->section) && mode("keep")) {
1482 char *name;
1483 assert(asprintf(&name, KSPLICE_SYMBOL_STR "%s", sym_ptr->name)
1484 >= 0);
1485 asymbol **symp = make_undefined_symbolp(ss->parent, name);
1486 write_reloc(kreloc_ss, &kreloc->symbol, symp, 0);
1487 } else {
1488 write_ksplice_symbol(kreloc_ss, &kreloc->symbol, sym_ptr, span,
1489 "");
1491 kreloc->pcrel = howto->pc_relative;
1492 if (span != NULL && span->start != 0)
1493 addend += sym_ptr->value - span->start;
1494 kreloc->addend = addend;
1495 kreloc->size = bfd_get_reloc_size(howto);
1496 kreloc->dst_mask = howto->dst_mask;
1497 kreloc->rightshift = howto->rightshift;
1498 kreloc->signed_addend =
1499 (howto->complain_on_overflow == complain_overflow_signed) ||
1500 (howto->complain_on_overflow == complain_overflow_bitfield);
1503 #define CANARY(x, canary) ((x & ~howto->dst_mask) | (canary & howto->dst_mask))
1505 void blot_section(struct supersect *ss, int offset, reloc_howto_type *howto)
1507 int bits = bfd_get_reloc_size(howto) * 8;
1508 void *address = ss->contents.data + offset;
1509 bfd_vma x = bfd_get(bits, ss->parent->abfd, address);
1510 x = (x & ~howto->dst_mask) |
1511 ((bfd_vma)KSPLICE_CANARY & howto->dst_mask);
1512 bfd_put(bits, ss->parent->abfd, x, address);
1515 static void write_ksplice_section(struct span *span)
1517 struct supersect *ss = span->ss;
1518 struct supersect *ksect_ss =
1519 make_section(ss->parent, ".ksplice_sections%s", span->ss->name);
1520 struct ksplice_section *ksect = sect_grow(ksect_ss, 1,
1521 struct ksplice_section);
1522 asymbol *sym = span->symbol == NULL ? ss->symbol : span->symbol;
1524 write_ksplice_symbol(ksect_ss, &ksect->symbol, sym, span,
1525 mode("keep-primary") ? "(post)" : "");
1526 ksect->size = span->size;
1527 ksect->flags = 0;
1529 if (ss->type == SS_TYPE_RODATA || ss->type == SS_TYPE_STRING)
1530 ksect->flags |= KSPLICE_SECTION_RODATA;
1531 if (ss->type == SS_TYPE_DATA)
1532 ksect->flags |= KSPLICE_SECTION_DATA;
1533 if (ss->type == SS_TYPE_TEXT)
1534 ksect->flags |= KSPLICE_SECTION_TEXT;
1535 assert(ksect->flags != 0);
1536 write_reloc(ksect_ss, &ksect->address, &ss->symbol,
1537 span->start + span->shift);
1540 void write_ksplice_patch(struct superbfd *sbfd, struct span *span)
1542 struct supersect *kpatch_ss =
1543 make_section(sbfd, ".ksplice_patches%s", span->ss->name);
1544 struct ksplice_patch *kpatch = sect_grow(kpatch_ss, 1,
1545 struct ksplice_patch);
1547 write_ksplice_symbol_backend(kpatch_ss, &kpatch->symbol, NULL,
1548 span->label, NULL);
1549 write_reloc(kpatch_ss, &kpatch->repladdr, &span->ss->symbol,
1550 span->start + span->shift);
1553 asymbol **make_undefined_symbolp(struct superbfd *sbfd, const char *name)
1555 asymbol **symp;
1556 for (symp = sbfd->syms.data; symp < sbfd->syms.data + sbfd->syms.size;
1557 symp++) {
1558 asymbol *sym = *symp;
1559 if (strcmp(name, sym->name) == 0 &&
1560 bfd_is_und_section(sym->section))
1561 return symp;
1563 asymbol ***sympp;
1564 for (sympp = sbfd->new_syms.data;
1565 sympp < sbfd->new_syms.data + sbfd->new_syms.size; sympp++) {
1566 asymbol **symp = *sympp;
1567 asymbol *sym = *symp;
1568 if (strcmp(name, sym->name) == 0 &&
1569 bfd_is_und_section(sym->section))
1570 return symp;
1573 symp = malloc(sizeof(*symp));
1574 *symp = bfd_make_empty_symbol(sbfd->abfd);
1575 asymbol *sym = *symp;
1576 sym->name = name;
1577 sym->section = bfd_und_section_ptr;
1578 sym->flags = 0;
1579 sym->value = 0;
1580 *vec_grow(&sbfd->new_syms, 1) = symp;
1581 return symp;
1584 void write_ksplice_deleted_patch(struct superbfd *sbfd, const char *name,
1585 const char *label, const char *sectname)
1587 struct supersect *kpatch_ss =
1588 make_section(sbfd, ".ksplice_patches%s", sectname);
1589 struct ksplice_patch *kpatch = sect_grow(kpatch_ss, 1,
1590 struct ksplice_patch);
1592 write_ksplice_symbol_backend(kpatch_ss, &kpatch->symbol, NULL,
1593 label, NULL);
1595 asymbol **symp = make_undefined_symbolp(sbfd, strdup(name));
1596 write_reloc(kpatch_ss, &kpatch->repladdr, symp, 0);
1599 void write_ksplice_export(struct superbfd *sbfd, const char *symname,
1600 const char *export_type, bool del)
1602 struct supersect *export_ss = make_section(sbfd, ".ksplice_exports");
1603 struct ksplice_export *exp = sect_grow(export_ss, 1,
1604 struct ksplice_export);
1606 if (del) {
1607 write_string(export_ss, &exp->name, "%s", symname);
1608 write_string(export_ss, &exp->new_name, "DISABLED_%s_%s",
1609 symname, kid);
1610 } else {
1611 write_string(export_ss, &exp->new_name, "%s", symname);
1612 write_string(export_ss, &exp->name, "DISABLED_%s_%s", symname,
1613 kid);
1617 void filter_table_sections(struct superbfd *isbfd)
1619 struct supersect *tables_ss =
1620 fetch_supersect(offsets_sbfd,
1621 bfd_get_section_by_name(offsets_sbfd->abfd,
1622 ".ksplice_table_sections"));
1623 const struct table_section *ts;
1624 for (ts = tables_ss->contents.data;
1625 (void *)ts < tables_ss->contents.data + tables_ss->contents.size;
1626 ts++) {
1627 struct table_section s = *ts;
1628 s.sect = read_string(tables_ss, &ts->sect);
1629 s.other_sect = read_string(tables_ss, &ts->other_sect);
1630 if (s.has_addr)
1631 filter_table_section(isbfd, &s);
1635 void filter_table_section(struct superbfd *sbfd, const struct table_section *s)
1637 asection *isection = bfd_get_section_by_name(sbfd->abfd, s->sect);
1638 if (isection == NULL)
1639 return;
1640 struct supersect *ss = fetch_supersect(sbfd, isection);
1642 void *entry;
1643 for (entry = ss->contents.data;
1644 entry < ss->contents.data + ss->contents.size;
1645 entry += s->entry_size) {
1646 asymbol *sym;
1647 struct span *span = find_span(ss, addr_offset(ss, entry));
1648 assert(span != NULL);
1650 read_reloc(ss, entry + s->addr_offset, sizeof(void *), &sym);
1651 struct supersect *sym_ss = fetch_supersect(sbfd, sym->section);
1652 if (sym_ss->keep)
1653 keep_span(span);
1655 if (s->other_sect != NULL) {
1656 arelent *reloc =
1657 find_reloc(ss, entry + s->other_offset);
1658 assert(reloc != NULL);
1659 struct span *sym_span = reloc_target_span(ss, reloc);
1660 if (span->keep)
1661 keep_span(sym_span);
1665 arelent **relocp;
1666 for (relocp = ss->relocs.data;
1667 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
1668 struct span *addr_span = find_span(ss, (*relocp)->address);
1669 struct span *target_span = reloc_target_span(ss, *relocp);
1670 if (addr_span->keep && mode("keep-primary"))
1671 keep_span(target_span);
1675 void keep_referenced_sections(struct superbfd *sbfd)
1677 asection *sect;
1678 struct supersect *ss, *sym_ss;
1679 struct span *address_span, *target_span;
1680 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
1681 ss = fetch_supersect(sbfd, sect);
1682 arelent **relocp;
1683 if (ss->type == SS_TYPE_SPECIAL || ss->type == SS_TYPE_EXPORT)
1684 continue;
1685 for (relocp = ss->relocs.data;
1686 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
1687 asymbol *sym = *(*relocp)->sym_ptr_ptr;
1688 address_span = find_span(ss, (*relocp)->address);
1689 if (!address_span->keep)
1690 continue;
1691 target_span = reloc_target_span(ss, *relocp);
1692 if (target_span == NULL || target_span->keep)
1693 continue;
1694 sym_ss = fetch_supersect(sbfd, sym->section);
1695 if (sym_ss->type == SS_TYPE_IGNORED)
1696 continue;
1697 keep_span(target_span);
1698 changed = true;
1703 void copy_symbols(struct asymbolp_vec *osyms, struct asymbolpp_vec *isyms)
1705 asymbol ***sympp;
1706 for (sympp = isyms->data; sympp < isyms->data + isyms->size; sympp++)
1707 *vec_grow(osyms, 1) = **sympp;
1710 /* Modified function from GNU Binutils objcopy.c */
1711 bfd_boolean copy_object(bfd *ibfd, bfd *obfd)
1713 assert(bfd_set_format(obfd, bfd_get_format(ibfd)));
1715 bfd_vma start = bfd_get_start_address(ibfd);
1717 flagword flags = bfd_get_file_flags(ibfd);
1718 flags &= bfd_applicable_file_flags(obfd);
1720 assert(bfd_set_start_address(obfd, start)
1721 && bfd_set_file_flags(obfd, flags));
1723 enum bfd_architecture iarch = bfd_get_arch(ibfd);
1724 unsigned int imach = bfd_get_mach(ibfd);
1725 assert(bfd_set_arch_mach(obfd, iarch, imach));
1726 assert(bfd_set_format(obfd, bfd_get_format(ibfd)));
1728 /* BFD mandates that all output sections be created and sizes set before
1729 any output is done. Thus, we traverse all sections multiple times. */
1730 bfd_map_over_sections(ibfd, setup_section, obfd);
1732 struct supersect *new_supersects = fetch_superbfd(ibfd)->new_supersects;
1733 struct supersect *ss;
1734 for (ss = new_supersects; ss != NULL; ss = ss->next)
1735 setup_new_section(obfd, ss);
1737 /* Mark symbols used in output relocations so that they
1738 are kept, even if they are local labels or static symbols.
1740 Note we iterate over the input sections examining their
1741 relocations since the relocations for the output sections
1742 haven't been set yet. mark_symbols_used_in_relocations will
1743 ignore input sections which have no corresponding output
1744 section. */
1746 bfd_map_over_sections(ibfd, mark_symbols_used_in_relocations, NULL);
1747 for (ss = new_supersects; ss != NULL; ss = ss->next)
1748 ss_mark_symbols_used_in_relocations(ss);
1749 struct asymbolp_vec osyms;
1750 vec_init(&osyms);
1751 filter_symbols(ibfd, obfd, &osyms, &fetch_superbfd(ibfd)->syms);
1752 copy_symbols(&osyms, &fetch_superbfd(ibfd)->new_syms);
1754 bfd_set_symtab(obfd, osyms.data, osyms.size);
1756 /* This has to happen after the symbol table has been set. */
1757 bfd_map_over_sections(obfd, write_section, NULL);
1759 /* Allow the BFD backend to copy any private data it understands
1760 from the input BFD to the output BFD. This is done last to
1761 permit the routine to look at the filtered symbol table, which is
1762 important for the ECOFF code at least. */
1763 assert(bfd_copy_private_bfd_data(ibfd, obfd));
1765 return TRUE;
1768 /* Modified function from GNU Binutils objcopy.c */
1769 void setup_section(bfd *ibfd, asection *isection, void *obfdarg)
1771 struct superbfd *isbfd = fetch_superbfd(ibfd);
1772 struct supersect *ss = fetch_supersect(isbfd, isection);
1773 bfd *obfd = obfdarg;
1774 bfd_vma vma;
1776 if (!ss->keep)
1777 return;
1779 asection *osection = bfd_make_section_anyway(obfd, ss->name);
1780 assert(osection != NULL);
1782 osection->userdata = ss;
1783 bfd_set_section_flags(obfd, osection, ss->flags);
1784 ss->symbol = osection->symbol;
1785 assert(bfd_set_section_size(obfd, osection, ss->contents.size));
1787 vma = bfd_section_vma(ibfd, isection);
1788 assert(bfd_set_section_vma(obfd, osection, vma));
1790 osection->lma = isection->lma;
1791 assert(bfd_set_section_alignment(obfd, osection, ss->alignment));
1792 osection->entsize = isection->entsize;
1793 osection->output_section = osection;
1794 osection->output_offset = 0;
1795 isection->output_section = osection;
1796 isection->output_offset = 0;
1797 return;
1800 void setup_new_section(bfd *obfd, struct supersect *ss)
1802 asection *osection = bfd_make_section_anyway(obfd, ss->name);
1803 assert(osection != NULL);
1804 bfd_set_section_flags(obfd, osection, ss->flags);
1806 osection->userdata = ss;
1807 ss->symbol = osection->symbol;
1808 assert(bfd_set_section_size(obfd, osection, ss->contents.size));
1809 assert(bfd_set_section_vma(obfd, osection, 0));
1811 osection->lma = 0;
1812 assert(bfd_set_section_alignment(obfd, osection, ss->alignment));
1813 osection->entsize = 0;
1814 osection->output_section = osection;
1815 osection->output_offset = 0;
1818 static int compare_reloc_addresses(const void *aptr, const void *bptr)
1820 const arelent *const *a = aptr, *const *b = bptr;
1821 return (*a)->address - (*b)->address;
1824 static void delete_obsolete_relocs(struct supersect *ss)
1826 if (ss->new_relocs.size == 0)
1827 return;
1829 qsort(ss->relocs.data, ss->relocs.size, sizeof(*ss->relocs.data),
1830 compare_reloc_addresses);
1831 qsort(ss->new_relocs.data, ss->new_relocs.size,
1832 sizeof(*ss->new_relocs.data), compare_reloc_addresses);
1834 struct arelentp_vec orig_relocs;
1835 vec_move(&orig_relocs, &ss->relocs);
1837 arelent **relocp, **new_relocp = ss->new_relocs.data;
1838 for (relocp = orig_relocs.data;
1839 relocp < orig_relocs.data + orig_relocs.size; relocp++) {
1840 while (new_relocp < ss->new_relocs.data + ss->new_relocs.size &&
1841 (*new_relocp)->address < (*relocp)->address)
1842 new_relocp++;
1843 arelent *reloc = *relocp, *new_reloc = *new_relocp;
1844 if (new_relocp == ss->new_relocs.data + ss->new_relocs.size ||
1845 reloc->address != new_reloc->address)
1846 *vec_grow(&ss->relocs, 1) = reloc;
1850 void write_section(bfd *obfd, asection *osection, void *arg)
1852 struct supersect *ss = osection->userdata;
1854 if ((ss->flags & SEC_GROUP) != 0 || ss->contents.size == 0)
1855 return;
1857 delete_obsolete_relocs(ss);
1859 arelent **relocp;
1860 char *error_message;
1861 for (relocp = ss->new_relocs.data;
1862 relocp < ss->new_relocs.data + ss->new_relocs.size; relocp++) {
1863 bfd_vma val;
1864 if (bfd_get_arch(obfd) == bfd_arch_arm)
1865 val = osection->use_rela_p ? 0 : (*relocp)->addend;
1866 else
1867 val = 0;
1868 bfd_put(bfd_get_reloc_size((*relocp)->howto) * 8, obfd, val,
1869 ss->contents.data + (*relocp)->address);
1870 if (bfd_install_relocation(obfd, *relocp, ss->contents.data,
1871 0, osection, &error_message) !=
1872 bfd_reloc_ok) {
1873 err(ss->parent, "ksplice: error installing reloc: %s",
1874 error_message);
1875 DIE;
1878 memcpy(vec_grow(&ss->relocs, ss->new_relocs.size), ss->new_relocs.data,
1879 ss->new_relocs.size * sizeof(*ss->new_relocs.data));
1881 bfd_set_reloc(obfd, osection,
1882 ss->relocs.size == 0 ? NULL : ss->relocs.data,
1883 ss->relocs.size);
1885 if (ss->flags & SEC_HAS_CONTENTS)
1886 assert(bfd_set_section_contents
1887 (obfd, osection, ss->contents.data, 0,
1888 ss->contents.size));
1891 /* Modified function from GNU Binutils objcopy.c
1893 * Mark all the symbols which will be used in output relocations with
1894 * the BSF_KEEP flag so that those symbols will not be stripped.
1896 * Ignore relocations which will not appear in the output file.
1898 void mark_symbols_used_in_relocations(bfd *abfd, asection *isection,
1899 void *ignored)
1901 struct superbfd *sbfd = fetch_superbfd(abfd);
1902 if (isection->output_section == NULL)
1903 return;
1905 struct supersect *ss = fetch_supersect(sbfd, isection);
1906 ss_mark_symbols_used_in_relocations(ss);
1909 void ss_mark_symbols_used_in_relocations(struct supersect *ss)
1911 /* Examine each symbol used in a relocation. If it's not one of the
1912 special bfd section symbols, then mark it with BSF_KEEP. */
1913 arelent **relocp;
1914 for (relocp = ss->relocs.data;
1915 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
1916 asymbol *sym = *(*relocp)->sym_ptr_ptr;
1917 if (!(bfd_is_const_section(sym->section) &&
1918 sym == sym->section->symbol))
1919 sym->flags |= BSF_KEEP;
1921 for (relocp = ss->new_relocs.data;
1922 relocp < ss->new_relocs.data + ss->new_relocs.size; relocp++) {
1923 asymbol *sym = *(*relocp)->sym_ptr_ptr;
1924 if (!(bfd_is_const_section(sym->section) &&
1925 sym == sym->section->symbol))
1926 sym->flags |= BSF_KEEP;
1930 static bool deleted_table_section_symbol(bfd *abfd, asymbol *sym)
1932 struct superbfd *sbfd = fetch_superbfd(abfd);
1933 if (bfd_is_const_section(sym->section))
1934 return false;
1935 struct supersect *ss = fetch_supersect(sbfd, sym->section);
1937 asymbol **symp;
1938 for (symp = ss->syms.data; symp < ss->syms.data + ss->syms.size; symp++) {
1939 if (sym == *symp)
1940 break;
1942 return symp >= ss->syms.data + ss->syms.size &&
1943 (sym->flags & BSF_SECTION_SYM) == 0;
1946 /* Modified function from GNU Binutils objcopy.c
1948 * Choose which symbol entries to copy.
1949 * We don't copy in place, because that confuses the relocs.
1950 * Return the number of symbols to print.
1952 void filter_symbols(bfd *ibfd, bfd *obfd, struct asymbolp_vec *osyms,
1953 struct asymbolp_vec *isyms)
1955 asymbol **symp;
1956 struct superbfd *sbfd = fetch_superbfd(ibfd);
1957 for (symp = isyms->data; symp < isyms->data + isyms->size; symp++) {
1958 asymbol *sym = *symp;
1959 struct supersect *sym_ss = NULL;
1960 struct span *sym_span = NULL;
1961 if (!bfd_is_const_section(sym->section)) {
1962 sym_ss = fetch_supersect(sbfd, sym->section);
1963 sym_span = find_span(sym_ss, sym->value);
1966 bool keep = false;
1968 if (mode("keep") && (sym->flags & BSF_GLOBAL) != 0 &&
1969 !(mode("keep-primary") && sym_span != NULL &&
1970 sym_span->new))
1971 sym->flags = (sym->flags & ~BSF_GLOBAL) | BSF_LOCAL;
1973 if (mode("finalize") && (sym->flags & BSF_GLOBAL) != 0)
1974 sym->flags = (sym->flags & ~BSF_GLOBAL) | BSF_LOCAL;
1976 if ((sym->flags & BSF_KEEP) != 0 /* Used in relocation. */
1977 || ((sym->flags & BSF_SECTION_SYM) != 0 && sym_ss != NULL &&
1978 sym_ss->keep))
1979 keep = true;
1980 else if ((sym->flags & (BSF_GLOBAL | BSF_WEAK)) != 0 &&
1981 sym_ss != NULL && sym_ss->keep)
1982 keep = true;
1984 if (deleted_table_section_symbol(ibfd, sym))
1985 keep = false;
1987 if (bfd_is_com_section(sym->section))
1988 keep = false;
1990 if (mode("rmsyms"))
1991 keep = !str_in_set(sym->name, &rmsyms);
1993 if (keep) {
1994 if (sym_ss != NULL && !sym_ss->keep) {
1995 err(sbfd, "Kept symbol %s in unkept section "
1996 "%s\n", sym->name, sym->section->name);
1997 DIE;
1999 *vec_grow(osyms, 1) = sym;
2004 void read_str_set(struct str_vec *strs)
2006 char *buf = NULL;
2007 size_t n = 0;
2008 assert(getline(&buf, &n, stdin) >= 0);
2009 vec_init(strs);
2010 char *saveptr;
2011 while (1) {
2012 char *str = strtok_r(buf, " \n", &saveptr);
2013 buf = NULL;
2014 if (str == NULL)
2015 break;
2016 *vec_grow(strs, 1) = str;
2020 bool str_in_set(const char *str, const struct str_vec *strs)
2022 const char **strp;
2023 for (strp = strs->data; strp < strs->data + strs->size; strp++) {
2024 if (strcmp(str, *strp) == 0)
2025 return true;
2027 return false;
2030 bool is_table_section(const char *name, bool consider_other)
2032 struct supersect *tables_ss =
2033 fetch_supersect(offsets_sbfd,
2034 bfd_get_section_by_name(offsets_sbfd->abfd,
2035 ".ksplice_table_sections"));
2036 const struct table_section *ts;
2037 for (ts = tables_ss->contents.data;
2038 (void *)ts < tables_ss->contents.data + tables_ss->contents.size;
2039 ts++) {
2040 if (strcmp(name, read_string(tables_ss, &ts->sect)) == 0)
2041 return true;
2042 const char *osect_name = read_string(tables_ss,
2043 &ts->other_sect);
2044 if (consider_other && osect_name != NULL &&
2045 strcmp(name, osect_name) == 0)
2046 return true;
2048 return false;
2051 enum supersect_type supersect_type(struct supersect *ss)
2053 if (mode("finalize") &&
2054 strcmp(finalize_target, "vmlinux") == 0 &&
2055 (starts_with(ss->name, ".ksplice_relocs.exit") ||
2056 starts_with(ss->name, ".ksplice_sections.exit") ||
2057 starts_with(ss->name, ".ksplice_patches.exit")))
2058 return SS_TYPE_EXIT;
2059 if (starts_with(ss->name, ".ksplice"))
2060 return SS_TYPE_KSPLICE;
2062 if (starts_with(ss->name, ".init"))
2063 return SS_TYPE_IGNORED;
2064 if (starts_with(ss->name, ".security_initcall.init"))
2065 return SS_TYPE_IGNORED;
2066 if (starts_with(ss->name, ".con_initcall.init"))
2067 return SS_TYPE_IGNORED;
2068 if (starts_with(ss->name, ".x86cpuvendor.init"))
2069 return SS_TYPE_IGNORED;
2070 if (starts_with(ss->name, ".early_param.init"))
2071 return SS_TYPE_IGNORED;
2072 if (starts_with(ss->name, ".taglist.init"))
2073 return SS_TYPE_IGNORED;
2074 if (starts_with(ss->name, ".arch.info.init"))
2075 return SS_TYPE_IGNORED;
2076 if (starts_with(ss->name, ".proc.info.init"))
2077 return SS_TYPE_IGNORED;
2078 /* .pci_fixup_* sections really should be treated as global rodata
2079 referenced only from quirks.c */
2080 if (starts_with(ss->name, ".pci_fixup_"))
2081 return SS_TYPE_IGNORED;
2082 /* .builtin_fw sections are similar to .pci_fixup */
2083 if (starts_with(ss->name, ".builtin_fw"))
2084 return SS_TYPE_IGNORED;
2085 /* same for .tracedata */
2086 if (starts_with(ss->name, ".tracedata"))
2087 return SS_TYPE_IGNORED;
2088 if (starts_with(ss->name, ".debug"))
2089 return SS_TYPE_IGNORED;
2090 /* .eh_frame should probably be discarded, not ignored */
2091 if (starts_with(ss->name, ".eh_frame"))
2092 return SS_TYPE_IGNORED;
2093 if (config->ignore_devinit && starts_with(ss->name, ".devinit"))
2094 return SS_TYPE_IGNORED;
2095 if (config->ignore_meminit && starts_with(ss->name, ".meminit"))
2096 return SS_TYPE_IGNORED;
2097 if (config->ignore_cpuinit && starts_with(ss->name, ".cpuinit"))
2098 return SS_TYPE_IGNORED;
2099 if (config->ignore_devinit && starts_with(ss->name, ".devexit"))
2100 return SS_TYPE_IGNORED;
2101 if (config->ignore_meminit && starts_with(ss->name, ".memexit"))
2102 return SS_TYPE_IGNORED;
2103 if (config->ignore_cpuinit && starts_with(ss->name, ".cpuexit"))
2104 return SS_TYPE_IGNORED;
2105 if (starts_with(ss->name, ".vgetcpu_mode") ||
2106 starts_with(ss->name, ".jiffies") ||
2107 starts_with(ss->name, ".wall_jiffies") ||
2108 starts_with(ss->name, ".vxtime") ||
2109 starts_with(ss->name, ".sys_tz") ||
2110 starts_with(ss->name, ".sysctl_vsyscall") ||
2111 starts_with(ss->name, ".xtime") ||
2112 starts_with(ss->name, ".xtime_lock") ||
2113 starts_with(ss->name, ".vsyscall"))
2114 return SS_TYPE_IGNORED;
2115 if (starts_with(ss->name, ".vdso"))
2116 return SS_TYPE_IGNORED;
2118 if (starts_with(ss->name, ".exit.text"))
2119 return SS_TYPE_TEXT;
2120 if (starts_with(ss->name, ".exit.data"))
2121 return SS_TYPE_DATA;
2123 if (starts_with(ss->name, ".text") ||
2124 starts_with(ss->name, ".kernel.text") ||
2125 starts_with(ss->name, ".devinit.text") ||
2126 starts_with(ss->name, ".meminit.text") ||
2127 starts_with(ss->name, ".cpuinit.text") ||
2128 starts_with(ss->name, ".devexit.text") ||
2129 starts_with(ss->name, ".memexit.text") ||
2130 starts_with(ss->name, ".cpuexit.text") ||
2131 starts_with(ss->name, ".ref.text") ||
2132 starts_with(ss->name, ".spinlock.text") ||
2133 starts_with(ss->name, ".kprobes.text") ||
2134 starts_with(ss->name, ".sched.text"))
2135 return SS_TYPE_TEXT;
2137 int n = -1;
2138 if (sscanf(ss->name, ".rodata.str%*u.%*u%n", &n) >= 0 &&
2139 n == strlen(ss->name))
2140 return SS_TYPE_STRING;
2142 if (starts_with(ss->name, ".rodata") ||
2143 starts_with(ss->name, ".kernel.rodata") ||
2144 starts_with(ss->name, ".devinit.rodata") ||
2145 starts_with(ss->name, ".meminit.rodata") ||
2146 starts_with(ss->name, ".cpuinit.rodata") ||
2147 starts_with(ss->name, ".devexit.rodata") ||
2148 starts_with(ss->name, ".memexit.rodata") ||
2149 starts_with(ss->name, ".cpuexit.rodata") ||
2150 starts_with(ss->name, ".ref.rodata") ||
2151 starts_with(ss->name, "__markers_strings"))
2152 return SS_TYPE_RODATA;
2154 if (starts_with(ss->name, ".bss"))
2155 return SS_TYPE_DATA;
2157 /* Ignore .data.percpu sections */
2158 if (starts_with(ss->name, ".data.percpu") ||
2159 starts_with(ss->name, ".kernel.data.percpu"))
2160 return SS_TYPE_IGNORED;
2161 if (starts_with(ss->name, ".data") ||
2162 starts_with(ss->name, ".kernel.data") ||
2163 starts_with(ss->name, ".devinit.data") ||
2164 starts_with(ss->name, ".cpuinit.data") ||
2165 starts_with(ss->name, ".meminit.data") ||
2166 starts_with(ss->name, ".devexit.data") ||
2167 starts_with(ss->name, ".memexit.data") ||
2168 starts_with(ss->name, ".cpuexit.data") ||
2169 starts_with(ss->name, ".ref.data") ||
2170 starts_with(ss->name, "__markers"))
2171 return SS_TYPE_DATA;
2173 /* We replace all the ksymtab strings, so delete them */
2174 if (strcmp(ss->name, "__ksymtab_strings") == 0)
2175 return SS_TYPE_IGNORED;
2176 if (starts_with(ss->name, "__ksymtab"))
2177 return SS_TYPE_EXPORT;
2178 if (starts_with(ss->name, "__kcrctab"))
2179 return SS_TYPE_EXPORT;
2181 if (is_table_section(ss->name, true))
2182 return SS_TYPE_SPECIAL;
2184 if (starts_with(ss->name, ".ARM."))
2185 return SS_TYPE_SPECIAL;
2187 if (starts_with(ss->name, ".note"))
2188 return SS_TYPE_IGNORED;
2189 if (starts_with(ss->name, ".comment"))
2190 return SS_TYPE_IGNORED;
2191 if (starts_with(ss->name, "__param"))
2192 return SS_TYPE_IGNORED;
2193 if (starts_with(ss->name, ".exitcall.exit"))
2194 return SS_TYPE_IGNORED;
2195 if (starts_with(ss->name, ".modinfo"))
2196 return SS_TYPE_IGNORED;
2198 return SS_TYPE_UNKNOWN;
2201 void initialize_supersect_types(struct superbfd *sbfd)
2203 asection *sect;
2204 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2205 struct supersect *ss = fetch_supersect(sbfd, sect);
2206 ss->type = supersect_type(ss);
2207 if (ss->type == SS_TYPE_UNKNOWN) {
2208 err(sbfd, "Unknown section type: %s\n", ss->name);
2209 DIE;
2214 static void init_label_map(struct superbfd *sbfd)
2216 struct label_map *map;
2218 vec_init(&sbfd->maps);
2219 init_csyms(sbfd);
2220 init_callers(sbfd);
2222 struct symbol_hash csyms;
2223 symbol_hash_init(&csyms);
2225 asymbol **symp;
2226 for (symp = sbfd->syms.data;
2227 symp < sbfd->syms.data + sbfd->syms.size; symp++) {
2228 asymbol *csym = canonical_symbol(sbfd, *symp);
2229 if (csym == NULL)
2230 continue;
2231 char *key;
2232 assert(asprintf(&key, "%p", csym) >= 0);
2233 asymbol **csymp = symbol_hash_lookup(&csyms, key, TRUE);
2234 free(key);
2235 if (*csymp != NULL)
2236 continue;
2237 *csymp = csym;
2239 map = vec_grow(&sbfd->maps, 1);
2240 map->csym = csym;
2241 map->count = 0;
2242 map->label = symbol_label(sbfd, csym);
2245 struct label_mapp_hash label_maps;
2246 label_mapp_hash_init(&label_maps);
2247 for (map = sbfd->maps.data;
2248 map < sbfd->maps.data + sbfd->maps.size; map++) {
2249 struct label_map **mapp =
2250 label_mapp_hash_lookup(&label_maps, map->label, TRUE);
2251 if (*mapp == NULL) {
2252 *mapp = map;
2253 continue;
2256 struct label_map *first_map = *mapp;
2257 char *buf;
2258 if (first_map->count == 0) {
2259 assert(asprintf(&buf, "%s~%d", map->label, 0) >= 0);
2260 first_map->label = buf;
2262 first_map->count++;
2263 assert(asprintf(&buf, "%s~%d", map->label, first_map->count)
2264 >= 0);
2265 map->label = buf;
2268 label_mapp_hash_init(&sbfd->maps_hash);
2269 for (map = sbfd->maps.data;
2270 map < sbfd->maps.data + sbfd->maps.size; map++) {
2271 char *key;
2272 assert(asprintf(&key, "%p", map->csym) >= 0);
2273 struct label_map **mapp =
2274 label_mapp_hash_lookup(&sbfd->maps_hash, key, TRUE);
2275 free(key);
2276 *mapp = map;
2277 map->orig_label = map->label;
2281 static const char *label_lookup(struct superbfd *sbfd, asymbol *sym)
2283 asymbol *csym = canonical_symbol(sbfd, sym);
2284 char *key;
2285 assert(asprintf(&key, "%p", csym) >= 0);
2286 struct label_map **mapp =
2287 label_mapp_hash_lookup(&sbfd->maps_hash, key, FALSE);
2288 free(key);
2289 if (mapp == NULL)
2290 DIE;
2291 return (*mapp)->label;
2294 static void print_label_changes(struct superbfd *sbfd)
2296 asection *sect;
2297 struct span *span;
2298 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2299 struct supersect *ss = fetch_supersect(sbfd, sect);
2300 for (span = ss->spans.data;
2301 span < ss->spans.data + ss->spans.size; span++) {
2302 if (strcmp(span->label, span->orig_label) != 0)
2303 debug1(sbfd, "Label change: %s -> %s\n",
2304 span->label, span->orig_label);
2309 static void label_map_set(struct superbfd *sbfd, const char *oldlabel,
2310 const char *label)
2312 struct label_map *map;
2313 for (map = sbfd->maps.data;
2314 map < sbfd->maps.data + sbfd->maps.size; map++) {
2315 if (strcmp(map->orig_label, oldlabel) == 0) {
2316 if (strcmp(map->orig_label, map->label) != 0 &&
2317 strcmp(map->label, label) != 0)
2318 DIE;
2319 map->label = label;
2320 return;
2323 DIE;
2326 static void init_callers(struct superbfd *sbfd)
2328 string_hash_init(&sbfd->callers);
2329 asection *sect;
2330 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2331 struct supersect *ss = fetch_supersect(sbfd, sect);
2332 arelent **relocp;
2333 for (relocp = ss->relocs.data;
2334 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
2335 asymbol *sym = *(*relocp)->sym_ptr_ptr;
2336 unsigned long val =
2337 sym->value + get_reloc_offset(ss, *relocp, true);
2338 char *key;
2339 assert(asprintf(&key, "%s+%lx", sym->section->name,
2340 val) >= 0);
2341 const char **ret = string_hash_lookup(&sbfd->callers,
2342 key, TRUE);
2343 free(key);
2344 if (*ret == NULL)
2345 *ret = sect->name;
2346 else
2347 *ret = "*multiple_callers*";
2352 static const char *find_caller(struct supersect *ss, asymbol *sym)
2354 char *key;
2355 assert(asprintf(&key, "%s+%lx", sym->section->name,
2356 (unsigned long)sym->value) >= 0);
2357 const char **ret = string_hash_lookup(&ss->parent->callers, key, FALSE);
2358 free(key);
2360 if (ret == NULL)
2361 return "*no_caller*";
2362 return *ret;
2365 static void init_csyms(struct superbfd *sbfd)
2367 asymbolpp_hash_init(&sbfd->csyms);
2369 asymbol **symp;
2370 for (symp = sbfd->syms.data; symp < sbfd->syms.data + sbfd->syms.size;
2371 symp++) {
2372 asymbol *sym = *symp;
2373 if ((sym->flags & BSF_DEBUGGING) != 0)
2374 continue;
2375 char *key;
2376 assert(asprintf(&key, "%s+%lx", sym->section->name,
2377 (unsigned long)sym->value) >= 0);
2378 asymbol ***csympp = asymbolpp_hash_lookup(&sbfd->csyms, key,
2379 TRUE);
2380 free(key);
2381 if (*csympp == NULL) {
2382 *csympp = symp;
2383 continue;
2385 asymbol *csym = **csympp;
2386 if ((csym->flags & BSF_GLOBAL) != 0)
2387 continue;
2388 if ((sym->flags & BSF_GLOBAL) != 0)
2389 *csympp = symp;
2393 static asymbol **symbolp_scan(struct supersect *ss, bfd_vma value)
2395 char *key;
2396 assert(asprintf(&key, "%s+%lx", ss->name, (unsigned long)value) >= 0);
2397 asymbol ***csympp =
2398 asymbolpp_hash_lookup(&ss->parent->csyms, key, FALSE);
2399 free(key);
2400 if (csympp != NULL)
2401 return *csympp;
2403 /* For section symbols of sections containing no symbols, return the
2404 section symbol that relocations are generated against */
2405 if (value == 0)
2406 return &ss->symbol;
2407 return NULL;
2410 static asymbol **canonical_symbolp(struct superbfd *sbfd, asymbol *sym)
2412 if (bfd_is_const_section(sym->section)) {
2413 asymbol **csymp;
2414 for (csymp = sbfd->syms.data;
2415 csymp < sbfd->syms.data + sbfd->syms.size; csymp++) {
2416 if (sym == *csymp)
2417 return csymp;
2419 return NULL;
2421 return symbolp_scan(fetch_supersect(sbfd, sym->section), sym->value);
2424 static asymbol *canonical_symbol(struct superbfd *sbfd, asymbol *sym)
2426 if (bfd_is_const_section(sym->section))
2427 return sym;
2428 asymbol **symp = canonical_symbolp(sbfd, sym);
2429 return symp != NULL ? *symp : NULL;
2432 static char *static_local_symbol(struct superbfd *sbfd, asymbol *sym)
2434 struct supersect *ss = fetch_supersect(sbfd, sym->section);
2435 if ((sym->flags & BSF_LOCAL) == 0 || (sym->flags & BSF_OBJECT) == 0)
2436 return NULL;
2437 char *dot = strrchr(sym->name, '.');
2438 if (dot == NULL || dot[1 + strspn(dot + 1, "0123546789")] != '\0')
2439 return NULL;
2440 char *basename = strndup(sym->name, dot - sym->name);
2441 char *mangled_name;
2442 if (strcmp(basename, "__func__") == 0 ||
2443 strcmp(basename, "__PRETTY_FUNCTION__") == 0)
2444 assert(asprintf(&mangled_name, "%s<%s>", basename,
2445 (char *)ss->contents.data + sym->value) >= 0);
2446 else
2447 assert(asprintf(&mangled_name, "%s<%s>", basename,
2448 find_caller(ss, sym)) >= 0);
2449 return mangled_name;
2452 static char *symbol_label(struct superbfd *sbfd, asymbol *sym)
2454 const char *filename = sbfd->abfd->filename;
2455 char *c = strstr(filename, ".KSPLICE");
2456 int flen = (c == NULL ? strlen(filename) : c - filename);
2458 char *label;
2459 if (bfd_is_und_section(sym->section) || (sym->flags & BSF_GLOBAL) != 0) {
2460 label = strdup(sym->name);
2461 } else if (bfd_is_const_section(sym->section)) {
2462 assert(asprintf(&label, "%s<%.*s>",
2463 sym->name, flen, filename) >= 0);
2464 } else {
2465 asymbol *gsym = canonical_symbol(sbfd, sym);
2467 if (gsym == NULL)
2468 assert(asprintf(&label, "%s+%lx<%.*s>",
2469 sym->section->name,
2470 (unsigned long)sym->value,
2471 flen, filename) >= 0);
2472 else if ((gsym->flags & BSF_GLOBAL) != 0)
2473 label = strdup(gsym->name);
2474 else if (static_local_symbol(sbfd, gsym))
2475 assert(asprintf(&label, "%s+%lx<%.*s>",
2476 static_local_symbol(sbfd, gsym),
2477 (unsigned long)sym->value,
2478 flen, filename) >= 0);
2479 else
2480 assert(asprintf(&label, "%s<%.*s>",
2481 gsym->name, flen, filename) >= 0);
2484 return label;
2487 static void keep_span(struct span *span)
2489 span->keep = true;
2490 span->ss->keep = true;
2493 static struct span *new_span(struct supersect *ss, bfd_vma start, bfd_vma size)
2495 struct span *span = vec_grow(&ss->spans, 1);
2496 span->size = size;
2497 span->start = start;
2498 span->ss = ss;
2499 span->keep = false;
2500 span->new = false;
2501 span->patch = false;
2502 span->match = NULL;
2503 span->shift = 0;
2504 asymbol **symp = symbolp_scan(ss, span->start);
2505 if (symp != NULL) {
2506 span->symbol = *symp;
2507 span->label = label_lookup(ss->parent, span->symbol);
2508 } else {
2509 span->symbol = NULL;
2510 const char *label = label_lookup(ss->parent, ss->symbol);
2511 if (span->start != 0) {
2512 char *buf;
2513 assert(asprintf(&buf, "%s<span:%lx>", label,
2514 (unsigned long)span->start) >= 0);
2515 span->label = buf;
2516 } else {
2517 span->label = label;
2520 span->orig_label = span->label;
2521 return span;
2524 static void initialize_string_spans(struct supersect *ss)
2526 const char *str;
2527 for (str = ss->contents.data;
2528 (void *)str < ss->contents.data + ss->contents.size;) {
2529 bfd_vma start = (unsigned long)str -
2530 (unsigned long)ss->contents.data;
2531 bfd_vma size = strlen(str) + 1;
2532 while ((start + size) % (1 << ss->alignment) != 0 &&
2533 start + size < ss->contents.size) {
2534 if (str[size] != '\0')
2535 DIE;
2536 size++;
2538 new_span(ss, start, size);
2539 str += size;
2543 static int compare_ulongs(const void *va, const void *vb)
2545 const unsigned long *a = va, *b = vb;
2546 return *a - *b;
2549 static void initialize_table_spans(struct superbfd *sbfd,
2550 struct table_section *s)
2552 asection *isection = bfd_get_section_by_name(sbfd->abfd, s->sect);
2553 if (isection == NULL)
2554 return;
2555 asection *other_sect = NULL;
2556 if (s->other_sect != NULL)
2557 other_sect = bfd_get_section_by_name(sbfd->abfd, s->other_sect);
2559 struct supersect *ss = fetch_supersect(sbfd, isection);
2560 if (ss->alignment < ffs(s->entry_align) - 1)
2561 ss->alignment = ffs(s->entry_align) - 1;
2563 struct supersect *other_ss = NULL;
2564 if (other_sect != NULL)
2565 other_ss = fetch_supersect(sbfd, other_sect);
2567 struct ulong_vec offsets;
2568 vec_init(&offsets);
2570 void *entry;
2571 for (entry = ss->contents.data;
2572 entry < ss->contents.data + ss->contents.size;
2573 entry += s->entry_size) {
2574 new_span(ss, addr_offset(ss, entry), s->entry_size);
2576 if (other_sect != NULL) {
2577 asymbol *sym;
2578 bfd_vma offset = read_reloc(ss, entry + s->other_offset,
2579 sizeof(void *), &sym);
2580 if (sym->section == other_sect) {
2581 assert(offset >= 0 &&
2582 offset < other_ss->contents.size);
2583 *vec_grow(&offsets, 1) = offset;
2588 if (other_sect == NULL)
2589 return;
2591 qsort(offsets.data, offsets.size, sizeof(*offsets.data),
2592 compare_ulongs);
2593 *vec_grow(&offsets, 1) = other_ss->contents.size;
2595 unsigned long *off;
2596 for (off = offsets.data; off < offsets.data + offsets.size - 1; off++)
2597 new_span(other_ss, *off, *(off + 1) - *off);
2600 static void initialize_table_section_spans(struct superbfd *sbfd)
2602 struct supersect *tables_ss =
2603 fetch_supersect(offsets_sbfd,
2604 bfd_get_section_by_name(offsets_sbfd->abfd,
2605 ".ksplice_table_sections"));
2606 const struct table_section *ts;
2607 struct table_section s;
2608 for (ts = tables_ss->contents.data;
2609 (void *)ts < tables_ss->contents.data + tables_ss->contents.size;
2610 ts++) {
2611 s = *ts;
2612 s.sect = read_string(tables_ss, &ts->sect);
2613 s.other_sect = read_string(tables_ss, &ts->other_sect);
2614 initialize_table_spans(sbfd, &s);
2618 static void initialize_spans(struct superbfd *sbfd)
2620 if (mode("keep"))
2621 initialize_table_section_spans(sbfd);
2623 asection *sect;
2624 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2625 if (is_table_section(sect->name, true) && mode("keep"))
2626 continue;
2628 struct supersect *ss = fetch_supersect(sbfd, sect);
2629 if (ss->type == SS_TYPE_STRING)
2630 initialize_string_spans(ss);
2631 else if (!mode("keep") || ss->type != SS_TYPE_EXPORT)
2632 new_span(ss, 0, ss->contents.size);
2636 struct span *reloc_target_span(struct supersect *ss, arelent *reloc)
2638 asymbol *sym_ptr = *reloc->sym_ptr_ptr;
2639 if (bfd_is_const_section(sym_ptr->section))
2640 return NULL;
2642 bfd_vma addend = get_reloc_offset(ss, reloc, true) + sym_ptr->value;
2643 struct supersect *sym_ss =
2644 fetch_supersect(ss->parent, sym_ptr->section);
2645 struct span *span, *target_span = sym_ss->spans.data;
2646 for (span = sym_ss->spans.data;
2647 span < sym_ss->spans.data + sym_ss->spans.size; span++) {
2648 if (addend >= span->start && addend < span->start + span->size)
2649 target_span = span;
2651 return target_span;
2654 struct span *find_span(struct supersect *ss, bfd_size_type address)
2656 struct span *span;
2657 for (span = ss->spans.data; span < ss->spans.data + ss->spans.size;
2658 span++) {
2659 if (address >= span->start &&
2660 address < span->start + span->size)
2661 return span;
2663 /* Deal with empty BSS sections */
2664 if (ss->contents.size == 0 && ss->spans.size > 0)
2665 return ss->spans.data;
2666 return NULL;
2669 void compute_span_shifts(struct superbfd *sbfd)
2671 asection *sect;
2672 struct span *span;
2673 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2674 struct supersect *ss = fetch_supersect(sbfd, sect);
2675 if (!ss->keep)
2676 continue;
2677 bfd_size_type offset = 0;
2678 for (span = ss->spans.data;
2679 span < ss->spans.data + ss->spans.size; span++) {
2680 if (!span->keep)
2681 continue;
2682 span->shift = offset - span->start;
2683 offset += span->size;
2688 void remove_unkept_spans(struct superbfd *sbfd)
2690 asection *sect;
2691 struct span *span;
2692 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2693 struct supersect *ss = fetch_supersect(sbfd, sect);
2694 delete_obsolete_relocs(ss);
2695 struct arelentp_vec orig_relocs;
2696 vec_move(&orig_relocs, &ss->relocs);
2697 arelent **relocp, *reloc;
2698 for (relocp = orig_relocs.data;
2699 relocp < orig_relocs.data + orig_relocs.size; relocp++) {
2700 reloc = *relocp;
2701 asymbol *sym = *reloc->sym_ptr_ptr;
2702 span = reloc_target_span(ss, reloc);
2703 if ((span != NULL && span->keep && span->shift == 0) ||
2704 bfd_is_const_section(sym->section)) {
2705 *vec_grow(&ss->relocs, 1) = reloc;
2706 continue;
2708 struct supersect *sym_ss =
2709 fetch_supersect(sbfd, sym->section);
2710 if (span != NULL && (sym->flags & BSF_SECTION_SYM) == 0
2711 && find_span(sym_ss, sym->value) != span) {
2712 err(sbfd, "Spans for symbol %s and relocation "
2713 "target do not match in sect %s\n",
2714 sym->name, sym_ss->name);
2715 DIE;
2717 if (span != NULL && span->keep) {
2718 arelent *new_reloc = malloc(sizeof(*new_reloc));
2719 *new_reloc = *reloc;
2720 new_reloc->addend =
2721 get_reloc_offset(ss, reloc, false);
2722 new_reloc->addend += span->shift;
2723 *vec_grow(&ss->new_relocs, 1) = new_reloc;
2728 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2729 struct supersect *ss = fetch_supersect(sbfd, sect), orig_ss;
2730 if (!ss->keep)
2731 continue;
2732 supersect_move(&orig_ss, ss);
2733 vec_init(&ss->spans);
2734 for (span = orig_ss.spans.data;
2735 span < orig_ss.spans.data + orig_ss.spans.size; span++) {
2736 if (!span->keep)
2737 continue;
2738 struct span *new_span = vec_grow(&ss->spans, 1);
2739 *new_span = *span;
2740 new_span->start = span->start + span->shift;
2741 new_span->shift = 0;
2742 sect_copy(ss, sect_do_grow(ss, 1, span->size, 1),
2743 &orig_ss, orig_ss.contents.data + span->start,
2744 span->size);
2749 static void init_objmanip_superbfd(struct superbfd *sbfd)
2751 init_label_map(sbfd);
2752 initialize_supersect_types(sbfd);
2753 initialize_spans(sbfd);
2756 void mangle_section_name(struct superbfd *sbfd, const char *name)
2758 asection *sect = bfd_get_section_by_name(sbfd->abfd, name);
2759 if (sect == NULL)
2760 return;
2761 struct supersect *ss = fetch_supersect(sbfd, sect);
2762 char *buf;
2763 assert(asprintf(&buf, ".ksplice_pre.%s", ss->name) >= 0);
2764 ss->name = buf;