1 /* This file is based in part on objcopy.c from GNU Binutils v2.17.
3 * Copyright (C) 1991-2006 Free Software Foundation, Inc.
4 * Copyright (C) 2007-2008 Jeffrey Brian Arnold <jbarnold@mit.edu>
5 * Copyright (C) 2008 Anders Kaseorg <andersk@mit.edu>,
6 * Tim Abbott <tabbott@mit.edu>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License, version 2.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
22 /* objmanip performs various object file manipulations for Ksplice. Its first
23 * two arguments are always an input object file and an output object file.
25 * - keep-primary: "objmanip <post.o> <out.o> keep-primary <pre.o> <kid>"
27 * This mode prepares the object file to be installed as a ksplice update. The
28 * kid argument is the ksplice id string for the ksplice update being built.
30 * - keep-helper: "objmanip <pre.o> <out.o> keep-helper"
32 * This mode prepares the object file to be used for run-pre matching. This
33 * involves replacing all ELF relocations with ksplice relocations and
34 * writing ksplice_section structures for each ELF text or data section.
36 * - rmsyms mode: "objmanip <in.o> <out.o> rmsyms
38 * In this mode, any ELF relocations involving the list of symbol names given on
39 * standard input are replaced with ksplice relocations. This is used only
40 * for KSPLICE_STANDALONE.
42 * - finalize mode: "objmanip <in.o> <out.o> finalize"
44 * In this mode, any ELF relocations to undefined symbols are replaced with
45 * ksplice relocations.
48 /* Always define KSPLICE_STANDALONE, even if you're using integrated Ksplice.
49 objmanip won't compile without it. */
50 #define KSPLICE_STANDALONE
53 #include "objcommon.h"
54 #include "kmodsrc/ksplice.h"
55 #include "kmodsrc/offsets.h"
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
);
72 DECLARE_VEC_TYPE(struct export
, export_vec
);
74 DECLARE_VEC_TYPE(const char *, str_vec
);
76 DECLARE_VEC_TYPE(unsigned long, ulong_vec
);
79 const char *export_type
;
82 struct supersect
*sym_ss
;
83 struct supersect
*crc_ss
;
85 DECLARE_VEC_TYPE(struct export_desc
, export_desc_vec
);
87 #define bool_init(b) *(b) = false
88 DEFINE_HASH_TYPE(bool, bool_hash
, bool_hash_init
, bool_hash_free
,
89 bool_hash_lookup
, bool_init
);
91 #define ulong_init(x) *(x) = 0
92 DEFINE_HASH_TYPE(unsigned long, ulong_hash
, ulong_hash_init
,
93 ulong_hash_free
, ulong_hash_lookup
, ulong_init
);
95 void do_keep_primary(struct superbfd
*isbfd
, const char *pre
);
96 void do_keep_helper(struct superbfd
*isbfd
);
97 void do_finalize(struct superbfd
*isbfd
);
98 void do_rmsyms(struct superbfd
*isbfd
);
100 struct export_vec
*get_export_syms(struct superbfd
*sbfd
);
101 void compare_exported_symbols(struct superbfd
*oldsbfd
,
102 struct superbfd
*newsbfd
, bool deletion
);
103 struct export_desc
*new_export_desc(struct supersect
*ss
, bool deletion
);
104 bool relocs_equal(struct supersect
*old_src_ss
, struct supersect
*new_src_ss
,
105 arelent
*old_reloc
, arelent
*new_reloc
);
106 bfd_vma
non_dst_mask(struct supersect
*ss
, arelent
*reloc
);
107 bool all_relocs_equal(struct span
*old_span
, struct span
*new_span
);
108 static bool part_of_reloc(struct supersect
*ss
, unsigned long addr
);
109 static bool nonrelocs_equal(struct span
*old_span
, struct span
*new_span
);
110 static void handle_section_symbol_renames(struct superbfd
*oldsbfd
,
111 struct superbfd
*newsbfd
);
113 enum supersect_type
supersect_type(struct supersect
*ss
);
114 void initialize_supersect_types(struct superbfd
*sbfd
);
115 static void initialize_spans(struct superbfd
*sbfd
);
116 static void initialize_string_spans(struct supersect
*ss
);
117 static void initialize_table_spans(struct superbfd
*sbfd
,
118 struct table_section
*s
);
119 static void initialize_table_section_spans(struct superbfd
*sbfd
);
120 struct span
*reloc_target_span(struct supersect
*ss
, arelent
*reloc
);
121 struct span
*find_span(struct supersect
*ss
, bfd_size_type address
);
122 void remove_unkept_spans(struct superbfd
*sbfd
);
123 void compute_span_shifts(struct superbfd
*sbfd
);
124 static struct span
*new_span(struct supersect
*ss
, bfd_vma start
, bfd_vma size
);
125 bool is_table_section(const char *name
, bool consider_other
);
126 const struct table_section
*get_table_section(const char *name
);
127 void mangle_section_name(struct superbfd
*sbfd
, const char *name
);
129 void rm_relocs(struct superbfd
*isbfd
);
130 void rm_some_relocs(struct supersect
*ss
);
131 void write_ksplice_reloc(struct supersect
*ss
, arelent
*orig_reloc
);
132 static void write_ksplice_reloc_howto(struct supersect
*ss
, const
133 struct ksplice_reloc_howto
*const *addr
,
134 reloc_howto_type
*howto
);
135 static void write_ksplice_date_reloc(struct supersect
*ss
, unsigned long offset
,
137 enum ksplice_reloc_howto_type type
);
138 static void write_ksplice_nonreloc_howto(struct supersect
*ss
,
139 const struct ksplice_reloc_howto
141 enum ksplice_reloc_howto_type type
,
143 static void write_date_relocs(struct superbfd
*sbfd
, const char *str
,
144 enum ksplice_reloc_howto_type type
);
145 void load_ksplice_symbol_offsets(struct superbfd
*sbfd
);
146 void blot_section(struct supersect
*ss
, int offset
, reloc_howto_type
*howto
);
147 static void write_ksplice_section(struct span
*span
);
148 void write_ksplice_patch(struct superbfd
*sbfd
, struct span
*span
);
149 void write_ksplice_deleted_patch(struct superbfd
*sbfd
, const char *name
,
150 const char *label
, const char *sectname
);
151 asymbol
**make_undefined_symbolp(struct superbfd
*sbfd
, const char *name
);
152 void filter_table_sections(struct superbfd
*isbfd
);
153 void filter_table_section(struct superbfd
*sbfd
, const struct table_section
*s
);
154 void keep_referenced_sections(struct superbfd
*sbfd
);
155 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 rm_some_exports(struct superbfd
*isbfd
, const struct export_desc
*ed
);
173 void write_ksplice_export(struct superbfd
*sbfd
, const char *symname
,
174 const char *export_type
, bool del
);
175 void write_reloc(struct supersect
*ss
, const void *addr
, asymbol
**symp
,
177 arelent
*create_reloc(struct supersect
*ss
, const void *addr
, asymbol
**symp
,
179 static void foreach_symbol_pair(struct superbfd
*oldsbfd
, struct superbfd
*newsbfd
,
180 void (*fn
)(struct span
*old_span
,
182 struct span
*new_span
,
184 static void check_global_symbols(struct span
*old_span
, asymbol
*oldsym
,
185 struct span
*new_span
, asymbol
*newsym
);
186 static void match_global_symbols(struct span
*old_span
, asymbol
*oldsym
,
187 struct span
*new_span
, asymbol
*newsym
);
188 static void match_symbol_spans(struct span
*old_span
, asymbol
*oldsym
,
189 struct span
*new_span
, asymbol
*newsym
);
191 static void foreach_span_pair(struct superbfd
*oldsbfd
,
192 struct superbfd
*newsbfd
,
193 void (*fn
)(struct span
*old_span
,
194 struct span
*new_span
));
195 static void match_spans_by_label(struct span
*old_span
, struct span
*new_span
);
196 static void match_string_spans(struct span
*old_span
, struct span
*new_span
);
197 static void mark_new_spans(struct superbfd
*sbfd
);
198 static void handle_deleted_spans(struct superbfd
*oldsbfd
,
199 struct superbfd
*newsbfd
);
200 static void compare_matched_spans(struct superbfd
*newsbfd
);
201 static void compare_spans(struct span
*old_span
, struct span
*new_span
);
202 static void update_nonzero_offsets(struct superbfd
*sbfd
);
203 static void handle_nonzero_offset_relocs(struct supersect
*ss
);
204 static void keep_span(struct span
*span
);
206 static void init_objmanip_superbfd(struct superbfd
*sbfd
);
207 static const char *label_lookup(struct superbfd
*sbfd
, asymbol
*sym
);
208 static void label_map_set(struct superbfd
*sbfd
, const char *oldlabel
,
210 static void print_label_changes(struct superbfd
*sbfd
);
211 static void init_label_map(struct superbfd
*sbfd
);
212 static asymbol
**symbolp_scan(struct supersect
*ss
, bfd_vma value
);
213 static void init_csyms(struct superbfd
*sbfd
);
214 static void init_callers(struct superbfd
*sbfd
);
215 static asymbol
*canonical_symbol(struct superbfd
*sbfd
, asymbol
*sym
);
216 static asymbol
**canonical_symbolp(struct superbfd
*sbfd
, asymbol
*sym
);
217 static char *static_local_symbol(struct superbfd
*sbfd
, asymbol
*sym
);
218 static char *symbol_label(struct superbfd
*sbfd
, asymbol
*sym
);
221 #define debug_(sbfd, level, fmt, ...) \
223 if (verbose >= (level)) \
224 printf("%s: " fmt, (sbfd)->abfd->filename, \
227 #define debug0(sbfd, fmt, ...) debug_(sbfd, 0, fmt, ## __VA_ARGS__)
228 #define debug1(sbfd, fmt, ...) debug_(sbfd, 1, fmt, ## __VA_ARGS__)
229 #define err(sbfd, fmt, ...) \
231 fprintf(stderr, "%s: " fmt, (sbfd)->abfd->filename, \
235 struct str_vec delsects
, rmsyms
;
236 struct export_desc_vec exports
;
239 struct ksplice_config
*config
;
241 const char *modestr
, *kid
, *finalize_target
= NULL
;
242 bool write_output
= true;
244 struct superbfd
*offsets_sbfd
= NULL
;
246 #define mode(str) starts_with(modestr, str)
248 DECLARE_VEC_TYPE(unsigned long, addr_vec
);
249 DEFINE_HASH_TYPE(struct addr_vec
, addr_vec_hash
,
250 addr_vec_hash_init
, addr_vec_hash_free
, addr_vec_hash_lookup
,
252 struct addr_vec_hash system_map
;
254 struct bool_hash system_map_written
;
255 struct ulong_hash ksplice_symbol_offset
;
256 struct ulong_hash ksplice_howto_offset
;
257 struct ulong_hash ksplice_string_offset
;
259 void load_system_map()
261 const char *config_dir
= getenv("KSPLICE_CONFIG_DIR");
264 assert(asprintf(&file
, "%s/System.map", config_dir
) >= 0);
265 FILE *fp
= fopen(file
, "r");
267 addr_vec_hash_init(&system_map
);
271 while (fscanf(fp
, "%lx %c %as\n", &addr
, &type
, &sym
) == 3)
272 *vec_grow(addr_vec_hash_lookup(&system_map
, sym
, TRUE
),
277 void load_ksplice_symbol_offsets(struct superbfd
*sbfd
)
279 asection
*sect
= bfd_get_section_by_name(sbfd
->abfd
,
283 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
285 struct ksplice_symbol
*ksym
;
286 for (ksym
= ss
->contents
.data
;
287 (void *)ksym
< ss
->contents
.data
+ ss
->contents
.size
; ksym
++) {
288 const char *label
= read_string(ss
, &ksym
->label
);
289 unsigned long *ksymbol_offp
=
290 ulong_hash_lookup(&ksplice_symbol_offset
, label
, TRUE
);
291 *ksymbol_offp
= addr_offset(ss
, ksym
);
297 char *kmodsrc
= getenv("KSPLICE_KMODSRC"), *offsets_file
;
298 assert(kmodsrc
!= NULL
);
299 assert(asprintf(&offsets_file
, "%s/offsets.o", kmodsrc
) >= 0);
300 bfd
*offsets_bfd
= bfd_openr(offsets_file
, 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 bool matchable_data_section(struct supersect
*ss
)
316 if (ss
->type
== SS_TYPE_STRING
)
318 if (ss
->type
== SS_TYPE_RODATA
)
320 if (ss
->type
== SS_TYPE_DATA
&& ss
->relocs
.size
!= 0)
325 bool unchangeable_section(struct supersect
*ss
)
327 if (ss
->type
== SS_TYPE_DATA
)
329 if (ss
->type
== SS_TYPE_IGNORED
&& !starts_with(ss
->name
, ".debug") &&
330 strcmp(ss
->name
, "__ksymtab_strings") != 0)
335 int main(int argc
, char *argv
[])
337 if (getenv("KSPLICE_VERBOSE") != NULL
)
338 verbose
= atoi(getenv("KSPLICE_VERBOSE"));
341 bfd
*ibfd
= bfd_openr(argv
[1], NULL
);
345 assert(bfd_check_format_matches(ibfd
, bfd_object
, &matching
));
347 const char *output_target
= bfd_get_target(ibfd
);
352 bool_hash_init(&system_map_written
);
353 ulong_hash_init(&ksplice_symbol_offset
);
354 ulong_hash_init(&ksplice_howto_offset
);
355 ulong_hash_init(&ksplice_string_offset
);
357 struct superbfd
*isbfd
= fetch_superbfd(ibfd
);
360 if (mode("finalize"))
361 finalize_target
= argv
[4];
362 init_objmanip_superbfd(isbfd
);
363 if (mode("keep-primary")) {
365 do_keep_primary(isbfd
, argv
[4]);
366 } else if (mode("keep-helper")) {
367 do_keep_helper(isbfd
);
368 } else if (mode("finalize")) {
370 } else if (mode("rmsyms")) {
375 bfd
*obfd
= bfd_openw(argv
[2], output_target
);
377 copy_object(ibfd
, obfd
);
378 assert(bfd_close(obfd
));
381 if (offsets_sbfd
!= NULL
)
382 assert(bfd_close(offsets_sbfd
->abfd
));
383 assert(bfd_close(ibfd
));
387 void do_keep_primary(struct superbfd
*isbfd
, const char *pre
)
389 struct bfd
*prebfd
= bfd_openr(pre
, NULL
);
390 assert(prebfd
!= NULL
);
392 assert(bfd_check_format_matches(prebfd
, bfd_object
, &matching
));
394 struct superbfd
*presbfd
= fetch_superbfd(prebfd
);
395 init_objmanip_superbfd(presbfd
);
397 foreach_symbol_pair(presbfd
, isbfd
, match_global_symbols
);
398 debug1(isbfd
, "Matched global\n");
399 foreach_span_pair(presbfd
, isbfd
, match_string_spans
);
400 debug1(isbfd
, "Matched string spans\n");
401 foreach_symbol_pair(presbfd
, isbfd
, match_symbol_spans
);
402 debug1(isbfd
, "Matched by name\n");
403 foreach_span_pair(presbfd
, isbfd
, match_spans_by_label
);
404 debug1(isbfd
, "Matched by label\n");
408 compare_matched_spans(isbfd
);
409 update_nonzero_offsets(isbfd
);
410 mark_new_spans(isbfd
);
414 foreach_symbol_pair(presbfd
, isbfd
, check_global_symbols
);
416 handle_deleted_spans(presbfd
, isbfd
);
417 handle_section_symbol_renames(presbfd
, isbfd
);
420 compare_exported_symbols(presbfd
, isbfd
, false);
421 compare_exported_symbols(isbfd
, presbfd
, true);
423 assert(bfd_close(prebfd
));
426 for (sect
= isbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
427 struct supersect
*ss
= fetch_supersect(isbfd
, sect
);
430 for (span
= ss
->spans
.data
;
431 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++) {
432 if (span
->new || span
->patch
)
439 print_label_changes(isbfd
);
441 for (sect
= isbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
442 struct supersect
*ss
= fetch_supersect(isbfd
, sect
);
444 for (span
= ss
->spans
.data
;
445 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++) {
447 debug0(isbfd
, "Patching span %s\n",
452 for (sect
= isbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
453 struct supersect
*ss
= fetch_supersect(isbfd
, sect
);
455 for (span
= ss
->spans
.data
;
456 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++) {
458 debug0(isbfd
, "New span %s\n", span
->label
);
462 const char **sectname
;
463 for (sectname
= delsects
.data
;
464 sectname
< delsects
.data
+ delsects
.size
; sectname
++)
465 debug0(isbfd
, "Deleted section: %s\n", *sectname
);
467 const struct export_desc
*ed
;
468 for (ed
= exports
.data
; ed
< exports
.data
+ exports
.size
; ed
++) {
469 const char **symname
;
470 for (symname
= ed
->names
.data
;
471 symname
< ed
->names
.data
+ ed
->names
.size
; symname
++)
472 debug0(isbfd
, "Export %s (%s): %s\n",
473 ed
->deletion
? "deletion" : "addition",
474 ed
->export_type
, *symname
);
477 filter_table_sections(isbfd
);
478 write_output
= false;
479 for (ed
= exports
.data
; ed
< exports
.data
+ exports
.size
; ed
++) {
480 const char **symname
;
481 for (symname
= ed
->names
.data
;
482 symname
< ed
->names
.data
+ ed
->names
.size
; symname
++)
483 write_ksplice_export(isbfd
, *symname
,
484 ed
->export_type
, ed
->deletion
);
488 rm_some_exports(isbfd
, ed
);
491 compute_span_shifts(isbfd
);
493 for (sect
= isbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
494 struct supersect
*ss
= fetch_supersect(isbfd
, sect
);
496 for (span
= ss
->spans
.data
;
497 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++) {
500 if (span
->patch
|| span
->new)
501 write_ksplice_section(span
);
503 write_ksplice_patch(isbfd
, span
);
508 remove_unkept_spans(isbfd
);
511 void do_keep_helper(struct superbfd
*isbfd
)
514 for (sect
= isbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
515 struct supersect
*ss
= fetch_supersect(isbfd
, sect
);
518 for (span
= ss
->spans
.data
;
519 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++) {
520 if (ss
->type
== SS_TYPE_TEXT
)
528 for (symp
= isbfd
->syms
.data
;
529 symp
< isbfd
->syms
.data
+ isbfd
->syms
.size
; symp
++) {
530 asymbol
*sym
= *symp
;
531 if (!bfd_is_const_section(sym
->section
) &&
532 (sym
->flags
& BSF_GLOBAL
) != 0) {
533 struct supersect
*sym_ss
=
534 fetch_supersect(isbfd
, sym
->section
);
535 struct span
*span
= find_span(sym_ss
, sym
->value
);
536 if (sym_ss
->type
!= SS_TYPE_IGNORED
)
543 keep_referenced_sections(isbfd
);
546 filter_table_sections(isbfd
);
547 compute_span_shifts(isbfd
);
549 for (sect
= isbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
550 struct supersect
*ss
= fetch_supersect(isbfd
, sect
);
551 asymbol
*sym
= canonical_symbol(isbfd
, sect
->symbol
);
554 if ((sym
->flags
& BSF_WEAK
) != 0)
556 if (bfd_get_section_size(sect
) == 0)
560 if (ss
->type
!= SS_TYPE_TEXT
&& !matchable_data_section(ss
))
564 for (span
= ss
->spans
.data
;
565 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++) {
567 write_ksplice_section(span
);
572 remove_unkept_spans(isbfd
);
573 mangle_section_name(isbfd
, "__markers");
576 void do_finalize(struct superbfd
*isbfd
)
578 load_ksplice_symbol_offsets(isbfd
);
580 for (sect
= isbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
581 struct supersect
*ss
= fetch_supersect(isbfd
, sect
);
582 if (ss
->type
== SS_TYPE_EXIT
) {
584 for (span
= ss
->spans
.data
;
585 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++)
590 write_date_relocs(isbfd
, "<{DATE...}>", KSPLICE_HOWTO_DATE
);
591 write_date_relocs(isbfd
, "<{TIME}>", KSPLICE_HOWTO_TIME
);
595 void do_rmsyms(struct superbfd
*isbfd
)
597 read_str_set(&rmsyms
);
601 struct export_vec
*get_export_syms(struct superbfd
*sbfd
)
604 struct export_vec
*exports
;
605 exports
= malloc(sizeof(*exports
));
606 assert(exports
!= NULL
);
609 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
610 if (!starts_with(sect
->name
, "__ksymtab") ||
611 ends_with(sect
->name
, "_strings"))
613 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
614 struct kernel_symbol
*sym
;
615 assert(ss
->contents
.size
* 2 == ss
->relocs
.size
*
616 sizeof(struct kernel_symbol
));
617 for (sym
= ss
->contents
.data
;
618 (void *)sym
< ss
->contents
.data
+ ss
->contents
.size
;
620 struct export
*exp
= vec_grow(exports
, 1);
622 read_string(ss
, (const char *const *)&sym
->name
);
629 struct export_desc
*new_export_desc(struct supersect
*ss
, bool deletion
)
631 struct export_desc
*ed
= vec_grow(&exports
, 1);
632 ed
->deletion
= deletion
;
633 vec_init(&ed
->names
);
634 ed
->export_type
= strdup(ss
->name
) + strlen("__ksymtab");
637 assert(asprintf(&crc_sect_name
, "__kcrctab%s", ed
->export_type
) >= 0);
639 bfd_get_section_by_name(ss
->parent
->abfd
, crc_sect_name
);
640 if (crc_sect
== NULL
)
643 ed
->crc_ss
= fetch_supersect(ss
->parent
, crc_sect
);
647 void compare_exported_symbols(struct superbfd
*oldsbfd
,
648 struct superbfd
*newsbfd
, bool deletion
)
650 struct export_vec
*new_exports
, *old_exports
;
651 new_exports
= get_export_syms(newsbfd
);
652 if (new_exports
== NULL
)
654 old_exports
= get_export_syms(oldsbfd
);
655 struct export
*old
, *new;
656 struct supersect
*last_ss
= NULL
;
657 struct export_desc
*ed
= NULL
;
658 for (new = new_exports
->data
; new < new_exports
->data
+
659 new_exports
->size
; new++) {
661 if (old_exports
!= NULL
) {
662 for (old
= old_exports
->data
; old
< old_exports
->data
+
663 old_exports
->size
; old
++) {
664 if (strcmp(new->name
, old
->name
) == 0 &&
665 strcmp(new->ss
->name
, old
->ss
->name
) == 0) {
672 if (last_ss
!= new->ss
) {
674 ed
= new_export_desc(new->ss
, deletion
);
676 *vec_grow(&ed
->names
, 1) = new->name
;
681 void match_spans(struct span
*old_span
, struct span
*new_span
)
683 struct superbfd
*sbfd
= new_span
->ss
->parent
;
684 if (old_span
->match
== new_span
&& new_span
->match
== old_span
)
686 if (old_span
->match
!= NULL
) {
687 err(sbfd
, "Matching conflict: old %s: %s != %s\n",
688 old_span
->label
, old_span
->match
->label
, new_span
->label
);
691 if (new_span
->match
!= NULL
) {
692 err(sbfd
, "Matching conflict: new %s: %s != %s\n",
693 new_span
->label
, new_span
->match
->label
, old_span
->label
);
696 old_span
->match
= new_span
;
697 new_span
->match
= old_span
;
698 debug1(sbfd
, "Matched old %s to new %s\n", old_span
->label
,
702 static void match_global_symbols(struct span
*old_span
, asymbol
*oldsym
,
703 struct span
*new_span
, asymbol
*newsym
)
705 if ((oldsym
->flags
& BSF_GLOBAL
) == 0 ||
706 (newsym
->flags
& BSF_GLOBAL
) == 0)
708 match_spans(old_span
, new_span
);
711 static void check_global_symbols(struct span
*old_span
, asymbol
*oldsym
,
712 struct span
*new_span
, asymbol
*newsym
)
714 if ((oldsym
->flags
& BSF_GLOBAL
) == 0 ||
715 (newsym
->flags
& BSF_GLOBAL
) == 0)
717 if (old_span
->ss
->type
== SS_TYPE_IGNORED
)
719 if (old_span
->match
!= new_span
|| new_span
->match
!= old_span
) {
720 err(new_span
->ss
->parent
, "Global symbol span mismatch: %s "
721 "%s/%s\n", oldsym
->name
, old_span
->ss
->name
,
727 static void foreach_symbol_pair(struct superbfd
*oldsbfd
, struct superbfd
*newsbfd
,
728 void (*fn
)(struct span
*old_span
,
730 struct span
*new_span
,
733 asymbol
**oldsymp
, **newsymp
;
734 for (oldsymp
= oldsbfd
->syms
.data
;
735 oldsymp
< oldsbfd
->syms
.data
+ oldsbfd
->syms
.size
; oldsymp
++) {
736 asymbol
*oldsym
= *oldsymp
;
737 if (bfd_is_const_section(oldsym
->section
))
739 for (newsymp
= newsbfd
->syms
.data
;
740 newsymp
< newsbfd
->syms
.data
+ newsbfd
->syms
.size
;
742 asymbol
*newsym
= *newsymp
;
743 if (bfd_is_const_section(newsym
->section
))
745 if (strcmp(oldsym
->name
, newsym
->name
) != 0)
748 struct supersect
*old_ss
=
749 fetch_supersect(oldsbfd
, oldsym
->section
);
750 struct supersect
*new_ss
=
751 fetch_supersect(newsbfd
, newsym
->section
);
752 if (old_ss
->type
!= new_ss
->type
||
753 old_ss
->type
== SS_TYPE_SPECIAL
||
754 old_ss
->type
== SS_TYPE_EXPORT
)
757 struct span
*old_span
=
758 find_span(old_ss
, oldsym
->value
);
759 struct span
*new_span
=
760 find_span(new_ss
, newsym
->value
);
761 if (old_span
== NULL
) {
762 err(oldsbfd
, "Could not find span for %s\n",
766 if (new_span
== NULL
) {
767 err(newsbfd
, "Could not find span for %s\n",
771 fn(old_span
, oldsym
, new_span
, newsym
);
776 static void match_symbol_spans(struct span
*old_span
, asymbol
*oldsym
,
777 struct span
*new_span
, asymbol
*newsym
)
779 if ((oldsym
->flags
& BSF_DEBUGGING
) != 0 ||
780 (newsym
->flags
& BSF_DEBUGGING
) != 0)
782 if (old_span
->ss
->type
== SS_TYPE_SPECIAL
||
783 old_span
->ss
->type
== SS_TYPE_EXPORT
)
785 if (static_local_symbol(old_span
->ss
->parent
, oldsym
) ||
786 static_local_symbol(new_span
->ss
->parent
, newsym
))
788 if (old_span
->match
== NULL
&& new_span
->match
== NULL
)
789 match_spans(old_span
, new_span
);
792 static void match_spans_by_label(struct span
*old_span
, struct span
*new_span
)
794 if (old_span
->ss
->type
== SS_TYPE_STRING
)
796 if (strcmp(old_span
->label
, new_span
->label
) == 0)
797 match_spans(old_span
, new_span
);
800 static void match_string_spans(struct span
*old_span
, struct span
*new_span
)
802 if (old_span
->ss
->type
!= SS_TYPE_STRING
||
803 strcmp(old_span
->ss
->name
, new_span
->ss
->name
) != 0)
805 if (strcmp((char *)old_span
->ss
->contents
.data
+ old_span
->start
,
806 (char *)new_span
->ss
->contents
.data
+ new_span
->start
) == 0)
807 match_spans(old_span
, new_span
);
810 static void foreach_span_pair(struct superbfd
*oldsbfd
,
811 struct superbfd
*newsbfd
,
812 void (*fn
)(struct span
*old_span
,
813 struct span
*new_span
))
815 asection
*oldsect
, *newsect
;
816 struct supersect
*oldss
, *newss
;
817 struct span
*old_span
, *new_span
;
818 for (newsect
= newsbfd
->abfd
->sections
; newsect
!= NULL
;
819 newsect
= newsect
->next
) {
820 newss
= fetch_supersect(newsbfd
, newsect
);
821 if (newss
->type
== SS_TYPE_SPECIAL
||
822 newss
->type
== SS_TYPE_EXPORT
)
824 for (oldsect
= oldsbfd
->abfd
->sections
; oldsect
!= NULL
;
825 oldsect
= oldsect
->next
) {
826 oldss
= fetch_supersect(oldsbfd
, oldsect
);
827 if (oldss
->type
!= newss
->type
)
829 for (new_span
= newss
->spans
.data
;
830 new_span
< newss
->spans
.data
+ newss
->spans
.size
;
832 for (old_span
= oldss
->spans
.data
;
833 old_span
< oldss
->spans
.data
+
834 oldss
->spans
.size
; old_span
++)
835 fn(old_span
, new_span
);
841 static void mark_new_spans(struct superbfd
*sbfd
)
844 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
845 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
846 if (ss
->type
== SS_TYPE_SPECIAL
|| ss
->type
== SS_TYPE_EXPORT
||
847 ss
->type
== SS_TYPE_IGNORED
)
850 for (span
= ss
->spans
.data
;
851 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++) {
852 if (span
->match
== NULL
)
858 static void handle_deleted_spans(struct superbfd
*oldsbfd
,
859 struct superbfd
*newsbfd
)
862 for (sect
= oldsbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
863 struct supersect
*ss
= fetch_supersect(oldsbfd
, sect
);
864 if (ss
->type
!= SS_TYPE_TEXT
)
867 for (span
= ss
->spans
.data
;
868 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++) {
869 if (span
->match
!= NULL
)
871 *vec_grow(&delsects
, 1) = span
->label
;
872 if (span
->symbol
== NULL
)
874 write_ksplice_deleted_patch(newsbfd
, span
->symbol
->name
,
881 static void handle_nonzero_offset_relocs(struct supersect
*ss
)
883 struct span
*address_span
, *target_span
;
885 for (relocp
= ss
->relocs
.data
;
886 relocp
< ss
->relocs
.data
+ ss
->relocs
.size
; relocp
++) {
887 arelent
*reloc
= *relocp
;
888 address_span
= find_span(ss
, reloc
->address
);
889 if (!address_span
->new && !address_span
->patch
)
892 asymbol
*sym
= *reloc
->sym_ptr_ptr
;
893 if (bfd_is_const_section(sym
->section
))
895 bfd_vma offset
= get_reloc_offset(ss
, reloc
, true);
896 target_span
= reloc_target_span(ss
, reloc
);
897 if (sym
->value
+ offset
== target_span
->start
)
900 if (target_span
->ss
->type
!= SS_TYPE_TEXT
)
902 if (target_span
->patch
)
905 target_span
->patch
= true;
907 debug1(ss
->parent
, "Changing %s because a relocation from sect "
908 "%s has a nonzero offset %lx+%lx into it\n",
909 target_span
->label
, ss
->name
, (unsigned long)sym
->value
,
910 (unsigned long)offset
);
914 static void update_nonzero_offsets(struct superbfd
*sbfd
)
917 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
918 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
919 if (ss
->type
== SS_TYPE_SPECIAL
|| ss
->type
== SS_TYPE_EXPORT
||
920 ss
->type
== SS_TYPE_IGNORED
)
922 handle_nonzero_offset_relocs(ss
);
926 static void compare_spans(struct span
*old_span
, struct span
*new_span
)
928 struct superbfd
*newsbfd
= new_span
->ss
->parent
;
930 if (nonrelocs_equal(old_span
, new_span
) &&
931 all_relocs_equal(old_span
, new_span
))
935 if (new_span
->size
!= old_span
->size
)
936 reason
= "differing sizes";
937 else if (!nonrelocs_equal(old_span
, new_span
))
938 reason
= "differing contents";
940 reason
= "differing relocations";
942 if (new_span
->ss
->type
== SS_TYPE_TEXT
) {
945 new_span
->patch
= true;
946 debug1(newsbfd
, "Changing %s due to %s\n", new_span
->label
,
949 debug1(newsbfd
, "Unmatching %s and %s due to %s\n",
950 old_span
->label
, new_span
->label
, reason
);
951 new_span
->match
= NULL
;
952 old_span
->match
= NULL
;
955 if (unchangeable_section(new_span
->ss
))
956 err(newsbfd
, "warning: ignoring change to nonpatchable "
957 "section %s\n", new_span
->ss
->name
);
960 static void compare_matched_spans(struct superbfd
*newsbfd
)
963 for (sect
= newsbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
964 struct supersect
*ss
= fetch_supersect(newsbfd
, sect
);
966 for (span
= ss
->spans
.data
;
967 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++) {
968 if (span
->match
== NULL
)
970 compare_spans(span
->match
, span
);
975 static void handle_section_symbol_renames(struct superbfd
*oldsbfd
,
976 struct superbfd
*newsbfd
)
980 for (sect
= newsbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
981 struct supersect
*ss
= fetch_supersect(newsbfd
, sect
);
982 for (span
= ss
->spans
.data
;
983 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++) {
984 if (span
->match
== NULL
)
986 if (strcmp(span
->label
, span
->match
->label
) == 0)
988 if (strcmp(span
->orig_label
, span
->label
) != 0 &&
989 strcmp(span
->label
, span
->match
->label
) != 0)
991 if (span
->symbol
!= NULL
)
992 label_map_set(newsbfd
, span
->label
,
994 span
->label
= span
->match
->label
;
999 static bool part_of_reloc(struct supersect
*ss
, unsigned long addr
)
1002 for (relocp
= ss
->relocs
.data
;
1003 relocp
< ss
->relocs
.data
+ ss
->relocs
.size
; relocp
++) {
1004 arelent
*reloc
= *relocp
;
1005 if (addr
>= reloc
->address
&&
1006 addr
< reloc
->address
+ reloc
->howto
->size
)
1012 static bool nonrelocs_equal(struct span
*old_span
, struct span
*new_span
)
1015 struct supersect
*old_ss
= old_span
->ss
, *new_ss
= new_span
->ss
;
1016 if (old_span
->size
!= new_span
->size
)
1018 const unsigned char *old
= old_ss
->contents
.data
+ old_span
->start
;
1019 const unsigned char *new = new_ss
->contents
.data
+ new_span
->start
;
1020 for (i
= 0; i
< old_span
->size
; i
++) {
1021 if (old
[i
] != new[i
] &&
1022 !(part_of_reloc(old_ss
, i
+ old_span
->start
) &&
1023 part_of_reloc(new_ss
, i
+ new_span
->start
)))
1029 bool relocs_equal(struct supersect
*old_src_ss
, struct supersect
*new_src_ss
,
1030 arelent
*old_reloc
, arelent
*new_reloc
)
1032 struct superbfd
*oldsbfd
= old_src_ss
->parent
;
1033 struct superbfd
*newsbfd
= new_src_ss
->parent
;
1034 struct span
*old_addr_span
= find_span(old_src_ss
, old_reloc
->address
);
1035 struct span
*new_addr_span
= find_span(new_src_ss
, new_reloc
->address
);
1037 if (old_reloc
->address
- old_addr_span
->start
!=
1038 new_reloc
->address
- new_addr_span
->start
) {
1039 debug1(newsbfd
, "Section %s/%s has reloc address mismatch at "
1040 "%lx\n", old_src_ss
->name
, new_src_ss
->name
,
1041 (unsigned long)old_reloc
->address
);
1045 if (old_reloc
->howto
!= new_reloc
->howto
) {
1046 debug1(newsbfd
, "Section %s/%s has howto type mismatch at "
1047 "%lx\n", old_src_ss
->name
, new_src_ss
->name
,
1048 (unsigned long)old_reloc
->address
);
1052 if (non_dst_mask(old_src_ss
, old_reloc
) !=
1053 non_dst_mask(new_src_ss
, new_reloc
)) {
1054 debug1(newsbfd
, "Section %s/%s has contents mismatch at %lx\n",
1055 old_src_ss
->name
, new_src_ss
->name
,
1056 (unsigned long)old_reloc
->address
);
1060 asymbol
*old_sym
= *old_reloc
->sym_ptr_ptr
;
1061 asymbol
*new_sym
= *new_reloc
->sym_ptr_ptr
;
1062 asection
*old_sect
= old_sym
->section
;
1063 asection
*new_sect
= new_sym
->section
;
1065 bfd_vma old_offset
= get_reloc_offset(old_src_ss
, old_reloc
, true);
1066 bfd_vma new_offset
= get_reloc_offset(new_src_ss
, new_reloc
, true);
1068 if (bfd_is_und_section(old_sect
) || bfd_is_und_section(new_sect
)) {
1069 if (!bfd_is_und_section(new_sect
) && old_offset
!= 0 &&
1070 fetch_supersect(newsbfd
, new_sect
)->type
== SS_TYPE_TEXT
)
1073 if (!bfd_is_und_section(new_sect
) && new_offset
!= 0 &&
1074 fetch_supersect(oldsbfd
, old_sect
)->type
== SS_TYPE_TEXT
)
1077 return strcmp(old_sym
->name
, new_sym
->name
) == 0 &&
1078 old_offset
== new_offset
;
1081 if (bfd_is_const_section(old_sect
) || bfd_is_const_section(new_sect
))
1084 struct supersect
*old_ss
= fetch_supersect(oldsbfd
, old_sect
);
1085 struct supersect
*new_ss
= fetch_supersect(newsbfd
, new_sect
);
1086 struct span
*old_span
= reloc_target_span(old_src_ss
, old_reloc
);
1087 struct span
*new_span
= reloc_target_span(new_src_ss
, new_reloc
);
1089 if (old_span
->match
!= new_span
|| new_span
->match
!= old_span
) {
1090 debug1(newsbfd
, "Nonmatching relocs from %s to %s/%s\n",
1091 new_src_ss
->name
, old_span
->label
, new_span
->label
);
1095 if (old_sym
->value
+ old_offset
- old_span
->start
!=
1096 new_sym
->value
+ new_offset
- new_span
->start
) {
1097 debug1(newsbfd
, "Offsets to %s/%s differ between %s "
1098 "and %s: %lx+%lx/%lx+%lx\n", old_ss
->name
,
1099 new_ss
->name
, old_src_ss
->name
, new_src_ss
->name
,
1100 (unsigned long)old_sym
->value
, (unsigned long)old_offset
,
1101 (unsigned long)new_sym
->value
,
1102 (unsigned long)new_offset
);
1106 if ((old_sym
->value
+ old_offset
- old_span
->start
!= 0 ||
1107 new_sym
->value
+ new_offset
- new_span
->start
!= 0) &&
1109 debug1(newsbfd
, "Relocation from %s to nonzero offsets "
1110 "%lx+%lx/%lx+%lx in changed section %s\n",
1111 new_src_ss
->name
, (unsigned long)old_sym
->value
,
1112 (unsigned long)old_offset
, (unsigned long)new_sym
->value
,
1113 (unsigned long)new_offset
, new_sym
->section
->name
);
1119 bool all_relocs_equal(struct span
*old_span
, struct span
*new_span
)
1121 struct supersect
*old_ss
= old_span
->ss
, *new_ss
= new_span
->ss
;
1122 arelent
**old_relocp
, **new_relocp
;
1124 for (old_relocp
= old_ss
->relocs
.data
;
1125 old_relocp
< old_ss
->relocs
.data
+ old_ss
->relocs
.size
;
1127 if (find_span(old_ss
, (*old_relocp
)->address
) == old_span
)
1131 for (new_relocp
= new_ss
->relocs
.data
;
1132 new_relocp
< new_ss
->relocs
.data
+ new_ss
->relocs
.size
;
1134 if (find_span(new_ss
, (*new_relocp
)->address
) == new_span
)
1138 for (; old_relocp
< old_ss
->relocs
.data
+ old_ss
->relocs
.size
&&
1139 find_span(old_ss
, (*old_relocp
)->address
) == old_span
&&
1140 new_relocp
< new_ss
->relocs
.data
+ new_ss
->relocs
.size
&&
1141 find_span(new_ss
, (*new_relocp
)->address
) == new_span
;
1142 old_relocp
++, new_relocp
++) {
1143 if (!relocs_equal(old_ss
, new_ss
, *old_relocp
, *new_relocp
))
1147 if ((old_relocp
< old_ss
->relocs
.data
+ old_ss
->relocs
.size
&&
1148 find_span(old_ss
, (*old_relocp
)->address
) == old_span
) ||
1149 (new_relocp
< new_ss
->relocs
.data
+ new_ss
->relocs
.size
&&
1150 find_span(new_ss
, (*new_relocp
)->address
) == new_span
)) {
1151 debug1(new_ss
->parent
, "Different reloc count between %s and "
1152 "%s\n", old_span
->label
, new_span
->label
);
1159 bfd_vma
non_dst_mask(struct supersect
*ss
, arelent
*reloc
)
1161 int bits
= bfd_get_reloc_size(reloc
->howto
) * 8;
1162 void *address
= ss
->contents
.data
+ reloc
->address
;
1163 bfd_vma x
= bfd_get(bits
, ss
->parent
->abfd
, address
);
1164 return x
& ~reloc
->howto
->dst_mask
;
1167 void rm_some_exports(struct superbfd
*sbfd
, const struct export_desc
*ed
)
1169 struct supersect
*ss
= ed
->sym_ss
;
1170 struct supersect
*crc_ss
= ed
->crc_ss
;
1172 assert(ss
->contents
.size
* sizeof(unsigned long) ==
1173 crc_ss
->contents
.size
* sizeof(struct kernel_symbol
));
1175 struct kernel_symbol
*ksym
;
1176 unsigned long *crc
= NULL
;
1178 crc
= crc_ss
->contents
.data
;
1179 struct span
*span
, *crc_span
;
1180 for (ksym
= ss
->contents
.data
;
1181 (void *)ksym
< ss
->contents
.data
+ ss
->contents
.size
;
1184 read_reloc(ss
, &ksym
->value
, sizeof(ksym
->value
), &sym
);
1185 span
= new_span(ss
, addr_offset(ss
, ksym
), sizeof(*ksym
));
1186 if (str_in_set(sym
->name
, &ed
->names
))
1189 if (crc_ss
!= NULL
) {
1190 crc_span
= new_span(crc_ss
, addr_offset(crc_ss
, crc
),
1193 keep_span(crc_span
);
1197 /* Replace name with a mangled name */
1198 write_string(ss
, (const char **)&ksym
->name
,
1199 "DISABLED_%s_%s", sym
->name
, kid
);
1204 void rm_relocs(struct superbfd
*isbfd
)
1207 for (p
= isbfd
->abfd
->sections
; p
!= NULL
; p
= p
->next
) {
1208 struct supersect
*ss
= fetch_supersect(isbfd
, p
);
1209 bool remove_relocs
= ss
->keep
;
1211 if (mode("keep") && ss
->type
== SS_TYPE_SPECIAL
)
1212 remove_relocs
= false;
1214 if (ss
->type
== SS_TYPE_KSPLICE
)
1215 remove_relocs
= false;
1216 if (mode("finalize") &&
1217 (starts_with(ss
->name
, ".ksplice_patches") ||
1218 starts_with(ss
->name
, ".ksplice_relocs")))
1219 remove_relocs
= true;
1226 void rm_some_relocs(struct supersect
*ss
)
1228 struct arelentp_vec orig_relocs
;
1229 vec_move(&orig_relocs
, &ss
->relocs
);
1232 for (relocp
= orig_relocs
.data
;
1233 relocp
< orig_relocs
.data
+ orig_relocs
.size
; relocp
++) {
1234 bool rm_reloc
= false;
1235 asymbol
*sym_ptr
= *(*relocp
)->sym_ptr_ptr
;
1237 if (mode("rmsyms") && str_in_set(sym_ptr
->name
, &rmsyms
) &&
1238 bfd_is_und_section(sym_ptr
->section
))
1244 if (mode("keep-primary") &&
1245 (bfd_is_const_section(sym_ptr
->section
) ||
1246 reloc_target_span(ss
, *relocp
)->new))
1249 if (mode("finalize") && bfd_is_und_section(sym_ptr
->section
))
1252 if (strcmp(sym_ptr
->name
, "mcount") == 0 &&
1253 bfd_is_und_section(sym_ptr
->section
))
1256 if (!find_span(ss
, (*relocp
)->address
)->keep
)
1260 write_ksplice_reloc(ss
, *relocp
);
1262 *vec_grow(&ss
->relocs
, 1) = *relocp
;
1266 struct supersect
*make_section(struct superbfd
*sbfd
, const char *fmt
, ...)
1271 assert(vasprintf(&name
, fmt
, ap
) >= 0);
1274 asection
*sect
= bfd_get_section_by_name(sbfd
->abfd
, name
);
1276 return fetch_supersect(sbfd
, sect
);
1278 return new_supersect(sbfd
, name
);
1281 arelent
*create_reloc(struct supersect
*ss
, const void *addr
, asymbol
**symp
,
1284 bfd_reloc_code_real_type code
;
1285 switch (bfd_arch_bits_per_address(ss
->parent
->abfd
)) {
1287 code
= BFD_RELOC_32
;
1290 code
= BFD_RELOC_64
;
1296 arelent
*reloc
= malloc(sizeof(*reloc
));
1297 reloc
->sym_ptr_ptr
= symp
;
1298 reloc
->address
= addr_offset(ss
, addr
);
1299 reloc
->howto
= bfd_reloc_type_lookup(ss
->parent
->abfd
, code
);
1300 reloc
->addend
= offset
;
1304 void write_reloc(struct supersect
*ss
, const void *addr
, asymbol
**symp
,
1307 *vec_grow(&ss
->new_relocs
, 1) = create_reloc(ss
, addr
, symp
, offset
);
1310 void write_string(struct supersect
*ss
, const char **addr
, const char *fmt
, ...)
1313 struct supersect
*str_ss
= make_section(ss
->parent
, ".ksplice_str");
1316 int len
= vasprintf(&str
, fmt
, ap
);
1320 unsigned long *str_offp
= ulong_hash_lookup(&ksplice_string_offset
, str
,
1322 if (str_offp
== NULL
) {
1323 char *buf
= sect_grow(str_ss
, len
+ 1, char);
1324 memcpy(buf
, str
, len
+ 1);
1325 str_offp
= ulong_hash_lookup(&ksplice_string_offset
, str
, TRUE
);
1326 *str_offp
= addr_offset(str_ss
, buf
);
1329 write_reloc(ss
, addr
, &str_ss
->symbol
, *str_offp
);
1332 void lookup_system_map(struct addr_vec
*addrs
, const char *name
, long offset
)
1334 struct addr_vec
*map_addrs
=
1335 addr_vec_hash_lookup(&system_map
, name
, FALSE
);
1336 if (map_addrs
== NULL
)
1339 unsigned long *addr
, *map_addr
;
1340 for (map_addr
= map_addrs
->data
;
1341 map_addr
< map_addrs
->data
+ map_addrs
->size
; map_addr
++) {
1342 for (addr
= addrs
->data
; addr
< addrs
->data
+ addrs
->size
;
1344 if (*addr
== *map_addr
+ offset
)
1347 if (addr
< addrs
->data
+ addrs
->size
)
1349 *vec_grow(addrs
, 1) = *map_addr
+ offset
;
1353 void compute_system_map_array(struct superbfd
*sbfd
, struct addr_vec
*addrs
,
1356 if (bfd_is_abs_section(sym
->section
)) {
1357 *vec_grow(addrs
, 1) = sym
->value
;
1358 } else if (bfd_is_und_section(sym
->section
)) {
1359 lookup_system_map(addrs
, sym
->name
, 0);
1360 } else if (!bfd_is_const_section(sym
->section
)) {
1362 for (gsymp
= sbfd
->syms
.data
;
1363 gsymp
< sbfd
->syms
.data
+ sbfd
->syms
.size
; gsymp
++) {
1364 asymbol
*gsym
= *gsymp
;
1365 if ((gsym
->flags
& BSF_DEBUGGING
) == 0 &&
1366 gsym
->section
== sym
->section
)
1367 lookup_system_map(addrs
, gsym
->name
,
1368 sym
->value
- gsym
->value
);
1373 void write_ksplice_system_map(struct superbfd
*sbfd
, asymbol
*sym
,
1376 bool *done
= bool_hash_lookup(&system_map_written
, label
, TRUE
);
1381 struct addr_vec addrs
;
1384 compute_system_map_array(sbfd
, &addrs
, sym
);
1385 if (addrs
.size
!= 0) {
1386 struct supersect
*smap_ss
=
1387 make_section(sbfd
, ".ksplice_system_map");
1388 struct ksplice_system_map
*smap
=
1389 sect_grow(smap_ss
, 1, struct ksplice_system_map
);
1390 write_string(smap_ss
, &smap
->label
, "%s", label
);
1392 struct supersect
*array_ss
= make_section(sbfd
,
1394 void *buf
= sect_grow(array_ss
, addrs
.size
,
1395 typeof(*addrs
.data
));
1396 memcpy(buf
, addrs
.data
, addrs
.size
* sizeof(*addrs
.data
));
1397 smap
->nr_candidates
= addrs
.size
;
1398 write_reloc(smap_ss
, &smap
->candidates
, &array_ss
->symbol
,
1399 addr_offset(array_ss
, buf
));
1404 void write_ksplice_symbol_backend(struct supersect
*ss
,
1405 struct ksplice_symbol
*const *addr
,
1406 asymbol
*sym
, const char *label
,
1409 struct supersect
*ksymbol_ss
= make_section(ss
->parent
,
1410 ".ksplice_symbols");
1411 struct ksplice_symbol
*ksymbol
;
1412 unsigned long *ksymbol_offp
;
1414 ksymbol_offp
= ulong_hash_lookup(&ksplice_symbol_offset
, label
, FALSE
);
1415 if (ksymbol_offp
!= NULL
) {
1416 write_reloc(ss
, addr
, &ksymbol_ss
->symbol
, *ksymbol_offp
);
1419 ksymbol
= sect_grow(ksymbol_ss
, 1, struct ksplice_symbol
);
1420 ksymbol_offp
= ulong_hash_lookup(&ksplice_symbol_offset
, label
, TRUE
);
1421 *ksymbol_offp
= addr_offset(ksymbol_ss
, ksymbol
);
1423 write_reloc(ss
, addr
, &ksymbol_ss
->symbol
, *ksymbol_offp
);
1424 write_string(ksymbol_ss
, &ksymbol
->label
, "%s", label
);
1426 write_string(ksymbol_ss
, &ksymbol
->name
, "%s", name
);
1427 write_ksplice_system_map(ksymbol_ss
->parent
, sym
, label
);
1431 void write_ksplice_symbol(struct supersect
*ss
,
1432 struct ksplice_symbol
*const *addr
,
1433 asymbol
*sym
, struct span
*span
,
1434 const char *addstr_sect
)
1436 const char *label
, *name
;
1438 if (span
!= NULL
&& span
->start
!= 0)
1439 label
= span
->label
;
1441 label
= label_lookup(ss
->parent
, sym
);
1443 assert(asprintf(&output
, "%s%s", label
, addstr_sect
) >= 0);
1445 asymbol
*gsym
= canonical_symbol(ss
->parent
, sym
);
1446 if (strcmp(addstr_sect
, "") != 0)
1448 else if (bfd_is_und_section(sym
->section
))
1450 else if (bfd_is_const_section(sym
->section
))
1452 else if (span
!= NULL
&& span
->symbol
== NULL
)
1454 else if (gsym
== NULL
|| (gsym
->flags
& BSF_SECTION_SYM
) != 0)
1459 write_ksplice_symbol_backend(ss
, addr
, sym
, output
, name
);
1462 void write_ksplice_reloc(struct supersect
*ss
, arelent
*orig_reloc
)
1464 asymbol
*sym_ptr
= *orig_reloc
->sym_ptr_ptr
;
1465 bfd_vma reloc_addend
= get_reloc_offset(ss
, orig_reloc
, false);
1466 bfd_vma target_addend
= get_reloc_offset(ss
, orig_reloc
, true);
1467 unsigned long *repladdr
= ss
->contents
.data
+ orig_reloc
->address
;
1469 if (mode("finalize") && starts_with(ss
->name
, ".ksplice_patches")) {
1473 if (mode("finalize") && starts_with(ss
->name
, ".ksplice_relocs")) {
1474 assert(starts_with(sym_ptr
->name
, KSPLICE_SYMBOL_STR
));
1476 fake_sym
.name
= sym_ptr
->name
+ strlen(KSPLICE_SYMBOL_STR
);
1477 fake_sym
.section
= bfd_und_section_ptr
;
1481 write_ksplice_symbol_backend
1482 (ss
, (struct ksplice_symbol
**)repladdr
, &fake_sym
,
1483 fake_sym
.name
, fake_sym
.name
);
1487 struct span
*span
= reloc_target_span(ss
, orig_reloc
);
1488 if (span
== ss
->spans
.data
&& span
->start
!= target_addend
)
1490 blot_section(ss
, orig_reloc
->address
, orig_reloc
->howto
);
1492 struct supersect
*kreloc_ss
;
1494 kreloc_ss
= make_section(ss
->parent
, ".ksplice_init_relocs");
1496 kreloc_ss
= make_section(ss
->parent
, ".ksplice_relocs%s",
1498 struct ksplice_reloc
*kreloc
= sect_grow(kreloc_ss
, 1,
1499 struct ksplice_reloc
);
1501 struct span
*address_span
= find_span(ss
, orig_reloc
->address
);
1502 write_reloc(kreloc_ss
, &kreloc
->blank_addr
,
1503 &ss
->symbol
, orig_reloc
->address
+ address_span
->shift
);
1504 if (bfd_is_und_section(sym_ptr
->section
) && mode("keep")) {
1506 assert(asprintf(&name
, KSPLICE_SYMBOL_STR
"%s", sym_ptr
->name
)
1508 asymbol
**symp
= make_undefined_symbolp(ss
->parent
, name
);
1509 write_reloc(kreloc_ss
, &kreloc
->symbol
, symp
, 0);
1511 write_ksplice_symbol(kreloc_ss
, &kreloc
->symbol
, sym_ptr
, span
,
1514 if (span
!= NULL
&& span
->start
!= 0) {
1515 reloc_addend
+= sym_ptr
->value
- span
->start
;
1516 target_addend
+= sym_ptr
->value
- span
->start
;
1518 kreloc
->insn_addend
= reloc_addend
- target_addend
;
1519 kreloc
->target_addend
= target_addend
;
1520 write_ksplice_reloc_howto(kreloc_ss
, &kreloc
->howto
, orig_reloc
->howto
);
1523 static void write_ksplice_reloc_howto(struct supersect
*ss
, const
1524 struct ksplice_reloc_howto
*const *addr
,
1525 reloc_howto_type
*howto
)
1527 struct supersect
*khowto_ss
= make_section(ss
->parent
,
1528 ".ksplice_reloc_howtos");
1529 struct ksplice_reloc_howto
*khowto
;
1530 unsigned long *khowto_offp
;
1532 khowto_offp
= ulong_hash_lookup(&ksplice_howto_offset
, howto
->name
,
1534 if (khowto_offp
!= NULL
) {
1535 write_reloc(ss
, addr
, &khowto_ss
->symbol
, *khowto_offp
);
1538 khowto
= sect_grow(khowto_ss
, 1, struct ksplice_reloc_howto
);
1539 khowto_offp
= ulong_hash_lookup(&ksplice_howto_offset
, howto
->name
,
1541 *khowto_offp
= addr_offset(khowto_ss
, khowto
);
1543 khowto
->type
= KSPLICE_HOWTO_RELOC
;
1544 khowto
->pcrel
= howto
->pc_relative
;
1545 khowto
->size
= bfd_get_reloc_size(howto
);
1546 khowto
->dst_mask
= howto
->dst_mask
;
1547 khowto
->rightshift
= howto
->rightshift
;
1548 khowto
->signed_addend
=
1549 (howto
->complain_on_overflow
== complain_overflow_signed
) ||
1550 (howto
->complain_on_overflow
== complain_overflow_bitfield
);
1551 write_reloc(ss
, addr
, &khowto_ss
->symbol
, *khowto_offp
);
1554 #define CANARY(x, canary) ((x & ~howto->dst_mask) | (canary & howto->dst_mask))
1556 void blot_section(struct supersect
*ss
, int offset
, reloc_howto_type
*howto
)
1558 int bits
= bfd_get_reloc_size(howto
) * 8;
1559 void *address
= ss
->contents
.data
+ offset
;
1560 bfd_vma x
= bfd_get(bits
, ss
->parent
->abfd
, address
);
1561 x
= (x
& ~howto
->dst_mask
) |
1562 ((bfd_vma
)KSPLICE_CANARY
& howto
->dst_mask
);
1563 bfd_put(bits
, ss
->parent
->abfd
, x
, address
);
1566 static void write_date_relocs(struct superbfd
*sbfd
, const char *str
,
1567 enum ksplice_reloc_howto_type type
)
1570 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
1571 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
1572 if (ss
->type
!= SS_TYPE_STRING
&& ss
->type
!= SS_TYPE_RODATA
)
1575 for (ptr
= ss
->contents
.data
;
1576 ptr
+ strlen(str
) < ss
->contents
.data
+ ss
->contents
.size
;
1578 if (strcmp((const char *)ptr
, str
) == 0)
1579 write_ksplice_date_reloc(ss
,
1580 addr_offset(ss
, ptr
),
1586 static void write_ksplice_date_reloc(struct supersect
*ss
, unsigned long offset
,
1588 enum ksplice_reloc_howto_type type
)
1590 struct supersect
*kreloc_ss
;
1591 kreloc_ss
= make_section(ss
->parent
, ".ksplice_relocs%s", ss
->name
);
1592 struct ksplice_reloc
*kreloc
= sect_grow(kreloc_ss
, 1,
1593 struct ksplice_reloc
);
1595 const char *filename
= ss
->parent
->abfd
->filename
;
1596 char *c
= strstr(filename
, ".KSPLICE");
1597 int flen
= (c
== NULL
? strlen(filename
) : c
- filename
);
1600 assert(asprintf(&label
, "%s<%.*s>", str
, flen
, filename
) >= 0);
1601 write_ksplice_symbol_backend(kreloc_ss
, &kreloc
->symbol
, NULL
,
1604 struct span
*span
= find_span(ss
, offset
);
1605 write_reloc(kreloc_ss
, &kreloc
->blank_addr
, &ss
->symbol
,
1606 offset
+ span
->shift
);
1607 write_ksplice_nonreloc_howto(kreloc_ss
, &kreloc
->howto
, type
,
1611 static void write_ksplice_nonreloc_howto(struct supersect
*ss
,
1612 const struct ksplice_reloc_howto
1614 enum ksplice_reloc_howto_type type
,
1617 struct supersect
*khowto_ss
=
1618 make_section(ss
->parent
, ".ksplice_reloc_howtos");
1619 struct ksplice_reloc_howto
*khowto
=
1620 sect_grow(khowto_ss
, 1, struct ksplice_reloc_howto
);
1622 khowto
->type
= type
;
1623 khowto
->size
= size
;
1625 khowto
->dst_mask
= 0;
1626 khowto
->rightshift
= 0;
1627 khowto
->signed_addend
= 0;
1628 write_reloc(ss
, addr
, &khowto_ss
->symbol
,
1629 addr_offset(khowto_ss
, khowto
));
1632 static void write_ksplice_section(struct span
*span
)
1634 struct supersect
*ss
= span
->ss
;
1635 struct supersect
*ksect_ss
=
1636 make_section(ss
->parent
, ".ksplice_sections%s", span
->ss
->name
);
1637 struct ksplice_section
*ksect
= sect_grow(ksect_ss
, 1,
1638 struct ksplice_section
);
1639 asymbol
*sym
= span
->symbol
== NULL
? ss
->symbol
: span
->symbol
;
1641 write_ksplice_symbol(ksect_ss
, &ksect
->symbol
, sym
, span
,
1642 mode("keep-primary") ? "(post)" : "");
1643 ksect
->size
= span
->size
;
1646 if (ss
->type
== SS_TYPE_RODATA
|| ss
->type
== SS_TYPE_STRING
)
1647 ksect
->flags
|= KSPLICE_SECTION_RODATA
;
1648 if (ss
->type
== SS_TYPE_DATA
)
1649 ksect
->flags
|= KSPLICE_SECTION_DATA
;
1650 if (ss
->type
== SS_TYPE_TEXT
)
1651 ksect
->flags
|= KSPLICE_SECTION_TEXT
;
1652 assert(ksect
->flags
!= 0);
1654 if (ss
->type
== SS_TYPE_STRING
)
1655 ksect
->flags
|= KSPLICE_SECTION_STRING
;
1657 write_reloc(ksect_ss
, &ksect
->address
, &ss
->symbol
,
1658 span
->start
+ span
->shift
);
1661 void write_ksplice_patch(struct superbfd
*sbfd
, struct span
*span
)
1663 struct supersect
*kpatch_ss
=
1664 make_section(sbfd
, ".ksplice_patches%s", span
->ss
->name
);
1665 struct ksplice_patch
*kpatch
= sect_grow(kpatch_ss
, 1,
1666 struct ksplice_patch
);
1668 write_ksplice_symbol_backend(kpatch_ss
, &kpatch
->symbol
, NULL
,
1670 write_reloc(kpatch_ss
, &kpatch
->repladdr
, &span
->ss
->symbol
,
1671 span
->start
+ span
->shift
);
1674 asymbol
**make_undefined_symbolp(struct superbfd
*sbfd
, const char *name
)
1677 for (symp
= sbfd
->syms
.data
; symp
< sbfd
->syms
.data
+ sbfd
->syms
.size
;
1679 asymbol
*sym
= *symp
;
1680 if (strcmp(name
, sym
->name
) == 0 &&
1681 bfd_is_und_section(sym
->section
))
1685 for (sympp
= sbfd
->new_syms
.data
;
1686 sympp
< sbfd
->new_syms
.data
+ sbfd
->new_syms
.size
; sympp
++) {
1687 asymbol
**symp
= *sympp
;
1688 asymbol
*sym
= *symp
;
1689 if (strcmp(name
, sym
->name
) == 0 &&
1690 bfd_is_und_section(sym
->section
))
1694 symp
= malloc(sizeof(*symp
));
1695 *symp
= bfd_make_empty_symbol(sbfd
->abfd
);
1696 asymbol
*sym
= *symp
;
1698 sym
->section
= bfd_und_section_ptr
;
1701 *vec_grow(&sbfd
->new_syms
, 1) = symp
;
1705 void write_ksplice_deleted_patch(struct superbfd
*sbfd
, const char *name
,
1706 const char *label
, const char *sectname
)
1708 struct supersect
*kpatch_ss
=
1709 make_section(sbfd
, ".ksplice_patches%s", sectname
);
1710 struct ksplice_patch
*kpatch
= sect_grow(kpatch_ss
, 1,
1711 struct ksplice_patch
);
1713 write_ksplice_symbol_backend(kpatch_ss
, &kpatch
->symbol
, NULL
,
1716 asymbol
**symp
= make_undefined_symbolp(sbfd
, strdup(name
));
1717 write_reloc(kpatch_ss
, &kpatch
->repladdr
, symp
, 0);
1720 void write_ksplice_export(struct superbfd
*sbfd
, const char *symname
,
1721 const char *export_type
, bool del
)
1723 struct supersect
*export_ss
= make_section(sbfd
, ".ksplice_exports");
1724 struct ksplice_export
*exp
= sect_grow(export_ss
, 1,
1725 struct ksplice_export
);
1728 write_string(export_ss
, &exp
->name
, "%s", symname
);
1729 write_string(export_ss
, &exp
->new_name
, "DISABLED_%s_%s",
1732 write_string(export_ss
, &exp
->new_name
, "%s", symname
);
1733 write_string(export_ss
, &exp
->name
, "DISABLED_%s_%s", symname
,
1738 void filter_table_sections(struct superbfd
*isbfd
)
1740 struct supersect
*tables_ss
=
1741 fetch_supersect(offsets_sbfd
,
1742 bfd_get_section_by_name(offsets_sbfd
->abfd
,
1743 ".ksplice_table_sections"));
1744 const struct table_section
*ts
;
1745 for (ts
= tables_ss
->contents
.data
;
1746 (void *)ts
< tables_ss
->contents
.data
+ tables_ss
->contents
.size
;
1748 struct table_section s
= *ts
;
1749 s
.sect
= read_string(tables_ss
, &ts
->sect
);
1750 s
.other_sect
= read_string(tables_ss
, &ts
->other_sect
);
1752 filter_table_section(isbfd
, &s
);
1756 void filter_table_section(struct superbfd
*sbfd
, const struct table_section
*s
)
1758 asection
*isection
= bfd_get_section_by_name(sbfd
->abfd
, s
->sect
);
1759 if (isection
== NULL
)
1761 struct supersect
*ss
= fetch_supersect(sbfd
, isection
);
1764 for (entry
= ss
->contents
.data
;
1765 entry
< ss
->contents
.data
+ ss
->contents
.size
;
1766 entry
+= s
->entry_size
) {
1768 struct span
*span
= find_span(ss
, addr_offset(ss
, entry
));
1769 assert(span
!= NULL
);
1771 read_reloc(ss
, entry
+ s
->addr_offset
, sizeof(void *), &sym
);
1772 struct supersect
*sym_ss
= fetch_supersect(sbfd
, sym
->section
);
1776 if (s
->other_sect
!= NULL
) {
1778 find_reloc(ss
, entry
+ s
->other_offset
);
1779 assert(reloc
!= NULL
);
1780 struct span
*sym_span
= reloc_target_span(ss
, reloc
);
1782 keep_span(sym_span
);
1787 for (relocp
= ss
->relocs
.data
;
1788 relocp
< ss
->relocs
.data
+ ss
->relocs
.size
; relocp
++) {
1789 struct span
*addr_span
= find_span(ss
, (*relocp
)->address
);
1790 struct span
*target_span
= reloc_target_span(ss
, *relocp
);
1791 if (addr_span
->keep
&& mode("keep-primary"))
1792 keep_span(target_span
);
1796 void keep_referenced_sections(struct superbfd
*sbfd
)
1799 struct supersect
*ss
, *sym_ss
;
1800 struct span
*address_span
, *target_span
;
1801 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
1802 ss
= fetch_supersect(sbfd
, sect
);
1804 if (ss
->type
== SS_TYPE_SPECIAL
|| ss
->type
== SS_TYPE_EXPORT
)
1806 for (relocp
= ss
->relocs
.data
;
1807 relocp
< ss
->relocs
.data
+ ss
->relocs
.size
; relocp
++) {
1808 asymbol
*sym
= *(*relocp
)->sym_ptr_ptr
;
1809 address_span
= find_span(ss
, (*relocp
)->address
);
1810 if (!address_span
->keep
)
1812 target_span
= reloc_target_span(ss
, *relocp
);
1813 if (target_span
== NULL
|| target_span
->keep
)
1815 sym_ss
= fetch_supersect(sbfd
, sym
->section
);
1816 if (sym_ss
->type
== SS_TYPE_IGNORED
)
1818 keep_span(target_span
);
1824 void copy_symbols(struct asymbolp_vec
*osyms
, struct asymbolpp_vec
*isyms
)
1827 for (sympp
= isyms
->data
; sympp
< isyms
->data
+ isyms
->size
; sympp
++)
1828 *vec_grow(osyms
, 1) = **sympp
;
1831 /* Modified function from GNU Binutils objcopy.c */
1832 bfd_boolean
copy_object(bfd
*ibfd
, bfd
*obfd
)
1834 assert(bfd_set_format(obfd
, bfd_get_format(ibfd
)));
1836 bfd_vma start
= bfd_get_start_address(ibfd
);
1838 flagword flags
= bfd_get_file_flags(ibfd
);
1839 flags
&= bfd_applicable_file_flags(obfd
);
1841 assert(bfd_set_start_address(obfd
, start
)
1842 && bfd_set_file_flags(obfd
, flags
));
1844 enum bfd_architecture iarch
= bfd_get_arch(ibfd
);
1845 unsigned int imach
= bfd_get_mach(ibfd
);
1846 assert(bfd_set_arch_mach(obfd
, iarch
, imach
));
1847 assert(bfd_set_format(obfd
, bfd_get_format(ibfd
)));
1849 /* BFD mandates that all output sections be created and sizes set before
1850 any output is done. Thus, we traverse all sections multiple times. */
1851 bfd_map_over_sections(ibfd
, setup_section
, obfd
);
1853 struct supersect
*new_supersects
= fetch_superbfd(ibfd
)->new_supersects
;
1854 struct supersect
*ss
;
1855 for (ss
= new_supersects
; ss
!= NULL
; ss
= ss
->next
)
1856 setup_new_section(obfd
, ss
);
1858 /* Mark symbols used in output relocations so that they
1859 are kept, even if they are local labels or static symbols.
1861 Note we iterate over the input sections examining their
1862 relocations since the relocations for the output sections
1863 haven't been set yet. mark_symbols_used_in_relocations will
1864 ignore input sections which have no corresponding output
1867 bfd_map_over_sections(ibfd
, mark_symbols_used_in_relocations
, NULL
);
1868 for (ss
= new_supersects
; ss
!= NULL
; ss
= ss
->next
)
1869 ss_mark_symbols_used_in_relocations(ss
);
1870 struct asymbolp_vec osyms
;
1872 filter_symbols(ibfd
, obfd
, &osyms
, &fetch_superbfd(ibfd
)->syms
);
1873 copy_symbols(&osyms
, &fetch_superbfd(ibfd
)->new_syms
);
1875 bfd_set_symtab(obfd
, osyms
.data
, osyms
.size
);
1877 /* This has to happen after the symbol table has been set. */
1878 bfd_map_over_sections(obfd
, write_section
, NULL
);
1880 /* Allow the BFD backend to copy any private data it understands
1881 from the input BFD to the output BFD. This is done last to
1882 permit the routine to look at the filtered symbol table, which is
1883 important for the ECOFF code at least. */
1884 assert(bfd_copy_private_bfd_data(ibfd
, obfd
));
1889 /* Modified function from GNU Binutils objcopy.c */
1890 void setup_section(bfd
*ibfd
, asection
*isection
, void *obfdarg
)
1892 struct superbfd
*isbfd
= fetch_superbfd(ibfd
);
1893 struct supersect
*ss
= fetch_supersect(isbfd
, isection
);
1894 bfd
*obfd
= obfdarg
;
1900 asection
*osection
= bfd_make_section_anyway(obfd
, ss
->name
);
1901 assert(osection
!= NULL
);
1903 osection
->userdata
= ss
;
1904 bfd_set_section_flags(obfd
, osection
, ss
->flags
);
1905 ss
->symbol
= osection
->symbol
;
1906 assert(bfd_set_section_size(obfd
, osection
, ss
->contents
.size
));
1908 vma
= bfd_section_vma(ibfd
, isection
);
1909 assert(bfd_set_section_vma(obfd
, osection
, vma
));
1911 osection
->lma
= isection
->lma
;
1912 assert(bfd_set_section_alignment(obfd
, osection
, ss
->alignment
));
1913 osection
->entsize
= isection
->entsize
;
1914 osection
->output_section
= osection
;
1915 osection
->output_offset
= 0;
1916 isection
->output_section
= osection
;
1917 isection
->output_offset
= 0;
1921 void setup_new_section(bfd
*obfd
, struct supersect
*ss
)
1923 asection
*osection
= bfd_make_section_anyway(obfd
, ss
->name
);
1924 assert(osection
!= NULL
);
1925 bfd_set_section_flags(obfd
, osection
, ss
->flags
);
1927 osection
->userdata
= ss
;
1928 ss
->symbol
= osection
->symbol
;
1929 assert(bfd_set_section_size(obfd
, osection
, ss
->contents
.size
));
1930 assert(bfd_set_section_vma(obfd
, osection
, 0));
1933 assert(bfd_set_section_alignment(obfd
, osection
, ss
->alignment
));
1934 osection
->entsize
= 0;
1935 osection
->output_section
= osection
;
1936 osection
->output_offset
= 0;
1939 static int compare_reloc_addresses(const void *aptr
, const void *bptr
)
1941 const arelent
*const *a
= aptr
, *const *b
= bptr
;
1942 return (*a
)->address
- (*b
)->address
;
1945 static void delete_obsolete_relocs(struct supersect
*ss
)
1947 if (ss
->new_relocs
.size
== 0)
1950 qsort(ss
->relocs
.data
, ss
->relocs
.size
, sizeof(*ss
->relocs
.data
),
1951 compare_reloc_addresses
);
1952 qsort(ss
->new_relocs
.data
, ss
->new_relocs
.size
,
1953 sizeof(*ss
->new_relocs
.data
), compare_reloc_addresses
);
1955 struct arelentp_vec orig_relocs
;
1956 vec_move(&orig_relocs
, &ss
->relocs
);
1958 arelent
**relocp
, **new_relocp
= ss
->new_relocs
.data
;
1959 for (relocp
= orig_relocs
.data
;
1960 relocp
< orig_relocs
.data
+ orig_relocs
.size
; relocp
++) {
1961 while (new_relocp
< ss
->new_relocs
.data
+ ss
->new_relocs
.size
&&
1962 (*new_relocp
)->address
< (*relocp
)->address
)
1964 arelent
*reloc
= *relocp
, *new_reloc
= *new_relocp
;
1965 if (new_relocp
== ss
->new_relocs
.data
+ ss
->new_relocs
.size
||
1966 reloc
->address
!= new_reloc
->address
)
1967 *vec_grow(&ss
->relocs
, 1) = reloc
;
1971 void write_section(bfd
*obfd
, asection
*osection
, void *arg
)
1973 struct supersect
*ss
= osection
->userdata
;
1975 if ((ss
->flags
& SEC_GROUP
) != 0 || ss
->contents
.size
== 0)
1978 delete_obsolete_relocs(ss
);
1981 char *error_message
;
1982 for (relocp
= ss
->new_relocs
.data
;
1983 relocp
< ss
->new_relocs
.data
+ ss
->new_relocs
.size
; relocp
++) {
1985 if (bfd_get_arch(obfd
) == bfd_arch_arm
)
1986 val
= osection
->use_rela_p
? 0 : (*relocp
)->addend
;
1989 bfd_put(bfd_get_reloc_size((*relocp
)->howto
) * 8, obfd
, val
,
1990 ss
->contents
.data
+ (*relocp
)->address
);
1991 if (bfd_install_relocation(obfd
, *relocp
, ss
->contents
.data
,
1992 0, osection
, &error_message
) !=
1994 err(ss
->parent
, "ksplice: error installing reloc: %s",
1999 memcpy(vec_grow(&ss
->relocs
, ss
->new_relocs
.size
), ss
->new_relocs
.data
,
2000 ss
->new_relocs
.size
* sizeof(*ss
->new_relocs
.data
));
2002 bfd_set_reloc(obfd
, osection
,
2003 ss
->relocs
.size
== 0 ? NULL
: ss
->relocs
.data
,
2006 if (ss
->flags
& SEC_HAS_CONTENTS
)
2007 assert(bfd_set_section_contents
2008 (obfd
, osection
, ss
->contents
.data
, 0,
2009 ss
->contents
.size
));
2012 /* Modified function from GNU Binutils objcopy.c
2014 * Mark all the symbols which will be used in output relocations with
2015 * the BSF_KEEP flag so that those symbols will not be stripped.
2017 * Ignore relocations which will not appear in the output file.
2019 void mark_symbols_used_in_relocations(bfd
*abfd
, asection
*isection
,
2022 struct superbfd
*sbfd
= fetch_superbfd(abfd
);
2023 if (isection
->output_section
== NULL
)
2026 struct supersect
*ss
= fetch_supersect(sbfd
, isection
);
2027 ss_mark_symbols_used_in_relocations(ss
);
2030 void ss_mark_symbols_used_in_relocations(struct supersect
*ss
)
2032 /* Examine each symbol used in a relocation. If it's not one of the
2033 special bfd section symbols, then mark it with BSF_KEEP. */
2035 for (relocp
= ss
->relocs
.data
;
2036 relocp
< ss
->relocs
.data
+ ss
->relocs
.size
; relocp
++) {
2037 asymbol
*sym
= *(*relocp
)->sym_ptr_ptr
;
2038 if (!(bfd_is_const_section(sym
->section
) &&
2039 sym
== sym
->section
->symbol
))
2040 sym
->flags
|= BSF_KEEP
;
2042 for (relocp
= ss
->new_relocs
.data
;
2043 relocp
< ss
->new_relocs
.data
+ ss
->new_relocs
.size
; relocp
++) {
2044 asymbol
*sym
= *(*relocp
)->sym_ptr_ptr
;
2045 if (!(bfd_is_const_section(sym
->section
) &&
2046 sym
== sym
->section
->symbol
))
2047 sym
->flags
|= BSF_KEEP
;
2051 static bool deleted_table_section_symbol(bfd
*abfd
, asymbol
*sym
)
2053 struct superbfd
*sbfd
= fetch_superbfd(abfd
);
2054 if (bfd_is_const_section(sym
->section
))
2056 struct supersect
*ss
= fetch_supersect(sbfd
, sym
->section
);
2059 for (symp
= ss
->syms
.data
; symp
< ss
->syms
.data
+ ss
->syms
.size
; symp
++) {
2063 return symp
>= ss
->syms
.data
+ ss
->syms
.size
&&
2064 (sym
->flags
& BSF_SECTION_SYM
) == 0;
2067 void filter_symbols(bfd
*ibfd
, bfd
*obfd
, struct asymbolp_vec
*osyms
,
2068 struct asymbolp_vec
*isyms
)
2071 struct superbfd
*sbfd
= fetch_superbfd(ibfd
);
2072 for (symp
= isyms
->data
; symp
< isyms
->data
+ isyms
->size
; symp
++) {
2073 asymbol
*sym
= *symp
;
2074 struct supersect
*sym_ss
= NULL
;
2075 struct span
*sym_span
= NULL
;
2076 if (!bfd_is_const_section(sym
->section
)) {
2077 sym_ss
= fetch_supersect(sbfd
, sym
->section
);
2078 sym_span
= find_span(sym_ss
, sym
->value
);
2081 if (mode("keep") && (sym
->flags
& BSF_GLOBAL
) != 0 &&
2082 !(mode("keep-primary") && sym_span
!= NULL
&&
2084 sym
->flags
= (sym
->flags
& ~BSF_GLOBAL
) | BSF_LOCAL
;
2086 if (mode("finalize") && (sym
->flags
& BSF_GLOBAL
) != 0)
2087 sym
->flags
= (sym
->flags
& ~BSF_GLOBAL
) | BSF_LOCAL
;
2089 bool keep
= bfd_is_const_section(sym
->section
) ||
2090 (sym_ss
->keep
&& (sym
->flags
& BSF_SECTION_SYM
) != 0) ||
2091 (sym_span
!= NULL
&& sym_span
->keep
);
2092 if (bfd_is_und_section(sym
->section
) &&
2093 (sym
->flags
& BSF_KEEP
) == 0)
2095 if (deleted_table_section_symbol(ibfd
, sym
))
2099 if (sym_ss
!= NULL
&& !sym_ss
->keep
) {
2100 err(sbfd
, "Kept symbol %s in unkept section "
2101 "%s\n", sym
->name
, sym
->section
->name
);
2104 *vec_grow(osyms
, 1) = sym
;
2109 void read_str_set(struct str_vec
*strs
)
2113 assert(getline(&buf
, &n
, stdin
) >= 0);
2117 char *str
= strtok_r(buf
, " \n", &saveptr
);
2121 *vec_grow(strs
, 1) = str
;
2125 bool str_in_set(const char *str
, const struct str_vec
*strs
)
2128 for (strp
= strs
->data
; strp
< strs
->data
+ strs
->size
; strp
++) {
2129 if (strcmp(str
, *strp
) == 0)
2135 bool is_table_section(const char *name
, bool consider_other
)
2137 struct supersect
*tables_ss
=
2138 fetch_supersect(offsets_sbfd
,
2139 bfd_get_section_by_name(offsets_sbfd
->abfd
,
2140 ".ksplice_table_sections"));
2141 const struct table_section
*ts
;
2142 for (ts
= tables_ss
->contents
.data
;
2143 (void *)ts
< tables_ss
->contents
.data
+ tables_ss
->contents
.size
;
2145 if (strcmp(name
, read_string(tables_ss
, &ts
->sect
)) == 0)
2147 const char *osect_name
= read_string(tables_ss
,
2149 if (consider_other
&& osect_name
!= NULL
&&
2150 strcmp(name
, osect_name
) == 0)
2156 const struct table_section
*get_table_section(const char *name
)
2158 struct supersect
*tables_ss
=
2159 fetch_supersect(offsets_sbfd
,
2160 bfd_get_section_by_name(offsets_sbfd
->abfd
,
2161 ".ksplice_table_sections"));
2162 const struct table_section
*ts
;
2163 for (ts
= tables_ss
->contents
.data
;
2164 (void *)ts
< tables_ss
->contents
.data
+ tables_ss
->contents
.size
;
2166 if (strcmp(name
, read_string(tables_ss
, &ts
->sect
)) == 0)
2172 enum supersect_type
supersect_type(struct supersect
*ss
)
2174 if (mode("finalize") &&
2175 strcmp(finalize_target
, "vmlinux") == 0 &&
2176 (starts_with(ss
->name
, ".ksplice_relocs.exit") ||
2177 starts_with(ss
->name
, ".ksplice_sections.exit") ||
2178 starts_with(ss
->name
, ".ksplice_patches.exit")))
2179 return SS_TYPE_EXIT
;
2180 if (starts_with(ss
->name
, ".ksplice"))
2181 return SS_TYPE_KSPLICE
;
2183 if (starts_with(ss
->name
, ".init"))
2184 return SS_TYPE_IGNORED
;
2185 if (starts_with(ss
->name
, ".security_initcall.init"))
2186 return SS_TYPE_IGNORED
;
2187 if (starts_with(ss
->name
, ".con_initcall.init"))
2188 return SS_TYPE_IGNORED
;
2189 if (starts_with(ss
->name
, ".x86cpuvendor.init"))
2190 return SS_TYPE_IGNORED
;
2191 if (starts_with(ss
->name
, ".early_param.init"))
2192 return SS_TYPE_IGNORED
;
2193 if (starts_with(ss
->name
, ".taglist.init"))
2194 return SS_TYPE_IGNORED
;
2195 if (starts_with(ss
->name
, ".arch.info.init"))
2196 return SS_TYPE_IGNORED
;
2197 if (starts_with(ss
->name
, ".proc.info.init"))
2198 return SS_TYPE_IGNORED
;
2199 /* .pci_fixup_* sections really should be treated as global rodata
2200 referenced only from quirks.c */
2201 if (starts_with(ss
->name
, ".pci_fixup_"))
2202 return SS_TYPE_IGNORED
;
2203 /* .builtin_fw sections are similar to .pci_fixup */
2204 if (starts_with(ss
->name
, ".builtin_fw"))
2205 return SS_TYPE_IGNORED
;
2206 /* same for .tracedata */
2207 if (starts_with(ss
->name
, ".tracedata"))
2208 return SS_TYPE_IGNORED
;
2209 if (starts_with(ss
->name
, ".debug"))
2210 return SS_TYPE_IGNORED
;
2211 /* .eh_frame should probably be discarded, not ignored */
2212 if (starts_with(ss
->name
, ".eh_frame"))
2213 return SS_TYPE_IGNORED
;
2214 if (config
->ignore_devinit
&& starts_with(ss
->name
, ".devinit"))
2215 return SS_TYPE_IGNORED
;
2216 if (config
->ignore_meminit
&& starts_with(ss
->name
, ".meminit"))
2217 return SS_TYPE_IGNORED
;
2218 if (config
->ignore_cpuinit
&& starts_with(ss
->name
, ".cpuinit"))
2219 return SS_TYPE_IGNORED
;
2220 if (config
->ignore_devinit
&& starts_with(ss
->name
, ".devexit"))
2221 return SS_TYPE_IGNORED
;
2222 if (config
->ignore_meminit
&& starts_with(ss
->name
, ".memexit"))
2223 return SS_TYPE_IGNORED
;
2224 if (config
->ignore_cpuinit
&& starts_with(ss
->name
, ".cpuexit"))
2225 return SS_TYPE_IGNORED
;
2226 if (starts_with(ss
->name
, ".vgetcpu_mode") ||
2227 starts_with(ss
->name
, ".jiffies") ||
2228 starts_with(ss
->name
, ".wall_jiffies") ||
2229 starts_with(ss
->name
, ".vxtime") ||
2230 starts_with(ss
->name
, ".sys_tz") ||
2231 starts_with(ss
->name
, ".sysctl_vsyscall") ||
2232 starts_with(ss
->name
, ".xtime") ||
2233 starts_with(ss
->name
, ".xtime_lock") ||
2234 starts_with(ss
->name
, ".vsyscall"))
2235 return SS_TYPE_IGNORED
;
2236 if (starts_with(ss
->name
, ".vdso"))
2237 return SS_TYPE_IGNORED
;
2239 if (starts_with(ss
->name
, ".exit.text"))
2240 return SS_TYPE_TEXT
;
2241 if (starts_with(ss
->name
, ".exit.data"))
2242 return SS_TYPE_DATA
;
2244 if (starts_with(ss
->name
, ".text") ||
2245 starts_with(ss
->name
, ".kernel.text") ||
2246 starts_with(ss
->name
, ".devinit.text") ||
2247 starts_with(ss
->name
, ".meminit.text") ||
2248 starts_with(ss
->name
, ".cpuinit.text") ||
2249 starts_with(ss
->name
, ".devexit.text") ||
2250 starts_with(ss
->name
, ".memexit.text") ||
2251 starts_with(ss
->name
, ".cpuexit.text") ||
2252 starts_with(ss
->name
, ".ref.text") ||
2253 starts_with(ss
->name
, ".spinlock.text") ||
2254 starts_with(ss
->name
, ".kprobes.text") ||
2255 starts_with(ss
->name
, ".sched.text"))
2256 return SS_TYPE_TEXT
;
2259 if (sscanf(ss
->name
, ".rodata.str%*u.%*u%n", &n
) >= 0 &&
2260 n
== strlen(ss
->name
))
2261 return SS_TYPE_STRING
;
2263 if (starts_with(ss
->name
, ".rodata") ||
2264 starts_with(ss
->name
, ".kernel.rodata") ||
2265 starts_with(ss
->name
, ".devinit.rodata") ||
2266 starts_with(ss
->name
, ".meminit.rodata") ||
2267 starts_with(ss
->name
, ".cpuinit.rodata") ||
2268 starts_with(ss
->name
, ".devexit.rodata") ||
2269 starts_with(ss
->name
, ".memexit.rodata") ||
2270 starts_with(ss
->name
, ".cpuexit.rodata") ||
2271 starts_with(ss
->name
, ".ref.rodata") ||
2272 starts_with(ss
->name
, "__markers_strings"))
2273 return SS_TYPE_RODATA
;
2275 if (starts_with(ss
->name
, ".bss"))
2276 return SS_TYPE_DATA
;
2278 /* Ignore .data.percpu sections */
2279 if (starts_with(ss
->name
, ".data.percpu") ||
2280 starts_with(ss
->name
, ".kernel.data.percpu"))
2281 return SS_TYPE_IGNORED
;
2282 if (starts_with(ss
->name
, ".data") ||
2283 starts_with(ss
->name
, ".kernel.data") ||
2284 starts_with(ss
->name
, ".devinit.data") ||
2285 starts_with(ss
->name
, ".cpuinit.data") ||
2286 starts_with(ss
->name
, ".meminit.data") ||
2287 starts_with(ss
->name
, ".devexit.data") ||
2288 starts_with(ss
->name
, ".memexit.data") ||
2289 starts_with(ss
->name
, ".cpuexit.data") ||
2290 starts_with(ss
->name
, ".ref.data") ||
2291 starts_with(ss
->name
, "__markers"))
2292 return SS_TYPE_DATA
;
2294 /* We replace all the ksymtab strings, so delete them */
2295 if (strcmp(ss
->name
, "__ksymtab_strings") == 0)
2296 return SS_TYPE_IGNORED
;
2297 if (starts_with(ss
->name
, "__ksymtab"))
2298 return SS_TYPE_EXPORT
;
2299 if (starts_with(ss
->name
, "__kcrctab"))
2300 return SS_TYPE_EXPORT
;
2302 if (is_table_section(ss
->name
, true))
2303 return SS_TYPE_SPECIAL
;
2305 if (starts_with(ss
->name
, ".ARM."))
2306 return SS_TYPE_SPECIAL
;
2308 if (starts_with(ss
->name
, ".note"))
2309 return SS_TYPE_IGNORED
;
2310 if (starts_with(ss
->name
, ".comment"))
2311 return SS_TYPE_IGNORED
;
2312 if (starts_with(ss
->name
, "__param"))
2313 return SS_TYPE_IGNORED
;
2314 if (starts_with(ss
->name
, ".exitcall.exit"))
2315 return SS_TYPE_IGNORED
;
2316 if (starts_with(ss
->name
, ".modinfo"))
2317 return SS_TYPE_IGNORED
;
2319 return SS_TYPE_UNKNOWN
;
2322 void initialize_supersect_types(struct superbfd
*sbfd
)
2325 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
2326 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
2327 ss
->type
= supersect_type(ss
);
2328 if (ss
->type
== SS_TYPE_UNKNOWN
) {
2329 err(sbfd
, "Unknown section type: %s\n", ss
->name
);
2335 static void init_label_map(struct superbfd
*sbfd
)
2337 struct label_map
*map
;
2339 vec_init(&sbfd
->maps
);
2343 struct symbol_hash csyms
;
2344 symbol_hash_init(&csyms
);
2347 for (symp
= sbfd
->syms
.data
;
2348 symp
< sbfd
->syms
.data
+ sbfd
->syms
.size
; symp
++) {
2349 asymbol
*csym
= canonical_symbol(sbfd
, *symp
);
2353 assert(asprintf(&key
, "%p", csym
) >= 0);
2354 asymbol
**csymp
= symbol_hash_lookup(&csyms
, key
, TRUE
);
2360 map
= vec_grow(&sbfd
->maps
, 1);
2363 map
->label
= symbol_label(sbfd
, csym
);
2366 struct label_mapp_hash label_maps
;
2367 label_mapp_hash_init(&label_maps
);
2368 for (map
= sbfd
->maps
.data
;
2369 map
< sbfd
->maps
.data
+ sbfd
->maps
.size
; map
++) {
2370 struct label_map
**mapp
=
2371 label_mapp_hash_lookup(&label_maps
, map
->label
, TRUE
);
2372 if (*mapp
== NULL
) {
2377 struct label_map
*first_map
= *mapp
;
2379 if (first_map
->count
== 0) {
2380 assert(asprintf(&buf
, "%s~%d", map
->label
, 0) >= 0);
2381 first_map
->label
= buf
;
2384 assert(asprintf(&buf
, "%s~%d", map
->label
, first_map
->count
)
2389 label_mapp_hash_init(&sbfd
->maps_hash
);
2390 for (map
= sbfd
->maps
.data
;
2391 map
< sbfd
->maps
.data
+ sbfd
->maps
.size
; map
++) {
2393 assert(asprintf(&key
, "%p", map
->csym
) >= 0);
2394 struct label_map
**mapp
=
2395 label_mapp_hash_lookup(&sbfd
->maps_hash
, key
, TRUE
);
2398 map
->orig_label
= map
->label
;
2402 static const char *label_lookup(struct superbfd
*sbfd
, asymbol
*sym
)
2404 asymbol
*csym
= canonical_symbol(sbfd
, sym
);
2406 assert(asprintf(&key
, "%p", csym
) >= 0);
2407 struct label_map
**mapp
=
2408 label_mapp_hash_lookup(&sbfd
->maps_hash
, key
, FALSE
);
2412 return (*mapp
)->label
;
2415 static void print_label_changes(struct superbfd
*sbfd
)
2419 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
2420 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
2421 for (span
= ss
->spans
.data
;
2422 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++) {
2423 if (strcmp(span
->label
, span
->orig_label
) != 0)
2424 debug1(sbfd
, "Label change: %s -> %s\n",
2425 span
->label
, span
->orig_label
);
2430 static void label_map_set(struct superbfd
*sbfd
, const char *oldlabel
,
2433 struct label_map
*map
;
2434 for (map
= sbfd
->maps
.data
;
2435 map
< sbfd
->maps
.data
+ sbfd
->maps
.size
; map
++) {
2436 if (strcmp(map
->orig_label
, oldlabel
) == 0) {
2437 if (strcmp(map
->orig_label
, map
->label
) != 0 &&
2438 strcmp(map
->label
, label
) != 0)
2447 static void init_callers(struct superbfd
*sbfd
)
2449 string_hash_init(&sbfd
->callers
);
2451 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
2452 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
2454 for (relocp
= ss
->relocs
.data
;
2455 relocp
< ss
->relocs
.data
+ ss
->relocs
.size
; relocp
++) {
2456 asymbol
*sym
= *(*relocp
)->sym_ptr_ptr
;
2458 sym
->value
+ get_reloc_offset(ss
, *relocp
, true);
2460 assert(asprintf(&key
, "%s+%lx", sym
->section
->name
,
2462 const char **ret
= string_hash_lookup(&sbfd
->callers
,
2468 *ret
= "*multiple_callers*";
2473 static const char *find_caller(struct supersect
*ss
, asymbol
*sym
)
2476 assert(asprintf(&key
, "%s+%lx", sym
->section
->name
,
2477 (unsigned long)sym
->value
) >= 0);
2478 const char **ret
= string_hash_lookup(&ss
->parent
->callers
, key
, FALSE
);
2482 return "*no_caller*";
2486 static void init_csyms(struct superbfd
*sbfd
)
2488 asymbolpp_hash_init(&sbfd
->csyms
);
2491 for (symp
= sbfd
->syms
.data
; symp
< sbfd
->syms
.data
+ sbfd
->syms
.size
;
2493 asymbol
*sym
= *symp
;
2494 if ((sym
->flags
& BSF_DEBUGGING
) != 0)
2497 assert(asprintf(&key
, "%s+%lx", sym
->section
->name
,
2498 (unsigned long)sym
->value
) >= 0);
2499 asymbol
***csympp
= asymbolpp_hash_lookup(&sbfd
->csyms
, key
,
2502 if (*csympp
== NULL
) {
2506 asymbol
*csym
= **csympp
;
2507 if ((csym
->flags
& BSF_GLOBAL
) != 0)
2509 if ((sym
->flags
& BSF_GLOBAL
) != 0)
2514 static asymbol
**symbolp_scan(struct supersect
*ss
, bfd_vma value
)
2517 assert(asprintf(&key
, "%s+%lx", ss
->name
, (unsigned long)value
) >= 0);
2519 asymbolpp_hash_lookup(&ss
->parent
->csyms
, key
, FALSE
);
2524 /* For section symbols of sections containing no symbols, return the
2525 section symbol that relocations are generated against */
2531 static asymbol
**canonical_symbolp(struct superbfd
*sbfd
, asymbol
*sym
)
2533 if (bfd_is_const_section(sym
->section
)) {
2535 for (csymp
= sbfd
->syms
.data
;
2536 csymp
< sbfd
->syms
.data
+ sbfd
->syms
.size
; csymp
++) {
2542 return symbolp_scan(fetch_supersect(sbfd
, sym
->section
), sym
->value
);
2545 static asymbol
*canonical_symbol(struct superbfd
*sbfd
, asymbol
*sym
)
2547 if (bfd_is_const_section(sym
->section
))
2549 asymbol
**symp
= canonical_symbolp(sbfd
, sym
);
2550 return symp
!= NULL
? *symp
: NULL
;
2553 static char *static_local_symbol(struct superbfd
*sbfd
, asymbol
*sym
)
2555 struct supersect
*ss
= fetch_supersect(sbfd
, sym
->section
);
2556 if ((sym
->flags
& BSF_LOCAL
) == 0 || (sym
->flags
& BSF_OBJECT
) == 0)
2558 char *dot
= strrchr(sym
->name
, '.');
2559 if (dot
== NULL
|| dot
[1 + strspn(dot
+ 1, "0123546789")] != '\0')
2561 char *basename
= strndup(sym
->name
, dot
- sym
->name
);
2563 if (strcmp(basename
, "__func__") == 0 ||
2564 strcmp(basename
, "__PRETTY_FUNCTION__") == 0)
2565 assert(asprintf(&mangled_name
, "%s<%s>", basename
,
2566 (char *)ss
->contents
.data
+ sym
->value
) >= 0);
2568 assert(asprintf(&mangled_name
, "%s<%s>", basename
,
2569 find_caller(ss
, sym
)) >= 0);
2570 return mangled_name
;
2573 static char *symbol_label(struct superbfd
*sbfd
, asymbol
*sym
)
2575 const char *filename
= sbfd
->abfd
->filename
;
2576 char *c
= strstr(filename
, ".KSPLICE");
2577 int flen
= (c
== NULL
? strlen(filename
) : c
- filename
);
2580 if (bfd_is_und_section(sym
->section
) || (sym
->flags
& BSF_GLOBAL
) != 0) {
2581 label
= strdup(sym
->name
);
2582 } else if (bfd_is_const_section(sym
->section
)) {
2583 assert(asprintf(&label
, "%s<%.*s>",
2584 sym
->name
, flen
, filename
) >= 0);
2586 asymbol
*gsym
= canonical_symbol(sbfd
, sym
);
2589 assert(asprintf(&label
, "%s+%lx<%.*s>",
2591 (unsigned long)sym
->value
,
2592 flen
, filename
) >= 0);
2593 else if ((gsym
->flags
& BSF_GLOBAL
) != 0)
2594 label
= strdup(gsym
->name
);
2595 else if (static_local_symbol(sbfd
, gsym
))
2596 assert(asprintf(&label
, "%s+%lx<%.*s>",
2597 static_local_symbol(sbfd
, gsym
),
2598 (unsigned long)sym
->value
,
2599 flen
, filename
) >= 0);
2601 assert(asprintf(&label
, "%s<%.*s>",
2602 gsym
->name
, flen
, filename
) >= 0);
2608 static void keep_span(struct span
*span
)
2611 span
->ss
->keep
= true;
2614 static struct span
*new_span(struct supersect
*ss
, bfd_vma start
, bfd_vma size
)
2616 struct span
*span
= vec_grow(&ss
->spans
, 1);
2618 span
->start
= start
;
2622 span
->patch
= false;
2625 asymbol
**symp
= symbolp_scan(ss
, span
->start
);
2627 span
->symbol
= *symp
;
2628 span
->label
= label_lookup(ss
->parent
, span
->symbol
);
2630 span
->symbol
= NULL
;
2631 const char *label
= label_lookup(ss
->parent
, ss
->symbol
);
2632 if (span
->start
!= 0) {
2634 assert(asprintf(&buf
, "%s<span:%lx>", label
,
2635 (unsigned long)span
->start
) >= 0);
2638 span
->label
= label
;
2641 span
->orig_label
= span
->label
;
2645 static void initialize_string_spans(struct supersect
*ss
)
2648 for (str
= ss
->contents
.data
;
2649 (void *)str
< ss
->contents
.data
+ ss
->contents
.size
;) {
2650 bfd_vma start
= (unsigned long)str
-
2651 (unsigned long)ss
->contents
.data
;
2652 bfd_vma size
= strlen(str
) + 1;
2653 while ((start
+ size
) % (1 << ss
->alignment
) != 0 &&
2654 start
+ size
< ss
->contents
.size
) {
2655 if (str
[size
] != '\0')
2659 new_span(ss
, start
, size
);
2664 static int compare_ulongs(const void *va
, const void *vb
)
2666 const unsigned long *a
= va
, *b
= vb
;
2670 static void initialize_table_spans(struct superbfd
*sbfd
,
2671 struct table_section
*s
)
2673 asection
*isection
= bfd_get_section_by_name(sbfd
->abfd
, s
->sect
);
2674 if (isection
== NULL
)
2676 asection
*other_sect
= NULL
;
2677 if (s
->other_sect
!= NULL
)
2678 other_sect
= bfd_get_section_by_name(sbfd
->abfd
, s
->other_sect
);
2680 struct supersect
*ss
= fetch_supersect(sbfd
, isection
);
2681 if (ss
->alignment
< ffs(s
->entry_align
) - 1)
2682 ss
->alignment
= ffs(s
->entry_align
) - 1;
2684 struct supersect
*other_ss
= NULL
;
2685 if (other_sect
!= NULL
)
2686 other_ss
= fetch_supersect(sbfd
, other_sect
);
2688 struct ulong_vec offsets
;
2692 for (entry
= ss
->contents
.data
;
2693 entry
< ss
->contents
.data
+ ss
->contents
.size
;
2694 entry
+= s
->entry_size
) {
2695 new_span(ss
, addr_offset(ss
, entry
), s
->entry_size
);
2697 if (other_sect
!= NULL
) {
2699 bfd_vma offset
= read_reloc(ss
, entry
+ s
->other_offset
,
2700 sizeof(void *), &sym
);
2701 if (sym
->section
== other_sect
) {
2702 assert(offset
>= 0 &&
2703 offset
< other_ss
->contents
.size
);
2704 *vec_grow(&offsets
, 1) = offset
;
2709 if (other_sect
== NULL
)
2712 qsort(offsets
.data
, offsets
.size
, sizeof(*offsets
.data
),
2714 *vec_grow(&offsets
, 1) = other_ss
->contents
.size
;
2717 for (off
= offsets
.data
; off
< offsets
.data
+ offsets
.size
- 1; off
++) {
2718 if (*off
!= *(off
+ 1))
2719 new_span(other_ss
, *off
, *(off
+ 1) - *off
);
2723 static void initialize_table_section_spans(struct superbfd
*sbfd
)
2725 struct supersect
*tables_ss
=
2726 fetch_supersect(offsets_sbfd
,
2727 bfd_get_section_by_name(offsets_sbfd
->abfd
,
2728 ".ksplice_table_sections"));
2729 const struct table_section
*ts
;
2730 struct table_section s
;
2731 for (ts
= tables_ss
->contents
.data
;
2732 (void *)ts
< tables_ss
->contents
.data
+ tables_ss
->contents
.size
;
2735 s
.sect
= read_string(tables_ss
, &ts
->sect
);
2736 s
.other_sect
= read_string(tables_ss
, &ts
->other_sect
);
2737 initialize_table_spans(sbfd
, &s
);
2741 static void initialize_spans(struct superbfd
*sbfd
)
2744 initialize_table_section_spans(sbfd
);
2747 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
2748 if (is_table_section(sect
->name
, true) && mode("keep"))
2751 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
2752 if (ss
->type
== SS_TYPE_STRING
)
2753 initialize_string_spans(ss
);
2754 else if (!mode("keep") || ss
->type
!= SS_TYPE_EXPORT
)
2755 new_span(ss
, 0, ss
->contents
.size
);
2759 struct span
*reloc_target_span(struct supersect
*ss
, arelent
*reloc
)
2761 asymbol
*sym_ptr
= *reloc
->sym_ptr_ptr
;
2762 if (bfd_is_const_section(sym_ptr
->section
))
2765 bfd_vma addend
= get_reloc_offset(ss
, reloc
, true) + sym_ptr
->value
;
2766 struct supersect
*sym_ss
=
2767 fetch_supersect(ss
->parent
, sym_ptr
->section
);
2768 struct span
*span
, *target_span
= sym_ss
->spans
.data
;
2769 for (span
= sym_ss
->spans
.data
;
2770 span
< sym_ss
->spans
.data
+ sym_ss
->spans
.size
; span
++) {
2771 if (addend
>= span
->start
&& addend
< span
->start
+ span
->size
)
2777 struct span
*find_span(struct supersect
*ss
, bfd_size_type address
)
2780 for (span
= ss
->spans
.data
; span
< ss
->spans
.data
+ ss
->spans
.size
;
2782 if (address
>= span
->start
&&
2783 address
< span
->start
+ span
->size
)
2786 /* Deal with empty BSS sections */
2787 if (ss
->contents
.size
== 0 && ss
->spans
.size
> 0)
2788 return ss
->spans
.data
;
2792 void compute_span_shifts(struct superbfd
*sbfd
)
2796 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
2797 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
2800 bfd_size_type offset
= 0;
2801 for (span
= ss
->spans
.data
;
2802 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++) {
2805 span
->shift
= offset
- span
->start
;
2806 offset
+= span
->size
;
2811 void remove_unkept_spans(struct superbfd
*sbfd
)
2815 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
2816 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
2817 delete_obsolete_relocs(ss
);
2818 struct arelentp_vec orig_relocs
;
2819 vec_move(&orig_relocs
, &ss
->relocs
);
2820 arelent
**relocp
, *reloc
;
2821 for (relocp
= orig_relocs
.data
;
2822 relocp
< orig_relocs
.data
+ orig_relocs
.size
; relocp
++) {
2824 asymbol
*sym
= *reloc
->sym_ptr_ptr
;
2825 span
= reloc_target_span(ss
, reloc
);
2826 if ((span
!= NULL
&& span
->keep
&& span
->shift
== 0) ||
2827 bfd_is_const_section(sym
->section
)) {
2828 *vec_grow(&ss
->relocs
, 1) = reloc
;
2831 struct supersect
*sym_ss
=
2832 fetch_supersect(sbfd
, sym
->section
);
2833 if (span
!= NULL
&& (sym
->flags
& BSF_SECTION_SYM
) == 0
2834 && find_span(sym_ss
, sym
->value
) != span
) {
2835 err(sbfd
, "Spans for symbol %s and relocation "
2836 "target do not match in sect %s\n",
2837 sym
->name
, sym_ss
->name
);
2840 if (span
!= NULL
&& span
->keep
) {
2841 arelent
*new_reloc
= malloc(sizeof(*new_reloc
));
2842 *new_reloc
= *reloc
;
2844 get_reloc_offset(ss
, reloc
, false);
2845 new_reloc
->addend
+= span
->shift
;
2846 *vec_grow(&ss
->new_relocs
, 1) = new_reloc
;
2851 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
2852 struct supersect
*ss
= fetch_supersect(sbfd
, sect
), orig_ss
;
2855 supersect_move(&orig_ss
, ss
);
2856 vec_init(&ss
->spans
);
2857 for (span
= orig_ss
.spans
.data
;
2858 span
< orig_ss
.spans
.data
+ orig_ss
.spans
.size
; span
++) {
2861 struct span
*new_span
= vec_grow(&ss
->spans
, 1);
2863 new_span
->start
= span
->start
+ span
->shift
;
2864 new_span
->shift
= 0;
2865 sect_copy(ss
, sect_do_grow(ss
, 1, span
->size
, 1),
2866 &orig_ss
, orig_ss
.contents
.data
+ span
->start
,
2872 static void init_objmanip_superbfd(struct superbfd
*sbfd
)
2874 init_label_map(sbfd
);
2875 initialize_supersect_types(sbfd
);
2876 initialize_spans(sbfd
);
2879 void mangle_section_name(struct superbfd
*sbfd
, const char *name
)
2881 asection
*sect
= bfd_get_section_by_name(sbfd
->abfd
, name
);
2884 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
2886 assert(asprintf(&buf
, ".ksplice_pre.%s", ss
->name
) >= 0);