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) 2008 Jeffrey Brian Arnold <jbarnold@mit.edu>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License, version 2.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
20 /* objmanip performs various object file manipulations for Ksplice. Its first
21 * argument is always an object file, which is modified in-place during
22 * objmanip's execution. (objmanip's code is similar to objcopy from GNU
23 * binutils because every manipulation that objmanip performs is essentially a
24 * "copy" operation with certain changes which make the new version different
25 * from the old version). objmanip has four modes of operation:
29 * This mode is the first objmanip step in processing the target object files.
31 * This mode can be broken down into two submodes, called "keep-primary" (which
32 * is used to prepare the primary kernel module) and "keep-helper" (which is
33 * used to prepare the helper kernel module):
35 * (a) keep-primary: "objmanip file.o keep-primary ADDSTR sect_1 ... sect_n"
37 * In this submode, only certain sections are kept; all other sections are
38 * discarded. Specifically, the following sections are kept: the listed
39 * sections (sect_1 ... sect_n), certain sections referenced by the listed
40 * sections, and certain special sections. The sections that are kept have
41 * ADDSTR added to the end of their names.
43 * The sections that are kept have most of their ELF relocations removed.
44 * (Relocations that point to sections that are being kept are not removed; all
45 * other relocations are removed). Information about each of the removed ELF
46 * relocations is printed to STDOUT (ksplice-create will save this information
47 * into Ksplice-specific ELF sections for the primary kernel module to use
50 * Each line of the STDOUT output represents a single place within the ELF
51 * object file at which a relocation has been removed. Each line contains the
52 * following fields, separated by spaces: an ELF symbol name, the name of a
53 * section previously containing a relocation pointing to that symbol, the
54 * offset (within that section) of the former relocation to that symbol, a bit
55 * representing whether that ELF relocation is PC-relative, and the ELF addend
56 * value for that relocation.
58 * (b) keep-helper: "objmanip file.o keep-helper ADDSTR"
60 * In this submode, essentially all sections are kept and have ADDSTR added to
61 * the end of their names.
63 * The sections that are kept have all of their ELF relocations removed.
64 * Information about each of the removed ELF relocations is printed to STDOUT
65 * (ksplice-create will save this information into Ksplice-specific ELF
66 * sections for the helper kernel module to use later).
68 * The fields of the STDOUT output are the same as with keep-primary.
70 * (2) globalize mode: "objmanip file.o globalize GLOBALIZESTR"
72 * This mode is the second objmanip step in processing the target object files.
73 * In this mode, all symbols whose names end in GLOBALIZESTR will be
74 * duplicated, with the duplicate symbols differing slightly from the original
75 * symbols. The duplicate symbols will have the string "_global" added to the
76 * end of their symbol names, and they will be global ELF symbols, regardless
77 * of whether the corresponding original symbol was global.
79 * (3) sizelist mode: "objmanip file.o sizelist"
81 * After the target object files have been linked into a single collection
82 * object file, this mode is used in order to obtain a list of all of the
83 * functions in the collection object file. Each line of the STDOUT output
84 * contains an ELF section name and that section's size, as presented by BFD's
85 * bfd_print_symbol function.
87 * (4) rmsyms mode: "objmanip file.o rmsyms sym_1 ... sym_n"
89 * This mode is the final objmanip step in preparing the Ksplice kernel
90 * modules. In this mode, any ELF relocations involving the listed symbols
91 * (sym_1 ... sym_n) are removed, and information about each of the removed
92 * relocations is printed to STDOUT.
94 * The fields of the STDOUT output are the same as with keep-primary.
98 #include "objcommon.h"
99 #include "kmodsrc/ksplice.h"
106 DECLARE_VEC_TYPE(const char *, str_vec
);
114 const char *sectname
;
119 const char *sectname
;
120 struct str_vec names
;
122 DECLARE_VEC_TYPE(struct export_desc
, export_desc_vec
);
124 void rm_some_relocs(struct supersect
*ss
);
125 void write_ksplice_reloc(struct supersect
*ss
, arelent
*orig_reloc
);
126 void blot_section(struct supersect
*ss
, int offset
, reloc_howto_type
*howto
);
127 void write_ksplice_size(struct superbfd
*sbfd
, asymbol
**symp
);
128 void write_ksplice_patch(struct superbfd
*sbfd
, const char *symname
);
129 void rm_from_special(struct superbfd
*sbfd
, const struct specsect
*s
);
130 void mark_wanted_if_referenced(bfd
*abfd
, asection
*sect
, void *ignored
);
131 void check_for_ref_to_section(bfd
*abfd
, asection
*looking_at
,
133 bfd_boolean
copy_object(bfd
*ibfd
, bfd
*obfd
);
134 void setup_section(bfd
*ibfd
, asection
*isection
, void *obfdarg
);
135 static void setup_new_section(bfd
*obfd
, struct supersect
*ss
);
136 static void write_section(bfd
*obfd
, asection
*osection
, void *arg
);
137 void mark_symbols_used_in_relocations(bfd
*abfd
, asection
*isection
,
139 static void ss_mark_symbols_used_in_relocations(struct supersect
*ss
);
140 void filter_symbols(bfd
*ibfd
, bfd
*obfd
, struct asymbolp_vec
*osyms
,
141 struct asymbolp_vec
*isyms
);
142 int match_varargs(const char *str
);
143 void read_str_set(struct str_vec
*strs
);
144 int str_in_set(const char *str
, const struct str_vec
*strs
);
145 int want_section(asection
*sect
);
146 const struct specsect
*is_special(asection
*sect
);
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
, int del
);
156 struct str_vec sections
, entrysyms
, newgsyms
, newsyms
, delsyms
;
157 struct export_desc_vec exports
;
159 const char *modestr
, *addstr_all
= "", *kid
;
161 struct wsect
*wanted_sections
= NULL
;
163 const struct specsect special_sections
[] = {
164 {".altinstructions", 2 * sizeof(void *) + 4},
165 {".smp_locks", sizeof(void *)},
166 {".parainstructions", sizeof(void *) + 4},
167 }, *const end_special_sections
= *(&special_sections
+ 1);
169 #define mode(str) starts_with(modestr, str)
171 DECLARE_VEC_TYPE(unsigned long, addr_vec
);
172 DEFINE_HASH_TYPE(struct addr_vec
, addr_vec_hash
,
173 addr_vec_hash_init
, addr_vec_hash_free
, addr_vec_hash_lookup
,
175 struct addr_vec_hash system_map
;
177 void load_system_map()
179 const char *config_dir
= getenv("KSPLICE_CONFIG_DIR");
182 assert(asprintf(&file
, "%s/System.map", config_dir
) >= 0);
183 FILE *fp
= fopen(file
, "r");
185 addr_vec_hash_init(&system_map
);
189 while (fscanf(fp
, "%lx %c %as\n", &addr
, &type
, &sym
) == 3)
190 *vec_grow(addr_vec_hash_lookup(&system_map
, sym
, TRUE
),
195 int main(int argc
, char *argv
[])
198 assert(asprintf(&debug_name
, "%s.pre%s", argv
[1], argv
[2]) >= 0);
199 rename(argv
[1], debug_name
);
202 bfd
*ibfd
= bfd_openr(debug_name
, NULL
);
206 assert(bfd_check_format_matches(ibfd
, bfd_object
, &matching
));
208 const char *output_target
= bfd_get_target(ibfd
);
209 bfd
*obfd
= bfd_openw(argv
[1], output_target
);
212 struct superbfd
*isbfd
= fetch_superbfd(ibfd
);
215 if (mode("keep") || mode("sizelist") || mode("patchlist")) {
216 addstr_all
= argv
[3];
217 } else if (mode("export")) {
219 } else if (mode("rmsyms")) {
221 varargs_count
= argc
- 3;
224 if (mode("export") || mode("keep") || mode("globalize-new") ||
225 mode("rmrelocs") || mode("sizelist") || mode("patchlist")) {
226 read_str_set(§ions
);
227 read_str_set(&entrysyms
);
228 read_str_set(&newgsyms
);
229 read_str_set(&newsyms
);
230 read_str_set(&delsyms
);
232 /* https://bugzilla.redhat.com/show_bug.cgi?id=431832 */
233 while (ungetc(getc(stdin
), stdin
) != EOF
) {
235 int ret
= scanf("%as", §name
);
239 struct export_desc
*ed
= vec_grow(&exports
, 1);
240 ed
->sectname
= sectname
;
241 read_str_set(&ed
->names
);
245 if (mode("keep") || mode("sizelist") || mode("rmsyms") ||
251 const struct wsect
*tmp
= wanted_sections
;
252 bfd_map_over_sections(ibfd
, mark_wanted_if_referenced
,
254 if (tmp
== wanted_sections
)
260 for (symp
= isbfd
->syms
.data
;
261 mode("sizelist") && symp
< isbfd
->syms
.data
+ isbfd
->syms
.size
;
263 asymbol
*sym
= *symp
;
264 if ((sym
->flags
& BSF_FUNCTION
)
265 && sym
->value
== 0 && !(sym
->flags
& BSF_WEAK
))
266 write_ksplice_size(isbfd
, symp
);
267 if (starts_with(sym
->section
->name
, ".rodata") &&
268 (sym
->flags
& BSF_DEBUGGING
) == 0 &&
269 sym
->value
== 0 && (sym
->flags
& BSF_WEAK
) == 0)
270 write_ksplice_size(isbfd
, symp
);
273 if (mode("patchlist")) {
274 const char **symname
;
275 for (symname
= entrysyms
.data
;
276 symname
< entrysyms
.data
+ entrysyms
.size
; symname
++)
277 write_ksplice_patch(isbfd
, *symname
);
281 for (p
= ibfd
->sections
; p
!= NULL
; p
= p
->next
) {
282 struct supersect
*ss
= fetch_supersect(isbfd
, p
);
283 if (is_special(p
) || starts_with(p
->name
, ".ksplice"))
285 if (want_section(p
) || mode("rmsyms"))
289 const struct specsect
*ss
;
291 for (ss
= special_sections
; ss
!= end_special_sections
; ss
++)
292 rm_from_special(isbfd
, ss
);
295 if (mode("export")) {
296 const struct export_desc
*ed
;
297 for (ed
= exports
.data
; ed
< exports
.data
+ exports
.size
;
299 if (starts_with(ed
->sectname
, "del___ksymtab")) {
300 const char *export_type
=
301 ed
->sectname
+ strlen("del___ksymtab");
302 const char **symname
;
303 for (symname
= ed
->names
.data
;
304 symname
< ed
->names
.data
+ ed
->names
.size
;
306 write_ksplice_export(isbfd
, *symname
,
309 rm_some_exports(isbfd
, ed
);
314 copy_object(ibfd
, obfd
);
315 assert(bfd_close(obfd
));
316 assert(bfd_close(ibfd
));
320 void rm_some_exports(struct superbfd
*isbfd
, const struct export_desc
*ed
)
322 assert(starts_with(ed
->sectname
, "__ksymtab"));
323 const char *export_type
= ed
->sectname
+ strlen("__ksymtab");
324 asection
*sym_sect
= bfd_get_section_by_name(isbfd
->abfd
, ed
->sectname
);
325 assert(sym_sect
!= NULL
);
326 char *export_crc_name
;
327 assert(asprintf(&export_crc_name
, "__kcrctab%s", export_type
) >= 0);
328 asection
*crc_sect
= bfd_get_section_by_name(isbfd
->abfd
,
330 struct supersect
*ss
, *crc_ss
= NULL
;
331 ss
= fetch_supersect(isbfd
, sym_sect
);
332 if (crc_sect
!= NULL
)
333 crc_ss
= fetch_supersect(isbfd
, crc_sect
);
336 assert(ss
->contents
.size
* sizeof(unsigned long) ==
337 crc_ss
->contents
.size
* sizeof(struct kernel_symbol
));
339 struct supersect orig_ss
, orig_crc_ss
;
340 supersect_move(&orig_ss
, ss
);
342 supersect_move(&orig_crc_ss
, crc_ss
);
344 struct kernel_symbol
*orig_ksym
;
345 unsigned long *orig_crc
;
346 for (orig_ksym
= orig_ss
.contents
.data
,
347 orig_crc
= orig_crc_ss
.contents
.data
;
348 (void *)orig_ksym
< orig_ss
.contents
.data
+ orig_ss
.contents
.size
;
349 orig_ksym
++, orig_crc
++) {
351 read_reloc(&orig_ss
, &orig_ksym
->value
,
352 sizeof(orig_ksym
->value
), &sym
);
353 if (!str_in_set(sym
->name
, &ed
->names
))
356 struct kernel_symbol
*ksym
= sect_grow(ss
, 1, typeof(*ksym
));
357 sect_copy(ss
, &ksym
->value
, &orig_ss
, &orig_ksym
->value
, 1);
358 /* Replace name with a mangled name */
359 write_ksplice_export(ss
->parent
, sym
->name
, export_type
, 0);
360 write_string(ss
, (const char **)&ksym
->name
,
361 "DISABLED_%s_%s", sym
->name
, kid
);
365 sect_grow(crc_ss
, 1, typeof(*orig_crc
)),
366 &orig_crc_ss
, orig_crc
, 1);
370 void rm_some_relocs(struct supersect
*ss
)
372 struct arelentp_vec orig_relocs
;
373 vec_move(&orig_relocs
, &ss
->relocs
);
376 for (relocp
= orig_relocs
.data
;
377 relocp
< orig_relocs
.data
+ orig_relocs
.size
; relocp
++) {
379 asymbol
*sym_ptr
= *(*relocp
)->sym_ptr_ptr
;
381 if (mode("rmsyms") && match_varargs(sym_ptr
->name
))
384 if (mode("keep") || mode("rmrelocs"))
387 if (mode("keep-primary") && want_section(sym_ptr
->section
))
390 if (mode("rmrelocs") &&
391 (str_in_set(sym_ptr
->name
, &newsyms
) ||
392 bfd_is_und_section(sym_ptr
->section
) ||
393 (sym_ptr
->flags
& BSF_FUNCTION
) == 0))
396 if (mode("finalize") && bfd_is_und_section(sym_ptr
->section
))
400 write_ksplice_reloc(ss
, *relocp
);
402 *vec_grow(&ss
->relocs
, 1) = *relocp
;
406 struct supersect
*make_section(struct superbfd
*sbfd
, const char *name
)
408 asection
*sect
= bfd_get_section_by_name(sbfd
->abfd
, name
);
410 return fetch_supersect(sbfd
, sect
);
412 return new_supersect(sbfd
, name
);
415 void write_reloc(struct supersect
*ss
, const void *addr
, asymbol
**symp
,
418 bfd_reloc_code_real_type code
;
419 switch (bfd_arch_bits_per_address(ss
->parent
->abfd
)) {
430 arelent
*reloc
= malloc(sizeof(*reloc
));
431 reloc
->sym_ptr_ptr
= symp
;
432 reloc
->address
= addr
- ss
->contents
.data
;
433 reloc
->howto
= bfd_reloc_type_lookup(ss
->parent
->abfd
, code
);
434 reloc
->addend
= offset
;
435 *vec_grow(&ss
->new_relocs
, 1) = reloc
;
438 void write_string(struct supersect
*ss
, const char **addr
, const char *fmt
, ...)
442 int len
= vsnprintf(NULL
, 0, fmt
, ap
);
444 struct supersect
*str_ss
= make_section(ss
->parent
, ".ksplice_str");
445 char *buf
= sect_grow(str_ss
, len
+ 1, char);
447 vsnprintf(buf
, len
+ 1, fmt
, ap
);
450 write_reloc(ss
, addr
, &str_ss
->symbol
,
451 (void *)buf
- str_ss
->contents
.data
);
454 void write_system_map_array(struct superbfd
*sbfd
, struct supersect
*ss
,
455 const unsigned long **sym_addrs
,
456 unsigned long *num_sym_addrs
, asymbol
*sym
)
458 const char *system_map_name
= sym
->name
;
460 for (prefix
= (const char *[]){".text.", ".data.", ".bss.", NULL
};
461 *prefix
!= NULL
; prefix
++) {
462 if (starts_with(system_map_name
, *prefix
))
463 system_map_name
+= strlen(*prefix
);
465 struct addr_vec
*addrs
= addr_vec_hash_lookup(&system_map
,
466 system_map_name
, FALSE
);
468 struct supersect
*array_ss
= make_section(sbfd
,
470 void *buf
= sect_grow(array_ss
, addrs
->size
,
471 typeof(*addrs
->data
));
472 memcpy(buf
, addrs
->data
, addrs
->size
* sizeof(*addrs
->data
));
473 *num_sym_addrs
= addrs
->size
;
474 write_reloc(ss
, sym_addrs
, &array_ss
->symbol
,
475 buf
- array_ss
->contents
.data
);
482 void write_ksplice_reloc(struct supersect
*ss
, arelent
*orig_reloc
)
484 asymbol
*sym_ptr
= *orig_reloc
->sym_ptr_ptr
;
486 reloc_howto_type
*howto
= orig_reloc
->howto
;
488 bfd_vma addend
= get_reloc_offset(ss
, orig_reloc
, 0);
489 blot_section(ss
, orig_reloc
->address
, howto
);
491 struct supersect
*kreloc_ss
= make_section(ss
->parent
,
493 ".ksplice_init_relocs" :
495 struct ksplice_reloc
*kreloc
= sect_grow(kreloc_ss
, 1,
496 struct ksplice_reloc
);
498 write_string(kreloc_ss
, &kreloc
->sym_name
, "%s%s",
499 sym_ptr
->name
, addstr_all
);
500 write_reloc(kreloc_ss
, &kreloc
->blank_addr
,
501 &ss
->symbol
, orig_reloc
->address
);
502 kreloc
->blank_offset
= (unsigned long)orig_reloc
->address
;
503 write_system_map_array(ss
->parent
, kreloc_ss
, &kreloc
->sym_addrs
,
504 &kreloc
->num_sym_addrs
, sym_ptr
);
505 kreloc
->pcrel
= howto
->pc_relative
;
506 kreloc
->addend
= addend
;
507 kreloc
->size
= bfd_get_reloc_size(howto
);
508 kreloc
->dst_mask
= howto
->dst_mask
;
509 kreloc
->rightshift
= howto
->rightshift
;
512 #define CANARY(x, canary) ((x & ~howto->dst_mask) | (canary & howto->dst_mask))
514 void blot_section(struct supersect
*ss
, int offset
, reloc_howto_type
*howto
)
516 int bits
= bfd_get_reloc_size(howto
) * 8;
517 void *address
= ss
->contents
.data
+ offset
;
518 bfd_vma x
= bfd_get(bits
, ss
->parent
->abfd
, address
);
519 x
= (x
& ~howto
->dst_mask
) |
520 ((bfd_vma
)0x7777777777777777LL
& howto
->dst_mask
);
521 bfd_put(bits
, ss
->parent
->abfd
, x
, address
);
524 void write_ksplice_size(struct superbfd
*sbfd
, asymbol
**symp
)
526 asymbol
*sym
= *symp
;
528 /* We call bfd_print_symbol in order to get access to
529 * the size associated with the function symbol, which
530 * is not otherwise available through the BFD API
534 FILE *fp
= open_memstream(&buf
, &bufsize
);
535 bfd_print_symbol(sbfd
->abfd
, fp
, sym
, bfd_print_symbol_all
);
539 unsigned long symsize
;
542 assert(sscanf(buf
, "%*[^\t]\t%lx %as%n", &symsize
, &symname
, &len
) >=
544 assert(buf
[len
] == '\0');
545 assert(strcmp(symname
, sym
->name
) == 0);
549 struct supersect
*ksize_ss
= make_section(sbfd
, ".ksplice_sizes");
550 struct ksplice_size
*ksize
= sect_grow(ksize_ss
, 1,
551 struct ksplice_size
);
553 write_string(ksize_ss
, &ksize
->name
, "%s%s%s", sym
->name
, addstr_all
,
554 mode("sizelist-primary") ? "_post" : "_pre");
555 ksize
->size
= symsize
;
557 if (mode("sizelist-helper") &&
558 str_in_set(sym
->name
, &delsyms
) && (sym
->flags
& BSF_FUNCTION
))
559 ksize
->flags
|= KSPLICE_SIZE_DELETED
;
560 if (starts_with(sym
->section
->name
, ".rodata"))
561 ksize
->flags
|= KSPLICE_SIZE_RODATA
;
562 write_reloc(ksize_ss
, &ksize
->thismod_addr
, symp
, 0);
563 write_system_map_array(sbfd
, ksize_ss
, &ksize
->sym_addrs
,
564 &ksize
->num_sym_addrs
, sym
);
567 void write_ksplice_patch(struct superbfd
*sbfd
, const char *symname
)
569 struct supersect
*kpatch_ss
= make_section(sbfd
, ".ksplice_patches");
570 struct ksplice_patch
*kpatch
= sect_grow(kpatch_ss
, 1,
571 struct ksplice_patch
);
574 for (symp
= sbfd
->syms
.data
; symp
< sbfd
->syms
.data
+ sbfd
->syms
.size
;
576 if (strcmp((*symp
)->name
, symname
) == 0)
579 assert(symp
< sbfd
->syms
.data
+ sbfd
->syms
.size
);
581 write_string(kpatch_ss
, &kpatch
->oldstr
, "%s%s_pre",
582 symname
, addstr_all
);
584 kpatch
->saved
= NULL
;
585 kpatch
->trampoline
= NULL
;
586 write_reloc(kpatch_ss
, &kpatch
->repladdr
, symp
, 0);
589 void write_ksplice_export(struct superbfd
*sbfd
, const char *symname
,
590 const char *export_type
, int del
)
592 struct supersect
*export_ss
= make_section(sbfd
, ".ksplice_exports");
593 struct ksplice_export
*export
= sect_grow(export_ss
, 1,
594 struct ksplice_export
);
596 write_string(export_ss
, &export
->type
, "%s", export_type
);
598 write_string(export_ss
, &export
->name
, "%s", symname
);
599 write_string(export_ss
, &export
->new_name
,
600 "DISABLED_%s_%s", symname
, kid
);
602 write_string(export_ss
, &export
->new_name
, "%s", symname
);
603 write_string(export_ss
, &export
->name
, "DISABLED_%s_%s",
608 void rm_from_special(struct superbfd
*sbfd
, const struct specsect
*s
)
610 asection
*isection
= bfd_get_section_by_name(sbfd
->abfd
, s
->sectname
);
611 if (isection
== NULL
)
614 struct supersect
*ss
= fetch_supersect(sbfd
, isection
), orig_ss
;
615 supersect_move(&orig_ss
, ss
);
617 const void *orig_entry
;
618 for (orig_entry
= orig_ss
.contents
.data
;
619 orig_entry
< orig_ss
.contents
.data
+ orig_ss
.contents
.size
;
620 orig_entry
+= align(s
->entry_size
, 1 << ss
->alignment
)) {
622 read_reloc(&orig_ss
, orig_entry
, sizeof(void *), &sym
);
625 for (p
= sbfd
->abfd
->sections
; p
!= NULL
; p
= p
->next
) {
626 if (sym
->section
== p
627 && !is_special(p
) && !want_section(p
))
633 sect_copy(ss
, sect_do_grow(ss
, 1, s
->entry_size
,
635 &orig_ss
, orig_entry
, s
->entry_size
);
639 void mark_wanted_if_referenced(bfd
*abfd
, asection
*sect
, void *ignored
)
641 if (want_section(sect
))
643 if (!starts_with(sect
->name
, ".text")
644 && !starts_with(sect
->name
, ".rodata"))
647 bfd_map_over_sections(abfd
, check_for_ref_to_section
, sect
);
650 void check_for_ref_to_section(bfd
*abfd
, asection
*looking_at
,
653 if (!want_section(looking_at
) || is_special(looking_at
))
656 struct superbfd
*sbfd
= fetch_superbfd(abfd
);
657 struct supersect
*ss
= fetch_supersect(sbfd
, looking_at
);
659 for (relocp
= ss
->relocs
.data
;
660 relocp
< ss
->relocs
.data
+ ss
->relocs
.size
; relocp
++) {
661 asymbol
*sym
= *(*relocp
)->sym_ptr_ptr
;
662 if (sym
->section
== (asection
*)looking_for
&&
663 (!starts_with(sym
->section
->name
, ".text") ||
664 get_reloc_offset(ss
, *relocp
, 1) != 0)) {
665 struct wsect
*w
= malloc(sizeof(*w
));
666 w
->sect
= looking_for
;
667 w
->next
= wanted_sections
;
674 /* Modified function from GNU Binutils objcopy.c */
675 bfd_boolean
copy_object(bfd
*ibfd
, bfd
*obfd
)
677 assert(bfd_set_format(obfd
, bfd_get_format(ibfd
)));
679 bfd_vma start
= bfd_get_start_address(ibfd
);
681 flagword flags
= bfd_get_file_flags(ibfd
);
682 flags
&= bfd_applicable_file_flags(obfd
);
684 assert(bfd_set_start_address(obfd
, start
)
685 && bfd_set_file_flags(obfd
, flags
));
687 enum bfd_architecture iarch
= bfd_get_arch(ibfd
);
688 unsigned int imach
= bfd_get_mach(ibfd
);
689 assert(bfd_set_arch_mach(obfd
, iarch
, imach
));
690 assert(bfd_set_format(obfd
, bfd_get_format(ibfd
)));
692 /* BFD mandates that all output sections be created and sizes set before
693 any output is done. Thus, we traverse all sections multiple times. */
694 bfd_map_over_sections(ibfd
, setup_section
, obfd
);
696 struct supersect
*new_supersects
= fetch_superbfd(ibfd
)->new_supersects
;
697 struct supersect
*ss
;
698 for (ss
= new_supersects
; ss
!= NULL
; ss
= ss
->next
)
699 setup_new_section(obfd
, ss
);
701 /* Mark symbols used in output relocations so that they
702 are kept, even if they are local labels or static symbols.
704 Note we iterate over the input sections examining their
705 relocations since the relocations for the output sections
706 haven't been set yet. mark_symbols_used_in_relocations will
707 ignore input sections which have no corresponding output
710 bfd_map_over_sections(ibfd
, mark_symbols_used_in_relocations
, NULL
);
711 for (ss
= new_supersects
; ss
!= NULL
; ss
= ss
->next
)
712 ss_mark_symbols_used_in_relocations(ss
);
713 struct asymbolp_vec osyms
;
715 filter_symbols(ibfd
, obfd
, &osyms
, &fetch_superbfd(ibfd
)->syms
);
717 bfd_set_symtab(obfd
, osyms
.data
, osyms
.size
);
719 /* This has to happen after the symbol table has been set. */
720 bfd_map_over_sections(obfd
, write_section
, NULL
);
722 /* Allow the BFD backend to copy any private data it understands
723 from the input BFD to the output BFD. This is done last to
724 permit the routine to look at the filtered symbol table, which is
725 important for the ECOFF code at least. */
726 assert(bfd_copy_private_bfd_data(ibfd
, obfd
));
731 /* Modified function from GNU Binutils objcopy.c */
732 void setup_section(bfd
*ibfd
, asection
*isection
, void *obfdarg
)
737 if (!want_section(isection
))
740 asection
*osection
= bfd_make_section_anyway(obfd
, isection
->name
);
741 assert(osection
!= NULL
);
743 struct superbfd
*isbfd
= fetch_superbfd(ibfd
);
744 struct supersect
*ss
= fetch_supersect(isbfd
, isection
);
745 osection
->userdata
= ss
;
746 bfd_set_section_flags(obfd
, osection
, ss
->flags
);
747 ss
->symbol
= osection
->symbol
;
748 assert(bfd_set_section_size(obfd
, osection
, ss
->contents
.size
));
750 vma
= bfd_section_vma(ibfd
, isection
);
751 assert(bfd_set_section_vma(obfd
, osection
, vma
));
753 osection
->lma
= isection
->lma
;
754 assert(bfd_set_section_alignment(obfd
, osection
, ss
->alignment
));
755 osection
->entsize
= isection
->entsize
;
756 osection
->output_section
= osection
;
757 osection
->output_offset
= 0;
758 isection
->output_section
= osection
;
759 isection
->output_offset
= 0;
763 void setup_new_section(bfd
*obfd
, struct supersect
*ss
)
765 asection
*osection
= bfd_make_section_anyway(obfd
, ss
->name
);
766 assert(osection
!= NULL
);
767 bfd_set_section_flags(obfd
, osection
, ss
->flags
);
769 osection
->userdata
= ss
;
770 ss
->symbol
= osection
->symbol
;
771 assert(bfd_set_section_size(obfd
, osection
, ss
->contents
.size
));
772 assert(bfd_set_section_vma(obfd
, osection
, 0));
775 assert(bfd_set_section_alignment(obfd
, osection
, ss
->alignment
));
776 osection
->entsize
= 0;
777 osection
->output_section
= osection
;
778 osection
->output_offset
= 0;
781 void write_section(bfd
*obfd
, asection
*osection
, void *arg
)
783 struct supersect
*ss
= osection
->userdata
;
785 if ((ss
->flags
& SEC_GROUP
) != 0 || ss
->contents
.size
== 0)
790 for (relocp
= ss
->new_relocs
.data
;
791 relocp
< ss
->new_relocs
.data
+ ss
->new_relocs
.size
; relocp
++) {
792 bfd_put(bfd_get_reloc_size((*relocp
)->howto
) * 8, obfd
, 0,
793 ss
->contents
.data
+ (*relocp
)->address
);
794 if (bfd_install_relocation(obfd
, *relocp
, ss
->contents
.data
,
795 0, osection
, &error_message
) !=
797 fprintf(stderr
, "ksplice: error installing reloc: %s",
802 memcpy(vec_grow(&ss
->relocs
, ss
->new_relocs
.size
), ss
->new_relocs
.data
,
803 ss
->new_relocs
.size
* sizeof(*ss
->new_relocs
.data
));
805 bfd_set_reloc(obfd
, osection
,
806 ss
->relocs
.size
== 0 ? NULL
: ss
->relocs
.data
,
809 if (ss
->flags
& SEC_HAS_CONTENTS
)
810 assert(bfd_set_section_contents
811 (obfd
, osection
, ss
->contents
.data
, 0,
815 /* Modified function from GNU Binutils objcopy.c
817 * Mark all the symbols which will be used in output relocations with
818 * the BSF_KEEP flag so that those symbols will not be stripped.
820 * Ignore relocations which will not appear in the output file.
822 void mark_symbols_used_in_relocations(bfd
*abfd
, asection
*isection
,
825 struct superbfd
*sbfd
= fetch_superbfd(abfd
);
826 if (isection
->output_section
== NULL
)
829 struct supersect
*ss
= fetch_supersect(sbfd
, isection
);
830 ss_mark_symbols_used_in_relocations(ss
);
833 void ss_mark_symbols_used_in_relocations(struct supersect
*ss
)
835 /* Examine each symbol used in a relocation. If it's not one of the
836 special bfd section symbols, then mark it with BSF_KEEP. */
838 for (relocp
= ss
->relocs
.data
;
839 relocp
< ss
->relocs
.data
+ ss
->relocs
.size
; relocp
++) {
840 asymbol
*sym
= *(*relocp
)->sym_ptr_ptr
;
841 if (!(bfd_is_const_section(sym
->section
) &&
842 sym
== sym
->section
->symbol
))
843 sym
->flags
|= BSF_KEEP
;
847 /* Modified function from GNU Binutils objcopy.c
849 * Choose which symbol entries to copy.
850 * We don't copy in place, because that confuses the relocs.
851 * Return the number of symbols to print.
853 void filter_symbols(bfd
*ibfd
, bfd
*obfd
, struct asymbolp_vec
*osyms
,
854 struct asymbolp_vec
*isyms
)
857 for (symp
= isyms
->data
; symp
< isyms
->data
+ isyms
->size
; symp
++) {
858 asymbol
*sym
= *symp
;
862 if (mode("keep") && (sym
->flags
& BSF_GLOBAL
) != 0)
863 sym
->flags
= (sym
->flags
& ~BSF_GLOBAL
) | BSF_LOCAL
;
865 if (mode("globalize-new") && str_in_set(sym
->name
, &newgsyms
))
866 sym
->flags
= (sym
->flags
& ~BSF_LOCAL
) | BSF_GLOBAL
;
868 if ((sym
->flags
& BSF_KEEP
) != 0 /* Used in relocation. */
869 || ((sym
->flags
& BSF_SECTION_SYM
) != 0
870 && ((*(sym
->section
)->symbol_ptr_ptr
)->flags
873 else if ((sym
->flags
& (BSF_GLOBAL
| BSF_WEAK
)) != 0)
875 else if (bfd_decode_symclass(sym
) == 'I')
876 /* Global symbols in $idata sections need to be retained.
877 External users of the library containing the $idata
878 section may reference these symbols. */
880 else if ((sym
->flags
& BSF_GLOBAL
) != 0
881 || (sym
->flags
& BSF_WEAK
) != 0
882 || bfd_is_com_section(sym
->section
))
884 else if ((sym
->flags
& BSF_DEBUGGING
) != 0)
887 keep
= !bfd_is_local_label(ibfd
, sym
);
889 if (!want_section(sym
->section
))
892 if (mode("rmsyms") && match_varargs(sym
->name
))
896 *vec_grow(osyms
, 1) = sym
;
900 int match_varargs(const char *str
)
903 for (i
= 0; i
< varargs_count
; i
++) {
904 if (strcmp(str
, varargs
[i
]) == 0)
910 void read_str_set(struct str_vec
*strs
)
914 assert(getline(&buf
, &n
, stdin
) >= 0);
918 char *str
= strtok_r(buf
, " \n", &saveptr
);
922 *vec_grow(strs
, 1) = str
;
926 int str_in_set(const char *str
, const struct str_vec
*strs
)
929 for (strp
= strs
->data
; strp
< strs
->data
+ strs
->size
; strp
++) {
930 if (strcmp(str
, *strp
) == 0)
936 int want_section(asection
*sect
)
938 static const char *static_want
[] = {
940 ".altinstr_replacement",
949 if (mode("keep-primary") && bfd_is_abs_section(sect
))
951 const struct wsect
*w
= wanted_sections
;
952 for (; w
!= NULL
; w
= w
->next
) {
957 if (starts_with(sect
->name
, ".ksplice"))
959 if (mode("keep-helper") && starts_with(sect
->name
, ".text"))
961 if (mode("keep-primary") && starts_with(sect
->name
, "__ksymtab"))
963 if (mode("keep-primary") && starts_with(sect
->name
, "__kcrctab"))
965 if (mode("keep-primary") && str_in_set(sect
->name
, §ions
))
969 for (i
= 0; static_want
[i
] != NULL
; i
++) {
970 if (strcmp(sect
->name
, static_want
[i
]) == 0)
976 const struct specsect
*is_special(asection
*sect
)
978 const struct specsect
*ss
;
979 for (ss
= special_sections
; ss
!= end_special_sections
; ss
++) {
980 if (strcmp(ss
->sectname
, sect
->name
) == 0)