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 * argument is always an object file, which is modified in-place during
24 * objmanip's execution. (objmanip's code is similar to objcopy from GNU
25 * binutils because every manipulation that objmanip performs is essentially a
26 * "copy" operation with certain changes which make the new version different
27 * from the old version). objmanip has four modes of operation:
31 * This mode is the first objmanip step in processing the target object files.
33 * This mode can be broken down into two submodes, called "keep-primary" (which
34 * is used to prepare the primary kernel module) and "keep-helper" (which is
35 * used to prepare the helper kernel module):
37 * (a) keep-primary: "objmanip file.o keep-primary ADDSTR sect_1 ... sect_n"
39 * In this submode, only certain sections are kept; all other sections are
40 * discarded. Specifically, the following sections are kept: the listed
41 * sections (sect_1 ... sect_n), certain sections referenced by the listed
42 * sections, and certain special sections. The sections that are kept have
43 * ADDSTR added to the end of their names.
45 * The sections that are kept have most of their ELF relocations removed.
46 * (Relocations that point to sections that are being kept are not removed; all
47 * other relocations are removed). Information about each of the removed ELF
48 * relocations is printed to STDOUT (ksplice-create will save this information
49 * into Ksplice-specific ELF sections for the primary kernel module to use
52 * Each line of the STDOUT output represents a single place within the ELF
53 * object file at which a relocation has been removed. Each line contains the
54 * following fields, separated by spaces: an ELF symbol name, the name of a
55 * section previously containing a relocation pointing to that symbol, the
56 * offset (within that section) of the former relocation to that symbol, a bit
57 * representing whether that ELF relocation is PC-relative, and the ELF addend
58 * value for that relocation.
60 * (b) keep-helper: "objmanip file.o keep-helper ADDSTR"
62 * In this submode, essentially all sections are kept and have ADDSTR added to
63 * the end of their names.
65 * The sections that are kept have all of their ELF relocations removed.
66 * Information about each of the removed ELF relocations is printed to STDOUT
67 * (ksplice-create will save this information into Ksplice-specific ELF
68 * sections for the helper kernel module to use later).
70 * The fields of the STDOUT output are the same as with keep-primary.
72 * (2) globalize mode: "objmanip file.o globalize GLOBALIZESTR"
74 * This mode is the second objmanip step in processing the target object files.
75 * In this mode, all symbols whose names end in GLOBALIZESTR will be
76 * duplicated, with the duplicate symbols differing slightly from the original
77 * symbols. The duplicate symbols will have the string "_global" added to the
78 * end of their symbol names, and they will be global ELF symbols, regardless
79 * of whether the corresponding original symbol was global.
81 * (3) sizelist mode: "objmanip file.o sizelist"
83 * After the target object files have been linked into a single collection
84 * object file, this mode is used in order to obtain a list of all of the
85 * functions in the collection object file. Each line of the STDOUT output
86 * contains an ELF section name and that section's size, as presented by BFD's
87 * bfd_print_symbol function.
89 * (4) rmsyms mode: "objmanip file.o rmsyms sym_1 ... sym_n"
91 * This mode is the final objmanip step in preparing the Ksplice kernel
92 * modules. In this mode, any ELF relocations involving the listed symbols
93 * (sym_1 ... sym_n) are removed, and information about each of the removed
94 * relocations is printed to STDOUT.
96 * The fields of the STDOUT output are the same as with keep-primary.
100 #include "objcommon.h"
101 #include "kmodsrc/ksplice.h"
108 DECLARE_VEC_TYPE(const char *, str_vec
);
116 const char *sectname
;
121 const char *sectname
;
122 struct str_vec names
;
124 DECLARE_VEC_TYPE(struct export_desc
, export_desc_vec
);
126 void rm_some_relocs(struct supersect
*ss
);
127 void write_ksplice_reloc(struct supersect
*ss
, arelent
*orig_reloc
);
128 void blot_section(struct supersect
*ss
, int offset
, reloc_howto_type
*howto
);
129 void write_ksplice_size(struct superbfd
*sbfd
, asymbol
**symp
);
130 void write_ksplice_patch(struct superbfd
*sbfd
, const char *sectname
);
131 void rm_from_special(struct superbfd
*sbfd
, const struct specsect
*s
);
132 void mark_wanted_if_referenced(bfd
*abfd
, asection
*sect
, void *ignored
);
133 void check_for_ref_to_section(bfd
*abfd
, asection
*looking_at
,
135 bfd_boolean
copy_object(bfd
*ibfd
, bfd
*obfd
);
136 void setup_section(bfd
*ibfd
, asection
*isection
, void *obfdarg
);
137 static void setup_new_section(bfd
*obfd
, struct supersect
*ss
);
138 static void write_section(bfd
*obfd
, asection
*osection
, void *arg
);
139 void mark_symbols_used_in_relocations(bfd
*abfd
, asection
*isection
,
141 static void ss_mark_symbols_used_in_relocations(struct supersect
*ss
);
142 void filter_symbols(bfd
*ibfd
, bfd
*obfd
, struct asymbolp_vec
*osyms
,
143 struct asymbolp_vec
*isyms
);
144 int match_varargs(const char *str
);
145 void read_str_set(struct str_vec
*strs
);
146 int str_in_set(const char *str
, const struct str_vec
*strs
);
147 int want_section(asection
*sect
);
148 const struct specsect
*is_special(asection
*sect
);
149 struct supersect
*make_section(struct superbfd
*sbfd
, const char *name
);
150 void __attribute__((format(printf
, 3, 4)))
151 write_string(struct supersect
*ss
, const char **addr
, const char *fmt
, ...);
152 void rm_some_exports(struct superbfd
*isbfd
, const struct export_desc
*ed
);
153 void write_ksplice_export(struct superbfd
*sbfd
, const char *symname
,
154 const char *export_type
, int del
);
155 void write_reloc(struct supersect
*ss
, const void *addr
, asymbol
**symp
,
157 arelent
*create_reloc(struct supersect
*ss
, const void *addr
, asymbol
**symp
,
162 struct str_vec sections
, newsects
, delsects
;
163 struct export_desc_vec exports
;
165 const char *modestr
, *kid
;
167 struct wsect
*wanted_sections
= NULL
;
169 const struct specsect special_sections
[] = {
170 {".altinstructions", 2 * sizeof(void *) + 4},
171 {".smp_locks", sizeof(void *)},
172 {".parainstructions", sizeof(void *) + 4},
173 }, *const end_special_sections
= *(&special_sections
+ 1);
175 #define mode(str) starts_with(modestr, str)
177 DECLARE_VEC_TYPE(unsigned long, addr_vec
);
178 DEFINE_HASH_TYPE(struct addr_vec
, addr_vec_hash
,
179 addr_vec_hash_init
, addr_vec_hash_free
, addr_vec_hash_lookup
,
181 struct addr_vec_hash system_map
;
183 void load_system_map()
185 const char *config_dir
= getenv("KSPLICE_CONFIG_DIR");
188 assert(asprintf(&file
, "%s/System.map", config_dir
) >= 0);
189 FILE *fp
= fopen(file
, "r");
191 addr_vec_hash_init(&system_map
);
195 while (fscanf(fp
, "%lx %c %as\n", &addr
, &type
, &sym
) == 3)
196 *vec_grow(addr_vec_hash_lookup(&system_map
, sym
, TRUE
),
201 int needed_data_section(struct superbfd
*sbfd
, asection
*isection
)
203 struct supersect
*ss
= fetch_supersect(sbfd
, isection
);
204 if (starts_with(isection
->name
, ".rodata."))
206 if (starts_with(isection
->name
, ".data.")) {
207 /* Ignore .data.percpu sections */
208 if (starts_with(isection
->name
, ".data.percpu"))
210 return ss
->relocs
.size
!= 0;
215 int main(int argc
, char *argv
[])
218 bfd
*ibfd
= bfd_openr(argv
[1], NULL
);
222 assert(bfd_check_format_matches(ibfd
, bfd_object
, &matching
));
224 const char *output_target
= bfd_get_target(ibfd
);
225 bfd
*obfd
= bfd_openw(argv
[2], output_target
);
228 struct superbfd
*isbfd
= fetch_superbfd(ibfd
);
233 } else if (mode("rmsyms")) {
235 varargs_count
= argc
- 4;
239 read_str_set(§ions
);
240 read_str_set(&newsects
);
241 read_str_set(&delsects
);
243 /* https://bugzilla.redhat.com/show_bug.cgi?id=431832 */
244 while (ungetc(getc(stdin
), stdin
) != EOF
) {
246 int ret
= scanf("%as", §name
);
250 struct export_desc
*ed
= vec_grow(&exports
, 1);
251 ed
->sectname
= sectname
;
252 read_str_set(&ed
->names
);
256 if (mode("keep-primary")) {
257 /* Create export_desc structures for all export sections */
259 for (sect
= isbfd
->abfd
->sections
; sect
!= NULL
;
261 struct export_desc
*ed
;
262 if (!starts_with(sect
->name
, "__ksymtab") ||
263 ends_with(sect
->name
, "_strings"))
265 for (ed
= exports
.data
;
266 ed
< exports
.data
+ exports
.size
; ed
++) {
267 if (strcmp(ed
->sectname
, sect
->name
) == 0)
270 if (ed
< exports
.data
+ exports
.size
)
272 ed
= vec_grow(&exports
, 1);
273 ed
->sectname
= sect
->name
;
274 vec_init(&ed
->names
);
278 if (mode("keep") || mode("rmsyms"))
283 const struct wsect
*tmp
= wanted_sections
;
284 bfd_map_over_sections(ibfd
, mark_wanted_if_referenced
,
286 if (tmp
== wanted_sections
)
292 for (symp
= isbfd
->syms
.data
;
293 mode("keep") && symp
< isbfd
->syms
.data
+ isbfd
->syms
.size
;
295 asymbol
*sym
= *symp
;
296 if (!want_section(sym
->section
))
298 if ((sym
->flags
& BSF_WEAK
) != 0)
300 if ((sym
->flags
& BSF_DEBUGGING
) != 0)
302 if ((sym
->flags
& BSF_FUNCTION
) && sym
->value
== 0)
303 write_ksplice_size(isbfd
, symp
);
304 if (sym
->value
== 0 && needed_data_section(isbfd
, sym
->section
))
305 write_ksplice_size(isbfd
, symp
);
308 if (mode("keep-primary")) {
309 const char **sectname
;
310 for (sectname
= sections
.data
;
311 sectname
< sections
.data
+ sections
.size
; sectname
++)
312 write_ksplice_patch(isbfd
, *sectname
);
314 const struct export_desc
*ed
;
315 for (ed
= exports
.data
; ed
< exports
.data
+ exports
.size
;
317 if (starts_with(ed
->sectname
, "del___ksymtab")) {
318 const char *export_type
=
319 ed
->sectname
+ strlen("del___ksymtab");
320 const char **symname
;
321 for (symname
= ed
->names
.data
;
322 symname
< ed
->names
.data
+ ed
->names
.size
;
324 write_ksplice_export(isbfd
, *symname
,
327 rm_some_exports(isbfd
, ed
);
333 for (p
= ibfd
->sections
; p
!= NULL
; p
= p
->next
) {
334 struct supersect
*ss
= fetch_supersect(isbfd
, p
);
335 if (is_special(p
) || starts_with(p
->name
, ".ksplice"))
337 if (want_section(p
) || mode("rmsyms"))
341 const struct specsect
*ss
;
343 for (ss
= special_sections
; ss
!= end_special_sections
; ss
++)
344 rm_from_special(isbfd
, ss
);
347 copy_object(ibfd
, obfd
);
348 assert(bfd_close(obfd
));
349 assert(bfd_close(ibfd
));
353 void rm_some_exports(struct superbfd
*isbfd
, const struct export_desc
*ed
)
355 assert(starts_with(ed
->sectname
, "__ksymtab"));
356 const char *export_type
= ed
->sectname
+ strlen("__ksymtab");
357 asection
*sym_sect
= bfd_get_section_by_name(isbfd
->abfd
, ed
->sectname
);
358 assert(sym_sect
!= NULL
);
359 char *export_crc_name
;
360 assert(asprintf(&export_crc_name
, "__kcrctab%s", export_type
) >= 0);
361 asection
*crc_sect
= bfd_get_section_by_name(isbfd
->abfd
,
363 struct supersect
*ss
, *crc_ss
= NULL
;
364 ss
= fetch_supersect(isbfd
, sym_sect
);
365 if (crc_sect
!= NULL
)
366 crc_ss
= fetch_supersect(isbfd
, crc_sect
);
369 assert(ss
->contents
.size
* sizeof(unsigned long) ==
370 crc_ss
->contents
.size
* sizeof(struct kernel_symbol
));
372 struct supersect orig_ss
, orig_crc_ss
;
373 supersect_move(&orig_ss
, ss
);
375 supersect_move(&orig_crc_ss
, crc_ss
);
377 struct kernel_symbol
*orig_ksym
;
378 unsigned long *orig_crc
;
379 for (orig_ksym
= orig_ss
.contents
.data
,
380 orig_crc
= orig_crc_ss
.contents
.data
;
381 (void *)orig_ksym
< orig_ss
.contents
.data
+ orig_ss
.contents
.size
;
382 orig_ksym
++, orig_crc
++) {
384 read_reloc(&orig_ss
, &orig_ksym
->value
,
385 sizeof(orig_ksym
->value
), &sym
);
386 if (!str_in_set(sym
->name
, &ed
->names
))
389 struct kernel_symbol
*ksym
= sect_grow(ss
, 1, typeof(*ksym
));
390 sect_copy(ss
, &ksym
->value
, &orig_ss
, &orig_ksym
->value
, 1);
391 /* Replace name with a mangled name */
392 write_ksplice_export(ss
->parent
, sym
->name
, export_type
, 0);
393 write_string(ss
, (const char **)&ksym
->name
,
394 "DISABLED_%s_%s", sym
->name
, kid
);
398 sect_grow(crc_ss
, 1, typeof(*orig_crc
)),
399 &orig_crc_ss
, orig_crc
, 1);
403 void rm_some_relocs(struct supersect
*ss
)
405 struct arelentp_vec orig_relocs
;
406 vec_move(&orig_relocs
, &ss
->relocs
);
409 for (relocp
= orig_relocs
.data
;
410 relocp
< orig_relocs
.data
+ orig_relocs
.size
; relocp
++) {
412 asymbol
*sym_ptr
= *(*relocp
)->sym_ptr_ptr
;
414 if (mode("rmsyms") && match_varargs(sym_ptr
->name
))
420 if (mode("keep-primary") && want_section(sym_ptr
->section
) &&
421 (str_in_set(sym_ptr
->section
->name
, &newsects
) ||
422 bfd_is_und_section(sym_ptr
->section
) ||
423 (sym_ptr
->flags
& BSF_FUNCTION
) == 0))
426 if (mode("finalize") && bfd_is_und_section(sym_ptr
->section
))
430 write_ksplice_reloc(ss
, *relocp
);
432 *vec_grow(&ss
->relocs
, 1) = *relocp
;
436 struct supersect
*make_section(struct superbfd
*sbfd
, const char *name
)
438 asection
*sect
= bfd_get_section_by_name(sbfd
->abfd
, name
);
440 return fetch_supersect(sbfd
, sect
);
442 return new_supersect(sbfd
, name
);
445 arelent
*create_reloc(struct supersect
*ss
, const void *addr
, asymbol
**symp
,
448 bfd_reloc_code_real_type code
;
449 switch (bfd_arch_bits_per_address(ss
->parent
->abfd
)) {
460 arelent
*reloc
= malloc(sizeof(*reloc
));
461 reloc
->sym_ptr_ptr
= symp
;
462 reloc
->address
= addr
- ss
->contents
.data
;
463 reloc
->howto
= bfd_reloc_type_lookup(ss
->parent
->abfd
, code
);
464 reloc
->addend
= offset
;
468 void write_reloc(struct supersect
*ss
, const void *addr
, asymbol
**symp
,
471 *vec_grow(&ss
->new_relocs
, 1) = create_reloc(ss
, addr
, symp
, offset
);
474 void write_string(struct supersect
*ss
, const char **addr
, const char *fmt
, ...)
478 int len
= vsnprintf(NULL
, 0, fmt
, ap
);
480 struct supersect
*str_ss
= make_section(ss
->parent
, ".ksplice_str");
481 char *buf
= sect_grow(str_ss
, len
+ 1, char);
483 vsnprintf(buf
, len
+ 1, fmt
, ap
);
486 write_reloc(ss
, addr
, &str_ss
->symbol
,
487 (void *)buf
- str_ss
->contents
.data
);
490 void lookup_system_map(struct addr_vec
*addrs
, const char *name
, long offset
)
492 struct addr_vec
*map_addrs
=
493 addr_vec_hash_lookup(&system_map
, name
, FALSE
);
494 if (map_addrs
== NULL
)
497 unsigned long *addr
, *map_addr
;
498 for (map_addr
= map_addrs
->data
;
499 map_addr
< map_addrs
->data
+ map_addrs
->size
; map_addr
++) {
500 for (addr
= addrs
->data
; addr
< addrs
->data
+ addrs
->size
;
502 if (*addr
== *map_addr
+ offset
)
505 if (addr
< addrs
->data
+ addrs
->size
)
507 *vec_grow(addrs
, 1) = *map_addr
+ offset
;
511 void write_system_map_array(struct superbfd
*sbfd
, struct supersect
*ss
,
512 const unsigned long **sym_addrs
,
513 unsigned long *num_sym_addrs
, asymbol
*sym
)
515 struct addr_vec addrs
;
518 if (bfd_is_abs_section(sym
->section
)) {
519 *vec_grow(&addrs
, 1) = sym
->value
;
520 } else if (bfd_is_und_section(sym
->section
)) {
521 lookup_system_map(&addrs
, sym
->name
, 0);
522 } else if (!bfd_is_const_section(sym
->section
)) {
524 for (gsymp
= sbfd
->syms
.data
;
525 gsymp
< sbfd
->syms
.data
+ sbfd
->syms
.size
; gsymp
++) {
526 asymbol
*gsym
= *gsymp
;
527 if ((gsym
->flags
& BSF_DEBUGGING
) == 0 &&
528 gsym
->section
== sym
->section
)
529 lookup_system_map(&addrs
, gsym
->name
,
530 sym
->value
- gsym
->value
);
534 *num_sym_addrs
= addrs
.size
;
535 if (addrs
.size
!= 0) {
536 struct supersect
*array_ss
= make_section(sbfd
,
538 void *buf
= sect_grow(array_ss
, addrs
.size
,
539 typeof(*addrs
.data
));
540 memcpy(buf
, addrs
.data
, addrs
.size
* sizeof(*addrs
.data
));
541 write_reloc(ss
, sym_addrs
, &array_ss
->symbol
,
542 buf
- array_ss
->contents
.data
);
550 void write_ksplice_symbol(struct supersect
*ss
,
551 const struct ksplice_symbol
*const *addr
,
552 asymbol
*sym
, const char *addstr_sect
)
554 struct supersect
*ksymbol_ss
= make_section(ss
->parent
,
556 struct ksplice_symbol
*ksymbol
= sect_grow(ksymbol_ss
, 1,
557 struct ksplice_symbol
);
559 if (bfd_is_und_section(sym
->section
) || (sym
->flags
& BSF_GLOBAL
) != 0) {
560 write_string(ksymbol_ss
, &ksymbol
->name
, "%s", sym
->name
);
561 } else if (bfd_is_const_section(sym
->section
)) {
562 ksymbol
->name
= NULL
;
564 asymbol
*gsym
= canonical_symbol(ss
->parent
, sym
);
567 ksymbol
->name
= NULL
;
569 write_string(ksymbol_ss
, &ksymbol
->name
, "%s",
573 write_string(ksymbol_ss
, &ksymbol
->label
, "%s%s",
574 symbol_label(ss
->parent
, sym
), addstr_sect
);
576 write_system_map_array(ss
->parent
, ksymbol_ss
, &ksymbol
->candidates
,
577 &ksymbol
->nr_candidates
, sym
);
579 write_reloc(ss
, addr
, &ksymbol_ss
->symbol
,
580 (void *)ksymbol
- ksymbol_ss
->contents
.data
);
583 void write_ksplice_reloc(struct supersect
*ss
, arelent
*orig_reloc
)
585 asymbol
*sym_ptr
= *orig_reloc
->sym_ptr_ptr
;
587 reloc_howto_type
*howto
= orig_reloc
->howto
;
589 bfd_vma addend
= get_reloc_offset(ss
, orig_reloc
, 0);
590 blot_section(ss
, orig_reloc
->address
, howto
);
592 struct supersect
*kreloc_ss
= make_section(ss
->parent
,
594 ".ksplice_init_relocs" :
596 struct ksplice_reloc
*kreloc
= sect_grow(kreloc_ss
, 1,
597 struct ksplice_reloc
);
599 write_reloc(kreloc_ss
, &kreloc
->blank_addr
,
600 &ss
->symbol
, orig_reloc
->address
);
601 kreloc
->blank_offset
= (unsigned long)orig_reloc
->address
;
602 write_ksplice_symbol(kreloc_ss
, &kreloc
->symbol
, sym_ptr
, "");
603 kreloc
->pcrel
= howto
->pc_relative
;
604 kreloc
->addend
= addend
;
605 kreloc
->size
= bfd_get_reloc_size(howto
);
606 kreloc
->dst_mask
= howto
->dst_mask
;
607 kreloc
->rightshift
= howto
->rightshift
;
608 kreloc
->signed_addend
=
609 (howto
->complain_on_overflow
== complain_overflow_signed
) ||
610 (howto
->complain_on_overflow
== complain_overflow_bitfield
);
613 #define CANARY(x, canary) ((x & ~howto->dst_mask) | (canary & howto->dst_mask))
615 void blot_section(struct supersect
*ss
, int offset
, reloc_howto_type
*howto
)
617 int bits
= bfd_get_reloc_size(howto
) * 8;
618 void *address
= ss
->contents
.data
+ offset
;
619 bfd_vma x
= bfd_get(bits
, ss
->parent
->abfd
, address
);
620 x
= (x
& ~howto
->dst_mask
) |
621 ((bfd_vma
)0x7777777777777777LL
& howto
->dst_mask
);
622 bfd_put(bits
, ss
->parent
->abfd
, x
, address
);
625 void write_ksplice_size(struct superbfd
*sbfd
, asymbol
**symp
)
627 asymbol
*sym
= *symp
;
629 /* We call bfd_print_symbol in order to get access to
630 * the size associated with the function symbol, which
631 * is not otherwise available through the BFD API
635 FILE *fp
= open_memstream(&buf
, &bufsize
);
636 bfd_print_symbol(sbfd
->abfd
, fp
, sym
, bfd_print_symbol_all
);
640 unsigned long symsize
;
643 assert(sscanf(buf
, "%*[^\t]\t%lx %as%n", &symsize
, &symname
, &len
) >=
645 assert(buf
[len
] == '\0');
646 assert(strcmp(symname
, sym
->name
) == 0);
650 struct supersect
*ksize_ss
= make_section(sbfd
, ".ksplice_sizes");
651 struct ksplice_size
*ksize
= sect_grow(ksize_ss
, 1,
652 struct ksplice_size
);
654 write_ksplice_symbol(ksize_ss
, &ksize
->symbol
, sym
,
655 mode("keep-primary") ? "(post)" : "");
656 ksize
->size
= symsize
;
657 ksize
->extended_size
= bfd_get_section_size(sym
->section
);
659 if (mode("keep-helper") &&
660 str_in_set(symbol_label(sbfd
, sym
->section
->symbol
), &delsects
) &&
661 (sym
->flags
& BSF_FUNCTION
))
662 ksize
->flags
|= KSPLICE_SIZE_DELETED
;
663 if (starts_with(sym
->section
->name
, ".rodata"))
664 ksize
->flags
|= KSPLICE_SIZE_RODATA
;
665 if (starts_with(sym
->section
->name
, ".data"))
666 ksize
->flags
|= KSPLICE_SIZE_DATA
;
667 if (starts_with(sym
->section
->name
, ".text") ||
668 starts_with(sym
->section
->name
, ".exit.text"))
669 ksize
->flags
|= KSPLICE_SIZE_TEXT
;
670 assert(ksize
->flags
!= 0);
671 write_reloc(ksize_ss
, &ksize
->thismod_addr
, symp
, 0);
674 void write_ksplice_patch(struct superbfd
*sbfd
, const char *sectname
)
676 struct supersect
*kpatch_ss
= make_section(sbfd
, ".ksplice_patches");
677 struct ksplice_patch
*kpatch
= sect_grow(kpatch_ss
, 1,
678 struct ksplice_patch
);
679 asection
*sect
= bfd_get_section_by_name(sbfd
->abfd
, sectname
);
680 assert(sect
!= NULL
);
682 write_string(kpatch_ss
, &kpatch
->label
, "%s",
683 symbol_label(sbfd
, sect
->symbol
));
684 write_ksplice_reloc(kpatch_ss
, create_reloc(kpatch_ss
, &kpatch
->oldaddr
,
686 write_reloc(kpatch_ss
, &kpatch
->repladdr
, §
->symbol
, 0);
689 void write_ksplice_export(struct superbfd
*sbfd
, const char *symname
,
690 const char *export_type
, int del
)
692 struct supersect
*export_ss
= make_section(sbfd
, ".ksplice_exports");
693 struct ksplice_export
*export
= sect_grow(export_ss
, 1,
694 struct ksplice_export
);
696 write_string(export_ss
, &export
->type
, "%s", export_type
);
698 write_string(export_ss
, &export
->name
, "%s", symname
);
699 write_string(export_ss
, &export
->new_name
,
700 "DISABLED_%s_%s", symname
, kid
);
702 write_string(export_ss
, &export
->new_name
, "%s", symname
);
703 write_string(export_ss
, &export
->name
, "DISABLED_%s_%s",
708 void rm_from_special(struct superbfd
*sbfd
, const struct specsect
*s
)
710 asection
*isection
= bfd_get_section_by_name(sbfd
->abfd
, s
->sectname
);
711 if (isection
== NULL
)
714 struct supersect
*ss
= fetch_supersect(sbfd
, isection
), orig_ss
;
715 supersect_move(&orig_ss
, ss
);
717 const void *orig_entry
;
718 for (orig_entry
= orig_ss
.contents
.data
;
719 orig_entry
< orig_ss
.contents
.data
+ orig_ss
.contents
.size
;
720 orig_entry
+= align(s
->entry_size
, 1 << ss
->alignment
)) {
722 read_reloc(&orig_ss
, orig_entry
, sizeof(void *), &sym
);
725 for (p
= sbfd
->abfd
->sections
; p
!= NULL
; p
= p
->next
) {
726 if (sym
->section
== p
727 && !is_special(p
) && !want_section(p
))
733 sect_copy(ss
, sect_do_grow(ss
, 1, s
->entry_size
,
735 &orig_ss
, orig_entry
, s
->entry_size
);
739 void mark_wanted_if_referenced(bfd
*abfd
, asection
*sect
, void *ignored
)
741 if (want_section(sect
))
743 if (!starts_with(sect
->name
, ".text")
744 && !starts_with(sect
->name
, ".exit.text")
745 && !starts_with(sect
->name
, ".rodata")
746 && !(starts_with(sect
->name
, ".data") && mode("keep-helper")))
749 if (mode("keep-helper")) {
750 struct superbfd
*sbfd
= fetch_superbfd(abfd
);
752 for (symp
= sbfd
->syms
.data
;
753 symp
< sbfd
->syms
.data
+ sbfd
->syms
.size
; symp
++) {
754 asymbol
*sym
= *symp
;
755 if (sym
->section
== sect
&&
756 (sym
->flags
& BSF_GLOBAL
) != 0) {
757 struct wsect
*w
= malloc(sizeof(*w
));
759 w
->next
= wanted_sections
;
766 bfd_map_over_sections(abfd
, check_for_ref_to_section
, sect
);
769 void check_for_ref_to_section(bfd
*abfd
, asection
*looking_at
,
772 if (!want_section(looking_at
) || is_special(looking_at
))
775 struct superbfd
*sbfd
= fetch_superbfd(abfd
);
776 struct supersect
*ss
= fetch_supersect(sbfd
, looking_at
);
778 for (relocp
= ss
->relocs
.data
;
779 relocp
< ss
->relocs
.data
+ ss
->relocs
.size
; relocp
++) {
780 asymbol
*sym
= *(*relocp
)->sym_ptr_ptr
;
781 if (sym
->section
== (asection
*)looking_for
&&
782 (!starts_with(sym
->section
->name
, ".text") ||
783 get_reloc_offset(ss
, *relocp
, 1) != 0)) {
784 struct wsect
*w
= malloc(sizeof(*w
));
785 w
->sect
= looking_for
;
786 w
->next
= wanted_sections
;
793 /* Modified function from GNU Binutils objcopy.c */
794 bfd_boolean
copy_object(bfd
*ibfd
, bfd
*obfd
)
796 assert(bfd_set_format(obfd
, bfd_get_format(ibfd
)));
798 bfd_vma start
= bfd_get_start_address(ibfd
);
800 flagword flags
= bfd_get_file_flags(ibfd
);
801 flags
&= bfd_applicable_file_flags(obfd
);
803 assert(bfd_set_start_address(obfd
, start
)
804 && bfd_set_file_flags(obfd
, flags
));
806 enum bfd_architecture iarch
= bfd_get_arch(ibfd
);
807 unsigned int imach
= bfd_get_mach(ibfd
);
808 assert(bfd_set_arch_mach(obfd
, iarch
, imach
));
809 assert(bfd_set_format(obfd
, bfd_get_format(ibfd
)));
811 /* BFD mandates that all output sections be created and sizes set before
812 any output is done. Thus, we traverse all sections multiple times. */
813 bfd_map_over_sections(ibfd
, setup_section
, obfd
);
815 struct supersect
*new_supersects
= fetch_superbfd(ibfd
)->new_supersects
;
816 struct supersect
*ss
;
817 for (ss
= new_supersects
; ss
!= NULL
; ss
= ss
->next
)
818 setup_new_section(obfd
, ss
);
820 /* Mark symbols used in output relocations so that they
821 are kept, even if they are local labels or static symbols.
823 Note we iterate over the input sections examining their
824 relocations since the relocations for the output sections
825 haven't been set yet. mark_symbols_used_in_relocations will
826 ignore input sections which have no corresponding output
829 bfd_map_over_sections(ibfd
, mark_symbols_used_in_relocations
, NULL
);
830 for (ss
= new_supersects
; ss
!= NULL
; ss
= ss
->next
)
831 ss_mark_symbols_used_in_relocations(ss
);
832 struct asymbolp_vec osyms
;
834 filter_symbols(ibfd
, obfd
, &osyms
, &fetch_superbfd(ibfd
)->syms
);
836 bfd_set_symtab(obfd
, osyms
.data
, osyms
.size
);
838 /* This has to happen after the symbol table has been set. */
839 bfd_map_over_sections(obfd
, write_section
, NULL
);
841 /* Allow the BFD backend to copy any private data it understands
842 from the input BFD to the output BFD. This is done last to
843 permit the routine to look at the filtered symbol table, which is
844 important for the ECOFF code at least. */
845 assert(bfd_copy_private_bfd_data(ibfd
, obfd
));
850 /* Modified function from GNU Binutils objcopy.c */
851 void setup_section(bfd
*ibfd
, asection
*isection
, void *obfdarg
)
856 if (!want_section(isection
))
859 asection
*osection
= bfd_make_section_anyway(obfd
, isection
->name
);
860 assert(osection
!= NULL
);
862 struct superbfd
*isbfd
= fetch_superbfd(ibfd
);
863 struct supersect
*ss
= fetch_supersect(isbfd
, isection
);
864 osection
->userdata
= ss
;
865 bfd_set_section_flags(obfd
, osection
, ss
->flags
);
866 ss
->symbol
= osection
->symbol
;
867 assert(bfd_set_section_size(obfd
, osection
, ss
->contents
.size
));
869 vma
= bfd_section_vma(ibfd
, isection
);
870 assert(bfd_set_section_vma(obfd
, osection
, vma
));
872 osection
->lma
= isection
->lma
;
873 assert(bfd_set_section_alignment(obfd
, osection
, ss
->alignment
));
874 osection
->entsize
= isection
->entsize
;
875 osection
->output_section
= osection
;
876 osection
->output_offset
= 0;
877 isection
->output_section
= osection
;
878 isection
->output_offset
= 0;
882 void setup_new_section(bfd
*obfd
, struct supersect
*ss
)
884 asection
*osection
= bfd_make_section_anyway(obfd
, ss
->name
);
885 assert(osection
!= NULL
);
886 bfd_set_section_flags(obfd
, osection
, ss
->flags
);
888 osection
->userdata
= ss
;
889 ss
->symbol
= osection
->symbol
;
890 assert(bfd_set_section_size(obfd
, osection
, ss
->contents
.size
));
891 assert(bfd_set_section_vma(obfd
, osection
, 0));
894 assert(bfd_set_section_alignment(obfd
, osection
, ss
->alignment
));
895 osection
->entsize
= 0;
896 osection
->output_section
= osection
;
897 osection
->output_offset
= 0;
900 void write_section(bfd
*obfd
, asection
*osection
, void *arg
)
902 struct supersect
*ss
= osection
->userdata
;
904 if ((ss
->flags
& SEC_GROUP
) != 0 || ss
->contents
.size
== 0)
909 for (relocp
= ss
->new_relocs
.data
;
910 relocp
< ss
->new_relocs
.data
+ ss
->new_relocs
.size
; relocp
++) {
912 if (bfd_get_arch(obfd
) == bfd_arch_arm
)
913 val
= osection
->use_rela_p
? 0 : (*relocp
)->addend
;
916 bfd_put(bfd_get_reloc_size((*relocp
)->howto
) * 8, obfd
, val
,
917 ss
->contents
.data
+ (*relocp
)->address
);
918 if (bfd_install_relocation(obfd
, *relocp
, ss
->contents
.data
,
919 0, osection
, &error_message
) !=
921 fprintf(stderr
, "ksplice: error installing reloc: %s",
926 memcpy(vec_grow(&ss
->relocs
, ss
->new_relocs
.size
), ss
->new_relocs
.data
,
927 ss
->new_relocs
.size
* sizeof(*ss
->new_relocs
.data
));
929 bfd_set_reloc(obfd
, osection
,
930 ss
->relocs
.size
== 0 ? NULL
: ss
->relocs
.data
,
933 if (ss
->flags
& SEC_HAS_CONTENTS
)
934 assert(bfd_set_section_contents
935 (obfd
, osection
, ss
->contents
.data
, 0,
939 /* Modified function from GNU Binutils objcopy.c
941 * Mark all the symbols which will be used in output relocations with
942 * the BSF_KEEP flag so that those symbols will not be stripped.
944 * Ignore relocations which will not appear in the output file.
946 void mark_symbols_used_in_relocations(bfd
*abfd
, asection
*isection
,
949 struct superbfd
*sbfd
= fetch_superbfd(abfd
);
950 if (isection
->output_section
== NULL
)
953 struct supersect
*ss
= fetch_supersect(sbfd
, isection
);
954 ss_mark_symbols_used_in_relocations(ss
);
957 void ss_mark_symbols_used_in_relocations(struct supersect
*ss
)
959 /* Examine each symbol used in a relocation. If it's not one of the
960 special bfd section symbols, then mark it with BSF_KEEP. */
962 for (relocp
= ss
->relocs
.data
;
963 relocp
< ss
->relocs
.data
+ ss
->relocs
.size
; relocp
++) {
964 asymbol
*sym
= *(*relocp
)->sym_ptr_ptr
;
965 if (!(bfd_is_const_section(sym
->section
) &&
966 sym
== sym
->section
->symbol
))
967 sym
->flags
|= BSF_KEEP
;
971 /* Modified function from GNU Binutils objcopy.c
973 * Choose which symbol entries to copy.
974 * We don't copy in place, because that confuses the relocs.
975 * Return the number of symbols to print.
977 void filter_symbols(bfd
*ibfd
, bfd
*obfd
, struct asymbolp_vec
*osyms
,
978 struct asymbolp_vec
*isyms
)
981 for (symp
= isyms
->data
; symp
< isyms
->data
+ isyms
->size
; symp
++) {
982 asymbol
*sym
= *symp
;
986 if (mode("keep") && (sym
->flags
& BSF_GLOBAL
) != 0 &&
987 !(mode("keep-primary") &&
988 str_in_set(sym
->section
->name
, &newsects
)))
989 sym
->flags
= (sym
->flags
& ~BSF_GLOBAL
) | BSF_LOCAL
;
991 if (mode("finalize") && (sym
->flags
& BSF_GLOBAL
) != 0)
992 sym
->flags
= (sym
->flags
& ~BSF_GLOBAL
) | BSF_LOCAL
;
994 if ((sym
->flags
& BSF_KEEP
) != 0 /* Used in relocation. */
995 || ((sym
->flags
& BSF_SECTION_SYM
) != 0
996 && ((*(sym
->section
)->symbol_ptr_ptr
)->flags
999 else if ((sym
->flags
& (BSF_GLOBAL
| BSF_WEAK
)) != 0)
1001 else if (bfd_decode_symclass(sym
) == 'I')
1002 /* Global symbols in $idata sections need to be retained.
1003 External users of the library containing the $idata
1004 section may reference these symbols. */
1006 else if ((sym
->flags
& BSF_GLOBAL
) != 0
1007 || (sym
->flags
& BSF_WEAK
) != 0
1008 || bfd_is_com_section(sym
->section
))
1010 else if ((sym
->flags
& BSF_DEBUGGING
) != 0)
1013 keep
= !bfd_is_local_label(ibfd
, sym
);
1015 if (!want_section(sym
->section
))
1018 if (mode("rmsyms") && match_varargs(sym
->name
))
1022 *vec_grow(osyms
, 1) = sym
;
1026 int match_varargs(const char *str
)
1029 for (i
= 0; i
< varargs_count
; i
++) {
1030 if (strcmp(str
, varargs
[i
]) == 0)
1036 void read_str_set(struct str_vec
*strs
)
1040 assert(getline(&buf
, &n
, stdin
) >= 0);
1044 char *str
= strtok_r(buf
, " \n", &saveptr
);
1048 *vec_grow(strs
, 1) = str
;
1052 int str_in_set(const char *str
, const struct str_vec
*strs
)
1055 for (strp
= strs
->data
; strp
< strs
->data
+ strs
->size
; strp
++) {
1056 if (strcmp(str
, *strp
) == 0)
1062 int want_section(asection
*sect
)
1064 static const char *static_want
[] = {
1066 ".altinstr_replacement",
1068 ".parainstructions",
1075 if (mode("keep-primary") && bfd_is_abs_section(sect
))
1077 const struct wsect
*w
= wanted_sections
;
1078 for (; w
!= NULL
; w
= w
->next
) {
1079 if (w
->sect
== sect
)
1083 if (starts_with(sect
->name
, ".ksplice"))
1085 if (mode("keep-helper") && starts_with(sect
->name
, ".text"))
1087 if (mode("keep-helper") && starts_with(sect
->name
, ".exit.text")
1088 && bfd_get_section_by_name(sect
->owner
, ".exitcall.exit") == NULL
)
1090 if (mode("keep-primary") && starts_with(sect
->name
, "__ksymtab"))
1092 if (mode("keep-primary") && starts_with(sect
->name
, "__kcrctab"))
1094 if (mode("keep-primary") && str_in_set(sect
->name
, §ions
))
1096 if (mode("keep-primary") && str_in_set(sect
->name
, &newsects
))
1100 for (i
= 0; static_want
[i
] != NULL
; i
++) {
1101 if (strcmp(sect
->name
, static_want
[i
]) == 0)
1107 const struct specsect
*is_special(asection
*sect
)
1109 const struct specsect
*ss
;
1110 for (ss
= special_sections
; ss
!= end_special_sections
; ss
++) {
1111 if (strcmp(ss
->sectname
, sect
->name
) == 0)