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"
100 #include "kmodsrc/ksplice.h"
107 struct asymbolp_vec isyms
;
111 char *modestr
, *addstr_all
= "", *addstr_sect_pre
= "", *addstr_sect
= "";
113 struct wsect
*wanted_sections
= NULL
;
115 struct specsect special_sections
[] = {
116 {".altinstructions", 1, ".altinstr_replacement",
117 2 * sizeof(void *) + 4},
118 {".smp_locks", 0, NULL
, sizeof(void *)},
119 {".parainstructions", 0, NULL
, sizeof(void *) + 4},
120 }, *const end_special_sections
= *(&special_sections
+ 1);
122 #define mode(str) starts_with(modestr, str)
124 DECLARE_VEC_TYPE(unsigned long, addr_vec
);
125 DEFINE_HASH_TYPE(struct addr_vec
, addr_vec_hash
,
126 addr_vec_hash_init
, addr_vec_hash_free
, addr_vec_hash_lookup
,
128 struct addr_vec_hash system_map
;
130 void load_system_map()
132 const char *config_dir
= getenv("KSPLICE_CONFIG_DIR");
135 snprintf(file
, sizeof(file
), "%s/System.map", config_dir
);
136 FILE *fp
= fopen(file
, "r");
138 addr_vec_hash_init(&system_map
);
142 while (fscanf(fp
, "%lx %c %256s\n", &addr
, &type
, sym
) == 3)
143 *vec_grow(addr_vec_hash_lookup(&system_map
, sym
, TRUE
),
148 int main(int argc
, char **argv
)
150 char *debug_name
= malloc(strlen(argv
[1]) + 4 + strlen(argv
[2]) + 1);
151 sprintf(debug_name
, "%s.pre%s", argv
[1], argv
[2]);
152 rename(argv
[1], debug_name
);
155 bfd
*ibfd
= bfd_openr(debug_name
, NULL
);
159 assert(bfd_check_format_matches(ibfd
, bfd_object
, &matching
));
161 const char *output_target
= bfd_get_target(ibfd
);
162 bfd
*obfd
= bfd_openw(argv
[1], output_target
);
165 get_syms(ibfd
, &isyms
);
168 if (mode("keep") || mode("sizelist")) {
169 addstr_all
= argv
[3];
170 addstr_sect
= argv
[4];
172 varargs_count
= argc
- 5;
173 } else if (mode("patchlist")) {
174 addstr_all
= argv
[3];
175 addstr_sect_pre
= argv
[4];
176 addstr_sect
= argv
[5];
178 varargs_count
= argc
- 6;
181 varargs_count
= argc
- 3;
184 if (mode("keep") || mode("sizelist") || mode("rmsyms"))
189 struct wsect
*tmp
= wanted_sections
;
190 bfd_map_over_sections(ibfd
, mark_wanted_if_referenced
,
192 if (tmp
== wanted_sections
)
198 for (symp
= isyms
.data
;
199 mode("sizelist") && symp
< isyms
.data
+ isyms
.size
; symp
++) {
200 asymbol
*sym
= *symp
;
201 if ((sym
->flags
& BSF_FUNCTION
)
202 && sym
->value
== 0 && !(sym
->flags
& BSF_WEAK
))
203 write_ksplice_size(ibfd
, symp
);
206 if (mode("patchlist")) {
208 for (symname
= varargs
; symname
< varargs
+ varargs_count
;
210 write_ksplice_patch(ibfd
, *symname
);
214 for (p
= ibfd
->sections
; p
!= NULL
; p
= p
->next
) {
215 if (is_special(p
->name
) || starts_with(p
->name
, ".ksplice"))
217 if (want_section(p
->name
) || mode("rmsyms"))
218 rm_some_relocs(ibfd
, p
);
223 for (ss
= special_sections
; ss
!= end_special_sections
; ss
++)
224 rm_from_special(ibfd
, ss
);
227 copy_object(ibfd
, obfd
);
228 assert(bfd_close(obfd
));
229 assert(bfd_close(ibfd
));
233 void rm_some_relocs(bfd
*ibfd
, asection
*isection
)
235 struct supersect
*ss
= fetch_supersect(ibfd
, isection
, &isyms
);
236 struct arelentp_vec orig_relocs
;
237 vec_move(&orig_relocs
, &ss
->relocs
);
240 for (relocp
= orig_relocs
.data
;
241 relocp
< orig_relocs
.data
+ orig_relocs
.size
; ++relocp
) {
243 asymbol
*sym_ptr
= *(*relocp
)->sym_ptr_ptr
;
245 if (mode("rmsyms") && match_varargs(sym_ptr
->name
))
251 if (mode("keep-primary") && want_section(sym_ptr
->name
))
255 write_ksplice_reloc(ibfd
, isection
, *relocp
, ss
);
257 *vec_grow(&ss
->relocs
, 1) = *relocp
;
261 struct supersect
*make_section(bfd
*abfd
, struct asymbolp_vec
*syms
, char *name
)
263 asection
*sect
= bfd_get_section_by_name(abfd
, name
);
265 return fetch_supersect(abfd
, sect
, syms
);
267 return new_supersect(name
);
270 void write_reloc(bfd
*abfd
, struct supersect
*ss
, void *addr
, asymbol
**symp
,
273 bfd_reloc_code_real_type code
;
274 switch (bfd_arch_bits_per_address(abfd
)) {
285 arelent
*reloc
= malloc(sizeof(*reloc
));
286 reloc
->sym_ptr_ptr
= symp
;
287 reloc
->address
= addr
- ss
->contents
.data
;
288 reloc
->howto
= bfd_reloc_type_lookup(abfd
, code
);
289 reloc
->addend
= offset
;
290 *vec_grow(&ss
->new_relocs
, 1) = reloc
;
293 void write_string(bfd
*ibfd
, struct supersect
*ss
, void *addr
,
294 const char *fmt
, ...)
298 int len
= vsnprintf(NULL
, 0, fmt
, ap
);
300 struct supersect
*str_ss
= make_section(ibfd
, &isyms
, ".ksplice_str");
301 char *buf
= sect_grow(str_ss
, len
+ 1, char);
303 vsnprintf(buf
, len
+ 1, fmt
, ap
);
306 write_reloc(ibfd
, ss
, addr
, &str_ss
->symbol
,
307 (void *)buf
- str_ss
->contents
.data
);
310 void write_system_map_array(bfd
*ibfd
, struct supersect
*ss
,
311 unsigned long **sym_addrs
,
312 unsigned long *num_sym_addrs
, asymbol
*sym
)
314 const char *system_map_name
= dup_wolabel(sym
->name
);
316 for (prefix
= (const char *[]){".text.", ".data.", ".bss.", NULL
};
317 *prefix
!= NULL
; prefix
++) {
318 if (starts_with(system_map_name
, *prefix
))
319 system_map_name
+= strlen(*prefix
);
321 struct addr_vec
*addrs
= addr_vec_hash_lookup(&system_map
,
322 system_map_name
, FALSE
);
324 struct supersect
*array_ss
= make_section(ibfd
, &isyms
,
326 void *buf
= sect_grow(array_ss
, addrs
->size
,
327 typeof(*addrs
->data
));
328 memcpy(buf
, addrs
->data
, addrs
->size
* sizeof(*addrs
->data
));
329 *num_sym_addrs
= addrs
->size
;
330 write_reloc(ibfd
, ss
, sym_addrs
, &array_ss
->symbol
,
331 buf
- array_ss
->contents
.data
);
338 void write_ksplice_reloc(bfd
*ibfd
, asection
*isection
, arelent
*orig_reloc
,
339 struct supersect
*ss
)
341 asymbol
*sym_ptr
= *orig_reloc
->sym_ptr_ptr
;
343 reloc_howto_type
*howto
= orig_reloc
->howto
;
345 bfd_vma inplace
= blot_section(ibfd
, isection
, orig_reloc
->address
,
348 struct supersect
*kreloc_ss
= make_section(ibfd
, &isyms
,
350 ".ksplice_init_relocs" :
352 struct ksplice_reloc
*kreloc
= sect_grow(kreloc_ss
, 1,
353 struct ksplice_reloc
);
355 write_string(ibfd
, kreloc_ss
, &kreloc
->sym_name
, "%s%s",
356 sym_ptr
->name
, addstr_all
);
357 write_reloc(ibfd
, kreloc_ss
, &kreloc
->blank_addr
,
358 &ss
->symbol
, orig_reloc
->address
);
359 kreloc
->blank_offset
= (unsigned long)orig_reloc
->address
;
360 write_system_map_array(ibfd
, kreloc_ss
, &kreloc
->sym_addrs
,
361 &kreloc
->num_sym_addrs
, sym_ptr
);
362 kreloc
->pcrel
= howto
->pc_relative
;
363 if (howto
->partial_inplace
)
364 kreloc
->addend
= inplace
;
366 kreloc
->addend
= orig_reloc
->addend
;
367 kreloc
->size
= bfd_get_reloc_size(howto
);
368 kreloc
->dst_mask
= howto
->dst_mask
;
369 kreloc
->rightshift
= howto
->rightshift
;
372 #define CANARY(x, canary) ((x & ~howto->dst_mask) | (canary & howto->dst_mask))
374 bfd_vma
blot_section(bfd
*abfd
, asection
*sect
, int offset
,
375 reloc_howto_type
*howto
)
377 struct supersect
*ss
= fetch_supersect(abfd
, sect
, &isyms
);
378 void *address
= ss
->contents
.data
+ offset
;
379 switch (howto
->size
) {
382 int8_t x
= bfd_get_8(abfd
, address
);
383 bfd_vma newx
= CANARY(x
, 0x77);
384 bfd_put_8(abfd
, newx
, address
);
385 return x
& howto
->src_mask
;
389 int16_t x
= bfd_get_16(abfd
, address
);
390 bfd_vma newx
= CANARY(x
, 0x7777);
391 bfd_put_16(abfd
, newx
, address
);
392 return x
& howto
->src_mask
;
396 int32_t x
= bfd_get_32(abfd
, address
);
397 bfd_vma newx
= CANARY(x
, 0x77777777);
398 bfd_put_32(abfd
, newx
, address
);
399 return x
& howto
->src_mask
;
403 int64_t x
= bfd_get_64(abfd
, address
);
404 bfd_vma newx
= CANARY(x
, 0x7777777777777777ll
);
405 bfd_put_64(abfd
, newx
, address
);
406 return x
& howto
->src_mask
;
409 fprintf(stderr
, "ksplice: Unsupported howto->size %d\n",
415 void write_ksplice_size(bfd
*ibfd
, asymbol
**symp
)
417 asymbol
*sym
= *symp
;
419 /* We call bfd_print_symbol in order to get access to
420 * the size associated with the function symbol, which
421 * is not otherwise available through the BFD API
425 FILE *fp
= open_memstream(&buf
, &bufsize
);
426 bfd_print_symbol(ibfd
, fp
, sym
, bfd_print_symbol_all
);
430 unsigned long symsize
;
433 assert(sscanf(buf
, "%*[^\t]\t%lx %as%n", &symsize
, &symname
, &len
) >=
435 assert(buf
[len
] == '\0');
436 assert(strcmp(symname
, sym
->name
) == 0);
440 struct supersect
*ksize_ss
= make_section(ibfd
, &isyms
,
442 struct ksplice_size
*ksize
= sect_grow(ksize_ss
, 1,
443 struct ksplice_size
);
445 write_string(ibfd
, ksize_ss
, &ksize
->name
, "%s", sym
->name
);
446 ksize
->size
= symsize
;
447 write_reloc(ibfd
, ksize_ss
, &ksize
->thismod_addr
, symp
, 0);
448 write_system_map_array(ibfd
, ksize_ss
, &ksize
->sym_addrs
,
449 &ksize
->num_sym_addrs
, sym
);
452 void write_ksplice_patch(bfd
*ibfd
, char *symname
)
454 struct supersect
*kpatch_ss
= make_section(ibfd
, &isyms
,
456 struct ksplice_patch
*kpatch
= sect_grow(kpatch_ss
, 1,
457 struct ksplice_patch
);
460 snprintf(newname
, sizeof(newname
), "%s%s%s",
461 symname
, addstr_all
, addstr_sect
);
463 for (symp
= isyms
.data
; symp
< isyms
.data
+ isyms
.size
; symp
++) {
464 if (strcmp((*symp
)->name
, newname
) == 0)
467 assert(symp
< isyms
.data
+ isyms
.size
);
469 write_string(ibfd
, kpatch_ss
, &kpatch
->oldstr
, "%s%s%s",
470 symname
, addstr_all
, addstr_sect_pre
);
472 write_reloc(ibfd
, kpatch_ss
, &kpatch
->repladdr
, symp
, 0);
473 kpatch
->saved
= NULL
;
476 void rm_from_special(bfd
*ibfd
, struct specsect
*s
)
478 asection
*isection
= bfd_get_section_by_name(ibfd
, s
->sectname
);
479 if (isection
== NULL
)
482 struct supersect
*ss
= fetch_supersect(ibfd
, isection
, &isyms
);
483 struct void_vec orig_contents
;
484 vec_move(&orig_contents
, &ss
->contents
);
485 size_t pad
= align(orig_contents
.size
, 1 << ss
->alignment
) -
487 memset(vec_grow(&orig_contents
, pad
), 0, pad
);
488 struct arelentp_vec orig_relocs
;
489 vec_move(&orig_relocs
, &ss
->relocs
);
491 int entry_size
= align(s
->entry_size
, 1 << ss
->alignment
);
492 int relocs_per_entry
= s
->odd_relocs
? 2 : 1;
493 assert((orig_contents
.size
/ entry_size
) * relocs_per_entry
==
498 for (orig_entry
= orig_contents
.data
, relocp
= orig_relocs
.data
;
499 orig_entry
< orig_contents
.data
+ orig_contents
.size
;
500 orig_entry
+= entry_size
, relocp
+= relocs_per_entry
) {
501 asymbol
*sym
= *(*relocp
)->sym_ptr_ptr
;
503 asymbol
*odd_sym
= *(*(relocp
+ 1))->sym_ptr_ptr
;
504 assert(strcmp(odd_sym
->name
, s
->odd_relocname
) == 0);
507 for (p
= ibfd
->sections
; p
!= NULL
; p
= p
->next
) {
508 if (strcmp(sym
->name
, p
->name
) == 0
509 && !is_special(p
->name
)
510 && !want_section(p
->name
))
516 void *new_entry
= vec_grow(&ss
->contents
, entry_size
);
517 memcpy(new_entry
, orig_entry
, entry_size
);
518 int modifier
= (new_entry
- ss
->contents
.data
) -
519 (orig_entry
- orig_contents
.data
);
520 arelent
**new_relocp
= vec_grow(&ss
->relocs
, 1);
521 *new_relocp
= *relocp
;
522 (*new_relocp
)->address
+= modifier
;
524 new_relocp
= vec_grow(&ss
->relocs
, 1);
525 *new_relocp
= *(relocp
+ 1);
526 (*new_relocp
)->address
+= modifier
;
531 void mark_wanted_if_referenced(bfd
*abfd
, asection
*sect
, void *ignored
)
533 if (want_section(sect
->name
))
535 if (!starts_with(sect
->name
, ".text")
536 && !starts_with(sect
->name
, ".rodata"))
539 bfd_map_over_sections(abfd
, check_for_ref_to_section
, sect
);
542 void check_for_ref_to_section(bfd
*abfd
, asection
*looking_at
,
545 if (!want_section(looking_at
->name
))
548 struct supersect
*ss
= fetch_supersect(abfd
, looking_at
, &isyms
);
550 for (relocp
= ss
->relocs
.data
;
551 relocp
!= ss
->relocs
.data
+ ss
->relocs
.size
; ++relocp
) {
552 asymbol
*sym
= *(*relocp
)->sym_ptr_ptr
;
553 if (sym
->section
== (asection
*)looking_for
) {
554 struct wsect
*w
= malloc(sizeof(*w
));
555 w
->name
= strdup(((asection
*)looking_for
)->name
);
556 w
->next
= wanted_sections
;
562 /* Modified function from GNU Binutils objcopy.c */
563 bfd_boolean
copy_object(bfd
*ibfd
, bfd
*obfd
)
565 assert(bfd_set_format(obfd
, bfd_get_format(ibfd
)));
567 bfd_vma start
= bfd_get_start_address(ibfd
);
569 flagword flags
= bfd_get_file_flags(ibfd
);
570 flags
&= bfd_applicable_file_flags(obfd
);
572 assert(bfd_set_start_address(obfd
, start
)
573 && bfd_set_file_flags(obfd
, flags
));
575 enum bfd_architecture iarch
= bfd_get_arch(ibfd
);
576 unsigned int imach
= bfd_get_mach(ibfd
);
577 assert(bfd_set_arch_mach(obfd
, iarch
, imach
));
578 assert(bfd_set_format(obfd
, bfd_get_format(ibfd
)));
580 /* BFD mandates that all output sections be created and sizes set before
581 any output is done. Thus, we traverse all sections multiple times. */
582 bfd_map_over_sections(ibfd
, setup_section
, obfd
);
584 assert(bfd_count_sections(obfd
));
586 struct supersect
*ss
;
587 for (ss
= new_supersects
; ss
!= NULL
; ss
= ss
->next
)
588 setup_new_section(obfd
, ss
);
590 /* Mark symbols used in output relocations so that they
591 are kept, even if they are local labels or static symbols.
593 Note we iterate over the input sections examining their
594 relocations since the relocations for the output sections
595 haven't been set yet. mark_symbols_used_in_relocations will
596 ignore input sections which have no corresponding output
599 bfd_map_over_sections(ibfd
, mark_symbols_used_in_relocations
, &isyms
);
600 for (ss
= new_supersects
; ss
!= NULL
; ss
= ss
->next
)
601 ss_mark_symbols_used_in_relocations(ss
);
602 struct asymbolp_vec osyms
;
604 filter_symbols(ibfd
, obfd
, &osyms
, &isyms
);
606 bfd_set_symtab(obfd
, osyms
.data
, osyms
.size
);
608 /* This has to happen after the symbol table has been set. */
609 bfd_map_over_sections(obfd
, write_section
, NULL
);
611 /* Allow the BFD backend to copy any private data it understands
612 from the input BFD to the output BFD. This is done last to
613 permit the routine to look at the filtered symbol table, which is
614 important for the ECOFF code at least. */
615 assert(bfd_copy_private_bfd_data(ibfd
, obfd
));
620 /* Modified function from GNU Binutils objcopy.c */
621 void setup_section(bfd
*ibfd
, asection
*isection
, void *obfdarg
)
626 if (!want_section(isection
->name
))
629 asection
*osection
= bfd_make_section_anyway(obfd
, isection
->name
);
630 assert(osection
!= NULL
);
632 struct supersect
*ss
= fetch_supersect(ibfd
, isection
, &isyms
);
633 osection
->userdata
= ss
;
634 bfd_set_section_flags(obfd
, osection
, ss
->flags
);
635 ss
->symbol
= osection
->symbol
;
636 assert(bfd_set_section_size(obfd
, osection
, ss
->contents
.size
));
638 vma
= bfd_section_vma(ibfd
, isection
);
639 assert(bfd_set_section_vma(obfd
, osection
, vma
));
641 osection
->lma
= isection
->lma
;
642 assert(bfd_set_section_alignment(obfd
, osection
, ss
->alignment
));
643 osection
->entsize
= isection
->entsize
;
644 osection
->output_section
= osection
;
645 osection
->output_offset
= 0;
646 isection
->output_section
= osection
;
647 isection
->output_offset
= 0;
651 void setup_new_section(bfd
*obfd
, struct supersect
*ss
)
653 asection
*osection
= bfd_make_section_anyway(obfd
, ss
->name
);
654 assert(osection
!= NULL
);
655 bfd_set_section_flags(obfd
, osection
, ss
->flags
);
657 osection
->userdata
= ss
;
658 ss
->symbol
= osection
->symbol
;
659 assert(bfd_set_section_size(obfd
, osection
, ss
->contents
.size
));
660 assert(bfd_set_section_vma(obfd
, osection
, 0));
663 assert(bfd_set_section_alignment(obfd
, osection
, ss
->alignment
));
664 osection
->entsize
= 0;
665 osection
->output_section
= osection
;
666 osection
->output_offset
= 0;
669 void write_section(bfd
*obfd
, asection
*osection
, void *arg
)
671 struct supersect
*ss
= osection
->userdata
;
673 if (!want_section(ss
->name
) ||
674 (ss
->flags
& SEC_GROUP
) != 0 ||
675 ss
->contents
.size
== 0)
680 for (relocp
= ss
->new_relocs
.data
;
681 relocp
< ss
->new_relocs
.data
+ ss
->new_relocs
.size
; ++relocp
) {
682 bfd_put(bfd_get_reloc_size((*relocp
)->howto
) * 8, obfd
, 0,
683 ss
->contents
.data
+ (*relocp
)->address
);
684 if (bfd_install_relocation(obfd
, *relocp
, ss
->contents
.data
,
685 0, osection
, &error_message
) !=
687 fprintf(stderr
, "ksplice: error installing reloc: %s",
692 memcpy(vec_grow(&ss
->relocs
, ss
->new_relocs
.size
), ss
->new_relocs
.data
,
693 ss
->new_relocs
.size
* sizeof(*ss
->new_relocs
.data
));
695 bfd_set_reloc(obfd
, osection
,
696 ss
->relocs
.size
== 0 ? NULL
: ss
->relocs
.data
,
699 if (ss
->flags
& SEC_HAS_CONTENTS
)
700 assert(bfd_set_section_contents
701 (obfd
, osection
, ss
->contents
.data
, 0,
705 /* Modified function from GNU Binutils objcopy.c
707 * Mark all the symbols which will be used in output relocations with
708 * the BSF_KEEP flag so that those symbols will not be stripped.
710 * Ignore relocations which will not appear in the output file.
712 void mark_symbols_used_in_relocations(bfd
*ibfd
, asection
*isection
,
715 if (isection
->output_section
== NULL
)
718 struct supersect
*ss
= fetch_supersect(ibfd
, isection
, &isyms
);
719 ss_mark_symbols_used_in_relocations(ss
);
722 void ss_mark_symbols_used_in_relocations(struct supersect
*ss
)
724 /* Examine each symbol used in a relocation. If it's not one of the
725 special bfd section symbols, then mark it with BSF_KEEP. */
727 for (relocp
= ss
->relocs
.data
;
728 relocp
< ss
->relocs
.data
+ ss
->relocs
.size
; relocp
++) {
729 asymbol
*sym
= *(*relocp
)->sym_ptr_ptr
;
730 if (sym
!= bfd_com_section_ptr
->symbol
731 && sym
!= bfd_abs_section_ptr
->symbol
732 && sym
!= bfd_und_section_ptr
->symbol
)
733 sym
->flags
|= BSF_KEEP
;
737 /* Modified function from GNU Binutils objcopy.c
739 * Choose which symbol entries to copy.
740 * We don't copy in place, because that confuses the relocs.
741 * Return the number of symbols to print.
743 void filter_symbols(bfd
*abfd
, bfd
*obfd
, struct asymbolp_vec
*osyms
,
744 struct asymbolp_vec
*isyms
)
747 for (symp
= isyms
->data
; symp
< isyms
->data
+ isyms
->size
; symp
++) {
748 asymbol
*sym
= *symp
;
750 if (mode("keep") && want_section(sym
->section
->name
)) {
752 malloc(strlen(sym
->name
) + strlen(addstr_all
) +
753 strlen(addstr_sect
) + 1);
754 sprintf(newname
, "%s%s%s", sym
->name
, addstr_all
,
759 if ((sym
->flags
& BSF_KEEP
) != 0 /* Used in relocation. */
760 || ((sym
->flags
& BSF_SECTION_SYM
) != 0
761 && ((*(sym
->section
)->symbol_ptr_ptr
)->flags
764 else if ((sym
->flags
& (BSF_GLOBAL
| BSF_WEAK
)) != 0)
766 else if (bfd_decode_symclass(sym
) == 'I')
767 /* Global symbols in $idata sections need to be retained.
768 External users of the library containing the $idata
769 section may reference these symbols. */
771 else if ((sym
->flags
& BSF_GLOBAL
) != 0
772 || (sym
->flags
& BSF_WEAK
) != 0
773 || bfd_is_com_section(sym
->section
))
775 else if ((sym
->flags
& BSF_DEBUGGING
) != 0)
778 keep
= !bfd_is_local_label(abfd
, sym
);
780 if (!want_section(sym
->section
->name
))
783 if (mode("rmsyms") && match_varargs(sym
->name
))
787 *vec_grow(osyms
, 1) = sym
;
791 int exists_sym_with_name(struct asymbolp_vec
*syms
, const char *desired
)
794 for (symp
= syms
->data
; symp
< syms
->data
+ syms
->size
; symp
++) {
795 if (strcmp(bfd_asymbol_name(*symp
), desired
) == 0)
801 int match_varargs(const char *str
)
804 for (i
= 0; i
< varargs_count
; i
++) {
805 if (strcmp(str
, varargs
[i
]) == 0)
811 int want_section(const char *name
)
813 static const char *static_want
[] = {
815 ".altinstr_replacement",
824 struct wsect
*w
= wanted_sections
;
825 for (; w
!= NULL
; w
= w
->next
) {
826 if (strcmp(w
->name
, name
) == 0)
830 if (starts_with(name
, ".ksplice"))
832 if (mode("keep-helper") && starts_with(name
, ".text"))
834 if (match_varargs(name
))
838 for (i
= 0; static_want
[i
] != NULL
; i
++) {
839 if (strcmp(name
, static_want
[i
]) == 0)
845 struct specsect
*is_special(const char *name
)
848 for (ss
= special_sections
; ss
!= end_special_sections
; ss
++) {
849 if (strcmp(ss
->sectname
, name
) == 0)