blob: 1ea10fdab2e5ce26e38516fdf892336bbdfa255c [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 Cespedes2c4a8cb1998-03-11 23:33:18 +01007#include <limits.h>
Juan Cespedes5e01f651998-03-08 22:31:44 +01008
9#include "ltrace.h"
10#include "options.h"
11
Juan Cespedesac3db291998-04-25 14:31:58 +020012static int display_char(int what);
Juan Cespedes5e01f651998-03-08 22:31:44 +010013static int display_string(enum tof type, struct process * proc, int arg_num);
14static int display_stringN(int arg2, enum tof type, struct process * proc, int arg_num);
15static int display_unknown(enum tof type, struct process * proc, int arg_num);
Juan Cespedesac3db291998-04-25 14:31:58 +020016static int display_format(enum tof type, struct process * proc, int arg_num);
Juan Cespedes5e01f651998-03-08 22:31:44 +010017
Juan Cespedese3eb9aa1999-04-03 03:21:52 +020018int display_arg(enum tof type, struct process * proc, int arg_num, enum arg_type at)
Juan Cespedes5e01f651998-03-08 22:31:44 +010019{
20 int tmp;
21 long arg;
22
Juan Cespedese3eb9aa1999-04-03 03:21:52 +020023 switch(at) {
24 case ARGTYPE_VOID:
Juan Cespedes5e01f651998-03-08 22:31:44 +010025 return 0;
Juan Cespedese3eb9aa1999-04-03 03:21:52 +020026 case ARGTYPE_INT:
Juan Cespedes5e01f651998-03-08 22:31:44 +010027 return fprintf(output, "%d", (int)gimme_arg(type, proc, arg_num));
Juan Cespedese3eb9aa1999-04-03 03:21:52 +020028 case ARGTYPE_UINT:
Juan Cespedes5e01f651998-03-08 22:31:44 +010029 return fprintf(output, "%u", (unsigned)gimme_arg(type, proc, arg_num));
Juan Cespedese3eb9aa1999-04-03 03:21:52 +020030 case ARGTYPE_OCTAL:
Juan Cespedes5e01f651998-03-08 22:31:44 +010031 return fprintf(output, "0%o", (unsigned)gimme_arg(type, proc, arg_num));
Juan Cespedese3eb9aa1999-04-03 03:21:52 +020032 case ARGTYPE_CHAR:
Juan Cespedes5e01f651998-03-08 22:31:44 +010033 tmp = fprintf(output, "'");
34 tmp += display_char((int)gimme_arg(type, proc, arg_num));
35 tmp += fprintf(output, "'");
36 return tmp;
Juan Cespedese3eb9aa1999-04-03 03:21:52 +020037 case ARGTYPE_ADDR:
Juan Cespedes5e01f651998-03-08 22:31:44 +010038 arg = gimme_arg(type, proc, arg_num);
39 if (!arg) {
40 return fprintf(output, "NULL");
41 } else {
42 return fprintf(output, "0x%08x", (unsigned)arg);
43 }
Juan Cespedese3eb9aa1999-04-03 03:21:52 +020044 case ARGTYPE_FORMAT:
Juan Cespedesac3db291998-04-25 14:31:58 +020045 return display_format(type, proc, arg_num);
Juan Cespedese3eb9aa1999-04-03 03:21:52 +020046 case ARGTYPE_STRING:
Juan Cespedes5e01f651998-03-08 22:31:44 +010047 return display_string(type, proc, arg_num);
Juan Cespedese3eb9aa1999-04-03 03:21:52 +020048 case ARGTYPE_STRING0:
Juan Cespedes5e01f651998-03-08 22:31:44 +010049 return display_stringN(0, type, proc, arg_num);
Juan Cespedese3eb9aa1999-04-03 03:21:52 +020050 case ARGTYPE_STRING1:
Juan Cespedes5e01f651998-03-08 22:31:44 +010051 return display_stringN(1, type, proc, arg_num);
Juan Cespedese3eb9aa1999-04-03 03:21:52 +020052 case ARGTYPE_STRING2:
Juan Cespedes5e01f651998-03-08 22:31:44 +010053 return display_stringN(2, type, proc, arg_num);
Juan Cespedese3eb9aa1999-04-03 03:21:52 +020054 case ARGTYPE_STRING3:
Juan Cespedes5e01f651998-03-08 22:31:44 +010055 return display_stringN(3, type, proc, arg_num);
Juan Cespedese3eb9aa1999-04-03 03:21:52 +020056 case ARGTYPE_UNKNOWN:
Juan Cespedes5e01f651998-03-08 22:31:44 +010057 default:
58 return display_unknown(type, proc, arg_num);
59 }
60 return fprintf(output, "?");
61}
62
Juan Cespedesac3db291998-04-25 14:31:58 +020063static int display_char(int what)
Juan Cespedes5e01f651998-03-08 22:31:44 +010064{
65 switch(what) {
66 case -1: return fprintf(output, "EOF");
67 case '\r': return fprintf(output, "\\r");
68 case '\n': return fprintf(output, "\\n");
69 case '\t': return fprintf(output, "\\t");
Juan Cespedes81690ef1998-03-13 19:31:29 +010070 case '\b': return fprintf(output, "\\b");
Juan Cespedese3eb9aa1999-04-03 03:21:52 +020071 case '\\': return fprintf(output, "\\\\");
Juan Cespedes5e01f651998-03-08 22:31:44 +010072 default:
73 if ((what<32) || (what>126)) {
Juan Cespedes81690ef1998-03-13 19:31:29 +010074 return fprintf(output, "\\%03o", (unsigned char)what);
Juan Cespedes5e01f651998-03-08 22:31:44 +010075 } else {
76 return fprintf(output, "%c", what);
77 }
78 }
79}
80
Juan Cespedes2c4a8cb1998-03-11 23:33:18 +010081static int string_maxlength=INT_MAX;
82
83#define MIN(a,b) (((a)<(b)) ? (a) : (b))
84
Juan Cespedes5e01f651998-03-08 22:31:44 +010085static int display_string(enum tof type, struct process * proc, int arg_num)
86{
87 void * addr;
88 char * str1;
89 int i;
90 int len=0;
91
92 addr = (void *)gimme_arg(type, proc, arg_num);
93 if (!addr) {
94 return fprintf(output, "NULL");
95 }
96
Juan Cespedes2c4a8cb1998-03-11 23:33:18 +010097 str1 = malloc(MIN(opt_s,string_maxlength)+3);
Juan Cespedes5e01f651998-03-08 22:31:44 +010098 if (!str1) {
99 return fprintf(output, "???");
100 }
Juan Cespedes2c4a8cb1998-03-11 23:33:18 +0100101 umovestr(proc, addr, MIN(opt_s,string_maxlength)+1, str1);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100102 len = fprintf(output, "\"");
Juan Cespedes370c8e61998-09-06 14:29:46 +0200103 for(i=0; i<MIN(opt_s,string_maxlength); i++) {
Juan Cespedes5e01f651998-03-08 22:31:44 +0100104 if (str1[i]) {
105 len += display_char(str1[i]);
106 } else {
107 break;
108 }
109 }
110 len += fprintf(output, "\"");
Juan Cespedes2c4a8cb1998-03-11 23:33:18 +0100111 if (str1[i] && (opt_s <= string_maxlength)) {
Juan Cespedes5e01f651998-03-08 22:31:44 +0100112 len += fprintf(output, "...");
113 }
114 free(str1);
115 return len;
116}
117
Juan Cespedes5e01f651998-03-08 22:31:44 +0100118static int display_stringN(int arg2, enum tof type, struct process * proc, int arg_num)
119{
Juan Cespedes2c4a8cb1998-03-11 23:33:18 +0100120 int a;
121
122 string_maxlength=gimme_arg(type, proc, arg2-1);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100123 a = display_string(type, proc, arg_num);
Juan Cespedes2c4a8cb1998-03-11 23:33:18 +0100124 string_maxlength=INT_MAX;
Juan Cespedes5e01f651998-03-08 22:31:44 +0100125 return a;
126}
127
128static int display_unknown(enum tof type, struct process * proc, int arg_num)
129{
130 long tmp;
131
132 tmp = gimme_arg(type, proc, arg_num);
133
134 if (tmp<1000000 && tmp>-1000000) {
135 return fprintf(output, "%ld", tmp);
136 } else {
137 return fprintf(output, "0x%08lx", tmp);
138 }
139}
Juan Cespedesac3db291998-04-25 14:31:58 +0200140
141static int display_format(enum tof type, struct process * proc, int arg_num)
142{
143 void * addr;
144 char * str1;
145 int i;
146 int len=0;
147
148 addr = (void *)gimme_arg(type, proc, arg_num);
149 if (!addr) {
150 return fprintf(output, "NULL");
151 }
152
153 str1 = malloc(MIN(opt_s,string_maxlength)+3);
154 if (!str1) {
155 return fprintf(output, "???");
156 }
157 umovestr(proc, addr, MIN(opt_s,string_maxlength)+1, str1);
158 len = fprintf(output, "\"");
159 for(i=0; len<MIN(opt_s,string_maxlength)+1; i++) {
160 if (str1[i]) {
161 len += display_char(str1[i]);
162 } else {
163 break;
164 }
165 }
166 len += fprintf(output, "\"");
167 if (str1[i] && (opt_s <= string_maxlength)) {
168 len += fprintf(output, "...");
169 }
170 for(i=0; str1[i]; i++) {
171 if (str1[i]=='%') {
172 while(1) {
173 char c = str1[++i];
174 if (c == '%') {
175 break;
176 } else if (!c) {
177 break;
178 } else if ((c=='d') || (c=='i')) {
179 len += fprintf(output, ", %d", (int)gimme_arg(type, proc, ++arg_num));
180 break;
181 } else if (c=='u') {
182 len += fprintf(output, ", %u", (int)gimme_arg(type, proc, ++arg_num));
183 break;
184 } else if (c=='o') {
185 len += fprintf(output, ", 0%o", (int)gimme_arg(type, proc, ++arg_num));
186 break;
187 } else if ((c=='x') || (c=='X')) {
188 len += fprintf(output, ", 0x%x", (int)gimme_arg(type, proc, ++arg_num));
189 break;
190 } else if (c=='c') {
191 len += fprintf(output, ", '");
192 len += display_char((int)gimme_arg(type, proc, ++arg_num));
193 len += fprintf(output, "'");
194 break;
195 } else if (c=='s') {
196 len += fprintf(output, ", ");
197 len += display_string(type, proc, ++arg_num);
198 break;
199 } else if ((c=='e') || (c=='E') || (c=='f') || (c=='g')) {
200 len += fprintf(output, ", ...");
201 str1[i+1]='\0';
202 break;
203 } else if (c=='*') {
204 len += fprintf(output, ", %d", (int)gimme_arg(type, proc, ++arg_num));
205 }
206 }
207 }
208 }
209 free(str1);
210 return len;
211}