Check that the non-dst_mask parts of relocations match in relocs_equal.
[ksplice.git] / objmanip.c
blobd00afbd32a849de395e36a2788469e12db996642
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 match_global_symbol_sections(struct superbfd *oldsbfd,
159 struct superbfd *newsbfd);
160 static void match_sections_by_name(struct superbfd *oldsbfd,
161 struct superbfd *newsbfd);
162 static void match_sections_by_label(struct superbfd *oldsbfd,
163 struct superbfd *newsbfd);
164 static void mark_new_sections(struct superbfd *sbfd);
165 static void handle_deleted_sections(struct superbfd *oldsbfd,
166 struct superbfd *newsbfd);
167 static void compare_matched_sections(struct superbfd *sbfd);
168 static void update_nonzero_offsets(struct superbfd *sbfd);
169 static void handle_nonzero_offset_relocs(struct supersect *ss);
171 static const char *label_lookup(struct superbfd *sbfd, asymbol *sym);
172 static void print_label_map(struct superbfd *sbfd);
173 static void label_map_set(struct superbfd *sbfd, const char *oldlabel,
174 const char *label);
175 static void init_label_map(struct superbfd *sbfd);
176 static asymbol **symbolp_scan(struct supersect *ss, bfd_vma value);
177 static void init_csyms(struct superbfd *sbfd);
178 static void init_callers(struct superbfd *sbfd);
179 static asymbol *canonical_symbol(struct superbfd *sbfd, asymbol *sym);
180 static asymbol **canonical_symbolp(struct superbfd *sbfd, asymbol *sym);
181 static char *static_local_symbol(struct superbfd *sbfd, asymbol *sym);
182 static char *symbol_label(struct superbfd *sbfd, asymbol *sym);
184 int verbose = 0;
185 #define debug_(sbfd, level, fmt, ...) \
186 do { \
187 if (verbose >= (level)) \
188 printf("%s: " fmt, (sbfd)->abfd->filename, \
189 ## __VA_ARGS__); \
190 } while (0)
191 #define debug0(sbfd, fmt, ...) debug_(sbfd, 0, fmt, ## __VA_ARGS__)
192 #define debug1(sbfd, fmt, ...) debug_(sbfd, 1, fmt, ## __VA_ARGS__)
193 #define err(sbfd, fmt, ...) \
194 do { \
195 fprintf(stderr, "%s: " fmt, (sbfd)->abfd->filename, \
196 ## __VA_ARGS__); \
197 } while (0)
199 struct str_vec delsects, rmsyms;
200 struct export_desc_vec exports;
201 bool changed;
203 struct ksplice_config *config;
205 const char *modestr, *kid;
207 struct superbfd *offsets_sbfd = NULL;
209 #define mode(str) starts_with(modestr, str)
211 DECLARE_VEC_TYPE(unsigned long, addr_vec);
212 DEFINE_HASH_TYPE(struct addr_vec, addr_vec_hash,
213 addr_vec_hash_init, addr_vec_hash_free, addr_vec_hash_lookup,
214 vec_init);
215 struct addr_vec_hash system_map;
217 struct bool_hash system_map_written;
218 struct ulong_hash ksplice_symbol_offset;
219 struct ulong_hash ksplice_string_offset;
221 void load_system_map()
223 const char *config_dir = getenv("KSPLICE_CONFIG_DIR");
224 assert(config_dir);
225 char *file;
226 assert(asprintf(&file, "%s/System.map", config_dir) >= 0);
227 FILE *fp = fopen(file, "r");
228 assert(fp);
229 addr_vec_hash_init(&system_map);
230 unsigned long addr;
231 char type;
232 char *sym;
233 while (fscanf(fp, "%lx %c %as\n", &addr, &type, &sym) == 3)
234 *vec_grow(addr_vec_hash_lookup(&system_map, sym, TRUE),
235 1) = addr;
236 fclose(fp);
239 void load_ksplice_symbol_offsets(struct superbfd *sbfd)
241 asection *sect = bfd_get_section_by_name(sbfd->abfd,
242 ".ksplice_symbols");
243 if (sect == NULL)
244 return;
245 struct supersect *ss = fetch_supersect(sbfd, sect);
247 struct ksplice_symbol *ksym;
248 for (ksym = ss->contents.data;
249 (void *)ksym < ss->contents.data + ss->contents.size; ksym++) {
250 const char *label = read_string(ss, &ksym->label);
251 unsigned long *ksymbol_offp =
252 ulong_hash_lookup(&ksplice_symbol_offset, label, TRUE);
253 *ksymbol_offp = addr_offset(ss, ksym);
257 void load_offsets()
259 char *kmodsrc = getenv("KSPLICE_KMODSRC"), *offsets_file;
260 assert(kmodsrc != NULL);
261 assert(asprintf(&offsets_file, "%s/offsets.o", kmodsrc) >= 0);
262 bfd *offsets_bfd = bfd_openr(offsets_file, NULL);
263 assert(offsets_bfd != NULL);
264 char **matching;
265 assert(bfd_check_format_matches(offsets_bfd, bfd_object, &matching));
266 offsets_sbfd = fetch_superbfd(offsets_bfd);
268 asection *config_sect = bfd_get_section_by_name(offsets_sbfd->abfd,
269 ".ksplice_config");
270 struct supersect *config_ss =
271 fetch_supersect(offsets_sbfd, config_sect);
273 config = config_ss->contents.data;
276 bool matchable_data_section(struct supersect *ss)
278 if (ss->type == SS_TYPE_STRING)
279 return true;
280 if (ss->type == SS_TYPE_RODATA)
281 return true;
282 if (ss->type == SS_TYPE_DATA && ss->relocs.size != 0)
283 return true;
284 return false;
287 bool unchangeable_section(struct supersect *ss)
289 if (ss->type == SS_TYPE_DATA)
290 return true;
291 if (ss->type == SS_TYPE_IGNORED && !starts_with(ss->name, ".debug") &&
292 strcmp(ss->name, "__ksymtab_strings") != 0)
293 return true;
294 return false;
297 int main(int argc, char *argv[])
299 if (getenv("KSPLICE_VERBOSE") != NULL)
300 verbose = atoi(getenv("KSPLICE_VERBOSE"));
302 bfd_init();
303 bfd *ibfd = bfd_openr(argv[1], NULL);
304 assert(ibfd);
306 char **matching;
307 assert(bfd_check_format_matches(ibfd, bfd_object, &matching));
309 const char *output_target = bfd_get_target(ibfd);
310 bfd *obfd = bfd_openw(argv[2], output_target);
311 assert(obfd);
313 struct superbfd *isbfd = fetch_superbfd(ibfd);
314 init_label_map(isbfd);
316 bool_hash_init(&system_map_written);
317 ulong_hash_init(&ksplice_symbol_offset);
318 ulong_hash_init(&ksplice_string_offset);
320 modestr = argv[3];
321 if (mode("keep-primary")) {
322 kid = argv[5];
323 do_keep_primary(isbfd, argv[4]);
324 } else if (mode("keep-helper")) {
325 do_keep_helper(isbfd);
326 } else if (mode("finalize")) {
327 do_finalize(isbfd);
328 } else if (mode("rmsyms")) {
329 do_rmsyms(isbfd);
332 copy_object(ibfd, obfd);
334 if (offsets_sbfd != NULL)
335 assert(bfd_close(offsets_sbfd->abfd));
336 assert(bfd_close(obfd));
337 assert(bfd_close(ibfd));
338 return EXIT_SUCCESS;
341 void do_keep_primary(struct superbfd *isbfd, const char *pre)
343 struct bfd *prebfd = bfd_openr(pre, NULL);
344 assert(prebfd != NULL);
345 char **matching;
346 assert(bfd_check_format_matches(prebfd, bfd_object, &matching));
348 struct superbfd *presbfd = fetch_superbfd(prebfd);
349 init_label_map(presbfd);
350 load_system_map();
351 load_offsets();
352 initialize_supersect_types(isbfd);
353 initialize_supersect_types(presbfd);
355 match_global_symbol_sections(presbfd, isbfd);
356 debug1(isbfd, "Matched global\n");
357 match_sections_by_name(presbfd, isbfd);
358 debug1(isbfd, "Matched by name\n");
359 match_sections_by_label(presbfd, isbfd);
360 debug1(isbfd, "Matched by label\n");
362 do {
363 changed = false;
364 compare_matched_sections(isbfd);
365 update_nonzero_offsets(isbfd);
366 mark_new_sections(isbfd);
367 } while (changed);
368 vec_init(&delsects);
370 handle_deleted_sections(presbfd, isbfd);
371 handle_section_symbol_renames(presbfd, isbfd);
373 vec_init(&exports);
374 compare_exported_symbols(presbfd, isbfd, false);
375 compare_exported_symbols(isbfd, presbfd, true);
377 initialize_spans(isbfd);
378 initialize_spans(presbfd);
379 asection *sect;
380 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
381 struct supersect *ss = fetch_supersect(isbfd, sect);
382 if (ss->type != SS_TYPE_STRING)
383 continue;
384 asection *oldsect = bfd_get_section_by_name(prebfd, sect->name);
385 if (oldsect == NULL)
386 continue;
387 struct supersect *old_ss = fetch_supersect(presbfd, oldsect);
388 struct span *span, *old_span;
389 for (span = ss->spans.data;
390 span < ss->spans.data + ss->spans.size; span++) {
391 span->new = true;
392 for (old_span = old_ss->spans.data;
393 old_span < old_ss->spans.data + old_ss->spans.size;
394 old_span++) {
395 if (strcmp((char *)ss->contents.data +
396 span->start,
397 (char *)old_ss->contents.data +
398 old_span->start) == 0) {
399 if (!span->new)
400 DIE;
401 span->label = old_span->label;
402 span->new = false;
407 assert(bfd_close(prebfd));
409 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
410 struct supersect *ss = fetch_supersect(isbfd, sect);
411 ss->keep = false;
412 if (ss->type == SS_TYPE_STRING || ss->type == SS_TYPE_SPECIAL ||
413 ss->type == SS_TYPE_EXPORT)
414 ss->keep = true;
415 if (ss->new || ss->patch)
416 ss->keep = true;
419 print_label_map(isbfd);
421 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
422 struct supersect *ss = fetch_supersect(isbfd, sect);
423 if (ss->patch)
424 debug0(isbfd, "Patching section: %s\n", sect->name);
427 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
428 struct supersect *ss = fetch_supersect(isbfd, sect);
429 if (ss->new)
430 debug0(isbfd, "New section: %s\n", sect->name);
433 const char **sectname;
434 for (sectname = delsects.data;
435 sectname < delsects.data + delsects.size; sectname++)
436 debug0(isbfd, "Deleted section: %s\n", *sectname);
438 const struct export_desc *ed;
439 for (ed = exports.data; ed < exports.data + exports.size; ed++) {
440 const char **symname;
441 for (symname = ed->names.data;
442 symname < ed->names.data + ed->names.size; symname++)
443 debug0(isbfd, "Export %s (%s): %s\n",
444 ed->deletion ? "deletion" : "addition",
445 ed->export_type, *symname);
448 struct span *span;
449 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
450 struct supersect *ss = fetch_supersect(isbfd, sect);
451 for (span = ss->spans.data;
452 span < ss->spans.data + ss->spans.size; span++)
453 span->keep = ss->keep;
456 filter_table_sections(isbfd);
457 for (ed = exports.data; ed < exports.data + exports.size; ed++) {
458 const char **symname;
459 for (symname = ed->names.data;
460 symname < ed->names.data + ed->names.size; symname++)
461 write_ksplice_export(isbfd, *symname,
462 ed->export_type, ed->deletion);
463 if (!ed->deletion)
464 rm_some_exports(isbfd, ed);
467 compute_span_shifts(isbfd);
469 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
470 struct supersect *ss = fetch_supersect(isbfd, sect);
471 if (!ss->patch && !ss->new)
472 continue;
474 struct span *span;
475 for (span = ss->spans.data;
476 span < ss->spans.data + ss->spans.size; span++)
477 write_ksplice_section(span);
479 if (ss->patch)
480 write_ksplice_patch(isbfd, sect->name);
483 rm_relocs(isbfd);
484 remove_unkept_spans(isbfd);
487 void do_keep_helper(struct superbfd *isbfd)
489 load_system_map();
490 load_offsets();
491 initialize_supersect_types(isbfd);
492 initialize_spans(isbfd);
494 asection *sect;
495 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
496 struct supersect *ss = fetch_supersect(isbfd, sect);
497 ss->keep = false;
498 if (ss->type == SS_TYPE_SPECIAL || ss->type == SS_TYPE_TEXT)
499 ss->keep = true;
502 asymbol **symp;
503 for (symp = isbfd->syms.data;
504 symp < isbfd->syms.data + isbfd->syms.size; symp++) {
505 asymbol *sym = *symp;
506 if (!bfd_is_const_section(sym->section) &&
507 (sym->flags & BSF_GLOBAL) != 0) {
508 struct supersect *sym_ss =
509 fetch_supersect(isbfd, sym->section);
510 if (sym_ss->type != SS_TYPE_IGNORED)
511 sym_ss->keep = true;
515 struct span *span;
516 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
517 struct supersect *ss = fetch_supersect(isbfd, sect);
518 for (span = ss->spans.data;
519 span < ss->spans.data + ss->spans.size; span++)
520 span->keep = ss->keep;
523 do {
524 changed = false;
525 keep_referenced_sections(isbfd);
526 } while (changed);
528 filter_table_sections(isbfd);
529 compute_span_shifts(isbfd);
531 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
532 struct supersect *ss = fetch_supersect(isbfd, sect);
533 asymbol *sym = canonical_symbol(isbfd, sect->symbol);
534 if (sym == NULL)
535 continue;
536 if ((sym->flags & BSF_WEAK) != 0)
537 continue;
538 if (bfd_get_section_size(sect) == 0)
539 continue;
540 if (!ss->keep)
541 continue;
542 if (ss->type != SS_TYPE_TEXT && !matchable_data_section(ss))
543 continue;
545 struct span *span;
546 for (span = ss->spans.data;
547 span < ss->spans.data + ss->spans.size; span++) {
548 if (span->keep)
549 write_ksplice_section(span);
553 rm_relocs(isbfd);
554 remove_unkept_spans(isbfd);
557 void do_finalize(struct superbfd *isbfd)
559 load_system_map();
560 load_ksplice_symbol_offsets(isbfd);
561 load_offsets();
562 initialize_supersect_types(isbfd);
563 initialize_spans(isbfd);
564 rm_relocs(isbfd);
567 void do_rmsyms(struct superbfd *isbfd)
569 read_str_set(&rmsyms);
570 load_system_map();
571 load_offsets();
572 initialize_supersect_types(isbfd);
573 initialize_spans(isbfd);
574 rm_relocs(isbfd);
577 struct export_vec *get_export_syms(struct superbfd *sbfd)
579 asection *sect;
580 struct export_vec *exports;
581 exports = malloc(sizeof(*exports));
582 assert(exports != NULL);
583 vec_init(exports);
585 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
586 if (!starts_with(sect->name, "__ksymtab") ||
587 ends_with(sect->name, "_strings"))
588 continue;
589 struct supersect *ss = fetch_supersect(sbfd, sect);
590 struct kernel_symbol *sym;
591 assert(ss->contents.size * 2 == ss->relocs.size *
592 sizeof(struct kernel_symbol));
593 for (sym = ss->contents.data;
594 (void *)sym < ss->contents.data + ss->contents.size;
595 sym++) {
596 struct export *exp = vec_grow(exports, 1);
597 exp->name =
598 read_string(ss, (const char *const *)&sym->name);
599 exp->ss = ss;
602 return exports;
605 struct export_desc *new_export_desc(struct supersect *ss, bool deletion)
607 struct export_desc *ed = vec_grow(&exports, 1);
608 ed->deletion = deletion;
609 vec_init(&ed->names);
610 ed->export_type = strdup(ss->name) + strlen("__ksymtab");
611 ed->sym_ss = ss;
612 char *crc_sect_name;
613 assert(asprintf(&crc_sect_name, "__kcrctab%s", ed->export_type) >= 0);
614 asection *crc_sect =
615 bfd_get_section_by_name(ss->parent->abfd, crc_sect_name);
616 if (crc_sect == NULL)
617 ed->crc_ss = NULL;
618 else
619 ed->crc_ss = fetch_supersect(ss->parent, crc_sect);
620 return ed;
623 void compare_exported_symbols(struct superbfd *oldsbfd,
624 struct superbfd *newsbfd, bool deletion)
626 struct export_vec *new_exports, *old_exports;
627 new_exports = get_export_syms(newsbfd);
628 if (new_exports == NULL)
629 return;
630 old_exports = get_export_syms(oldsbfd);
631 struct export *old, *new;
632 struct supersect *last_ss = NULL;
633 struct export_desc *ed = NULL;
634 for (new = new_exports->data; new < new_exports->data +
635 new_exports->size; new++) {
636 bool found = false;
637 if (old_exports != NULL) {
638 for (old = old_exports->data; old < old_exports->data +
639 old_exports->size; old++) {
640 if (strcmp(new->name, old->name) == 0 &&
641 strcmp(new->ss->name, old->ss->name) == 0) {
642 found = true;
643 break;
647 if (last_ss != new->ss) {
648 last_ss = new->ss;
649 ed = new_export_desc(new->ss, deletion);
651 if (!found)
652 *vec_grow(&ed->names, 1) = new->name;
656 void match_sections(struct supersect *oldss, struct supersect *newss)
658 if (oldss->match == newss && newss->match == oldss)
659 return;
660 if (oldss->match != NULL) {
661 err(newss->parent, "Matching conflict: old %s: %s != %s\n",
662 oldss->name, oldss->match->name, newss->name);
663 DIE;
665 if (newss->match != NULL) {
666 err(newss->parent, "Matching conflict: new %s: %s != %s\n",
667 newss->name, newss->match->name, oldss->name);
668 DIE;
670 oldss->match = newss;
671 newss->match = oldss;
672 debug1(newss->parent, "Matched old %s to new %s\n",
673 oldss->name, newss->name);
676 static void match_global_symbol_sections(struct superbfd *oldsbfd,
677 struct superbfd *newsbfd)
679 asymbol **oldsymp, **newsymp;
680 for (oldsymp = oldsbfd->syms.data;
681 oldsymp < oldsbfd->syms.data + oldsbfd->syms.size; oldsymp++) {
682 asymbol *oldsym = *oldsymp;
683 if ((oldsym->flags & BSF_GLOBAL) == 0 ||
684 bfd_is_const_section(oldsym->section))
685 continue;
686 for (newsymp = newsbfd->syms.data;
687 newsymp < newsbfd->syms.data + newsbfd->syms.size;
688 newsymp++) {
689 asymbol *newsym = *newsymp;
690 if ((newsym->flags & BSF_GLOBAL) == 0 ||
691 bfd_is_const_section(oldsym->section))
692 continue;
693 if (strcmp(oldsym->name, newsym->name) != 0)
694 continue;
695 struct supersect *oldss =
696 fetch_supersect(oldsbfd, oldsym->section);
697 struct supersect *newss =
698 fetch_supersect(newsbfd, newsym->section);
699 match_sections(oldss, newss);
704 static void match_sections_by_name(struct superbfd *oldsbfd,
705 struct superbfd *newsbfd)
707 asection *newp, *oldp;
708 for (newp = newsbfd->abfd->sections; newp != NULL; newp = newp->next) {
709 struct supersect *newss = fetch_supersect(newsbfd, newp);
710 oldp = bfd_get_section_by_name(oldsbfd->abfd, newp->name);
711 if (oldp == NULL || newss->type == SS_TYPE_STRING ||
712 newss->type == SS_TYPE_SPECIAL ||
713 newss->type == SS_TYPE_EXPORT)
714 continue;
715 if (static_local_symbol(newsbfd,
716 canonical_symbol(newsbfd,
717 newp->symbol)))
718 continue;
720 struct supersect *oldss = fetch_supersect(oldsbfd, oldp);
721 match_sections(oldss, newss);
725 static void match_sections_by_label(struct superbfd *oldsbfd,
726 struct superbfd *newsbfd)
728 asection *oldsect, *newsect;
729 struct supersect *oldss, *newss;
730 for (newsect = newsbfd->abfd->sections; newsect != NULL;
731 newsect = newsect->next) {
732 newss = fetch_supersect(newsbfd, newsect);
733 if (newss->type == SS_TYPE_STRING ||
734 newss->type == SS_TYPE_SPECIAL ||
735 newss->type == SS_TYPE_EXPORT)
736 continue;
737 for (oldsect = oldsbfd->abfd->sections; oldsect != NULL;
738 oldsect = oldsect->next) {
739 if (strcmp(label_lookup(newsbfd, newsect->symbol),
740 label_lookup(oldsbfd, oldsect->symbol)) != 0)
741 continue;
742 oldss = fetch_supersect(oldsbfd, oldsect);
743 match_sections(oldss, newss);
748 static void mark_new_sections(struct superbfd *sbfd)
750 asection *sect;
751 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
752 struct supersect *ss = fetch_supersect(sbfd, sect);
753 if (ss->type == SS_TYPE_STRING || ss->type == SS_TYPE_SPECIAL ||
754 ss->type == SS_TYPE_IGNORED || ss->type == SS_TYPE_EXPORT)
755 continue;
756 if (ss->match == NULL)
757 ss->new = true;
761 static void handle_deleted_sections(struct superbfd *oldsbfd,
762 struct superbfd *newsbfd)
764 asection *sect;
765 for (sect = oldsbfd->abfd->sections; sect != NULL; sect = sect->next) {
766 struct supersect *ss = fetch_supersect(oldsbfd, sect);
767 if (ss->type != SS_TYPE_TEXT)
768 continue;
769 if (ss->match != NULL)
770 continue;
771 const char *label = label_lookup(oldsbfd, sect->symbol);
772 *vec_grow(&delsects, 1) = label;
773 asymbol *csym = canonical_symbol(oldsbfd, sect->symbol);
774 write_ksplice_deleted_patch(newsbfd, csym->name, label);
778 static void handle_nonzero_offset_relocs(struct supersect *ss)
780 int i;
781 for (i = 0; i < ss->relocs.size; i++) {
782 asymbol *sym = *ss->relocs.data[i]->sym_ptr_ptr;
783 bfd_vma offset = get_reloc_offset(ss, ss->relocs.data[i], true);
784 if (sym->value + offset == 0)
785 continue;
786 if (bfd_is_const_section(sym->section))
787 continue;
788 struct supersect *sym_ss = fetch_supersect(ss->parent,
789 sym->section);
790 if (sym_ss->type != SS_TYPE_TEXT)
791 continue;
792 if (!sym_ss->patch) {
793 changed = true;
794 debug1(ss->parent,
795 "Changing %s because a relocation from sect %s "
796 "has a nonzero offset %lx+%lx into it\n",
797 sym_ss->name, ss->name,
798 (unsigned long)sym->value,
799 (unsigned long)offset);
801 sym_ss->patch = true;
805 static void update_nonzero_offsets(struct superbfd *sbfd)
807 asection *sect;
808 struct supersect *ss;
810 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
811 ss = fetch_supersect(sbfd, sect);
812 if (ss->new || ss->patch)
813 handle_nonzero_offset_relocs(ss);
817 static void compare_matched_sections(struct superbfd *newsbfd)
819 asection *newp;
820 struct supersect *old_ss, *new_ss;
821 for (newp = newsbfd->abfd->sections; newp != NULL; newp = newp->next) {
822 new_ss = fetch_supersect(newsbfd, newp);
823 if (new_ss->match == NULL)
824 continue;
825 old_ss = new_ss->match;
827 if (nonrelocs_equal(old_ss, new_ss) &&
828 all_relocs_equal(old_ss, new_ss))
829 continue;
831 char *reason;
832 if (new_ss->contents.size != old_ss->contents.size)
833 reason = "differing sizes";
834 else if (memcmp(new_ss->contents.data, old_ss->contents.data,
835 new_ss->contents.size) != 0)
836 reason = "differing contents";
837 else
838 reason = "differing relocations";
839 if (new_ss->type == SS_TYPE_TEXT) {
840 if (new_ss->patch)
841 continue;
842 new_ss->patch = true;
843 debug1(newsbfd, "Changing %s due to %s\n", new_ss->name,
844 reason);
845 } else {
846 debug1(newsbfd, "Unmatching %s and %s due to %s\n",
847 old_ss->name, new_ss->name, reason);
848 new_ss->match = NULL;
849 old_ss->match = NULL;
851 changed = true;
852 if (unchangeable_section(new_ss))
853 err(newsbfd, "warning: ignoring change to nonpatchable "
854 "section %s\n", new_ss->name);
858 static void handle_section_symbol_renames(struct superbfd *oldsbfd,
859 struct superbfd *newsbfd)
861 asection *newp, *oldp;
862 for (newp = newsbfd->abfd->sections; newp != NULL; newp = newp->next) {
863 struct supersect *newss = fetch_supersect(newsbfd, newp);
864 if (newss->match == NULL)
865 continue;
866 oldp = bfd_get_section_by_name(oldsbfd->abfd,
867 newss->match->name);
868 if (oldp == NULL)
869 continue;
871 const char *old_label = label_lookup(oldsbfd, oldp->symbol);
872 const char *new_label = label_lookup(newsbfd, newp->symbol);
874 if (strcmp(old_label, new_label) == 0)
875 continue;
876 label_map_set(newsbfd, new_label, old_label);
880 static bool part_of_reloc(struct supersect *ss, unsigned long addr)
882 arelent **relocp;
883 for (relocp = ss->relocs.data;
884 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
885 arelent *reloc = *relocp;
886 if (addr >= reloc->address &&
887 addr < reloc->address + reloc->howto->size)
888 return true;
890 return false;
893 static bool nonrelocs_equal(struct supersect *old_ss, struct supersect *new_ss)
895 int i;
896 if (old_ss->contents.size != new_ss->contents.size)
897 return false;
898 const unsigned char *old = old_ss->contents.data;
899 const unsigned char *new = new_ss->contents.data;
900 for (i = 0; i < old_ss->contents.size; i++) {
901 if (old[i] != new[i] &&
902 !(part_of_reloc(old_ss, i) && part_of_reloc(new_ss, i)))
903 return false;
905 return true;
908 bool relocs_equal(struct supersect *old_src_ss, struct supersect *new_src_ss,
909 arelent *old_reloc, arelent *new_reloc)
911 struct superbfd *oldsbfd = old_src_ss->parent;
912 struct superbfd *newsbfd = new_src_ss->parent;
914 if (old_reloc->address != new_reloc->address) {
915 debug1(newsbfd, "Section %s/%s has reloc address mismatch at "
916 "%lx\n", old_src_ss->name, new_src_ss->name,
917 (unsigned long)old_reloc->address);
918 return false;
921 if (old_reloc->howto != new_reloc->howto) {
922 debug1(newsbfd, "Section %s/%s has howto type mismatch at "
923 "%lx\n", old_src_ss->name, new_src_ss->name,
924 (unsigned long)old_reloc->address);
925 return false;
928 if (non_dst_mask(old_src_ss, old_reloc) !=
929 non_dst_mask(new_src_ss, new_reloc)) {
930 debug1(newsbfd, "Section %s/%s has contents mismatch at %lx\n",
931 old_src_ss->name, new_src_ss->name,
932 (unsigned long)old_reloc->address);
933 return false;
936 asymbol *old_sym = *old_reloc->sym_ptr_ptr;
937 asymbol *new_sym = *new_reloc->sym_ptr_ptr;
938 asection *old_sect = old_sym->section;
939 asection *new_sect = new_sym->section;
941 bfd_vma old_offset = get_reloc_offset(old_src_ss, old_reloc, true);
942 bfd_vma new_offset = get_reloc_offset(new_src_ss, new_reloc, true);
944 if (bfd_is_und_section(old_sect) || bfd_is_und_section(new_sect)) {
945 if (!bfd_is_und_section(new_sect) && old_offset != 0 &&
946 fetch_supersect(newsbfd, new_sect)->type == SS_TYPE_TEXT)
947 return false;
949 if (!bfd_is_und_section(new_sect) && new_offset != 0 &&
950 fetch_supersect(oldsbfd, old_sect)->type == SS_TYPE_TEXT)
951 return false;
953 return strcmp(old_sym->name, new_sym->name) == 0 &&
954 old_offset == new_offset;
957 if (bfd_is_const_section(old_sect) || bfd_is_const_section(new_sect))
958 DIE;
960 struct supersect *old_ss = fetch_supersect(oldsbfd, old_sect);
961 struct supersect *new_ss = fetch_supersect(newsbfd, new_sect);
963 if (old_ss->type == SS_TYPE_STRING &&
964 /* check it's not an out-of-range relocation to a string;
965 we'll just compare entire sections for them */
966 !(old_offset >= old_ss->contents.size ||
967 new_offset >= new_ss->contents.size)) {
968 if (strcmp(old_ss->contents.data + old_sym->value + old_offset,
969 new_ss->contents.data + new_sym->value + new_offset)
970 != 0) {
971 debug0(newsbfd, "Section %s/%s has string difference "
972 "\"%s\"/\"%s\"\n", old_src_ss->name,
973 new_src_ss->name,
974 (const char *)(old_ss->contents.data +
975 old_sym->value + old_offset),
976 (const char *)(new_ss->contents.data +
977 new_sym->value + new_offset));
978 debug1(newsbfd, "Strings differ between %s and %s\n",
979 old_src_ss->name, new_src_ss->name);
980 return false;
982 return true;
985 if (old_ss->match != new_ss || new_ss->match != old_ss) {
986 debug1(newsbfd, "Nonmatching relocs from %s to %s/%s\n",
987 new_src_ss->name, new_ss->name, old_ss->name);
988 return false;
991 if (old_sym->value + old_offset != new_sym->value + new_offset) {
992 debug1(newsbfd, "Offsets to %s/%s differ between %s "
993 "and %s: %lx+%lx/%lx+%lx\n", old_ss->name,
994 new_ss->name, old_src_ss->name, new_src_ss->name,
995 (unsigned long)old_sym->value, (unsigned long)old_offset,
996 (unsigned long)new_sym->value,
997 (unsigned long)new_offset);
998 return false;
1001 if ((old_sym->value + old_offset != 0 ||
1002 new_sym->value + new_offset != 0) && new_ss->patch) {
1003 debug1(newsbfd, "Relocation from %s to nonzero offsets "
1004 "%lx+%lx/%lx+%lx in changed section %s\n",
1005 new_src_ss->name, (unsigned long)old_sym->value,
1006 (unsigned long)old_offset, (unsigned long)new_sym->value,
1007 (unsigned long)new_offset, new_sym->section->name);
1008 return false;
1010 return true;
1013 bool all_relocs_equal(struct supersect *old_ss, struct supersect *new_ss)
1015 if (old_ss->relocs.size != new_ss->relocs.size) {
1016 debug1(new_ss->parent, "Different reloc count between %s and "
1017 "%s\n", old_ss->name, new_ss->name);
1018 return false;
1021 int i;
1022 for (i = 0; i < old_ss->relocs.size; i++) {
1023 if (!relocs_equal(old_ss, new_ss, old_ss->relocs.data[i],
1024 new_ss->relocs.data[i]))
1025 return false;
1028 return true;
1031 bfd_vma non_dst_mask(struct supersect *ss, arelent *reloc)
1033 int bits = bfd_get_reloc_size(reloc->howto) * 8;
1034 void *address = ss->contents.data + reloc->address;
1035 bfd_vma x = bfd_get(bits, ss->parent->abfd, address);
1036 return x & ~reloc->howto->dst_mask;
1039 void rm_some_exports(struct superbfd *sbfd, const struct export_desc *ed)
1041 struct supersect *ss = ed->sym_ss;
1042 struct supersect *crc_ss = ed->crc_ss;
1043 if (crc_ss != NULL)
1044 assert(ss->contents.size * sizeof(unsigned long) ==
1045 crc_ss->contents.size * sizeof(struct kernel_symbol));
1047 struct kernel_symbol *ksym;
1048 unsigned long *crc = NULL;
1049 if (crc_ss != NULL)
1050 crc = crc_ss->contents.data;
1051 struct span *span, *crc_span;
1052 for (ksym = ss->contents.data;
1053 (void *)ksym < ss->contents.data + ss->contents.size;
1054 ksym++, crc++) {
1055 asymbol *sym;
1056 read_reloc(ss, &ksym->value, sizeof(ksym->value), &sym);
1057 span = new_span(ss, addr_offset(ss, ksym), sizeof(*ksym));
1058 span->keep = str_in_set(sym->name, &ed->names);
1060 if (crc_ss != NULL) {
1061 crc_span = new_span(crc_ss, addr_offset(crc_ss, crc),
1062 sizeof(*crc));
1063 crc_span->keep = span->keep;
1066 if (span->keep) {
1067 /* Replace name with a mangled name */
1068 write_string(ss, (const char **)&ksym->name,
1069 "DISABLED_%s_%s", sym->name, kid);
1074 void rm_relocs(struct superbfd *isbfd)
1076 asection *p;
1077 for (p = isbfd->abfd->sections; p != NULL; p = p->next) {
1078 struct supersect *ss = fetch_supersect(isbfd, p);
1079 if ((mode("keep") && ss->type == SS_TYPE_SPECIAL) ||
1080 ss->type == SS_TYPE_KSPLICE)
1081 continue;
1082 if (ss->keep || mode("rmsyms"))
1083 rm_some_relocs(ss);
1085 if (mode("finalize")) {
1086 p = bfd_get_section_by_name(isbfd->abfd, ".ksplice_patches");
1087 if (p != NULL) {
1088 struct supersect *ss = fetch_supersect(isbfd, p);
1089 rm_some_relocs(ss);
1091 p = bfd_get_section_by_name(isbfd->abfd, ".ksplice_relocs");
1092 if (p != NULL) {
1093 struct supersect *ss = fetch_supersect(isbfd, p);
1094 rm_some_relocs(ss);
1099 void rm_some_relocs(struct supersect *ss)
1101 struct arelentp_vec orig_relocs;
1102 vec_move(&orig_relocs, &ss->relocs);
1104 arelent **relocp;
1105 for (relocp = orig_relocs.data;
1106 relocp < orig_relocs.data + orig_relocs.size; relocp++) {
1107 bool rm_reloc = false;
1108 asymbol *sym_ptr = *(*relocp)->sym_ptr_ptr;
1110 if (mode("rmsyms") && str_in_set(sym_ptr->name, &rmsyms) &&
1111 bfd_is_und_section(sym_ptr->section))
1112 rm_reloc = true;
1114 if (mode("keep"))
1115 rm_reloc = true;
1117 if (mode("keep-primary") &&
1118 (bfd_is_const_section(sym_ptr->section) ||
1119 fetch_supersect(ss->parent, sym_ptr->section)->new ||
1120 reloc_target_span(ss, *relocp)->new ||
1121 !reloc_address_span(ss, *relocp)->keep))
1122 rm_reloc = false;
1124 if (mode("finalize") && bfd_is_und_section(sym_ptr->section))
1125 rm_reloc = true;
1127 if (strcmp(sym_ptr->name, "mcount") == 0 &&
1128 bfd_is_und_section(sym_ptr->section))
1129 rm_reloc = false;
1131 if (rm_reloc)
1132 write_ksplice_reloc(ss, *relocp);
1133 else
1134 *vec_grow(&ss->relocs, 1) = *relocp;
1138 struct supersect *make_section(struct superbfd *sbfd, const char *name)
1140 asection *sect = bfd_get_section_by_name(sbfd->abfd, name);
1141 if (sect != NULL)
1142 return fetch_supersect(sbfd, sect);
1143 else
1144 return new_supersect(sbfd, name);
1147 arelent *create_reloc(struct supersect *ss, const void *addr, asymbol **symp,
1148 bfd_vma offset)
1150 bfd_reloc_code_real_type code;
1151 switch (bfd_arch_bits_per_address(ss->parent->abfd)) {
1152 case 32:
1153 code = BFD_RELOC_32;
1154 break;
1155 case 64:
1156 code = BFD_RELOC_64;
1157 break;
1158 default:
1159 DIE;
1162 arelent *reloc = malloc(sizeof(*reloc));
1163 reloc->sym_ptr_ptr = symp;
1164 reloc->address = addr_offset(ss, addr);
1165 reloc->howto = bfd_reloc_type_lookup(ss->parent->abfd, code);
1166 reloc->addend = offset;
1167 return reloc;
1170 void write_reloc(struct supersect *ss, const void *addr, asymbol **symp,
1171 bfd_vma offset)
1173 *vec_grow(&ss->new_relocs, 1) = create_reloc(ss, addr, symp, offset);
1176 void write_string(struct supersect *ss, const char **addr, const char *fmt, ...)
1178 va_list ap;
1179 struct supersect *str_ss = make_section(ss->parent, ".ksplice_str");
1180 char *str;
1181 va_start(ap, fmt);
1182 int len = vasprintf(&str, fmt, ap);
1183 assert(len >= 0);
1184 va_end(ap);
1186 unsigned long *str_offp = ulong_hash_lookup(&ksplice_string_offset, str,
1187 FALSE);
1188 if (str_offp == NULL) {
1189 char *buf = sect_grow(str_ss, len + 1, char);
1190 memcpy(buf, str, len + 1);
1191 str_offp = ulong_hash_lookup(&ksplice_string_offset, str, TRUE);
1192 *str_offp = addr_offset(str_ss, buf);
1195 write_reloc(ss, addr, &str_ss->symbol, *str_offp);
1198 void lookup_system_map(struct addr_vec *addrs, const char *name, long offset)
1200 struct addr_vec *map_addrs =
1201 addr_vec_hash_lookup(&system_map, name, FALSE);
1202 if (map_addrs == NULL)
1203 return;
1205 unsigned long *addr, *map_addr;
1206 for (map_addr = map_addrs->data;
1207 map_addr < map_addrs->data + map_addrs->size; map_addr++) {
1208 for (addr = addrs->data; addr < addrs->data + addrs->size;
1209 addr++) {
1210 if (*addr == *map_addr + offset)
1211 break;
1213 if (addr < addrs->data + addrs->size)
1214 continue;
1215 *vec_grow(addrs, 1) = *map_addr + offset;
1219 void compute_system_map_array(struct superbfd *sbfd, struct addr_vec *addrs,
1220 asymbol *sym)
1222 if (bfd_is_abs_section(sym->section)) {
1223 *vec_grow(addrs, 1) = sym->value;
1224 } else if (bfd_is_und_section(sym->section)) {
1225 lookup_system_map(addrs, sym->name, 0);
1226 } else if (!bfd_is_const_section(sym->section)) {
1227 asymbol **gsymp;
1228 for (gsymp = sbfd->syms.data;
1229 gsymp < sbfd->syms.data + sbfd->syms.size; gsymp++) {
1230 asymbol *gsym = *gsymp;
1231 if ((gsym->flags & BSF_DEBUGGING) == 0 &&
1232 gsym->section == sym->section)
1233 lookup_system_map(addrs, gsym->name,
1234 sym->value - gsym->value);
1239 void write_ksplice_system_map(struct superbfd *sbfd, asymbol *sym,
1240 const char *label)
1242 bool *done = bool_hash_lookup(&system_map_written, label, TRUE);
1243 if (*done)
1244 return;
1245 *done = true;
1247 struct addr_vec addrs;
1248 vec_init(&addrs);
1250 compute_system_map_array(sbfd, &addrs, sym);
1251 if (addrs.size != 0) {
1252 struct supersect *smap_ss =
1253 make_section(sbfd, ".ksplice_system_map");
1254 struct ksplice_system_map *smap =
1255 sect_grow(smap_ss, 1, struct ksplice_system_map);
1256 write_string(smap_ss, &smap->label, "%s", label);
1258 struct supersect *array_ss = make_section(sbfd,
1259 ".ksplice_array");
1260 void *buf = sect_grow(array_ss, addrs.size,
1261 typeof(*addrs.data));
1262 memcpy(buf, addrs.data, addrs.size * sizeof(*addrs.data));
1263 smap->nr_candidates = addrs.size;
1264 write_reloc(smap_ss, &smap->candidates, &array_ss->symbol,
1265 addr_offset(array_ss, buf));
1267 vec_free(&addrs);
1270 void write_ksplice_symbol_backend(struct supersect *ss,
1271 struct ksplice_symbol *const *addr,
1272 asymbol *sym, const char *label,
1273 const char *name)
1275 struct supersect *ksymbol_ss = make_section(ss->parent,
1276 ".ksplice_symbols");
1277 struct ksplice_symbol *ksymbol;
1278 unsigned long *ksymbol_offp;
1280 ksymbol_offp = ulong_hash_lookup(&ksplice_symbol_offset, label, FALSE);
1281 if (ksymbol_offp != NULL) {
1282 write_reloc(ss, addr, &ksymbol_ss->symbol, *ksymbol_offp);
1283 return;
1285 ksymbol = sect_grow(ksymbol_ss, 1, struct ksplice_symbol);
1286 ksymbol_offp = ulong_hash_lookup(&ksplice_symbol_offset, label, TRUE);
1287 *ksymbol_offp = addr_offset(ksymbol_ss, ksymbol);
1289 write_reloc(ss, addr, &ksymbol_ss->symbol, *ksymbol_offp);
1290 write_string(ksymbol_ss, &ksymbol->label, "%s", label);
1291 if (name != NULL) {
1292 write_string(ksymbol_ss, &ksymbol->name, "%s", name);
1293 write_ksplice_system_map(ksymbol_ss->parent, sym, label);
1297 void write_ksplice_symbol(struct supersect *ss,
1298 struct ksplice_symbol *const *addr,
1299 asymbol *sym, struct span *span,
1300 const char *addstr_sect)
1302 const char *label, *name;
1303 char *output;
1304 if (span != NULL && span->start != 0)
1305 label = span->label;
1306 else
1307 label = label_lookup(ss->parent, sym);
1309 assert(asprintf(&output, "%s%s", label, addstr_sect) >= 0);
1311 asymbol *gsym = canonical_symbol(ss->parent, sym);
1312 if (strcmp(addstr_sect, "") != 0)
1313 name = NULL;
1314 else if (bfd_is_und_section(sym->section))
1315 name = sym->name;
1316 else if (bfd_is_const_section(sym->section))
1317 name = NULL;
1318 else if (span != NULL && span->symbol == NULL)
1319 name = NULL;
1320 else if (gsym == NULL || (gsym->flags & BSF_SECTION_SYM) != 0)
1321 name = NULL;
1322 else
1323 name = gsym->name;
1325 write_ksplice_symbol_backend(ss, addr, sym, output, name);
1328 void write_ksplice_reloc(struct supersect *ss, arelent *orig_reloc)
1330 asymbol *sym_ptr = *orig_reloc->sym_ptr_ptr;
1331 reloc_howto_type *howto = orig_reloc->howto;
1332 bfd_vma addend = get_reloc_offset(ss, orig_reloc, false);
1333 unsigned long *repladdr = ss->contents.data + orig_reloc->address;
1335 if (mode("finalize") && strcmp(ss->name, ".ksplice_patches") == 0) {
1336 *repladdr = 0;
1337 return;
1339 if (mode("finalize") && strcmp(ss->name, ".ksplice_relocs") == 0) {
1340 assert(starts_with(sym_ptr->name, KSPLICE_SYMBOL_STR));
1341 asymbol fake_sym;
1342 fake_sym.name = sym_ptr->name + strlen(KSPLICE_SYMBOL_STR);
1343 fake_sym.section = bfd_und_section_ptr;
1344 fake_sym.value = 0;
1345 fake_sym.flags = 0;
1347 write_ksplice_symbol_backend
1348 (ss, (struct ksplice_symbol **)repladdr, &fake_sym,
1349 fake_sym.name, fake_sym.name);
1350 return;
1353 struct span *span = reloc_target_span(ss, orig_reloc);
1354 if (span == ss->spans.data && span->start != addend)
1355 span = NULL;
1356 blot_section(ss, orig_reloc->address, howto);
1358 struct supersect *kreloc_ss = make_section(ss->parent,
1359 mode("rmsyms") ?
1360 ".ksplice_init_relocs" :
1361 ".ksplice_relocs");
1362 struct ksplice_reloc *kreloc = sect_grow(kreloc_ss, 1,
1363 struct ksplice_reloc);
1365 struct span *address_span = reloc_address_span(ss, orig_reloc);
1366 write_reloc(kreloc_ss, &kreloc->blank_addr,
1367 &ss->symbol, orig_reloc->address + address_span->shift);
1368 if (bfd_is_und_section(sym_ptr->section) && mode("keep")) {
1369 char *name;
1370 assert(asprintf(&name, KSPLICE_SYMBOL_STR "%s", sym_ptr->name)
1371 >= 0);
1372 asymbol **symp = make_undefined_symbolp(ss->parent, name);
1373 write_reloc(kreloc_ss, &kreloc->symbol, symp, 0);
1374 } else {
1375 write_ksplice_symbol(kreloc_ss, &kreloc->symbol, sym_ptr, span,
1376 "");
1378 kreloc->pcrel = howto->pc_relative;
1379 if (span != NULL && span->start != 0)
1380 addend += sym_ptr->value - span->start;
1381 kreloc->addend = addend;
1382 kreloc->size = bfd_get_reloc_size(howto);
1383 kreloc->dst_mask = howto->dst_mask;
1384 kreloc->rightshift = howto->rightshift;
1385 kreloc->signed_addend =
1386 (howto->complain_on_overflow == complain_overflow_signed) ||
1387 (howto->complain_on_overflow == complain_overflow_bitfield);
1390 #define CANARY(x, canary) ((x & ~howto->dst_mask) | (canary & howto->dst_mask))
1392 void blot_section(struct supersect *ss, int offset, reloc_howto_type *howto)
1394 int bits = bfd_get_reloc_size(howto) * 8;
1395 void *address = ss->contents.data + offset;
1396 bfd_vma x = bfd_get(bits, ss->parent->abfd, address);
1397 x = (x & ~howto->dst_mask) |
1398 ((bfd_vma)KSPLICE_CANARY & howto->dst_mask);
1399 bfd_put(bits, ss->parent->abfd, x, address);
1402 static void write_ksplice_section(struct span *span)
1404 struct supersect *ss = span->ss;
1405 struct supersect *ksect_ss =
1406 make_section(ss->parent, ".ksplice_sections");
1407 struct ksplice_section *ksect = sect_grow(ksect_ss, 1,
1408 struct ksplice_section);
1409 asymbol *sym = span->symbol == NULL ? ss->symbol : span->symbol;
1411 write_ksplice_symbol(ksect_ss, &ksect->symbol, sym, span,
1412 mode("keep-primary") ? "(post)" : "");
1413 ksect->size = span->size;
1414 ksect->flags = 0;
1416 if (ss->type == SS_TYPE_RODATA || ss->type == SS_TYPE_STRING)
1417 ksect->flags |= KSPLICE_SECTION_RODATA;
1418 if (ss->type == SS_TYPE_DATA)
1419 ksect->flags |= KSPLICE_SECTION_DATA;
1420 if (ss->type == SS_TYPE_TEXT)
1421 ksect->flags |= KSPLICE_SECTION_TEXT;
1422 assert(ksect->flags != 0);
1423 write_reloc(ksect_ss, &ksect->address, &ss->symbol,
1424 span->start + span->shift);
1427 void write_ksplice_patch(struct superbfd *sbfd, const char *sectname)
1429 struct supersect *kpatch_ss = make_section(sbfd, ".ksplice_patches");
1430 struct ksplice_patch *kpatch = sect_grow(kpatch_ss, 1,
1431 struct ksplice_patch);
1432 asection *sect = bfd_get_section_by_name(sbfd->abfd, sectname);
1433 assert(sect != NULL);
1435 write_string(kpatch_ss, &kpatch->label, "%s",
1436 label_lookup(sbfd, sect->symbol));
1437 write_reloc(kpatch_ss, &kpatch->repladdr, &sect->symbol, 0);
1440 asymbol **make_undefined_symbolp(struct superbfd *sbfd, const char *name)
1442 asymbol **symp;
1443 for (symp = sbfd->syms.data; symp < sbfd->syms.data + sbfd->syms.size;
1444 symp++) {
1445 asymbol *sym = *symp;
1446 if (strcmp(name, sym->name) == 0 &&
1447 bfd_is_und_section(sym->section))
1448 return symp;
1450 asymbol ***sympp;
1451 for (sympp = sbfd->new_syms.data;
1452 sympp < sbfd->new_syms.data + sbfd->new_syms.size; sympp++) {
1453 asymbol **symp = *sympp;
1454 asymbol *sym = *symp;
1455 if (strcmp(name, sym->name) == 0 &&
1456 bfd_is_und_section(sym->section))
1457 return symp;
1460 symp = malloc(sizeof(*symp));
1461 *symp = bfd_make_empty_symbol(sbfd->abfd);
1462 asymbol *sym = *symp;
1463 sym->name = name;
1464 sym->section = bfd_und_section_ptr;
1465 sym->flags = 0;
1466 sym->value = 0;
1467 *vec_grow(&sbfd->new_syms, 1) = symp;
1468 return symp;
1471 void write_ksplice_deleted_patch(struct superbfd *sbfd, const char *name,
1472 const char *label)
1474 struct supersect *kpatch_ss = make_section(sbfd, ".ksplice_patches");
1475 struct ksplice_patch *kpatch = sect_grow(kpatch_ss, 1,
1476 struct ksplice_patch);
1478 write_string(kpatch_ss, &kpatch->label, "%s", label);
1479 asymbol **symp = make_undefined_symbolp(sbfd, strdup(name));
1480 write_reloc(kpatch_ss, &kpatch->repladdr, symp, 0);
1483 void write_ksplice_export(struct superbfd *sbfd, const char *symname,
1484 const char *export_type, bool del)
1486 struct supersect *export_ss = make_section(sbfd, ".ksplice_exports");
1487 struct ksplice_export *exp = sect_grow(export_ss, 1,
1488 struct ksplice_export);
1490 if (del) {
1491 write_string(export_ss, &exp->name, "%s", symname);
1492 write_string(export_ss, &exp->new_name, "DISABLED_%s_%s",
1493 symname, kid);
1494 } else {
1495 write_string(export_ss, &exp->new_name, "%s", symname);
1496 write_string(export_ss, &exp->name, "DISABLED_%s_%s", symname,
1497 kid);
1501 struct fixup_entry {
1502 bfd_vma offset;
1503 bool used;
1505 DECLARE_VEC_TYPE(struct fixup_entry, fixup_entry_vec);
1507 int compare_fixups(const void *aptr, const void *bptr)
1509 const struct fixup_entry *a = aptr, *b = bptr;
1510 if (a->offset < b->offset)
1511 return -1;
1512 else if (a->offset > b->offset)
1513 return 1;
1514 else
1515 return (int)a->used - (int)b->used;
1518 void filter_table_sections(struct superbfd *isbfd)
1520 struct supersect *tables_ss =
1521 fetch_supersect(offsets_sbfd,
1522 bfd_get_section_by_name(offsets_sbfd->abfd,
1523 ".ksplice_table_sections"));
1524 const struct table_section *ts;
1525 for (ts = tables_ss->contents.data;
1526 (void *)ts < tables_ss->contents.data + tables_ss->contents.size;
1527 ts++) {
1528 struct table_section s = *ts;
1529 s.sect = read_string(tables_ss, &ts->sect);
1530 s.other_sect = read_string(tables_ss, &ts->other_sect);
1531 filter_table_section(isbfd, &s);
1535 void filter_table_section(struct superbfd *sbfd, const struct table_section *s)
1537 asection *isection = bfd_get_section_by_name(sbfd->abfd, s->sect);
1538 if (isection == NULL)
1539 return;
1540 asection *fixup_sect = NULL;
1541 if (s->other_sect != NULL)
1542 fixup_sect = bfd_get_section_by_name(sbfd->abfd, s->other_sect);
1544 struct supersect *ss = fetch_supersect(sbfd, isection);
1545 if (ss->alignment < ffs(s->entry_align) - 1)
1546 ss->alignment = ffs(s->entry_align) - 1;
1548 struct supersect *fixup_ss = NULL;
1549 if (fixup_sect != NULL)
1550 fixup_ss = fetch_supersect(sbfd, fixup_sect);
1552 struct fixup_entry_vec fixups;
1553 vec_init(&fixups);
1555 void *entry;
1556 for (entry = ss->contents.data;
1557 entry < ss->contents.data + ss->contents.size;
1558 entry += s->entry_size) {
1559 asymbol *sym, *fixup_sym;
1560 read_reloc(ss, entry + s->addr_offset, sizeof(void *), &sym);
1562 struct span *span = new_span(ss, addr_offset(ss, entry),
1563 s->entry_size);
1564 struct supersect *sym_ss = fetch_supersect(sbfd, sym->section);
1565 span->keep = sym_ss->keep;
1567 struct fixup_entry *f;
1568 if (fixup_sect != NULL) {
1569 bfd_vma fixup_offset =
1570 read_reloc(ss, entry + s->other_offset,
1571 sizeof(void *), &fixup_sym);
1572 if (fixup_sym->section == fixup_sect) {
1573 assert(fixup_offset < fixup_ss->contents.size);
1574 f = vec_grow(&fixups, 1);
1575 f->offset = fixup_offset;
1576 f->used = span->keep;
1581 if (fixup_sect == NULL)
1582 return;
1584 qsort(fixups.data, fixups.size, sizeof(*fixups.data), compare_fixups);
1585 *vec_grow(&fixups, 1) = (struct fixup_entry)
1586 { .offset = fixup_ss->contents.size, .used = false };
1588 struct fixup_entry *f;
1589 for (f = fixups.data; f < fixups.data + fixups.size - 1; f++) {
1590 struct span *span = new_span(fixup_ss, f->offset,
1591 (f + 1)->offset - f->offset);
1592 span->keep = f->used;
1596 void keep_referenced_sections(struct superbfd *sbfd)
1598 asection *sect;
1599 struct supersect *ss, *sym_ss;
1600 struct span *address_span, *target_span;
1601 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
1602 ss = fetch_supersect(sbfd, sect);
1603 arelent **relocp;
1604 if (ss->type == SS_TYPE_SPECIAL || ss->type == SS_TYPE_EXPORT)
1605 continue;
1606 for (relocp = ss->relocs.data;
1607 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
1608 asymbol *sym = *(*relocp)->sym_ptr_ptr;
1609 address_span = reloc_address_span(ss, *relocp);
1610 if (!address_span->keep)
1611 continue;
1612 target_span = reloc_target_span(ss, *relocp);
1613 if (target_span == NULL || target_span->keep)
1614 continue;
1615 sym_ss = fetch_supersect(sbfd, sym->section);
1616 if (sym_ss->type == SS_TYPE_IGNORED)
1617 continue;
1618 target_span->keep = true;
1619 sym_ss->keep = true;
1620 changed = true;
1625 void copy_symbols(struct asymbolp_vec *osyms, struct asymbolpp_vec *isyms)
1627 asymbol ***sympp;
1628 for (sympp = isyms->data; sympp < isyms->data + isyms->size; sympp++)
1629 *vec_grow(osyms, 1) = **sympp;
1632 /* Modified function from GNU Binutils objcopy.c */
1633 bfd_boolean copy_object(bfd *ibfd, bfd *obfd)
1635 assert(bfd_set_format(obfd, bfd_get_format(ibfd)));
1637 bfd_vma start = bfd_get_start_address(ibfd);
1639 flagword flags = bfd_get_file_flags(ibfd);
1640 flags &= bfd_applicable_file_flags(obfd);
1642 assert(bfd_set_start_address(obfd, start)
1643 && bfd_set_file_flags(obfd, flags));
1645 enum bfd_architecture iarch = bfd_get_arch(ibfd);
1646 unsigned int imach = bfd_get_mach(ibfd);
1647 assert(bfd_set_arch_mach(obfd, iarch, imach));
1648 assert(bfd_set_format(obfd, bfd_get_format(ibfd)));
1650 /* BFD mandates that all output sections be created and sizes set before
1651 any output is done. Thus, we traverse all sections multiple times. */
1652 bfd_map_over_sections(ibfd, setup_section, obfd);
1654 struct supersect *new_supersects = fetch_superbfd(ibfd)->new_supersects;
1655 struct supersect *ss;
1656 for (ss = new_supersects; ss != NULL; ss = ss->next)
1657 setup_new_section(obfd, ss);
1659 /* Mark symbols used in output relocations so that they
1660 are kept, even if they are local labels or static symbols.
1662 Note we iterate over the input sections examining their
1663 relocations since the relocations for the output sections
1664 haven't been set yet. mark_symbols_used_in_relocations will
1665 ignore input sections which have no corresponding output
1666 section. */
1668 bfd_map_over_sections(ibfd, mark_symbols_used_in_relocations, NULL);
1669 for (ss = new_supersects; ss != NULL; ss = ss->next)
1670 ss_mark_symbols_used_in_relocations(ss);
1671 struct asymbolp_vec osyms;
1672 vec_init(&osyms);
1673 filter_symbols(ibfd, obfd, &osyms, &fetch_superbfd(ibfd)->syms);
1674 copy_symbols(&osyms, &fetch_superbfd(ibfd)->new_syms);
1676 bfd_set_symtab(obfd, osyms.data, osyms.size);
1678 /* This has to happen after the symbol table has been set. */
1679 bfd_map_over_sections(obfd, write_section, NULL);
1681 /* Allow the BFD backend to copy any private data it understands
1682 from the input BFD to the output BFD. This is done last to
1683 permit the routine to look at the filtered symbol table, which is
1684 important for the ECOFF code at least. */
1685 assert(bfd_copy_private_bfd_data(ibfd, obfd));
1687 return TRUE;
1690 /* Modified function from GNU Binutils objcopy.c */
1691 void setup_section(bfd *ibfd, asection *isection, void *obfdarg)
1693 struct superbfd *isbfd = fetch_superbfd(ibfd);
1694 struct supersect *ss = fetch_supersect(isbfd, isection);
1695 bfd *obfd = obfdarg;
1696 bfd_vma vma;
1698 if (!ss->keep)
1699 return;
1701 asection *osection = bfd_make_section_anyway(obfd, isection->name);
1702 assert(osection != NULL);
1704 osection->userdata = ss;
1705 bfd_set_section_flags(obfd, osection, ss->flags);
1706 ss->symbol = osection->symbol;
1707 assert(bfd_set_section_size(obfd, osection, ss->contents.size));
1709 vma = bfd_section_vma(ibfd, isection);
1710 assert(bfd_set_section_vma(obfd, osection, vma));
1712 osection->lma = isection->lma;
1713 assert(bfd_set_section_alignment(obfd, osection, ss->alignment));
1714 osection->entsize = isection->entsize;
1715 osection->output_section = osection;
1716 osection->output_offset = 0;
1717 isection->output_section = osection;
1718 isection->output_offset = 0;
1719 return;
1722 void setup_new_section(bfd *obfd, struct supersect *ss)
1724 asection *osection = bfd_make_section_anyway(obfd, ss->name);
1725 assert(osection != NULL);
1726 bfd_set_section_flags(obfd, osection, ss->flags);
1728 osection->userdata = ss;
1729 ss->symbol = osection->symbol;
1730 assert(bfd_set_section_size(obfd, osection, ss->contents.size));
1731 assert(bfd_set_section_vma(obfd, osection, 0));
1733 osection->lma = 0;
1734 assert(bfd_set_section_alignment(obfd, osection, ss->alignment));
1735 osection->entsize = 0;
1736 osection->output_section = osection;
1737 osection->output_offset = 0;
1740 static int compare_reloc_addresses(const void *aptr, const void *bptr)
1742 const arelent *const *a = aptr, *const *b = bptr;
1743 return (*a)->address - (*b)->address;
1746 static void delete_obsolete_relocs(struct supersect *ss)
1748 if (ss->new_relocs.size == 0)
1749 return;
1751 qsort(ss->relocs.data, ss->relocs.size, sizeof(*ss->relocs.data),
1752 compare_reloc_addresses);
1753 qsort(ss->new_relocs.data, ss->new_relocs.size,
1754 sizeof(*ss->new_relocs.data), compare_reloc_addresses);
1756 struct arelentp_vec orig_relocs;
1757 vec_move(&orig_relocs, &ss->relocs);
1759 arelent **relocp, **new_relocp = ss->new_relocs.data;
1760 for (relocp = orig_relocs.data;
1761 relocp < orig_relocs.data + orig_relocs.size; relocp++) {
1762 while (new_relocp < ss->new_relocs.data + ss->new_relocs.size &&
1763 (*new_relocp)->address < (*relocp)->address)
1764 new_relocp++;
1765 arelent *reloc = *relocp, *new_reloc = *new_relocp;
1766 if (new_relocp == ss->new_relocs.data + ss->new_relocs.size ||
1767 reloc->address != new_reloc->address)
1768 *vec_grow(&ss->relocs, 1) = reloc;
1772 void write_section(bfd *obfd, asection *osection, void *arg)
1774 struct supersect *ss = osection->userdata;
1776 if ((ss->flags & SEC_GROUP) != 0 || ss->contents.size == 0)
1777 return;
1779 delete_obsolete_relocs(ss);
1781 arelent **relocp;
1782 char *error_message;
1783 for (relocp = ss->new_relocs.data;
1784 relocp < ss->new_relocs.data + ss->new_relocs.size; relocp++) {
1785 bfd_vma val;
1786 if (bfd_get_arch(obfd) == bfd_arch_arm)
1787 val = osection->use_rela_p ? 0 : (*relocp)->addend;
1788 else
1789 val = 0;
1790 bfd_put(bfd_get_reloc_size((*relocp)->howto) * 8, obfd, val,
1791 ss->contents.data + (*relocp)->address);
1792 if (bfd_install_relocation(obfd, *relocp, ss->contents.data,
1793 0, osection, &error_message) !=
1794 bfd_reloc_ok) {
1795 err(ss->parent, "ksplice: error installing reloc: %s",
1796 error_message);
1797 DIE;
1800 memcpy(vec_grow(&ss->relocs, ss->new_relocs.size), ss->new_relocs.data,
1801 ss->new_relocs.size * sizeof(*ss->new_relocs.data));
1803 bfd_set_reloc(obfd, osection,
1804 ss->relocs.size == 0 ? NULL : ss->relocs.data,
1805 ss->relocs.size);
1807 if (ss->flags & SEC_HAS_CONTENTS)
1808 assert(bfd_set_section_contents
1809 (obfd, osection, ss->contents.data, 0,
1810 ss->contents.size));
1813 /* Modified function from GNU Binutils objcopy.c
1815 * Mark all the symbols which will be used in output relocations with
1816 * the BSF_KEEP flag so that those symbols will not be stripped.
1818 * Ignore relocations which will not appear in the output file.
1820 void mark_symbols_used_in_relocations(bfd *abfd, asection *isection,
1821 void *ignored)
1823 struct superbfd *sbfd = fetch_superbfd(abfd);
1824 if (isection->output_section == NULL)
1825 return;
1827 struct supersect *ss = fetch_supersect(sbfd, isection);
1828 ss_mark_symbols_used_in_relocations(ss);
1831 void ss_mark_symbols_used_in_relocations(struct supersect *ss)
1833 /* Examine each symbol used in a relocation. If it's not one of the
1834 special bfd section symbols, then mark it with BSF_KEEP. */
1835 arelent **relocp;
1836 for (relocp = ss->relocs.data;
1837 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
1838 asymbol *sym = *(*relocp)->sym_ptr_ptr;
1839 if (!(bfd_is_const_section(sym->section) &&
1840 sym == sym->section->symbol))
1841 sym->flags |= BSF_KEEP;
1843 for (relocp = ss->new_relocs.data;
1844 relocp < ss->new_relocs.data + ss->new_relocs.size; relocp++) {
1845 asymbol *sym = *(*relocp)->sym_ptr_ptr;
1846 if (!(bfd_is_const_section(sym->section) &&
1847 sym == sym->section->symbol))
1848 sym->flags |= BSF_KEEP;
1852 static bool deleted_table_section_symbol(bfd *abfd, asymbol *sym)
1854 struct superbfd *sbfd = fetch_superbfd(abfd);
1855 if (bfd_is_const_section(sym->section))
1856 return false;
1857 struct supersect *ss = fetch_supersect(sbfd, sym->section);
1859 asymbol **symp;
1860 for (symp = ss->syms.data; symp < ss->syms.data + ss->syms.size; symp++) {
1861 if (sym == *symp)
1862 break;
1864 return symp >= ss->syms.data + ss->syms.size;
1867 /* Modified function from GNU Binutils objcopy.c
1869 * Choose which symbol entries to copy.
1870 * We don't copy in place, because that confuses the relocs.
1871 * Return the number of symbols to print.
1873 void filter_symbols(bfd *ibfd, bfd *obfd, struct asymbolp_vec *osyms,
1874 struct asymbolp_vec *isyms)
1876 asymbol **symp;
1877 struct superbfd *sbfd = fetch_superbfd(ibfd);
1878 for (symp = isyms->data; symp < isyms->data + isyms->size; symp++) {
1879 asymbol *sym = *symp;
1880 struct supersect *sym_ss = NULL;
1881 if (!bfd_is_const_section(sym->section))
1882 sym_ss = fetch_supersect(sbfd, sym->section);
1884 bool keep = false;
1886 if (mode("keep") && (sym->flags & BSF_GLOBAL) != 0 &&
1887 !(mode("keep-primary") && sym_ss != NULL && sym_ss->new))
1888 sym->flags = (sym->flags & ~BSF_GLOBAL) | BSF_LOCAL;
1890 if (mode("finalize") && (sym->flags & BSF_GLOBAL) != 0)
1891 sym->flags = (sym->flags & ~BSF_GLOBAL) | BSF_LOCAL;
1893 if ((sym->flags & BSF_KEEP) != 0 /* Used in relocation. */
1894 || ((sym->flags & BSF_SECTION_SYM) != 0 && sym_ss != NULL &&
1895 sym_ss->keep))
1896 keep = true;
1897 else if ((sym->flags & (BSF_GLOBAL | BSF_WEAK)) != 0 &&
1898 sym_ss != NULL && sym_ss->keep)
1899 keep = true;
1901 if (deleted_table_section_symbol(ibfd, sym))
1902 keep = false;
1904 if (bfd_is_com_section(sym->section))
1905 keep = false;
1907 if (mode("rmsyms"))
1908 keep = !str_in_set(sym->name, &rmsyms);
1910 if (keep) {
1911 if (sym_ss != NULL && !sym_ss->keep) {
1912 err(sbfd, "Kept symbol %s in unkept section "
1913 "%s\n", sym->name, sym->section->name);
1914 DIE;
1916 *vec_grow(osyms, 1) = sym;
1921 void read_str_set(struct str_vec *strs)
1923 char *buf = NULL;
1924 size_t n = 0;
1925 assert(getline(&buf, &n, stdin) >= 0);
1926 vec_init(strs);
1927 char *saveptr;
1928 while (1) {
1929 char *str = strtok_r(buf, " \n", &saveptr);
1930 buf = NULL;
1931 if (str == NULL)
1932 break;
1933 *vec_grow(strs, 1) = str;
1937 bool str_in_set(const char *str, const struct str_vec *strs)
1939 const char **strp;
1940 for (strp = strs->data; strp < strs->data + strs->size; strp++) {
1941 if (strcmp(str, *strp) == 0)
1942 return true;
1944 return false;
1947 bool is_table_section(const char *name, bool consider_other)
1949 struct supersect *tables_ss =
1950 fetch_supersect(offsets_sbfd,
1951 bfd_get_section_by_name(offsets_sbfd->abfd,
1952 ".ksplice_table_sections"));
1953 const struct table_section *ts;
1954 for (ts = tables_ss->contents.data;
1955 (void *)ts < tables_ss->contents.data + tables_ss->contents.size;
1956 ts++) {
1957 if (strcmp(name, read_string(tables_ss, &ts->sect)) == 0)
1958 return true;
1959 const char *osect_name = read_string(tables_ss,
1960 &ts->other_sect);
1961 if (consider_other && osect_name != NULL &&
1962 strcmp(name, osect_name) == 0)
1963 return true;
1965 return false;
1968 enum supersect_type supersect_type(struct supersect *ss)
1970 if (starts_with(ss->name, ".ksplice"))
1971 return SS_TYPE_KSPLICE;
1973 if (starts_with(ss->name, ".init"))
1974 return SS_TYPE_IGNORED;
1975 if (starts_with(ss->name, ".security_initcall.init"))
1976 return SS_TYPE_IGNORED;
1977 if (starts_with(ss->name, ".con_initcall.init"))
1978 return SS_TYPE_IGNORED;
1979 if (starts_with(ss->name, ".x86cpuvendor.init"))
1980 return SS_TYPE_IGNORED;
1981 if (starts_with(ss->name, ".early_param.init"))
1982 return SS_TYPE_IGNORED;
1983 if (starts_with(ss->name, ".taglist.init"))
1984 return SS_TYPE_IGNORED;
1985 if (starts_with(ss->name, ".arch.info.init"))
1986 return SS_TYPE_IGNORED;
1987 if (starts_with(ss->name, ".proc.info.init"))
1988 return SS_TYPE_IGNORED;
1989 /* .pci_fixup_* sections really should be treated as global rodata
1990 referenced only from quirks.c */
1991 if (starts_with(ss->name, ".pci_fixup_"))
1992 return SS_TYPE_IGNORED;
1993 /* .builtin_fw sections are similar to .pci_fixup */
1994 if (starts_with(ss->name, ".builtin_fw"))
1995 return SS_TYPE_IGNORED;
1996 /* same for .tracedata */
1997 if (starts_with(ss->name, ".tracedata"))
1998 return SS_TYPE_IGNORED;
1999 if (starts_with(ss->name, ".debug"))
2000 return SS_TYPE_IGNORED;
2001 /* .eh_frame should probably be discarded, not ignored */
2002 if (starts_with(ss->name, ".eh_frame"))
2003 return SS_TYPE_IGNORED;
2004 if (config->ignore_devinit && starts_with(ss->name, ".devinit"))
2005 return SS_TYPE_IGNORED;
2006 if (config->ignore_meminit && starts_with(ss->name, ".meminit"))
2007 return SS_TYPE_IGNORED;
2008 if (config->ignore_cpuinit && starts_with(ss->name, ".cpuinit"))
2009 return SS_TYPE_IGNORED;
2010 if (config->ignore_devinit && starts_with(ss->name, ".devexit"))
2011 return SS_TYPE_IGNORED;
2012 if (config->ignore_meminit && starts_with(ss->name, ".memexit"))
2013 return SS_TYPE_IGNORED;
2014 if (config->ignore_cpuinit && starts_with(ss->name, ".cpuexit"))
2015 return SS_TYPE_IGNORED;
2016 if (starts_with(ss->name, ".vgetcpu_mode") ||
2017 starts_with(ss->name, ".jiffies") ||
2018 starts_with(ss->name, ".wall_jiffies") ||
2019 starts_with(ss->name, ".vxtime") ||
2020 starts_with(ss->name, ".sys_tz") ||
2021 starts_with(ss->name, ".sysctl_vsyscall") ||
2022 starts_with(ss->name, ".xtime") ||
2023 starts_with(ss->name, ".xtime_lock") ||
2024 starts_with(ss->name, ".vsyscall"))
2025 return SS_TYPE_IGNORED;
2026 if (starts_with(ss->name, ".vdso"))
2027 return SS_TYPE_IGNORED;
2029 if (bfd_get_section_by_name(ss->parent->abfd, ".exitcall.exit") == NULL) {
2030 if (starts_with(ss->name, ".exit.text"))
2031 return SS_TYPE_TEXT;
2032 if (starts_with(ss->name, ".exit.data"))
2033 return SS_TYPE_DATA;
2034 } else if (starts_with(ss->name, ".exit.text") ||
2035 starts_with(ss->name, ".exit.data"))
2036 return SS_TYPE_IGNORED;
2038 if (starts_with(ss->name, ".text") ||
2039 starts_with(ss->name, ".kernel.text") ||
2040 starts_with(ss->name, ".devinit.text") ||
2041 starts_with(ss->name, ".meminit.text") ||
2042 starts_with(ss->name, ".cpuinit.text") ||
2043 starts_with(ss->name, ".devexit.text") ||
2044 starts_with(ss->name, ".memexit.text") ||
2045 starts_with(ss->name, ".cpuexit.text") ||
2046 starts_with(ss->name, ".ref.text") ||
2047 starts_with(ss->name, ".spinlock.text") ||
2048 starts_with(ss->name, ".kprobes.text") ||
2049 starts_with(ss->name, ".sched.text"))
2050 return SS_TYPE_TEXT;
2052 int n = -1;
2053 if (sscanf(ss->name, ".rodata.str%*u.%*u%n", &n) >= 0 &&
2054 n == strlen(ss->name))
2055 return SS_TYPE_STRING;
2057 if (starts_with(ss->name, ".rodata") ||
2058 starts_with(ss->name, ".kernel.rodata") ||
2059 starts_with(ss->name, ".devinit.rodata") ||
2060 starts_with(ss->name, ".meminit.rodata") ||
2061 starts_with(ss->name, ".cpuinit.rodata") ||
2062 starts_with(ss->name, ".devexit.rodata") ||
2063 starts_with(ss->name, ".memexit.rodata") ||
2064 starts_with(ss->name, ".cpuexit.rodata") ||
2065 starts_with(ss->name, ".ref.rodata") ||
2066 starts_with(ss->name, "__markers_strings"))
2067 return SS_TYPE_RODATA;
2069 if (starts_with(ss->name, ".bss"))
2070 return SS_TYPE_DATA;
2072 /* Ignore .data.percpu sections */
2073 if (starts_with(ss->name, ".data.percpu") ||
2074 starts_with(ss->name, ".kernel.data.percpu"))
2075 return SS_TYPE_IGNORED;
2076 if (starts_with(ss->name, ".data") ||
2077 starts_with(ss->name, ".kernel.data") ||
2078 starts_with(ss->name, ".devinit.data") ||
2079 starts_with(ss->name, ".cpuinit.data") ||
2080 starts_with(ss->name, ".meminit.data") ||
2081 starts_with(ss->name, ".devexit.data") ||
2082 starts_with(ss->name, ".memexit.data") ||
2083 starts_with(ss->name, ".cpuexit.data") ||
2084 starts_with(ss->name, ".ref.data") ||
2085 starts_with(ss->name, "__markers"))
2086 return SS_TYPE_DATA;
2088 /* We replace all the ksymtab strings, so delete them */
2089 if (strcmp(ss->name, "__ksymtab_strings") == 0)
2090 return SS_TYPE_IGNORED;
2091 if (starts_with(ss->name, "__ksymtab"))
2092 return SS_TYPE_EXPORT;
2093 if (starts_with(ss->name, "__kcrctab"))
2094 return SS_TYPE_EXPORT;
2096 if (is_table_section(ss->name, true))
2097 return SS_TYPE_SPECIAL;
2099 if (starts_with(ss->name, ".ARM."))
2100 return SS_TYPE_SPECIAL;
2102 if (starts_with(ss->name, ".note"))
2103 return SS_TYPE_IGNORED;
2104 if (starts_with(ss->name, ".comment"))
2105 return SS_TYPE_IGNORED;
2106 if (starts_with(ss->name, "__param"))
2107 return SS_TYPE_IGNORED;
2108 if (starts_with(ss->name, ".exitcall.exit"))
2109 return SS_TYPE_IGNORED;
2110 if (starts_with(ss->name, ".modinfo"))
2111 return SS_TYPE_IGNORED;
2113 return SS_TYPE_UNKNOWN;
2116 void initialize_supersect_types(struct superbfd *sbfd)
2118 asection *sect;
2119 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2120 struct supersect *ss = fetch_supersect(sbfd, sect);
2121 ss->type = supersect_type(ss);
2122 if (ss->type == SS_TYPE_UNKNOWN) {
2123 err(sbfd, "Unknown section type: %s\n", ss->name);
2124 DIE;
2129 static void init_label_map(struct superbfd *sbfd)
2131 struct label_map *map;
2133 vec_init(&sbfd->maps);
2134 init_csyms(sbfd);
2135 init_callers(sbfd);
2137 struct symbol_hash csyms;
2138 symbol_hash_init(&csyms);
2140 asymbol **symp;
2141 for (symp = sbfd->syms.data;
2142 symp < sbfd->syms.data + sbfd->syms.size; symp++) {
2143 asymbol *csym = canonical_symbol(sbfd, *symp);
2144 if (csym == NULL)
2145 continue;
2146 char *key;
2147 assert(asprintf(&key, "%p", csym) >= 0);
2148 asymbol **csymp = symbol_hash_lookup(&csyms, key, TRUE);
2149 free(key);
2150 if (*csymp != NULL)
2151 continue;
2152 *csymp = csym;
2154 map = vec_grow(&sbfd->maps, 1);
2155 map->csym = csym;
2156 map->count = 0;
2157 map->label = symbol_label(sbfd, csym);
2160 struct label_mapp_hash label_maps;
2161 label_mapp_hash_init(&label_maps);
2162 for (map = sbfd->maps.data;
2163 map < sbfd->maps.data + sbfd->maps.size; map++) {
2164 struct label_map **mapp =
2165 label_mapp_hash_lookup(&label_maps, map->label, TRUE);
2166 if (*mapp == NULL) {
2167 *mapp = map;
2168 continue;
2171 struct label_map *first_map = *mapp;
2172 char *buf;
2173 if (first_map->count == 0) {
2174 assert(asprintf(&buf, "%s~%d", map->label, 0) >= 0);
2175 first_map->label = buf;
2177 first_map->count++;
2178 assert(asprintf(&buf, "%s~%d", map->label, first_map->count)
2179 >= 0);
2180 map->label = buf;
2183 label_mapp_hash_init(&sbfd->maps_hash);
2184 for (map = sbfd->maps.data;
2185 map < sbfd->maps.data + sbfd->maps.size; map++) {
2186 char *key;
2187 assert(asprintf(&key, "%p", map->csym) >= 0);
2188 struct label_map **mapp =
2189 label_mapp_hash_lookup(&sbfd->maps_hash, key, TRUE);
2190 free(key);
2191 *mapp = map;
2192 map->orig_label = map->label;
2196 static const char *label_lookup(struct superbfd *sbfd, asymbol *sym)
2198 asymbol *csym = canonical_symbol(sbfd, sym);
2199 char *key;
2200 assert(asprintf(&key, "%p", csym) >= 0);
2201 struct label_map **mapp =
2202 label_mapp_hash_lookup(&sbfd->maps_hash, key, FALSE);
2203 free(key);
2204 if (mapp == NULL)
2205 DIE;
2206 return (*mapp)->label;
2209 static void print_label_map(struct superbfd *sbfd)
2211 struct label_map *map;
2212 for (map = sbfd->maps.data;
2213 map < sbfd->maps.data + sbfd->maps.size; map++) {
2214 if (strcmp(map->orig_label, map->label) == 0)
2215 continue;
2216 debug1(sbfd, "Label change: %s -> %s\n",
2217 map->label, map->orig_label);
2221 static void label_map_set(struct superbfd *sbfd, const char *oldlabel,
2222 const char *label)
2224 struct label_map *map;
2225 for (map = sbfd->maps.data;
2226 map < sbfd->maps.data + sbfd->maps.size; map++) {
2227 if (strcmp(map->orig_label, oldlabel) == 0) {
2228 if (strcmp(map->orig_label, map->label) != 0 &&
2229 strcmp(map->label, label) != 0)
2230 DIE;
2231 map->label = label;
2232 return;
2235 DIE;
2238 static void init_callers(struct superbfd *sbfd)
2240 string_hash_init(&sbfd->callers);
2241 asection *sect;
2242 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2243 struct supersect *ss = fetch_supersect(sbfd, sect);
2244 arelent **relocp;
2245 for (relocp = ss->relocs.data;
2246 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
2247 asymbol *sym = *(*relocp)->sym_ptr_ptr;
2248 unsigned long val =
2249 sym->value + get_reloc_offset(ss, *relocp, true);
2250 char *key;
2251 assert(asprintf(&key, "%s+%lx", sym->section->name,
2252 val) >= 0);
2253 const char **ret = string_hash_lookup(&sbfd->callers,
2254 key, TRUE);
2255 free(key);
2256 if (*ret == NULL)
2257 *ret = sect->name;
2258 else
2259 *ret = "*multiple_callers*";
2264 static const char *find_caller(struct supersect *ss, asymbol *sym)
2266 char *key;
2267 assert(asprintf(&key, "%s+%lx", sym->section->name,
2268 (unsigned long)sym->value) >= 0);
2269 const char **ret = string_hash_lookup(&ss->parent->callers, key, FALSE);
2270 free(key);
2272 if (ret == NULL)
2273 return "*no_caller*";
2274 return *ret;
2277 static void init_csyms(struct superbfd *sbfd)
2279 asymbolpp_hash_init(&sbfd->csyms);
2281 asymbol **symp;
2282 for (symp = sbfd->syms.data; symp < sbfd->syms.data + sbfd->syms.size;
2283 symp++) {
2284 asymbol *sym = *symp;
2285 if ((sym->flags & BSF_DEBUGGING) != 0)
2286 continue;
2287 char *key;
2288 assert(asprintf(&key, "%s+%lx", sym->section->name,
2289 (unsigned long)sym->value) >= 0);
2290 asymbol ***csympp = asymbolpp_hash_lookup(&sbfd->csyms, key,
2291 TRUE);
2292 free(key);
2293 if (*csympp == NULL) {
2294 *csympp = symp;
2295 continue;
2297 asymbol *csym = **csympp;
2298 if ((csym->flags & BSF_GLOBAL) != 0)
2299 continue;
2300 if ((sym->flags & BSF_GLOBAL) != 0)
2301 *csympp = symp;
2305 static asymbol **symbolp_scan(struct supersect *ss, bfd_vma value)
2307 char *key;
2308 assert(asprintf(&key, "%s+%lx", ss->name, (unsigned long)value) >= 0);
2309 asymbol ***csympp =
2310 asymbolpp_hash_lookup(&ss->parent->csyms, key, FALSE);
2311 free(key);
2312 if (csympp != NULL)
2313 return *csympp;
2315 /* For section symbols of sections containing no symbols, return the
2316 section symbol that relocations are generated against */
2317 if (value == 0)
2318 return &ss->symbol;
2319 return NULL;
2322 static asymbol **canonical_symbolp(struct superbfd *sbfd, asymbol *sym)
2324 if (bfd_is_const_section(sym->section)) {
2325 asymbol **csymp;
2326 for (csymp = sbfd->syms.data;
2327 csymp < sbfd->syms.data + sbfd->syms.size; csymp++) {
2328 if (sym == *csymp)
2329 return csymp;
2331 return NULL;
2333 return symbolp_scan(fetch_supersect(sbfd, sym->section), sym->value);
2336 static asymbol *canonical_symbol(struct superbfd *sbfd, asymbol *sym)
2338 if (bfd_is_const_section(sym->section))
2339 return sym;
2340 asymbol **symp = canonical_symbolp(sbfd, sym);
2341 return symp != NULL ? *symp : NULL;
2344 static char *static_local_symbol(struct superbfd *sbfd, asymbol *sym)
2346 struct supersect *ss = fetch_supersect(sbfd, sym->section);
2347 if ((sym->flags & BSF_LOCAL) == 0 || (sym->flags & BSF_OBJECT) == 0)
2348 return NULL;
2349 char *dot = strrchr(sym->name, '.');
2350 if (dot == NULL || dot[1 + strspn(dot + 1, "0123546789")] != '\0')
2351 return NULL;
2352 char *basename = strndup(sym->name, dot - sym->name);
2353 char *mangled_name;
2354 if (strcmp(basename, "__func__") == 0 ||
2355 strcmp(basename, "__PRETTY_FUNCTION__") == 0)
2356 assert(asprintf(&mangled_name, "%s<%s>", basename,
2357 (char *)ss->contents.data + sym->value) >= 0);
2358 else
2359 assert(asprintf(&mangled_name, "%s<%s>", basename,
2360 find_caller(ss, sym)) >= 0);
2361 return mangled_name;
2364 static char *symbol_label(struct superbfd *sbfd, asymbol *sym)
2366 const char *filename = sbfd->abfd->filename;
2367 char *c = strstr(filename, ".KSPLICE");
2368 int flen = (c == NULL ? strlen(filename) : c - filename);
2370 char *label;
2371 if (bfd_is_und_section(sym->section) || (sym->flags & BSF_GLOBAL) != 0) {
2372 label = strdup(sym->name);
2373 } else if (bfd_is_const_section(sym->section)) {
2374 assert(asprintf(&label, "%s<%.*s>",
2375 sym->name, flen, filename) >= 0);
2376 } else {
2377 asymbol *gsym = canonical_symbol(sbfd, sym);
2379 if (gsym == NULL)
2380 assert(asprintf(&label, "%s+%lx<%.*s>",
2381 sym->section->name,
2382 (unsigned long)sym->value,
2383 flen, filename) >= 0);
2384 else if ((gsym->flags & BSF_GLOBAL) != 0)
2385 label = strdup(gsym->name);
2386 else if (static_local_symbol(sbfd, gsym))
2387 assert(asprintf(&label, "%s+%lx<%.*s>",
2388 static_local_symbol(sbfd, gsym),
2389 (unsigned long)sym->value,
2390 flen, filename) >= 0);
2391 else
2392 assert(asprintf(&label, "%s<%.*s>",
2393 gsym->name, flen, filename) >= 0);
2396 return label;
2399 static struct span *new_span(struct supersect *ss, bfd_vma start, bfd_vma size)
2401 struct span *span = vec_grow(&ss->spans, 1);
2402 span->size = size;
2403 span->start = start;
2404 span->ss = ss;
2405 span->keep = false;
2406 span->new = false;
2407 span->shift = 0;
2408 asymbol **symp = symbolp_scan(ss, span->start);
2409 if (symp != NULL) {
2410 span->symbol = *symp;
2411 span->label = label_lookup(ss->parent, span->symbol);
2412 } else {
2413 span->symbol = NULL;
2414 const char *label = label_lookup(ss->parent, ss->symbol);
2415 if (span->start != 0) {
2416 char *buf;
2417 assert(asprintf(&buf, "%s<span:%lx>", label,
2418 (unsigned long)span->start) >= 0);
2419 span->label = buf;
2420 } else {
2421 span->label = label;
2424 return span;
2427 static void initialize_string_spans(struct supersect *ss)
2429 const char *str;
2430 for (str = ss->contents.data;
2431 (void *)str < ss->contents.data + ss->contents.size;) {
2432 bfd_vma start = (unsigned long)str -
2433 (unsigned long)ss->contents.data;
2434 bfd_vma size = strlen(str) + 1;
2435 while ((start + size) % (1 << ss->alignment) != 0 &&
2436 start + size < ss->contents.size) {
2437 if (str[size] != '\0')
2438 DIE;
2439 size++;
2441 new_span(ss, start, size);
2442 str += size;
2446 static void initialize_spans(struct superbfd *sbfd)
2448 asection *sect;
2449 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2450 struct supersect *ss = fetch_supersect(sbfd, sect);
2451 if (ss->type == SS_TYPE_STRING)
2452 initialize_string_spans(ss);
2453 else if (!mode("keep") || (ss->type != SS_TYPE_SPECIAL &&
2454 ss->type != SS_TYPE_EXPORT))
2455 new_span(ss, 0, ss->contents.size);
2459 struct span *reloc_target_span(struct supersect *ss, arelent *reloc)
2461 asymbol *sym_ptr = *reloc->sym_ptr_ptr;
2462 if (bfd_is_const_section(sym_ptr->section))
2463 return NULL;
2465 bfd_vma addend = get_reloc_offset(ss, reloc, true) + sym_ptr->value;
2466 struct supersect *sym_ss =
2467 fetch_supersect(ss->parent, sym_ptr->section);
2468 struct span *span, *target_span = sym_ss->spans.data;
2469 for (span = sym_ss->spans.data;
2470 span < sym_ss->spans.data + sym_ss->spans.size; span++) {
2471 if (addend >= span->start && addend < span->start + span->size)
2472 target_span = span;
2474 return target_span;
2477 struct span *reloc_address_span(struct supersect *ss, arelent *reloc)
2479 struct span *span;
2480 for (span = ss->spans.data; span < ss->spans.data + ss->spans.size;
2481 span++) {
2482 if (reloc->address >= span->start &&
2483 reloc->address < span->start + span->size)
2484 return span;
2486 return NULL;
2489 void compute_span_shifts(struct superbfd *sbfd)
2491 asection *sect;
2492 struct span *span;
2493 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2494 struct supersect *ss = fetch_supersect(sbfd, sect);
2495 if (!ss->keep)
2496 continue;
2497 bfd_size_type offset = 0;
2498 for (span = ss->spans.data;
2499 span < ss->spans.data + ss->spans.size; span++) {
2500 if (!span->keep)
2501 continue;
2502 span->shift = offset - span->start;
2503 offset += span->size;
2508 void remove_unkept_spans(struct superbfd *sbfd)
2510 asection *sect;
2511 struct span *span;
2512 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2513 struct supersect *ss = fetch_supersect(sbfd, sect);
2514 struct arelentp_vec orig_relocs;
2515 vec_move(&orig_relocs, &ss->relocs);
2516 arelent **relocp, *reloc;
2517 for (relocp = orig_relocs.data;
2518 relocp < orig_relocs.data + orig_relocs.size; relocp++) {
2519 reloc = *relocp;
2520 asymbol *sym = *reloc->sym_ptr_ptr;
2521 span = reloc_target_span(ss, reloc);
2522 if ((span != NULL && span->keep && span->shift == 0) ||
2523 bfd_is_const_section(sym->section)) {
2524 *vec_grow(&ss->relocs, 1) = reloc;
2525 continue;
2527 if (span != NULL && span->keep) {
2528 arelent *new_reloc = malloc(sizeof(*new_reloc));
2529 *new_reloc = *reloc;
2530 new_reloc->addend =
2531 get_reloc_offset(ss, reloc, false);
2532 new_reloc->addend += span->shift;
2533 *vec_grow(&ss->new_relocs, 1) = new_reloc;
2538 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2539 struct supersect *ss = fetch_supersect(sbfd, sect), orig_ss;
2540 if (!ss->keep)
2541 continue;
2542 supersect_move(&orig_ss, ss);
2543 vec_init(&ss->spans);
2544 for (span = orig_ss.spans.data;
2545 span < orig_ss.spans.data + orig_ss.spans.size; span++) {
2546 if (!span->keep)
2547 continue;
2548 struct span *new_span = vec_grow(&ss->spans, 1);
2549 *new_span = *span;
2550 new_span->start = span->start + span->shift;
2551 new_span->shift = 0;
2552 sect_copy(ss, sect_do_grow(ss, 1, span->size, 1),
2553 &orig_ss, orig_ss.contents.data + span->start,
2554 span->size);