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
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
53 #include "objcommon.h"
54 #include "kmodsrc/ksplice.h"
61 #define symbol_init(sym) *(sym) = (asymbol *)NULL
62 DEFINE_HASH_TYPE(asymbol
*, symbol_hash
, symbol_hash_init
, symbol_hash_free
,
63 symbol_hash_lookup
, symbol_init
);
69 DECLARE_VEC_TYPE(struct export
, export_vec
);
71 DECLARE_VEC_TYPE(const char *, str_vec
);
78 struct table_section
{
87 DECLARE_VEC_TYPE(struct export_desc
, export_desc_vec
);
89 #define bool_init(b) *(b) = false
90 DEFINE_HASH_TYPE(bool, bool_hash
, bool_hash_init
, bool_hash_free
,
91 bool_hash_lookup
, bool_init
);
93 #define ulong_init(x) *(x) = 0
94 DEFINE_HASH_TYPE(unsigned long, ulong_hash
, ulong_hash_init
,
95 ulong_hash_free
, ulong_hash_lookup
, ulong_init
);
97 void foreach_nonmatching(struct superbfd
*oldsbfd
, struct superbfd
*newsbfd
,
98 void (*s_fn
)(struct superbfd
*, asection
*));
99 void foreach_new_section(struct superbfd
*oldsbfd
, struct superbfd
*newsbfd
,
100 void (*s_fn
)(struct superbfd
*, asection
*));
101 void print_changed_section(struct superbfd
*sbfd
, asection
*sect
);
102 void print_new_section(struct superbfd
*sbfd
, asection
*sect
);
103 void print_deleted_section(struct superbfd
*sbfd
, asection
*sect
);
104 struct export_vec
*get_export_syms(struct superbfd
*sbfd
);
105 void compare_exported_symbols(struct superbfd
*oldsbfd
,
106 struct superbfd
*newsbfd
, char *addstr
);
107 bool relocs_equal(struct superbfd
*oldsbfd
, asection
*oldp
,
108 struct superbfd
*newsbfd
, asection
*newp
);
109 static void handle_section_symbol_renames(struct superbfd
*oldsbfd
,
110 struct superbfd
*newsbfd
);
112 void rm_some_relocs(struct supersect
*ss
);
113 void write_ksplice_reloc(struct supersect
*ss
, arelent
*orig_reloc
);
114 void blot_section(struct supersect
*ss
, int offset
, reloc_howto_type
*howto
);
115 void write_ksplice_section(struct superbfd
*sbfd
, asymbol
**symp
);
116 void write_ksplice_patch(struct superbfd
*sbfd
, const char *sectname
);
117 void write_ksplice_deleted_patch(struct superbfd
*sbfd
, const char *label
);
118 void filter_table_section(struct superbfd
*sbfd
, const struct table_section
*s
);
119 void filter_ex_table_section(struct superbfd
*sbfd
);
120 void mark_wanted_if_referenced(bfd
*abfd
, asection
*sect
, void *ignored
);
121 void check_for_ref_to_section(bfd
*abfd
, asection
*looking_at
,
123 bfd_boolean
copy_object(bfd
*ibfd
, bfd
*obfd
);
124 void setup_section(bfd
*ibfd
, asection
*isection
, void *obfdarg
);
125 static void setup_new_section(bfd
*obfd
, struct supersect
*ss
);
126 static void write_section(bfd
*obfd
, asection
*osection
, void *arg
);
127 void mark_symbols_used_in_relocations(bfd
*abfd
, asection
*isection
,
129 static void ss_mark_symbols_used_in_relocations(struct supersect
*ss
);
130 void filter_symbols(bfd
*ibfd
, bfd
*obfd
, struct asymbolp_vec
*osyms
,
131 struct asymbolp_vec
*isyms
);
132 static bool deleted_table_section_symbol(bfd
*abfd
, asymbol
*sym
);
133 void read_str_set(struct str_vec
*strs
);
134 bool str_in_set(const char *str
, const struct str_vec
*strs
);
135 bool want_section(asection
*sect
);
136 bool is_table_section(asection
*sect
);
137 struct supersect
*make_section(struct superbfd
*sbfd
, const char *name
);
138 void __attribute__((format(printf
, 3, 4)))
139 write_string(struct supersect
*ss
, const char **addr
, const char *fmt
, ...);
140 void rm_some_exports(struct superbfd
*isbfd
, const struct export_desc
*ed
);
141 void write_ksplice_export(struct superbfd
*sbfd
, const char *symname
,
142 const char *export_type
, bool del
);
143 void write_reloc(struct supersect
*ss
, const void *addr
, asymbol
**symp
,
145 arelent
*create_reloc(struct supersect
*ss
, const void *addr
, asymbol
**symp
,
148 struct str_vec sections
, newsects
, delsects
, rmsyms
;
149 struct export_desc_vec exports
;
151 const char *modestr
, *kid
;
153 struct wsect
*wanted_sections
= NULL
;
155 const struct table_section table_sections
[] = {
156 {".altinstructions", 2 * sizeof(void *) + 4},
157 {".smp_locks", sizeof(void *)},
158 {".parainstructions", sizeof(void *) + 4},
159 }, *const end_table_sections
= *(&table_sections
+ 1);
161 #define mode(str) starts_with(modestr, str)
163 DECLARE_VEC_TYPE(unsigned long, addr_vec
);
164 DEFINE_HASH_TYPE(struct addr_vec
, addr_vec_hash
,
165 addr_vec_hash_init
, addr_vec_hash_free
, addr_vec_hash_lookup
,
167 struct addr_vec_hash system_map
;
169 struct bool_hash system_map_written
;
170 struct ulong_hash ksplice_symbol_offset
;
171 struct ulong_hash ksplice_string_offset
;
173 void load_system_map()
175 const char *config_dir
= getenv("KSPLICE_CONFIG_DIR");
178 assert(asprintf(&file
, "%s/System.map", config_dir
) >= 0);
179 FILE *fp
= fopen(file
, "r");
181 addr_vec_hash_init(&system_map
);
185 while (fscanf(fp
, "%lx %c %as\n", &addr
, &type
, &sym
) == 3)
186 *vec_grow(addr_vec_hash_lookup(&system_map
, sym
, TRUE
),
191 bool needed_data_section(struct superbfd
*sbfd
, asection
*isection
)
193 struct supersect
*ss
= fetch_supersect(sbfd
, isection
);
194 if (starts_with(isection
->name
, ".rodata"))
196 if (starts_with(isection
->name
, ".data")) {
197 /* Ignore .data.percpu sections */
198 if (starts_with(isection
->name
, ".data.percpu"))
200 return ss
->relocs
.size
!= 0;
205 int main(int argc
, char *argv
[])
208 bfd
*ibfd
= bfd_openr(argv
[1], NULL
);
212 assert(bfd_check_format_matches(ibfd
, bfd_object
, &matching
));
214 const char *output_target
= bfd_get_target(ibfd
);
215 bfd
*obfd
= bfd_openw(argv
[2], output_target
);
218 struct superbfd
*isbfd
= fetch_superbfd(ibfd
);
220 bool_hash_init(&system_map_written
);
221 ulong_hash_init(&ksplice_symbol_offset
);
222 ulong_hash_init(&ksplice_string_offset
);
225 if (mode("keep-primary")) {
226 struct bfd
*prebfd
= bfd_openr(argv
[4], NULL
);
229 assert(prebfd
!= NULL
);
230 assert(bfd_check_format_matches(prebfd
, bfd_object
, &matching
));
232 struct superbfd
*presbfd
= fetch_superbfd(prebfd
);
234 handle_section_symbol_renames(presbfd
, isbfd
);
235 print_label_map(isbfd
);
238 foreach_nonmatching(presbfd
, isbfd
, print_changed_section
);
241 foreach_new_section(presbfd
, isbfd
, print_new_section
);
244 foreach_new_section(isbfd
, presbfd
, print_deleted_section
);
246 compare_exported_symbols(presbfd
, isbfd
, "");
247 compare_exported_symbols(isbfd
, presbfd
, "del_");
250 assert(bfd_close(prebfd
));
251 } else if (mode("rmsyms")) {
252 read_str_set(&rmsyms
);
255 if (mode("keep-primary")) {
256 /* Create export_desc structures for all export sections */
258 for (sect
= isbfd
->abfd
->sections
; sect
!= NULL
;
260 struct export_desc
*ed
;
261 if (!starts_with(sect
->name
, "__ksymtab") ||
262 ends_with(sect
->name
, "_strings"))
264 for (ed
= exports
.data
;
265 ed
< exports
.data
+ exports
.size
; ed
++) {
266 if (strcmp(ed
->sectname
, sect
->name
) == 0)
269 if (ed
< exports
.data
+ exports
.size
)
271 ed
= vec_grow(&exports
, 1);
272 ed
->sectname
= sect
->name
;
273 vec_init(&ed
->names
);
277 if (mode("keep") || mode("rmsyms"))
282 const struct wsect
*tmp
= wanted_sections
;
283 bfd_map_over_sections(ibfd
, mark_wanted_if_referenced
,
285 if (tmp
== wanted_sections
)
290 for (sect
= ibfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
291 asymbol
**symp
= canonical_symbolp(isbfd
, sect
->symbol
);
294 asymbol
*sym
= *symp
;
295 if (!want_section(sect
))
297 if (starts_with(sect
->name
, ".rodata.str"))
299 if ((sym
->flags
& BSF_WEAK
) != 0)
301 if ((sym
->flags
& BSF_FUNCTION
) != 0 ||
302 needed_data_section(isbfd
, sect
))
303 write_ksplice_section(isbfd
, symp
);
307 if (mode("keep-primary")) {
309 for (sect
= isbfd
->abfd
->sections
; sect
!= NULL
;
311 if (str_in_set(sect
->name
, §ions
) ||
312 (starts_with(sect
->name
, ".text") &&
313 want_section(sect
) &&
314 !str_in_set(sect
->name
, &newsects
)))
315 write_ksplice_patch(isbfd
, sect
->name
);
319 for (label
= delsects
.data
;
320 label
< delsects
.data
+ delsects
.size
; label
++)
321 write_ksplice_deleted_patch(isbfd
, *label
);
323 const struct export_desc
*ed
;
324 for (ed
= exports
.data
; ed
< exports
.data
+ exports
.size
;
326 if (starts_with(ed
->sectname
, "del___ksymtab")) {
327 const char *export_type
=
328 ed
->sectname
+ strlen("del___ksymtab");
329 const char **symname
;
330 for (symname
= ed
->names
.data
;
331 symname
< ed
->names
.data
+ ed
->names
.size
;
333 write_ksplice_export(isbfd
, *symname
,
336 rm_some_exports(isbfd
, ed
);
342 for (p
= ibfd
->sections
; p
!= NULL
; p
= p
->next
) {
343 struct supersect
*ss
= fetch_supersect(isbfd
, p
);
344 if (is_table_section(p
) || starts_with(p
->name
, ".ksplice") ||
345 strcmp(p
->name
, ".fixup") == 0)
347 if (want_section(p
) || mode("rmsyms"))
351 const struct table_section
*ss
;
353 for (ss
= table_sections
; ss
!= end_table_sections
; ss
++)
354 filter_table_section(isbfd
, ss
);
355 filter_ex_table_section(isbfd
);
358 copy_object(ibfd
, obfd
);
359 assert(bfd_close(obfd
));
360 assert(bfd_close(ibfd
));
364 struct export_vec
*get_export_syms(struct superbfd
*sbfd
)
367 struct export_vec
*exports
;
368 exports
= malloc(sizeof(*exports
));
369 assert(exports
!= NULL
);
372 for (sect
= sbfd
->abfd
->sections
; sect
!= NULL
; sect
= sect
->next
) {
373 if (!starts_with(sect
->name
, "__ksymtab") ||
374 ends_with(sect
->name
, "_strings"))
376 struct supersect
*ss
= fetch_supersect(sbfd
, sect
);
377 struct kernel_symbol
*sym
;
378 assert(ss
->contents
.size
* 2 == ss
->relocs
.size
*
379 sizeof(struct kernel_symbol
));
380 for (sym
= ss
->contents
.data
;
381 (void *)sym
< ss
->contents
.data
+ ss
->contents
.size
;
383 struct export
*exp
= vec_grow(exports
, 1);
385 read_string(ss
, (const char *const *)&sym
->name
);
392 void compare_exported_symbols(struct superbfd
*oldsbfd
,
393 struct superbfd
*newsbfd
, char *addstr
)
395 struct export_vec
*new_exports
, *old_exports
;
396 new_exports
= get_export_syms(newsbfd
);
397 if (new_exports
== NULL
)
399 old_exports
= get_export_syms(oldsbfd
);
400 struct export
*old
, *new;
401 asection
*last_sect
= NULL
;
402 struct export_desc
*ed
;
403 for (new = new_exports
->data
; new < new_exports
->data
+
404 new_exports
->size
; new++) {
406 if (old_exports
!= NULL
) {
407 for (old
= old_exports
->data
; old
< old_exports
->data
+
408 old_exports
->size
; old
++) {
409 if (strcmp(new->name
, old
->name
) == 0 &&
410 strcmp(new->sect
->name
, old
->sect
->name
)
418 if (last_sect
!= new->sect
) {
419 last_sect
= new->sect
;
420 ed
= vec_grow(&exports
, 1);
422 assert(asprintf(§name
, "%s%s", addstr
,
423 new->sect
->name
) >= 0);
424 ed
->sectname
= sectname
;
425 vec_init(&ed
->names
);
426 printf("\n%s", sectname
);
428 *vec_grow(&ed
->names
, 1) = new->name
;
429 printf(" %s", new->name
);
434 void foreach_new_section(struct superbfd
*oldsbfd
, struct superbfd
*newsbfd
,
435 void (*s_fn
)(struct superbfd
*, asection
*))
437 asection
*oldsect
, *newsect
;
438 struct supersect
*old_ss
, *new_ss
;
439 for (newsect
= newsbfd
->abfd
->sections
; newsect
!= NULL
;
440 newsect
= newsect
->next
) {
441 if (starts_with(newsect
->name
, ".rodata.str") ||
444 for (oldsect
= oldsbfd
->abfd
->sections
; oldsect
!= NULL
;
445 oldsect
= oldsect
->next
) {
446 if (strcmp(newsect
->name
, oldsect
->name
) != 0 &&
447 strcmp(label_lookup(newsbfd
, newsect
->symbol
),
448 label_lookup(oldsbfd
, oldsect
->symbol
))
451 if (!starts_with(newsect
->name
, ".rodata"))
453 new_ss
= fetch_supersect(oldsbfd
, oldsect
);
454 old_ss
= fetch_supersect(oldsbfd
, oldsect
);
455 if (old_ss
->contents
.size
!= new_ss
->contents
.size
||
456 memcmp(old_ss
->contents
.data
, new_ss
->contents
.data
,
457 old_ss
->contents
.size
) != 0)
462 s_fn(newsbfd
, newsect
);
466 void foreach_nonmatching(struct superbfd
*oldsbfd
, struct superbfd
*newsbfd
,
467 void (*s_fn
)(struct superbfd
*, asection
*))
469 asection
*newp
, *oldp
;
470 struct supersect
*old_ss
, *new_ss
;
471 for (newp
= newsbfd
->abfd
->sections
; newp
!= NULL
; newp
= newp
->next
) {
472 if (!starts_with(newp
->name
, ".text"))
474 new_ss
= fetch_supersect(newsbfd
, newp
);
475 oldp
= bfd_get_section_by_name(oldsbfd
->abfd
, newp
->name
);
478 old_ss
= fetch_supersect(oldsbfd
, oldp
);
479 if (new_ss
->contents
.size
== old_ss
->contents
.size
&&
480 memcmp(new_ss
->contents
.data
, old_ss
->contents
.data
,
481 new_ss
->contents
.size
) == 0 &&
482 relocs_equal(oldsbfd
, oldp
, newsbfd
, newp
))
488 static void handle_section_symbol_renames(struct superbfd
*oldsbfd
,
489 struct superbfd
*newsbfd
)
491 asection
*newp
, *oldp
;
492 for (newp
= newsbfd
->abfd
->sections
; newp
!= NULL
; newp
= newp
->next
) {
493 if (!starts_with(newp
->name
, ".text") &&
494 !starts_with(newp
->name
, ".data") &&
495 !starts_with(newp
->name
, ".rodata") &&
496 !starts_with(newp
->name
, ".bss"))
498 oldp
= bfd_get_section_by_name(oldsbfd
->abfd
, newp
->name
);
502 const char *old_label
= label_lookup(oldsbfd
, oldp
->symbol
);
503 const char *new_label
= label_lookup(newsbfd
, newp
->symbol
);
505 if (strcmp(old_label
, new_label
) == 0)
507 label_map_set(newsbfd
, new_label
, old_label
);
512 * relocs_equal checks to see whether the old section and the new section
513 * reference different read-only data in their relocations -- if a hard-coded
514 * string has been changed between the old file and the new file, relocs_equal
515 * will detect the difference.
517 bool relocs_equal(struct superbfd
*oldsbfd
, asection
*oldp
,
518 struct superbfd
*newsbfd
, asection
*newp
)
521 struct supersect
*old_ss
, *new_ss
;
523 old_ss
= fetch_supersect(oldsbfd
, oldp
);
524 new_ss
= fetch_supersect(newsbfd
, newp
);
526 if (old_ss
->relocs
.size
!= new_ss
->relocs
.size
)
529 for (i
= 0; i
< old_ss
->relocs
.size
; i
++) {
530 struct supersect
*ro_old_ss
, *ro_new_ss
;
532 asymbol
*old_sym
= *old_ss
->relocs
.data
[i
]->sym_ptr_ptr
;
533 asymbol
*new_sym
= *new_ss
->relocs
.data
[i
]->sym_ptr_ptr
;
535 ro_old_ss
= fetch_supersect(oldsbfd
, old_sym
->section
);
536 ro_new_ss
= fetch_supersect(newsbfd
, new_sym
->section
);
539 get_reloc_offset(old_ss
, old_ss
->relocs
.data
[i
], true);
541 get_reloc_offset(new_ss
, new_ss
->relocs
.data
[i
], true);
543 if (strcmp(ro_old_ss
->name
, ro_new_ss
->name
) != 0)
546 if (!starts_with(ro_old_ss
->name
, ".rodata")) {
547 /* for non-rodata, we just compare that the two
548 relocations are to the same offset within the same
550 if (old_sym
->value
+ old_offset
!=
551 new_sym
->value
+ new_offset
)
556 if (starts_with(ro_old_ss
->name
, ".rodata.str") &&
557 /* check it's not an out-of-range relocation to a string;
558 we'll just compare entire sections for them */
559 !(old_offset
>= ro_old_ss
->contents
.size
||
560 new_offset
>= ro_new_ss
->contents
.size
)) {
562 (ro_old_ss
->contents
.data
+ old_sym
->value
+
564 ro_new_ss
->contents
.data
+ new_sym
->value
+
570 if (ro_old_ss
->contents
.size
!= ro_new_ss
->contents
.size
)
573 if (memcmp(ro_old_ss
->contents
.data
, ro_new_ss
->contents
.data
,
574 ro_old_ss
->contents
.size
) != 0)
581 void print_changed_section(struct superbfd
*sbfd
, asection
*sect
)
583 *vec_grow(§ions
, 1) = sect
->name
;
584 printf("%s ", sect
->name
);
587 void print_new_section(struct superbfd
*sbfd
, asection
*sect
)
589 *vec_grow(&newsects
, 1) = sect
->name
;
590 printf("%s ", sect
->name
);
593 void print_deleted_section(struct superbfd
*sbfd
, asection
*sect
)
595 if (!starts_with(sect
->name
, ".text"))
597 const char *label
= label_lookup(sbfd
, sect
->symbol
);
598 *vec_grow(&delsects
, 1) = label
;
599 printf("%s ", label
);
602 void rm_some_exports(struct superbfd
*isbfd
, const struct export_desc
*ed
)
604 assert(starts_with(ed
->sectname
, "__ksymtab"));
605 const char *export_type
= ed
->sectname
+ strlen("__ksymtab");
606 asection
*sym_sect
= bfd_get_section_by_name(isbfd
->abfd
, ed
->sectname
);
607 assert(sym_sect
!= NULL
);
608 char *export_crc_name
;
609 assert(asprintf(&export_crc_name
, "__kcrctab%s", export_type
) >= 0);
610 asection
*crc_sect
= bfd_get_section_by_name(isbfd
->abfd
,
612 struct supersect
*ss
, *crc_ss
= NULL
;
613 ss
= fetch_supersect(isbfd
, sym_sect
);
614 if (crc_sect
!= NULL
)
615 crc_ss
= fetch_supersect(isbfd
, crc_sect
);
618 assert(ss
->contents
.size
* sizeof(unsigned long) ==
619 crc_ss
->contents
.size
* sizeof(struct kernel_symbol
));
621 struct supersect orig_ss
, orig_crc_ss
;
622 supersect_move(&orig_ss
, ss
);
624 supersect_move(&orig_crc_ss
, crc_ss
);
626 struct kernel_symbol
*orig_ksym
;
627 unsigned long *orig_crc
;
628 for (orig_ksym
= orig_ss
.contents
.data
,
629 orig_crc
= orig_crc_ss
.contents
.data
;
630 (void *)orig_ksym
< orig_ss
.contents
.data
+ orig_ss
.contents
.size
;
631 orig_ksym
++, orig_crc
++) {
633 read_reloc(&orig_ss
, &orig_ksym
->value
,
634 sizeof(orig_ksym
->value
), &sym
);
635 if (!str_in_set(sym
->name
, &ed
->names
))
638 struct kernel_symbol
*ksym
= sect_grow(ss
, 1, typeof(*ksym
));
639 sect_copy(ss
, &ksym
->value
, &orig_ss
, &orig_ksym
->value
, 1);
640 /* Replace name with a mangled name */
641 write_ksplice_export(ss
->parent
, sym
->name
, export_type
, false);
642 write_string(ss
, (const char **)&ksym
->name
,
643 "DISABLED_%s_%s", sym
->name
, kid
);
647 sect_grow(crc_ss
, 1, typeof(*orig_crc
)),
648 &orig_crc_ss
, orig_crc
, 1);
652 void rm_some_relocs(struct supersect
*ss
)
654 struct arelentp_vec orig_relocs
;
655 vec_move(&orig_relocs
, &ss
->relocs
);
658 for (relocp
= orig_relocs
.data
;
659 relocp
< orig_relocs
.data
+ orig_relocs
.size
; relocp
++) {
660 bool rm_reloc
= false;
661 asymbol
*sym_ptr
= *(*relocp
)->sym_ptr_ptr
;
663 if (mode("rmsyms") && str_in_set(sym_ptr
->name
, &rmsyms
) &&
664 bfd_is_und_section(sym_ptr
->section
))
670 if (mode("keep-primary") && want_section(sym_ptr
->section
) &&
671 (str_in_set(sym_ptr
->section
->name
, &newsects
) ||
672 bfd_is_const_section(sym_ptr
->section
) ||
673 starts_with(sym_ptr
->section
->name
, ".rodata.str")))
676 if (mode("finalize") && bfd_is_und_section(sym_ptr
->section
))
680 write_ksplice_reloc(ss
, *relocp
);
682 *vec_grow(&ss
->relocs
, 1) = *relocp
;
686 struct supersect
*make_section(struct superbfd
*sbfd
, const char *name
)
688 asection
*sect
= bfd_get_section_by_name(sbfd
->abfd
, name
);
690 return fetch_supersect(sbfd
, sect
);
692 return new_supersect(sbfd
, name
);
695 arelent
*create_reloc(struct supersect
*ss
, const void *addr
, asymbol
**symp
,
698 bfd_reloc_code_real_type code
;
699 switch (bfd_arch_bits_per_address(ss
->parent
->abfd
)) {
710 arelent
*reloc
= malloc(sizeof(*reloc
));
711 reloc
->sym_ptr_ptr
= symp
;
712 reloc
->address
= addr
- ss
->contents
.data
;
713 reloc
->howto
= bfd_reloc_type_lookup(ss
->parent
->abfd
, code
);
714 reloc
->addend
= offset
;
718 void write_reloc(struct supersect
*ss
, const void *addr
, asymbol
**symp
,
721 arelent
*new_reloc
= create_reloc(ss
, addr
, symp
, offset
), **relocp
;
722 for (relocp
= ss
->relocs
.data
;
723 relocp
< ss
->relocs
.data
+ ss
->relocs
.size
; relocp
++) {
724 if ((*relocp
)->address
== new_reloc
->address
) {
727 (void *)(ss
->relocs
.data
+ ss
->relocs
.size
) -
728 (void *)(relocp
+ 1));
733 *vec_grow(&ss
->new_relocs
, 1) = new_reloc
;
736 void write_string(struct supersect
*ss
, const char **addr
, const char *fmt
, ...)
739 struct supersect
*str_ss
= make_section(ss
->parent
, ".ksplice_str");
742 int len
= vasprintf(&str
, fmt
, ap
);
746 unsigned long *str_offp
= ulong_hash_lookup(&ksplice_string_offset
, str
,
748 if (str_offp
== NULL
) {
749 char *buf
= sect_grow(str_ss
, len
+ 1, char);
750 memcpy(buf
, str
, len
+ 1);
751 str_offp
= ulong_hash_lookup(&ksplice_string_offset
, str
, TRUE
);
752 *str_offp
= (void *)buf
- str_ss
->contents
.data
;
755 write_reloc(ss
, addr
, &str_ss
->symbol
, *str_offp
);
758 void lookup_system_map(struct addr_vec
*addrs
, const char *name
, long offset
)
760 struct addr_vec
*map_addrs
=
761 addr_vec_hash_lookup(&system_map
, name
, FALSE
);
762 if (map_addrs
== NULL
)
765 unsigned long *addr
, *map_addr
;
766 for (map_addr
= map_addrs
->data
;
767 map_addr
< map_addrs
->data
+ map_addrs
->size
; map_addr
++) {
768 for (addr
= addrs
->data
; addr
< addrs
->data
+ addrs
->size
;
770 if (*addr
== *map_addr
+ offset
)
773 if (addr
< addrs
->data
+ addrs
->size
)
775 *vec_grow(addrs
, 1) = *map_addr
+ offset
;
779 void write_system_map_array(struct superbfd
*sbfd
, struct supersect
*ss
,
780 const unsigned long **sym_addrs
,
781 unsigned long *num_sym_addrs
, asymbol
*sym
)
783 struct addr_vec addrs
;
786 if (bfd_is_abs_section(sym
->section
)) {
787 *vec_grow(&addrs
, 1) = sym
->value
;
788 } else if (bfd_is_und_section(sym
->section
)) {
789 lookup_system_map(&addrs
, sym
->name
, 0);
790 } else if (!bfd_is_const_section(sym
->section
)) {
792 for (gsymp
= sbfd
->syms
.data
;
793 gsymp
< sbfd
->syms
.data
+ sbfd
->syms
.size
; gsymp
++) {
794 asymbol
*gsym
= *gsymp
;
795 if ((gsym
->flags
& BSF_DEBUGGING
) == 0 &&
796 gsym
->section
== sym
->section
)
797 lookup_system_map(&addrs
, gsym
->name
,
798 sym
->value
- gsym
->value
);
802 *num_sym_addrs
= addrs
.size
;
803 if (addrs
.size
!= 0) {
804 struct supersect
*array_ss
= make_section(sbfd
,
806 void *buf
= sect_grow(array_ss
, addrs
.size
,
807 typeof(*addrs
.data
));
808 memcpy(buf
, addrs
.data
, addrs
.size
* sizeof(*addrs
.data
));
809 write_reloc(ss
, sym_addrs
, &array_ss
->symbol
,
810 buf
- array_ss
->contents
.data
);
818 void write_ksplice_system_map(struct superbfd
*sbfd
, asymbol
*sym
,
819 const char *addstr_sect
)
821 struct supersect
*smap_ss
= make_section(sbfd
, ".ksplice_system_map");
822 struct ksplice_system_map
*smap
;
823 const char *label
= label_lookup(sbfd
, sym
);
825 bool *done
= bool_hash_lookup(&system_map_written
, label
, TRUE
);
830 smap
= sect_grow(smap_ss
, 1, struct ksplice_system_map
);
832 write_system_map_array(sbfd
, smap_ss
, &smap
->candidates
,
833 &smap
->nr_candidates
, sym
);
834 write_string(smap_ss
, &smap
->label
, "%s%s", label
, addstr_sect
);
837 void write_ksplice_symbol(struct supersect
*ss
,
838 const struct ksplice_symbol
*const *addr
,
839 asymbol
*sym
, const char *addstr_sect
)
841 struct supersect
*ksymbol_ss
= make_section(ss
->parent
,
843 struct ksplice_symbol
*ksymbol
;
844 unsigned long *ksymbol_offp
;
845 const char *label
= label_lookup(ss
->parent
, sym
);
847 assert(asprintf(&output
, "%s%s", label
, addstr_sect
) >= 0);
849 ksymbol_offp
= ulong_hash_lookup(&ksplice_symbol_offset
, output
, FALSE
);
850 if (ksymbol_offp
!= NULL
) {
851 write_reloc(ss
, addr
, &ksymbol_ss
->symbol
, *ksymbol_offp
);
854 ksymbol
= sect_grow(ksymbol_ss
, 1, struct ksplice_symbol
);
855 ksymbol_offp
= ulong_hash_lookup(&ksplice_symbol_offset
, output
, TRUE
);
856 *ksymbol_offp
= (void *)ksymbol
- ksymbol_ss
->contents
.data
;
858 if (bfd_is_und_section(sym
->section
) || (sym
->flags
& BSF_GLOBAL
) != 0) {
859 write_string(ksymbol_ss
, &ksymbol
->name
, "%s", sym
->name
);
860 } else if (bfd_is_const_section(sym
->section
)) {
861 ksymbol
->name
= NULL
;
863 asymbol
*gsym
= canonical_symbol(ss
->parent
, sym
);
866 ksymbol
->name
= NULL
;
868 write_string(ksymbol_ss
, &ksymbol
->name
, "%s",
872 write_string(ksymbol_ss
, &ksymbol
->label
, "%s%s", label
, addstr_sect
);
874 write_ksplice_system_map(ksymbol_ss
->parent
, sym
, addstr_sect
);
876 write_reloc(ss
, addr
, &ksymbol_ss
->symbol
, *ksymbol_offp
);
879 void write_ksplice_reloc(struct supersect
*ss
, arelent
*orig_reloc
)
881 asymbol
*sym_ptr
= *orig_reloc
->sym_ptr_ptr
;
882 reloc_howto_type
*howto
= orig_reloc
->howto
;
883 bfd_vma addend
= get_reloc_offset(ss
, orig_reloc
, false);
885 if (mode("finalize") && starts_with(ss
->name
, ".ksplice_patches")) {
886 unsigned long *repladdr
=
887 ss
->contents
.data
+ orig_reloc
->address
;
892 blot_section(ss
, orig_reloc
->address
, howto
);
894 struct supersect
*kreloc_ss
= make_section(ss
->parent
,
896 ".ksplice_init_relocs" :
898 struct ksplice_reloc
*kreloc
= sect_grow(kreloc_ss
, 1,
899 struct ksplice_reloc
);
901 write_reloc(kreloc_ss
, &kreloc
->blank_addr
,
902 &ss
->symbol
, orig_reloc
->address
);
903 kreloc
->blank_offset
= (unsigned long)orig_reloc
->address
;
904 write_ksplice_symbol(kreloc_ss
, &kreloc
->symbol
, sym_ptr
, "");
905 kreloc
->pcrel
= howto
->pc_relative
;
906 kreloc
->addend
= addend
;
907 kreloc
->size
= bfd_get_reloc_size(howto
);
908 kreloc
->dst_mask
= howto
->dst_mask
;
909 kreloc
->rightshift
= howto
->rightshift
;
910 kreloc
->signed_addend
=
911 (howto
->complain_on_overflow
== complain_overflow_signed
) ||
912 (howto
->complain_on_overflow
== complain_overflow_bitfield
);
915 #define CANARY(x, canary) ((x & ~howto->dst_mask) | (canary & howto->dst_mask))
917 void blot_section(struct supersect
*ss
, int offset
, reloc_howto_type
*howto
)
919 int bits
= bfd_get_reloc_size(howto
) * 8;
920 void *address
= ss
->contents
.data
+ offset
;
921 bfd_vma x
= bfd_get(bits
, ss
->parent
->abfd
, address
);
922 x
= (x
& ~howto
->dst_mask
) |
923 ((bfd_vma
)KSPLICE_CANARY
& howto
->dst_mask
);
924 bfd_put(bits
, ss
->parent
->abfd
, x
, address
);
927 void write_ksplice_section(struct superbfd
*sbfd
, asymbol
**symp
)
929 asymbol
*sym
= *symp
;
930 struct supersect
*ksect_ss
= make_section(sbfd
, ".ksplice_sections");
931 struct ksplice_section
*ksect
= sect_grow(ksect_ss
, 1,
932 struct ksplice_section
);
934 write_ksplice_symbol(ksect_ss
, &ksect
->symbol
, sym
,
935 mode("keep-primary") ? "(post)" : "");
936 ksect
->size
= bfd_get_section_size(sym
->section
);
938 if (starts_with(sym
->section
->name
, ".rodata"))
939 ksect
->flags
|= KSPLICE_SECTION_RODATA
;
940 if (starts_with(sym
->section
->name
, ".data"))
941 ksect
->flags
|= KSPLICE_SECTION_DATA
;
942 if (starts_with(sym
->section
->name
, ".text") ||
943 starts_with(sym
->section
->name
, ".exit.text"))
944 ksect
->flags
|= KSPLICE_SECTION_TEXT
;
945 assert(ksect
->flags
!= 0);
946 write_reloc(ksect_ss
, &ksect
->address
, symp
, 0);
949 void write_ksplice_patch(struct superbfd
*sbfd
, const char *sectname
)
951 struct supersect
*kpatch_ss
= make_section(sbfd
, ".ksplice_patches");
952 struct ksplice_patch
*kpatch
= sect_grow(kpatch_ss
, 1,
953 struct ksplice_patch
);
954 asection
*sect
= bfd_get_section_by_name(sbfd
->abfd
, sectname
);
955 assert(sect
!= NULL
);
957 write_string(kpatch_ss
, &kpatch
->label
, "%s",
958 label_lookup(sbfd
, sect
->symbol
));
959 write_reloc(kpatch_ss
, &kpatch
->repladdr
, §
->symbol
, 0);
962 void write_ksplice_deleted_patch(struct superbfd
*sbfd
, const char *label
)
964 struct supersect
*kpatch_ss
= make_section(sbfd
, ".ksplice_patches");
965 struct ksplice_patch
*kpatch
= sect_grow(kpatch_ss
, 1,
966 struct ksplice_patch
);
968 write_string(kpatch_ss
, &kpatch
->label
, "%s", label
);
969 const char *orig_label
= lookup_orig_label(sbfd
, label
);
970 if (orig_label
== NULL
)
973 for (symp
= sbfd
->syms
.data
; symp
< sbfd
->syms
.data
+ sbfd
->syms
.size
;
975 asymbol
*sym
= *symp
;
976 if (bfd_is_und_section(sym
->section
) &&
977 strcmp(orig_label
, sym
->name
) == 0)
980 if (symp
>= sbfd
->syms
.data
+ sbfd
->syms
.size
)
982 write_reloc(kpatch_ss
, &kpatch
->repladdr
, symp
, 0);
985 void write_ksplice_export(struct superbfd
*sbfd
, const char *symname
,
986 const char *export_type
, bool del
)
988 struct supersect
*export_ss
= make_section(sbfd
, ".ksplice_exports");
989 struct ksplice_export
*exp
= sect_grow(export_ss
, 1,
990 struct ksplice_export
);
993 write_string(export_ss
, &exp
->name
, "%s", symname
);
994 write_string(export_ss
, &exp
->new_name
, "DISABLED_%s_%s",
997 write_string(export_ss
, &exp
->new_name
, "%s", symname
);
998 write_string(export_ss
, &exp
->name
, "DISABLED_%s_%s", symname
,
1003 void filter_table_section(struct superbfd
*sbfd
, const struct table_section
*s
)
1005 asection
*isection
= bfd_get_section_by_name(sbfd
->abfd
, s
->sectname
);
1006 if (isection
== NULL
)
1009 struct supersect
*ss
= fetch_supersect(sbfd
, isection
), orig_ss
;
1010 supersect_move(&orig_ss
, ss
);
1012 const void *orig_entry
;
1013 for (orig_entry
= orig_ss
.contents
.data
;
1014 orig_entry
< orig_ss
.contents
.data
+ orig_ss
.contents
.size
;
1015 orig_entry
+= align(s
->entry_size
, 1 << ss
->alignment
)) {
1017 read_reloc(&orig_ss
, orig_entry
, sizeof(void *), &sym
);
1020 for (p
= sbfd
->abfd
->sections
; p
!= NULL
; p
= p
->next
) {
1021 if (sym
->section
== p
1022 && !is_table_section(p
) && !want_section(p
))
1028 sect_copy(ss
, sect_do_grow(ss
, 1, s
->entry_size
,
1029 1 << ss
->alignment
),
1030 &orig_ss
, orig_entry
, s
->entry_size
);
1034 struct fixup_entry
{
1039 DECLARE_VEC_TYPE(struct fixup_entry
, fixup_entry_vec
);
1041 int compare_fixups(const void *aptr
, const void *bptr
)
1043 const struct fixup_entry
*a
= aptr
, *b
= bptr
;
1044 if (a
->offset
< b
->offset
)
1046 else if (a
->offset
> b
->offset
)
1049 return (int)a
->used
- (int)b
->used
;
1052 void filter_ex_table_section(struct superbfd
*sbfd
)
1054 asection
*isection
= bfd_get_section_by_name(sbfd
->abfd
, "__ex_table");
1055 if (isection
== NULL
)
1057 asection
*fixup_sect
= bfd_get_section_by_name(sbfd
->abfd
, ".fixup");
1059 struct supersect
*ss
= fetch_supersect(sbfd
, isection
), orig_ss
;
1060 supersect_move(&orig_ss
, ss
);
1062 struct supersect
*fixup_ss
= NULL
;
1063 if (fixup_sect
!= NULL
)
1064 fixup_ss
= fetch_supersect(sbfd
, fixup_sect
);
1066 struct fixup_entry_vec fixups
;
1069 const struct exception_table_entry
*orig_entry
;
1070 for (orig_entry
= orig_ss
.contents
.data
;
1071 (void *)orig_entry
< orig_ss
.contents
.data
+ orig_ss
.contents
.size
;
1073 asymbol
*sym
, *fixup_sym
;
1074 read_reloc(&orig_ss
, &orig_entry
->insn
,
1075 sizeof(orig_entry
->insn
), &sym
);
1077 struct fixup_entry
*f
;
1078 bfd_vma fixup_offset
= read_reloc(&orig_ss
, &orig_entry
->fixup
,
1079 sizeof(orig_entry
->fixup
),
1081 if (fixup_sym
->section
== fixup_sect
) {
1082 assert(fixup_offset
< fixup_ss
->contents
.size
);
1083 f
= vec_grow(&fixups
, 1);
1084 f
->offset
= fixup_offset
;
1089 for (p
= sbfd
->abfd
->sections
; p
!= NULL
; p
= p
->next
) {
1090 if (sym
->section
== p
1091 && !is_table_section(p
) && !want_section(p
))
1097 if (fixup_sym
->section
== fixup_sect
) {
1099 f
->ex_offset
= ss
->contents
.size
+
1100 offsetof(struct exception_table_entry
, fixup
);
1102 sect_copy(ss
, sect_grow(ss
, 1, struct exception_table_entry
),
1103 &orig_ss
, orig_entry
, 1);
1106 if (fixup_sect
== NULL
)
1109 struct supersect orig_fixup_ss
;
1110 supersect_move(&orig_fixup_ss
, fixup_ss
);
1112 qsort(fixups
.data
, fixups
.size
, sizeof(*fixups
.data
), compare_fixups
);
1113 *vec_grow(&fixups
, 1) = (struct fixup_entry
)
1114 { .offset
= orig_fixup_ss
.contents
.size
, .used
= false };
1116 struct fixup_entry
*f
;
1117 for (f
= fixups
.data
; f
< fixups
.data
+ fixups
.size
- 1; f
++) {
1120 write_reloc(ss
, ss
->contents
.data
+ f
->ex_offset
,
1121 &fixup_ss
->symbol
, fixup_ss
->contents
.size
);
1123 sect_grow(fixup_ss
, (f
+ 1)->offset
- f
->offset
,
1126 orig_fixup_ss
.contents
.data
+ f
->offset
,
1127 (f
+ 1)->offset
- f
->offset
);
1131 void mark_wanted_if_referenced(bfd
*abfd
, asection
*sect
, void *ignored
)
1133 if (want_section(sect
))
1135 if (!starts_with(sect
->name
, ".text")
1136 && !starts_with(sect
->name
, ".exit.text")
1137 && !starts_with(sect
->name
, ".rodata")
1138 && !(starts_with(sect
->name
, ".data") && mode("keep-helper")))
1141 if (mode("keep-helper")) {
1142 struct superbfd
*sbfd
= fetch_superbfd(abfd
);
1144 for (symp
= sbfd
->syms
.data
;
1145 symp
< sbfd
->syms
.data
+ sbfd
->syms
.size
; symp
++) {
1146 asymbol
*sym
= *symp
;
1147 if (sym
->section
== sect
&&
1148 (sym
->flags
& BSF_GLOBAL
) != 0) {
1149 struct wsect
*w
= malloc(sizeof(*w
));
1151 w
->next
= wanted_sections
;
1152 wanted_sections
= w
;
1158 bfd_map_over_sections(abfd
, check_for_ref_to_section
, sect
);
1161 void check_for_ref_to_section(bfd
*abfd
, asection
*looking_at
,
1164 if (!want_section(looking_at
) || is_table_section(looking_at
))
1167 struct superbfd
*sbfd
= fetch_superbfd(abfd
);
1168 struct supersect
*ss
= fetch_supersect(sbfd
, looking_at
);
1170 for (relocp
= ss
->relocs
.data
;
1171 relocp
< ss
->relocs
.data
+ ss
->relocs
.size
; relocp
++) {
1172 asymbol
*sym
= *(*relocp
)->sym_ptr_ptr
;
1173 if (sym
->section
== (asection
*)looking_for
&&
1174 (!starts_with(sym
->section
->name
, ".text") ||
1175 (get_reloc_offset(ss
, *relocp
, true) != 0 &&
1176 strcmp(looking_at
->name
, ".fixup") != 0))) {
1177 struct wsect
*w
= malloc(sizeof(*w
));
1178 w
->sect
= looking_for
;
1179 w
->next
= wanted_sections
;
1180 wanted_sections
= w
;
1186 /* Modified function from GNU Binutils objcopy.c */
1187 bfd_boolean
copy_object(bfd
*ibfd
, bfd
*obfd
)
1189 assert(bfd_set_format(obfd
, bfd_get_format(ibfd
)));
1191 bfd_vma start
= bfd_get_start_address(ibfd
);
1193 flagword flags
= bfd_get_file_flags(ibfd
);
1194 flags
&= bfd_applicable_file_flags(obfd
);
1196 assert(bfd_set_start_address(obfd
, start
)
1197 && bfd_set_file_flags(obfd
, flags
));
1199 enum bfd_architecture iarch
= bfd_get_arch(ibfd
);
1200 unsigned int imach
= bfd_get_mach(ibfd
);
1201 assert(bfd_set_arch_mach(obfd
, iarch
, imach
));
1202 assert(bfd_set_format(obfd
, bfd_get_format(ibfd
)));
1204 /* BFD mandates that all output sections be created and sizes set before
1205 any output is done. Thus, we traverse all sections multiple times. */
1206 bfd_map_over_sections(ibfd
, setup_section
, obfd
);
1208 struct supersect
*new_supersects
= fetch_superbfd(ibfd
)->new_supersects
;
1209 struct supersect
*ss
;
1210 for (ss
= new_supersects
; ss
!= NULL
; ss
= ss
->next
)
1211 setup_new_section(obfd
, ss
);
1213 /* Mark symbols used in output relocations so that they
1214 are kept, even if they are local labels or static symbols.
1216 Note we iterate over the input sections examining their
1217 relocations since the relocations for the output sections
1218 haven't been set yet. mark_symbols_used_in_relocations will
1219 ignore input sections which have no corresponding output
1222 bfd_map_over_sections(ibfd
, mark_symbols_used_in_relocations
, NULL
);
1223 for (ss
= new_supersects
; ss
!= NULL
; ss
= ss
->next
)
1224 ss_mark_symbols_used_in_relocations(ss
);
1225 struct asymbolp_vec osyms
;
1227 filter_symbols(ibfd
, obfd
, &osyms
, &fetch_superbfd(ibfd
)->syms
);
1229 bfd_set_symtab(obfd
, osyms
.data
, osyms
.size
);
1231 /* This has to happen after the symbol table has been set. */
1232 bfd_map_over_sections(obfd
, write_section
, NULL
);
1234 /* Allow the BFD backend to copy any private data it understands
1235 from the input BFD to the output BFD. This is done last to
1236 permit the routine to look at the filtered symbol table, which is
1237 important for the ECOFF code at least. */
1238 assert(bfd_copy_private_bfd_data(ibfd
, obfd
));
1243 /* Modified function from GNU Binutils objcopy.c */
1244 void setup_section(bfd
*ibfd
, asection
*isection
, void *obfdarg
)
1246 bfd
*obfd
= obfdarg
;
1249 if (!want_section(isection
))
1252 asection
*osection
= bfd_make_section_anyway(obfd
, isection
->name
);
1253 assert(osection
!= NULL
);
1255 struct superbfd
*isbfd
= fetch_superbfd(ibfd
);
1256 struct supersect
*ss
= fetch_supersect(isbfd
, isection
);
1257 osection
->userdata
= ss
;
1258 bfd_set_section_flags(obfd
, osection
, ss
->flags
);
1259 ss
->symbol
= osection
->symbol
;
1260 assert(bfd_set_section_size(obfd
, osection
, ss
->contents
.size
));
1262 vma
= bfd_section_vma(ibfd
, isection
);
1263 assert(bfd_set_section_vma(obfd
, osection
, vma
));
1265 osection
->lma
= isection
->lma
;
1266 assert(bfd_set_section_alignment(obfd
, osection
, ss
->alignment
));
1267 osection
->entsize
= isection
->entsize
;
1268 osection
->output_section
= osection
;
1269 osection
->output_offset
= 0;
1270 isection
->output_section
= osection
;
1271 isection
->output_offset
= 0;
1275 void setup_new_section(bfd
*obfd
, struct supersect
*ss
)
1277 asection
*osection
= bfd_make_section_anyway(obfd
, ss
->name
);
1278 assert(osection
!= NULL
);
1279 bfd_set_section_flags(obfd
, osection
, ss
->flags
);
1281 osection
->userdata
= ss
;
1282 ss
->symbol
= osection
->symbol
;
1283 assert(bfd_set_section_size(obfd
, osection
, ss
->contents
.size
));
1284 assert(bfd_set_section_vma(obfd
, osection
, 0));
1287 assert(bfd_set_section_alignment(obfd
, osection
, ss
->alignment
));
1288 osection
->entsize
= 0;
1289 osection
->output_section
= osection
;
1290 osection
->output_offset
= 0;
1293 void write_section(bfd
*obfd
, asection
*osection
, void *arg
)
1295 struct supersect
*ss
= osection
->userdata
;
1297 if ((ss
->flags
& SEC_GROUP
) != 0 || ss
->contents
.size
== 0)
1301 char *error_message
;
1302 for (relocp
= ss
->new_relocs
.data
;
1303 relocp
< ss
->new_relocs
.data
+ ss
->new_relocs
.size
; relocp
++) {
1305 if (bfd_get_arch(obfd
) == bfd_arch_arm
)
1306 val
= osection
->use_rela_p
? 0 : (*relocp
)->addend
;
1309 bfd_put(bfd_get_reloc_size((*relocp
)->howto
) * 8, obfd
, val
,
1310 ss
->contents
.data
+ (*relocp
)->address
);
1311 if (bfd_install_relocation(obfd
, *relocp
, ss
->contents
.data
,
1312 0, osection
, &error_message
) !=
1314 fprintf(stderr
, "ksplice: error installing reloc: %s",
1319 memcpy(vec_grow(&ss
->relocs
, ss
->new_relocs
.size
), ss
->new_relocs
.data
,
1320 ss
->new_relocs
.size
* sizeof(*ss
->new_relocs
.data
));
1322 bfd_set_reloc(obfd
, osection
,
1323 ss
->relocs
.size
== 0 ? NULL
: ss
->relocs
.data
,
1326 if (ss
->flags
& SEC_HAS_CONTENTS
)
1327 assert(bfd_set_section_contents
1328 (obfd
, osection
, ss
->contents
.data
, 0,
1329 ss
->contents
.size
));
1332 /* Modified function from GNU Binutils objcopy.c
1334 * Mark all the symbols which will be used in output relocations with
1335 * the BSF_KEEP flag so that those symbols will not be stripped.
1337 * Ignore relocations which will not appear in the output file.
1339 void mark_symbols_used_in_relocations(bfd
*abfd
, asection
*isection
,
1342 struct superbfd
*sbfd
= fetch_superbfd(abfd
);
1343 if (isection
->output_section
== NULL
)
1346 struct supersect
*ss
= fetch_supersect(sbfd
, isection
);
1347 ss_mark_symbols_used_in_relocations(ss
);
1350 void ss_mark_symbols_used_in_relocations(struct supersect
*ss
)
1352 /* Examine each symbol used in a relocation. If it's not one of the
1353 special bfd section symbols, then mark it with BSF_KEEP. */
1355 for (relocp
= ss
->relocs
.data
;
1356 relocp
< ss
->relocs
.data
+ ss
->relocs
.size
; relocp
++) {
1357 asymbol
*sym
= *(*relocp
)->sym_ptr_ptr
;
1358 if (!(bfd_is_const_section(sym
->section
) &&
1359 sym
== sym
->section
->symbol
))
1360 sym
->flags
|= BSF_KEEP
;
1362 for (relocp
= ss
->new_relocs
.data
;
1363 relocp
< ss
->new_relocs
.data
+ ss
->new_relocs
.size
; relocp
++) {
1364 asymbol
*sym
= *(*relocp
)->sym_ptr_ptr
;
1365 if (!(bfd_is_const_section(sym
->section
) &&
1366 sym
== sym
->section
->symbol
))
1367 sym
->flags
|= BSF_KEEP
;
1371 static bool deleted_table_section_symbol(bfd
*abfd
, asymbol
*sym
)
1373 struct superbfd
*sbfd
= fetch_superbfd(abfd
);
1374 struct supersect
*ss
= fetch_supersect(sbfd
, sym
->section
);
1376 if (bfd_is_const_section(sym
->section
))
1380 for (symp
= ss
->syms
.data
; symp
< ss
->syms
.data
+ ss
->syms
.size
; symp
++) {
1384 return symp
>= ss
->syms
.data
+ ss
->syms
.size
;
1387 /* Modified function from GNU Binutils objcopy.c
1389 * Choose which symbol entries to copy.
1390 * We don't copy in place, because that confuses the relocs.
1391 * Return the number of symbols to print.
1393 void filter_symbols(bfd
*ibfd
, bfd
*obfd
, struct asymbolp_vec
*osyms
,
1394 struct asymbolp_vec
*isyms
)
1397 for (symp
= isyms
->data
; symp
< isyms
->data
+ isyms
->size
; symp
++) {
1398 asymbol
*sym
= *symp
;
1402 if (mode("keep") && (sym
->flags
& BSF_GLOBAL
) != 0 &&
1403 !(mode("keep-primary") &&
1404 str_in_set(sym
->section
->name
, &newsects
)))
1405 sym
->flags
= (sym
->flags
& ~BSF_GLOBAL
) | BSF_LOCAL
;
1407 if (mode("finalize") && (sym
->flags
& BSF_GLOBAL
) != 0)
1408 sym
->flags
= (sym
->flags
& ~BSF_GLOBAL
) | BSF_LOCAL
;
1410 if ((sym
->flags
& BSF_KEEP
) != 0 /* Used in relocation. */
1411 || ((sym
->flags
& BSF_SECTION_SYM
) != 0 &&
1412 want_section(fetch_superbfd(ibfd
), sym
->section
)))
1414 else if ((sym
->flags
& (BSF_GLOBAL
| BSF_WEAK
)) != 0 &&
1415 want_section(sym
->section
))
1417 else if (mode("keep-primary") &&
1418 starts_with(sym
->section
->name
, "__ksymtab"))
1421 if (deleted_table_section_symbol(ibfd
, sym
))
1424 if (bfd_is_com_section(sym
->section
))
1428 keep
= !str_in_set(sym
->name
, &rmsyms
);
1431 *vec_grow(osyms
, 1) = sym
;
1435 void read_str_set(struct str_vec
*strs
)
1439 assert(getline(&buf
, &n
, stdin
) >= 0);
1443 char *str
= strtok_r(buf
, " \n", &saveptr
);
1447 *vec_grow(strs
, 1) = str
;
1451 bool str_in_set(const char *str
, const struct str_vec
*strs
)
1454 for (strp
= strs
->data
; strp
< strs
->data
+ strs
->size
; strp
++) {
1455 if (strcmp(str
, *strp
) == 0)
1461 bool want_section(asection
*sect
)
1466 if (mode("keep-primary") && bfd_is_abs_section(sect
))
1468 const struct wsect
*w
= wanted_sections
;
1469 for (; w
!= NULL
; w
= w
->next
) {
1470 if (w
->sect
== sect
)
1474 if (starts_with(sect
->name
, ".ksplice"))
1476 if (mode("keep-helper") && starts_with(sect
->name
, ".text"))
1478 if (mode("keep-helper") && starts_with(sect
->name
, ".exit.text")
1479 && bfd_get_section_by_name(sect
->owner
, ".exitcall.exit") == NULL
)
1481 if (mode("keep-primary") && str_in_set(sect
->name
, §ions
))
1483 if (mode("keep-primary") && str_in_set(sect
->name
, &newsects
))
1486 if (mode("keep-helper") && starts_with(sect
->name
, "__ksymtab"))
1488 if (mode("keep-helper") && starts_with(sect
->name
, "__kcrctab"))
1491 if (is_special(sect
))
1497 bool is_table_section(asection
*sect
)
1499 const struct table_section
*ss
;
1500 for (ss
= table_sections
; ss
!= end_table_sections
; ss
++) {
1501 if (strcmp(ss
->sectname
, sect
->name
) == 0)
1504 if (strcmp(sect
->name
, "__ex_table") == 0)