-
Notifications
You must be signed in to change notification settings - Fork 33
/
objcommon.h
301 lines (267 loc) · 8.61 KB
/
objcommon.h
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
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
/* workaround for bfd crap check. WTF were they thinking? */
#ifndef PACKAGE
#define PACKAGE "ksplice"
#endif
#include <bfd.h>
#include <limits.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BITS_PER_LONG LONG_BIT
#define _PASTE(x, y) x##y
#define PASTE(x, y) _PASTE(x, y)
#define DIE do { fprintf(stderr, "ksplice: died at %s:%d\n", __FILE__, __LINE__); abort(); } while(0)
#define assert(x) do { if(!(x)) DIE; } while(0)
#define align(x, n) ((((x)+(n)-1)/(n))*(n))
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) );})
#define DECLARE_VEC_TYPE(elt_t, vectype) \
struct vectype { \
elt_t *data; \
size_t size; \
size_t mem_size; \
}
/* void vec_init(struct vectype *vec); */
#define vec_init(vec) *(vec) = (typeof(*(vec))) { NULL, 0, 0 }
/* void vec_move(struct vectype *dstvec, struct vectype *srcvec); */
#define vec_move(dstvec, srcvec) do { \
typeof(srcvec) _srcvec = (srcvec); \
*(dstvec) = *(_srcvec); \
vec_init(_srcvec); \
} while (0)
/* void vec_free(struct vectype *vec); */
#define vec_free(vec) do { \
typeof(vec) _vec1 = (vec); \
free(_vec1->data); \
vec_init(_vec1); \
} while (0)
void vec_do_reserve(void **data, size_t *mem_size, size_t newsize);
/* void vec_reserve(struct vectype *vec, size_t new_mem_size); */
#define vec_reserve(vec, new_mem_size) do { \
typeof(vec) _vec2 = (vec); \
vec_do_reserve((void **)&_vec2->data, &_vec2->mem_size, \
(new_mem_size)); \
} while (0)
/* void vec_resize(struct vectype *vec, size_t new_size); */
#define vec_resize(vec, new_size) do { \
typeof(vec) _vec3 = (vec); \
_vec3->size = (new_size); \
vec_reserve(_vec3, _vec3->size * sizeof(*_vec3->data)); \
} while (0)
/* elt_t *vec_grow(struct vectype *vec, size_t n); */
#define vec_grow(vec, n) ({ \
typeof(vec) _vec4 = (vec); \
size_t _n = (n); \
vec_resize(_vec4, _vec4->size + _n); \
_vec4->data + (_vec4->size - _n); \
})
DECLARE_VEC_TYPE(void, void_vec);
DECLARE_VEC_TYPE(arelent *, arelentp_vec);
DECLARE_VEC_TYPE(asymbol *, asymbolp_vec);
DECLARE_VEC_TYPE(asymbol **, asymbolpp_vec);
#define DECLARE_HASH_TYPE(elt_t, hashtype, \
hashtype_init, hashtype_free, \
hashtype_lookup) \
struct hashtype { \
struct bfd_hash_table root; \
}; \
\
void hashtype_init(struct hashtype *table); \
void hashtype_free(struct hashtype *table); \
typeof(elt_t) *hashtype_lookup(struct hashtype *table, \
const char *string, \
bfd_boolean create)
#ifndef BFD_HASH_TABLE_HAS_ENTSIZE
#define bfd_hash_table_init(table, newfunc, entry) \
bfd_hash_table_init(table, newfunc)
#endif
#define IMPLEMENT_HASH_TYPE(elt_t, hashtype, \
hashtype_init, hashtype_free, \
hashtype_lookup, \
elt_construct) \
\
struct hashtype##_entry { \
struct bfd_hash_entry root; \
typeof(elt_t) val; \
}; \
\
static struct bfd_hash_entry *hashtype##_newfunc( \
struct bfd_hash_entry *entry, \
struct bfd_hash_table *table, \
const char *string) \
{ \
if (entry == NULL) { \
entry = bfd_hash_allocate(table, \
sizeof(struct hashtype##_entry)); \
if (entry == NULL) \
return entry; \
} \
entry = bfd_hash_newfunc(entry, table, string); \
typeof(elt_t) *v = \
&container_of(entry, struct hashtype##_entry, \
root)->val; \
elt_construct(v); \
return entry; \
}; \
\
void hashtype_init(struct hashtype *table) \
{ \
bfd_hash_table_init(&table->root, hashtype##_newfunc, \
sizeof(struct hashtype##_entry)); \
} \
\
void hashtype_free(struct hashtype *table) \
{ \
bfd_hash_table_free(&table->root); \
} \
\
typeof(elt_t) *hashtype_lookup(struct hashtype *table, \
const char *string, \
bfd_boolean create) \
{ \
struct bfd_hash_entry *e = \
bfd_hash_lookup(&table->root, string, create, \
TRUE); \
if (create) \
assert(e != NULL); \
else if (e == NULL) \
return NULL; \
return &container_of(e, struct hashtype##_entry, \
root)->val; \
} \
\
struct eat_trailing_semicolon
#define DEFINE_HASH_TYPE(elt_t, hashtype, \
hashtype_init, hashtype_free, \
hashtype_lookup, \
elt_construct) \
DECLARE_HASH_TYPE(elt_t, hashtype, hashtype_init, \
hashtype_free, hashtype_lookup); \
IMPLEMENT_HASH_TYPE(elt_t, hashtype, hashtype_init, \
hashtype_free, hashtype_lookup, \
elt_construct);
#ifndef bfd_get_section_size
#define bfd_get_section_size(x) ((x)->_cooked_size)
#endif
DECLARE_HASH_TYPE(arelent *, arelentp_hash, arelentp_hash_init,
arelentp_hash_free, arelentp_hash_lookup);
DECLARE_HASH_TYPE(asymbol **, asymbolpp_hash, asymbolpp_hash_init,
asymbolpp_hash_free, asymbolpp_hash_lookup);
DECLARE_HASH_TYPE(const char *, string_hash, string_hash_init,
string_hash_free, string_hash_lookup);
struct label_map {
asymbol *csym;
const char *orig_label;
const char *label;
int count;
};
DECLARE_VEC_TYPE(struct label_map, label_map_vec);
DECLARE_HASH_TYPE(struct label_map *, label_mapp_hash, label_mapp_hash_init,
label_mapp_hash_free, label_mapp_hash_lookup);
struct entry_point {
const char *label;
const char *name;
long offset;
asymbol *symbol;
};
DECLARE_VEC_TYPE(struct entry_point, entry_point_vec);
struct span {
struct supersect *ss;
asymbol *symbol;
const char *orig_label;
const char *label;
bfd_vma start;
bfd_vma size;
bfd_vma contents_size;
bool keep;
bool new;
bool patch;
bool bugpatch;
bool datapatch;
bool precallable;
struct span *match;
struct entry_point_vec entry_points;
struct entry_point_vec pre_entry_points;
bfd_size_type shift;
};
DECLARE_VEC_TYPE(struct span, span_vec);
struct superbfd {
bfd *abfd;
struct asymbolp_vec syms;
struct supersect *new_supersects;
struct label_map_vec maps;
struct label_mapp_hash maps_hash;
struct asymbolpp_vec new_syms;
struct asymbolpp_hash csyms;
struct string_hash callers;
};
enum supersect_type {
SS_TYPE_TEXT, SS_TYPE_DATA, SS_TYPE_RODATA, SS_TYPE_STRING,
SS_TYPE_SPECIAL, SS_TYPE_IGNORED, SS_TYPE_KSPLICE, SS_TYPE_EXPORT,
SS_TYPE_EXIT, SS_TYPE_KSPLICE_CALL, SS_TYPE_KSPLICE_EXTRACT,
SS_TYPE_BUGTABLE, SS_TYPE_UNKNOWN
};
struct supersect {
struct superbfd *parent;
const char *name;
flagword flags;
struct void_vec contents;
int alignment;
unsigned int entsize;
struct arelentp_vec relocs;
struct arelentp_vec new_relocs;
struct supersect *next;
struct asymbolp_vec syms;
struct span_vec spans;
struct arelentp_hash reloc_hash;
asymbol *symbol;
bool keep;
enum supersect_type type;
enum supersect_type orig_type;
bool match_data_early;
};
struct superbfd *fetch_superbfd(bfd *abfd);
struct supersect *fetch_supersect(struct superbfd *sbfd, asection *sect);
struct supersect *new_supersect(struct superbfd *sbfd, const char *name);
void supersect_move(struct supersect *dest_ss, struct supersect *src_ss);
#define sect_grow(ss, n, type) \
((type *)sect_do_grow(ss, n, sizeof(type), __alignof__(type)))
void *sect_do_grow(struct supersect *ss, size_t n, size_t size, int alignment);
#define sect_copy(dest_ss, dest, src_ss, src, n) \
sect_do_copy(dest_ss, dest, src_ss, src, (n) * sizeof(*(src)))
void sect_do_copy(struct supersect *dest_ss, void *dest,
struct supersect *src_ss, const void *src, size_t n);
#define strstarts(str, prefix) \
(strncmp(str, prefix, strlen(prefix)) == 0)
#define ends_with(str, suffix) \
(strlen(str) >= strlen(suffix) && \
strcmp(&str[strlen(str) - strlen(suffix)], suffix) == 0)
bfd_vma addr_offset(struct supersect *ss, const void *addr);
bfd_vma reloc_offset(struct supersect *ss, arelent *reloc);
arelent *find_reloc(struct supersect *ss, const void *addr);
bfd_vma read_reloc(struct supersect *ss, const void *addr, size_t size,
asymbol **symp);
const void *read_pointer(struct supersect *ss, void *const *addr,
struct supersect **ssp);
const char *read_string(struct supersect *ss, const char *const *addr);
#define read_num(ss, addr) ((typeof(*(addr))) \
read_reloc(ss, addr, sizeof(*(addr)), NULL))
static inline char *vstrprintf(const char *fmt, va_list ap)
{
char *str;
assert(vasprintf(&str, fmt, ap) >= 0);
return str;
}
static inline char * __attribute__((format (printf, 1, 2)))
strprintf(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
char *str = vstrprintf(fmt, ap);
va_end(ap);
return str;
}