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 void foreach_span_pair(struct superbfd
*oldsbfd
,
188 struct superbfd
*newsbfd
,
189 void (*fn
)(struct span
*old_span
,
190 struct span
*new_span
));
191 static void match_spans_by_label(struct span
*old_span
, struct span
*new_span
);
192 static void match_string_spans(struct span
*old_span
, struct span
*new_span
);
193 static void mark_new_spans(struct superbfd
*sbfd
);
194 static void handle_deleted_spans(struct superbfd
*oldsbfd
,
195 struct superbfd
*newsbfd
);
196 static void compare_matched_spans(struct superbfd
*newsbfd
);
197 static void compare_spans(struct span
*old_span
, struct span
*new_span
);
198 static void update_nonzero_offsets(struct superbfd
*sbfd
);
199 static void handle_nonzero_offset_relocs(struct supersect
*ss
);
200 static void keep_span(struct span
*span
);
202 static void init_objmanip_superbfd(struct superbfd
*sbfd
);
203 static const char *label_lookup(struct superbfd
*sbfd
, asymbol
*sym
);
204 static void label_map_set(struct superbfd
*sbfd
, const char *oldlabel
,
206 static void print_label_changes(struct superbfd
*sbfd
);
207 static void init_label_map(struct superbfd
*sbfd
);
208 static void change_initial_label(struct span
*span
, const char *label
);
209 static asymbol
**symbolp_scan(struct supersect
*ss
, bfd_vma value
);
210 static void init_csyms(struct superbfd
*sbfd
);
211 static void init_callers(struct superbfd
*sbfd
);
212 static asymbol
*canonical_symbol(struct superbfd
*sbfd
, asymbol
*sym
);
213 static asymbol
**canonical_symbolp(struct superbfd
*sbfd
, asymbol
*sym
);
214 static char *static_local_symbol(struct superbfd
*sbfd
, asymbol
*sym
);
215 static char *symbol_label(struct superbfd
*sbfd
, asymbol
*sym
);
218 #define debug_(sbfd, level, fmt, ...) \
220 if (verbose >= (level)) \
221 printf("%s: " fmt, (sbfd)->abfd->filename, \
224 #define debug0(sbfd, fmt, ...) debug_(sbfd, 0, fmt, ## __VA_ARGS__)
225 #define debug1(sbfd, fmt, ...) debug_(sbfd, 1, fmt, ## __VA_ARGS__)
226 #define err(sbfd, fmt, ...) \
228 fprintf(stderr, "%s: " fmt, (sbfd)->abfd->filename, \
232 struct str_vec delsects
, rmsyms
;
235 struct ksplice_config
*config
;
237 const char *modestr
, *kid
, *finalize_target
= NULL
;
238 bool write_output
= true;
240 struct superbfd
*offsets_sbfd
= NULL
;
242 #define mode(str) starts_with(modestr, str)
244 DECLARE_VEC_TYPE(unsigned long, addr_vec
);
245 DEFINE_HASH_TYPE(struct addr_vec
, addr_vec_hash
,
246 addr_vec_hash_init
, addr_vec_hash_free
, addr_vec_hash_lookup
,
248 struct addr_vec_hash system_map
;
250 struct bool_hash system_map_written
;
251 struct ulong_hash ksplice_symbol_offset
;
252 struct ulong_hash ksplice_howto_offset
;
253 struct ulong_hash ksplice_string_offset
;
255 void load_system_map()
257 const char *config_dir
= getenv("KSPLICE_CONFIG_DIR");
259 FILE *fp
= fopen(strprintf("%s/System.map", config_dir
), "r");
261 addr_vec_hash_init(&system_map
);
265 while (fscanf(fp
, "%lx %c %as\n", &addr
, &type
, &sym
) == 3)
266 *vec_grow(addr_vec_hash_lookup(&system_map
, sym
, TRUE
),
271 void load_ksplice_symbol_offsets(struct superbfd
*sbfd
)
273 asection
*sect
= bfd_get_section_by_name(sbfd
->abfd
,
277 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
279 struct ksplice_symbol
*ksym
;
280 for (ksym
= ss
->contents
.data
;
281 (void *)ksym
< ss
->contents
.data
+ ss
->contents
.size
; ksym
++) {
282 const char *label
= read_string(ss
, &ksym
->label
);
283 unsigned long *ksymbol_offp
=
284 ulong_hash_lookup(&ksplice_symbol_offset
, label
, TRUE
);
285 *ksymbol_offp
= addr_offset(ss
, ksym
);
291 char *kmodsrc
= getenv("KSPLICE_KMODSRC");
292 assert(kmodsrc
!= NULL
);
293 bfd
*offsets_bfd
= bfd_openr(strprintf("%s/offsets.o", kmodsrc
), NULL
);
294 assert(offsets_bfd
!= NULL
);
296 assert(bfd_check_format_matches(offsets_bfd
, bfd_object
, &matching
));
297 offsets_sbfd
= fetch_superbfd(offsets_bfd
);
299 asection
*config_sect
= bfd_get_section_by_name(offsets_sbfd
->abfd
,
301 struct supersect
*config_ss
=
302 fetch_supersect(offsets_sbfd
, config_sect
);
304 config
= config_ss
->contents
.data
;
307 void load_options(struct superbfd
*sbfd
)
309 asection
*sect
= bfd_get_section_by_name(sbfd
->abfd
,
313 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
314 const struct ksplice_option
*opt
;
315 for (opt
= ss
->contents
.data
;
316 (void *)opt
< ss
->contents
.data
+ ss
->contents
.size
; opt
++) {
317 if (opt
->type
== KSPLICE_OPTION_ASSUME_RODATA
) {
318 arelent
*reloc
= find_reloc(ss
, &opt
->target
);
319 struct span
*span
= reloc_target_span(ss
, reloc
);
320 assert(span
!= NULL
);
321 assert(span
->ss
->type
== SS_TYPE_DATA
);
322 assert(span
->start
== 0 &&
323 span
->size
== span
->ss
->contents
.size
);
324 span
->ss
->type
= SS_TYPE_RODATA
;
327 err(sbfd
, "Unrecognized Ksplice option %d\n",
334 bool matchable_data_section(struct supersect
*ss
)
336 if (ss
->type
== SS_TYPE_STRING
)
338 if (ss
->type
== SS_TYPE_RODATA
)
340 if (ss
->type
== SS_TYPE_DATA
&& ss
->relocs
.size
!= 0)
342 if (ss
->type
== SS_TYPE_EXPORT
)
347 bool unchangeable_section(struct supersect
*ss
)
349 if (ss
->type
== SS_TYPE_DATA
)
351 if (ss
->type
== SS_TYPE_IGNORED
&& !starts_with(ss
->name
, ".debug") &&
352 strcmp(ss
->name
, "__ksymtab_strings") != 0)
357 int main(int argc
, char *argv
[])
359 if (getenv("KSPLICE_VERBOSE") != NULL
)
360 verbose
= atoi(getenv("KSPLICE_VERBOSE"));
363 bfd
*ibfd
= bfd_openr(argv
[1], NULL
);
367 assert(bfd_check_format_matches(ibfd
, bfd_object
, &matching
));
369 const char *output_target
= bfd_get_target(ibfd
);
374 bool_hash_init(&system_map_written
);
375 ulong_hash_init(&ksplice_symbol_offset
);
376 ulong_hash_init(&ksplice_howto_offset
);
377 ulong_hash_init(&ksplice_string_offset
);
379 struct superbfd
*isbfd
= fetch_superbfd(ibfd
);
382 if (mode("finalize"))
383 finalize_target
= argv
[4];
384 init_objmanip_superbfd(isbfd
);
385 if (mode("keep-primary")) {
387 do_keep_primary(isbfd
, argv
[4]);
388 } else if (mode("keep-helper")) {
389 do_keep_helper(isbfd
);
390 } else if (mode("finalize")) {
392 } else if (mode("rmsyms")) {
397 bfd
*obfd
= bfd_openw(argv
[2], output_target
);
399 copy_object(ibfd
, obfd
);
400 assert(bfd_close(obfd
));
403 if (offsets_sbfd
!= NULL
)
404 assert(bfd_close(offsets_sbfd
->abfd
));
405 assert(bfd_close(ibfd
));
409 void do_keep_primary(struct superbfd
*isbfd
, const char *pre
)
411 struct bfd
*prebfd
= bfd_openr(pre
, NULL
);
412 assert(prebfd
!= NULL
);
414 assert(bfd_check_format_matches(prebfd
, bfd_object
, &matching
));
416 struct superbfd
*presbfd
= fetch_superbfd(prebfd
);
417 init_objmanip_superbfd(presbfd
);
419 foreach_symbol_pair(presbfd
, isbfd
, match_global_symbols
);
420 debug1(isbfd
, "Matched global\n");
421 foreach_span_pair(presbfd
, isbfd
, match_string_spans
);
422 debug1(isbfd
, "Matched string spans\n");
423 foreach_symbol_pair(presbfd
, isbfd
, match_symbol_spans
);
424 debug1(isbfd
, "Matched by name\n");
425 foreach_span_pair(presbfd
, isbfd
, match_spans_by_label
);
426 debug1(isbfd
, "Matched by label\n");
430 compare_matched_spans(isbfd
);
431 update_nonzero_offsets(isbfd
);
432 mark_new_spans(isbfd
);
436 foreach_symbol_pair(presbfd
, isbfd
, check_global_symbols
);
438 handle_deleted_spans(presbfd
, isbfd
);
439 handle_section_symbol_renames(presbfd
, isbfd
);
441 assert(bfd_close(prebfd
));
445 mark_precallable_spans(isbfd
);
449 for (sect
= isbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
450 struct supersect
*ss
= fetch_supersect(isbfd
, sect
);
453 for (span
= ss
->spans
.data
;
454 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++) {
455 if (starts_with(ss
->name
, ".ksplice_options"))
457 else if (span
->new || span
->patch
|| span
->datapatch
)
461 if (span
->patch
&& span
->precallable
) {
462 err(isbfd
, "Patched span %s can be reached "
463 "by a precall function\n", span
->label
);
469 print_label_changes(isbfd
);
471 for (sect
= isbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
472 struct supersect
*ss
= fetch_supersect(isbfd
, sect
);
474 for (span
= ss
->spans
.data
;
475 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++) {
476 if (span
->patch
|| span
->bugpatch
|| span
->datapatch
)
477 debug0(isbfd
, "Patching span %s\n",
482 for (sect
= isbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
483 struct supersect
*ss
= fetch_supersect(isbfd
, sect
);
485 for (span
= ss
->spans
.data
;
486 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++) {
488 debug0(isbfd
, "New span %s\n", span
->label
);
492 write_output
= false;
493 const char **sectname
;
494 for (sectname
= delsects
.data
;
495 sectname
< delsects
.data
+ delsects
.size
; sectname
++) {
497 debug0(isbfd
, "Deleted section: %s\n", *sectname
);
500 filter_table_sections(isbfd
);
502 compute_span_shifts(isbfd
);
504 for (sect
= isbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
505 struct supersect
*ss
= fetch_supersect(isbfd
, sect
);
506 if (ss
->type
== SS_TYPE_KSPLICE_CALL
)
509 for (span
= ss
->spans
.data
;
510 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++) {
513 if (span
->patch
|| span
->new || span
->datapatch
)
514 write_ksplice_section(span
);
515 if (span
->patch
|| span
->datapatch
)
516 write_ksplice_patch(isbfd
, span
);
517 if (ss
->type
== SS_TYPE_EXPORT
&& span
->new)
518 write_ksplice_export(isbfd
, span
, false);
522 write_bugline_patches(isbfd
);
524 remove_unkept_spans(isbfd
);
527 void do_keep_helper(struct superbfd
*isbfd
)
530 for (sect
= isbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
531 struct supersect
*ss
= fetch_supersect(isbfd
, sect
);
534 for (span
= ss
->spans
.data
;
535 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++) {
537 if (ss
->type
== SS_TYPE_TEXT
&&
538 !starts_with(ss
->name
, ".fixup"))
540 if (ss
->type
== SS_TYPE_EXPORT
)
546 for (symp
= isbfd
->syms
.data
;
547 symp
< isbfd
->syms
.data
+ isbfd
->syms
.size
; symp
++) {
548 asymbol
*sym
= *symp
;
549 if (!bfd_is_const_section(sym
->section
) &&
550 (sym
->flags
& BSF_GLOBAL
) != 0) {
551 struct supersect
*sym_ss
=
552 fetch_supersect(isbfd
, sym
->section
);
553 if (sym
->value
== sym_ss
->contents
.size
)
555 struct span
*span
= find_span(sym_ss
, sym
->value
);
556 assert(span
!= NULL
);
557 if (sym_ss
->type
!= SS_TYPE_IGNORED
)
564 keep_referenced_sections(isbfd
);
567 filter_table_sections(isbfd
);
568 compute_span_shifts(isbfd
);
570 for (sect
= isbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
571 struct supersect
*ss
= fetch_supersect(isbfd
, sect
);
572 asymbol
*sym
= canonical_symbol(isbfd
, sect
->symbol
);
575 if ((sym
->flags
& BSF_WEAK
) != 0)
577 if (bfd_get_section_size(sect
) == 0)
581 if (ss
->type
!= SS_TYPE_TEXT
&& !matchable_data_section(ss
))
585 for (span
= ss
->spans
.data
;
586 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++) {
588 write_ksplice_section(span
);
592 write_table_relocs(isbfd
, "__bug_table", KSPLICE_HOWTO_BUG
);
593 write_table_relocs(isbfd
, "__ex_table", KSPLICE_HOWTO_EXTABLE
);
595 remove_unkept_spans(isbfd
);
597 mangle_section_name(isbfd
, "__markers");
598 mangle_section_name(isbfd
, "__ex_table");
599 for (sect
= isbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
600 struct supersect
*ss
= fetch_supersect(isbfd
, sect
);
601 if (ss
->type
== SS_TYPE_EXPORT
)
602 mangle_section_name(isbfd
, ss
->name
);
606 void do_finalize(struct superbfd
*isbfd
)
608 load_ksplice_symbol_offsets(isbfd
);
610 for (sect
= isbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
611 struct supersect
*ss
= fetch_supersect(isbfd
, sect
);
612 if (ss
->type
== SS_TYPE_EXIT
) {
614 for (span
= ss
->spans
.data
;
615 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++)
620 write_date_relocs(isbfd
, "<{DATE...}>", KSPLICE_HOWTO_DATE
);
621 write_date_relocs(isbfd
, "<{TIME}>", KSPLICE_HOWTO_TIME
);
625 void do_rmsyms(struct superbfd
*isbfd
)
627 read_str_set(&rmsyms
);
631 void match_spans(struct span
*old_span
, struct span
*new_span
)
633 struct superbfd
*sbfd
= new_span
->ss
->parent
;
634 if (old_span
->match
== new_span
&& new_span
->match
== old_span
)
636 if (old_span
->match
!= NULL
) {
637 err(sbfd
, "Matching conflict: old %s: %s != %s\n",
638 old_span
->label
, old_span
->match
->label
, new_span
->label
);
641 if (new_span
->match
!= NULL
) {
642 err(sbfd
, "Matching conflict: new %s: %s != %s\n",
643 new_span
->label
, new_span
->match
->label
, old_span
->label
);
646 old_span
->match
= new_span
;
647 new_span
->match
= old_span
;
648 debug1(sbfd
, "Matched old %s to new %s\n", old_span
->label
,
650 if (old_span
->ss
->type
!= new_span
->ss
->type
&&
651 old_span
->ss
->type
== new_span
->ss
->orig_type
)
652 old_span
->ss
->type
= new_span
->ss
->type
;
655 static void match_global_symbols(struct span
*old_span
, asymbol
*oldsym
,
656 struct span
*new_span
, asymbol
*newsym
)
658 if ((oldsym
->flags
& BSF_GLOBAL
) == 0 ||
659 (newsym
->flags
& BSF_GLOBAL
) == 0)
661 match_spans(old_span
, new_span
);
664 static void check_global_symbols(struct span
*old_span
, asymbol
*oldsym
,
665 struct span
*new_span
, asymbol
*newsym
)
667 if ((oldsym
->flags
& BSF_GLOBAL
) == 0 ||
668 (newsym
->flags
& BSF_GLOBAL
) == 0)
670 if (old_span
->ss
->type
== SS_TYPE_IGNORED
)
672 if (old_span
->match
!= new_span
|| new_span
->match
!= old_span
) {
673 err(new_span
->ss
->parent
, "Global symbol span mismatch: %s "
674 "%s/%s\n", oldsym
->name
, old_span
->ss
->name
,
680 static void foreach_symbol_pair(struct superbfd
*oldsbfd
, struct superbfd
*newsbfd
,
681 void (*fn
)(struct span
*old_span
,
683 struct span
*new_span
,
686 asymbol
**oldsymp
, **newsymp
;
687 for (oldsymp
= oldsbfd
->syms
.data
;
688 oldsymp
< oldsbfd
->syms
.data
+ oldsbfd
->syms
.size
; oldsymp
++) {
689 asymbol
*oldsym
= *oldsymp
;
690 if (bfd_is_const_section(oldsym
->section
))
692 for (newsymp
= newsbfd
->syms
.data
;
693 newsymp
< newsbfd
->syms
.data
+ newsbfd
->syms
.size
;
695 asymbol
*newsym
= *newsymp
;
696 if (bfd_is_const_section(newsym
->section
))
698 if (strcmp(oldsym
->name
, newsym
->name
) != 0)
701 struct supersect
*old_ss
=
702 fetch_supersect(oldsbfd
, oldsym
->section
);
703 struct supersect
*new_ss
=
704 fetch_supersect(newsbfd
, newsym
->section
);
705 if ((old_ss
->type
!= new_ss
->type
&&
706 old_ss
->type
!= new_ss
->orig_type
) ||
707 old_ss
->type
== SS_TYPE_SPECIAL
||
708 old_ss
->type
== SS_TYPE_EXPORT
)
711 struct span
*old_span
=
712 find_span(old_ss
, oldsym
->value
);
713 struct span
*new_span
=
714 find_span(new_ss
, newsym
->value
);
715 if (old_span
== NULL
) {
716 err(oldsbfd
, "Could not find span for %s\n",
720 if (new_span
== NULL
) {
721 err(newsbfd
, "Could not find span for %s\n",
725 fn(old_span
, oldsym
, new_span
, newsym
);
730 static void match_symbol_spans(struct span
*old_span
, asymbol
*oldsym
,
731 struct span
*new_span
, asymbol
*newsym
)
733 if ((oldsym
->flags
& BSF_DEBUGGING
) != 0 ||
734 (newsym
->flags
& BSF_DEBUGGING
) != 0)
736 if (old_span
->ss
->type
== SS_TYPE_SPECIAL
)
738 if (static_local_symbol(old_span
->ss
->parent
, oldsym
) ||
739 static_local_symbol(new_span
->ss
->parent
, newsym
))
741 if (old_span
->match
== NULL
&& new_span
->match
== NULL
)
742 match_spans(old_span
, new_span
);
745 static void match_spans_by_label(struct span
*old_span
, struct span
*new_span
)
747 if (old_span
->ss
->type
== SS_TYPE_STRING
)
749 if (strcmp(old_span
->label
, new_span
->label
) == 0)
750 match_spans(old_span
, new_span
);
753 static void match_string_spans(struct span
*old_span
, struct span
*new_span
)
755 if (old_span
->ss
->type
!= SS_TYPE_STRING
||
756 strcmp(old_span
->ss
->name
, new_span
->ss
->name
) != 0)
758 if (strcmp((char *)old_span
->ss
->contents
.data
+ old_span
->start
,
759 (char *)new_span
->ss
->contents
.data
+ new_span
->start
) == 0)
760 match_spans(old_span
, new_span
);
763 static void foreach_span_pair(struct superbfd
*oldsbfd
,
764 struct superbfd
*newsbfd
,
765 void (*fn
)(struct span
*old_span
,
766 struct span
*new_span
))
768 asection
*oldsect
, *newsect
;
769 struct supersect
*oldss
, *newss
;
770 struct span
*old_span
, *new_span
;
771 for (newsect
= newsbfd
->abfd
->sections
; newsect
!= NULL
;
772 newsect
= newsect
->next
) {
773 newss
= fetch_supersect(newsbfd
, newsect
);
774 if (newss
->type
== SS_TYPE_SPECIAL
)
776 for (oldsect
= oldsbfd
->abfd
->sections
; oldsect
!= NULL
;
777 oldsect
= oldsect
->next
) {
778 oldss
= fetch_supersect(oldsbfd
, oldsect
);
779 if (oldss
->type
!= newss
->type
)
781 for (new_span
= newss
->spans
.data
;
782 new_span
< newss
->spans
.data
+ newss
->spans
.size
;
784 for (old_span
= oldss
->spans
.data
;
785 old_span
< oldss
->spans
.data
+
786 oldss
->spans
.size
; old_span
++)
787 fn(old_span
, new_span
);
793 static void mark_new_spans(struct superbfd
*sbfd
)
796 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
797 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
798 if (ss
->type
== SS_TYPE_SPECIAL
|| ss
->type
== SS_TYPE_IGNORED
)
801 for (span
= ss
->spans
.data
;
802 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++) {
803 if (span
->match
== NULL
&& !span
->bugpatch
)
809 static void handle_deleted_spans(struct superbfd
*oldsbfd
,
810 struct superbfd
*newsbfd
)
813 for (sect
= oldsbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
814 struct supersect
*ss
= fetch_supersect(oldsbfd
, sect
);
816 for (span
= ss
->spans
.data
;
817 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++) {
818 if (span
->match
!= NULL
)
820 if (ss
->type
== SS_TYPE_EXPORT
) {
821 *vec_grow(&delsects
, 1) = span
->label
;
822 write_ksplice_export(newsbfd
, span
, true);
823 } else if (ss
->type
== SS_TYPE_TEXT
) {
824 *vec_grow(&delsects
, 1) = span
->label
;
825 if (span
->symbol
== NULL
)
827 write_ksplice_deleted_patch
828 (newsbfd
, span
->symbol
->name
, span
->label
,
835 static void handle_nonzero_offset_relocs(struct supersect
*ss
)
837 struct span
*address_span
, *target_span
;
839 for (relocp
= ss
->relocs
.data
;
840 relocp
< ss
->relocs
.data
+ ss
->relocs
.size
; relocp
++) {
841 arelent
*reloc
= *relocp
;
842 address_span
= find_span(ss
, reloc
->address
);
843 if (!address_span
->new && !address_span
->patch
)
846 asymbol
*sym
= *reloc
->sym_ptr_ptr
;
847 if (bfd_is_const_section(sym
->section
))
849 bfd_vma offset
= get_reloc_offset(ss
, reloc
, true);
850 target_span
= reloc_target_span(ss
, reloc
);
851 if (sym
->value
+ offset
== target_span
->start
)
854 if (target_span
->ss
->type
!= SS_TYPE_TEXT
)
856 if (target_span
->patch
)
859 target_span
->patch
= true;
861 debug1(ss
->parent
, "Changing %s because a relocation from sect "
862 "%s has a nonzero offset %lx+%lx into it\n",
863 target_span
->label
, ss
->name
, (unsigned long)sym
->value
,
864 (unsigned long)offset
);
868 static void update_nonzero_offsets(struct superbfd
*sbfd
)
871 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
872 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
873 if (ss
->type
== SS_TYPE_SPECIAL
|| ss
->type
== SS_TYPE_IGNORED
)
875 handle_nonzero_offset_relocs(ss
);
879 static void compare_spans(struct span
*old_span
, struct span
*new_span
)
881 struct superbfd
*newsbfd
= new_span
->ss
->parent
;
883 bool nonrelocs_match
= nonrelocs_equal(old_span
, new_span
);
884 bool relocs_match
= all_relocs_equal(old_span
, new_span
);
885 if (nonrelocs_match
&& relocs_match
)
887 if (strcmp(old_span
->ss
->name
, "__bug_table") == 0 &&
888 strcmp(new_span
->ss
->name
, "__bug_table") == 0 && relocs_match
) {
889 debug1(newsbfd
, "Changing %s due to nonmatching line numbers\n",
891 new_span
->match
= NULL
;
892 old_span
->match
= NULL
;
893 new_span
->bugpatch
= true;
898 if (new_span
->contents_size
!= old_span
->contents_size
)
899 reason
= "differing sizes";
900 else if (!nonrelocs_match
)
901 reason
= "differing contents";
903 reason
= "differing relocations";
905 if (new_span
->ss
->type
== SS_TYPE_TEXT
) {
908 new_span
->patch
= true;
909 debug1(newsbfd
, "Changing %s due to %s\n", new_span
->label
,
911 } else if (new_span
->ss
->type
== SS_TYPE_RODATA
&&
912 new_span
->contents_size
== old_span
->contents_size
) {
913 if (new_span
->datapatch
)
915 new_span
->datapatch
= true;
916 debug1(newsbfd
, "Changing %s in-place due to %s\n",
917 new_span
->label
, reason
);
918 } else if (new_span
->ss
->type
== SS_TYPE_STRING
&&
919 old_span
->ss
->type
== SS_TYPE_STRING
&& relocs_match
&&
920 strcmp(new_span
->ss
->contents
.data
+ new_span
->start
,
921 old_span
->ss
->contents
.data
+ old_span
->start
) == 0) {
924 debug1(newsbfd
, "Unmatching %s and %s due to %s\n",
925 old_span
->label
, new_span
->label
, reason
);
926 new_span
->match
= NULL
;
927 old_span
->match
= NULL
;
930 if (unchangeable_section(new_span
->ss
))
931 err(newsbfd
, "warning: ignoring change to nonpatchable "
932 "section %s\n", new_span
->ss
->name
);
935 static void compare_matched_spans(struct superbfd
*newsbfd
)
938 for (sect
= newsbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
939 struct supersect
*ss
= fetch_supersect(newsbfd
, sect
);
941 for (span
= ss
->spans
.data
;
942 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++) {
943 if (span
->match
== NULL
)
945 compare_spans(span
->match
, span
);
950 static void handle_section_symbol_renames(struct superbfd
*oldsbfd
,
951 struct superbfd
*newsbfd
)
955 for (sect
= newsbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
956 struct supersect
*ss
= fetch_supersect(newsbfd
, sect
);
957 for (span
= ss
->spans
.data
;
958 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++) {
959 if (span
->match
== NULL
)
961 if (strcmp(span
->label
, span
->match
->label
) == 0)
963 if (strcmp(span
->orig_label
, span
->label
) != 0 &&
964 strcmp(span
->label
, span
->match
->label
) != 0)
966 if (span
->symbol
!= NULL
)
967 label_map_set(newsbfd
, span
->label
,
969 span
->label
= span
->match
->label
;
974 static bool part_of_reloc(struct supersect
*ss
, unsigned long addr
)
977 for (relocp
= ss
->relocs
.data
;
978 relocp
< ss
->relocs
.data
+ ss
->relocs
.size
; relocp
++) {
979 arelent
*reloc
= *relocp
;
980 if (addr
>= reloc
->address
&&
981 addr
< reloc
->address
+ reloc
->howto
->size
)
987 static bool nonrelocs_equal(struct span
*old_span
, struct span
*new_span
)
990 struct supersect
*old_ss
= old_span
->ss
, *new_ss
= new_span
->ss
;
991 if (old_span
->contents_size
!= new_span
->contents_size
)
993 const unsigned char *old
= old_ss
->contents
.data
+ old_span
->start
;
994 const unsigned char *new = new_ss
->contents
.data
+ new_span
->start
;
995 for (i
= 0; i
< old_span
->contents_size
; i
++) {
996 if (old
[i
] != new[i
] &&
997 !(part_of_reloc(old_ss
, i
+ old_span
->start
) &&
998 part_of_reloc(new_ss
, i
+ new_span
->start
)))
1004 bool relocs_equal(struct supersect
*old_src_ss
, struct supersect
*new_src_ss
,
1005 arelent
*old_reloc
, arelent
*new_reloc
)
1007 struct superbfd
*oldsbfd
= old_src_ss
->parent
;
1008 struct superbfd
*newsbfd
= new_src_ss
->parent
;
1009 struct span
*old_addr_span
= find_span(old_src_ss
, old_reloc
->address
);
1010 struct span
*new_addr_span
= find_span(new_src_ss
, new_reloc
->address
);
1012 if (old_reloc
->address
- old_addr_span
->start
!=
1013 new_reloc
->address
- new_addr_span
->start
) {
1014 debug1(newsbfd
, "Section %s/%s has reloc address mismatch at "
1015 "%lx\n", old_src_ss
->name
, new_src_ss
->name
,
1016 (unsigned long)old_reloc
->address
);
1020 if (old_reloc
->howto
!= new_reloc
->howto
) {
1021 debug1(newsbfd
, "Section %s/%s has howto type mismatch at "
1022 "%lx\n", old_src_ss
->name
, new_src_ss
->name
,
1023 (unsigned long)old_reloc
->address
);
1027 if (non_dst_mask(old_src_ss
, old_reloc
) !=
1028 non_dst_mask(new_src_ss
, new_reloc
)) {
1029 debug1(newsbfd
, "Section %s/%s has contents mismatch at %lx\n",
1030 old_src_ss
->name
, new_src_ss
->name
,
1031 (unsigned long)old_reloc
->address
);
1035 asymbol
*old_sym
= *old_reloc
->sym_ptr_ptr
;
1036 asymbol
*new_sym
= *new_reloc
->sym_ptr_ptr
;
1037 asection
*old_sect
= old_sym
->section
;
1038 asection
*new_sect
= new_sym
->section
;
1040 bfd_vma old_offset
= get_reloc_offset(old_src_ss
, old_reloc
, true);
1041 bfd_vma new_offset
= get_reloc_offset(new_src_ss
, new_reloc
, true);
1043 if (bfd_is_und_section(old_sect
) || bfd_is_und_section(new_sect
)) {
1044 if (!bfd_is_und_section(new_sect
) && old_offset
!= 0 &&
1045 fetch_supersect(newsbfd
, new_sect
)->type
== SS_TYPE_TEXT
)
1048 if (!bfd_is_und_section(new_sect
) && new_offset
!= 0 &&
1049 fetch_supersect(oldsbfd
, old_sect
)->type
== SS_TYPE_TEXT
)
1052 return strcmp(old_sym
->name
, new_sym
->name
) == 0 &&
1053 old_offset
== new_offset
;
1056 if (bfd_is_const_section(old_sect
) || bfd_is_const_section(new_sect
))
1059 struct supersect
*old_ss
= fetch_supersect(oldsbfd
, old_sect
);
1060 struct supersect
*new_ss
= fetch_supersect(newsbfd
, new_sect
);
1061 struct span
*old_span
= reloc_target_span(old_src_ss
, old_reloc
);
1062 struct span
*new_span
= reloc_target_span(new_src_ss
, new_reloc
);
1064 if (old_span
->match
!= new_span
|| new_span
->match
!= old_span
) {
1065 debug1(newsbfd
, "Nonmatching relocs from %s to %s/%s\n",
1066 new_src_ss
->name
, old_span
->label
, new_span
->label
);
1070 if (old_sym
->value
+ old_offset
- old_span
->start
!=
1071 new_sym
->value
+ new_offset
- new_span
->start
) {
1072 debug1(newsbfd
, "Offsets to %s/%s differ between %s "
1073 "and %s: %lx+%lx/%lx+%lx\n", old_ss
->name
,
1074 new_ss
->name
, old_src_ss
->name
, new_src_ss
->name
,
1075 (unsigned long)old_sym
->value
, (unsigned long)old_offset
,
1076 (unsigned long)new_sym
->value
,
1077 (unsigned long)new_offset
);
1081 if ((old_sym
->value
+ old_offset
- old_span
->start
!= 0 ||
1082 new_sym
->value
+ new_offset
- new_span
->start
!= 0) &&
1084 debug1(newsbfd
, "Relocation from %s to nonzero offsets "
1085 "%lx+%lx/%lx+%lx in changed section %s\n",
1086 new_src_ss
->name
, (unsigned long)old_sym
->value
,
1087 (unsigned long)old_offset
, (unsigned long)new_sym
->value
,
1088 (unsigned long)new_offset
, new_sym
->section
->name
);
1094 bool all_relocs_equal(struct span
*old_span
, struct span
*new_span
)
1096 struct supersect
*old_ss
= old_span
->ss
, *new_ss
= new_span
->ss
;
1097 arelent
**old_relocp
, **new_relocp
;
1099 for (old_relocp
= old_ss
->relocs
.data
;
1100 old_relocp
< old_ss
->relocs
.data
+ old_ss
->relocs
.size
;
1102 if (find_span(old_ss
, (*old_relocp
)->address
) == old_span
)
1106 for (new_relocp
= new_ss
->relocs
.data
;
1107 new_relocp
< new_ss
->relocs
.data
+ new_ss
->relocs
.size
;
1109 if (find_span(new_ss
, (*new_relocp
)->address
) == new_span
)
1113 for (; old_relocp
< old_ss
->relocs
.data
+ old_ss
->relocs
.size
&&
1114 find_span(old_ss
, (*old_relocp
)->address
) == old_span
&&
1115 new_relocp
< new_ss
->relocs
.data
+ new_ss
->relocs
.size
&&
1116 find_span(new_ss
, (*new_relocp
)->address
) == new_span
;
1117 old_relocp
++, new_relocp
++) {
1118 if (!relocs_equal(old_ss
, new_ss
, *old_relocp
, *new_relocp
))
1122 if ((old_relocp
< old_ss
->relocs
.data
+ old_ss
->relocs
.size
&&
1123 find_span(old_ss
, (*old_relocp
)->address
) == old_span
) ||
1124 (new_relocp
< new_ss
->relocs
.data
+ new_ss
->relocs
.size
&&
1125 find_span(new_ss
, (*new_relocp
)->address
) == new_span
)) {
1126 debug1(new_ss
->parent
, "Different reloc count between %s and "
1127 "%s\n", old_span
->label
, new_span
->label
);
1134 bfd_vma
non_dst_mask(struct supersect
*ss
, arelent
*reloc
)
1136 int bits
= bfd_get_reloc_size(reloc
->howto
) * 8;
1137 void *address
= ss
->contents
.data
+ reloc
->address
;
1138 bfd_vma x
= bfd_get(bits
, ss
->parent
->abfd
, address
);
1139 return x
& ~reloc
->howto
->dst_mask
;
1142 void rm_relocs(struct superbfd
*isbfd
)
1145 for (p
= isbfd
->abfd
->sections
; p
!= NULL
; p
= p
->next
) {
1146 struct supersect
*ss
= fetch_supersect(isbfd
, p
);
1147 bool remove_relocs
= ss
->keep
;
1149 if (mode("keep") && ss
->type
== SS_TYPE_SPECIAL
)
1150 remove_relocs
= false;
1152 if (ss
->type
== SS_TYPE_KSPLICE
||
1153 ss
->type
== SS_TYPE_KSPLICE_CALL
)
1154 remove_relocs
= false;
1155 if (mode("finalize") &&
1156 (starts_with(ss
->name
, ".ksplice_patches") ||
1157 starts_with(ss
->name
, ".ksplice_relocs")))
1158 remove_relocs
= true;
1165 void rm_some_relocs(struct supersect
*ss
)
1167 struct arelentp_vec orig_relocs
;
1168 vec_move(&orig_relocs
, &ss
->relocs
);
1171 for (relocp
= orig_relocs
.data
;
1172 relocp
< orig_relocs
.data
+ orig_relocs
.size
; relocp
++) {
1173 bool rm_reloc
= false;
1174 asymbol
*sym_ptr
= *(*relocp
)->sym_ptr_ptr
;
1176 if (mode("rmsyms") && str_in_set(sym_ptr
->name
, &rmsyms
) &&
1177 bfd_is_und_section(sym_ptr
->section
))
1183 if (mode("keep-primary") &&
1184 (bfd_is_const_section(sym_ptr
->section
) ||
1185 reloc_target_span(ss
, *relocp
)->new))
1188 if (mode("keep-primary")) {
1189 const struct table_section
*ts
=
1190 get_table_section(ss
->name
);
1191 if (ts
!= NULL
&& ts
->has_addr
&&
1192 ((*relocp
)->address
% ts
->entry_size
==
1194 (*relocp
)->address
% ts
->entry_size
==
1199 if (mode("finalize") && bfd_is_und_section(sym_ptr
->section
))
1202 if (strcmp(sym_ptr
->name
, "mcount") == 0 &&
1203 bfd_is_und_section(sym_ptr
->section
))
1206 if (!find_span(ss
, (*relocp
)->address
)->keep
)
1210 write_ksplice_reloc(ss
, *relocp
);
1212 *vec_grow(&ss
->relocs
, 1) = *relocp
;
1216 struct supersect
*make_section(struct superbfd
*sbfd
, const char *fmt
, ...)
1220 char *name
= vstrprintf(fmt
, ap
);
1223 asection
*sect
= bfd_get_section_by_name(sbfd
->abfd
, name
);
1225 return fetch_supersect(sbfd
, sect
);
1227 return new_supersect(sbfd
, name
);
1230 arelent
*create_reloc(struct supersect
*ss
, const void *addr
, asymbol
**symp
,
1233 bfd_reloc_code_real_type code
;
1234 switch (bfd_arch_bits_per_address(ss
->parent
->abfd
)) {
1236 code
= BFD_RELOC_32
;
1239 code
= BFD_RELOC_64
;
1245 arelent
*reloc
= malloc(sizeof(*reloc
));
1246 reloc
->sym_ptr_ptr
= symp
;
1247 reloc
->address
= addr_offset(ss
, addr
);
1248 reloc
->howto
= bfd_reloc_type_lookup(ss
->parent
->abfd
, code
);
1249 reloc
->addend
= offset
;
1253 void write_reloc(struct supersect
*ss
, const void *addr
, asymbol
**symp
,
1256 *vec_grow(&ss
->new_relocs
, 1) = create_reloc(ss
, addr
, symp
, offset
);
1259 void write_string(struct supersect
*ss
, const char **addr
, const char *fmt
, ...)
1262 struct supersect
*str_ss
= make_section(ss
->parent
, ".ksplice_str");
1265 int len
= vasprintf(&str
, fmt
, ap
);
1269 unsigned long *str_offp
= ulong_hash_lookup(&ksplice_string_offset
, str
,
1271 if (str_offp
== NULL
) {
1272 char *buf
= sect_grow(str_ss
, len
+ 1, char);
1273 memcpy(buf
, str
, len
+ 1);
1274 str_offp
= ulong_hash_lookup(&ksplice_string_offset
, str
, TRUE
);
1275 *str_offp
= addr_offset(str_ss
, buf
);
1278 write_reloc(ss
, addr
, &str_ss
->symbol
, *str_offp
);
1281 void lookup_system_map(struct addr_vec
*addrs
, const char *name
, long offset
)
1283 struct addr_vec
*map_addrs
=
1284 addr_vec_hash_lookup(&system_map
, name
, FALSE
);
1285 if (map_addrs
== NULL
)
1288 unsigned long *addr
, *map_addr
;
1289 for (map_addr
= map_addrs
->data
;
1290 map_addr
< map_addrs
->data
+ map_addrs
->size
; map_addr
++) {
1291 for (addr
= addrs
->data
; addr
< addrs
->data
+ addrs
->size
;
1293 if (*addr
== *map_addr
+ offset
)
1296 if (addr
< addrs
->data
+ addrs
->size
)
1298 *vec_grow(addrs
, 1) = *map_addr
+ offset
;
1302 void compute_system_map_array(struct superbfd
*sbfd
, struct addr_vec
*addrs
,
1305 if (bfd_is_abs_section(sym
->section
)) {
1306 *vec_grow(addrs
, 1) = sym
->value
;
1307 } else if (bfd_is_und_section(sym
->section
)) {
1308 lookup_system_map(addrs
, sym
->name
, 0);
1309 } else if (!bfd_is_const_section(sym
->section
)) {
1311 for (gsymp
= sbfd
->syms
.data
;
1312 gsymp
< sbfd
->syms
.data
+ sbfd
->syms
.size
; gsymp
++) {
1313 asymbol
*gsym
= *gsymp
;
1314 if ((gsym
->flags
& BSF_DEBUGGING
) == 0 &&
1315 gsym
->section
== sym
->section
)
1316 lookup_system_map(addrs
, gsym
->name
,
1317 sym
->value
- gsym
->value
);
1322 void write_ksplice_system_map(struct superbfd
*sbfd
, asymbol
*sym
,
1325 bool *done
= bool_hash_lookup(&system_map_written
, label
, TRUE
);
1330 struct addr_vec addrs
;
1333 compute_system_map_array(sbfd
, &addrs
, sym
);
1334 if (addrs
.size
!= 0) {
1335 struct supersect
*smap_ss
=
1336 make_section(sbfd
, ".ksplice_system_map");
1337 struct ksplice_system_map
*smap
=
1338 sect_grow(smap_ss
, 1, struct ksplice_system_map
);
1339 write_string(smap_ss
, &smap
->label
, "%s", label
);
1341 struct supersect
*array_ss
= make_section(sbfd
,
1343 void *buf
= sect_grow(array_ss
, addrs
.size
,
1344 typeof(*addrs
.data
));
1345 memcpy(buf
, addrs
.data
, addrs
.size
* sizeof(*addrs
.data
));
1346 smap
->nr_candidates
= addrs
.size
;
1347 write_reloc(smap_ss
, &smap
->candidates
, &array_ss
->symbol
,
1348 addr_offset(array_ss
, buf
));
1353 void write_ksplice_symbol_backend(struct supersect
*ss
,
1354 struct ksplice_symbol
*const *addr
,
1355 asymbol
*sym
, const char *label
,
1358 struct supersect
*ksymbol_ss
= make_section(ss
->parent
,
1359 ".ksplice_symbols");
1360 struct ksplice_symbol
*ksymbol
;
1361 unsigned long *ksymbol_offp
;
1363 ksymbol_offp
= ulong_hash_lookup(&ksplice_symbol_offset
, label
, FALSE
);
1364 if (ksymbol_offp
!= NULL
) {
1365 write_reloc(ss
, addr
, &ksymbol_ss
->symbol
, *ksymbol_offp
);
1368 ksymbol
= sect_grow(ksymbol_ss
, 1, struct ksplice_symbol
);
1369 ksymbol_offp
= ulong_hash_lookup(&ksplice_symbol_offset
, label
, TRUE
);
1370 *ksymbol_offp
= addr_offset(ksymbol_ss
, ksymbol
);
1372 write_reloc(ss
, addr
, &ksymbol_ss
->symbol
, *ksymbol_offp
);
1373 write_string(ksymbol_ss
, &ksymbol
->label
, "%s", label
);
1375 write_string(ksymbol_ss
, &ksymbol
->name
, "%s", name
);
1376 write_ksplice_system_map(ksymbol_ss
->parent
, sym
, label
);
1380 void write_ksplice_symbol(struct supersect
*ss
,
1381 struct ksplice_symbol
*const *addr
,
1382 asymbol
*sym
, struct span
*span
,
1383 const char *addstr_sect
)
1385 const char *label
, *name
;
1386 if (span
!= NULL
&& span
->start
!= 0)
1387 label
= span
->label
;
1389 label
= label_lookup(ss
->parent
, sym
);
1391 asymbol
*gsym
= canonical_symbol(ss
->parent
, sym
);
1392 if (strcmp(addstr_sect
, "") != 0)
1394 else if (bfd_is_und_section(sym
->section
))
1396 else if (bfd_is_const_section(sym
->section
))
1398 else if (span
!= NULL
&& span
->symbol
== NULL
)
1400 else if (gsym
== NULL
|| (gsym
->flags
& BSF_SECTION_SYM
) != 0)
1405 write_ksplice_symbol_backend(ss
, addr
, sym
,
1406 strprintf("%s%s", addstr_sect
, label
),
1410 void write_ksplice_reloc(struct supersect
*ss
, arelent
*orig_reloc
)
1412 asymbol
*sym_ptr
= *orig_reloc
->sym_ptr_ptr
;
1413 bfd_vma reloc_addend
= get_reloc_offset(ss
, orig_reloc
, false);
1414 bfd_vma target_addend
= get_reloc_offset(ss
, orig_reloc
, true);
1415 unsigned long *repladdr
= ss
->contents
.data
+ orig_reloc
->address
;
1417 if (mode("finalize") && starts_with(ss
->name
, ".ksplice_patches")) {
1421 if (mode("finalize") && starts_with(ss
->name
, ".ksplice_relocs")) {
1422 assert(starts_with(sym_ptr
->name
, KSPLICE_SYMBOL_STR
));
1424 fake_sym
.name
= sym_ptr
->name
+ strlen(KSPLICE_SYMBOL_STR
);
1425 fake_sym
.section
= bfd_und_section_ptr
;
1429 write_ksplice_symbol_backend
1430 (ss
, (struct ksplice_symbol
**)repladdr
, &fake_sym
,
1431 fake_sym
.name
, fake_sym
.name
);
1435 struct span
*span
= reloc_target_span(ss
, orig_reloc
);
1436 if (span
== ss
->spans
.data
&& span
->start
!= target_addend
)
1438 write_canary(ss
, orig_reloc
->address
,
1439 bfd_get_reloc_size(orig_reloc
->howto
),
1440 orig_reloc
->howto
->dst_mask
);
1442 struct supersect
*kreloc_ss
;
1444 kreloc_ss
= make_section(ss
->parent
, ".ksplice_init_relocs");
1446 kreloc_ss
= make_section(ss
->parent
, ".ksplice_relocs%s",
1448 struct ksplice_reloc
*kreloc
= sect_grow(kreloc_ss
, 1,
1449 struct ksplice_reloc
);
1451 struct span
*address_span
= find_span(ss
, orig_reloc
->address
);
1452 write_reloc(kreloc_ss
, &kreloc
->blank_addr
,
1453 &ss
->symbol
, orig_reloc
->address
+ address_span
->shift
);
1454 if (bfd_is_und_section(sym_ptr
->section
) && mode("keep")) {
1455 char *name
= strprintf(KSPLICE_SYMBOL_STR
"%s", sym_ptr
->name
);
1456 asymbol
**symp
= make_undefined_symbolp(ss
->parent
, name
);
1457 write_reloc(kreloc_ss
, &kreloc
->symbol
, symp
, 0);
1459 write_ksplice_symbol(kreloc_ss
, &kreloc
->symbol
, sym_ptr
, span
,
1462 if (span
!= NULL
&& span
->start
!= 0) {
1463 reloc_addend
+= sym_ptr
->value
- span
->start
;
1464 target_addend
+= sym_ptr
->value
- span
->start
;
1466 kreloc
->insn_addend
= reloc_addend
- target_addend
;
1467 kreloc
->target_addend
= target_addend
;
1468 write_ksplice_reloc_howto(kreloc_ss
, &kreloc
->howto
, orig_reloc
->howto
,
1469 KSPLICE_HOWTO_RELOC
);
1472 static void write_ksplice_reloc_howto(struct supersect
*ss
, const
1473 struct ksplice_reloc_howto
*const *addr
,
1474 reloc_howto_type
*howto
,
1475 enum ksplice_reloc_howto_type type
)
1477 struct supersect
*khowto_ss
= make_section(ss
->parent
,
1478 ".ksplice_reloc_howtos");
1479 struct ksplice_reloc_howto
*khowto
;
1480 unsigned long *khowto_offp
;
1482 khowto_offp
= ulong_hash_lookup(&ksplice_howto_offset
, howto
->name
,
1484 if (khowto_offp
!= NULL
) {
1485 write_reloc(ss
, addr
, &khowto_ss
->symbol
, *khowto_offp
);
1488 khowto
= sect_grow(khowto_ss
, 1, struct ksplice_reloc_howto
);
1489 khowto_offp
= ulong_hash_lookup(&ksplice_howto_offset
, howto
->name
,
1491 *khowto_offp
= addr_offset(khowto_ss
, khowto
);
1493 khowto
->type
= type
;
1494 khowto
->pcrel
= howto
->pc_relative
;
1495 khowto
->size
= bfd_get_reloc_size(howto
);
1496 khowto
->dst_mask
= howto
->dst_mask
;
1497 khowto
->rightshift
= howto
->rightshift
;
1498 khowto
->signed_addend
=
1499 (howto
->complain_on_overflow
== complain_overflow_signed
) ||
1500 (howto
->complain_on_overflow
== complain_overflow_bitfield
);
1501 write_reloc(ss
, addr
, &khowto_ss
->symbol
, *khowto_offp
);
1504 #define CANARY(x, canary) ((x & ~howto->dst_mask) | (canary & howto->dst_mask))
1506 void write_canary(struct supersect
*ss
, int offset
, bfd_size_type size
,
1509 int bits
= size
* 8;
1510 void *address
= ss
->contents
.data
+ offset
;
1511 bfd_vma x
= bfd_get(bits
, ss
->parent
->abfd
, address
);
1512 x
= (x
& ~dst_mask
) | ((bfd_vma
)KSPLICE_CANARY
& dst_mask
);
1513 bfd_put(bits
, ss
->parent
->abfd
, x
, address
);
1516 static void write_date_relocs(struct superbfd
*sbfd
, const char *str
,
1517 enum ksplice_reloc_howto_type type
)
1520 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
1521 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
1522 if (ss
->type
!= SS_TYPE_STRING
&& ss
->type
!= SS_TYPE_RODATA
)
1526 for (span
= ss
->spans
.data
;
1527 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++) {
1530 for (ptr
= ss
->contents
.data
+ span
->start
;
1531 ptr
+ strlen(str
) < ss
->contents
.data
+
1532 span
->start
+ span
->contents_size
; ptr
++) {
1533 if (strcmp((const char *)ptr
, str
) == 0)
1534 write_ksplice_date_reloc
1535 (ss
, addr_offset(ss
, ptr
), str
,
1542 static void write_ksplice_date_reloc(struct supersect
*ss
, unsigned long offset
,
1544 enum ksplice_reloc_howto_type type
)
1546 struct supersect
*kreloc_ss
;
1547 kreloc_ss
= make_section(ss
->parent
, ".ksplice_relocs%s", ss
->name
);
1548 struct ksplice_reloc
*kreloc
= sect_grow(kreloc_ss
, 1,
1549 struct ksplice_reloc
);
1551 const char *filename
= ss
->parent
->abfd
->filename
;
1552 char *c
= strstr(filename
, ".KSPLICE");
1553 int flen
= (c
== NULL
? strlen(filename
) : c
- filename
);
1555 write_ksplice_symbol_backend(kreloc_ss
, &kreloc
->symbol
, NULL
,
1556 strprintf("%s<%.*s>", str
, flen
, filename
),
1559 struct span
*span
= find_span(ss
, offset
);
1560 write_reloc(kreloc_ss
, &kreloc
->blank_addr
, &ss
->symbol
,
1561 offset
+ span
->shift
);
1562 write_ksplice_nonreloc_howto(kreloc_ss
, &kreloc
->howto
, type
,
1566 static void write_table_relocs(struct superbfd
*sbfd
, const char *sectname
,
1567 enum ksplice_reloc_howto_type type
)
1569 asection
*sect
= bfd_get_section_by_name(sbfd
->abfd
, sectname
);
1572 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
1574 const struct table_section
*s
= get_table_section(sectname
);
1579 for (entry
= ss
->contents
.data
;
1580 entry
< ss
->contents
.data
+ ss
->contents
.size
;
1581 entry
+= s
->entry_size
) {
1582 struct span
*span
= find_span(ss
, addr_offset(ss
, entry
));
1583 assert(span
!= NULL
);
1587 arelent
*reloc
= find_reloc(ss
, entry
+ s
->addr_offset
);
1588 assert(reloc
!= NULL
);
1589 asymbol
*sym
= *reloc
->sym_ptr_ptr
;
1590 assert(!bfd_is_const_section(sym
->section
));
1591 struct supersect
*sym_ss
= fetch_supersect(sbfd
, sym
->section
);
1592 unsigned long addr
= get_reloc_offset(ss
, reloc
, true) +
1594 write_ksplice_table_reloc(sym_ss
, addr
, span
->label
, type
);
1598 static void write_ksplice_table_reloc(struct supersect
*ss
,
1599 unsigned long address
,
1601 enum ksplice_reloc_howto_type type
)
1603 struct supersect
*kreloc_ss
;
1604 kreloc_ss
= make_section(ss
->parent
, ".ksplice_relocs%s", ss
->name
);
1605 struct ksplice_reloc
*kreloc
= sect_grow(kreloc_ss
, 1,
1606 struct ksplice_reloc
);
1607 struct span
*span
= find_span(ss
, address
);
1608 assert(span
!= NULL
);
1610 write_ksplice_symbol_backend(kreloc_ss
, &kreloc
->symbol
, NULL
,
1612 write_reloc(kreloc_ss
, &kreloc
->blank_addr
, &ss
->symbol
,
1613 address
+ span
->shift
);
1614 write_ksplice_nonreloc_howto(kreloc_ss
, &kreloc
->howto
, type
, 0);
1617 static void write_ksplice_nonreloc_howto(struct supersect
*ss
,
1618 const struct ksplice_reloc_howto
1620 enum ksplice_reloc_howto_type type
,
1623 struct supersect
*khowto_ss
=
1624 make_section(ss
->parent
, ".ksplice_reloc_howtos");
1625 struct ksplice_reloc_howto
*khowto
=
1626 sect_grow(khowto_ss
, 1, struct ksplice_reloc_howto
);
1628 khowto
->type
= type
;
1629 khowto
->size
= size
;
1631 khowto
->dst_mask
= 0;
1632 khowto
->rightshift
= 0;
1633 khowto
->signed_addend
= 0;
1634 write_reloc(ss
, addr
, &khowto_ss
->symbol
,
1635 addr_offset(khowto_ss
, khowto
));
1638 static void write_ksplice_section(struct span
*span
)
1640 struct supersect
*ss
= span
->ss
;
1641 const char *sectname
= span
->ss
->name
;
1642 const struct table_section
*ts
= get_table_section(ss
->name
);
1644 if (ts
!= NULL
&& ts
->has_addr
) {
1645 arelent
*reloc
= find_reloc(ss
, ss
->contents
.data
+ span
->start
1647 assert(reloc
!= NULL
);
1648 asymbol
*rsym
= *reloc
->sym_ptr_ptr
;
1649 assert(!bfd_is_const_section(rsym
->section
));
1650 sectname
= rsym
->section
->name
;
1653 struct supersect
*ksect_ss
=
1654 make_section(ss
->parent
, ".ksplice_sections%s", sectname
);
1655 struct ksplice_section
*ksect
= sect_grow(ksect_ss
, 1,
1656 struct ksplice_section
);
1657 asymbol
*sym
= span
->symbol
== NULL
? ss
->symbol
: span
->symbol
;
1659 write_ksplice_symbol(ksect_ss
, &ksect
->symbol
, sym
, span
,
1660 mode("keep-primary") ? "(post)" : "");
1661 ksect
->size
= span
->size
;
1664 if (ss
->type
== SS_TYPE_RODATA
|| ss
->type
== SS_TYPE_STRING
||
1665 ss
->type
== SS_TYPE_EXPORT
)
1666 ksect
->flags
|= KSPLICE_SECTION_RODATA
;
1667 if (ss
->type
== SS_TYPE_DATA
)
1668 ksect
->flags
|= KSPLICE_SECTION_DATA
;
1669 if (ss
->type
== SS_TYPE_TEXT
)
1670 ksect
->flags
|= KSPLICE_SECTION_TEXT
;
1671 assert(ksect
->flags
!= 0);
1673 if (ss
->type
== SS_TYPE_STRING
)
1674 ksect
->flags
|= KSPLICE_SECTION_STRING
;
1676 write_reloc(ksect_ss
, &ksect
->address
, &ss
->symbol
,
1677 span
->start
+ span
->shift
);
1680 static void write_ksplice_patch_reloc(struct supersect
*ss
,
1681 const char *sectname
, unsigned long *addr
,
1682 bfd_size_type size
, const char *label
,
1685 struct supersect
*kreloc_ss
;
1686 kreloc_ss
= make_section(ss
->parent
, ".ksplice_relocs%s", sectname
);
1687 struct ksplice_reloc
*kreloc
= sect_grow(kreloc_ss
, 1,
1688 struct ksplice_reloc
);
1690 write_canary(ss
, addr_offset(ss
, addr
), size
, -1);
1691 write_ksplice_symbol_backend(kreloc_ss
, &kreloc
->symbol
, NULL
,
1693 write_reloc(kreloc_ss
, &kreloc
->blank_addr
, &ss
->symbol
,
1694 addr_offset(ss
, addr
));
1695 reloc_howto_type
*howto
=
1696 bfd_reloc_type_lookup(ss
->parent
->abfd
,
1697 PASTE(BFD_RELOC_
, LONG_BIT
));
1698 write_ksplice_reloc_howto(kreloc_ss
, &kreloc
->howto
, howto
,
1699 KSPLICE_HOWTO_RELOC
);
1700 kreloc
->target_addend
= addend
;
1701 kreloc
->insn_addend
= 0;
1704 void write_ksplice_patch(struct superbfd
*sbfd
, struct span
*span
)
1706 struct supersect
*kpatch_ss
=
1707 make_section(sbfd
, ".ksplice_patches%s", span
->ss
->name
);
1708 struct ksplice_patch
*kpatch
= sect_grow(kpatch_ss
, 1,
1709 struct ksplice_patch
);
1711 write_ksplice_patch_reloc(kpatch_ss
, span
->ss
->name
, &kpatch
->oldaddr
,
1712 sizeof(kpatch
->oldaddr
), span
->label
, 0);
1713 if (span
->ss
->type
== SS_TYPE_TEXT
) {
1714 kpatch
->type
= KSPLICE_PATCH_TEXT
;
1715 write_patch_storage(kpatch_ss
, kpatch
, MAX_TRAMPOLINE_SIZE
,
1718 kpatch
->type
= KSPLICE_PATCH_DATA
;
1719 kpatch
->size
= span
->contents_size
;
1720 struct supersect
*data_ss
=
1721 make_section(sbfd
, ".ksplice_patch_data");
1722 write_reloc(kpatch_ss
, &kpatch
->contents
, &span
->ss
->symbol
,
1723 span
->start
+ span
->shift
);
1724 char *saved
= sect_do_grow(data_ss
, 1, span
->contents_size
, 1);
1725 write_reloc(kpatch_ss
, &kpatch
->saved
, &data_ss
->symbol
,
1726 addr_offset(data_ss
, saved
));
1728 write_reloc(kpatch_ss
, &kpatch
->repladdr
, &span
->ss
->symbol
,
1729 span
->start
+ span
->shift
);
1732 asymbol
**make_undefined_symbolp(struct superbfd
*sbfd
, const char *name
)
1735 for (symp
= sbfd
->syms
.data
; symp
< sbfd
->syms
.data
+ sbfd
->syms
.size
;
1737 asymbol
*sym
= *symp
;
1738 if (strcmp(name
, sym
->name
) == 0 &&
1739 bfd_is_und_section(sym
->section
))
1743 for (sympp
= sbfd
->new_syms
.data
;
1744 sympp
< sbfd
->new_syms
.data
+ sbfd
->new_syms
.size
; sympp
++) {
1745 asymbol
**symp
= *sympp
;
1746 asymbol
*sym
= *symp
;
1747 if (strcmp(name
, sym
->name
) == 0 &&
1748 bfd_is_und_section(sym
->section
))
1752 symp
= malloc(sizeof(*symp
));
1753 *symp
= bfd_make_empty_symbol(sbfd
->abfd
);
1754 asymbol
*sym
= *symp
;
1756 sym
->section
= bfd_und_section_ptr
;
1759 *vec_grow(&sbfd
->new_syms
, 1) = symp
;
1763 void write_ksplice_deleted_patch(struct superbfd
*sbfd
, const char *name
,
1764 const char *label
, const char *sectname
)
1766 struct supersect
*kpatch_ss
=
1767 make_section(sbfd
, ".ksplice_patches%s", sectname
);
1768 struct ksplice_patch
*kpatch
= sect_grow(kpatch_ss
, 1,
1769 struct ksplice_patch
);
1771 write_ksplice_patch_reloc(kpatch_ss
, sectname
, &kpatch
->oldaddr
,
1772 sizeof(kpatch
->oldaddr
), label
, 0);
1773 kpatch
->type
= KSPLICE_PATCH_TEXT
;
1774 asymbol
**symp
= make_undefined_symbolp(sbfd
, strdup(name
));
1775 write_reloc(kpatch_ss
, &kpatch
->repladdr
, symp
, 0);
1776 write_patch_storage(kpatch_ss
, kpatch
, MAX_TRAMPOLINE_SIZE
, NULL
);
1779 void write_ksplice_export(struct superbfd
*sbfd
, struct span
*span
, bool del
)
1781 struct supersect
*kpatch_ss
= make_section(sbfd
, ".ksplice_patches");
1782 struct ksplice_patch
*kpatch
= sect_grow(kpatch_ss
, 1,
1783 struct ksplice_patch
);
1784 struct supersect
*data_ss
;
1786 const struct table_section
*ts
= get_table_section(span
->ss
->name
);
1789 span
->ss
->contents
.data
+ span
->start
+ ts
->other_offset
;
1790 const char *symname
= read_string(span
->ss
, addr
);
1792 char *oldname
, *newname
;
1794 oldname
= strprintf("%s:%s", span
->ss
->name
, symname
);
1795 newname
= strprintf("DISABLED_%s_%s", symname
, kid
);
1797 oldname
= strprintf("%s:DISABLED_%s_%s", span
->ss
->name
,
1799 newname
= strprintf("%s", symname
);
1800 write_string(span
->ss
, addr
, "DISABLED_%s_%s", symname
, kid
);
1803 write_ksplice_patch_reloc(kpatch_ss
, "", &kpatch
->oldaddr
,
1804 sizeof(kpatch
->oldaddr
), oldname
,
1806 kpatch
->type
= KSPLICE_PATCH_EXPORT
;
1807 const char **namep
= write_patch_storage(kpatch_ss
, kpatch
,
1808 sizeof(newname
), &data_ss
);
1809 write_string(data_ss
, namep
, "%s", newname
);
1812 void filter_table_sections(struct superbfd
*isbfd
)
1814 struct supersect
*tables_ss
=
1815 fetch_supersect(offsets_sbfd
,
1816 bfd_get_section_by_name(offsets_sbfd
->abfd
,
1817 ".ksplice_table_sections"));
1818 const struct table_section
*ts
;
1819 for (ts
= tables_ss
->contents
.data
;
1820 (void *)ts
< tables_ss
->contents
.data
+ tables_ss
->contents
.size
;
1822 struct table_section s
= *ts
;
1823 s
.sect
= read_string(tables_ss
, &ts
->sect
);
1824 s
.other_sect
= read_string(tables_ss
, &ts
->other_sect
);
1825 s
.crc_sect
= read_string(tables_ss
, &ts
->crc_sect
);
1826 filter_table_section(isbfd
, &s
);
1830 void filter_table_section(struct superbfd
*sbfd
, const struct table_section
*s
)
1832 asection
*isection
= bfd_get_section_by_name(sbfd
->abfd
, s
->sect
);
1833 if (isection
== NULL
)
1835 struct supersect
*ss
= fetch_supersect(sbfd
, isection
);
1838 for (entry
= ss
->contents
.data
;
1839 entry
< ss
->contents
.data
+ ss
->contents
.size
;
1840 entry
+= s
->entry_size
) {
1841 struct span
*span
= find_span(ss
, addr_offset(ss
, entry
));
1842 assert(span
!= NULL
);
1845 arelent
*reloc
= find_reloc(ss
, entry
+ s
->addr_offset
);
1846 assert(reloc
!= NULL
);
1847 struct span
*sym_span
= reloc_target_span(ss
, reloc
);
1852 if (s
->other_sect
!= NULL
) {
1854 find_reloc(ss
, entry
+ s
->other_offset
);
1855 assert(reloc
!= NULL
);
1856 struct span
*sym_span
= reloc_target_span(ss
, reloc
);
1858 keep_span(sym_span
);
1861 if (s
->crc_sect
!= NULL
) {
1862 asection
*crc_sect
=
1863 bfd_get_section_by_name(sbfd
->abfd
, s
->crc_sect
);
1864 struct supersect
*crc_ss
=
1865 fetch_supersect(sbfd
, crc_sect
);
1866 struct span
*crc_span
=
1867 find_span(crc_ss
, addr_offset(ss
, entry
) /
1868 s
->entry_size
* s
->crc_size
);
1871 keep_span(crc_span
);
1876 void mark_precallable_spans(struct superbfd
*sbfd
)
1879 struct supersect
*ss
, *sym_ss
;
1880 struct span
*address_span
, *target_span
;
1881 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
1882 ss
= fetch_supersect(sbfd
, sect
);
1884 if (ss
->type
== SS_TYPE_SPECIAL
)
1886 for (relocp
= ss
->relocs
.data
;
1887 relocp
< ss
->relocs
.data
+ ss
->relocs
.size
; relocp
++) {
1888 asymbol
*sym
= *(*relocp
)->sym_ptr_ptr
;
1889 address_span
= find_span(ss
, (*relocp
)->address
);
1890 if (!address_span
->precallable
)
1892 target_span
= reloc_target_span(ss
, *relocp
);
1893 if (target_span
== NULL
|| target_span
->keep
)
1895 sym_ss
= fetch_supersect(sbfd
, sym
->section
);
1896 if (sym_ss
->type
== SS_TYPE_IGNORED
)
1898 target_span
->precallable
= true;
1904 void keep_referenced_sections(struct superbfd
*sbfd
)
1907 struct supersect
*ss
, *sym_ss
;
1908 struct span
*address_span
, *target_span
;
1909 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
1910 ss
= fetch_supersect(sbfd
, sect
);
1912 if (ss
->type
== SS_TYPE_SPECIAL
)
1914 for (relocp
= ss
->relocs
.data
;
1915 relocp
< ss
->relocs
.data
+ ss
->relocs
.size
; relocp
++) {
1916 asymbol
*sym
= *(*relocp
)->sym_ptr_ptr
;
1917 address_span
= find_span(ss
, (*relocp
)->address
);
1918 if (!address_span
->keep
)
1920 target_span
= reloc_target_span(ss
, *relocp
);
1921 if (target_span
== NULL
|| target_span
->keep
)
1923 sym_ss
= fetch_supersect(sbfd
, sym
->section
);
1924 if (sym_ss
->type
== SS_TYPE_IGNORED
)
1926 keep_span(target_span
);
1932 void copy_symbols(struct asymbolp_vec
*osyms
, struct asymbolpp_vec
*isyms
)
1935 for (sympp
= isyms
->data
; sympp
< isyms
->data
+ isyms
->size
; sympp
++)
1936 *vec_grow(osyms
, 1) = **sympp
;
1939 /* Modified function from GNU Binutils objcopy.c */
1940 bfd_boolean
copy_object(bfd
*ibfd
, bfd
*obfd
)
1942 assert(bfd_set_format(obfd
, bfd_get_format(ibfd
)));
1944 bfd_vma start
= bfd_get_start_address(ibfd
);
1946 flagword flags
= bfd_get_file_flags(ibfd
);
1947 flags
&= bfd_applicable_file_flags(obfd
);
1949 assert(bfd_set_start_address(obfd
, start
)
1950 && bfd_set_file_flags(obfd
, flags
));
1952 enum bfd_architecture iarch
= bfd_get_arch(ibfd
);
1953 unsigned int imach
= bfd_get_mach(ibfd
);
1954 assert(bfd_set_arch_mach(obfd
, iarch
, imach
));
1955 assert(bfd_set_format(obfd
, bfd_get_format(ibfd
)));
1957 /* BFD mandates that all output sections be created and sizes set before
1958 any output is done. Thus, we traverse all sections multiple times. */
1959 bfd_map_over_sections(ibfd
, setup_section
, obfd
);
1961 struct supersect
*new_supersects
= fetch_superbfd(ibfd
)->new_supersects
;
1962 struct supersect
*ss
;
1963 for (ss
= new_supersects
; ss
!= NULL
; ss
= ss
->next
)
1964 setup_new_section(obfd
, ss
);
1966 /* Mark symbols used in output relocations so that they
1967 are kept, even if they are local labels or static symbols.
1969 Note we iterate over the input sections examining their
1970 relocations since the relocations for the output sections
1971 haven't been set yet. mark_symbols_used_in_relocations will
1972 ignore input sections which have no corresponding output
1975 bfd_map_over_sections(ibfd
, mark_symbols_used_in_relocations
, NULL
);
1976 for (ss
= new_supersects
; ss
!= NULL
; ss
= ss
->next
)
1977 ss_mark_symbols_used_in_relocations(ss
);
1978 struct asymbolp_vec osyms
;
1980 filter_symbols(ibfd
, obfd
, &osyms
, &fetch_superbfd(ibfd
)->syms
);
1981 copy_symbols(&osyms
, &fetch_superbfd(ibfd
)->new_syms
);
1983 bfd_set_symtab(obfd
, osyms
.data
, osyms
.size
);
1985 /* This has to happen after the symbol table has been set. */
1986 bfd_map_over_sections(obfd
, write_section
, NULL
);
1988 /* Allow the BFD backend to copy any private data it understands
1989 from the input BFD to the output BFD. This is done last to
1990 permit the routine to look at the filtered symbol table, which is
1991 important for the ECOFF code at least. */
1992 assert(bfd_copy_private_bfd_data(ibfd
, obfd
));
1997 /* Modified function from GNU Binutils objcopy.c */
1998 void setup_section(bfd
*ibfd
, asection
*isection
, void *obfdarg
)
2000 struct superbfd
*isbfd
= fetch_superbfd(ibfd
);
2001 struct supersect
*ss
= fetch_supersect(isbfd
, isection
);
2002 bfd
*obfd
= obfdarg
;
2008 asection
*osection
= bfd_make_section_anyway(obfd
, ss
->name
);
2009 assert(osection
!= NULL
);
2011 osection
->userdata
= ss
;
2012 bfd_set_section_flags(obfd
, osection
, ss
->flags
);
2013 ss
->symbol
= osection
->symbol
;
2014 assert(bfd_set_section_size(obfd
, osection
, ss
->contents
.size
));
2016 vma
= bfd_section_vma(ibfd
, isection
);
2017 assert(bfd_set_section_vma(obfd
, osection
, vma
));
2019 osection
->lma
= isection
->lma
;
2020 assert(bfd_set_section_alignment(obfd
, osection
, ss
->alignment
));
2021 osection
->entsize
= ss
->entsize
;
2022 osection
->output_section
= osection
;
2023 osection
->output_offset
= 0;
2024 isection
->output_section
= osection
;
2025 isection
->output_offset
= 0;
2029 void setup_new_section(bfd
*obfd
, struct supersect
*ss
)
2031 asection
*osection
= bfd_make_section_anyway(obfd
, ss
->name
);
2032 assert(osection
!= NULL
);
2033 bfd_set_section_flags(obfd
, osection
, ss
->flags
);
2035 osection
->userdata
= ss
;
2036 ss
->symbol
= osection
->symbol
;
2037 assert(bfd_set_section_size(obfd
, osection
, ss
->contents
.size
));
2038 assert(bfd_set_section_vma(obfd
, osection
, 0));
2041 assert(bfd_set_section_alignment(obfd
, osection
, ss
->alignment
));
2042 osection
->entsize
= ss
->entsize
;
2043 osection
->output_section
= osection
;
2044 osection
->output_offset
= 0;
2047 static int compare_reloc_addresses(const void *aptr
, const void *bptr
)
2049 const arelent
*const *a
= aptr
, *const *b
= bptr
;
2050 return (*a
)->address
- (*b
)->address
;
2053 static void delete_obsolete_relocs(struct supersect
*ss
)
2055 if (ss
->new_relocs
.size
== 0)
2058 qsort(ss
->relocs
.data
, ss
->relocs
.size
, sizeof(*ss
->relocs
.data
),
2059 compare_reloc_addresses
);
2060 qsort(ss
->new_relocs
.data
, ss
->new_relocs
.size
,
2061 sizeof(*ss
->new_relocs
.data
), compare_reloc_addresses
);
2063 struct arelentp_vec orig_relocs
;
2064 vec_move(&orig_relocs
, &ss
->relocs
);
2066 arelent
**relocp
, **new_relocp
= ss
->new_relocs
.data
;
2067 for (relocp
= orig_relocs
.data
;
2068 relocp
< orig_relocs
.data
+ orig_relocs
.size
; relocp
++) {
2069 while (new_relocp
< ss
->new_relocs
.data
+ ss
->new_relocs
.size
&&
2070 (*new_relocp
)->address
< (*relocp
)->address
)
2072 arelent
*reloc
= *relocp
, *new_reloc
= *new_relocp
;
2073 if (new_relocp
== ss
->new_relocs
.data
+ ss
->new_relocs
.size
||
2074 reloc
->address
!= new_reloc
->address
)
2075 *vec_grow(&ss
->relocs
, 1) = reloc
;
2079 void write_section(bfd
*obfd
, asection
*osection
, void *arg
)
2081 struct supersect
*ss
= osection
->userdata
;
2083 if ((ss
->flags
& SEC_GROUP
) != 0 || ss
->contents
.size
== 0)
2086 delete_obsolete_relocs(ss
);
2089 char *error_message
;
2090 for (relocp
= ss
->new_relocs
.data
;
2091 relocp
< ss
->new_relocs
.data
+ ss
->new_relocs
.size
; relocp
++) {
2093 if (bfd_get_arch(obfd
) == bfd_arch_arm
)
2094 val
= osection
->use_rela_p
? 0 : (*relocp
)->addend
;
2097 bfd_put(bfd_get_reloc_size((*relocp
)->howto
) * 8, obfd
, val
,
2098 ss
->contents
.data
+ (*relocp
)->address
);
2099 if (bfd_install_relocation(obfd
, *relocp
, ss
->contents
.data
,
2100 0, osection
, &error_message
) !=
2102 err(ss
->parent
, "ksplice: error installing reloc: %s",
2107 memcpy(vec_grow(&ss
->relocs
, ss
->new_relocs
.size
), ss
->new_relocs
.data
,
2108 ss
->new_relocs
.size
* sizeof(*ss
->new_relocs
.data
));
2110 bfd_set_reloc(obfd
, osection
,
2111 ss
->relocs
.size
== 0 ? NULL
: ss
->relocs
.data
,
2114 if (ss
->flags
& SEC_HAS_CONTENTS
)
2115 assert(bfd_set_section_contents
2116 (obfd
, osection
, ss
->contents
.data
, 0,
2117 ss
->contents
.size
));
2120 /* Modified function from GNU Binutils objcopy.c
2122 * Mark all the symbols which will be used in output relocations with
2123 * the BSF_KEEP flag so that those symbols will not be stripped.
2125 * Ignore relocations which will not appear in the output file.
2127 void mark_symbols_used_in_relocations(bfd
*abfd
, asection
*isection
,
2130 struct superbfd
*sbfd
= fetch_superbfd(abfd
);
2131 if (isection
->output_section
== NULL
)
2134 struct supersect
*ss
= fetch_supersect(sbfd
, isection
);
2135 ss_mark_symbols_used_in_relocations(ss
);
2138 void ss_mark_symbols_used_in_relocations(struct supersect
*ss
)
2140 /* Examine each symbol used in a relocation. If it's not one of the
2141 special bfd section symbols, then mark it with BSF_KEEP. */
2143 for (relocp
= ss
->relocs
.data
;
2144 relocp
< ss
->relocs
.data
+ ss
->relocs
.size
; relocp
++) {
2145 asymbol
*sym
= *(*relocp
)->sym_ptr_ptr
;
2146 if (!(bfd_is_const_section(sym
->section
) &&
2147 sym
== sym
->section
->symbol
))
2148 sym
->flags
|= BSF_KEEP
;
2150 for (relocp
= ss
->new_relocs
.data
;
2151 relocp
< ss
->new_relocs
.data
+ ss
->new_relocs
.size
; relocp
++) {
2152 asymbol
*sym
= *(*relocp
)->sym_ptr_ptr
;
2153 if (!(bfd_is_const_section(sym
->section
) &&
2154 sym
== sym
->section
->symbol
))
2155 sym
->flags
|= BSF_KEEP
;
2159 static bool deleted_table_section_symbol(bfd
*abfd
, asymbol
*sym
)
2161 struct superbfd
*sbfd
= fetch_superbfd(abfd
);
2162 if (bfd_is_const_section(sym
->section
))
2164 struct supersect
*ss
= fetch_supersect(sbfd
, sym
->section
);
2167 for (symp
= ss
->syms
.data
; symp
< ss
->syms
.data
+ ss
->syms
.size
; symp
++) {
2171 return symp
>= ss
->syms
.data
+ ss
->syms
.size
&&
2172 (sym
->flags
& BSF_SECTION_SYM
) == 0;
2175 void filter_symbols(bfd
*ibfd
, bfd
*obfd
, struct asymbolp_vec
*osyms
,
2176 struct asymbolp_vec
*isyms
)
2179 struct superbfd
*sbfd
= fetch_superbfd(ibfd
);
2180 for (symp
= isyms
->data
; symp
< isyms
->data
+ isyms
->size
; symp
++) {
2181 asymbol
*sym
= *symp
;
2182 struct supersect
*sym_ss
= NULL
;
2183 struct span
*sym_span
= NULL
;
2184 if (!bfd_is_const_section(sym
->section
)) {
2185 sym_ss
= fetch_supersect(sbfd
, sym
->section
);
2186 sym_span
= find_span(sym_ss
, sym
->value
);
2189 if (mode("keep") && (sym
->flags
& BSF_GLOBAL
) != 0 &&
2190 !(mode("keep-primary") && sym_span
!= NULL
&&
2192 sym
->flags
= (sym
->flags
& ~BSF_GLOBAL
) | BSF_LOCAL
;
2194 if (mode("finalize") && (sym
->flags
& BSF_GLOBAL
) != 0)
2195 sym
->flags
= (sym
->flags
& ~BSF_GLOBAL
) | BSF_LOCAL
;
2197 bool keep
= bfd_is_const_section(sym
->section
) ||
2198 (sym_ss
->keep
&& (sym
->flags
& BSF_SECTION_SYM
) != 0) ||
2199 (sym_span
!= NULL
&& sym_span
->keep
);
2200 if (bfd_is_und_section(sym
->section
) &&
2201 (sym
->flags
& BSF_KEEP
) == 0)
2203 if (deleted_table_section_symbol(ibfd
, sym
))
2206 if (mode("keep-helper") && sym_ss
!= NULL
&&
2207 sym_ss
->type
== SS_TYPE_EXPORT
)
2211 if (sym_ss
!= NULL
&& !sym_ss
->keep
) {
2212 err(sbfd
, "Kept symbol %s in unkept section "
2213 "%s\n", sym
->name
, sym
->section
->name
);
2216 *vec_grow(osyms
, 1) = sym
;
2221 void read_str_set(struct str_vec
*strs
)
2225 assert(getline(&buf
, &n
, stdin
) >= 0);
2229 char *str
= strtok_r(buf
, " \n", &saveptr
);
2233 *vec_grow(strs
, 1) = str
;
2237 bool str_in_set(const char *str
, const struct str_vec
*strs
)
2240 for (strp
= strs
->data
; strp
< strs
->data
+ strs
->size
; strp
++) {
2241 if (strcmp(str
, *strp
) == 0)
2247 bool is_table_section(const char *name
, bool consider_other
)
2249 struct supersect
*tables_ss
=
2250 fetch_supersect(offsets_sbfd
,
2251 bfd_get_section_by_name(offsets_sbfd
->abfd
,
2252 ".ksplice_table_sections"));
2253 const struct table_section
*ts
;
2254 for (ts
= tables_ss
->contents
.data
;
2255 (void *)ts
< tables_ss
->contents
.data
+ tables_ss
->contents
.size
;
2257 if (strcmp(name
, read_string(tables_ss
, &ts
->sect
)) == 0)
2259 const char *osect_name
= read_string(tables_ss
,
2261 if (consider_other
&& osect_name
!= NULL
&&
2262 strcmp(name
, osect_name
) == 0)
2264 const char *crc_name
= read_string(tables_ss
, &ts
->crc_sect
);
2265 if (consider_other
&& crc_name
!= NULL
&&
2266 strcmp(name
, crc_name
) == 0)
2272 const struct table_section
*get_table_section(const char *name
)
2274 struct supersect
*tables_ss
=
2275 fetch_supersect(offsets_sbfd
,
2276 bfd_get_section_by_name(offsets_sbfd
->abfd
,
2277 ".ksplice_table_sections"));
2278 const struct table_section
*ts
;
2279 for (ts
= tables_ss
->contents
.data
;
2280 (void *)ts
< tables_ss
->contents
.data
+ tables_ss
->contents
.size
;
2282 if (strcmp(name
, read_string(tables_ss
, &ts
->sect
)) == 0) {
2283 if (ts
->entry_contents_size
!= 0)
2284 assert(align(ts
->entry_contents_size
,
2287 struct table_section
*ns
= malloc(sizeof(*ns
));
2289 ns
->sect
= read_string(tables_ss
, &ts
->sect
);
2290 ns
->crc_sect
= read_string(tables_ss
, &ts
->crc_sect
);
2292 read_string(tables_ss
, &ts
->other_sect
);
2299 enum supersect_type
supersect_type(struct supersect
*ss
)
2301 if (mode("finalize") &&
2302 strcmp(finalize_target
, "vmlinux") == 0 &&
2303 (starts_with(ss
->name
, ".ksplice_relocs.exit") ||
2304 starts_with(ss
->name
, ".ksplice_sections.exit") ||
2305 starts_with(ss
->name
, ".ksplice_patches.exit")))
2306 return SS_TYPE_EXIT
;
2307 if (starts_with(ss
->name
, ".ksplice_call"))
2308 return SS_TYPE_KSPLICE_CALL
;
2309 if (starts_with(ss
->name
, ".ksplice_options"))
2310 return SS_TYPE_SPECIAL
;
2311 if (starts_with(ss
->name
, ".ksplice"))
2312 return SS_TYPE_KSPLICE
;
2314 if (starts_with(ss
->name
, ".init"))
2315 return SS_TYPE_IGNORED
;
2316 if (starts_with(ss
->name
, ".security_initcall.init"))
2317 return SS_TYPE_IGNORED
;
2318 if (starts_with(ss
->name
, ".con_initcall.init"))
2319 return SS_TYPE_IGNORED
;
2320 if (starts_with(ss
->name
, ".x86cpuvendor.init"))
2321 return SS_TYPE_IGNORED
;
2322 if (starts_with(ss
->name
, ".early_param.init"))
2323 return SS_TYPE_IGNORED
;
2324 if (starts_with(ss
->name
, ".taglist.init"))
2325 return SS_TYPE_IGNORED
;
2326 if (starts_with(ss
->name
, ".arch.info.init"))
2327 return SS_TYPE_IGNORED
;
2328 if (starts_with(ss
->name
, ".proc.info.init"))
2329 return SS_TYPE_IGNORED
;
2330 /* .pci_fixup_* sections really should be treated as global rodata
2331 referenced only from quirks.c */
2332 if (starts_with(ss
->name
, ".pci_fixup_"))
2333 return SS_TYPE_IGNORED
;
2334 /* .builtin_fw sections are similar to .pci_fixup */
2335 if (starts_with(ss
->name
, ".builtin_fw"))
2336 return SS_TYPE_IGNORED
;
2337 /* same for .tracedata */
2338 if (starts_with(ss
->name
, ".tracedata"))
2339 return SS_TYPE_IGNORED
;
2340 if (starts_with(ss
->name
, ".debug"))
2341 return SS_TYPE_IGNORED
;
2342 /* .eh_frame should probably be discarded, not ignored */
2343 if (starts_with(ss
->name
, ".eh_frame"))
2344 return SS_TYPE_IGNORED
;
2345 if (config
->ignore_devinit
&& starts_with(ss
->name
, ".devinit"))
2346 return SS_TYPE_IGNORED
;
2347 if (config
->ignore_meminit
&& starts_with(ss
->name
, ".meminit"))
2348 return SS_TYPE_IGNORED
;
2349 if (config
->ignore_cpuinit
&& starts_with(ss
->name
, ".cpuinit"))
2350 return SS_TYPE_IGNORED
;
2351 if (config
->ignore_devinit
&& starts_with(ss
->name
, ".devexit"))
2352 return SS_TYPE_IGNORED
;
2353 if (config
->ignore_meminit
&& starts_with(ss
->name
, ".memexit"))
2354 return SS_TYPE_IGNORED
;
2355 if (config
->ignore_cpuinit
&& starts_with(ss
->name
, ".cpuexit"))
2356 return SS_TYPE_IGNORED
;
2357 if (starts_with(ss
->name
, ".vgetcpu_mode") ||
2358 starts_with(ss
->name
, ".jiffies") ||
2359 starts_with(ss
->name
, ".wall_jiffies") ||
2360 starts_with(ss
->name
, ".vxtime") ||
2361 starts_with(ss
->name
, ".sys_tz") ||
2362 starts_with(ss
->name
, ".sysctl_vsyscall") ||
2363 starts_with(ss
->name
, ".xtime") ||
2364 starts_with(ss
->name
, ".xtime_lock") ||
2365 starts_with(ss
->name
, ".vsyscall"))
2366 return SS_TYPE_IGNORED
;
2367 if (starts_with(ss
->name
, ".vdso"))
2368 return SS_TYPE_IGNORED
;
2370 if (starts_with(ss
->name
, ".exit.text"))
2371 return SS_TYPE_TEXT
;
2372 if (starts_with(ss
->name
, ".exit.data"))
2373 return SS_TYPE_DATA
;
2375 if (starts_with(ss
->name
, ".text") ||
2376 starts_with(ss
->name
, ".kernel.text") ||
2377 starts_with(ss
->name
, ".devinit.text") ||
2378 starts_with(ss
->name
, ".meminit.text") ||
2379 starts_with(ss
->name
, ".cpuinit.text") ||
2380 starts_with(ss
->name
, ".devexit.text") ||
2381 starts_with(ss
->name
, ".memexit.text") ||
2382 starts_with(ss
->name
, ".cpuexit.text") ||
2383 starts_with(ss
->name
, ".ref.text") ||
2384 starts_with(ss
->name
, ".spinlock.text") ||
2385 starts_with(ss
->name
, ".kprobes.text") ||
2386 starts_with(ss
->name
, ".sched.text") ||
2387 (mode("keep-helper") && starts_with(ss
->name
, ".fixup")))
2388 return SS_TYPE_TEXT
;
2391 if (sscanf(ss
->name
, ".rodata.str%*u.%*u%n", &n
) >= 0 &&
2392 n
== strlen(ss
->name
))
2393 return ss
->entsize
== 1 ? SS_TYPE_STRING
: SS_TYPE_RODATA
;
2395 if (starts_with(ss
->name
, ".rodata") ||
2396 starts_with(ss
->name
, ".kernel.rodata") ||
2397 starts_with(ss
->name
, ".devinit.rodata") ||
2398 starts_with(ss
->name
, ".meminit.rodata") ||
2399 starts_with(ss
->name
, ".cpuinit.rodata") ||
2400 starts_with(ss
->name
, ".devexit.rodata") ||
2401 starts_with(ss
->name
, ".memexit.rodata") ||
2402 starts_with(ss
->name
, ".cpuexit.rodata") ||
2403 starts_with(ss
->name
, ".ref.rodata") ||
2404 starts_with(ss
->name
, "__markers_strings") ||
2405 starts_with(ss
->name
, "__bug_table") ||
2406 (mode("keep-helper") && starts_with(ss
->name
, "__ex_table")))
2407 return SS_TYPE_RODATA
;
2409 if (starts_with(ss
->name
, ".bss"))
2410 return SS_TYPE_DATA
;
2412 /* Ignore .data.percpu sections */
2413 if (starts_with(ss
->name
, ".data.percpu") ||
2414 starts_with(ss
->name
, ".kernel.data.percpu"))
2415 return SS_TYPE_IGNORED
;
2416 if (starts_with(ss
->name
, ".data") ||
2417 starts_with(ss
->name
, ".kernel.data") ||
2418 starts_with(ss
->name
, ".devinit.data") ||
2419 starts_with(ss
->name
, ".cpuinit.data") ||
2420 starts_with(ss
->name
, ".meminit.data") ||
2421 starts_with(ss
->name
, ".devexit.data") ||
2422 starts_with(ss
->name
, ".memexit.data") ||
2423 starts_with(ss
->name
, ".cpuexit.data") ||
2424 starts_with(ss
->name
, ".ref.data") ||
2425 starts_with(ss
->name
, "__markers"))
2426 return SS_TYPE_DATA
;
2428 /* We replace all the ksymtab strings, so delete them */
2429 if (strcmp(ss
->name
, "__ksymtab_strings") == 0)
2430 return SS_TYPE_STRING
;
2431 if (starts_with(ss
->name
, "__ksymtab"))
2432 return SS_TYPE_EXPORT
;
2433 if (starts_with(ss
->name
, "__kcrctab"))
2434 return SS_TYPE_SPECIAL
;
2436 if (is_table_section(ss
->name
, true))
2437 return SS_TYPE_SPECIAL
;
2439 if (starts_with(ss
->name
, ".ARM."))
2440 return SS_TYPE_SPECIAL
;
2442 if (starts_with(ss
->name
, ".note"))
2443 return SS_TYPE_IGNORED
;
2444 if (starts_with(ss
->name
, ".comment"))
2445 return SS_TYPE_IGNORED
;
2446 if (starts_with(ss
->name
, "__param"))
2447 return SS_TYPE_IGNORED
;
2448 if (starts_with(ss
->name
, ".exitcall.exit"))
2449 return SS_TYPE_IGNORED
;
2450 if (starts_with(ss
->name
, ".modinfo"))
2451 return SS_TYPE_IGNORED
;
2453 return SS_TYPE_UNKNOWN
;
2456 void initialize_supersect_types(struct superbfd
*sbfd
)
2459 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
2460 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
2461 ss
->type
= supersect_type(ss
);
2462 ss
->orig_type
= ss
->type
;
2463 if (ss
->type
== SS_TYPE_UNKNOWN
) {
2464 err(sbfd
, "Unknown section type: %s\n", ss
->name
);
2470 static void init_label_map(struct superbfd
*sbfd
)
2472 struct label_map
*map
;
2474 vec_init(&sbfd
->maps
);
2478 struct symbol_hash csyms
;
2479 symbol_hash_init(&csyms
);
2482 for (symp
= sbfd
->syms
.data
;
2483 symp
< sbfd
->syms
.data
+ sbfd
->syms
.size
; symp
++) {
2484 asymbol
*csym
= canonical_symbol(sbfd
, *symp
);
2487 char *key
= strprintf("%p", csym
);
2488 asymbol
**csymp
= symbol_hash_lookup(&csyms
, key
, TRUE
);
2494 map
= vec_grow(&sbfd
->maps
, 1);
2497 map
->label
= symbol_label(sbfd
, csym
);
2500 struct label_mapp_hash label_maps
;
2501 label_mapp_hash_init(&label_maps
);
2502 for (map
= sbfd
->maps
.data
;
2503 map
< sbfd
->maps
.data
+ sbfd
->maps
.size
; map
++) {
2504 struct label_map
**mapp
=
2505 label_mapp_hash_lookup(&label_maps
, map
->label
, TRUE
);
2506 if (*mapp
== NULL
) {
2511 struct label_map
*first_map
= *mapp
;
2512 if (first_map
->count
== 0)
2513 first_map
->label
= strprintf("%s~%d", map
->label
, 0);
2514 map
->label
= strprintf("%s~%d", map
->label
, ++first_map
->count
);
2517 label_mapp_hash_init(&sbfd
->maps_hash
);
2518 for (map
= sbfd
->maps
.data
;
2519 map
< sbfd
->maps
.data
+ sbfd
->maps
.size
; map
++) {
2520 char *key
= strprintf("%p", map
->csym
);
2521 struct label_map
**mapp
=
2522 label_mapp_hash_lookup(&sbfd
->maps_hash
, key
, TRUE
);
2525 map
->orig_label
= map
->label
;
2529 static const char *label_lookup(struct superbfd
*sbfd
, asymbol
*sym
)
2531 asymbol
*csym
= canonical_symbol(sbfd
, sym
);
2532 char *key
= strprintf("%p", csym
);
2533 struct label_map
**mapp
=
2534 label_mapp_hash_lookup(&sbfd
->maps_hash
, key
, FALSE
);
2538 return (*mapp
)->label
;
2541 static void print_label_changes(struct superbfd
*sbfd
)
2545 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
2546 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
2547 for (span
= ss
->spans
.data
;
2548 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++) {
2549 if (strcmp(span
->label
, span
->orig_label
) != 0)
2550 debug1(sbfd
, "Label change: %s -> %s\n",
2551 span
->label
, span
->orig_label
);
2556 static void label_map_set(struct superbfd
*sbfd
, const char *oldlabel
,
2559 struct label_map
*map
;
2560 for (map
= sbfd
->maps
.data
;
2561 map
< sbfd
->maps
.data
+ sbfd
->maps
.size
; map
++) {
2562 if (strcmp(map
->orig_label
, oldlabel
) == 0) {
2563 if (strcmp(map
->orig_label
, map
->label
) != 0 &&
2564 strcmp(map
->label
, label
) != 0)
2573 static void change_initial_label(struct span
*span
, const char *label
)
2575 struct superbfd
*sbfd
= span
->ss
->parent
;
2576 span
->label
= label
;
2577 span
->orig_label
= label
;
2579 asymbol
*csym
= canonical_symbol(sbfd
, span
->symbol
);
2580 char *key
= strprintf("%p", csym
);
2581 struct label_map
**mapp
=
2582 label_mapp_hash_lookup(&sbfd
->maps_hash
, key
, FALSE
);
2585 (*mapp
)->label
= span
->label
;
2586 (*mapp
)->orig_label
= span
->orig_label
;
2587 span
->symbol
= NULL
;
2591 static void init_callers(struct superbfd
*sbfd
)
2593 string_hash_init(&sbfd
->callers
);
2595 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
2596 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
2598 for (relocp
= ss
->relocs
.data
;
2599 relocp
< ss
->relocs
.data
+ ss
->relocs
.size
; relocp
++) {
2600 asymbol
*sym
= *(*relocp
)->sym_ptr_ptr
;
2602 sym
->value
+ get_reloc_offset(ss
, *relocp
, true);
2603 char *key
= strprintf("%s+%lx", sym
->section
->name
,
2605 const char **ret
= string_hash_lookup(&sbfd
->callers
,
2608 asymbol
*csym
= canonical_symbol(sbfd
, sect
->symbol
);
2610 *ret
= "*multiple_callers*";
2611 else if (static_local_symbol(sbfd
, csym
))
2612 *ret
= static_local_symbol(sbfd
, csym
);
2619 static const char *find_caller(struct supersect
*ss
, asymbol
*sym
)
2621 char *key
= strprintf("%s+%lx", sym
->section
->name
,
2622 (unsigned long)sym
->value
);
2623 const char **ret
= string_hash_lookup(&ss
->parent
->callers
, key
, FALSE
);
2627 return "*no_caller*";
2631 static void init_csyms(struct superbfd
*sbfd
)
2633 asymbolpp_hash_init(&sbfd
->csyms
);
2636 for (symp
= sbfd
->syms
.data
; symp
< sbfd
->syms
.data
+ sbfd
->syms
.size
;
2638 asymbol
*sym
= *symp
;
2639 if ((sym
->flags
& BSF_DEBUGGING
) != 0)
2641 char *key
= strprintf("%s+%lx", sym
->section
->name
,
2642 (unsigned long)sym
->value
);
2643 asymbol
***csympp
= asymbolpp_hash_lookup(&sbfd
->csyms
, key
,
2646 if (*csympp
== NULL
) {
2650 asymbol
*csym
= **csympp
;
2651 if ((csym
->flags
& BSF_GLOBAL
) != 0)
2653 if ((sym
->flags
& BSF_GLOBAL
) != 0)
2658 static asymbol
**symbolp_scan(struct supersect
*ss
, bfd_vma value
)
2660 char *key
= strprintf("%s+%lx", ss
->name
, (unsigned long)value
);
2662 asymbolpp_hash_lookup(&ss
->parent
->csyms
, key
, FALSE
);
2667 /* For section symbols of sections containing no symbols, return the
2668 section symbol that relocations are generated against */
2674 static asymbol
**canonical_symbolp(struct superbfd
*sbfd
, asymbol
*sym
)
2676 if (bfd_is_const_section(sym
->section
)) {
2678 for (csymp
= sbfd
->syms
.data
;
2679 csymp
< sbfd
->syms
.data
+ sbfd
->syms
.size
; csymp
++) {
2685 return symbolp_scan(fetch_supersect(sbfd
, sym
->section
), sym
->value
);
2688 static asymbol
*canonical_symbol(struct superbfd
*sbfd
, asymbol
*sym
)
2690 if (bfd_is_const_section(sym
->section
))
2692 asymbol
**symp
= canonical_symbolp(sbfd
, sym
);
2693 return symp
!= NULL
? *symp
: NULL
;
2696 static char *static_local_symbol(struct superbfd
*sbfd
, asymbol
*sym
)
2698 struct supersect
*ss
= fetch_supersect(sbfd
, sym
->section
);
2699 if ((sym
->flags
& BSF_LOCAL
) == 0 || (sym
->flags
& BSF_OBJECT
) == 0)
2701 char *dot
= strrchr(sym
->name
, '.');
2702 if (dot
== NULL
|| dot
[1 + strspn(dot
+ 1, "0123546789")] != '\0')
2704 char *basename
= strndup(sym
->name
, dot
- sym
->name
);
2706 /* Handle C.123.12345 symbols */
2707 dot
= strrchr(basename
, '.');
2708 if (dot
!= NULL
&& dot
[1 + strspn(dot
+ 1, "0123546789")] == '\0')
2709 basename
= strndup(basename
, dot
- basename
);
2711 if (strcmp(basename
, "__func__") == 0 ||
2712 strcmp(basename
, "__PRETTY_FUNCTION__") == 0)
2713 caller
= (const char *)ss
->contents
.data
+ sym
->value
;
2715 caller
= find_caller(ss
, sym
);
2716 return strprintf("%s<%s>", basename
, caller
);
2719 static char *symbol_label(struct superbfd
*sbfd
, asymbol
*sym
)
2721 const char *filename
= sbfd
->abfd
->filename
;
2722 char *c
= strstr(filename
, ".KSPLICE");
2723 int flen
= (c
== NULL
? strlen(filename
) : c
- filename
);
2726 if (bfd_is_und_section(sym
->section
) || (sym
->flags
& BSF_GLOBAL
) != 0) {
2727 label
= strdup(sym
->name
);
2728 } else if (bfd_is_const_section(sym
->section
)) {
2729 label
= strprintf("%s<%.*s>", sym
->name
, flen
, filename
);
2731 asymbol
*gsym
= canonical_symbol(sbfd
, sym
);
2734 label
= strprintf("%s+%lx<%.*s>",
2736 (unsigned long)sym
->value
,
2738 else if ((gsym
->flags
& BSF_GLOBAL
) != 0)
2739 label
= strdup(gsym
->name
);
2740 else if (static_local_symbol(sbfd
, gsym
))
2741 label
= strprintf("%s+%lx<%.*s>",
2742 static_local_symbol(sbfd
, gsym
),
2743 (unsigned long)sym
->value
,
2746 label
= strprintf("%s<%.*s>",
2747 gsym
->name
, flen
, filename
);
2753 static void keep_span(struct span
*span
)
2756 span
->ss
->keep
= true;
2759 static struct span
*new_span(struct supersect
*ss
, bfd_vma start
, bfd_vma size
)
2761 struct span
*span
= vec_grow(&ss
->spans
, 1);
2763 span
->contents_size
= size
;
2764 span
->start
= start
;
2768 span
->patch
= false;
2769 span
->bugpatch
= false;
2770 span
->datapatch
= false;
2771 span
->precallable
= starts_with(ss
->name
, ".ksplice_call_pre_apply") ||
2772 starts_with(ss
->name
, ".ksplice_call_check_apply") ||
2773 starts_with(ss
->name
, ".ksplice_call_fail_apply") ||
2774 starts_with(ss
->name
, ".ksplice_call_post_remove");
2777 asymbol
**symp
= symbolp_scan(ss
, span
->start
);
2779 span
->symbol
= *symp
;
2780 span
->label
= label_lookup(ss
->parent
, span
->symbol
);
2782 span
->symbol
= NULL
;
2783 const char *label
= label_lookup(ss
->parent
, ss
->symbol
);
2784 if (span
->start
!= 0)
2785 span
->label
= strprintf("%s<span:%lx>", label
,
2786 (unsigned long)span
->start
);
2788 span
->label
= label
;
2790 span
->orig_label
= span
->label
;
2794 static void initialize_string_spans(struct supersect
*ss
)
2797 for (str
= ss
->contents
.data
;
2798 (void *)str
< ss
->contents
.data
+ ss
->contents
.size
;) {
2799 bfd_vma start
= (unsigned long)str
-
2800 (unsigned long)ss
->contents
.data
;
2801 bfd_vma size
= strlen(str
) + 1;
2802 bfd_vma contents_size
= size
;
2803 while ((start
+ size
) % (1 << ss
->alignment
) != 0 &&
2804 start
+ size
< ss
->contents
.size
) {
2805 /* Some string sections, like __ksymtab_strings, only
2806 align some strings with the declared alignment */
2807 if (str
[size
] != '\0')
2811 struct span
*span
= new_span(ss
, start
, size
);
2812 span
->contents_size
= contents_size
;
2817 static int compare_ulongs(const void *va
, const void *vb
)
2819 const unsigned long *a
= va
, *b
= vb
;
2823 static void initialize_table_spans(struct superbfd
*sbfd
,
2824 struct table_section
*s
)
2826 asection
*isection
= bfd_get_section_by_name(sbfd
->abfd
, s
->sect
);
2827 if (isection
== NULL
)
2829 struct supersect
*ss
= fetch_supersect(sbfd
, isection
);
2830 if (ss
->alignment
< ffs(s
->entry_align
) - 1)
2831 ss
->alignment
= ffs(s
->entry_align
) - 1;
2833 asection
*other_sect
= NULL
;
2834 if (s
->other_sect
!= NULL
)
2835 other_sect
= bfd_get_section_by_name(sbfd
->abfd
, s
->other_sect
);
2836 struct supersect
*other_ss
= NULL
;
2837 if (other_sect
!= NULL
)
2838 other_ss
= fetch_supersect(sbfd
, other_sect
);
2840 asection
*crc_sect
= NULL
;
2841 if (s
->crc_sect
!= NULL
)
2842 crc_sect
= bfd_get_section_by_name(sbfd
->abfd
, s
->crc_sect
);
2843 struct supersect
*crc_ss
= NULL
;
2844 if (crc_sect
!= NULL
)
2845 crc_ss
= fetch_supersect(sbfd
, crc_sect
);
2847 struct ulong_vec offsets
;
2851 for (entry
= ss
->contents
.data
;
2852 entry
< ss
->contents
.data
+ ss
->contents
.size
;
2853 entry
+= s
->entry_size
) {
2854 struct span
*span
= new_span(ss
, addr_offset(ss
, entry
),
2856 if (s
->entry_contents_size
!= 0)
2857 span
->contents_size
= s
->entry_contents_size
;
2858 if ((span
->symbol
== NULL
||
2859 (span
->symbol
->flags
& BSF_SECTION_SYM
) != 0) &&
2861 arelent
*reloc
= find_reloc(ss
, entry
+ s
->addr_offset
);
2863 struct span
*target_span
= reloc_target_span(ss
, reloc
);
2864 assert(target_span
);
2865 asymbol
*sym
= *reloc
->sym_ptr_ptr
;
2866 unsigned long val
= get_reloc_offset(ss
, reloc
, true) +
2867 sym
->value
- (target_span
->start
+
2868 target_span
->shift
);
2869 char *label
= strprintf("%s<target:%s+%lx>", ss
->name
,
2870 target_span
->label
, val
);
2871 change_initial_label(span
, label
);
2874 if (other_sect
!= NULL
) {
2876 bfd_vma offset
= read_reloc(ss
, entry
+ s
->other_offset
,
2877 sizeof(void *), &sym
);
2878 if (sym
->section
== other_sect
) {
2879 assert(offset
>= 0 &&
2880 offset
< other_ss
->contents
.size
);
2881 *vec_grow(&offsets
, 1) = offset
;
2885 if (crc_sect
!= NULL
)
2886 new_span(crc_ss
, addr_offset(ss
, entry
) / s
->entry_size
2887 * s
->crc_size
, s
->crc_size
);
2889 if (ss
->type
== SS_TYPE_EXPORT
) {
2890 const char *symname
= read_string(ss
, entry
+
2892 char *label
= strprintf("%s:%s", ss
->name
, symname
);
2893 change_initial_label(span
, label
);
2897 if (other_sect
== NULL
)
2900 *vec_grow(&offsets
, 1) = 0;
2901 qsort(offsets
.data
, offsets
.size
, sizeof(*offsets
.data
),
2903 *vec_grow(&offsets
, 1) = other_ss
->contents
.size
;
2906 for (off
= offsets
.data
; off
< offsets
.data
+ offsets
.size
- 1; off
++) {
2907 if (*off
!= *(off
+ 1))
2908 new_span(other_ss
, *off
, *(off
+ 1) - *off
);
2912 static void initialize_table_section_spans(struct superbfd
*sbfd
)
2914 struct supersect
*tables_ss
=
2915 fetch_supersect(offsets_sbfd
,
2916 bfd_get_section_by_name(offsets_sbfd
->abfd
,
2917 ".ksplice_table_sections"));
2918 const struct table_section
*ts
;
2919 struct table_section s
;
2920 for (ts
= tables_ss
->contents
.data
;
2921 (void *)ts
< tables_ss
->contents
.data
+ tables_ss
->contents
.size
;
2924 s
.sect
= read_string(tables_ss
, &ts
->sect
);
2925 s
.other_sect
= read_string(tables_ss
, &ts
->other_sect
);
2926 s
.crc_sect
= read_string(tables_ss
, &ts
->crc_sect
);
2927 initialize_table_spans(sbfd
, &s
);
2931 static void initialize_ksplice_call_spans(struct supersect
*ss
)
2934 for (relocp
= ss
->relocs
.data
;
2935 relocp
< ss
->relocs
.data
+ ss
->relocs
.size
; relocp
++) {
2936 arelent
*reloc
= *relocp
;
2937 new_span(ss
, reloc
->address
, bfd_get_reloc_size(reloc
->howto
));
2938 /* the span labels should already be unique */
2942 static void initialize_spans(struct superbfd
*sbfd
)
2945 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
2946 if (is_table_section(sect
->name
, true) && mode("keep"))
2949 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
2950 if (ss
->type
== SS_TYPE_STRING
)
2951 initialize_string_spans(ss
);
2952 else if (ss
->type
== SS_TYPE_KSPLICE_CALL
)
2953 initialize_ksplice_call_spans(ss
);
2955 new_span(ss
, 0, ss
->contents
.size
);
2958 initialize_table_section_spans(sbfd
);
2961 struct span
*reloc_target_span(struct supersect
*ss
, arelent
*reloc
)
2963 asymbol
*sym_ptr
= *reloc
->sym_ptr_ptr
;
2964 if (bfd_is_const_section(sym_ptr
->section
))
2967 bfd_vma addend
= get_reloc_offset(ss
, reloc
, true) + sym_ptr
->value
;
2968 struct supersect
*sym_ss
=
2969 fetch_supersect(ss
->parent
, sym_ptr
->section
);
2970 struct span
*span
, *target_span
= sym_ss
->spans
.data
;
2971 for (span
= sym_ss
->spans
.data
;
2972 span
< sym_ss
->spans
.data
+ sym_ss
->spans
.size
; span
++) {
2973 if (addend
>= span
->start
&& addend
< span
->start
+ span
->size
)
2979 struct span
*find_span(struct supersect
*ss
, bfd_size_type address
)
2982 for (span
= ss
->spans
.data
; span
< ss
->spans
.data
+ ss
->spans
.size
;
2984 if (address
>= span
->start
&&
2985 address
< span
->start
+ span
->size
)
2988 /* Deal with empty BSS sections */
2989 if (ss
->contents
.size
== 0 && ss
->spans
.size
> 0)
2990 return ss
->spans
.data
;
2994 void compute_span_shifts(struct superbfd
*sbfd
)
2998 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
2999 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
3002 bfd_size_type offset
= 0;
3003 for (span
= ss
->spans
.data
;
3004 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++) {
3007 span
->shift
= offset
- span
->start
;
3008 offset
+= span
->size
;
3013 void remove_unkept_spans(struct superbfd
*sbfd
)
3017 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
3018 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
3019 delete_obsolete_relocs(ss
);
3020 struct arelentp_vec orig_relocs
;
3021 vec_move(&orig_relocs
, &ss
->relocs
);
3022 arelent
**relocp
, *reloc
;
3023 for (relocp
= orig_relocs
.data
;
3024 relocp
< orig_relocs
.data
+ orig_relocs
.size
; relocp
++) {
3026 asymbol
*sym
= *reloc
->sym_ptr_ptr
;
3027 span
= reloc_target_span(ss
, reloc
);
3028 if ((span
!= NULL
&& span
->keep
&& span
->shift
== 0) ||
3029 bfd_is_const_section(sym
->section
)) {
3030 *vec_grow(&ss
->relocs
, 1) = reloc
;
3033 struct supersect
*sym_ss
=
3034 fetch_supersect(sbfd
, sym
->section
);
3035 if (span
!= NULL
&& (sym
->flags
& BSF_SECTION_SYM
) == 0
3036 && find_span(sym_ss
, sym
->value
) != span
) {
3037 err(sbfd
, "Spans for symbol %s and relocation "
3038 "target do not match in sect %s\n",
3039 sym
->name
, sym_ss
->name
);
3042 if (span
!= NULL
&& span
->keep
) {
3043 arelent
*new_reloc
= malloc(sizeof(*new_reloc
));
3044 *new_reloc
= *reloc
;
3046 get_reloc_offset(ss
, reloc
, false);
3047 new_reloc
->addend
+= span
->shift
;
3048 *vec_grow(&ss
->new_relocs
, 1) = new_reloc
;
3053 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
3054 struct supersect
*ss
= fetch_supersect(sbfd
, sect
), orig_ss
;
3057 supersect_move(&orig_ss
, ss
);
3058 vec_init(&ss
->spans
);
3059 for (span
= orig_ss
.spans
.data
;
3060 span
< orig_ss
.spans
.data
+ orig_ss
.spans
.size
; span
++) {
3063 struct span
*new_span
= vec_grow(&ss
->spans
, 1);
3065 new_span
->start
= span
->start
+ span
->shift
;
3066 new_span
->shift
= 0;
3067 sect_copy(ss
, sect_do_grow(ss
, 1, span
->size
, 1),
3068 &orig_ss
, orig_ss
.contents
.data
+ span
->start
,
3074 static void init_objmanip_superbfd(struct superbfd
*sbfd
)
3076 init_label_map(sbfd
);
3077 initialize_supersect_types(sbfd
);
3078 initialize_spans(sbfd
);
3082 void mangle_section_name(struct superbfd
*sbfd
, const char *name
)
3084 asection
*sect
= bfd_get_section_by_name(sbfd
->abfd
, name
);
3087 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
3088 ss
->name
= strprintf(".ksplice_pre.%s", ss
->name
);
3091 static void write_bugline_patches(struct superbfd
*sbfd
)
3093 const struct table_section
*ts
= get_table_section("__bug_table");
3094 asection
*sect
= bfd_get_section_by_name(sbfd
->abfd
, "__bug_table");
3097 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
3101 for (entry
= ss
->contents
.data
;
3102 entry
< ss
->contents
.data
+ ss
->contents
.size
;
3103 entry
+= ts
->entry_size
) {
3104 struct span
*span
= find_span(ss
, addr_offset(ss
, entry
));
3105 assert(span
!= NULL
);
3106 if (!span
->bugpatch
)
3108 arelent
*reloc
= find_reloc(ss
, entry
+ ts
->addr_offset
);
3109 assert(reloc
!= NULL
);
3110 asymbol
*sym
= *reloc
->sym_ptr_ptr
;
3111 assert(!bfd_is_const_section(sym
->section
));
3113 struct supersect
*kpatch_ss
=
3114 make_section(sbfd
, ".ksplice_patches%s",
3115 sym
->section
->name
);
3116 struct ksplice_patch
*kpatch
=
3117 sect_grow(kpatch_ss
, 1, struct ksplice_patch
);
3118 write_ksplice_patch_reloc
3119 (kpatch_ss
, sym
->section
->name
, &kpatch
->oldaddr
,
3120 sizeof(kpatch
->oldaddr
), span
->label
, ts
->other_offset
);
3122 unsigned short *line
=
3123 write_patch_storage(kpatch_ss
, kpatch
, sizeof(*line
), NULL
);
3124 *line
= *(unsigned short *)(entry
+ ts
->other_offset
);
3125 kpatch
->type
= KSPLICE_PATCH_BUGLINE
;
3129 void *write_patch_storage(struct supersect
*ss
, struct ksplice_patch
*kpatch
,
3130 size_t size
, struct supersect
**data_ssp
)
3132 struct supersect
*data_ss
= make_section(ss
->parent
,
3133 ".ksplice_patch_data");
3134 char *saved
= sect_do_grow(data_ss
, 1, size
, 1);
3135 write_reloc(ss
, &kpatch
->saved
, &data_ss
->symbol
,
3136 addr_offset(data_ss
, saved
));
3137 char *data
= sect_do_grow(data_ss
, 1, size
, 1);
3138 write_reloc(ss
, &kpatch
->contents
, &data_ss
->symbol
,
3139 addr_offset(data_ss
, data
));
3140 kpatch
->size
= size
;
3141 if (data_ssp
!= NULL
)
3142 *data_ssp
= data_ss
;