blob: 87fd084af0ccf0a55c5e5f00c28c1b2ebf72102f [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);
Juan Cespedes5e01f651998-03-08 22:31:44 +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, int arg_num);
16static int display_unknown(enum tof type, struct process * proc, int arg_num);
Juan Cespedesac3db291998-04-25 14:31:58 +020017static int display_format(enum tof type, struct process * proc, int arg_num);
Juan Cespedes5e01f651998-03-08 22:31:44 +010018
Juan Cespedes8cc1b9d2002-03-01 19:54:23 +010019int
20display_arg(enum tof type, struct process * proc, int arg_num, enum arg_type at) {
Juan Cespedes5e01f651998-03-08 22:31:44 +010021 int tmp;
22 long arg;
23
Juan Cespedese3eb9aa1999-04-03 03:21:52 +020024 switch(at) {
25 case ARGTYPE_VOID:
Juan Cespedes5e01f651998-03-08 22:31:44 +010026 return 0;
Juan Cespedese3eb9aa1999-04-03 03:21:52 +020027 case ARGTYPE_INT:
Juan Cespedes5e01f651998-03-08 22:31:44 +010028 return fprintf(output, "%d", (int)gimme_arg(type, proc, arg_num));
Juan Cespedese3eb9aa1999-04-03 03:21:52 +020029 case ARGTYPE_UINT:
Juan Cespedes5e01f651998-03-08 22:31:44 +010030 return fprintf(output, "%u", (unsigned)gimme_arg(type, proc, arg_num));
Juan Cespedesd914a202004-11-10 00:15:33 +010031 case ARGTYPE_LONG:
32 return fprintf(output, "%ld", gimme_arg(type, proc, arg_num));
33 case ARGTYPE_ULONG:
34 return fprintf(output, "%lu", (unsigned long)gimme_arg(type, proc, arg_num));
Juan Cespedese3eb9aa1999-04-03 03:21:52 +020035 case ARGTYPE_OCTAL:
Juan Cespedes5e01f651998-03-08 22:31:44 +010036 return fprintf(output, "0%o", (unsigned)gimme_arg(type, proc, arg_num));
Juan Cespedese3eb9aa1999-04-03 03:21:52 +020037 case ARGTYPE_CHAR:
Juan Cespedes5e01f651998-03-08 22:31:44 +010038 tmp = fprintf(output, "'");
39 tmp += display_char((int)gimme_arg(type, proc, arg_num));
40 tmp += fprintf(output, "'");
41 return tmp;
Juan Cespedese3eb9aa1999-04-03 03:21:52 +020042 case ARGTYPE_ADDR:
Juan Cespedes5e01f651998-03-08 22:31:44 +010043 arg = gimme_arg(type, proc, arg_num);
44 if (!arg) {
45 return fprintf(output, "NULL");
46 } else {
Juan Cespedes5c3fe062004-06-14 18:08:37 +020047 return fprintf(output, "%p", (void *)arg);
Juan Cespedes5e01f651998-03-08 22:31:44 +010048 }
Juan Cespedese3eb9aa1999-04-03 03:21:52 +020049 case ARGTYPE_FORMAT:
Juan Cespedesac3db291998-04-25 14:31:58 +020050 return display_format(type, proc, arg_num);
Juan Cespedese3eb9aa1999-04-03 03:21:52 +020051 case ARGTYPE_STRING:
Juan Cespedes5e01f651998-03-08 22:31:44 +010052 return display_string(type, proc, arg_num);
Juan Cespedese3eb9aa1999-04-03 03:21:52 +020053 case ARGTYPE_STRING0:
Juan Cespedes5e01f651998-03-08 22:31:44 +010054 return display_stringN(0, type, proc, arg_num);
Juan Cespedese3eb9aa1999-04-03 03:21:52 +020055 case ARGTYPE_STRING1:
Juan Cespedes5e01f651998-03-08 22:31:44 +010056 return display_stringN(1, type, proc, arg_num);
Juan Cespedese3eb9aa1999-04-03 03:21:52 +020057 case ARGTYPE_STRING2:
Juan Cespedes5e01f651998-03-08 22:31:44 +010058 return display_stringN(2, type, proc, arg_num);
Juan Cespedese3eb9aa1999-04-03 03:21:52 +020059 case ARGTYPE_STRING3:
Juan Cespedes5e01f651998-03-08 22:31:44 +010060 return display_stringN(3, type, proc, arg_num);
Juan Cespedesd914a202004-11-10 00:15:33 +010061 case ARGTYPE_STRING4:
62 return display_stringN(4, type, proc, arg_num);
63 case ARGTYPE_STRING5:
64 return display_stringN(5, type, proc, arg_num);
Juan Cespedese3eb9aa1999-04-03 03:21:52 +020065 case ARGTYPE_UNKNOWN:
Juan Cespedes5e01f651998-03-08 22:31:44 +010066 default:
67 return display_unknown(type, proc, arg_num);
68 }
69 return fprintf(output, "?");
70}
71
Juan Cespedes8cc1b9d2002-03-01 19:54:23 +010072static int
73display_char(int what) {
Juan Cespedes5e01f651998-03-08 22:31:44 +010074 switch(what) {
75 case -1: return fprintf(output, "EOF");
76 case '\r': return fprintf(output, "\\r");
77 case '\n': return fprintf(output, "\\n");
78 case '\t': return fprintf(output, "\\t");
Juan Cespedes81690ef1998-03-13 19:31:29 +010079 case '\b': return fprintf(output, "\\b");
Juan Cespedese3eb9aa1999-04-03 03:21:52 +020080 case '\\': return fprintf(output, "\\\\");
Juan Cespedes5e01f651998-03-08 22:31:44 +010081 default:
82 if ((what<32) || (what>126)) {
Juan Cespedes81690ef1998-03-13 19:31:29 +010083 return fprintf(output, "\\%03o", (unsigned char)what);
Juan Cespedes5e01f651998-03-08 22:31:44 +010084 } else {
85 return fprintf(output, "%c", what);
86 }
87 }
88}
89
Juan Cespedes2c4a8cb1998-03-11 23:33:18 +010090static int string_maxlength=INT_MAX;
91
92#define MIN(a,b) (((a)<(b)) ? (a) : (b))
93
Juan Cespedes8cc1b9d2002-03-01 19:54:23 +010094static int
95display_string(enum tof type, struct process * proc, int arg_num) {
Juan Cespedes5e01f651998-03-08 22:31:44 +010096 void * addr;
Juan Cespedes5c3fe062004-06-14 18:08:37 +020097 unsigned char * str1;
Juan Cespedes5e01f651998-03-08 22:31:44 +010098 int i;
99 int len=0;
100
101 addr = (void *)gimme_arg(type, proc, arg_num);
102 if (!addr) {
103 return fprintf(output, "NULL");
104 }
105
Juan Cespedes2c4a8cb1998-03-11 23:33:18 +0100106 str1 = malloc(MIN(opt_s,string_maxlength)+3);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100107 if (!str1) {
108 return fprintf(output, "???");
109 }
Juan Cespedes2c4a8cb1998-03-11 23:33:18 +0100110 umovestr(proc, addr, MIN(opt_s,string_maxlength)+1, str1);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100111 len = fprintf(output, "\"");
Juan Cespedes370c8e61998-09-06 14:29:46 +0200112 for(i=0; i<MIN(opt_s,string_maxlength); i++) {
Juan Cespedes5e01f651998-03-08 22:31:44 +0100113 if (str1[i]) {
114 len += display_char(str1[i]);
115 } else {
116 break;
117 }
118 }
119 len += fprintf(output, "\"");
Juan Cespedes2c4a8cb1998-03-11 23:33:18 +0100120 if (str1[i] && (opt_s <= string_maxlength)) {
Juan Cespedes5e01f651998-03-08 22:31:44 +0100121 len += fprintf(output, "...");
122 }
123 free(str1);
124 return len;
125}
126
Juan Cespedes8cc1b9d2002-03-01 19:54:23 +0100127static int
128display_stringN(int arg2, enum tof type, struct process * proc, int arg_num) {
Juan Cespedes2c4a8cb1998-03-11 23:33:18 +0100129 int a;
130
131 string_maxlength=gimme_arg(type, proc, arg2-1);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100132 a = display_string(type, proc, arg_num);
Juan Cespedes2c4a8cb1998-03-11 23:33:18 +0100133 string_maxlength=INT_MAX;
Juan Cespedes5e01f651998-03-08 22:31:44 +0100134 return a;
135}
136
Juan Cespedes8cc1b9d2002-03-01 19:54:23 +0100137static int
138display_unknown(enum tof type, struct process * proc, int arg_num) {
Juan Cespedes5e01f651998-03-08 22:31:44 +0100139 long tmp;
140
141 tmp = gimme_arg(type, proc, arg_num);
142
143 if (tmp<1000000 && tmp>-1000000) {
144 return fprintf(output, "%ld", tmp);
145 } else {
Juan Cespedesefe85f02004-04-04 01:31:38 +0200146 return fprintf(output, "%p", (void *)tmp);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100147 }
148}
Juan Cespedesac3db291998-04-25 14:31:58 +0200149
Juan Cespedes8cc1b9d2002-03-01 19:54:23 +0100150static int
151display_format(enum tof type, struct process * proc, int arg_num) {
Juan Cespedesac3db291998-04-25 14:31:58 +0200152 void * addr;
Juan Cespedes5c3fe062004-06-14 18:08:37 +0200153 unsigned char * str1;
Juan Cespedesac3db291998-04-25 14:31:58 +0200154 int i;
155 int len=0;
156
157 addr = (void *)gimme_arg(type, proc, arg_num);
158 if (!addr) {
159 return fprintf(output, "NULL");
160 }
161
162 str1 = malloc(MIN(opt_s,string_maxlength)+3);
163 if (!str1) {
164 return fprintf(output, "???");
165 }
166 umovestr(proc, addr, MIN(opt_s,string_maxlength)+1, str1);
167 len = fprintf(output, "\"");
168 for(i=0; len<MIN(opt_s,string_maxlength)+1; i++) {
169 if (str1[i]) {
170 len += display_char(str1[i]);
171 } else {
172 break;
173 }
174 }
175 len += fprintf(output, "\"");
176 if (str1[i] && (opt_s <= string_maxlength)) {
177 len += fprintf(output, "...");
178 }
179 for(i=0; str1[i]; i++) {
180 if (str1[i]=='%') {
Juan Cespedesd914a202004-11-10 00:15:33 +0100181 int is_long = 0;
Juan Cespedesac3db291998-04-25 14:31:58 +0200182 while(1) {
Juan Cespedes5c3fe062004-06-14 18:08:37 +0200183 unsigned char c = str1[++i];
Juan Cespedesac3db291998-04-25 14:31:58 +0200184 if (c == '%') {
185 break;
186 } else if (!c) {
187 break;
Juan Cespedesd914a202004-11-10 00:15:33 +0100188 } else if (strchr ("lzZtj", c)) {
189 is_long++;
190 if (c == 'j')
191 is_long++;
192 if (is_long > 1 && sizeof (long) < sizeof (long long)) {
193 len += fprintf(output, ", ...");
194 str1[i+1]='\0';
195 break;
196 }
197 } else if (c=='d' || c=='i') {
198 if (is_long)
199 len += fprintf(output, ", %d", (int)gimme_arg(type, proc, ++arg_num));
200 else
201 len += fprintf(output, ", %ld", gimme_arg(type, proc, ++arg_num));
Juan Cespedesac3db291998-04-25 14:31:58 +0200202 break;
203 } else if (c=='u') {
Juan Cespedesd914a202004-11-10 00:15:33 +0100204 if (is_long)
205 len += fprintf(output, ", %u", (int)gimme_arg(type, proc, ++arg_num));
206 else
207 len += fprintf(output, ", %lu", gimme_arg(type, proc, ++arg_num));
Juan Cespedesac3db291998-04-25 14:31:58 +0200208 break;
209 } else if (c=='o') {
Juan Cespedesd914a202004-11-10 00:15:33 +0100210 if (is_long)
211 len += fprintf(output, ", 0%o", (int)gimme_arg(type, proc, ++arg_num));
212 else
213 len += fprintf(output, ", 0%lo", gimme_arg(type, proc, ++arg_num));
Juan Cespedesac3db291998-04-25 14:31:58 +0200214 break;
Juan Cespedesd914a202004-11-10 00:15:33 +0100215 } else if (c=='x' || c=='X') {
216 if (is_long)
217 len += fprintf(output, ", %#x", (int)gimme_arg(type, proc, ++arg_num));
218 else
219 len += fprintf(output, ", %#lx", gimme_arg(type, proc, ++arg_num));
220 break;
221 } else if (strchr("eEfFgGaACS", c)
222 || (is_long && (c=='c' || c=='s'))) {
223 len += fprintf(output, ", ...");
224 str1[i+1]='\0';
Juan Cespedesac3db291998-04-25 14:31:58 +0200225 break;
226 } else if (c=='c') {
227 len += fprintf(output, ", '");
228 len += display_char((int)gimme_arg(type, proc, ++arg_num));
229 len += fprintf(output, "'");
230 break;
231 } else if (c=='s') {
232 len += fprintf(output, ", ");
233 len += display_string(type, proc, ++arg_num);
234 break;
Juan Cespedesd914a202004-11-10 00:15:33 +0100235 } else if (c=='p' || c=='n') {
236 len += fprintf(output, ", %p", (void *)gimme_arg(type, proc, ++arg_num));
Juan Cespedesac3db291998-04-25 14:31:58 +0200237 break;
238 } else if (c=='*') {
239 len += fprintf(output, ", %d", (int)gimme_arg(type, proc, ++arg_num));
240 }
241 }
242 }
243 }
244 free(str1);
245 return len;
246}