blob: e922d4b950baad0dcd5ec9b79a2107da09b985ab [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 Wienand9a2ad352006-02-20 22:44:45 +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);
17static 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
Ian Wienand9a2ad352006-02-20 22:44:45 +010020display_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
Ian Wienand9a2ad352006-02-20 22:44:45 +010024 switch(at) {
25 case ARGTYPE_VOID:
26 return 0;
27 case ARGTYPE_INT:
28 return fprintf(output, "%d", (int)gimme_arg(type, proc, arg_num));
29 case ARGTYPE_UINT:
30 return fprintf(output, "%u", (unsigned)gimme_arg(type, proc, arg_num));
31 case ARGTYPE_LONG:
32 if (proc->mask_32bit)
33 return fprintf(output, "%d", (int)gimme_arg(type, proc, arg_num));
34 return fprintf(output, "%ld", gimme_arg(type, proc, arg_num));
35 case ARGTYPE_ULONG:
36 if (proc->mask_32bit)
37 return fprintf(output, "%u", (unsigned)gimme_arg(type, proc, arg_num));
38 return fprintf(output, "%lu", (unsigned long)gimme_arg(type, proc, arg_num));
39 case ARGTYPE_OCTAL:
40 return fprintf(output, "0%o", (unsigned)gimme_arg(type, proc, arg_num));
41 case ARGTYPE_CHAR:
42 tmp = fprintf(output, "'");
43 tmp += display_char((int)gimme_arg(type, proc, arg_num));
44 tmp += fprintf(output, "'");
45 return tmp;
46 case ARGTYPE_ADDR:
47 arg = gimme_arg(type, proc, arg_num);
48 if (!arg) {
49 return fprintf(output, "NULL");
50 } else {
51 return fprintf(output, "%p", (void *)arg);
52 }
53 case ARGTYPE_FORMAT:
54 return display_format(type, proc, arg_num);
55 case ARGTYPE_STRING:
56 return display_string(type, proc, arg_num);
57 case ARGTYPE_STRING0:
58 return display_stringN(0, type, proc, arg_num);
59 case ARGTYPE_STRING1:
60 return display_stringN(1, type, proc, arg_num);
61 case ARGTYPE_STRING2:
62 return display_stringN(2, type, proc, arg_num);
63 case ARGTYPE_STRING3:
64 return display_stringN(3, type, proc, arg_num);
65 case ARGTYPE_STRING4:
66 return display_stringN(4, type, proc, arg_num);
67 case ARGTYPE_STRING5:
68 return display_stringN(5, type, proc, arg_num);
69 case ARGTYPE_UNKNOWN:
70 default:
71 return display_unknown(type, proc, arg_num);
Juan Cespedes5e01f651998-03-08 22:31:44 +010072 }
73 return fprintf(output, "?");
74}
75
Ian Wienand9a2ad352006-02-20 22:44:45 +010076static int
77display_char(int what) {
78 switch(what) {
79 case -1: return fprintf(output, "EOF");
80 case '\r': return fprintf(output, "\\r");
81 case '\n': return fprintf(output, "\\n");
82 case '\t': return fprintf(output, "\\t");
83 case '\b': return fprintf(output, "\\b");
84 case '\\': return fprintf(output, "\\\\");
85 default:
86 if ((what<32) || (what>126)) {
87 return fprintf(output, "\\%03o", (unsigned char)what);
88 } else {
89 return fprintf(output, "%c", what);
90 }
Juan Cespedes5e01f651998-03-08 22:31:44 +010091 }
92}
93
Ian Wienand9a2ad352006-02-20 22:44:45 +010094static int string_maxlength=INT_MAX;
Juan Cespedes2c4a8cb1998-03-11 23:33:18 +010095
96#define MIN(a,b) (((a)<(b)) ? (a) : (b))
97
Ian Wienand9a2ad352006-02-20 22:44:45 +010098static int
99display_string(enum tof type, struct process * proc, int arg_num) {
100 void * addr;
101 unsigned char * str1;
Juan Cespedes5e01f651998-03-08 22:31:44 +0100102 int i;
Ian Wienand9a2ad352006-02-20 22:44:45 +0100103 int len=0;
Juan Cespedes5e01f651998-03-08 22:31:44 +0100104
105 addr = (void *)gimme_arg(type, proc, arg_num);
106 if (!addr) {
107 return fprintf(output, "NULL");
108 }
109
Ian Wienand9a2ad352006-02-20 22:44:45 +0100110 str1 = malloc(MIN(opt_s,string_maxlength)+3);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100111 if (!str1) {
112 return fprintf(output, "???");
113 }
Ian Wienand9a2ad352006-02-20 22:44:45 +0100114 umovestr(proc, addr, MIN(opt_s,string_maxlength)+1, str1);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100115 len = fprintf(output, "\"");
Ian Wienand9a2ad352006-02-20 22:44:45 +0100116 for(i=0; i<MIN(opt_s,string_maxlength); i++) {
Juan Cespedes5e01f651998-03-08 22:31:44 +0100117 if (str1[i]) {
118 len += display_char(str1[i]);
119 } else {
120 break;
121 }
122 }
123 len += fprintf(output, "\"");
Juan Cespedes2c4a8cb1998-03-11 23:33:18 +0100124 if (str1[i] && (opt_s <= string_maxlength)) {
Juan Cespedes5e01f651998-03-08 22:31:44 +0100125 len += fprintf(output, "...");
126 }
127 free(str1);
128 return len;
129}
130
Juan Cespedes8cc1b9d2002-03-01 19:54:23 +0100131static int
Ian Wienand9a2ad352006-02-20 22:44:45 +0100132display_stringN(int arg2, enum tof type, struct process * proc, int arg_num) {
Juan Cespedes2c4a8cb1998-03-11 23:33:18 +0100133 int a;
134
Ian Wienand9a2ad352006-02-20 22:44:45 +0100135 string_maxlength=gimme_arg(type, proc, arg2-1);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100136 a = display_string(type, proc, arg_num);
Ian Wienand9a2ad352006-02-20 22:44:45 +0100137 string_maxlength=INT_MAX;
Juan Cespedes5e01f651998-03-08 22:31:44 +0100138 return a;
139}
140
Ian Wienand9a2ad352006-02-20 22:44:45 +0100141static int
142display_unknown(enum tof type, struct process * proc, int arg_num) {
Juan Cespedes5e01f651998-03-08 22:31:44 +0100143 long tmp;
144
145 tmp = gimme_arg(type, proc, arg_num);
146
Ian Wienand9a2ad352006-02-20 22:44:45 +0100147 if (proc->mask_32bit) {
148 if ((int)tmp<1000000 && (int)tmp>-1000000)
149 return fprintf(output, "%d", (int)tmp);
150 else
151 return fprintf(output, "%p", (void *)tmp);
152 } else if (tmp<1000000 && tmp>-1000000) {
Juan Cespedes5e01f651998-03-08 22:31:44 +0100153 return fprintf(output, "%ld", tmp);
154 } else {
Juan Cespedesefe85f02004-04-04 01:31:38 +0200155 return fprintf(output, "%p", (void *)tmp);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100156 }
157}
Juan Cespedesac3db291998-04-25 14:31:58 +0200158
Ian Wienand9a2ad352006-02-20 22:44:45 +0100159static int
160display_format(enum tof type, struct process * proc, int arg_num) {
161 void * addr;
162 unsigned char * str1;
Juan Cespedesac3db291998-04-25 14:31:58 +0200163 int i;
Ian Wienand9a2ad352006-02-20 22:44:45 +0100164 int len=0;
Juan Cespedesac3db291998-04-25 14:31:58 +0200165
166 addr = (void *)gimme_arg(type, proc, arg_num);
167 if (!addr) {
168 return fprintf(output, "NULL");
169 }
170
Ian Wienand9a2ad352006-02-20 22:44:45 +0100171 str1 = malloc(MIN(opt_s,string_maxlength)+3);
Juan Cespedesac3db291998-04-25 14:31:58 +0200172 if (!str1) {
173 return fprintf(output, "???");
174 }
Ian Wienand9a2ad352006-02-20 22:44:45 +0100175 umovestr(proc, addr, MIN(opt_s,string_maxlength)+1, str1);
Juan Cespedesac3db291998-04-25 14:31:58 +0200176 len = fprintf(output, "\"");
Ian Wienand9a2ad352006-02-20 22:44:45 +0100177 for(i=0; len<MIN(opt_s,string_maxlength)+1; i++) {
Juan Cespedesac3db291998-04-25 14:31:58 +0200178 if (str1[i]) {
179 len += display_char(str1[i]);
180 } else {
181 break;
182 }
183 }
184 len += fprintf(output, "\"");
185 if (str1[i] && (opt_s <= string_maxlength)) {
186 len += fprintf(output, "...");
187 }
Ian Wienand9a2ad352006-02-20 22:44:45 +0100188 for(i=0; str1[i]; i++) {
189 if (str1[i]=='%') {
Juan Cespedesd914a202004-11-10 00:15:33 +0100190 int is_long = 0;
Ian Wienand9a2ad352006-02-20 22:44:45 +0100191 while(1) {
Juan Cespedes5c3fe062004-06-14 18:08:37 +0200192 unsigned char c = str1[++i];
Juan Cespedesac3db291998-04-25 14:31:58 +0200193 if (c == '%') {
194 break;
195 } else if (!c) {
196 break;
Ian Wienand9a2ad352006-02-20 22:44:45 +0100197 } else if (strchr ("lzZtj", c)) {
Juan Cespedesd914a202004-11-10 00:15:33 +0100198 is_long++;
199 if (c == 'j')
200 is_long++;
Ian Wienand3219f322006-02-16 06:00:00 +0100201 if (is_long > 1
Ian Wienand9a2ad352006-02-20 22:44:45 +0100202 && (sizeof (long) < sizeof (long long) || proc->mask_32bit)) {
Juan Cespedesd914a202004-11-10 00:15:33 +0100203 len += fprintf(output, ", ...");
Ian Wienand9a2ad352006-02-20 22:44:45 +0100204 str1[i+1]='\0';
Juan Cespedesd914a202004-11-10 00:15:33 +0100205 break;
206 }
Ian Wienand9a2ad352006-02-20 22:44:45 +0100207 } else if (c=='d' || c=='i') {
208 if (!is_long || proc->mask_32bit)
209 len += fprintf(output, ", %d", (int)gimme_arg(type, proc, ++arg_num));
Juan Cespedesd914a202004-11-10 00:15:33 +0100210 else
Ian Wienand9a2ad352006-02-20 22:44:45 +0100211 len += fprintf(output, ", %ld", gimme_arg(type, proc, ++arg_num));
Juan Cespedesac3db291998-04-25 14:31:58 +0200212 break;
Ian Wienand9a2ad352006-02-20 22:44:45 +0100213 } else if (c=='u') {
214 if (!is_long || proc->mask_32bit)
215 len += fprintf(output, ", %u", (int)gimme_arg(type, proc, ++arg_num));
Juan Cespedesd914a202004-11-10 00:15:33 +0100216 else
Ian Wienand9a2ad352006-02-20 22:44:45 +0100217 len += fprintf(output, ", %lu", gimme_arg(type, proc, ++arg_num));
Juan Cespedesac3db291998-04-25 14:31:58 +0200218 break;
Ian Wienand9a2ad352006-02-20 22:44:45 +0100219 } else if (c=='o') {
220 if (!is_long || proc->mask_32bit)
221 len += fprintf(output, ", 0%o", (int)gimme_arg(type, proc, ++arg_num));
Juan Cespedesd914a202004-11-10 00:15:33 +0100222 else
Ian Wienand9a2ad352006-02-20 22:44:45 +0100223 len += fprintf(output, ", 0%lo", gimme_arg(type, proc, ++arg_num));
Juan Cespedesac3db291998-04-25 14:31:58 +0200224 break;
Ian Wienand9a2ad352006-02-20 22:44:45 +0100225 } else if (c=='x' || c=='X') {
226 if (!is_long || proc->mask_32bit)
227 len += fprintf(output, ", %#x", (int)gimme_arg(type, proc, ++arg_num));
Juan Cespedesd914a202004-11-10 00:15:33 +0100228 else
Ian Wienand9a2ad352006-02-20 22:44:45 +0100229 len += fprintf(output, ", %#lx", gimme_arg(type, proc, ++arg_num));
Juan Cespedesd914a202004-11-10 00:15:33 +0100230 break;
231 } else if (strchr("eEfFgGaACS", c)
Ian Wienand9a2ad352006-02-20 22:44:45 +0100232 || (is_long && (c=='c' || c=='s'))) {
Juan Cespedesd914a202004-11-10 00:15:33 +0100233 len += fprintf(output, ", ...");
Ian Wienand9a2ad352006-02-20 22:44:45 +0100234 str1[i+1]='\0';
Juan Cespedesac3db291998-04-25 14:31:58 +0200235 break;
Ian Wienand9a2ad352006-02-20 22:44:45 +0100236 } else if (c=='c') {
Juan Cespedesac3db291998-04-25 14:31:58 +0200237 len += fprintf(output, ", '");
Ian Wienand9a2ad352006-02-20 22:44:45 +0100238 len += display_char((int)gimme_arg(type, proc, ++arg_num));
Juan Cespedesac3db291998-04-25 14:31:58 +0200239 len += fprintf(output, "'");
240 break;
Ian Wienand9a2ad352006-02-20 22:44:45 +0100241 } else if (c=='s') {
Juan Cespedesac3db291998-04-25 14:31:58 +0200242 len += fprintf(output, ", ");
Ian Wienand9a2ad352006-02-20 22:44:45 +0100243 len += display_string(type, proc, ++arg_num);
Juan Cespedesac3db291998-04-25 14:31:58 +0200244 break;
Ian Wienand9a2ad352006-02-20 22:44:45 +0100245 } else if (c=='p' || c=='n') {
246 len += fprintf(output, ", %p", (void *)gimme_arg(type, proc, ++arg_num));
Juan Cespedesac3db291998-04-25 14:31:58 +0200247 break;
Ian Wienand9a2ad352006-02-20 22:44:45 +0100248 } else if (c=='*') {
249 len += fprintf(output, ", %d", (int)gimme_arg(type, proc, ++arg_num));
Juan Cespedesac3db291998-04-25 14:31:58 +0200250 }
251 }
252 }
253 }
254 free(str1);
255 return len;
256}