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 bool is_table_section(const char *name
, bool consider_other
);
111 void rm_relocs(struct superbfd
*isbfd
);
112 void rm_some_relocs(struct supersect
*ss
);
113 void write_ksplice_reloc(struct supersect
*ss
, arelent
*orig_reloc
);
114 void blot_section(struct supersect
*ss
, int offset
, reloc_howto_type
*howto
);
115 void write_ksplice_section(struct superbfd
*sbfd
, asymbol
**symp
);
116 void write_ksplice_patch(struct superbfd
*sbfd
, const char *sectname
);
117 void write_ksplice_deleted_patch(struct superbfd
*sbfd
, const char *name
,
119 void filter_table_sections(struct superbfd
*isbfd
);
120 void filter_table_section(struct superbfd
*sbfd
, const struct table_section
*s
);
121 void keep_if_referenced(bfd
*abfd
, asection
*sect
, void *ignored
);
122 void check_for_ref_to_section(bfd
*abfd
, asection
*looking_at
,
124 bfd_boolean
copy_object(bfd
*ibfd
, bfd
*obfd
);
125 void setup_section(bfd
*ibfd
, asection
*isection
, void *obfdarg
);
126 static void setup_new_section(bfd
*obfd
, struct supersect
*ss
);
127 static void write_section(bfd
*obfd
, asection
*osection
, void *arg
);
128 void mark_symbols_used_in_relocations(bfd
*abfd
, asection
*isection
,
130 static void ss_mark_symbols_used_in_relocations(struct supersect
*ss
);
131 void filter_symbols(bfd
*ibfd
, bfd
*obfd
, struct asymbolp_vec
*osyms
,
132 struct asymbolp_vec
*isyms
);
133 static bool deleted_table_section_symbol(bfd
*abfd
, asymbol
*sym
);
134 void read_str_set(struct str_vec
*strs
);
135 bool str_in_set(const char *str
, const struct str_vec
*strs
);
136 struct supersect
*make_section(struct superbfd
*sbfd
, const char *name
);
137 void __attribute__((format(printf
, 3, 4)))
138 write_string(struct supersect
*ss
, const char **addr
, const char *fmt
, ...);
139 void rm_some_exports(struct superbfd
*isbfd
, const struct export_desc
*ed
);
140 void write_ksplice_export(struct superbfd
*sbfd
, const char *symname
,
141 const char *export_type
, bool del
);
142 void write_reloc(struct supersect
*ss
, const void *addr
, asymbol
**symp
,
144 arelent
*create_reloc(struct supersect
*ss
, const void *addr
, asymbol
**symp
,
146 static void match_global_symbol_sections(struct superbfd
*oldsbfd
,
147 struct superbfd
*newsbfd
);
148 static void match_sections_by_name(struct superbfd
*oldsbfd
,
149 struct superbfd
*newsbfd
);
150 static void match_sections_by_contents(struct superbfd
*oldsbfd
,
151 struct superbfd
*newsbfd
);
152 static void match_sections_by_label(struct superbfd
*oldsbfd
,
153 struct superbfd
*newsbfd
);
154 static void mark_new_sections(struct superbfd
*sbfd
);
155 static void handle_deleted_sections(struct superbfd
*oldsbfd
,
156 struct superbfd
*newsbfd
);
157 static void compare_matched_sections(struct superbfd
*sbfd
);
158 static void update_nonzero_offsets(struct superbfd
*sbfd
);
159 static void handle_nonzero_offset_relocs(struct supersect
*ss
);
161 struct str_vec delsects
, rmsyms
;
162 struct export_desc_vec exports
;
165 struct ksplice_config
*config
;
167 const char *modestr
, *kid
;
169 struct superbfd
*offsets_sbfd
= NULL
;
171 #define mode(str) starts_with(modestr, str)
173 DECLARE_VEC_TYPE(unsigned long, addr_vec
);
174 DEFINE_HASH_TYPE(struct addr_vec
, addr_vec_hash
,
175 addr_vec_hash_init
, addr_vec_hash_free
, addr_vec_hash_lookup
,
177 struct addr_vec_hash system_map
;
179 struct bool_hash system_map_written
;
180 struct ulong_hash ksplice_symbol_offset
;
181 struct ulong_hash ksplice_string_offset
;
183 void load_system_map()
185 const char *config_dir
= getenv("KSPLICE_CONFIG_DIR");
188 assert(asprintf(&file
, "%s/System.map", config_dir
) >= 0);
189 FILE *fp
= fopen(file
, "r");
191 addr_vec_hash_init(&system_map
);
195 while (fscanf(fp
, "%lx %c %as\n", &addr
, &type
, &sym
) == 3)
196 *vec_grow(addr_vec_hash_lookup(&system_map
, sym
, TRUE
),
203 char *kmodsrc
= getenv("KSPLICE_KMODSRC"), *offsets_file
;
204 assert(kmodsrc
!= NULL
);
205 assert(asprintf(&offsets_file
, "%s/offsets.o", kmodsrc
) >= 0);
206 bfd
*offsets_bfd
= bfd_openr(offsets_file
, NULL
);
207 assert(offsets_bfd
!= NULL
);
209 assert(bfd_check_format_matches(offsets_bfd
, bfd_object
, &matching
));
210 offsets_sbfd
= fetch_superbfd(offsets_bfd
);
212 asection
*config_sect
= bfd_get_section_by_name(offsets_sbfd
->abfd
,
214 struct supersect
*config_ss
=
215 fetch_supersect(offsets_sbfd
, config_sect
);
217 config
= config_ss
->contents
.data
;
220 bool matchable_data_section(struct supersect
*ss
)
222 if (ss
->type
== SS_TYPE_RODATA
)
224 if (ss
->type
== SS_TYPE_DATA
&& ss
->relocs
.size
!= 0)
229 bool unchangeable_section(struct supersect
*ss
)
231 if (ss
->type
== SS_TYPE_DATA
)
233 if (ss
->type
== SS_TYPE_IGNORED
&& !starts_with(ss
->name
, ".debug"))
238 int main(int argc
, char *argv
[])
241 bfd
*ibfd
= bfd_openr(argv
[1], NULL
);
245 assert(bfd_check_format_matches(ibfd
, bfd_object
, &matching
));
247 const char *output_target
= bfd_get_target(ibfd
);
248 bfd
*obfd
= bfd_openw(argv
[2], output_target
);
251 struct superbfd
*isbfd
= fetch_superbfd(ibfd
);
253 bool_hash_init(&system_map_written
);
254 ulong_hash_init(&ksplice_symbol_offset
);
255 ulong_hash_init(&ksplice_string_offset
);
258 if (mode("keep-primary")) {
260 do_keep_primary(isbfd
, argv
[4]);
261 } else if (mode("keep-helper")) {
262 do_keep_helper(isbfd
);
263 } else if (mode("finalize")) {
265 } else if (mode("rmsyms")) {
269 copy_object(ibfd
, obfd
);
271 if (offsets_sbfd
!= NULL
)
272 assert(bfd_close(offsets_sbfd
->abfd
));
273 assert(bfd_close(obfd
));
274 assert(bfd_close(ibfd
));
278 void do_keep_primary(struct superbfd
*isbfd
, const char *pre
)
280 struct bfd
*prebfd
= bfd_openr(pre
, NULL
);
281 assert(prebfd
!= NULL
);
283 assert(bfd_check_format_matches(prebfd
, bfd_object
, &matching
));
285 struct superbfd
*presbfd
= fetch_superbfd(prebfd
);
288 initialize_supersect_types(isbfd
);
289 initialize_supersect_types(presbfd
);
291 match_global_symbol_sections(presbfd
, isbfd
);
292 printf("Matched global\n");
293 match_sections_by_name(presbfd
, isbfd
);
294 printf("Matched by name\n");
295 match_sections_by_label(presbfd
, isbfd
);
296 printf("Matched by label\n");
297 match_sections_by_contents(presbfd
, isbfd
);
298 printf("Matched by contents\n");
302 compare_matched_sections(isbfd
);
303 update_nonzero_offsets(isbfd
);
304 mark_new_sections(isbfd
);
308 handle_deleted_sections(presbfd
, isbfd
);
309 handle_section_symbol_renames(presbfd
, isbfd
);
312 compare_exported_symbols(presbfd
, isbfd
, "");
313 compare_exported_symbols(isbfd
, presbfd
, "del_");
315 assert(bfd_close(prebfd
));
318 for (sect
= isbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
319 struct supersect
*ss
= fetch_supersect(isbfd
, sect
);
321 if (ss
->type
== SS_TYPE_STRING
|| ss
->type
== SS_TYPE_SPECIAL
||
322 ss
->type
== SS_TYPE_EXPORT
)
324 if (ss
->new || ss
->patch
)
328 const char **sectname
;
329 printf("Label name changes:\n");
330 print_label_map(isbfd
);
332 printf("Changed text sections:\n");
333 for (sect
= isbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
334 struct supersect
*ss
= fetch_supersect(isbfd
, sect
);
336 printf(" %s\n", sect
->name
);
339 printf("New sections:\n");
340 for (sect
= isbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
341 struct supersect
*ss
= fetch_supersect(isbfd
, sect
);
343 printf(" %s\n", sect
->name
);
345 if (delsects
.size
!= 0) {
346 printf("Deleted section names:\n");
347 for (sectname
= delsects
.data
;
348 sectname
< delsects
.data
+ delsects
.size
; sectname
++)
349 printf(" %s\n", *sectname
);
351 const struct export_desc
*ed
;
352 for (ed
= exports
.data
; ed
< exports
.data
+ exports
.size
; ed
++) {
353 const char **symname
;
354 bool del
= starts_with(ed
->sectname
, "del___ksymtab");
355 const char *export_type
= ed
->sectname
+ strlen("__ksymtab");
357 export_type
+= strlen("_del");
358 for (symname
= ed
->names
.data
;
359 symname
< ed
->names
.data
+ ed
->names
.size
; symname
++)
360 printf("Export %s(%s): %s\n",
361 del
? "deletion" : "addition",
362 export_type
, *symname
);
365 for (sect
= isbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
366 struct supersect
*ss
= fetch_supersect(isbfd
, sect
);
367 if (!ss
->patch
&& !ss
->new)
369 asymbol
**symp
= canonical_symbolp(isbfd
, sect
->symbol
);
372 write_ksplice_section(isbfd
, symp
);
374 write_ksplice_patch(isbfd
, sect
->name
);
377 for (ed
= exports
.data
; ed
< exports
.data
+ exports
.size
; ed
++) {
378 if (starts_with(ed
->sectname
, "del___ksymtab")) {
379 const char *export_type
=
380 ed
->sectname
+ strlen("del___ksymtab");
381 const char **symname
;
382 for (symname
= ed
->names
.data
;
383 symname
< ed
->names
.data
+ ed
->names
.size
;
385 write_ksplice_export(isbfd
, *symname
,
388 rm_some_exports(isbfd
, ed
);
393 filter_table_sections(isbfd
);
396 void do_keep_helper(struct superbfd
*isbfd
)
400 initialize_supersect_types(isbfd
);
403 for (sect
= isbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
404 struct supersect
*ss
= fetch_supersect(isbfd
, sect
);
406 if (ss
->type
== SS_TYPE_STRING
|| ss
->type
== SS_TYPE_SPECIAL
||
407 ss
->type
== SS_TYPE_TEXT
)
412 bfd_map_over_sections(isbfd
->abfd
, keep_if_referenced
, NULL
);
415 for (sect
= isbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
416 struct supersect
*ss
= fetch_supersect(isbfd
, sect
);
417 asymbol
**symp
= canonical_symbolp(isbfd
, sect
->symbol
);
420 asymbol
*sym
= *symp
;
421 if ((sym
->flags
& BSF_WEAK
) != 0)
423 if (bfd_get_section_size(sect
) == 0)
425 if (ss
->keep
&& (ss
->type
== SS_TYPE_TEXT
||
426 matchable_data_section(ss
)))
427 write_ksplice_section(isbfd
, symp
);
431 filter_table_sections(isbfd
);
434 void do_finalize(struct superbfd
*isbfd
)
438 initialize_supersect_types(isbfd
);
442 void do_rmsyms(struct superbfd
*isbfd
)
444 read_str_set(&rmsyms
);
447 initialize_supersect_types(isbfd
);
451 struct export_vec
*get_export_syms(struct superbfd
*sbfd
)
454 struct export_vec
*exports
;
455 exports
= malloc(sizeof(*exports
));
456 assert(exports
!= NULL
);
459 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
460 if (!starts_with(sect
->name
, "__ksymtab") ||
461 ends_with(sect
->name
, "_strings"))
463 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
464 struct kernel_symbol
*sym
;
465 assert(ss
->contents
.size
* 2 == ss
->relocs
.size
*
466 sizeof(struct kernel_symbol
));
467 for (sym
= ss
->contents
.data
;
468 (void *)sym
< ss
->contents
.data
+ ss
->contents
.size
;
470 struct export
*exp
= vec_grow(exports
, 1);
472 read_string(ss
, (const char *const *)&sym
->name
);
479 void compare_exported_symbols(struct superbfd
*oldsbfd
,
480 struct superbfd
*newsbfd
, char *addstr
)
482 struct export_vec
*new_exports
, *old_exports
;
483 new_exports
= get_export_syms(newsbfd
);
484 if (new_exports
== NULL
)
486 old_exports
= get_export_syms(oldsbfd
);
487 struct export
*old
, *new;
488 asection
*last_sect
= NULL
;
489 struct export_desc
*ed
;
490 for (new = new_exports
->data
; new < new_exports
->data
+
491 new_exports
->size
; new++) {
493 if (old_exports
!= NULL
) {
494 for (old
= old_exports
->data
; old
< old_exports
->data
+
495 old_exports
->size
; old
++) {
496 if (strcmp(new->name
, old
->name
) == 0 &&
497 strcmp(new->sect
->name
, old
->sect
->name
)
504 if (last_sect
!= new->sect
) {
505 last_sect
= new->sect
;
506 ed
= vec_grow(&exports
, 1);
508 assert(asprintf(§name
, "%s%s", addstr
,
509 new->sect
->name
) >= 0);
510 ed
->sectname
= sectname
;
511 vec_init(&ed
->names
);
514 *vec_grow(&ed
->names
, 1) = new->name
;
518 void match_sections(struct supersect
*oldss
, struct supersect
*newss
)
520 if (oldss
->match
== newss
&& newss
->match
== oldss
)
522 if (oldss
->match
!= NULL
) {
523 fprintf(stderr
, "Matching conflict: old %s: %s != %s\n",
524 oldss
->name
, oldss
->match
->name
, newss
->name
);
527 if (newss
->match
!= NULL
) {
528 fprintf(stderr
, "Matching conflict: new %s: %s != %s\n",
529 newss
->name
, newss
->match
->name
, oldss
->name
);
532 oldss
->match
= newss
;
533 newss
->match
= oldss
;
534 printf("Matched old %s to new %s\n", oldss
->name
, newss
->name
);
537 static void match_global_symbol_sections(struct superbfd
*oldsbfd
,
538 struct superbfd
*newsbfd
)
540 asymbol
**oldsymp
, **newsymp
;
541 for (oldsymp
= oldsbfd
->syms
.data
;
542 oldsymp
< oldsbfd
->syms
.data
+ oldsbfd
->syms
.size
; oldsymp
++) {
543 asymbol
*oldsym
= *oldsymp
;
544 if ((oldsym
->flags
& BSF_GLOBAL
) == 0 ||
545 bfd_is_const_section(oldsym
->section
))
547 for (newsymp
= newsbfd
->syms
.data
;
548 newsymp
< newsbfd
->syms
.data
+ newsbfd
->syms
.size
;
550 asymbol
*newsym
= *newsymp
;
551 if ((newsym
->flags
& BSF_GLOBAL
) == 0 ||
552 bfd_is_const_section(oldsym
->section
))
554 if (strcmp(oldsym
->name
, newsym
->name
) != 0)
556 struct supersect
*oldss
=
557 fetch_supersect(oldsbfd
, oldsym
->section
);
558 struct supersect
*newss
=
559 fetch_supersect(newsbfd
, newsym
->section
);
560 match_sections(oldss
, newss
);
565 static void match_sections_by_name(struct superbfd
*oldsbfd
,
566 struct superbfd
*newsbfd
)
568 asection
*newp
, *oldp
;
569 for (newp
= newsbfd
->abfd
->sections
; newp
!= NULL
; newp
= newp
->next
) {
570 struct supersect
*newss
= fetch_supersect(newsbfd
, newp
);
571 oldp
= bfd_get_section_by_name(oldsbfd
->abfd
, newp
->name
);
572 if (oldp
== NULL
|| newss
->type
== SS_TYPE_STRING
||
573 newss
->type
== SS_TYPE_SPECIAL
||
574 newss
->type
== SS_TYPE_EXPORT
)
576 if (static_local_symbol(newsbfd
,
577 canonical_symbol(newsbfd
,
581 struct supersect
*oldss
= fetch_supersect(oldsbfd
, oldp
);
582 match_sections(oldss
, newss
);
586 static void match_sections_by_label(struct superbfd
*oldsbfd
,
587 struct superbfd
*newsbfd
)
589 asection
*oldsect
, *newsect
;
590 struct supersect
*oldss
, *newss
;
591 for (newsect
= newsbfd
->abfd
->sections
; newsect
!= NULL
;
592 newsect
= newsect
->next
) {
593 newss
= fetch_supersect(newsbfd
, newsect
);
594 if (newss
->type
== SS_TYPE_STRING
||
595 newss
->type
== SS_TYPE_SPECIAL
||
596 newss
->type
== SS_TYPE_EXPORT
)
598 for (oldsect
= oldsbfd
->abfd
->sections
; oldsect
!= NULL
;
599 oldsect
= oldsect
->next
) {
600 if (strcmp(label_lookup(newsbfd
, newsect
->symbol
),
601 label_lookup(oldsbfd
, oldsect
->symbol
)) != 0)
603 oldss
= fetch_supersect(oldsbfd
, oldsect
);
604 match_sections(oldss
, newss
);
609 static void match_sections_by_contents(struct superbfd
*oldsbfd
,
610 struct superbfd
*newsbfd
)
612 asection
*oldsect
, *newsect
;
613 struct supersect
*oldss
, *newss
;
614 for (newsect
= newsbfd
->abfd
->sections
; newsect
!= NULL
;
615 newsect
= newsect
->next
) {
616 newss
= fetch_supersect(newsbfd
, newsect
);
617 if (newss
->type
!= SS_TYPE_RODATA
)
619 for (oldsect
= oldsbfd
->abfd
->sections
; oldsect
!= NULL
;
620 oldsect
= oldsect
->next
) {
621 oldss
= fetch_supersect(oldsbfd
, oldsect
);
622 if (oldss
->type
!= SS_TYPE_RODATA
)
624 if (oldss
->relocs
.size
!= 0 || newss
->relocs
.size
!= 0)
626 if (oldss
->contents
.size
!= newss
->contents
.size
)
628 if (memcmp(oldss
->contents
.data
, newss
->contents
.data
,
629 oldss
->contents
.size
) != 0)
631 match_sections(oldss
, newss
);
636 static void mark_new_sections(struct superbfd
*sbfd
)
639 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
640 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
641 if (ss
->type
== SS_TYPE_STRING
|| ss
->type
== SS_TYPE_SPECIAL
||
642 ss
->type
== SS_TYPE_IGNORED
|| ss
->type
== SS_TYPE_EXPORT
)
644 if (ss
->match
== NULL
)
649 static void handle_deleted_sections(struct superbfd
*oldsbfd
,
650 struct superbfd
*newsbfd
)
653 for (sect
= oldsbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
654 struct supersect
*ss
= fetch_supersect(oldsbfd
, sect
);
655 if (ss
->type
!= SS_TYPE_TEXT
)
657 if (ss
->match
!= NULL
)
659 const char *label
= label_lookup(oldsbfd
, sect
->symbol
);
660 *vec_grow(&delsects
, 1) = label
;
661 asymbol
*csym
= canonical_symbol(oldsbfd
, sect
->symbol
);
662 write_ksplice_deleted_patch(newsbfd
, csym
->name
, label
);
666 static void handle_nonzero_offset_relocs(struct supersect
*ss
)
669 for (i
= 0; i
< ss
->relocs
.size
; i
++) {
670 asymbol
*sym
= *ss
->relocs
.data
[i
]->sym_ptr_ptr
;
671 bfd_vma offset
= get_reloc_offset(ss
, ss
->relocs
.data
[i
], true);
672 if (sym
->value
+ offset
== 0)
674 if (bfd_is_const_section(sym
->section
))
676 struct supersect
*sym_ss
= fetch_supersect(ss
->parent
,
678 if (sym_ss
->type
!= SS_TYPE_TEXT
)
680 if (!sym_ss
->patch
) {
682 printf("Changing %s because a relocation from sect %s "
683 "has a nonzero offset %lx+%lx into it\n",
684 sym_ss
->name
, ss
->name
,
685 (unsigned long)sym
->value
,
686 (unsigned long)offset
);
688 sym_ss
->patch
= true;
692 static void update_nonzero_offsets(struct superbfd
*sbfd
)
695 struct supersect
*ss
;
697 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
698 ss
= fetch_supersect(sbfd
, sect
);
699 if (ss
->new || ss
->patch
)
700 handle_nonzero_offset_relocs(ss
);
704 static void compare_matched_sections(struct superbfd
*newsbfd
)
707 struct supersect
*old_ss
, *new_ss
;
708 for (newp
= newsbfd
->abfd
->sections
; newp
!= NULL
; newp
= newp
->next
) {
709 new_ss
= fetch_supersect(newsbfd
, newp
);
710 if (new_ss
->match
== NULL
)
712 old_ss
= new_ss
->match
;
714 if (nonrelocs_equal(old_ss
, new_ss
) &&
715 relocs_equal(old_ss
, new_ss
))
717 if (new_ss
->type
== SS_TYPE_TEXT
) {
720 new_ss
->patch
= true;
721 printf("Changing %s due to ", new_ss
->name
);
723 printf("Unmatching %s and %s due to ", old_ss
->name
,
725 new_ss
->match
= NULL
;
726 old_ss
->match
= NULL
;
728 if (new_ss
->contents
.size
!= old_ss
->contents
.size
)
729 printf("differing sizes\n");
730 else if (memcmp(new_ss
->contents
.data
, old_ss
->contents
.data
,
731 new_ss
->contents
.size
) != 0)
732 printf("differing contents\n");
734 printf("differing relocations\n");
736 if (unchangeable_section(new_ss
))
737 fprintf(stderr
, "WARNING: ignoring change to "
738 "nonpatchable section %s\n", new_ss
->name
);
742 static void handle_section_symbol_renames(struct superbfd
*oldsbfd
,
743 struct superbfd
*newsbfd
)
745 asection
*newp
, *oldp
;
746 for (newp
= newsbfd
->abfd
->sections
; newp
!= NULL
; newp
= newp
->next
) {
747 struct supersect
*newss
= fetch_supersect(newsbfd
, newp
);
748 if (newss
->match
== NULL
)
750 oldp
= bfd_get_section_by_name(oldsbfd
->abfd
,
755 const char *old_label
= label_lookup(oldsbfd
, oldp
->symbol
);
756 const char *new_label
= label_lookup(newsbfd
, newp
->symbol
);
758 if (strcmp(old_label
, new_label
) == 0)
760 label_map_set(newsbfd
, new_label
, old_label
);
764 static bool part_of_reloc(struct supersect
*ss
, unsigned long addr
)
767 for (relocp
= ss
->relocs
.data
;
768 relocp
< ss
->relocs
.data
+ ss
->relocs
.size
; relocp
++) {
769 arelent
*reloc
= *relocp
;
770 if (addr
>= reloc
->address
&&
771 addr
< reloc
->address
+ reloc
->howto
->size
)
777 static bool nonrelocs_equal(struct supersect
*old_ss
, struct supersect
*new_ss
)
780 if (old_ss
->contents
.size
!= new_ss
->contents
.size
)
782 const unsigned char *old
= old_ss
->contents
.data
;
783 const unsigned char *new = new_ss
->contents
.data
;
784 for (i
= 0; i
< old_ss
->contents
.size
; i
++) {
785 if (old
[i
] != new[i
] &&
786 !(part_of_reloc(old_ss
, i
) && part_of_reloc(new_ss
, i
)))
793 * relocs_equal checks to see whether the old section and the new section
794 * reference different read-only data in their relocations -- if a hard-coded
795 * string has been changed between the old file and the new file, relocs_equal
796 * will detect the difference.
798 bool relocs_equal(struct supersect
*old_ss
, struct supersect
*new_ss
)
801 struct superbfd
*oldsbfd
= old_ss
->parent
;
802 struct superbfd
*newsbfd
= new_ss
->parent
;
804 if (old_ss
->relocs
.size
!= new_ss
->relocs
.size
) {
805 printf("Different reloc count between %s and %s\n",
806 old_ss
->name
, new_ss
->name
);
810 for (i
= 0; i
< old_ss
->relocs
.size
; i
++) {
811 struct supersect
*ro_old_ss
, *ro_new_ss
;
813 asymbol
*old_sym
= *old_ss
->relocs
.data
[i
]->sym_ptr_ptr
;
814 asymbol
*new_sym
= *new_ss
->relocs
.data
[i
]->sym_ptr_ptr
;
817 get_reloc_offset(old_ss
, old_ss
->relocs
.data
[i
], true);
819 get_reloc_offset(new_ss
, new_ss
->relocs
.data
[i
], true);
821 if (bfd_is_und_section(old_sym
->section
) ||
822 bfd_is_und_section(new_sym
->section
)) {
823 if (!bfd_is_und_section(new_sym
->section
) &&
824 fetch_supersect(newsbfd
, new_sym
->section
)->type
825 == SS_TYPE_TEXT
&& old_offset
!= 0)
828 if (!bfd_is_und_section(old_sym
->section
) &&
829 fetch_supersect(oldsbfd
, old_sym
->section
)->type
830 == SS_TYPE_TEXT
&& new_offset
!= 0)
833 if (strcmp(old_sym
->name
, new_sym
->name
) == 0 &&
834 old_offset
== new_offset
)
839 if (bfd_is_const_section(old_sym
->section
) ||
840 bfd_is_const_section(new_sym
->section
))
843 ro_old_ss
= fetch_supersect(oldsbfd
, old_sym
->section
);
844 ro_new_ss
= fetch_supersect(newsbfd
, new_sym
->section
);
846 if (ro_old_ss
->type
== SS_TYPE_STRING
&&
847 /* check it's not an out-of-range relocation to a string;
848 we'll just compare entire sections for them */
849 !(old_offset
>= ro_old_ss
->contents
.size
||
850 new_offset
>= ro_new_ss
->contents
.size
)) {
851 if (strcmp(ro_old_ss
->contents
.data
+ old_sym
->value
+
853 ro_new_ss
->contents
.data
+ new_sym
->value
+
855 printf("Strings differ between %s and %s\n",
856 old_ss
->name
, new_ss
->name
);
862 if (ro_old_ss
->match
!= ro_new_ss
||
863 ro_new_ss
->match
!= ro_old_ss
) {
864 printf("Nonmatching relocs from %s to %s/%s\n",
865 new_ss
->name
, ro_new_ss
->name
, ro_old_ss
->name
);
869 if (old_sym
->value
+ old_offset
!= new_sym
->value
+ new_offset
) {
870 printf("Offsets to %s/%s differ between %s and %s: "
871 "%lx+%lx/%lx+%lx\n", ro_old_ss
->name
,
872 ro_new_ss
->name
, old_ss
->name
, new_ss
->name
,
873 (unsigned long)old_sym
->value
,
874 (unsigned long)old_offset
,
875 (unsigned long)new_sym
->value
,
876 (unsigned long)new_offset
);
880 if ((old_sym
->value
+ old_offset
!= 0 ||
881 new_sym
->value
+ new_offset
!= 0) && ro_new_ss
->patch
) {
882 printf("Relocation from %s to nonzero offsets %lx+%lx/"
883 "%lx+%lx in changed section %s\n", new_ss
->name
,
884 (unsigned long)old_sym
->value
,
885 (unsigned long)old_offset
,
886 (unsigned long)new_sym
->value
,
887 (unsigned long)new_offset
,
888 new_sym
->section
->name
);
896 void rm_some_exports(struct superbfd
*isbfd
, const struct export_desc
*ed
)
898 assert(starts_with(ed
->sectname
, "__ksymtab"));
899 const char *export_type
= ed
->sectname
+ strlen("__ksymtab");
900 asection
*sym_sect
= bfd_get_section_by_name(isbfd
->abfd
, ed
->sectname
);
901 assert(sym_sect
!= NULL
);
902 char *export_crc_name
;
903 assert(asprintf(&export_crc_name
, "__kcrctab%s", export_type
) >= 0);
904 asection
*crc_sect
= bfd_get_section_by_name(isbfd
->abfd
,
906 struct supersect
*ss
, *crc_ss
= NULL
;
907 ss
= fetch_supersect(isbfd
, sym_sect
);
908 if (crc_sect
!= NULL
)
909 crc_ss
= fetch_supersect(isbfd
, crc_sect
);
912 assert(ss
->contents
.size
* sizeof(unsigned long) ==
913 crc_ss
->contents
.size
* sizeof(struct kernel_symbol
));
915 struct supersect orig_ss
, orig_crc_ss
;
916 supersect_move(&orig_ss
, ss
);
918 supersect_move(&orig_crc_ss
, crc_ss
);
920 struct kernel_symbol
*orig_ksym
;
921 unsigned long *orig_crc
;
922 for (orig_ksym
= orig_ss
.contents
.data
,
923 orig_crc
= orig_crc_ss
.contents
.data
;
924 (void *)orig_ksym
< orig_ss
.contents
.data
+ orig_ss
.contents
.size
;
925 orig_ksym
++, orig_crc
++) {
927 read_reloc(&orig_ss
, &orig_ksym
->value
,
928 sizeof(orig_ksym
->value
), &sym
);
929 if (!str_in_set(sym
->name
, &ed
->names
))
932 struct kernel_symbol
*ksym
= sect_grow(ss
, 1, typeof(*ksym
));
933 sect_copy(ss
, &ksym
->value
, &orig_ss
, &orig_ksym
->value
, 1);
934 /* Replace name with a mangled name */
935 write_ksplice_export(ss
->parent
, sym
->name
, export_type
, false);
936 write_string(ss
, (const char **)&ksym
->name
,
937 "DISABLED_%s_%s", sym
->name
, kid
);
941 sect_grow(crc_ss
, 1, typeof(*orig_crc
)),
942 &orig_crc_ss
, orig_crc
, 1);
946 void rm_relocs(struct superbfd
*isbfd
)
949 for (p
= isbfd
->abfd
->sections
; p
!= NULL
; p
= p
->next
) {
950 struct supersect
*ss
= fetch_supersect(isbfd
, p
);
951 if (ss
->type
== SS_TYPE_SPECIAL
|| ss
->type
== SS_TYPE_KSPLICE
)
953 if (ss
->keep
|| mode("rmsyms"))
956 if (mode("finalize")) {
957 p
= bfd_get_section_by_name(isbfd
->abfd
, ".ksplice_patches");
959 struct supersect
*ss
= fetch_supersect(isbfd
, p
);
965 void rm_some_relocs(struct supersect
*ss
)
967 struct arelentp_vec orig_relocs
;
968 vec_move(&orig_relocs
, &ss
->relocs
);
971 for (relocp
= orig_relocs
.data
;
972 relocp
< orig_relocs
.data
+ orig_relocs
.size
; relocp
++) {
973 bool rm_reloc
= false;
974 asymbol
*sym_ptr
= *(*relocp
)->sym_ptr_ptr
;
976 if (mode("rmsyms") && str_in_set(sym_ptr
->name
, &rmsyms
) &&
977 bfd_is_und_section(sym_ptr
->section
))
983 if (mode("keep-primary") &&
984 (bfd_is_const_section(sym_ptr
->section
) ||
985 fetch_supersect(ss
->parent
, sym_ptr
->section
)->new ||
986 fetch_supersect(ss
->parent
, sym_ptr
->section
)->type
==
990 if (mode("finalize") && bfd_is_und_section(sym_ptr
->section
))
994 write_ksplice_reloc(ss
, *relocp
);
996 *vec_grow(&ss
->relocs
, 1) = *relocp
;
1000 struct supersect
*make_section(struct superbfd
*sbfd
, const char *name
)
1002 asection
*sect
= bfd_get_section_by_name(sbfd
->abfd
, name
);
1004 return fetch_supersect(sbfd
, sect
);
1006 return new_supersect(sbfd
, name
);
1009 arelent
*create_reloc(struct supersect
*ss
, const void *addr
, asymbol
**symp
,
1012 bfd_reloc_code_real_type code
;
1013 switch (bfd_arch_bits_per_address(ss
->parent
->abfd
)) {
1015 code
= BFD_RELOC_32
;
1018 code
= BFD_RELOC_64
;
1024 arelent
*reloc
= malloc(sizeof(*reloc
));
1025 reloc
->sym_ptr_ptr
= symp
;
1026 reloc
->address
= addr
- ss
->contents
.data
;
1027 reloc
->howto
= bfd_reloc_type_lookup(ss
->parent
->abfd
, code
);
1028 reloc
->addend
= offset
;
1032 void write_reloc(struct supersect
*ss
, const void *addr
, asymbol
**symp
,
1035 arelent
*new_reloc
= create_reloc(ss
, addr
, symp
, offset
), **relocp
;
1036 for (relocp
= ss
->relocs
.data
;
1037 relocp
< ss
->relocs
.data
+ ss
->relocs
.size
; relocp
++) {
1038 if ((*relocp
)->address
== new_reloc
->address
) {
1041 (void *)(ss
->relocs
.data
+ ss
->relocs
.size
) -
1042 (void *)(relocp
+ 1));
1047 *vec_grow(&ss
->new_relocs
, 1) = new_reloc
;
1050 void write_string(struct supersect
*ss
, const char **addr
, const char *fmt
, ...)
1053 struct supersect
*str_ss
= make_section(ss
->parent
, ".ksplice_str");
1056 int len
= vasprintf(&str
, fmt
, ap
);
1060 unsigned long *str_offp
= ulong_hash_lookup(&ksplice_string_offset
, str
,
1062 if (str_offp
== NULL
) {
1063 char *buf
= sect_grow(str_ss
, len
+ 1, char);
1064 memcpy(buf
, str
, len
+ 1);
1065 str_offp
= ulong_hash_lookup(&ksplice_string_offset
, str
, TRUE
);
1066 *str_offp
= (void *)buf
- str_ss
->contents
.data
;
1069 write_reloc(ss
, addr
, &str_ss
->symbol
, *str_offp
);
1072 void lookup_system_map(struct addr_vec
*addrs
, const char *name
, long offset
)
1074 struct addr_vec
*map_addrs
=
1075 addr_vec_hash_lookup(&system_map
, name
, FALSE
);
1076 if (map_addrs
== NULL
)
1079 unsigned long *addr
, *map_addr
;
1080 for (map_addr
= map_addrs
->data
;
1081 map_addr
< map_addrs
->data
+ map_addrs
->size
; map_addr
++) {
1082 for (addr
= addrs
->data
; addr
< addrs
->data
+ addrs
->size
;
1084 if (*addr
== *map_addr
+ offset
)
1087 if (addr
< addrs
->data
+ addrs
->size
)
1089 *vec_grow(addrs
, 1) = *map_addr
+ offset
;
1093 void write_system_map_array(struct superbfd
*sbfd
, struct supersect
*ss
,
1094 const unsigned long **sym_addrs
,
1095 unsigned long *num_sym_addrs
, asymbol
*sym
)
1097 struct addr_vec addrs
;
1100 if (bfd_is_abs_section(sym
->section
)) {
1101 *vec_grow(&addrs
, 1) = sym
->value
;
1102 } else if (bfd_is_und_section(sym
->section
)) {
1103 lookup_system_map(&addrs
, sym
->name
, 0);
1104 } else if (!bfd_is_const_section(sym
->section
)) {
1106 for (gsymp
= sbfd
->syms
.data
;
1107 gsymp
< sbfd
->syms
.data
+ sbfd
->syms
.size
; gsymp
++) {
1108 asymbol
*gsym
= *gsymp
;
1109 if ((gsym
->flags
& BSF_DEBUGGING
) == 0 &&
1110 gsym
->section
== sym
->section
)
1111 lookup_system_map(&addrs
, gsym
->name
,
1112 sym
->value
- gsym
->value
);
1116 *num_sym_addrs
= addrs
.size
;
1117 if (addrs
.size
!= 0) {
1118 struct supersect
*array_ss
= make_section(sbfd
,
1120 void *buf
= sect_grow(array_ss
, addrs
.size
,
1121 typeof(*addrs
.data
));
1122 memcpy(buf
, addrs
.data
, addrs
.size
* sizeof(*addrs
.data
));
1123 write_reloc(ss
, sym_addrs
, &array_ss
->symbol
,
1124 buf
- array_ss
->contents
.data
);
1132 void write_ksplice_system_map(struct superbfd
*sbfd
, asymbol
*sym
,
1133 const char *addstr_sect
)
1135 struct supersect
*smap_ss
= make_section(sbfd
, ".ksplice_system_map");
1136 struct ksplice_system_map
*smap
;
1137 const char *label
= label_lookup(sbfd
, sym
);
1139 bool *done
= bool_hash_lookup(&system_map_written
, label
, TRUE
);
1144 smap
= sect_grow(smap_ss
, 1, struct ksplice_system_map
);
1146 write_system_map_array(sbfd
, smap_ss
, &smap
->candidates
,
1147 &smap
->nr_candidates
, sym
);
1148 write_string(smap_ss
, &smap
->label
, "%s%s", label
, addstr_sect
);
1151 void write_ksplice_symbol(struct supersect
*ss
,
1152 const struct ksplice_symbol
*const *addr
,
1153 asymbol
*sym
, const char *addstr_sect
)
1155 struct supersect
*ksymbol_ss
= make_section(ss
->parent
,
1156 ".ksplice_symbols");
1157 struct ksplice_symbol
*ksymbol
;
1158 unsigned long *ksymbol_offp
;
1159 const char *label
= label_lookup(ss
->parent
, sym
);
1161 assert(asprintf(&output
, "%s%s", label
, addstr_sect
) >= 0);
1163 ksymbol_offp
= ulong_hash_lookup(&ksplice_symbol_offset
, output
, FALSE
);
1164 if (ksymbol_offp
!= NULL
) {
1165 write_reloc(ss
, addr
, &ksymbol_ss
->symbol
, *ksymbol_offp
);
1168 ksymbol
= sect_grow(ksymbol_ss
, 1, struct ksplice_symbol
);
1169 ksymbol_offp
= ulong_hash_lookup(&ksplice_symbol_offset
, output
, TRUE
);
1170 *ksymbol_offp
= (void *)ksymbol
- ksymbol_ss
->contents
.data
;
1172 if (bfd_is_und_section(sym
->section
) || (sym
->flags
& BSF_GLOBAL
) != 0) {
1173 write_string(ksymbol_ss
, &ksymbol
->name
, "%s", sym
->name
);
1174 } else if (bfd_is_const_section(sym
->section
)) {
1175 ksymbol
->name
= NULL
;
1177 asymbol
*gsym
= canonical_symbol(ss
->parent
, sym
);
1179 if (gsym
== NULL
|| (gsym
->flags
& BSF_SECTION_SYM
) != 0)
1180 ksymbol
->name
= NULL
;
1182 write_string(ksymbol_ss
, &ksymbol
->name
, "%s",
1186 write_string(ksymbol_ss
, &ksymbol
->label
, "%s%s", label
, addstr_sect
);
1188 write_ksplice_system_map(ksymbol_ss
->parent
, sym
, addstr_sect
);
1190 write_reloc(ss
, addr
, &ksymbol_ss
->symbol
, *ksymbol_offp
);
1193 void write_ksplice_reloc(struct supersect
*ss
, arelent
*orig_reloc
)
1195 asymbol
*sym_ptr
= *orig_reloc
->sym_ptr_ptr
;
1196 reloc_howto_type
*howto
= orig_reloc
->howto
;
1197 bfd_vma addend
= get_reloc_offset(ss
, orig_reloc
, false);
1199 if (mode("finalize") && starts_with(ss
->name
, ".ksplice_patches")) {
1200 unsigned long *repladdr
=
1201 ss
->contents
.data
+ orig_reloc
->address
;
1206 blot_section(ss
, orig_reloc
->address
, howto
);
1208 struct supersect
*kreloc_ss
= make_section(ss
->parent
,
1210 ".ksplice_init_relocs" :
1212 struct ksplice_reloc
*kreloc
= sect_grow(kreloc_ss
, 1,
1213 struct ksplice_reloc
);
1215 write_reloc(kreloc_ss
, &kreloc
->blank_addr
,
1216 &ss
->symbol
, orig_reloc
->address
);
1217 kreloc
->blank_offset
= (unsigned long)orig_reloc
->address
;
1218 write_ksplice_symbol(kreloc_ss
, &kreloc
->symbol
, sym_ptr
, "");
1219 kreloc
->pcrel
= howto
->pc_relative
;
1220 kreloc
->addend
= addend
;
1221 kreloc
->size
= bfd_get_reloc_size(howto
);
1222 kreloc
->dst_mask
= howto
->dst_mask
;
1223 kreloc
->rightshift
= howto
->rightshift
;
1224 kreloc
->signed_addend
=
1225 (howto
->complain_on_overflow
== complain_overflow_signed
) ||
1226 (howto
->complain_on_overflow
== complain_overflow_bitfield
);
1229 #define CANARY(x, canary) ((x & ~howto->dst_mask) | (canary & howto->dst_mask))
1231 void blot_section(struct supersect
*ss
, int offset
, reloc_howto_type
*howto
)
1233 int bits
= bfd_get_reloc_size(howto
) * 8;
1234 void *address
= ss
->contents
.data
+ offset
;
1235 bfd_vma x
= bfd_get(bits
, ss
->parent
->abfd
, address
);
1236 x
= (x
& ~howto
->dst_mask
) |
1237 ((bfd_vma
)KSPLICE_CANARY
& howto
->dst_mask
);
1238 bfd_put(bits
, ss
->parent
->abfd
, x
, address
);
1241 void write_ksplice_section(struct superbfd
*sbfd
, asymbol
**symp
)
1243 asymbol
*sym
= *symp
;
1244 struct supersect
*ksect_ss
= make_section(sbfd
, ".ksplice_sections");
1245 struct ksplice_section
*ksect
= sect_grow(ksect_ss
, 1,
1246 struct ksplice_section
);
1248 write_ksplice_symbol(ksect_ss
, &ksect
->symbol
, sym
,
1249 mode("keep-primary") ? "(post)" : "");
1250 ksect
->size
= bfd_get_section_size(sym
->section
);
1252 struct supersect
*sym_ss
= fetch_supersect(sbfd
, sym
->section
);
1253 if (sym_ss
->type
== SS_TYPE_RODATA
)
1254 ksect
->flags
|= KSPLICE_SECTION_RODATA
;
1255 if (sym_ss
->type
== SS_TYPE_DATA
)
1256 ksect
->flags
|= KSPLICE_SECTION_DATA
;
1257 if (sym_ss
->type
== SS_TYPE_TEXT
)
1258 ksect
->flags
|= KSPLICE_SECTION_TEXT
;
1259 assert(ksect
->flags
!= 0);
1260 write_reloc(ksect_ss
, &ksect
->address
, symp
, 0);
1263 void write_ksplice_patch(struct superbfd
*sbfd
, const char *sectname
)
1265 struct supersect
*kpatch_ss
= make_section(sbfd
, ".ksplice_patches");
1266 struct ksplice_patch
*kpatch
= sect_grow(kpatch_ss
, 1,
1267 struct ksplice_patch
);
1268 asection
*sect
= bfd_get_section_by_name(sbfd
->abfd
, sectname
);
1269 assert(sect
!= NULL
);
1271 write_string(kpatch_ss
, &kpatch
->label
, "%s",
1272 label_lookup(sbfd
, sect
->symbol
));
1273 write_reloc(kpatch_ss
, &kpatch
->repladdr
, §
->symbol
, 0);
1276 void write_ksplice_deleted_patch(struct superbfd
*sbfd
, const char *name
,
1279 struct supersect
*kpatch_ss
= make_section(sbfd
, ".ksplice_patches");
1280 struct ksplice_patch
*kpatch
= sect_grow(kpatch_ss
, 1,
1281 struct ksplice_patch
);
1283 write_string(kpatch_ss
, &kpatch
->label
, "%s", label
);
1285 for (symp
= sbfd
->syms
.data
; symp
< sbfd
->syms
.data
+ sbfd
->syms
.size
;
1287 asymbol
*sym
= *symp
;
1288 if (bfd_is_und_section(sym
->section
) &&
1289 strcmp(name
, sym
->name
) == 0)
1292 if (symp
>= sbfd
->syms
.data
+ sbfd
->syms
.size
) {
1293 symp
= malloc(sizeof(*symp
));
1294 *symp
= bfd_make_empty_symbol(sbfd
->abfd
);
1295 asymbol
*sym
= *symp
;
1296 sym
->name
= strdup(name
);
1297 sym
->section
= bfd_und_section_ptr
;
1300 *vec_grow(&sbfd
->new_syms
, 1) = symp
;
1302 write_reloc(kpatch_ss
, &kpatch
->repladdr
, symp
, 0);
1305 void write_ksplice_export(struct superbfd
*sbfd
, const char *symname
,
1306 const char *export_type
, bool del
)
1308 struct supersect
*export_ss
= make_section(sbfd
, ".ksplice_exports");
1309 struct ksplice_export
*exp
= sect_grow(export_ss
, 1,
1310 struct ksplice_export
);
1313 write_string(export_ss
, &exp
->name
, "%s", symname
);
1314 write_string(export_ss
, &exp
->new_name
, "DISABLED_%s_%s",
1317 write_string(export_ss
, &exp
->new_name
, "%s", symname
);
1318 write_string(export_ss
, &exp
->name
, "DISABLED_%s_%s", symname
,
1323 struct fixup_entry
{
1328 DECLARE_VEC_TYPE(struct fixup_entry
, fixup_entry_vec
);
1330 int compare_fixups(const void *aptr
, const void *bptr
)
1332 const struct fixup_entry
*a
= aptr
, *b
= bptr
;
1333 if (a
->offset
< b
->offset
)
1335 else if (a
->offset
> b
->offset
)
1338 return (int)a
->used
- (int)b
->used
;
1341 void filter_table_sections(struct superbfd
*isbfd
)
1343 struct supersect
*tables_ss
=
1344 fetch_supersect(offsets_sbfd
,
1345 bfd_get_section_by_name(offsets_sbfd
->abfd
,
1346 ".ksplice_table_sections"));
1347 const struct table_section
*ts
;
1348 for (ts
= tables_ss
->contents
.data
;
1349 (void *)ts
< tables_ss
->contents
.data
+ tables_ss
->contents
.size
;
1351 struct table_section s
= *ts
;
1352 s
.sect
= read_string(tables_ss
, &ts
->sect
);
1353 s
.other_sect
= read_string(tables_ss
, &ts
->other_sect
);
1354 filter_table_section(isbfd
, &s
);
1358 void filter_table_section(struct superbfd
*sbfd
, const struct table_section
*s
)
1360 asection
*isection
= bfd_get_section_by_name(sbfd
->abfd
, s
->sect
);
1361 if (isection
== NULL
)
1363 asection
*fixup_sect
= NULL
;
1364 if (s
->other_sect
!= NULL
)
1365 fixup_sect
= bfd_get_section_by_name(sbfd
->abfd
, s
->other_sect
);
1367 struct supersect
*ss
= fetch_supersect(sbfd
, isection
), orig_ss
;
1368 supersect_move(&orig_ss
, ss
);
1370 struct supersect
*fixup_ss
= NULL
;
1371 if (fixup_sect
!= NULL
)
1372 fixup_ss
= fetch_supersect(sbfd
, fixup_sect
);
1374 struct fixup_entry_vec fixups
;
1378 for (orig_entry
= orig_ss
.contents
.data
;
1379 orig_entry
< orig_ss
.contents
.data
+ orig_ss
.contents
.size
;
1380 orig_entry
+= s
->entry_size
) {
1381 asymbol
*sym
, *fixup_sym
;
1382 read_reloc(&orig_ss
, orig_entry
+ s
->addr_offset
,
1383 sizeof(void *), &sym
);
1385 struct fixup_entry
*f
;
1386 if (fixup_sect
!= NULL
) {
1387 bfd_vma fixup_offset
=
1388 read_reloc(&orig_ss
, orig_entry
+ s
->other_offset
,
1389 sizeof(void *), &fixup_sym
);
1390 if (fixup_sym
->section
== fixup_sect
) {
1391 assert(fixup_offset
< fixup_ss
->contents
.size
);
1392 f
= vec_grow(&fixups
, 1);
1393 f
->offset
= fixup_offset
;
1398 struct supersect
*sym_ss
= fetch_supersect(sbfd
, sym
->section
);
1402 if (fixup_sect
!= NULL
&& fixup_sym
->section
== fixup_sect
) {
1404 f
->ex_offset
= ss
->contents
.size
+ s
->other_offset
;
1406 sect_copy(ss
, sect_do_grow(ss
, 1, s
->entry_size
,
1408 &orig_ss
, orig_entry
, s
->entry_size
);
1411 if (fixup_sect
== NULL
)
1414 struct supersect orig_fixup_ss
;
1415 supersect_move(&orig_fixup_ss
, fixup_ss
);
1417 qsort(fixups
.data
, fixups
.size
, sizeof(*fixups
.data
), compare_fixups
);
1418 *vec_grow(&fixups
, 1) = (struct fixup_entry
)
1419 { .offset
= orig_fixup_ss
.contents
.size
, .used
= false };
1421 struct fixup_entry
*f
;
1422 for (f
= fixups
.data
; f
< fixups
.data
+ fixups
.size
- 1; f
++) {
1425 write_reloc(ss
, ss
->contents
.data
+ f
->ex_offset
,
1426 &fixup_ss
->symbol
, fixup_ss
->contents
.size
);
1428 sect_grow(fixup_ss
, (f
+ 1)->offset
- f
->offset
,
1431 orig_fixup_ss
.contents
.data
+ f
->offset
,
1432 (f
+ 1)->offset
- f
->offset
);
1436 void keep_if_referenced(bfd
*abfd
, asection
*sect
, void *ignored
)
1438 struct superbfd
*sbfd
= fetch_superbfd(abfd
);
1439 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
1440 if (ss
->keep
|| ss
->type
== SS_TYPE_IGNORED
)
1444 for (symp
= sbfd
->syms
.data
;
1445 symp
< sbfd
->syms
.data
+ sbfd
->syms
.size
; symp
++) {
1446 asymbol
*sym
= *symp
;
1447 if (sym
->section
== sect
&& (sym
->flags
& BSF_GLOBAL
) != 0) {
1454 bfd_map_over_sections(abfd
, check_for_ref_to_section
, sect
);
1457 void check_for_ref_to_section(bfd
*abfd
, asection
*looking_at
,
1460 struct superbfd
*sbfd
= fetch_superbfd(abfd
);
1461 struct supersect
*ss
= fetch_supersect(sbfd
, looking_at
);
1462 struct supersect
*for_ss
= fetch_supersect(sbfd
,
1463 (asection
*)looking_for
);
1464 if (!ss
->keep
|| ss
->type
== SS_TYPE_STRING
||
1465 ss
->type
== SS_TYPE_SPECIAL
|| ss
->type
== SS_TYPE_EXPORT
)
1469 for (relocp
= ss
->relocs
.data
;
1470 relocp
< ss
->relocs
.data
+ ss
->relocs
.size
; relocp
++) {
1471 asymbol
*sym
= *(*relocp
)->sym_ptr_ptr
;
1472 if (sym
->section
!= (asection
*)looking_for
)
1474 for_ss
->keep
= true;
1480 void copy_symbols(struct asymbolp_vec
*osyms
, struct asymbolpp_vec
*isyms
)
1483 for (sympp
= isyms
->data
; sympp
< isyms
->data
+ isyms
->size
; sympp
++)
1484 *vec_grow(osyms
, 1) = **sympp
;
1487 /* Modified function from GNU Binutils objcopy.c */
1488 bfd_boolean
copy_object(bfd
*ibfd
, bfd
*obfd
)
1490 assert(bfd_set_format(obfd
, bfd_get_format(ibfd
)));
1492 bfd_vma start
= bfd_get_start_address(ibfd
);
1494 flagword flags
= bfd_get_file_flags(ibfd
);
1495 flags
&= bfd_applicable_file_flags(obfd
);
1497 assert(bfd_set_start_address(obfd
, start
)
1498 && bfd_set_file_flags(obfd
, flags
));
1500 enum bfd_architecture iarch
= bfd_get_arch(ibfd
);
1501 unsigned int imach
= bfd_get_mach(ibfd
);
1502 assert(bfd_set_arch_mach(obfd
, iarch
, imach
));
1503 assert(bfd_set_format(obfd
, bfd_get_format(ibfd
)));
1505 /* BFD mandates that all output sections be created and sizes set before
1506 any output is done. Thus, we traverse all sections multiple times. */
1507 bfd_map_over_sections(ibfd
, setup_section
, obfd
);
1509 struct supersect
*new_supersects
= fetch_superbfd(ibfd
)->new_supersects
;
1510 struct supersect
*ss
;
1511 for (ss
= new_supersects
; ss
!= NULL
; ss
= ss
->next
)
1512 setup_new_section(obfd
, ss
);
1514 /* Mark symbols used in output relocations so that they
1515 are kept, even if they are local labels or static symbols.
1517 Note we iterate over the input sections examining their
1518 relocations since the relocations for the output sections
1519 haven't been set yet. mark_symbols_used_in_relocations will
1520 ignore input sections which have no corresponding output
1523 bfd_map_over_sections(ibfd
, mark_symbols_used_in_relocations
, NULL
);
1524 for (ss
= new_supersects
; ss
!= NULL
; ss
= ss
->next
)
1525 ss_mark_symbols_used_in_relocations(ss
);
1526 struct asymbolp_vec osyms
;
1528 filter_symbols(ibfd
, obfd
, &osyms
, &fetch_superbfd(ibfd
)->syms
);
1529 copy_symbols(&osyms
, &fetch_superbfd(ibfd
)->new_syms
);
1531 bfd_set_symtab(obfd
, osyms
.data
, osyms
.size
);
1533 /* This has to happen after the symbol table has been set. */
1534 bfd_map_over_sections(obfd
, write_section
, NULL
);
1536 /* Allow the BFD backend to copy any private data it understands
1537 from the input BFD to the output BFD. This is done last to
1538 permit the routine to look at the filtered symbol table, which is
1539 important for the ECOFF code at least. */
1540 assert(bfd_copy_private_bfd_data(ibfd
, obfd
));
1545 /* Modified function from GNU Binutils objcopy.c */
1546 void setup_section(bfd
*ibfd
, asection
*isection
, void *obfdarg
)
1548 struct superbfd
*isbfd
= fetch_superbfd(ibfd
);
1549 struct supersect
*ss
= fetch_supersect(isbfd
, isection
);
1550 bfd
*obfd
= obfdarg
;
1556 asection
*osection
= bfd_make_section_anyway(obfd
, isection
->name
);
1557 assert(osection
!= NULL
);
1559 osection
->userdata
= ss
;
1560 bfd_set_section_flags(obfd
, osection
, ss
->flags
);
1561 ss
->symbol
= osection
->symbol
;
1562 assert(bfd_set_section_size(obfd
, osection
, ss
->contents
.size
));
1564 vma
= bfd_section_vma(ibfd
, isection
);
1565 assert(bfd_set_section_vma(obfd
, osection
, vma
));
1567 osection
->lma
= isection
->lma
;
1568 assert(bfd_set_section_alignment(obfd
, osection
, ss
->alignment
));
1569 osection
->entsize
= isection
->entsize
;
1570 osection
->output_section
= osection
;
1571 osection
->output_offset
= 0;
1572 isection
->output_section
= osection
;
1573 isection
->output_offset
= 0;
1577 void setup_new_section(bfd
*obfd
, struct supersect
*ss
)
1579 asection
*osection
= bfd_make_section_anyway(obfd
, ss
->name
);
1580 assert(osection
!= NULL
);
1581 bfd_set_section_flags(obfd
, osection
, ss
->flags
);
1583 osection
->userdata
= ss
;
1584 ss
->symbol
= osection
->symbol
;
1585 assert(bfd_set_section_size(obfd
, osection
, ss
->contents
.size
));
1586 assert(bfd_set_section_vma(obfd
, osection
, 0));
1589 assert(bfd_set_section_alignment(obfd
, osection
, ss
->alignment
));
1590 osection
->entsize
= 0;
1591 osection
->output_section
= osection
;
1592 osection
->output_offset
= 0;
1595 void write_section(bfd
*obfd
, asection
*osection
, void *arg
)
1597 struct supersect
*ss
= osection
->userdata
;
1599 if ((ss
->flags
& SEC_GROUP
) != 0 || ss
->contents
.size
== 0)
1603 char *error_message
;
1604 for (relocp
= ss
->new_relocs
.data
;
1605 relocp
< ss
->new_relocs
.data
+ ss
->new_relocs
.size
; relocp
++) {
1607 if (bfd_get_arch(obfd
) == bfd_arch_arm
)
1608 val
= osection
->use_rela_p
? 0 : (*relocp
)->addend
;
1611 bfd_put(bfd_get_reloc_size((*relocp
)->howto
) * 8, obfd
, val
,
1612 ss
->contents
.data
+ (*relocp
)->address
);
1613 if (bfd_install_relocation(obfd
, *relocp
, ss
->contents
.data
,
1614 0, osection
, &error_message
) !=
1616 fprintf(stderr
, "ksplice: error installing reloc: %s",
1621 memcpy(vec_grow(&ss
->relocs
, ss
->new_relocs
.size
), ss
->new_relocs
.data
,
1622 ss
->new_relocs
.size
* sizeof(*ss
->new_relocs
.data
));
1624 bfd_set_reloc(obfd
, osection
,
1625 ss
->relocs
.size
== 0 ? NULL
: ss
->relocs
.data
,
1628 if (ss
->flags
& SEC_HAS_CONTENTS
)
1629 assert(bfd_set_section_contents
1630 (obfd
, osection
, ss
->contents
.data
, 0,
1631 ss
->contents
.size
));
1634 /* Modified function from GNU Binutils objcopy.c
1636 * Mark all the symbols which will be used in output relocations with
1637 * the BSF_KEEP flag so that those symbols will not be stripped.
1639 * Ignore relocations which will not appear in the output file.
1641 void mark_symbols_used_in_relocations(bfd
*abfd
, asection
*isection
,
1644 struct superbfd
*sbfd
= fetch_superbfd(abfd
);
1645 if (isection
->output_section
== NULL
)
1648 struct supersect
*ss
= fetch_supersect(sbfd
, isection
);
1649 ss_mark_symbols_used_in_relocations(ss
);
1652 void ss_mark_symbols_used_in_relocations(struct supersect
*ss
)
1654 /* Examine each symbol used in a relocation. If it's not one of the
1655 special bfd section symbols, then mark it with BSF_KEEP. */
1657 for (relocp
= ss
->relocs
.data
;
1658 relocp
< ss
->relocs
.data
+ ss
->relocs
.size
; relocp
++) {
1659 asymbol
*sym
= *(*relocp
)->sym_ptr_ptr
;
1660 if (!(bfd_is_const_section(sym
->section
) &&
1661 sym
== sym
->section
->symbol
))
1662 sym
->flags
|= BSF_KEEP
;
1664 for (relocp
= ss
->new_relocs
.data
;
1665 relocp
< ss
->new_relocs
.data
+ ss
->new_relocs
.size
; relocp
++) {
1666 asymbol
*sym
= *(*relocp
)->sym_ptr_ptr
;
1667 if (!(bfd_is_const_section(sym
->section
) &&
1668 sym
== sym
->section
->symbol
))
1669 sym
->flags
|= BSF_KEEP
;
1673 static bool deleted_table_section_symbol(bfd
*abfd
, asymbol
*sym
)
1675 struct superbfd
*sbfd
= fetch_superbfd(abfd
);
1676 if (bfd_is_const_section(sym
->section
))
1678 struct supersect
*ss
= fetch_supersect(sbfd
, sym
->section
);
1681 for (symp
= ss
->syms
.data
; symp
< ss
->syms
.data
+ ss
->syms
.size
; symp
++) {
1685 return symp
>= ss
->syms
.data
+ ss
->syms
.size
;
1688 /* Modified function from GNU Binutils objcopy.c
1690 * Choose which symbol entries to copy.
1691 * We don't copy in place, because that confuses the relocs.
1692 * Return the number of symbols to print.
1694 void filter_symbols(bfd
*ibfd
, bfd
*obfd
, struct asymbolp_vec
*osyms
,
1695 struct asymbolp_vec
*isyms
)
1698 struct superbfd
*sbfd
= fetch_superbfd(ibfd
);
1699 for (symp
= isyms
->data
; symp
< isyms
->data
+ isyms
->size
; symp
++) {
1700 asymbol
*sym
= *symp
;
1701 struct supersect
*sym_ss
= NULL
;
1702 if (!bfd_is_const_section(sym
->section
))
1703 sym_ss
= fetch_supersect(sbfd
, sym
->section
);
1707 if (mode("keep") && (sym
->flags
& BSF_GLOBAL
) != 0 &&
1708 !(mode("keep-primary") && sym_ss
!= NULL
&& sym_ss
->new))
1709 sym
->flags
= (sym
->flags
& ~BSF_GLOBAL
) | BSF_LOCAL
;
1711 if (mode("finalize") && (sym
->flags
& BSF_GLOBAL
) != 0)
1712 sym
->flags
= (sym
->flags
& ~BSF_GLOBAL
) | BSF_LOCAL
;
1714 if ((sym
->flags
& BSF_KEEP
) != 0 /* Used in relocation. */
1715 || ((sym
->flags
& BSF_SECTION_SYM
) != 0 && sym_ss
!= NULL
&&
1718 else if ((sym
->flags
& (BSF_GLOBAL
| BSF_WEAK
)) != 0 &&
1719 sym_ss
!= NULL
&& sym_ss
->keep
)
1721 else if (mode("keep-primary") &&
1722 starts_with(sym
->section
->name
, "__ksymtab"))
1725 if (deleted_table_section_symbol(ibfd
, sym
))
1728 if (bfd_is_com_section(sym
->section
))
1732 keep
= !str_in_set(sym
->name
, &rmsyms
);
1735 assert(sym_ss
== NULL
|| sym_ss
->keep
);
1736 *vec_grow(osyms
, 1) = sym
;
1741 void read_str_set(struct str_vec
*strs
)
1745 assert(getline(&buf
, &n
, stdin
) >= 0);
1749 char *str
= strtok_r(buf
, " \n", &saveptr
);
1753 *vec_grow(strs
, 1) = str
;
1757 bool str_in_set(const char *str
, const struct str_vec
*strs
)
1760 for (strp
= strs
->data
; strp
< strs
->data
+ strs
->size
; strp
++) {
1761 if (strcmp(str
, *strp
) == 0)
1767 bool is_table_section(const char *name
, bool consider_other
)
1769 struct supersect
*tables_ss
=
1770 fetch_supersect(offsets_sbfd
,
1771 bfd_get_section_by_name(offsets_sbfd
->abfd
,
1772 ".ksplice_table_sections"));
1773 const struct table_section
*ts
;
1774 for (ts
= tables_ss
->contents
.data
;
1775 (void *)ts
< tables_ss
->contents
.data
+ tables_ss
->contents
.size
;
1777 if (strcmp(name
, read_string(tables_ss
, &ts
->sect
)) == 0)
1779 const char *osect_name
= read_string(tables_ss
,
1781 if (consider_other
&& osect_name
!= NULL
&&
1782 strcmp(name
, osect_name
) == 0)
1788 enum supersect_type
supersect_type(struct supersect
*ss
)
1790 if (starts_with(ss
->name
, ".ksplice"))
1791 return SS_TYPE_KSPLICE
;
1793 if (starts_with(ss
->name
, ".init"))
1794 return SS_TYPE_IGNORED
;
1795 if (starts_with(ss
->name
, ".security_initcall.init"))
1796 return SS_TYPE_IGNORED
;
1797 if (starts_with(ss
->name
, ".con_initcall.init"))
1798 return SS_TYPE_IGNORED
;
1799 if (starts_with(ss
->name
, ".x86cpuvendor.init"))
1800 return SS_TYPE_IGNORED
;
1801 if (starts_with(ss
->name
, ".early_param.init"))
1802 return SS_TYPE_IGNORED
;
1803 if (starts_with(ss
->name
, ".taglist.init"))
1804 return SS_TYPE_IGNORED
;
1805 if (starts_with(ss
->name
, ".arch.info.init"))
1806 return SS_TYPE_IGNORED
;
1807 if (starts_with(ss
->name
, ".proc.info.init"))
1808 return SS_TYPE_IGNORED
;
1809 /* .pci_fixup_* sections really should be treated as global rodata
1810 referenced only from quirks.c */
1811 if (starts_with(ss
->name
, ".pci_fixup_"))
1812 return SS_TYPE_IGNORED
;
1813 /* .builtin_fw sections are similar to .pci_fixup */
1814 if (starts_with(ss
->name
, ".builtin_fw"))
1815 return SS_TYPE_IGNORED
;
1816 /* same for .tracedata */
1817 if (starts_with(ss
->name
, ".tracedata"))
1818 return SS_TYPE_IGNORED
;
1819 if (starts_with(ss
->name
, ".debug"))
1820 return SS_TYPE_IGNORED
;
1821 /* .eh_frame should probably be discarded, not ignored */
1822 if (starts_with(ss
->name
, ".eh_frame"))
1823 return SS_TYPE_IGNORED
;
1824 if (config
->ignore_devinit
&& starts_with(ss
->name
, ".devinit"))
1825 return SS_TYPE_IGNORED
;
1826 if (config
->ignore_meminit
&& starts_with(ss
->name
, ".meminit"))
1827 return SS_TYPE_IGNORED
;
1828 if (config
->ignore_cpuinit
&& starts_with(ss
->name
, ".cpuinit"))
1829 return SS_TYPE_IGNORED
;
1830 if (config
->ignore_devinit
&& starts_with(ss
->name
, ".devexit"))
1831 return SS_TYPE_IGNORED
;
1832 if (config
->ignore_meminit
&& starts_with(ss
->name
, ".memexit"))
1833 return SS_TYPE_IGNORED
;
1834 if (config
->ignore_cpuinit
&& starts_with(ss
->name
, ".cpuexit"))
1835 return SS_TYPE_IGNORED
;
1836 if (starts_with(ss
->name
, ".vgetcpu_mode") ||
1837 starts_with(ss
->name
, ".jiffies") ||
1838 starts_with(ss
->name
, ".wall_jiffies") ||
1839 starts_with(ss
->name
, ".vxtime") ||
1840 starts_with(ss
->name
, ".sys_tz") ||
1841 starts_with(ss
->name
, ".sysctl_vsyscall") ||
1842 starts_with(ss
->name
, ".xtime") ||
1843 starts_with(ss
->name
, ".xtime_lock") ||
1844 starts_with(ss
->name
, ".vsyscall"))
1845 return SS_TYPE_IGNORED
;
1846 if (starts_with(ss
->name
, ".vdso"))
1847 return SS_TYPE_IGNORED
;
1849 if (bfd_get_section_by_name(ss
->parent
->abfd
, ".exitcall.exit") == NULL
) {
1850 if (starts_with(ss
->name
, ".exit.text"))
1851 return SS_TYPE_TEXT
;
1852 if (starts_with(ss
->name
, ".exit.data"))
1853 return SS_TYPE_DATA
;
1854 } else if (starts_with(ss
->name
, ".exit.text") ||
1855 starts_with(ss
->name
, ".exit.data"))
1856 return SS_TYPE_IGNORED
;
1858 if (starts_with(ss
->name
, ".text") ||
1859 starts_with(ss
->name
, ".kernel.text") ||
1860 starts_with(ss
->name
, ".devinit.text") ||
1861 starts_with(ss
->name
, ".meminit.text") ||
1862 starts_with(ss
->name
, ".cpuinit.text") ||
1863 starts_with(ss
->name
, ".devexit.text") ||
1864 starts_with(ss
->name
, ".memexit.text") ||
1865 starts_with(ss
->name
, ".cpuexit.text") ||
1866 starts_with(ss
->name
, ".ref.text") ||
1867 starts_with(ss
->name
, ".spinlock.text") ||
1868 starts_with(ss
->name
, ".kprobes.text") ||
1869 starts_with(ss
->name
, ".sched.text"))
1870 return SS_TYPE_TEXT
;
1873 if (sscanf(ss
->name
, ".rodata.str%*u.%*u%n", &n
) >= 0 &&
1874 n
== strlen(ss
->name
))
1875 return SS_TYPE_STRING
;
1877 if (starts_with(ss
->name
, ".rodata") ||
1878 starts_with(ss
->name
, ".kernel.rodata") ||
1879 starts_with(ss
->name
, ".devinit.rodata") ||
1880 starts_with(ss
->name
, ".meminit.rodata") ||
1881 starts_with(ss
->name
, ".cpuinit.rodata") ||
1882 starts_with(ss
->name
, ".devexit.rodata") ||
1883 starts_with(ss
->name
, ".memexit.rodata") ||
1884 starts_with(ss
->name
, ".cpuexit.rodata") ||
1885 starts_with(ss
->name
, ".ref.rodata") ||
1886 starts_with(ss
->name
, "__markers_strings"))
1887 return SS_TYPE_RODATA
;
1889 if (starts_with(ss
->name
, ".bss"))
1890 return SS_TYPE_DATA
;
1892 /* Ignore .data.percpu sections */
1893 if (starts_with(ss
->name
, ".data.percpu") ||
1894 starts_with(ss
->name
, ".kernel.data.percpu"))
1895 return SS_TYPE_IGNORED
;
1896 if (starts_with(ss
->name
, ".data") ||
1897 starts_with(ss
->name
, ".kernel.data") ||
1898 starts_with(ss
->name
, ".devinit.data") ||
1899 starts_with(ss
->name
, ".cpuinit.data") ||
1900 starts_with(ss
->name
, ".meminit.data") ||
1901 starts_with(ss
->name
, ".devexit.data") ||
1902 starts_with(ss
->name
, ".memexit.data") ||
1903 starts_with(ss
->name
, ".cpuexit.data") ||
1904 starts_with(ss
->name
, ".ref.data") ||
1905 starts_with(ss
->name
, "__markers"))
1906 return SS_TYPE_DATA
;
1908 if (starts_with(ss
->name
, "__ksymtab"))
1909 return SS_TYPE_EXPORT
;
1910 if (starts_with(ss
->name
, "__kcrctab"))
1911 return SS_TYPE_EXPORT
;
1913 if (is_table_section(ss
->name
, true))
1914 return SS_TYPE_SPECIAL
;
1916 if (starts_with(ss
->name
, ".ARM."))
1917 return SS_TYPE_SPECIAL
;
1919 if (starts_with(ss
->name
, ".note"))
1920 return SS_TYPE_IGNORED
;
1921 if (starts_with(ss
->name
, ".comment"))
1922 return SS_TYPE_IGNORED
;
1923 if (starts_with(ss
->name
, "__param"))
1924 return SS_TYPE_IGNORED
;
1925 if (starts_with(ss
->name
, ".exitcall.exit"))
1926 return SS_TYPE_IGNORED
;
1927 if (starts_with(ss
->name
, ".modinfo"))
1928 return SS_TYPE_IGNORED
;
1930 return SS_TYPE_UNKNOWN
;
1933 void initialize_supersect_types(struct superbfd
*sbfd
)
1936 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
1937 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
1938 ss
->type
= supersect_type(ss
);
1939 if (ss
->type
== SS_TYPE_UNKNOWN
) {
1940 fprintf(stderr
, "Unknown section type: %s\n", ss
->name
);