Stackdb
Stackdb is a stackable, multi-target and -level source debugger and memory forensics library.
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
target_os_linux_generic_decoders.c
Go to the documentation of this file.
1 
2 /*
3  * We need type and value decoders. Sometimes the stringification of a
4  * type is always the same no matter the context; sometimes the context
5  * (i.e., additional argument values of a functions) determines the
6  * stringification.
7  */
8 
9 #include <target_api.h>
10 #include <stdio.h>
11 #include <errno.h>
12 #include <sys/types.h>
13 #include <arpa/inet.h>
14 #include <sys/socket.h>
15 #include <netinet/in.h>
16 #include <netinet/ip.h>
17 #include <sys/un.h>
18 
28 };
29 
30 int os_linux_sockaddr_snprintf(struct target *target,void *_data,
31  struct value *value,char *buf,int buflen) {
32  struct os_linux_generic_decoder_data *data =
33  (struct os_linux_generic_decoder_data *)_data;
34  struct value *clone;
35  struct value *v;
36  unum_t family;
37  int nrc = 0;
38  unsigned short port;
39  uint32_t flowinfo;
40  uint32_t scopeid;
41  struct in_addr addr;
42  struct in6_addr addr6;
43  char addrstr[INET_ADDRSTRLEN];
44 
45  if (!data) {
46  errno = EINVAL;
47  return -1;
48  }
49 
50 #define Lsnprintf(...) \
51  snprintf((buf != NULL) ? buf + nrc : NULL,(buflen != 0) ? buflen - nrc : 0, \
52  ## __VA_ARGS__)
53 
54  v = target_load_value_member(target,NULL,value,"sa_family",NULL,0);
55  if (!v)
56  return -1;
57  family = v_unum(v);
58  value_free(v);
59 
60  if (family == AF_UNIX && data->sockaddr_un_type) {
62  if (!clone)
63  return -1;
64  v = target_load_value_member(target,NULL,clone,"sun_path",NULL,0);
65  if (!v) {
66  value_free(clone);
67  return -1;
68  }
69  /*
70  * Handle sun_path specially because if abstract unix socket,
71  * then the first byte is \0 , then the real abstract path name
72  * follows.
73  */
74  if (v->bufsiz > 1 && v->buf[0] == '\0')
75  nrc += Lsnprintf("{ .sun_family = AF_UNIX, .sun_path = \"@%s\" }",
76  &(v->buf[1]));
77  else
78  nrc += Lsnprintf("{ .sun_family = AF_UNIX, .sun_path = \"%s\" }",
79  v->buf);
80  value_free(v);
81  value_free(clone);
82  return nrc;
83  }
84  else if (family == AF_INET) {
86  if (!clone)
87  return -1;
88  v = target_load_value_member(target,NULL,clone,"sin_port",NULL,0);
89  if (!v) {
90  value_free(clone);
91  return -1;
92  }
93  port = ntohs((uint16_t)v_unum(v));
94  value_free(v);
95  v = target_load_value_member(target,NULL,clone,"sin_addr.s_addr",".",0);
96  if (!v) {
97  value_free(clone);
98  return -1;
99  }
100  addr.s_addr = (uint32_t)v_unum(v);
101  inet_ntop(AF_INET,&addr,addrstr,sizeof(addrstr));
102  value_free(v);
103  nrc += Lsnprintf("{ .sin_family = AF_INET, .sin_port = %hu, .sin_addr = { .s_addr = \"%s\" } }",
104  port,addrstr);
105  value_free(clone);
106  return nrc;
107  }
108  else if (family == AF_INET6) {
110  if (!clone)
111  return -1;
112  v = target_load_value_member(target,NULL,clone,"sin6_port",NULL,0);
113  if (!v) {
114  verror("could not load sin6_port");
115  value_free(clone);
116  return -1;
117  }
118  port = ntohs((uint16_t)v_unum(v));
119  value_free(v);
120  v = target_load_value_member(target,NULL,clone,"sin6_flowinfo",NULL,0);
121  if (!v) {
122  verror("could not load sin6_flowinfo");
123  value_free(clone);
124  return -1;
125  }
126  flowinfo = ntohl((uint32_t)v_unum(v));
127  value_free(v);
128  v = target_load_value_member(target,NULL,clone,"sin6_addr",".",0);
129  if (!v) {
130  verror("could not load sin6_addr");
131  value_free(clone);
132  return -1;
133  }
134  memcpy(&addr6.s6_addr,v->buf,
135  ((unsigned)v->bufsiz > sizeof(addr6.s6_addr)) ? sizeof(addr6.s6_addr) : (unsigned)v->bufsiz);
136  inet_ntop(AF_INET6,&addr6,addrstr,sizeof(addrstr));
137  value_free(v);
138  v = target_load_value_member(target,NULL,clone,"sin6_scope_id",NULL,0);
139  if (!v) {
140  verror("could not load sin6_scope_id");
141  value_free(clone);
142  return -1;
143  }
144  scopeid = ntohl((uint32_t)v_unum(v));
145  value_free(v);
146  nrc += Lsnprintf("{ .sin6_family = AF_INET6, .sin6_port = %hu, .sin6_flowinfo = %u, .sin6_addr = { .s6_addr = \"%s\" }, .sin6_scope_id = %u }",
147  port,flowinfo,addrstr,scopeid);
148  value_free(clone);
149  return nrc;
150  }
151  else {
152  return -1;
153  }
154 }
155 
156 int os_linux_iovec_snprintf(struct target *target,void *_data,
157  struct value *value,char *buf,int buflen) {
158  struct os_linux_generic_decoder_data *data =
159  (struct os_linux_generic_decoder_data *)_data;
160  struct value *v;
161  int nrc = 0;
162  unum_t iovlen;
163  int iovlen_noload = 0;
164  int iovbase_noload = 0;
165  ADDR iovbase;
166  unsigned char *ibuf,*ibuf2;
167  unsigned int j;
168  int unprintable;
169 
170  if (!data) {
171  errno = EINVAL;
172  return -1;
173  }
174 
175 #define Lsnprintf(...) \
176  snprintf((buf != NULL) ? buf + nrc : NULL,(buflen != 0) ? buflen - nrc : 0, \
177  ## __VA_ARGS__)
178 
179  v = target_load_value_member(target,NULL,value,"iov_len",NULL,0);
180  if (!v) {
181  iovlen_noload = 1;
182  iovlen = 0;
183  }
184  else {
185  iovlen = v_unum(v);
186  value_free(v);
187  }
188 
189  v = target_load_value_member(target,NULL,value,"iov_base",NULL,0);
190  if (!v)
191  iovbase_noload = 1;
192  else {
193  iovbase = v_addr(v);
194  value_free(v);
195  }
196 
197  if (!iovbase_noload && iovbase != 0 && iovlen) {
198  ibuf = malloc(iovlen + 1);
199  if (!target_read_addr(target,iovbase,iovlen,ibuf)) {
200  nrc += Lsnprintf("{ .iov_base = 0x%"PRIxADDR,iovbase);
201  }
202  else {
203  ibuf[iovlen] = '\0';
204 
205  /* Check for unprintable chars */
206  unprintable = 0;
207  for (j = 0; j < iovlen; ++j) {
208  if (!isgraph(ibuf[j]) && !isspace(ibuf[j])) {
209  unprintable = 1;
210  break;
211  }
212  }
213 
214  if (unprintable) {
215  //nrc += Lsnprintf("{ .iov_base = 0h");
216  ibuf2 = malloc(iovlen * 2 + 1);
217  for (j = 0; j < iovlen; ++j) {
218  //nrc += Lsnprintf("%hhx",ibuf[j]);
219  sprintf((char *)(ibuf2 + j * 2),"%.2hhx",ibuf[j]);
220  }
221  ibuf2[iovlen * 2] = '\0';
222 
223  nrc += Lsnprintf("{ .iov_base = 0h%s",ibuf2);
224  free(ibuf2);
225  }
226  else
227  nrc += Lsnprintf("{ .iov_base = \"%s\"",ibuf);
228  }
229  free(ibuf);
230  }
231  else if (!iovbase_noload) {
232  nrc += Lsnprintf("{ .iov_base = 0x%"PRIxADDR,iovbase);
233  }
234  else
235  nrc += Lsnprintf("{ .iov_base = ?");
236 
237  if (!iovlen_noload)
238  nrc += Lsnprintf(", .iov_len = %"PRIuNUM" }",iovlen);
239  else
240  nrc += Lsnprintf(", .iov_len = ? }");
241 
242  return nrc;
243 }
244 
245 int os_linux_msghdr_snprintf(struct target *target,void *_data,
246  struct value *value,char *buf,int buflen) {
247  struct os_linux_generic_decoder_data *data =
248  (struct os_linux_generic_decoder_data *)_data;
249  struct value *clone;
250  struct value *v,*v2;
251  uint32_t namelen;
252  int nrc = 0;
253  int _trc;
254  unum_t controllen;
255  num_t iovlen;
256  short iovlen_noload = 0,controllen_noload = 0;
257  ADDR iov;
258  struct symbol *type;
259  int typesize;
260  unsigned int i;
261  ADDR control;
262  unum_t cmsglen;
263  int32_t cmsglevel,cmsgtype;
264  unsigned char *ibuf,*ibuf2;
265  unsigned int j;
266 
267  if (!data) {
268  errno = EINVAL;
269  return -1;
270  }
271 
272 #define Lsnprintf(...) \
273  snprintf((buf != NULL) ? buf + nrc : NULL,(buflen != 0) ? buflen - nrc : 0, \
274  ## __VA_ARGS__)
275 
276  v = target_load_value_member(target,NULL,value,"msg_namelen",NULL,0);
277  if (!v)
278  return -1;
279  namelen = v_u32(v);
280  value_free(v);
281 
282  v = target_load_value_member(target,NULL,value,"msg_name",NULL,0);
283  if (!v)
284  return -1;
285  /*
286  clone = value_reload_as_type(v,data->sockaddr_ptr_type,LOAD_FLAG_AUTO_DEREF);
287  */
288  if (v_addr(v) != 0) {
289  clone = target_load_type(target,bsymbol_get_symbol(data->sockaddr_type),
290  v_addr(v),0);
291  if (!clone) {
292  value_free(v);
293  nrc += Lsnprintf("{ .msg_name = ?");
294  }
295  else {
296  nrc += Lsnprintf("{ .msg_name = ");
297  _trc = os_linux_sockaddr_snprintf(target,_data,clone,
298  buf+nrc,buflen-nrc);
299  if (_trc < 0)
300  return -1;
301  else
302  nrc += _trc;
303  value_free(clone);
304  }
305  }
306  else {
307  nrc += Lsnprintf(", .msg_name = 0x0");
308  }
309  nrc += Lsnprintf(", .msg_namelen = %u",namelen);
310  value_free(v);
311 
312  v = target_load_value_member(target,NULL,value,"msg_iovlen",NULL,0);
313  if (!v) {
314  iovlen_noload = 1;
315  iovlen = 0;
316  }
317  else {
318  iovlen = v_num(v);
319  value_free(v);
320  }
321 
322  v = target_load_value_member(target,NULL,value,"msg_controllen",NULL,0);
323  if (!v) {
324  controllen_noload = 1;
325  controllen = 0;
326  }
327  else {
328  controllen = v_unum(v);
329  value_free(v);
330  }
331 
332  /*
333  * iovecs.
334  */
335  if (iovlen > 0) {
336  v = target_load_value_member(target,NULL,value,"msg_iov",NULL,
338  if (!v) {
339  nrc += Lsnprintf(", .msg_iov = ?");
340  }
341  else {
342  type = symbol_type_skip_ptrs(v->type);
343  typesize = symbol_type_full_bytesize(type);
344  nrc += Lsnprintf(", .msg_iov = [ ");
345  for (i = 0; i < iovlen; ++i) {
346  if (i > 0) {
347  nrc += Lsnprintf(", ");
348  }
349  nrc += os_linux_iovec_snprintf(target,data,v,
350  (buf != NULL) ? buf + nrc : NULL,
351  (buflen != 0) ? buflen - nrc : 0);
352  if ((i + 1) >= iovlen)
353  break;
354 
355  iov = value_addr(v) + typesize;
356  value_free(v);
357  v = target_load_type(target,type,iov,0);
358  if (!v) {
359  nrc += Lsnprintf(" ? ");
360  break;
361  }
362  }
363  nrc += Lsnprintf(" ]");
364  }
365  }
366  else {
367  v = target_load_value_member(target,NULL,value,"msg_iov",NULL,0);
368  if (!v)
369  iov = 0x0;
370  else {
371  iov = v_addr(v);
372  value_free(v);
373  }
374  nrc += Lsnprintf(", .msg_iov = %"PRIxADDR,iov);
375  }
376 
377  if (iovlen_noload)
378  nrc += Lsnprintf(", .msg_iovlen = ?");
379  else
380  nrc += Lsnprintf(", .msg_iovlen = %"PRIiNUM,iovlen);
381 
382  /*
383  * Control data.
384  */
385  if (controllen > 0) {
386  v = target_load_value_member(target,NULL,value,"msg_control",NULL,0);
387  if (!v) {
388  nrc += Lsnprintf(", .msg_control = ?");
389  }
390  else {
391  control = v_addr(v);
392  value_free(v);
393 
394  type = bsymbol_get_symbol(data->cmsghdr_type);
395  typesize = symbol_type_full_bytesize(type);
396  nrc += Lsnprintf(", .msg_control = [ ");
397  i = 0;
398  while ((i + typesize) <= controllen) {
399  if (i > 0) {
400  nrc += Lsnprintf(", ");
401  }
402 
403  v = target_load_type(target,type,control + i,0);
404  if (!v) {
405  nrc += Lsnprintf(" ? ");
406  break;
407  }
408 
409  v2 = target_load_value_member(target,NULL,v,"cmsg_len",NULL,0);
410  if (!v2) {
411  nrc += Lsnprintf(" ? ");
412  value_free(v);
413  break;
414  }
415  cmsglen = v_unum(v2);
416  if ((cmsglen + i) > controllen) {
417  nrc += Lsnprintf(" ? ");
418  value_free(v2);
419  value_free(v);
420  break;
421  }
422  else
423  value_free(v2);
424 
425  v2 = target_load_value_member(target,NULL,v,"cmsg_level",NULL,0);
426  if (!v2) {
427  nrc += Lsnprintf(" ? ");
428  value_free(v);
429  break;
430  }
431  cmsglevel = v_i32(v2);
432  value_free(v2);
433 
434  v2 = target_load_value_member(target,NULL,v,"cmsg_type",NULL,0);
435  if (!v2) {
436  nrc += Lsnprintf(" ? ");
437  value_free(v);
438  break;
439  }
440  cmsgtype = v_i32(v2);
441  value_free(v2);
442 
443  value_free(v);
444 
445  if (cmsglen > 0) {
446  /* Now read the data buf */
447  ibuf = malloc(cmsglen - typesize + 1);
448  if (!target_read_addr(target,control + i + typesize,
449  cmsglen - typesize,ibuf)) {
450  nrc += Lsnprintf("{ .cmsg_len = %"PRIuNUM", .cmsg_level = %d, .cmsg_type = %d, .cmsg_data = ? }",
451  cmsglen,cmsglevel,cmsgtype);
452  }
453  else {
454  /* Assume it's unprintable */
455  ibuf2 = malloc((cmsglen - typesize) * 2 + 1);
456  for (j = 0; j < (cmsglen - typesize); ++j) {
457  sprintf((char *)(ibuf2 + j * 2),"%.2hhx",ibuf[j]);
458  }
459  ibuf2[(cmsglen - typesize) * 2] = '\0';
460 
461  nrc += Lsnprintf("{ .cmsg_len = %"PRIuNUM", .cmsg_level = %d, .cmsg_type = %d, .cmsg_data = 0h%s }",
462  cmsglen,cmsglevel,cmsgtype,ibuf2);
463 
464  free(ibuf2);
465  }
466  free(ibuf);
467  }
468  else {
469  /* With a 0-length cmsglen, we can't continue. */
470  nrc += Lsnprintf("{ .cmsg_len = %"PRIuNUM", .cmsg_level = %d, .cmsg_type = %d, .cmsg_data = ? }",
471  cmsglen,cmsglevel,cmsgtype);
472  break;
473  }
474 
475  i += cmsglen;
476  }
477  nrc += Lsnprintf(" ]");
478  }
479  }
480  else {
481  v = target_load_value_member(target,NULL,value,"msg_control",NULL,0);
482  if (!v)
483  control = 0x0;
484  else {
485  control = v_addr(v);
486  value_free(v);
487  }
488  nrc += Lsnprintf(", .msg_control = %"PRIxADDR,control);
489  }
490 
491  if (controllen_noload)
492  nrc += Lsnprintf(", .msg_controllen = ?");
493  else
494  nrc += Lsnprintf(", .msg_controllen = %"PRIiNUM,controllen);
495 
496  v = target_load_value_member(target,NULL,value,"msg_flags",NULL,0);
497  if (!v)
498  nrc += Lsnprintf(", .msg_flags = ?");
499  else {
500  nrc += Lsnprintf(", .msg_flags = %d",v_i32(v));
501  value_free(v);
502  }
503 
504  nrc += Lsnprintf(" }");
505 
506  return nrc;
507 }
508 
510  struct os_linux_generic_decoder_data *data;
511  struct target *target = tdb->target;
512  struct bsymbol *bs;
513 
514  data = (struct os_linux_generic_decoder_data *)calloc(1,sizeof(*data));
515 
516  data->sockaddr_type =
517  target_lookup_sym(target,"struct sockaddr",
518  NULL,NULL,SYMBOL_TYPE_FLAG_TYPE);
519  if (data->sockaddr_type)
520  data->sockaddr_ptr_type =
522  data->sockaddr_un_type =
523  target_lookup_sym(target,"struct sockaddr_un",
524  NULL,NULL,SYMBOL_TYPE_FLAG_TYPE);
525  data->sockaddr_in_type =
526  target_lookup_sym(target,"struct sockaddr_in",
527  NULL,NULL,SYMBOL_TYPE_FLAG_TYPE);
528  data->sockaddr_in6_type =
529  target_lookup_sym(target,"struct sockaddr_in6",
530  NULL,NULL,SYMBOL_TYPE_FLAG_TYPE);
531  data->msghdr_type =
532  target_lookup_sym(target,"struct msghdr",
533  NULL,NULL,SYMBOL_TYPE_FLAG_TYPE);
534  data->cmsghdr_type =
535  target_lookup_sym(target,"struct cmsghdr",
536  NULL,NULL,SYMBOL_TYPE_FLAG_TYPE);
537  data->cmsgcred_type =
538  target_lookup_sym(target,"struct cmsgcred",
539  NULL,NULL,SYMBOL_TYPE_FLAG_TYPE);
540 
541  bs = target_lookup_sym(target,"struct iovec",
542  NULL,NULL,SYMBOL_TYPE_FLAG_TYPE);
543  if (bs) {
545  bsymbol_release(bs);
546  bs = NULL;
547  }
548 
549  if (data->sockaddr_type)
552  if (data->msghdr_type)
555 
556  return data;
557 }
558 
560  void *_data) {
561  struct os_linux_generic_decoder_data *data =
562  (struct os_linux_generic_decoder_data *)_data;
563 
564  if (data) {
565  if (data->cmsgcred_type)
567  if (data->cmsghdr_type)
569  if (data->sockaddr_un_type)
571  if (data->sockaddr_in_type)
573  if (data->sockaddr_in6_type)
575  if (data->sockaddr_ptr_type)
577  if (data->sockaddr_type)
579  if (data->msghdr_type)
581  free(data);
582  }
583 
584  return 0;
585 }
586 
588  .name = "os_linux_generic_decoder_lib",
591 };
592 
594  target_decoder_lib_register(&os_linux_generic_decoder_lib);
595 }
struct value * target_load_type(struct target *target, struct symbol *type, ADDR addr, load_flags_t flags)
Definition: target.c:2653
int target_decoder_binding_add(struct target_decoder_binding *tdb, struct bsymbol *bsymbol, target_decoder_t dfn)
Definition: target.c:6338
struct target * target
Definition: target_api.h:1971
static uint64_t unsigned int i
struct bsymbol * target_lookup_sym(struct target *target, const char *name, const char *delim, char *srcfile, symbol_type_flag_t ftype)
Definition: target.c:2199
#define Lsnprintf(...)
int64_t num_t
Definition: common.h:87
int os_linux_sockaddr_snprintf(struct target *target, void *_data, struct value *value, char *buf, int buflen)
#define verror(format,...)
Definition: log.h:30
unsigned char * target_read_addr(struct target *target, ADDR addr, unsigned long length, unsigned char *buf)
Definition: target_api.c:1053
int bufsiz
Definition: target_api.h:3297
struct target_decoder_lib os_linux_generic_decoder_lib
symbol_type_t type
Definition: dwdebug_priv.h:833
void free(void *ptr)
Definition: debugserver.c:207
#define PRIiNUM
Definition: common.h:90
REFCNT bsymbol_release(struct bsymbol *bsymbol)
Definition: symbol.c:90
char * buf
Definition: target_api.h:3298
void value_free(struct value *value)
Definition: value.c:282
struct value * target_load_value_member(struct target *target, struct target_location_ctxt *tlctxt, struct value *old_value, const char *member, const char *delim, load_flags_t flags)
Definition: target.c:2942
REFCNT symbol_release(struct symbol *symbol)
Definition: debug.c:4318
ADDR v_addr(struct value *v)
Definition: value.c:429
struct value * value_reload_as_type(struct value *value, struct symbol *type, int force)
Definition: value.c:224
num_t v_num(struct value *v)
Definition: value.c:396
void * calloc(size_t nmemb, size_t size)
Definition: debugserver.c:200
unsigned int symbol_type_full_bytesize(struct symbol *type)
Definition: debug.c:4267
struct symbol * symbol_type_skip_ptrs(struct symbol *type)
Definition: debug.c:4209
int os_linux_iovec_snprintf(struct target *target, void *_data, struct value *value, char *buf, int buflen)
struct symbol * bsymbol_get_symbol(struct bsymbol *bsymbol)
Definition: symbol.c:66
uint32_t ADDR
Definition: common.h:64
struct symbol * type
Definition: target_api.h:3287
int32_t v_i32(struct value *v)
Definition: value.c:394
#define PRIxADDR
Definition: common.h:67
struct symbol * target_create_synthetic_type_pointer(struct target *target, struct symbol *type)
Definition: symbol.c:27
void * malloc(size_t size)
Definition: debugserver.c:214
uint64_t unum_t
Definition: common.h:88
void os_linux_generic_decoder_lib_register(void)
uint32_t v_u32(struct value *v)
Definition: value.c:390
int os_linux_generic_decoder_lib_unbind(struct target_decoder_binding *tdb, void *_data)
int target_decoder_lib_register(struct target_decoder_lib *lib)
Definition: target.c:6195
unum_t v_unum(struct value *v)
Definition: value.c:411
ADDR value_addr(struct value *value)
Definition: value.c:302
#define PRIuNUM
Definition: common.h:89
int os_linux_msghdr_snprintf(struct target *target, void *_data, struct value *value, char *buf, int buflen)
void * os_linux_generic_decoder_lib_bind(struct target_decoder_binding *tdb)