Fill in the string fields of struct table_section in get_table_section.
[ksplice.git] / objmanip.c
blob17a51567e0a87f2a46dd1a8d2ec9dece2cda59f4
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 Ksplice, Inc.
5 * Authors: Jeff Arnold, Anders Kaseorg, Tim Abbott
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License, version 2.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
18 * 02110-1301, USA.
21 /* objmanip performs various object file manipulations for Ksplice. Its first
22 * two arguments are always an input object file and an output object file.
24 * - keep-primary: "objmanip <post.o> <out.o> keep-primary <pre.o> <kid>"
26 * This mode prepares the object file to be installed as a ksplice update. The
27 * kid argument is the ksplice id string for the ksplice update being built.
29 * - keep-helper: "objmanip <pre.o> <out.o> keep-helper"
31 * This mode prepares the object file to be used for run-pre matching. This
32 * involves replacing all ELF relocations with ksplice relocations and
33 * writing ksplice_section structures for each ELF text or data section.
35 * - rmsyms mode: "objmanip <in.o> <out.o> rmsyms
37 * In this mode, any ELF relocations involving the list of symbol names given on
38 * standard input are replaced with ksplice relocations. This is used only
39 * for KSPLICE_STANDALONE.
41 * - finalize mode: "objmanip <in.o> <out.o> finalize"
43 * In this mode, any ELF relocations to undefined symbols are replaced with
44 * ksplice relocations.
47 /* Always define KSPLICE_STANDALONE, even if you're using integrated Ksplice.
48 objmanip won't compile without it. */
49 #define KSPLICE_STANDALONE
51 #define _GNU_SOURCE
52 #include "objcommon.h"
53 #include "kmodsrc/ksplice.h"
54 #include "kmodsrc/offsets.h"
55 #include "ksplice-patch/ksplice-patch.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 DECLARE_VEC_TYPE(const char *, str_vec);
70 DECLARE_VEC_TYPE(unsigned long, ulong_vec);
72 #define bool_init(b) *(b) = false
73 DEFINE_HASH_TYPE(bool, bool_hash, bool_hash_init, bool_hash_free,
74 bool_hash_lookup, bool_init);
76 #define ulong_init(x) *(x) = 0
77 DEFINE_HASH_TYPE(unsigned long, ulong_hash, ulong_hash_init,
78 ulong_hash_free, ulong_hash_lookup, ulong_init);
80 void do_keep_primary(struct superbfd *isbfd, const char *pre);
81 void do_keep_helper(struct superbfd *isbfd);
82 void do_finalize(struct superbfd *isbfd);
83 void do_rmsyms(struct superbfd *isbfd);
85 bool relocs_equal(struct supersect *old_src_ss, struct supersect *new_src_ss,
86 arelent *old_reloc, arelent *new_reloc);
87 bfd_vma non_dst_mask(struct supersect *ss, arelent *reloc);
88 bool all_relocs_equal(struct span *old_span, struct span *new_span);
89 static bool part_of_reloc(struct supersect *ss, unsigned long addr);
90 static bool nonrelocs_equal(struct span *old_span, struct span *new_span);
91 static void handle_section_symbol_renames(struct superbfd *oldsbfd,
92 struct superbfd *newsbfd);
94 enum supersect_type supersect_type(struct supersect *ss);
95 void initialize_supersect_types(struct superbfd *sbfd);
96 static void initialize_spans(struct superbfd *sbfd);
97 static void initialize_string_spans(struct supersect *ss);
98 static void initialize_table_spans(struct superbfd *sbfd,
99 struct table_section *s);
100 static void initialize_table_section_spans(struct superbfd *sbfd);
101 static void initialize_ksplice_call_spans(struct supersect *ss);
102 struct span *reloc_target_span(struct supersect *ss, arelent *reloc);
103 struct span *find_span(struct supersect *ss, bfd_size_type address);
104 void remove_unkept_spans(struct superbfd *sbfd);
105 void compute_span_shifts(struct superbfd *sbfd);
106 static struct span *new_span(struct supersect *ss, bfd_vma start, bfd_vma size);
107 bool is_table_section(const char *name, bool consider_other);
108 const struct table_section *get_table_section(const char *name);
109 void mangle_section_name(struct superbfd *sbfd, const char *name);
111 void rm_relocs(struct superbfd *isbfd);
112 void rm_some_relocs(struct supersect *ss);
113 void write_ksplice_reloc(struct supersect *ss, arelent *orig_reloc);
114 static void write_ksplice_reloc_howto(struct supersect *ss, const
115 struct ksplice_reloc_howto *const *addr,
116 reloc_howto_type *howto,
117 enum ksplice_reloc_howto_type type);
118 static void write_ksplice_date_reloc(struct supersect *ss, unsigned long offset,
119 const char *str,
120 enum ksplice_reloc_howto_type type);
121 static void write_ksplice_patch_reloc(struct supersect *ss,
122 const char *sectname, unsigned long *addr,
123 bfd_size_type size, const char *label,
124 long addend);
125 static void write_ksplice_nonreloc_howto(struct supersect *ss,
126 const struct ksplice_reloc_howto
127 *const *addr,
128 enum ksplice_reloc_howto_type type,
129 int size);
130 static void write_date_relocs(struct superbfd *sbfd, const char *str,
131 enum ksplice_reloc_howto_type type);
132 static void write_table_relocs(struct superbfd *sbfd, const char *sectname,
133 enum ksplice_reloc_howto_type type);
134 static void write_ksplice_table_reloc(struct supersect *ss,
135 unsigned long address,
136 const char *label,
137 enum ksplice_reloc_howto_type type);
138 void load_ksplice_symbol_offsets(struct superbfd *sbfd);
139 void write_canary(struct supersect *ss, int offset, bfd_size_type size,
140 bfd_vma dst_mask);
141 static void write_ksplice_section(struct span *span);
142 void write_ksplice_patch(struct superbfd *sbfd, struct span *span);
143 void *write_patch_storage(struct supersect *ss, struct ksplice_patch *patch,
144 size_t size, struct supersect **data_ssp);
145 void write_ksplice_deleted_patch(struct superbfd *sbfd, const char *name,
146 const char *label, const char *sectname);
147 static void write_bugline_patches(struct superbfd *sbfd);
148 asymbol **make_undefined_symbolp(struct superbfd *sbfd, const char *name);
149 void filter_table_sections(struct superbfd *isbfd);
150 void filter_table_section(struct superbfd *sbfd, const struct table_section *s);
151 void keep_referenced_sections(struct superbfd *sbfd);
152 void mark_precallable_spans(struct superbfd *sbfd);
153 bfd_boolean copy_object(bfd *ibfd, bfd *obfd);
154 void setup_section(bfd *ibfd, asection *isection, void *obfdarg);
155 static void setup_new_section(bfd *obfd, struct supersect *ss);
156 static void write_section(bfd *obfd, asection *osection, void *arg);
157 static void delete_obsolete_relocs(struct supersect *ss);
158 void mark_symbols_used_in_relocations(bfd *abfd, asection *isection,
159 void *ignored);
160 static void ss_mark_symbols_used_in_relocations(struct supersect *ss);
161 void filter_symbols(bfd *ibfd, bfd *obfd, struct asymbolp_vec *osyms,
162 struct asymbolp_vec *isyms);
163 static bool deleted_table_section_symbol(bfd *abfd, asymbol *sym);
164 void read_str_set(struct str_vec *strs);
165 bool str_in_set(const char *str, const struct str_vec *strs);
166 struct supersect *__attribute((format(printf, 2, 3)))
167 make_section(struct superbfd *sbfd, const char *fmt, ...);
168 void __attribute__((format(printf, 3, 4)))
169 write_string(struct supersect *ss, const char **addr, const char *fmt, ...);
170 void write_ksplice_export(struct superbfd *sbfd, struct span *span, bool del);
171 void write_reloc(struct supersect *ss, const void *addr, asymbol **symp,
172 bfd_vma offset);
173 arelent *create_reloc(struct supersect *ss, const void *addr, asymbol **symp,
174 bfd_vma offset);
175 static void foreach_symbol_pair(struct superbfd *oldsbfd, struct superbfd *newsbfd,
176 void (*fn)(struct span *old_span,
177 asymbol *oldsym,
178 struct span *new_span,
179 asymbol *newsym));
180 static void check_global_symbols(struct span *old_span, asymbol *oldsym,
181 struct span *new_span, asymbol *newsym);
182 static void match_global_symbols(struct span *old_span, asymbol *oldsym,
183 struct span *new_span, asymbol *newsym);
184 static void match_symbol_spans(struct span *old_span, asymbol *oldsym,
185 struct span *new_span, asymbol *newsym);
187 static void foreach_span_pair(struct superbfd *oldsbfd,
188 struct superbfd *newsbfd,
189 void (*fn)(struct span *old_span,
190 struct span *new_span));
191 static void match_spans_by_label(struct span *old_span, struct span *new_span);
192 static void match_string_spans(struct span *old_span, struct span *new_span);
193 static void mark_new_spans(struct superbfd *sbfd);
194 static void handle_deleted_spans(struct superbfd *oldsbfd,
195 struct superbfd *newsbfd);
196 static void compare_matched_spans(struct superbfd *newsbfd);
197 static void compare_spans(struct span *old_span, struct span *new_span);
198 static void update_nonzero_offsets(struct superbfd *sbfd);
199 static void handle_nonzero_offset_relocs(struct supersect *ss);
200 static void keep_span(struct span *span);
202 static void init_objmanip_superbfd(struct superbfd *sbfd);
203 static const char *label_lookup(struct superbfd *sbfd, asymbol *sym);
204 static void label_map_set(struct superbfd *sbfd, const char *oldlabel,
205 const char *label);
206 static void print_label_changes(struct superbfd *sbfd);
207 static void init_label_map(struct superbfd *sbfd);
208 static void change_initial_label(struct span *span, const char *label);
209 static asymbol **symbolp_scan(struct supersect *ss, bfd_vma value);
210 static void init_csyms(struct superbfd *sbfd);
211 static void init_callers(struct superbfd *sbfd);
212 static asymbol *canonical_symbol(struct superbfd *sbfd, asymbol *sym);
213 static asymbol **canonical_symbolp(struct superbfd *sbfd, asymbol *sym);
214 static char *static_local_symbol(struct superbfd *sbfd, asymbol *sym);
215 static char *symbol_label(struct superbfd *sbfd, asymbol *sym);
217 int verbose = 0;
218 #define debug_(sbfd, level, fmt, ...) \
219 do { \
220 if (verbose >= (level)) \
221 printf("%s: " fmt, (sbfd)->abfd->filename, \
222 ## __VA_ARGS__); \
223 } while (0)
224 #define debug0(sbfd, fmt, ...) debug_(sbfd, 0, fmt, ## __VA_ARGS__)
225 #define debug1(sbfd, fmt, ...) debug_(sbfd, 1, fmt, ## __VA_ARGS__)
226 #define err(sbfd, fmt, ...) \
227 do { \
228 fprintf(stderr, "%s: " fmt, (sbfd)->abfd->filename, \
229 ## __VA_ARGS__); \
230 } while (0)
232 struct str_vec delsects, rmsyms;
233 bool changed;
235 struct ksplice_config *config;
237 const char *modestr, *kid, *finalize_target = NULL;
238 bool write_output = true;
240 struct superbfd *offsets_sbfd = NULL;
242 #define mode(str) starts_with(modestr, str)
244 DECLARE_VEC_TYPE(unsigned long, addr_vec);
245 DEFINE_HASH_TYPE(struct addr_vec, addr_vec_hash,
246 addr_vec_hash_init, addr_vec_hash_free, addr_vec_hash_lookup,
247 vec_init);
248 struct addr_vec_hash system_map;
250 struct bool_hash system_map_written;
251 struct ulong_hash ksplice_symbol_offset;
252 struct ulong_hash ksplice_howto_offset;
253 struct ulong_hash ksplice_string_offset;
255 void load_system_map()
257 const char *config_dir = getenv("KSPLICE_CONFIG_DIR");
258 assert(config_dir);
259 FILE *fp = fopen(strprintf("%s/System.map", config_dir), "r");
260 assert(fp);
261 addr_vec_hash_init(&system_map);
262 unsigned long addr;
263 char type;
264 char *sym;
265 while (fscanf(fp, "%lx %c %as\n", &addr, &type, &sym) == 3)
266 *vec_grow(addr_vec_hash_lookup(&system_map, sym, TRUE),
267 1) = addr;
268 fclose(fp);
271 void load_ksplice_symbol_offsets(struct superbfd *sbfd)
273 asection *sect = bfd_get_section_by_name(sbfd->abfd,
274 ".ksplice_symbols");
275 if (sect == NULL)
276 return;
277 struct supersect *ss = fetch_supersect(sbfd, sect);
279 struct ksplice_symbol *ksym;
280 for (ksym = ss->contents.data;
281 (void *)ksym < ss->contents.data + ss->contents.size; ksym++) {
282 const char *label = read_string(ss, &ksym->label);
283 unsigned long *ksymbol_offp =
284 ulong_hash_lookup(&ksplice_symbol_offset, label, TRUE);
285 *ksymbol_offp = addr_offset(ss, ksym);
289 void load_offsets()
291 char *kmodsrc = getenv("KSPLICE_KMODSRC");
292 assert(kmodsrc != NULL);
293 bfd *offsets_bfd = bfd_openr(strprintf("%s/offsets.o", kmodsrc), NULL);
294 assert(offsets_bfd != NULL);
295 char **matching;
296 assert(bfd_check_format_matches(offsets_bfd, bfd_object, &matching));
297 offsets_sbfd = fetch_superbfd(offsets_bfd);
299 asection *config_sect = bfd_get_section_by_name(offsets_sbfd->abfd,
300 ".ksplice_config");
301 struct supersect *config_ss =
302 fetch_supersect(offsets_sbfd, config_sect);
304 config = config_ss->contents.data;
307 void load_options(struct superbfd *sbfd)
309 asection *sect = bfd_get_section_by_name(sbfd->abfd,
310 ".ksplice_options");
311 if (sect == NULL)
312 return;
313 struct supersect *ss = fetch_supersect(sbfd, sect);
314 const struct ksplice_option *opt;
315 for (opt = ss->contents.data;
316 (void *)opt < ss->contents.data + ss->contents.size; opt++) {
317 if (opt->type == KSPLICE_OPTION_ASSUME_RODATA) {
318 arelent *reloc = find_reloc(ss, &opt->target);
319 struct span *span = reloc_target_span(ss, reloc);
320 assert(span != NULL);
321 assert(span->ss->type == SS_TYPE_DATA);
322 assert(span->start == 0 &&
323 span->size == span->ss->contents.size);
324 span->ss->type = SS_TYPE_RODATA;
325 break;
326 } else {
327 err(sbfd, "Unrecognized Ksplice option %d\n",
328 opt->type);
329 DIE;
334 bool matchable_data_section(struct supersect *ss)
336 if (ss->type == SS_TYPE_STRING)
337 return true;
338 if (ss->type == SS_TYPE_RODATA)
339 return true;
340 if (ss->type == SS_TYPE_DATA && ss->relocs.size != 0)
341 return true;
342 if (ss->type == SS_TYPE_EXPORT)
343 return true;
344 return false;
347 bool unchangeable_section(struct supersect *ss)
349 if (ss->type == SS_TYPE_DATA)
350 return true;
351 if (ss->type == SS_TYPE_IGNORED && !starts_with(ss->name, ".debug") &&
352 strcmp(ss->name, "__ksymtab_strings") != 0)
353 return true;
354 return false;
357 int main(int argc, char *argv[])
359 if (getenv("KSPLICE_VERBOSE") != NULL)
360 verbose = atoi(getenv("KSPLICE_VERBOSE"));
362 bfd_init();
363 bfd *ibfd = bfd_openr(argv[1], NULL);
364 assert(ibfd);
366 char **matching;
367 assert(bfd_check_format_matches(ibfd, bfd_object, &matching));
369 const char *output_target = bfd_get_target(ibfd);
371 load_system_map();
372 load_offsets();
374 bool_hash_init(&system_map_written);
375 ulong_hash_init(&ksplice_symbol_offset);
376 ulong_hash_init(&ksplice_howto_offset);
377 ulong_hash_init(&ksplice_string_offset);
379 struct superbfd *isbfd = fetch_superbfd(ibfd);
381 modestr = argv[3];
382 if (mode("finalize"))
383 finalize_target = argv[4];
384 init_objmanip_superbfd(isbfd);
385 if (mode("keep-primary")) {
386 kid = argv[5];
387 do_keep_primary(isbfd, argv[4]);
388 } else if (mode("keep-helper")) {
389 do_keep_helper(isbfd);
390 } else if (mode("finalize")) {
391 do_finalize(isbfd);
392 } else if (mode("rmsyms")) {
393 do_rmsyms(isbfd);
396 if (write_output) {
397 bfd *obfd = bfd_openw(argv[2], output_target);
398 assert(obfd);
399 copy_object(ibfd, obfd);
400 assert(bfd_close(obfd));
403 if (offsets_sbfd != NULL)
404 assert(bfd_close(offsets_sbfd->abfd));
405 assert(bfd_close(ibfd));
406 return EXIT_SUCCESS;
409 void do_keep_primary(struct superbfd *isbfd, const char *pre)
411 struct bfd *prebfd = bfd_openr(pre, NULL);
412 assert(prebfd != NULL);
413 char **matching;
414 assert(bfd_check_format_matches(prebfd, bfd_object, &matching));
416 struct superbfd *presbfd = fetch_superbfd(prebfd);
417 init_objmanip_superbfd(presbfd);
419 foreach_symbol_pair(presbfd, isbfd, match_global_symbols);
420 debug1(isbfd, "Matched global\n");
421 foreach_span_pair(presbfd, isbfd, match_string_spans);
422 debug1(isbfd, "Matched string spans\n");
423 foreach_symbol_pair(presbfd, isbfd, match_symbol_spans);
424 debug1(isbfd, "Matched by name\n");
425 foreach_span_pair(presbfd, isbfd, match_spans_by_label);
426 debug1(isbfd, "Matched by label\n");
428 do {
429 changed = false;
430 compare_matched_spans(isbfd);
431 update_nonzero_offsets(isbfd);
432 mark_new_spans(isbfd);
433 } while (changed);
434 vec_init(&delsects);
436 foreach_symbol_pair(presbfd, isbfd, check_global_symbols);
438 handle_deleted_spans(presbfd, isbfd);
439 handle_section_symbol_renames(presbfd, isbfd);
441 assert(bfd_close(prebfd));
443 do {
444 changed = false;
445 mark_precallable_spans(isbfd);
446 } while (changed);
448 asection *sect;
449 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
450 struct supersect *ss = fetch_supersect(isbfd, sect);
451 ss->keep = false;
452 struct span *span;
453 for (span = ss->spans.data;
454 span < ss->spans.data + ss->spans.size; span++) {
455 if (starts_with(ss->name, ".ksplice_options"))
456 span->keep = false;
457 else if (span->new || span->patch || span->datapatch)
458 keep_span(span);
459 else
460 span->keep = false;
461 if (span->patch && span->precallable) {
462 err(isbfd, "Patched span %s can be reached "
463 "by a precall function\n", span->label);
464 DIE;
469 print_label_changes(isbfd);
471 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
472 struct supersect *ss = fetch_supersect(isbfd, sect);
473 struct span *span;
474 for (span = ss->spans.data;
475 span < ss->spans.data + ss->spans.size; span++) {
476 if (span->patch || span->bugpatch || span->datapatch)
477 debug0(isbfd, "Patching span %s\n",
478 span->label);
482 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
483 struct supersect *ss = fetch_supersect(isbfd, sect);
484 struct span *span;
485 for (span = ss->spans.data;
486 span < ss->spans.data + ss->spans.size; span++) {
487 if (span->new)
488 debug0(isbfd, "New span %s\n", span->label);
492 write_output = false;
493 const char **sectname;
494 for (sectname = delsects.data;
495 sectname < delsects.data + delsects.size; sectname++) {
496 write_output = true;
497 debug0(isbfd, "Deleted section: %s\n", *sectname);
500 filter_table_sections(isbfd);
502 compute_span_shifts(isbfd);
504 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
505 struct supersect *ss = fetch_supersect(isbfd, sect);
506 if (ss->type == SS_TYPE_KSPLICE_CALL)
507 continue;
508 struct span *span;
509 for (span = ss->spans.data;
510 span < ss->spans.data + ss->spans.size; span++) {
511 if (span->keep)
512 write_output = true;
513 if (span->patch || span->new || span->datapatch)
514 write_ksplice_section(span);
515 if (span->patch || span->datapatch)
516 write_ksplice_patch(isbfd, span);
517 if (ss->type == SS_TYPE_EXPORT && span->new)
518 write_ksplice_export(isbfd, span, false);
522 write_bugline_patches(isbfd);
523 rm_relocs(isbfd);
524 remove_unkept_spans(isbfd);
527 void do_keep_helper(struct superbfd *isbfd)
529 asection *sect;
530 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
531 struct supersect *ss = fetch_supersect(isbfd, sect);
532 ss->keep = false;
533 struct span *span;
534 for (span = ss->spans.data;
535 span < ss->spans.data + ss->spans.size; span++) {
536 span->keep = false;
537 if (ss->type == SS_TYPE_TEXT &&
538 !starts_with(ss->name, ".fixup"))
539 keep_span(span);
540 if (ss->type == SS_TYPE_EXPORT)
541 keep_span(span);
545 asymbol **symp;
546 for (symp = isbfd->syms.data;
547 symp < isbfd->syms.data + isbfd->syms.size; symp++) {
548 asymbol *sym = *symp;
549 if (!bfd_is_const_section(sym->section) &&
550 (sym->flags & BSF_GLOBAL) != 0) {
551 struct supersect *sym_ss =
552 fetch_supersect(isbfd, sym->section);
553 if (sym->value == sym_ss->contents.size)
554 continue;
555 struct span *span = find_span(sym_ss, sym->value);
556 assert(span != NULL);
557 if (sym_ss->type != SS_TYPE_IGNORED)
558 keep_span(span);
562 do {
563 changed = false;
564 keep_referenced_sections(isbfd);
565 } while (changed);
567 filter_table_sections(isbfd);
568 compute_span_shifts(isbfd);
570 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
571 struct supersect *ss = fetch_supersect(isbfd, sect);
572 asymbol *sym = canonical_symbol(isbfd, sect->symbol);
573 if (sym == NULL)
574 continue;
575 if ((sym->flags & BSF_WEAK) != 0)
576 continue;
577 if (bfd_get_section_size(sect) == 0)
578 continue;
579 if (!ss->keep)
580 continue;
581 if (ss->type != SS_TYPE_TEXT && !matchable_data_section(ss))
582 continue;
584 struct span *span;
585 for (span = ss->spans.data;
586 span < ss->spans.data + ss->spans.size; span++) {
587 if (span->keep)
588 write_ksplice_section(span);
592 write_table_relocs(isbfd, "__bug_table", KSPLICE_HOWTO_BUG);
593 write_table_relocs(isbfd, "__ex_table", KSPLICE_HOWTO_EXTABLE);
594 rm_relocs(isbfd);
595 remove_unkept_spans(isbfd);
597 mangle_section_name(isbfd, "__markers");
598 mangle_section_name(isbfd, "__ex_table");
599 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
600 struct supersect *ss = fetch_supersect(isbfd, sect);
601 if (ss->type == SS_TYPE_EXPORT)
602 mangle_section_name(isbfd, ss->name);
606 void do_finalize(struct superbfd *isbfd)
608 load_ksplice_symbol_offsets(isbfd);
609 asection *sect;
610 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
611 struct supersect *ss = fetch_supersect(isbfd, sect);
612 if (ss->type == SS_TYPE_EXIT) {
613 struct span *span;
614 for (span = ss->spans.data;
615 span < ss->spans.data + ss->spans.size; span++)
616 span->keep = false;
617 ss->keep = false;
620 write_date_relocs(isbfd, "<{DATE...}>", KSPLICE_HOWTO_DATE);
621 write_date_relocs(isbfd, "<{TIME}>", KSPLICE_HOWTO_TIME);
622 rm_relocs(isbfd);
625 void do_rmsyms(struct superbfd *isbfd)
627 read_str_set(&rmsyms);
628 rm_relocs(isbfd);
631 void match_spans(struct span *old_span, struct span *new_span)
633 struct superbfd *sbfd = new_span->ss->parent;
634 if (old_span->match == new_span && new_span->match == old_span)
635 return;
636 if (old_span->match != NULL) {
637 err(sbfd, "Matching conflict: old %s: %s != %s\n",
638 old_span->label, old_span->match->label, new_span->label);
639 DIE;
641 if (new_span->match != NULL) {
642 err(sbfd, "Matching conflict: new %s: %s != %s\n",
643 new_span->label, new_span->match->label, old_span->label);
644 DIE;
646 old_span->match = new_span;
647 new_span->match = old_span;
648 debug1(sbfd, "Matched old %s to new %s\n", old_span->label,
649 new_span->label);
650 if (old_span->ss->type != new_span->ss->type &&
651 old_span->ss->type == new_span->ss->orig_type)
652 old_span->ss->type = new_span->ss->type;
655 static void match_global_symbols(struct span *old_span, asymbol *oldsym,
656 struct span *new_span, asymbol *newsym)
658 if ((oldsym->flags & BSF_GLOBAL) == 0 ||
659 (newsym->flags & BSF_GLOBAL) == 0)
660 return;
661 match_spans(old_span, new_span);
664 static void check_global_symbols(struct span *old_span, asymbol *oldsym,
665 struct span *new_span, asymbol *newsym)
667 if ((oldsym->flags & BSF_GLOBAL) == 0 ||
668 (newsym->flags & BSF_GLOBAL) == 0)
669 return;
670 if (old_span->ss->type == SS_TYPE_IGNORED)
671 return;
672 if (old_span->match != new_span || new_span->match != old_span) {
673 err(new_span->ss->parent, "Global symbol span mismatch: %s "
674 "%s/%s\n", oldsym->name, old_span->ss->name,
675 new_span->ss->name);
676 DIE;
680 static void foreach_symbol_pair(struct superbfd *oldsbfd, struct superbfd *newsbfd,
681 void (*fn)(struct span *old_span,
682 asymbol *oldsym,
683 struct span *new_span,
684 asymbol *newsym))
686 asymbol **oldsymp, **newsymp;
687 for (oldsymp = oldsbfd->syms.data;
688 oldsymp < oldsbfd->syms.data + oldsbfd->syms.size; oldsymp++) {
689 asymbol *oldsym = *oldsymp;
690 if (bfd_is_const_section(oldsym->section))
691 continue;
692 for (newsymp = newsbfd->syms.data;
693 newsymp < newsbfd->syms.data + newsbfd->syms.size;
694 newsymp++) {
695 asymbol *newsym = *newsymp;
696 if (bfd_is_const_section(newsym->section))
697 continue;
698 if (strcmp(oldsym->name, newsym->name) != 0)
699 continue;
701 struct supersect *old_ss =
702 fetch_supersect(oldsbfd, oldsym->section);
703 struct supersect *new_ss =
704 fetch_supersect(newsbfd, newsym->section);
705 if ((old_ss->type != new_ss->type &&
706 old_ss->type != new_ss->orig_type) ||
707 old_ss->type == SS_TYPE_SPECIAL ||
708 old_ss->type == SS_TYPE_EXPORT)
709 continue;
711 struct span *old_span =
712 find_span(old_ss, oldsym->value);
713 struct span *new_span =
714 find_span(new_ss, newsym->value);
715 if (old_span == NULL) {
716 err(oldsbfd, "Could not find span for %s\n",
717 oldsym->name);
718 DIE;
720 if (new_span == NULL) {
721 err(newsbfd, "Could not find span for %s\n",
722 newsym->name);
723 DIE;
725 fn(old_span, oldsym, new_span, newsym);
730 static void match_symbol_spans(struct span *old_span, asymbol *oldsym,
731 struct span *new_span, asymbol *newsym)
733 if ((oldsym->flags & BSF_DEBUGGING) != 0 ||
734 (newsym->flags & BSF_DEBUGGING) != 0)
735 return;
736 if (old_span->ss->type == SS_TYPE_SPECIAL)
737 return;
738 if (static_local_symbol(old_span->ss->parent, oldsym) ||
739 static_local_symbol(new_span->ss->parent, newsym))
740 return;
741 if (old_span->match == NULL && new_span->match == NULL)
742 match_spans(old_span, new_span);
745 static void match_spans_by_label(struct span *old_span, struct span *new_span)
747 if (old_span->ss->type == SS_TYPE_STRING)
748 return;
749 if (strcmp(old_span->label, new_span->label) == 0)
750 match_spans(old_span, new_span);
753 static void match_string_spans(struct span *old_span, struct span *new_span)
755 if (old_span->ss->type != SS_TYPE_STRING ||
756 strcmp(old_span->ss->name, new_span->ss->name) != 0)
757 return;
758 if (strcmp((char *)old_span->ss->contents.data + old_span->start,
759 (char *)new_span->ss->contents.data + new_span->start) == 0)
760 match_spans(old_span, new_span);
763 static void foreach_span_pair(struct superbfd *oldsbfd,
764 struct superbfd *newsbfd,
765 void (*fn)(struct span *old_span,
766 struct span *new_span))
768 asection *oldsect, *newsect;
769 struct supersect *oldss, *newss;
770 struct span *old_span, *new_span;
771 for (newsect = newsbfd->abfd->sections; newsect != NULL;
772 newsect = newsect->next) {
773 newss = fetch_supersect(newsbfd, newsect);
774 if (newss->type == SS_TYPE_SPECIAL)
775 continue;
776 for (oldsect = oldsbfd->abfd->sections; oldsect != NULL;
777 oldsect = oldsect->next) {
778 oldss = fetch_supersect(oldsbfd, oldsect);
779 if (oldss->type != newss->type)
780 continue;
781 for (new_span = newss->spans.data;
782 new_span < newss->spans.data + newss->spans.size;
783 new_span++) {
784 for (old_span = oldss->spans.data;
785 old_span < oldss->spans.data +
786 oldss->spans.size; old_span++)
787 fn(old_span, new_span);
793 static void mark_new_spans(struct superbfd *sbfd)
795 asection *sect;
796 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
797 struct supersect *ss = fetch_supersect(sbfd, sect);
798 if (ss->type == SS_TYPE_SPECIAL || ss->type == SS_TYPE_IGNORED)
799 continue;
800 struct span *span;
801 for (span = ss->spans.data;
802 span < ss->spans.data + ss->spans.size; span++) {
803 if (span->match == NULL && !span->bugpatch)
804 span->new = true;
809 static void handle_deleted_spans(struct superbfd *oldsbfd,
810 struct superbfd *newsbfd)
812 asection *sect;
813 for (sect = oldsbfd->abfd->sections; sect != NULL; sect = sect->next) {
814 struct supersect *ss = fetch_supersect(oldsbfd, sect);
815 struct span *span;
816 for (span = ss->spans.data;
817 span < ss->spans.data + ss->spans.size; span++) {
818 if (span->match != NULL)
819 continue;
820 if (ss->type == SS_TYPE_EXPORT) {
821 *vec_grow(&delsects, 1) = span->label;
822 write_ksplice_export(newsbfd, span, true);
823 } else if (ss->type == SS_TYPE_TEXT) {
824 *vec_grow(&delsects, 1) = span->label;
825 if (span->symbol == NULL)
826 DIE;
827 write_ksplice_deleted_patch
828 (newsbfd, span->symbol->name, span->label,
829 span->ss->name);
835 static void handle_nonzero_offset_relocs(struct supersect *ss)
837 struct span *address_span, *target_span;
838 arelent **relocp;
839 for (relocp = ss->relocs.data;
840 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
841 arelent *reloc = *relocp;
842 address_span = find_span(ss, reloc->address);
843 if (!address_span->new && !address_span->patch)
844 continue;
846 asymbol *sym = *reloc->sym_ptr_ptr;
847 if (bfd_is_const_section(sym->section))
848 continue;
849 bfd_vma offset = get_reloc_offset(ss, reloc, true);
850 target_span = reloc_target_span(ss, reloc);
851 if (sym->value + offset == target_span->start)
852 continue;
854 if (target_span->ss->type != SS_TYPE_TEXT)
855 continue;
856 if (target_span->patch)
857 continue;
859 target_span->patch = true;
860 changed = true;
861 debug1(ss->parent, "Changing %s because a relocation from sect "
862 "%s has a nonzero offset %lx+%lx into it\n",
863 target_span->label, ss->name, (unsigned long)sym->value,
864 (unsigned long)offset);
868 static void update_nonzero_offsets(struct superbfd *sbfd)
870 asection *sect;
871 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
872 struct supersect *ss = fetch_supersect(sbfd, sect);
873 if (ss->type == SS_TYPE_SPECIAL || ss->type == SS_TYPE_IGNORED)
874 continue;
875 handle_nonzero_offset_relocs(ss);
879 static void compare_spans(struct span *old_span, struct span *new_span)
881 struct superbfd *newsbfd = new_span->ss->parent;
883 bool nonrelocs_match = nonrelocs_equal(old_span, new_span);
884 bool relocs_match = all_relocs_equal(old_span, new_span);
885 if (nonrelocs_match && relocs_match)
886 return;
887 if (strcmp(old_span->ss->name, "__bug_table") == 0 &&
888 strcmp(new_span->ss->name, "__bug_table") == 0 && relocs_match) {
889 debug1(newsbfd, "Changing %s due to nonmatching line numbers\n",
890 new_span->label);
891 new_span->match = NULL;
892 old_span->match = NULL;
893 new_span->bugpatch = true;
894 return;
897 char *reason;
898 if (new_span->contents_size != old_span->contents_size)
899 reason = "differing sizes";
900 else if (!nonrelocs_match)
901 reason = "differing contents";
902 else
903 reason = "differing relocations";
905 if (new_span->ss->type == SS_TYPE_TEXT) {
906 if (new_span->patch)
907 return;
908 new_span->patch = true;
909 debug1(newsbfd, "Changing %s due to %s\n", new_span->label,
910 reason);
911 } else if (new_span->ss->type == SS_TYPE_RODATA &&
912 new_span->contents_size == old_span->contents_size) {
913 if (new_span->datapatch)
914 return;
915 new_span->datapatch = true;
916 debug1(newsbfd, "Changing %s in-place due to %s\n",
917 new_span->label, reason);
918 } else if (new_span->ss->type == SS_TYPE_STRING &&
919 old_span->ss->type == SS_TYPE_STRING && relocs_match &&
920 strcmp(new_span->ss->contents.data + new_span->start,
921 old_span->ss->contents.data + old_span->start) == 0) {
922 return;
923 } else {
924 debug1(newsbfd, "Unmatching %s and %s due to %s\n",
925 old_span->label, new_span->label, reason);
926 new_span->match = NULL;
927 old_span->match = NULL;
929 changed = true;
930 if (unchangeable_section(new_span->ss))
931 err(newsbfd, "warning: ignoring change to nonpatchable "
932 "section %s\n", new_span->ss->name);
935 static void compare_matched_spans(struct superbfd *newsbfd)
937 asection *sect;
938 for (sect = newsbfd->abfd->sections; sect != NULL; sect = sect->next) {
939 struct supersect *ss = fetch_supersect(newsbfd, sect);
940 struct span *span;
941 for (span = ss->spans.data;
942 span < ss->spans.data + ss->spans.size; span++) {
943 if (span->match == NULL)
944 continue;
945 compare_spans(span->match, span);
950 static void handle_section_symbol_renames(struct superbfd *oldsbfd,
951 struct superbfd *newsbfd)
953 asection *sect;
954 struct span *span;
955 for (sect = newsbfd->abfd->sections; sect != NULL; sect = sect->next) {
956 struct supersect *ss = fetch_supersect(newsbfd, sect);
957 for (span = ss->spans.data;
958 span < ss->spans.data + ss->spans.size; span++) {
959 if (span->match == NULL)
960 continue;
961 if (strcmp(span->label, span->match->label) == 0)
962 continue;
963 if (strcmp(span->orig_label, span->label) != 0 &&
964 strcmp(span->label, span->match->label) != 0)
965 DIE;
966 if (span->symbol != NULL)
967 label_map_set(newsbfd, span->label,
968 span->match->label);
969 span->label = span->match->label;
974 static bool part_of_reloc(struct supersect *ss, unsigned long addr)
976 arelent **relocp;
977 for (relocp = ss->relocs.data;
978 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
979 arelent *reloc = *relocp;
980 if (addr >= reloc->address &&
981 addr < reloc->address + reloc->howto->size)
982 return true;
984 return false;
987 static bool nonrelocs_equal(struct span *old_span, struct span *new_span)
989 int i;
990 struct supersect *old_ss = old_span->ss, *new_ss = new_span->ss;
991 if (old_span->contents_size != new_span->contents_size)
992 return false;
993 const unsigned char *old = old_ss->contents.data + old_span->start;
994 const unsigned char *new = new_ss->contents.data + new_span->start;
995 for (i = 0; i < old_span->contents_size; i++) {
996 if (old[i] != new[i] &&
997 !(part_of_reloc(old_ss, i + old_span->start) &&
998 part_of_reloc(new_ss, i + new_span->start)))
999 return false;
1001 return true;
1004 bool relocs_equal(struct supersect *old_src_ss, struct supersect *new_src_ss,
1005 arelent *old_reloc, arelent *new_reloc)
1007 struct superbfd *oldsbfd = old_src_ss->parent;
1008 struct superbfd *newsbfd = new_src_ss->parent;
1009 struct span *old_addr_span = find_span(old_src_ss, old_reloc->address);
1010 struct span *new_addr_span = find_span(new_src_ss, new_reloc->address);
1012 if (old_reloc->address - old_addr_span->start !=
1013 new_reloc->address - new_addr_span->start) {
1014 debug1(newsbfd, "Section %s/%s has reloc address mismatch at "
1015 "%lx\n", old_src_ss->name, new_src_ss->name,
1016 (unsigned long)old_reloc->address);
1017 return false;
1020 if (old_reloc->howto != new_reloc->howto) {
1021 debug1(newsbfd, "Section %s/%s has howto type mismatch at "
1022 "%lx\n", old_src_ss->name, new_src_ss->name,
1023 (unsigned long)old_reloc->address);
1024 return false;
1027 if (non_dst_mask(old_src_ss, old_reloc) !=
1028 non_dst_mask(new_src_ss, new_reloc)) {
1029 debug1(newsbfd, "Section %s/%s has contents mismatch at %lx\n",
1030 old_src_ss->name, new_src_ss->name,
1031 (unsigned long)old_reloc->address);
1032 return false;
1035 asymbol *old_sym = *old_reloc->sym_ptr_ptr;
1036 asymbol *new_sym = *new_reloc->sym_ptr_ptr;
1037 asection *old_sect = old_sym->section;
1038 asection *new_sect = new_sym->section;
1040 bfd_vma old_offset = get_reloc_offset(old_src_ss, old_reloc, true);
1041 bfd_vma new_offset = get_reloc_offset(new_src_ss, new_reloc, true);
1043 if (bfd_is_und_section(old_sect) || bfd_is_und_section(new_sect)) {
1044 if (!bfd_is_und_section(new_sect) && old_offset != 0 &&
1045 fetch_supersect(newsbfd, new_sect)->type == SS_TYPE_TEXT)
1046 return false;
1048 if (!bfd_is_und_section(new_sect) && new_offset != 0 &&
1049 fetch_supersect(oldsbfd, old_sect)->type == SS_TYPE_TEXT)
1050 return false;
1052 return strcmp(old_sym->name, new_sym->name) == 0 &&
1053 old_offset == new_offset;
1056 if (bfd_is_const_section(old_sect) || bfd_is_const_section(new_sect))
1057 DIE;
1059 struct supersect *old_ss = fetch_supersect(oldsbfd, old_sect);
1060 struct supersect *new_ss = fetch_supersect(newsbfd, new_sect);
1061 struct span *old_span = reloc_target_span(old_src_ss, old_reloc);
1062 struct span *new_span = reloc_target_span(new_src_ss, new_reloc);
1064 if (old_span->match != new_span || new_span->match != old_span) {
1065 debug1(newsbfd, "Nonmatching relocs from %s to %s/%s\n",
1066 new_src_ss->name, old_span->label, new_span->label);
1067 return false;
1070 if (old_sym->value + old_offset - old_span->start !=
1071 new_sym->value + new_offset - new_span->start) {
1072 debug1(newsbfd, "Offsets to %s/%s differ between %s "
1073 "and %s: %lx+%lx/%lx+%lx\n", old_ss->name,
1074 new_ss->name, old_src_ss->name, new_src_ss->name,
1075 (unsigned long)old_sym->value, (unsigned long)old_offset,
1076 (unsigned long)new_sym->value,
1077 (unsigned long)new_offset);
1078 return false;
1081 if ((old_sym->value + old_offset - old_span->start != 0 ||
1082 new_sym->value + new_offset - new_span->start != 0) &&
1083 new_span->patch) {
1084 debug1(newsbfd, "Relocation from %s to nonzero offsets "
1085 "%lx+%lx/%lx+%lx in changed section %s\n",
1086 new_src_ss->name, (unsigned long)old_sym->value,
1087 (unsigned long)old_offset, (unsigned long)new_sym->value,
1088 (unsigned long)new_offset, new_sym->section->name);
1089 return false;
1091 return true;
1094 bool all_relocs_equal(struct span *old_span, struct span *new_span)
1096 struct supersect *old_ss = old_span->ss, *new_ss = new_span->ss;
1097 arelent **old_relocp, **new_relocp;
1099 for (old_relocp = old_ss->relocs.data;
1100 old_relocp < old_ss->relocs.data + old_ss->relocs.size;
1101 old_relocp++) {
1102 if (find_span(old_ss, (*old_relocp)->address) == old_span)
1103 break;
1106 for (new_relocp = new_ss->relocs.data;
1107 new_relocp < new_ss->relocs.data + new_ss->relocs.size;
1108 new_relocp++) {
1109 if (find_span(new_ss, (*new_relocp)->address) == new_span)
1110 break;
1113 for (; old_relocp < old_ss->relocs.data + old_ss->relocs.size &&
1114 find_span(old_ss, (*old_relocp)->address) == old_span &&
1115 new_relocp < new_ss->relocs.data + new_ss->relocs.size &&
1116 find_span(new_ss, (*new_relocp)->address) == new_span;
1117 old_relocp++, new_relocp++) {
1118 if (!relocs_equal(old_ss, new_ss, *old_relocp, *new_relocp))
1119 return false;
1122 if ((old_relocp < old_ss->relocs.data + old_ss->relocs.size &&
1123 find_span(old_ss, (*old_relocp)->address) == old_span) ||
1124 (new_relocp < new_ss->relocs.data + new_ss->relocs.size &&
1125 find_span(new_ss, (*new_relocp)->address) == new_span)) {
1126 debug1(new_ss->parent, "Different reloc count between %s and "
1127 "%s\n", old_span->label, new_span->label);
1128 return false;
1131 return true;
1134 bfd_vma non_dst_mask(struct supersect *ss, arelent *reloc)
1136 int bits = bfd_get_reloc_size(reloc->howto) * 8;
1137 void *address = ss->contents.data + reloc->address;
1138 bfd_vma x = bfd_get(bits, ss->parent->abfd, address);
1139 return x & ~reloc->howto->dst_mask;
1142 void rm_relocs(struct superbfd *isbfd)
1144 asection *p;
1145 for (p = isbfd->abfd->sections; p != NULL; p = p->next) {
1146 struct supersect *ss = fetch_supersect(isbfd, p);
1147 bool remove_relocs = ss->keep;
1149 if (mode("keep") && ss->type == SS_TYPE_SPECIAL)
1150 remove_relocs = false;
1152 if (ss->type == SS_TYPE_KSPLICE ||
1153 ss->type == SS_TYPE_KSPLICE_CALL)
1154 remove_relocs = false;
1155 if (mode("finalize") &&
1156 (starts_with(ss->name, ".ksplice_patches") ||
1157 starts_with(ss->name, ".ksplice_relocs")))
1158 remove_relocs = true;
1160 if (remove_relocs)
1161 rm_some_relocs(ss);
1165 void rm_some_relocs(struct supersect *ss)
1167 struct arelentp_vec orig_relocs;
1168 vec_move(&orig_relocs, &ss->relocs);
1170 arelent **relocp;
1171 for (relocp = orig_relocs.data;
1172 relocp < orig_relocs.data + orig_relocs.size; relocp++) {
1173 bool rm_reloc = false;
1174 asymbol *sym_ptr = *(*relocp)->sym_ptr_ptr;
1176 if (mode("rmsyms") && str_in_set(sym_ptr->name, &rmsyms) &&
1177 bfd_is_und_section(sym_ptr->section))
1178 rm_reloc = true;
1180 if (mode("keep"))
1181 rm_reloc = true;
1183 if (mode("keep-primary") &&
1184 (bfd_is_const_section(sym_ptr->section) ||
1185 reloc_target_span(ss, *relocp)->new))
1186 rm_reloc = false;
1188 if (mode("keep-primary")) {
1189 const struct table_section *ts =
1190 get_table_section(ss->name);
1191 if (ts != NULL && ts->has_addr &&
1192 ((*relocp)->address % ts->entry_size ==
1193 ts->addr_offset ||
1194 (*relocp)->address % ts->entry_size ==
1195 ts->other_offset))
1196 rm_reloc = false;
1199 if (mode("finalize") && bfd_is_und_section(sym_ptr->section))
1200 rm_reloc = true;
1202 if (strcmp(sym_ptr->name, "mcount") == 0 &&
1203 bfd_is_und_section(sym_ptr->section))
1204 rm_reloc = false;
1206 if (!find_span(ss, (*relocp)->address)->keep)
1207 rm_reloc = false;
1209 if (rm_reloc)
1210 write_ksplice_reloc(ss, *relocp);
1211 else
1212 *vec_grow(&ss->relocs, 1) = *relocp;
1216 struct supersect *make_section(struct superbfd *sbfd, const char *fmt, ...)
1218 va_list ap;
1219 va_start(ap, fmt);
1220 char *name = vstrprintf(fmt, ap);
1221 va_end(ap);
1223 asection *sect = bfd_get_section_by_name(sbfd->abfd, name);
1224 if (sect != NULL)
1225 return fetch_supersect(sbfd, sect);
1226 else
1227 return new_supersect(sbfd, name);
1230 arelent *create_reloc(struct supersect *ss, const void *addr, asymbol **symp,
1231 bfd_vma offset)
1233 bfd_reloc_code_real_type code;
1234 switch (bfd_arch_bits_per_address(ss->parent->abfd)) {
1235 case 32:
1236 code = BFD_RELOC_32;
1237 break;
1238 case 64:
1239 code = BFD_RELOC_64;
1240 break;
1241 default:
1242 DIE;
1245 arelent *reloc = malloc(sizeof(*reloc));
1246 reloc->sym_ptr_ptr = symp;
1247 reloc->address = addr_offset(ss, addr);
1248 reloc->howto = bfd_reloc_type_lookup(ss->parent->abfd, code);
1249 reloc->addend = offset;
1250 return reloc;
1253 void write_reloc(struct supersect *ss, const void *addr, asymbol **symp,
1254 bfd_vma offset)
1256 *vec_grow(&ss->new_relocs, 1) = create_reloc(ss, addr, symp, offset);
1259 void write_string(struct supersect *ss, const char **addr, const char *fmt, ...)
1261 va_list ap;
1262 struct supersect *str_ss = make_section(ss->parent, ".ksplice_str");
1263 char *str;
1264 va_start(ap, fmt);
1265 int len = vasprintf(&str, fmt, ap);
1266 assert(len >= 0);
1267 va_end(ap);
1269 unsigned long *str_offp = ulong_hash_lookup(&ksplice_string_offset, str,
1270 FALSE);
1271 if (str_offp == NULL) {
1272 char *buf = sect_grow(str_ss, len + 1, char);
1273 memcpy(buf, str, len + 1);
1274 str_offp = ulong_hash_lookup(&ksplice_string_offset, str, TRUE);
1275 *str_offp = addr_offset(str_ss, buf);
1278 write_reloc(ss, addr, &str_ss->symbol, *str_offp);
1281 void lookup_system_map(struct addr_vec *addrs, const char *name, long offset)
1283 struct addr_vec *map_addrs =
1284 addr_vec_hash_lookup(&system_map, name, FALSE);
1285 if (map_addrs == NULL)
1286 return;
1288 unsigned long *addr, *map_addr;
1289 for (map_addr = map_addrs->data;
1290 map_addr < map_addrs->data + map_addrs->size; map_addr++) {
1291 for (addr = addrs->data; addr < addrs->data + addrs->size;
1292 addr++) {
1293 if (*addr == *map_addr + offset)
1294 break;
1296 if (addr < addrs->data + addrs->size)
1297 continue;
1298 *vec_grow(addrs, 1) = *map_addr + offset;
1302 void compute_system_map_array(struct superbfd *sbfd, struct addr_vec *addrs,
1303 asymbol *sym)
1305 if (bfd_is_abs_section(sym->section)) {
1306 *vec_grow(addrs, 1) = sym->value;
1307 } else if (bfd_is_und_section(sym->section)) {
1308 lookup_system_map(addrs, sym->name, 0);
1309 } else if (!bfd_is_const_section(sym->section)) {
1310 asymbol **gsymp;
1311 for (gsymp = sbfd->syms.data;
1312 gsymp < sbfd->syms.data + sbfd->syms.size; gsymp++) {
1313 asymbol *gsym = *gsymp;
1314 if ((gsym->flags & BSF_DEBUGGING) == 0 &&
1315 gsym->section == sym->section)
1316 lookup_system_map(addrs, gsym->name,
1317 sym->value - gsym->value);
1322 void write_ksplice_system_map(struct superbfd *sbfd, asymbol *sym,
1323 const char *label)
1325 bool *done = bool_hash_lookup(&system_map_written, label, TRUE);
1326 if (*done)
1327 return;
1328 *done = true;
1330 struct addr_vec addrs;
1331 vec_init(&addrs);
1333 compute_system_map_array(sbfd, &addrs, sym);
1334 if (addrs.size != 0) {
1335 struct supersect *smap_ss =
1336 make_section(sbfd, ".ksplice_system_map");
1337 struct ksplice_system_map *smap =
1338 sect_grow(smap_ss, 1, struct ksplice_system_map);
1339 write_string(smap_ss, &smap->label, "%s", label);
1341 struct supersect *array_ss = make_section(sbfd,
1342 ".ksplice_array");
1343 void *buf = sect_grow(array_ss, addrs.size,
1344 typeof(*addrs.data));
1345 memcpy(buf, addrs.data, addrs.size * sizeof(*addrs.data));
1346 smap->nr_candidates = addrs.size;
1347 write_reloc(smap_ss, &smap->candidates, &array_ss->symbol,
1348 addr_offset(array_ss, buf));
1350 vec_free(&addrs);
1353 void write_ksplice_symbol_backend(struct supersect *ss,
1354 struct ksplice_symbol *const *addr,
1355 asymbol *sym, const char *label,
1356 const char *name)
1358 struct supersect *ksymbol_ss = make_section(ss->parent,
1359 ".ksplice_symbols");
1360 struct ksplice_symbol *ksymbol;
1361 unsigned long *ksymbol_offp;
1363 ksymbol_offp = ulong_hash_lookup(&ksplice_symbol_offset, label, FALSE);
1364 if (ksymbol_offp != NULL) {
1365 write_reloc(ss, addr, &ksymbol_ss->symbol, *ksymbol_offp);
1366 return;
1368 ksymbol = sect_grow(ksymbol_ss, 1, struct ksplice_symbol);
1369 ksymbol_offp = ulong_hash_lookup(&ksplice_symbol_offset, label, TRUE);
1370 *ksymbol_offp = addr_offset(ksymbol_ss, ksymbol);
1372 write_reloc(ss, addr, &ksymbol_ss->symbol, *ksymbol_offp);
1373 write_string(ksymbol_ss, &ksymbol->label, "%s", label);
1374 if (name != NULL) {
1375 write_string(ksymbol_ss, &ksymbol->name, "%s", name);
1376 write_ksplice_system_map(ksymbol_ss->parent, sym, label);
1380 void write_ksplice_symbol(struct supersect *ss,
1381 struct ksplice_symbol *const *addr,
1382 asymbol *sym, struct span *span,
1383 const char *addstr_sect)
1385 const char *label, *name;
1386 if (span != NULL && span->start != 0)
1387 label = span->label;
1388 else
1389 label = label_lookup(ss->parent, sym);
1391 asymbol *gsym = canonical_symbol(ss->parent, sym);
1392 if (strcmp(addstr_sect, "") != 0)
1393 name = NULL;
1394 else if (bfd_is_und_section(sym->section))
1395 name = sym->name;
1396 else if (bfd_is_const_section(sym->section))
1397 name = NULL;
1398 else if (span != NULL && span->symbol == NULL)
1399 name = NULL;
1400 else if (gsym == NULL || (gsym->flags & BSF_SECTION_SYM) != 0)
1401 name = NULL;
1402 else
1403 name = gsym->name;
1405 write_ksplice_symbol_backend(ss, addr, sym,
1406 strprintf("%s%s", addstr_sect, label),
1407 name);
1410 void write_ksplice_reloc(struct supersect *ss, arelent *orig_reloc)
1412 asymbol *sym_ptr = *orig_reloc->sym_ptr_ptr;
1413 bfd_vma reloc_addend = get_reloc_offset(ss, orig_reloc, false);
1414 bfd_vma target_addend = get_reloc_offset(ss, orig_reloc, true);
1415 unsigned long *repladdr = ss->contents.data + orig_reloc->address;
1417 if (mode("finalize") && starts_with(ss->name, ".ksplice_patches")) {
1418 *repladdr = 0;
1419 return;
1421 if (mode("finalize") && starts_with(ss->name, ".ksplice_relocs")) {
1422 assert(starts_with(sym_ptr->name, KSPLICE_SYMBOL_STR));
1423 asymbol fake_sym;
1424 fake_sym.name = sym_ptr->name + strlen(KSPLICE_SYMBOL_STR);
1425 fake_sym.section = bfd_und_section_ptr;
1426 fake_sym.value = 0;
1427 fake_sym.flags = 0;
1429 write_ksplice_symbol_backend
1430 (ss, (struct ksplice_symbol **)repladdr, &fake_sym,
1431 fake_sym.name, fake_sym.name);
1432 return;
1435 struct span *span = reloc_target_span(ss, orig_reloc);
1436 if (span == ss->spans.data && span->start != target_addend)
1437 span = NULL;
1438 write_canary(ss, orig_reloc->address,
1439 bfd_get_reloc_size(orig_reloc->howto),
1440 orig_reloc->howto->dst_mask);
1442 struct supersect *kreloc_ss;
1443 if (mode("rmsyms"))
1444 kreloc_ss = make_section(ss->parent, ".ksplice_init_relocs");
1445 else
1446 kreloc_ss = make_section(ss->parent, ".ksplice_relocs%s",
1447 ss->name);
1448 struct ksplice_reloc *kreloc = sect_grow(kreloc_ss, 1,
1449 struct ksplice_reloc);
1451 struct span *address_span = find_span(ss, orig_reloc->address);
1452 write_reloc(kreloc_ss, &kreloc->blank_addr,
1453 &ss->symbol, orig_reloc->address + address_span->shift);
1454 if (bfd_is_und_section(sym_ptr->section) && mode("keep")) {
1455 char *name = strprintf(KSPLICE_SYMBOL_STR "%s", sym_ptr->name);
1456 asymbol **symp = make_undefined_symbolp(ss->parent, name);
1457 write_reloc(kreloc_ss, &kreloc->symbol, symp, 0);
1458 } else {
1459 write_ksplice_symbol(kreloc_ss, &kreloc->symbol, sym_ptr, span,
1460 "");
1462 if (span != NULL && span->start != 0) {
1463 reloc_addend += sym_ptr->value - span->start;
1464 target_addend += sym_ptr->value - span->start;
1466 kreloc->insn_addend = reloc_addend - target_addend;
1467 kreloc->target_addend = target_addend;
1468 write_ksplice_reloc_howto(kreloc_ss, &kreloc->howto, orig_reloc->howto,
1469 KSPLICE_HOWTO_RELOC);
1472 static void write_ksplice_reloc_howto(struct supersect *ss, const
1473 struct ksplice_reloc_howto *const *addr,
1474 reloc_howto_type *howto,
1475 enum ksplice_reloc_howto_type type)
1477 struct supersect *khowto_ss = make_section(ss->parent,
1478 ".ksplice_reloc_howtos");
1479 struct ksplice_reloc_howto *khowto;
1480 unsigned long *khowto_offp;
1482 khowto_offp = ulong_hash_lookup(&ksplice_howto_offset, howto->name,
1483 FALSE);
1484 if (khowto_offp != NULL) {
1485 write_reloc(ss, addr, &khowto_ss->symbol, *khowto_offp);
1486 return;
1488 khowto = sect_grow(khowto_ss, 1, struct ksplice_reloc_howto);
1489 khowto_offp = ulong_hash_lookup(&ksplice_howto_offset, howto->name,
1490 TRUE);
1491 *khowto_offp = addr_offset(khowto_ss, khowto);
1493 khowto->type = type;
1494 khowto->pcrel = howto->pc_relative;
1495 khowto->size = bfd_get_reloc_size(howto);
1496 khowto->dst_mask = howto->dst_mask;
1497 khowto->rightshift = howto->rightshift;
1498 khowto->signed_addend =
1499 (howto->complain_on_overflow == complain_overflow_signed) ||
1500 (howto->complain_on_overflow == complain_overflow_bitfield);
1501 write_reloc(ss, addr, &khowto_ss->symbol, *khowto_offp);
1504 #define CANARY(x, canary) ((x & ~howto->dst_mask) | (canary & howto->dst_mask))
1506 void write_canary(struct supersect *ss, int offset, bfd_size_type size,
1507 bfd_vma dst_mask)
1509 int bits = size * 8;
1510 void *address = ss->contents.data + offset;
1511 bfd_vma x = bfd_get(bits, ss->parent->abfd, address);
1512 x = (x & ~dst_mask) | ((bfd_vma)KSPLICE_CANARY & dst_mask);
1513 bfd_put(bits, ss->parent->abfd, x, address);
1516 static void write_date_relocs(struct superbfd *sbfd, const char *str,
1517 enum ksplice_reloc_howto_type type)
1519 asection *sect;
1520 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
1521 struct supersect *ss = fetch_supersect(sbfd, sect);
1522 if (ss->type != SS_TYPE_STRING && ss->type != SS_TYPE_RODATA)
1523 continue;
1524 void *ptr;
1525 struct span *span;
1526 for (span = ss->spans.data;
1527 span < ss->spans.data + ss->spans.size; span++) {
1528 if (!span->keep)
1529 continue;
1530 for (ptr = ss->contents.data + span->start;
1531 ptr + strlen(str) < ss->contents.data +
1532 span->start + span->contents_size; ptr++) {
1533 if (strcmp((const char *)ptr, str) == 0)
1534 write_ksplice_date_reloc
1535 (ss, addr_offset(ss, ptr), str,
1536 type);
1542 static void write_ksplice_date_reloc(struct supersect *ss, unsigned long offset,
1543 const char *str,
1544 enum ksplice_reloc_howto_type type)
1546 struct supersect *kreloc_ss;
1547 kreloc_ss = make_section(ss->parent, ".ksplice_relocs%s", ss->name);
1548 struct ksplice_reloc *kreloc = sect_grow(kreloc_ss, 1,
1549 struct ksplice_reloc);
1551 const char *filename = ss->parent->abfd->filename;
1552 char *c = strstr(filename, ".KSPLICE");
1553 int flen = (c == NULL ? strlen(filename) : c - filename);
1555 write_ksplice_symbol_backend(kreloc_ss, &kreloc->symbol, NULL,
1556 strprintf("%s<%.*s>", str, flen, filename),
1557 NULL);
1559 struct span *span = find_span(ss, offset);
1560 write_reloc(kreloc_ss, &kreloc->blank_addr, &ss->symbol,
1561 offset + span->shift);
1562 write_ksplice_nonreloc_howto(kreloc_ss, &kreloc->howto, type,
1563 strlen(str));
1566 static void write_table_relocs(struct superbfd *sbfd, const char *sectname,
1567 enum ksplice_reloc_howto_type type)
1569 asection *sect = bfd_get_section_by_name(sbfd->abfd, sectname);
1570 if (sect == NULL)
1571 return;
1572 struct supersect *ss = fetch_supersect(sbfd, sect);
1574 const struct table_section *s = get_table_section(sectname);
1575 if (s == NULL)
1576 DIE;
1578 void *entry;
1579 for (entry = ss->contents.data;
1580 entry < ss->contents.data + ss->contents.size;
1581 entry += s->entry_size) {
1582 struct span *span = find_span(ss, addr_offset(ss, entry));
1583 assert(span != NULL);
1584 if (!span->keep)
1585 continue;
1587 arelent *reloc = find_reloc(ss, entry + s->addr_offset);
1588 assert(reloc != NULL);
1589 asymbol *sym = *reloc->sym_ptr_ptr;
1590 assert(!bfd_is_const_section(sym->section));
1591 struct supersect *sym_ss = fetch_supersect(sbfd, sym->section);
1592 unsigned long addr = get_reloc_offset(ss, reloc, true) +
1593 sym->value;
1594 write_ksplice_table_reloc(sym_ss, addr, span->label, type);
1598 static void write_ksplice_table_reloc(struct supersect *ss,
1599 unsigned long address,
1600 const char *label,
1601 enum ksplice_reloc_howto_type type)
1603 struct supersect *kreloc_ss;
1604 kreloc_ss = make_section(ss->parent, ".ksplice_relocs%s", ss->name);
1605 struct ksplice_reloc *kreloc = sect_grow(kreloc_ss, 1,
1606 struct ksplice_reloc);
1607 struct span *span = find_span(ss, address);
1608 assert(span != NULL);
1610 write_ksplice_symbol_backend(kreloc_ss, &kreloc->symbol, NULL,
1611 label, NULL);
1612 write_reloc(kreloc_ss, &kreloc->blank_addr, &ss->symbol,
1613 address + span->shift);
1614 write_ksplice_nonreloc_howto(kreloc_ss, &kreloc->howto, type, 0);
1617 static void write_ksplice_nonreloc_howto(struct supersect *ss,
1618 const struct ksplice_reloc_howto
1619 *const *addr,
1620 enum ksplice_reloc_howto_type type,
1621 int size)
1623 struct supersect *khowto_ss =
1624 make_section(ss->parent, ".ksplice_reloc_howtos");
1625 struct ksplice_reloc_howto *khowto =
1626 sect_grow(khowto_ss, 1, struct ksplice_reloc_howto);
1628 khowto->type = type;
1629 khowto->size = size;
1630 khowto->pcrel = 0;
1631 khowto->dst_mask = 0;
1632 khowto->rightshift = 0;
1633 khowto->signed_addend = 0;
1634 write_reloc(ss, addr, &khowto_ss->symbol,
1635 addr_offset(khowto_ss, khowto));
1638 static void write_ksplice_section(struct span *span)
1640 struct supersect *ss = span->ss;
1641 const char *sectname = span->ss->name;
1642 const struct table_section *ts = get_table_section(ss->name);
1644 if (ts != NULL && ts->has_addr) {
1645 arelent *reloc = find_reloc(ss, ss->contents.data + span->start
1646 + ts->addr_offset);
1647 assert(reloc != NULL);
1648 asymbol *rsym = *reloc->sym_ptr_ptr;
1649 assert(!bfd_is_const_section(rsym->section));
1650 sectname = rsym->section->name;
1653 struct supersect *ksect_ss =
1654 make_section(ss->parent, ".ksplice_sections%s", sectname);
1655 struct ksplice_section *ksect = sect_grow(ksect_ss, 1,
1656 struct ksplice_section);
1657 asymbol *sym = span->symbol == NULL ? ss->symbol : span->symbol;
1659 write_ksplice_symbol(ksect_ss, &ksect->symbol, sym, span,
1660 mode("keep-primary") ? "(post)" : "");
1661 ksect->size = span->size;
1662 ksect->flags = 0;
1664 if (ss->type == SS_TYPE_RODATA || ss->type == SS_TYPE_STRING ||
1665 ss->type == SS_TYPE_EXPORT)
1666 ksect->flags |= KSPLICE_SECTION_RODATA;
1667 if (ss->type == SS_TYPE_DATA)
1668 ksect->flags |= KSPLICE_SECTION_DATA;
1669 if (ss->type == SS_TYPE_TEXT)
1670 ksect->flags |= KSPLICE_SECTION_TEXT;
1671 assert(ksect->flags != 0);
1673 if (ss->type == SS_TYPE_STRING)
1674 ksect->flags |= KSPLICE_SECTION_STRING;
1676 write_reloc(ksect_ss, &ksect->address, &ss->symbol,
1677 span->start + span->shift);
1680 static void write_ksplice_patch_reloc(struct supersect *ss,
1681 const char *sectname, unsigned long *addr,
1682 bfd_size_type size, const char *label,
1683 long addend)
1685 struct supersect *kreloc_ss;
1686 kreloc_ss = make_section(ss->parent, ".ksplice_relocs%s", sectname);
1687 struct ksplice_reloc *kreloc = sect_grow(kreloc_ss, 1,
1688 struct ksplice_reloc);
1690 write_canary(ss, addr_offset(ss, addr), size, -1);
1691 write_ksplice_symbol_backend(kreloc_ss, &kreloc->symbol, NULL,
1692 label, NULL);
1693 write_reloc(kreloc_ss, &kreloc->blank_addr, &ss->symbol,
1694 addr_offset(ss, addr));
1695 reloc_howto_type *howto =
1696 bfd_reloc_type_lookup(ss->parent->abfd,
1697 PASTE(BFD_RELOC_, LONG_BIT));
1698 write_ksplice_reloc_howto(kreloc_ss, &kreloc->howto, howto,
1699 KSPLICE_HOWTO_RELOC);
1700 kreloc->target_addend = addend;
1701 kreloc->insn_addend = 0;
1704 void write_ksplice_patch(struct superbfd *sbfd, struct span *span)
1706 struct supersect *kpatch_ss =
1707 make_section(sbfd, ".ksplice_patches%s", span->ss->name);
1708 struct ksplice_patch *kpatch = sect_grow(kpatch_ss, 1,
1709 struct ksplice_patch);
1711 write_ksplice_patch_reloc(kpatch_ss, span->ss->name, &kpatch->oldaddr,
1712 sizeof(kpatch->oldaddr), span->label, 0);
1713 if (span->ss->type == SS_TYPE_TEXT) {
1714 kpatch->type = KSPLICE_PATCH_TEXT;
1715 write_patch_storage(kpatch_ss, kpatch, MAX_TRAMPOLINE_SIZE,
1716 NULL);
1717 } else {
1718 kpatch->type = KSPLICE_PATCH_DATA;
1719 kpatch->size = span->contents_size;
1720 struct supersect *data_ss =
1721 make_section(sbfd, ".ksplice_patch_data");
1722 write_reloc(kpatch_ss, &kpatch->contents, &span->ss->symbol,
1723 span->start + span->shift);
1724 char *saved = sect_do_grow(data_ss, 1, span->contents_size, 1);
1725 write_reloc(kpatch_ss, &kpatch->saved, &data_ss->symbol,
1726 addr_offset(data_ss, saved));
1728 write_reloc(kpatch_ss, &kpatch->repladdr, &span->ss->symbol,
1729 span->start + span->shift);
1732 asymbol **make_undefined_symbolp(struct superbfd *sbfd, const char *name)
1734 asymbol **symp;
1735 for (symp = sbfd->syms.data; symp < sbfd->syms.data + sbfd->syms.size;
1736 symp++) {
1737 asymbol *sym = *symp;
1738 if (strcmp(name, sym->name) == 0 &&
1739 bfd_is_und_section(sym->section))
1740 return symp;
1742 asymbol ***sympp;
1743 for (sympp = sbfd->new_syms.data;
1744 sympp < sbfd->new_syms.data + sbfd->new_syms.size; sympp++) {
1745 asymbol **symp = *sympp;
1746 asymbol *sym = *symp;
1747 if (strcmp(name, sym->name) == 0 &&
1748 bfd_is_und_section(sym->section))
1749 return symp;
1752 symp = malloc(sizeof(*symp));
1753 *symp = bfd_make_empty_symbol(sbfd->abfd);
1754 asymbol *sym = *symp;
1755 sym->name = name;
1756 sym->section = bfd_und_section_ptr;
1757 sym->flags = 0;
1758 sym->value = 0;
1759 *vec_grow(&sbfd->new_syms, 1) = symp;
1760 return symp;
1763 void write_ksplice_deleted_patch(struct superbfd *sbfd, const char *name,
1764 const char *label, const char *sectname)
1766 struct supersect *kpatch_ss =
1767 make_section(sbfd, ".ksplice_patches%s", sectname);
1768 struct ksplice_patch *kpatch = sect_grow(kpatch_ss, 1,
1769 struct ksplice_patch);
1771 write_ksplice_patch_reloc(kpatch_ss, sectname, &kpatch->oldaddr,
1772 sizeof(kpatch->oldaddr), label, 0);
1773 kpatch->type = KSPLICE_PATCH_TEXT;
1774 asymbol **symp = make_undefined_symbolp(sbfd, strdup(name));
1775 write_reloc(kpatch_ss, &kpatch->repladdr, symp, 0);
1776 write_patch_storage(kpatch_ss, kpatch, MAX_TRAMPOLINE_SIZE, NULL);
1779 void write_ksplice_export(struct superbfd *sbfd, struct span *span, bool del)
1781 struct supersect *kpatch_ss = make_section(sbfd, ".ksplice_patches");
1782 struct ksplice_patch *kpatch = sect_grow(kpatch_ss, 1,
1783 struct ksplice_patch);
1784 struct supersect *data_ss;
1786 const struct table_section *ts = get_table_section(span->ss->name);
1787 assert(ts != NULL);
1788 const char **addr =
1789 span->ss->contents.data + span->start + ts->other_offset;
1790 const char *symname = read_string(span->ss, addr);
1792 char *oldname, *newname;
1793 if (del) {
1794 oldname = strprintf("%s:%s", span->ss->name, symname);
1795 newname = strprintf("DISABLED_%s_%s", symname, kid);
1796 } else {
1797 oldname = strprintf("%s:DISABLED_%s_%s", span->ss->name,
1798 symname, kid);
1799 newname = strprintf("%s", symname);
1800 write_string(span->ss, addr, "DISABLED_%s_%s", symname, kid);
1803 write_ksplice_patch_reloc(kpatch_ss, "", &kpatch->oldaddr,
1804 sizeof(kpatch->oldaddr), oldname,
1805 ts->other_offset);
1806 kpatch->type = KSPLICE_PATCH_EXPORT;
1807 const char **namep = write_patch_storage(kpatch_ss, kpatch,
1808 sizeof(newname), &data_ss);
1809 write_string(data_ss, namep, "%s", newname);
1812 void filter_table_sections(struct superbfd *isbfd)
1814 struct supersect *tables_ss =
1815 fetch_supersect(offsets_sbfd,
1816 bfd_get_section_by_name(offsets_sbfd->abfd,
1817 ".ksplice_table_sections"));
1818 const struct table_section *ts;
1819 for (ts = tables_ss->contents.data;
1820 (void *)ts < tables_ss->contents.data + tables_ss->contents.size;
1821 ts++) {
1822 struct table_section s = *ts;
1823 s.sect = read_string(tables_ss, &ts->sect);
1824 s.other_sect = read_string(tables_ss, &ts->other_sect);
1825 s.crc_sect = read_string(tables_ss, &ts->crc_sect);
1826 filter_table_section(isbfd, &s);
1830 void filter_table_section(struct superbfd *sbfd, const struct table_section *s)
1832 asection *isection = bfd_get_section_by_name(sbfd->abfd, s->sect);
1833 if (isection == NULL)
1834 return;
1835 struct supersect *ss = fetch_supersect(sbfd, isection);
1837 void *entry;
1838 for (entry = ss->contents.data;
1839 entry < ss->contents.data + ss->contents.size;
1840 entry += s->entry_size) {
1841 struct span *span = find_span(ss, addr_offset(ss, entry));
1842 assert(span != NULL);
1844 if (s->has_addr) {
1845 arelent *reloc = find_reloc(ss, entry + s->addr_offset);
1846 assert(reloc != NULL);
1847 struct span *sym_span = reloc_target_span(ss, reloc);
1848 if (sym_span->keep)
1849 keep_span(span);
1852 if (s->other_sect != NULL) {
1853 arelent *reloc =
1854 find_reloc(ss, entry + s->other_offset);
1855 assert(reloc != NULL);
1856 struct span *sym_span = reloc_target_span(ss, reloc);
1857 if (span->keep)
1858 keep_span(sym_span);
1861 if (s->crc_sect != NULL) {
1862 asection *crc_sect =
1863 bfd_get_section_by_name(sbfd->abfd, s->crc_sect);
1864 struct supersect *crc_ss =
1865 fetch_supersect(sbfd, crc_sect);
1866 struct span *crc_span =
1867 find_span(crc_ss, addr_offset(ss, entry) /
1868 s->entry_size * s->crc_size);
1869 assert(crc_span);
1870 if (span->keep)
1871 keep_span(crc_span);
1876 void mark_precallable_spans(struct superbfd *sbfd)
1878 asection *sect;
1879 struct supersect *ss, *sym_ss;
1880 struct span *address_span, *target_span;
1881 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
1882 ss = fetch_supersect(sbfd, sect);
1883 arelent **relocp;
1884 if (ss->type == SS_TYPE_SPECIAL)
1885 continue;
1886 for (relocp = ss->relocs.data;
1887 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
1888 asymbol *sym = *(*relocp)->sym_ptr_ptr;
1889 address_span = find_span(ss, (*relocp)->address);
1890 if (!address_span->precallable)
1891 continue;
1892 target_span = reloc_target_span(ss, *relocp);
1893 if (target_span == NULL || target_span->keep)
1894 continue;
1895 sym_ss = fetch_supersect(sbfd, sym->section);
1896 if (sym_ss->type == SS_TYPE_IGNORED)
1897 continue;
1898 target_span->precallable = true;
1899 changed = true;
1904 void keep_referenced_sections(struct superbfd *sbfd)
1906 asection *sect;
1907 struct supersect *ss, *sym_ss;
1908 struct span *address_span, *target_span;
1909 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
1910 ss = fetch_supersect(sbfd, sect);
1911 arelent **relocp;
1912 if (ss->type == SS_TYPE_SPECIAL)
1913 continue;
1914 for (relocp = ss->relocs.data;
1915 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
1916 asymbol *sym = *(*relocp)->sym_ptr_ptr;
1917 address_span = find_span(ss, (*relocp)->address);
1918 if (!address_span->keep)
1919 continue;
1920 target_span = reloc_target_span(ss, *relocp);
1921 if (target_span == NULL || target_span->keep)
1922 continue;
1923 sym_ss = fetch_supersect(sbfd, sym->section);
1924 if (sym_ss->type == SS_TYPE_IGNORED)
1925 continue;
1926 keep_span(target_span);
1927 changed = true;
1932 void copy_symbols(struct asymbolp_vec *osyms, struct asymbolpp_vec *isyms)
1934 asymbol ***sympp;
1935 for (sympp = isyms->data; sympp < isyms->data + isyms->size; sympp++)
1936 *vec_grow(osyms, 1) = **sympp;
1939 /* Modified function from GNU Binutils objcopy.c */
1940 bfd_boolean copy_object(bfd *ibfd, bfd *obfd)
1942 assert(bfd_set_format(obfd, bfd_get_format(ibfd)));
1944 bfd_vma start = bfd_get_start_address(ibfd);
1946 flagword flags = bfd_get_file_flags(ibfd);
1947 flags &= bfd_applicable_file_flags(obfd);
1949 assert(bfd_set_start_address(obfd, start)
1950 && bfd_set_file_flags(obfd, flags));
1952 enum bfd_architecture iarch = bfd_get_arch(ibfd);
1953 unsigned int imach = bfd_get_mach(ibfd);
1954 assert(bfd_set_arch_mach(obfd, iarch, imach));
1955 assert(bfd_set_format(obfd, bfd_get_format(ibfd)));
1957 /* BFD mandates that all output sections be created and sizes set before
1958 any output is done. Thus, we traverse all sections multiple times. */
1959 bfd_map_over_sections(ibfd, setup_section, obfd);
1961 struct supersect *new_supersects = fetch_superbfd(ibfd)->new_supersects;
1962 struct supersect *ss;
1963 for (ss = new_supersects; ss != NULL; ss = ss->next)
1964 setup_new_section(obfd, ss);
1966 /* Mark symbols used in output relocations so that they
1967 are kept, even if they are local labels or static symbols.
1969 Note we iterate over the input sections examining their
1970 relocations since the relocations for the output sections
1971 haven't been set yet. mark_symbols_used_in_relocations will
1972 ignore input sections which have no corresponding output
1973 section. */
1975 bfd_map_over_sections(ibfd, mark_symbols_used_in_relocations, NULL);
1976 for (ss = new_supersects; ss != NULL; ss = ss->next)
1977 ss_mark_symbols_used_in_relocations(ss);
1978 struct asymbolp_vec osyms;
1979 vec_init(&osyms);
1980 filter_symbols(ibfd, obfd, &osyms, &fetch_superbfd(ibfd)->syms);
1981 copy_symbols(&osyms, &fetch_superbfd(ibfd)->new_syms);
1983 bfd_set_symtab(obfd, osyms.data, osyms.size);
1985 /* This has to happen after the symbol table has been set. */
1986 bfd_map_over_sections(obfd, write_section, NULL);
1988 /* Allow the BFD backend to copy any private data it understands
1989 from the input BFD to the output BFD. This is done last to
1990 permit the routine to look at the filtered symbol table, which is
1991 important for the ECOFF code at least. */
1992 assert(bfd_copy_private_bfd_data(ibfd, obfd));
1994 return TRUE;
1997 /* Modified function from GNU Binutils objcopy.c */
1998 void setup_section(bfd *ibfd, asection *isection, void *obfdarg)
2000 struct superbfd *isbfd = fetch_superbfd(ibfd);
2001 struct supersect *ss = fetch_supersect(isbfd, isection);
2002 bfd *obfd = obfdarg;
2003 bfd_vma vma;
2005 if (!ss->keep)
2006 return;
2008 asection *osection = bfd_make_section_anyway(obfd, ss->name);
2009 assert(osection != NULL);
2011 osection->userdata = ss;
2012 bfd_set_section_flags(obfd, osection, ss->flags);
2013 ss->symbol = osection->symbol;
2014 assert(bfd_set_section_size(obfd, osection, ss->contents.size));
2016 vma = bfd_section_vma(ibfd, isection);
2017 assert(bfd_set_section_vma(obfd, osection, vma));
2019 osection->lma = isection->lma;
2020 assert(bfd_set_section_alignment(obfd, osection, ss->alignment));
2021 osection->entsize = ss->entsize;
2022 osection->output_section = osection;
2023 osection->output_offset = 0;
2024 isection->output_section = osection;
2025 isection->output_offset = 0;
2026 return;
2029 void setup_new_section(bfd *obfd, struct supersect *ss)
2031 asection *osection = bfd_make_section_anyway(obfd, ss->name);
2032 assert(osection != NULL);
2033 bfd_set_section_flags(obfd, osection, ss->flags);
2035 osection->userdata = ss;
2036 ss->symbol = osection->symbol;
2037 assert(bfd_set_section_size(obfd, osection, ss->contents.size));
2038 assert(bfd_set_section_vma(obfd, osection, 0));
2040 osection->lma = 0;
2041 assert(bfd_set_section_alignment(obfd, osection, ss->alignment));
2042 osection->entsize = ss->entsize;
2043 osection->output_section = osection;
2044 osection->output_offset = 0;
2047 static int compare_reloc_addresses(const void *aptr, const void *bptr)
2049 const arelent *const *a = aptr, *const *b = bptr;
2050 return (*a)->address - (*b)->address;
2053 static void delete_obsolete_relocs(struct supersect *ss)
2055 if (ss->new_relocs.size == 0)
2056 return;
2058 qsort(ss->relocs.data, ss->relocs.size, sizeof(*ss->relocs.data),
2059 compare_reloc_addresses);
2060 qsort(ss->new_relocs.data, ss->new_relocs.size,
2061 sizeof(*ss->new_relocs.data), compare_reloc_addresses);
2063 struct arelentp_vec orig_relocs;
2064 vec_move(&orig_relocs, &ss->relocs);
2066 arelent **relocp, **new_relocp = ss->new_relocs.data;
2067 for (relocp = orig_relocs.data;
2068 relocp < orig_relocs.data + orig_relocs.size; relocp++) {
2069 while (new_relocp < ss->new_relocs.data + ss->new_relocs.size &&
2070 (*new_relocp)->address < (*relocp)->address)
2071 new_relocp++;
2072 arelent *reloc = *relocp, *new_reloc = *new_relocp;
2073 if (new_relocp == ss->new_relocs.data + ss->new_relocs.size ||
2074 reloc->address != new_reloc->address)
2075 *vec_grow(&ss->relocs, 1) = reloc;
2079 void write_section(bfd *obfd, asection *osection, void *arg)
2081 struct supersect *ss = osection->userdata;
2083 if ((ss->flags & SEC_GROUP) != 0 || ss->contents.size == 0)
2084 return;
2086 delete_obsolete_relocs(ss);
2088 arelent **relocp;
2089 char *error_message;
2090 for (relocp = ss->new_relocs.data;
2091 relocp < ss->new_relocs.data + ss->new_relocs.size; relocp++) {
2092 bfd_vma val;
2093 if (bfd_get_arch(obfd) == bfd_arch_arm)
2094 val = osection->use_rela_p ? 0 : (*relocp)->addend;
2095 else
2096 val = 0;
2097 bfd_put(bfd_get_reloc_size((*relocp)->howto) * 8, obfd, val,
2098 ss->contents.data + (*relocp)->address);
2099 if (bfd_install_relocation(obfd, *relocp, ss->contents.data,
2100 0, osection, &error_message) !=
2101 bfd_reloc_ok) {
2102 err(ss->parent, "ksplice: error installing reloc: %s",
2103 error_message);
2104 DIE;
2107 memcpy(vec_grow(&ss->relocs, ss->new_relocs.size), ss->new_relocs.data,
2108 ss->new_relocs.size * sizeof(*ss->new_relocs.data));
2110 bfd_set_reloc(obfd, osection,
2111 ss->relocs.size == 0 ? NULL : ss->relocs.data,
2112 ss->relocs.size);
2114 if (ss->flags & SEC_HAS_CONTENTS)
2115 assert(bfd_set_section_contents
2116 (obfd, osection, ss->contents.data, 0,
2117 ss->contents.size));
2120 /* Modified function from GNU Binutils objcopy.c
2122 * Mark all the symbols which will be used in output relocations with
2123 * the BSF_KEEP flag so that those symbols will not be stripped.
2125 * Ignore relocations which will not appear in the output file.
2127 void mark_symbols_used_in_relocations(bfd *abfd, asection *isection,
2128 void *ignored)
2130 struct superbfd *sbfd = fetch_superbfd(abfd);
2131 if (isection->output_section == NULL)
2132 return;
2134 struct supersect *ss = fetch_supersect(sbfd, isection);
2135 ss_mark_symbols_used_in_relocations(ss);
2138 void ss_mark_symbols_used_in_relocations(struct supersect *ss)
2140 /* Examine each symbol used in a relocation. If it's not one of the
2141 special bfd section symbols, then mark it with BSF_KEEP. */
2142 arelent **relocp;
2143 for (relocp = ss->relocs.data;
2144 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
2145 asymbol *sym = *(*relocp)->sym_ptr_ptr;
2146 if (!(bfd_is_const_section(sym->section) &&
2147 sym == sym->section->symbol))
2148 sym->flags |= BSF_KEEP;
2150 for (relocp = ss->new_relocs.data;
2151 relocp < ss->new_relocs.data + ss->new_relocs.size; relocp++) {
2152 asymbol *sym = *(*relocp)->sym_ptr_ptr;
2153 if (!(bfd_is_const_section(sym->section) &&
2154 sym == sym->section->symbol))
2155 sym->flags |= BSF_KEEP;
2159 static bool deleted_table_section_symbol(bfd *abfd, asymbol *sym)
2161 struct superbfd *sbfd = fetch_superbfd(abfd);
2162 if (bfd_is_const_section(sym->section))
2163 return false;
2164 struct supersect *ss = fetch_supersect(sbfd, sym->section);
2166 asymbol **symp;
2167 for (symp = ss->syms.data; symp < ss->syms.data + ss->syms.size; symp++) {
2168 if (sym == *symp)
2169 break;
2171 return symp >= ss->syms.data + ss->syms.size &&
2172 (sym->flags & BSF_SECTION_SYM) == 0;
2175 void filter_symbols(bfd *ibfd, bfd *obfd, struct asymbolp_vec *osyms,
2176 struct asymbolp_vec *isyms)
2178 asymbol **symp;
2179 struct superbfd *sbfd = fetch_superbfd(ibfd);
2180 for (symp = isyms->data; symp < isyms->data + isyms->size; symp++) {
2181 asymbol *sym = *symp;
2182 struct supersect *sym_ss = NULL;
2183 struct span *sym_span = NULL;
2184 if (!bfd_is_const_section(sym->section)) {
2185 sym_ss = fetch_supersect(sbfd, sym->section);
2186 sym_span = find_span(sym_ss, sym->value);
2189 if (mode("keep") && (sym->flags & BSF_GLOBAL) != 0 &&
2190 !(mode("keep-primary") && sym_span != NULL &&
2191 sym_span->new))
2192 sym->flags = (sym->flags & ~BSF_GLOBAL) | BSF_LOCAL;
2194 if (mode("finalize") && (sym->flags & BSF_GLOBAL) != 0)
2195 sym->flags = (sym->flags & ~BSF_GLOBAL) | BSF_LOCAL;
2197 bool keep = bfd_is_const_section(sym->section) ||
2198 (sym_ss->keep && (sym->flags & BSF_SECTION_SYM) != 0) ||
2199 (sym_span != NULL && sym_span->keep);
2200 if (bfd_is_und_section(sym->section) &&
2201 (sym->flags & BSF_KEEP) == 0)
2202 keep = false;
2203 if (deleted_table_section_symbol(ibfd, sym))
2204 keep = false;
2206 if (mode("keep-helper") && sym_ss != NULL &&
2207 sym_ss->type == SS_TYPE_EXPORT)
2208 keep = false;
2210 if (keep) {
2211 if (sym_ss != NULL && !sym_ss->keep) {
2212 err(sbfd, "Kept symbol %s in unkept section "
2213 "%s\n", sym->name, sym->section->name);
2214 DIE;
2216 *vec_grow(osyms, 1) = sym;
2221 void read_str_set(struct str_vec *strs)
2223 char *buf = NULL;
2224 size_t n = 0;
2225 assert(getline(&buf, &n, stdin) >= 0);
2226 vec_init(strs);
2227 char *saveptr;
2228 while (1) {
2229 char *str = strtok_r(buf, " \n", &saveptr);
2230 buf = NULL;
2231 if (str == NULL)
2232 break;
2233 *vec_grow(strs, 1) = str;
2237 bool str_in_set(const char *str, const struct str_vec *strs)
2239 const char **strp;
2240 for (strp = strs->data; strp < strs->data + strs->size; strp++) {
2241 if (strcmp(str, *strp) == 0)
2242 return true;
2244 return false;
2247 bool is_table_section(const char *name, bool consider_other)
2249 struct supersect *tables_ss =
2250 fetch_supersect(offsets_sbfd,
2251 bfd_get_section_by_name(offsets_sbfd->abfd,
2252 ".ksplice_table_sections"));
2253 const struct table_section *ts;
2254 for (ts = tables_ss->contents.data;
2255 (void *)ts < tables_ss->contents.data + tables_ss->contents.size;
2256 ts++) {
2257 if (strcmp(name, read_string(tables_ss, &ts->sect)) == 0)
2258 return true;
2259 const char *osect_name = read_string(tables_ss,
2260 &ts->other_sect);
2261 if (consider_other && osect_name != NULL &&
2262 strcmp(name, osect_name) == 0)
2263 return true;
2264 const char *crc_name = read_string(tables_ss, &ts->crc_sect);
2265 if (consider_other && crc_name != NULL &&
2266 strcmp(name, crc_name) == 0)
2267 return true;
2269 return false;
2272 const struct table_section *get_table_section(const char *name)
2274 struct supersect *tables_ss =
2275 fetch_supersect(offsets_sbfd,
2276 bfd_get_section_by_name(offsets_sbfd->abfd,
2277 ".ksplice_table_sections"));
2278 const struct table_section *ts;
2279 for (ts = tables_ss->contents.data;
2280 (void *)ts < tables_ss->contents.data + tables_ss->contents.size;
2281 ts++) {
2282 if (strcmp(name, read_string(tables_ss, &ts->sect)) == 0) {
2283 if (ts->entry_contents_size != 0)
2284 assert(align(ts->entry_contents_size,
2285 ts->entry_align) ==
2286 ts->entry_size);
2287 struct table_section *ns = malloc(sizeof(*ns));
2288 *ns = *ts;
2289 ns->sect = read_string(tables_ss, &ts->sect);
2290 ns->crc_sect = read_string(tables_ss, &ts->crc_sect);
2291 ns->other_sect =
2292 read_string(tables_ss, &ts->other_sect);
2293 return ns;
2296 return NULL;
2299 enum supersect_type supersect_type(struct supersect *ss)
2301 if (mode("finalize") &&
2302 strcmp(finalize_target, "vmlinux") == 0 &&
2303 (starts_with(ss->name, ".ksplice_relocs.exit") ||
2304 starts_with(ss->name, ".ksplice_sections.exit") ||
2305 starts_with(ss->name, ".ksplice_patches.exit")))
2306 return SS_TYPE_EXIT;
2307 if (starts_with(ss->name, ".ksplice_call"))
2308 return SS_TYPE_KSPLICE_CALL;
2309 if (starts_with(ss->name, ".ksplice_options"))
2310 return SS_TYPE_SPECIAL;
2311 if (starts_with(ss->name, ".ksplice"))
2312 return SS_TYPE_KSPLICE;
2314 if (starts_with(ss->name, ".init"))
2315 return SS_TYPE_IGNORED;
2316 if (starts_with(ss->name, ".security_initcall.init"))
2317 return SS_TYPE_IGNORED;
2318 if (starts_with(ss->name, ".con_initcall.init"))
2319 return SS_TYPE_IGNORED;
2320 if (starts_with(ss->name, ".x86cpuvendor.init"))
2321 return SS_TYPE_IGNORED;
2322 if (starts_with(ss->name, ".early_param.init"))
2323 return SS_TYPE_IGNORED;
2324 if (starts_with(ss->name, ".taglist.init"))
2325 return SS_TYPE_IGNORED;
2326 if (starts_with(ss->name, ".arch.info.init"))
2327 return SS_TYPE_IGNORED;
2328 if (starts_with(ss->name, ".proc.info.init"))
2329 return SS_TYPE_IGNORED;
2330 /* .pci_fixup_* sections really should be treated as global rodata
2331 referenced only from quirks.c */
2332 if (starts_with(ss->name, ".pci_fixup_"))
2333 return SS_TYPE_IGNORED;
2334 /* .builtin_fw sections are similar to .pci_fixup */
2335 if (starts_with(ss->name, ".builtin_fw"))
2336 return SS_TYPE_IGNORED;
2337 /* same for .tracedata */
2338 if (starts_with(ss->name, ".tracedata"))
2339 return SS_TYPE_IGNORED;
2340 if (starts_with(ss->name, ".debug"))
2341 return SS_TYPE_IGNORED;
2342 /* .eh_frame should probably be discarded, not ignored */
2343 if (starts_with(ss->name, ".eh_frame"))
2344 return SS_TYPE_IGNORED;
2345 if (config->ignore_devinit && starts_with(ss->name, ".devinit"))
2346 return SS_TYPE_IGNORED;
2347 if (config->ignore_meminit && starts_with(ss->name, ".meminit"))
2348 return SS_TYPE_IGNORED;
2349 if (config->ignore_cpuinit && starts_with(ss->name, ".cpuinit"))
2350 return SS_TYPE_IGNORED;
2351 if (config->ignore_devinit && starts_with(ss->name, ".devexit"))
2352 return SS_TYPE_IGNORED;
2353 if (config->ignore_meminit && starts_with(ss->name, ".memexit"))
2354 return SS_TYPE_IGNORED;
2355 if (config->ignore_cpuinit && starts_with(ss->name, ".cpuexit"))
2356 return SS_TYPE_IGNORED;
2357 if (starts_with(ss->name, ".vgetcpu_mode") ||
2358 starts_with(ss->name, ".jiffies") ||
2359 starts_with(ss->name, ".wall_jiffies") ||
2360 starts_with(ss->name, ".vxtime") ||
2361 starts_with(ss->name, ".sys_tz") ||
2362 starts_with(ss->name, ".sysctl_vsyscall") ||
2363 starts_with(ss->name, ".xtime") ||
2364 starts_with(ss->name, ".xtime_lock") ||
2365 starts_with(ss->name, ".vsyscall"))
2366 return SS_TYPE_IGNORED;
2367 if (starts_with(ss->name, ".vdso"))
2368 return SS_TYPE_IGNORED;
2370 if (starts_with(ss->name, ".exit.text"))
2371 return SS_TYPE_TEXT;
2372 if (starts_with(ss->name, ".exit.data"))
2373 return SS_TYPE_DATA;
2375 if (starts_with(ss->name, ".text") ||
2376 starts_with(ss->name, ".kernel.text") ||
2377 starts_with(ss->name, ".devinit.text") ||
2378 starts_with(ss->name, ".meminit.text") ||
2379 starts_with(ss->name, ".cpuinit.text") ||
2380 starts_with(ss->name, ".devexit.text") ||
2381 starts_with(ss->name, ".memexit.text") ||
2382 starts_with(ss->name, ".cpuexit.text") ||
2383 starts_with(ss->name, ".ref.text") ||
2384 starts_with(ss->name, ".spinlock.text") ||
2385 starts_with(ss->name, ".kprobes.text") ||
2386 starts_with(ss->name, ".sched.text") ||
2387 (mode("keep-helper") && starts_with(ss->name, ".fixup")))
2388 return SS_TYPE_TEXT;
2390 int n = -1;
2391 if (sscanf(ss->name, ".rodata.str%*u.%*u%n", &n) >= 0 &&
2392 n == strlen(ss->name))
2393 return ss->entsize == 1 ? SS_TYPE_STRING : SS_TYPE_RODATA;
2395 if (starts_with(ss->name, ".rodata") ||
2396 starts_with(ss->name, ".kernel.rodata") ||
2397 starts_with(ss->name, ".devinit.rodata") ||
2398 starts_with(ss->name, ".meminit.rodata") ||
2399 starts_with(ss->name, ".cpuinit.rodata") ||
2400 starts_with(ss->name, ".devexit.rodata") ||
2401 starts_with(ss->name, ".memexit.rodata") ||
2402 starts_with(ss->name, ".cpuexit.rodata") ||
2403 starts_with(ss->name, ".ref.rodata") ||
2404 starts_with(ss->name, "__markers_strings") ||
2405 starts_with(ss->name, "__bug_table") ||
2406 (mode("keep-helper") && starts_with(ss->name, "__ex_table")))
2407 return SS_TYPE_RODATA;
2409 if (starts_with(ss->name, ".bss"))
2410 return SS_TYPE_DATA;
2412 /* Ignore .data.percpu sections */
2413 if (starts_with(ss->name, ".data.percpu") ||
2414 starts_with(ss->name, ".kernel.data.percpu"))
2415 return SS_TYPE_IGNORED;
2416 if (starts_with(ss->name, ".data") ||
2417 starts_with(ss->name, ".kernel.data") ||
2418 starts_with(ss->name, ".devinit.data") ||
2419 starts_with(ss->name, ".cpuinit.data") ||
2420 starts_with(ss->name, ".meminit.data") ||
2421 starts_with(ss->name, ".devexit.data") ||
2422 starts_with(ss->name, ".memexit.data") ||
2423 starts_with(ss->name, ".cpuexit.data") ||
2424 starts_with(ss->name, ".ref.data") ||
2425 starts_with(ss->name, "__markers"))
2426 return SS_TYPE_DATA;
2428 /* We replace all the ksymtab strings, so delete them */
2429 if (strcmp(ss->name, "__ksymtab_strings") == 0)
2430 return SS_TYPE_STRING;
2431 if (starts_with(ss->name, "__ksymtab"))
2432 return SS_TYPE_EXPORT;
2433 if (starts_with(ss->name, "__kcrctab"))
2434 return SS_TYPE_SPECIAL;
2436 if (is_table_section(ss->name, true))
2437 return SS_TYPE_SPECIAL;
2439 if (starts_with(ss->name, ".ARM."))
2440 return SS_TYPE_SPECIAL;
2442 if (starts_with(ss->name, ".note"))
2443 return SS_TYPE_IGNORED;
2444 if (starts_with(ss->name, ".comment"))
2445 return SS_TYPE_IGNORED;
2446 if (starts_with(ss->name, "__param"))
2447 return SS_TYPE_IGNORED;
2448 if (starts_with(ss->name, ".exitcall.exit"))
2449 return SS_TYPE_IGNORED;
2450 if (starts_with(ss->name, ".modinfo"))
2451 return SS_TYPE_IGNORED;
2453 return SS_TYPE_UNKNOWN;
2456 void initialize_supersect_types(struct superbfd *sbfd)
2458 asection *sect;
2459 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2460 struct supersect *ss = fetch_supersect(sbfd, sect);
2461 ss->type = supersect_type(ss);
2462 ss->orig_type = ss->type;
2463 if (ss->type == SS_TYPE_UNKNOWN) {
2464 err(sbfd, "Unknown section type: %s\n", ss->name);
2465 DIE;
2470 static void init_label_map(struct superbfd *sbfd)
2472 struct label_map *map;
2474 vec_init(&sbfd->maps);
2475 init_csyms(sbfd);
2476 init_callers(sbfd);
2478 struct symbol_hash csyms;
2479 symbol_hash_init(&csyms);
2481 asymbol **symp;
2482 for (symp = sbfd->syms.data;
2483 symp < sbfd->syms.data + sbfd->syms.size; symp++) {
2484 asymbol *csym = canonical_symbol(sbfd, *symp);
2485 if (csym == NULL)
2486 continue;
2487 char *key = strprintf("%p", csym);
2488 asymbol **csymp = symbol_hash_lookup(&csyms, key, TRUE);
2489 free(key);
2490 if (*csymp != NULL)
2491 continue;
2492 *csymp = csym;
2494 map = vec_grow(&sbfd->maps, 1);
2495 map->csym = csym;
2496 map->count = 0;
2497 map->label = symbol_label(sbfd, csym);
2500 struct label_mapp_hash label_maps;
2501 label_mapp_hash_init(&label_maps);
2502 for (map = sbfd->maps.data;
2503 map < sbfd->maps.data + sbfd->maps.size; map++) {
2504 struct label_map **mapp =
2505 label_mapp_hash_lookup(&label_maps, map->label, TRUE);
2506 if (*mapp == NULL) {
2507 *mapp = map;
2508 continue;
2511 struct label_map *first_map = *mapp;
2512 if (first_map->count == 0)
2513 first_map->label = strprintf("%s~%d", map->label, 0);
2514 map->label = strprintf("%s~%d", map->label, ++first_map->count);
2517 label_mapp_hash_init(&sbfd->maps_hash);
2518 for (map = sbfd->maps.data;
2519 map < sbfd->maps.data + sbfd->maps.size; map++) {
2520 char *key = strprintf("%p", map->csym);
2521 struct label_map **mapp =
2522 label_mapp_hash_lookup(&sbfd->maps_hash, key, TRUE);
2523 free(key);
2524 *mapp = map;
2525 map->orig_label = map->label;
2529 static const char *label_lookup(struct superbfd *sbfd, asymbol *sym)
2531 asymbol *csym = canonical_symbol(sbfd, sym);
2532 char *key = strprintf("%p", csym);
2533 struct label_map **mapp =
2534 label_mapp_hash_lookup(&sbfd->maps_hash, key, FALSE);
2535 free(key);
2536 if (mapp == NULL)
2537 DIE;
2538 return (*mapp)->label;
2541 static void print_label_changes(struct superbfd *sbfd)
2543 asection *sect;
2544 struct span *span;
2545 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2546 struct supersect *ss = fetch_supersect(sbfd, sect);
2547 for (span = ss->spans.data;
2548 span < ss->spans.data + ss->spans.size; span++) {
2549 if (strcmp(span->label, span->orig_label) != 0)
2550 debug1(sbfd, "Label change: %s -> %s\n",
2551 span->label, span->orig_label);
2556 static void label_map_set(struct superbfd *sbfd, const char *oldlabel,
2557 const char *label)
2559 struct label_map *map;
2560 for (map = sbfd->maps.data;
2561 map < sbfd->maps.data + sbfd->maps.size; map++) {
2562 if (strcmp(map->orig_label, oldlabel) == 0) {
2563 if (strcmp(map->orig_label, map->label) != 0 &&
2564 strcmp(map->label, label) != 0)
2565 DIE;
2566 map->label = label;
2567 return;
2570 DIE;
2573 static void change_initial_label(struct span *span, const char *label)
2575 struct superbfd *sbfd = span->ss->parent;
2576 span->label = label;
2577 span->orig_label = label;
2578 if (span->symbol) {
2579 asymbol *csym = canonical_symbol(sbfd, span->symbol);
2580 char *key = strprintf("%p", csym);
2581 struct label_map **mapp =
2582 label_mapp_hash_lookup(&sbfd->maps_hash, key, FALSE);
2583 free(key);
2584 assert(mapp);
2585 (*mapp)->label = span->label;
2586 (*mapp)->orig_label = span->orig_label;
2587 span->symbol = NULL;
2591 static void init_callers(struct superbfd *sbfd)
2593 string_hash_init(&sbfd->callers);
2594 asection *sect;
2595 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2596 struct supersect *ss = fetch_supersect(sbfd, sect);
2597 arelent **relocp;
2598 for (relocp = ss->relocs.data;
2599 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
2600 asymbol *sym = *(*relocp)->sym_ptr_ptr;
2601 unsigned long val =
2602 sym->value + get_reloc_offset(ss, *relocp, true);
2603 char *key = strprintf("%s+%lx", sym->section->name,
2604 val);
2605 const char **ret = string_hash_lookup(&sbfd->callers,
2606 key, TRUE);
2607 free(key);
2608 asymbol *csym = canonical_symbol(sbfd, sect->symbol);
2609 if (*ret != NULL)
2610 *ret = "*multiple_callers*";
2611 else if (static_local_symbol(sbfd, csym))
2612 *ret = static_local_symbol(sbfd, csym);
2613 else
2614 *ret = sect->name;
2619 static const char *find_caller(struct supersect *ss, asymbol *sym)
2621 char *key = strprintf("%s+%lx", sym->section->name,
2622 (unsigned long)sym->value);
2623 const char **ret = string_hash_lookup(&ss->parent->callers, key, FALSE);
2624 free(key);
2626 if (ret == NULL)
2627 return "*no_caller*";
2628 return *ret;
2631 static void init_csyms(struct superbfd *sbfd)
2633 asymbolpp_hash_init(&sbfd->csyms);
2635 asymbol **symp;
2636 for (symp = sbfd->syms.data; symp < sbfd->syms.data + sbfd->syms.size;
2637 symp++) {
2638 asymbol *sym = *symp;
2639 if ((sym->flags & BSF_DEBUGGING) != 0)
2640 continue;
2641 char *key = strprintf("%s+%lx", sym->section->name,
2642 (unsigned long)sym->value);
2643 asymbol ***csympp = asymbolpp_hash_lookup(&sbfd->csyms, key,
2644 TRUE);
2645 free(key);
2646 if (*csympp == NULL) {
2647 *csympp = symp;
2648 continue;
2650 asymbol *csym = **csympp;
2651 if ((csym->flags & BSF_GLOBAL) != 0)
2652 continue;
2653 if ((sym->flags & BSF_GLOBAL) != 0)
2654 *csympp = symp;
2658 static asymbol **symbolp_scan(struct supersect *ss, bfd_vma value)
2660 char *key = strprintf("%s+%lx", ss->name, (unsigned long)value);
2661 asymbol ***csympp =
2662 asymbolpp_hash_lookup(&ss->parent->csyms, key, FALSE);
2663 free(key);
2664 if (csympp != NULL)
2665 return *csympp;
2667 /* For section symbols of sections containing no symbols, return the
2668 section symbol that relocations are generated against */
2669 if (value == 0)
2670 return &ss->symbol;
2671 return NULL;
2674 static asymbol **canonical_symbolp(struct superbfd *sbfd, asymbol *sym)
2676 if (bfd_is_const_section(sym->section)) {
2677 asymbol **csymp;
2678 for (csymp = sbfd->syms.data;
2679 csymp < sbfd->syms.data + sbfd->syms.size; csymp++) {
2680 if (sym == *csymp)
2681 return csymp;
2683 return NULL;
2685 return symbolp_scan(fetch_supersect(sbfd, sym->section), sym->value);
2688 static asymbol *canonical_symbol(struct superbfd *sbfd, asymbol *sym)
2690 if (bfd_is_const_section(sym->section))
2691 return sym;
2692 asymbol **symp = canonical_symbolp(sbfd, sym);
2693 return symp != NULL ? *symp : NULL;
2696 static char *static_local_symbol(struct superbfd *sbfd, asymbol *sym)
2698 struct supersect *ss = fetch_supersect(sbfd, sym->section);
2699 if ((sym->flags & BSF_LOCAL) == 0 || (sym->flags & BSF_OBJECT) == 0)
2700 return NULL;
2701 char *dot = strrchr(sym->name, '.');
2702 if (dot == NULL || dot[1 + strspn(dot + 1, "0123546789")] != '\0')
2703 return NULL;
2704 char *basename = strndup(sym->name, dot - sym->name);
2706 /* Handle C.123.12345 symbols */
2707 dot = strrchr(basename, '.');
2708 if (dot != NULL && dot[1 + strspn(dot + 1, "0123546789")] == '\0')
2709 basename = strndup(basename, dot - basename);
2710 const char *caller;
2711 if (strcmp(basename, "__func__") == 0 ||
2712 strcmp(basename, "__PRETTY_FUNCTION__") == 0)
2713 caller = (const char *)ss->contents.data + sym->value;
2714 else
2715 caller = find_caller(ss, sym);
2716 return strprintf("%s<%s>", basename, caller);
2719 static char *symbol_label(struct superbfd *sbfd, asymbol *sym)
2721 const char *filename = sbfd->abfd->filename;
2722 char *c = strstr(filename, ".KSPLICE");
2723 int flen = (c == NULL ? strlen(filename) : c - filename);
2725 char *label;
2726 if (bfd_is_und_section(sym->section) || (sym->flags & BSF_GLOBAL) != 0) {
2727 label = strdup(sym->name);
2728 } else if (bfd_is_const_section(sym->section)) {
2729 label = strprintf("%s<%.*s>", sym->name, flen, filename);
2730 } else {
2731 asymbol *gsym = canonical_symbol(sbfd, sym);
2733 if (gsym == NULL)
2734 label = strprintf("%s+%lx<%.*s>",
2735 sym->section->name,
2736 (unsigned long)sym->value,
2737 flen, filename);
2738 else if ((gsym->flags & BSF_GLOBAL) != 0)
2739 label = strdup(gsym->name);
2740 else if (static_local_symbol(sbfd, gsym))
2741 label = strprintf("%s+%lx<%.*s>",
2742 static_local_symbol(sbfd, gsym),
2743 (unsigned long)sym->value,
2744 flen, filename);
2745 else
2746 label = strprintf("%s<%.*s>",
2747 gsym->name, flen, filename);
2750 return label;
2753 static void keep_span(struct span *span)
2755 span->keep = true;
2756 span->ss->keep = true;
2759 static struct span *new_span(struct supersect *ss, bfd_vma start, bfd_vma size)
2761 struct span *span = vec_grow(&ss->spans, 1);
2762 span->size = size;
2763 span->contents_size = size;
2764 span->start = start;
2765 span->ss = ss;
2766 span->keep = true;
2767 span->new = false;
2768 span->patch = false;
2769 span->bugpatch = false;
2770 span->datapatch = false;
2771 span->precallable = starts_with(ss->name, ".ksplice_call_pre_apply") ||
2772 starts_with(ss->name, ".ksplice_call_check_apply") ||
2773 starts_with(ss->name, ".ksplice_call_fail_apply") ||
2774 starts_with(ss->name, ".ksplice_call_post_remove");
2775 span->match = NULL;
2776 span->shift = 0;
2777 asymbol **symp = symbolp_scan(ss, span->start);
2778 if (symp != NULL) {
2779 span->symbol = *symp;
2780 span->label = label_lookup(ss->parent, span->symbol);
2781 } else {
2782 span->symbol = NULL;
2783 const char *label = label_lookup(ss->parent, ss->symbol);
2784 if (span->start != 0)
2785 span->label = strprintf("%s<span:%lx>", label,
2786 (unsigned long)span->start);
2787 else
2788 span->label = label;
2790 span->orig_label = span->label;
2791 return span;
2794 static void initialize_string_spans(struct supersect *ss)
2796 const char *str;
2797 for (str = ss->contents.data;
2798 (void *)str < ss->contents.data + ss->contents.size;) {
2799 bfd_vma start = (unsigned long)str -
2800 (unsigned long)ss->contents.data;
2801 bfd_vma size = strlen(str) + 1;
2802 bfd_vma contents_size = size;
2803 while ((start + size) % (1 << ss->alignment) != 0 &&
2804 start + size < ss->contents.size) {
2805 /* Some string sections, like __ksymtab_strings, only
2806 align some strings with the declared alignment */
2807 if (str[size] != '\0')
2808 break;
2809 size++;
2811 struct span *span = new_span(ss, start, size);
2812 span->contents_size = contents_size;
2813 str += size;
2817 static int compare_ulongs(const void *va, const void *vb)
2819 const unsigned long *a = va, *b = vb;
2820 return *a - *b;
2823 static void initialize_table_spans(struct superbfd *sbfd,
2824 struct table_section *s)
2826 asection *isection = bfd_get_section_by_name(sbfd->abfd, s->sect);
2827 if (isection == NULL)
2828 return;
2829 struct supersect *ss = fetch_supersect(sbfd, isection);
2830 if (ss->alignment < ffs(s->entry_align) - 1)
2831 ss->alignment = ffs(s->entry_align) - 1;
2833 asection *other_sect = NULL;
2834 if (s->other_sect != NULL)
2835 other_sect = bfd_get_section_by_name(sbfd->abfd, s->other_sect);
2836 struct supersect *other_ss = NULL;
2837 if (other_sect != NULL)
2838 other_ss = fetch_supersect(sbfd, other_sect);
2840 asection *crc_sect = NULL;
2841 if (s->crc_sect != NULL)
2842 crc_sect = bfd_get_section_by_name(sbfd->abfd, s->crc_sect);
2843 struct supersect *crc_ss = NULL;
2844 if (crc_sect != NULL)
2845 crc_ss = fetch_supersect(sbfd, crc_sect);
2847 struct ulong_vec offsets;
2848 vec_init(&offsets);
2850 void *entry;
2851 for (entry = ss->contents.data;
2852 entry < ss->contents.data + ss->contents.size;
2853 entry += s->entry_size) {
2854 struct span *span = new_span(ss, addr_offset(ss, entry),
2855 s->entry_size);
2856 if (s->entry_contents_size != 0)
2857 span->contents_size = s->entry_contents_size;
2858 if ((span->symbol == NULL ||
2859 (span->symbol->flags & BSF_SECTION_SYM) != 0) &&
2860 s->has_addr) {
2861 arelent *reloc = find_reloc(ss, entry + s->addr_offset);
2862 assert(reloc);
2863 struct span *target_span = reloc_target_span(ss, reloc);
2864 assert(target_span);
2865 asymbol *sym = *reloc->sym_ptr_ptr;
2866 unsigned long val = get_reloc_offset(ss, reloc, true) +
2867 sym->value - (target_span->start +
2868 target_span->shift);
2869 char *label = strprintf("%s<target:%s+%lx>", ss->name,
2870 target_span->label, val);
2871 change_initial_label(span, label);
2874 if (other_sect != NULL) {
2875 asymbol *sym;
2876 bfd_vma offset = read_reloc(ss, entry + s->other_offset,
2877 sizeof(void *), &sym);
2878 if (sym->section == other_sect) {
2879 assert(offset >= 0 &&
2880 offset < other_ss->contents.size);
2881 *vec_grow(&offsets, 1) = offset;
2885 if (crc_sect != NULL)
2886 new_span(crc_ss, addr_offset(ss, entry) / s->entry_size
2887 * s->crc_size, s->crc_size);
2889 if (ss->type == SS_TYPE_EXPORT) {
2890 const char *symname = read_string(ss, entry +
2891 s->other_offset);
2892 char *label = strprintf("%s:%s", ss->name, symname);
2893 change_initial_label(span, label);
2897 if (other_sect == NULL)
2898 return;
2900 *vec_grow(&offsets, 1) = 0;
2901 qsort(offsets.data, offsets.size, sizeof(*offsets.data),
2902 compare_ulongs);
2903 *vec_grow(&offsets, 1) = other_ss->contents.size;
2905 unsigned long *off;
2906 for (off = offsets.data; off < offsets.data + offsets.size - 1; off++) {
2907 if (*off != *(off + 1))
2908 new_span(other_ss, *off, *(off + 1) - *off);
2912 static void initialize_table_section_spans(struct superbfd *sbfd)
2914 struct supersect *tables_ss =
2915 fetch_supersect(offsets_sbfd,
2916 bfd_get_section_by_name(offsets_sbfd->abfd,
2917 ".ksplice_table_sections"));
2918 const struct table_section *ts;
2919 struct table_section s;
2920 for (ts = tables_ss->contents.data;
2921 (void *)ts < tables_ss->contents.data + tables_ss->contents.size;
2922 ts++) {
2923 s = *ts;
2924 s.sect = read_string(tables_ss, &ts->sect);
2925 s.other_sect = read_string(tables_ss, &ts->other_sect);
2926 s.crc_sect = read_string(tables_ss, &ts->crc_sect);
2927 initialize_table_spans(sbfd, &s);
2931 static void initialize_ksplice_call_spans(struct supersect *ss)
2933 arelent **relocp;
2934 for (relocp = ss->relocs.data;
2935 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
2936 arelent *reloc = *relocp;
2937 new_span(ss, reloc->address, bfd_get_reloc_size(reloc->howto));
2938 /* the span labels should already be unique */
2942 static void initialize_spans(struct superbfd *sbfd)
2944 asection *sect;
2945 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2946 if (is_table_section(sect->name, true) && mode("keep"))
2947 continue;
2949 struct supersect *ss = fetch_supersect(sbfd, sect);
2950 if (ss->type == SS_TYPE_STRING)
2951 initialize_string_spans(ss);
2952 else if (ss->type == SS_TYPE_KSPLICE_CALL)
2953 initialize_ksplice_call_spans(ss);
2954 else
2955 new_span(ss, 0, ss->contents.size);
2957 if (mode("keep"))
2958 initialize_table_section_spans(sbfd);
2961 struct span *reloc_target_span(struct supersect *ss, arelent *reloc)
2963 asymbol *sym_ptr = *reloc->sym_ptr_ptr;
2964 if (bfd_is_const_section(sym_ptr->section))
2965 return NULL;
2967 bfd_vma addend = get_reloc_offset(ss, reloc, true) + sym_ptr->value;
2968 struct supersect *sym_ss =
2969 fetch_supersect(ss->parent, sym_ptr->section);
2970 struct span *span, *target_span = sym_ss->spans.data;
2971 for (span = sym_ss->spans.data;
2972 span < sym_ss->spans.data + sym_ss->spans.size; span++) {
2973 if (addend >= span->start && addend < span->start + span->size)
2974 target_span = span;
2976 return target_span;
2979 struct span *find_span(struct supersect *ss, bfd_size_type address)
2981 struct span *span;
2982 for (span = ss->spans.data; span < ss->spans.data + ss->spans.size;
2983 span++) {
2984 if (address >= span->start &&
2985 address < span->start + span->size)
2986 return span;
2988 /* Deal with empty BSS sections */
2989 if (ss->contents.size == 0 && ss->spans.size > 0)
2990 return ss->spans.data;
2991 return NULL;
2994 void compute_span_shifts(struct superbfd *sbfd)
2996 asection *sect;
2997 struct span *span;
2998 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2999 struct supersect *ss = fetch_supersect(sbfd, sect);
3000 if (!ss->keep)
3001 continue;
3002 bfd_size_type offset = 0;
3003 for (span = ss->spans.data;
3004 span < ss->spans.data + ss->spans.size; span++) {
3005 if (!span->keep)
3006 continue;
3007 span->shift = offset - span->start;
3008 offset += span->size;
3013 void remove_unkept_spans(struct superbfd *sbfd)
3015 asection *sect;
3016 struct span *span;
3017 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
3018 struct supersect *ss = fetch_supersect(sbfd, sect);
3019 delete_obsolete_relocs(ss);
3020 struct arelentp_vec orig_relocs;
3021 vec_move(&orig_relocs, &ss->relocs);
3022 arelent **relocp, *reloc;
3023 for (relocp = orig_relocs.data;
3024 relocp < orig_relocs.data + orig_relocs.size; relocp++) {
3025 reloc = *relocp;
3026 asymbol *sym = *reloc->sym_ptr_ptr;
3027 span = reloc_target_span(ss, reloc);
3028 if ((span != NULL && span->keep && span->shift == 0) ||
3029 bfd_is_const_section(sym->section)) {
3030 *vec_grow(&ss->relocs, 1) = reloc;
3031 continue;
3033 struct supersect *sym_ss =
3034 fetch_supersect(sbfd, sym->section);
3035 if (span != NULL && (sym->flags & BSF_SECTION_SYM) == 0
3036 && find_span(sym_ss, sym->value) != span) {
3037 err(sbfd, "Spans for symbol %s and relocation "
3038 "target do not match in sect %s\n",
3039 sym->name, sym_ss->name);
3040 DIE;
3042 if (span != NULL && span->keep) {
3043 arelent *new_reloc = malloc(sizeof(*new_reloc));
3044 *new_reloc = *reloc;
3045 new_reloc->addend =
3046 get_reloc_offset(ss, reloc, false);
3047 new_reloc->addend += span->shift;
3048 *vec_grow(&ss->new_relocs, 1) = new_reloc;
3053 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
3054 struct supersect *ss = fetch_supersect(sbfd, sect), orig_ss;
3055 if (!ss->keep)
3056 continue;
3057 supersect_move(&orig_ss, ss);
3058 vec_init(&ss->spans);
3059 for (span = orig_ss.spans.data;
3060 span < orig_ss.spans.data + orig_ss.spans.size; span++) {
3061 if (!span->keep)
3062 continue;
3063 struct span *new_span = vec_grow(&ss->spans, 1);
3064 *new_span = *span;
3065 new_span->start = span->start + span->shift;
3066 new_span->shift = 0;
3067 sect_copy(ss, sect_do_grow(ss, 1, span->size, 1),
3068 &orig_ss, orig_ss.contents.data + span->start,
3069 span->size);
3074 static void init_objmanip_superbfd(struct superbfd *sbfd)
3076 init_label_map(sbfd);
3077 initialize_supersect_types(sbfd);
3078 initialize_spans(sbfd);
3079 load_options(sbfd);
3082 void mangle_section_name(struct superbfd *sbfd, const char *name)
3084 asection *sect = bfd_get_section_by_name(sbfd->abfd, name);
3085 if (sect == NULL)
3086 return;
3087 struct supersect *ss = fetch_supersect(sbfd, sect);
3088 ss->name = strprintf(".ksplice_pre.%s", ss->name);
3091 static void write_bugline_patches(struct superbfd *sbfd)
3093 const struct table_section *ts = get_table_section("__bug_table");
3094 asection *sect = bfd_get_section_by_name(sbfd->abfd, "__bug_table");
3095 if (sect == NULL)
3096 return;
3097 struct supersect *ss = fetch_supersect(sbfd, sect);
3098 assert(ts != NULL);
3100 void *entry;
3101 for (entry = ss->contents.data;
3102 entry < ss->contents.data + ss->contents.size;
3103 entry += ts->entry_size) {
3104 struct span *span = find_span(ss, addr_offset(ss, entry));
3105 assert(span != NULL);
3106 if (!span->bugpatch)
3107 continue;
3108 arelent *reloc = find_reloc(ss, entry + ts->addr_offset);
3109 assert(reloc != NULL);
3110 asymbol *sym = *reloc->sym_ptr_ptr;
3111 assert(!bfd_is_const_section(sym->section));
3113 struct supersect *kpatch_ss =
3114 make_section(sbfd, ".ksplice_patches%s",
3115 sym->section->name);
3116 struct ksplice_patch *kpatch =
3117 sect_grow(kpatch_ss, 1, struct ksplice_patch);
3118 write_ksplice_patch_reloc
3119 (kpatch_ss, sym->section->name, &kpatch->oldaddr,
3120 sizeof(kpatch->oldaddr), span->label, ts->other_offset);
3122 unsigned short *line =
3123 write_patch_storage(kpatch_ss, kpatch, sizeof(*line), NULL);
3124 *line = *(unsigned short *)(entry + ts->other_offset);
3125 kpatch->type = KSPLICE_PATCH_BUGLINE;
3129 void *write_patch_storage(struct supersect *ss, struct ksplice_patch *kpatch,
3130 size_t size, struct supersect **data_ssp)
3132 struct supersect *data_ss = make_section(ss->parent,
3133 ".ksplice_patch_data");
3134 char *saved = sect_do_grow(data_ss, 1, size, 1);
3135 write_reloc(ss, &kpatch->saved, &data_ss->symbol,
3136 addr_offset(data_ss, saved));
3137 char *data = sect_do_grow(data_ss, 1, size, 1);
3138 write_reloc(ss, &kpatch->contents, &data_ss->symbol,
3139 addr_offset(data_ss, data));
3140 kpatch->size = size;
3141 if (data_ssp != NULL)
3142 *data_ssp = data_ss;
3143 return data;