/* * kpatch-elf.h * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA, * 02110-1301, USA. */ #ifndef _KPATCH_ELF_H_ #define _KPATCH_ELF_H_ #include #include #include "list.h" #include "log.h" #define KLP_SYM_PREFIX ".klp.sym." #define KLP_RELASEC_PREFIX ".klp.rela." #define KLP_ARCH_PREFIX ".klp.arch." #define SHF_RELA_LIVEPATCH 0x00100000 #define SHN_LIVEPATCH 0xff20 /******************* * Data structures * ****************/ struct section; struct symbol; struct rela; enum status { NEW, CHANGED, SAME }; struct section { struct list_head list; struct section *twin; GElf_Shdr sh; Elf_Data *data; char *name; unsigned int index; enum status status; int include; int ignore; int grouped; union { struct { /* if (is_rela_section()) */ struct section *base; struct list_head relas; }; struct { /* else */ struct section *rela; struct symbol *secsym, *sym; }; }; }; enum symbol_strip { SYMBOL_DEFAULT, SYMBOL_USED, SYMBOL_STRIP, }; struct symbol { struct list_head list; struct symbol *twin; struct symbol *parent; struct list_head children; struct list_head subfunction_node; struct section *sec; GElf_Sym sym; char *name; struct object_symbol *lookup_table_file_sym; unsigned int index; unsigned char bind, type; enum status status; union { int include; /* used in the patched elf */ enum symbol_strip strip; /* used in the output elf */ }; int has_func_profiling; }; struct rela { struct list_head list; GElf_Rela rela; struct symbol *sym; unsigned int type; unsigned int offset; long addend; char *string; bool need_dynrela; }; struct string { struct list_head list; char *name; }; enum architecture { PPC64 = 0x1 << 0, X86_64 = 0x1 << 1, S390 = 0x1 << 2, }; struct kpatch_elf { Elf *elf; enum architecture arch; struct list_head sections; struct list_head symbols; struct list_head strings; Elf_Data *symtab_shndx; int fd; }; /******************* * Helper functions ******************/ char *status_str(enum status status); bool is_rela_section(struct section *sec); bool is_text_section(struct section *sec); bool is_debug_section(struct section *sec); struct section *find_section_by_index(struct list_head *list, unsigned int index); struct section *find_section_by_name(struct list_head *list, const char *name); struct symbol *find_symbol_by_index(struct list_head *list, size_t index); struct symbol *find_symbol_by_name(struct list_head *list, const char *name); struct rela *find_rela_by_offset(struct section *relasec, unsigned int offset); #define ALLOC_LINK(_new, _list) \ { \ (_new) = malloc(sizeof(*(_new))); \ if (!(_new)) \ ERROR("malloc"); \ memset((_new), 0, sizeof(*(_new))); \ INIT_LIST_HEAD(&(_new)->list); \ if (_list) \ list_add_tail(&(_new)->list, (_list)); \ } unsigned int absolute_rela_type(struct kpatch_elf *kelf); int offset_of_string(struct list_head *list, char *name); long rela_target_offset(struct kpatch_elf *kelf, struct section *relasec, struct rela *rela); unsigned int insn_length(struct kpatch_elf *kelf, void *addr); #ifndef R_PPC64_ENTRY #define R_PPC64_ENTRY 118 #endif /************* * Functions * **********/ struct kpatch_elf *kpatch_elf_open(const char *name); void kpatch_dump_kelf(struct kpatch_elf *kelf); bool is_null_sym(struct symbol *sym); bool is_file_sym(struct symbol *sym); bool is_local_func_sym(struct symbol *sym); bool is_local_sym(struct symbol *sym); void print_strtab(char *buf, size_t size); void kpatch_create_shstrtab(struct kpatch_elf *kelf); void kpatch_create_strtab(struct kpatch_elf *kelf); void kpatch_create_symtab(struct kpatch_elf *kelf); struct section *create_section_pair(struct kpatch_elf *kelf, char *name, int entsize, int nr); void kpatch_remove_and_free_section(struct kpatch_elf *kelf, char *secname); void kpatch_reindex_elements(struct kpatch_elf *kelf); void kpatch_rebuild_rela_section_data(struct section *sec); void kpatch_write_output_elf(struct kpatch_elf *kelf, Elf *elf, char *outfile, mode_t mode); void kpatch_elf_teardown(struct kpatch_elf *kelf); void kpatch_elf_free(struct kpatch_elf *kelf); #endif /* _KPATCH_ELF_H_ */