Move lookup_symbol_kallsyms and accumulate_matching_names.
[ksplice.git] / objmanip.c
blobeb04e46045f18de7a2cf140e08c2bbd27142a5aa
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 * two arguments are always an input object file and an output object file.
25 * - keep-primary: "objmanip <in.o> <out.o> keep-primary <kid>"
27 * This mode prepares the object file to be installed as a ksplice update.
28 * It takes as input on STDIN the output of the objdiff command. The kid
29 * argument is the ksplice id string for the ksplice update being built.
31 * - keep-helper: "objmanip <in.o> <out.o> keep-helper"
33 * This mode prepares the object file to be used for run-pre matching. This
34 * involves replacing all ELF relocations with ksplice relocations and
35 * writing ksplice_section structures for each ELF text or data section.
37 * - rmsyms mode: "objmanip <in.o> <out.o> rmsyms
39 * In this mode, any ELF relocations involving the list of symbol names given on
40 * standard input are replaced with ksplice relocations. This is used only
41 * for KSPLICE_STANDALONE.
43 * - finalize mode: "objmanip <in.o> <out.o> finalize"
45 * In this mode, any ELF relocations to undefined symbols are replaced with
46 * ksplice relocations.
49 /* Always define KSPLICE_STANDALONE, even if you're using integrated Ksplice.
50 objmanip won't compile without it. */
51 #define KSPLICE_STANDALONE
53 #define _GNU_SOURCE
54 #include "objcommon.h"
55 #include "kmodsrc/ksplice.h"
56 #include <stdint.h>
57 #include <stdarg.h>
58 #include <stdlib.h>
59 #include <stdio.h>
60 #include <limits.h>
62 DECLARE_VEC_TYPE(const char *, str_vec);
64 struct wsect {
65 asection *sect;
66 struct wsect *next;
69 struct table_section {
70 const char *sectname;
71 int entry_size;
74 struct export_desc {
75 const char *sectname;
76 struct str_vec names;
78 DECLARE_VEC_TYPE(struct export_desc, export_desc_vec);
80 #define bool_init(b) *(b) = false
81 DEFINE_HASH_TYPE(bool, bool_hash, bool_hash_init, bool_hash_free,
82 bool_hash_lookup, bool_init);
84 void rm_some_relocs(struct supersect *ss);
85 void write_ksplice_reloc(struct supersect *ss, arelent *orig_reloc);
86 void blot_section(struct supersect *ss, int offset, reloc_howto_type *howto);
87 void write_ksplice_section(struct superbfd *sbfd, asymbol **symp);
88 void write_ksplice_patch(struct superbfd *sbfd, const char *sectname);
89 void write_ksplice_deleted_patch(struct superbfd *sbfd, const char *label);
90 void filter_table_section(struct superbfd *sbfd, const struct table_section *s);
91 void filter_ex_table_section(struct superbfd *sbfd);
92 void mark_wanted_if_referenced(bfd *abfd, asection *sect, void *ignored);
93 void check_for_ref_to_section(bfd *abfd, asection *looking_at,
94 void *looking_for);
95 bfd_boolean copy_object(bfd *ibfd, bfd *obfd);
96 void setup_section(bfd *ibfd, asection *isection, void *obfdarg);
97 static void setup_new_section(bfd *obfd, struct supersect *ss);
98 static void write_section(bfd *obfd, asection *osection, void *arg);
99 void mark_symbols_used_in_relocations(bfd *abfd, asection *isection,
100 void *ignored);
101 static void ss_mark_symbols_used_in_relocations(struct supersect *ss);
102 void filter_symbols(bfd *ibfd, bfd *obfd, struct asymbolp_vec *osyms,
103 struct asymbolp_vec *isyms);
104 static bool deleted_table_section_symbol(bfd *abfd, asymbol *sym);
105 void read_str_set(struct str_vec *strs);
106 bool str_in_set(const char *str, const struct str_vec *strs);
107 bool want_section(asection *sect);
108 bool is_table_section(asection *sect);
109 struct supersect *make_section(struct superbfd *sbfd, const char *name);
110 void __attribute__((format(printf, 3, 4)))
111 write_string(struct supersect *ss, const char **addr, const char *fmt, ...);
112 void rm_some_exports(struct superbfd *isbfd, const struct export_desc *ed);
113 void write_ksplice_export(struct superbfd *sbfd, const char *symname,
114 const char *export_type, bool del);
115 void write_reloc(struct supersect *ss, const void *addr, asymbol **symp,
116 bfd_vma offset);
117 arelent *create_reloc(struct supersect *ss, const void *addr, asymbol **symp,
118 bfd_vma offset);
120 struct str_vec sections, newsects, delsects, rmsyms;
121 struct export_desc_vec exports;
123 const char *modestr, *kid;
125 struct wsect *wanted_sections = NULL;
127 const struct table_section table_sections[] = {
128 {".altinstructions", 2 * sizeof(void *) + 4},
129 {".smp_locks", sizeof(void *)},
130 {".parainstructions", sizeof(void *) + 4},
131 }, *const end_table_sections = *(&table_sections + 1);
133 #define mode(str) starts_with(modestr, str)
135 DECLARE_VEC_TYPE(unsigned long, addr_vec);
136 DEFINE_HASH_TYPE(struct addr_vec, addr_vec_hash,
137 addr_vec_hash_init, addr_vec_hash_free, addr_vec_hash_lookup,
138 vec_init);
139 struct addr_vec_hash system_map;
141 struct bool_hash system_map_written;
143 void load_system_map()
145 const char *config_dir = getenv("KSPLICE_CONFIG_DIR");
146 assert(config_dir);
147 char *file;
148 assert(asprintf(&file, "%s/System.map", config_dir) >= 0);
149 FILE *fp = fopen(file, "r");
150 assert(fp);
151 addr_vec_hash_init(&system_map);
152 unsigned long addr;
153 char type;
154 char *sym;
155 while (fscanf(fp, "%lx %c %as\n", &addr, &type, &sym) == 3)
156 *vec_grow(addr_vec_hash_lookup(&system_map, sym, TRUE),
157 1) = addr;
158 fclose(fp);
161 bool needed_data_section(struct superbfd *sbfd, asection *isection)
163 struct supersect *ss = fetch_supersect(sbfd, isection);
164 if (starts_with(isection->name, ".rodata"))
165 return true;
166 if (starts_with(isection->name, ".data")) {
167 /* Ignore .data.percpu sections */
168 if (starts_with(isection->name, ".data.percpu"))
169 return false;
170 return ss->relocs.size != 0;
172 return false;
175 int main(int argc, char *argv[])
177 bfd_init();
178 bfd *ibfd = bfd_openr(argv[1], NULL);
179 assert(ibfd);
181 char **matching;
182 assert(bfd_check_format_matches(ibfd, bfd_object, &matching));
184 const char *output_target = bfd_get_target(ibfd);
185 bfd *obfd = bfd_openw(argv[2], output_target);
186 assert(obfd);
188 struct superbfd *isbfd = fetch_superbfd(ibfd);
190 bool_hash_init(&system_map_written);
192 modestr = argv[3];
193 if (mode("keep-primary"))
194 kid = argv[4];
196 if (mode("keep-primary")) {
197 read_label_map(isbfd);
198 read_str_set(&sections);
199 read_str_set(&newsects);
200 read_str_set(&delsects);
201 vec_init(&exports);
202 /* https://bugzilla.redhat.com/show_bug.cgi?id=431832 */
203 while (ungetc(getc(stdin), stdin) != EOF) {
204 char *sectname;
205 int ret = scanf("%as", &sectname);
206 if (ret == EOF)
207 break;
208 assert(ret == 1);
209 struct export_desc *ed = vec_grow(&exports, 1);
210 ed->sectname = sectname;
211 read_str_set(&ed->names);
213 } else if (mode("rmsyms")) {
214 read_str_set(&rmsyms);
217 if (mode("keep-primary")) {
218 /* Create export_desc structures for all export sections */
219 asection *sect;
220 for (sect = isbfd->abfd->sections; sect != NULL;
221 sect = sect->next) {
222 struct export_desc *ed;
223 if (!starts_with(sect->name, "__ksymtab") ||
224 ends_with(sect->name, "_strings"))
225 continue;
226 for (ed = exports.data;
227 ed < exports.data + exports.size; ed++) {
228 if (strcmp(ed->sectname, sect->name) == 0)
229 break;
231 if (ed < exports.data + exports.size)
232 continue;
233 ed = vec_grow(&exports, 1);
234 ed->sectname = sect->name;
235 vec_init(&ed->names);
239 if (mode("keep") || mode("rmsyms"))
240 load_system_map();
242 if (mode("keep")) {
243 while (1) {
244 const struct wsect *tmp = wanted_sections;
245 bfd_map_over_sections(ibfd, mark_wanted_if_referenced,
246 NULL);
247 if (tmp == wanted_sections)
248 break;
251 asection *sect;
252 for (sect = ibfd->sections; sect != NULL; sect = sect->next) {
253 asymbol **symp = canonical_symbolp(isbfd, sect->symbol);
254 if (symp == NULL)
255 continue;
256 asymbol *sym = *symp;
257 if (!want_section(sect))
258 continue;
259 if (starts_with(sect->name, ".rodata.str"))
260 continue;
261 if ((sym->flags & BSF_WEAK) != 0)
262 continue;
263 if ((sym->flags & BSF_FUNCTION) != 0 ||
264 needed_data_section(isbfd, sect))
265 write_ksplice_section(isbfd, symp);
269 if (mode("keep-primary")) {
270 asection *sect;
271 for (sect = isbfd->abfd->sections; sect != NULL;
272 sect = sect->next) {
273 if (str_in_set(sect->name, &sections) ||
274 (starts_with(sect->name, ".text") &&
275 want_section(sect) &&
276 !str_in_set(sect->name, &newsects)))
277 write_ksplice_patch(isbfd, sect->name);
280 const char **label;
281 for (label = delsects.data;
282 label < delsects.data + delsects.size; label++)
283 write_ksplice_deleted_patch(isbfd, *label);
285 const struct export_desc *ed;
286 for (ed = exports.data; ed < exports.data + exports.size;
287 ed++) {
288 if (starts_with(ed->sectname, "del___ksymtab")) {
289 const char *export_type =
290 ed->sectname + strlen("del___ksymtab");
291 const char **symname;
292 for (symname = ed->names.data;
293 symname < ed->names.data + ed->names.size;
294 symname++)
295 write_ksplice_export(isbfd, *symname,
296 export_type, true);
297 } else {
298 rm_some_exports(isbfd, ed);
303 asection *p;
304 for (p = ibfd->sections; p != NULL; p = p->next) {
305 struct supersect *ss = fetch_supersect(isbfd, p);
306 if (is_table_section(p) || starts_with(p->name, ".ksplice") ||
307 strcmp(p->name, ".fixup") == 0)
308 continue;
309 if (want_section(p) || mode("rmsyms"))
310 rm_some_relocs(ss);
313 const struct table_section *ss;
314 if (mode("keep")) {
315 for (ss = table_sections; ss != end_table_sections; ss++)
316 filter_table_section(isbfd, ss);
317 filter_ex_table_section(isbfd);
320 copy_object(ibfd, obfd);
321 assert(bfd_close(obfd));
322 assert(bfd_close(ibfd));
323 return EXIT_SUCCESS;
326 void rm_some_exports(struct superbfd *isbfd, const struct export_desc *ed)
328 assert(starts_with(ed->sectname, "__ksymtab"));
329 const char *export_type = ed->sectname + strlen("__ksymtab");
330 asection *sym_sect = bfd_get_section_by_name(isbfd->abfd, ed->sectname);
331 assert(sym_sect != NULL);
332 char *export_crc_name;
333 assert(asprintf(&export_crc_name, "__kcrctab%s", export_type) >= 0);
334 asection *crc_sect = bfd_get_section_by_name(isbfd->abfd,
335 export_crc_name);
336 struct supersect *ss, *crc_ss = NULL;
337 ss = fetch_supersect(isbfd, sym_sect);
338 if (crc_sect != NULL)
339 crc_ss = fetch_supersect(isbfd, crc_sect);
341 if (crc_ss != NULL)
342 assert(ss->contents.size * sizeof(unsigned long) ==
343 crc_ss->contents.size * sizeof(struct kernel_symbol));
345 struct supersect orig_ss, orig_crc_ss;
346 supersect_move(&orig_ss, ss);
347 if (crc_ss != NULL)
348 supersect_move(&orig_crc_ss, crc_ss);
350 struct kernel_symbol *orig_ksym;
351 unsigned long *orig_crc;
352 for (orig_ksym = orig_ss.contents.data,
353 orig_crc = orig_crc_ss.contents.data;
354 (void *)orig_ksym < orig_ss.contents.data + orig_ss.contents.size;
355 orig_ksym++, orig_crc++) {
356 asymbol *sym;
357 read_reloc(&orig_ss, &orig_ksym->value,
358 sizeof(orig_ksym->value), &sym);
359 if (!str_in_set(sym->name, &ed->names))
360 continue;
362 struct kernel_symbol *ksym = sect_grow(ss, 1, typeof(*ksym));
363 sect_copy(ss, &ksym->value, &orig_ss, &orig_ksym->value, 1);
364 /* Replace name with a mangled name */
365 write_ksplice_export(ss->parent, sym->name, export_type, false);
366 write_string(ss, (const char **)&ksym->name,
367 "DISABLED_%s_%s", sym->name, kid);
369 if (crc_ss != NULL)
370 sect_copy(crc_ss,
371 sect_grow(crc_ss, 1, typeof(*orig_crc)),
372 &orig_crc_ss, orig_crc, 1);
376 void rm_some_relocs(struct supersect *ss)
378 struct arelentp_vec orig_relocs;
379 vec_move(&orig_relocs, &ss->relocs);
381 arelent **relocp;
382 for (relocp = orig_relocs.data;
383 relocp < orig_relocs.data + orig_relocs.size; relocp++) {
384 bool rm_reloc = false;
385 asymbol *sym_ptr = *(*relocp)->sym_ptr_ptr;
387 if (mode("rmsyms") && str_in_set(sym_ptr->name, &rmsyms))
388 rm_reloc = true;
390 if (mode("keep"))
391 rm_reloc = true;
393 if (mode("keep-primary") && want_section(sym_ptr->section) &&
394 (str_in_set(sym_ptr->section->name, &newsects) ||
395 bfd_is_const_section(sym_ptr->section) ||
396 starts_with(sym_ptr->section->name, ".rodata.str")))
397 rm_reloc = false;
399 if (mode("finalize") && bfd_is_und_section(sym_ptr->section))
400 rm_reloc = true;
402 if (rm_reloc)
403 write_ksplice_reloc(ss, *relocp);
404 else
405 *vec_grow(&ss->relocs, 1) = *relocp;
409 struct supersect *make_section(struct superbfd *sbfd, const char *name)
411 asection *sect = bfd_get_section_by_name(sbfd->abfd, name);
412 if (sect != NULL)
413 return fetch_supersect(sbfd, sect);
414 else
415 return new_supersect(sbfd, name);
418 arelent *create_reloc(struct supersect *ss, const void *addr, asymbol **symp,
419 bfd_vma offset)
421 bfd_reloc_code_real_type code;
422 switch (bfd_arch_bits_per_address(ss->parent->abfd)) {
423 case 32:
424 code = BFD_RELOC_32;
425 break;
426 case 64:
427 code = BFD_RELOC_64;
428 break;
429 default:
430 DIE;
433 arelent *reloc = malloc(sizeof(*reloc));
434 reloc->sym_ptr_ptr = symp;
435 reloc->address = addr - ss->contents.data;
436 reloc->howto = bfd_reloc_type_lookup(ss->parent->abfd, code);
437 reloc->addend = offset;
438 return reloc;
441 void write_reloc(struct supersect *ss, const void *addr, asymbol **symp,
442 bfd_vma offset)
444 arelent *new_reloc = create_reloc(ss, addr, symp, offset), **relocp;
445 for (relocp = ss->relocs.data;
446 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
447 if ((*relocp)->address == new_reloc->address) {
448 memmove(relocp,
449 relocp + 1,
450 (void *)(ss->relocs.data + ss->relocs.size) -
451 (void *)(relocp + 1));
452 ss->relocs.size--;
453 relocp--;
456 *vec_grow(&ss->new_relocs, 1) = new_reloc;
459 void write_string(struct supersect *ss, const char **addr, const char *fmt, ...)
461 va_list ap;
462 va_start(ap, fmt);
463 int len = vsnprintf(NULL, 0, fmt, ap);
464 va_end(ap);
465 struct supersect *str_ss = make_section(ss->parent, ".ksplice_str");
466 char *buf = sect_grow(str_ss, len + 1, char);
467 va_start(ap, fmt);
468 vsnprintf(buf, len + 1, fmt, ap);
469 va_end(ap);
471 write_reloc(ss, addr, &str_ss->symbol,
472 (void *)buf - str_ss->contents.data);
475 void lookup_system_map(struct addr_vec *addrs, const char *name, long offset)
477 struct addr_vec *map_addrs =
478 addr_vec_hash_lookup(&system_map, name, FALSE);
479 if (map_addrs == NULL)
480 return;
482 unsigned long *addr, *map_addr;
483 for (map_addr = map_addrs->data;
484 map_addr < map_addrs->data + map_addrs->size; map_addr++) {
485 for (addr = addrs->data; addr < addrs->data + addrs->size;
486 addr++) {
487 if (*addr == *map_addr + offset)
488 break;
490 if (addr < addrs->data + addrs->size)
491 continue;
492 *vec_grow(addrs, 1) = *map_addr + offset;
496 void write_system_map_array(struct superbfd *sbfd, struct supersect *ss,
497 const unsigned long **sym_addrs,
498 unsigned long *num_sym_addrs, asymbol *sym)
500 struct addr_vec addrs;
501 vec_init(&addrs);
503 if (bfd_is_abs_section(sym->section)) {
504 *vec_grow(&addrs, 1) = sym->value;
505 } else if (bfd_is_und_section(sym->section)) {
506 lookup_system_map(&addrs, sym->name, 0);
507 } else if (!bfd_is_const_section(sym->section)) {
508 asymbol **gsymp;
509 for (gsymp = sbfd->syms.data;
510 gsymp < sbfd->syms.data + sbfd->syms.size; gsymp++) {
511 asymbol *gsym = *gsymp;
512 if ((gsym->flags & BSF_DEBUGGING) == 0 &&
513 gsym->section == sym->section)
514 lookup_system_map(&addrs, gsym->name,
515 sym->value - gsym->value);
519 *num_sym_addrs = addrs.size;
520 if (addrs.size != 0) {
521 struct supersect *array_ss = make_section(sbfd,
522 ".ksplice_array");
523 void *buf = sect_grow(array_ss, addrs.size,
524 typeof(*addrs.data));
525 memcpy(buf, addrs.data, addrs.size * sizeof(*addrs.data));
526 write_reloc(ss, sym_addrs, &array_ss->symbol,
527 buf - array_ss->contents.data);
528 } else {
529 *sym_addrs = NULL;
532 vec_free(&addrs);
535 void write_ksplice_system_map(struct superbfd *sbfd, asymbol *sym,
536 const char *addstr_sect)
538 struct supersect *smap_ss = make_section(sbfd, ".ksplice_system_map");
539 struct ksplice_system_map *smap;
540 const char *label = label_lookup(sbfd, sym);
542 bool *done = bool_hash_lookup(&system_map_written, label, TRUE);
543 if (*done)
544 return;
545 *done = true;
547 smap = sect_grow(smap_ss, 1, struct ksplice_system_map);
549 write_system_map_array(sbfd, smap_ss, &smap->candidates,
550 &smap->nr_candidates, sym);
551 write_string(smap_ss, &smap->label, "%s%s", label, addstr_sect);
554 void write_ksplice_symbol(struct supersect *ss,
555 const struct ksplice_symbol *const *addr,
556 asymbol *sym, const char *addstr_sect)
558 struct supersect *ksymbol_ss = make_section(ss->parent,
559 ".ksplice_symbols");
560 struct ksplice_symbol *ksymbol = sect_grow(ksymbol_ss, 1,
561 struct ksplice_symbol);
563 if (bfd_is_und_section(sym->section) || (sym->flags & BSF_GLOBAL) != 0) {
564 write_string(ksymbol_ss, &ksymbol->name, "%s", sym->name);
565 } else if (bfd_is_const_section(sym->section)) {
566 ksymbol->name = NULL;
567 } else {
568 asymbol *gsym = canonical_symbol(ss->parent, sym);
570 if (gsym == NULL)
571 ksymbol->name = NULL;
572 else
573 write_string(ksymbol_ss, &ksymbol->name, "%s",
574 gsym->name);
577 write_string(ksymbol_ss, &ksymbol->label, "%s%s",
578 label_lookup(ss->parent, sym), addstr_sect);
580 write_ksplice_system_map(ksymbol_ss->parent, sym, addstr_sect);
582 write_reloc(ss, addr, &ksymbol_ss->symbol,
583 (void *)ksymbol - ksymbol_ss->contents.data);
586 void write_ksplice_reloc(struct supersect *ss, arelent *orig_reloc)
588 asymbol *sym_ptr = *orig_reloc->sym_ptr_ptr;
590 reloc_howto_type *howto = orig_reloc->howto;
592 bfd_vma addend = get_reloc_offset(ss, orig_reloc, false);
593 blot_section(ss, orig_reloc->address, howto);
595 struct supersect *kreloc_ss = make_section(ss->parent,
596 mode("rmsyms") ?
597 ".ksplice_init_relocs" :
598 ".ksplice_relocs");
599 struct ksplice_reloc *kreloc = sect_grow(kreloc_ss, 1,
600 struct ksplice_reloc);
602 write_reloc(kreloc_ss, &kreloc->blank_addr,
603 &ss->symbol, orig_reloc->address);
604 kreloc->blank_offset = (unsigned long)orig_reloc->address;
605 write_ksplice_symbol(kreloc_ss, &kreloc->symbol, sym_ptr, "");
606 kreloc->pcrel = howto->pc_relative;
607 kreloc->addend = addend;
608 kreloc->size = bfd_get_reloc_size(howto);
609 kreloc->dst_mask = howto->dst_mask;
610 kreloc->rightshift = howto->rightshift;
611 kreloc->signed_addend =
612 (howto->complain_on_overflow == complain_overflow_signed) ||
613 (howto->complain_on_overflow == complain_overflow_bitfield);
616 #define CANARY(x, canary) ((x & ~howto->dst_mask) | (canary & howto->dst_mask))
618 void blot_section(struct supersect *ss, int offset, reloc_howto_type *howto)
620 int bits = bfd_get_reloc_size(howto) * 8;
621 void *address = ss->contents.data + offset;
622 bfd_vma x = bfd_get(bits, ss->parent->abfd, address);
623 x = (x & ~howto->dst_mask) |
624 ((bfd_vma)KSPLICE_CANARY & howto->dst_mask);
625 bfd_put(bits, ss->parent->abfd, x, address);
628 void write_ksplice_section(struct superbfd *sbfd, asymbol **symp)
630 asymbol *sym = *symp;
631 struct supersect *ksect_ss = make_section(sbfd, ".ksplice_sections");
632 struct ksplice_section *ksect = sect_grow(ksect_ss, 1,
633 struct ksplice_section);
635 write_ksplice_symbol(ksect_ss, &ksect->symbol, sym,
636 mode("keep-primary") ? "(post)" : "");
637 ksect->size = bfd_get_section_size(sym->section);
638 ksect->flags = 0;
639 if (starts_with(sym->section->name, ".rodata"))
640 ksect->flags |= KSPLICE_SECTION_RODATA;
641 if (starts_with(sym->section->name, ".data"))
642 ksect->flags |= KSPLICE_SECTION_DATA;
643 if (starts_with(sym->section->name, ".text") ||
644 starts_with(sym->section->name, ".exit.text"))
645 ksect->flags |= KSPLICE_SECTION_TEXT;
646 assert(ksect->flags != 0);
647 write_reloc(ksect_ss, &ksect->thismod_addr, symp, 0);
650 void write_ksplice_patch(struct superbfd *sbfd, const char *sectname)
652 struct supersect *kpatch_ss = make_section(sbfd, ".ksplice_patches");
653 struct ksplice_patch *kpatch = sect_grow(kpatch_ss, 1,
654 struct ksplice_patch);
655 asection *sect = bfd_get_section_by_name(sbfd->abfd, sectname);
656 assert(sect != NULL);
658 write_string(kpatch_ss, &kpatch->label, "%s",
659 label_lookup(sbfd, sect->symbol));
660 write_reloc(kpatch_ss, &kpatch->trampoline.repladdr, &sect->symbol, 0);
663 void write_ksplice_deleted_patch(struct superbfd *sbfd, const char *label)
665 struct supersect *kpatch_ss = make_section(sbfd, ".ksplice_patches");
666 struct ksplice_patch *kpatch = sect_grow(kpatch_ss, 1,
667 struct ksplice_patch);
669 write_string(kpatch_ss, &kpatch->label, "%s", label);
670 kpatch->trampoline.repladdr = 0;
673 void write_ksplice_export(struct superbfd *sbfd, const char *symname,
674 const char *export_type, bool del)
676 struct supersect *export_ss = make_section(sbfd, ".ksplice_exports");
677 struct ksplice_export *exp = sect_grow(export_ss, 1,
678 struct ksplice_export);
680 if (del) {
681 write_string(export_ss, &exp->name, "%s", symname);
682 write_string(export_ss, &exp->new_name, "DISABLED_%s_%s",
683 symname, kid);
684 } else {
685 write_string(export_ss, &exp->new_name, "%s", symname);
686 write_string(export_ss, &exp->name, "DISABLED_%s_%s", symname,
687 kid);
691 void filter_table_section(struct superbfd *sbfd, const struct table_section *s)
693 asection *isection = bfd_get_section_by_name(sbfd->abfd, s->sectname);
694 if (isection == NULL)
695 return;
697 struct supersect *ss = fetch_supersect(sbfd, isection), orig_ss;
698 supersect_move(&orig_ss, ss);
700 const void *orig_entry;
701 for (orig_entry = orig_ss.contents.data;
702 orig_entry < orig_ss.contents.data + orig_ss.contents.size;
703 orig_entry += align(s->entry_size, 1 << ss->alignment)) {
704 asymbol *sym;
705 read_reloc(&orig_ss, orig_entry, sizeof(void *), &sym);
707 asection *p;
708 for (p = sbfd->abfd->sections; p != NULL; p = p->next) {
709 if (sym->section == p
710 && !is_table_section(p) && !want_section(p))
711 break;
713 if (p != NULL)
714 continue;
716 sect_copy(ss, sect_do_grow(ss, 1, s->entry_size,
717 1 << ss->alignment),
718 &orig_ss, orig_entry, s->entry_size);
722 struct fixup_entry {
723 bfd_vma offset;
724 bool used;
725 bfd_vma ex_offset;
727 DECLARE_VEC_TYPE(struct fixup_entry, fixup_entry_vec);
729 int compare_fixups(const void *aptr, const void *bptr)
731 const struct fixup_entry *a = aptr, *b = bptr;
732 if (a->offset < b->offset)
733 return -1;
734 else if (a->offset > b->offset)
735 return 1;
736 else
737 return (int)a->used - (int)b->used;
740 void filter_ex_table_section(struct superbfd *sbfd)
742 asection *isection = bfd_get_section_by_name(sbfd->abfd, "__ex_table");
743 if (isection == NULL)
744 return;
745 asection *fixup_sect = bfd_get_section_by_name(sbfd->abfd, ".fixup");
747 struct supersect *ss = fetch_supersect(sbfd, isection), orig_ss;
748 supersect_move(&orig_ss, ss);
750 struct supersect *fixup_ss = NULL;
751 if (fixup_sect != NULL)
752 fixup_ss = fetch_supersect(sbfd, fixup_sect);
754 struct fixup_entry_vec fixups;
755 vec_init(&fixups);
757 const struct exception_table_entry *orig_entry;
758 for (orig_entry = orig_ss.contents.data;
759 (void *)orig_entry < orig_ss.contents.data + orig_ss.contents.size;
760 orig_entry++) {
761 asymbol *sym, *fixup_sym;
762 read_reloc(&orig_ss, &orig_entry->insn,
763 sizeof(orig_entry->insn), &sym);
765 struct fixup_entry *f;
766 bfd_vma fixup_offset = read_reloc(&orig_ss, &orig_entry->fixup,
767 sizeof(orig_entry->fixup),
768 &fixup_sym);
769 if (fixup_sym->section == fixup_sect) {
770 assert(fixup_offset < fixup_ss->contents.size);
771 f = vec_grow(&fixups, 1);
772 f->offset = fixup_offset;
773 f->used = false;
776 asection *p;
777 for (p = sbfd->abfd->sections; p != NULL; p = p->next) {
778 if (sym->section == p
779 && !is_table_section(p) && !want_section(p))
780 break;
782 if (p != NULL)
783 continue;
785 if (fixup_sym->section == fixup_sect) {
786 f->used = true;
787 f->ex_offset = ss->contents.size;
789 sect_copy(ss, sect_grow(ss, 1, struct exception_table_entry),
790 &orig_ss, orig_entry, 1);
793 if (fixup_sect == NULL)
794 return;
796 struct supersect orig_fixup_ss;
797 supersect_move(&orig_fixup_ss, fixup_ss);
799 qsort(fixups.data, fixups.size, sizeof(*fixups.data), compare_fixups);
800 *vec_grow(&fixups, 1) = (struct fixup_entry)
801 { .offset = orig_fixup_ss.contents.size, .used = false };
803 struct fixup_entry *f;
804 for (f = fixups.data; f < fixups.data + fixups.size - 1; f++) {
805 if (!f->used)
806 continue;
807 write_reloc(ss, ss->contents.data + f->ex_offset,
808 &fixup_ss->symbol, fixup_ss->contents.size);
809 sect_copy(fixup_ss,
810 sect_grow(fixup_ss, (f + 1)->offset - f->offset,
811 unsigned char),
812 &orig_fixup_ss,
813 orig_fixup_ss.contents.data + f->offset,
814 (f + 1)->offset - f->offset);
818 void mark_wanted_if_referenced(bfd *abfd, asection *sect, void *ignored)
820 if (want_section(sect))
821 return;
822 if (!starts_with(sect->name, ".text")
823 && !starts_with(sect->name, ".exit.text")
824 && !starts_with(sect->name, ".rodata")
825 && !(starts_with(sect->name, ".data") && mode("keep-helper")))
826 return;
828 if (mode("keep-helper")) {
829 struct superbfd *sbfd = fetch_superbfd(abfd);
830 asymbol **symp;
831 for (symp = sbfd->syms.data;
832 symp < sbfd->syms.data + sbfd->syms.size; symp++) {
833 asymbol *sym = *symp;
834 if (sym->section == sect &&
835 (sym->flags & BSF_GLOBAL) != 0) {
836 struct wsect *w = malloc(sizeof(*w));
837 w->sect = sect;
838 w->next = wanted_sections;
839 wanted_sections = w;
840 return;
845 bfd_map_over_sections(abfd, check_for_ref_to_section, sect);
848 void check_for_ref_to_section(bfd *abfd, asection *looking_at,
849 void *looking_for)
851 if (!want_section(looking_at) || is_table_section(looking_at))
852 return;
854 struct superbfd *sbfd = fetch_superbfd(abfd);
855 struct supersect *ss = fetch_supersect(sbfd, looking_at);
856 arelent **relocp;
857 for (relocp = ss->relocs.data;
858 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
859 asymbol *sym = *(*relocp)->sym_ptr_ptr;
860 if (sym->section == (asection *)looking_for &&
861 (!starts_with(sym->section->name, ".text") ||
862 (get_reloc_offset(ss, *relocp, true) != 0 &&
863 strcmp(looking_at->name, ".fixup") != 0))) {
864 struct wsect *w = malloc(sizeof(*w));
865 w->sect = looking_for;
866 w->next = wanted_sections;
867 wanted_sections = w;
868 break;
873 /* Modified function from GNU Binutils objcopy.c */
874 bfd_boolean copy_object(bfd *ibfd, bfd *obfd)
876 assert(bfd_set_format(obfd, bfd_get_format(ibfd)));
878 bfd_vma start = bfd_get_start_address(ibfd);
880 flagword flags = bfd_get_file_flags(ibfd);
881 flags &= bfd_applicable_file_flags(obfd);
883 assert(bfd_set_start_address(obfd, start)
884 && bfd_set_file_flags(obfd, flags));
886 enum bfd_architecture iarch = bfd_get_arch(ibfd);
887 unsigned int imach = bfd_get_mach(ibfd);
888 assert(bfd_set_arch_mach(obfd, iarch, imach));
889 assert(bfd_set_format(obfd, bfd_get_format(ibfd)));
891 /* BFD mandates that all output sections be created and sizes set before
892 any output is done. Thus, we traverse all sections multiple times. */
893 bfd_map_over_sections(ibfd, setup_section, obfd);
895 struct supersect *new_supersects = fetch_superbfd(ibfd)->new_supersects;
896 struct supersect *ss;
897 for (ss = new_supersects; ss != NULL; ss = ss->next)
898 setup_new_section(obfd, ss);
900 /* Mark symbols used in output relocations so that they
901 are kept, even if they are local labels or static symbols.
903 Note we iterate over the input sections examining their
904 relocations since the relocations for the output sections
905 haven't been set yet. mark_symbols_used_in_relocations will
906 ignore input sections which have no corresponding output
907 section. */
909 bfd_map_over_sections(ibfd, mark_symbols_used_in_relocations, NULL);
910 for (ss = new_supersects; ss != NULL; ss = ss->next)
911 ss_mark_symbols_used_in_relocations(ss);
912 struct asymbolp_vec osyms;
913 vec_init(&osyms);
914 filter_symbols(ibfd, obfd, &osyms, &fetch_superbfd(ibfd)->syms);
916 bfd_set_symtab(obfd, osyms.data, osyms.size);
918 /* This has to happen after the symbol table has been set. */
919 bfd_map_over_sections(obfd, write_section, NULL);
921 /* Allow the BFD backend to copy any private data it understands
922 from the input BFD to the output BFD. This is done last to
923 permit the routine to look at the filtered symbol table, which is
924 important for the ECOFF code at least. */
925 assert(bfd_copy_private_bfd_data(ibfd, obfd));
927 return TRUE;
930 /* Modified function from GNU Binutils objcopy.c */
931 void setup_section(bfd *ibfd, asection *isection, void *obfdarg)
933 bfd *obfd = obfdarg;
934 bfd_vma vma;
936 if (!want_section(isection))
937 return;
939 asection *osection = bfd_make_section_anyway(obfd, isection->name);
940 assert(osection != NULL);
942 struct superbfd *isbfd = fetch_superbfd(ibfd);
943 struct supersect *ss = fetch_supersect(isbfd, isection);
944 osection->userdata = ss;
945 bfd_set_section_flags(obfd, osection, ss->flags);
946 ss->symbol = osection->symbol;
947 assert(bfd_set_section_size(obfd, osection, ss->contents.size));
949 vma = bfd_section_vma(ibfd, isection);
950 assert(bfd_set_section_vma(obfd, osection, vma));
952 osection->lma = isection->lma;
953 assert(bfd_set_section_alignment(obfd, osection, ss->alignment));
954 osection->entsize = isection->entsize;
955 osection->output_section = osection;
956 osection->output_offset = 0;
957 isection->output_section = osection;
958 isection->output_offset = 0;
959 return;
962 void setup_new_section(bfd *obfd, struct supersect *ss)
964 asection *osection = bfd_make_section_anyway(obfd, ss->name);
965 assert(osection != NULL);
966 bfd_set_section_flags(obfd, osection, ss->flags);
968 osection->userdata = ss;
969 ss->symbol = osection->symbol;
970 assert(bfd_set_section_size(obfd, osection, ss->contents.size));
971 assert(bfd_set_section_vma(obfd, osection, 0));
973 osection->lma = 0;
974 assert(bfd_set_section_alignment(obfd, osection, ss->alignment));
975 osection->entsize = 0;
976 osection->output_section = osection;
977 osection->output_offset = 0;
980 void write_section(bfd *obfd, asection *osection, void *arg)
982 struct supersect *ss = osection->userdata;
984 if ((ss->flags & SEC_GROUP) != 0 || ss->contents.size == 0)
985 return;
987 arelent **relocp;
988 char *error_message;
989 for (relocp = ss->new_relocs.data;
990 relocp < ss->new_relocs.data + ss->new_relocs.size; relocp++) {
991 bfd_vma val;
992 if (bfd_get_arch(obfd) == bfd_arch_arm)
993 val = osection->use_rela_p ? 0 : (*relocp)->addend;
994 else
995 val = 0;
996 bfd_put(bfd_get_reloc_size((*relocp)->howto) * 8, obfd, val,
997 ss->contents.data + (*relocp)->address);
998 if (bfd_install_relocation(obfd, *relocp, ss->contents.data,
999 0, osection, &error_message) !=
1000 bfd_reloc_ok) {
1001 fprintf(stderr, "ksplice: error installing reloc: %s",
1002 error_message);
1003 DIE;
1006 memcpy(vec_grow(&ss->relocs, ss->new_relocs.size), ss->new_relocs.data,
1007 ss->new_relocs.size * sizeof(*ss->new_relocs.data));
1009 bfd_set_reloc(obfd, osection,
1010 ss->relocs.size == 0 ? NULL : ss->relocs.data,
1011 ss->relocs.size);
1013 if (ss->flags & SEC_HAS_CONTENTS)
1014 assert(bfd_set_section_contents
1015 (obfd, osection, ss->contents.data, 0,
1016 ss->contents.size));
1019 /* Modified function from GNU Binutils objcopy.c
1021 * Mark all the symbols which will be used in output relocations with
1022 * the BSF_KEEP flag so that those symbols will not be stripped.
1024 * Ignore relocations which will not appear in the output file.
1026 void mark_symbols_used_in_relocations(bfd *abfd, asection *isection,
1027 void *ignored)
1029 struct superbfd *sbfd = fetch_superbfd(abfd);
1030 if (isection->output_section == NULL)
1031 return;
1033 struct supersect *ss = fetch_supersect(sbfd, isection);
1034 ss_mark_symbols_used_in_relocations(ss);
1037 void ss_mark_symbols_used_in_relocations(struct supersect *ss)
1039 /* Examine each symbol used in a relocation. If it's not one of the
1040 special bfd section symbols, then mark it with BSF_KEEP. */
1041 arelent **relocp;
1042 for (relocp = ss->relocs.data;
1043 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
1044 asymbol *sym = *(*relocp)->sym_ptr_ptr;
1045 if (!(bfd_is_const_section(sym->section) &&
1046 sym == sym->section->symbol))
1047 sym->flags |= BSF_KEEP;
1051 static bool deleted_table_section_symbol(bfd *abfd, asymbol *sym)
1053 struct superbfd *sbfd = fetch_superbfd(abfd);
1054 struct supersect *ss = fetch_supersect(sbfd, sym->section);
1056 if (bfd_is_const_section(sym->section))
1057 return false;
1059 asymbol **symp;
1060 for (symp = ss->syms.data; symp < ss->syms.data + ss->syms.size; symp++) {
1061 if (sym == *symp)
1062 break;
1064 return symp >= ss->syms.data + ss->syms.size;
1067 /* Modified function from GNU Binutils objcopy.c
1069 * Choose which symbol entries to copy.
1070 * We don't copy in place, because that confuses the relocs.
1071 * Return the number of symbols to print.
1073 void filter_symbols(bfd *ibfd, bfd *obfd, struct asymbolp_vec *osyms,
1074 struct asymbolp_vec *isyms)
1076 asymbol **symp;
1077 for (symp = isyms->data; symp < isyms->data + isyms->size; symp++) {
1078 asymbol *sym = *symp;
1080 bool keep;
1082 if (mode("keep") && (sym->flags & BSF_GLOBAL) != 0 &&
1083 !(mode("keep-primary") &&
1084 str_in_set(sym->section->name, &newsects)))
1085 sym->flags = (sym->flags & ~BSF_GLOBAL) | BSF_LOCAL;
1087 if (mode("finalize") && (sym->flags & BSF_GLOBAL) != 0)
1088 sym->flags = (sym->flags & ~BSF_GLOBAL) | BSF_LOCAL;
1090 if ((sym->flags & BSF_KEEP) != 0 /* Used in relocation. */
1091 || ((sym->flags & BSF_SECTION_SYM) != 0
1092 && ((*(sym->section)->symbol_ptr_ptr)->flags
1093 & BSF_KEEP) != 0))
1094 keep = true;
1095 else if ((sym->flags & (BSF_GLOBAL | BSF_WEAK)) != 0)
1096 keep = true;
1097 else if (bfd_decode_symclass(sym) == 'I')
1098 /* Global symbols in $idata sections need to be retained.
1099 External users of the library containing the $idata
1100 section may reference these symbols. */
1101 keep = true;
1102 else if ((sym->flags & BSF_GLOBAL) != 0
1103 || (sym->flags & BSF_WEAK) != 0
1104 || bfd_is_com_section(sym->section))
1105 keep = true;
1106 else if ((sym->flags & BSF_DEBUGGING) != 0)
1107 keep = true;
1108 else
1109 keep = !bfd_is_local_label(ibfd, sym);
1111 if (!want_section(sym->section))
1112 keep = false;
1114 if (deleted_table_section_symbol(ibfd, sym))
1115 keep = false;
1117 if (mode("rmsyms") && str_in_set(sym->name, &rmsyms))
1118 keep = false;
1120 if (keep)
1121 *vec_grow(osyms, 1) = sym;
1125 void read_str_set(struct str_vec *strs)
1127 char *buf = NULL;
1128 size_t n = 0;
1129 assert(getline(&buf, &n, stdin) >= 0);
1130 vec_init(strs);
1131 char *saveptr;
1132 while (1) {
1133 char *str = strtok_r(buf, " \n", &saveptr);
1134 buf = NULL;
1135 if (str == NULL)
1136 break;
1137 *vec_grow(strs, 1) = str;
1141 bool str_in_set(const char *str, const struct str_vec *strs)
1143 const char **strp;
1144 for (strp = strs->data; strp < strs->data + strs->size; strp++) {
1145 if (strcmp(str, *strp) == 0)
1146 return true;
1148 return false;
1151 bool want_section(asection *sect)
1153 if (!mode("keep"))
1154 return true;
1156 if (mode("keep-primary") && bfd_is_abs_section(sect))
1157 return true;
1158 const struct wsect *w = wanted_sections;
1159 for (; w != NULL; w = w->next) {
1160 if (w->sect == sect)
1161 return true;
1164 if (starts_with(sect->name, ".ksplice"))
1165 return true;
1166 if (mode("keep-helper") && starts_with(sect->name, ".text"))
1167 return true;
1168 if (mode("keep-helper") && starts_with(sect->name, ".exit.text")
1169 && bfd_get_section_by_name(sect->owner, ".exitcall.exit") == NULL)
1170 return true;
1171 if (mode("keep-primary") && str_in_set(sect->name, &sections))
1172 return true;
1173 if (mode("keep-primary") && str_in_set(sect->name, &newsects))
1174 return true;
1176 if (mode("keep-helper") && starts_with(sect->name, "__ksymtab"))
1177 return false;
1178 if (mode("keep-helper") && starts_with(sect->name, "__kcrctab"))
1179 return false;
1181 if (is_special(sect))
1182 return true;
1184 return false;
1187 bool is_table_section(asection *sect)
1189 const struct table_section *ss;
1190 for (ss = table_sections; ss != end_table_sections; ss++) {
1191 if (strcmp(ss->sectname, sect->name) == 0)
1192 return true;
1194 if (strcmp(sect->name, "__ex_table") == 0)
1195 return true;
1196 return false;