Check that spans containing global symbols are never unmatched.
[ksplice.git] / objmanip.c
blob36dc2b8b5affcd827582b2bf762b4fa16be755c2
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 struct export_desc {
77 const char *export_type;
78 bool deletion;
79 struct str_vec names;
80 struct supersect *sym_ss;
81 struct supersect *crc_ss;
83 DECLARE_VEC_TYPE(struct export_desc, export_desc_vec);
85 #define bool_init(b) *(b) = false
86 DEFINE_HASH_TYPE(bool, bool_hash, bool_hash_init, bool_hash_free,
87 bool_hash_lookup, bool_init);
89 #define ulong_init(x) *(x) = 0
90 DEFINE_HASH_TYPE(unsigned long, ulong_hash, ulong_hash_init,
91 ulong_hash_free, ulong_hash_lookup, ulong_init);
93 void do_keep_primary(struct superbfd *isbfd, const char *pre);
94 void do_keep_helper(struct superbfd *isbfd);
95 void do_finalize(struct superbfd *isbfd);
96 void do_rmsyms(struct superbfd *isbfd);
98 struct export_vec *get_export_syms(struct superbfd *sbfd);
99 void compare_exported_symbols(struct superbfd *oldsbfd,
100 struct superbfd *newsbfd, bool deletion);
101 struct export_desc *new_export_desc(struct supersect *ss, bool deletion);
102 bool relocs_equal(struct supersect *old_src_ss, struct supersect *new_src_ss,
103 arelent *old_reloc, arelent *new_reloc);
104 bool all_relocs_equal(struct supersect *old_ss, struct supersect *new_ss);
105 bfd_vma non_dst_mask(struct supersect *ss, arelent *reloc);
106 static bool part_of_reloc(struct supersect *ss, unsigned long addr);
107 static bool nonrelocs_equal(struct supersect *old_ss, struct supersect *new_ss);
108 static void handle_section_symbol_renames(struct superbfd *oldsbfd,
109 struct superbfd *newsbfd);
111 enum supersect_type supersect_type(struct supersect *ss);
112 void initialize_supersect_types(struct superbfd *sbfd);
113 static void initialize_spans(struct superbfd *sbfd);
114 static void initialize_string_spans(struct supersect *ss);
115 struct span *reloc_target_span(struct supersect *ss, arelent *reloc);
116 struct span *reloc_address_span(struct supersect *ss, arelent *reloc);
117 void remove_unkept_spans(struct superbfd *sbfd);
118 void compute_span_shifts(struct superbfd *sbfd);
119 static struct span *new_span(struct supersect *ss, bfd_vma start, bfd_vma size);
120 bool is_table_section(const char *name, bool consider_other);
122 void rm_relocs(struct superbfd *isbfd);
123 void rm_some_relocs(struct supersect *ss);
124 void write_ksplice_reloc(struct supersect *ss, arelent *orig_reloc);
125 void load_ksplice_symbol_offsets(struct superbfd *sbfd);
126 void blot_section(struct supersect *ss, int offset, reloc_howto_type *howto);
127 static void write_ksplice_section(struct span *span);
128 void write_ksplice_patch(struct superbfd *sbfd, const char *sectname);
129 void write_ksplice_deleted_patch(struct superbfd *sbfd, const char *name,
130 const char *label);
131 asymbol **make_undefined_symbolp(struct superbfd *sbfd, const char *name);
132 void filter_table_sections(struct superbfd *isbfd);
133 void filter_table_section(struct superbfd *sbfd, const struct table_section *s);
134 void keep_referenced_sections(struct superbfd *sbfd);
135 bfd_boolean copy_object(bfd *ibfd, bfd *obfd);
136 void setup_section(bfd *ibfd, asection *isection, void *obfdarg);
137 static void setup_new_section(bfd *obfd, struct supersect *ss);
138 static void write_section(bfd *obfd, asection *osection, void *arg);
139 static void delete_obsolete_relocs(struct supersect *ss);
140 void mark_symbols_used_in_relocations(bfd *abfd, asection *isection,
141 void *ignored);
142 static void ss_mark_symbols_used_in_relocations(struct supersect *ss);
143 void filter_symbols(bfd *ibfd, bfd *obfd, struct asymbolp_vec *osyms,
144 struct asymbolp_vec *isyms);
145 static bool deleted_table_section_symbol(bfd *abfd, asymbol *sym);
146 void read_str_set(struct str_vec *strs);
147 bool str_in_set(const char *str, const struct str_vec *strs);
148 struct supersect *make_section(struct superbfd *sbfd, const char *name);
149 void __attribute__((format(printf, 3, 4)))
150 write_string(struct supersect *ss, const char **addr, const char *fmt, ...);
151 void rm_some_exports(struct superbfd *isbfd, const struct export_desc *ed);
152 void write_ksplice_export(struct superbfd *sbfd, const char *symname,
153 const char *export_type, bool del);
154 void write_reloc(struct supersect *ss, const void *addr, asymbol **symp,
155 bfd_vma offset);
156 arelent *create_reloc(struct supersect *ss, const void *addr, asymbol **symp,
157 bfd_vma offset);
158 static void foreach_symbol_pair(struct superbfd *oldsbfd, struct superbfd *newsbfd,
159 void (*fn)(struct supersect *oldss,
160 asymbol *oldsym,
161 struct supersect *newss,
162 asymbol *newsym));
163 static void check_global_symbols(struct supersect *oldss, asymbol *oldsym,
164 struct supersect *newss, asymbol *newsym);
165 static void match_global_symbols(struct supersect *oldss, asymbol *oldsym,
166 struct supersect *newss, asymbol *newsym);
168 static void match_sections_by_name(struct superbfd *oldsbfd,
169 struct superbfd *newsbfd);
170 static void match_sections_by_label(struct superbfd *oldsbfd,
171 struct superbfd *newsbfd);
172 static void mark_new_sections(struct superbfd *sbfd);
173 static void handle_deleted_sections(struct superbfd *oldsbfd,
174 struct superbfd *newsbfd);
175 static void compare_matched_sections(struct superbfd *sbfd);
176 static void update_nonzero_offsets(struct superbfd *sbfd);
177 static void handle_nonzero_offset_relocs(struct supersect *ss);
179 static const char *label_lookup(struct superbfd *sbfd, asymbol *sym);
180 static void print_label_map(struct superbfd *sbfd);
181 static void label_map_set(struct superbfd *sbfd, const char *oldlabel,
182 const char *label);
183 static void init_label_map(struct superbfd *sbfd);
184 static asymbol **symbolp_scan(struct supersect *ss, bfd_vma value);
185 static void init_csyms(struct superbfd *sbfd);
186 static void init_callers(struct superbfd *sbfd);
187 static asymbol *canonical_symbol(struct superbfd *sbfd, asymbol *sym);
188 static asymbol **canonical_symbolp(struct superbfd *sbfd, asymbol *sym);
189 static char *static_local_symbol(struct superbfd *sbfd, asymbol *sym);
190 static char *symbol_label(struct superbfd *sbfd, asymbol *sym);
192 int verbose = 0;
193 #define debug_(sbfd, level, fmt, ...) \
194 do { \
195 if (verbose >= (level)) \
196 printf("%s: " fmt, (sbfd)->abfd->filename, \
197 ## __VA_ARGS__); \
198 } while (0)
199 #define debug0(sbfd, fmt, ...) debug_(sbfd, 0, fmt, ## __VA_ARGS__)
200 #define debug1(sbfd, fmt, ...) debug_(sbfd, 1, fmt, ## __VA_ARGS__)
201 #define err(sbfd, fmt, ...) \
202 do { \
203 fprintf(stderr, "%s: " fmt, (sbfd)->abfd->filename, \
204 ## __VA_ARGS__); \
205 } while (0)
207 struct str_vec delsects, rmsyms;
208 struct export_desc_vec exports;
209 bool changed;
211 struct ksplice_config *config;
213 const char *modestr, *kid;
215 struct superbfd *offsets_sbfd = NULL;
217 #define mode(str) starts_with(modestr, str)
219 DECLARE_VEC_TYPE(unsigned long, addr_vec);
220 DEFINE_HASH_TYPE(struct addr_vec, addr_vec_hash,
221 addr_vec_hash_init, addr_vec_hash_free, addr_vec_hash_lookup,
222 vec_init);
223 struct addr_vec_hash system_map;
225 struct bool_hash system_map_written;
226 struct ulong_hash ksplice_symbol_offset;
227 struct ulong_hash ksplice_string_offset;
229 void load_system_map()
231 const char *config_dir = getenv("KSPLICE_CONFIG_DIR");
232 assert(config_dir);
233 char *file;
234 assert(asprintf(&file, "%s/System.map", config_dir) >= 0);
235 FILE *fp = fopen(file, "r");
236 assert(fp);
237 addr_vec_hash_init(&system_map);
238 unsigned long addr;
239 char type;
240 char *sym;
241 while (fscanf(fp, "%lx %c %as\n", &addr, &type, &sym) == 3)
242 *vec_grow(addr_vec_hash_lookup(&system_map, sym, TRUE),
243 1) = addr;
244 fclose(fp);
247 void load_ksplice_symbol_offsets(struct superbfd *sbfd)
249 asection *sect = bfd_get_section_by_name(sbfd->abfd,
250 ".ksplice_symbols");
251 if (sect == NULL)
252 return;
253 struct supersect *ss = fetch_supersect(sbfd, sect);
255 struct ksplice_symbol *ksym;
256 for (ksym = ss->contents.data;
257 (void *)ksym < ss->contents.data + ss->contents.size; ksym++) {
258 const char *label = read_string(ss, &ksym->label);
259 unsigned long *ksymbol_offp =
260 ulong_hash_lookup(&ksplice_symbol_offset, label, TRUE);
261 *ksymbol_offp = addr_offset(ss, ksym);
265 void load_offsets()
267 char *kmodsrc = getenv("KSPLICE_KMODSRC"), *offsets_file;
268 assert(kmodsrc != NULL);
269 assert(asprintf(&offsets_file, "%s/offsets.o", kmodsrc) >= 0);
270 bfd *offsets_bfd = bfd_openr(offsets_file, NULL);
271 assert(offsets_bfd != NULL);
272 char **matching;
273 assert(bfd_check_format_matches(offsets_bfd, bfd_object, &matching));
274 offsets_sbfd = fetch_superbfd(offsets_bfd);
276 asection *config_sect = bfd_get_section_by_name(offsets_sbfd->abfd,
277 ".ksplice_config");
278 struct supersect *config_ss =
279 fetch_supersect(offsets_sbfd, config_sect);
281 config = config_ss->contents.data;
284 bool matchable_data_section(struct supersect *ss)
286 if (ss->type == SS_TYPE_STRING)
287 return true;
288 if (ss->type == SS_TYPE_RODATA)
289 return true;
290 if (ss->type == SS_TYPE_DATA && ss->relocs.size != 0)
291 return true;
292 return false;
295 bool unchangeable_section(struct supersect *ss)
297 if (ss->type == SS_TYPE_DATA)
298 return true;
299 if (ss->type == SS_TYPE_IGNORED && !starts_with(ss->name, ".debug") &&
300 strcmp(ss->name, "__ksymtab_strings") != 0)
301 return true;
302 return false;
305 int main(int argc, char *argv[])
307 if (getenv("KSPLICE_VERBOSE") != NULL)
308 verbose = atoi(getenv("KSPLICE_VERBOSE"));
310 bfd_init();
311 bfd *ibfd = bfd_openr(argv[1], NULL);
312 assert(ibfd);
314 char **matching;
315 assert(bfd_check_format_matches(ibfd, bfd_object, &matching));
317 const char *output_target = bfd_get_target(ibfd);
318 bfd *obfd = bfd_openw(argv[2], output_target);
319 assert(obfd);
321 struct superbfd *isbfd = fetch_superbfd(ibfd);
322 init_label_map(isbfd);
324 bool_hash_init(&system_map_written);
325 ulong_hash_init(&ksplice_symbol_offset);
326 ulong_hash_init(&ksplice_string_offset);
328 modestr = argv[3];
329 if (mode("keep-primary")) {
330 kid = argv[5];
331 do_keep_primary(isbfd, argv[4]);
332 } else if (mode("keep-helper")) {
333 do_keep_helper(isbfd);
334 } else if (mode("finalize")) {
335 do_finalize(isbfd);
336 } else if (mode("rmsyms")) {
337 do_rmsyms(isbfd);
340 copy_object(ibfd, obfd);
342 if (offsets_sbfd != NULL)
343 assert(bfd_close(offsets_sbfd->abfd));
344 assert(bfd_close(obfd));
345 assert(bfd_close(ibfd));
346 return EXIT_SUCCESS;
349 void do_keep_primary(struct superbfd *isbfd, const char *pre)
351 struct bfd *prebfd = bfd_openr(pre, NULL);
352 assert(prebfd != NULL);
353 char **matching;
354 assert(bfd_check_format_matches(prebfd, bfd_object, &matching));
356 struct superbfd *presbfd = fetch_superbfd(prebfd);
357 init_label_map(presbfd);
358 load_system_map();
359 load_offsets();
360 initialize_supersect_types(isbfd);
361 initialize_supersect_types(presbfd);
363 foreach_symbol_pair(presbfd, isbfd, match_global_symbols);
364 debug1(isbfd, "Matched global\n");
365 match_sections_by_name(presbfd, isbfd);
366 debug1(isbfd, "Matched by name\n");
367 match_sections_by_label(presbfd, isbfd);
368 debug1(isbfd, "Matched by label\n");
370 do {
371 changed = false;
372 compare_matched_sections(isbfd);
373 update_nonzero_offsets(isbfd);
374 mark_new_sections(isbfd);
375 } while (changed);
376 vec_init(&delsects);
378 foreach_symbol_pair(presbfd, isbfd, check_global_symbols);
380 handle_deleted_sections(presbfd, isbfd);
381 handle_section_symbol_renames(presbfd, isbfd);
383 vec_init(&exports);
384 compare_exported_symbols(presbfd, isbfd, false);
385 compare_exported_symbols(isbfd, presbfd, true);
387 initialize_spans(isbfd);
388 initialize_spans(presbfd);
389 asection *sect;
390 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
391 struct supersect *ss = fetch_supersect(isbfd, sect);
392 if (ss->type != SS_TYPE_STRING)
393 continue;
394 asection *oldsect = bfd_get_section_by_name(prebfd, sect->name);
395 if (oldsect == NULL)
396 continue;
397 struct supersect *old_ss = fetch_supersect(presbfd, oldsect);
398 struct span *span, *old_span;
399 for (span = ss->spans.data;
400 span < ss->spans.data + ss->spans.size; span++) {
401 span->new = true;
402 for (old_span = old_ss->spans.data;
403 old_span < old_ss->spans.data + old_ss->spans.size;
404 old_span++) {
405 if (strcmp((char *)ss->contents.data +
406 span->start,
407 (char *)old_ss->contents.data +
408 old_span->start) == 0) {
409 if (!span->new)
410 DIE;
411 span->label = old_span->label;
412 span->new = false;
417 assert(bfd_close(prebfd));
419 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
420 struct supersect *ss = fetch_supersect(isbfd, sect);
421 ss->keep = false;
422 if (ss->type == SS_TYPE_STRING || ss->type == SS_TYPE_SPECIAL ||
423 ss->type == SS_TYPE_EXPORT)
424 ss->keep = true;
425 if (ss->new || ss->patch)
426 ss->keep = true;
429 print_label_map(isbfd);
431 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
432 struct supersect *ss = fetch_supersect(isbfd, sect);
433 if (ss->patch)
434 debug0(isbfd, "Patching section: %s\n", sect->name);
437 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
438 struct supersect *ss = fetch_supersect(isbfd, sect);
439 if (ss->new)
440 debug0(isbfd, "New section: %s\n", sect->name);
443 const char **sectname;
444 for (sectname = delsects.data;
445 sectname < delsects.data + delsects.size; sectname++)
446 debug0(isbfd, "Deleted section: %s\n", *sectname);
448 const struct export_desc *ed;
449 for (ed = exports.data; ed < exports.data + exports.size; ed++) {
450 const char **symname;
451 for (symname = ed->names.data;
452 symname < ed->names.data + ed->names.size; symname++)
453 debug0(isbfd, "Export %s (%s): %s\n",
454 ed->deletion ? "deletion" : "addition",
455 ed->export_type, *symname);
458 struct span *span;
459 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
460 struct supersect *ss = fetch_supersect(isbfd, sect);
461 for (span = ss->spans.data;
462 span < ss->spans.data + ss->spans.size; span++)
463 span->keep = ss->keep;
466 filter_table_sections(isbfd);
467 for (ed = exports.data; ed < exports.data + exports.size; ed++) {
468 const char **symname;
469 for (symname = ed->names.data;
470 symname < ed->names.data + ed->names.size; symname++)
471 write_ksplice_export(isbfd, *symname,
472 ed->export_type, ed->deletion);
473 if (!ed->deletion)
474 rm_some_exports(isbfd, ed);
477 compute_span_shifts(isbfd);
479 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
480 struct supersect *ss = fetch_supersect(isbfd, sect);
481 if (!ss->patch && !ss->new)
482 continue;
484 struct span *span;
485 for (span = ss->spans.data;
486 span < ss->spans.data + ss->spans.size; span++)
487 write_ksplice_section(span);
489 if (ss->patch)
490 write_ksplice_patch(isbfd, sect->name);
493 rm_relocs(isbfd);
494 remove_unkept_spans(isbfd);
497 void do_keep_helper(struct superbfd *isbfd)
499 load_system_map();
500 load_offsets();
501 initialize_supersect_types(isbfd);
502 initialize_spans(isbfd);
504 asection *sect;
505 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
506 struct supersect *ss = fetch_supersect(isbfd, sect);
507 ss->keep = false;
508 if (ss->type == SS_TYPE_SPECIAL || ss->type == SS_TYPE_TEXT)
509 ss->keep = true;
512 asymbol **symp;
513 for (symp = isbfd->syms.data;
514 symp < isbfd->syms.data + isbfd->syms.size; symp++) {
515 asymbol *sym = *symp;
516 if (!bfd_is_const_section(sym->section) &&
517 (sym->flags & BSF_GLOBAL) != 0) {
518 struct supersect *sym_ss =
519 fetch_supersect(isbfd, sym->section);
520 if (sym_ss->type != SS_TYPE_IGNORED)
521 sym_ss->keep = true;
525 struct span *span;
526 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
527 struct supersect *ss = fetch_supersect(isbfd, sect);
528 for (span = ss->spans.data;
529 span < ss->spans.data + ss->spans.size; span++)
530 span->keep = ss->keep;
533 do {
534 changed = false;
535 keep_referenced_sections(isbfd);
536 } while (changed);
538 filter_table_sections(isbfd);
539 compute_span_shifts(isbfd);
541 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
542 struct supersect *ss = fetch_supersect(isbfd, sect);
543 asymbol *sym = canonical_symbol(isbfd, sect->symbol);
544 if (sym == NULL)
545 continue;
546 if ((sym->flags & BSF_WEAK) != 0)
547 continue;
548 if (bfd_get_section_size(sect) == 0)
549 continue;
550 if (!ss->keep)
551 continue;
552 if (ss->type != SS_TYPE_TEXT && !matchable_data_section(ss))
553 continue;
555 struct span *span;
556 for (span = ss->spans.data;
557 span < ss->spans.data + ss->spans.size; span++) {
558 if (span->keep)
559 write_ksplice_section(span);
563 rm_relocs(isbfd);
564 remove_unkept_spans(isbfd);
567 void do_finalize(struct superbfd *isbfd)
569 load_system_map();
570 load_ksplice_symbol_offsets(isbfd);
571 load_offsets();
572 initialize_supersect_types(isbfd);
573 initialize_spans(isbfd);
574 rm_relocs(isbfd);
577 void do_rmsyms(struct superbfd *isbfd)
579 read_str_set(&rmsyms);
580 load_system_map();
581 load_offsets();
582 initialize_supersect_types(isbfd);
583 initialize_spans(isbfd);
584 rm_relocs(isbfd);
587 struct export_vec *get_export_syms(struct superbfd *sbfd)
589 asection *sect;
590 struct export_vec *exports;
591 exports = malloc(sizeof(*exports));
592 assert(exports != NULL);
593 vec_init(exports);
595 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
596 if (!starts_with(sect->name, "__ksymtab") ||
597 ends_with(sect->name, "_strings"))
598 continue;
599 struct supersect *ss = fetch_supersect(sbfd, sect);
600 struct kernel_symbol *sym;
601 assert(ss->contents.size * 2 == ss->relocs.size *
602 sizeof(struct kernel_symbol));
603 for (sym = ss->contents.data;
604 (void *)sym < ss->contents.data + ss->contents.size;
605 sym++) {
606 struct export *exp = vec_grow(exports, 1);
607 exp->name =
608 read_string(ss, (const char *const *)&sym->name);
609 exp->ss = ss;
612 return exports;
615 struct export_desc *new_export_desc(struct supersect *ss, bool deletion)
617 struct export_desc *ed = vec_grow(&exports, 1);
618 ed->deletion = deletion;
619 vec_init(&ed->names);
620 ed->export_type = strdup(ss->name) + strlen("__ksymtab");
621 ed->sym_ss = ss;
622 char *crc_sect_name;
623 assert(asprintf(&crc_sect_name, "__kcrctab%s", ed->export_type) >= 0);
624 asection *crc_sect =
625 bfd_get_section_by_name(ss->parent->abfd, crc_sect_name);
626 if (crc_sect == NULL)
627 ed->crc_ss = NULL;
628 else
629 ed->crc_ss = fetch_supersect(ss->parent, crc_sect);
630 return ed;
633 void compare_exported_symbols(struct superbfd *oldsbfd,
634 struct superbfd *newsbfd, bool deletion)
636 struct export_vec *new_exports, *old_exports;
637 new_exports = get_export_syms(newsbfd);
638 if (new_exports == NULL)
639 return;
640 old_exports = get_export_syms(oldsbfd);
641 struct export *old, *new;
642 struct supersect *last_ss = NULL;
643 struct export_desc *ed = NULL;
644 for (new = new_exports->data; new < new_exports->data +
645 new_exports->size; new++) {
646 bool found = false;
647 if (old_exports != NULL) {
648 for (old = old_exports->data; old < old_exports->data +
649 old_exports->size; old++) {
650 if (strcmp(new->name, old->name) == 0 &&
651 strcmp(new->ss->name, old->ss->name) == 0) {
652 found = true;
653 break;
657 if (last_ss != new->ss) {
658 last_ss = new->ss;
659 ed = new_export_desc(new->ss, deletion);
661 if (!found)
662 *vec_grow(&ed->names, 1) = new->name;
666 void match_sections(struct supersect *oldss, struct supersect *newss)
668 if (oldss->match == newss && newss->match == oldss)
669 return;
670 if (oldss->match != NULL) {
671 err(newss->parent, "Matching conflict: old %s: %s != %s\n",
672 oldss->name, oldss->match->name, newss->name);
673 DIE;
675 if (newss->match != NULL) {
676 err(newss->parent, "Matching conflict: new %s: %s != %s\n",
677 newss->name, newss->match->name, oldss->name);
678 DIE;
680 oldss->match = newss;
681 newss->match = oldss;
682 debug1(newss->parent, "Matched old %s to new %s\n",
683 oldss->name, newss->name);
686 static void match_global_symbols(struct supersect *oldss, asymbol *oldsym,
687 struct supersect *newss, asymbol *newsym)
689 if ((oldsym->flags & BSF_GLOBAL) == 0 ||
690 (newsym->flags & BSF_GLOBAL) == 0)
691 return;
692 match_sections(oldss, newss);
695 static void check_global_symbols(struct supersect *oldss, asymbol *oldsym,
696 struct supersect *newss, asymbol *newsym)
698 if ((oldsym->flags & BSF_GLOBAL) == 0 ||
699 (newsym->flags & BSF_GLOBAL) == 0)
700 return;
701 if (oldss->type == SS_TYPE_IGNORED)
702 return;
703 if (oldss->match != newss || newss->match != oldss) {
704 err(newss->parent, "Global symbol section mismatch: %s %s/%s\n",
705 oldsym->name, oldss->name, newss->name);
706 DIE;
710 static void foreach_symbol_pair(struct superbfd *oldsbfd, struct superbfd *newsbfd,
711 void (*fn)(struct supersect *oldss,
712 asymbol *oldsym,
713 struct supersect *newss,
714 asymbol *newsym))
716 asymbol **oldsymp, **newsymp;
717 for (oldsymp = oldsbfd->syms.data;
718 oldsymp < oldsbfd->syms.data + oldsbfd->syms.size; oldsymp++) {
719 asymbol *oldsym = *oldsymp;
720 if (bfd_is_const_section(oldsym->section))
721 continue;
722 for (newsymp = newsbfd->syms.data;
723 newsymp < newsbfd->syms.data + newsbfd->syms.size;
724 newsymp++) {
725 asymbol *newsym = *newsymp;
726 if (bfd_is_const_section(newsym->section))
727 continue;
728 if (strcmp(oldsym->name, newsym->name) != 0)
729 continue;
730 struct supersect *oldss =
731 fetch_supersect(oldsbfd, oldsym->section);
732 struct supersect *newss =
733 fetch_supersect(newsbfd, newsym->section);
734 fn(oldss, oldsym, newss, newsym);
739 static void match_sections_by_name(struct superbfd *oldsbfd,
740 struct superbfd *newsbfd)
742 asection *newp, *oldp;
743 for (newp = newsbfd->abfd->sections; newp != NULL; newp = newp->next) {
744 struct supersect *newss = fetch_supersect(newsbfd, newp);
745 oldp = bfd_get_section_by_name(oldsbfd->abfd, newp->name);
746 if (oldp == NULL || newss->type == SS_TYPE_STRING ||
747 newss->type == SS_TYPE_SPECIAL ||
748 newss->type == SS_TYPE_EXPORT)
749 continue;
750 if (static_local_symbol(newsbfd,
751 canonical_symbol(newsbfd,
752 newp->symbol)))
753 continue;
755 struct supersect *oldss = fetch_supersect(oldsbfd, oldp);
756 match_sections(oldss, newss);
760 static void match_sections_by_label(struct superbfd *oldsbfd,
761 struct superbfd *newsbfd)
763 asection *oldsect, *newsect;
764 struct supersect *oldss, *newss;
765 for (newsect = newsbfd->abfd->sections; newsect != NULL;
766 newsect = newsect->next) {
767 newss = fetch_supersect(newsbfd, newsect);
768 if (newss->type == SS_TYPE_STRING ||
769 newss->type == SS_TYPE_SPECIAL ||
770 newss->type == SS_TYPE_EXPORT)
771 continue;
772 for (oldsect = oldsbfd->abfd->sections; oldsect != NULL;
773 oldsect = oldsect->next) {
774 if (strcmp(label_lookup(newsbfd, newsect->symbol),
775 label_lookup(oldsbfd, oldsect->symbol)) != 0)
776 continue;
777 oldss = fetch_supersect(oldsbfd, oldsect);
778 match_sections(oldss, newss);
783 static void mark_new_sections(struct superbfd *sbfd)
785 asection *sect;
786 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
787 struct supersect *ss = fetch_supersect(sbfd, sect);
788 if (ss->type == SS_TYPE_STRING || ss->type == SS_TYPE_SPECIAL ||
789 ss->type == SS_TYPE_IGNORED || ss->type == SS_TYPE_EXPORT)
790 continue;
791 if (ss->match == NULL)
792 ss->new = true;
796 static void handle_deleted_sections(struct superbfd *oldsbfd,
797 struct superbfd *newsbfd)
799 asection *sect;
800 for (sect = oldsbfd->abfd->sections; sect != NULL; sect = sect->next) {
801 struct supersect *ss = fetch_supersect(oldsbfd, sect);
802 if (ss->type != SS_TYPE_TEXT)
803 continue;
804 if (ss->match != NULL)
805 continue;
806 const char *label = label_lookup(oldsbfd, sect->symbol);
807 *vec_grow(&delsects, 1) = label;
808 asymbol *csym = canonical_symbol(oldsbfd, sect->symbol);
809 write_ksplice_deleted_patch(newsbfd, csym->name, label);
813 static void handle_nonzero_offset_relocs(struct supersect *ss)
815 int i;
816 for (i = 0; i < ss->relocs.size; i++) {
817 asymbol *sym = *ss->relocs.data[i]->sym_ptr_ptr;
818 bfd_vma offset = get_reloc_offset(ss, ss->relocs.data[i], true);
819 if (sym->value + offset == 0)
820 continue;
821 if (bfd_is_const_section(sym->section))
822 continue;
823 struct supersect *sym_ss = fetch_supersect(ss->parent,
824 sym->section);
825 if (sym_ss->type != SS_TYPE_TEXT)
826 continue;
827 if (!sym_ss->patch) {
828 changed = true;
829 debug1(ss->parent,
830 "Changing %s because a relocation from sect %s "
831 "has a nonzero offset %lx+%lx into it\n",
832 sym_ss->name, ss->name,
833 (unsigned long)sym->value,
834 (unsigned long)offset);
836 sym_ss->patch = true;
840 static void update_nonzero_offsets(struct superbfd *sbfd)
842 asection *sect;
843 struct supersect *ss;
845 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
846 ss = fetch_supersect(sbfd, sect);
847 if (ss->new || ss->patch)
848 handle_nonzero_offset_relocs(ss);
852 static void compare_matched_sections(struct superbfd *newsbfd)
854 asection *newp;
855 struct supersect *old_ss, *new_ss;
856 for (newp = newsbfd->abfd->sections; newp != NULL; newp = newp->next) {
857 new_ss = fetch_supersect(newsbfd, newp);
858 if (new_ss->match == NULL)
859 continue;
860 old_ss = new_ss->match;
862 if (nonrelocs_equal(old_ss, new_ss) &&
863 all_relocs_equal(old_ss, new_ss))
864 continue;
866 char *reason;
867 if (new_ss->contents.size != old_ss->contents.size)
868 reason = "differing sizes";
869 else if (memcmp(new_ss->contents.data, old_ss->contents.data,
870 new_ss->contents.size) != 0)
871 reason = "differing contents";
872 else
873 reason = "differing relocations";
874 if (new_ss->type == SS_TYPE_TEXT) {
875 if (new_ss->patch)
876 continue;
877 new_ss->patch = true;
878 debug1(newsbfd, "Changing %s due to %s\n", new_ss->name,
879 reason);
880 } else {
881 debug1(newsbfd, "Unmatching %s and %s due to %s\n",
882 old_ss->name, new_ss->name, reason);
883 new_ss->match = NULL;
884 old_ss->match = NULL;
886 changed = true;
887 if (unchangeable_section(new_ss))
888 err(newsbfd, "warning: ignoring change to nonpatchable "
889 "section %s\n", new_ss->name);
893 static void handle_section_symbol_renames(struct superbfd *oldsbfd,
894 struct superbfd *newsbfd)
896 asection *newp, *oldp;
897 for (newp = newsbfd->abfd->sections; newp != NULL; newp = newp->next) {
898 struct supersect *newss = fetch_supersect(newsbfd, newp);
899 if (newss->match == NULL)
900 continue;
901 oldp = bfd_get_section_by_name(oldsbfd->abfd,
902 newss->match->name);
903 if (oldp == NULL)
904 continue;
906 const char *old_label = label_lookup(oldsbfd, oldp->symbol);
907 const char *new_label = label_lookup(newsbfd, newp->symbol);
909 if (strcmp(old_label, new_label) == 0)
910 continue;
911 label_map_set(newsbfd, new_label, old_label);
915 static bool part_of_reloc(struct supersect *ss, unsigned long addr)
917 arelent **relocp;
918 for (relocp = ss->relocs.data;
919 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
920 arelent *reloc = *relocp;
921 if (addr >= reloc->address &&
922 addr < reloc->address + reloc->howto->size)
923 return true;
925 return false;
928 static bool nonrelocs_equal(struct supersect *old_ss, struct supersect *new_ss)
930 int i;
931 if (old_ss->contents.size != new_ss->contents.size)
932 return false;
933 const unsigned char *old = old_ss->contents.data;
934 const unsigned char *new = new_ss->contents.data;
935 for (i = 0; i < old_ss->contents.size; i++) {
936 if (old[i] != new[i] &&
937 !(part_of_reloc(old_ss, i) && part_of_reloc(new_ss, i)))
938 return false;
940 return true;
943 bool relocs_equal(struct supersect *old_src_ss, struct supersect *new_src_ss,
944 arelent *old_reloc, arelent *new_reloc)
946 struct superbfd *oldsbfd = old_src_ss->parent;
947 struct superbfd *newsbfd = new_src_ss->parent;
949 if (old_reloc->address != new_reloc->address) {
950 debug1(newsbfd, "Section %s/%s has reloc address mismatch at "
951 "%lx\n", old_src_ss->name, new_src_ss->name,
952 (unsigned long)old_reloc->address);
953 return false;
956 if (old_reloc->howto != new_reloc->howto) {
957 debug1(newsbfd, "Section %s/%s has howto type mismatch at "
958 "%lx\n", old_src_ss->name, new_src_ss->name,
959 (unsigned long)old_reloc->address);
960 return false;
963 if (non_dst_mask(old_src_ss, old_reloc) !=
964 non_dst_mask(new_src_ss, new_reloc)) {
965 debug1(newsbfd, "Section %s/%s has contents mismatch at %lx\n",
966 old_src_ss->name, new_src_ss->name,
967 (unsigned long)old_reloc->address);
968 return false;
971 asymbol *old_sym = *old_reloc->sym_ptr_ptr;
972 asymbol *new_sym = *new_reloc->sym_ptr_ptr;
973 asection *old_sect = old_sym->section;
974 asection *new_sect = new_sym->section;
976 bfd_vma old_offset = get_reloc_offset(old_src_ss, old_reloc, true);
977 bfd_vma new_offset = get_reloc_offset(new_src_ss, new_reloc, true);
979 if (bfd_is_und_section(old_sect) || bfd_is_und_section(new_sect)) {
980 if (!bfd_is_und_section(new_sect) && old_offset != 0 &&
981 fetch_supersect(newsbfd, new_sect)->type == SS_TYPE_TEXT)
982 return false;
984 if (!bfd_is_und_section(new_sect) && new_offset != 0 &&
985 fetch_supersect(oldsbfd, old_sect)->type == SS_TYPE_TEXT)
986 return false;
988 return strcmp(old_sym->name, new_sym->name) == 0 &&
989 old_offset == new_offset;
992 if (bfd_is_const_section(old_sect) || bfd_is_const_section(new_sect))
993 DIE;
995 struct supersect *old_ss = fetch_supersect(oldsbfd, old_sect);
996 struct supersect *new_ss = fetch_supersect(newsbfd, new_sect);
998 if (old_ss->type == SS_TYPE_STRING &&
999 /* check it's not an out-of-range relocation to a string;
1000 we'll just compare entire sections for them */
1001 !(old_offset >= old_ss->contents.size ||
1002 new_offset >= new_ss->contents.size)) {
1003 if (strcmp(old_ss->contents.data + old_sym->value + old_offset,
1004 new_ss->contents.data + new_sym->value + new_offset)
1005 != 0) {
1006 debug0(newsbfd, "Section %s/%s has string difference "
1007 "\"%s\"/\"%s\"\n", old_src_ss->name,
1008 new_src_ss->name,
1009 (const char *)(old_ss->contents.data +
1010 old_sym->value + old_offset),
1011 (const char *)(new_ss->contents.data +
1012 new_sym->value + new_offset));
1013 debug1(newsbfd, "Strings differ between %s and %s\n",
1014 old_src_ss->name, new_src_ss->name);
1015 return false;
1017 return true;
1020 if (old_ss->match != new_ss || new_ss->match != old_ss) {
1021 debug1(newsbfd, "Nonmatching relocs from %s to %s/%s\n",
1022 new_src_ss->name, new_ss->name, old_ss->name);
1023 return false;
1026 if (old_sym->value + old_offset != new_sym->value + new_offset) {
1027 debug1(newsbfd, "Offsets to %s/%s differ between %s "
1028 "and %s: %lx+%lx/%lx+%lx\n", old_ss->name,
1029 new_ss->name, old_src_ss->name, new_src_ss->name,
1030 (unsigned long)old_sym->value, (unsigned long)old_offset,
1031 (unsigned long)new_sym->value,
1032 (unsigned long)new_offset);
1033 return false;
1036 if ((old_sym->value + old_offset != 0 ||
1037 new_sym->value + new_offset != 0) && new_ss->patch) {
1038 debug1(newsbfd, "Relocation from %s to nonzero offsets "
1039 "%lx+%lx/%lx+%lx in changed section %s\n",
1040 new_src_ss->name, (unsigned long)old_sym->value,
1041 (unsigned long)old_offset, (unsigned long)new_sym->value,
1042 (unsigned long)new_offset, new_sym->section->name);
1043 return false;
1045 return true;
1048 bool all_relocs_equal(struct supersect *old_ss, struct supersect *new_ss)
1050 if (old_ss->relocs.size != new_ss->relocs.size) {
1051 debug1(new_ss->parent, "Different reloc count between %s and "
1052 "%s\n", old_ss->name, new_ss->name);
1053 return false;
1056 int i;
1057 for (i = 0; i < old_ss->relocs.size; i++) {
1058 if (!relocs_equal(old_ss, new_ss, old_ss->relocs.data[i],
1059 new_ss->relocs.data[i]))
1060 return false;
1063 return true;
1066 bfd_vma non_dst_mask(struct supersect *ss, arelent *reloc)
1068 int bits = bfd_get_reloc_size(reloc->howto) * 8;
1069 void *address = ss->contents.data + reloc->address;
1070 bfd_vma x = bfd_get(bits, ss->parent->abfd, address);
1071 return x & ~reloc->howto->dst_mask;
1074 void rm_some_exports(struct superbfd *sbfd, const struct export_desc *ed)
1076 struct supersect *ss = ed->sym_ss;
1077 struct supersect *crc_ss = ed->crc_ss;
1078 if (crc_ss != NULL)
1079 assert(ss->contents.size * sizeof(unsigned long) ==
1080 crc_ss->contents.size * sizeof(struct kernel_symbol));
1082 struct kernel_symbol *ksym;
1083 unsigned long *crc = NULL;
1084 if (crc_ss != NULL)
1085 crc = crc_ss->contents.data;
1086 struct span *span, *crc_span;
1087 for (ksym = ss->contents.data;
1088 (void *)ksym < ss->contents.data + ss->contents.size;
1089 ksym++, crc++) {
1090 asymbol *sym;
1091 read_reloc(ss, &ksym->value, sizeof(ksym->value), &sym);
1092 span = new_span(ss, addr_offset(ss, ksym), sizeof(*ksym));
1093 span->keep = str_in_set(sym->name, &ed->names);
1095 if (crc_ss != NULL) {
1096 crc_span = new_span(crc_ss, addr_offset(crc_ss, crc),
1097 sizeof(*crc));
1098 crc_span->keep = span->keep;
1101 if (span->keep) {
1102 /* Replace name with a mangled name */
1103 write_string(ss, (const char **)&ksym->name,
1104 "DISABLED_%s_%s", sym->name, kid);
1109 void rm_relocs(struct superbfd *isbfd)
1111 asection *p;
1112 for (p = isbfd->abfd->sections; p != NULL; p = p->next) {
1113 struct supersect *ss = fetch_supersect(isbfd, p);
1114 if ((mode("keep") && ss->type == SS_TYPE_SPECIAL) ||
1115 ss->type == SS_TYPE_KSPLICE)
1116 continue;
1117 if (ss->keep || mode("rmsyms"))
1118 rm_some_relocs(ss);
1120 if (mode("finalize")) {
1121 p = bfd_get_section_by_name(isbfd->abfd, ".ksplice_patches");
1122 if (p != NULL) {
1123 struct supersect *ss = fetch_supersect(isbfd, p);
1124 rm_some_relocs(ss);
1126 p = bfd_get_section_by_name(isbfd->abfd, ".ksplice_relocs");
1127 if (p != NULL) {
1128 struct supersect *ss = fetch_supersect(isbfd, p);
1129 rm_some_relocs(ss);
1134 void rm_some_relocs(struct supersect *ss)
1136 struct arelentp_vec orig_relocs;
1137 vec_move(&orig_relocs, &ss->relocs);
1139 arelent **relocp;
1140 for (relocp = orig_relocs.data;
1141 relocp < orig_relocs.data + orig_relocs.size; relocp++) {
1142 bool rm_reloc = false;
1143 asymbol *sym_ptr = *(*relocp)->sym_ptr_ptr;
1145 if (mode("rmsyms") && str_in_set(sym_ptr->name, &rmsyms) &&
1146 bfd_is_und_section(sym_ptr->section))
1147 rm_reloc = true;
1149 if (mode("keep"))
1150 rm_reloc = true;
1152 if (mode("keep-primary") &&
1153 (bfd_is_const_section(sym_ptr->section) ||
1154 fetch_supersect(ss->parent, sym_ptr->section)->new ||
1155 reloc_target_span(ss, *relocp)->new ||
1156 !reloc_address_span(ss, *relocp)->keep))
1157 rm_reloc = false;
1159 if (mode("finalize") && bfd_is_und_section(sym_ptr->section))
1160 rm_reloc = true;
1162 if (strcmp(sym_ptr->name, "mcount") == 0 &&
1163 bfd_is_und_section(sym_ptr->section))
1164 rm_reloc = false;
1166 if (rm_reloc)
1167 write_ksplice_reloc(ss, *relocp);
1168 else
1169 *vec_grow(&ss->relocs, 1) = *relocp;
1173 struct supersect *make_section(struct superbfd *sbfd, const char *name)
1175 asection *sect = bfd_get_section_by_name(sbfd->abfd, name);
1176 if (sect != NULL)
1177 return fetch_supersect(sbfd, sect);
1178 else
1179 return new_supersect(sbfd, name);
1182 arelent *create_reloc(struct supersect *ss, const void *addr, asymbol **symp,
1183 bfd_vma offset)
1185 bfd_reloc_code_real_type code;
1186 switch (bfd_arch_bits_per_address(ss->parent->abfd)) {
1187 case 32:
1188 code = BFD_RELOC_32;
1189 break;
1190 case 64:
1191 code = BFD_RELOC_64;
1192 break;
1193 default:
1194 DIE;
1197 arelent *reloc = malloc(sizeof(*reloc));
1198 reloc->sym_ptr_ptr = symp;
1199 reloc->address = addr_offset(ss, addr);
1200 reloc->howto = bfd_reloc_type_lookup(ss->parent->abfd, code);
1201 reloc->addend = offset;
1202 return reloc;
1205 void write_reloc(struct supersect *ss, const void *addr, asymbol **symp,
1206 bfd_vma offset)
1208 *vec_grow(&ss->new_relocs, 1) = create_reloc(ss, addr, symp, offset);
1211 void write_string(struct supersect *ss, const char **addr, const char *fmt, ...)
1213 va_list ap;
1214 struct supersect *str_ss = make_section(ss->parent, ".ksplice_str");
1215 char *str;
1216 va_start(ap, fmt);
1217 int len = vasprintf(&str, fmt, ap);
1218 assert(len >= 0);
1219 va_end(ap);
1221 unsigned long *str_offp = ulong_hash_lookup(&ksplice_string_offset, str,
1222 FALSE);
1223 if (str_offp == NULL) {
1224 char *buf = sect_grow(str_ss, len + 1, char);
1225 memcpy(buf, str, len + 1);
1226 str_offp = ulong_hash_lookup(&ksplice_string_offset, str, TRUE);
1227 *str_offp = addr_offset(str_ss, buf);
1230 write_reloc(ss, addr, &str_ss->symbol, *str_offp);
1233 void lookup_system_map(struct addr_vec *addrs, const char *name, long offset)
1235 struct addr_vec *map_addrs =
1236 addr_vec_hash_lookup(&system_map, name, FALSE);
1237 if (map_addrs == NULL)
1238 return;
1240 unsigned long *addr, *map_addr;
1241 for (map_addr = map_addrs->data;
1242 map_addr < map_addrs->data + map_addrs->size; map_addr++) {
1243 for (addr = addrs->data; addr < addrs->data + addrs->size;
1244 addr++) {
1245 if (*addr == *map_addr + offset)
1246 break;
1248 if (addr < addrs->data + addrs->size)
1249 continue;
1250 *vec_grow(addrs, 1) = *map_addr + offset;
1254 void compute_system_map_array(struct superbfd *sbfd, struct addr_vec *addrs,
1255 asymbol *sym)
1257 if (bfd_is_abs_section(sym->section)) {
1258 *vec_grow(addrs, 1) = sym->value;
1259 } else if (bfd_is_und_section(sym->section)) {
1260 lookup_system_map(addrs, sym->name, 0);
1261 } else if (!bfd_is_const_section(sym->section)) {
1262 asymbol **gsymp;
1263 for (gsymp = sbfd->syms.data;
1264 gsymp < sbfd->syms.data + sbfd->syms.size; gsymp++) {
1265 asymbol *gsym = *gsymp;
1266 if ((gsym->flags & BSF_DEBUGGING) == 0 &&
1267 gsym->section == sym->section)
1268 lookup_system_map(addrs, gsym->name,
1269 sym->value - gsym->value);
1274 void write_ksplice_system_map(struct superbfd *sbfd, asymbol *sym,
1275 const char *label)
1277 bool *done = bool_hash_lookup(&system_map_written, label, TRUE);
1278 if (*done)
1279 return;
1280 *done = true;
1282 struct addr_vec addrs;
1283 vec_init(&addrs);
1285 compute_system_map_array(sbfd, &addrs, sym);
1286 if (addrs.size != 0) {
1287 struct supersect *smap_ss =
1288 make_section(sbfd, ".ksplice_system_map");
1289 struct ksplice_system_map *smap =
1290 sect_grow(smap_ss, 1, struct ksplice_system_map);
1291 write_string(smap_ss, &smap->label, "%s", label);
1293 struct supersect *array_ss = make_section(sbfd,
1294 ".ksplice_array");
1295 void *buf = sect_grow(array_ss, addrs.size,
1296 typeof(*addrs.data));
1297 memcpy(buf, addrs.data, addrs.size * sizeof(*addrs.data));
1298 smap->nr_candidates = addrs.size;
1299 write_reloc(smap_ss, &smap->candidates, &array_ss->symbol,
1300 addr_offset(array_ss, buf));
1302 vec_free(&addrs);
1305 void write_ksplice_symbol_backend(struct supersect *ss,
1306 struct ksplice_symbol *const *addr,
1307 asymbol *sym, const char *label,
1308 const char *name)
1310 struct supersect *ksymbol_ss = make_section(ss->parent,
1311 ".ksplice_symbols");
1312 struct ksplice_symbol *ksymbol;
1313 unsigned long *ksymbol_offp;
1315 ksymbol_offp = ulong_hash_lookup(&ksplice_symbol_offset, label, FALSE);
1316 if (ksymbol_offp != NULL) {
1317 write_reloc(ss, addr, &ksymbol_ss->symbol, *ksymbol_offp);
1318 return;
1320 ksymbol = sect_grow(ksymbol_ss, 1, struct ksplice_symbol);
1321 ksymbol_offp = ulong_hash_lookup(&ksplice_symbol_offset, label, TRUE);
1322 *ksymbol_offp = addr_offset(ksymbol_ss, ksymbol);
1324 write_reloc(ss, addr, &ksymbol_ss->symbol, *ksymbol_offp);
1325 write_string(ksymbol_ss, &ksymbol->label, "%s", label);
1326 if (name != NULL) {
1327 write_string(ksymbol_ss, &ksymbol->name, "%s", name);
1328 write_ksplice_system_map(ksymbol_ss->parent, sym, label);
1332 void write_ksplice_symbol(struct supersect *ss,
1333 struct ksplice_symbol *const *addr,
1334 asymbol *sym, struct span *span,
1335 const char *addstr_sect)
1337 const char *label, *name;
1338 char *output;
1339 if (span != NULL && span->start != 0)
1340 label = span->label;
1341 else
1342 label = label_lookup(ss->parent, sym);
1344 assert(asprintf(&output, "%s%s", label, addstr_sect) >= 0);
1346 asymbol *gsym = canonical_symbol(ss->parent, sym);
1347 if (strcmp(addstr_sect, "") != 0)
1348 name = NULL;
1349 else if (bfd_is_und_section(sym->section))
1350 name = sym->name;
1351 else if (bfd_is_const_section(sym->section))
1352 name = NULL;
1353 else if (span != NULL && span->symbol == NULL)
1354 name = NULL;
1355 else if (gsym == NULL || (gsym->flags & BSF_SECTION_SYM) != 0)
1356 name = NULL;
1357 else
1358 name = gsym->name;
1360 write_ksplice_symbol_backend(ss, addr, sym, output, name);
1363 void write_ksplice_reloc(struct supersect *ss, arelent *orig_reloc)
1365 asymbol *sym_ptr = *orig_reloc->sym_ptr_ptr;
1366 reloc_howto_type *howto = orig_reloc->howto;
1367 bfd_vma addend = get_reloc_offset(ss, orig_reloc, false);
1368 unsigned long *repladdr = ss->contents.data + orig_reloc->address;
1370 if (mode("finalize") && strcmp(ss->name, ".ksplice_patches") == 0) {
1371 *repladdr = 0;
1372 return;
1374 if (mode("finalize") && strcmp(ss->name, ".ksplice_relocs") == 0) {
1375 assert(starts_with(sym_ptr->name, KSPLICE_SYMBOL_STR));
1376 asymbol fake_sym;
1377 fake_sym.name = sym_ptr->name + strlen(KSPLICE_SYMBOL_STR);
1378 fake_sym.section = bfd_und_section_ptr;
1379 fake_sym.value = 0;
1380 fake_sym.flags = 0;
1382 write_ksplice_symbol_backend
1383 (ss, (struct ksplice_symbol **)repladdr, &fake_sym,
1384 fake_sym.name, fake_sym.name);
1385 return;
1388 struct span *span = reloc_target_span(ss, orig_reloc);
1389 if (span == ss->spans.data && span->start != addend)
1390 span = NULL;
1391 blot_section(ss, orig_reloc->address, howto);
1393 struct supersect *kreloc_ss = make_section(ss->parent,
1394 mode("rmsyms") ?
1395 ".ksplice_init_relocs" :
1396 ".ksplice_relocs");
1397 struct ksplice_reloc *kreloc = sect_grow(kreloc_ss, 1,
1398 struct ksplice_reloc);
1400 struct span *address_span = reloc_address_span(ss, orig_reloc);
1401 write_reloc(kreloc_ss, &kreloc->blank_addr,
1402 &ss->symbol, orig_reloc->address + address_span->shift);
1403 if (bfd_is_und_section(sym_ptr->section) && mode("keep")) {
1404 char *name;
1405 assert(asprintf(&name, KSPLICE_SYMBOL_STR "%s", sym_ptr->name)
1406 >= 0);
1407 asymbol **symp = make_undefined_symbolp(ss->parent, name);
1408 write_reloc(kreloc_ss, &kreloc->symbol, symp, 0);
1409 } else {
1410 write_ksplice_symbol(kreloc_ss, &kreloc->symbol, sym_ptr, span,
1411 "");
1413 kreloc->pcrel = howto->pc_relative;
1414 if (span != NULL && span->start != 0)
1415 addend += sym_ptr->value - span->start;
1416 kreloc->addend = addend;
1417 kreloc->size = bfd_get_reloc_size(howto);
1418 kreloc->dst_mask = howto->dst_mask;
1419 kreloc->rightshift = howto->rightshift;
1420 kreloc->signed_addend =
1421 (howto->complain_on_overflow == complain_overflow_signed) ||
1422 (howto->complain_on_overflow == complain_overflow_bitfield);
1425 #define CANARY(x, canary) ((x & ~howto->dst_mask) | (canary & howto->dst_mask))
1427 void blot_section(struct supersect *ss, int offset, reloc_howto_type *howto)
1429 int bits = bfd_get_reloc_size(howto) * 8;
1430 void *address = ss->contents.data + offset;
1431 bfd_vma x = bfd_get(bits, ss->parent->abfd, address);
1432 x = (x & ~howto->dst_mask) |
1433 ((bfd_vma)KSPLICE_CANARY & howto->dst_mask);
1434 bfd_put(bits, ss->parent->abfd, x, address);
1437 static void write_ksplice_section(struct span *span)
1439 struct supersect *ss = span->ss;
1440 struct supersect *ksect_ss =
1441 make_section(ss->parent, ".ksplice_sections");
1442 struct ksplice_section *ksect = sect_grow(ksect_ss, 1,
1443 struct ksplice_section);
1444 asymbol *sym = span->symbol == NULL ? ss->symbol : span->symbol;
1446 write_ksplice_symbol(ksect_ss, &ksect->symbol, sym, span,
1447 mode("keep-primary") ? "(post)" : "");
1448 ksect->size = span->size;
1449 ksect->flags = 0;
1451 if (ss->type == SS_TYPE_RODATA || ss->type == SS_TYPE_STRING)
1452 ksect->flags |= KSPLICE_SECTION_RODATA;
1453 if (ss->type == SS_TYPE_DATA)
1454 ksect->flags |= KSPLICE_SECTION_DATA;
1455 if (ss->type == SS_TYPE_TEXT)
1456 ksect->flags |= KSPLICE_SECTION_TEXT;
1457 assert(ksect->flags != 0);
1458 write_reloc(ksect_ss, &ksect->address, &ss->symbol,
1459 span->start + span->shift);
1462 void write_ksplice_patch(struct superbfd *sbfd, const char *sectname)
1464 struct supersect *kpatch_ss = make_section(sbfd, ".ksplice_patches");
1465 struct ksplice_patch *kpatch = sect_grow(kpatch_ss, 1,
1466 struct ksplice_patch);
1467 asection *sect = bfd_get_section_by_name(sbfd->abfd, sectname);
1468 assert(sect != NULL);
1470 write_string(kpatch_ss, &kpatch->label, "%s",
1471 label_lookup(sbfd, sect->symbol));
1472 write_reloc(kpatch_ss, &kpatch->repladdr, &sect->symbol, 0);
1475 asymbol **make_undefined_symbolp(struct superbfd *sbfd, const char *name)
1477 asymbol **symp;
1478 for (symp = sbfd->syms.data; symp < sbfd->syms.data + sbfd->syms.size;
1479 symp++) {
1480 asymbol *sym = *symp;
1481 if (strcmp(name, sym->name) == 0 &&
1482 bfd_is_und_section(sym->section))
1483 return symp;
1485 asymbol ***sympp;
1486 for (sympp = sbfd->new_syms.data;
1487 sympp < sbfd->new_syms.data + sbfd->new_syms.size; sympp++) {
1488 asymbol **symp = *sympp;
1489 asymbol *sym = *symp;
1490 if (strcmp(name, sym->name) == 0 &&
1491 bfd_is_und_section(sym->section))
1492 return symp;
1495 symp = malloc(sizeof(*symp));
1496 *symp = bfd_make_empty_symbol(sbfd->abfd);
1497 asymbol *sym = *symp;
1498 sym->name = name;
1499 sym->section = bfd_und_section_ptr;
1500 sym->flags = 0;
1501 sym->value = 0;
1502 *vec_grow(&sbfd->new_syms, 1) = symp;
1503 return symp;
1506 void write_ksplice_deleted_patch(struct superbfd *sbfd, const char *name,
1507 const char *label)
1509 struct supersect *kpatch_ss = make_section(sbfd, ".ksplice_patches");
1510 struct ksplice_patch *kpatch = sect_grow(kpatch_ss, 1,
1511 struct ksplice_patch);
1513 write_string(kpatch_ss, &kpatch->label, "%s", label);
1514 asymbol **symp = make_undefined_symbolp(sbfd, strdup(name));
1515 write_reloc(kpatch_ss, &kpatch->repladdr, symp, 0);
1518 void write_ksplice_export(struct superbfd *sbfd, const char *symname,
1519 const char *export_type, bool del)
1521 struct supersect *export_ss = make_section(sbfd, ".ksplice_exports");
1522 struct ksplice_export *exp = sect_grow(export_ss, 1,
1523 struct ksplice_export);
1525 if (del) {
1526 write_string(export_ss, &exp->name, "%s", symname);
1527 write_string(export_ss, &exp->new_name, "DISABLED_%s_%s",
1528 symname, kid);
1529 } else {
1530 write_string(export_ss, &exp->new_name, "%s", symname);
1531 write_string(export_ss, &exp->name, "DISABLED_%s_%s", symname,
1532 kid);
1536 struct fixup_entry {
1537 bfd_vma offset;
1538 bool used;
1540 DECLARE_VEC_TYPE(struct fixup_entry, fixup_entry_vec);
1542 int compare_fixups(const void *aptr, const void *bptr)
1544 const struct fixup_entry *a = aptr, *b = bptr;
1545 if (a->offset < b->offset)
1546 return -1;
1547 else if (a->offset > b->offset)
1548 return 1;
1549 else
1550 return (int)a->used - (int)b->used;
1553 void filter_table_sections(struct superbfd *isbfd)
1555 struct supersect *tables_ss =
1556 fetch_supersect(offsets_sbfd,
1557 bfd_get_section_by_name(offsets_sbfd->abfd,
1558 ".ksplice_table_sections"));
1559 const struct table_section *ts;
1560 for (ts = tables_ss->contents.data;
1561 (void *)ts < tables_ss->contents.data + tables_ss->contents.size;
1562 ts++) {
1563 struct table_section s = *ts;
1564 s.sect = read_string(tables_ss, &ts->sect);
1565 s.other_sect = read_string(tables_ss, &ts->other_sect);
1566 filter_table_section(isbfd, &s);
1570 void filter_table_section(struct superbfd *sbfd, const struct table_section *s)
1572 asection *isection = bfd_get_section_by_name(sbfd->abfd, s->sect);
1573 if (isection == NULL)
1574 return;
1575 asection *fixup_sect = NULL;
1576 if (s->other_sect != NULL)
1577 fixup_sect = bfd_get_section_by_name(sbfd->abfd, s->other_sect);
1579 struct supersect *ss = fetch_supersect(sbfd, isection);
1580 if (ss->alignment < ffs(s->entry_align) - 1)
1581 ss->alignment = ffs(s->entry_align) - 1;
1583 struct supersect *fixup_ss = NULL;
1584 if (fixup_sect != NULL)
1585 fixup_ss = fetch_supersect(sbfd, fixup_sect);
1587 struct fixup_entry_vec fixups;
1588 vec_init(&fixups);
1590 void *entry;
1591 for (entry = ss->contents.data;
1592 entry < ss->contents.data + ss->contents.size;
1593 entry += s->entry_size) {
1594 asymbol *sym, *fixup_sym;
1595 read_reloc(ss, entry + s->addr_offset, sizeof(void *), &sym);
1597 struct span *span = new_span(ss, addr_offset(ss, entry),
1598 s->entry_size);
1599 struct supersect *sym_ss = fetch_supersect(sbfd, sym->section);
1600 span->keep = sym_ss->keep;
1602 struct fixup_entry *f;
1603 if (fixup_sect != NULL) {
1604 bfd_vma fixup_offset =
1605 read_reloc(ss, entry + s->other_offset,
1606 sizeof(void *), &fixup_sym);
1607 if (fixup_sym->section == fixup_sect) {
1608 assert(fixup_offset < fixup_ss->contents.size);
1609 f = vec_grow(&fixups, 1);
1610 f->offset = fixup_offset;
1611 f->used = span->keep;
1616 if (fixup_sect == NULL)
1617 return;
1619 qsort(fixups.data, fixups.size, sizeof(*fixups.data), compare_fixups);
1620 *vec_grow(&fixups, 1) = (struct fixup_entry)
1621 { .offset = fixup_ss->contents.size, .used = false };
1623 struct fixup_entry *f;
1624 for (f = fixups.data; f < fixups.data + fixups.size - 1; f++) {
1625 struct span *span = new_span(fixup_ss, f->offset,
1626 (f + 1)->offset - f->offset);
1627 span->keep = f->used;
1631 void keep_referenced_sections(struct superbfd *sbfd)
1633 asection *sect;
1634 struct supersect *ss, *sym_ss;
1635 struct span *address_span, *target_span;
1636 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
1637 ss = fetch_supersect(sbfd, sect);
1638 arelent **relocp;
1639 if (ss->type == SS_TYPE_SPECIAL || ss->type == SS_TYPE_EXPORT)
1640 continue;
1641 for (relocp = ss->relocs.data;
1642 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
1643 asymbol *sym = *(*relocp)->sym_ptr_ptr;
1644 address_span = reloc_address_span(ss, *relocp);
1645 if (!address_span->keep)
1646 continue;
1647 target_span = reloc_target_span(ss, *relocp);
1648 if (target_span == NULL || target_span->keep)
1649 continue;
1650 sym_ss = fetch_supersect(sbfd, sym->section);
1651 if (sym_ss->type == SS_TYPE_IGNORED)
1652 continue;
1653 target_span->keep = true;
1654 sym_ss->keep = true;
1655 changed = true;
1660 void copy_symbols(struct asymbolp_vec *osyms, struct asymbolpp_vec *isyms)
1662 asymbol ***sympp;
1663 for (sympp = isyms->data; sympp < isyms->data + isyms->size; sympp++)
1664 *vec_grow(osyms, 1) = **sympp;
1667 /* Modified function from GNU Binutils objcopy.c */
1668 bfd_boolean copy_object(bfd *ibfd, bfd *obfd)
1670 assert(bfd_set_format(obfd, bfd_get_format(ibfd)));
1672 bfd_vma start = bfd_get_start_address(ibfd);
1674 flagword flags = bfd_get_file_flags(ibfd);
1675 flags &= bfd_applicable_file_flags(obfd);
1677 assert(bfd_set_start_address(obfd, start)
1678 && bfd_set_file_flags(obfd, flags));
1680 enum bfd_architecture iarch = bfd_get_arch(ibfd);
1681 unsigned int imach = bfd_get_mach(ibfd);
1682 assert(bfd_set_arch_mach(obfd, iarch, imach));
1683 assert(bfd_set_format(obfd, bfd_get_format(ibfd)));
1685 /* BFD mandates that all output sections be created and sizes set before
1686 any output is done. Thus, we traverse all sections multiple times. */
1687 bfd_map_over_sections(ibfd, setup_section, obfd);
1689 struct supersect *new_supersects = fetch_superbfd(ibfd)->new_supersects;
1690 struct supersect *ss;
1691 for (ss = new_supersects; ss != NULL; ss = ss->next)
1692 setup_new_section(obfd, ss);
1694 /* Mark symbols used in output relocations so that they
1695 are kept, even if they are local labels or static symbols.
1697 Note we iterate over the input sections examining their
1698 relocations since the relocations for the output sections
1699 haven't been set yet. mark_symbols_used_in_relocations will
1700 ignore input sections which have no corresponding output
1701 section. */
1703 bfd_map_over_sections(ibfd, mark_symbols_used_in_relocations, NULL);
1704 for (ss = new_supersects; ss != NULL; ss = ss->next)
1705 ss_mark_symbols_used_in_relocations(ss);
1706 struct asymbolp_vec osyms;
1707 vec_init(&osyms);
1708 filter_symbols(ibfd, obfd, &osyms, &fetch_superbfd(ibfd)->syms);
1709 copy_symbols(&osyms, &fetch_superbfd(ibfd)->new_syms);
1711 bfd_set_symtab(obfd, osyms.data, osyms.size);
1713 /* This has to happen after the symbol table has been set. */
1714 bfd_map_over_sections(obfd, write_section, NULL);
1716 /* Allow the BFD backend to copy any private data it understands
1717 from the input BFD to the output BFD. This is done last to
1718 permit the routine to look at the filtered symbol table, which is
1719 important for the ECOFF code at least. */
1720 assert(bfd_copy_private_bfd_data(ibfd, obfd));
1722 return TRUE;
1725 /* Modified function from GNU Binutils objcopy.c */
1726 void setup_section(bfd *ibfd, asection *isection, void *obfdarg)
1728 struct superbfd *isbfd = fetch_superbfd(ibfd);
1729 struct supersect *ss = fetch_supersect(isbfd, isection);
1730 bfd *obfd = obfdarg;
1731 bfd_vma vma;
1733 if (!ss->keep)
1734 return;
1736 asection *osection = bfd_make_section_anyway(obfd, isection->name);
1737 assert(osection != NULL);
1739 osection->userdata = ss;
1740 bfd_set_section_flags(obfd, osection, ss->flags);
1741 ss->symbol = osection->symbol;
1742 assert(bfd_set_section_size(obfd, osection, ss->contents.size));
1744 vma = bfd_section_vma(ibfd, isection);
1745 assert(bfd_set_section_vma(obfd, osection, vma));
1747 osection->lma = isection->lma;
1748 assert(bfd_set_section_alignment(obfd, osection, ss->alignment));
1749 osection->entsize = isection->entsize;
1750 osection->output_section = osection;
1751 osection->output_offset = 0;
1752 isection->output_section = osection;
1753 isection->output_offset = 0;
1754 return;
1757 void setup_new_section(bfd *obfd, struct supersect *ss)
1759 asection *osection = bfd_make_section_anyway(obfd, ss->name);
1760 assert(osection != NULL);
1761 bfd_set_section_flags(obfd, osection, ss->flags);
1763 osection->userdata = ss;
1764 ss->symbol = osection->symbol;
1765 assert(bfd_set_section_size(obfd, osection, ss->contents.size));
1766 assert(bfd_set_section_vma(obfd, osection, 0));
1768 osection->lma = 0;
1769 assert(bfd_set_section_alignment(obfd, osection, ss->alignment));
1770 osection->entsize = 0;
1771 osection->output_section = osection;
1772 osection->output_offset = 0;
1775 static int compare_reloc_addresses(const void *aptr, const void *bptr)
1777 const arelent *const *a = aptr, *const *b = bptr;
1778 return (*a)->address - (*b)->address;
1781 static void delete_obsolete_relocs(struct supersect *ss)
1783 if (ss->new_relocs.size == 0)
1784 return;
1786 qsort(ss->relocs.data, ss->relocs.size, sizeof(*ss->relocs.data),
1787 compare_reloc_addresses);
1788 qsort(ss->new_relocs.data, ss->new_relocs.size,
1789 sizeof(*ss->new_relocs.data), compare_reloc_addresses);
1791 struct arelentp_vec orig_relocs;
1792 vec_move(&orig_relocs, &ss->relocs);
1794 arelent **relocp, **new_relocp = ss->new_relocs.data;
1795 for (relocp = orig_relocs.data;
1796 relocp < orig_relocs.data + orig_relocs.size; relocp++) {
1797 while (new_relocp < ss->new_relocs.data + ss->new_relocs.size &&
1798 (*new_relocp)->address < (*relocp)->address)
1799 new_relocp++;
1800 arelent *reloc = *relocp, *new_reloc = *new_relocp;
1801 if (new_relocp == ss->new_relocs.data + ss->new_relocs.size ||
1802 reloc->address != new_reloc->address)
1803 *vec_grow(&ss->relocs, 1) = reloc;
1807 void write_section(bfd *obfd, asection *osection, void *arg)
1809 struct supersect *ss = osection->userdata;
1811 if ((ss->flags & SEC_GROUP) != 0 || ss->contents.size == 0)
1812 return;
1814 delete_obsolete_relocs(ss);
1816 arelent **relocp;
1817 char *error_message;
1818 for (relocp = ss->new_relocs.data;
1819 relocp < ss->new_relocs.data + ss->new_relocs.size; relocp++) {
1820 bfd_vma val;
1821 if (bfd_get_arch(obfd) == bfd_arch_arm)
1822 val = osection->use_rela_p ? 0 : (*relocp)->addend;
1823 else
1824 val = 0;
1825 bfd_put(bfd_get_reloc_size((*relocp)->howto) * 8, obfd, val,
1826 ss->contents.data + (*relocp)->address);
1827 if (bfd_install_relocation(obfd, *relocp, ss->contents.data,
1828 0, osection, &error_message) !=
1829 bfd_reloc_ok) {
1830 err(ss->parent, "ksplice: error installing reloc: %s",
1831 error_message);
1832 DIE;
1835 memcpy(vec_grow(&ss->relocs, ss->new_relocs.size), ss->new_relocs.data,
1836 ss->new_relocs.size * sizeof(*ss->new_relocs.data));
1838 bfd_set_reloc(obfd, osection,
1839 ss->relocs.size == 0 ? NULL : ss->relocs.data,
1840 ss->relocs.size);
1842 if (ss->flags & SEC_HAS_CONTENTS)
1843 assert(bfd_set_section_contents
1844 (obfd, osection, ss->contents.data, 0,
1845 ss->contents.size));
1848 /* Modified function from GNU Binutils objcopy.c
1850 * Mark all the symbols which will be used in output relocations with
1851 * the BSF_KEEP flag so that those symbols will not be stripped.
1853 * Ignore relocations which will not appear in the output file.
1855 void mark_symbols_used_in_relocations(bfd *abfd, asection *isection,
1856 void *ignored)
1858 struct superbfd *sbfd = fetch_superbfd(abfd);
1859 if (isection->output_section == NULL)
1860 return;
1862 struct supersect *ss = fetch_supersect(sbfd, isection);
1863 ss_mark_symbols_used_in_relocations(ss);
1866 void ss_mark_symbols_used_in_relocations(struct supersect *ss)
1868 /* Examine each symbol used in a relocation. If it's not one of the
1869 special bfd section symbols, then mark it with BSF_KEEP. */
1870 arelent **relocp;
1871 for (relocp = ss->relocs.data;
1872 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
1873 asymbol *sym = *(*relocp)->sym_ptr_ptr;
1874 if (!(bfd_is_const_section(sym->section) &&
1875 sym == sym->section->symbol))
1876 sym->flags |= BSF_KEEP;
1878 for (relocp = ss->new_relocs.data;
1879 relocp < ss->new_relocs.data + ss->new_relocs.size; relocp++) {
1880 asymbol *sym = *(*relocp)->sym_ptr_ptr;
1881 if (!(bfd_is_const_section(sym->section) &&
1882 sym == sym->section->symbol))
1883 sym->flags |= BSF_KEEP;
1887 static bool deleted_table_section_symbol(bfd *abfd, asymbol *sym)
1889 struct superbfd *sbfd = fetch_superbfd(abfd);
1890 if (bfd_is_const_section(sym->section))
1891 return false;
1892 struct supersect *ss = fetch_supersect(sbfd, sym->section);
1894 asymbol **symp;
1895 for (symp = ss->syms.data; symp < ss->syms.data + ss->syms.size; symp++) {
1896 if (sym == *symp)
1897 break;
1899 return symp >= ss->syms.data + ss->syms.size;
1902 /* Modified function from GNU Binutils objcopy.c
1904 * Choose which symbol entries to copy.
1905 * We don't copy in place, because that confuses the relocs.
1906 * Return the number of symbols to print.
1908 void filter_symbols(bfd *ibfd, bfd *obfd, struct asymbolp_vec *osyms,
1909 struct asymbolp_vec *isyms)
1911 asymbol **symp;
1912 struct superbfd *sbfd = fetch_superbfd(ibfd);
1913 for (symp = isyms->data; symp < isyms->data + isyms->size; symp++) {
1914 asymbol *sym = *symp;
1915 struct supersect *sym_ss = NULL;
1916 if (!bfd_is_const_section(sym->section))
1917 sym_ss = fetch_supersect(sbfd, sym->section);
1919 bool keep = false;
1921 if (mode("keep") && (sym->flags & BSF_GLOBAL) != 0 &&
1922 !(mode("keep-primary") && sym_ss != NULL && sym_ss->new))
1923 sym->flags = (sym->flags & ~BSF_GLOBAL) | BSF_LOCAL;
1925 if (mode("finalize") && (sym->flags & BSF_GLOBAL) != 0)
1926 sym->flags = (sym->flags & ~BSF_GLOBAL) | BSF_LOCAL;
1928 if ((sym->flags & BSF_KEEP) != 0 /* Used in relocation. */
1929 || ((sym->flags & BSF_SECTION_SYM) != 0 && sym_ss != NULL &&
1930 sym_ss->keep))
1931 keep = true;
1932 else if ((sym->flags & (BSF_GLOBAL | BSF_WEAK)) != 0 &&
1933 sym_ss != NULL && sym_ss->keep)
1934 keep = true;
1936 if (deleted_table_section_symbol(ibfd, sym))
1937 keep = false;
1939 if (bfd_is_com_section(sym->section))
1940 keep = false;
1942 if (mode("rmsyms"))
1943 keep = !str_in_set(sym->name, &rmsyms);
1945 if (keep) {
1946 if (sym_ss != NULL && !sym_ss->keep) {
1947 err(sbfd, "Kept symbol %s in unkept section "
1948 "%s\n", sym->name, sym->section->name);
1949 DIE;
1951 *vec_grow(osyms, 1) = sym;
1956 void read_str_set(struct str_vec *strs)
1958 char *buf = NULL;
1959 size_t n = 0;
1960 assert(getline(&buf, &n, stdin) >= 0);
1961 vec_init(strs);
1962 char *saveptr;
1963 while (1) {
1964 char *str = strtok_r(buf, " \n", &saveptr);
1965 buf = NULL;
1966 if (str == NULL)
1967 break;
1968 *vec_grow(strs, 1) = str;
1972 bool str_in_set(const char *str, const struct str_vec *strs)
1974 const char **strp;
1975 for (strp = strs->data; strp < strs->data + strs->size; strp++) {
1976 if (strcmp(str, *strp) == 0)
1977 return true;
1979 return false;
1982 bool is_table_section(const char *name, bool consider_other)
1984 struct supersect *tables_ss =
1985 fetch_supersect(offsets_sbfd,
1986 bfd_get_section_by_name(offsets_sbfd->abfd,
1987 ".ksplice_table_sections"));
1988 const struct table_section *ts;
1989 for (ts = tables_ss->contents.data;
1990 (void *)ts < tables_ss->contents.data + tables_ss->contents.size;
1991 ts++) {
1992 if (strcmp(name, read_string(tables_ss, &ts->sect)) == 0)
1993 return true;
1994 const char *osect_name = read_string(tables_ss,
1995 &ts->other_sect);
1996 if (consider_other && osect_name != NULL &&
1997 strcmp(name, osect_name) == 0)
1998 return true;
2000 return false;
2003 enum supersect_type supersect_type(struct supersect *ss)
2005 if (starts_with(ss->name, ".ksplice"))
2006 return SS_TYPE_KSPLICE;
2008 if (starts_with(ss->name, ".init"))
2009 return SS_TYPE_IGNORED;
2010 if (starts_with(ss->name, ".security_initcall.init"))
2011 return SS_TYPE_IGNORED;
2012 if (starts_with(ss->name, ".con_initcall.init"))
2013 return SS_TYPE_IGNORED;
2014 if (starts_with(ss->name, ".x86cpuvendor.init"))
2015 return SS_TYPE_IGNORED;
2016 if (starts_with(ss->name, ".early_param.init"))
2017 return SS_TYPE_IGNORED;
2018 if (starts_with(ss->name, ".taglist.init"))
2019 return SS_TYPE_IGNORED;
2020 if (starts_with(ss->name, ".arch.info.init"))
2021 return SS_TYPE_IGNORED;
2022 if (starts_with(ss->name, ".proc.info.init"))
2023 return SS_TYPE_IGNORED;
2024 /* .pci_fixup_* sections really should be treated as global rodata
2025 referenced only from quirks.c */
2026 if (starts_with(ss->name, ".pci_fixup_"))
2027 return SS_TYPE_IGNORED;
2028 /* .builtin_fw sections are similar to .pci_fixup */
2029 if (starts_with(ss->name, ".builtin_fw"))
2030 return SS_TYPE_IGNORED;
2031 /* same for .tracedata */
2032 if (starts_with(ss->name, ".tracedata"))
2033 return SS_TYPE_IGNORED;
2034 if (starts_with(ss->name, ".debug"))
2035 return SS_TYPE_IGNORED;
2036 /* .eh_frame should probably be discarded, not ignored */
2037 if (starts_with(ss->name, ".eh_frame"))
2038 return SS_TYPE_IGNORED;
2039 if (config->ignore_devinit && starts_with(ss->name, ".devinit"))
2040 return SS_TYPE_IGNORED;
2041 if (config->ignore_meminit && starts_with(ss->name, ".meminit"))
2042 return SS_TYPE_IGNORED;
2043 if (config->ignore_cpuinit && starts_with(ss->name, ".cpuinit"))
2044 return SS_TYPE_IGNORED;
2045 if (config->ignore_devinit && starts_with(ss->name, ".devexit"))
2046 return SS_TYPE_IGNORED;
2047 if (config->ignore_meminit && starts_with(ss->name, ".memexit"))
2048 return SS_TYPE_IGNORED;
2049 if (config->ignore_cpuinit && starts_with(ss->name, ".cpuexit"))
2050 return SS_TYPE_IGNORED;
2051 if (starts_with(ss->name, ".vgetcpu_mode") ||
2052 starts_with(ss->name, ".jiffies") ||
2053 starts_with(ss->name, ".wall_jiffies") ||
2054 starts_with(ss->name, ".vxtime") ||
2055 starts_with(ss->name, ".sys_tz") ||
2056 starts_with(ss->name, ".sysctl_vsyscall") ||
2057 starts_with(ss->name, ".xtime") ||
2058 starts_with(ss->name, ".xtime_lock") ||
2059 starts_with(ss->name, ".vsyscall"))
2060 return SS_TYPE_IGNORED;
2061 if (starts_with(ss->name, ".vdso"))
2062 return SS_TYPE_IGNORED;
2064 if (bfd_get_section_by_name(ss->parent->abfd, ".exitcall.exit") == NULL) {
2065 if (starts_with(ss->name, ".exit.text"))
2066 return SS_TYPE_TEXT;
2067 if (starts_with(ss->name, ".exit.data"))
2068 return SS_TYPE_DATA;
2069 } else if (starts_with(ss->name, ".exit.text") ||
2070 starts_with(ss->name, ".exit.data"))
2071 return SS_TYPE_IGNORED;
2073 if (starts_with(ss->name, ".text") ||
2074 starts_with(ss->name, ".kernel.text") ||
2075 starts_with(ss->name, ".devinit.text") ||
2076 starts_with(ss->name, ".meminit.text") ||
2077 starts_with(ss->name, ".cpuinit.text") ||
2078 starts_with(ss->name, ".devexit.text") ||
2079 starts_with(ss->name, ".memexit.text") ||
2080 starts_with(ss->name, ".cpuexit.text") ||
2081 starts_with(ss->name, ".ref.text") ||
2082 starts_with(ss->name, ".spinlock.text") ||
2083 starts_with(ss->name, ".kprobes.text") ||
2084 starts_with(ss->name, ".sched.text"))
2085 return SS_TYPE_TEXT;
2087 int n = -1;
2088 if (sscanf(ss->name, ".rodata.str%*u.%*u%n", &n) >= 0 &&
2089 n == strlen(ss->name))
2090 return SS_TYPE_STRING;
2092 if (starts_with(ss->name, ".rodata") ||
2093 starts_with(ss->name, ".kernel.rodata") ||
2094 starts_with(ss->name, ".devinit.rodata") ||
2095 starts_with(ss->name, ".meminit.rodata") ||
2096 starts_with(ss->name, ".cpuinit.rodata") ||
2097 starts_with(ss->name, ".devexit.rodata") ||
2098 starts_with(ss->name, ".memexit.rodata") ||
2099 starts_with(ss->name, ".cpuexit.rodata") ||
2100 starts_with(ss->name, ".ref.rodata") ||
2101 starts_with(ss->name, "__markers_strings"))
2102 return SS_TYPE_RODATA;
2104 if (starts_with(ss->name, ".bss"))
2105 return SS_TYPE_DATA;
2107 /* Ignore .data.percpu sections */
2108 if (starts_with(ss->name, ".data.percpu") ||
2109 starts_with(ss->name, ".kernel.data.percpu"))
2110 return SS_TYPE_IGNORED;
2111 if (starts_with(ss->name, ".data") ||
2112 starts_with(ss->name, ".kernel.data") ||
2113 starts_with(ss->name, ".devinit.data") ||
2114 starts_with(ss->name, ".cpuinit.data") ||
2115 starts_with(ss->name, ".meminit.data") ||
2116 starts_with(ss->name, ".devexit.data") ||
2117 starts_with(ss->name, ".memexit.data") ||
2118 starts_with(ss->name, ".cpuexit.data") ||
2119 starts_with(ss->name, ".ref.data") ||
2120 starts_with(ss->name, "__markers"))
2121 return SS_TYPE_DATA;
2123 /* We replace all the ksymtab strings, so delete them */
2124 if (strcmp(ss->name, "__ksymtab_strings") == 0)
2125 return SS_TYPE_IGNORED;
2126 if (starts_with(ss->name, "__ksymtab"))
2127 return SS_TYPE_EXPORT;
2128 if (starts_with(ss->name, "__kcrctab"))
2129 return SS_TYPE_EXPORT;
2131 if (is_table_section(ss->name, true))
2132 return SS_TYPE_SPECIAL;
2134 if (starts_with(ss->name, ".ARM."))
2135 return SS_TYPE_SPECIAL;
2137 if (starts_with(ss->name, ".note"))
2138 return SS_TYPE_IGNORED;
2139 if (starts_with(ss->name, ".comment"))
2140 return SS_TYPE_IGNORED;
2141 if (starts_with(ss->name, "__param"))
2142 return SS_TYPE_IGNORED;
2143 if (starts_with(ss->name, ".exitcall.exit"))
2144 return SS_TYPE_IGNORED;
2145 if (starts_with(ss->name, ".modinfo"))
2146 return SS_TYPE_IGNORED;
2148 return SS_TYPE_UNKNOWN;
2151 void initialize_supersect_types(struct superbfd *sbfd)
2153 asection *sect;
2154 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2155 struct supersect *ss = fetch_supersect(sbfd, sect);
2156 ss->type = supersect_type(ss);
2157 if (ss->type == SS_TYPE_UNKNOWN) {
2158 err(sbfd, "Unknown section type: %s\n", ss->name);
2159 DIE;
2164 static void init_label_map(struct superbfd *sbfd)
2166 struct label_map *map;
2168 vec_init(&sbfd->maps);
2169 init_csyms(sbfd);
2170 init_callers(sbfd);
2172 struct symbol_hash csyms;
2173 symbol_hash_init(&csyms);
2175 asymbol **symp;
2176 for (symp = sbfd->syms.data;
2177 symp < sbfd->syms.data + sbfd->syms.size; symp++) {
2178 asymbol *csym = canonical_symbol(sbfd, *symp);
2179 if (csym == NULL)
2180 continue;
2181 char *key;
2182 assert(asprintf(&key, "%p", csym) >= 0);
2183 asymbol **csymp = symbol_hash_lookup(&csyms, key, TRUE);
2184 free(key);
2185 if (*csymp != NULL)
2186 continue;
2187 *csymp = csym;
2189 map = vec_grow(&sbfd->maps, 1);
2190 map->csym = csym;
2191 map->count = 0;
2192 map->label = symbol_label(sbfd, csym);
2195 struct label_mapp_hash label_maps;
2196 label_mapp_hash_init(&label_maps);
2197 for (map = sbfd->maps.data;
2198 map < sbfd->maps.data + sbfd->maps.size; map++) {
2199 struct label_map **mapp =
2200 label_mapp_hash_lookup(&label_maps, map->label, TRUE);
2201 if (*mapp == NULL) {
2202 *mapp = map;
2203 continue;
2206 struct label_map *first_map = *mapp;
2207 char *buf;
2208 if (first_map->count == 0) {
2209 assert(asprintf(&buf, "%s~%d", map->label, 0) >= 0);
2210 first_map->label = buf;
2212 first_map->count++;
2213 assert(asprintf(&buf, "%s~%d", map->label, first_map->count)
2214 >= 0);
2215 map->label = buf;
2218 label_mapp_hash_init(&sbfd->maps_hash);
2219 for (map = sbfd->maps.data;
2220 map < sbfd->maps.data + sbfd->maps.size; map++) {
2221 char *key;
2222 assert(asprintf(&key, "%p", map->csym) >= 0);
2223 struct label_map **mapp =
2224 label_mapp_hash_lookup(&sbfd->maps_hash, key, TRUE);
2225 free(key);
2226 *mapp = map;
2227 map->orig_label = map->label;
2231 static const char *label_lookup(struct superbfd *sbfd, asymbol *sym)
2233 asymbol *csym = canonical_symbol(sbfd, sym);
2234 char *key;
2235 assert(asprintf(&key, "%p", csym) >= 0);
2236 struct label_map **mapp =
2237 label_mapp_hash_lookup(&sbfd->maps_hash, key, FALSE);
2238 free(key);
2239 if (mapp == NULL)
2240 DIE;
2241 return (*mapp)->label;
2244 static void print_label_map(struct superbfd *sbfd)
2246 struct label_map *map;
2247 for (map = sbfd->maps.data;
2248 map < sbfd->maps.data + sbfd->maps.size; map++) {
2249 if (strcmp(map->orig_label, map->label) == 0)
2250 continue;
2251 debug1(sbfd, "Label change: %s -> %s\n",
2252 map->label, map->orig_label);
2256 static void label_map_set(struct superbfd *sbfd, const char *oldlabel,
2257 const char *label)
2259 struct label_map *map;
2260 for (map = sbfd->maps.data;
2261 map < sbfd->maps.data + sbfd->maps.size; map++) {
2262 if (strcmp(map->orig_label, oldlabel) == 0) {
2263 if (strcmp(map->orig_label, map->label) != 0 &&
2264 strcmp(map->label, label) != 0)
2265 DIE;
2266 map->label = label;
2267 return;
2270 DIE;
2273 static void init_callers(struct superbfd *sbfd)
2275 string_hash_init(&sbfd->callers);
2276 asection *sect;
2277 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2278 struct supersect *ss = fetch_supersect(sbfd, sect);
2279 arelent **relocp;
2280 for (relocp = ss->relocs.data;
2281 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
2282 asymbol *sym = *(*relocp)->sym_ptr_ptr;
2283 unsigned long val =
2284 sym->value + get_reloc_offset(ss, *relocp, true);
2285 char *key;
2286 assert(asprintf(&key, "%s+%lx", sym->section->name,
2287 val) >= 0);
2288 const char **ret = string_hash_lookup(&sbfd->callers,
2289 key, TRUE);
2290 free(key);
2291 if (*ret == NULL)
2292 *ret = sect->name;
2293 else
2294 *ret = "*multiple_callers*";
2299 static const char *find_caller(struct supersect *ss, asymbol *sym)
2301 char *key;
2302 assert(asprintf(&key, "%s+%lx", sym->section->name,
2303 (unsigned long)sym->value) >= 0);
2304 const char **ret = string_hash_lookup(&ss->parent->callers, key, FALSE);
2305 free(key);
2307 if (ret == NULL)
2308 return "*no_caller*";
2309 return *ret;
2312 static void init_csyms(struct superbfd *sbfd)
2314 asymbolpp_hash_init(&sbfd->csyms);
2316 asymbol **symp;
2317 for (symp = sbfd->syms.data; symp < sbfd->syms.data + sbfd->syms.size;
2318 symp++) {
2319 asymbol *sym = *symp;
2320 if ((sym->flags & BSF_DEBUGGING) != 0)
2321 continue;
2322 char *key;
2323 assert(asprintf(&key, "%s+%lx", sym->section->name,
2324 (unsigned long)sym->value) >= 0);
2325 asymbol ***csympp = asymbolpp_hash_lookup(&sbfd->csyms, key,
2326 TRUE);
2327 free(key);
2328 if (*csympp == NULL) {
2329 *csympp = symp;
2330 continue;
2332 asymbol *csym = **csympp;
2333 if ((csym->flags & BSF_GLOBAL) != 0)
2334 continue;
2335 if ((sym->flags & BSF_GLOBAL) != 0)
2336 *csympp = symp;
2340 static asymbol **symbolp_scan(struct supersect *ss, bfd_vma value)
2342 char *key;
2343 assert(asprintf(&key, "%s+%lx", ss->name, (unsigned long)value) >= 0);
2344 asymbol ***csympp =
2345 asymbolpp_hash_lookup(&ss->parent->csyms, key, FALSE);
2346 free(key);
2347 if (csympp != NULL)
2348 return *csympp;
2350 /* For section symbols of sections containing no symbols, return the
2351 section symbol that relocations are generated against */
2352 if (value == 0)
2353 return &ss->symbol;
2354 return NULL;
2357 static asymbol **canonical_symbolp(struct superbfd *sbfd, asymbol *sym)
2359 if (bfd_is_const_section(sym->section)) {
2360 asymbol **csymp;
2361 for (csymp = sbfd->syms.data;
2362 csymp < sbfd->syms.data + sbfd->syms.size; csymp++) {
2363 if (sym == *csymp)
2364 return csymp;
2366 return NULL;
2368 return symbolp_scan(fetch_supersect(sbfd, sym->section), sym->value);
2371 static asymbol *canonical_symbol(struct superbfd *sbfd, asymbol *sym)
2373 if (bfd_is_const_section(sym->section))
2374 return sym;
2375 asymbol **symp = canonical_symbolp(sbfd, sym);
2376 return symp != NULL ? *symp : NULL;
2379 static char *static_local_symbol(struct superbfd *sbfd, asymbol *sym)
2381 struct supersect *ss = fetch_supersect(sbfd, sym->section);
2382 if ((sym->flags & BSF_LOCAL) == 0 || (sym->flags & BSF_OBJECT) == 0)
2383 return NULL;
2384 char *dot = strrchr(sym->name, '.');
2385 if (dot == NULL || dot[1 + strspn(dot + 1, "0123546789")] != '\0')
2386 return NULL;
2387 char *basename = strndup(sym->name, dot - sym->name);
2388 char *mangled_name;
2389 if (strcmp(basename, "__func__") == 0 ||
2390 strcmp(basename, "__PRETTY_FUNCTION__") == 0)
2391 assert(asprintf(&mangled_name, "%s<%s>", basename,
2392 (char *)ss->contents.data + sym->value) >= 0);
2393 else
2394 assert(asprintf(&mangled_name, "%s<%s>", basename,
2395 find_caller(ss, sym)) >= 0);
2396 return mangled_name;
2399 static char *symbol_label(struct superbfd *sbfd, asymbol *sym)
2401 const char *filename = sbfd->abfd->filename;
2402 char *c = strstr(filename, ".KSPLICE");
2403 int flen = (c == NULL ? strlen(filename) : c - filename);
2405 char *label;
2406 if (bfd_is_und_section(sym->section) || (sym->flags & BSF_GLOBAL) != 0) {
2407 label = strdup(sym->name);
2408 } else if (bfd_is_const_section(sym->section)) {
2409 assert(asprintf(&label, "%s<%.*s>",
2410 sym->name, flen, filename) >= 0);
2411 } else {
2412 asymbol *gsym = canonical_symbol(sbfd, sym);
2414 if (gsym == NULL)
2415 assert(asprintf(&label, "%s+%lx<%.*s>",
2416 sym->section->name,
2417 (unsigned long)sym->value,
2418 flen, filename) >= 0);
2419 else if ((gsym->flags & BSF_GLOBAL) != 0)
2420 label = strdup(gsym->name);
2421 else if (static_local_symbol(sbfd, gsym))
2422 assert(asprintf(&label, "%s+%lx<%.*s>",
2423 static_local_symbol(sbfd, gsym),
2424 (unsigned long)sym->value,
2425 flen, filename) >= 0);
2426 else
2427 assert(asprintf(&label, "%s<%.*s>",
2428 gsym->name, flen, filename) >= 0);
2431 return label;
2434 static struct span *new_span(struct supersect *ss, bfd_vma start, bfd_vma size)
2436 struct span *span = vec_grow(&ss->spans, 1);
2437 span->size = size;
2438 span->start = start;
2439 span->ss = ss;
2440 span->keep = false;
2441 span->new = false;
2442 span->shift = 0;
2443 asymbol **symp = symbolp_scan(ss, span->start);
2444 if (symp != NULL) {
2445 span->symbol = *symp;
2446 span->label = label_lookup(ss->parent, span->symbol);
2447 } else {
2448 span->symbol = NULL;
2449 const char *label = label_lookup(ss->parent, ss->symbol);
2450 if (span->start != 0) {
2451 char *buf;
2452 assert(asprintf(&buf, "%s<span:%lx>", label,
2453 (unsigned long)span->start) >= 0);
2454 span->label = buf;
2455 } else {
2456 span->label = label;
2459 return span;
2462 static void initialize_string_spans(struct supersect *ss)
2464 const char *str;
2465 for (str = ss->contents.data;
2466 (void *)str < ss->contents.data + ss->contents.size;) {
2467 bfd_vma start = (unsigned long)str -
2468 (unsigned long)ss->contents.data;
2469 bfd_vma size = strlen(str) + 1;
2470 while ((start + size) % (1 << ss->alignment) != 0 &&
2471 start + size < ss->contents.size) {
2472 if (str[size] != '\0')
2473 DIE;
2474 size++;
2476 new_span(ss, start, size);
2477 str += size;
2481 static void initialize_spans(struct superbfd *sbfd)
2483 asection *sect;
2484 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2485 struct supersect *ss = fetch_supersect(sbfd, sect);
2486 if (ss->type == SS_TYPE_STRING)
2487 initialize_string_spans(ss);
2488 else if (!mode("keep") || (ss->type != SS_TYPE_SPECIAL &&
2489 ss->type != SS_TYPE_EXPORT))
2490 new_span(ss, 0, ss->contents.size);
2494 struct span *reloc_target_span(struct supersect *ss, arelent *reloc)
2496 asymbol *sym_ptr = *reloc->sym_ptr_ptr;
2497 if (bfd_is_const_section(sym_ptr->section))
2498 return NULL;
2500 bfd_vma addend = get_reloc_offset(ss, reloc, true) + sym_ptr->value;
2501 struct supersect *sym_ss =
2502 fetch_supersect(ss->parent, sym_ptr->section);
2503 struct span *span, *target_span = sym_ss->spans.data;
2504 for (span = sym_ss->spans.data;
2505 span < sym_ss->spans.data + sym_ss->spans.size; span++) {
2506 if (addend >= span->start && addend < span->start + span->size)
2507 target_span = span;
2509 return target_span;
2512 struct span *reloc_address_span(struct supersect *ss, arelent *reloc)
2514 struct span *span;
2515 for (span = ss->spans.data; span < ss->spans.data + ss->spans.size;
2516 span++) {
2517 if (reloc->address >= span->start &&
2518 reloc->address < span->start + span->size)
2519 return span;
2521 return NULL;
2524 void compute_span_shifts(struct superbfd *sbfd)
2526 asection *sect;
2527 struct span *span;
2528 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2529 struct supersect *ss = fetch_supersect(sbfd, sect);
2530 if (!ss->keep)
2531 continue;
2532 bfd_size_type offset = 0;
2533 for (span = ss->spans.data;
2534 span < ss->spans.data + ss->spans.size; span++) {
2535 if (!span->keep)
2536 continue;
2537 span->shift = offset - span->start;
2538 offset += span->size;
2543 void remove_unkept_spans(struct superbfd *sbfd)
2545 asection *sect;
2546 struct span *span;
2547 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2548 struct supersect *ss = fetch_supersect(sbfd, sect);
2549 struct arelentp_vec orig_relocs;
2550 vec_move(&orig_relocs, &ss->relocs);
2551 arelent **relocp, *reloc;
2552 for (relocp = orig_relocs.data;
2553 relocp < orig_relocs.data + orig_relocs.size; relocp++) {
2554 reloc = *relocp;
2555 asymbol *sym = *reloc->sym_ptr_ptr;
2556 span = reloc_target_span(ss, reloc);
2557 if ((span != NULL && span->keep && span->shift == 0) ||
2558 bfd_is_const_section(sym->section)) {
2559 *vec_grow(&ss->relocs, 1) = reloc;
2560 continue;
2562 if (span != NULL && span->keep) {
2563 arelent *new_reloc = malloc(sizeof(*new_reloc));
2564 *new_reloc = *reloc;
2565 new_reloc->addend =
2566 get_reloc_offset(ss, reloc, false);
2567 new_reloc->addend += span->shift;
2568 *vec_grow(&ss->new_relocs, 1) = new_reloc;
2573 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2574 struct supersect *ss = fetch_supersect(sbfd, sect), orig_ss;
2575 if (!ss->keep)
2576 continue;
2577 supersect_move(&orig_ss, ss);
2578 vec_init(&ss->spans);
2579 for (span = orig_ss.spans.data;
2580 span < orig_ss.spans.data + orig_ss.spans.size; span++) {
2581 if (!span->keep)
2582 continue;
2583 struct span *new_span = vec_grow(&ss->spans, 1);
2584 *new_span = *span;
2585 new_span->start = span->start + span->shift;
2586 new_span->shift = 0;
2587 sect_copy(ss, sect_do_grow(ss, 1, span->size, 1),
2588 &orig_ss, orig_ss.contents.data + span->start,
2589 span->size);