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 static bool part_of_reloc(struct supersect
*ss
, unsigned long addr
);
106 static bool nonrelocs_equal(struct supersect
*old_ss
, struct supersect
*new_ss
);
107 static void handle_section_symbol_renames(struct superbfd
*oldsbfd
,
108 struct superbfd
*newsbfd
);
110 enum supersect_type
supersect_type(struct supersect
*ss
);
111 void initialize_supersect_types(struct superbfd
*sbfd
);
112 static void initialize_spans(struct superbfd
*sbfd
);
113 static void initialize_string_spans(struct supersect
*ss
);
114 struct span
*reloc_target_span(struct supersect
*ss
, arelent
*reloc
);
115 struct span
*reloc_address_span(struct supersect
*ss
, arelent
*reloc
);
116 void remove_unkept_spans(struct superbfd
*sbfd
);
117 void compute_span_shifts(struct superbfd
*sbfd
);
118 static struct span
*new_span(struct supersect
*ss
, bfd_vma start
, bfd_vma size
);
119 bool is_table_section(const char *name
, bool consider_other
);
121 void rm_relocs(struct superbfd
*isbfd
);
122 void rm_some_relocs(struct supersect
*ss
);
123 void write_ksplice_reloc(struct supersect
*ss
, arelent
*orig_reloc
);
124 void load_ksplice_symbol_offsets(struct superbfd
*sbfd
);
125 void blot_section(struct supersect
*ss
, int offset
, reloc_howto_type
*howto
);
126 static void write_ksplice_section(struct span
*span
);
127 void write_ksplice_patch(struct superbfd
*sbfd
, const char *sectname
);
128 void write_ksplice_deleted_patch(struct superbfd
*sbfd
, const char *name
,
130 asymbol
**make_undefined_symbolp(struct superbfd
*sbfd
, const char *name
);
131 void filter_table_sections(struct superbfd
*isbfd
);
132 void filter_table_section(struct superbfd
*sbfd
, const struct table_section
*s
);
133 void keep_referenced_sections(struct superbfd
*sbfd
);
134 bfd_boolean
copy_object(bfd
*ibfd
, bfd
*obfd
);
135 void setup_section(bfd
*ibfd
, asection
*isection
, void *obfdarg
);
136 static void setup_new_section(bfd
*obfd
, struct supersect
*ss
);
137 static void write_section(bfd
*obfd
, asection
*osection
, void *arg
);
138 static void delete_obsolete_relocs(struct supersect
*ss
);
139 void mark_symbols_used_in_relocations(bfd
*abfd
, asection
*isection
,
141 static void ss_mark_symbols_used_in_relocations(struct supersect
*ss
);
142 void filter_symbols(bfd
*ibfd
, bfd
*obfd
, struct asymbolp_vec
*osyms
,
143 struct asymbolp_vec
*isyms
);
144 static bool deleted_table_section_symbol(bfd
*abfd
, asymbol
*sym
);
145 void read_str_set(struct str_vec
*strs
);
146 bool str_in_set(const char *str
, const struct str_vec
*strs
);
147 struct supersect
*make_section(struct superbfd
*sbfd
, const char *name
);
148 void __attribute__((format(printf
, 3, 4)))
149 write_string(struct supersect
*ss
, const char **addr
, const char *fmt
, ...);
150 void rm_some_exports(struct superbfd
*isbfd
, const struct export_desc
*ed
);
151 void write_ksplice_export(struct superbfd
*sbfd
, const char *symname
,
152 const char *export_type
, bool del
);
153 void write_reloc(struct supersect
*ss
, const void *addr
, asymbol
**symp
,
155 arelent
*create_reloc(struct supersect
*ss
, const void *addr
, asymbol
**symp
,
157 static void match_global_symbol_sections(struct superbfd
*oldsbfd
,
158 struct superbfd
*newsbfd
);
159 static void match_sections_by_name(struct superbfd
*oldsbfd
,
160 struct superbfd
*newsbfd
);
161 static void match_sections_by_label(struct superbfd
*oldsbfd
,
162 struct superbfd
*newsbfd
);
163 static void mark_new_sections(struct superbfd
*sbfd
);
164 static void handle_deleted_sections(struct superbfd
*oldsbfd
,
165 struct superbfd
*newsbfd
);
166 static void compare_matched_sections(struct superbfd
*sbfd
);
167 static void update_nonzero_offsets(struct superbfd
*sbfd
);
168 static void handle_nonzero_offset_relocs(struct supersect
*ss
);
170 static const char *label_lookup(struct superbfd
*sbfd
, asymbol
*sym
);
171 static void print_label_map(struct superbfd
*sbfd
);
172 static void label_map_set(struct superbfd
*sbfd
, const char *oldlabel
,
174 static void init_label_map(struct superbfd
*sbfd
);
175 static asymbol
**symbolp_scan(struct supersect
*ss
, bfd_vma value
);
176 static void init_csyms(struct superbfd
*sbfd
);
177 static void init_callers(struct superbfd
*sbfd
);
178 static asymbol
*canonical_symbol(struct superbfd
*sbfd
, asymbol
*sym
);
179 static asymbol
**canonical_symbolp(struct superbfd
*sbfd
, asymbol
*sym
);
180 static char *static_local_symbol(struct superbfd
*sbfd
, asymbol
*sym
);
181 static char *symbol_label(struct superbfd
*sbfd
, asymbol
*sym
);
184 #define debug_(sbfd, level, fmt, ...) \
186 if (verbose >= (level)) \
187 printf("%s: " fmt, (sbfd)->abfd->filename, \
190 #define debug0(sbfd, fmt, ...) debug_(sbfd, 0, fmt, ## __VA_ARGS__)
191 #define debug1(sbfd, fmt, ...) debug_(sbfd, 1, fmt, ## __VA_ARGS__)
192 #define err(sbfd, fmt, ...) \
194 fprintf(stderr, "%s: " fmt, (sbfd)->abfd->filename, \
198 struct str_vec delsects
, rmsyms
;
199 struct export_desc_vec exports
;
202 struct ksplice_config
*config
;
204 const char *modestr
, *kid
;
206 struct superbfd
*offsets_sbfd
= NULL
;
208 #define mode(str) starts_with(modestr, str)
210 DECLARE_VEC_TYPE(unsigned long, addr_vec
);
211 DEFINE_HASH_TYPE(struct addr_vec
, addr_vec_hash
,
212 addr_vec_hash_init
, addr_vec_hash_free
, addr_vec_hash_lookup
,
214 struct addr_vec_hash system_map
;
216 struct bool_hash system_map_written
;
217 struct ulong_hash ksplice_symbol_offset
;
218 struct ulong_hash ksplice_string_offset
;
220 void load_system_map()
222 const char *config_dir
= getenv("KSPLICE_CONFIG_DIR");
225 assert(asprintf(&file
, "%s/System.map", config_dir
) >= 0);
226 FILE *fp
= fopen(file
, "r");
228 addr_vec_hash_init(&system_map
);
232 while (fscanf(fp
, "%lx %c %as\n", &addr
, &type
, &sym
) == 3)
233 *vec_grow(addr_vec_hash_lookup(&system_map
, sym
, TRUE
),
238 void load_ksplice_symbol_offsets(struct superbfd
*sbfd
)
240 asection
*sect
= bfd_get_section_by_name(sbfd
->abfd
,
244 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
246 struct ksplice_symbol
*ksym
;
247 for (ksym
= ss
->contents
.data
;
248 (void *)ksym
< ss
->contents
.data
+ ss
->contents
.size
; ksym
++) {
249 const char *label
= read_string(ss
, &ksym
->label
);
250 unsigned long *ksymbol_offp
=
251 ulong_hash_lookup(&ksplice_symbol_offset
, label
, TRUE
);
252 *ksymbol_offp
= addr_offset(ss
, ksym
);
258 char *kmodsrc
= getenv("KSPLICE_KMODSRC"), *offsets_file
;
259 assert(kmodsrc
!= NULL
);
260 assert(asprintf(&offsets_file
, "%s/offsets.o", kmodsrc
) >= 0);
261 bfd
*offsets_bfd
= bfd_openr(offsets_file
, NULL
);
262 assert(offsets_bfd
!= NULL
);
264 assert(bfd_check_format_matches(offsets_bfd
, bfd_object
, &matching
));
265 offsets_sbfd
= fetch_superbfd(offsets_bfd
);
267 asection
*config_sect
= bfd_get_section_by_name(offsets_sbfd
->abfd
,
269 struct supersect
*config_ss
=
270 fetch_supersect(offsets_sbfd
, config_sect
);
272 config
= config_ss
->contents
.data
;
275 bool matchable_data_section(struct supersect
*ss
)
277 if (ss
->type
== SS_TYPE_STRING
)
279 if (ss
->type
== SS_TYPE_RODATA
)
281 if (ss
->type
== SS_TYPE_DATA
&& ss
->relocs
.size
!= 0)
286 bool unchangeable_section(struct supersect
*ss
)
288 if (ss
->type
== SS_TYPE_DATA
)
290 if (ss
->type
== SS_TYPE_IGNORED
&& !starts_with(ss
->name
, ".debug") &&
291 strcmp(ss
->name
, "__ksymtab_strings") != 0)
296 int main(int argc
, char *argv
[])
298 if (getenv("KSPLICE_VERBOSE") != NULL
)
299 verbose
= atoi(getenv("KSPLICE_VERBOSE"));
302 bfd
*ibfd
= bfd_openr(argv
[1], NULL
);
306 assert(bfd_check_format_matches(ibfd
, bfd_object
, &matching
));
308 const char *output_target
= bfd_get_target(ibfd
);
309 bfd
*obfd
= bfd_openw(argv
[2], output_target
);
312 struct superbfd
*isbfd
= fetch_superbfd(ibfd
);
313 init_label_map(isbfd
);
315 bool_hash_init(&system_map_written
);
316 ulong_hash_init(&ksplice_symbol_offset
);
317 ulong_hash_init(&ksplice_string_offset
);
320 if (mode("keep-primary")) {
322 do_keep_primary(isbfd
, argv
[4]);
323 } else if (mode("keep-helper")) {
324 do_keep_helper(isbfd
);
325 } else if (mode("finalize")) {
327 } else if (mode("rmsyms")) {
331 copy_object(ibfd
, obfd
);
333 if (offsets_sbfd
!= NULL
)
334 assert(bfd_close(offsets_sbfd
->abfd
));
335 assert(bfd_close(obfd
));
336 assert(bfd_close(ibfd
));
340 void do_keep_primary(struct superbfd
*isbfd
, const char *pre
)
342 struct bfd
*prebfd
= bfd_openr(pre
, NULL
);
343 assert(prebfd
!= NULL
);
345 assert(bfd_check_format_matches(prebfd
, bfd_object
, &matching
));
347 struct superbfd
*presbfd
= fetch_superbfd(prebfd
);
348 init_label_map(presbfd
);
351 initialize_supersect_types(isbfd
);
352 initialize_supersect_types(presbfd
);
354 match_global_symbol_sections(presbfd
, isbfd
);
355 debug1(isbfd
, "Matched global\n");
356 match_sections_by_name(presbfd
, isbfd
);
357 debug1(isbfd
, "Matched by name\n");
358 match_sections_by_label(presbfd
, isbfd
);
359 debug1(isbfd
, "Matched by label\n");
363 compare_matched_sections(isbfd
);
364 update_nonzero_offsets(isbfd
);
365 mark_new_sections(isbfd
);
369 handle_deleted_sections(presbfd
, isbfd
);
370 handle_section_symbol_renames(presbfd
, isbfd
);
373 compare_exported_symbols(presbfd
, isbfd
, false);
374 compare_exported_symbols(isbfd
, presbfd
, true);
376 initialize_spans(isbfd
);
377 initialize_spans(presbfd
);
379 for (sect
= isbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
380 struct supersect
*ss
= fetch_supersect(isbfd
, sect
);
381 if (ss
->type
!= SS_TYPE_STRING
)
383 asection
*oldsect
= bfd_get_section_by_name(prebfd
, sect
->name
);
386 struct supersect
*old_ss
= fetch_supersect(presbfd
, oldsect
);
387 struct span
*span
, *old_span
;
388 for (span
= ss
->spans
.data
;
389 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++) {
391 for (old_span
= old_ss
->spans
.data
;
392 old_span
< old_ss
->spans
.data
+ old_ss
->spans
.size
;
394 if (strcmp((char *)ss
->contents
.data
+
396 (char *)old_ss
->contents
.data
+
397 old_span
->start
) == 0) {
400 span
->label
= old_span
->label
;
406 assert(bfd_close(prebfd
));
408 for (sect
= isbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
409 struct supersect
*ss
= fetch_supersect(isbfd
, sect
);
411 if (ss
->type
== SS_TYPE_STRING
|| ss
->type
== SS_TYPE_SPECIAL
||
412 ss
->type
== SS_TYPE_EXPORT
)
414 if (ss
->new || ss
->patch
)
418 print_label_map(isbfd
);
420 for (sect
= isbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
421 struct supersect
*ss
= fetch_supersect(isbfd
, sect
);
423 debug0(isbfd
, "Patching section: %s\n", sect
->name
);
426 for (sect
= isbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
427 struct supersect
*ss
= fetch_supersect(isbfd
, sect
);
429 debug0(isbfd
, "New section: %s\n", sect
->name
);
432 const char **sectname
;
433 for (sectname
= delsects
.data
;
434 sectname
< delsects
.data
+ delsects
.size
; sectname
++)
435 debug0(isbfd
, "Deleted section: %s\n", *sectname
);
437 const struct export_desc
*ed
;
438 for (ed
= exports
.data
; ed
< exports
.data
+ exports
.size
; ed
++) {
439 const char **symname
;
440 for (symname
= ed
->names
.data
;
441 symname
< ed
->names
.data
+ ed
->names
.size
; symname
++)
442 debug0(isbfd
, "Export %s (%s): %s\n",
443 ed
->deletion
? "deletion" : "addition",
444 ed
->export_type
, *symname
);
448 for (sect
= isbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
449 struct supersect
*ss
= fetch_supersect(isbfd
, sect
);
450 for (span
= ss
->spans
.data
;
451 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++)
452 span
->keep
= ss
->keep
;
455 filter_table_sections(isbfd
);
456 for (ed
= exports
.data
; ed
< exports
.data
+ exports
.size
; ed
++) {
457 const char **symname
;
458 for (symname
= ed
->names
.data
;
459 symname
< ed
->names
.data
+ ed
->names
.size
; symname
++)
460 write_ksplice_export(isbfd
, *symname
,
461 ed
->export_type
, ed
->deletion
);
463 rm_some_exports(isbfd
, ed
);
466 compute_span_shifts(isbfd
);
468 for (sect
= isbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
469 struct supersect
*ss
= fetch_supersect(isbfd
, sect
);
470 if (!ss
->patch
&& !ss
->new)
474 for (span
= ss
->spans
.data
;
475 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++)
476 write_ksplice_section(span
);
479 write_ksplice_patch(isbfd
, sect
->name
);
483 remove_unkept_spans(isbfd
);
486 void do_keep_helper(struct superbfd
*isbfd
)
490 initialize_supersect_types(isbfd
);
491 initialize_spans(isbfd
);
494 for (sect
= isbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
495 struct supersect
*ss
= fetch_supersect(isbfd
, sect
);
497 if (ss
->type
== SS_TYPE_SPECIAL
|| ss
->type
== SS_TYPE_TEXT
)
502 for (symp
= isbfd
->syms
.data
;
503 symp
< isbfd
->syms
.data
+ isbfd
->syms
.size
; symp
++) {
504 asymbol
*sym
= *symp
;
505 if (!bfd_is_const_section(sym
->section
) &&
506 (sym
->flags
& BSF_GLOBAL
) != 0) {
507 struct supersect
*sym_ss
=
508 fetch_supersect(isbfd
, sym
->section
);
509 if (sym_ss
->type
!= SS_TYPE_IGNORED
)
515 for (sect
= isbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
516 struct supersect
*ss
= fetch_supersect(isbfd
, sect
);
517 for (span
= ss
->spans
.data
;
518 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++)
519 span
->keep
= ss
->keep
;
524 keep_referenced_sections(isbfd
);
527 filter_table_sections(isbfd
);
528 compute_span_shifts(isbfd
);
530 for (sect
= isbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
531 struct supersect
*ss
= fetch_supersect(isbfd
, sect
);
532 asymbol
*sym
= canonical_symbol(isbfd
, sect
->symbol
);
535 if ((sym
->flags
& BSF_WEAK
) != 0)
537 if (bfd_get_section_size(sect
) == 0)
541 if (ss
->type
!= SS_TYPE_TEXT
&& !matchable_data_section(ss
))
545 for (span
= ss
->spans
.data
;
546 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++) {
548 write_ksplice_section(span
);
553 remove_unkept_spans(isbfd
);
556 void do_finalize(struct superbfd
*isbfd
)
559 load_ksplice_symbol_offsets(isbfd
);
561 initialize_supersect_types(isbfd
);
562 initialize_spans(isbfd
);
566 void do_rmsyms(struct superbfd
*isbfd
)
568 read_str_set(&rmsyms
);
571 initialize_supersect_types(isbfd
);
572 initialize_spans(isbfd
);
576 struct export_vec
*get_export_syms(struct superbfd
*sbfd
)
579 struct export_vec
*exports
;
580 exports
= malloc(sizeof(*exports
));
581 assert(exports
!= NULL
);
584 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
585 if (!starts_with(sect
->name
, "__ksymtab") ||
586 ends_with(sect
->name
, "_strings"))
588 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
589 struct kernel_symbol
*sym
;
590 assert(ss
->contents
.size
* 2 == ss
->relocs
.size
*
591 sizeof(struct kernel_symbol
));
592 for (sym
= ss
->contents
.data
;
593 (void *)sym
< ss
->contents
.data
+ ss
->contents
.size
;
595 struct export
*exp
= vec_grow(exports
, 1);
597 read_string(ss
, (const char *const *)&sym
->name
);
604 struct export_desc
*new_export_desc(struct supersect
*ss
, bool deletion
)
606 struct export_desc
*ed
= vec_grow(&exports
, 1);
607 ed
->deletion
= deletion
;
608 vec_init(&ed
->names
);
609 ed
->export_type
= strdup(ss
->name
) + strlen("__ksymtab");
612 assert(asprintf(&crc_sect_name
, "__kcrctab%s", ed
->export_type
) >= 0);
614 bfd_get_section_by_name(ss
->parent
->abfd
, crc_sect_name
);
615 if (crc_sect
== NULL
)
618 ed
->crc_ss
= fetch_supersect(ss
->parent
, crc_sect
);
622 void compare_exported_symbols(struct superbfd
*oldsbfd
,
623 struct superbfd
*newsbfd
, bool deletion
)
625 struct export_vec
*new_exports
, *old_exports
;
626 new_exports
= get_export_syms(newsbfd
);
627 if (new_exports
== NULL
)
629 old_exports
= get_export_syms(oldsbfd
);
630 struct export
*old
, *new;
631 struct supersect
*last_ss
= NULL
;
632 struct export_desc
*ed
= NULL
;
633 for (new = new_exports
->data
; new < new_exports
->data
+
634 new_exports
->size
; new++) {
636 if (old_exports
!= NULL
) {
637 for (old
= old_exports
->data
; old
< old_exports
->data
+
638 old_exports
->size
; old
++) {
639 if (strcmp(new->name
, old
->name
) == 0 &&
640 strcmp(new->ss
->name
, old
->ss
->name
) == 0) {
646 if (last_ss
!= new->ss
) {
648 ed
= new_export_desc(new->ss
, deletion
);
651 *vec_grow(&ed
->names
, 1) = new->name
;
655 void match_sections(struct supersect
*oldss
, struct supersect
*newss
)
657 if (oldss
->match
== newss
&& newss
->match
== oldss
)
659 if (oldss
->match
!= NULL
) {
660 err(newss
->parent
, "Matching conflict: old %s: %s != %s\n",
661 oldss
->name
, oldss
->match
->name
, newss
->name
);
664 if (newss
->match
!= NULL
) {
665 err(newss
->parent
, "Matching conflict: new %s: %s != %s\n",
666 newss
->name
, newss
->match
->name
, oldss
->name
);
669 oldss
->match
= newss
;
670 newss
->match
= oldss
;
671 debug1(newss
->parent
, "Matched old %s to new %s\n",
672 oldss
->name
, newss
->name
);
675 static void match_global_symbol_sections(struct superbfd
*oldsbfd
,
676 struct superbfd
*newsbfd
)
678 asymbol
**oldsymp
, **newsymp
;
679 for (oldsymp
= oldsbfd
->syms
.data
;
680 oldsymp
< oldsbfd
->syms
.data
+ oldsbfd
->syms
.size
; oldsymp
++) {
681 asymbol
*oldsym
= *oldsymp
;
682 if ((oldsym
->flags
& BSF_GLOBAL
) == 0 ||
683 bfd_is_const_section(oldsym
->section
))
685 for (newsymp
= newsbfd
->syms
.data
;
686 newsymp
< newsbfd
->syms
.data
+ newsbfd
->syms
.size
;
688 asymbol
*newsym
= *newsymp
;
689 if ((newsym
->flags
& BSF_GLOBAL
) == 0 ||
690 bfd_is_const_section(oldsym
->section
))
692 if (strcmp(oldsym
->name
, newsym
->name
) != 0)
694 struct supersect
*oldss
=
695 fetch_supersect(oldsbfd
, oldsym
->section
);
696 struct supersect
*newss
=
697 fetch_supersect(newsbfd
, newsym
->section
);
698 match_sections(oldss
, newss
);
703 static void match_sections_by_name(struct superbfd
*oldsbfd
,
704 struct superbfd
*newsbfd
)
706 asection
*newp
, *oldp
;
707 for (newp
= newsbfd
->abfd
->sections
; newp
!= NULL
; newp
= newp
->next
) {
708 struct supersect
*newss
= fetch_supersect(newsbfd
, newp
);
709 oldp
= bfd_get_section_by_name(oldsbfd
->abfd
, newp
->name
);
710 if (oldp
== NULL
|| newss
->type
== SS_TYPE_STRING
||
711 newss
->type
== SS_TYPE_SPECIAL
||
712 newss
->type
== SS_TYPE_EXPORT
)
714 if (static_local_symbol(newsbfd
,
715 canonical_symbol(newsbfd
,
719 struct supersect
*oldss
= fetch_supersect(oldsbfd
, oldp
);
720 match_sections(oldss
, newss
);
724 static void match_sections_by_label(struct superbfd
*oldsbfd
,
725 struct superbfd
*newsbfd
)
727 asection
*oldsect
, *newsect
;
728 struct supersect
*oldss
, *newss
;
729 for (newsect
= newsbfd
->abfd
->sections
; newsect
!= NULL
;
730 newsect
= newsect
->next
) {
731 newss
= fetch_supersect(newsbfd
, newsect
);
732 if (newss
->type
== SS_TYPE_STRING
||
733 newss
->type
== SS_TYPE_SPECIAL
||
734 newss
->type
== SS_TYPE_EXPORT
)
736 for (oldsect
= oldsbfd
->abfd
->sections
; oldsect
!= NULL
;
737 oldsect
= oldsect
->next
) {
738 if (strcmp(label_lookup(newsbfd
, newsect
->symbol
),
739 label_lookup(oldsbfd
, oldsect
->symbol
)) != 0)
741 oldss
= fetch_supersect(oldsbfd
, oldsect
);
742 match_sections(oldss
, newss
);
747 static void mark_new_sections(struct superbfd
*sbfd
)
750 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
751 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
752 if (ss
->type
== SS_TYPE_STRING
|| ss
->type
== SS_TYPE_SPECIAL
||
753 ss
->type
== SS_TYPE_IGNORED
|| ss
->type
== SS_TYPE_EXPORT
)
755 if (ss
->match
== NULL
)
760 static void handle_deleted_sections(struct superbfd
*oldsbfd
,
761 struct superbfd
*newsbfd
)
764 for (sect
= oldsbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
765 struct supersect
*ss
= fetch_supersect(oldsbfd
, sect
);
766 if (ss
->type
!= SS_TYPE_TEXT
)
768 if (ss
->match
!= NULL
)
770 const char *label
= label_lookup(oldsbfd
, sect
->symbol
);
771 *vec_grow(&delsects
, 1) = label
;
772 asymbol
*csym
= canonical_symbol(oldsbfd
, sect
->symbol
);
773 write_ksplice_deleted_patch(newsbfd
, csym
->name
, label
);
777 static void handle_nonzero_offset_relocs(struct supersect
*ss
)
780 for (i
= 0; i
< ss
->relocs
.size
; i
++) {
781 asymbol
*sym
= *ss
->relocs
.data
[i
]->sym_ptr_ptr
;
782 bfd_vma offset
= get_reloc_offset(ss
, ss
->relocs
.data
[i
], true);
783 if (sym
->value
+ offset
== 0)
785 if (bfd_is_const_section(sym
->section
))
787 struct supersect
*sym_ss
= fetch_supersect(ss
->parent
,
789 if (sym_ss
->type
!= SS_TYPE_TEXT
)
791 if (!sym_ss
->patch
) {
794 "Changing %s because a relocation from sect %s "
795 "has a nonzero offset %lx+%lx into it\n",
796 sym_ss
->name
, ss
->name
,
797 (unsigned long)sym
->value
,
798 (unsigned long)offset
);
800 sym_ss
->patch
= true;
804 static void update_nonzero_offsets(struct superbfd
*sbfd
)
807 struct supersect
*ss
;
809 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
810 ss
= fetch_supersect(sbfd
, sect
);
811 if (ss
->new || ss
->patch
)
812 handle_nonzero_offset_relocs(ss
);
816 static void compare_matched_sections(struct superbfd
*newsbfd
)
819 struct supersect
*old_ss
, *new_ss
;
820 for (newp
= newsbfd
->abfd
->sections
; newp
!= NULL
; newp
= newp
->next
) {
821 new_ss
= fetch_supersect(newsbfd
, newp
);
822 if (new_ss
->match
== NULL
)
824 old_ss
= new_ss
->match
;
826 if (nonrelocs_equal(old_ss
, new_ss
) &&
827 all_relocs_equal(old_ss
, new_ss
))
831 if (new_ss
->contents
.size
!= old_ss
->contents
.size
)
832 reason
= "differing sizes";
833 else if (memcmp(new_ss
->contents
.data
, old_ss
->contents
.data
,
834 new_ss
->contents
.size
) != 0)
835 reason
= "differing contents";
837 reason
= "differing relocations";
838 if (new_ss
->type
== SS_TYPE_TEXT
) {
841 new_ss
->patch
= true;
842 debug1(newsbfd
, "Changing %s due to %s\n", new_ss
->name
,
845 debug1(newsbfd
, "Unmatching %s and %s due to %s\n",
846 old_ss
->name
, new_ss
->name
, reason
);
847 new_ss
->match
= NULL
;
848 old_ss
->match
= NULL
;
851 if (unchangeable_section(new_ss
))
852 err(newsbfd
, "warning: ignoring change to nonpatchable "
853 "section %s\n", new_ss
->name
);
857 static void handle_section_symbol_renames(struct superbfd
*oldsbfd
,
858 struct superbfd
*newsbfd
)
860 asection
*newp
, *oldp
;
861 for (newp
= newsbfd
->abfd
->sections
; newp
!= NULL
; newp
= newp
->next
) {
862 struct supersect
*newss
= fetch_supersect(newsbfd
, newp
);
863 if (newss
->match
== NULL
)
865 oldp
= bfd_get_section_by_name(oldsbfd
->abfd
,
870 const char *old_label
= label_lookup(oldsbfd
, oldp
->symbol
);
871 const char *new_label
= label_lookup(newsbfd
, newp
->symbol
);
873 if (strcmp(old_label
, new_label
) == 0)
875 label_map_set(newsbfd
, new_label
, old_label
);
879 static bool part_of_reloc(struct supersect
*ss
, unsigned long addr
)
882 for (relocp
= ss
->relocs
.data
;
883 relocp
< ss
->relocs
.data
+ ss
->relocs
.size
; relocp
++) {
884 arelent
*reloc
= *relocp
;
885 if (addr
>= reloc
->address
&&
886 addr
< reloc
->address
+ reloc
->howto
->size
)
892 static bool nonrelocs_equal(struct supersect
*old_ss
, struct supersect
*new_ss
)
895 if (old_ss
->contents
.size
!= new_ss
->contents
.size
)
897 const unsigned char *old
= old_ss
->contents
.data
;
898 const unsigned char *new = new_ss
->contents
.data
;
899 for (i
= 0; i
< old_ss
->contents
.size
; i
++) {
900 if (old
[i
] != new[i
] &&
901 !(part_of_reloc(old_ss
, i
) && part_of_reloc(new_ss
, i
)))
907 bool relocs_equal(struct supersect
*old_src_ss
, struct supersect
*new_src_ss
,
908 arelent
*old_reloc
, arelent
*new_reloc
)
910 if (old_reloc
->address
!= new_reloc
->address
)
913 struct superbfd
*oldsbfd
= old_src_ss
->parent
;
914 struct superbfd
*newsbfd
= new_src_ss
->parent
;
915 asymbol
*old_sym
= *old_reloc
->sym_ptr_ptr
;
916 asymbol
*new_sym
= *new_reloc
->sym_ptr_ptr
;
917 asection
*old_sect
= old_sym
->section
;
918 asection
*new_sect
= new_sym
->section
;
920 bfd_vma old_offset
= get_reloc_offset(old_src_ss
, old_reloc
, true);
921 bfd_vma new_offset
= get_reloc_offset(new_src_ss
, new_reloc
, true);
923 if (bfd_is_und_section(old_sect
) || bfd_is_und_section(new_sect
)) {
924 if (!bfd_is_und_section(new_sect
) && old_offset
!= 0 &&
925 fetch_supersect(newsbfd
, new_sect
)->type
== SS_TYPE_TEXT
)
928 if (!bfd_is_und_section(new_sect
) && new_offset
!= 0 &&
929 fetch_supersect(oldsbfd
, old_sect
)->type
== SS_TYPE_TEXT
)
932 return strcmp(old_sym
->name
, new_sym
->name
) == 0 &&
933 old_offset
== new_offset
;
936 if (bfd_is_const_section(old_sect
) || bfd_is_const_section(new_sect
))
939 struct supersect
*old_ss
= fetch_supersect(oldsbfd
, old_sect
);
940 struct supersect
*new_ss
= fetch_supersect(newsbfd
, new_sect
);
942 if (old_ss
->type
== SS_TYPE_STRING
&&
943 /* check it's not an out-of-range relocation to a string;
944 we'll just compare entire sections for them */
945 !(old_offset
>= old_ss
->contents
.size
||
946 new_offset
>= new_ss
->contents
.size
)) {
947 if (strcmp(old_ss
->contents
.data
+ old_sym
->value
+ old_offset
,
948 new_ss
->contents
.data
+ new_sym
->value
+ new_offset
)
950 debug0(newsbfd
, "Section %s/%s has string difference "
951 "\"%s\"/\"%s\"\n", old_src_ss
->name
,
953 (const char *)(old_ss
->contents
.data
+
954 old_sym
->value
+ old_offset
),
955 (const char *)(new_ss
->contents
.data
+
956 new_sym
->value
+ new_offset
));
957 debug1(newsbfd
, "Strings differ between %s and %s\n",
958 old_src_ss
->name
, new_src_ss
->name
);
964 if (old_ss
->match
!= new_ss
|| new_ss
->match
!= old_ss
) {
965 debug1(newsbfd
, "Nonmatching relocs from %s to %s/%s\n",
966 new_src_ss
->name
, new_ss
->name
, old_ss
->name
);
970 if (old_sym
->value
+ old_offset
!= new_sym
->value
+ new_offset
) {
971 debug1(newsbfd
, "Offsets to %s/%s differ between %s "
972 "and %s: %lx+%lx/%lx+%lx\n", old_ss
->name
,
973 new_ss
->name
, old_src_ss
->name
, new_src_ss
->name
,
974 (unsigned long)old_sym
->value
, (unsigned long)old_offset
,
975 (unsigned long)new_sym
->value
,
976 (unsigned long)new_offset
);
980 if ((old_sym
->value
+ old_offset
!= 0 ||
981 new_sym
->value
+ new_offset
!= 0) && new_ss
->patch
) {
982 debug1(newsbfd
, "Relocation from %s to nonzero offsets "
983 "%lx+%lx/%lx+%lx in changed section %s\n",
984 new_src_ss
->name
, (unsigned long)old_sym
->value
,
985 (unsigned long)old_offset
, (unsigned long)new_sym
->value
,
986 (unsigned long)new_offset
, new_sym
->section
->name
);
992 bool all_relocs_equal(struct supersect
*old_ss
, struct supersect
*new_ss
)
994 if (old_ss
->relocs
.size
!= new_ss
->relocs
.size
) {
995 debug1(new_ss
->parent
, "Different reloc count between %s and "
996 "%s\n", old_ss
->name
, new_ss
->name
);
1001 for (i
= 0; i
< old_ss
->relocs
.size
; i
++) {
1002 if (!relocs_equal(old_ss
, new_ss
, old_ss
->relocs
.data
[i
],
1003 new_ss
->relocs
.data
[i
]))
1010 void rm_some_exports(struct superbfd
*sbfd
, const struct export_desc
*ed
)
1012 struct supersect
*ss
= ed
->sym_ss
;
1013 struct supersect
*crc_ss
= ed
->crc_ss
;
1015 assert(ss
->contents
.size
* sizeof(unsigned long) ==
1016 crc_ss
->contents
.size
* sizeof(struct kernel_symbol
));
1018 struct kernel_symbol
*ksym
;
1019 unsigned long *crc
= NULL
;
1021 crc
= crc_ss
->contents
.data
;
1022 struct span
*span
, *crc_span
;
1023 for (ksym
= ss
->contents
.data
;
1024 (void *)ksym
< ss
->contents
.data
+ ss
->contents
.size
;
1027 read_reloc(ss
, &ksym
->value
, sizeof(ksym
->value
), &sym
);
1028 span
= new_span(ss
, addr_offset(ss
, ksym
), sizeof(*ksym
));
1029 span
->keep
= str_in_set(sym
->name
, &ed
->names
);
1031 if (crc_ss
!= NULL
) {
1032 crc_span
= new_span(crc_ss
, addr_offset(crc_ss
, crc
),
1034 crc_span
->keep
= span
->keep
;
1038 /* Replace name with a mangled name */
1039 write_string(ss
, (const char **)&ksym
->name
,
1040 "DISABLED_%s_%s", sym
->name
, kid
);
1045 void rm_relocs(struct superbfd
*isbfd
)
1048 for (p
= isbfd
->abfd
->sections
; p
!= NULL
; p
= p
->next
) {
1049 struct supersect
*ss
= fetch_supersect(isbfd
, p
);
1050 if ((mode("keep") && ss
->type
== SS_TYPE_SPECIAL
) ||
1051 ss
->type
== SS_TYPE_KSPLICE
)
1053 if (ss
->keep
|| mode("rmsyms"))
1056 if (mode("finalize")) {
1057 p
= bfd_get_section_by_name(isbfd
->abfd
, ".ksplice_patches");
1059 struct supersect
*ss
= fetch_supersect(isbfd
, p
);
1062 p
= bfd_get_section_by_name(isbfd
->abfd
, ".ksplice_relocs");
1064 struct supersect
*ss
= fetch_supersect(isbfd
, p
);
1070 void rm_some_relocs(struct supersect
*ss
)
1072 struct arelentp_vec orig_relocs
;
1073 vec_move(&orig_relocs
, &ss
->relocs
);
1076 for (relocp
= orig_relocs
.data
;
1077 relocp
< orig_relocs
.data
+ orig_relocs
.size
; relocp
++) {
1078 bool rm_reloc
= false;
1079 asymbol
*sym_ptr
= *(*relocp
)->sym_ptr_ptr
;
1081 if (mode("rmsyms") && str_in_set(sym_ptr
->name
, &rmsyms
) &&
1082 bfd_is_und_section(sym_ptr
->section
))
1088 if (mode("keep-primary") &&
1089 (bfd_is_const_section(sym_ptr
->section
) ||
1090 fetch_supersect(ss
->parent
, sym_ptr
->section
)->new ||
1091 reloc_target_span(ss
, *relocp
)->new ||
1092 !reloc_address_span(ss
, *relocp
)->keep
))
1095 if (mode("finalize") && bfd_is_und_section(sym_ptr
->section
))
1098 if (strcmp(sym_ptr
->name
, "mcount") == 0 &&
1099 bfd_is_und_section(sym_ptr
->section
))
1103 write_ksplice_reloc(ss
, *relocp
);
1105 *vec_grow(&ss
->relocs
, 1) = *relocp
;
1109 struct supersect
*make_section(struct superbfd
*sbfd
, const char *name
)
1111 asection
*sect
= bfd_get_section_by_name(sbfd
->abfd
, name
);
1113 return fetch_supersect(sbfd
, sect
);
1115 return new_supersect(sbfd
, name
);
1118 arelent
*create_reloc(struct supersect
*ss
, const void *addr
, asymbol
**symp
,
1121 bfd_reloc_code_real_type code
;
1122 switch (bfd_arch_bits_per_address(ss
->parent
->abfd
)) {
1124 code
= BFD_RELOC_32
;
1127 code
= BFD_RELOC_64
;
1133 arelent
*reloc
= malloc(sizeof(*reloc
));
1134 reloc
->sym_ptr_ptr
= symp
;
1135 reloc
->address
= addr_offset(ss
, addr
);
1136 reloc
->howto
= bfd_reloc_type_lookup(ss
->parent
->abfd
, code
);
1137 reloc
->addend
= offset
;
1141 void write_reloc(struct supersect
*ss
, const void *addr
, asymbol
**symp
,
1144 *vec_grow(&ss
->new_relocs
, 1) = create_reloc(ss
, addr
, symp
, offset
);
1147 void write_string(struct supersect
*ss
, const char **addr
, const char *fmt
, ...)
1150 struct supersect
*str_ss
= make_section(ss
->parent
, ".ksplice_str");
1153 int len
= vasprintf(&str
, fmt
, ap
);
1157 unsigned long *str_offp
= ulong_hash_lookup(&ksplice_string_offset
, str
,
1159 if (str_offp
== NULL
) {
1160 char *buf
= sect_grow(str_ss
, len
+ 1, char);
1161 memcpy(buf
, str
, len
+ 1);
1162 str_offp
= ulong_hash_lookup(&ksplice_string_offset
, str
, TRUE
);
1163 *str_offp
= addr_offset(str_ss
, buf
);
1166 write_reloc(ss
, addr
, &str_ss
->symbol
, *str_offp
);
1169 void lookup_system_map(struct addr_vec
*addrs
, const char *name
, long offset
)
1171 struct addr_vec
*map_addrs
=
1172 addr_vec_hash_lookup(&system_map
, name
, FALSE
);
1173 if (map_addrs
== NULL
)
1176 unsigned long *addr
, *map_addr
;
1177 for (map_addr
= map_addrs
->data
;
1178 map_addr
< map_addrs
->data
+ map_addrs
->size
; map_addr
++) {
1179 for (addr
= addrs
->data
; addr
< addrs
->data
+ addrs
->size
;
1181 if (*addr
== *map_addr
+ offset
)
1184 if (addr
< addrs
->data
+ addrs
->size
)
1186 *vec_grow(addrs
, 1) = *map_addr
+ offset
;
1190 void compute_system_map_array(struct superbfd
*sbfd
, struct addr_vec
*addrs
,
1193 if (bfd_is_abs_section(sym
->section
)) {
1194 *vec_grow(addrs
, 1) = sym
->value
;
1195 } else if (bfd_is_und_section(sym
->section
)) {
1196 lookup_system_map(addrs
, sym
->name
, 0);
1197 } else if (!bfd_is_const_section(sym
->section
)) {
1199 for (gsymp
= sbfd
->syms
.data
;
1200 gsymp
< sbfd
->syms
.data
+ sbfd
->syms
.size
; gsymp
++) {
1201 asymbol
*gsym
= *gsymp
;
1202 if ((gsym
->flags
& BSF_DEBUGGING
) == 0 &&
1203 gsym
->section
== sym
->section
)
1204 lookup_system_map(addrs
, gsym
->name
,
1205 sym
->value
- gsym
->value
);
1210 void write_ksplice_system_map(struct superbfd
*sbfd
, asymbol
*sym
,
1213 bool *done
= bool_hash_lookup(&system_map_written
, label
, TRUE
);
1218 struct addr_vec addrs
;
1221 compute_system_map_array(sbfd
, &addrs
, sym
);
1222 if (addrs
.size
!= 0) {
1223 struct supersect
*smap_ss
=
1224 make_section(sbfd
, ".ksplice_system_map");
1225 struct ksplice_system_map
*smap
=
1226 sect_grow(smap_ss
, 1, struct ksplice_system_map
);
1227 write_string(smap_ss
, &smap
->label
, "%s", label
);
1229 struct supersect
*array_ss
= make_section(sbfd
,
1231 void *buf
= sect_grow(array_ss
, addrs
.size
,
1232 typeof(*addrs
.data
));
1233 memcpy(buf
, addrs
.data
, addrs
.size
* sizeof(*addrs
.data
));
1234 smap
->nr_candidates
= addrs
.size
;
1235 write_reloc(smap_ss
, &smap
->candidates
, &array_ss
->symbol
,
1236 addr_offset(array_ss
, buf
));
1241 void write_ksplice_symbol_backend(struct supersect
*ss
,
1242 struct ksplice_symbol
*const *addr
,
1243 asymbol
*sym
, const char *label
,
1246 struct supersect
*ksymbol_ss
= make_section(ss
->parent
,
1247 ".ksplice_symbols");
1248 struct ksplice_symbol
*ksymbol
;
1249 unsigned long *ksymbol_offp
;
1251 ksymbol_offp
= ulong_hash_lookup(&ksplice_symbol_offset
, label
, FALSE
);
1252 if (ksymbol_offp
!= NULL
) {
1253 write_reloc(ss
, addr
, &ksymbol_ss
->symbol
, *ksymbol_offp
);
1256 ksymbol
= sect_grow(ksymbol_ss
, 1, struct ksplice_symbol
);
1257 ksymbol_offp
= ulong_hash_lookup(&ksplice_symbol_offset
, label
, TRUE
);
1258 *ksymbol_offp
= addr_offset(ksymbol_ss
, ksymbol
);
1260 write_reloc(ss
, addr
, &ksymbol_ss
->symbol
, *ksymbol_offp
);
1261 write_string(ksymbol_ss
, &ksymbol
->label
, "%s", label
);
1263 write_string(ksymbol_ss
, &ksymbol
->name
, "%s", name
);
1264 write_ksplice_system_map(ksymbol_ss
->parent
, sym
, label
);
1268 void write_ksplice_symbol(struct supersect
*ss
,
1269 struct ksplice_symbol
*const *addr
,
1270 asymbol
*sym
, struct span
*span
,
1271 const char *addstr_sect
)
1273 const char *label
, *name
;
1275 if (span
!= NULL
&& span
->start
!= 0)
1276 label
= span
->label
;
1278 label
= label_lookup(ss
->parent
, sym
);
1280 assert(asprintf(&output
, "%s%s", label
, addstr_sect
) >= 0);
1282 asymbol
*gsym
= canonical_symbol(ss
->parent
, sym
);
1283 if (strcmp(addstr_sect
, "") != 0)
1285 else if (bfd_is_und_section(sym
->section
))
1287 else if (bfd_is_const_section(sym
->section
))
1289 else if (span
!= NULL
&& span
->symbol
== NULL
)
1291 else if (gsym
== NULL
|| (gsym
->flags
& BSF_SECTION_SYM
) != 0)
1296 write_ksplice_symbol_backend(ss
, addr
, sym
, output
, name
);
1299 void write_ksplice_reloc(struct supersect
*ss
, arelent
*orig_reloc
)
1301 asymbol
*sym_ptr
= *orig_reloc
->sym_ptr_ptr
;
1302 reloc_howto_type
*howto
= orig_reloc
->howto
;
1303 bfd_vma addend
= get_reloc_offset(ss
, orig_reloc
, false);
1304 unsigned long *repladdr
= ss
->contents
.data
+ orig_reloc
->address
;
1306 if (mode("finalize") && strcmp(ss
->name
, ".ksplice_patches") == 0) {
1310 if (mode("finalize") && strcmp(ss
->name
, ".ksplice_relocs") == 0) {
1311 assert(starts_with(sym_ptr
->name
, KSPLICE_SYMBOL_STR
));
1313 fake_sym
.name
= sym_ptr
->name
+ strlen(KSPLICE_SYMBOL_STR
);
1314 fake_sym
.section
= bfd_und_section_ptr
;
1318 write_ksplice_symbol_backend
1319 (ss
, (struct ksplice_symbol
**)repladdr
, &fake_sym
,
1320 fake_sym
.name
, fake_sym
.name
);
1324 struct span
*span
= reloc_target_span(ss
, orig_reloc
);
1325 if (span
== ss
->spans
.data
&& span
->start
!= addend
)
1327 blot_section(ss
, orig_reloc
->address
, howto
);
1329 struct supersect
*kreloc_ss
= make_section(ss
->parent
,
1331 ".ksplice_init_relocs" :
1333 struct ksplice_reloc
*kreloc
= sect_grow(kreloc_ss
, 1,
1334 struct ksplice_reloc
);
1336 struct span
*address_span
= reloc_address_span(ss
, orig_reloc
);
1337 write_reloc(kreloc_ss
, &kreloc
->blank_addr
,
1338 &ss
->symbol
, orig_reloc
->address
+ address_span
->shift
);
1339 if (bfd_is_und_section(sym_ptr
->section
) && mode("keep")) {
1341 assert(asprintf(&name
, KSPLICE_SYMBOL_STR
"%s", sym_ptr
->name
)
1343 asymbol
**symp
= make_undefined_symbolp(ss
->parent
, name
);
1344 write_reloc(kreloc_ss
, &kreloc
->symbol
, symp
, 0);
1346 write_ksplice_symbol(kreloc_ss
, &kreloc
->symbol
, sym_ptr
, span
,
1349 kreloc
->pcrel
= howto
->pc_relative
;
1350 if (span
!= NULL
&& span
->start
!= 0)
1351 addend
+= sym_ptr
->value
- span
->start
;
1352 kreloc
->addend
= addend
;
1353 kreloc
->size
= bfd_get_reloc_size(howto
);
1354 kreloc
->dst_mask
= howto
->dst_mask
;
1355 kreloc
->rightshift
= howto
->rightshift
;
1356 kreloc
->signed_addend
=
1357 (howto
->complain_on_overflow
== complain_overflow_signed
) ||
1358 (howto
->complain_on_overflow
== complain_overflow_bitfield
);
1361 #define CANARY(x, canary) ((x & ~howto->dst_mask) | (canary & howto->dst_mask))
1363 void blot_section(struct supersect
*ss
, int offset
, reloc_howto_type
*howto
)
1365 int bits
= bfd_get_reloc_size(howto
) * 8;
1366 void *address
= ss
->contents
.data
+ offset
;
1367 bfd_vma x
= bfd_get(bits
, ss
->parent
->abfd
, address
);
1368 x
= (x
& ~howto
->dst_mask
) |
1369 ((bfd_vma
)KSPLICE_CANARY
& howto
->dst_mask
);
1370 bfd_put(bits
, ss
->parent
->abfd
, x
, address
);
1373 static void write_ksplice_section(struct span
*span
)
1375 struct supersect
*ss
= span
->ss
;
1376 struct supersect
*ksect_ss
=
1377 make_section(ss
->parent
, ".ksplice_sections");
1378 struct ksplice_section
*ksect
= sect_grow(ksect_ss
, 1,
1379 struct ksplice_section
);
1380 asymbol
*sym
= span
->symbol
== NULL
? ss
->symbol
: span
->symbol
;
1382 write_ksplice_symbol(ksect_ss
, &ksect
->symbol
, sym
, span
,
1383 mode("keep-primary") ? "(post)" : "");
1384 ksect
->size
= span
->size
;
1387 if (ss
->type
== SS_TYPE_RODATA
|| ss
->type
== SS_TYPE_STRING
)
1388 ksect
->flags
|= KSPLICE_SECTION_RODATA
;
1389 if (ss
->type
== SS_TYPE_DATA
)
1390 ksect
->flags
|= KSPLICE_SECTION_DATA
;
1391 if (ss
->type
== SS_TYPE_TEXT
)
1392 ksect
->flags
|= KSPLICE_SECTION_TEXT
;
1393 assert(ksect
->flags
!= 0);
1394 write_reloc(ksect_ss
, &ksect
->address
, &ss
->symbol
,
1395 span
->start
+ span
->shift
);
1398 void write_ksplice_patch(struct superbfd
*sbfd
, const char *sectname
)
1400 struct supersect
*kpatch_ss
= make_section(sbfd
, ".ksplice_patches");
1401 struct ksplice_patch
*kpatch
= sect_grow(kpatch_ss
, 1,
1402 struct ksplice_patch
);
1403 asection
*sect
= bfd_get_section_by_name(sbfd
->abfd
, sectname
);
1404 assert(sect
!= NULL
);
1406 write_string(kpatch_ss
, &kpatch
->label
, "%s",
1407 label_lookup(sbfd
, sect
->symbol
));
1408 write_reloc(kpatch_ss
, &kpatch
->repladdr
, §
->symbol
, 0);
1411 asymbol
**make_undefined_symbolp(struct superbfd
*sbfd
, const char *name
)
1414 for (symp
= sbfd
->syms
.data
; symp
< sbfd
->syms
.data
+ sbfd
->syms
.size
;
1416 asymbol
*sym
= *symp
;
1417 if (strcmp(name
, sym
->name
) == 0 &&
1418 bfd_is_und_section(sym
->section
))
1422 for (sympp
= sbfd
->new_syms
.data
;
1423 sympp
< sbfd
->new_syms
.data
+ sbfd
->new_syms
.size
; sympp
++) {
1424 asymbol
**symp
= *sympp
;
1425 asymbol
*sym
= *symp
;
1426 if (strcmp(name
, sym
->name
) == 0 &&
1427 bfd_is_und_section(sym
->section
))
1431 symp
= malloc(sizeof(*symp
));
1432 *symp
= bfd_make_empty_symbol(sbfd
->abfd
);
1433 asymbol
*sym
= *symp
;
1435 sym
->section
= bfd_und_section_ptr
;
1438 *vec_grow(&sbfd
->new_syms
, 1) = symp
;
1442 void write_ksplice_deleted_patch(struct superbfd
*sbfd
, const char *name
,
1445 struct supersect
*kpatch_ss
= make_section(sbfd
, ".ksplice_patches");
1446 struct ksplice_patch
*kpatch
= sect_grow(kpatch_ss
, 1,
1447 struct ksplice_patch
);
1449 write_string(kpatch_ss
, &kpatch
->label
, "%s", label
);
1450 asymbol
**symp
= make_undefined_symbolp(sbfd
, strdup(name
));
1451 write_reloc(kpatch_ss
, &kpatch
->repladdr
, symp
, 0);
1454 void write_ksplice_export(struct superbfd
*sbfd
, const char *symname
,
1455 const char *export_type
, bool del
)
1457 struct supersect
*export_ss
= make_section(sbfd
, ".ksplice_exports");
1458 struct ksplice_export
*exp
= sect_grow(export_ss
, 1,
1459 struct ksplice_export
);
1462 write_string(export_ss
, &exp
->name
, "%s", symname
);
1463 write_string(export_ss
, &exp
->new_name
, "DISABLED_%s_%s",
1466 write_string(export_ss
, &exp
->new_name
, "%s", symname
);
1467 write_string(export_ss
, &exp
->name
, "DISABLED_%s_%s", symname
,
1472 struct fixup_entry
{
1476 DECLARE_VEC_TYPE(struct fixup_entry
, fixup_entry_vec
);
1478 int compare_fixups(const void *aptr
, const void *bptr
)
1480 const struct fixup_entry
*a
= aptr
, *b
= bptr
;
1481 if (a
->offset
< b
->offset
)
1483 else if (a
->offset
> b
->offset
)
1486 return (int)a
->used
- (int)b
->used
;
1489 void filter_table_sections(struct superbfd
*isbfd
)
1491 struct supersect
*tables_ss
=
1492 fetch_supersect(offsets_sbfd
,
1493 bfd_get_section_by_name(offsets_sbfd
->abfd
,
1494 ".ksplice_table_sections"));
1495 const struct table_section
*ts
;
1496 for (ts
= tables_ss
->contents
.data
;
1497 (void *)ts
< tables_ss
->contents
.data
+ tables_ss
->contents
.size
;
1499 struct table_section s
= *ts
;
1500 s
.sect
= read_string(tables_ss
, &ts
->sect
);
1501 s
.other_sect
= read_string(tables_ss
, &ts
->other_sect
);
1502 filter_table_section(isbfd
, &s
);
1506 void filter_table_section(struct superbfd
*sbfd
, const struct table_section
*s
)
1508 asection
*isection
= bfd_get_section_by_name(sbfd
->abfd
, s
->sect
);
1509 if (isection
== NULL
)
1511 asection
*fixup_sect
= NULL
;
1512 if (s
->other_sect
!= NULL
)
1513 fixup_sect
= bfd_get_section_by_name(sbfd
->abfd
, s
->other_sect
);
1515 struct supersect
*ss
= fetch_supersect(sbfd
, isection
);
1516 if (ss
->alignment
< ffs(s
->entry_align
) - 1)
1517 ss
->alignment
= ffs(s
->entry_align
) - 1;
1519 struct supersect
*fixup_ss
= NULL
;
1520 if (fixup_sect
!= NULL
)
1521 fixup_ss
= fetch_supersect(sbfd
, fixup_sect
);
1523 struct fixup_entry_vec fixups
;
1527 for (entry
= ss
->contents
.data
;
1528 entry
< ss
->contents
.data
+ ss
->contents
.size
;
1529 entry
+= s
->entry_size
) {
1530 asymbol
*sym
, *fixup_sym
;
1531 read_reloc(ss
, entry
+ s
->addr_offset
, sizeof(void *), &sym
);
1533 struct span
*span
= new_span(ss
, addr_offset(ss
, entry
),
1535 struct supersect
*sym_ss
= fetch_supersect(sbfd
, sym
->section
);
1536 span
->keep
= sym_ss
->keep
;
1538 struct fixup_entry
*f
;
1539 if (fixup_sect
!= NULL
) {
1540 bfd_vma fixup_offset
=
1541 read_reloc(ss
, entry
+ s
->other_offset
,
1542 sizeof(void *), &fixup_sym
);
1543 if (fixup_sym
->section
== fixup_sect
) {
1544 assert(fixup_offset
< fixup_ss
->contents
.size
);
1545 f
= vec_grow(&fixups
, 1);
1546 f
->offset
= fixup_offset
;
1547 f
->used
= span
->keep
;
1552 if (fixup_sect
== NULL
)
1555 qsort(fixups
.data
, fixups
.size
, sizeof(*fixups
.data
), compare_fixups
);
1556 *vec_grow(&fixups
, 1) = (struct fixup_entry
)
1557 { .offset
= fixup_ss
->contents
.size
, .used
= false };
1559 struct fixup_entry
*f
;
1560 for (f
= fixups
.data
; f
< fixups
.data
+ fixups
.size
- 1; f
++) {
1561 struct span
*span
= new_span(fixup_ss
, f
->offset
,
1562 (f
+ 1)->offset
- f
->offset
);
1563 span
->keep
= f
->used
;
1567 void keep_referenced_sections(struct superbfd
*sbfd
)
1570 struct supersect
*ss
, *sym_ss
;
1571 struct span
*address_span
, *target_span
;
1572 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
1573 ss
= fetch_supersect(sbfd
, sect
);
1575 if (ss
->type
== SS_TYPE_SPECIAL
|| ss
->type
== SS_TYPE_EXPORT
)
1577 for (relocp
= ss
->relocs
.data
;
1578 relocp
< ss
->relocs
.data
+ ss
->relocs
.size
; relocp
++) {
1579 asymbol
*sym
= *(*relocp
)->sym_ptr_ptr
;
1580 address_span
= reloc_address_span(ss
, *relocp
);
1581 if (!address_span
->keep
)
1583 target_span
= reloc_target_span(ss
, *relocp
);
1584 if (target_span
== NULL
|| target_span
->keep
)
1586 sym_ss
= fetch_supersect(sbfd
, sym
->section
);
1587 if (sym_ss
->type
== SS_TYPE_IGNORED
)
1589 target_span
->keep
= true;
1590 sym_ss
->keep
= true;
1596 void copy_symbols(struct asymbolp_vec
*osyms
, struct asymbolpp_vec
*isyms
)
1599 for (sympp
= isyms
->data
; sympp
< isyms
->data
+ isyms
->size
; sympp
++)
1600 *vec_grow(osyms
, 1) = **sympp
;
1603 /* Modified function from GNU Binutils objcopy.c */
1604 bfd_boolean
copy_object(bfd
*ibfd
, bfd
*obfd
)
1606 assert(bfd_set_format(obfd
, bfd_get_format(ibfd
)));
1608 bfd_vma start
= bfd_get_start_address(ibfd
);
1610 flagword flags
= bfd_get_file_flags(ibfd
);
1611 flags
&= bfd_applicable_file_flags(obfd
);
1613 assert(bfd_set_start_address(obfd
, start
)
1614 && bfd_set_file_flags(obfd
, flags
));
1616 enum bfd_architecture iarch
= bfd_get_arch(ibfd
);
1617 unsigned int imach
= bfd_get_mach(ibfd
);
1618 assert(bfd_set_arch_mach(obfd
, iarch
, imach
));
1619 assert(bfd_set_format(obfd
, bfd_get_format(ibfd
)));
1621 /* BFD mandates that all output sections be created and sizes set before
1622 any output is done. Thus, we traverse all sections multiple times. */
1623 bfd_map_over_sections(ibfd
, setup_section
, obfd
);
1625 struct supersect
*new_supersects
= fetch_superbfd(ibfd
)->new_supersects
;
1626 struct supersect
*ss
;
1627 for (ss
= new_supersects
; ss
!= NULL
; ss
= ss
->next
)
1628 setup_new_section(obfd
, ss
);
1630 /* Mark symbols used in output relocations so that they
1631 are kept, even if they are local labels or static symbols.
1633 Note we iterate over the input sections examining their
1634 relocations since the relocations for the output sections
1635 haven't been set yet. mark_symbols_used_in_relocations will
1636 ignore input sections which have no corresponding output
1639 bfd_map_over_sections(ibfd
, mark_symbols_used_in_relocations
, NULL
);
1640 for (ss
= new_supersects
; ss
!= NULL
; ss
= ss
->next
)
1641 ss_mark_symbols_used_in_relocations(ss
);
1642 struct asymbolp_vec osyms
;
1644 filter_symbols(ibfd
, obfd
, &osyms
, &fetch_superbfd(ibfd
)->syms
);
1645 copy_symbols(&osyms
, &fetch_superbfd(ibfd
)->new_syms
);
1647 bfd_set_symtab(obfd
, osyms
.data
, osyms
.size
);
1649 /* This has to happen after the symbol table has been set. */
1650 bfd_map_over_sections(obfd
, write_section
, NULL
);
1652 /* Allow the BFD backend to copy any private data it understands
1653 from the input BFD to the output BFD. This is done last to
1654 permit the routine to look at the filtered symbol table, which is
1655 important for the ECOFF code at least. */
1656 assert(bfd_copy_private_bfd_data(ibfd
, obfd
));
1661 /* Modified function from GNU Binutils objcopy.c */
1662 void setup_section(bfd
*ibfd
, asection
*isection
, void *obfdarg
)
1664 struct superbfd
*isbfd
= fetch_superbfd(ibfd
);
1665 struct supersect
*ss
= fetch_supersect(isbfd
, isection
);
1666 bfd
*obfd
= obfdarg
;
1672 asection
*osection
= bfd_make_section_anyway(obfd
, isection
->name
);
1673 assert(osection
!= NULL
);
1675 osection
->userdata
= ss
;
1676 bfd_set_section_flags(obfd
, osection
, ss
->flags
);
1677 ss
->symbol
= osection
->symbol
;
1678 assert(bfd_set_section_size(obfd
, osection
, ss
->contents
.size
));
1680 vma
= bfd_section_vma(ibfd
, isection
);
1681 assert(bfd_set_section_vma(obfd
, osection
, vma
));
1683 osection
->lma
= isection
->lma
;
1684 assert(bfd_set_section_alignment(obfd
, osection
, ss
->alignment
));
1685 osection
->entsize
= isection
->entsize
;
1686 osection
->output_section
= osection
;
1687 osection
->output_offset
= 0;
1688 isection
->output_section
= osection
;
1689 isection
->output_offset
= 0;
1693 void setup_new_section(bfd
*obfd
, struct supersect
*ss
)
1695 asection
*osection
= bfd_make_section_anyway(obfd
, ss
->name
);
1696 assert(osection
!= NULL
);
1697 bfd_set_section_flags(obfd
, osection
, ss
->flags
);
1699 osection
->userdata
= ss
;
1700 ss
->symbol
= osection
->symbol
;
1701 assert(bfd_set_section_size(obfd
, osection
, ss
->contents
.size
));
1702 assert(bfd_set_section_vma(obfd
, osection
, 0));
1705 assert(bfd_set_section_alignment(obfd
, osection
, ss
->alignment
));
1706 osection
->entsize
= 0;
1707 osection
->output_section
= osection
;
1708 osection
->output_offset
= 0;
1711 static int compare_reloc_addresses(const void *aptr
, const void *bptr
)
1713 const arelent
*const *a
= aptr
, *const *b
= bptr
;
1714 return (*a
)->address
- (*b
)->address
;
1717 static void delete_obsolete_relocs(struct supersect
*ss
)
1719 if (ss
->new_relocs
.size
== 0)
1722 qsort(ss
->relocs
.data
, ss
->relocs
.size
, sizeof(*ss
->relocs
.data
),
1723 compare_reloc_addresses
);
1724 qsort(ss
->new_relocs
.data
, ss
->new_relocs
.size
,
1725 sizeof(*ss
->new_relocs
.data
), compare_reloc_addresses
);
1727 struct arelentp_vec orig_relocs
;
1728 vec_move(&orig_relocs
, &ss
->relocs
);
1730 arelent
**relocp
, **new_relocp
= ss
->new_relocs
.data
;
1731 for (relocp
= orig_relocs
.data
;
1732 relocp
< orig_relocs
.data
+ orig_relocs
.size
; relocp
++) {
1733 while (new_relocp
< ss
->new_relocs
.data
+ ss
->new_relocs
.size
&&
1734 (*new_relocp
)->address
< (*relocp
)->address
)
1736 arelent
*reloc
= *relocp
, *new_reloc
= *new_relocp
;
1737 if (new_relocp
== ss
->new_relocs
.data
+ ss
->new_relocs
.size
||
1738 reloc
->address
!= new_reloc
->address
)
1739 *vec_grow(&ss
->relocs
, 1) = reloc
;
1743 void write_section(bfd
*obfd
, asection
*osection
, void *arg
)
1745 struct supersect
*ss
= osection
->userdata
;
1747 if ((ss
->flags
& SEC_GROUP
) != 0 || ss
->contents
.size
== 0)
1750 delete_obsolete_relocs(ss
);
1753 char *error_message
;
1754 for (relocp
= ss
->new_relocs
.data
;
1755 relocp
< ss
->new_relocs
.data
+ ss
->new_relocs
.size
; relocp
++) {
1757 if (bfd_get_arch(obfd
) == bfd_arch_arm
)
1758 val
= osection
->use_rela_p
? 0 : (*relocp
)->addend
;
1761 bfd_put(bfd_get_reloc_size((*relocp
)->howto
) * 8, obfd
, val
,
1762 ss
->contents
.data
+ (*relocp
)->address
);
1763 if (bfd_install_relocation(obfd
, *relocp
, ss
->contents
.data
,
1764 0, osection
, &error_message
) !=
1766 err(ss
->parent
, "ksplice: error installing reloc: %s",
1771 memcpy(vec_grow(&ss
->relocs
, ss
->new_relocs
.size
), ss
->new_relocs
.data
,
1772 ss
->new_relocs
.size
* sizeof(*ss
->new_relocs
.data
));
1774 bfd_set_reloc(obfd
, osection
,
1775 ss
->relocs
.size
== 0 ? NULL
: ss
->relocs
.data
,
1778 if (ss
->flags
& SEC_HAS_CONTENTS
)
1779 assert(bfd_set_section_contents
1780 (obfd
, osection
, ss
->contents
.data
, 0,
1781 ss
->contents
.size
));
1784 /* Modified function from GNU Binutils objcopy.c
1786 * Mark all the symbols which will be used in output relocations with
1787 * the BSF_KEEP flag so that those symbols will not be stripped.
1789 * Ignore relocations which will not appear in the output file.
1791 void mark_symbols_used_in_relocations(bfd
*abfd
, asection
*isection
,
1794 struct superbfd
*sbfd
= fetch_superbfd(abfd
);
1795 if (isection
->output_section
== NULL
)
1798 struct supersect
*ss
= fetch_supersect(sbfd
, isection
);
1799 ss_mark_symbols_used_in_relocations(ss
);
1802 void ss_mark_symbols_used_in_relocations(struct supersect
*ss
)
1804 /* Examine each symbol used in a relocation. If it's not one of the
1805 special bfd section symbols, then mark it with BSF_KEEP. */
1807 for (relocp
= ss
->relocs
.data
;
1808 relocp
< ss
->relocs
.data
+ ss
->relocs
.size
; relocp
++) {
1809 asymbol
*sym
= *(*relocp
)->sym_ptr_ptr
;
1810 if (!(bfd_is_const_section(sym
->section
) &&
1811 sym
== sym
->section
->symbol
))
1812 sym
->flags
|= BSF_KEEP
;
1814 for (relocp
= ss
->new_relocs
.data
;
1815 relocp
< ss
->new_relocs
.data
+ ss
->new_relocs
.size
; relocp
++) {
1816 asymbol
*sym
= *(*relocp
)->sym_ptr_ptr
;
1817 if (!(bfd_is_const_section(sym
->section
) &&
1818 sym
== sym
->section
->symbol
))
1819 sym
->flags
|= BSF_KEEP
;
1823 static bool deleted_table_section_symbol(bfd
*abfd
, asymbol
*sym
)
1825 struct superbfd
*sbfd
= fetch_superbfd(abfd
);
1826 if (bfd_is_const_section(sym
->section
))
1828 struct supersect
*ss
= fetch_supersect(sbfd
, sym
->section
);
1831 for (symp
= ss
->syms
.data
; symp
< ss
->syms
.data
+ ss
->syms
.size
; symp
++) {
1835 return symp
>= ss
->syms
.data
+ ss
->syms
.size
;
1838 /* Modified function from GNU Binutils objcopy.c
1840 * Choose which symbol entries to copy.
1841 * We don't copy in place, because that confuses the relocs.
1842 * Return the number of symbols to print.
1844 void filter_symbols(bfd
*ibfd
, bfd
*obfd
, struct asymbolp_vec
*osyms
,
1845 struct asymbolp_vec
*isyms
)
1848 struct superbfd
*sbfd
= fetch_superbfd(ibfd
);
1849 for (symp
= isyms
->data
; symp
< isyms
->data
+ isyms
->size
; symp
++) {
1850 asymbol
*sym
= *symp
;
1851 struct supersect
*sym_ss
= NULL
;
1852 if (!bfd_is_const_section(sym
->section
))
1853 sym_ss
= fetch_supersect(sbfd
, sym
->section
);
1857 if (mode("keep") && (sym
->flags
& BSF_GLOBAL
) != 0 &&
1858 !(mode("keep-primary") && sym_ss
!= NULL
&& sym_ss
->new))
1859 sym
->flags
= (sym
->flags
& ~BSF_GLOBAL
) | BSF_LOCAL
;
1861 if (mode("finalize") && (sym
->flags
& BSF_GLOBAL
) != 0)
1862 sym
->flags
= (sym
->flags
& ~BSF_GLOBAL
) | BSF_LOCAL
;
1864 if ((sym
->flags
& BSF_KEEP
) != 0 /* Used in relocation. */
1865 || ((sym
->flags
& BSF_SECTION_SYM
) != 0 && sym_ss
!= NULL
&&
1868 else if ((sym
->flags
& (BSF_GLOBAL
| BSF_WEAK
)) != 0 &&
1869 sym_ss
!= NULL
&& sym_ss
->keep
)
1872 if (deleted_table_section_symbol(ibfd
, sym
))
1875 if (bfd_is_com_section(sym
->section
))
1879 keep
= !str_in_set(sym
->name
, &rmsyms
);
1882 if (sym_ss
!= NULL
&& !sym_ss
->keep
) {
1883 err(sbfd
, "Kept symbol %s in unkept section "
1884 "%s\n", sym
->name
, sym
->section
->name
);
1887 *vec_grow(osyms
, 1) = sym
;
1892 void read_str_set(struct str_vec
*strs
)
1896 assert(getline(&buf
, &n
, stdin
) >= 0);
1900 char *str
= strtok_r(buf
, " \n", &saveptr
);
1904 *vec_grow(strs
, 1) = str
;
1908 bool str_in_set(const char *str
, const struct str_vec
*strs
)
1911 for (strp
= strs
->data
; strp
< strs
->data
+ strs
->size
; strp
++) {
1912 if (strcmp(str
, *strp
) == 0)
1918 bool is_table_section(const char *name
, bool consider_other
)
1920 struct supersect
*tables_ss
=
1921 fetch_supersect(offsets_sbfd
,
1922 bfd_get_section_by_name(offsets_sbfd
->abfd
,
1923 ".ksplice_table_sections"));
1924 const struct table_section
*ts
;
1925 for (ts
= tables_ss
->contents
.data
;
1926 (void *)ts
< tables_ss
->contents
.data
+ tables_ss
->contents
.size
;
1928 if (strcmp(name
, read_string(tables_ss
, &ts
->sect
)) == 0)
1930 const char *osect_name
= read_string(tables_ss
,
1932 if (consider_other
&& osect_name
!= NULL
&&
1933 strcmp(name
, osect_name
) == 0)
1939 enum supersect_type
supersect_type(struct supersect
*ss
)
1941 if (starts_with(ss
->name
, ".ksplice"))
1942 return SS_TYPE_KSPLICE
;
1944 if (starts_with(ss
->name
, ".init"))
1945 return SS_TYPE_IGNORED
;
1946 if (starts_with(ss
->name
, ".security_initcall.init"))
1947 return SS_TYPE_IGNORED
;
1948 if (starts_with(ss
->name
, ".con_initcall.init"))
1949 return SS_TYPE_IGNORED
;
1950 if (starts_with(ss
->name
, ".x86cpuvendor.init"))
1951 return SS_TYPE_IGNORED
;
1952 if (starts_with(ss
->name
, ".early_param.init"))
1953 return SS_TYPE_IGNORED
;
1954 if (starts_with(ss
->name
, ".taglist.init"))
1955 return SS_TYPE_IGNORED
;
1956 if (starts_with(ss
->name
, ".arch.info.init"))
1957 return SS_TYPE_IGNORED
;
1958 if (starts_with(ss
->name
, ".proc.info.init"))
1959 return SS_TYPE_IGNORED
;
1960 /* .pci_fixup_* sections really should be treated as global rodata
1961 referenced only from quirks.c */
1962 if (starts_with(ss
->name
, ".pci_fixup_"))
1963 return SS_TYPE_IGNORED
;
1964 /* .builtin_fw sections are similar to .pci_fixup */
1965 if (starts_with(ss
->name
, ".builtin_fw"))
1966 return SS_TYPE_IGNORED
;
1967 /* same for .tracedata */
1968 if (starts_with(ss
->name
, ".tracedata"))
1969 return SS_TYPE_IGNORED
;
1970 if (starts_with(ss
->name
, ".debug"))
1971 return SS_TYPE_IGNORED
;
1972 /* .eh_frame should probably be discarded, not ignored */
1973 if (starts_with(ss
->name
, ".eh_frame"))
1974 return SS_TYPE_IGNORED
;
1975 if (config
->ignore_devinit
&& starts_with(ss
->name
, ".devinit"))
1976 return SS_TYPE_IGNORED
;
1977 if (config
->ignore_meminit
&& starts_with(ss
->name
, ".meminit"))
1978 return SS_TYPE_IGNORED
;
1979 if (config
->ignore_cpuinit
&& starts_with(ss
->name
, ".cpuinit"))
1980 return SS_TYPE_IGNORED
;
1981 if (config
->ignore_devinit
&& starts_with(ss
->name
, ".devexit"))
1982 return SS_TYPE_IGNORED
;
1983 if (config
->ignore_meminit
&& starts_with(ss
->name
, ".memexit"))
1984 return SS_TYPE_IGNORED
;
1985 if (config
->ignore_cpuinit
&& starts_with(ss
->name
, ".cpuexit"))
1986 return SS_TYPE_IGNORED
;
1987 if (starts_with(ss
->name
, ".vgetcpu_mode") ||
1988 starts_with(ss
->name
, ".jiffies") ||
1989 starts_with(ss
->name
, ".wall_jiffies") ||
1990 starts_with(ss
->name
, ".vxtime") ||
1991 starts_with(ss
->name
, ".sys_tz") ||
1992 starts_with(ss
->name
, ".sysctl_vsyscall") ||
1993 starts_with(ss
->name
, ".xtime") ||
1994 starts_with(ss
->name
, ".xtime_lock") ||
1995 starts_with(ss
->name
, ".vsyscall"))
1996 return SS_TYPE_IGNORED
;
1997 if (starts_with(ss
->name
, ".vdso"))
1998 return SS_TYPE_IGNORED
;
2000 if (bfd_get_section_by_name(ss
->parent
->abfd
, ".exitcall.exit") == NULL
) {
2001 if (starts_with(ss
->name
, ".exit.text"))
2002 return SS_TYPE_TEXT
;
2003 if (starts_with(ss
->name
, ".exit.data"))
2004 return SS_TYPE_DATA
;
2005 } else if (starts_with(ss
->name
, ".exit.text") ||
2006 starts_with(ss
->name
, ".exit.data"))
2007 return SS_TYPE_IGNORED
;
2009 if (starts_with(ss
->name
, ".text") ||
2010 starts_with(ss
->name
, ".kernel.text") ||
2011 starts_with(ss
->name
, ".devinit.text") ||
2012 starts_with(ss
->name
, ".meminit.text") ||
2013 starts_with(ss
->name
, ".cpuinit.text") ||
2014 starts_with(ss
->name
, ".devexit.text") ||
2015 starts_with(ss
->name
, ".memexit.text") ||
2016 starts_with(ss
->name
, ".cpuexit.text") ||
2017 starts_with(ss
->name
, ".ref.text") ||
2018 starts_with(ss
->name
, ".spinlock.text") ||
2019 starts_with(ss
->name
, ".kprobes.text") ||
2020 starts_with(ss
->name
, ".sched.text"))
2021 return SS_TYPE_TEXT
;
2024 if (sscanf(ss
->name
, ".rodata.str%*u.%*u%n", &n
) >= 0 &&
2025 n
== strlen(ss
->name
))
2026 return SS_TYPE_STRING
;
2028 if (starts_with(ss
->name
, ".rodata") ||
2029 starts_with(ss
->name
, ".kernel.rodata") ||
2030 starts_with(ss
->name
, ".devinit.rodata") ||
2031 starts_with(ss
->name
, ".meminit.rodata") ||
2032 starts_with(ss
->name
, ".cpuinit.rodata") ||
2033 starts_with(ss
->name
, ".devexit.rodata") ||
2034 starts_with(ss
->name
, ".memexit.rodata") ||
2035 starts_with(ss
->name
, ".cpuexit.rodata") ||
2036 starts_with(ss
->name
, ".ref.rodata") ||
2037 starts_with(ss
->name
, "__markers_strings"))
2038 return SS_TYPE_RODATA
;
2040 if (starts_with(ss
->name
, ".bss"))
2041 return SS_TYPE_DATA
;
2043 /* Ignore .data.percpu sections */
2044 if (starts_with(ss
->name
, ".data.percpu") ||
2045 starts_with(ss
->name
, ".kernel.data.percpu"))
2046 return SS_TYPE_IGNORED
;
2047 if (starts_with(ss
->name
, ".data") ||
2048 starts_with(ss
->name
, ".kernel.data") ||
2049 starts_with(ss
->name
, ".devinit.data") ||
2050 starts_with(ss
->name
, ".cpuinit.data") ||
2051 starts_with(ss
->name
, ".meminit.data") ||
2052 starts_with(ss
->name
, ".devexit.data") ||
2053 starts_with(ss
->name
, ".memexit.data") ||
2054 starts_with(ss
->name
, ".cpuexit.data") ||
2055 starts_with(ss
->name
, ".ref.data") ||
2056 starts_with(ss
->name
, "__markers"))
2057 return SS_TYPE_DATA
;
2059 /* We replace all the ksymtab strings, so delete them */
2060 if (strcmp(ss
->name
, "__ksymtab_strings") == 0)
2061 return SS_TYPE_IGNORED
;
2062 if (starts_with(ss
->name
, "__ksymtab"))
2063 return SS_TYPE_EXPORT
;
2064 if (starts_with(ss
->name
, "__kcrctab"))
2065 return SS_TYPE_EXPORT
;
2067 if (is_table_section(ss
->name
, true))
2068 return SS_TYPE_SPECIAL
;
2070 if (starts_with(ss
->name
, ".ARM."))
2071 return SS_TYPE_SPECIAL
;
2073 if (starts_with(ss
->name
, ".note"))
2074 return SS_TYPE_IGNORED
;
2075 if (starts_with(ss
->name
, ".comment"))
2076 return SS_TYPE_IGNORED
;
2077 if (starts_with(ss
->name
, "__param"))
2078 return SS_TYPE_IGNORED
;
2079 if (starts_with(ss
->name
, ".exitcall.exit"))
2080 return SS_TYPE_IGNORED
;
2081 if (starts_with(ss
->name
, ".modinfo"))
2082 return SS_TYPE_IGNORED
;
2084 return SS_TYPE_UNKNOWN
;
2087 void initialize_supersect_types(struct superbfd
*sbfd
)
2090 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
2091 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
2092 ss
->type
= supersect_type(ss
);
2093 if (ss
->type
== SS_TYPE_UNKNOWN
) {
2094 err(sbfd
, "Unknown section type: %s\n", ss
->name
);
2100 static void init_label_map(struct superbfd
*sbfd
)
2102 struct label_map
*map
;
2104 vec_init(&sbfd
->maps
);
2108 struct symbol_hash csyms
;
2109 symbol_hash_init(&csyms
);
2112 for (symp
= sbfd
->syms
.data
;
2113 symp
< sbfd
->syms
.data
+ sbfd
->syms
.size
; symp
++) {
2114 asymbol
*csym
= canonical_symbol(sbfd
, *symp
);
2118 assert(asprintf(&key
, "%p", csym
) >= 0);
2119 asymbol
**csymp
= symbol_hash_lookup(&csyms
, key
, TRUE
);
2125 map
= vec_grow(&sbfd
->maps
, 1);
2128 map
->label
= symbol_label(sbfd
, csym
);
2131 struct label_mapp_hash label_maps
;
2132 label_mapp_hash_init(&label_maps
);
2133 for (map
= sbfd
->maps
.data
;
2134 map
< sbfd
->maps
.data
+ sbfd
->maps
.size
; map
++) {
2135 struct label_map
**mapp
=
2136 label_mapp_hash_lookup(&label_maps
, map
->label
, TRUE
);
2137 if (*mapp
== NULL
) {
2142 struct label_map
*first_map
= *mapp
;
2144 if (first_map
->count
== 0) {
2145 assert(asprintf(&buf
, "%s~%d", map
->label
, 0) >= 0);
2146 first_map
->label
= buf
;
2149 assert(asprintf(&buf
, "%s~%d", map
->label
, first_map
->count
)
2154 label_mapp_hash_init(&sbfd
->maps_hash
);
2155 for (map
= sbfd
->maps
.data
;
2156 map
< sbfd
->maps
.data
+ sbfd
->maps
.size
; map
++) {
2158 assert(asprintf(&key
, "%p", map
->csym
) >= 0);
2159 struct label_map
**mapp
=
2160 label_mapp_hash_lookup(&sbfd
->maps_hash
, key
, TRUE
);
2163 map
->orig_label
= map
->label
;
2167 static const char *label_lookup(struct superbfd
*sbfd
, asymbol
*sym
)
2169 asymbol
*csym
= canonical_symbol(sbfd
, sym
);
2171 assert(asprintf(&key
, "%p", csym
) >= 0);
2172 struct label_map
**mapp
=
2173 label_mapp_hash_lookup(&sbfd
->maps_hash
, key
, FALSE
);
2177 return (*mapp
)->label
;
2180 static void print_label_map(struct superbfd
*sbfd
)
2182 struct label_map
*map
;
2183 for (map
= sbfd
->maps
.data
;
2184 map
< sbfd
->maps
.data
+ sbfd
->maps
.size
; map
++) {
2185 if (strcmp(map
->orig_label
, map
->label
) == 0)
2187 debug1(sbfd
, "Label change: %s -> %s\n",
2188 map
->label
, map
->orig_label
);
2192 static void label_map_set(struct superbfd
*sbfd
, const char *oldlabel
,
2195 struct label_map
*map
;
2196 for (map
= sbfd
->maps
.data
;
2197 map
< sbfd
->maps
.data
+ sbfd
->maps
.size
; map
++) {
2198 if (strcmp(map
->orig_label
, oldlabel
) == 0) {
2199 if (strcmp(map
->orig_label
, map
->label
) != 0 &&
2200 strcmp(map
->label
, label
) != 0)
2209 static void init_callers(struct superbfd
*sbfd
)
2211 string_hash_init(&sbfd
->callers
);
2213 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
2214 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
2216 for (relocp
= ss
->relocs
.data
;
2217 relocp
< ss
->relocs
.data
+ ss
->relocs
.size
; relocp
++) {
2218 asymbol
*sym
= *(*relocp
)->sym_ptr_ptr
;
2220 sym
->value
+ get_reloc_offset(ss
, *relocp
, true);
2222 assert(asprintf(&key
, "%s+%lx", sym
->section
->name
,
2224 const char **ret
= string_hash_lookup(&sbfd
->callers
,
2230 *ret
= "*multiple_callers*";
2235 static const char *find_caller(struct supersect
*ss
, asymbol
*sym
)
2238 assert(asprintf(&key
, "%s+%lx", sym
->section
->name
,
2239 (unsigned long)sym
->value
) >= 0);
2240 const char **ret
= string_hash_lookup(&ss
->parent
->callers
, key
, FALSE
);
2244 return "*no_caller*";
2248 static void init_csyms(struct superbfd
*sbfd
)
2250 asymbolpp_hash_init(&sbfd
->csyms
);
2253 for (symp
= sbfd
->syms
.data
; symp
< sbfd
->syms
.data
+ sbfd
->syms
.size
;
2255 asymbol
*sym
= *symp
;
2256 if ((sym
->flags
& BSF_DEBUGGING
) != 0)
2259 assert(asprintf(&key
, "%s+%lx", sym
->section
->name
,
2260 (unsigned long)sym
->value
) >= 0);
2261 asymbol
***csympp
= asymbolpp_hash_lookup(&sbfd
->csyms
, key
,
2264 if (*csympp
== NULL
) {
2268 asymbol
*csym
= **csympp
;
2269 if ((csym
->flags
& BSF_GLOBAL
) != 0)
2271 if ((sym
->flags
& BSF_GLOBAL
) != 0)
2276 static asymbol
**symbolp_scan(struct supersect
*ss
, bfd_vma value
)
2279 assert(asprintf(&key
, "%s+%lx", ss
->name
, (unsigned long)value
) >= 0);
2281 asymbolpp_hash_lookup(&ss
->parent
->csyms
, key
, FALSE
);
2286 /* For section symbols of sections containing no symbols, return the
2287 section symbol that relocations are generated against */
2293 static asymbol
**canonical_symbolp(struct superbfd
*sbfd
, asymbol
*sym
)
2295 if (bfd_is_const_section(sym
->section
)) {
2297 for (csymp
= sbfd
->syms
.data
;
2298 csymp
< sbfd
->syms
.data
+ sbfd
->syms
.size
; csymp
++) {
2304 return symbolp_scan(fetch_supersect(sbfd
, sym
->section
), sym
->value
);
2307 static asymbol
*canonical_symbol(struct superbfd
*sbfd
, asymbol
*sym
)
2309 if (bfd_is_const_section(sym
->section
))
2311 asymbol
**symp
= canonical_symbolp(sbfd
, sym
);
2312 return symp
!= NULL
? *symp
: NULL
;
2315 static char *static_local_symbol(struct superbfd
*sbfd
, asymbol
*sym
)
2317 struct supersect
*ss
= fetch_supersect(sbfd
, sym
->section
);
2318 if ((sym
->flags
& BSF_LOCAL
) == 0 || (sym
->flags
& BSF_OBJECT
) == 0)
2320 char *dot
= strrchr(sym
->name
, '.');
2321 if (dot
== NULL
|| dot
[1 + strspn(dot
+ 1, "0123546789")] != '\0')
2323 char *basename
= strndup(sym
->name
, dot
- sym
->name
);
2325 if (strcmp(basename
, "__func__") == 0 ||
2326 strcmp(basename
, "__PRETTY_FUNCTION__") == 0)
2327 assert(asprintf(&mangled_name
, "%s<%s>", basename
,
2328 (char *)ss
->contents
.data
+ sym
->value
) >= 0);
2330 assert(asprintf(&mangled_name
, "%s<%s>", basename
,
2331 find_caller(ss
, sym
)) >= 0);
2332 return mangled_name
;
2335 static char *symbol_label(struct superbfd
*sbfd
, asymbol
*sym
)
2337 const char *filename
= sbfd
->abfd
->filename
;
2338 char *c
= strstr(filename
, ".KSPLICE");
2339 int flen
= (c
== NULL
? strlen(filename
) : c
- filename
);
2342 if (bfd_is_und_section(sym
->section
) || (sym
->flags
& BSF_GLOBAL
) != 0) {
2343 label
= strdup(sym
->name
);
2344 } else if (bfd_is_const_section(sym
->section
)) {
2345 assert(asprintf(&label
, "%s<%.*s>",
2346 sym
->name
, flen
, filename
) >= 0);
2348 asymbol
*gsym
= canonical_symbol(sbfd
, sym
);
2351 assert(asprintf(&label
, "%s+%lx<%.*s>",
2353 (unsigned long)sym
->value
,
2354 flen
, filename
) >= 0);
2355 else if ((gsym
->flags
& BSF_GLOBAL
) != 0)
2356 label
= strdup(gsym
->name
);
2357 else if (static_local_symbol(sbfd
, gsym
))
2358 assert(asprintf(&label
, "%s+%lx<%.*s>",
2359 static_local_symbol(sbfd
, gsym
),
2360 (unsigned long)sym
->value
,
2361 flen
, filename
) >= 0);
2363 assert(asprintf(&label
, "%s<%.*s>",
2364 gsym
->name
, flen
, filename
) >= 0);
2370 static struct span
*new_span(struct supersect
*ss
, bfd_vma start
, bfd_vma size
)
2372 struct span
*span
= vec_grow(&ss
->spans
, 1);
2374 span
->start
= start
;
2379 asymbol
**symp
= symbolp_scan(ss
, span
->start
);
2381 span
->symbol
= *symp
;
2382 span
->label
= label_lookup(ss
->parent
, span
->symbol
);
2384 span
->symbol
= NULL
;
2385 const char *label
= label_lookup(ss
->parent
, ss
->symbol
);
2386 if (span
->start
!= 0) {
2388 assert(asprintf(&buf
, "%s<span:%lx>", label
,
2389 (unsigned long)span
->start
) >= 0);
2392 span
->label
= label
;
2398 static void initialize_string_spans(struct supersect
*ss
)
2401 for (str
= ss
->contents
.data
;
2402 (void *)str
< ss
->contents
.data
+ ss
->contents
.size
;) {
2403 bfd_vma start
= (unsigned long)str
-
2404 (unsigned long)ss
->contents
.data
;
2405 bfd_vma size
= strlen(str
) + 1;
2406 while ((start
+ size
) % (1 << ss
->alignment
) != 0 &&
2407 start
+ size
< ss
->contents
.size
) {
2408 if (str
[size
] != '\0')
2412 new_span(ss
, start
, size
);
2417 static void initialize_spans(struct superbfd
*sbfd
)
2420 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
2421 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
2422 if (ss
->type
== SS_TYPE_STRING
)
2423 initialize_string_spans(ss
);
2424 else if (!mode("keep") || (ss
->type
!= SS_TYPE_SPECIAL
&&
2425 ss
->type
!= SS_TYPE_EXPORT
))
2426 new_span(ss
, 0, ss
->contents
.size
);
2430 struct span
*reloc_target_span(struct supersect
*ss
, arelent
*reloc
)
2432 asymbol
*sym_ptr
= *reloc
->sym_ptr_ptr
;
2433 if (bfd_is_const_section(sym_ptr
->section
))
2436 bfd_vma addend
= get_reloc_offset(ss
, reloc
, true) + sym_ptr
->value
;
2437 struct supersect
*sym_ss
=
2438 fetch_supersect(ss
->parent
, sym_ptr
->section
);
2439 struct span
*span
, *target_span
= sym_ss
->spans
.data
;
2440 for (span
= sym_ss
->spans
.data
;
2441 span
< sym_ss
->spans
.data
+ sym_ss
->spans
.size
; span
++) {
2442 if (addend
>= span
->start
&& addend
< span
->start
+ span
->size
)
2448 struct span
*reloc_address_span(struct supersect
*ss
, arelent
*reloc
)
2451 for (span
= ss
->spans
.data
; span
< ss
->spans
.data
+ ss
->spans
.size
;
2453 if (reloc
->address
>= span
->start
&&
2454 reloc
->address
< span
->start
+ span
->size
)
2460 void compute_span_shifts(struct superbfd
*sbfd
)
2464 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
2465 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
2468 bfd_size_type offset
= 0;
2469 for (span
= ss
->spans
.data
;
2470 span
< ss
->spans
.data
+ ss
->spans
.size
; span
++) {
2473 span
->shift
= offset
- span
->start
;
2474 offset
+= span
->size
;
2479 void remove_unkept_spans(struct superbfd
*sbfd
)
2483 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
2484 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
2485 struct arelentp_vec orig_relocs
;
2486 vec_move(&orig_relocs
, &ss
->relocs
);
2487 arelent
**relocp
, *reloc
;
2488 for (relocp
= orig_relocs
.data
;
2489 relocp
< orig_relocs
.data
+ orig_relocs
.size
; relocp
++) {
2491 asymbol
*sym
= *reloc
->sym_ptr_ptr
;
2492 span
= reloc_target_span(ss
, reloc
);
2493 if ((span
!= NULL
&& span
->keep
&& span
->shift
== 0) ||
2494 bfd_is_const_section(sym
->section
)) {
2495 *vec_grow(&ss
->relocs
, 1) = reloc
;
2498 if (span
!= NULL
&& span
->keep
) {
2499 arelent
*new_reloc
= malloc(sizeof(*new_reloc
));
2500 *new_reloc
= *reloc
;
2502 get_reloc_offset(ss
, reloc
, false);
2503 new_reloc
->addend
+= span
->shift
;
2504 *vec_grow(&ss
->new_relocs
, 1) = new_reloc
;
2509 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
2510 struct supersect
*ss
= fetch_supersect(sbfd
, sect
), orig_ss
;
2513 supersect_move(&orig_ss
, ss
);
2514 vec_init(&ss
->spans
);
2515 for (span
= orig_ss
.spans
.data
;
2516 span
< orig_ss
.spans
.data
+ orig_ss
.spans
.size
; span
++) {
2519 struct span
*new_span
= vec_grow(&ss
->spans
, 1);
2521 new_span
->start
= span
->start
+ span
->shift
;
2522 new_span
->shift
= 0;
2523 sect_copy(ss
, sect_do_grow(ss
, 1, span
->size
, 1),
2524 &orig_ss
, orig_ss
.contents
.data
+ span
->start
,