/
cmds_helper_funcs.c
320 lines (232 loc) · 7.17 KB
/
cmds_helper_funcs.c
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
#include "cmds_helper_funcs.h"
//file_cmd helper funcs
//DBG init and exit functions
error_t load_dbg(mygdb_info_t* gdb_info){
Dwarf_Error err;
Dwarf_Die no_die = 0;
Dwarf_Unsigned cu_header_length;
Dwarf_Half version_stamp;
Dwarf_Unsigned abbrev_offset;
Dwarf_Half addr_size;
Dwarf_Unsigned nxt_cu_hdr;
gdb_info->dbg_fd = open(gdb_info->src_file, O_RDONLY);
if( dwarf_init(gdb_info->dbg_fd,DW_DLC_READ,0,0, &gdb_info->dbg, &err) != DW_DLV_OK )
return E_FATAL;
printf("Succesfully loaded symbol info\n");
int res;
if( (res = dwarf_next_cu_header(gdb_info->dbg, &cu_header_length, &version_stamp, &abbrev_offset, &addr_size, &nxt_cu_hdr, &err)) == DW_DLV_ERROR ){
printf("failed to get next header\n");
return E_FATAL;
}
if( dwarf_siblingof(gdb_info->dbg, no_die, &gdb_info->cu_die, &err) == DW_DLV_ERROR){
printf("siblingof() failed\n");
return E_FATAL;
}
return E_NONE;
}
void release_dbg(mygdb_info_t* gdb_info){
Dwarf_Error* err = NULL;
dwarf_finish(gdb_info->dbg, err);
close(gdb_info->dbg_fd);
gdb_info->dbg_fd = -1;
}
//run_cmd helper func
void parse_args(mygdb_info_t* gdb_info, cmd_info_t* info, char* input){
int i;
for(i = 0; i < MAX_CMD_ARGS; i++){
info->run.args[i] = malloc(sizeof(char)*MAX_IN_LINE_SZ);
}
printf("input = %s\n", input);
char tmp[MAX_IN_LINE_SZ];
strcpy(tmp, "");
strcat(tmp, "./");
strcat(tmp, gdb_info->src_file);
info->run.args[0] = strdup(tmp);
i = 1;
strtok(input, " \n");
while((input = strtok(NULL, " \n")) != NULL && i < MAX_CMD_ARGS){
info->run.args[i++] = strdup(input);
}
info->run.args[i] = NULL;
}
//print_cmd helper funcs
error_t ip_in_func(Dwarf_Die the_die, size_t rip, bool* res){
char* die_name = 0;
Dwarf_Error err;
Dwarf_Half tag;
Dwarf_Attribute* attrs;
Dwarf_Addr lowpc, highpc;
Dwarf_Signed attrcount, i;
int rc = dwarf_diename(the_die, &die_name, &err);
if (rc == DW_DLV_ERROR)
return E_FATAL;
else if (rc == DW_DLV_NO_ENTRY)
return E_NONE;
if (dwarf_tag(the_die, &tag, &err) != DW_DLV_OK)
return E_FATAL;
/* Only interested in subprogram DIEs here */
if (tag != DW_TAG_subprogram)
return E_NONE;
/* Grab the DIEs attributes for display */
if (dwarf_attrlist(the_die, &attrs, &attrcount, &err) != DW_DLV_OK)
return E_FATAL;
for (i = 0; i < attrcount; ++i) {
Dwarf_Half attrcode;
if (dwarf_whatattr(attrs[i], &attrcode, &err) != DW_DLV_OK)
return E_FATAL;
/* We only take some of the attributes for display here.
** More can be picked with appropriate tag constants.
*/
if (attrcode == DW_AT_low_pc)
dwarf_formaddr(attrs[i], &lowpc, 0);
else if (attrcode == DW_AT_high_pc)
dwarf_formaddr(attrs[i], &highpc, 0);
}
if( rip >= lowpc && rip <= highpc){
*res = true;
return E_NONE;
}
return E_NONE;
}
error_t find_func_die(mygdb_info_t* gdb_info, Dwarf_Die* ret_die){
Dwarf_Error err;
//Dwarf_Die child_die;
/* Find compilation unit header */
/* Expect the CU DIE to have children */
if (dwarf_child(gdb_info->cu_die, ret_die, &err) == DW_DLV_ERROR)
return E_FATAL;
struct user_regs_struct regs;
if( ptrace(PTRACE_GETREGS, gdb_info->child_pid, NULL, ®s) < 0)
return E_FATAL;
/* Now go over all children DIEs */
while (1) {
int rc;
bool found = false;
if( ip_in_func(*ret_die, regs.rip - 1, &found) == E_FATAL)
return E_FATAL;
if(found){
return E_NONE;
}
rc = dwarf_siblingof(gdb_info->dbg, *ret_die, ret_die, &err);
if (rc == DW_DLV_ERROR)
return E_FATAL;
else if (rc == DW_DLV_NO_ENTRY){
return E_FATAL; //Func not found!
}
}
return E_FATAL; // didnt find func
}
error_t is_right_var(Dwarf_Die var_die, char* var_name, bool* found){
char* die_name = 0;
Dwarf_Error err;
Dwarf_Half tag;
Dwarf_Attribute* attrs;
Dwarf_Signed attrcount, i;
int rc = dwarf_diename(var_die, &die_name, &err);
if (rc == DW_DLV_ERROR)
return E_FATAL;
else if (rc == DW_DLV_NO_ENTRY)
return E_NONE;
if (dwarf_tag(var_die, &tag, &err) != DW_DLV_OK)
return E_FATAL;
/* Only interested in variable DIEs here */
if (tag != DW_TAG_variable)
return E_NONE;
/* Grab the DIEs attributes for display */
if (dwarf_attrlist(var_die, &attrs, &attrcount, &err) != DW_DLV_OK)
return E_FATAL;
for (i = 0; i < attrcount; ++i) {
Dwarf_Half attrcode;
if (dwarf_whatattr(attrs[i], &attrcode, &err) != DW_DLV_OK)
return E_FATAL;
if (attrcode == DW_AT_name){
char* die_var_name;
dwarf_formstring(attrs[i], &die_var_name, &err);
if( strcmp(die_var_name, var_name) == 0 ){
*found = true;
return E_NONE;
}
}
}
return E_NONE; //Not var_die being searched for
}
error_t print_local_var(mygdb_info_t* gdb_info, Dwarf_Die var_die, char* var_name){
Dwarf_Half tag;
Dwarf_Error err;
unsigned long var_addr;
Dwarf_Attribute* attrs;
Dwarf_Locdesc* locs_var;
Dwarf_Signed attrcount, i, cnt_var;
if (dwarf_tag(var_die, &tag, &err) != DW_DLV_OK)
return E_FATAL;
/* Make sure to only have a var die */
if (tag != DW_TAG_variable)
return E_FATAL;
/* Grab the DIEs attributes */
if (dwarf_attrlist(var_die, &attrs, &attrcount, &err) != DW_DLV_OK)
return E_FATAL;
for (i = 0; i < attrcount; ++i) {
Dwarf_Half attrcode;
if (dwarf_whatattr(attrs[i], &attrcode, &err) != DW_DLV_OK)
return E_FATAL;
if (attrcode == DW_AT_location)
break;
}
if( attrs[i] == NULL ){
printf("Failed to find the DW_AT_location attribute\n");
return E_NON_FATAL;
}
if( dwarf_loclist(attrs[i], &locs_var, &cnt_var, &err) != DW_DLV_OK){
printf("dwarf_loclist failed\n");
return E_FATAL;
}
if((cnt_var != 1) || (locs_var[0].ld_cents != 1) || (locs_var[0].ld_s[0].lr_atom != DW_OP_fbreg)){
fprintf(stderr, "Unexpected location information\n");
return E_NON_FATAL;
}
struct user_regs_struct regs;
if( ptrace(PTRACE_GETREGS, gdb_info->child_pid, NULL, ®s ) < 0 )
return E_FATAL;
var_addr = (unsigned long)(regs.rbp + (long)locs_var[0].ld_s[0].lr_number + 16);
errno = 0;
unsigned long data;
data = ptrace(PTRACE_PEEKTEXT, gdb_info->child_pid, (void*)var_addr);
if(errno){
printf("peektext failed\n");
return E_FATAL;
}
printf("%s = %lu\n", var_name, data);
return E_NONE;
}
error_t find_var_die(mygdb_info_t* gdb_info, Dwarf_Die func_die, char* var_name){
Dwarf_Half tag;
Dwarf_Error err;
Dwarf_Die child_die;
/* Find compilation unit header */
if (dwarf_tag(func_die, &tag, &err) != DW_DLV_OK)
return E_FATAL;
/* Can't find var if this isn't a func_die */
if (tag != DW_TAG_subprogram)
return E_FATAL; //
/* Expect the CU DIE to have children */
if (dwarf_child(func_die, &child_die, &err) == DW_DLV_ERROR)
return E_FATAL;
/* Now go over all children DIEs */
while (1) {
int rc;
bool found = false;
if( is_right_var(child_die, var_name, &found) == E_FATAL)
return E_FATAL;
if(found){
return print_local_var(gdb_info, child_die, var_name);
}
rc = dwarf_siblingof(gdb_info->dbg, child_die, &child_die, &err);
if (rc == DW_DLV_ERROR)
return E_FATAL;
else if (rc == DW_DLV_NO_ENTRY){
printf("Couldn't find var named: %s\n", var_name);
return E_NON_FATAL; //var not found!
}
}
return E_FATAL; //if reached here, didnt find var and didnt hit end of dies list
} //must have broken something