Replace __DATE__ and __TIME__ in the final code with the right date.
[ksplice.git] / objmanip.c
blob332c50f29cdd465531664c1cc948fb5179542c61
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 static void write_table_relocs(struct superbfd *sbfd, const char *sectname,
146 enum ksplice_reloc_howto_type type);
147 static void write_ksplice_table_reloc(struct supersect *ss,
148 unsigned long address,
149 const char *label,
150 enum ksplice_reloc_howto_type type);
151 static void write_ksplice_ignore_reloc(struct supersect *ss,
152 unsigned long address,
153 bfd_size_type size);
154 void load_ksplice_symbol_offsets(struct superbfd *sbfd);
155 void blot_section(struct supersect *ss, int offset, reloc_howto_type *howto);
156 static void write_ksplice_section(struct span *span);
157 void write_ksplice_patch(struct superbfd *sbfd, struct span *span);
158 void write_ksplice_deleted_patch(struct superbfd *sbfd, const char *name,
159 const char *label, const char *sectname);
160 asymbol **make_undefined_symbolp(struct superbfd *sbfd, const char *name);
161 void filter_table_sections(struct superbfd *isbfd);
162 void filter_table_section(struct superbfd *sbfd, const struct table_section *s);
163 void keep_referenced_sections(struct superbfd *sbfd);
164 bfd_boolean copy_object(bfd *ibfd, bfd *obfd);
165 void setup_section(bfd *ibfd, asection *isection, void *obfdarg);
166 static void setup_new_section(bfd *obfd, struct supersect *ss);
167 static void write_section(bfd *obfd, asection *osection, void *arg);
168 static void delete_obsolete_relocs(struct supersect *ss);
169 void mark_symbols_used_in_relocations(bfd *abfd, asection *isection,
170 void *ignored);
171 static void ss_mark_symbols_used_in_relocations(struct supersect *ss);
172 void filter_symbols(bfd *ibfd, bfd *obfd, struct asymbolp_vec *osyms,
173 struct asymbolp_vec *isyms);
174 static bool deleted_table_section_symbol(bfd *abfd, asymbol *sym);
175 void read_str_set(struct str_vec *strs);
176 bool str_in_set(const char *str, const struct str_vec *strs);
177 struct supersect *__attribute((format(printf, 2, 3)))
178 make_section(struct superbfd *sbfd, const char *fmt, ...);
179 void __attribute__((format(printf, 3, 4)))
180 write_string(struct supersect *ss, const char **addr, const char *fmt, ...);
181 void rm_some_exports(struct superbfd *isbfd, const struct export_desc *ed);
182 void write_ksplice_export(struct superbfd *sbfd, const char *symname,
183 const char *export_type, bool del);
184 void write_reloc(struct supersect *ss, const void *addr, asymbol **symp,
185 bfd_vma offset);
186 arelent *create_reloc(struct supersect *ss, const void *addr, asymbol **symp,
187 bfd_vma offset);
188 static void foreach_symbol_pair(struct superbfd *oldsbfd, struct superbfd *newsbfd,
189 void (*fn)(struct span *old_span,
190 asymbol *oldsym,
191 struct span *new_span,
192 asymbol *newsym));
193 static void check_global_symbols(struct span *old_span, asymbol *oldsym,
194 struct span *new_span, asymbol *newsym);
195 static void match_global_symbols(struct span *old_span, asymbol *oldsym,
196 struct span *new_span, asymbol *newsym);
197 static void match_symbol_spans(struct span *old_span, asymbol *oldsym,
198 struct span *new_span, asymbol *newsym);
200 static void foreach_span_pair(struct superbfd *oldsbfd,
201 struct superbfd *newsbfd,
202 void (*fn)(struct span *old_span,
203 struct span *new_span));
204 static void match_spans_by_label(struct span *old_span, struct span *new_span);
205 static void match_string_spans(struct span *old_span, struct span *new_span);
206 static void mark_new_spans(struct superbfd *sbfd);
207 static void handle_deleted_spans(struct superbfd *oldsbfd,
208 struct superbfd *newsbfd);
209 static void compare_matched_spans(struct superbfd *newsbfd);
210 static void compare_spans(struct span *old_span, struct span *new_span);
211 static void update_nonzero_offsets(struct superbfd *sbfd);
212 static void handle_nonzero_offset_relocs(struct supersect *ss);
213 static void keep_span(struct span *span);
215 static void init_objmanip_superbfd(struct superbfd *sbfd);
216 static const char *label_lookup(struct superbfd *sbfd, asymbol *sym);
217 static void label_map_set(struct superbfd *sbfd, const char *oldlabel,
218 const char *label);
219 static void print_label_changes(struct superbfd *sbfd);
220 static void init_label_map(struct superbfd *sbfd);
221 static asymbol **symbolp_scan(struct supersect *ss, bfd_vma value);
222 static void init_csyms(struct superbfd *sbfd);
223 static void init_callers(struct superbfd *sbfd);
224 static asymbol *canonical_symbol(struct superbfd *sbfd, asymbol *sym);
225 static asymbol **canonical_symbolp(struct superbfd *sbfd, asymbol *sym);
226 static char *static_local_symbol(struct superbfd *sbfd, asymbol *sym);
227 static char *symbol_label(struct superbfd *sbfd, asymbol *sym);
229 int verbose = 0;
230 #define debug_(sbfd, level, fmt, ...) \
231 do { \
232 if (verbose >= (level)) \
233 printf("%s: " fmt, (sbfd)->abfd->filename, \
234 ## __VA_ARGS__); \
235 } while (0)
236 #define debug0(sbfd, fmt, ...) debug_(sbfd, 0, fmt, ## __VA_ARGS__)
237 #define debug1(sbfd, fmt, ...) debug_(sbfd, 1, fmt, ## __VA_ARGS__)
238 #define err(sbfd, fmt, ...) \
239 do { \
240 fprintf(stderr, "%s: " fmt, (sbfd)->abfd->filename, \
241 ## __VA_ARGS__); \
242 } while (0)
244 struct str_vec delsects, rmsyms;
245 struct export_desc_vec exports;
246 bool changed;
248 struct ksplice_config *config;
250 const char *modestr, *kid, *finalize_target = NULL;
251 bool write_output = true;
253 struct superbfd *offsets_sbfd = NULL;
255 #define mode(str) starts_with(modestr, str)
257 DECLARE_VEC_TYPE(unsigned long, addr_vec);
258 DEFINE_HASH_TYPE(struct addr_vec, addr_vec_hash,
259 addr_vec_hash_init, addr_vec_hash_free, addr_vec_hash_lookup,
260 vec_init);
261 struct addr_vec_hash system_map;
263 struct bool_hash system_map_written;
264 struct ulong_hash ksplice_symbol_offset;
265 struct ulong_hash ksplice_howto_offset;
266 struct ulong_hash ksplice_string_offset;
268 void load_system_map()
270 const char *config_dir = getenv("KSPLICE_CONFIG_DIR");
271 assert(config_dir);
272 char *file;
273 assert(asprintf(&file, "%s/System.map", config_dir) >= 0);
274 FILE *fp = fopen(file, "r");
275 assert(fp);
276 addr_vec_hash_init(&system_map);
277 unsigned long addr;
278 char type;
279 char *sym;
280 while (fscanf(fp, "%lx %c %as\n", &addr, &type, &sym) == 3)
281 *vec_grow(addr_vec_hash_lookup(&system_map, sym, TRUE),
282 1) = addr;
283 fclose(fp);
286 void load_ksplice_symbol_offsets(struct superbfd *sbfd)
288 asection *sect = bfd_get_section_by_name(sbfd->abfd,
289 ".ksplice_symbols");
290 if (sect == NULL)
291 return;
292 struct supersect *ss = fetch_supersect(sbfd, sect);
294 struct ksplice_symbol *ksym;
295 for (ksym = ss->contents.data;
296 (void *)ksym < ss->contents.data + ss->contents.size; ksym++) {
297 const char *label = read_string(ss, &ksym->label);
298 unsigned long *ksymbol_offp =
299 ulong_hash_lookup(&ksplice_symbol_offset, label, TRUE);
300 *ksymbol_offp = addr_offset(ss, ksym);
304 void load_offsets()
306 char *kmodsrc = getenv("KSPLICE_KMODSRC"), *offsets_file;
307 assert(kmodsrc != NULL);
308 assert(asprintf(&offsets_file, "%s/offsets.o", kmodsrc) >= 0);
309 bfd *offsets_bfd = bfd_openr(offsets_file, NULL);
310 assert(offsets_bfd != NULL);
311 char **matching;
312 assert(bfd_check_format_matches(offsets_bfd, bfd_object, &matching));
313 offsets_sbfd = fetch_superbfd(offsets_bfd);
315 asection *config_sect = bfd_get_section_by_name(offsets_sbfd->abfd,
316 ".ksplice_config");
317 struct supersect *config_ss =
318 fetch_supersect(offsets_sbfd, config_sect);
320 config = config_ss->contents.data;
323 bool matchable_data_section(struct supersect *ss)
325 if (ss->type == SS_TYPE_STRING)
326 return true;
327 if (ss->type == SS_TYPE_RODATA)
328 return true;
329 if (ss->type == SS_TYPE_DATA && ss->relocs.size != 0)
330 return true;
331 return false;
334 bool unchangeable_section(struct supersect *ss)
336 if (ss->type == SS_TYPE_DATA)
337 return true;
338 if (ss->type == SS_TYPE_IGNORED && !starts_with(ss->name, ".debug") &&
339 strcmp(ss->name, "__ksymtab_strings") != 0)
340 return true;
341 return false;
344 int main(int argc, char *argv[])
346 if (getenv("KSPLICE_VERBOSE") != NULL)
347 verbose = atoi(getenv("KSPLICE_VERBOSE"));
349 bfd_init();
350 bfd *ibfd = bfd_openr(argv[1], NULL);
351 assert(ibfd);
353 char **matching;
354 assert(bfd_check_format_matches(ibfd, bfd_object, &matching));
356 const char *output_target = bfd_get_target(ibfd);
358 load_system_map();
359 load_offsets();
361 bool_hash_init(&system_map_written);
362 ulong_hash_init(&ksplice_symbol_offset);
363 ulong_hash_init(&ksplice_howto_offset);
364 ulong_hash_init(&ksplice_string_offset);
366 struct superbfd *isbfd = fetch_superbfd(ibfd);
368 modestr = argv[3];
369 if (mode("finalize"))
370 finalize_target = argv[4];
371 init_objmanip_superbfd(isbfd);
372 if (mode("keep-primary")) {
373 kid = argv[5];
374 do_keep_primary(isbfd, argv[4]);
375 } else if (mode("keep-helper")) {
376 do_keep_helper(isbfd);
377 } else if (mode("finalize")) {
378 do_finalize(isbfd);
379 } else if (mode("rmsyms")) {
380 do_rmsyms(isbfd);
383 if (write_output) {
384 bfd *obfd = bfd_openw(argv[2], output_target);
385 assert(obfd);
386 copy_object(ibfd, obfd);
387 assert(bfd_close(obfd));
390 if (offsets_sbfd != NULL)
391 assert(bfd_close(offsets_sbfd->abfd));
392 assert(bfd_close(ibfd));
393 return EXIT_SUCCESS;
396 void do_keep_primary(struct superbfd *isbfd, const char *pre)
398 struct bfd *prebfd = bfd_openr(pre, NULL);
399 assert(prebfd != NULL);
400 char **matching;
401 assert(bfd_check_format_matches(prebfd, bfd_object, &matching));
403 struct superbfd *presbfd = fetch_superbfd(prebfd);
404 init_objmanip_superbfd(presbfd);
406 foreach_symbol_pair(presbfd, isbfd, match_global_symbols);
407 debug1(isbfd, "Matched global\n");
408 foreach_span_pair(presbfd, isbfd, match_string_spans);
409 debug1(isbfd, "Matched string spans\n");
410 foreach_symbol_pair(presbfd, isbfd, match_symbol_spans);
411 debug1(isbfd, "Matched by name\n");
412 foreach_span_pair(presbfd, isbfd, match_spans_by_label);
413 debug1(isbfd, "Matched by label\n");
415 do {
416 changed = false;
417 compare_matched_spans(isbfd);
418 update_nonzero_offsets(isbfd);
419 mark_new_spans(isbfd);
420 } while (changed);
421 vec_init(&delsects);
423 foreach_symbol_pair(presbfd, isbfd, check_global_symbols);
425 handle_deleted_spans(presbfd, isbfd);
426 handle_section_symbol_renames(presbfd, isbfd);
428 vec_init(&exports);
429 compare_exported_symbols(presbfd, isbfd, false);
430 compare_exported_symbols(isbfd, presbfd, true);
432 assert(bfd_close(prebfd));
434 asection *sect;
435 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
436 struct supersect *ss = fetch_supersect(isbfd, sect);
437 ss->keep = false;
438 struct span *span;
439 for (span = ss->spans.data;
440 span < ss->spans.data + ss->spans.size; span++) {
441 if (span->new || span->patch)
442 keep_span(span);
443 else
444 span->keep = false;
448 print_label_changes(isbfd);
450 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
451 struct supersect *ss = fetch_supersect(isbfd, sect);
452 struct span *span;
453 for (span = ss->spans.data;
454 span < ss->spans.data + ss->spans.size; span++) {
455 if (span->patch)
456 debug0(isbfd, "Patching span %s\n",
457 span->label);
461 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
462 struct supersect *ss = fetch_supersect(isbfd, sect);
463 struct span *span;
464 for (span = ss->spans.data;
465 span < ss->spans.data + ss->spans.size; span++) {
466 if (span->new)
467 debug0(isbfd, "New span %s\n", span->label);
471 const char **sectname;
472 for (sectname = delsects.data;
473 sectname < delsects.data + delsects.size; sectname++)
474 debug0(isbfd, "Deleted section: %s\n", *sectname);
476 const struct export_desc *ed;
477 for (ed = exports.data; ed < exports.data + exports.size; ed++) {
478 const char **symname;
479 for (symname = ed->names.data;
480 symname < ed->names.data + ed->names.size; symname++)
481 debug0(isbfd, "Export %s (%s): %s\n",
482 ed->deletion ? "deletion" : "addition",
483 ed->export_type, *symname);
486 filter_table_sections(isbfd);
487 write_output = false;
488 for (ed = exports.data; ed < exports.data + exports.size; ed++) {
489 const char **symname;
490 for (symname = ed->names.data;
491 symname < ed->names.data + ed->names.size; symname++)
492 write_ksplice_export(isbfd, *symname,
493 ed->export_type, ed->deletion);
494 if (ed->deletion)
495 write_output = true;
496 else
497 rm_some_exports(isbfd, ed);
500 compute_span_shifts(isbfd);
502 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
503 struct supersect *ss = fetch_supersect(isbfd, sect);
504 struct span *span;
505 for (span = ss->spans.data;
506 span < ss->spans.data + ss->spans.size; span++) {
507 if (span->keep)
508 write_output = true;
509 if (span->patch || span->new)
510 write_ksplice_section(span);
511 if (span->patch)
512 write_ksplice_patch(isbfd, span);
516 rm_relocs(isbfd);
517 remove_unkept_spans(isbfd);
520 void do_keep_helper(struct superbfd *isbfd)
522 asection *sect;
523 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
524 struct supersect *ss = fetch_supersect(isbfd, sect);
525 ss->keep = false;
526 struct span *span;
527 for (span = ss->spans.data;
528 span < ss->spans.data + ss->spans.size; span++) {
529 if (ss->type == SS_TYPE_TEXT &&
530 !starts_with(ss->name, ".fixup"))
531 keep_span(span);
532 else
533 span->keep = false;
537 asymbol **symp;
538 for (symp = isbfd->syms.data;
539 symp < isbfd->syms.data + isbfd->syms.size; symp++) {
540 asymbol *sym = *symp;
541 if (!bfd_is_const_section(sym->section) &&
542 (sym->flags & BSF_GLOBAL) != 0) {
543 struct supersect *sym_ss =
544 fetch_supersect(isbfd, sym->section);
545 struct span *span = find_span(sym_ss, sym->value);
546 if (sym_ss->type != SS_TYPE_IGNORED)
547 keep_span(span);
551 do {
552 changed = false;
553 keep_referenced_sections(isbfd);
554 } while (changed);
556 filter_table_sections(isbfd);
557 compute_span_shifts(isbfd);
559 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
560 struct supersect *ss = fetch_supersect(isbfd, sect);
561 asymbol *sym = canonical_symbol(isbfd, sect->symbol);
562 if (sym == NULL)
563 continue;
564 if ((sym->flags & BSF_WEAK) != 0)
565 continue;
566 if (bfd_get_section_size(sect) == 0)
567 continue;
568 if (!ss->keep)
569 continue;
570 if (ss->type != SS_TYPE_TEXT && !matchable_data_section(ss))
571 continue;
573 struct span *span;
574 for (span = ss->spans.data;
575 span < ss->spans.data + ss->spans.size; span++) {
576 if (span->keep)
577 write_ksplice_section(span);
581 write_table_relocs(isbfd, "__bug_table", KSPLICE_HOWTO_BUG);
582 write_table_relocs(isbfd, "__ex_table", KSPLICE_HOWTO_EXTABLE);
583 rm_relocs(isbfd);
584 remove_unkept_spans(isbfd);
586 mangle_section_name(isbfd, "__markers");
587 mangle_section_name(isbfd, "__ex_table");
590 void do_finalize(struct superbfd *isbfd)
592 load_ksplice_symbol_offsets(isbfd);
593 asection *sect;
594 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
595 struct supersect *ss = fetch_supersect(isbfd, sect);
596 if (ss->type == SS_TYPE_EXIT) {
597 struct span *span;
598 for (span = ss->spans.data;
599 span < ss->spans.data + ss->spans.size; span++)
600 span->keep = false;
601 ss->keep = false;
604 write_date_relocs(isbfd, "<{DATE...}>", KSPLICE_HOWTO_DATE);
605 write_date_relocs(isbfd, "<{TIME}>", KSPLICE_HOWTO_TIME);
606 rm_relocs(isbfd);
609 void do_rmsyms(struct superbfd *isbfd)
611 read_str_set(&rmsyms);
612 rm_relocs(isbfd);
615 struct export_vec *get_export_syms(struct superbfd *sbfd)
617 asection *sect;
618 struct export_vec *exports;
619 exports = malloc(sizeof(*exports));
620 assert(exports != NULL);
621 vec_init(exports);
623 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
624 if (!starts_with(sect->name, "__ksymtab") ||
625 ends_with(sect->name, "_strings"))
626 continue;
627 struct supersect *ss = fetch_supersect(sbfd, sect);
628 struct kernel_symbol *sym;
629 assert(ss->contents.size * 2 == ss->relocs.size *
630 sizeof(struct kernel_symbol));
631 for (sym = ss->contents.data;
632 (void *)sym < ss->contents.data + ss->contents.size;
633 sym++) {
634 struct export *exp = vec_grow(exports, 1);
635 exp->name =
636 read_string(ss, (const char *const *)&sym->name);
637 exp->ss = ss;
640 return exports;
643 struct export_desc *new_export_desc(struct supersect *ss, bool deletion)
645 struct export_desc *ed = vec_grow(&exports, 1);
646 ed->deletion = deletion;
647 vec_init(&ed->names);
648 ed->export_type = strdup(ss->name) + strlen("__ksymtab");
649 ed->sym_ss = ss;
650 char *crc_sect_name;
651 assert(asprintf(&crc_sect_name, "__kcrctab%s", ed->export_type) >= 0);
652 asection *crc_sect =
653 bfd_get_section_by_name(ss->parent->abfd, crc_sect_name);
654 if (crc_sect == NULL)
655 ed->crc_ss = NULL;
656 else
657 ed->crc_ss = fetch_supersect(ss->parent, crc_sect);
658 return ed;
661 void compare_exported_symbols(struct superbfd *oldsbfd,
662 struct superbfd *newsbfd, bool deletion)
664 struct export_vec *new_exports, *old_exports;
665 new_exports = get_export_syms(newsbfd);
666 if (new_exports == NULL)
667 return;
668 old_exports = get_export_syms(oldsbfd);
669 struct export *old, *new;
670 struct supersect *last_ss = NULL;
671 struct export_desc *ed = NULL;
672 for (new = new_exports->data; new < new_exports->data +
673 new_exports->size; new++) {
674 bool found = false;
675 if (old_exports != NULL) {
676 for (old = old_exports->data; old < old_exports->data +
677 old_exports->size; old++) {
678 if (strcmp(new->name, old->name) == 0 &&
679 strcmp(new->ss->name, old->ss->name) == 0) {
680 found = true;
681 break;
685 if (!found) {
686 if (last_ss != new->ss) {
687 last_ss = new->ss;
688 ed = new_export_desc(new->ss, deletion);
690 *vec_grow(&ed->names, 1) = new->name;
695 void match_spans(struct span *old_span, struct span *new_span)
697 struct superbfd *sbfd = new_span->ss->parent;
698 if (old_span->match == new_span && new_span->match == old_span)
699 return;
700 if (old_span->match != NULL) {
701 err(sbfd, "Matching conflict: old %s: %s != %s\n",
702 old_span->label, old_span->match->label, new_span->label);
703 DIE;
705 if (new_span->match != NULL) {
706 err(sbfd, "Matching conflict: new %s: %s != %s\n",
707 new_span->label, new_span->match->label, old_span->label);
708 DIE;
710 old_span->match = new_span;
711 new_span->match = old_span;
712 debug1(sbfd, "Matched old %s to new %s\n", old_span->label,
713 new_span->label);
716 static void match_global_symbols(struct span *old_span, asymbol *oldsym,
717 struct span *new_span, asymbol *newsym)
719 if ((oldsym->flags & BSF_GLOBAL) == 0 ||
720 (newsym->flags & BSF_GLOBAL) == 0)
721 return;
722 match_spans(old_span, new_span);
725 static void check_global_symbols(struct span *old_span, asymbol *oldsym,
726 struct span *new_span, asymbol *newsym)
728 if ((oldsym->flags & BSF_GLOBAL) == 0 ||
729 (newsym->flags & BSF_GLOBAL) == 0)
730 return;
731 if (old_span->ss->type == SS_TYPE_IGNORED)
732 return;
733 if (old_span->match != new_span || new_span->match != old_span) {
734 err(new_span->ss->parent, "Global symbol span mismatch: %s "
735 "%s/%s\n", oldsym->name, old_span->ss->name,
736 new_span->ss->name);
737 DIE;
741 static void foreach_symbol_pair(struct superbfd *oldsbfd, struct superbfd *newsbfd,
742 void (*fn)(struct span *old_span,
743 asymbol *oldsym,
744 struct span *new_span,
745 asymbol *newsym))
747 asymbol **oldsymp, **newsymp;
748 for (oldsymp = oldsbfd->syms.data;
749 oldsymp < oldsbfd->syms.data + oldsbfd->syms.size; oldsymp++) {
750 asymbol *oldsym = *oldsymp;
751 if (bfd_is_const_section(oldsym->section))
752 continue;
753 for (newsymp = newsbfd->syms.data;
754 newsymp < newsbfd->syms.data + newsbfd->syms.size;
755 newsymp++) {
756 asymbol *newsym = *newsymp;
757 if (bfd_is_const_section(newsym->section))
758 continue;
759 if (strcmp(oldsym->name, newsym->name) != 0)
760 continue;
762 struct supersect *old_ss =
763 fetch_supersect(oldsbfd, oldsym->section);
764 struct supersect *new_ss =
765 fetch_supersect(newsbfd, newsym->section);
766 if (old_ss->type != new_ss->type ||
767 old_ss->type == SS_TYPE_SPECIAL ||
768 old_ss->type == SS_TYPE_EXPORT)
769 continue;
771 struct span *old_span =
772 find_span(old_ss, oldsym->value);
773 struct span *new_span =
774 find_span(new_ss, newsym->value);
775 if (old_span == NULL) {
776 err(oldsbfd, "Could not find span for %s\n",
777 oldsym->name);
778 DIE;
780 if (new_span == NULL) {
781 err(newsbfd, "Could not find span for %s\n",
782 newsym->name);
783 DIE;
785 fn(old_span, oldsym, new_span, newsym);
790 static void match_symbol_spans(struct span *old_span, asymbol *oldsym,
791 struct span *new_span, asymbol *newsym)
793 if ((oldsym->flags & BSF_DEBUGGING) != 0 ||
794 (newsym->flags & BSF_DEBUGGING) != 0)
795 return;
796 if (old_span->ss->type == SS_TYPE_SPECIAL ||
797 old_span->ss->type == SS_TYPE_EXPORT)
798 return;
799 if (static_local_symbol(old_span->ss->parent, oldsym) ||
800 static_local_symbol(new_span->ss->parent, newsym))
801 return;
802 if (old_span->match == NULL && new_span->match == NULL)
803 match_spans(old_span, new_span);
806 static void match_spans_by_label(struct span *old_span, struct span *new_span)
808 if (old_span->ss->type == SS_TYPE_STRING)
809 return;
810 if (strcmp(old_span->label, new_span->label) == 0)
811 match_spans(old_span, new_span);
814 static void match_string_spans(struct span *old_span, struct span *new_span)
816 if (old_span->ss->type != SS_TYPE_STRING ||
817 strcmp(old_span->ss->name, new_span->ss->name) != 0)
818 return;
819 if (strcmp((char *)old_span->ss->contents.data + old_span->start,
820 (char *)new_span->ss->contents.data + new_span->start) == 0)
821 match_spans(old_span, new_span);
824 static void foreach_span_pair(struct superbfd *oldsbfd,
825 struct superbfd *newsbfd,
826 void (*fn)(struct span *old_span,
827 struct span *new_span))
829 asection *oldsect, *newsect;
830 struct supersect *oldss, *newss;
831 struct span *old_span, *new_span;
832 for (newsect = newsbfd->abfd->sections; newsect != NULL;
833 newsect = newsect->next) {
834 newss = fetch_supersect(newsbfd, newsect);
835 if (newss->type == SS_TYPE_SPECIAL ||
836 newss->type == SS_TYPE_EXPORT)
837 continue;
838 for (oldsect = oldsbfd->abfd->sections; oldsect != NULL;
839 oldsect = oldsect->next) {
840 oldss = fetch_supersect(oldsbfd, oldsect);
841 if (oldss->type != newss->type)
842 continue;
843 for (new_span = newss->spans.data;
844 new_span < newss->spans.data + newss->spans.size;
845 new_span++) {
846 for (old_span = oldss->spans.data;
847 old_span < oldss->spans.data +
848 oldss->spans.size; old_span++)
849 fn(old_span, new_span);
855 static void mark_new_spans(struct superbfd *sbfd)
857 asection *sect;
858 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
859 struct supersect *ss = fetch_supersect(sbfd, sect);
860 if (ss->type == SS_TYPE_SPECIAL || ss->type == SS_TYPE_EXPORT ||
861 ss->type == SS_TYPE_IGNORED)
862 continue;
863 struct span *span;
864 for (span = ss->spans.data;
865 span < ss->spans.data + ss->spans.size; span++) {
866 if (span->match == NULL)
867 span->new = true;
872 static void handle_deleted_spans(struct superbfd *oldsbfd,
873 struct superbfd *newsbfd)
875 asection *sect;
876 for (sect = oldsbfd->abfd->sections; sect != NULL; sect = sect->next) {
877 struct supersect *ss = fetch_supersect(oldsbfd, sect);
878 if (ss->type != SS_TYPE_TEXT)
879 continue;
880 struct span *span;
881 for (span = ss->spans.data;
882 span < ss->spans.data + ss->spans.size; span++) {
883 if (span->match != NULL)
884 continue;
885 *vec_grow(&delsects, 1) = span->label;
886 if (span->symbol == NULL)
887 DIE;
888 write_ksplice_deleted_patch(newsbfd, span->symbol->name,
889 span->label,
890 span->ss->name);
895 static void handle_nonzero_offset_relocs(struct supersect *ss)
897 struct span *address_span, *target_span;
898 arelent **relocp;
899 for (relocp = ss->relocs.data;
900 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
901 arelent *reloc = *relocp;
902 address_span = find_span(ss, reloc->address);
903 if (!address_span->new && !address_span->patch)
904 continue;
906 asymbol *sym = *reloc->sym_ptr_ptr;
907 if (bfd_is_const_section(sym->section))
908 continue;
909 bfd_vma offset = get_reloc_offset(ss, reloc, true);
910 target_span = reloc_target_span(ss, reloc);
911 if (sym->value + offset == target_span->start)
912 continue;
914 if (target_span->ss->type != SS_TYPE_TEXT)
915 continue;
916 if (target_span->patch)
917 continue;
919 target_span->patch = true;
920 changed = true;
921 debug1(ss->parent, "Changing %s because a relocation from sect "
922 "%s has a nonzero offset %lx+%lx into it\n",
923 target_span->label, ss->name, (unsigned long)sym->value,
924 (unsigned long)offset);
928 static void update_nonzero_offsets(struct superbfd *sbfd)
930 asection *sect;
931 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
932 struct supersect *ss = fetch_supersect(sbfd, sect);
933 if (ss->type == SS_TYPE_SPECIAL || ss->type == SS_TYPE_EXPORT ||
934 ss->type == SS_TYPE_IGNORED)
935 continue;
936 handle_nonzero_offset_relocs(ss);
940 static void compare_spans(struct span *old_span, struct span *new_span)
942 struct superbfd *newsbfd = new_span->ss->parent;
944 if (nonrelocs_equal(old_span, new_span) &&
945 all_relocs_equal(old_span, new_span))
946 return;
948 char *reason;
949 if (new_span->size != old_span->size)
950 reason = "differing sizes";
951 else if (!nonrelocs_equal(old_span, new_span))
952 reason = "differing contents";
953 else
954 reason = "differing relocations";
956 if (new_span->ss->type == SS_TYPE_TEXT) {
957 if (new_span->patch)
958 return;
959 new_span->patch = true;
960 debug1(newsbfd, "Changing %s due to %s\n", new_span->label,
961 reason);
962 } else {
963 debug1(newsbfd, "Unmatching %s and %s due to %s\n",
964 old_span->label, new_span->label, reason);
965 new_span->match = NULL;
966 old_span->match = NULL;
968 changed = true;
969 if (unchangeable_section(new_span->ss))
970 err(newsbfd, "warning: ignoring change to nonpatchable "
971 "section %s\n", new_span->ss->name);
974 static void compare_matched_spans(struct superbfd *newsbfd)
976 asection *sect;
977 for (sect = newsbfd->abfd->sections; sect != NULL; sect = sect->next) {
978 struct supersect *ss = fetch_supersect(newsbfd, sect);
979 struct span *span;
980 for (span = ss->spans.data;
981 span < ss->spans.data + ss->spans.size; span++) {
982 if (span->match == NULL)
983 continue;
984 compare_spans(span->match, span);
989 static void handle_section_symbol_renames(struct superbfd *oldsbfd,
990 struct superbfd *newsbfd)
992 asection *sect;
993 struct span *span;
994 for (sect = newsbfd->abfd->sections; sect != NULL; sect = sect->next) {
995 struct supersect *ss = fetch_supersect(newsbfd, sect);
996 for (span = ss->spans.data;
997 span < ss->spans.data + ss->spans.size; span++) {
998 if (span->match == NULL)
999 continue;
1000 if (strcmp(span->label, span->match->label) == 0)
1001 continue;
1002 if (strcmp(span->orig_label, span->label) != 0 &&
1003 strcmp(span->label, span->match->label) != 0)
1004 DIE;
1005 if (span->symbol != NULL)
1006 label_map_set(newsbfd, span->label,
1007 span->match->label);
1008 span->label = span->match->label;
1013 static bool part_of_reloc(struct supersect *ss, unsigned long addr)
1015 arelent **relocp;
1016 for (relocp = ss->relocs.data;
1017 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
1018 arelent *reloc = *relocp;
1019 if (addr >= reloc->address &&
1020 addr < reloc->address + reloc->howto->size)
1021 return true;
1023 return false;
1026 static bool nonrelocs_equal(struct span *old_span, struct span *new_span)
1028 int i;
1029 struct supersect *old_ss = old_span->ss, *new_ss = new_span->ss;
1030 if (old_span->size != new_span->size)
1031 return false;
1032 const unsigned char *old = old_ss->contents.data + old_span->start;
1033 const unsigned char *new = new_ss->contents.data + new_span->start;
1034 for (i = 0; i < old_span->size; i++) {
1035 if (old[i] != new[i] &&
1036 !(part_of_reloc(old_ss, i + old_span->start) &&
1037 part_of_reloc(new_ss, i + new_span->start)))
1038 return false;
1040 return true;
1043 bool relocs_equal(struct supersect *old_src_ss, struct supersect *new_src_ss,
1044 arelent *old_reloc, arelent *new_reloc)
1046 struct superbfd *oldsbfd = old_src_ss->parent;
1047 struct superbfd *newsbfd = new_src_ss->parent;
1048 struct span *old_addr_span = find_span(old_src_ss, old_reloc->address);
1049 struct span *new_addr_span = find_span(new_src_ss, new_reloc->address);
1051 if (old_reloc->address - old_addr_span->start !=
1052 new_reloc->address - new_addr_span->start) {
1053 debug1(newsbfd, "Section %s/%s has reloc address mismatch at "
1054 "%lx\n", old_src_ss->name, new_src_ss->name,
1055 (unsigned long)old_reloc->address);
1056 return false;
1059 if (old_reloc->howto != new_reloc->howto) {
1060 debug1(newsbfd, "Section %s/%s has howto type mismatch at "
1061 "%lx\n", old_src_ss->name, new_src_ss->name,
1062 (unsigned long)old_reloc->address);
1063 return false;
1066 if (non_dst_mask(old_src_ss, old_reloc) !=
1067 non_dst_mask(new_src_ss, new_reloc)) {
1068 debug1(newsbfd, "Section %s/%s has contents mismatch at %lx\n",
1069 old_src_ss->name, new_src_ss->name,
1070 (unsigned long)old_reloc->address);
1071 return false;
1074 asymbol *old_sym = *old_reloc->sym_ptr_ptr;
1075 asymbol *new_sym = *new_reloc->sym_ptr_ptr;
1076 asection *old_sect = old_sym->section;
1077 asection *new_sect = new_sym->section;
1079 bfd_vma old_offset = get_reloc_offset(old_src_ss, old_reloc, true);
1080 bfd_vma new_offset = get_reloc_offset(new_src_ss, new_reloc, true);
1082 if (bfd_is_und_section(old_sect) || bfd_is_und_section(new_sect)) {
1083 if (!bfd_is_und_section(new_sect) && old_offset != 0 &&
1084 fetch_supersect(newsbfd, new_sect)->type == SS_TYPE_TEXT)
1085 return false;
1087 if (!bfd_is_und_section(new_sect) && new_offset != 0 &&
1088 fetch_supersect(oldsbfd, old_sect)->type == SS_TYPE_TEXT)
1089 return false;
1091 return strcmp(old_sym->name, new_sym->name) == 0 &&
1092 old_offset == new_offset;
1095 if (bfd_is_const_section(old_sect) || bfd_is_const_section(new_sect))
1096 DIE;
1098 struct supersect *old_ss = fetch_supersect(oldsbfd, old_sect);
1099 struct supersect *new_ss = fetch_supersect(newsbfd, new_sect);
1100 struct span *old_span = reloc_target_span(old_src_ss, old_reloc);
1101 struct span *new_span = reloc_target_span(new_src_ss, new_reloc);
1103 if (old_span->match != new_span || new_span->match != old_span) {
1104 debug1(newsbfd, "Nonmatching relocs from %s to %s/%s\n",
1105 new_src_ss->name, old_span->label, new_span->label);
1106 return false;
1109 if (old_sym->value + old_offset - old_span->start !=
1110 new_sym->value + new_offset - new_span->start) {
1111 debug1(newsbfd, "Offsets to %s/%s differ between %s "
1112 "and %s: %lx+%lx/%lx+%lx\n", old_ss->name,
1113 new_ss->name, old_src_ss->name, new_src_ss->name,
1114 (unsigned long)old_sym->value, (unsigned long)old_offset,
1115 (unsigned long)new_sym->value,
1116 (unsigned long)new_offset);
1117 return false;
1120 if ((old_sym->value + old_offset - old_span->start != 0 ||
1121 new_sym->value + new_offset - new_span->start != 0) &&
1122 new_span->patch) {
1123 debug1(newsbfd, "Relocation from %s to nonzero offsets "
1124 "%lx+%lx/%lx+%lx in changed section %s\n",
1125 new_src_ss->name, (unsigned long)old_sym->value,
1126 (unsigned long)old_offset, (unsigned long)new_sym->value,
1127 (unsigned long)new_offset, new_sym->section->name);
1128 return false;
1130 return true;
1133 bool all_relocs_equal(struct span *old_span, struct span *new_span)
1135 struct supersect *old_ss = old_span->ss, *new_ss = new_span->ss;
1136 arelent **old_relocp, **new_relocp;
1138 for (old_relocp = old_ss->relocs.data;
1139 old_relocp < old_ss->relocs.data + old_ss->relocs.size;
1140 old_relocp++) {
1141 if (find_span(old_ss, (*old_relocp)->address) == old_span)
1142 break;
1145 for (new_relocp = new_ss->relocs.data;
1146 new_relocp < new_ss->relocs.data + new_ss->relocs.size;
1147 new_relocp++) {
1148 if (find_span(new_ss, (*new_relocp)->address) == new_span)
1149 break;
1152 for (; old_relocp < old_ss->relocs.data + old_ss->relocs.size &&
1153 find_span(old_ss, (*old_relocp)->address) == old_span &&
1154 new_relocp < new_ss->relocs.data + new_ss->relocs.size &&
1155 find_span(new_ss, (*new_relocp)->address) == new_span;
1156 old_relocp++, new_relocp++) {
1157 if (!relocs_equal(old_ss, new_ss, *old_relocp, *new_relocp))
1158 return false;
1161 if ((old_relocp < old_ss->relocs.data + old_ss->relocs.size &&
1162 find_span(old_ss, (*old_relocp)->address) == old_span) ||
1163 (new_relocp < new_ss->relocs.data + new_ss->relocs.size &&
1164 find_span(new_ss, (*new_relocp)->address) == new_span)) {
1165 debug1(new_ss->parent, "Different reloc count between %s and "
1166 "%s\n", old_span->label, new_span->label);
1167 return false;
1170 return true;
1173 bfd_vma non_dst_mask(struct supersect *ss, arelent *reloc)
1175 int bits = bfd_get_reloc_size(reloc->howto) * 8;
1176 void *address = ss->contents.data + reloc->address;
1177 bfd_vma x = bfd_get(bits, ss->parent->abfd, address);
1178 return x & ~reloc->howto->dst_mask;
1181 void rm_some_exports(struct superbfd *sbfd, const struct export_desc *ed)
1183 struct supersect *ss = ed->sym_ss;
1184 struct supersect *crc_ss = ed->crc_ss;
1185 if (crc_ss != NULL)
1186 assert(ss->contents.size * sizeof(unsigned long) ==
1187 crc_ss->contents.size * sizeof(struct kernel_symbol));
1189 struct kernel_symbol *ksym;
1190 unsigned long *crc = NULL;
1191 if (crc_ss != NULL)
1192 crc = crc_ss->contents.data;
1193 struct span *span, *crc_span;
1194 for (ksym = ss->contents.data;
1195 (void *)ksym < ss->contents.data + ss->contents.size;
1196 ksym++, crc++) {
1197 asymbol *sym;
1198 read_reloc(ss, &ksym->value, sizeof(ksym->value), &sym);
1199 span = new_span(ss, addr_offset(ss, ksym), sizeof(*ksym));
1200 if (str_in_set(sym->name, &ed->names))
1201 keep_span(span);
1203 if (crc_ss != NULL) {
1204 crc_span = new_span(crc_ss, addr_offset(crc_ss, crc),
1205 sizeof(*crc));
1206 if (span->keep)
1207 keep_span(crc_span);
1210 if (span->keep) {
1211 /* Replace name with a mangled name */
1212 write_string(ss, (const char **)&ksym->name,
1213 "DISABLED_%s_%s", sym->name, kid);
1218 void rm_relocs(struct superbfd *isbfd)
1220 asection *p;
1221 for (p = isbfd->abfd->sections; p != NULL; p = p->next) {
1222 struct supersect *ss = fetch_supersect(isbfd, p);
1223 bool remove_relocs = ss->keep;
1225 if (mode("keep") && ss->type == SS_TYPE_SPECIAL &&
1226 strcmp(ss->name, "__bug_table") != 0)
1227 remove_relocs = false;
1229 if (ss->type == SS_TYPE_KSPLICE)
1230 remove_relocs = false;
1231 if (mode("finalize") &&
1232 (starts_with(ss->name, ".ksplice_patches") ||
1233 starts_with(ss->name, ".ksplice_relocs")))
1234 remove_relocs = true;
1236 if (remove_relocs)
1237 rm_some_relocs(ss);
1241 void rm_some_relocs(struct supersect *ss)
1243 struct arelentp_vec orig_relocs;
1244 vec_move(&orig_relocs, &ss->relocs);
1246 arelent **relocp;
1247 for (relocp = orig_relocs.data;
1248 relocp < orig_relocs.data + orig_relocs.size; relocp++) {
1249 bool rm_reloc = false;
1250 asymbol *sym_ptr = *(*relocp)->sym_ptr_ptr;
1252 if (mode("rmsyms") && str_in_set(sym_ptr->name, &rmsyms) &&
1253 bfd_is_und_section(sym_ptr->section))
1254 rm_reloc = true;
1256 if (mode("keep"))
1257 rm_reloc = true;
1259 if (mode("keep-primary") &&
1260 (bfd_is_const_section(sym_ptr->section) ||
1261 reloc_target_span(ss, *relocp)->new))
1262 rm_reloc = false;
1264 if (mode("keep-primary")) {
1265 const struct table_section *ts =
1266 get_table_section(ss->name);
1267 if (ts != NULL && ts->has_addr &&
1268 ((*relocp)->address % ts->entry_size ==
1269 ts->addr_offset ||
1270 (*relocp)->address % ts->entry_size ==
1271 ts->other_offset))
1272 rm_reloc = false;
1275 if (mode("finalize") && bfd_is_und_section(sym_ptr->section))
1276 rm_reloc = true;
1278 if (strcmp(sym_ptr->name, "mcount") == 0 &&
1279 bfd_is_und_section(sym_ptr->section))
1280 rm_reloc = false;
1282 if (!find_span(ss, (*relocp)->address)->keep)
1283 rm_reloc = false;
1285 if (rm_reloc)
1286 write_ksplice_reloc(ss, *relocp);
1287 else
1288 *vec_grow(&ss->relocs, 1) = *relocp;
1292 struct supersect *make_section(struct superbfd *sbfd, const char *fmt, ...)
1294 va_list ap;
1295 char *name;
1296 va_start(ap, fmt);
1297 assert(vasprintf(&name, fmt, ap) >= 0);
1298 va_end(ap);
1300 asection *sect = bfd_get_section_by_name(sbfd->abfd, name);
1301 if (sect != NULL)
1302 return fetch_supersect(sbfd, sect);
1303 else
1304 return new_supersect(sbfd, name);
1307 arelent *create_reloc(struct supersect *ss, const void *addr, asymbol **symp,
1308 bfd_vma offset)
1310 bfd_reloc_code_real_type code;
1311 switch (bfd_arch_bits_per_address(ss->parent->abfd)) {
1312 case 32:
1313 code = BFD_RELOC_32;
1314 break;
1315 case 64:
1316 code = BFD_RELOC_64;
1317 break;
1318 default:
1319 DIE;
1322 arelent *reloc = malloc(sizeof(*reloc));
1323 reloc->sym_ptr_ptr = symp;
1324 reloc->address = addr_offset(ss, addr);
1325 reloc->howto = bfd_reloc_type_lookup(ss->parent->abfd, code);
1326 reloc->addend = offset;
1327 return reloc;
1330 void write_reloc(struct supersect *ss, const void *addr, asymbol **symp,
1331 bfd_vma offset)
1333 *vec_grow(&ss->new_relocs, 1) = create_reloc(ss, addr, symp, offset);
1336 void write_string(struct supersect *ss, const char **addr, const char *fmt, ...)
1338 va_list ap;
1339 struct supersect *str_ss = make_section(ss->parent, ".ksplice_str");
1340 char *str;
1341 va_start(ap, fmt);
1342 int len = vasprintf(&str, fmt, ap);
1343 assert(len >= 0);
1344 va_end(ap);
1346 unsigned long *str_offp = ulong_hash_lookup(&ksplice_string_offset, str,
1347 FALSE);
1348 if (str_offp == NULL) {
1349 char *buf = sect_grow(str_ss, len + 1, char);
1350 memcpy(buf, str, len + 1);
1351 str_offp = ulong_hash_lookup(&ksplice_string_offset, str, TRUE);
1352 *str_offp = addr_offset(str_ss, buf);
1355 write_reloc(ss, addr, &str_ss->symbol, *str_offp);
1358 void lookup_system_map(struct addr_vec *addrs, const char *name, long offset)
1360 struct addr_vec *map_addrs =
1361 addr_vec_hash_lookup(&system_map, name, FALSE);
1362 if (map_addrs == NULL)
1363 return;
1365 unsigned long *addr, *map_addr;
1366 for (map_addr = map_addrs->data;
1367 map_addr < map_addrs->data + map_addrs->size; map_addr++) {
1368 for (addr = addrs->data; addr < addrs->data + addrs->size;
1369 addr++) {
1370 if (*addr == *map_addr + offset)
1371 break;
1373 if (addr < addrs->data + addrs->size)
1374 continue;
1375 *vec_grow(addrs, 1) = *map_addr + offset;
1379 void compute_system_map_array(struct superbfd *sbfd, struct addr_vec *addrs,
1380 asymbol *sym)
1382 if (bfd_is_abs_section(sym->section)) {
1383 *vec_grow(addrs, 1) = sym->value;
1384 } else if (bfd_is_und_section(sym->section)) {
1385 lookup_system_map(addrs, sym->name, 0);
1386 } else if (!bfd_is_const_section(sym->section)) {
1387 asymbol **gsymp;
1388 for (gsymp = sbfd->syms.data;
1389 gsymp < sbfd->syms.data + sbfd->syms.size; gsymp++) {
1390 asymbol *gsym = *gsymp;
1391 if ((gsym->flags & BSF_DEBUGGING) == 0 &&
1392 gsym->section == sym->section)
1393 lookup_system_map(addrs, gsym->name,
1394 sym->value - gsym->value);
1399 void write_ksplice_system_map(struct superbfd *sbfd, asymbol *sym,
1400 const char *label)
1402 bool *done = bool_hash_lookup(&system_map_written, label, TRUE);
1403 if (*done)
1404 return;
1405 *done = true;
1407 struct addr_vec addrs;
1408 vec_init(&addrs);
1410 compute_system_map_array(sbfd, &addrs, sym);
1411 if (addrs.size != 0) {
1412 struct supersect *smap_ss =
1413 make_section(sbfd, ".ksplice_system_map");
1414 struct ksplice_system_map *smap =
1415 sect_grow(smap_ss, 1, struct ksplice_system_map);
1416 write_string(smap_ss, &smap->label, "%s", label);
1418 struct supersect *array_ss = make_section(sbfd,
1419 ".ksplice_array");
1420 void *buf = sect_grow(array_ss, addrs.size,
1421 typeof(*addrs.data));
1422 memcpy(buf, addrs.data, addrs.size * sizeof(*addrs.data));
1423 smap->nr_candidates = addrs.size;
1424 write_reloc(smap_ss, &smap->candidates, &array_ss->symbol,
1425 addr_offset(array_ss, buf));
1427 vec_free(&addrs);
1430 void write_ksplice_symbol_backend(struct supersect *ss,
1431 struct ksplice_symbol *const *addr,
1432 asymbol *sym, const char *label,
1433 const char *name)
1435 struct supersect *ksymbol_ss = make_section(ss->parent,
1436 ".ksplice_symbols");
1437 struct ksplice_symbol *ksymbol;
1438 unsigned long *ksymbol_offp;
1440 ksymbol_offp = ulong_hash_lookup(&ksplice_symbol_offset, label, FALSE);
1441 if (ksymbol_offp != NULL) {
1442 write_reloc(ss, addr, &ksymbol_ss->symbol, *ksymbol_offp);
1443 return;
1445 ksymbol = sect_grow(ksymbol_ss, 1, struct ksplice_symbol);
1446 ksymbol_offp = ulong_hash_lookup(&ksplice_symbol_offset, label, TRUE);
1447 *ksymbol_offp = addr_offset(ksymbol_ss, ksymbol);
1449 write_reloc(ss, addr, &ksymbol_ss->symbol, *ksymbol_offp);
1450 write_string(ksymbol_ss, &ksymbol->label, "%s", label);
1451 if (name != NULL) {
1452 write_string(ksymbol_ss, &ksymbol->name, "%s", name);
1453 write_ksplice_system_map(ksymbol_ss->parent, sym, label);
1457 void write_ksplice_symbol(struct supersect *ss,
1458 struct ksplice_symbol *const *addr,
1459 asymbol *sym, struct span *span,
1460 const char *addstr_sect)
1462 const char *label, *name;
1463 char *output;
1464 if (span != NULL && span->start != 0)
1465 label = span->label;
1466 else
1467 label = label_lookup(ss->parent, sym);
1469 assert(asprintf(&output, "%s%s", label, addstr_sect) >= 0);
1471 asymbol *gsym = canonical_symbol(ss->parent, sym);
1472 if (strcmp(addstr_sect, "") != 0)
1473 name = NULL;
1474 else if (bfd_is_und_section(sym->section))
1475 name = sym->name;
1476 else if (bfd_is_const_section(sym->section))
1477 name = NULL;
1478 else if (span != NULL && span->symbol == NULL)
1479 name = NULL;
1480 else if (gsym == NULL || (gsym->flags & BSF_SECTION_SYM) != 0)
1481 name = NULL;
1482 else
1483 name = gsym->name;
1485 write_ksplice_symbol_backend(ss, addr, sym, output, name);
1488 void write_ksplice_reloc(struct supersect *ss, arelent *orig_reloc)
1490 asymbol *sym_ptr = *orig_reloc->sym_ptr_ptr;
1491 bfd_vma reloc_addend = get_reloc_offset(ss, orig_reloc, false);
1492 bfd_vma target_addend = get_reloc_offset(ss, orig_reloc, true);
1493 unsigned long *repladdr = ss->contents.data + orig_reloc->address;
1495 if (mode("finalize") && starts_with(ss->name, ".ksplice_patches")) {
1496 *repladdr = 0;
1497 return;
1499 if (mode("finalize") && starts_with(ss->name, ".ksplice_relocs")) {
1500 assert(starts_with(sym_ptr->name, KSPLICE_SYMBOL_STR));
1501 asymbol fake_sym;
1502 fake_sym.name = sym_ptr->name + strlen(KSPLICE_SYMBOL_STR);
1503 fake_sym.section = bfd_und_section_ptr;
1504 fake_sym.value = 0;
1505 fake_sym.flags = 0;
1507 write_ksplice_symbol_backend
1508 (ss, (struct ksplice_symbol **)repladdr, &fake_sym,
1509 fake_sym.name, fake_sym.name);
1510 return;
1513 struct span *span = reloc_target_span(ss, orig_reloc);
1514 if (span == ss->spans.data && span->start != target_addend)
1515 span = NULL;
1516 blot_section(ss, orig_reloc->address, orig_reloc->howto);
1518 struct supersect *kreloc_ss;
1519 if (mode("rmsyms"))
1520 kreloc_ss = make_section(ss->parent, ".ksplice_init_relocs");
1521 else
1522 kreloc_ss = make_section(ss->parent, ".ksplice_relocs%s",
1523 ss->name);
1524 struct ksplice_reloc *kreloc = sect_grow(kreloc_ss, 1,
1525 struct ksplice_reloc);
1527 struct span *address_span = find_span(ss, orig_reloc->address);
1528 write_reloc(kreloc_ss, &kreloc->blank_addr,
1529 &ss->symbol, orig_reloc->address + address_span->shift);
1530 if (bfd_is_und_section(sym_ptr->section) && mode("keep")) {
1531 char *name;
1532 assert(asprintf(&name, KSPLICE_SYMBOL_STR "%s", sym_ptr->name)
1533 >= 0);
1534 asymbol **symp = make_undefined_symbolp(ss->parent, name);
1535 write_reloc(kreloc_ss, &kreloc->symbol, symp, 0);
1536 } else {
1537 write_ksplice_symbol(kreloc_ss, &kreloc->symbol, sym_ptr, span,
1538 "");
1540 if (span != NULL && span->start != 0) {
1541 reloc_addend += sym_ptr->value - span->start;
1542 target_addend += sym_ptr->value - span->start;
1544 kreloc->insn_addend = reloc_addend - target_addend;
1545 kreloc->target_addend = target_addend;
1546 write_ksplice_reloc_howto(kreloc_ss, &kreloc->howto, orig_reloc->howto);
1549 static void write_ksplice_reloc_howto(struct supersect *ss, const
1550 struct ksplice_reloc_howto *const *addr,
1551 reloc_howto_type *howto)
1553 struct supersect *khowto_ss = make_section(ss->parent,
1554 ".ksplice_reloc_howtos");
1555 struct ksplice_reloc_howto *khowto;
1556 unsigned long *khowto_offp;
1558 khowto_offp = ulong_hash_lookup(&ksplice_howto_offset, howto->name,
1559 FALSE);
1560 if (khowto_offp != NULL) {
1561 write_reloc(ss, addr, &khowto_ss->symbol, *khowto_offp);
1562 return;
1564 khowto = sect_grow(khowto_ss, 1, struct ksplice_reloc_howto);
1565 khowto_offp = ulong_hash_lookup(&ksplice_howto_offset, howto->name,
1566 TRUE);
1567 *khowto_offp = addr_offset(khowto_ss, khowto);
1569 khowto->type = KSPLICE_HOWTO_RELOC;
1570 khowto->pcrel = howto->pc_relative;
1571 khowto->size = bfd_get_reloc_size(howto);
1572 khowto->dst_mask = howto->dst_mask;
1573 khowto->rightshift = howto->rightshift;
1574 khowto->signed_addend =
1575 (howto->complain_on_overflow == complain_overflow_signed) ||
1576 (howto->complain_on_overflow == complain_overflow_bitfield);
1577 write_reloc(ss, addr, &khowto_ss->symbol, *khowto_offp);
1580 #define CANARY(x, canary) ((x & ~howto->dst_mask) | (canary & howto->dst_mask))
1582 void blot_section(struct supersect *ss, int offset, reloc_howto_type *howto)
1584 int bits = bfd_get_reloc_size(howto) * 8;
1585 void *address = ss->contents.data + offset;
1586 bfd_vma x = bfd_get(bits, ss->parent->abfd, address);
1587 x = (x & ~howto->dst_mask) |
1588 ((bfd_vma)KSPLICE_CANARY & howto->dst_mask);
1589 bfd_put(bits, ss->parent->abfd, x, address);
1592 static void write_date_relocs(struct superbfd *sbfd, const char *str,
1593 enum ksplice_reloc_howto_type type)
1595 asection *sect;
1596 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
1597 struct supersect *ss = fetch_supersect(sbfd, sect);
1598 if (ss->type != SS_TYPE_STRING && ss->type != SS_TYPE_RODATA)
1599 continue;
1600 void *ptr;
1601 struct span *span;
1602 for (span = ss->spans.data;
1603 span < ss->spans.data + ss->spans.size; span++) {
1604 if (!span->keep)
1605 continue;
1606 for (ptr = ss->contents.data + span->start;
1607 ptr + strlen(str) < ss->contents.data +
1608 span->start + span->size; ptr++) {
1609 if (strcmp((const char *)ptr, str) == 0)
1610 write_ksplice_date_reloc
1611 (ss, addr_offset(ss, ptr), str,
1612 type);
1618 static void write_ksplice_date_reloc(struct supersect *ss, unsigned long offset,
1619 const char *str,
1620 enum ksplice_reloc_howto_type type)
1622 struct supersect *kreloc_ss;
1623 kreloc_ss = make_section(ss->parent, ".ksplice_relocs%s", ss->name);
1624 struct ksplice_reloc *kreloc = sect_grow(kreloc_ss, 1,
1625 struct ksplice_reloc);
1627 const char *filename = ss->parent->abfd->filename;
1628 char *c = strstr(filename, ".KSPLICE");
1629 int flen = (c == NULL ? strlen(filename) : c - filename);
1631 char *label;
1632 assert(asprintf(&label, "%s<%.*s>", str, flen, filename) >= 0);
1633 write_ksplice_symbol_backend(kreloc_ss, &kreloc->symbol, NULL,
1634 label, NULL);
1636 struct span *span = find_span(ss, offset);
1637 write_reloc(kreloc_ss, &kreloc->blank_addr, &ss->symbol,
1638 offset + span->shift);
1639 write_ksplice_nonreloc_howto(kreloc_ss, &kreloc->howto, type,
1640 strlen(str));
1643 static void write_table_relocs(struct superbfd *sbfd, const char *sectname,
1644 enum ksplice_reloc_howto_type type)
1646 asection *sect = bfd_get_section_by_name(sbfd->abfd, sectname);
1647 if (sect == NULL)
1648 return;
1649 struct supersect *ss = fetch_supersect(sbfd, sect);
1651 const struct table_section *s = get_table_section(sectname);
1652 if (s == NULL)
1653 DIE;
1655 void *entry;
1656 for (entry = ss->contents.data;
1657 entry < ss->contents.data + ss->contents.size;
1658 entry += s->entry_size) {
1659 struct span *span = find_span(ss, addr_offset(ss, entry));
1660 assert(span != NULL);
1661 if (!span->keep)
1662 continue;
1664 arelent *reloc = find_reloc(ss, entry + s->addr_offset);
1665 assert(reloc != NULL);
1666 if (strcmp(ss->name, "__bug_table") == 0)
1667 write_ksplice_ignore_reloc
1668 (ss, addr_offset(ss, entry + s->other_offset),
1669 sizeof(unsigned short));
1670 asymbol *sym = *reloc->sym_ptr_ptr;
1671 assert(!bfd_is_const_section(sym->section));
1672 struct supersect *sym_ss = fetch_supersect(sbfd, sym->section);
1673 unsigned long addr = get_reloc_offset(ss, reloc, true) +
1674 sym->value;
1675 write_ksplice_table_reloc(sym_ss, addr, span->label, type);
1679 static void write_ksplice_table_reloc(struct supersect *ss,
1680 unsigned long address,
1681 const char *label,
1682 enum ksplice_reloc_howto_type type)
1684 struct supersect *kreloc_ss;
1685 kreloc_ss = make_section(ss->parent, ".ksplice_relocs%s", ss->name);
1686 struct ksplice_reloc *kreloc = sect_grow(kreloc_ss, 1,
1687 struct ksplice_reloc);
1688 struct span *span = find_span(ss, address);
1689 assert(span != NULL);
1691 write_ksplice_symbol_backend(kreloc_ss, &kreloc->symbol, NULL,
1692 label, NULL);
1693 write_reloc(kreloc_ss, &kreloc->blank_addr, &ss->symbol,
1694 address + span->shift);
1695 write_ksplice_nonreloc_howto(kreloc_ss, &kreloc->howto, type, 0);
1698 static void write_ksplice_ignore_reloc(struct supersect *ss,
1699 unsigned long address,
1700 bfd_size_type size)
1702 struct supersect *kreloc_ss;
1703 kreloc_ss = make_section(ss->parent, ".ksplice_relocs%s", ss->name);
1704 struct ksplice_reloc *kreloc = sect_grow(kreloc_ss, 1,
1705 struct ksplice_reloc);
1706 struct span *span = find_span(ss, address);
1707 assert(span != NULL);
1708 char *label;
1709 assert(asprintf(&label, "%s+%lx(IGNORED)", span->label, address) >= 0);
1711 write_ksplice_symbol_backend(kreloc_ss, &kreloc->symbol, NULL,
1712 label, NULL);
1713 write_reloc(kreloc_ss, &kreloc->blank_addr, &ss->symbol,
1714 address + span->shift);
1715 write_ksplice_nonreloc_howto(kreloc_ss, &kreloc->howto,
1716 KSPLICE_HOWTO_IGNORE, size);
1719 static void write_ksplice_nonreloc_howto(struct supersect *ss,
1720 const struct ksplice_reloc_howto
1721 *const *addr,
1722 enum ksplice_reloc_howto_type type,
1723 int size)
1725 struct supersect *khowto_ss =
1726 make_section(ss->parent, ".ksplice_reloc_howtos");
1727 struct ksplice_reloc_howto *khowto =
1728 sect_grow(khowto_ss, 1, struct ksplice_reloc_howto);
1730 khowto->type = type;
1731 khowto->size = size;
1732 khowto->pcrel = 0;
1733 khowto->dst_mask = 0;
1734 khowto->rightshift = 0;
1735 khowto->signed_addend = 0;
1736 write_reloc(ss, addr, &khowto_ss->symbol,
1737 addr_offset(khowto_ss, khowto));
1740 static void write_ksplice_section(struct span *span)
1742 struct supersect *ss = span->ss;
1743 const char *sectname = span->ss->name;
1744 const struct table_section *ts = get_table_section(ss->name);
1746 if (ts != NULL && ts->has_addr) {
1747 arelent *reloc = find_reloc(ss, ss->contents.data + span->start
1748 + ts->addr_offset);
1749 assert(reloc != NULL);
1750 asymbol *rsym = *reloc->sym_ptr_ptr;
1751 assert(!bfd_is_const_section(rsym->section));
1752 sectname = rsym->section->name;
1755 struct supersect *ksect_ss =
1756 make_section(ss->parent, ".ksplice_sections%s", sectname);
1757 struct ksplice_section *ksect = sect_grow(ksect_ss, 1,
1758 struct ksplice_section);
1759 asymbol *sym = span->symbol == NULL ? ss->symbol : span->symbol;
1761 write_ksplice_symbol(ksect_ss, &ksect->symbol, sym, span,
1762 mode("keep-primary") ? "(post)" : "");
1763 ksect->size = span->size;
1764 ksect->flags = 0;
1766 if (ss->type == SS_TYPE_RODATA || ss->type == SS_TYPE_STRING)
1767 ksect->flags |= KSPLICE_SECTION_RODATA;
1768 if (ss->type == SS_TYPE_DATA)
1769 ksect->flags |= KSPLICE_SECTION_DATA;
1770 if (ss->type == SS_TYPE_TEXT)
1771 ksect->flags |= KSPLICE_SECTION_TEXT;
1772 assert(ksect->flags != 0);
1774 if (ss->type == SS_TYPE_STRING)
1775 ksect->flags |= KSPLICE_SECTION_STRING;
1777 write_reloc(ksect_ss, &ksect->address, &ss->symbol,
1778 span->start + span->shift);
1781 void write_ksplice_patch(struct superbfd *sbfd, struct span *span)
1783 struct supersect *kpatch_ss =
1784 make_section(sbfd, ".ksplice_patches%s", span->ss->name);
1785 struct ksplice_patch *kpatch = sect_grow(kpatch_ss, 1,
1786 struct ksplice_patch);
1788 write_ksplice_symbol_backend(kpatch_ss, &kpatch->symbol, NULL,
1789 span->label, NULL);
1790 write_reloc(kpatch_ss, &kpatch->repladdr, &span->ss->symbol,
1791 span->start + span->shift);
1794 asymbol **make_undefined_symbolp(struct superbfd *sbfd, const char *name)
1796 asymbol **symp;
1797 for (symp = sbfd->syms.data; symp < sbfd->syms.data + sbfd->syms.size;
1798 symp++) {
1799 asymbol *sym = *symp;
1800 if (strcmp(name, sym->name) == 0 &&
1801 bfd_is_und_section(sym->section))
1802 return symp;
1804 asymbol ***sympp;
1805 for (sympp = sbfd->new_syms.data;
1806 sympp < sbfd->new_syms.data + sbfd->new_syms.size; sympp++) {
1807 asymbol **symp = *sympp;
1808 asymbol *sym = *symp;
1809 if (strcmp(name, sym->name) == 0 &&
1810 bfd_is_und_section(sym->section))
1811 return symp;
1814 symp = malloc(sizeof(*symp));
1815 *symp = bfd_make_empty_symbol(sbfd->abfd);
1816 asymbol *sym = *symp;
1817 sym->name = name;
1818 sym->section = bfd_und_section_ptr;
1819 sym->flags = 0;
1820 sym->value = 0;
1821 *vec_grow(&sbfd->new_syms, 1) = symp;
1822 return symp;
1825 void write_ksplice_deleted_patch(struct superbfd *sbfd, const char *name,
1826 const char *label, const char *sectname)
1828 struct supersect *kpatch_ss =
1829 make_section(sbfd, ".ksplice_patches%s", sectname);
1830 struct ksplice_patch *kpatch = sect_grow(kpatch_ss, 1,
1831 struct ksplice_patch);
1833 write_ksplice_symbol_backend(kpatch_ss, &kpatch->symbol, NULL,
1834 label, NULL);
1836 asymbol **symp = make_undefined_symbolp(sbfd, strdup(name));
1837 write_reloc(kpatch_ss, &kpatch->repladdr, symp, 0);
1840 void write_ksplice_export(struct superbfd *sbfd, const char *symname,
1841 const char *export_type, bool del)
1843 struct supersect *export_ss = make_section(sbfd, ".ksplice_exports");
1844 struct ksplice_export *exp = sect_grow(export_ss, 1,
1845 struct ksplice_export);
1847 if (del) {
1848 write_string(export_ss, &exp->name, "%s", symname);
1849 write_string(export_ss, &exp->new_name, "DISABLED_%s_%s",
1850 symname, kid);
1851 } else {
1852 write_string(export_ss, &exp->new_name, "%s", symname);
1853 write_string(export_ss, &exp->name, "DISABLED_%s_%s", symname,
1854 kid);
1858 void filter_table_sections(struct superbfd *isbfd)
1860 struct supersect *tables_ss =
1861 fetch_supersect(offsets_sbfd,
1862 bfd_get_section_by_name(offsets_sbfd->abfd,
1863 ".ksplice_table_sections"));
1864 const struct table_section *ts;
1865 for (ts = tables_ss->contents.data;
1866 (void *)ts < tables_ss->contents.data + tables_ss->contents.size;
1867 ts++) {
1868 struct table_section s = *ts;
1869 s.sect = read_string(tables_ss, &ts->sect);
1870 s.other_sect = read_string(tables_ss, &ts->other_sect);
1871 if (s.has_addr)
1872 filter_table_section(isbfd, &s);
1876 void filter_table_section(struct superbfd *sbfd, const struct table_section *s)
1878 asection *isection = bfd_get_section_by_name(sbfd->abfd, s->sect);
1879 if (isection == NULL)
1880 return;
1881 struct supersect *ss = fetch_supersect(sbfd, isection);
1883 void *entry;
1884 for (entry = ss->contents.data;
1885 entry < ss->contents.data + ss->contents.size;
1886 entry += s->entry_size) {
1887 asymbol *sym;
1888 struct span *span = find_span(ss, addr_offset(ss, entry));
1889 assert(span != NULL);
1891 read_reloc(ss, entry + s->addr_offset, sizeof(void *), &sym);
1892 struct supersect *sym_ss = fetch_supersect(sbfd, sym->section);
1893 if (sym_ss->keep)
1894 keep_span(span);
1896 if (s->other_sect != NULL) {
1897 arelent *reloc =
1898 find_reloc(ss, entry + s->other_offset);
1899 assert(reloc != NULL);
1900 struct span *sym_span = reloc_target_span(ss, reloc);
1901 if (span->keep)
1902 keep_span(sym_span);
1907 void keep_referenced_sections(struct superbfd *sbfd)
1909 asection *sect;
1910 struct supersect *ss, *sym_ss;
1911 struct span *address_span, *target_span;
1912 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
1913 ss = fetch_supersect(sbfd, sect);
1914 arelent **relocp;
1915 if (ss->type == SS_TYPE_SPECIAL || ss->type == SS_TYPE_EXPORT)
1916 continue;
1917 for (relocp = ss->relocs.data;
1918 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
1919 asymbol *sym = *(*relocp)->sym_ptr_ptr;
1920 address_span = find_span(ss, (*relocp)->address);
1921 if (!address_span->keep)
1922 continue;
1923 target_span = reloc_target_span(ss, *relocp);
1924 if (target_span == NULL || target_span->keep)
1925 continue;
1926 sym_ss = fetch_supersect(sbfd, sym->section);
1927 if (sym_ss->type == SS_TYPE_IGNORED)
1928 continue;
1929 keep_span(target_span);
1930 changed = true;
1935 void copy_symbols(struct asymbolp_vec *osyms, struct asymbolpp_vec *isyms)
1937 asymbol ***sympp;
1938 for (sympp = isyms->data; sympp < isyms->data + isyms->size; sympp++)
1939 *vec_grow(osyms, 1) = **sympp;
1942 /* Modified function from GNU Binutils objcopy.c */
1943 bfd_boolean copy_object(bfd *ibfd, bfd *obfd)
1945 assert(bfd_set_format(obfd, bfd_get_format(ibfd)));
1947 bfd_vma start = bfd_get_start_address(ibfd);
1949 flagword flags = bfd_get_file_flags(ibfd);
1950 flags &= bfd_applicable_file_flags(obfd);
1952 assert(bfd_set_start_address(obfd, start)
1953 && bfd_set_file_flags(obfd, flags));
1955 enum bfd_architecture iarch = bfd_get_arch(ibfd);
1956 unsigned int imach = bfd_get_mach(ibfd);
1957 assert(bfd_set_arch_mach(obfd, iarch, imach));
1958 assert(bfd_set_format(obfd, bfd_get_format(ibfd)));
1960 /* BFD mandates that all output sections be created and sizes set before
1961 any output is done. Thus, we traverse all sections multiple times. */
1962 bfd_map_over_sections(ibfd, setup_section, obfd);
1964 struct supersect *new_supersects = fetch_superbfd(ibfd)->new_supersects;
1965 struct supersect *ss;
1966 for (ss = new_supersects; ss != NULL; ss = ss->next)
1967 setup_new_section(obfd, ss);
1969 /* Mark symbols used in output relocations so that they
1970 are kept, even if they are local labels or static symbols.
1972 Note we iterate over the input sections examining their
1973 relocations since the relocations for the output sections
1974 haven't been set yet. mark_symbols_used_in_relocations will
1975 ignore input sections which have no corresponding output
1976 section. */
1978 bfd_map_over_sections(ibfd, mark_symbols_used_in_relocations, NULL);
1979 for (ss = new_supersects; ss != NULL; ss = ss->next)
1980 ss_mark_symbols_used_in_relocations(ss);
1981 struct asymbolp_vec osyms;
1982 vec_init(&osyms);
1983 filter_symbols(ibfd, obfd, &osyms, &fetch_superbfd(ibfd)->syms);
1984 copy_symbols(&osyms, &fetch_superbfd(ibfd)->new_syms);
1986 bfd_set_symtab(obfd, osyms.data, osyms.size);
1988 /* This has to happen after the symbol table has been set. */
1989 bfd_map_over_sections(obfd, write_section, NULL);
1991 /* Allow the BFD backend to copy any private data it understands
1992 from the input BFD to the output BFD. This is done last to
1993 permit the routine to look at the filtered symbol table, which is
1994 important for the ECOFF code at least. */
1995 assert(bfd_copy_private_bfd_data(ibfd, obfd));
1997 return TRUE;
2000 /* Modified function from GNU Binutils objcopy.c */
2001 void setup_section(bfd *ibfd, asection *isection, void *obfdarg)
2003 struct superbfd *isbfd = fetch_superbfd(ibfd);
2004 struct supersect *ss = fetch_supersect(isbfd, isection);
2005 bfd *obfd = obfdarg;
2006 bfd_vma vma;
2008 if (!ss->keep)
2009 return;
2011 asection *osection = bfd_make_section_anyway(obfd, ss->name);
2012 assert(osection != NULL);
2014 osection->userdata = ss;
2015 bfd_set_section_flags(obfd, osection, ss->flags);
2016 ss->symbol = osection->symbol;
2017 assert(bfd_set_section_size(obfd, osection, ss->contents.size));
2019 vma = bfd_section_vma(ibfd, isection);
2020 assert(bfd_set_section_vma(obfd, osection, vma));
2022 osection->lma = isection->lma;
2023 assert(bfd_set_section_alignment(obfd, osection, ss->alignment));
2024 osection->entsize = isection->entsize;
2025 osection->output_section = osection;
2026 osection->output_offset = 0;
2027 isection->output_section = osection;
2028 isection->output_offset = 0;
2029 return;
2032 void setup_new_section(bfd *obfd, struct supersect *ss)
2034 asection *osection = bfd_make_section_anyway(obfd, ss->name);
2035 assert(osection != NULL);
2036 bfd_set_section_flags(obfd, osection, ss->flags);
2038 osection->userdata = ss;
2039 ss->symbol = osection->symbol;
2040 assert(bfd_set_section_size(obfd, osection, ss->contents.size));
2041 assert(bfd_set_section_vma(obfd, osection, 0));
2043 osection->lma = 0;
2044 assert(bfd_set_section_alignment(obfd, osection, ss->alignment));
2045 osection->entsize = 0;
2046 osection->output_section = osection;
2047 osection->output_offset = 0;
2050 static int compare_reloc_addresses(const void *aptr, const void *bptr)
2052 const arelent *const *a = aptr, *const *b = bptr;
2053 return (*a)->address - (*b)->address;
2056 static void delete_obsolete_relocs(struct supersect *ss)
2058 if (ss->new_relocs.size == 0)
2059 return;
2061 qsort(ss->relocs.data, ss->relocs.size, sizeof(*ss->relocs.data),
2062 compare_reloc_addresses);
2063 qsort(ss->new_relocs.data, ss->new_relocs.size,
2064 sizeof(*ss->new_relocs.data), compare_reloc_addresses);
2066 struct arelentp_vec orig_relocs;
2067 vec_move(&orig_relocs, &ss->relocs);
2069 arelent **relocp, **new_relocp = ss->new_relocs.data;
2070 for (relocp = orig_relocs.data;
2071 relocp < orig_relocs.data + orig_relocs.size; relocp++) {
2072 while (new_relocp < ss->new_relocs.data + ss->new_relocs.size &&
2073 (*new_relocp)->address < (*relocp)->address)
2074 new_relocp++;
2075 arelent *reloc = *relocp, *new_reloc = *new_relocp;
2076 if (new_relocp == ss->new_relocs.data + ss->new_relocs.size ||
2077 reloc->address != new_reloc->address)
2078 *vec_grow(&ss->relocs, 1) = reloc;
2082 void write_section(bfd *obfd, asection *osection, void *arg)
2084 struct supersect *ss = osection->userdata;
2086 if ((ss->flags & SEC_GROUP) != 0 || ss->contents.size == 0)
2087 return;
2089 delete_obsolete_relocs(ss);
2091 arelent **relocp;
2092 char *error_message;
2093 for (relocp = ss->new_relocs.data;
2094 relocp < ss->new_relocs.data + ss->new_relocs.size; relocp++) {
2095 bfd_vma val;
2096 if (bfd_get_arch(obfd) == bfd_arch_arm)
2097 val = osection->use_rela_p ? 0 : (*relocp)->addend;
2098 else
2099 val = 0;
2100 bfd_put(bfd_get_reloc_size((*relocp)->howto) * 8, obfd, val,
2101 ss->contents.data + (*relocp)->address);
2102 if (bfd_install_relocation(obfd, *relocp, ss->contents.data,
2103 0, osection, &error_message) !=
2104 bfd_reloc_ok) {
2105 err(ss->parent, "ksplice: error installing reloc: %s",
2106 error_message);
2107 DIE;
2110 memcpy(vec_grow(&ss->relocs, ss->new_relocs.size), ss->new_relocs.data,
2111 ss->new_relocs.size * sizeof(*ss->new_relocs.data));
2113 bfd_set_reloc(obfd, osection,
2114 ss->relocs.size == 0 ? NULL : ss->relocs.data,
2115 ss->relocs.size);
2117 if (ss->flags & SEC_HAS_CONTENTS)
2118 assert(bfd_set_section_contents
2119 (obfd, osection, ss->contents.data, 0,
2120 ss->contents.size));
2123 /* Modified function from GNU Binutils objcopy.c
2125 * Mark all the symbols which will be used in output relocations with
2126 * the BSF_KEEP flag so that those symbols will not be stripped.
2128 * Ignore relocations which will not appear in the output file.
2130 void mark_symbols_used_in_relocations(bfd *abfd, asection *isection,
2131 void *ignored)
2133 struct superbfd *sbfd = fetch_superbfd(abfd);
2134 if (isection->output_section == NULL)
2135 return;
2137 struct supersect *ss = fetch_supersect(sbfd, isection);
2138 ss_mark_symbols_used_in_relocations(ss);
2141 void ss_mark_symbols_used_in_relocations(struct supersect *ss)
2143 /* Examine each symbol used in a relocation. If it's not one of the
2144 special bfd section symbols, then mark it with BSF_KEEP. */
2145 arelent **relocp;
2146 for (relocp = ss->relocs.data;
2147 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
2148 asymbol *sym = *(*relocp)->sym_ptr_ptr;
2149 if (!(bfd_is_const_section(sym->section) &&
2150 sym == sym->section->symbol))
2151 sym->flags |= BSF_KEEP;
2153 for (relocp = ss->new_relocs.data;
2154 relocp < ss->new_relocs.data + ss->new_relocs.size; relocp++) {
2155 asymbol *sym = *(*relocp)->sym_ptr_ptr;
2156 if (!(bfd_is_const_section(sym->section) &&
2157 sym == sym->section->symbol))
2158 sym->flags |= BSF_KEEP;
2162 static bool deleted_table_section_symbol(bfd *abfd, asymbol *sym)
2164 struct superbfd *sbfd = fetch_superbfd(abfd);
2165 if (bfd_is_const_section(sym->section))
2166 return false;
2167 struct supersect *ss = fetch_supersect(sbfd, sym->section);
2169 asymbol **symp;
2170 for (symp = ss->syms.data; symp < ss->syms.data + ss->syms.size; symp++) {
2171 if (sym == *symp)
2172 break;
2174 return symp >= ss->syms.data + ss->syms.size &&
2175 (sym->flags & BSF_SECTION_SYM) == 0;
2178 void filter_symbols(bfd *ibfd, bfd *obfd, struct asymbolp_vec *osyms,
2179 struct asymbolp_vec *isyms)
2181 asymbol **symp;
2182 struct superbfd *sbfd = fetch_superbfd(ibfd);
2183 for (symp = isyms->data; symp < isyms->data + isyms->size; symp++) {
2184 asymbol *sym = *symp;
2185 struct supersect *sym_ss = NULL;
2186 struct span *sym_span = NULL;
2187 if (!bfd_is_const_section(sym->section)) {
2188 sym_ss = fetch_supersect(sbfd, sym->section);
2189 sym_span = find_span(sym_ss, sym->value);
2192 if (mode("keep") && (sym->flags & BSF_GLOBAL) != 0 &&
2193 !(mode("keep-primary") && sym_span != NULL &&
2194 sym_span->new))
2195 sym->flags = (sym->flags & ~BSF_GLOBAL) | BSF_LOCAL;
2197 if (mode("finalize") && (sym->flags & BSF_GLOBAL) != 0)
2198 sym->flags = (sym->flags & ~BSF_GLOBAL) | BSF_LOCAL;
2200 bool keep = bfd_is_const_section(sym->section) ||
2201 (sym_ss->keep && (sym->flags & BSF_SECTION_SYM) != 0) ||
2202 (sym_span != NULL && sym_span->keep);
2203 if (bfd_is_und_section(sym->section) &&
2204 (sym->flags & BSF_KEEP) == 0)
2205 keep = false;
2206 if (deleted_table_section_symbol(ibfd, sym))
2207 keep = false;
2209 if (keep) {
2210 if (sym_ss != NULL && !sym_ss->keep) {
2211 err(sbfd, "Kept symbol %s in unkept section "
2212 "%s\n", sym->name, sym->section->name);
2213 DIE;
2215 *vec_grow(osyms, 1) = sym;
2220 void read_str_set(struct str_vec *strs)
2222 char *buf = NULL;
2223 size_t n = 0;
2224 assert(getline(&buf, &n, stdin) >= 0);
2225 vec_init(strs);
2226 char *saveptr;
2227 while (1) {
2228 char *str = strtok_r(buf, " \n", &saveptr);
2229 buf = NULL;
2230 if (str == NULL)
2231 break;
2232 *vec_grow(strs, 1) = str;
2236 bool str_in_set(const char *str, const struct str_vec *strs)
2238 const char **strp;
2239 for (strp = strs->data; strp < strs->data + strs->size; strp++) {
2240 if (strcmp(str, *strp) == 0)
2241 return true;
2243 return false;
2246 bool is_table_section(const char *name, bool consider_other)
2248 struct supersect *tables_ss =
2249 fetch_supersect(offsets_sbfd,
2250 bfd_get_section_by_name(offsets_sbfd->abfd,
2251 ".ksplice_table_sections"));
2252 const struct table_section *ts;
2253 for (ts = tables_ss->contents.data;
2254 (void *)ts < tables_ss->contents.data + tables_ss->contents.size;
2255 ts++) {
2256 if (strcmp(name, read_string(tables_ss, &ts->sect)) == 0)
2257 return true;
2258 const char *osect_name = read_string(tables_ss,
2259 &ts->other_sect);
2260 if (consider_other && osect_name != NULL &&
2261 strcmp(name, osect_name) == 0)
2262 return true;
2264 return false;
2267 const struct table_section *get_table_section(const char *name)
2269 struct supersect *tables_ss =
2270 fetch_supersect(offsets_sbfd,
2271 bfd_get_section_by_name(offsets_sbfd->abfd,
2272 ".ksplice_table_sections"));
2273 const struct table_section *ts;
2274 for (ts = tables_ss->contents.data;
2275 (void *)ts < tables_ss->contents.data + tables_ss->contents.size;
2276 ts++) {
2277 if (strcmp(name, read_string(tables_ss, &ts->sect)) == 0)
2278 return ts;
2280 return NULL;
2283 enum supersect_type supersect_type(struct supersect *ss)
2285 if (mode("finalize") &&
2286 strcmp(finalize_target, "vmlinux") == 0 &&
2287 (starts_with(ss->name, ".ksplice_relocs.exit") ||
2288 starts_with(ss->name, ".ksplice_sections.exit") ||
2289 starts_with(ss->name, ".ksplice_patches.exit")))
2290 return SS_TYPE_EXIT;
2291 if (starts_with(ss->name, ".ksplice"))
2292 return SS_TYPE_KSPLICE;
2294 if (starts_with(ss->name, ".init"))
2295 return SS_TYPE_IGNORED;
2296 if (starts_with(ss->name, ".security_initcall.init"))
2297 return SS_TYPE_IGNORED;
2298 if (starts_with(ss->name, ".con_initcall.init"))
2299 return SS_TYPE_IGNORED;
2300 if (starts_with(ss->name, ".x86cpuvendor.init"))
2301 return SS_TYPE_IGNORED;
2302 if (starts_with(ss->name, ".early_param.init"))
2303 return SS_TYPE_IGNORED;
2304 if (starts_with(ss->name, ".taglist.init"))
2305 return SS_TYPE_IGNORED;
2306 if (starts_with(ss->name, ".arch.info.init"))
2307 return SS_TYPE_IGNORED;
2308 if (starts_with(ss->name, ".proc.info.init"))
2309 return SS_TYPE_IGNORED;
2310 /* .pci_fixup_* sections really should be treated as global rodata
2311 referenced only from quirks.c */
2312 if (starts_with(ss->name, ".pci_fixup_"))
2313 return SS_TYPE_IGNORED;
2314 /* .builtin_fw sections are similar to .pci_fixup */
2315 if (starts_with(ss->name, ".builtin_fw"))
2316 return SS_TYPE_IGNORED;
2317 /* same for .tracedata */
2318 if (starts_with(ss->name, ".tracedata"))
2319 return SS_TYPE_IGNORED;
2320 if (starts_with(ss->name, ".debug"))
2321 return SS_TYPE_IGNORED;
2322 /* .eh_frame should probably be discarded, not ignored */
2323 if (starts_with(ss->name, ".eh_frame"))
2324 return SS_TYPE_IGNORED;
2325 if (config->ignore_devinit && starts_with(ss->name, ".devinit"))
2326 return SS_TYPE_IGNORED;
2327 if (config->ignore_meminit && starts_with(ss->name, ".meminit"))
2328 return SS_TYPE_IGNORED;
2329 if (config->ignore_cpuinit && starts_with(ss->name, ".cpuinit"))
2330 return SS_TYPE_IGNORED;
2331 if (config->ignore_devinit && starts_with(ss->name, ".devexit"))
2332 return SS_TYPE_IGNORED;
2333 if (config->ignore_meminit && starts_with(ss->name, ".memexit"))
2334 return SS_TYPE_IGNORED;
2335 if (config->ignore_cpuinit && starts_with(ss->name, ".cpuexit"))
2336 return SS_TYPE_IGNORED;
2337 if (starts_with(ss->name, ".vgetcpu_mode") ||
2338 starts_with(ss->name, ".jiffies") ||
2339 starts_with(ss->name, ".wall_jiffies") ||
2340 starts_with(ss->name, ".vxtime") ||
2341 starts_with(ss->name, ".sys_tz") ||
2342 starts_with(ss->name, ".sysctl_vsyscall") ||
2343 starts_with(ss->name, ".xtime") ||
2344 starts_with(ss->name, ".xtime_lock") ||
2345 starts_with(ss->name, ".vsyscall"))
2346 return SS_TYPE_IGNORED;
2347 if (starts_with(ss->name, ".vdso"))
2348 return SS_TYPE_IGNORED;
2350 if (starts_with(ss->name, ".exit.text"))
2351 return SS_TYPE_TEXT;
2352 if (starts_with(ss->name, ".exit.data"))
2353 return SS_TYPE_DATA;
2355 if (starts_with(ss->name, ".text") ||
2356 starts_with(ss->name, ".kernel.text") ||
2357 starts_with(ss->name, ".devinit.text") ||
2358 starts_with(ss->name, ".meminit.text") ||
2359 starts_with(ss->name, ".cpuinit.text") ||
2360 starts_with(ss->name, ".devexit.text") ||
2361 starts_with(ss->name, ".memexit.text") ||
2362 starts_with(ss->name, ".cpuexit.text") ||
2363 starts_with(ss->name, ".ref.text") ||
2364 starts_with(ss->name, ".spinlock.text") ||
2365 starts_with(ss->name, ".kprobes.text") ||
2366 starts_with(ss->name, ".sched.text") ||
2367 (mode("keep-helper") && starts_with(ss->name, ".fixup")))
2368 return SS_TYPE_TEXT;
2370 int n = -1;
2371 if (sscanf(ss->name, ".rodata.str%*u.%*u%n", &n) >= 0 &&
2372 n == strlen(ss->name))
2373 return SS_TYPE_STRING;
2375 if (starts_with(ss->name, ".rodata") ||
2376 starts_with(ss->name, ".kernel.rodata") ||
2377 starts_with(ss->name, ".devinit.rodata") ||
2378 starts_with(ss->name, ".meminit.rodata") ||
2379 starts_with(ss->name, ".cpuinit.rodata") ||
2380 starts_with(ss->name, ".devexit.rodata") ||
2381 starts_with(ss->name, ".memexit.rodata") ||
2382 starts_with(ss->name, ".cpuexit.rodata") ||
2383 starts_with(ss->name, ".ref.rodata") ||
2384 starts_with(ss->name, "__markers_strings") ||
2385 (mode("keep-helper") && (starts_with(ss->name, "__bug_table") ||
2386 starts_with(ss->name, "__ex_table"))))
2387 return SS_TYPE_RODATA;
2389 if (starts_with(ss->name, ".bss"))
2390 return SS_TYPE_DATA;
2392 /* Ignore .data.percpu sections */
2393 if (starts_with(ss->name, ".data.percpu") ||
2394 starts_with(ss->name, ".kernel.data.percpu"))
2395 return SS_TYPE_IGNORED;
2396 if (starts_with(ss->name, ".data") ||
2397 starts_with(ss->name, ".kernel.data") ||
2398 starts_with(ss->name, ".devinit.data") ||
2399 starts_with(ss->name, ".cpuinit.data") ||
2400 starts_with(ss->name, ".meminit.data") ||
2401 starts_with(ss->name, ".devexit.data") ||
2402 starts_with(ss->name, ".memexit.data") ||
2403 starts_with(ss->name, ".cpuexit.data") ||
2404 starts_with(ss->name, ".ref.data") ||
2405 starts_with(ss->name, "__markers"))
2406 return SS_TYPE_DATA;
2408 /* We replace all the ksymtab strings, so delete them */
2409 if (strcmp(ss->name, "__ksymtab_strings") == 0)
2410 return SS_TYPE_IGNORED;
2411 if (starts_with(ss->name, "__ksymtab"))
2412 return SS_TYPE_EXPORT;
2413 if (starts_with(ss->name, "__kcrctab"))
2414 return SS_TYPE_EXPORT;
2416 if (is_table_section(ss->name, true))
2417 return SS_TYPE_SPECIAL;
2419 if (starts_with(ss->name, ".ARM."))
2420 return SS_TYPE_SPECIAL;
2422 if (starts_with(ss->name, ".note"))
2423 return SS_TYPE_IGNORED;
2424 if (starts_with(ss->name, ".comment"))
2425 return SS_TYPE_IGNORED;
2426 if (starts_with(ss->name, "__param"))
2427 return SS_TYPE_IGNORED;
2428 if (starts_with(ss->name, ".exitcall.exit"))
2429 return SS_TYPE_IGNORED;
2430 if (starts_with(ss->name, ".modinfo"))
2431 return SS_TYPE_IGNORED;
2433 return SS_TYPE_UNKNOWN;
2436 void initialize_supersect_types(struct superbfd *sbfd)
2438 asection *sect;
2439 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2440 struct supersect *ss = fetch_supersect(sbfd, sect);
2441 ss->type = supersect_type(ss);
2442 if (ss->type == SS_TYPE_UNKNOWN) {
2443 err(sbfd, "Unknown section type: %s\n", ss->name);
2444 DIE;
2449 static void init_label_map(struct superbfd *sbfd)
2451 struct label_map *map;
2453 vec_init(&sbfd->maps);
2454 init_csyms(sbfd);
2455 init_callers(sbfd);
2457 struct symbol_hash csyms;
2458 symbol_hash_init(&csyms);
2460 asymbol **symp;
2461 for (symp = sbfd->syms.data;
2462 symp < sbfd->syms.data + sbfd->syms.size; symp++) {
2463 asymbol *csym = canonical_symbol(sbfd, *symp);
2464 if (csym == NULL)
2465 continue;
2466 char *key;
2467 assert(asprintf(&key, "%p", csym) >= 0);
2468 asymbol **csymp = symbol_hash_lookup(&csyms, key, TRUE);
2469 free(key);
2470 if (*csymp != NULL)
2471 continue;
2472 *csymp = csym;
2474 map = vec_grow(&sbfd->maps, 1);
2475 map->csym = csym;
2476 map->count = 0;
2477 map->label = symbol_label(sbfd, csym);
2480 struct label_mapp_hash label_maps;
2481 label_mapp_hash_init(&label_maps);
2482 for (map = sbfd->maps.data;
2483 map < sbfd->maps.data + sbfd->maps.size; map++) {
2484 struct label_map **mapp =
2485 label_mapp_hash_lookup(&label_maps, map->label, TRUE);
2486 if (*mapp == NULL) {
2487 *mapp = map;
2488 continue;
2491 struct label_map *first_map = *mapp;
2492 char *buf;
2493 if (first_map->count == 0) {
2494 assert(asprintf(&buf, "%s~%d", map->label, 0) >= 0);
2495 first_map->label = buf;
2497 first_map->count++;
2498 assert(asprintf(&buf, "%s~%d", map->label, first_map->count)
2499 >= 0);
2500 map->label = buf;
2503 label_mapp_hash_init(&sbfd->maps_hash);
2504 for (map = sbfd->maps.data;
2505 map < sbfd->maps.data + sbfd->maps.size; map++) {
2506 char *key;
2507 assert(asprintf(&key, "%p", map->csym) >= 0);
2508 struct label_map **mapp =
2509 label_mapp_hash_lookup(&sbfd->maps_hash, key, TRUE);
2510 free(key);
2511 *mapp = map;
2512 map->orig_label = map->label;
2516 static const char *label_lookup(struct superbfd *sbfd, asymbol *sym)
2518 asymbol *csym = canonical_symbol(sbfd, sym);
2519 char *key;
2520 assert(asprintf(&key, "%p", csym) >= 0);
2521 struct label_map **mapp =
2522 label_mapp_hash_lookup(&sbfd->maps_hash, key, FALSE);
2523 free(key);
2524 if (mapp == NULL)
2525 DIE;
2526 return (*mapp)->label;
2529 static void print_label_changes(struct superbfd *sbfd)
2531 asection *sect;
2532 struct span *span;
2533 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2534 struct supersect *ss = fetch_supersect(sbfd, sect);
2535 for (span = ss->spans.data;
2536 span < ss->spans.data + ss->spans.size; span++) {
2537 if (strcmp(span->label, span->orig_label) != 0)
2538 debug1(sbfd, "Label change: %s -> %s\n",
2539 span->label, span->orig_label);
2544 static void label_map_set(struct superbfd *sbfd, const char *oldlabel,
2545 const char *label)
2547 struct label_map *map;
2548 for (map = sbfd->maps.data;
2549 map < sbfd->maps.data + sbfd->maps.size; map++) {
2550 if (strcmp(map->orig_label, oldlabel) == 0) {
2551 if (strcmp(map->orig_label, map->label) != 0 &&
2552 strcmp(map->label, label) != 0)
2553 DIE;
2554 map->label = label;
2555 return;
2558 DIE;
2561 static void init_callers(struct superbfd *sbfd)
2563 string_hash_init(&sbfd->callers);
2564 asection *sect;
2565 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2566 struct supersect *ss = fetch_supersect(sbfd, sect);
2567 arelent **relocp;
2568 for (relocp = ss->relocs.data;
2569 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
2570 asymbol *sym = *(*relocp)->sym_ptr_ptr;
2571 unsigned long val =
2572 sym->value + get_reloc_offset(ss, *relocp, true);
2573 char *key;
2574 assert(asprintf(&key, "%s+%lx", sym->section->name,
2575 val) >= 0);
2576 const char **ret = string_hash_lookup(&sbfd->callers,
2577 key, TRUE);
2578 free(key);
2579 if (*ret == NULL)
2580 *ret = sect->name;
2581 else
2582 *ret = "*multiple_callers*";
2587 static const char *find_caller(struct supersect *ss, asymbol *sym)
2589 char *key;
2590 assert(asprintf(&key, "%s+%lx", sym->section->name,
2591 (unsigned long)sym->value) >= 0);
2592 const char **ret = string_hash_lookup(&ss->parent->callers, key, FALSE);
2593 free(key);
2595 if (ret == NULL)
2596 return "*no_caller*";
2597 return *ret;
2600 static void init_csyms(struct superbfd *sbfd)
2602 asymbolpp_hash_init(&sbfd->csyms);
2604 asymbol **symp;
2605 for (symp = sbfd->syms.data; symp < sbfd->syms.data + sbfd->syms.size;
2606 symp++) {
2607 asymbol *sym = *symp;
2608 if ((sym->flags & BSF_DEBUGGING) != 0)
2609 continue;
2610 char *key;
2611 assert(asprintf(&key, "%s+%lx", sym->section->name,
2612 (unsigned long)sym->value) >= 0);
2613 asymbol ***csympp = asymbolpp_hash_lookup(&sbfd->csyms, key,
2614 TRUE);
2615 free(key);
2616 if (*csympp == NULL) {
2617 *csympp = symp;
2618 continue;
2620 asymbol *csym = **csympp;
2621 if ((csym->flags & BSF_GLOBAL) != 0)
2622 continue;
2623 if ((sym->flags & BSF_GLOBAL) != 0)
2624 *csympp = symp;
2628 static asymbol **symbolp_scan(struct supersect *ss, bfd_vma value)
2630 char *key;
2631 assert(asprintf(&key, "%s+%lx", ss->name, (unsigned long)value) >= 0);
2632 asymbol ***csympp =
2633 asymbolpp_hash_lookup(&ss->parent->csyms, key, FALSE);
2634 free(key);
2635 if (csympp != NULL)
2636 return *csympp;
2638 /* For section symbols of sections containing no symbols, return the
2639 section symbol that relocations are generated against */
2640 if (value == 0)
2641 return &ss->symbol;
2642 return NULL;
2645 static asymbol **canonical_symbolp(struct superbfd *sbfd, asymbol *sym)
2647 if (bfd_is_const_section(sym->section)) {
2648 asymbol **csymp;
2649 for (csymp = sbfd->syms.data;
2650 csymp < sbfd->syms.data + sbfd->syms.size; csymp++) {
2651 if (sym == *csymp)
2652 return csymp;
2654 return NULL;
2656 return symbolp_scan(fetch_supersect(sbfd, sym->section), sym->value);
2659 static asymbol *canonical_symbol(struct superbfd *sbfd, asymbol *sym)
2661 if (bfd_is_const_section(sym->section))
2662 return sym;
2663 asymbol **symp = canonical_symbolp(sbfd, sym);
2664 return symp != NULL ? *symp : NULL;
2667 static char *static_local_symbol(struct superbfd *sbfd, asymbol *sym)
2669 struct supersect *ss = fetch_supersect(sbfd, sym->section);
2670 if ((sym->flags & BSF_LOCAL) == 0 || (sym->flags & BSF_OBJECT) == 0)
2671 return NULL;
2672 char *dot = strrchr(sym->name, '.');
2673 if (dot == NULL || dot[1 + strspn(dot + 1, "0123546789")] != '\0')
2674 return NULL;
2675 char *basename = strndup(sym->name, dot - sym->name);
2676 char *mangled_name;
2677 if (strcmp(basename, "__func__") == 0 ||
2678 strcmp(basename, "__PRETTY_FUNCTION__") == 0)
2679 assert(asprintf(&mangled_name, "%s<%s>", basename,
2680 (char *)ss->contents.data + sym->value) >= 0);
2681 else
2682 assert(asprintf(&mangled_name, "%s<%s>", basename,
2683 find_caller(ss, sym)) >= 0);
2684 return mangled_name;
2687 static char *symbol_label(struct superbfd *sbfd, asymbol *sym)
2689 const char *filename = sbfd->abfd->filename;
2690 char *c = strstr(filename, ".KSPLICE");
2691 int flen = (c == NULL ? strlen(filename) : c - filename);
2693 char *label;
2694 if (bfd_is_und_section(sym->section) || (sym->flags & BSF_GLOBAL) != 0) {
2695 label = strdup(sym->name);
2696 } else if (bfd_is_const_section(sym->section)) {
2697 assert(asprintf(&label, "%s<%.*s>",
2698 sym->name, flen, filename) >= 0);
2699 } else {
2700 asymbol *gsym = canonical_symbol(sbfd, sym);
2702 if (gsym == NULL)
2703 assert(asprintf(&label, "%s+%lx<%.*s>",
2704 sym->section->name,
2705 (unsigned long)sym->value,
2706 flen, filename) >= 0);
2707 else if ((gsym->flags & BSF_GLOBAL) != 0)
2708 label = strdup(gsym->name);
2709 else if (static_local_symbol(sbfd, gsym))
2710 assert(asprintf(&label, "%s+%lx<%.*s>",
2711 static_local_symbol(sbfd, gsym),
2712 (unsigned long)sym->value,
2713 flen, filename) >= 0);
2714 else
2715 assert(asprintf(&label, "%s<%.*s>",
2716 gsym->name, flen, filename) >= 0);
2719 return label;
2722 static void keep_span(struct span *span)
2724 span->keep = true;
2725 span->ss->keep = true;
2728 static struct span *new_span(struct supersect *ss, bfd_vma start, bfd_vma size)
2730 struct span *span = vec_grow(&ss->spans, 1);
2731 span->size = size;
2732 span->start = start;
2733 span->ss = ss;
2734 span->keep = true;
2735 span->new = false;
2736 span->patch = false;
2737 span->match = NULL;
2738 span->shift = 0;
2739 asymbol **symp = symbolp_scan(ss, span->start);
2740 if (symp != NULL) {
2741 span->symbol = *symp;
2742 span->label = label_lookup(ss->parent, span->symbol);
2743 } else {
2744 span->symbol = NULL;
2745 const char *label = label_lookup(ss->parent, ss->symbol);
2746 if (span->start != 0) {
2747 char *buf;
2748 assert(asprintf(&buf, "%s<span:%lx>", label,
2749 (unsigned long)span->start) >= 0);
2750 span->label = buf;
2751 } else {
2752 span->label = label;
2755 span->orig_label = span->label;
2756 return span;
2759 static void initialize_string_spans(struct supersect *ss)
2761 const char *str;
2762 for (str = ss->contents.data;
2763 (void *)str < ss->contents.data + ss->contents.size;) {
2764 bfd_vma start = (unsigned long)str -
2765 (unsigned long)ss->contents.data;
2766 bfd_vma size = strlen(str) + 1;
2767 while ((start + size) % (1 << ss->alignment) != 0 &&
2768 start + size < ss->contents.size) {
2769 if (str[size] != '\0')
2770 DIE;
2771 size++;
2773 new_span(ss, start, size);
2774 str += size;
2778 static int compare_ulongs(const void *va, const void *vb)
2780 const unsigned long *a = va, *b = vb;
2781 return *a - *b;
2784 static void initialize_table_spans(struct superbfd *sbfd,
2785 struct table_section *s)
2787 asection *isection = bfd_get_section_by_name(sbfd->abfd, s->sect);
2788 if (isection == NULL)
2789 return;
2790 asection *other_sect = NULL;
2791 if (s->other_sect != NULL)
2792 other_sect = bfd_get_section_by_name(sbfd->abfd, s->other_sect);
2794 struct supersect *ss = fetch_supersect(sbfd, isection);
2795 if (ss->alignment < ffs(s->entry_align) - 1)
2796 ss->alignment = ffs(s->entry_align) - 1;
2798 struct supersect *other_ss = NULL;
2799 if (other_sect != NULL)
2800 other_ss = fetch_supersect(sbfd, other_sect);
2802 struct ulong_vec offsets;
2803 vec_init(&offsets);
2805 void *entry;
2806 for (entry = ss->contents.data;
2807 entry < ss->contents.data + ss->contents.size;
2808 entry += s->entry_size) {
2809 new_span(ss, addr_offset(ss, entry), s->entry_size);
2811 if (other_sect != NULL) {
2812 asymbol *sym;
2813 bfd_vma offset = read_reloc(ss, entry + s->other_offset,
2814 sizeof(void *), &sym);
2815 if (sym->section == other_sect) {
2816 assert(offset >= 0 &&
2817 offset < other_ss->contents.size);
2818 *vec_grow(&offsets, 1) = offset;
2823 if (other_sect == NULL)
2824 return;
2826 qsort(offsets.data, offsets.size, sizeof(*offsets.data),
2827 compare_ulongs);
2828 *vec_grow(&offsets, 1) = other_ss->contents.size;
2830 unsigned long *off;
2831 for (off = offsets.data; off < offsets.data + offsets.size - 1; off++) {
2832 if (*off != *(off + 1))
2833 new_span(other_ss, *off, *(off + 1) - *off);
2837 static void initialize_table_section_spans(struct superbfd *sbfd)
2839 struct supersect *tables_ss =
2840 fetch_supersect(offsets_sbfd,
2841 bfd_get_section_by_name(offsets_sbfd->abfd,
2842 ".ksplice_table_sections"));
2843 const struct table_section *ts;
2844 struct table_section s;
2845 for (ts = tables_ss->contents.data;
2846 (void *)ts < tables_ss->contents.data + tables_ss->contents.size;
2847 ts++) {
2848 s = *ts;
2849 s.sect = read_string(tables_ss, &ts->sect);
2850 s.other_sect = read_string(tables_ss, &ts->other_sect);
2851 initialize_table_spans(sbfd, &s);
2855 static void initialize_spans(struct superbfd *sbfd)
2857 if (mode("keep"))
2858 initialize_table_section_spans(sbfd);
2860 asection *sect;
2861 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2862 if (is_table_section(sect->name, true) && mode("keep"))
2863 continue;
2865 struct supersect *ss = fetch_supersect(sbfd, sect);
2866 if (ss->type == SS_TYPE_STRING)
2867 initialize_string_spans(ss);
2868 else if (!mode("keep") || ss->type != SS_TYPE_EXPORT)
2869 new_span(ss, 0, ss->contents.size);
2873 struct span *reloc_target_span(struct supersect *ss, arelent *reloc)
2875 asymbol *sym_ptr = *reloc->sym_ptr_ptr;
2876 if (bfd_is_const_section(sym_ptr->section))
2877 return NULL;
2879 bfd_vma addend = get_reloc_offset(ss, reloc, true) + sym_ptr->value;
2880 struct supersect *sym_ss =
2881 fetch_supersect(ss->parent, sym_ptr->section);
2882 struct span *span, *target_span = sym_ss->spans.data;
2883 for (span = sym_ss->spans.data;
2884 span < sym_ss->spans.data + sym_ss->spans.size; span++) {
2885 if (addend >= span->start && addend < span->start + span->size)
2886 target_span = span;
2888 return target_span;
2891 struct span *find_span(struct supersect *ss, bfd_size_type address)
2893 struct span *span;
2894 for (span = ss->spans.data; span < ss->spans.data + ss->spans.size;
2895 span++) {
2896 if (address >= span->start &&
2897 address < span->start + span->size)
2898 return span;
2900 /* Deal with empty BSS sections */
2901 if (ss->contents.size == 0 && ss->spans.size > 0)
2902 return ss->spans.data;
2903 return NULL;
2906 void compute_span_shifts(struct superbfd *sbfd)
2908 asection *sect;
2909 struct span *span;
2910 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2911 struct supersect *ss = fetch_supersect(sbfd, sect);
2912 if (!ss->keep)
2913 continue;
2914 bfd_size_type offset = 0;
2915 for (span = ss->spans.data;
2916 span < ss->spans.data + ss->spans.size; span++) {
2917 if (!span->keep)
2918 continue;
2919 span->shift = offset - span->start;
2920 offset += span->size;
2925 void remove_unkept_spans(struct superbfd *sbfd)
2927 asection *sect;
2928 struct span *span;
2929 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2930 struct supersect *ss = fetch_supersect(sbfd, sect);
2931 delete_obsolete_relocs(ss);
2932 struct arelentp_vec orig_relocs;
2933 vec_move(&orig_relocs, &ss->relocs);
2934 arelent **relocp, *reloc;
2935 for (relocp = orig_relocs.data;
2936 relocp < orig_relocs.data + orig_relocs.size; relocp++) {
2937 reloc = *relocp;
2938 asymbol *sym = *reloc->sym_ptr_ptr;
2939 span = reloc_target_span(ss, reloc);
2940 if ((span != NULL && span->keep && span->shift == 0) ||
2941 bfd_is_const_section(sym->section)) {
2942 *vec_grow(&ss->relocs, 1) = reloc;
2943 continue;
2945 struct supersect *sym_ss =
2946 fetch_supersect(sbfd, sym->section);
2947 if (span != NULL && (sym->flags & BSF_SECTION_SYM) == 0
2948 && find_span(sym_ss, sym->value) != span) {
2949 err(sbfd, "Spans for symbol %s and relocation "
2950 "target do not match in sect %s\n",
2951 sym->name, sym_ss->name);
2952 DIE;
2954 if (span != NULL && span->keep) {
2955 arelent *new_reloc = malloc(sizeof(*new_reloc));
2956 *new_reloc = *reloc;
2957 new_reloc->addend =
2958 get_reloc_offset(ss, reloc, false);
2959 new_reloc->addend += span->shift;
2960 *vec_grow(&ss->new_relocs, 1) = new_reloc;
2965 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2966 struct supersect *ss = fetch_supersect(sbfd, sect), orig_ss;
2967 if (!ss->keep)
2968 continue;
2969 supersect_move(&orig_ss, ss);
2970 vec_init(&ss->spans);
2971 for (span = orig_ss.spans.data;
2972 span < orig_ss.spans.data + orig_ss.spans.size; span++) {
2973 if (!span->keep)
2974 continue;
2975 struct span *new_span = vec_grow(&ss->spans, 1);
2976 *new_span = *span;
2977 new_span->start = span->start + span->shift;
2978 new_span->shift = 0;
2979 sect_copy(ss, sect_do_grow(ss, 1, span->size, 1),
2980 &orig_ss, orig_ss.contents.data + span->start,
2981 span->size);
2986 static void init_objmanip_superbfd(struct superbfd *sbfd)
2988 init_label_map(sbfd);
2989 initialize_supersect_types(sbfd);
2990 initialize_spans(sbfd);
2993 void mangle_section_name(struct superbfd *sbfd, const char *name)
2995 asection *sect = bfd_get_section_by_name(sbfd->abfd, name);
2996 if (sect == NULL)
2997 return;
2998 struct supersect *ss = fetch_supersect(sbfd, sect);
2999 char *buf;
3000 assert(asprintf(&buf, ".ksplice_pre.%s", ss->name) >= 0);
3001 ss->name = buf;