Only use COW hooks in diff mode.
[ksplice.git] / objmanip.c
blobf02d014f0a249a531570a8072f6d41f804ac39b4
1 /* This file is based in part on objcopy.c from GNU Binutils v2.17.
3 * Copyright (C) 1991-2006 Free Software Foundation, Inc.
4 * Copyright (C) 2007-2008 Jeffrey Brian Arnold <jbarnold@mit.edu>
5 * Copyright (C) 2008 Anders Kaseorg <andersk@mit.edu>,
6 * Tim Abbott <tabbott@mit.edu>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License, version 2.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
19 * 02110-1301, USA.
22 /* objmanip performs various object file manipulations for Ksplice. Its first
23 * two arguments are always an input object file and an output object file.
25 * - keep-primary: "objmanip <post.o> <out.o> keep-primary <pre.o> <kid>"
27 * This mode prepares the object file to be installed as a ksplice update. The
28 * kid argument is the ksplice id string for the ksplice update being built.
30 * - keep-helper: "objmanip <pre.o> <out.o> keep-helper"
32 * This mode prepares the object file to be used for run-pre matching. This
33 * involves replacing all ELF relocations with ksplice relocations and
34 * writing ksplice_section structures for each ELF text or data section.
36 * - rmsyms mode: "objmanip <in.o> <out.o> rmsyms
38 * In this mode, any ELF relocations involving the list of symbol names given on
39 * standard input are replaced with ksplice relocations. This is used only
40 * for KSPLICE_STANDALONE.
42 * - finalize mode: "objmanip <in.o> <out.o> finalize"
44 * In this mode, any ELF relocations to undefined symbols are replaced with
45 * ksplice relocations.
48 /* Always define KSPLICE_STANDALONE, even if you're using integrated Ksplice.
49 objmanip won't compile without it. */
50 #define KSPLICE_STANDALONE
52 #define _GNU_SOURCE
53 #include "objcommon.h"
54 #include "kmodsrc/ksplice.h"
55 #include "kmodsrc/offsets.h"
56 #include "ksplice-patch/ksplice-patch.h"
57 #include <stdint.h>
58 #include <stdarg.h>
59 #include <stdlib.h>
60 #include <stdio.h>
61 #include <limits.h>
63 #define KSPLICE_SYMBOL_STR "KSPLICE_SYMBOL_"
65 #define symbol_init(sym) *(sym) = (asymbol *)NULL
66 DEFINE_HASH_TYPE(asymbol *, symbol_hash, symbol_hash_init, symbol_hash_free,
67 symbol_hash_lookup, symbol_init);
69 DECLARE_VEC_TYPE(const char *, str_vec);
71 DECLARE_VEC_TYPE(unsigned long, ulong_vec);
73 #define bool_init(b) *(b) = false
74 DEFINE_HASH_TYPE(bool, bool_hash, bool_hash_init, bool_hash_free,
75 bool_hash_lookup, bool_init);
77 #define ulong_init(x) *(x) = 0
78 DEFINE_HASH_TYPE(unsigned long, ulong_hash, ulong_hash_init,
79 ulong_hash_free, ulong_hash_lookup, ulong_init);
81 void do_keep_primary(struct superbfd *isbfd, const char *pre);
82 void do_keep_helper(struct superbfd *isbfd);
83 void do_finalize(struct superbfd *isbfd);
84 void do_rmsyms(struct superbfd *isbfd);
86 bool relocs_equal(struct supersect *old_src_ss, struct supersect *new_src_ss,
87 arelent *old_reloc, arelent *new_reloc);
88 bfd_vma non_dst_mask(struct supersect *ss, arelent *reloc);
89 bool all_relocs_equal(struct span *old_span, struct span *new_span);
90 static bool part_of_reloc(struct supersect *ss, unsigned long addr);
91 static bool nonrelocs_equal(struct span *old_span, struct span *new_span);
92 static void handle_section_symbol_renames(struct superbfd *oldsbfd,
93 struct superbfd *newsbfd);
95 enum supersect_type supersect_type(struct supersect *ss);
96 void initialize_supersect_types(struct superbfd *sbfd);
97 static void initialize_spans(struct superbfd *sbfd);
98 static void initialize_string_spans(struct supersect *ss);
99 static void initialize_table_spans(struct superbfd *sbfd,
100 struct table_section *s);
101 static void initialize_table_section_spans(struct superbfd *sbfd);
102 static void initialize_ksplice_call_spans(struct supersect *ss);
103 struct span *reloc_target_span(struct supersect *ss, arelent *reloc);
104 struct span *find_span(struct supersect *ss, bfd_size_type address);
105 void remove_unkept_spans(struct superbfd *sbfd);
106 void compute_span_shifts(struct superbfd *sbfd);
107 static struct span *new_span(struct supersect *ss, bfd_vma start, bfd_vma size);
108 bool is_table_section(const char *name, bool consider_other);
109 const struct table_section *get_table_section(const char *name);
110 void mangle_section_name(struct superbfd *sbfd, const char *name);
112 void rm_relocs(struct superbfd *isbfd);
113 void rm_some_relocs(struct supersect *ss);
114 void write_ksplice_reloc(struct supersect *ss, arelent *orig_reloc);
115 static void write_ksplice_reloc_howto(struct supersect *ss, const
116 struct ksplice_reloc_howto *const *addr,
117 reloc_howto_type *howto,
118 enum ksplice_reloc_howto_type type);
119 static void write_ksplice_date_reloc(struct supersect *ss, unsigned long offset,
120 const char *str,
121 enum ksplice_reloc_howto_type type);
122 static void write_ksplice_patch_reloc(struct supersect *ss,
123 const char *sectname, unsigned long *addr,
124 bfd_size_type size, const char *label,
125 long addend);
126 static void write_ksplice_nonreloc_howto(struct supersect *ss,
127 const struct ksplice_reloc_howto
128 *const *addr,
129 enum ksplice_reloc_howto_type type,
130 int size);
131 static void write_date_relocs(struct superbfd *sbfd, const char *str,
132 enum ksplice_reloc_howto_type type);
133 static void write_table_relocs(struct superbfd *sbfd, const char *sectname,
134 enum ksplice_reloc_howto_type type);
135 static void write_ksplice_table_reloc(struct supersect *ss,
136 unsigned long address,
137 const char *label,
138 enum ksplice_reloc_howto_type type);
139 void load_ksplice_symbol_offsets(struct superbfd *sbfd);
140 void write_canary(struct supersect *ss, int offset, bfd_size_type size,
141 bfd_vma dst_mask);
142 static void write_ksplice_section(struct span *span);
143 void write_ksplice_patch(struct superbfd *sbfd, struct span *span);
144 void *write_patch_storage(struct supersect *ss, struct ksplice_patch *patch,
145 size_t size, struct supersect **data_ssp);
146 void write_ksplice_deleted_patch(struct superbfd *sbfd, const char *name,
147 const char *label, const char *sectname);
148 static void write_bugline_patches(struct superbfd *sbfd);
149 asymbol **make_undefined_symbolp(struct superbfd *sbfd, const char *name);
150 void filter_table_sections(struct superbfd *isbfd);
151 void filter_table_section(struct superbfd *sbfd, const struct table_section *s);
152 void keep_referenced_sections(struct superbfd *sbfd);
153 void mark_precallable_spans(struct superbfd *sbfd);
154 bfd_boolean copy_object(bfd *ibfd, bfd *obfd);
155 void setup_section(bfd *ibfd, asection *isection, void *obfdarg);
156 static void setup_new_section(bfd *obfd, struct supersect *ss);
157 static void write_section(bfd *obfd, asection *osection, void *arg);
158 static void delete_obsolete_relocs(struct supersect *ss);
159 void mark_symbols_used_in_relocations(bfd *abfd, asection *isection,
160 void *ignored);
161 static void ss_mark_symbols_used_in_relocations(struct supersect *ss);
162 void filter_symbols(bfd *ibfd, bfd *obfd, struct asymbolp_vec *osyms,
163 struct asymbolp_vec *isyms);
164 static bool deleted_table_section_symbol(bfd *abfd, asymbol *sym);
165 void read_str_set(struct str_vec *strs);
166 bool str_in_set(const char *str, const struct str_vec *strs);
167 struct supersect *__attribute((format(printf, 2, 3)))
168 make_section(struct superbfd *sbfd, const char *fmt, ...);
169 void __attribute__((format(printf, 3, 4)))
170 write_string(struct supersect *ss, const char **addr, const char *fmt, ...);
171 void write_ksplice_export(struct superbfd *sbfd, struct span *span, bool del);
172 void write_reloc(struct supersect *ss, const void *addr, asymbol **symp,
173 bfd_vma offset);
174 arelent *create_reloc(struct supersect *ss, const void *addr, asymbol **symp,
175 bfd_vma offset);
176 static void foreach_symbol_pair(struct superbfd *oldsbfd, struct superbfd *newsbfd,
177 void (*fn)(struct span *old_span,
178 asymbol *oldsym,
179 struct span *new_span,
180 asymbol *newsym));
181 static void check_global_symbols(struct span *old_span, asymbol *oldsym,
182 struct span *new_span, asymbol *newsym);
183 static void match_global_symbols(struct span *old_span, asymbol *oldsym,
184 struct span *new_span, asymbol *newsym);
185 static void match_symbol_spans(struct span *old_span, asymbol *oldsym,
186 struct span *new_span, asymbol *newsym);
188 static void foreach_span_pair(struct superbfd *oldsbfd,
189 struct superbfd *newsbfd,
190 void (*fn)(struct span *old_span,
191 struct span *new_span));
192 static void match_spans_by_label(struct span *old_span, struct span *new_span);
193 static void match_string_spans(struct span *old_span, struct span *new_span);
194 static void mark_new_spans(struct superbfd *sbfd);
195 static void handle_deleted_spans(struct superbfd *oldsbfd,
196 struct superbfd *newsbfd);
197 static void compare_matched_spans(struct superbfd *newsbfd);
198 static void compare_spans(struct span *old_span, struct span *new_span);
199 static void update_nonzero_offsets(struct superbfd *sbfd);
200 static void handle_nonzero_offset_relocs(struct supersect *ss);
201 static void keep_span(struct span *span);
203 static void init_objmanip_superbfd(struct superbfd *sbfd);
204 static const char *label_lookup(struct superbfd *sbfd, asymbol *sym);
205 static void label_map_set(struct superbfd *sbfd, const char *oldlabel,
206 const char *label);
207 static void print_label_changes(struct superbfd *sbfd);
208 static void init_label_map(struct superbfd *sbfd);
209 static void change_initial_label(struct span *span, const char *label);
210 static asymbol **symbolp_scan(struct supersect *ss, bfd_vma value);
211 static void init_csyms(struct superbfd *sbfd);
212 static void init_callers(struct superbfd *sbfd);
213 static asymbol *canonical_symbol(struct superbfd *sbfd, asymbol *sym);
214 static asymbol **canonical_symbolp(struct superbfd *sbfd, asymbol *sym);
215 static char *static_local_symbol(struct superbfd *sbfd, asymbol *sym);
216 static char *symbol_label(struct superbfd *sbfd, asymbol *sym);
218 int verbose = 0;
219 #define debug_(sbfd, level, fmt, ...) \
220 do { \
221 if (verbose >= (level)) \
222 printf("%s: " fmt, (sbfd)->abfd->filename, \
223 ## __VA_ARGS__); \
224 } while (0)
225 #define debug0(sbfd, fmt, ...) debug_(sbfd, 0, fmt, ## __VA_ARGS__)
226 #define debug1(sbfd, fmt, ...) debug_(sbfd, 1, fmt, ## __VA_ARGS__)
227 #define err(sbfd, fmt, ...) \
228 do { \
229 fprintf(stderr, "%s: " fmt, (sbfd)->abfd->filename, \
230 ## __VA_ARGS__); \
231 } while (0)
233 struct str_vec delsects, rmsyms;
234 bool changed;
236 struct ksplice_config *config;
238 const char *modestr, *kid, *finalize_target = NULL;
239 bool write_output = true;
241 struct superbfd *offsets_sbfd = NULL;
243 #define mode(str) starts_with(modestr, str)
245 DECLARE_VEC_TYPE(unsigned long, addr_vec);
246 DEFINE_HASH_TYPE(struct addr_vec, addr_vec_hash,
247 addr_vec_hash_init, addr_vec_hash_free, addr_vec_hash_lookup,
248 vec_init);
249 struct addr_vec_hash system_map;
251 struct bool_hash system_map_written;
252 struct ulong_hash ksplice_symbol_offset;
253 struct ulong_hash ksplice_howto_offset;
254 struct ulong_hash ksplice_string_offset;
256 void load_system_map()
258 const char *config_dir = getenv("KSPLICE_CONFIG_DIR");
259 assert(config_dir);
260 FILE *fp = fopen(strprintf("%s/System.map", config_dir), "r");
261 assert(fp);
262 addr_vec_hash_init(&system_map);
263 unsigned long addr;
264 char type;
265 char *sym;
266 while (fscanf(fp, "%lx %c %as\n", &addr, &type, &sym) == 3)
267 *vec_grow(addr_vec_hash_lookup(&system_map, sym, TRUE),
268 1) = addr;
269 fclose(fp);
272 void load_ksplice_symbol_offsets(struct superbfd *sbfd)
274 asection *sect = bfd_get_section_by_name(sbfd->abfd,
275 ".ksplice_symbols");
276 if (sect == NULL)
277 return;
278 struct supersect *ss = fetch_supersect(sbfd, sect);
280 struct ksplice_symbol *ksym;
281 for (ksym = ss->contents.data;
282 (void *)ksym < ss->contents.data + ss->contents.size; ksym++) {
283 const char *label = read_string(ss, &ksym->label);
284 unsigned long *ksymbol_offp =
285 ulong_hash_lookup(&ksplice_symbol_offset, label, TRUE);
286 *ksymbol_offp = addr_offset(ss, ksym);
290 void load_offsets()
292 char *kmodsrc = getenv("KSPLICE_KMODSRC");
293 assert(kmodsrc != NULL);
294 bfd *offsets_bfd = bfd_openr(strprintf("%s/offsets.o", kmodsrc), NULL);
295 assert(offsets_bfd != NULL);
296 char **matching;
297 assert(bfd_check_format_matches(offsets_bfd, bfd_object, &matching));
298 offsets_sbfd = fetch_superbfd(offsets_bfd);
300 asection *config_sect = bfd_get_section_by_name(offsets_sbfd->abfd,
301 ".ksplice_config");
302 struct supersect *config_ss =
303 fetch_supersect(offsets_sbfd, config_sect);
305 config = config_ss->contents.data;
308 void load_options(struct superbfd *sbfd)
310 asection *sect = bfd_get_section_by_name(sbfd->abfd,
311 ".ksplice_options");
312 if (sect == NULL)
313 return;
314 struct supersect *ss = fetch_supersect(sbfd, sect);
315 const struct ksplice_option *opt;
316 for (opt = ss->contents.data;
317 (void *)opt < ss->contents.data + ss->contents.size; opt++) {
318 if (opt->type == KSPLICE_OPTION_ASSUME_RODATA) {
319 arelent *reloc = find_reloc(ss, &opt->target);
320 struct span *span = reloc_target_span(ss, reloc);
321 assert(span != NULL);
322 assert(span->ss->type == SS_TYPE_DATA);
323 assert(span->start == 0 &&
324 span->size == span->ss->contents.size);
325 span->ss->type = SS_TYPE_RODATA;
326 break;
327 } else {
328 err(sbfd, "Unrecognized Ksplice option %d\n",
329 opt->type);
330 DIE;
335 bool matchable_data_section(struct supersect *ss)
337 if (ss->type == SS_TYPE_STRING)
338 return true;
339 if (ss->type == SS_TYPE_RODATA)
340 return true;
341 if (ss->type == SS_TYPE_DATA && ss->relocs.size != 0)
342 return true;
343 if (ss->type == SS_TYPE_EXPORT)
344 return true;
345 return false;
348 bool unchangeable_section(struct supersect *ss)
350 if (ss->type == SS_TYPE_DATA)
351 return true;
352 if (ss->type == SS_TYPE_IGNORED && !starts_with(ss->name, ".debug") &&
353 strcmp(ss->name, "__ksymtab_strings") != 0)
354 return true;
355 return false;
358 int main(int argc, char *argv[])
360 if (getenv("KSPLICE_VERBOSE") != NULL)
361 verbose = atoi(getenv("KSPLICE_VERBOSE"));
363 bfd_init();
364 bfd *ibfd = bfd_openr(argv[1], NULL);
365 assert(ibfd);
367 char **matching;
368 assert(bfd_check_format_matches(ibfd, bfd_object, &matching));
370 const char *output_target = bfd_get_target(ibfd);
372 load_system_map();
373 load_offsets();
375 bool_hash_init(&system_map_written);
376 ulong_hash_init(&ksplice_symbol_offset);
377 ulong_hash_init(&ksplice_howto_offset);
378 ulong_hash_init(&ksplice_string_offset);
380 struct superbfd *isbfd = fetch_superbfd(ibfd);
382 modestr = argv[3];
383 if (mode("finalize"))
384 finalize_target = argv[4];
385 init_objmanip_superbfd(isbfd);
386 if (mode("keep-primary")) {
387 kid = argv[5];
388 do_keep_primary(isbfd, argv[4]);
389 } else if (mode("keep-helper")) {
390 do_keep_helper(isbfd);
391 } else if (mode("finalize")) {
392 do_finalize(isbfd);
393 } else if (mode("rmsyms")) {
394 do_rmsyms(isbfd);
397 if (write_output) {
398 bfd *obfd = bfd_openw(argv[2], output_target);
399 assert(obfd);
400 copy_object(ibfd, obfd);
401 assert(bfd_close(obfd));
404 if (offsets_sbfd != NULL)
405 assert(bfd_close(offsets_sbfd->abfd));
406 assert(bfd_close(ibfd));
407 return EXIT_SUCCESS;
410 void do_keep_primary(struct superbfd *isbfd, const char *pre)
412 struct bfd *prebfd = bfd_openr(pre, NULL);
413 assert(prebfd != NULL);
414 char **matching;
415 assert(bfd_check_format_matches(prebfd, bfd_object, &matching));
417 struct superbfd *presbfd = fetch_superbfd(prebfd);
418 init_objmanip_superbfd(presbfd);
420 foreach_symbol_pair(presbfd, isbfd, match_global_symbols);
421 debug1(isbfd, "Matched global\n");
422 foreach_span_pair(presbfd, isbfd, match_string_spans);
423 debug1(isbfd, "Matched string spans\n");
424 foreach_symbol_pair(presbfd, isbfd, match_symbol_spans);
425 debug1(isbfd, "Matched by name\n");
426 foreach_span_pair(presbfd, isbfd, match_spans_by_label);
427 debug1(isbfd, "Matched by label\n");
429 do {
430 changed = false;
431 compare_matched_spans(isbfd);
432 update_nonzero_offsets(isbfd);
433 mark_new_spans(isbfd);
434 } while (changed);
435 vec_init(&delsects);
437 foreach_symbol_pair(presbfd, isbfd, check_global_symbols);
439 handle_deleted_spans(presbfd, isbfd);
440 handle_section_symbol_renames(presbfd, isbfd);
442 assert(bfd_close(prebfd));
444 do {
445 changed = false;
446 mark_precallable_spans(isbfd);
447 } while (changed);
449 asection *sect;
450 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
451 struct supersect *ss = fetch_supersect(isbfd, sect);
452 ss->keep = false;
453 struct span *span;
454 for (span = ss->spans.data;
455 span < ss->spans.data + ss->spans.size; span++) {
456 if (starts_with(ss->name, ".ksplice_options"))
457 span->keep = false;
458 else if (span->new || span->patch || span->datapatch)
459 keep_span(span);
460 else
461 span->keep = false;
462 if (span->patch && span->precallable) {
463 err(isbfd, "Patched span %s can be reached "
464 "by a precall function\n", span->label);
465 DIE;
470 print_label_changes(isbfd);
472 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
473 struct supersect *ss = fetch_supersect(isbfd, sect);
474 struct span *span;
475 for (span = ss->spans.data;
476 span < ss->spans.data + ss->spans.size; span++) {
477 if (span->patch || span->bugpatch || span->datapatch)
478 debug0(isbfd, "Patching span %s\n",
479 span->label);
483 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
484 struct supersect *ss = fetch_supersect(isbfd, sect);
485 struct span *span;
486 for (span = ss->spans.data;
487 span < ss->spans.data + ss->spans.size; span++) {
488 if (span->new)
489 debug0(isbfd, "New span %s\n", span->label);
493 write_output = false;
494 const char **sectname;
495 for (sectname = delsects.data;
496 sectname < delsects.data + delsects.size; sectname++) {
497 write_output = true;
498 debug0(isbfd, "Deleted section: %s\n", *sectname);
501 filter_table_sections(isbfd);
503 compute_span_shifts(isbfd);
505 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
506 struct supersect *ss = fetch_supersect(isbfd, sect);
507 if (ss->type == SS_TYPE_KSPLICE_CALL)
508 continue;
509 struct span *span;
510 for (span = ss->spans.data;
511 span < ss->spans.data + ss->spans.size; span++) {
512 if (span->keep)
513 write_output = true;
514 if (span->patch || span->new || span->datapatch)
515 write_ksplice_section(span);
516 if (span->patch || span->datapatch)
517 write_ksplice_patch(isbfd, span);
518 if (ss->type == SS_TYPE_EXPORT && span->new)
519 write_ksplice_export(isbfd, span, false);
523 write_bugline_patches(isbfd);
524 rm_relocs(isbfd);
525 remove_unkept_spans(isbfd);
528 void do_keep_helper(struct superbfd *isbfd)
530 asection *sect;
531 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
532 struct supersect *ss = fetch_supersect(isbfd, sect);
533 ss->keep = false;
534 struct span *span;
535 for (span = ss->spans.data;
536 span < ss->spans.data + ss->spans.size; span++) {
537 span->keep = false;
538 if (ss->type == SS_TYPE_TEXT &&
539 !starts_with(ss->name, ".fixup"))
540 keep_span(span);
541 if (ss->type == SS_TYPE_EXPORT)
542 keep_span(span);
546 asymbol **symp;
547 for (symp = isbfd->syms.data;
548 symp < isbfd->syms.data + isbfd->syms.size; symp++) {
549 asymbol *sym = *symp;
550 if (!bfd_is_const_section(sym->section) &&
551 (sym->flags & BSF_GLOBAL) != 0) {
552 struct supersect *sym_ss =
553 fetch_supersect(isbfd, sym->section);
554 if (sym->value == sym_ss->contents.size)
555 continue;
556 struct span *span = find_span(sym_ss, sym->value);
557 assert(span != NULL);
558 if (sym_ss->type != SS_TYPE_IGNORED)
559 keep_span(span);
563 do {
564 changed = false;
565 keep_referenced_sections(isbfd);
566 } while (changed);
568 filter_table_sections(isbfd);
569 compute_span_shifts(isbfd);
571 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
572 struct supersect *ss = fetch_supersect(isbfd, sect);
573 asymbol *sym = canonical_symbol(isbfd, sect->symbol);
574 if (sym == NULL)
575 continue;
576 if ((sym->flags & BSF_WEAK) != 0)
577 continue;
578 if (bfd_get_section_size(sect) == 0)
579 continue;
580 if (!ss->keep)
581 continue;
582 if (ss->type != SS_TYPE_TEXT && !matchable_data_section(ss))
583 continue;
585 struct span *span;
586 for (span = ss->spans.data;
587 span < ss->spans.data + ss->spans.size; span++) {
588 if (span->keep)
589 write_ksplice_section(span);
593 write_table_relocs(isbfd, "__bug_table", KSPLICE_HOWTO_BUG);
594 write_table_relocs(isbfd, "__ex_table", KSPLICE_HOWTO_EXTABLE);
595 rm_relocs(isbfd);
596 remove_unkept_spans(isbfd);
598 mangle_section_name(isbfd, "__markers");
599 mangle_section_name(isbfd, "__ex_table");
600 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
601 struct supersect *ss = fetch_supersect(isbfd, sect);
602 if (ss->type == SS_TYPE_EXPORT)
603 mangle_section_name(isbfd, ss->name);
607 void do_finalize(struct superbfd *isbfd)
609 load_ksplice_symbol_offsets(isbfd);
610 asection *sect;
611 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
612 struct supersect *ss = fetch_supersect(isbfd, sect);
613 if (ss->type == SS_TYPE_EXIT) {
614 struct span *span;
615 for (span = ss->spans.data;
616 span < ss->spans.data + ss->spans.size; span++)
617 span->keep = false;
618 ss->keep = false;
621 write_date_relocs(isbfd, "<{DATE...}>", KSPLICE_HOWTO_DATE);
622 write_date_relocs(isbfd, "<{TIME}>", KSPLICE_HOWTO_TIME);
623 rm_relocs(isbfd);
626 void do_rmsyms(struct superbfd *isbfd)
628 read_str_set(&rmsyms);
629 rm_relocs(isbfd);
632 void match_spans(struct span *old_span, struct span *new_span)
634 struct superbfd *sbfd = new_span->ss->parent;
635 if (old_span->match == new_span && new_span->match == old_span)
636 return;
637 if (old_span->match != NULL) {
638 err(sbfd, "Matching conflict: old %s: %s != %s\n",
639 old_span->label, old_span->match->label, new_span->label);
640 DIE;
642 if (new_span->match != NULL) {
643 err(sbfd, "Matching conflict: new %s: %s != %s\n",
644 new_span->label, new_span->match->label, old_span->label);
645 DIE;
647 old_span->match = new_span;
648 new_span->match = old_span;
649 debug1(sbfd, "Matched old %s to new %s\n", old_span->label,
650 new_span->label);
651 if (old_span->ss->type != new_span->ss->type &&
652 old_span->ss->type == new_span->ss->orig_type)
653 old_span->ss->type = new_span->ss->type;
656 static void match_global_symbols(struct span *old_span, asymbol *oldsym,
657 struct span *new_span, asymbol *newsym)
659 if ((oldsym->flags & BSF_GLOBAL) == 0 ||
660 (newsym->flags & BSF_GLOBAL) == 0)
661 return;
662 match_spans(old_span, new_span);
665 static void check_global_symbols(struct span *old_span, asymbol *oldsym,
666 struct span *new_span, asymbol *newsym)
668 if ((oldsym->flags & BSF_GLOBAL) == 0 ||
669 (newsym->flags & BSF_GLOBAL) == 0)
670 return;
671 if (old_span->ss->type == SS_TYPE_IGNORED)
672 return;
673 if (old_span->match != new_span || new_span->match != old_span) {
674 err(new_span->ss->parent, "Global symbol span mismatch: %s "
675 "%s/%s\n", oldsym->name, old_span->ss->name,
676 new_span->ss->name);
677 DIE;
681 static void foreach_symbol_pair(struct superbfd *oldsbfd, struct superbfd *newsbfd,
682 void (*fn)(struct span *old_span,
683 asymbol *oldsym,
684 struct span *new_span,
685 asymbol *newsym))
687 asymbol **oldsymp, **newsymp;
688 for (oldsymp = oldsbfd->syms.data;
689 oldsymp < oldsbfd->syms.data + oldsbfd->syms.size; oldsymp++) {
690 asymbol *oldsym = *oldsymp;
691 if (bfd_is_const_section(oldsym->section))
692 continue;
693 for (newsymp = newsbfd->syms.data;
694 newsymp < newsbfd->syms.data + newsbfd->syms.size;
695 newsymp++) {
696 asymbol *newsym = *newsymp;
697 if (bfd_is_const_section(newsym->section))
698 continue;
699 if (strcmp(oldsym->name, newsym->name) != 0)
700 continue;
702 struct supersect *old_ss =
703 fetch_supersect(oldsbfd, oldsym->section);
704 struct supersect *new_ss =
705 fetch_supersect(newsbfd, newsym->section);
706 if ((old_ss->type != new_ss->type &&
707 old_ss->type != new_ss->orig_type) ||
708 old_ss->type == SS_TYPE_SPECIAL ||
709 old_ss->type == SS_TYPE_EXPORT)
710 continue;
712 struct span *old_span =
713 find_span(old_ss, oldsym->value);
714 struct span *new_span =
715 find_span(new_ss, newsym->value);
716 if (old_span == NULL) {
717 err(oldsbfd, "Could not find span for %s\n",
718 oldsym->name);
719 DIE;
721 if (new_span == NULL) {
722 err(newsbfd, "Could not find span for %s\n",
723 newsym->name);
724 DIE;
726 fn(old_span, oldsym, new_span, newsym);
731 static void match_symbol_spans(struct span *old_span, asymbol *oldsym,
732 struct span *new_span, asymbol *newsym)
734 if ((oldsym->flags & BSF_DEBUGGING) != 0 ||
735 (newsym->flags & BSF_DEBUGGING) != 0)
736 return;
737 if (old_span->ss->type == SS_TYPE_SPECIAL)
738 return;
739 if (static_local_symbol(old_span->ss->parent, oldsym) ||
740 static_local_symbol(new_span->ss->parent, newsym))
741 return;
742 if (old_span->match == NULL && new_span->match == NULL)
743 match_spans(old_span, new_span);
746 static void match_spans_by_label(struct span *old_span, struct span *new_span)
748 if (old_span->ss->type == SS_TYPE_STRING)
749 return;
750 if (strcmp(old_span->label, new_span->label) == 0)
751 match_spans(old_span, new_span);
754 static void match_string_spans(struct span *old_span, struct span *new_span)
756 if (old_span->ss->type != SS_TYPE_STRING ||
757 strcmp(old_span->ss->name, new_span->ss->name) != 0)
758 return;
759 if (strcmp((char *)old_span->ss->contents.data + old_span->start,
760 (char *)new_span->ss->contents.data + new_span->start) == 0)
761 match_spans(old_span, new_span);
764 static void foreach_span_pair(struct superbfd *oldsbfd,
765 struct superbfd *newsbfd,
766 void (*fn)(struct span *old_span,
767 struct span *new_span))
769 asection *oldsect, *newsect;
770 struct supersect *oldss, *newss;
771 struct span *old_span, *new_span;
772 for (newsect = newsbfd->abfd->sections; newsect != NULL;
773 newsect = newsect->next) {
774 newss = fetch_supersect(newsbfd, newsect);
775 if (newss->type == SS_TYPE_SPECIAL)
776 continue;
777 for (oldsect = oldsbfd->abfd->sections; oldsect != NULL;
778 oldsect = oldsect->next) {
779 oldss = fetch_supersect(oldsbfd, oldsect);
780 if (oldss->type != newss->type)
781 continue;
782 for (new_span = newss->spans.data;
783 new_span < newss->spans.data + newss->spans.size;
784 new_span++) {
785 for (old_span = oldss->spans.data;
786 old_span < oldss->spans.data +
787 oldss->spans.size; old_span++)
788 fn(old_span, new_span);
794 static void mark_new_spans(struct superbfd *sbfd)
796 asection *sect;
797 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
798 struct supersect *ss = fetch_supersect(sbfd, sect);
799 if (ss->type == SS_TYPE_SPECIAL || ss->type == SS_TYPE_IGNORED)
800 continue;
801 struct span *span;
802 for (span = ss->spans.data;
803 span < ss->spans.data + ss->spans.size; span++) {
804 if (span->match == NULL && !span->bugpatch)
805 span->new = true;
810 static void handle_deleted_spans(struct superbfd *oldsbfd,
811 struct superbfd *newsbfd)
813 asection *sect;
814 for (sect = oldsbfd->abfd->sections; sect != NULL; sect = sect->next) {
815 struct supersect *ss = fetch_supersect(oldsbfd, sect);
816 struct span *span;
817 for (span = ss->spans.data;
818 span < ss->spans.data + ss->spans.size; span++) {
819 if (span->match != NULL)
820 continue;
821 if (ss->type == SS_TYPE_EXPORT) {
822 *vec_grow(&delsects, 1) = span->label;
823 write_ksplice_export(newsbfd, span, true);
824 } else if (ss->type == SS_TYPE_TEXT) {
825 *vec_grow(&delsects, 1) = span->label;
826 if (span->symbol == NULL)
827 DIE;
828 write_ksplice_deleted_patch
829 (newsbfd, span->symbol->name, span->label,
830 span->ss->name);
836 static void handle_nonzero_offset_relocs(struct supersect *ss)
838 struct span *address_span, *target_span;
839 arelent **relocp;
840 for (relocp = ss->relocs.data;
841 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
842 arelent *reloc = *relocp;
843 address_span = find_span(ss, reloc->address);
844 if (!address_span->new && !address_span->patch)
845 continue;
847 asymbol *sym = *reloc->sym_ptr_ptr;
848 if (bfd_is_const_section(sym->section))
849 continue;
850 bfd_vma offset = get_reloc_offset(ss, reloc, true);
851 target_span = reloc_target_span(ss, reloc);
852 if (sym->value + offset == target_span->start)
853 continue;
855 if (target_span->ss->type != SS_TYPE_TEXT)
856 continue;
857 if (target_span->patch)
858 continue;
860 target_span->patch = true;
861 changed = true;
862 debug1(ss->parent, "Changing %s because a relocation from sect "
863 "%s has a nonzero offset %lx+%lx into it\n",
864 target_span->label, ss->name, (unsigned long)sym->value,
865 (unsigned long)offset);
869 static void update_nonzero_offsets(struct superbfd *sbfd)
871 asection *sect;
872 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
873 struct supersect *ss = fetch_supersect(sbfd, sect);
874 if (ss->type == SS_TYPE_SPECIAL || ss->type == SS_TYPE_IGNORED)
875 continue;
876 handle_nonzero_offset_relocs(ss);
880 static void compare_spans(struct span *old_span, struct span *new_span)
882 struct superbfd *newsbfd = new_span->ss->parent;
884 bool nonrelocs_match = nonrelocs_equal(old_span, new_span);
885 bool relocs_match = all_relocs_equal(old_span, new_span);
886 if (nonrelocs_match && relocs_match)
887 return;
888 if (strcmp(old_span->ss->name, "__bug_table") == 0 &&
889 strcmp(new_span->ss->name, "__bug_table") == 0 && relocs_match) {
890 debug1(newsbfd, "Changing %s due to nonmatching line numbers\n",
891 new_span->label);
892 new_span->match = NULL;
893 old_span->match = NULL;
894 new_span->bugpatch = true;
895 return;
898 char *reason;
899 if (new_span->size != old_span->size)
900 reason = "differing sizes";
901 else if (!nonrelocs_match)
902 reason = "differing contents";
903 else
904 reason = "differing relocations";
906 if (new_span->ss->type == SS_TYPE_TEXT) {
907 if (new_span->patch)
908 return;
909 new_span->patch = true;
910 debug1(newsbfd, "Changing %s due to %s\n", new_span->label,
911 reason);
912 } else if (new_span->ss->type == SS_TYPE_RODATA &&
913 new_span->size == old_span->size) {
914 if (new_span->datapatch)
915 return;
916 new_span->datapatch = true;
917 debug1(newsbfd, "Changing %s in-place due to %s\n",
918 new_span->label, reason);
919 } else if (new_span->ss->type == SS_TYPE_STRING &&
920 old_span->ss->type == SS_TYPE_STRING && relocs_match &&
921 strcmp(new_span->ss->contents.data + new_span->start,
922 old_span->ss->contents.data + old_span->start) == 0) {
923 return;
924 } else {
925 debug1(newsbfd, "Unmatching %s and %s due to %s\n",
926 old_span->label, new_span->label, reason);
927 new_span->match = NULL;
928 old_span->match = NULL;
930 changed = true;
931 if (unchangeable_section(new_span->ss))
932 err(newsbfd, "warning: ignoring change to nonpatchable "
933 "section %s\n", new_span->ss->name);
936 static void compare_matched_spans(struct superbfd *newsbfd)
938 asection *sect;
939 for (sect = newsbfd->abfd->sections; sect != NULL; sect = sect->next) {
940 struct supersect *ss = fetch_supersect(newsbfd, sect);
941 struct span *span;
942 for (span = ss->spans.data;
943 span < ss->spans.data + ss->spans.size; span++) {
944 if (span->match == NULL)
945 continue;
946 compare_spans(span->match, span);
951 static void handle_section_symbol_renames(struct superbfd *oldsbfd,
952 struct superbfd *newsbfd)
954 asection *sect;
955 struct span *span;
956 for (sect = newsbfd->abfd->sections; sect != NULL; sect = sect->next) {
957 struct supersect *ss = fetch_supersect(newsbfd, sect);
958 for (span = ss->spans.data;
959 span < ss->spans.data + ss->spans.size; span++) {
960 if (span->match == NULL)
961 continue;
962 if (strcmp(span->label, span->match->label) == 0)
963 continue;
964 if (strcmp(span->orig_label, span->label) != 0 &&
965 strcmp(span->label, span->match->label) != 0)
966 DIE;
967 if (span->symbol != NULL)
968 label_map_set(newsbfd, span->label,
969 span->match->label);
970 span->label = span->match->label;
975 static bool part_of_reloc(struct supersect *ss, unsigned long addr)
977 arelent **relocp;
978 for (relocp = ss->relocs.data;
979 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
980 arelent *reloc = *relocp;
981 if (addr >= reloc->address &&
982 addr < reloc->address + reloc->howto->size)
983 return true;
985 return false;
988 static bool nonrelocs_equal(struct span *old_span, struct span *new_span)
990 int i;
991 struct supersect *old_ss = old_span->ss, *new_ss = new_span->ss;
992 if (old_span->size != new_span->size)
993 return false;
994 const unsigned char *old = old_ss->contents.data + old_span->start;
995 const unsigned char *new = new_ss->contents.data + new_span->start;
996 for (i = 0; i < old_span->size; i++) {
997 if (old[i] != new[i] &&
998 !(part_of_reloc(old_ss, i + old_span->start) &&
999 part_of_reloc(new_ss, i + new_span->start)))
1000 return false;
1002 return true;
1005 bool relocs_equal(struct supersect *old_src_ss, struct supersect *new_src_ss,
1006 arelent *old_reloc, arelent *new_reloc)
1008 struct superbfd *oldsbfd = old_src_ss->parent;
1009 struct superbfd *newsbfd = new_src_ss->parent;
1010 struct span *old_addr_span = find_span(old_src_ss, old_reloc->address);
1011 struct span *new_addr_span = find_span(new_src_ss, new_reloc->address);
1013 if (old_reloc->address - old_addr_span->start !=
1014 new_reloc->address - new_addr_span->start) {
1015 debug1(newsbfd, "Section %s/%s has reloc address mismatch at "
1016 "%lx\n", old_src_ss->name, new_src_ss->name,
1017 (unsigned long)old_reloc->address);
1018 return false;
1021 if (old_reloc->howto != new_reloc->howto) {
1022 debug1(newsbfd, "Section %s/%s has howto type mismatch at "
1023 "%lx\n", old_src_ss->name, new_src_ss->name,
1024 (unsigned long)old_reloc->address);
1025 return false;
1028 if (non_dst_mask(old_src_ss, old_reloc) !=
1029 non_dst_mask(new_src_ss, new_reloc)) {
1030 debug1(newsbfd, "Section %s/%s has contents mismatch at %lx\n",
1031 old_src_ss->name, new_src_ss->name,
1032 (unsigned long)old_reloc->address);
1033 return false;
1036 asymbol *old_sym = *old_reloc->sym_ptr_ptr;
1037 asymbol *new_sym = *new_reloc->sym_ptr_ptr;
1038 asection *old_sect = old_sym->section;
1039 asection *new_sect = new_sym->section;
1041 bfd_vma old_offset = get_reloc_offset(old_src_ss, old_reloc, true);
1042 bfd_vma new_offset = get_reloc_offset(new_src_ss, new_reloc, true);
1044 if (bfd_is_und_section(old_sect) || bfd_is_und_section(new_sect)) {
1045 if (!bfd_is_und_section(new_sect) && old_offset != 0 &&
1046 fetch_supersect(newsbfd, new_sect)->type == SS_TYPE_TEXT)
1047 return false;
1049 if (!bfd_is_und_section(new_sect) && new_offset != 0 &&
1050 fetch_supersect(oldsbfd, old_sect)->type == SS_TYPE_TEXT)
1051 return false;
1053 return strcmp(old_sym->name, new_sym->name) == 0 &&
1054 old_offset == new_offset;
1057 if (bfd_is_const_section(old_sect) || bfd_is_const_section(new_sect))
1058 DIE;
1060 struct supersect *old_ss = fetch_supersect(oldsbfd, old_sect);
1061 struct supersect *new_ss = fetch_supersect(newsbfd, new_sect);
1062 struct span *old_span = reloc_target_span(old_src_ss, old_reloc);
1063 struct span *new_span = reloc_target_span(new_src_ss, new_reloc);
1065 if (old_span->match != new_span || new_span->match != old_span) {
1066 debug1(newsbfd, "Nonmatching relocs from %s to %s/%s\n",
1067 new_src_ss->name, old_span->label, new_span->label);
1068 return false;
1071 if (old_sym->value + old_offset - old_span->start !=
1072 new_sym->value + new_offset - new_span->start) {
1073 debug1(newsbfd, "Offsets to %s/%s differ between %s "
1074 "and %s: %lx+%lx/%lx+%lx\n", old_ss->name,
1075 new_ss->name, old_src_ss->name, new_src_ss->name,
1076 (unsigned long)old_sym->value, (unsigned long)old_offset,
1077 (unsigned long)new_sym->value,
1078 (unsigned long)new_offset);
1079 return false;
1082 if ((old_sym->value + old_offset - old_span->start != 0 ||
1083 new_sym->value + new_offset - new_span->start != 0) &&
1084 new_span->patch) {
1085 debug1(newsbfd, "Relocation from %s to nonzero offsets "
1086 "%lx+%lx/%lx+%lx in changed section %s\n",
1087 new_src_ss->name, (unsigned long)old_sym->value,
1088 (unsigned long)old_offset, (unsigned long)new_sym->value,
1089 (unsigned long)new_offset, new_sym->section->name);
1090 return false;
1092 return true;
1095 bool all_relocs_equal(struct span *old_span, struct span *new_span)
1097 struct supersect *old_ss = old_span->ss, *new_ss = new_span->ss;
1098 arelent **old_relocp, **new_relocp;
1100 for (old_relocp = old_ss->relocs.data;
1101 old_relocp < old_ss->relocs.data + old_ss->relocs.size;
1102 old_relocp++) {
1103 if (find_span(old_ss, (*old_relocp)->address) == old_span)
1104 break;
1107 for (new_relocp = new_ss->relocs.data;
1108 new_relocp < new_ss->relocs.data + new_ss->relocs.size;
1109 new_relocp++) {
1110 if (find_span(new_ss, (*new_relocp)->address) == new_span)
1111 break;
1114 for (; old_relocp < old_ss->relocs.data + old_ss->relocs.size &&
1115 find_span(old_ss, (*old_relocp)->address) == old_span &&
1116 new_relocp < new_ss->relocs.data + new_ss->relocs.size &&
1117 find_span(new_ss, (*new_relocp)->address) == new_span;
1118 old_relocp++, new_relocp++) {
1119 if (!relocs_equal(old_ss, new_ss, *old_relocp, *new_relocp))
1120 return false;
1123 if ((old_relocp < old_ss->relocs.data + old_ss->relocs.size &&
1124 find_span(old_ss, (*old_relocp)->address) == old_span) ||
1125 (new_relocp < new_ss->relocs.data + new_ss->relocs.size &&
1126 find_span(new_ss, (*new_relocp)->address) == new_span)) {
1127 debug1(new_ss->parent, "Different reloc count between %s and "
1128 "%s\n", old_span->label, new_span->label);
1129 return false;
1132 return true;
1135 bfd_vma non_dst_mask(struct supersect *ss, arelent *reloc)
1137 int bits = bfd_get_reloc_size(reloc->howto) * 8;
1138 void *address = ss->contents.data + reloc->address;
1139 bfd_vma x = bfd_get(bits, ss->parent->abfd, address);
1140 return x & ~reloc->howto->dst_mask;
1143 void rm_relocs(struct superbfd *isbfd)
1145 asection *p;
1146 for (p = isbfd->abfd->sections; p != NULL; p = p->next) {
1147 struct supersect *ss = fetch_supersect(isbfd, p);
1148 bool remove_relocs = ss->keep;
1150 if (mode("keep") && ss->type == SS_TYPE_SPECIAL)
1151 remove_relocs = false;
1153 if (ss->type == SS_TYPE_KSPLICE ||
1154 ss->type == SS_TYPE_KSPLICE_CALL)
1155 remove_relocs = false;
1156 if (mode("finalize") &&
1157 (starts_with(ss->name, ".ksplice_patches") ||
1158 starts_with(ss->name, ".ksplice_relocs")))
1159 remove_relocs = true;
1161 if (remove_relocs)
1162 rm_some_relocs(ss);
1166 void rm_some_relocs(struct supersect *ss)
1168 struct arelentp_vec orig_relocs;
1169 vec_move(&orig_relocs, &ss->relocs);
1171 arelent **relocp;
1172 for (relocp = orig_relocs.data;
1173 relocp < orig_relocs.data + orig_relocs.size; relocp++) {
1174 bool rm_reloc = false;
1175 asymbol *sym_ptr = *(*relocp)->sym_ptr_ptr;
1177 if (mode("rmsyms") && str_in_set(sym_ptr->name, &rmsyms) &&
1178 bfd_is_und_section(sym_ptr->section))
1179 rm_reloc = true;
1181 if (mode("keep"))
1182 rm_reloc = true;
1184 if (mode("keep-primary") &&
1185 (bfd_is_const_section(sym_ptr->section) ||
1186 reloc_target_span(ss, *relocp)->new))
1187 rm_reloc = false;
1189 if (mode("keep-primary")) {
1190 const struct table_section *ts =
1191 get_table_section(ss->name);
1192 if (ts != NULL && ts->has_addr &&
1193 ((*relocp)->address % ts->entry_size ==
1194 ts->addr_offset ||
1195 (*relocp)->address % ts->entry_size ==
1196 ts->other_offset))
1197 rm_reloc = false;
1200 if (mode("finalize") && bfd_is_und_section(sym_ptr->section))
1201 rm_reloc = true;
1203 if (strcmp(sym_ptr->name, "mcount") == 0 &&
1204 bfd_is_und_section(sym_ptr->section))
1205 rm_reloc = false;
1207 if (!find_span(ss, (*relocp)->address)->keep)
1208 rm_reloc = false;
1210 if (rm_reloc)
1211 write_ksplice_reloc(ss, *relocp);
1212 else
1213 *vec_grow(&ss->relocs, 1) = *relocp;
1217 struct supersect *make_section(struct superbfd *sbfd, const char *fmt, ...)
1219 va_list ap;
1220 va_start(ap, fmt);
1221 char *name = vstrprintf(fmt, ap);
1222 va_end(ap);
1224 asection *sect = bfd_get_section_by_name(sbfd->abfd, name);
1225 if (sect != NULL)
1226 return fetch_supersect(sbfd, sect);
1227 else
1228 return new_supersect(sbfd, name);
1231 arelent *create_reloc(struct supersect *ss, const void *addr, asymbol **symp,
1232 bfd_vma offset)
1234 bfd_reloc_code_real_type code;
1235 switch (bfd_arch_bits_per_address(ss->parent->abfd)) {
1236 case 32:
1237 code = BFD_RELOC_32;
1238 break;
1239 case 64:
1240 code = BFD_RELOC_64;
1241 break;
1242 default:
1243 DIE;
1246 arelent *reloc = malloc(sizeof(*reloc));
1247 reloc->sym_ptr_ptr = symp;
1248 reloc->address = addr_offset(ss, addr);
1249 reloc->howto = bfd_reloc_type_lookup(ss->parent->abfd, code);
1250 reloc->addend = offset;
1251 return reloc;
1254 void write_reloc(struct supersect *ss, const void *addr, asymbol **symp,
1255 bfd_vma offset)
1257 *vec_grow(&ss->new_relocs, 1) = create_reloc(ss, addr, symp, offset);
1260 void write_string(struct supersect *ss, const char **addr, const char *fmt, ...)
1262 va_list ap;
1263 struct supersect *str_ss = make_section(ss->parent, ".ksplice_str");
1264 char *str;
1265 va_start(ap, fmt);
1266 int len = vasprintf(&str, fmt, ap);
1267 assert(len >= 0);
1268 va_end(ap);
1270 unsigned long *str_offp = ulong_hash_lookup(&ksplice_string_offset, str,
1271 FALSE);
1272 if (str_offp == NULL) {
1273 char *buf = sect_grow(str_ss, len + 1, char);
1274 memcpy(buf, str, len + 1);
1275 str_offp = ulong_hash_lookup(&ksplice_string_offset, str, TRUE);
1276 *str_offp = addr_offset(str_ss, buf);
1279 write_reloc(ss, addr, &str_ss->symbol, *str_offp);
1282 void lookup_system_map(struct addr_vec *addrs, const char *name, long offset)
1284 struct addr_vec *map_addrs =
1285 addr_vec_hash_lookup(&system_map, name, FALSE);
1286 if (map_addrs == NULL)
1287 return;
1289 unsigned long *addr, *map_addr;
1290 for (map_addr = map_addrs->data;
1291 map_addr < map_addrs->data + map_addrs->size; map_addr++) {
1292 for (addr = addrs->data; addr < addrs->data + addrs->size;
1293 addr++) {
1294 if (*addr == *map_addr + offset)
1295 break;
1297 if (addr < addrs->data + addrs->size)
1298 continue;
1299 *vec_grow(addrs, 1) = *map_addr + offset;
1303 void compute_system_map_array(struct superbfd *sbfd, struct addr_vec *addrs,
1304 asymbol *sym)
1306 if (bfd_is_abs_section(sym->section)) {
1307 *vec_grow(addrs, 1) = sym->value;
1308 } else if (bfd_is_und_section(sym->section)) {
1309 lookup_system_map(addrs, sym->name, 0);
1310 } else if (!bfd_is_const_section(sym->section)) {
1311 asymbol **gsymp;
1312 for (gsymp = sbfd->syms.data;
1313 gsymp < sbfd->syms.data + sbfd->syms.size; gsymp++) {
1314 asymbol *gsym = *gsymp;
1315 if ((gsym->flags & BSF_DEBUGGING) == 0 &&
1316 gsym->section == sym->section)
1317 lookup_system_map(addrs, gsym->name,
1318 sym->value - gsym->value);
1323 void write_ksplice_system_map(struct superbfd *sbfd, asymbol *sym,
1324 const char *label)
1326 bool *done = bool_hash_lookup(&system_map_written, label, TRUE);
1327 if (*done)
1328 return;
1329 *done = true;
1331 struct addr_vec addrs;
1332 vec_init(&addrs);
1334 compute_system_map_array(sbfd, &addrs, sym);
1335 if (addrs.size != 0) {
1336 struct supersect *smap_ss =
1337 make_section(sbfd, ".ksplice_system_map");
1338 struct ksplice_system_map *smap =
1339 sect_grow(smap_ss, 1, struct ksplice_system_map);
1340 write_string(smap_ss, &smap->label, "%s", label);
1342 struct supersect *array_ss = make_section(sbfd,
1343 ".ksplice_array");
1344 void *buf = sect_grow(array_ss, addrs.size,
1345 typeof(*addrs.data));
1346 memcpy(buf, addrs.data, addrs.size * sizeof(*addrs.data));
1347 smap->nr_candidates = addrs.size;
1348 write_reloc(smap_ss, &smap->candidates, &array_ss->symbol,
1349 addr_offset(array_ss, buf));
1351 vec_free(&addrs);
1354 void write_ksplice_symbol_backend(struct supersect *ss,
1355 struct ksplice_symbol *const *addr,
1356 asymbol *sym, const char *label,
1357 const char *name)
1359 struct supersect *ksymbol_ss = make_section(ss->parent,
1360 ".ksplice_symbols");
1361 struct ksplice_symbol *ksymbol;
1362 unsigned long *ksymbol_offp;
1364 ksymbol_offp = ulong_hash_lookup(&ksplice_symbol_offset, label, FALSE);
1365 if (ksymbol_offp != NULL) {
1366 write_reloc(ss, addr, &ksymbol_ss->symbol, *ksymbol_offp);
1367 return;
1369 ksymbol = sect_grow(ksymbol_ss, 1, struct ksplice_symbol);
1370 ksymbol_offp = ulong_hash_lookup(&ksplice_symbol_offset, label, TRUE);
1371 *ksymbol_offp = addr_offset(ksymbol_ss, ksymbol);
1373 write_reloc(ss, addr, &ksymbol_ss->symbol, *ksymbol_offp);
1374 write_string(ksymbol_ss, &ksymbol->label, "%s", label);
1375 if (name != NULL) {
1376 write_string(ksymbol_ss, &ksymbol->name, "%s", name);
1377 write_ksplice_system_map(ksymbol_ss->parent, sym, label);
1381 void write_ksplice_symbol(struct supersect *ss,
1382 struct ksplice_symbol *const *addr,
1383 asymbol *sym, struct span *span,
1384 const char *addstr_sect)
1386 const char *label, *name;
1387 if (span != NULL && span->start != 0)
1388 label = span->label;
1389 else
1390 label = label_lookup(ss->parent, sym);
1392 asymbol *gsym = canonical_symbol(ss->parent, sym);
1393 if (strcmp(addstr_sect, "") != 0)
1394 name = NULL;
1395 else if (bfd_is_und_section(sym->section))
1396 name = sym->name;
1397 else if (bfd_is_const_section(sym->section))
1398 name = NULL;
1399 else if (span != NULL && span->symbol == NULL)
1400 name = NULL;
1401 else if (gsym == NULL || (gsym->flags & BSF_SECTION_SYM) != 0)
1402 name = NULL;
1403 else
1404 name = gsym->name;
1406 write_ksplice_symbol_backend(ss, addr, sym,
1407 strprintf("%s%s", addstr_sect, label),
1408 name);
1411 void write_ksplice_reloc(struct supersect *ss, arelent *orig_reloc)
1413 asymbol *sym_ptr = *orig_reloc->sym_ptr_ptr;
1414 bfd_vma reloc_addend = get_reloc_offset(ss, orig_reloc, false);
1415 bfd_vma target_addend = get_reloc_offset(ss, orig_reloc, true);
1416 unsigned long *repladdr = ss->contents.data + orig_reloc->address;
1418 if (mode("finalize") && starts_with(ss->name, ".ksplice_patches")) {
1419 *repladdr = 0;
1420 return;
1422 if (mode("finalize") && starts_with(ss->name, ".ksplice_relocs")) {
1423 assert(starts_with(sym_ptr->name, KSPLICE_SYMBOL_STR));
1424 asymbol fake_sym;
1425 fake_sym.name = sym_ptr->name + strlen(KSPLICE_SYMBOL_STR);
1426 fake_sym.section = bfd_und_section_ptr;
1427 fake_sym.value = 0;
1428 fake_sym.flags = 0;
1430 write_ksplice_symbol_backend
1431 (ss, (struct ksplice_symbol **)repladdr, &fake_sym,
1432 fake_sym.name, fake_sym.name);
1433 return;
1436 struct span *span = reloc_target_span(ss, orig_reloc);
1437 if (span == ss->spans.data && span->start != target_addend)
1438 span = NULL;
1439 write_canary(ss, orig_reloc->address,
1440 bfd_get_reloc_size(orig_reloc->howto),
1441 orig_reloc->howto->dst_mask);
1443 struct supersect *kreloc_ss;
1444 if (mode("rmsyms"))
1445 kreloc_ss = make_section(ss->parent, ".ksplice_init_relocs");
1446 else
1447 kreloc_ss = make_section(ss->parent, ".ksplice_relocs%s",
1448 ss->name);
1449 struct ksplice_reloc *kreloc = sect_grow(kreloc_ss, 1,
1450 struct ksplice_reloc);
1452 struct span *address_span = find_span(ss, orig_reloc->address);
1453 write_reloc(kreloc_ss, &kreloc->blank_addr,
1454 &ss->symbol, orig_reloc->address + address_span->shift);
1455 if (bfd_is_und_section(sym_ptr->section) && mode("keep")) {
1456 char *name = strprintf(KSPLICE_SYMBOL_STR "%s", sym_ptr->name);
1457 asymbol **symp = make_undefined_symbolp(ss->parent, name);
1458 write_reloc(kreloc_ss, &kreloc->symbol, symp, 0);
1459 } else {
1460 write_ksplice_symbol(kreloc_ss, &kreloc->symbol, sym_ptr, span,
1461 "");
1463 if (span != NULL && span->start != 0) {
1464 reloc_addend += sym_ptr->value - span->start;
1465 target_addend += sym_ptr->value - span->start;
1467 kreloc->insn_addend = reloc_addend - target_addend;
1468 kreloc->target_addend = target_addend;
1469 write_ksplice_reloc_howto(kreloc_ss, &kreloc->howto, orig_reloc->howto,
1470 KSPLICE_HOWTO_RELOC);
1473 static void write_ksplice_reloc_howto(struct supersect *ss, const
1474 struct ksplice_reloc_howto *const *addr,
1475 reloc_howto_type *howto,
1476 enum ksplice_reloc_howto_type type)
1478 struct supersect *khowto_ss = make_section(ss->parent,
1479 ".ksplice_reloc_howtos");
1480 struct ksplice_reloc_howto *khowto;
1481 unsigned long *khowto_offp;
1483 khowto_offp = ulong_hash_lookup(&ksplice_howto_offset, howto->name,
1484 FALSE);
1485 if (khowto_offp != NULL) {
1486 write_reloc(ss, addr, &khowto_ss->symbol, *khowto_offp);
1487 return;
1489 khowto = sect_grow(khowto_ss, 1, struct ksplice_reloc_howto);
1490 khowto_offp = ulong_hash_lookup(&ksplice_howto_offset, howto->name,
1491 TRUE);
1492 *khowto_offp = addr_offset(khowto_ss, khowto);
1494 khowto->type = type;
1495 khowto->pcrel = howto->pc_relative;
1496 khowto->size = bfd_get_reloc_size(howto);
1497 khowto->dst_mask = howto->dst_mask;
1498 khowto->rightshift = howto->rightshift;
1499 khowto->signed_addend =
1500 (howto->complain_on_overflow == complain_overflow_signed) ||
1501 (howto->complain_on_overflow == complain_overflow_bitfield);
1502 write_reloc(ss, addr, &khowto_ss->symbol, *khowto_offp);
1505 #define CANARY(x, canary) ((x & ~howto->dst_mask) | (canary & howto->dst_mask))
1507 void write_canary(struct supersect *ss, int offset, bfd_size_type size,
1508 bfd_vma dst_mask)
1510 int bits = size * 8;
1511 void *address = ss->contents.data + offset;
1512 bfd_vma x = bfd_get(bits, ss->parent->abfd, address);
1513 x = (x & ~dst_mask) | ((bfd_vma)KSPLICE_CANARY & dst_mask);
1514 bfd_put(bits, ss->parent->abfd, x, address);
1517 static void write_date_relocs(struct superbfd *sbfd, const char *str,
1518 enum ksplice_reloc_howto_type type)
1520 asection *sect;
1521 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
1522 struct supersect *ss = fetch_supersect(sbfd, sect);
1523 if (ss->type != SS_TYPE_STRING && ss->type != SS_TYPE_RODATA)
1524 continue;
1525 void *ptr;
1526 struct span *span;
1527 for (span = ss->spans.data;
1528 span < ss->spans.data + ss->spans.size; span++) {
1529 if (!span->keep)
1530 continue;
1531 for (ptr = ss->contents.data + span->start;
1532 ptr + strlen(str) < ss->contents.data +
1533 span->start + span->size; ptr++) {
1534 if (strcmp((const char *)ptr, str) == 0)
1535 write_ksplice_date_reloc
1536 (ss, addr_offset(ss, ptr), str,
1537 type);
1543 static void write_ksplice_date_reloc(struct supersect *ss, unsigned long offset,
1544 const char *str,
1545 enum ksplice_reloc_howto_type type)
1547 struct supersect *kreloc_ss;
1548 kreloc_ss = make_section(ss->parent, ".ksplice_relocs%s", ss->name);
1549 struct ksplice_reloc *kreloc = sect_grow(kreloc_ss, 1,
1550 struct ksplice_reloc);
1552 const char *filename = ss->parent->abfd->filename;
1553 char *c = strstr(filename, ".KSPLICE");
1554 int flen = (c == NULL ? strlen(filename) : c - filename);
1556 write_ksplice_symbol_backend(kreloc_ss, &kreloc->symbol, NULL,
1557 strprintf("%s<%.*s>", str, flen, filename),
1558 NULL);
1560 struct span *span = find_span(ss, offset);
1561 write_reloc(kreloc_ss, &kreloc->blank_addr, &ss->symbol,
1562 offset + span->shift);
1563 write_ksplice_nonreloc_howto(kreloc_ss, &kreloc->howto, type,
1564 strlen(str));
1567 static void write_table_relocs(struct superbfd *sbfd, const char *sectname,
1568 enum ksplice_reloc_howto_type type)
1570 asection *sect = bfd_get_section_by_name(sbfd->abfd, sectname);
1571 if (sect == NULL)
1572 return;
1573 struct supersect *ss = fetch_supersect(sbfd, sect);
1575 const struct table_section *s = get_table_section(sectname);
1576 if (s == NULL)
1577 DIE;
1579 void *entry;
1580 for (entry = ss->contents.data;
1581 entry < ss->contents.data + ss->contents.size;
1582 entry += s->entry_size) {
1583 struct span *span = find_span(ss, addr_offset(ss, entry));
1584 assert(span != NULL);
1585 if (!span->keep)
1586 continue;
1588 arelent *reloc = find_reloc(ss, entry + s->addr_offset);
1589 assert(reloc != NULL);
1590 asymbol *sym = *reloc->sym_ptr_ptr;
1591 assert(!bfd_is_const_section(sym->section));
1592 struct supersect *sym_ss = fetch_supersect(sbfd, sym->section);
1593 unsigned long addr = get_reloc_offset(ss, reloc, true) +
1594 sym->value;
1595 write_ksplice_table_reloc(sym_ss, addr, span->label, type);
1599 static void write_ksplice_table_reloc(struct supersect *ss,
1600 unsigned long address,
1601 const char *label,
1602 enum ksplice_reloc_howto_type type)
1604 struct supersect *kreloc_ss;
1605 kreloc_ss = make_section(ss->parent, ".ksplice_relocs%s", ss->name);
1606 struct ksplice_reloc *kreloc = sect_grow(kreloc_ss, 1,
1607 struct ksplice_reloc);
1608 struct span *span = find_span(ss, address);
1609 assert(span != NULL);
1611 write_ksplice_symbol_backend(kreloc_ss, &kreloc->symbol, NULL,
1612 label, NULL);
1613 write_reloc(kreloc_ss, &kreloc->blank_addr, &ss->symbol,
1614 address + span->shift);
1615 write_ksplice_nonreloc_howto(kreloc_ss, &kreloc->howto, type, 0);
1618 static void write_ksplice_nonreloc_howto(struct supersect *ss,
1619 const struct ksplice_reloc_howto
1620 *const *addr,
1621 enum ksplice_reloc_howto_type type,
1622 int size)
1624 struct supersect *khowto_ss =
1625 make_section(ss->parent, ".ksplice_reloc_howtos");
1626 struct ksplice_reloc_howto *khowto =
1627 sect_grow(khowto_ss, 1, struct ksplice_reloc_howto);
1629 khowto->type = type;
1630 khowto->size = size;
1631 khowto->pcrel = 0;
1632 khowto->dst_mask = 0;
1633 khowto->rightshift = 0;
1634 khowto->signed_addend = 0;
1635 write_reloc(ss, addr, &khowto_ss->symbol,
1636 addr_offset(khowto_ss, khowto));
1639 static void write_ksplice_section(struct span *span)
1641 struct supersect *ss = span->ss;
1642 const char *sectname = span->ss->name;
1643 const struct table_section *ts = get_table_section(ss->name);
1645 if (ts != NULL && ts->has_addr) {
1646 arelent *reloc = find_reloc(ss, ss->contents.data + span->start
1647 + ts->addr_offset);
1648 assert(reloc != NULL);
1649 asymbol *rsym = *reloc->sym_ptr_ptr;
1650 assert(!bfd_is_const_section(rsym->section));
1651 sectname = rsym->section->name;
1654 struct supersect *ksect_ss =
1655 make_section(ss->parent, ".ksplice_sections%s", sectname);
1656 struct ksplice_section *ksect = sect_grow(ksect_ss, 1,
1657 struct ksplice_section);
1658 asymbol *sym = span->symbol == NULL ? ss->symbol : span->symbol;
1660 write_ksplice_symbol(ksect_ss, &ksect->symbol, sym, span,
1661 mode("keep-primary") ? "(post)" : "");
1662 ksect->size = span->size;
1663 ksect->flags = 0;
1665 if (ss->type == SS_TYPE_RODATA || ss->type == SS_TYPE_STRING ||
1666 ss->type == SS_TYPE_EXPORT)
1667 ksect->flags |= KSPLICE_SECTION_RODATA;
1668 if (ss->type == SS_TYPE_DATA)
1669 ksect->flags |= KSPLICE_SECTION_DATA;
1670 if (ss->type == SS_TYPE_TEXT)
1671 ksect->flags |= KSPLICE_SECTION_TEXT;
1672 assert(ksect->flags != 0);
1674 if (ss->type == SS_TYPE_STRING)
1675 ksect->flags |= KSPLICE_SECTION_STRING;
1677 write_reloc(ksect_ss, &ksect->address, &ss->symbol,
1678 span->start + span->shift);
1681 static void write_ksplice_patch_reloc(struct supersect *ss,
1682 const char *sectname, unsigned long *addr,
1683 bfd_size_type size, const char *label,
1684 long addend)
1686 struct supersect *kreloc_ss;
1687 kreloc_ss = make_section(ss->parent, ".ksplice_relocs%s", sectname);
1688 struct ksplice_reloc *kreloc = sect_grow(kreloc_ss, 1,
1689 struct ksplice_reloc);
1691 write_canary(ss, addr_offset(ss, addr), size, -1);
1692 write_ksplice_symbol_backend(kreloc_ss, &kreloc->symbol, NULL,
1693 label, NULL);
1694 write_reloc(kreloc_ss, &kreloc->blank_addr, &ss->symbol,
1695 addr_offset(ss, addr));
1696 reloc_howto_type *howto =
1697 bfd_reloc_type_lookup(ss->parent->abfd,
1698 PASTE(BFD_RELOC_, LONG_BIT));
1699 write_ksplice_reloc_howto(kreloc_ss, &kreloc->howto, howto,
1700 KSPLICE_HOWTO_RELOC);
1701 kreloc->target_addend = addend;
1702 kreloc->insn_addend = 0;
1705 void write_ksplice_patch(struct superbfd *sbfd, struct span *span)
1707 struct supersect *kpatch_ss =
1708 make_section(sbfd, ".ksplice_patches%s", span->ss->name);
1709 struct ksplice_patch *kpatch = sect_grow(kpatch_ss, 1,
1710 struct ksplice_patch);
1712 write_ksplice_patch_reloc(kpatch_ss, span->ss->name, &kpatch->oldaddr,
1713 sizeof(kpatch->oldaddr), span->label, 0);
1714 if (span->ss->type == SS_TYPE_TEXT) {
1715 kpatch->type = KSPLICE_PATCH_TEXT;
1716 write_patch_storage(kpatch_ss, kpatch, MAX_TRAMPOLINE_SIZE,
1717 NULL);
1718 } else {
1719 kpatch->type = KSPLICE_PATCH_DATA;
1720 kpatch->size = span->size;
1721 struct supersect *data_ss =
1722 make_section(sbfd, ".ksplice_patch_data");
1723 write_reloc(kpatch_ss, &kpatch->contents, &span->ss->symbol,
1724 span->start + span->shift);
1725 char *saved = sect_do_grow(data_ss, 1, span->size, 1);
1726 write_reloc(kpatch_ss, &kpatch->saved, &data_ss->symbol,
1727 addr_offset(data_ss, saved));
1729 write_reloc(kpatch_ss, &kpatch->repladdr, &span->ss->symbol,
1730 span->start + span->shift);
1733 asymbol **make_undefined_symbolp(struct superbfd *sbfd, const char *name)
1735 asymbol **symp;
1736 for (symp = sbfd->syms.data; symp < sbfd->syms.data + sbfd->syms.size;
1737 symp++) {
1738 asymbol *sym = *symp;
1739 if (strcmp(name, sym->name) == 0 &&
1740 bfd_is_und_section(sym->section))
1741 return symp;
1743 asymbol ***sympp;
1744 for (sympp = sbfd->new_syms.data;
1745 sympp < sbfd->new_syms.data + sbfd->new_syms.size; sympp++) {
1746 asymbol **symp = *sympp;
1747 asymbol *sym = *symp;
1748 if (strcmp(name, sym->name) == 0 &&
1749 bfd_is_und_section(sym->section))
1750 return symp;
1753 symp = malloc(sizeof(*symp));
1754 *symp = bfd_make_empty_symbol(sbfd->abfd);
1755 asymbol *sym = *symp;
1756 sym->name = name;
1757 sym->section = bfd_und_section_ptr;
1758 sym->flags = 0;
1759 sym->value = 0;
1760 *vec_grow(&sbfd->new_syms, 1) = symp;
1761 return symp;
1764 void write_ksplice_deleted_patch(struct superbfd *sbfd, const char *name,
1765 const char *label, const char *sectname)
1767 struct supersect *kpatch_ss =
1768 make_section(sbfd, ".ksplice_patches%s", sectname);
1769 struct ksplice_patch *kpatch = sect_grow(kpatch_ss, 1,
1770 struct ksplice_patch);
1772 write_ksplice_patch_reloc(kpatch_ss, sectname, &kpatch->oldaddr,
1773 sizeof(kpatch->oldaddr), label, 0);
1774 kpatch->type = KSPLICE_PATCH_TEXT;
1775 asymbol **symp = make_undefined_symbolp(sbfd, strdup(name));
1776 write_reloc(kpatch_ss, &kpatch->repladdr, symp, 0);
1777 write_patch_storage(kpatch_ss, kpatch, MAX_TRAMPOLINE_SIZE, NULL);
1780 void write_ksplice_export(struct superbfd *sbfd, struct span *span, bool del)
1782 struct supersect *kpatch_ss = make_section(sbfd, ".ksplice_patches");
1783 struct ksplice_patch *kpatch = sect_grow(kpatch_ss, 1,
1784 struct ksplice_patch);
1785 struct supersect *data_ss;
1787 const struct table_section *ts = get_table_section(span->ss->name);
1788 assert(ts != NULL);
1789 const char **addr =
1790 span->ss->contents.data + span->start + ts->other_offset;
1791 const char *symname = read_string(span->ss, addr);
1793 char *oldname, *newname;
1794 if (del) {
1795 oldname = strprintf("%s:%s", span->ss->name, symname);
1796 newname = strprintf("DISABLED_%s_%s", symname, kid);
1797 } else {
1798 oldname = strprintf("%s:DISABLED_%s_%s", span->ss->name,
1799 symname, kid);
1800 newname = strprintf("%s", symname);
1801 write_string(span->ss, addr, "DISABLED_%s_%s", symname, kid);
1804 write_ksplice_patch_reloc(kpatch_ss, "", &kpatch->oldaddr,
1805 sizeof(kpatch->oldaddr), oldname,
1806 ts->other_offset);
1807 kpatch->type = KSPLICE_PATCH_EXPORT;
1808 const char **namep = write_patch_storage(kpatch_ss, kpatch,
1809 sizeof(newname), &data_ss);
1810 write_string(data_ss, namep, "%s", newname);
1813 void filter_table_sections(struct superbfd *isbfd)
1815 struct supersect *tables_ss =
1816 fetch_supersect(offsets_sbfd,
1817 bfd_get_section_by_name(offsets_sbfd->abfd,
1818 ".ksplice_table_sections"));
1819 const struct table_section *ts;
1820 for (ts = tables_ss->contents.data;
1821 (void *)ts < tables_ss->contents.data + tables_ss->contents.size;
1822 ts++) {
1823 struct table_section s = *ts;
1824 s.sect = read_string(tables_ss, &ts->sect);
1825 s.other_sect = read_string(tables_ss, &ts->other_sect);
1826 s.crc_sect = read_string(tables_ss, &ts->crc_sect);
1827 filter_table_section(isbfd, &s);
1831 void filter_table_section(struct superbfd *sbfd, const struct table_section *s)
1833 asection *isection = bfd_get_section_by_name(sbfd->abfd, s->sect);
1834 if (isection == NULL)
1835 return;
1836 struct supersect *ss = fetch_supersect(sbfd, isection);
1838 void *entry;
1839 for (entry = ss->contents.data;
1840 entry < ss->contents.data + ss->contents.size;
1841 entry += s->entry_size) {
1842 asymbol *sym;
1843 struct span *span = find_span(ss, addr_offset(ss, entry));
1844 assert(span != NULL);
1846 if (s->has_addr) {
1847 read_reloc(ss, entry + s->addr_offset,
1848 sizeof(void *), &sym);
1849 struct supersect *sym_ss =
1850 fetch_supersect(sbfd, sym->section);
1851 if (sym_ss->keep)
1852 keep_span(span);
1855 if (s->other_sect != NULL) {
1856 arelent *reloc =
1857 find_reloc(ss, entry + s->other_offset);
1858 assert(reloc != NULL);
1859 struct span *sym_span = reloc_target_span(ss, reloc);
1860 if (span->keep)
1861 keep_span(sym_span);
1864 if (s->crc_sect != NULL) {
1865 asection *crc_sect =
1866 bfd_get_section_by_name(sbfd->abfd, s->crc_sect);
1867 struct supersect *crc_ss =
1868 fetch_supersect(sbfd, crc_sect);
1869 struct span *crc_span =
1870 find_span(crc_ss, addr_offset(ss, entry) /
1871 s->entry_size * s->crc_size);
1872 assert(crc_span);
1873 if (span->keep)
1874 keep_span(crc_span);
1879 void mark_precallable_spans(struct superbfd *sbfd)
1881 asection *sect;
1882 struct supersect *ss, *sym_ss;
1883 struct span *address_span, *target_span;
1884 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
1885 ss = fetch_supersect(sbfd, sect);
1886 arelent **relocp;
1887 if (ss->type == SS_TYPE_SPECIAL)
1888 continue;
1889 for (relocp = ss->relocs.data;
1890 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
1891 asymbol *sym = *(*relocp)->sym_ptr_ptr;
1892 address_span = find_span(ss, (*relocp)->address);
1893 if (!address_span->precallable)
1894 continue;
1895 target_span = reloc_target_span(ss, *relocp);
1896 if (target_span == NULL || target_span->keep)
1897 continue;
1898 sym_ss = fetch_supersect(sbfd, sym->section);
1899 if (sym_ss->type == SS_TYPE_IGNORED)
1900 continue;
1901 target_span->precallable = true;
1902 changed = true;
1907 void keep_referenced_sections(struct superbfd *sbfd)
1909 asection *sect;
1910 struct supersect *ss, *sym_ss;
1911 struct span *address_span, *target_span;
1912 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
1913 ss = fetch_supersect(sbfd, sect);
1914 arelent **relocp;
1915 if (ss->type == SS_TYPE_SPECIAL)
1916 continue;
1917 for (relocp = ss->relocs.data;
1918 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
1919 asymbol *sym = *(*relocp)->sym_ptr_ptr;
1920 address_span = find_span(ss, (*relocp)->address);
1921 if (!address_span->keep)
1922 continue;
1923 target_span = reloc_target_span(ss, *relocp);
1924 if (target_span == NULL || target_span->keep)
1925 continue;
1926 sym_ss = fetch_supersect(sbfd, sym->section);
1927 if (sym_ss->type == SS_TYPE_IGNORED)
1928 continue;
1929 keep_span(target_span);
1930 changed = true;
1935 void copy_symbols(struct asymbolp_vec *osyms, struct asymbolpp_vec *isyms)
1937 asymbol ***sympp;
1938 for (sympp = isyms->data; sympp < isyms->data + isyms->size; sympp++)
1939 *vec_grow(osyms, 1) = **sympp;
1942 /* Modified function from GNU Binutils objcopy.c */
1943 bfd_boolean copy_object(bfd *ibfd, bfd *obfd)
1945 assert(bfd_set_format(obfd, bfd_get_format(ibfd)));
1947 bfd_vma start = bfd_get_start_address(ibfd);
1949 flagword flags = bfd_get_file_flags(ibfd);
1950 flags &= bfd_applicable_file_flags(obfd);
1952 assert(bfd_set_start_address(obfd, start)
1953 && bfd_set_file_flags(obfd, flags));
1955 enum bfd_architecture iarch = bfd_get_arch(ibfd);
1956 unsigned int imach = bfd_get_mach(ibfd);
1957 assert(bfd_set_arch_mach(obfd, iarch, imach));
1958 assert(bfd_set_format(obfd, bfd_get_format(ibfd)));
1960 /* BFD mandates that all output sections be created and sizes set before
1961 any output is done. Thus, we traverse all sections multiple times. */
1962 bfd_map_over_sections(ibfd, setup_section, obfd);
1964 struct supersect *new_supersects = fetch_superbfd(ibfd)->new_supersects;
1965 struct supersect *ss;
1966 for (ss = new_supersects; ss != NULL; ss = ss->next)
1967 setup_new_section(obfd, ss);
1969 /* Mark symbols used in output relocations so that they
1970 are kept, even if they are local labels or static symbols.
1972 Note we iterate over the input sections examining their
1973 relocations since the relocations for the output sections
1974 haven't been set yet. mark_symbols_used_in_relocations will
1975 ignore input sections which have no corresponding output
1976 section. */
1978 bfd_map_over_sections(ibfd, mark_symbols_used_in_relocations, NULL);
1979 for (ss = new_supersects; ss != NULL; ss = ss->next)
1980 ss_mark_symbols_used_in_relocations(ss);
1981 struct asymbolp_vec osyms;
1982 vec_init(&osyms);
1983 filter_symbols(ibfd, obfd, &osyms, &fetch_superbfd(ibfd)->syms);
1984 copy_symbols(&osyms, &fetch_superbfd(ibfd)->new_syms);
1986 bfd_set_symtab(obfd, osyms.data, osyms.size);
1988 /* This has to happen after the symbol table has been set. */
1989 bfd_map_over_sections(obfd, write_section, NULL);
1991 /* Allow the BFD backend to copy any private data it understands
1992 from the input BFD to the output BFD. This is done last to
1993 permit the routine to look at the filtered symbol table, which is
1994 important for the ECOFF code at least. */
1995 assert(bfd_copy_private_bfd_data(ibfd, obfd));
1997 return TRUE;
2000 /* Modified function from GNU Binutils objcopy.c */
2001 void setup_section(bfd *ibfd, asection *isection, void *obfdarg)
2003 struct superbfd *isbfd = fetch_superbfd(ibfd);
2004 struct supersect *ss = fetch_supersect(isbfd, isection);
2005 bfd *obfd = obfdarg;
2006 bfd_vma vma;
2008 if (!ss->keep)
2009 return;
2011 asection *osection = bfd_make_section_anyway(obfd, ss->name);
2012 assert(osection != NULL);
2014 osection->userdata = ss;
2015 bfd_set_section_flags(obfd, osection, ss->flags);
2016 ss->symbol = osection->symbol;
2017 assert(bfd_set_section_size(obfd, osection, ss->contents.size));
2019 vma = bfd_section_vma(ibfd, isection);
2020 assert(bfd_set_section_vma(obfd, osection, vma));
2022 osection->lma = isection->lma;
2023 assert(bfd_set_section_alignment(obfd, osection, ss->alignment));
2024 osection->entsize = ss->entsize;
2025 osection->output_section = osection;
2026 osection->output_offset = 0;
2027 isection->output_section = osection;
2028 isection->output_offset = 0;
2029 return;
2032 void setup_new_section(bfd *obfd, struct supersect *ss)
2034 asection *osection = bfd_make_section_anyway(obfd, ss->name);
2035 assert(osection != NULL);
2036 bfd_set_section_flags(obfd, osection, ss->flags);
2038 osection->userdata = ss;
2039 ss->symbol = osection->symbol;
2040 assert(bfd_set_section_size(obfd, osection, ss->contents.size));
2041 assert(bfd_set_section_vma(obfd, osection, 0));
2043 osection->lma = 0;
2044 assert(bfd_set_section_alignment(obfd, osection, ss->alignment));
2045 osection->entsize = ss->entsize;
2046 osection->output_section = osection;
2047 osection->output_offset = 0;
2050 static int compare_reloc_addresses(const void *aptr, const void *bptr)
2052 const arelent *const *a = aptr, *const *b = bptr;
2053 return (*a)->address - (*b)->address;
2056 static void delete_obsolete_relocs(struct supersect *ss)
2058 if (ss->new_relocs.size == 0)
2059 return;
2061 qsort(ss->relocs.data, ss->relocs.size, sizeof(*ss->relocs.data),
2062 compare_reloc_addresses);
2063 qsort(ss->new_relocs.data, ss->new_relocs.size,
2064 sizeof(*ss->new_relocs.data), compare_reloc_addresses);
2066 struct arelentp_vec orig_relocs;
2067 vec_move(&orig_relocs, &ss->relocs);
2069 arelent **relocp, **new_relocp = ss->new_relocs.data;
2070 for (relocp = orig_relocs.data;
2071 relocp < orig_relocs.data + orig_relocs.size; relocp++) {
2072 while (new_relocp < ss->new_relocs.data + ss->new_relocs.size &&
2073 (*new_relocp)->address < (*relocp)->address)
2074 new_relocp++;
2075 arelent *reloc = *relocp, *new_reloc = *new_relocp;
2076 if (new_relocp == ss->new_relocs.data + ss->new_relocs.size ||
2077 reloc->address != new_reloc->address)
2078 *vec_grow(&ss->relocs, 1) = reloc;
2082 void write_section(bfd *obfd, asection *osection, void *arg)
2084 struct supersect *ss = osection->userdata;
2086 if ((ss->flags & SEC_GROUP) != 0 || ss->contents.size == 0)
2087 return;
2089 delete_obsolete_relocs(ss);
2091 arelent **relocp;
2092 char *error_message;
2093 for (relocp = ss->new_relocs.data;
2094 relocp < ss->new_relocs.data + ss->new_relocs.size; relocp++) {
2095 bfd_vma val;
2096 if (bfd_get_arch(obfd) == bfd_arch_arm)
2097 val = osection->use_rela_p ? 0 : (*relocp)->addend;
2098 else
2099 val = 0;
2100 bfd_put(bfd_get_reloc_size((*relocp)->howto) * 8, obfd, val,
2101 ss->contents.data + (*relocp)->address);
2102 if (bfd_install_relocation(obfd, *relocp, ss->contents.data,
2103 0, osection, &error_message) !=
2104 bfd_reloc_ok) {
2105 err(ss->parent, "ksplice: error installing reloc: %s",
2106 error_message);
2107 DIE;
2110 memcpy(vec_grow(&ss->relocs, ss->new_relocs.size), ss->new_relocs.data,
2111 ss->new_relocs.size * sizeof(*ss->new_relocs.data));
2113 bfd_set_reloc(obfd, osection,
2114 ss->relocs.size == 0 ? NULL : ss->relocs.data,
2115 ss->relocs.size);
2117 if (ss->flags & SEC_HAS_CONTENTS)
2118 assert(bfd_set_section_contents
2119 (obfd, osection, ss->contents.data, 0,
2120 ss->contents.size));
2123 /* Modified function from GNU Binutils objcopy.c
2125 * Mark all the symbols which will be used in output relocations with
2126 * the BSF_KEEP flag so that those symbols will not be stripped.
2128 * Ignore relocations which will not appear in the output file.
2130 void mark_symbols_used_in_relocations(bfd *abfd, asection *isection,
2131 void *ignored)
2133 struct superbfd *sbfd = fetch_superbfd(abfd);
2134 if (isection->output_section == NULL)
2135 return;
2137 struct supersect *ss = fetch_supersect(sbfd, isection);
2138 ss_mark_symbols_used_in_relocations(ss);
2141 void ss_mark_symbols_used_in_relocations(struct supersect *ss)
2143 /* Examine each symbol used in a relocation. If it's not one of the
2144 special bfd section symbols, then mark it with BSF_KEEP. */
2145 arelent **relocp;
2146 for (relocp = ss->relocs.data;
2147 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
2148 asymbol *sym = *(*relocp)->sym_ptr_ptr;
2149 if (!(bfd_is_const_section(sym->section) &&
2150 sym == sym->section->symbol))
2151 sym->flags |= BSF_KEEP;
2153 for (relocp = ss->new_relocs.data;
2154 relocp < ss->new_relocs.data + ss->new_relocs.size; relocp++) {
2155 asymbol *sym = *(*relocp)->sym_ptr_ptr;
2156 if (!(bfd_is_const_section(sym->section) &&
2157 sym == sym->section->symbol))
2158 sym->flags |= BSF_KEEP;
2162 static bool deleted_table_section_symbol(bfd *abfd, asymbol *sym)
2164 struct superbfd *sbfd = fetch_superbfd(abfd);
2165 if (bfd_is_const_section(sym->section))
2166 return false;
2167 struct supersect *ss = fetch_supersect(sbfd, sym->section);
2169 asymbol **symp;
2170 for (symp = ss->syms.data; symp < ss->syms.data + ss->syms.size; symp++) {
2171 if (sym == *symp)
2172 break;
2174 return symp >= ss->syms.data + ss->syms.size &&
2175 (sym->flags & BSF_SECTION_SYM) == 0;
2178 void filter_symbols(bfd *ibfd, bfd *obfd, struct asymbolp_vec *osyms,
2179 struct asymbolp_vec *isyms)
2181 asymbol **symp;
2182 struct superbfd *sbfd = fetch_superbfd(ibfd);
2183 for (symp = isyms->data; symp < isyms->data + isyms->size; symp++) {
2184 asymbol *sym = *symp;
2185 struct supersect *sym_ss = NULL;
2186 struct span *sym_span = NULL;
2187 if (!bfd_is_const_section(sym->section)) {
2188 sym_ss = fetch_supersect(sbfd, sym->section);
2189 sym_span = find_span(sym_ss, sym->value);
2192 if (mode("keep") && (sym->flags & BSF_GLOBAL) != 0 &&
2193 !(mode("keep-primary") && sym_span != NULL &&
2194 sym_span->new))
2195 sym->flags = (sym->flags & ~BSF_GLOBAL) | BSF_LOCAL;
2197 if (mode("finalize") && (sym->flags & BSF_GLOBAL) != 0)
2198 sym->flags = (sym->flags & ~BSF_GLOBAL) | BSF_LOCAL;
2200 bool keep = bfd_is_const_section(sym->section) ||
2201 (sym_ss->keep && (sym->flags & BSF_SECTION_SYM) != 0) ||
2202 (sym_span != NULL && sym_span->keep);
2203 if (bfd_is_und_section(sym->section) &&
2204 (sym->flags & BSF_KEEP) == 0)
2205 keep = false;
2206 if (deleted_table_section_symbol(ibfd, sym))
2207 keep = false;
2209 if (mode("keep-helper") && sym_ss != NULL &&
2210 sym_ss->type == SS_TYPE_EXPORT)
2211 keep = false;
2213 if (keep) {
2214 if (sym_ss != NULL && !sym_ss->keep) {
2215 err(sbfd, "Kept symbol %s in unkept section "
2216 "%s\n", sym->name, sym->section->name);
2217 DIE;
2219 *vec_grow(osyms, 1) = sym;
2224 void read_str_set(struct str_vec *strs)
2226 char *buf = NULL;
2227 size_t n = 0;
2228 assert(getline(&buf, &n, stdin) >= 0);
2229 vec_init(strs);
2230 char *saveptr;
2231 while (1) {
2232 char *str = strtok_r(buf, " \n", &saveptr);
2233 buf = NULL;
2234 if (str == NULL)
2235 break;
2236 *vec_grow(strs, 1) = str;
2240 bool str_in_set(const char *str, const struct str_vec *strs)
2242 const char **strp;
2243 for (strp = strs->data; strp < strs->data + strs->size; strp++) {
2244 if (strcmp(str, *strp) == 0)
2245 return true;
2247 return false;
2250 bool is_table_section(const char *name, bool consider_other)
2252 struct supersect *tables_ss =
2253 fetch_supersect(offsets_sbfd,
2254 bfd_get_section_by_name(offsets_sbfd->abfd,
2255 ".ksplice_table_sections"));
2256 const struct table_section *ts;
2257 for (ts = tables_ss->contents.data;
2258 (void *)ts < tables_ss->contents.data + tables_ss->contents.size;
2259 ts++) {
2260 if (strcmp(name, read_string(tables_ss, &ts->sect)) == 0)
2261 return true;
2262 const char *osect_name = read_string(tables_ss,
2263 &ts->other_sect);
2264 if (consider_other && osect_name != NULL &&
2265 strcmp(name, osect_name) == 0)
2266 return true;
2267 const char *crc_name = read_string(tables_ss, &ts->crc_sect);
2268 if (consider_other && crc_name != NULL &&
2269 strcmp(name, crc_name) == 0)
2270 return true;
2272 return false;
2275 const struct table_section *get_table_section(const char *name)
2277 struct supersect *tables_ss =
2278 fetch_supersect(offsets_sbfd,
2279 bfd_get_section_by_name(offsets_sbfd->abfd,
2280 ".ksplice_table_sections"));
2281 const struct table_section *ts;
2282 for (ts = tables_ss->contents.data;
2283 (void *)ts < tables_ss->contents.data + tables_ss->contents.size;
2284 ts++) {
2285 if (strcmp(name, read_string(tables_ss, &ts->sect)) == 0)
2286 return ts;
2288 return NULL;
2291 enum supersect_type supersect_type(struct supersect *ss)
2293 if (mode("finalize") &&
2294 strcmp(finalize_target, "vmlinux") == 0 &&
2295 (starts_with(ss->name, ".ksplice_relocs.exit") ||
2296 starts_with(ss->name, ".ksplice_sections.exit") ||
2297 starts_with(ss->name, ".ksplice_patches.exit")))
2298 return SS_TYPE_EXIT;
2299 if (starts_with(ss->name, ".ksplice_call"))
2300 return SS_TYPE_KSPLICE_CALL;
2301 if (starts_with(ss->name, ".ksplice_options"))
2302 return SS_TYPE_SPECIAL;
2303 if (starts_with(ss->name, ".ksplice"))
2304 return SS_TYPE_KSPLICE;
2306 if (starts_with(ss->name, ".init"))
2307 return SS_TYPE_IGNORED;
2308 if (starts_with(ss->name, ".security_initcall.init"))
2309 return SS_TYPE_IGNORED;
2310 if (starts_with(ss->name, ".con_initcall.init"))
2311 return SS_TYPE_IGNORED;
2312 if (starts_with(ss->name, ".x86cpuvendor.init"))
2313 return SS_TYPE_IGNORED;
2314 if (starts_with(ss->name, ".early_param.init"))
2315 return SS_TYPE_IGNORED;
2316 if (starts_with(ss->name, ".taglist.init"))
2317 return SS_TYPE_IGNORED;
2318 if (starts_with(ss->name, ".arch.info.init"))
2319 return SS_TYPE_IGNORED;
2320 if (starts_with(ss->name, ".proc.info.init"))
2321 return SS_TYPE_IGNORED;
2322 /* .pci_fixup_* sections really should be treated as global rodata
2323 referenced only from quirks.c */
2324 if (starts_with(ss->name, ".pci_fixup_"))
2325 return SS_TYPE_IGNORED;
2326 /* .builtin_fw sections are similar to .pci_fixup */
2327 if (starts_with(ss->name, ".builtin_fw"))
2328 return SS_TYPE_IGNORED;
2329 /* same for .tracedata */
2330 if (starts_with(ss->name, ".tracedata"))
2331 return SS_TYPE_IGNORED;
2332 if (starts_with(ss->name, ".debug"))
2333 return SS_TYPE_IGNORED;
2334 /* .eh_frame should probably be discarded, not ignored */
2335 if (starts_with(ss->name, ".eh_frame"))
2336 return SS_TYPE_IGNORED;
2337 if (config->ignore_devinit && starts_with(ss->name, ".devinit"))
2338 return SS_TYPE_IGNORED;
2339 if (config->ignore_meminit && starts_with(ss->name, ".meminit"))
2340 return SS_TYPE_IGNORED;
2341 if (config->ignore_cpuinit && starts_with(ss->name, ".cpuinit"))
2342 return SS_TYPE_IGNORED;
2343 if (config->ignore_devinit && starts_with(ss->name, ".devexit"))
2344 return SS_TYPE_IGNORED;
2345 if (config->ignore_meminit && starts_with(ss->name, ".memexit"))
2346 return SS_TYPE_IGNORED;
2347 if (config->ignore_cpuinit && starts_with(ss->name, ".cpuexit"))
2348 return SS_TYPE_IGNORED;
2349 if (starts_with(ss->name, ".vgetcpu_mode") ||
2350 starts_with(ss->name, ".jiffies") ||
2351 starts_with(ss->name, ".wall_jiffies") ||
2352 starts_with(ss->name, ".vxtime") ||
2353 starts_with(ss->name, ".sys_tz") ||
2354 starts_with(ss->name, ".sysctl_vsyscall") ||
2355 starts_with(ss->name, ".xtime") ||
2356 starts_with(ss->name, ".xtime_lock") ||
2357 starts_with(ss->name, ".vsyscall"))
2358 return SS_TYPE_IGNORED;
2359 if (starts_with(ss->name, ".vdso"))
2360 return SS_TYPE_IGNORED;
2362 if (starts_with(ss->name, ".exit.text"))
2363 return SS_TYPE_TEXT;
2364 if (starts_with(ss->name, ".exit.data"))
2365 return SS_TYPE_DATA;
2367 if (starts_with(ss->name, ".text") ||
2368 starts_with(ss->name, ".kernel.text") ||
2369 starts_with(ss->name, ".devinit.text") ||
2370 starts_with(ss->name, ".meminit.text") ||
2371 starts_with(ss->name, ".cpuinit.text") ||
2372 starts_with(ss->name, ".devexit.text") ||
2373 starts_with(ss->name, ".memexit.text") ||
2374 starts_with(ss->name, ".cpuexit.text") ||
2375 starts_with(ss->name, ".ref.text") ||
2376 starts_with(ss->name, ".spinlock.text") ||
2377 starts_with(ss->name, ".kprobes.text") ||
2378 starts_with(ss->name, ".sched.text") ||
2379 (mode("keep-helper") && starts_with(ss->name, ".fixup")))
2380 return SS_TYPE_TEXT;
2382 int n = -1;
2383 if (sscanf(ss->name, ".rodata.str%*u.%*u%n", &n) >= 0 &&
2384 n == strlen(ss->name))
2385 return ss->entsize == 1 ? SS_TYPE_STRING : SS_TYPE_RODATA;
2387 if (starts_with(ss->name, ".rodata") ||
2388 starts_with(ss->name, ".kernel.rodata") ||
2389 starts_with(ss->name, ".devinit.rodata") ||
2390 starts_with(ss->name, ".meminit.rodata") ||
2391 starts_with(ss->name, ".cpuinit.rodata") ||
2392 starts_with(ss->name, ".devexit.rodata") ||
2393 starts_with(ss->name, ".memexit.rodata") ||
2394 starts_with(ss->name, ".cpuexit.rodata") ||
2395 starts_with(ss->name, ".ref.rodata") ||
2396 starts_with(ss->name, "__markers_strings") ||
2397 starts_with(ss->name, "__bug_table") ||
2398 (mode("keep-helper") && starts_with(ss->name, "__ex_table")))
2399 return SS_TYPE_RODATA;
2401 if (starts_with(ss->name, ".bss"))
2402 return SS_TYPE_DATA;
2404 /* Ignore .data.percpu sections */
2405 if (starts_with(ss->name, ".data.percpu") ||
2406 starts_with(ss->name, ".kernel.data.percpu"))
2407 return SS_TYPE_IGNORED;
2408 if (starts_with(ss->name, ".data") ||
2409 starts_with(ss->name, ".kernel.data") ||
2410 starts_with(ss->name, ".devinit.data") ||
2411 starts_with(ss->name, ".cpuinit.data") ||
2412 starts_with(ss->name, ".meminit.data") ||
2413 starts_with(ss->name, ".devexit.data") ||
2414 starts_with(ss->name, ".memexit.data") ||
2415 starts_with(ss->name, ".cpuexit.data") ||
2416 starts_with(ss->name, ".ref.data") ||
2417 starts_with(ss->name, "__markers"))
2418 return SS_TYPE_DATA;
2420 /* We replace all the ksymtab strings, so delete them */
2421 if (strcmp(ss->name, "__ksymtab_strings") == 0)
2422 return SS_TYPE_STRING;
2423 if (starts_with(ss->name, "__ksymtab"))
2424 return SS_TYPE_EXPORT;
2425 if (starts_with(ss->name, "__kcrctab"))
2426 return SS_TYPE_SPECIAL;
2428 if (is_table_section(ss->name, true))
2429 return SS_TYPE_SPECIAL;
2431 if (starts_with(ss->name, ".ARM."))
2432 return SS_TYPE_SPECIAL;
2434 if (starts_with(ss->name, ".note"))
2435 return SS_TYPE_IGNORED;
2436 if (starts_with(ss->name, ".comment"))
2437 return SS_TYPE_IGNORED;
2438 if (starts_with(ss->name, "__param"))
2439 return SS_TYPE_IGNORED;
2440 if (starts_with(ss->name, ".exitcall.exit"))
2441 return SS_TYPE_IGNORED;
2442 if (starts_with(ss->name, ".modinfo"))
2443 return SS_TYPE_IGNORED;
2445 return SS_TYPE_UNKNOWN;
2448 void initialize_supersect_types(struct superbfd *sbfd)
2450 asection *sect;
2451 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2452 struct supersect *ss = fetch_supersect(sbfd, sect);
2453 ss->type = supersect_type(ss);
2454 ss->orig_type = ss->type;
2455 if (ss->type == SS_TYPE_UNKNOWN) {
2456 err(sbfd, "Unknown section type: %s\n", ss->name);
2457 DIE;
2462 static void init_label_map(struct superbfd *sbfd)
2464 struct label_map *map;
2466 vec_init(&sbfd->maps);
2467 init_csyms(sbfd);
2468 init_callers(sbfd);
2470 struct symbol_hash csyms;
2471 symbol_hash_init(&csyms);
2473 asymbol **symp;
2474 for (symp = sbfd->syms.data;
2475 symp < sbfd->syms.data + sbfd->syms.size; symp++) {
2476 asymbol *csym = canonical_symbol(sbfd, *symp);
2477 if (csym == NULL)
2478 continue;
2479 char *key = strprintf("%p", csym);
2480 asymbol **csymp = symbol_hash_lookup(&csyms, key, TRUE);
2481 free(key);
2482 if (*csymp != NULL)
2483 continue;
2484 *csymp = csym;
2486 map = vec_grow(&sbfd->maps, 1);
2487 map->csym = csym;
2488 map->count = 0;
2489 map->label = symbol_label(sbfd, csym);
2492 struct label_mapp_hash label_maps;
2493 label_mapp_hash_init(&label_maps);
2494 for (map = sbfd->maps.data;
2495 map < sbfd->maps.data + sbfd->maps.size; map++) {
2496 struct label_map **mapp =
2497 label_mapp_hash_lookup(&label_maps, map->label, TRUE);
2498 if (*mapp == NULL) {
2499 *mapp = map;
2500 continue;
2503 struct label_map *first_map = *mapp;
2504 if (first_map->count == 0)
2505 first_map->label = strprintf("%s~%d", map->label, 0);
2506 map->label = strprintf("%s~%d", map->label, ++first_map->count);
2509 label_mapp_hash_init(&sbfd->maps_hash);
2510 for (map = sbfd->maps.data;
2511 map < sbfd->maps.data + sbfd->maps.size; map++) {
2512 char *key = strprintf("%p", map->csym);
2513 struct label_map **mapp =
2514 label_mapp_hash_lookup(&sbfd->maps_hash, key, TRUE);
2515 free(key);
2516 *mapp = map;
2517 map->orig_label = map->label;
2521 static const char *label_lookup(struct superbfd *sbfd, asymbol *sym)
2523 asymbol *csym = canonical_symbol(sbfd, sym);
2524 char *key = strprintf("%p", csym);
2525 struct label_map **mapp =
2526 label_mapp_hash_lookup(&sbfd->maps_hash, key, FALSE);
2527 free(key);
2528 if (mapp == NULL)
2529 DIE;
2530 return (*mapp)->label;
2533 static void print_label_changes(struct superbfd *sbfd)
2535 asection *sect;
2536 struct span *span;
2537 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2538 struct supersect *ss = fetch_supersect(sbfd, sect);
2539 for (span = ss->spans.data;
2540 span < ss->spans.data + ss->spans.size; span++) {
2541 if (strcmp(span->label, span->orig_label) != 0)
2542 debug1(sbfd, "Label change: %s -> %s\n",
2543 span->label, span->orig_label);
2548 static void label_map_set(struct superbfd *sbfd, const char *oldlabel,
2549 const char *label)
2551 struct label_map *map;
2552 for (map = sbfd->maps.data;
2553 map < sbfd->maps.data + sbfd->maps.size; map++) {
2554 if (strcmp(map->orig_label, oldlabel) == 0) {
2555 if (strcmp(map->orig_label, map->label) != 0 &&
2556 strcmp(map->label, label) != 0)
2557 DIE;
2558 map->label = label;
2559 return;
2562 DIE;
2565 static void change_initial_label(struct span *span, const char *label)
2567 struct superbfd *sbfd = span->ss->parent;
2568 span->label = label;
2569 span->orig_label = label;
2570 if (span->symbol) {
2571 asymbol *csym = canonical_symbol(sbfd, span->symbol);
2572 char *key = strprintf("%p", csym);
2573 struct label_map **mapp =
2574 label_mapp_hash_lookup(&sbfd->maps_hash, key, FALSE);
2575 free(key);
2576 assert(mapp);
2577 (*mapp)->label = span->label;
2578 (*mapp)->orig_label = span->orig_label;
2579 span->symbol = NULL;
2583 static void init_callers(struct superbfd *sbfd)
2585 string_hash_init(&sbfd->callers);
2586 asection *sect;
2587 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2588 struct supersect *ss = fetch_supersect(sbfd, sect);
2589 arelent **relocp;
2590 for (relocp = ss->relocs.data;
2591 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
2592 asymbol *sym = *(*relocp)->sym_ptr_ptr;
2593 unsigned long val =
2594 sym->value + get_reloc_offset(ss, *relocp, true);
2595 char *key = strprintf("%s+%lx", sym->section->name,
2596 val);
2597 const char **ret = string_hash_lookup(&sbfd->callers,
2598 key, TRUE);
2599 free(key);
2600 asymbol *csym = canonical_symbol(sbfd, sect->symbol);
2601 if (*ret != NULL)
2602 *ret = "*multiple_callers*";
2603 else if (static_local_symbol(sbfd, csym))
2604 *ret = static_local_symbol(sbfd, csym);
2605 else
2606 *ret = sect->name;
2611 static const char *find_caller(struct supersect *ss, asymbol *sym)
2613 char *key = strprintf("%s+%lx", sym->section->name,
2614 (unsigned long)sym->value);
2615 const char **ret = string_hash_lookup(&ss->parent->callers, key, FALSE);
2616 free(key);
2618 if (ret == NULL)
2619 return "*no_caller*";
2620 return *ret;
2623 static void init_csyms(struct superbfd *sbfd)
2625 asymbolpp_hash_init(&sbfd->csyms);
2627 asymbol **symp;
2628 for (symp = sbfd->syms.data; symp < sbfd->syms.data + sbfd->syms.size;
2629 symp++) {
2630 asymbol *sym = *symp;
2631 if ((sym->flags & BSF_DEBUGGING) != 0)
2632 continue;
2633 char *key = strprintf("%s+%lx", sym->section->name,
2634 (unsigned long)sym->value);
2635 asymbol ***csympp = asymbolpp_hash_lookup(&sbfd->csyms, key,
2636 TRUE);
2637 free(key);
2638 if (*csympp == NULL) {
2639 *csympp = symp;
2640 continue;
2642 asymbol *csym = **csympp;
2643 if ((csym->flags & BSF_GLOBAL) != 0)
2644 continue;
2645 if ((sym->flags & BSF_GLOBAL) != 0)
2646 *csympp = symp;
2650 static asymbol **symbolp_scan(struct supersect *ss, bfd_vma value)
2652 char *key = strprintf("%s+%lx", ss->name, (unsigned long)value);
2653 asymbol ***csympp =
2654 asymbolpp_hash_lookup(&ss->parent->csyms, key, FALSE);
2655 free(key);
2656 if (csympp != NULL)
2657 return *csympp;
2659 /* For section symbols of sections containing no symbols, return the
2660 section symbol that relocations are generated against */
2661 if (value == 0)
2662 return &ss->symbol;
2663 return NULL;
2666 static asymbol **canonical_symbolp(struct superbfd *sbfd, asymbol *sym)
2668 if (bfd_is_const_section(sym->section)) {
2669 asymbol **csymp;
2670 for (csymp = sbfd->syms.data;
2671 csymp < sbfd->syms.data + sbfd->syms.size; csymp++) {
2672 if (sym == *csymp)
2673 return csymp;
2675 return NULL;
2677 return symbolp_scan(fetch_supersect(sbfd, sym->section), sym->value);
2680 static asymbol *canonical_symbol(struct superbfd *sbfd, asymbol *sym)
2682 if (bfd_is_const_section(sym->section))
2683 return sym;
2684 asymbol **symp = canonical_symbolp(sbfd, sym);
2685 return symp != NULL ? *symp : NULL;
2688 static char *static_local_symbol(struct superbfd *sbfd, asymbol *sym)
2690 struct supersect *ss = fetch_supersect(sbfd, sym->section);
2691 if ((sym->flags & BSF_LOCAL) == 0 || (sym->flags & BSF_OBJECT) == 0)
2692 return NULL;
2693 char *dot = strrchr(sym->name, '.');
2694 if (dot == NULL || dot[1 + strspn(dot + 1, "0123546789")] != '\0')
2695 return NULL;
2696 char *basename = strndup(sym->name, dot - sym->name);
2698 /* Handle C.123.12345 symbols */
2699 dot = strrchr(basename, '.');
2700 if (dot != NULL && dot[1 + strspn(dot + 1, "0123546789")] == '\0')
2701 basename = strndup(basename, dot - basename);
2702 const char *caller;
2703 if (strcmp(basename, "__func__") == 0 ||
2704 strcmp(basename, "__PRETTY_FUNCTION__") == 0)
2705 caller = (const char *)ss->contents.data + sym->value;
2706 else
2707 caller = find_caller(ss, sym);
2708 return strprintf("%s<%s>", basename, caller);
2711 static char *symbol_label(struct superbfd *sbfd, asymbol *sym)
2713 const char *filename = sbfd->abfd->filename;
2714 char *c = strstr(filename, ".KSPLICE");
2715 int flen = (c == NULL ? strlen(filename) : c - filename);
2717 char *label;
2718 if (bfd_is_und_section(sym->section) || (sym->flags & BSF_GLOBAL) != 0) {
2719 label = strdup(sym->name);
2720 } else if (bfd_is_const_section(sym->section)) {
2721 label = strprintf("%s<%.*s>", sym->name, flen, filename);
2722 } else {
2723 asymbol *gsym = canonical_symbol(sbfd, sym);
2725 if (gsym == NULL)
2726 label = strprintf("%s+%lx<%.*s>",
2727 sym->section->name,
2728 (unsigned long)sym->value,
2729 flen, filename);
2730 else if ((gsym->flags & BSF_GLOBAL) != 0)
2731 label = strdup(gsym->name);
2732 else if (static_local_symbol(sbfd, gsym))
2733 label = strprintf("%s+%lx<%.*s>",
2734 static_local_symbol(sbfd, gsym),
2735 (unsigned long)sym->value,
2736 flen, filename);
2737 else
2738 label = strprintf("%s<%.*s>",
2739 gsym->name, flen, filename);
2742 return label;
2745 static void keep_span(struct span *span)
2747 span->keep = true;
2748 span->ss->keep = true;
2751 static struct span *new_span(struct supersect *ss, bfd_vma start, bfd_vma size)
2753 struct span *span = vec_grow(&ss->spans, 1);
2754 span->size = size;
2755 span->start = start;
2756 span->ss = ss;
2757 span->keep = true;
2758 span->new = false;
2759 span->patch = false;
2760 span->bugpatch = false;
2761 span->datapatch = false;
2762 span->precallable = starts_with(ss->name, ".ksplice_call_pre_apply") ||
2763 starts_with(ss->name, ".ksplice_call_check_apply") ||
2764 starts_with(ss->name, ".ksplice_call_fail_apply") ||
2765 starts_with(ss->name, ".ksplice_call_post_remove");
2766 span->match = NULL;
2767 span->shift = 0;
2768 asymbol **symp = symbolp_scan(ss, span->start);
2769 if (symp != NULL) {
2770 span->symbol = *symp;
2771 span->label = label_lookup(ss->parent, span->symbol);
2772 } else {
2773 span->symbol = NULL;
2774 const char *label = label_lookup(ss->parent, ss->symbol);
2775 if (span->start != 0)
2776 span->label = strprintf("%s<span:%lx>", label,
2777 (unsigned long)span->start);
2778 else
2779 span->label = label;
2781 span->orig_label = span->label;
2782 return span;
2785 static void initialize_string_spans(struct supersect *ss)
2787 const char *str;
2788 for (str = ss->contents.data;
2789 (void *)str < ss->contents.data + ss->contents.size;) {
2790 bfd_vma start = (unsigned long)str -
2791 (unsigned long)ss->contents.data;
2792 bfd_vma size = strlen(str) + 1;
2793 while ((start + size) % (1 << ss->alignment) != 0 &&
2794 start + size < ss->contents.size) {
2795 /* Some string sections, like __ksymtab_strings, only
2796 align some strings with the declared alignment */
2797 if (str[size] != '\0')
2798 break;
2799 size++;
2801 new_span(ss, start, size);
2802 str += size;
2806 static int compare_ulongs(const void *va, const void *vb)
2808 const unsigned long *a = va, *b = vb;
2809 return *a - *b;
2812 static void initialize_table_spans(struct superbfd *sbfd,
2813 struct table_section *s)
2815 asection *isection = bfd_get_section_by_name(sbfd->abfd, s->sect);
2816 if (isection == NULL)
2817 return;
2818 struct supersect *ss = fetch_supersect(sbfd, isection);
2819 if (ss->alignment < ffs(s->entry_align) - 1)
2820 ss->alignment = ffs(s->entry_align) - 1;
2822 asection *other_sect = NULL;
2823 if (s->other_sect != NULL)
2824 other_sect = bfd_get_section_by_name(sbfd->abfd, s->other_sect);
2825 struct supersect *other_ss = NULL;
2826 if (other_sect != NULL)
2827 other_ss = fetch_supersect(sbfd, other_sect);
2829 asection *crc_sect = NULL;
2830 if (s->crc_sect != NULL)
2831 crc_sect = bfd_get_section_by_name(sbfd->abfd, s->crc_sect);
2832 struct supersect *crc_ss = NULL;
2833 if (crc_sect != NULL)
2834 crc_ss = fetch_supersect(sbfd, crc_sect);
2836 struct ulong_vec offsets;
2837 vec_init(&offsets);
2839 void *entry;
2840 for (entry = ss->contents.data;
2841 entry < ss->contents.data + ss->contents.size;
2842 entry += s->entry_size) {
2843 struct span *span = new_span(ss, addr_offset(ss, entry),
2844 s->entry_size);
2845 if ((span->symbol == NULL ||
2846 (span->symbol->flags & BSF_SECTION_SYM) != 0) &&
2847 s->has_addr) {
2848 arelent *reloc = find_reloc(ss, entry + s->addr_offset);
2849 assert(reloc);
2850 struct span *target_span = reloc_target_span(ss, reloc);
2851 assert(target_span);
2852 asymbol *sym = *reloc->sym_ptr_ptr;
2853 unsigned long val = get_reloc_offset(ss, reloc, true) +
2854 sym->value - (target_span->start +
2855 target_span->shift);
2856 char *label = strprintf("%s<target:%s+%lx>", ss->name,
2857 target_span->label, val);
2858 change_initial_label(span, label);
2861 if (other_sect != NULL) {
2862 asymbol *sym;
2863 bfd_vma offset = read_reloc(ss, entry + s->other_offset,
2864 sizeof(void *), &sym);
2865 if (sym->section == other_sect) {
2866 assert(offset >= 0 &&
2867 offset < other_ss->contents.size);
2868 *vec_grow(&offsets, 1) = offset;
2872 if (crc_sect != NULL)
2873 new_span(crc_ss, addr_offset(ss, entry) / s->entry_size
2874 * s->crc_size, s->crc_size);
2876 if (ss->type == SS_TYPE_EXPORT) {
2877 const char *symname = read_string(ss, entry +
2878 s->other_offset);
2879 char *label = strprintf("%s:%s", ss->name, symname);
2880 change_initial_label(span, label);
2884 if (other_sect == NULL)
2885 return;
2887 qsort(offsets.data, offsets.size, sizeof(*offsets.data),
2888 compare_ulongs);
2889 *vec_grow(&offsets, 1) = other_ss->contents.size;
2891 unsigned long *off;
2892 for (off = offsets.data; off < offsets.data + offsets.size - 1; off++) {
2893 if (*off != *(off + 1))
2894 new_span(other_ss, *off, *(off + 1) - *off);
2898 static void initialize_table_section_spans(struct superbfd *sbfd)
2900 struct supersect *tables_ss =
2901 fetch_supersect(offsets_sbfd,
2902 bfd_get_section_by_name(offsets_sbfd->abfd,
2903 ".ksplice_table_sections"));
2904 const struct table_section *ts;
2905 struct table_section s;
2906 for (ts = tables_ss->contents.data;
2907 (void *)ts < tables_ss->contents.data + tables_ss->contents.size;
2908 ts++) {
2909 s = *ts;
2910 s.sect = read_string(tables_ss, &ts->sect);
2911 s.other_sect = read_string(tables_ss, &ts->other_sect);
2912 s.crc_sect = read_string(tables_ss, &ts->crc_sect);
2913 initialize_table_spans(sbfd, &s);
2917 static void initialize_ksplice_call_spans(struct supersect *ss)
2919 arelent **relocp;
2920 for (relocp = ss->relocs.data;
2921 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
2922 arelent *reloc = *relocp;
2923 new_span(ss, reloc->address, bfd_get_reloc_size(reloc->howto));
2924 /* the span labels should already be unique */
2928 static void initialize_spans(struct superbfd *sbfd)
2930 asection *sect;
2931 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2932 if (is_table_section(sect->name, true) && mode("keep"))
2933 continue;
2935 struct supersect *ss = fetch_supersect(sbfd, sect);
2936 if (ss->type == SS_TYPE_STRING)
2937 initialize_string_spans(ss);
2938 else if (ss->type == SS_TYPE_KSPLICE_CALL)
2939 initialize_ksplice_call_spans(ss);
2940 else
2941 new_span(ss, 0, ss->contents.size);
2943 if (mode("keep"))
2944 initialize_table_section_spans(sbfd);
2947 struct span *reloc_target_span(struct supersect *ss, arelent *reloc)
2949 asymbol *sym_ptr = *reloc->sym_ptr_ptr;
2950 if (bfd_is_const_section(sym_ptr->section))
2951 return NULL;
2953 bfd_vma addend = get_reloc_offset(ss, reloc, true) + sym_ptr->value;
2954 struct supersect *sym_ss =
2955 fetch_supersect(ss->parent, sym_ptr->section);
2956 struct span *span, *target_span = sym_ss->spans.data;
2957 for (span = sym_ss->spans.data;
2958 span < sym_ss->spans.data + sym_ss->spans.size; span++) {
2959 if (addend >= span->start && addend < span->start + span->size)
2960 target_span = span;
2962 return target_span;
2965 struct span *find_span(struct supersect *ss, bfd_size_type address)
2967 struct span *span;
2968 for (span = ss->spans.data; span < ss->spans.data + ss->spans.size;
2969 span++) {
2970 if (address >= span->start &&
2971 address < span->start + span->size)
2972 return span;
2974 /* Deal with empty BSS sections */
2975 if (ss->contents.size == 0 && ss->spans.size > 0)
2976 return ss->spans.data;
2977 return NULL;
2980 void compute_span_shifts(struct superbfd *sbfd)
2982 asection *sect;
2983 struct span *span;
2984 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2985 struct supersect *ss = fetch_supersect(sbfd, sect);
2986 if (!ss->keep)
2987 continue;
2988 bfd_size_type offset = 0;
2989 for (span = ss->spans.data;
2990 span < ss->spans.data + ss->spans.size; span++) {
2991 if (!span->keep)
2992 continue;
2993 span->shift = offset - span->start;
2994 offset += span->size;
2999 void remove_unkept_spans(struct superbfd *sbfd)
3001 asection *sect;
3002 struct span *span;
3003 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
3004 struct supersect *ss = fetch_supersect(sbfd, sect);
3005 delete_obsolete_relocs(ss);
3006 struct arelentp_vec orig_relocs;
3007 vec_move(&orig_relocs, &ss->relocs);
3008 arelent **relocp, *reloc;
3009 for (relocp = orig_relocs.data;
3010 relocp < orig_relocs.data + orig_relocs.size; relocp++) {
3011 reloc = *relocp;
3012 asymbol *sym = *reloc->sym_ptr_ptr;
3013 span = reloc_target_span(ss, reloc);
3014 if ((span != NULL && span->keep && span->shift == 0) ||
3015 bfd_is_const_section(sym->section)) {
3016 *vec_grow(&ss->relocs, 1) = reloc;
3017 continue;
3019 struct supersect *sym_ss =
3020 fetch_supersect(sbfd, sym->section);
3021 if (span != NULL && (sym->flags & BSF_SECTION_SYM) == 0
3022 && find_span(sym_ss, sym->value) != span) {
3023 err(sbfd, "Spans for symbol %s and relocation "
3024 "target do not match in sect %s\n",
3025 sym->name, sym_ss->name);
3026 DIE;
3028 if (span != NULL && span->keep) {
3029 arelent *new_reloc = malloc(sizeof(*new_reloc));
3030 *new_reloc = *reloc;
3031 new_reloc->addend =
3032 get_reloc_offset(ss, reloc, false);
3033 new_reloc->addend += span->shift;
3034 *vec_grow(&ss->new_relocs, 1) = new_reloc;
3039 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
3040 struct supersect *ss = fetch_supersect(sbfd, sect), orig_ss;
3041 if (!ss->keep)
3042 continue;
3043 supersect_move(&orig_ss, ss);
3044 vec_init(&ss->spans);
3045 for (span = orig_ss.spans.data;
3046 span < orig_ss.spans.data + orig_ss.spans.size; span++) {
3047 if (!span->keep)
3048 continue;
3049 struct span *new_span = vec_grow(&ss->spans, 1);
3050 *new_span = *span;
3051 new_span->start = span->start + span->shift;
3052 new_span->shift = 0;
3053 sect_copy(ss, sect_do_grow(ss, 1, span->size, 1),
3054 &orig_ss, orig_ss.contents.data + span->start,
3055 span->size);
3060 static void init_objmanip_superbfd(struct superbfd *sbfd)
3062 init_label_map(sbfd);
3063 initialize_supersect_types(sbfd);
3064 initialize_spans(sbfd);
3065 load_options(sbfd);
3068 void mangle_section_name(struct superbfd *sbfd, const char *name)
3070 asection *sect = bfd_get_section_by_name(sbfd->abfd, name);
3071 if (sect == NULL)
3072 return;
3073 struct supersect *ss = fetch_supersect(sbfd, sect);
3074 ss->name = strprintf(".ksplice_pre.%s", ss->name);
3077 static void write_bugline_patches(struct superbfd *sbfd)
3079 const struct table_section *ts = get_table_section("__bug_table");
3080 asection *sect = bfd_get_section_by_name(sbfd->abfd, "__bug_table");
3081 if (sect == NULL)
3082 return;
3083 struct supersect *ss = fetch_supersect(sbfd, sect);
3084 assert(ts != NULL);
3086 void *entry;
3087 for (entry = ss->contents.data;
3088 entry < ss->contents.data + ss->contents.size;
3089 entry += ts->entry_size) {
3090 struct span *span = find_span(ss, addr_offset(ss, entry));
3091 assert(span != NULL);
3092 if (!span->bugpatch)
3093 continue;
3094 arelent *reloc = find_reloc(ss, entry + ts->addr_offset);
3095 assert(reloc != NULL);
3096 asymbol *sym = *reloc->sym_ptr_ptr;
3097 assert(!bfd_is_const_section(sym->section));
3099 struct supersect *kpatch_ss =
3100 make_section(sbfd, ".ksplice_patches%s",
3101 sym->section->name);
3102 struct ksplice_patch *kpatch =
3103 sect_grow(kpatch_ss, 1, struct ksplice_patch);
3104 write_ksplice_patch_reloc
3105 (kpatch_ss, sym->section->name, &kpatch->oldaddr,
3106 sizeof(kpatch->oldaddr), span->label, ts->other_offset);
3108 unsigned short *line =
3109 write_patch_storage(kpatch_ss, kpatch, sizeof(*line), NULL);
3110 *line = *(unsigned short *)(entry + ts->other_offset);
3111 kpatch->type = KSPLICE_PATCH_BUGLINE;
3115 void *write_patch_storage(struct supersect *ss, struct ksplice_patch *kpatch,
3116 size_t size, struct supersect **data_ssp)
3118 struct supersect *data_ss = make_section(ss->parent,
3119 ".ksplice_patch_data");
3120 char *saved = sect_do_grow(data_ss, 1, size, 1);
3121 write_reloc(ss, &kpatch->saved, &data_ss->symbol,
3122 addr_offset(data_ss, saved));
3123 char *data = sect_do_grow(data_ss, 1, size, 1);
3124 write_reloc(ss, &kpatch->contents, &data_ss->symbol,
3125 addr_offset(data_ss, data));
3126 kpatch->size = size;
3127 if (data_ssp != NULL)
3128 *data_ssp = data_ss;
3129 return data;