xref: /plan9/sys/lib/acid/port (revision 976d3a687802c08e9dea20e32392e7a12b1f3502)
1// portable acid for all architectures
2
3defn pfl(addr)
4{
5	print(pcfile(addr), ":", pcline(addr), "\n");
6}
7
8defn
9notestk(addr)
10{
11	local pc, sp;
12	complex Ureg addr;
13
14	pc = addr.pc\X;
15	sp = addr.sp\X;
16
17	print("Note pc:", pc, " sp:", sp, " ", fmt(pc, 'a'), " ");
18	pfl(pc);
19	_stk(pc, sp, linkreg(addr), 1);
20}
21
22defn
23notelstk(addr)
24{
25	local pc, sp;
26	complex Ureg addr;
27
28	pc = addr.pc\X;
29	sp = addr.sp\X;
30
31	print("Note pc:", pc, " sp:", sp, " ", fmt(pc, 'a'), " ");
32	pfl(pc);
33	_stk(pc, sp, linkreg(addr), 1);
34}
35
36defn labstk(l)				// trace from a label
37{
38	_stk(*(l+4), *l, linkreg(0), 0);
39}
40
41defn params(param)
42{
43	while param do {
44		sym = head param;
45		print(sym[0], "=", itoa(sym[1], "%ux"));
46		param = tail param;
47		if param then
48			print (",");
49	}
50}
51
52stkprefix = "";
53stkignore = {};
54stkend = 0;
55
56defn locals(l)
57{
58	local sym;
59
60	while l do {
61		sym = head l;
62		print(stkprefix, "\t", sym[0], "=", itoa(sym[1], "%ux"), "\n");
63		l = tail l;
64	}
65}
66
67defn _stkign(file)
68{
69	s = stkignore;
70	while s do {
71		if regexp(head s, file) then
72			return 1;
73		s = tail s;
74	}
75	return 0;
76}
77
78// print a stack trace
79//
80// in a run of leading frames in files matched by regexps in stkignore,
81// only print the last one.
82defn _stk(pc, sp, link, dolocals)
83{
84	local stk, ign, last, lastpc;
85
86	stk = strace(pc, sp, link);
87	if stkignore then
88		ign = 1;
89	else
90		ign = 0;
91	last = stk;
92	lastpc = pc;
93	while stk do {
94		if ign then {
95			if !_stkign(pcfile(pc)) then {
96				ign = 0;
97				stk = last;
98				pc = lastpc;
99			}
100		}
101		frame = head stk;
102		if !ign then {
103			print(stkprefix, fmt(frame[0], 'a'), "(");
104			params(frame[2]);
105			print(")+", itoa(pc-frame[0], "%ux"), " ");
106			pfl(pc);
107			if dolocals then
108				locals(frame[3]);
109		}
110		last = stk;
111		lastpc = pc;
112		stk = tail stk;
113		pc = frame[1];
114	}
115	print(stkprefix, fmt(pc, 'a'), " ");
116	pfl(pc);
117}
118
119defn findsrc(file)
120{
121	local lst, src;
122
123	if file[0] == '/' then {
124		src = file(file);
125		if src != {} then {
126			srcfiles = append srcfiles, file;
127			srctext = append srctext, src;
128			return src;
129		}
130		return {};
131	}
132
133	lst = srcpath;
134	while head lst do {
135		src = file(head lst+file);
136		if src != {} then {
137			srcfiles = append srcfiles, file;
138			srctext = append srctext, src;
139			return src;
140		}
141		lst = tail lst;
142	}
143}
144
145defn line(addr)
146{
147	local src, file;
148
149	file = pcfile(addr);
150	src = match(file, srcfiles);
151
152	if src >= 0 then
153		src = srctext[src];
154	else
155		src = findsrc(file);
156
157	if src == {} then {
158		print("no source for ", file, "\n");
159		return {};
160	}
161	line = pcline(addr)-1;
162	print(file, ":", src[line], "\n");
163}
164
165defn addsrcdir(dir)
166{
167	dir = dir+"/";
168
169	if match(dir, srcpath) >= 0 then {
170		print("already in srcpath\n");
171		return {};
172	}
173
174	srcpath = {dir}+srcpath;
175}
176
177defn source()
178{
179	local l;
180
181	l = srcpath;
182	while l do {
183		print(head l, "\n");
184		l = tail l;
185	}
186	l = srcfiles;
187
188	while l do {
189		print("\t", head l, "\n");
190		l = tail l;
191	}
192}
193
194defn Bsrc(addr)
195{
196	local lst;
197
198	lst = srcpath;
199	file = pcfile(addr);
200	if file[0] == '/' && access(file) then {
201		rc("B "+file+":"+itoa(pcline(addr)));
202		return {};
203	}
204	while head lst do {
205		name = head lst+file;
206		if access(name) then {
207			rc("B "+name+":"+itoa(pcline(addr)));
208			return {};
209		}
210		lst = tail lst;
211	}
212	print("no source for ", file, "\n");
213}
214
215defn srcline(addr)
216{
217	local text, cline, line, file, src;
218	file = pcfile(addr);
219	src = match(file,srcfiles);
220	if (src>=0) then
221		src = srctext[src];
222	else
223		src = findsrc(file);
224	if (src=={}) then
225	{
226		return "(no source)";
227	}
228	return src[pcline(addr)-1];
229}
230
231defn src(addr)
232{
233	local src, file, line, cline, text;
234
235	file = pcfile(addr);
236	src = match(file, srcfiles);
237
238	if src >= 0 then
239		src = srctext[src];
240	else
241		src = findsrc(file);
242
243	if src == {} then {
244		print("no source for ", file, "\n");
245		return {};
246	}
247
248	cline = pcline(addr)-1;
249	print(file, ":", cline+1, "\n");
250	line = cline-5;
251	loop 0,10 do {
252		if line >= 0 then {
253			text = src[line];
254			if text == {} then
255				return {};
256			if line == cline then
257				print(">");
258			else
259				print(" ");
260			print(line+1, "\t", text, "\n");
261		}
262		line = line+1;
263	}
264}
265
266defn step()					// single step the process
267{
268	local lst, lpl, addr, bput;
269
270	bput = 0;
271	if match(*PC, bplist) >= 0 then {	// Sitting on a breakpoint
272		bput = fmt(*PC, bpfmt);
273		*bput = @bput;
274	}
275
276	lst = follow(*PC);
277
278	lpl = lst;
279	while lpl do {				// place break points
280		*(head lpl) = bpinst;
281		lpl = tail lpl;
282	}
283
284	startstop(pid);				// do the step
285
286	while lst do {				// remove the breakpoints
287		addr = fmt(head lst, bpfmt);
288		*addr = @addr;
289		lst = tail lst;
290	}
291	if bput != 0 then
292		*bput = bpinst;
293}
294
295defn bpset(addr)				// set a breakpoint
296{
297	if status(pid) != "Stopped" then {
298		print("Waiting...\n");
299		stop(pid);
300	}
301	if match(addr, bplist) >= 0 then
302		print("breakpoint already set at ", fmt(addr, 'a'), "\n");
303	else {
304		*fmt(addr, bpfmt) = bpinst;
305		bplist = append bplist, addr;
306	}
307}
308
309defn bptab()					// print a table of breakpoints
310{
311	local lst, addr;
312
313	lst = bplist;
314	while lst do {
315		addr = head lst;
316		print("\t", fmt(addr, 'X'), " ", fmt(addr, 'a'), "  ", fmt(addr, 'i'), "\n");
317		lst = tail lst;
318	}
319}
320
321defn bpdel(addr)				// delete a breakpoint
322{
323	local n, pc, nbplist;
324
325	n = match(addr, bplist);
326	if n < 0  then {
327		print("no breakpoint at ", fmt(addr, 'a'), "\n");
328		return {};
329	}
330
331	addr = fmt(addr, bpfmt);
332	*addr = @addr;
333
334	nbplist = {};				// delete from list
335	while bplist do {
336		pc = head bplist;
337		if pc != addr then
338			nbplist = append nbplist, pc;
339		bplist = tail bplist;
340	}
341	bplist = nbplist;			// delete from memory
342}
343
344defn cont()					// continue execution
345{
346	local addr;
347
348	addr = fmt(*PC, bpfmt);
349	if match(addr, bplist) >= 0 then {	// Sitting on a breakpoint
350		*addr = @addr;
351		step();				// Step over
352		*addr = bpinst;
353	}
354	startstop(pid);				// Run
355}
356
357defn stopped(pid)		// called from acid when a process changes state
358{
359	pstop(pid);		// stub so this is easy to replace
360}
361
362defn procs()			// print status of processes
363{
364	local c, lst, cpid;
365
366	cpid = pid;
367	lst = proclist;
368	while lst do {
369		np = head lst;
370		setproc(np);
371		if np == cpid then
372			c = '>';
373		else
374			c = ' ';
375		print(fmt(c, 'c'), np, ": ", status(np), " at ", fmt(*PC, 'a'), " setproc(", np, ")\n");
376		lst = tail lst;
377	}
378	pid = cpid;
379	if pid != 0 then
380		setproc(pid);
381}
382
383_asmlines = 30;
384
385defn asm(addr)
386{
387	local bound;
388
389	bound = fnbound(addr);
390
391	addr = fmt(addr, 'i');
392	loop 1,_asmlines do {
393		print(fmt(addr, 'a'), " ", fmt(addr, 'X'));
394		print("\t", @addr++, "\n");
395		if bound != {} && addr > bound[1] then {
396			lasmaddr = addr;
397			return {};
398		}
399	}
400	lasmaddr = addr;
401}
402
403defn casm()
404{
405	asm(lasmaddr);
406}
407
408defn win()
409{
410	local npid, estr;
411
412	bplist = {};
413	notes = {};
414
415	estr = "/sys/lib/acid/window '0 0 600 400' "+textfile;
416	if progargs != "" then
417		estr = estr+" "+progargs;
418
419	npid = rc(estr);
420	npid = atoi(npid);
421	if npid == 0 then
422		error("win failed to create process");
423
424	setproc(npid);
425	stopped(npid);
426}
427
428defn win2()
429{
430	local npid, estr;
431
432	bplist = {};
433	notes = {};
434
435	estr = "/sys/lib/acid/transcript '0 0 600 400' '100 100 700 500' "+textfile;
436	if progargs != "" then
437		estr = estr+" "+progargs;
438
439	npid = rc(estr);
440	npid = atoi(npid);
441	if npid == 0 then
442		error("win failed to create process");
443
444	setproc(npid);
445	stopped(npid);
446}
447
448defn new()
449{
450	bplist = {};
451	newproc(progargs);
452	// Dont miss the delay slot calls
453	bpset(follow(main)[0]);
454	cont();
455	bpdel(*PC);
456}
457
458defn stmnt()			// step one statement
459{
460	local line;
461
462	line = pcline(*PC);
463	while 1 do {
464		step();
465		if line != pcline(*PC) then {
466			src(*PC);
467			return {};
468		}
469	}
470}
471
472defn func()			// step until we leave the current function
473{
474	local bound, end, start, pc;
475
476	bound = fnbound(*PC);
477	if bound == {} then {
478		print("cannot locate text symbol\n");
479		return {};
480	}
481
482	pc = *PC;
483	start = bound[0];
484	end = bound[1];
485	while pc >= start && pc < end do {
486		step();
487		pc = *PC;
488	}
489}
490
491defn next()
492{
493	local sp, bound;
494
495	sp = *SP;
496	bound = fnbound(*PC);
497	stmnt();
498	pc = *PC;
499	if pc >= bound[0] && pc < bound[1] then
500		return {};
501
502	while (pc < bound[0] || pc > bound[1]) && sp >= *SP do {
503		step();
504		pc = *PC;
505	}
506	src(*PC);
507}
508
509defn dump(addr, n, fmt)
510{
511	// see definition of dump in acid manual: it does n+1 iterations
512	loop 0, n do {
513		print(fmt(addr, 'X'), ": ");
514		addr = mem(addr, fmt);
515	}
516}
517
518defn mem(addr, fmt)
519{
520
521	local i, c, n;
522
523	i = 0;
524	while fmt[i] != 0 do {
525		c = fmt[i];
526		n = 0;
527		while '0' <= fmt[i] && fmt[i] <= '9' do {
528			n = 10*n + fmt[i]-'0';
529			i = i+1;
530		}
531		if n <= 0 then n = 1;
532		addr = fmt(addr, fmt[i]);
533		while n > 0 do {
534			print(*addr++, " ");
535			n = n-1;
536		}
537		i = i+1;
538	}
539	print("\n");
540	return addr;
541}
542
543defn symbols(pattern)
544{
545	local l, s;
546
547	l = symbols;
548	while l do {
549		s = head l;
550		if regexp(pattern, s[0]) then
551			print(s[0], "\t", s[1], "\t", s[2], "\n");
552		l = tail l;
553	}
554}
555
556defn spsrch(len)
557{
558	local addr, a, s, e;
559
560	addr = *SP;
561	s = origin & 0x7fffffff;
562	e = etext & 0x7fffffff;
563	loop 1, len do {
564		a = *addr++;
565		c = a & 0x7fffffff;
566		if c > s && c < e then {
567			print("src(", a, ")\n");
568			pfl(a);
569		}
570	}
571}
572
573progargs="";
574print("/sys/lib/acid/port");
575