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 KSPLICE_SYMBOL_STR "KSPLICE_SYMBOL_"
64 #define symbol_init(sym) *(sym) = (asymbol *)NULL
65 DEFINE_HASH_TYPE(asymbol
*, symbol_hash
, symbol_hash_init
, symbol_hash_free
,
66 symbol_hash_lookup
, symbol_init
);
72 DECLARE_VEC_TYPE(struct export
, export_vec
);
74 DECLARE_VEC_TYPE(const char *, str_vec
);
77 const char *export_type
;
80 struct supersect
*sym_ss
;
81 struct supersect
*crc_ss
;
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
, bool deletion
);
101 struct export_desc
*new_export_desc(struct supersect
*ss
, bool deletion
);
102 bool relocs_equal(struct supersect
*old_src_ss
, struct supersect
*new_src_ss
,
103 arelent
*old_reloc
, arelent
*new_reloc
);
104 bool all_relocs_equal(struct supersect
*old_ss
, struct supersect
*new_ss
);
105 bfd_vma
non_dst_mask(struct supersect
*ss
, arelent
*reloc
);
106 static bool part_of_reloc(struct supersect
*ss
, unsigned long addr
);
107 static bool nonrelocs_equal(struct supersect
*old_ss
, struct supersect
*new_ss
);
108 static void handle_section_symbol_renames(struct superbfd
*oldsbfd
,
109 struct superbfd
*newsbfd
);
111 enum supersect_type
supersect_type(struct supersect
*ss
);
112 void initialize_supersect_types(struct superbfd
*sbfd
);
113 static void initialize_spans(struct superbfd
*sbfd
);
114 static void initialize_string_spans(struct supersect
*ss
);
115 struct span
*reloc_target_span(struct supersect
*ss
, arelent
*reloc
);
116 struct span
*reloc_address_span(struct supersect
*ss
, arelent
*reloc
);
117 void remove_unkept_spans(struct superbfd
*sbfd
);
118 void compute_span_shifts(struct superbfd
*sbfd
);
119 static struct span
*new_span(struct supersect
*ss
, bfd_vma start
, bfd_vma size
);
120 bool is_table_section(const char *name
, bool consider_other
);
122 void rm_relocs(struct superbfd
*isbfd
);
123 void rm_some_relocs(struct supersect
*ss
);
124 void write_ksplice_reloc(struct supersect
*ss
, arelent
*orig_reloc
);
125 void load_ksplice_symbol_offsets(struct superbfd
*sbfd
);
126 void blot_section(struct supersect
*ss
, int offset
, reloc_howto_type
*howto
);
127 static void write_ksplice_section(struct span
*span
);
128 void write_ksplice_patch(struct superbfd
*sbfd
, const char *sectname
);
129 void write_ksplice_deleted_patch(struct superbfd
*sbfd
, const char *name
,
131 asymbol
**make_undefined_symbolp(struct superbfd
*sbfd
, const char *name
);
132 void filter_table_sections(struct superbfd
*isbfd
);
133 void filter_table_section(struct superbfd
*sbfd
, const struct table_section
*s
);
134 void keep_referenced_sections(struct superbfd
*sbfd
);
135 bfd_boolean
copy_object(bfd
*ibfd
, bfd
*obfd
);
136 void setup_section(bfd
*ibfd
, asection
*isection
, void *obfdarg
);
137 static void setup_new_section(bfd
*obfd
, struct supersect
*ss
);
138 static void write_section(bfd
*obfd
, asection
*osection
, void *arg
);
139 static void delete_obsolete_relocs(struct supersect
*ss
);
140 void mark_symbols_used_in_relocations(bfd
*abfd
, asection
*isection
,
142 static void ss_mark_symbols_used_in_relocations(struct supersect
*ss
);
143 void filter_symbols(bfd
*ibfd
, bfd
*obfd
, struct asymbolp_vec
*osyms
,
144 struct asymbolp_vec
*isyms
);
145 static bool deleted_table_section_symbol(bfd
*abfd
, asymbol
*sym
);
146 void read_str_set(struct str_vec
*strs
);
147 bool str_in_set(const char *str
, const struct str_vec
*strs
);
148 struct supersect
*make_section(struct superbfd
*sbfd
, const char *name
);
149 void __attribute__((format(printf
, 3, 4)))
150 write_string(struct supersect
*ss
, const char **addr
, const char *fmt
, ...);
151 void rm_some_exports(struct superbfd
*isbfd
, const struct export_desc
*ed
);
152 void write_ksplice_export(struct superbfd
*sbfd
, const char *symname
,
153 const char *export_type
, bool del
);
154 void write_reloc(struct supersect
*ss
, const void *addr
, asymbol
**symp
,
156 arelent
*create_reloc(struct supersect
*ss
, const void *addr
, asymbol
**symp
,
158 static void foreach_symbol_pair(struct superbfd
*oldsbfd
, struct superbfd
*newsbfd
,
159 void (*fn
)(struct supersect
*oldss
,
161 struct supersect
*newss
,
163 static void check_global_symbols(struct supersect
*oldss
, asymbol
*oldsym
,
164 struct supersect
*newss
, asymbol
*newsym
);
165 static void match_global_symbols(struct supersect
*oldss
, asymbol
*oldsym
,
166 struct supersect
*newss
, asymbol
*newsym
);
168 static void match_sections_by_name(struct superbfd
*oldsbfd
,
169 struct superbfd
*newsbfd
);
170 static void match_sections_by_label(struct superbfd
*oldsbfd
,
171 struct superbfd
*newsbfd
);
172 static void mark_new_sections(struct superbfd
*sbfd
);
173 static void handle_deleted_sections(struct superbfd
*oldsbfd
,
174 struct superbfd
*newsbfd
);
175 static void compare_matched_sections(struct superbfd
*sbfd
);
176 static void update_nonzero_offsets(struct superbfd
*sbfd
);
177 static void handle_nonzero_offset_relocs(struct supersect
*ss
);
179 static const char *label_lookup(struct superbfd
*sbfd
, asymbol
*sym
);
180 static void print_label_map(struct superbfd
*sbfd
);
181 static void label_map_set(struct superbfd
*sbfd
, const char *oldlabel
,
183 static void init_label_map(struct superbfd
*sbfd
);
184 static asymbol
**symbolp_scan(struct supersect
*ss
, bfd_vma value
);
185 static void init_csyms(struct superbfd
*sbfd
);
186 static void init_callers(struct superbfd
*sbfd
);
187 static asymbol
*canonical_symbol(struct superbfd
*sbfd
, asymbol
*sym
);
188 static asymbol
**canonical_symbolp(struct superbfd
*sbfd
, asymbol
*sym
);
189 static char *static_local_symbol(struct superbfd
*sbfd
, asymbol
*sym
);
190 static char *symbol_label(struct superbfd
*sbfd
, asymbol
*sym
);
193 #define debug_(sbfd, level, fmt, ...) \
195 if (verbose >= (level)) \
196 printf("%s: " fmt, (sbfd)->abfd->filename, \
199 #define debug0(sbfd, fmt, ...) debug_(sbfd, 0, fmt, ## __VA_ARGS__)
200 #define debug1(sbfd, fmt, ...) debug_(sbfd, 1, fmt, ## __VA_ARGS__)
201 #define err(sbfd, fmt, ...) \
203 fprintf(stderr, "%s: " fmt, (sbfd)->abfd->filename, \
207 struct str_vec delsects
, rmsyms
;
208 struct export_desc_vec exports
;
211 struct ksplice_config
*config
;
213 const char *modestr
, *kid
;
215 struct superbfd
*offsets_sbfd
= NULL
;
217 #define mode(str) starts_with(modestr, str)
219 DECLARE_VEC_TYPE(unsigned long, addr_vec
);
220 DEFINE_HASH_TYPE(struct addr_vec
, addr_vec_hash
,
221 addr_vec_hash_init
, addr_vec_hash_free
, addr_vec_hash_lookup
,
223 struct addr_vec_hash system_map
;
225 struct bool_hash system_map_written
;
226 struct ulong_hash ksplice_symbol_offset
;
227 struct ulong_hash ksplice_string_offset
;
229 void load_system_map()
231 const char *config_dir
= getenv("KSPLICE_CONFIG_DIR");
234 assert(asprintf(&file
, "%s/System.map", config_dir
) >= 0);
235 FILE *fp
= fopen(file
, "r");
237 addr_vec_hash_init(&system_map
);
241 while (fscanf(fp
, "%lx %c %as\n", &addr
, &type
, &sym
) == 3)
242 *vec_grow(addr_vec_hash_lookup(&system_map
, sym
, TRUE
),
247 void load_ksplice_symbol_offsets(struct superbfd
*sbfd
)
249 asection
*sect
= bfd_get_section_by_name(sbfd
->abfd
,
253 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
255 struct ksplice_symbol
*ksym
;
256 for (ksym
= ss
->contents
.data
;
257 (void *)ksym
< ss
->contents
.data
+ ss
->contents
.size
; ksym
++) {
258 const char *label
= read_string(ss
, &ksym
->label
);
259 unsigned long *ksymbol_offp
=
260 ulong_hash_lookup(&ksplice_symbol_offset
, label
, TRUE
);
261 *ksymbol_offp
= addr_offset(ss
, ksym
);
267 char *kmodsrc
= getenv("KSPLICE_KMODSRC"), *offsets_file
;
268 assert(kmodsrc
!= NULL
);
269 assert(asprintf(&offsets_file
, "%s/offsets.o", kmodsrc
) >= 0);
270 bfd
*offsets_bfd
= bfd_openr(offsets_file
, NULL
);
271 assert(offsets_bfd
!= NULL
);
273 assert(bfd_check_format_matches(offsets_bfd
, bfd_object
, &matching
));
274 offsets_sbfd
= fetch_superbfd(offsets_bfd
);
276 asection
*config_sect
= bfd_get_section_by_name(offsets_sbfd
->abfd
,
278 struct supersect
*config_ss
=
279 fetch_supersect(offsets_sbfd
, config_sect
);
281 config
= config_ss
->contents
.data
;
284 bool matchable_data_section(struct supersect
*ss
)
286 if (ss
->type
== SS_TYPE_STRING
)
288 if (ss
->type
== SS_TYPE_RODATA
)
290 if (ss
->type
== SS_TYPE_DATA
&& ss
->relocs
.size
!= 0)
295 bool unchangeable_section(struct supersect
*ss
)
297 if (ss
->type
== SS_TYPE_DATA
)
299 if (ss
->type
== SS_TYPE_IGNORED
&& !starts_with(ss
->name
, ".debug") &&
300 strcmp(ss
->name
, "__ksymtab_strings") != 0)
305 int main(int argc
, char *argv
[])
307 if (getenv("KSPLICE_VERBOSE") != NULL
)
308 verbose
= atoi(getenv("KSPLICE_VERBOSE"));
311 bfd
*ibfd
= bfd_openr(argv
[1], NULL
);
315 assert(bfd_check_format_matches(ibfd
, bfd_object
, &matching
));
317 const char *output_target
= bfd_get_target(ibfd
);
318 bfd
*obfd
= bfd_openw(argv
[2], output_target
);
321 struct superbfd
*isbfd
= fetch_superbfd(ibfd
);
322 init_label_map(isbfd
);
324 bool_hash_init(&system_map_written
);
325 ulong_hash_init(&ksplice_symbol_offset
);
326 ulong_hash_init(&ksplice_string_offset
);
329 if (mode("keep-primary")) {
331 do_keep_primary(isbfd
, argv
[4]);
332 } else if (mode("keep-helper")) {
333 do_keep_helper(isbfd
);
334 } else if (mode("finalize")) {
336 } else if (mode("rmsyms")) {
340 copy_object(ibfd
, obfd
);
342 if (offsets_sbfd
!= NULL
)
343 assert(bfd_close(offsets_sbfd
->abfd
));
344 assert(bfd_close(obfd
));
345 assert(bfd_close(ibfd
));
349 void do_keep_primary(struct superbfd
*isbfd
, const char *pre
)
351 struct bfd
*prebfd
= bfd_openr(pre
, NULL
);
352 assert(prebfd
!= NULL
);
354 assert(bfd_check_format_matches(prebfd
, bfd_object
, &matching
));
356 struct superbfd
*presbfd
= fetch_superbfd(prebfd
);
357 init_label_map(presbfd
);
360 initialize_supersect_types(isbfd
);
361 initialize_supersect_types(presbfd
);
363 foreach_symbol_pair(presbfd
, isbfd
, match_global_symbols
);
364 debug1(isbfd
, "Matched global\n");
365 match_sections_by_name(presbfd
, isbfd
);
366 debug1(isbfd
, "Matched by name\n");
367 match_sections_by_label(presbfd
, isbfd
);
368 debug1(isbfd
, "Matched by label\n");
372 compare_matched_sections(isbfd
);
373 update_nonzero_offsets(isbfd
);
374 mark_new_sections(isbfd
);
378 foreach_symbol_pair(presbfd
, isbfd
, check_global_symbols
);
380 handle_deleted_sections(presbfd
, isbfd
);
381 handle_section_symbol_renames(presbfd
, isbfd
);
384 compare_exported_symbols(presbfd
, isbfd
, false);
385 compare_exported_symbols(isbfd
, presbfd
, true);
387 initialize_spans(isbfd
);
388 initialize_spans(presbfd
);
390 for (sect
= isbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
391 struct supersect
*ss
= fetch_supersect(isbfd
, sect
);
392 if (ss
->type
!= SS_TYPE_STRING
)
394 asection
*oldsect
= bfd_get_section_by_name(prebfd
, sect
->name
);
397 struct supersect
*old_ss
= fetch_supersect(presbfd
, oldsect
);
398 struct span
*span
, *old_span
;
399 for (span
= ss
->spans
.data
;
400 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++) {
402 for (old_span
= old_ss
->spans
.data
;
403 old_span
< old_ss
->spans
.data
+ old_ss
->spans
.size
;
405 if (strcmp((char *)ss
->contents
.data
+
407 (char *)old_ss
->contents
.data
+
408 old_span
->start
) == 0) {
411 span
->label
= old_span
->label
;
417 assert(bfd_close(prebfd
));
419 for (sect
= isbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
420 struct supersect
*ss
= fetch_supersect(isbfd
, sect
);
422 if (ss
->type
== SS_TYPE_STRING
|| ss
->type
== SS_TYPE_SPECIAL
||
423 ss
->type
== SS_TYPE_EXPORT
)
425 if (ss
->new || ss
->patch
)
429 print_label_map(isbfd
);
431 for (sect
= isbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
432 struct supersect
*ss
= fetch_supersect(isbfd
, sect
);
434 debug0(isbfd
, "Patching section: %s\n", sect
->name
);
437 for (sect
= isbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
438 struct supersect
*ss
= fetch_supersect(isbfd
, sect
);
440 debug0(isbfd
, "New section: %s\n", sect
->name
);
443 const char **sectname
;
444 for (sectname
= delsects
.data
;
445 sectname
< delsects
.data
+ delsects
.size
; sectname
++)
446 debug0(isbfd
, "Deleted section: %s\n", *sectname
);
448 const struct export_desc
*ed
;
449 for (ed
= exports
.data
; ed
< exports
.data
+ exports
.size
; ed
++) {
450 const char **symname
;
451 for (symname
= ed
->names
.data
;
452 symname
< ed
->names
.data
+ ed
->names
.size
; symname
++)
453 debug0(isbfd
, "Export %s (%s): %s\n",
454 ed
->deletion
? "deletion" : "addition",
455 ed
->export_type
, *symname
);
459 for (sect
= isbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
460 struct supersect
*ss
= fetch_supersect(isbfd
, sect
);
461 for (span
= ss
->spans
.data
;
462 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++)
463 span
->keep
= ss
->keep
;
466 filter_table_sections(isbfd
);
467 for (ed
= exports
.data
; ed
< exports
.data
+ exports
.size
; ed
++) {
468 const char **symname
;
469 for (symname
= ed
->names
.data
;
470 symname
< ed
->names
.data
+ ed
->names
.size
; symname
++)
471 write_ksplice_export(isbfd
, *symname
,
472 ed
->export_type
, ed
->deletion
);
474 rm_some_exports(isbfd
, ed
);
477 compute_span_shifts(isbfd
);
479 for (sect
= isbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
480 struct supersect
*ss
= fetch_supersect(isbfd
, sect
);
481 if (!ss
->patch
&& !ss
->new)
485 for (span
= ss
->spans
.data
;
486 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++)
487 write_ksplice_section(span
);
490 write_ksplice_patch(isbfd
, sect
->name
);
494 remove_unkept_spans(isbfd
);
497 void do_keep_helper(struct superbfd
*isbfd
)
501 initialize_supersect_types(isbfd
);
502 initialize_spans(isbfd
);
505 for (sect
= isbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
506 struct supersect
*ss
= fetch_supersect(isbfd
, sect
);
508 if (ss
->type
== SS_TYPE_SPECIAL
|| ss
->type
== SS_TYPE_TEXT
)
513 for (symp
= isbfd
->syms
.data
;
514 symp
< isbfd
->syms
.data
+ isbfd
->syms
.size
; symp
++) {
515 asymbol
*sym
= *symp
;
516 if (!bfd_is_const_section(sym
->section
) &&
517 (sym
->flags
& BSF_GLOBAL
) != 0) {
518 struct supersect
*sym_ss
=
519 fetch_supersect(isbfd
, sym
->section
);
520 if (sym_ss
->type
!= SS_TYPE_IGNORED
)
526 for (sect
= isbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
527 struct supersect
*ss
= fetch_supersect(isbfd
, sect
);
528 for (span
= ss
->spans
.data
;
529 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++)
530 span
->keep
= ss
->keep
;
535 keep_referenced_sections(isbfd
);
538 filter_table_sections(isbfd
);
539 compute_span_shifts(isbfd
);
541 for (sect
= isbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
542 struct supersect
*ss
= fetch_supersect(isbfd
, sect
);
543 asymbol
*sym
= canonical_symbol(isbfd
, sect
->symbol
);
546 if ((sym
->flags
& BSF_WEAK
) != 0)
548 if (bfd_get_section_size(sect
) == 0)
552 if (ss
->type
!= SS_TYPE_TEXT
&& !matchable_data_section(ss
))
556 for (span
= ss
->spans
.data
;
557 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++) {
559 write_ksplice_section(span
);
564 remove_unkept_spans(isbfd
);
567 void do_finalize(struct superbfd
*isbfd
)
570 load_ksplice_symbol_offsets(isbfd
);
572 initialize_supersect_types(isbfd
);
573 initialize_spans(isbfd
);
577 void do_rmsyms(struct superbfd
*isbfd
)
579 read_str_set(&rmsyms
);
582 initialize_supersect_types(isbfd
);
583 initialize_spans(isbfd
);
587 struct export_vec
*get_export_syms(struct superbfd
*sbfd
)
590 struct export_vec
*exports
;
591 exports
= malloc(sizeof(*exports
));
592 assert(exports
!= NULL
);
595 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
596 if (!starts_with(sect
->name
, "__ksymtab") ||
597 ends_with(sect
->name
, "_strings"))
599 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
600 struct kernel_symbol
*sym
;
601 assert(ss
->contents
.size
* 2 == ss
->relocs
.size
*
602 sizeof(struct kernel_symbol
));
603 for (sym
= ss
->contents
.data
;
604 (void *)sym
< ss
->contents
.data
+ ss
->contents
.size
;
606 struct export
*exp
= vec_grow(exports
, 1);
608 read_string(ss
, (const char *const *)&sym
->name
);
615 struct export_desc
*new_export_desc(struct supersect
*ss
, bool deletion
)
617 struct export_desc
*ed
= vec_grow(&exports
, 1);
618 ed
->deletion
= deletion
;
619 vec_init(&ed
->names
);
620 ed
->export_type
= strdup(ss
->name
) + strlen("__ksymtab");
623 assert(asprintf(&crc_sect_name
, "__kcrctab%s", ed
->export_type
) >= 0);
625 bfd_get_section_by_name(ss
->parent
->abfd
, crc_sect_name
);
626 if (crc_sect
== NULL
)
629 ed
->crc_ss
= fetch_supersect(ss
->parent
, crc_sect
);
633 void compare_exported_symbols(struct superbfd
*oldsbfd
,
634 struct superbfd
*newsbfd
, bool deletion
)
636 struct export_vec
*new_exports
, *old_exports
;
637 new_exports
= get_export_syms(newsbfd
);
638 if (new_exports
== NULL
)
640 old_exports
= get_export_syms(oldsbfd
);
641 struct export
*old
, *new;
642 struct supersect
*last_ss
= NULL
;
643 struct export_desc
*ed
= NULL
;
644 for (new = new_exports
->data
; new < new_exports
->data
+
645 new_exports
->size
; new++) {
647 if (old_exports
!= NULL
) {
648 for (old
= old_exports
->data
; old
< old_exports
->data
+
649 old_exports
->size
; old
++) {
650 if (strcmp(new->name
, old
->name
) == 0 &&
651 strcmp(new->ss
->name
, old
->ss
->name
) == 0) {
657 if (last_ss
!= new->ss
) {
659 ed
= new_export_desc(new->ss
, deletion
);
662 *vec_grow(&ed
->names
, 1) = new->name
;
666 void match_sections(struct supersect
*oldss
, struct supersect
*newss
)
668 if (oldss
->match
== newss
&& newss
->match
== oldss
)
670 if (oldss
->match
!= NULL
) {
671 err(newss
->parent
, "Matching conflict: old %s: %s != %s\n",
672 oldss
->name
, oldss
->match
->name
, newss
->name
);
675 if (newss
->match
!= NULL
) {
676 err(newss
->parent
, "Matching conflict: new %s: %s != %s\n",
677 newss
->name
, newss
->match
->name
, oldss
->name
);
680 oldss
->match
= newss
;
681 newss
->match
= oldss
;
682 debug1(newss
->parent
, "Matched old %s to new %s\n",
683 oldss
->name
, newss
->name
);
686 static void match_global_symbols(struct supersect
*oldss
, asymbol
*oldsym
,
687 struct supersect
*newss
, asymbol
*newsym
)
689 if ((oldsym
->flags
& BSF_GLOBAL
) == 0 ||
690 (newsym
->flags
& BSF_GLOBAL
) == 0)
692 match_sections(oldss
, newss
);
695 static void check_global_symbols(struct supersect
*oldss
, asymbol
*oldsym
,
696 struct supersect
*newss
, asymbol
*newsym
)
698 if ((oldsym
->flags
& BSF_GLOBAL
) == 0 ||
699 (newsym
->flags
& BSF_GLOBAL
) == 0)
701 if (oldss
->type
== SS_TYPE_IGNORED
)
703 if (oldss
->match
!= newss
|| newss
->match
!= oldss
) {
704 err(newss
->parent
, "Global symbol section mismatch: %s %s/%s\n",
705 oldsym
->name
, oldss
->name
, newss
->name
);
710 static void foreach_symbol_pair(struct superbfd
*oldsbfd
, struct superbfd
*newsbfd
,
711 void (*fn
)(struct supersect
*oldss
,
713 struct supersect
*newss
,
716 asymbol
**oldsymp
, **newsymp
;
717 for (oldsymp
= oldsbfd
->syms
.data
;
718 oldsymp
< oldsbfd
->syms
.data
+ oldsbfd
->syms
.size
; oldsymp
++) {
719 asymbol
*oldsym
= *oldsymp
;
720 if (bfd_is_const_section(oldsym
->section
))
722 for (newsymp
= newsbfd
->syms
.data
;
723 newsymp
< newsbfd
->syms
.data
+ newsbfd
->syms
.size
;
725 asymbol
*newsym
= *newsymp
;
726 if (bfd_is_const_section(newsym
->section
))
728 if (strcmp(oldsym
->name
, newsym
->name
) != 0)
730 struct supersect
*oldss
=
731 fetch_supersect(oldsbfd
, oldsym
->section
);
732 struct supersect
*newss
=
733 fetch_supersect(newsbfd
, newsym
->section
);
734 fn(oldss
, oldsym
, newss
, newsym
);
739 static void match_sections_by_name(struct superbfd
*oldsbfd
,
740 struct superbfd
*newsbfd
)
742 asection
*newp
, *oldp
;
743 for (newp
= newsbfd
->abfd
->sections
; newp
!= NULL
; newp
= newp
->next
) {
744 struct supersect
*newss
= fetch_supersect(newsbfd
, newp
);
745 oldp
= bfd_get_section_by_name(oldsbfd
->abfd
, newp
->name
);
746 if (oldp
== NULL
|| newss
->type
== SS_TYPE_STRING
||
747 newss
->type
== SS_TYPE_SPECIAL
||
748 newss
->type
== SS_TYPE_EXPORT
)
750 if (static_local_symbol(newsbfd
,
751 canonical_symbol(newsbfd
,
755 struct supersect
*oldss
= fetch_supersect(oldsbfd
, oldp
);
756 match_sections(oldss
, newss
);
760 static void match_sections_by_label(struct superbfd
*oldsbfd
,
761 struct superbfd
*newsbfd
)
763 asection
*oldsect
, *newsect
;
764 struct supersect
*oldss
, *newss
;
765 for (newsect
= newsbfd
->abfd
->sections
; newsect
!= NULL
;
766 newsect
= newsect
->next
) {
767 newss
= fetch_supersect(newsbfd
, newsect
);
768 if (newss
->type
== SS_TYPE_STRING
||
769 newss
->type
== SS_TYPE_SPECIAL
||
770 newss
->type
== SS_TYPE_EXPORT
)
772 for (oldsect
= oldsbfd
->abfd
->sections
; oldsect
!= NULL
;
773 oldsect
= oldsect
->next
) {
774 if (strcmp(label_lookup(newsbfd
, newsect
->symbol
),
775 label_lookup(oldsbfd
, oldsect
->symbol
)) != 0)
777 oldss
= fetch_supersect(oldsbfd
, oldsect
);
778 match_sections(oldss
, newss
);
783 static void mark_new_sections(struct superbfd
*sbfd
)
786 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
787 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
788 if (ss
->type
== SS_TYPE_STRING
|| ss
->type
== SS_TYPE_SPECIAL
||
789 ss
->type
== SS_TYPE_IGNORED
|| ss
->type
== SS_TYPE_EXPORT
)
791 if (ss
->match
== NULL
)
796 static void handle_deleted_sections(struct superbfd
*oldsbfd
,
797 struct superbfd
*newsbfd
)
800 for (sect
= oldsbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
801 struct supersect
*ss
= fetch_supersect(oldsbfd
, sect
);
802 if (ss
->type
!= SS_TYPE_TEXT
)
804 if (ss
->match
!= NULL
)
806 const char *label
= label_lookup(oldsbfd
, sect
->symbol
);
807 *vec_grow(&delsects
, 1) = label
;
808 asymbol
*csym
= canonical_symbol(oldsbfd
, sect
->symbol
);
809 write_ksplice_deleted_patch(newsbfd
, csym
->name
, label
);
813 static void handle_nonzero_offset_relocs(struct supersect
*ss
)
816 for (i
= 0; i
< ss
->relocs
.size
; i
++) {
817 asymbol
*sym
= *ss
->relocs
.data
[i
]->sym_ptr_ptr
;
818 bfd_vma offset
= get_reloc_offset(ss
, ss
->relocs
.data
[i
], true);
819 if (sym
->value
+ offset
== 0)
821 if (bfd_is_const_section(sym
->section
))
823 struct supersect
*sym_ss
= fetch_supersect(ss
->parent
,
825 if (sym_ss
->type
!= SS_TYPE_TEXT
)
827 if (!sym_ss
->patch
) {
830 "Changing %s because a relocation from sect %s "
831 "has a nonzero offset %lx+%lx into it\n",
832 sym_ss
->name
, ss
->name
,
833 (unsigned long)sym
->value
,
834 (unsigned long)offset
);
836 sym_ss
->patch
= true;
840 static void update_nonzero_offsets(struct superbfd
*sbfd
)
843 struct supersect
*ss
;
845 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
846 ss
= fetch_supersect(sbfd
, sect
);
847 if (ss
->new || ss
->patch
)
848 handle_nonzero_offset_relocs(ss
);
852 static void compare_matched_sections(struct superbfd
*newsbfd
)
855 struct supersect
*old_ss
, *new_ss
;
856 for (newp
= newsbfd
->abfd
->sections
; newp
!= NULL
; newp
= newp
->next
) {
857 new_ss
= fetch_supersect(newsbfd
, newp
);
858 if (new_ss
->match
== NULL
)
860 old_ss
= new_ss
->match
;
862 if (nonrelocs_equal(old_ss
, new_ss
) &&
863 all_relocs_equal(old_ss
, new_ss
))
867 if (new_ss
->contents
.size
!= old_ss
->contents
.size
)
868 reason
= "differing sizes";
869 else if (memcmp(new_ss
->contents
.data
, old_ss
->contents
.data
,
870 new_ss
->contents
.size
) != 0)
871 reason
= "differing contents";
873 reason
= "differing relocations";
874 if (new_ss
->type
== SS_TYPE_TEXT
) {
877 new_ss
->patch
= true;
878 debug1(newsbfd
, "Changing %s due to %s\n", new_ss
->name
,
881 debug1(newsbfd
, "Unmatching %s and %s due to %s\n",
882 old_ss
->name
, new_ss
->name
, reason
);
883 new_ss
->match
= NULL
;
884 old_ss
->match
= NULL
;
887 if (unchangeable_section(new_ss
))
888 err(newsbfd
, "warning: ignoring change to nonpatchable "
889 "section %s\n", new_ss
->name
);
893 static void handle_section_symbol_renames(struct superbfd
*oldsbfd
,
894 struct superbfd
*newsbfd
)
896 asection
*newp
, *oldp
;
897 for (newp
= newsbfd
->abfd
->sections
; newp
!= NULL
; newp
= newp
->next
) {
898 struct supersect
*newss
= fetch_supersect(newsbfd
, newp
);
899 if (newss
->match
== NULL
)
901 oldp
= bfd_get_section_by_name(oldsbfd
->abfd
,
906 const char *old_label
= label_lookup(oldsbfd
, oldp
->symbol
);
907 const char *new_label
= label_lookup(newsbfd
, newp
->symbol
);
909 if (strcmp(old_label
, new_label
) == 0)
911 label_map_set(newsbfd
, new_label
, old_label
);
915 static bool part_of_reloc(struct supersect
*ss
, unsigned long addr
)
918 for (relocp
= ss
->relocs
.data
;
919 relocp
< ss
->relocs
.data
+ ss
->relocs
.size
; relocp
++) {
920 arelent
*reloc
= *relocp
;
921 if (addr
>= reloc
->address
&&
922 addr
< reloc
->address
+ reloc
->howto
->size
)
928 static bool nonrelocs_equal(struct supersect
*old_ss
, struct supersect
*new_ss
)
931 if (old_ss
->contents
.size
!= new_ss
->contents
.size
)
933 const unsigned char *old
= old_ss
->contents
.data
;
934 const unsigned char *new = new_ss
->contents
.data
;
935 for (i
= 0; i
< old_ss
->contents
.size
; i
++) {
936 if (old
[i
] != new[i
] &&
937 !(part_of_reloc(old_ss
, i
) && part_of_reloc(new_ss
, i
)))
943 bool relocs_equal(struct supersect
*old_src_ss
, struct supersect
*new_src_ss
,
944 arelent
*old_reloc
, arelent
*new_reloc
)
946 struct superbfd
*oldsbfd
= old_src_ss
->parent
;
947 struct superbfd
*newsbfd
= new_src_ss
->parent
;
949 if (old_reloc
->address
!= new_reloc
->address
) {
950 debug1(newsbfd
, "Section %s/%s has reloc address mismatch at "
951 "%lx\n", old_src_ss
->name
, new_src_ss
->name
,
952 (unsigned long)old_reloc
->address
);
956 if (old_reloc
->howto
!= new_reloc
->howto
) {
957 debug1(newsbfd
, "Section %s/%s has howto type mismatch at "
958 "%lx\n", old_src_ss
->name
, new_src_ss
->name
,
959 (unsigned long)old_reloc
->address
);
963 if (non_dst_mask(old_src_ss
, old_reloc
) !=
964 non_dst_mask(new_src_ss
, new_reloc
)) {
965 debug1(newsbfd
, "Section %s/%s has contents mismatch at %lx\n",
966 old_src_ss
->name
, new_src_ss
->name
,
967 (unsigned long)old_reloc
->address
);
971 asymbol
*old_sym
= *old_reloc
->sym_ptr_ptr
;
972 asymbol
*new_sym
= *new_reloc
->sym_ptr_ptr
;
973 asection
*old_sect
= old_sym
->section
;
974 asection
*new_sect
= new_sym
->section
;
976 bfd_vma old_offset
= get_reloc_offset(old_src_ss
, old_reloc
, true);
977 bfd_vma new_offset
= get_reloc_offset(new_src_ss
, new_reloc
, true);
979 if (bfd_is_und_section(old_sect
) || bfd_is_und_section(new_sect
)) {
980 if (!bfd_is_und_section(new_sect
) && old_offset
!= 0 &&
981 fetch_supersect(newsbfd
, new_sect
)->type
== SS_TYPE_TEXT
)
984 if (!bfd_is_und_section(new_sect
) && new_offset
!= 0 &&
985 fetch_supersect(oldsbfd
, old_sect
)->type
== SS_TYPE_TEXT
)
988 return strcmp(old_sym
->name
, new_sym
->name
) == 0 &&
989 old_offset
== new_offset
;
992 if (bfd_is_const_section(old_sect
) || bfd_is_const_section(new_sect
))
995 struct supersect
*old_ss
= fetch_supersect(oldsbfd
, old_sect
);
996 struct supersect
*new_ss
= fetch_supersect(newsbfd
, new_sect
);
998 if (old_ss
->type
== SS_TYPE_STRING
&&
999 /* check it's not an out-of-range relocation to a string;
1000 we'll just compare entire sections for them */
1001 !(old_offset
>= old_ss
->contents
.size
||
1002 new_offset
>= new_ss
->contents
.size
)) {
1003 if (strcmp(old_ss
->contents
.data
+ old_sym
->value
+ old_offset
,
1004 new_ss
->contents
.data
+ new_sym
->value
+ new_offset
)
1006 debug0(newsbfd
, "Section %s/%s has string difference "
1007 "\"%s\"/\"%s\"\n", old_src_ss
->name
,
1009 (const char *)(old_ss
->contents
.data
+
1010 old_sym
->value
+ old_offset
),
1011 (const char *)(new_ss
->contents
.data
+
1012 new_sym
->value
+ new_offset
));
1013 debug1(newsbfd
, "Strings differ between %s and %s\n",
1014 old_src_ss
->name
, new_src_ss
->name
);
1020 if (old_ss
->match
!= new_ss
|| new_ss
->match
!= old_ss
) {
1021 debug1(newsbfd
, "Nonmatching relocs from %s to %s/%s\n",
1022 new_src_ss
->name
, new_ss
->name
, old_ss
->name
);
1026 if (old_sym
->value
+ old_offset
!= new_sym
->value
+ new_offset
) {
1027 debug1(newsbfd
, "Offsets to %s/%s differ between %s "
1028 "and %s: %lx+%lx/%lx+%lx\n", old_ss
->name
,
1029 new_ss
->name
, old_src_ss
->name
, new_src_ss
->name
,
1030 (unsigned long)old_sym
->value
, (unsigned long)old_offset
,
1031 (unsigned long)new_sym
->value
,
1032 (unsigned long)new_offset
);
1036 if ((old_sym
->value
+ old_offset
!= 0 ||
1037 new_sym
->value
+ new_offset
!= 0) && new_ss
->patch
) {
1038 debug1(newsbfd
, "Relocation from %s to nonzero offsets "
1039 "%lx+%lx/%lx+%lx in changed section %s\n",
1040 new_src_ss
->name
, (unsigned long)old_sym
->value
,
1041 (unsigned long)old_offset
, (unsigned long)new_sym
->value
,
1042 (unsigned long)new_offset
, new_sym
->section
->name
);
1048 bool all_relocs_equal(struct supersect
*old_ss
, struct supersect
*new_ss
)
1050 if (old_ss
->relocs
.size
!= new_ss
->relocs
.size
) {
1051 debug1(new_ss
->parent
, "Different reloc count between %s and "
1052 "%s\n", old_ss
->name
, new_ss
->name
);
1057 for (i
= 0; i
< old_ss
->relocs
.size
; i
++) {
1058 if (!relocs_equal(old_ss
, new_ss
, old_ss
->relocs
.data
[i
],
1059 new_ss
->relocs
.data
[i
]))
1066 bfd_vma
non_dst_mask(struct supersect
*ss
, arelent
*reloc
)
1068 int bits
= bfd_get_reloc_size(reloc
->howto
) * 8;
1069 void *address
= ss
->contents
.data
+ reloc
->address
;
1070 bfd_vma x
= bfd_get(bits
, ss
->parent
->abfd
, address
);
1071 return x
& ~reloc
->howto
->dst_mask
;
1074 void rm_some_exports(struct superbfd
*sbfd
, const struct export_desc
*ed
)
1076 struct supersect
*ss
= ed
->sym_ss
;
1077 struct supersect
*crc_ss
= ed
->crc_ss
;
1079 assert(ss
->contents
.size
* sizeof(unsigned long) ==
1080 crc_ss
->contents
.size
* sizeof(struct kernel_symbol
));
1082 struct kernel_symbol
*ksym
;
1083 unsigned long *crc
= NULL
;
1085 crc
= crc_ss
->contents
.data
;
1086 struct span
*span
, *crc_span
;
1087 for (ksym
= ss
->contents
.data
;
1088 (void *)ksym
< ss
->contents
.data
+ ss
->contents
.size
;
1091 read_reloc(ss
, &ksym
->value
, sizeof(ksym
->value
), &sym
);
1092 span
= new_span(ss
, addr_offset(ss
, ksym
), sizeof(*ksym
));
1093 span
->keep
= str_in_set(sym
->name
, &ed
->names
);
1095 if (crc_ss
!= NULL
) {
1096 crc_span
= new_span(crc_ss
, addr_offset(crc_ss
, crc
),
1098 crc_span
->keep
= span
->keep
;
1102 /* Replace name with a mangled name */
1103 write_string(ss
, (const char **)&ksym
->name
,
1104 "DISABLED_%s_%s", sym
->name
, kid
);
1109 void rm_relocs(struct superbfd
*isbfd
)
1112 for (p
= isbfd
->abfd
->sections
; p
!= NULL
; p
= p
->next
) {
1113 struct supersect
*ss
= fetch_supersect(isbfd
, p
);
1114 if ((mode("keep") && ss
->type
== SS_TYPE_SPECIAL
) ||
1115 ss
->type
== SS_TYPE_KSPLICE
)
1117 if (ss
->keep
|| mode("rmsyms"))
1120 if (mode("finalize")) {
1121 p
= bfd_get_section_by_name(isbfd
->abfd
, ".ksplice_patches");
1123 struct supersect
*ss
= fetch_supersect(isbfd
, p
);
1126 p
= bfd_get_section_by_name(isbfd
->abfd
, ".ksplice_relocs");
1128 struct supersect
*ss
= fetch_supersect(isbfd
, p
);
1134 void rm_some_relocs(struct supersect
*ss
)
1136 struct arelentp_vec orig_relocs
;
1137 vec_move(&orig_relocs
, &ss
->relocs
);
1140 for (relocp
= orig_relocs
.data
;
1141 relocp
< orig_relocs
.data
+ orig_relocs
.size
; relocp
++) {
1142 bool rm_reloc
= false;
1143 asymbol
*sym_ptr
= *(*relocp
)->sym_ptr_ptr
;
1145 if (mode("rmsyms") && str_in_set(sym_ptr
->name
, &rmsyms
) &&
1146 bfd_is_und_section(sym_ptr
->section
))
1152 if (mode("keep-primary") &&
1153 (bfd_is_const_section(sym_ptr
->section
) ||
1154 fetch_supersect(ss
->parent
, sym_ptr
->section
)->new ||
1155 reloc_target_span(ss
, *relocp
)->new ||
1156 !reloc_address_span(ss
, *relocp
)->keep
))
1159 if (mode("finalize") && bfd_is_und_section(sym_ptr
->section
))
1162 if (strcmp(sym_ptr
->name
, "mcount") == 0 &&
1163 bfd_is_und_section(sym_ptr
->section
))
1167 write_ksplice_reloc(ss
, *relocp
);
1169 *vec_grow(&ss
->relocs
, 1) = *relocp
;
1173 struct supersect
*make_section(struct superbfd
*sbfd
, const char *name
)
1175 asection
*sect
= bfd_get_section_by_name(sbfd
->abfd
, name
);
1177 return fetch_supersect(sbfd
, sect
);
1179 return new_supersect(sbfd
, name
);
1182 arelent
*create_reloc(struct supersect
*ss
, const void *addr
, asymbol
**symp
,
1185 bfd_reloc_code_real_type code
;
1186 switch (bfd_arch_bits_per_address(ss
->parent
->abfd
)) {
1188 code
= BFD_RELOC_32
;
1191 code
= BFD_RELOC_64
;
1197 arelent
*reloc
= malloc(sizeof(*reloc
));
1198 reloc
->sym_ptr_ptr
= symp
;
1199 reloc
->address
= addr_offset(ss
, addr
);
1200 reloc
->howto
= bfd_reloc_type_lookup(ss
->parent
->abfd
, code
);
1201 reloc
->addend
= offset
;
1205 void write_reloc(struct supersect
*ss
, const void *addr
, asymbol
**symp
,
1208 *vec_grow(&ss
->new_relocs
, 1) = create_reloc(ss
, addr
, symp
, offset
);
1211 void write_string(struct supersect
*ss
, const char **addr
, const char *fmt
, ...)
1214 struct supersect
*str_ss
= make_section(ss
->parent
, ".ksplice_str");
1217 int len
= vasprintf(&str
, fmt
, ap
);
1221 unsigned long *str_offp
= ulong_hash_lookup(&ksplice_string_offset
, str
,
1223 if (str_offp
== NULL
) {
1224 char *buf
= sect_grow(str_ss
, len
+ 1, char);
1225 memcpy(buf
, str
, len
+ 1);
1226 str_offp
= ulong_hash_lookup(&ksplice_string_offset
, str
, TRUE
);
1227 *str_offp
= addr_offset(str_ss
, buf
);
1230 write_reloc(ss
, addr
, &str_ss
->symbol
, *str_offp
);
1233 void lookup_system_map(struct addr_vec
*addrs
, const char *name
, long offset
)
1235 struct addr_vec
*map_addrs
=
1236 addr_vec_hash_lookup(&system_map
, name
, FALSE
);
1237 if (map_addrs
== NULL
)
1240 unsigned long *addr
, *map_addr
;
1241 for (map_addr
= map_addrs
->data
;
1242 map_addr
< map_addrs
->data
+ map_addrs
->size
; map_addr
++) {
1243 for (addr
= addrs
->data
; addr
< addrs
->data
+ addrs
->size
;
1245 if (*addr
== *map_addr
+ offset
)
1248 if (addr
< addrs
->data
+ addrs
->size
)
1250 *vec_grow(addrs
, 1) = *map_addr
+ offset
;
1254 void compute_system_map_array(struct superbfd
*sbfd
, struct addr_vec
*addrs
,
1257 if (bfd_is_abs_section(sym
->section
)) {
1258 *vec_grow(addrs
, 1) = sym
->value
;
1259 } else if (bfd_is_und_section(sym
->section
)) {
1260 lookup_system_map(addrs
, sym
->name
, 0);
1261 } else if (!bfd_is_const_section(sym
->section
)) {
1263 for (gsymp
= sbfd
->syms
.data
;
1264 gsymp
< sbfd
->syms
.data
+ sbfd
->syms
.size
; gsymp
++) {
1265 asymbol
*gsym
= *gsymp
;
1266 if ((gsym
->flags
& BSF_DEBUGGING
) == 0 &&
1267 gsym
->section
== sym
->section
)
1268 lookup_system_map(addrs
, gsym
->name
,
1269 sym
->value
- gsym
->value
);
1274 void write_ksplice_system_map(struct superbfd
*sbfd
, asymbol
*sym
,
1277 bool *done
= bool_hash_lookup(&system_map_written
, label
, TRUE
);
1282 struct addr_vec addrs
;
1285 compute_system_map_array(sbfd
, &addrs
, sym
);
1286 if (addrs
.size
!= 0) {
1287 struct supersect
*smap_ss
=
1288 make_section(sbfd
, ".ksplice_system_map");
1289 struct ksplice_system_map
*smap
=
1290 sect_grow(smap_ss
, 1, struct ksplice_system_map
);
1291 write_string(smap_ss
, &smap
->label
, "%s", label
);
1293 struct supersect
*array_ss
= make_section(sbfd
,
1295 void *buf
= sect_grow(array_ss
, addrs
.size
,
1296 typeof(*addrs
.data
));
1297 memcpy(buf
, addrs
.data
, addrs
.size
* sizeof(*addrs
.data
));
1298 smap
->nr_candidates
= addrs
.size
;
1299 write_reloc(smap_ss
, &smap
->candidates
, &array_ss
->symbol
,
1300 addr_offset(array_ss
, buf
));
1305 void write_ksplice_symbol_backend(struct supersect
*ss
,
1306 struct ksplice_symbol
*const *addr
,
1307 asymbol
*sym
, const char *label
,
1310 struct supersect
*ksymbol_ss
= make_section(ss
->parent
,
1311 ".ksplice_symbols");
1312 struct ksplice_symbol
*ksymbol
;
1313 unsigned long *ksymbol_offp
;
1315 ksymbol_offp
= ulong_hash_lookup(&ksplice_symbol_offset
, label
, FALSE
);
1316 if (ksymbol_offp
!= NULL
) {
1317 write_reloc(ss
, addr
, &ksymbol_ss
->symbol
, *ksymbol_offp
);
1320 ksymbol
= sect_grow(ksymbol_ss
, 1, struct ksplice_symbol
);
1321 ksymbol_offp
= ulong_hash_lookup(&ksplice_symbol_offset
, label
, TRUE
);
1322 *ksymbol_offp
= addr_offset(ksymbol_ss
, ksymbol
);
1324 write_reloc(ss
, addr
, &ksymbol_ss
->symbol
, *ksymbol_offp
);
1325 write_string(ksymbol_ss
, &ksymbol
->label
, "%s", label
);
1327 write_string(ksymbol_ss
, &ksymbol
->name
, "%s", name
);
1328 write_ksplice_system_map(ksymbol_ss
->parent
, sym
, label
);
1332 void write_ksplice_symbol(struct supersect
*ss
,
1333 struct ksplice_symbol
*const *addr
,
1334 asymbol
*sym
, struct span
*span
,
1335 const char *addstr_sect
)
1337 const char *label
, *name
;
1339 if (span
!= NULL
&& span
->start
!= 0)
1340 label
= span
->label
;
1342 label
= label_lookup(ss
->parent
, sym
);
1344 assert(asprintf(&output
, "%s%s", label
, addstr_sect
) >= 0);
1346 asymbol
*gsym
= canonical_symbol(ss
->parent
, sym
);
1347 if (strcmp(addstr_sect
, "") != 0)
1349 else if (bfd_is_und_section(sym
->section
))
1351 else if (bfd_is_const_section(sym
->section
))
1353 else if (span
!= NULL
&& span
->symbol
== NULL
)
1355 else if (gsym
== NULL
|| (gsym
->flags
& BSF_SECTION_SYM
) != 0)
1360 write_ksplice_symbol_backend(ss
, addr
, sym
, output
, name
);
1363 void write_ksplice_reloc(struct supersect
*ss
, arelent
*orig_reloc
)
1365 asymbol
*sym_ptr
= *orig_reloc
->sym_ptr_ptr
;
1366 reloc_howto_type
*howto
= orig_reloc
->howto
;
1367 bfd_vma addend
= get_reloc_offset(ss
, orig_reloc
, false);
1368 unsigned long *repladdr
= ss
->contents
.data
+ orig_reloc
->address
;
1370 if (mode("finalize") && strcmp(ss
->name
, ".ksplice_patches") == 0) {
1374 if (mode("finalize") && strcmp(ss
->name
, ".ksplice_relocs") == 0) {
1375 assert(starts_with(sym_ptr
->name
, KSPLICE_SYMBOL_STR
));
1377 fake_sym
.name
= sym_ptr
->name
+ strlen(KSPLICE_SYMBOL_STR
);
1378 fake_sym
.section
= bfd_und_section_ptr
;
1382 write_ksplice_symbol_backend
1383 (ss
, (struct ksplice_symbol
**)repladdr
, &fake_sym
,
1384 fake_sym
.name
, fake_sym
.name
);
1388 struct span
*span
= reloc_target_span(ss
, orig_reloc
);
1389 if (span
== ss
->spans
.data
&& span
->start
!= addend
)
1391 blot_section(ss
, orig_reloc
->address
, howto
);
1393 struct supersect
*kreloc_ss
= make_section(ss
->parent
,
1395 ".ksplice_init_relocs" :
1397 struct ksplice_reloc
*kreloc
= sect_grow(kreloc_ss
, 1,
1398 struct ksplice_reloc
);
1400 struct span
*address_span
= reloc_address_span(ss
, orig_reloc
);
1401 write_reloc(kreloc_ss
, &kreloc
->blank_addr
,
1402 &ss
->symbol
, orig_reloc
->address
+ address_span
->shift
);
1403 if (bfd_is_und_section(sym_ptr
->section
) && mode("keep")) {
1405 assert(asprintf(&name
, KSPLICE_SYMBOL_STR
"%s", sym_ptr
->name
)
1407 asymbol
**symp
= make_undefined_symbolp(ss
->parent
, name
);
1408 write_reloc(kreloc_ss
, &kreloc
->symbol
, symp
, 0);
1410 write_ksplice_symbol(kreloc_ss
, &kreloc
->symbol
, sym_ptr
, span
,
1413 kreloc
->pcrel
= howto
->pc_relative
;
1414 if (span
!= NULL
&& span
->start
!= 0)
1415 addend
+= sym_ptr
->value
- span
->start
;
1416 kreloc
->addend
= addend
;
1417 kreloc
->size
= bfd_get_reloc_size(howto
);
1418 kreloc
->dst_mask
= howto
->dst_mask
;
1419 kreloc
->rightshift
= howto
->rightshift
;
1420 kreloc
->signed_addend
=
1421 (howto
->complain_on_overflow
== complain_overflow_signed
) ||
1422 (howto
->complain_on_overflow
== complain_overflow_bitfield
);
1425 #define CANARY(x, canary) ((x & ~howto->dst_mask) | (canary & howto->dst_mask))
1427 void blot_section(struct supersect
*ss
, int offset
, reloc_howto_type
*howto
)
1429 int bits
= bfd_get_reloc_size(howto
) * 8;
1430 void *address
= ss
->contents
.data
+ offset
;
1431 bfd_vma x
= bfd_get(bits
, ss
->parent
->abfd
, address
);
1432 x
= (x
& ~howto
->dst_mask
) |
1433 ((bfd_vma
)KSPLICE_CANARY
& howto
->dst_mask
);
1434 bfd_put(bits
, ss
->parent
->abfd
, x
, address
);
1437 static void write_ksplice_section(struct span
*span
)
1439 struct supersect
*ss
= span
->ss
;
1440 struct supersect
*ksect_ss
=
1441 make_section(ss
->parent
, ".ksplice_sections");
1442 struct ksplice_section
*ksect
= sect_grow(ksect_ss
, 1,
1443 struct ksplice_section
);
1444 asymbol
*sym
= span
->symbol
== NULL
? ss
->symbol
: span
->symbol
;
1446 write_ksplice_symbol(ksect_ss
, &ksect
->symbol
, sym
, span
,
1447 mode("keep-primary") ? "(post)" : "");
1448 ksect
->size
= span
->size
;
1451 if (ss
->type
== SS_TYPE_RODATA
|| ss
->type
== SS_TYPE_STRING
)
1452 ksect
->flags
|= KSPLICE_SECTION_RODATA
;
1453 if (ss
->type
== SS_TYPE_DATA
)
1454 ksect
->flags
|= KSPLICE_SECTION_DATA
;
1455 if (ss
->type
== SS_TYPE_TEXT
)
1456 ksect
->flags
|= KSPLICE_SECTION_TEXT
;
1457 assert(ksect
->flags
!= 0);
1458 write_reloc(ksect_ss
, &ksect
->address
, &ss
->symbol
,
1459 span
->start
+ span
->shift
);
1462 void write_ksplice_patch(struct superbfd
*sbfd
, const char *sectname
)
1464 struct supersect
*kpatch_ss
= make_section(sbfd
, ".ksplice_patches");
1465 struct ksplice_patch
*kpatch
= sect_grow(kpatch_ss
, 1,
1466 struct ksplice_patch
);
1467 asection
*sect
= bfd_get_section_by_name(sbfd
->abfd
, sectname
);
1468 assert(sect
!= NULL
);
1470 write_string(kpatch_ss
, &kpatch
->label
, "%s",
1471 label_lookup(sbfd
, sect
->symbol
));
1472 write_reloc(kpatch_ss
, &kpatch
->repladdr
, §
->symbol
, 0);
1475 asymbol
**make_undefined_symbolp(struct superbfd
*sbfd
, const char *name
)
1478 for (symp
= sbfd
->syms
.data
; symp
< sbfd
->syms
.data
+ sbfd
->syms
.size
;
1480 asymbol
*sym
= *symp
;
1481 if (strcmp(name
, sym
->name
) == 0 &&
1482 bfd_is_und_section(sym
->section
))
1486 for (sympp
= sbfd
->new_syms
.data
;
1487 sympp
< sbfd
->new_syms
.data
+ sbfd
->new_syms
.size
; sympp
++) {
1488 asymbol
**symp
= *sympp
;
1489 asymbol
*sym
= *symp
;
1490 if (strcmp(name
, sym
->name
) == 0 &&
1491 bfd_is_und_section(sym
->section
))
1495 symp
= malloc(sizeof(*symp
));
1496 *symp
= bfd_make_empty_symbol(sbfd
->abfd
);
1497 asymbol
*sym
= *symp
;
1499 sym
->section
= bfd_und_section_ptr
;
1502 *vec_grow(&sbfd
->new_syms
, 1) = symp
;
1506 void write_ksplice_deleted_patch(struct superbfd
*sbfd
, const char *name
,
1509 struct supersect
*kpatch_ss
= make_section(sbfd
, ".ksplice_patches");
1510 struct ksplice_patch
*kpatch
= sect_grow(kpatch_ss
, 1,
1511 struct ksplice_patch
);
1513 write_string(kpatch_ss
, &kpatch
->label
, "%s", label
);
1514 asymbol
**symp
= make_undefined_symbolp(sbfd
, strdup(name
));
1515 write_reloc(kpatch_ss
, &kpatch
->repladdr
, symp
, 0);
1518 void write_ksplice_export(struct superbfd
*sbfd
, const char *symname
,
1519 const char *export_type
, bool del
)
1521 struct supersect
*export_ss
= make_section(sbfd
, ".ksplice_exports");
1522 struct ksplice_export
*exp
= sect_grow(export_ss
, 1,
1523 struct ksplice_export
);
1526 write_string(export_ss
, &exp
->name
, "%s", symname
);
1527 write_string(export_ss
, &exp
->new_name
, "DISABLED_%s_%s",
1530 write_string(export_ss
, &exp
->new_name
, "%s", symname
);
1531 write_string(export_ss
, &exp
->name
, "DISABLED_%s_%s", symname
,
1536 struct fixup_entry
{
1540 DECLARE_VEC_TYPE(struct fixup_entry
, fixup_entry_vec
);
1542 int compare_fixups(const void *aptr
, const void *bptr
)
1544 const struct fixup_entry
*a
= aptr
, *b
= bptr
;
1545 if (a
->offset
< b
->offset
)
1547 else if (a
->offset
> b
->offset
)
1550 return (int)a
->used
- (int)b
->used
;
1553 void filter_table_sections(struct superbfd
*isbfd
)
1555 struct supersect
*tables_ss
=
1556 fetch_supersect(offsets_sbfd
,
1557 bfd_get_section_by_name(offsets_sbfd
->abfd
,
1558 ".ksplice_table_sections"));
1559 const struct table_section
*ts
;
1560 for (ts
= tables_ss
->contents
.data
;
1561 (void *)ts
< tables_ss
->contents
.data
+ tables_ss
->contents
.size
;
1563 struct table_section s
= *ts
;
1564 s
.sect
= read_string(tables_ss
, &ts
->sect
);
1565 s
.other_sect
= read_string(tables_ss
, &ts
->other_sect
);
1566 filter_table_section(isbfd
, &s
);
1570 void filter_table_section(struct superbfd
*sbfd
, const struct table_section
*s
)
1572 asection
*isection
= bfd_get_section_by_name(sbfd
->abfd
, s
->sect
);
1573 if (isection
== NULL
)
1575 asection
*fixup_sect
= NULL
;
1576 if (s
->other_sect
!= NULL
)
1577 fixup_sect
= bfd_get_section_by_name(sbfd
->abfd
, s
->other_sect
);
1579 struct supersect
*ss
= fetch_supersect(sbfd
, isection
);
1580 if (ss
->alignment
< ffs(s
->entry_align
) - 1)
1581 ss
->alignment
= ffs(s
->entry_align
) - 1;
1583 struct supersect
*fixup_ss
= NULL
;
1584 if (fixup_sect
!= NULL
)
1585 fixup_ss
= fetch_supersect(sbfd
, fixup_sect
);
1587 struct fixup_entry_vec fixups
;
1591 for (entry
= ss
->contents
.data
;
1592 entry
< ss
->contents
.data
+ ss
->contents
.size
;
1593 entry
+= s
->entry_size
) {
1594 asymbol
*sym
, *fixup_sym
;
1595 read_reloc(ss
, entry
+ s
->addr_offset
, sizeof(void *), &sym
);
1597 struct span
*span
= new_span(ss
, addr_offset(ss
, entry
),
1599 struct supersect
*sym_ss
= fetch_supersect(sbfd
, sym
->section
);
1600 span
->keep
= sym_ss
->keep
;
1602 struct fixup_entry
*f
;
1603 if (fixup_sect
!= NULL
) {
1604 bfd_vma fixup_offset
=
1605 read_reloc(ss
, entry
+ s
->other_offset
,
1606 sizeof(void *), &fixup_sym
);
1607 if (fixup_sym
->section
== fixup_sect
) {
1608 assert(fixup_offset
< fixup_ss
->contents
.size
);
1609 f
= vec_grow(&fixups
, 1);
1610 f
->offset
= fixup_offset
;
1611 f
->used
= span
->keep
;
1616 if (fixup_sect
== NULL
)
1619 qsort(fixups
.data
, fixups
.size
, sizeof(*fixups
.data
), compare_fixups
);
1620 *vec_grow(&fixups
, 1) = (struct fixup_entry
)
1621 { .offset
= fixup_ss
->contents
.size
, .used
= false };
1623 struct fixup_entry
*f
;
1624 for (f
= fixups
.data
; f
< fixups
.data
+ fixups
.size
- 1; f
++) {
1625 struct span
*span
= new_span(fixup_ss
, f
->offset
,
1626 (f
+ 1)->offset
- f
->offset
);
1627 span
->keep
= f
->used
;
1631 void keep_referenced_sections(struct superbfd
*sbfd
)
1634 struct supersect
*ss
, *sym_ss
;
1635 struct span
*address_span
, *target_span
;
1636 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
1637 ss
= fetch_supersect(sbfd
, sect
);
1639 if (ss
->type
== SS_TYPE_SPECIAL
|| ss
->type
== SS_TYPE_EXPORT
)
1641 for (relocp
= ss
->relocs
.data
;
1642 relocp
< ss
->relocs
.data
+ ss
->relocs
.size
; relocp
++) {
1643 asymbol
*sym
= *(*relocp
)->sym_ptr_ptr
;
1644 address_span
= reloc_address_span(ss
, *relocp
);
1645 if (!address_span
->keep
)
1647 target_span
= reloc_target_span(ss
, *relocp
);
1648 if (target_span
== NULL
|| target_span
->keep
)
1650 sym_ss
= fetch_supersect(sbfd
, sym
->section
);
1651 if (sym_ss
->type
== SS_TYPE_IGNORED
)
1653 target_span
->keep
= true;
1654 sym_ss
->keep
= true;
1660 void copy_symbols(struct asymbolp_vec
*osyms
, struct asymbolpp_vec
*isyms
)
1663 for (sympp
= isyms
->data
; sympp
< isyms
->data
+ isyms
->size
; sympp
++)
1664 *vec_grow(osyms
, 1) = **sympp
;
1667 /* Modified function from GNU Binutils objcopy.c */
1668 bfd_boolean
copy_object(bfd
*ibfd
, bfd
*obfd
)
1670 assert(bfd_set_format(obfd
, bfd_get_format(ibfd
)));
1672 bfd_vma start
= bfd_get_start_address(ibfd
);
1674 flagword flags
= bfd_get_file_flags(ibfd
);
1675 flags
&= bfd_applicable_file_flags(obfd
);
1677 assert(bfd_set_start_address(obfd
, start
)
1678 && bfd_set_file_flags(obfd
, flags
));
1680 enum bfd_architecture iarch
= bfd_get_arch(ibfd
);
1681 unsigned int imach
= bfd_get_mach(ibfd
);
1682 assert(bfd_set_arch_mach(obfd
, iarch
, imach
));
1683 assert(bfd_set_format(obfd
, bfd_get_format(ibfd
)));
1685 /* BFD mandates that all output sections be created and sizes set before
1686 any output is done. Thus, we traverse all sections multiple times. */
1687 bfd_map_over_sections(ibfd
, setup_section
, obfd
);
1689 struct supersect
*new_supersects
= fetch_superbfd(ibfd
)->new_supersects
;
1690 struct supersect
*ss
;
1691 for (ss
= new_supersects
; ss
!= NULL
; ss
= ss
->next
)
1692 setup_new_section(obfd
, ss
);
1694 /* Mark symbols used in output relocations so that they
1695 are kept, even if they are local labels or static symbols.
1697 Note we iterate over the input sections examining their
1698 relocations since the relocations for the output sections
1699 haven't been set yet. mark_symbols_used_in_relocations will
1700 ignore input sections which have no corresponding output
1703 bfd_map_over_sections(ibfd
, mark_symbols_used_in_relocations
, NULL
);
1704 for (ss
= new_supersects
; ss
!= NULL
; ss
= ss
->next
)
1705 ss_mark_symbols_used_in_relocations(ss
);
1706 struct asymbolp_vec osyms
;
1708 filter_symbols(ibfd
, obfd
, &osyms
, &fetch_superbfd(ibfd
)->syms
);
1709 copy_symbols(&osyms
, &fetch_superbfd(ibfd
)->new_syms
);
1711 bfd_set_symtab(obfd
, osyms
.data
, osyms
.size
);
1713 /* This has to happen after the symbol table has been set. */
1714 bfd_map_over_sections(obfd
, write_section
, NULL
);
1716 /* Allow the BFD backend to copy any private data it understands
1717 from the input BFD to the output BFD. This is done last to
1718 permit the routine to look at the filtered symbol table, which is
1719 important for the ECOFF code at least. */
1720 assert(bfd_copy_private_bfd_data(ibfd
, obfd
));
1725 /* Modified function from GNU Binutils objcopy.c */
1726 void setup_section(bfd
*ibfd
, asection
*isection
, void *obfdarg
)
1728 struct superbfd
*isbfd
= fetch_superbfd(ibfd
);
1729 struct supersect
*ss
= fetch_supersect(isbfd
, isection
);
1730 bfd
*obfd
= obfdarg
;
1736 asection
*osection
= bfd_make_section_anyway(obfd
, isection
->name
);
1737 assert(osection
!= NULL
);
1739 osection
->userdata
= ss
;
1740 bfd_set_section_flags(obfd
, osection
, ss
->flags
);
1741 ss
->symbol
= osection
->symbol
;
1742 assert(bfd_set_section_size(obfd
, osection
, ss
->contents
.size
));
1744 vma
= bfd_section_vma(ibfd
, isection
);
1745 assert(bfd_set_section_vma(obfd
, osection
, vma
));
1747 osection
->lma
= isection
->lma
;
1748 assert(bfd_set_section_alignment(obfd
, osection
, ss
->alignment
));
1749 osection
->entsize
= isection
->entsize
;
1750 osection
->output_section
= osection
;
1751 osection
->output_offset
= 0;
1752 isection
->output_section
= osection
;
1753 isection
->output_offset
= 0;
1757 void setup_new_section(bfd
*obfd
, struct supersect
*ss
)
1759 asection
*osection
= bfd_make_section_anyway(obfd
, ss
->name
);
1760 assert(osection
!= NULL
);
1761 bfd_set_section_flags(obfd
, osection
, ss
->flags
);
1763 osection
->userdata
= ss
;
1764 ss
->symbol
= osection
->symbol
;
1765 assert(bfd_set_section_size(obfd
, osection
, ss
->contents
.size
));
1766 assert(bfd_set_section_vma(obfd
, osection
, 0));
1769 assert(bfd_set_section_alignment(obfd
, osection
, ss
->alignment
));
1770 osection
->entsize
= 0;
1771 osection
->output_section
= osection
;
1772 osection
->output_offset
= 0;
1775 static int compare_reloc_addresses(const void *aptr
, const void *bptr
)
1777 const arelent
*const *a
= aptr
, *const *b
= bptr
;
1778 return (*a
)->address
- (*b
)->address
;
1781 static void delete_obsolete_relocs(struct supersect
*ss
)
1783 if (ss
->new_relocs
.size
== 0)
1786 qsort(ss
->relocs
.data
, ss
->relocs
.size
, sizeof(*ss
->relocs
.data
),
1787 compare_reloc_addresses
);
1788 qsort(ss
->new_relocs
.data
, ss
->new_relocs
.size
,
1789 sizeof(*ss
->new_relocs
.data
), compare_reloc_addresses
);
1791 struct arelentp_vec orig_relocs
;
1792 vec_move(&orig_relocs
, &ss
->relocs
);
1794 arelent
**relocp
, **new_relocp
= ss
->new_relocs
.data
;
1795 for (relocp
= orig_relocs
.data
;
1796 relocp
< orig_relocs
.data
+ orig_relocs
.size
; relocp
++) {
1797 while (new_relocp
< ss
->new_relocs
.data
+ ss
->new_relocs
.size
&&
1798 (*new_relocp
)->address
< (*relocp
)->address
)
1800 arelent
*reloc
= *relocp
, *new_reloc
= *new_relocp
;
1801 if (new_relocp
== ss
->new_relocs
.data
+ ss
->new_relocs
.size
||
1802 reloc
->address
!= new_reloc
->address
)
1803 *vec_grow(&ss
->relocs
, 1) = reloc
;
1807 void write_section(bfd
*obfd
, asection
*osection
, void *arg
)
1809 struct supersect
*ss
= osection
->userdata
;
1811 if ((ss
->flags
& SEC_GROUP
) != 0 || ss
->contents
.size
== 0)
1814 delete_obsolete_relocs(ss
);
1817 char *error_message
;
1818 for (relocp
= ss
->new_relocs
.data
;
1819 relocp
< ss
->new_relocs
.data
+ ss
->new_relocs
.size
; relocp
++) {
1821 if (bfd_get_arch(obfd
) == bfd_arch_arm
)
1822 val
= osection
->use_rela_p
? 0 : (*relocp
)->addend
;
1825 bfd_put(bfd_get_reloc_size((*relocp
)->howto
) * 8, obfd
, val
,
1826 ss
->contents
.data
+ (*relocp
)->address
);
1827 if (bfd_install_relocation(obfd
, *relocp
, ss
->contents
.data
,
1828 0, osection
, &error_message
) !=
1830 err(ss
->parent
, "ksplice: error installing reloc: %s",
1835 memcpy(vec_grow(&ss
->relocs
, ss
->new_relocs
.size
), ss
->new_relocs
.data
,
1836 ss
->new_relocs
.size
* sizeof(*ss
->new_relocs
.data
));
1838 bfd_set_reloc(obfd
, osection
,
1839 ss
->relocs
.size
== 0 ? NULL
: ss
->relocs
.data
,
1842 if (ss
->flags
& SEC_HAS_CONTENTS
)
1843 assert(bfd_set_section_contents
1844 (obfd
, osection
, ss
->contents
.data
, 0,
1845 ss
->contents
.size
));
1848 /* Modified function from GNU Binutils objcopy.c
1850 * Mark all the symbols which will be used in output relocations with
1851 * the BSF_KEEP flag so that those symbols will not be stripped.
1853 * Ignore relocations which will not appear in the output file.
1855 void mark_symbols_used_in_relocations(bfd
*abfd
, asection
*isection
,
1858 struct superbfd
*sbfd
= fetch_superbfd(abfd
);
1859 if (isection
->output_section
== NULL
)
1862 struct supersect
*ss
= fetch_supersect(sbfd
, isection
);
1863 ss_mark_symbols_used_in_relocations(ss
);
1866 void ss_mark_symbols_used_in_relocations(struct supersect
*ss
)
1868 /* Examine each symbol used in a relocation. If it's not one of the
1869 special bfd section symbols, then mark it with BSF_KEEP. */
1871 for (relocp
= ss
->relocs
.data
;
1872 relocp
< ss
->relocs
.data
+ ss
->relocs
.size
; relocp
++) {
1873 asymbol
*sym
= *(*relocp
)->sym_ptr_ptr
;
1874 if (!(bfd_is_const_section(sym
->section
) &&
1875 sym
== sym
->section
->symbol
))
1876 sym
->flags
|= BSF_KEEP
;
1878 for (relocp
= ss
->new_relocs
.data
;
1879 relocp
< ss
->new_relocs
.data
+ ss
->new_relocs
.size
; relocp
++) {
1880 asymbol
*sym
= *(*relocp
)->sym_ptr_ptr
;
1881 if (!(bfd_is_const_section(sym
->section
) &&
1882 sym
== sym
->section
->symbol
))
1883 sym
->flags
|= BSF_KEEP
;
1887 static bool deleted_table_section_symbol(bfd
*abfd
, asymbol
*sym
)
1889 struct superbfd
*sbfd
= fetch_superbfd(abfd
);
1890 if (bfd_is_const_section(sym
->section
))
1892 struct supersect
*ss
= fetch_supersect(sbfd
, sym
->section
);
1895 for (symp
= ss
->syms
.data
; symp
< ss
->syms
.data
+ ss
->syms
.size
; symp
++) {
1899 return symp
>= ss
->syms
.data
+ ss
->syms
.size
;
1902 /* Modified function from GNU Binutils objcopy.c
1904 * Choose which symbol entries to copy.
1905 * We don't copy in place, because that confuses the relocs.
1906 * Return the number of symbols to print.
1908 void filter_symbols(bfd
*ibfd
, bfd
*obfd
, struct asymbolp_vec
*osyms
,
1909 struct asymbolp_vec
*isyms
)
1912 struct superbfd
*sbfd
= fetch_superbfd(ibfd
);
1913 for (symp
= isyms
->data
; symp
< isyms
->data
+ isyms
->size
; symp
++) {
1914 asymbol
*sym
= *symp
;
1915 struct supersect
*sym_ss
= NULL
;
1916 if (!bfd_is_const_section(sym
->section
))
1917 sym_ss
= fetch_supersect(sbfd
, sym
->section
);
1921 if (mode("keep") && (sym
->flags
& BSF_GLOBAL
) != 0 &&
1922 !(mode("keep-primary") && sym_ss
!= NULL
&& sym_ss
->new))
1923 sym
->flags
= (sym
->flags
& ~BSF_GLOBAL
) | BSF_LOCAL
;
1925 if (mode("finalize") && (sym
->flags
& BSF_GLOBAL
) != 0)
1926 sym
->flags
= (sym
->flags
& ~BSF_GLOBAL
) | BSF_LOCAL
;
1928 if ((sym
->flags
& BSF_KEEP
) != 0 /* Used in relocation. */
1929 || ((sym
->flags
& BSF_SECTION_SYM
) != 0 && sym_ss
!= NULL
&&
1932 else if ((sym
->flags
& (BSF_GLOBAL
| BSF_WEAK
)) != 0 &&
1933 sym_ss
!= NULL
&& sym_ss
->keep
)
1936 if (deleted_table_section_symbol(ibfd
, sym
))
1939 if (bfd_is_com_section(sym
->section
))
1943 keep
= !str_in_set(sym
->name
, &rmsyms
);
1946 if (sym_ss
!= NULL
&& !sym_ss
->keep
) {
1947 err(sbfd
, "Kept symbol %s in unkept section "
1948 "%s\n", sym
->name
, sym
->section
->name
);
1951 *vec_grow(osyms
, 1) = sym
;
1956 void read_str_set(struct str_vec
*strs
)
1960 assert(getline(&buf
, &n
, stdin
) >= 0);
1964 char *str
= strtok_r(buf
, " \n", &saveptr
);
1968 *vec_grow(strs
, 1) = str
;
1972 bool str_in_set(const char *str
, const struct str_vec
*strs
)
1975 for (strp
= strs
->data
; strp
< strs
->data
+ strs
->size
; strp
++) {
1976 if (strcmp(str
, *strp
) == 0)
1982 bool is_table_section(const char *name
, bool consider_other
)
1984 struct supersect
*tables_ss
=
1985 fetch_supersect(offsets_sbfd
,
1986 bfd_get_section_by_name(offsets_sbfd
->abfd
,
1987 ".ksplice_table_sections"));
1988 const struct table_section
*ts
;
1989 for (ts
= tables_ss
->contents
.data
;
1990 (void *)ts
< tables_ss
->contents
.data
+ tables_ss
->contents
.size
;
1992 if (strcmp(name
, read_string(tables_ss
, &ts
->sect
)) == 0)
1994 const char *osect_name
= read_string(tables_ss
,
1996 if (consider_other
&& osect_name
!= NULL
&&
1997 strcmp(name
, osect_name
) == 0)
2003 enum supersect_type
supersect_type(struct supersect
*ss
)
2005 if (starts_with(ss
->name
, ".ksplice"))
2006 return SS_TYPE_KSPLICE
;
2008 if (starts_with(ss
->name
, ".init"))
2009 return SS_TYPE_IGNORED
;
2010 if (starts_with(ss
->name
, ".security_initcall.init"))
2011 return SS_TYPE_IGNORED
;
2012 if (starts_with(ss
->name
, ".con_initcall.init"))
2013 return SS_TYPE_IGNORED
;
2014 if (starts_with(ss
->name
, ".x86cpuvendor.init"))
2015 return SS_TYPE_IGNORED
;
2016 if (starts_with(ss
->name
, ".early_param.init"))
2017 return SS_TYPE_IGNORED
;
2018 if (starts_with(ss
->name
, ".taglist.init"))
2019 return SS_TYPE_IGNORED
;
2020 if (starts_with(ss
->name
, ".arch.info.init"))
2021 return SS_TYPE_IGNORED
;
2022 if (starts_with(ss
->name
, ".proc.info.init"))
2023 return SS_TYPE_IGNORED
;
2024 /* .pci_fixup_* sections really should be treated as global rodata
2025 referenced only from quirks.c */
2026 if (starts_with(ss
->name
, ".pci_fixup_"))
2027 return SS_TYPE_IGNORED
;
2028 /* .builtin_fw sections are similar to .pci_fixup */
2029 if (starts_with(ss
->name
, ".builtin_fw"))
2030 return SS_TYPE_IGNORED
;
2031 /* same for .tracedata */
2032 if (starts_with(ss
->name
, ".tracedata"))
2033 return SS_TYPE_IGNORED
;
2034 if (starts_with(ss
->name
, ".debug"))
2035 return SS_TYPE_IGNORED
;
2036 /* .eh_frame should probably be discarded, not ignored */
2037 if (starts_with(ss
->name
, ".eh_frame"))
2038 return SS_TYPE_IGNORED
;
2039 if (config
->ignore_devinit
&& starts_with(ss
->name
, ".devinit"))
2040 return SS_TYPE_IGNORED
;
2041 if (config
->ignore_meminit
&& starts_with(ss
->name
, ".meminit"))
2042 return SS_TYPE_IGNORED
;
2043 if (config
->ignore_cpuinit
&& starts_with(ss
->name
, ".cpuinit"))
2044 return SS_TYPE_IGNORED
;
2045 if (config
->ignore_devinit
&& starts_with(ss
->name
, ".devexit"))
2046 return SS_TYPE_IGNORED
;
2047 if (config
->ignore_meminit
&& starts_with(ss
->name
, ".memexit"))
2048 return SS_TYPE_IGNORED
;
2049 if (config
->ignore_cpuinit
&& starts_with(ss
->name
, ".cpuexit"))
2050 return SS_TYPE_IGNORED
;
2051 if (starts_with(ss
->name
, ".vgetcpu_mode") ||
2052 starts_with(ss
->name
, ".jiffies") ||
2053 starts_with(ss
->name
, ".wall_jiffies") ||
2054 starts_with(ss
->name
, ".vxtime") ||
2055 starts_with(ss
->name
, ".sys_tz") ||
2056 starts_with(ss
->name
, ".sysctl_vsyscall") ||
2057 starts_with(ss
->name
, ".xtime") ||
2058 starts_with(ss
->name
, ".xtime_lock") ||
2059 starts_with(ss
->name
, ".vsyscall"))
2060 return SS_TYPE_IGNORED
;
2061 if (starts_with(ss
->name
, ".vdso"))
2062 return SS_TYPE_IGNORED
;
2064 if (bfd_get_section_by_name(ss
->parent
->abfd
, ".exitcall.exit") == NULL
) {
2065 if (starts_with(ss
->name
, ".exit.text"))
2066 return SS_TYPE_TEXT
;
2067 if (starts_with(ss
->name
, ".exit.data"))
2068 return SS_TYPE_DATA
;
2069 } else if (starts_with(ss
->name
, ".exit.text") ||
2070 starts_with(ss
->name
, ".exit.data"))
2071 return SS_TYPE_IGNORED
;
2073 if (starts_with(ss
->name
, ".text") ||
2074 starts_with(ss
->name
, ".kernel.text") ||
2075 starts_with(ss
->name
, ".devinit.text") ||
2076 starts_with(ss
->name
, ".meminit.text") ||
2077 starts_with(ss
->name
, ".cpuinit.text") ||
2078 starts_with(ss
->name
, ".devexit.text") ||
2079 starts_with(ss
->name
, ".memexit.text") ||
2080 starts_with(ss
->name
, ".cpuexit.text") ||
2081 starts_with(ss
->name
, ".ref.text") ||
2082 starts_with(ss
->name
, ".spinlock.text") ||
2083 starts_with(ss
->name
, ".kprobes.text") ||
2084 starts_with(ss
->name
, ".sched.text"))
2085 return SS_TYPE_TEXT
;
2088 if (sscanf(ss
->name
, ".rodata.str%*u.%*u%n", &n
) >= 0 &&
2089 n
== strlen(ss
->name
))
2090 return SS_TYPE_STRING
;
2092 if (starts_with(ss
->name
, ".rodata") ||
2093 starts_with(ss
->name
, ".kernel.rodata") ||
2094 starts_with(ss
->name
, ".devinit.rodata") ||
2095 starts_with(ss
->name
, ".meminit.rodata") ||
2096 starts_with(ss
->name
, ".cpuinit.rodata") ||
2097 starts_with(ss
->name
, ".devexit.rodata") ||
2098 starts_with(ss
->name
, ".memexit.rodata") ||
2099 starts_with(ss
->name
, ".cpuexit.rodata") ||
2100 starts_with(ss
->name
, ".ref.rodata") ||
2101 starts_with(ss
->name
, "__markers_strings"))
2102 return SS_TYPE_RODATA
;
2104 if (starts_with(ss
->name
, ".bss"))
2105 return SS_TYPE_DATA
;
2107 /* Ignore .data.percpu sections */
2108 if (starts_with(ss
->name
, ".data.percpu") ||
2109 starts_with(ss
->name
, ".kernel.data.percpu"))
2110 return SS_TYPE_IGNORED
;
2111 if (starts_with(ss
->name
, ".data") ||
2112 starts_with(ss
->name
, ".kernel.data") ||
2113 starts_with(ss
->name
, ".devinit.data") ||
2114 starts_with(ss
->name
, ".cpuinit.data") ||
2115 starts_with(ss
->name
, ".meminit.data") ||
2116 starts_with(ss
->name
, ".devexit.data") ||
2117 starts_with(ss
->name
, ".memexit.data") ||
2118 starts_with(ss
->name
, ".cpuexit.data") ||
2119 starts_with(ss
->name
, ".ref.data") ||
2120 starts_with(ss
->name
, "__markers"))
2121 return SS_TYPE_DATA
;
2123 /* We replace all the ksymtab strings, so delete them */
2124 if (strcmp(ss
->name
, "__ksymtab_strings") == 0)
2125 return SS_TYPE_IGNORED
;
2126 if (starts_with(ss
->name
, "__ksymtab"))
2127 return SS_TYPE_EXPORT
;
2128 if (starts_with(ss
->name
, "__kcrctab"))
2129 return SS_TYPE_EXPORT
;
2131 if (is_table_section(ss
->name
, true))
2132 return SS_TYPE_SPECIAL
;
2134 if (starts_with(ss
->name
, ".ARM."))
2135 return SS_TYPE_SPECIAL
;
2137 if (starts_with(ss
->name
, ".note"))
2138 return SS_TYPE_IGNORED
;
2139 if (starts_with(ss
->name
, ".comment"))
2140 return SS_TYPE_IGNORED
;
2141 if (starts_with(ss
->name
, "__param"))
2142 return SS_TYPE_IGNORED
;
2143 if (starts_with(ss
->name
, ".exitcall.exit"))
2144 return SS_TYPE_IGNORED
;
2145 if (starts_with(ss
->name
, ".modinfo"))
2146 return SS_TYPE_IGNORED
;
2148 return SS_TYPE_UNKNOWN
;
2151 void initialize_supersect_types(struct superbfd
*sbfd
)
2154 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
2155 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
2156 ss
->type
= supersect_type(ss
);
2157 if (ss
->type
== SS_TYPE_UNKNOWN
) {
2158 err(sbfd
, "Unknown section type: %s\n", ss
->name
);
2164 static void init_label_map(struct superbfd
*sbfd
)
2166 struct label_map
*map
;
2168 vec_init(&sbfd
->maps
);
2172 struct symbol_hash csyms
;
2173 symbol_hash_init(&csyms
);
2176 for (symp
= sbfd
->syms
.data
;
2177 symp
< sbfd
->syms
.data
+ sbfd
->syms
.size
; symp
++) {
2178 asymbol
*csym
= canonical_symbol(sbfd
, *symp
);
2182 assert(asprintf(&key
, "%p", csym
) >= 0);
2183 asymbol
**csymp
= symbol_hash_lookup(&csyms
, key
, TRUE
);
2189 map
= vec_grow(&sbfd
->maps
, 1);
2192 map
->label
= symbol_label(sbfd
, csym
);
2195 struct label_mapp_hash label_maps
;
2196 label_mapp_hash_init(&label_maps
);
2197 for (map
= sbfd
->maps
.data
;
2198 map
< sbfd
->maps
.data
+ sbfd
->maps
.size
; map
++) {
2199 struct label_map
**mapp
=
2200 label_mapp_hash_lookup(&label_maps
, map
->label
, TRUE
);
2201 if (*mapp
== NULL
) {
2206 struct label_map
*first_map
= *mapp
;
2208 if (first_map
->count
== 0) {
2209 assert(asprintf(&buf
, "%s~%d", map
->label
, 0) >= 0);
2210 first_map
->label
= buf
;
2213 assert(asprintf(&buf
, "%s~%d", map
->label
, first_map
->count
)
2218 label_mapp_hash_init(&sbfd
->maps_hash
);
2219 for (map
= sbfd
->maps
.data
;
2220 map
< sbfd
->maps
.data
+ sbfd
->maps
.size
; map
++) {
2222 assert(asprintf(&key
, "%p", map
->csym
) >= 0);
2223 struct label_map
**mapp
=
2224 label_mapp_hash_lookup(&sbfd
->maps_hash
, key
, TRUE
);
2227 map
->orig_label
= map
->label
;
2231 static const char *label_lookup(struct superbfd
*sbfd
, asymbol
*sym
)
2233 asymbol
*csym
= canonical_symbol(sbfd
, sym
);
2235 assert(asprintf(&key
, "%p", csym
) >= 0);
2236 struct label_map
**mapp
=
2237 label_mapp_hash_lookup(&sbfd
->maps_hash
, key
, FALSE
);
2241 return (*mapp
)->label
;
2244 static void print_label_map(struct superbfd
*sbfd
)
2246 struct label_map
*map
;
2247 for (map
= sbfd
->maps
.data
;
2248 map
< sbfd
->maps
.data
+ sbfd
->maps
.size
; map
++) {
2249 if (strcmp(map
->orig_label
, map
->label
) == 0)
2251 debug1(sbfd
, "Label change: %s -> %s\n",
2252 map
->label
, map
->orig_label
);
2256 static void label_map_set(struct superbfd
*sbfd
, const char *oldlabel
,
2259 struct label_map
*map
;
2260 for (map
= sbfd
->maps
.data
;
2261 map
< sbfd
->maps
.data
+ sbfd
->maps
.size
; map
++) {
2262 if (strcmp(map
->orig_label
, oldlabel
) == 0) {
2263 if (strcmp(map
->orig_label
, map
->label
) != 0 &&
2264 strcmp(map
->label
, label
) != 0)
2273 static void init_callers(struct superbfd
*sbfd
)
2275 string_hash_init(&sbfd
->callers
);
2277 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
2278 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
2280 for (relocp
= ss
->relocs
.data
;
2281 relocp
< ss
->relocs
.data
+ ss
->relocs
.size
; relocp
++) {
2282 asymbol
*sym
= *(*relocp
)->sym_ptr_ptr
;
2284 sym
->value
+ get_reloc_offset(ss
, *relocp
, true);
2286 assert(asprintf(&key
, "%s+%lx", sym
->section
->name
,
2288 const char **ret
= string_hash_lookup(&sbfd
->callers
,
2294 *ret
= "*multiple_callers*";
2299 static const char *find_caller(struct supersect
*ss
, asymbol
*sym
)
2302 assert(asprintf(&key
, "%s+%lx", sym
->section
->name
,
2303 (unsigned long)sym
->value
) >= 0);
2304 const char **ret
= string_hash_lookup(&ss
->parent
->callers
, key
, FALSE
);
2308 return "*no_caller*";
2312 static void init_csyms(struct superbfd
*sbfd
)
2314 asymbolpp_hash_init(&sbfd
->csyms
);
2317 for (symp
= sbfd
->syms
.data
; symp
< sbfd
->syms
.data
+ sbfd
->syms
.size
;
2319 asymbol
*sym
= *symp
;
2320 if ((sym
->flags
& BSF_DEBUGGING
) != 0)
2323 assert(asprintf(&key
, "%s+%lx", sym
->section
->name
,
2324 (unsigned long)sym
->value
) >= 0);
2325 asymbol
***csympp
= asymbolpp_hash_lookup(&sbfd
->csyms
, key
,
2328 if (*csympp
== NULL
) {
2332 asymbol
*csym
= **csympp
;
2333 if ((csym
->flags
& BSF_GLOBAL
) != 0)
2335 if ((sym
->flags
& BSF_GLOBAL
) != 0)
2340 static asymbol
**symbolp_scan(struct supersect
*ss
, bfd_vma value
)
2343 assert(asprintf(&key
, "%s+%lx", ss
->name
, (unsigned long)value
) >= 0);
2345 asymbolpp_hash_lookup(&ss
->parent
->csyms
, key
, FALSE
);
2350 /* For section symbols of sections containing no symbols, return the
2351 section symbol that relocations are generated against */
2357 static asymbol
**canonical_symbolp(struct superbfd
*sbfd
, asymbol
*sym
)
2359 if (bfd_is_const_section(sym
->section
)) {
2361 for (csymp
= sbfd
->syms
.data
;
2362 csymp
< sbfd
->syms
.data
+ sbfd
->syms
.size
; csymp
++) {
2368 return symbolp_scan(fetch_supersect(sbfd
, sym
->section
), sym
->value
);
2371 static asymbol
*canonical_symbol(struct superbfd
*sbfd
, asymbol
*sym
)
2373 if (bfd_is_const_section(sym
->section
))
2375 asymbol
**symp
= canonical_symbolp(sbfd
, sym
);
2376 return symp
!= NULL
? *symp
: NULL
;
2379 static char *static_local_symbol(struct superbfd
*sbfd
, asymbol
*sym
)
2381 struct supersect
*ss
= fetch_supersect(sbfd
, sym
->section
);
2382 if ((sym
->flags
& BSF_LOCAL
) == 0 || (sym
->flags
& BSF_OBJECT
) == 0)
2384 char *dot
= strrchr(sym
->name
, '.');
2385 if (dot
== NULL
|| dot
[1 + strspn(dot
+ 1, "0123546789")] != '\0')
2387 char *basename
= strndup(sym
->name
, dot
- sym
->name
);
2389 if (strcmp(basename
, "__func__") == 0 ||
2390 strcmp(basename
, "__PRETTY_FUNCTION__") == 0)
2391 assert(asprintf(&mangled_name
, "%s<%s>", basename
,
2392 (char *)ss
->contents
.data
+ sym
->value
) >= 0);
2394 assert(asprintf(&mangled_name
, "%s<%s>", basename
,
2395 find_caller(ss
, sym
)) >= 0);
2396 return mangled_name
;
2399 static char *symbol_label(struct superbfd
*sbfd
, asymbol
*sym
)
2401 const char *filename
= sbfd
->abfd
->filename
;
2402 char *c
= strstr(filename
, ".KSPLICE");
2403 int flen
= (c
== NULL
? strlen(filename
) : c
- filename
);
2406 if (bfd_is_und_section(sym
->section
) || (sym
->flags
& BSF_GLOBAL
) != 0) {
2407 label
= strdup(sym
->name
);
2408 } else if (bfd_is_const_section(sym
->section
)) {
2409 assert(asprintf(&label
, "%s<%.*s>",
2410 sym
->name
, flen
, filename
) >= 0);
2412 asymbol
*gsym
= canonical_symbol(sbfd
, sym
);
2415 assert(asprintf(&label
, "%s+%lx<%.*s>",
2417 (unsigned long)sym
->value
,
2418 flen
, filename
) >= 0);
2419 else if ((gsym
->flags
& BSF_GLOBAL
) != 0)
2420 label
= strdup(gsym
->name
);
2421 else if (static_local_symbol(sbfd
, gsym
))
2422 assert(asprintf(&label
, "%s+%lx<%.*s>",
2423 static_local_symbol(sbfd
, gsym
),
2424 (unsigned long)sym
->value
,
2425 flen
, filename
) >= 0);
2427 assert(asprintf(&label
, "%s<%.*s>",
2428 gsym
->name
, flen
, filename
) >= 0);
2434 static struct span
*new_span(struct supersect
*ss
, bfd_vma start
, bfd_vma size
)
2436 struct span
*span
= vec_grow(&ss
->spans
, 1);
2438 span
->start
= start
;
2443 asymbol
**symp
= symbolp_scan(ss
, span
->start
);
2445 span
->symbol
= *symp
;
2446 span
->label
= label_lookup(ss
->parent
, span
->symbol
);
2448 span
->symbol
= NULL
;
2449 const char *label
= label_lookup(ss
->parent
, ss
->symbol
);
2450 if (span
->start
!= 0) {
2452 assert(asprintf(&buf
, "%s<span:%lx>", label
,
2453 (unsigned long)span
->start
) >= 0);
2456 span
->label
= label
;
2462 static void initialize_string_spans(struct supersect
*ss
)
2465 for (str
= ss
->contents
.data
;
2466 (void *)str
< ss
->contents
.data
+ ss
->contents
.size
;) {
2467 bfd_vma start
= (unsigned long)str
-
2468 (unsigned long)ss
->contents
.data
;
2469 bfd_vma size
= strlen(str
) + 1;
2470 while ((start
+ size
) % (1 << ss
->alignment
) != 0 &&
2471 start
+ size
< ss
->contents
.size
) {
2472 if (str
[size
] != '\0')
2476 new_span(ss
, start
, size
);
2481 static void initialize_spans(struct superbfd
*sbfd
)
2484 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
2485 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
2486 if (ss
->type
== SS_TYPE_STRING
)
2487 initialize_string_spans(ss
);
2488 else if (!mode("keep") || (ss
->type
!= SS_TYPE_SPECIAL
&&
2489 ss
->type
!= SS_TYPE_EXPORT
))
2490 new_span(ss
, 0, ss
->contents
.size
);
2494 struct span
*reloc_target_span(struct supersect
*ss
, arelent
*reloc
)
2496 asymbol
*sym_ptr
= *reloc
->sym_ptr_ptr
;
2497 if (bfd_is_const_section(sym_ptr
->section
))
2500 bfd_vma addend
= get_reloc_offset(ss
, reloc
, true) + sym_ptr
->value
;
2501 struct supersect
*sym_ss
=
2502 fetch_supersect(ss
->parent
, sym_ptr
->section
);
2503 struct span
*span
, *target_span
= sym_ss
->spans
.data
;
2504 for (span
= sym_ss
->spans
.data
;
2505 span
< sym_ss
->spans
.data
+ sym_ss
->spans
.size
; span
++) {
2506 if (addend
>= span
->start
&& addend
< span
->start
+ span
->size
)
2512 struct span
*reloc_address_span(struct supersect
*ss
, arelent
*reloc
)
2515 for (span
= ss
->spans
.data
; span
< ss
->spans
.data
+ ss
->spans
.size
;
2517 if (reloc
->address
>= span
->start
&&
2518 reloc
->address
< span
->start
+ span
->size
)
2524 void compute_span_shifts(struct superbfd
*sbfd
)
2528 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
2529 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
2532 bfd_size_type offset
= 0;
2533 for (span
= ss
->spans
.data
;
2534 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++) {
2537 span
->shift
= offset
- span
->start
;
2538 offset
+= span
->size
;
2543 void remove_unkept_spans(struct superbfd
*sbfd
)
2547 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
2548 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
2549 struct arelentp_vec orig_relocs
;
2550 vec_move(&orig_relocs
, &ss
->relocs
);
2551 arelent
**relocp
, *reloc
;
2552 for (relocp
= orig_relocs
.data
;
2553 relocp
< orig_relocs
.data
+ orig_relocs
.size
; relocp
++) {
2555 asymbol
*sym
= *reloc
->sym_ptr_ptr
;
2556 span
= reloc_target_span(ss
, reloc
);
2557 if ((span
!= NULL
&& span
->keep
&& span
->shift
== 0) ||
2558 bfd_is_const_section(sym
->section
)) {
2559 *vec_grow(&ss
->relocs
, 1) = reloc
;
2562 if (span
!= NULL
&& span
->keep
) {
2563 arelent
*new_reloc
= malloc(sizeof(*new_reloc
));
2564 *new_reloc
= *reloc
;
2566 get_reloc_offset(ss
, reloc
, false);
2567 new_reloc
->addend
+= span
->shift
;
2568 *vec_grow(&ss
->new_relocs
, 1) = new_reloc
;
2573 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
2574 struct supersect
*ss
= fetch_supersect(sbfd
, sect
), orig_ss
;
2577 supersect_move(&orig_ss
, ss
);
2578 vec_init(&ss
->spans
);
2579 for (span
= orig_ss
.spans
.data
;
2580 span
< orig_ss
.spans
.data
+ orig_ss
.spans
.size
; span
++) {
2583 struct span
*new_span
= vec_grow(&ss
->spans
, 1);
2585 new_span
->start
= span
->start
+ span
->shift
;
2586 new_span
->shift
= 0;
2587 sect_copy(ss
, sect_do_grow(ss
, 1, span
->size
, 1),
2588 &orig_ss
, orig_ss
.contents
.data
+ span
->start
,