-
Notifications
You must be signed in to change notification settings - Fork 0
/
assembly.h
331 lines (263 loc) · 6.61 KB
/
assembly.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
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
/*
* Copyright (c) 2015-2016 SUSE Linux GmbH
*
* Licensed under the GNU General Public License Version 2
* as published by the Free Software Foundation.
*
* See http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* for details.
*
* Author: Joerg Roedel <[email protected]>
*/
#ifndef __ASSEMBLY_H
#define __ASSEMBLY_H
#include <vector>
#include <string>
#include <memory>
#include <map>
#include <functional>
#include "generic-diff.h"
namespace assembly {
enum class stmt_type {
NOSTMT = 0,
UNKNOWN,
DOTFILE,
INSTRUCTION,
SECTION,
TEXT,
DATA,
DATADEF,
BSS,
TYPE,
GLOBAL,
LOCAL,
STRING,
ASCII,
BYTE,
SHORT,
WORD,
LONG,
QUAD,
FLOAT,
DOUBLE,
ORG,
ZERO,
SIZE,
ALIGN,
P2ALIGN,
COMM,
LCOMM,
POPSECTION,
PUSHSECTION,
LABEL,
IDENT,
LOC,
CFI_STARTPROC,
CFI_ENDPROC,
CFI_OFFSET,
CFI_REMEBER_STATE,
CFI_RESTORE_STATE,
CFI_RESTORE,
CFI_DEF_CFA_OFFSET,
CFI_DEF_CFA_REGISTER,
CFI_DEF_CFA,
CFI_SECTIONS,
CFI_ESCAPE,
BALIGN,
WEAK,
VALUE,
ULEB128,
SLEB128,
};
enum class token_type {
UNKNOWN,
OPERATOR,
IDENTIFIER,
REGISTER,
NUMBER,
STRING,
TYPEFLAG,
};
enum class symbol_type {
FUNCTION,
OBJECT,
UNKNOWN,
};
enum class symbol_scope {
UNKNOWN,
LOCAL,
GLOBAL,
};
// Used as a bitfield
enum class func_flags {
NONE = 0,
NORMALIZE = 1,
STRIP_DEBUG = 2,
};
using symbol_map = std::map<std::string, std::string>;
constexpr enum func_flags operator|(const enum func_flags f1,
const enum func_flags f2)
{
return static_cast<enum func_flags>(
static_cast<int>(f1) | static_cast<int>(f2));
}
constexpr enum func_flags operator&(const enum func_flags f1,
const enum func_flags f2)
{
return static_cast<enum func_flags>(
static_cast<int>(f1) & static_cast<int>(f2));
}
class asm_token {
protected:
std::string m_token;
enum token_type m_type;
public:
asm_token(std::string, enum token_type);
enum token_type type() const;
std::string token() const;
void set(std::string);
std::string serialize() const;
};
class asm_param {
protected:
using token_t = std::vector<asm_token>;
using token_handler = std::function<void(asm_token&)>;
using const_token_handler = std::function<void(const asm_token&)>;
token_t m_tokens;
public:
template<typename T>
void add_token(T&&);
void reset();
size_t tokens() const;
void token(token_t::size_type,
std::function<void(enum token_type, std::string)>) const;
void for_each_token(token_handler);
void for_each_token(const_token_handler) const;
std::string serialize() const;
};
class asm_statement {
protected:
using param_type = std::vector<asm_param>;
using param_handler = std::function<void(asm_param&)>;
using const_param_handler = std::function<void(const asm_param&)>;
std::string m_stmt;
std::string m_instr;
enum stmt_type m_type;
param_type m_params;
public:
asm_statement(std::string);
virtual void rename_label(std::string, std::string);
virtual void analyze();
bool operator==(const asm_statement&) const;
bool operator!=(const asm_statement&) const;
void type(enum stmt_type);
enum stmt_type type() const;
std::string raw() const;
std::string instr() const;
void set_instr(std::string);
template<typename T> void add_param(T&&);
void param(param_type::size_type, param_handler);
void param(param_type::size_type, const_param_handler) const;
void for_each_param(param_handler);
void for_each_param(const_param_handler) const;
void map_symbols(symbol_map&, const asm_statement&) const;
std::string serialize() const;
std::string statement() const;
};
class asm_type : public asm_statement {
protected:
enum symbol_type m_stype;
std::string m_symbol;
public:
asm_type(std::string);
virtual void rename_label(std::string, std::string);
enum symbol_type get_type() const;
std::string get_symbol() const;
virtual void analyze();
};
class asm_label : public asm_statement {
public:
asm_label(std::string);
virtual void rename_label(std::string, std::string);
std::string get_label() const;
};
class asm_size : public asm_statement {
protected:
std::string m_symbol;
public:
asm_size(std::string);
virtual void rename_label(std::string, std::string);
virtual void analyze();
std::string get_symbol() const;
};
class asm_section : public asm_statement {
protected:
std::string m_name;
std::string m_flags;
bool m_executable;
public:
asm_section(std::string);
virtual void rename_label(std::string, std::string);
virtual void analyze();
std::string get_name() const;
bool executable() const;
};
class asm_comm : public asm_statement {
protected:
std::string m_symbol;
uint32_t m_alignment;
uint64_t m_size;
public:
asm_comm(std::string);
virtual void rename_label(std::string, std::string);
virtual void analyze();
std::string get_symbol() const;
};
struct asm_symbol {
size_t m_idx;
size_t m_size_idx;
size_t m_section_idx;
size_t m_align_idx;
size_t m_type_idx;
enum symbol_type m_type;
enum symbol_scope m_scope;
asm_symbol();
};
class asm_object : public diff::diffable<asm_statement> {
protected:
std::vector<std::unique_ptr<asm_statement>> m_statements;
std::string m_name;
public:
asm_object(std::string);
void add_statement(const std::unique_ptr<asm_statement> &stmt);
void for_each_statement(std::function<void(asm_statement&)>);
// Diffable interface
virtual diff::size_type elements() const;
virtual const asm_statement& element(diff::size_type) const;
std::vector<std::string> get_symbols() const;
void get_symbol_map(symbol_map&, const asm_object&) const;
};
class asm_file {
std::vector<std::unique_ptr<asm_statement>> m_statements;
std::map<std::string, asm_symbol> m_symbols;
std::string m_filename;
void cleanup_symbol_table();
public:
template<typename T> inline asm_file(T&& fn)
: m_filename(std::forward<T>(fn))
{}
void load();
const asm_statement& stmt(unsigned) const;
void for_each_symbol(std::function<void(std::string, asm_symbol)>);
bool has_symbol(std::string) const;
const asm_symbol& get_symbol(std::string) const;
bool has_function(std::string) const;
std::unique_ptr<asm_object> get_function(std::string, enum func_flags) const;
bool has_object(std::string) const;
std::unique_ptr<asm_object> get_object(std::string, enum func_flags) const;
};
using asm_diff = diff::diff<assembly::asm_statement>;
std::unique_ptr<asm_statement> parse_statement(std::string);
std::unique_ptr<asm_statement> copy_statement(const std::unique_ptr<asm_statement>&);
} // namespace assembly
#endif