]>
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>
19 #include <objtool/builtin.h>
21 #include <objtool/elf.h>
22 #include <objtool/warn.h>
24 #define MAX_NAME_LEN 128
26 static inline u32
str_hash(const char *str
)
28 return jhash(str
, strlen(str
), 0);
31 #define __elf_table(name) (elf->name##_hash)
32 #define __elf_bits(name) (elf->name##_bits)
34 #define elf_hash_add(name, node, key) \
35 hlist_add_head(node, &__elf_table(name)[hash_min(key, __elf_bits(name))])
37 #define elf_hash_for_each_possible(name, obj, member, key) \
38 hlist_for_each_entry(obj, &__elf_table(name)[hash_min(key, __elf_bits(name))], member)
40 #define elf_alloc_hash(name, size) \
42 __elf_bits(name) = max(10, ilog2(size)); \
43 __elf_table(name) = mmap(NULL, sizeof(struct hlist_head) << __elf_bits(name), \
44 PROT_READ|PROT_WRITE, \
45 MAP_PRIVATE|MAP_ANON, -1, 0); \
46 if (__elf_table(name) == (void *)-1L) { \
47 WARN("mmap fail " #name); \
48 __elf_table(name) = NULL; \
53 static bool symbol_to_offset(struct rb_node
*a
, const struct rb_node
*b
)
55 struct symbol
*sa
= rb_entry(a
, struct symbol
, node
);
56 struct symbol
*sb
= rb_entry(b
, struct symbol
, node
);
58 if (sa
->offset
< sb
->offset
)
60 if (sa
->offset
> sb
->offset
)
63 if (sa
->len
< sb
->len
)
65 if (sa
->len
> sb
->len
)
73 static int symbol_by_offset(const void *key
, const struct rb_node
*node
)
75 const struct symbol
*s
= rb_entry(node
, struct symbol
, node
);
76 const unsigned long *o
= key
;
80 if (*o
>= s
->offset
+ s
->len
)
86 struct section
*find_section_by_name(const struct elf
*elf
, const char *name
)
90 elf_hash_for_each_possible(section_name
, sec
, name_hash
, str_hash(name
)) {
91 if (!strcmp(sec
->name
, name
))
98 static struct section
*find_section_by_index(struct elf
*elf
,
103 elf_hash_for_each_possible(section
, sec
, hash
, idx
) {
111 static struct symbol
*find_symbol_by_index(struct elf
*elf
, unsigned int idx
)
115 elf_hash_for_each_possible(symbol
, sym
, hash
, idx
) {
123 struct symbol
*find_symbol_by_offset(struct section
*sec
, unsigned long offset
)
125 struct rb_node
*node
;
127 rb_for_each(node
, &offset
, &sec
->symbol_tree
, symbol_by_offset
) {
128 struct symbol
*s
= rb_entry(node
, struct symbol
, node
);
130 if (s
->offset
== offset
&& s
->type
!= STT_SECTION
)
137 struct symbol
*find_func_by_offset(struct section
*sec
, unsigned long offset
)
139 struct rb_node
*node
;
141 rb_for_each(node
, &offset
, &sec
->symbol_tree
, symbol_by_offset
) {
142 struct symbol
*s
= rb_entry(node
, struct symbol
, node
);
144 if (s
->offset
== offset
&& s
->type
== STT_FUNC
)
151 struct symbol
*find_symbol_containing(const struct section
*sec
, unsigned long offset
)
153 struct rb_node
*node
;
155 rb_for_each(node
, &offset
, &sec
->symbol_tree
, symbol_by_offset
) {
156 struct symbol
*s
= rb_entry(node
, struct symbol
, node
);
158 if (s
->type
!= STT_SECTION
)
165 struct symbol
*find_func_containing(struct section
*sec
, unsigned long offset
)
167 struct rb_node
*node
;
169 rb_for_each(node
, &offset
, &sec
->symbol_tree
, symbol_by_offset
) {
170 struct symbol
*s
= rb_entry(node
, struct symbol
, node
);
172 if (s
->type
== STT_FUNC
)
179 struct symbol
*find_symbol_by_name(const struct elf
*elf
, const char *name
)
183 elf_hash_for_each_possible(symbol_name
, sym
, name_hash
, str_hash(name
)) {
184 if (!strcmp(sym
->name
, name
))
191 struct reloc
*find_reloc_by_dest_range(const struct elf
*elf
, struct section
*sec
,
192 unsigned long offset
, unsigned int len
)
194 struct reloc
*reloc
, *r
= NULL
;
202 for_offset_range(o
, offset
, offset
+ len
) {
203 elf_hash_for_each_possible(reloc
, reloc
, hash
,
204 sec_offset_hash(sec
, o
)) {
205 if (reloc
->sec
!= sec
)
208 if (reloc
->offset
>= offset
&& reloc
->offset
< offset
+ len
) {
209 if (!r
|| reloc
->offset
< r
->offset
)
220 struct reloc
*find_reloc_by_dest(const struct elf
*elf
, struct section
*sec
, unsigned long offset
)
222 return find_reloc_by_dest_range(elf
, sec
, offset
, 1);
225 static int read_sections(struct elf
*elf
)
229 size_t shstrndx
, sections_nr
;
232 if (elf_getshdrnum(elf
->elf
, §ions_nr
)) {
233 WARN_ELF("elf_getshdrnum");
237 if (elf_getshdrstrndx(elf
->elf
, &shstrndx
)) {
238 WARN_ELF("elf_getshdrstrndx");
242 if (!elf_alloc_hash(section
, sections_nr
) ||
243 !elf_alloc_hash(section_name
, sections_nr
))
246 for (i
= 0; i
< sections_nr
; i
++) {
247 sec
= malloc(sizeof(*sec
));
252 memset(sec
, 0, sizeof(*sec
));
254 INIT_LIST_HEAD(&sec
->symbol_list
);
255 INIT_LIST_HEAD(&sec
->reloc_list
);
257 s
= elf_getscn(elf
->elf
, i
);
259 WARN_ELF("elf_getscn");
263 sec
->idx
= elf_ndxscn(s
);
265 if (!gelf_getshdr(s
, &sec
->sh
)) {
266 WARN_ELF("gelf_getshdr");
270 sec
->name
= elf_strptr(elf
->elf
, shstrndx
, sec
->sh
.sh_name
);
272 WARN_ELF("elf_strptr");
276 if (sec
->sh
.sh_size
!= 0) {
277 sec
->data
= elf_getdata(s
, NULL
);
279 WARN_ELF("elf_getdata");
282 if (sec
->data
->d_off
!= 0 ||
283 sec
->data
->d_size
!= sec
->sh
.sh_size
) {
284 WARN("unexpected data attributes for %s",
290 if (sec
->sh
.sh_flags
& SHF_EXECINSTR
)
291 elf
->text_size
+= sec
->sh
.sh_size
;
293 list_add_tail(&sec
->list
, &elf
->sections
);
294 elf_hash_add(section
, &sec
->hash
, sec
->idx
);
295 elf_hash_add(section_name
, &sec
->name_hash
, str_hash(sec
->name
));
299 printf("nr_sections: %lu\n", (unsigned long)sections_nr
);
300 printf("section_bits: %d\n", elf
->section_bits
);
303 /* sanity check, one more call to elf_nextscn() should return NULL */
304 if (elf_nextscn(elf
->elf
, s
)) {
305 WARN("section entry mismatch");
312 static void elf_add_symbol(struct elf
*elf
, struct symbol
*sym
)
314 struct list_head
*entry
;
315 struct rb_node
*pnode
;
317 sym
->type
= GELF_ST_TYPE(sym
->sym
.st_info
);
318 sym
->bind
= GELF_ST_BIND(sym
->sym
.st_info
);
320 sym
->offset
= sym
->sym
.st_value
;
321 sym
->len
= sym
->sym
.st_size
;
323 rb_add(&sym
->node
, &sym
->sec
->symbol_tree
, symbol_to_offset
);
324 pnode
= rb_prev(&sym
->node
);
326 entry
= &rb_entry(pnode
, struct symbol
, node
)->list
;
328 entry
= &sym
->sec
->symbol_list
;
329 list_add(&sym
->list
, entry
);
330 elf_hash_add(symbol
, &sym
->hash
, sym
->idx
);
331 elf_hash_add(symbol_name
, &sym
->name_hash
, str_hash(sym
->name
));
334 * Don't store empty STT_NOTYPE symbols in the rbtree. They
335 * can exist within a function, confusing the sorting.
338 rb_erase(&sym
->node
, &sym
->sec
->symbol_tree
);
341 static int read_symbols(struct elf
*elf
)
343 struct section
*symtab
, *symtab_shndx
, *sec
;
344 struct symbol
*sym
, *pfunc
;
347 Elf_Data
*shndx_data
= NULL
;
350 symtab
= find_section_by_name(elf
, ".symtab");
352 symtab_shndx
= find_section_by_name(elf
, ".symtab_shndx");
354 shndx_data
= symtab_shndx
->data
;
356 symbols_nr
= symtab
->sh
.sh_size
/ symtab
->sh
.sh_entsize
;
359 * A missing symbol table is actually possible if it's an empty
360 * .o file. This can happen for thunk_64.o. Make sure to at
361 * least allocate the symbol hash tables so we can do symbol
362 * lookups without crashing.
367 if (!elf_alloc_hash(symbol
, symbols_nr
) ||
368 !elf_alloc_hash(symbol_name
, symbols_nr
))
371 for (i
= 0; i
< symbols_nr
; i
++) {
372 sym
= malloc(sizeof(*sym
));
377 memset(sym
, 0, sizeof(*sym
));
382 if (!gelf_getsymshndx(symtab
->data
, shndx_data
, i
, &sym
->sym
,
384 WARN_ELF("gelf_getsymshndx");
388 sym
->name
= elf_strptr(elf
->elf
, symtab
->sh
.sh_link
,
391 WARN_ELF("elf_strptr");
395 if ((sym
->sym
.st_shndx
> SHN_UNDEF
&&
396 sym
->sym
.st_shndx
< SHN_LORESERVE
) ||
397 (shndx_data
&& sym
->sym
.st_shndx
== SHN_XINDEX
)) {
398 if (sym
->sym
.st_shndx
!= SHN_XINDEX
)
399 shndx
= sym
->sym
.st_shndx
;
401 sym
->sec
= find_section_by_index(elf
, shndx
);
403 WARN("couldn't find section for symbol %s",
407 if (GELF_ST_TYPE(sym
->sym
.st_info
) == STT_SECTION
) {
408 sym
->name
= sym
->sec
->name
;
412 sym
->sec
= find_section_by_index(elf
, 0);
414 elf_add_symbol(elf
, sym
);
418 printf("nr_symbols: %lu\n", (unsigned long)symbols_nr
);
419 printf("symbol_bits: %d\n", elf
->symbol_bits
);
422 /* Create parent/child links for any cold subfunctions */
423 list_for_each_entry(sec
, &elf
->sections
, list
) {
424 list_for_each_entry(sym
, &sec
->symbol_list
, list
) {
425 char pname
[MAX_NAME_LEN
+ 1];
427 if (sym
->type
!= STT_FUNC
)
430 if (sym
->pfunc
== NULL
)
433 if (sym
->cfunc
== NULL
)
436 coldstr
= strstr(sym
->name
, ".cold");
440 pnamelen
= coldstr
- sym
->name
;
441 if (pnamelen
> MAX_NAME_LEN
) {
442 WARN("%s(): parent function name exceeds maximum length of %d characters",
443 sym
->name
, MAX_NAME_LEN
);
447 strncpy(pname
, sym
->name
, pnamelen
);
448 pname
[pnamelen
] = '\0';
449 pfunc
= find_symbol_by_name(elf
, pname
);
452 WARN("%s(): can't find parent function",
461 * Unfortunately, -fnoreorder-functions puts the child
462 * inside the parent. Remove the overlap so we can
463 * have sane assumptions.
465 * Note that pfunc->len now no longer matches
466 * pfunc->sym.st_size.
468 if (sym
->sec
== pfunc
->sec
&&
469 sym
->offset
>= pfunc
->offset
&&
470 sym
->offset
+ sym
->len
== pfunc
->offset
+ pfunc
->len
) {
471 pfunc
->len
-= sym
->len
;
483 static struct section
*elf_create_reloc_section(struct elf
*elf
,
484 struct section
*base
,
487 int elf_add_reloc(struct elf
*elf
, struct section
*sec
, unsigned long offset
,
488 unsigned int type
, struct symbol
*sym
, int addend
)
492 if (!sec
->reloc
&& !elf_create_reloc_section(elf
, sec
, SHT_RELA
))
495 reloc
= malloc(sizeof(*reloc
));
500 memset(reloc
, 0, sizeof(*reloc
));
502 reloc
->sec
= sec
->reloc
;
503 reloc
->offset
= offset
;
506 reloc
->addend
= addend
;
508 list_add_tail(&reloc
->list
, &sec
->reloc
->reloc_list
);
509 elf_hash_add(reloc
, &reloc
->hash
, reloc_hash(reloc
));
511 sec
->reloc
->sh
.sh_size
+= sec
->reloc
->sh
.sh_entsize
;
512 sec
->reloc
->changed
= true;
517 int elf_add_reloc_to_insn(struct elf
*elf
, struct section
*sec
,
518 unsigned long offset
, unsigned int type
,
519 struct section
*insn_sec
, unsigned long insn_off
)
530 * The Clang assembler strips section symbols, so we have to
531 * reference the function symbol instead:
533 sym
= find_symbol_containing(insn_sec
, insn_off
);
536 * Hack alert. This happens when we need to reference
537 * the NOP pad insn immediately after the function.
539 sym
= find_symbol_containing(insn_sec
, insn_off
- 1);
543 WARN("can't find symbol containing %s+0x%lx", insn_sec
->name
, insn_off
);
547 addend
= insn_off
- sym
->offset
;
550 return elf_add_reloc(elf
, sec
, offset
, type
, sym
, addend
);
553 static int read_rel_reloc(struct section
*sec
, int i
, struct reloc
*reloc
, unsigned int *symndx
)
555 if (!gelf_getrel(sec
->data
, i
, &reloc
->rel
)) {
556 WARN_ELF("gelf_getrel");
559 reloc
->type
= GELF_R_TYPE(reloc
->rel
.r_info
);
561 reloc
->offset
= reloc
->rel
.r_offset
;
562 *symndx
= GELF_R_SYM(reloc
->rel
.r_info
);
566 static int read_rela_reloc(struct section
*sec
, int i
, struct reloc
*reloc
, unsigned int *symndx
)
568 if (!gelf_getrela(sec
->data
, i
, &reloc
->rela
)) {
569 WARN_ELF("gelf_getrela");
572 reloc
->type
= GELF_R_TYPE(reloc
->rela
.r_info
);
573 reloc
->addend
= reloc
->rela
.r_addend
;
574 reloc
->offset
= reloc
->rela
.r_offset
;
575 *symndx
= GELF_R_SYM(reloc
->rela
.r_info
);
579 static int read_relocs(struct elf
*elf
)
585 unsigned long nr_reloc
, max_reloc
= 0, tot_reloc
= 0;
587 if (!elf_alloc_hash(reloc
, elf
->text_size
/ 16))
590 list_for_each_entry(sec
, &elf
->sections
, list
) {
591 if ((sec
->sh
.sh_type
!= SHT_RELA
) &&
592 (sec
->sh
.sh_type
!= SHT_REL
))
595 sec
->base
= find_section_by_index(elf
, sec
->sh
.sh_info
);
597 WARN("can't find base section for reloc section %s",
602 sec
->base
->reloc
= sec
;
605 for (i
= 0; i
< sec
->sh
.sh_size
/ sec
->sh
.sh_entsize
; i
++) {
606 reloc
= malloc(sizeof(*reloc
));
611 memset(reloc
, 0, sizeof(*reloc
));
612 switch (sec
->sh
.sh_type
) {
614 if (read_rel_reloc(sec
, i
, reloc
, &symndx
))
618 if (read_rela_reloc(sec
, i
, reloc
, &symndx
))
626 reloc
->sym
= find_symbol_by_index(elf
, symndx
);
628 WARN("can't find reloc entry symbol %d for %s",
633 list_add_tail(&reloc
->list
, &sec
->reloc_list
);
634 elf_hash_add(reloc
, &reloc
->hash
, reloc_hash(reloc
));
638 max_reloc
= max(max_reloc
, nr_reloc
);
639 tot_reloc
+= nr_reloc
;
643 printf("max_reloc: %lu\n", max_reloc
);
644 printf("tot_reloc: %lu\n", tot_reloc
);
645 printf("reloc_bits: %d\n", elf
->reloc_bits
);
651 struct elf
*elf_open_read(const char *name
, int flags
)
656 elf_version(EV_CURRENT
);
658 elf
= malloc(sizeof(*elf
));
663 memset(elf
, 0, offsetof(struct elf
, sections
));
665 INIT_LIST_HEAD(&elf
->sections
);
667 elf
->fd
= open(name
, flags
);
669 fprintf(stderr
, "objtool: Can't open '%s': %s\n",
670 name
, strerror(errno
));
674 if ((flags
& O_ACCMODE
) == O_RDONLY
)
675 cmd
= ELF_C_READ_MMAP
;
676 else if ((flags
& O_ACCMODE
) == O_RDWR
)
681 elf
->elf
= elf_begin(elf
->fd
, cmd
, NULL
);
683 WARN_ELF("elf_begin");
687 if (!gelf_getehdr(elf
->elf
, &elf
->ehdr
)) {
688 WARN_ELF("gelf_getehdr");
692 if (read_sections(elf
))
695 if (read_symbols(elf
))
698 if (read_relocs(elf
))
708 static int elf_add_string(struct elf
*elf
, struct section
*strtab
, char *str
)
715 strtab
= find_section_by_name(elf
, ".strtab");
717 WARN("can't find .strtab section");
721 s
= elf_getscn(elf
->elf
, strtab
->idx
);
723 WARN_ELF("elf_getscn");
727 data
= elf_newdata(s
);
729 WARN_ELF("elf_newdata");
734 data
->d_size
= strlen(str
) + 1;
737 len
= strtab
->sh
.sh_size
;
738 strtab
->sh
.sh_size
+= data
->d_size
;
739 strtab
->changed
= true;
744 struct section
*elf_create_section(struct elf
*elf
, const char *name
,
745 unsigned int sh_flags
, size_t entsize
, int nr
)
747 struct section
*sec
, *shstrtab
;
748 size_t size
= entsize
* nr
;
751 sec
= malloc(sizeof(*sec
));
756 memset(sec
, 0, sizeof(*sec
));
758 INIT_LIST_HEAD(&sec
->symbol_list
);
759 INIT_LIST_HEAD(&sec
->reloc_list
);
761 s
= elf_newscn(elf
->elf
);
763 WARN_ELF("elf_newscn");
767 sec
->name
= strdup(name
);
773 sec
->idx
= elf_ndxscn(s
);
776 sec
->data
= elf_newdata(s
);
778 WARN_ELF("elf_newdata");
782 sec
->data
->d_size
= size
;
783 sec
->data
->d_align
= 1;
786 sec
->data
->d_buf
= malloc(size
);
787 if (!sec
->data
->d_buf
) {
791 memset(sec
->data
->d_buf
, 0, size
);
794 if (!gelf_getshdr(s
, &sec
->sh
)) {
795 WARN_ELF("gelf_getshdr");
799 sec
->sh
.sh_size
= size
;
800 sec
->sh
.sh_entsize
= entsize
;
801 sec
->sh
.sh_type
= SHT_PROGBITS
;
802 sec
->sh
.sh_addralign
= 1;
803 sec
->sh
.sh_flags
= SHF_ALLOC
| sh_flags
;
805 /* Add section name to .shstrtab (or .strtab for Clang) */
806 shstrtab
= find_section_by_name(elf
, ".shstrtab");
808 shstrtab
= find_section_by_name(elf
, ".strtab");
810 WARN("can't find .shstrtab or .strtab section");
813 sec
->sh
.sh_name
= elf_add_string(elf
, shstrtab
, sec
->name
);
814 if (sec
->sh
.sh_name
== -1)
817 list_add_tail(&sec
->list
, &elf
->sections
);
818 elf_hash_add(section
, &sec
->hash
, sec
->idx
);
819 elf_hash_add(section_name
, &sec
->name_hash
, str_hash(sec
->name
));
826 static struct section
*elf_create_rel_reloc_section(struct elf
*elf
, struct section
*base
)
831 relocname
= malloc(strlen(base
->name
) + strlen(".rel") + 1);
836 strcpy(relocname
, ".rel");
837 strcat(relocname
, base
->name
);
839 sec
= elf_create_section(elf
, relocname
, 0, sizeof(GElf_Rel
), 0);
847 sec
->sh
.sh_type
= SHT_REL
;
848 sec
->sh
.sh_addralign
= 8;
849 sec
->sh
.sh_link
= find_section_by_name(elf
, ".symtab")->idx
;
850 sec
->sh
.sh_info
= base
->idx
;
851 sec
->sh
.sh_flags
= SHF_INFO_LINK
;
856 static struct section
*elf_create_rela_reloc_section(struct elf
*elf
, struct section
*base
)
861 relocname
= malloc(strlen(base
->name
) + strlen(".rela") + 1);
866 strcpy(relocname
, ".rela");
867 strcat(relocname
, base
->name
);
869 sec
= elf_create_section(elf
, relocname
, 0, sizeof(GElf_Rela
), 0);
877 sec
->sh
.sh_type
= SHT_RELA
;
878 sec
->sh
.sh_addralign
= 8;
879 sec
->sh
.sh_link
= find_section_by_name(elf
, ".symtab")->idx
;
880 sec
->sh
.sh_info
= base
->idx
;
881 sec
->sh
.sh_flags
= SHF_INFO_LINK
;
886 static struct section
*elf_create_reloc_section(struct elf
*elf
,
887 struct section
*base
,
891 case SHT_REL
: return elf_create_rel_reloc_section(elf
, base
);
892 case SHT_RELA
: return elf_create_rela_reloc_section(elf
, base
);
893 default: return NULL
;
897 static int elf_rebuild_rel_reloc_section(struct section
*sec
)
903 /* Allocate a buffer for relocations */
904 buf
= malloc(sec
->sh
.sh_size
);
910 sec
->data
->d_buf
= buf
;
911 sec
->data
->d_size
= sec
->sh
.sh_size
;
912 sec
->data
->d_type
= ELF_T_REL
;
915 list_for_each_entry(reloc
, &sec
->reloc_list
, list
) {
916 reloc
->rel
.r_offset
= reloc
->offset
;
917 reloc
->rel
.r_info
= GELF_R_INFO(reloc
->sym
->idx
, reloc
->type
);
918 if (!gelf_update_rel(sec
->data
, idx
, &reloc
->rel
)) {
919 WARN_ELF("gelf_update_rel");
928 static int elf_rebuild_rela_reloc_section(struct section
*sec
)
934 /* Allocate a buffer for relocations with addends */
935 buf
= malloc(sec
->sh
.sh_size
);
941 sec
->data
->d_buf
= buf
;
942 sec
->data
->d_size
= sec
->sh
.sh_size
;
943 sec
->data
->d_type
= ELF_T_RELA
;
946 list_for_each_entry(reloc
, &sec
->reloc_list
, list
) {
947 reloc
->rela
.r_offset
= reloc
->offset
;
948 reloc
->rela
.r_addend
= reloc
->addend
;
949 reloc
->rela
.r_info
= GELF_R_INFO(reloc
->sym
->idx
, reloc
->type
);
950 if (!gelf_update_rela(sec
->data
, idx
, &reloc
->rela
)) {
951 WARN_ELF("gelf_update_rela");
960 static int elf_rebuild_reloc_section(struct elf
*elf
, struct section
*sec
)
962 switch (sec
->sh
.sh_type
) {
963 case SHT_REL
: return elf_rebuild_rel_reloc_section(sec
);
964 case SHT_RELA
: return elf_rebuild_rela_reloc_section(sec
);
969 int elf_write_insn(struct elf
*elf
, struct section
*sec
,
970 unsigned long offset
, unsigned int len
,
973 Elf_Data
*data
= sec
->data
;
975 if (data
->d_type
!= ELF_T_BYTE
|| data
->d_off
) {
976 WARN("write to unexpected data for section: %s", sec
->name
);
980 memcpy(data
->d_buf
+ offset
, insn
, len
);
981 elf_flagdata(data
, ELF_C_SET
, ELF_F_DIRTY
);
988 int elf_write_reloc(struct elf
*elf
, struct reloc
*reloc
)
990 struct section
*sec
= reloc
->sec
;
992 if (sec
->sh
.sh_type
== SHT_REL
) {
993 reloc
->rel
.r_info
= GELF_R_INFO(reloc
->sym
->idx
, reloc
->type
);
994 reloc
->rel
.r_offset
= reloc
->offset
;
996 if (!gelf_update_rel(sec
->data
, reloc
->idx
, &reloc
->rel
)) {
997 WARN_ELF("gelf_update_rel");
1001 reloc
->rela
.r_info
= GELF_R_INFO(reloc
->sym
->idx
, reloc
->type
);
1002 reloc
->rela
.r_addend
= reloc
->addend
;
1003 reloc
->rela
.r_offset
= reloc
->offset
;
1005 if (!gelf_update_rela(sec
->data
, reloc
->idx
, &reloc
->rela
)) {
1006 WARN_ELF("gelf_update_rela");
1011 elf
->changed
= true;
1016 int elf_write(struct elf
*elf
)
1018 struct section
*sec
;
1021 /* Update changed relocation sections and section headers: */
1022 list_for_each_entry(sec
, &elf
->sections
, list
) {
1024 s
= elf_getscn(elf
->elf
, sec
->idx
);
1026 WARN_ELF("elf_getscn");
1029 if (!gelf_update_shdr(s
, &sec
->sh
)) {
1030 WARN_ELF("gelf_update_shdr");
1035 elf_rebuild_reloc_section(elf
, sec
)) {
1036 WARN("elf_rebuild_reloc_section");
1040 sec
->changed
= false;
1041 elf
->changed
= true;
1045 /* Make sure the new section header entries get updated properly. */
1046 elf_flagelf(elf
->elf
, ELF_C_SET
, ELF_F_DIRTY
);
1048 /* Write all changes to the file. */
1049 if (elf_update(elf
->elf
, ELF_C_WRITE
) < 0) {
1050 WARN_ELF("elf_update");
1054 elf
->changed
= false;
1059 void elf_close(struct elf
*elf
)
1061 struct section
*sec
, *tmpsec
;
1062 struct symbol
*sym
, *tmpsym
;
1063 struct reloc
*reloc
, *tmpreloc
;
1071 list_for_each_entry_safe(sec
, tmpsec
, &elf
->sections
, list
) {
1072 list_for_each_entry_safe(sym
, tmpsym
, &sec
->symbol_list
, list
) {
1073 list_del(&sym
->list
);
1074 hash_del(&sym
->hash
);
1077 list_for_each_entry_safe(reloc
, tmpreloc
, &sec
->reloc_list
, list
) {
1078 list_del(&reloc
->list
);
1079 hash_del(&reloc
->hash
);
1082 list_del(&sec
->list
);