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_section 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_section(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 filter_ex_table_section(struct superbfd
*sbfd
);
92 void mark_wanted_if_referenced(bfd
*abfd
, asection
*sect
, void *ignored
);
93 void check_for_ref_to_section(bfd
*abfd
, asection
*looking_at
,
95 bfd_boolean
copy_object(bfd
*ibfd
, bfd
*obfd
);
96 void setup_section(bfd
*ibfd
, asection
*isection
, void *obfdarg
);
97 static void setup_new_section(bfd
*obfd
, struct supersect
*ss
);
98 static void write_section(bfd
*obfd
, asection
*osection
, void *arg
);
99 void mark_symbols_used_in_relocations(bfd
*abfd
, asection
*isection
,
101 static void ss_mark_symbols_used_in_relocations(struct supersect
*ss
);
102 void filter_symbols(bfd
*ibfd
, bfd
*obfd
, struct asymbolp_vec
*osyms
,
103 struct asymbolp_vec
*isyms
);
104 static bool deleted_table_section_symbol(bfd
*abfd
, asymbol
*sym
);
105 void read_str_set(struct str_vec
*strs
);
106 bool str_in_set(const char *str
, const struct str_vec
*strs
);
107 bool want_section(asection
*sect
);
108 bool is_table_section(asection
*sect
);
109 struct supersect
*make_section(struct superbfd
*sbfd
, const char *name
);
110 void __attribute__((format(printf
, 3, 4)))
111 write_string(struct supersect
*ss
, const char **addr
, const char *fmt
, ...);
112 void rm_some_exports(struct superbfd
*isbfd
, const struct export_desc
*ed
);
113 void write_ksplice_export(struct superbfd
*sbfd
, const char *symname
,
114 const char *export_type
, bool del
);
115 void write_reloc(struct supersect
*ss
, const void *addr
, asymbol
**symp
,
117 arelent
*create_reloc(struct supersect
*ss
, const void *addr
, asymbol
**symp
,
120 struct str_vec sections
, newsects
, delsects
, rmsyms
;
121 struct export_desc_vec exports
;
123 const char *modestr
, *kid
;
125 struct wsect
*wanted_sections
= NULL
;
127 const struct table_section table_sections
[] = {
128 {".altinstructions", 2 * sizeof(void *) + 4},
129 {".smp_locks", sizeof(void *)},
130 {".parainstructions", sizeof(void *) + 4},
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 bool 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_section(isbfd
, symp
);
269 if (mode("keep-primary")) {
271 for (sect
= isbfd
->abfd
->sections
; sect
!= NULL
;
273 if (str_in_set(sect
->name
, §ions
) ||
274 (starts_with(sect
->name
, ".text") &&
275 want_section(sect
) &&
276 !str_in_set(sect
->name
, &newsects
)))
277 write_ksplice_patch(isbfd
, sect
->name
);
281 for (label
= delsects
.data
;
282 label
< delsects
.data
+ delsects
.size
; label
++)
283 write_ksplice_deleted_patch(isbfd
, *label
);
285 const struct export_desc
*ed
;
286 for (ed
= exports
.data
; ed
< exports
.data
+ exports
.size
;
288 if (starts_with(ed
->sectname
, "del___ksymtab")) {
289 const char *export_type
=
290 ed
->sectname
+ strlen("del___ksymtab");
291 const char **symname
;
292 for (symname
= ed
->names
.data
;
293 symname
< ed
->names
.data
+ ed
->names
.size
;
295 write_ksplice_export(isbfd
, *symname
,
298 rm_some_exports(isbfd
, ed
);
304 for (p
= ibfd
->sections
; p
!= NULL
; p
= p
->next
) {
305 struct supersect
*ss
= fetch_supersect(isbfd
, p
);
306 if (is_table_section(p
) || starts_with(p
->name
, ".ksplice") ||
307 strcmp(p
->name
, ".fixup") == 0)
309 if (want_section(p
) || mode("rmsyms"))
313 const struct table_section
*ss
;
315 for (ss
= table_sections
; ss
!= end_table_sections
; ss
++)
316 filter_table_section(isbfd
, ss
);
317 filter_ex_table_section(isbfd
);
320 copy_object(ibfd
, obfd
);
321 assert(bfd_close(obfd
));
322 assert(bfd_close(ibfd
));
326 void rm_some_exports(struct superbfd
*isbfd
, const struct export_desc
*ed
)
328 assert(starts_with(ed
->sectname
, "__ksymtab"));
329 const char *export_type
= ed
->sectname
+ strlen("__ksymtab");
330 asection
*sym_sect
= bfd_get_section_by_name(isbfd
->abfd
, ed
->sectname
);
331 assert(sym_sect
!= NULL
);
332 char *export_crc_name
;
333 assert(asprintf(&export_crc_name
, "__kcrctab%s", export_type
) >= 0);
334 asection
*crc_sect
= bfd_get_section_by_name(isbfd
->abfd
,
336 struct supersect
*ss
, *crc_ss
= NULL
;
337 ss
= fetch_supersect(isbfd
, sym_sect
);
338 if (crc_sect
!= NULL
)
339 crc_ss
= fetch_supersect(isbfd
, crc_sect
);
342 assert(ss
->contents
.size
* sizeof(unsigned long) ==
343 crc_ss
->contents
.size
* sizeof(struct kernel_symbol
));
345 struct supersect orig_ss
, orig_crc_ss
;
346 supersect_move(&orig_ss
, ss
);
348 supersect_move(&orig_crc_ss
, crc_ss
);
350 struct kernel_symbol
*orig_ksym
;
351 unsigned long *orig_crc
;
352 for (orig_ksym
= orig_ss
.contents
.data
,
353 orig_crc
= orig_crc_ss
.contents
.data
;
354 (void *)orig_ksym
< orig_ss
.contents
.data
+ orig_ss
.contents
.size
;
355 orig_ksym
++, orig_crc
++) {
357 read_reloc(&orig_ss
, &orig_ksym
->value
,
358 sizeof(orig_ksym
->value
), &sym
);
359 if (!str_in_set(sym
->name
, &ed
->names
))
362 struct kernel_symbol
*ksym
= sect_grow(ss
, 1, typeof(*ksym
));
363 sect_copy(ss
, &ksym
->value
, &orig_ss
, &orig_ksym
->value
, 1);
364 /* Replace name with a mangled name */
365 write_ksplice_export(ss
->parent
, sym
->name
, export_type
, false);
366 write_string(ss
, (const char **)&ksym
->name
,
367 "DISABLED_%s_%s", sym
->name
, kid
);
371 sect_grow(crc_ss
, 1, typeof(*orig_crc
)),
372 &orig_crc_ss
, orig_crc
, 1);
376 void rm_some_relocs(struct supersect
*ss
)
378 struct arelentp_vec orig_relocs
;
379 vec_move(&orig_relocs
, &ss
->relocs
);
382 for (relocp
= orig_relocs
.data
;
383 relocp
< orig_relocs
.data
+ orig_relocs
.size
; relocp
++) {
384 bool rm_reloc
= false;
385 asymbol
*sym_ptr
= *(*relocp
)->sym_ptr_ptr
;
387 if (mode("rmsyms") && str_in_set(sym_ptr
->name
, &rmsyms
))
393 if (mode("keep-primary") && want_section(sym_ptr
->section
) &&
394 (str_in_set(sym_ptr
->section
->name
, &newsects
) ||
395 bfd_is_const_section(sym_ptr
->section
) ||
396 starts_with(sym_ptr
->section
->name
, ".rodata.str")))
399 if (mode("finalize") && bfd_is_und_section(sym_ptr
->section
))
403 write_ksplice_reloc(ss
, *relocp
);
405 *vec_grow(&ss
->relocs
, 1) = *relocp
;
409 struct supersect
*make_section(struct superbfd
*sbfd
, const char *name
)
411 asection
*sect
= bfd_get_section_by_name(sbfd
->abfd
, name
);
413 return fetch_supersect(sbfd
, sect
);
415 return new_supersect(sbfd
, name
);
418 arelent
*create_reloc(struct supersect
*ss
, const void *addr
, asymbol
**symp
,
421 bfd_reloc_code_real_type code
;
422 switch (bfd_arch_bits_per_address(ss
->parent
->abfd
)) {
433 arelent
*reloc
= malloc(sizeof(*reloc
));
434 reloc
->sym_ptr_ptr
= symp
;
435 reloc
->address
= addr
- ss
->contents
.data
;
436 reloc
->howto
= bfd_reloc_type_lookup(ss
->parent
->abfd
, code
);
437 reloc
->addend
= offset
;
441 void write_reloc(struct supersect
*ss
, const void *addr
, asymbol
**symp
,
444 arelent
*new_reloc
= create_reloc(ss
, addr
, symp
, offset
), **relocp
;
445 for (relocp
= ss
->relocs
.data
;
446 relocp
< ss
->relocs
.data
+ ss
->relocs
.size
; relocp
++) {
447 if ((*relocp
)->address
== new_reloc
->address
) {
450 (void *)(ss
->relocs
.data
+ ss
->relocs
.size
) -
451 (void *)(relocp
+ 1));
456 *vec_grow(&ss
->new_relocs
, 1) = new_reloc
;
459 void write_string(struct supersect
*ss
, const char **addr
, const char *fmt
, ...)
463 int len
= vsnprintf(NULL
, 0, fmt
, ap
);
465 struct supersect
*str_ss
= make_section(ss
->parent
, ".ksplice_str");
466 char *buf
= sect_grow(str_ss
, len
+ 1, char);
468 vsnprintf(buf
, len
+ 1, fmt
, ap
);
471 write_reloc(ss
, addr
, &str_ss
->symbol
,
472 (void *)buf
- str_ss
->contents
.data
);
475 void lookup_system_map(struct addr_vec
*addrs
, const char *name
, long offset
)
477 struct addr_vec
*map_addrs
=
478 addr_vec_hash_lookup(&system_map
, name
, FALSE
);
479 if (map_addrs
== NULL
)
482 unsigned long *addr
, *map_addr
;
483 for (map_addr
= map_addrs
->data
;
484 map_addr
< map_addrs
->data
+ map_addrs
->size
; map_addr
++) {
485 for (addr
= addrs
->data
; addr
< addrs
->data
+ addrs
->size
;
487 if (*addr
== *map_addr
+ offset
)
490 if (addr
< addrs
->data
+ addrs
->size
)
492 *vec_grow(addrs
, 1) = *map_addr
+ offset
;
496 void write_system_map_array(struct superbfd
*sbfd
, struct supersect
*ss
,
497 const unsigned long **sym_addrs
,
498 unsigned long *num_sym_addrs
, asymbol
*sym
)
500 struct addr_vec addrs
;
503 if (bfd_is_abs_section(sym
->section
)) {
504 *vec_grow(&addrs
, 1) = sym
->value
;
505 } else if (bfd_is_und_section(sym
->section
)) {
506 lookup_system_map(&addrs
, sym
->name
, 0);
507 } else if (!bfd_is_const_section(sym
->section
)) {
509 for (gsymp
= sbfd
->syms
.data
;
510 gsymp
< sbfd
->syms
.data
+ sbfd
->syms
.size
; gsymp
++) {
511 asymbol
*gsym
= *gsymp
;
512 if ((gsym
->flags
& BSF_DEBUGGING
) == 0 &&
513 gsym
->section
== sym
->section
)
514 lookup_system_map(&addrs
, gsym
->name
,
515 sym
->value
- gsym
->value
);
519 *num_sym_addrs
= addrs
.size
;
520 if (addrs
.size
!= 0) {
521 struct supersect
*array_ss
= make_section(sbfd
,
523 void *buf
= sect_grow(array_ss
, addrs
.size
,
524 typeof(*addrs
.data
));
525 memcpy(buf
, addrs
.data
, addrs
.size
* sizeof(*addrs
.data
));
526 write_reloc(ss
, sym_addrs
, &array_ss
->symbol
,
527 buf
- array_ss
->contents
.data
);
535 void write_ksplice_system_map(struct superbfd
*sbfd
, asymbol
*sym
,
536 const char *addstr_sect
)
538 struct supersect
*smap_ss
= make_section(sbfd
, ".ksplice_system_map");
539 struct ksplice_system_map
*smap
;
540 const char *label
= label_lookup(sbfd
, sym
);
542 bool *done
= bool_hash_lookup(&system_map_written
, label
, TRUE
);
547 smap
= sect_grow(smap_ss
, 1, struct ksplice_system_map
);
549 write_system_map_array(sbfd
, smap_ss
, &smap
->candidates
,
550 &smap
->nr_candidates
, sym
);
551 write_string(smap_ss
, &smap
->label
, "%s%s", label
, addstr_sect
);
554 void write_ksplice_symbol(struct supersect
*ss
,
555 const struct ksplice_symbol
*const *addr
,
556 asymbol
*sym
, const char *addstr_sect
)
558 struct supersect
*ksymbol_ss
= make_section(ss
->parent
,
560 struct ksplice_symbol
*ksymbol
= sect_grow(ksymbol_ss
, 1,
561 struct ksplice_symbol
);
563 if (bfd_is_und_section(sym
->section
) || (sym
->flags
& BSF_GLOBAL
) != 0) {
564 write_string(ksymbol_ss
, &ksymbol
->name
, "%s", sym
->name
);
565 } else if (bfd_is_const_section(sym
->section
)) {
566 ksymbol
->name
= NULL
;
568 asymbol
*gsym
= canonical_symbol(ss
->parent
, sym
);
571 ksymbol
->name
= NULL
;
573 write_string(ksymbol_ss
, &ksymbol
->name
, "%s",
577 write_string(ksymbol_ss
, &ksymbol
->label
, "%s%s",
578 label_lookup(ss
->parent
, sym
), addstr_sect
);
580 write_ksplice_system_map(ksymbol_ss
->parent
, sym
, addstr_sect
);
582 write_reloc(ss
, addr
, &ksymbol_ss
->symbol
,
583 (void *)ksymbol
- ksymbol_ss
->contents
.data
);
586 void write_ksplice_reloc(struct supersect
*ss
, arelent
*orig_reloc
)
588 asymbol
*sym_ptr
= *orig_reloc
->sym_ptr_ptr
;
590 reloc_howto_type
*howto
= orig_reloc
->howto
;
592 bfd_vma addend
= get_reloc_offset(ss
, orig_reloc
, false);
593 blot_section(ss
, orig_reloc
->address
, howto
);
595 struct supersect
*kreloc_ss
= make_section(ss
->parent
,
597 ".ksplice_init_relocs" :
599 struct ksplice_reloc
*kreloc
= sect_grow(kreloc_ss
, 1,
600 struct ksplice_reloc
);
602 write_reloc(kreloc_ss
, &kreloc
->blank_addr
,
603 &ss
->symbol
, orig_reloc
->address
);
604 kreloc
->blank_offset
= (unsigned long)orig_reloc
->address
;
605 write_ksplice_symbol(kreloc_ss
, &kreloc
->symbol
, sym_ptr
, "");
606 kreloc
->pcrel
= howto
->pc_relative
;
607 kreloc
->addend
= addend
;
608 kreloc
->size
= bfd_get_reloc_size(howto
);
609 kreloc
->dst_mask
= howto
->dst_mask
;
610 kreloc
->rightshift
= howto
->rightshift
;
611 kreloc
->signed_addend
=
612 (howto
->complain_on_overflow
== complain_overflow_signed
) ||
613 (howto
->complain_on_overflow
== complain_overflow_bitfield
);
616 #define CANARY(x, canary) ((x & ~howto->dst_mask) | (canary & howto->dst_mask))
618 void blot_section(struct supersect
*ss
, int offset
, reloc_howto_type
*howto
)
620 int bits
= bfd_get_reloc_size(howto
) * 8;
621 void *address
= ss
->contents
.data
+ offset
;
622 bfd_vma x
= bfd_get(bits
, ss
->parent
->abfd
, address
);
623 x
= (x
& ~howto
->dst_mask
) |
624 ((bfd_vma
)KSPLICE_CANARY
& howto
->dst_mask
);
625 bfd_put(bits
, ss
->parent
->abfd
, x
, address
);
628 void write_ksplice_section(struct superbfd
*sbfd
, asymbol
**symp
)
630 asymbol
*sym
= *symp
;
631 struct supersect
*ksect_ss
= make_section(sbfd
, ".ksplice_sections");
632 struct ksplice_section
*ksect
= sect_grow(ksect_ss
, 1,
633 struct ksplice_section
);
635 write_ksplice_symbol(ksect_ss
, &ksect
->symbol
, sym
,
636 mode("keep-primary") ? "(post)" : "");
637 ksect
->size
= bfd_get_section_size(sym
->section
);
639 if (starts_with(sym
->section
->name
, ".rodata"))
640 ksect
->flags
|= KSPLICE_SECTION_RODATA
;
641 if (starts_with(sym
->section
->name
, ".data"))
642 ksect
->flags
|= KSPLICE_SECTION_DATA
;
643 if (starts_with(sym
->section
->name
, ".text") ||
644 starts_with(sym
->section
->name
, ".exit.text"))
645 ksect
->flags
|= KSPLICE_SECTION_TEXT
;
646 assert(ksect
->flags
!= 0);
647 write_reloc(ksect_ss
, &ksect
->thismod_addr
, symp
, 0);
650 void write_ksplice_patch(struct superbfd
*sbfd
, const char *sectname
)
652 struct supersect
*kpatch_ss
= make_section(sbfd
, ".ksplice_patches");
653 struct ksplice_patch
*kpatch
= sect_grow(kpatch_ss
, 1,
654 struct ksplice_patch
);
655 asection
*sect
= bfd_get_section_by_name(sbfd
->abfd
, sectname
);
656 assert(sect
!= NULL
);
658 write_string(kpatch_ss
, &kpatch
->label
, "%s",
659 label_lookup(sbfd
, sect
->symbol
));
660 write_reloc(kpatch_ss
, &kpatch
->trampoline
.repladdr
, §
->symbol
, 0);
663 void write_ksplice_deleted_patch(struct superbfd
*sbfd
, const char *label
)
665 struct supersect
*kpatch_ss
= make_section(sbfd
, ".ksplice_patches");
666 struct ksplice_patch
*kpatch
= sect_grow(kpatch_ss
, 1,
667 struct ksplice_patch
);
669 write_string(kpatch_ss
, &kpatch
->label
, "%s", label
);
670 kpatch
->trampoline
.repladdr
= 0;
673 void write_ksplice_export(struct superbfd
*sbfd
, const char *symname
,
674 const char *export_type
, bool del
)
676 struct supersect
*export_ss
= make_section(sbfd
, ".ksplice_exports");
677 struct ksplice_export
*exp
= sect_grow(export_ss
, 1,
678 struct ksplice_export
);
681 write_string(export_ss
, &exp
->name
, "%s", symname
);
682 write_string(export_ss
, &exp
->new_name
, "DISABLED_%s_%s",
685 write_string(export_ss
, &exp
->new_name
, "%s", symname
);
686 write_string(export_ss
, &exp
->name
, "DISABLED_%s_%s", symname
,
691 void filter_table_section(struct superbfd
*sbfd
, const struct table_section
*s
)
693 asection
*isection
= bfd_get_section_by_name(sbfd
->abfd
, s
->sectname
);
694 if (isection
== NULL
)
697 struct supersect
*ss
= fetch_supersect(sbfd
, isection
), orig_ss
;
698 supersect_move(&orig_ss
, ss
);
700 const void *orig_entry
;
701 for (orig_entry
= orig_ss
.contents
.data
;
702 orig_entry
< orig_ss
.contents
.data
+ orig_ss
.contents
.size
;
703 orig_entry
+= align(s
->entry_size
, 1 << ss
->alignment
)) {
705 read_reloc(&orig_ss
, orig_entry
, sizeof(void *), &sym
);
708 for (p
= sbfd
->abfd
->sections
; p
!= NULL
; p
= p
->next
) {
709 if (sym
->section
== p
710 && !is_table_section(p
) && !want_section(p
))
716 sect_copy(ss
, sect_do_grow(ss
, 1, s
->entry_size
,
718 &orig_ss
, orig_entry
, s
->entry_size
);
727 DECLARE_VEC_TYPE(struct fixup_entry
, fixup_entry_vec
);
729 int compare_fixups(const void *aptr
, const void *bptr
)
731 const struct fixup_entry
*a
= aptr
, *b
= bptr
;
732 if (a
->offset
< b
->offset
)
734 else if (a
->offset
> b
->offset
)
737 return (int)a
->used
- (int)b
->used
;
740 void filter_ex_table_section(struct superbfd
*sbfd
)
742 asection
*isection
= bfd_get_section_by_name(sbfd
->abfd
, "__ex_table");
743 if (isection
== NULL
)
745 asection
*fixup_sect
= bfd_get_section_by_name(sbfd
->abfd
, ".fixup");
747 struct supersect
*ss
= fetch_supersect(sbfd
, isection
), orig_ss
;
748 supersect_move(&orig_ss
, ss
);
750 struct supersect
*fixup_ss
= NULL
;
751 if (fixup_sect
!= NULL
)
752 fixup_ss
= fetch_supersect(sbfd
, fixup_sect
);
754 struct fixup_entry_vec fixups
;
757 const struct exception_table_entry
*orig_entry
;
758 for (orig_entry
= orig_ss
.contents
.data
;
759 (void *)orig_entry
< orig_ss
.contents
.data
+ orig_ss
.contents
.size
;
761 asymbol
*sym
, *fixup_sym
;
762 read_reloc(&orig_ss
, &orig_entry
->insn
,
763 sizeof(orig_entry
->insn
), &sym
);
765 struct fixup_entry
*f
;
766 bfd_vma fixup_offset
= read_reloc(&orig_ss
, &orig_entry
->fixup
,
767 sizeof(orig_entry
->fixup
),
769 if (fixup_sym
->section
== fixup_sect
) {
770 assert(fixup_offset
< fixup_ss
->contents
.size
);
771 f
= vec_grow(&fixups
, 1);
772 f
->offset
= fixup_offset
;
777 for (p
= sbfd
->abfd
->sections
; p
!= NULL
; p
= p
->next
) {
778 if (sym
->section
== p
779 && !is_table_section(p
) && !want_section(p
))
785 if (fixup_sym
->section
== fixup_sect
) {
787 f
->ex_offset
= ss
->contents
.size
;
789 sect_copy(ss
, sect_grow(ss
, 1, struct exception_table_entry
),
790 &orig_ss
, orig_entry
, 1);
793 if (fixup_sect
== NULL
)
796 struct supersect orig_fixup_ss
;
797 supersect_move(&orig_fixup_ss
, fixup_ss
);
799 qsort(fixups
.data
, fixups
.size
, sizeof(*fixups
.data
), compare_fixups
);
800 *vec_grow(&fixups
, 1) = (struct fixup_entry
)
801 { .offset
= orig_fixup_ss
.contents
.size
, .used
= false };
803 struct fixup_entry
*f
;
804 for (f
= fixups
.data
; f
< fixups
.data
+ fixups
.size
- 1; f
++) {
807 write_reloc(ss
, ss
->contents
.data
+ f
->ex_offset
,
808 &fixup_ss
->symbol
, fixup_ss
->contents
.size
);
810 sect_grow(fixup_ss
, (f
+ 1)->offset
- f
->offset
,
813 orig_fixup_ss
.contents
.data
+ f
->offset
,
814 (f
+ 1)->offset
- f
->offset
);
818 void mark_wanted_if_referenced(bfd
*abfd
, asection
*sect
, void *ignored
)
820 if (want_section(sect
))
822 if (!starts_with(sect
->name
, ".text")
823 && !starts_with(sect
->name
, ".exit.text")
824 && !starts_with(sect
->name
, ".rodata")
825 && !(starts_with(sect
->name
, ".data") && mode("keep-helper")))
828 if (mode("keep-helper")) {
829 struct superbfd
*sbfd
= fetch_superbfd(abfd
);
831 for (symp
= sbfd
->syms
.data
;
832 symp
< sbfd
->syms
.data
+ sbfd
->syms
.size
; symp
++) {
833 asymbol
*sym
= *symp
;
834 if (sym
->section
== sect
&&
835 (sym
->flags
& BSF_GLOBAL
) != 0) {
836 struct wsect
*w
= malloc(sizeof(*w
));
838 w
->next
= wanted_sections
;
845 bfd_map_over_sections(abfd
, check_for_ref_to_section
, sect
);
848 void check_for_ref_to_section(bfd
*abfd
, asection
*looking_at
,
851 if (!want_section(looking_at
) || is_table_section(looking_at
))
854 struct superbfd
*sbfd
= fetch_superbfd(abfd
);
855 struct supersect
*ss
= fetch_supersect(sbfd
, looking_at
);
857 for (relocp
= ss
->relocs
.data
;
858 relocp
< ss
->relocs
.data
+ ss
->relocs
.size
; relocp
++) {
859 asymbol
*sym
= *(*relocp
)->sym_ptr_ptr
;
860 if (sym
->section
== (asection
*)looking_for
&&
861 (!starts_with(sym
->section
->name
, ".text") ||
862 (get_reloc_offset(ss
, *relocp
, true) != 0 &&
863 strcmp(looking_at
->name
, ".fixup") != 0))) {
864 struct wsect
*w
= malloc(sizeof(*w
));
865 w
->sect
= looking_for
;
866 w
->next
= wanted_sections
;
873 /* Modified function from GNU Binutils objcopy.c */
874 bfd_boolean
copy_object(bfd
*ibfd
, bfd
*obfd
)
876 assert(bfd_set_format(obfd
, bfd_get_format(ibfd
)));
878 bfd_vma start
= bfd_get_start_address(ibfd
);
880 flagword flags
= bfd_get_file_flags(ibfd
);
881 flags
&= bfd_applicable_file_flags(obfd
);
883 assert(bfd_set_start_address(obfd
, start
)
884 && bfd_set_file_flags(obfd
, flags
));
886 enum bfd_architecture iarch
= bfd_get_arch(ibfd
);
887 unsigned int imach
= bfd_get_mach(ibfd
);
888 assert(bfd_set_arch_mach(obfd
, iarch
, imach
));
889 assert(bfd_set_format(obfd
, bfd_get_format(ibfd
)));
891 /* BFD mandates that all output sections be created and sizes set before
892 any output is done. Thus, we traverse all sections multiple times. */
893 bfd_map_over_sections(ibfd
, setup_section
, obfd
);
895 struct supersect
*new_supersects
= fetch_superbfd(ibfd
)->new_supersects
;
896 struct supersect
*ss
;
897 for (ss
= new_supersects
; ss
!= NULL
; ss
= ss
->next
)
898 setup_new_section(obfd
, ss
);
900 /* Mark symbols used in output relocations so that they
901 are kept, even if they are local labels or static symbols.
903 Note we iterate over the input sections examining their
904 relocations since the relocations for the output sections
905 haven't been set yet. mark_symbols_used_in_relocations will
906 ignore input sections which have no corresponding output
909 bfd_map_over_sections(ibfd
, mark_symbols_used_in_relocations
, NULL
);
910 for (ss
= new_supersects
; ss
!= NULL
; ss
= ss
->next
)
911 ss_mark_symbols_used_in_relocations(ss
);
912 struct asymbolp_vec osyms
;
914 filter_symbols(ibfd
, obfd
, &osyms
, &fetch_superbfd(ibfd
)->syms
);
916 bfd_set_symtab(obfd
, osyms
.data
, osyms
.size
);
918 /* This has to happen after the symbol table has been set. */
919 bfd_map_over_sections(obfd
, write_section
, NULL
);
921 /* Allow the BFD backend to copy any private data it understands
922 from the input BFD to the output BFD. This is done last to
923 permit the routine to look at the filtered symbol table, which is
924 important for the ECOFF code at least. */
925 assert(bfd_copy_private_bfd_data(ibfd
, obfd
));
930 /* Modified function from GNU Binutils objcopy.c */
931 void setup_section(bfd
*ibfd
, asection
*isection
, void *obfdarg
)
936 if (!want_section(isection
))
939 asection
*osection
= bfd_make_section_anyway(obfd
, isection
->name
);
940 assert(osection
!= NULL
);
942 struct superbfd
*isbfd
= fetch_superbfd(ibfd
);
943 struct supersect
*ss
= fetch_supersect(isbfd
, isection
);
944 osection
->userdata
= ss
;
945 bfd_set_section_flags(obfd
, osection
, ss
->flags
);
946 ss
->symbol
= osection
->symbol
;
947 assert(bfd_set_section_size(obfd
, osection
, ss
->contents
.size
));
949 vma
= bfd_section_vma(ibfd
, isection
);
950 assert(bfd_set_section_vma(obfd
, osection
, vma
));
952 osection
->lma
= isection
->lma
;
953 assert(bfd_set_section_alignment(obfd
, osection
, ss
->alignment
));
954 osection
->entsize
= isection
->entsize
;
955 osection
->output_section
= osection
;
956 osection
->output_offset
= 0;
957 isection
->output_section
= osection
;
958 isection
->output_offset
= 0;
962 void setup_new_section(bfd
*obfd
, struct supersect
*ss
)
964 asection
*osection
= bfd_make_section_anyway(obfd
, ss
->name
);
965 assert(osection
!= NULL
);
966 bfd_set_section_flags(obfd
, osection
, ss
->flags
);
968 osection
->userdata
= ss
;
969 ss
->symbol
= osection
->symbol
;
970 assert(bfd_set_section_size(obfd
, osection
, ss
->contents
.size
));
971 assert(bfd_set_section_vma(obfd
, osection
, 0));
974 assert(bfd_set_section_alignment(obfd
, osection
, ss
->alignment
));
975 osection
->entsize
= 0;
976 osection
->output_section
= osection
;
977 osection
->output_offset
= 0;
980 void write_section(bfd
*obfd
, asection
*osection
, void *arg
)
982 struct supersect
*ss
= osection
->userdata
;
984 if ((ss
->flags
& SEC_GROUP
) != 0 || ss
->contents
.size
== 0)
989 for (relocp
= ss
->new_relocs
.data
;
990 relocp
< ss
->new_relocs
.data
+ ss
->new_relocs
.size
; relocp
++) {
992 if (bfd_get_arch(obfd
) == bfd_arch_arm
)
993 val
= osection
->use_rela_p
? 0 : (*relocp
)->addend
;
996 bfd_put(bfd_get_reloc_size((*relocp
)->howto
) * 8, obfd
, val
,
997 ss
->contents
.data
+ (*relocp
)->address
);
998 if (bfd_install_relocation(obfd
, *relocp
, ss
->contents
.data
,
999 0, osection
, &error_message
) !=
1001 fprintf(stderr
, "ksplice: error installing reloc: %s",
1006 memcpy(vec_grow(&ss
->relocs
, ss
->new_relocs
.size
), ss
->new_relocs
.data
,
1007 ss
->new_relocs
.size
* sizeof(*ss
->new_relocs
.data
));
1009 bfd_set_reloc(obfd
, osection
,
1010 ss
->relocs
.size
== 0 ? NULL
: ss
->relocs
.data
,
1013 if (ss
->flags
& SEC_HAS_CONTENTS
)
1014 assert(bfd_set_section_contents
1015 (obfd
, osection
, ss
->contents
.data
, 0,
1016 ss
->contents
.size
));
1019 /* Modified function from GNU Binutils objcopy.c
1021 * Mark all the symbols which will be used in output relocations with
1022 * the BSF_KEEP flag so that those symbols will not be stripped.
1024 * Ignore relocations which will not appear in the output file.
1026 void mark_symbols_used_in_relocations(bfd
*abfd
, asection
*isection
,
1029 struct superbfd
*sbfd
= fetch_superbfd(abfd
);
1030 if (isection
->output_section
== NULL
)
1033 struct supersect
*ss
= fetch_supersect(sbfd
, isection
);
1034 ss_mark_symbols_used_in_relocations(ss
);
1037 void ss_mark_symbols_used_in_relocations(struct supersect
*ss
)
1039 /* Examine each symbol used in a relocation. If it's not one of the
1040 special bfd section symbols, then mark it with BSF_KEEP. */
1042 for (relocp
= ss
->relocs
.data
;
1043 relocp
< ss
->relocs
.data
+ ss
->relocs
.size
; relocp
++) {
1044 asymbol
*sym
= *(*relocp
)->sym_ptr_ptr
;
1045 if (!(bfd_is_const_section(sym
->section
) &&
1046 sym
== sym
->section
->symbol
))
1047 sym
->flags
|= BSF_KEEP
;
1051 static bool deleted_table_section_symbol(bfd
*abfd
, asymbol
*sym
)
1053 struct superbfd
*sbfd
= fetch_superbfd(abfd
);
1054 struct supersect
*ss
= fetch_supersect(sbfd
, sym
->section
);
1056 if (bfd_is_const_section(sym
->section
))
1060 for (symp
= ss
->syms
.data
; symp
< ss
->syms
.data
+ ss
->syms
.size
; symp
++) {
1064 return symp
>= ss
->syms
.data
+ ss
->syms
.size
;
1067 /* Modified function from GNU Binutils objcopy.c
1069 * Choose which symbol entries to copy.
1070 * We don't copy in place, because that confuses the relocs.
1071 * Return the number of symbols to print.
1073 void filter_symbols(bfd
*ibfd
, bfd
*obfd
, struct asymbolp_vec
*osyms
,
1074 struct asymbolp_vec
*isyms
)
1077 for (symp
= isyms
->data
; symp
< isyms
->data
+ isyms
->size
; symp
++) {
1078 asymbol
*sym
= *symp
;
1082 if (mode("keep") && (sym
->flags
& BSF_GLOBAL
) != 0 &&
1083 !(mode("keep-primary") &&
1084 str_in_set(sym
->section
->name
, &newsects
)))
1085 sym
->flags
= (sym
->flags
& ~BSF_GLOBAL
) | BSF_LOCAL
;
1087 if (mode("finalize") && (sym
->flags
& BSF_GLOBAL
) != 0)
1088 sym
->flags
= (sym
->flags
& ~BSF_GLOBAL
) | BSF_LOCAL
;
1090 if ((sym
->flags
& BSF_KEEP
) != 0 /* Used in relocation. */
1091 || ((sym
->flags
& BSF_SECTION_SYM
) != 0
1092 && ((*(sym
->section
)->symbol_ptr_ptr
)->flags
1095 else if ((sym
->flags
& (BSF_GLOBAL
| BSF_WEAK
)) != 0)
1097 else if (bfd_decode_symclass(sym
) == 'I')
1098 /* Global symbols in $idata sections need to be retained.
1099 External users of the library containing the $idata
1100 section may reference these symbols. */
1102 else if ((sym
->flags
& BSF_GLOBAL
) != 0
1103 || (sym
->flags
& BSF_WEAK
) != 0
1104 || bfd_is_com_section(sym
->section
))
1106 else if ((sym
->flags
& BSF_DEBUGGING
) != 0)
1109 keep
= !bfd_is_local_label(ibfd
, sym
);
1111 if (!want_section(sym
->section
))
1114 if (deleted_table_section_symbol(ibfd
, sym
))
1117 if (mode("rmsyms") && str_in_set(sym
->name
, &rmsyms
))
1121 *vec_grow(osyms
, 1) = sym
;
1125 void read_str_set(struct str_vec
*strs
)
1129 assert(getline(&buf
, &n
, stdin
) >= 0);
1133 char *str
= strtok_r(buf
, " \n", &saveptr
);
1137 *vec_grow(strs
, 1) = str
;
1141 bool str_in_set(const char *str
, const struct str_vec
*strs
)
1144 for (strp
= strs
->data
; strp
< strs
->data
+ strs
->size
; strp
++) {
1145 if (strcmp(str
, *strp
) == 0)
1151 bool want_section(asection
*sect
)
1156 if (mode("keep-primary") && bfd_is_abs_section(sect
))
1158 const struct wsect
*w
= wanted_sections
;
1159 for (; w
!= NULL
; w
= w
->next
) {
1160 if (w
->sect
== sect
)
1164 if (starts_with(sect
->name
, ".ksplice"))
1166 if (mode("keep-helper") && starts_with(sect
->name
, ".text"))
1168 if (mode("keep-helper") && starts_with(sect
->name
, ".exit.text")
1169 && bfd_get_section_by_name(sect
->owner
, ".exitcall.exit") == NULL
)
1171 if (mode("keep-primary") && str_in_set(sect
->name
, §ions
))
1173 if (mode("keep-primary") && str_in_set(sect
->name
, &newsects
))
1176 if (mode("keep-helper") && starts_with(sect
->name
, "__ksymtab"))
1178 if (mode("keep-helper") && starts_with(sect
->name
, "__kcrctab"))
1181 if (is_special(sect
))
1187 bool is_table_section(asection
*sect
)
1189 const struct table_section
*ss
;
1190 for (ss
= table_sections
; ss
!= end_table_sections
; ss
++) {
1191 if (strcmp(ss
->sectname
, sect
->name
) == 0)
1194 if (strcmp(sect
->name
, "__ex_table") == 0)