blob: 083c9dceb36bf01c07758312aa12d55dd33052a7 [file] [log] [blame]
Juan Cespedesd44c6b81998-09-25 14:48:42 +02001#if HAVE_CONFIG_H
2#include "config.h"
3#endif
4
Juan Cespedes5e01f651998-03-08 22:31:44 +01005#include <stdio.h>
6#include <stdlib.h>
Juan Cespedesd914a202004-11-10 00:15:33 +01007#include <string.h>
Juan Cespedes2c4a8cb1998-03-11 23:33:18 +01008#include <limits.h>
Juan Cespedes5e01f651998-03-08 22:31:44 +01009
10#include "ltrace.h"
11#include "options.h"
12
Juan Cespedesac3db291998-04-25 14:31:58 +020013static int display_char(int what);
Ian Wienand2d45b1a2006-02-20 22:48:07 +010014static int display_string(enum tof type, struct process *proc, int arg_num);
15static int display_stringN(int arg2, enum tof type, struct process *proc,
16 int arg_num);
17static int display_unknown(enum tof type, struct process *proc, int arg_num);
18static int display_format(enum tof type, struct process *proc, int arg_num);
Juan Cespedes5e01f651998-03-08 22:31:44 +010019
Juan Cespedes8cc1b9d2002-03-01 19:54:23 +010020int
Ian Wienand2d45b1a2006-02-20 22:48:07 +010021display_arg(enum tof type, struct process *proc, int arg_num, enum arg_type at)
22{
Juan Cespedes5e01f651998-03-08 22:31:44 +010023 int tmp;
24 long arg;
25
Ian Wienand2d45b1a2006-02-20 22:48:07 +010026 switch (at) {
27 case ARGTYPE_VOID:
28 return 0;
29 case ARGTYPE_INT:
30 return fprintf(output, "%d",
31 (int)gimme_arg(type, proc, arg_num));
32 case ARGTYPE_UINT:
33 return fprintf(output, "%u",
34 (unsigned)gimme_arg(type, proc, arg_num));
35 case ARGTYPE_LONG:
36 if (proc->mask_32bit)
37 return fprintf(output, "%d",
38 (int)gimme_arg(type, proc, arg_num));
39 return fprintf(output, "%ld", gimme_arg(type, proc, arg_num));
40 case ARGTYPE_ULONG:
41 if (proc->mask_32bit)
42 return fprintf(output, "%u",
43 (unsigned)gimme_arg(type, proc,
44 arg_num));
45 return fprintf(output, "%lu",
46 (unsigned long)gimme_arg(type, proc, arg_num));
47 case ARGTYPE_OCTAL:
48 return fprintf(output, "0%o",
49 (unsigned)gimme_arg(type, proc, arg_num));
50 case ARGTYPE_CHAR:
51 tmp = fprintf(output, "'");
52 tmp += display_char((int)gimme_arg(type, proc, arg_num));
53 tmp += fprintf(output, "'");
54 return tmp;
55 case ARGTYPE_ADDR:
56 arg = gimme_arg(type, proc, arg_num);
57 if (!arg) {
58 return fprintf(output, "NULL");
59 } else {
60 return fprintf(output, "%p", (void *)arg);
61 }
62 case ARGTYPE_FORMAT:
63 return display_format(type, proc, arg_num);
64 case ARGTYPE_STRING:
65 return display_string(type, proc, arg_num);
66 case ARGTYPE_STRING0:
67 return display_stringN(0, type, proc, arg_num);
68 case ARGTYPE_STRING1:
69 return display_stringN(1, type, proc, arg_num);
70 case ARGTYPE_STRING2:
71 return display_stringN(2, type, proc, arg_num);
72 case ARGTYPE_STRING3:
73 return display_stringN(3, type, proc, arg_num);
74 case ARGTYPE_STRING4:
75 return display_stringN(4, type, proc, arg_num);
76 case ARGTYPE_STRING5:
77 return display_stringN(5, type, proc, arg_num);
78 case ARGTYPE_UNKNOWN:
79 default:
80 return display_unknown(type, proc, arg_num);
Juan Cespedes5e01f651998-03-08 22:31:44 +010081 }
82 return fprintf(output, "?");
83}
84
Ian Wienand2d45b1a2006-02-20 22:48:07 +010085static int display_char(int what)
86{
87 switch (what) {
88 case -1:
89 return fprintf(output, "EOF");
90 case '\r':
91 return fprintf(output, "\\r");
92 case '\n':
93 return fprintf(output, "\\n");
94 case '\t':
95 return fprintf(output, "\\t");
96 case '\b':
97 return fprintf(output, "\\b");
98 case '\\':
99 return fprintf(output, "\\\\");
100 default:
101 if ((what < 32) || (what > 126)) {
102 return fprintf(output, "\\%03o", (unsigned char)what);
103 } else {
104 return fprintf(output, "%c", what);
105 }
Juan Cespedes5e01f651998-03-08 22:31:44 +0100106 }
107}
108
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100109static int string_maxlength = INT_MAX;
Juan Cespedes2c4a8cb1998-03-11 23:33:18 +0100110
111#define MIN(a,b) (((a)<(b)) ? (a) : (b))
112
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100113static int display_string(enum tof type, struct process *proc, int arg_num)
114{
115 void *addr;
116 unsigned char *str1;
Juan Cespedes5e01f651998-03-08 22:31:44 +0100117 int i;
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100118 int len = 0;
Juan Cespedes5e01f651998-03-08 22:31:44 +0100119
120 addr = (void *)gimme_arg(type, proc, arg_num);
121 if (!addr) {
122 return fprintf(output, "NULL");
123 }
124
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100125 str1 = malloc(MIN(opt_s, string_maxlength) + 3);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100126 if (!str1) {
127 return fprintf(output, "???");
128 }
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100129 umovestr(proc, addr, MIN(opt_s, string_maxlength) + 1, str1);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100130 len = fprintf(output, "\"");
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100131 for (i = 0; i < MIN(opt_s, string_maxlength); i++) {
Juan Cespedes5e01f651998-03-08 22:31:44 +0100132 if (str1[i]) {
133 len += display_char(str1[i]);
134 } else {
135 break;
136 }
137 }
138 len += fprintf(output, "\"");
Juan Cespedes2c4a8cb1998-03-11 23:33:18 +0100139 if (str1[i] && (opt_s <= string_maxlength)) {
Juan Cespedes5e01f651998-03-08 22:31:44 +0100140 len += fprintf(output, "...");
141 }
142 free(str1);
143 return len;
144}
145
Juan Cespedes8cc1b9d2002-03-01 19:54:23 +0100146static int
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100147display_stringN(int arg2, enum tof type, struct process *proc, int arg_num)
148{
Juan Cespedes2c4a8cb1998-03-11 23:33:18 +0100149 int a;
150
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100151 string_maxlength = gimme_arg(type, proc, arg2 - 1);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100152 a = display_string(type, proc, arg_num);
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100153 string_maxlength = INT_MAX;
Juan Cespedes5e01f651998-03-08 22:31:44 +0100154 return a;
155}
156
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100157static int display_unknown(enum tof type, struct process *proc, int arg_num)
158{
Juan Cespedes5e01f651998-03-08 22:31:44 +0100159 long tmp;
160
161 tmp = gimme_arg(type, proc, arg_num);
162
Ian Wienand9a2ad352006-02-20 22:44:45 +0100163 if (proc->mask_32bit) {
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100164 if ((int)tmp < 1000000 && (int)tmp > -1000000)
Ian Wienand9a2ad352006-02-20 22:44:45 +0100165 return fprintf(output, "%d", (int)tmp);
166 else
167 return fprintf(output, "%p", (void *)tmp);
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100168 } else if (tmp < 1000000 && tmp > -1000000) {
Juan Cespedes5e01f651998-03-08 22:31:44 +0100169 return fprintf(output, "%ld", tmp);
170 } else {
Juan Cespedesefe85f02004-04-04 01:31:38 +0200171 return fprintf(output, "%p", (void *)tmp);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100172 }
173}
Juan Cespedesac3db291998-04-25 14:31:58 +0200174
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100175static int display_format(enum tof type, struct process *proc, int arg_num)
176{
177 void *addr;
178 unsigned char *str1;
Juan Cespedesac3db291998-04-25 14:31:58 +0200179 int i;
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100180 int len = 0;
Juan Cespedesac3db291998-04-25 14:31:58 +0200181
182 addr = (void *)gimme_arg(type, proc, arg_num);
183 if (!addr) {
184 return fprintf(output, "NULL");
185 }
186
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100187 str1 = malloc(MIN(opt_s, string_maxlength) + 3);
Juan Cespedesac3db291998-04-25 14:31:58 +0200188 if (!str1) {
189 return fprintf(output, "???");
190 }
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100191 umovestr(proc, addr, MIN(opt_s, string_maxlength) + 1, str1);
Juan Cespedesac3db291998-04-25 14:31:58 +0200192 len = fprintf(output, "\"");
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100193 for (i = 0; len < MIN(opt_s, string_maxlength) + 1; i++) {
Juan Cespedesac3db291998-04-25 14:31:58 +0200194 if (str1[i]) {
195 len += display_char(str1[i]);
196 } else {
197 break;
198 }
199 }
200 len += fprintf(output, "\"");
201 if (str1[i] && (opt_s <= string_maxlength)) {
202 len += fprintf(output, "...");
203 }
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100204 for (i = 0; str1[i]; i++) {
205 if (str1[i] == '%') {
Juan Cespedesd914a202004-11-10 00:15:33 +0100206 int is_long = 0;
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100207 while (1) {
Juan Cespedes5c3fe062004-06-14 18:08:37 +0200208 unsigned char c = str1[++i];
Juan Cespedesac3db291998-04-25 14:31:58 +0200209 if (c == '%') {
210 break;
211 } else if (!c) {
212 break;
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100213 } else if (strchr("lzZtj", c)) {
Juan Cespedesd914a202004-11-10 00:15:33 +0100214 is_long++;
215 if (c == 'j')
216 is_long++;
Ian Wienand3219f322006-02-16 06:00:00 +0100217 if (is_long > 1
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100218 && (sizeof(long) < sizeof(long long)
219 || proc->mask_32bit)) {
Juan Cespedesd914a202004-11-10 00:15:33 +0100220 len += fprintf(output, ", ...");
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100221 str1[i + 1] = '\0';
Juan Cespedesd914a202004-11-10 00:15:33 +0100222 break;
223 }
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100224 } else if (c == 'd' || c == 'i') {
Ian Wienand9a2ad352006-02-20 22:44:45 +0100225 if (!is_long || proc->mask_32bit)
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100226 len +=
227 fprintf(output, ", %d",
228 (int)gimme_arg(type,
229 proc,
230 ++arg_num));
Juan Cespedesd914a202004-11-10 00:15:33 +0100231 else
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100232 len +=
233 fprintf(output, ", %ld",
234 gimme_arg(type,
235 proc,
236 ++arg_num));
Juan Cespedesac3db291998-04-25 14:31:58 +0200237 break;
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100238 } else if (c == 'u') {
Ian Wienand9a2ad352006-02-20 22:44:45 +0100239 if (!is_long || proc->mask_32bit)
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100240 len +=
241 fprintf(output, ", %u",
242 (int)gimme_arg(type,
243 proc,
244 ++arg_num));
Juan Cespedesd914a202004-11-10 00:15:33 +0100245 else
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100246 len +=
247 fprintf(output, ", %lu",
248 gimme_arg(type,
249 proc,
250 ++arg_num));
Juan Cespedesac3db291998-04-25 14:31:58 +0200251 break;
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100252 } else if (c == 'o') {
Ian Wienand9a2ad352006-02-20 22:44:45 +0100253 if (!is_long || proc->mask_32bit)
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100254 len +=
255 fprintf(output, ", 0%o",
256 (int)gimme_arg(type,
257 proc,
258 ++arg_num));
Juan Cespedesd914a202004-11-10 00:15:33 +0100259 else
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100260 len +=
261 fprintf(output, ", 0%lo",
262 gimme_arg(type,
263 proc,
264 ++arg_num));
Juan Cespedesac3db291998-04-25 14:31:58 +0200265 break;
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100266 } else if (c == 'x' || c == 'X') {
Ian Wienand9a2ad352006-02-20 22:44:45 +0100267 if (!is_long || proc->mask_32bit)
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100268 len +=
269 fprintf(output, ", %#x",
270 (int)gimme_arg(type,
271 proc,
272 ++arg_num));
Juan Cespedesd914a202004-11-10 00:15:33 +0100273 else
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100274 len +=
275 fprintf(output, ", %#lx",
276 gimme_arg(type,
277 proc,
278 ++arg_num));
Juan Cespedesd914a202004-11-10 00:15:33 +0100279 break;
280 } else if (strchr("eEfFgGaACS", c)
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100281 || (is_long
282 && (c == 'c' || c == 's'))) {
Juan Cespedesd914a202004-11-10 00:15:33 +0100283 len += fprintf(output, ", ...");
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100284 str1[i + 1] = '\0';
Juan Cespedesac3db291998-04-25 14:31:58 +0200285 break;
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100286 } else if (c == 'c') {
Juan Cespedesac3db291998-04-25 14:31:58 +0200287 len += fprintf(output, ", '");
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100288 len +=
289 display_char((int)
290 gimme_arg(type, proc,
291 ++arg_num));
Juan Cespedesac3db291998-04-25 14:31:58 +0200292 len += fprintf(output, "'");
293 break;
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100294 } else if (c == 's') {
Juan Cespedesac3db291998-04-25 14:31:58 +0200295 len += fprintf(output, ", ");
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100296 len +=
297 display_string(type, proc,
298 ++arg_num);
Juan Cespedesac3db291998-04-25 14:31:58 +0200299 break;
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100300 } else if (c == 'p' || c == 'n') {
301 len +=
302 fprintf(output, ", %p",
303 (void *)gimme_arg(type,
304 proc,
305 ++arg_num));
Juan Cespedesac3db291998-04-25 14:31:58 +0200306 break;
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100307 } else if (c == '*') {
308 len +=
309 fprintf(output, ", %d",
310 (int)gimme_arg(type, proc,
311 ++arg_num));
Juan Cespedesac3db291998-04-25 14:31:58 +0200312 }
313 }
314 }
315 }
316 free(str1);
317 return len;
318}