1 /* This file is based in part on objcopy.c from GNU Binutils v2.17.
3 * Copyright (C) 1991-2006 Free Software Foundation, Inc.
4 * Copyright (C) 2007-2008 Ksplice, Inc.
5 * Authors: Jeff Arnold, Anders Kaseorg, Tim Abbott
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License, version 2.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
21 /* objmanip performs various object file manipulations for Ksplice. Its first
22 * two arguments are always an input object file and an output object file.
24 * - keep-primary: "objmanip <post.o> <out.o> keep-primary <pre.o> <kid>"
26 * This mode prepares the object file to be installed as a ksplice update. The
27 * kid argument is the ksplice id string for the ksplice update being built.
29 * - keep-helper: "objmanip <pre.o> <out.o> keep-helper"
31 * This mode prepares the object file to be used for run-pre matching. This
32 * involves replacing all ELF relocations with ksplice relocations and
33 * writing ksplice_section structures for each ELF text or data section.
35 * - rmsyms mode: "objmanip <in.o> <out.o> rmsyms
37 * In this mode, any ELF relocations involving the list of symbol names given on
38 * standard input are replaced with ksplice relocations. This is used only
39 * for KSPLICE_STANDALONE.
41 * - finalize mode: "objmanip <in.o> <out.o> finalize"
43 * In this mode, any ELF relocations to undefined symbols are replaced with
44 * ksplice relocations.
47 /* Always define KSPLICE_STANDALONE, even if you're using integrated Ksplice.
48 objmanip won't compile without it. */
49 #define KSPLICE_STANDALONE
52 #include "objcommon.h"
53 #include "kmodsrc/ksplice.h"
54 #include "kmodsrc/offsets.h"
55 #include "ksplice-patch/ksplice-patch.h"
62 #define KSPLICE_SYMBOL_STR "KSPLICE_SYMBOL_"
64 #define symbol_init(sym) *(sym) = (asymbol *)NULL
65 DEFINE_HASH_TYPE(asymbol
*, symbol_hash
, symbol_hash_init
, symbol_hash_free
,
66 symbol_hash_lookup
, symbol_init
);
68 DECLARE_VEC_TYPE(const char *, str_vec
);
70 DECLARE_VEC_TYPE(unsigned long, ulong_vec
);
72 #define bool_init(b) *(b) = false
73 DEFINE_HASH_TYPE(bool, bool_hash
, bool_hash_init
, bool_hash_free
,
74 bool_hash_lookup
, bool_init
);
76 #define ulong_init(x) *(x) = 0
77 DEFINE_HASH_TYPE(unsigned long, ulong_hash
, ulong_hash_init
,
78 ulong_hash_free
, ulong_hash_lookup
, ulong_init
);
80 void do_keep_primary(struct superbfd
*isbfd
, const char *pre
);
81 void do_keep_helper(struct superbfd
*isbfd
);
82 void do_finalize(struct superbfd
*isbfd
);
83 void do_rmsyms(struct superbfd
*isbfd
);
85 bool relocs_equal(struct supersect
*old_src_ss
, struct supersect
*new_src_ss
,
86 arelent
*old_reloc
, arelent
*new_reloc
);
87 bfd_vma
non_dst_mask(struct supersect
*ss
, arelent
*reloc
);
88 bool all_relocs_equal(struct span
*old_span
, struct span
*new_span
);
89 static bool part_of_reloc(struct supersect
*ss
, unsigned long addr
);
90 static bool nonrelocs_equal(struct span
*old_span
, struct span
*new_span
);
91 static void handle_section_symbol_renames(struct superbfd
*oldsbfd
,
92 struct superbfd
*newsbfd
);
94 enum supersect_type
supersect_type(struct supersect
*ss
);
95 void initialize_supersect_types(struct superbfd
*sbfd
);
96 static void initialize_spans(struct superbfd
*sbfd
);
97 static void initialize_string_spans(struct supersect
*ss
);
98 static void initialize_table_spans(struct superbfd
*sbfd
,
99 struct table_section
*s
);
100 static void initialize_table_section_spans(struct superbfd
*sbfd
);
101 static void initialize_ksplice_call_spans(struct supersect
*ss
);
102 struct span
*reloc_target_span(struct supersect
*ss
, arelent
*reloc
);
103 struct span
*find_span(struct supersect
*ss
, bfd_size_type address
);
104 void remove_unkept_spans(struct superbfd
*sbfd
);
105 void compute_span_shifts(struct superbfd
*sbfd
);
106 static struct span
*new_span(struct supersect
*ss
, bfd_vma start
, bfd_vma size
);
107 bool is_table_section(const char *name
, bool consider_other
);
108 const struct table_section
*get_table_section(const char *name
);
109 void mangle_section_name(struct superbfd
*sbfd
, const char *name
);
111 void rm_relocs(struct superbfd
*isbfd
);
112 void rm_some_relocs(struct supersect
*ss
);
113 void write_ksplice_reloc(struct supersect
*ss
, arelent
*orig_reloc
);
114 static void write_ksplice_reloc_howto(struct supersect
*ss
, const
115 struct ksplice_reloc_howto
*const *addr
,
116 reloc_howto_type
*howto
,
117 enum ksplice_reloc_howto_type type
);
118 static void write_ksplice_date_reloc(struct supersect
*ss
, unsigned long offset
,
120 enum ksplice_reloc_howto_type type
);
121 static void write_ksplice_patch_reloc(struct supersect
*ss
,
122 const char *sectname
, unsigned long *addr
,
123 bfd_size_type size
, const char *label
,
125 static void write_ksplice_nonreloc_howto(struct supersect
*ss
,
126 const struct ksplice_reloc_howto
128 enum ksplice_reloc_howto_type type
,
130 static void write_date_relocs(struct superbfd
*sbfd
, const char *str
,
131 enum ksplice_reloc_howto_type type
);
132 static void write_table_relocs(struct superbfd
*sbfd
, const char *sectname
,
133 enum ksplice_reloc_howto_type type
);
134 static void write_ksplice_table_reloc(struct supersect
*ss
,
135 unsigned long address
,
137 enum ksplice_reloc_howto_type type
);
138 void load_ksplice_symbol_offsets(struct superbfd
*sbfd
);
139 void write_canary(struct supersect
*ss
, int offset
, bfd_size_type size
,
141 static void write_ksplice_section(struct span
*span
);
142 void write_ksplice_patch(struct superbfd
*sbfd
, struct span
*span
);
143 void *write_patch_storage(struct supersect
*ss
, struct ksplice_patch
*patch
,
144 size_t size
, struct supersect
**data_ssp
);
145 void write_ksplice_deleted_patch(struct superbfd
*sbfd
, const char *name
,
146 const char *label
, const char *sectname
);
147 static void write_bugline_patches(struct superbfd
*sbfd
);
148 asymbol
**make_undefined_symbolp(struct superbfd
*sbfd
, const char *name
);
149 void filter_table_sections(struct superbfd
*isbfd
);
150 void filter_table_section(struct superbfd
*sbfd
, const struct table_section
*s
);
151 void keep_referenced_sections(struct superbfd
*sbfd
);
152 void mark_precallable_spans(struct superbfd
*sbfd
);
153 bfd_boolean
copy_object(bfd
*ibfd
, bfd
*obfd
);
154 void setup_section(bfd
*ibfd
, asection
*isection
, void *obfdarg
);
155 static void setup_new_section(bfd
*obfd
, struct supersect
*ss
);
156 static void write_section(bfd
*obfd
, asection
*osection
, void *arg
);
157 static void delete_obsolete_relocs(struct supersect
*ss
);
158 void mark_symbols_used_in_relocations(bfd
*abfd
, asection
*isection
,
160 static void ss_mark_symbols_used_in_relocations(struct supersect
*ss
);
161 void filter_symbols(bfd
*ibfd
, bfd
*obfd
, struct asymbolp_vec
*osyms
,
162 struct asymbolp_vec
*isyms
);
163 static bool deleted_table_section_symbol(bfd
*abfd
, asymbol
*sym
);
164 void read_str_set(struct str_vec
*strs
);
165 bool str_in_set(const char *str
, const struct str_vec
*strs
);
166 struct supersect
*__attribute((format(printf
, 2, 3)))
167 make_section(struct superbfd
*sbfd
, const char *fmt
, ...);
168 void __attribute__((format(printf
, 3, 4)))
169 write_string(struct supersect
*ss
, const char **addr
, const char *fmt
, ...);
170 void write_ksplice_export(struct superbfd
*sbfd
, struct span
*span
, bool del
);
171 void write_reloc(struct supersect
*ss
, const void *addr
, asymbol
**symp
,
173 arelent
*create_reloc(struct supersect
*ss
, const void *addr
, asymbol
**symp
,
175 static void foreach_symbol_pair(struct superbfd
*oldsbfd
, struct superbfd
*newsbfd
,
176 void (*fn
)(struct span
*old_span
,
178 struct span
*new_span
,
180 static void check_global_symbols(struct span
*old_span
, asymbol
*oldsym
,
181 struct span
*new_span
, asymbol
*newsym
);
182 static void match_global_symbols(struct span
*old_span
, asymbol
*oldsym
,
183 struct span
*new_span
, asymbol
*newsym
);
184 static void match_symbol_spans(struct span
*old_span
, asymbol
*oldsym
,
185 struct span
*new_span
, asymbol
*newsym
);
187 static struct span
*get_crc_span(struct span
*span
,
188 const struct table_section
*ts
);
189 static void foreach_span_pair(struct superbfd
*oldsbfd
,
190 struct superbfd
*newsbfd
,
191 void (*fn
)(struct span
*old_span
,
192 struct span
*new_span
));
193 static void match_spans_by_label(struct span
*old_span
, struct span
*new_span
);
194 static void match_string_spans(struct span
*old_span
, struct span
*new_span
);
195 static void mark_new_spans(struct superbfd
*sbfd
);
196 static void handle_deleted_spans(struct superbfd
*oldsbfd
,
197 struct superbfd
*newsbfd
);
198 static void compare_matched_spans(struct superbfd
*newsbfd
);
199 static void compare_spans(struct span
*old_span
, struct span
*new_span
);
200 static void update_nonzero_offsets(struct superbfd
*sbfd
);
201 static void handle_nonzero_offset_relocs(struct supersect
*ss
);
202 static void keep_span(struct span
*span
);
204 static void init_objmanip_superbfd(struct superbfd
*sbfd
);
205 static const char *label_lookup(struct superbfd
*sbfd
, asymbol
*sym
);
206 static void label_map_set(struct superbfd
*sbfd
, const char *oldlabel
,
208 static void print_label_changes(struct superbfd
*sbfd
);
209 static void init_label_map(struct superbfd
*sbfd
);
210 static void change_initial_label(struct span
*span
, const char *label
);
211 static asymbol
**symbolp_scan(struct supersect
*ss
, bfd_vma value
);
212 static void init_csyms(struct superbfd
*sbfd
);
213 static void init_callers(struct superbfd
*sbfd
);
214 static asymbol
*canonical_symbol(struct superbfd
*sbfd
, asymbol
*sym
);
215 static asymbol
**canonical_symbolp(struct superbfd
*sbfd
, asymbol
*sym
);
216 static char *static_local_symbol(struct superbfd
*sbfd
, asymbol
*sym
);
217 static char *symbol_label(struct superbfd
*sbfd
, asymbol
*sym
);
220 #define debug_(sbfd, level, fmt, ...) \
222 if (verbose >= (level)) \
223 printf("%s: " fmt, (sbfd)->abfd->filename, \
226 #define debug0(sbfd, fmt, ...) debug_(sbfd, 0, fmt, ## __VA_ARGS__)
227 #define debug1(sbfd, fmt, ...) debug_(sbfd, 1, fmt, ## __VA_ARGS__)
228 #define err(sbfd, fmt, ...) \
230 fprintf(stderr, "%s: " fmt, (sbfd)->abfd->filename, \
234 struct str_vec delsects
, rmsyms
;
237 struct ksplice_config
*config
;
239 const char *modestr
, *kid
, *finalize_target
= NULL
;
240 bool write_output
= true;
242 struct superbfd
*offsets_sbfd
= NULL
;
244 #define mode(str) starts_with(modestr, str)
246 DECLARE_VEC_TYPE(unsigned long, addr_vec
);
247 DEFINE_HASH_TYPE(struct addr_vec
, addr_vec_hash
,
248 addr_vec_hash_init
, addr_vec_hash_free
, addr_vec_hash_lookup
,
250 struct addr_vec_hash system_map
;
252 struct bool_hash system_map_written
;
253 struct ulong_hash ksplice_symbol_offset
;
254 struct ulong_hash ksplice_howto_offset
;
255 struct ulong_hash ksplice_string_offset
;
257 void load_system_map()
259 const char *config_dir
= getenv("KSPLICE_CONFIG_DIR");
261 FILE *fp
= fopen(strprintf("%s/System.map", config_dir
), "r");
263 addr_vec_hash_init(&system_map
);
267 while (fscanf(fp
, "%lx %c %as\n", &addr
, &type
, &sym
) == 3)
268 *vec_grow(addr_vec_hash_lookup(&system_map
, sym
, TRUE
),
273 void load_ksplice_symbol_offsets(struct superbfd
*sbfd
)
275 asection
*sect
= bfd_get_section_by_name(sbfd
->abfd
,
279 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
281 struct ksplice_symbol
*ksym
;
282 for (ksym
= ss
->contents
.data
;
283 (void *)ksym
< ss
->contents
.data
+ ss
->contents
.size
; ksym
++) {
284 const char *label
= read_string(ss
, &ksym
->label
);
285 unsigned long *ksymbol_offp
=
286 ulong_hash_lookup(&ksplice_symbol_offset
, label
, TRUE
);
287 *ksymbol_offp
= addr_offset(ss
, ksym
);
293 char *kmodsrc
= getenv("KSPLICE_KMODSRC");
294 assert(kmodsrc
!= NULL
);
295 bfd
*offsets_bfd
= bfd_openr(strprintf("%s/offsets.o", kmodsrc
), NULL
);
296 assert(offsets_bfd
!= NULL
);
298 assert(bfd_check_format_matches(offsets_bfd
, bfd_object
, &matching
));
299 offsets_sbfd
= fetch_superbfd(offsets_bfd
);
301 asection
*config_sect
= bfd_get_section_by_name(offsets_sbfd
->abfd
,
303 struct supersect
*config_ss
=
304 fetch_supersect(offsets_sbfd
, config_sect
);
306 config
= config_ss
->contents
.data
;
309 void load_options(struct superbfd
*sbfd
)
311 asection
*sect
= bfd_get_section_by_name(sbfd
->abfd
,
315 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
316 const struct ksplice_option
*opt
;
317 for (opt
= ss
->contents
.data
;
318 (void *)opt
< ss
->contents
.data
+ ss
->contents
.size
; opt
++) {
319 if (opt
->type
== KSPLICE_OPTION_ASSUME_RODATA
) {
320 arelent
*reloc
= find_reloc(ss
, &opt
->target
);
321 struct span
*span
= reloc_target_span(ss
, reloc
);
322 assert(span
!= NULL
);
323 assert(span
->ss
->type
== SS_TYPE_DATA
);
324 assert(span
->start
== 0 &&
325 span
->size
== span
->ss
->contents
.size
);
326 span
->ss
->type
= SS_TYPE_RODATA
;
329 err(sbfd
, "Unrecognized Ksplice option %d\n",
336 bool matchable_data_section(struct supersect
*ss
)
338 if (ss
->type
== SS_TYPE_STRING
)
340 if (ss
->type
== SS_TYPE_RODATA
)
342 if (ss
->type
== SS_TYPE_DATA
&& ss
->relocs
.size
!= 0)
344 if (ss
->type
== SS_TYPE_EXPORT
)
349 bool unchangeable_section(struct supersect
*ss
)
351 if (ss
->type
== SS_TYPE_DATA
)
353 if (ss
->type
== SS_TYPE_IGNORED
&& !starts_with(ss
->name
, ".debug") &&
354 strcmp(ss
->name
, "__ksymtab_strings") != 0)
359 int main(int argc
, char *argv
[])
361 if (getenv("KSPLICE_VERBOSE") != NULL
)
362 verbose
= atoi(getenv("KSPLICE_VERBOSE"));
365 bfd
*ibfd
= bfd_openr(argv
[1], NULL
);
369 assert(bfd_check_format_matches(ibfd
, bfd_object
, &matching
));
371 const char *output_target
= bfd_get_target(ibfd
);
376 bool_hash_init(&system_map_written
);
377 ulong_hash_init(&ksplice_symbol_offset
);
378 ulong_hash_init(&ksplice_howto_offset
);
379 ulong_hash_init(&ksplice_string_offset
);
381 struct superbfd
*isbfd
= fetch_superbfd(ibfd
);
384 if (mode("finalize"))
385 finalize_target
= argv
[4];
386 init_objmanip_superbfd(isbfd
);
387 if (mode("keep-primary")) {
389 do_keep_primary(isbfd
, argv
[4]);
390 } else if (mode("keep-helper")) {
391 do_keep_helper(isbfd
);
392 } else if (mode("finalize")) {
394 } else if (mode("rmsyms")) {
399 bfd
*obfd
= bfd_openw(argv
[2], output_target
);
401 copy_object(ibfd
, obfd
);
402 assert(bfd_close(obfd
));
405 if (offsets_sbfd
!= NULL
)
406 assert(bfd_close(offsets_sbfd
->abfd
));
407 assert(bfd_close(ibfd
));
411 void do_keep_primary(struct superbfd
*isbfd
, const char *pre
)
413 struct bfd
*prebfd
= bfd_openr(pre
, NULL
);
414 assert(prebfd
!= NULL
);
416 assert(bfd_check_format_matches(prebfd
, bfd_object
, &matching
));
418 struct superbfd
*presbfd
= fetch_superbfd(prebfd
);
419 init_objmanip_superbfd(presbfd
);
421 foreach_symbol_pair(presbfd
, isbfd
, match_global_symbols
);
422 debug1(isbfd
, "Matched global\n");
423 foreach_span_pair(presbfd
, isbfd
, match_string_spans
);
424 debug1(isbfd
, "Matched string spans\n");
425 foreach_symbol_pair(presbfd
, isbfd
, match_symbol_spans
);
426 debug1(isbfd
, "Matched by name\n");
427 foreach_span_pair(presbfd
, isbfd
, match_spans_by_label
);
428 debug1(isbfd
, "Matched by label\n");
432 compare_matched_spans(isbfd
);
433 update_nonzero_offsets(isbfd
);
434 mark_new_spans(isbfd
);
438 foreach_symbol_pair(presbfd
, isbfd
, check_global_symbols
);
440 handle_deleted_spans(presbfd
, isbfd
);
441 handle_section_symbol_renames(presbfd
, isbfd
);
443 assert(bfd_close(prebfd
));
447 mark_precallable_spans(isbfd
);
451 for (sect
= isbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
452 struct supersect
*ss
= fetch_supersect(isbfd
, sect
);
455 for (span
= ss
->spans
.data
;
456 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++) {
457 if (starts_with(ss
->name
, ".ksplice_options"))
459 else if (span
->new || span
->patch
|| span
->datapatch
)
463 if (span
->patch
&& span
->precallable
) {
464 err(isbfd
, "Patched span %s can be reached "
465 "by a precall function\n", span
->label
);
471 print_label_changes(isbfd
);
473 for (sect
= isbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
474 struct supersect
*ss
= fetch_supersect(isbfd
, sect
);
476 for (span
= ss
->spans
.data
;
477 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++) {
478 if (span
->patch
|| span
->bugpatch
|| span
->datapatch
)
479 debug0(isbfd
, "Patching span %s\n",
484 for (sect
= isbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
485 struct supersect
*ss
= fetch_supersect(isbfd
, sect
);
487 for (span
= ss
->spans
.data
;
488 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++) {
490 debug0(isbfd
, "New span %s\n", span
->label
);
494 write_output
= false;
495 const char **sectname
;
496 for (sectname
= delsects
.data
;
497 sectname
< delsects
.data
+ delsects
.size
; sectname
++) {
499 debug0(isbfd
, "Deleted section: %s\n", *sectname
);
502 filter_table_sections(isbfd
);
504 compute_span_shifts(isbfd
);
506 for (sect
= isbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
507 struct supersect
*ss
= fetch_supersect(isbfd
, sect
);
508 if (ss
->type
== SS_TYPE_KSPLICE_CALL
)
511 for (span
= ss
->spans
.data
;
512 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++) {
515 if (span
->patch
|| span
->new || span
->datapatch
)
516 write_ksplice_section(span
);
517 if (span
->patch
|| span
->datapatch
)
518 write_ksplice_patch(isbfd
, span
);
519 if (ss
->type
== SS_TYPE_EXPORT
&& span
->new)
520 write_ksplice_export(isbfd
, span
, false);
524 write_bugline_patches(isbfd
);
526 remove_unkept_spans(isbfd
);
529 void do_keep_helper(struct superbfd
*isbfd
)
532 for (sect
= isbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
533 struct supersect
*ss
= fetch_supersect(isbfd
, sect
);
536 for (span
= ss
->spans
.data
;
537 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++) {
539 if (ss
->type
== SS_TYPE_TEXT
&&
540 !starts_with(ss
->name
, ".fixup"))
542 if (ss
->type
== SS_TYPE_EXPORT
)
548 for (symp
= isbfd
->syms
.data
;
549 symp
< isbfd
->syms
.data
+ isbfd
->syms
.size
; symp
++) {
550 asymbol
*sym
= *symp
;
551 if (!bfd_is_const_section(sym
->section
) &&
552 (sym
->flags
& BSF_GLOBAL
) != 0) {
553 struct supersect
*sym_ss
=
554 fetch_supersect(isbfd
, sym
->section
);
555 if (sym
->value
== sym_ss
->contents
.size
)
557 struct span
*span
= find_span(sym_ss
, sym
->value
);
558 assert(span
!= NULL
);
559 if (sym_ss
->type
!= SS_TYPE_IGNORED
)
566 keep_referenced_sections(isbfd
);
569 filter_table_sections(isbfd
);
570 compute_span_shifts(isbfd
);
572 for (sect
= isbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
573 struct supersect
*ss
= fetch_supersect(isbfd
, sect
);
574 asymbol
*sym
= canonical_symbol(isbfd
, sect
->symbol
);
577 if ((sym
->flags
& BSF_WEAK
) != 0)
579 if (bfd_get_section_size(sect
) == 0)
583 if (ss
->type
!= SS_TYPE_TEXT
&& !matchable_data_section(ss
))
587 for (span
= ss
->spans
.data
;
588 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++) {
590 write_ksplice_section(span
);
594 write_table_relocs(isbfd
, "__bug_table", KSPLICE_HOWTO_BUG
);
595 write_table_relocs(isbfd
, "__ex_table", KSPLICE_HOWTO_EXTABLE
);
597 remove_unkept_spans(isbfd
);
599 mangle_section_name(isbfd
, "__markers");
600 mangle_section_name(isbfd
, "__ex_table");
601 for (sect
= isbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
602 struct supersect
*ss
= fetch_supersect(isbfd
, sect
);
603 if (ss
->type
== SS_TYPE_EXPORT
)
604 mangle_section_name(isbfd
, ss
->name
);
608 void do_finalize(struct superbfd
*isbfd
)
610 load_ksplice_symbol_offsets(isbfd
);
612 for (sect
= isbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
613 struct supersect
*ss
= fetch_supersect(isbfd
, sect
);
614 if (ss
->type
== SS_TYPE_EXIT
) {
616 for (span
= ss
->spans
.data
;
617 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++)
622 write_date_relocs(isbfd
, "<{DATE...}>", KSPLICE_HOWTO_DATE
);
623 write_date_relocs(isbfd
, "<{TIME}>", KSPLICE_HOWTO_TIME
);
627 void do_rmsyms(struct superbfd
*isbfd
)
629 read_str_set(&rmsyms
);
633 void match_spans(struct span
*old_span
, struct span
*new_span
)
635 struct superbfd
*sbfd
= new_span
->ss
->parent
;
636 if (old_span
->match
== new_span
&& new_span
->match
== old_span
)
638 if (old_span
->match
!= NULL
) {
639 err(sbfd
, "Matching conflict: old %s: %s != %s\n",
640 old_span
->label
, old_span
->match
->label
, new_span
->label
);
643 if (new_span
->match
!= NULL
) {
644 err(sbfd
, "Matching conflict: new %s: %s != %s\n",
645 new_span
->label
, new_span
->match
->label
, old_span
->label
);
648 old_span
->match
= new_span
;
649 new_span
->match
= old_span
;
650 debug1(sbfd
, "Matched old %s to new %s\n", old_span
->label
,
652 if (old_span
->ss
->type
!= new_span
->ss
->type
&&
653 old_span
->ss
->type
== new_span
->ss
->orig_type
)
654 old_span
->ss
->type
= new_span
->ss
->type
;
657 static void match_global_symbols(struct span
*old_span
, asymbol
*oldsym
,
658 struct span
*new_span
, asymbol
*newsym
)
660 if ((oldsym
->flags
& BSF_GLOBAL
) == 0 ||
661 (newsym
->flags
& BSF_GLOBAL
) == 0)
663 match_spans(old_span
, new_span
);
666 static void check_global_symbols(struct span
*old_span
, asymbol
*oldsym
,
667 struct span
*new_span
, asymbol
*newsym
)
669 if ((oldsym
->flags
& BSF_GLOBAL
) == 0 ||
670 (newsym
->flags
& BSF_GLOBAL
) == 0)
672 if (old_span
->ss
->type
== SS_TYPE_IGNORED
)
674 if (old_span
->match
!= new_span
|| new_span
->match
!= old_span
) {
675 err(new_span
->ss
->parent
, "Global symbol span mismatch: %s "
676 "%s/%s\n", oldsym
->name
, old_span
->ss
->name
,
682 static void foreach_symbol_pair(struct superbfd
*oldsbfd
, struct superbfd
*newsbfd
,
683 void (*fn
)(struct span
*old_span
,
685 struct span
*new_span
,
688 asymbol
**oldsymp
, **newsymp
;
689 for (oldsymp
= oldsbfd
->syms
.data
;
690 oldsymp
< oldsbfd
->syms
.data
+ oldsbfd
->syms
.size
; oldsymp
++) {
691 asymbol
*oldsym
= *oldsymp
;
692 if (bfd_is_const_section(oldsym
->section
))
694 for (newsymp
= newsbfd
->syms
.data
;
695 newsymp
< newsbfd
->syms
.data
+ newsbfd
->syms
.size
;
697 asymbol
*newsym
= *newsymp
;
698 if (bfd_is_const_section(newsym
->section
))
700 if (strcmp(oldsym
->name
, newsym
->name
) != 0)
703 struct supersect
*old_ss
=
704 fetch_supersect(oldsbfd
, oldsym
->section
);
705 struct supersect
*new_ss
=
706 fetch_supersect(newsbfd
, newsym
->section
);
707 if ((old_ss
->type
!= new_ss
->type
&&
708 old_ss
->type
!= new_ss
->orig_type
) ||
709 old_ss
->type
== SS_TYPE_SPECIAL
||
710 old_ss
->type
== SS_TYPE_EXPORT
)
713 struct span
*old_span
=
714 find_span(old_ss
, oldsym
->value
);
715 struct span
*new_span
=
716 find_span(new_ss
, newsym
->value
);
717 if (old_span
== NULL
) {
718 err(oldsbfd
, "Could not find span for %s\n",
722 if (new_span
== NULL
) {
723 err(newsbfd
, "Could not find span for %s\n",
727 fn(old_span
, oldsym
, new_span
, newsym
);
732 static void match_symbol_spans(struct span
*old_span
, asymbol
*oldsym
,
733 struct span
*new_span
, asymbol
*newsym
)
735 if ((oldsym
->flags
& BSF_DEBUGGING
) != 0 ||
736 (newsym
->flags
& BSF_DEBUGGING
) != 0)
738 if (old_span
->ss
->type
== SS_TYPE_SPECIAL
)
740 if (static_local_symbol(old_span
->ss
->parent
, oldsym
) ||
741 static_local_symbol(new_span
->ss
->parent
, newsym
))
743 if (old_span
->match
== NULL
&& new_span
->match
== NULL
)
744 match_spans(old_span
, new_span
);
747 static void match_spans_by_label(struct span
*old_span
, struct span
*new_span
)
749 if (old_span
->ss
->type
== SS_TYPE_STRING
)
751 if (strcmp(old_span
->label
, new_span
->label
) == 0)
752 match_spans(old_span
, new_span
);
755 static void match_string_spans(struct span
*old_span
, struct span
*new_span
)
757 if (old_span
->ss
->type
!= SS_TYPE_STRING
||
758 strcmp(old_span
->ss
->name
, new_span
->ss
->name
) != 0)
760 if (strcmp((char *)old_span
->ss
->contents
.data
+ old_span
->start
,
761 (char *)new_span
->ss
->contents
.data
+ new_span
->start
) == 0)
762 match_spans(old_span
, new_span
);
765 static void foreach_span_pair(struct superbfd
*oldsbfd
,
766 struct superbfd
*newsbfd
,
767 void (*fn
)(struct span
*old_span
,
768 struct span
*new_span
))
770 asection
*oldsect
, *newsect
;
771 struct supersect
*oldss
, *newss
;
772 struct span
*old_span
, *new_span
;
773 for (newsect
= newsbfd
->abfd
->sections
; newsect
!= NULL
;
774 newsect
= newsect
->next
) {
775 newss
= fetch_supersect(newsbfd
, newsect
);
776 if (newss
->type
== SS_TYPE_SPECIAL
)
778 for (oldsect
= oldsbfd
->abfd
->sections
; oldsect
!= NULL
;
779 oldsect
= oldsect
->next
) {
780 oldss
= fetch_supersect(oldsbfd
, oldsect
);
781 if (oldss
->type
!= newss
->type
)
783 for (new_span
= newss
->spans
.data
;
784 new_span
< newss
->spans
.data
+ newss
->spans
.size
;
786 for (old_span
= oldss
->spans
.data
;
787 old_span
< oldss
->spans
.data
+
788 oldss
->spans
.size
; old_span
++)
789 fn(old_span
, new_span
);
795 static void mark_new_spans(struct superbfd
*sbfd
)
798 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
799 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
800 if (ss
->type
== SS_TYPE_SPECIAL
|| ss
->type
== SS_TYPE_IGNORED
)
803 for (span
= ss
->spans
.data
;
804 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++) {
805 if (span
->match
== NULL
&& !span
->bugpatch
)
811 static void handle_deleted_spans(struct superbfd
*oldsbfd
,
812 struct superbfd
*newsbfd
)
815 for (sect
= oldsbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
816 struct supersect
*ss
= fetch_supersect(oldsbfd
, sect
);
818 for (span
= ss
->spans
.data
;
819 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++) {
820 if (span
->match
!= NULL
)
822 if (ss
->type
== SS_TYPE_EXPORT
) {
823 *vec_grow(&delsects
, 1) = span
->label
;
824 write_ksplice_export(newsbfd
, span
, true);
825 } else if (ss
->type
== SS_TYPE_TEXT
) {
826 *vec_grow(&delsects
, 1) = span
->label
;
827 if (span
->symbol
== NULL
)
829 write_ksplice_deleted_patch
830 (newsbfd
, span
->symbol
->name
, span
->label
,
837 static void handle_nonzero_offset_relocs(struct supersect
*ss
)
839 struct span
*address_span
, *target_span
;
841 for (relocp
= ss
->relocs
.data
;
842 relocp
< ss
->relocs
.data
+ ss
->relocs
.size
; relocp
++) {
843 arelent
*reloc
= *relocp
;
844 address_span
= find_span(ss
, reloc
->address
);
845 if (!address_span
->new && !address_span
->patch
)
848 asymbol
*sym
= *reloc
->sym_ptr_ptr
;
849 if (bfd_is_const_section(sym
->section
))
851 bfd_vma offset
= get_reloc_offset(ss
, reloc
, true);
852 target_span
= reloc_target_span(ss
, reloc
);
853 if (sym
->value
+ offset
== target_span
->start
)
856 if (target_span
->ss
->type
!= SS_TYPE_TEXT
)
858 if (target_span
->patch
)
861 target_span
->patch
= true;
863 debug1(ss
->parent
, "Changing %s because a relocation from sect "
864 "%s has a nonzero offset %lx+%lx into it\n",
865 target_span
->label
, ss
->name
, (unsigned long)sym
->value
,
866 (unsigned long)offset
);
870 static void update_nonzero_offsets(struct superbfd
*sbfd
)
873 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
874 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
875 if (ss
->type
== SS_TYPE_SPECIAL
|| ss
->type
== SS_TYPE_IGNORED
)
877 handle_nonzero_offset_relocs(ss
);
881 static void compare_spans(struct span
*old_span
, struct span
*new_span
)
883 struct superbfd
*newsbfd
= new_span
->ss
->parent
;
885 bool nonrelocs_match
= nonrelocs_equal(old_span
, new_span
);
886 bool relocs_match
= all_relocs_equal(old_span
, new_span
);
887 if (nonrelocs_match
&& relocs_match
)
889 if (strcmp(old_span
->ss
->name
, "__bug_table") == 0 &&
890 strcmp(new_span
->ss
->name
, "__bug_table") == 0 && relocs_match
) {
891 debug1(newsbfd
, "Changing %s due to nonmatching line numbers\n",
893 new_span
->match
= NULL
;
894 old_span
->match
= NULL
;
895 new_span
->bugpatch
= true;
900 if (new_span
->contents_size
!= old_span
->contents_size
)
901 reason
= "differing sizes";
902 else if (!nonrelocs_match
)
903 reason
= "differing contents";
905 reason
= "differing relocations";
907 if (new_span
->ss
->type
== SS_TYPE_TEXT
) {
910 new_span
->patch
= true;
911 debug1(newsbfd
, "Changing %s due to %s\n", new_span
->label
,
913 } else if (new_span
->ss
->type
== SS_TYPE_RODATA
&&
914 new_span
->contents_size
== old_span
->contents_size
) {
915 if (new_span
->datapatch
)
917 new_span
->datapatch
= true;
918 debug1(newsbfd
, "Changing %s in-place due to %s\n",
919 new_span
->label
, reason
);
920 } else if (new_span
->ss
->type
== SS_TYPE_STRING
&&
921 old_span
->ss
->type
== SS_TYPE_STRING
&& relocs_match
&&
922 strcmp(new_span
->ss
->contents
.data
+ new_span
->start
,
923 old_span
->ss
->contents
.data
+ old_span
->start
) == 0) {
926 debug1(newsbfd
, "Unmatching %s and %s due to %s\n",
927 old_span
->label
, new_span
->label
, reason
);
928 new_span
->match
= NULL
;
929 old_span
->match
= NULL
;
932 if (unchangeable_section(new_span
->ss
))
933 err(newsbfd
, "warning: ignoring change to nonpatchable "
934 "section %s\n", new_span
->ss
->name
);
937 static void compare_matched_spans(struct superbfd
*newsbfd
)
940 for (sect
= newsbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
941 struct supersect
*ss
= fetch_supersect(newsbfd
, sect
);
943 for (span
= ss
->spans
.data
;
944 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++) {
945 if (span
->match
== NULL
)
947 compare_spans(span
->match
, span
);
952 static void handle_section_symbol_renames(struct superbfd
*oldsbfd
,
953 struct superbfd
*newsbfd
)
957 for (sect
= newsbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
958 struct supersect
*ss
= fetch_supersect(newsbfd
, sect
);
959 for (span
= ss
->spans
.data
;
960 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++) {
961 if (span
->match
== NULL
)
963 if (strcmp(span
->label
, span
->match
->label
) == 0)
965 if (strcmp(span
->orig_label
, span
->label
) != 0 &&
966 strcmp(span
->label
, span
->match
->label
) != 0)
968 if (span
->symbol
!= NULL
)
969 label_map_set(newsbfd
, span
->label
,
971 span
->label
= span
->match
->label
;
976 static bool part_of_reloc(struct supersect
*ss
, unsigned long addr
)
979 for (relocp
= ss
->relocs
.data
;
980 relocp
< ss
->relocs
.data
+ ss
->relocs
.size
; relocp
++) {
981 arelent
*reloc
= *relocp
;
982 if (addr
>= reloc
->address
&&
983 addr
< reloc
->address
+ reloc
->howto
->size
)
989 static bool nonrelocs_equal(struct span
*old_span
, struct span
*new_span
)
992 struct supersect
*old_ss
= old_span
->ss
, *new_ss
= new_span
->ss
;
993 if (old_span
->contents_size
!= new_span
->contents_size
)
995 const unsigned char *old
= old_ss
->contents
.data
+ old_span
->start
;
996 const unsigned char *new = new_ss
->contents
.data
+ new_span
->start
;
997 for (i
= 0; i
< old_span
->contents_size
; i
++) {
998 if (old
[i
] != new[i
] &&
999 !(part_of_reloc(old_ss
, i
+ old_span
->start
) &&
1000 part_of_reloc(new_ss
, i
+ new_span
->start
)))
1006 bool relocs_equal(struct supersect
*old_src_ss
, struct supersect
*new_src_ss
,
1007 arelent
*old_reloc
, arelent
*new_reloc
)
1009 struct superbfd
*oldsbfd
= old_src_ss
->parent
;
1010 struct superbfd
*newsbfd
= new_src_ss
->parent
;
1011 struct span
*old_addr_span
= find_span(old_src_ss
, old_reloc
->address
);
1012 struct span
*new_addr_span
= find_span(new_src_ss
, new_reloc
->address
);
1014 if (old_reloc
->address
- old_addr_span
->start
!=
1015 new_reloc
->address
- new_addr_span
->start
) {
1016 debug1(newsbfd
, "Section %s/%s has reloc address mismatch at "
1017 "%lx\n", old_src_ss
->name
, new_src_ss
->name
,
1018 (unsigned long)old_reloc
->address
);
1022 if (old_reloc
->howto
!= new_reloc
->howto
) {
1023 debug1(newsbfd
, "Section %s/%s has howto type mismatch at "
1024 "%lx\n", old_src_ss
->name
, new_src_ss
->name
,
1025 (unsigned long)old_reloc
->address
);
1029 if (non_dst_mask(old_src_ss
, old_reloc
) !=
1030 non_dst_mask(new_src_ss
, new_reloc
)) {
1031 debug1(newsbfd
, "Section %s/%s has contents mismatch at %lx\n",
1032 old_src_ss
->name
, new_src_ss
->name
,
1033 (unsigned long)old_reloc
->address
);
1037 asymbol
*old_sym
= *old_reloc
->sym_ptr_ptr
;
1038 asymbol
*new_sym
= *new_reloc
->sym_ptr_ptr
;
1039 asection
*old_sect
= old_sym
->section
;
1040 asection
*new_sect
= new_sym
->section
;
1042 bfd_vma old_offset
= get_reloc_offset(old_src_ss
, old_reloc
, true);
1043 bfd_vma new_offset
= get_reloc_offset(new_src_ss
, new_reloc
, true);
1045 if (bfd_is_und_section(old_sect
) || bfd_is_und_section(new_sect
)) {
1046 if (!bfd_is_und_section(new_sect
) && old_offset
!= 0 &&
1047 fetch_supersect(newsbfd
, new_sect
)->type
== SS_TYPE_TEXT
)
1050 if (!bfd_is_und_section(new_sect
) && new_offset
!= 0 &&
1051 fetch_supersect(oldsbfd
, old_sect
)->type
== SS_TYPE_TEXT
)
1054 return strcmp(old_sym
->name
, new_sym
->name
) == 0 &&
1055 old_offset
== new_offset
;
1058 if (bfd_is_abs_section(old_sect
) && bfd_is_abs_section(new_sect
)) {
1059 if (old_offset
+ old_sym
->value
== new_offset
+ new_sym
->value
)
1061 debug1(newsbfd
, "Differing relocations from %s/%s to ABS "
1062 "section: %lx/%lx\n", old_addr_span
->label
,
1063 new_addr_span
->label
,
1064 (unsigned long)(old_offset
+ old_sym
->value
),
1065 (unsigned long)(new_offset
+ new_sym
->value
));
1069 if (bfd_is_const_section(old_sect
) || bfd_is_const_section(new_sect
))
1072 struct supersect
*old_ss
= fetch_supersect(oldsbfd
, old_sect
);
1073 struct supersect
*new_ss
= fetch_supersect(newsbfd
, new_sect
);
1074 struct span
*old_span
= reloc_target_span(old_src_ss
, old_reloc
);
1075 struct span
*new_span
= reloc_target_span(new_src_ss
, new_reloc
);
1077 if (old_span
->match
!= new_span
|| new_span
->match
!= old_span
) {
1078 debug1(newsbfd
, "Nonmatching relocs from %s to %s/%s\n",
1079 new_src_ss
->name
, old_span
->label
, new_span
->label
);
1083 if (old_sym
->value
+ old_offset
- old_span
->start
!=
1084 new_sym
->value
+ new_offset
- new_span
->start
) {
1085 debug1(newsbfd
, "Offsets to %s/%s differ between %s "
1086 "and %s: %lx+%lx/%lx+%lx\n", old_ss
->name
,
1087 new_ss
->name
, old_src_ss
->name
, new_src_ss
->name
,
1088 (unsigned long)old_sym
->value
, (unsigned long)old_offset
,
1089 (unsigned long)new_sym
->value
,
1090 (unsigned long)new_offset
);
1094 if ((old_sym
->value
+ old_offset
- old_span
->start
!= 0 ||
1095 new_sym
->value
+ new_offset
- new_span
->start
!= 0) &&
1097 debug1(newsbfd
, "Relocation from %s to nonzero offsets "
1098 "%lx+%lx/%lx+%lx in changed section %s\n",
1099 new_src_ss
->name
, (unsigned long)old_sym
->value
,
1100 (unsigned long)old_offset
, (unsigned long)new_sym
->value
,
1101 (unsigned long)new_offset
, new_sym
->section
->name
);
1107 bool all_relocs_equal(struct span
*old_span
, struct span
*new_span
)
1109 struct supersect
*old_ss
= old_span
->ss
, *new_ss
= new_span
->ss
;
1110 arelent
**old_relocp
, **new_relocp
;
1112 for (old_relocp
= old_ss
->relocs
.data
;
1113 old_relocp
< old_ss
->relocs
.data
+ old_ss
->relocs
.size
;
1115 if (find_span(old_ss
, (*old_relocp
)->address
) == old_span
)
1119 for (new_relocp
= new_ss
->relocs
.data
;
1120 new_relocp
< new_ss
->relocs
.data
+ new_ss
->relocs
.size
;
1122 if (find_span(new_ss
, (*new_relocp
)->address
) == new_span
)
1126 for (; old_relocp
< old_ss
->relocs
.data
+ old_ss
->relocs
.size
&&
1127 find_span(old_ss
, (*old_relocp
)->address
) == old_span
&&
1128 new_relocp
< new_ss
->relocs
.data
+ new_ss
->relocs
.size
&&
1129 find_span(new_ss
, (*new_relocp
)->address
) == new_span
;
1130 old_relocp
++, new_relocp
++) {
1131 if (!relocs_equal(old_ss
, new_ss
, *old_relocp
, *new_relocp
))
1135 if ((old_relocp
< old_ss
->relocs
.data
+ old_ss
->relocs
.size
&&
1136 find_span(old_ss
, (*old_relocp
)->address
) == old_span
) ||
1137 (new_relocp
< new_ss
->relocs
.data
+ new_ss
->relocs
.size
&&
1138 find_span(new_ss
, (*new_relocp
)->address
) == new_span
)) {
1139 debug1(new_ss
->parent
, "Different reloc count between %s and "
1140 "%s\n", old_span
->label
, new_span
->label
);
1147 bfd_vma
non_dst_mask(struct supersect
*ss
, arelent
*reloc
)
1149 int bits
= bfd_get_reloc_size(reloc
->howto
) * 8;
1150 void *address
= ss
->contents
.data
+ reloc
->address
;
1151 bfd_vma x
= bfd_get(bits
, ss
->parent
->abfd
, address
);
1152 return x
& ~reloc
->howto
->dst_mask
;
1155 void rm_relocs(struct superbfd
*isbfd
)
1158 for (p
= isbfd
->abfd
->sections
; p
!= NULL
; p
= p
->next
) {
1159 struct supersect
*ss
= fetch_supersect(isbfd
, p
);
1160 bool remove_relocs
= ss
->keep
;
1162 if (mode("keep") && ss
->type
== SS_TYPE_SPECIAL
)
1163 remove_relocs
= false;
1165 if (ss
->type
== SS_TYPE_KSPLICE
||
1166 ss
->type
== SS_TYPE_KSPLICE_CALL
)
1167 remove_relocs
= false;
1168 if (mode("finalize") &&
1169 (starts_with(ss
->name
, ".ksplice_patches") ||
1170 starts_with(ss
->name
, ".ksplice_relocs")))
1171 remove_relocs
= true;
1178 void rm_some_relocs(struct supersect
*ss
)
1180 struct arelentp_vec orig_relocs
;
1181 vec_move(&orig_relocs
, &ss
->relocs
);
1184 for (relocp
= orig_relocs
.data
;
1185 relocp
< orig_relocs
.data
+ orig_relocs
.size
; relocp
++) {
1186 bool rm_reloc
= false;
1187 asymbol
*sym_ptr
= *(*relocp
)->sym_ptr_ptr
;
1189 if (mode("rmsyms") && str_in_set(sym_ptr
->name
, &rmsyms
) &&
1190 bfd_is_und_section(sym_ptr
->section
))
1196 if (mode("keep-primary") &&
1197 (bfd_is_const_section(sym_ptr
->section
) ||
1198 reloc_target_span(ss
, *relocp
)->new))
1201 if (mode("keep-primary")) {
1202 const struct table_section
*ts
=
1203 get_table_section(ss
->name
);
1204 if (ts
!= NULL
&& ts
->has_addr
&&
1205 ((*relocp
)->address
% ts
->entry_size
==
1207 (*relocp
)->address
% ts
->entry_size
==
1212 if (mode("finalize") && bfd_is_und_section(sym_ptr
->section
))
1215 if (strcmp(sym_ptr
->name
, "mcount") == 0 &&
1216 bfd_is_und_section(sym_ptr
->section
))
1219 if (!find_span(ss
, (*relocp
)->address
)->keep
)
1223 write_ksplice_reloc(ss
, *relocp
);
1225 *vec_grow(&ss
->relocs
, 1) = *relocp
;
1229 struct supersect
*make_section(struct superbfd
*sbfd
, const char *fmt
, ...)
1233 char *name
= vstrprintf(fmt
, ap
);
1236 asection
*sect
= bfd_get_section_by_name(sbfd
->abfd
, name
);
1238 return fetch_supersect(sbfd
, sect
);
1240 return new_supersect(sbfd
, name
);
1243 arelent
*create_reloc(struct supersect
*ss
, const void *addr
, asymbol
**symp
,
1246 bfd_reloc_code_real_type code
;
1247 switch (bfd_arch_bits_per_address(ss
->parent
->abfd
)) {
1249 code
= BFD_RELOC_32
;
1252 code
= BFD_RELOC_64
;
1258 arelent
*reloc
= malloc(sizeof(*reloc
));
1259 reloc
->sym_ptr_ptr
= symp
;
1260 reloc
->address
= addr_offset(ss
, addr
);
1261 reloc
->howto
= bfd_reloc_type_lookup(ss
->parent
->abfd
, code
);
1262 reloc
->addend
= offset
;
1266 void write_reloc(struct supersect
*ss
, const void *addr
, asymbol
**symp
,
1269 *vec_grow(&ss
->new_relocs
, 1) = create_reloc(ss
, addr
, symp
, offset
);
1272 void write_string(struct supersect
*ss
, const char **addr
, const char *fmt
, ...)
1275 struct supersect
*str_ss
= make_section(ss
->parent
, ".ksplice_str");
1278 int len
= vasprintf(&str
, fmt
, ap
);
1282 unsigned long *str_offp
= ulong_hash_lookup(&ksplice_string_offset
, str
,
1284 if (str_offp
== NULL
) {
1285 char *buf
= sect_grow(str_ss
, len
+ 1, char);
1286 memcpy(buf
, str
, len
+ 1);
1287 str_offp
= ulong_hash_lookup(&ksplice_string_offset
, str
, TRUE
);
1288 *str_offp
= addr_offset(str_ss
, buf
);
1291 write_reloc(ss
, addr
, &str_ss
->symbol
, *str_offp
);
1294 void lookup_system_map(struct addr_vec
*addrs
, const char *name
, long offset
)
1296 struct addr_vec
*map_addrs
=
1297 addr_vec_hash_lookup(&system_map
, name
, FALSE
);
1298 if (map_addrs
== NULL
)
1301 unsigned long *addr
, *map_addr
;
1302 for (map_addr
= map_addrs
->data
;
1303 map_addr
< map_addrs
->data
+ map_addrs
->size
; map_addr
++) {
1304 for (addr
= addrs
->data
; addr
< addrs
->data
+ addrs
->size
;
1306 if (*addr
== *map_addr
+ offset
)
1309 if (addr
< addrs
->data
+ addrs
->size
)
1311 *vec_grow(addrs
, 1) = *map_addr
+ offset
;
1315 void compute_system_map_array(struct superbfd
*sbfd
, struct addr_vec
*addrs
,
1318 if (bfd_is_abs_section(sym
->section
)) {
1319 *vec_grow(addrs
, 1) = sym
->value
;
1320 } else if (bfd_is_und_section(sym
->section
)) {
1321 lookup_system_map(addrs
, sym
->name
, 0);
1322 } else if (!bfd_is_const_section(sym
->section
)) {
1324 for (gsymp
= sbfd
->syms
.data
;
1325 gsymp
< sbfd
->syms
.data
+ sbfd
->syms
.size
; gsymp
++) {
1326 asymbol
*gsym
= *gsymp
;
1327 if ((gsym
->flags
& BSF_DEBUGGING
) == 0 &&
1328 gsym
->section
== sym
->section
)
1329 lookup_system_map(addrs
, gsym
->name
,
1330 sym
->value
- gsym
->value
);
1335 void write_ksplice_system_map(struct superbfd
*sbfd
, asymbol
*sym
,
1338 bool *done
= bool_hash_lookup(&system_map_written
, label
, TRUE
);
1343 struct addr_vec addrs
;
1346 compute_system_map_array(sbfd
, &addrs
, sym
);
1347 if (addrs
.size
!= 0) {
1348 struct supersect
*smap_ss
=
1349 make_section(sbfd
, ".ksplice_system_map");
1350 struct ksplice_system_map
*smap
=
1351 sect_grow(smap_ss
, 1, struct ksplice_system_map
);
1352 write_string(smap_ss
, &smap
->label
, "%s", label
);
1354 struct supersect
*array_ss
= make_section(sbfd
,
1356 void *buf
= sect_grow(array_ss
, addrs
.size
,
1357 typeof(*addrs
.data
));
1358 memcpy(buf
, addrs
.data
, addrs
.size
* sizeof(*addrs
.data
));
1359 smap
->nr_candidates
= addrs
.size
;
1360 write_reloc(smap_ss
, &smap
->candidates
, &array_ss
->symbol
,
1361 addr_offset(array_ss
, buf
));
1366 void write_ksplice_symbol_backend(struct supersect
*ss
,
1367 struct ksplice_symbol
*const *addr
,
1368 asymbol
*sym
, const char *label
,
1371 struct supersect
*ksymbol_ss
= make_section(ss
->parent
,
1372 ".ksplice_symbols");
1373 struct ksplice_symbol
*ksymbol
;
1374 unsigned long *ksymbol_offp
;
1376 ksymbol_offp
= ulong_hash_lookup(&ksplice_symbol_offset
, label
, FALSE
);
1377 if (ksymbol_offp
!= NULL
) {
1378 write_reloc(ss
, addr
, &ksymbol_ss
->symbol
, *ksymbol_offp
);
1381 ksymbol
= sect_grow(ksymbol_ss
, 1, struct ksplice_symbol
);
1382 ksymbol_offp
= ulong_hash_lookup(&ksplice_symbol_offset
, label
, TRUE
);
1383 *ksymbol_offp
= addr_offset(ksymbol_ss
, ksymbol
);
1385 write_reloc(ss
, addr
, &ksymbol_ss
->symbol
, *ksymbol_offp
);
1386 write_string(ksymbol_ss
, &ksymbol
->label
, "%s", label
);
1388 write_string(ksymbol_ss
, &ksymbol
->name
, "%s", name
);
1389 write_ksplice_system_map(ksymbol_ss
->parent
, sym
, label
);
1393 void write_ksplice_symbol(struct supersect
*ss
,
1394 struct ksplice_symbol
*const *addr
,
1395 asymbol
*sym
, struct span
*span
,
1396 const char *addstr_sect
)
1398 const char *label
, *name
;
1399 if (span
!= NULL
&& span
->start
!= 0)
1400 label
= span
->label
;
1402 label
= label_lookup(ss
->parent
, sym
);
1404 asymbol
*gsym
= canonical_symbol(ss
->parent
, sym
);
1405 if (strcmp(addstr_sect
, "") != 0)
1407 else if (bfd_is_und_section(sym
->section
))
1409 else if (bfd_is_const_section(sym
->section
))
1411 else if (span
!= NULL
&& span
->symbol
== NULL
)
1413 else if (gsym
== NULL
|| (gsym
->flags
& BSF_SECTION_SYM
) != 0)
1418 write_ksplice_symbol_backend(ss
, addr
, sym
,
1419 strprintf("%s%s", addstr_sect
, label
),
1423 void write_ksplice_reloc(struct supersect
*ss
, arelent
*orig_reloc
)
1425 asymbol
*sym_ptr
= *orig_reloc
->sym_ptr_ptr
;
1426 bfd_vma reloc_addend
= get_reloc_offset(ss
, orig_reloc
, false);
1427 bfd_vma target_addend
= get_reloc_offset(ss
, orig_reloc
, true);
1428 unsigned long *repladdr
= ss
->contents
.data
+ orig_reloc
->address
;
1430 if (mode("finalize") && starts_with(ss
->name
, ".ksplice_patches")) {
1434 if (mode("finalize") && starts_with(ss
->name
, ".ksplice_relocs")) {
1435 assert(starts_with(sym_ptr
->name
, KSPLICE_SYMBOL_STR
));
1437 fake_sym
.name
= sym_ptr
->name
+ strlen(KSPLICE_SYMBOL_STR
);
1438 fake_sym
.section
= bfd_und_section_ptr
;
1442 write_ksplice_symbol_backend
1443 (ss
, (struct ksplice_symbol
**)repladdr
, &fake_sym
,
1444 fake_sym
.name
, fake_sym
.name
);
1448 struct span
*span
= reloc_target_span(ss
, orig_reloc
);
1449 if (span
== ss
->spans
.data
&& span
->start
!= target_addend
)
1451 write_canary(ss
, orig_reloc
->address
,
1452 bfd_get_reloc_size(orig_reloc
->howto
),
1453 orig_reloc
->howto
->dst_mask
);
1455 struct supersect
*kreloc_ss
;
1457 kreloc_ss
= make_section(ss
->parent
, ".ksplice_init_relocs");
1459 kreloc_ss
= make_section(ss
->parent
, ".ksplice_relocs%s",
1461 struct ksplice_reloc
*kreloc
= sect_grow(kreloc_ss
, 1,
1462 struct ksplice_reloc
);
1464 struct span
*address_span
= find_span(ss
, orig_reloc
->address
);
1465 write_reloc(kreloc_ss
, &kreloc
->blank_addr
,
1466 &ss
->symbol
, orig_reloc
->address
+ address_span
->shift
);
1467 if (bfd_is_und_section(sym_ptr
->section
) && mode("keep")) {
1468 char *name
= strprintf(KSPLICE_SYMBOL_STR
"%s", sym_ptr
->name
);
1469 asymbol
**symp
= make_undefined_symbolp(ss
->parent
, name
);
1470 write_reloc(kreloc_ss
, &kreloc
->symbol
, symp
, 0);
1472 write_ksplice_symbol(kreloc_ss
, &kreloc
->symbol
, sym_ptr
, span
,
1475 if (span
!= NULL
&& span
->start
!= 0) {
1476 reloc_addend
+= sym_ptr
->value
- span
->start
;
1477 target_addend
+= sym_ptr
->value
- span
->start
;
1479 kreloc
->insn_addend
= reloc_addend
- target_addend
;
1480 kreloc
->target_addend
= target_addend
;
1481 write_ksplice_reloc_howto(kreloc_ss
, &kreloc
->howto
, orig_reloc
->howto
,
1482 KSPLICE_HOWTO_RELOC
);
1485 static void write_ksplice_reloc_howto(struct supersect
*ss
, const
1486 struct ksplice_reloc_howto
*const *addr
,
1487 reloc_howto_type
*howto
,
1488 enum ksplice_reloc_howto_type type
)
1490 struct supersect
*khowto_ss
= make_section(ss
->parent
,
1491 ".ksplice_reloc_howtos");
1492 struct ksplice_reloc_howto
*khowto
;
1493 unsigned long *khowto_offp
;
1495 khowto_offp
= ulong_hash_lookup(&ksplice_howto_offset
, howto
->name
,
1497 if (khowto_offp
!= NULL
) {
1498 write_reloc(ss
, addr
, &khowto_ss
->symbol
, *khowto_offp
);
1501 khowto
= sect_grow(khowto_ss
, 1, struct ksplice_reloc_howto
);
1502 khowto_offp
= ulong_hash_lookup(&ksplice_howto_offset
, howto
->name
,
1504 *khowto_offp
= addr_offset(khowto_ss
, khowto
);
1506 khowto
->type
= type
;
1507 khowto
->pcrel
= howto
->pc_relative
;
1508 khowto
->size
= bfd_get_reloc_size(howto
);
1509 khowto
->dst_mask
= howto
->dst_mask
;
1510 khowto
->rightshift
= howto
->rightshift
;
1511 khowto
->signed_addend
=
1512 (howto
->complain_on_overflow
== complain_overflow_signed
) ||
1513 (howto
->complain_on_overflow
== complain_overflow_bitfield
);
1514 write_reloc(ss
, addr
, &khowto_ss
->symbol
, *khowto_offp
);
1517 #define CANARY(x, canary) ((x & ~howto->dst_mask) | (canary & howto->dst_mask))
1519 void write_canary(struct supersect
*ss
, int offset
, bfd_size_type size
,
1522 int bits
= size
* 8;
1523 void *address
= ss
->contents
.data
+ offset
;
1524 bfd_vma x
= bfd_get(bits
, ss
->parent
->abfd
, address
);
1525 x
= (x
& ~dst_mask
) | ((bfd_vma
)KSPLICE_CANARY
& dst_mask
);
1526 bfd_put(bits
, ss
->parent
->abfd
, x
, address
);
1529 static void write_date_relocs(struct superbfd
*sbfd
, const char *str
,
1530 enum ksplice_reloc_howto_type type
)
1533 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
1534 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
1535 if (ss
->type
!= SS_TYPE_STRING
&& ss
->type
!= SS_TYPE_RODATA
)
1539 for (span
= ss
->spans
.data
;
1540 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++) {
1543 for (ptr
= ss
->contents
.data
+ span
->start
;
1544 ptr
+ strlen(str
) < ss
->contents
.data
+
1545 span
->start
+ span
->contents_size
; ptr
++) {
1546 if (strcmp((const char *)ptr
, str
) == 0)
1547 write_ksplice_date_reloc
1548 (ss
, addr_offset(ss
, ptr
), str
,
1555 static void write_ksplice_date_reloc(struct supersect
*ss
, unsigned long offset
,
1557 enum ksplice_reloc_howto_type type
)
1559 struct supersect
*kreloc_ss
;
1560 kreloc_ss
= make_section(ss
->parent
, ".ksplice_relocs%s", ss
->name
);
1561 struct ksplice_reloc
*kreloc
= sect_grow(kreloc_ss
, 1,
1562 struct ksplice_reloc
);
1564 const char *filename
= ss
->parent
->abfd
->filename
;
1565 char *c
= strstr(filename
, ".KSPLICE");
1566 int flen
= (c
== NULL
? strlen(filename
) : c
- filename
);
1568 write_ksplice_symbol_backend(kreloc_ss
, &kreloc
->symbol
, NULL
,
1569 strprintf("%s<%.*s>", str
, flen
, filename
),
1572 struct span
*span
= find_span(ss
, offset
);
1573 write_reloc(kreloc_ss
, &kreloc
->blank_addr
, &ss
->symbol
,
1574 offset
+ span
->shift
);
1575 write_ksplice_nonreloc_howto(kreloc_ss
, &kreloc
->howto
, type
,
1579 static void write_table_relocs(struct superbfd
*sbfd
, const char *sectname
,
1580 enum ksplice_reloc_howto_type type
)
1582 asection
*sect
= bfd_get_section_by_name(sbfd
->abfd
, sectname
);
1585 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
1587 const struct table_section
*s
= get_table_section(sectname
);
1592 for (entry
= ss
->contents
.data
;
1593 entry
< ss
->contents
.data
+ ss
->contents
.size
;
1594 entry
+= s
->entry_size
) {
1595 struct span
*span
= find_span(ss
, addr_offset(ss
, entry
));
1596 assert(span
!= NULL
);
1600 arelent
*reloc
= find_reloc(ss
, entry
+ s
->addr_offset
);
1601 assert(reloc
!= NULL
);
1602 asymbol
*sym
= *reloc
->sym_ptr_ptr
;
1603 assert(!bfd_is_const_section(sym
->section
));
1604 struct supersect
*sym_ss
= fetch_supersect(sbfd
, sym
->section
);
1605 unsigned long addr
= get_reloc_offset(ss
, reloc
, true) +
1607 write_ksplice_table_reloc(sym_ss
, addr
, span
->label
, type
);
1611 static void write_ksplice_table_reloc(struct supersect
*ss
,
1612 unsigned long address
,
1614 enum ksplice_reloc_howto_type type
)
1616 struct supersect
*kreloc_ss
;
1617 kreloc_ss
= make_section(ss
->parent
, ".ksplice_relocs%s", ss
->name
);
1618 struct ksplice_reloc
*kreloc
= sect_grow(kreloc_ss
, 1,
1619 struct ksplice_reloc
);
1620 struct span
*span
= find_span(ss
, address
);
1621 assert(span
!= NULL
);
1623 write_ksplice_symbol_backend(kreloc_ss
, &kreloc
->symbol
, NULL
,
1625 write_reloc(kreloc_ss
, &kreloc
->blank_addr
, &ss
->symbol
,
1626 address
+ span
->shift
);
1627 write_ksplice_nonreloc_howto(kreloc_ss
, &kreloc
->howto
, type
, 0);
1630 static void write_ksplice_nonreloc_howto(struct supersect
*ss
,
1631 const struct ksplice_reloc_howto
1633 enum ksplice_reloc_howto_type type
,
1636 struct supersect
*khowto_ss
=
1637 make_section(ss
->parent
, ".ksplice_reloc_howtos");
1638 struct ksplice_reloc_howto
*khowto
=
1639 sect_grow(khowto_ss
, 1, struct ksplice_reloc_howto
);
1641 khowto
->type
= type
;
1642 khowto
->size
= size
;
1644 khowto
->dst_mask
= 0;
1645 khowto
->rightshift
= 0;
1646 khowto
->signed_addend
= 0;
1647 write_reloc(ss
, addr
, &khowto_ss
->symbol
,
1648 addr_offset(khowto_ss
, khowto
));
1651 static void write_ksplice_section(struct span
*span
)
1653 struct supersect
*ss
= span
->ss
;
1654 const char *sectname
= span
->ss
->name
;
1655 const struct table_section
*ts
= get_table_section(ss
->name
);
1657 if (ts
!= NULL
&& ts
->has_addr
) {
1658 arelent
*reloc
= find_reloc(ss
, ss
->contents
.data
+ span
->start
1660 assert(reloc
!= NULL
);
1661 asymbol
*rsym
= *reloc
->sym_ptr_ptr
;
1662 assert(!bfd_is_const_section(rsym
->section
));
1663 sectname
= rsym
->section
->name
;
1666 struct supersect
*ksect_ss
=
1667 make_section(ss
->parent
, ".ksplice_sections%s", sectname
);
1668 struct ksplice_section
*ksect
= sect_grow(ksect_ss
, 1,
1669 struct ksplice_section
);
1670 asymbol
*sym
= span
->symbol
== NULL
? ss
->symbol
: span
->symbol
;
1672 write_ksplice_symbol(ksect_ss
, &ksect
->symbol
, sym
, span
,
1673 mode("keep-primary") ? "(post)" : "");
1674 ksect
->size
= span
->size
;
1677 if (ss
->type
== SS_TYPE_RODATA
|| ss
->type
== SS_TYPE_STRING
||
1678 ss
->type
== SS_TYPE_EXPORT
)
1679 ksect
->flags
|= KSPLICE_SECTION_RODATA
;
1680 if (ss
->type
== SS_TYPE_DATA
)
1681 ksect
->flags
|= KSPLICE_SECTION_DATA
;
1682 if (ss
->type
== SS_TYPE_TEXT
)
1683 ksect
->flags
|= KSPLICE_SECTION_TEXT
;
1684 assert(ksect
->flags
!= 0);
1686 if (ss
->type
== SS_TYPE_STRING
)
1687 ksect
->flags
|= KSPLICE_SECTION_STRING
;
1689 write_reloc(ksect_ss
, &ksect
->address
, &ss
->symbol
,
1690 span
->start
+ span
->shift
);
1693 static void write_ksplice_patch_reloc(struct supersect
*ss
,
1694 const char *sectname
, unsigned long *addr
,
1695 bfd_size_type size
, const char *label
,
1698 struct supersect
*kreloc_ss
;
1699 kreloc_ss
= make_section(ss
->parent
, ".ksplice_relocs%s", sectname
);
1700 struct ksplice_reloc
*kreloc
= sect_grow(kreloc_ss
, 1,
1701 struct ksplice_reloc
);
1703 write_canary(ss
, addr_offset(ss
, addr
), size
, -1);
1704 write_ksplice_symbol_backend(kreloc_ss
, &kreloc
->symbol
, NULL
,
1706 write_reloc(kreloc_ss
, &kreloc
->blank_addr
, &ss
->symbol
,
1707 addr_offset(ss
, addr
));
1708 reloc_howto_type
*howto
=
1709 bfd_reloc_type_lookup(ss
->parent
->abfd
,
1710 PASTE(BFD_RELOC_
, LONG_BIT
));
1711 write_ksplice_reloc_howto(kreloc_ss
, &kreloc
->howto
, howto
,
1712 KSPLICE_HOWTO_RELOC
);
1713 kreloc
->target_addend
= addend
;
1714 kreloc
->insn_addend
= 0;
1717 void write_ksplice_patch(struct superbfd
*sbfd
, struct span
*span
)
1719 struct supersect
*kpatch_ss
=
1720 make_section(sbfd
, ".ksplice_patches%s", span
->ss
->name
);
1721 struct ksplice_patch
*kpatch
= sect_grow(kpatch_ss
, 1,
1722 struct ksplice_patch
);
1724 write_ksplice_patch_reloc(kpatch_ss
, span
->ss
->name
, &kpatch
->oldaddr
,
1725 sizeof(kpatch
->oldaddr
), span
->label
, 0);
1726 if (span
->ss
->type
== SS_TYPE_TEXT
) {
1727 kpatch
->type
= KSPLICE_PATCH_TEXT
;
1728 write_patch_storage(kpatch_ss
, kpatch
, MAX_TRAMPOLINE_SIZE
,
1731 kpatch
->type
= KSPLICE_PATCH_DATA
;
1732 kpatch
->size
= span
->contents_size
;
1733 struct supersect
*data_ss
=
1734 make_section(sbfd
, ".ksplice_patch_data");
1735 write_reloc(kpatch_ss
, &kpatch
->contents
, &span
->ss
->symbol
,
1736 span
->start
+ span
->shift
);
1737 char *saved
= sect_do_grow(data_ss
, 1, span
->contents_size
, 1);
1738 write_reloc(kpatch_ss
, &kpatch
->saved
, &data_ss
->symbol
,
1739 addr_offset(data_ss
, saved
));
1741 write_reloc(kpatch_ss
, &kpatch
->repladdr
, &span
->ss
->symbol
,
1742 span
->start
+ span
->shift
);
1745 asymbol
**make_undefined_symbolp(struct superbfd
*sbfd
, const char *name
)
1748 for (symp
= sbfd
->syms
.data
; symp
< sbfd
->syms
.data
+ sbfd
->syms
.size
;
1750 asymbol
*sym
= *symp
;
1751 if (strcmp(name
, sym
->name
) == 0 &&
1752 bfd_is_und_section(sym
->section
))
1756 for (sympp
= sbfd
->new_syms
.data
;
1757 sympp
< sbfd
->new_syms
.data
+ sbfd
->new_syms
.size
; sympp
++) {
1758 asymbol
**symp
= *sympp
;
1759 asymbol
*sym
= *symp
;
1760 if (strcmp(name
, sym
->name
) == 0 &&
1761 bfd_is_und_section(sym
->section
))
1765 symp
= malloc(sizeof(*symp
));
1766 *symp
= bfd_make_empty_symbol(sbfd
->abfd
);
1767 asymbol
*sym
= *symp
;
1769 sym
->section
= bfd_und_section_ptr
;
1772 *vec_grow(&sbfd
->new_syms
, 1) = symp
;
1776 void write_ksplice_deleted_patch(struct superbfd
*sbfd
, const char *name
,
1777 const char *label
, const char *sectname
)
1779 struct supersect
*kpatch_ss
=
1780 make_section(sbfd
, ".ksplice_patches%s", sectname
);
1781 struct ksplice_patch
*kpatch
= sect_grow(kpatch_ss
, 1,
1782 struct ksplice_patch
);
1784 write_ksplice_patch_reloc(kpatch_ss
, sectname
, &kpatch
->oldaddr
,
1785 sizeof(kpatch
->oldaddr
), label
, 0);
1786 kpatch
->type
= KSPLICE_PATCH_TEXT
;
1787 asymbol
**symp
= make_undefined_symbolp(sbfd
, strdup(name
));
1788 write_reloc(kpatch_ss
, &kpatch
->repladdr
, symp
, 0);
1789 write_patch_storage(kpatch_ss
, kpatch
, MAX_TRAMPOLINE_SIZE
, NULL
);
1792 void write_ksplice_export(struct superbfd
*sbfd
, struct span
*span
, bool del
)
1794 struct supersect
*kpatch_ss
= make_section(sbfd
, ".ksplice_patches");
1795 struct ksplice_patch
*kpatch
= sect_grow(kpatch_ss
, 1,
1796 struct ksplice_patch
);
1797 struct supersect
*data_ss
;
1799 const struct table_section
*ts
= get_table_section(span
->ss
->name
);
1802 span
->ss
->contents
.data
+ span
->start
+ ts
->other_offset
;
1803 const char *symname
= read_string(span
->ss
, addr
);
1805 char *oldname
, *newname
;
1807 oldname
= strprintf("%s:%s", span
->ss
->name
, symname
);
1808 newname
= strprintf("DISABLED_%s_%s", symname
, kid
);
1810 oldname
= strprintf("%s:DISABLED_%s_%s", span
->ss
->name
,
1812 newname
= strprintf("%s", symname
);
1813 write_string(span
->ss
, addr
, "DISABLED_%s_%s", symname
, kid
);
1816 write_ksplice_patch_reloc(kpatch_ss
, "", &kpatch
->oldaddr
,
1817 sizeof(kpatch
->oldaddr
), oldname
,
1819 kpatch
->type
= KSPLICE_PATCH_EXPORT
;
1820 const char **namep
= write_patch_storage(kpatch_ss
, kpatch
,
1821 sizeof(newname
), &data_ss
);
1822 write_string(data_ss
, namep
, "%s", newname
);
1825 void filter_table_sections(struct superbfd
*isbfd
)
1827 struct supersect
*tables_ss
=
1828 fetch_supersect(offsets_sbfd
,
1829 bfd_get_section_by_name(offsets_sbfd
->abfd
,
1830 ".ksplice_table_sections"));
1831 const struct table_section
*ts
;
1832 for (ts
= tables_ss
->contents
.data
;
1833 (void *)ts
< tables_ss
->contents
.data
+ tables_ss
->contents
.size
;
1835 struct table_section s
= *ts
;
1836 s
.sect
= read_string(tables_ss
, &ts
->sect
);
1837 s
.other_sect
= read_string(tables_ss
, &ts
->other_sect
);
1838 s
.crc_sect
= read_string(tables_ss
, &ts
->crc_sect
);
1839 filter_table_section(isbfd
, &s
);
1843 void filter_table_section(struct superbfd
*sbfd
, const struct table_section
*s
)
1845 asection
*isection
= bfd_get_section_by_name(sbfd
->abfd
, s
->sect
);
1846 if (isection
== NULL
)
1848 struct supersect
*ss
= fetch_supersect(sbfd
, isection
);
1851 for (entry
= ss
->contents
.data
;
1852 entry
< ss
->contents
.data
+ ss
->contents
.size
;
1853 entry
+= s
->entry_size
) {
1854 struct span
*span
= find_span(ss
, addr_offset(ss
, entry
));
1855 assert(span
!= NULL
);
1858 arelent
*reloc
= find_reloc(ss
, entry
+ s
->addr_offset
);
1859 assert(reloc
!= NULL
);
1860 struct span
*sym_span
= reloc_target_span(ss
, reloc
);
1865 if (s
->other_sect
!= NULL
) {
1867 find_reloc(ss
, entry
+ s
->other_offset
);
1868 assert(reloc
!= NULL
);
1869 struct span
*sym_span
= reloc_target_span(ss
, reloc
);
1871 keep_span(sym_span
);
1874 if (s
->crc_sect
!= NULL
) {
1875 struct span
*crc_span
= get_crc_span(span
, s
);
1876 assert(crc_span
!= NULL
);
1877 if (span
->keep
&& mode("keep-primary"))
1878 keep_span(crc_span
);
1883 static struct span
*get_crc_span(struct span
*span
,
1884 const struct table_section
*ts
)
1886 void *entry
= span
->ss
->contents
.data
+ span
->start
;
1887 asection
*crc_sect
= bfd_get_section_by_name(span
->ss
->parent
->abfd
,
1889 if (crc_sect
== NULL
)
1891 struct supersect
*crc_ss
= fetch_supersect(span
->ss
->parent
, crc_sect
);
1894 struct span
*crc_span
= find_span(crc_ss
, addr_offset(span
->ss
, entry
) /
1895 ts
->entry_size
* ts
->crc_size
);
1899 void mark_precallable_spans(struct superbfd
*sbfd
)
1902 struct supersect
*ss
, *sym_ss
;
1903 struct span
*address_span
, *target_span
;
1904 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
1905 ss
= fetch_supersect(sbfd
, sect
);
1907 if (ss
->type
== SS_TYPE_SPECIAL
)
1909 for (relocp
= ss
->relocs
.data
;
1910 relocp
< ss
->relocs
.data
+ ss
->relocs
.size
; relocp
++) {
1911 asymbol
*sym
= *(*relocp
)->sym_ptr_ptr
;
1912 address_span
= find_span(ss
, (*relocp
)->address
);
1913 if (!address_span
->precallable
)
1915 target_span
= reloc_target_span(ss
, *relocp
);
1916 if (target_span
== NULL
|| target_span
->keep
)
1918 sym_ss
= fetch_supersect(sbfd
, sym
->section
);
1919 if (sym_ss
->type
== SS_TYPE_IGNORED
)
1921 target_span
->precallable
= true;
1927 void keep_referenced_sections(struct superbfd
*sbfd
)
1930 struct supersect
*ss
, *sym_ss
;
1931 struct span
*address_span
, *target_span
;
1932 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
1933 ss
= fetch_supersect(sbfd
, sect
);
1935 if (ss
->type
== SS_TYPE_SPECIAL
)
1937 for (relocp
= ss
->relocs
.data
;
1938 relocp
< ss
->relocs
.data
+ ss
->relocs
.size
; relocp
++) {
1939 asymbol
*sym
= *(*relocp
)->sym_ptr_ptr
;
1940 address_span
= find_span(ss
, (*relocp
)->address
);
1941 if (!address_span
->keep
)
1943 target_span
= reloc_target_span(ss
, *relocp
);
1944 if (target_span
== NULL
|| target_span
->keep
)
1946 sym_ss
= fetch_supersect(sbfd
, sym
->section
);
1947 if (sym_ss
->type
== SS_TYPE_IGNORED
)
1949 keep_span(target_span
);
1955 void copy_symbols(struct asymbolp_vec
*osyms
, struct asymbolpp_vec
*isyms
)
1958 for (sympp
= isyms
->data
; sympp
< isyms
->data
+ isyms
->size
; sympp
++)
1959 *vec_grow(osyms
, 1) = **sympp
;
1962 /* Modified function from GNU Binutils objcopy.c */
1963 bfd_boolean
copy_object(bfd
*ibfd
, bfd
*obfd
)
1965 assert(bfd_set_format(obfd
, bfd_get_format(ibfd
)));
1967 bfd_vma start
= bfd_get_start_address(ibfd
);
1969 flagword flags
= bfd_get_file_flags(ibfd
);
1970 flags
&= bfd_applicable_file_flags(obfd
);
1972 assert(bfd_set_start_address(obfd
, start
)
1973 && bfd_set_file_flags(obfd
, flags
));
1975 enum bfd_architecture iarch
= bfd_get_arch(ibfd
);
1976 unsigned int imach
= bfd_get_mach(ibfd
);
1977 assert(bfd_set_arch_mach(obfd
, iarch
, imach
));
1978 assert(bfd_set_format(obfd
, bfd_get_format(ibfd
)));
1980 /* BFD mandates that all output sections be created and sizes set before
1981 any output is done. Thus, we traverse all sections multiple times. */
1982 bfd_map_over_sections(ibfd
, setup_section
, obfd
);
1984 struct supersect
*new_supersects
= fetch_superbfd(ibfd
)->new_supersects
;
1985 struct supersect
*ss
;
1986 for (ss
= new_supersects
; ss
!= NULL
; ss
= ss
->next
)
1987 setup_new_section(obfd
, ss
);
1989 /* Mark symbols used in output relocations so that they
1990 are kept, even if they are local labels or static symbols.
1992 Note we iterate over the input sections examining their
1993 relocations since the relocations for the output sections
1994 haven't been set yet. mark_symbols_used_in_relocations will
1995 ignore input sections which have no corresponding output
1998 bfd_map_over_sections(ibfd
, mark_symbols_used_in_relocations
, NULL
);
1999 for (ss
= new_supersects
; ss
!= NULL
; ss
= ss
->next
)
2000 ss_mark_symbols_used_in_relocations(ss
);
2001 struct asymbolp_vec osyms
;
2003 filter_symbols(ibfd
, obfd
, &osyms
, &fetch_superbfd(ibfd
)->syms
);
2004 copy_symbols(&osyms
, &fetch_superbfd(ibfd
)->new_syms
);
2006 bfd_set_symtab(obfd
, osyms
.data
, osyms
.size
);
2008 /* This has to happen after the symbol table has been set. */
2009 bfd_map_over_sections(obfd
, write_section
, NULL
);
2011 /* Allow the BFD backend to copy any private data it understands
2012 from the input BFD to the output BFD. This is done last to
2013 permit the routine to look at the filtered symbol table, which is
2014 important for the ECOFF code at least. */
2015 assert(bfd_copy_private_bfd_data(ibfd
, obfd
));
2020 /* Modified function from GNU Binutils objcopy.c */
2021 void setup_section(bfd
*ibfd
, asection
*isection
, void *obfdarg
)
2023 struct superbfd
*isbfd
= fetch_superbfd(ibfd
);
2024 struct supersect
*ss
= fetch_supersect(isbfd
, isection
);
2025 bfd
*obfd
= obfdarg
;
2031 asection
*osection
= bfd_make_section_anyway(obfd
, ss
->name
);
2032 assert(osection
!= NULL
);
2034 osection
->userdata
= ss
;
2035 bfd_set_section_flags(obfd
, osection
, ss
->flags
);
2036 ss
->symbol
= osection
->symbol
;
2037 assert(bfd_set_section_size(obfd
, osection
, ss
->contents
.size
));
2039 vma
= bfd_section_vma(ibfd
, isection
);
2040 assert(bfd_set_section_vma(obfd
, osection
, vma
));
2042 osection
->lma
= isection
->lma
;
2043 assert(bfd_set_section_alignment(obfd
, osection
, ss
->alignment
));
2044 osection
->entsize
= ss
->entsize
;
2045 osection
->output_section
= osection
;
2046 osection
->output_offset
= 0;
2047 isection
->output_section
= osection
;
2048 isection
->output_offset
= 0;
2052 void setup_new_section(bfd
*obfd
, struct supersect
*ss
)
2054 asection
*osection
= bfd_make_section_anyway(obfd
, ss
->name
);
2055 assert(osection
!= NULL
);
2056 bfd_set_section_flags(obfd
, osection
, ss
->flags
);
2058 osection
->userdata
= ss
;
2059 ss
->symbol
= osection
->symbol
;
2060 assert(bfd_set_section_size(obfd
, osection
, ss
->contents
.size
));
2061 assert(bfd_set_section_vma(obfd
, osection
, 0));
2064 assert(bfd_set_section_alignment(obfd
, osection
, ss
->alignment
));
2065 osection
->entsize
= ss
->entsize
;
2066 osection
->output_section
= osection
;
2067 osection
->output_offset
= 0;
2070 static int compare_reloc_addresses(const void *aptr
, const void *bptr
)
2072 const arelent
*const *a
= aptr
, *const *b
= bptr
;
2073 return (*a
)->address
- (*b
)->address
;
2076 static void delete_obsolete_relocs(struct supersect
*ss
)
2078 if (ss
->new_relocs
.size
== 0)
2081 qsort(ss
->relocs
.data
, ss
->relocs
.size
, sizeof(*ss
->relocs
.data
),
2082 compare_reloc_addresses
);
2083 qsort(ss
->new_relocs
.data
, ss
->new_relocs
.size
,
2084 sizeof(*ss
->new_relocs
.data
), compare_reloc_addresses
);
2086 struct arelentp_vec orig_relocs
;
2087 vec_move(&orig_relocs
, &ss
->relocs
);
2089 arelent
**relocp
, **new_relocp
= ss
->new_relocs
.data
;
2090 for (relocp
= orig_relocs
.data
;
2091 relocp
< orig_relocs
.data
+ orig_relocs
.size
; relocp
++) {
2092 while (new_relocp
< ss
->new_relocs
.data
+ ss
->new_relocs
.size
&&
2093 (*new_relocp
)->address
< (*relocp
)->address
)
2095 arelent
*reloc
= *relocp
, *new_reloc
= *new_relocp
;
2096 if (new_relocp
== ss
->new_relocs
.data
+ ss
->new_relocs
.size
||
2097 reloc
->address
!= new_reloc
->address
)
2098 *vec_grow(&ss
->relocs
, 1) = reloc
;
2102 void write_section(bfd
*obfd
, asection
*osection
, void *arg
)
2104 struct supersect
*ss
= osection
->userdata
;
2106 if ((ss
->flags
& SEC_GROUP
) != 0 || ss
->contents
.size
== 0)
2109 delete_obsolete_relocs(ss
);
2112 char *error_message
;
2113 for (relocp
= ss
->new_relocs
.data
;
2114 relocp
< ss
->new_relocs
.data
+ ss
->new_relocs
.size
; relocp
++) {
2116 if (bfd_get_arch(obfd
) == bfd_arch_arm
)
2117 val
= osection
->use_rela_p
? 0 : (*relocp
)->addend
;
2120 bfd_put(bfd_get_reloc_size((*relocp
)->howto
) * 8, obfd
, val
,
2121 ss
->contents
.data
+ (*relocp
)->address
);
2122 if (bfd_install_relocation(obfd
, *relocp
, ss
->contents
.data
,
2123 0, osection
, &error_message
) !=
2125 err(ss
->parent
, "ksplice: error installing reloc: %s",
2130 memcpy(vec_grow(&ss
->relocs
, ss
->new_relocs
.size
), ss
->new_relocs
.data
,
2131 ss
->new_relocs
.size
* sizeof(*ss
->new_relocs
.data
));
2133 bfd_set_reloc(obfd
, osection
,
2134 ss
->relocs
.size
== 0 ? NULL
: ss
->relocs
.data
,
2137 if (ss
->flags
& SEC_HAS_CONTENTS
)
2138 assert(bfd_set_section_contents
2139 (obfd
, osection
, ss
->contents
.data
, 0,
2140 ss
->contents
.size
));
2143 /* Modified function from GNU Binutils objcopy.c
2145 * Mark all the symbols which will be used in output relocations with
2146 * the BSF_KEEP flag so that those symbols will not be stripped.
2148 * Ignore relocations which will not appear in the output file.
2150 void mark_symbols_used_in_relocations(bfd
*abfd
, asection
*isection
,
2153 struct superbfd
*sbfd
= fetch_superbfd(abfd
);
2154 if (isection
->output_section
== NULL
)
2157 struct supersect
*ss
= fetch_supersect(sbfd
, isection
);
2158 ss_mark_symbols_used_in_relocations(ss
);
2161 void ss_mark_symbols_used_in_relocations(struct supersect
*ss
)
2163 /* Examine each symbol used in a relocation. If it's not one of the
2164 special bfd section symbols, then mark it with BSF_KEEP. */
2166 for (relocp
= ss
->relocs
.data
;
2167 relocp
< ss
->relocs
.data
+ ss
->relocs
.size
; relocp
++) {
2168 asymbol
*sym
= *(*relocp
)->sym_ptr_ptr
;
2169 if (!(bfd_is_const_section(sym
->section
) &&
2170 sym
== sym
->section
->symbol
))
2171 sym
->flags
|= BSF_KEEP
;
2173 for (relocp
= ss
->new_relocs
.data
;
2174 relocp
< ss
->new_relocs
.data
+ ss
->new_relocs
.size
; relocp
++) {
2175 asymbol
*sym
= *(*relocp
)->sym_ptr_ptr
;
2176 if (!(bfd_is_const_section(sym
->section
) &&
2177 sym
== sym
->section
->symbol
))
2178 sym
->flags
|= BSF_KEEP
;
2182 static bool deleted_table_section_symbol(bfd
*abfd
, asymbol
*sym
)
2184 struct superbfd
*sbfd
= fetch_superbfd(abfd
);
2185 if (bfd_is_const_section(sym
->section
))
2187 struct supersect
*ss
= fetch_supersect(sbfd
, sym
->section
);
2190 for (symp
= ss
->syms
.data
; symp
< ss
->syms
.data
+ ss
->syms
.size
; symp
++) {
2194 return symp
>= ss
->syms
.data
+ ss
->syms
.size
&&
2195 (sym
->flags
& BSF_SECTION_SYM
) == 0;
2198 void filter_symbols(bfd
*ibfd
, bfd
*obfd
, struct asymbolp_vec
*osyms
,
2199 struct asymbolp_vec
*isyms
)
2202 struct superbfd
*sbfd
= fetch_superbfd(ibfd
);
2203 for (symp
= isyms
->data
; symp
< isyms
->data
+ isyms
->size
; symp
++) {
2204 asymbol
*sym
= *symp
;
2205 struct supersect
*sym_ss
= NULL
;
2206 struct span
*sym_span
= NULL
;
2207 if (!bfd_is_const_section(sym
->section
)) {
2208 sym_ss
= fetch_supersect(sbfd
, sym
->section
);
2209 sym_span
= find_span(sym_ss
, sym
->value
);
2212 if (mode("keep") && (sym
->flags
& BSF_GLOBAL
) != 0 &&
2213 !(mode("keep-primary") && sym_span
!= NULL
&&
2215 sym
->flags
= (sym
->flags
& ~BSF_GLOBAL
) | BSF_LOCAL
;
2217 if (mode("finalize") && (sym
->flags
& BSF_GLOBAL
) != 0)
2218 sym
->flags
= (sym
->flags
& ~BSF_GLOBAL
) | BSF_LOCAL
;
2220 bool keep
= bfd_is_const_section(sym
->section
) ||
2221 (sym_ss
->keep
&& (sym
->flags
& BSF_SECTION_SYM
) != 0) ||
2222 (sym_span
!= NULL
&& sym_span
->keep
);
2223 if (bfd_is_und_section(sym
->section
) &&
2224 (sym
->flags
& BSF_KEEP
) == 0)
2226 if (bfd_is_abs_section(sym
->section
) &&
2227 (sym
->flags
& BSF_KEEP
) == 0 &&
2228 (sym
->flags
& BSF_FILE
) == 0)
2230 if (deleted_table_section_symbol(ibfd
, sym
))
2233 if (mode("keep-helper") && sym_ss
!= NULL
&&
2234 sym_ss
->type
== SS_TYPE_EXPORT
)
2238 if (sym_ss
!= NULL
&& !sym_ss
->keep
) {
2239 err(sbfd
, "Kept symbol %s in unkept section "
2240 "%s\n", sym
->name
, sym
->section
->name
);
2243 *vec_grow(osyms
, 1) = sym
;
2248 void read_str_set(struct str_vec
*strs
)
2252 assert(getline(&buf
, &n
, stdin
) >= 0);
2256 char *str
= strtok_r(buf
, " \n", &saveptr
);
2260 *vec_grow(strs
, 1) = str
;
2264 bool str_in_set(const char *str
, const struct str_vec
*strs
)
2267 for (strp
= strs
->data
; strp
< strs
->data
+ strs
->size
; strp
++) {
2268 if (strcmp(str
, *strp
) == 0)
2274 bool is_table_section(const char *name
, bool consider_other
)
2276 struct supersect
*tables_ss
=
2277 fetch_supersect(offsets_sbfd
,
2278 bfd_get_section_by_name(offsets_sbfd
->abfd
,
2279 ".ksplice_table_sections"));
2280 const struct table_section
*ts
;
2281 for (ts
= tables_ss
->contents
.data
;
2282 (void *)ts
< tables_ss
->contents
.data
+ tables_ss
->contents
.size
;
2284 if (strcmp(name
, read_string(tables_ss
, &ts
->sect
)) == 0)
2286 const char *osect_name
= read_string(tables_ss
,
2288 if (consider_other
&& osect_name
!= NULL
&&
2289 strcmp(name
, osect_name
) == 0)
2291 const char *crc_name
= read_string(tables_ss
, &ts
->crc_sect
);
2292 if (consider_other
&& crc_name
!= NULL
&&
2293 strcmp(name
, crc_name
) == 0)
2299 const struct table_section
*get_table_section(const char *name
)
2301 struct supersect
*tables_ss
=
2302 fetch_supersect(offsets_sbfd
,
2303 bfd_get_section_by_name(offsets_sbfd
->abfd
,
2304 ".ksplice_table_sections"));
2305 const struct table_section
*ts
;
2306 for (ts
= tables_ss
->contents
.data
;
2307 (void *)ts
< tables_ss
->contents
.data
+ tables_ss
->contents
.size
;
2309 if (strcmp(name
, read_string(tables_ss
, &ts
->sect
)) == 0) {
2310 if (ts
->entry_contents_size
!= 0)
2311 assert(align(ts
->entry_contents_size
,
2314 struct table_section
*ns
= malloc(sizeof(*ns
));
2316 ns
->sect
= read_string(tables_ss
, &ts
->sect
);
2317 ns
->crc_sect
= read_string(tables_ss
, &ts
->crc_sect
);
2319 read_string(tables_ss
, &ts
->other_sect
);
2326 enum supersect_type
supersect_type(struct supersect
*ss
)
2328 if (mode("finalize") &&
2329 strcmp(finalize_target
, "vmlinux") == 0 &&
2330 (starts_with(ss
->name
, ".ksplice_relocs.exit") ||
2331 starts_with(ss
->name
, ".ksplice_sections.exit") ||
2332 starts_with(ss
->name
, ".ksplice_patches.exit")))
2333 return SS_TYPE_EXIT
;
2334 if (starts_with(ss
->name
, ".ksplice_call"))
2335 return SS_TYPE_KSPLICE_CALL
;
2336 if (starts_with(ss
->name
, ".ksplice_options"))
2337 return SS_TYPE_SPECIAL
;
2338 if (starts_with(ss
->name
, ".ksplice"))
2339 return SS_TYPE_KSPLICE
;
2341 if (starts_with(ss
->name
, ".init"))
2342 return SS_TYPE_IGNORED
;
2343 if (starts_with(ss
->name
, ".security_initcall.init"))
2344 return SS_TYPE_IGNORED
;
2345 if (starts_with(ss
->name
, ".con_initcall.init"))
2346 return SS_TYPE_IGNORED
;
2347 if (starts_with(ss
->name
, ".x86cpuvendor.init"))
2348 return SS_TYPE_IGNORED
;
2349 if (starts_with(ss
->name
, ".early_param.init"))
2350 return SS_TYPE_IGNORED
;
2351 if (starts_with(ss
->name
, ".taglist.init"))
2352 return SS_TYPE_IGNORED
;
2353 if (starts_with(ss
->name
, ".arch.info.init"))
2354 return SS_TYPE_IGNORED
;
2355 if (starts_with(ss
->name
, ".proc.info.init"))
2356 return SS_TYPE_IGNORED
;
2357 /* .pci_fixup_* sections really should be treated as global rodata
2358 referenced only from quirks.c */
2359 if (starts_with(ss
->name
, ".pci_fixup_"))
2360 return SS_TYPE_IGNORED
;
2361 /* .builtin_fw sections are similar to .pci_fixup */
2362 if (starts_with(ss
->name
, ".builtin_fw"))
2363 return SS_TYPE_IGNORED
;
2364 /* same for .tracedata */
2365 if (starts_with(ss
->name
, ".tracedata"))
2366 return SS_TYPE_IGNORED
;
2367 if (starts_with(ss
->name
, ".debug"))
2368 return SS_TYPE_IGNORED
;
2369 /* .eh_frame should probably be discarded, not ignored */
2370 if (starts_with(ss
->name
, ".eh_frame"))
2371 return SS_TYPE_IGNORED
;
2372 if (config
->ignore_devinit
&& starts_with(ss
->name
, ".devinit"))
2373 return SS_TYPE_IGNORED
;
2374 if (config
->ignore_meminit
&& starts_with(ss
->name
, ".meminit"))
2375 return SS_TYPE_IGNORED
;
2376 if (config
->ignore_cpuinit
&& starts_with(ss
->name
, ".cpuinit"))
2377 return SS_TYPE_IGNORED
;
2378 if (config
->ignore_devinit
&& starts_with(ss
->name
, ".devexit"))
2379 return SS_TYPE_IGNORED
;
2380 if (config
->ignore_meminit
&& starts_with(ss
->name
, ".memexit"))
2381 return SS_TYPE_IGNORED
;
2382 if (config
->ignore_cpuinit
&& starts_with(ss
->name
, ".cpuexit"))
2383 return SS_TYPE_IGNORED
;
2384 if (starts_with(ss
->name
, ".vgetcpu_mode") ||
2385 starts_with(ss
->name
, ".jiffies") ||
2386 starts_with(ss
->name
, ".wall_jiffies") ||
2387 starts_with(ss
->name
, ".vxtime") ||
2388 starts_with(ss
->name
, ".sys_tz") ||
2389 starts_with(ss
->name
, ".sysctl_vsyscall") ||
2390 starts_with(ss
->name
, ".xtime") ||
2391 starts_with(ss
->name
, ".xtime_lock") ||
2392 starts_with(ss
->name
, ".vsyscall"))
2393 return SS_TYPE_IGNORED
;
2394 if (starts_with(ss
->name
, ".vdso"))
2395 return SS_TYPE_IGNORED
;
2397 if (starts_with(ss
->name
, ".exit.text"))
2398 return SS_TYPE_TEXT
;
2399 if (starts_with(ss
->name
, ".exit.data"))
2400 return SS_TYPE_DATA
;
2402 if (starts_with(ss
->name
, ".text") ||
2403 starts_with(ss
->name
, ".kernel.text") ||
2404 starts_with(ss
->name
, ".devinit.text") ||
2405 starts_with(ss
->name
, ".meminit.text") ||
2406 starts_with(ss
->name
, ".cpuinit.text") ||
2407 starts_with(ss
->name
, ".devexit.text") ||
2408 starts_with(ss
->name
, ".memexit.text") ||
2409 starts_with(ss
->name
, ".cpuexit.text") ||
2410 starts_with(ss
->name
, ".ref.text") ||
2411 starts_with(ss
->name
, ".spinlock.text") ||
2412 starts_with(ss
->name
, ".kprobes.text") ||
2413 starts_with(ss
->name
, ".sched.text") ||
2414 (mode("keep-helper") && starts_with(ss
->name
, ".fixup")))
2415 return SS_TYPE_TEXT
;
2418 if (sscanf(ss
->name
, ".rodata.str%*u.%*u%n", &n
) >= 0 &&
2419 n
== strlen(ss
->name
))
2420 return ss
->entsize
== 1 ? SS_TYPE_STRING
: SS_TYPE_RODATA
;
2422 if (starts_with(ss
->name
, ".rodata") ||
2423 starts_with(ss
->name
, ".kernel.rodata") ||
2424 starts_with(ss
->name
, ".devinit.rodata") ||
2425 starts_with(ss
->name
, ".meminit.rodata") ||
2426 starts_with(ss
->name
, ".cpuinit.rodata") ||
2427 starts_with(ss
->name
, ".devexit.rodata") ||
2428 starts_with(ss
->name
, ".memexit.rodata") ||
2429 starts_with(ss
->name
, ".cpuexit.rodata") ||
2430 starts_with(ss
->name
, ".ref.rodata") ||
2431 starts_with(ss
->name
, "__markers_strings") ||
2432 starts_with(ss
->name
, "__bug_table") ||
2433 (mode("keep-helper") && starts_with(ss
->name
, "__ex_table")))
2434 return SS_TYPE_RODATA
;
2436 if (starts_with(ss
->name
, ".bss"))
2437 return SS_TYPE_DATA
;
2439 /* Ignore .data.percpu sections */
2440 if (starts_with(ss
->name
, ".data.percpu") ||
2441 starts_with(ss
->name
, ".kernel.data.percpu"))
2442 return SS_TYPE_IGNORED
;
2443 if (starts_with(ss
->name
, ".data") ||
2444 starts_with(ss
->name
, ".kernel.data") ||
2445 starts_with(ss
->name
, ".devinit.data") ||
2446 starts_with(ss
->name
, ".cpuinit.data") ||
2447 starts_with(ss
->name
, ".meminit.data") ||
2448 starts_with(ss
->name
, ".devexit.data") ||
2449 starts_with(ss
->name
, ".memexit.data") ||
2450 starts_with(ss
->name
, ".cpuexit.data") ||
2451 starts_with(ss
->name
, ".ref.data") ||
2452 starts_with(ss
->name
, "__markers"))
2453 return SS_TYPE_DATA
;
2455 /* We replace all the ksymtab strings, so delete them */
2456 if (strcmp(ss
->name
, "__ksymtab_strings") == 0)
2457 return SS_TYPE_STRING
;
2458 if (starts_with(ss
->name
, "__ksymtab"))
2459 return SS_TYPE_EXPORT
;
2460 if (starts_with(ss
->name
, "__kcrctab"))
2461 return SS_TYPE_SPECIAL
;
2463 if (is_table_section(ss
->name
, true))
2464 return SS_TYPE_SPECIAL
;
2466 if (starts_with(ss
->name
, ".ARM."))
2467 return SS_TYPE_SPECIAL
;
2469 if (starts_with(ss
->name
, ".note"))
2470 return SS_TYPE_IGNORED
;
2471 if (starts_with(ss
->name
, ".comment"))
2472 return SS_TYPE_IGNORED
;
2473 if (starts_with(ss
->name
, "__param"))
2474 return SS_TYPE_IGNORED
;
2475 if (starts_with(ss
->name
, ".exitcall.exit"))
2476 return SS_TYPE_IGNORED
;
2477 if (starts_with(ss
->name
, ".modinfo"))
2478 return SS_TYPE_IGNORED
;
2480 return SS_TYPE_UNKNOWN
;
2483 void initialize_supersect_types(struct superbfd
*sbfd
)
2486 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
2487 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
2488 ss
->type
= supersect_type(ss
);
2489 ss
->orig_type
= ss
->type
;
2490 if (ss
->type
== SS_TYPE_UNKNOWN
) {
2491 err(sbfd
, "Unknown section type: %s\n", ss
->name
);
2497 static void init_label_map(struct superbfd
*sbfd
)
2499 struct label_map
*map
;
2501 vec_init(&sbfd
->maps
);
2505 struct symbol_hash csyms
;
2506 symbol_hash_init(&csyms
);
2509 for (symp
= sbfd
->syms
.data
;
2510 symp
< sbfd
->syms
.data
+ sbfd
->syms
.size
; symp
++) {
2511 asymbol
*csym
= canonical_symbol(sbfd
, *symp
);
2514 char *key
= strprintf("%p", csym
);
2515 asymbol
**csymp
= symbol_hash_lookup(&csyms
, key
, TRUE
);
2521 map
= vec_grow(&sbfd
->maps
, 1);
2524 map
->label
= symbol_label(sbfd
, csym
);
2527 struct label_mapp_hash label_maps
;
2528 label_mapp_hash_init(&label_maps
);
2529 for (map
= sbfd
->maps
.data
;
2530 map
< sbfd
->maps
.data
+ sbfd
->maps
.size
; map
++) {
2531 struct label_map
**mapp
=
2532 label_mapp_hash_lookup(&label_maps
, map
->label
, TRUE
);
2533 if (*mapp
== NULL
) {
2538 struct label_map
*first_map
= *mapp
;
2539 if (first_map
->count
== 0)
2540 first_map
->label
= strprintf("%s~%d", map
->label
, 0);
2541 map
->label
= strprintf("%s~%d", map
->label
, ++first_map
->count
);
2544 label_mapp_hash_init(&sbfd
->maps_hash
);
2545 for (map
= sbfd
->maps
.data
;
2546 map
< sbfd
->maps
.data
+ sbfd
->maps
.size
; map
++) {
2547 char *key
= strprintf("%p", map
->csym
);
2548 struct label_map
**mapp
=
2549 label_mapp_hash_lookup(&sbfd
->maps_hash
, key
, TRUE
);
2552 map
->orig_label
= map
->label
;
2556 static const char *label_lookup(struct superbfd
*sbfd
, asymbol
*sym
)
2558 asymbol
*csym
= canonical_symbol(sbfd
, sym
);
2559 char *key
= strprintf("%p", csym
);
2560 struct label_map
**mapp
=
2561 label_mapp_hash_lookup(&sbfd
->maps_hash
, key
, FALSE
);
2565 return (*mapp
)->label
;
2568 static void print_label_changes(struct superbfd
*sbfd
)
2572 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
2573 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
2574 for (span
= ss
->spans
.data
;
2575 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++) {
2576 if (strcmp(span
->label
, span
->orig_label
) != 0)
2577 debug1(sbfd
, "Label change: %s -> %s\n",
2578 span
->label
, span
->orig_label
);
2583 static void label_map_set(struct superbfd
*sbfd
, const char *oldlabel
,
2586 struct label_map
*map
;
2587 for (map
= sbfd
->maps
.data
;
2588 map
< sbfd
->maps
.data
+ sbfd
->maps
.size
; map
++) {
2589 if (strcmp(map
->orig_label
, oldlabel
) == 0) {
2590 if (strcmp(map
->orig_label
, map
->label
) != 0 &&
2591 strcmp(map
->label
, label
) != 0)
2600 static void change_initial_label(struct span
*span
, const char *label
)
2602 struct superbfd
*sbfd
= span
->ss
->parent
;
2603 span
->label
= label
;
2604 span
->orig_label
= label
;
2606 asymbol
*csym
= canonical_symbol(sbfd
, span
->symbol
);
2607 char *key
= strprintf("%p", csym
);
2608 struct label_map
**mapp
=
2609 label_mapp_hash_lookup(&sbfd
->maps_hash
, key
, FALSE
);
2612 (*mapp
)->label
= span
->label
;
2613 (*mapp
)->orig_label
= span
->orig_label
;
2614 span
->symbol
= NULL
;
2618 static void init_callers(struct superbfd
*sbfd
)
2620 string_hash_init(&sbfd
->callers
);
2622 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
2623 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
2625 for (relocp
= ss
->relocs
.data
;
2626 relocp
< ss
->relocs
.data
+ ss
->relocs
.size
; relocp
++) {
2627 asymbol
*sym
= *(*relocp
)->sym_ptr_ptr
;
2629 sym
->value
+ get_reloc_offset(ss
, *relocp
, true);
2630 char *key
= strprintf("%s+%lx", sym
->section
->name
,
2632 const char **ret
= string_hash_lookup(&sbfd
->callers
,
2635 asymbol
*csym
= canonical_symbol(sbfd
, sect
->symbol
);
2637 *ret
= "*multiple_callers*";
2638 else if (static_local_symbol(sbfd
, csym
))
2639 *ret
= static_local_symbol(sbfd
, csym
);
2646 static const char *find_caller(struct supersect
*ss
, asymbol
*sym
)
2648 char *key
= strprintf("%s+%lx", sym
->section
->name
,
2649 (unsigned long)sym
->value
);
2650 const char **ret
= string_hash_lookup(&ss
->parent
->callers
, key
, FALSE
);
2654 return "*no_caller*";
2658 static void init_csyms(struct superbfd
*sbfd
)
2660 asymbolpp_hash_init(&sbfd
->csyms
);
2663 for (symp
= sbfd
->syms
.data
; symp
< sbfd
->syms
.data
+ sbfd
->syms
.size
;
2665 asymbol
*sym
= *symp
;
2666 if ((sym
->flags
& BSF_DEBUGGING
) != 0)
2668 char *key
= strprintf("%s+%lx", sym
->section
->name
,
2669 (unsigned long)sym
->value
);
2670 asymbol
***csympp
= asymbolpp_hash_lookup(&sbfd
->csyms
, key
,
2673 if (*csympp
== NULL
) {
2677 asymbol
*csym
= **csympp
;
2678 if ((csym
->flags
& BSF_GLOBAL
) != 0)
2680 if ((sym
->flags
& BSF_GLOBAL
) != 0)
2685 static asymbol
**symbolp_scan(struct supersect
*ss
, bfd_vma value
)
2687 char *key
= strprintf("%s+%lx", ss
->name
, (unsigned long)value
);
2689 asymbolpp_hash_lookup(&ss
->parent
->csyms
, key
, FALSE
);
2694 /* For section symbols of sections containing no symbols, return the
2695 section symbol that relocations are generated against */
2701 static asymbol
**canonical_symbolp(struct superbfd
*sbfd
, asymbol
*sym
)
2703 if (bfd_is_const_section(sym
->section
)) {
2705 for (csymp
= sbfd
->syms
.data
;
2706 csymp
< sbfd
->syms
.data
+ sbfd
->syms
.size
; csymp
++) {
2712 return symbolp_scan(fetch_supersect(sbfd
, sym
->section
), sym
->value
);
2715 static asymbol
*canonical_symbol(struct superbfd
*sbfd
, asymbol
*sym
)
2717 if (bfd_is_const_section(sym
->section
))
2719 asymbol
**symp
= canonical_symbolp(sbfd
, sym
);
2720 return symp
!= NULL
? *symp
: NULL
;
2723 static char *static_local_symbol(struct superbfd
*sbfd
, asymbol
*sym
)
2725 struct supersect
*ss
= fetch_supersect(sbfd
, sym
->section
);
2726 if ((sym
->flags
& BSF_LOCAL
) == 0 || (sym
->flags
& BSF_OBJECT
) == 0)
2728 char *dot
= strrchr(sym
->name
, '.');
2729 if (dot
== NULL
|| dot
[1 + strspn(dot
+ 1, "0123546789")] != '\0')
2731 char *basename
= strndup(sym
->name
, dot
- sym
->name
);
2733 /* Handle C.123.12345 symbols */
2734 dot
= strrchr(basename
, '.');
2735 if (dot
!= NULL
&& dot
[1 + strspn(dot
+ 1, "0123546789")] == '\0')
2736 basename
= strndup(basename
, dot
- basename
);
2738 if (strcmp(basename
, "__func__") == 0 ||
2739 strcmp(basename
, "__PRETTY_FUNCTION__") == 0)
2740 caller
= (const char *)ss
->contents
.data
+ sym
->value
;
2742 caller
= find_caller(ss
, sym
);
2743 return strprintf("%s<%s>", basename
, caller
);
2746 static char *symbol_label(struct superbfd
*sbfd
, asymbol
*sym
)
2748 const char *filename
= sbfd
->abfd
->filename
;
2749 char *c
= strstr(filename
, ".KSPLICE");
2750 int flen
= (c
== NULL
? strlen(filename
) : c
- filename
);
2753 if (bfd_is_und_section(sym
->section
) || (sym
->flags
& BSF_GLOBAL
) != 0) {
2754 label
= strdup(sym
->name
);
2755 } else if (bfd_is_const_section(sym
->section
)) {
2756 label
= strprintf("%s<%.*s>", sym
->name
, flen
, filename
);
2758 asymbol
*gsym
= canonical_symbol(sbfd
, sym
);
2761 label
= strprintf("%s+%lx<%.*s>",
2763 (unsigned long)sym
->value
,
2765 else if ((gsym
->flags
& BSF_GLOBAL
) != 0)
2766 label
= strdup(gsym
->name
);
2767 else if (static_local_symbol(sbfd
, gsym
))
2768 label
= strprintf("%s+%lx<%.*s>",
2769 static_local_symbol(sbfd
, gsym
),
2770 (unsigned long)sym
->value
,
2773 label
= strprintf("%s<%.*s>",
2774 gsym
->name
, flen
, filename
);
2780 static void keep_span(struct span
*span
)
2783 span
->ss
->keep
= true;
2786 static struct span
*new_span(struct supersect
*ss
, bfd_vma start
, bfd_vma size
)
2788 struct span
*span
= vec_grow(&ss
->spans
, 1);
2790 span
->contents_size
= size
;
2791 span
->start
= start
;
2795 span
->patch
= false;
2796 span
->bugpatch
= false;
2797 span
->datapatch
= false;
2798 span
->precallable
= starts_with(ss
->name
, ".ksplice_call_pre_apply") ||
2799 starts_with(ss
->name
, ".ksplice_call_check_apply") ||
2800 starts_with(ss
->name
, ".ksplice_call_fail_apply") ||
2801 starts_with(ss
->name
, ".ksplice_call_post_remove");
2804 asymbol
**symp
= symbolp_scan(ss
, span
->start
);
2806 span
->symbol
= *symp
;
2807 span
->label
= label_lookup(ss
->parent
, span
->symbol
);
2809 span
->symbol
= NULL
;
2810 const char *label
= label_lookup(ss
->parent
, ss
->symbol
);
2811 if (span
->start
!= 0)
2812 span
->label
= strprintf("%s<span:%lx>", label
,
2813 (unsigned long)span
->start
);
2815 span
->label
= label
;
2817 span
->orig_label
= span
->label
;
2821 static void initialize_string_spans(struct supersect
*ss
)
2824 for (str
= ss
->contents
.data
;
2825 (void *)str
< ss
->contents
.data
+ ss
->contents
.size
;) {
2826 bfd_vma start
= (unsigned long)str
-
2827 (unsigned long)ss
->contents
.data
;
2828 bfd_vma size
= strlen(str
) + 1;
2829 bfd_vma contents_size
= size
;
2830 while ((start
+ size
) % (1 << ss
->alignment
) != 0 &&
2831 start
+ size
< ss
->contents
.size
) {
2832 /* Some string sections, like __ksymtab_strings, only
2833 align some strings with the declared alignment */
2834 if (str
[size
] != '\0')
2838 struct span
*span
= new_span(ss
, start
, size
);
2839 span
->contents_size
= contents_size
;
2844 static int compare_ulongs(const void *va
, const void *vb
)
2846 const unsigned long *a
= va
, *b
= vb
;
2850 static void initialize_table_spans(struct superbfd
*sbfd
,
2851 struct table_section
*s
)
2853 asection
*isection
= bfd_get_section_by_name(sbfd
->abfd
, s
->sect
);
2854 if (isection
== NULL
)
2856 struct supersect
*ss
= fetch_supersect(sbfd
, isection
);
2857 if (ss
->alignment
< ffs(s
->entry_align
) - 1)
2858 ss
->alignment
= ffs(s
->entry_align
) - 1;
2860 asection
*other_sect
= NULL
;
2861 if (s
->other_sect
!= NULL
)
2862 other_sect
= bfd_get_section_by_name(sbfd
->abfd
, s
->other_sect
);
2863 struct supersect
*other_ss
= NULL
;
2864 if (other_sect
!= NULL
)
2865 other_ss
= fetch_supersect(sbfd
, other_sect
);
2867 asection
*crc_sect
= NULL
;
2868 if (s
->crc_sect
!= NULL
)
2869 crc_sect
= bfd_get_section_by_name(sbfd
->abfd
, s
->crc_sect
);
2870 struct supersect
*crc_ss
= NULL
;
2871 if (crc_sect
!= NULL
)
2872 crc_ss
= fetch_supersect(sbfd
, crc_sect
);
2874 struct ulong_vec offsets
;
2878 for (entry
= ss
->contents
.data
;
2879 entry
< ss
->contents
.data
+ ss
->contents
.size
;
2880 entry
+= s
->entry_size
) {
2881 struct span
*span
= new_span(ss
, addr_offset(ss
, entry
),
2883 if (s
->entry_contents_size
!= 0)
2884 span
->contents_size
= s
->entry_contents_size
;
2885 if ((span
->symbol
== NULL
||
2886 (span
->symbol
->flags
& BSF_SECTION_SYM
) != 0) &&
2888 arelent
*reloc
= find_reloc(ss
, entry
+ s
->addr_offset
);
2890 struct span
*target_span
= reloc_target_span(ss
, reloc
);
2891 assert(target_span
);
2892 asymbol
*sym
= *reloc
->sym_ptr_ptr
;
2893 unsigned long val
= get_reloc_offset(ss
, reloc
, true) +
2894 sym
->value
- (target_span
->start
+
2895 target_span
->shift
);
2896 char *label
= strprintf("%s<target:%s+%lx>", ss
->name
,
2897 target_span
->label
, val
);
2898 change_initial_label(span
, label
);
2901 if (other_sect
!= NULL
) {
2903 bfd_vma offset
= read_reloc(ss
, entry
+ s
->other_offset
,
2904 sizeof(void *), &sym
);
2905 if (sym
->section
== other_sect
) {
2906 assert(offset
>= 0 &&
2907 offset
< other_ss
->contents
.size
);
2908 *vec_grow(&offsets
, 1) = offset
;
2912 if (crc_sect
!= NULL
)
2913 new_span(crc_ss
, addr_offset(ss
, entry
) / s
->entry_size
2914 * s
->crc_size
, s
->crc_size
);
2916 if (ss
->type
== SS_TYPE_EXPORT
) {
2917 const char *symname
= read_string(ss
, entry
+
2919 char *label
= strprintf("%s:%s", ss
->name
, symname
);
2920 change_initial_label(span
, label
);
2924 if (other_sect
== NULL
)
2927 *vec_grow(&offsets
, 1) = 0;
2928 qsort(offsets
.data
, offsets
.size
, sizeof(*offsets
.data
),
2930 *vec_grow(&offsets
, 1) = other_ss
->contents
.size
;
2933 for (off
= offsets
.data
; off
< offsets
.data
+ offsets
.size
- 1; off
++) {
2934 if (*off
!= *(off
+ 1))
2935 new_span(other_ss
, *off
, *(off
+ 1) - *off
);
2939 static void initialize_table_section_spans(struct superbfd
*sbfd
)
2941 struct supersect
*tables_ss
=
2942 fetch_supersect(offsets_sbfd
,
2943 bfd_get_section_by_name(offsets_sbfd
->abfd
,
2944 ".ksplice_table_sections"));
2945 const struct table_section
*ts
;
2946 struct table_section s
;
2947 for (ts
= tables_ss
->contents
.data
;
2948 (void *)ts
< tables_ss
->contents
.data
+ tables_ss
->contents
.size
;
2951 s
.sect
= read_string(tables_ss
, &ts
->sect
);
2952 s
.other_sect
= read_string(tables_ss
, &ts
->other_sect
);
2953 s
.crc_sect
= read_string(tables_ss
, &ts
->crc_sect
);
2954 initialize_table_spans(sbfd
, &s
);
2958 static void initialize_ksplice_call_spans(struct supersect
*ss
)
2961 for (relocp
= ss
->relocs
.data
;
2962 relocp
< ss
->relocs
.data
+ ss
->relocs
.size
; relocp
++) {
2963 arelent
*reloc
= *relocp
;
2964 new_span(ss
, reloc
->address
, bfd_get_reloc_size(reloc
->howto
));
2965 /* the span labels should already be unique */
2969 static void initialize_spans(struct superbfd
*sbfd
)
2972 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
2973 if (is_table_section(sect
->name
, true) && mode("keep"))
2976 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
2977 if (ss
->type
== SS_TYPE_STRING
)
2978 initialize_string_spans(ss
);
2979 else if (ss
->type
== SS_TYPE_KSPLICE_CALL
)
2980 initialize_ksplice_call_spans(ss
);
2982 new_span(ss
, 0, ss
->contents
.size
);
2985 initialize_table_section_spans(sbfd
);
2988 struct span
*reloc_target_span(struct supersect
*ss
, arelent
*reloc
)
2990 asymbol
*sym_ptr
= *reloc
->sym_ptr_ptr
;
2991 if (bfd_is_const_section(sym_ptr
->section
))
2994 bfd_vma addend
= get_reloc_offset(ss
, reloc
, true) + sym_ptr
->value
;
2995 struct supersect
*sym_ss
=
2996 fetch_supersect(ss
->parent
, sym_ptr
->section
);
2997 struct span
*span
, *target_span
= sym_ss
->spans
.data
;
2998 for (span
= sym_ss
->spans
.data
;
2999 span
< sym_ss
->spans
.data
+ sym_ss
->spans
.size
; span
++) {
3000 if (addend
>= span
->start
&& addend
< span
->start
+ span
->size
)
3006 struct span
*find_span(struct supersect
*ss
, bfd_size_type address
)
3009 for (span
= ss
->spans
.data
; span
< ss
->spans
.data
+ ss
->spans
.size
;
3011 if (address
>= span
->start
&&
3012 address
< span
->start
+ span
->size
)
3015 /* Deal with empty BSS sections */
3016 if (ss
->contents
.size
== 0 && ss
->spans
.size
> 0)
3017 return ss
->spans
.data
;
3021 void compute_span_shifts(struct superbfd
*sbfd
)
3025 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
3026 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
3029 bfd_size_type offset
= 0;
3030 for (span
= ss
->spans
.data
;
3031 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++) {
3034 span
->shift
= offset
- span
->start
;
3035 offset
+= span
->size
;
3040 void remove_unkept_spans(struct superbfd
*sbfd
)
3044 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
3045 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
3046 delete_obsolete_relocs(ss
);
3047 struct arelentp_vec orig_relocs
;
3048 vec_move(&orig_relocs
, &ss
->relocs
);
3049 arelent
**relocp
, *reloc
;
3050 for (relocp
= orig_relocs
.data
;
3051 relocp
< orig_relocs
.data
+ orig_relocs
.size
; relocp
++) {
3053 asymbol
*sym
= *reloc
->sym_ptr_ptr
;
3054 span
= reloc_target_span(ss
, reloc
);
3055 if ((span
!= NULL
&& span
->keep
&& span
->shift
== 0) ||
3056 bfd_is_const_section(sym
->section
)) {
3057 *vec_grow(&ss
->relocs
, 1) = reloc
;
3060 struct supersect
*sym_ss
=
3061 fetch_supersect(sbfd
, sym
->section
);
3062 if (span
!= NULL
&& (sym
->flags
& BSF_SECTION_SYM
) == 0
3063 && find_span(sym_ss
, sym
->value
) != span
) {
3064 err(sbfd
, "Spans for symbol %s and relocation "
3065 "target do not match in sect %s\n",
3066 sym
->name
, sym_ss
->name
);
3069 if (span
!= NULL
&& span
->keep
) {
3070 arelent
*new_reloc
= malloc(sizeof(*new_reloc
));
3071 *new_reloc
= *reloc
;
3073 get_reloc_offset(ss
, reloc
, false);
3074 new_reloc
->addend
+= span
->shift
;
3075 *vec_grow(&ss
->new_relocs
, 1) = new_reloc
;
3080 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
3081 struct supersect
*ss
= fetch_supersect(sbfd
, sect
), orig_ss
;
3084 supersect_move(&orig_ss
, ss
);
3085 vec_init(&ss
->spans
);
3086 for (span
= orig_ss
.spans
.data
;
3087 span
< orig_ss
.spans
.data
+ orig_ss
.spans
.size
; span
++) {
3090 struct span
*new_span
= vec_grow(&ss
->spans
, 1);
3092 new_span
->start
= span
->start
+ span
->shift
;
3093 new_span
->shift
= 0;
3094 sect_copy(ss
, sect_do_grow(ss
, 1, span
->size
, 1),
3095 &orig_ss
, orig_ss
.contents
.data
+ span
->start
,
3101 static void init_objmanip_superbfd(struct superbfd
*sbfd
)
3103 init_label_map(sbfd
);
3104 initialize_supersect_types(sbfd
);
3105 initialize_spans(sbfd
);
3109 void mangle_section_name(struct superbfd
*sbfd
, const char *name
)
3111 asection
*sect
= bfd_get_section_by_name(sbfd
->abfd
, name
);
3114 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
3115 ss
->name
= strprintf(".ksplice_pre.%s", ss
->name
);
3118 static void write_bugline_patches(struct superbfd
*sbfd
)
3120 const struct table_section
*ts
= get_table_section("__bug_table");
3121 asection
*sect
= bfd_get_section_by_name(sbfd
->abfd
, "__bug_table");
3124 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
3128 for (entry
= ss
->contents
.data
;
3129 entry
< ss
->contents
.data
+ ss
->contents
.size
;
3130 entry
+= ts
->entry_size
) {
3131 struct span
*span
= find_span(ss
, addr_offset(ss
, entry
));
3132 assert(span
!= NULL
);
3133 if (!span
->bugpatch
)
3135 arelent
*reloc
= find_reloc(ss
, entry
+ ts
->addr_offset
);
3136 assert(reloc
!= NULL
);
3137 asymbol
*sym
= *reloc
->sym_ptr_ptr
;
3138 assert(!bfd_is_const_section(sym
->section
));
3140 struct supersect
*kpatch_ss
=
3141 make_section(sbfd
, ".ksplice_patches%s",
3142 sym
->section
->name
);
3143 struct ksplice_patch
*kpatch
=
3144 sect_grow(kpatch_ss
, 1, struct ksplice_patch
);
3145 write_ksplice_patch_reloc
3146 (kpatch_ss
, sym
->section
->name
, &kpatch
->oldaddr
,
3147 sizeof(kpatch
->oldaddr
), span
->label
, ts
->other_offset
);
3149 unsigned short *line
=
3150 write_patch_storage(kpatch_ss
, kpatch
, sizeof(*line
), NULL
);
3151 *line
= *(unsigned short *)(entry
+ ts
->other_offset
);
3152 kpatch
->type
= KSPLICE_PATCH_BUGLINE
;
3156 void *write_patch_storage(struct supersect
*ss
, struct ksplice_patch
*kpatch
,
3157 size_t size
, struct supersect
**data_ssp
)
3159 struct supersect
*data_ss
= make_section(ss
->parent
,
3160 ".ksplice_patch_data");
3161 char *saved
= sect_do_grow(data_ss
, 1, size
, 1);
3162 write_reloc(ss
, &kpatch
->saved
, &data_ss
->symbol
,
3163 addr_offset(data_ss
, saved
));
3164 char *data
= sect_do_grow(data_ss
, 1, size
, 1);
3165 write_reloc(ss
, &kpatch
->contents
, &data_ss
->symbol
,
3166 addr_offset(data_ss
, data
));
3167 kpatch
->size
= size
;
3168 if (data_ssp
!= NULL
)
3169 *data_ssp
= data_ss
;