Ignore relocations from a data section to itself.
[ksplice.git] / objmanip.c
blob37bdd3142536b288c35a86b79800f56124ab83b9
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 <post.o> <out.o> keep-primary <pre.o> <kid>"
27 * This mode prepares the object file to be installed as a ksplice update. The
28 * kid argument is the ksplice id string for the ksplice update being built.
30 * - keep-helper: "objmanip <pre.o> <out.o> keep-helper"
32 * This mode prepares the object file to be used for run-pre matching. This
33 * involves replacing all ELF relocations with ksplice relocations and
34 * writing ksplice_section structures for each ELF text or data section.
36 * - rmsyms mode: "objmanip <in.o> <out.o> rmsyms
38 * In this mode, any ELF relocations involving the list of symbol names given on
39 * standard input are replaced with ksplice relocations. This is used only
40 * for KSPLICE_STANDALONE.
42 * - finalize mode: "objmanip <in.o> <out.o> finalize"
44 * In this mode, any ELF relocations to undefined symbols are replaced with
45 * ksplice relocations.
48 /* Always define KSPLICE_STANDALONE, even if you're using integrated Ksplice.
49 objmanip won't compile without it. */
50 #define KSPLICE_STANDALONE
52 #define _GNU_SOURCE
53 #include "objcommon.h"
54 #include "kmodsrc/ksplice.h"
55 #include "kmodsrc/offsets.h"
56 #include <stdint.h>
57 #include <stdarg.h>
58 #include <stdlib.h>
59 #include <stdio.h>
60 #include <limits.h>
62 #define KSPLICE_SYMBOL_STR "KSPLICE_SYMBOL_"
64 #define symbol_init(sym) *(sym) = (asymbol *)NULL
65 DEFINE_HASH_TYPE(asymbol *, symbol_hash, symbol_hash_init, symbol_hash_free,
66 symbol_hash_lookup, symbol_init);
68 struct export {
69 const char *name;
70 struct supersect *ss;
72 DECLARE_VEC_TYPE(struct export, export_vec);
74 DECLARE_VEC_TYPE(const char *, str_vec);
76 struct export_desc {
77 const char *export_type;
78 bool deletion;
79 struct str_vec names;
80 struct supersect *sym_ss;
81 struct supersect *crc_ss;
83 DECLARE_VEC_TYPE(struct export_desc, export_desc_vec);
85 #define bool_init(b) *(b) = false
86 DEFINE_HASH_TYPE(bool, bool_hash, bool_hash_init, bool_hash_free,
87 bool_hash_lookup, bool_init);
89 #define ulong_init(x) *(x) = 0
90 DEFINE_HASH_TYPE(unsigned long, ulong_hash, ulong_hash_init,
91 ulong_hash_free, ulong_hash_lookup, ulong_init);
93 void do_keep_primary(struct superbfd *isbfd, const char *pre);
94 void do_keep_helper(struct superbfd *isbfd);
95 void do_finalize(struct superbfd *isbfd);
96 void do_rmsyms(struct superbfd *isbfd);
98 struct export_vec *get_export_syms(struct superbfd *sbfd);
99 void compare_exported_symbols(struct superbfd *oldsbfd,
100 struct superbfd *newsbfd, bool deletion);
101 struct export_desc *new_export_desc(struct supersect *ss, bool deletion);
102 bool relocs_equal(struct supersect *old_src_ss, struct supersect *new_src_ss,
103 arelent *old_reloc, arelent *new_reloc);
104 bool all_relocs_equal(struct supersect *old_ss, struct supersect *new_ss);
105 static bool part_of_reloc(struct supersect *ss, unsigned long addr);
106 static bool nonrelocs_equal(struct supersect *old_ss, struct supersect *new_ss);
107 static void handle_section_symbol_renames(struct superbfd *oldsbfd,
108 struct superbfd *newsbfd);
110 enum supersect_type supersect_type(struct supersect *ss);
111 void initialize_supersect_types(struct superbfd *sbfd);
112 static void initialize_spans(struct superbfd *sbfd);
113 static void initialize_string_spans(struct supersect *ss);
114 struct span *reloc_target_span(struct supersect *ss, arelent *reloc);
115 struct span *reloc_address_span(struct supersect *ss, arelent *reloc);
116 void remove_unkept_spans(struct superbfd *sbfd);
117 void compute_span_shifts(struct superbfd *sbfd);
118 static struct span *new_span(struct supersect *ss, bfd_vma start, bfd_vma size);
119 bool is_table_section(const char *name, bool consider_other);
121 void rm_relocs(struct superbfd *isbfd);
122 void rm_some_relocs(struct supersect *ss);
123 void write_ksplice_reloc(struct supersect *ss, arelent *orig_reloc);
124 void load_ksplice_symbol_offsets(struct superbfd *sbfd);
125 void blot_section(struct supersect *ss, int offset, reloc_howto_type *howto);
126 static void write_ksplice_section(struct span *span);
127 void write_ksplice_patch(struct superbfd *sbfd, const char *sectname);
128 void write_ksplice_deleted_patch(struct superbfd *sbfd, const char *name,
129 const char *label);
130 asymbol **make_undefined_symbolp(struct superbfd *sbfd, const char *name);
131 void filter_table_sections(struct superbfd *isbfd);
132 void filter_table_section(struct superbfd *sbfd, const struct table_section *s);
133 void keep_referenced_sections(struct superbfd *sbfd);
134 bfd_boolean copy_object(bfd *ibfd, bfd *obfd);
135 void setup_section(bfd *ibfd, asection *isection, void *obfdarg);
136 static void setup_new_section(bfd *obfd, struct supersect *ss);
137 static void write_section(bfd *obfd, asection *osection, void *arg);
138 static void delete_obsolete_relocs(struct supersect *ss);
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 static bool deleted_table_section_symbol(bfd *abfd, asymbol *sym);
145 void read_str_set(struct str_vec *strs);
146 bool str_in_set(const char *str, const struct str_vec *strs);
147 struct supersect *make_section(struct superbfd *sbfd, const char *name);
148 void __attribute__((format(printf, 3, 4)))
149 write_string(struct supersect *ss, const char **addr, const char *fmt, ...);
150 void rm_some_exports(struct superbfd *isbfd, const struct export_desc *ed);
151 void write_ksplice_export(struct superbfd *sbfd, const char *symname,
152 const char *export_type, bool del);
153 void write_reloc(struct supersect *ss, const void *addr, asymbol **symp,
154 bfd_vma offset);
155 arelent *create_reloc(struct supersect *ss, const void *addr, asymbol **symp,
156 bfd_vma offset);
157 static void match_global_symbol_sections(struct superbfd *oldsbfd,
158 struct superbfd *newsbfd);
159 static void match_sections_by_name(struct superbfd *oldsbfd,
160 struct superbfd *newsbfd);
161 static void match_sections_by_label(struct superbfd *oldsbfd,
162 struct superbfd *newsbfd);
163 static void mark_new_sections(struct superbfd *sbfd);
164 static void handle_deleted_sections(struct superbfd *oldsbfd,
165 struct superbfd *newsbfd);
166 static void compare_matched_sections(struct superbfd *sbfd);
167 static void update_nonzero_offsets(struct superbfd *sbfd);
168 static void handle_nonzero_offset_relocs(struct supersect *ss);
170 static const char *label_lookup(struct superbfd *sbfd, asymbol *sym);
171 static void print_label_map(struct superbfd *sbfd);
172 static void label_map_set(struct superbfd *sbfd, const char *oldlabel,
173 const char *label);
174 static void init_label_map(struct superbfd *sbfd);
175 static asymbol **symbolp_scan(struct supersect *ss, bfd_vma value);
176 static void init_csyms(struct superbfd *sbfd);
177 static void init_callers(struct superbfd *sbfd);
178 static asymbol *canonical_symbol(struct superbfd *sbfd, asymbol *sym);
179 static asymbol **canonical_symbolp(struct superbfd *sbfd, asymbol *sym);
180 static char *static_local_symbol(struct superbfd *sbfd, asymbol *sym);
181 static char *symbol_label(struct superbfd *sbfd, asymbol *sym);
183 int verbose = 0;
184 #define debug_(sbfd, level, fmt, ...) \
185 do { \
186 if (verbose >= (level)) \
187 printf("%s: " fmt, (sbfd)->abfd->filename, \
188 ## __VA_ARGS__); \
189 } while (0)
190 #define debug0(sbfd, fmt, ...) debug_(sbfd, 0, fmt, ## __VA_ARGS__)
191 #define debug1(sbfd, fmt, ...) debug_(sbfd, 1, fmt, ## __VA_ARGS__)
192 #define err(sbfd, fmt, ...) \
193 do { \
194 fprintf(stderr, "%s: " fmt, (sbfd)->abfd->filename, \
195 ## __VA_ARGS__); \
196 } while (0)
198 struct str_vec delsects, rmsyms;
199 struct export_desc_vec exports;
200 bool changed;
202 struct ksplice_config *config;
204 const char *modestr, *kid;
206 struct superbfd *offsets_sbfd = NULL;
208 #define mode(str) starts_with(modestr, str)
210 DECLARE_VEC_TYPE(unsigned long, addr_vec);
211 DEFINE_HASH_TYPE(struct addr_vec, addr_vec_hash,
212 addr_vec_hash_init, addr_vec_hash_free, addr_vec_hash_lookup,
213 vec_init);
214 struct addr_vec_hash system_map;
216 struct bool_hash system_map_written;
217 struct ulong_hash ksplice_symbol_offset;
218 struct ulong_hash ksplice_string_offset;
220 void load_system_map()
222 const char *config_dir = getenv("KSPLICE_CONFIG_DIR");
223 assert(config_dir);
224 char *file;
225 assert(asprintf(&file, "%s/System.map", config_dir) >= 0);
226 FILE *fp = fopen(file, "r");
227 assert(fp);
228 addr_vec_hash_init(&system_map);
229 unsigned long addr;
230 char type;
231 char *sym;
232 while (fscanf(fp, "%lx %c %as\n", &addr, &type, &sym) == 3)
233 *vec_grow(addr_vec_hash_lookup(&system_map, sym, TRUE),
234 1) = addr;
235 fclose(fp);
238 void load_ksplice_symbol_offsets(struct superbfd *sbfd)
240 asection *sect = bfd_get_section_by_name(sbfd->abfd,
241 ".ksplice_symbols");
242 if (sect == NULL)
243 return;
244 struct supersect *ss = fetch_supersect(sbfd, sect);
246 struct ksplice_symbol *ksym;
247 for (ksym = ss->contents.data;
248 (void *)ksym < ss->contents.data + ss->contents.size; ksym++) {
249 const char *label = read_string(ss, &ksym->label);
250 unsigned long *ksymbol_offp =
251 ulong_hash_lookup(&ksplice_symbol_offset, label, TRUE);
252 *ksymbol_offp = addr_offset(ss, ksym);
256 void load_offsets()
258 char *kmodsrc = getenv("KSPLICE_KMODSRC"), *offsets_file;
259 assert(kmodsrc != NULL);
260 assert(asprintf(&offsets_file, "%s/offsets.o", kmodsrc) >= 0);
261 bfd *offsets_bfd = bfd_openr(offsets_file, NULL);
262 assert(offsets_bfd != NULL);
263 char **matching;
264 assert(bfd_check_format_matches(offsets_bfd, bfd_object, &matching));
265 offsets_sbfd = fetch_superbfd(offsets_bfd);
267 asection *config_sect = bfd_get_section_by_name(offsets_sbfd->abfd,
268 ".ksplice_config");
269 struct supersect *config_ss =
270 fetch_supersect(offsets_sbfd, config_sect);
272 config = config_ss->contents.data;
275 bool matchable_data_section(struct supersect *ss)
277 if (ss->type == SS_TYPE_STRING)
278 return true;
279 if (ss->type == SS_TYPE_RODATA)
280 return true;
281 if (ss->type == SS_TYPE_DATA && ss->relocs.size != 0)
282 return true;
283 return false;
286 bool unchangeable_section(struct supersect *ss)
288 if (ss->type == SS_TYPE_DATA)
289 return true;
290 if (ss->type == SS_TYPE_IGNORED && !starts_with(ss->name, ".debug") &&
291 strcmp(ss->name, "__ksymtab_strings") != 0)
292 return true;
293 return false;
296 int main(int argc, char *argv[])
298 if (getenv("KSPLICE_VERBOSE") != NULL)
299 verbose = atoi(getenv("KSPLICE_VERBOSE"));
301 bfd_init();
302 bfd *ibfd = bfd_openr(argv[1], NULL);
303 assert(ibfd);
305 char **matching;
306 assert(bfd_check_format_matches(ibfd, bfd_object, &matching));
308 const char *output_target = bfd_get_target(ibfd);
309 bfd *obfd = bfd_openw(argv[2], output_target);
310 assert(obfd);
312 struct superbfd *isbfd = fetch_superbfd(ibfd);
313 init_label_map(isbfd);
315 bool_hash_init(&system_map_written);
316 ulong_hash_init(&ksplice_symbol_offset);
317 ulong_hash_init(&ksplice_string_offset);
319 modestr = argv[3];
320 if (mode("keep-primary")) {
321 kid = argv[5];
322 do_keep_primary(isbfd, argv[4]);
323 } else if (mode("keep-helper")) {
324 do_keep_helper(isbfd);
325 } else if (mode("finalize")) {
326 do_finalize(isbfd);
327 } else if (mode("rmsyms")) {
328 do_rmsyms(isbfd);
331 copy_object(ibfd, obfd);
333 if (offsets_sbfd != NULL)
334 assert(bfd_close(offsets_sbfd->abfd));
335 assert(bfd_close(obfd));
336 assert(bfd_close(ibfd));
337 return EXIT_SUCCESS;
340 void do_keep_primary(struct superbfd *isbfd, const char *pre)
342 struct bfd *prebfd = bfd_openr(pre, NULL);
343 assert(prebfd != NULL);
344 char **matching;
345 assert(bfd_check_format_matches(prebfd, bfd_object, &matching));
347 struct superbfd *presbfd = fetch_superbfd(prebfd);
348 init_label_map(presbfd);
349 load_system_map();
350 load_offsets();
351 initialize_supersect_types(isbfd);
352 initialize_supersect_types(presbfd);
354 match_global_symbol_sections(presbfd, isbfd);
355 debug1(isbfd, "Matched global\n");
356 match_sections_by_name(presbfd, isbfd);
357 debug1(isbfd, "Matched by name\n");
358 match_sections_by_label(presbfd, isbfd);
359 debug1(isbfd, "Matched by label\n");
361 do {
362 changed = false;
363 compare_matched_sections(isbfd);
364 update_nonzero_offsets(isbfd);
365 mark_new_sections(isbfd);
366 } while (changed);
367 vec_init(&delsects);
369 handle_deleted_sections(presbfd, isbfd);
370 handle_section_symbol_renames(presbfd, isbfd);
372 vec_init(&exports);
373 compare_exported_symbols(presbfd, isbfd, false);
374 compare_exported_symbols(isbfd, presbfd, true);
376 initialize_spans(isbfd);
377 initialize_spans(presbfd);
378 asection *sect;
379 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
380 struct supersect *ss = fetch_supersect(isbfd, sect);
381 if (ss->type != SS_TYPE_STRING)
382 continue;
383 asection *oldsect = bfd_get_section_by_name(prebfd, sect->name);
384 if (oldsect == NULL)
385 continue;
386 struct supersect *old_ss = fetch_supersect(presbfd, oldsect);
387 struct span *span, *old_span;
388 for (span = ss->spans.data;
389 span < ss->spans.data + ss->spans.size; span++) {
390 span->new = true;
391 for (old_span = old_ss->spans.data;
392 old_span < old_ss->spans.data + old_ss->spans.size;
393 old_span++) {
394 if (strcmp((char *)ss->contents.data +
395 span->start,
396 (char *)old_ss->contents.data +
397 old_span->start) == 0) {
398 if (!span->new)
399 DIE;
400 span->label = old_span->label;
401 span->new = false;
406 assert(bfd_close(prebfd));
408 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
409 struct supersect *ss = fetch_supersect(isbfd, sect);
410 ss->keep = false;
411 if (ss->type == SS_TYPE_STRING || ss->type == SS_TYPE_SPECIAL ||
412 ss->type == SS_TYPE_EXPORT)
413 ss->keep = true;
414 if (ss->new || ss->patch)
415 ss->keep = true;
418 print_label_map(isbfd);
420 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
421 struct supersect *ss = fetch_supersect(isbfd, sect);
422 if (ss->patch)
423 debug0(isbfd, "Patching section: %s\n", sect->name);
426 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
427 struct supersect *ss = fetch_supersect(isbfd, sect);
428 if (ss->new)
429 debug0(isbfd, "New section: %s\n", sect->name);
432 const char **sectname;
433 for (sectname = delsects.data;
434 sectname < delsects.data + delsects.size; sectname++)
435 debug0(isbfd, "Deleted section: %s\n", *sectname);
437 const struct export_desc *ed;
438 for (ed = exports.data; ed < exports.data + exports.size; ed++) {
439 const char **symname;
440 for (symname = ed->names.data;
441 symname < ed->names.data + ed->names.size; symname++)
442 debug0(isbfd, "Export %s (%s): %s\n",
443 ed->deletion ? "deletion" : "addition",
444 ed->export_type, *symname);
447 struct span *span;
448 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
449 struct supersect *ss = fetch_supersect(isbfd, sect);
450 for (span = ss->spans.data;
451 span < ss->spans.data + ss->spans.size; span++)
452 span->keep = ss->keep;
455 filter_table_sections(isbfd);
456 for (ed = exports.data; ed < exports.data + exports.size; ed++) {
457 const char **symname;
458 for (symname = ed->names.data;
459 symname < ed->names.data + ed->names.size; symname++)
460 write_ksplice_export(isbfd, *symname,
461 ed->export_type, ed->deletion);
462 if (!ed->deletion)
463 rm_some_exports(isbfd, ed);
466 compute_span_shifts(isbfd);
468 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
469 struct supersect *ss = fetch_supersect(isbfd, sect);
470 if (!ss->patch && !ss->new)
471 continue;
473 struct span *span;
474 for (span = ss->spans.data;
475 span < ss->spans.data + ss->spans.size; span++)
476 write_ksplice_section(span);
478 if (ss->patch)
479 write_ksplice_patch(isbfd, sect->name);
482 rm_relocs(isbfd);
483 remove_unkept_spans(isbfd);
486 void do_keep_helper(struct superbfd *isbfd)
488 load_system_map();
489 load_offsets();
490 initialize_supersect_types(isbfd);
491 initialize_spans(isbfd);
493 asection *sect;
494 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
495 struct supersect *ss = fetch_supersect(isbfd, sect);
496 ss->keep = false;
497 if (ss->type == SS_TYPE_SPECIAL || ss->type == SS_TYPE_TEXT)
498 ss->keep = true;
501 asymbol **symp;
502 for (symp = isbfd->syms.data;
503 symp < isbfd->syms.data + isbfd->syms.size; symp++) {
504 asymbol *sym = *symp;
505 if (!bfd_is_const_section(sym->section) &&
506 (sym->flags & BSF_GLOBAL) != 0) {
507 struct supersect *sym_ss =
508 fetch_supersect(isbfd, sym->section);
509 if (sym_ss->type != SS_TYPE_IGNORED)
510 sym_ss->keep = true;
514 struct span *span;
515 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
516 struct supersect *ss = fetch_supersect(isbfd, sect);
517 for (span = ss->spans.data;
518 span < ss->spans.data + ss->spans.size; span++)
519 span->keep = ss->keep;
522 do {
523 changed = false;
524 keep_referenced_sections(isbfd);
525 } while (changed);
527 filter_table_sections(isbfd);
528 compute_span_shifts(isbfd);
530 for (sect = isbfd->abfd->sections; sect != NULL; sect = sect->next) {
531 struct supersect *ss = fetch_supersect(isbfd, sect);
532 asymbol *sym = canonical_symbol(isbfd, sect->symbol);
533 if (sym == NULL)
534 continue;
535 if ((sym->flags & BSF_WEAK) != 0)
536 continue;
537 if (bfd_get_section_size(sect) == 0)
538 continue;
539 if (!ss->keep)
540 continue;
541 if (ss->type != SS_TYPE_TEXT && !matchable_data_section(ss))
542 continue;
544 struct span *span;
545 for (span = ss->spans.data;
546 span < ss->spans.data + ss->spans.size; span++) {
547 if (span->keep)
548 write_ksplice_section(span);
552 rm_relocs(isbfd);
553 remove_unkept_spans(isbfd);
556 void do_finalize(struct superbfd *isbfd)
558 load_system_map();
559 load_ksplice_symbol_offsets(isbfd);
560 load_offsets();
561 initialize_supersect_types(isbfd);
562 initialize_spans(isbfd);
563 rm_relocs(isbfd);
566 void do_rmsyms(struct superbfd *isbfd)
568 read_str_set(&rmsyms);
569 load_system_map();
570 load_offsets();
571 initialize_supersect_types(isbfd);
572 initialize_spans(isbfd);
573 rm_relocs(isbfd);
576 struct export_vec *get_export_syms(struct superbfd *sbfd)
578 asection *sect;
579 struct export_vec *exports;
580 exports = malloc(sizeof(*exports));
581 assert(exports != NULL);
582 vec_init(exports);
584 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
585 if (!starts_with(sect->name, "__ksymtab") ||
586 ends_with(sect->name, "_strings"))
587 continue;
588 struct supersect *ss = fetch_supersect(sbfd, sect);
589 struct kernel_symbol *sym;
590 assert(ss->contents.size * 2 == ss->relocs.size *
591 sizeof(struct kernel_symbol));
592 for (sym = ss->contents.data;
593 (void *)sym < ss->contents.data + ss->contents.size;
594 sym++) {
595 struct export *exp = vec_grow(exports, 1);
596 exp->name =
597 read_string(ss, (const char *const *)&sym->name);
598 exp->ss = ss;
601 return exports;
604 struct export_desc *new_export_desc(struct supersect *ss, bool deletion)
606 struct export_desc *ed = vec_grow(&exports, 1);
607 ed->deletion = deletion;
608 vec_init(&ed->names);
609 ed->export_type = strdup(ss->name) + strlen("__ksymtab");
610 ed->sym_ss = ss;
611 char *crc_sect_name;
612 assert(asprintf(&crc_sect_name, "__kcrctab%s", ed->export_type) >= 0);
613 asection *crc_sect =
614 bfd_get_section_by_name(ss->parent->abfd, crc_sect_name);
615 if (crc_sect == NULL)
616 ed->crc_ss = NULL;
617 else
618 ed->crc_ss = fetch_supersect(ss->parent, crc_sect);
619 return ed;
622 void compare_exported_symbols(struct superbfd *oldsbfd,
623 struct superbfd *newsbfd, bool deletion)
625 struct export_vec *new_exports, *old_exports;
626 new_exports = get_export_syms(newsbfd);
627 if (new_exports == NULL)
628 return;
629 old_exports = get_export_syms(oldsbfd);
630 struct export *old, *new;
631 struct supersect *last_ss = NULL;
632 struct export_desc *ed = NULL;
633 for (new = new_exports->data; new < new_exports->data +
634 new_exports->size; new++) {
635 bool found = false;
636 if (old_exports != NULL) {
637 for (old = old_exports->data; old < old_exports->data +
638 old_exports->size; old++) {
639 if (strcmp(new->name, old->name) == 0 &&
640 strcmp(new->ss->name, old->ss->name) == 0) {
641 found = true;
642 break;
646 if (last_ss != new->ss) {
647 last_ss = new->ss;
648 ed = new_export_desc(new->ss, deletion);
650 if (!found)
651 *vec_grow(&ed->names, 1) = new->name;
655 void match_sections(struct supersect *oldss, struct supersect *newss)
657 if (oldss->match == newss && newss->match == oldss)
658 return;
659 if (oldss->match != NULL) {
660 err(newss->parent, "Matching conflict: old %s: %s != %s\n",
661 oldss->name, oldss->match->name, newss->name);
662 DIE;
664 if (newss->match != NULL) {
665 err(newss->parent, "Matching conflict: new %s: %s != %s\n",
666 newss->name, newss->match->name, oldss->name);
667 DIE;
669 oldss->match = newss;
670 newss->match = oldss;
671 debug1(newss->parent, "Matched old %s to new %s\n",
672 oldss->name, newss->name);
675 static void match_global_symbol_sections(struct superbfd *oldsbfd,
676 struct superbfd *newsbfd)
678 asymbol **oldsymp, **newsymp;
679 for (oldsymp = oldsbfd->syms.data;
680 oldsymp < oldsbfd->syms.data + oldsbfd->syms.size; oldsymp++) {
681 asymbol *oldsym = *oldsymp;
682 if ((oldsym->flags & BSF_GLOBAL) == 0 ||
683 bfd_is_const_section(oldsym->section))
684 continue;
685 for (newsymp = newsbfd->syms.data;
686 newsymp < newsbfd->syms.data + newsbfd->syms.size;
687 newsymp++) {
688 asymbol *newsym = *newsymp;
689 if ((newsym->flags & BSF_GLOBAL) == 0 ||
690 bfd_is_const_section(oldsym->section))
691 continue;
692 if (strcmp(oldsym->name, newsym->name) != 0)
693 continue;
694 struct supersect *oldss =
695 fetch_supersect(oldsbfd, oldsym->section);
696 struct supersect *newss =
697 fetch_supersect(newsbfd, newsym->section);
698 match_sections(oldss, newss);
703 static void match_sections_by_name(struct superbfd *oldsbfd,
704 struct superbfd *newsbfd)
706 asection *newp, *oldp;
707 for (newp = newsbfd->abfd->sections; newp != NULL; newp = newp->next) {
708 struct supersect *newss = fetch_supersect(newsbfd, newp);
709 oldp = bfd_get_section_by_name(oldsbfd->abfd, newp->name);
710 if (oldp == NULL || newss->type == SS_TYPE_STRING ||
711 newss->type == SS_TYPE_SPECIAL ||
712 newss->type == SS_TYPE_EXPORT)
713 continue;
714 if (static_local_symbol(newsbfd,
715 canonical_symbol(newsbfd,
716 newp->symbol)))
717 continue;
719 struct supersect *oldss = fetch_supersect(oldsbfd, oldp);
720 match_sections(oldss, newss);
724 static void match_sections_by_label(struct superbfd *oldsbfd,
725 struct superbfd *newsbfd)
727 asection *oldsect, *newsect;
728 struct supersect *oldss, *newss;
729 for (newsect = newsbfd->abfd->sections; newsect != NULL;
730 newsect = newsect->next) {
731 newss = fetch_supersect(newsbfd, newsect);
732 if (newss->type == SS_TYPE_STRING ||
733 newss->type == SS_TYPE_SPECIAL ||
734 newss->type == SS_TYPE_EXPORT)
735 continue;
736 for (oldsect = oldsbfd->abfd->sections; oldsect != NULL;
737 oldsect = oldsect->next) {
738 if (strcmp(label_lookup(newsbfd, newsect->symbol),
739 label_lookup(oldsbfd, oldsect->symbol)) != 0)
740 continue;
741 oldss = fetch_supersect(oldsbfd, oldsect);
742 match_sections(oldss, newss);
747 static void mark_new_sections(struct superbfd *sbfd)
749 asection *sect;
750 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
751 struct supersect *ss = fetch_supersect(sbfd, sect);
752 if (ss->type == SS_TYPE_STRING || ss->type == SS_TYPE_SPECIAL ||
753 ss->type == SS_TYPE_IGNORED || ss->type == SS_TYPE_EXPORT)
754 continue;
755 if (ss->match == NULL)
756 ss->new = true;
760 static void handle_deleted_sections(struct superbfd *oldsbfd,
761 struct superbfd *newsbfd)
763 asection *sect;
764 for (sect = oldsbfd->abfd->sections; sect != NULL; sect = sect->next) {
765 struct supersect *ss = fetch_supersect(oldsbfd, sect);
766 if (ss->type != SS_TYPE_TEXT)
767 continue;
768 if (ss->match != NULL)
769 continue;
770 const char *label = label_lookup(oldsbfd, sect->symbol);
771 *vec_grow(&delsects, 1) = label;
772 asymbol *csym = canonical_symbol(oldsbfd, sect->symbol);
773 write_ksplice_deleted_patch(newsbfd, csym->name, label);
777 static void handle_nonzero_offset_relocs(struct supersect *ss)
779 int i;
780 for (i = 0; i < ss->relocs.size; i++) {
781 asymbol *sym = *ss->relocs.data[i]->sym_ptr_ptr;
782 bfd_vma offset = get_reloc_offset(ss, ss->relocs.data[i], true);
783 if (sym->value + offset == 0)
784 continue;
785 if (bfd_is_const_section(sym->section))
786 continue;
787 struct supersect *sym_ss = fetch_supersect(ss->parent,
788 sym->section);
789 if (sym_ss->type != SS_TYPE_TEXT)
790 continue;
791 if (!sym_ss->patch) {
792 changed = true;
793 debug1(ss->parent,
794 "Changing %s because a relocation from sect %s "
795 "has a nonzero offset %lx+%lx into it\n",
796 sym_ss->name, ss->name,
797 (unsigned long)sym->value,
798 (unsigned long)offset);
800 sym_ss->patch = true;
804 static void update_nonzero_offsets(struct superbfd *sbfd)
806 asection *sect;
807 struct supersect *ss;
809 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
810 ss = fetch_supersect(sbfd, sect);
811 if (ss->new || ss->patch)
812 handle_nonzero_offset_relocs(ss);
816 static void compare_matched_sections(struct superbfd *newsbfd)
818 asection *newp;
819 struct supersect *old_ss, *new_ss;
820 for (newp = newsbfd->abfd->sections; newp != NULL; newp = newp->next) {
821 new_ss = fetch_supersect(newsbfd, newp);
822 if (new_ss->match == NULL)
823 continue;
824 old_ss = new_ss->match;
826 if (nonrelocs_equal(old_ss, new_ss) &&
827 all_relocs_equal(old_ss, new_ss))
828 continue;
830 char *reason;
831 if (new_ss->contents.size != old_ss->contents.size)
832 reason = "differing sizes";
833 else if (memcmp(new_ss->contents.data, old_ss->contents.data,
834 new_ss->contents.size) != 0)
835 reason = "differing contents";
836 else
837 reason = "differing relocations";
838 if (new_ss->type == SS_TYPE_TEXT) {
839 if (new_ss->patch)
840 continue;
841 new_ss->patch = true;
842 debug1(newsbfd, "Changing %s due to %s\n", new_ss->name,
843 reason);
844 } else {
845 debug1(newsbfd, "Unmatching %s and %s due to %s\n",
846 old_ss->name, new_ss->name, reason);
847 new_ss->match = NULL;
848 old_ss->match = NULL;
850 changed = true;
851 if (unchangeable_section(new_ss))
852 err(newsbfd, "warning: ignoring change to nonpatchable "
853 "section %s\n", new_ss->name);
857 static void handle_section_symbol_renames(struct superbfd *oldsbfd,
858 struct superbfd *newsbfd)
860 asection *newp, *oldp;
861 for (newp = newsbfd->abfd->sections; newp != NULL; newp = newp->next) {
862 struct supersect *newss = fetch_supersect(newsbfd, newp);
863 if (newss->match == NULL)
864 continue;
865 oldp = bfd_get_section_by_name(oldsbfd->abfd,
866 newss->match->name);
867 if (oldp == NULL)
868 continue;
870 const char *old_label = label_lookup(oldsbfd, oldp->symbol);
871 const char *new_label = label_lookup(newsbfd, newp->symbol);
873 if (strcmp(old_label, new_label) == 0)
874 continue;
875 label_map_set(newsbfd, new_label, old_label);
879 static bool part_of_reloc(struct supersect *ss, unsigned long addr)
881 arelent **relocp;
882 for (relocp = ss->relocs.data;
883 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
884 arelent *reloc = *relocp;
885 if (addr >= reloc->address &&
886 addr < reloc->address + reloc->howto->size)
887 return true;
889 return false;
892 static bool nonrelocs_equal(struct supersect *old_ss, struct supersect *new_ss)
894 int i;
895 if (old_ss->contents.size != new_ss->contents.size)
896 return false;
897 const unsigned char *old = old_ss->contents.data;
898 const unsigned char *new = new_ss->contents.data;
899 for (i = 0; i < old_ss->contents.size; i++) {
900 if (old[i] != new[i] &&
901 !(part_of_reloc(old_ss, i) && part_of_reloc(new_ss, i)))
902 return false;
904 return true;
907 bool relocs_equal(struct supersect *old_src_ss, struct supersect *new_src_ss,
908 arelent *old_reloc, arelent *new_reloc)
910 if (old_reloc->address != new_reloc->address)
911 return false;
913 struct superbfd *oldsbfd = old_src_ss->parent;
914 struct superbfd *newsbfd = new_src_ss->parent;
915 asymbol *old_sym = *old_reloc->sym_ptr_ptr;
916 asymbol *new_sym = *new_reloc->sym_ptr_ptr;
917 asection *old_sect = old_sym->section;
918 asection *new_sect = new_sym->section;
920 bfd_vma old_offset = get_reloc_offset(old_src_ss, old_reloc, true);
921 bfd_vma new_offset = get_reloc_offset(new_src_ss, new_reloc, true);
923 if (bfd_is_und_section(old_sect) || bfd_is_und_section(new_sect)) {
924 if (!bfd_is_und_section(new_sect) && old_offset != 0 &&
925 fetch_supersect(newsbfd, new_sect)->type == SS_TYPE_TEXT)
926 return false;
928 if (!bfd_is_und_section(new_sect) && new_offset != 0 &&
929 fetch_supersect(oldsbfd, old_sect)->type == SS_TYPE_TEXT)
930 return false;
932 return strcmp(old_sym->name, new_sym->name) == 0 &&
933 old_offset == new_offset;
936 if (bfd_is_const_section(old_sect) || bfd_is_const_section(new_sect))
937 DIE;
939 struct supersect *old_ss = fetch_supersect(oldsbfd, old_sect);
940 struct supersect *new_ss = fetch_supersect(newsbfd, new_sect);
942 if (old_ss->type == SS_TYPE_STRING &&
943 /* check it's not an out-of-range relocation to a string;
944 we'll just compare entire sections for them */
945 !(old_offset >= old_ss->contents.size ||
946 new_offset >= new_ss->contents.size)) {
947 if (strcmp(old_ss->contents.data + old_sym->value + old_offset,
948 new_ss->contents.data + new_sym->value + new_offset)
949 != 0) {
950 debug0(newsbfd, "Section %s/%s has string difference "
951 "\"%s\"/\"%s\"\n", old_src_ss->name,
952 new_src_ss->name,
953 (const char *)(old_ss->contents.data +
954 old_sym->value + old_offset),
955 (const char *)(new_ss->contents.data +
956 new_sym->value + new_offset));
957 debug1(newsbfd, "Strings differ between %s and %s\n",
958 old_src_ss->name, new_src_ss->name);
959 return false;
961 return true;
964 if (old_ss->match != new_ss || new_ss->match != old_ss) {
965 debug1(newsbfd, "Nonmatching relocs from %s to %s/%s\n",
966 new_src_ss->name, new_ss->name, old_ss->name);
967 return false;
970 if (old_sym->value + old_offset != new_sym->value + new_offset) {
971 debug1(newsbfd, "Offsets to %s/%s differ between %s "
972 "and %s: %lx+%lx/%lx+%lx\n", old_ss->name,
973 new_ss->name, old_src_ss->name, new_src_ss->name,
974 (unsigned long)old_sym->value, (unsigned long)old_offset,
975 (unsigned long)new_sym->value,
976 (unsigned long)new_offset);
977 return false;
980 if ((old_sym->value + old_offset != 0 ||
981 new_sym->value + new_offset != 0) && new_ss->patch) {
982 debug1(newsbfd, "Relocation from %s to nonzero offsets "
983 "%lx+%lx/%lx+%lx in changed section %s\n",
984 new_src_ss->name, (unsigned long)old_sym->value,
985 (unsigned long)old_offset, (unsigned long)new_sym->value,
986 (unsigned long)new_offset, new_sym->section->name);
987 return false;
989 return true;
992 bool all_relocs_equal(struct supersect *old_ss, struct supersect *new_ss)
994 if (old_ss->relocs.size != new_ss->relocs.size) {
995 debug1(new_ss->parent, "Different reloc count between %s and "
996 "%s\n", old_ss->name, new_ss->name);
997 return false;
1000 int i;
1001 for (i = 0; i < old_ss->relocs.size; i++) {
1002 if (!relocs_equal(old_ss, new_ss, old_ss->relocs.data[i],
1003 new_ss->relocs.data[i]))
1004 return false;
1007 return true;
1010 void rm_some_exports(struct superbfd *sbfd, const struct export_desc *ed)
1012 struct supersect *ss = ed->sym_ss;
1013 struct supersect *crc_ss = ed->crc_ss;
1014 if (crc_ss != NULL)
1015 assert(ss->contents.size * sizeof(unsigned long) ==
1016 crc_ss->contents.size * sizeof(struct kernel_symbol));
1018 struct kernel_symbol *ksym;
1019 unsigned long *crc = NULL;
1020 if (crc_ss != NULL)
1021 crc = crc_ss->contents.data;
1022 struct span *span, *crc_span;
1023 for (ksym = ss->contents.data;
1024 (void *)ksym < ss->contents.data + ss->contents.size;
1025 ksym++, crc++) {
1026 asymbol *sym;
1027 read_reloc(ss, &ksym->value, sizeof(ksym->value), &sym);
1028 span = new_span(ss, addr_offset(ss, ksym), sizeof(*ksym));
1029 span->keep = str_in_set(sym->name, &ed->names);
1031 if (crc_ss != NULL) {
1032 crc_span = new_span(crc_ss, addr_offset(crc_ss, crc),
1033 sizeof(*crc));
1034 crc_span->keep = span->keep;
1037 if (span->keep) {
1038 /* Replace name with a mangled name */
1039 write_string(ss, (const char **)&ksym->name,
1040 "DISABLED_%s_%s", sym->name, kid);
1045 void rm_relocs(struct superbfd *isbfd)
1047 asection *p;
1048 for (p = isbfd->abfd->sections; p != NULL; p = p->next) {
1049 struct supersect *ss = fetch_supersect(isbfd, p);
1050 if ((mode("keep") && ss->type == SS_TYPE_SPECIAL) ||
1051 ss->type == SS_TYPE_KSPLICE)
1052 continue;
1053 if (ss->keep || mode("rmsyms"))
1054 rm_some_relocs(ss);
1056 if (mode("finalize")) {
1057 p = bfd_get_section_by_name(isbfd->abfd, ".ksplice_patches");
1058 if (p != NULL) {
1059 struct supersect *ss = fetch_supersect(isbfd, p);
1060 rm_some_relocs(ss);
1062 p = bfd_get_section_by_name(isbfd->abfd, ".ksplice_relocs");
1063 if (p != NULL) {
1064 struct supersect *ss = fetch_supersect(isbfd, p);
1065 rm_some_relocs(ss);
1070 void rm_some_relocs(struct supersect *ss)
1072 struct arelentp_vec orig_relocs;
1073 vec_move(&orig_relocs, &ss->relocs);
1075 arelent **relocp;
1076 for (relocp = orig_relocs.data;
1077 relocp < orig_relocs.data + orig_relocs.size; relocp++) {
1078 bool rm_reloc = false;
1079 asymbol *sym_ptr = *(*relocp)->sym_ptr_ptr;
1081 if (mode("rmsyms") && str_in_set(sym_ptr->name, &rmsyms) &&
1082 bfd_is_und_section(sym_ptr->section))
1083 rm_reloc = true;
1085 if (mode("keep"))
1086 rm_reloc = true;
1088 if (mode("keep-primary") &&
1089 (bfd_is_const_section(sym_ptr->section) ||
1090 fetch_supersect(ss->parent, sym_ptr->section)->new ||
1091 reloc_target_span(ss, *relocp)->new ||
1092 !reloc_address_span(ss, *relocp)->keep))
1093 rm_reloc = false;
1095 if (mode("finalize") && bfd_is_und_section(sym_ptr->section))
1096 rm_reloc = true;
1098 if (strcmp(sym_ptr->name, "mcount") == 0 &&
1099 bfd_is_und_section(sym_ptr->section))
1100 rm_reloc = false;
1102 if (rm_reloc)
1103 write_ksplice_reloc(ss, *relocp);
1104 else
1105 *vec_grow(&ss->relocs, 1) = *relocp;
1109 struct supersect *make_section(struct superbfd *sbfd, const char *name)
1111 asection *sect = bfd_get_section_by_name(sbfd->abfd, name);
1112 if (sect != NULL)
1113 return fetch_supersect(sbfd, sect);
1114 else
1115 return new_supersect(sbfd, name);
1118 arelent *create_reloc(struct supersect *ss, const void *addr, asymbol **symp,
1119 bfd_vma offset)
1121 bfd_reloc_code_real_type code;
1122 switch (bfd_arch_bits_per_address(ss->parent->abfd)) {
1123 case 32:
1124 code = BFD_RELOC_32;
1125 break;
1126 case 64:
1127 code = BFD_RELOC_64;
1128 break;
1129 default:
1130 DIE;
1133 arelent *reloc = malloc(sizeof(*reloc));
1134 reloc->sym_ptr_ptr = symp;
1135 reloc->address = addr_offset(ss, addr);
1136 reloc->howto = bfd_reloc_type_lookup(ss->parent->abfd, code);
1137 reloc->addend = offset;
1138 return reloc;
1141 void write_reloc(struct supersect *ss, const void *addr, asymbol **symp,
1142 bfd_vma offset)
1144 *vec_grow(&ss->new_relocs, 1) = create_reloc(ss, addr, symp, offset);
1147 void write_string(struct supersect *ss, const char **addr, const char *fmt, ...)
1149 va_list ap;
1150 struct supersect *str_ss = make_section(ss->parent, ".ksplice_str");
1151 char *str;
1152 va_start(ap, fmt);
1153 int len = vasprintf(&str, fmt, ap);
1154 assert(len >= 0);
1155 va_end(ap);
1157 unsigned long *str_offp = ulong_hash_lookup(&ksplice_string_offset, str,
1158 FALSE);
1159 if (str_offp == NULL) {
1160 char *buf = sect_grow(str_ss, len + 1, char);
1161 memcpy(buf, str, len + 1);
1162 str_offp = ulong_hash_lookup(&ksplice_string_offset, str, TRUE);
1163 *str_offp = addr_offset(str_ss, buf);
1166 write_reloc(ss, addr, &str_ss->symbol, *str_offp);
1169 void lookup_system_map(struct addr_vec *addrs, const char *name, long offset)
1171 struct addr_vec *map_addrs =
1172 addr_vec_hash_lookup(&system_map, name, FALSE);
1173 if (map_addrs == NULL)
1174 return;
1176 unsigned long *addr, *map_addr;
1177 for (map_addr = map_addrs->data;
1178 map_addr < map_addrs->data + map_addrs->size; map_addr++) {
1179 for (addr = addrs->data; addr < addrs->data + addrs->size;
1180 addr++) {
1181 if (*addr == *map_addr + offset)
1182 break;
1184 if (addr < addrs->data + addrs->size)
1185 continue;
1186 *vec_grow(addrs, 1) = *map_addr + offset;
1190 void compute_system_map_array(struct superbfd *sbfd, struct addr_vec *addrs,
1191 asymbol *sym)
1193 if (bfd_is_abs_section(sym->section)) {
1194 *vec_grow(addrs, 1) = sym->value;
1195 } else if (bfd_is_und_section(sym->section)) {
1196 lookup_system_map(addrs, sym->name, 0);
1197 } else if (!bfd_is_const_section(sym->section)) {
1198 asymbol **gsymp;
1199 for (gsymp = sbfd->syms.data;
1200 gsymp < sbfd->syms.data + sbfd->syms.size; gsymp++) {
1201 asymbol *gsym = *gsymp;
1202 if ((gsym->flags & BSF_DEBUGGING) == 0 &&
1203 gsym->section == sym->section)
1204 lookup_system_map(addrs, gsym->name,
1205 sym->value - gsym->value);
1210 void write_ksplice_system_map(struct superbfd *sbfd, asymbol *sym,
1211 const char *label)
1213 bool *done = bool_hash_lookup(&system_map_written, label, TRUE);
1214 if (*done)
1215 return;
1216 *done = true;
1218 struct addr_vec addrs;
1219 vec_init(&addrs);
1221 compute_system_map_array(sbfd, &addrs, sym);
1222 if (addrs.size != 0) {
1223 struct supersect *smap_ss =
1224 make_section(sbfd, ".ksplice_system_map");
1225 struct ksplice_system_map *smap =
1226 sect_grow(smap_ss, 1, struct ksplice_system_map);
1227 write_string(smap_ss, &smap->label, "%s", label);
1229 struct supersect *array_ss = make_section(sbfd,
1230 ".ksplice_array");
1231 void *buf = sect_grow(array_ss, addrs.size,
1232 typeof(*addrs.data));
1233 memcpy(buf, addrs.data, addrs.size * sizeof(*addrs.data));
1234 smap->nr_candidates = addrs.size;
1235 write_reloc(smap_ss, &smap->candidates, &array_ss->symbol,
1236 addr_offset(array_ss, buf));
1238 vec_free(&addrs);
1241 void write_ksplice_symbol_backend(struct supersect *ss,
1242 struct ksplice_symbol *const *addr,
1243 asymbol *sym, const char *label,
1244 const char *name)
1246 struct supersect *ksymbol_ss = make_section(ss->parent,
1247 ".ksplice_symbols");
1248 struct ksplice_symbol *ksymbol;
1249 unsigned long *ksymbol_offp;
1251 ksymbol_offp = ulong_hash_lookup(&ksplice_symbol_offset, label, FALSE);
1252 if (ksymbol_offp != NULL) {
1253 write_reloc(ss, addr, &ksymbol_ss->symbol, *ksymbol_offp);
1254 return;
1256 ksymbol = sect_grow(ksymbol_ss, 1, struct ksplice_symbol);
1257 ksymbol_offp = ulong_hash_lookup(&ksplice_symbol_offset, label, TRUE);
1258 *ksymbol_offp = addr_offset(ksymbol_ss, ksymbol);
1260 write_reloc(ss, addr, &ksymbol_ss->symbol, *ksymbol_offp);
1261 write_string(ksymbol_ss, &ksymbol->label, "%s", label);
1262 if (name != NULL) {
1263 write_string(ksymbol_ss, &ksymbol->name, "%s", name);
1264 write_ksplice_system_map(ksymbol_ss->parent, sym, label);
1268 void write_ksplice_symbol(struct supersect *ss,
1269 struct ksplice_symbol *const *addr,
1270 asymbol *sym, struct span *span,
1271 const char *addstr_sect)
1273 const char *label, *name;
1274 char *output;
1275 if (span != NULL && span->start != 0)
1276 label = span->label;
1277 else
1278 label = label_lookup(ss->parent, sym);
1280 assert(asprintf(&output, "%s%s", label, addstr_sect) >= 0);
1282 asymbol *gsym = canonical_symbol(ss->parent, sym);
1283 if (strcmp(addstr_sect, "") != 0)
1284 name = NULL;
1285 else if (bfd_is_und_section(sym->section))
1286 name = sym->name;
1287 else if (bfd_is_const_section(sym->section))
1288 name = NULL;
1289 else if (span != NULL && span->symbol == NULL)
1290 name = NULL;
1291 else if (gsym == NULL || (gsym->flags & BSF_SECTION_SYM) != 0)
1292 name = NULL;
1293 else
1294 name = gsym->name;
1296 write_ksplice_symbol_backend(ss, addr, sym, output, name);
1299 void write_ksplice_reloc(struct supersect *ss, arelent *orig_reloc)
1301 asymbol *sym_ptr = *orig_reloc->sym_ptr_ptr;
1302 reloc_howto_type *howto = orig_reloc->howto;
1303 bfd_vma addend = get_reloc_offset(ss, orig_reloc, false);
1304 unsigned long *repladdr = ss->contents.data + orig_reloc->address;
1306 if (mode("finalize") && strcmp(ss->name, ".ksplice_patches") == 0) {
1307 *repladdr = 0;
1308 return;
1310 if (mode("finalize") && strcmp(ss->name, ".ksplice_relocs") == 0) {
1311 assert(starts_with(sym_ptr->name, KSPLICE_SYMBOL_STR));
1312 asymbol fake_sym;
1313 fake_sym.name = sym_ptr->name + strlen(KSPLICE_SYMBOL_STR);
1314 fake_sym.section = bfd_und_section_ptr;
1315 fake_sym.value = 0;
1316 fake_sym.flags = 0;
1318 write_ksplice_symbol_backend
1319 (ss, (struct ksplice_symbol **)repladdr, &fake_sym,
1320 fake_sym.name, fake_sym.name);
1321 return;
1324 struct span *span = reloc_target_span(ss, orig_reloc);
1325 if (span == ss->spans.data && span->start != addend)
1326 span = NULL;
1327 blot_section(ss, orig_reloc->address, howto);
1329 struct supersect *kreloc_ss = make_section(ss->parent,
1330 mode("rmsyms") ?
1331 ".ksplice_init_relocs" :
1332 ".ksplice_relocs");
1333 struct ksplice_reloc *kreloc = sect_grow(kreloc_ss, 1,
1334 struct ksplice_reloc);
1336 struct span *address_span = reloc_address_span(ss, orig_reloc);
1337 write_reloc(kreloc_ss, &kreloc->blank_addr,
1338 &ss->symbol, orig_reloc->address + address_span->shift);
1339 if (bfd_is_und_section(sym_ptr->section) && mode("keep")) {
1340 char *name;
1341 assert(asprintf(&name, KSPLICE_SYMBOL_STR "%s", sym_ptr->name)
1342 >= 0);
1343 asymbol **symp = make_undefined_symbolp(ss->parent, name);
1344 write_reloc(kreloc_ss, &kreloc->symbol, symp, 0);
1345 } else {
1346 write_ksplice_symbol(kreloc_ss, &kreloc->symbol, sym_ptr, span,
1347 "");
1349 kreloc->pcrel = howto->pc_relative;
1350 if (span != NULL && span->start != 0)
1351 addend += sym_ptr->value - span->start;
1352 kreloc->addend = addend;
1353 kreloc->size = bfd_get_reloc_size(howto);
1354 kreloc->dst_mask = howto->dst_mask;
1355 kreloc->rightshift = howto->rightshift;
1356 kreloc->signed_addend =
1357 (howto->complain_on_overflow == complain_overflow_signed) ||
1358 (howto->complain_on_overflow == complain_overflow_bitfield);
1361 #define CANARY(x, canary) ((x & ~howto->dst_mask) | (canary & howto->dst_mask))
1363 void blot_section(struct supersect *ss, int offset, reloc_howto_type *howto)
1365 int bits = bfd_get_reloc_size(howto) * 8;
1366 void *address = ss->contents.data + offset;
1367 bfd_vma x = bfd_get(bits, ss->parent->abfd, address);
1368 x = (x & ~howto->dst_mask) |
1369 ((bfd_vma)KSPLICE_CANARY & howto->dst_mask);
1370 bfd_put(bits, ss->parent->abfd, x, address);
1373 static void write_ksplice_section(struct span *span)
1375 struct supersect *ss = span->ss;
1376 struct supersect *ksect_ss =
1377 make_section(ss->parent, ".ksplice_sections");
1378 struct ksplice_section *ksect = sect_grow(ksect_ss, 1,
1379 struct ksplice_section);
1380 asymbol *sym = span->symbol == NULL ? ss->symbol : span->symbol;
1382 write_ksplice_symbol(ksect_ss, &ksect->symbol, sym, span,
1383 mode("keep-primary") ? "(post)" : "");
1384 ksect->size = span->size;
1385 ksect->flags = 0;
1387 if (ss->type == SS_TYPE_RODATA || ss->type == SS_TYPE_STRING)
1388 ksect->flags |= KSPLICE_SECTION_RODATA;
1389 if (ss->type == SS_TYPE_DATA)
1390 ksect->flags |= KSPLICE_SECTION_DATA;
1391 if (ss->type == SS_TYPE_TEXT)
1392 ksect->flags |= KSPLICE_SECTION_TEXT;
1393 assert(ksect->flags != 0);
1394 write_reloc(ksect_ss, &ksect->address, &ss->symbol,
1395 span->start + span->shift);
1398 void write_ksplice_patch(struct superbfd *sbfd, const char *sectname)
1400 struct supersect *kpatch_ss = make_section(sbfd, ".ksplice_patches");
1401 struct ksplice_patch *kpatch = sect_grow(kpatch_ss, 1,
1402 struct ksplice_patch);
1403 asection *sect = bfd_get_section_by_name(sbfd->abfd, sectname);
1404 assert(sect != NULL);
1406 write_string(kpatch_ss, &kpatch->label, "%s",
1407 label_lookup(sbfd, sect->symbol));
1408 write_reloc(kpatch_ss, &kpatch->repladdr, &sect->symbol, 0);
1411 asymbol **make_undefined_symbolp(struct superbfd *sbfd, const char *name)
1413 asymbol **symp;
1414 for (symp = sbfd->syms.data; symp < sbfd->syms.data + sbfd->syms.size;
1415 symp++) {
1416 asymbol *sym = *symp;
1417 if (strcmp(name, sym->name) == 0 &&
1418 bfd_is_und_section(sym->section))
1419 return symp;
1421 asymbol ***sympp;
1422 for (sympp = sbfd->new_syms.data;
1423 sympp < sbfd->new_syms.data + sbfd->new_syms.size; sympp++) {
1424 asymbol **symp = *sympp;
1425 asymbol *sym = *symp;
1426 if (strcmp(name, sym->name) == 0 &&
1427 bfd_is_und_section(sym->section))
1428 return symp;
1431 symp = malloc(sizeof(*symp));
1432 *symp = bfd_make_empty_symbol(sbfd->abfd);
1433 asymbol *sym = *symp;
1434 sym->name = name;
1435 sym->section = bfd_und_section_ptr;
1436 sym->flags = 0;
1437 sym->value = 0;
1438 *vec_grow(&sbfd->new_syms, 1) = symp;
1439 return symp;
1442 void write_ksplice_deleted_patch(struct superbfd *sbfd, const char *name,
1443 const char *label)
1445 struct supersect *kpatch_ss = make_section(sbfd, ".ksplice_patches");
1446 struct ksplice_patch *kpatch = sect_grow(kpatch_ss, 1,
1447 struct ksplice_patch);
1449 write_string(kpatch_ss, &kpatch->label, "%s", label);
1450 asymbol **symp = make_undefined_symbolp(sbfd, strdup(name));
1451 write_reloc(kpatch_ss, &kpatch->repladdr, symp, 0);
1454 void write_ksplice_export(struct superbfd *sbfd, const char *symname,
1455 const char *export_type, bool del)
1457 struct supersect *export_ss = make_section(sbfd, ".ksplice_exports");
1458 struct ksplice_export *exp = sect_grow(export_ss, 1,
1459 struct ksplice_export);
1461 if (del) {
1462 write_string(export_ss, &exp->name, "%s", symname);
1463 write_string(export_ss, &exp->new_name, "DISABLED_%s_%s",
1464 symname, kid);
1465 } else {
1466 write_string(export_ss, &exp->new_name, "%s", symname);
1467 write_string(export_ss, &exp->name, "DISABLED_%s_%s", symname,
1468 kid);
1472 struct fixup_entry {
1473 bfd_vma offset;
1474 bool used;
1476 DECLARE_VEC_TYPE(struct fixup_entry, fixup_entry_vec);
1478 int compare_fixups(const void *aptr, const void *bptr)
1480 const struct fixup_entry *a = aptr, *b = bptr;
1481 if (a->offset < b->offset)
1482 return -1;
1483 else if (a->offset > b->offset)
1484 return 1;
1485 else
1486 return (int)a->used - (int)b->used;
1489 void filter_table_sections(struct superbfd *isbfd)
1491 struct supersect *tables_ss =
1492 fetch_supersect(offsets_sbfd,
1493 bfd_get_section_by_name(offsets_sbfd->abfd,
1494 ".ksplice_table_sections"));
1495 const struct table_section *ts;
1496 for (ts = tables_ss->contents.data;
1497 (void *)ts < tables_ss->contents.data + tables_ss->contents.size;
1498 ts++) {
1499 struct table_section s = *ts;
1500 s.sect = read_string(tables_ss, &ts->sect);
1501 s.other_sect = read_string(tables_ss, &ts->other_sect);
1502 filter_table_section(isbfd, &s);
1506 void filter_table_section(struct superbfd *sbfd, const struct table_section *s)
1508 asection *isection = bfd_get_section_by_name(sbfd->abfd, s->sect);
1509 if (isection == NULL)
1510 return;
1511 asection *fixup_sect = NULL;
1512 if (s->other_sect != NULL)
1513 fixup_sect = bfd_get_section_by_name(sbfd->abfd, s->other_sect);
1515 struct supersect *ss = fetch_supersect(sbfd, isection);
1516 if (ss->alignment < ffs(s->entry_align) - 1)
1517 ss->alignment = ffs(s->entry_align) - 1;
1519 struct supersect *fixup_ss = NULL;
1520 if (fixup_sect != NULL)
1521 fixup_ss = fetch_supersect(sbfd, fixup_sect);
1523 struct fixup_entry_vec fixups;
1524 vec_init(&fixups);
1526 void *entry;
1527 for (entry = ss->contents.data;
1528 entry < ss->contents.data + ss->contents.size;
1529 entry += s->entry_size) {
1530 asymbol *sym, *fixup_sym;
1531 read_reloc(ss, entry + s->addr_offset, sizeof(void *), &sym);
1533 struct span *span = new_span(ss, addr_offset(ss, entry),
1534 s->entry_size);
1535 struct supersect *sym_ss = fetch_supersect(sbfd, sym->section);
1536 span->keep = sym_ss->keep;
1538 struct fixup_entry *f;
1539 if (fixup_sect != NULL) {
1540 bfd_vma fixup_offset =
1541 read_reloc(ss, entry + s->other_offset,
1542 sizeof(void *), &fixup_sym);
1543 if (fixup_sym->section == fixup_sect) {
1544 assert(fixup_offset < fixup_ss->contents.size);
1545 f = vec_grow(&fixups, 1);
1546 f->offset = fixup_offset;
1547 f->used = span->keep;
1552 if (fixup_sect == NULL)
1553 return;
1555 qsort(fixups.data, fixups.size, sizeof(*fixups.data), compare_fixups);
1556 *vec_grow(&fixups, 1) = (struct fixup_entry)
1557 { .offset = fixup_ss->contents.size, .used = false };
1559 struct fixup_entry *f;
1560 for (f = fixups.data; f < fixups.data + fixups.size - 1; f++) {
1561 struct span *span = new_span(fixup_ss, f->offset,
1562 (f + 1)->offset - f->offset);
1563 span->keep = f->used;
1567 void keep_referenced_sections(struct superbfd *sbfd)
1569 asection *sect;
1570 struct supersect *ss, *sym_ss;
1571 struct span *address_span, *target_span;
1572 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
1573 ss = fetch_supersect(sbfd, sect);
1574 arelent **relocp;
1575 if (ss->type == SS_TYPE_SPECIAL || ss->type == SS_TYPE_EXPORT)
1576 continue;
1577 for (relocp = ss->relocs.data;
1578 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
1579 asymbol *sym = *(*relocp)->sym_ptr_ptr;
1580 address_span = reloc_address_span(ss, *relocp);
1581 if (!address_span->keep)
1582 continue;
1583 target_span = reloc_target_span(ss, *relocp);
1584 if (target_span == NULL || target_span->keep)
1585 continue;
1586 sym_ss = fetch_supersect(sbfd, sym->section);
1587 if (sym_ss->type == SS_TYPE_IGNORED)
1588 continue;
1589 target_span->keep = true;
1590 sym_ss->keep = true;
1591 changed = true;
1596 void copy_symbols(struct asymbolp_vec *osyms, struct asymbolpp_vec *isyms)
1598 asymbol ***sympp;
1599 for (sympp = isyms->data; sympp < isyms->data + isyms->size; sympp++)
1600 *vec_grow(osyms, 1) = **sympp;
1603 /* Modified function from GNU Binutils objcopy.c */
1604 bfd_boolean copy_object(bfd *ibfd, bfd *obfd)
1606 assert(bfd_set_format(obfd, bfd_get_format(ibfd)));
1608 bfd_vma start = bfd_get_start_address(ibfd);
1610 flagword flags = bfd_get_file_flags(ibfd);
1611 flags &= bfd_applicable_file_flags(obfd);
1613 assert(bfd_set_start_address(obfd, start)
1614 && bfd_set_file_flags(obfd, flags));
1616 enum bfd_architecture iarch = bfd_get_arch(ibfd);
1617 unsigned int imach = bfd_get_mach(ibfd);
1618 assert(bfd_set_arch_mach(obfd, iarch, imach));
1619 assert(bfd_set_format(obfd, bfd_get_format(ibfd)));
1621 /* BFD mandates that all output sections be created and sizes set before
1622 any output is done. Thus, we traverse all sections multiple times. */
1623 bfd_map_over_sections(ibfd, setup_section, obfd);
1625 struct supersect *new_supersects = fetch_superbfd(ibfd)->new_supersects;
1626 struct supersect *ss;
1627 for (ss = new_supersects; ss != NULL; ss = ss->next)
1628 setup_new_section(obfd, ss);
1630 /* Mark symbols used in output relocations so that they
1631 are kept, even if they are local labels or static symbols.
1633 Note we iterate over the input sections examining their
1634 relocations since the relocations for the output sections
1635 haven't been set yet. mark_symbols_used_in_relocations will
1636 ignore input sections which have no corresponding output
1637 section. */
1639 bfd_map_over_sections(ibfd, mark_symbols_used_in_relocations, NULL);
1640 for (ss = new_supersects; ss != NULL; ss = ss->next)
1641 ss_mark_symbols_used_in_relocations(ss);
1642 struct asymbolp_vec osyms;
1643 vec_init(&osyms);
1644 filter_symbols(ibfd, obfd, &osyms, &fetch_superbfd(ibfd)->syms);
1645 copy_symbols(&osyms, &fetch_superbfd(ibfd)->new_syms);
1647 bfd_set_symtab(obfd, osyms.data, osyms.size);
1649 /* This has to happen after the symbol table has been set. */
1650 bfd_map_over_sections(obfd, write_section, NULL);
1652 /* Allow the BFD backend to copy any private data it understands
1653 from the input BFD to the output BFD. This is done last to
1654 permit the routine to look at the filtered symbol table, which is
1655 important for the ECOFF code at least. */
1656 assert(bfd_copy_private_bfd_data(ibfd, obfd));
1658 return TRUE;
1661 /* Modified function from GNU Binutils objcopy.c */
1662 void setup_section(bfd *ibfd, asection *isection, void *obfdarg)
1664 struct superbfd *isbfd = fetch_superbfd(ibfd);
1665 struct supersect *ss = fetch_supersect(isbfd, isection);
1666 bfd *obfd = obfdarg;
1667 bfd_vma vma;
1669 if (!ss->keep)
1670 return;
1672 asection *osection = bfd_make_section_anyway(obfd, isection->name);
1673 assert(osection != NULL);
1675 osection->userdata = ss;
1676 bfd_set_section_flags(obfd, osection, ss->flags);
1677 ss->symbol = osection->symbol;
1678 assert(bfd_set_section_size(obfd, osection, ss->contents.size));
1680 vma = bfd_section_vma(ibfd, isection);
1681 assert(bfd_set_section_vma(obfd, osection, vma));
1683 osection->lma = isection->lma;
1684 assert(bfd_set_section_alignment(obfd, osection, ss->alignment));
1685 osection->entsize = isection->entsize;
1686 osection->output_section = osection;
1687 osection->output_offset = 0;
1688 isection->output_section = osection;
1689 isection->output_offset = 0;
1690 return;
1693 void setup_new_section(bfd *obfd, struct supersect *ss)
1695 asection *osection = bfd_make_section_anyway(obfd, ss->name);
1696 assert(osection != NULL);
1697 bfd_set_section_flags(obfd, osection, ss->flags);
1699 osection->userdata = ss;
1700 ss->symbol = osection->symbol;
1701 assert(bfd_set_section_size(obfd, osection, ss->contents.size));
1702 assert(bfd_set_section_vma(obfd, osection, 0));
1704 osection->lma = 0;
1705 assert(bfd_set_section_alignment(obfd, osection, ss->alignment));
1706 osection->entsize = 0;
1707 osection->output_section = osection;
1708 osection->output_offset = 0;
1711 static int compare_reloc_addresses(const void *aptr, const void *bptr)
1713 const arelent *const *a = aptr, *const *b = bptr;
1714 return (*a)->address - (*b)->address;
1717 static void delete_obsolete_relocs(struct supersect *ss)
1719 if (ss->new_relocs.size == 0)
1720 return;
1722 qsort(ss->relocs.data, ss->relocs.size, sizeof(*ss->relocs.data),
1723 compare_reloc_addresses);
1724 qsort(ss->new_relocs.data, ss->new_relocs.size,
1725 sizeof(*ss->new_relocs.data), compare_reloc_addresses);
1727 struct arelentp_vec orig_relocs;
1728 vec_move(&orig_relocs, &ss->relocs);
1730 arelent **relocp, **new_relocp = ss->new_relocs.data;
1731 for (relocp = orig_relocs.data;
1732 relocp < orig_relocs.data + orig_relocs.size; relocp++) {
1733 while (new_relocp < ss->new_relocs.data + ss->new_relocs.size &&
1734 (*new_relocp)->address < (*relocp)->address)
1735 new_relocp++;
1736 arelent *reloc = *relocp, *new_reloc = *new_relocp;
1737 if (new_relocp == ss->new_relocs.data + ss->new_relocs.size ||
1738 reloc->address != new_reloc->address)
1739 *vec_grow(&ss->relocs, 1) = reloc;
1743 void write_section(bfd *obfd, asection *osection, void *arg)
1745 struct supersect *ss = osection->userdata;
1747 if ((ss->flags & SEC_GROUP) != 0 || ss->contents.size == 0)
1748 return;
1750 delete_obsolete_relocs(ss);
1752 arelent **relocp;
1753 char *error_message;
1754 for (relocp = ss->new_relocs.data;
1755 relocp < ss->new_relocs.data + ss->new_relocs.size; relocp++) {
1756 bfd_vma val;
1757 if (bfd_get_arch(obfd) == bfd_arch_arm)
1758 val = osection->use_rela_p ? 0 : (*relocp)->addend;
1759 else
1760 val = 0;
1761 bfd_put(bfd_get_reloc_size((*relocp)->howto) * 8, obfd, val,
1762 ss->contents.data + (*relocp)->address);
1763 if (bfd_install_relocation(obfd, *relocp, ss->contents.data,
1764 0, osection, &error_message) !=
1765 bfd_reloc_ok) {
1766 err(ss->parent, "ksplice: error installing reloc: %s",
1767 error_message);
1768 DIE;
1771 memcpy(vec_grow(&ss->relocs, ss->new_relocs.size), ss->new_relocs.data,
1772 ss->new_relocs.size * sizeof(*ss->new_relocs.data));
1774 bfd_set_reloc(obfd, osection,
1775 ss->relocs.size == 0 ? NULL : ss->relocs.data,
1776 ss->relocs.size);
1778 if (ss->flags & SEC_HAS_CONTENTS)
1779 assert(bfd_set_section_contents
1780 (obfd, osection, ss->contents.data, 0,
1781 ss->contents.size));
1784 /* Modified function from GNU Binutils objcopy.c
1786 * Mark all the symbols which will be used in output relocations with
1787 * the BSF_KEEP flag so that those symbols will not be stripped.
1789 * Ignore relocations which will not appear in the output file.
1791 void mark_symbols_used_in_relocations(bfd *abfd, asection *isection,
1792 void *ignored)
1794 struct superbfd *sbfd = fetch_superbfd(abfd);
1795 if (isection->output_section == NULL)
1796 return;
1798 struct supersect *ss = fetch_supersect(sbfd, isection);
1799 ss_mark_symbols_used_in_relocations(ss);
1802 void ss_mark_symbols_used_in_relocations(struct supersect *ss)
1804 /* Examine each symbol used in a relocation. If it's not one of the
1805 special bfd section symbols, then mark it with BSF_KEEP. */
1806 arelent **relocp;
1807 for (relocp = ss->relocs.data;
1808 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
1809 asymbol *sym = *(*relocp)->sym_ptr_ptr;
1810 if (!(bfd_is_const_section(sym->section) &&
1811 sym == sym->section->symbol))
1812 sym->flags |= BSF_KEEP;
1814 for (relocp = ss->new_relocs.data;
1815 relocp < ss->new_relocs.data + ss->new_relocs.size; relocp++) {
1816 asymbol *sym = *(*relocp)->sym_ptr_ptr;
1817 if (!(bfd_is_const_section(sym->section) &&
1818 sym == sym->section->symbol))
1819 sym->flags |= BSF_KEEP;
1823 static bool deleted_table_section_symbol(bfd *abfd, asymbol *sym)
1825 struct superbfd *sbfd = fetch_superbfd(abfd);
1826 if (bfd_is_const_section(sym->section))
1827 return false;
1828 struct supersect *ss = fetch_supersect(sbfd, sym->section);
1830 asymbol **symp;
1831 for (symp = ss->syms.data; symp < ss->syms.data + ss->syms.size; symp++) {
1832 if (sym == *symp)
1833 break;
1835 return symp >= ss->syms.data + ss->syms.size;
1838 /* Modified function from GNU Binutils objcopy.c
1840 * Choose which symbol entries to copy.
1841 * We don't copy in place, because that confuses the relocs.
1842 * Return the number of symbols to print.
1844 void filter_symbols(bfd *ibfd, bfd *obfd, struct asymbolp_vec *osyms,
1845 struct asymbolp_vec *isyms)
1847 asymbol **symp;
1848 struct superbfd *sbfd = fetch_superbfd(ibfd);
1849 for (symp = isyms->data; symp < isyms->data + isyms->size; symp++) {
1850 asymbol *sym = *symp;
1851 struct supersect *sym_ss = NULL;
1852 if (!bfd_is_const_section(sym->section))
1853 sym_ss = fetch_supersect(sbfd, sym->section);
1855 bool keep = false;
1857 if (mode("keep") && (sym->flags & BSF_GLOBAL) != 0 &&
1858 !(mode("keep-primary") && sym_ss != NULL && sym_ss->new))
1859 sym->flags = (sym->flags & ~BSF_GLOBAL) | BSF_LOCAL;
1861 if (mode("finalize") && (sym->flags & BSF_GLOBAL) != 0)
1862 sym->flags = (sym->flags & ~BSF_GLOBAL) | BSF_LOCAL;
1864 if ((sym->flags & BSF_KEEP) != 0 /* Used in relocation. */
1865 || ((sym->flags & BSF_SECTION_SYM) != 0 && sym_ss != NULL &&
1866 sym_ss->keep))
1867 keep = true;
1868 else if ((sym->flags & (BSF_GLOBAL | BSF_WEAK)) != 0 &&
1869 sym_ss != NULL && sym_ss->keep)
1870 keep = true;
1872 if (deleted_table_section_symbol(ibfd, sym))
1873 keep = false;
1875 if (bfd_is_com_section(sym->section))
1876 keep = false;
1878 if (mode("rmsyms"))
1879 keep = !str_in_set(sym->name, &rmsyms);
1881 if (keep) {
1882 if (sym_ss != NULL && !sym_ss->keep) {
1883 err(sbfd, "Kept symbol %s in unkept section "
1884 "%s\n", sym->name, sym->section->name);
1885 DIE;
1887 *vec_grow(osyms, 1) = sym;
1892 void read_str_set(struct str_vec *strs)
1894 char *buf = NULL;
1895 size_t n = 0;
1896 assert(getline(&buf, &n, stdin) >= 0);
1897 vec_init(strs);
1898 char *saveptr;
1899 while (1) {
1900 char *str = strtok_r(buf, " \n", &saveptr);
1901 buf = NULL;
1902 if (str == NULL)
1903 break;
1904 *vec_grow(strs, 1) = str;
1908 bool str_in_set(const char *str, const struct str_vec *strs)
1910 const char **strp;
1911 for (strp = strs->data; strp < strs->data + strs->size; strp++) {
1912 if (strcmp(str, *strp) == 0)
1913 return true;
1915 return false;
1918 bool is_table_section(const char *name, bool consider_other)
1920 struct supersect *tables_ss =
1921 fetch_supersect(offsets_sbfd,
1922 bfd_get_section_by_name(offsets_sbfd->abfd,
1923 ".ksplice_table_sections"));
1924 const struct table_section *ts;
1925 for (ts = tables_ss->contents.data;
1926 (void *)ts < tables_ss->contents.data + tables_ss->contents.size;
1927 ts++) {
1928 if (strcmp(name, read_string(tables_ss, &ts->sect)) == 0)
1929 return true;
1930 const char *osect_name = read_string(tables_ss,
1931 &ts->other_sect);
1932 if (consider_other && osect_name != NULL &&
1933 strcmp(name, osect_name) == 0)
1934 return true;
1936 return false;
1939 enum supersect_type supersect_type(struct supersect *ss)
1941 if (starts_with(ss->name, ".ksplice"))
1942 return SS_TYPE_KSPLICE;
1944 if (starts_with(ss->name, ".init"))
1945 return SS_TYPE_IGNORED;
1946 if (starts_with(ss->name, ".security_initcall.init"))
1947 return SS_TYPE_IGNORED;
1948 if (starts_with(ss->name, ".con_initcall.init"))
1949 return SS_TYPE_IGNORED;
1950 if (starts_with(ss->name, ".x86cpuvendor.init"))
1951 return SS_TYPE_IGNORED;
1952 if (starts_with(ss->name, ".early_param.init"))
1953 return SS_TYPE_IGNORED;
1954 if (starts_with(ss->name, ".taglist.init"))
1955 return SS_TYPE_IGNORED;
1956 if (starts_with(ss->name, ".arch.info.init"))
1957 return SS_TYPE_IGNORED;
1958 if (starts_with(ss->name, ".proc.info.init"))
1959 return SS_TYPE_IGNORED;
1960 /* .pci_fixup_* sections really should be treated as global rodata
1961 referenced only from quirks.c */
1962 if (starts_with(ss->name, ".pci_fixup_"))
1963 return SS_TYPE_IGNORED;
1964 /* .builtin_fw sections are similar to .pci_fixup */
1965 if (starts_with(ss->name, ".builtin_fw"))
1966 return SS_TYPE_IGNORED;
1967 /* same for .tracedata */
1968 if (starts_with(ss->name, ".tracedata"))
1969 return SS_TYPE_IGNORED;
1970 if (starts_with(ss->name, ".debug"))
1971 return SS_TYPE_IGNORED;
1972 /* .eh_frame should probably be discarded, not ignored */
1973 if (starts_with(ss->name, ".eh_frame"))
1974 return SS_TYPE_IGNORED;
1975 if (config->ignore_devinit && starts_with(ss->name, ".devinit"))
1976 return SS_TYPE_IGNORED;
1977 if (config->ignore_meminit && starts_with(ss->name, ".meminit"))
1978 return SS_TYPE_IGNORED;
1979 if (config->ignore_cpuinit && starts_with(ss->name, ".cpuinit"))
1980 return SS_TYPE_IGNORED;
1981 if (config->ignore_devinit && starts_with(ss->name, ".devexit"))
1982 return SS_TYPE_IGNORED;
1983 if (config->ignore_meminit && starts_with(ss->name, ".memexit"))
1984 return SS_TYPE_IGNORED;
1985 if (config->ignore_cpuinit && starts_with(ss->name, ".cpuexit"))
1986 return SS_TYPE_IGNORED;
1987 if (starts_with(ss->name, ".vgetcpu_mode") ||
1988 starts_with(ss->name, ".jiffies") ||
1989 starts_with(ss->name, ".wall_jiffies") ||
1990 starts_with(ss->name, ".vxtime") ||
1991 starts_with(ss->name, ".sys_tz") ||
1992 starts_with(ss->name, ".sysctl_vsyscall") ||
1993 starts_with(ss->name, ".xtime") ||
1994 starts_with(ss->name, ".xtime_lock") ||
1995 starts_with(ss->name, ".vsyscall"))
1996 return SS_TYPE_IGNORED;
1997 if (starts_with(ss->name, ".vdso"))
1998 return SS_TYPE_IGNORED;
2000 if (bfd_get_section_by_name(ss->parent->abfd, ".exitcall.exit") == NULL) {
2001 if (starts_with(ss->name, ".exit.text"))
2002 return SS_TYPE_TEXT;
2003 if (starts_with(ss->name, ".exit.data"))
2004 return SS_TYPE_DATA;
2005 } else if (starts_with(ss->name, ".exit.text") ||
2006 starts_with(ss->name, ".exit.data"))
2007 return SS_TYPE_IGNORED;
2009 if (starts_with(ss->name, ".text") ||
2010 starts_with(ss->name, ".kernel.text") ||
2011 starts_with(ss->name, ".devinit.text") ||
2012 starts_with(ss->name, ".meminit.text") ||
2013 starts_with(ss->name, ".cpuinit.text") ||
2014 starts_with(ss->name, ".devexit.text") ||
2015 starts_with(ss->name, ".memexit.text") ||
2016 starts_with(ss->name, ".cpuexit.text") ||
2017 starts_with(ss->name, ".ref.text") ||
2018 starts_with(ss->name, ".spinlock.text") ||
2019 starts_with(ss->name, ".kprobes.text") ||
2020 starts_with(ss->name, ".sched.text"))
2021 return SS_TYPE_TEXT;
2023 int n = -1;
2024 if (sscanf(ss->name, ".rodata.str%*u.%*u%n", &n) >= 0 &&
2025 n == strlen(ss->name))
2026 return SS_TYPE_STRING;
2028 if (starts_with(ss->name, ".rodata") ||
2029 starts_with(ss->name, ".kernel.rodata") ||
2030 starts_with(ss->name, ".devinit.rodata") ||
2031 starts_with(ss->name, ".meminit.rodata") ||
2032 starts_with(ss->name, ".cpuinit.rodata") ||
2033 starts_with(ss->name, ".devexit.rodata") ||
2034 starts_with(ss->name, ".memexit.rodata") ||
2035 starts_with(ss->name, ".cpuexit.rodata") ||
2036 starts_with(ss->name, ".ref.rodata") ||
2037 starts_with(ss->name, "__markers_strings"))
2038 return SS_TYPE_RODATA;
2040 if (starts_with(ss->name, ".bss"))
2041 return SS_TYPE_DATA;
2043 /* Ignore .data.percpu sections */
2044 if (starts_with(ss->name, ".data.percpu") ||
2045 starts_with(ss->name, ".kernel.data.percpu"))
2046 return SS_TYPE_IGNORED;
2047 if (starts_with(ss->name, ".data") ||
2048 starts_with(ss->name, ".kernel.data") ||
2049 starts_with(ss->name, ".devinit.data") ||
2050 starts_with(ss->name, ".cpuinit.data") ||
2051 starts_with(ss->name, ".meminit.data") ||
2052 starts_with(ss->name, ".devexit.data") ||
2053 starts_with(ss->name, ".memexit.data") ||
2054 starts_with(ss->name, ".cpuexit.data") ||
2055 starts_with(ss->name, ".ref.data") ||
2056 starts_with(ss->name, "__markers"))
2057 return SS_TYPE_DATA;
2059 /* We replace all the ksymtab strings, so delete them */
2060 if (strcmp(ss->name, "__ksymtab_strings") == 0)
2061 return SS_TYPE_IGNORED;
2062 if (starts_with(ss->name, "__ksymtab"))
2063 return SS_TYPE_EXPORT;
2064 if (starts_with(ss->name, "__kcrctab"))
2065 return SS_TYPE_EXPORT;
2067 if (is_table_section(ss->name, true))
2068 return SS_TYPE_SPECIAL;
2070 if (starts_with(ss->name, ".ARM."))
2071 return SS_TYPE_SPECIAL;
2073 if (starts_with(ss->name, ".note"))
2074 return SS_TYPE_IGNORED;
2075 if (starts_with(ss->name, ".comment"))
2076 return SS_TYPE_IGNORED;
2077 if (starts_with(ss->name, "__param"))
2078 return SS_TYPE_IGNORED;
2079 if (starts_with(ss->name, ".exitcall.exit"))
2080 return SS_TYPE_IGNORED;
2081 if (starts_with(ss->name, ".modinfo"))
2082 return SS_TYPE_IGNORED;
2084 return SS_TYPE_UNKNOWN;
2087 void initialize_supersect_types(struct superbfd *sbfd)
2089 asection *sect;
2090 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2091 struct supersect *ss = fetch_supersect(sbfd, sect);
2092 ss->type = supersect_type(ss);
2093 if (ss->type == SS_TYPE_UNKNOWN) {
2094 err(sbfd, "Unknown section type: %s\n", ss->name);
2095 DIE;
2100 static void init_label_map(struct superbfd *sbfd)
2102 struct label_map *map;
2104 vec_init(&sbfd->maps);
2105 init_csyms(sbfd);
2106 init_callers(sbfd);
2108 struct symbol_hash csyms;
2109 symbol_hash_init(&csyms);
2111 asymbol **symp;
2112 for (symp = sbfd->syms.data;
2113 symp < sbfd->syms.data + sbfd->syms.size; symp++) {
2114 asymbol *csym = canonical_symbol(sbfd, *symp);
2115 if (csym == NULL)
2116 continue;
2117 char *key;
2118 assert(asprintf(&key, "%p", csym) >= 0);
2119 asymbol **csymp = symbol_hash_lookup(&csyms, key, TRUE);
2120 free(key);
2121 if (*csymp != NULL)
2122 continue;
2123 *csymp = csym;
2125 map = vec_grow(&sbfd->maps, 1);
2126 map->csym = csym;
2127 map->count = 0;
2128 map->label = symbol_label(sbfd, csym);
2131 struct label_mapp_hash label_maps;
2132 label_mapp_hash_init(&label_maps);
2133 for (map = sbfd->maps.data;
2134 map < sbfd->maps.data + sbfd->maps.size; map++) {
2135 struct label_map **mapp =
2136 label_mapp_hash_lookup(&label_maps, map->label, TRUE);
2137 if (*mapp == NULL) {
2138 *mapp = map;
2139 continue;
2142 struct label_map *first_map = *mapp;
2143 char *buf;
2144 if (first_map->count == 0) {
2145 assert(asprintf(&buf, "%s~%d", map->label, 0) >= 0);
2146 first_map->label = buf;
2148 first_map->count++;
2149 assert(asprintf(&buf, "%s~%d", map->label, first_map->count)
2150 >= 0);
2151 map->label = buf;
2154 label_mapp_hash_init(&sbfd->maps_hash);
2155 for (map = sbfd->maps.data;
2156 map < sbfd->maps.data + sbfd->maps.size; map++) {
2157 char *key;
2158 assert(asprintf(&key, "%p", map->csym) >= 0);
2159 struct label_map **mapp =
2160 label_mapp_hash_lookup(&sbfd->maps_hash, key, TRUE);
2161 free(key);
2162 *mapp = map;
2163 map->orig_label = map->label;
2167 static const char *label_lookup(struct superbfd *sbfd, asymbol *sym)
2169 asymbol *csym = canonical_symbol(sbfd, sym);
2170 char *key;
2171 assert(asprintf(&key, "%p", csym) >= 0);
2172 struct label_map **mapp =
2173 label_mapp_hash_lookup(&sbfd->maps_hash, key, FALSE);
2174 free(key);
2175 if (mapp == NULL)
2176 DIE;
2177 return (*mapp)->label;
2180 static void print_label_map(struct superbfd *sbfd)
2182 struct label_map *map;
2183 for (map = sbfd->maps.data;
2184 map < sbfd->maps.data + sbfd->maps.size; map++) {
2185 if (strcmp(map->orig_label, map->label) == 0)
2186 continue;
2187 debug1(sbfd, "Label change: %s -> %s\n",
2188 map->label, map->orig_label);
2192 static void label_map_set(struct superbfd *sbfd, const char *oldlabel,
2193 const char *label)
2195 struct label_map *map;
2196 for (map = sbfd->maps.data;
2197 map < sbfd->maps.data + sbfd->maps.size; map++) {
2198 if (strcmp(map->orig_label, oldlabel) == 0) {
2199 if (strcmp(map->orig_label, map->label) != 0 &&
2200 strcmp(map->label, label) != 0)
2201 DIE;
2202 map->label = label;
2203 return;
2206 DIE;
2209 static void init_callers(struct superbfd *sbfd)
2211 string_hash_init(&sbfd->callers);
2212 asection *sect;
2213 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2214 struct supersect *ss = fetch_supersect(sbfd, sect);
2215 arelent **relocp;
2216 for (relocp = ss->relocs.data;
2217 relocp < ss->relocs.data + ss->relocs.size; relocp++) {
2218 asymbol *sym = *(*relocp)->sym_ptr_ptr;
2219 unsigned long val =
2220 sym->value + get_reloc_offset(ss, *relocp, true);
2221 char *key;
2222 assert(asprintf(&key, "%s+%lx", sym->section->name,
2223 val) >= 0);
2224 const char **ret = string_hash_lookup(&sbfd->callers,
2225 key, TRUE);
2226 free(key);
2227 if (*ret == NULL)
2228 *ret = sect->name;
2229 else
2230 *ret = "*multiple_callers*";
2235 static const char *find_caller(struct supersect *ss, asymbol *sym)
2237 char *key;
2238 assert(asprintf(&key, "%s+%lx", sym->section->name,
2239 (unsigned long)sym->value) >= 0);
2240 const char **ret = string_hash_lookup(&ss->parent->callers, key, FALSE);
2241 free(key);
2243 if (ret == NULL)
2244 return "*no_caller*";
2245 return *ret;
2248 static void init_csyms(struct superbfd *sbfd)
2250 asymbolpp_hash_init(&sbfd->csyms);
2252 asymbol **symp;
2253 for (symp = sbfd->syms.data; symp < sbfd->syms.data + sbfd->syms.size;
2254 symp++) {
2255 asymbol *sym = *symp;
2256 if ((sym->flags & BSF_DEBUGGING) != 0)
2257 continue;
2258 char *key;
2259 assert(asprintf(&key, "%s+%lx", sym->section->name,
2260 (unsigned long)sym->value) >= 0);
2261 asymbol ***csympp = asymbolpp_hash_lookup(&sbfd->csyms, key,
2262 TRUE);
2263 free(key);
2264 if (*csympp == NULL) {
2265 *csympp = symp;
2266 continue;
2268 asymbol *csym = **csympp;
2269 if ((csym->flags & BSF_GLOBAL) != 0)
2270 continue;
2271 if ((sym->flags & BSF_GLOBAL) != 0)
2272 *csympp = symp;
2276 static asymbol **symbolp_scan(struct supersect *ss, bfd_vma value)
2278 char *key;
2279 assert(asprintf(&key, "%s+%lx", ss->name, (unsigned long)value) >= 0);
2280 asymbol ***csympp =
2281 asymbolpp_hash_lookup(&ss->parent->csyms, key, FALSE);
2282 free(key);
2283 if (csympp != NULL)
2284 return *csympp;
2286 /* For section symbols of sections containing no symbols, return the
2287 section symbol that relocations are generated against */
2288 if (value == 0)
2289 return &ss->symbol;
2290 return NULL;
2293 static asymbol **canonical_symbolp(struct superbfd *sbfd, asymbol *sym)
2295 if (bfd_is_const_section(sym->section)) {
2296 asymbol **csymp;
2297 for (csymp = sbfd->syms.data;
2298 csymp < sbfd->syms.data + sbfd->syms.size; csymp++) {
2299 if (sym == *csymp)
2300 return csymp;
2302 return NULL;
2304 return symbolp_scan(fetch_supersect(sbfd, sym->section), sym->value);
2307 static asymbol *canonical_symbol(struct superbfd *sbfd, asymbol *sym)
2309 if (bfd_is_const_section(sym->section))
2310 return sym;
2311 asymbol **symp = canonical_symbolp(sbfd, sym);
2312 return symp != NULL ? *symp : NULL;
2315 static char *static_local_symbol(struct superbfd *sbfd, asymbol *sym)
2317 struct supersect *ss = fetch_supersect(sbfd, sym->section);
2318 if ((sym->flags & BSF_LOCAL) == 0 || (sym->flags & BSF_OBJECT) == 0)
2319 return NULL;
2320 char *dot = strrchr(sym->name, '.');
2321 if (dot == NULL || dot[1 + strspn(dot + 1, "0123546789")] != '\0')
2322 return NULL;
2323 char *basename = strndup(sym->name, dot - sym->name);
2324 char *mangled_name;
2325 if (strcmp(basename, "__func__") == 0 ||
2326 strcmp(basename, "__PRETTY_FUNCTION__") == 0)
2327 assert(asprintf(&mangled_name, "%s<%s>", basename,
2328 (char *)ss->contents.data + sym->value) >= 0);
2329 else
2330 assert(asprintf(&mangled_name, "%s<%s>", basename,
2331 find_caller(ss, sym)) >= 0);
2332 return mangled_name;
2335 static char *symbol_label(struct superbfd *sbfd, asymbol *sym)
2337 const char *filename = sbfd->abfd->filename;
2338 char *c = strstr(filename, ".KSPLICE");
2339 int flen = (c == NULL ? strlen(filename) : c - filename);
2341 char *label;
2342 if (bfd_is_und_section(sym->section) || (sym->flags & BSF_GLOBAL) != 0) {
2343 label = strdup(sym->name);
2344 } else if (bfd_is_const_section(sym->section)) {
2345 assert(asprintf(&label, "%s<%.*s>",
2346 sym->name, flen, filename) >= 0);
2347 } else {
2348 asymbol *gsym = canonical_symbol(sbfd, sym);
2350 if (gsym == NULL)
2351 assert(asprintf(&label, "%s+%lx<%.*s>",
2352 sym->section->name,
2353 (unsigned long)sym->value,
2354 flen, filename) >= 0);
2355 else if ((gsym->flags & BSF_GLOBAL) != 0)
2356 label = strdup(gsym->name);
2357 else if (static_local_symbol(sbfd, gsym))
2358 assert(asprintf(&label, "%s+%lx<%.*s>",
2359 static_local_symbol(sbfd, gsym),
2360 (unsigned long)sym->value,
2361 flen, filename) >= 0);
2362 else
2363 assert(asprintf(&label, "%s<%.*s>",
2364 gsym->name, flen, filename) >= 0);
2367 return label;
2370 static struct span *new_span(struct supersect *ss, bfd_vma start, bfd_vma size)
2372 struct span *span = vec_grow(&ss->spans, 1);
2373 span->size = size;
2374 span->start = start;
2375 span->ss = ss;
2376 span->keep = false;
2377 span->new = false;
2378 span->shift = 0;
2379 asymbol **symp = symbolp_scan(ss, span->start);
2380 if (symp != NULL) {
2381 span->symbol = *symp;
2382 span->label = label_lookup(ss->parent, span->symbol);
2383 } else {
2384 span->symbol = NULL;
2385 const char *label = label_lookup(ss->parent, ss->symbol);
2386 if (span->start != 0) {
2387 char *buf;
2388 assert(asprintf(&buf, "%s<span:%lx>", label,
2389 (unsigned long)span->start) >= 0);
2390 span->label = buf;
2391 } else {
2392 span->label = label;
2395 return span;
2398 static void initialize_string_spans(struct supersect *ss)
2400 const char *str;
2401 for (str = ss->contents.data;
2402 (void *)str < ss->contents.data + ss->contents.size;) {
2403 bfd_vma start = (unsigned long)str -
2404 (unsigned long)ss->contents.data;
2405 bfd_vma size = strlen(str) + 1;
2406 while ((start + size) % (1 << ss->alignment) != 0 &&
2407 start + size < ss->contents.size) {
2408 if (str[size] != '\0')
2409 DIE;
2410 size++;
2412 new_span(ss, start, size);
2413 str += size;
2417 static void initialize_spans(struct superbfd *sbfd)
2419 asection *sect;
2420 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2421 struct supersect *ss = fetch_supersect(sbfd, sect);
2422 if (ss->type == SS_TYPE_STRING)
2423 initialize_string_spans(ss);
2424 else if (!mode("keep") || (ss->type != SS_TYPE_SPECIAL &&
2425 ss->type != SS_TYPE_EXPORT))
2426 new_span(ss, 0, ss->contents.size);
2430 struct span *reloc_target_span(struct supersect *ss, arelent *reloc)
2432 asymbol *sym_ptr = *reloc->sym_ptr_ptr;
2433 if (bfd_is_const_section(sym_ptr->section))
2434 return NULL;
2436 bfd_vma addend = get_reloc_offset(ss, reloc, true) + sym_ptr->value;
2437 struct supersect *sym_ss =
2438 fetch_supersect(ss->parent, sym_ptr->section);
2439 struct span *span, *target_span = sym_ss->spans.data;
2440 for (span = sym_ss->spans.data;
2441 span < sym_ss->spans.data + sym_ss->spans.size; span++) {
2442 if (addend >= span->start && addend < span->start + span->size)
2443 target_span = span;
2445 return target_span;
2448 struct span *reloc_address_span(struct supersect *ss, arelent *reloc)
2450 struct span *span;
2451 for (span = ss->spans.data; span < ss->spans.data + ss->spans.size;
2452 span++) {
2453 if (reloc->address >= span->start &&
2454 reloc->address < span->start + span->size)
2455 return span;
2457 return NULL;
2460 void compute_span_shifts(struct superbfd *sbfd)
2462 asection *sect;
2463 struct span *span;
2464 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2465 struct supersect *ss = fetch_supersect(sbfd, sect);
2466 if (!ss->keep)
2467 continue;
2468 bfd_size_type offset = 0;
2469 for (span = ss->spans.data;
2470 span < ss->spans.data + ss->spans.size; span++) {
2471 if (!span->keep)
2472 continue;
2473 span->shift = offset - span->start;
2474 offset += span->size;
2479 void remove_unkept_spans(struct superbfd *sbfd)
2481 asection *sect;
2482 struct span *span;
2483 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2484 struct supersect *ss = fetch_supersect(sbfd, sect);
2485 struct arelentp_vec orig_relocs;
2486 vec_move(&orig_relocs, &ss->relocs);
2487 arelent **relocp, *reloc;
2488 for (relocp = orig_relocs.data;
2489 relocp < orig_relocs.data + orig_relocs.size; relocp++) {
2490 reloc = *relocp;
2491 asymbol *sym = *reloc->sym_ptr_ptr;
2492 span = reloc_target_span(ss, reloc);
2493 if ((span != NULL && span->keep && span->shift == 0) ||
2494 bfd_is_const_section(sym->section)) {
2495 *vec_grow(&ss->relocs, 1) = reloc;
2496 continue;
2498 if (span != NULL && span->keep) {
2499 arelent *new_reloc = malloc(sizeof(*new_reloc));
2500 *new_reloc = *reloc;
2501 new_reloc->addend =
2502 get_reloc_offset(ss, reloc, false);
2503 new_reloc->addend += span->shift;
2504 *vec_grow(&ss->new_relocs, 1) = new_reloc;
2509 for (sect = sbfd->abfd->sections; sect != NULL; sect = sect->next) {
2510 struct supersect *ss = fetch_supersect(sbfd, sect), orig_ss;
2511 if (!ss->keep)
2512 continue;
2513 supersect_move(&orig_ss, ss);
2514 vec_init(&ss->spans);
2515 for (span = orig_ss.spans.data;
2516 span < orig_ss.spans.data + orig_ss.spans.size; span++) {
2517 if (!span->keep)
2518 continue;
2519 struct span *new_span = vec_grow(&ss->spans, 1);
2520 *new_span = *span;
2521 new_span->start = span->start + span->shift;
2522 new_span->shift = 0;
2523 sect_copy(ss, sect_do_grow(ss, 1, span->size, 1),
2524 &orig_ss, orig_ss.contents.data + span->start,
2525 span->size);