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"
106 struct asymbolp_vec isyms
;
110 char *modestr
, *addstr_all
= "", *addstr_sect_pre
= "", *addstr_sect
= "";
112 struct wsect
*wanted_sections
= NULL
;
114 struct specsect special_sections
[] = {
115 {".altinstructions", 1, ".altinstr_replacement",
116 2 * sizeof(void *) + 4},
117 {".smp_locks", 0, NULL
, sizeof(void *)},
118 {".parainstructions", 0, NULL
, sizeof(void *) + 4},
119 }, *const end_special_sections
= *(&special_sections
+ 1);
121 #define mode(str) starts_with(modestr, str)
123 DECLARE_VEC_TYPE(long, addr_vec
);
124 DEFINE_HASH_TYPE(struct addr_vec
, addr_vec_hash
,
125 addr_vec_hash_init
, addr_vec_hash_free
, addr_vec_hash_lookup
,
127 struct addr_vec_hash system_map
;
129 void load_system_map()
131 const char *config_dir
= getenv("KSPLICE_CONFIG_DIR");
134 snprintf(file
, sizeof(file
), "%s/System.map", config_dir
);
135 FILE *fp
= fopen(file
, "r");
137 addr_vec_hash_init(&system_map
);
141 while (fscanf(fp
, "%lx %c %256s\n", &addr
, &type
, sym
) == 3)
142 *vec_grow(addr_vec_hash_lookup(&system_map
, sym
, TRUE
),
147 int main(int argc
, char **argv
)
149 char *debug_name
= malloc(strlen(argv
[1]) + 4 + strlen(argv
[2]) + 1);
150 sprintf(debug_name
, "%s.pre%s", argv
[1], argv
[2]);
151 rename(argv
[1], debug_name
);
154 bfd
*ibfd
= bfd_openr(debug_name
, NULL
);
158 assert(bfd_check_format_matches(ibfd
, bfd_object
, &matching
));
160 const char *output_target
= bfd_get_target(ibfd
);
161 bfd
*obfd
= bfd_openw(argv
[1], output_target
);
164 get_syms(ibfd
, &isyms
);
168 addstr_all
= argv
[3];
169 addstr_sect
= argv
[4];
171 varargs_count
= argc
- 5;
172 } else if (mode("patchlist")) {
173 addstr_all
= argv
[3];
174 addstr_sect_pre
= argv
[4];
175 addstr_sect
= argv
[5];
177 varargs_count
= argc
- 6;
180 varargs_count
= argc
- 3;
183 if (mode("keep") || mode("sizelist") || mode("rmsyms"))
188 struct wsect
*tmp
= wanted_sections
;
189 bfd_map_over_sections(ibfd
, mark_wanted_if_referenced
,
191 if (tmp
== wanted_sections
)
197 for (symp
= isyms
.data
;
198 mode("sizelist") && symp
< isyms
.data
+ isyms
.size
; symp
++) {
199 asymbol
*sym
= *symp
;
200 if ((sym
->flags
& BSF_FUNCTION
)
201 && sym
->value
== 0 && !(sym
->flags
& BSF_WEAK
))
202 write_ksplice_size(ibfd
, symp
);
205 if (mode("patchlist")) {
207 for (symname
= varargs
; symname
< varargs
+ varargs_count
;
209 write_ksplice_patch(ibfd
, *symname
);
213 for (p
= ibfd
->sections
; p
!= NULL
; p
= p
->next
) {
214 if (is_special(p
->name
) || starts_with(p
->name
, ".ksplice"))
216 if (want_section(p
->name
, NULL
) || mode("rmsyms"))
217 rm_some_relocs(ibfd
, p
);
222 for (ss
= special_sections
; ss
!= end_special_sections
; ss
++)
223 rm_from_special(ibfd
, ss
);
226 copy_object(ibfd
, obfd
);
227 assert(bfd_close(obfd
));
228 assert(bfd_close(ibfd
));
232 void rm_some_relocs(bfd
*ibfd
, asection
*isection
)
234 struct supersect
*ss
= fetch_supersect(ibfd
, isection
, &isyms
);
235 struct arelentp_vec orig_relocs
;
236 vec_move(&orig_relocs
, &ss
->relocs
);
239 for (relocp
= orig_relocs
.data
;
240 relocp
< orig_relocs
.data
+ orig_relocs
.size
; ++relocp
) {
242 asymbol
*sym_ptr
= *(*relocp
)->sym_ptr_ptr
;
244 if (mode("rmsyms") && match_varargs(sym_ptr
->name
))
250 if (mode("keep-primary") && want_section(sym_ptr
->name
, NULL
))
254 write_ksplice_reloc(ibfd
, isection
, *relocp
, ss
);
256 *vec_grow(&ss
->relocs
, 1) = *relocp
;
260 struct supersect
*make_section(bfd
*abfd
, struct asymbolp_vec
*syms
, char *name
)
262 asection
*sect
= bfd_get_section_by_name(abfd
, name
);
264 return fetch_supersect(abfd
, sect
, syms
);
266 return new_supersect(name
);
269 void write_reloc(bfd
*abfd
, struct supersect
*ss
, void *addr
, asymbol
**symp
,
272 bfd_reloc_code_real_type code
;
273 switch (bfd_arch_bits_per_address(abfd
)) {
284 arelent
*reloc
= malloc(sizeof(*reloc
));
285 reloc
->sym_ptr_ptr
= symp
;
286 reloc
->address
= addr
- ss
->contents
.data
;
287 reloc
->howto
= bfd_reloc_type_lookup(abfd
, code
);
288 /* FIXME: bfd_perform_relocation? bfd_install_relocation? */
289 reloc
->addend
= offset
;
290 *(long *)addr
= reloc
->howto
->partial_inplace
? offset
: 0;
291 *vec_grow(&ss
->relocs
, 1) = reloc
;
294 void write_string(bfd
*ibfd
, struct supersect
*ss
, void *addr
,
295 const char *fmt
, ...)
299 int len
= vsnprintf(NULL
, 0, fmt
, ap
);
301 struct supersect
*str_ss
= make_section(ibfd
, &isyms
, ".ksplice_str");
302 char *buf
= sect_grow(str_ss
, len
+ 1, char);
304 vsnprintf(buf
, len
+ 1, fmt
, ap
);
307 write_reloc(ibfd
, ss
, addr
, &str_ss
->symbol
,
308 (void *)buf
- str_ss
->contents
.data
);
311 void write_system_map_array(bfd
*ibfd
, struct supersect
*ss
, long **sym_addrs
,
312 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 char *new_symname
= strdup(sym_ptr
->name
);
344 if (mode("keep-primary"))
345 want_section(sym_ptr
->name
, &new_symname
);
347 int addend
= orig_reloc
->addend
;
348 reloc_howto_type
*howto
= orig_reloc
->howto
;
349 int size
= bfd_get_reloc_size(howto
);
350 int addend2
= blot_section(ibfd
, isection
, orig_reloc
->address
, size
);
351 assert(addend
== 0 || addend2
== 0);
355 struct supersect
*kreloc_ss
= make_section(ibfd
, &isyms
,
357 ".ksplice_init_relocs" :
359 struct ksplice_reloc
*kreloc
= sect_grow(kreloc_ss
, 1,
360 struct ksplice_reloc
);
362 write_string(ibfd
, kreloc_ss
, &kreloc
->sym_name
, "%s%s",
363 new_symname
, addstr_all
);
364 write_reloc(ibfd
, kreloc_ss
, &kreloc
->blank_addr
,
365 &ss
->symbol
, orig_reloc
->address
);
366 kreloc
->blank_offset
= (long)orig_reloc
->address
;
367 write_system_map_array(ibfd
, kreloc_ss
, &kreloc
->sym_addrs
,
368 &kreloc
->num_sym_addrs
, sym_ptr
);
369 kreloc
->pcrel
= howto
->pc_relative
;
370 kreloc
->addend
= addend
;
374 int blot_section(bfd
*abfd
, asection
*sect
, int offset
, int size
)
376 struct supersect
*ss
= fetch_supersect(abfd
, sect
, &isyms
);
377 void *address
= ss
->contents
.data
+ offset
;
380 tmp
= *(int *)address
;
381 *((int *)address
) = 0x77777777;
382 } else if (size
== 8) {
383 tmp
= *(long long *)address
;
384 *((long long *)address
) = 0x7777777777777777ll
;
386 fprintf(stderr
, "ksplice: Unsupported size %d\n", size
);
392 void write_ksplice_size(bfd
*ibfd
, asymbol
**symp
)
394 asymbol
*sym
= *symp
;
396 /* We call bfd_print_symbol in order to get access to
397 * the size associated with the function symbol, which
398 * is not otherwise available through the BFD API
402 FILE *fp
= open_memstream(&buf
, &bufsize
);
403 bfd_print_symbol(ibfd
, fp
, sym
, bfd_print_symbol_all
);
407 unsigned long symsize
;
410 assert(sscanf(buf
, "%*[^\t]\t%lx %as%n", &symsize
, &symname
, &len
) >=
412 assert(buf
[len
] == '\0');
413 assert(strcmp(symname
, sym
->name
) == 0);
417 struct supersect
*ksize_ss
= make_section(ibfd
, &isyms
,
419 struct ksplice_size
*ksize
= sect_grow(ksize_ss
, 1,
420 struct ksplice_size
);
422 write_string(ibfd
, ksize_ss
, &ksize
->name
, "%s", sym
->name
);
423 ksize
->size
= symsize
;
424 write_reloc(ibfd
, ksize_ss
, &ksize
->thismod_addr
, symp
, 0);
425 write_system_map_array(ibfd
, ksize_ss
, &ksize
->sym_addrs
,
426 &ksize
->num_sym_addrs
, sym
);
429 void write_ksplice_patch(bfd
*ibfd
, char *symname
)
431 struct supersect
*kpatch_ss
= make_section(ibfd
, &isyms
,
433 struct ksplice_patch
*kpatch
= sect_grow(kpatch_ss
, 1,
434 struct ksplice_patch
);
437 snprintf(newname
, sizeof(newname
), "%s%s%s",
438 symname
, addstr_all
, addstr_sect
);
440 for (symp
= isyms
.data
; symp
< isyms
.data
+ isyms
.size
; symp
++) {
441 if (strcmp((*symp
)->name
, newname
) == 0)
444 assert(symp
< isyms
.data
+ isyms
.size
);
446 write_string(ibfd
, kpatch_ss
, &kpatch
->oldstr
, "%s%s%s",
447 symname
, addstr_all
, addstr_sect_pre
);
448 write_string(ibfd
, kpatch_ss
, &kpatch
->replstr
, "%s", newname
);
450 write_reloc(ibfd
, kpatch_ss
, &kpatch
->repladdr
, symp
, 0);
451 kpatch
->saved
= NULL
;
454 void rm_from_special(bfd
*ibfd
, struct specsect
*s
)
456 asection
*isection
= bfd_get_section_by_name(ibfd
, s
->sectname
);
457 if (isection
== NULL
)
460 struct supersect
*ss
= fetch_supersect(ibfd
, isection
, &isyms
);
461 struct void_vec orig_contents
;
462 vec_move(&orig_contents
, &ss
->contents
);
463 size_t pad
= align(orig_contents
.size
, 1 << ss
->alignment
) -
465 memset(vec_grow(&orig_contents
, pad
), 0, pad
);
466 struct arelentp_vec orig_relocs
;
467 vec_move(&orig_relocs
, &ss
->relocs
);
469 int entry_size
= align(s
->entry_size
, 1 << ss
->alignment
);
470 int relocs_per_entry
= s
->odd_relocs
? 2 : 1;
471 assert((orig_contents
.size
/ entry_size
) * relocs_per_entry
==
476 for (orig_entry
= orig_contents
.data
, relocp
= orig_relocs
.data
;
477 orig_entry
< orig_contents
.data
+ orig_contents
.size
;
478 orig_entry
+= entry_size
, relocp
+= relocs_per_entry
) {
479 asymbol
*sym
= *(*relocp
)->sym_ptr_ptr
;
481 asymbol
*odd_sym
= *(*(relocp
+ 1))->sym_ptr_ptr
;
482 assert(strcmp(odd_sym
->name
, s
->odd_relocname
) == 0);
485 for (p
= ibfd
->sections
; p
!= NULL
; p
= p
->next
) {
486 if (strcmp(sym
->name
, p
->name
) == 0
487 && !is_special(p
->name
)
488 && !want_section(p
->name
, NULL
))
494 void *new_entry
= vec_grow(&ss
->contents
, entry_size
);
495 memcpy(new_entry
, orig_entry
, entry_size
);
496 int modifier
= (new_entry
- ss
->contents
.data
) -
497 (orig_entry
- orig_contents
.data
);
498 arelent
**new_relocp
= vec_grow(&ss
->relocs
, 1);
499 *new_relocp
= *relocp
;
500 (*new_relocp
)->address
+= modifier
;
502 new_relocp
= vec_grow(&ss
->relocs
, 1);
503 *new_relocp
= *(relocp
+ 1);
504 (*new_relocp
)->address
+= modifier
;
509 void mark_wanted_if_referenced(bfd
*abfd
, asection
*sect
, void *ignored
)
511 if (want_section(sect
->name
, NULL
))
513 if (!starts_with(sect
->name
, ".text")
514 && !starts_with(sect
->name
, ".rodata"))
517 bfd_map_over_sections(abfd
, check_for_ref_to_section
, sect
);
520 void check_for_ref_to_section(bfd
*abfd
, asection
*looking_at
,
523 if (!want_section(looking_at
->name
, NULL
))
526 struct supersect
*ss
= fetch_supersect(abfd
, looking_at
, &isyms
);
528 for (relocp
= ss
->relocs
.data
;
529 relocp
!= ss
->relocs
.data
+ ss
->relocs
.size
; ++relocp
) {
530 asymbol
*sym
= *(*relocp
)->sym_ptr_ptr
;
531 if (sym
->section
== (asection
*)looking_for
) {
532 struct wsect
*w
= malloc(sizeof(*w
));
533 w
->name
= strdup(((asection
*)looking_for
)->name
);
534 w
->next
= wanted_sections
;
540 /* Modified function from GNU Binutils objcopy.c */
541 bfd_boolean
copy_object(bfd
*ibfd
, bfd
*obfd
)
543 assert(bfd_set_format(obfd
, bfd_get_format(ibfd
)));
545 bfd_vma start
= bfd_get_start_address(ibfd
);
547 flagword flags
= bfd_get_file_flags(ibfd
);
548 flags
&= bfd_applicable_file_flags(obfd
);
550 assert(bfd_set_start_address(obfd
, start
)
551 && bfd_set_file_flags(obfd
, flags
));
553 enum bfd_architecture iarch
= bfd_get_arch(ibfd
);
554 unsigned int imach
= bfd_get_mach(ibfd
);
555 assert(bfd_set_arch_mach(obfd
, iarch
, imach
));
556 assert(bfd_set_format(obfd
, bfd_get_format(ibfd
)));
558 /* BFD mandates that all output sections be created and sizes set before
559 any output is done. Thus, we traverse all sections multiple times. */
560 bfd_map_over_sections(ibfd
, setup_section
, obfd
);
562 assert(bfd_count_sections(obfd
));
564 struct supersect
*ss
;
565 for (ss
= new_supersects
; ss
!= NULL
; ss
= ss
->next
)
566 setup_new_section(obfd
, ss
);
568 /* Mark symbols used in output relocations so that they
569 are kept, even if they are local labels or static symbols.
571 Note we iterate over the input sections examining their
572 relocations since the relocations for the output sections
573 haven't been set yet. mark_symbols_used_in_relocations will
574 ignore input sections which have no corresponding output
577 bfd_map_over_sections(ibfd
, mark_symbols_used_in_relocations
, &isyms
);
578 for (ss
= new_supersects
; ss
!= NULL
; ss
= ss
->next
)
579 ss_mark_symbols_used_in_relocations(ss
);
580 struct asymbolp_vec osyms
;
582 filter_symbols(ibfd
, obfd
, &osyms
, &isyms
);
584 bfd_set_symtab(obfd
, osyms
.data
, osyms
.size
);
586 /* This has to happen after the symbol table has been set. */
587 bfd_map_over_sections(ibfd
, copy_section
, obfd
);
588 for (ss
= new_supersects
; ss
!= NULL
; ss
= ss
->next
)
589 write_new_section(obfd
, ss
);
591 /* Allow the BFD backend to copy any private data it understands
592 from the input BFD to the output BFD. This is done last to
593 permit the routine to look at the filtered symbol table, which is
594 important for the ECOFF code at least. */
595 assert(bfd_copy_private_bfd_data(ibfd
, obfd
));
600 /* Modified function from GNU Binutils objcopy.c */
601 void setup_section(bfd
*ibfd
, asection
*isection
, void *obfdarg
)
606 char *name
= strdup(isection
->name
);
607 if (!want_section(isection
->name
, &name
))
610 asection
*osection
= bfd_make_section_anyway(obfd
, name
);
611 assert(osection
!= NULL
);
613 flagword flags
= bfd_get_section_flags(ibfd
, isection
);
614 bfd_set_section_flags(obfd
, osection
, flags
);
616 struct supersect
*ss
= fetch_supersect(ibfd
, isection
, &isyms
);
617 osection
->userdata
= ss
;
618 ss
->symbol
= osection
->symbol
;
619 assert(bfd_set_section_size(obfd
, osection
, ss
->contents
.size
));
621 vma
= bfd_section_vma(ibfd
, isection
);
622 assert(bfd_set_section_vma(obfd
, osection
, vma
));
624 osection
->lma
= isection
->lma
;
625 assert(bfd_set_section_alignment(obfd
, osection
, ss
->alignment
));
626 osection
->entsize
= isection
->entsize
;
627 isection
->output_section
= osection
;
628 isection
->output_offset
= 0;
632 void setup_new_section(bfd
*obfd
, struct supersect
*ss
)
634 asection
*osection
= bfd_make_section_anyway(obfd
, ss
->name
);
635 assert(osection
!= NULL
);
636 bfd_set_section_flags(obfd
, osection
,
637 SEC_ALLOC
| SEC_HAS_CONTENTS
| SEC_RELOC
);
639 osection
->userdata
= ss
;
640 ss
->symbol
= osection
->symbol
;
641 assert(bfd_set_section_size(obfd
, osection
, ss
->contents
.size
));
642 assert(bfd_set_section_vma(obfd
, osection
, 0));
645 assert(bfd_set_section_alignment(obfd
, osection
, ss
->alignment
));
646 osection
->entsize
= 0;
649 /* Modified function from GNU Binutils objcopy.c */
650 void copy_section(bfd
*ibfd
, asection
*isection
, void *obfdarg
)
654 char *name
= strdup(isection
->name
);
655 if (!want_section(isection
->name
, &name
))
658 flagword flags
= bfd_get_section_flags(ibfd
, isection
);
659 if ((flags
& SEC_GROUP
) != 0)
662 struct supersect
*ss
= fetch_supersect(ibfd
, isection
, &isyms
);
663 asection
*osection
= isection
->output_section
;
664 if (ss
->contents
.size
== 0 || osection
== 0)
667 bfd_set_reloc(obfd
, osection
,
668 ss
->relocs
.size
== 0 ? NULL
: ss
->relocs
.data
,
671 if (bfd_get_section_flags(ibfd
, isection
) & SEC_HAS_CONTENTS
672 && bfd_get_section_flags(obfd
, osection
) & SEC_HAS_CONTENTS
)
673 assert(bfd_set_section_contents
674 (obfd
, osection
, ss
->contents
.data
, 0,
678 void write_new_section(bfd
*obfd
, struct supersect
*ss
)
680 asection
*osection
= bfd_get_section_by_name(obfd
, ss
->name
);
682 if (ss
->contents
.size
== 0 || osection
== 0)
685 bfd_set_reloc(obfd
, osection
,
686 ss
->relocs
.size
== 0 ? NULL
: ss
->relocs
.data
,
689 if (bfd_get_section_flags(obfd
, osection
) & SEC_HAS_CONTENTS
)
690 assert(bfd_set_section_contents
691 (obfd
, osection
, ss
->contents
.data
, 0,
695 /* Modified function from GNU Binutils objcopy.c
697 * Mark all the symbols which will be used in output relocations with
698 * the BSF_KEEP flag so that those symbols will not be stripped.
700 * Ignore relocations which will not appear in the output file.
702 void mark_symbols_used_in_relocations(bfd
*ibfd
, asection
*isection
,
705 if (isection
->output_section
== NULL
)
708 struct supersect
*ss
= fetch_supersect(ibfd
, isection
, &isyms
);
709 ss_mark_symbols_used_in_relocations(ss
);
712 void ss_mark_symbols_used_in_relocations(struct supersect
*ss
)
714 /* Examine each symbol used in a relocation. If it's not one of the
715 special bfd section symbols, then mark it with BSF_KEEP. */
717 for (relocp
= ss
->relocs
.data
;
718 relocp
< ss
->relocs
.data
+ ss
->relocs
.size
; relocp
++) {
719 asymbol
*sym
= *(*relocp
)->sym_ptr_ptr
;
720 if (sym
!= bfd_com_section_ptr
->symbol
721 && sym
!= bfd_abs_section_ptr
->symbol
722 && sym
!= bfd_und_section_ptr
->symbol
)
723 sym
->flags
|= BSF_KEEP
;
727 /* Modified function from GNU Binutils objcopy.c
729 * Choose which symbol entries to copy.
730 * We don't copy in place, because that confuses the relocs.
731 * Return the number of symbols to print.
733 void filter_symbols(bfd
*abfd
, bfd
*obfd
, struct asymbolp_vec
*osyms
,
734 struct asymbolp_vec
*isyms
)
737 for (symp
= isyms
->data
; symp
< isyms
->data
+ isyms
->size
; symp
++) {
738 asymbol
*sym
= *symp
;
739 flagword flags
= sym
->flags
;
741 if (mode("keep") && want_section(sym
->section
->name
, NULL
)) {
743 malloc(strlen(sym
->name
) + strlen(addstr_all
) +
744 strlen(addstr_sect
) + 1);
745 sprintf(newname
, "%s%s%s", sym
->name
, addstr_all
,
751 if ((flags
& BSF_KEEP
) != 0 /* Used in relocation. */
752 || ((flags
& BSF_SECTION_SYM
) != 0
753 && ((*(sym
->section
)->symbol_ptr_ptr
)->flags
756 else if ((flags
& (BSF_GLOBAL
| BSF_WEAK
)) != 0)
758 else if (bfd_decode_symclass(sym
) == 'I')
759 /* Global symbols in $idata sections need to be retained.
760 External users of the library containing the $idata
761 section may reference these symbols. */
763 else if ((flags
& BSF_GLOBAL
) != 0
764 || (flags
& BSF_WEAK
) != 0
765 || bfd_is_com_section(sym
->section
))
767 else if ((flags
& BSF_DEBUGGING
) != 0)
770 keep
= !bfd_is_local_label(abfd
, sym
);
772 if (!want_section(sym
->section
->name
, NULL
))
775 if (mode("rmsyms") && match_varargs(sym
->name
))
779 *vec_grow(osyms
, 1) = sym
;
783 for (p
= obfd
->sections
; mode("keep") && p
!= NULL
; p
= p
->next
) {
784 if (starts_with(p
->name
, ".rodata") &&
785 !exists_sym_with_name(isyms
, p
->name
)) {
786 asymbol
*new = bfd_make_empty_symbol(obfd
);
789 new->flags
= BSF_GLOBAL
;
791 *vec_grow(osyms
, 1) = new;
796 int exists_sym_with_name(struct asymbolp_vec
*syms
, const char *desired
)
799 for (symp
= syms
->data
; symp
< syms
->data
+ syms
->size
; symp
++) {
800 if (strcmp(bfd_asymbol_name(*symp
), desired
) == 0)
806 int match_varargs(const char *str
)
809 for (i
= 0; i
< varargs_count
; i
++) {
810 if (strcmp(str
, varargs
[i
]) == 0)
816 int want_section(const char *name
, char **newname
)
818 static const char *static_want
[] = {
820 ".altinstr_replacement",
829 struct wsect
*w
= wanted_sections
;
830 for (; w
!= NULL
; w
= w
->next
) {
831 if (strcmp(w
->name
, name
) == 0)
835 if (starts_with(name
, ".ksplice"))
837 if (mode("keep-helper") && starts_with(name
, ".text"))
839 if (match_varargs(name
))
843 for (i
= 0; static_want
[i
] != NULL
; i
++) {
844 if (strcmp(name
, static_want
[i
]) == 0)
851 if (newname
!= NULL
) {
853 malloc(strlen(name
) + strlen(addstr_all
) +
854 strlen(addstr_sect
) + 1);
855 sprintf(*newname
, "%s%s%s", name
, addstr_all
, addstr_sect
);
860 struct specsect
*is_special(const char *name
)
863 for (ss
= special_sections
; ss
!= end_special_sections
; ss
++) {
864 if (strcmp(ss
->sectname
, name
) == 0)