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
))
1070 if (strcmp(sym_ptr
->name
, "mcount") == 0 &&
1071 bfd_is_und_section(sym_ptr
->section
))
1075 write_ksplice_reloc(ss
, *relocp
);
1077 *vec_grow(&ss
->relocs
, 1) = *relocp
;
1081 struct supersect
*make_section(struct superbfd
*sbfd
, const char *name
)
1083 asection
*sect
= bfd_get_section_by_name(sbfd
->abfd
, name
);
1085 return fetch_supersect(sbfd
, sect
);
1087 return new_supersect(sbfd
, name
);
1090 arelent
*create_reloc(struct supersect
*ss
, const void *addr
, asymbol
**symp
,
1093 bfd_reloc_code_real_type code
;
1094 switch (bfd_arch_bits_per_address(ss
->parent
->abfd
)) {
1096 code
= BFD_RELOC_32
;
1099 code
= BFD_RELOC_64
;
1105 arelent
*reloc
= malloc(sizeof(*reloc
));
1106 reloc
->sym_ptr_ptr
= symp
;
1107 reloc
->address
= addr_offset(ss
, addr
);
1108 reloc
->howto
= bfd_reloc_type_lookup(ss
->parent
->abfd
, code
);
1109 reloc
->addend
= offset
;
1113 void write_reloc(struct supersect
*ss
, const void *addr
, asymbol
**symp
,
1116 *vec_grow(&ss
->new_relocs
, 1) = create_reloc(ss
, addr
, symp
, offset
);
1119 void write_string(struct supersect
*ss
, const char **addr
, const char *fmt
, ...)
1122 struct supersect
*str_ss
= make_section(ss
->parent
, ".ksplice_str");
1125 int len
= vasprintf(&str
, fmt
, ap
);
1129 unsigned long *str_offp
= ulong_hash_lookup(&ksplice_string_offset
, str
,
1131 if (str_offp
== NULL
) {
1132 char *buf
= sect_grow(str_ss
, len
+ 1, char);
1133 memcpy(buf
, str
, len
+ 1);
1134 str_offp
= ulong_hash_lookup(&ksplice_string_offset
, str
, TRUE
);
1135 *str_offp
= addr_offset(str_ss
, buf
);
1138 write_reloc(ss
, addr
, &str_ss
->symbol
, *str_offp
);
1141 void lookup_system_map(struct addr_vec
*addrs
, const char *name
, long offset
)
1143 struct addr_vec
*map_addrs
=
1144 addr_vec_hash_lookup(&system_map
, name
, FALSE
);
1145 if (map_addrs
== NULL
)
1148 unsigned long *addr
, *map_addr
;
1149 for (map_addr
= map_addrs
->data
;
1150 map_addr
< map_addrs
->data
+ map_addrs
->size
; map_addr
++) {
1151 for (addr
= addrs
->data
; addr
< addrs
->data
+ addrs
->size
;
1153 if (*addr
== *map_addr
+ offset
)
1156 if (addr
< addrs
->data
+ addrs
->size
)
1158 *vec_grow(addrs
, 1) = *map_addr
+ offset
;
1162 void write_system_map_array(struct superbfd
*sbfd
, struct supersect
*ss
,
1163 const unsigned long **sym_addrs
,
1164 unsigned long *num_sym_addrs
, asymbol
*sym
)
1166 struct addr_vec addrs
;
1169 if (bfd_is_abs_section(sym
->section
)) {
1170 *vec_grow(&addrs
, 1) = sym
->value
;
1171 } else if (bfd_is_und_section(sym
->section
)) {
1172 lookup_system_map(&addrs
, sym
->name
, 0);
1173 } else if (!bfd_is_const_section(sym
->section
)) {
1175 for (gsymp
= sbfd
->syms
.data
;
1176 gsymp
< sbfd
->syms
.data
+ sbfd
->syms
.size
; gsymp
++) {
1177 asymbol
*gsym
= *gsymp
;
1178 if ((gsym
->flags
& BSF_DEBUGGING
) == 0 &&
1179 gsym
->section
== sym
->section
)
1180 lookup_system_map(&addrs
, gsym
->name
,
1181 sym
->value
- gsym
->value
);
1185 *num_sym_addrs
= addrs
.size
;
1186 if (addrs
.size
!= 0) {
1187 struct supersect
*array_ss
= make_section(sbfd
,
1189 void *buf
= sect_grow(array_ss
, addrs
.size
,
1190 typeof(*addrs
.data
));
1191 memcpy(buf
, addrs
.data
, addrs
.size
* sizeof(*addrs
.data
));
1192 write_reloc(ss
, sym_addrs
, &array_ss
->symbol
,
1193 addr_offset(array_ss
, buf
));
1201 void write_ksplice_system_map(struct superbfd
*sbfd
, asymbol
*sym
,
1202 const char *addstr_sect
)
1204 struct supersect
*smap_ss
= make_section(sbfd
, ".ksplice_system_map");
1205 struct ksplice_system_map
*smap
;
1206 const char *label
= label_lookup(sbfd
, sym
);
1208 bool *done
= bool_hash_lookup(&system_map_written
, label
, TRUE
);
1213 smap
= sect_grow(smap_ss
, 1, struct ksplice_system_map
);
1215 write_system_map_array(sbfd
, smap_ss
, &smap
->candidates
,
1216 &smap
->nr_candidates
, sym
);
1217 write_string(smap_ss
, &smap
->label
, "%s%s", label
, addstr_sect
);
1220 void write_ksplice_symbol(struct supersect
*ss
,
1221 const struct ksplice_symbol
*const *addr
,
1222 asymbol
*sym
, struct span
*span
,
1223 const char *addstr_sect
)
1225 struct supersect
*ksymbol_ss
= make_section(ss
->parent
,
1226 ".ksplice_symbols");
1227 struct ksplice_symbol
*ksymbol
;
1228 unsigned long *ksymbol_offp
;
1231 if (span
!= NULL
&& span
->start
!= 0)
1232 label
= span
->label
;
1234 label
= label_lookup(ss
->parent
, sym
);
1235 assert(asprintf(&output
, "%s%s", label
, addstr_sect
) >= 0);
1237 ksymbol_offp
= ulong_hash_lookup(&ksplice_symbol_offset
, output
, FALSE
);
1238 if (ksymbol_offp
!= NULL
) {
1239 write_reloc(ss
, addr
, &ksymbol_ss
->symbol
, *ksymbol_offp
);
1242 ksymbol
= sect_grow(ksymbol_ss
, 1, struct ksplice_symbol
);
1243 ksymbol_offp
= ulong_hash_lookup(&ksplice_symbol_offset
, output
, TRUE
);
1244 *ksymbol_offp
= addr_offset(ksymbol_ss
, ksymbol
);
1246 write_reloc(ss
, addr
, &ksymbol_ss
->symbol
, *ksymbol_offp
);
1247 write_string(ksymbol_ss
, &ksymbol
->label
, "%s", output
);
1249 if (span
!= NULL
&& span
->symbol
== NULL
) {
1250 ksymbol
->name
= NULL
;
1254 write_ksplice_system_map(ksymbol_ss
->parent
, sym
, addstr_sect
);
1256 if (bfd_is_und_section(sym
->section
) || (sym
->flags
& BSF_GLOBAL
) != 0) {
1257 write_string(ksymbol_ss
, &ksymbol
->name
, "%s", sym
->name
);
1258 } else if (bfd_is_const_section(sym
->section
)) {
1259 ksymbol
->name
= NULL
;
1261 asymbol
*gsym
= canonical_symbol(ss
->parent
, sym
);
1263 if (gsym
== NULL
|| (gsym
->flags
& BSF_SECTION_SYM
) != 0)
1264 ksymbol
->name
= NULL
;
1266 write_string(ksymbol_ss
, &ksymbol
->name
, "%s",
1271 void write_ksplice_reloc(struct supersect
*ss
, arelent
*orig_reloc
)
1273 asymbol
*sym_ptr
= *orig_reloc
->sym_ptr_ptr
;
1274 reloc_howto_type
*howto
= orig_reloc
->howto
;
1275 bfd_vma addend
= get_reloc_offset(ss
, orig_reloc
, false);
1277 if (mode("finalize") && starts_with(ss
->name
, ".ksplice_patches")) {
1278 unsigned long *repladdr
=
1279 ss
->contents
.data
+ orig_reloc
->address
;
1284 struct span
*span
= reloc_target_span(ss
, orig_reloc
);
1285 if (span
== ss
->spans
.data
&& span
->start
!= addend
)
1287 blot_section(ss
, orig_reloc
->address
, howto
);
1289 struct supersect
*kreloc_ss
= make_section(ss
->parent
,
1291 ".ksplice_init_relocs" :
1293 struct ksplice_reloc
*kreloc
= sect_grow(kreloc_ss
, 1,
1294 struct ksplice_reloc
);
1296 struct span
*address_span
= reloc_address_span(ss
, orig_reloc
);
1297 write_reloc(kreloc_ss
, &kreloc
->blank_addr
,
1298 &ss
->symbol
, orig_reloc
->address
+ address_span
->shift
);
1299 write_ksplice_symbol(kreloc_ss
, &kreloc
->symbol
, sym_ptr
, span
, "");
1300 kreloc
->pcrel
= howto
->pc_relative
;
1301 if (span
!= NULL
&& span
->start
!= 0)
1302 addend
+= sym_ptr
->value
- span
->start
;
1303 kreloc
->addend
= addend
;
1304 kreloc
->size
= bfd_get_reloc_size(howto
);
1305 kreloc
->dst_mask
= howto
->dst_mask
;
1306 kreloc
->rightshift
= howto
->rightshift
;
1307 kreloc
->signed_addend
=
1308 (howto
->complain_on_overflow
== complain_overflow_signed
) ||
1309 (howto
->complain_on_overflow
== complain_overflow_bitfield
);
1312 #define CANARY(x, canary) ((x & ~howto->dst_mask) | (canary & howto->dst_mask))
1314 void blot_section(struct supersect
*ss
, int offset
, reloc_howto_type
*howto
)
1316 int bits
= bfd_get_reloc_size(howto
) * 8;
1317 void *address
= ss
->contents
.data
+ offset
;
1318 bfd_vma x
= bfd_get(bits
, ss
->parent
->abfd
, address
);
1319 x
= (x
& ~howto
->dst_mask
) |
1320 ((bfd_vma
)KSPLICE_CANARY
& howto
->dst_mask
);
1321 bfd_put(bits
, ss
->parent
->abfd
, x
, address
);
1324 static void write_ksplice_section(struct span
*span
)
1326 struct supersect
*ss
= span
->ss
;
1327 struct supersect
*ksect_ss
=
1328 make_section(ss
->parent
, ".ksplice_sections");
1329 struct ksplice_section
*ksect
= sect_grow(ksect_ss
, 1,
1330 struct ksplice_section
);
1331 asymbol
*sym
= span
->symbol
== NULL
? ss
->symbol
: span
->symbol
;
1333 write_ksplice_symbol(ksect_ss
, &ksect
->symbol
, sym
, span
,
1334 mode("keep-primary") ? "(post)" : "");
1335 ksect
->size
= span
->size
;
1338 if (ss
->type
== SS_TYPE_RODATA
|| ss
->type
== SS_TYPE_STRING
)
1339 ksect
->flags
|= KSPLICE_SECTION_RODATA
;
1340 if (ss
->type
== SS_TYPE_DATA
)
1341 ksect
->flags
|= KSPLICE_SECTION_DATA
;
1342 if (ss
->type
== SS_TYPE_TEXT
)
1343 ksect
->flags
|= KSPLICE_SECTION_TEXT
;
1344 assert(ksect
->flags
!= 0);
1345 write_reloc(ksect_ss
, &ksect
->address
, &ss
->symbol
,
1346 span
->start
+ span
->shift
);
1349 void write_ksplice_patch(struct superbfd
*sbfd
, const char *sectname
)
1351 struct supersect
*kpatch_ss
= make_section(sbfd
, ".ksplice_patches");
1352 struct ksplice_patch
*kpatch
= sect_grow(kpatch_ss
, 1,
1353 struct ksplice_patch
);
1354 asection
*sect
= bfd_get_section_by_name(sbfd
->abfd
, sectname
);
1355 assert(sect
!= NULL
);
1357 write_string(kpatch_ss
, &kpatch
->label
, "%s",
1358 label_lookup(sbfd
, sect
->symbol
));
1359 write_reloc(kpatch_ss
, &kpatch
->repladdr
, §
->symbol
, 0);
1362 void write_ksplice_deleted_patch(struct superbfd
*sbfd
, const char *name
,
1365 struct supersect
*kpatch_ss
= make_section(sbfd
, ".ksplice_patches");
1366 struct ksplice_patch
*kpatch
= sect_grow(kpatch_ss
, 1,
1367 struct ksplice_patch
);
1369 write_string(kpatch_ss
, &kpatch
->label
, "%s", label
);
1371 for (symp
= sbfd
->syms
.data
; symp
< sbfd
->syms
.data
+ sbfd
->syms
.size
;
1373 asymbol
*sym
= *symp
;
1374 if (bfd_is_und_section(sym
->section
) &&
1375 strcmp(name
, sym
->name
) == 0)
1378 if (symp
>= sbfd
->syms
.data
+ sbfd
->syms
.size
) {
1379 symp
= malloc(sizeof(*symp
));
1380 *symp
= bfd_make_empty_symbol(sbfd
->abfd
);
1381 asymbol
*sym
= *symp
;
1382 sym
->name
= strdup(name
);
1383 sym
->section
= bfd_und_section_ptr
;
1386 *vec_grow(&sbfd
->new_syms
, 1) = symp
;
1388 write_reloc(kpatch_ss
, &kpatch
->repladdr
, symp
, 0);
1391 void write_ksplice_export(struct superbfd
*sbfd
, const char *symname
,
1392 const char *export_type
, bool del
)
1394 struct supersect
*export_ss
= make_section(sbfd
, ".ksplice_exports");
1395 struct ksplice_export
*exp
= sect_grow(export_ss
, 1,
1396 struct ksplice_export
);
1399 write_string(export_ss
, &exp
->name
, "%s", symname
);
1400 write_string(export_ss
, &exp
->new_name
, "DISABLED_%s_%s",
1403 write_string(export_ss
, &exp
->new_name
, "%s", symname
);
1404 write_string(export_ss
, &exp
->name
, "DISABLED_%s_%s", symname
,
1409 struct fixup_entry
{
1413 DECLARE_VEC_TYPE(struct fixup_entry
, fixup_entry_vec
);
1415 int compare_fixups(const void *aptr
, const void *bptr
)
1417 const struct fixup_entry
*a
= aptr
, *b
= bptr
;
1418 if (a
->offset
< b
->offset
)
1420 else if (a
->offset
> b
->offset
)
1423 return (int)a
->used
- (int)b
->used
;
1426 void filter_table_sections(struct superbfd
*isbfd
)
1428 struct supersect
*tables_ss
=
1429 fetch_supersect(offsets_sbfd
,
1430 bfd_get_section_by_name(offsets_sbfd
->abfd
,
1431 ".ksplice_table_sections"));
1432 const struct table_section
*ts
;
1433 for (ts
= tables_ss
->contents
.data
;
1434 (void *)ts
< tables_ss
->contents
.data
+ tables_ss
->contents
.size
;
1436 struct table_section s
= *ts
;
1437 s
.sect
= read_string(tables_ss
, &ts
->sect
);
1438 s
.other_sect
= read_string(tables_ss
, &ts
->other_sect
);
1439 filter_table_section(isbfd
, &s
);
1443 void filter_table_section(struct superbfd
*sbfd
, const struct table_section
*s
)
1445 asection
*isection
= bfd_get_section_by_name(sbfd
->abfd
, s
->sect
);
1446 if (isection
== NULL
)
1448 asection
*fixup_sect
= NULL
;
1449 if (s
->other_sect
!= NULL
)
1450 fixup_sect
= bfd_get_section_by_name(sbfd
->abfd
, s
->other_sect
);
1452 struct supersect
*ss
= fetch_supersect(sbfd
, isection
);
1453 if (ss
->alignment
< ffs(s
->entry_align
) - 1)
1454 ss
->alignment
= ffs(s
->entry_align
) - 1;
1456 struct supersect
*fixup_ss
= NULL
;
1457 if (fixup_sect
!= NULL
)
1458 fixup_ss
= fetch_supersect(sbfd
, fixup_sect
);
1460 struct fixup_entry_vec fixups
;
1464 for (entry
= ss
->contents
.data
;
1465 entry
< ss
->contents
.data
+ ss
->contents
.size
;
1466 entry
+= s
->entry_size
) {
1467 asymbol
*sym
, *fixup_sym
;
1468 read_reloc(ss
, entry
+ s
->addr_offset
, sizeof(void *), &sym
);
1470 struct span
*span
= new_span(ss
, addr_offset(ss
, entry
),
1472 struct supersect
*sym_ss
= fetch_supersect(sbfd
, sym
->section
);
1473 span
->keep
= sym_ss
->keep
;
1475 struct fixup_entry
*f
;
1476 if (fixup_sect
!= NULL
) {
1477 bfd_vma fixup_offset
=
1478 read_reloc(ss
, entry
+ s
->other_offset
,
1479 sizeof(void *), &fixup_sym
);
1480 if (fixup_sym
->section
== fixup_sect
) {
1481 assert(fixup_offset
< fixup_ss
->contents
.size
);
1482 f
= vec_grow(&fixups
, 1);
1483 f
->offset
= fixup_offset
;
1484 f
->used
= span
->keep
;
1489 if (fixup_sect
== NULL
)
1492 qsort(fixups
.data
, fixups
.size
, sizeof(*fixups
.data
), compare_fixups
);
1493 *vec_grow(&fixups
, 1) = (struct fixup_entry
)
1494 { .offset
= fixup_ss
->contents
.size
, .used
= false };
1496 struct fixup_entry
*f
;
1497 for (f
= fixups
.data
; f
< fixups
.data
+ fixups
.size
- 1; f
++) {
1498 struct span
*span
= new_span(fixup_ss
, f
->offset
,
1499 (f
+ 1)->offset
- f
->offset
);
1500 span
->keep
= f
->used
;
1504 void keep_referenced_sections(struct superbfd
*sbfd
)
1507 struct supersect
*ss
, *sym_ss
;
1508 struct span
*address_span
, *target_span
;
1509 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
1510 ss
= fetch_supersect(sbfd
, sect
);
1512 if (ss
->type
== SS_TYPE_SPECIAL
|| ss
->type
== SS_TYPE_EXPORT
)
1514 for (relocp
= ss
->relocs
.data
;
1515 relocp
< ss
->relocs
.data
+ ss
->relocs
.size
; relocp
++) {
1516 asymbol
*sym
= *(*relocp
)->sym_ptr_ptr
;
1517 address_span
= reloc_address_span(ss
, *relocp
);
1518 if (!address_span
->keep
)
1520 target_span
= reloc_target_span(ss
, *relocp
);
1521 if (target_span
== NULL
|| target_span
->keep
)
1523 sym_ss
= fetch_supersect(sbfd
, sym
->section
);
1524 if (sym_ss
->type
== SS_TYPE_IGNORED
)
1526 target_span
->keep
= true;
1527 sym_ss
->keep
= true;
1533 void copy_symbols(struct asymbolp_vec
*osyms
, struct asymbolpp_vec
*isyms
)
1536 for (sympp
= isyms
->data
; sympp
< isyms
->data
+ isyms
->size
; sympp
++)
1537 *vec_grow(osyms
, 1) = **sympp
;
1540 /* Modified function from GNU Binutils objcopy.c */
1541 bfd_boolean
copy_object(bfd
*ibfd
, bfd
*obfd
)
1543 assert(bfd_set_format(obfd
, bfd_get_format(ibfd
)));
1545 bfd_vma start
= bfd_get_start_address(ibfd
);
1547 flagword flags
= bfd_get_file_flags(ibfd
);
1548 flags
&= bfd_applicable_file_flags(obfd
);
1550 assert(bfd_set_start_address(obfd
, start
)
1551 && bfd_set_file_flags(obfd
, flags
));
1553 enum bfd_architecture iarch
= bfd_get_arch(ibfd
);
1554 unsigned int imach
= bfd_get_mach(ibfd
);
1555 assert(bfd_set_arch_mach(obfd
, iarch
, imach
));
1556 assert(bfd_set_format(obfd
, bfd_get_format(ibfd
)));
1558 /* BFD mandates that all output sections be created and sizes set before
1559 any output is done. Thus, we traverse all sections multiple times. */
1560 bfd_map_over_sections(ibfd
, setup_section
, obfd
);
1562 struct supersect
*new_supersects
= fetch_superbfd(ibfd
)->new_supersects
;
1563 struct supersect
*ss
;
1564 for (ss
= new_supersects
; ss
!= NULL
; ss
= ss
->next
)
1565 setup_new_section(obfd
, ss
);
1567 /* Mark symbols used in output relocations so that they
1568 are kept, even if they are local labels or static symbols.
1570 Note we iterate over the input sections examining their
1571 relocations since the relocations for the output sections
1572 haven't been set yet. mark_symbols_used_in_relocations will
1573 ignore input sections which have no corresponding output
1576 bfd_map_over_sections(ibfd
, mark_symbols_used_in_relocations
, NULL
);
1577 for (ss
= new_supersects
; ss
!= NULL
; ss
= ss
->next
)
1578 ss_mark_symbols_used_in_relocations(ss
);
1579 struct asymbolp_vec osyms
;
1581 filter_symbols(ibfd
, obfd
, &osyms
, &fetch_superbfd(ibfd
)->syms
);
1582 copy_symbols(&osyms
, &fetch_superbfd(ibfd
)->new_syms
);
1584 bfd_set_symtab(obfd
, osyms
.data
, osyms
.size
);
1586 /* This has to happen after the symbol table has been set. */
1587 bfd_map_over_sections(obfd
, write_section
, NULL
);
1589 /* Allow the BFD backend to copy any private data it understands
1590 from the input BFD to the output BFD. This is done last to
1591 permit the routine to look at the filtered symbol table, which is
1592 important for the ECOFF code at least. */
1593 assert(bfd_copy_private_bfd_data(ibfd
, obfd
));
1598 /* Modified function from GNU Binutils objcopy.c */
1599 void setup_section(bfd
*ibfd
, asection
*isection
, void *obfdarg
)
1601 struct superbfd
*isbfd
= fetch_superbfd(ibfd
);
1602 struct supersect
*ss
= fetch_supersect(isbfd
, isection
);
1603 bfd
*obfd
= obfdarg
;
1609 asection
*osection
= bfd_make_section_anyway(obfd
, isection
->name
);
1610 assert(osection
!= NULL
);
1612 osection
->userdata
= ss
;
1613 bfd_set_section_flags(obfd
, osection
, ss
->flags
);
1614 ss
->symbol
= osection
->symbol
;
1615 assert(bfd_set_section_size(obfd
, osection
, ss
->contents
.size
));
1617 vma
= bfd_section_vma(ibfd
, isection
);
1618 assert(bfd_set_section_vma(obfd
, osection
, vma
));
1620 osection
->lma
= isection
->lma
;
1621 assert(bfd_set_section_alignment(obfd
, osection
, ss
->alignment
));
1622 osection
->entsize
= isection
->entsize
;
1623 osection
->output_section
= osection
;
1624 osection
->output_offset
= 0;
1625 isection
->output_section
= osection
;
1626 isection
->output_offset
= 0;
1630 void setup_new_section(bfd
*obfd
, struct supersect
*ss
)
1632 asection
*osection
= bfd_make_section_anyway(obfd
, ss
->name
);
1633 assert(osection
!= NULL
);
1634 bfd_set_section_flags(obfd
, osection
, ss
->flags
);
1636 osection
->userdata
= ss
;
1637 ss
->symbol
= osection
->symbol
;
1638 assert(bfd_set_section_size(obfd
, osection
, ss
->contents
.size
));
1639 assert(bfd_set_section_vma(obfd
, osection
, 0));
1642 assert(bfd_set_section_alignment(obfd
, osection
, ss
->alignment
));
1643 osection
->entsize
= 0;
1644 osection
->output_section
= osection
;
1645 osection
->output_offset
= 0;
1648 static int compare_reloc_addresses(const void *aptr
, const void *bptr
)
1650 const arelent
*const *a
= aptr
, *const *b
= bptr
;
1651 return (*a
)->address
- (*b
)->address
;
1654 static void delete_obsolete_relocs(struct supersect
*ss
)
1656 if (ss
->new_relocs
.size
== 0)
1659 qsort(ss
->relocs
.data
, ss
->relocs
.size
, sizeof(*ss
->relocs
.data
),
1660 compare_reloc_addresses
);
1661 qsort(ss
->new_relocs
.data
, ss
->new_relocs
.size
,
1662 sizeof(*ss
->new_relocs
.data
), compare_reloc_addresses
);
1664 struct arelentp_vec orig_relocs
;
1665 vec_move(&orig_relocs
, &ss
->relocs
);
1667 arelent
**relocp
, **new_relocp
= ss
->new_relocs
.data
;
1668 for (relocp
= orig_relocs
.data
;
1669 relocp
< orig_relocs
.data
+ orig_relocs
.size
; relocp
++) {
1670 while (new_relocp
< ss
->new_relocs
.data
+ ss
->new_relocs
.size
&&
1671 (*new_relocp
)->address
< (*relocp
)->address
)
1673 arelent
*reloc
= *relocp
, *new_reloc
= *new_relocp
;
1674 if (new_relocp
== ss
->new_relocs
.data
+ ss
->new_relocs
.size
||
1675 reloc
->address
!= new_reloc
->address
)
1676 *vec_grow(&ss
->relocs
, 1) = reloc
;
1680 void write_section(bfd
*obfd
, asection
*osection
, void *arg
)
1682 struct supersect
*ss
= osection
->userdata
;
1684 if ((ss
->flags
& SEC_GROUP
) != 0 || ss
->contents
.size
== 0)
1687 delete_obsolete_relocs(ss
);
1690 char *error_message
;
1691 for (relocp
= ss
->new_relocs
.data
;
1692 relocp
< ss
->new_relocs
.data
+ ss
->new_relocs
.size
; relocp
++) {
1694 if (bfd_get_arch(obfd
) == bfd_arch_arm
)
1695 val
= osection
->use_rela_p
? 0 : (*relocp
)->addend
;
1698 bfd_put(bfd_get_reloc_size((*relocp
)->howto
) * 8, obfd
, val
,
1699 ss
->contents
.data
+ (*relocp
)->address
);
1700 if (bfd_install_relocation(obfd
, *relocp
, ss
->contents
.data
,
1701 0, osection
, &error_message
) !=
1703 err(ss
->parent
, "ksplice: error installing reloc: %s",
1708 memcpy(vec_grow(&ss
->relocs
, ss
->new_relocs
.size
), ss
->new_relocs
.data
,
1709 ss
->new_relocs
.size
* sizeof(*ss
->new_relocs
.data
));
1711 bfd_set_reloc(obfd
, osection
,
1712 ss
->relocs
.size
== 0 ? NULL
: ss
->relocs
.data
,
1715 if (ss
->flags
& SEC_HAS_CONTENTS
)
1716 assert(bfd_set_section_contents
1717 (obfd
, osection
, ss
->contents
.data
, 0,
1718 ss
->contents
.size
));
1721 /* Modified function from GNU Binutils objcopy.c
1723 * Mark all the symbols which will be used in output relocations with
1724 * the BSF_KEEP flag so that those symbols will not be stripped.
1726 * Ignore relocations which will not appear in the output file.
1728 void mark_symbols_used_in_relocations(bfd
*abfd
, asection
*isection
,
1731 struct superbfd
*sbfd
= fetch_superbfd(abfd
);
1732 if (isection
->output_section
== NULL
)
1735 struct supersect
*ss
= fetch_supersect(sbfd
, isection
);
1736 ss_mark_symbols_used_in_relocations(ss
);
1739 void ss_mark_symbols_used_in_relocations(struct supersect
*ss
)
1741 /* Examine each symbol used in a relocation. If it's not one of the
1742 special bfd section symbols, then mark it with BSF_KEEP. */
1744 for (relocp
= ss
->relocs
.data
;
1745 relocp
< ss
->relocs
.data
+ ss
->relocs
.size
; relocp
++) {
1746 asymbol
*sym
= *(*relocp
)->sym_ptr_ptr
;
1747 if (!(bfd_is_const_section(sym
->section
) &&
1748 sym
== sym
->section
->symbol
))
1749 sym
->flags
|= BSF_KEEP
;
1751 for (relocp
= ss
->new_relocs
.data
;
1752 relocp
< ss
->new_relocs
.data
+ ss
->new_relocs
.size
; relocp
++) {
1753 asymbol
*sym
= *(*relocp
)->sym_ptr_ptr
;
1754 if (!(bfd_is_const_section(sym
->section
) &&
1755 sym
== sym
->section
->symbol
))
1756 sym
->flags
|= BSF_KEEP
;
1760 static bool deleted_table_section_symbol(bfd
*abfd
, asymbol
*sym
)
1762 struct superbfd
*sbfd
= fetch_superbfd(abfd
);
1763 if (bfd_is_const_section(sym
->section
))
1765 struct supersect
*ss
= fetch_supersect(sbfd
, sym
->section
);
1768 for (symp
= ss
->syms
.data
; symp
< ss
->syms
.data
+ ss
->syms
.size
; symp
++) {
1772 return symp
>= ss
->syms
.data
+ ss
->syms
.size
;
1775 /* Modified function from GNU Binutils objcopy.c
1777 * Choose which symbol entries to copy.
1778 * We don't copy in place, because that confuses the relocs.
1779 * Return the number of symbols to print.
1781 void filter_symbols(bfd
*ibfd
, bfd
*obfd
, struct asymbolp_vec
*osyms
,
1782 struct asymbolp_vec
*isyms
)
1785 struct superbfd
*sbfd
= fetch_superbfd(ibfd
);
1786 for (symp
= isyms
->data
; symp
< isyms
->data
+ isyms
->size
; symp
++) {
1787 asymbol
*sym
= *symp
;
1788 struct supersect
*sym_ss
= NULL
;
1789 if (!bfd_is_const_section(sym
->section
))
1790 sym_ss
= fetch_supersect(sbfd
, sym
->section
);
1794 if (mode("keep") && (sym
->flags
& BSF_GLOBAL
) != 0 &&
1795 !(mode("keep-primary") && sym_ss
!= NULL
&& sym_ss
->new))
1796 sym
->flags
= (sym
->flags
& ~BSF_GLOBAL
) | BSF_LOCAL
;
1798 if (mode("finalize") && (sym
->flags
& BSF_GLOBAL
) != 0)
1799 sym
->flags
= (sym
->flags
& ~BSF_GLOBAL
) | BSF_LOCAL
;
1801 if ((sym
->flags
& BSF_KEEP
) != 0 /* Used in relocation. */
1802 || ((sym
->flags
& BSF_SECTION_SYM
) != 0 && sym_ss
!= NULL
&&
1805 else if ((sym
->flags
& (BSF_GLOBAL
| BSF_WEAK
)) != 0 &&
1806 sym_ss
!= NULL
&& sym_ss
->keep
)
1809 if (deleted_table_section_symbol(ibfd
, sym
))
1812 if (bfd_is_com_section(sym
->section
))
1816 keep
= !str_in_set(sym
->name
, &rmsyms
);
1819 if (sym_ss
!= NULL
&& !sym_ss
->keep
) {
1820 err(sbfd
, "Kept symbol %s in unkept section "
1821 "%s\n", sym
->name
, sym
->section
->name
);
1824 *vec_grow(osyms
, 1) = sym
;
1829 void read_str_set(struct str_vec
*strs
)
1833 assert(getline(&buf
, &n
, stdin
) >= 0);
1837 char *str
= strtok_r(buf
, " \n", &saveptr
);
1841 *vec_grow(strs
, 1) = str
;
1845 bool str_in_set(const char *str
, const struct str_vec
*strs
)
1848 for (strp
= strs
->data
; strp
< strs
->data
+ strs
->size
; strp
++) {
1849 if (strcmp(str
, *strp
) == 0)
1855 bool is_table_section(const char *name
, bool consider_other
)
1857 struct supersect
*tables_ss
=
1858 fetch_supersect(offsets_sbfd
,
1859 bfd_get_section_by_name(offsets_sbfd
->abfd
,
1860 ".ksplice_table_sections"));
1861 const struct table_section
*ts
;
1862 for (ts
= tables_ss
->contents
.data
;
1863 (void *)ts
< tables_ss
->contents
.data
+ tables_ss
->contents
.size
;
1865 if (strcmp(name
, read_string(tables_ss
, &ts
->sect
)) == 0)
1867 const char *osect_name
= read_string(tables_ss
,
1869 if (consider_other
&& osect_name
!= NULL
&&
1870 strcmp(name
, osect_name
) == 0)
1876 enum supersect_type
supersect_type(struct supersect
*ss
)
1878 if (starts_with(ss
->name
, ".ksplice"))
1879 return SS_TYPE_KSPLICE
;
1881 if (starts_with(ss
->name
, ".init"))
1882 return SS_TYPE_IGNORED
;
1883 if (starts_with(ss
->name
, ".security_initcall.init"))
1884 return SS_TYPE_IGNORED
;
1885 if (starts_with(ss
->name
, ".con_initcall.init"))
1886 return SS_TYPE_IGNORED
;
1887 if (starts_with(ss
->name
, ".x86cpuvendor.init"))
1888 return SS_TYPE_IGNORED
;
1889 if (starts_with(ss
->name
, ".early_param.init"))
1890 return SS_TYPE_IGNORED
;
1891 if (starts_with(ss
->name
, ".taglist.init"))
1892 return SS_TYPE_IGNORED
;
1893 if (starts_with(ss
->name
, ".arch.info.init"))
1894 return SS_TYPE_IGNORED
;
1895 if (starts_with(ss
->name
, ".proc.info.init"))
1896 return SS_TYPE_IGNORED
;
1897 /* .pci_fixup_* sections really should be treated as global rodata
1898 referenced only from quirks.c */
1899 if (starts_with(ss
->name
, ".pci_fixup_"))
1900 return SS_TYPE_IGNORED
;
1901 /* .builtin_fw sections are similar to .pci_fixup */
1902 if (starts_with(ss
->name
, ".builtin_fw"))
1903 return SS_TYPE_IGNORED
;
1904 /* same for .tracedata */
1905 if (starts_with(ss
->name
, ".tracedata"))
1906 return SS_TYPE_IGNORED
;
1907 if (starts_with(ss
->name
, ".debug"))
1908 return SS_TYPE_IGNORED
;
1909 /* .eh_frame should probably be discarded, not ignored */
1910 if (starts_with(ss
->name
, ".eh_frame"))
1911 return SS_TYPE_IGNORED
;
1912 if (config
->ignore_devinit
&& starts_with(ss
->name
, ".devinit"))
1913 return SS_TYPE_IGNORED
;
1914 if (config
->ignore_meminit
&& starts_with(ss
->name
, ".meminit"))
1915 return SS_TYPE_IGNORED
;
1916 if (config
->ignore_cpuinit
&& starts_with(ss
->name
, ".cpuinit"))
1917 return SS_TYPE_IGNORED
;
1918 if (config
->ignore_devinit
&& starts_with(ss
->name
, ".devexit"))
1919 return SS_TYPE_IGNORED
;
1920 if (config
->ignore_meminit
&& starts_with(ss
->name
, ".memexit"))
1921 return SS_TYPE_IGNORED
;
1922 if (config
->ignore_cpuinit
&& starts_with(ss
->name
, ".cpuexit"))
1923 return SS_TYPE_IGNORED
;
1924 if (starts_with(ss
->name
, ".vgetcpu_mode") ||
1925 starts_with(ss
->name
, ".jiffies") ||
1926 starts_with(ss
->name
, ".wall_jiffies") ||
1927 starts_with(ss
->name
, ".vxtime") ||
1928 starts_with(ss
->name
, ".sys_tz") ||
1929 starts_with(ss
->name
, ".sysctl_vsyscall") ||
1930 starts_with(ss
->name
, ".xtime") ||
1931 starts_with(ss
->name
, ".xtime_lock") ||
1932 starts_with(ss
->name
, ".vsyscall"))
1933 return SS_TYPE_IGNORED
;
1934 if (starts_with(ss
->name
, ".vdso"))
1935 return SS_TYPE_IGNORED
;
1937 if (bfd_get_section_by_name(ss
->parent
->abfd
, ".exitcall.exit") == NULL
) {
1938 if (starts_with(ss
->name
, ".exit.text"))
1939 return SS_TYPE_TEXT
;
1940 if (starts_with(ss
->name
, ".exit.data"))
1941 return SS_TYPE_DATA
;
1942 } else if (starts_with(ss
->name
, ".exit.text") ||
1943 starts_with(ss
->name
, ".exit.data"))
1944 return SS_TYPE_IGNORED
;
1946 if (starts_with(ss
->name
, ".text") ||
1947 starts_with(ss
->name
, ".kernel.text") ||
1948 starts_with(ss
->name
, ".devinit.text") ||
1949 starts_with(ss
->name
, ".meminit.text") ||
1950 starts_with(ss
->name
, ".cpuinit.text") ||
1951 starts_with(ss
->name
, ".devexit.text") ||
1952 starts_with(ss
->name
, ".memexit.text") ||
1953 starts_with(ss
->name
, ".cpuexit.text") ||
1954 starts_with(ss
->name
, ".ref.text") ||
1955 starts_with(ss
->name
, ".spinlock.text") ||
1956 starts_with(ss
->name
, ".kprobes.text") ||
1957 starts_with(ss
->name
, ".sched.text"))
1958 return SS_TYPE_TEXT
;
1961 if (sscanf(ss
->name
, ".rodata.str%*u.%*u%n", &n
) >= 0 &&
1962 n
== strlen(ss
->name
))
1963 return SS_TYPE_STRING
;
1965 if (starts_with(ss
->name
, ".rodata") ||
1966 starts_with(ss
->name
, ".kernel.rodata") ||
1967 starts_with(ss
->name
, ".devinit.rodata") ||
1968 starts_with(ss
->name
, ".meminit.rodata") ||
1969 starts_with(ss
->name
, ".cpuinit.rodata") ||
1970 starts_with(ss
->name
, ".devexit.rodata") ||
1971 starts_with(ss
->name
, ".memexit.rodata") ||
1972 starts_with(ss
->name
, ".cpuexit.rodata") ||
1973 starts_with(ss
->name
, ".ref.rodata") ||
1974 starts_with(ss
->name
, "__markers_strings"))
1975 return SS_TYPE_RODATA
;
1977 if (starts_with(ss
->name
, ".bss"))
1978 return SS_TYPE_DATA
;
1980 /* Ignore .data.percpu sections */
1981 if (starts_with(ss
->name
, ".data.percpu") ||
1982 starts_with(ss
->name
, ".kernel.data.percpu"))
1983 return SS_TYPE_IGNORED
;
1984 if (starts_with(ss
->name
, ".data") ||
1985 starts_with(ss
->name
, ".kernel.data") ||
1986 starts_with(ss
->name
, ".devinit.data") ||
1987 starts_with(ss
->name
, ".cpuinit.data") ||
1988 starts_with(ss
->name
, ".meminit.data") ||
1989 starts_with(ss
->name
, ".devexit.data") ||
1990 starts_with(ss
->name
, ".memexit.data") ||
1991 starts_with(ss
->name
, ".cpuexit.data") ||
1992 starts_with(ss
->name
, ".ref.data") ||
1993 starts_with(ss
->name
, "__markers"))
1994 return SS_TYPE_DATA
;
1996 /* We replace all the ksymtab strings, so delete them */
1997 if (strcmp(ss
->name
, "__ksymtab_strings") == 0)
1998 return SS_TYPE_IGNORED
;
1999 if (starts_with(ss
->name
, "__ksymtab"))
2000 return SS_TYPE_EXPORT
;
2001 if (starts_with(ss
->name
, "__kcrctab"))
2002 return SS_TYPE_EXPORT
;
2004 if (is_table_section(ss
->name
, true))
2005 return SS_TYPE_SPECIAL
;
2007 if (starts_with(ss
->name
, ".ARM."))
2008 return SS_TYPE_SPECIAL
;
2010 if (starts_with(ss
->name
, ".note"))
2011 return SS_TYPE_IGNORED
;
2012 if (starts_with(ss
->name
, ".comment"))
2013 return SS_TYPE_IGNORED
;
2014 if (starts_with(ss
->name
, "__param"))
2015 return SS_TYPE_IGNORED
;
2016 if (starts_with(ss
->name
, ".exitcall.exit"))
2017 return SS_TYPE_IGNORED
;
2018 if (starts_with(ss
->name
, ".modinfo"))
2019 return SS_TYPE_IGNORED
;
2021 return SS_TYPE_UNKNOWN
;
2024 void initialize_supersect_types(struct superbfd
*sbfd
)
2027 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
2028 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
2029 ss
->type
= supersect_type(ss
);
2030 if (ss
->type
== SS_TYPE_UNKNOWN
) {
2031 err(sbfd
, "Unknown section type: %s\n", ss
->name
);
2037 static void init_label_map(struct superbfd
*sbfd
)
2039 struct label_map
*map
;
2041 vec_init(&sbfd
->maps
);
2045 struct symbol_hash csyms
;
2046 symbol_hash_init(&csyms
);
2049 for (symp
= sbfd
->syms
.data
;
2050 symp
< sbfd
->syms
.data
+ sbfd
->syms
.size
; symp
++) {
2051 asymbol
*csym
= canonical_symbol(sbfd
, *symp
);
2055 assert(asprintf(&key
, "%p", csym
) >= 0);
2056 asymbol
**csymp
= symbol_hash_lookup(&csyms
, key
, TRUE
);
2062 map
= vec_grow(&sbfd
->maps
, 1);
2065 map
->label
= symbol_label(sbfd
, csym
);
2068 struct label_mapp_hash label_maps
;
2069 label_mapp_hash_init(&label_maps
);
2070 for (map
= sbfd
->maps
.data
;
2071 map
< sbfd
->maps
.data
+ sbfd
->maps
.size
; map
++) {
2072 struct label_map
**mapp
=
2073 label_mapp_hash_lookup(&label_maps
, map
->label
, TRUE
);
2074 if (*mapp
== NULL
) {
2079 struct label_map
*first_map
= *mapp
;
2081 if (first_map
->count
== 0) {
2082 assert(asprintf(&buf
, "%s~%d", map
->label
, 0) >= 0);
2083 first_map
->label
= buf
;
2086 assert(asprintf(&buf
, "%s~%d", map
->label
, first_map
->count
)
2091 label_mapp_hash_init(&sbfd
->maps_hash
);
2092 for (map
= sbfd
->maps
.data
;
2093 map
< sbfd
->maps
.data
+ sbfd
->maps
.size
; map
++) {
2095 assert(asprintf(&key
, "%p", map
->csym
) >= 0);
2096 struct label_map
**mapp
=
2097 label_mapp_hash_lookup(&sbfd
->maps_hash
, key
, TRUE
);
2100 map
->orig_label
= map
->label
;
2104 static const char *label_lookup(struct superbfd
*sbfd
, asymbol
*sym
)
2106 asymbol
*csym
= canonical_symbol(sbfd
, sym
);
2108 assert(asprintf(&key
, "%p", csym
) >= 0);
2109 struct label_map
**mapp
=
2110 label_mapp_hash_lookup(&sbfd
->maps_hash
, key
, FALSE
);
2114 return (*mapp
)->label
;
2117 static void print_label_map(struct superbfd
*sbfd
)
2119 struct label_map
*map
;
2120 for (map
= sbfd
->maps
.data
;
2121 map
< sbfd
->maps
.data
+ sbfd
->maps
.size
; map
++) {
2122 if (strcmp(map
->orig_label
, map
->label
) == 0)
2124 debug1(sbfd
, "Label change: %s -> %s\n",
2125 map
->label
, map
->orig_label
);
2129 static void label_map_set(struct superbfd
*sbfd
, const char *oldlabel
,
2132 struct label_map
*map
;
2133 for (map
= sbfd
->maps
.data
;
2134 map
< sbfd
->maps
.data
+ sbfd
->maps
.size
; map
++) {
2135 if (strcmp(map
->orig_label
, oldlabel
) == 0) {
2136 if (strcmp(map
->orig_label
, map
->label
) != 0 &&
2137 strcmp(map
->label
, label
) != 0)
2146 static void init_callers(struct superbfd
*sbfd
)
2148 string_hash_init(&sbfd
->callers
);
2150 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
2151 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
2153 for (relocp
= ss
->relocs
.data
;
2154 relocp
< ss
->relocs
.data
+ ss
->relocs
.size
; relocp
++) {
2155 asymbol
*sym
= *(*relocp
)->sym_ptr_ptr
;
2157 sym
->value
+ get_reloc_offset(ss
, *relocp
, true);
2159 assert(asprintf(&key
, "%s+%lx", sym
->section
->name
,
2161 const char **ret
= string_hash_lookup(&sbfd
->callers
,
2167 *ret
= "*multiple_callers*";
2172 static const char *find_caller(struct supersect
*ss
, asymbol
*sym
)
2175 assert(asprintf(&key
, "%s+%lx", sym
->section
->name
,
2176 (unsigned long)sym
->value
) >= 0);
2177 const char **ret
= string_hash_lookup(&ss
->parent
->callers
, key
, FALSE
);
2181 return "*no_caller*";
2185 static void init_csyms(struct superbfd
*sbfd
)
2187 asymbolpp_hash_init(&sbfd
->csyms
);
2190 for (symp
= sbfd
->syms
.data
; symp
< sbfd
->syms
.data
+ sbfd
->syms
.size
;
2192 asymbol
*sym
= *symp
;
2193 if ((sym
->flags
& BSF_DEBUGGING
) != 0)
2196 assert(asprintf(&key
, "%s+%lx", sym
->section
->name
,
2197 (unsigned long)sym
->value
) >= 0);
2198 asymbol
***csympp
= asymbolpp_hash_lookup(&sbfd
->csyms
, key
,
2201 if (*csympp
== NULL
) {
2205 asymbol
*csym
= **csympp
;
2206 if ((csym
->flags
& BSF_GLOBAL
) != 0)
2208 if ((sym
->flags
& BSF_GLOBAL
) != 0)
2213 static asymbol
**symbolp_scan(struct supersect
*ss
, bfd_vma value
)
2216 assert(asprintf(&key
, "%s+%lx", ss
->name
, (unsigned long)value
) >= 0);
2218 asymbolpp_hash_lookup(&ss
->parent
->csyms
, key
, FALSE
);
2223 /* For section symbols of sections containing no symbols, return the
2224 section symbol that relocations are generated against */
2230 static asymbol
**canonical_symbolp(struct superbfd
*sbfd
, asymbol
*sym
)
2232 if (bfd_is_const_section(sym
->section
)) {
2234 for (csymp
= sbfd
->syms
.data
;
2235 csymp
< sbfd
->syms
.data
+ sbfd
->syms
.size
; csymp
++) {
2241 return symbolp_scan(fetch_supersect(sbfd
, sym
->section
), sym
->value
);
2244 static asymbol
*canonical_symbol(struct superbfd
*sbfd
, asymbol
*sym
)
2246 if (bfd_is_const_section(sym
->section
))
2248 asymbol
**symp
= canonical_symbolp(sbfd
, sym
);
2249 return symp
!= NULL
? *symp
: NULL
;
2252 static char *static_local_symbol(struct superbfd
*sbfd
, asymbol
*sym
)
2254 struct supersect
*ss
= fetch_supersect(sbfd
, sym
->section
);
2255 if ((sym
->flags
& BSF_LOCAL
) == 0 || (sym
->flags
& BSF_OBJECT
) == 0)
2257 char *dot
= strrchr(sym
->name
, '.');
2258 if (dot
== NULL
|| dot
[1 + strspn(dot
+ 1, "0123546789")] != '\0')
2260 char *basename
= strndup(sym
->name
, dot
- sym
->name
);
2262 if (strcmp(basename
, "__func__") == 0 ||
2263 strcmp(basename
, "__PRETTY_FUNCTION__") == 0)
2264 assert(asprintf(&mangled_name
, "%s<%s>", basename
,
2265 (char *)ss
->contents
.data
+ sym
->value
) >= 0);
2267 assert(asprintf(&mangled_name
, "%s<%s>", basename
,
2268 find_caller(ss
, sym
)) >= 0);
2269 return mangled_name
;
2272 static char *symbol_label(struct superbfd
*sbfd
, asymbol
*sym
)
2274 const char *filename
= sbfd
->abfd
->filename
;
2275 char *c
= strstr(filename
, ".KSPLICE");
2276 int flen
= (c
== NULL
? strlen(filename
) : c
- filename
);
2279 if (bfd_is_und_section(sym
->section
) || (sym
->flags
& BSF_GLOBAL
) != 0) {
2280 label
= strdup(sym
->name
);
2281 } else if (bfd_is_const_section(sym
->section
)) {
2282 assert(asprintf(&label
, "%s<%.*s>",
2283 sym
->name
, flen
, filename
) >= 0);
2285 asymbol
*gsym
= canonical_symbol(sbfd
, sym
);
2288 assert(asprintf(&label
, "%s+%lx<%.*s>",
2290 (unsigned long)sym
->value
,
2291 flen
, filename
) >= 0);
2292 else if ((gsym
->flags
& BSF_GLOBAL
) != 0)
2293 label
= strdup(gsym
->name
);
2294 else if (static_local_symbol(sbfd
, gsym
))
2295 assert(asprintf(&label
, "%s+%lx<%.*s>",
2296 static_local_symbol(sbfd
, gsym
),
2297 (unsigned long)sym
->value
,
2298 flen
, filename
) >= 0);
2300 assert(asprintf(&label
, "%s<%.*s>",
2301 gsym
->name
, flen
, filename
) >= 0);
2307 static struct span
*new_span(struct supersect
*ss
, bfd_vma start
, bfd_vma size
)
2309 struct span
*span
= vec_grow(&ss
->spans
, 1);
2311 span
->start
= start
;
2316 asymbol
**symp
= symbolp_scan(ss
, span
->start
);
2318 span
->symbol
= *symp
;
2319 span
->label
= label_lookup(ss
->parent
, span
->symbol
);
2321 span
->symbol
= NULL
;
2322 const char *label
= label_lookup(ss
->parent
, ss
->symbol
);
2323 if (span
->start
!= 0) {
2325 assert(asprintf(&buf
, "%s<span:%lx>", label
,
2326 (unsigned long)span
->start
) >= 0);
2329 span
->label
= label
;
2335 static void initialize_string_spans(struct supersect
*ss
)
2338 for (str
= ss
->contents
.data
;
2339 (void *)str
< ss
->contents
.data
+ ss
->contents
.size
;) {
2340 bfd_vma start
= (unsigned long)str
-
2341 (unsigned long)ss
->contents
.data
;
2342 bfd_vma size
= strlen(str
) + 1;
2343 while ((start
+ size
) % (1 << ss
->alignment
) != 0 &&
2344 start
+ size
< ss
->contents
.size
) {
2345 if (str
[size
] != '\0')
2349 new_span(ss
, start
, size
);
2354 static void initialize_spans(struct superbfd
*sbfd
)
2357 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
2358 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
2359 if (ss
->type
== SS_TYPE_STRING
)
2360 initialize_string_spans(ss
);
2361 else if (!mode("keep") || (ss
->type
!= SS_TYPE_SPECIAL
&&
2362 ss
->type
!= SS_TYPE_EXPORT
))
2363 new_span(ss
, 0, ss
->contents
.size
);
2367 struct span
*reloc_target_span(struct supersect
*ss
, arelent
*reloc
)
2369 asymbol
*sym_ptr
= *reloc
->sym_ptr_ptr
;
2370 if (bfd_is_const_section(sym_ptr
->section
))
2373 bfd_vma addend
= get_reloc_offset(ss
, reloc
, true) + sym_ptr
->value
;
2374 struct supersect
*sym_ss
=
2375 fetch_supersect(ss
->parent
, sym_ptr
->section
);
2376 struct span
*span
, *target_span
= sym_ss
->spans
.data
;
2377 for (span
= sym_ss
->spans
.data
;
2378 span
< sym_ss
->spans
.data
+ sym_ss
->spans
.size
; span
++) {
2379 if (addend
>= span
->start
&& addend
< span
->start
+ span
->size
)
2385 struct span
*reloc_address_span(struct supersect
*ss
, arelent
*reloc
)
2388 for (span
= ss
->spans
.data
; span
< ss
->spans
.data
+ ss
->spans
.size
;
2390 if (reloc
->address
>= span
->start
&&
2391 reloc
->address
< span
->start
+ span
->size
)
2397 void compute_span_shifts(struct superbfd
*sbfd
)
2401 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
2402 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
2405 bfd_size_type offset
= 0;
2406 for (span
= ss
->spans
.data
;
2407 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++) {
2410 span
->shift
= offset
- span
->start
;
2411 offset
+= span
->size
;
2416 void remove_unkept_spans(struct superbfd
*sbfd
)
2420 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
2421 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
2422 struct arelentp_vec orig_relocs
;
2423 vec_move(&orig_relocs
, &ss
->relocs
);
2424 arelent
**relocp
, *reloc
;
2425 for (relocp
= orig_relocs
.data
;
2426 relocp
< orig_relocs
.data
+ orig_relocs
.size
; relocp
++) {
2428 asymbol
*sym
= *reloc
->sym_ptr_ptr
;
2429 span
= reloc_target_span(ss
, reloc
);
2430 if ((span
!= NULL
&& span
->keep
&& span
->shift
== 0) ||
2431 bfd_is_const_section(sym
->section
)) {
2432 *vec_grow(&ss
->relocs
, 1) = reloc
;
2435 if (span
!= NULL
&& span
->keep
) {
2436 arelent
*new_reloc
= malloc(sizeof(*new_reloc
));
2437 *new_reloc
= *reloc
;
2439 get_reloc_offset(ss
, reloc
, false);
2440 new_reloc
->addend
+= span
->shift
;
2441 *vec_grow(&ss
->new_relocs
, 1) = new_reloc
;
2446 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
2447 struct supersect
*ss
= fetch_supersect(sbfd
, sect
), orig_ss
;
2450 supersect_move(&orig_ss
, ss
);
2451 vec_init(&ss
->spans
);
2452 for (span
= orig_ss
.spans
.data
;
2453 span
< orig_ss
.spans
.data
+ orig_ss
.spans
.size
; span
++) {
2456 struct span
*new_span
= vec_grow(&ss
->spans
, 1);
2458 new_span
->start
= span
->start
+ span
->shift
;
2459 new_span
->shift
= 0;
2460 sect_copy(ss
, sect_do_grow(ss
, 1, span
->size
, 1),
2461 &orig_ss
, orig_ss
.contents
.data
+ span
->start
,