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-2009 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-new-code: "objmanip <post.o> <out.o> keep-new-code <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-old-code: "objmanip <pre.o> <out.o> keep-old-code"
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_new_code(struct superbfd
*isbfd
, const char *pre
);
81 void do_keep_old_code(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 static struct span
*span_offset_target_span(struct span
*span
, int offset
);
104 static bfd_vma
reloc_target_offset(struct supersect
*ss
, arelent
*reloc
);
105 struct span
*find_span(struct supersect
*ss
, bfd_size_type address
);
106 void remove_unkept_spans(struct superbfd
*sbfd
);
107 void compute_span_shifts(struct superbfd
*sbfd
);
108 static struct span
*new_span(struct supersect
*ss
, bfd_vma start
, bfd_vma size
);
109 static bool is_table_section(const char *name
, bool consider_other
,
111 const struct table_section
*get_table_section(const char *name
);
112 void mangle_section_name(struct superbfd
*sbfd
, const char *name
);
114 void rm_relocs(struct superbfd
*isbfd
);
115 void rm_some_relocs(struct supersect
*ss
);
116 void write_ksplice_reloc(struct supersect
*ss
, arelent
*orig_reloc
);
117 static void write_ksplice_reloc_howto(struct supersect
*ss
, const
118 struct ksplice_reloc_howto
*const *addr
,
119 reloc_howto_type
*howto
,
120 enum ksplice_reloc_howto_type type
);
121 static void write_ksplice_date_reloc(struct supersect
*ss
, unsigned long offset
,
123 enum ksplice_reloc_howto_type type
);
124 static void write_ksplice_patch_reloc(struct supersect
*ss
,
125 const char *sectname
, unsigned long *addr
,
126 bfd_size_type size
, const char *label
,
128 static void write_ksplice_nonreloc_howto(struct supersect
*ss
,
129 const struct ksplice_reloc_howto
131 enum ksplice_reloc_howto_type type
,
133 static void write_date_relocs(struct superbfd
*sbfd
, const char *str
,
134 enum ksplice_reloc_howto_type type
);
135 static void write_table_relocs(struct superbfd
*sbfd
, const char *sectname
,
136 enum ksplice_reloc_howto_type type
);
137 static void write_ksplice_table_reloc(struct supersect
*ss
,
138 unsigned long address
,
140 enum ksplice_reloc_howto_type type
);
141 void load_ksplice_symbol_offsets(struct superbfd
*sbfd
);
142 void write_canary(struct supersect
*ss
, int offset
, bfd_size_type size
,
144 static void write_ksplice_section(struct span
*span
);
145 void write_ksplice_patch(struct superbfd
*sbfd
, struct span
*span
);
146 void *write_patch_storage(struct supersect
*ss
, struct ksplice_patch
*patch
,
147 size_t size
, struct supersect
**data_ssp
);
148 void write_ksplice_deleted_patch(struct superbfd
*sbfd
, const char *name
,
149 const char *label
, const char *sectname
);
150 static void write_bugline_patches(struct superbfd
*sbfd
);
151 asymbol
**make_undefined_symbolp(struct superbfd
*sbfd
, const char *name
);
152 void filter_table_sections(struct superbfd
*isbfd
);
153 void filter_table_section(struct superbfd
*sbfd
, const struct table_section
*s
);
154 void keep_referenced_sections(struct superbfd
*sbfd
);
155 void mark_precallable_spans(struct superbfd
*sbfd
);
156 bfd_boolean
copy_object(bfd
*ibfd
, bfd
*obfd
);
157 void setup_section(bfd
*ibfd
, asection
*isection
, void *obfdarg
);
158 static void setup_new_section(bfd
*obfd
, struct supersect
*ss
);
159 static void write_section(bfd
*obfd
, asection
*osection
, void *arg
);
160 static void delete_obsolete_relocs(struct supersect
*ss
);
161 void mark_symbols_used_in_relocations(bfd
*abfd
, asection
*isection
,
163 static void ss_mark_symbols_used_in_relocations(struct supersect
*ss
);
164 void filter_symbols(bfd
*ibfd
, bfd
*obfd
, struct asymbolp_vec
*osyms
,
165 struct asymbolp_vec
*isyms
);
166 static bool deleted_table_section_symbol(bfd
*abfd
, asymbol
*sym
);
167 void read_str_set(struct str_vec
*strs
);
168 bool str_in_set(const char *str
, const struct str_vec
*strs
);
169 struct supersect
*__attribute((format(printf
, 2, 3)))
170 make_section(struct superbfd
*sbfd
, const char *fmt
, ...);
171 void __attribute__((format(printf
, 3, 4)))
172 write_string(struct supersect
*ss
, const char **addr
, const char *fmt
, ...);
173 void write_ksplice_export(struct superbfd
*sbfd
, struct span
*span
, bool del
);
174 void write_reloc(struct supersect
*ss
, const void *addr
, asymbol
**symp
,
176 arelent
*create_reloc(struct supersect
*ss
, const void *addr
, asymbol
**symp
,
178 static void foreach_symbol_pair(struct superbfd
*oldsbfd
, struct superbfd
*newsbfd
,
179 void (*fn
)(struct span
*old_span
,
181 struct span
*new_span
,
183 static void check_global_symbols(struct span
*old_span
, asymbol
*oldsym
,
184 struct span
*new_span
, asymbol
*newsym
);
185 static void match_global_symbols(struct span
*old_span
, asymbol
*oldsym
,
186 struct span
*new_span
, asymbol
*newsym
);
187 static void match_symbol_spans(struct span
*old_span
, asymbol
*oldsym
,
188 struct span
*new_span
, asymbol
*newsym
);
189 static void match_table_spans(struct span
*old_span
, struct span
*new_span
);
191 static struct span
*get_crc_span(struct span
*span
,
192 const struct table_section
*ts
);
193 static void foreach_span_pair(struct superbfd
*oldsbfd
,
194 struct superbfd
*newsbfd
,
195 void (*fn
)(struct span
*old_span
,
196 struct span
*new_span
));
197 static void match_spans_by_label(struct span
*old_span
, struct span
*new_span
);
198 static void match_string_spans(struct span
*old_span
, struct span
*new_span
);
199 static void mark_new_spans(struct superbfd
*sbfd
);
200 static void handle_deleted_spans(struct superbfd
*oldsbfd
,
201 struct superbfd
*newsbfd
);
202 static void unmatch_addr_spans(struct span
*old_span
, struct span
*new_span
,
203 const struct table_section
*ts
);
204 static void compare_matched_spans(struct superbfd
*newsbfd
);
205 static void compare_spans(struct span
*old_span
, struct span
*new_span
);
206 static void update_nonzero_offsets(struct superbfd
*sbfd
);
207 static void handle_nonzero_offset_relocs(struct supersect
*ss
);
208 static void keep_span(struct span
*span
);
210 static void init_objmanip_superbfd(struct superbfd
*sbfd
);
211 static const char *label_lookup(struct superbfd
*sbfd
, asymbol
*sym
);
212 static void label_map_set(struct superbfd
*sbfd
, const char *oldlabel
,
214 static void print_label_changes(struct superbfd
*sbfd
);
215 static void init_label_map(struct superbfd
*sbfd
);
216 static void change_initial_label(struct span
*span
, const char *label
);
217 static asymbol
**symbolp_scan(struct supersect
*ss
, bfd_vma value
);
218 static void init_csyms(struct superbfd
*sbfd
);
219 static void init_callers(struct superbfd
*sbfd
);
220 static asymbol
*canonical_symbol(struct superbfd
*sbfd
, asymbol
*sym
);
221 static asymbol
**canonical_symbolp(struct superbfd
*sbfd
, asymbol
*sym
);
222 static char *static_local_symbol(struct superbfd
*sbfd
, asymbol
*sym
);
223 static char *symbol_label(struct superbfd
*sbfd
, asymbol
*sym
);
226 #define debug_(sbfd, level, fmt, ...) \
228 if (verbose >= (level)) \
229 printf("%s: " fmt, (sbfd)->abfd->filename, \
232 #define debug0(sbfd, fmt, ...) debug_(sbfd, 0, fmt, ## __VA_ARGS__)
233 #define debug1(sbfd, fmt, ...) debug_(sbfd, 1, fmt, ## __VA_ARGS__)
234 #define err(sbfd, fmt, ...) \
236 fprintf(stderr, "%s: " fmt, (sbfd)->abfd->filename, \
240 struct str_vec delsects
, rmsyms
;
243 struct ksplice_config
*config
;
245 const char *modestr
, *kid
, *finalize_target
= NULL
;
246 bool write_output
= true;
248 struct superbfd
*offsets_sbfd
= NULL
;
250 #define mode(str) strstarts(modestr, str)
252 DECLARE_VEC_TYPE(unsigned long, addr_vec
);
253 DEFINE_HASH_TYPE(struct addr_vec
, addr_vec_hash
,
254 addr_vec_hash_init
, addr_vec_hash_free
, addr_vec_hash_lookup
,
256 struct addr_vec_hash system_map
;
258 struct bool_hash system_map_written
;
259 struct ulong_hash ksplice_symbol_offset
;
260 struct ulong_hash ksplice_howto_offset
;
261 struct ulong_hash ksplice_string_offset
;
263 void load_system_map()
265 const char *config_dir
= getenv("KSPLICE_CONFIG_DIR");
267 FILE *fp
= fopen(strprintf("%s/System.map", config_dir
), "r");
269 addr_vec_hash_init(&system_map
);
273 while (fscanf(fp
, "%lx %c %as\n", &addr
, &type
, &sym
) == 3)
274 *vec_grow(addr_vec_hash_lookup(&system_map
, sym
, TRUE
),
279 void load_ksplice_symbol_offsets(struct superbfd
*sbfd
)
281 asection
*sect
= bfd_get_section_by_name(sbfd
->abfd
,
285 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
287 struct ksplice_symbol
*ksym
;
288 for (ksym
= ss
->contents
.data
;
289 (void *)ksym
< ss
->contents
.data
+ ss
->contents
.size
; ksym
++) {
290 const char *label
= read_string(ss
, &ksym
->label
);
291 unsigned long *ksymbol_offp
=
292 ulong_hash_lookup(&ksplice_symbol_offset
, label
, TRUE
);
293 *ksymbol_offp
= addr_offset(ss
, ksym
);
299 char *kmodsrc
= getenv("KSPLICE_KMODSRC");
300 assert(kmodsrc
!= NULL
);
301 bfd
*offsets_bfd
= bfd_openr(strprintf("%s/offsets.o", kmodsrc
), NULL
);
302 assert(offsets_bfd
!= NULL
);
304 assert(bfd_check_format_matches(offsets_bfd
, bfd_object
, &matching
));
305 offsets_sbfd
= fetch_superbfd(offsets_bfd
);
307 asection
*config_sect
= bfd_get_section_by_name(offsets_sbfd
->abfd
,
309 struct supersect
*config_ss
=
310 fetch_supersect(offsets_sbfd
, config_sect
);
312 config
= config_ss
->contents
.data
;
315 void load_options(struct superbfd
*sbfd
)
317 asection
*sect
= bfd_get_section_by_name(sbfd
->abfd
,
321 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
322 const struct ksplice_option
*opt
;
323 for (opt
= ss
->contents
.data
;
324 (void *)opt
< ss
->contents
.data
+ ss
->contents
.size
; opt
++) {
325 if (opt
->type
== KSPLICE_OPTION_ASSUME_RODATA
) {
326 arelent
*reloc
= find_reloc(ss
, &opt
->target
);
327 struct span
*span
= reloc_target_span(ss
, reloc
);
328 assert(span
!= NULL
);
329 assert(span
->ss
->type
== SS_TYPE_DATA
);
330 assert(span
->start
== 0 &&
331 span
->size
== span
->ss
->contents
.size
);
332 span
->ss
->type
= SS_TYPE_RODATA
;
335 err(sbfd
, "Unrecognized Ksplice option %d\n",
342 bool matchable_data_section(struct supersect
*ss
)
344 if (ss
->type
== SS_TYPE_STRING
)
346 if (ss
->type
== SS_TYPE_RODATA
)
348 if (ss
->type
== SS_TYPE_DATA
&& ss
->relocs
.size
!= 0)
350 if (ss
->type
== SS_TYPE_EXPORT
)
355 bool unchangeable_section(struct supersect
*ss
)
357 if (ss
->type
== SS_TYPE_DATA
)
359 if (ss
->type
== SS_TYPE_IGNORED
&& !strstarts(ss
->name
, ".debug") &&
360 strcmp(ss
->name
, "__ksymtab_strings") != 0)
365 int main(int argc
, char *argv
[])
367 if (getenv("KSPLICE_VERBOSE") != NULL
)
368 verbose
= atoi(getenv("KSPLICE_VERBOSE"));
371 bfd
*ibfd
= bfd_openr(argv
[1], NULL
);
375 if (bfd_check_format_matches(ibfd
, bfd_archive
, &matching
) &&
376 bfd_openr_next_archived_file(ibfd
, NULL
) == NULL
)
377 return 66; /* empty archive */
378 assert(bfd_check_format_matches(ibfd
, bfd_object
, &matching
));
380 const char *output_target
= bfd_get_target(ibfd
);
385 bool_hash_init(&system_map_written
);
386 ulong_hash_init(&ksplice_symbol_offset
);
387 ulong_hash_init(&ksplice_howto_offset
);
388 ulong_hash_init(&ksplice_string_offset
);
390 struct superbfd
*isbfd
= fetch_superbfd(ibfd
);
393 if (mode("finalize"))
394 finalize_target
= argv
[4];
395 init_objmanip_superbfd(isbfd
);
396 if (mode("keep-new-code")) {
398 do_keep_new_code(isbfd
, argv
[4]);
399 } else if (mode("keep-old-code")) {
400 do_keep_old_code(isbfd
);
401 } else if (mode("finalize")) {
403 } else if (mode("rmsyms")) {
408 bfd
*obfd
= bfd_openw(argv
[2], output_target
);
410 copy_object(ibfd
, obfd
);
411 assert(bfd_close(obfd
));
414 if (offsets_sbfd
!= NULL
)
415 assert(bfd_close(offsets_sbfd
->abfd
));
416 assert(bfd_close(ibfd
));
420 void do_keep_new_code(struct superbfd
*isbfd
, const char *pre
)
422 struct bfd
*prebfd
= bfd_openr(pre
, NULL
);
423 assert(prebfd
!= NULL
);
425 assert(bfd_check_format_matches(prebfd
, bfd_object
, &matching
));
427 struct superbfd
*presbfd
= fetch_superbfd(prebfd
);
428 init_objmanip_superbfd(presbfd
);
430 foreach_symbol_pair(presbfd
, isbfd
, match_global_symbols
);
431 debug1(isbfd
, "Matched global\n");
432 foreach_span_pair(presbfd
, isbfd
, match_string_spans
);
433 debug1(isbfd
, "Matched string spans\n");
434 foreach_symbol_pair(presbfd
, isbfd
, match_symbol_spans
);
435 debug1(isbfd
, "Matched by name\n");
436 foreach_span_pair(presbfd
, isbfd
, match_spans_by_label
);
437 debug1(isbfd
, "Matched by label\n");
438 foreach_span_pair(presbfd
, isbfd
, match_table_spans
);
439 debug1(isbfd
, "Matched table spans\n");
443 compare_matched_spans(isbfd
);
444 update_nonzero_offsets(isbfd
);
445 mark_new_spans(isbfd
);
449 foreach_symbol_pair(presbfd
, isbfd
, check_global_symbols
);
451 handle_deleted_spans(presbfd
, isbfd
);
452 handle_section_symbol_renames(presbfd
, isbfd
);
454 assert(bfd_close(prebfd
));
458 mark_precallable_spans(isbfd
);
462 for (sect
= isbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
463 struct supersect
*ss
= fetch_supersect(isbfd
, sect
);
466 for (span
= ss
->spans
.data
;
467 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++) {
468 if (strstarts(ss
->name
, ".ksplice_options"))
470 else if (span
->new || span
->patch
|| span
->datapatch
)
474 if (span
->patch
&& span
->precallable
) {
475 err(isbfd
, "Patched span %s can be reached "
476 "by a precall function\n", span
->label
);
482 print_label_changes(isbfd
);
484 for (sect
= isbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
485 struct supersect
*ss
= fetch_supersect(isbfd
, sect
);
487 for (span
= ss
->spans
.data
;
488 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++) {
489 if (span
->patch
|| span
->bugpatch
|| span
->datapatch
)
490 debug0(isbfd
, "Patching span %s\n",
495 for (sect
= isbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
496 struct supersect
*ss
= fetch_supersect(isbfd
, sect
);
498 for (span
= ss
->spans
.data
;
499 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++) {
501 debug0(isbfd
, "New span %s\n", span
->label
);
505 write_output
= false;
506 const char **sectname
;
507 for (sectname
= delsects
.data
;
508 sectname
< delsects
.data
+ delsects
.size
; sectname
++) {
510 debug0(isbfd
, "Deleted section: %s\n", *sectname
);
513 filter_table_sections(isbfd
);
515 compute_span_shifts(isbfd
);
517 for (sect
= isbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
518 struct supersect
*ss
= fetch_supersect(isbfd
, sect
);
519 if (ss
->type
== SS_TYPE_KSPLICE_CALL
)
522 for (span
= ss
->spans
.data
;
523 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++) {
526 if (span
->patch
|| span
->new || span
->datapatch
)
527 write_ksplice_section(span
);
528 if (span
->patch
|| span
->datapatch
)
529 write_ksplice_patch(isbfd
, span
);
530 if (ss
->type
== SS_TYPE_EXPORT
&& span
->new)
531 write_ksplice_export(isbfd
, span
, false);
535 write_bugline_patches(isbfd
);
537 remove_unkept_spans(isbfd
);
540 void do_keep_old_code(struct superbfd
*isbfd
)
543 for (sect
= isbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
544 struct supersect
*ss
= fetch_supersect(isbfd
, sect
);
547 for (span
= ss
->spans
.data
;
548 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++) {
550 if (ss
->type
== SS_TYPE_TEXT
&&
551 !strstarts(ss
->name
, ".fixup"))
553 if (ss
->type
== SS_TYPE_EXPORT
)
559 for (symp
= isbfd
->syms
.data
;
560 symp
< isbfd
->syms
.data
+ isbfd
->syms
.size
; symp
++) {
561 asymbol
*sym
= *symp
;
562 if (!bfd_is_const_section(sym
->section
) &&
563 (sym
->flags
& BSF_GLOBAL
) != 0) {
564 struct supersect
*sym_ss
=
565 fetch_supersect(isbfd
, sym
->section
);
566 if (sym
->value
== sym_ss
->contents
.size
)
568 struct span
*span
= find_span(sym_ss
, sym
->value
);
569 assert(span
!= NULL
);
570 if (sym_ss
->type
!= SS_TYPE_IGNORED
)
577 keep_referenced_sections(isbfd
);
580 filter_table_sections(isbfd
);
581 compute_span_shifts(isbfd
);
583 for (sect
= isbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
584 struct supersect
*ss
= fetch_supersect(isbfd
, sect
);
585 asymbol
*sym
= canonical_symbol(isbfd
, sect
->symbol
);
588 if ((sym
->flags
& BSF_WEAK
) != 0)
590 if (bfd_get_section_size(sect
) == 0)
594 if (ss
->type
!= SS_TYPE_TEXT
&& !matchable_data_section(ss
))
598 for (span
= ss
->spans
.data
;
599 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++) {
601 write_ksplice_section(span
);
605 write_table_relocs(isbfd
, "__bug_table", KSPLICE_HOWTO_BUG
);
606 write_table_relocs(isbfd
, "__ex_table", KSPLICE_HOWTO_EXTABLE
);
608 remove_unkept_spans(isbfd
);
610 mangle_section_name(isbfd
, "__markers");
611 mangle_section_name(isbfd
, "__ex_table");
612 for (sect
= isbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
613 struct supersect
*ss
= fetch_supersect(isbfd
, sect
);
614 if (ss
->type
== SS_TYPE_EXPORT
)
615 mangle_section_name(isbfd
, ss
->name
);
619 void do_finalize(struct superbfd
*isbfd
)
621 load_ksplice_symbol_offsets(isbfd
);
623 for (sect
= isbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
624 struct supersect
*ss
= fetch_supersect(isbfd
, sect
);
625 if (ss
->type
== SS_TYPE_EXIT
) {
627 for (span
= ss
->spans
.data
;
628 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++)
633 write_date_relocs(isbfd
, "<{DATE...}>", KSPLICE_HOWTO_DATE
);
634 write_date_relocs(isbfd
, "<{TIME}>", KSPLICE_HOWTO_TIME
);
638 void do_rmsyms(struct superbfd
*isbfd
)
640 read_str_set(&rmsyms
);
644 void match_spans(struct span
*old_span
, struct span
*new_span
)
646 struct superbfd
*sbfd
= new_span
->ss
->parent
;
647 if (old_span
->match
== new_span
&& new_span
->match
== old_span
)
649 if (old_span
->match
!= NULL
) {
650 err(sbfd
, "Matching conflict: old %s: %s != %s\n",
651 old_span
->label
, old_span
->match
->label
, new_span
->label
);
654 if (new_span
->match
!= NULL
) {
655 err(sbfd
, "Matching conflict: new %s: %s != %s\n",
656 new_span
->label
, new_span
->match
->label
, old_span
->label
);
659 old_span
->match
= new_span
;
660 new_span
->match
= old_span
;
661 debug1(sbfd
, "Matched old %s to new %s\n", old_span
->label
,
663 if (old_span
->ss
->type
!= new_span
->ss
->type
&&
664 old_span
->ss
->type
== new_span
->ss
->orig_type
)
665 old_span
->ss
->type
= new_span
->ss
->type
;
667 const struct table_section
*ts
= get_table_section(old_span
->ss
->name
);
668 if (ts
== NULL
|| !ts
->has_addr
|| ts
->other_sect
== NULL
)
670 struct span
*old_sym_span
=
671 span_offset_target_span(old_span
, ts
->other_offset
);
672 struct span
*new_sym_span
=
673 span_offset_target_span(new_span
, ts
->other_offset
);
674 assert(old_sym_span
!= NULL
&& new_sym_span
!= NULL
);
675 match_spans(old_sym_span
, new_sym_span
);
678 static void match_global_symbols(struct span
*old_span
, asymbol
*oldsym
,
679 struct span
*new_span
, asymbol
*newsym
)
681 if ((oldsym
->flags
& BSF_GLOBAL
) == 0 ||
682 (newsym
->flags
& BSF_GLOBAL
) == 0)
684 match_spans(old_span
, new_span
);
687 static void check_global_symbols(struct span
*old_span
, asymbol
*oldsym
,
688 struct span
*new_span
, asymbol
*newsym
)
690 if ((oldsym
->flags
& BSF_GLOBAL
) == 0 ||
691 (newsym
->flags
& BSF_GLOBAL
) == 0)
693 if (old_span
->ss
->type
== SS_TYPE_IGNORED
)
695 if (old_span
->match
!= new_span
|| new_span
->match
!= old_span
) {
696 err(new_span
->ss
->parent
, "Global symbol span mismatch: %s "
697 "%s/%s\n", oldsym
->name
, old_span
->ss
->name
,
703 static void foreach_symbol_pair(struct superbfd
*oldsbfd
, struct superbfd
*newsbfd
,
704 void (*fn
)(struct span
*old_span
,
706 struct span
*new_span
,
709 asymbol
**oldsymp
, **newsymp
;
710 for (oldsymp
= oldsbfd
->syms
.data
;
711 oldsymp
< oldsbfd
->syms
.data
+ oldsbfd
->syms
.size
; oldsymp
++) {
712 asymbol
*oldsym
= *oldsymp
;
713 if (bfd_is_const_section(oldsym
->section
))
715 for (newsymp
= newsbfd
->syms
.data
;
716 newsymp
< newsbfd
->syms
.data
+ newsbfd
->syms
.size
;
718 asymbol
*newsym
= *newsymp
;
719 if (bfd_is_const_section(newsym
->section
))
721 if (strcmp(oldsym
->name
, newsym
->name
) != 0)
724 struct supersect
*old_ss
=
725 fetch_supersect(oldsbfd
, oldsym
->section
);
726 struct supersect
*new_ss
=
727 fetch_supersect(newsbfd
, newsym
->section
);
728 if ((old_ss
->type
!= new_ss
->type
&&
729 old_ss
->type
!= new_ss
->orig_type
) ||
730 old_ss
->type
== SS_TYPE_SPECIAL
||
731 old_ss
->type
== SS_TYPE_EXPORT
)
734 struct span
*old_span
=
735 find_span(old_ss
, oldsym
->value
);
736 struct span
*new_span
=
737 find_span(new_ss
, newsym
->value
);
738 if (old_span
== NULL
) {
739 err(oldsbfd
, "Could not find span for %s\n",
743 if (new_span
== NULL
) {
744 err(newsbfd
, "Could not find span for %s\n",
748 fn(old_span
, oldsym
, new_span
, newsym
);
753 static void match_symbol_spans(struct span
*old_span
, asymbol
*oldsym
,
754 struct span
*new_span
, asymbol
*newsym
)
756 if ((oldsym
->flags
& BSF_DEBUGGING
) != 0 ||
757 (newsym
->flags
& BSF_DEBUGGING
) != 0)
759 if (old_span
->ss
->type
== SS_TYPE_SPECIAL
)
761 if (static_local_symbol(old_span
->ss
->parent
, oldsym
) ||
762 static_local_symbol(new_span
->ss
->parent
, newsym
))
764 if (old_span
->match
== NULL
&& new_span
->match
== NULL
)
765 match_spans(old_span
, new_span
);
768 static void match_spans_by_label(struct span
*old_span
, struct span
*new_span
)
770 if (old_span
->ss
->type
== SS_TYPE_STRING
||
771 (is_table_section(old_span
->ss
->name
, true, false) &&
772 !is_table_section(old_span
->ss
->name
, false, false)))
774 if (strcmp(old_span
->label
, new_span
->label
) == 0)
775 match_spans(old_span
, new_span
);
778 static void match_string_spans(struct span
*old_span
, struct span
*new_span
)
780 if (old_span
->ss
->type
!= SS_TYPE_STRING
||
781 strcmp(old_span
->ss
->name
, new_span
->ss
->name
) != 0)
783 if (strcmp((char *)old_span
->ss
->contents
.data
+ old_span
->start
,
784 (char *)new_span
->ss
->contents
.data
+ new_span
->start
) == 0)
785 match_spans(old_span
, new_span
);
788 static void foreach_span_pair(struct superbfd
*oldsbfd
,
789 struct superbfd
*newsbfd
,
790 void (*fn
)(struct span
*old_span
,
791 struct span
*new_span
))
793 asection
*oldsect
, *newsect
;
794 struct supersect
*oldss
, *newss
;
795 struct span
*old_span
, *new_span
;
796 for (newsect
= newsbfd
->abfd
->sections
; newsect
!= NULL
;
797 newsect
= newsect
->next
) {
798 newss
= fetch_supersect(newsbfd
, newsect
);
799 for (oldsect
= oldsbfd
->abfd
->sections
; oldsect
!= NULL
;
800 oldsect
= oldsect
->next
) {
801 oldss
= fetch_supersect(oldsbfd
, oldsect
);
802 if (oldss
->type
!= newss
->type
)
804 for (new_span
= newss
->spans
.data
;
805 new_span
< newss
->spans
.data
+ newss
->spans
.size
;
807 for (old_span
= oldss
->spans
.data
;
808 old_span
< oldss
->spans
.data
+
809 oldss
->spans
.size
; old_span
++)
810 fn(old_span
, new_span
);
816 static void mark_new_spans(struct superbfd
*sbfd
)
819 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
820 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
821 if (ss
->type
== SS_TYPE_SPECIAL
|| ss
->type
== SS_TYPE_IGNORED
)
824 for (span
= ss
->spans
.data
;
825 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++) {
826 if (span
->match
== NULL
&& !span
->bugpatch
)
832 static void handle_deleted_spans(struct superbfd
*oldsbfd
,
833 struct superbfd
*newsbfd
)
836 for (sect
= oldsbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
837 struct supersect
*ss
= fetch_supersect(oldsbfd
, sect
);
839 for (span
= ss
->spans
.data
;
840 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++) {
841 if (span
->match
!= NULL
)
843 if (ss
->type
== SS_TYPE_EXPORT
) {
844 *vec_grow(&delsects
, 1) = span
->label
;
845 write_ksplice_export(newsbfd
, span
, true);
846 } else if (ss
->type
== SS_TYPE_TEXT
) {
847 *vec_grow(&delsects
, 1) = span
->label
;
848 if (span
->symbol
== NULL
)
850 write_ksplice_deleted_patch
851 (newsbfd
, span
->symbol
->name
, span
->label
,
858 static void handle_nonzero_offset_relocs(struct supersect
*ss
)
860 struct span
*address_span
, *target_span
;
862 for (relocp
= ss
->relocs
.data
;
863 relocp
< ss
->relocs
.data
+ ss
->relocs
.size
; relocp
++) {
864 arelent
*reloc
= *relocp
;
865 address_span
= find_span(ss
, reloc
->address
);
866 if (!address_span
->new && !address_span
->patch
)
869 asymbol
*sym
= *reloc
->sym_ptr_ptr
;
870 if (bfd_is_const_section(sym
->section
))
872 bfd_vma offset
= reloc_target_offset(ss
, reloc
);
873 target_span
= reloc_target_span(ss
, reloc
);
874 if (sym
->value
+ offset
== target_span
->start
)
877 if (target_span
->ss
->type
!= SS_TYPE_TEXT
)
879 if (target_span
->patch
)
882 target_span
->patch
= true;
884 debug1(ss
->parent
, "Changing %s because a relocation from sect "
885 "%s has a nonzero offset %lx+%lx into it\n",
886 target_span
->label
, ss
->name
, (unsigned long)sym
->value
,
887 (unsigned long)offset
);
891 static void update_nonzero_offsets(struct superbfd
*sbfd
)
894 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
895 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
896 if (ss
->type
== SS_TYPE_SPECIAL
|| ss
->type
== SS_TYPE_IGNORED
)
898 handle_nonzero_offset_relocs(ss
);
902 static void unmatch_addr_spans(struct span
*old_span
, struct span
*new_span
,
903 const struct table_section
*ts
)
905 struct span
*old_sym_span
=
906 span_offset_target_span(old_span
, ts
->addr_offset
);
907 struct span
*new_sym_span
=
908 span_offset_target_span(new_span
, ts
->addr_offset
);
909 assert(old_sym_span
!= NULL
&& new_sym_span
!= NULL
);
910 if (old_sym_span
->match
== new_sym_span
&&
911 new_sym_span
->match
== old_sym_span
&&
912 !(new_sym_span
->patch
&& new_sym_span
->ss
->type
== SS_TYPE_TEXT
)) {
913 if (old_sym_span
->ss
->type
== SS_TYPE_TEXT
) {
914 debug1(new_span
->ss
->parent
, "Patching %s due "
915 "to relocations from special section %s\n",
916 new_sym_span
->label
, new_span
->label
);
917 new_sym_span
->patch
= true;
919 debug1(new_span
->ss
->parent
, "Unmatching %s and %s due "
920 "to relocations from special section %s/%s\n",
921 old_sym_span
->label
, new_sym_span
->label
,
922 old_span
->label
, new_span
->label
);
923 old_sym_span
->match
= NULL
;
924 new_sym_span
->match
= NULL
;
930 static void compare_spans(struct span
*old_span
, struct span
*new_span
)
932 struct superbfd
*newsbfd
= new_span
->ss
->parent
;
934 bool nonrelocs_match
= nonrelocs_equal(old_span
, new_span
);
935 bool relocs_match
= all_relocs_equal(old_span
, new_span
);
936 if (nonrelocs_match
&& relocs_match
) {
937 const struct table_section
*ts
=
938 get_table_section(old_span
->ss
->name
);
939 if (ts
!= NULL
&& ts
->crc_sect
!= NULL
) {
940 struct span
*old_crc_span
= get_crc_span(old_span
, ts
);
941 struct span
*new_crc_span
= get_crc_span(new_span
, ts
);
942 assert(old_crc_span
!= NULL
);
943 assert(new_crc_span
!= NULL
);
944 if (old_crc_span
->match
!= new_crc_span
||
945 new_crc_span
->match
!= old_crc_span
) {
946 debug1(newsbfd
, "Unmatching %s and %s due to "
947 "nonmatching CRCs\n", old_span
->label
,
949 old_span
->match
= NULL
;
950 new_span
->match
= NULL
;
955 if (strcmp(old_span
->ss
->name
, "__bug_table") == 0 &&
956 strcmp(new_span
->ss
->name
, "__bug_table") == 0 && relocs_match
) {
957 debug1(newsbfd
, "Changing %s due to nonmatching line numbers\n",
959 new_span
->match
= NULL
;
960 old_span
->match
= NULL
;
961 new_span
->bugpatch
= true;
966 if (new_span
->contents_size
!= old_span
->contents_size
)
967 reason
= "differing sizes";
968 else if (!nonrelocs_match
)
969 reason
= "differing contents";
971 reason
= "differing relocations";
973 if (new_span
->ss
->type
== SS_TYPE_TEXT
) {
976 new_span
->patch
= true;
977 debug1(newsbfd
, "Changing %s due to %s\n", new_span
->label
,
979 } else if (new_span
->ss
->type
== SS_TYPE_RODATA
&&
980 new_span
->contents_size
== old_span
->contents_size
) {
981 if (new_span
->datapatch
)
983 new_span
->datapatch
= true;
984 debug1(newsbfd
, "Changing %s in-place due to %s\n",
985 new_span
->label
, reason
);
986 } else if (new_span
->ss
->type
== SS_TYPE_STRING
&&
987 old_span
->ss
->type
== SS_TYPE_STRING
&& relocs_match
&&
988 strcmp(new_span
->ss
->contents
.data
+ new_span
->start
,
989 old_span
->ss
->contents
.data
+ old_span
->start
) == 0) {
992 debug1(newsbfd
, "Unmatching %s and %s due to %s\n",
993 old_span
->label
, new_span
->label
, reason
);
994 new_span
->match
= NULL
;
995 old_span
->match
= NULL
;
996 if (old_span
->ss
->type
== SS_TYPE_SPECIAL
) {
997 const struct table_section
*ts
=
998 get_table_section(old_span
->ss
->name
);
999 if (ts
!= NULL
&& ts
->has_addr
)
1000 unmatch_addr_spans(old_span
, new_span
, ts
);
1004 if (unchangeable_section(new_span
->ss
))
1005 err(newsbfd
, "warning: ignoring change to nonpatchable "
1006 "section %s\n", new_span
->ss
->name
);
1009 static void compare_matched_spans(struct superbfd
*newsbfd
)
1012 for (sect
= newsbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
1013 struct supersect
*ss
= fetch_supersect(newsbfd
, sect
);
1015 for (span
= ss
->spans
.data
;
1016 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++) {
1017 if (span
->match
== NULL
)
1019 compare_spans(span
->match
, span
);
1024 static void handle_section_symbol_renames(struct superbfd
*oldsbfd
,
1025 struct superbfd
*newsbfd
)
1029 for (sect
= newsbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
1030 struct supersect
*ss
= fetch_supersect(newsbfd
, sect
);
1031 for (span
= ss
->spans
.data
;
1032 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++) {
1033 if (span
->match
== NULL
)
1035 if (strcmp(span
->label
, span
->match
->label
) == 0)
1037 if (strcmp(span
->orig_label
, span
->label
) != 0 &&
1038 strcmp(span
->label
, span
->match
->label
) != 0)
1040 if (span
->symbol
!= NULL
)
1041 label_map_set(newsbfd
, span
->label
,
1042 span
->match
->label
);
1043 span
->label
= span
->match
->label
;
1048 static bool part_of_reloc(struct supersect
*ss
, unsigned long addr
)
1051 for (relocp
= ss
->relocs
.data
;
1052 relocp
< ss
->relocs
.data
+ ss
->relocs
.size
; relocp
++) {
1053 arelent
*reloc
= *relocp
;
1054 if (addr
>= reloc
->address
&&
1055 addr
< reloc
->address
+ bfd_get_reloc_size(reloc
->howto
))
1061 static bool nonrelocs_equal(struct span
*old_span
, struct span
*new_span
)
1064 struct supersect
*old_ss
= old_span
->ss
, *new_ss
= new_span
->ss
;
1065 if (old_span
->contents_size
!= new_span
->contents_size
)
1067 const unsigned char *old
= old_ss
->contents
.data
+ old_span
->start
;
1068 const unsigned char *new = new_ss
->contents
.data
+ new_span
->start
;
1069 for (i
= 0; i
< old_span
->contents_size
; i
++) {
1070 if (old
[i
] != new[i
] &&
1071 !(part_of_reloc(old_ss
, i
+ old_span
->start
) &&
1072 part_of_reloc(new_ss
, i
+ new_span
->start
)))
1078 bool relocs_equal(struct supersect
*old_src_ss
, struct supersect
*new_src_ss
,
1079 arelent
*old_reloc
, arelent
*new_reloc
)
1081 struct superbfd
*oldsbfd
= old_src_ss
->parent
;
1082 struct superbfd
*newsbfd
= new_src_ss
->parent
;
1083 struct span
*old_addr_span
= find_span(old_src_ss
, old_reloc
->address
);
1084 struct span
*new_addr_span
= find_span(new_src_ss
, new_reloc
->address
);
1086 if (old_reloc
->address
- old_addr_span
->start
!=
1087 new_reloc
->address
- new_addr_span
->start
) {
1088 debug1(newsbfd
, "Section %s/%s has reloc address mismatch at "
1089 "%lx\n", old_src_ss
->name
, new_src_ss
->name
,
1090 (unsigned long)old_reloc
->address
);
1094 if (old_reloc
->howto
!= new_reloc
->howto
) {
1095 debug1(newsbfd
, "Section %s/%s has howto type mismatch at "
1096 "%lx\n", old_src_ss
->name
, new_src_ss
->name
,
1097 (unsigned long)old_reloc
->address
);
1101 if (non_dst_mask(old_src_ss
, old_reloc
) !=
1102 non_dst_mask(new_src_ss
, new_reloc
)) {
1103 debug1(newsbfd
, "Section %s/%s has contents mismatch at %lx\n",
1104 old_src_ss
->name
, new_src_ss
->name
,
1105 (unsigned long)old_reloc
->address
);
1109 asymbol
*old_sym
= *old_reloc
->sym_ptr_ptr
;
1110 asymbol
*new_sym
= *new_reloc
->sym_ptr_ptr
;
1111 asection
*old_sect
= old_sym
->section
;
1112 asection
*new_sect
= new_sym
->section
;
1114 bfd_vma old_offset
= reloc_target_offset(old_src_ss
, old_reloc
);
1115 bfd_vma new_offset
= reloc_target_offset(new_src_ss
, new_reloc
);
1117 if (bfd_is_und_section(old_sect
) || bfd_is_und_section(new_sect
)) {
1118 if (!bfd_is_und_section(new_sect
) && old_offset
!= 0 &&
1119 fetch_supersect(newsbfd
, new_sect
)->type
== SS_TYPE_TEXT
)
1122 if (!bfd_is_und_section(new_sect
) && new_offset
!= 0 &&
1123 fetch_supersect(oldsbfd
, old_sect
)->type
== SS_TYPE_TEXT
)
1126 return strcmp(old_sym
->name
, new_sym
->name
) == 0 &&
1127 old_offset
== new_offset
;
1130 if (bfd_is_abs_section(old_sect
) && bfd_is_abs_section(new_sect
)) {
1131 if (old_sym
->value
+ old_offset
== new_sym
->value
+ new_offset
)
1133 debug1(newsbfd
, "Differing relocations from %s/%s to ABS "
1134 "section: %lx/%lx\n", old_addr_span
->label
,
1135 new_addr_span
->label
,
1136 (unsigned long)(old_sym
->value
+ old_offset
),
1137 (unsigned long)(new_sym
->value
+ new_offset
));
1141 if (bfd_is_const_section(old_sect
) || bfd_is_const_section(new_sect
))
1144 struct supersect
*old_ss
= fetch_supersect(oldsbfd
, old_sect
);
1145 struct supersect
*new_ss
= fetch_supersect(newsbfd
, new_sect
);
1146 struct span
*old_span
= reloc_target_span(old_src_ss
, old_reloc
);
1147 struct span
*new_span
= reloc_target_span(new_src_ss
, new_reloc
);
1149 if (old_span
->match
!= new_span
|| new_span
->match
!= old_span
) {
1150 debug1(newsbfd
, "Nonmatching relocs from %s to %s/%s\n",
1151 new_src_ss
->name
, old_span
->label
, new_span
->label
);
1155 if (old_sym
->value
+ old_offset
- old_span
->start
!=
1156 new_sym
->value
+ new_offset
- new_span
->start
) {
1157 debug1(newsbfd
, "Offsets to %s/%s differ between %s "
1158 "and %s: %lx+%lx/%lx+%lx\n", old_ss
->name
,
1159 new_ss
->name
, old_src_ss
->name
, new_src_ss
->name
,
1160 (unsigned long)old_sym
->value
, (unsigned long)old_offset
,
1161 (unsigned long)new_sym
->value
,
1162 (unsigned long)new_offset
);
1166 if ((old_sym
->value
+ old_offset
- old_span
->start
!= 0 ||
1167 new_sym
->value
+ new_offset
- new_span
->start
!= 0) &&
1169 debug1(newsbfd
, "Relocation from %s to nonzero offsets "
1170 "%lx+%lx/%lx+%lx in changed section %s\n",
1171 new_src_ss
->name
, (unsigned long)old_sym
->value
,
1172 (unsigned long)old_offset
, (unsigned long)new_sym
->value
,
1173 (unsigned long)new_offset
, new_sym
->section
->name
);
1179 bool all_relocs_equal(struct span
*old_span
, struct span
*new_span
)
1181 struct supersect
*old_ss
= old_span
->ss
, *new_ss
= new_span
->ss
;
1182 arelent
**old_relocp
, **new_relocp
;
1184 for (old_relocp
= old_ss
->relocs
.data
;
1185 old_relocp
< old_ss
->relocs
.data
+ old_ss
->relocs
.size
;
1187 if (find_span(old_ss
, (*old_relocp
)->address
) == old_span
)
1191 for (new_relocp
= new_ss
->relocs
.data
;
1192 new_relocp
< new_ss
->relocs
.data
+ new_ss
->relocs
.size
;
1194 if (find_span(new_ss
, (*new_relocp
)->address
) == new_span
)
1198 for (; old_relocp
< old_ss
->relocs
.data
+ old_ss
->relocs
.size
&&
1199 find_span(old_ss
, (*old_relocp
)->address
) == old_span
&&
1200 new_relocp
< new_ss
->relocs
.data
+ new_ss
->relocs
.size
&&
1201 find_span(new_ss
, (*new_relocp
)->address
) == new_span
;
1202 old_relocp
++, new_relocp
++) {
1203 if (!relocs_equal(old_ss
, new_ss
, *old_relocp
, *new_relocp
))
1207 if ((old_relocp
< old_ss
->relocs
.data
+ old_ss
->relocs
.size
&&
1208 find_span(old_ss
, (*old_relocp
)->address
) == old_span
) ||
1209 (new_relocp
< new_ss
->relocs
.data
+ new_ss
->relocs
.size
&&
1210 find_span(new_ss
, (*new_relocp
)->address
) == new_span
)) {
1211 debug1(new_ss
->parent
, "Different reloc count between %s and "
1212 "%s\n", old_span
->label
, new_span
->label
);
1219 bfd_vma
non_dst_mask(struct supersect
*ss
, arelent
*reloc
)
1221 int bits
= bfd_get_reloc_size(reloc
->howto
) * 8;
1222 void *address
= ss
->contents
.data
+ reloc
->address
;
1223 bfd_vma x
= bfd_get(bits
, ss
->parent
->abfd
, address
);
1224 return x
& ~reloc
->howto
->dst_mask
;
1227 void rm_relocs(struct superbfd
*isbfd
)
1230 for (p
= isbfd
->abfd
->sections
; p
!= NULL
; p
= p
->next
) {
1231 struct supersect
*ss
= fetch_supersect(isbfd
, p
);
1232 bool remove_relocs
= ss
->keep
;
1234 if (mode("keep") && ss
->type
== SS_TYPE_SPECIAL
)
1235 remove_relocs
= false;
1237 if (ss
->type
== SS_TYPE_KSPLICE
||
1238 ss
->type
== SS_TYPE_KSPLICE_CALL
)
1239 remove_relocs
= false;
1240 if (mode("finalize") &&
1241 (strstarts(ss
->name
, ".ksplice_patches") ||
1242 strstarts(ss
->name
, ".ksplice_relocs")))
1243 remove_relocs
= true;
1250 void rm_some_relocs(struct supersect
*ss
)
1252 struct arelentp_vec orig_relocs
;
1253 vec_move(&orig_relocs
, &ss
->relocs
);
1256 for (relocp
= orig_relocs
.data
;
1257 relocp
< orig_relocs
.data
+ orig_relocs
.size
; relocp
++) {
1258 bool rm_reloc
= false;
1259 asymbol
*sym_ptr
= *(*relocp
)->sym_ptr_ptr
;
1261 if (mode("rmsyms") && str_in_set(sym_ptr
->name
, &rmsyms
) &&
1262 bfd_is_und_section(sym_ptr
->section
))
1268 if (mode("keep-new-code")) {
1269 if (bfd_is_const_section(sym_ptr
->section
)) {
1272 bfd_vma offset
= reloc_target_offset(ss
, *relocp
);
1273 struct span
*target_span
=
1274 reloc_target_span(ss
, *relocp
);
1275 if (target_span
->new ||
1276 (target_span
->ss
->type
== SS_TYPE_TEXT
&&
1277 sym_ptr
->value
+ offset
!=
1278 target_span
->start
))
1282 const struct table_section
*ts
=
1283 get_table_section(ss
->name
);
1284 if (ts
!= NULL
&& ts
->has_addr
&&
1285 ((*relocp
)->address
% ts
->entry_size
==
1287 (*relocp
)->address
% ts
->entry_size
==
1292 if (mode("finalize") && bfd_is_und_section(sym_ptr
->section
))
1295 if (strcmp(sym_ptr
->name
, "mcount") == 0 &&
1296 bfd_is_und_section(sym_ptr
->section
))
1299 if (!find_span(ss
, (*relocp
)->address
)->keep
)
1303 write_ksplice_reloc(ss
, *relocp
);
1305 *vec_grow(&ss
->relocs
, 1) = *relocp
;
1309 struct supersect
*make_section(struct superbfd
*sbfd
, const char *fmt
, ...)
1313 char *name
= vstrprintf(fmt
, ap
);
1316 asection
*sect
= bfd_get_section_by_name(sbfd
->abfd
, name
);
1318 return fetch_supersect(sbfd
, sect
);
1320 return new_supersect(sbfd
, name
);
1323 arelent
*create_reloc(struct supersect
*ss
, const void *addr
, asymbol
**symp
,
1326 bfd_reloc_code_real_type code
;
1327 switch (bfd_arch_bits_per_address(ss
->parent
->abfd
)) {
1329 code
= BFD_RELOC_32
;
1332 code
= BFD_RELOC_64
;
1338 arelent
*reloc
= malloc(sizeof(*reloc
));
1339 reloc
->sym_ptr_ptr
= symp
;
1340 reloc
->address
= addr_offset(ss
, addr
);
1341 reloc
->howto
= bfd_reloc_type_lookup(ss
->parent
->abfd
, code
);
1342 reloc
->addend
= offset
;
1346 void write_reloc(struct supersect
*ss
, const void *addr
, asymbol
**symp
,
1349 *vec_grow(&ss
->new_relocs
, 1) = create_reloc(ss
, addr
, symp
, offset
);
1352 void write_string(struct supersect
*ss
, const char **addr
, const char *fmt
, ...)
1355 struct supersect
*str_ss
= make_section(ss
->parent
, ".ksplice_str");
1358 int len
= vasprintf(&str
, fmt
, ap
);
1362 unsigned long *str_offp
= ulong_hash_lookup(&ksplice_string_offset
, str
,
1364 if (str_offp
== NULL
) {
1365 char *buf
= sect_grow(str_ss
, len
+ 1, char);
1366 memcpy(buf
, str
, len
+ 1);
1367 str_offp
= ulong_hash_lookup(&ksplice_string_offset
, str
, TRUE
);
1368 *str_offp
= addr_offset(str_ss
, buf
);
1371 write_reloc(ss
, addr
, &str_ss
->symbol
, *str_offp
);
1374 void lookup_system_map(struct addr_vec
*addrs
, const char *name
, long offset
)
1376 struct addr_vec
*map_addrs
=
1377 addr_vec_hash_lookup(&system_map
, name
, FALSE
);
1378 if (map_addrs
== NULL
)
1381 unsigned long *addr
, *map_addr
;
1382 for (map_addr
= map_addrs
->data
;
1383 map_addr
< map_addrs
->data
+ map_addrs
->size
; map_addr
++) {
1384 for (addr
= addrs
->data
; addr
< addrs
->data
+ addrs
->size
;
1386 if (*addr
== *map_addr
+ offset
)
1389 if (addr
< addrs
->data
+ addrs
->size
)
1391 *vec_grow(addrs
, 1) = *map_addr
+ offset
;
1395 void compute_system_map_array(struct superbfd
*sbfd
, struct addr_vec
*addrs
,
1398 if (bfd_is_abs_section(sym
->section
)) {
1399 *vec_grow(addrs
, 1) = sym
->value
;
1400 } else if (bfd_is_und_section(sym
->section
)) {
1401 lookup_system_map(addrs
, sym
->name
, 0);
1402 } else if (!bfd_is_const_section(sym
->section
)) {
1404 for (gsymp
= sbfd
->syms
.data
;
1405 gsymp
< sbfd
->syms
.data
+ sbfd
->syms
.size
; gsymp
++) {
1406 asymbol
*gsym
= *gsymp
;
1407 if ((gsym
->flags
& BSF_DEBUGGING
) == 0 &&
1408 gsym
->section
== sym
->section
)
1409 lookup_system_map(addrs
, gsym
->name
,
1410 sym
->value
- gsym
->value
);
1415 void write_ksplice_system_map(struct superbfd
*sbfd
, asymbol
*sym
,
1418 bool *done
= bool_hash_lookup(&system_map_written
, label
, TRUE
);
1423 struct addr_vec addrs
;
1426 compute_system_map_array(sbfd
, &addrs
, sym
);
1427 if (addrs
.size
!= 0) {
1428 struct supersect
*smap_ss
=
1429 make_section(sbfd
, ".ksplice_system_map");
1430 struct ksplice_system_map
*smap
=
1431 sect_grow(smap_ss
, 1, struct ksplice_system_map
);
1432 write_string(smap_ss
, &smap
->label
, "%s", label
);
1434 struct supersect
*array_ss
= make_section(sbfd
,
1436 void *buf
= sect_grow(array_ss
, addrs
.size
,
1437 typeof(*addrs
.data
));
1438 memcpy(buf
, addrs
.data
, addrs
.size
* sizeof(*addrs
.data
));
1439 smap
->nr_candidates
= addrs
.size
;
1440 write_reloc(smap_ss
, &smap
->candidates
, &array_ss
->symbol
,
1441 addr_offset(array_ss
, buf
));
1446 void write_ksplice_symbol_backend(struct supersect
*ss
,
1447 struct ksplice_symbol
*const *addr
,
1448 asymbol
*sym
, const char *label
,
1451 struct supersect
*ksymbol_ss
= make_section(ss
->parent
,
1452 ".ksplice_symbols");
1453 struct ksplice_symbol
*ksymbol
;
1454 unsigned long *ksymbol_offp
;
1456 ksymbol_offp
= ulong_hash_lookup(&ksplice_symbol_offset
, label
, FALSE
);
1457 if (ksymbol_offp
!= NULL
) {
1458 write_reloc(ss
, addr
, &ksymbol_ss
->symbol
, *ksymbol_offp
);
1461 ksymbol
= sect_grow(ksymbol_ss
, 1, struct ksplice_symbol
);
1462 ksymbol_offp
= ulong_hash_lookup(&ksplice_symbol_offset
, label
, TRUE
);
1463 *ksymbol_offp
= addr_offset(ksymbol_ss
, ksymbol
);
1465 write_reloc(ss
, addr
, &ksymbol_ss
->symbol
, *ksymbol_offp
);
1466 write_string(ksymbol_ss
, &ksymbol
->label
, "%s", label
);
1468 write_string(ksymbol_ss
, &ksymbol
->name
, "%s", name
);
1469 write_ksplice_system_map(ksymbol_ss
->parent
, sym
, label
);
1473 void write_ksplice_symbol(struct supersect
*ss
,
1474 struct ksplice_symbol
*const *addr
,
1475 asymbol
*sym
, struct span
*span
,
1476 const char *addstr_sect
)
1478 const char *label
, *name
;
1479 if (span
!= NULL
&& span
->start
!= 0)
1480 label
= span
->label
;
1482 label
= label_lookup(ss
->parent
, sym
);
1484 asymbol
*gsym
= canonical_symbol(ss
->parent
, sym
);
1485 if (strcmp(addstr_sect
, "") != 0)
1487 else if (bfd_is_und_section(sym
->section
))
1489 else if (bfd_is_const_section(sym
->section
))
1491 else if (span
!= NULL
&& span
->symbol
== NULL
)
1493 else if (gsym
== NULL
|| (gsym
->flags
& BSF_SECTION_SYM
) != 0)
1498 write_ksplice_symbol_backend(ss
, addr
, sym
,
1499 strprintf("%s%s", addstr_sect
, label
),
1503 void write_ksplice_reloc(struct supersect
*ss
, arelent
*orig_reloc
)
1505 asymbol
*sym_ptr
= *orig_reloc
->sym_ptr_ptr
;
1506 bfd_vma reloc_addend
= reloc_offset(ss
, orig_reloc
);
1507 bfd_vma target_addend
= reloc_target_offset(ss
, orig_reloc
);
1508 unsigned long *repladdr
= ss
->contents
.data
+ orig_reloc
->address
;
1510 if (mode("finalize") && strstarts(ss
->name
, ".ksplice_patches")) {
1514 if (mode("finalize") && strstarts(ss
->name
, ".ksplice_relocs")) {
1515 assert(strstarts(sym_ptr
->name
, KSPLICE_SYMBOL_STR
));
1517 fake_sym
.name
= sym_ptr
->name
+ strlen(KSPLICE_SYMBOL_STR
);
1518 fake_sym
.section
= bfd_und_section_ptr
;
1522 write_ksplice_symbol_backend
1523 (ss
, (struct ksplice_symbol
**)repladdr
, &fake_sym
,
1524 fake_sym
.name
, fake_sym
.name
);
1528 struct span
*span
= reloc_target_span(ss
, orig_reloc
);
1529 if (span
== ss
->spans
.data
&& span
->start
!= target_addend
)
1531 write_canary(ss
, orig_reloc
->address
,
1532 bfd_get_reloc_size(orig_reloc
->howto
),
1533 orig_reloc
->howto
->dst_mask
);
1535 struct supersect
*kreloc_ss
;
1537 kreloc_ss
= make_section(ss
->parent
, ".ksplice_init_relocs");
1539 kreloc_ss
= make_section(ss
->parent
, ".ksplice_relocs%s",
1541 struct ksplice_reloc
*kreloc
= sect_grow(kreloc_ss
, 1,
1542 struct ksplice_reloc
);
1544 struct span
*address_span
= find_span(ss
, orig_reloc
->address
);
1545 write_reloc(kreloc_ss
, &kreloc
->blank_addr
,
1546 &ss
->symbol
, orig_reloc
->address
+ address_span
->shift
);
1547 if (bfd_is_und_section(sym_ptr
->section
) && mode("keep")) {
1548 char *name
= strprintf(KSPLICE_SYMBOL_STR
"%s", sym_ptr
->name
);
1549 asymbol
**symp
= make_undefined_symbolp(ss
->parent
, name
);
1550 write_reloc(kreloc_ss
, &kreloc
->symbol
, symp
, 0);
1552 write_ksplice_symbol(kreloc_ss
, &kreloc
->symbol
, sym_ptr
, span
,
1555 if (span
!= NULL
&& span
->start
!= 0) {
1556 reloc_addend
+= sym_ptr
->value
- span
->start
;
1557 target_addend
+= sym_ptr
->value
- span
->start
;
1559 kreloc
->insn_addend
= reloc_addend
- target_addend
;
1560 kreloc
->target_addend
= target_addend
;
1561 write_ksplice_reloc_howto(kreloc_ss
, &kreloc
->howto
, orig_reloc
->howto
,
1562 KSPLICE_HOWTO_RELOC
);
1565 static void write_ksplice_reloc_howto(struct supersect
*ss
, const
1566 struct ksplice_reloc_howto
*const *addr
,
1567 reloc_howto_type
*howto
,
1568 enum ksplice_reloc_howto_type type
)
1570 struct supersect
*khowto_ss
= make_section(ss
->parent
,
1571 ".ksplice_reloc_howtos");
1572 struct ksplice_reloc_howto
*khowto
;
1573 unsigned long *khowto_offp
;
1575 khowto_offp
= ulong_hash_lookup(&ksplice_howto_offset
, howto
->name
,
1577 if (khowto_offp
!= NULL
) {
1578 write_reloc(ss
, addr
, &khowto_ss
->symbol
, *khowto_offp
);
1581 khowto
= sect_grow(khowto_ss
, 1, struct ksplice_reloc_howto
);
1582 khowto_offp
= ulong_hash_lookup(&ksplice_howto_offset
, howto
->name
,
1584 *khowto_offp
= addr_offset(khowto_ss
, khowto
);
1586 khowto
->type
= type
;
1587 khowto
->pcrel
= howto
->pc_relative
;
1588 khowto
->size
= bfd_get_reloc_size(howto
);
1589 khowto
->dst_mask
= howto
->dst_mask
;
1590 khowto
->rightshift
= howto
->rightshift
;
1591 khowto
->signed_addend
=
1592 (howto
->complain_on_overflow
== complain_overflow_signed
) ||
1593 (howto
->complain_on_overflow
== complain_overflow_bitfield
);
1594 write_reloc(ss
, addr
, &khowto_ss
->symbol
, *khowto_offp
);
1597 #define CANARY(x, canary) ((x & ~howto->dst_mask) | (canary & howto->dst_mask))
1599 void write_canary(struct supersect
*ss
, int offset
, bfd_size_type size
,
1602 int bits
= size
* 8;
1603 void *address
= ss
->contents
.data
+ offset
;
1604 bfd_vma x
= bfd_get(bits
, ss
->parent
->abfd
, address
);
1605 x
= (x
& ~dst_mask
) | ((bfd_vma
)KSPLICE_CANARY
& dst_mask
);
1606 bfd_put(bits
, ss
->parent
->abfd
, x
, address
);
1609 static void write_date_relocs(struct superbfd
*sbfd
, const char *str
,
1610 enum ksplice_reloc_howto_type type
)
1613 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
1614 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
1615 if (ss
->type
!= SS_TYPE_STRING
&& ss
->type
!= SS_TYPE_RODATA
)
1619 for (span
= ss
->spans
.data
;
1620 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++) {
1623 for (ptr
= ss
->contents
.data
+ span
->start
;
1624 ptr
+ strlen(str
) < ss
->contents
.data
+
1625 span
->start
+ span
->contents_size
; ptr
++) {
1626 if (strcmp((const char *)ptr
, str
) == 0)
1627 write_ksplice_date_reloc
1628 (ss
, addr_offset(ss
, ptr
), str
,
1635 static void write_ksplice_date_reloc(struct supersect
*ss
, unsigned long offset
,
1637 enum ksplice_reloc_howto_type type
)
1639 struct supersect
*kreloc_ss
;
1640 kreloc_ss
= make_section(ss
->parent
, ".ksplice_relocs%s", ss
->name
);
1641 struct ksplice_reloc
*kreloc
= sect_grow(kreloc_ss
, 1,
1642 struct ksplice_reloc
);
1644 const char *filename
= ss
->parent
->abfd
->filename
;
1645 char *c
= strstr(filename
, ".KSPLICE");
1646 int flen
= (c
== NULL
? strlen(filename
) : c
- filename
);
1648 write_ksplice_symbol_backend(kreloc_ss
, &kreloc
->symbol
, NULL
,
1649 strprintf("%s<%.*s>", str
, flen
, filename
),
1652 struct span
*span
= find_span(ss
, offset
);
1653 write_reloc(kreloc_ss
, &kreloc
->blank_addr
, &ss
->symbol
,
1654 offset
+ span
->shift
);
1655 write_ksplice_nonreloc_howto(kreloc_ss
, &kreloc
->howto
, type
,
1659 static void write_table_relocs(struct superbfd
*sbfd
, const char *sectname
,
1660 enum ksplice_reloc_howto_type type
)
1662 asection
*sect
= bfd_get_section_by_name(sbfd
->abfd
, sectname
);
1665 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
1667 const struct table_section
*s
= get_table_section(sectname
);
1672 for (entry
= ss
->contents
.data
;
1673 entry
< ss
->contents
.data
+ ss
->contents
.size
;
1674 entry
+= s
->entry_size
) {
1675 struct span
*span
= find_span(ss
, addr_offset(ss
, entry
));
1676 assert(span
!= NULL
);
1680 arelent
*reloc
= find_reloc(ss
, entry
+ s
->addr_offset
);
1681 assert(reloc
!= NULL
);
1682 asymbol
*sym
= *reloc
->sym_ptr_ptr
;
1683 assert(!bfd_is_const_section(sym
->section
));
1684 struct supersect
*sym_ss
= fetch_supersect(sbfd
, sym
->section
);
1685 unsigned long addr
= sym
->value
+
1686 reloc_target_offset(ss
, reloc
);
1687 write_ksplice_table_reloc(sym_ss
, addr
, span
->label
, type
);
1691 static void write_ksplice_table_reloc(struct supersect
*ss
,
1692 unsigned long address
,
1694 enum ksplice_reloc_howto_type type
)
1696 struct supersect
*kreloc_ss
;
1697 kreloc_ss
= make_section(ss
->parent
, ".ksplice_relocs%s", ss
->name
);
1698 struct ksplice_reloc
*kreloc
= sect_grow(kreloc_ss
, 1,
1699 struct ksplice_reloc
);
1700 struct span
*span
= find_span(ss
, address
);
1701 assert(span
!= NULL
);
1703 write_ksplice_symbol_backend(kreloc_ss
, &kreloc
->symbol
, NULL
,
1705 write_reloc(kreloc_ss
, &kreloc
->blank_addr
, &ss
->symbol
,
1706 address
+ span
->shift
);
1707 write_ksplice_nonreloc_howto(kreloc_ss
, &kreloc
->howto
, type
, 0);
1710 static void write_ksplice_nonreloc_howto(struct supersect
*ss
,
1711 const struct ksplice_reloc_howto
1713 enum ksplice_reloc_howto_type type
,
1716 struct supersect
*khowto_ss
=
1717 make_section(ss
->parent
, ".ksplice_reloc_howtos");
1718 struct ksplice_reloc_howto
*khowto
=
1719 sect_grow(khowto_ss
, 1, struct ksplice_reloc_howto
);
1721 khowto
->type
= type
;
1722 khowto
->size
= size
;
1724 khowto
->dst_mask
= 0;
1725 khowto
->rightshift
= 0;
1726 khowto
->signed_addend
= 0;
1727 write_reloc(ss
, addr
, &khowto_ss
->symbol
,
1728 addr_offset(khowto_ss
, khowto
));
1731 static void write_ksplice_section(struct span
*span
)
1733 struct supersect
*ss
= span
->ss
;
1734 const char *sectname
= span
->ss
->name
;
1735 const struct table_section
*ts
= get_table_section(ss
->name
);
1737 if (ts
!= NULL
&& ts
->has_addr
) {
1738 arelent
*reloc
= find_reloc(ss
, ss
->contents
.data
+ span
->start
1740 assert(reloc
!= NULL
);
1741 asymbol
*rsym
= *reloc
->sym_ptr_ptr
;
1742 assert(!bfd_is_const_section(rsym
->section
));
1743 sectname
= rsym
->section
->name
;
1746 struct supersect
*ksect_ss
=
1747 make_section(ss
->parent
, ".ksplice_sections%s", sectname
);
1748 struct ksplice_section
*ksect
= sect_grow(ksect_ss
, 1,
1749 struct ksplice_section
);
1750 asymbol
*sym
= span
->symbol
== NULL
? ss
->symbol
: span
->symbol
;
1752 write_ksplice_symbol(ksect_ss
, &ksect
->symbol
, sym
, span
,
1753 mode("keep-new-code") ? "(post)" : "");
1754 ksect
->size
= span
->size
;
1757 if (ss
->type
== SS_TYPE_RODATA
|| ss
->type
== SS_TYPE_STRING
||
1758 ss
->type
== SS_TYPE_EXPORT
)
1759 ksect
->flags
|= KSPLICE_SECTION_RODATA
;
1760 if (ss
->type
== SS_TYPE_DATA
)
1761 ksect
->flags
|= KSPLICE_SECTION_DATA
;
1762 if (ss
->type
== SS_TYPE_TEXT
)
1763 ksect
->flags
|= KSPLICE_SECTION_TEXT
;
1764 assert(ksect
->flags
!= 0);
1766 if (ss
->type
== SS_TYPE_STRING
)
1767 ksect
->flags
|= KSPLICE_SECTION_STRING
;
1769 write_reloc(ksect_ss
, &ksect
->address
, &ss
->symbol
,
1770 span
->start
+ span
->shift
);
1773 static void write_ksplice_patch_reloc(struct supersect
*ss
,
1774 const char *sectname
, unsigned long *addr
,
1775 bfd_size_type size
, const char *label
,
1778 struct supersect
*kreloc_ss
;
1779 kreloc_ss
= make_section(ss
->parent
, ".ksplice_relocs%s", sectname
);
1780 struct ksplice_reloc
*kreloc
= sect_grow(kreloc_ss
, 1,
1781 struct ksplice_reloc
);
1783 write_canary(ss
, addr_offset(ss
, addr
), size
, -1);
1784 write_ksplice_symbol_backend(kreloc_ss
, &kreloc
->symbol
, NULL
,
1786 write_reloc(kreloc_ss
, &kreloc
->blank_addr
, &ss
->symbol
,
1787 addr_offset(ss
, addr
));
1788 reloc_howto_type
*howto
=
1789 bfd_reloc_type_lookup(ss
->parent
->abfd
,
1790 PASTE(BFD_RELOC_
, LONG_BIT
));
1791 write_ksplice_reloc_howto(kreloc_ss
, &kreloc
->howto
, howto
,
1792 KSPLICE_HOWTO_RELOC
);
1793 kreloc
->target_addend
= addend
;
1794 kreloc
->insn_addend
= 0;
1797 void write_ksplice_patch(struct superbfd
*sbfd
, struct span
*span
)
1799 struct supersect
*kpatch_ss
=
1800 make_section(sbfd
, ".ksplice_patches%s", span
->ss
->name
);
1801 struct ksplice_patch
*kpatch
= sect_grow(kpatch_ss
, 1,
1802 struct ksplice_patch
);
1804 write_ksplice_patch_reloc(kpatch_ss
, span
->ss
->name
, &kpatch
->oldaddr
,
1805 sizeof(kpatch
->oldaddr
), span
->label
, 0);
1806 if (span
->ss
->type
== SS_TYPE_TEXT
) {
1807 kpatch
->type
= KSPLICE_PATCH_TEXT
;
1808 write_patch_storage(kpatch_ss
, kpatch
, MAX_TRAMPOLINE_SIZE
,
1811 kpatch
->type
= KSPLICE_PATCH_DATA
;
1812 kpatch
->size
= span
->contents_size
;
1813 struct supersect
*data_ss
=
1814 make_section(sbfd
, ".ksplice_patch_data");
1815 write_reloc(kpatch_ss
, &kpatch
->contents
, &span
->ss
->symbol
,
1816 span
->start
+ span
->shift
);
1817 char *saved
= sect_do_grow(data_ss
, 1, span
->contents_size
, 1);
1818 write_reloc(kpatch_ss
, &kpatch
->saved
, &data_ss
->symbol
,
1819 addr_offset(data_ss
, saved
));
1821 write_reloc(kpatch_ss
, &kpatch
->repladdr
, &span
->ss
->symbol
,
1822 span
->start
+ span
->shift
);
1825 asymbol
**make_undefined_symbolp(struct superbfd
*sbfd
, const char *name
)
1828 for (symp
= sbfd
->syms
.data
; symp
< sbfd
->syms
.data
+ sbfd
->syms
.size
;
1830 asymbol
*sym
= *symp
;
1831 if (strcmp(name
, sym
->name
) == 0 &&
1832 bfd_is_und_section(sym
->section
))
1836 for (sympp
= sbfd
->new_syms
.data
;
1837 sympp
< sbfd
->new_syms
.data
+ sbfd
->new_syms
.size
; sympp
++) {
1838 asymbol
**symp
= *sympp
;
1839 asymbol
*sym
= *symp
;
1840 if (strcmp(name
, sym
->name
) == 0 &&
1841 bfd_is_und_section(sym
->section
))
1845 symp
= malloc(sizeof(*symp
));
1846 *symp
= bfd_make_empty_symbol(sbfd
->abfd
);
1847 asymbol
*sym
= *symp
;
1849 sym
->section
= bfd_und_section_ptr
;
1852 *vec_grow(&sbfd
->new_syms
, 1) = symp
;
1856 void write_ksplice_deleted_patch(struct superbfd
*sbfd
, const char *name
,
1857 const char *label
, const char *sectname
)
1859 struct supersect
*kpatch_ss
=
1860 make_section(sbfd
, ".ksplice_patches%s", sectname
);
1861 struct ksplice_patch
*kpatch
= sect_grow(kpatch_ss
, 1,
1862 struct ksplice_patch
);
1864 write_ksplice_patch_reloc(kpatch_ss
, sectname
, &kpatch
->oldaddr
,
1865 sizeof(kpatch
->oldaddr
), label
, 0);
1866 kpatch
->type
= KSPLICE_PATCH_TEXT
;
1867 asymbol
**symp
= make_undefined_symbolp(sbfd
, strdup(name
));
1868 write_reloc(kpatch_ss
, &kpatch
->repladdr
, symp
, 0);
1869 write_patch_storage(kpatch_ss
, kpatch
, MAX_TRAMPOLINE_SIZE
, NULL
);
1872 void write_ksplice_export(struct superbfd
*sbfd
, struct span
*span
, bool del
)
1874 struct supersect
*kpatch_ss
= make_section(sbfd
, ".ksplice_patches");
1875 struct ksplice_patch
*kpatch
= sect_grow(kpatch_ss
, 1,
1876 struct ksplice_patch
);
1877 struct supersect
*data_ss
;
1879 const struct table_section
*ts
= get_table_section(span
->ss
->name
);
1882 span
->ss
->contents
.data
+ span
->start
+ ts
->other_offset
;
1883 const char *symname
= read_string(span
->ss
, addr
);
1885 char *oldname
, *newname
;
1887 oldname
= strprintf("%s:%s", span
->ss
->name
, symname
);
1888 newname
= strprintf("DISABLED_%s_%s", symname
, kid
);
1890 oldname
= strprintf("%s:DISABLED_%s_%s", span
->ss
->name
,
1892 newname
= strprintf("%s", symname
);
1893 write_string(span
->ss
, addr
, "DISABLED_%s_%s", symname
, kid
);
1896 write_ksplice_patch_reloc(kpatch_ss
, "", &kpatch
->oldaddr
,
1897 sizeof(kpatch
->oldaddr
), oldname
,
1899 kpatch
->type
= KSPLICE_PATCH_EXPORT
;
1900 const char **namep
= write_patch_storage(kpatch_ss
, kpatch
,
1901 sizeof(newname
), &data_ss
);
1902 write_string(data_ss
, namep
, "%s", newname
);
1905 void filter_table_sections(struct superbfd
*isbfd
)
1907 struct supersect
*tables_ss
=
1908 fetch_supersect(offsets_sbfd
,
1909 bfd_get_section_by_name(offsets_sbfd
->abfd
,
1910 ".ksplice_table_sections"));
1911 const struct table_section
*ts
;
1912 for (ts
= tables_ss
->contents
.data
;
1913 (void *)ts
< tables_ss
->contents
.data
+ tables_ss
->contents
.size
;
1915 struct table_section s
= *ts
;
1916 s
.sect
= read_string(tables_ss
, &ts
->sect
);
1917 s
.other_sect
= read_string(tables_ss
, &ts
->other_sect
);
1918 s
.crc_sect
= read_string(tables_ss
, &ts
->crc_sect
);
1919 filter_table_section(isbfd
, &s
);
1923 void filter_table_section(struct superbfd
*sbfd
, const struct table_section
*s
)
1925 asection
*isection
= bfd_get_section_by_name(sbfd
->abfd
, s
->sect
);
1926 if (isection
== NULL
)
1928 struct supersect
*ss
= fetch_supersect(sbfd
, isection
);
1931 for (entry
= ss
->contents
.data
;
1932 entry
< ss
->contents
.data
+ ss
->contents
.size
;
1933 entry
+= s
->entry_size
) {
1934 struct span
*span
= find_span(ss
, addr_offset(ss
, entry
));
1935 assert(span
!= NULL
);
1938 struct span
*sym_span
=
1939 span_offset_target_span(span
, s
->addr_offset
);
1940 assert(sym_span
!= NULL
);
1945 if (s
->other_sect
!= NULL
) {
1946 struct span
*sym_span
=
1947 span_offset_target_span(span
, s
->other_offset
);
1948 assert(sym_span
!= NULL
);
1950 keep_span(sym_span
);
1953 if (s
->crc_sect
!= NULL
) {
1954 struct span
*crc_span
= get_crc_span(span
, s
);
1955 assert(crc_span
!= NULL
);
1956 if (span
->keep
&& mode("keep-new-code"))
1957 keep_span(crc_span
);
1962 static void match_table_spans(struct span
*old_span
, struct span
*new_span
)
1964 const struct table_section
*ts
= get_table_section(old_span
->ss
->name
);
1966 if (strcmp(old_span
->ss
->name
, new_span
->ss
->name
) != 0)
1968 if (ts
== NULL
|| old_span
->ss
->type
!= SS_TYPE_SPECIAL
||
1969 new_span
->ss
->type
!= SS_TYPE_SPECIAL
)
1971 if (old_span
->match
!= NULL
|| new_span
->match
!= NULL
)
1975 void *old_entry
= old_span
->ss
->contents
.data
+ old_span
->start
;
1976 void *new_entry
= new_span
->ss
->contents
.data
+ new_span
->start
;
1977 arelent
*old_reloc
=
1978 find_reloc(old_span
->ss
, old_entry
+ ts
->addr_offset
);
1979 arelent
*new_reloc
=
1980 find_reloc(new_span
->ss
, new_entry
+ ts
->addr_offset
);
1981 assert(old_reloc
!= NULL
&& new_reloc
!= NULL
);
1982 struct span
*old_sym_span
=
1983 reloc_target_span(old_span
->ss
, old_reloc
);
1984 struct span
*new_sym_span
=
1985 reloc_target_span(new_span
->ss
, new_reloc
);
1986 assert(old_sym_span
!= NULL
&& new_sym_span
!= NULL
);
1987 if (old_sym_span
->match
== new_sym_span
&&
1988 new_sym_span
->match
== old_sym_span
&&
1989 old_reloc
->address
- old_sym_span
->start
==
1990 new_reloc
->address
- new_sym_span
->start
)
1991 match_spans(old_span
, new_span
);
1995 static struct span
*get_crc_span(struct span
*span
,
1996 const struct table_section
*ts
)
1998 void *entry
= span
->ss
->contents
.data
+ span
->start
;
1999 asection
*crc_sect
= bfd_get_section_by_name(span
->ss
->parent
->abfd
,
2001 if (crc_sect
== NULL
)
2003 struct supersect
*crc_ss
= fetch_supersect(span
->ss
->parent
, crc_sect
);
2006 struct span
*crc_span
= find_span(crc_ss
, addr_offset(span
->ss
, entry
) /
2007 ts
->entry_size
* ts
->crc_size
);
2011 void mark_precallable_spans(struct superbfd
*sbfd
)
2014 struct supersect
*ss
, *sym_ss
;
2015 struct span
*address_span
, *target_span
;
2016 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
2017 ss
= fetch_supersect(sbfd
, sect
);
2019 if (ss
->type
== SS_TYPE_SPECIAL
)
2021 for (relocp
= ss
->relocs
.data
;
2022 relocp
< ss
->relocs
.data
+ ss
->relocs
.size
; relocp
++) {
2023 asymbol
*sym
= *(*relocp
)->sym_ptr_ptr
;
2024 address_span
= find_span(ss
, (*relocp
)->address
);
2025 if (!address_span
->precallable
)
2027 target_span
= reloc_target_span(ss
, *relocp
);
2028 if (target_span
== NULL
|| target_span
->keep
)
2030 sym_ss
= fetch_supersect(sbfd
, sym
->section
);
2031 if (sym_ss
->type
== SS_TYPE_IGNORED
)
2033 target_span
->precallable
= true;
2039 void keep_referenced_sections(struct superbfd
*sbfd
)
2042 struct supersect
*ss
, *sym_ss
;
2043 struct span
*address_span
, *target_span
;
2044 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
2045 ss
= fetch_supersect(sbfd
, sect
);
2047 if (ss
->type
== SS_TYPE_SPECIAL
)
2049 for (relocp
= ss
->relocs
.data
;
2050 relocp
< ss
->relocs
.data
+ ss
->relocs
.size
; relocp
++) {
2051 asymbol
*sym
= *(*relocp
)->sym_ptr_ptr
;
2052 address_span
= find_span(ss
, (*relocp
)->address
);
2053 if (!address_span
->keep
)
2055 target_span
= reloc_target_span(ss
, *relocp
);
2056 if (target_span
== NULL
|| target_span
->keep
)
2058 sym_ss
= fetch_supersect(sbfd
, sym
->section
);
2059 if (sym_ss
->type
== SS_TYPE_IGNORED
)
2061 keep_span(target_span
);
2067 void copy_symbols(struct asymbolp_vec
*osyms
, struct asymbolpp_vec
*isyms
)
2070 for (sympp
= isyms
->data
; sympp
< isyms
->data
+ isyms
->size
; sympp
++)
2071 *vec_grow(osyms
, 1) = **sympp
;
2074 /* Modified function from GNU Binutils objcopy.c */
2075 bfd_boolean
copy_object(bfd
*ibfd
, bfd
*obfd
)
2077 assert(bfd_set_format(obfd
, bfd_get_format(ibfd
)));
2079 bfd_vma start
= bfd_get_start_address(ibfd
);
2081 flagword flags
= bfd_get_file_flags(ibfd
);
2082 flags
&= bfd_applicable_file_flags(obfd
);
2084 assert(bfd_set_start_address(obfd
, start
)
2085 && bfd_set_file_flags(obfd
, flags
));
2087 enum bfd_architecture iarch
= bfd_get_arch(ibfd
);
2088 unsigned int imach
= bfd_get_mach(ibfd
);
2089 assert(bfd_set_arch_mach(obfd
, iarch
, imach
));
2090 assert(bfd_set_format(obfd
, bfd_get_format(ibfd
)));
2092 /* BFD mandates that all output sections be created and sizes set before
2093 any output is done. Thus, we traverse all sections multiple times. */
2094 bfd_map_over_sections(ibfd
, setup_section
, obfd
);
2096 struct supersect
*new_supersects
= fetch_superbfd(ibfd
)->new_supersects
;
2097 struct supersect
*ss
;
2098 for (ss
= new_supersects
; ss
!= NULL
; ss
= ss
->next
)
2099 setup_new_section(obfd
, ss
);
2101 /* Mark symbols used in output relocations so that they
2102 are kept, even if they are local labels or static symbols.
2104 Note we iterate over the input sections examining their
2105 relocations since the relocations for the output sections
2106 haven't been set yet. mark_symbols_used_in_relocations will
2107 ignore input sections which have no corresponding output
2110 bfd_map_over_sections(ibfd
, mark_symbols_used_in_relocations
, NULL
);
2111 for (ss
= new_supersects
; ss
!= NULL
; ss
= ss
->next
)
2112 ss_mark_symbols_used_in_relocations(ss
);
2113 struct asymbolp_vec osyms
;
2115 filter_symbols(ibfd
, obfd
, &osyms
, &fetch_superbfd(ibfd
)->syms
);
2116 copy_symbols(&osyms
, &fetch_superbfd(ibfd
)->new_syms
);
2118 bfd_set_symtab(obfd
, osyms
.data
, osyms
.size
);
2120 /* This has to happen after the symbol table has been set. */
2121 bfd_map_over_sections(obfd
, write_section
, NULL
);
2123 /* Allow the BFD backend to copy any private data it understands
2124 from the input BFD to the output BFD. This is done last to
2125 permit the routine to look at the filtered symbol table, which is
2126 important for the ECOFF code at least. */
2127 assert(bfd_copy_private_bfd_data(ibfd
, obfd
));
2132 /* Modified function from GNU Binutils objcopy.c */
2133 void setup_section(bfd
*ibfd
, asection
*isection
, void *obfdarg
)
2135 struct superbfd
*isbfd
= fetch_superbfd(ibfd
);
2136 struct supersect
*ss
= fetch_supersect(isbfd
, isection
);
2137 bfd
*obfd
= obfdarg
;
2143 asection
*osection
= bfd_make_section_anyway(obfd
, ss
->name
);
2144 assert(osection
!= NULL
);
2146 osection
->userdata
= ss
;
2147 bfd_set_section_flags(obfd
, osection
, ss
->flags
);
2148 ss
->symbol
= osection
->symbol
;
2149 assert(bfd_set_section_size(obfd
, osection
, ss
->contents
.size
));
2151 vma
= bfd_section_vma(ibfd
, isection
);
2152 assert(bfd_set_section_vma(obfd
, osection
, vma
));
2154 osection
->lma
= isection
->lma
;
2155 assert(bfd_set_section_alignment(obfd
, osection
, ss
->alignment
));
2156 osection
->entsize
= ss
->entsize
;
2157 osection
->output_section
= osection
;
2158 osection
->output_offset
= 0;
2159 isection
->output_section
= osection
;
2160 isection
->output_offset
= 0;
2164 void setup_new_section(bfd
*obfd
, struct supersect
*ss
)
2166 asection
*osection
= bfd_make_section_anyway(obfd
, ss
->name
);
2167 assert(osection
!= NULL
);
2168 bfd_set_section_flags(obfd
, osection
, ss
->flags
);
2170 osection
->userdata
= ss
;
2171 ss
->symbol
= osection
->symbol
;
2172 assert(bfd_set_section_size(obfd
, osection
, ss
->contents
.size
));
2173 assert(bfd_set_section_vma(obfd
, osection
, 0));
2176 assert(bfd_set_section_alignment(obfd
, osection
, ss
->alignment
));
2177 osection
->entsize
= ss
->entsize
;
2178 osection
->output_section
= osection
;
2179 osection
->output_offset
= 0;
2182 static int compare_reloc_addresses(const void *aptr
, const void *bptr
)
2184 const arelent
*const *a
= aptr
, *const *b
= bptr
;
2185 return (*a
)->address
- (*b
)->address
;
2188 static void delete_obsolete_relocs(struct supersect
*ss
)
2190 if (ss
->new_relocs
.size
== 0)
2193 qsort(ss
->relocs
.data
, ss
->relocs
.size
, sizeof(*ss
->relocs
.data
),
2194 compare_reloc_addresses
);
2195 qsort(ss
->new_relocs
.data
, ss
->new_relocs
.size
,
2196 sizeof(*ss
->new_relocs
.data
), compare_reloc_addresses
);
2198 struct arelentp_vec orig_relocs
;
2199 vec_move(&orig_relocs
, &ss
->relocs
);
2201 arelent
**relocp
, **new_relocp
= ss
->new_relocs
.data
;
2202 for (relocp
= orig_relocs
.data
;
2203 relocp
< orig_relocs
.data
+ orig_relocs
.size
; relocp
++) {
2204 while (new_relocp
< ss
->new_relocs
.data
+ ss
->new_relocs
.size
&&
2205 (*new_relocp
)->address
< (*relocp
)->address
)
2207 arelent
*reloc
= *relocp
, *new_reloc
= *new_relocp
;
2208 if (new_relocp
== ss
->new_relocs
.data
+ ss
->new_relocs
.size
||
2209 reloc
->address
!= new_reloc
->address
)
2210 *vec_grow(&ss
->relocs
, 1) = reloc
;
2214 void write_section(bfd
*obfd
, asection
*osection
, void *arg
)
2216 struct supersect
*ss
= osection
->userdata
;
2218 if ((ss
->flags
& SEC_GROUP
) != 0 || ss
->contents
.size
== 0)
2221 delete_obsolete_relocs(ss
);
2224 char *error_message
;
2225 for (relocp
= ss
->new_relocs
.data
;
2226 relocp
< ss
->new_relocs
.data
+ ss
->new_relocs
.size
; relocp
++) {
2228 if (bfd_get_arch(obfd
) == bfd_arch_arm
)
2229 val
= osection
->use_rela_p
? 0 : (*relocp
)->addend
;
2232 bfd_put(bfd_get_reloc_size((*relocp
)->howto
) * 8, obfd
, val
,
2233 ss
->contents
.data
+ (*relocp
)->address
);
2234 if (bfd_install_relocation(obfd
, *relocp
, ss
->contents
.data
,
2235 0, osection
, &error_message
) !=
2237 err(ss
->parent
, "ksplice: error installing reloc: %s",
2241 if (mode("finalize")) {
2242 /* Check that all our sections will be allocated */
2243 asymbol
*sym
= *((*relocp
)->sym_ptr_ptr
);
2244 if (!bfd_is_const_section(sym
->section
)) {
2245 struct supersect
*sym_ss
=
2246 fetch_supersect(ss
->parent
, sym
->section
);
2247 assert((sym_ss
->flags
& SEC_ALLOC
) != 0);
2251 memcpy(vec_grow(&ss
->relocs
, ss
->new_relocs
.size
), ss
->new_relocs
.data
,
2252 ss
->new_relocs
.size
* sizeof(*ss
->new_relocs
.data
));
2254 bfd_set_reloc(obfd
, osection
,
2255 ss
->relocs
.size
== 0 ? NULL
: ss
->relocs
.data
,
2258 if (ss
->flags
& SEC_HAS_CONTENTS
)
2259 assert(bfd_set_section_contents
2260 (obfd
, osection
, ss
->contents
.data
, 0,
2261 ss
->contents
.size
));
2264 /* Modified function from GNU Binutils objcopy.c
2266 * Mark all the symbols which will be used in output relocations with
2267 * the BSF_KEEP flag so that those symbols will not be stripped.
2269 * Ignore relocations which will not appear in the output file.
2271 void mark_symbols_used_in_relocations(bfd
*abfd
, asection
*isection
,
2274 struct superbfd
*sbfd
= fetch_superbfd(abfd
);
2275 if (isection
->output_section
== NULL
)
2278 struct supersect
*ss
= fetch_supersect(sbfd
, isection
);
2279 ss_mark_symbols_used_in_relocations(ss
);
2282 void ss_mark_symbols_used_in_relocations(struct supersect
*ss
)
2284 /* Examine each symbol used in a relocation. If it's not one of the
2285 special bfd section symbols, then mark it with BSF_KEEP. */
2287 for (relocp
= ss
->relocs
.data
;
2288 relocp
< ss
->relocs
.data
+ ss
->relocs
.size
; relocp
++) {
2289 asymbol
*sym
= *(*relocp
)->sym_ptr_ptr
;
2290 if (!(bfd_is_const_section(sym
->section
) &&
2291 sym
== sym
->section
->symbol
))
2292 sym
->flags
|= BSF_KEEP
;
2294 for (relocp
= ss
->new_relocs
.data
;
2295 relocp
< ss
->new_relocs
.data
+ ss
->new_relocs
.size
; relocp
++) {
2296 asymbol
*sym
= *(*relocp
)->sym_ptr_ptr
;
2297 if (!(bfd_is_const_section(sym
->section
) &&
2298 sym
== sym
->section
->symbol
))
2299 sym
->flags
|= BSF_KEEP
;
2303 static bool deleted_table_section_symbol(bfd
*abfd
, asymbol
*sym
)
2305 struct superbfd
*sbfd
= fetch_superbfd(abfd
);
2306 if (bfd_is_const_section(sym
->section
))
2308 struct supersect
*ss
= fetch_supersect(sbfd
, sym
->section
);
2311 for (symp
= ss
->syms
.data
; symp
< ss
->syms
.data
+ ss
->syms
.size
; symp
++) {
2315 return symp
>= ss
->syms
.data
+ ss
->syms
.size
&&
2316 (sym
->flags
& BSF_SECTION_SYM
) == 0;
2319 void filter_symbols(bfd
*ibfd
, bfd
*obfd
, struct asymbolp_vec
*osyms
,
2320 struct asymbolp_vec
*isyms
)
2323 struct superbfd
*sbfd
= fetch_superbfd(ibfd
);
2324 for (symp
= isyms
->data
; symp
< isyms
->data
+ isyms
->size
; symp
++) {
2325 asymbol
*sym
= *symp
;
2326 struct supersect
*sym_ss
= NULL
;
2327 struct span
*sym_span
= NULL
;
2328 if (!bfd_is_const_section(sym
->section
)) {
2329 sym_ss
= fetch_supersect(sbfd
, sym
->section
);
2330 sym_span
= find_span(sym_ss
, sym
->value
);
2333 if (mode("keep") && (sym
->flags
& BSF_GLOBAL
) != 0 &&
2334 !(mode("keep-new-code") && sym_span
!= NULL
&&
2336 sym
->flags
= (sym
->flags
& ~BSF_GLOBAL
) | BSF_LOCAL
;
2338 if (mode("finalize") && (sym
->flags
& BSF_GLOBAL
) != 0)
2339 sym
->flags
= (sym
->flags
& ~BSF_GLOBAL
) | BSF_LOCAL
;
2341 bool keep
= bfd_is_const_section(sym
->section
) ||
2342 (sym_ss
->keep
&& (sym
->flags
& BSF_SECTION_SYM
) != 0) ||
2343 (sym_span
!= NULL
&& sym_span
->keep
);
2344 if (bfd_is_und_section(sym
->section
) &&
2345 (sym
->flags
& BSF_KEEP
) == 0)
2347 if (bfd_is_abs_section(sym
->section
) &&
2348 (sym
->flags
& BSF_KEEP
) == 0 &&
2349 (sym
->flags
& BSF_FILE
) == 0)
2351 if (deleted_table_section_symbol(ibfd
, sym
))
2354 if (mode("keep-old-code") && sym_ss
!= NULL
&&
2355 sym_ss
->type
== SS_TYPE_EXPORT
)
2359 if (sym_ss
!= NULL
&& !sym_ss
->keep
) {
2360 err(sbfd
, "Kept symbol %s in unkept section "
2361 "%s\n", sym
->name
, sym
->section
->name
);
2364 *vec_grow(osyms
, 1) = sym
;
2369 void read_str_set(struct str_vec
*strs
)
2373 assert(getline(&buf
, &n
, stdin
) >= 0);
2377 char *str
= strtok_r(buf
, " \n", &saveptr
);
2381 *vec_grow(strs
, 1) = str
;
2385 bool str_in_set(const char *str
, const struct str_vec
*strs
)
2388 for (strp
= strs
->data
; strp
< strs
->data
+ strs
->size
; strp
++) {
2389 if (strcmp(str
, *strp
) == 0)
2395 static bool is_table_section(const char *name
, bool consider_other
,
2398 struct supersect
*tables_ss
=
2399 fetch_supersect(offsets_sbfd
,
2400 bfd_get_section_by_name(offsets_sbfd
->abfd
,
2401 ".ksplice_table_sections"));
2402 const struct table_section
*ts
;
2403 for (ts
= tables_ss
->contents
.data
;
2404 (void *)ts
< tables_ss
->contents
.data
+ tables_ss
->contents
.size
;
2406 if (strcmp(name
, read_string(tables_ss
, &ts
->sect
)) == 0)
2408 const char *osect_name
= read_string(tables_ss
,
2410 if (consider_other
&& osect_name
!= NULL
&&
2411 strcmp(name
, osect_name
) == 0)
2413 const char *crc_name
= read_string(tables_ss
, &ts
->crc_sect
);
2414 if (consider_crc
&& crc_name
!= NULL
&&
2415 strcmp(name
, crc_name
) == 0)
2421 const struct table_section
*get_table_section(const char *name
)
2423 struct supersect
*tables_ss
=
2424 fetch_supersect(offsets_sbfd
,
2425 bfd_get_section_by_name(offsets_sbfd
->abfd
,
2426 ".ksplice_table_sections"));
2427 const struct table_section
*ts
;
2428 for (ts
= tables_ss
->contents
.data
;
2429 (void *)ts
< tables_ss
->contents
.data
+ tables_ss
->contents
.size
;
2431 if (strcmp(name
, read_string(tables_ss
, &ts
->sect
)) == 0) {
2432 if (ts
->entry_contents_size
!= 0)
2433 assert(align(ts
->entry_contents_size
,
2436 struct table_section
*ns
= malloc(sizeof(*ns
));
2438 ns
->sect
= read_string(tables_ss
, &ts
->sect
);
2439 ns
->crc_sect
= read_string(tables_ss
, &ts
->crc_sect
);
2441 read_string(tables_ss
, &ts
->other_sect
);
2448 enum supersect_type
supersect_type(struct supersect
*ss
)
2450 if (mode("finalize") &&
2451 strcmp(finalize_target
, "vmlinux") == 0 &&
2452 (strstarts(ss
->name
, ".ksplice_relocs.exit") ||
2453 strstarts(ss
->name
, ".ksplice_sections.exit") ||
2454 strstarts(ss
->name
, ".ksplice_patches.exit")))
2455 return SS_TYPE_EXIT
;
2456 if (strstarts(ss
->name
, ".ksplice_call"))
2457 return SS_TYPE_KSPLICE_CALL
;
2458 if (strstarts(ss
->name
, ".ksplice_options"))
2459 return SS_TYPE_SPECIAL
;
2460 if (strstarts(ss
->name
, ".ksplice"))
2461 return SS_TYPE_KSPLICE
;
2463 if (strstarts(ss
->name
, ".init"))
2464 return SS_TYPE_IGNORED
;
2465 if (strstarts(ss
->name
, ".security_initcall.init"))
2466 return SS_TYPE_IGNORED
;
2467 if (strstarts(ss
->name
, ".con_initcall.init"))
2468 return SS_TYPE_IGNORED
;
2469 if (strstarts(ss
->name
, ".x86cpuvendor.init"))
2470 return SS_TYPE_IGNORED
;
2471 if (strstarts(ss
->name
, ".early_param.init"))
2472 return SS_TYPE_IGNORED
;
2473 if (strstarts(ss
->name
, ".taglist.init"))
2474 return SS_TYPE_IGNORED
;
2475 if (strstarts(ss
->name
, ".arch.info.init"))
2476 return SS_TYPE_IGNORED
;
2477 if (strstarts(ss
->name
, ".proc.info.init"))
2478 return SS_TYPE_IGNORED
;
2479 /* .pci_fixup_* sections really should be treated as global rodata
2480 referenced only from quirks.c */
2481 if (strstarts(ss
->name
, ".pci_fixup_"))
2482 return SS_TYPE_IGNORED
;
2483 /* .builtin_fw sections are similar to .pci_fixup */
2484 if (strstarts(ss
->name
, ".builtin_fw"))
2485 return SS_TYPE_IGNORED
;
2486 /* same for .tracedata */
2487 if (strstarts(ss
->name
, ".tracedata"))
2488 return SS_TYPE_IGNORED
;
2489 if (strstarts(ss
->name
, ".debug"))
2490 return SS_TYPE_IGNORED
;
2491 /* .eh_frame should probably be discarded, not ignored */
2492 if (strstarts(ss
->name
, ".eh_frame"))
2493 return SS_TYPE_IGNORED
;
2494 if (config
->ignore_devinit
&& strstarts(ss
->name
, ".devinit"))
2495 return SS_TYPE_IGNORED
;
2496 if (config
->ignore_meminit
&& strstarts(ss
->name
, ".meminit"))
2497 return SS_TYPE_IGNORED
;
2498 if (config
->ignore_cpuinit
&& strstarts(ss
->name
, ".cpuinit"))
2499 return SS_TYPE_IGNORED
;
2500 if (config
->ignore_devinit
&& strstarts(ss
->name
, ".devexit"))
2501 return SS_TYPE_IGNORED
;
2502 if (config
->ignore_meminit
&& strstarts(ss
->name
, ".memexit"))
2503 return SS_TYPE_IGNORED
;
2504 if (config
->ignore_cpuinit
&& strstarts(ss
->name
, ".cpuexit"))
2505 return SS_TYPE_IGNORED
;
2506 if (strstarts(ss
->name
, ".vgetcpu_mode") ||
2507 strstarts(ss
->name
, ".jiffies") ||
2508 strstarts(ss
->name
, ".wall_jiffies") ||
2509 strstarts(ss
->name
, ".vxtime") ||
2510 strstarts(ss
->name
, ".sys_tz") ||
2511 strstarts(ss
->name
, ".sysctl_vsyscall") ||
2512 strstarts(ss
->name
, ".xtime") ||
2513 strstarts(ss
->name
, ".xtime_lock") ||
2514 strstarts(ss
->name
, ".vsyscall"))
2515 return SS_TYPE_IGNORED
;
2516 if (strstarts(ss
->name
, ".vdso"))
2517 return SS_TYPE_IGNORED
;
2519 if (strstarts(ss
->name
, ".exit.text"))
2520 return SS_TYPE_TEXT
;
2521 if (strstarts(ss
->name
, ".exit.data"))
2522 return SS_TYPE_DATA
;
2524 if (strstarts(ss
->name
, ".text") ||
2525 strstarts(ss
->name
, ".kernel.text") ||
2526 strstarts(ss
->name
, ".devinit.text") ||
2527 strstarts(ss
->name
, ".meminit.text") ||
2528 strstarts(ss
->name
, ".cpuinit.text") ||
2529 strstarts(ss
->name
, ".devexit.text") ||
2530 strstarts(ss
->name
, ".memexit.text") ||
2531 strstarts(ss
->name
, ".cpuexit.text") ||
2532 strstarts(ss
->name
, ".ref.text") ||
2533 strstarts(ss
->name
, ".spinlock.text") ||
2534 strstarts(ss
->name
, ".kprobes.text") ||
2535 strstarts(ss
->name
, ".sched.text") ||
2536 strstarts(ss
->name
, ".entry.text") || /* OpenVZ */
2537 (mode("keep-old-code") && strstarts(ss
->name
, ".fixup")))
2538 return SS_TYPE_TEXT
;
2541 if (sscanf(ss
->name
, ".rodata.str%*u.%*u%n", &n
) >= 0 &&
2542 n
== strlen(ss
->name
))
2543 return ss
->entsize
== 1 ? SS_TYPE_STRING
: SS_TYPE_RODATA
;
2545 if (strstarts(ss
->name
, ".rodata") ||
2546 strstarts(ss
->name
, ".kernel.rodata") ||
2547 strstarts(ss
->name
, ".devinit.rodata") ||
2548 strstarts(ss
->name
, ".meminit.rodata") ||
2549 strstarts(ss
->name
, ".cpuinit.rodata") ||
2550 strstarts(ss
->name
, ".devexit.rodata") ||
2551 strstarts(ss
->name
, ".memexit.rodata") ||
2552 strstarts(ss
->name
, ".cpuexit.rodata") ||
2553 strstarts(ss
->name
, ".ref.rodata") ||
2554 strstarts(ss
->name
, "__markers_strings") ||
2555 strstarts(ss
->name
, "__bug_table") ||
2556 (mode("keep-old-code") && strstarts(ss
->name
, "__ex_table")))
2557 return SS_TYPE_RODATA
;
2559 if (strstarts(ss
->name
, ".bss"))
2560 return SS_TYPE_DATA
;
2562 /* Ignore .data.percpu sections */
2563 if (strstarts(ss
->name
, ".data.percpu") ||
2564 strstarts(ss
->name
, ".kernel.data.percpu") ||
2565 strstarts(ss
->name
, ".data..percpu"))
2566 return SS_TYPE_IGNORED
;
2567 if (strstarts(ss
->name
, ".data") ||
2568 strstarts(ss
->name
, ".kernel.data") ||
2569 strstarts(ss
->name
, ".devinit.data") ||
2570 strstarts(ss
->name
, ".cpuinit.data") ||
2571 strstarts(ss
->name
, ".meminit.data") ||
2572 strstarts(ss
->name
, ".devexit.data") ||
2573 strstarts(ss
->name
, ".memexit.data") ||
2574 strstarts(ss
->name
, ".cpuexit.data") ||
2575 strstarts(ss
->name
, ".ref.data") ||
2576 strstarts(ss
->name
, "__markers"))
2577 return SS_TYPE_DATA
;
2579 /* We replace all the ksymtab strings, so delete them */
2580 if (strcmp(ss
->name
, "__ksymtab_strings") == 0)
2581 return SS_TYPE_STRING
;
2582 if (strstarts(ss
->name
, "__ksymtab"))
2583 return SS_TYPE_EXPORT
;
2585 if (is_table_section(ss
->name
, true, true))
2586 return SS_TYPE_SPECIAL
;
2588 if (strstarts(ss
->name
, ".ARM."))
2589 return SS_TYPE_SPECIAL
;
2591 if (strstarts(ss
->name
, ".note"))
2592 return SS_TYPE_IGNORED
;
2593 if (strstarts(ss
->name
, ".comment"))
2594 return SS_TYPE_IGNORED
;
2595 if (strstarts(ss
->name
, "__param"))
2596 return SS_TYPE_IGNORED
;
2597 if (strstarts(ss
->name
, ".exitcall.exit"))
2598 return SS_TYPE_IGNORED
;
2599 if (strstarts(ss
->name
, ".modinfo"))
2600 return SS_TYPE_IGNORED
;
2602 return SS_TYPE_UNKNOWN
;
2605 void initialize_supersect_types(struct superbfd
*sbfd
)
2608 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
2609 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
2610 ss
->type
= supersect_type(ss
);
2611 ss
->orig_type
= ss
->type
;
2612 if (ss
->type
== SS_TYPE_UNKNOWN
) {
2613 err(sbfd
, "Unknown section type: %s\n", ss
->name
);
2619 static void init_label_map(struct superbfd
*sbfd
)
2621 struct label_map
*map
;
2623 vec_init(&sbfd
->maps
);
2627 struct symbol_hash csyms
;
2628 symbol_hash_init(&csyms
);
2631 for (symp
= sbfd
->syms
.data
;
2632 symp
< sbfd
->syms
.data
+ sbfd
->syms
.size
; symp
++) {
2633 asymbol
*csym
= canonical_symbol(sbfd
, *symp
);
2636 char *key
= strprintf("%p", csym
);
2637 asymbol
**csymp
= symbol_hash_lookup(&csyms
, key
, TRUE
);
2643 map
= vec_grow(&sbfd
->maps
, 1);
2646 map
->label
= symbol_label(sbfd
, csym
);
2649 struct label_mapp_hash label_maps
;
2650 label_mapp_hash_init(&label_maps
);
2651 for (map
= sbfd
->maps
.data
;
2652 map
< sbfd
->maps
.data
+ sbfd
->maps
.size
; map
++) {
2653 struct label_map
**mapp
=
2654 label_mapp_hash_lookup(&label_maps
, map
->label
, TRUE
);
2655 if (*mapp
== NULL
) {
2660 struct label_map
*first_map
= *mapp
;
2661 if (first_map
->count
== 0)
2662 first_map
->label
= strprintf("%s~%d", map
->label
, 0);
2663 map
->label
= strprintf("%s~%d", map
->label
, ++first_map
->count
);
2666 label_mapp_hash_init(&sbfd
->maps_hash
);
2667 for (map
= sbfd
->maps
.data
;
2668 map
< sbfd
->maps
.data
+ sbfd
->maps
.size
; map
++) {
2669 char *key
= strprintf("%p", map
->csym
);
2670 struct label_map
**mapp
=
2671 label_mapp_hash_lookup(&sbfd
->maps_hash
, key
, TRUE
);
2674 map
->orig_label
= map
->label
;
2678 static const char *label_lookup(struct superbfd
*sbfd
, asymbol
*sym
)
2680 asymbol
*csym
= canonical_symbol(sbfd
, sym
);
2681 char *key
= strprintf("%p", csym
);
2682 struct label_map
**mapp
=
2683 label_mapp_hash_lookup(&sbfd
->maps_hash
, key
, FALSE
);
2687 return (*mapp
)->label
;
2690 static void print_label_changes(struct superbfd
*sbfd
)
2694 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
2695 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
2696 for (span
= ss
->spans
.data
;
2697 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++) {
2698 if (strcmp(span
->label
, span
->orig_label
) != 0)
2699 debug1(sbfd
, "Label change: %s -> %s\n",
2700 span
->label
, span
->orig_label
);
2705 static void label_map_set(struct superbfd
*sbfd
, const char *oldlabel
,
2708 struct label_map
*map
;
2709 for (map
= sbfd
->maps
.data
;
2710 map
< sbfd
->maps
.data
+ sbfd
->maps
.size
; map
++) {
2711 if (strcmp(map
->orig_label
, oldlabel
) == 0) {
2712 if (strcmp(map
->orig_label
, map
->label
) != 0 &&
2713 strcmp(map
->label
, label
) != 0)
2722 static void change_initial_label(struct span
*span
, const char *label
)
2724 struct superbfd
*sbfd
= span
->ss
->parent
;
2725 span
->label
= label
;
2726 span
->orig_label
= label
;
2728 asymbol
*csym
= canonical_symbol(sbfd
, span
->symbol
);
2729 char *key
= strprintf("%p", csym
);
2730 struct label_map
**mapp
=
2731 label_mapp_hash_lookup(&sbfd
->maps_hash
, key
, FALSE
);
2734 (*mapp
)->label
= span
->label
;
2735 (*mapp
)->orig_label
= span
->orig_label
;
2736 span
->symbol
= NULL
;
2740 static void init_callers(struct superbfd
*sbfd
)
2742 string_hash_init(&sbfd
->callers
);
2744 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
2745 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
2747 for (relocp
= ss
->relocs
.data
;
2748 relocp
< ss
->relocs
.data
+ ss
->relocs
.size
; relocp
++) {
2749 asymbol
*sym
= *(*relocp
)->sym_ptr_ptr
;
2751 sym
->value
+ reloc_target_offset(ss
, *relocp
);
2752 char *key
= strprintf("%s+%lx", sym
->section
->name
,
2754 const char **ret
= string_hash_lookup(&sbfd
->callers
,
2757 asymbol
*csym
= canonical_symbol(sbfd
, sect
->symbol
);
2759 *ret
= "*multiple_callers*";
2760 else if (static_local_symbol(sbfd
, csym
))
2761 *ret
= static_local_symbol(sbfd
, csym
);
2768 static const char *find_caller(struct supersect
*ss
, asymbol
*sym
)
2770 char *key
= strprintf("%s+%lx", sym
->section
->name
,
2771 (unsigned long)sym
->value
);
2772 const char **ret
= string_hash_lookup(&ss
->parent
->callers
, key
, FALSE
);
2776 return "*no_caller*";
2780 static void init_csyms(struct superbfd
*sbfd
)
2782 asymbolpp_hash_init(&sbfd
->csyms
);
2785 for (symp
= sbfd
->syms
.data
; symp
< sbfd
->syms
.data
+ sbfd
->syms
.size
;
2787 asymbol
*sym
= *symp
;
2788 if ((sym
->flags
& BSF_DEBUGGING
) != 0)
2790 char *key
= strprintf("%s+%lx", sym
->section
->name
,
2791 (unsigned long)sym
->value
);
2792 asymbol
***csympp
= asymbolpp_hash_lookup(&sbfd
->csyms
, key
,
2795 if (*csympp
== NULL
) {
2799 asymbol
*csym
= **csympp
;
2800 if ((csym
->flags
& BSF_GLOBAL
) != 0)
2802 if ((sym
->flags
& BSF_GLOBAL
) != 0)
2807 static asymbol
**symbolp_scan(struct supersect
*ss
, bfd_vma value
)
2809 char *key
= strprintf("%s+%lx", ss
->name
, (unsigned long)value
);
2811 asymbolpp_hash_lookup(&ss
->parent
->csyms
, key
, FALSE
);
2816 /* For section symbols of sections containing no symbols, return the
2817 section symbol that relocations are generated against */
2823 static asymbol
**canonical_symbolp(struct superbfd
*sbfd
, asymbol
*sym
)
2825 if (bfd_is_const_section(sym
->section
)) {
2827 for (csymp
= sbfd
->syms
.data
;
2828 csymp
< sbfd
->syms
.data
+ sbfd
->syms
.size
; csymp
++) {
2834 return symbolp_scan(fetch_supersect(sbfd
, sym
->section
), sym
->value
);
2837 static asymbol
*canonical_symbol(struct superbfd
*sbfd
, asymbol
*sym
)
2839 if (bfd_is_const_section(sym
->section
))
2841 asymbol
**symp
= canonical_symbolp(sbfd
, sym
);
2842 return symp
!= NULL
? *symp
: NULL
;
2845 static char *static_local_symbol(struct superbfd
*sbfd
, asymbol
*sym
)
2847 struct supersect
*ss
= fetch_supersect(sbfd
, sym
->section
);
2848 if ((sym
->flags
& BSF_LOCAL
) == 0 || (sym
->flags
& BSF_OBJECT
) == 0)
2850 char *dot
= strrchr(sym
->name
, '.');
2851 if (dot
== NULL
|| dot
[1 + strspn(dot
+ 1, "0123546789")] != '\0')
2853 char *basename
= strndup(sym
->name
, dot
- sym
->name
);
2855 /* Handle C.123.12345 symbols */
2856 dot
= strrchr(basename
, '.');
2857 if (dot
!= NULL
&& dot
[1 + strspn(dot
+ 1, "0123546789")] == '\0')
2858 basename
= strndup(basename
, dot
- basename
);
2860 if (strcmp(basename
, "__func__") == 0 ||
2861 strcmp(basename
, "__PRETTY_FUNCTION__") == 0)
2862 caller
= (const char *)ss
->contents
.data
+ sym
->value
;
2864 caller
= find_caller(ss
, sym
);
2865 return strprintf("%s<%s>", basename
, caller
);
2868 static char *symbol_label(struct superbfd
*sbfd
, asymbol
*sym
)
2870 const char *filename
= sbfd
->abfd
->filename
;
2871 char *c
= strstr(filename
, ".KSPLICE");
2872 int flen
= (c
== NULL
? strlen(filename
) : c
- filename
);
2875 if (bfd_is_und_section(sym
->section
) || (sym
->flags
& BSF_GLOBAL
) != 0) {
2876 label
= strdup(sym
->name
);
2877 } else if (bfd_is_const_section(sym
->section
)) {
2878 label
= strprintf("%s<%.*s>", sym
->name
, flen
, filename
);
2880 asymbol
*gsym
= canonical_symbol(sbfd
, sym
);
2883 label
= strprintf("%s+%lx<%.*s>",
2885 (unsigned long)sym
->value
,
2887 else if ((gsym
->flags
& BSF_GLOBAL
) != 0)
2888 label
= strdup(gsym
->name
);
2889 else if (static_local_symbol(sbfd
, gsym
))
2890 label
= strprintf("%s+%lx<%.*s>",
2891 static_local_symbol(sbfd
, gsym
),
2892 (unsigned long)sym
->value
,
2895 label
= strprintf("%s<%.*s>",
2896 gsym
->name
, flen
, filename
);
2902 static void keep_span(struct span
*span
)
2905 span
->ss
->keep
= true;
2908 static struct span
*new_span(struct supersect
*ss
, bfd_vma start
, bfd_vma size
)
2910 struct span
*span
= vec_grow(&ss
->spans
, 1);
2912 span
->contents_size
= size
;
2913 span
->start
= start
;
2917 span
->patch
= false;
2918 span
->bugpatch
= false;
2919 span
->datapatch
= false;
2920 span
->precallable
= strstarts(ss
->name
, ".ksplice_call_pre_apply") ||
2921 strstarts(ss
->name
, ".ksplice_call_check_apply") ||
2922 strstarts(ss
->name
, ".ksplice_call_fail_apply") ||
2923 strstarts(ss
->name
, ".ksplice_call_post_remove");
2926 asymbol
**symp
= symbolp_scan(ss
, span
->start
);
2928 span
->symbol
= *symp
;
2929 span
->label
= label_lookup(ss
->parent
, span
->symbol
);
2931 span
->symbol
= NULL
;
2932 const char *label
= label_lookup(ss
->parent
, ss
->symbol
);
2933 if (span
->start
!= 0)
2934 span
->label
= strprintf("%s<span:%lx>", label
,
2935 (unsigned long)span
->start
);
2937 span
->label
= label
;
2939 span
->orig_label
= span
->label
;
2943 static void initialize_string_spans(struct supersect
*ss
)
2946 for (str
= ss
->contents
.data
;
2947 (void *)str
< ss
->contents
.data
+ ss
->contents
.size
;) {
2948 bfd_vma start
= (unsigned long)str
-
2949 (unsigned long)ss
->contents
.data
;
2950 bfd_vma size
= strlen(str
) + 1;
2951 bfd_vma contents_size
= size
;
2952 while ((start
+ size
) % (1 << ss
->alignment
) != 0 &&
2953 start
+ size
< ss
->contents
.size
) {
2954 /* Some string sections, like __ksymtab_strings, only
2955 align some strings with the declared alignment */
2956 if (str
[size
] != '\0')
2960 struct span
*span
= new_span(ss
, start
, size
);
2961 span
->contents_size
= contents_size
;
2966 static int compare_ulongs(const void *va
, const void *vb
)
2968 const unsigned long *a
= va
, *b
= vb
;
2972 static void initialize_table_spans(struct superbfd
*sbfd
,
2973 struct table_section
*s
)
2975 asection
*isection
= bfd_get_section_by_name(sbfd
->abfd
, s
->sect
);
2976 if (isection
== NULL
)
2978 struct supersect
*ss
= fetch_supersect(sbfd
, isection
);
2979 if (ss
->alignment
< ffs(s
->entry_align
) - 1)
2980 ss
->alignment
= ffs(s
->entry_align
) - 1;
2982 asection
*other_sect
= NULL
;
2983 if (s
->other_sect
!= NULL
)
2984 other_sect
= bfd_get_section_by_name(sbfd
->abfd
, s
->other_sect
);
2985 struct supersect
*other_ss
= NULL
;
2986 if (other_sect
!= NULL
)
2987 other_ss
= fetch_supersect(sbfd
, other_sect
);
2989 asection
*crc_sect
= NULL
;
2990 if (s
->crc_sect
!= NULL
)
2991 crc_sect
= bfd_get_section_by_name(sbfd
->abfd
, s
->crc_sect
);
2992 struct supersect
*crc_ss
= NULL
;
2993 if (crc_sect
!= NULL
)
2994 crc_ss
= fetch_supersect(sbfd
, crc_sect
);
2996 struct ulong_vec offsets
;
3000 for (entry
= ss
->contents
.data
;
3001 entry
< ss
->contents
.data
+ ss
->contents
.size
;
3002 entry
+= s
->entry_size
) {
3003 struct span
*span
= new_span(ss
, addr_offset(ss
, entry
),
3005 if (s
->entry_contents_size
!= 0)
3006 span
->contents_size
= s
->entry_contents_size
;
3007 if ((span
->symbol
== NULL
||
3008 (span
->symbol
->flags
& BSF_SECTION_SYM
) != 0) &&
3010 arelent
*reloc
= find_reloc(ss
, entry
+ s
->addr_offset
);
3012 struct span
*target_span
= reloc_target_span(ss
, reloc
);
3013 assert(target_span
);
3014 asymbol
*sym
= *reloc
->sym_ptr_ptr
;
3015 unsigned long val
= sym
->value
+
3016 reloc_target_offset(ss
, reloc
) -
3017 (target_span
->start
+ target_span
->shift
);
3018 char *label
= strprintf("%s<target:%s+%lx>", ss
->name
,
3019 target_span
->label
, val
);
3020 change_initial_label(span
, label
);
3023 if (other_sect
!= NULL
) {
3025 bfd_vma offset
= read_reloc(ss
, entry
+ s
->other_offset
,
3026 sizeof(void *), &sym
);
3027 if (sym
->section
== other_sect
) {
3028 assert(offset
>= 0 &&
3029 offset
< other_ss
->contents
.size
);
3030 *vec_grow(&offsets
, 1) = offset
;
3034 if (crc_sect
!= NULL
)
3035 new_span(crc_ss
, addr_offset(ss
, entry
) / s
->entry_size
3036 * s
->crc_size
, s
->crc_size
);
3038 if (ss
->type
== SS_TYPE_EXPORT
) {
3039 const char *symname
= read_string(ss
, entry
+
3041 char *label
= strprintf("%s:%s", ss
->name
, symname
);
3042 change_initial_label(span
, label
);
3046 if (other_sect
== NULL
)
3049 *vec_grow(&offsets
, 1) = 0;
3050 qsort(offsets
.data
, offsets
.size
, sizeof(*offsets
.data
),
3052 *vec_grow(&offsets
, 1) = other_ss
->contents
.size
;
3055 for (off
= offsets
.data
; off
< offsets
.data
+ offsets
.size
- 1; off
++) {
3056 if (*off
!= *(off
+ 1))
3057 new_span(other_ss
, *off
, *(off
+ 1) - *off
);
3061 static void initialize_table_section_spans(struct superbfd
*sbfd
)
3063 struct supersect
*tables_ss
=
3064 fetch_supersect(offsets_sbfd
,
3065 bfd_get_section_by_name(offsets_sbfd
->abfd
,
3066 ".ksplice_table_sections"));
3067 const struct table_section
*ts
;
3068 struct table_section s
;
3069 for (ts
= tables_ss
->contents
.data
;
3070 (void *)ts
< tables_ss
->contents
.data
+ tables_ss
->contents
.size
;
3073 s
.sect
= read_string(tables_ss
, &ts
->sect
);
3074 s
.other_sect
= read_string(tables_ss
, &ts
->other_sect
);
3075 s
.crc_sect
= read_string(tables_ss
, &ts
->crc_sect
);
3076 initialize_table_spans(sbfd
, &s
);
3080 static void initialize_ksplice_call_spans(struct supersect
*ss
)
3083 for (relocp
= ss
->relocs
.data
;
3084 relocp
< ss
->relocs
.data
+ ss
->relocs
.size
; relocp
++) {
3085 arelent
*reloc
= *relocp
;
3086 new_span(ss
, reloc
->address
, bfd_get_reloc_size(reloc
->howto
));
3087 /* the span labels should already be unique */
3091 static void initialize_spans(struct superbfd
*sbfd
)
3094 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
3095 if (is_table_section(sect
->name
, true, true) && mode("keep"))
3098 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
3099 if (ss
->type
== SS_TYPE_STRING
)
3100 initialize_string_spans(ss
);
3101 else if (ss
->type
== SS_TYPE_KSPLICE_CALL
)
3102 initialize_ksplice_call_spans(ss
);
3104 new_span(ss
, 0, ss
->contents
.size
);
3107 initialize_table_section_spans(sbfd
);
3110 /* Returns the span pointed to by the relocation at span->start + offset */
3111 static struct span
*span_offset_target_span(struct span
*span
, int offset
)
3113 void *entry
= span
->ss
->contents
.data
+ span
->start
;
3114 arelent
*reloc
= find_reloc(span
->ss
, entry
+ offset
);
3117 return reloc_target_span(span
->ss
, reloc
);
3120 struct span
*reloc_target_span(struct supersect
*ss
, arelent
*reloc
)
3122 asymbol
*sym_ptr
= *reloc
->sym_ptr_ptr
;
3123 if (bfd_is_const_section(sym_ptr
->section
))
3126 bfd_vma addend
= sym_ptr
->value
+ reloc_target_offset(ss
, reloc
);
3127 struct supersect
*sym_ss
=
3128 fetch_supersect(ss
->parent
, sym_ptr
->section
);
3129 struct span
*span
, *target_span
= sym_ss
->spans
.data
;
3130 for (span
= sym_ss
->spans
.data
;
3131 span
< sym_ss
->spans
.data
+ sym_ss
->spans
.size
; span
++) {
3132 if (addend
>= span
->start
&& addend
< span
->start
+ span
->size
)
3138 static bfd_vma
reloc_target_offset(struct supersect
*ss
, arelent
*reloc
)
3140 bfd_vma offset
= reloc_offset(ss
, reloc
);
3141 if (reloc
->howto
->pc_relative
) {
3142 if ((ss
->flags
& SEC_CODE
) != 0)
3143 return offset
+ bfd_get_reloc_size(reloc
->howto
);
3145 const struct table_section
*ts
= get_table_section(ss
->name
);
3146 if (ts
!= NULL
&& ts
->relative_addr
&&
3147 reloc
->address
% ts
->entry_size
== ts
->addr_offset
)
3148 return offset
- ts
->addr_offset
;
3149 if (ts
!= NULL
&& ts
->relative_other
&&
3150 reloc
->address
% ts
->entry_size
== ts
->other_offset
)
3151 return offset
- ts
->other_offset
;
3158 struct span
*find_span(struct supersect
*ss
, bfd_size_type address
)
3161 for (span
= ss
->spans
.data
; span
< ss
->spans
.data
+ ss
->spans
.size
;
3163 if (address
>= span
->start
&&
3164 address
< span
->start
+ span
->size
)
3167 /* Deal with empty BSS sections */
3168 if (ss
->contents
.size
== 0 && ss
->spans
.size
> 0)
3169 return ss
->spans
.data
;
3170 /* Deal with section end pointers */
3171 if (address
== ss
->contents
.size
&& ss
->spans
.size
== 1)
3172 return ss
->spans
.data
;
3176 void compute_span_shifts(struct superbfd
*sbfd
)
3180 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
3181 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
3184 bfd_size_type offset
= 0;
3185 for (span
= ss
->spans
.data
;
3186 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++) {
3189 span
->shift
= offset
- span
->start
;
3190 offset
+= span
->size
;
3195 void remove_unkept_spans(struct superbfd
*sbfd
)
3199 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
3200 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
3201 delete_obsolete_relocs(ss
);
3202 struct arelentp_vec orig_relocs
;
3203 vec_move(&orig_relocs
, &ss
->relocs
);
3204 arelent
**relocp
, *reloc
;
3205 for (relocp
= orig_relocs
.data
;
3206 relocp
< orig_relocs
.data
+ orig_relocs
.size
; relocp
++) {
3208 asymbol
*sym
= *reloc
->sym_ptr_ptr
;
3209 span
= reloc_target_span(ss
, reloc
);
3210 if ((span
!= NULL
&& span
->keep
&& span
->shift
== 0) ||
3211 bfd_is_const_section(sym
->section
)) {
3212 *vec_grow(&ss
->relocs
, 1) = reloc
;
3215 struct supersect
*sym_ss
=
3216 fetch_supersect(sbfd
, sym
->section
);
3217 if (span
!= NULL
&& (sym
->flags
& BSF_SECTION_SYM
) == 0
3218 && find_span(sym_ss
, sym
->value
) != span
) {
3219 err(sbfd
, "Spans for symbol %s and relocation "
3220 "target do not match in sect %s\n",
3221 sym
->name
, sym_ss
->name
);
3224 if (span
!= NULL
&& span
->keep
) {
3225 arelent
*new_reloc
= malloc(sizeof(*new_reloc
));
3226 *new_reloc
= *reloc
;
3227 new_reloc
->addend
= reloc_offset(ss
, reloc
);
3228 new_reloc
->addend
+= span
->shift
;
3229 *vec_grow(&ss
->new_relocs
, 1) = new_reloc
;
3234 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
3235 struct supersect
*ss
= fetch_supersect(sbfd
, sect
), orig_ss
;
3238 supersect_move(&orig_ss
, ss
);
3239 vec_init(&ss
->spans
);
3240 for (span
= orig_ss
.spans
.data
;
3241 span
< orig_ss
.spans
.data
+ orig_ss
.spans
.size
; span
++) {
3244 struct span
*new_span
= vec_grow(&ss
->spans
, 1);
3246 new_span
->start
= span
->start
+ span
->shift
;
3247 new_span
->shift
= 0;
3248 sect_copy(ss
, sect_do_grow(ss
, 1, span
->size
, 1),
3249 &orig_ss
, orig_ss
.contents
.data
+ span
->start
,
3255 static void init_objmanip_superbfd(struct superbfd
*sbfd
)
3257 init_label_map(sbfd
);
3258 initialize_supersect_types(sbfd
);
3259 initialize_spans(sbfd
);
3263 void mangle_section_name(struct superbfd
*sbfd
, const char *name
)
3265 asection
*sect
= bfd_get_section_by_name(sbfd
->abfd
, name
);
3268 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
3269 ss
->name
= strprintf(".ksplice_pre.%s", ss
->name
);
3272 static void write_bugline_patches(struct superbfd
*sbfd
)
3274 const struct table_section
*ts
= get_table_section("__bug_table");
3275 asection
*sect
= bfd_get_section_by_name(sbfd
->abfd
, "__bug_table");
3278 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
3282 for (entry
= ss
->contents
.data
;
3283 entry
< ss
->contents
.data
+ ss
->contents
.size
;
3284 entry
+= ts
->entry_size
) {
3285 struct span
*span
= find_span(ss
, addr_offset(ss
, entry
));
3286 assert(span
!= NULL
);
3287 if (!span
->bugpatch
)
3289 arelent
*reloc
= find_reloc(ss
, entry
+ ts
->addr_offset
);
3290 assert(reloc
!= NULL
);
3291 asymbol
*sym
= *reloc
->sym_ptr_ptr
;
3292 assert(!bfd_is_const_section(sym
->section
));
3293 struct supersect
*kpatch_ss
=
3294 make_section(sbfd
, ".ksplice_patches%s",
3295 sym
->section
->name
);
3297 bfd_vma offset
, start
= 0;
3298 for (offset
= 0; offset
<= span
->size
; offset
++) {
3299 if (offset
!= span
->size
&&
3300 !part_of_reloc(ss
, span
->start
+ offset
))
3302 if (start
== offset
) {
3306 /* an interval of non-relocations just passed */
3307 struct ksplice_patch
*kpatch
=
3308 sect_grow(kpatch_ss
, 1, struct ksplice_patch
);
3309 write_ksplice_patch_reloc
3310 (kpatch_ss
, sym
->section
->name
, &kpatch
->oldaddr
,
3311 sizeof(kpatch
->oldaddr
), span
->label
, start
);
3313 char *data
= write_patch_storage(kpatch_ss
, kpatch
,
3314 offset
- start
, NULL
);
3315 memcpy(data
, entry
+ start
, offset
- start
);
3316 kpatch
->type
= KSPLICE_PATCH_DATA
;
3322 void *write_patch_storage(struct supersect
*ss
, struct ksplice_patch
*kpatch
,
3323 size_t size
, struct supersect
**data_ssp
)
3325 struct supersect
*data_ss
= make_section(ss
->parent
,
3326 ".ksplice_patch_data");
3327 char *saved
= sect_do_grow(data_ss
, 1, size
, 1);
3328 write_reloc(ss
, &kpatch
->saved
, &data_ss
->symbol
,
3329 addr_offset(data_ss
, saved
));
3330 char *data
= sect_do_grow(data_ss
, 1, size
, 1);
3331 write_reloc(ss
, &kpatch
->contents
, &data_ss
->symbol
,
3332 addr_offset(data_ss
, data
));
3333 kpatch
->size
= size
;
3334 if (data_ssp
!= NULL
)
3335 *data_ssp
= data_ss
;