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
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
53 #include "objcommon.h"
54 #include "kmodsrc/ksplice.h"
55 #include "kmodsrc/offsets.h"
56 #include "ksplice-patch/ksplice-patch.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
,
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
,
126 static void write_ksplice_nonreloc_howto(struct supersect
*ss
,
127 const struct ksplice_reloc_howto
129 enum ksplice_reloc_howto_type type
,
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
,
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
,
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
,
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
,
174 arelent
*create_reloc(struct supersect
*ss
, const void *addr
, asymbol
**symp
,
176 static void foreach_symbol_pair(struct superbfd
*oldsbfd
, struct superbfd
*newsbfd
,
177 void (*fn
)(struct span
*old_span
,
179 struct span
*new_span
,
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
,
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
);
219 #define debug_(sbfd, level, fmt, ...) \
221 if (verbose >= (level)) \
222 printf("%s: " fmt, (sbfd)->abfd->filename, \
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, ...) \
229 fprintf(stderr, "%s: " fmt, (sbfd)->abfd->filename, \
233 struct str_vec delsects
, rmsyms
;
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
,
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");
260 FILE *fp
= fopen(strprintf("%s/System.map", config_dir
), "r");
262 addr_vec_hash_init(&system_map
);
266 while (fscanf(fp
, "%lx %c %as\n", &addr
, &type
, &sym
) == 3)
267 *vec_grow(addr_vec_hash_lookup(&system_map
, sym
, TRUE
),
272 void load_ksplice_symbol_offsets(struct superbfd
*sbfd
)
274 asection
*sect
= bfd_get_section_by_name(sbfd
->abfd
,
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
);
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
);
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
,
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
,
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
;
328 err(sbfd
, "Unrecognized Ksplice option %d\n",
335 bool matchable_data_section(struct supersect
*ss
)
337 if (ss
->type
== SS_TYPE_STRING
)
339 if (ss
->type
== SS_TYPE_RODATA
)
341 if (ss
->type
== SS_TYPE_DATA
&& ss
->relocs
.size
!= 0)
343 if (ss
->type
== SS_TYPE_EXPORT
)
348 bool unchangeable_section(struct supersect
*ss
)
350 if (ss
->type
== SS_TYPE_DATA
)
352 if (ss
->type
== SS_TYPE_IGNORED
&& !starts_with(ss
->name
, ".debug") &&
353 strcmp(ss
->name
, "__ksymtab_strings") != 0)
358 int main(int argc
, char *argv
[])
360 if (getenv("KSPLICE_VERBOSE") != NULL
)
361 verbose
= atoi(getenv("KSPLICE_VERBOSE"));
364 bfd
*ibfd
= bfd_openr(argv
[1], NULL
);
368 assert(bfd_check_format_matches(ibfd
, bfd_object
, &matching
));
370 const char *output_target
= bfd_get_target(ibfd
);
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
);
383 if (mode("finalize"))
384 finalize_target
= argv
[4];
385 init_objmanip_superbfd(isbfd
);
386 if (mode("keep-primary")) {
388 do_keep_primary(isbfd
, argv
[4]);
389 } else if (mode("keep-helper")) {
390 do_keep_helper(isbfd
);
391 } else if (mode("finalize")) {
393 } else if (mode("rmsyms")) {
398 bfd
*obfd
= bfd_openw(argv
[2], output_target
);
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
));
410 void do_keep_primary(struct superbfd
*isbfd
, const char *pre
)
412 struct bfd
*prebfd
= bfd_openr(pre
, NULL
);
413 assert(prebfd
!= NULL
);
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");
431 compare_matched_spans(isbfd
);
432 update_nonzero_offsets(isbfd
);
433 mark_new_spans(isbfd
);
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
));
446 mark_precallable_spans(isbfd
);
450 for (sect
= isbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
451 struct supersect
*ss
= fetch_supersect(isbfd
, sect
);
454 for (span
= ss
->spans
.data
;
455 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++) {
456 if (starts_with(ss
->name
, ".ksplice_options"))
458 else if (span
->new || span
->patch
|| span
->datapatch
)
462 if (span
->patch
&& span
->precallable
) {
463 err(isbfd
, "Patched span %s can be reached "
464 "by a precall function\n", span
->label
);
470 print_label_changes(isbfd
);
472 for (sect
= isbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
473 struct supersect
*ss
= fetch_supersect(isbfd
, sect
);
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",
483 for (sect
= isbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
484 struct supersect
*ss
= fetch_supersect(isbfd
, sect
);
486 for (span
= ss
->spans
.data
;
487 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++) {
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
++) {
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
)
510 for (span
= ss
->spans
.data
;
511 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++) {
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
);
525 remove_unkept_spans(isbfd
);
528 void do_keep_helper(struct superbfd
*isbfd
)
531 for (sect
= isbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
532 struct supersect
*ss
= fetch_supersect(isbfd
, sect
);
535 for (span
= ss
->spans
.data
;
536 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++) {
538 if (ss
->type
== SS_TYPE_TEXT
&&
539 !starts_with(ss
->name
, ".fixup"))
541 if (ss
->type
== SS_TYPE_EXPORT
)
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
)
556 struct span
*span
= find_span(sym_ss
, sym
->value
);
557 assert(span
!= NULL
);
558 if (sym_ss
->type
!= SS_TYPE_IGNORED
)
565 keep_referenced_sections(isbfd
);
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
);
576 if ((sym
->flags
& BSF_WEAK
) != 0)
578 if (bfd_get_section_size(sect
) == 0)
582 if (ss
->type
!= SS_TYPE_TEXT
&& !matchable_data_section(ss
))
586 for (span
= ss
->spans
.data
;
587 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++) {
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
);
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
);
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
) {
615 for (span
= ss
->spans
.data
;
616 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++)
621 write_date_relocs(isbfd
, "<{DATE...}>", KSPLICE_HOWTO_DATE
);
622 write_date_relocs(isbfd
, "<{TIME}>", KSPLICE_HOWTO_TIME
);
626 void do_rmsyms(struct superbfd
*isbfd
)
628 read_str_set(&rmsyms
);
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
)
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
);
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
);
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
,
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)
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)
671 if (old_span
->ss
->type
== SS_TYPE_IGNORED
)
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
,
681 static void foreach_symbol_pair(struct superbfd
*oldsbfd
, struct superbfd
*newsbfd
,
682 void (*fn
)(struct span
*old_span
,
684 struct span
*new_span
,
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
))
693 for (newsymp
= newsbfd
->syms
.data
;
694 newsymp
< newsbfd
->syms
.data
+ newsbfd
->syms
.size
;
696 asymbol
*newsym
= *newsymp
;
697 if (bfd_is_const_section(newsym
->section
))
699 if (strcmp(oldsym
->name
, newsym
->name
) != 0)
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
)
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",
721 if (new_span
== NULL
) {
722 err(newsbfd
, "Could not find span for %s\n",
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)
737 if (old_span
->ss
->type
== SS_TYPE_SPECIAL
)
739 if (static_local_symbol(old_span
->ss
->parent
, oldsym
) ||
740 static_local_symbol(new_span
->ss
->parent
, newsym
))
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
)
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)
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
)
777 for (oldsect
= oldsbfd
->abfd
->sections
; oldsect
!= NULL
;
778 oldsect
= oldsect
->next
) {
779 oldss
= fetch_supersect(oldsbfd
, oldsect
);
780 if (oldss
->type
!= newss
->type
)
782 for (new_span
= newss
->spans
.data
;
783 new_span
< newss
->spans
.data
+ newss
->spans
.size
;
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
)
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
)
802 for (span
= ss
->spans
.data
;
803 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++) {
804 if (span
->match
== NULL
&& !span
->bugpatch
)
810 static void handle_deleted_spans(struct superbfd
*oldsbfd
,
811 struct superbfd
*newsbfd
)
814 for (sect
= oldsbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
815 struct supersect
*ss
= fetch_supersect(oldsbfd
, sect
);
817 for (span
= ss
->spans
.data
;
818 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++) {
819 if (span
->match
!= NULL
)
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
)
828 write_ksplice_deleted_patch
829 (newsbfd
, span
->symbol
->name
, span
->label
,
836 static void handle_nonzero_offset_relocs(struct supersect
*ss
)
838 struct span
*address_span
, *target_span
;
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
)
847 asymbol
*sym
= *reloc
->sym_ptr_ptr
;
848 if (bfd_is_const_section(sym
->section
))
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
)
855 if (target_span
->ss
->type
!= SS_TYPE_TEXT
)
857 if (target_span
->patch
)
860 target_span
->patch
= 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
)
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
)
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
)
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",
892 new_span
->match
= NULL
;
893 old_span
->match
= NULL
;
894 new_span
->bugpatch
= true;
899 if (new_span
->size
!= old_span
->size
)
900 reason
= "differing sizes";
901 else if (!nonrelocs_match
)
902 reason
= "differing contents";
904 reason
= "differing relocations";
906 if (new_span
->ss
->type
== SS_TYPE_TEXT
) {
909 new_span
->patch
= true;
910 debug1(newsbfd
, "Changing %s due to %s\n", new_span
->label
,
912 } else if (new_span
->ss
->type
== SS_TYPE_RODATA
&&
913 new_span
->size
== old_span
->size
) {
914 if (new_span
->datapatch
)
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) {
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
;
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
)
939 for (sect
= newsbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
940 struct supersect
*ss
= fetch_supersect(newsbfd
, sect
);
942 for (span
= ss
->spans
.data
;
943 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++) {
944 if (span
->match
== NULL
)
946 compare_spans(span
->match
, span
);
951 static void handle_section_symbol_renames(struct superbfd
*oldsbfd
,
952 struct superbfd
*newsbfd
)
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
)
962 if (strcmp(span
->label
, span
->match
->label
) == 0)
964 if (strcmp(span
->orig_label
, span
->label
) != 0 &&
965 strcmp(span
->label
, span
->match
->label
) != 0)
967 if (span
->symbol
!= NULL
)
968 label_map_set(newsbfd
, span
->label
,
970 span
->label
= span
->match
->label
;
975 static bool part_of_reloc(struct supersect
*ss
, unsigned long addr
)
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
)
988 static bool nonrelocs_equal(struct span
*old_span
, struct span
*new_span
)
991 struct supersect
*old_ss
= old_span
->ss
, *new_ss
= new_span
->ss
;
992 if (old_span
->size
!= new_span
->size
)
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
)))
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
);
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
);
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
);
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
)
1049 if (!bfd_is_und_section(new_sect
) && new_offset
!= 0 &&
1050 fetch_supersect(oldsbfd
, old_sect
)->type
== SS_TYPE_TEXT
)
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
))
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
);
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
);
1082 if ((old_sym
->value
+ old_offset
- old_span
->start
!= 0 ||
1083 new_sym
->value
+ new_offset
- new_span
->start
!= 0) &&
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
);
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
;
1103 if (find_span(old_ss
, (*old_relocp
)->address
) == old_span
)
1107 for (new_relocp
= new_ss
->relocs
.data
;
1108 new_relocp
< new_ss
->relocs
.data
+ new_ss
->relocs
.size
;
1110 if (find_span(new_ss
, (*new_relocp
)->address
) == new_span
)
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
))
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
);
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
)
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;
1166 void rm_some_relocs(struct supersect
*ss
)
1168 struct arelentp_vec orig_relocs
;
1169 vec_move(&orig_relocs
, &ss
->relocs
);
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
))
1184 if (mode("keep-primary") &&
1185 (bfd_is_const_section(sym_ptr
->section
) ||
1186 reloc_target_span(ss
, *relocp
)->new))
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
==
1195 (*relocp
)->address
% ts
->entry_size
==
1200 if (mode("finalize") && bfd_is_und_section(sym_ptr
->section
))
1203 if (strcmp(sym_ptr
->name
, "mcount") == 0 &&
1204 bfd_is_und_section(sym_ptr
->section
))
1207 if (!find_span(ss
, (*relocp
)->address
)->keep
)
1211 write_ksplice_reloc(ss
, *relocp
);
1213 *vec_grow(&ss
->relocs
, 1) = *relocp
;
1217 struct supersect
*make_section(struct superbfd
*sbfd
, const char *fmt
, ...)
1221 char *name
= vstrprintf(fmt
, ap
);
1224 asection
*sect
= bfd_get_section_by_name(sbfd
->abfd
, name
);
1226 return fetch_supersect(sbfd
, sect
);
1228 return new_supersect(sbfd
, name
);
1231 arelent
*create_reloc(struct supersect
*ss
, const void *addr
, asymbol
**symp
,
1234 bfd_reloc_code_real_type code
;
1235 switch (bfd_arch_bits_per_address(ss
->parent
->abfd
)) {
1237 code
= BFD_RELOC_32
;
1240 code
= BFD_RELOC_64
;
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
;
1254 void write_reloc(struct supersect
*ss
, const void *addr
, asymbol
**symp
,
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
, ...)
1263 struct supersect
*str_ss
= make_section(ss
->parent
, ".ksplice_str");
1266 int len
= vasprintf(&str
, fmt
, ap
);
1270 unsigned long *str_offp
= ulong_hash_lookup(&ksplice_string_offset
, str
,
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
)
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
;
1294 if (*addr
== *map_addr
+ offset
)
1297 if (addr
< addrs
->data
+ addrs
->size
)
1299 *vec_grow(addrs
, 1) = *map_addr
+ offset
;
1303 void compute_system_map_array(struct superbfd
*sbfd
, struct addr_vec
*addrs
,
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
)) {
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
,
1326 bool *done
= bool_hash_lookup(&system_map_written
, label
, TRUE
);
1331 struct addr_vec 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
,
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
));
1354 void write_ksplice_symbol_backend(struct supersect
*ss
,
1355 struct ksplice_symbol
*const *addr
,
1356 asymbol
*sym
, const char *label
,
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
);
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
);
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
;
1390 label
= label_lookup(ss
->parent
, sym
);
1392 asymbol
*gsym
= canonical_symbol(ss
->parent
, sym
);
1393 if (strcmp(addstr_sect
, "") != 0)
1395 else if (bfd_is_und_section(sym
->section
))
1397 else if (bfd_is_const_section(sym
->section
))
1399 else if (span
!= NULL
&& span
->symbol
== NULL
)
1401 else if (gsym
== NULL
|| (gsym
->flags
& BSF_SECTION_SYM
) != 0)
1406 write_ksplice_symbol_backend(ss
, addr
, sym
,
1407 strprintf("%s%s", addstr_sect
, label
),
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")) {
1422 if (mode("finalize") && starts_with(ss
->name
, ".ksplice_relocs")) {
1423 assert(starts_with(sym_ptr
->name
, KSPLICE_SYMBOL_STR
));
1425 fake_sym
.name
= sym_ptr
->name
+ strlen(KSPLICE_SYMBOL_STR
);
1426 fake_sym
.section
= bfd_und_section_ptr
;
1430 write_ksplice_symbol_backend
1431 (ss
, (struct ksplice_symbol
**)repladdr
, &fake_sym
,
1432 fake_sym
.name
, fake_sym
.name
);
1436 struct span
*span
= reloc_target_span(ss
, orig_reloc
);
1437 if (span
== ss
->spans
.data
&& span
->start
!= target_addend
)
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
;
1445 kreloc_ss
= make_section(ss
->parent
, ".ksplice_init_relocs");
1447 kreloc_ss
= make_section(ss
->parent
, ".ksplice_relocs%s",
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);
1460 write_ksplice_symbol(kreloc_ss
, &kreloc
->symbol
, sym_ptr
, span
,
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
,
1485 if (khowto_offp
!= NULL
) {
1486 write_reloc(ss
, addr
, &khowto_ss
->symbol
, *khowto_offp
);
1489 khowto
= sect_grow(khowto_ss
, 1, struct ksplice_reloc_howto
);
1490 khowto_offp
= ulong_hash_lookup(&ksplice_howto_offset
, howto
->name
,
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
,
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
)
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
)
1527 for (span
= ss
->spans
.data
;
1528 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++) {
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
,
1543 static void write_ksplice_date_reloc(struct supersect
*ss
, unsigned long offset
,
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
),
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
,
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
);
1573 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
1575 const struct table_section
*s
= get_table_section(sectname
);
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
);
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) +
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
,
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
,
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
1621 enum ksplice_reloc_howto_type type
,
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
;
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
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
;
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
,
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
,
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
,
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
)
1736 for (symp
= sbfd
->syms
.data
; symp
< sbfd
->syms
.data
+ sbfd
->syms
.size
;
1738 asymbol
*sym
= *symp
;
1739 if (strcmp(name
, sym
->name
) == 0 &&
1740 bfd_is_und_section(sym
->section
))
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
))
1753 symp
= malloc(sizeof(*symp
));
1754 *symp
= bfd_make_empty_symbol(sbfd
->abfd
);
1755 asymbol
*sym
= *symp
;
1757 sym
->section
= bfd_und_section_ptr
;
1760 *vec_grow(&sbfd
->new_syms
, 1) = 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
);
1790 span
->ss
->contents
.data
+ span
->start
+ ts
->other_offset
;
1791 const char *symname
= read_string(span
->ss
, addr
);
1793 char *oldname
, *newname
;
1795 oldname
= strprintf("%s:%s", span
->ss
->name
, symname
);
1796 newname
= strprintf("DISABLED_%s_%s", symname
, kid
);
1798 oldname
= strprintf("%s:DISABLED_%s_%s", span
->ss
->name
,
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
,
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
;
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
)
1836 struct supersect
*ss
= fetch_supersect(sbfd
, isection
);
1839 for (entry
= ss
->contents
.data
;
1840 entry
< ss
->contents
.data
+ ss
->contents
.size
;
1841 entry
+= s
->entry_size
) {
1843 struct span
*span
= find_span(ss
, addr_offset(ss
, entry
));
1844 assert(span
!= NULL
);
1847 read_reloc(ss
, entry
+ s
->addr_offset
,
1848 sizeof(void *), &sym
);
1849 struct supersect
*sym_ss
=
1850 fetch_supersect(sbfd
, sym
->section
);
1855 if (s
->other_sect
!= NULL
) {
1857 find_reloc(ss
, entry
+ s
->other_offset
);
1858 assert(reloc
!= NULL
);
1859 struct span
*sym_span
= reloc_target_span(ss
, reloc
);
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
);
1874 keep_span(crc_span
);
1879 void mark_precallable_spans(struct superbfd
*sbfd
)
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
);
1887 if (ss
->type
== SS_TYPE_SPECIAL
)
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
)
1895 target_span
= reloc_target_span(ss
, *relocp
);
1896 if (target_span
== NULL
|| target_span
->keep
)
1898 sym_ss
= fetch_supersect(sbfd
, sym
->section
);
1899 if (sym_ss
->type
== SS_TYPE_IGNORED
)
1901 target_span
->precallable
= true;
1907 void keep_referenced_sections(struct superbfd
*sbfd
)
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
);
1915 if (ss
->type
== SS_TYPE_SPECIAL
)
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
)
1923 target_span
= reloc_target_span(ss
, *relocp
);
1924 if (target_span
== NULL
|| target_span
->keep
)
1926 sym_ss
= fetch_supersect(sbfd
, sym
->section
);
1927 if (sym_ss
->type
== SS_TYPE_IGNORED
)
1929 keep_span(target_span
);
1935 void copy_symbols(struct asymbolp_vec
*osyms
, struct asymbolpp_vec
*isyms
)
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
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
;
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
));
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
;
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;
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));
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)
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
)
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)
2089 delete_obsolete_relocs(ss
);
2092 char *error_message
;
2093 for (relocp
= ss
->new_relocs
.data
;
2094 relocp
< ss
->new_relocs
.data
+ ss
->new_relocs
.size
; relocp
++) {
2096 if (bfd_get_arch(obfd
) == bfd_arch_arm
)
2097 val
= osection
->use_rela_p
? 0 : (*relocp
)->addend
;
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
) !=
2105 err(ss
->parent
, "ksplice: error installing reloc: %s",
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
,
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
,
2133 struct superbfd
*sbfd
= fetch_superbfd(abfd
);
2134 if (isection
->output_section
== NULL
)
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. */
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
))
2167 struct supersect
*ss
= fetch_supersect(sbfd
, sym
->section
);
2170 for (symp
= ss
->syms
.data
; symp
< ss
->syms
.data
+ ss
->syms
.size
; symp
++) {
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
)
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
&&
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)
2206 if (deleted_table_section_symbol(ibfd
, sym
))
2209 if (mode("keep-helper") && sym_ss
!= NULL
&&
2210 sym_ss
->type
== SS_TYPE_EXPORT
)
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
);
2219 *vec_grow(osyms
, 1) = sym
;
2224 void read_str_set(struct str_vec
*strs
)
2228 assert(getline(&buf
, &n
, stdin
) >= 0);
2232 char *str
= strtok_r(buf
, " \n", &saveptr
);
2236 *vec_grow(strs
, 1) = str
;
2240 bool str_in_set(const char *str
, const struct str_vec
*strs
)
2243 for (strp
= strs
->data
; strp
< strs
->data
+ strs
->size
; strp
++) {
2244 if (strcmp(str
, *strp
) == 0)
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
;
2260 if (strcmp(name
, read_string(tables_ss
, &ts
->sect
)) == 0)
2262 const char *osect_name
= read_string(tables_ss
,
2264 if (consider_other
&& osect_name
!= NULL
&&
2265 strcmp(name
, osect_name
) == 0)
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)
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
;
2285 if (strcmp(name
, read_string(tables_ss
, &ts
->sect
)) == 0)
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
;
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
)
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
);
2462 static void init_label_map(struct superbfd
*sbfd
)
2464 struct label_map
*map
;
2466 vec_init(&sbfd
->maps
);
2470 struct symbol_hash csyms
;
2471 symbol_hash_init(&csyms
);
2474 for (symp
= sbfd
->syms
.data
;
2475 symp
< sbfd
->syms
.data
+ sbfd
->syms
.size
; symp
++) {
2476 asymbol
*csym
= canonical_symbol(sbfd
, *symp
);
2479 char *key
= strprintf("%p", csym
);
2480 asymbol
**csymp
= symbol_hash_lookup(&csyms
, key
, TRUE
);
2486 map
= vec_grow(&sbfd
->maps
, 1);
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
) {
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
);
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
);
2530 return (*mapp
)->label
;
2533 static void print_label_changes(struct superbfd
*sbfd
)
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
,
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)
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
;
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
);
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
);
2587 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
2588 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
2590 for (relocp
= ss
->relocs
.data
;
2591 relocp
< ss
->relocs
.data
+ ss
->relocs
.size
; relocp
++) {
2592 asymbol
*sym
= *(*relocp
)->sym_ptr_ptr
;
2594 sym
->value
+ get_reloc_offset(ss
, *relocp
, true);
2595 char *key
= strprintf("%s+%lx", sym
->section
->name
,
2597 const char **ret
= string_hash_lookup(&sbfd
->callers
,
2600 asymbol
*csym
= canonical_symbol(sbfd
, sect
->symbol
);
2602 *ret
= "*multiple_callers*";
2603 else if (static_local_symbol(sbfd
, csym
))
2604 *ret
= static_local_symbol(sbfd
, csym
);
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
);
2619 return "*no_caller*";
2623 static void init_csyms(struct superbfd
*sbfd
)
2625 asymbolpp_hash_init(&sbfd
->csyms
);
2628 for (symp
= sbfd
->syms
.data
; symp
< sbfd
->syms
.data
+ sbfd
->syms
.size
;
2630 asymbol
*sym
= *symp
;
2631 if ((sym
->flags
& BSF_DEBUGGING
) != 0)
2633 char *key
= strprintf("%s+%lx", sym
->section
->name
,
2634 (unsigned long)sym
->value
);
2635 asymbol
***csympp
= asymbolpp_hash_lookup(&sbfd
->csyms
, key
,
2638 if (*csympp
== NULL
) {
2642 asymbol
*csym
= **csympp
;
2643 if ((csym
->flags
& BSF_GLOBAL
) != 0)
2645 if ((sym
->flags
& BSF_GLOBAL
) != 0)
2650 static asymbol
**symbolp_scan(struct supersect
*ss
, bfd_vma value
)
2652 char *key
= strprintf("%s+%lx", ss
->name
, (unsigned long)value
);
2654 asymbolpp_hash_lookup(&ss
->parent
->csyms
, key
, FALSE
);
2659 /* For section symbols of sections containing no symbols, return the
2660 section symbol that relocations are generated against */
2666 static asymbol
**canonical_symbolp(struct superbfd
*sbfd
, asymbol
*sym
)
2668 if (bfd_is_const_section(sym
->section
)) {
2670 for (csymp
= sbfd
->syms
.data
;
2671 csymp
< sbfd
->syms
.data
+ sbfd
->syms
.size
; csymp
++) {
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
))
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)
2693 char *dot
= strrchr(sym
->name
, '.');
2694 if (dot
== NULL
|| dot
[1 + strspn(dot
+ 1, "0123546789")] != '\0')
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
);
2703 if (strcmp(basename
, "__func__") == 0 ||
2704 strcmp(basename
, "__PRETTY_FUNCTION__") == 0)
2705 caller
= (const char *)ss
->contents
.data
+ sym
->value
;
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
);
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
);
2723 asymbol
*gsym
= canonical_symbol(sbfd
, sym
);
2726 label
= strprintf("%s+%lx<%.*s>",
2728 (unsigned long)sym
->value
,
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
,
2738 label
= strprintf("%s<%.*s>",
2739 gsym
->name
, flen
, filename
);
2745 static void keep_span(struct span
*span
)
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);
2755 span
->start
= start
;
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");
2768 asymbol
**symp
= symbolp_scan(ss
, span
->start
);
2770 span
->symbol
= *symp
;
2771 span
->label
= label_lookup(ss
->parent
, span
->symbol
);
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
);
2779 span
->label
= label
;
2781 span
->orig_label
= span
->label
;
2785 static void initialize_string_spans(struct supersect
*ss
)
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')
2801 new_span(ss
, start
, size
);
2806 static int compare_ulongs(const void *va
, const void *vb
)
2808 const unsigned long *a
= va
, *b
= vb
;
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
)
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
;
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
),
2845 if ((span
->symbol
== NULL
||
2846 (span
->symbol
->flags
& BSF_SECTION_SYM
) != 0) &&
2848 arelent
*reloc
= find_reloc(ss
, entry
+ s
->addr_offset
);
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
) {
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
+
2879 char *label
= strprintf("%s:%s", ss
->name
, symname
);
2880 change_initial_label(span
, label
);
2884 if (other_sect
== NULL
)
2887 qsort(offsets
.data
, offsets
.size
, sizeof(*offsets
.data
),
2889 *vec_grow(&offsets
, 1) = other_ss
->contents
.size
;
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
;
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
)
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
)
2931 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
2932 if (is_table_section(sect
->name
, true) && mode("keep"))
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
);
2941 new_span(ss
, 0, ss
->contents
.size
);
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
))
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
)
2965 struct span
*find_span(struct supersect
*ss
, bfd_size_type address
)
2968 for (span
= ss
->spans
.data
; span
< ss
->spans
.data
+ ss
->spans
.size
;
2970 if (address
>= span
->start
&&
2971 address
< span
->start
+ span
->size
)
2974 /* Deal with empty BSS sections */
2975 if (ss
->contents
.size
== 0 && ss
->spans
.size
> 0)
2976 return ss
->spans
.data
;
2980 void compute_span_shifts(struct superbfd
*sbfd
)
2984 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
2985 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
2988 bfd_size_type offset
= 0;
2989 for (span
= ss
->spans
.data
;
2990 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++) {
2993 span
->shift
= offset
- span
->start
;
2994 offset
+= span
->size
;
2999 void remove_unkept_spans(struct superbfd
*sbfd
)
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
++) {
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
;
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
);
3028 if (span
!= NULL
&& span
->keep
) {
3029 arelent
*new_reloc
= malloc(sizeof(*new_reloc
));
3030 *new_reloc
= *reloc
;
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
;
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
++) {
3049 struct span
*new_span
= vec_grow(&ss
->spans
, 1);
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
,
3060 static void init_objmanip_superbfd(struct superbfd
*sbfd
)
3062 init_label_map(sbfd
);
3063 initialize_supersect_types(sbfd
);
3064 initialize_spans(sbfd
);
3068 void mangle_section_name(struct superbfd
*sbfd
, const char *name
)
3070 asection
*sect
= bfd_get_section_by_name(sbfd
->abfd
, name
);
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");
3083 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
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
)
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
;