Warning: Attempt to read property "date" on null in /usr/local/www/websvn.planix.org/blame.php on line 247

Warning: Attempt to read property "msg" on null in /usr/local/www/websvn.planix.org/blame.php on line 247
WebSVN – planix.SVN – Blame – /os/branches/feature_fixcpp/sys/lib/acid/truss – Rev 2

Subversion Repositories planix.SVN

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
// poor emulation of SVR5 truss command - traces system calls
2
 
3
include("/sys/lib/acid/syscall");
4
 
5
_stoprunning = 0;
6
 
7
defn stopped(pid) {
8
	local l;
9
	local pc;
10
	pc = *PC;
11
	if notes then {
12
		if (notes[0]!="sys: breakpoint") then
13
		{
14
			print(pid,": ",trapreason(),"\t");
15
			print(fmt(pc,97),"\t",fmt(pc,105),"\n");
16
			print("Notes pending:\n");
17
			l = notes;
18
			while l do
19
			{
20
				print("\t",head l,"\n");
21
				l = tail l;
22
			}
23
			_stoprunning = 1;
24
		}
25
	}
26
}
27
 
28
defn _addressof(pattern) {
29
	local s, l;
30
	l = symbols;
31
	pattern = "^\\$*"+pattern+"$";
32
	while l do
33
	{
34
		s = head l;
35
		if regexp(pattern, s[0]) && ((s[1] == 'T') || (s[1] == 'L')) then
36
			return s[2];
37
		l = tail l;
38
	}
39
	return 0;
40
}
41
 
42
stopPC = {};
43
readPC = {};
44
fd2pathPC = {};
45
errstrPC = {};
46
awaitPC = {};
47
_waitPC = {};
48
_errstrPC = {};
49
trusscalls = {
50
		"sysr1",
51
		"_errstr",
52
		"bind",
53
		"chdir",
54
		"close",
55
		"dup",
56
		"alarm",
57
		"exec",
58
		"_exits",
59
		"_fsession",
60
		"fauth",
61
		"_fstat",
62
		"segbrk",
63
		"_mount",
64
		"open",
65
		"_read",
66
		"oseek",
67
		"sleep",
68
		"_stat",
69
		"rfork",
70
		"_write",
71
		"pipe",
72
		"create",
73
		"fd2path",
74
		"brk_",
75
		"remove",
76
		"_wstat",
77
		"_fwstat",
78
		"notify",
79
		"noted",
80
		"segattach",
81
		"segdetach",
82
		"segfree",
83
		"segflush",
84
		"rendezvous",
85
		"unmount",
86
		"_wait",
87
		"seek",
88
		"fversion",
89
		"errstr",
90
		"stat",
91
		"fstat",
92
		"wstat",
93
		"fwstat",
94
		"mount",
95
		"await",
96
		"pread",
97
		"pwrite",
98
	};
99
 
100
trussapecalls = {
101
		"_SYSR1",
102
		"__ERRSTR",
103
		"_BIND",
104
		"_CHDIR",
105
		"_CLOSE",
106
		"_DUP",
107
		"_ALARM",
108
		"_EXEC",
109
		"_EXITS",
110
		"__FSESSION",
111
		"_FAUTH",
112
		"__FSTAT",
113
		"_SEGBRK",
114
		"__MOUNT",
115
		"_OPEN",
116
		"__READ",
117
		"_OSEEK",
118
		"_SLEEP",
119
		"__STAT",
120
		"_RFORK",
121
		"__WRITE",
122
		"_PIPE",
123
		"_CREATE",
124
		"_FD2PATH",
125
		"_BRK_",
126
		"_REMOVE",
127
		"__WSTAT",
128
		"__FWSTAT",
129
		"_NOTIFY",
130
		"_NOTED",
131
		"_SEGATTACH",
132
		"_SEGDETACH",
133
		"_SEGFREE",
134
		"_SEGFLUSH",
135
		"_RENDEZVOUS",
136
		"_UNMOUNT",
137
		"__WAIT",
138
		"_SEEK",
139
		"__NFVERSION",
140
		"__NERRSTR",
141
		"_STAT",
142
		"__NFSTAT",
143
		"__NWSTAT",
144
		"__NFWSTAT",
145
		"__NMOUNT",
146
		"__NAWAIT",
147
		"_PREAD",
148
		"_PWRITE",
149
	};
150
 
151
defn addressof(pattern) {
152
	// translate to ape system calls if we have an ape binary
153
	if _addressof("_EXITS") == 0 then
154
		return _addressof(pattern);
155
	return _addressof(trussapecalls[match(pattern, trusscalls)]);
156
}
157
 
158
defn setuptruss() {
159
	local lst, offset, name, addr;
160
 
161
	trussbpt = {};
162
	offset = trapoffset();
163
	lst = trusscalls;
164
	while lst do
165
	{
166
		name = head lst;
167
		lst = tail lst;
168
		addr = addressof(name);
169
		if addr then
170
		{
171
			bpset(addr+offset);
172
			trussbpt = append trussbpt, (addr+offset);
173
			// sometimes _exits is renamed $_exits
174
			if(regexp("exits|exec", name)) then stopPC = append stopPC, (addr+offset);
175
			if(regexp("read", name)) then readPC = append readPC, (addr+offset);
176
			if(regexp("fd2path", name)) then fd2pathPC = append fd2pathPC, (addr+offset);
177
			if(regexp("^\\$*await", name)) then awaitPC = append awaitPC, (addr+offset);
178
			if(regexp("^\\$*errstr", name)) then errstrPC = append errstrPC, (addr+offset);
179
			// compatibility hacks for old kernel
180
			if(regexp("_wait", name)) then _waitPC = append _waitPC, (addr+offset);
181
			if(regexp("_errstr", name)) then _errstrPC = append _errstrPC, (addr+offset);
182
		}
183
	}
184
}
185
 
186
defn trussflush() {
187
	stop(pid);		// already stopped, but flushes output
188
}
189
 
190
defn new() {
191
	bplist = {};
192
	newproc(progargs);
193
	bpset(follow(main)[0]);
194
	cont();
195
	bpdel(*PC);
196
	// clear the hang bit, which is left set by newproc, so programs we fork/exec don't hang
197
	printto("/proc/"+itoa(pid)+"/ctl", "nohang");
198
}
199
 
200
defn truss() {
201
	local pc, lst, offset, prevpc, pcspret, ret;
202
 
203
	offset = trapoffset();
204
 
205
	stop(pid);
206
	_stoprunning = 0;
207
	setuptruss();
208
	pcspret = UPCSPRET();
209
 
210
	while !_stoprunning do {
211
		cont();
212
		if notes[0]!="sys: breakpoint" then {
213
			cleantruss();
214
			return {};
215
		}
216
		pc = *PC;
217
		if match(*PC, stopPC)>=0 then {
218
			print(pid,": ",trapreason(),"\t");
219
			print(fmt(pc,'a'),"\t",fmt(pc,'i'),"\n");
220
			cleantruss();
221
			return {};
222
		}
223
		if match(*PC, trussbpt)>=0 then {
224
			usyscall();
225
			trussflush();
226
			prevpc = *PC;
227
			step();
228
			ret = eval pcspret[2];
229
			print("\treturn value: ", ret\D, "\n");
230
			if (ret>=0) && (match(prevpc, readPC)>=0) then {
231
				print("\tdata: ");
232
				printtextordata(*((eval pcspret[1])+4), ret);
233
				print("\n");
234
			}
235
			if (ret>=0) && (match(prevpc, fd2pathPC)>=0) then {
236
				print("\tdata: \"", *(*((eval pcspret[1])+4)\s), "\"\n");
237
			}
238
			if (ret>=0) && (match(prevpc, errstrPC)>=0) then {
239
				print("\tdata: \"", *(*(eval pcspret[1])\s), "\"\n");
240
			}
241
			if (ret>=0) && (match(prevpc, awaitPC)>=0) then {
242
				print("\tdata: ");
243
				printtextordata(*(eval pcspret[1]), ret);
244
				print("\n");
245
			}
246
			// compatibility hacks for old kernel:
247
			if (ret>=0) && (match(prevpc, _waitPC)>=0) then {
248
				print("\tdata: ");
249
				printtextordata(*(eval pcspret[1]), 12+3*12+64);
250
				print("\n");
251
			}
252
			if (ret>=0) && (match(prevpc, _errstrPC)>=0) then {
253
				print("\tdata: ");
254
				printtextordata(*(eval pcspret[1]), 64);
255
				print("\n");
256
			}
257
		}
258
		trussflush();
259
	}
260
}
261
 
262
defn cleantruss() {
263
	local lst, offset, addr;
264
 
265
	stop(pid);
266
	offset = trapoffset();
267
	lst = trussbpt;
268
	while lst do
269
	{
270
		addr = head lst;
271
		lst = tail lst;
272
		bpdel(addr);
273
	}
274
	trussbpt = {};
275
	**PC = @*PC;	// repair current instruction
276
}
277
 
278
defn untruss() {
279
	cleantruss();
280
	start(pid);
281
}
282
 
283
print("/sys/lib/acid/truss");