Use bool types in objutils.
[ksplice.git] / objmanip.c
blobbe4f8274ab153555120ef506f294556acb5bcedd
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_size 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_size(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 mark_wanted_if_referenced(bfd *abfd, asection *sect, void *ignored);
92 void check_for_ref_to_section(bfd *abfd, asection *looking_at,
93 void *looking_for);
94 bfd_boolean copy_object(bfd *ibfd, bfd *obfd);
95 void setup_section(bfd *ibfd, asection *isection, void *obfdarg);
96 static void setup_new_section(bfd *obfd, struct supersect *ss);
97 static void write_section(bfd *obfd, asection *osection, void *arg);
98 void mark_symbols_used_in_relocations(bfd *abfd, asection *isection,
99 void *ignored);
100 static void ss_mark_symbols_used_in_relocations(struct supersect *ss);
101 void filter_symbols(bfd *ibfd, bfd *obfd, struct asymbolp_vec *osyms,
102 struct asymbolp_vec *isyms);
103 static bool deleted_table_section_symbol(bfd *abfd, asymbol *sym);
104 void read_str_set(struct str_vec *strs);
105 bool str_in_set(const char *str, const struct str_vec *strs);
106 bool want_section(asection *sect);
107 bool is_table_section(asection *sect);
108 struct supersect *make_section(struct superbfd *sbfd, const char *name);
109 void __attribute__((format(printf, 3, 4)))
110 write_string(struct supersect *ss, const char **addr, const char *fmt, ...);
111 void rm_some_exports(struct superbfd *isbfd, const struct export_desc *ed);
112 void write_ksplice_export(struct superbfd *sbfd, const char *symname,
113 const char *export_type, bool del);
114 void write_reloc(struct supersect *ss, const void *addr, asymbol **symp,
115 bfd_vma offset);
116 arelent *create_reloc(struct supersect *ss, const void *addr, asymbol **symp,
117 bfd_vma offset);
119 struct str_vec sections, newsects, delsects, rmsyms;
120 struct export_desc_vec exports;
122 const char *modestr, *kid;
124 struct wsect *wanted_sections = NULL;
126 const struct table_section table_sections[] = {
127 {".altinstructions", 2 * sizeof(void *) + 4},
128 {".smp_locks", sizeof(void *)},
129 {".parainstructions", sizeof(void *) + 4},
130 {"__ex_table", 2 * sizeof(unsigned long)},
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_size(isbfd, symp);
269 if (mode("keep-primary")) {
270 const char **sectname;
271 for (sectname = sections.data;
272 sectname < sections.data + sections.size; sectname++)
273 write_ksplice_patch(isbfd, *sectname);
275 const char **label;
276 for (label = delsects.data;
277 label < delsects.data + delsects.size; label++)
278 write_ksplice_deleted_patch(isbfd, *label);
280 const struct export_desc *ed;
281 for (ed = exports.data; ed < exports.data + exports.size;
282 ed++) {
283 if (starts_with(ed->sectname, "del___ksymtab")) {
284 const char *export_type =
285 ed->sectname + strlen("del___ksymtab");
286 const char **symname;
287 for (symname = ed->names.data;
288 symname < ed->names.data + ed->names.size;
289 symname++)
290 write_ksplice_export(isbfd, *symname,
291 export_type, true);
292 } else {
293 rm_some_exports(isbfd, ed);
298 asection *p;
299 for (p = ibfd->sections; p != NULL; p = p->next) {
300 struct supersect *ss = fetch_supersect(isbfd, p);
301 if (is_table_section(p) || starts_with(p->name, ".ksplice"))
302 continue;
303 if (want_section(p) || mode("rmsyms"))
304 rm_some_relocs(ss);
307 const struct table_section *ss;
308 if (mode("keep")) {
309 for (ss = table_sections; ss != end_table_sections; ss++)
310 filter_table_section(isbfd, ss);
313 copy_object(ibfd, obfd);
314 assert(bfd_close(obfd));
315 assert(bfd_close(ibfd));
316 return EXIT_SUCCESS;
319 void rm_some_exports(struct superbfd *isbfd, const struct export_desc *ed)
321 assert(starts_with(ed->sectname, "__ksymtab"));
322 const char *export_type = ed->sectname + strlen("__ksymtab");
323 asection *sym_sect = bfd_get_section_by_name(isbfd->abfd, ed->sectname);
324 assert(sym_sect != NULL);
325 char *export_crc_name;
326 assert(asprintf(&export_crc_name, "__kcrctab%s", export_type) >= 0);
327 asection *crc_sect = bfd_get_section_by_name(isbfd->abfd,
328 export_crc_name);
329 struct supersect *ss, *crc_ss = NULL;
330 ss = fetch_supersect(isbfd, sym_sect);
331 if (crc_sect != NULL)
332 crc_ss = fetch_supersect(isbfd, crc_sect);
334 if (crc_ss != NULL)
335 assert(ss->contents.size * sizeof(unsigned long) ==
336 crc_ss->contents.size * sizeof(struct kernel_symbol));
338 struct supersect orig_ss, orig_crc_ss;
339 supersect_move(&orig_ss, ss);
340 if (crc_ss != NULL)
341 supersect_move(&orig_crc_ss, crc_ss);
343 struct kernel_symbol *orig_ksym;
344 unsigned long *orig_crc;
345 for (orig_ksym = orig_ss.contents.data,
346 orig_crc = orig_crc_ss.contents.data;
347 (void *)orig_ksym < orig_ss.contents.data + orig_ss.contents.size;
348 orig_ksym++, orig_crc++) {
349 asymbol *sym;
350 read_reloc(&orig_ss, &orig_ksym->value,
351 sizeof(orig_ksym->value), &sym);
352 if (!str_in_set(sym->name, &ed->names))
353 continue;
355 struct kernel_symbol *ksym = sect_grow(ss, 1, typeof(*ksym));
356 sect_copy(ss, &ksym->value, &orig_ss, &orig_ksym->value, 1);
357 /* Replace name with a mangled name */
358 write_ksplice_export(ss->parent, sym->name, export_type, false);
359 write_string(ss, (const char **)&ksym->name,
360 "DISABLED_%s_%s", sym->name, kid);
362 if (crc_ss != NULL)
363 sect_copy(crc_ss,
364 sect_grow(crc_ss, 1, typeof(*orig_crc)),
365 &orig_crc_ss, orig_crc, 1);
369 void rm_some_relocs(struct supersect *ss)
371 struct arelentp_vec orig_relocs;
372 vec_move(&orig_relocs, &ss->relocs);
374 arelent **relocp;
375 for (relocp = orig_relocs.data;
376 relocp < orig_relocs.data + orig_relocs.size; relocp++) {
377 bool rm_reloc = false;
378 asymbol *sym_ptr = *(*relocp)->sym_ptr_ptr;
380 if (mode("rmsyms") && str_in_set(sym_ptr->name, &rmsyms))
381 rm_reloc = true;
383 if (mode("keep"))
384 rm_reloc = true;
386 if (mode("keep-primary") && want_section(sym_ptr->section) &&
387 (str_in_set(sym_ptr->section->name, &newsects) ||
388 bfd_is_const_section(sym_ptr->section) ||
389 starts_with(sym_ptr->section->name, ".rodata.str")))
390 rm_reloc = false;
392 if (mode("finalize") && bfd_is_und_section(sym_ptr->section))
393 rm_reloc = true;
395 if (rm_reloc)
396 write_ksplice_reloc(ss, *relocp);
397 else
398 *vec_grow(&ss->relocs, 1) = *relocp;
402 struct supersect *make_section(struct superbfd *sbfd, const char *name)
404 asection *sect = bfd_get_section_by_name(sbfd->abfd, name);
405 if (sect != NULL)
406 return fetch_supersect(sbfd, sect);
407 else
408 return new_supersect(sbfd, name);
411 arelent *create_reloc(struct supersect *ss, const void *addr, asymbol **symp,
412 bfd_vma offset)
414 bfd_reloc_code_real_type code;
415 switch (bfd_arch_bits_per_address(ss->parent->abfd)) {
416 case 32:
417 code = BFD_RELOC_32;
418 break;
419 case 64:
420 code = BFD_RELOC_64;
421 break;
422 default:
423 DIE;
426 arelent *reloc = malloc(sizeof(*reloc));
427 reloc->sym_ptr_ptr = symp;
428 reloc->address = addr - ss->contents.data;
429 reloc->howto = bfd_reloc_type_lookup(ss->parent->abfd, code);
430 reloc->addend = offset;
431 return reloc;
434 void write_reloc(struct supersect *ss, const void *addr, asymbol **symp,
435 bfd_vma offset)
437 *vec_grow(&ss->new_relocs, 1) = create_reloc(ss, addr, symp, offset);
440 void write_string(struct supersect *ss, const char **addr, const char *fmt, ...)
442 va_list ap;
443 va_start(ap, fmt);
444 int len = vsnprintf(NULL, 0, fmt, ap);
445 va_end(ap);
446 struct supersect *str_ss = make_section(ss->parent, ".ksplice_str");
447 char *buf = sect_grow(str_ss, len + 1, char);
448 va_start(ap, fmt);
449 vsnprintf(buf, len + 1, fmt, ap);
450 va_end(ap);
452 write_reloc(ss, addr, &str_ss->symbol,
453 (void *)buf - str_ss->contents.data);
456 void lookup_system_map(struct addr_vec *addrs, const char *name, long offset)
458 struct addr_vec *map_addrs =
459 addr_vec_hash_lookup(&system_map, name, FALSE);
460 if (map_addrs == NULL)
461 return;
463 unsigned long *addr, *map_addr;
464 for (map_addr = map_addrs->data;
465 map_addr < map_addrs->data + map_addrs->size; map_addr++) {
466 for (addr = addrs->data; addr < addrs->data + addrs->size;
467 addr++) {
468 if (*addr == *map_addr + offset)
469 break;
471 if (addr < addrs->data + addrs->size)
472 continue;
473 *vec_grow(addrs, 1) = *map_addr + offset;
477 void write_system_map_array(struct superbfd *sbfd, struct supersect *ss,
478 const unsigned long **sym_addrs,
479 unsigned long *num_sym_addrs, asymbol *sym)
481 struct addr_vec addrs;
482 vec_init(&addrs);
484 if (bfd_is_abs_section(sym->section)) {
485 *vec_grow(&addrs, 1) = sym->value;
486 } else if (bfd_is_und_section(sym->section)) {
487 lookup_system_map(&addrs, sym->name, 0);
488 } else if (!bfd_is_const_section(sym->section)) {
489 asymbol **gsymp;
490 for (gsymp = sbfd->syms.data;
491 gsymp < sbfd->syms.data + sbfd->syms.size; gsymp++) {
492 asymbol *gsym = *gsymp;
493 if ((gsym->flags & BSF_DEBUGGING) == 0 &&
494 gsym->section == sym->section)
495 lookup_system_map(&addrs, gsym->name,
496 sym->value - gsym->value);
500 *num_sym_addrs = addrs.size;
501 if (addrs.size != 0) {
502 struct supersect *array_ss = make_section(sbfd,
503 ".ksplice_array");
504 void *buf = sect_grow(array_ss, addrs.size,
505 typeof(*addrs.data));
506 memcpy(buf, addrs.data, addrs.size * sizeof(*addrs.data));
507 write_reloc(ss, sym_addrs, &array_ss->symbol,
508 buf - array_ss->contents.data);
509 } else {
510 *sym_addrs = NULL;
513 vec_free(&addrs);
516 void write_ksplice_system_map(struct superbfd *sbfd, asymbol *sym,
517 const char *addstr_sect)
519 struct supersect *smap_ss = make_section(sbfd, ".ksplice_system_map");
520 struct ksplice_system_map *smap;
521 const char *label = label_lookup(sbfd, sym);
523 bool *done = bool_hash_lookup(&system_map_written, label, TRUE);
524 if (*done)
525 return;
526 *done = true;
528 smap = sect_grow(smap_ss, 1, struct ksplice_system_map);
530 write_system_map_array(sbfd, smap_ss, &smap->candidates,
531 &smap->nr_candidates, sym);
532 write_string(smap_ss, &smap->label, "%s%s", label, addstr_sect);
535 void write_ksplice_symbol(struct supersect *ss,
536 const struct ksplice_symbol *const *addr,
537 asymbol *sym, const char *addstr_sect)
539 struct supersect *ksymbol_ss = make_section(ss->parent,
540 ".ksplice_symbols");
541 struct ksplice_symbol *ksymbol = sect_grow(ksymbol_ss, 1,
542 struct ksplice_symbol);
544 if (bfd_is_und_section(sym->section) || (sym->flags & BSF_GLOBAL) != 0) {
545 write_string(ksymbol_ss, &ksymbol->name, "%s", sym->name);
546 } else if (bfd_is_const_section(sym->section)) {
547 ksymbol->name = NULL;
548 } else {
549 asymbol *gsym = canonical_symbol(ss->parent, sym);
551 if (gsym == NULL)
552 ksymbol->name = NULL;
553 else
554 write_string(ksymbol_ss, &ksymbol->name, "%s",
555 gsym->name);
558 write_string(ksymbol_ss, &ksymbol->label, "%s%s",
559 label_lookup(ss->parent, sym), addstr_sect);
561 write_ksplice_system_map(ksymbol_ss->parent, sym, addstr_sect);
563 write_reloc(ss, addr, &ksymbol_ss->symbol,
564 (void *)ksymbol - ksymbol_ss->contents.data);
567 void write_ksplice_reloc(struct supersect *ss, arelent *orig_reloc)
569 asymbol *sym_ptr = *orig_reloc->sym_ptr_ptr;
571 reloc_howto_type *howto = orig_reloc->howto;
573 bfd_vma addend = get_reloc_offset(ss, orig_reloc, false);
574 blot_section(ss, orig_reloc->address, howto);
576 struct supersect *kreloc_ss = make_section(ss->parent,
577 mode("rmsyms") ?
578 ".ksplice_init_relocs" :
579 ".ksplice_relocs");
580 struct ksplice_reloc *kreloc = sect_grow(kreloc_ss, 1,
581 struct ksplice_reloc);
583 write_reloc(kreloc_ss, &kreloc->blank_addr,
584 &ss->symbol, orig_reloc->address);
585 kreloc->blank_offset = (unsigned long)orig_reloc->address;
586 write_ksplice_symbol(kreloc_ss, &kreloc->symbol, sym_ptr, "");
587 kreloc->pcrel = howto->pc_relative;
588 kreloc->addend = addend;
589 kreloc->size = bfd_get_reloc_size(howto);
590 kreloc->dst_mask = howto->dst_mask;
591 kreloc->rightshift = howto->rightshift;
592 kreloc->signed_addend =
593 (howto->complain_on_overflow == complain_overflow_signed) ||
594 (howto->complain_on_overflow == complain_overflow_bitfield);
597 #define CANARY(x, canary) ((x & ~howto->dst_mask) | (canary & howto->dst_mask))
599 void blot_section(struct supersect *ss, int offset, reloc_howto_type *howto)
601 int bits = bfd_get_reloc_size(howto) * 8;
602 void *address = ss->contents.data + offset;
603 bfd_vma x = bfd_get(bits, ss->parent->abfd, address);
604 x = (x & ~howto->dst_mask) |
605 ((bfd_vma)0x7777777777777777LL & howto->dst_mask);
606 bfd_put(bits, ss->parent->abfd, x, address);
609 void write_ksplice_size(struct superbfd *sbfd, asymbol **symp)
611 asymbol *sym = *symp;
612 struct supersect *ksize_ss = make_section(sbfd, ".ksplice_sizes");
613 struct ksplice_size *ksize = sect_grow(ksize_ss, 1,
614 struct ksplice_size);
616 write_ksplice_symbol(ksize_ss, &ksize->symbol, sym,
617 mode("keep-primary") ? "(post)" : "");
618 ksize->size = bfd_get_section_size(sym->section);
619 ksize->flags = 0;
620 if (starts_with(sym->section->name, ".rodata"))
621 ksize->flags |= KSPLICE_SIZE_RODATA;
622 if (starts_with(sym->section->name, ".data"))
623 ksize->flags |= KSPLICE_SIZE_DATA;
624 if (starts_with(sym->section->name, ".text") ||
625 starts_with(sym->section->name, ".exit.text"))
626 ksize->flags |= KSPLICE_SIZE_TEXT;
627 assert(ksize->flags != 0);
628 write_reloc(ksize_ss, &ksize->thismod_addr, symp, 0);
631 void write_ksplice_patch(struct superbfd *sbfd, const char *sectname)
633 struct supersect *kpatch_ss = make_section(sbfd, ".ksplice_patches");
634 struct ksplice_patch *kpatch = sect_grow(kpatch_ss, 1,
635 struct ksplice_patch);
636 asection *sect = bfd_get_section_by_name(sbfd->abfd, sectname);
637 assert(sect != NULL);
639 write_string(kpatch_ss, &kpatch->label, "%s",
640 label_lookup(sbfd, sect->symbol));
641 write_reloc(kpatch_ss, &kpatch->repladdr, &sect->symbol, 0);
644 void write_ksplice_deleted_patch(struct superbfd *sbfd, const char *label)
646 struct supersect *kpatch_ss = make_section(sbfd, ".ksplice_patches");
647 struct ksplice_patch *kpatch = sect_grow(kpatch_ss, 1,
648 struct ksplice_patch);
650 write_string(kpatch_ss, &kpatch->label, "%s", label);
651 kpatch->repladdr = 0;
654 void write_ksplice_export(struct superbfd *sbfd, const char *symname,
655 const char *export_type, bool del)
657 struct supersect *export_ss = make_section(sbfd, ".ksplice_exports");
658 struct ksplice_export *export = sect_grow(export_ss, 1,
659 struct ksplice_export);
661 if (del) {
662 write_string(export_ss, &export->name, "%s", symname);
663 write_string(export_ss, &export->new_name,
664 "DISABLED_%s_%s", symname, kid);
665 } else {
666 write_string(export_ss, &export->new_name, "%s", symname);
667 write_string(export_ss, &export->name, "DISABLED_%s_%s",
668 symname, kid);
672 void filter_table_section(struct superbfd *sbfd, const struct table_section *s)
674 asection *isection = bfd_get_section_by_name(sbfd->abfd, s->sectname);
675 if (isection == NULL)
676 return;
678 struct supersect *ss = fetch_supersect(sbfd, isection), orig_ss;
679 supersect_move(&orig_ss, ss);
681 const void *orig_entry;
682 for (orig_entry = orig_ss.contents.data;
683 orig_entry < orig_ss.contents.data + orig_ss.contents.size;
684 orig_entry += align(s->entry_size, 1 << ss->alignment)) {
685 asymbol *sym;
686 read_reloc(&orig_ss, orig_entry, sizeof(void *), &sym);
688 asection *p;
689 for (p = sbfd->abfd->sections; p != NULL; p = p->next) {
690 if (sym->section == p
691 && !is_table_section(p) && !want_section(p))
692 break;
694 if (p != NULL)
695 continue;
697 sect_copy(ss, sect_do_grow(ss, 1, s->entry_size,
698 1 << ss->alignment),
699 &orig_ss, orig_entry, s->entry_size);
703 void mark_wanted_if_referenced(bfd *abfd, asection *sect, void *ignored)
705 if (want_section(sect))
706 return;
707 if (!starts_with(sect->name, ".text")
708 && !starts_with(sect->name, ".exit.text")
709 && !starts_with(sect->name, ".rodata")
710 && !(starts_with(sect->name, ".data") && mode("keep-helper")))
711 return;
713 if (mode("keep-helper")) {
714 struct superbfd *sbfd = fetch_superbfd(abfd);
715 asymbol **symp;
716 for (symp = sbfd->syms.data;
717 symp < sbfd->syms.data + sbfd->syms.size; symp++) {
718 asymbol *sym = *symp;
719 if (sym->section == sect &&
720 (sym->flags & BSF_GLOBAL) != 0) {
721 struct wsect *w = malloc(sizeof(*w));
722 w->sect = sect;
723 w->next = wanted_sections;
724 wanted_sections = w;
725 return;
730 bfd_map_over_sections(abfd, check_for_ref_to_section, sect);
733 void check_for_ref_to_section(bfd *abfd, asection *looking_at,
734 void *looking_for)
736 if (!want_section(looking_at) || is_table_section(looking_at))
737 return;
739 struct superbfd *sbfd = fetch_superbfd(abfd);
740 struct supersect *ss = fetch_supersect(sbfd, looking_at);
741 arelent **relocp;
742 for (relocp = ss->relocs.data;
743 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
744 asymbol *sym = *(*relocp)->sym_ptr_ptr;
745 if (sym->section == (asection *)looking_for &&
746 (!starts_with(sym->section->name, ".text") ||
747 get_reloc_offset(ss, *relocp, true) != 0)) {
748 struct wsect *w = malloc(sizeof(*w));
749 w->sect = looking_for;
750 w->next = wanted_sections;
751 wanted_sections = w;
752 break;
757 /* Modified function from GNU Binutils objcopy.c */
758 bfd_boolean copy_object(bfd *ibfd, bfd *obfd)
760 assert(bfd_set_format(obfd, bfd_get_format(ibfd)));
762 bfd_vma start = bfd_get_start_address(ibfd);
764 flagword flags = bfd_get_file_flags(ibfd);
765 flags &= bfd_applicable_file_flags(obfd);
767 assert(bfd_set_start_address(obfd, start)
768 && bfd_set_file_flags(obfd, flags));
770 enum bfd_architecture iarch = bfd_get_arch(ibfd);
771 unsigned int imach = bfd_get_mach(ibfd);
772 assert(bfd_set_arch_mach(obfd, iarch, imach));
773 assert(bfd_set_format(obfd, bfd_get_format(ibfd)));
775 /* BFD mandates that all output sections be created and sizes set before
776 any output is done. Thus, we traverse all sections multiple times. */
777 bfd_map_over_sections(ibfd, setup_section, obfd);
779 struct supersect *new_supersects = fetch_superbfd(ibfd)->new_supersects;
780 struct supersect *ss;
781 for (ss = new_supersects; ss != NULL; ss = ss->next)
782 setup_new_section(obfd, ss);
784 /* Mark symbols used in output relocations so that they
785 are kept, even if they are local labels or static symbols.
787 Note we iterate over the input sections examining their
788 relocations since the relocations for the output sections
789 haven't been set yet. mark_symbols_used_in_relocations will
790 ignore input sections which have no corresponding output
791 section. */
793 bfd_map_over_sections(ibfd, mark_symbols_used_in_relocations, NULL);
794 for (ss = new_supersects; ss != NULL; ss = ss->next)
795 ss_mark_symbols_used_in_relocations(ss);
796 struct asymbolp_vec osyms;
797 vec_init(&osyms);
798 filter_symbols(ibfd, obfd, &osyms, &fetch_superbfd(ibfd)->syms);
800 bfd_set_symtab(obfd, osyms.data, osyms.size);
802 /* This has to happen after the symbol table has been set. */
803 bfd_map_over_sections(obfd, write_section, NULL);
805 /* Allow the BFD backend to copy any private data it understands
806 from the input BFD to the output BFD. This is done last to
807 permit the routine to look at the filtered symbol table, which is
808 important for the ECOFF code at least. */
809 assert(bfd_copy_private_bfd_data(ibfd, obfd));
811 return TRUE;
814 /* Modified function from GNU Binutils objcopy.c */
815 void setup_section(bfd *ibfd, asection *isection, void *obfdarg)
817 bfd *obfd = obfdarg;
818 bfd_vma vma;
820 if (!want_section(isection))
821 return;
823 asection *osection = bfd_make_section_anyway(obfd, isection->name);
824 assert(osection != NULL);
826 struct superbfd *isbfd = fetch_superbfd(ibfd);
827 struct supersect *ss = fetch_supersect(isbfd, isection);
828 osection->userdata = ss;
829 bfd_set_section_flags(obfd, osection, ss->flags);
830 ss->symbol = osection->symbol;
831 assert(bfd_set_section_size(obfd, osection, ss->contents.size));
833 vma = bfd_section_vma(ibfd, isection);
834 assert(bfd_set_section_vma(obfd, osection, vma));
836 osection->lma = isection->lma;
837 assert(bfd_set_section_alignment(obfd, osection, ss->alignment));
838 osection->entsize = isection->entsize;
839 osection->output_section = osection;
840 osection->output_offset = 0;
841 isection->output_section = osection;
842 isection->output_offset = 0;
843 return;
846 void setup_new_section(bfd *obfd, struct supersect *ss)
848 asection *osection = bfd_make_section_anyway(obfd, ss->name);
849 assert(osection != NULL);
850 bfd_set_section_flags(obfd, osection, ss->flags);
852 osection->userdata = ss;
853 ss->symbol = osection->symbol;
854 assert(bfd_set_section_size(obfd, osection, ss->contents.size));
855 assert(bfd_set_section_vma(obfd, osection, 0));
857 osection->lma = 0;
858 assert(bfd_set_section_alignment(obfd, osection, ss->alignment));
859 osection->entsize = 0;
860 osection->output_section = osection;
861 osection->output_offset = 0;
864 void write_section(bfd *obfd, asection *osection, void *arg)
866 struct supersect *ss = osection->userdata;
868 if ((ss->flags & SEC_GROUP) != 0 || ss->contents.size == 0)
869 return;
871 arelent **relocp;
872 char *error_message;
873 for (relocp = ss->new_relocs.data;
874 relocp < ss->new_relocs.data + ss->new_relocs.size; relocp++) {
875 bfd_vma val;
876 if (bfd_get_arch(obfd) == bfd_arch_arm)
877 val = osection->use_rela_p ? 0 : (*relocp)->addend;
878 else
879 val = 0;
880 bfd_put(bfd_get_reloc_size((*relocp)->howto) * 8, obfd, val,
881 ss->contents.data + (*relocp)->address);
882 if (bfd_install_relocation(obfd, *relocp, ss->contents.data,
883 0, osection, &error_message) !=
884 bfd_reloc_ok) {
885 fprintf(stderr, "ksplice: error installing reloc: %s",
886 error_message);
887 DIE;
890 memcpy(vec_grow(&ss->relocs, ss->new_relocs.size), ss->new_relocs.data,
891 ss->new_relocs.size * sizeof(*ss->new_relocs.data));
893 bfd_set_reloc(obfd, osection,
894 ss->relocs.size == 0 ? NULL : ss->relocs.data,
895 ss->relocs.size);
897 if (ss->flags & SEC_HAS_CONTENTS)
898 assert(bfd_set_section_contents
899 (obfd, osection, ss->contents.data, 0,
900 ss->contents.size));
903 /* Modified function from GNU Binutils objcopy.c
905 * Mark all the symbols which will be used in output relocations with
906 * the BSF_KEEP flag so that those symbols will not be stripped.
908 * Ignore relocations which will not appear in the output file.
910 void mark_symbols_used_in_relocations(bfd *abfd, asection *isection,
911 void *ignored)
913 struct superbfd *sbfd = fetch_superbfd(abfd);
914 if (isection->output_section == NULL)
915 return;
917 struct supersect *ss = fetch_supersect(sbfd, isection);
918 ss_mark_symbols_used_in_relocations(ss);
921 void ss_mark_symbols_used_in_relocations(struct supersect *ss)
923 /* Examine each symbol used in a relocation. If it's not one of the
924 special bfd section symbols, then mark it with BSF_KEEP. */
925 arelent **relocp;
926 for (relocp = ss->relocs.data;
927 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
928 asymbol *sym = *(*relocp)->sym_ptr_ptr;
929 if (!(bfd_is_const_section(sym->section) &&
930 sym == sym->section->symbol))
931 sym->flags |= BSF_KEEP;
935 static bool deleted_table_section_symbol(bfd *abfd, asymbol *sym)
937 struct superbfd *sbfd = fetch_superbfd(abfd);
938 struct supersect *ss = fetch_supersect(sbfd, sym->section);
940 if (bfd_is_const_section(sym->section))
941 return false;
943 asymbol **symp;
944 for (symp = ss->syms.data; symp < ss->syms.data + ss->syms.size; symp++) {
945 if (sym == *symp)
946 break;
948 return symp >= ss->syms.data + ss->syms.size;
951 /* Modified function from GNU Binutils objcopy.c
953 * Choose which symbol entries to copy.
954 * We don't copy in place, because that confuses the relocs.
955 * Return the number of symbols to print.
957 void filter_symbols(bfd *ibfd, bfd *obfd, struct asymbolp_vec *osyms,
958 struct asymbolp_vec *isyms)
960 asymbol **symp;
961 for (symp = isyms->data; symp < isyms->data + isyms->size; symp++) {
962 asymbol *sym = *symp;
964 bool keep;
966 if (mode("keep") && (sym->flags & BSF_GLOBAL) != 0 &&
967 !(mode("keep-primary") &&
968 str_in_set(sym->section->name, &newsects)))
969 sym->flags = (sym->flags & ~BSF_GLOBAL) | BSF_LOCAL;
971 if (mode("finalize") && (sym->flags & BSF_GLOBAL) != 0)
972 sym->flags = (sym->flags & ~BSF_GLOBAL) | BSF_LOCAL;
974 if ((sym->flags & BSF_KEEP) != 0 /* Used in relocation. */
975 || ((sym->flags & BSF_SECTION_SYM) != 0
976 && ((*(sym->section)->symbol_ptr_ptr)->flags
977 & BSF_KEEP) != 0))
978 keep = true;
979 else if ((sym->flags & (BSF_GLOBAL | BSF_WEAK)) != 0)
980 keep = true;
981 else if (bfd_decode_symclass(sym) == 'I')
982 /* Global symbols in $idata sections need to be retained.
983 External users of the library containing the $idata
984 section may reference these symbols. */
985 keep = true;
986 else if ((sym->flags & BSF_GLOBAL) != 0
987 || (sym->flags & BSF_WEAK) != 0
988 || bfd_is_com_section(sym->section))
989 keep = true;
990 else if ((sym->flags & BSF_DEBUGGING) != 0)
991 keep = true;
992 else
993 keep = !bfd_is_local_label(ibfd, sym);
995 if (!want_section(sym->section))
996 keep = false;
998 if (deleted_table_section_symbol(ibfd, sym))
999 keep = false;
1001 if (mode("rmsyms") && str_in_set(sym->name, &rmsyms))
1002 keep = false;
1004 if (keep)
1005 *vec_grow(osyms, 1) = sym;
1009 void read_str_set(struct str_vec *strs)
1011 char *buf = NULL;
1012 size_t n = 0;
1013 assert(getline(&buf, &n, stdin) >= 0);
1014 vec_init(strs);
1015 char *saveptr;
1016 while (1) {
1017 char *str = strtok_r(buf, " \n", &saveptr);
1018 buf = NULL;
1019 if (str == NULL)
1020 break;
1021 *vec_grow(strs, 1) = str;
1025 bool str_in_set(const char *str, const struct str_vec *strs)
1027 const char **strp;
1028 for (strp = strs->data; strp < strs->data + strs->size; strp++) {
1029 if (strcmp(str, *strp) == 0)
1030 return true;
1032 return false;
1035 bool want_section(asection *sect)
1037 if (!mode("keep"))
1038 return true;
1040 if (mode("keep-primary") && bfd_is_abs_section(sect))
1041 return true;
1042 const struct wsect *w = wanted_sections;
1043 for (; w != NULL; w = w->next) {
1044 if (w->sect == sect)
1045 return true;
1048 if (starts_with(sect->name, ".ksplice"))
1049 return true;
1050 if (mode("keep-helper") && starts_with(sect->name, ".text"))
1051 return true;
1052 if (mode("keep-helper") && starts_with(sect->name, ".exit.text")
1053 && bfd_get_section_by_name(sect->owner, ".exitcall.exit") == NULL)
1054 return true;
1055 if (mode("keep-primary") && str_in_set(sect->name, &sections))
1056 return true;
1057 if (mode("keep-primary") && str_in_set(sect->name, &newsects))
1058 return true;
1060 if (mode("keep-helper") && starts_with(sect->name, "__ksymtab"))
1061 return false;
1062 if (mode("keep-helper") && starts_with(sect->name, "__kcrctab"))
1063 return false;
1065 if (is_special(sect))
1066 return true;
1068 return false;
1071 bool is_table_section(asection *sect)
1073 const struct table_section *ss;
1074 for (ss = table_sections; ss != end_table_sections; ss++) {
1075 if (strcmp(ss->sectname, sect->name) == 0)
1076 return true;
1078 return false;