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-primary: "objmanip <post.o> <out.o> keep-primary <pre.o> <kid>"
26 * This mode prepares the object file to be installed as a ksplice update. The
27 * kid argument is the ksplice id string for the ksplice update being built.
29 * - keep-helper: "objmanip <pre.o> <out.o> keep-helper"
31 * This mode prepares the object file to be used for run-pre matching. This
32 * involves replacing all ELF relocations with ksplice relocations and
33 * writing ksplice_section structures for each ELF text or data section.
35 * - rmsyms mode: "objmanip <in.o> <out.o> rmsyms
37 * In this mode, any ELF relocations involving the list of symbol names given on
38 * standard input are replaced with ksplice relocations. This is used only
39 * for KSPLICE_STANDALONE.
41 * - finalize mode: "objmanip <in.o> <out.o> finalize"
43 * In this mode, any ELF relocations to undefined symbols are replaced with
44 * ksplice relocations.
47 /* Always define KSPLICE_STANDALONE, even if you're using integrated Ksplice.
48 objmanip won't compile without it. */
49 #define KSPLICE_STANDALONE
52 #include "objcommon.h"
53 #include "kmodsrc/ksplice.h"
54 #include "kmodsrc/offsets.h"
55 #include "ksplice-patch/ksplice-patch.h"
62 #define KSPLICE_SYMBOL_STR "KSPLICE_SYMBOL_"
64 #define symbol_init(sym) *(sym) = (asymbol *)NULL
65 DEFINE_HASH_TYPE(asymbol
*, symbol_hash
, symbol_hash_init
, symbol_hash_free
,
66 symbol_hash_lookup
, symbol_init
);
68 DECLARE_VEC_TYPE(const char *, str_vec
);
70 DECLARE_VEC_TYPE(unsigned long, ulong_vec
);
72 #define bool_init(b) *(b) = false
73 DEFINE_HASH_TYPE(bool, bool_hash
, bool_hash_init
, bool_hash_free
,
74 bool_hash_lookup
, bool_init
);
76 #define ulong_init(x) *(x) = 0
77 DEFINE_HASH_TYPE(unsigned long, ulong_hash
, ulong_hash_init
,
78 ulong_hash_free
, ulong_hash_lookup
, ulong_init
);
80 void do_keep_primary(struct superbfd
*isbfd
, const char *pre
);
81 void do_keep_helper(struct superbfd
*isbfd
);
82 void do_finalize(struct superbfd
*isbfd
);
83 void do_rmsyms(struct superbfd
*isbfd
);
85 bool relocs_equal(struct supersect
*old_src_ss
, struct supersect
*new_src_ss
,
86 arelent
*old_reloc
, arelent
*new_reloc
);
87 bfd_vma
non_dst_mask(struct supersect
*ss
, arelent
*reloc
);
88 bool all_relocs_equal(struct span
*old_span
, struct span
*new_span
);
89 static bool part_of_reloc(struct supersect
*ss
, unsigned long addr
);
90 static bool nonrelocs_equal(struct span
*old_span
, struct span
*new_span
);
91 static void handle_section_symbol_renames(struct superbfd
*oldsbfd
,
92 struct superbfd
*newsbfd
);
94 enum supersect_type
supersect_type(struct supersect
*ss
);
95 void initialize_supersect_types(struct superbfd
*sbfd
);
96 static void initialize_spans(struct superbfd
*sbfd
);
97 static void initialize_string_spans(struct supersect
*ss
);
98 static void initialize_table_spans(struct superbfd
*sbfd
,
99 struct table_section
*s
);
100 static void initialize_table_section_spans(struct superbfd
*sbfd
);
101 static void initialize_ksplice_call_spans(struct supersect
*ss
);
102 struct span
*reloc_target_span(struct supersect
*ss
, arelent
*reloc
);
103 static struct span
*span_offset_target_span(struct span
*span
, int offset
);
104 struct span
*find_span(struct supersect
*ss
, bfd_size_type address
);
105 void remove_unkept_spans(struct superbfd
*sbfd
);
106 void compute_span_shifts(struct superbfd
*sbfd
);
107 static struct span
*new_span(struct supersect
*ss
, bfd_vma start
, bfd_vma size
);
108 static bool is_table_section(const char *name
, bool consider_other
,
110 const struct table_section
*get_table_section(const char *name
);
111 void mangle_section_name(struct superbfd
*sbfd
, const char *name
);
113 void rm_relocs(struct superbfd
*isbfd
);
114 void rm_some_relocs(struct supersect
*ss
);
115 void write_ksplice_reloc(struct supersect
*ss
, arelent
*orig_reloc
);
116 static void write_ksplice_reloc_howto(struct supersect
*ss
, const
117 struct ksplice_reloc_howto
*const *addr
,
118 reloc_howto_type
*howto
,
119 enum ksplice_reloc_howto_type type
);
120 static void write_ksplice_date_reloc(struct supersect
*ss
, unsigned long offset
,
122 enum ksplice_reloc_howto_type type
);
123 static void write_ksplice_patch_reloc(struct supersect
*ss
,
124 const char *sectname
, unsigned long *addr
,
125 bfd_size_type size
, const char *label
,
127 static void write_ksplice_nonreloc_howto(struct supersect
*ss
,
128 const struct ksplice_reloc_howto
130 enum ksplice_reloc_howto_type type
,
132 static void write_date_relocs(struct superbfd
*sbfd
, const char *str
,
133 enum ksplice_reloc_howto_type type
);
134 static void write_table_relocs(struct superbfd
*sbfd
, const char *sectname
,
135 enum ksplice_reloc_howto_type type
);
136 static void write_ksplice_table_reloc(struct supersect
*ss
,
137 unsigned long address
,
139 enum ksplice_reloc_howto_type type
);
140 void load_ksplice_symbol_offsets(struct superbfd
*sbfd
);
141 void write_canary(struct supersect
*ss
, int offset
, bfd_size_type size
,
143 static void write_ksplice_section(struct span
*span
);
144 void write_ksplice_patch(struct superbfd
*sbfd
, struct span
*span
);
145 void *write_patch_storage(struct supersect
*ss
, struct ksplice_patch
*patch
,
146 size_t size
, struct supersect
**data_ssp
);
147 void write_ksplice_deleted_patch(struct superbfd
*sbfd
, const char *name
,
148 const char *label
, const char *sectname
);
149 static void write_bugline_patches(struct superbfd
*sbfd
);
150 asymbol
**make_undefined_symbolp(struct superbfd
*sbfd
, const char *name
);
151 void filter_table_sections(struct superbfd
*isbfd
);
152 void filter_table_section(struct superbfd
*sbfd
, const struct table_section
*s
);
153 void keep_referenced_sections(struct superbfd
*sbfd
);
154 void mark_precallable_spans(struct superbfd
*sbfd
);
155 bfd_boolean
copy_object(bfd
*ibfd
, bfd
*obfd
);
156 void setup_section(bfd
*ibfd
, asection
*isection
, void *obfdarg
);
157 static void setup_new_section(bfd
*obfd
, struct supersect
*ss
);
158 static void write_section(bfd
*obfd
, asection
*osection
, void *arg
);
159 static void delete_obsolete_relocs(struct supersect
*ss
);
160 void mark_symbols_used_in_relocations(bfd
*abfd
, asection
*isection
,
162 static void ss_mark_symbols_used_in_relocations(struct supersect
*ss
);
163 void filter_symbols(bfd
*ibfd
, bfd
*obfd
, struct asymbolp_vec
*osyms
,
164 struct asymbolp_vec
*isyms
);
165 static bool deleted_table_section_symbol(bfd
*abfd
, asymbol
*sym
);
166 void read_str_set(struct str_vec
*strs
);
167 bool str_in_set(const char *str
, const struct str_vec
*strs
);
168 struct supersect
*__attribute((format(printf
, 2, 3)))
169 make_section(struct superbfd
*sbfd
, const char *fmt
, ...);
170 void __attribute__((format(printf
, 3, 4)))
171 write_string(struct supersect
*ss
, const char **addr
, const char *fmt
, ...);
172 void write_ksplice_export(struct superbfd
*sbfd
, struct span
*span
, bool del
);
173 void write_reloc(struct supersect
*ss
, const void *addr
, asymbol
**symp
,
175 arelent
*create_reloc(struct supersect
*ss
, const void *addr
, asymbol
**symp
,
177 static void foreach_symbol_pair(struct superbfd
*oldsbfd
, struct superbfd
*newsbfd
,
178 void (*fn
)(struct span
*old_span
,
180 struct span
*new_span
,
182 static void check_global_symbols(struct span
*old_span
, asymbol
*oldsym
,
183 struct span
*new_span
, asymbol
*newsym
);
184 static void match_global_symbols(struct span
*old_span
, asymbol
*oldsym
,
185 struct span
*new_span
, asymbol
*newsym
);
186 static void match_symbol_spans(struct span
*old_span
, asymbol
*oldsym
,
187 struct span
*new_span
, asymbol
*newsym
);
188 static void match_table_spans(struct span
*old_span
, struct span
*new_span
);
190 static struct span
*get_crc_span(struct span
*span
,
191 const struct table_section
*ts
);
192 static void foreach_span_pair(struct superbfd
*oldsbfd
,
193 struct superbfd
*newsbfd
,
194 void (*fn
)(struct span
*old_span
,
195 struct span
*new_span
));
196 static void match_spans_by_label(struct span
*old_span
, struct span
*new_span
);
197 static void match_string_spans(struct span
*old_span
, struct span
*new_span
);
198 static void mark_new_spans(struct superbfd
*sbfd
);
199 static void handle_deleted_spans(struct superbfd
*oldsbfd
,
200 struct superbfd
*newsbfd
);
201 static void unmatch_addr_spans(struct span
*old_span
, struct span
*new_span
,
202 const struct table_section
*ts
);
203 static void compare_matched_spans(struct superbfd
*newsbfd
);
204 static void compare_spans(struct span
*old_span
, struct span
*new_span
);
205 static void update_nonzero_offsets(struct superbfd
*sbfd
);
206 static void handle_nonzero_offset_relocs(struct supersect
*ss
);
207 static void keep_span(struct span
*span
);
209 static void init_objmanip_superbfd(struct superbfd
*sbfd
);
210 static const char *label_lookup(struct superbfd
*sbfd
, asymbol
*sym
);
211 static void label_map_set(struct superbfd
*sbfd
, const char *oldlabel
,
213 static void print_label_changes(struct superbfd
*sbfd
);
214 static void init_label_map(struct superbfd
*sbfd
);
215 static void change_initial_label(struct span
*span
, const char *label
);
216 static asymbol
**symbolp_scan(struct supersect
*ss
, bfd_vma value
);
217 static void init_csyms(struct superbfd
*sbfd
);
218 static void init_callers(struct superbfd
*sbfd
);
219 static asymbol
*canonical_symbol(struct superbfd
*sbfd
, asymbol
*sym
);
220 static asymbol
**canonical_symbolp(struct superbfd
*sbfd
, asymbol
*sym
);
221 static char *static_local_symbol(struct superbfd
*sbfd
, asymbol
*sym
);
222 static char *symbol_label(struct superbfd
*sbfd
, asymbol
*sym
);
225 #define debug_(sbfd, level, fmt, ...) \
227 if (verbose >= (level)) \
228 printf("%s: " fmt, (sbfd)->abfd->filename, \
231 #define debug0(sbfd, fmt, ...) debug_(sbfd, 0, fmt, ## __VA_ARGS__)
232 #define debug1(sbfd, fmt, ...) debug_(sbfd, 1, fmt, ## __VA_ARGS__)
233 #define err(sbfd, fmt, ...) \
235 fprintf(stderr, "%s: " fmt, (sbfd)->abfd->filename, \
239 struct str_vec delsects
, rmsyms
;
242 struct ksplice_config
*config
;
244 const char *modestr
, *kid
, *finalize_target
= NULL
;
245 bool write_output
= true;
247 struct superbfd
*offsets_sbfd
= NULL
;
249 #define mode(str) starts_with(modestr, str)
251 DECLARE_VEC_TYPE(unsigned long, addr_vec
);
252 DEFINE_HASH_TYPE(struct addr_vec
, addr_vec_hash
,
253 addr_vec_hash_init
, addr_vec_hash_free
, addr_vec_hash_lookup
,
255 struct addr_vec_hash system_map
;
257 struct bool_hash system_map_written
;
258 struct ulong_hash ksplice_symbol_offset
;
259 struct ulong_hash ksplice_howto_offset
;
260 struct ulong_hash ksplice_string_offset
;
262 void load_system_map()
264 const char *config_dir
= getenv("KSPLICE_CONFIG_DIR");
266 FILE *fp
= fopen(strprintf("%s/System.map", config_dir
), "r");
268 addr_vec_hash_init(&system_map
);
272 while (fscanf(fp
, "%lx %c %as\n", &addr
, &type
, &sym
) == 3)
273 *vec_grow(addr_vec_hash_lookup(&system_map
, sym
, TRUE
),
278 void load_ksplice_symbol_offsets(struct superbfd
*sbfd
)
280 asection
*sect
= bfd_get_section_by_name(sbfd
->abfd
,
284 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
286 struct ksplice_symbol
*ksym
;
287 for (ksym
= ss
->contents
.data
;
288 (void *)ksym
< ss
->contents
.data
+ ss
->contents
.size
; ksym
++) {
289 const char *label
= read_string(ss
, &ksym
->label
);
290 unsigned long *ksymbol_offp
=
291 ulong_hash_lookup(&ksplice_symbol_offset
, label
, TRUE
);
292 *ksymbol_offp
= addr_offset(ss
, ksym
);
298 char *kmodsrc
= getenv("KSPLICE_KMODSRC");
299 assert(kmodsrc
!= NULL
);
300 bfd
*offsets_bfd
= bfd_openr(strprintf("%s/offsets.o", kmodsrc
), NULL
);
301 assert(offsets_bfd
!= NULL
);
303 assert(bfd_check_format_matches(offsets_bfd
, bfd_object
, &matching
));
304 offsets_sbfd
= fetch_superbfd(offsets_bfd
);
306 asection
*config_sect
= bfd_get_section_by_name(offsets_sbfd
->abfd
,
308 struct supersect
*config_ss
=
309 fetch_supersect(offsets_sbfd
, config_sect
);
311 config
= config_ss
->contents
.data
;
314 void load_options(struct superbfd
*sbfd
)
316 asection
*sect
= bfd_get_section_by_name(sbfd
->abfd
,
320 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
321 const struct ksplice_option
*opt
;
322 for (opt
= ss
->contents
.data
;
323 (void *)opt
< ss
->contents
.data
+ ss
->contents
.size
; opt
++) {
324 if (opt
->type
== KSPLICE_OPTION_ASSUME_RODATA
) {
325 arelent
*reloc
= find_reloc(ss
, &opt
->target
);
326 struct span
*span
= reloc_target_span(ss
, reloc
);
327 assert(span
!= NULL
);
328 assert(span
->ss
->type
== SS_TYPE_DATA
);
329 assert(span
->start
== 0 &&
330 span
->size
== span
->ss
->contents
.size
);
331 span
->ss
->type
= SS_TYPE_RODATA
;
334 err(sbfd
, "Unrecognized Ksplice option %d\n",
341 bool matchable_data_section(struct supersect
*ss
)
343 if (ss
->type
== SS_TYPE_STRING
)
345 if (ss
->type
== SS_TYPE_RODATA
)
347 if (ss
->type
== SS_TYPE_DATA
&& ss
->relocs
.size
!= 0)
349 if (ss
->type
== SS_TYPE_EXPORT
)
354 bool unchangeable_section(struct supersect
*ss
)
356 if (ss
->type
== SS_TYPE_DATA
)
358 if (ss
->type
== SS_TYPE_IGNORED
&& !starts_with(ss
->name
, ".debug") &&
359 strcmp(ss
->name
, "__ksymtab_strings") != 0)
364 int main(int argc
, char *argv
[])
366 if (getenv("KSPLICE_VERBOSE") != NULL
)
367 verbose
= atoi(getenv("KSPLICE_VERBOSE"));
370 bfd
*ibfd
= bfd_openr(argv
[1], NULL
);
374 assert(bfd_check_format_matches(ibfd
, bfd_object
, &matching
));
376 const char *output_target
= bfd_get_target(ibfd
);
381 bool_hash_init(&system_map_written
);
382 ulong_hash_init(&ksplice_symbol_offset
);
383 ulong_hash_init(&ksplice_howto_offset
);
384 ulong_hash_init(&ksplice_string_offset
);
386 struct superbfd
*isbfd
= fetch_superbfd(ibfd
);
389 if (mode("finalize"))
390 finalize_target
= argv
[4];
391 init_objmanip_superbfd(isbfd
);
392 if (mode("keep-primary")) {
394 do_keep_primary(isbfd
, argv
[4]);
395 } else if (mode("keep-helper")) {
396 do_keep_helper(isbfd
);
397 } else if (mode("finalize")) {
399 } else if (mode("rmsyms")) {
404 bfd
*obfd
= bfd_openw(argv
[2], output_target
);
406 copy_object(ibfd
, obfd
);
407 assert(bfd_close(obfd
));
410 if (offsets_sbfd
!= NULL
)
411 assert(bfd_close(offsets_sbfd
->abfd
));
412 assert(bfd_close(ibfd
));
416 void do_keep_primary(struct superbfd
*isbfd
, const char *pre
)
418 struct bfd
*prebfd
= bfd_openr(pre
, NULL
);
419 assert(prebfd
!= NULL
);
421 assert(bfd_check_format_matches(prebfd
, bfd_object
, &matching
));
423 struct superbfd
*presbfd
= fetch_superbfd(prebfd
);
424 init_objmanip_superbfd(presbfd
);
426 foreach_symbol_pair(presbfd
, isbfd
, match_global_symbols
);
427 debug1(isbfd
, "Matched global\n");
428 foreach_span_pair(presbfd
, isbfd
, match_string_spans
);
429 debug1(isbfd
, "Matched string spans\n");
430 foreach_symbol_pair(presbfd
, isbfd
, match_symbol_spans
);
431 debug1(isbfd
, "Matched by name\n");
432 foreach_span_pair(presbfd
, isbfd
, match_spans_by_label
);
433 debug1(isbfd
, "Matched by label\n");
434 foreach_span_pair(presbfd
, isbfd
, match_table_spans
);
435 debug1(isbfd
, "Matched table spans\n");
439 compare_matched_spans(isbfd
);
440 update_nonzero_offsets(isbfd
);
441 mark_new_spans(isbfd
);
445 foreach_symbol_pair(presbfd
, isbfd
, check_global_symbols
);
447 handle_deleted_spans(presbfd
, isbfd
);
448 handle_section_symbol_renames(presbfd
, isbfd
);
450 assert(bfd_close(prebfd
));
454 mark_precallable_spans(isbfd
);
458 for (sect
= isbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
459 struct supersect
*ss
= fetch_supersect(isbfd
, sect
);
462 for (span
= ss
->spans
.data
;
463 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++) {
464 if (starts_with(ss
->name
, ".ksplice_options"))
466 else if (span
->new || span
->patch
|| span
->datapatch
)
470 if (span
->patch
&& span
->precallable
) {
471 err(isbfd
, "Patched span %s can be reached "
472 "by a precall function\n", span
->label
);
478 print_label_changes(isbfd
);
480 for (sect
= isbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
481 struct supersect
*ss
= fetch_supersect(isbfd
, sect
);
483 for (span
= ss
->spans
.data
;
484 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++) {
485 if (span
->patch
|| span
->bugpatch
|| span
->datapatch
)
486 debug0(isbfd
, "Patching span %s\n",
491 for (sect
= isbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
492 struct supersect
*ss
= fetch_supersect(isbfd
, sect
);
494 for (span
= ss
->spans
.data
;
495 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++) {
497 debug0(isbfd
, "New span %s\n", span
->label
);
501 write_output
= false;
502 const char **sectname
;
503 for (sectname
= delsects
.data
;
504 sectname
< delsects
.data
+ delsects
.size
; sectname
++) {
506 debug0(isbfd
, "Deleted section: %s\n", *sectname
);
509 filter_table_sections(isbfd
);
511 compute_span_shifts(isbfd
);
513 for (sect
= isbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
514 struct supersect
*ss
= fetch_supersect(isbfd
, sect
);
515 if (ss
->type
== SS_TYPE_KSPLICE_CALL
)
518 for (span
= ss
->spans
.data
;
519 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++) {
522 if (span
->patch
|| span
->new || span
->datapatch
)
523 write_ksplice_section(span
);
524 if (span
->patch
|| span
->datapatch
)
525 write_ksplice_patch(isbfd
, span
);
526 if (ss
->type
== SS_TYPE_EXPORT
&& span
->new)
527 write_ksplice_export(isbfd
, span
, false);
531 write_bugline_patches(isbfd
);
533 remove_unkept_spans(isbfd
);
536 void do_keep_helper(struct superbfd
*isbfd
)
539 for (sect
= isbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
540 struct supersect
*ss
= fetch_supersect(isbfd
, sect
);
543 for (span
= ss
->spans
.data
;
544 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++) {
546 if (ss
->type
== SS_TYPE_TEXT
&&
547 !starts_with(ss
->name
, ".fixup"))
549 if (ss
->type
== SS_TYPE_EXPORT
)
555 for (symp
= isbfd
->syms
.data
;
556 symp
< isbfd
->syms
.data
+ isbfd
->syms
.size
; symp
++) {
557 asymbol
*sym
= *symp
;
558 if (!bfd_is_const_section(sym
->section
) &&
559 (sym
->flags
& BSF_GLOBAL
) != 0) {
560 struct supersect
*sym_ss
=
561 fetch_supersect(isbfd
, sym
->section
);
562 if (sym
->value
== sym_ss
->contents
.size
)
564 struct span
*span
= find_span(sym_ss
, sym
->value
);
565 assert(span
!= NULL
);
566 if (sym_ss
->type
!= SS_TYPE_IGNORED
)
573 keep_referenced_sections(isbfd
);
576 filter_table_sections(isbfd
);
577 compute_span_shifts(isbfd
);
579 for (sect
= isbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
580 struct supersect
*ss
= fetch_supersect(isbfd
, sect
);
581 asymbol
*sym
= canonical_symbol(isbfd
, sect
->symbol
);
584 if ((sym
->flags
& BSF_WEAK
) != 0)
586 if (bfd_get_section_size(sect
) == 0)
590 if (ss
->type
!= SS_TYPE_TEXT
&& !matchable_data_section(ss
))
594 for (span
= ss
->spans
.data
;
595 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++) {
597 write_ksplice_section(span
);
601 write_table_relocs(isbfd
, "__bug_table", KSPLICE_HOWTO_BUG
);
602 write_table_relocs(isbfd
, "__ex_table", KSPLICE_HOWTO_EXTABLE
);
604 remove_unkept_spans(isbfd
);
606 mangle_section_name(isbfd
, "__markers");
607 mangle_section_name(isbfd
, "__ex_table");
608 for (sect
= isbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
609 struct supersect
*ss
= fetch_supersect(isbfd
, sect
);
610 if (ss
->type
== SS_TYPE_EXPORT
)
611 mangle_section_name(isbfd
, ss
->name
);
615 void do_finalize(struct superbfd
*isbfd
)
617 load_ksplice_symbol_offsets(isbfd
);
619 for (sect
= isbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
620 struct supersect
*ss
= fetch_supersect(isbfd
, sect
);
621 if (ss
->type
== SS_TYPE_EXIT
) {
623 for (span
= ss
->spans
.data
;
624 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++)
629 write_date_relocs(isbfd
, "<{DATE...}>", KSPLICE_HOWTO_DATE
);
630 write_date_relocs(isbfd
, "<{TIME}>", KSPLICE_HOWTO_TIME
);
634 void do_rmsyms(struct superbfd
*isbfd
)
636 read_str_set(&rmsyms
);
640 void match_spans(struct span
*old_span
, struct span
*new_span
)
642 struct superbfd
*sbfd
= new_span
->ss
->parent
;
643 if (old_span
->match
== new_span
&& new_span
->match
== old_span
)
645 if (old_span
->match
!= NULL
) {
646 err(sbfd
, "Matching conflict: old %s: %s != %s\n",
647 old_span
->label
, old_span
->match
->label
, new_span
->label
);
650 if (new_span
->match
!= NULL
) {
651 err(sbfd
, "Matching conflict: new %s: %s != %s\n",
652 new_span
->label
, new_span
->match
->label
, old_span
->label
);
655 old_span
->match
= new_span
;
656 new_span
->match
= old_span
;
657 debug1(sbfd
, "Matched old %s to new %s\n", old_span
->label
,
659 if (old_span
->ss
->type
!= new_span
->ss
->type
&&
660 old_span
->ss
->type
== new_span
->ss
->orig_type
)
661 old_span
->ss
->type
= new_span
->ss
->type
;
663 const struct table_section
*ts
= get_table_section(old_span
->ss
->name
);
664 if (ts
== NULL
|| !ts
->has_addr
|| ts
->other_sect
== NULL
)
666 struct span
*old_sym_span
=
667 span_offset_target_span(old_span
, ts
->other_offset
);
668 struct span
*new_sym_span
=
669 span_offset_target_span(new_span
, ts
->other_offset
);
670 assert(old_sym_span
!= NULL
&& new_sym_span
!= NULL
);
671 match_spans(old_sym_span
, new_sym_span
);
674 static void match_global_symbols(struct span
*old_span
, asymbol
*oldsym
,
675 struct span
*new_span
, asymbol
*newsym
)
677 if ((oldsym
->flags
& BSF_GLOBAL
) == 0 ||
678 (newsym
->flags
& BSF_GLOBAL
) == 0)
680 match_spans(old_span
, new_span
);
683 static void check_global_symbols(struct span
*old_span
, asymbol
*oldsym
,
684 struct span
*new_span
, asymbol
*newsym
)
686 if ((oldsym
->flags
& BSF_GLOBAL
) == 0 ||
687 (newsym
->flags
& BSF_GLOBAL
) == 0)
689 if (old_span
->ss
->type
== SS_TYPE_IGNORED
)
691 if (old_span
->match
!= new_span
|| new_span
->match
!= old_span
) {
692 err(new_span
->ss
->parent
, "Global symbol span mismatch: %s "
693 "%s/%s\n", oldsym
->name
, old_span
->ss
->name
,
699 static void foreach_symbol_pair(struct superbfd
*oldsbfd
, struct superbfd
*newsbfd
,
700 void (*fn
)(struct span
*old_span
,
702 struct span
*new_span
,
705 asymbol
**oldsymp
, **newsymp
;
706 for (oldsymp
= oldsbfd
->syms
.data
;
707 oldsymp
< oldsbfd
->syms
.data
+ oldsbfd
->syms
.size
; oldsymp
++) {
708 asymbol
*oldsym
= *oldsymp
;
709 if (bfd_is_const_section(oldsym
->section
))
711 for (newsymp
= newsbfd
->syms
.data
;
712 newsymp
< newsbfd
->syms
.data
+ newsbfd
->syms
.size
;
714 asymbol
*newsym
= *newsymp
;
715 if (bfd_is_const_section(newsym
->section
))
717 if (strcmp(oldsym
->name
, newsym
->name
) != 0)
720 struct supersect
*old_ss
=
721 fetch_supersect(oldsbfd
, oldsym
->section
);
722 struct supersect
*new_ss
=
723 fetch_supersect(newsbfd
, newsym
->section
);
724 if ((old_ss
->type
!= new_ss
->type
&&
725 old_ss
->type
!= new_ss
->orig_type
) ||
726 old_ss
->type
== SS_TYPE_SPECIAL
||
727 old_ss
->type
== SS_TYPE_EXPORT
)
730 struct span
*old_span
=
731 find_span(old_ss
, oldsym
->value
);
732 struct span
*new_span
=
733 find_span(new_ss
, newsym
->value
);
734 if (old_span
== NULL
) {
735 err(oldsbfd
, "Could not find span for %s\n",
739 if (new_span
== NULL
) {
740 err(newsbfd
, "Could not find span for %s\n",
744 fn(old_span
, oldsym
, new_span
, newsym
);
749 static void match_symbol_spans(struct span
*old_span
, asymbol
*oldsym
,
750 struct span
*new_span
, asymbol
*newsym
)
752 if ((oldsym
->flags
& BSF_DEBUGGING
) != 0 ||
753 (newsym
->flags
& BSF_DEBUGGING
) != 0)
755 if (old_span
->ss
->type
== SS_TYPE_SPECIAL
)
757 if (static_local_symbol(old_span
->ss
->parent
, oldsym
) ||
758 static_local_symbol(new_span
->ss
->parent
, newsym
))
760 if (old_span
->match
== NULL
&& new_span
->match
== NULL
)
761 match_spans(old_span
, new_span
);
764 static void match_spans_by_label(struct span
*old_span
, struct span
*new_span
)
766 if (old_span
->ss
->type
== SS_TYPE_STRING
||
767 (is_table_section(old_span
->ss
->name
, true, false) &&
768 !is_table_section(old_span
->ss
->name
, false, false)))
770 if (strcmp(old_span
->label
, new_span
->label
) == 0)
771 match_spans(old_span
, new_span
);
774 static void match_string_spans(struct span
*old_span
, struct span
*new_span
)
776 if (old_span
->ss
->type
!= SS_TYPE_STRING
||
777 strcmp(old_span
->ss
->name
, new_span
->ss
->name
) != 0)
779 if (strcmp((char *)old_span
->ss
->contents
.data
+ old_span
->start
,
780 (char *)new_span
->ss
->contents
.data
+ new_span
->start
) == 0)
781 match_spans(old_span
, new_span
);
784 static void foreach_span_pair(struct superbfd
*oldsbfd
,
785 struct superbfd
*newsbfd
,
786 void (*fn
)(struct span
*old_span
,
787 struct span
*new_span
))
789 asection
*oldsect
, *newsect
;
790 struct supersect
*oldss
, *newss
;
791 struct span
*old_span
, *new_span
;
792 for (newsect
= newsbfd
->abfd
->sections
; newsect
!= NULL
;
793 newsect
= newsect
->next
) {
794 newss
= fetch_supersect(newsbfd
, newsect
);
795 for (oldsect
= oldsbfd
->abfd
->sections
; oldsect
!= NULL
;
796 oldsect
= oldsect
->next
) {
797 oldss
= fetch_supersect(oldsbfd
, oldsect
);
798 if (oldss
->type
!= newss
->type
)
800 for (new_span
= newss
->spans
.data
;
801 new_span
< newss
->spans
.data
+ newss
->spans
.size
;
803 for (old_span
= oldss
->spans
.data
;
804 old_span
< oldss
->spans
.data
+
805 oldss
->spans
.size
; old_span
++)
806 fn(old_span
, new_span
);
812 static void mark_new_spans(struct superbfd
*sbfd
)
815 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
816 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
817 if (ss
->type
== SS_TYPE_SPECIAL
|| ss
->type
== SS_TYPE_IGNORED
)
820 for (span
= ss
->spans
.data
;
821 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++) {
822 if (span
->match
== NULL
&& !span
->bugpatch
)
828 static void handle_deleted_spans(struct superbfd
*oldsbfd
,
829 struct superbfd
*newsbfd
)
832 for (sect
= oldsbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
833 struct supersect
*ss
= fetch_supersect(oldsbfd
, sect
);
835 for (span
= ss
->spans
.data
;
836 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++) {
837 if (span
->match
!= NULL
)
839 if (ss
->type
== SS_TYPE_EXPORT
) {
840 *vec_grow(&delsects
, 1) = span
->label
;
841 write_ksplice_export(newsbfd
, span
, true);
842 } else if (ss
->type
== SS_TYPE_TEXT
) {
843 *vec_grow(&delsects
, 1) = span
->label
;
844 if (span
->symbol
== NULL
)
846 write_ksplice_deleted_patch
847 (newsbfd
, span
->symbol
->name
, span
->label
,
854 static void handle_nonzero_offset_relocs(struct supersect
*ss
)
856 struct span
*address_span
, *target_span
;
858 for (relocp
= ss
->relocs
.data
;
859 relocp
< ss
->relocs
.data
+ ss
->relocs
.size
; relocp
++) {
860 arelent
*reloc
= *relocp
;
861 address_span
= find_span(ss
, reloc
->address
);
862 if (!address_span
->new && !address_span
->patch
)
865 asymbol
*sym
= *reloc
->sym_ptr_ptr
;
866 if (bfd_is_const_section(sym
->section
))
868 bfd_vma offset
= get_reloc_offset(ss
, reloc
, true);
869 target_span
= reloc_target_span(ss
, reloc
);
870 if (sym
->value
+ offset
== target_span
->start
)
873 if (target_span
->ss
->type
!= SS_TYPE_TEXT
)
875 if (target_span
->patch
)
878 target_span
->patch
= true;
880 debug1(ss
->parent
, "Changing %s because a relocation from sect "
881 "%s has a nonzero offset %lx+%lx into it\n",
882 target_span
->label
, ss
->name
, (unsigned long)sym
->value
,
883 (unsigned long)offset
);
887 static void update_nonzero_offsets(struct superbfd
*sbfd
)
890 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
891 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
892 if (ss
->type
== SS_TYPE_SPECIAL
|| ss
->type
== SS_TYPE_IGNORED
)
894 handle_nonzero_offset_relocs(ss
);
898 static void unmatch_addr_spans(struct span
*old_span
, struct span
*new_span
,
899 const struct table_section
*ts
)
901 struct span
*old_sym_span
=
902 span_offset_target_span(old_span
, ts
->addr_offset
);
903 struct span
*new_sym_span
=
904 span_offset_target_span(new_span
, ts
->addr_offset
);
905 assert(old_sym_span
!= NULL
&& new_sym_span
!= NULL
);
906 if (old_sym_span
->match
== new_sym_span
&&
907 new_sym_span
->match
== old_sym_span
&&
908 !(new_sym_span
->patch
&& new_sym_span
->ss
->type
== SS_TYPE_TEXT
)) {
909 if (old_sym_span
->ss
->type
== SS_TYPE_TEXT
) {
910 debug1(new_span
->ss
->parent
, "Patching %s due "
911 "to relocations from special section %s\n",
912 new_sym_span
->label
, new_span
->label
);
913 new_sym_span
->patch
= true;
915 debug1(new_span
->ss
->parent
, "Unmatching %s and %s due "
916 "to relocations from special section %s/%s\n",
917 old_sym_span
->label
, new_sym_span
->label
,
918 old_span
->label
, new_span
->label
);
919 old_sym_span
->match
= NULL
;
920 new_sym_span
->match
= NULL
;
926 static void compare_spans(struct span
*old_span
, struct span
*new_span
)
928 struct superbfd
*newsbfd
= new_span
->ss
->parent
;
930 bool nonrelocs_match
= nonrelocs_equal(old_span
, new_span
);
931 bool relocs_match
= all_relocs_equal(old_span
, new_span
);
932 if (nonrelocs_match
&& relocs_match
) {
933 const struct table_section
*ts
=
934 get_table_section(old_span
->ss
->name
);
935 if (ts
!= NULL
&& ts
->crc_sect
!= NULL
) {
936 struct span
*old_crc_span
= get_crc_span(old_span
, ts
);
937 struct span
*new_crc_span
= get_crc_span(new_span
, ts
);
938 assert(old_crc_span
!= NULL
);
939 assert(new_crc_span
!= NULL
);
940 if (old_crc_span
->match
!= new_crc_span
||
941 new_crc_span
->match
!= old_crc_span
) {
942 debug1(newsbfd
, "Unmatching %s and %s due to "
943 "nonmatching CRCs\n", old_span
->label
,
945 old_span
->match
= NULL
;
946 new_span
->match
= NULL
;
951 if (strcmp(old_span
->ss
->name
, "__bug_table") == 0 &&
952 strcmp(new_span
->ss
->name
, "__bug_table") == 0 && relocs_match
) {
953 debug1(newsbfd
, "Changing %s due to nonmatching line numbers\n",
955 new_span
->match
= NULL
;
956 old_span
->match
= NULL
;
957 new_span
->bugpatch
= true;
962 if (new_span
->contents_size
!= old_span
->contents_size
)
963 reason
= "differing sizes";
964 else if (!nonrelocs_match
)
965 reason
= "differing contents";
967 reason
= "differing relocations";
969 if (new_span
->ss
->type
== SS_TYPE_TEXT
) {
972 new_span
->patch
= true;
973 debug1(newsbfd
, "Changing %s due to %s\n", new_span
->label
,
975 } else if (new_span
->ss
->type
== SS_TYPE_RODATA
&&
976 new_span
->contents_size
== old_span
->contents_size
) {
977 if (new_span
->datapatch
)
979 new_span
->datapatch
= true;
980 debug1(newsbfd
, "Changing %s in-place due to %s\n",
981 new_span
->label
, reason
);
982 } else if (new_span
->ss
->type
== SS_TYPE_STRING
&&
983 old_span
->ss
->type
== SS_TYPE_STRING
&& relocs_match
&&
984 strcmp(new_span
->ss
->contents
.data
+ new_span
->start
,
985 old_span
->ss
->contents
.data
+ old_span
->start
) == 0) {
988 debug1(newsbfd
, "Unmatching %s and %s due to %s\n",
989 old_span
->label
, new_span
->label
, reason
);
990 new_span
->match
= NULL
;
991 old_span
->match
= NULL
;
992 if (old_span
->ss
->type
== SS_TYPE_SPECIAL
) {
993 const struct table_section
*ts
=
994 get_table_section(old_span
->ss
->name
);
995 if (ts
!= NULL
&& ts
->has_addr
)
996 unmatch_addr_spans(old_span
, new_span
, ts
);
1000 if (unchangeable_section(new_span
->ss
))
1001 err(newsbfd
, "warning: ignoring change to nonpatchable "
1002 "section %s\n", new_span
->ss
->name
);
1005 static void compare_matched_spans(struct superbfd
*newsbfd
)
1008 for (sect
= newsbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
1009 struct supersect
*ss
= fetch_supersect(newsbfd
, sect
);
1011 for (span
= ss
->spans
.data
;
1012 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++) {
1013 if (span
->match
== NULL
)
1015 compare_spans(span
->match
, span
);
1020 static void handle_section_symbol_renames(struct superbfd
*oldsbfd
,
1021 struct superbfd
*newsbfd
)
1025 for (sect
= newsbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
1026 struct supersect
*ss
= fetch_supersect(newsbfd
, sect
);
1027 for (span
= ss
->spans
.data
;
1028 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++) {
1029 if (span
->match
== NULL
)
1031 if (strcmp(span
->label
, span
->match
->label
) == 0)
1033 if (strcmp(span
->orig_label
, span
->label
) != 0 &&
1034 strcmp(span
->label
, span
->match
->label
) != 0)
1036 if (span
->symbol
!= NULL
)
1037 label_map_set(newsbfd
, span
->label
,
1038 span
->match
->label
);
1039 span
->label
= span
->match
->label
;
1044 static bool part_of_reloc(struct supersect
*ss
, unsigned long addr
)
1047 for (relocp
= ss
->relocs
.data
;
1048 relocp
< ss
->relocs
.data
+ ss
->relocs
.size
; relocp
++) {
1049 arelent
*reloc
= *relocp
;
1050 if (addr
>= reloc
->address
&&
1051 addr
< reloc
->address
+ reloc
->howto
->size
)
1057 static bool nonrelocs_equal(struct span
*old_span
, struct span
*new_span
)
1060 struct supersect
*old_ss
= old_span
->ss
, *new_ss
= new_span
->ss
;
1061 if (old_span
->contents_size
!= new_span
->contents_size
)
1063 const unsigned char *old
= old_ss
->contents
.data
+ old_span
->start
;
1064 const unsigned char *new = new_ss
->contents
.data
+ new_span
->start
;
1065 for (i
= 0; i
< old_span
->contents_size
; i
++) {
1066 if (old
[i
] != new[i
] &&
1067 !(part_of_reloc(old_ss
, i
+ old_span
->start
) &&
1068 part_of_reloc(new_ss
, i
+ new_span
->start
)))
1074 bool relocs_equal(struct supersect
*old_src_ss
, struct supersect
*new_src_ss
,
1075 arelent
*old_reloc
, arelent
*new_reloc
)
1077 struct superbfd
*oldsbfd
= old_src_ss
->parent
;
1078 struct superbfd
*newsbfd
= new_src_ss
->parent
;
1079 struct span
*old_addr_span
= find_span(old_src_ss
, old_reloc
->address
);
1080 struct span
*new_addr_span
= find_span(new_src_ss
, new_reloc
->address
);
1082 if (old_reloc
->address
- old_addr_span
->start
!=
1083 new_reloc
->address
- new_addr_span
->start
) {
1084 debug1(newsbfd
, "Section %s/%s has reloc address mismatch at "
1085 "%lx\n", old_src_ss
->name
, new_src_ss
->name
,
1086 (unsigned long)old_reloc
->address
);
1090 if (old_reloc
->howto
!= new_reloc
->howto
) {
1091 debug1(newsbfd
, "Section %s/%s has howto type mismatch at "
1092 "%lx\n", old_src_ss
->name
, new_src_ss
->name
,
1093 (unsigned long)old_reloc
->address
);
1097 if (non_dst_mask(old_src_ss
, old_reloc
) !=
1098 non_dst_mask(new_src_ss
, new_reloc
)) {
1099 debug1(newsbfd
, "Section %s/%s has contents mismatch at %lx\n",
1100 old_src_ss
->name
, new_src_ss
->name
,
1101 (unsigned long)old_reloc
->address
);
1105 asymbol
*old_sym
= *old_reloc
->sym_ptr_ptr
;
1106 asymbol
*new_sym
= *new_reloc
->sym_ptr_ptr
;
1107 asection
*old_sect
= old_sym
->section
;
1108 asection
*new_sect
= new_sym
->section
;
1110 bfd_vma old_offset
= get_reloc_offset(old_src_ss
, old_reloc
, true);
1111 bfd_vma new_offset
= get_reloc_offset(new_src_ss
, new_reloc
, true);
1113 if (bfd_is_und_section(old_sect
) || bfd_is_und_section(new_sect
)) {
1114 if (!bfd_is_und_section(new_sect
) && old_offset
!= 0 &&
1115 fetch_supersect(newsbfd
, new_sect
)->type
== SS_TYPE_TEXT
)
1118 if (!bfd_is_und_section(new_sect
) && new_offset
!= 0 &&
1119 fetch_supersect(oldsbfd
, old_sect
)->type
== SS_TYPE_TEXT
)
1122 return strcmp(old_sym
->name
, new_sym
->name
) == 0 &&
1123 old_offset
== new_offset
;
1126 if (bfd_is_abs_section(old_sect
) && bfd_is_abs_section(new_sect
)) {
1127 if (old_offset
+ old_sym
->value
== new_offset
+ new_sym
->value
)
1129 debug1(newsbfd
, "Differing relocations from %s/%s to ABS "
1130 "section: %lx/%lx\n", old_addr_span
->label
,
1131 new_addr_span
->label
,
1132 (unsigned long)(old_offset
+ old_sym
->value
),
1133 (unsigned long)(new_offset
+ new_sym
->value
));
1137 if (bfd_is_const_section(old_sect
) || bfd_is_const_section(new_sect
))
1140 struct supersect
*old_ss
= fetch_supersect(oldsbfd
, old_sect
);
1141 struct supersect
*new_ss
= fetch_supersect(newsbfd
, new_sect
);
1142 struct span
*old_span
= reloc_target_span(old_src_ss
, old_reloc
);
1143 struct span
*new_span
= reloc_target_span(new_src_ss
, new_reloc
);
1145 if (old_span
->match
!= new_span
|| new_span
->match
!= old_span
) {
1146 debug1(newsbfd
, "Nonmatching relocs from %s to %s/%s\n",
1147 new_src_ss
->name
, old_span
->label
, new_span
->label
);
1151 if (old_sym
->value
+ old_offset
- old_span
->start
!=
1152 new_sym
->value
+ new_offset
- new_span
->start
) {
1153 debug1(newsbfd
, "Offsets to %s/%s differ between %s "
1154 "and %s: %lx+%lx/%lx+%lx\n", old_ss
->name
,
1155 new_ss
->name
, old_src_ss
->name
, new_src_ss
->name
,
1156 (unsigned long)old_sym
->value
, (unsigned long)old_offset
,
1157 (unsigned long)new_sym
->value
,
1158 (unsigned long)new_offset
);
1162 if ((old_sym
->value
+ old_offset
- old_span
->start
!= 0 ||
1163 new_sym
->value
+ new_offset
- new_span
->start
!= 0) &&
1165 debug1(newsbfd
, "Relocation from %s to nonzero offsets "
1166 "%lx+%lx/%lx+%lx in changed section %s\n",
1167 new_src_ss
->name
, (unsigned long)old_sym
->value
,
1168 (unsigned long)old_offset
, (unsigned long)new_sym
->value
,
1169 (unsigned long)new_offset
, new_sym
->section
->name
);
1175 bool all_relocs_equal(struct span
*old_span
, struct span
*new_span
)
1177 struct supersect
*old_ss
= old_span
->ss
, *new_ss
= new_span
->ss
;
1178 arelent
**old_relocp
, **new_relocp
;
1180 for (old_relocp
= old_ss
->relocs
.data
;
1181 old_relocp
< old_ss
->relocs
.data
+ old_ss
->relocs
.size
;
1183 if (find_span(old_ss
, (*old_relocp
)->address
) == old_span
)
1187 for (new_relocp
= new_ss
->relocs
.data
;
1188 new_relocp
< new_ss
->relocs
.data
+ new_ss
->relocs
.size
;
1190 if (find_span(new_ss
, (*new_relocp
)->address
) == new_span
)
1194 for (; old_relocp
< old_ss
->relocs
.data
+ old_ss
->relocs
.size
&&
1195 find_span(old_ss
, (*old_relocp
)->address
) == old_span
&&
1196 new_relocp
< new_ss
->relocs
.data
+ new_ss
->relocs
.size
&&
1197 find_span(new_ss
, (*new_relocp
)->address
) == new_span
;
1198 old_relocp
++, new_relocp
++) {
1199 if (!relocs_equal(old_ss
, new_ss
, *old_relocp
, *new_relocp
))
1203 if ((old_relocp
< old_ss
->relocs
.data
+ old_ss
->relocs
.size
&&
1204 find_span(old_ss
, (*old_relocp
)->address
) == old_span
) ||
1205 (new_relocp
< new_ss
->relocs
.data
+ new_ss
->relocs
.size
&&
1206 find_span(new_ss
, (*new_relocp
)->address
) == new_span
)) {
1207 debug1(new_ss
->parent
, "Different reloc count between %s and "
1208 "%s\n", old_span
->label
, new_span
->label
);
1215 bfd_vma
non_dst_mask(struct supersect
*ss
, arelent
*reloc
)
1217 int bits
= bfd_get_reloc_size(reloc
->howto
) * 8;
1218 void *address
= ss
->contents
.data
+ reloc
->address
;
1219 bfd_vma x
= bfd_get(bits
, ss
->parent
->abfd
, address
);
1220 return x
& ~reloc
->howto
->dst_mask
;
1223 void rm_relocs(struct superbfd
*isbfd
)
1226 for (p
= isbfd
->abfd
->sections
; p
!= NULL
; p
= p
->next
) {
1227 struct supersect
*ss
= fetch_supersect(isbfd
, p
);
1228 bool remove_relocs
= ss
->keep
;
1230 if (mode("keep") && ss
->type
== SS_TYPE_SPECIAL
)
1231 remove_relocs
= false;
1233 if (ss
->type
== SS_TYPE_KSPLICE
||
1234 ss
->type
== SS_TYPE_KSPLICE_CALL
)
1235 remove_relocs
= false;
1236 if (mode("finalize") &&
1237 (starts_with(ss
->name
, ".ksplice_patches") ||
1238 starts_with(ss
->name
, ".ksplice_relocs")))
1239 remove_relocs
= true;
1246 void rm_some_relocs(struct supersect
*ss
)
1248 struct arelentp_vec orig_relocs
;
1249 vec_move(&orig_relocs
, &ss
->relocs
);
1252 for (relocp
= orig_relocs
.data
;
1253 relocp
< orig_relocs
.data
+ orig_relocs
.size
; relocp
++) {
1254 bool rm_reloc
= false;
1255 asymbol
*sym_ptr
= *(*relocp
)->sym_ptr_ptr
;
1257 if (mode("rmsyms") && str_in_set(sym_ptr
->name
, &rmsyms
) &&
1258 bfd_is_und_section(sym_ptr
->section
))
1264 if (mode("keep-primary") &&
1265 (bfd_is_const_section(sym_ptr
->section
) ||
1266 reloc_target_span(ss
, *relocp
)->new))
1269 if (mode("keep-primary")) {
1270 const struct table_section
*ts
=
1271 get_table_section(ss
->name
);
1272 if (ts
!= NULL
&& ts
->has_addr
&&
1273 ((*relocp
)->address
% ts
->entry_size
==
1275 (*relocp
)->address
% ts
->entry_size
==
1280 if (mode("finalize") && bfd_is_und_section(sym_ptr
->section
))
1283 if (strcmp(sym_ptr
->name
, "mcount") == 0 &&
1284 bfd_is_und_section(sym_ptr
->section
))
1287 if (!find_span(ss
, (*relocp
)->address
)->keep
)
1291 write_ksplice_reloc(ss
, *relocp
);
1293 *vec_grow(&ss
->relocs
, 1) = *relocp
;
1297 struct supersect
*make_section(struct superbfd
*sbfd
, const char *fmt
, ...)
1301 char *name
= vstrprintf(fmt
, ap
);
1304 asection
*sect
= bfd_get_section_by_name(sbfd
->abfd
, name
);
1306 return fetch_supersect(sbfd
, sect
);
1308 return new_supersect(sbfd
, name
);
1311 arelent
*create_reloc(struct supersect
*ss
, const void *addr
, asymbol
**symp
,
1314 bfd_reloc_code_real_type code
;
1315 switch (bfd_arch_bits_per_address(ss
->parent
->abfd
)) {
1317 code
= BFD_RELOC_32
;
1320 code
= BFD_RELOC_64
;
1326 arelent
*reloc
= malloc(sizeof(*reloc
));
1327 reloc
->sym_ptr_ptr
= symp
;
1328 reloc
->address
= addr_offset(ss
, addr
);
1329 reloc
->howto
= bfd_reloc_type_lookup(ss
->parent
->abfd
, code
);
1330 reloc
->addend
= offset
;
1334 void write_reloc(struct supersect
*ss
, const void *addr
, asymbol
**symp
,
1337 *vec_grow(&ss
->new_relocs
, 1) = create_reloc(ss
, addr
, symp
, offset
);
1340 void write_string(struct supersect
*ss
, const char **addr
, const char *fmt
, ...)
1343 struct supersect
*str_ss
= make_section(ss
->parent
, ".ksplice_str");
1346 int len
= vasprintf(&str
, fmt
, ap
);
1350 unsigned long *str_offp
= ulong_hash_lookup(&ksplice_string_offset
, str
,
1352 if (str_offp
== NULL
) {
1353 char *buf
= sect_grow(str_ss
, len
+ 1, char);
1354 memcpy(buf
, str
, len
+ 1);
1355 str_offp
= ulong_hash_lookup(&ksplice_string_offset
, str
, TRUE
);
1356 *str_offp
= addr_offset(str_ss
, buf
);
1359 write_reloc(ss
, addr
, &str_ss
->symbol
, *str_offp
);
1362 void lookup_system_map(struct addr_vec
*addrs
, const char *name
, long offset
)
1364 struct addr_vec
*map_addrs
=
1365 addr_vec_hash_lookup(&system_map
, name
, FALSE
);
1366 if (map_addrs
== NULL
)
1369 unsigned long *addr
, *map_addr
;
1370 for (map_addr
= map_addrs
->data
;
1371 map_addr
< map_addrs
->data
+ map_addrs
->size
; map_addr
++) {
1372 for (addr
= addrs
->data
; addr
< addrs
->data
+ addrs
->size
;
1374 if (*addr
== *map_addr
+ offset
)
1377 if (addr
< addrs
->data
+ addrs
->size
)
1379 *vec_grow(addrs
, 1) = *map_addr
+ offset
;
1383 void compute_system_map_array(struct superbfd
*sbfd
, struct addr_vec
*addrs
,
1386 if (bfd_is_abs_section(sym
->section
)) {
1387 *vec_grow(addrs
, 1) = sym
->value
;
1388 } else if (bfd_is_und_section(sym
->section
)) {
1389 lookup_system_map(addrs
, sym
->name
, 0);
1390 } else if (!bfd_is_const_section(sym
->section
)) {
1392 for (gsymp
= sbfd
->syms
.data
;
1393 gsymp
< sbfd
->syms
.data
+ sbfd
->syms
.size
; gsymp
++) {
1394 asymbol
*gsym
= *gsymp
;
1395 if ((gsym
->flags
& BSF_DEBUGGING
) == 0 &&
1396 gsym
->section
== sym
->section
)
1397 lookup_system_map(addrs
, gsym
->name
,
1398 sym
->value
- gsym
->value
);
1403 void write_ksplice_system_map(struct superbfd
*sbfd
, asymbol
*sym
,
1406 bool *done
= bool_hash_lookup(&system_map_written
, label
, TRUE
);
1411 struct addr_vec addrs
;
1414 compute_system_map_array(sbfd
, &addrs
, sym
);
1415 if (addrs
.size
!= 0) {
1416 struct supersect
*smap_ss
=
1417 make_section(sbfd
, ".ksplice_system_map");
1418 struct ksplice_system_map
*smap
=
1419 sect_grow(smap_ss
, 1, struct ksplice_system_map
);
1420 write_string(smap_ss
, &smap
->label
, "%s", label
);
1422 struct supersect
*array_ss
= make_section(sbfd
,
1424 void *buf
= sect_grow(array_ss
, addrs
.size
,
1425 typeof(*addrs
.data
));
1426 memcpy(buf
, addrs
.data
, addrs
.size
* sizeof(*addrs
.data
));
1427 smap
->nr_candidates
= addrs
.size
;
1428 write_reloc(smap_ss
, &smap
->candidates
, &array_ss
->symbol
,
1429 addr_offset(array_ss
, buf
));
1434 void write_ksplice_symbol_backend(struct supersect
*ss
,
1435 struct ksplice_symbol
*const *addr
,
1436 asymbol
*sym
, const char *label
,
1439 struct supersect
*ksymbol_ss
= make_section(ss
->parent
,
1440 ".ksplice_symbols");
1441 struct ksplice_symbol
*ksymbol
;
1442 unsigned long *ksymbol_offp
;
1444 ksymbol_offp
= ulong_hash_lookup(&ksplice_symbol_offset
, label
, FALSE
);
1445 if (ksymbol_offp
!= NULL
) {
1446 write_reloc(ss
, addr
, &ksymbol_ss
->symbol
, *ksymbol_offp
);
1449 ksymbol
= sect_grow(ksymbol_ss
, 1, struct ksplice_symbol
);
1450 ksymbol_offp
= ulong_hash_lookup(&ksplice_symbol_offset
, label
, TRUE
);
1451 *ksymbol_offp
= addr_offset(ksymbol_ss
, ksymbol
);
1453 write_reloc(ss
, addr
, &ksymbol_ss
->symbol
, *ksymbol_offp
);
1454 write_string(ksymbol_ss
, &ksymbol
->label
, "%s", label
);
1456 write_string(ksymbol_ss
, &ksymbol
->name
, "%s", name
);
1457 write_ksplice_system_map(ksymbol_ss
->parent
, sym
, label
);
1461 void write_ksplice_symbol(struct supersect
*ss
,
1462 struct ksplice_symbol
*const *addr
,
1463 asymbol
*sym
, struct span
*span
,
1464 const char *addstr_sect
)
1466 const char *label
, *name
;
1467 if (span
!= NULL
&& span
->start
!= 0)
1468 label
= span
->label
;
1470 label
= label_lookup(ss
->parent
, sym
);
1472 asymbol
*gsym
= canonical_symbol(ss
->parent
, sym
);
1473 if (strcmp(addstr_sect
, "") != 0)
1475 else if (bfd_is_und_section(sym
->section
))
1477 else if (bfd_is_const_section(sym
->section
))
1479 else if (span
!= NULL
&& span
->symbol
== NULL
)
1481 else if (gsym
== NULL
|| (gsym
->flags
& BSF_SECTION_SYM
) != 0)
1486 write_ksplice_symbol_backend(ss
, addr
, sym
,
1487 strprintf("%s%s", addstr_sect
, label
),
1491 void write_ksplice_reloc(struct supersect
*ss
, arelent
*orig_reloc
)
1493 asymbol
*sym_ptr
= *orig_reloc
->sym_ptr_ptr
;
1494 bfd_vma reloc_addend
= get_reloc_offset(ss
, orig_reloc
, false);
1495 bfd_vma target_addend
= get_reloc_offset(ss
, orig_reloc
, true);
1496 unsigned long *repladdr
= ss
->contents
.data
+ orig_reloc
->address
;
1498 if (mode("finalize") && starts_with(ss
->name
, ".ksplice_patches")) {
1502 if (mode("finalize") && starts_with(ss
->name
, ".ksplice_relocs")) {
1503 assert(starts_with(sym_ptr
->name
, KSPLICE_SYMBOL_STR
));
1505 fake_sym
.name
= sym_ptr
->name
+ strlen(KSPLICE_SYMBOL_STR
);
1506 fake_sym
.section
= bfd_und_section_ptr
;
1510 write_ksplice_symbol_backend
1511 (ss
, (struct ksplice_symbol
**)repladdr
, &fake_sym
,
1512 fake_sym
.name
, fake_sym
.name
);
1516 struct span
*span
= reloc_target_span(ss
, orig_reloc
);
1517 if (span
== ss
->spans
.data
&& span
->start
!= target_addend
)
1519 write_canary(ss
, orig_reloc
->address
,
1520 bfd_get_reloc_size(orig_reloc
->howto
),
1521 orig_reloc
->howto
->dst_mask
);
1523 struct supersect
*kreloc_ss
;
1525 kreloc_ss
= make_section(ss
->parent
, ".ksplice_init_relocs");
1527 kreloc_ss
= make_section(ss
->parent
, ".ksplice_relocs%s",
1529 struct ksplice_reloc
*kreloc
= sect_grow(kreloc_ss
, 1,
1530 struct ksplice_reloc
);
1532 struct span
*address_span
= find_span(ss
, orig_reloc
->address
);
1533 write_reloc(kreloc_ss
, &kreloc
->blank_addr
,
1534 &ss
->symbol
, orig_reloc
->address
+ address_span
->shift
);
1535 if (bfd_is_und_section(sym_ptr
->section
) && mode("keep")) {
1536 char *name
= strprintf(KSPLICE_SYMBOL_STR
"%s", sym_ptr
->name
);
1537 asymbol
**symp
= make_undefined_symbolp(ss
->parent
, name
);
1538 write_reloc(kreloc_ss
, &kreloc
->symbol
, symp
, 0);
1540 write_ksplice_symbol(kreloc_ss
, &kreloc
->symbol
, sym_ptr
, span
,
1543 if (span
!= NULL
&& span
->start
!= 0) {
1544 reloc_addend
+= sym_ptr
->value
- span
->start
;
1545 target_addend
+= sym_ptr
->value
- span
->start
;
1547 kreloc
->insn_addend
= reloc_addend
- target_addend
;
1548 kreloc
->target_addend
= target_addend
;
1549 write_ksplice_reloc_howto(kreloc_ss
, &kreloc
->howto
, orig_reloc
->howto
,
1550 KSPLICE_HOWTO_RELOC
);
1553 static void write_ksplice_reloc_howto(struct supersect
*ss
, const
1554 struct ksplice_reloc_howto
*const *addr
,
1555 reloc_howto_type
*howto
,
1556 enum ksplice_reloc_howto_type type
)
1558 struct supersect
*khowto_ss
= make_section(ss
->parent
,
1559 ".ksplice_reloc_howtos");
1560 struct ksplice_reloc_howto
*khowto
;
1561 unsigned long *khowto_offp
;
1563 khowto_offp
= ulong_hash_lookup(&ksplice_howto_offset
, howto
->name
,
1565 if (khowto_offp
!= NULL
) {
1566 write_reloc(ss
, addr
, &khowto_ss
->symbol
, *khowto_offp
);
1569 khowto
= sect_grow(khowto_ss
, 1, struct ksplice_reloc_howto
);
1570 khowto_offp
= ulong_hash_lookup(&ksplice_howto_offset
, howto
->name
,
1572 *khowto_offp
= addr_offset(khowto_ss
, khowto
);
1574 khowto
->type
= type
;
1575 khowto
->pcrel
= howto
->pc_relative
;
1576 khowto
->size
= bfd_get_reloc_size(howto
);
1577 khowto
->dst_mask
= howto
->dst_mask
;
1578 khowto
->rightshift
= howto
->rightshift
;
1579 khowto
->signed_addend
=
1580 (howto
->complain_on_overflow
== complain_overflow_signed
) ||
1581 (howto
->complain_on_overflow
== complain_overflow_bitfield
);
1582 write_reloc(ss
, addr
, &khowto_ss
->symbol
, *khowto_offp
);
1585 #define CANARY(x, canary) ((x & ~howto->dst_mask) | (canary & howto->dst_mask))
1587 void write_canary(struct supersect
*ss
, int offset
, bfd_size_type size
,
1590 int bits
= size
* 8;
1591 void *address
= ss
->contents
.data
+ offset
;
1592 bfd_vma x
= bfd_get(bits
, ss
->parent
->abfd
, address
);
1593 x
= (x
& ~dst_mask
) | ((bfd_vma
)KSPLICE_CANARY
& dst_mask
);
1594 bfd_put(bits
, ss
->parent
->abfd
, x
, address
);
1597 static void write_date_relocs(struct superbfd
*sbfd
, const char *str
,
1598 enum ksplice_reloc_howto_type type
)
1601 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
1602 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
1603 if (ss
->type
!= SS_TYPE_STRING
&& ss
->type
!= SS_TYPE_RODATA
)
1607 for (span
= ss
->spans
.data
;
1608 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++) {
1611 for (ptr
= ss
->contents
.data
+ span
->start
;
1612 ptr
+ strlen(str
) < ss
->contents
.data
+
1613 span
->start
+ span
->contents_size
; ptr
++) {
1614 if (strcmp((const char *)ptr
, str
) == 0)
1615 write_ksplice_date_reloc
1616 (ss
, addr_offset(ss
, ptr
), str
,
1623 static void write_ksplice_date_reloc(struct supersect
*ss
, unsigned long offset
,
1625 enum ksplice_reloc_howto_type type
)
1627 struct supersect
*kreloc_ss
;
1628 kreloc_ss
= make_section(ss
->parent
, ".ksplice_relocs%s", ss
->name
);
1629 struct ksplice_reloc
*kreloc
= sect_grow(kreloc_ss
, 1,
1630 struct ksplice_reloc
);
1632 const char *filename
= ss
->parent
->abfd
->filename
;
1633 char *c
= strstr(filename
, ".KSPLICE");
1634 int flen
= (c
== NULL
? strlen(filename
) : c
- filename
);
1636 write_ksplice_symbol_backend(kreloc_ss
, &kreloc
->symbol
, NULL
,
1637 strprintf("%s<%.*s>", str
, flen
, filename
),
1640 struct span
*span
= find_span(ss
, offset
);
1641 write_reloc(kreloc_ss
, &kreloc
->blank_addr
, &ss
->symbol
,
1642 offset
+ span
->shift
);
1643 write_ksplice_nonreloc_howto(kreloc_ss
, &kreloc
->howto
, type
,
1647 static void write_table_relocs(struct superbfd
*sbfd
, const char *sectname
,
1648 enum ksplice_reloc_howto_type type
)
1650 asection
*sect
= bfd_get_section_by_name(sbfd
->abfd
, sectname
);
1653 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
1655 const struct table_section
*s
= get_table_section(sectname
);
1660 for (entry
= ss
->contents
.data
;
1661 entry
< ss
->contents
.data
+ ss
->contents
.size
;
1662 entry
+= s
->entry_size
) {
1663 struct span
*span
= find_span(ss
, addr_offset(ss
, entry
));
1664 assert(span
!= NULL
);
1668 arelent
*reloc
= find_reloc(ss
, entry
+ s
->addr_offset
);
1669 assert(reloc
!= NULL
);
1670 asymbol
*sym
= *reloc
->sym_ptr_ptr
;
1671 assert(!bfd_is_const_section(sym
->section
));
1672 struct supersect
*sym_ss
= fetch_supersect(sbfd
, sym
->section
);
1673 unsigned long addr
= get_reloc_offset(ss
, reloc
, true) +
1675 write_ksplice_table_reloc(sym_ss
, addr
, span
->label
, type
);
1679 static void write_ksplice_table_reloc(struct supersect
*ss
,
1680 unsigned long address
,
1682 enum ksplice_reloc_howto_type type
)
1684 struct supersect
*kreloc_ss
;
1685 kreloc_ss
= make_section(ss
->parent
, ".ksplice_relocs%s", ss
->name
);
1686 struct ksplice_reloc
*kreloc
= sect_grow(kreloc_ss
, 1,
1687 struct ksplice_reloc
);
1688 struct span
*span
= find_span(ss
, address
);
1689 assert(span
!= NULL
);
1691 write_ksplice_symbol_backend(kreloc_ss
, &kreloc
->symbol
, NULL
,
1693 write_reloc(kreloc_ss
, &kreloc
->blank_addr
, &ss
->symbol
,
1694 address
+ span
->shift
);
1695 write_ksplice_nonreloc_howto(kreloc_ss
, &kreloc
->howto
, type
, 0);
1698 static void write_ksplice_nonreloc_howto(struct supersect
*ss
,
1699 const struct ksplice_reloc_howto
1701 enum ksplice_reloc_howto_type type
,
1704 struct supersect
*khowto_ss
=
1705 make_section(ss
->parent
, ".ksplice_reloc_howtos");
1706 struct ksplice_reloc_howto
*khowto
=
1707 sect_grow(khowto_ss
, 1, struct ksplice_reloc_howto
);
1709 khowto
->type
= type
;
1710 khowto
->size
= size
;
1712 khowto
->dst_mask
= 0;
1713 khowto
->rightshift
= 0;
1714 khowto
->signed_addend
= 0;
1715 write_reloc(ss
, addr
, &khowto_ss
->symbol
,
1716 addr_offset(khowto_ss
, khowto
));
1719 static void write_ksplice_section(struct span
*span
)
1721 struct supersect
*ss
= span
->ss
;
1722 const char *sectname
= span
->ss
->name
;
1723 const struct table_section
*ts
= get_table_section(ss
->name
);
1725 if (ts
!= NULL
&& ts
->has_addr
) {
1726 arelent
*reloc
= find_reloc(ss
, ss
->contents
.data
+ span
->start
1728 assert(reloc
!= NULL
);
1729 asymbol
*rsym
= *reloc
->sym_ptr_ptr
;
1730 assert(!bfd_is_const_section(rsym
->section
));
1731 sectname
= rsym
->section
->name
;
1734 struct supersect
*ksect_ss
=
1735 make_section(ss
->parent
, ".ksplice_sections%s", sectname
);
1736 struct ksplice_section
*ksect
= sect_grow(ksect_ss
, 1,
1737 struct ksplice_section
);
1738 asymbol
*sym
= span
->symbol
== NULL
? ss
->symbol
: span
->symbol
;
1740 write_ksplice_symbol(ksect_ss
, &ksect
->symbol
, sym
, span
,
1741 mode("keep-primary") ? "(post)" : "");
1742 ksect
->size
= span
->size
;
1745 if (ss
->type
== SS_TYPE_RODATA
|| ss
->type
== SS_TYPE_STRING
||
1746 ss
->type
== SS_TYPE_EXPORT
)
1747 ksect
->flags
|= KSPLICE_SECTION_RODATA
;
1748 if (ss
->type
== SS_TYPE_DATA
)
1749 ksect
->flags
|= KSPLICE_SECTION_DATA
;
1750 if (ss
->type
== SS_TYPE_TEXT
)
1751 ksect
->flags
|= KSPLICE_SECTION_TEXT
;
1752 assert(ksect
->flags
!= 0);
1754 if (ss
->type
== SS_TYPE_STRING
)
1755 ksect
->flags
|= KSPLICE_SECTION_STRING
;
1757 write_reloc(ksect_ss
, &ksect
->address
, &ss
->symbol
,
1758 span
->start
+ span
->shift
);
1761 static void write_ksplice_patch_reloc(struct supersect
*ss
,
1762 const char *sectname
, unsigned long *addr
,
1763 bfd_size_type size
, const char *label
,
1766 struct supersect
*kreloc_ss
;
1767 kreloc_ss
= make_section(ss
->parent
, ".ksplice_relocs%s", sectname
);
1768 struct ksplice_reloc
*kreloc
= sect_grow(kreloc_ss
, 1,
1769 struct ksplice_reloc
);
1771 write_canary(ss
, addr_offset(ss
, addr
), size
, -1);
1772 write_ksplice_symbol_backend(kreloc_ss
, &kreloc
->symbol
, NULL
,
1774 write_reloc(kreloc_ss
, &kreloc
->blank_addr
, &ss
->symbol
,
1775 addr_offset(ss
, addr
));
1776 reloc_howto_type
*howto
=
1777 bfd_reloc_type_lookup(ss
->parent
->abfd
,
1778 PASTE(BFD_RELOC_
, LONG_BIT
));
1779 write_ksplice_reloc_howto(kreloc_ss
, &kreloc
->howto
, howto
,
1780 KSPLICE_HOWTO_RELOC
);
1781 kreloc
->target_addend
= addend
;
1782 kreloc
->insn_addend
= 0;
1785 void write_ksplice_patch(struct superbfd
*sbfd
, struct span
*span
)
1787 struct supersect
*kpatch_ss
=
1788 make_section(sbfd
, ".ksplice_patches%s", span
->ss
->name
);
1789 struct ksplice_patch
*kpatch
= sect_grow(kpatch_ss
, 1,
1790 struct ksplice_patch
);
1792 write_ksplice_patch_reloc(kpatch_ss
, span
->ss
->name
, &kpatch
->oldaddr
,
1793 sizeof(kpatch
->oldaddr
), span
->label
, 0);
1794 if (span
->ss
->type
== SS_TYPE_TEXT
) {
1795 kpatch
->type
= KSPLICE_PATCH_TEXT
;
1796 write_patch_storage(kpatch_ss
, kpatch
, MAX_TRAMPOLINE_SIZE
,
1799 kpatch
->type
= KSPLICE_PATCH_DATA
;
1800 kpatch
->size
= span
->contents_size
;
1801 struct supersect
*data_ss
=
1802 make_section(sbfd
, ".ksplice_patch_data");
1803 write_reloc(kpatch_ss
, &kpatch
->contents
, &span
->ss
->symbol
,
1804 span
->start
+ span
->shift
);
1805 char *saved
= sect_do_grow(data_ss
, 1, span
->contents_size
, 1);
1806 write_reloc(kpatch_ss
, &kpatch
->saved
, &data_ss
->symbol
,
1807 addr_offset(data_ss
, saved
));
1809 write_reloc(kpatch_ss
, &kpatch
->repladdr
, &span
->ss
->symbol
,
1810 span
->start
+ span
->shift
);
1813 asymbol
**make_undefined_symbolp(struct superbfd
*sbfd
, const char *name
)
1816 for (symp
= sbfd
->syms
.data
; symp
< sbfd
->syms
.data
+ sbfd
->syms
.size
;
1818 asymbol
*sym
= *symp
;
1819 if (strcmp(name
, sym
->name
) == 0 &&
1820 bfd_is_und_section(sym
->section
))
1824 for (sympp
= sbfd
->new_syms
.data
;
1825 sympp
< sbfd
->new_syms
.data
+ sbfd
->new_syms
.size
; sympp
++) {
1826 asymbol
**symp
= *sympp
;
1827 asymbol
*sym
= *symp
;
1828 if (strcmp(name
, sym
->name
) == 0 &&
1829 bfd_is_und_section(sym
->section
))
1833 symp
= malloc(sizeof(*symp
));
1834 *symp
= bfd_make_empty_symbol(sbfd
->abfd
);
1835 asymbol
*sym
= *symp
;
1837 sym
->section
= bfd_und_section_ptr
;
1840 *vec_grow(&sbfd
->new_syms
, 1) = symp
;
1844 void write_ksplice_deleted_patch(struct superbfd
*sbfd
, const char *name
,
1845 const char *label
, const char *sectname
)
1847 struct supersect
*kpatch_ss
=
1848 make_section(sbfd
, ".ksplice_patches%s", sectname
);
1849 struct ksplice_patch
*kpatch
= sect_grow(kpatch_ss
, 1,
1850 struct ksplice_patch
);
1852 write_ksplice_patch_reloc(kpatch_ss
, sectname
, &kpatch
->oldaddr
,
1853 sizeof(kpatch
->oldaddr
), label
, 0);
1854 kpatch
->type
= KSPLICE_PATCH_TEXT
;
1855 asymbol
**symp
= make_undefined_symbolp(sbfd
, strdup(name
));
1856 write_reloc(kpatch_ss
, &kpatch
->repladdr
, symp
, 0);
1857 write_patch_storage(kpatch_ss
, kpatch
, MAX_TRAMPOLINE_SIZE
, NULL
);
1860 void write_ksplice_export(struct superbfd
*sbfd
, struct span
*span
, bool del
)
1862 struct supersect
*kpatch_ss
= make_section(sbfd
, ".ksplice_patches");
1863 struct ksplice_patch
*kpatch
= sect_grow(kpatch_ss
, 1,
1864 struct ksplice_patch
);
1865 struct supersect
*data_ss
;
1867 const struct table_section
*ts
= get_table_section(span
->ss
->name
);
1870 span
->ss
->contents
.data
+ span
->start
+ ts
->other_offset
;
1871 const char *symname
= read_string(span
->ss
, addr
);
1873 char *oldname
, *newname
;
1875 oldname
= strprintf("%s:%s", span
->ss
->name
, symname
);
1876 newname
= strprintf("DISABLED_%s_%s", symname
, kid
);
1878 oldname
= strprintf("%s:DISABLED_%s_%s", span
->ss
->name
,
1880 newname
= strprintf("%s", symname
);
1881 write_string(span
->ss
, addr
, "DISABLED_%s_%s", symname
, kid
);
1884 write_ksplice_patch_reloc(kpatch_ss
, "", &kpatch
->oldaddr
,
1885 sizeof(kpatch
->oldaddr
), oldname
,
1887 kpatch
->type
= KSPLICE_PATCH_EXPORT
;
1888 const char **namep
= write_patch_storage(kpatch_ss
, kpatch
,
1889 sizeof(newname
), &data_ss
);
1890 write_string(data_ss
, namep
, "%s", newname
);
1893 void filter_table_sections(struct superbfd
*isbfd
)
1895 struct supersect
*tables_ss
=
1896 fetch_supersect(offsets_sbfd
,
1897 bfd_get_section_by_name(offsets_sbfd
->abfd
,
1898 ".ksplice_table_sections"));
1899 const struct table_section
*ts
;
1900 for (ts
= tables_ss
->contents
.data
;
1901 (void *)ts
< tables_ss
->contents
.data
+ tables_ss
->contents
.size
;
1903 struct table_section s
= *ts
;
1904 s
.sect
= read_string(tables_ss
, &ts
->sect
);
1905 s
.other_sect
= read_string(tables_ss
, &ts
->other_sect
);
1906 s
.crc_sect
= read_string(tables_ss
, &ts
->crc_sect
);
1907 filter_table_section(isbfd
, &s
);
1911 void filter_table_section(struct superbfd
*sbfd
, const struct table_section
*s
)
1913 asection
*isection
= bfd_get_section_by_name(sbfd
->abfd
, s
->sect
);
1914 if (isection
== NULL
)
1916 struct supersect
*ss
= fetch_supersect(sbfd
, isection
);
1919 for (entry
= ss
->contents
.data
;
1920 entry
< ss
->contents
.data
+ ss
->contents
.size
;
1921 entry
+= s
->entry_size
) {
1922 struct span
*span
= find_span(ss
, addr_offset(ss
, entry
));
1923 assert(span
!= NULL
);
1926 struct span
*sym_span
=
1927 span_offset_target_span(span
, s
->addr_offset
);
1928 assert(sym_span
!= NULL
);
1933 if (s
->other_sect
!= NULL
) {
1934 struct span
*sym_span
=
1935 span_offset_target_span(span
, s
->other_offset
);
1936 assert(sym_span
!= NULL
);
1938 keep_span(sym_span
);
1941 if (s
->crc_sect
!= NULL
) {
1942 struct span
*crc_span
= get_crc_span(span
, s
);
1943 assert(crc_span
!= NULL
);
1944 if (span
->keep
&& mode("keep-primary"))
1945 keep_span(crc_span
);
1950 static void match_table_spans(struct span
*old_span
, struct span
*new_span
)
1952 const struct table_section
*ts
= get_table_section(old_span
->ss
->name
);
1954 if (strcmp(old_span
->ss
->name
, new_span
->ss
->name
) != 0)
1956 if (ts
== NULL
|| old_span
->ss
->type
!= SS_TYPE_SPECIAL
||
1957 new_span
->ss
->type
!= SS_TYPE_SPECIAL
)
1959 if (old_span
->match
!= NULL
|| new_span
->match
!= NULL
)
1963 void *old_entry
= old_span
->ss
->contents
.data
+ old_span
->start
;
1964 void *new_entry
= new_span
->ss
->contents
.data
+ new_span
->start
;
1965 arelent
*old_reloc
=
1966 find_reloc(old_span
->ss
, old_entry
+ ts
->addr_offset
);
1967 arelent
*new_reloc
=
1968 find_reloc(new_span
->ss
, new_entry
+ ts
->addr_offset
);
1969 assert(old_reloc
!= NULL
&& new_reloc
!= NULL
);
1970 struct span
*old_sym_span
=
1971 reloc_target_span(old_span
->ss
, old_reloc
);
1972 struct span
*new_sym_span
=
1973 reloc_target_span(new_span
->ss
, new_reloc
);
1974 assert(old_sym_span
!= NULL
&& new_sym_span
!= NULL
);
1975 if (old_sym_span
->match
== new_sym_span
&&
1976 new_sym_span
->match
== old_sym_span
&&
1977 old_reloc
->address
- old_sym_span
->start
==
1978 new_reloc
->address
- new_sym_span
->start
)
1979 match_spans(old_span
, new_span
);
1983 static struct span
*get_crc_span(struct span
*span
,
1984 const struct table_section
*ts
)
1986 void *entry
= span
->ss
->contents
.data
+ span
->start
;
1987 asection
*crc_sect
= bfd_get_section_by_name(span
->ss
->parent
->abfd
,
1989 if (crc_sect
== NULL
)
1991 struct supersect
*crc_ss
= fetch_supersect(span
->ss
->parent
, crc_sect
);
1994 struct span
*crc_span
= find_span(crc_ss
, addr_offset(span
->ss
, entry
) /
1995 ts
->entry_size
* ts
->crc_size
);
1999 void mark_precallable_spans(struct superbfd
*sbfd
)
2002 struct supersect
*ss
, *sym_ss
;
2003 struct span
*address_span
, *target_span
;
2004 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
2005 ss
= fetch_supersect(sbfd
, sect
);
2007 if (ss
->type
== SS_TYPE_SPECIAL
)
2009 for (relocp
= ss
->relocs
.data
;
2010 relocp
< ss
->relocs
.data
+ ss
->relocs
.size
; relocp
++) {
2011 asymbol
*sym
= *(*relocp
)->sym_ptr_ptr
;
2012 address_span
= find_span(ss
, (*relocp
)->address
);
2013 if (!address_span
->precallable
)
2015 target_span
= reloc_target_span(ss
, *relocp
);
2016 if (target_span
== NULL
|| target_span
->keep
)
2018 sym_ss
= fetch_supersect(sbfd
, sym
->section
);
2019 if (sym_ss
->type
== SS_TYPE_IGNORED
)
2021 target_span
->precallable
= true;
2027 void keep_referenced_sections(struct superbfd
*sbfd
)
2030 struct supersect
*ss
, *sym_ss
;
2031 struct span
*address_span
, *target_span
;
2032 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
2033 ss
= fetch_supersect(sbfd
, sect
);
2035 if (ss
->type
== SS_TYPE_SPECIAL
)
2037 for (relocp
= ss
->relocs
.data
;
2038 relocp
< ss
->relocs
.data
+ ss
->relocs
.size
; relocp
++) {
2039 asymbol
*sym
= *(*relocp
)->sym_ptr_ptr
;
2040 address_span
= find_span(ss
, (*relocp
)->address
);
2041 if (!address_span
->keep
)
2043 target_span
= reloc_target_span(ss
, *relocp
);
2044 if (target_span
== NULL
|| target_span
->keep
)
2046 sym_ss
= fetch_supersect(sbfd
, sym
->section
);
2047 if (sym_ss
->type
== SS_TYPE_IGNORED
)
2049 keep_span(target_span
);
2055 void copy_symbols(struct asymbolp_vec
*osyms
, struct asymbolpp_vec
*isyms
)
2058 for (sympp
= isyms
->data
; sympp
< isyms
->data
+ isyms
->size
; sympp
++)
2059 *vec_grow(osyms
, 1) = **sympp
;
2062 /* Modified function from GNU Binutils objcopy.c */
2063 bfd_boolean
copy_object(bfd
*ibfd
, bfd
*obfd
)
2065 assert(bfd_set_format(obfd
, bfd_get_format(ibfd
)));
2067 bfd_vma start
= bfd_get_start_address(ibfd
);
2069 flagword flags
= bfd_get_file_flags(ibfd
);
2070 flags
&= bfd_applicable_file_flags(obfd
);
2072 assert(bfd_set_start_address(obfd
, start
)
2073 && bfd_set_file_flags(obfd
, flags
));
2075 enum bfd_architecture iarch
= bfd_get_arch(ibfd
);
2076 unsigned int imach
= bfd_get_mach(ibfd
);
2077 assert(bfd_set_arch_mach(obfd
, iarch
, imach
));
2078 assert(bfd_set_format(obfd
, bfd_get_format(ibfd
)));
2080 /* BFD mandates that all output sections be created and sizes set before
2081 any output is done. Thus, we traverse all sections multiple times. */
2082 bfd_map_over_sections(ibfd
, setup_section
, obfd
);
2084 struct supersect
*new_supersects
= fetch_superbfd(ibfd
)->new_supersects
;
2085 struct supersect
*ss
;
2086 for (ss
= new_supersects
; ss
!= NULL
; ss
= ss
->next
)
2087 setup_new_section(obfd
, ss
);
2089 /* Mark symbols used in output relocations so that they
2090 are kept, even if they are local labels or static symbols.
2092 Note we iterate over the input sections examining their
2093 relocations since the relocations for the output sections
2094 haven't been set yet. mark_symbols_used_in_relocations will
2095 ignore input sections which have no corresponding output
2098 bfd_map_over_sections(ibfd
, mark_symbols_used_in_relocations
, NULL
);
2099 for (ss
= new_supersects
; ss
!= NULL
; ss
= ss
->next
)
2100 ss_mark_symbols_used_in_relocations(ss
);
2101 struct asymbolp_vec osyms
;
2103 filter_symbols(ibfd
, obfd
, &osyms
, &fetch_superbfd(ibfd
)->syms
);
2104 copy_symbols(&osyms
, &fetch_superbfd(ibfd
)->new_syms
);
2106 bfd_set_symtab(obfd
, osyms
.data
, osyms
.size
);
2108 /* This has to happen after the symbol table has been set. */
2109 bfd_map_over_sections(obfd
, write_section
, NULL
);
2111 /* Allow the BFD backend to copy any private data it understands
2112 from the input BFD to the output BFD. This is done last to
2113 permit the routine to look at the filtered symbol table, which is
2114 important for the ECOFF code at least. */
2115 assert(bfd_copy_private_bfd_data(ibfd
, obfd
));
2120 /* Modified function from GNU Binutils objcopy.c */
2121 void setup_section(bfd
*ibfd
, asection
*isection
, void *obfdarg
)
2123 struct superbfd
*isbfd
= fetch_superbfd(ibfd
);
2124 struct supersect
*ss
= fetch_supersect(isbfd
, isection
);
2125 bfd
*obfd
= obfdarg
;
2131 asection
*osection
= bfd_make_section_anyway(obfd
, ss
->name
);
2132 assert(osection
!= NULL
);
2134 osection
->userdata
= ss
;
2135 bfd_set_section_flags(obfd
, osection
, ss
->flags
);
2136 ss
->symbol
= osection
->symbol
;
2137 assert(bfd_set_section_size(obfd
, osection
, ss
->contents
.size
));
2139 vma
= bfd_section_vma(ibfd
, isection
);
2140 assert(bfd_set_section_vma(obfd
, osection
, vma
));
2142 osection
->lma
= isection
->lma
;
2143 assert(bfd_set_section_alignment(obfd
, osection
, ss
->alignment
));
2144 osection
->entsize
= ss
->entsize
;
2145 osection
->output_section
= osection
;
2146 osection
->output_offset
= 0;
2147 isection
->output_section
= osection
;
2148 isection
->output_offset
= 0;
2152 void setup_new_section(bfd
*obfd
, struct supersect
*ss
)
2154 asection
*osection
= bfd_make_section_anyway(obfd
, ss
->name
);
2155 assert(osection
!= NULL
);
2156 bfd_set_section_flags(obfd
, osection
, ss
->flags
);
2158 osection
->userdata
= ss
;
2159 ss
->symbol
= osection
->symbol
;
2160 assert(bfd_set_section_size(obfd
, osection
, ss
->contents
.size
));
2161 assert(bfd_set_section_vma(obfd
, osection
, 0));
2164 assert(bfd_set_section_alignment(obfd
, osection
, ss
->alignment
));
2165 osection
->entsize
= ss
->entsize
;
2166 osection
->output_section
= osection
;
2167 osection
->output_offset
= 0;
2170 static int compare_reloc_addresses(const void *aptr
, const void *bptr
)
2172 const arelent
*const *a
= aptr
, *const *b
= bptr
;
2173 return (*a
)->address
- (*b
)->address
;
2176 static void delete_obsolete_relocs(struct supersect
*ss
)
2178 if (ss
->new_relocs
.size
== 0)
2181 qsort(ss
->relocs
.data
, ss
->relocs
.size
, sizeof(*ss
->relocs
.data
),
2182 compare_reloc_addresses
);
2183 qsort(ss
->new_relocs
.data
, ss
->new_relocs
.size
,
2184 sizeof(*ss
->new_relocs
.data
), compare_reloc_addresses
);
2186 struct arelentp_vec orig_relocs
;
2187 vec_move(&orig_relocs
, &ss
->relocs
);
2189 arelent
**relocp
, **new_relocp
= ss
->new_relocs
.data
;
2190 for (relocp
= orig_relocs
.data
;
2191 relocp
< orig_relocs
.data
+ orig_relocs
.size
; relocp
++) {
2192 while (new_relocp
< ss
->new_relocs
.data
+ ss
->new_relocs
.size
&&
2193 (*new_relocp
)->address
< (*relocp
)->address
)
2195 arelent
*reloc
= *relocp
, *new_reloc
= *new_relocp
;
2196 if (new_relocp
== ss
->new_relocs
.data
+ ss
->new_relocs
.size
||
2197 reloc
->address
!= new_reloc
->address
)
2198 *vec_grow(&ss
->relocs
, 1) = reloc
;
2202 void write_section(bfd
*obfd
, asection
*osection
, void *arg
)
2204 struct supersect
*ss
= osection
->userdata
;
2206 if ((ss
->flags
& SEC_GROUP
) != 0 || ss
->contents
.size
== 0)
2209 delete_obsolete_relocs(ss
);
2212 char *error_message
;
2213 for (relocp
= ss
->new_relocs
.data
;
2214 relocp
< ss
->new_relocs
.data
+ ss
->new_relocs
.size
; relocp
++) {
2216 if (bfd_get_arch(obfd
) == bfd_arch_arm
)
2217 val
= osection
->use_rela_p
? 0 : (*relocp
)->addend
;
2220 bfd_put(bfd_get_reloc_size((*relocp
)->howto
) * 8, obfd
, val
,
2221 ss
->contents
.data
+ (*relocp
)->address
);
2222 if (bfd_install_relocation(obfd
, *relocp
, ss
->contents
.data
,
2223 0, osection
, &error_message
) !=
2225 err(ss
->parent
, "ksplice: error installing reloc: %s",
2230 memcpy(vec_grow(&ss
->relocs
, ss
->new_relocs
.size
), ss
->new_relocs
.data
,
2231 ss
->new_relocs
.size
* sizeof(*ss
->new_relocs
.data
));
2233 bfd_set_reloc(obfd
, osection
,
2234 ss
->relocs
.size
== 0 ? NULL
: ss
->relocs
.data
,
2237 if (ss
->flags
& SEC_HAS_CONTENTS
)
2238 assert(bfd_set_section_contents
2239 (obfd
, osection
, ss
->contents
.data
, 0,
2240 ss
->contents
.size
));
2243 /* Modified function from GNU Binutils objcopy.c
2245 * Mark all the symbols which will be used in output relocations with
2246 * the BSF_KEEP flag so that those symbols will not be stripped.
2248 * Ignore relocations which will not appear in the output file.
2250 void mark_symbols_used_in_relocations(bfd
*abfd
, asection
*isection
,
2253 struct superbfd
*sbfd
= fetch_superbfd(abfd
);
2254 if (isection
->output_section
== NULL
)
2257 struct supersect
*ss
= fetch_supersect(sbfd
, isection
);
2258 ss_mark_symbols_used_in_relocations(ss
);
2261 void ss_mark_symbols_used_in_relocations(struct supersect
*ss
)
2263 /* Examine each symbol used in a relocation. If it's not one of the
2264 special bfd section symbols, then mark it with BSF_KEEP. */
2266 for (relocp
= ss
->relocs
.data
;
2267 relocp
< ss
->relocs
.data
+ ss
->relocs
.size
; relocp
++) {
2268 asymbol
*sym
= *(*relocp
)->sym_ptr_ptr
;
2269 if (!(bfd_is_const_section(sym
->section
) &&
2270 sym
== sym
->section
->symbol
))
2271 sym
->flags
|= BSF_KEEP
;
2273 for (relocp
= ss
->new_relocs
.data
;
2274 relocp
< ss
->new_relocs
.data
+ ss
->new_relocs
.size
; relocp
++) {
2275 asymbol
*sym
= *(*relocp
)->sym_ptr_ptr
;
2276 if (!(bfd_is_const_section(sym
->section
) &&
2277 sym
== sym
->section
->symbol
))
2278 sym
->flags
|= BSF_KEEP
;
2282 static bool deleted_table_section_symbol(bfd
*abfd
, asymbol
*sym
)
2284 struct superbfd
*sbfd
= fetch_superbfd(abfd
);
2285 if (bfd_is_const_section(sym
->section
))
2287 struct supersect
*ss
= fetch_supersect(sbfd
, sym
->section
);
2290 for (symp
= ss
->syms
.data
; symp
< ss
->syms
.data
+ ss
->syms
.size
; symp
++) {
2294 return symp
>= ss
->syms
.data
+ ss
->syms
.size
&&
2295 (sym
->flags
& BSF_SECTION_SYM
) == 0;
2298 void filter_symbols(bfd
*ibfd
, bfd
*obfd
, struct asymbolp_vec
*osyms
,
2299 struct asymbolp_vec
*isyms
)
2302 struct superbfd
*sbfd
= fetch_superbfd(ibfd
);
2303 for (symp
= isyms
->data
; symp
< isyms
->data
+ isyms
->size
; symp
++) {
2304 asymbol
*sym
= *symp
;
2305 struct supersect
*sym_ss
= NULL
;
2306 struct span
*sym_span
= NULL
;
2307 if (!bfd_is_const_section(sym
->section
)) {
2308 sym_ss
= fetch_supersect(sbfd
, sym
->section
);
2309 sym_span
= find_span(sym_ss
, sym
->value
);
2312 if (mode("keep") && (sym
->flags
& BSF_GLOBAL
) != 0 &&
2313 !(mode("keep-primary") && sym_span
!= NULL
&&
2315 sym
->flags
= (sym
->flags
& ~BSF_GLOBAL
) | BSF_LOCAL
;
2317 if (mode("finalize") && (sym
->flags
& BSF_GLOBAL
) != 0)
2318 sym
->flags
= (sym
->flags
& ~BSF_GLOBAL
) | BSF_LOCAL
;
2320 bool keep
= bfd_is_const_section(sym
->section
) ||
2321 (sym_ss
->keep
&& (sym
->flags
& BSF_SECTION_SYM
) != 0) ||
2322 (sym_span
!= NULL
&& sym_span
->keep
);
2323 if (bfd_is_und_section(sym
->section
) &&
2324 (sym
->flags
& BSF_KEEP
) == 0)
2326 if (bfd_is_abs_section(sym
->section
) &&
2327 (sym
->flags
& BSF_KEEP
) == 0 &&
2328 (sym
->flags
& BSF_FILE
) == 0)
2330 if (deleted_table_section_symbol(ibfd
, sym
))
2333 if (mode("keep-helper") && sym_ss
!= NULL
&&
2334 sym_ss
->type
== SS_TYPE_EXPORT
)
2338 if (sym_ss
!= NULL
&& !sym_ss
->keep
) {
2339 err(sbfd
, "Kept symbol %s in unkept section "
2340 "%s\n", sym
->name
, sym
->section
->name
);
2343 *vec_grow(osyms
, 1) = sym
;
2348 void read_str_set(struct str_vec
*strs
)
2352 assert(getline(&buf
, &n
, stdin
) >= 0);
2356 char *str
= strtok_r(buf
, " \n", &saveptr
);
2360 *vec_grow(strs
, 1) = str
;
2364 bool str_in_set(const char *str
, const struct str_vec
*strs
)
2367 for (strp
= strs
->data
; strp
< strs
->data
+ strs
->size
; strp
++) {
2368 if (strcmp(str
, *strp
) == 0)
2374 static bool is_table_section(const char *name
, bool consider_other
,
2377 struct supersect
*tables_ss
=
2378 fetch_supersect(offsets_sbfd
,
2379 bfd_get_section_by_name(offsets_sbfd
->abfd
,
2380 ".ksplice_table_sections"));
2381 const struct table_section
*ts
;
2382 for (ts
= tables_ss
->contents
.data
;
2383 (void *)ts
< tables_ss
->contents
.data
+ tables_ss
->contents
.size
;
2385 if (strcmp(name
, read_string(tables_ss
, &ts
->sect
)) == 0)
2387 const char *osect_name
= read_string(tables_ss
,
2389 if (consider_other
&& osect_name
!= NULL
&&
2390 strcmp(name
, osect_name
) == 0)
2392 const char *crc_name
= read_string(tables_ss
, &ts
->crc_sect
);
2393 if (consider_crc
&& crc_name
!= NULL
&&
2394 strcmp(name
, crc_name
) == 0)
2400 const struct table_section
*get_table_section(const char *name
)
2402 struct supersect
*tables_ss
=
2403 fetch_supersect(offsets_sbfd
,
2404 bfd_get_section_by_name(offsets_sbfd
->abfd
,
2405 ".ksplice_table_sections"));
2406 const struct table_section
*ts
;
2407 for (ts
= tables_ss
->contents
.data
;
2408 (void *)ts
< tables_ss
->contents
.data
+ tables_ss
->contents
.size
;
2410 if (strcmp(name
, read_string(tables_ss
, &ts
->sect
)) == 0) {
2411 if (ts
->entry_contents_size
!= 0)
2412 assert(align(ts
->entry_contents_size
,
2415 struct table_section
*ns
= malloc(sizeof(*ns
));
2417 ns
->sect
= read_string(tables_ss
, &ts
->sect
);
2418 ns
->crc_sect
= read_string(tables_ss
, &ts
->crc_sect
);
2420 read_string(tables_ss
, &ts
->other_sect
);
2427 enum supersect_type
supersect_type(struct supersect
*ss
)
2429 if (mode("finalize") &&
2430 strcmp(finalize_target
, "vmlinux") == 0 &&
2431 (starts_with(ss
->name
, ".ksplice_relocs.exit") ||
2432 starts_with(ss
->name
, ".ksplice_sections.exit") ||
2433 starts_with(ss
->name
, ".ksplice_patches.exit")))
2434 return SS_TYPE_EXIT
;
2435 if (starts_with(ss
->name
, ".ksplice_call"))
2436 return SS_TYPE_KSPLICE_CALL
;
2437 if (starts_with(ss
->name
, ".ksplice_options"))
2438 return SS_TYPE_SPECIAL
;
2439 if (starts_with(ss
->name
, ".ksplice"))
2440 return SS_TYPE_KSPLICE
;
2442 if (starts_with(ss
->name
, ".init"))
2443 return SS_TYPE_IGNORED
;
2444 if (starts_with(ss
->name
, ".security_initcall.init"))
2445 return SS_TYPE_IGNORED
;
2446 if (starts_with(ss
->name
, ".con_initcall.init"))
2447 return SS_TYPE_IGNORED
;
2448 if (starts_with(ss
->name
, ".x86cpuvendor.init"))
2449 return SS_TYPE_IGNORED
;
2450 if (starts_with(ss
->name
, ".early_param.init"))
2451 return SS_TYPE_IGNORED
;
2452 if (starts_with(ss
->name
, ".taglist.init"))
2453 return SS_TYPE_IGNORED
;
2454 if (starts_with(ss
->name
, ".arch.info.init"))
2455 return SS_TYPE_IGNORED
;
2456 if (starts_with(ss
->name
, ".proc.info.init"))
2457 return SS_TYPE_IGNORED
;
2458 /* .pci_fixup_* sections really should be treated as global rodata
2459 referenced only from quirks.c */
2460 if (starts_with(ss
->name
, ".pci_fixup_"))
2461 return SS_TYPE_IGNORED
;
2462 /* .builtin_fw sections are similar to .pci_fixup */
2463 if (starts_with(ss
->name
, ".builtin_fw"))
2464 return SS_TYPE_IGNORED
;
2465 /* same for .tracedata */
2466 if (starts_with(ss
->name
, ".tracedata"))
2467 return SS_TYPE_IGNORED
;
2468 if (starts_with(ss
->name
, ".debug"))
2469 return SS_TYPE_IGNORED
;
2470 /* .eh_frame should probably be discarded, not ignored */
2471 if (starts_with(ss
->name
, ".eh_frame"))
2472 return SS_TYPE_IGNORED
;
2473 if (config
->ignore_devinit
&& starts_with(ss
->name
, ".devinit"))
2474 return SS_TYPE_IGNORED
;
2475 if (config
->ignore_meminit
&& starts_with(ss
->name
, ".meminit"))
2476 return SS_TYPE_IGNORED
;
2477 if (config
->ignore_cpuinit
&& starts_with(ss
->name
, ".cpuinit"))
2478 return SS_TYPE_IGNORED
;
2479 if (config
->ignore_devinit
&& starts_with(ss
->name
, ".devexit"))
2480 return SS_TYPE_IGNORED
;
2481 if (config
->ignore_meminit
&& starts_with(ss
->name
, ".memexit"))
2482 return SS_TYPE_IGNORED
;
2483 if (config
->ignore_cpuinit
&& starts_with(ss
->name
, ".cpuexit"))
2484 return SS_TYPE_IGNORED
;
2485 if (starts_with(ss
->name
, ".vgetcpu_mode") ||
2486 starts_with(ss
->name
, ".jiffies") ||
2487 starts_with(ss
->name
, ".wall_jiffies") ||
2488 starts_with(ss
->name
, ".vxtime") ||
2489 starts_with(ss
->name
, ".sys_tz") ||
2490 starts_with(ss
->name
, ".sysctl_vsyscall") ||
2491 starts_with(ss
->name
, ".xtime") ||
2492 starts_with(ss
->name
, ".xtime_lock") ||
2493 starts_with(ss
->name
, ".vsyscall"))
2494 return SS_TYPE_IGNORED
;
2495 if (starts_with(ss
->name
, ".vdso"))
2496 return SS_TYPE_IGNORED
;
2498 if (starts_with(ss
->name
, ".exit.text"))
2499 return SS_TYPE_TEXT
;
2500 if (starts_with(ss
->name
, ".exit.data"))
2501 return SS_TYPE_DATA
;
2503 if (starts_with(ss
->name
, ".text") ||
2504 starts_with(ss
->name
, ".kernel.text") ||
2505 starts_with(ss
->name
, ".devinit.text") ||
2506 starts_with(ss
->name
, ".meminit.text") ||
2507 starts_with(ss
->name
, ".cpuinit.text") ||
2508 starts_with(ss
->name
, ".devexit.text") ||
2509 starts_with(ss
->name
, ".memexit.text") ||
2510 starts_with(ss
->name
, ".cpuexit.text") ||
2511 starts_with(ss
->name
, ".ref.text") ||
2512 starts_with(ss
->name
, ".spinlock.text") ||
2513 starts_with(ss
->name
, ".kprobes.text") ||
2514 starts_with(ss
->name
, ".sched.text") ||
2515 (mode("keep-helper") && starts_with(ss
->name
, ".fixup")))
2516 return SS_TYPE_TEXT
;
2519 if (sscanf(ss
->name
, ".rodata.str%*u.%*u%n", &n
) >= 0 &&
2520 n
== strlen(ss
->name
))
2521 return ss
->entsize
== 1 ? SS_TYPE_STRING
: SS_TYPE_RODATA
;
2523 if (starts_with(ss
->name
, ".rodata") ||
2524 starts_with(ss
->name
, ".kernel.rodata") ||
2525 starts_with(ss
->name
, ".devinit.rodata") ||
2526 starts_with(ss
->name
, ".meminit.rodata") ||
2527 starts_with(ss
->name
, ".cpuinit.rodata") ||
2528 starts_with(ss
->name
, ".devexit.rodata") ||
2529 starts_with(ss
->name
, ".memexit.rodata") ||
2530 starts_with(ss
->name
, ".cpuexit.rodata") ||
2531 starts_with(ss
->name
, ".ref.rodata") ||
2532 starts_with(ss
->name
, "__markers_strings") ||
2533 starts_with(ss
->name
, "__bug_table") ||
2534 (mode("keep-helper") && starts_with(ss
->name
, "__ex_table")))
2535 return SS_TYPE_RODATA
;
2537 if (starts_with(ss
->name
, ".bss"))
2538 return SS_TYPE_DATA
;
2540 /* Ignore .data.percpu sections */
2541 if (starts_with(ss
->name
, ".data.percpu") ||
2542 starts_with(ss
->name
, ".kernel.data.percpu"))
2543 return SS_TYPE_IGNORED
;
2544 if (starts_with(ss
->name
, ".data") ||
2545 starts_with(ss
->name
, ".kernel.data") ||
2546 starts_with(ss
->name
, ".devinit.data") ||
2547 starts_with(ss
->name
, ".cpuinit.data") ||
2548 starts_with(ss
->name
, ".meminit.data") ||
2549 starts_with(ss
->name
, ".devexit.data") ||
2550 starts_with(ss
->name
, ".memexit.data") ||
2551 starts_with(ss
->name
, ".cpuexit.data") ||
2552 starts_with(ss
->name
, ".ref.data") ||
2553 starts_with(ss
->name
, "__markers"))
2554 return SS_TYPE_DATA
;
2556 /* We replace all the ksymtab strings, so delete them */
2557 if (strcmp(ss
->name
, "__ksymtab_strings") == 0)
2558 return SS_TYPE_STRING
;
2559 if (starts_with(ss
->name
, "__ksymtab"))
2560 return SS_TYPE_EXPORT
;
2562 if (is_table_section(ss
->name
, true, true))
2563 return SS_TYPE_SPECIAL
;
2565 if (starts_with(ss
->name
, ".ARM."))
2566 return SS_TYPE_SPECIAL
;
2568 if (starts_with(ss
->name
, ".note"))
2569 return SS_TYPE_IGNORED
;
2570 if (starts_with(ss
->name
, ".comment"))
2571 return SS_TYPE_IGNORED
;
2572 if (starts_with(ss
->name
, "__param"))
2573 return SS_TYPE_IGNORED
;
2574 if (starts_with(ss
->name
, ".exitcall.exit"))
2575 return SS_TYPE_IGNORED
;
2576 if (starts_with(ss
->name
, ".modinfo"))
2577 return SS_TYPE_IGNORED
;
2579 return SS_TYPE_UNKNOWN
;
2582 void initialize_supersect_types(struct superbfd
*sbfd
)
2585 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
2586 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
2587 ss
->type
= supersect_type(ss
);
2588 ss
->orig_type
= ss
->type
;
2589 if (ss
->type
== SS_TYPE_UNKNOWN
) {
2590 err(sbfd
, "Unknown section type: %s\n", ss
->name
);
2596 static void init_label_map(struct superbfd
*sbfd
)
2598 struct label_map
*map
;
2600 vec_init(&sbfd
->maps
);
2604 struct symbol_hash csyms
;
2605 symbol_hash_init(&csyms
);
2608 for (symp
= sbfd
->syms
.data
;
2609 symp
< sbfd
->syms
.data
+ sbfd
->syms
.size
; symp
++) {
2610 asymbol
*csym
= canonical_symbol(sbfd
, *symp
);
2613 char *key
= strprintf("%p", csym
);
2614 asymbol
**csymp
= symbol_hash_lookup(&csyms
, key
, TRUE
);
2620 map
= vec_grow(&sbfd
->maps
, 1);
2623 map
->label
= symbol_label(sbfd
, csym
);
2626 struct label_mapp_hash label_maps
;
2627 label_mapp_hash_init(&label_maps
);
2628 for (map
= sbfd
->maps
.data
;
2629 map
< sbfd
->maps
.data
+ sbfd
->maps
.size
; map
++) {
2630 struct label_map
**mapp
=
2631 label_mapp_hash_lookup(&label_maps
, map
->label
, TRUE
);
2632 if (*mapp
== NULL
) {
2637 struct label_map
*first_map
= *mapp
;
2638 if (first_map
->count
== 0)
2639 first_map
->label
= strprintf("%s~%d", map
->label
, 0);
2640 map
->label
= strprintf("%s~%d", map
->label
, ++first_map
->count
);
2643 label_mapp_hash_init(&sbfd
->maps_hash
);
2644 for (map
= sbfd
->maps
.data
;
2645 map
< sbfd
->maps
.data
+ sbfd
->maps
.size
; map
++) {
2646 char *key
= strprintf("%p", map
->csym
);
2647 struct label_map
**mapp
=
2648 label_mapp_hash_lookup(&sbfd
->maps_hash
, key
, TRUE
);
2651 map
->orig_label
= map
->label
;
2655 static const char *label_lookup(struct superbfd
*sbfd
, asymbol
*sym
)
2657 asymbol
*csym
= canonical_symbol(sbfd
, sym
);
2658 char *key
= strprintf("%p", csym
);
2659 struct label_map
**mapp
=
2660 label_mapp_hash_lookup(&sbfd
->maps_hash
, key
, FALSE
);
2664 return (*mapp
)->label
;
2667 static void print_label_changes(struct superbfd
*sbfd
)
2671 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
2672 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
2673 for (span
= ss
->spans
.data
;
2674 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++) {
2675 if (strcmp(span
->label
, span
->orig_label
) != 0)
2676 debug1(sbfd
, "Label change: %s -> %s\n",
2677 span
->label
, span
->orig_label
);
2682 static void label_map_set(struct superbfd
*sbfd
, const char *oldlabel
,
2685 struct label_map
*map
;
2686 for (map
= sbfd
->maps
.data
;
2687 map
< sbfd
->maps
.data
+ sbfd
->maps
.size
; map
++) {
2688 if (strcmp(map
->orig_label
, oldlabel
) == 0) {
2689 if (strcmp(map
->orig_label
, map
->label
) != 0 &&
2690 strcmp(map
->label
, label
) != 0)
2699 static void change_initial_label(struct span
*span
, const char *label
)
2701 struct superbfd
*sbfd
= span
->ss
->parent
;
2702 span
->label
= label
;
2703 span
->orig_label
= label
;
2705 asymbol
*csym
= canonical_symbol(sbfd
, span
->symbol
);
2706 char *key
= strprintf("%p", csym
);
2707 struct label_map
**mapp
=
2708 label_mapp_hash_lookup(&sbfd
->maps_hash
, key
, FALSE
);
2711 (*mapp
)->label
= span
->label
;
2712 (*mapp
)->orig_label
= span
->orig_label
;
2713 span
->symbol
= NULL
;
2717 static void init_callers(struct superbfd
*sbfd
)
2719 string_hash_init(&sbfd
->callers
);
2721 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
2722 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
2724 for (relocp
= ss
->relocs
.data
;
2725 relocp
< ss
->relocs
.data
+ ss
->relocs
.size
; relocp
++) {
2726 asymbol
*sym
= *(*relocp
)->sym_ptr_ptr
;
2728 sym
->value
+ get_reloc_offset(ss
, *relocp
, true);
2729 char *key
= strprintf("%s+%lx", sym
->section
->name
,
2731 const char **ret
= string_hash_lookup(&sbfd
->callers
,
2734 asymbol
*csym
= canonical_symbol(sbfd
, sect
->symbol
);
2736 *ret
= "*multiple_callers*";
2737 else if (static_local_symbol(sbfd
, csym
))
2738 *ret
= static_local_symbol(sbfd
, csym
);
2745 static const char *find_caller(struct supersect
*ss
, asymbol
*sym
)
2747 char *key
= strprintf("%s+%lx", sym
->section
->name
,
2748 (unsigned long)sym
->value
);
2749 const char **ret
= string_hash_lookup(&ss
->parent
->callers
, key
, FALSE
);
2753 return "*no_caller*";
2757 static void init_csyms(struct superbfd
*sbfd
)
2759 asymbolpp_hash_init(&sbfd
->csyms
);
2762 for (symp
= sbfd
->syms
.data
; symp
< sbfd
->syms
.data
+ sbfd
->syms
.size
;
2764 asymbol
*sym
= *symp
;
2765 if ((sym
->flags
& BSF_DEBUGGING
) != 0)
2767 char *key
= strprintf("%s+%lx", sym
->section
->name
,
2768 (unsigned long)sym
->value
);
2769 asymbol
***csympp
= asymbolpp_hash_lookup(&sbfd
->csyms
, key
,
2772 if (*csympp
== NULL
) {
2776 asymbol
*csym
= **csympp
;
2777 if ((csym
->flags
& BSF_GLOBAL
) != 0)
2779 if ((sym
->flags
& BSF_GLOBAL
) != 0)
2784 static asymbol
**symbolp_scan(struct supersect
*ss
, bfd_vma value
)
2786 char *key
= strprintf("%s+%lx", ss
->name
, (unsigned long)value
);
2788 asymbolpp_hash_lookup(&ss
->parent
->csyms
, key
, FALSE
);
2793 /* For section symbols of sections containing no symbols, return the
2794 section symbol that relocations are generated against */
2800 static asymbol
**canonical_symbolp(struct superbfd
*sbfd
, asymbol
*sym
)
2802 if (bfd_is_const_section(sym
->section
)) {
2804 for (csymp
= sbfd
->syms
.data
;
2805 csymp
< sbfd
->syms
.data
+ sbfd
->syms
.size
; csymp
++) {
2811 return symbolp_scan(fetch_supersect(sbfd
, sym
->section
), sym
->value
);
2814 static asymbol
*canonical_symbol(struct superbfd
*sbfd
, asymbol
*sym
)
2816 if (bfd_is_const_section(sym
->section
))
2818 asymbol
**symp
= canonical_symbolp(sbfd
, sym
);
2819 return symp
!= NULL
? *symp
: NULL
;
2822 static char *static_local_symbol(struct superbfd
*sbfd
, asymbol
*sym
)
2824 struct supersect
*ss
= fetch_supersect(sbfd
, sym
->section
);
2825 if ((sym
->flags
& BSF_LOCAL
) == 0 || (sym
->flags
& BSF_OBJECT
) == 0)
2827 char *dot
= strrchr(sym
->name
, '.');
2828 if (dot
== NULL
|| dot
[1 + strspn(dot
+ 1, "0123546789")] != '\0')
2830 char *basename
= strndup(sym
->name
, dot
- sym
->name
);
2832 /* Handle C.123.12345 symbols */
2833 dot
= strrchr(basename
, '.');
2834 if (dot
!= NULL
&& dot
[1 + strspn(dot
+ 1, "0123546789")] == '\0')
2835 basename
= strndup(basename
, dot
- basename
);
2837 if (strcmp(basename
, "__func__") == 0 ||
2838 strcmp(basename
, "__PRETTY_FUNCTION__") == 0)
2839 caller
= (const char *)ss
->contents
.data
+ sym
->value
;
2841 caller
= find_caller(ss
, sym
);
2842 return strprintf("%s<%s>", basename
, caller
);
2845 static char *symbol_label(struct superbfd
*sbfd
, asymbol
*sym
)
2847 const char *filename
= sbfd
->abfd
->filename
;
2848 char *c
= strstr(filename
, ".KSPLICE");
2849 int flen
= (c
== NULL
? strlen(filename
) : c
- filename
);
2852 if (bfd_is_und_section(sym
->section
) || (sym
->flags
& BSF_GLOBAL
) != 0) {
2853 label
= strdup(sym
->name
);
2854 } else if (bfd_is_const_section(sym
->section
)) {
2855 label
= strprintf("%s<%.*s>", sym
->name
, flen
, filename
);
2857 asymbol
*gsym
= canonical_symbol(sbfd
, sym
);
2860 label
= strprintf("%s+%lx<%.*s>",
2862 (unsigned long)sym
->value
,
2864 else if ((gsym
->flags
& BSF_GLOBAL
) != 0)
2865 label
= strdup(gsym
->name
);
2866 else if (static_local_symbol(sbfd
, gsym
))
2867 label
= strprintf("%s+%lx<%.*s>",
2868 static_local_symbol(sbfd
, gsym
),
2869 (unsigned long)sym
->value
,
2872 label
= strprintf("%s<%.*s>",
2873 gsym
->name
, flen
, filename
);
2879 static void keep_span(struct span
*span
)
2882 span
->ss
->keep
= true;
2885 static struct span
*new_span(struct supersect
*ss
, bfd_vma start
, bfd_vma size
)
2887 struct span
*span
= vec_grow(&ss
->spans
, 1);
2889 span
->contents_size
= size
;
2890 span
->start
= start
;
2894 span
->patch
= false;
2895 span
->bugpatch
= false;
2896 span
->datapatch
= false;
2897 span
->precallable
= starts_with(ss
->name
, ".ksplice_call_pre_apply") ||
2898 starts_with(ss
->name
, ".ksplice_call_check_apply") ||
2899 starts_with(ss
->name
, ".ksplice_call_fail_apply") ||
2900 starts_with(ss
->name
, ".ksplice_call_post_remove");
2903 asymbol
**symp
= symbolp_scan(ss
, span
->start
);
2905 span
->symbol
= *symp
;
2906 span
->label
= label_lookup(ss
->parent
, span
->symbol
);
2908 span
->symbol
= NULL
;
2909 const char *label
= label_lookup(ss
->parent
, ss
->symbol
);
2910 if (span
->start
!= 0)
2911 span
->label
= strprintf("%s<span:%lx>", label
,
2912 (unsigned long)span
->start
);
2914 span
->label
= label
;
2916 span
->orig_label
= span
->label
;
2920 static void initialize_string_spans(struct supersect
*ss
)
2923 for (str
= ss
->contents
.data
;
2924 (void *)str
< ss
->contents
.data
+ ss
->contents
.size
;) {
2925 bfd_vma start
= (unsigned long)str
-
2926 (unsigned long)ss
->contents
.data
;
2927 bfd_vma size
= strlen(str
) + 1;
2928 bfd_vma contents_size
= size
;
2929 while ((start
+ size
) % (1 << ss
->alignment
) != 0 &&
2930 start
+ size
< ss
->contents
.size
) {
2931 /* Some string sections, like __ksymtab_strings, only
2932 align some strings with the declared alignment */
2933 if (str
[size
] != '\0')
2937 struct span
*span
= new_span(ss
, start
, size
);
2938 span
->contents_size
= contents_size
;
2943 static int compare_ulongs(const void *va
, const void *vb
)
2945 const unsigned long *a
= va
, *b
= vb
;
2949 static void initialize_table_spans(struct superbfd
*sbfd
,
2950 struct table_section
*s
)
2952 asection
*isection
= bfd_get_section_by_name(sbfd
->abfd
, s
->sect
);
2953 if (isection
== NULL
)
2955 struct supersect
*ss
= fetch_supersect(sbfd
, isection
);
2956 if (ss
->alignment
< ffs(s
->entry_align
) - 1)
2957 ss
->alignment
= ffs(s
->entry_align
) - 1;
2959 asection
*other_sect
= NULL
;
2960 if (s
->other_sect
!= NULL
)
2961 other_sect
= bfd_get_section_by_name(sbfd
->abfd
, s
->other_sect
);
2962 struct supersect
*other_ss
= NULL
;
2963 if (other_sect
!= NULL
)
2964 other_ss
= fetch_supersect(sbfd
, other_sect
);
2966 asection
*crc_sect
= NULL
;
2967 if (s
->crc_sect
!= NULL
)
2968 crc_sect
= bfd_get_section_by_name(sbfd
->abfd
, s
->crc_sect
);
2969 struct supersect
*crc_ss
= NULL
;
2970 if (crc_sect
!= NULL
)
2971 crc_ss
= fetch_supersect(sbfd
, crc_sect
);
2973 struct ulong_vec offsets
;
2977 for (entry
= ss
->contents
.data
;
2978 entry
< ss
->contents
.data
+ ss
->contents
.size
;
2979 entry
+= s
->entry_size
) {
2980 struct span
*span
= new_span(ss
, addr_offset(ss
, entry
),
2982 if (s
->entry_contents_size
!= 0)
2983 span
->contents_size
= s
->entry_contents_size
;
2984 if ((span
->symbol
== NULL
||
2985 (span
->symbol
->flags
& BSF_SECTION_SYM
) != 0) &&
2987 arelent
*reloc
= find_reloc(ss
, entry
+ s
->addr_offset
);
2989 struct span
*target_span
= reloc_target_span(ss
, reloc
);
2990 assert(target_span
);
2991 asymbol
*sym
= *reloc
->sym_ptr_ptr
;
2992 unsigned long val
= get_reloc_offset(ss
, reloc
, true) +
2993 sym
->value
- (target_span
->start
+
2994 target_span
->shift
);
2995 char *label
= strprintf("%s<target:%s+%lx>", ss
->name
,
2996 target_span
->label
, val
);
2997 change_initial_label(span
, label
);
3000 if (other_sect
!= NULL
) {
3002 bfd_vma offset
= read_reloc(ss
, entry
+ s
->other_offset
,
3003 sizeof(void *), &sym
);
3004 if (sym
->section
== other_sect
) {
3005 assert(offset
>= 0 &&
3006 offset
< other_ss
->contents
.size
);
3007 *vec_grow(&offsets
, 1) = offset
;
3011 if (crc_sect
!= NULL
)
3012 new_span(crc_ss
, addr_offset(ss
, entry
) / s
->entry_size
3013 * s
->crc_size
, s
->crc_size
);
3015 if (ss
->type
== SS_TYPE_EXPORT
) {
3016 const char *symname
= read_string(ss
, entry
+
3018 char *label
= strprintf("%s:%s", ss
->name
, symname
);
3019 change_initial_label(span
, label
);
3023 if (other_sect
== NULL
)
3026 *vec_grow(&offsets
, 1) = 0;
3027 qsort(offsets
.data
, offsets
.size
, sizeof(*offsets
.data
),
3029 *vec_grow(&offsets
, 1) = other_ss
->contents
.size
;
3032 for (off
= offsets
.data
; off
< offsets
.data
+ offsets
.size
- 1; off
++) {
3033 if (*off
!= *(off
+ 1))
3034 new_span(other_ss
, *off
, *(off
+ 1) - *off
);
3038 static void initialize_table_section_spans(struct superbfd
*sbfd
)
3040 struct supersect
*tables_ss
=
3041 fetch_supersect(offsets_sbfd
,
3042 bfd_get_section_by_name(offsets_sbfd
->abfd
,
3043 ".ksplice_table_sections"));
3044 const struct table_section
*ts
;
3045 struct table_section s
;
3046 for (ts
= tables_ss
->contents
.data
;
3047 (void *)ts
< tables_ss
->contents
.data
+ tables_ss
->contents
.size
;
3050 s
.sect
= read_string(tables_ss
, &ts
->sect
);
3051 s
.other_sect
= read_string(tables_ss
, &ts
->other_sect
);
3052 s
.crc_sect
= read_string(tables_ss
, &ts
->crc_sect
);
3053 initialize_table_spans(sbfd
, &s
);
3057 static void initialize_ksplice_call_spans(struct supersect
*ss
)
3060 for (relocp
= ss
->relocs
.data
;
3061 relocp
< ss
->relocs
.data
+ ss
->relocs
.size
; relocp
++) {
3062 arelent
*reloc
= *relocp
;
3063 new_span(ss
, reloc
->address
, bfd_get_reloc_size(reloc
->howto
));
3064 /* the span labels should already be unique */
3068 static void initialize_spans(struct superbfd
*sbfd
)
3071 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
3072 if (is_table_section(sect
->name
, true, true) && mode("keep"))
3075 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
3076 if (ss
->type
== SS_TYPE_STRING
)
3077 initialize_string_spans(ss
);
3078 else if (ss
->type
== SS_TYPE_KSPLICE_CALL
)
3079 initialize_ksplice_call_spans(ss
);
3081 new_span(ss
, 0, ss
->contents
.size
);
3084 initialize_table_section_spans(sbfd
);
3087 /* Returns the span pointed to by the relocation at span->start + offset */
3088 static struct span
*span_offset_target_span(struct span
*span
, int offset
)
3090 void *entry
= span
->ss
->contents
.data
+ span
->start
;
3091 arelent
*reloc
= find_reloc(span
->ss
, entry
+ offset
);
3094 struct span
*sym_span
= reloc_target_span(span
->ss
, reloc
);
3095 if (sym_span
== NULL
)
3100 struct span
*reloc_target_span(struct supersect
*ss
, arelent
*reloc
)
3102 asymbol
*sym_ptr
= *reloc
->sym_ptr_ptr
;
3103 if (bfd_is_const_section(sym_ptr
->section
))
3106 bfd_vma addend
= get_reloc_offset(ss
, reloc
, true) + sym_ptr
->value
;
3107 struct supersect
*sym_ss
=
3108 fetch_supersect(ss
->parent
, sym_ptr
->section
);
3109 struct span
*span
, *target_span
= sym_ss
->spans
.data
;
3110 for (span
= sym_ss
->spans
.data
;
3111 span
< sym_ss
->spans
.data
+ sym_ss
->spans
.size
; span
++) {
3112 if (addend
>= span
->start
&& addend
< span
->start
+ span
->size
)
3118 struct span
*find_span(struct supersect
*ss
, bfd_size_type address
)
3121 for (span
= ss
->spans
.data
; span
< ss
->spans
.data
+ ss
->spans
.size
;
3123 if (address
>= span
->start
&&
3124 address
< span
->start
+ span
->size
)
3127 /* Deal with empty BSS sections */
3128 if (ss
->contents
.size
== 0 && ss
->spans
.size
> 0)
3129 return ss
->spans
.data
;
3133 void compute_span_shifts(struct superbfd
*sbfd
)
3137 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
3138 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
3141 bfd_size_type offset
= 0;
3142 for (span
= ss
->spans
.data
;
3143 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++) {
3146 span
->shift
= offset
- span
->start
;
3147 offset
+= span
->size
;
3152 void remove_unkept_spans(struct superbfd
*sbfd
)
3156 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
3157 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
3158 delete_obsolete_relocs(ss
);
3159 struct arelentp_vec orig_relocs
;
3160 vec_move(&orig_relocs
, &ss
->relocs
);
3161 arelent
**relocp
, *reloc
;
3162 for (relocp
= orig_relocs
.data
;
3163 relocp
< orig_relocs
.data
+ orig_relocs
.size
; relocp
++) {
3165 asymbol
*sym
= *reloc
->sym_ptr_ptr
;
3166 span
= reloc_target_span(ss
, reloc
);
3167 if ((span
!= NULL
&& span
->keep
&& span
->shift
== 0) ||
3168 bfd_is_const_section(sym
->section
)) {
3169 *vec_grow(&ss
->relocs
, 1) = reloc
;
3172 struct supersect
*sym_ss
=
3173 fetch_supersect(sbfd
, sym
->section
);
3174 if (span
!= NULL
&& (sym
->flags
& BSF_SECTION_SYM
) == 0
3175 && find_span(sym_ss
, sym
->value
) != span
) {
3176 err(sbfd
, "Spans for symbol %s and relocation "
3177 "target do not match in sect %s\n",
3178 sym
->name
, sym_ss
->name
);
3181 if (span
!= NULL
&& span
->keep
) {
3182 arelent
*new_reloc
= malloc(sizeof(*new_reloc
));
3183 *new_reloc
= *reloc
;
3185 get_reloc_offset(ss
, reloc
, false);
3186 new_reloc
->addend
+= span
->shift
;
3187 *vec_grow(&ss
->new_relocs
, 1) = new_reloc
;
3192 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
3193 struct supersect
*ss
= fetch_supersect(sbfd
, sect
), orig_ss
;
3196 supersect_move(&orig_ss
, ss
);
3197 vec_init(&ss
->spans
);
3198 for (span
= orig_ss
.spans
.data
;
3199 span
< orig_ss
.spans
.data
+ orig_ss
.spans
.size
; span
++) {
3202 struct span
*new_span
= vec_grow(&ss
->spans
, 1);
3204 new_span
->start
= span
->start
+ span
->shift
;
3205 new_span
->shift
= 0;
3206 sect_copy(ss
, sect_do_grow(ss
, 1, span
->size
, 1),
3207 &orig_ss
, orig_ss
.contents
.data
+ span
->start
,
3213 static void init_objmanip_superbfd(struct superbfd
*sbfd
)
3215 init_label_map(sbfd
);
3216 initialize_supersect_types(sbfd
);
3217 initialize_spans(sbfd
);
3221 void mangle_section_name(struct superbfd
*sbfd
, const char *name
)
3223 asection
*sect
= bfd_get_section_by_name(sbfd
->abfd
, name
);
3226 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
3227 ss
->name
= strprintf(".ksplice_pre.%s", ss
->name
);
3230 static void write_bugline_patches(struct superbfd
*sbfd
)
3232 const struct table_section
*ts
= get_table_section("__bug_table");
3233 asection
*sect
= bfd_get_section_by_name(sbfd
->abfd
, "__bug_table");
3236 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
3240 for (entry
= ss
->contents
.data
;
3241 entry
< ss
->contents
.data
+ ss
->contents
.size
;
3242 entry
+= ts
->entry_size
) {
3243 struct span
*span
= find_span(ss
, addr_offset(ss
, entry
));
3244 assert(span
!= NULL
);
3245 if (!span
->bugpatch
)
3247 arelent
*reloc
= find_reloc(ss
, entry
+ ts
->addr_offset
);
3248 assert(reloc
!= NULL
);
3249 asymbol
*sym
= *reloc
->sym_ptr_ptr
;
3250 assert(!bfd_is_const_section(sym
->section
));
3252 struct supersect
*kpatch_ss
=
3253 make_section(sbfd
, ".ksplice_patches%s",
3254 sym
->section
->name
);
3255 struct ksplice_patch
*kpatch
=
3256 sect_grow(kpatch_ss
, 1, struct ksplice_patch
);
3257 write_ksplice_patch_reloc
3258 (kpatch_ss
, sym
->section
->name
, &kpatch
->oldaddr
,
3259 sizeof(kpatch
->oldaddr
), span
->label
, ts
->other_offset
);
3261 unsigned short *line
=
3262 write_patch_storage(kpatch_ss
, kpatch
, sizeof(*line
), NULL
);
3263 *line
= *(unsigned short *)(entry
+ ts
->other_offset
);
3264 kpatch
->type
= KSPLICE_PATCH_BUGLINE
;
3268 void *write_patch_storage(struct supersect
*ss
, struct ksplice_patch
*kpatch
,
3269 size_t size
, struct supersect
**data_ssp
)
3271 struct supersect
*data_ss
= make_section(ss
->parent
,
3272 ".ksplice_patch_data");
3273 char *saved
= sect_do_grow(data_ss
, 1, size
, 1);
3274 write_reloc(ss
, &kpatch
->saved
, &data_ss
->symbol
,
3275 addr_offset(data_ss
, saved
));
3276 char *data
= sect_do_grow(data_ss
, 1, size
, 1);
3277 write_reloc(ss
, &kpatch
->contents
, &data_ss
->symbol
,
3278 addr_offset(data_ss
, data
));
3279 kpatch
->size
= size
;
3280 if (data_ssp
!= NULL
)
3281 *data_ssp
= data_ss
;