1 /* 2 * This file is part of ltrace. 3 * Copyright (C) 2011,2012,2013 Petr Machata, Red Hat Inc. 4 * Copyright (C) 1998,2004,2007,2008,2009 Juan Cespedes 5 * Copyright (C) 2006 Steve Fink 6 * Copyright (C) 2006 Ian Wienand 7 * 8 * This program is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU General Public License as 10 * published by the Free Software Foundation; either version 2 of the 11 * License, or (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, but 14 * WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 * General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 21 * 02110-1301 USA 22 */ 23 24 #include <assert.h> 25 #include <stdint.h> 26 #include <stdlib.h> 27 #include <string.h> 28 29 #include "printf.h" 30 #include "type.h" 31 #include "value.h" 32 #include "expr.h" 33 #include "zero.h" 34 #include "param.h" 35 #include "lens_default.h" 36 37 struct param_enum { 38 struct value array; 39 int percent; 40 size_t *future_length; 41 char *format; 42 char const *ptr; 43 char const *end; 44 size_t width; 45 }; 46 47 static struct param_enum * 48 param_printf_init(struct value *cb_args, size_t nargs, 49 struct value_dict *arguments) 50 { 51 assert(nargs == 1); 52 53 struct process *proc = cb_args[0].inferior; 54 assert(proc != NULL); 55 56 /* We expect a pointer to array. */ 57 if (cb_args->type->type != ARGTYPE_POINTER 58 || cb_args->type->u.ptr_info.info->type != ARGTYPE_ARRAY) 59 return NULL; 60 61 /* The element type should be either character (for narrow 62 * strings) or an integral type (for wide strings). */ 63 struct arg_type_info *et 64 = cb_args->type->u.ptr_info.info->u.array_info.elt_type; 65 switch (et->type) { 66 case ARGTYPE_CHAR: 67 case ARGTYPE_SHORT: 68 case ARGTYPE_USHORT: 69 case ARGTYPE_INT: 70 case ARGTYPE_UINT: 71 case ARGTYPE_LONG: 72 case ARGTYPE_ULONG: 73 break; 74 default: 75 return NULL; 76 } 77 78 struct param_enum *self = malloc(sizeof(*self)); 79 if (self == NULL) { 80 fail: 81 free(self); 82 return NULL; 83 } 84 self->width = type_sizeof(proc, et); 85 if (self->width == (size_t) -1) 86 goto fail; 87 88 if (value_init_deref(&self->array, cb_args) < 0) 89 goto fail; 90 assert(self->array.type->type == ARGTYPE_ARRAY); 91 92 self->format = (char *)value_get_data(&self->array, arguments); 93 if (self->format == NULL) { 94 value_destroy(&self->array); 95 goto fail; 96 } 97 98 size_t size = value_size(&self->array, arguments); 99 if (size == (size_t)-1) { 100 value_destroy(&self->array); 101 goto fail; 102 } 103 104 self->percent = 0; 105 self->ptr = self->format; 106 self->end = self->format + size; 107 self->future_length = NULL; 108 return self; 109 } 110 111 static void 112 drop_future_length(struct param_enum *self) 113 { 114 if (self->future_length != NULL) { 115 free(self->future_length); 116 self->future_length = NULL; 117 } 118 } 119 120 static int 121 form_next_param(struct param_enum *self, 122 enum arg_type format_type, enum arg_type elt_type, 123 unsigned hlf, unsigned lng, char *len_buf, size_t len_buf_len, 124 struct arg_type_info *infop) 125 { 126 /* XXX note: Some types are wrong because we lack 127 ARGTYPE_LONGLONG, ARGTYPE_UCHAR and ARGTYPE_SCHAR. */ 128 assert(lng <= 2); 129 assert(hlf <= 2); 130 static enum arg_type ints[] = 131 { ARGTYPE_CHAR, ARGTYPE_SHORT, ARGTYPE_INT, 132 ARGTYPE_LONG, ARGTYPE_ULONG }; 133 static enum arg_type uints[] = 134 { ARGTYPE_CHAR, ARGTYPE_USHORT, ARGTYPE_UINT, 135 ARGTYPE_ULONG, ARGTYPE_ULONG }; 136 137 struct arg_type_info *elt_info = NULL; 138 if (format_type == ARGTYPE_ARRAY || format_type == ARGTYPE_POINTER) 139 elt_info = type_get_simple(elt_type); 140 else if (format_type == ARGTYPE_INT) 141 format_type = ints[2 + lng - hlf]; 142 else if (format_type == ARGTYPE_UINT) 143 format_type = uints[2 + lng - hlf]; 144 145 146 if (format_type == ARGTYPE_ARRAY) { 147 struct arg_type_info *array = malloc(sizeof(*array)); 148 if (array == NULL) 149 return -1; 150 151 struct expr_node *node = NULL; 152 int own_node; 153 if (len_buf_len != 0 154 || self->future_length != NULL) { 155 struct tmp { 156 struct expr_node node; 157 struct arg_type_info type; 158 }; 159 struct tmp *len = malloc(sizeof(*len)); 160 if (len == NULL) { 161 fail: 162 free(len); 163 free(array); 164 return -1; 165 } 166 167 len->type = *type_get_simple(ARGTYPE_LONG); 168 169 long l; 170 if (self->future_length != NULL) { 171 l = *self->future_length; 172 drop_future_length(self); 173 } else { 174 l = atol(len_buf); 175 } 176 177 expr_init_const_word(&len->node, l, &len->type, 0); 178 179 node = build_zero_w_arg(&len->node, 1); 180 if (node == NULL) 181 goto fail; 182 own_node = 1; 183 184 } else { 185 node = expr_node_zero(); 186 own_node = 0; 187 } 188 assert(node != NULL); 189 190 type_init_array(array, elt_info, 0, node, own_node); 191 type_init_pointer(infop, array, 1); 192 193 } else if (format_type == ARGTYPE_POINTER) { 194 type_init_pointer(infop, elt_info, 0); 195 196 } else { 197 *infop = *type_get_simple(format_type); 198 } 199 200 return 0; 201 } 202 203 static int 204 param_printf_next(struct param_enum *self, struct arg_type_info *infop, 205 int *insert_stop) 206 { 207 unsigned hlf = 0; 208 unsigned lng = 0; 209 enum arg_type format_type = ARGTYPE_VOID; 210 enum arg_type elt_type = ARGTYPE_VOID; 211 char len_buf[25] = {}; 212 size_t len_buf_len = 0; 213 struct lens *lens = NULL; 214 215 for (; self->ptr < self->end; self->ptr += self->width) { 216 union { 217 uint8_t u8; 218 uint16_t u16; 219 uint32_t u32; 220 uint64_t u64; 221 char buf[0]; 222 } u; 223 memcpy(u.buf, self->ptr, self->width); 224 switch (self->width) { 225 case 1: u.u64 = u.u8; break; 226 case 2: u.u64 = u.u16; break; 227 case 4: u.u64 = u.u32; break; 228 } 229 uint64_t c = u.u64; 230 231 if (!self->percent) { 232 if (c == '%') 233 self->percent = 1; 234 continue; 235 } 236 237 switch (c) { 238 case '#': case ' ': case '-': 239 case '+': case 'I': case '\'': 240 /* These are only important for formatting, 241 * not for interpreting the type. */ 242 continue; 243 244 case '*': 245 /* Length parameter given in the next 246 * argument. */ 247 if (self->future_length == NULL) 248 /* This should really be an assert, 249 * but we can't just fail on invalid 250 * format string. */ 251 self->future_length 252 = malloc(sizeof(*self->future_length)); 253 254 if (self->future_length != NULL) { 255 self->ptr += self->width; 256 format_type = ARGTYPE_INT; 257 break; 258 } 259 260 case '0': 261 case '1': case '2': case '3': 262 case '4': case '5': case '6': 263 case '7': case '8': case '9': 264 /* Field length likewise, but we need to parse 265 * this to attach the appropriate string 266 * length expression. */ 267 if (len_buf_len < sizeof(len_buf) - 1) 268 len_buf[len_buf_len++] = c; 269 continue; 270 271 case 'h': 272 if (hlf < 2) 273 hlf++; 274 continue; 275 276 case 'l': 277 if (lng < 2) 278 lng++; 279 continue; 280 281 case 'q': 282 lng = 2; 283 continue; 284 285 case 'L': /* long double */ 286 lng = 1; 287 continue; 288 289 case 'j': /* intmax_t */ 290 /* XXX ABI should know */ 291 lng = 2; 292 continue; 293 294 case 't': /* ptrdiff_t */ 295 case 'Z': case 'z': /* size_t */ 296 lng = 1; /* XXX ABI should tell */ 297 continue; 298 299 case 'd': 300 case 'i': 301 format_type = ARGTYPE_INT; 302 self->percent = 0; 303 break; 304 305 case 'o': 306 lens = &octal_lens; 307 goto uint; 308 309 case 'x': case 'X': 310 lens = &hex_lens; 311 /* Fall through. */ 312 case 'u': 313 uint: 314 format_type = ARGTYPE_UINT; 315 self->percent = 0; 316 break; 317 318 case 'e': case 'E': 319 case 'f': case 'F': 320 case 'g': case 'G': 321 case 'a': case 'A': 322 format_type = ARGTYPE_DOUBLE; 323 self->percent = 0; 324 break; 325 326 case 'C': /* like "lc" */ 327 if (lng == 0) 328 lng++; 329 case 'c': 330 /* XXX "lc" means wchar_t string. */ 331 format_type = ARGTYPE_CHAR; 332 self->percent = 0; 333 break; 334 335 case 'S': /* like "ls" */ 336 if (lng == 0) 337 lng++; 338 case 's': 339 format_type = ARGTYPE_ARRAY; 340 elt_type = lng == 0 ? ARGTYPE_CHAR : ARGTYPE_INT; 341 self->percent = 0; 342 lens = &string_lens; 343 break; 344 345 case 'p': 346 case 'n': /* int* where to store no. of printed chars. */ 347 format_type = ARGTYPE_POINTER; 348 elt_type = ARGTYPE_VOID; 349 self->percent = 0; 350 break; 351 352 case 'm': /* (glibc) print argument of errno */ 353 case '%': 354 lng = 0; 355 hlf = 0; 356 self->percent = 0; 357 continue; 358 359 default: 360 continue; 361 } 362 363 /* If we got here, the type must have been set. */ 364 assert(format_type != ARGTYPE_VOID); 365 366 if (form_next_param(self, format_type, elt_type, hlf, lng, 367 len_buf, len_buf_len, infop) < 0) 368 return -1; 369 370 infop->lens = lens; 371 infop->own_lens = 0; 372 373 return 0; 374 } 375 376 *infop = *type_get_simple(ARGTYPE_VOID); 377 return 0; 378 } 379 380 static enum param_status 381 param_printf_stop(struct param_enum *self, struct value *value) 382 { 383 if (self->future_length != NULL 384 && value_extract_word(value, (long *)self->future_length, NULL) < 0) 385 drop_future_length(self); 386 387 return PPCB_CONT; 388 } 389 390 static void 391 param_printf_done(struct param_enum *context) 392 { 393 value_destroy(&context->array); 394 free(context); 395 } 396 397 void 398 param_pack_init_printf(struct param *param, struct expr_node *arg, int own_arg) 399 { 400 param_init_pack(param, PARAM_PACK_VARARGS, arg, 1, own_arg, 401 ¶m_printf_init, ¶m_printf_next, 402 ¶m_printf_stop, ¶m_printf_done); 403 } 404