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
);
83 DECLARE_VEC_TYPE(struct export_desc
, export_desc_vec
);
85 #define bool_init(b) *(b) = false
86 DEFINE_HASH_TYPE(bool, bool_hash
, bool_hash_init
, bool_hash_free
,
87 bool_hash_lookup
, bool_init
);
89 #define ulong_init(x) *(x) = 0
90 DEFINE_HASH_TYPE(unsigned long, ulong_hash
, ulong_hash_init
,
91 ulong_hash_free
, ulong_hash_lookup
, ulong_init
);
93 void do_keep_primary(struct superbfd
*isbfd
, const char *pre
);
94 void do_keep_helper(struct superbfd
*isbfd
);
95 void do_finalize(struct superbfd
*isbfd
);
96 void do_rmsyms(struct superbfd
*isbfd
);
98 struct export_vec
*get_export_syms(struct superbfd
*sbfd
);
99 void compare_exported_symbols(struct superbfd
*oldsbfd
,
100 struct superbfd
*newsbfd
, char *addstr
);
101 bool relocs_equal(struct supersect
*old_ss
, struct supersect
*new_ss
);
102 static bool part_of_reloc(struct supersect
*ss
, unsigned long addr
);
103 static bool nonrelocs_equal(struct supersect
*old_ss
, struct supersect
*new_ss
);
104 static void handle_section_symbol_renames(struct superbfd
*oldsbfd
,
105 struct superbfd
*newsbfd
);
107 enum supersect_type
supersect_type(struct supersect
*ss
);
108 void initialize_supersect_types(struct superbfd
*sbfd
);
109 static void initialize_spans(struct superbfd
*sbfd
);
110 static void initialize_string_spans(struct superbfd
*sbfd
, asection
*sect
);
111 struct span
*reloc_target_span(struct supersect
*ss
, arelent
*reloc
);
112 struct span
*reloc_address_span(struct supersect
*ss
, arelent
*reloc
);
113 void remove_unkept_spans(struct superbfd
*sbfd
);
114 void compute_span_shifts(struct superbfd
*sbfd
);
115 static struct span
*new_span(struct superbfd
*sbfd
, asection
*sect
,
116 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 void write_ksplice_section(struct superbfd
*sbfd
, asymbol
**symp
,
125 void write_ksplice_patch(struct superbfd
*sbfd
, const char *sectname
);
126 void write_ksplice_deleted_patch(struct superbfd
*sbfd
, const char *name
,
128 void filter_table_sections(struct superbfd
*isbfd
);
129 void filter_table_section(struct superbfd
*sbfd
, const struct table_section
*s
);
130 void keep_referenced_sections(struct superbfd
*sbfd
);
131 bfd_boolean
copy_object(bfd
*ibfd
, bfd
*obfd
);
132 void setup_section(bfd
*ibfd
, asection
*isection
, void *obfdarg
);
133 static void setup_new_section(bfd
*obfd
, struct supersect
*ss
);
134 static void write_section(bfd
*obfd
, asection
*osection
, void *arg
);
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_contents(struct superbfd
*oldsbfd
,
158 struct superbfd
*newsbfd
);
159 static void match_sections_by_label(struct superbfd
*oldsbfd
,
160 struct superbfd
*newsbfd
);
161 static void mark_new_sections(struct superbfd
*sbfd
);
162 static void handle_deleted_sections(struct superbfd
*oldsbfd
,
163 struct superbfd
*newsbfd
);
164 static void compare_matched_sections(struct superbfd
*sbfd
);
165 static void update_nonzero_offsets(struct superbfd
*sbfd
);
166 static void handle_nonzero_offset_relocs(struct supersect
*ss
);
168 static const char *label_lookup(struct superbfd
*sbfd
, asymbol
*sym
);
169 static void print_label_map(struct superbfd
*sbfd
);
170 static void label_map_set(struct superbfd
*sbfd
, const char *oldlabel
,
172 static void init_label_map(struct superbfd
*sbfd
);
175 #define debug_(sbfd, level, fmt, ...) \
177 if (verbose >= (level)) \
178 printf("%s: " fmt, (sbfd)->abfd->filename, \
181 #define debug0(sbfd, fmt, ...) debug_(sbfd, 0, fmt, ## __VA_ARGS__)
182 #define debug1(sbfd, fmt, ...) debug_(sbfd, 1, fmt, ## __VA_ARGS__)
183 #define err(sbfd, fmt, ...) \
185 fprintf(stderr, "%s: " fmt, (sbfd)->abfd->filename, \
189 struct str_vec delsects
, rmsyms
;
190 struct export_desc_vec exports
;
193 struct ksplice_config
*config
;
195 const char *modestr
, *kid
;
197 struct superbfd
*offsets_sbfd
= NULL
;
199 #define mode(str) starts_with(modestr, str)
201 DECLARE_VEC_TYPE(unsigned long, addr_vec
);
202 DEFINE_HASH_TYPE(struct addr_vec
, addr_vec_hash
,
203 addr_vec_hash_init
, addr_vec_hash_free
, addr_vec_hash_lookup
,
205 struct addr_vec_hash system_map
;
207 struct bool_hash system_map_written
;
208 struct ulong_hash ksplice_symbol_offset
;
209 struct ulong_hash ksplice_string_offset
;
211 void load_system_map()
213 const char *config_dir
= getenv("KSPLICE_CONFIG_DIR");
216 assert(asprintf(&file
, "%s/System.map", config_dir
) >= 0);
217 FILE *fp
= fopen(file
, "r");
219 addr_vec_hash_init(&system_map
);
223 while (fscanf(fp
, "%lx %c %as\n", &addr
, &type
, &sym
) == 3)
224 *vec_grow(addr_vec_hash_lookup(&system_map
, sym
, TRUE
),
231 char *kmodsrc
= getenv("KSPLICE_KMODSRC"), *offsets_file
;
232 assert(kmodsrc
!= NULL
);
233 assert(asprintf(&offsets_file
, "%s/offsets.o", kmodsrc
) >= 0);
234 bfd
*offsets_bfd
= bfd_openr(offsets_file
, NULL
);
235 assert(offsets_bfd
!= NULL
);
237 assert(bfd_check_format_matches(offsets_bfd
, bfd_object
, &matching
));
238 offsets_sbfd
= fetch_superbfd(offsets_bfd
);
240 asection
*config_sect
= bfd_get_section_by_name(offsets_sbfd
->abfd
,
242 struct supersect
*config_ss
=
243 fetch_supersect(offsets_sbfd
, config_sect
);
245 config
= config_ss
->contents
.data
;
248 bool matchable_data_section(struct supersect
*ss
)
250 if (ss
->type
== SS_TYPE_STRING
)
252 if (ss
->type
== SS_TYPE_RODATA
)
254 if (ss
->type
== SS_TYPE_DATA
&& ss
->relocs
.size
!= 0)
259 bool unchangeable_section(struct supersect
*ss
)
261 if (ss
->type
== SS_TYPE_DATA
)
263 if (ss
->type
== SS_TYPE_IGNORED
&& !starts_with(ss
->name
, ".debug"))
268 int main(int argc
, char *argv
[])
270 if (getenv("KSPLICE_VERBOSE") != NULL
)
271 verbose
= atoi(getenv("KSPLICE_VERBOSE"));
274 bfd
*ibfd
= bfd_openr(argv
[1], NULL
);
278 assert(bfd_check_format_matches(ibfd
, bfd_object
, &matching
));
280 const char *output_target
= bfd_get_target(ibfd
);
281 bfd
*obfd
= bfd_openw(argv
[2], output_target
);
284 struct superbfd
*isbfd
= fetch_superbfd(ibfd
);
285 init_label_map(isbfd
);
287 bool_hash_init(&system_map_written
);
288 ulong_hash_init(&ksplice_symbol_offset
);
289 ulong_hash_init(&ksplice_string_offset
);
292 if (mode("keep-primary")) {
294 do_keep_primary(isbfd
, argv
[4]);
295 } else if (mode("keep-helper")) {
296 do_keep_helper(isbfd
);
297 } else if (mode("finalize")) {
299 } else if (mode("rmsyms")) {
303 copy_object(ibfd
, obfd
);
305 if (offsets_sbfd
!= NULL
)
306 assert(bfd_close(offsets_sbfd
->abfd
));
307 assert(bfd_close(obfd
));
308 assert(bfd_close(ibfd
));
312 void do_keep_primary(struct superbfd
*isbfd
, const char *pre
)
314 struct bfd
*prebfd
= bfd_openr(pre
, NULL
);
315 assert(prebfd
!= NULL
);
317 assert(bfd_check_format_matches(prebfd
, bfd_object
, &matching
));
319 struct superbfd
*presbfd
= fetch_superbfd(prebfd
);
320 init_label_map(presbfd
);
323 initialize_supersect_types(isbfd
);
324 initialize_supersect_types(presbfd
);
326 match_global_symbol_sections(presbfd
, isbfd
);
327 debug1(isbfd
, "Matched global\n");
328 match_sections_by_name(presbfd
, isbfd
);
329 debug1(isbfd
, "Matched by name\n");
330 match_sections_by_label(presbfd
, isbfd
);
331 debug1(isbfd
, "Matched by label\n");
332 match_sections_by_contents(presbfd
, isbfd
);
333 debug1(isbfd
, "Matched by contents\n");
337 compare_matched_sections(isbfd
);
338 update_nonzero_offsets(isbfd
);
339 mark_new_sections(isbfd
);
343 handle_deleted_sections(presbfd
, isbfd
);
344 handle_section_symbol_renames(presbfd
, isbfd
);
347 compare_exported_symbols(presbfd
, isbfd
, "");
348 compare_exported_symbols(isbfd
, presbfd
, "del_");
350 initialize_spans(isbfd
);
351 initialize_spans(presbfd
);
353 for (sect
= isbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
354 struct supersect
*ss
= fetch_supersect(isbfd
, sect
);
355 if (ss
->type
!= SS_TYPE_STRING
)
357 asection
*oldsect
= bfd_get_section_by_name(prebfd
, sect
->name
);
360 struct supersect
*old_ss
= fetch_supersect(presbfd
, oldsect
);
361 struct span
*span
, *old_span
;
362 for (span
= ss
->spans
.data
;
363 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++) {
365 for (old_span
= old_ss
->spans
.data
;
366 old_span
< old_ss
->spans
.data
+ old_ss
->spans
.size
;
368 if (strcmp((char *)ss
->contents
.data
+
370 (char *)old_ss
->contents
.data
+
371 old_span
->start
) == 0) {
374 span
->label
= old_span
->label
;
380 assert(bfd_close(prebfd
));
382 for (sect
= isbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
383 struct supersect
*ss
= fetch_supersect(isbfd
, sect
);
385 if (ss
->type
== SS_TYPE_STRING
|| ss
->type
== SS_TYPE_SPECIAL
||
386 ss
->type
== SS_TYPE_EXPORT
)
388 if (ss
->new || ss
->patch
)
392 print_label_map(isbfd
);
394 for (sect
= isbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
395 struct supersect
*ss
= fetch_supersect(isbfd
, sect
);
397 debug0(isbfd
, "Patching section: %s\n", sect
->name
);
400 for (sect
= isbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
401 struct supersect
*ss
= fetch_supersect(isbfd
, sect
);
403 debug0(isbfd
, "New section: %s\n", sect
->name
);
406 const char **sectname
;
407 for (sectname
= delsects
.data
;
408 sectname
< delsects
.data
+ delsects
.size
; sectname
++)
409 debug0(isbfd
, "Deleted section: %s\n", *sectname
);
411 const struct export_desc
*ed
;
412 for (ed
= exports
.data
; ed
< exports
.data
+ exports
.size
; ed
++) {
413 const char **symname
;
414 bool del
= starts_with(ed
->sectname
, "del___ksymtab");
415 const char *export_type
= ed
->sectname
+ strlen("__ksymtab");
417 export_type
+= strlen("_del");
418 for (symname
= ed
->names
.data
;
419 symname
< ed
->names
.data
+ ed
->names
.size
; symname
++)
420 debug0(isbfd
, "Export %s (%s): %s\n",
421 del
? "deletion" : "addition",
422 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 compute_span_shifts(isbfd
);
436 for (sect
= isbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
437 struct supersect
*ss
= fetch_supersect(isbfd
, sect
);
438 if (!ss
->patch
&& !ss
->new)
440 asymbol
**symp
= canonical_symbolp(isbfd
, sect
->symbol
);
445 for (span
= ss
->spans
.data
;
446 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++)
447 write_ksplice_section(isbfd
, symp
, span
);
450 write_ksplice_patch(isbfd
, sect
->name
);
453 for (ed
= exports
.data
; ed
< exports
.data
+ exports
.size
; ed
++) {
454 if (starts_with(ed
->sectname
, "del___ksymtab")) {
455 const char *export_type
=
456 ed
->sectname
+ strlen("del___ksymtab");
457 const char **symname
;
458 for (symname
= ed
->names
.data
;
459 symname
< ed
->names
.data
+ ed
->names
.size
;
461 write_ksplice_export(isbfd
, *symname
,
464 rm_some_exports(isbfd
, ed
);
469 remove_unkept_spans(isbfd
);
472 void do_keep_helper(struct superbfd
*isbfd
)
476 initialize_supersect_types(isbfd
);
477 initialize_spans(isbfd
);
480 for (sect
= isbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
481 struct supersect
*ss
= fetch_supersect(isbfd
, sect
);
483 if (ss
->type
== SS_TYPE_SPECIAL
|| ss
->type
== SS_TYPE_TEXT
)
488 for (symp
= isbfd
->syms
.data
;
489 symp
< isbfd
->syms
.data
+ isbfd
->syms
.size
; symp
++) {
490 asymbol
*sym
= *symp
;
491 if (!bfd_is_const_section(sym
->section
) &&
492 (sym
->flags
& BSF_GLOBAL
) != 0) {
493 struct supersect
*sym_ss
=
494 fetch_supersect(isbfd
, sym
->section
);
495 if (sym_ss
->type
!= SS_TYPE_IGNORED
)
501 for (sect
= isbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
502 struct supersect
*ss
= fetch_supersect(isbfd
, sect
);
503 for (span
= ss
->spans
.data
;
504 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++)
505 span
->keep
= ss
->keep
;
510 keep_referenced_sections(isbfd
);
513 filter_table_sections(isbfd
);
514 compute_span_shifts(isbfd
);
516 for (sect
= isbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
517 struct supersect
*ss
= fetch_supersect(isbfd
, sect
);
518 asymbol
**symp
= canonical_symbolp(isbfd
, sect
->symbol
);
521 asymbol
*sym
= *symp
;
522 if ((sym
->flags
& BSF_WEAK
) != 0)
524 if (bfd_get_section_size(sect
) == 0)
528 if (ss
->type
!= SS_TYPE_TEXT
&& !matchable_data_section(ss
))
532 for (span
= ss
->spans
.data
;
533 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++) {
535 write_ksplice_section(isbfd
, symp
, span
);
540 remove_unkept_spans(isbfd
);
543 void do_finalize(struct superbfd
*isbfd
)
547 initialize_supersect_types(isbfd
);
548 initialize_spans(isbfd
);
552 void do_rmsyms(struct superbfd
*isbfd
)
554 read_str_set(&rmsyms
);
557 initialize_supersect_types(isbfd
);
558 initialize_spans(isbfd
);
562 struct export_vec
*get_export_syms(struct superbfd
*sbfd
)
565 struct export_vec
*exports
;
566 exports
= malloc(sizeof(*exports
));
567 assert(exports
!= NULL
);
570 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
571 if (!starts_with(sect
->name
, "__ksymtab") ||
572 ends_with(sect
->name
, "_strings"))
574 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
575 struct kernel_symbol
*sym
;
576 assert(ss
->contents
.size
* 2 == ss
->relocs
.size
*
577 sizeof(struct kernel_symbol
));
578 for (sym
= ss
->contents
.data
;
579 (void *)sym
< ss
->contents
.data
+ ss
->contents
.size
;
581 struct export
*exp
= vec_grow(exports
, 1);
583 read_string(ss
, (const char *const *)&sym
->name
);
590 void compare_exported_symbols(struct superbfd
*oldsbfd
,
591 struct superbfd
*newsbfd
, char *addstr
)
593 struct export_vec
*new_exports
, *old_exports
;
594 new_exports
= get_export_syms(newsbfd
);
595 if (new_exports
== NULL
)
597 old_exports
= get_export_syms(oldsbfd
);
598 struct export
*old
, *new;
599 asection
*last_sect
= NULL
;
600 struct export_desc
*ed
= NULL
;
601 for (new = new_exports
->data
; new < new_exports
->data
+
602 new_exports
->size
; new++) {
604 if (old_exports
!= NULL
) {
605 for (old
= old_exports
->data
; old
< old_exports
->data
+
606 old_exports
->size
; old
++) {
607 if (strcmp(new->name
, old
->name
) == 0 &&
608 strcmp(new->sect
->name
, old
->sect
->name
)
615 if (last_sect
!= new->sect
) {
616 last_sect
= new->sect
;
617 ed
= vec_grow(&exports
, 1);
619 assert(asprintf(§name
, "%s%s", addstr
,
620 new->sect
->name
) >= 0);
621 ed
->sectname
= sectname
;
622 vec_init(&ed
->names
);
625 *vec_grow(&ed
->names
, 1) = new->name
;
629 void match_sections(struct supersect
*oldss
, struct supersect
*newss
)
631 if (oldss
->match
== newss
&& newss
->match
== oldss
)
633 if (oldss
->match
!= NULL
) {
634 err(newss
->parent
, "Matching conflict: old %s: %s != %s\n",
635 oldss
->name
, oldss
->match
->name
, newss
->name
);
638 if (newss
->match
!= NULL
) {
639 err(newss
->parent
, "Matching conflict: new %s: %s != %s\n",
640 newss
->name
, newss
->match
->name
, oldss
->name
);
643 oldss
->match
= newss
;
644 newss
->match
= oldss
;
645 debug1(newss
->parent
, "Matched old %s to new %s\n",
646 oldss
->name
, newss
->name
);
649 static void match_global_symbol_sections(struct superbfd
*oldsbfd
,
650 struct superbfd
*newsbfd
)
652 asymbol
**oldsymp
, **newsymp
;
653 for (oldsymp
= oldsbfd
->syms
.data
;
654 oldsymp
< oldsbfd
->syms
.data
+ oldsbfd
->syms
.size
; oldsymp
++) {
655 asymbol
*oldsym
= *oldsymp
;
656 if ((oldsym
->flags
& BSF_GLOBAL
) == 0 ||
657 bfd_is_const_section(oldsym
->section
))
659 for (newsymp
= newsbfd
->syms
.data
;
660 newsymp
< newsbfd
->syms
.data
+ newsbfd
->syms
.size
;
662 asymbol
*newsym
= *newsymp
;
663 if ((newsym
->flags
& BSF_GLOBAL
) == 0 ||
664 bfd_is_const_section(oldsym
->section
))
666 if (strcmp(oldsym
->name
, newsym
->name
) != 0)
668 struct supersect
*oldss
=
669 fetch_supersect(oldsbfd
, oldsym
->section
);
670 struct supersect
*newss
=
671 fetch_supersect(newsbfd
, newsym
->section
);
672 match_sections(oldss
, newss
);
677 static void match_sections_by_name(struct superbfd
*oldsbfd
,
678 struct superbfd
*newsbfd
)
680 asection
*newp
, *oldp
;
681 for (newp
= newsbfd
->abfd
->sections
; newp
!= NULL
; newp
= newp
->next
) {
682 struct supersect
*newss
= fetch_supersect(newsbfd
, newp
);
683 oldp
= bfd_get_section_by_name(oldsbfd
->abfd
, newp
->name
);
684 if (oldp
== NULL
|| newss
->type
== SS_TYPE_STRING
||
685 newss
->type
== SS_TYPE_SPECIAL
||
686 newss
->type
== SS_TYPE_EXPORT
)
688 if (static_local_symbol(newsbfd
,
689 canonical_symbol(newsbfd
,
693 struct supersect
*oldss
= fetch_supersect(oldsbfd
, oldp
);
694 match_sections(oldss
, newss
);
698 static void match_sections_by_label(struct superbfd
*oldsbfd
,
699 struct superbfd
*newsbfd
)
701 asection
*oldsect
, *newsect
;
702 struct supersect
*oldss
, *newss
;
703 for (newsect
= newsbfd
->abfd
->sections
; newsect
!= NULL
;
704 newsect
= newsect
->next
) {
705 newss
= fetch_supersect(newsbfd
, newsect
);
706 if (newss
->type
== SS_TYPE_STRING
||
707 newss
->type
== SS_TYPE_SPECIAL
||
708 newss
->type
== SS_TYPE_EXPORT
)
710 for (oldsect
= oldsbfd
->abfd
->sections
; oldsect
!= NULL
;
711 oldsect
= oldsect
->next
) {
712 if (strcmp(label_lookup(newsbfd
, newsect
->symbol
),
713 label_lookup(oldsbfd
, oldsect
->symbol
)) != 0)
715 oldss
= fetch_supersect(oldsbfd
, oldsect
);
716 match_sections(oldss
, newss
);
721 static void match_sections_by_contents(struct superbfd
*oldsbfd
,
722 struct superbfd
*newsbfd
)
724 asection
*oldsect
, *newsect
;
725 struct supersect
*oldss
, *newss
;
726 for (newsect
= newsbfd
->abfd
->sections
; newsect
!= NULL
;
727 newsect
= newsect
->next
) {
728 newss
= fetch_supersect(newsbfd
, newsect
);
729 if (newss
->type
!= SS_TYPE_RODATA
)
731 for (oldsect
= oldsbfd
->abfd
->sections
; oldsect
!= NULL
;
732 oldsect
= oldsect
->next
) {
733 oldss
= fetch_supersect(oldsbfd
, oldsect
);
734 if (oldss
->type
!= SS_TYPE_RODATA
)
736 if (oldss
->relocs
.size
!= 0 || newss
->relocs
.size
!= 0)
738 if (oldss
->contents
.size
!= newss
->contents
.size
)
740 if (memcmp(oldss
->contents
.data
, newss
->contents
.data
,
741 oldss
->contents
.size
) != 0)
743 match_sections(oldss
, newss
);
748 static void mark_new_sections(struct superbfd
*sbfd
)
751 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
752 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
753 if (ss
->type
== SS_TYPE_STRING
|| ss
->type
== SS_TYPE_SPECIAL
||
754 ss
->type
== SS_TYPE_IGNORED
|| ss
->type
== SS_TYPE_EXPORT
)
756 if (ss
->match
== NULL
)
761 static void handle_deleted_sections(struct superbfd
*oldsbfd
,
762 struct superbfd
*newsbfd
)
765 for (sect
= oldsbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
766 struct supersect
*ss
= fetch_supersect(oldsbfd
, sect
);
767 if (ss
->type
!= SS_TYPE_TEXT
)
769 if (ss
->match
!= NULL
)
771 const char *label
= label_lookup(oldsbfd
, sect
->symbol
);
772 *vec_grow(&delsects
, 1) = label
;
773 asymbol
*csym
= canonical_symbol(oldsbfd
, sect
->symbol
);
774 write_ksplice_deleted_patch(newsbfd
, csym
->name
, label
);
778 static void handle_nonzero_offset_relocs(struct supersect
*ss
)
781 for (i
= 0; i
< ss
->relocs
.size
; i
++) {
782 asymbol
*sym
= *ss
->relocs
.data
[i
]->sym_ptr_ptr
;
783 bfd_vma offset
= get_reloc_offset(ss
, ss
->relocs
.data
[i
], true);
784 if (sym
->value
+ offset
== 0)
786 if (bfd_is_const_section(sym
->section
))
788 struct supersect
*sym_ss
= fetch_supersect(ss
->parent
,
790 if (sym_ss
->type
!= SS_TYPE_TEXT
)
792 if (!sym_ss
->patch
) {
795 "Changing %s because a relocation from sect %s "
796 "has a nonzero offset %lx+%lx into it\n",
797 sym_ss
->name
, ss
->name
,
798 (unsigned long)sym
->value
,
799 (unsigned long)offset
);
801 sym_ss
->patch
= true;
805 static void update_nonzero_offsets(struct superbfd
*sbfd
)
808 struct supersect
*ss
;
810 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
811 ss
= fetch_supersect(sbfd
, sect
);
812 if (ss
->new || ss
->patch
)
813 handle_nonzero_offset_relocs(ss
);
817 static void compare_matched_sections(struct superbfd
*newsbfd
)
820 struct supersect
*old_ss
, *new_ss
;
821 for (newp
= newsbfd
->abfd
->sections
; newp
!= NULL
; newp
= newp
->next
) {
822 new_ss
= fetch_supersect(newsbfd
, newp
);
823 if (new_ss
->match
== NULL
)
825 old_ss
= new_ss
->match
;
827 if (nonrelocs_equal(old_ss
, new_ss
) &&
828 relocs_equal(old_ss
, new_ss
))
832 if (new_ss
->contents
.size
!= old_ss
->contents
.size
)
833 reason
= "differing sizes";
834 else if (memcmp(new_ss
->contents
.data
, old_ss
->contents
.data
,
835 new_ss
->contents
.size
) != 0)
836 reason
= "differing contents";
838 reason
= "differing relocations";
839 if (new_ss
->type
== SS_TYPE_TEXT
) {
842 new_ss
->patch
= true;
843 debug1(newsbfd
, "Changing %s due to %s\n", new_ss
->name
,
846 debug1(newsbfd
, "Unmatching %s and %s due to %s\n",
847 old_ss
->name
, new_ss
->name
, reason
);
848 new_ss
->match
= NULL
;
849 old_ss
->match
= NULL
;
852 if (unchangeable_section(new_ss
))
853 err(newsbfd
, "warning: ignoring change to nonpatchable "
854 "section %s\n", new_ss
->name
);
858 static void handle_section_symbol_renames(struct superbfd
*oldsbfd
,
859 struct superbfd
*newsbfd
)
861 asection
*newp
, *oldp
;
862 for (newp
= newsbfd
->abfd
->sections
; newp
!= NULL
; newp
= newp
->next
) {
863 struct supersect
*newss
= fetch_supersect(newsbfd
, newp
);
864 if (newss
->match
== NULL
)
866 oldp
= bfd_get_section_by_name(oldsbfd
->abfd
,
871 const char *old_label
= label_lookup(oldsbfd
, oldp
->symbol
);
872 const char *new_label
= label_lookup(newsbfd
, newp
->symbol
);
874 if (strcmp(old_label
, new_label
) == 0)
876 label_map_set(newsbfd
, new_label
, old_label
);
880 static bool part_of_reloc(struct supersect
*ss
, unsigned long addr
)
883 for (relocp
= ss
->relocs
.data
;
884 relocp
< ss
->relocs
.data
+ ss
->relocs
.size
; relocp
++) {
885 arelent
*reloc
= *relocp
;
886 if (addr
>= reloc
->address
&&
887 addr
< reloc
->address
+ reloc
->howto
->size
)
893 static bool nonrelocs_equal(struct supersect
*old_ss
, struct supersect
*new_ss
)
896 if (old_ss
->contents
.size
!= new_ss
->contents
.size
)
898 const unsigned char *old
= old_ss
->contents
.data
;
899 const unsigned char *new = new_ss
->contents
.data
;
900 for (i
= 0; i
< old_ss
->contents
.size
; i
++) {
901 if (old
[i
] != new[i
] &&
902 !(part_of_reloc(old_ss
, i
) && part_of_reloc(new_ss
, i
)))
909 * relocs_equal checks to see whether the old section and the new section
910 * reference different read-only data in their relocations -- if a hard-coded
911 * string has been changed between the old file and the new file, relocs_equal
912 * will detect the difference.
914 bool relocs_equal(struct supersect
*old_ss
, struct supersect
*new_ss
)
917 struct superbfd
*oldsbfd
= old_ss
->parent
;
918 struct superbfd
*newsbfd
= new_ss
->parent
;
920 if (old_ss
->relocs
.size
!= new_ss
->relocs
.size
) {
921 debug1(newsbfd
, "Different reloc count between %s and %s\n",
922 old_ss
->name
, new_ss
->name
);
926 for (i
= 0; i
< old_ss
->relocs
.size
; i
++) {
927 struct supersect
*ro_old_ss
, *ro_new_ss
;
929 if (old_ss
->relocs
.data
[i
]->address
!=
930 new_ss
->relocs
.data
[i
]->address
)
933 asymbol
*old_sym
= *old_ss
->relocs
.data
[i
]->sym_ptr_ptr
;
934 asymbol
*new_sym
= *new_ss
->relocs
.data
[i
]->sym_ptr_ptr
;
937 get_reloc_offset(old_ss
, old_ss
->relocs
.data
[i
], true);
939 get_reloc_offset(new_ss
, new_ss
->relocs
.data
[i
], true);
941 if (bfd_is_und_section(old_sym
->section
) ||
942 bfd_is_und_section(new_sym
->section
)) {
943 if (!bfd_is_und_section(new_sym
->section
) &&
944 fetch_supersect(newsbfd
, new_sym
->section
)->type
945 == SS_TYPE_TEXT
&& old_offset
!= 0)
948 if (!bfd_is_und_section(old_sym
->section
) &&
949 fetch_supersect(oldsbfd
, old_sym
->section
)->type
950 == SS_TYPE_TEXT
&& new_offset
!= 0)
953 if (strcmp(old_sym
->name
, new_sym
->name
) == 0 &&
954 old_offset
== new_offset
)
959 if (bfd_is_const_section(old_sym
->section
) ||
960 bfd_is_const_section(new_sym
->section
))
963 ro_old_ss
= fetch_supersect(oldsbfd
, old_sym
->section
);
964 ro_new_ss
= fetch_supersect(newsbfd
, new_sym
->section
);
966 if (ro_old_ss
->type
== SS_TYPE_STRING
&&
967 /* check it's not an out-of-range relocation to a string;
968 we'll just compare entire sections for them */
969 !(old_offset
>= ro_old_ss
->contents
.size
||
970 new_offset
>= ro_new_ss
->contents
.size
)) {
971 if (strcmp(ro_old_ss
->contents
.data
+ old_sym
->value
+
973 ro_new_ss
->contents
.data
+ new_sym
->value
+
975 debug0(newsbfd
, "Section %s/%s has string "
976 "difference \"%s\"/\"%s\"\n",
977 old_ss
->name
, new_ss
->name
,
978 (const char *)(ro_old_ss
->contents
.data
+
981 (const char *)(ro_new_ss
->contents
.data
+
985 "Strings differ between %s and %s\n",
986 old_ss
->name
, new_ss
->name
);
992 if (ro_old_ss
->match
!= ro_new_ss
||
993 ro_new_ss
->match
!= ro_old_ss
) {
994 debug1(newsbfd
, "Nonmatching relocs from %s to %s/%s\n",
995 new_ss
->name
, ro_new_ss
->name
, ro_old_ss
->name
);
999 if (old_sym
->value
+ old_offset
!= new_sym
->value
+ new_offset
) {
1000 debug1(newsbfd
, "Offsets to %s/%s differ between %s "
1001 "and %s: %lx+%lx/%lx+%lx\n", ro_old_ss
->name
,
1002 ro_new_ss
->name
, old_ss
->name
, new_ss
->name
,
1003 (unsigned long)old_sym
->value
,
1004 (unsigned long)old_offset
,
1005 (unsigned long)new_sym
->value
,
1006 (unsigned long)new_offset
);
1010 if ((old_sym
->value
+ old_offset
!= 0 ||
1011 new_sym
->value
+ new_offset
!= 0) && ro_new_ss
->patch
) {
1012 debug1(newsbfd
, "Relocation from %s to nonzero offsets "
1013 "%lx+%lx/%lx+%lx in changed section %s\n",
1015 (unsigned long)old_sym
->value
,
1016 (unsigned long)old_offset
,
1017 (unsigned long)new_sym
->value
,
1018 (unsigned long)new_offset
,
1019 new_sym
->section
->name
);
1027 void rm_some_exports(struct superbfd
*isbfd
, const struct export_desc
*ed
)
1029 assert(starts_with(ed
->sectname
, "__ksymtab"));
1030 const char *export_type
= ed
->sectname
+ strlen("__ksymtab");
1031 asection
*sym_sect
= bfd_get_section_by_name(isbfd
->abfd
, ed
->sectname
);
1032 assert(sym_sect
!= NULL
);
1033 char *export_crc_name
;
1034 assert(asprintf(&export_crc_name
, "__kcrctab%s", export_type
) >= 0);
1035 asection
*crc_sect
= bfd_get_section_by_name(isbfd
->abfd
,
1037 struct supersect
*ss
, *crc_ss
= NULL
;
1038 ss
= fetch_supersect(isbfd
, sym_sect
);
1039 if (crc_sect
!= NULL
)
1040 crc_ss
= fetch_supersect(isbfd
, crc_sect
);
1043 assert(ss
->contents
.size
* sizeof(unsigned long) ==
1044 crc_ss
->contents
.size
* sizeof(struct kernel_symbol
));
1046 struct supersect orig_ss
, orig_crc_ss
;
1047 supersect_move(&orig_ss
, ss
);
1049 supersect_move(&orig_crc_ss
, crc_ss
);
1051 struct kernel_symbol
*orig_ksym
;
1052 unsigned long *orig_crc
;
1053 for (orig_ksym
= orig_ss
.contents
.data
,
1054 orig_crc
= orig_crc_ss
.contents
.data
;
1055 (void *)orig_ksym
< orig_ss
.contents
.data
+ orig_ss
.contents
.size
;
1056 orig_ksym
++, orig_crc
++) {
1058 read_reloc(&orig_ss
, &orig_ksym
->value
,
1059 sizeof(orig_ksym
->value
), &sym
);
1060 if (!str_in_set(sym
->name
, &ed
->names
))
1063 struct kernel_symbol
*ksym
= sect_grow(ss
, 1, typeof(*ksym
));
1064 sect_copy(ss
, &ksym
->value
, &orig_ss
, &orig_ksym
->value
, 1);
1065 /* Replace name with a mangled name */
1066 write_ksplice_export(ss
->parent
, sym
->name
, export_type
, false);
1067 write_string(ss
, (const char **)&ksym
->name
,
1068 "DISABLED_%s_%s", sym
->name
, kid
);
1072 sect_grow(crc_ss
, 1, typeof(*orig_crc
)),
1073 &orig_crc_ss
, orig_crc
, 1);
1077 void rm_relocs(struct superbfd
*isbfd
)
1080 for (p
= isbfd
->abfd
->sections
; p
!= NULL
; p
= p
->next
) {
1081 struct supersect
*ss
= fetch_supersect(isbfd
, p
);
1082 if ((mode("keep") && ss
->type
== SS_TYPE_SPECIAL
) ||
1083 ss
->type
== SS_TYPE_KSPLICE
)
1085 if (ss
->keep
|| mode("rmsyms"))
1088 if (mode("finalize")) {
1089 p
= bfd_get_section_by_name(isbfd
->abfd
, ".ksplice_patches");
1091 struct supersect
*ss
= fetch_supersect(isbfd
, p
);
1097 void rm_some_relocs(struct supersect
*ss
)
1099 struct arelentp_vec orig_relocs
;
1100 vec_move(&orig_relocs
, &ss
->relocs
);
1103 for (relocp
= orig_relocs
.data
;
1104 relocp
< orig_relocs
.data
+ orig_relocs
.size
; relocp
++) {
1105 bool rm_reloc
= false;
1106 asymbol
*sym_ptr
= *(*relocp
)->sym_ptr_ptr
;
1108 if (mode("rmsyms") && str_in_set(sym_ptr
->name
, &rmsyms
) &&
1109 bfd_is_und_section(sym_ptr
->section
))
1115 if (mode("keep-primary") &&
1116 (bfd_is_const_section(sym_ptr
->section
) ||
1117 fetch_supersect(ss
->parent
, sym_ptr
->section
)->new ||
1118 reloc_target_span(ss
, *relocp
)->new ||
1119 !reloc_address_span(ss
, *relocp
)->keep
))
1122 if (mode("finalize") && bfd_is_und_section(sym_ptr
->section
))
1126 write_ksplice_reloc(ss
, *relocp
);
1128 *vec_grow(&ss
->relocs
, 1) = *relocp
;
1132 struct supersect
*make_section(struct superbfd
*sbfd
, const char *name
)
1134 asection
*sect
= bfd_get_section_by_name(sbfd
->abfd
, name
);
1136 return fetch_supersect(sbfd
, sect
);
1138 return new_supersect(sbfd
, name
);
1141 arelent
*create_reloc(struct supersect
*ss
, const void *addr
, asymbol
**symp
,
1144 bfd_reloc_code_real_type code
;
1145 switch (bfd_arch_bits_per_address(ss
->parent
->abfd
)) {
1147 code
= BFD_RELOC_32
;
1150 code
= BFD_RELOC_64
;
1156 arelent
*reloc
= malloc(sizeof(*reloc
));
1157 reloc
->sym_ptr_ptr
= symp
;
1158 reloc
->address
= addr_offset(ss
, addr
);
1159 reloc
->howto
= bfd_reloc_type_lookup(ss
->parent
->abfd
, code
);
1160 reloc
->addend
= offset
;
1164 void write_reloc(struct supersect
*ss
, const void *addr
, asymbol
**symp
,
1167 arelent
*new_reloc
= create_reloc(ss
, addr
, symp
, offset
), **relocp
;
1168 for (relocp
= ss
->relocs
.data
;
1169 relocp
< ss
->relocs
.data
+ ss
->relocs
.size
; relocp
++) {
1170 if ((*relocp
)->address
== new_reloc
->address
) {
1173 (void *)(ss
->relocs
.data
+ ss
->relocs
.size
) -
1174 (void *)(relocp
+ 1));
1179 *vec_grow(&ss
->new_relocs
, 1) = new_reloc
;
1182 void write_string(struct supersect
*ss
, const char **addr
, const char *fmt
, ...)
1185 struct supersect
*str_ss
= make_section(ss
->parent
, ".ksplice_str");
1188 int len
= vasprintf(&str
, fmt
, ap
);
1192 unsigned long *str_offp
= ulong_hash_lookup(&ksplice_string_offset
, str
,
1194 if (str_offp
== NULL
) {
1195 char *buf
= sect_grow(str_ss
, len
+ 1, char);
1196 memcpy(buf
, str
, len
+ 1);
1197 str_offp
= ulong_hash_lookup(&ksplice_string_offset
, str
, TRUE
);
1198 *str_offp
= addr_offset(str_ss
, buf
);
1201 write_reloc(ss
, addr
, &str_ss
->symbol
, *str_offp
);
1204 void lookup_system_map(struct addr_vec
*addrs
, const char *name
, long offset
)
1206 struct addr_vec
*map_addrs
=
1207 addr_vec_hash_lookup(&system_map
, name
, FALSE
);
1208 if (map_addrs
== NULL
)
1211 unsigned long *addr
, *map_addr
;
1212 for (map_addr
= map_addrs
->data
;
1213 map_addr
< map_addrs
->data
+ map_addrs
->size
; map_addr
++) {
1214 for (addr
= addrs
->data
; addr
< addrs
->data
+ addrs
->size
;
1216 if (*addr
== *map_addr
+ offset
)
1219 if (addr
< addrs
->data
+ addrs
->size
)
1221 *vec_grow(addrs
, 1) = *map_addr
+ offset
;
1225 void write_system_map_array(struct superbfd
*sbfd
, struct supersect
*ss
,
1226 const unsigned long **sym_addrs
,
1227 unsigned long *num_sym_addrs
, asymbol
*sym
)
1229 struct addr_vec addrs
;
1232 if (bfd_is_abs_section(sym
->section
)) {
1233 *vec_grow(&addrs
, 1) = sym
->value
;
1234 } else if (bfd_is_und_section(sym
->section
)) {
1235 lookup_system_map(&addrs
, sym
->name
, 0);
1236 } else if (!bfd_is_const_section(sym
->section
)) {
1238 for (gsymp
= sbfd
->syms
.data
;
1239 gsymp
< sbfd
->syms
.data
+ sbfd
->syms
.size
; gsymp
++) {
1240 asymbol
*gsym
= *gsymp
;
1241 if ((gsym
->flags
& BSF_DEBUGGING
) == 0 &&
1242 gsym
->section
== sym
->section
)
1243 lookup_system_map(&addrs
, gsym
->name
,
1244 sym
->value
- gsym
->value
);
1248 *num_sym_addrs
= addrs
.size
;
1249 if (addrs
.size
!= 0) {
1250 struct supersect
*array_ss
= make_section(sbfd
,
1252 void *buf
= sect_grow(array_ss
, addrs
.size
,
1253 typeof(*addrs
.data
));
1254 memcpy(buf
, addrs
.data
, addrs
.size
* sizeof(*addrs
.data
));
1255 write_reloc(ss
, sym_addrs
, &array_ss
->symbol
,
1256 addr_offset(array_ss
, buf
));
1264 void write_ksplice_system_map(struct superbfd
*sbfd
, asymbol
*sym
,
1265 const char *addstr_sect
)
1267 struct supersect
*smap_ss
= make_section(sbfd
, ".ksplice_system_map");
1268 struct ksplice_system_map
*smap
;
1269 const char *label
= label_lookup(sbfd
, sym
);
1271 bool *done
= bool_hash_lookup(&system_map_written
, label
, TRUE
);
1276 smap
= sect_grow(smap_ss
, 1, struct ksplice_system_map
);
1278 write_system_map_array(sbfd
, smap_ss
, &smap
->candidates
,
1279 &smap
->nr_candidates
, sym
);
1280 write_string(smap_ss
, &smap
->label
, "%s%s", label
, addstr_sect
);
1283 void write_ksplice_symbol(struct supersect
*ss
,
1284 const struct ksplice_symbol
*const *addr
,
1285 asymbol
*sym
, struct span
*span
,
1286 const char *addstr_sect
)
1288 struct supersect
*ksymbol_ss
= make_section(ss
->parent
,
1289 ".ksplice_symbols");
1290 struct ksplice_symbol
*ksymbol
;
1291 unsigned long *ksymbol_offp
;
1294 if (span
!= NULL
&& span
->start
!= 0)
1295 label
= span
->label
;
1297 label
= label_lookup(ss
->parent
, sym
);
1298 assert(asprintf(&output
, "%s%s", label
, addstr_sect
) >= 0);
1300 ksymbol_offp
= ulong_hash_lookup(&ksplice_symbol_offset
, output
, FALSE
);
1301 if (ksymbol_offp
!= NULL
) {
1302 write_reloc(ss
, addr
, &ksymbol_ss
->symbol
, *ksymbol_offp
);
1305 ksymbol
= sect_grow(ksymbol_ss
, 1, struct ksplice_symbol
);
1306 ksymbol_offp
= ulong_hash_lookup(&ksplice_symbol_offset
, output
, TRUE
);
1307 *ksymbol_offp
= addr_offset(ksymbol_ss
, ksymbol
);
1309 write_reloc(ss
, addr
, &ksymbol_ss
->symbol
, *ksymbol_offp
);
1310 write_string(ksymbol_ss
, &ksymbol
->label
, "%s", output
);
1312 if (span
!= NULL
&& span
->symbol
== NULL
) {
1313 ksymbol
->name
= NULL
;
1317 write_ksplice_system_map(ksymbol_ss
->parent
, sym
, addstr_sect
);
1319 if (bfd_is_und_section(sym
->section
) || (sym
->flags
& BSF_GLOBAL
) != 0) {
1320 write_string(ksymbol_ss
, &ksymbol
->name
, "%s", sym
->name
);
1321 } else if (bfd_is_const_section(sym
->section
)) {
1322 ksymbol
->name
= NULL
;
1324 asymbol
*gsym
= canonical_symbol(ss
->parent
, sym
);
1326 if (gsym
== NULL
|| (gsym
->flags
& BSF_SECTION_SYM
) != 0)
1327 ksymbol
->name
= NULL
;
1329 write_string(ksymbol_ss
, &ksymbol
->name
, "%s",
1334 void write_ksplice_reloc(struct supersect
*ss
, arelent
*orig_reloc
)
1336 asymbol
*sym_ptr
= *orig_reloc
->sym_ptr_ptr
;
1337 reloc_howto_type
*howto
= orig_reloc
->howto
;
1338 bfd_vma addend
= get_reloc_offset(ss
, orig_reloc
, false);
1340 if (mode("finalize") && starts_with(ss
->name
, ".ksplice_patches")) {
1341 unsigned long *repladdr
=
1342 ss
->contents
.data
+ orig_reloc
->address
;
1347 struct span
*span
= reloc_target_span(ss
, orig_reloc
);
1348 if (span
== ss
->spans
.data
&& span
->start
!= addend
)
1350 blot_section(ss
, orig_reloc
->address
, howto
);
1352 struct supersect
*kreloc_ss
= make_section(ss
->parent
,
1354 ".ksplice_init_relocs" :
1356 struct ksplice_reloc
*kreloc
= sect_grow(kreloc_ss
, 1,
1357 struct ksplice_reloc
);
1359 write_reloc(kreloc_ss
, &kreloc
->blank_addr
,
1360 &ss
->symbol
, orig_reloc
->address
);
1361 write_ksplice_symbol(kreloc_ss
, &kreloc
->symbol
, sym_ptr
, span
, "");
1362 kreloc
->pcrel
= howto
->pc_relative
;
1363 if (span
!= NULL
&& span
->start
!= 0)
1364 addend
+= sym_ptr
->value
- span
->start
;
1365 kreloc
->addend
= addend
;
1366 kreloc
->size
= bfd_get_reloc_size(howto
);
1367 kreloc
->dst_mask
= howto
->dst_mask
;
1368 kreloc
->rightshift
= howto
->rightshift
;
1369 kreloc
->signed_addend
=
1370 (howto
->complain_on_overflow
== complain_overflow_signed
) ||
1371 (howto
->complain_on_overflow
== complain_overflow_bitfield
);
1374 #define CANARY(x, canary) ((x & ~howto->dst_mask) | (canary & howto->dst_mask))
1376 void blot_section(struct supersect
*ss
, int offset
, reloc_howto_type
*howto
)
1378 int bits
= bfd_get_reloc_size(howto
) * 8;
1379 void *address
= ss
->contents
.data
+ offset
;
1380 bfd_vma x
= bfd_get(bits
, ss
->parent
->abfd
, address
);
1381 x
= (x
& ~howto
->dst_mask
) |
1382 ((bfd_vma
)KSPLICE_CANARY
& howto
->dst_mask
);
1383 bfd_put(bits
, ss
->parent
->abfd
, x
, address
);
1386 void write_ksplice_section(struct superbfd
*sbfd
, asymbol
**symp
,
1389 asymbol
*sym
= span
->symbol
== NULL
? *symp
: span
->symbol
;
1390 struct supersect
*ksect_ss
= make_section(sbfd
, ".ksplice_sections");
1391 struct ksplice_section
*ksect
= sect_grow(ksect_ss
, 1,
1392 struct ksplice_section
);
1394 write_ksplice_symbol(ksect_ss
, &ksect
->symbol
, sym
, span
,
1395 mode("keep-primary") ? "(post)" : "");
1396 ksect
->size
= span
->size
;
1398 struct supersect
*sym_ss
= fetch_supersect(sbfd
, sym
->section
);
1399 if (sym_ss
->type
== SS_TYPE_RODATA
|| sym_ss
->type
== SS_TYPE_STRING
)
1400 ksect
->flags
|= KSPLICE_SECTION_RODATA
;
1401 if (sym_ss
->type
== SS_TYPE_DATA
)
1402 ksect
->flags
|= KSPLICE_SECTION_DATA
;
1403 if (sym_ss
->type
== SS_TYPE_TEXT
)
1404 ksect
->flags
|= KSPLICE_SECTION_TEXT
;
1405 assert(ksect
->flags
!= 0);
1406 write_reloc(ksect_ss
, &ksect
->address
, symp
, span
->start
+ span
->shift
);
1409 void write_ksplice_patch(struct superbfd
*sbfd
, const char *sectname
)
1411 struct supersect
*kpatch_ss
= make_section(sbfd
, ".ksplice_patches");
1412 struct ksplice_patch
*kpatch
= sect_grow(kpatch_ss
, 1,
1413 struct ksplice_patch
);
1414 asection
*sect
= bfd_get_section_by_name(sbfd
->abfd
, sectname
);
1415 assert(sect
!= NULL
);
1417 write_string(kpatch_ss
, &kpatch
->label
, "%s",
1418 label_lookup(sbfd
, sect
->symbol
));
1419 write_reloc(kpatch_ss
, &kpatch
->repladdr
, §
->symbol
, 0);
1422 void write_ksplice_deleted_patch(struct superbfd
*sbfd
, const char *name
,
1425 struct supersect
*kpatch_ss
= make_section(sbfd
, ".ksplice_patches");
1426 struct ksplice_patch
*kpatch
= sect_grow(kpatch_ss
, 1,
1427 struct ksplice_patch
);
1429 write_string(kpatch_ss
, &kpatch
->label
, "%s", label
);
1431 for (symp
= sbfd
->syms
.data
; symp
< sbfd
->syms
.data
+ sbfd
->syms
.size
;
1433 asymbol
*sym
= *symp
;
1434 if (bfd_is_und_section(sym
->section
) &&
1435 strcmp(name
, sym
->name
) == 0)
1438 if (symp
>= sbfd
->syms
.data
+ sbfd
->syms
.size
) {
1439 symp
= malloc(sizeof(*symp
));
1440 *symp
= bfd_make_empty_symbol(sbfd
->abfd
);
1441 asymbol
*sym
= *symp
;
1442 sym
->name
= strdup(name
);
1443 sym
->section
= bfd_und_section_ptr
;
1446 *vec_grow(&sbfd
->new_syms
, 1) = symp
;
1448 write_reloc(kpatch_ss
, &kpatch
->repladdr
, symp
, 0);
1451 void write_ksplice_export(struct superbfd
*sbfd
, const char *symname
,
1452 const char *export_type
, bool del
)
1454 struct supersect
*export_ss
= make_section(sbfd
, ".ksplice_exports");
1455 struct ksplice_export
*exp
= sect_grow(export_ss
, 1,
1456 struct ksplice_export
);
1459 write_string(export_ss
, &exp
->name
, "%s", symname
);
1460 write_string(export_ss
, &exp
->new_name
, "DISABLED_%s_%s",
1463 write_string(export_ss
, &exp
->new_name
, "%s", symname
);
1464 write_string(export_ss
, &exp
->name
, "DISABLED_%s_%s", symname
,
1469 struct fixup_entry
{
1473 DECLARE_VEC_TYPE(struct fixup_entry
, fixup_entry_vec
);
1475 int compare_fixups(const void *aptr
, const void *bptr
)
1477 const struct fixup_entry
*a
= aptr
, *b
= bptr
;
1478 if (a
->offset
< b
->offset
)
1480 else if (a
->offset
> b
->offset
)
1483 return (int)a
->used
- (int)b
->used
;
1486 void filter_table_sections(struct superbfd
*isbfd
)
1488 struct supersect
*tables_ss
=
1489 fetch_supersect(offsets_sbfd
,
1490 bfd_get_section_by_name(offsets_sbfd
->abfd
,
1491 ".ksplice_table_sections"));
1492 const struct table_section
*ts
;
1493 for (ts
= tables_ss
->contents
.data
;
1494 (void *)ts
< tables_ss
->contents
.data
+ tables_ss
->contents
.size
;
1496 struct table_section s
= *ts
;
1497 s
.sect
= read_string(tables_ss
, &ts
->sect
);
1498 s
.other_sect
= read_string(tables_ss
, &ts
->other_sect
);
1499 filter_table_section(isbfd
, &s
);
1503 void filter_table_section(struct superbfd
*sbfd
, const struct table_section
*s
)
1505 asection
*isection
= bfd_get_section_by_name(sbfd
->abfd
, s
->sect
);
1506 if (isection
== NULL
)
1508 asection
*fixup_sect
= NULL
;
1509 if (s
->other_sect
!= NULL
)
1510 fixup_sect
= bfd_get_section_by_name(sbfd
->abfd
, s
->other_sect
);
1512 struct supersect
*ss
= fetch_supersect(sbfd
, isection
);
1513 if (ss
->alignment
< ffs(s
->entry_align
) - 1)
1514 ss
->alignment
= ffs(s
->entry_align
) - 1;
1516 struct supersect
*fixup_ss
= NULL
;
1517 if (fixup_sect
!= NULL
)
1518 fixup_ss
= fetch_supersect(sbfd
, fixup_sect
);
1520 struct fixup_entry_vec fixups
;
1524 for (entry
= ss
->contents
.data
;
1525 entry
< ss
->contents
.data
+ ss
->contents
.size
;
1526 entry
+= s
->entry_size
) {
1527 asymbol
*sym
, *fixup_sym
;
1528 read_reloc(ss
, entry
+ s
->addr_offset
, sizeof(void *), &sym
);
1530 struct span
*span
= new_span(sbfd
, isection
,
1531 addr_offset(ss
, entry
),
1533 struct supersect
*sym_ss
= fetch_supersect(sbfd
, sym
->section
);
1534 span
->keep
= sym_ss
->keep
;
1536 struct fixup_entry
*f
;
1537 if (fixup_sect
!= NULL
) {
1538 bfd_vma fixup_offset
=
1539 read_reloc(ss
, entry
+ s
->other_offset
,
1540 sizeof(void *), &fixup_sym
);
1541 if (fixup_sym
->section
== fixup_sect
) {
1542 assert(fixup_offset
< fixup_ss
->contents
.size
);
1543 f
= vec_grow(&fixups
, 1);
1544 f
->offset
= fixup_offset
;
1545 f
->used
= span
->keep
;
1550 if (fixup_sect
== NULL
)
1553 qsort(fixups
.data
, fixups
.size
, sizeof(*fixups
.data
), compare_fixups
);
1554 *vec_grow(&fixups
, 1) = (struct fixup_entry
)
1555 { .offset
= fixup_ss
->contents
.size
, .used
= false };
1557 struct fixup_entry
*f
;
1558 for (f
= fixups
.data
; f
< fixups
.data
+ fixups
.size
- 1; f
++) {
1559 struct span
*span
= new_span(sbfd
, fixup_sect
, f
->offset
,
1560 (f
+ 1)->offset
- f
->offset
);
1561 span
->keep
= f
->used
;
1565 void keep_referenced_sections(struct superbfd
*sbfd
)
1568 struct supersect
*ss
, *sym_ss
;
1569 struct span
*address_span
, *target_span
;
1570 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
1571 ss
= fetch_supersect(sbfd
, sect
);
1573 if (ss
->type
== SS_TYPE_SPECIAL
|| ss
->type
== SS_TYPE_EXPORT
)
1575 for (relocp
= ss
->relocs
.data
;
1576 relocp
< ss
->relocs
.data
+ ss
->relocs
.size
; relocp
++) {
1577 asymbol
*sym
= *(*relocp
)->sym_ptr_ptr
;
1578 address_span
= reloc_address_span(ss
, *relocp
);
1579 if (!address_span
->keep
)
1581 target_span
= reloc_target_span(ss
, *relocp
);
1582 if (target_span
== NULL
|| target_span
->keep
)
1584 sym_ss
= fetch_supersect(sbfd
, sym
->section
);
1585 if (sym_ss
->type
== SS_TYPE_IGNORED
)
1587 target_span
->keep
= true;
1588 sym_ss
->keep
= true;
1594 void copy_symbols(struct asymbolp_vec
*osyms
, struct asymbolpp_vec
*isyms
)
1597 for (sympp
= isyms
->data
; sympp
< isyms
->data
+ isyms
->size
; sympp
++)
1598 *vec_grow(osyms
, 1) = **sympp
;
1601 /* Modified function from GNU Binutils objcopy.c */
1602 bfd_boolean
copy_object(bfd
*ibfd
, bfd
*obfd
)
1604 assert(bfd_set_format(obfd
, bfd_get_format(ibfd
)));
1606 bfd_vma start
= bfd_get_start_address(ibfd
);
1608 flagword flags
= bfd_get_file_flags(ibfd
);
1609 flags
&= bfd_applicable_file_flags(obfd
);
1611 assert(bfd_set_start_address(obfd
, start
)
1612 && bfd_set_file_flags(obfd
, flags
));
1614 enum bfd_architecture iarch
= bfd_get_arch(ibfd
);
1615 unsigned int imach
= bfd_get_mach(ibfd
);
1616 assert(bfd_set_arch_mach(obfd
, iarch
, imach
));
1617 assert(bfd_set_format(obfd
, bfd_get_format(ibfd
)));
1619 /* BFD mandates that all output sections be created and sizes set before
1620 any output is done. Thus, we traverse all sections multiple times. */
1621 bfd_map_over_sections(ibfd
, setup_section
, obfd
);
1623 struct supersect
*new_supersects
= fetch_superbfd(ibfd
)->new_supersects
;
1624 struct supersect
*ss
;
1625 for (ss
= new_supersects
; ss
!= NULL
; ss
= ss
->next
)
1626 setup_new_section(obfd
, ss
);
1628 /* Mark symbols used in output relocations so that they
1629 are kept, even if they are local labels or static symbols.
1631 Note we iterate over the input sections examining their
1632 relocations since the relocations for the output sections
1633 haven't been set yet. mark_symbols_used_in_relocations will
1634 ignore input sections which have no corresponding output
1637 bfd_map_over_sections(ibfd
, mark_symbols_used_in_relocations
, NULL
);
1638 for (ss
= new_supersects
; ss
!= NULL
; ss
= ss
->next
)
1639 ss_mark_symbols_used_in_relocations(ss
);
1640 struct asymbolp_vec osyms
;
1642 filter_symbols(ibfd
, obfd
, &osyms
, &fetch_superbfd(ibfd
)->syms
);
1643 copy_symbols(&osyms
, &fetch_superbfd(ibfd
)->new_syms
);
1645 bfd_set_symtab(obfd
, osyms
.data
, osyms
.size
);
1647 /* This has to happen after the symbol table has been set. */
1648 bfd_map_over_sections(obfd
, write_section
, NULL
);
1650 /* Allow the BFD backend to copy any private data it understands
1651 from the input BFD to the output BFD. This is done last to
1652 permit the routine to look at the filtered symbol table, which is
1653 important for the ECOFF code at least. */
1654 assert(bfd_copy_private_bfd_data(ibfd
, obfd
));
1659 /* Modified function from GNU Binutils objcopy.c */
1660 void setup_section(bfd
*ibfd
, asection
*isection
, void *obfdarg
)
1662 struct superbfd
*isbfd
= fetch_superbfd(ibfd
);
1663 struct supersect
*ss
= fetch_supersect(isbfd
, isection
);
1664 bfd
*obfd
= obfdarg
;
1670 asection
*osection
= bfd_make_section_anyway(obfd
, isection
->name
);
1671 assert(osection
!= NULL
);
1673 osection
->userdata
= ss
;
1674 bfd_set_section_flags(obfd
, osection
, ss
->flags
);
1675 ss
->symbol
= osection
->symbol
;
1676 assert(bfd_set_section_size(obfd
, osection
, ss
->contents
.size
));
1678 vma
= bfd_section_vma(ibfd
, isection
);
1679 assert(bfd_set_section_vma(obfd
, osection
, vma
));
1681 osection
->lma
= isection
->lma
;
1682 assert(bfd_set_section_alignment(obfd
, osection
, ss
->alignment
));
1683 osection
->entsize
= isection
->entsize
;
1684 osection
->output_section
= osection
;
1685 osection
->output_offset
= 0;
1686 isection
->output_section
= osection
;
1687 isection
->output_offset
= 0;
1691 void setup_new_section(bfd
*obfd
, struct supersect
*ss
)
1693 asection
*osection
= bfd_make_section_anyway(obfd
, ss
->name
);
1694 assert(osection
!= NULL
);
1695 bfd_set_section_flags(obfd
, osection
, ss
->flags
);
1697 osection
->userdata
= ss
;
1698 ss
->symbol
= osection
->symbol
;
1699 assert(bfd_set_section_size(obfd
, osection
, ss
->contents
.size
));
1700 assert(bfd_set_section_vma(obfd
, osection
, 0));
1703 assert(bfd_set_section_alignment(obfd
, osection
, ss
->alignment
));
1704 osection
->entsize
= 0;
1705 osection
->output_section
= osection
;
1706 osection
->output_offset
= 0;
1709 void write_section(bfd
*obfd
, asection
*osection
, void *arg
)
1711 struct supersect
*ss
= osection
->userdata
;
1713 if ((ss
->flags
& SEC_GROUP
) != 0 || ss
->contents
.size
== 0)
1717 char *error_message
;
1718 for (relocp
= ss
->new_relocs
.data
;
1719 relocp
< ss
->new_relocs
.data
+ ss
->new_relocs
.size
; relocp
++) {
1721 if (bfd_get_arch(obfd
) == bfd_arch_arm
)
1722 val
= osection
->use_rela_p
? 0 : (*relocp
)->addend
;
1725 bfd_put(bfd_get_reloc_size((*relocp
)->howto
) * 8, obfd
, val
,
1726 ss
->contents
.data
+ (*relocp
)->address
);
1727 if (bfd_install_relocation(obfd
, *relocp
, ss
->contents
.data
,
1728 0, osection
, &error_message
) !=
1730 err(ss
->parent
, "ksplice: error installing reloc: %s",
1735 memcpy(vec_grow(&ss
->relocs
, ss
->new_relocs
.size
), ss
->new_relocs
.data
,
1736 ss
->new_relocs
.size
* sizeof(*ss
->new_relocs
.data
));
1738 bfd_set_reloc(obfd
, osection
,
1739 ss
->relocs
.size
== 0 ? NULL
: ss
->relocs
.data
,
1742 if (ss
->flags
& SEC_HAS_CONTENTS
)
1743 assert(bfd_set_section_contents
1744 (obfd
, osection
, ss
->contents
.data
, 0,
1745 ss
->contents
.size
));
1748 /* Modified function from GNU Binutils objcopy.c
1750 * Mark all the symbols which will be used in output relocations with
1751 * the BSF_KEEP flag so that those symbols will not be stripped.
1753 * Ignore relocations which will not appear in the output file.
1755 void mark_symbols_used_in_relocations(bfd
*abfd
, asection
*isection
,
1758 struct superbfd
*sbfd
= fetch_superbfd(abfd
);
1759 if (isection
->output_section
== NULL
)
1762 struct supersect
*ss
= fetch_supersect(sbfd
, isection
);
1763 ss_mark_symbols_used_in_relocations(ss
);
1766 void ss_mark_symbols_used_in_relocations(struct supersect
*ss
)
1768 /* Examine each symbol used in a relocation. If it's not one of the
1769 special bfd section symbols, then mark it with BSF_KEEP. */
1771 for (relocp
= ss
->relocs
.data
;
1772 relocp
< ss
->relocs
.data
+ ss
->relocs
.size
; relocp
++) {
1773 asymbol
*sym
= *(*relocp
)->sym_ptr_ptr
;
1774 if (!(bfd_is_const_section(sym
->section
) &&
1775 sym
== sym
->section
->symbol
))
1776 sym
->flags
|= BSF_KEEP
;
1778 for (relocp
= ss
->new_relocs
.data
;
1779 relocp
< ss
->new_relocs
.data
+ ss
->new_relocs
.size
; relocp
++) {
1780 asymbol
*sym
= *(*relocp
)->sym_ptr_ptr
;
1781 if (!(bfd_is_const_section(sym
->section
) &&
1782 sym
== sym
->section
->symbol
))
1783 sym
->flags
|= BSF_KEEP
;
1787 static bool deleted_table_section_symbol(bfd
*abfd
, asymbol
*sym
)
1789 struct superbfd
*sbfd
= fetch_superbfd(abfd
);
1790 if (bfd_is_const_section(sym
->section
))
1792 struct supersect
*ss
= fetch_supersect(sbfd
, sym
->section
);
1795 for (symp
= ss
->syms
.data
; symp
< ss
->syms
.data
+ ss
->syms
.size
; symp
++) {
1799 return symp
>= ss
->syms
.data
+ ss
->syms
.size
;
1802 /* Modified function from GNU Binutils objcopy.c
1804 * Choose which symbol entries to copy.
1805 * We don't copy in place, because that confuses the relocs.
1806 * Return the number of symbols to print.
1808 void filter_symbols(bfd
*ibfd
, bfd
*obfd
, struct asymbolp_vec
*osyms
,
1809 struct asymbolp_vec
*isyms
)
1812 struct superbfd
*sbfd
= fetch_superbfd(ibfd
);
1813 for (symp
= isyms
->data
; symp
< isyms
->data
+ isyms
->size
; symp
++) {
1814 asymbol
*sym
= *symp
;
1815 struct supersect
*sym_ss
= NULL
;
1816 if (!bfd_is_const_section(sym
->section
))
1817 sym_ss
= fetch_supersect(sbfd
, sym
->section
);
1821 if (mode("keep") && (sym
->flags
& BSF_GLOBAL
) != 0 &&
1822 !(mode("keep-primary") && sym_ss
!= NULL
&& sym_ss
->new))
1823 sym
->flags
= (sym
->flags
& ~BSF_GLOBAL
) | BSF_LOCAL
;
1825 if (mode("finalize") && (sym
->flags
& BSF_GLOBAL
) != 0)
1826 sym
->flags
= (sym
->flags
& ~BSF_GLOBAL
) | BSF_LOCAL
;
1828 if ((sym
->flags
& BSF_KEEP
) != 0 /* Used in relocation. */
1829 || ((sym
->flags
& BSF_SECTION_SYM
) != 0 && sym_ss
!= NULL
&&
1832 else if ((sym
->flags
& (BSF_GLOBAL
| BSF_WEAK
)) != 0 &&
1833 sym_ss
!= NULL
&& sym_ss
->keep
)
1835 else if (mode("keep-primary") &&
1836 starts_with(sym
->section
->name
, "__ksymtab"))
1839 if (deleted_table_section_symbol(ibfd
, sym
))
1842 if (bfd_is_com_section(sym
->section
))
1846 keep
= !str_in_set(sym
->name
, &rmsyms
);
1849 if (sym_ss
!= NULL
&& !sym_ss
->keep
) {
1850 err(sbfd
, "Kept symbol %s in unkept section "
1851 "%s\n", sym
->name
, sym
->section
->name
);
1854 *vec_grow(osyms
, 1) = sym
;
1859 void read_str_set(struct str_vec
*strs
)
1863 assert(getline(&buf
, &n
, stdin
) >= 0);
1867 char *str
= strtok_r(buf
, " \n", &saveptr
);
1871 *vec_grow(strs
, 1) = str
;
1875 bool str_in_set(const char *str
, const struct str_vec
*strs
)
1878 for (strp
= strs
->data
; strp
< strs
->data
+ strs
->size
; strp
++) {
1879 if (strcmp(str
, *strp
) == 0)
1885 bool is_table_section(const char *name
, bool consider_other
)
1887 struct supersect
*tables_ss
=
1888 fetch_supersect(offsets_sbfd
,
1889 bfd_get_section_by_name(offsets_sbfd
->abfd
,
1890 ".ksplice_table_sections"));
1891 const struct table_section
*ts
;
1892 for (ts
= tables_ss
->contents
.data
;
1893 (void *)ts
< tables_ss
->contents
.data
+ tables_ss
->contents
.size
;
1895 if (strcmp(name
, read_string(tables_ss
, &ts
->sect
)) == 0)
1897 const char *osect_name
= read_string(tables_ss
,
1899 if (consider_other
&& osect_name
!= NULL
&&
1900 strcmp(name
, osect_name
) == 0)
1906 enum supersect_type
supersect_type(struct supersect
*ss
)
1908 if (starts_with(ss
->name
, ".ksplice"))
1909 return SS_TYPE_KSPLICE
;
1911 if (starts_with(ss
->name
, ".init"))
1912 return SS_TYPE_IGNORED
;
1913 if (starts_with(ss
->name
, ".security_initcall.init"))
1914 return SS_TYPE_IGNORED
;
1915 if (starts_with(ss
->name
, ".con_initcall.init"))
1916 return SS_TYPE_IGNORED
;
1917 if (starts_with(ss
->name
, ".x86cpuvendor.init"))
1918 return SS_TYPE_IGNORED
;
1919 if (starts_with(ss
->name
, ".early_param.init"))
1920 return SS_TYPE_IGNORED
;
1921 if (starts_with(ss
->name
, ".taglist.init"))
1922 return SS_TYPE_IGNORED
;
1923 if (starts_with(ss
->name
, ".arch.info.init"))
1924 return SS_TYPE_IGNORED
;
1925 if (starts_with(ss
->name
, ".proc.info.init"))
1926 return SS_TYPE_IGNORED
;
1927 /* .pci_fixup_* sections really should be treated as global rodata
1928 referenced only from quirks.c */
1929 if (starts_with(ss
->name
, ".pci_fixup_"))
1930 return SS_TYPE_IGNORED
;
1931 /* .builtin_fw sections are similar to .pci_fixup */
1932 if (starts_with(ss
->name
, ".builtin_fw"))
1933 return SS_TYPE_IGNORED
;
1934 /* same for .tracedata */
1935 if (starts_with(ss
->name
, ".tracedata"))
1936 return SS_TYPE_IGNORED
;
1937 if (starts_with(ss
->name
, ".debug"))
1938 return SS_TYPE_IGNORED
;
1939 /* .eh_frame should probably be discarded, not ignored */
1940 if (starts_with(ss
->name
, ".eh_frame"))
1941 return SS_TYPE_IGNORED
;
1942 if (config
->ignore_devinit
&& starts_with(ss
->name
, ".devinit"))
1943 return SS_TYPE_IGNORED
;
1944 if (config
->ignore_meminit
&& starts_with(ss
->name
, ".meminit"))
1945 return SS_TYPE_IGNORED
;
1946 if (config
->ignore_cpuinit
&& starts_with(ss
->name
, ".cpuinit"))
1947 return SS_TYPE_IGNORED
;
1948 if (config
->ignore_devinit
&& starts_with(ss
->name
, ".devexit"))
1949 return SS_TYPE_IGNORED
;
1950 if (config
->ignore_meminit
&& starts_with(ss
->name
, ".memexit"))
1951 return SS_TYPE_IGNORED
;
1952 if (config
->ignore_cpuinit
&& starts_with(ss
->name
, ".cpuexit"))
1953 return SS_TYPE_IGNORED
;
1954 if (starts_with(ss
->name
, ".vgetcpu_mode") ||
1955 starts_with(ss
->name
, ".jiffies") ||
1956 starts_with(ss
->name
, ".wall_jiffies") ||
1957 starts_with(ss
->name
, ".vxtime") ||
1958 starts_with(ss
->name
, ".sys_tz") ||
1959 starts_with(ss
->name
, ".sysctl_vsyscall") ||
1960 starts_with(ss
->name
, ".xtime") ||
1961 starts_with(ss
->name
, ".xtime_lock") ||
1962 starts_with(ss
->name
, ".vsyscall"))
1963 return SS_TYPE_IGNORED
;
1964 if (starts_with(ss
->name
, ".vdso"))
1965 return SS_TYPE_IGNORED
;
1967 if (bfd_get_section_by_name(ss
->parent
->abfd
, ".exitcall.exit") == NULL
) {
1968 if (starts_with(ss
->name
, ".exit.text"))
1969 return SS_TYPE_TEXT
;
1970 if (starts_with(ss
->name
, ".exit.data"))
1971 return SS_TYPE_DATA
;
1972 } else if (starts_with(ss
->name
, ".exit.text") ||
1973 starts_with(ss
->name
, ".exit.data"))
1974 return SS_TYPE_IGNORED
;
1976 if (starts_with(ss
->name
, ".text") ||
1977 starts_with(ss
->name
, ".kernel.text") ||
1978 starts_with(ss
->name
, ".devinit.text") ||
1979 starts_with(ss
->name
, ".meminit.text") ||
1980 starts_with(ss
->name
, ".cpuinit.text") ||
1981 starts_with(ss
->name
, ".devexit.text") ||
1982 starts_with(ss
->name
, ".memexit.text") ||
1983 starts_with(ss
->name
, ".cpuexit.text") ||
1984 starts_with(ss
->name
, ".ref.text") ||
1985 starts_with(ss
->name
, ".spinlock.text") ||
1986 starts_with(ss
->name
, ".kprobes.text") ||
1987 starts_with(ss
->name
, ".sched.text"))
1988 return SS_TYPE_TEXT
;
1991 if (sscanf(ss
->name
, ".rodata.str%*u.%*u%n", &n
) >= 0 &&
1992 n
== strlen(ss
->name
))
1993 return SS_TYPE_STRING
;
1995 if (starts_with(ss
->name
, ".rodata") ||
1996 starts_with(ss
->name
, ".kernel.rodata") ||
1997 starts_with(ss
->name
, ".devinit.rodata") ||
1998 starts_with(ss
->name
, ".meminit.rodata") ||
1999 starts_with(ss
->name
, ".cpuinit.rodata") ||
2000 starts_with(ss
->name
, ".devexit.rodata") ||
2001 starts_with(ss
->name
, ".memexit.rodata") ||
2002 starts_with(ss
->name
, ".cpuexit.rodata") ||
2003 starts_with(ss
->name
, ".ref.rodata") ||
2004 starts_with(ss
->name
, "__markers_strings"))
2005 return SS_TYPE_RODATA
;
2007 if (starts_with(ss
->name
, ".bss"))
2008 return SS_TYPE_DATA
;
2010 /* Ignore .data.percpu sections */
2011 if (starts_with(ss
->name
, ".data.percpu") ||
2012 starts_with(ss
->name
, ".kernel.data.percpu"))
2013 return SS_TYPE_IGNORED
;
2014 if (starts_with(ss
->name
, ".data") ||
2015 starts_with(ss
->name
, ".kernel.data") ||
2016 starts_with(ss
->name
, ".devinit.data") ||
2017 starts_with(ss
->name
, ".cpuinit.data") ||
2018 starts_with(ss
->name
, ".meminit.data") ||
2019 starts_with(ss
->name
, ".devexit.data") ||
2020 starts_with(ss
->name
, ".memexit.data") ||
2021 starts_with(ss
->name
, ".cpuexit.data") ||
2022 starts_with(ss
->name
, ".ref.data") ||
2023 starts_with(ss
->name
, "__markers"))
2024 return SS_TYPE_DATA
;
2026 if (starts_with(ss
->name
, "__ksymtab"))
2027 return SS_TYPE_EXPORT
;
2028 if (starts_with(ss
->name
, "__kcrctab"))
2029 return SS_TYPE_EXPORT
;
2031 if (is_table_section(ss
->name
, true))
2032 return SS_TYPE_SPECIAL
;
2034 if (starts_with(ss
->name
, ".ARM."))
2035 return SS_TYPE_SPECIAL
;
2037 if (starts_with(ss
->name
, ".note"))
2038 return SS_TYPE_IGNORED
;
2039 if (starts_with(ss
->name
, ".comment"))
2040 return SS_TYPE_IGNORED
;
2041 if (starts_with(ss
->name
, "__param"))
2042 return SS_TYPE_IGNORED
;
2043 if (starts_with(ss
->name
, ".exitcall.exit"))
2044 return SS_TYPE_IGNORED
;
2045 if (starts_with(ss
->name
, ".modinfo"))
2046 return SS_TYPE_IGNORED
;
2048 return SS_TYPE_UNKNOWN
;
2051 void initialize_supersect_types(struct superbfd
*sbfd
)
2054 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
2055 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
2056 ss
->type
= supersect_type(ss
);
2057 if (ss
->type
== SS_TYPE_UNKNOWN
) {
2058 err(sbfd
, "Unknown section type: %s\n", ss
->name
);
2064 static void init_label_map(struct superbfd
*sbfd
)
2066 vec_init(&sbfd
->maps
);
2067 struct label_map
*map
, *map2
;
2070 for (symp
= sbfd
->syms
.data
;
2071 symp
< sbfd
->syms
.data
+ sbfd
->syms
.size
; symp
++) {
2072 asymbol
*csym
= canonical_symbol(sbfd
, *symp
);
2075 for (map
= sbfd
->maps
.data
;
2076 map
< sbfd
->maps
.data
+ sbfd
->maps
.size
; map
++) {
2077 if (map
->csym
== csym
)
2080 if (map
< sbfd
->maps
.data
+ sbfd
->maps
.size
)
2082 map
= vec_grow(&sbfd
->maps
, 1);
2086 map
->label
= symbol_label(sbfd
, csym
);
2088 for (map
= sbfd
->maps
.data
;
2089 map
< sbfd
->maps
.data
+ sbfd
->maps
.size
; map
++) {
2090 for (map2
= sbfd
->maps
.data
;
2091 map2
< sbfd
->maps
.data
+ sbfd
->maps
.size
; map2
++) {
2092 if (strcmp(map
->label
, map2
->label
) != 0)
2100 for (map
= sbfd
->maps
.data
;
2101 map
< sbfd
->maps
.data
+ sbfd
->maps
.size
; map
++) {
2102 if (map
->count
> 1) {
2104 assert(asprintf(&buf
, "%s~%d", map
->label
,
2108 map
->orig_label
= map
->label
;
2112 static const char *label_lookup(struct superbfd
*sbfd
, asymbol
*sym
)
2114 struct label_map
*map
;
2115 asymbol
*csym
= canonical_symbol(sbfd
, sym
);
2116 for (map
= sbfd
->maps
.data
;
2117 map
< sbfd
->maps
.data
+ sbfd
->maps
.size
; map
++) {
2118 if (csym
== map
->csym
)
2121 return symbol_label(sbfd
, sym
);
2124 static void print_label_map(struct superbfd
*sbfd
)
2126 struct label_map
*map
;
2127 for (map
= sbfd
->maps
.data
;
2128 map
< sbfd
->maps
.data
+ sbfd
->maps
.size
; map
++) {
2129 if (strcmp(map
->orig_label
, map
->label
) == 0)
2131 debug1(sbfd
, "Label change: %s -> %s\n",
2132 map
->label
, map
->orig_label
);
2136 static void label_map_set(struct superbfd
*sbfd
, const char *oldlabel
,
2139 struct label_map
*map
;
2140 for (map
= sbfd
->maps
.data
;
2141 map
< sbfd
->maps
.data
+ sbfd
->maps
.size
; map
++) {
2142 if (strcmp(map
->orig_label
, oldlabel
) == 0) {
2143 if (strcmp(map
->orig_label
, map
->label
) != 0 &&
2144 strcmp(map
->label
, label
) != 0)
2153 static struct span
*new_span(struct superbfd
*sbfd
, asection
*sect
,
2154 bfd_vma start
, bfd_vma size
)
2156 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
2157 struct span
*span
= vec_grow(&ss
->spans
, 1);
2159 span
->start
= start
;
2164 asymbol
**symp
= symbolp_scan(sbfd
, sect
, span
->start
);
2166 span
->symbol
= *symp
;
2167 span
->label
= label_lookup(sbfd
, span
->symbol
);
2169 span
->symbol
= NULL
;
2170 const char *label
= label_lookup(sbfd
, sect
->symbol
);
2171 if (span
->start
!= 0) {
2173 assert(asprintf(&buf
, "%s<span:%lx>", label
,
2174 (unsigned long)span
->start
) >= 0);
2177 span
->label
= label
;
2183 static void initialize_string_spans(struct superbfd
*sbfd
, asection
*sect
)
2185 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
2187 for (str
= ss
->contents
.data
;
2188 (void *)str
< ss
->contents
.data
+ ss
->contents
.size
;) {
2189 bfd_vma start
= (unsigned long)str
-
2190 (unsigned long)ss
->contents
.data
;
2191 bfd_vma size
= strlen(str
) + 1;
2192 while ((start
+ size
) % (1 << ss
->alignment
) != 0 &&
2193 start
+ size
< ss
->contents
.size
) {
2194 if (str
[size
] != '\0')
2198 new_span(sbfd
, sect
, start
, size
);
2203 static void initialize_spans(struct superbfd
*sbfd
)
2206 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
2207 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
2208 if (ss
->type
== SS_TYPE_STRING
)
2209 initialize_string_spans(sbfd
, sect
);
2210 else if (ss
->type
!= SS_TYPE_SPECIAL
&&
2211 ss
->type
!= SS_TYPE_EXPORT
)
2212 new_span(sbfd
, sect
, 0, ss
->contents
.size
);
2216 struct span
*reloc_target_span(struct supersect
*ss
, arelent
*reloc
)
2218 asymbol
*sym_ptr
= *reloc
->sym_ptr_ptr
;
2219 if (bfd_is_const_section(sym_ptr
->section
))
2222 bfd_vma addend
= get_reloc_offset(ss
, reloc
, true) + sym_ptr
->value
;
2223 struct supersect
*sym_ss
=
2224 fetch_supersect(ss
->parent
, sym_ptr
->section
);
2225 struct span
*span
, *target_span
= sym_ss
->spans
.data
;
2226 for (span
= sym_ss
->spans
.data
;
2227 span
< sym_ss
->spans
.data
+ sym_ss
->spans
.size
; span
++) {
2228 if (addend
>= span
->start
&& addend
< span
->start
+ span
->size
)
2234 struct span
*reloc_address_span(struct supersect
*ss
, arelent
*reloc
)
2237 for (span
= ss
->spans
.data
; span
< ss
->spans
.data
+ ss
->spans
.size
;
2239 if (reloc
->address
>= span
->start
&&
2240 reloc
->address
< span
->start
+ span
->size
)
2246 void compute_span_shifts(struct superbfd
*sbfd
)
2250 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
2251 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
2252 if (!ss
->keep
|| ss
->type
== SS_TYPE_EXPORT
)
2254 bfd_size_type offset
= 0;
2255 for (span
= ss
->spans
.data
;
2256 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++) {
2259 span
->shift
= offset
- span
->start
;
2260 offset
+= span
->size
;
2265 void remove_unkept_spans(struct superbfd
*sbfd
)
2269 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
2270 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
2271 if (ss
->type
== SS_TYPE_EXPORT
)
2273 struct arelentp_vec orig_relocs
;
2274 vec_move(&orig_relocs
, &ss
->relocs
);
2275 arelent
**relocp
, *reloc
;
2276 for (relocp
= orig_relocs
.data
;
2277 relocp
< orig_relocs
.data
+ orig_relocs
.size
; relocp
++) {
2279 asymbol
*sym
= *reloc
->sym_ptr_ptr
;
2280 span
= reloc_target_span(ss
, reloc
);
2281 if ((span
!= NULL
&& span
->keep
&& span
->shift
== 0) ||
2282 bfd_is_const_section(sym
->section
)) {
2283 *vec_grow(&ss
->relocs
, 1) = reloc
;
2286 if (span
!= NULL
&& span
->keep
) {
2287 arelent
*new_reloc
= malloc(sizeof(*new_reloc
));
2288 *new_reloc
= *reloc
;
2290 get_reloc_offset(ss
, reloc
, false);
2291 new_reloc
->addend
+= span
->shift
;
2292 *vec_grow(&ss
->new_relocs
, 1) = new_reloc
;
2297 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
2298 struct supersect
*ss
= fetch_supersect(sbfd
, sect
), orig_ss
;
2299 if (!ss
->keep
|| ss
->type
== SS_TYPE_EXPORT
)
2301 supersect_move(&orig_ss
, ss
);
2302 vec_init(&ss
->spans
);
2303 for (span
= orig_ss
.spans
.data
;
2304 span
< orig_ss
.spans
.data
+ orig_ss
.spans
.size
; span
++) {
2307 struct span
*new_span
= vec_grow(&ss
->spans
, 1);
2309 new_span
->start
= span
->start
+ span
->shift
;
2310 new_span
->shift
= 0;
2311 sect_copy(ss
, sect_do_grow(ss
, 1, span
->size
, 1),
2312 &orig_ss
, orig_ss
.contents
.data
+ span
->start
,