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 <in.o> <out.o> keep-primary <kid>"
27 * This mode prepares the object file to be installed as a ksplice update.
28 * It takes as input on STDIN the output of the objdiff command. The kid
29 * argument is the ksplice id string for the ksplice update being built.
31 * - keep-helper: "objmanip <in.o> <out.o> keep-helper"
33 * This mode prepares the object file to be used for run-pre matching. This
34 * involves replacing all ELF relocations with ksplice relocations and
35 * writing ksplice_size structures for each ELF text or data section.
37 * - rmsyms mode: "objmanip <in.o> <out.o> rmsyms
39 * In this mode, any ELF relocations involving the list of symbol names given on
40 * standard input are replaced with ksplice relocations. This is used only
41 * for KSPLICE_STANDALONE.
43 * - finalize mode: "objmanip <in.o> <out.o> finalize"
45 * In this mode, any ELF relocations to undefined symbols are replaced with
46 * ksplice relocations.
49 /* Always define KSPLICE_STANDALONE, even if you're using integrated Ksplice.
50 objmanip won't compile without it. */
51 #define KSPLICE_STANDALONE
54 #include "objcommon.h"
55 #include "kmodsrc/ksplice.h"
62 DECLARE_VEC_TYPE(const char *, str_vec
);
69 struct table_section
{
78 DECLARE_VEC_TYPE(struct export_desc
, export_desc_vec
);
80 #define bool_init(b) *(b) = false
81 DEFINE_HASH_TYPE(bool, bool_hash
, bool_hash_init
, bool_hash_free
,
82 bool_hash_lookup
, bool_init
);
84 void rm_some_relocs(struct supersect
*ss
);
85 void write_ksplice_reloc(struct supersect
*ss
, arelent
*orig_reloc
);
86 void blot_section(struct supersect
*ss
, int offset
, reloc_howto_type
*howto
);
87 void write_ksplice_size(struct superbfd
*sbfd
, asymbol
**symp
);
88 void write_ksplice_patch(struct superbfd
*sbfd
, const char *sectname
);
89 void write_ksplice_deleted_patch(struct superbfd
*sbfd
, const char *label
);
90 void filter_table_section(struct superbfd
*sbfd
, const struct table_section
*s
);
91 void mark_wanted_if_referenced(bfd
*abfd
, asection
*sect
, void *ignored
);
92 void check_for_ref_to_section(bfd
*abfd
, asection
*looking_at
,
94 bfd_boolean
copy_object(bfd
*ibfd
, bfd
*obfd
);
95 void setup_section(bfd
*ibfd
, asection
*isection
, void *obfdarg
);
96 static void setup_new_section(bfd
*obfd
, struct supersect
*ss
);
97 static void write_section(bfd
*obfd
, asection
*osection
, void *arg
);
98 void mark_symbols_used_in_relocations(bfd
*abfd
, asection
*isection
,
100 static void ss_mark_symbols_used_in_relocations(struct supersect
*ss
);
101 void filter_symbols(bfd
*ibfd
, bfd
*obfd
, struct asymbolp_vec
*osyms
,
102 struct asymbolp_vec
*isyms
);
103 static int deleted_table_section_symbol(bfd
*abfd
, asymbol
*sym
);
104 void read_str_set(struct str_vec
*strs
);
105 int str_in_set(const char *str
, const struct str_vec
*strs
);
106 int want_section(asection
*sect
);
107 const struct table_section
*is_table_section(asection
*sect
);
108 struct supersect
*make_section(struct superbfd
*sbfd
, const char *name
);
109 void __attribute__((format(printf
, 3, 4)))
110 write_string(struct supersect
*ss
, const char **addr
, const char *fmt
, ...);
111 void rm_some_exports(struct superbfd
*isbfd
, const struct export_desc
*ed
);
112 void write_ksplice_export(struct superbfd
*sbfd
, const char *symname
,
113 const char *export_type
, int del
);
114 void write_reloc(struct supersect
*ss
, const void *addr
, asymbol
**symp
,
116 arelent
*create_reloc(struct supersect
*ss
, const void *addr
, asymbol
**symp
,
119 struct str_vec sections
, newsects
, delsects
, rmsyms
;
120 struct export_desc_vec exports
;
122 const char *modestr
, *kid
;
124 struct wsect
*wanted_sections
= NULL
;
126 const struct table_section table_sections
[] = {
127 {".altinstructions", 2 * sizeof(void *) + 4},
128 {".smp_locks", sizeof(void *)},
129 {".parainstructions", sizeof(void *) + 4},
130 {"__ex_table", 2 * sizeof(unsigned long)},
131 }, *const end_table_sections
= *(&table_sections
+ 1);
133 #define mode(str) starts_with(modestr, str)
135 DECLARE_VEC_TYPE(unsigned long, addr_vec
);
136 DEFINE_HASH_TYPE(struct addr_vec
, addr_vec_hash
,
137 addr_vec_hash_init
, addr_vec_hash_free
, addr_vec_hash_lookup
,
139 struct addr_vec_hash system_map
;
141 struct bool_hash system_map_written
;
143 void load_system_map()
145 const char *config_dir
= getenv("KSPLICE_CONFIG_DIR");
148 assert(asprintf(&file
, "%s/System.map", config_dir
) >= 0);
149 FILE *fp
= fopen(file
, "r");
151 addr_vec_hash_init(&system_map
);
155 while (fscanf(fp
, "%lx %c %as\n", &addr
, &type
, &sym
) == 3)
156 *vec_grow(addr_vec_hash_lookup(&system_map
, sym
, TRUE
),
161 int needed_data_section(struct superbfd
*sbfd
, asection
*isection
)
163 struct supersect
*ss
= fetch_supersect(sbfd
, isection
);
164 if (starts_with(isection
->name
, ".rodata"))
166 if (starts_with(isection
->name
, ".data")) {
167 /* Ignore .data.percpu sections */
168 if (starts_with(isection
->name
, ".data.percpu"))
170 return ss
->relocs
.size
!= 0;
175 int main(int argc
, char *argv
[])
178 bfd
*ibfd
= bfd_openr(argv
[1], NULL
);
182 assert(bfd_check_format_matches(ibfd
, bfd_object
, &matching
));
184 const char *output_target
= bfd_get_target(ibfd
);
185 bfd
*obfd
= bfd_openw(argv
[2], output_target
);
188 struct superbfd
*isbfd
= fetch_superbfd(ibfd
);
190 bool_hash_init(&system_map_written
);
193 if (mode("keep-primary"))
196 if (mode("keep-primary")) {
197 read_label_map(isbfd
);
198 read_str_set(§ions
);
199 read_str_set(&newsects
);
200 read_str_set(&delsects
);
202 /* https://bugzilla.redhat.com/show_bug.cgi?id=431832 */
203 while (ungetc(getc(stdin
), stdin
) != EOF
) {
205 int ret
= scanf("%as", §name
);
209 struct export_desc
*ed
= vec_grow(&exports
, 1);
210 ed
->sectname
= sectname
;
211 read_str_set(&ed
->names
);
213 } else if (mode("rmsyms")) {
214 read_str_set(&rmsyms
);
217 if (mode("keep-primary")) {
218 /* Create export_desc structures for all export sections */
220 for (sect
= isbfd
->abfd
->sections
; sect
!= NULL
;
222 struct export_desc
*ed
;
223 if (!starts_with(sect
->name
, "__ksymtab") ||
224 ends_with(sect
->name
, "_strings"))
226 for (ed
= exports
.data
;
227 ed
< exports
.data
+ exports
.size
; ed
++) {
228 if (strcmp(ed
->sectname
, sect
->name
) == 0)
231 if (ed
< exports
.data
+ exports
.size
)
233 ed
= vec_grow(&exports
, 1);
234 ed
->sectname
= sect
->name
;
235 vec_init(&ed
->names
);
239 if (mode("keep") || mode("rmsyms"))
244 const struct wsect
*tmp
= wanted_sections
;
245 bfd_map_over_sections(ibfd
, mark_wanted_if_referenced
,
247 if (tmp
== wanted_sections
)
252 for (sect
= ibfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
253 asymbol
**symp
= canonical_symbolp(isbfd
, sect
->symbol
);
256 asymbol
*sym
= *symp
;
257 if (!want_section(sect
))
259 if (starts_with(sect
->name
, ".rodata.str"))
261 if ((sym
->flags
& BSF_WEAK
) != 0)
263 if ((sym
->flags
& BSF_FUNCTION
) != 0 ||
264 needed_data_section(isbfd
, sect
))
265 write_ksplice_size(isbfd
, symp
);
269 if (mode("keep-primary")) {
270 const char **sectname
;
271 for (sectname
= sections
.data
;
272 sectname
< sections
.data
+ sections
.size
; sectname
++)
273 write_ksplice_patch(isbfd
, *sectname
);
276 for (label
= delsects
.data
;
277 label
< delsects
.data
+ delsects
.size
; label
++)
278 write_ksplice_deleted_patch(isbfd
, *label
);
280 const struct export_desc
*ed
;
281 for (ed
= exports
.data
; ed
< exports
.data
+ exports
.size
;
283 if (starts_with(ed
->sectname
, "del___ksymtab")) {
284 const char *export_type
=
285 ed
->sectname
+ strlen("del___ksymtab");
286 const char **symname
;
287 for (symname
= ed
->names
.data
;
288 symname
< ed
->names
.data
+ ed
->names
.size
;
290 write_ksplice_export(isbfd
, *symname
,
293 rm_some_exports(isbfd
, ed
);
299 for (p
= ibfd
->sections
; p
!= NULL
; p
= p
->next
) {
300 struct supersect
*ss
= fetch_supersect(isbfd
, p
);
301 if (is_table_section(p
) || starts_with(p
->name
, ".ksplice"))
303 if (want_section(p
) || mode("rmsyms"))
307 const struct table_section
*ss
;
309 for (ss
= table_sections
; ss
!= end_table_sections
; ss
++)
310 filter_table_section(isbfd
, ss
);
313 copy_object(ibfd
, obfd
);
314 assert(bfd_close(obfd
));
315 assert(bfd_close(ibfd
));
319 void rm_some_exports(struct superbfd
*isbfd
, const struct export_desc
*ed
)
321 assert(starts_with(ed
->sectname
, "__ksymtab"));
322 const char *export_type
= ed
->sectname
+ strlen("__ksymtab");
323 asection
*sym_sect
= bfd_get_section_by_name(isbfd
->abfd
, ed
->sectname
);
324 assert(sym_sect
!= NULL
);
325 char *export_crc_name
;
326 assert(asprintf(&export_crc_name
, "__kcrctab%s", export_type
) >= 0);
327 asection
*crc_sect
= bfd_get_section_by_name(isbfd
->abfd
,
329 struct supersect
*ss
, *crc_ss
= NULL
;
330 ss
= fetch_supersect(isbfd
, sym_sect
);
331 if (crc_sect
!= NULL
)
332 crc_ss
= fetch_supersect(isbfd
, crc_sect
);
335 assert(ss
->contents
.size
* sizeof(unsigned long) ==
336 crc_ss
->contents
.size
* sizeof(struct kernel_symbol
));
338 struct supersect orig_ss
, orig_crc_ss
;
339 supersect_move(&orig_ss
, ss
);
341 supersect_move(&orig_crc_ss
, crc_ss
);
343 struct kernel_symbol
*orig_ksym
;
344 unsigned long *orig_crc
;
345 for (orig_ksym
= orig_ss
.contents
.data
,
346 orig_crc
= orig_crc_ss
.contents
.data
;
347 (void *)orig_ksym
< orig_ss
.contents
.data
+ orig_ss
.contents
.size
;
348 orig_ksym
++, orig_crc
++) {
350 read_reloc(&orig_ss
, &orig_ksym
->value
,
351 sizeof(orig_ksym
->value
), &sym
);
352 if (!str_in_set(sym
->name
, &ed
->names
))
355 struct kernel_symbol
*ksym
= sect_grow(ss
, 1, typeof(*ksym
));
356 sect_copy(ss
, &ksym
->value
, &orig_ss
, &orig_ksym
->value
, 1);
357 /* Replace name with a mangled name */
358 write_ksplice_export(ss
->parent
, sym
->name
, export_type
, 0);
359 write_string(ss
, (const char **)&ksym
->name
,
360 "DISABLED_%s_%s", sym
->name
, kid
);
364 sect_grow(crc_ss
, 1, typeof(*orig_crc
)),
365 &orig_crc_ss
, orig_crc
, 1);
369 void rm_some_relocs(struct supersect
*ss
)
371 struct arelentp_vec orig_relocs
;
372 vec_move(&orig_relocs
, &ss
->relocs
);
375 for (relocp
= orig_relocs
.data
;
376 relocp
< orig_relocs
.data
+ orig_relocs
.size
; relocp
++) {
378 asymbol
*sym_ptr
= *(*relocp
)->sym_ptr_ptr
;
380 if (mode("rmsyms") && str_in_set(sym_ptr
->name
, &rmsyms
))
386 if (mode("keep-primary") && want_section(sym_ptr
->section
) &&
387 (str_in_set(sym_ptr
->section
->name
, &newsects
) ||
388 bfd_is_const_section(sym_ptr
->section
) ||
389 starts_with(sym_ptr
->section
->name
, ".rodata.str")))
392 if (mode("finalize") && bfd_is_und_section(sym_ptr
->section
))
396 write_ksplice_reloc(ss
, *relocp
);
398 *vec_grow(&ss
->relocs
, 1) = *relocp
;
402 struct supersect
*make_section(struct superbfd
*sbfd
, const char *name
)
404 asection
*sect
= bfd_get_section_by_name(sbfd
->abfd
, name
);
406 return fetch_supersect(sbfd
, sect
);
408 return new_supersect(sbfd
, name
);
411 arelent
*create_reloc(struct supersect
*ss
, const void *addr
, asymbol
**symp
,
414 bfd_reloc_code_real_type code
;
415 switch (bfd_arch_bits_per_address(ss
->parent
->abfd
)) {
426 arelent
*reloc
= malloc(sizeof(*reloc
));
427 reloc
->sym_ptr_ptr
= symp
;
428 reloc
->address
= addr
- ss
->contents
.data
;
429 reloc
->howto
= bfd_reloc_type_lookup(ss
->parent
->abfd
, code
);
430 reloc
->addend
= offset
;
434 void write_reloc(struct supersect
*ss
, const void *addr
, asymbol
**symp
,
437 *vec_grow(&ss
->new_relocs
, 1) = create_reloc(ss
, addr
, symp
, offset
);
440 void write_string(struct supersect
*ss
, const char **addr
, const char *fmt
, ...)
444 int len
= vsnprintf(NULL
, 0, fmt
, ap
);
446 struct supersect
*str_ss
= make_section(ss
->parent
, ".ksplice_str");
447 char *buf
= sect_grow(str_ss
, len
+ 1, char);
449 vsnprintf(buf
, len
+ 1, fmt
, ap
);
452 write_reloc(ss
, addr
, &str_ss
->symbol
,
453 (void *)buf
- str_ss
->contents
.data
);
456 void lookup_system_map(struct addr_vec
*addrs
, const char *name
, long offset
)
458 struct addr_vec
*map_addrs
=
459 addr_vec_hash_lookup(&system_map
, name
, FALSE
);
460 if (map_addrs
== NULL
)
463 unsigned long *addr
, *map_addr
;
464 for (map_addr
= map_addrs
->data
;
465 map_addr
< map_addrs
->data
+ map_addrs
->size
; map_addr
++) {
466 for (addr
= addrs
->data
; addr
< addrs
->data
+ addrs
->size
;
468 if (*addr
== *map_addr
+ offset
)
471 if (addr
< addrs
->data
+ addrs
->size
)
473 *vec_grow(addrs
, 1) = *map_addr
+ offset
;
477 void write_system_map_array(struct superbfd
*sbfd
, struct supersect
*ss
,
478 const unsigned long **sym_addrs
,
479 unsigned long *num_sym_addrs
, asymbol
*sym
)
481 struct addr_vec addrs
;
484 if (bfd_is_abs_section(sym
->section
)) {
485 *vec_grow(&addrs
, 1) = sym
->value
;
486 } else if (bfd_is_und_section(sym
->section
)) {
487 lookup_system_map(&addrs
, sym
->name
, 0);
488 } else if (!bfd_is_const_section(sym
->section
)) {
490 for (gsymp
= sbfd
->syms
.data
;
491 gsymp
< sbfd
->syms
.data
+ sbfd
->syms
.size
; gsymp
++) {
492 asymbol
*gsym
= *gsymp
;
493 if ((gsym
->flags
& BSF_DEBUGGING
) == 0 &&
494 gsym
->section
== sym
->section
)
495 lookup_system_map(&addrs
, gsym
->name
,
496 sym
->value
- gsym
->value
);
500 *num_sym_addrs
= addrs
.size
;
501 if (addrs
.size
!= 0) {
502 struct supersect
*array_ss
= make_section(sbfd
,
504 void *buf
= sect_grow(array_ss
, addrs
.size
,
505 typeof(*addrs
.data
));
506 memcpy(buf
, addrs
.data
, addrs
.size
* sizeof(*addrs
.data
));
507 write_reloc(ss
, sym_addrs
, &array_ss
->symbol
,
508 buf
- array_ss
->contents
.data
);
516 void write_ksplice_system_map(struct superbfd
*sbfd
, asymbol
*sym
,
517 const char *addstr_sect
)
519 struct supersect
*smap_ss
= make_section(sbfd
, ".ksplice_system_map");
520 struct ksplice_system_map
*smap
;
521 const char *label
= label_lookup(sbfd
, sym
);
523 bool *done
= bool_hash_lookup(&system_map_written
, label
, TRUE
);
528 smap
= sect_grow(smap_ss
, 1, struct ksplice_system_map
);
530 write_system_map_array(sbfd
, smap_ss
, &smap
->candidates
,
531 &smap
->nr_candidates
, sym
);
532 write_string(smap_ss
, &smap
->label
, "%s%s", label
, addstr_sect
);
535 void write_ksplice_symbol(struct supersect
*ss
,
536 const struct ksplice_symbol
*const *addr
,
537 asymbol
*sym
, const char *addstr_sect
)
539 struct supersect
*ksymbol_ss
= make_section(ss
->parent
,
541 struct ksplice_symbol
*ksymbol
= sect_grow(ksymbol_ss
, 1,
542 struct ksplice_symbol
);
544 if (bfd_is_und_section(sym
->section
) || (sym
->flags
& BSF_GLOBAL
) != 0) {
545 write_string(ksymbol_ss
, &ksymbol
->name
, "%s", sym
->name
);
546 } else if (bfd_is_const_section(sym
->section
)) {
547 ksymbol
->name
= NULL
;
549 asymbol
*gsym
= canonical_symbol(ss
->parent
, sym
);
552 ksymbol
->name
= NULL
;
554 write_string(ksymbol_ss
, &ksymbol
->name
, "%s",
558 write_string(ksymbol_ss
, &ksymbol
->label
, "%s%s",
559 label_lookup(ss
->parent
, sym
), addstr_sect
);
561 write_ksplice_system_map(ksymbol_ss
->parent
, sym
, addstr_sect
);
563 write_reloc(ss
, addr
, &ksymbol_ss
->symbol
,
564 (void *)ksymbol
- ksymbol_ss
->contents
.data
);
567 void write_ksplice_reloc(struct supersect
*ss
, arelent
*orig_reloc
)
569 asymbol
*sym_ptr
= *orig_reloc
->sym_ptr_ptr
;
571 reloc_howto_type
*howto
= orig_reloc
->howto
;
573 bfd_vma addend
= get_reloc_offset(ss
, orig_reloc
, 0);
574 blot_section(ss
, orig_reloc
->address
, howto
);
576 struct supersect
*kreloc_ss
= make_section(ss
->parent
,
578 ".ksplice_init_relocs" :
580 struct ksplice_reloc
*kreloc
= sect_grow(kreloc_ss
, 1,
581 struct ksplice_reloc
);
583 write_reloc(kreloc_ss
, &kreloc
->blank_addr
,
584 &ss
->symbol
, orig_reloc
->address
);
585 kreloc
->blank_offset
= (unsigned long)orig_reloc
->address
;
586 write_ksplice_symbol(kreloc_ss
, &kreloc
->symbol
, sym_ptr
, "");
587 kreloc
->pcrel
= howto
->pc_relative
;
588 kreloc
->addend
= addend
;
589 kreloc
->size
= bfd_get_reloc_size(howto
);
590 kreloc
->dst_mask
= howto
->dst_mask
;
591 kreloc
->rightshift
= howto
->rightshift
;
592 kreloc
->signed_addend
=
593 (howto
->complain_on_overflow
== complain_overflow_signed
) ||
594 (howto
->complain_on_overflow
== complain_overflow_bitfield
);
597 #define CANARY(x, canary) ((x & ~howto->dst_mask) | (canary & howto->dst_mask))
599 void blot_section(struct supersect
*ss
, int offset
, reloc_howto_type
*howto
)
601 int bits
= bfd_get_reloc_size(howto
) * 8;
602 void *address
= ss
->contents
.data
+ offset
;
603 bfd_vma x
= bfd_get(bits
, ss
->parent
->abfd
, address
);
604 x
= (x
& ~howto
->dst_mask
) |
605 ((bfd_vma
)0x7777777777777777LL
& howto
->dst_mask
);
606 bfd_put(bits
, ss
->parent
->abfd
, x
, address
);
609 void write_ksplice_size(struct superbfd
*sbfd
, asymbol
**symp
)
611 asymbol
*sym
= *symp
;
612 struct supersect
*ksize_ss
= make_section(sbfd
, ".ksplice_sizes");
613 struct ksplice_size
*ksize
= sect_grow(ksize_ss
, 1,
614 struct ksplice_size
);
616 write_ksplice_symbol(ksize_ss
, &ksize
->symbol
, sym
,
617 mode("keep-primary") ? "(post)" : "");
618 ksize
->size
= bfd_get_section_size(sym
->section
);
620 if (starts_with(sym
->section
->name
, ".rodata"))
621 ksize
->flags
|= KSPLICE_SIZE_RODATA
;
622 if (starts_with(sym
->section
->name
, ".data"))
623 ksize
->flags
|= KSPLICE_SIZE_DATA
;
624 if (starts_with(sym
->section
->name
, ".text") ||
625 starts_with(sym
->section
->name
, ".exit.text"))
626 ksize
->flags
|= KSPLICE_SIZE_TEXT
;
627 assert(ksize
->flags
!= 0);
628 write_reloc(ksize_ss
, &ksize
->thismod_addr
, symp
, 0);
631 void write_ksplice_patch(struct superbfd
*sbfd
, const char *sectname
)
633 struct supersect
*kpatch_ss
= make_section(sbfd
, ".ksplice_patches");
634 struct ksplice_patch
*kpatch
= sect_grow(kpatch_ss
, 1,
635 struct ksplice_patch
);
636 asection
*sect
= bfd_get_section_by_name(sbfd
->abfd
, sectname
);
637 assert(sect
!= NULL
);
639 write_string(kpatch_ss
, &kpatch
->label
, "%s",
640 label_lookup(sbfd
, sect
->symbol
));
641 write_reloc(kpatch_ss
, &kpatch
->repladdr
, §
->symbol
, 0);
644 void write_ksplice_deleted_patch(struct superbfd
*sbfd
, const char *label
)
646 struct supersect
*kpatch_ss
= make_section(sbfd
, ".ksplice_patches");
647 struct ksplice_patch
*kpatch
= sect_grow(kpatch_ss
, 1,
648 struct ksplice_patch
);
650 write_string(kpatch_ss
, &kpatch
->label
, "%s", label
);
651 kpatch
->repladdr
= 0;
654 void write_ksplice_export(struct superbfd
*sbfd
, const char *symname
,
655 const char *export_type
, int del
)
657 struct supersect
*export_ss
= make_section(sbfd
, ".ksplice_exports");
658 struct ksplice_export
*export
= sect_grow(export_ss
, 1,
659 struct ksplice_export
);
662 write_string(export_ss
, &export
->name
, "%s", symname
);
663 write_string(export_ss
, &export
->new_name
,
664 "DISABLED_%s_%s", symname
, kid
);
666 write_string(export_ss
, &export
->new_name
, "%s", symname
);
667 write_string(export_ss
, &export
->name
, "DISABLED_%s_%s",
672 void filter_table_section(struct superbfd
*sbfd
, const struct table_section
*s
)
674 asection
*isection
= bfd_get_section_by_name(sbfd
->abfd
, s
->sectname
);
675 if (isection
== NULL
)
678 struct supersect
*ss
= fetch_supersect(sbfd
, isection
), orig_ss
;
679 supersect_move(&orig_ss
, ss
);
681 const void *orig_entry
;
682 for (orig_entry
= orig_ss
.contents
.data
;
683 orig_entry
< orig_ss
.contents
.data
+ orig_ss
.contents
.size
;
684 orig_entry
+= align(s
->entry_size
, 1 << ss
->alignment
)) {
686 read_reloc(&orig_ss
, orig_entry
, sizeof(void *), &sym
);
689 for (p
= sbfd
->abfd
->sections
; p
!= NULL
; p
= p
->next
) {
690 if (sym
->section
== p
691 && !is_table_section(p
) && !want_section(p
))
697 sect_copy(ss
, sect_do_grow(ss
, 1, s
->entry_size
,
699 &orig_ss
, orig_entry
, s
->entry_size
);
703 void mark_wanted_if_referenced(bfd
*abfd
, asection
*sect
, void *ignored
)
705 if (want_section(sect
))
707 if (!starts_with(sect
->name
, ".text")
708 && !starts_with(sect
->name
, ".exit.text")
709 && !starts_with(sect
->name
, ".rodata")
710 && !(starts_with(sect
->name
, ".data") && mode("keep-helper")))
713 if (mode("keep-helper")) {
714 struct superbfd
*sbfd
= fetch_superbfd(abfd
);
716 for (symp
= sbfd
->syms
.data
;
717 symp
< sbfd
->syms
.data
+ sbfd
->syms
.size
; symp
++) {
718 asymbol
*sym
= *symp
;
719 if (sym
->section
== sect
&&
720 (sym
->flags
& BSF_GLOBAL
) != 0) {
721 struct wsect
*w
= malloc(sizeof(*w
));
723 w
->next
= wanted_sections
;
730 bfd_map_over_sections(abfd
, check_for_ref_to_section
, sect
);
733 void check_for_ref_to_section(bfd
*abfd
, asection
*looking_at
,
736 if (!want_section(looking_at
) || is_table_section(looking_at
))
739 struct superbfd
*sbfd
= fetch_superbfd(abfd
);
740 struct supersect
*ss
= fetch_supersect(sbfd
, looking_at
);
742 for (relocp
= ss
->relocs
.data
;
743 relocp
< ss
->relocs
.data
+ ss
->relocs
.size
; relocp
++) {
744 asymbol
*sym
= *(*relocp
)->sym_ptr_ptr
;
745 if (sym
->section
== (asection
*)looking_for
&&
746 (!starts_with(sym
->section
->name
, ".text") ||
747 get_reloc_offset(ss
, *relocp
, 1) != 0)) {
748 struct wsect
*w
= malloc(sizeof(*w
));
749 w
->sect
= looking_for
;
750 w
->next
= wanted_sections
;
757 /* Modified function from GNU Binutils objcopy.c */
758 bfd_boolean
copy_object(bfd
*ibfd
, bfd
*obfd
)
760 assert(bfd_set_format(obfd
, bfd_get_format(ibfd
)));
762 bfd_vma start
= bfd_get_start_address(ibfd
);
764 flagword flags
= bfd_get_file_flags(ibfd
);
765 flags
&= bfd_applicable_file_flags(obfd
);
767 assert(bfd_set_start_address(obfd
, start
)
768 && bfd_set_file_flags(obfd
, flags
));
770 enum bfd_architecture iarch
= bfd_get_arch(ibfd
);
771 unsigned int imach
= bfd_get_mach(ibfd
);
772 assert(bfd_set_arch_mach(obfd
, iarch
, imach
));
773 assert(bfd_set_format(obfd
, bfd_get_format(ibfd
)));
775 /* BFD mandates that all output sections be created and sizes set before
776 any output is done. Thus, we traverse all sections multiple times. */
777 bfd_map_over_sections(ibfd
, setup_section
, obfd
);
779 struct supersect
*new_supersects
= fetch_superbfd(ibfd
)->new_supersects
;
780 struct supersect
*ss
;
781 for (ss
= new_supersects
; ss
!= NULL
; ss
= ss
->next
)
782 setup_new_section(obfd
, ss
);
784 /* Mark symbols used in output relocations so that they
785 are kept, even if they are local labels or static symbols.
787 Note we iterate over the input sections examining their
788 relocations since the relocations for the output sections
789 haven't been set yet. mark_symbols_used_in_relocations will
790 ignore input sections which have no corresponding output
793 bfd_map_over_sections(ibfd
, mark_symbols_used_in_relocations
, NULL
);
794 for (ss
= new_supersects
; ss
!= NULL
; ss
= ss
->next
)
795 ss_mark_symbols_used_in_relocations(ss
);
796 struct asymbolp_vec osyms
;
798 filter_symbols(ibfd
, obfd
, &osyms
, &fetch_superbfd(ibfd
)->syms
);
800 bfd_set_symtab(obfd
, osyms
.data
, osyms
.size
);
802 /* This has to happen after the symbol table has been set. */
803 bfd_map_over_sections(obfd
, write_section
, NULL
);
805 /* Allow the BFD backend to copy any private data it understands
806 from the input BFD to the output BFD. This is done last to
807 permit the routine to look at the filtered symbol table, which is
808 important for the ECOFF code at least. */
809 assert(bfd_copy_private_bfd_data(ibfd
, obfd
));
814 /* Modified function from GNU Binutils objcopy.c */
815 void setup_section(bfd
*ibfd
, asection
*isection
, void *obfdarg
)
820 if (!want_section(isection
))
823 asection
*osection
= bfd_make_section_anyway(obfd
, isection
->name
);
824 assert(osection
!= NULL
);
826 struct superbfd
*isbfd
= fetch_superbfd(ibfd
);
827 struct supersect
*ss
= fetch_supersect(isbfd
, isection
);
828 osection
->userdata
= ss
;
829 bfd_set_section_flags(obfd
, osection
, ss
->flags
);
830 ss
->symbol
= osection
->symbol
;
831 assert(bfd_set_section_size(obfd
, osection
, ss
->contents
.size
));
833 vma
= bfd_section_vma(ibfd
, isection
);
834 assert(bfd_set_section_vma(obfd
, osection
, vma
));
836 osection
->lma
= isection
->lma
;
837 assert(bfd_set_section_alignment(obfd
, osection
, ss
->alignment
));
838 osection
->entsize
= isection
->entsize
;
839 osection
->output_section
= osection
;
840 osection
->output_offset
= 0;
841 isection
->output_section
= osection
;
842 isection
->output_offset
= 0;
846 void setup_new_section(bfd
*obfd
, struct supersect
*ss
)
848 asection
*osection
= bfd_make_section_anyway(obfd
, ss
->name
);
849 assert(osection
!= NULL
);
850 bfd_set_section_flags(obfd
, osection
, ss
->flags
);
852 osection
->userdata
= ss
;
853 ss
->symbol
= osection
->symbol
;
854 assert(bfd_set_section_size(obfd
, osection
, ss
->contents
.size
));
855 assert(bfd_set_section_vma(obfd
, osection
, 0));
858 assert(bfd_set_section_alignment(obfd
, osection
, ss
->alignment
));
859 osection
->entsize
= 0;
860 osection
->output_section
= osection
;
861 osection
->output_offset
= 0;
864 void write_section(bfd
*obfd
, asection
*osection
, void *arg
)
866 struct supersect
*ss
= osection
->userdata
;
868 if ((ss
->flags
& SEC_GROUP
) != 0 || ss
->contents
.size
== 0)
873 for (relocp
= ss
->new_relocs
.data
;
874 relocp
< ss
->new_relocs
.data
+ ss
->new_relocs
.size
; relocp
++) {
876 if (bfd_get_arch(obfd
) == bfd_arch_arm
)
877 val
= osection
->use_rela_p
? 0 : (*relocp
)->addend
;
880 bfd_put(bfd_get_reloc_size((*relocp
)->howto
) * 8, obfd
, val
,
881 ss
->contents
.data
+ (*relocp
)->address
);
882 if (bfd_install_relocation(obfd
, *relocp
, ss
->contents
.data
,
883 0, osection
, &error_message
) !=
885 fprintf(stderr
, "ksplice: error installing reloc: %s",
890 memcpy(vec_grow(&ss
->relocs
, ss
->new_relocs
.size
), ss
->new_relocs
.data
,
891 ss
->new_relocs
.size
* sizeof(*ss
->new_relocs
.data
));
893 bfd_set_reloc(obfd
, osection
,
894 ss
->relocs
.size
== 0 ? NULL
: ss
->relocs
.data
,
897 if (ss
->flags
& SEC_HAS_CONTENTS
)
898 assert(bfd_set_section_contents
899 (obfd
, osection
, ss
->contents
.data
, 0,
903 /* Modified function from GNU Binutils objcopy.c
905 * Mark all the symbols which will be used in output relocations with
906 * the BSF_KEEP flag so that those symbols will not be stripped.
908 * Ignore relocations which will not appear in the output file.
910 void mark_symbols_used_in_relocations(bfd
*abfd
, asection
*isection
,
913 struct superbfd
*sbfd
= fetch_superbfd(abfd
);
914 if (isection
->output_section
== NULL
)
917 struct supersect
*ss
= fetch_supersect(sbfd
, isection
);
918 ss_mark_symbols_used_in_relocations(ss
);
921 void ss_mark_symbols_used_in_relocations(struct supersect
*ss
)
923 /* Examine each symbol used in a relocation. If it's not one of the
924 special bfd section symbols, then mark it with BSF_KEEP. */
926 for (relocp
= ss
->relocs
.data
;
927 relocp
< ss
->relocs
.data
+ ss
->relocs
.size
; relocp
++) {
928 asymbol
*sym
= *(*relocp
)->sym_ptr_ptr
;
929 if (!(bfd_is_const_section(sym
->section
) &&
930 sym
== sym
->section
->symbol
))
931 sym
->flags
|= BSF_KEEP
;
935 static int deleted_table_section_symbol(bfd
*abfd
, asymbol
*sym
)
937 struct superbfd
*sbfd
= fetch_superbfd(abfd
);
938 struct supersect
*ss
= fetch_supersect(sbfd
, sym
->section
);
940 if (bfd_is_const_section(sym
->section
))
944 for (symp
= ss
->syms
.data
; symp
< ss
->syms
.data
+ ss
->syms
.size
; symp
++) {
948 return symp
>= ss
->syms
.data
+ ss
->syms
.size
;
951 /* Modified function from GNU Binutils objcopy.c
953 * Choose which symbol entries to copy.
954 * We don't copy in place, because that confuses the relocs.
955 * Return the number of symbols to print.
957 void filter_symbols(bfd
*ibfd
, bfd
*obfd
, struct asymbolp_vec
*osyms
,
958 struct asymbolp_vec
*isyms
)
961 for (symp
= isyms
->data
; symp
< isyms
->data
+ isyms
->size
; symp
++) {
962 asymbol
*sym
= *symp
;
966 if (mode("keep") && (sym
->flags
& BSF_GLOBAL
) != 0 &&
967 !(mode("keep-primary") &&
968 str_in_set(sym
->section
->name
, &newsects
)))
969 sym
->flags
= (sym
->flags
& ~BSF_GLOBAL
) | BSF_LOCAL
;
971 if (mode("finalize") && (sym
->flags
& BSF_GLOBAL
) != 0)
972 sym
->flags
= (sym
->flags
& ~BSF_GLOBAL
) | BSF_LOCAL
;
974 if ((sym
->flags
& BSF_KEEP
) != 0 /* Used in relocation. */
975 || ((sym
->flags
& BSF_SECTION_SYM
) != 0
976 && ((*(sym
->section
)->symbol_ptr_ptr
)->flags
979 else if ((sym
->flags
& (BSF_GLOBAL
| BSF_WEAK
)) != 0)
981 else if (bfd_decode_symclass(sym
) == 'I')
982 /* Global symbols in $idata sections need to be retained.
983 External users of the library containing the $idata
984 section may reference these symbols. */
986 else if ((sym
->flags
& BSF_GLOBAL
) != 0
987 || (sym
->flags
& BSF_WEAK
) != 0
988 || bfd_is_com_section(sym
->section
))
990 else if ((sym
->flags
& BSF_DEBUGGING
) != 0)
993 keep
= !bfd_is_local_label(ibfd
, sym
);
995 if (!want_section(sym
->section
))
998 if (deleted_table_section_symbol(ibfd
, sym
) == 1)
1001 if (mode("rmsyms") && str_in_set(sym
->name
, &rmsyms
))
1005 *vec_grow(osyms
, 1) = sym
;
1009 void read_str_set(struct str_vec
*strs
)
1013 assert(getline(&buf
, &n
, stdin
) >= 0);
1017 char *str
= strtok_r(buf
, " \n", &saveptr
);
1021 *vec_grow(strs
, 1) = str
;
1025 int str_in_set(const char *str
, const struct str_vec
*strs
)
1028 for (strp
= strs
->data
; strp
< strs
->data
+ strs
->size
; strp
++) {
1029 if (strcmp(str
, *strp
) == 0)
1035 int want_section(asection
*sect
)
1040 if (mode("keep-primary") && bfd_is_abs_section(sect
))
1042 const struct wsect
*w
= wanted_sections
;
1043 for (; w
!= NULL
; w
= w
->next
) {
1044 if (w
->sect
== sect
)
1048 if (starts_with(sect
->name
, ".ksplice"))
1050 if (mode("keep-helper") && starts_with(sect
->name
, ".text"))
1052 if (mode("keep-helper") && starts_with(sect
->name
, ".exit.text")
1053 && bfd_get_section_by_name(sect
->owner
, ".exitcall.exit") == NULL
)
1055 if (mode("keep-primary") && str_in_set(sect
->name
, §ions
))
1057 if (mode("keep-primary") && str_in_set(sect
->name
, &newsects
))
1060 if (mode("keep-helper") && starts_with(sect
->name
, "__ksymtab"))
1062 if (mode("keep-helper") && starts_with(sect
->name
, "__kcrctab"))
1065 if (is_special(sect
))
1071 const struct table_section
*is_table_section(asection
*sect
)
1073 const struct table_section
*ss
;
1074 for (ss
= table_sections
; ss
!= end_table_sections
; ss
++) {
1075 if (strcmp(ss
->sectname
, sect
->name
) == 0)