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 symbol_init(sym) *(sym) = (asymbol *)NULL
63 DEFINE_HASH_TYPE(asymbol
*, symbol_hash
, symbol_hash_init
, symbol_hash_free
,
64 symbol_hash_lookup
, symbol_init
);
70 DECLARE_VEC_TYPE(struct export
, export_vec
);
72 DECLARE_VEC_TYPE(const char *, str_vec
);
75 const char *export_type
;
78 struct supersect
*sym_ss
;
79 struct supersect
*crc_ss
;
81 DECLARE_VEC_TYPE(struct export_desc
, export_desc_vec
);
83 #define bool_init(b) *(b) = false
84 DEFINE_HASH_TYPE(bool, bool_hash
, bool_hash_init
, bool_hash_free
,
85 bool_hash_lookup
, bool_init
);
87 #define ulong_init(x) *(x) = 0
88 DEFINE_HASH_TYPE(unsigned long, ulong_hash
, ulong_hash_init
,
89 ulong_hash_free
, ulong_hash_lookup
, ulong_init
);
91 void do_keep_primary(struct superbfd
*isbfd
, const char *pre
);
92 void do_keep_helper(struct superbfd
*isbfd
);
93 void do_finalize(struct superbfd
*isbfd
);
94 void do_rmsyms(struct superbfd
*isbfd
);
96 struct export_vec
*get_export_syms(struct superbfd
*sbfd
);
97 void compare_exported_symbols(struct superbfd
*oldsbfd
,
98 struct superbfd
*newsbfd
, bool deletion
);
99 struct export_desc
*new_export_desc(struct supersect
*ss
, bool deletion
);
100 bool relocs_equal(struct supersect
*old_src_ss
, struct supersect
*new_src_ss
,
101 arelent
*old_reloc
, arelent
*new_reloc
);
102 bool all_relocs_equal(struct supersect
*old_ss
, struct supersect
*new_ss
);
103 static bool part_of_reloc(struct supersect
*ss
, unsigned long addr
);
104 static bool nonrelocs_equal(struct supersect
*old_ss
, struct supersect
*new_ss
);
105 static void handle_section_symbol_renames(struct superbfd
*oldsbfd
,
106 struct superbfd
*newsbfd
);
108 enum supersect_type
supersect_type(struct supersect
*ss
);
109 void initialize_supersect_types(struct superbfd
*sbfd
);
110 static void initialize_spans(struct superbfd
*sbfd
);
111 static void initialize_string_spans(struct supersect
*ss
);
112 struct span
*reloc_target_span(struct supersect
*ss
, arelent
*reloc
);
113 struct span
*reloc_address_span(struct supersect
*ss
, arelent
*reloc
);
114 void remove_unkept_spans(struct superbfd
*sbfd
);
115 void compute_span_shifts(struct superbfd
*sbfd
);
116 static struct span
*new_span(struct supersect
*ss
, bfd_vma start
, bfd_vma size
);
117 bool is_table_section(const char *name
, bool consider_other
);
119 void rm_relocs(struct superbfd
*isbfd
);
120 void rm_some_relocs(struct supersect
*ss
);
121 void write_ksplice_reloc(struct supersect
*ss
, arelent
*orig_reloc
);
122 void blot_section(struct supersect
*ss
, int offset
, reloc_howto_type
*howto
);
123 static void write_ksplice_section(struct span
*span
);
124 void write_ksplice_patch(struct superbfd
*sbfd
, const char *sectname
);
125 void write_ksplice_deleted_patch(struct superbfd
*sbfd
, const char *name
,
127 void filter_table_sections(struct superbfd
*isbfd
);
128 void filter_table_section(struct superbfd
*sbfd
, const struct table_section
*s
);
129 void keep_referenced_sections(struct superbfd
*sbfd
);
130 bfd_boolean
copy_object(bfd
*ibfd
, bfd
*obfd
);
131 void setup_section(bfd
*ibfd
, asection
*isection
, void *obfdarg
);
132 static void setup_new_section(bfd
*obfd
, struct supersect
*ss
);
133 static void write_section(bfd
*obfd
, asection
*osection
, void *arg
);
134 static void delete_obsolete_relocs(struct supersect
*ss
);
135 void mark_symbols_used_in_relocations(bfd
*abfd
, asection
*isection
,
137 static void ss_mark_symbols_used_in_relocations(struct supersect
*ss
);
138 void filter_symbols(bfd
*ibfd
, bfd
*obfd
, struct asymbolp_vec
*osyms
,
139 struct asymbolp_vec
*isyms
);
140 static bool deleted_table_section_symbol(bfd
*abfd
, asymbol
*sym
);
141 void read_str_set(struct str_vec
*strs
);
142 bool str_in_set(const char *str
, const struct str_vec
*strs
);
143 struct supersect
*make_section(struct superbfd
*sbfd
, const char *name
);
144 void __attribute__((format(printf
, 3, 4)))
145 write_string(struct supersect
*ss
, const char **addr
, const char *fmt
, ...);
146 void rm_some_exports(struct superbfd
*isbfd
, const struct export_desc
*ed
);
147 void write_ksplice_export(struct superbfd
*sbfd
, const char *symname
,
148 const char *export_type
, bool del
);
149 void write_reloc(struct supersect
*ss
, const void *addr
, asymbol
**symp
,
151 arelent
*create_reloc(struct supersect
*ss
, const void *addr
, asymbol
**symp
,
153 static void match_global_symbol_sections(struct superbfd
*oldsbfd
,
154 struct superbfd
*newsbfd
);
155 static void match_sections_by_name(struct superbfd
*oldsbfd
,
156 struct superbfd
*newsbfd
);
157 static void match_sections_by_label(struct superbfd
*oldsbfd
,
158 struct superbfd
*newsbfd
);
159 static void mark_new_sections(struct superbfd
*sbfd
);
160 static void handle_deleted_sections(struct superbfd
*oldsbfd
,
161 struct superbfd
*newsbfd
);
162 static void compare_matched_sections(struct superbfd
*sbfd
);
163 static void update_nonzero_offsets(struct superbfd
*sbfd
);
164 static void handle_nonzero_offset_relocs(struct supersect
*ss
);
166 static const char *label_lookup(struct superbfd
*sbfd
, asymbol
*sym
);
167 static void print_label_map(struct superbfd
*sbfd
);
168 static void label_map_set(struct superbfd
*sbfd
, const char *oldlabel
,
170 static void init_label_map(struct superbfd
*sbfd
);
171 static asymbol
**symbolp_scan(struct supersect
*ss
, bfd_vma value
);
172 static void init_csyms(struct superbfd
*sbfd
);
173 static void init_callers(struct superbfd
*sbfd
);
174 static asymbol
*canonical_symbol(struct superbfd
*sbfd
, asymbol
*sym
);
175 static asymbol
**canonical_symbolp(struct superbfd
*sbfd
, asymbol
*sym
);
176 static char *static_local_symbol(struct superbfd
*sbfd
, asymbol
*sym
);
177 static char *symbol_label(struct superbfd
*sbfd
, asymbol
*sym
);
180 #define debug_(sbfd, level, fmt, ...) \
182 if (verbose >= (level)) \
183 printf("%s: " fmt, (sbfd)->abfd->filename, \
186 #define debug0(sbfd, fmt, ...) debug_(sbfd, 0, fmt, ## __VA_ARGS__)
187 #define debug1(sbfd, fmt, ...) debug_(sbfd, 1, fmt, ## __VA_ARGS__)
188 #define err(sbfd, fmt, ...) \
190 fprintf(stderr, "%s: " fmt, (sbfd)->abfd->filename, \
194 struct str_vec delsects
, rmsyms
;
195 struct export_desc_vec exports
;
198 struct ksplice_config
*config
;
200 const char *modestr
, *kid
;
202 struct superbfd
*offsets_sbfd
= NULL
;
204 #define mode(str) starts_with(modestr, str)
206 DECLARE_VEC_TYPE(unsigned long, addr_vec
);
207 DEFINE_HASH_TYPE(struct addr_vec
, addr_vec_hash
,
208 addr_vec_hash_init
, addr_vec_hash_free
, addr_vec_hash_lookup
,
210 struct addr_vec_hash system_map
;
212 struct bool_hash system_map_written
;
213 struct ulong_hash ksplice_symbol_offset
;
214 struct ulong_hash ksplice_string_offset
;
216 void load_system_map()
218 const char *config_dir
= getenv("KSPLICE_CONFIG_DIR");
221 assert(asprintf(&file
, "%s/System.map", config_dir
) >= 0);
222 FILE *fp
= fopen(file
, "r");
224 addr_vec_hash_init(&system_map
);
228 while (fscanf(fp
, "%lx %c %as\n", &addr
, &type
, &sym
) == 3)
229 *vec_grow(addr_vec_hash_lookup(&system_map
, sym
, TRUE
),
236 char *kmodsrc
= getenv("KSPLICE_KMODSRC"), *offsets_file
;
237 assert(kmodsrc
!= NULL
);
238 assert(asprintf(&offsets_file
, "%s/offsets.o", kmodsrc
) >= 0);
239 bfd
*offsets_bfd
= bfd_openr(offsets_file
, NULL
);
240 assert(offsets_bfd
!= NULL
);
242 assert(bfd_check_format_matches(offsets_bfd
, bfd_object
, &matching
));
243 offsets_sbfd
= fetch_superbfd(offsets_bfd
);
245 asection
*config_sect
= bfd_get_section_by_name(offsets_sbfd
->abfd
,
247 struct supersect
*config_ss
=
248 fetch_supersect(offsets_sbfd
, config_sect
);
250 config
= config_ss
->contents
.data
;
253 bool matchable_data_section(struct supersect
*ss
)
255 if (ss
->type
== SS_TYPE_STRING
)
257 if (ss
->type
== SS_TYPE_RODATA
)
259 if (ss
->type
== SS_TYPE_DATA
&& ss
->relocs
.size
!= 0)
264 bool unchangeable_section(struct supersect
*ss
)
266 if (ss
->type
== SS_TYPE_DATA
)
268 if (ss
->type
== SS_TYPE_IGNORED
&& !starts_with(ss
->name
, ".debug") &&
269 strcmp(ss
->name
, "__ksymtab_strings") != 0)
274 int main(int argc
, char *argv
[])
276 if (getenv("KSPLICE_VERBOSE") != NULL
)
277 verbose
= atoi(getenv("KSPLICE_VERBOSE"));
280 bfd
*ibfd
= bfd_openr(argv
[1], NULL
);
284 assert(bfd_check_format_matches(ibfd
, bfd_object
, &matching
));
286 const char *output_target
= bfd_get_target(ibfd
);
287 bfd
*obfd
= bfd_openw(argv
[2], output_target
);
290 struct superbfd
*isbfd
= fetch_superbfd(ibfd
);
291 init_label_map(isbfd
);
293 bool_hash_init(&system_map_written
);
294 ulong_hash_init(&ksplice_symbol_offset
);
295 ulong_hash_init(&ksplice_string_offset
);
298 if (mode("keep-primary")) {
300 do_keep_primary(isbfd
, argv
[4]);
301 } else if (mode("keep-helper")) {
302 do_keep_helper(isbfd
);
303 } else if (mode("finalize")) {
305 } else if (mode("rmsyms")) {
309 copy_object(ibfd
, obfd
);
311 if (offsets_sbfd
!= NULL
)
312 assert(bfd_close(offsets_sbfd
->abfd
));
313 assert(bfd_close(obfd
));
314 assert(bfd_close(ibfd
));
318 void do_keep_primary(struct superbfd
*isbfd
, const char *pre
)
320 struct bfd
*prebfd
= bfd_openr(pre
, NULL
);
321 assert(prebfd
!= NULL
);
323 assert(bfd_check_format_matches(prebfd
, bfd_object
, &matching
));
325 struct superbfd
*presbfd
= fetch_superbfd(prebfd
);
326 init_label_map(presbfd
);
329 initialize_supersect_types(isbfd
);
330 initialize_supersect_types(presbfd
);
332 match_global_symbol_sections(presbfd
, isbfd
);
333 debug1(isbfd
, "Matched global\n");
334 match_sections_by_name(presbfd
, isbfd
);
335 debug1(isbfd
, "Matched by name\n");
336 match_sections_by_label(presbfd
, isbfd
);
337 debug1(isbfd
, "Matched by label\n");
341 compare_matched_sections(isbfd
);
342 update_nonzero_offsets(isbfd
);
343 mark_new_sections(isbfd
);
347 handle_deleted_sections(presbfd
, isbfd
);
348 handle_section_symbol_renames(presbfd
, isbfd
);
351 compare_exported_symbols(presbfd
, isbfd
, false);
352 compare_exported_symbols(isbfd
, presbfd
, true);
354 initialize_spans(isbfd
);
355 initialize_spans(presbfd
);
357 for (sect
= isbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
358 struct supersect
*ss
= fetch_supersect(isbfd
, sect
);
359 if (ss
->type
!= SS_TYPE_STRING
)
361 asection
*oldsect
= bfd_get_section_by_name(prebfd
, sect
->name
);
364 struct supersect
*old_ss
= fetch_supersect(presbfd
, oldsect
);
365 struct span
*span
, *old_span
;
366 for (span
= ss
->spans
.data
;
367 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++) {
369 for (old_span
= old_ss
->spans
.data
;
370 old_span
< old_ss
->spans
.data
+ old_ss
->spans
.size
;
372 if (strcmp((char *)ss
->contents
.data
+
374 (char *)old_ss
->contents
.data
+
375 old_span
->start
) == 0) {
378 span
->label
= old_span
->label
;
384 assert(bfd_close(prebfd
));
386 for (sect
= isbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
387 struct supersect
*ss
= fetch_supersect(isbfd
, sect
);
389 if (ss
->type
== SS_TYPE_STRING
|| ss
->type
== SS_TYPE_SPECIAL
||
390 ss
->type
== SS_TYPE_EXPORT
)
392 if (ss
->new || ss
->patch
)
396 print_label_map(isbfd
);
398 for (sect
= isbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
399 struct supersect
*ss
= fetch_supersect(isbfd
, sect
);
401 debug0(isbfd
, "Patching section: %s\n", sect
->name
);
404 for (sect
= isbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
405 struct supersect
*ss
= fetch_supersect(isbfd
, sect
);
407 debug0(isbfd
, "New section: %s\n", sect
->name
);
410 const char **sectname
;
411 for (sectname
= delsects
.data
;
412 sectname
< delsects
.data
+ delsects
.size
; sectname
++)
413 debug0(isbfd
, "Deleted section: %s\n", *sectname
);
415 const struct export_desc
*ed
;
416 for (ed
= exports
.data
; ed
< exports
.data
+ exports
.size
; ed
++) {
417 const char **symname
;
418 for (symname
= ed
->names
.data
;
419 symname
< ed
->names
.data
+ ed
->names
.size
; symname
++)
420 debug0(isbfd
, "Export %s (%s): %s\n",
421 ed
->deletion
? "deletion" : "addition",
422 ed
->export_type
, *symname
);
426 for (sect
= isbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
427 struct supersect
*ss
= fetch_supersect(isbfd
, sect
);
428 for (span
= ss
->spans
.data
;
429 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++)
430 span
->keep
= ss
->keep
;
433 filter_table_sections(isbfd
);
434 for (ed
= exports
.data
; ed
< exports
.data
+ exports
.size
; ed
++) {
435 const char **symname
;
436 for (symname
= ed
->names
.data
;
437 symname
< ed
->names
.data
+ ed
->names
.size
; symname
++)
438 write_ksplice_export(isbfd
, *symname
,
439 ed
->export_type
, ed
->deletion
);
441 rm_some_exports(isbfd
, ed
);
444 compute_span_shifts(isbfd
);
446 for (sect
= isbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
447 struct supersect
*ss
= fetch_supersect(isbfd
, sect
);
448 if (!ss
->patch
&& !ss
->new)
452 for (span
= ss
->spans
.data
;
453 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++)
454 write_ksplice_section(span
);
457 write_ksplice_patch(isbfd
, sect
->name
);
461 remove_unkept_spans(isbfd
);
464 void do_keep_helper(struct superbfd
*isbfd
)
468 initialize_supersect_types(isbfd
);
469 initialize_spans(isbfd
);
472 for (sect
= isbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
473 struct supersect
*ss
= fetch_supersect(isbfd
, sect
);
475 if (ss
->type
== SS_TYPE_SPECIAL
|| ss
->type
== SS_TYPE_TEXT
)
480 for (symp
= isbfd
->syms
.data
;
481 symp
< isbfd
->syms
.data
+ isbfd
->syms
.size
; symp
++) {
482 asymbol
*sym
= *symp
;
483 if (!bfd_is_const_section(sym
->section
) &&
484 (sym
->flags
& BSF_GLOBAL
) != 0) {
485 struct supersect
*sym_ss
=
486 fetch_supersect(isbfd
, sym
->section
);
487 if (sym_ss
->type
!= SS_TYPE_IGNORED
)
493 for (sect
= isbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
494 struct supersect
*ss
= fetch_supersect(isbfd
, sect
);
495 for (span
= ss
->spans
.data
;
496 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++)
497 span
->keep
= ss
->keep
;
502 keep_referenced_sections(isbfd
);
505 filter_table_sections(isbfd
);
506 compute_span_shifts(isbfd
);
508 for (sect
= isbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
509 struct supersect
*ss
= fetch_supersect(isbfd
, sect
);
510 asymbol
*sym
= canonical_symbol(isbfd
, sect
->symbol
);
513 if ((sym
->flags
& BSF_WEAK
) != 0)
515 if (bfd_get_section_size(sect
) == 0)
519 if (ss
->type
!= SS_TYPE_TEXT
&& !matchable_data_section(ss
))
523 for (span
= ss
->spans
.data
;
524 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++) {
526 write_ksplice_section(span
);
531 remove_unkept_spans(isbfd
);
534 void do_finalize(struct superbfd
*isbfd
)
538 initialize_supersect_types(isbfd
);
539 initialize_spans(isbfd
);
543 void do_rmsyms(struct superbfd
*isbfd
)
545 read_str_set(&rmsyms
);
548 initialize_supersect_types(isbfd
);
549 initialize_spans(isbfd
);
553 struct export_vec
*get_export_syms(struct superbfd
*sbfd
)
556 struct export_vec
*exports
;
557 exports
= malloc(sizeof(*exports
));
558 assert(exports
!= NULL
);
561 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
562 if (!starts_with(sect
->name
, "__ksymtab") ||
563 ends_with(sect
->name
, "_strings"))
565 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
566 struct kernel_symbol
*sym
;
567 assert(ss
->contents
.size
* 2 == ss
->relocs
.size
*
568 sizeof(struct kernel_symbol
));
569 for (sym
= ss
->contents
.data
;
570 (void *)sym
< ss
->contents
.data
+ ss
->contents
.size
;
572 struct export
*exp
= vec_grow(exports
, 1);
574 read_string(ss
, (const char *const *)&sym
->name
);
581 struct export_desc
*new_export_desc(struct supersect
*ss
, bool deletion
)
583 struct export_desc
*ed
= vec_grow(&exports
, 1);
584 ed
->deletion
= deletion
;
585 vec_init(&ed
->names
);
586 ed
->export_type
= strdup(ss
->name
) + strlen("__ksymtab");
589 assert(asprintf(&crc_sect_name
, "__kcrctab%s", ed
->export_type
) >= 0);
591 bfd_get_section_by_name(ss
->parent
->abfd
, crc_sect_name
);
592 if (crc_sect
== NULL
)
595 ed
->crc_ss
= fetch_supersect(ss
->parent
, crc_sect
);
599 void compare_exported_symbols(struct superbfd
*oldsbfd
,
600 struct superbfd
*newsbfd
, bool deletion
)
602 struct export_vec
*new_exports
, *old_exports
;
603 new_exports
= get_export_syms(newsbfd
);
604 if (new_exports
== NULL
)
606 old_exports
= get_export_syms(oldsbfd
);
607 struct export
*old
, *new;
608 struct supersect
*last_ss
= NULL
;
609 struct export_desc
*ed
= NULL
;
610 for (new = new_exports
->data
; new < new_exports
->data
+
611 new_exports
->size
; new++) {
613 if (old_exports
!= NULL
) {
614 for (old
= old_exports
->data
; old
< old_exports
->data
+
615 old_exports
->size
; old
++) {
616 if (strcmp(new->name
, old
->name
) == 0 &&
617 strcmp(new->ss
->name
, old
->ss
->name
) == 0) {
623 if (last_ss
!= new->ss
) {
625 ed
= new_export_desc(new->ss
, deletion
);
628 *vec_grow(&ed
->names
, 1) = new->name
;
632 void match_sections(struct supersect
*oldss
, struct supersect
*newss
)
634 if (oldss
->match
== newss
&& newss
->match
== oldss
)
636 if (oldss
->match
!= NULL
) {
637 err(newss
->parent
, "Matching conflict: old %s: %s != %s\n",
638 oldss
->name
, oldss
->match
->name
, newss
->name
);
641 if (newss
->match
!= NULL
) {
642 err(newss
->parent
, "Matching conflict: new %s: %s != %s\n",
643 newss
->name
, newss
->match
->name
, oldss
->name
);
646 oldss
->match
= newss
;
647 newss
->match
= oldss
;
648 debug1(newss
->parent
, "Matched old %s to new %s\n",
649 oldss
->name
, newss
->name
);
652 static void match_global_symbol_sections(struct superbfd
*oldsbfd
,
653 struct superbfd
*newsbfd
)
655 asymbol
**oldsymp
, **newsymp
;
656 for (oldsymp
= oldsbfd
->syms
.data
;
657 oldsymp
< oldsbfd
->syms
.data
+ oldsbfd
->syms
.size
; oldsymp
++) {
658 asymbol
*oldsym
= *oldsymp
;
659 if ((oldsym
->flags
& BSF_GLOBAL
) == 0 ||
660 bfd_is_const_section(oldsym
->section
))
662 for (newsymp
= newsbfd
->syms
.data
;
663 newsymp
< newsbfd
->syms
.data
+ newsbfd
->syms
.size
;
665 asymbol
*newsym
= *newsymp
;
666 if ((newsym
->flags
& BSF_GLOBAL
) == 0 ||
667 bfd_is_const_section(oldsym
->section
))
669 if (strcmp(oldsym
->name
, newsym
->name
) != 0)
671 struct supersect
*oldss
=
672 fetch_supersect(oldsbfd
, oldsym
->section
);
673 struct supersect
*newss
=
674 fetch_supersect(newsbfd
, newsym
->section
);
675 match_sections(oldss
, newss
);
680 static void match_sections_by_name(struct superbfd
*oldsbfd
,
681 struct superbfd
*newsbfd
)
683 asection
*newp
, *oldp
;
684 for (newp
= newsbfd
->abfd
->sections
; newp
!= NULL
; newp
= newp
->next
) {
685 struct supersect
*newss
= fetch_supersect(newsbfd
, newp
);
686 oldp
= bfd_get_section_by_name(oldsbfd
->abfd
, newp
->name
);
687 if (oldp
== NULL
|| newss
->type
== SS_TYPE_STRING
||
688 newss
->type
== SS_TYPE_SPECIAL
||
689 newss
->type
== SS_TYPE_EXPORT
)
691 if (static_local_symbol(newsbfd
,
692 canonical_symbol(newsbfd
,
696 struct supersect
*oldss
= fetch_supersect(oldsbfd
, oldp
);
697 match_sections(oldss
, newss
);
701 static void match_sections_by_label(struct superbfd
*oldsbfd
,
702 struct superbfd
*newsbfd
)
704 asection
*oldsect
, *newsect
;
705 struct supersect
*oldss
, *newss
;
706 for (newsect
= newsbfd
->abfd
->sections
; newsect
!= NULL
;
707 newsect
= newsect
->next
) {
708 newss
= fetch_supersect(newsbfd
, newsect
);
709 if (newss
->type
== SS_TYPE_STRING
||
710 newss
->type
== SS_TYPE_SPECIAL
||
711 newss
->type
== SS_TYPE_EXPORT
)
713 for (oldsect
= oldsbfd
->abfd
->sections
; oldsect
!= NULL
;
714 oldsect
= oldsect
->next
) {
715 if (strcmp(label_lookup(newsbfd
, newsect
->symbol
),
716 label_lookup(oldsbfd
, oldsect
->symbol
)) != 0)
718 oldss
= fetch_supersect(oldsbfd
, oldsect
);
719 match_sections(oldss
, newss
);
724 static void mark_new_sections(struct superbfd
*sbfd
)
727 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
728 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
729 if (ss
->type
== SS_TYPE_STRING
|| ss
->type
== SS_TYPE_SPECIAL
||
730 ss
->type
== SS_TYPE_IGNORED
|| ss
->type
== SS_TYPE_EXPORT
)
732 if (ss
->match
== NULL
)
737 static void handle_deleted_sections(struct superbfd
*oldsbfd
,
738 struct superbfd
*newsbfd
)
741 for (sect
= oldsbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
742 struct supersect
*ss
= fetch_supersect(oldsbfd
, sect
);
743 if (ss
->type
!= SS_TYPE_TEXT
)
745 if (ss
->match
!= NULL
)
747 const char *label
= label_lookup(oldsbfd
, sect
->symbol
);
748 *vec_grow(&delsects
, 1) = label
;
749 asymbol
*csym
= canonical_symbol(oldsbfd
, sect
->symbol
);
750 write_ksplice_deleted_patch(newsbfd
, csym
->name
, label
);
754 static void handle_nonzero_offset_relocs(struct supersect
*ss
)
757 for (i
= 0; i
< ss
->relocs
.size
; i
++) {
758 asymbol
*sym
= *ss
->relocs
.data
[i
]->sym_ptr_ptr
;
759 bfd_vma offset
= get_reloc_offset(ss
, ss
->relocs
.data
[i
], true);
760 if (sym
->value
+ offset
== 0)
762 if (bfd_is_const_section(sym
->section
))
764 struct supersect
*sym_ss
= fetch_supersect(ss
->parent
,
766 if (sym_ss
->type
!= SS_TYPE_TEXT
)
768 if (!sym_ss
->patch
) {
771 "Changing %s because a relocation from sect %s "
772 "has a nonzero offset %lx+%lx into it\n",
773 sym_ss
->name
, ss
->name
,
774 (unsigned long)sym
->value
,
775 (unsigned long)offset
);
777 sym_ss
->patch
= true;
781 static void update_nonzero_offsets(struct superbfd
*sbfd
)
784 struct supersect
*ss
;
786 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
787 ss
= fetch_supersect(sbfd
, sect
);
788 if (ss
->new || ss
->patch
)
789 handle_nonzero_offset_relocs(ss
);
793 static void compare_matched_sections(struct superbfd
*newsbfd
)
796 struct supersect
*old_ss
, *new_ss
;
797 for (newp
= newsbfd
->abfd
->sections
; newp
!= NULL
; newp
= newp
->next
) {
798 new_ss
= fetch_supersect(newsbfd
, newp
);
799 if (new_ss
->match
== NULL
)
801 old_ss
= new_ss
->match
;
803 if (nonrelocs_equal(old_ss
, new_ss
) &&
804 all_relocs_equal(old_ss
, new_ss
))
808 if (new_ss
->contents
.size
!= old_ss
->contents
.size
)
809 reason
= "differing sizes";
810 else if (memcmp(new_ss
->contents
.data
, old_ss
->contents
.data
,
811 new_ss
->contents
.size
) != 0)
812 reason
= "differing contents";
814 reason
= "differing relocations";
815 if (new_ss
->type
== SS_TYPE_TEXT
) {
818 new_ss
->patch
= true;
819 debug1(newsbfd
, "Changing %s due to %s\n", new_ss
->name
,
822 debug1(newsbfd
, "Unmatching %s and %s due to %s\n",
823 old_ss
->name
, new_ss
->name
, reason
);
824 new_ss
->match
= NULL
;
825 old_ss
->match
= NULL
;
828 if (unchangeable_section(new_ss
))
829 err(newsbfd
, "warning: ignoring change to nonpatchable "
830 "section %s\n", new_ss
->name
);
834 static void handle_section_symbol_renames(struct superbfd
*oldsbfd
,
835 struct superbfd
*newsbfd
)
837 asection
*newp
, *oldp
;
838 for (newp
= newsbfd
->abfd
->sections
; newp
!= NULL
; newp
= newp
->next
) {
839 struct supersect
*newss
= fetch_supersect(newsbfd
, newp
);
840 if (newss
->match
== NULL
)
842 oldp
= bfd_get_section_by_name(oldsbfd
->abfd
,
847 const char *old_label
= label_lookup(oldsbfd
, oldp
->symbol
);
848 const char *new_label
= label_lookup(newsbfd
, newp
->symbol
);
850 if (strcmp(old_label
, new_label
) == 0)
852 label_map_set(newsbfd
, new_label
, old_label
);
856 static bool part_of_reloc(struct supersect
*ss
, unsigned long addr
)
859 for (relocp
= ss
->relocs
.data
;
860 relocp
< ss
->relocs
.data
+ ss
->relocs
.size
; relocp
++) {
861 arelent
*reloc
= *relocp
;
862 if (addr
>= reloc
->address
&&
863 addr
< reloc
->address
+ reloc
->howto
->size
)
869 static bool nonrelocs_equal(struct supersect
*old_ss
, struct supersect
*new_ss
)
872 if (old_ss
->contents
.size
!= new_ss
->contents
.size
)
874 const unsigned char *old
= old_ss
->contents
.data
;
875 const unsigned char *new = new_ss
->contents
.data
;
876 for (i
= 0; i
< old_ss
->contents
.size
; i
++) {
877 if (old
[i
] != new[i
] &&
878 !(part_of_reloc(old_ss
, i
) && part_of_reloc(new_ss
, i
)))
884 bool relocs_equal(struct supersect
*old_src_ss
, struct supersect
*new_src_ss
,
885 arelent
*old_reloc
, arelent
*new_reloc
)
887 if (old_reloc
->address
!= new_reloc
->address
)
890 struct superbfd
*oldsbfd
= old_src_ss
->parent
;
891 struct superbfd
*newsbfd
= new_src_ss
->parent
;
892 asymbol
*old_sym
= *old_reloc
->sym_ptr_ptr
;
893 asymbol
*new_sym
= *new_reloc
->sym_ptr_ptr
;
894 asection
*old_sect
= old_sym
->section
;
895 asection
*new_sect
= new_sym
->section
;
897 bfd_vma old_offset
= get_reloc_offset(old_src_ss
, old_reloc
, true);
898 bfd_vma new_offset
= get_reloc_offset(new_src_ss
, new_reloc
, true);
900 if (bfd_is_und_section(old_sect
) || bfd_is_und_section(new_sect
)) {
901 if (!bfd_is_und_section(new_sect
) && old_offset
!= 0 &&
902 fetch_supersect(newsbfd
, new_sect
)->type
== SS_TYPE_TEXT
)
905 if (!bfd_is_und_section(new_sect
) && new_offset
!= 0 &&
906 fetch_supersect(oldsbfd
, old_sect
)->type
== SS_TYPE_TEXT
)
909 return strcmp(old_sym
->name
, new_sym
->name
) == 0 &&
910 old_offset
== new_offset
;
913 if (bfd_is_const_section(old_sect
) || bfd_is_const_section(new_sect
))
916 struct supersect
*old_ss
= fetch_supersect(oldsbfd
, old_sect
);
917 struct supersect
*new_ss
= fetch_supersect(newsbfd
, new_sect
);
919 if (old_ss
->type
== SS_TYPE_STRING
&&
920 /* check it's not an out-of-range relocation to a string;
921 we'll just compare entire sections for them */
922 !(old_offset
>= old_ss
->contents
.size
||
923 new_offset
>= new_ss
->contents
.size
)) {
924 if (strcmp(old_ss
->contents
.data
+ old_sym
->value
+ old_offset
,
925 new_ss
->contents
.data
+ new_sym
->value
+ new_offset
)
927 debug0(newsbfd
, "Section %s/%s has string difference "
928 "\"%s\"/\"%s\"\n", old_src_ss
->name
,
930 (const char *)(old_ss
->contents
.data
+
931 old_sym
->value
+ old_offset
),
932 (const char *)(new_ss
->contents
.data
+
933 new_sym
->value
+ new_offset
));
934 debug1(newsbfd
, "Strings differ between %s and %s\n",
935 old_src_ss
->name
, new_src_ss
->name
);
941 if (old_ss
->match
!= new_ss
|| new_ss
->match
!= old_ss
) {
942 debug1(newsbfd
, "Nonmatching relocs from %s to %s/%s\n",
943 new_src_ss
->name
, new_ss
->name
, old_ss
->name
);
947 if (old_sym
->value
+ old_offset
!= new_sym
->value
+ new_offset
) {
948 debug1(newsbfd
, "Offsets to %s/%s differ between %s "
949 "and %s: %lx+%lx/%lx+%lx\n", old_ss
->name
,
950 new_ss
->name
, old_src_ss
->name
, new_src_ss
->name
,
951 (unsigned long)old_sym
->value
, (unsigned long)old_offset
,
952 (unsigned long)new_sym
->value
,
953 (unsigned long)new_offset
);
957 if ((old_sym
->value
+ old_offset
!= 0 ||
958 new_sym
->value
+ new_offset
!= 0) && new_ss
->patch
) {
959 debug1(newsbfd
, "Relocation from %s to nonzero offsets "
960 "%lx+%lx/%lx+%lx in changed section %s\n",
961 new_src_ss
->name
, (unsigned long)old_sym
->value
,
962 (unsigned long)old_offset
, (unsigned long)new_sym
->value
,
963 (unsigned long)new_offset
, new_sym
->section
->name
);
969 bool all_relocs_equal(struct supersect
*old_ss
, struct supersect
*new_ss
)
971 if (old_ss
->relocs
.size
!= new_ss
->relocs
.size
) {
972 debug1(new_ss
->parent
, "Different reloc count between %s and "
973 "%s\n", old_ss
->name
, new_ss
->name
);
978 for (i
= 0; i
< old_ss
->relocs
.size
; i
++) {
979 if (!relocs_equal(old_ss
, new_ss
, old_ss
->relocs
.data
[i
],
980 new_ss
->relocs
.data
[i
]))
987 void rm_some_exports(struct superbfd
*sbfd
, const struct export_desc
*ed
)
989 struct supersect
*ss
= ed
->sym_ss
;
990 struct supersect
*crc_ss
= ed
->crc_ss
;
992 assert(ss
->contents
.size
* sizeof(unsigned long) ==
993 crc_ss
->contents
.size
* sizeof(struct kernel_symbol
));
995 struct kernel_symbol
*ksym
;
996 unsigned long *crc
= NULL
;
998 crc
= crc_ss
->contents
.data
;
999 struct span
*span
, *crc_span
;
1000 for (ksym
= ss
->contents
.data
;
1001 (void *)ksym
< ss
->contents
.data
+ ss
->contents
.size
;
1004 read_reloc(ss
, &ksym
->value
, sizeof(ksym
->value
), &sym
);
1005 span
= new_span(ss
, addr_offset(ss
, ksym
), sizeof(*ksym
));
1006 span
->keep
= str_in_set(sym
->name
, &ed
->names
);
1008 if (crc_ss
!= NULL
) {
1009 crc_span
= new_span(crc_ss
, addr_offset(crc_ss
, crc
),
1011 crc_span
->keep
= span
->keep
;
1015 /* Replace name with a mangled name */
1016 write_string(ss
, (const char **)&ksym
->name
,
1017 "DISABLED_%s_%s", sym
->name
, kid
);
1022 void rm_relocs(struct superbfd
*isbfd
)
1025 for (p
= isbfd
->abfd
->sections
; p
!= NULL
; p
= p
->next
) {
1026 struct supersect
*ss
= fetch_supersect(isbfd
, p
);
1027 if ((mode("keep") && ss
->type
== SS_TYPE_SPECIAL
) ||
1028 ss
->type
== SS_TYPE_KSPLICE
)
1030 if (ss
->keep
|| mode("rmsyms"))
1033 if (mode("finalize")) {
1034 p
= bfd_get_section_by_name(isbfd
->abfd
, ".ksplice_patches");
1036 struct supersect
*ss
= fetch_supersect(isbfd
, p
);
1042 void rm_some_relocs(struct supersect
*ss
)
1044 struct arelentp_vec orig_relocs
;
1045 vec_move(&orig_relocs
, &ss
->relocs
);
1048 for (relocp
= orig_relocs
.data
;
1049 relocp
< orig_relocs
.data
+ orig_relocs
.size
; relocp
++) {
1050 bool rm_reloc
= false;
1051 asymbol
*sym_ptr
= *(*relocp
)->sym_ptr_ptr
;
1053 if (mode("rmsyms") && str_in_set(sym_ptr
->name
, &rmsyms
) &&
1054 bfd_is_und_section(sym_ptr
->section
))
1060 if (mode("keep-primary") &&
1061 (bfd_is_const_section(sym_ptr
->section
) ||
1062 fetch_supersect(ss
->parent
, sym_ptr
->section
)->new ||
1063 reloc_target_span(ss
, *relocp
)->new ||
1064 !reloc_address_span(ss
, *relocp
)->keep
))
1067 if (mode("finalize") && bfd_is_und_section(sym_ptr
->section
))
1071 write_ksplice_reloc(ss
, *relocp
);
1073 *vec_grow(&ss
->relocs
, 1) = *relocp
;
1077 struct supersect
*make_section(struct superbfd
*sbfd
, const char *name
)
1079 asection
*sect
= bfd_get_section_by_name(sbfd
->abfd
, name
);
1081 return fetch_supersect(sbfd
, sect
);
1083 return new_supersect(sbfd
, name
);
1086 arelent
*create_reloc(struct supersect
*ss
, const void *addr
, asymbol
**symp
,
1089 bfd_reloc_code_real_type code
;
1090 switch (bfd_arch_bits_per_address(ss
->parent
->abfd
)) {
1092 code
= BFD_RELOC_32
;
1095 code
= BFD_RELOC_64
;
1101 arelent
*reloc
= malloc(sizeof(*reloc
));
1102 reloc
->sym_ptr_ptr
= symp
;
1103 reloc
->address
= addr_offset(ss
, addr
);
1104 reloc
->howto
= bfd_reloc_type_lookup(ss
->parent
->abfd
, code
);
1105 reloc
->addend
= offset
;
1109 void write_reloc(struct supersect
*ss
, const void *addr
, asymbol
**symp
,
1112 *vec_grow(&ss
->new_relocs
, 1) = create_reloc(ss
, addr
, symp
, offset
);
1115 void write_string(struct supersect
*ss
, const char **addr
, const char *fmt
, ...)
1118 struct supersect
*str_ss
= make_section(ss
->parent
, ".ksplice_str");
1121 int len
= vasprintf(&str
, fmt
, ap
);
1125 unsigned long *str_offp
= ulong_hash_lookup(&ksplice_string_offset
, str
,
1127 if (str_offp
== NULL
) {
1128 char *buf
= sect_grow(str_ss
, len
+ 1, char);
1129 memcpy(buf
, str
, len
+ 1);
1130 str_offp
= ulong_hash_lookup(&ksplice_string_offset
, str
, TRUE
);
1131 *str_offp
= addr_offset(str_ss
, buf
);
1134 write_reloc(ss
, addr
, &str_ss
->symbol
, *str_offp
);
1137 void lookup_system_map(struct addr_vec
*addrs
, const char *name
, long offset
)
1139 struct addr_vec
*map_addrs
=
1140 addr_vec_hash_lookup(&system_map
, name
, FALSE
);
1141 if (map_addrs
== NULL
)
1144 unsigned long *addr
, *map_addr
;
1145 for (map_addr
= map_addrs
->data
;
1146 map_addr
< map_addrs
->data
+ map_addrs
->size
; map_addr
++) {
1147 for (addr
= addrs
->data
; addr
< addrs
->data
+ addrs
->size
;
1149 if (*addr
== *map_addr
+ offset
)
1152 if (addr
< addrs
->data
+ addrs
->size
)
1154 *vec_grow(addrs
, 1) = *map_addr
+ offset
;
1158 void write_system_map_array(struct superbfd
*sbfd
, struct supersect
*ss
,
1159 const unsigned long **sym_addrs
,
1160 unsigned long *num_sym_addrs
, asymbol
*sym
)
1162 struct addr_vec addrs
;
1165 if (bfd_is_abs_section(sym
->section
)) {
1166 *vec_grow(&addrs
, 1) = sym
->value
;
1167 } else if (bfd_is_und_section(sym
->section
)) {
1168 lookup_system_map(&addrs
, sym
->name
, 0);
1169 } else if (!bfd_is_const_section(sym
->section
)) {
1171 for (gsymp
= sbfd
->syms
.data
;
1172 gsymp
< sbfd
->syms
.data
+ sbfd
->syms
.size
; gsymp
++) {
1173 asymbol
*gsym
= *gsymp
;
1174 if ((gsym
->flags
& BSF_DEBUGGING
) == 0 &&
1175 gsym
->section
== sym
->section
)
1176 lookup_system_map(&addrs
, gsym
->name
,
1177 sym
->value
- gsym
->value
);
1181 *num_sym_addrs
= addrs
.size
;
1182 if (addrs
.size
!= 0) {
1183 struct supersect
*array_ss
= make_section(sbfd
,
1185 void *buf
= sect_grow(array_ss
, addrs
.size
,
1186 typeof(*addrs
.data
));
1187 memcpy(buf
, addrs
.data
, addrs
.size
* sizeof(*addrs
.data
));
1188 write_reloc(ss
, sym_addrs
, &array_ss
->symbol
,
1189 addr_offset(array_ss
, buf
));
1197 void write_ksplice_system_map(struct superbfd
*sbfd
, asymbol
*sym
,
1198 const char *addstr_sect
)
1200 struct supersect
*smap_ss
= make_section(sbfd
, ".ksplice_system_map");
1201 struct ksplice_system_map
*smap
;
1202 const char *label
= label_lookup(sbfd
, sym
);
1204 bool *done
= bool_hash_lookup(&system_map_written
, label
, TRUE
);
1209 smap
= sect_grow(smap_ss
, 1, struct ksplice_system_map
);
1211 write_system_map_array(sbfd
, smap_ss
, &smap
->candidates
,
1212 &smap
->nr_candidates
, sym
);
1213 write_string(smap_ss
, &smap
->label
, "%s%s", label
, addstr_sect
);
1216 void write_ksplice_symbol(struct supersect
*ss
,
1217 const struct ksplice_symbol
*const *addr
,
1218 asymbol
*sym
, struct span
*span
,
1219 const char *addstr_sect
)
1221 struct supersect
*ksymbol_ss
= make_section(ss
->parent
,
1222 ".ksplice_symbols");
1223 struct ksplice_symbol
*ksymbol
;
1224 unsigned long *ksymbol_offp
;
1227 if (span
!= NULL
&& span
->start
!= 0)
1228 label
= span
->label
;
1230 label
= label_lookup(ss
->parent
, sym
);
1231 assert(asprintf(&output
, "%s%s", label
, addstr_sect
) >= 0);
1233 ksymbol_offp
= ulong_hash_lookup(&ksplice_symbol_offset
, output
, FALSE
);
1234 if (ksymbol_offp
!= NULL
) {
1235 write_reloc(ss
, addr
, &ksymbol_ss
->symbol
, *ksymbol_offp
);
1238 ksymbol
= sect_grow(ksymbol_ss
, 1, struct ksplice_symbol
);
1239 ksymbol_offp
= ulong_hash_lookup(&ksplice_symbol_offset
, output
, TRUE
);
1240 *ksymbol_offp
= addr_offset(ksymbol_ss
, ksymbol
);
1242 write_reloc(ss
, addr
, &ksymbol_ss
->symbol
, *ksymbol_offp
);
1243 write_string(ksymbol_ss
, &ksymbol
->label
, "%s", output
);
1245 if (span
!= NULL
&& span
->symbol
== NULL
) {
1246 ksymbol
->name
= NULL
;
1250 write_ksplice_system_map(ksymbol_ss
->parent
, sym
, addstr_sect
);
1252 if (bfd_is_und_section(sym
->section
) || (sym
->flags
& BSF_GLOBAL
) != 0) {
1253 write_string(ksymbol_ss
, &ksymbol
->name
, "%s", sym
->name
);
1254 } else if (bfd_is_const_section(sym
->section
)) {
1255 ksymbol
->name
= NULL
;
1257 asymbol
*gsym
= canonical_symbol(ss
->parent
, sym
);
1259 if (gsym
== NULL
|| (gsym
->flags
& BSF_SECTION_SYM
) != 0)
1260 ksymbol
->name
= NULL
;
1262 write_string(ksymbol_ss
, &ksymbol
->name
, "%s",
1267 void write_ksplice_reloc(struct supersect
*ss
, arelent
*orig_reloc
)
1269 asymbol
*sym_ptr
= *orig_reloc
->sym_ptr_ptr
;
1270 reloc_howto_type
*howto
= orig_reloc
->howto
;
1271 bfd_vma addend
= get_reloc_offset(ss
, orig_reloc
, false);
1273 if (mode("finalize") && starts_with(ss
->name
, ".ksplice_patches")) {
1274 unsigned long *repladdr
=
1275 ss
->contents
.data
+ orig_reloc
->address
;
1280 struct span
*span
= reloc_target_span(ss
, orig_reloc
);
1281 if (span
== ss
->spans
.data
&& span
->start
!= addend
)
1283 blot_section(ss
, orig_reloc
->address
, howto
);
1285 struct supersect
*kreloc_ss
= make_section(ss
->parent
,
1287 ".ksplice_init_relocs" :
1289 struct ksplice_reloc
*kreloc
= sect_grow(kreloc_ss
, 1,
1290 struct ksplice_reloc
);
1292 struct span
*address_span
= reloc_address_span(ss
, orig_reloc
);
1293 write_reloc(kreloc_ss
, &kreloc
->blank_addr
,
1294 &ss
->symbol
, orig_reloc
->address
+ address_span
->shift
);
1295 write_ksplice_symbol(kreloc_ss
, &kreloc
->symbol
, sym_ptr
, span
, "");
1296 kreloc
->pcrel
= howto
->pc_relative
;
1297 if (span
!= NULL
&& span
->start
!= 0)
1298 addend
+= sym_ptr
->value
- span
->start
;
1299 kreloc
->addend
= addend
;
1300 kreloc
->size
= bfd_get_reloc_size(howto
);
1301 kreloc
->dst_mask
= howto
->dst_mask
;
1302 kreloc
->rightshift
= howto
->rightshift
;
1303 kreloc
->signed_addend
=
1304 (howto
->complain_on_overflow
== complain_overflow_signed
) ||
1305 (howto
->complain_on_overflow
== complain_overflow_bitfield
);
1308 #define CANARY(x, canary) ((x & ~howto->dst_mask) | (canary & howto->dst_mask))
1310 void blot_section(struct supersect
*ss
, int offset
, reloc_howto_type
*howto
)
1312 int bits
= bfd_get_reloc_size(howto
) * 8;
1313 void *address
= ss
->contents
.data
+ offset
;
1314 bfd_vma x
= bfd_get(bits
, ss
->parent
->abfd
, address
);
1315 x
= (x
& ~howto
->dst_mask
) |
1316 ((bfd_vma
)KSPLICE_CANARY
& howto
->dst_mask
);
1317 bfd_put(bits
, ss
->parent
->abfd
, x
, address
);
1320 static void write_ksplice_section(struct span
*span
)
1322 struct supersect
*ss
= span
->ss
;
1323 struct supersect
*ksect_ss
=
1324 make_section(ss
->parent
, ".ksplice_sections");
1325 struct ksplice_section
*ksect
= sect_grow(ksect_ss
, 1,
1326 struct ksplice_section
);
1327 asymbol
*sym
= span
->symbol
== NULL
? ss
->symbol
: span
->symbol
;
1329 write_ksplice_symbol(ksect_ss
, &ksect
->symbol
, sym
, span
,
1330 mode("keep-primary") ? "(post)" : "");
1331 ksect
->size
= span
->size
;
1334 if (ss
->type
== SS_TYPE_RODATA
|| ss
->type
== SS_TYPE_STRING
)
1335 ksect
->flags
|= KSPLICE_SECTION_RODATA
;
1336 if (ss
->type
== SS_TYPE_DATA
)
1337 ksect
->flags
|= KSPLICE_SECTION_DATA
;
1338 if (ss
->type
== SS_TYPE_TEXT
)
1339 ksect
->flags
|= KSPLICE_SECTION_TEXT
;
1340 assert(ksect
->flags
!= 0);
1341 write_reloc(ksect_ss
, &ksect
->address
, &ss
->symbol
,
1342 span
->start
+ span
->shift
);
1345 void write_ksplice_patch(struct superbfd
*sbfd
, const char *sectname
)
1347 struct supersect
*kpatch_ss
= make_section(sbfd
, ".ksplice_patches");
1348 struct ksplice_patch
*kpatch
= sect_grow(kpatch_ss
, 1,
1349 struct ksplice_patch
);
1350 asection
*sect
= bfd_get_section_by_name(sbfd
->abfd
, sectname
);
1351 assert(sect
!= NULL
);
1353 write_string(kpatch_ss
, &kpatch
->label
, "%s",
1354 label_lookup(sbfd
, sect
->symbol
));
1355 write_reloc(kpatch_ss
, &kpatch
->repladdr
, §
->symbol
, 0);
1358 void write_ksplice_deleted_patch(struct superbfd
*sbfd
, const char *name
,
1361 struct supersect
*kpatch_ss
= make_section(sbfd
, ".ksplice_patches");
1362 struct ksplice_patch
*kpatch
= sect_grow(kpatch_ss
, 1,
1363 struct ksplice_patch
);
1365 write_string(kpatch_ss
, &kpatch
->label
, "%s", label
);
1367 for (symp
= sbfd
->syms
.data
; symp
< sbfd
->syms
.data
+ sbfd
->syms
.size
;
1369 asymbol
*sym
= *symp
;
1370 if (bfd_is_und_section(sym
->section
) &&
1371 strcmp(name
, sym
->name
) == 0)
1374 if (symp
>= sbfd
->syms
.data
+ sbfd
->syms
.size
) {
1375 symp
= malloc(sizeof(*symp
));
1376 *symp
= bfd_make_empty_symbol(sbfd
->abfd
);
1377 asymbol
*sym
= *symp
;
1378 sym
->name
= strdup(name
);
1379 sym
->section
= bfd_und_section_ptr
;
1382 *vec_grow(&sbfd
->new_syms
, 1) = symp
;
1384 write_reloc(kpatch_ss
, &kpatch
->repladdr
, symp
, 0);
1387 void write_ksplice_export(struct superbfd
*sbfd
, const char *symname
,
1388 const char *export_type
, bool del
)
1390 struct supersect
*export_ss
= make_section(sbfd
, ".ksplice_exports");
1391 struct ksplice_export
*exp
= sect_grow(export_ss
, 1,
1392 struct ksplice_export
);
1395 write_string(export_ss
, &exp
->name
, "%s", symname
);
1396 write_string(export_ss
, &exp
->new_name
, "DISABLED_%s_%s",
1399 write_string(export_ss
, &exp
->new_name
, "%s", symname
);
1400 write_string(export_ss
, &exp
->name
, "DISABLED_%s_%s", symname
,
1405 struct fixup_entry
{
1409 DECLARE_VEC_TYPE(struct fixup_entry
, fixup_entry_vec
);
1411 int compare_fixups(const void *aptr
, const void *bptr
)
1413 const struct fixup_entry
*a
= aptr
, *b
= bptr
;
1414 if (a
->offset
< b
->offset
)
1416 else if (a
->offset
> b
->offset
)
1419 return (int)a
->used
- (int)b
->used
;
1422 void filter_table_sections(struct superbfd
*isbfd
)
1424 struct supersect
*tables_ss
=
1425 fetch_supersect(offsets_sbfd
,
1426 bfd_get_section_by_name(offsets_sbfd
->abfd
,
1427 ".ksplice_table_sections"));
1428 const struct table_section
*ts
;
1429 for (ts
= tables_ss
->contents
.data
;
1430 (void *)ts
< tables_ss
->contents
.data
+ tables_ss
->contents
.size
;
1432 struct table_section s
= *ts
;
1433 s
.sect
= read_string(tables_ss
, &ts
->sect
);
1434 s
.other_sect
= read_string(tables_ss
, &ts
->other_sect
);
1435 filter_table_section(isbfd
, &s
);
1439 void filter_table_section(struct superbfd
*sbfd
, const struct table_section
*s
)
1441 asection
*isection
= bfd_get_section_by_name(sbfd
->abfd
, s
->sect
);
1442 if (isection
== NULL
)
1444 asection
*fixup_sect
= NULL
;
1445 if (s
->other_sect
!= NULL
)
1446 fixup_sect
= bfd_get_section_by_name(sbfd
->abfd
, s
->other_sect
);
1448 struct supersect
*ss
= fetch_supersect(sbfd
, isection
);
1449 if (ss
->alignment
< ffs(s
->entry_align
) - 1)
1450 ss
->alignment
= ffs(s
->entry_align
) - 1;
1452 struct supersect
*fixup_ss
= NULL
;
1453 if (fixup_sect
!= NULL
)
1454 fixup_ss
= fetch_supersect(sbfd
, fixup_sect
);
1456 struct fixup_entry_vec fixups
;
1460 for (entry
= ss
->contents
.data
;
1461 entry
< ss
->contents
.data
+ ss
->contents
.size
;
1462 entry
+= s
->entry_size
) {
1463 asymbol
*sym
, *fixup_sym
;
1464 read_reloc(ss
, entry
+ s
->addr_offset
, sizeof(void *), &sym
);
1466 struct span
*span
= new_span(ss
, addr_offset(ss
, entry
),
1468 struct supersect
*sym_ss
= fetch_supersect(sbfd
, sym
->section
);
1469 span
->keep
= sym_ss
->keep
;
1471 struct fixup_entry
*f
;
1472 if (fixup_sect
!= NULL
) {
1473 bfd_vma fixup_offset
=
1474 read_reloc(ss
, entry
+ s
->other_offset
,
1475 sizeof(void *), &fixup_sym
);
1476 if (fixup_sym
->section
== fixup_sect
) {
1477 assert(fixup_offset
< fixup_ss
->contents
.size
);
1478 f
= vec_grow(&fixups
, 1);
1479 f
->offset
= fixup_offset
;
1480 f
->used
= span
->keep
;
1485 if (fixup_sect
== NULL
)
1488 qsort(fixups
.data
, fixups
.size
, sizeof(*fixups
.data
), compare_fixups
);
1489 *vec_grow(&fixups
, 1) = (struct fixup_entry
)
1490 { .offset
= fixup_ss
->contents
.size
, .used
= false };
1492 struct fixup_entry
*f
;
1493 for (f
= fixups
.data
; f
< fixups
.data
+ fixups
.size
- 1; f
++) {
1494 struct span
*span
= new_span(fixup_ss
, f
->offset
,
1495 (f
+ 1)->offset
- f
->offset
);
1496 span
->keep
= f
->used
;
1500 void keep_referenced_sections(struct superbfd
*sbfd
)
1503 struct supersect
*ss
, *sym_ss
;
1504 struct span
*address_span
, *target_span
;
1505 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
1506 ss
= fetch_supersect(sbfd
, sect
);
1508 if (ss
->type
== SS_TYPE_SPECIAL
|| ss
->type
== SS_TYPE_EXPORT
)
1510 for (relocp
= ss
->relocs
.data
;
1511 relocp
< ss
->relocs
.data
+ ss
->relocs
.size
; relocp
++) {
1512 asymbol
*sym
= *(*relocp
)->sym_ptr_ptr
;
1513 address_span
= reloc_address_span(ss
, *relocp
);
1514 if (!address_span
->keep
)
1516 target_span
= reloc_target_span(ss
, *relocp
);
1517 if (target_span
== NULL
|| target_span
->keep
)
1519 sym_ss
= fetch_supersect(sbfd
, sym
->section
);
1520 if (sym_ss
->type
== SS_TYPE_IGNORED
)
1522 target_span
->keep
= true;
1523 sym_ss
->keep
= true;
1529 void copy_symbols(struct asymbolp_vec
*osyms
, struct asymbolpp_vec
*isyms
)
1532 for (sympp
= isyms
->data
; sympp
< isyms
->data
+ isyms
->size
; sympp
++)
1533 *vec_grow(osyms
, 1) = **sympp
;
1536 /* Modified function from GNU Binutils objcopy.c */
1537 bfd_boolean
copy_object(bfd
*ibfd
, bfd
*obfd
)
1539 assert(bfd_set_format(obfd
, bfd_get_format(ibfd
)));
1541 bfd_vma start
= bfd_get_start_address(ibfd
);
1543 flagword flags
= bfd_get_file_flags(ibfd
);
1544 flags
&= bfd_applicable_file_flags(obfd
);
1546 assert(bfd_set_start_address(obfd
, start
)
1547 && bfd_set_file_flags(obfd
, flags
));
1549 enum bfd_architecture iarch
= bfd_get_arch(ibfd
);
1550 unsigned int imach
= bfd_get_mach(ibfd
);
1551 assert(bfd_set_arch_mach(obfd
, iarch
, imach
));
1552 assert(bfd_set_format(obfd
, bfd_get_format(ibfd
)));
1554 /* BFD mandates that all output sections be created and sizes set before
1555 any output is done. Thus, we traverse all sections multiple times. */
1556 bfd_map_over_sections(ibfd
, setup_section
, obfd
);
1558 struct supersect
*new_supersects
= fetch_superbfd(ibfd
)->new_supersects
;
1559 struct supersect
*ss
;
1560 for (ss
= new_supersects
; ss
!= NULL
; ss
= ss
->next
)
1561 setup_new_section(obfd
, ss
);
1563 /* Mark symbols used in output relocations so that they
1564 are kept, even if they are local labels or static symbols.
1566 Note we iterate over the input sections examining their
1567 relocations since the relocations for the output sections
1568 haven't been set yet. mark_symbols_used_in_relocations will
1569 ignore input sections which have no corresponding output
1572 bfd_map_over_sections(ibfd
, mark_symbols_used_in_relocations
, NULL
);
1573 for (ss
= new_supersects
; ss
!= NULL
; ss
= ss
->next
)
1574 ss_mark_symbols_used_in_relocations(ss
);
1575 struct asymbolp_vec osyms
;
1577 filter_symbols(ibfd
, obfd
, &osyms
, &fetch_superbfd(ibfd
)->syms
);
1578 copy_symbols(&osyms
, &fetch_superbfd(ibfd
)->new_syms
);
1580 bfd_set_symtab(obfd
, osyms
.data
, osyms
.size
);
1582 /* This has to happen after the symbol table has been set. */
1583 bfd_map_over_sections(obfd
, write_section
, NULL
);
1585 /* Allow the BFD backend to copy any private data it understands
1586 from the input BFD to the output BFD. This is done last to
1587 permit the routine to look at the filtered symbol table, which is
1588 important for the ECOFF code at least. */
1589 assert(bfd_copy_private_bfd_data(ibfd
, obfd
));
1594 /* Modified function from GNU Binutils objcopy.c */
1595 void setup_section(bfd
*ibfd
, asection
*isection
, void *obfdarg
)
1597 struct superbfd
*isbfd
= fetch_superbfd(ibfd
);
1598 struct supersect
*ss
= fetch_supersect(isbfd
, isection
);
1599 bfd
*obfd
= obfdarg
;
1605 asection
*osection
= bfd_make_section_anyway(obfd
, isection
->name
);
1606 assert(osection
!= NULL
);
1608 osection
->userdata
= ss
;
1609 bfd_set_section_flags(obfd
, osection
, ss
->flags
);
1610 ss
->symbol
= osection
->symbol
;
1611 assert(bfd_set_section_size(obfd
, osection
, ss
->contents
.size
));
1613 vma
= bfd_section_vma(ibfd
, isection
);
1614 assert(bfd_set_section_vma(obfd
, osection
, vma
));
1616 osection
->lma
= isection
->lma
;
1617 assert(bfd_set_section_alignment(obfd
, osection
, ss
->alignment
));
1618 osection
->entsize
= isection
->entsize
;
1619 osection
->output_section
= osection
;
1620 osection
->output_offset
= 0;
1621 isection
->output_section
= osection
;
1622 isection
->output_offset
= 0;
1626 void setup_new_section(bfd
*obfd
, struct supersect
*ss
)
1628 asection
*osection
= bfd_make_section_anyway(obfd
, ss
->name
);
1629 assert(osection
!= NULL
);
1630 bfd_set_section_flags(obfd
, osection
, ss
->flags
);
1632 osection
->userdata
= ss
;
1633 ss
->symbol
= osection
->symbol
;
1634 assert(bfd_set_section_size(obfd
, osection
, ss
->contents
.size
));
1635 assert(bfd_set_section_vma(obfd
, osection
, 0));
1638 assert(bfd_set_section_alignment(obfd
, osection
, ss
->alignment
));
1639 osection
->entsize
= 0;
1640 osection
->output_section
= osection
;
1641 osection
->output_offset
= 0;
1644 static int compare_reloc_addresses(const void *aptr
, const void *bptr
)
1646 const arelent
*const *a
= aptr
, *const *b
= bptr
;
1647 return (*a
)->address
- (*b
)->address
;
1650 static void delete_obsolete_relocs(struct supersect
*ss
)
1652 if (ss
->new_relocs
.size
== 0)
1655 qsort(ss
->relocs
.data
, ss
->relocs
.size
, sizeof(*ss
->relocs
.data
),
1656 compare_reloc_addresses
);
1657 qsort(ss
->new_relocs
.data
, ss
->new_relocs
.size
,
1658 sizeof(*ss
->new_relocs
.data
), compare_reloc_addresses
);
1660 struct arelentp_vec orig_relocs
;
1661 vec_move(&orig_relocs
, &ss
->relocs
);
1663 arelent
**relocp
, **new_relocp
= ss
->new_relocs
.data
;
1664 for (relocp
= orig_relocs
.data
;
1665 relocp
< orig_relocs
.data
+ orig_relocs
.size
; relocp
++) {
1666 while (new_relocp
< ss
->new_relocs
.data
+ ss
->new_relocs
.size
&&
1667 (*new_relocp
)->address
< (*relocp
)->address
)
1669 arelent
*reloc
= *relocp
, *new_reloc
= *new_relocp
;
1670 if (new_relocp
== ss
->new_relocs
.data
+ ss
->new_relocs
.size
||
1671 reloc
->address
!= new_reloc
->address
)
1672 *vec_grow(&ss
->relocs
, 1) = reloc
;
1676 void write_section(bfd
*obfd
, asection
*osection
, void *arg
)
1678 struct supersect
*ss
= osection
->userdata
;
1680 if ((ss
->flags
& SEC_GROUP
) != 0 || ss
->contents
.size
== 0)
1683 delete_obsolete_relocs(ss
);
1686 char *error_message
;
1687 for (relocp
= ss
->new_relocs
.data
;
1688 relocp
< ss
->new_relocs
.data
+ ss
->new_relocs
.size
; relocp
++) {
1690 if (bfd_get_arch(obfd
) == bfd_arch_arm
)
1691 val
= osection
->use_rela_p
? 0 : (*relocp
)->addend
;
1694 bfd_put(bfd_get_reloc_size((*relocp
)->howto
) * 8, obfd
, val
,
1695 ss
->contents
.data
+ (*relocp
)->address
);
1696 if (bfd_install_relocation(obfd
, *relocp
, ss
->contents
.data
,
1697 0, osection
, &error_message
) !=
1699 err(ss
->parent
, "ksplice: error installing reloc: %s",
1704 memcpy(vec_grow(&ss
->relocs
, ss
->new_relocs
.size
), ss
->new_relocs
.data
,
1705 ss
->new_relocs
.size
* sizeof(*ss
->new_relocs
.data
));
1707 bfd_set_reloc(obfd
, osection
,
1708 ss
->relocs
.size
== 0 ? NULL
: ss
->relocs
.data
,
1711 if (ss
->flags
& SEC_HAS_CONTENTS
)
1712 assert(bfd_set_section_contents
1713 (obfd
, osection
, ss
->contents
.data
, 0,
1714 ss
->contents
.size
));
1717 /* Modified function from GNU Binutils objcopy.c
1719 * Mark all the symbols which will be used in output relocations with
1720 * the BSF_KEEP flag so that those symbols will not be stripped.
1722 * Ignore relocations which will not appear in the output file.
1724 void mark_symbols_used_in_relocations(bfd
*abfd
, asection
*isection
,
1727 struct superbfd
*sbfd
= fetch_superbfd(abfd
);
1728 if (isection
->output_section
== NULL
)
1731 struct supersect
*ss
= fetch_supersect(sbfd
, isection
);
1732 ss_mark_symbols_used_in_relocations(ss
);
1735 void ss_mark_symbols_used_in_relocations(struct supersect
*ss
)
1737 /* Examine each symbol used in a relocation. If it's not one of the
1738 special bfd section symbols, then mark it with BSF_KEEP. */
1740 for (relocp
= ss
->relocs
.data
;
1741 relocp
< ss
->relocs
.data
+ ss
->relocs
.size
; relocp
++) {
1742 asymbol
*sym
= *(*relocp
)->sym_ptr_ptr
;
1743 if (!(bfd_is_const_section(sym
->section
) &&
1744 sym
== sym
->section
->symbol
))
1745 sym
->flags
|= BSF_KEEP
;
1747 for (relocp
= ss
->new_relocs
.data
;
1748 relocp
< ss
->new_relocs
.data
+ ss
->new_relocs
.size
; relocp
++) {
1749 asymbol
*sym
= *(*relocp
)->sym_ptr_ptr
;
1750 if (!(bfd_is_const_section(sym
->section
) &&
1751 sym
== sym
->section
->symbol
))
1752 sym
->flags
|= BSF_KEEP
;
1756 static bool deleted_table_section_symbol(bfd
*abfd
, asymbol
*sym
)
1758 struct superbfd
*sbfd
= fetch_superbfd(abfd
);
1759 if (bfd_is_const_section(sym
->section
))
1761 struct supersect
*ss
= fetch_supersect(sbfd
, sym
->section
);
1764 for (symp
= ss
->syms
.data
; symp
< ss
->syms
.data
+ ss
->syms
.size
; symp
++) {
1768 return symp
>= ss
->syms
.data
+ ss
->syms
.size
;
1771 /* Modified function from GNU Binutils objcopy.c
1773 * Choose which symbol entries to copy.
1774 * We don't copy in place, because that confuses the relocs.
1775 * Return the number of symbols to print.
1777 void filter_symbols(bfd
*ibfd
, bfd
*obfd
, struct asymbolp_vec
*osyms
,
1778 struct asymbolp_vec
*isyms
)
1781 struct superbfd
*sbfd
= fetch_superbfd(ibfd
);
1782 for (symp
= isyms
->data
; symp
< isyms
->data
+ isyms
->size
; symp
++) {
1783 asymbol
*sym
= *symp
;
1784 struct supersect
*sym_ss
= NULL
;
1785 if (!bfd_is_const_section(sym
->section
))
1786 sym_ss
= fetch_supersect(sbfd
, sym
->section
);
1790 if (mode("keep") && (sym
->flags
& BSF_GLOBAL
) != 0 &&
1791 !(mode("keep-primary") && sym_ss
!= NULL
&& sym_ss
->new))
1792 sym
->flags
= (sym
->flags
& ~BSF_GLOBAL
) | BSF_LOCAL
;
1794 if (mode("finalize") && (sym
->flags
& BSF_GLOBAL
) != 0)
1795 sym
->flags
= (sym
->flags
& ~BSF_GLOBAL
) | BSF_LOCAL
;
1797 if ((sym
->flags
& BSF_KEEP
) != 0 /* Used in relocation. */
1798 || ((sym
->flags
& BSF_SECTION_SYM
) != 0 && sym_ss
!= NULL
&&
1801 else if ((sym
->flags
& (BSF_GLOBAL
| BSF_WEAK
)) != 0 &&
1802 sym_ss
!= NULL
&& sym_ss
->keep
)
1805 if (deleted_table_section_symbol(ibfd
, sym
))
1808 if (bfd_is_com_section(sym
->section
))
1812 keep
= !str_in_set(sym
->name
, &rmsyms
);
1815 if (sym_ss
!= NULL
&& !sym_ss
->keep
) {
1816 err(sbfd
, "Kept symbol %s in unkept section "
1817 "%s\n", sym
->name
, sym
->section
->name
);
1820 *vec_grow(osyms
, 1) = sym
;
1825 void read_str_set(struct str_vec
*strs
)
1829 assert(getline(&buf
, &n
, stdin
) >= 0);
1833 char *str
= strtok_r(buf
, " \n", &saveptr
);
1837 *vec_grow(strs
, 1) = str
;
1841 bool str_in_set(const char *str
, const struct str_vec
*strs
)
1844 for (strp
= strs
->data
; strp
< strs
->data
+ strs
->size
; strp
++) {
1845 if (strcmp(str
, *strp
) == 0)
1851 bool is_table_section(const char *name
, bool consider_other
)
1853 struct supersect
*tables_ss
=
1854 fetch_supersect(offsets_sbfd
,
1855 bfd_get_section_by_name(offsets_sbfd
->abfd
,
1856 ".ksplice_table_sections"));
1857 const struct table_section
*ts
;
1858 for (ts
= tables_ss
->contents
.data
;
1859 (void *)ts
< tables_ss
->contents
.data
+ tables_ss
->contents
.size
;
1861 if (strcmp(name
, read_string(tables_ss
, &ts
->sect
)) == 0)
1863 const char *osect_name
= read_string(tables_ss
,
1865 if (consider_other
&& osect_name
!= NULL
&&
1866 strcmp(name
, osect_name
) == 0)
1872 enum supersect_type
supersect_type(struct supersect
*ss
)
1874 if (starts_with(ss
->name
, ".ksplice"))
1875 return SS_TYPE_KSPLICE
;
1877 if (starts_with(ss
->name
, ".init"))
1878 return SS_TYPE_IGNORED
;
1879 if (starts_with(ss
->name
, ".security_initcall.init"))
1880 return SS_TYPE_IGNORED
;
1881 if (starts_with(ss
->name
, ".con_initcall.init"))
1882 return SS_TYPE_IGNORED
;
1883 if (starts_with(ss
->name
, ".x86cpuvendor.init"))
1884 return SS_TYPE_IGNORED
;
1885 if (starts_with(ss
->name
, ".early_param.init"))
1886 return SS_TYPE_IGNORED
;
1887 if (starts_with(ss
->name
, ".taglist.init"))
1888 return SS_TYPE_IGNORED
;
1889 if (starts_with(ss
->name
, ".arch.info.init"))
1890 return SS_TYPE_IGNORED
;
1891 if (starts_with(ss
->name
, ".proc.info.init"))
1892 return SS_TYPE_IGNORED
;
1893 /* .pci_fixup_* sections really should be treated as global rodata
1894 referenced only from quirks.c */
1895 if (starts_with(ss
->name
, ".pci_fixup_"))
1896 return SS_TYPE_IGNORED
;
1897 /* .builtin_fw sections are similar to .pci_fixup */
1898 if (starts_with(ss
->name
, ".builtin_fw"))
1899 return SS_TYPE_IGNORED
;
1900 /* same for .tracedata */
1901 if (starts_with(ss
->name
, ".tracedata"))
1902 return SS_TYPE_IGNORED
;
1903 if (starts_with(ss
->name
, ".debug"))
1904 return SS_TYPE_IGNORED
;
1905 /* .eh_frame should probably be discarded, not ignored */
1906 if (starts_with(ss
->name
, ".eh_frame"))
1907 return SS_TYPE_IGNORED
;
1908 if (config
->ignore_devinit
&& starts_with(ss
->name
, ".devinit"))
1909 return SS_TYPE_IGNORED
;
1910 if (config
->ignore_meminit
&& starts_with(ss
->name
, ".meminit"))
1911 return SS_TYPE_IGNORED
;
1912 if (config
->ignore_cpuinit
&& starts_with(ss
->name
, ".cpuinit"))
1913 return SS_TYPE_IGNORED
;
1914 if (config
->ignore_devinit
&& starts_with(ss
->name
, ".devexit"))
1915 return SS_TYPE_IGNORED
;
1916 if (config
->ignore_meminit
&& starts_with(ss
->name
, ".memexit"))
1917 return SS_TYPE_IGNORED
;
1918 if (config
->ignore_cpuinit
&& starts_with(ss
->name
, ".cpuexit"))
1919 return SS_TYPE_IGNORED
;
1920 if (starts_with(ss
->name
, ".vgetcpu_mode") ||
1921 starts_with(ss
->name
, ".jiffies") ||
1922 starts_with(ss
->name
, ".wall_jiffies") ||
1923 starts_with(ss
->name
, ".vxtime") ||
1924 starts_with(ss
->name
, ".sys_tz") ||
1925 starts_with(ss
->name
, ".sysctl_vsyscall") ||
1926 starts_with(ss
->name
, ".xtime") ||
1927 starts_with(ss
->name
, ".xtime_lock") ||
1928 starts_with(ss
->name
, ".vsyscall"))
1929 return SS_TYPE_IGNORED
;
1930 if (starts_with(ss
->name
, ".vdso"))
1931 return SS_TYPE_IGNORED
;
1933 if (bfd_get_section_by_name(ss
->parent
->abfd
, ".exitcall.exit") == NULL
) {
1934 if (starts_with(ss
->name
, ".exit.text"))
1935 return SS_TYPE_TEXT
;
1936 if (starts_with(ss
->name
, ".exit.data"))
1937 return SS_TYPE_DATA
;
1938 } else if (starts_with(ss
->name
, ".exit.text") ||
1939 starts_with(ss
->name
, ".exit.data"))
1940 return SS_TYPE_IGNORED
;
1942 if (starts_with(ss
->name
, ".text") ||
1943 starts_with(ss
->name
, ".kernel.text") ||
1944 starts_with(ss
->name
, ".devinit.text") ||
1945 starts_with(ss
->name
, ".meminit.text") ||
1946 starts_with(ss
->name
, ".cpuinit.text") ||
1947 starts_with(ss
->name
, ".devexit.text") ||
1948 starts_with(ss
->name
, ".memexit.text") ||
1949 starts_with(ss
->name
, ".cpuexit.text") ||
1950 starts_with(ss
->name
, ".ref.text") ||
1951 starts_with(ss
->name
, ".spinlock.text") ||
1952 starts_with(ss
->name
, ".kprobes.text") ||
1953 starts_with(ss
->name
, ".sched.text"))
1954 return SS_TYPE_TEXT
;
1957 if (sscanf(ss
->name
, ".rodata.str%*u.%*u%n", &n
) >= 0 &&
1958 n
== strlen(ss
->name
))
1959 return SS_TYPE_STRING
;
1961 if (starts_with(ss
->name
, ".rodata") ||
1962 starts_with(ss
->name
, ".kernel.rodata") ||
1963 starts_with(ss
->name
, ".devinit.rodata") ||
1964 starts_with(ss
->name
, ".meminit.rodata") ||
1965 starts_with(ss
->name
, ".cpuinit.rodata") ||
1966 starts_with(ss
->name
, ".devexit.rodata") ||
1967 starts_with(ss
->name
, ".memexit.rodata") ||
1968 starts_with(ss
->name
, ".cpuexit.rodata") ||
1969 starts_with(ss
->name
, ".ref.rodata") ||
1970 starts_with(ss
->name
, "__markers_strings"))
1971 return SS_TYPE_RODATA
;
1973 if (starts_with(ss
->name
, ".bss"))
1974 return SS_TYPE_DATA
;
1976 /* Ignore .data.percpu sections */
1977 if (starts_with(ss
->name
, ".data.percpu") ||
1978 starts_with(ss
->name
, ".kernel.data.percpu"))
1979 return SS_TYPE_IGNORED
;
1980 if (starts_with(ss
->name
, ".data") ||
1981 starts_with(ss
->name
, ".kernel.data") ||
1982 starts_with(ss
->name
, ".devinit.data") ||
1983 starts_with(ss
->name
, ".cpuinit.data") ||
1984 starts_with(ss
->name
, ".meminit.data") ||
1985 starts_with(ss
->name
, ".devexit.data") ||
1986 starts_with(ss
->name
, ".memexit.data") ||
1987 starts_with(ss
->name
, ".cpuexit.data") ||
1988 starts_with(ss
->name
, ".ref.data") ||
1989 starts_with(ss
->name
, "__markers"))
1990 return SS_TYPE_DATA
;
1992 /* We replace all the ksymtab strings, so delete them */
1993 if (strcmp(ss
->name
, "__ksymtab_strings") == 0)
1994 return SS_TYPE_IGNORED
;
1995 if (starts_with(ss
->name
, "__ksymtab"))
1996 return SS_TYPE_EXPORT
;
1997 if (starts_with(ss
->name
, "__kcrctab"))
1998 return SS_TYPE_EXPORT
;
2000 if (is_table_section(ss
->name
, true))
2001 return SS_TYPE_SPECIAL
;
2003 if (starts_with(ss
->name
, ".ARM."))
2004 return SS_TYPE_SPECIAL
;
2006 if (starts_with(ss
->name
, ".note"))
2007 return SS_TYPE_IGNORED
;
2008 if (starts_with(ss
->name
, ".comment"))
2009 return SS_TYPE_IGNORED
;
2010 if (starts_with(ss
->name
, "__param"))
2011 return SS_TYPE_IGNORED
;
2012 if (starts_with(ss
->name
, ".exitcall.exit"))
2013 return SS_TYPE_IGNORED
;
2014 if (starts_with(ss
->name
, ".modinfo"))
2015 return SS_TYPE_IGNORED
;
2017 return SS_TYPE_UNKNOWN
;
2020 void initialize_supersect_types(struct superbfd
*sbfd
)
2023 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
2024 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
2025 ss
->type
= supersect_type(ss
);
2026 if (ss
->type
== SS_TYPE_UNKNOWN
) {
2027 err(sbfd
, "Unknown section type: %s\n", ss
->name
);
2033 static void init_label_map(struct superbfd
*sbfd
)
2035 struct label_map
*map
;
2037 vec_init(&sbfd
->maps
);
2041 struct symbol_hash csyms
;
2042 symbol_hash_init(&csyms
);
2045 for (symp
= sbfd
->syms
.data
;
2046 symp
< sbfd
->syms
.data
+ sbfd
->syms
.size
; symp
++) {
2047 asymbol
*csym
= canonical_symbol(sbfd
, *symp
);
2051 assert(asprintf(&key
, "%p", csym
) >= 0);
2052 asymbol
**csymp
= symbol_hash_lookup(&csyms
, key
, TRUE
);
2058 map
= vec_grow(&sbfd
->maps
, 1);
2061 map
->label
= symbol_label(sbfd
, csym
);
2064 struct label_mapp_hash label_maps
;
2065 label_mapp_hash_init(&label_maps
);
2066 for (map
= sbfd
->maps
.data
;
2067 map
< sbfd
->maps
.data
+ sbfd
->maps
.size
; map
++) {
2068 struct label_map
**mapp
=
2069 label_mapp_hash_lookup(&label_maps
, map
->label
, TRUE
);
2070 if (*mapp
== NULL
) {
2075 struct label_map
*first_map
= *mapp
;
2077 if (first_map
->count
== 0) {
2078 assert(asprintf(&buf
, "%s~%d", map
->label
, 0) >= 0);
2079 first_map
->label
= buf
;
2082 assert(asprintf(&buf
, "%s~%d", map
->label
, first_map
->count
)
2087 label_mapp_hash_init(&sbfd
->maps_hash
);
2088 for (map
= sbfd
->maps
.data
;
2089 map
< sbfd
->maps
.data
+ sbfd
->maps
.size
; map
++) {
2091 assert(asprintf(&key
, "%p", map
->csym
) >= 0);
2092 struct label_map
**mapp
=
2093 label_mapp_hash_lookup(&sbfd
->maps_hash
, key
, TRUE
);
2096 map
->orig_label
= map
->label
;
2100 static const char *label_lookup(struct superbfd
*sbfd
, asymbol
*sym
)
2102 asymbol
*csym
= canonical_symbol(sbfd
, sym
);
2104 assert(asprintf(&key
, "%p", csym
) >= 0);
2105 struct label_map
**mapp
=
2106 label_mapp_hash_lookup(&sbfd
->maps_hash
, key
, FALSE
);
2110 return (*mapp
)->label
;
2113 static void print_label_map(struct superbfd
*sbfd
)
2115 struct label_map
*map
;
2116 for (map
= sbfd
->maps
.data
;
2117 map
< sbfd
->maps
.data
+ sbfd
->maps
.size
; map
++) {
2118 if (strcmp(map
->orig_label
, map
->label
) == 0)
2120 debug1(sbfd
, "Label change: %s -> %s\n",
2121 map
->label
, map
->orig_label
);
2125 static void label_map_set(struct superbfd
*sbfd
, const char *oldlabel
,
2128 struct label_map
*map
;
2129 for (map
= sbfd
->maps
.data
;
2130 map
< sbfd
->maps
.data
+ sbfd
->maps
.size
; map
++) {
2131 if (strcmp(map
->orig_label
, oldlabel
) == 0) {
2132 if (strcmp(map
->orig_label
, map
->label
) != 0 &&
2133 strcmp(map
->label
, label
) != 0)
2142 static void init_callers(struct superbfd
*sbfd
)
2144 string_hash_init(&sbfd
->callers
);
2146 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
2147 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
2149 for (relocp
= ss
->relocs
.data
;
2150 relocp
< ss
->relocs
.data
+ ss
->relocs
.size
; relocp
++) {
2151 asymbol
*sym
= *(*relocp
)->sym_ptr_ptr
;
2153 sym
->value
+ get_reloc_offset(ss
, *relocp
, true);
2155 assert(asprintf(&key
, "%s+%lx", sym
->section
->name
,
2157 const char **ret
= string_hash_lookup(&sbfd
->callers
,
2163 *ret
= "*multiple_callers*";
2168 static const char *find_caller(struct supersect
*ss
, asymbol
*sym
)
2171 assert(asprintf(&key
, "%s+%lx", sym
->section
->name
,
2172 (unsigned long)sym
->value
) >= 0);
2173 const char **ret
= string_hash_lookup(&ss
->parent
->callers
, key
, FALSE
);
2177 return "*no_caller*";
2181 static void init_csyms(struct superbfd
*sbfd
)
2183 asymbolpp_hash_init(&sbfd
->csyms
);
2186 for (symp
= sbfd
->syms
.data
; symp
< sbfd
->syms
.data
+ sbfd
->syms
.size
;
2188 asymbol
*sym
= *symp
;
2189 if ((sym
->flags
& BSF_DEBUGGING
) != 0)
2192 assert(asprintf(&key
, "%s+%lx", sym
->section
->name
,
2193 (unsigned long)sym
->value
) >= 0);
2194 asymbol
***csympp
= asymbolpp_hash_lookup(&sbfd
->csyms
, key
,
2197 if (*csympp
== NULL
) {
2201 asymbol
*csym
= **csympp
;
2202 if ((csym
->flags
& BSF_GLOBAL
) != 0)
2204 if ((sym
->flags
& BSF_GLOBAL
) != 0)
2209 static asymbol
**symbolp_scan(struct supersect
*ss
, bfd_vma value
)
2212 assert(asprintf(&key
, "%s+%lx", ss
->name
, (unsigned long)value
) >= 0);
2214 asymbolpp_hash_lookup(&ss
->parent
->csyms
, key
, FALSE
);
2219 /* For section symbols of sections containing no symbols, return the
2220 section symbol that relocations are generated against */
2226 static asymbol
**canonical_symbolp(struct superbfd
*sbfd
, asymbol
*sym
)
2228 if (bfd_is_const_section(sym
->section
)) {
2230 for (csymp
= sbfd
->syms
.data
;
2231 csymp
< sbfd
->syms
.data
+ sbfd
->syms
.size
; csymp
++) {
2237 return symbolp_scan(fetch_supersect(sbfd
, sym
->section
), sym
->value
);
2240 static asymbol
*canonical_symbol(struct superbfd
*sbfd
, asymbol
*sym
)
2242 if (bfd_is_const_section(sym
->section
))
2244 asymbol
**symp
= canonical_symbolp(sbfd
, sym
);
2245 return symp
!= NULL
? *symp
: NULL
;
2248 static char *static_local_symbol(struct superbfd
*sbfd
, asymbol
*sym
)
2250 struct supersect
*ss
= fetch_supersect(sbfd
, sym
->section
);
2251 if ((sym
->flags
& BSF_LOCAL
) == 0 || (sym
->flags
& BSF_OBJECT
) == 0)
2253 char *dot
= strrchr(sym
->name
, '.');
2254 if (dot
== NULL
|| dot
[1 + strspn(dot
+ 1, "0123546789")] != '\0')
2256 char *basename
= strndup(sym
->name
, dot
- sym
->name
);
2258 if (strcmp(basename
, "__func__") == 0 ||
2259 strcmp(basename
, "__PRETTY_FUNCTION__") == 0)
2260 assert(asprintf(&mangled_name
, "%s<%s>", basename
,
2261 (char *)ss
->contents
.data
+ sym
->value
) >= 0);
2263 assert(asprintf(&mangled_name
, "%s<%s>", basename
,
2264 find_caller(ss
, sym
)) >= 0);
2265 return mangled_name
;
2268 static char *symbol_label(struct superbfd
*sbfd
, asymbol
*sym
)
2270 const char *filename
= sbfd
->abfd
->filename
;
2271 char *c
= strstr(filename
, ".KSPLICE");
2272 int flen
= (c
== NULL
? strlen(filename
) : c
- filename
);
2275 if (bfd_is_und_section(sym
->section
) || (sym
->flags
& BSF_GLOBAL
) != 0) {
2276 label
= strdup(sym
->name
);
2277 } else if (bfd_is_const_section(sym
->section
)) {
2278 assert(asprintf(&label
, "%s<%.*s>",
2279 sym
->name
, flen
, filename
) >= 0);
2281 asymbol
*gsym
= canonical_symbol(sbfd
, sym
);
2284 assert(asprintf(&label
, "%s+%lx<%.*s>",
2286 (unsigned long)sym
->value
,
2287 flen
, filename
) >= 0);
2288 else if ((gsym
->flags
& BSF_GLOBAL
) != 0)
2289 label
= strdup(gsym
->name
);
2290 else if (static_local_symbol(sbfd
, gsym
))
2291 assert(asprintf(&label
, "%s+%lx<%.*s>",
2292 static_local_symbol(sbfd
, gsym
),
2293 (unsigned long)sym
->value
,
2294 flen
, filename
) >= 0);
2296 assert(asprintf(&label
, "%s<%.*s>",
2297 gsym
->name
, flen
, filename
) >= 0);
2303 static struct span
*new_span(struct supersect
*ss
, bfd_vma start
, bfd_vma size
)
2305 struct span
*span
= vec_grow(&ss
->spans
, 1);
2307 span
->start
= start
;
2312 asymbol
**symp
= symbolp_scan(ss
, span
->start
);
2314 span
->symbol
= *symp
;
2315 span
->label
= label_lookup(ss
->parent
, span
->symbol
);
2317 span
->symbol
= NULL
;
2318 const char *label
= label_lookup(ss
->parent
, ss
->symbol
);
2319 if (span
->start
!= 0) {
2321 assert(asprintf(&buf
, "%s<span:%lx>", label
,
2322 (unsigned long)span
->start
) >= 0);
2325 span
->label
= label
;
2331 static void initialize_string_spans(struct supersect
*ss
)
2334 for (str
= ss
->contents
.data
;
2335 (void *)str
< ss
->contents
.data
+ ss
->contents
.size
;) {
2336 bfd_vma start
= (unsigned long)str
-
2337 (unsigned long)ss
->contents
.data
;
2338 bfd_vma size
= strlen(str
) + 1;
2339 while ((start
+ size
) % (1 << ss
->alignment
) != 0 &&
2340 start
+ size
< ss
->contents
.size
) {
2341 if (str
[size
] != '\0')
2345 new_span(ss
, start
, size
);
2350 static void initialize_spans(struct superbfd
*sbfd
)
2353 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
2354 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
2355 if (ss
->type
== SS_TYPE_STRING
)
2356 initialize_string_spans(ss
);
2357 else if (!mode("keep") || (ss
->type
!= SS_TYPE_SPECIAL
&&
2358 ss
->type
!= SS_TYPE_EXPORT
))
2359 new_span(ss
, 0, ss
->contents
.size
);
2363 struct span
*reloc_target_span(struct supersect
*ss
, arelent
*reloc
)
2365 asymbol
*sym_ptr
= *reloc
->sym_ptr_ptr
;
2366 if (bfd_is_const_section(sym_ptr
->section
))
2369 bfd_vma addend
= get_reloc_offset(ss
, reloc
, true) + sym_ptr
->value
;
2370 struct supersect
*sym_ss
=
2371 fetch_supersect(ss
->parent
, sym_ptr
->section
);
2372 struct span
*span
, *target_span
= sym_ss
->spans
.data
;
2373 for (span
= sym_ss
->spans
.data
;
2374 span
< sym_ss
->spans
.data
+ sym_ss
->spans
.size
; span
++) {
2375 if (addend
>= span
->start
&& addend
< span
->start
+ span
->size
)
2381 struct span
*reloc_address_span(struct supersect
*ss
, arelent
*reloc
)
2384 for (span
= ss
->spans
.data
; span
< ss
->spans
.data
+ ss
->spans
.size
;
2386 if (reloc
->address
>= span
->start
&&
2387 reloc
->address
< span
->start
+ span
->size
)
2393 void compute_span_shifts(struct superbfd
*sbfd
)
2397 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
2398 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
2401 bfd_size_type offset
= 0;
2402 for (span
= ss
->spans
.data
;
2403 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++) {
2406 span
->shift
= offset
- span
->start
;
2407 offset
+= span
->size
;
2412 void remove_unkept_spans(struct superbfd
*sbfd
)
2416 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
2417 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
2418 struct arelentp_vec orig_relocs
;
2419 vec_move(&orig_relocs
, &ss
->relocs
);
2420 arelent
**relocp
, *reloc
;
2421 for (relocp
= orig_relocs
.data
;
2422 relocp
< orig_relocs
.data
+ orig_relocs
.size
; relocp
++) {
2424 asymbol
*sym
= *reloc
->sym_ptr_ptr
;
2425 span
= reloc_target_span(ss
, reloc
);
2426 if ((span
!= NULL
&& span
->keep
&& span
->shift
== 0) ||
2427 bfd_is_const_section(sym
->section
)) {
2428 *vec_grow(&ss
->relocs
, 1) = reloc
;
2431 if (span
!= NULL
&& span
->keep
) {
2432 arelent
*new_reloc
= malloc(sizeof(*new_reloc
));
2433 *new_reloc
= *reloc
;
2435 get_reloc_offset(ss
, reloc
, false);
2436 new_reloc
->addend
+= span
->shift
;
2437 *vec_grow(&ss
->new_relocs
, 1) = new_reloc
;
2442 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
2443 struct supersect
*ss
= fetch_supersect(sbfd
, sect
), orig_ss
;
2446 supersect_move(&orig_ss
, ss
);
2447 vec_init(&ss
->spans
);
2448 for (span
= orig_ss
.spans
.data
;
2449 span
< orig_ss
.spans
.data
+ orig_ss
.spans
.size
; span
++) {
2452 struct span
*new_span
= vec_grow(&ss
->spans
, 1);
2454 new_span
->start
= span
->start
+ span
->shift
;
2455 new_span
->shift
= 0;
2456 sect_copy(ss
, sect_do_grow(ss
, 1, span
->size
, 1),
2457 &orig_ss
, orig_ss
.contents
.data
+ span
->start
,