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 void rm_relocs(struct superbfd
*isbfd
);
108 void rm_some_relocs(struct supersect
*ss
);
109 void write_ksplice_reloc(struct supersect
*ss
, arelent
*orig_reloc
);
110 void blot_section(struct supersect
*ss
, int offset
, reloc_howto_type
*howto
);
111 void write_ksplice_section(struct superbfd
*sbfd
, asymbol
**symp
);
112 void write_ksplice_patch(struct superbfd
*sbfd
, const char *sectname
);
113 void write_ksplice_deleted_patch(struct superbfd
*sbfd
, const char *name
,
115 void filter_table_sections(struct superbfd
*isbfd
);
116 void filter_table_section(struct superbfd
*sbfd
, const struct table_section
*s
);
117 void keep_if_referenced(bfd
*abfd
, asection
*sect
, void *ignored
);
118 void check_for_ref_to_section(bfd
*abfd
, asection
*looking_at
,
120 bfd_boolean
copy_object(bfd
*ibfd
, bfd
*obfd
);
121 void setup_section(bfd
*ibfd
, asection
*isection
, void *obfdarg
);
122 static void setup_new_section(bfd
*obfd
, struct supersect
*ss
);
123 static void write_section(bfd
*obfd
, asection
*osection
, void *arg
);
124 void mark_symbols_used_in_relocations(bfd
*abfd
, asection
*isection
,
126 static void ss_mark_symbols_used_in_relocations(struct supersect
*ss
);
127 void filter_symbols(bfd
*ibfd
, bfd
*obfd
, struct asymbolp_vec
*osyms
,
128 struct asymbolp_vec
*isyms
);
129 static bool deleted_table_section_symbol(bfd
*abfd
, asymbol
*sym
);
130 void read_str_set(struct str_vec
*strs
);
131 bool str_in_set(const char *str
, const struct str_vec
*strs
);
132 bool is_table_section(asection
*sect
);
133 bool is_special(asection
*sect
);
134 struct supersect
*make_section(struct superbfd
*sbfd
, const char *name
);
135 void __attribute__((format(printf
, 3, 4)))
136 write_string(struct supersect
*ss
, const char **addr
, const char *fmt
, ...);
137 void rm_some_exports(struct superbfd
*isbfd
, const struct export_desc
*ed
);
138 void write_ksplice_export(struct superbfd
*sbfd
, const char *symname
,
139 const char *export_type
, bool del
);
140 void write_reloc(struct supersect
*ss
, const void *addr
, asymbol
**symp
,
142 arelent
*create_reloc(struct supersect
*ss
, const void *addr
, asymbol
**symp
,
144 static void match_global_symbol_sections(struct superbfd
*oldsbfd
,
145 struct superbfd
*newsbfd
);
146 static void match_sections_by_name(struct superbfd
*oldsbfd
,
147 struct superbfd
*newsbfd
);
148 static void match_sections_by_contents(struct superbfd
*oldsbfd
,
149 struct superbfd
*newsbfd
);
150 static void match_sections_by_label(struct superbfd
*oldsbfd
,
151 struct superbfd
*newsbfd
);
152 static void mark_new_sections(struct superbfd
*sbfd
);
153 static void handle_deleted_sections(struct superbfd
*oldsbfd
,
154 struct superbfd
*newsbfd
);
155 static void compare_matched_sections(struct superbfd
*sbfd
);
156 static void update_nonzero_offsets(struct superbfd
*sbfd
);
157 static void handle_nonzero_offset_relocs(struct supersect
*ss
);
159 struct str_vec delsects
, rmsyms
;
160 struct export_desc_vec exports
;
163 const char *modestr
, *kid
;
165 struct superbfd
*offsets_sbfd
= NULL
;
167 #define mode(str) starts_with(modestr, str)
169 DECLARE_VEC_TYPE(unsigned long, addr_vec
);
170 DEFINE_HASH_TYPE(struct addr_vec
, addr_vec_hash
,
171 addr_vec_hash_init
, addr_vec_hash_free
, addr_vec_hash_lookup
,
173 struct addr_vec_hash system_map
;
175 struct bool_hash system_map_written
;
176 struct ulong_hash ksplice_symbol_offset
;
177 struct ulong_hash ksplice_string_offset
;
179 void load_system_map()
181 const char *config_dir
= getenv("KSPLICE_CONFIG_DIR");
184 assert(asprintf(&file
, "%s/System.map", config_dir
) >= 0);
185 FILE *fp
= fopen(file
, "r");
187 addr_vec_hash_init(&system_map
);
191 while (fscanf(fp
, "%lx %c %as\n", &addr
, &type
, &sym
) == 3)
192 *vec_grow(addr_vec_hash_lookup(&system_map
, sym
, TRUE
),
199 char *kmodsrc
= getenv("KSPLICE_KMODSRC"), *offsets_file
;
200 assert(kmodsrc
!= NULL
);
201 assert(asprintf(&offsets_file
, "%s/offsets.o", kmodsrc
) >= 0);
202 bfd
*offsets_bfd
= bfd_openr(offsets_file
, NULL
);
203 assert(offsets_bfd
!= NULL
);
205 assert(bfd_check_format_matches(offsets_bfd
, bfd_object
, &matching
));
206 offsets_sbfd
= fetch_superbfd(offsets_bfd
);
209 bool matchable_data_section(struct superbfd
*sbfd
, asection
*isection
)
211 if (bfd_is_const_section(isection
))
213 struct supersect
*ss
= fetch_supersect(sbfd
, isection
);
214 if (starts_with(isection
->name
, ".rodata")) {
215 if (starts_with(isection
->name
, ".rodata.str"))
219 if (starts_with(isection
->name
, ".data")) {
220 /* Ignore .data.percpu sections */
221 if (starts_with(isection
->name
, ".data.percpu"))
223 return ss
->relocs
.size
!= 0;
228 bool matchable_text_section(struct superbfd
*sbfd
, asection
*isection
)
230 if (bfd_is_const_section(isection
))
232 if (starts_with(isection
->name
, ".text"))
234 if (starts_with(isection
->name
, ".exit.text")
235 && bfd_get_section_by_name(sbfd
->abfd
, ".exitcall.exit") == NULL
)
240 bool ignored_section(struct superbfd
*sbfd
, asection
*isection
)
242 if (bfd_is_const_section(isection
))
244 if (starts_with(isection
->name
, ".init"))
246 if (starts_with(isection
->name
, ".debug"))
251 bool unchangeable_section(struct superbfd
*sbfd
, asection
*isection
)
253 if (bfd_is_const_section(isection
))
255 if (starts_with(isection
->name
, ".bss"))
257 if (starts_with(isection
->name
, ".data"))
262 int main(int argc
, char *argv
[])
265 bfd
*ibfd
= bfd_openr(argv
[1], NULL
);
269 assert(bfd_check_format_matches(ibfd
, bfd_object
, &matching
));
271 const char *output_target
= bfd_get_target(ibfd
);
272 bfd
*obfd
= bfd_openw(argv
[2], output_target
);
275 struct superbfd
*isbfd
= fetch_superbfd(ibfd
);
277 bool_hash_init(&system_map_written
);
278 ulong_hash_init(&ksplice_symbol_offset
);
279 ulong_hash_init(&ksplice_string_offset
);
282 if (mode("keep-primary")) {
284 do_keep_primary(isbfd
, argv
[4]);
285 } else if (mode("keep-helper")) {
286 do_keep_helper(isbfd
);
287 } else if (mode("finalize")) {
289 } else if (mode("rmsyms")) {
293 copy_object(ibfd
, obfd
);
295 if (offsets_sbfd
!= NULL
)
296 assert(bfd_close(offsets_sbfd
->abfd
));
297 assert(bfd_close(obfd
));
298 assert(bfd_close(ibfd
));
302 void do_keep_primary(struct superbfd
*isbfd
, const char *pre
)
304 struct bfd
*prebfd
= bfd_openr(pre
, NULL
);
305 assert(prebfd
!= NULL
);
307 assert(bfd_check_format_matches(prebfd
, bfd_object
, &matching
));
309 struct superbfd
*presbfd
= fetch_superbfd(prebfd
);
311 match_global_symbol_sections(presbfd
, isbfd
);
312 printf("Matched global\n");
313 match_sections_by_name(presbfd
, isbfd
);
314 printf("Matched by name\n");
315 match_sections_by_label(presbfd
, isbfd
);
316 printf("Matched by label\n");
317 match_sections_by_contents(presbfd
, isbfd
);
318 printf("Matched by contents\n");
322 compare_matched_sections(isbfd
);
323 update_nonzero_offsets(isbfd
);
324 mark_new_sections(isbfd
);
328 handle_deleted_sections(presbfd
, isbfd
);
329 handle_section_symbol_renames(presbfd
, isbfd
);
332 compare_exported_symbols(presbfd
, isbfd
, "");
333 compare_exported_symbols(isbfd
, presbfd
, "del_");
335 assert(bfd_close(prebfd
));
341 for (sect
= isbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
342 struct supersect
*ss
= fetch_supersect(isbfd
, sect
);
344 if (is_special(sect
))
346 if (ss
->new || ss
->patch
)
350 const char **sectname
;
351 printf("Label name changes:\n");
352 print_label_map(isbfd
);
354 printf("Changed text sections:\n");
355 for (sect
= isbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
356 struct supersect
*ss
= fetch_supersect(isbfd
, sect
);
358 printf(" %s\n", sect
->name
);
361 printf("New sections:\n");
362 for (sect
= isbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
363 struct supersect
*ss
= fetch_supersect(isbfd
, sect
);
365 printf(" %s\n", sect
->name
);
367 if (delsects
.size
!= 0) {
368 printf("Deleted section names:\n");
369 for (sectname
= delsects
.data
;
370 sectname
< delsects
.data
+ delsects
.size
; sectname
++)
371 printf(" %s\n", *sectname
);
373 const struct export_desc
*ed
;
374 for (ed
= exports
.data
; ed
< exports
.data
+ exports
.size
; ed
++) {
375 const char **symname
;
376 bool del
= starts_with(ed
->sectname
, "del___ksymtab");
377 const char *export_type
= ed
->sectname
+ strlen("__ksymtab");
379 export_type
+= strlen("_del");
380 for (symname
= ed
->names
.data
;
381 symname
< ed
->names
.data
+ ed
->names
.size
; symname
++)
382 printf("Export %s(%s): %s\n",
383 del
? "deletion" : "addition",
384 export_type
, *symname
);
387 for (sect
= isbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
388 struct supersect
*ss
= fetch_supersect(isbfd
, sect
);
389 if (!ss
->patch
&& !ss
->new)
391 asymbol
**symp
= canonical_symbolp(isbfd
, sect
->symbol
);
394 write_ksplice_section(isbfd
, symp
);
396 write_ksplice_patch(isbfd
, sect
->name
);
399 for (ed
= exports
.data
; ed
< exports
.data
+ exports
.size
; ed
++) {
400 if (starts_with(ed
->sectname
, "del___ksymtab")) {
401 const char *export_type
=
402 ed
->sectname
+ strlen("del___ksymtab");
403 const char **symname
;
404 for (symname
= ed
->names
.data
;
405 symname
< ed
->names
.data
+ ed
->names
.size
;
407 write_ksplice_export(isbfd
, *symname
,
410 rm_some_exports(isbfd
, ed
);
415 filter_table_sections(isbfd
);
418 void do_keep_helper(struct superbfd
*isbfd
)
424 for (sect
= isbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
425 struct supersect
*ss
= fetch_supersect(isbfd
, sect
);
427 if (is_special(sect
) && !starts_with(sect
->name
, "__ksymtab") &&
428 !starts_with(sect
->name
, "__kcrctab"))
430 if (matchable_text_section(isbfd
, sect
))
435 bfd_map_over_sections(isbfd
->abfd
, keep_if_referenced
, NULL
);
438 for (sect
= isbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
439 struct supersect
*ss
= fetch_supersect(isbfd
, sect
);
440 asymbol
**symp
= canonical_symbolp(isbfd
, sect
->symbol
);
443 asymbol
*sym
= *symp
;
444 if ((sym
->flags
& BSF_WEAK
) != 0)
446 if (bfd_get_section_size(sect
) == 0)
448 if (ss
->keep
&& (matchable_text_section(isbfd
, sect
) ||
449 matchable_data_section(isbfd
, sect
)))
450 write_ksplice_section(isbfd
, symp
);
454 filter_table_sections(isbfd
);
457 void do_finalize(struct superbfd
*isbfd
)
464 void do_rmsyms(struct superbfd
*isbfd
)
466 read_str_set(&rmsyms
);
471 struct export_vec
*get_export_syms(struct superbfd
*sbfd
)
474 struct export_vec
*exports
;
475 exports
= malloc(sizeof(*exports
));
476 assert(exports
!= NULL
);
479 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
480 if (!starts_with(sect
->name
, "__ksymtab") ||
481 ends_with(sect
->name
, "_strings"))
483 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
484 struct kernel_symbol
*sym
;
485 assert(ss
->contents
.size
* 2 == ss
->relocs
.size
*
486 sizeof(struct kernel_symbol
));
487 for (sym
= ss
->contents
.data
;
488 (void *)sym
< ss
->contents
.data
+ ss
->contents
.size
;
490 struct export
*exp
= vec_grow(exports
, 1);
492 read_string(ss
, (const char *const *)&sym
->name
);
499 void compare_exported_symbols(struct superbfd
*oldsbfd
,
500 struct superbfd
*newsbfd
, char *addstr
)
502 struct export_vec
*new_exports
, *old_exports
;
503 new_exports
= get_export_syms(newsbfd
);
504 if (new_exports
== NULL
)
506 old_exports
= get_export_syms(oldsbfd
);
507 struct export
*old
, *new;
508 asection
*last_sect
= NULL
;
509 struct export_desc
*ed
;
510 for (new = new_exports
->data
; new < new_exports
->data
+
511 new_exports
->size
; new++) {
513 if (old_exports
!= NULL
) {
514 for (old
= old_exports
->data
; old
< old_exports
->data
+
515 old_exports
->size
; old
++) {
516 if (strcmp(new->name
, old
->name
) == 0 &&
517 strcmp(new->sect
->name
, old
->sect
->name
)
524 if (last_sect
!= new->sect
) {
525 last_sect
= new->sect
;
526 ed
= vec_grow(&exports
, 1);
528 assert(asprintf(§name
, "%s%s", addstr
,
529 new->sect
->name
) >= 0);
530 ed
->sectname
= sectname
;
531 vec_init(&ed
->names
);
534 *vec_grow(&ed
->names
, 1) = new->name
;
538 void match_sections(struct supersect
*oldss
, struct supersect
*newss
)
540 if (oldss
->match
== newss
&& newss
->match
== oldss
)
542 if (oldss
->match
!= NULL
) {
543 fprintf(stderr
, "Matching conflict: old %s: %s != %s\n",
544 oldss
->name
, oldss
->match
->name
, newss
->name
);
547 if (newss
->match
!= NULL
) {
548 fprintf(stderr
, "Matching conflict: new %s: %s != %s\n",
549 newss
->name
, newss
->match
->name
, oldss
->name
);
552 oldss
->match
= newss
;
553 newss
->match
= oldss
;
554 printf("Matched old %s to new %s\n", oldss
->name
, newss
->name
);
557 static void match_global_symbol_sections(struct superbfd
*oldsbfd
,
558 struct superbfd
*newsbfd
)
560 asymbol
**oldsymp
, **newsymp
;
561 for (oldsymp
= oldsbfd
->syms
.data
;
562 oldsymp
< oldsbfd
->syms
.data
+ oldsbfd
->syms
.size
; oldsymp
++) {
563 asymbol
*oldsym
= *oldsymp
;
564 if ((oldsym
->flags
& BSF_GLOBAL
) == 0 ||
565 bfd_is_const_section(oldsym
->section
))
567 for (newsymp
= newsbfd
->syms
.data
;
568 newsymp
< newsbfd
->syms
.data
+ newsbfd
->syms
.size
;
570 asymbol
*newsym
= *newsymp
;
571 if ((newsym
->flags
& BSF_GLOBAL
) == 0 ||
572 bfd_is_const_section(oldsym
->section
))
574 if (strcmp(oldsym
->name
, newsym
->name
) != 0)
576 struct supersect
*oldss
=
577 fetch_supersect(oldsbfd
, oldsym
->section
);
578 struct supersect
*newss
=
579 fetch_supersect(newsbfd
, newsym
->section
);
580 match_sections(oldss
, newss
);
585 static void match_sections_by_name(struct superbfd
*oldsbfd
,
586 struct superbfd
*newsbfd
)
588 asection
*newp
, *oldp
;
589 for (newp
= newsbfd
->abfd
->sections
; newp
!= NULL
; newp
= newp
->next
) {
590 oldp
= bfd_get_section_by_name(oldsbfd
->abfd
, newp
->name
);
591 if (oldp
== NULL
|| is_special(newp
))
593 if (static_local_symbol(newsbfd
,
594 canonical_symbol(newsbfd
,
598 struct supersect
*oldss
= fetch_supersect(oldsbfd
, oldp
);
599 struct supersect
*newss
= fetch_supersect(newsbfd
, newp
);
600 match_sections(oldss
, newss
);
604 static void match_sections_by_label(struct superbfd
*oldsbfd
,
605 struct superbfd
*newsbfd
)
607 asection
*oldsect
, *newsect
;
608 struct supersect
*oldss
, *newss
;
609 for (newsect
= newsbfd
->abfd
->sections
; newsect
!= NULL
;
610 newsect
= newsect
->next
) {
611 if (is_special(newsect
))
613 for (oldsect
= oldsbfd
->abfd
->sections
; oldsect
!= NULL
;
614 oldsect
= oldsect
->next
) {
615 if (strcmp(label_lookup(newsbfd
, newsect
->symbol
),
616 label_lookup(oldsbfd
, oldsect
->symbol
)) != 0)
618 oldss
= fetch_supersect(oldsbfd
, oldsect
);
619 newss
= fetch_supersect(newsbfd
, newsect
);
620 match_sections(oldss
, newss
);
625 static void match_sections_by_contents(struct superbfd
*oldsbfd
,
626 struct superbfd
*newsbfd
)
628 asection
*oldsect
, *newsect
;
629 struct supersect
*oldss
, *newss
;
630 for (newsect
= newsbfd
->abfd
->sections
; newsect
!= NULL
;
631 newsect
= newsect
->next
) {
632 for (oldsect
= oldsbfd
->abfd
->sections
; oldsect
!= NULL
;
633 oldsect
= oldsect
->next
) {
634 oldss
= fetch_supersect(oldsbfd
, oldsect
);
635 newss
= fetch_supersect(newsbfd
, newsect
);
636 if (!matchable_data_section(newsbfd
, newsect
) ||
637 !matchable_data_section(oldsbfd
, oldsect
))
639 if (oldss
->relocs
.size
!= 0 || newss
->relocs
.size
!= 0)
641 if (oldss
->contents
.size
!= newss
->contents
.size
)
643 if (memcmp(oldss
->contents
.data
, newss
->contents
.data
,
644 oldss
->contents
.size
) != 0)
646 match_sections(oldss
, newss
);
651 static void mark_new_sections(struct superbfd
*sbfd
)
654 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
655 if (is_special(sect
) || ignored_section(sbfd
, sect
))
657 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
658 if (ss
->match
== NULL
)
663 static void handle_deleted_sections(struct superbfd
*oldsbfd
,
664 struct superbfd
*newsbfd
)
667 for (sect
= oldsbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
668 if (is_special(sect
) || ignored_section(oldsbfd
, sect
))
670 if (!matchable_text_section(oldsbfd
, sect
))
672 struct supersect
*ss
= fetch_supersect(oldsbfd
, sect
);
673 if (ss
->match
!= NULL
)
675 const char *label
= label_lookup(oldsbfd
, sect
->symbol
);
676 *vec_grow(&delsects
, 1) = label
;
677 asymbol
*csym
= canonical_symbol(oldsbfd
, sect
->symbol
);
678 write_ksplice_deleted_patch(newsbfd
, csym
->name
, label
);
682 static void handle_nonzero_offset_relocs(struct supersect
*ss
)
685 for (i
= 0; i
< ss
->relocs
.size
; i
++) {
686 asymbol
*sym
= *ss
->relocs
.data
[i
]->sym_ptr_ptr
;
687 bfd_vma offset
= get_reloc_offset(ss
, ss
->relocs
.data
[i
], true);
688 if (sym
->value
+ offset
== 0)
690 if (!matchable_text_section(ss
->parent
, sym
->section
))
692 struct supersect
*sym_ss
= fetch_supersect(ss
->parent
,
694 if (!sym_ss
->patch
) {
696 printf("Changing %s because a relocation from sect %s "
697 "has a nonzero offset %lx+%lx into it\n",
698 sym_ss
->name
, ss
->name
,
699 (unsigned long)sym
->value
,
700 (unsigned long)offset
);
702 sym_ss
->patch
= true;
706 static void update_nonzero_offsets(struct superbfd
*sbfd
)
709 struct supersect
*ss
;
711 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
712 ss
= fetch_supersect(sbfd
, sect
);
713 if (ss
->new || ss
->patch
)
714 handle_nonzero_offset_relocs(ss
);
718 static void compare_matched_sections(struct superbfd
*newsbfd
)
721 struct supersect
*old_ss
, *new_ss
;
722 for (newp
= newsbfd
->abfd
->sections
; newp
!= NULL
; newp
= newp
->next
) {
723 new_ss
= fetch_supersect(newsbfd
, newp
);
724 if (new_ss
->match
== NULL
)
726 old_ss
= new_ss
->match
;
728 if (nonrelocs_equal(old_ss
, new_ss
) &&
729 relocs_equal(old_ss
, new_ss
))
731 if (matchable_text_section(newsbfd
, newp
)) {
734 new_ss
->patch
= true;
735 printf("Changing %s due to ", new_ss
->name
);
737 printf("Unmatching %s and %s due to ", old_ss
->name
,
739 new_ss
->match
= NULL
;
740 old_ss
->match
= NULL
;
742 if (new_ss
->contents
.size
!= old_ss
->contents
.size
)
743 printf("differing sizes\n");
744 else if (memcmp(new_ss
->contents
.data
, old_ss
->contents
.data
,
745 new_ss
->contents
.size
) != 0)
746 printf("differing contents\n");
748 printf("differing relocations\n");
750 if (unchangeable_section(newsbfd
, newp
))
755 static void handle_section_symbol_renames(struct superbfd
*oldsbfd
,
756 struct superbfd
*newsbfd
)
758 asection
*newp
, *oldp
;
759 for (newp
= newsbfd
->abfd
->sections
; newp
!= NULL
; newp
= newp
->next
) {
760 struct supersect
*newss
= fetch_supersect(newsbfd
, newp
);
761 if (newss
->match
== NULL
)
763 oldp
= bfd_get_section_by_name(oldsbfd
->abfd
,
768 const char *old_label
= label_lookup(oldsbfd
, oldp
->symbol
);
769 const char *new_label
= label_lookup(newsbfd
, newp
->symbol
);
771 if (strcmp(old_label
, new_label
) == 0)
773 label_map_set(newsbfd
, new_label
, old_label
);
777 static bool part_of_reloc(struct supersect
*ss
, unsigned long addr
)
780 for (relocp
= ss
->relocs
.data
;
781 relocp
< ss
->relocs
.data
+ ss
->relocs
.size
; relocp
++) {
782 arelent
*reloc
= *relocp
;
783 if (addr
>= reloc
->address
&&
784 addr
< reloc
->address
+ reloc
->howto
->size
)
790 static bool nonrelocs_equal(struct supersect
*old_ss
, struct supersect
*new_ss
)
793 if (old_ss
->contents
.size
!= new_ss
->contents
.size
)
795 const unsigned char *old
= old_ss
->contents
.data
;
796 const unsigned char *new = new_ss
->contents
.data
;
797 for (i
= 0; i
< old_ss
->contents
.size
; i
++) {
798 if (old
[i
] != new[i
] &&
799 !(part_of_reloc(old_ss
, i
) && part_of_reloc(new_ss
, i
)))
806 * relocs_equal checks to see whether the old section and the new section
807 * reference different read-only data in their relocations -- if a hard-coded
808 * string has been changed between the old file and the new file, relocs_equal
809 * will detect the difference.
811 bool relocs_equal(struct supersect
*old_ss
, struct supersect
*new_ss
)
814 struct superbfd
*oldsbfd
= old_ss
->parent
;
815 struct superbfd
*newsbfd
= new_ss
->parent
;
817 if (old_ss
->relocs
.size
!= new_ss
->relocs
.size
) {
818 printf("Different reloc count between %s and %s\n",
819 old_ss
->name
, new_ss
->name
);
823 for (i
= 0; i
< old_ss
->relocs
.size
; i
++) {
824 struct supersect
*ro_old_ss
, *ro_new_ss
;
826 asymbol
*old_sym
= *old_ss
->relocs
.data
[i
]->sym_ptr_ptr
;
827 asymbol
*new_sym
= *new_ss
->relocs
.data
[i
]->sym_ptr_ptr
;
830 get_reloc_offset(old_ss
, old_ss
->relocs
.data
[i
], true);
832 get_reloc_offset(new_ss
, new_ss
->relocs
.data
[i
], true);
834 if (bfd_is_und_section(old_sym
->section
) ||
835 bfd_is_und_section(new_sym
->section
)) {
836 if (!bfd_is_und_section(new_sym
->section
) &&
837 matchable_text_section(newsbfd
, new_sym
->section
) &&
841 if (!bfd_is_und_section(old_sym
->section
) &&
842 matchable_text_section(oldsbfd
, old_sym
->section
) &&
846 if (strcmp(old_sym
->name
, new_sym
->name
) == 0 &&
847 old_offset
== new_offset
)
852 if (bfd_is_const_section(old_sym
->section
) ||
853 bfd_is_const_section(new_sym
->section
))
856 ro_old_ss
= fetch_supersect(oldsbfd
, old_sym
->section
);
857 ro_new_ss
= fetch_supersect(newsbfd
, new_sym
->section
);
859 if (starts_with(ro_old_ss
->name
, ".rodata.str") &&
860 /* check it's not an out-of-range relocation to a string;
861 we'll just compare entire sections for them */
862 !(old_offset
>= ro_old_ss
->contents
.size
||
863 new_offset
>= ro_new_ss
->contents
.size
)) {
864 if (strcmp(ro_old_ss
->contents
.data
+ old_sym
->value
+
866 ro_new_ss
->contents
.data
+ new_sym
->value
+
868 printf("Strings differ between %s and %s\n",
869 old_ss
->name
, new_ss
->name
);
875 if (ro_old_ss
->match
!= ro_new_ss
||
876 ro_new_ss
->match
!= ro_old_ss
) {
877 printf("Nonmatching relocs from %s to %s/%s\n",
878 new_ss
->name
, ro_new_ss
->name
, ro_old_ss
->name
);
882 if (old_sym
->value
+ old_offset
!= new_sym
->value
+ new_offset
) {
883 printf("Offsets to %s/%s differ between %s and %s: "
884 "%lx+%lx/%lx+%lx\n", ro_old_ss
->name
,
885 ro_new_ss
->name
, old_ss
->name
, new_ss
->name
,
886 (unsigned long)old_sym
->value
,
887 (unsigned long)old_offset
,
888 (unsigned long)new_sym
->value
,
889 (unsigned long)new_offset
);
893 if ((old_sym
->value
+ old_offset
!= 0 ||
894 new_sym
->value
+ new_offset
!= 0) && ro_new_ss
->patch
) {
895 printf("Relocation from %s to nonzero offsets %lx+%lx/"
896 "%lx+%lx in changed section %s\n", new_ss
->name
,
897 (unsigned long)old_sym
->value
,
898 (unsigned long)old_offset
,
899 (unsigned long)new_sym
->value
,
900 (unsigned long)new_offset
,
901 new_sym
->section
->name
);
909 void rm_some_exports(struct superbfd
*isbfd
, const struct export_desc
*ed
)
911 assert(starts_with(ed
->sectname
, "__ksymtab"));
912 const char *export_type
= ed
->sectname
+ strlen("__ksymtab");
913 asection
*sym_sect
= bfd_get_section_by_name(isbfd
->abfd
, ed
->sectname
);
914 assert(sym_sect
!= NULL
);
915 char *export_crc_name
;
916 assert(asprintf(&export_crc_name
, "__kcrctab%s", export_type
) >= 0);
917 asection
*crc_sect
= bfd_get_section_by_name(isbfd
->abfd
,
919 struct supersect
*ss
, *crc_ss
= NULL
;
920 ss
= fetch_supersect(isbfd
, sym_sect
);
921 if (crc_sect
!= NULL
)
922 crc_ss
= fetch_supersect(isbfd
, crc_sect
);
925 assert(ss
->contents
.size
* sizeof(unsigned long) ==
926 crc_ss
->contents
.size
* sizeof(struct kernel_symbol
));
928 struct supersect orig_ss
, orig_crc_ss
;
929 supersect_move(&orig_ss
, ss
);
931 supersect_move(&orig_crc_ss
, crc_ss
);
933 struct kernel_symbol
*orig_ksym
;
934 unsigned long *orig_crc
;
935 for (orig_ksym
= orig_ss
.contents
.data
,
936 orig_crc
= orig_crc_ss
.contents
.data
;
937 (void *)orig_ksym
< orig_ss
.contents
.data
+ orig_ss
.contents
.size
;
938 orig_ksym
++, orig_crc
++) {
940 read_reloc(&orig_ss
, &orig_ksym
->value
,
941 sizeof(orig_ksym
->value
), &sym
);
942 if (!str_in_set(sym
->name
, &ed
->names
))
945 struct kernel_symbol
*ksym
= sect_grow(ss
, 1, typeof(*ksym
));
946 sect_copy(ss
, &ksym
->value
, &orig_ss
, &orig_ksym
->value
, 1);
947 /* Replace name with a mangled name */
948 write_ksplice_export(ss
->parent
, sym
->name
, export_type
, false);
949 write_string(ss
, (const char **)&ksym
->name
,
950 "DISABLED_%s_%s", sym
->name
, kid
);
954 sect_grow(crc_ss
, 1, typeof(*orig_crc
)),
955 &orig_crc_ss
, orig_crc
, 1);
959 void rm_relocs(struct superbfd
*isbfd
)
962 for (p
= isbfd
->abfd
->sections
; p
!= NULL
; p
= p
->next
) {
963 struct supersect
*ss
= fetch_supersect(isbfd
, p
);
964 if (is_table_section(p
) || starts_with(p
->name
, ".ksplice") ||
965 strcmp(p
->name
, ".fixup") == 0)
967 if (ss
->keep
|| mode("rmsyms"))
970 if (mode("finalize")) {
971 p
= bfd_get_section_by_name(isbfd
->abfd
, ".ksplice_patches");
973 struct supersect
*ss
= fetch_supersect(isbfd
, p
);
979 void rm_some_relocs(struct supersect
*ss
)
981 struct arelentp_vec orig_relocs
;
982 vec_move(&orig_relocs
, &ss
->relocs
);
985 for (relocp
= orig_relocs
.data
;
986 relocp
< orig_relocs
.data
+ orig_relocs
.size
; relocp
++) {
987 bool rm_reloc
= false;
988 asymbol
*sym_ptr
= *(*relocp
)->sym_ptr_ptr
;
990 if (mode("rmsyms") && str_in_set(sym_ptr
->name
, &rmsyms
) &&
991 bfd_is_und_section(sym_ptr
->section
))
997 if (mode("keep-primary") &&
998 (bfd_is_const_section(sym_ptr
->section
) ||
999 fetch_supersect(ss
->parent
, sym_ptr
->section
)->new ||
1000 starts_with(sym_ptr
->section
->name
, ".rodata.str")))
1003 if (mode("finalize") && bfd_is_und_section(sym_ptr
->section
))
1007 write_ksplice_reloc(ss
, *relocp
);
1009 *vec_grow(&ss
->relocs
, 1) = *relocp
;
1013 struct supersect
*make_section(struct superbfd
*sbfd
, const char *name
)
1015 asection
*sect
= bfd_get_section_by_name(sbfd
->abfd
, name
);
1017 return fetch_supersect(sbfd
, sect
);
1019 return new_supersect(sbfd
, name
);
1022 arelent
*create_reloc(struct supersect
*ss
, const void *addr
, asymbol
**symp
,
1025 bfd_reloc_code_real_type code
;
1026 switch (bfd_arch_bits_per_address(ss
->parent
->abfd
)) {
1028 code
= BFD_RELOC_32
;
1031 code
= BFD_RELOC_64
;
1037 arelent
*reloc
= malloc(sizeof(*reloc
));
1038 reloc
->sym_ptr_ptr
= symp
;
1039 reloc
->address
= addr
- ss
->contents
.data
;
1040 reloc
->howto
= bfd_reloc_type_lookup(ss
->parent
->abfd
, code
);
1041 reloc
->addend
= offset
;
1045 void write_reloc(struct supersect
*ss
, const void *addr
, asymbol
**symp
,
1048 arelent
*new_reloc
= create_reloc(ss
, addr
, symp
, offset
), **relocp
;
1049 for (relocp
= ss
->relocs
.data
;
1050 relocp
< ss
->relocs
.data
+ ss
->relocs
.size
; relocp
++) {
1051 if ((*relocp
)->address
== new_reloc
->address
) {
1054 (void *)(ss
->relocs
.data
+ ss
->relocs
.size
) -
1055 (void *)(relocp
+ 1));
1060 *vec_grow(&ss
->new_relocs
, 1) = new_reloc
;
1063 void write_string(struct supersect
*ss
, const char **addr
, const char *fmt
, ...)
1066 struct supersect
*str_ss
= make_section(ss
->parent
, ".ksplice_str");
1069 int len
= vasprintf(&str
, fmt
, ap
);
1073 unsigned long *str_offp
= ulong_hash_lookup(&ksplice_string_offset
, str
,
1075 if (str_offp
== NULL
) {
1076 char *buf
= sect_grow(str_ss
, len
+ 1, char);
1077 memcpy(buf
, str
, len
+ 1);
1078 str_offp
= ulong_hash_lookup(&ksplice_string_offset
, str
, TRUE
);
1079 *str_offp
= (void *)buf
- str_ss
->contents
.data
;
1082 write_reloc(ss
, addr
, &str_ss
->symbol
, *str_offp
);
1085 void lookup_system_map(struct addr_vec
*addrs
, const char *name
, long offset
)
1087 struct addr_vec
*map_addrs
=
1088 addr_vec_hash_lookup(&system_map
, name
, FALSE
);
1089 if (map_addrs
== NULL
)
1092 unsigned long *addr
, *map_addr
;
1093 for (map_addr
= map_addrs
->data
;
1094 map_addr
< map_addrs
->data
+ map_addrs
->size
; map_addr
++) {
1095 for (addr
= addrs
->data
; addr
< addrs
->data
+ addrs
->size
;
1097 if (*addr
== *map_addr
+ offset
)
1100 if (addr
< addrs
->data
+ addrs
->size
)
1102 *vec_grow(addrs
, 1) = *map_addr
+ offset
;
1106 void write_system_map_array(struct superbfd
*sbfd
, struct supersect
*ss
,
1107 const unsigned long **sym_addrs
,
1108 unsigned long *num_sym_addrs
, asymbol
*sym
)
1110 struct addr_vec addrs
;
1113 if (bfd_is_abs_section(sym
->section
)) {
1114 *vec_grow(&addrs
, 1) = sym
->value
;
1115 } else if (bfd_is_und_section(sym
->section
)) {
1116 lookup_system_map(&addrs
, sym
->name
, 0);
1117 } else if (!bfd_is_const_section(sym
->section
)) {
1119 for (gsymp
= sbfd
->syms
.data
;
1120 gsymp
< sbfd
->syms
.data
+ sbfd
->syms
.size
; gsymp
++) {
1121 asymbol
*gsym
= *gsymp
;
1122 if ((gsym
->flags
& BSF_DEBUGGING
) == 0 &&
1123 gsym
->section
== sym
->section
)
1124 lookup_system_map(&addrs
, gsym
->name
,
1125 sym
->value
- gsym
->value
);
1129 *num_sym_addrs
= addrs
.size
;
1130 if (addrs
.size
!= 0) {
1131 struct supersect
*array_ss
= make_section(sbfd
,
1133 void *buf
= sect_grow(array_ss
, addrs
.size
,
1134 typeof(*addrs
.data
));
1135 memcpy(buf
, addrs
.data
, addrs
.size
* sizeof(*addrs
.data
));
1136 write_reloc(ss
, sym_addrs
, &array_ss
->symbol
,
1137 buf
- array_ss
->contents
.data
);
1145 void write_ksplice_system_map(struct superbfd
*sbfd
, asymbol
*sym
,
1146 const char *addstr_sect
)
1148 struct supersect
*smap_ss
= make_section(sbfd
, ".ksplice_system_map");
1149 struct ksplice_system_map
*smap
;
1150 const char *label
= label_lookup(sbfd
, sym
);
1152 bool *done
= bool_hash_lookup(&system_map_written
, label
, TRUE
);
1157 smap
= sect_grow(smap_ss
, 1, struct ksplice_system_map
);
1159 write_system_map_array(sbfd
, smap_ss
, &smap
->candidates
,
1160 &smap
->nr_candidates
, sym
);
1161 write_string(smap_ss
, &smap
->label
, "%s%s", label
, addstr_sect
);
1164 void write_ksplice_symbol(struct supersect
*ss
,
1165 const struct ksplice_symbol
*const *addr
,
1166 asymbol
*sym
, const char *addstr_sect
)
1168 struct supersect
*ksymbol_ss
= make_section(ss
->parent
,
1169 ".ksplice_symbols");
1170 struct ksplice_symbol
*ksymbol
;
1171 unsigned long *ksymbol_offp
;
1172 const char *label
= label_lookup(ss
->parent
, sym
);
1174 assert(asprintf(&output
, "%s%s", label
, addstr_sect
) >= 0);
1176 ksymbol_offp
= ulong_hash_lookup(&ksplice_symbol_offset
, output
, FALSE
);
1177 if (ksymbol_offp
!= NULL
) {
1178 write_reloc(ss
, addr
, &ksymbol_ss
->symbol
, *ksymbol_offp
);
1181 ksymbol
= sect_grow(ksymbol_ss
, 1, struct ksplice_symbol
);
1182 ksymbol_offp
= ulong_hash_lookup(&ksplice_symbol_offset
, output
, TRUE
);
1183 *ksymbol_offp
= (void *)ksymbol
- ksymbol_ss
->contents
.data
;
1185 if (bfd_is_und_section(sym
->section
) || (sym
->flags
& BSF_GLOBAL
) != 0) {
1186 write_string(ksymbol_ss
, &ksymbol
->name
, "%s", sym
->name
);
1187 } else if (bfd_is_const_section(sym
->section
)) {
1188 ksymbol
->name
= NULL
;
1190 asymbol
*gsym
= canonical_symbol(ss
->parent
, sym
);
1193 ksymbol
->name
= NULL
;
1195 write_string(ksymbol_ss
, &ksymbol
->name
, "%s",
1199 write_string(ksymbol_ss
, &ksymbol
->label
, "%s%s", label
, addstr_sect
);
1201 write_ksplice_system_map(ksymbol_ss
->parent
, sym
, addstr_sect
);
1203 write_reloc(ss
, addr
, &ksymbol_ss
->symbol
, *ksymbol_offp
);
1206 void write_ksplice_reloc(struct supersect
*ss
, arelent
*orig_reloc
)
1208 asymbol
*sym_ptr
= *orig_reloc
->sym_ptr_ptr
;
1209 reloc_howto_type
*howto
= orig_reloc
->howto
;
1210 bfd_vma addend
= get_reloc_offset(ss
, orig_reloc
, false);
1212 if (mode("finalize") && starts_with(ss
->name
, ".ksplice_patches")) {
1213 unsigned long *repladdr
=
1214 ss
->contents
.data
+ orig_reloc
->address
;
1219 blot_section(ss
, orig_reloc
->address
, howto
);
1221 struct supersect
*kreloc_ss
= make_section(ss
->parent
,
1223 ".ksplice_init_relocs" :
1225 struct ksplice_reloc
*kreloc
= sect_grow(kreloc_ss
, 1,
1226 struct ksplice_reloc
);
1228 write_reloc(kreloc_ss
, &kreloc
->blank_addr
,
1229 &ss
->symbol
, orig_reloc
->address
);
1230 kreloc
->blank_offset
= (unsigned long)orig_reloc
->address
;
1231 write_ksplice_symbol(kreloc_ss
, &kreloc
->symbol
, sym_ptr
, "");
1232 kreloc
->pcrel
= howto
->pc_relative
;
1233 kreloc
->addend
= addend
;
1234 kreloc
->size
= bfd_get_reloc_size(howto
);
1235 kreloc
->dst_mask
= howto
->dst_mask
;
1236 kreloc
->rightshift
= howto
->rightshift
;
1237 kreloc
->signed_addend
=
1238 (howto
->complain_on_overflow
== complain_overflow_signed
) ||
1239 (howto
->complain_on_overflow
== complain_overflow_bitfield
);
1242 #define CANARY(x, canary) ((x & ~howto->dst_mask) | (canary & howto->dst_mask))
1244 void blot_section(struct supersect
*ss
, int offset
, reloc_howto_type
*howto
)
1246 int bits
= bfd_get_reloc_size(howto
) * 8;
1247 void *address
= ss
->contents
.data
+ offset
;
1248 bfd_vma x
= bfd_get(bits
, ss
->parent
->abfd
, address
);
1249 x
= (x
& ~howto
->dst_mask
) |
1250 ((bfd_vma
)KSPLICE_CANARY
& howto
->dst_mask
);
1251 bfd_put(bits
, ss
->parent
->abfd
, x
, address
);
1254 void write_ksplice_section(struct superbfd
*sbfd
, asymbol
**symp
)
1256 asymbol
*sym
= *symp
;
1257 struct supersect
*ksect_ss
= make_section(sbfd
, ".ksplice_sections");
1258 struct ksplice_section
*ksect
= sect_grow(ksect_ss
, 1,
1259 struct ksplice_section
);
1261 write_ksplice_symbol(ksect_ss
, &ksect
->symbol
, sym
,
1262 mode("keep-primary") ? "(post)" : "");
1263 ksect
->size
= bfd_get_section_size(sym
->section
);
1265 if (starts_with(sym
->section
->name
, ".rodata"))
1266 ksect
->flags
|= KSPLICE_SECTION_RODATA
;
1267 if (starts_with(sym
->section
->name
, ".data"))
1268 ksect
->flags
|= KSPLICE_SECTION_DATA
;
1269 if (matchable_text_section(sbfd
, sym
->section
))
1270 ksect
->flags
|= KSPLICE_SECTION_TEXT
;
1271 assert(ksect
->flags
!= 0);
1272 write_reloc(ksect_ss
, &ksect
->address
, symp
, 0);
1275 void write_ksplice_patch(struct superbfd
*sbfd
, const char *sectname
)
1277 struct supersect
*kpatch_ss
= make_section(sbfd
, ".ksplice_patches");
1278 struct ksplice_patch
*kpatch
= sect_grow(kpatch_ss
, 1,
1279 struct ksplice_patch
);
1280 asection
*sect
= bfd_get_section_by_name(sbfd
->abfd
, sectname
);
1281 assert(sect
!= NULL
);
1283 write_string(kpatch_ss
, &kpatch
->label
, "%s",
1284 label_lookup(sbfd
, sect
->symbol
));
1285 write_reloc(kpatch_ss
, &kpatch
->repladdr
, §
->symbol
, 0);
1288 void write_ksplice_deleted_patch(struct superbfd
*sbfd
, const char *name
,
1291 struct supersect
*kpatch_ss
= make_section(sbfd
, ".ksplice_patches");
1292 struct ksplice_patch
*kpatch
= sect_grow(kpatch_ss
, 1,
1293 struct ksplice_patch
);
1295 write_string(kpatch_ss
, &kpatch
->label
, "%s", label
);
1297 for (symp
= sbfd
->syms
.data
; symp
< sbfd
->syms
.data
+ sbfd
->syms
.size
;
1299 asymbol
*sym
= *symp
;
1300 if (bfd_is_und_section(sym
->section
) &&
1301 strcmp(name
, sym
->name
) == 0)
1304 if (symp
>= sbfd
->syms
.data
+ sbfd
->syms
.size
) {
1305 symp
= malloc(sizeof(*symp
));
1306 *symp
= bfd_make_empty_symbol(sbfd
->abfd
);
1307 asymbol
*sym
= *symp
;
1308 sym
->name
= strdup(name
);
1309 sym
->section
= bfd_und_section_ptr
;
1312 *vec_grow(&sbfd
->new_syms
, 1) = symp
;
1314 write_reloc(kpatch_ss
, &kpatch
->repladdr
, symp
, 0);
1317 void write_ksplice_export(struct superbfd
*sbfd
, const char *symname
,
1318 const char *export_type
, bool del
)
1320 struct supersect
*export_ss
= make_section(sbfd
, ".ksplice_exports");
1321 struct ksplice_export
*exp
= sect_grow(export_ss
, 1,
1322 struct ksplice_export
);
1325 write_string(export_ss
, &exp
->name
, "%s", symname
);
1326 write_string(export_ss
, &exp
->new_name
, "DISABLED_%s_%s",
1329 write_string(export_ss
, &exp
->new_name
, "%s", symname
);
1330 write_string(export_ss
, &exp
->name
, "DISABLED_%s_%s", symname
,
1335 struct fixup_entry
{
1340 DECLARE_VEC_TYPE(struct fixup_entry
, fixup_entry_vec
);
1342 int compare_fixups(const void *aptr
, const void *bptr
)
1344 const struct fixup_entry
*a
= aptr
, *b
= bptr
;
1345 if (a
->offset
< b
->offset
)
1347 else if (a
->offset
> b
->offset
)
1350 return (int)a
->used
- (int)b
->used
;
1353 void filter_table_sections(struct superbfd
*isbfd
)
1355 struct supersect
*tables_ss
=
1356 fetch_supersect(offsets_sbfd
,
1357 bfd_get_section_by_name(offsets_sbfd
->abfd
,
1358 ".ksplice_table_sections"));
1359 const struct table_section
*ts
;
1360 for (ts
= tables_ss
->contents
.data
;
1361 (void *)ts
< tables_ss
->contents
.data
+ tables_ss
->contents
.size
;
1363 struct table_section s
= *ts
;
1364 s
.sect
= read_string(tables_ss
, &ts
->sect
);
1365 s
.other_sect
= read_string(tables_ss
, &ts
->other_sect
);
1366 filter_table_section(isbfd
, &s
);
1370 void filter_table_section(struct superbfd
*sbfd
, const struct table_section
*s
)
1372 asection
*isection
= bfd_get_section_by_name(sbfd
->abfd
, s
->sect
);
1373 if (isection
== NULL
)
1375 asection
*fixup_sect
= NULL
;
1376 if (s
->other_sect
!= NULL
)
1377 fixup_sect
= bfd_get_section_by_name(sbfd
->abfd
, s
->other_sect
);
1379 struct supersect
*ss
= fetch_supersect(sbfd
, isection
), orig_ss
;
1380 supersect_move(&orig_ss
, ss
);
1382 struct supersect
*fixup_ss
= NULL
;
1383 if (fixup_sect
!= NULL
)
1384 fixup_ss
= fetch_supersect(sbfd
, fixup_sect
);
1386 struct fixup_entry_vec fixups
;
1390 for (orig_entry
= orig_ss
.contents
.data
;
1391 orig_entry
< orig_ss
.contents
.data
+ orig_ss
.contents
.size
;
1392 orig_entry
+= s
->entry_size
) {
1393 asymbol
*sym
, *fixup_sym
;
1394 read_reloc(&orig_ss
, orig_entry
+ s
->addr_offset
,
1395 sizeof(void *), &sym
);
1397 struct fixup_entry
*f
;
1398 if (fixup_sect
!= NULL
) {
1399 bfd_vma fixup_offset
=
1400 read_reloc(&orig_ss
, orig_entry
+ s
->other_offset
,
1401 sizeof(void *), &fixup_sym
);
1402 if (fixup_sym
->section
== fixup_sect
) {
1403 assert(fixup_offset
< fixup_ss
->contents
.size
);
1404 f
= vec_grow(&fixups
, 1);
1405 f
->offset
= fixup_offset
;
1410 struct supersect
*sym_ss
= fetch_supersect(sbfd
, sym
->section
);
1414 if (fixup_sect
!= NULL
&& fixup_sym
->section
== fixup_sect
) {
1416 f
->ex_offset
= ss
->contents
.size
+ s
->other_offset
;
1418 sect_copy(ss
, sect_do_grow(ss
, 1, s
->entry_size
,
1420 &orig_ss
, orig_entry
, s
->entry_size
);
1423 if (fixup_sect
== NULL
)
1426 struct supersect orig_fixup_ss
;
1427 supersect_move(&orig_fixup_ss
, fixup_ss
);
1429 qsort(fixups
.data
, fixups
.size
, sizeof(*fixups
.data
), compare_fixups
);
1430 *vec_grow(&fixups
, 1) = (struct fixup_entry
)
1431 { .offset
= orig_fixup_ss
.contents
.size
, .used
= false };
1433 struct fixup_entry
*f
;
1434 for (f
= fixups
.data
; f
< fixups
.data
+ fixups
.size
- 1; f
++) {
1437 write_reloc(ss
, ss
->contents
.data
+ f
->ex_offset
,
1438 &fixup_ss
->symbol
, fixup_ss
->contents
.size
);
1440 sect_grow(fixup_ss
, (f
+ 1)->offset
- f
->offset
,
1443 orig_fixup_ss
.contents
.data
+ f
->offset
,
1444 (f
+ 1)->offset
- f
->offset
);
1448 void keep_if_referenced(bfd
*abfd
, asection
*sect
, void *ignored
)
1450 struct superbfd
*sbfd
= fetch_superbfd(abfd
);
1451 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
1452 if (ss
->keep
|| ignored_section(sbfd
, sect
))
1456 for (symp
= sbfd
->syms
.data
;
1457 symp
< sbfd
->syms
.data
+ sbfd
->syms
.size
; symp
++) {
1458 asymbol
*sym
= *symp
;
1459 if (sym
->section
== sect
&& (sym
->flags
& BSF_GLOBAL
) != 0) {
1466 bfd_map_over_sections(abfd
, check_for_ref_to_section
, sect
);
1469 void check_for_ref_to_section(bfd
*abfd
, asection
*looking_at
,
1472 struct superbfd
*sbfd
= fetch_superbfd(abfd
);
1473 struct supersect
*ss
= fetch_supersect(sbfd
, looking_at
);
1474 struct supersect
*for_ss
= fetch_supersect(sbfd
,
1475 (asection
*)looking_for
);
1476 if (!ss
->keep
|| is_table_section(looking_at
)
1477 || strcmp(looking_at
->name
, ".fixup") == 0)
1481 for (relocp
= ss
->relocs
.data
;
1482 relocp
< ss
->relocs
.data
+ ss
->relocs
.size
; relocp
++) {
1483 asymbol
*sym
= *(*relocp
)->sym_ptr_ptr
;
1484 if (sym
->section
!= (asection
*)looking_for
)
1486 for_ss
->keep
= true;
1492 void copy_symbols(struct asymbolp_vec
*osyms
, struct asymbolpp_vec
*isyms
)
1495 for (sympp
= isyms
->data
; sympp
< isyms
->data
+ isyms
->size
; sympp
++)
1496 *vec_grow(osyms
, 1) = **sympp
;
1499 /* Modified function from GNU Binutils objcopy.c */
1500 bfd_boolean
copy_object(bfd
*ibfd
, bfd
*obfd
)
1502 assert(bfd_set_format(obfd
, bfd_get_format(ibfd
)));
1504 bfd_vma start
= bfd_get_start_address(ibfd
);
1506 flagword flags
= bfd_get_file_flags(ibfd
);
1507 flags
&= bfd_applicable_file_flags(obfd
);
1509 assert(bfd_set_start_address(obfd
, start
)
1510 && bfd_set_file_flags(obfd
, flags
));
1512 enum bfd_architecture iarch
= bfd_get_arch(ibfd
);
1513 unsigned int imach
= bfd_get_mach(ibfd
);
1514 assert(bfd_set_arch_mach(obfd
, iarch
, imach
));
1515 assert(bfd_set_format(obfd
, bfd_get_format(ibfd
)));
1517 /* BFD mandates that all output sections be created and sizes set before
1518 any output is done. Thus, we traverse all sections multiple times. */
1519 bfd_map_over_sections(ibfd
, setup_section
, obfd
);
1521 struct supersect
*new_supersects
= fetch_superbfd(ibfd
)->new_supersects
;
1522 struct supersect
*ss
;
1523 for (ss
= new_supersects
; ss
!= NULL
; ss
= ss
->next
)
1524 setup_new_section(obfd
, ss
);
1526 /* Mark symbols used in output relocations so that they
1527 are kept, even if they are local labels or static symbols.
1529 Note we iterate over the input sections examining their
1530 relocations since the relocations for the output sections
1531 haven't been set yet. mark_symbols_used_in_relocations will
1532 ignore input sections which have no corresponding output
1535 bfd_map_over_sections(ibfd
, mark_symbols_used_in_relocations
, NULL
);
1536 for (ss
= new_supersects
; ss
!= NULL
; ss
= ss
->next
)
1537 ss_mark_symbols_used_in_relocations(ss
);
1538 struct asymbolp_vec osyms
;
1540 filter_symbols(ibfd
, obfd
, &osyms
, &fetch_superbfd(ibfd
)->syms
);
1541 copy_symbols(&osyms
, &fetch_superbfd(ibfd
)->new_syms
);
1543 bfd_set_symtab(obfd
, osyms
.data
, osyms
.size
);
1545 /* This has to happen after the symbol table has been set. */
1546 bfd_map_over_sections(obfd
, write_section
, NULL
);
1548 /* Allow the BFD backend to copy any private data it understands
1549 from the input BFD to the output BFD. This is done last to
1550 permit the routine to look at the filtered symbol table, which is
1551 important for the ECOFF code at least. */
1552 assert(bfd_copy_private_bfd_data(ibfd
, obfd
));
1557 /* Modified function from GNU Binutils objcopy.c */
1558 void setup_section(bfd
*ibfd
, asection
*isection
, void *obfdarg
)
1560 struct superbfd
*isbfd
= fetch_superbfd(ibfd
);
1561 struct supersect
*ss
= fetch_supersect(isbfd
, isection
);
1562 bfd
*obfd
= obfdarg
;
1568 asection
*osection
= bfd_make_section_anyway(obfd
, isection
->name
);
1569 assert(osection
!= NULL
);
1571 osection
->userdata
= ss
;
1572 bfd_set_section_flags(obfd
, osection
, ss
->flags
);
1573 ss
->symbol
= osection
->symbol
;
1574 assert(bfd_set_section_size(obfd
, osection
, ss
->contents
.size
));
1576 vma
= bfd_section_vma(ibfd
, isection
);
1577 assert(bfd_set_section_vma(obfd
, osection
, vma
));
1579 osection
->lma
= isection
->lma
;
1580 assert(bfd_set_section_alignment(obfd
, osection
, ss
->alignment
));
1581 osection
->entsize
= isection
->entsize
;
1582 osection
->output_section
= osection
;
1583 osection
->output_offset
= 0;
1584 isection
->output_section
= osection
;
1585 isection
->output_offset
= 0;
1589 void setup_new_section(bfd
*obfd
, struct supersect
*ss
)
1591 asection
*osection
= bfd_make_section_anyway(obfd
, ss
->name
);
1592 assert(osection
!= NULL
);
1593 bfd_set_section_flags(obfd
, osection
, ss
->flags
);
1595 osection
->userdata
= ss
;
1596 ss
->symbol
= osection
->symbol
;
1597 assert(bfd_set_section_size(obfd
, osection
, ss
->contents
.size
));
1598 assert(bfd_set_section_vma(obfd
, osection
, 0));
1601 assert(bfd_set_section_alignment(obfd
, osection
, ss
->alignment
));
1602 osection
->entsize
= 0;
1603 osection
->output_section
= osection
;
1604 osection
->output_offset
= 0;
1607 void write_section(bfd
*obfd
, asection
*osection
, void *arg
)
1609 struct supersect
*ss
= osection
->userdata
;
1611 if ((ss
->flags
& SEC_GROUP
) != 0 || ss
->contents
.size
== 0)
1615 char *error_message
;
1616 for (relocp
= ss
->new_relocs
.data
;
1617 relocp
< ss
->new_relocs
.data
+ ss
->new_relocs
.size
; relocp
++) {
1619 if (bfd_get_arch(obfd
) == bfd_arch_arm
)
1620 val
= osection
->use_rela_p
? 0 : (*relocp
)->addend
;
1623 bfd_put(bfd_get_reloc_size((*relocp
)->howto
) * 8, obfd
, val
,
1624 ss
->contents
.data
+ (*relocp
)->address
);
1625 if (bfd_install_relocation(obfd
, *relocp
, ss
->contents
.data
,
1626 0, osection
, &error_message
) !=
1628 fprintf(stderr
, "ksplice: error installing reloc: %s",
1633 memcpy(vec_grow(&ss
->relocs
, ss
->new_relocs
.size
), ss
->new_relocs
.data
,
1634 ss
->new_relocs
.size
* sizeof(*ss
->new_relocs
.data
));
1636 bfd_set_reloc(obfd
, osection
,
1637 ss
->relocs
.size
== 0 ? NULL
: ss
->relocs
.data
,
1640 if (ss
->flags
& SEC_HAS_CONTENTS
)
1641 assert(bfd_set_section_contents
1642 (obfd
, osection
, ss
->contents
.data
, 0,
1643 ss
->contents
.size
));
1646 /* Modified function from GNU Binutils objcopy.c
1648 * Mark all the symbols which will be used in output relocations with
1649 * the BSF_KEEP flag so that those symbols will not be stripped.
1651 * Ignore relocations which will not appear in the output file.
1653 void mark_symbols_used_in_relocations(bfd
*abfd
, asection
*isection
,
1656 struct superbfd
*sbfd
= fetch_superbfd(abfd
);
1657 if (isection
->output_section
== NULL
)
1660 struct supersect
*ss
= fetch_supersect(sbfd
, isection
);
1661 ss_mark_symbols_used_in_relocations(ss
);
1664 void ss_mark_symbols_used_in_relocations(struct supersect
*ss
)
1666 /* Examine each symbol used in a relocation. If it's not one of the
1667 special bfd section symbols, then mark it with BSF_KEEP. */
1669 for (relocp
= ss
->relocs
.data
;
1670 relocp
< ss
->relocs
.data
+ ss
->relocs
.size
; relocp
++) {
1671 asymbol
*sym
= *(*relocp
)->sym_ptr_ptr
;
1672 if (!(bfd_is_const_section(sym
->section
) &&
1673 sym
== sym
->section
->symbol
))
1674 sym
->flags
|= BSF_KEEP
;
1676 for (relocp
= ss
->new_relocs
.data
;
1677 relocp
< ss
->new_relocs
.data
+ ss
->new_relocs
.size
; relocp
++) {
1678 asymbol
*sym
= *(*relocp
)->sym_ptr_ptr
;
1679 if (!(bfd_is_const_section(sym
->section
) &&
1680 sym
== sym
->section
->symbol
))
1681 sym
->flags
|= BSF_KEEP
;
1685 static bool deleted_table_section_symbol(bfd
*abfd
, asymbol
*sym
)
1687 struct superbfd
*sbfd
= fetch_superbfd(abfd
);
1688 if (bfd_is_const_section(sym
->section
))
1690 struct supersect
*ss
= fetch_supersect(sbfd
, sym
->section
);
1693 for (symp
= ss
->syms
.data
; symp
< ss
->syms
.data
+ ss
->syms
.size
; symp
++) {
1697 return symp
>= ss
->syms
.data
+ ss
->syms
.size
;
1700 /* Modified function from GNU Binutils objcopy.c
1702 * Choose which symbol entries to copy.
1703 * We don't copy in place, because that confuses the relocs.
1704 * Return the number of symbols to print.
1706 void filter_symbols(bfd
*ibfd
, bfd
*obfd
, struct asymbolp_vec
*osyms
,
1707 struct asymbolp_vec
*isyms
)
1710 struct superbfd
*sbfd
= fetch_superbfd(ibfd
);
1711 for (symp
= isyms
->data
; symp
< isyms
->data
+ isyms
->size
; symp
++) {
1712 asymbol
*sym
= *symp
;
1713 struct supersect
*sym_ss
= NULL
;
1714 if (!bfd_is_const_section(sym
->section
))
1715 sym_ss
= fetch_supersect(sbfd
, sym
->section
);
1719 if (mode("keep") && (sym
->flags
& BSF_GLOBAL
) != 0 &&
1720 !(mode("keep-primary") && sym_ss
!= NULL
&& sym_ss
->new))
1721 sym
->flags
= (sym
->flags
& ~BSF_GLOBAL
) | BSF_LOCAL
;
1723 if (mode("finalize") && (sym
->flags
& BSF_GLOBAL
) != 0)
1724 sym
->flags
= (sym
->flags
& ~BSF_GLOBAL
) | BSF_LOCAL
;
1726 if ((sym
->flags
& BSF_KEEP
) != 0 /* Used in relocation. */
1727 || ((sym
->flags
& BSF_SECTION_SYM
) != 0 && sym_ss
!= NULL
&&
1730 else if ((sym
->flags
& (BSF_GLOBAL
| BSF_WEAK
)) != 0 &&
1731 sym_ss
!= NULL
&& sym_ss
->keep
)
1733 else if (mode("keep-primary") &&
1734 starts_with(sym
->section
->name
, "__ksymtab"))
1737 if (deleted_table_section_symbol(ibfd
, sym
))
1740 if (bfd_is_com_section(sym
->section
))
1744 keep
= !str_in_set(sym
->name
, &rmsyms
);
1747 assert(sym_ss
== NULL
|| sym_ss
->keep
);
1748 *vec_grow(osyms
, 1) = sym
;
1753 void read_str_set(struct str_vec
*strs
)
1757 assert(getline(&buf
, &n
, stdin
) >= 0);
1761 char *str
= strtok_r(buf
, " \n", &saveptr
);
1765 *vec_grow(strs
, 1) = str
;
1769 bool str_in_set(const char *str
, const struct str_vec
*strs
)
1772 for (strp
= strs
->data
; strp
< strs
->data
+ strs
->size
; strp
++) {
1773 if (strcmp(str
, *strp
) == 0)
1779 bool is_table_section(asection
*sect
)
1781 if (!mode("keep") && !mode("finalize"))
1784 struct supersect
*tables_ss
=
1785 fetch_supersect(offsets_sbfd
, bfd_get_section_by_name(
1786 offsets_sbfd
->abfd
, ".ksplice_table_sections"));
1787 const struct table_section
*ts
;
1788 for (ts
= tables_ss
->contents
.data
;
1789 (void *)ts
< tables_ss
->contents
.data
+ tables_ss
->contents
.size
;
1791 if (strcmp(sect
->name
, read_string(tables_ss
, &ts
->sect
)) == 0)
1797 bool is_special(asection
*sect
)
1799 static const char *static_want
[] = {
1801 ".altinstr_replacement",
1803 ".parainstructions",
1811 for (i
= 0; static_want
[i
] != NULL
; i
++) {
1812 if (strcmp(sect
->name
, static_want
[i
]) == 0)
1816 if (starts_with(sect
->name
, ".rodata.str"))
1818 if (starts_with(sect
->name
, "__ksymtab"))
1820 if (starts_with(sect
->name
, "__kcrctab"))