add_to_bundle should not add pack to ksplice_module_list.
[ksplice.git] / objmanip.c
blobb8848daad771496b4019eb034101a63b0173ded0
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
19 * 02110-1301, USA.
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:
29 * (1) keep mode
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
50 * later).
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.
99 #define _GNU_SOURCE
100 #include "objcommon.h"
101 #include "kmodsrc/ksplice.h"
102 #include <stdint.h>
103 #include <stdarg.h>
104 #include <stdlib.h>
105 #include <stdio.h>
106 #include <limits.h>
108 DECLARE_VEC_TYPE(const char *, str_vec);
110 struct wsect {
111 asection *sect;
112 struct wsect *next;
115 struct specsect {
116 const char *sectname;
117 int entry_size;
120 struct export_desc {
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,
134 void *looking_for);
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,
140 void *ignored);
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,
156 bfd_vma offset);
157 arelent *create_reloc(struct supersect *ss, const void *addr, asymbol **symp,
158 bfd_vma offset);
160 char **varargs;
161 int varargs_count;
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,
180 vec_init);
181 struct addr_vec_hash system_map;
183 void load_system_map()
185 const char *config_dir = getenv("KSPLICE_CONFIG_DIR");
186 assert(config_dir);
187 char *file;
188 assert(asprintf(&file, "%s/System.map", config_dir) >= 0);
189 FILE *fp = fopen(file, "r");
190 assert(fp);
191 addr_vec_hash_init(&system_map);
192 unsigned long addr;
193 char type;
194 char *sym;
195 while (fscanf(fp, "%lx %c %as\n", &addr, &type, &sym) == 3)
196 *vec_grow(addr_vec_hash_lookup(&system_map, sym, TRUE),
197 1) = addr;
198 fclose(fp);
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."))
205 return 1;
206 if (starts_with(isection->name, ".data.")) {
207 /* Ignore .data.percpu sections */
208 if (starts_with(isection->name, ".data.percpu"))
209 return 0;
210 return ss->relocs.size != 0;
212 return 0;
215 int main(int argc, char *argv[])
217 bfd_init();
218 bfd *ibfd = bfd_openr(argv[1], NULL);
219 assert(ibfd);
221 char **matching;
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);
226 assert(obfd);
228 struct superbfd *isbfd = fetch_superbfd(ibfd);
230 modestr = argv[3];
231 if (mode("keep")) {
232 kid = argv[4];
233 } else if (mode("rmsyms")) {
234 varargs = &argv[4];
235 varargs_count = argc - 4;
238 if (mode("keep")) {
239 read_str_set(&sections);
240 read_str_set(&newsects);
241 read_str_set(&delsects);
242 vec_init(&exports);
243 /* https://bugzilla.redhat.com/show_bug.cgi?id=431832 */
244 while (ungetc(getc(stdin), stdin) != EOF) {
245 char *sectname;
246 int ret = scanf("%as", &sectname);
247 if (ret == EOF)
248 break;
249 assert(ret == 1);
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 */
258 asection *sect;
259 for (sect = isbfd->abfd->sections; sect != NULL;
260 sect = sect->next) {
261 struct export_desc *ed;
262 if (!starts_with(sect->name, "__ksymtab") ||
263 ends_with(sect->name, "_strings"))
264 continue;
265 for (ed = exports.data;
266 ed < exports.data + exports.size; ed++) {
267 if (strcmp(ed->sectname, sect->name) == 0)
268 break;
270 if (ed < exports.data + exports.size)
271 continue;
272 ed = vec_grow(&exports, 1);
273 ed->sectname = sect->name;
274 vec_init(&ed->names);
278 if (mode("keep") || mode("rmsyms"))
279 load_system_map();
281 if (mode("keep")) {
282 while (1) {
283 const struct wsect *tmp = wanted_sections;
284 bfd_map_over_sections(ibfd, mark_wanted_if_referenced,
285 NULL);
286 if (tmp == wanted_sections)
287 break;
291 asymbol **symp;
292 for (symp = isbfd->syms.data;
293 mode("keep") && symp < isbfd->syms.data + isbfd->syms.size;
294 symp++) {
295 asymbol *sym = *symp;
296 if (!want_section(sym->section))
297 continue;
298 if ((sym->flags & BSF_WEAK) != 0)
299 continue;
300 if ((sym->flags & BSF_DEBUGGING) != 0)
301 continue;
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;
316 ed++) {
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;
323 symname++)
324 write_ksplice_export(isbfd, *symname,
325 export_type, 1);
326 } else {
327 rm_some_exports(isbfd, ed);
332 asection *p;
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"))
336 continue;
337 if (want_section(p) || mode("rmsyms"))
338 rm_some_relocs(ss);
341 const struct specsect *ss;
342 if (mode("keep")) {
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));
350 return EXIT_SUCCESS;
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,
362 export_crc_name);
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);
368 if (crc_ss != NULL)
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);
374 if (crc_ss != NULL)
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++) {
383 asymbol *sym;
384 read_reloc(&orig_ss, &orig_ksym->value,
385 sizeof(orig_ksym->value), &sym);
386 if (!str_in_set(sym->name, &ed->names))
387 continue;
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);
396 if (crc_ss != NULL)
397 sect_copy(crc_ss,
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);
408 arelent **relocp;
409 for (relocp = orig_relocs.data;
410 relocp < orig_relocs.data + orig_relocs.size; relocp++) {
411 int rm_reloc = 0;
412 asymbol *sym_ptr = *(*relocp)->sym_ptr_ptr;
414 if (mode("rmsyms") && match_varargs(sym_ptr->name))
415 rm_reloc = 1;
417 if (mode("keep"))
418 rm_reloc = 1;
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))
424 rm_reloc = 0;
426 if (mode("finalize") && bfd_is_und_section(sym_ptr->section))
427 rm_reloc = 1;
429 if (rm_reloc)
430 write_ksplice_reloc(ss, *relocp);
431 else
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);
439 if (sect != NULL)
440 return fetch_supersect(sbfd, sect);
441 else
442 return new_supersect(sbfd, name);
445 arelent *create_reloc(struct supersect *ss, const void *addr, asymbol **symp,
446 bfd_vma offset)
448 bfd_reloc_code_real_type code;
449 switch (bfd_arch_bits_per_address(ss->parent->abfd)) {
450 case 32:
451 code = BFD_RELOC_32;
452 break;
453 case 64:
454 code = BFD_RELOC_64;
455 break;
456 default:
457 DIE;
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;
465 return reloc;
468 void write_reloc(struct supersect *ss, const void *addr, asymbol **symp,
469 bfd_vma offset)
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, ...)
476 va_list ap;
477 va_start(ap, fmt);
478 int len = vsnprintf(NULL, 0, fmt, ap);
479 va_end(ap);
480 struct supersect *str_ss = make_section(ss->parent, ".ksplice_str");
481 char *buf = sect_grow(str_ss, len + 1, char);
482 va_start(ap, fmt);
483 vsnprintf(buf, len + 1, fmt, ap);
484 va_end(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)
495 return;
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;
501 addr++) {
502 if (*addr == *map_addr + offset)
503 break;
505 if (addr < addrs->data + addrs->size)
506 continue;
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;
516 vec_init(&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)) {
523 asymbol **gsymp;
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,
537 ".ksplice_array");
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);
543 } else {
544 *sym_addrs = NULL;
547 vec_free(&addrs);
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,
555 ".ksplice_symbols");
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;
563 } else {
564 asymbol *gsym = canonical_symbol(ss->parent, sym);
566 if (gsym == NULL)
567 ksymbol->name = NULL;
568 else
569 write_string(ksymbol_ss, &ksymbol->name, "%s",
570 gsym->name);
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,
593 mode("rmsyms") ?
594 ".ksplice_init_relocs" :
595 ".ksplice_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
633 char *buf = NULL;
634 size_t bufsize = 0;
635 FILE *fp = open_memstream(&buf, &bufsize);
636 bfd_print_symbol(sbfd->abfd, fp, sym, bfd_print_symbol_all);
637 fclose(fp);
638 assert(buf != NULL);
640 unsigned long symsize;
641 char *symname;
642 int len;
643 assert(sscanf(buf, "%*[^\t]\t%lx %as%n", &symsize, &symname, &len) >=
645 assert(buf[len] == '\0');
646 assert(strcmp(symname, sym->name) == 0);
647 free(symname);
648 free(buf);
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);
658 ksize->flags = 0;
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,
685 &sect->symbol, 0));
686 write_reloc(kpatch_ss, &kpatch->repladdr, &sect->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);
697 if (del) {
698 write_string(export_ss, &export->name, "%s", symname);
699 write_string(export_ss, &export->new_name,
700 "DISABLED_%s_%s", symname, kid);
701 } else {
702 write_string(export_ss, &export->new_name, "%s", symname);
703 write_string(export_ss, &export->name, "DISABLED_%s_%s",
704 symname, kid);
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)
712 return;
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)) {
721 asymbol *sym;
722 read_reloc(&orig_ss, orig_entry, sizeof(void *), &sym);
724 asection *p;
725 for (p = sbfd->abfd->sections; p != NULL; p = p->next) {
726 if (sym->section == p
727 && !is_special(p) && !want_section(p))
728 break;
730 if (p != NULL)
731 continue;
733 sect_copy(ss, sect_do_grow(ss, 1, s->entry_size,
734 1 << ss->alignment),
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))
742 return;
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")))
747 return;
749 if (mode("keep-helper")) {
750 struct superbfd *sbfd = fetch_superbfd(abfd);
751 asymbol **symp;
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));
758 w->sect = sect;
759 w->next = wanted_sections;
760 wanted_sections = w;
761 return;
766 bfd_map_over_sections(abfd, check_for_ref_to_section, sect);
769 void check_for_ref_to_section(bfd *abfd, asection *looking_at,
770 void *looking_for)
772 if (!want_section(looking_at) || is_special(looking_at))
773 return;
775 struct superbfd *sbfd = fetch_superbfd(abfd);
776 struct supersect *ss = fetch_supersect(sbfd, looking_at);
777 arelent **relocp;
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;
787 wanted_sections = w;
788 break;
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
827 section. */
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;
833 vec_init(&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));
847 return TRUE;
850 /* Modified function from GNU Binutils objcopy.c */
851 void setup_section(bfd *ibfd, asection *isection, void *obfdarg)
853 bfd *obfd = obfdarg;
854 bfd_vma vma;
856 if (!want_section(isection))
857 return;
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;
879 return;
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));
893 osection->lma = 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)
905 return;
907 arelent **relocp;
908 char *error_message;
909 for (relocp = ss->new_relocs.data;
910 relocp < ss->new_relocs.data + ss->new_relocs.size; relocp++) {
911 bfd_vma val;
912 if (bfd_get_arch(obfd) == bfd_arch_arm)
913 val = osection->use_rela_p ? 0 : (*relocp)->addend;
914 else
915 val = 0;
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) !=
920 bfd_reloc_ok) {
921 fprintf(stderr, "ksplice: error installing reloc: %s",
922 error_message);
923 DIE;
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,
931 ss->relocs.size);
933 if (ss->flags & SEC_HAS_CONTENTS)
934 assert(bfd_set_section_contents
935 (obfd, osection, ss->contents.data, 0,
936 ss->contents.size));
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,
947 void *ignored)
949 struct superbfd *sbfd = fetch_superbfd(abfd);
950 if (isection->output_section == NULL)
951 return;
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. */
961 arelent **relocp;
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)
980 asymbol **symp;
981 for (symp = isyms->data; symp < isyms->data + isyms->size; symp++) {
982 asymbol *sym = *symp;
984 int keep;
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
997 & BSF_KEEP) != 0))
998 keep = 1;
999 else if ((sym->flags & (BSF_GLOBAL | BSF_WEAK)) != 0)
1000 keep = 1;
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. */
1005 keep = 1;
1006 else if ((sym->flags & BSF_GLOBAL) != 0
1007 || (sym->flags & BSF_WEAK) != 0
1008 || bfd_is_com_section(sym->section))
1009 keep = 1;
1010 else if ((sym->flags & BSF_DEBUGGING) != 0)
1011 keep = 1;
1012 else
1013 keep = !bfd_is_local_label(ibfd, sym);
1015 if (!want_section(sym->section))
1016 keep = 0;
1018 if (mode("rmsyms") && match_varargs(sym->name))
1019 keep = 0;
1021 if (keep)
1022 *vec_grow(osyms, 1) = sym;
1026 int match_varargs(const char *str)
1028 int i;
1029 for (i = 0; i < varargs_count; i++) {
1030 if (strcmp(str, varargs[i]) == 0)
1031 return 1;
1033 return 0;
1036 void read_str_set(struct str_vec *strs)
1038 char *buf = NULL;
1039 size_t n = 0;
1040 assert(getline(&buf, &n, stdin) >= 0);
1041 vec_init(strs);
1042 char *saveptr;
1043 while (1) {
1044 char *str = strtok_r(buf, " \n", &saveptr);
1045 buf = NULL;
1046 if (str == NULL)
1047 break;
1048 *vec_grow(strs, 1) = str;
1052 int str_in_set(const char *str, const struct str_vec *strs)
1054 const char **strp;
1055 for (strp = strs->data; strp < strs->data + strs->size; strp++) {
1056 if (strcmp(str, *strp) == 0)
1057 return 1;
1059 return 0;
1062 int want_section(asection *sect)
1064 static const char *static_want[] = {
1065 ".altinstructions",
1066 ".altinstr_replacement",
1067 ".smp_locks",
1068 ".parainstructions",
1069 NULL
1072 if (!mode("keep"))
1073 return 1;
1075 if (mode("keep-primary") && bfd_is_abs_section(sect))
1076 return 1;
1077 const struct wsect *w = wanted_sections;
1078 for (; w != NULL; w = w->next) {
1079 if (w->sect == sect)
1080 return 1;
1083 if (starts_with(sect->name, ".ksplice"))
1084 return 1;
1085 if (mode("keep-helper") && starts_with(sect->name, ".text"))
1086 return 1;
1087 if (mode("keep-helper") && starts_with(sect->name, ".exit.text")
1088 && bfd_get_section_by_name(sect->owner, ".exitcall.exit") == NULL)
1089 return 1;
1090 if (mode("keep-primary") && starts_with(sect->name, "__ksymtab"))
1091 return 1;
1092 if (mode("keep-primary") && starts_with(sect->name, "__kcrctab"))
1093 return 1;
1094 if (mode("keep-primary") && str_in_set(sect->name, &sections))
1095 return 1;
1096 if (mode("keep-primary") && str_in_set(sect->name, &newsects))
1097 return 1;
1099 int i;
1100 for (i = 0; static_want[i] != NULL; i++) {
1101 if (strcmp(sect->name, static_want[i]) == 0)
1102 return 1;
1104 return 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)
1112 return ss;
1114 return NULL;