1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192
|
/*
* 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 <stdbool.h>
#include <gelf.h>
#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 symbol *pfx;
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;
bool is_pfx;
struct section *pfe;
};
struct rela {
struct list_head list;
GElf_Rela rela;
struct symbol *sym;
unsigned int type;
unsigned int offset;
long addend;
char *string;
bool need_klp_reloc;
};
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;
bool has_pfe;
};
/*******************
* 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);
bool is_ubsan_sec(const char *name);
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_ */
|