Split the addend field into the instruction and target addends.
[ksplice.git] / objmanip.c
blob103b336350495b5e45fa82b43c261322718a8145
1 /* This file is based in part on objcopy.c from GNU Binutils v2.17.
3 * Copyright (C) 1991-2006 Free Software Foundation, Inc.
4 * Copyright (C) 2007-2008 Jeffrey Brian Arnold <jbarnold@mit.edu>
5 * Copyright (C) 2008 Anders Kaseorg <andersk@mit.edu>,
6 * Tim Abbott <tabbott@mit.edu>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License, version 2.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
19 * 02110-1301, USA.
22 /* objmanip performs various object file manipulations for Ksplice. Its first
23 * two arguments are always an input object file and an output object file.
25 * - keep-primary: "objmanip <post.o> <out.o> keep-primary <pre.o> <kid>"
27 * This mode prepares the object file to be installed as a ksplice update. The
28 * kid argument is the ksplice id string for the ksplice update being built.
30 * - keep-helper: "objmanip <pre.o> <out.o> keep-helper"
32 * This mode prepares the object file to be used for run-pre matching. This
33 * involves replacing all ELF relocations with ksplice relocations and
34 * writing ksplice_section structures for each ELF text or data section.
36 * - rmsyms mode: "objmanip <in.o> <out.o> rmsyms
38 * In this mode, any ELF relocations involving the list of symbol names given on
39 * standard input are replaced with ksplice relocations. This is used only
40 * for KSPLICE_STANDALONE.
42 * - finalize mode: "objmanip <in.o> <out.o> finalize"
44 * In this mode, any ELF relocations to undefined symbols are replaced with
45 * ksplice relocations.
48 /* Always define KSPLICE_STANDALONE, even if you're using integrated Ksplice.
49 objmanip won't compile without it. */
50 #define KSPLICE_STANDALONE
52 #define _GNU_SOURCE
53 #include "objcommon.h"
54 #include "kmodsrc/ksplice.h"
55 #include "kmodsrc/offsets.h"
56 #include <stdint.h>
57 #include <stdarg.h>
58 #include <stdlib.h>
59 #include <stdio.h>
60 #include <limits.h>
62 #define KSPLICE_SYMBOL_STR "KSPLICE_SYMBOL_"
64 #define symbol_init(sym) *(sym) = (asymbol *)NULL
65 DEFINE_HASH_TYPE(asymbol *, symbol_hash, symbol_hash_init, symbol_hash_free,
66 symbol_hash_lookup, symbol_init);
68 struct export {
69 const char *name;
70 struct supersect *ss;
72 DECLARE_VEC_TYPE(struct export, export_vec);
74 DECLARE_VEC_TYPE(const char *, str_vec);
76 DECLARE_VEC_TYPE(unsigned long, ulong_vec);
78 struct export_desc {
79 const char *export_type;
80 bool deletion;
81 struct str_vec names;
82 struct supersect *sym_ss;
83 struct supersect *crc_ss;
85 DECLARE_VEC_TYPE(struct export_desc, export_desc_vec);
87 #define bool_init(b) *(b) = false
88 DEFINE_HASH_TYPE(bool, bool_hash, bool_hash_init, bool_hash_free,
89 bool_hash_lookup, bool_init);
91 #define ulong_init(x) *(x) = 0
92 DEFINE_HASH_TYPE(unsigned long, ulong_hash, ulong_hash_init,
93 ulong_hash_free, ulong_hash_lookup, ulong_init);
95 void do_keep_primary(struct superbfd *isbfd, const char *pre);
96 void do_keep_helper(struct superbfd *isbfd);
97 void do_finalize(struct superbfd *isbfd);
98 void do_rmsyms(struct superbfd *isbfd);
100 struct export_vec *get_export_syms(struct superbfd *sbfd);
101 void compare_exported_symbols(struct superbfd *oldsbfd,
102 struct superbfd *newsbfd, bool deletion);
103 struct export_desc *new_export_desc(struct supersect *ss, bool deletion);
104 bool relocs_equal(struct supersect *old_src_ss, struct supersect *new_src_ss,
105 arelent *old_reloc, arelent *new_reloc);
106 bfd_vma non_dst_mask(struct supersect *ss, arelent *reloc);
107 bool all_relocs_equal(struct span *old_span, struct span *new_span);
108 static bool part_of_reloc(struct supersect *ss, unsigned long addr);
109 static bool nonrelocs_equal(struct span *old_span, struct span *new_span);
110 static void handle_section_symbol_renames(struct superbfd *oldsbfd,
111 struct superbfd *newsbfd);
113 enum supersect_type supersect_type(struct supersect *ss);
114 void initialize_supersect_types(struct superbfd *sbfd);
115 static void initialize_spans(struct superbfd *sbfd);
116 static void initialize_string_spans(struct supersect *ss);
117 static void initialize_table_spans(struct superbfd *sbfd,
118 struct table_section *s);
119 static void initialize_table_section_spans(struct superbfd *sbfd);
120 struct span *reloc_target_span(struct supersect *ss, arelent *reloc);
121 struct span *find_span(struct supersect *ss, bfd_size_type address);
122 void remove_unkept_spans(struct superbfd *sbfd);
123 void compute_span_shifts(struct superbfd *sbfd);
124 static struct span *new_span(struct supersect *ss, bfd_vma start, bfd_vma size);
125 bool is_table_section(const char *name, bool consider_other);
126 const struct table_section *get_table_section(const char *name);
127 void mangle_section_name(struct superbfd *sbfd, const char *name);
129 void rm_relocs(struct superbfd *isbfd);
130 void rm_some_relocs(struct supersect *ss);
131 void write_ksplice_reloc(struct supersect *ss, arelent *orig_reloc);
132 static void write_ksplice_reloc_howto(struct supersect *ss, const
133 struct ksplice_reloc_howto *const *addr,
134 reloc_howto_type *howto);
135 static void write_ksplice_date_reloc(struct supersect *ss, unsigned long offset,
136 const char *str,
137 enum ksplice_reloc_howto_type type);
138 static void write_ksplice_nonreloc_howto(struct supersect *ss,
139 const struct ksplice_reloc_howto
140 *const *addr,
141 enum ksplice_reloc_howto_type type,
142 int size);
143 static void write_date_relocs(struct superbfd *sbfd, const char *str,
144 enum ksplice_reloc_howto_type type);
145 void load_ksplice_symbol_offsets(struct superbfd *sbfd);
146 void blot_section(struct supersect *ss, int offset, reloc_howto_type *howto);
147 static void write_ksplice_section(struct span *span);
148 void write_ksplice_patch(struct superbfd *sbfd, struct span *span);
149 void write_ksplice_deleted_patch(struct superbfd *sbfd, const char *name,
150 const char *label, const char *sectname);
151 asymbol **make_undefined_symbolp(struct superbfd *sbfd, const char *name);
152 void filter_table_sections(struct superbfd *isbfd);
153 void filter_table_section(struct superbfd *sbfd, const struct table_section *s);
154 void keep_referenced_sections(struct superbfd *sbfd);
155 bfd_boolean copy_object(bfd *ibfd, bfd *obfd);
156 void setup_section(bfd *ibfd, asection *isection, void *obfdarg);
157 static void setup_new_section(bfd *obfd, struct supersect *ss);
158 static void write_section(bfd *obfd, asection *osection, void *arg);
159 static void delete_obsolete_relocs(struct supersect *ss);
160 void mark_symbols_used_in_relocations(bfd *abfd, asection *isection,
161 void *ignored);
162 static void ss_mark_symbols_used_in_relocations(struct supersect *ss);
163 void filter_symbols(bfd *ibfd, bfd *obfd, struct asymbolp_vec *osyms,
164 struct asymbolp_vec *isyms);
165 static bool deleted_table_section_symbol(bfd *abfd, asymbol *sym);
166 void read_str_set(struct str_vec *strs);
167 bool str_in_set(const char *str, const struct str_vec *strs);
168 struct supersect *__attribute((format(printf, 2, 3)))
169 make_section(struct superbfd *sbfd, const char *fmt, ...);
170 void __attribute__((format(printf, 3, 4)))
171 write_string(struct supersect *ss, const char **addr, const char *fmt, ...);
172 void rm_some_exports(struct superbfd *isbfd, const struct export_desc *ed);
173 void write_ksplice_export(struct superbfd *sbfd, const char *symname,
174 const char *export_type, bool del);
175 void write_reloc(struct supersect *ss, const void *addr, asymbol **symp,
176 bfd_vma offset);
177 arelent *create_reloc(struct supersect *ss, const void *addr, asymbol **symp,
178 bfd_vma offset);
179 static void foreach_symbol_pair(struct superbfd *oldsbfd, struct superbfd *newsbfd,
180 void (*fn)(struct span *old_span,
181 asymbol *oldsym,
182 struct span *new_span,
183 asymbol *newsym));
184 static void check_global_symbols(struct span *old_span, asymbol *oldsym,
185 struct span *new_span, asymbol *newsym);
186 static void match_global_symbols(struct span *old_span, asymbol *oldsym,
187 struct span *new_span, asymbol *newsym);
188 static void match_symbol_spans(struct span *old_span, asymbol *oldsym,
189 struct span *new_span, asymbol *newsym);
191 static void foreach_span_pair(struct superbfd *oldsbfd,
192 struct superbfd *newsbfd,
193 void (*fn)(struct span *old_span,
194 struct span *new_span));
195 static void match_spans_by_label(struct span *old_span, struct span *new_span);
196 static void match_string_spans(struct span *old_span, struct span *new_span);
197 static void mark_new_spans(struct superbfd *sbfd);
198 static void handle_deleted_spans(struct superbfd *oldsbfd,
199 struct superbfd *newsbfd);
200 static void compare_matched_spans(struct superbfd *newsbfd);
201 static void compare_spans(struct span *old_span, struct span *new_span);
202 static void update_nonzero_offsets(struct superbfd *sbfd);
203 static void handle_nonzero_offset_relocs(struct supersect *ss);
204 static void keep_span(struct span *span);
206 static void init_objmanip_superbfd(struct superbfd *sbfd);
207 static const char *label_lookup(struct superbfd *sbfd, asymbol *sym);
208 static void label_map_set(struct superbfd *sbfd, const char *oldlabel,
209 const char *label);
210 static void print_label_changes(struct superbfd *sbfd);
211 static void init_label_map(struct superbfd *sbfd);
212 static asymbol **symbolp_scan(struct supersect *ss, bfd_vma value);
213 static void init_csyms(struct superbfd *sbfd);
214 static void init_callers(struct superbfd *sbfd);
215 static asymbol *canonical_symbol(struct superbfd *sbfd, asymbol *sym);
216 static asymbol **canonical_symbolp(struct superbfd *sbfd, asymbol *sym);
217 static char *static_local_symbol(struct superbfd *sbfd, asymbol *sym);
218 static char *symbol_label(struct superbfd *sbfd, asymbol *sym);
220 int verbose = 0;
221 #define debug_(sbfd, level, fmt, ...) \
222 do { \
223 if (verbose >= (level)) \
224 printf("%s: " fmt, (sbfd)->abfd->filename, \
225 ## __VA_ARGS__); \
226 } while (0)
227 #define debug0(sbfd, fmt, ...) debug_(sbfd, 0, fmt, ## __VA_ARGS__)
228 #define debug1(sbfd, fmt, ...) debug_(sbfd, 1, fmt, ## __VA_ARGS__)
229 #define err(sbfd, fmt, ...) \
230 do { \
231 fprintf(stderr, "%s: " fmt, (sbfd)->abfd->filename, \
232 ## __VA_ARGS__); \
233 } while (0)
235 struct str_vec delsects, rmsyms;
236 struct export_desc_vec exports;
237 bool changed;
239 struct ksplice_config *config;
241 const char *modestr, *kid, *finalize_target = NULL;
242 bool write_output = true;
244 struct superbfd *offsets_sbfd = NULL;
246 #define mode(str) starts_with(modestr, str)
248 DECLARE_VEC_TYPE(unsigned long, addr_vec);
249 DEFINE_HASH_TYPE(struct addr_vec, addr_vec_hash,
250 addr_vec_hash_init, addr_vec_hash_free, addr_vec_hash_lookup,
251 vec_init);
252 struct addr_vec_hash system_map;
254 struct bool_hash system_map_written;
255 struct ulong_hash ksplice_symbol_offset;
256 struct ulong_hash ksplice_howto_offset;
257 struct ulong_hash ksplice_string_offset;
259 void load_system_map()
261 const char *config_dir = getenv("KSPLICE_CONFIG_DIR");
262 assert(config_dir);
263 char *file;
264 assert(asprintf(&file, "%s/System.map", config_dir) >= 0);
265 FILE *fp = fopen(file, "r");
266 assert(fp);
267 addr_vec_hash_init(&system_map);
268 unsigned long addr;
269 char type;
270 char *sym;
271 while (fscanf(fp, "%lx %c %as\n", &addr, &type, &sym) == 3)
272 *vec_grow(addr_vec_hash_lookup(&system_map, sym, TRUE),
273 1) = addr;
274 fclose(fp);
277 void load_ksplice_symbol_offsets(struct superbfd *sbfd)
279 asection *sect = bfd_get_section_by_name(sbfd->abfd,
280 ".ksplice_symbols");
281 if (sect == NULL)
282 return;
283 struct supersect *ss = fetch_supersect(sbfd, sect);
285 struct ksplice_symbol *ksym;
286 for (ksym = ss->contents.data;
287 (void *)ksym < ss->contents.data + ss->contents.size; ksym++) {
288 const char *label = read_string(ss, &ksym->label);
289 unsigned long *ksymbol_offp =
290 ulong_hash_lookup(&ksplice_symbol_offset, label, TRUE);
291 *ksymbol_offp = addr_offset(ss, ksym);
295 void load_offsets()
297 char *kmodsrc = getenv("KSPLICE_KMODSRC"), *offsets_file;
298 assert(kmodsrc != NULL);
299 assert(asprintf(&offsets_file, "%s/offsets.o", kmodsrc) >= 0);
300 bfd *offsets_bfd = bfd_openr(offsets_file, NULL);
301 assert(offsets_bfd != NULL);
302 char **matching;
303 assert(bfd_check_format_matches(offsets_bfd, bfd_object, &matching));
304 offsets_sbfd = fetch_superbfd(offsets_bfd);
306 asection *config_sect = bfd_get_section_by_name(offsets_sbfd->abfd,
307 ".ksplice_config");
308 struct supersect *config_ss =
309 fetch_supersect(offsets_sbfd, config_sect);
311 config = config_ss->contents.data;
314 bool matchable_data_section(struct supersect *ss)
316 if (ss->type == SS_TYPE_STRING)
317 return true;
318 if (ss->type == SS_TYPE_RODATA)
319 return true;
320 if (ss->type == SS_TYPE_DATA && ss->relocs.size != 0)
321 return true;
322 return false;
325 bool unchangeable_section(struct supersect *ss)
327 if (ss->type == SS_TYPE_DATA)
328 return true;
329 if (ss->type == SS_TYPE_IGNORED && !starts_with(ss->name, ".debug") &&
330 strcmp(ss->name, "__ksymtab_strings") != 0)
331 return true;
332 return false;
335 int main(int argc, char *argv[])
337 if (getenv("KSPLICE_VERBOSE") != NULL)
338 verbose = atoi(getenv("KSPLICE_VERBOSE"));
340 bfd_init();
341 bfd *ibfd = bfd_openr(argv[1], NULL);
342 assert(ibfd);
344 char **matching;
345 assert(bfd_check_format_matches(ibfd, bfd_object, &matching));
347 const char *output_target = bfd_get_target(ibfd);
349 load_system_map();
350 load_offsets();
352 bool_hash_init(&system_map_written);
353 ulong_hash_init(&ksplice_symbol_offset);
354 ulong_hash_init(&ksplice_howto_offset);
355 ulong_hash_init(&ksplice_string_offset);
357 struct superbfd *isbfd = fetch_superbfd(ibfd);
359 modestr = argv[3];
360 if (mode("finalize"))
361 finalize_target = argv[4];
362 init_objmanip_superbfd(isbfd);
363 if (mode("keep-primary")) {
364 kid = argv[5];
365 do_keep_primary(isbfd, argv[4]);
366 } else if (mode("keep-helper")) {
367 do_keep_helper(isbfd);
368 } else if (mode("finalize")) {
369 do_finalize(isbfd);
370 } else if (mode("rmsyms")) {
371 do_rmsyms(isbfd);
374 if (write_output) {
375 bfd *obfd = bfd_openw(argv[2], output_target);
376 assert(obfd);
377 copy_object(ibfd, obfd);
378 assert(bfd_close(obfd));
381 if (offsets_sbfd != NULL)
382 assert(bfd_close(offsets_sbfd->abfd));
383 assert(bfd_close(ibfd));
384 return EXIT_SUCCESS;
387 void do_keep_primary(struct superbfd *isbfd, const char *pre)
389 struct bfd *prebfd = bfd_openr(pre, NULL);
390 assert(prebfd != NULL);
391 char **matching;
392 assert(bfd_check_format_matches(prebfd, bfd_object, &matching));
394 struct superbfd *presbfd = fetch_superbfd(prebfd);
395 init_objmanip_superbfd(presbfd);
397 foreach_symbol_pair(presbfd, isbfd, match_global_symbols);
398 debug1(isbfd, "Matched global\n");
399 foreach_span_pair(presbfd, isbfd, match_string_spans);
400 debug1(isbfd, "Matched string spans\n");
401 foreach_symbol_pair(presbfd, isbfd, match_symbol_spans);
402 debug1(isbfd, "Matched by name\n");
403 foreach_span_pair(presbfd, isbfd, match_spans_by_label);
404 debug1(isbfd, "Matched by label\n");
406 do {
407 changed = false;
408 compare_matched_spans(isbfd);
409 update_nonzero_offsets(isbfd);
410 mark_new_spans(isbfd);
411 } while (changed);
412 vec_init(&delsects);
414 foreach_symbol_pair(presbfd, isbfd, check_global_symbols);
416 handle_deleted_spans(presbfd, isbfd);
417 handle_section_symbol_renames(presbfd, isbfd);
419 vec_init(&exports);
420 compare_exported_symbols(presbfd, isbfd, false);
421 compare_exported_symbols(isbfd, presbfd, true);
423 assert(bfd_close(prebfd));
425 asection *sect;
426 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
427 struct supersect *ss = fetch_supersect(isbfd, sect);
428 ss->keep = false;
429 struct span *span;
430 for (span = ss->spans.data;
431 span < ss->spans.data + ss->spans.size; span++) {
432 if (span->new || span->patch)
433 keep_span(span);
434 else
435 span->keep = false;
439 print_label_changes(isbfd);
441 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
442 struct supersect *ss = fetch_supersect(isbfd, sect);
443 struct span *span;
444 for (span = ss->spans.data;
445 span < ss->spans.data + ss->spans.size; span++) {
446 if (span->patch)
447 debug0(isbfd, "Patching span %s\n",
448 span->label);
452 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
453 struct supersect *ss = fetch_supersect(isbfd, sect);
454 struct span *span;
455 for (span = ss->spans.data;
456 span < ss->spans.data + ss->spans.size; span++) {
457 if (span->new)
458 debug0(isbfd, "New span %s\n", span->label);
462 const char **sectname;
463 for (sectname = delsects.data;
464 sectname < delsects.data + delsects.size; sectname++)
465 debug0(isbfd, "Deleted section: %s\n", *sectname);
467 const struct export_desc *ed;
468 for (ed = exports.data; ed < exports.data + exports.size; ed++) {
469 const char **symname;
470 for (symname = ed->names.data;
471 symname < ed->names.data + ed->names.size; symname++)
472 debug0(isbfd, "Export %s (%s): %s\n",
473 ed->deletion ? "deletion" : "addition",
474 ed->export_type, *symname);
477 filter_table_sections(isbfd);
478 write_output = false;
479 for (ed = exports.data; ed < exports.data + exports.size; ed++) {
480 const char **symname;
481 for (symname = ed->names.data;
482 symname < ed->names.data + ed->names.size; symname++)
483 write_ksplice_export(isbfd, *symname,
484 ed->export_type, ed->deletion);
485 if (ed->deletion)
486 write_output = true;
487 else
488 rm_some_exports(isbfd, ed);
491 compute_span_shifts(isbfd);
493 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
494 struct supersect *ss = fetch_supersect(isbfd, sect);
495 struct span *span;
496 for (span = ss->spans.data;
497 span < ss->spans.data + ss->spans.size; span++) {
498 if (span->keep)
499 write_output = true;
500 if (span->patch || span->new)
501 write_ksplice_section(span);
502 if (span->patch)
503 write_ksplice_patch(isbfd, span);
507 rm_relocs(isbfd);
508 remove_unkept_spans(isbfd);
511 void do_keep_helper(struct superbfd *isbfd)
513 asection *sect;
514 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
515 struct supersect *ss = fetch_supersect(isbfd, sect);
516 ss->keep = false;
517 struct span *span;
518 for (span = ss->spans.data;
519 span < ss->spans.data + ss->spans.size; span++) {
520 if (ss->type == SS_TYPE_TEXT)
521 keep_span(span);
522 else
523 span->keep = false;
527 asymbol **symp;
528 for (symp = isbfd->syms.data;
529 symp < isbfd->syms.data + isbfd->syms.size; symp++) {
530 asymbol *sym = *symp;
531 if (!bfd_is_const_section(sym->section) &&
532 (sym->flags & BSF_GLOBAL) != 0) {
533 struct supersect *sym_ss =
534 fetch_supersect(isbfd, sym->section);
535 struct span *span = find_span(sym_ss, sym->value);
536 if (sym_ss->type != SS_TYPE_IGNORED)
537 keep_span(span);
541 do {
542 changed = false;
543 keep_referenced_sections(isbfd);
544 } while (changed);
546 filter_table_sections(isbfd);
547 compute_span_shifts(isbfd);
549 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
550 struct supersect *ss = fetch_supersect(isbfd, sect);
551 asymbol *sym = canonical_symbol(isbfd, sect->symbol);
552 if (sym == NULL)
553 continue;
554 if ((sym->flags & BSF_WEAK) != 0)
555 continue;
556 if (bfd_get_section_size(sect) == 0)
557 continue;
558 if (!ss->keep)
559 continue;
560 if (ss->type != SS_TYPE_TEXT && !matchable_data_section(ss))
561 continue;
563 struct span *span;
564 for (span = ss->spans.data;
565 span < ss->spans.data + ss->spans.size; span++) {
566 if (span->keep)
567 write_ksplice_section(span);
571 rm_relocs(isbfd);
572 remove_unkept_spans(isbfd);
573 mangle_section_name(isbfd, "__markers");
576 void do_finalize(struct superbfd *isbfd)
578 load_ksplice_symbol_offsets(isbfd);
579 asection *sect;
580 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
581 struct supersect *ss = fetch_supersect(isbfd, sect);
582 if (ss->type == SS_TYPE_EXIT) {
583 struct span *span;
584 for (span = ss->spans.data;
585 span < ss->spans.data + ss->spans.size; span++)
586 span->keep = false;
587 ss->keep = false;
590 write_date_relocs(isbfd, "<{DATE...}>", KSPLICE_HOWTO_DATE);
591 write_date_relocs(isbfd, "<{TIME}>", KSPLICE_HOWTO_TIME);
592 rm_relocs(isbfd);
595 void do_rmsyms(struct superbfd *isbfd)
597 read_str_set(&rmsyms);
598 rm_relocs(isbfd);
601 struct export_vec *get_export_syms(struct superbfd *sbfd)
603 asection *sect;
604 struct export_vec *exports;
605 exports = malloc(sizeof(*exports));
606 assert(exports != NULL);
607 vec_init(exports);
609 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
610 if (!starts_with(sect->name, "__ksymtab") ||
611 ends_with(sect->name, "_strings"))
612 continue;
613 struct supersect *ss = fetch_supersect(sbfd, sect);
614 struct kernel_symbol *sym;
615 assert(ss->contents.size * 2 == ss->relocs.size *
616 sizeof(struct kernel_symbol));
617 for (sym = ss->contents.data;
618 (void *)sym < ss->contents.data + ss->contents.size;
619 sym++) {
620 struct export *exp = vec_grow(exports, 1);
621 exp->name =
622 read_string(ss, (const char *const *)&sym->name);
623 exp->ss = ss;
626 return exports;
629 struct export_desc *new_export_desc(struct supersect *ss, bool deletion)
631 struct export_desc *ed = vec_grow(&exports, 1);
632 ed->deletion = deletion;
633 vec_init(&ed->names);
634 ed->export_type = strdup(ss->name) + strlen("__ksymtab");
635 ed->sym_ss = ss;
636 char *crc_sect_name;
637 assert(asprintf(&crc_sect_name, "__kcrctab%s", ed->export_type) >= 0);
638 asection *crc_sect =
639 bfd_get_section_by_name(ss->parent->abfd, crc_sect_name);
640 if (crc_sect == NULL)
641 ed->crc_ss = NULL;
642 else
643 ed->crc_ss = fetch_supersect(ss->parent, crc_sect);
644 return ed;
647 void compare_exported_symbols(struct superbfd *oldsbfd,
648 struct superbfd *newsbfd, bool deletion)
650 struct export_vec *new_exports, *old_exports;
651 new_exports = get_export_syms(newsbfd);
652 if (new_exports == NULL)
653 return;
654 old_exports = get_export_syms(oldsbfd);
655 struct export *old, *new;
656 struct supersect *last_ss = NULL;
657 struct export_desc *ed = NULL;
658 for (new = new_exports->data; new < new_exports->data +
659 new_exports->size; new++) {
660 bool found = false;
661 if (old_exports != NULL) {
662 for (old = old_exports->data; old < old_exports->data +
663 old_exports->size; old++) {
664 if (strcmp(new->name, old->name) == 0 &&
665 strcmp(new->ss->name, old->ss->name) == 0) {
666 found = true;
667 break;
671 if (!found) {
672 if (last_ss != new->ss) {
673 last_ss = new->ss;
674 ed = new_export_desc(new->ss, deletion);
676 *vec_grow(&ed->names, 1) = new->name;
681 void match_spans(struct span *old_span, struct span *new_span)
683 struct superbfd *sbfd = new_span->ss->parent;
684 if (old_span->match == new_span && new_span->match == old_span)
685 return;
686 if (old_span->match != NULL) {
687 err(sbfd, "Matching conflict: old %s: %s != %s\n",
688 old_span->label, old_span->match->label, new_span->label);
689 DIE;
691 if (new_span->match != NULL) {
692 err(sbfd, "Matching conflict: new %s: %s != %s\n",
693 new_span->label, new_span->match->label, old_span->label);
694 DIE;
696 old_span->match = new_span;
697 new_span->match = old_span;
698 debug1(sbfd, "Matched old %s to new %s\n", old_span->label,
699 new_span->label);
702 static void match_global_symbols(struct span *old_span, asymbol *oldsym,
703 struct span *new_span, asymbol *newsym)
705 if ((oldsym->flags & BSF_GLOBAL) == 0 ||
706 (newsym->flags & BSF_GLOBAL) == 0)
707 return;
708 match_spans(old_span, new_span);
711 static void check_global_symbols(struct span *old_span, asymbol *oldsym,
712 struct span *new_span, asymbol *newsym)
714 if ((oldsym->flags & BSF_GLOBAL) == 0 ||
715 (newsym->flags & BSF_GLOBAL) == 0)
716 return;
717 if (old_span->ss->type == SS_TYPE_IGNORED)
718 return;
719 if (old_span->match != new_span || new_span->match != old_span) {
720 err(new_span->ss->parent, "Global symbol span mismatch: %s "
721 "%s/%s\n", oldsym->name, old_span->ss->name,
722 new_span->ss->name);
723 DIE;
727 static void foreach_symbol_pair(struct superbfd *oldsbfd, struct superbfd *newsbfd,
728 void (*fn)(struct span *old_span,
729 asymbol *oldsym,
730 struct span *new_span,
731 asymbol *newsym))
733 asymbol **oldsymp, **newsymp;
734 for (oldsymp = oldsbfd->syms.data;
735 oldsymp < oldsbfd->syms.data + oldsbfd->syms.size; oldsymp++) {
736 asymbol *oldsym = *oldsymp;
737 if (bfd_is_const_section(oldsym->section))
738 continue;
739 for (newsymp = newsbfd->syms.data;
740 newsymp < newsbfd->syms.data + newsbfd->syms.size;
741 newsymp++) {
742 asymbol *newsym = *newsymp;
743 if (bfd_is_const_section(newsym->section))
744 continue;
745 if (strcmp(oldsym->name, newsym->name) != 0)
746 continue;
748 struct supersect *old_ss =
749 fetch_supersect(oldsbfd, oldsym->section);
750 struct supersect *new_ss =
751 fetch_supersect(newsbfd, newsym->section);
752 if (old_ss->type != new_ss->type ||
753 old_ss->type == SS_TYPE_SPECIAL ||
754 old_ss->type == SS_TYPE_EXPORT)
755 continue;
757 struct span *old_span =
758 find_span(old_ss, oldsym->value);
759 struct span *new_span =
760 find_span(new_ss, newsym->value);
761 if (old_span == NULL) {
762 err(oldsbfd, "Could not find span for %s\n",
763 oldsym->name);
764 DIE;
766 if (new_span == NULL) {
767 err(newsbfd, "Could not find span for %s\n",
768 newsym->name);
769 DIE;
771 fn(old_span, oldsym, new_span, newsym);
776 static void match_symbol_spans(struct span *old_span, asymbol *oldsym,
777 struct span *new_span, asymbol *newsym)
779 if ((oldsym->flags & BSF_DEBUGGING) != 0 ||
780 (newsym->flags & BSF_DEBUGGING) != 0)
781 return;
782 if (old_span->ss->type == SS_TYPE_SPECIAL ||
783 old_span->ss->type == SS_TYPE_EXPORT)
784 return;
785 if (static_local_symbol(old_span->ss->parent, oldsym) ||
786 static_local_symbol(new_span->ss->parent, newsym))
787 return;
788 if (old_span->match == NULL && new_span->match == NULL)
789 match_spans(old_span, new_span);
792 static void match_spans_by_label(struct span *old_span, struct span *new_span)
794 if (old_span->ss->type == SS_TYPE_STRING)
795 return;
796 if (strcmp(old_span->label, new_span->label) == 0)
797 match_spans(old_span, new_span);
800 static void match_string_spans(struct span *old_span, struct span *new_span)
802 if (old_span->ss->type != SS_TYPE_STRING ||
803 strcmp(old_span->ss->name, new_span->ss->name) != 0)
804 return;
805 if (strcmp((char *)old_span->ss->contents.data + old_span->start,
806 (char *)new_span->ss->contents.data + new_span->start) == 0)
807 match_spans(old_span, new_span);
810 static void foreach_span_pair(struct superbfd *oldsbfd,
811 struct superbfd *newsbfd,
812 void (*fn)(struct span *old_span,
813 struct span *new_span))
815 asection *oldsect, *newsect;
816 struct supersect *oldss, *newss;
817 struct span *old_span, *new_span;
818 for (newsect = newsbfd->abfd->sections; newsect != NULL;
819 newsect = newsect->next) {
820 newss = fetch_supersect(newsbfd, newsect);
821 if (newss->type == SS_TYPE_SPECIAL ||
822 newss->type == SS_TYPE_EXPORT)
823 continue;
824 for (oldsect = oldsbfd->abfd->sections; oldsect != NULL;
825 oldsect = oldsect->next) {
826 oldss = fetch_supersect(oldsbfd, oldsect);
827 if (oldss->type != newss->type)
828 continue;
829 for (new_span = newss->spans.data;
830 new_span < newss->spans.data + newss->spans.size;
831 new_span++) {
832 for (old_span = oldss->spans.data;
833 old_span < oldss->spans.data +
834 oldss->spans.size; old_span++)
835 fn(old_span, new_span);
841 static void mark_new_spans(struct superbfd *sbfd)
843 asection *sect;
844 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
845 struct supersect *ss = fetch_supersect(sbfd, sect);
846 if (ss->type == SS_TYPE_SPECIAL || ss->type == SS_TYPE_EXPORT ||
847 ss->type == SS_TYPE_IGNORED)
848 continue;
849 struct span *span;
850 for (span = ss->spans.data;
851 span < ss->spans.data + ss->spans.size; span++) {
852 if (span->match == NULL)
853 span->new = true;
858 static void handle_deleted_spans(struct superbfd *oldsbfd,
859 struct superbfd *newsbfd)
861 asection *sect;
862 for (sect = oldsbfd->abfd->sections; sect != NULL; sect = sect->next) {
863 struct supersect *ss = fetch_supersect(oldsbfd, sect);
864 if (ss->type != SS_TYPE_TEXT)
865 continue;
866 struct span *span;
867 for (span = ss->spans.data;
868 span < ss->spans.data + ss->spans.size; span++) {
869 if (span->match != NULL)
870 continue;
871 *vec_grow(&delsects, 1) = span->label;
872 if (span->symbol == NULL)
873 DIE;
874 write_ksplice_deleted_patch(newsbfd, span->symbol->name,
875 span->label,
876 span->ss->name);
881 static void handle_nonzero_offset_relocs(struct supersect *ss)
883 struct span *address_span, *target_span;
884 arelent **relocp;
885 for (relocp = ss->relocs.data;
886 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
887 arelent *reloc = *relocp;
888 address_span = find_span(ss, reloc->address);
889 if (!address_span->new && !address_span->patch)
890 continue;
892 asymbol *sym = *reloc->sym_ptr_ptr;
893 if (bfd_is_const_section(sym->section))
894 continue;
895 bfd_vma offset = get_reloc_offset(ss, reloc, true);
896 target_span = reloc_target_span(ss, reloc);
897 if (sym->value + offset == target_span->start)
898 continue;
900 if (target_span->ss->type != SS_TYPE_TEXT)
901 continue;
902 if (target_span->patch)
903 continue;
905 target_span->patch = true;
906 changed = true;
907 debug1(ss->parent, "Changing %s because a relocation from sect "
908 "%s has a nonzero offset %lx+%lx into it\n",
909 target_span->label, ss->name, (unsigned long)sym->value,
910 (unsigned long)offset);
914 static void update_nonzero_offsets(struct superbfd *sbfd)
916 asection *sect;
917 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
918 struct supersect *ss = fetch_supersect(sbfd, sect);
919 if (ss->type == SS_TYPE_SPECIAL || ss->type == SS_TYPE_EXPORT ||
920 ss->type == SS_TYPE_IGNORED)
921 continue;
922 handle_nonzero_offset_relocs(ss);
926 static void compare_spans(struct span *old_span, struct span *new_span)
928 struct superbfd *newsbfd = new_span->ss->parent;
930 if (nonrelocs_equal(old_span, new_span) &&
931 all_relocs_equal(old_span, new_span))
932 return;
934 char *reason;
935 if (new_span->size != old_span->size)
936 reason = "differing sizes";
937 else if (!nonrelocs_equal(old_span, new_span))
938 reason = "differing contents";
939 else
940 reason = "differing relocations";
942 if (new_span->ss->type == SS_TYPE_TEXT) {
943 if (new_span->patch)
944 return;
945 new_span->patch = true;
946 debug1(newsbfd, "Changing %s due to %s\n", new_span->label,
947 reason);
948 } else {
949 debug1(newsbfd, "Unmatching %s and %s due to %s\n",
950 old_span->label, new_span->label, reason);
951 new_span->match = NULL;
952 old_span->match = NULL;
954 changed = true;
955 if (unchangeable_section(new_span->ss))
956 err(newsbfd, "warning: ignoring change to nonpatchable "
957 "section %s\n", new_span->ss->name);
960 static void compare_matched_spans(struct superbfd *newsbfd)
962 asection *sect;
963 for (sect = newsbfd->abfd->sections; sect != NULL; sect = sect->next) {
964 struct supersect *ss = fetch_supersect(newsbfd, sect);
965 struct span *span;
966 for (span = ss->spans.data;
967 span < ss->spans.data + ss->spans.size; span++) {
968 if (span->match == NULL)
969 continue;
970 compare_spans(span->match, span);
975 static void handle_section_symbol_renames(struct superbfd *oldsbfd,
976 struct superbfd *newsbfd)
978 asection *sect;
979 struct span *span;
980 for (sect = newsbfd->abfd->sections; sect != NULL; sect = sect->next) {
981 struct supersect *ss = fetch_supersect(newsbfd, sect);
982 for (span = ss->spans.data;
983 span < ss->spans.data + ss->spans.size; span++) {
984 if (span->match == NULL)
985 continue;
986 if (strcmp(span->label, span->match->label) == 0)
987 continue;
988 if (strcmp(span->orig_label, span->label) != 0 &&
989 strcmp(span->label, span->match->label) != 0)
990 DIE;
991 if (span->symbol != NULL)
992 label_map_set(newsbfd, span->label,
993 span->match->label);
994 span->label = span->match->label;
999 static bool part_of_reloc(struct supersect *ss, unsigned long addr)
1001 arelent **relocp;
1002 for (relocp = ss->relocs.data;
1003 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
1004 arelent *reloc = *relocp;
1005 if (addr >= reloc->address &&
1006 addr < reloc->address + reloc->howto->size)
1007 return true;
1009 return false;
1012 static bool nonrelocs_equal(struct span *old_span, struct span *new_span)
1014 int i;
1015 struct supersect *old_ss = old_span->ss, *new_ss = new_span->ss;
1016 if (old_span->size != new_span->size)
1017 return false;
1018 const unsigned char *old = old_ss->contents.data + old_span->start;
1019 const unsigned char *new = new_ss->contents.data + new_span->start;
1020 for (i = 0; i < old_span->size; i++) {
1021 if (old[i] != new[i] &&
1022 !(part_of_reloc(old_ss, i + old_span->start) &&
1023 part_of_reloc(new_ss, i + new_span->start)))
1024 return false;
1026 return true;
1029 bool relocs_equal(struct supersect *old_src_ss, struct supersect *new_src_ss,
1030 arelent *old_reloc, arelent *new_reloc)
1032 struct superbfd *oldsbfd = old_src_ss->parent;
1033 struct superbfd *newsbfd = new_src_ss->parent;
1034 struct span *old_addr_span = find_span(old_src_ss, old_reloc->address);
1035 struct span *new_addr_span = find_span(new_src_ss, new_reloc->address);
1037 if (old_reloc->address - old_addr_span->start !=
1038 new_reloc->address - new_addr_span->start) {
1039 debug1(newsbfd, "Section %s/%s has reloc address mismatch at "
1040 "%lx\n", old_src_ss->name, new_src_ss->name,
1041 (unsigned long)old_reloc->address);
1042 return false;
1045 if (old_reloc->howto != new_reloc->howto) {
1046 debug1(newsbfd, "Section %s/%s has howto type mismatch at "
1047 "%lx\n", old_src_ss->name, new_src_ss->name,
1048 (unsigned long)old_reloc->address);
1049 return false;
1052 if (non_dst_mask(old_src_ss, old_reloc) !=
1053 non_dst_mask(new_src_ss, new_reloc)) {
1054 debug1(newsbfd, "Section %s/%s has contents mismatch at %lx\n",
1055 old_src_ss->name, new_src_ss->name,
1056 (unsigned long)old_reloc->address);
1057 return false;
1060 asymbol *old_sym = *old_reloc->sym_ptr_ptr;
1061 asymbol *new_sym = *new_reloc->sym_ptr_ptr;
1062 asection *old_sect = old_sym->section;
1063 asection *new_sect = new_sym->section;
1065 bfd_vma old_offset = get_reloc_offset(old_src_ss, old_reloc, true);
1066 bfd_vma new_offset = get_reloc_offset(new_src_ss, new_reloc, true);
1068 if (bfd_is_und_section(old_sect) || bfd_is_und_section(new_sect)) {
1069 if (!bfd_is_und_section(new_sect) && old_offset != 0 &&
1070 fetch_supersect(newsbfd, new_sect)->type == SS_TYPE_TEXT)
1071 return false;
1073 if (!bfd_is_und_section(new_sect) && new_offset != 0 &&
1074 fetch_supersect(oldsbfd, old_sect)->type == SS_TYPE_TEXT)
1075 return false;
1077 return strcmp(old_sym->name, new_sym->name) == 0 &&
1078 old_offset == new_offset;
1081 if (bfd_is_const_section(old_sect) || bfd_is_const_section(new_sect))
1082 DIE;
1084 struct supersect *old_ss = fetch_supersect(oldsbfd, old_sect);
1085 struct supersect *new_ss = fetch_supersect(newsbfd, new_sect);
1086 struct span *old_span = reloc_target_span(old_src_ss, old_reloc);
1087 struct span *new_span = reloc_target_span(new_src_ss, new_reloc);
1089 if (old_span->match != new_span || new_span->match != old_span) {
1090 debug1(newsbfd, "Nonmatching relocs from %s to %s/%s\n",
1091 new_src_ss->name, old_span->label, new_span->label);
1092 return false;
1095 if (old_sym->value + old_offset - old_span->start !=
1096 new_sym->value + new_offset - new_span->start) {
1097 debug1(newsbfd, "Offsets to %s/%s differ between %s "
1098 "and %s: %lx+%lx/%lx+%lx\n", old_ss->name,
1099 new_ss->name, old_src_ss->name, new_src_ss->name,
1100 (unsigned long)old_sym->value, (unsigned long)old_offset,
1101 (unsigned long)new_sym->value,
1102 (unsigned long)new_offset);
1103 return false;
1106 if ((old_sym->value + old_offset - old_span->start != 0 ||
1107 new_sym->value + new_offset - new_span->start != 0) &&
1108 new_span->patch) {
1109 debug1(newsbfd, "Relocation from %s to nonzero offsets "
1110 "%lx+%lx/%lx+%lx in changed section %s\n",
1111 new_src_ss->name, (unsigned long)old_sym->value,
1112 (unsigned long)old_offset, (unsigned long)new_sym->value,
1113 (unsigned long)new_offset, new_sym->section->name);
1114 return false;
1116 return true;
1119 bool all_relocs_equal(struct span *old_span, struct span *new_span)
1121 struct supersect *old_ss = old_span->ss, *new_ss = new_span->ss;
1122 arelent **old_relocp, **new_relocp;
1124 for (old_relocp = old_ss->relocs.data;
1125 old_relocp < old_ss->relocs.data + old_ss->relocs.size;
1126 old_relocp++) {
1127 if (find_span(old_ss, (*old_relocp)->address) == old_span)
1128 break;
1131 for (new_relocp = new_ss->relocs.data;
1132 new_relocp < new_ss->relocs.data + new_ss->relocs.size;
1133 new_relocp++) {
1134 if (find_span(new_ss, (*new_relocp)->address) == new_span)
1135 break;
1138 for (; old_relocp < old_ss->relocs.data + old_ss->relocs.size &&
1139 find_span(old_ss, (*old_relocp)->address) == old_span &&
1140 new_relocp < new_ss->relocs.data + new_ss->relocs.size &&
1141 find_span(new_ss, (*new_relocp)->address) == new_span;
1142 old_relocp++, new_relocp++) {
1143 if (!relocs_equal(old_ss, new_ss, *old_relocp, *new_relocp))
1144 return false;
1147 if ((old_relocp < old_ss->relocs.data + old_ss->relocs.size &&
1148 find_span(old_ss, (*old_relocp)->address) == old_span) ||
1149 (new_relocp < new_ss->relocs.data + new_ss->relocs.size &&
1150 find_span(new_ss, (*new_relocp)->address) == new_span)) {
1151 debug1(new_ss->parent, "Different reloc count between %s and "
1152 "%s\n", old_span->label, new_span->label);
1153 return false;
1156 return true;
1159 bfd_vma non_dst_mask(struct supersect *ss, arelent *reloc)
1161 int bits = bfd_get_reloc_size(reloc->howto) * 8;
1162 void *address = ss->contents.data + reloc->address;
1163 bfd_vma x = bfd_get(bits, ss->parent->abfd, address);
1164 return x & ~reloc->howto->dst_mask;
1167 void rm_some_exports(struct superbfd *sbfd, const struct export_desc *ed)
1169 struct supersect *ss = ed->sym_ss;
1170 struct supersect *crc_ss = ed->crc_ss;
1171 if (crc_ss != NULL)
1172 assert(ss->contents.size * sizeof(unsigned long) ==
1173 crc_ss->contents.size * sizeof(struct kernel_symbol));
1175 struct kernel_symbol *ksym;
1176 unsigned long *crc = NULL;
1177 if (crc_ss != NULL)
1178 crc = crc_ss->contents.data;
1179 struct span *span, *crc_span;
1180 for (ksym = ss->contents.data;
1181 (void *)ksym < ss->contents.data + ss->contents.size;
1182 ksym++, crc++) {
1183 asymbol *sym;
1184 read_reloc(ss, &ksym->value, sizeof(ksym->value), &sym);
1185 span = new_span(ss, addr_offset(ss, ksym), sizeof(*ksym));
1186 if (str_in_set(sym->name, &ed->names))
1187 keep_span(span);
1189 if (crc_ss != NULL) {
1190 crc_span = new_span(crc_ss, addr_offset(crc_ss, crc),
1191 sizeof(*crc));
1192 if (span->keep)
1193 keep_span(crc_span);
1196 if (span->keep) {
1197 /* Replace name with a mangled name */
1198 write_string(ss, (const char **)&ksym->name,
1199 "DISABLED_%s_%s", sym->name, kid);
1204 void rm_relocs(struct superbfd *isbfd)
1206 asection *p;
1207 for (p = isbfd->abfd->sections; p != NULL; p = p->next) {
1208 struct supersect *ss = fetch_supersect(isbfd, p);
1209 bool remove_relocs = ss->keep;
1211 if (mode("keep") && ss->type == SS_TYPE_SPECIAL)
1212 remove_relocs = false;
1214 if (ss->type == SS_TYPE_KSPLICE)
1215 remove_relocs = false;
1216 if (mode("finalize") &&
1217 (starts_with(ss->name, ".ksplice_patches") ||
1218 starts_with(ss->name, ".ksplice_relocs")))
1219 remove_relocs = true;
1221 if (remove_relocs)
1222 rm_some_relocs(ss);
1226 void rm_some_relocs(struct supersect *ss)
1228 struct arelentp_vec orig_relocs;
1229 vec_move(&orig_relocs, &ss->relocs);
1231 arelent **relocp;
1232 for (relocp = orig_relocs.data;
1233 relocp < orig_relocs.data + orig_relocs.size; relocp++) {
1234 bool rm_reloc = false;
1235 asymbol *sym_ptr = *(*relocp)->sym_ptr_ptr;
1237 if (mode("rmsyms") && str_in_set(sym_ptr->name, &rmsyms) &&
1238 bfd_is_und_section(sym_ptr->section))
1239 rm_reloc = true;
1241 if (mode("keep"))
1242 rm_reloc = true;
1244 if (mode("keep-primary") &&
1245 (bfd_is_const_section(sym_ptr->section) ||
1246 reloc_target_span(ss, *relocp)->new))
1247 rm_reloc = false;
1249 if (mode("finalize") && bfd_is_und_section(sym_ptr->section))
1250 rm_reloc = true;
1252 if (strcmp(sym_ptr->name, "mcount") == 0 &&
1253 bfd_is_und_section(sym_ptr->section))
1254 rm_reloc = false;
1256 if (!find_span(ss, (*relocp)->address)->keep)
1257 rm_reloc = false;
1259 if (rm_reloc)
1260 write_ksplice_reloc(ss, *relocp);
1261 else
1262 *vec_grow(&ss->relocs, 1) = *relocp;
1266 struct supersect *make_section(struct superbfd *sbfd, const char *fmt, ...)
1268 va_list ap;
1269 char *name;
1270 va_start(ap, fmt);
1271 assert(vasprintf(&name, fmt, ap) >= 0);
1272 va_end(ap);
1274 asection *sect = bfd_get_section_by_name(sbfd->abfd, name);
1275 if (sect != NULL)
1276 return fetch_supersect(sbfd, sect);
1277 else
1278 return new_supersect(sbfd, name);
1281 arelent *create_reloc(struct supersect *ss, const void *addr, asymbol **symp,
1282 bfd_vma offset)
1284 bfd_reloc_code_real_type code;
1285 switch (bfd_arch_bits_per_address(ss->parent->abfd)) {
1286 case 32:
1287 code = BFD_RELOC_32;
1288 break;
1289 case 64:
1290 code = BFD_RELOC_64;
1291 break;
1292 default:
1293 DIE;
1296 arelent *reloc = malloc(sizeof(*reloc));
1297 reloc->sym_ptr_ptr = symp;
1298 reloc->address = addr_offset(ss, addr);
1299 reloc->howto = bfd_reloc_type_lookup(ss->parent->abfd, code);
1300 reloc->addend = offset;
1301 return reloc;
1304 void write_reloc(struct supersect *ss, const void *addr, asymbol **symp,
1305 bfd_vma offset)
1307 *vec_grow(&ss->new_relocs, 1) = create_reloc(ss, addr, symp, offset);
1310 void write_string(struct supersect *ss, const char **addr, const char *fmt, ...)
1312 va_list ap;
1313 struct supersect *str_ss = make_section(ss->parent, ".ksplice_str");
1314 char *str;
1315 va_start(ap, fmt);
1316 int len = vasprintf(&str, fmt, ap);
1317 assert(len >= 0);
1318 va_end(ap);
1320 unsigned long *str_offp = ulong_hash_lookup(&ksplice_string_offset, str,
1321 FALSE);
1322 if (str_offp == NULL) {
1323 char *buf = sect_grow(str_ss, len + 1, char);
1324 memcpy(buf, str, len + 1);
1325 str_offp = ulong_hash_lookup(&ksplice_string_offset, str, TRUE);
1326 *str_offp = addr_offset(str_ss, buf);
1329 write_reloc(ss, addr, &str_ss->symbol, *str_offp);
1332 void lookup_system_map(struct addr_vec *addrs, const char *name, long offset)
1334 struct addr_vec *map_addrs =
1335 addr_vec_hash_lookup(&system_map, name, FALSE);
1336 if (map_addrs == NULL)
1337 return;
1339 unsigned long *addr, *map_addr;
1340 for (map_addr = map_addrs->data;
1341 map_addr < map_addrs->data + map_addrs->size; map_addr++) {
1342 for (addr = addrs->data; addr < addrs->data + addrs->size;
1343 addr++) {
1344 if (*addr == *map_addr + offset)
1345 break;
1347 if (addr < addrs->data + addrs->size)
1348 continue;
1349 *vec_grow(addrs, 1) = *map_addr + offset;
1353 void compute_system_map_array(struct superbfd *sbfd, struct addr_vec *addrs,
1354 asymbol *sym)
1356 if (bfd_is_abs_section(sym->section)) {
1357 *vec_grow(addrs, 1) = sym->value;
1358 } else if (bfd_is_und_section(sym->section)) {
1359 lookup_system_map(addrs, sym->name, 0);
1360 } else if (!bfd_is_const_section(sym->section)) {
1361 asymbol **gsymp;
1362 for (gsymp = sbfd->syms.data;
1363 gsymp < sbfd->syms.data + sbfd->syms.size; gsymp++) {
1364 asymbol *gsym = *gsymp;
1365 if ((gsym->flags & BSF_DEBUGGING) == 0 &&
1366 gsym->section == sym->section)
1367 lookup_system_map(addrs, gsym->name,
1368 sym->value - gsym->value);
1373 void write_ksplice_system_map(struct superbfd *sbfd, asymbol *sym,
1374 const char *label)
1376 bool *done = bool_hash_lookup(&system_map_written, label, TRUE);
1377 if (*done)
1378 return;
1379 *done = true;
1381 struct addr_vec addrs;
1382 vec_init(&addrs);
1384 compute_system_map_array(sbfd, &addrs, sym);
1385 if (addrs.size != 0) {
1386 struct supersect *smap_ss =
1387 make_section(sbfd, ".ksplice_system_map");
1388 struct ksplice_system_map *smap =
1389 sect_grow(smap_ss, 1, struct ksplice_system_map);
1390 write_string(smap_ss, &smap->label, "%s", label);
1392 struct supersect *array_ss = make_section(sbfd,
1393 ".ksplice_array");
1394 void *buf = sect_grow(array_ss, addrs.size,
1395 typeof(*addrs.data));
1396 memcpy(buf, addrs.data, addrs.size * sizeof(*addrs.data));
1397 smap->nr_candidates = addrs.size;
1398 write_reloc(smap_ss, &smap->candidates, &array_ss->symbol,
1399 addr_offset(array_ss, buf));
1401 vec_free(&addrs);
1404 void write_ksplice_symbol_backend(struct supersect *ss,
1405 struct ksplice_symbol *const *addr,
1406 asymbol *sym, const char *label,
1407 const char *name)
1409 struct supersect *ksymbol_ss = make_section(ss->parent,
1410 ".ksplice_symbols");
1411 struct ksplice_symbol *ksymbol;
1412 unsigned long *ksymbol_offp;
1414 ksymbol_offp = ulong_hash_lookup(&ksplice_symbol_offset, label, FALSE);
1415 if (ksymbol_offp != NULL) {
1416 write_reloc(ss, addr, &ksymbol_ss->symbol, *ksymbol_offp);
1417 return;
1419 ksymbol = sect_grow(ksymbol_ss, 1, struct ksplice_symbol);
1420 ksymbol_offp = ulong_hash_lookup(&ksplice_symbol_offset, label, TRUE);
1421 *ksymbol_offp = addr_offset(ksymbol_ss, ksymbol);
1423 write_reloc(ss, addr, &ksymbol_ss->symbol, *ksymbol_offp);
1424 write_string(ksymbol_ss, &ksymbol->label, "%s", label);
1425 if (name != NULL) {
1426 write_string(ksymbol_ss, &ksymbol->name, "%s", name);
1427 write_ksplice_system_map(ksymbol_ss->parent, sym, label);
1431 void write_ksplice_symbol(struct supersect *ss,
1432 struct ksplice_symbol *const *addr,
1433 asymbol *sym, struct span *span,
1434 const char *addstr_sect)
1436 const char *label, *name;
1437 char *output;
1438 if (span != NULL && span->start != 0)
1439 label = span->label;
1440 else
1441 label = label_lookup(ss->parent, sym);
1443 assert(asprintf(&output, "%s%s", label, addstr_sect) >= 0);
1445 asymbol *gsym = canonical_symbol(ss->parent, sym);
1446 if (strcmp(addstr_sect, "") != 0)
1447 name = NULL;
1448 else if (bfd_is_und_section(sym->section))
1449 name = sym->name;
1450 else if (bfd_is_const_section(sym->section))
1451 name = NULL;
1452 else if (span != NULL && span->symbol == NULL)
1453 name = NULL;
1454 else if (gsym == NULL || (gsym->flags & BSF_SECTION_SYM) != 0)
1455 name = NULL;
1456 else
1457 name = gsym->name;
1459 write_ksplice_symbol_backend(ss, addr, sym, output, name);
1462 void write_ksplice_reloc(struct supersect *ss, arelent *orig_reloc)
1464 asymbol *sym_ptr = *orig_reloc->sym_ptr_ptr;
1465 bfd_vma reloc_addend = get_reloc_offset(ss, orig_reloc, false);
1466 bfd_vma target_addend = get_reloc_offset(ss, orig_reloc, true);
1467 unsigned long *repladdr = ss->contents.data + orig_reloc->address;
1469 if (mode("finalize") && starts_with(ss->name, ".ksplice_patches")) {
1470 *repladdr = 0;
1471 return;
1473 if (mode("finalize") && starts_with(ss->name, ".ksplice_relocs")) {
1474 assert(starts_with(sym_ptr->name, KSPLICE_SYMBOL_STR));
1475 asymbol fake_sym;
1476 fake_sym.name = sym_ptr->name + strlen(KSPLICE_SYMBOL_STR);
1477 fake_sym.section = bfd_und_section_ptr;
1478 fake_sym.value = 0;
1479 fake_sym.flags = 0;
1481 write_ksplice_symbol_backend
1482 (ss, (struct ksplice_symbol **)repladdr, &fake_sym,
1483 fake_sym.name, fake_sym.name);
1484 return;
1487 struct span *span = reloc_target_span(ss, orig_reloc);
1488 if (span == ss->spans.data && span->start != target_addend)
1489 span = NULL;
1490 blot_section(ss, orig_reloc->address, orig_reloc->howto);
1492 struct supersect *kreloc_ss;
1493 if (mode("rmsyms"))
1494 kreloc_ss = make_section(ss->parent, ".ksplice_init_relocs");
1495 else
1496 kreloc_ss = make_section(ss->parent, ".ksplice_relocs%s",
1497 ss->name);
1498 struct ksplice_reloc *kreloc = sect_grow(kreloc_ss, 1,
1499 struct ksplice_reloc);
1501 struct span *address_span = find_span(ss, orig_reloc->address);
1502 write_reloc(kreloc_ss, &kreloc->blank_addr,
1503 &ss->symbol, orig_reloc->address + address_span->shift);
1504 if (bfd_is_und_section(sym_ptr->section) && mode("keep")) {
1505 char *name;
1506 assert(asprintf(&name, KSPLICE_SYMBOL_STR "%s", sym_ptr->name)
1507 >= 0);
1508 asymbol **symp = make_undefined_symbolp(ss->parent, name);
1509 write_reloc(kreloc_ss, &kreloc->symbol, symp, 0);
1510 } else {
1511 write_ksplice_symbol(kreloc_ss, &kreloc->symbol, sym_ptr, span,
1512 "");
1514 if (span != NULL && span->start != 0) {
1515 reloc_addend += sym_ptr->value - span->start;
1516 target_addend += sym_ptr->value - span->start;
1518 kreloc->insn_addend = reloc_addend - target_addend;
1519 kreloc->target_addend = target_addend;
1520 write_ksplice_reloc_howto(kreloc_ss, &kreloc->howto, orig_reloc->howto);
1523 static void write_ksplice_reloc_howto(struct supersect *ss, const
1524 struct ksplice_reloc_howto *const *addr,
1525 reloc_howto_type *howto)
1527 struct supersect *khowto_ss = make_section(ss->parent,
1528 ".ksplice_reloc_howtos");
1529 struct ksplice_reloc_howto *khowto;
1530 unsigned long *khowto_offp;
1532 khowto_offp = ulong_hash_lookup(&ksplice_howto_offset, howto->name,
1533 FALSE);
1534 if (khowto_offp != NULL) {
1535 write_reloc(ss, addr, &khowto_ss->symbol, *khowto_offp);
1536 return;
1538 khowto = sect_grow(khowto_ss, 1, struct ksplice_reloc_howto);
1539 khowto_offp = ulong_hash_lookup(&ksplice_howto_offset, howto->name,
1540 TRUE);
1541 *khowto_offp = addr_offset(khowto_ss, khowto);
1543 khowto->type = KSPLICE_HOWTO_RELOC;
1544 khowto->pcrel = howto->pc_relative;
1545 khowto->size = bfd_get_reloc_size(howto);
1546 khowto->dst_mask = howto->dst_mask;
1547 khowto->rightshift = howto->rightshift;
1548 khowto->signed_addend =
1549 (howto->complain_on_overflow == complain_overflow_signed) ||
1550 (howto->complain_on_overflow == complain_overflow_bitfield);
1551 write_reloc(ss, addr, &khowto_ss->symbol, *khowto_offp);
1554 #define CANARY(x, canary) ((x & ~howto->dst_mask) | (canary & howto->dst_mask))
1556 void blot_section(struct supersect *ss, int offset, reloc_howto_type *howto)
1558 int bits = bfd_get_reloc_size(howto) * 8;
1559 void *address = ss->contents.data + offset;
1560 bfd_vma x = bfd_get(bits, ss->parent->abfd, address);
1561 x = (x & ~howto->dst_mask) |
1562 ((bfd_vma)KSPLICE_CANARY & howto->dst_mask);
1563 bfd_put(bits, ss->parent->abfd, x, address);
1566 static void write_date_relocs(struct superbfd *sbfd, const char *str,
1567 enum ksplice_reloc_howto_type type)
1569 asection *sect;
1570 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
1571 struct supersect *ss = fetch_supersect(sbfd, sect);
1572 if (ss->type != SS_TYPE_STRING && ss->type != SS_TYPE_RODATA)
1573 continue;
1574 void *ptr;
1575 for (ptr = ss->contents.data;
1576 ptr + strlen(str) < ss->contents.data + ss->contents.size;
1577 ptr++) {
1578 if (strcmp((const char *)ptr, str) == 0)
1579 write_ksplice_date_reloc(ss,
1580 addr_offset(ss, ptr),
1581 str, type);
1586 static void write_ksplice_date_reloc(struct supersect *ss, unsigned long offset,
1587 const char *str,
1588 enum ksplice_reloc_howto_type type)
1590 struct supersect *kreloc_ss;
1591 kreloc_ss = make_section(ss->parent, ".ksplice_relocs%s", ss->name);
1592 struct ksplice_reloc *kreloc = sect_grow(kreloc_ss, 1,
1593 struct ksplice_reloc);
1595 const char *filename = ss->parent->abfd->filename;
1596 char *c = strstr(filename, ".KSPLICE");
1597 int flen = (c == NULL ? strlen(filename) : c - filename);
1599 char *label;
1600 assert(asprintf(&label, "%s<%.*s>", str, flen, filename) >= 0);
1601 write_ksplice_symbol_backend(kreloc_ss, &kreloc->symbol, NULL,
1602 label, NULL);
1604 struct span *span = find_span(ss, offset);
1605 write_reloc(kreloc_ss, &kreloc->blank_addr, &ss->symbol,
1606 offset + span->shift);
1607 write_ksplice_nonreloc_howto(kreloc_ss, &kreloc->howto, type,
1608 strlen(str));
1611 static void write_ksplice_nonreloc_howto(struct supersect *ss,
1612 const struct ksplice_reloc_howto
1613 *const *addr,
1614 enum ksplice_reloc_howto_type type,
1615 int size)
1617 struct supersect *khowto_ss =
1618 make_section(ss->parent, ".ksplice_reloc_howtos");
1619 struct ksplice_reloc_howto *khowto =
1620 sect_grow(khowto_ss, 1, struct ksplice_reloc_howto);
1622 khowto->type = type;
1623 khowto->size = size;
1624 khowto->pcrel = 0;
1625 khowto->dst_mask = 0;
1626 khowto->rightshift = 0;
1627 khowto->signed_addend = 0;
1628 write_reloc(ss, addr, &khowto_ss->symbol,
1629 addr_offset(khowto_ss, khowto));
1632 static void write_ksplice_section(struct span *span)
1634 struct supersect *ss = span->ss;
1635 struct supersect *ksect_ss =
1636 make_section(ss->parent, ".ksplice_sections%s", span->ss->name);
1637 struct ksplice_section *ksect = sect_grow(ksect_ss, 1,
1638 struct ksplice_section);
1639 asymbol *sym = span->symbol == NULL ? ss->symbol : span->symbol;
1641 write_ksplice_symbol(ksect_ss, &ksect->symbol, sym, span,
1642 mode("keep-primary") ? "(post)" : "");
1643 ksect->size = span->size;
1644 ksect->flags = 0;
1646 if (ss->type == SS_TYPE_RODATA || ss->type == SS_TYPE_STRING)
1647 ksect->flags |= KSPLICE_SECTION_RODATA;
1648 if (ss->type == SS_TYPE_DATA)
1649 ksect->flags |= KSPLICE_SECTION_DATA;
1650 if (ss->type == SS_TYPE_TEXT)
1651 ksect->flags |= KSPLICE_SECTION_TEXT;
1652 assert(ksect->flags != 0);
1654 if (ss->type == SS_TYPE_STRING)
1655 ksect->flags |= KSPLICE_SECTION_STRING;
1657 write_reloc(ksect_ss, &ksect->address, &ss->symbol,
1658 span->start + span->shift);
1661 void write_ksplice_patch(struct superbfd *sbfd, struct span *span)
1663 struct supersect *kpatch_ss =
1664 make_section(sbfd, ".ksplice_patches%s", span->ss->name);
1665 struct ksplice_patch *kpatch = sect_grow(kpatch_ss, 1,
1666 struct ksplice_patch);
1668 write_ksplice_symbol_backend(kpatch_ss, &kpatch->symbol, NULL,
1669 span->label, NULL);
1670 write_reloc(kpatch_ss, &kpatch->repladdr, &span->ss->symbol,
1671 span->start + span->shift);
1674 asymbol **make_undefined_symbolp(struct superbfd *sbfd, const char *name)
1676 asymbol **symp;
1677 for (symp = sbfd->syms.data; symp < sbfd->syms.data + sbfd->syms.size;
1678 symp++) {
1679 asymbol *sym = *symp;
1680 if (strcmp(name, sym->name) == 0 &&
1681 bfd_is_und_section(sym->section))
1682 return symp;
1684 asymbol ***sympp;
1685 for (sympp = sbfd->new_syms.data;
1686 sympp < sbfd->new_syms.data + sbfd->new_syms.size; sympp++) {
1687 asymbol **symp = *sympp;
1688 asymbol *sym = *symp;
1689 if (strcmp(name, sym->name) == 0 &&
1690 bfd_is_und_section(sym->section))
1691 return symp;
1694 symp = malloc(sizeof(*symp));
1695 *symp = bfd_make_empty_symbol(sbfd->abfd);
1696 asymbol *sym = *symp;
1697 sym->name = name;
1698 sym->section = bfd_und_section_ptr;
1699 sym->flags = 0;
1700 sym->value = 0;
1701 *vec_grow(&sbfd->new_syms, 1) = symp;
1702 return symp;
1705 void write_ksplice_deleted_patch(struct superbfd *sbfd, const char *name,
1706 const char *label, const char *sectname)
1708 struct supersect *kpatch_ss =
1709 make_section(sbfd, ".ksplice_patches%s", sectname);
1710 struct ksplice_patch *kpatch = sect_grow(kpatch_ss, 1,
1711 struct ksplice_patch);
1713 write_ksplice_symbol_backend(kpatch_ss, &kpatch->symbol, NULL,
1714 label, NULL);
1716 asymbol **symp = make_undefined_symbolp(sbfd, strdup(name));
1717 write_reloc(kpatch_ss, &kpatch->repladdr, symp, 0);
1720 void write_ksplice_export(struct superbfd *sbfd, const char *symname,
1721 const char *export_type, bool del)
1723 struct supersect *export_ss = make_section(sbfd, ".ksplice_exports");
1724 struct ksplice_export *exp = sect_grow(export_ss, 1,
1725 struct ksplice_export);
1727 if (del) {
1728 write_string(export_ss, &exp->name, "%s", symname);
1729 write_string(export_ss, &exp->new_name, "DISABLED_%s_%s",
1730 symname, kid);
1731 } else {
1732 write_string(export_ss, &exp->new_name, "%s", symname);
1733 write_string(export_ss, &exp->name, "DISABLED_%s_%s", symname,
1734 kid);
1738 void filter_table_sections(struct superbfd *isbfd)
1740 struct supersect *tables_ss =
1741 fetch_supersect(offsets_sbfd,
1742 bfd_get_section_by_name(offsets_sbfd->abfd,
1743 ".ksplice_table_sections"));
1744 const struct table_section *ts;
1745 for (ts = tables_ss->contents.data;
1746 (void *)ts < tables_ss->contents.data + tables_ss->contents.size;
1747 ts++) {
1748 struct table_section s = *ts;
1749 s.sect = read_string(tables_ss, &ts->sect);
1750 s.other_sect = read_string(tables_ss, &ts->other_sect);
1751 if (s.has_addr)
1752 filter_table_section(isbfd, &s);
1756 void filter_table_section(struct superbfd *sbfd, const struct table_section *s)
1758 asection *isection = bfd_get_section_by_name(sbfd->abfd, s->sect);
1759 if (isection == NULL)
1760 return;
1761 struct supersect *ss = fetch_supersect(sbfd, isection);
1763 void *entry;
1764 for (entry = ss->contents.data;
1765 entry < ss->contents.data + ss->contents.size;
1766 entry += s->entry_size) {
1767 asymbol *sym;
1768 struct span *span = find_span(ss, addr_offset(ss, entry));
1769 assert(span != NULL);
1771 read_reloc(ss, entry + s->addr_offset, sizeof(void *), &sym);
1772 struct supersect *sym_ss = fetch_supersect(sbfd, sym->section);
1773 if (sym_ss->keep)
1774 keep_span(span);
1776 if (s->other_sect != NULL) {
1777 arelent *reloc =
1778 find_reloc(ss, entry + s->other_offset);
1779 assert(reloc != NULL);
1780 struct span *sym_span = reloc_target_span(ss, reloc);
1781 if (span->keep)
1782 keep_span(sym_span);
1786 arelent **relocp;
1787 for (relocp = ss->relocs.data;
1788 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
1789 struct span *addr_span = find_span(ss, (*relocp)->address);
1790 struct span *target_span = reloc_target_span(ss, *relocp);
1791 if (addr_span->keep && mode("keep-primary"))
1792 keep_span(target_span);
1796 void keep_referenced_sections(struct superbfd *sbfd)
1798 asection *sect;
1799 struct supersect *ss, *sym_ss;
1800 struct span *address_span, *target_span;
1801 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
1802 ss = fetch_supersect(sbfd, sect);
1803 arelent **relocp;
1804 if (ss->type == SS_TYPE_SPECIAL || ss->type == SS_TYPE_EXPORT)
1805 continue;
1806 for (relocp = ss->relocs.data;
1807 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
1808 asymbol *sym = *(*relocp)->sym_ptr_ptr;
1809 address_span = find_span(ss, (*relocp)->address);
1810 if (!address_span->keep)
1811 continue;
1812 target_span = reloc_target_span(ss, *relocp);
1813 if (target_span == NULL || target_span->keep)
1814 continue;
1815 sym_ss = fetch_supersect(sbfd, sym->section);
1816 if (sym_ss->type == SS_TYPE_IGNORED)
1817 continue;
1818 keep_span(target_span);
1819 changed = true;
1824 void copy_symbols(struct asymbolp_vec *osyms, struct asymbolpp_vec *isyms)
1826 asymbol ***sympp;
1827 for (sympp = isyms->data; sympp < isyms->data + isyms->size; sympp++)
1828 *vec_grow(osyms, 1) = **sympp;
1831 /* Modified function from GNU Binutils objcopy.c */
1832 bfd_boolean copy_object(bfd *ibfd, bfd *obfd)
1834 assert(bfd_set_format(obfd, bfd_get_format(ibfd)));
1836 bfd_vma start = bfd_get_start_address(ibfd);
1838 flagword flags = bfd_get_file_flags(ibfd);
1839 flags &= bfd_applicable_file_flags(obfd);
1841 assert(bfd_set_start_address(obfd, start)
1842 && bfd_set_file_flags(obfd, flags));
1844 enum bfd_architecture iarch = bfd_get_arch(ibfd);
1845 unsigned int imach = bfd_get_mach(ibfd);
1846 assert(bfd_set_arch_mach(obfd, iarch, imach));
1847 assert(bfd_set_format(obfd, bfd_get_format(ibfd)));
1849 /* BFD mandates that all output sections be created and sizes set before
1850 any output is done. Thus, we traverse all sections multiple times. */
1851 bfd_map_over_sections(ibfd, setup_section, obfd);
1853 struct supersect *new_supersects = fetch_superbfd(ibfd)->new_supersects;
1854 struct supersect *ss;
1855 for (ss = new_supersects; ss != NULL; ss = ss->next)
1856 setup_new_section(obfd, ss);
1858 /* Mark symbols used in output relocations so that they
1859 are kept, even if they are local labels or static symbols.
1861 Note we iterate over the input sections examining their
1862 relocations since the relocations for the output sections
1863 haven't been set yet. mark_symbols_used_in_relocations will
1864 ignore input sections which have no corresponding output
1865 section. */
1867 bfd_map_over_sections(ibfd, mark_symbols_used_in_relocations, NULL);
1868 for (ss = new_supersects; ss != NULL; ss = ss->next)
1869 ss_mark_symbols_used_in_relocations(ss);
1870 struct asymbolp_vec osyms;
1871 vec_init(&osyms);
1872 filter_symbols(ibfd, obfd, &osyms, &fetch_superbfd(ibfd)->syms);
1873 copy_symbols(&osyms, &fetch_superbfd(ibfd)->new_syms);
1875 bfd_set_symtab(obfd, osyms.data, osyms.size);
1877 /* This has to happen after the symbol table has been set. */
1878 bfd_map_over_sections(obfd, write_section, NULL);
1880 /* Allow the BFD backend to copy any private data it understands
1881 from the input BFD to the output BFD. This is done last to
1882 permit the routine to look at the filtered symbol table, which is
1883 important for the ECOFF code at least. */
1884 assert(bfd_copy_private_bfd_data(ibfd, obfd));
1886 return TRUE;
1889 /* Modified function from GNU Binutils objcopy.c */
1890 void setup_section(bfd *ibfd, asection *isection, void *obfdarg)
1892 struct superbfd *isbfd = fetch_superbfd(ibfd);
1893 struct supersect *ss = fetch_supersect(isbfd, isection);
1894 bfd *obfd = obfdarg;
1895 bfd_vma vma;
1897 if (!ss->keep)
1898 return;
1900 asection *osection = bfd_make_section_anyway(obfd, ss->name);
1901 assert(osection != NULL);
1903 osection->userdata = ss;
1904 bfd_set_section_flags(obfd, osection, ss->flags);
1905 ss->symbol = osection->symbol;
1906 assert(bfd_set_section_size(obfd, osection, ss->contents.size));
1908 vma = bfd_section_vma(ibfd, isection);
1909 assert(bfd_set_section_vma(obfd, osection, vma));
1911 osection->lma = isection->lma;
1912 assert(bfd_set_section_alignment(obfd, osection, ss->alignment));
1913 osection->entsize = isection->entsize;
1914 osection->output_section = osection;
1915 osection->output_offset = 0;
1916 isection->output_section = osection;
1917 isection->output_offset = 0;
1918 return;
1921 void setup_new_section(bfd *obfd, struct supersect *ss)
1923 asection *osection = bfd_make_section_anyway(obfd, ss->name);
1924 assert(osection != NULL);
1925 bfd_set_section_flags(obfd, osection, ss->flags);
1927 osection->userdata = ss;
1928 ss->symbol = osection->symbol;
1929 assert(bfd_set_section_size(obfd, osection, ss->contents.size));
1930 assert(bfd_set_section_vma(obfd, osection, 0));
1932 osection->lma = 0;
1933 assert(bfd_set_section_alignment(obfd, osection, ss->alignment));
1934 osection->entsize = 0;
1935 osection->output_section = osection;
1936 osection->output_offset = 0;
1939 static int compare_reloc_addresses(const void *aptr, const void *bptr)
1941 const arelent *const *a = aptr, *const *b = bptr;
1942 return (*a)->address - (*b)->address;
1945 static void delete_obsolete_relocs(struct supersect *ss)
1947 if (ss->new_relocs.size == 0)
1948 return;
1950 qsort(ss->relocs.data, ss->relocs.size, sizeof(*ss->relocs.data),
1951 compare_reloc_addresses);
1952 qsort(ss->new_relocs.data, ss->new_relocs.size,
1953 sizeof(*ss->new_relocs.data), compare_reloc_addresses);
1955 struct arelentp_vec orig_relocs;
1956 vec_move(&orig_relocs, &ss->relocs);
1958 arelent **relocp, **new_relocp = ss->new_relocs.data;
1959 for (relocp = orig_relocs.data;
1960 relocp < orig_relocs.data + orig_relocs.size; relocp++) {
1961 while (new_relocp < ss->new_relocs.data + ss->new_relocs.size &&
1962 (*new_relocp)->address < (*relocp)->address)
1963 new_relocp++;
1964 arelent *reloc = *relocp, *new_reloc = *new_relocp;
1965 if (new_relocp == ss->new_relocs.data + ss->new_relocs.size ||
1966 reloc->address != new_reloc->address)
1967 *vec_grow(&ss->relocs, 1) = reloc;
1971 void write_section(bfd *obfd, asection *osection, void *arg)
1973 struct supersect *ss = osection->userdata;
1975 if ((ss->flags & SEC_GROUP) != 0 || ss->contents.size == 0)
1976 return;
1978 delete_obsolete_relocs(ss);
1980 arelent **relocp;
1981 char *error_message;
1982 for (relocp = ss->new_relocs.data;
1983 relocp < ss->new_relocs.data + ss->new_relocs.size; relocp++) {
1984 bfd_vma val;
1985 if (bfd_get_arch(obfd) == bfd_arch_arm)
1986 val = osection->use_rela_p ? 0 : (*relocp)->addend;
1987 else
1988 val = 0;
1989 bfd_put(bfd_get_reloc_size((*relocp)->howto) * 8, obfd, val,
1990 ss->contents.data + (*relocp)->address);
1991 if (bfd_install_relocation(obfd, *relocp, ss->contents.data,
1992 0, osection, &error_message) !=
1993 bfd_reloc_ok) {
1994 err(ss->parent, "ksplice: error installing reloc: %s",
1995 error_message);
1996 DIE;
1999 memcpy(vec_grow(&ss->relocs, ss->new_relocs.size), ss->new_relocs.data,
2000 ss->new_relocs.size * sizeof(*ss->new_relocs.data));
2002 bfd_set_reloc(obfd, osection,
2003 ss->relocs.size == 0 ? NULL : ss->relocs.data,
2004 ss->relocs.size);
2006 if (ss->flags & SEC_HAS_CONTENTS)
2007 assert(bfd_set_section_contents
2008 (obfd, osection, ss->contents.data, 0,
2009 ss->contents.size));
2012 /* Modified function from GNU Binutils objcopy.c
2014 * Mark all the symbols which will be used in output relocations with
2015 * the BSF_KEEP flag so that those symbols will not be stripped.
2017 * Ignore relocations which will not appear in the output file.
2019 void mark_symbols_used_in_relocations(bfd *abfd, asection *isection,
2020 void *ignored)
2022 struct superbfd *sbfd = fetch_superbfd(abfd);
2023 if (isection->output_section == NULL)
2024 return;
2026 struct supersect *ss = fetch_supersect(sbfd, isection);
2027 ss_mark_symbols_used_in_relocations(ss);
2030 void ss_mark_symbols_used_in_relocations(struct supersect *ss)
2032 /* Examine each symbol used in a relocation. If it's not one of the
2033 special bfd section symbols, then mark it with BSF_KEEP. */
2034 arelent **relocp;
2035 for (relocp = ss->relocs.data;
2036 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
2037 asymbol *sym = *(*relocp)->sym_ptr_ptr;
2038 if (!(bfd_is_const_section(sym->section) &&
2039 sym == sym->section->symbol))
2040 sym->flags |= BSF_KEEP;
2042 for (relocp = ss->new_relocs.data;
2043 relocp < ss->new_relocs.data + ss->new_relocs.size; relocp++) {
2044 asymbol *sym = *(*relocp)->sym_ptr_ptr;
2045 if (!(bfd_is_const_section(sym->section) &&
2046 sym == sym->section->symbol))
2047 sym->flags |= BSF_KEEP;
2051 static bool deleted_table_section_symbol(bfd *abfd, asymbol *sym)
2053 struct superbfd *sbfd = fetch_superbfd(abfd);
2054 if (bfd_is_const_section(sym->section))
2055 return false;
2056 struct supersect *ss = fetch_supersect(sbfd, sym->section);
2058 asymbol **symp;
2059 for (symp = ss->syms.data; symp < ss->syms.data + ss->syms.size; symp++) {
2060 if (sym == *symp)
2061 break;
2063 return symp >= ss->syms.data + ss->syms.size &&
2064 (sym->flags & BSF_SECTION_SYM) == 0;
2067 void filter_symbols(bfd *ibfd, bfd *obfd, struct asymbolp_vec *osyms,
2068 struct asymbolp_vec *isyms)
2070 asymbol **symp;
2071 struct superbfd *sbfd = fetch_superbfd(ibfd);
2072 for (symp = isyms->data; symp < isyms->data + isyms->size; symp++) {
2073 asymbol *sym = *symp;
2074 struct supersect *sym_ss = NULL;
2075 struct span *sym_span = NULL;
2076 if (!bfd_is_const_section(sym->section)) {
2077 sym_ss = fetch_supersect(sbfd, sym->section);
2078 sym_span = find_span(sym_ss, sym->value);
2081 if (mode("keep") && (sym->flags & BSF_GLOBAL) != 0 &&
2082 !(mode("keep-primary") && sym_span != NULL &&
2083 sym_span->new))
2084 sym->flags = (sym->flags & ~BSF_GLOBAL) | BSF_LOCAL;
2086 if (mode("finalize") && (sym->flags & BSF_GLOBAL) != 0)
2087 sym->flags = (sym->flags & ~BSF_GLOBAL) | BSF_LOCAL;
2089 bool keep = bfd_is_const_section(sym->section) ||
2090 (sym_ss->keep && (sym->flags & BSF_SECTION_SYM) != 0) ||
2091 (sym_span != NULL && sym_span->keep);
2092 if (bfd_is_und_section(sym->section) &&
2093 (sym->flags & BSF_KEEP) == 0)
2094 keep = false;
2095 if (deleted_table_section_symbol(ibfd, sym))
2096 keep = false;
2098 if (keep) {
2099 if (sym_ss != NULL && !sym_ss->keep) {
2100 err(sbfd, "Kept symbol %s in unkept section "
2101 "%s\n", sym->name, sym->section->name);
2102 DIE;
2104 *vec_grow(osyms, 1) = sym;
2109 void read_str_set(struct str_vec *strs)
2111 char *buf = NULL;
2112 size_t n = 0;
2113 assert(getline(&buf, &n, stdin) >= 0);
2114 vec_init(strs);
2115 char *saveptr;
2116 while (1) {
2117 char *str = strtok_r(buf, " \n", &saveptr);
2118 buf = NULL;
2119 if (str == NULL)
2120 break;
2121 *vec_grow(strs, 1) = str;
2125 bool str_in_set(const char *str, const struct str_vec *strs)
2127 const char **strp;
2128 for (strp = strs->data; strp < strs->data + strs->size; strp++) {
2129 if (strcmp(str, *strp) == 0)
2130 return true;
2132 return false;
2135 bool is_table_section(const char *name, bool consider_other)
2137 struct supersect *tables_ss =
2138 fetch_supersect(offsets_sbfd,
2139 bfd_get_section_by_name(offsets_sbfd->abfd,
2140 ".ksplice_table_sections"));
2141 const struct table_section *ts;
2142 for (ts = tables_ss->contents.data;
2143 (void *)ts < tables_ss->contents.data + tables_ss->contents.size;
2144 ts++) {
2145 if (strcmp(name, read_string(tables_ss, &ts->sect)) == 0)
2146 return true;
2147 const char *osect_name = read_string(tables_ss,
2148 &ts->other_sect);
2149 if (consider_other && osect_name != NULL &&
2150 strcmp(name, osect_name) == 0)
2151 return true;
2153 return false;
2156 const struct table_section *get_table_section(const char *name)
2158 struct supersect *tables_ss =
2159 fetch_supersect(offsets_sbfd,
2160 bfd_get_section_by_name(offsets_sbfd->abfd,
2161 ".ksplice_table_sections"));
2162 const struct table_section *ts;
2163 for (ts = tables_ss->contents.data;
2164 (void *)ts < tables_ss->contents.data + tables_ss->contents.size;
2165 ts++) {
2166 if (strcmp(name, read_string(tables_ss, &ts->sect)) == 0)
2167 return ts;
2169 return NULL;
2172 enum supersect_type supersect_type(struct supersect *ss)
2174 if (mode("finalize") &&
2175 strcmp(finalize_target, "vmlinux") == 0 &&
2176 (starts_with(ss->name, ".ksplice_relocs.exit") ||
2177 starts_with(ss->name, ".ksplice_sections.exit") ||
2178 starts_with(ss->name, ".ksplice_patches.exit")))
2179 return SS_TYPE_EXIT;
2180 if (starts_with(ss->name, ".ksplice"))
2181 return SS_TYPE_KSPLICE;
2183 if (starts_with(ss->name, ".init"))
2184 return SS_TYPE_IGNORED;
2185 if (starts_with(ss->name, ".security_initcall.init"))
2186 return SS_TYPE_IGNORED;
2187 if (starts_with(ss->name, ".con_initcall.init"))
2188 return SS_TYPE_IGNORED;
2189 if (starts_with(ss->name, ".x86cpuvendor.init"))
2190 return SS_TYPE_IGNORED;
2191 if (starts_with(ss->name, ".early_param.init"))
2192 return SS_TYPE_IGNORED;
2193 if (starts_with(ss->name, ".taglist.init"))
2194 return SS_TYPE_IGNORED;
2195 if (starts_with(ss->name, ".arch.info.init"))
2196 return SS_TYPE_IGNORED;
2197 if (starts_with(ss->name, ".proc.info.init"))
2198 return SS_TYPE_IGNORED;
2199 /* .pci_fixup_* sections really should be treated as global rodata
2200 referenced only from quirks.c */
2201 if (starts_with(ss->name, ".pci_fixup_"))
2202 return SS_TYPE_IGNORED;
2203 /* .builtin_fw sections are similar to .pci_fixup */
2204 if (starts_with(ss->name, ".builtin_fw"))
2205 return SS_TYPE_IGNORED;
2206 /* same for .tracedata */
2207 if (starts_with(ss->name, ".tracedata"))
2208 return SS_TYPE_IGNORED;
2209 if (starts_with(ss->name, ".debug"))
2210 return SS_TYPE_IGNORED;
2211 /* .eh_frame should probably be discarded, not ignored */
2212 if (starts_with(ss->name, ".eh_frame"))
2213 return SS_TYPE_IGNORED;
2214 if (config->ignore_devinit && starts_with(ss->name, ".devinit"))
2215 return SS_TYPE_IGNORED;
2216 if (config->ignore_meminit && starts_with(ss->name, ".meminit"))
2217 return SS_TYPE_IGNORED;
2218 if (config->ignore_cpuinit && starts_with(ss->name, ".cpuinit"))
2219 return SS_TYPE_IGNORED;
2220 if (config->ignore_devinit && starts_with(ss->name, ".devexit"))
2221 return SS_TYPE_IGNORED;
2222 if (config->ignore_meminit && starts_with(ss->name, ".memexit"))
2223 return SS_TYPE_IGNORED;
2224 if (config->ignore_cpuinit && starts_with(ss->name, ".cpuexit"))
2225 return SS_TYPE_IGNORED;
2226 if (starts_with(ss->name, ".vgetcpu_mode") ||
2227 starts_with(ss->name, ".jiffies") ||
2228 starts_with(ss->name, ".wall_jiffies") ||
2229 starts_with(ss->name, ".vxtime") ||
2230 starts_with(ss->name, ".sys_tz") ||
2231 starts_with(ss->name, ".sysctl_vsyscall") ||
2232 starts_with(ss->name, ".xtime") ||
2233 starts_with(ss->name, ".xtime_lock") ||
2234 starts_with(ss->name, ".vsyscall"))
2235 return SS_TYPE_IGNORED;
2236 if (starts_with(ss->name, ".vdso"))
2237 return SS_TYPE_IGNORED;
2239 if (starts_with(ss->name, ".exit.text"))
2240 return SS_TYPE_TEXT;
2241 if (starts_with(ss->name, ".exit.data"))
2242 return SS_TYPE_DATA;
2244 if (starts_with(ss->name, ".text") ||
2245 starts_with(ss->name, ".kernel.text") ||
2246 starts_with(ss->name, ".devinit.text") ||
2247 starts_with(ss->name, ".meminit.text") ||
2248 starts_with(ss->name, ".cpuinit.text") ||
2249 starts_with(ss->name, ".devexit.text") ||
2250 starts_with(ss->name, ".memexit.text") ||
2251 starts_with(ss->name, ".cpuexit.text") ||
2252 starts_with(ss->name, ".ref.text") ||
2253 starts_with(ss->name, ".spinlock.text") ||
2254 starts_with(ss->name, ".kprobes.text") ||
2255 starts_with(ss->name, ".sched.text"))
2256 return SS_TYPE_TEXT;
2258 int n = -1;
2259 if (sscanf(ss->name, ".rodata.str%*u.%*u%n", &n) >= 0 &&
2260 n == strlen(ss->name))
2261 return SS_TYPE_STRING;
2263 if (starts_with(ss->name, ".rodata") ||
2264 starts_with(ss->name, ".kernel.rodata") ||
2265 starts_with(ss->name, ".devinit.rodata") ||
2266 starts_with(ss->name, ".meminit.rodata") ||
2267 starts_with(ss->name, ".cpuinit.rodata") ||
2268 starts_with(ss->name, ".devexit.rodata") ||
2269 starts_with(ss->name, ".memexit.rodata") ||
2270 starts_with(ss->name, ".cpuexit.rodata") ||
2271 starts_with(ss->name, ".ref.rodata") ||
2272 starts_with(ss->name, "__markers_strings"))
2273 return SS_TYPE_RODATA;
2275 if (starts_with(ss->name, ".bss"))
2276 return SS_TYPE_DATA;
2278 /* Ignore .data.percpu sections */
2279 if (starts_with(ss->name, ".data.percpu") ||
2280 starts_with(ss->name, ".kernel.data.percpu"))
2281 return SS_TYPE_IGNORED;
2282 if (starts_with(ss->name, ".data") ||
2283 starts_with(ss->name, ".kernel.data") ||
2284 starts_with(ss->name, ".devinit.data") ||
2285 starts_with(ss->name, ".cpuinit.data") ||
2286 starts_with(ss->name, ".meminit.data") ||
2287 starts_with(ss->name, ".devexit.data") ||
2288 starts_with(ss->name, ".memexit.data") ||
2289 starts_with(ss->name, ".cpuexit.data") ||
2290 starts_with(ss->name, ".ref.data") ||
2291 starts_with(ss->name, "__markers"))
2292 return SS_TYPE_DATA;
2294 /* We replace all the ksymtab strings, so delete them */
2295 if (strcmp(ss->name, "__ksymtab_strings") == 0)
2296 return SS_TYPE_IGNORED;
2297 if (starts_with(ss->name, "__ksymtab"))
2298 return SS_TYPE_EXPORT;
2299 if (starts_with(ss->name, "__kcrctab"))
2300 return SS_TYPE_EXPORT;
2302 if (is_table_section(ss->name, true))
2303 return SS_TYPE_SPECIAL;
2305 if (starts_with(ss->name, ".ARM."))
2306 return SS_TYPE_SPECIAL;
2308 if (starts_with(ss->name, ".note"))
2309 return SS_TYPE_IGNORED;
2310 if (starts_with(ss->name, ".comment"))
2311 return SS_TYPE_IGNORED;
2312 if (starts_with(ss->name, "__param"))
2313 return SS_TYPE_IGNORED;
2314 if (starts_with(ss->name, ".exitcall.exit"))
2315 return SS_TYPE_IGNORED;
2316 if (starts_with(ss->name, ".modinfo"))
2317 return SS_TYPE_IGNORED;
2319 return SS_TYPE_UNKNOWN;
2322 void initialize_supersect_types(struct superbfd *sbfd)
2324 asection *sect;
2325 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2326 struct supersect *ss = fetch_supersect(sbfd, sect);
2327 ss->type = supersect_type(ss);
2328 if (ss->type == SS_TYPE_UNKNOWN) {
2329 err(sbfd, "Unknown section type: %s\n", ss->name);
2330 DIE;
2335 static void init_label_map(struct superbfd *sbfd)
2337 struct label_map *map;
2339 vec_init(&sbfd->maps);
2340 init_csyms(sbfd);
2341 init_callers(sbfd);
2343 struct symbol_hash csyms;
2344 symbol_hash_init(&csyms);
2346 asymbol **symp;
2347 for (symp = sbfd->syms.data;
2348 symp < sbfd->syms.data + sbfd->syms.size; symp++) {
2349 asymbol *csym = canonical_symbol(sbfd, *symp);
2350 if (csym == NULL)
2351 continue;
2352 char *key;
2353 assert(asprintf(&key, "%p", csym) >= 0);
2354 asymbol **csymp = symbol_hash_lookup(&csyms, key, TRUE);
2355 free(key);
2356 if (*csymp != NULL)
2357 continue;
2358 *csymp = csym;
2360 map = vec_grow(&sbfd->maps, 1);
2361 map->csym = csym;
2362 map->count = 0;
2363 map->label = symbol_label(sbfd, csym);
2366 struct label_mapp_hash label_maps;
2367 label_mapp_hash_init(&label_maps);
2368 for (map = sbfd->maps.data;
2369 map < sbfd->maps.data + sbfd->maps.size; map++) {
2370 struct label_map **mapp =
2371 label_mapp_hash_lookup(&label_maps, map->label, TRUE);
2372 if (*mapp == NULL) {
2373 *mapp = map;
2374 continue;
2377 struct label_map *first_map = *mapp;
2378 char *buf;
2379 if (first_map->count == 0) {
2380 assert(asprintf(&buf, "%s~%d", map->label, 0) >= 0);
2381 first_map->label = buf;
2383 first_map->count++;
2384 assert(asprintf(&buf, "%s~%d", map->label, first_map->count)
2385 >= 0);
2386 map->label = buf;
2389 label_mapp_hash_init(&sbfd->maps_hash);
2390 for (map = sbfd->maps.data;
2391 map < sbfd->maps.data + sbfd->maps.size; map++) {
2392 char *key;
2393 assert(asprintf(&key, "%p", map->csym) >= 0);
2394 struct label_map **mapp =
2395 label_mapp_hash_lookup(&sbfd->maps_hash, key, TRUE);
2396 free(key);
2397 *mapp = map;
2398 map->orig_label = map->label;
2402 static const char *label_lookup(struct superbfd *sbfd, asymbol *sym)
2404 asymbol *csym = canonical_symbol(sbfd, sym);
2405 char *key;
2406 assert(asprintf(&key, "%p", csym) >= 0);
2407 struct label_map **mapp =
2408 label_mapp_hash_lookup(&sbfd->maps_hash, key, FALSE);
2409 free(key);
2410 if (mapp == NULL)
2411 DIE;
2412 return (*mapp)->label;
2415 static void print_label_changes(struct superbfd *sbfd)
2417 asection *sect;
2418 struct span *span;
2419 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2420 struct supersect *ss = fetch_supersect(sbfd, sect);
2421 for (span = ss->spans.data;
2422 span < ss->spans.data + ss->spans.size; span++) {
2423 if (strcmp(span->label, span->orig_label) != 0)
2424 debug1(sbfd, "Label change: %s -> %s\n",
2425 span->label, span->orig_label);
2430 static void label_map_set(struct superbfd *sbfd, const char *oldlabel,
2431 const char *label)
2433 struct label_map *map;
2434 for (map = sbfd->maps.data;
2435 map < sbfd->maps.data + sbfd->maps.size; map++) {
2436 if (strcmp(map->orig_label, oldlabel) == 0) {
2437 if (strcmp(map->orig_label, map->label) != 0 &&
2438 strcmp(map->label, label) != 0)
2439 DIE;
2440 map->label = label;
2441 return;
2444 DIE;
2447 static void init_callers(struct superbfd *sbfd)
2449 string_hash_init(&sbfd->callers);
2450 asection *sect;
2451 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2452 struct supersect *ss = fetch_supersect(sbfd, sect);
2453 arelent **relocp;
2454 for (relocp = ss->relocs.data;
2455 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
2456 asymbol *sym = *(*relocp)->sym_ptr_ptr;
2457 unsigned long val =
2458 sym->value + get_reloc_offset(ss, *relocp, true);
2459 char *key;
2460 assert(asprintf(&key, "%s+%lx", sym->section->name,
2461 val) >= 0);
2462 const char **ret = string_hash_lookup(&sbfd->callers,
2463 key, TRUE);
2464 free(key);
2465 if (*ret == NULL)
2466 *ret = sect->name;
2467 else
2468 *ret = "*multiple_callers*";
2473 static const char *find_caller(struct supersect *ss, asymbol *sym)
2475 char *key;
2476 assert(asprintf(&key, "%s+%lx", sym->section->name,
2477 (unsigned long)sym->value) >= 0);
2478 const char **ret = string_hash_lookup(&ss->parent->callers, key, FALSE);
2479 free(key);
2481 if (ret == NULL)
2482 return "*no_caller*";
2483 return *ret;
2486 static void init_csyms(struct superbfd *sbfd)
2488 asymbolpp_hash_init(&sbfd->csyms);
2490 asymbol **symp;
2491 for (symp = sbfd->syms.data; symp < sbfd->syms.data + sbfd->syms.size;
2492 symp++) {
2493 asymbol *sym = *symp;
2494 if ((sym->flags & BSF_DEBUGGING) != 0)
2495 continue;
2496 char *key;
2497 assert(asprintf(&key, "%s+%lx", sym->section->name,
2498 (unsigned long)sym->value) >= 0);
2499 asymbol ***csympp = asymbolpp_hash_lookup(&sbfd->csyms, key,
2500 TRUE);
2501 free(key);
2502 if (*csympp == NULL) {
2503 *csympp = symp;
2504 continue;
2506 asymbol *csym = **csympp;
2507 if ((csym->flags & BSF_GLOBAL) != 0)
2508 continue;
2509 if ((sym->flags & BSF_GLOBAL) != 0)
2510 *csympp = symp;
2514 static asymbol **symbolp_scan(struct supersect *ss, bfd_vma value)
2516 char *key;
2517 assert(asprintf(&key, "%s+%lx", ss->name, (unsigned long)value) >= 0);
2518 asymbol ***csympp =
2519 asymbolpp_hash_lookup(&ss->parent->csyms, key, FALSE);
2520 free(key);
2521 if (csympp != NULL)
2522 return *csympp;
2524 /* For section symbols of sections containing no symbols, return the
2525 section symbol that relocations are generated against */
2526 if (value == 0)
2527 return &ss->symbol;
2528 return NULL;
2531 static asymbol **canonical_symbolp(struct superbfd *sbfd, asymbol *sym)
2533 if (bfd_is_const_section(sym->section)) {
2534 asymbol **csymp;
2535 for (csymp = sbfd->syms.data;
2536 csymp < sbfd->syms.data + sbfd->syms.size; csymp++) {
2537 if (sym == *csymp)
2538 return csymp;
2540 return NULL;
2542 return symbolp_scan(fetch_supersect(sbfd, sym->section), sym->value);
2545 static asymbol *canonical_symbol(struct superbfd *sbfd, asymbol *sym)
2547 if (bfd_is_const_section(sym->section))
2548 return sym;
2549 asymbol **symp = canonical_symbolp(sbfd, sym);
2550 return symp != NULL ? *symp : NULL;
2553 static char *static_local_symbol(struct superbfd *sbfd, asymbol *sym)
2555 struct supersect *ss = fetch_supersect(sbfd, sym->section);
2556 if ((sym->flags & BSF_LOCAL) == 0 || (sym->flags & BSF_OBJECT) == 0)
2557 return NULL;
2558 char *dot = strrchr(sym->name, '.');
2559 if (dot == NULL || dot[1 + strspn(dot + 1, "0123546789")] != '\0')
2560 return NULL;
2561 char *basename = strndup(sym->name, dot - sym->name);
2562 char *mangled_name;
2563 if (strcmp(basename, "__func__") == 0 ||
2564 strcmp(basename, "__PRETTY_FUNCTION__") == 0)
2565 assert(asprintf(&mangled_name, "%s<%s>", basename,
2566 (char *)ss->contents.data + sym->value) >= 0);
2567 else
2568 assert(asprintf(&mangled_name, "%s<%s>", basename,
2569 find_caller(ss, sym)) >= 0);
2570 return mangled_name;
2573 static char *symbol_label(struct superbfd *sbfd, asymbol *sym)
2575 const char *filename = sbfd->abfd->filename;
2576 char *c = strstr(filename, ".KSPLICE");
2577 int flen = (c == NULL ? strlen(filename) : c - filename);
2579 char *label;
2580 if (bfd_is_und_section(sym->section) || (sym->flags & BSF_GLOBAL) != 0) {
2581 label = strdup(sym->name);
2582 } else if (bfd_is_const_section(sym->section)) {
2583 assert(asprintf(&label, "%s<%.*s>",
2584 sym->name, flen, filename) >= 0);
2585 } else {
2586 asymbol *gsym = canonical_symbol(sbfd, sym);
2588 if (gsym == NULL)
2589 assert(asprintf(&label, "%s+%lx<%.*s>",
2590 sym->section->name,
2591 (unsigned long)sym->value,
2592 flen, filename) >= 0);
2593 else if ((gsym->flags & BSF_GLOBAL) != 0)
2594 label = strdup(gsym->name);
2595 else if (static_local_symbol(sbfd, gsym))
2596 assert(asprintf(&label, "%s+%lx<%.*s>",
2597 static_local_symbol(sbfd, gsym),
2598 (unsigned long)sym->value,
2599 flen, filename) >= 0);
2600 else
2601 assert(asprintf(&label, "%s<%.*s>",
2602 gsym->name, flen, filename) >= 0);
2605 return label;
2608 static void keep_span(struct span *span)
2610 span->keep = true;
2611 span->ss->keep = true;
2614 static struct span *new_span(struct supersect *ss, bfd_vma start, bfd_vma size)
2616 struct span *span = vec_grow(&ss->spans, 1);
2617 span->size = size;
2618 span->start = start;
2619 span->ss = ss;
2620 span->keep = true;
2621 span->new = false;
2622 span->patch = false;
2623 span->match = NULL;
2624 span->shift = 0;
2625 asymbol **symp = symbolp_scan(ss, span->start);
2626 if (symp != NULL) {
2627 span->symbol = *symp;
2628 span->label = label_lookup(ss->parent, span->symbol);
2629 } else {
2630 span->symbol = NULL;
2631 const char *label = label_lookup(ss->parent, ss->symbol);
2632 if (span->start != 0) {
2633 char *buf;
2634 assert(asprintf(&buf, "%s<span:%lx>", label,
2635 (unsigned long)span->start) >= 0);
2636 span->label = buf;
2637 } else {
2638 span->label = label;
2641 span->orig_label = span->label;
2642 return span;
2645 static void initialize_string_spans(struct supersect *ss)
2647 const char *str;
2648 for (str = ss->contents.data;
2649 (void *)str < ss->contents.data + ss->contents.size;) {
2650 bfd_vma start = (unsigned long)str -
2651 (unsigned long)ss->contents.data;
2652 bfd_vma size = strlen(str) + 1;
2653 while ((start + size) % (1 << ss->alignment) != 0 &&
2654 start + size < ss->contents.size) {
2655 if (str[size] != '\0')
2656 DIE;
2657 size++;
2659 new_span(ss, start, size);
2660 str += size;
2664 static int compare_ulongs(const void *va, const void *vb)
2666 const unsigned long *a = va, *b = vb;
2667 return *a - *b;
2670 static void initialize_table_spans(struct superbfd *sbfd,
2671 struct table_section *s)
2673 asection *isection = bfd_get_section_by_name(sbfd->abfd, s->sect);
2674 if (isection == NULL)
2675 return;
2676 asection *other_sect = NULL;
2677 if (s->other_sect != NULL)
2678 other_sect = bfd_get_section_by_name(sbfd->abfd, s->other_sect);
2680 struct supersect *ss = fetch_supersect(sbfd, isection);
2681 if (ss->alignment < ffs(s->entry_align) - 1)
2682 ss->alignment = ffs(s->entry_align) - 1;
2684 struct supersect *other_ss = NULL;
2685 if (other_sect != NULL)
2686 other_ss = fetch_supersect(sbfd, other_sect);
2688 struct ulong_vec offsets;
2689 vec_init(&offsets);
2691 void *entry;
2692 for (entry = ss->contents.data;
2693 entry < ss->contents.data + ss->contents.size;
2694 entry += s->entry_size) {
2695 new_span(ss, addr_offset(ss, entry), s->entry_size);
2697 if (other_sect != NULL) {
2698 asymbol *sym;
2699 bfd_vma offset = read_reloc(ss, entry + s->other_offset,
2700 sizeof(void *), &sym);
2701 if (sym->section == other_sect) {
2702 assert(offset >= 0 &&
2703 offset < other_ss->contents.size);
2704 *vec_grow(&offsets, 1) = offset;
2709 if (other_sect == NULL)
2710 return;
2712 qsort(offsets.data, offsets.size, sizeof(*offsets.data),
2713 compare_ulongs);
2714 *vec_grow(&offsets, 1) = other_ss->contents.size;
2716 unsigned long *off;
2717 for (off = offsets.data; off < offsets.data + offsets.size - 1; off++) {
2718 if (*off != *(off + 1))
2719 new_span(other_ss, *off, *(off + 1) - *off);
2723 static void initialize_table_section_spans(struct superbfd *sbfd)
2725 struct supersect *tables_ss =
2726 fetch_supersect(offsets_sbfd,
2727 bfd_get_section_by_name(offsets_sbfd->abfd,
2728 ".ksplice_table_sections"));
2729 const struct table_section *ts;
2730 struct table_section s;
2731 for (ts = tables_ss->contents.data;
2732 (void *)ts < tables_ss->contents.data + tables_ss->contents.size;
2733 ts++) {
2734 s = *ts;
2735 s.sect = read_string(tables_ss, &ts->sect);
2736 s.other_sect = read_string(tables_ss, &ts->other_sect);
2737 initialize_table_spans(sbfd, &s);
2741 static void initialize_spans(struct superbfd *sbfd)
2743 if (mode("keep"))
2744 initialize_table_section_spans(sbfd);
2746 asection *sect;
2747 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2748 if (is_table_section(sect->name, true) && mode("keep"))
2749 continue;
2751 struct supersect *ss = fetch_supersect(sbfd, sect);
2752 if (ss->type == SS_TYPE_STRING)
2753 initialize_string_spans(ss);
2754 else if (!mode("keep") || ss->type != SS_TYPE_EXPORT)
2755 new_span(ss, 0, ss->contents.size);
2759 struct span *reloc_target_span(struct supersect *ss, arelent *reloc)
2761 asymbol *sym_ptr = *reloc->sym_ptr_ptr;
2762 if (bfd_is_const_section(sym_ptr->section))
2763 return NULL;
2765 bfd_vma addend = get_reloc_offset(ss, reloc, true) + sym_ptr->value;
2766 struct supersect *sym_ss =
2767 fetch_supersect(ss->parent, sym_ptr->section);
2768 struct span *span, *target_span = sym_ss->spans.data;
2769 for (span = sym_ss->spans.data;
2770 span < sym_ss->spans.data + sym_ss->spans.size; span++) {
2771 if (addend >= span->start && addend < span->start + span->size)
2772 target_span = span;
2774 return target_span;
2777 struct span *find_span(struct supersect *ss, bfd_size_type address)
2779 struct span *span;
2780 for (span = ss->spans.data; span < ss->spans.data + ss->spans.size;
2781 span++) {
2782 if (address >= span->start &&
2783 address < span->start + span->size)
2784 return span;
2786 /* Deal with empty BSS sections */
2787 if (ss->contents.size == 0 && ss->spans.size > 0)
2788 return ss->spans.data;
2789 return NULL;
2792 void compute_span_shifts(struct superbfd *sbfd)
2794 asection *sect;
2795 struct span *span;
2796 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2797 struct supersect *ss = fetch_supersect(sbfd, sect);
2798 if (!ss->keep)
2799 continue;
2800 bfd_size_type offset = 0;
2801 for (span = ss->spans.data;
2802 span < ss->spans.data + ss->spans.size; span++) {
2803 if (!span->keep)
2804 continue;
2805 span->shift = offset - span->start;
2806 offset += span->size;
2811 void remove_unkept_spans(struct superbfd *sbfd)
2813 asection *sect;
2814 struct span *span;
2815 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2816 struct supersect *ss = fetch_supersect(sbfd, sect);
2817 delete_obsolete_relocs(ss);
2818 struct arelentp_vec orig_relocs;
2819 vec_move(&orig_relocs, &ss->relocs);
2820 arelent **relocp, *reloc;
2821 for (relocp = orig_relocs.data;
2822 relocp < orig_relocs.data + orig_relocs.size; relocp++) {
2823 reloc = *relocp;
2824 asymbol *sym = *reloc->sym_ptr_ptr;
2825 span = reloc_target_span(ss, reloc);
2826 if ((span != NULL && span->keep && span->shift == 0) ||
2827 bfd_is_const_section(sym->section)) {
2828 *vec_grow(&ss->relocs, 1) = reloc;
2829 continue;
2831 struct supersect *sym_ss =
2832 fetch_supersect(sbfd, sym->section);
2833 if (span != NULL && (sym->flags & BSF_SECTION_SYM) == 0
2834 && find_span(sym_ss, sym->value) != span) {
2835 err(sbfd, "Spans for symbol %s and relocation "
2836 "target do not match in sect %s\n",
2837 sym->name, sym_ss->name);
2838 DIE;
2840 if (span != NULL && span->keep) {
2841 arelent *new_reloc = malloc(sizeof(*new_reloc));
2842 *new_reloc = *reloc;
2843 new_reloc->addend =
2844 get_reloc_offset(ss, reloc, false);
2845 new_reloc->addend += span->shift;
2846 *vec_grow(&ss->new_relocs, 1) = new_reloc;
2851 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2852 struct supersect *ss = fetch_supersect(sbfd, sect), orig_ss;
2853 if (!ss->keep)
2854 continue;
2855 supersect_move(&orig_ss, ss);
2856 vec_init(&ss->spans);
2857 for (span = orig_ss.spans.data;
2858 span < orig_ss.spans.data + orig_ss.spans.size; span++) {
2859 if (!span->keep)
2860 continue;
2861 struct span *new_span = vec_grow(&ss->spans, 1);
2862 *new_span = *span;
2863 new_span->start = span->start + span->shift;
2864 new_span->shift = 0;
2865 sect_copy(ss, sect_do_grow(ss, 1, span->size, 1),
2866 &orig_ss, orig_ss.contents.data + span->start,
2867 span->size);
2872 static void init_objmanip_superbfd(struct superbfd *sbfd)
2874 init_label_map(sbfd);
2875 initialize_supersect_types(sbfd);
2876 initialize_spans(sbfd);
2879 void mangle_section_name(struct superbfd *sbfd, const char *name)
2881 asection *sect = bfd_get_section_by_name(sbfd->abfd, name);
2882 if (sect == NULL)
2883 return;
2884 struct supersect *ss = fetch_supersect(sbfd, sect);
2885 char *buf;
2886 assert(asprintf(&buf, ".ksplice_pre.%s", ss->name) >= 0);
2887 ss->name = buf;