blob: 26692283c9974470387abf618e315203664f3e93 [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);
Steve Fink6a48a6d2006-08-07 04:29:06 +020014static int display_string(enum tof type, struct process *proc,
15 int arg_num, arg_type_info *info,
16 size_t maxlen);
Ian Wienand2d45b1a2006-02-20 22:48:07 +010017static 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
Steve Fink6a48a6d2006-08-07 04:29:06 +020020static int string_maxlength = INT_MAX;
21
22static long get_length(enum tof type, struct process *proc, int len_spec)
23{
24 if (len_spec > 0)
25 return len_spec;
26 return gimme_arg(type, proc, -len_spec - 1);
27}
28
Juan Cespedes8cc1b9d2002-03-01 19:54:23 +010029int
Steve Fink6a48a6d2006-08-07 04:29:06 +020030display_arg(enum tof type, struct process *proc,
31 int arg_num, arg_type_info *info)
Ian Wienand2d45b1a2006-02-20 22:48:07 +010032{
Juan Cespedes5e01f651998-03-08 22:31:44 +010033 int tmp;
34 long arg;
35
Steve Fink6a48a6d2006-08-07 04:29:06 +020036 switch (info->type) {
Ian Wienand2d45b1a2006-02-20 22:48:07 +010037 case ARGTYPE_VOID:
38 return 0;
Steve Fink6b175832006-08-07 04:37:33 +020039 case ARGTYPE_IGNORE:
40 return 0; /* Empty gap between commas */
Ian Wienand2d45b1a2006-02-20 22:48:07 +010041 case ARGTYPE_INT:
42 return fprintf(output, "%d",
43 (int)gimme_arg(type, proc, arg_num));
44 case ARGTYPE_UINT:
45 return fprintf(output, "%u",
46 (unsigned)gimme_arg(type, proc, arg_num));
47 case ARGTYPE_LONG:
48 if (proc->mask_32bit)
49 return fprintf(output, "%d",
50 (int)gimme_arg(type, proc, arg_num));
51 return fprintf(output, "%ld", gimme_arg(type, proc, arg_num));
52 case ARGTYPE_ULONG:
53 if (proc->mask_32bit)
54 return fprintf(output, "%u",
55 (unsigned)gimme_arg(type, proc,
56 arg_num));
57 return fprintf(output, "%lu",
58 (unsigned long)gimme_arg(type, proc, arg_num));
59 case ARGTYPE_OCTAL:
60 return fprintf(output, "0%o",
61 (unsigned)gimme_arg(type, proc, arg_num));
62 case ARGTYPE_CHAR:
63 tmp = fprintf(output, "'");
64 tmp += display_char((int)gimme_arg(type, proc, arg_num));
65 tmp += fprintf(output, "'");
66 return tmp;
67 case ARGTYPE_ADDR:
68 arg = gimme_arg(type, proc, arg_num);
69 if (!arg) {
70 return fprintf(output, "NULL");
71 } else {
72 return fprintf(output, "%p", (void *)arg);
73 }
74 case ARGTYPE_FORMAT:
75 return display_format(type, proc, arg_num);
76 case ARGTYPE_STRING:
Steve Fink6a48a6d2006-08-07 04:29:06 +020077 return display_string(type, proc, arg_num, info,
78 string_maxlength);
79 case ARGTYPE_STRING_N:
80 return display_string(type, proc, arg_num, info,
81 get_length(type, proc,
82 info->u.string_n_info.size_spec));
Ian Wienand2d45b1a2006-02-20 22:48:07 +010083 case ARGTYPE_UNKNOWN:
84 default:
85 return display_unknown(type, proc, arg_num);
Juan Cespedes5e01f651998-03-08 22:31:44 +010086 }
87 return fprintf(output, "?");
88}
89
Ian Wienand2d45b1a2006-02-20 22:48:07 +010090static int display_char(int what)
91{
92 switch (what) {
93 case -1:
94 return fprintf(output, "EOF");
95 case '\r':
96 return fprintf(output, "\\r");
97 case '\n':
98 return fprintf(output, "\\n");
99 case '\t':
100 return fprintf(output, "\\t");
101 case '\b':
102 return fprintf(output, "\\b");
103 case '\\':
104 return fprintf(output, "\\\\");
105 default:
106 if ((what < 32) || (what > 126)) {
107 return fprintf(output, "\\%03o", (unsigned char)what);
108 } else {
109 return fprintf(output, "%c", what);
110 }
Juan Cespedes5e01f651998-03-08 22:31:44 +0100111 }
112}
113
Juan Cespedes2c4a8cb1998-03-11 23:33:18 +0100114#define MIN(a,b) (((a)<(b)) ? (a) : (b))
115
Steve Fink6a48a6d2006-08-07 04:29:06 +0200116static int display_string(enum tof type, struct process *proc,
117 int arg_num, arg_type_info *info, size_t maxlength)
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100118{
119 void *addr;
120 unsigned char *str1;
Juan Cespedes5e01f651998-03-08 22:31:44 +0100121 int i;
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100122 int len = 0;
Juan Cespedes5e01f651998-03-08 22:31:44 +0100123
124 addr = (void *)gimme_arg(type, proc, arg_num);
125 if (!addr) {
126 return fprintf(output, "NULL");
127 }
128
Steve Fink6a48a6d2006-08-07 04:29:06 +0200129 str1 = malloc(MIN(opt_s, maxlength) + 3);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100130 if (!str1) {
131 return fprintf(output, "???");
132 }
Steve Fink6a48a6d2006-08-07 04:29:06 +0200133 umovestr(proc, addr, MIN(opt_s, maxlength) + 1, str1);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100134 len = fprintf(output, "\"");
Steve Fink6a48a6d2006-08-07 04:29:06 +0200135 for (i = 0; i < MIN(opt_s, maxlength); i++) {
Juan Cespedes5e01f651998-03-08 22:31:44 +0100136 if (str1[i]) {
137 len += display_char(str1[i]);
138 } else {
139 break;
140 }
141 }
142 len += fprintf(output, "\"");
Steve Fink6a48a6d2006-08-07 04:29:06 +0200143 if (str1[i] && (opt_s <= maxlength)) {
Juan Cespedes5e01f651998-03-08 22:31:44 +0100144 len += fprintf(output, "...");
145 }
146 free(str1);
147 return len;
148}
149
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100150static int display_unknown(enum tof type, struct process *proc, int arg_num)
151{
Juan Cespedes5e01f651998-03-08 22:31:44 +0100152 long tmp;
153
154 tmp = gimme_arg(type, proc, arg_num);
155
Ian Wienand9a2ad352006-02-20 22:44:45 +0100156 if (proc->mask_32bit) {
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100157 if ((int)tmp < 1000000 && (int)tmp > -1000000)
Ian Wienand9a2ad352006-02-20 22:44:45 +0100158 return fprintf(output, "%d", (int)tmp);
159 else
160 return fprintf(output, "%p", (void *)tmp);
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100161 } else if (tmp < 1000000 && tmp > -1000000) {
Juan Cespedes5e01f651998-03-08 22:31:44 +0100162 return fprintf(output, "%ld", tmp);
163 } else {
Juan Cespedesefe85f02004-04-04 01:31:38 +0200164 return fprintf(output, "%p", (void *)tmp);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100165 }
166}
Juan Cespedesac3db291998-04-25 14:31:58 +0200167
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100168static int display_format(enum tof type, struct process *proc, int arg_num)
169{
170 void *addr;
171 unsigned char *str1;
Juan Cespedesac3db291998-04-25 14:31:58 +0200172 int i;
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100173 int len = 0;
Juan Cespedesac3db291998-04-25 14:31:58 +0200174
175 addr = (void *)gimme_arg(type, proc, arg_num);
176 if (!addr) {
177 return fprintf(output, "NULL");
178 }
179
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100180 str1 = malloc(MIN(opt_s, string_maxlength) + 3);
Juan Cespedesac3db291998-04-25 14:31:58 +0200181 if (!str1) {
182 return fprintf(output, "???");
183 }
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100184 umovestr(proc, addr, MIN(opt_s, string_maxlength) + 1, str1);
Juan Cespedesac3db291998-04-25 14:31:58 +0200185 len = fprintf(output, "\"");
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100186 for (i = 0; len < MIN(opt_s, string_maxlength) + 1; i++) {
Juan Cespedesac3db291998-04-25 14:31:58 +0200187 if (str1[i]) {
188 len += display_char(str1[i]);
189 } else {
190 break;
191 }
192 }
193 len += fprintf(output, "\"");
194 if (str1[i] && (opt_s <= string_maxlength)) {
195 len += fprintf(output, "...");
196 }
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100197 for (i = 0; str1[i]; i++) {
198 if (str1[i] == '%') {
Juan Cespedesd914a202004-11-10 00:15:33 +0100199 int is_long = 0;
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100200 while (1) {
Juan Cespedes5c3fe062004-06-14 18:08:37 +0200201 unsigned char c = str1[++i];
Juan Cespedesac3db291998-04-25 14:31:58 +0200202 if (c == '%') {
203 break;
204 } else if (!c) {
205 break;
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100206 } else if (strchr("lzZtj", c)) {
Juan Cespedesd914a202004-11-10 00:15:33 +0100207 is_long++;
208 if (c == 'j')
209 is_long++;
Ian Wienand3219f322006-02-16 06:00:00 +0100210 if (is_long > 1
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100211 && (sizeof(long) < sizeof(long long)
212 || proc->mask_32bit)) {
Juan Cespedesd914a202004-11-10 00:15:33 +0100213 len += fprintf(output, ", ...");
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100214 str1[i + 1] = '\0';
Juan Cespedesd914a202004-11-10 00:15:33 +0100215 break;
216 }
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100217 } else if (c == 'd' || c == 'i') {
Ian Wienand9a2ad352006-02-20 22:44:45 +0100218 if (!is_long || proc->mask_32bit)
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100219 len +=
220 fprintf(output, ", %d",
221 (int)gimme_arg(type,
222 proc,
223 ++arg_num));
Juan Cespedesd914a202004-11-10 00:15:33 +0100224 else
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100225 len +=
226 fprintf(output, ", %ld",
227 gimme_arg(type,
228 proc,
229 ++arg_num));
Juan Cespedesac3db291998-04-25 14:31:58 +0200230 break;
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100231 } else if (c == 'u') {
Ian Wienand9a2ad352006-02-20 22:44:45 +0100232 if (!is_long || proc->mask_32bit)
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100233 len +=
234 fprintf(output, ", %u",
235 (int)gimme_arg(type,
236 proc,
237 ++arg_num));
Juan Cespedesd914a202004-11-10 00:15:33 +0100238 else
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100239 len +=
240 fprintf(output, ", %lu",
241 gimme_arg(type,
242 proc,
243 ++arg_num));
Juan Cespedesac3db291998-04-25 14:31:58 +0200244 break;
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100245 } else if (c == 'o') {
Ian Wienand9a2ad352006-02-20 22:44:45 +0100246 if (!is_long || proc->mask_32bit)
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100247 len +=
248 fprintf(output, ", 0%o",
249 (int)gimme_arg(type,
250 proc,
251 ++arg_num));
Juan Cespedesd914a202004-11-10 00:15:33 +0100252 else
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100253 len +=
254 fprintf(output, ", 0%lo",
255 gimme_arg(type,
256 proc,
257 ++arg_num));
Juan Cespedesac3db291998-04-25 14:31:58 +0200258 break;
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100259 } else if (c == 'x' || c == 'X') {
Ian Wienand9a2ad352006-02-20 22:44:45 +0100260 if (!is_long || proc->mask_32bit)
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100261 len +=
262 fprintf(output, ", %#x",
263 (int)gimme_arg(type,
264 proc,
265 ++arg_num));
Juan Cespedesd914a202004-11-10 00:15:33 +0100266 else
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100267 len +=
268 fprintf(output, ", %#lx",
269 gimme_arg(type,
270 proc,
271 ++arg_num));
Juan Cespedesd914a202004-11-10 00:15:33 +0100272 break;
273 } else if (strchr("eEfFgGaACS", c)
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100274 || (is_long
275 && (c == 'c' || c == 's'))) {
Juan Cespedesd914a202004-11-10 00:15:33 +0100276 len += fprintf(output, ", ...");
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100277 str1[i + 1] = '\0';
Juan Cespedesac3db291998-04-25 14:31:58 +0200278 break;
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100279 } else if (c == 'c') {
Juan Cespedesac3db291998-04-25 14:31:58 +0200280 len += fprintf(output, ", '");
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100281 len +=
282 display_char((int)
283 gimme_arg(type, proc,
284 ++arg_num));
Juan Cespedesac3db291998-04-25 14:31:58 +0200285 len += fprintf(output, "'");
286 break;
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100287 } else if (c == 's') {
Steve Fink6a48a6d2006-08-07 04:29:06 +0200288 arg_type_info *info =
289 lookup_singleton(ARGTYPE_STRING);
Juan Cespedesac3db291998-04-25 14:31:58 +0200290 len += fprintf(output, ", ");
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100291 len +=
292 display_string(type, proc,
Steve Fink6a48a6d2006-08-07 04:29:06 +0200293 ++arg_num, info,
294 string_maxlength);
Juan Cespedesac3db291998-04-25 14:31:58 +0200295 break;
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100296 } else if (c == 'p' || c == 'n') {
297 len +=
298 fprintf(output, ", %p",
299 (void *)gimme_arg(type,
300 proc,
301 ++arg_num));
Juan Cespedesac3db291998-04-25 14:31:58 +0200302 break;
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100303 } else if (c == '*') {
304 len +=
305 fprintf(output, ", %d",
306 (int)gimme_arg(type, proc,
307 ++arg_num));
Juan Cespedesac3db291998-04-25 14:31:58 +0200308 }
309 }
310 }
311 }
312 free(str1);
313 return len;
314}