blob: b8dc0f6f95284a1171c03735cfefe73204878151 [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 Wienand3219f322006-02-16 06:00:00 +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 Wienand3219f322006-02-16 06:00:00 +010021display_arg(enum tof type, struct process *proc, int arg_num,
22 const struct complete_arg_type *at)
23{
Juan Cespedes5e01f651998-03-08 22:31:44 +010024 int tmp;
25 long arg;
26
Ian Wienand3219f322006-02-16 06:00:00 +010027 if (!at)
Richard Kettlewell5df62692006-02-16 01:10:00 +010028 return display_unknown(type, proc, arg_num);
Ian Wienand3219f322006-02-16 06:00:00 +010029 switch (at->at) {
30 case ARGTYPE_VOID:
31 return 0;
32 case ARGTYPE_INT:
33 return fprintf(output, "%d",
34 (int)gimme_arg(type, proc, arg_num));
35 case ARGTYPE_UINT:
36 return fprintf(output, "%u",
37 (unsigned)gimme_arg(type, proc, arg_num));
38 case ARGTYPE_LONG:
39 return fprintf(output, "%ld", gimme_arg(type, proc, arg_num));
40 case ARGTYPE_ULONG:
41 return fprintf(output, "%lu",
42 (unsigned long)gimme_arg(type, proc, arg_num));
43 case ARGTYPE_OCTAL:
44 return fprintf(output, "0%o",
45 (unsigned)gimme_arg(type, proc, arg_num));
46 case ARGTYPE_CHAR:
47 tmp = fprintf(output, "'");
48 tmp += display_char((int)gimme_arg(type, proc, arg_num));
49 tmp += fprintf(output, "'");
50 return tmp;
51 case ARGTYPE_ADDR:
52 arg = gimme_arg(type, proc, arg_num);
53 if (!arg) {
54 return fprintf(output, "NULL");
55 } else {
56 return fprintf(output, "%p", (void *)arg);
57 }
58 case ARGTYPE_FORMAT:
59 return display_format(type, proc, arg_num);
60 case ARGTYPE_STRING:
61 return display_string(type, proc, arg_num);
62 case ARGTYPE_STRINGN:
63 return display_stringN(at->argno, type, proc, arg_num);
64 case ARGTYPE_UNKNOWN:
65 default:
66 return display_unknown(type, proc, arg_num);
Juan Cespedes5e01f651998-03-08 22:31:44 +010067 }
68 return fprintf(output, "?");
69}
70
Ian Wienand3219f322006-02-16 06:00:00 +010071static int display_char(int what)
72{
73 switch (what) {
74 case -1:
75 return fprintf(output, "EOF");
76 case '\r':
77 return fprintf(output, "\\r");
78 case '\n':
79 return fprintf(output, "\\n");
80 case '\t':
81 return fprintf(output, "\\t");
82 case '\b':
83 return fprintf(output, "\\b");
84 case '\\':
85 return fprintf(output, "\\\\");
86 default:
87 if ((what < 32) || (what > 126)) {
88 return fprintf(output, "\\%03o", (unsigned char)what);
89 } else {
90 return fprintf(output, "%c", what);
91 }
Juan Cespedes5e01f651998-03-08 22:31:44 +010092 }
93}
94
Ian Wienand3219f322006-02-16 06:00:00 +010095static int string_maxlength = INT_MAX;
Juan Cespedes2c4a8cb1998-03-11 23:33:18 +010096
97#define MIN(a,b) (((a)<(b)) ? (a) : (b))
98
Ian Wienand3219f322006-02-16 06:00:00 +010099static int display_string(enum tof type, struct process *proc, int arg_num)
100{
101 void *addr;
102 unsigned char *str1;
Juan Cespedes5e01f651998-03-08 22:31:44 +0100103 int i;
Ian Wienand3219f322006-02-16 06:00:00 +0100104 int len = 0;
Juan Cespedes5e01f651998-03-08 22:31:44 +0100105
106 addr = (void *)gimme_arg(type, proc, arg_num);
107 if (!addr) {
108 return fprintf(output, "NULL");
109 }
110
Ian Wienand3219f322006-02-16 06:00:00 +0100111 str1 = malloc(MIN(opt_s, string_maxlength) + 3);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100112 if (!str1) {
113 return fprintf(output, "???");
114 }
Ian Wienand3219f322006-02-16 06:00:00 +0100115 umovestr(proc, addr, MIN(opt_s, string_maxlength) + 1, str1);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100116 len = fprintf(output, "\"");
Ian Wienand3219f322006-02-16 06:00:00 +0100117 for (i = 0; i < MIN(opt_s, string_maxlength); i++) {
Juan Cespedes5e01f651998-03-08 22:31:44 +0100118 if (str1[i]) {
119 len += display_char(str1[i]);
120 } else {
121 break;
122 }
123 }
124 len += fprintf(output, "\"");
Juan Cespedes2c4a8cb1998-03-11 23:33:18 +0100125 if (str1[i] && (opt_s <= string_maxlength)) {
Juan Cespedes5e01f651998-03-08 22:31:44 +0100126 len += fprintf(output, "...");
127 }
128 free(str1);
129 return len;
130}
131
Juan Cespedes8cc1b9d2002-03-01 19:54:23 +0100132static int
Ian Wienand3219f322006-02-16 06:00:00 +0100133display_stringN(int arg2, enum tof type, struct process *proc, int arg_num)
134{
Juan Cespedes2c4a8cb1998-03-11 23:33:18 +0100135 int a;
136
Ian Wienand3219f322006-02-16 06:00:00 +0100137 string_maxlength = gimme_arg(type, proc, arg2 - 1);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100138 a = display_string(type, proc, arg_num);
Ian Wienand3219f322006-02-16 06:00:00 +0100139 string_maxlength = INT_MAX;
Juan Cespedes5e01f651998-03-08 22:31:44 +0100140 return a;
141}
142
Ian Wienand3219f322006-02-16 06:00:00 +0100143static int display_unknown(enum tof type, struct process *proc, int arg_num)
144{
Juan Cespedes5e01f651998-03-08 22:31:44 +0100145 long tmp;
146
147 tmp = gimme_arg(type, proc, arg_num);
148
Ian Wienand3219f322006-02-16 06:00:00 +0100149 if (tmp < 1000000 && tmp > -1000000) {
Juan Cespedes5e01f651998-03-08 22:31:44 +0100150 return fprintf(output, "%ld", tmp);
151 } else {
Juan Cespedesefe85f02004-04-04 01:31:38 +0200152 return fprintf(output, "%p", (void *)tmp);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100153 }
154}
Juan Cespedesac3db291998-04-25 14:31:58 +0200155
Ian Wienand3219f322006-02-16 06:00:00 +0100156static int display_format(enum tof type, struct process *proc, int arg_num)
157{
158 void *addr;
159 unsigned char *str1;
Juan Cespedesac3db291998-04-25 14:31:58 +0200160 int i;
Ian Wienand3219f322006-02-16 06:00:00 +0100161 int len = 0;
Juan Cespedesac3db291998-04-25 14:31:58 +0200162
163 addr = (void *)gimme_arg(type, proc, arg_num);
164 if (!addr) {
165 return fprintf(output, "NULL");
166 }
167
Ian Wienand3219f322006-02-16 06:00:00 +0100168 str1 = malloc(MIN(opt_s, string_maxlength) + 3);
Juan Cespedesac3db291998-04-25 14:31:58 +0200169 if (!str1) {
170 return fprintf(output, "???");
171 }
Ian Wienand3219f322006-02-16 06:00:00 +0100172 umovestr(proc, addr, MIN(opt_s, string_maxlength) + 1, str1);
Juan Cespedesac3db291998-04-25 14:31:58 +0200173 len = fprintf(output, "\"");
Ian Wienand3219f322006-02-16 06:00:00 +0100174 for (i = 0; len < MIN(opt_s, string_maxlength) + 1; i++) {
Juan Cespedesac3db291998-04-25 14:31:58 +0200175 if (str1[i]) {
176 len += display_char(str1[i]);
177 } else {
178 break;
179 }
180 }
181 len += fprintf(output, "\"");
182 if (str1[i] && (opt_s <= string_maxlength)) {
183 len += fprintf(output, "...");
184 }
Ian Wienand3219f322006-02-16 06:00:00 +0100185 for (i = 0; str1[i]; i++) {
186 if (str1[i] == '%') {
Juan Cespedesd914a202004-11-10 00:15:33 +0100187 int is_long = 0;
Ian Wienand3219f322006-02-16 06:00:00 +0100188 while (1) {
Juan Cespedes5c3fe062004-06-14 18:08:37 +0200189 unsigned char c = str1[++i];
Juan Cespedesac3db291998-04-25 14:31:58 +0200190 if (c == '%') {
191 break;
192 } else if (!c) {
193 break;
Ian Wienand3219f322006-02-16 06:00:00 +0100194 } else if (strchr("lzZtj", c)) {
Juan Cespedesd914a202004-11-10 00:15:33 +0100195 is_long++;
196 if (c == 'j')
197 is_long++;
Ian Wienand3219f322006-02-16 06:00:00 +0100198 if (is_long > 1
199 && sizeof(long) <
200 sizeof(long long)) {
Juan Cespedesd914a202004-11-10 00:15:33 +0100201 len += fprintf(output, ", ...");
Ian Wienand3219f322006-02-16 06:00:00 +0100202 str1[i + 1] = '\0';
Juan Cespedesd914a202004-11-10 00:15:33 +0100203 break;
204 }
Ian Wienand3219f322006-02-16 06:00:00 +0100205 } else if (c == 'd' || c == 'i') {
Juan Cespedesd914a202004-11-10 00:15:33 +0100206 if (is_long)
Ian Wienand3219f322006-02-16 06:00:00 +0100207 len +=
208 fprintf(output, ", %d",
209 (int)gimme_arg(type,
210 proc,
211 ++arg_num));
Juan Cespedesd914a202004-11-10 00:15:33 +0100212 else
Ian Wienand3219f322006-02-16 06:00:00 +0100213 len +=
214 fprintf(output, ", %ld",
215 gimme_arg(type,
216 proc,
217 ++arg_num));
Juan Cespedesac3db291998-04-25 14:31:58 +0200218 break;
Ian Wienand3219f322006-02-16 06:00:00 +0100219 } else if (c == 'u') {
Juan Cespedesd914a202004-11-10 00:15:33 +0100220 if (is_long)
Ian Wienand3219f322006-02-16 06:00:00 +0100221 len +=
222 fprintf(output, ", %u",
223 (int)gimme_arg(type,
224 proc,
225 ++arg_num));
Juan Cespedesd914a202004-11-10 00:15:33 +0100226 else
Ian Wienand3219f322006-02-16 06:00:00 +0100227 len +=
228 fprintf(output, ", %lu",
229 gimme_arg(type,
230 proc,
231 ++arg_num));
Juan Cespedesac3db291998-04-25 14:31:58 +0200232 break;
Ian Wienand3219f322006-02-16 06:00:00 +0100233 } else if (c == 'o') {
Juan Cespedesd914a202004-11-10 00:15:33 +0100234 if (is_long)
Ian Wienand3219f322006-02-16 06:00:00 +0100235 len +=
236 fprintf(output, ", 0%o",
237 (int)gimme_arg(type,
238 proc,
239 ++arg_num));
Juan Cespedesd914a202004-11-10 00:15:33 +0100240 else
Ian Wienand3219f322006-02-16 06:00:00 +0100241 len +=
242 fprintf(output, ", 0%lo",
243 gimme_arg(type,
244 proc,
245 ++arg_num));
Juan Cespedesac3db291998-04-25 14:31:58 +0200246 break;
Ian Wienand3219f322006-02-16 06:00:00 +0100247 } else if (c == 'x' || c == 'X') {
Juan Cespedesd914a202004-11-10 00:15:33 +0100248 if (is_long)
Ian Wienand3219f322006-02-16 06:00:00 +0100249 len +=
250 fprintf(output, ", %#x",
251 (int)gimme_arg(type,
252 proc,
253 ++arg_num));
Juan Cespedesd914a202004-11-10 00:15:33 +0100254 else
Ian Wienand3219f322006-02-16 06:00:00 +0100255 len +=
256 fprintf(output, ", %#lx",
257 gimme_arg(type,
258 proc,
259 ++arg_num));
Juan Cespedesd914a202004-11-10 00:15:33 +0100260 break;
261 } else if (strchr("eEfFgGaACS", c)
Ian Wienand3219f322006-02-16 06:00:00 +0100262 || (is_long
263 && (c == 'c' || c == 's'))) {
Juan Cespedesd914a202004-11-10 00:15:33 +0100264 len += fprintf(output, ", ...");
Ian Wienand3219f322006-02-16 06:00:00 +0100265 str1[i + 1] = '\0';
Juan Cespedesac3db291998-04-25 14:31:58 +0200266 break;
Ian Wienand3219f322006-02-16 06:00:00 +0100267 } else if (c == 'c') {
Juan Cespedesac3db291998-04-25 14:31:58 +0200268 len += fprintf(output, ", '");
Ian Wienand3219f322006-02-16 06:00:00 +0100269 len += display_char((int)
270 gimme_arg(type,
271 proc,
272 ++arg_num));
Juan Cespedesac3db291998-04-25 14:31:58 +0200273 len += fprintf(output, "'");
274 break;
Ian Wienand3219f322006-02-16 06:00:00 +0100275 } else if (c == 's') {
Juan Cespedesac3db291998-04-25 14:31:58 +0200276 len += fprintf(output, ", ");
Ian Wienand3219f322006-02-16 06:00:00 +0100277 len +=
278 display_string(type, proc,
279 ++arg_num);
Juan Cespedesac3db291998-04-25 14:31:58 +0200280 break;
Ian Wienand3219f322006-02-16 06:00:00 +0100281 } else if (c == 'p' || c == 'n') {
282 len +=
283 fprintf(output, ", %p",
284 (void *)gimme_arg(type,
285 proc,
286 ++arg_num));
Juan Cespedesac3db291998-04-25 14:31:58 +0200287 break;
Ian Wienand3219f322006-02-16 06:00:00 +0100288 } else if (c == '*') {
289 len +=
290 fprintf(output, ", %d",
291 (int)gimme_arg(type, proc,
292 ++arg_num));
Juan Cespedesac3db291998-04-25 14:31:58 +0200293 }
294 }
295 }
296 }
297 free(str1);
298 return len;
299}