Lines Matching +full:- +full:section
1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * elf.c - ELF access library
6 * Copyright (C) 2013-2015 Josh Poimboeuf <jpoimboe@redhat.com>
33 #define __elf_table(name) (elf->name##_hash)
34 #define __elf_bits(name) (elf->name##_bits)
42 __node->next = __elf_table_entry(name, key); \
52 *head = node->next; in __elf_hash_del()
56 for (prev = NULL, cur = *head; cur; prev = cur, cur = cur->next) { in __elf_hash_del()
58 prev->next = cur->next; in __elf_hash_del()
76 obj = elf_list_entry(obj->member.next, typeof(*(obj)), member))
83 MAP_PRIVATE|MAP_ANON, -1, 0); \
84 if (__elf_table(name) == (void *)-1L) { \
93 return s->offset; in __sym_start()
98 return s->offset + (s->len ? s->len - 1 : 0); in __sym_last()
122 if (sh->key < s->offset) in symbol_hole_by_offset()
123 return -1; in symbol_hole_by_offset()
125 if (sh->key >= s->offset + s->len) { in symbol_hole_by_offset()
126 sh->sym = s; in symbol_hole_by_offset()
133 struct section *find_section_by_name(const struct elf *elf, const char *name) in find_section_by_name()
135 struct section *sec; in find_section_by_name()
138 if (!strcmp(sec->name, name)) in find_section_by_name()
145 static struct section *find_section_by_index(struct elf *elf, in find_section_by_index()
148 struct section *sec; in find_section_by_index()
150 elf_hash_for_each_possible(section, sec, hash, idx) { in find_section_by_index()
151 if (sec->idx == idx) in find_section_by_index()
163 if (sym->idx == idx) in find_symbol_by_index()
170 struct symbol *find_symbol_by_offset(struct section *sec, unsigned long offset) in find_symbol_by_offset()
172 struct rb_root_cached *tree = (struct rb_root_cached *)&sec->symbol_tree; in find_symbol_by_offset()
176 if (sym->offset == offset && !is_sec_sym(sym)) in find_symbol_by_offset()
177 return sym->alias; in find_symbol_by_offset()
183 struct symbol *find_func_by_offset(struct section *sec, unsigned long offset) in find_func_by_offset()
185 struct rb_root_cached *tree = (struct rb_root_cached *)&sec->symbol_tree; in find_func_by_offset()
189 if (func->offset == offset && is_func_sym(func)) in find_func_by_offset()
190 return func->alias; in find_func_by_offset()
196 struct symbol *find_symbol_containing(const struct section *sec, unsigned long offset) in find_symbol_containing()
198 struct rb_root_cached *tree = (struct rb_root_cached *)&sec->symbol_tree; in find_symbol_containing()
202 if (tmp->len) { in find_symbol_containing()
208 if (sym->offset != tmp->offset || sym->len != tmp->len) { in find_symbol_containing()
215 if (tmp->len < sym->len) in find_symbol_containing()
221 return sym ? sym->alias : NULL; in find_symbol_containing()
227 int find_symbol_hole_containing(const struct section *sec, unsigned long offset) in find_symbol_hole_containing()
239 n = rb_find(&hole, &sec->symbol_tree.rb_root, symbol_hole_by_offset); in find_symbol_hole_containing()
246 * @offset >= sym->offset + sym->len, find symbol after it. in find_symbol_hole_containing()
248 * If there is no symbol in the section, the first node will be NULL, in find_symbol_hole_containing()
249 * in which case, -1 is returned to skip the whole section. in find_symbol_hole_containing()
252 n = rb_next(&hole.sym->node); in find_symbol_hole_containing()
254 n = rb_first_cached(&sec->symbol_tree); in find_symbol_hole_containing()
257 return -1; /* until end of address space */ in find_symbol_hole_containing()
261 return s->offset - offset; in find_symbol_hole_containing()
264 struct symbol *find_func_containing(struct section *sec, unsigned long offset) in find_func_containing()
266 struct rb_root_cached *tree = (struct rb_root_cached *)&sec->symbol_tree; in find_func_containing()
271 return func->alias; in find_func_containing()
282 if (!strcmp(sym->name, name)) in find_symbol_by_name()
297 if (sym->bind == STB_LOCAL && sym->file == file && in find_local_symbol_by_file_and_name()
298 !strcmp(sym->name, name)) { in find_local_symbol_by_file_and_name()
311 if (!strcmp(sym->name, name) && !is_local_sym(sym)) in find_global_symbol_by_name()
318 struct reloc *find_reloc_by_dest_range(const struct elf *elf, struct section *sec, in find_reloc_by_dest_range()
322 struct section *rsec; in find_reloc_by_dest_range()
325 rsec = sec->rsec; in find_reloc_by_dest_range()
332 if (reloc->sec != rsec) in find_reloc_by_dest_range()
348 struct reloc *find_reloc_by_dest(const struct elf *elf, struct section *sec, unsigned long offset) in find_reloc_by_dest()
353 static bool is_dwarf_section(struct section *sec) in is_dwarf_section()
355 return !strncmp(sec->name, ".debug_", 7); in is_dwarf_section()
361 struct section *sec; in read_sections()
365 if (elf_getshdrnum(elf->elf, §ions_nr)) { in read_sections()
367 return -1; in read_sections()
370 if (elf_getshdrstrndx(elf->elf, &shstrndx)) { in read_sections()
372 return -1; in read_sections()
375 if (!elf_alloc_hash(section, sections_nr) || in read_sections()
377 return -1; in read_sections()
379 elf->section_data = calloc(sections_nr, sizeof(*sec)); in read_sections()
380 if (!elf->section_data) { in read_sections()
382 return -1; in read_sections()
385 sec = &elf->section_data[i]; in read_sections()
387 INIT_LIST_HEAD(&sec->symbol_list); in read_sections()
389 s = elf_getscn(elf->elf, i); in read_sections()
392 return -1; in read_sections()
395 sec->idx = elf_ndxscn(s); in read_sections()
397 if (!gelf_getshdr(s, &sec->sh)) { in read_sections()
399 return -1; in read_sections()
402 sec->name = elf_strptr(elf->elf, shstrndx, sec->sh.sh_name); in read_sections()
403 if (!sec->name) { in read_sections()
405 return -1; in read_sections()
409 sec->data = elf_getdata(s, NULL); in read_sections()
410 if (!sec->data) { in read_sections()
412 return -1; in read_sections()
414 if (sec->data->d_off != 0 || in read_sections()
415 sec->data->d_size != sec_size(sec)) { in read_sections()
416 ERROR("unexpected data attributes for %s", sec->name); in read_sections()
417 return -1; in read_sections()
421 list_add_tail(&sec->list, &elf->sections); in read_sections()
422 elf_hash_add(section, &sec->hash, sec->idx); in read_sections()
423 elf_hash_add(section_name, &sec->name_hash, str_hash(sec->name)); in read_sections()
426 elf->num_relocs += sec_num_entries(sec); in read_sections()
431 printf("section_bits: %d\n", elf->section_bits); in read_sections()
435 if (elf_nextscn(elf->elf, s)) { in read_sections()
436 ERROR("section entry mismatch"); in read_sections()
437 return -1; in read_sections()
448 return sym->name; in demangle_name()
451 return sym->name; in demangle_name()
453 if (!strstarts(sym->name, "__UNIQUE_ID_") && !strchr(sym->name, '.')) in demangle_name()
454 return sym->name; in demangle_name()
456 str = strdup(sym->name); in demangle_name()
462 for (int i = strlen(str) - 1; i >= 0; i--) { in demangle_name()
480 INIT_LIST_HEAD(&sym->pv_target); in elf_add_symbol()
481 sym->alias = sym; in elf_add_symbol()
483 sym->type = GELF_ST_TYPE(sym->sym.st_info); in elf_add_symbol()
484 sym->bind = GELF_ST_BIND(sym->sym.st_info); in elf_add_symbol()
487 elf->num_files++; in elf_add_symbol()
489 sym->offset = sym->sym.st_value; in elf_add_symbol()
490 sym->len = sym->sym.st_size; in elf_add_symbol()
492 __sym_for_each(iter, &sym->sec->symbol_tree, sym->offset, sym->offset) { in elf_add_symbol()
493 if (!is_undef_sym(iter) && iter->offset == sym->offset && in elf_add_symbol()
494 iter->type == sym->type && iter->len == sym->len) in elf_add_symbol()
495 iter->alias = sym; in elf_add_symbol()
498 __sym_insert(sym, &sym->sec->symbol_tree); in elf_add_symbol()
499 pnode = rb_prev(&sym->node); in elf_add_symbol()
501 entry = &rb_entry(pnode, struct symbol, node)->list; in elf_add_symbol()
503 entry = &sym->sec->symbol_list; in elf_add_symbol()
504 list_add(&sym->list, entry); in elf_add_symbol()
506 list_add_tail(&sym->global_list, &elf->symbols); in elf_add_symbol()
507 elf_hash_add(symbol, &sym->hash, sym->idx); in elf_add_symbol()
508 elf_hash_add(symbol_name, &sym->name_hash, str_hash(sym->name)); in elf_add_symbol()
511 (strstarts(sym->name, "__pfx_") || in elf_add_symbol()
512 strstarts(sym->name, "__cfi_") || in elf_add_symbol()
513 strstarts(sym->name, "__pi___pfx_") || in elf_add_symbol()
514 strstarts(sym->name, "__pi___cfi_"))) in elf_add_symbol()
515 sym->prefix = 1; in elf_add_symbol()
517 if (strstarts(sym->name, ".klp.sym")) in elf_add_symbol()
518 sym->klp = 1; in elf_add_symbol()
520 if (!sym->klp && !is_sec_sym(sym) && strstr(sym->name, ".cold")) { in elf_add_symbol()
521 sym->cold = 1; in elf_add_symbol()
527 sym->type = STT_FUNC; in elf_add_symbol()
530 sym->pfunc = sym->cfunc = sym; in elf_add_symbol()
532 sym->demangled_name = demangle_name(sym); in elf_add_symbol()
533 if (!sym->demangled_name) in elf_add_symbol()
534 return -1; in elf_add_symbol()
541 struct section *symtab, *symtab_shndx, *sec; in read_symbols()
552 shndx_data = symtab_shndx->data; in read_symbols()
567 return -1; in read_symbols()
569 elf->symbol_data = calloc(symbols_nr, sizeof(*sym)); in read_symbols()
570 if (!elf->symbol_data) { in read_symbols()
572 return -1; in read_symbols()
575 INIT_LIST_HEAD(&elf->symbols); in read_symbols()
578 sym = &elf->symbol_data[i]; in read_symbols()
580 sym->idx = i; in read_symbols()
582 if (!gelf_getsymshndx(symtab->data, shndx_data, i, &sym->sym, in read_symbols()
585 return -1; in read_symbols()
588 sym->name = elf_strptr(elf->elf, symtab->sh.sh_link, in read_symbols()
589 sym->sym.st_name); in read_symbols()
590 if (!sym->name) { in read_symbols()
592 return -1; in read_symbols()
595 if ((sym->sym.st_shndx > SHN_UNDEF && in read_symbols()
596 sym->sym.st_shndx < SHN_LORESERVE) || in read_symbols()
597 (shndx_data && sym->sym.st_shndx == SHN_XINDEX)) { in read_symbols()
598 if (sym->sym.st_shndx != SHN_XINDEX) in read_symbols()
599 shndx = sym->sym.st_shndx; in read_symbols()
601 sym->sec = find_section_by_index(elf, shndx); in read_symbols()
602 if (!sym->sec) { in read_symbols()
603 ERROR("couldn't find section for symbol %s", sym->name); in read_symbols()
604 return -1; in read_symbols()
606 if (GELF_ST_TYPE(sym->sym.st_info) == STT_SECTION) { in read_symbols()
607 sym->name = sym->sec->name; in read_symbols()
608 sym->sec->sym = sym; in read_symbols()
611 sym->sec = find_section_by_index(elf, 0); in read_symbols()
614 return -1; in read_symbols()
616 if (sym->type == STT_FILE) in read_symbols()
618 else if (sym->bind == STB_LOCAL) in read_symbols()
619 sym->file = file; in read_symbols()
624 printf("symbol_bits: %d\n", elf->symbol_bits); in read_symbols()
628 list_for_each_entry(sec, &elf->sections, list) { in read_symbols()
633 if (!sym->cold) in read_symbols()
636 coldstr = strstr(sym->name, ".cold"); in read_symbols()
638 ERROR("%s(): cold subfunction without \".cold\"?", sym->name); in read_symbols()
639 return -1; in read_symbols()
642 pnamelen = coldstr - sym->name; in read_symbols()
643 pname = strndup(sym->name, pnamelen); in read_symbols()
645 ERROR("%s(): failed to allocate memory", sym->name); in read_symbols()
646 return -1; in read_symbols()
649 pfunc = find_local_symbol_by_file_and_name(elf, sym->file, pname); in read_symbols()
655 ERROR("%s(): can't find parent function", sym->name); in read_symbols()
656 return -1; in read_symbols()
659 sym->pfunc = pfunc->alias; in read_symbols()
660 pfunc->cfunc = sym; in read_symbols()
661 pfunc->alias->cfunc = sym; in read_symbols()
664 * Unfortunately, -fnoreorder-functions puts the child in read_symbols()
668 * Note that pfunc->len now no longer matches in read_symbols()
669 * pfunc->sym.st_size. in read_symbols()
671 if (sym->sec == pfunc->sec && in read_symbols()
672 sym->offset >= pfunc->offset && in read_symbols()
673 sym->offset + sym->len == pfunc->offset + pfunc->len) { in read_symbols()
674 pfunc->len -= sym->len; in read_symbols()
684 struct section *symtab, *sec; in mark_group_syms()
690 return -1; in mark_group_syms()
694 if (sec->sh.sh_type == SHT_GROUP && in mark_group_syms()
695 sec->sh.sh_link == symtab->idx) { in mark_group_syms()
696 sym = find_symbol_by_index(elf, sec->sh.sh_info); in mark_group_syms()
699 sec->name); in mark_group_syms()
700 return -1; in mark_group_syms()
703 sym->group_sec = sec; in mark_group_syms()
717 for (reloc = sym->relocs; reloc; reloc = sym_next_reloc(reloc)) in elf_update_sym_relocs()
718 set_reloc_sym(elf, reloc, reloc->sym->idx); in elf_update_sym_relocs()
731 static int elf_update_symbol(struct elf *elf, struct section *symtab, in elf_update_symbol()
732 struct section *symtab_shndx, struct symbol *sym) in elf_update_symbol()
736 Elf64_Xword entsize = symtab->sh.sh_entsize; in elf_update_symbol()
737 int max_idx, idx = sym->idx; in elf_update_symbol()
739 bool is_special_shndx = sym->sym.st_shndx >= SHN_LORESERVE && in elf_update_symbol()
740 sym->sym.st_shndx != SHN_XINDEX; in elf_update_symbol()
742 shndx = is_special_shndx ? sym->sym.st_shndx : sym->sec->idx; in elf_update_symbol()
744 s = elf_getscn(elf->elf, symtab->idx); in elf_update_symbol()
747 return -1; in elf_update_symbol()
751 t = elf_getscn(elf->elf, symtab_shndx->idx); in elf_update_symbol()
754 return -1; in elf_update_symbol()
764 /* end-of-list */ in elf_update_symbol()
767 * Over-allocate to avoid O(n^2) symbol creation in elf_update_symbol()
771 int num = max(1U, sym->idx/3); in elf_update_symbol()
777 return -1; in elf_update_symbol()
788 return -1; in elf_update_symbol()
791 symtab_data->d_buf = buf; in elf_update_symbol()
792 symtab_data->d_size = num * entsize; in elf_update_symbol()
793 symtab_data->d_align = 1; in elf_update_symbol()
794 symtab_data->d_type = ELF_T_SYM; in elf_update_symbol()
797 symtab->truncate = true; in elf_update_symbol()
803 return -1; in elf_update_symbol()
806 shndx_data->d_buf = buf; in elf_update_symbol()
807 shndx_data->d_size = num * sizeof(Elf32_Word); in elf_update_symbol()
808 shndx_data->d_align = sizeof(Elf32_Word); in elf_update_symbol()
809 shndx_data->d_type = ELF_T_WORD; in elf_update_symbol()
812 symtab_shndx->truncate = true; in elf_update_symbol()
819 if (!symtab_data->d_size) { in elf_update_symbol()
821 return -1; in elf_update_symbol()
825 max_idx = symtab_data->d_size / entsize; in elf_update_symbol()
830 idx -= max_idx; in elf_update_symbol()
833 /* something went side-ways */ in elf_update_symbol()
836 return -1; in elf_update_symbol()
839 /* setup extended section index magic and write the symbol */ in elf_update_symbol()
841 sym->sym.st_shndx = shndx; in elf_update_symbol()
845 sym->sym.st_shndx = SHN_XINDEX; in elf_update_symbol()
848 return -1; in elf_update_symbol()
852 if (!gelf_update_symshndx(symtab_data, shndx_data, idx, &sym->sym, shndx)) { in elf_update_symbol()
854 return -1; in elf_update_symbol()
861 struct section *sec, unsigned int bind, in elf_create_symbol()
865 struct section *symtab, *symtab_shndx; in elf_create_symbol()
875 sym->name = strdup(name); in elf_create_symbol()
876 if (!sym->name) { in elf_create_symbol()
882 sym->sym.st_name = elf_add_string(elf, NULL, sym->name); in elf_create_symbol()
883 if (sym->sym.st_name == -1) in elf_create_symbol()
888 sym->sec = sec; in elf_create_symbol()
890 sym->sec = find_section_by_index(elf, 0); in elf_create_symbol()
891 if (!sym->sec) { in elf_create_symbol()
892 ERROR("no NULL section"); in elf_create_symbol()
897 sym->sym.st_info = GELF_ST_INFO(bind, type); in elf_create_symbol()
898 sym->sym.st_value = offset; in elf_create_symbol()
899 sym->sym.st_size = size; in elf_create_symbol()
918 first_non_local = symtab->sh.sh_info; in elf_create_symbol()
922 elf_hash_del(symbol, &old->hash, old->idx); in elf_create_symbol()
923 elf_hash_add(symbol, &old->hash, new_idx); in elf_create_symbol()
924 old->idx = new_idx; in elf_create_symbol()
934 if (old->group_sec) { in elf_create_symbol()
935 old->group_sec->sh.sh_info = new_idx; in elf_create_symbol()
936 mark_sec_changed(elf, old->group_sec, true); in elf_create_symbol()
945 symtab->sh.sh_info += 1; in elf_create_symbol()
948 sym->idx = new_idx; in elf_create_symbol()
949 if (sym->idx && elf_update_symbol(elf, symtab, symtab_shndx, sym)) in elf_create_symbol()
952 symtab->sh.sh_size += symtab->sh.sh_entsize; in elf_create_symbol()
956 symtab_shndx->sh.sh_size += sizeof(Elf32_Word); in elf_create_symbol()
966 struct symbol *elf_create_section_symbol(struct elf *elf, struct section *sec) in elf_create_section_symbol()
970 sym = elf_create_symbol(elf, sec->name, sec, STB_LOCAL, STT_SECTION, 0, 0); in elf_create_section_symbol()
974 sec->sym = sym; in elf_create_section_symbol()
979 struct reloc *elf_init_reloc(struct elf *elf, struct section *rsec, in elf_init_reloc()
987 __func__, reloc_idx, rsec->name, sec_num_entries(rsec)); in elf_init_reloc()
991 reloc = &rsec->relocs[reloc_idx]; in elf_init_reloc()
995 __func__, rsec->name, reloc_idx); in elf_init_reloc()
999 reloc->sec = rsec; in elf_init_reloc()
1000 reloc->sym = sym; in elf_init_reloc()
1003 set_reloc_sym(elf, reloc, sym->idx); in elf_init_reloc()
1007 elf_hash_add(reloc, &reloc->hash, reloc_hash(reloc)); in elf_init_reloc()
1008 set_sym_next_reloc(reloc, sym->relocs); in elf_init_reloc()
1009 sym->relocs = reloc; in elf_init_reloc()
1014 struct reloc *elf_init_reloc_text_sym(struct elf *elf, struct section *sec, in elf_init_reloc_text_sym()
1017 struct section *insn_sec, in elf_init_reloc_text_sym()
1020 struct symbol *sym = insn_sec->sym; in elf_init_reloc_text_sym()
1024 ERROR("bad call to %s() for data symbol %s", __func__, sym->name); in elf_init_reloc_text_sym()
1030 * Due to how weak functions work, we must use section based in elf_init_reloc_text_sym()
1032 * weak and non-weak function annotations being overlaid on the in elf_init_reloc_text_sym()
1033 * non-weak function after linking. in elf_init_reloc_text_sym()
1040 return elf_init_reloc(elf, sec->rsec, reloc_idx, offset, sym, addend, in elf_init_reloc_text_sym()
1044 struct reloc *elf_init_reloc_data_sym(struct elf *elf, struct section *sec, in elf_init_reloc_data_sym()
1051 ERROR("bad call to %s() for text symbol %s", __func__, sym->name); in elf_init_reloc_data_sym()
1055 return elf_init_reloc(elf, sec->rsec, reloc_idx, offset, sym, addend, in elf_init_reloc_data_sym()
1062 struct section *rsec; in read_relocs()
1068 if (!elf_alloc_hash(reloc, elf->num_relocs)) in read_relocs()
1069 return -1; in read_relocs()
1071 list_for_each_entry(rsec, &elf->sections, list) { in read_relocs()
1075 rsec->base = find_section_by_index(elf, rsec->sh.sh_info); in read_relocs()
1076 if (!rsec->base) { in read_relocs()
1077 ERROR("can't find base section for reloc section %s", rsec->name); in read_relocs()
1078 return -1; in read_relocs()
1081 rsec->base->rsec = rsec; in read_relocs()
1084 rsec->nr_alloc_relocs = 0; in read_relocs()
1086 rsec->relocs = calloc(sec_num_entries(rsec), sizeof(*reloc)); in read_relocs()
1087 if (!rsec->relocs) { in read_relocs()
1089 return -1; in read_relocs()
1094 reloc = &rsec->relocs[i]; in read_relocs()
1096 reloc->sec = rsec; in read_relocs()
1098 reloc->sym = sym = find_symbol_by_index(elf, symndx); in read_relocs()
1099 if (!reloc->sym) { in read_relocs()
1100 ERROR("can't find reloc entry symbol %d for %s", symndx, rsec->name); in read_relocs()
1101 return -1; in read_relocs()
1104 elf_hash_add(reloc, &reloc->hash, reloc_hash(reloc)); in read_relocs()
1105 set_sym_next_reloc(reloc, sym->relocs); in read_relocs()
1106 sym->relocs = reloc; in read_relocs()
1115 printf("num_relocs: %lu\n", elf->num_relocs); in read_relocs()
1116 printf("reloc_bits: %d\n", elf->reloc_bits); in read_relocs()
1136 INIT_LIST_HEAD(&elf->sections); in elf_open_read()
1138 elf->fd = open(name, flags); in elf_open_read()
1139 if (elf->fd == -1) { in elf_open_read()
1145 elf->name = strdup(name); in elf_open_read()
1146 if (!elf->name) { in elf_open_read()
1158 elf->elf = elf_begin(elf->fd, cmd, NULL); in elf_open_read()
1159 if (!elf->elf) { in elf_open_read()
1164 if (!gelf_getehdr(elf->elf, &elf->ehdr)) { in elf_open_read()
1190 struct section *null, *symtab, *strtab, *shstrtab; in elf_create_file()
1203 INIT_LIST_HEAD(&elf->sections); in elf_create_file()
1213 elf->fd = mkstemp(tmp_name); in elf_create_file()
1214 if (elf->fd == -1) { in elf_create_file()
1219 elf->tmp_name = tmp_name; in elf_create_file()
1221 elf->name = strdup(name); in elf_create_file()
1222 if (!elf->name) { in elf_create_file()
1227 elf->elf = elf_begin(elf->fd, ELF_C_WRITE, NULL); in elf_create_file()
1228 if (!elf->elf) { in elf_create_file()
1233 if (!gelf_newehdr(elf->elf, ELFCLASS64)) { in elf_create_file()
1238 memcpy(&elf->ehdr, ehdr, sizeof(elf->ehdr)); in elf_create_file()
1240 if (!gelf_update_ehdr(elf->elf, &elf->ehdr)) { in elf_create_file()
1245 INIT_LIST_HEAD(&elf->symbols); in elf_create_file()
1247 if (!elf_alloc_hash(section, 1000) || in elf_create_file()
1261 null->name = ""; in elf_create_file()
1262 shstrtab->name = ".shstrtab"; in elf_create_file()
1263 strtab->name = ".strtab"; in elf_create_file()
1265 null->sh.sh_name = elf_add_string(elf, shstrtab, null->name); in elf_create_file()
1266 shstrtab->sh.sh_name = elf_add_string(elf, shstrtab, shstrtab->name); in elf_create_file()
1267 strtab->sh.sh_name = elf_add_string(elf, shstrtab, strtab->name); in elf_create_file()
1269 if (null->sh.sh_name == -1 || shstrtab->sh.sh_name == -1 || strtab->sh.sh_name == -1) in elf_create_file()
1272 elf_hash_add(section_name, &null->name_hash, str_hash(null->name)); in elf_create_file()
1273 elf_hash_add(section_name, &strtab->name_hash, str_hash(strtab->name)); in elf_create_file()
1274 elf_hash_add(section_name, &shstrtab->name_hash, str_hash(shstrtab->name)); in elf_create_file()
1276 if (elf_add_string(elf, strtab, "") == -1) in elf_create_file()
1283 symtab->sh.sh_link = strtab->idx; in elf_create_file()
1284 symtab->sh.sh_info = 1; in elf_create_file()
1286 elf->ehdr.e_shstrndx = shstrtab->idx; in elf_create_file()
1287 if (!gelf_update_ehdr(elf->elf, &elf->ehdr)) { in elf_create_file()
1298 sym->name = ""; in elf_create_file()
1299 sym->sec = null; in elf_create_file()
1305 unsigned int elf_add_string(struct elf *elf, struct section *strtab, const char *str) in elf_add_string()
1312 ERROR("can't find .strtab section"); in elf_add_string()
1313 return -1; in elf_add_string()
1316 if (!strtab->sh.sh_addralign) { in elf_add_string()
1317 ERROR("'%s': invalid sh_addralign", strtab->name); in elf_add_string()
1318 return -1; in elf_add_string()
1321 offset = ALIGN(strtab->sh.sh_size, strtab->sh.sh_addralign); in elf_add_string()
1324 return -1; in elf_add_string()
1329 void *elf_add_data(struct elf *elf, struct section *sec, const void *data, size_t size) in elf_add_data()
1334 if (!sec->sh.sh_addralign) { in elf_add_data()
1335 ERROR("'%s': invalid sh_addralign", sec->name); in elf_add_data()
1339 s = elf_getscn(elf->elf, sec->idx); in elf_add_data()
1345 sec->data = elf_newdata(s); in elf_add_data()
1346 if (!sec->data) { in elf_add_data()
1351 sec->data->d_buf = calloc(1, size); in elf_add_data()
1352 if (!sec->data->d_buf) { in elf_add_data()
1358 memcpy(sec->data->d_buf, data, size); in elf_add_data()
1360 sec->data->d_size = size; in elf_add_data()
1361 sec->data->d_align = sec->sh.sh_addralign; in elf_add_data()
1363 offset = ALIGN(sec->sh.sh_size, sec->sh.sh_addralign); in elf_add_data()
1364 sec->sh.sh_size = offset + size; in elf_add_data()
1368 return sec->data->d_buf; in elf_add_data()
1371 struct section *elf_create_section(struct elf *elf, const char *name, in elf_create_section()
1376 struct section *sec, *shstrtab; in elf_create_section()
1380 ERROR("section '%s' already exists", name); in elf_create_section()
1390 INIT_LIST_HEAD(&sec->symbol_list); in elf_create_section()
1392 /* don't actually create the section, just the data structures */ in elf_create_section()
1396 s = elf_newscn(elf->elf); in elf_create_section()
1402 sec->idx = elf_ndxscn(s); in elf_create_section()
1405 sec->data = elf_newdata(s); in elf_create_section()
1406 if (!sec->data) { in elf_create_section()
1411 sec->data->d_size = size; in elf_create_section()
1412 sec->data->d_align = 1; in elf_create_section()
1414 sec->data->d_buf = calloc(1, size); in elf_create_section()
1415 if (!sec->data->d_buf) { in elf_create_section()
1421 if (!gelf_getshdr(s, &sec->sh)) { in elf_create_section()
1426 sec->sh.sh_size = size; in elf_create_section()
1427 sec->sh.sh_entsize = entsize; in elf_create_section()
1428 sec->sh.sh_type = type; in elf_create_section()
1429 sec->sh.sh_addralign = align; in elf_create_section()
1430 sec->sh.sh_flags = flags; in elf_create_section()
1433 sec->name = strdup(name); in elf_create_section()
1434 if (!sec->name) { in elf_create_section()
1439 /* Add section name to .shstrtab (or .strtab for Clang) */ in elf_create_section()
1448 sec->sh.sh_name = elf_add_string(elf, shstrtab, sec->name); in elf_create_section()
1449 if (sec->sh.sh_name == -1) in elf_create_section()
1452 elf_hash_add(section_name, &sec->name_hash, str_hash(sec->name)); in elf_create_section()
1456 list_add_tail(&sec->list, &elf->sections); in elf_create_section()
1457 elf_hash_add(section, &sec->hash, sec->idx); in elf_create_section()
1464 static int elf_alloc_reloc(struct elf *elf, struct section *rsec) in elf_alloc_reloc()
1472 if (!rsec->data) { in elf_alloc_reloc()
1473 rsec->data = elf_newdata(elf_getscn(elf->elf, rsec->idx)); in elf_alloc_reloc()
1474 if (!rsec->data) { in elf_alloc_reloc()
1476 return -1; in elf_alloc_reloc()
1479 rsec->data->d_align = 1; in elf_alloc_reloc()
1480 rsec->data->d_type = ELF_T_RELA; in elf_alloc_reloc()
1481 rsec->data->d_buf = NULL; in elf_alloc_reloc()
1484 rsec->data->d_size = nr_relocs_new * elf_rela_size(elf); in elf_alloc_reloc()
1485 rsec->sh.sh_size = rsec->data->d_size; in elf_alloc_reloc()
1488 if (nr_alloc <= rsec->nr_alloc_relocs) in elf_alloc_reloc()
1491 if (rsec->data->d_buf && !rsec->nr_alloc_relocs) { in elf_alloc_reloc()
1492 void *orig_buf = rsec->data->d_buf; in elf_alloc_reloc()
1498 rsec->data->d_buf = malloc(nr_alloc * elf_rela_size(elf)); in elf_alloc_reloc()
1499 if (!rsec->data->d_buf) { in elf_alloc_reloc()
1501 return -1; in elf_alloc_reloc()
1503 memcpy(rsec->data->d_buf, orig_buf, in elf_alloc_reloc()
1506 rsec->data->d_buf = realloc(rsec->data->d_buf, in elf_alloc_reloc()
1508 if (!rsec->data->d_buf) { in elf_alloc_reloc()
1510 return -1; in elf_alloc_reloc()
1514 rsec->nr_alloc_relocs = nr_alloc; in elf_alloc_reloc()
1516 old_relocs = rsec->relocs; in elf_alloc_reloc()
1520 return -1; in elf_alloc_reloc()
1535 reloc = sym->relocs; in elf_alloc_reloc()
1540 sym->relocs = &new_relocs[reloc - old_relocs]; in elf_alloc_reloc()
1549 set_sym_next_reloc(reloc, &new_relocs[next_reloc - old_relocs]); in elf_alloc_reloc()
1562 elf_hash_del(reloc, &old->hash, key); in elf_alloc_reloc()
1563 elf_hash_add(reloc, &new->hash, key); in elf_alloc_reloc()
1568 rsec->relocs = new_relocs; in elf_alloc_reloc()
1572 struct section *elf_create_rela_section(struct elf *elf, struct section *sec, in elf_create_rela_section()
1575 struct section *rsec; in elf_create_rela_section()
1578 rsec_name = malloc(strlen(sec->name) + strlen(".rela") + 1); in elf_create_rela_section()
1584 strcat(rsec_name, sec->name); in elf_create_rela_section()
1594 rsec->data->d_type = ELF_T_RELA; in elf_create_rela_section()
1596 rsec->nr_alloc_relocs = nr_relocs; in elf_create_rela_section()
1597 rsec->relocs = calloc(nr_relocs, sizeof(struct reloc)); in elf_create_rela_section()
1598 if (!rsec->relocs) { in elf_create_rela_section()
1604 rsec->sh.sh_link = find_section_by_name(elf, ".symtab")->idx; in elf_create_rela_section()
1605 rsec->sh.sh_info = sec->idx; in elf_create_rela_section()
1607 sec->rsec = rsec; in elf_create_rela_section()
1608 rsec->base = sec; in elf_create_rela_section()
1613 struct reloc *elf_create_reloc(struct elf *elf, struct section *sec, in elf_create_reloc()
1618 struct section *rsec = sec->rsec; in elf_create_reloc()
1636 return elf_init_reloc(elf, rsec, sec_num_entries(rsec) - 1, offset, sym, in elf_create_reloc()
1640 struct section *elf_create_section_pair(struct elf *elf, const char *name, in elf_create_section_pair()
1644 struct section *sec; in elf_create_section_pair()
1657 int elf_write_insn(struct elf *elf, struct section *sec, in elf_write_insn()
1661 Elf_Data *data = sec->data; in elf_write_insn()
1663 if (data->d_type != ELF_T_BYTE || data->d_off) { in elf_write_insn()
1664 ERROR("write to unexpected data for section: %s", sec->name); in elf_write_insn()
1665 return -1; in elf_write_insn()
1668 memcpy(data->d_buf + offset, insn, len); in elf_write_insn()
1679 * A) adhere to the section header and truncate the data, or
1680 * B) ignore the section header and write out all the data you've got?
1682 * Yes, libelf sucks and we need to manually truncate if we over-allocate data.
1684 static int elf_truncate_section(struct elf *elf, struct section *sec) in elf_truncate_section()
1691 s = elf_getscn(elf->elf, sec->idx); in elf_truncate_section()
1694 return -1; in elf_truncate_section()
1698 /* get next data descriptor for the relevant section */ in elf_truncate_section()
1702 ERROR("end of section data but non-zero size left\n"); in elf_truncate_section()
1703 return -1; in elf_truncate_section()
1711 return -1; in elf_truncate_section()
1714 if (!data->d_size) { in elf_truncate_section()
1716 return -1; in elf_truncate_section()
1719 if (data->d_size > size) { in elf_truncate_section()
1721 data->d_size = size; in elf_truncate_section()
1724 size -= data->d_size; in elf_truncate_section()
1730 struct section *sec; in elf_write()
1733 /* Update changed relocation sections and section headers: */ in elf_write()
1734 list_for_each_entry(sec, &elf->sections, list) { in elf_write()
1735 if (sec->truncate && elf_truncate_section(elf, sec)) in elf_write()
1736 return -1; in elf_write()
1739 s = elf_getscn(elf->elf, sec->idx); in elf_write()
1742 return -1; in elf_write()
1745 /* Note this also flags the section dirty */ in elf_write()
1746 if (!gelf_update_shdr(s, &sec->sh)) { in elf_write()
1748 return -1; in elf_write()
1755 /* Make sure the new section header entries get updated properly. */ in elf_write()
1756 elf_flagelf(elf->elf, ELF_C_SET, ELF_F_DIRTY); in elf_write()
1759 if (elf_update(elf->elf, ELF_C_WRITE) < 0) { in elf_write()
1761 return -1; in elf_write()
1764 elf->changed = false; in elf_write()
1771 if (elf->elf) in elf_close()
1772 elf_end(elf->elf); in elf_close()
1774 if (elf->fd > 0) in elf_close()
1775 close(elf->fd); in elf_close()
1777 if (elf->tmp_name && rename(elf->tmp_name, elf->name)) in elf_close()
1778 return -1; in elf_close()