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 *symname
);
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
, entrysyms
, newsyms
, delsyms
;
163 struct export_desc_vec exports
;
165 const char *modestr
, *kid
;
168 struct wsect
*wanted_sections
= NULL
;
170 const struct specsect special_sections
[] = {
171 {".altinstructions", 2 * sizeof(void *) + 4},
172 {".smp_locks", sizeof(void *)},
173 {".parainstructions", sizeof(void *) + 4},
174 }, *const end_special_sections
= *(&special_sections
+ 1);
176 #define mode(str) starts_with(modestr, str)
178 DECLARE_VEC_TYPE(unsigned long, addr_vec
);
179 DEFINE_HASH_TYPE(struct addr_vec
, addr_vec_hash
,
180 addr_vec_hash_init
, addr_vec_hash_free
, addr_vec_hash_lookup
,
182 struct addr_vec_hash system_map
;
184 void load_system_map()
186 const char *config_dir
= getenv("KSPLICE_CONFIG_DIR");
189 assert(asprintf(&file
, "%s/System.map", config_dir
) >= 0);
190 FILE *fp
= fopen(file
, "r");
192 addr_vec_hash_init(&system_map
);
196 while (fscanf(fp
, "%lx %c %as\n", &addr
, &type
, &sym
) == 3)
197 *vec_grow(addr_vec_hash_lookup(&system_map
, sym
, TRUE
),
202 int needed_data_section(struct superbfd
*sbfd
, asection
*isection
)
204 struct supersect
*ss
= fetch_supersect(sbfd
, isection
);
205 if (starts_with(isection
->name
, ".rodata."))
207 if (starts_with(isection
->name
, ".data.")) {
208 /* Ignore .data.percpu sections */
209 if (starts_with(isection
->name
, ".data.percpu"))
211 return ss
->relocs
.size
!= 0;
216 int main(int argc
, char *argv
[])
219 assert(asprintf(&debug_name
, "%s.pre%s", argv
[1], argv
[2]) >= 0);
220 rename(argv
[1], debug_name
);
223 bfd
*ibfd
= bfd_openr(debug_name
, NULL
);
227 assert(bfd_check_format_matches(ibfd
, bfd_object
, &matching
));
229 const char *output_target
= bfd_get_target(ibfd
);
230 bfd
*obfd
= bfd_openw(argv
[1], output_target
);
233 struct superbfd
*isbfd
= fetch_superbfd(ibfd
);
238 } else if (mode("rmsyms")) {
240 varargs_count
= argc
- 3;
244 read_str_set(§ions
);
245 read_str_set(&entrysyms
);
246 read_str_set(&newsyms
);
247 read_str_set(&delsyms
);
249 /* https://bugzilla.redhat.com/show_bug.cgi?id=431832 */
250 while (ungetc(getc(stdin
), stdin
) != EOF
) {
252 int ret
= scanf("%as", §name
);
256 struct export_desc
*ed
= vec_grow(&exports
, 1);
257 ed
->sectname
= sectname
;
258 read_str_set(&ed
->names
);
262 char *c
= strstr(argv
[1], ".KSPLICE");
263 assert(asprintf(&addstr_all
, "<%.*s>",
264 (int)(c
== NULL
? strlen(argv
[1]) : c
- argv
[1]),
267 if (mode("keep-primary")) {
268 /* Create export_desc structures for all export sections */
270 for (sect
= isbfd
->abfd
->sections
; sect
!= NULL
;
272 struct export_desc
*ed
;
273 if (!starts_with(sect
->name
, "__ksymtab") ||
274 ends_with(sect
->name
, "_strings"))
276 for (ed
= exports
.data
;
277 ed
< exports
.data
+ exports
.size
; ed
++) {
278 if (strcmp(ed
->sectname
, sect
->name
) == 0)
281 if (ed
< exports
.data
+ exports
.size
)
283 ed
= vec_grow(&exports
, 1);
284 ed
->sectname
= sect
->name
;
285 vec_init(&ed
->names
);
289 if (mode("keep") || mode("rmsyms"))
294 const struct wsect
*tmp
= wanted_sections
;
295 bfd_map_over_sections(ibfd
, mark_wanted_if_referenced
,
297 if (tmp
== wanted_sections
)
303 for (symp
= isbfd
->syms
.data
;
304 mode("keep") && symp
< isbfd
->syms
.data
+ isbfd
->syms
.size
;
306 asymbol
*sym
= *symp
;
307 if (!want_section(sym
->section
))
309 if ((sym
->flags
& BSF_WEAK
) != 0)
311 if ((sym
->flags
& BSF_DEBUGGING
) != 0)
313 if ((sym
->flags
& BSF_FUNCTION
) && sym
->value
== 0)
314 write_ksplice_size(isbfd
, symp
);
315 if (sym
->value
== 0 && needed_data_section(isbfd
, sym
->section
))
316 write_ksplice_size(isbfd
, symp
);
319 if (mode("keep-primary")) {
320 const char **symname
;
321 for (symname
= entrysyms
.data
;
322 symname
< entrysyms
.data
+ entrysyms
.size
; symname
++)
323 write_ksplice_patch(isbfd
, *symname
);
325 const struct export_desc
*ed
;
326 for (ed
= exports
.data
; ed
< exports
.data
+ exports
.size
;
328 if (starts_with(ed
->sectname
, "del___ksymtab")) {
329 const char *export_type
=
330 ed
->sectname
+ strlen("del___ksymtab");
331 const char **symname
;
332 for (symname
= ed
->names
.data
;
333 symname
< ed
->names
.data
+ ed
->names
.size
;
335 write_ksplice_export(isbfd
, *symname
,
338 rm_some_exports(isbfd
, ed
);
344 for (p
= ibfd
->sections
; p
!= NULL
; p
= p
->next
) {
345 struct supersect
*ss
= fetch_supersect(isbfd
, p
);
346 if (is_special(p
) || starts_with(p
->name
, ".ksplice"))
348 if (want_section(p
) || mode("rmsyms"))
352 const struct specsect
*ss
;
354 for (ss
= special_sections
; ss
!= end_special_sections
; ss
++)
355 rm_from_special(isbfd
, ss
);
358 copy_object(ibfd
, obfd
);
359 assert(bfd_close(obfd
));
360 assert(bfd_close(ibfd
));
364 void rm_some_exports(struct superbfd
*isbfd
, const struct export_desc
*ed
)
366 assert(starts_with(ed
->sectname
, "__ksymtab"));
367 const char *export_type
= ed
->sectname
+ strlen("__ksymtab");
368 asection
*sym_sect
= bfd_get_section_by_name(isbfd
->abfd
, ed
->sectname
);
369 assert(sym_sect
!= NULL
);
370 char *export_crc_name
;
371 assert(asprintf(&export_crc_name
, "__kcrctab%s", export_type
) >= 0);
372 asection
*crc_sect
= bfd_get_section_by_name(isbfd
->abfd
,
374 struct supersect
*ss
, *crc_ss
= NULL
;
375 ss
= fetch_supersect(isbfd
, sym_sect
);
376 if (crc_sect
!= NULL
)
377 crc_ss
= fetch_supersect(isbfd
, crc_sect
);
380 assert(ss
->contents
.size
* sizeof(unsigned long) ==
381 crc_ss
->contents
.size
* sizeof(struct kernel_symbol
));
383 struct supersect orig_ss
, orig_crc_ss
;
384 supersect_move(&orig_ss
, ss
);
386 supersect_move(&orig_crc_ss
, crc_ss
);
388 struct kernel_symbol
*orig_ksym
;
389 unsigned long *orig_crc
;
390 for (orig_ksym
= orig_ss
.contents
.data
,
391 orig_crc
= orig_crc_ss
.contents
.data
;
392 (void *)orig_ksym
< orig_ss
.contents
.data
+ orig_ss
.contents
.size
;
393 orig_ksym
++, orig_crc
++) {
395 read_reloc(&orig_ss
, &orig_ksym
->value
,
396 sizeof(orig_ksym
->value
), &sym
);
397 if (!str_in_set(sym
->name
, &ed
->names
))
400 struct kernel_symbol
*ksym
= sect_grow(ss
, 1, typeof(*ksym
));
401 sect_copy(ss
, &ksym
->value
, &orig_ss
, &orig_ksym
->value
, 1);
402 /* Replace name with a mangled name */
403 write_ksplice_export(ss
->parent
, sym
->name
, export_type
, 0);
404 write_string(ss
, (const char **)&ksym
->name
,
405 "DISABLED_%s_%s", sym
->name
, kid
);
409 sect_grow(crc_ss
, 1, typeof(*orig_crc
)),
410 &orig_crc_ss
, orig_crc
, 1);
414 void rm_some_relocs(struct supersect
*ss
)
416 struct arelentp_vec orig_relocs
;
417 vec_move(&orig_relocs
, &ss
->relocs
);
420 for (relocp
= orig_relocs
.data
;
421 relocp
< orig_relocs
.data
+ orig_relocs
.size
; relocp
++) {
423 asymbol
*sym_ptr
= *(*relocp
)->sym_ptr_ptr
;
425 if (mode("rmsyms") && match_varargs(sym_ptr
->name
))
431 if (mode("keep-primary") && want_section(sym_ptr
->section
) &&
432 (str_in_set(sym_ptr
->name
, &newsyms
) ||
433 bfd_is_und_section(sym_ptr
->section
) ||
434 (sym_ptr
->flags
& BSF_FUNCTION
) == 0))
437 if (mode("finalize") && bfd_is_und_section(sym_ptr
->section
))
441 write_ksplice_reloc(ss
, *relocp
);
443 *vec_grow(&ss
->relocs
, 1) = *relocp
;
447 struct supersect
*make_section(struct superbfd
*sbfd
, const char *name
)
449 asection
*sect
= bfd_get_section_by_name(sbfd
->abfd
, name
);
451 return fetch_supersect(sbfd
, sect
);
453 return new_supersect(sbfd
, name
);
456 arelent
*create_reloc(struct supersect
*ss
, const void *addr
, asymbol
**symp
,
459 bfd_reloc_code_real_type code
;
460 switch (bfd_arch_bits_per_address(ss
->parent
->abfd
)) {
471 arelent
*reloc
= malloc(sizeof(*reloc
));
472 reloc
->sym_ptr_ptr
= symp
;
473 reloc
->address
= addr
- ss
->contents
.data
;
474 reloc
->howto
= bfd_reloc_type_lookup(ss
->parent
->abfd
, code
);
475 reloc
->addend
= offset
;
479 void write_reloc(struct supersect
*ss
, const void *addr
, asymbol
**symp
,
482 *vec_grow(&ss
->new_relocs
, 1) = create_reloc(ss
, addr
, symp
, offset
);
485 void write_string(struct supersect
*ss
, const char **addr
, const char *fmt
, ...)
489 int len
= vsnprintf(NULL
, 0, fmt
, ap
);
491 struct supersect
*str_ss
= make_section(ss
->parent
, ".ksplice_str");
492 char *buf
= sect_grow(str_ss
, len
+ 1, char);
494 vsnprintf(buf
, len
+ 1, fmt
, ap
);
497 write_reloc(ss
, addr
, &str_ss
->symbol
,
498 (void *)buf
- str_ss
->contents
.data
);
501 void lookup_system_map(struct addr_vec
*addrs
, const char *name
, long offset
)
503 struct addr_vec
*map_addrs
=
504 addr_vec_hash_lookup(&system_map
, name
, FALSE
);
505 if (map_addrs
== NULL
)
508 unsigned long *addr
, *map_addr
;
509 for (map_addr
= map_addrs
->data
;
510 map_addr
< map_addrs
->data
+ map_addrs
->size
; map_addr
++) {
511 for (addr
= addrs
->data
; addr
< addrs
->data
+ addrs
->size
;
513 if (*addr
== *map_addr
+ offset
)
516 if (addr
< addrs
->data
+ addrs
->size
)
518 *vec_grow(addrs
, 1) = *map_addr
+ offset
;
522 void write_system_map_array(struct superbfd
*sbfd
, struct supersect
*ss
,
523 const unsigned long **sym_addrs
,
524 unsigned long *num_sym_addrs
, asymbol
*sym
)
526 struct addr_vec addrs
;
529 if (bfd_is_abs_section(sym
->section
)) {
530 *vec_grow(&addrs
, 1) = sym
->value
;
531 } else if (bfd_is_und_section(sym
->section
)) {
532 lookup_system_map(&addrs
, sym
->name
, 0);
533 } else if (!bfd_is_const_section(sym
->section
)) {
535 for (gsymp
= sbfd
->syms
.data
;
536 gsymp
< sbfd
->syms
.data
+ sbfd
->syms
.size
; gsymp
++) {
537 asymbol
*gsym
= *gsymp
;
538 if ((gsym
->flags
& BSF_DEBUGGING
) == 0 &&
539 gsym
->section
== sym
->section
)
540 lookup_system_map(&addrs
, gsym
->name
,
541 sym
->value
- gsym
->value
);
545 *num_sym_addrs
= addrs
.size
;
546 if (addrs
.size
!= 0) {
547 struct supersect
*array_ss
= make_section(sbfd
,
549 void *buf
= sect_grow(array_ss
, addrs
.size
,
550 typeof(*addrs
.data
));
551 memcpy(buf
, addrs
.data
, addrs
.size
* sizeof(*addrs
.data
));
552 write_reloc(ss
, sym_addrs
, &array_ss
->symbol
,
553 buf
- array_ss
->contents
.data
);
561 struct caller_search
{
562 struct superbfd
*sbfd
;
564 asection
*calling_section
;
568 void search_for_caller(bfd
*abfd
, asection
*sect
, void *searchptr
)
570 struct caller_search
*search
= searchptr
;
571 struct superbfd
*sbfd
= search
->sbfd
;
572 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
575 for (relocp
= ss
->relocs
.data
;
576 relocp
< ss
->relocs
.data
+ ss
->relocs
.size
; relocp
++) {
577 asymbol
*rsym
= *(*relocp
)->sym_ptr_ptr
;
578 if (rsym
->section
== search
->sym
->section
&&
579 rsym
->value
+ get_reloc_offset(ss
, *relocp
, 1) ==
580 search
->sym
->value
) {
581 if (search
->calling_section
!= sect
)
583 if (search
->calling_section
== NULL
)
584 search
->calling_section
= sect
;
589 static const char *find_caller(struct supersect
*ss
, asymbol
*sym
)
591 struct caller_search search
= {
595 .calling_section
= NULL
,
598 bfd_map_over_sections(ss
->parent
->abfd
, search_for_caller
, &search
);
599 if (search
.count
== 1) {
600 return search
.calling_section
->name
;
601 } else if (search
.count
== 0) {
602 fprintf(stderr
, "No callers found in caller search: %s\n",
606 fprintf(stderr
, "Multiple candidates in caller search: %s: "
607 "%d\n", sym
->name
, search
.count
);
608 return "multiple callers";
612 const char *static_local_symbol(struct superbfd
*sbfd
, asymbol
*sym
)
614 struct supersect
*ss
= fetch_supersect(sbfd
, sym
->section
);
615 if ((sym
->flags
& BSF_LOCAL
) == 0 || (sym
->flags
& BSF_OBJECT
) == 0)
617 char *dot
= strrchr(sym
->name
, '.');
618 if (dot
== NULL
|| dot
[1 + strspn(dot
+ 1, "0123546789")] != '\0')
620 char *basename
= strndup(sym
->name
, dot
- sym
->name
);
622 if (strcmp(basename
, "__func__") == 0 ||
623 strcmp(basename
, "__PRETTY_FUNCTION__") == 0)
624 assert(asprintf(&mangled_name
, "%s<%s>", basename
,
625 (char *)ss
->contents
.data
+ sym
->value
) >= 0);
627 assert(asprintf(&mangled_name
, "%s<%s>", basename
,
628 find_caller(ss
, sym
)) >= 0);
632 void write_ksplice_symbol(struct supersect
*ss
,
633 const struct ksplice_symbol
*const *addr
,
634 asymbol
*sym
, const char *addstr_sect
)
636 struct supersect
*ksymbol_ss
= make_section(ss
->parent
,
638 struct ksplice_symbol
*ksymbol
= sect_grow(ksymbol_ss
, 1,
639 struct ksplice_symbol
);
641 if (bfd_is_und_section(sym
->section
) || (sym
->flags
& BSF_GLOBAL
) != 0) {
642 write_string(ksymbol_ss
, &ksymbol
->name
, "%s", sym
->name
);
643 write_string(ksymbol_ss
, &ksymbol
->label
, "%s%s", sym
->name
,
645 } else if (bfd_is_const_section(sym
->section
)) {
646 ksymbol
->name
= NULL
;
647 write_string(ksymbol_ss
, &ksymbol
->label
, "%s%s%s",
648 sym
->name
, addstr_all
, addstr_sect
);
650 const struct asymbolp_vec
*syms
= &ss
->parent
->syms
;
652 asymbol
*gsym
= NULL
;
653 for (gsymp
= syms
->data
; gsymp
< syms
->data
+ syms
->size
;
655 asymbol
*gsymtemp
= *gsymp
;
656 if ((gsymtemp
->flags
& BSF_DEBUGGING
) != 0 ||
657 sym
->section
!= gsymtemp
->section
||
658 sym
->value
!= gsymtemp
->value
)
660 if (gsym
== NULL
|| (gsymtemp
->flags
& BSF_GLOBAL
) != 0)
665 ksymbol
->name
= NULL
;
667 write_string(ksymbol_ss
, &ksymbol
->name
, "%s",
671 write_string(ksymbol_ss
, &ksymbol
->label
, "%s+%lx%s%s",
673 (unsigned long)sym
->value
, addstr_all
,
675 else if ((gsym
->flags
& BSF_GLOBAL
) != 0)
676 write_string(ksymbol_ss
, &ksymbol
->label
, "%s%s",
677 gsym
->name
, addstr_sect
);
678 else if (static_local_symbol(ss
->parent
, gsym
))
679 write_string(ksymbol_ss
, &ksymbol
->label
, "%s+%lx%s%s",
680 static_local_symbol(ss
->parent
, gsym
),
681 (unsigned long)sym
->value
,
682 addstr_all
, addstr_sect
);
684 write_string(ksymbol_ss
, &ksymbol
->label
, "%s%s%s",
685 gsym
->name
, addstr_all
, addstr_sect
);
688 write_system_map_array(ss
->parent
, ksymbol_ss
, &ksymbol
->candidates
,
689 &ksymbol
->nr_candidates
, sym
);
691 write_reloc(ss
, addr
, &ksymbol_ss
->symbol
,
692 (void *)ksymbol
- ksymbol_ss
->contents
.data
);
695 void write_ksplice_reloc(struct supersect
*ss
, arelent
*orig_reloc
)
697 asymbol
*sym_ptr
= *orig_reloc
->sym_ptr_ptr
;
699 reloc_howto_type
*howto
= orig_reloc
->howto
;
701 bfd_vma addend
= get_reloc_offset(ss
, orig_reloc
, 0);
702 blot_section(ss
, orig_reloc
->address
, howto
);
704 struct supersect
*kreloc_ss
= make_section(ss
->parent
,
706 ".ksplice_init_relocs" :
708 struct ksplice_reloc
*kreloc
= sect_grow(kreloc_ss
, 1,
709 struct ksplice_reloc
);
711 write_reloc(kreloc_ss
, &kreloc
->blank_addr
,
712 &ss
->symbol
, orig_reloc
->address
);
713 kreloc
->blank_offset
= (unsigned long)orig_reloc
->address
;
714 write_ksplice_symbol(kreloc_ss
, &kreloc
->symbol
, sym_ptr
, "");
715 kreloc
->pcrel
= howto
->pc_relative
;
716 kreloc
->addend
= addend
;
717 kreloc
->size
= bfd_get_reloc_size(howto
);
718 kreloc
->dst_mask
= howto
->dst_mask
;
719 kreloc
->rightshift
= howto
->rightshift
;
720 kreloc
->signed_addend
=
721 (howto
->complain_on_overflow
== complain_overflow_signed
) ||
722 (howto
->complain_on_overflow
== complain_overflow_bitfield
);
725 #define CANARY(x, canary) ((x & ~howto->dst_mask) | (canary & howto->dst_mask))
727 void blot_section(struct supersect
*ss
, int offset
, reloc_howto_type
*howto
)
729 int bits
= bfd_get_reloc_size(howto
) * 8;
730 void *address
= ss
->contents
.data
+ offset
;
731 bfd_vma x
= bfd_get(bits
, ss
->parent
->abfd
, address
);
732 x
= (x
& ~howto
->dst_mask
) |
733 ((bfd_vma
)0x7777777777777777LL
& howto
->dst_mask
);
734 bfd_put(bits
, ss
->parent
->abfd
, x
, address
);
737 void write_ksplice_size(struct superbfd
*sbfd
, asymbol
**symp
)
739 asymbol
*sym
= *symp
;
741 /* We call bfd_print_symbol in order to get access to
742 * the size associated with the function symbol, which
743 * is not otherwise available through the BFD API
747 FILE *fp
= open_memstream(&buf
, &bufsize
);
748 bfd_print_symbol(sbfd
->abfd
, fp
, sym
, bfd_print_symbol_all
);
752 unsigned long symsize
;
755 assert(sscanf(buf
, "%*[^\t]\t%lx %as%n", &symsize
, &symname
, &len
) >=
757 assert(buf
[len
] == '\0');
758 assert(strcmp(symname
, sym
->name
) == 0);
762 struct supersect
*ksize_ss
= make_section(sbfd
, ".ksplice_sizes");
763 struct ksplice_size
*ksize
= sect_grow(ksize_ss
, 1,
764 struct ksplice_size
);
766 write_ksplice_symbol(ksize_ss
, &ksize
->symbol
, sym
,
767 mode("keep-primary") ? "(post)" : "");
768 ksize
->size
= symsize
;
769 ksize
->extended_size
= bfd_get_section_size(sym
->section
);
771 if (mode("keep-helper") &&
772 str_in_set(sym
->name
, &delsyms
) && (sym
->flags
& BSF_FUNCTION
))
773 ksize
->flags
|= KSPLICE_SIZE_DELETED
;
774 if (starts_with(sym
->section
->name
, ".rodata"))
775 ksize
->flags
|= KSPLICE_SIZE_RODATA
;
776 if (starts_with(sym
->section
->name
, ".data"))
777 ksize
->flags
|= KSPLICE_SIZE_DATA
;
778 if (starts_with(sym
->section
->name
, ".text") ||
779 starts_with(sym
->section
->name
, ".exit.text"))
780 ksize
->flags
|= KSPLICE_SIZE_TEXT
;
781 assert(ksize
->flags
!= 0);
782 write_reloc(ksize_ss
, &ksize
->thismod_addr
, symp
, 0);
785 void write_ksplice_patch(struct superbfd
*sbfd
, const char *symname
)
787 struct supersect
*kpatch_ss
= make_section(sbfd
, ".ksplice_patches");
788 struct ksplice_patch
*kpatch
= sect_grow(kpatch_ss
, 1,
789 struct ksplice_patch
);
792 for (symp
= sbfd
->syms
.data
; symp
< sbfd
->syms
.data
+ sbfd
->syms
.size
;
794 if (strcmp((*symp
)->name
, symname
) == 0)
797 assert(symp
< sbfd
->syms
.data
+ sbfd
->syms
.size
);
799 write_ksplice_symbol(kpatch_ss
, &kpatch
->symbol
, *symp
, "");
800 write_ksplice_reloc(kpatch_ss
, create_reloc(kpatch_ss
, &kpatch
->oldaddr
,
802 write_reloc(kpatch_ss
, &kpatch
->repladdr
, symp
, 0);
805 void write_ksplice_export(struct superbfd
*sbfd
, const char *symname
,
806 const char *export_type
, int del
)
808 struct supersect
*export_ss
= make_section(sbfd
, ".ksplice_exports");
809 struct ksplice_export
*export
= sect_grow(export_ss
, 1,
810 struct ksplice_export
);
812 write_string(export_ss
, &export
->type
, "%s", export_type
);
814 write_string(export_ss
, &export
->name
, "%s", symname
);
815 write_string(export_ss
, &export
->new_name
,
816 "DISABLED_%s_%s", symname
, kid
);
818 write_string(export_ss
, &export
->new_name
, "%s", symname
);
819 write_string(export_ss
, &export
->name
, "DISABLED_%s_%s",
824 void rm_from_special(struct superbfd
*sbfd
, const struct specsect
*s
)
826 asection
*isection
= bfd_get_section_by_name(sbfd
->abfd
, s
->sectname
);
827 if (isection
== NULL
)
830 struct supersect
*ss
= fetch_supersect(sbfd
, isection
), orig_ss
;
831 supersect_move(&orig_ss
, ss
);
833 const void *orig_entry
;
834 for (orig_entry
= orig_ss
.contents
.data
;
835 orig_entry
< orig_ss
.contents
.data
+ orig_ss
.contents
.size
;
836 orig_entry
+= align(s
->entry_size
, 1 << ss
->alignment
)) {
838 read_reloc(&orig_ss
, orig_entry
, sizeof(void *), &sym
);
841 for (p
= sbfd
->abfd
->sections
; p
!= NULL
; p
= p
->next
) {
842 if (sym
->section
== p
843 && !is_special(p
) && !want_section(p
))
849 sect_copy(ss
, sect_do_grow(ss
, 1, s
->entry_size
,
851 &orig_ss
, orig_entry
, s
->entry_size
);
855 void mark_wanted_if_referenced(bfd
*abfd
, asection
*sect
, void *ignored
)
857 if (want_section(sect
))
859 if (!starts_with(sect
->name
, ".text")
860 && !starts_with(sect
->name
, ".exit.text")
861 && !starts_with(sect
->name
, ".rodata")
862 && !(starts_with(sect
->name
, ".data") && mode("keep-helper")))
865 if (mode("keep-helper")) {
866 struct superbfd
*sbfd
= fetch_superbfd(abfd
);
868 for (symp
= sbfd
->syms
.data
;
869 symp
< sbfd
->syms
.data
+ sbfd
->syms
.size
; symp
++) {
870 asymbol
*sym
= *symp
;
871 if (sym
->section
== sect
&&
872 (sym
->flags
& BSF_GLOBAL
) != 0) {
873 struct wsect
*w
= malloc(sizeof(*w
));
875 w
->next
= wanted_sections
;
882 bfd_map_over_sections(abfd
, check_for_ref_to_section
, sect
);
885 void check_for_ref_to_section(bfd
*abfd
, asection
*looking_at
,
888 if (!want_section(looking_at
) || is_special(looking_at
))
891 struct superbfd
*sbfd
= fetch_superbfd(abfd
);
892 struct supersect
*ss
= fetch_supersect(sbfd
, looking_at
);
894 for (relocp
= ss
->relocs
.data
;
895 relocp
< ss
->relocs
.data
+ ss
->relocs
.size
; relocp
++) {
896 asymbol
*sym
= *(*relocp
)->sym_ptr_ptr
;
897 if (sym
->section
== (asection
*)looking_for
&&
898 (!starts_with(sym
->section
->name
, ".text") ||
899 get_reloc_offset(ss
, *relocp
, 1) != 0)) {
900 struct wsect
*w
= malloc(sizeof(*w
));
901 w
->sect
= looking_for
;
902 w
->next
= wanted_sections
;
909 /* Modified function from GNU Binutils objcopy.c */
910 bfd_boolean
copy_object(bfd
*ibfd
, bfd
*obfd
)
912 assert(bfd_set_format(obfd
, bfd_get_format(ibfd
)));
914 bfd_vma start
= bfd_get_start_address(ibfd
);
916 flagword flags
= bfd_get_file_flags(ibfd
);
917 flags
&= bfd_applicable_file_flags(obfd
);
919 assert(bfd_set_start_address(obfd
, start
)
920 && bfd_set_file_flags(obfd
, flags
));
922 enum bfd_architecture iarch
= bfd_get_arch(ibfd
);
923 unsigned int imach
= bfd_get_mach(ibfd
);
924 assert(bfd_set_arch_mach(obfd
, iarch
, imach
));
925 assert(bfd_set_format(obfd
, bfd_get_format(ibfd
)));
927 /* BFD mandates that all output sections be created and sizes set before
928 any output is done. Thus, we traverse all sections multiple times. */
929 bfd_map_over_sections(ibfd
, setup_section
, obfd
);
931 struct supersect
*new_supersects
= fetch_superbfd(ibfd
)->new_supersects
;
932 struct supersect
*ss
;
933 for (ss
= new_supersects
; ss
!= NULL
; ss
= ss
->next
)
934 setup_new_section(obfd
, ss
);
936 /* Mark symbols used in output relocations so that they
937 are kept, even if they are local labels or static symbols.
939 Note we iterate over the input sections examining their
940 relocations since the relocations for the output sections
941 haven't been set yet. mark_symbols_used_in_relocations will
942 ignore input sections which have no corresponding output
945 bfd_map_over_sections(ibfd
, mark_symbols_used_in_relocations
, NULL
);
946 for (ss
= new_supersects
; ss
!= NULL
; ss
= ss
->next
)
947 ss_mark_symbols_used_in_relocations(ss
);
948 struct asymbolp_vec osyms
;
950 filter_symbols(ibfd
, obfd
, &osyms
, &fetch_superbfd(ibfd
)->syms
);
952 bfd_set_symtab(obfd
, osyms
.data
, osyms
.size
);
954 /* This has to happen after the symbol table has been set. */
955 bfd_map_over_sections(obfd
, write_section
, NULL
);
957 /* Allow the BFD backend to copy any private data it understands
958 from the input BFD to the output BFD. This is done last to
959 permit the routine to look at the filtered symbol table, which is
960 important for the ECOFF code at least. */
961 assert(bfd_copy_private_bfd_data(ibfd
, obfd
));
966 /* Modified function from GNU Binutils objcopy.c */
967 void setup_section(bfd
*ibfd
, asection
*isection
, void *obfdarg
)
972 if (!want_section(isection
))
975 asection
*osection
= bfd_make_section_anyway(obfd
, isection
->name
);
976 assert(osection
!= NULL
);
978 struct superbfd
*isbfd
= fetch_superbfd(ibfd
);
979 struct supersect
*ss
= fetch_supersect(isbfd
, isection
);
980 osection
->userdata
= ss
;
981 bfd_set_section_flags(obfd
, osection
, ss
->flags
);
982 ss
->symbol
= osection
->symbol
;
983 assert(bfd_set_section_size(obfd
, osection
, ss
->contents
.size
));
985 vma
= bfd_section_vma(ibfd
, isection
);
986 assert(bfd_set_section_vma(obfd
, osection
, vma
));
988 osection
->lma
= isection
->lma
;
989 assert(bfd_set_section_alignment(obfd
, osection
, ss
->alignment
));
990 osection
->entsize
= isection
->entsize
;
991 osection
->output_section
= osection
;
992 osection
->output_offset
= 0;
993 isection
->output_section
= osection
;
994 isection
->output_offset
= 0;
998 void setup_new_section(bfd
*obfd
, struct supersect
*ss
)
1000 asection
*osection
= bfd_make_section_anyway(obfd
, ss
->name
);
1001 assert(osection
!= NULL
);
1002 bfd_set_section_flags(obfd
, osection
, ss
->flags
);
1004 osection
->userdata
= ss
;
1005 ss
->symbol
= osection
->symbol
;
1006 assert(bfd_set_section_size(obfd
, osection
, ss
->contents
.size
));
1007 assert(bfd_set_section_vma(obfd
, osection
, 0));
1010 assert(bfd_set_section_alignment(obfd
, osection
, ss
->alignment
));
1011 osection
->entsize
= 0;
1012 osection
->output_section
= osection
;
1013 osection
->output_offset
= 0;
1016 void write_section(bfd
*obfd
, asection
*osection
, void *arg
)
1018 struct supersect
*ss
= osection
->userdata
;
1020 if ((ss
->flags
& SEC_GROUP
) != 0 || ss
->contents
.size
== 0)
1024 char *error_message
;
1025 for (relocp
= ss
->new_relocs
.data
;
1026 relocp
< ss
->new_relocs
.data
+ ss
->new_relocs
.size
; relocp
++) {
1027 bfd_put(bfd_get_reloc_size((*relocp
)->howto
) * 8, obfd
, 0,
1028 ss
->contents
.data
+ (*relocp
)->address
);
1029 if (bfd_install_relocation(obfd
, *relocp
, ss
->contents
.data
,
1030 0, osection
, &error_message
) !=
1032 fprintf(stderr
, "ksplice: error installing reloc: %s",
1037 memcpy(vec_grow(&ss
->relocs
, ss
->new_relocs
.size
), ss
->new_relocs
.data
,
1038 ss
->new_relocs
.size
* sizeof(*ss
->new_relocs
.data
));
1040 bfd_set_reloc(obfd
, osection
,
1041 ss
->relocs
.size
== 0 ? NULL
: ss
->relocs
.data
,
1044 if (ss
->flags
& SEC_HAS_CONTENTS
)
1045 assert(bfd_set_section_contents
1046 (obfd
, osection
, ss
->contents
.data
, 0,
1047 ss
->contents
.size
));
1050 /* Modified function from GNU Binutils objcopy.c
1052 * Mark all the symbols which will be used in output relocations with
1053 * the BSF_KEEP flag so that those symbols will not be stripped.
1055 * Ignore relocations which will not appear in the output file.
1057 void mark_symbols_used_in_relocations(bfd
*abfd
, asection
*isection
,
1060 struct superbfd
*sbfd
= fetch_superbfd(abfd
);
1061 if (isection
->output_section
== NULL
)
1064 struct supersect
*ss
= fetch_supersect(sbfd
, isection
);
1065 ss_mark_symbols_used_in_relocations(ss
);
1068 void ss_mark_symbols_used_in_relocations(struct supersect
*ss
)
1070 /* Examine each symbol used in a relocation. If it's not one of the
1071 special bfd section symbols, then mark it with BSF_KEEP. */
1073 for (relocp
= ss
->relocs
.data
;
1074 relocp
< ss
->relocs
.data
+ ss
->relocs
.size
; relocp
++) {
1075 asymbol
*sym
= *(*relocp
)->sym_ptr_ptr
;
1076 if (!(bfd_is_const_section(sym
->section
) &&
1077 sym
== sym
->section
->symbol
))
1078 sym
->flags
|= BSF_KEEP
;
1082 /* Modified function from GNU Binutils objcopy.c
1084 * Choose which symbol entries to copy.
1085 * We don't copy in place, because that confuses the relocs.
1086 * Return the number of symbols to print.
1088 void filter_symbols(bfd
*ibfd
, bfd
*obfd
, struct asymbolp_vec
*osyms
,
1089 struct asymbolp_vec
*isyms
)
1092 for (symp
= isyms
->data
; symp
< isyms
->data
+ isyms
->size
; symp
++) {
1093 asymbol
*sym
= *symp
;
1097 if (mode("keep") && (sym
->flags
& BSF_GLOBAL
) != 0 &&
1098 !(mode("keep-primary") && str_in_set(sym
->name
, &newsyms
)))
1099 sym
->flags
= (sym
->flags
& ~BSF_GLOBAL
) | BSF_LOCAL
;
1101 if (mode("finalize") && (sym
->flags
& BSF_GLOBAL
) != 0)
1102 sym
->flags
= (sym
->flags
& ~BSF_GLOBAL
) | BSF_LOCAL
;
1104 if ((sym
->flags
& BSF_KEEP
) != 0 /* Used in relocation. */
1105 || ((sym
->flags
& BSF_SECTION_SYM
) != 0
1106 && ((*(sym
->section
)->symbol_ptr_ptr
)->flags
1109 else if ((sym
->flags
& (BSF_GLOBAL
| BSF_WEAK
)) != 0)
1111 else if (bfd_decode_symclass(sym
) == 'I')
1112 /* Global symbols in $idata sections need to be retained.
1113 External users of the library containing the $idata
1114 section may reference these symbols. */
1116 else if ((sym
->flags
& BSF_GLOBAL
) != 0
1117 || (sym
->flags
& BSF_WEAK
) != 0
1118 || bfd_is_com_section(sym
->section
))
1120 else if ((sym
->flags
& BSF_DEBUGGING
) != 0)
1123 keep
= !bfd_is_local_label(ibfd
, sym
);
1125 if (!want_section(sym
->section
))
1128 if (mode("rmsyms") && match_varargs(sym
->name
))
1132 *vec_grow(osyms
, 1) = sym
;
1136 int match_varargs(const char *str
)
1139 for (i
= 0; i
< varargs_count
; i
++) {
1140 if (strcmp(str
, varargs
[i
]) == 0)
1146 void read_str_set(struct str_vec
*strs
)
1150 assert(getline(&buf
, &n
, stdin
) >= 0);
1154 char *str
= strtok_r(buf
, " \n", &saveptr
);
1158 *vec_grow(strs
, 1) = str
;
1162 int str_in_set(const char *str
, const struct str_vec
*strs
)
1165 for (strp
= strs
->data
; strp
< strs
->data
+ strs
->size
; strp
++) {
1166 if (strcmp(str
, *strp
) == 0)
1172 int want_section(asection
*sect
)
1174 static const char *static_want
[] = {
1176 ".altinstr_replacement",
1178 ".parainstructions",
1185 if (mode("keep-primary") && bfd_is_abs_section(sect
))
1187 const struct wsect
*w
= wanted_sections
;
1188 for (; w
!= NULL
; w
= w
->next
) {
1189 if (w
->sect
== sect
)
1193 if (starts_with(sect
->name
, ".ksplice"))
1195 if (mode("keep-helper") && starts_with(sect
->name
, ".text"))
1197 if (mode("keep-helper") && starts_with(sect
->name
, ".exit.text")
1198 && bfd_get_section_by_name(sect
->owner
, ".exitcall.exit") == NULL
)
1200 if (mode("keep-primary") && starts_with(sect
->name
, "__ksymtab"))
1202 if (mode("keep-primary") && starts_with(sect
->name
, "__kcrctab"))
1204 if (mode("keep-primary") && str_in_set(sect
->name
, §ions
))
1208 for (i
= 0; static_want
[i
] != NULL
; i
++) {
1209 if (strcmp(sect
->name
, static_want
[i
]) == 0)
1215 const struct specsect
*is_special(asection
*sect
)
1217 const struct specsect
*ss
;
1218 for (ss
= special_sections
; ss
!= end_special_sections
; ss
++) {
1219 if (strcmp(ss
->sectname
, sect
->name
) == 0)