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