Add ksplice-create --git option to build Ksplice updates from Git commits.
[ksplice.git] / objmanip.c
blob3195a540b7875eba1117f2f110b7db2d9957b72c
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->size != old_span->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->size == old_span->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->size != new_span->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->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->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->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->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 asymbol *sym;
1842 struct span *span = find_span(ss, addr_offset(ss, entry));
1843 assert(span != NULL);
1845 if (s->has_addr) {
1846 read_reloc(ss, entry + s->addr_offset,
1847 sizeof(void *), &sym);
1848 struct supersect *sym_ss =
1849 fetch_supersect(sbfd, sym->section);
1850 if (sym_ss->keep)
1851 keep_span(span);
1854 if (s->other_sect != NULL) {
1855 arelent *reloc =
1856 find_reloc(ss, entry + s->other_offset);
1857 assert(reloc != NULL);
1858 struct span *sym_span = reloc_target_span(ss, reloc);
1859 if (span->keep)
1860 keep_span(sym_span);
1863 if (s->crc_sect != NULL) {
1864 asection *crc_sect =
1865 bfd_get_section_by_name(sbfd->abfd, s->crc_sect);
1866 struct supersect *crc_ss =
1867 fetch_supersect(sbfd, crc_sect);
1868 struct span *crc_span =
1869 find_span(crc_ss, addr_offset(ss, entry) /
1870 s->entry_size * s->crc_size);
1871 assert(crc_span);
1872 if (span->keep)
1873 keep_span(crc_span);
1878 void mark_precallable_spans(struct superbfd *sbfd)
1880 asection *sect;
1881 struct supersect *ss, *sym_ss;
1882 struct span *address_span, *target_span;
1883 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
1884 ss = fetch_supersect(sbfd, sect);
1885 arelent **relocp;
1886 if (ss->type == SS_TYPE_SPECIAL)
1887 continue;
1888 for (relocp = ss->relocs.data;
1889 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
1890 asymbol *sym = *(*relocp)->sym_ptr_ptr;
1891 address_span = find_span(ss, (*relocp)->address);
1892 if (!address_span->precallable)
1893 continue;
1894 target_span = reloc_target_span(ss, *relocp);
1895 if (target_span == NULL || target_span->keep)
1896 continue;
1897 sym_ss = fetch_supersect(sbfd, sym->section);
1898 if (sym_ss->type == SS_TYPE_IGNORED)
1899 continue;
1900 target_span->precallable = true;
1901 changed = true;
1906 void keep_referenced_sections(struct superbfd *sbfd)
1908 asection *sect;
1909 struct supersect *ss, *sym_ss;
1910 struct span *address_span, *target_span;
1911 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
1912 ss = fetch_supersect(sbfd, sect);
1913 arelent **relocp;
1914 if (ss->type == SS_TYPE_SPECIAL)
1915 continue;
1916 for (relocp = ss->relocs.data;
1917 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
1918 asymbol *sym = *(*relocp)->sym_ptr_ptr;
1919 address_span = find_span(ss, (*relocp)->address);
1920 if (!address_span->keep)
1921 continue;
1922 target_span = reloc_target_span(ss, *relocp);
1923 if (target_span == NULL || target_span->keep)
1924 continue;
1925 sym_ss = fetch_supersect(sbfd, sym->section);
1926 if (sym_ss->type == SS_TYPE_IGNORED)
1927 continue;
1928 keep_span(target_span);
1929 changed = true;
1934 void copy_symbols(struct asymbolp_vec *osyms, struct asymbolpp_vec *isyms)
1936 asymbol ***sympp;
1937 for (sympp = isyms->data; sympp < isyms->data + isyms->size; sympp++)
1938 *vec_grow(osyms, 1) = **sympp;
1941 /* Modified function from GNU Binutils objcopy.c */
1942 bfd_boolean copy_object(bfd *ibfd, bfd *obfd)
1944 assert(bfd_set_format(obfd, bfd_get_format(ibfd)));
1946 bfd_vma start = bfd_get_start_address(ibfd);
1948 flagword flags = bfd_get_file_flags(ibfd);
1949 flags &= bfd_applicable_file_flags(obfd);
1951 assert(bfd_set_start_address(obfd, start)
1952 && bfd_set_file_flags(obfd, flags));
1954 enum bfd_architecture iarch = bfd_get_arch(ibfd);
1955 unsigned int imach = bfd_get_mach(ibfd);
1956 assert(bfd_set_arch_mach(obfd, iarch, imach));
1957 assert(bfd_set_format(obfd, bfd_get_format(ibfd)));
1959 /* BFD mandates that all output sections be created and sizes set before
1960 any output is done. Thus, we traverse all sections multiple times. */
1961 bfd_map_over_sections(ibfd, setup_section, obfd);
1963 struct supersect *new_supersects = fetch_superbfd(ibfd)->new_supersects;
1964 struct supersect *ss;
1965 for (ss = new_supersects; ss != NULL; ss = ss->next)
1966 setup_new_section(obfd, ss);
1968 /* Mark symbols used in output relocations so that they
1969 are kept, even if they are local labels or static symbols.
1971 Note we iterate over the input sections examining their
1972 relocations since the relocations for the output sections
1973 haven't been set yet. mark_symbols_used_in_relocations will
1974 ignore input sections which have no corresponding output
1975 section. */
1977 bfd_map_over_sections(ibfd, mark_symbols_used_in_relocations, NULL);
1978 for (ss = new_supersects; ss != NULL; ss = ss->next)
1979 ss_mark_symbols_used_in_relocations(ss);
1980 struct asymbolp_vec osyms;
1981 vec_init(&osyms);
1982 filter_symbols(ibfd, obfd, &osyms, &fetch_superbfd(ibfd)->syms);
1983 copy_symbols(&osyms, &fetch_superbfd(ibfd)->new_syms);
1985 bfd_set_symtab(obfd, osyms.data, osyms.size);
1987 /* This has to happen after the symbol table has been set. */
1988 bfd_map_over_sections(obfd, write_section, NULL);
1990 /* Allow the BFD backend to copy any private data it understands
1991 from the input BFD to the output BFD. This is done last to
1992 permit the routine to look at the filtered symbol table, which is
1993 important for the ECOFF code at least. */
1994 assert(bfd_copy_private_bfd_data(ibfd, obfd));
1996 return TRUE;
1999 /* Modified function from GNU Binutils objcopy.c */
2000 void setup_section(bfd *ibfd, asection *isection, void *obfdarg)
2002 struct superbfd *isbfd = fetch_superbfd(ibfd);
2003 struct supersect *ss = fetch_supersect(isbfd, isection);
2004 bfd *obfd = obfdarg;
2005 bfd_vma vma;
2007 if (!ss->keep)
2008 return;
2010 asection *osection = bfd_make_section_anyway(obfd, ss->name);
2011 assert(osection != NULL);
2013 osection->userdata = ss;
2014 bfd_set_section_flags(obfd, osection, ss->flags);
2015 ss->symbol = osection->symbol;
2016 assert(bfd_set_section_size(obfd, osection, ss->contents.size));
2018 vma = bfd_section_vma(ibfd, isection);
2019 assert(bfd_set_section_vma(obfd, osection, vma));
2021 osection->lma = isection->lma;
2022 assert(bfd_set_section_alignment(obfd, osection, ss->alignment));
2023 osection->entsize = ss->entsize;
2024 osection->output_section = osection;
2025 osection->output_offset = 0;
2026 isection->output_section = osection;
2027 isection->output_offset = 0;
2028 return;
2031 void setup_new_section(bfd *obfd, struct supersect *ss)
2033 asection *osection = bfd_make_section_anyway(obfd, ss->name);
2034 assert(osection != NULL);
2035 bfd_set_section_flags(obfd, osection, ss->flags);
2037 osection->userdata = ss;
2038 ss->symbol = osection->symbol;
2039 assert(bfd_set_section_size(obfd, osection, ss->contents.size));
2040 assert(bfd_set_section_vma(obfd, osection, 0));
2042 osection->lma = 0;
2043 assert(bfd_set_section_alignment(obfd, osection, ss->alignment));
2044 osection->entsize = ss->entsize;
2045 osection->output_section = osection;
2046 osection->output_offset = 0;
2049 static int compare_reloc_addresses(const void *aptr, const void *bptr)
2051 const arelent *const *a = aptr, *const *b = bptr;
2052 return (*a)->address - (*b)->address;
2055 static void delete_obsolete_relocs(struct supersect *ss)
2057 if (ss->new_relocs.size == 0)
2058 return;
2060 qsort(ss->relocs.data, ss->relocs.size, sizeof(*ss->relocs.data),
2061 compare_reloc_addresses);
2062 qsort(ss->new_relocs.data, ss->new_relocs.size,
2063 sizeof(*ss->new_relocs.data), compare_reloc_addresses);
2065 struct arelentp_vec orig_relocs;
2066 vec_move(&orig_relocs, &ss->relocs);
2068 arelent **relocp, **new_relocp = ss->new_relocs.data;
2069 for (relocp = orig_relocs.data;
2070 relocp < orig_relocs.data + orig_relocs.size; relocp++) {
2071 while (new_relocp < ss->new_relocs.data + ss->new_relocs.size &&
2072 (*new_relocp)->address < (*relocp)->address)
2073 new_relocp++;
2074 arelent *reloc = *relocp, *new_reloc = *new_relocp;
2075 if (new_relocp == ss->new_relocs.data + ss->new_relocs.size ||
2076 reloc->address != new_reloc->address)
2077 *vec_grow(&ss->relocs, 1) = reloc;
2081 void write_section(bfd *obfd, asection *osection, void *arg)
2083 struct supersect *ss = osection->userdata;
2085 if ((ss->flags & SEC_GROUP) != 0 || ss->contents.size == 0)
2086 return;
2088 delete_obsolete_relocs(ss);
2090 arelent **relocp;
2091 char *error_message;
2092 for (relocp = ss->new_relocs.data;
2093 relocp < ss->new_relocs.data + ss->new_relocs.size; relocp++) {
2094 bfd_vma val;
2095 if (bfd_get_arch(obfd) == bfd_arch_arm)
2096 val = osection->use_rela_p ? 0 : (*relocp)->addend;
2097 else
2098 val = 0;
2099 bfd_put(bfd_get_reloc_size((*relocp)->howto) * 8, obfd, val,
2100 ss->contents.data + (*relocp)->address);
2101 if (bfd_install_relocation(obfd, *relocp, ss->contents.data,
2102 0, osection, &error_message) !=
2103 bfd_reloc_ok) {
2104 err(ss->parent, "ksplice: error installing reloc: %s",
2105 error_message);
2106 DIE;
2109 memcpy(vec_grow(&ss->relocs, ss->new_relocs.size), ss->new_relocs.data,
2110 ss->new_relocs.size * sizeof(*ss->new_relocs.data));
2112 bfd_set_reloc(obfd, osection,
2113 ss->relocs.size == 0 ? NULL : ss->relocs.data,
2114 ss->relocs.size);
2116 if (ss->flags & SEC_HAS_CONTENTS)
2117 assert(bfd_set_section_contents
2118 (obfd, osection, ss->contents.data, 0,
2119 ss->contents.size));
2122 /* Modified function from GNU Binutils objcopy.c
2124 * Mark all the symbols which will be used in output relocations with
2125 * the BSF_KEEP flag so that those symbols will not be stripped.
2127 * Ignore relocations which will not appear in the output file.
2129 void mark_symbols_used_in_relocations(bfd *abfd, asection *isection,
2130 void *ignored)
2132 struct superbfd *sbfd = fetch_superbfd(abfd);
2133 if (isection->output_section == NULL)
2134 return;
2136 struct supersect *ss = fetch_supersect(sbfd, isection);
2137 ss_mark_symbols_used_in_relocations(ss);
2140 void ss_mark_symbols_used_in_relocations(struct supersect *ss)
2142 /* Examine each symbol used in a relocation. If it's not one of the
2143 special bfd section symbols, then mark it with BSF_KEEP. */
2144 arelent **relocp;
2145 for (relocp = ss->relocs.data;
2146 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
2147 asymbol *sym = *(*relocp)->sym_ptr_ptr;
2148 if (!(bfd_is_const_section(sym->section) &&
2149 sym == sym->section->symbol))
2150 sym->flags |= BSF_KEEP;
2152 for (relocp = ss->new_relocs.data;
2153 relocp < ss->new_relocs.data + ss->new_relocs.size; relocp++) {
2154 asymbol *sym = *(*relocp)->sym_ptr_ptr;
2155 if (!(bfd_is_const_section(sym->section) &&
2156 sym == sym->section->symbol))
2157 sym->flags |= BSF_KEEP;
2161 static bool deleted_table_section_symbol(bfd *abfd, asymbol *sym)
2163 struct superbfd *sbfd = fetch_superbfd(abfd);
2164 if (bfd_is_const_section(sym->section))
2165 return false;
2166 struct supersect *ss = fetch_supersect(sbfd, sym->section);
2168 asymbol **symp;
2169 for (symp = ss->syms.data; symp < ss->syms.data + ss->syms.size; symp++) {
2170 if (sym == *symp)
2171 break;
2173 return symp >= ss->syms.data + ss->syms.size &&
2174 (sym->flags & BSF_SECTION_SYM) == 0;
2177 void filter_symbols(bfd *ibfd, bfd *obfd, struct asymbolp_vec *osyms,
2178 struct asymbolp_vec *isyms)
2180 asymbol **symp;
2181 struct superbfd *sbfd = fetch_superbfd(ibfd);
2182 for (symp = isyms->data; symp < isyms->data + isyms->size; symp++) {
2183 asymbol *sym = *symp;
2184 struct supersect *sym_ss = NULL;
2185 struct span *sym_span = NULL;
2186 if (!bfd_is_const_section(sym->section)) {
2187 sym_ss = fetch_supersect(sbfd, sym->section);
2188 sym_span = find_span(sym_ss, sym->value);
2191 if (mode("keep") && (sym->flags & BSF_GLOBAL) != 0 &&
2192 !(mode("keep-primary") && sym_span != NULL &&
2193 sym_span->new))
2194 sym->flags = (sym->flags & ~BSF_GLOBAL) | BSF_LOCAL;
2196 if (mode("finalize") && (sym->flags & BSF_GLOBAL) != 0)
2197 sym->flags = (sym->flags & ~BSF_GLOBAL) | BSF_LOCAL;
2199 bool keep = bfd_is_const_section(sym->section) ||
2200 (sym_ss->keep && (sym->flags & BSF_SECTION_SYM) != 0) ||
2201 (sym_span != NULL && sym_span->keep);
2202 if (bfd_is_und_section(sym->section) &&
2203 (sym->flags & BSF_KEEP) == 0)
2204 keep = false;
2205 if (deleted_table_section_symbol(ibfd, sym))
2206 keep = false;
2208 if (mode("keep-helper") && sym_ss != NULL &&
2209 sym_ss->type == SS_TYPE_EXPORT)
2210 keep = false;
2212 if (keep) {
2213 if (sym_ss != NULL && !sym_ss->keep) {
2214 err(sbfd, "Kept symbol %s in unkept section "
2215 "%s\n", sym->name, sym->section->name);
2216 DIE;
2218 *vec_grow(osyms, 1) = sym;
2223 void read_str_set(struct str_vec *strs)
2225 char *buf = NULL;
2226 size_t n = 0;
2227 assert(getline(&buf, &n, stdin) >= 0);
2228 vec_init(strs);
2229 char *saveptr;
2230 while (1) {
2231 char *str = strtok_r(buf, " \n", &saveptr);
2232 buf = NULL;
2233 if (str == NULL)
2234 break;
2235 *vec_grow(strs, 1) = str;
2239 bool str_in_set(const char *str, const struct str_vec *strs)
2241 const char **strp;
2242 for (strp = strs->data; strp < strs->data + strs->size; strp++) {
2243 if (strcmp(str, *strp) == 0)
2244 return true;
2246 return false;
2249 bool is_table_section(const char *name, bool consider_other)
2251 struct supersect *tables_ss =
2252 fetch_supersect(offsets_sbfd,
2253 bfd_get_section_by_name(offsets_sbfd->abfd,
2254 ".ksplice_table_sections"));
2255 const struct table_section *ts;
2256 for (ts = tables_ss->contents.data;
2257 (void *)ts < tables_ss->contents.data + tables_ss->contents.size;
2258 ts++) {
2259 if (strcmp(name, read_string(tables_ss, &ts->sect)) == 0)
2260 return true;
2261 const char *osect_name = read_string(tables_ss,
2262 &ts->other_sect);
2263 if (consider_other && osect_name != NULL &&
2264 strcmp(name, osect_name) == 0)
2265 return true;
2266 const char *crc_name = read_string(tables_ss, &ts->crc_sect);
2267 if (consider_other && crc_name != NULL &&
2268 strcmp(name, crc_name) == 0)
2269 return true;
2271 return false;
2274 const struct table_section *get_table_section(const char *name)
2276 struct supersect *tables_ss =
2277 fetch_supersect(offsets_sbfd,
2278 bfd_get_section_by_name(offsets_sbfd->abfd,
2279 ".ksplice_table_sections"));
2280 const struct table_section *ts;
2281 for (ts = tables_ss->contents.data;
2282 (void *)ts < tables_ss->contents.data + tables_ss->contents.size;
2283 ts++) {
2284 if (strcmp(name, read_string(tables_ss, &ts->sect)) == 0)
2285 return ts;
2287 return NULL;
2290 enum supersect_type supersect_type(struct supersect *ss)
2292 if (mode("finalize") &&
2293 strcmp(finalize_target, "vmlinux") == 0 &&
2294 (starts_with(ss->name, ".ksplice_relocs.exit") ||
2295 starts_with(ss->name, ".ksplice_sections.exit") ||
2296 starts_with(ss->name, ".ksplice_patches.exit")))
2297 return SS_TYPE_EXIT;
2298 if (starts_with(ss->name, ".ksplice_call"))
2299 return SS_TYPE_KSPLICE_CALL;
2300 if (starts_with(ss->name, ".ksplice_options"))
2301 return SS_TYPE_SPECIAL;
2302 if (starts_with(ss->name, ".ksplice"))
2303 return SS_TYPE_KSPLICE;
2305 if (starts_with(ss->name, ".init"))
2306 return SS_TYPE_IGNORED;
2307 if (starts_with(ss->name, ".security_initcall.init"))
2308 return SS_TYPE_IGNORED;
2309 if (starts_with(ss->name, ".con_initcall.init"))
2310 return SS_TYPE_IGNORED;
2311 if (starts_with(ss->name, ".x86cpuvendor.init"))
2312 return SS_TYPE_IGNORED;
2313 if (starts_with(ss->name, ".early_param.init"))
2314 return SS_TYPE_IGNORED;
2315 if (starts_with(ss->name, ".taglist.init"))
2316 return SS_TYPE_IGNORED;
2317 if (starts_with(ss->name, ".arch.info.init"))
2318 return SS_TYPE_IGNORED;
2319 if (starts_with(ss->name, ".proc.info.init"))
2320 return SS_TYPE_IGNORED;
2321 /* .pci_fixup_* sections really should be treated as global rodata
2322 referenced only from quirks.c */
2323 if (starts_with(ss->name, ".pci_fixup_"))
2324 return SS_TYPE_IGNORED;
2325 /* .builtin_fw sections are similar to .pci_fixup */
2326 if (starts_with(ss->name, ".builtin_fw"))
2327 return SS_TYPE_IGNORED;
2328 /* same for .tracedata */
2329 if (starts_with(ss->name, ".tracedata"))
2330 return SS_TYPE_IGNORED;
2331 if (starts_with(ss->name, ".debug"))
2332 return SS_TYPE_IGNORED;
2333 /* .eh_frame should probably be discarded, not ignored */
2334 if (starts_with(ss->name, ".eh_frame"))
2335 return SS_TYPE_IGNORED;
2336 if (config->ignore_devinit && starts_with(ss->name, ".devinit"))
2337 return SS_TYPE_IGNORED;
2338 if (config->ignore_meminit && starts_with(ss->name, ".meminit"))
2339 return SS_TYPE_IGNORED;
2340 if (config->ignore_cpuinit && starts_with(ss->name, ".cpuinit"))
2341 return SS_TYPE_IGNORED;
2342 if (config->ignore_devinit && starts_with(ss->name, ".devexit"))
2343 return SS_TYPE_IGNORED;
2344 if (config->ignore_meminit && starts_with(ss->name, ".memexit"))
2345 return SS_TYPE_IGNORED;
2346 if (config->ignore_cpuinit && starts_with(ss->name, ".cpuexit"))
2347 return SS_TYPE_IGNORED;
2348 if (starts_with(ss->name, ".vgetcpu_mode") ||
2349 starts_with(ss->name, ".jiffies") ||
2350 starts_with(ss->name, ".wall_jiffies") ||
2351 starts_with(ss->name, ".vxtime") ||
2352 starts_with(ss->name, ".sys_tz") ||
2353 starts_with(ss->name, ".sysctl_vsyscall") ||
2354 starts_with(ss->name, ".xtime") ||
2355 starts_with(ss->name, ".xtime_lock") ||
2356 starts_with(ss->name, ".vsyscall"))
2357 return SS_TYPE_IGNORED;
2358 if (starts_with(ss->name, ".vdso"))
2359 return SS_TYPE_IGNORED;
2361 if (starts_with(ss->name, ".exit.text"))
2362 return SS_TYPE_TEXT;
2363 if (starts_with(ss->name, ".exit.data"))
2364 return SS_TYPE_DATA;
2366 if (starts_with(ss->name, ".text") ||
2367 starts_with(ss->name, ".kernel.text") ||
2368 starts_with(ss->name, ".devinit.text") ||
2369 starts_with(ss->name, ".meminit.text") ||
2370 starts_with(ss->name, ".cpuinit.text") ||
2371 starts_with(ss->name, ".devexit.text") ||
2372 starts_with(ss->name, ".memexit.text") ||
2373 starts_with(ss->name, ".cpuexit.text") ||
2374 starts_with(ss->name, ".ref.text") ||
2375 starts_with(ss->name, ".spinlock.text") ||
2376 starts_with(ss->name, ".kprobes.text") ||
2377 starts_with(ss->name, ".sched.text") ||
2378 (mode("keep-helper") && starts_with(ss->name, ".fixup")))
2379 return SS_TYPE_TEXT;
2381 int n = -1;
2382 if (sscanf(ss->name, ".rodata.str%*u.%*u%n", &n) >= 0 &&
2383 n == strlen(ss->name))
2384 return ss->entsize == 1 ? SS_TYPE_STRING : SS_TYPE_RODATA;
2386 if (starts_with(ss->name, ".rodata") ||
2387 starts_with(ss->name, ".kernel.rodata") ||
2388 starts_with(ss->name, ".devinit.rodata") ||
2389 starts_with(ss->name, ".meminit.rodata") ||
2390 starts_with(ss->name, ".cpuinit.rodata") ||
2391 starts_with(ss->name, ".devexit.rodata") ||
2392 starts_with(ss->name, ".memexit.rodata") ||
2393 starts_with(ss->name, ".cpuexit.rodata") ||
2394 starts_with(ss->name, ".ref.rodata") ||
2395 starts_with(ss->name, "__markers_strings") ||
2396 starts_with(ss->name, "__bug_table") ||
2397 (mode("keep-helper") && starts_with(ss->name, "__ex_table")))
2398 return SS_TYPE_RODATA;
2400 if (starts_with(ss->name, ".bss"))
2401 return SS_TYPE_DATA;
2403 /* Ignore .data.percpu sections */
2404 if (starts_with(ss->name, ".data.percpu") ||
2405 starts_with(ss->name, ".kernel.data.percpu"))
2406 return SS_TYPE_IGNORED;
2407 if (starts_with(ss->name, ".data") ||
2408 starts_with(ss->name, ".kernel.data") ||
2409 starts_with(ss->name, ".devinit.data") ||
2410 starts_with(ss->name, ".cpuinit.data") ||
2411 starts_with(ss->name, ".meminit.data") ||
2412 starts_with(ss->name, ".devexit.data") ||
2413 starts_with(ss->name, ".memexit.data") ||
2414 starts_with(ss->name, ".cpuexit.data") ||
2415 starts_with(ss->name, ".ref.data") ||
2416 starts_with(ss->name, "__markers"))
2417 return SS_TYPE_DATA;
2419 /* We replace all the ksymtab strings, so delete them */
2420 if (strcmp(ss->name, "__ksymtab_strings") == 0)
2421 return SS_TYPE_STRING;
2422 if (starts_with(ss->name, "__ksymtab"))
2423 return SS_TYPE_EXPORT;
2424 if (starts_with(ss->name, "__kcrctab"))
2425 return SS_TYPE_SPECIAL;
2427 if (is_table_section(ss->name, true))
2428 return SS_TYPE_SPECIAL;
2430 if (starts_with(ss->name, ".ARM."))
2431 return SS_TYPE_SPECIAL;
2433 if (starts_with(ss->name, ".note"))
2434 return SS_TYPE_IGNORED;
2435 if (starts_with(ss->name, ".comment"))
2436 return SS_TYPE_IGNORED;
2437 if (starts_with(ss->name, "__param"))
2438 return SS_TYPE_IGNORED;
2439 if (starts_with(ss->name, ".exitcall.exit"))
2440 return SS_TYPE_IGNORED;
2441 if (starts_with(ss->name, ".modinfo"))
2442 return SS_TYPE_IGNORED;
2444 return SS_TYPE_UNKNOWN;
2447 void initialize_supersect_types(struct superbfd *sbfd)
2449 asection *sect;
2450 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2451 struct supersect *ss = fetch_supersect(sbfd, sect);
2452 ss->type = supersect_type(ss);
2453 ss->orig_type = ss->type;
2454 if (ss->type == SS_TYPE_UNKNOWN) {
2455 err(sbfd, "Unknown section type: %s\n", ss->name);
2456 DIE;
2461 static void init_label_map(struct superbfd *sbfd)
2463 struct label_map *map;
2465 vec_init(&sbfd->maps);
2466 init_csyms(sbfd);
2467 init_callers(sbfd);
2469 struct symbol_hash csyms;
2470 symbol_hash_init(&csyms);
2472 asymbol **symp;
2473 for (symp = sbfd->syms.data;
2474 symp < sbfd->syms.data + sbfd->syms.size; symp++) {
2475 asymbol *csym = canonical_symbol(sbfd, *symp);
2476 if (csym == NULL)
2477 continue;
2478 char *key = strprintf("%p", csym);
2479 asymbol **csymp = symbol_hash_lookup(&csyms, key, TRUE);
2480 free(key);
2481 if (*csymp != NULL)
2482 continue;
2483 *csymp = csym;
2485 map = vec_grow(&sbfd->maps, 1);
2486 map->csym = csym;
2487 map->count = 0;
2488 map->label = symbol_label(sbfd, csym);
2491 struct label_mapp_hash label_maps;
2492 label_mapp_hash_init(&label_maps);
2493 for (map = sbfd->maps.data;
2494 map < sbfd->maps.data + sbfd->maps.size; map++) {
2495 struct label_map **mapp =
2496 label_mapp_hash_lookup(&label_maps, map->label, TRUE);
2497 if (*mapp == NULL) {
2498 *mapp = map;
2499 continue;
2502 struct label_map *first_map = *mapp;
2503 if (first_map->count == 0)
2504 first_map->label = strprintf("%s~%d", map->label, 0);
2505 map->label = strprintf("%s~%d", map->label, ++first_map->count);
2508 label_mapp_hash_init(&sbfd->maps_hash);
2509 for (map = sbfd->maps.data;
2510 map < sbfd->maps.data + sbfd->maps.size; map++) {
2511 char *key = strprintf("%p", map->csym);
2512 struct label_map **mapp =
2513 label_mapp_hash_lookup(&sbfd->maps_hash, key, TRUE);
2514 free(key);
2515 *mapp = map;
2516 map->orig_label = map->label;
2520 static const char *label_lookup(struct superbfd *sbfd, asymbol *sym)
2522 asymbol *csym = canonical_symbol(sbfd, sym);
2523 char *key = strprintf("%p", csym);
2524 struct label_map **mapp =
2525 label_mapp_hash_lookup(&sbfd->maps_hash, key, FALSE);
2526 free(key);
2527 if (mapp == NULL)
2528 DIE;
2529 return (*mapp)->label;
2532 static void print_label_changes(struct superbfd *sbfd)
2534 asection *sect;
2535 struct span *span;
2536 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2537 struct supersect *ss = fetch_supersect(sbfd, sect);
2538 for (span = ss->spans.data;
2539 span < ss->spans.data + ss->spans.size; span++) {
2540 if (strcmp(span->label, span->orig_label) != 0)
2541 debug1(sbfd, "Label change: %s -> %s\n",
2542 span->label, span->orig_label);
2547 static void label_map_set(struct superbfd *sbfd, const char *oldlabel,
2548 const char *label)
2550 struct label_map *map;
2551 for (map = sbfd->maps.data;
2552 map < sbfd->maps.data + sbfd->maps.size; map++) {
2553 if (strcmp(map->orig_label, oldlabel) == 0) {
2554 if (strcmp(map->orig_label, map->label) != 0 &&
2555 strcmp(map->label, label) != 0)
2556 DIE;
2557 map->label = label;
2558 return;
2561 DIE;
2564 static void change_initial_label(struct span *span, const char *label)
2566 struct superbfd *sbfd = span->ss->parent;
2567 span->label = label;
2568 span->orig_label = label;
2569 if (span->symbol) {
2570 asymbol *csym = canonical_symbol(sbfd, span->symbol);
2571 char *key = strprintf("%p", csym);
2572 struct label_map **mapp =
2573 label_mapp_hash_lookup(&sbfd->maps_hash, key, FALSE);
2574 free(key);
2575 assert(mapp);
2576 (*mapp)->label = span->label;
2577 (*mapp)->orig_label = span->orig_label;
2578 span->symbol = NULL;
2582 static void init_callers(struct superbfd *sbfd)
2584 string_hash_init(&sbfd->callers);
2585 asection *sect;
2586 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2587 struct supersect *ss = fetch_supersect(sbfd, sect);
2588 arelent **relocp;
2589 for (relocp = ss->relocs.data;
2590 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
2591 asymbol *sym = *(*relocp)->sym_ptr_ptr;
2592 unsigned long val =
2593 sym->value + get_reloc_offset(ss, *relocp, true);
2594 char *key = strprintf("%s+%lx", sym->section->name,
2595 val);
2596 const char **ret = string_hash_lookup(&sbfd->callers,
2597 key, TRUE);
2598 free(key);
2599 asymbol *csym = canonical_symbol(sbfd, sect->symbol);
2600 if (*ret != NULL)
2601 *ret = "*multiple_callers*";
2602 else if (static_local_symbol(sbfd, csym))
2603 *ret = static_local_symbol(sbfd, csym);
2604 else
2605 *ret = sect->name;
2610 static const char *find_caller(struct supersect *ss, asymbol *sym)
2612 char *key = strprintf("%s+%lx", sym->section->name,
2613 (unsigned long)sym->value);
2614 const char **ret = string_hash_lookup(&ss->parent->callers, key, FALSE);
2615 free(key);
2617 if (ret == NULL)
2618 return "*no_caller*";
2619 return *ret;
2622 static void init_csyms(struct superbfd *sbfd)
2624 asymbolpp_hash_init(&sbfd->csyms);
2626 asymbol **symp;
2627 for (symp = sbfd->syms.data; symp < sbfd->syms.data + sbfd->syms.size;
2628 symp++) {
2629 asymbol *sym = *symp;
2630 if ((sym->flags & BSF_DEBUGGING) != 0)
2631 continue;
2632 char *key = strprintf("%s+%lx", sym->section->name,
2633 (unsigned long)sym->value);
2634 asymbol ***csympp = asymbolpp_hash_lookup(&sbfd->csyms, key,
2635 TRUE);
2636 free(key);
2637 if (*csympp == NULL) {
2638 *csympp = symp;
2639 continue;
2641 asymbol *csym = **csympp;
2642 if ((csym->flags & BSF_GLOBAL) != 0)
2643 continue;
2644 if ((sym->flags & BSF_GLOBAL) != 0)
2645 *csympp = symp;
2649 static asymbol **symbolp_scan(struct supersect *ss, bfd_vma value)
2651 char *key = strprintf("%s+%lx", ss->name, (unsigned long)value);
2652 asymbol ***csympp =
2653 asymbolpp_hash_lookup(&ss->parent->csyms, key, FALSE);
2654 free(key);
2655 if (csympp != NULL)
2656 return *csympp;
2658 /* For section symbols of sections containing no symbols, return the
2659 section symbol that relocations are generated against */
2660 if (value == 0)
2661 return &ss->symbol;
2662 return NULL;
2665 static asymbol **canonical_symbolp(struct superbfd *sbfd, asymbol *sym)
2667 if (bfd_is_const_section(sym->section)) {
2668 asymbol **csymp;
2669 for (csymp = sbfd->syms.data;
2670 csymp < sbfd->syms.data + sbfd->syms.size; csymp++) {
2671 if (sym == *csymp)
2672 return csymp;
2674 return NULL;
2676 return symbolp_scan(fetch_supersect(sbfd, sym->section), sym->value);
2679 static asymbol *canonical_symbol(struct superbfd *sbfd, asymbol *sym)
2681 if (bfd_is_const_section(sym->section))
2682 return sym;
2683 asymbol **symp = canonical_symbolp(sbfd, sym);
2684 return symp != NULL ? *symp : NULL;
2687 static char *static_local_symbol(struct superbfd *sbfd, asymbol *sym)
2689 struct supersect *ss = fetch_supersect(sbfd, sym->section);
2690 if ((sym->flags & BSF_LOCAL) == 0 || (sym->flags & BSF_OBJECT) == 0)
2691 return NULL;
2692 char *dot = strrchr(sym->name, '.');
2693 if (dot == NULL || dot[1 + strspn(dot + 1, "0123546789")] != '\0')
2694 return NULL;
2695 char *basename = strndup(sym->name, dot - sym->name);
2697 /* Handle C.123.12345 symbols */
2698 dot = strrchr(basename, '.');
2699 if (dot != NULL && dot[1 + strspn(dot + 1, "0123546789")] == '\0')
2700 basename = strndup(basename, dot - basename);
2701 const char *caller;
2702 if (strcmp(basename, "__func__") == 0 ||
2703 strcmp(basename, "__PRETTY_FUNCTION__") == 0)
2704 caller = (const char *)ss->contents.data + sym->value;
2705 else
2706 caller = find_caller(ss, sym);
2707 return strprintf("%s<%s>", basename, caller);
2710 static char *symbol_label(struct superbfd *sbfd, asymbol *sym)
2712 const char *filename = sbfd->abfd->filename;
2713 char *c = strstr(filename, ".KSPLICE");
2714 int flen = (c == NULL ? strlen(filename) : c - filename);
2716 char *label;
2717 if (bfd_is_und_section(sym->section) || (sym->flags & BSF_GLOBAL) != 0) {
2718 label = strdup(sym->name);
2719 } else if (bfd_is_const_section(sym->section)) {
2720 label = strprintf("%s<%.*s>", sym->name, flen, filename);
2721 } else {
2722 asymbol *gsym = canonical_symbol(sbfd, sym);
2724 if (gsym == NULL)
2725 label = strprintf("%s+%lx<%.*s>",
2726 sym->section->name,
2727 (unsigned long)sym->value,
2728 flen, filename);
2729 else if ((gsym->flags & BSF_GLOBAL) != 0)
2730 label = strdup(gsym->name);
2731 else if (static_local_symbol(sbfd, gsym))
2732 label = strprintf("%s+%lx<%.*s>",
2733 static_local_symbol(sbfd, gsym),
2734 (unsigned long)sym->value,
2735 flen, filename);
2736 else
2737 label = strprintf("%s<%.*s>",
2738 gsym->name, flen, filename);
2741 return label;
2744 static void keep_span(struct span *span)
2746 span->keep = true;
2747 span->ss->keep = true;
2750 static struct span *new_span(struct supersect *ss, bfd_vma start, bfd_vma size)
2752 struct span *span = vec_grow(&ss->spans, 1);
2753 span->size = size;
2754 span->start = start;
2755 span->ss = ss;
2756 span->keep = true;
2757 span->new = false;
2758 span->patch = false;
2759 span->bugpatch = false;
2760 span->datapatch = false;
2761 span->precallable = starts_with(ss->name, ".ksplice_call_pre_apply") ||
2762 starts_with(ss->name, ".ksplice_call_check_apply") ||
2763 starts_with(ss->name, ".ksplice_call_fail_apply") ||
2764 starts_with(ss->name, ".ksplice_call_post_remove");
2765 span->match = NULL;
2766 span->shift = 0;
2767 asymbol **symp = symbolp_scan(ss, span->start);
2768 if (symp != NULL) {
2769 span->symbol = *symp;
2770 span->label = label_lookup(ss->parent, span->symbol);
2771 } else {
2772 span->symbol = NULL;
2773 const char *label = label_lookup(ss->parent, ss->symbol);
2774 if (span->start != 0)
2775 span->label = strprintf("%s<span:%lx>", label,
2776 (unsigned long)span->start);
2777 else
2778 span->label = label;
2780 span->orig_label = span->label;
2781 return span;
2784 static void initialize_string_spans(struct supersect *ss)
2786 const char *str;
2787 for (str = ss->contents.data;
2788 (void *)str < ss->contents.data + ss->contents.size;) {
2789 bfd_vma start = (unsigned long)str -
2790 (unsigned long)ss->contents.data;
2791 bfd_vma size = strlen(str) + 1;
2792 while ((start + size) % (1 << ss->alignment) != 0 &&
2793 start + size < ss->contents.size) {
2794 /* Some string sections, like __ksymtab_strings, only
2795 align some strings with the declared alignment */
2796 if (str[size] != '\0')
2797 break;
2798 size++;
2800 new_span(ss, start, size);
2801 str += size;
2805 static int compare_ulongs(const void *va, const void *vb)
2807 const unsigned long *a = va, *b = vb;
2808 return *a - *b;
2811 static void initialize_table_spans(struct superbfd *sbfd,
2812 struct table_section *s)
2814 asection *isection = bfd_get_section_by_name(sbfd->abfd, s->sect);
2815 if (isection == NULL)
2816 return;
2817 struct supersect *ss = fetch_supersect(sbfd, isection);
2818 if (ss->alignment < ffs(s->entry_align) - 1)
2819 ss->alignment = ffs(s->entry_align) - 1;
2821 asection *other_sect = NULL;
2822 if (s->other_sect != NULL)
2823 other_sect = bfd_get_section_by_name(sbfd->abfd, s->other_sect);
2824 struct supersect *other_ss = NULL;
2825 if (other_sect != NULL)
2826 other_ss = fetch_supersect(sbfd, other_sect);
2828 asection *crc_sect = NULL;
2829 if (s->crc_sect != NULL)
2830 crc_sect = bfd_get_section_by_name(sbfd->abfd, s->crc_sect);
2831 struct supersect *crc_ss = NULL;
2832 if (crc_sect != NULL)
2833 crc_ss = fetch_supersect(sbfd, crc_sect);
2835 struct ulong_vec offsets;
2836 vec_init(&offsets);
2838 void *entry;
2839 for (entry = ss->contents.data;
2840 entry < ss->contents.data + ss->contents.size;
2841 entry += s->entry_size) {
2842 struct span *span = new_span(ss, addr_offset(ss, entry),
2843 s->entry_size);
2844 if ((span->symbol == NULL ||
2845 (span->symbol->flags & BSF_SECTION_SYM) != 0) &&
2846 s->has_addr) {
2847 arelent *reloc = find_reloc(ss, entry + s->addr_offset);
2848 assert(reloc);
2849 struct span *target_span = reloc_target_span(ss, reloc);
2850 assert(target_span);
2851 asymbol *sym = *reloc->sym_ptr_ptr;
2852 unsigned long val = get_reloc_offset(ss, reloc, true) +
2853 sym->value - (target_span->start +
2854 target_span->shift);
2855 char *label = strprintf("%s<target:%s+%lx>", ss->name,
2856 target_span->label, val);
2857 change_initial_label(span, label);
2860 if (other_sect != NULL) {
2861 asymbol *sym;
2862 bfd_vma offset = read_reloc(ss, entry + s->other_offset,
2863 sizeof(void *), &sym);
2864 if (sym->section == other_sect) {
2865 assert(offset >= 0 &&
2866 offset < other_ss->contents.size);
2867 *vec_grow(&offsets, 1) = offset;
2871 if (crc_sect != NULL)
2872 new_span(crc_ss, addr_offset(ss, entry) / s->entry_size
2873 * s->crc_size, s->crc_size);
2875 if (ss->type == SS_TYPE_EXPORT) {
2876 const char *symname = read_string(ss, entry +
2877 s->other_offset);
2878 char *label = strprintf("%s:%s", ss->name, symname);
2879 change_initial_label(span, label);
2883 if (other_sect == NULL)
2884 return;
2886 qsort(offsets.data, offsets.size, sizeof(*offsets.data),
2887 compare_ulongs);
2888 *vec_grow(&offsets, 1) = other_ss->contents.size;
2890 unsigned long *off;
2891 for (off = offsets.data; off < offsets.data + offsets.size - 1; off++) {
2892 if (*off != *(off + 1))
2893 new_span(other_ss, *off, *(off + 1) - *off);
2897 static void initialize_table_section_spans(struct superbfd *sbfd)
2899 struct supersect *tables_ss =
2900 fetch_supersect(offsets_sbfd,
2901 bfd_get_section_by_name(offsets_sbfd->abfd,
2902 ".ksplice_table_sections"));
2903 const struct table_section *ts;
2904 struct table_section s;
2905 for (ts = tables_ss->contents.data;
2906 (void *)ts < tables_ss->contents.data + tables_ss->contents.size;
2907 ts++) {
2908 s = *ts;
2909 s.sect = read_string(tables_ss, &ts->sect);
2910 s.other_sect = read_string(tables_ss, &ts->other_sect);
2911 s.crc_sect = read_string(tables_ss, &ts->crc_sect);
2912 initialize_table_spans(sbfd, &s);
2916 static void initialize_ksplice_call_spans(struct supersect *ss)
2918 arelent **relocp;
2919 for (relocp = ss->relocs.data;
2920 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
2921 arelent *reloc = *relocp;
2922 new_span(ss, reloc->address, bfd_get_reloc_size(reloc->howto));
2923 /* the span labels should already be unique */
2927 static void initialize_spans(struct superbfd *sbfd)
2929 asection *sect;
2930 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2931 if (is_table_section(sect->name, true) && mode("keep"))
2932 continue;
2934 struct supersect *ss = fetch_supersect(sbfd, sect);
2935 if (ss->type == SS_TYPE_STRING)
2936 initialize_string_spans(ss);
2937 else if (ss->type == SS_TYPE_KSPLICE_CALL)
2938 initialize_ksplice_call_spans(ss);
2939 else
2940 new_span(ss, 0, ss->contents.size);
2942 if (mode("keep"))
2943 initialize_table_section_spans(sbfd);
2946 struct span *reloc_target_span(struct supersect *ss, arelent *reloc)
2948 asymbol *sym_ptr = *reloc->sym_ptr_ptr;
2949 if (bfd_is_const_section(sym_ptr->section))
2950 return NULL;
2952 bfd_vma addend = get_reloc_offset(ss, reloc, true) + sym_ptr->value;
2953 struct supersect *sym_ss =
2954 fetch_supersect(ss->parent, sym_ptr->section);
2955 struct span *span, *target_span = sym_ss->spans.data;
2956 for (span = sym_ss->spans.data;
2957 span < sym_ss->spans.data + sym_ss->spans.size; span++) {
2958 if (addend >= span->start && addend < span->start + span->size)
2959 target_span = span;
2961 return target_span;
2964 struct span *find_span(struct supersect *ss, bfd_size_type address)
2966 struct span *span;
2967 for (span = ss->spans.data; span < ss->spans.data + ss->spans.size;
2968 span++) {
2969 if (address >= span->start &&
2970 address < span->start + span->size)
2971 return span;
2973 /* Deal with empty BSS sections */
2974 if (ss->contents.size == 0 && ss->spans.size > 0)
2975 return ss->spans.data;
2976 return NULL;
2979 void compute_span_shifts(struct superbfd *sbfd)
2981 asection *sect;
2982 struct span *span;
2983 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2984 struct supersect *ss = fetch_supersect(sbfd, sect);
2985 if (!ss->keep)
2986 continue;
2987 bfd_size_type offset = 0;
2988 for (span = ss->spans.data;
2989 span < ss->spans.data + ss->spans.size; span++) {
2990 if (!span->keep)
2991 continue;
2992 span->shift = offset - span->start;
2993 offset += span->size;
2998 void remove_unkept_spans(struct superbfd *sbfd)
3000 asection *sect;
3001 struct span *span;
3002 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
3003 struct supersect *ss = fetch_supersect(sbfd, sect);
3004 delete_obsolete_relocs(ss);
3005 struct arelentp_vec orig_relocs;
3006 vec_move(&orig_relocs, &ss->relocs);
3007 arelent **relocp, *reloc;
3008 for (relocp = orig_relocs.data;
3009 relocp < orig_relocs.data + orig_relocs.size; relocp++) {
3010 reloc = *relocp;
3011 asymbol *sym = *reloc->sym_ptr_ptr;
3012 span = reloc_target_span(ss, reloc);
3013 if ((span != NULL && span->keep && span->shift == 0) ||
3014 bfd_is_const_section(sym->section)) {
3015 *vec_grow(&ss->relocs, 1) = reloc;
3016 continue;
3018 struct supersect *sym_ss =
3019 fetch_supersect(sbfd, sym->section);
3020 if (span != NULL && (sym->flags & BSF_SECTION_SYM) == 0
3021 && find_span(sym_ss, sym->value) != span) {
3022 err(sbfd, "Spans for symbol %s and relocation "
3023 "target do not match in sect %s\n",
3024 sym->name, sym_ss->name);
3025 DIE;
3027 if (span != NULL && span->keep) {
3028 arelent *new_reloc = malloc(sizeof(*new_reloc));
3029 *new_reloc = *reloc;
3030 new_reloc->addend =
3031 get_reloc_offset(ss, reloc, false);
3032 new_reloc->addend += span->shift;
3033 *vec_grow(&ss->new_relocs, 1) = new_reloc;
3038 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
3039 struct supersect *ss = fetch_supersect(sbfd, sect), orig_ss;
3040 if (!ss->keep)
3041 continue;
3042 supersect_move(&orig_ss, ss);
3043 vec_init(&ss->spans);
3044 for (span = orig_ss.spans.data;
3045 span < orig_ss.spans.data + orig_ss.spans.size; span++) {
3046 if (!span->keep)
3047 continue;
3048 struct span *new_span = vec_grow(&ss->spans, 1);
3049 *new_span = *span;
3050 new_span->start = span->start + span->shift;
3051 new_span->shift = 0;
3052 sect_copy(ss, sect_do_grow(ss, 1, span->size, 1),
3053 &orig_ss, orig_ss.contents.data + span->start,
3054 span->size);
3059 static void init_objmanip_superbfd(struct superbfd *sbfd)
3061 init_label_map(sbfd);
3062 initialize_supersect_types(sbfd);
3063 initialize_spans(sbfd);
3064 load_options(sbfd);
3067 void mangle_section_name(struct superbfd *sbfd, const char *name)
3069 asection *sect = bfd_get_section_by_name(sbfd->abfd, name);
3070 if (sect == NULL)
3071 return;
3072 struct supersect *ss = fetch_supersect(sbfd, sect);
3073 ss->name = strprintf(".ksplice_pre.%s", ss->name);
3076 static void write_bugline_patches(struct superbfd *sbfd)
3078 const struct table_section *ts = get_table_section("__bug_table");
3079 asection *sect = bfd_get_section_by_name(sbfd->abfd, "__bug_table");
3080 if (sect == NULL)
3081 return;
3082 struct supersect *ss = fetch_supersect(sbfd, sect);
3083 assert(ts != NULL);
3085 void *entry;
3086 for (entry = ss->contents.data;
3087 entry < ss->contents.data + ss->contents.size;
3088 entry += ts->entry_size) {
3089 struct span *span = find_span(ss, addr_offset(ss, entry));
3090 assert(span != NULL);
3091 if (!span->bugpatch)
3092 continue;
3093 arelent *reloc = find_reloc(ss, entry + ts->addr_offset);
3094 assert(reloc != NULL);
3095 asymbol *sym = *reloc->sym_ptr_ptr;
3096 assert(!bfd_is_const_section(sym->section));
3098 struct supersect *kpatch_ss =
3099 make_section(sbfd, ".ksplice_patches%s",
3100 sym->section->name);
3101 struct ksplice_patch *kpatch =
3102 sect_grow(kpatch_ss, 1, struct ksplice_patch);
3103 write_ksplice_patch_reloc
3104 (kpatch_ss, sym->section->name, &kpatch->oldaddr,
3105 sizeof(kpatch->oldaddr), span->label, ts->other_offset);
3107 unsigned short *line =
3108 write_patch_storage(kpatch_ss, kpatch, sizeof(*line), NULL);
3109 *line = *(unsigned short *)(entry + ts->other_offset);
3110 kpatch->type = KSPLICE_PATCH_BUGLINE;
3114 void *write_patch_storage(struct supersect *ss, struct ksplice_patch *kpatch,
3115 size_t size, struct supersect **data_ssp)
3117 struct supersect *data_ss = make_section(ss->parent,
3118 ".ksplice_patch_data");
3119 char *saved = sect_do_grow(data_ss, 1, size, 1);
3120 write_reloc(ss, &kpatch->saved, &data_ss->symbol,
3121 addr_offset(data_ss, saved));
3122 char *data = sect_do_grow(data_ss, 1, size, 1);
3123 write_reloc(ss, &kpatch->contents, &data_ss->symbol,
3124 addr_offset(data_ss, data));
3125 kpatch->size = size;
3126 if (data_ssp != NULL)
3127 *data_ssp = data_ss;
3128 return data;