File: kpatch-elf.h

package info (click to toggle)
kpatch 0.9.10-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 4,716 kB
  • sloc: ansic: 9,716; sh: 2,592; makefile: 260; asm: 35
file content (192 lines) | stat: -rw-r--r-- 4,982 bytes parent folder | download
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_ */