]>
git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blob - tools/objtool/elf.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * elf.c - ELF access library
5 * Adapted from kpatch (https://github.com/dynup/kpatch):
6 * Copyright (C) 2013-2015 Josh Poimboeuf <jpoimboe@redhat.com>
7 * Copyright (C) 2014 Seth Jennings <sjenning@redhat.com>
10 #include <sys/types.h>
23 #define MAX_NAME_LEN 128
25 static inline u32
str_hash(const char *str
)
27 return jhash(str
, strlen(str
), 0);
30 static inline int elf_hash_bits(void)
32 return vmlinux
? ELF_HASH_BITS
: 16;
35 #define elf_hash_add(hashtable, node, key) \
36 hlist_add_head(node, &hashtable[hash_min(key, elf_hash_bits())])
38 static void elf_hash_init(struct hlist_head
*table
)
40 __hash_init(table
, 1U << elf_hash_bits());
43 #define elf_hash_for_each_possible(name, obj, member, key) \
44 hlist_for_each_entry(obj, &name[hash_min(key, elf_hash_bits())], member)
46 static void rb_add(struct rb_root
*tree
, struct rb_node
*node
,
47 int (*cmp
)(struct rb_node
*, const struct rb_node
*))
49 struct rb_node
**link
= &tree
->rb_node
;
50 struct rb_node
*parent
= NULL
;
54 if (cmp(node
, parent
) < 0)
55 link
= &parent
->rb_left
;
57 link
= &parent
->rb_right
;
60 rb_link_node(node
, parent
, link
);
61 rb_insert_color(node
, tree
);
64 static struct rb_node
*rb_find_first(const struct rb_root
*tree
, const void *key
,
65 int (*cmp
)(const void *key
, const struct rb_node
*))
67 struct rb_node
*node
= tree
->rb_node
;
68 struct rb_node
*match
= NULL
;
71 int c
= cmp(key
, node
);
77 node
= node
->rb_right
;
84 static struct rb_node
*rb_next_match(struct rb_node
*node
, const void *key
,
85 int (*cmp
)(const void *key
, const struct rb_node
*))
88 if (node
&& cmp(key
, node
))
93 #define rb_for_each(tree, node, key, cmp) \
94 for ((node) = rb_find_first((tree), (key), (cmp)); \
95 (node); (node) = rb_next_match((node), (key), (cmp)))
97 static int symbol_to_offset(struct rb_node
*a
, const struct rb_node
*b
)
99 struct symbol
*sa
= rb_entry(a
, struct symbol
, node
);
100 struct symbol
*sb
= rb_entry(b
, struct symbol
, node
);
102 if (sa
->offset
< sb
->offset
)
104 if (sa
->offset
> sb
->offset
)
107 if (sa
->len
< sb
->len
)
109 if (sa
->len
> sb
->len
)
117 static int symbol_by_offset(const void *key
, const struct rb_node
*node
)
119 const struct symbol
*s
= rb_entry(node
, struct symbol
, node
);
120 const unsigned long *o
= key
;
124 if (*o
>= s
->offset
+ s
->len
)
130 struct section
*find_section_by_name(const struct elf
*elf
, const char *name
)
134 elf_hash_for_each_possible(elf
->section_name_hash
, sec
, name_hash
, str_hash(name
))
135 if (!strcmp(sec
->name
, name
))
141 static struct section
*find_section_by_index(struct elf
*elf
,
146 elf_hash_for_each_possible(elf
->section_hash
, sec
, hash
, idx
)
153 static struct symbol
*find_symbol_by_index(struct elf
*elf
, unsigned int idx
)
157 elf_hash_for_each_possible(elf
->symbol_hash
, sym
, hash
, idx
)
164 struct symbol
*find_symbol_by_offset(struct section
*sec
, unsigned long offset
)
166 struct rb_node
*node
;
168 rb_for_each(&sec
->symbol_tree
, node
, &offset
, symbol_by_offset
) {
169 struct symbol
*s
= rb_entry(node
, struct symbol
, node
);
171 if (s
->offset
== offset
&& s
->type
!= STT_SECTION
)
178 struct symbol
*find_func_by_offset(struct section
*sec
, unsigned long offset
)
180 struct rb_node
*node
;
182 rb_for_each(&sec
->symbol_tree
, node
, &offset
, symbol_by_offset
) {
183 struct symbol
*s
= rb_entry(node
, struct symbol
, node
);
185 if (s
->offset
== offset
&& s
->type
== STT_FUNC
)
192 struct symbol
*find_symbol_containing(const struct section
*sec
, unsigned long offset
)
194 struct rb_node
*node
;
196 rb_for_each(&sec
->symbol_tree
, node
, &offset
, symbol_by_offset
) {
197 struct symbol
*s
= rb_entry(node
, struct symbol
, node
);
199 if (s
->type
!= STT_SECTION
)
206 struct symbol
*find_func_containing(struct section
*sec
, unsigned long offset
)
208 struct rb_node
*node
;
210 rb_for_each(&sec
->symbol_tree
, node
, &offset
, symbol_by_offset
) {
211 struct symbol
*s
= rb_entry(node
, struct symbol
, node
);
213 if (s
->type
== STT_FUNC
)
220 struct symbol
*find_symbol_by_name(const struct elf
*elf
, const char *name
)
224 elf_hash_for_each_possible(elf
->symbol_name_hash
, sym
, name_hash
, str_hash(name
))
225 if (!strcmp(sym
->name
, name
))
231 struct reloc
*find_reloc_by_dest_range(const struct elf
*elf
, struct section
*sec
,
232 unsigned long offset
, unsigned int len
)
234 struct reloc
*reloc
, *r
= NULL
;
242 for_offset_range(o
, offset
, offset
+ len
) {
243 elf_hash_for_each_possible(elf
->reloc_hash
, reloc
, hash
,
244 sec_offset_hash(sec
, o
)) {
245 if (reloc
->sec
!= sec
)
248 if (reloc
->offset
>= offset
&& reloc
->offset
< offset
+ len
) {
249 if (!r
|| reloc
->offset
< r
->offset
)
260 struct reloc
*find_reloc_by_dest(const struct elf
*elf
, struct section
*sec
, unsigned long offset
)
262 return find_reloc_by_dest_range(elf
, sec
, offset
, 1);
265 void insn_to_reloc_sym_addend(struct section
*sec
, unsigned long offset
,
269 reloc
->sym
= sec
->sym
;
270 reloc
->addend
= offset
;
275 * The Clang assembler strips section symbols, so we have to reference
276 * the function symbol instead:
278 reloc
->sym
= find_symbol_containing(sec
, offset
);
281 * Hack alert. This happens when we need to reference the NOP
282 * pad insn immediately after the function.
284 reloc
->sym
= find_symbol_containing(sec
, offset
- 1);
288 reloc
->addend
= offset
- reloc
->sym
->offset
;
291 static int read_sections(struct elf
*elf
)
295 size_t shstrndx
, sections_nr
;
298 if (elf_getshdrnum(elf
->elf
, §ions_nr
)) {
299 WARN_ELF("elf_getshdrnum");
303 if (elf_getshdrstrndx(elf
->elf
, &shstrndx
)) {
304 WARN_ELF("elf_getshdrstrndx");
308 for (i
= 0; i
< sections_nr
; i
++) {
309 sec
= malloc(sizeof(*sec
));
314 memset(sec
, 0, sizeof(*sec
));
316 INIT_LIST_HEAD(&sec
->symbol_list
);
317 INIT_LIST_HEAD(&sec
->reloc_list
);
319 s
= elf_getscn(elf
->elf
, i
);
321 WARN_ELF("elf_getscn");
325 sec
->idx
= elf_ndxscn(s
);
327 if (!gelf_getshdr(s
, &sec
->sh
)) {
328 WARN_ELF("gelf_getshdr");
332 sec
->name
= elf_strptr(elf
->elf
, shstrndx
, sec
->sh
.sh_name
);
334 WARN_ELF("elf_strptr");
338 if (sec
->sh
.sh_size
!= 0) {
339 sec
->data
= elf_getdata(s
, NULL
);
341 WARN_ELF("elf_getdata");
344 if (sec
->data
->d_off
!= 0 ||
345 sec
->data
->d_size
!= sec
->sh
.sh_size
) {
346 WARN("unexpected data attributes for %s",
351 sec
->len
= sec
->sh
.sh_size
;
353 list_add_tail(&sec
->list
, &elf
->sections
);
354 elf_hash_add(elf
->section_hash
, &sec
->hash
, sec
->idx
);
355 elf_hash_add(elf
->section_name_hash
, &sec
->name_hash
, str_hash(sec
->name
));
359 printf("nr_sections: %lu\n", (unsigned long)sections_nr
);
361 /* sanity check, one more call to elf_nextscn() should return NULL */
362 if (elf_nextscn(elf
->elf
, s
)) {
363 WARN("section entry mismatch");
370 static int read_symbols(struct elf
*elf
)
372 struct section
*symtab
, *symtab_shndx
, *sec
;
373 struct symbol
*sym
, *pfunc
;
374 struct list_head
*entry
;
375 struct rb_node
*pnode
;
378 Elf_Data
*shndx_data
= NULL
;
381 symtab
= find_section_by_name(elf
, ".symtab");
383 WARN("missing symbol table");
387 symtab_shndx
= find_section_by_name(elf
, ".symtab_shndx");
389 shndx_data
= symtab_shndx
->data
;
391 symbols_nr
= symtab
->sh
.sh_size
/ symtab
->sh
.sh_entsize
;
393 for (i
= 0; i
< symbols_nr
; i
++) {
394 sym
= malloc(sizeof(*sym
));
399 memset(sym
, 0, sizeof(*sym
));
404 if (!gelf_getsymshndx(symtab
->data
, shndx_data
, i
, &sym
->sym
,
406 WARN_ELF("gelf_getsymshndx");
410 sym
->name
= elf_strptr(elf
->elf
, symtab
->sh
.sh_link
,
413 WARN_ELF("elf_strptr");
417 sym
->type
= GELF_ST_TYPE(sym
->sym
.st_info
);
418 sym
->bind
= GELF_ST_BIND(sym
->sym
.st_info
);
420 if ((sym
->sym
.st_shndx
> SHN_UNDEF
&&
421 sym
->sym
.st_shndx
< SHN_LORESERVE
) ||
422 (shndx_data
&& sym
->sym
.st_shndx
== SHN_XINDEX
)) {
423 if (sym
->sym
.st_shndx
!= SHN_XINDEX
)
424 shndx
= sym
->sym
.st_shndx
;
426 sym
->sec
= find_section_by_index(elf
, shndx
);
428 WARN("couldn't find section for symbol %s",
432 if (sym
->type
== STT_SECTION
) {
433 sym
->name
= sym
->sec
->name
;
437 sym
->sec
= find_section_by_index(elf
, 0);
439 sym
->offset
= sym
->sym
.st_value
;
440 sym
->len
= sym
->sym
.st_size
;
442 rb_add(&sym
->sec
->symbol_tree
, &sym
->node
, symbol_to_offset
);
443 pnode
= rb_prev(&sym
->node
);
445 entry
= &rb_entry(pnode
, struct symbol
, node
)->list
;
447 entry
= &sym
->sec
->symbol_list
;
448 list_add(&sym
->list
, entry
);
449 elf_hash_add(elf
->symbol_hash
, &sym
->hash
, sym
->idx
);
450 elf_hash_add(elf
->symbol_name_hash
, &sym
->name_hash
, str_hash(sym
->name
));
454 printf("nr_symbols: %lu\n", (unsigned long)symbols_nr
);
456 /* Create parent/child links for any cold subfunctions */
457 list_for_each_entry(sec
, &elf
->sections
, list
) {
458 list_for_each_entry(sym
, &sec
->symbol_list
, list
) {
459 char pname
[MAX_NAME_LEN
+ 1];
461 if (sym
->type
!= STT_FUNC
)
464 if (sym
->pfunc
== NULL
)
467 if (sym
->cfunc
== NULL
)
470 coldstr
= strstr(sym
->name
, ".cold");
474 pnamelen
= coldstr
- sym
->name
;
475 if (pnamelen
> MAX_NAME_LEN
) {
476 WARN("%s(): parent function name exceeds maximum length of %d characters",
477 sym
->name
, MAX_NAME_LEN
);
481 strncpy(pname
, sym
->name
, pnamelen
);
482 pname
[pnamelen
] = '\0';
483 pfunc
= find_symbol_by_name(elf
, pname
);
486 WARN("%s(): can't find parent function",
495 * Unfortunately, -fnoreorder-functions puts the child
496 * inside the parent. Remove the overlap so we can
497 * have sane assumptions.
499 * Note that pfunc->len now no longer matches
500 * pfunc->sym.st_size.
502 if (sym
->sec
== pfunc
->sec
&&
503 sym
->offset
>= pfunc
->offset
&&
504 sym
->offset
+ sym
->len
== pfunc
->offset
+ pfunc
->len
) {
505 pfunc
->len
-= sym
->len
;
517 void elf_add_reloc(struct elf
*elf
, struct reloc
*reloc
)
519 struct section
*sec
= reloc
->sec
;
521 list_add_tail(&reloc
->list
, &sec
->reloc_list
);
522 elf_hash_add(elf
->reloc_hash
, &reloc
->hash
, reloc_hash(reloc
));
525 static int read_rel_reloc(struct section
*sec
, int i
, struct reloc
*reloc
, unsigned int *symndx
)
527 if (!gelf_getrel(sec
->data
, i
, &reloc
->rel
)) {
528 WARN_ELF("gelf_getrel");
531 reloc
->type
= GELF_R_TYPE(reloc
->rel
.r_info
);
533 reloc
->offset
= reloc
->rel
.r_offset
;
534 *symndx
= GELF_R_SYM(reloc
->rel
.r_info
);
538 static int read_rela_reloc(struct section
*sec
, int i
, struct reloc
*reloc
, unsigned int *symndx
)
540 if (!gelf_getrela(sec
->data
, i
, &reloc
->rela
)) {
541 WARN_ELF("gelf_getrela");
544 reloc
->type
= GELF_R_TYPE(reloc
->rela
.r_info
);
545 reloc
->addend
= reloc
->rela
.r_addend
;
546 reloc
->offset
= reloc
->rela
.r_offset
;
547 *symndx
= GELF_R_SYM(reloc
->rela
.r_info
);
551 static int read_relocs(struct elf
*elf
)
557 unsigned long nr_reloc
, max_reloc
= 0, tot_reloc
= 0;
559 list_for_each_entry(sec
, &elf
->sections
, list
) {
560 if ((sec
->sh
.sh_type
!= SHT_RELA
) &&
561 (sec
->sh
.sh_type
!= SHT_REL
))
564 sec
->base
= find_section_by_index(elf
, sec
->sh
.sh_info
);
566 WARN("can't find base section for reloc section %s",
571 sec
->base
->reloc
= sec
;
574 for (i
= 0; i
< sec
->sh
.sh_size
/ sec
->sh
.sh_entsize
; i
++) {
575 reloc
= malloc(sizeof(*reloc
));
580 memset(reloc
, 0, sizeof(*reloc
));
581 switch (sec
->sh
.sh_type
) {
583 if (read_rel_reloc(sec
, i
, reloc
, &symndx
))
587 if (read_rela_reloc(sec
, i
, reloc
, &symndx
))
595 reloc
->sym
= find_symbol_by_index(elf
, symndx
);
597 WARN("can't find reloc entry symbol %d for %s",
602 elf_add_reloc(elf
, reloc
);
605 max_reloc
= max(max_reloc
, nr_reloc
);
606 tot_reloc
+= nr_reloc
;
610 printf("max_reloc: %lu\n", max_reloc
);
611 printf("tot_reloc: %lu\n", tot_reloc
);
617 struct elf
*elf_open_read(const char *name
, int flags
)
622 elf_version(EV_CURRENT
);
624 elf
= malloc(sizeof(*elf
));
629 memset(elf
, 0, offsetof(struct elf
, sections
));
631 INIT_LIST_HEAD(&elf
->sections
);
633 elf_hash_init(elf
->symbol_hash
);
634 elf_hash_init(elf
->symbol_name_hash
);
635 elf_hash_init(elf
->section_hash
);
636 elf_hash_init(elf
->section_name_hash
);
637 elf_hash_init(elf
->reloc_hash
);
639 elf
->fd
= open(name
, flags
);
641 fprintf(stderr
, "objtool: Can't open '%s': %s\n",
642 name
, strerror(errno
));
646 if ((flags
& O_ACCMODE
) == O_RDONLY
)
647 cmd
= ELF_C_READ_MMAP
;
648 else if ((flags
& O_ACCMODE
) == O_RDWR
)
653 elf
->elf
= elf_begin(elf
->fd
, cmd
, NULL
);
655 WARN_ELF("elf_begin");
659 if (!gelf_getehdr(elf
->elf
, &elf
->ehdr
)) {
660 WARN_ELF("gelf_getehdr");
664 if (read_sections(elf
))
667 if (read_symbols(elf
))
670 if (read_relocs(elf
))
680 struct section
*elf_create_section(struct elf
*elf
, const char *name
,
681 unsigned int sh_flags
, size_t entsize
, int nr
)
683 struct section
*sec
, *shstrtab
;
684 size_t size
= entsize
* nr
;
688 sec
= malloc(sizeof(*sec
));
693 memset(sec
, 0, sizeof(*sec
));
695 INIT_LIST_HEAD(&sec
->symbol_list
);
696 INIT_LIST_HEAD(&sec
->reloc_list
);
698 s
= elf_newscn(elf
->elf
);
700 WARN_ELF("elf_newscn");
704 sec
->name
= strdup(name
);
710 sec
->idx
= elf_ndxscn(s
);
714 sec
->data
= elf_newdata(s
);
716 WARN_ELF("elf_newdata");
720 sec
->data
->d_size
= size
;
721 sec
->data
->d_align
= 1;
724 sec
->data
->d_buf
= malloc(size
);
725 if (!sec
->data
->d_buf
) {
729 memset(sec
->data
->d_buf
, 0, size
);
732 if (!gelf_getshdr(s
, &sec
->sh
)) {
733 WARN_ELF("gelf_getshdr");
737 sec
->sh
.sh_size
= size
;
738 sec
->sh
.sh_entsize
= entsize
;
739 sec
->sh
.sh_type
= SHT_PROGBITS
;
740 sec
->sh
.sh_addralign
= 1;
741 sec
->sh
.sh_flags
= SHF_ALLOC
| sh_flags
;
744 /* Add section name to .shstrtab (or .strtab for Clang) */
745 shstrtab
= find_section_by_name(elf
, ".shstrtab");
747 shstrtab
= find_section_by_name(elf
, ".strtab");
749 WARN("can't find .shstrtab or .strtab section");
753 s
= elf_getscn(elf
->elf
, shstrtab
->idx
);
755 WARN_ELF("elf_getscn");
759 data
= elf_newdata(s
);
761 WARN_ELF("elf_newdata");
765 data
->d_buf
= sec
->name
;
766 data
->d_size
= strlen(name
) + 1;
769 sec
->sh
.sh_name
= shstrtab
->len
;
771 shstrtab
->len
+= strlen(name
) + 1;
772 shstrtab
->changed
= true;
774 list_add_tail(&sec
->list
, &elf
->sections
);
775 elf_hash_add(elf
->section_hash
, &sec
->hash
, sec
->idx
);
776 elf_hash_add(elf
->section_name_hash
, &sec
->name_hash
, str_hash(sec
->name
));
783 static struct section
*elf_create_rel_reloc_section(struct elf
*elf
, struct section
*base
)
788 relocname
= malloc(strlen(base
->name
) + strlen(".rel") + 1);
793 strcpy(relocname
, ".rel");
794 strcat(relocname
, base
->name
);
796 sec
= elf_create_section(elf
, relocname
, 0, sizeof(GElf_Rel
), 0);
804 sec
->sh
.sh_type
= SHT_REL
;
805 sec
->sh
.sh_addralign
= 8;
806 sec
->sh
.sh_link
= find_section_by_name(elf
, ".symtab")->idx
;
807 sec
->sh
.sh_info
= base
->idx
;
808 sec
->sh
.sh_flags
= SHF_INFO_LINK
;
813 static struct section
*elf_create_rela_reloc_section(struct elf
*elf
, struct section
*base
)
818 relocname
= malloc(strlen(base
->name
) + strlen(".rela") + 1);
823 strcpy(relocname
, ".rela");
824 strcat(relocname
, base
->name
);
826 sec
= elf_create_section(elf
, relocname
, 0, sizeof(GElf_Rela
), 0);
834 sec
->sh
.sh_type
= SHT_RELA
;
835 sec
->sh
.sh_addralign
= 8;
836 sec
->sh
.sh_link
= find_section_by_name(elf
, ".symtab")->idx
;
837 sec
->sh
.sh_info
= base
->idx
;
838 sec
->sh
.sh_flags
= SHF_INFO_LINK
;
843 struct section
*elf_create_reloc_section(struct elf
*elf
,
844 struct section
*base
,
848 case SHT_REL
: return elf_create_rel_reloc_section(elf
, base
);
849 case SHT_RELA
: return elf_create_rela_reloc_section(elf
, base
);
850 default: return NULL
;
854 static int elf_rebuild_rel_reloc_section(struct section
*sec
, int nr
)
860 /* Allocate a buffer for relocations */
861 size
= nr
* sizeof(*relocs
);
862 relocs
= malloc(size
);
868 sec
->data
->d_buf
= relocs
;
869 sec
->data
->d_size
= size
;
871 sec
->sh
.sh_size
= size
;
874 list_for_each_entry(reloc
, &sec
->reloc_list
, list
) {
875 relocs
[idx
].r_offset
= reloc
->offset
;
876 relocs
[idx
].r_info
= GELF_R_INFO(reloc
->sym
->idx
, reloc
->type
);
883 static int elf_rebuild_rela_reloc_section(struct section
*sec
, int nr
)
889 /* Allocate a buffer for relocations with addends */
890 size
= nr
* sizeof(*relocs
);
891 relocs
= malloc(size
);
897 sec
->data
->d_buf
= relocs
;
898 sec
->data
->d_size
= size
;
900 sec
->sh
.sh_size
= size
;
903 list_for_each_entry(reloc
, &sec
->reloc_list
, list
) {
904 relocs
[idx
].r_offset
= reloc
->offset
;
905 relocs
[idx
].r_addend
= reloc
->addend
;
906 relocs
[idx
].r_info
= GELF_R_INFO(reloc
->sym
->idx
, reloc
->type
);
913 int elf_rebuild_reloc_section(struct elf
*elf
, struct section
*sec
)
922 list_for_each_entry(reloc
, &sec
->reloc_list
, list
)
925 switch (sec
->sh
.sh_type
) {
926 case SHT_REL
: return elf_rebuild_rel_reloc_section(sec
, nr
);
927 case SHT_RELA
: return elf_rebuild_rela_reloc_section(sec
, nr
);
932 int elf_write_insn(struct elf
*elf
, struct section
*sec
,
933 unsigned long offset
, unsigned int len
,
936 Elf_Data
*data
= sec
->data
;
938 if (data
->d_type
!= ELF_T_BYTE
|| data
->d_off
) {
939 WARN("write to unexpected data for section: %s", sec
->name
);
943 memcpy(data
->d_buf
+ offset
, insn
, len
);
944 elf_flagdata(data
, ELF_C_SET
, ELF_F_DIRTY
);
951 int elf_write_reloc(struct elf
*elf
, struct reloc
*reloc
)
953 struct section
*sec
= reloc
->sec
;
955 if (sec
->sh
.sh_type
== SHT_REL
) {
956 reloc
->rel
.r_info
= GELF_R_INFO(reloc
->sym
->idx
, reloc
->type
);
957 reloc
->rel
.r_offset
= reloc
->offset
;
959 if (!gelf_update_rel(sec
->data
, reloc
->idx
, &reloc
->rel
)) {
960 WARN_ELF("gelf_update_rel");
964 reloc
->rela
.r_info
= GELF_R_INFO(reloc
->sym
->idx
, reloc
->type
);
965 reloc
->rela
.r_addend
= reloc
->addend
;
966 reloc
->rela
.r_offset
= reloc
->offset
;
968 if (!gelf_update_rela(sec
->data
, reloc
->idx
, &reloc
->rela
)) {
969 WARN_ELF("gelf_update_rela");
979 int elf_write(struct elf
*elf
)
984 /* Update section headers for changed sections: */
985 list_for_each_entry(sec
, &elf
->sections
, list
) {
987 s
= elf_getscn(elf
->elf
, sec
->idx
);
989 WARN_ELF("elf_getscn");
992 if (!gelf_update_shdr(s
, &sec
->sh
)) {
993 WARN_ELF("gelf_update_shdr");
997 sec
->changed
= false;
1001 /* Make sure the new section header entries get updated properly. */
1002 elf_flagelf(elf
->elf
, ELF_C_SET
, ELF_F_DIRTY
);
1004 /* Write all changes to the file. */
1005 if (elf_update(elf
->elf
, ELF_C_WRITE
) < 0) {
1006 WARN_ELF("elf_update");
1010 elf
->changed
= false;
1015 void elf_close(struct elf
*elf
)
1017 struct section
*sec
, *tmpsec
;
1018 struct symbol
*sym
, *tmpsym
;
1019 struct reloc
*reloc
, *tmpreloc
;
1027 list_for_each_entry_safe(sec
, tmpsec
, &elf
->sections
, list
) {
1028 list_for_each_entry_safe(sym
, tmpsym
, &sec
->symbol_list
, list
) {
1029 list_del(&sym
->list
);
1030 hash_del(&sym
->hash
);
1033 list_for_each_entry_safe(reloc
, tmpreloc
, &sec
->reloc_list
, list
) {
1034 list_del(&reloc
->list
);
1035 hash_del(&reloc
->hash
);
1038 list_del(&sec
->list
);