/*
 * process interface for Linux.
 * 
 * Uses ptrace for registers and data,
 * /proc for some process status.
 * There's not much point to worrying about
 * byte order here -- using ptrace means
 * we're running on the architecture we're debugging,
 * unless truly weird stuff is going on.
 *
 * It is tempting to use /proc/%d/mem along with
 * the sp and pc in the stat file to get a stack trace
 * without attaching to the program, but unfortunately
 * you can't read the mem file unless you've attached.
 */

#include <u.h>
#include <sys/ptrace.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/procfs.h>
#include <signal.h>
#include <errno.h>
#include <libc.h>
#include <mach.h>
#include <elf.h>
#include "ureg386.h"

Mach *machcpu = &mach386;

typedef struct PtraceRegs PtraceRegs;

struct PtraceRegs
{
	Regs r;
	int pid;
};

static int ptracesegrw(Map*, Seg*, ulong, void*, uint, int);
static int ptraceregrw(Regs*, char*, ulong*, int);

static int attachedpids[1000];
static int nattached;

static int
ptraceattach(int pid)
{
	int i;

	/*
	if(nattached==1 && attachedpids[0] == pid)
		goto already;
	if(nattached)
		detachproc(attachedpids[0]);
	*/
	
	for(i=0; i<nattached; i++)
		if(attachedpids[i]==pid)
			return 0;
	if(nattached == nelem(attachedpids)){
		werrstr("attached to too many processes");
		return -1;
	}

	if(ptrace(PTRACE_ATTACH, pid, 0, 0) < 0){
		werrstr("ptrace attach %d: %r", pid);
		return -1;
	}
	
	if(ctlproc(pid, "waitstop") < 0){
		fprint(2, "waitstop: %r");
		ptrace(PTRACE_DETACH, pid, 0, 0);
		return -1;
	}
	attachedpids[nattached++] = pid;
	return 0;
}

void
unmapproc(Map *map)
{
	int i;

	if(map == nil)
		return;
	for(i=0; i<map->nseg; i++)
		while(i<map->nseg && map->seg[i].pid){
			map->nseg--;
			memmove(&map->seg[i], &map->seg[i+1], 
				(map->nseg-i)*sizeof(map->seg[0]));
		}
}

int
mapproc(int pid, Map *map, Regs **rp)
{
	Seg s;
	PtraceRegs *r;

	if(ptraceattach(pid) < 0)
		return -1;

	memset(&s, 0, sizeof s);
	s.base = 0;
	s.size = 0xFFFFFFFF;
	s.offset = 0;
	s.name = "data";
	s.file = nil;
	s.rw = ptracesegrw;
	s.pid = pid;
	if(addseg(map, s) < 0){
		fprint(2, "addseg: %r\n");
		return -1;
	}

	if((r = mallocz(sizeof(PtraceRegs), 1)) == nil){
		fprint(2, "mallocz: %r\n");
		return -1;
	}
	r->r.rw = ptraceregrw;
	r->pid = pid;
	*rp = (Regs*)r;
	return 0;
}

int
detachproc(int pid)
{
	int i;

	for(i=0; i<nattached; i++){
		if(attachedpids[i] == pid){
			attachedpids[i] = attachedpids[--nattached];
			break;
		}
	}
	return ptrace(PTRACE_DETACH, pid, 0, 0);
}

static int
ptracerw(int type, int xtype, int isr, int pid, ulong addr, void *v, uint n)
{
	int i;
	u32int u;
	uchar buf[4];

	for(i=0; i<n; i+=4){
		if(isr){
			errno = 0;
			u = ptrace(type, pid, addr+i, 0);
			if(errno)
				goto ptraceerr;
			if(n-i >= 4)
				*(u32int*)((char*)v+i) = u;
			else{
				*(u32int*)buf = u;
				memmove((char*)v+i, buf, n-i);
			}
		}else{
			if(n-i >= 4)
				u = *(u32int*)((char*)v+i);
			else{
				errno = 0;
				u = ptrace(xtype, pid, addr+i, 0);
				if(errno)
					return -1;
				*(u32int*)buf = u;
				memmove(buf, (char*)v+i, n-i);
				u = *(u32int*)buf;
			}
			if(ptrace(type, pid, addr+i, u) < 0)
				goto ptraceerr;
		}
	}
	return 0;

ptraceerr:
	werrstr("ptrace: %r");
	return -1;
}

static int
ptracesegrw(Map *map, Seg *seg, ulong addr, void *v, uint n, int isr)
{
	addr += seg->base;
	return ptracerw(isr ? PTRACE_PEEKDATA : PTRACE_POKEDATA, PTRACE_PEEKDATA,
		isr, seg->pid, addr, v, n);
}

static char* linuxregs[] = {
	"BX",
	"CX",
	"DX",
	"SI",
	"DI",
	"BP",
	"AX",
	"DS",
	"ES",
	"FS",
	"GS",
	"OAX",
	"PC",
	"CS",
	"EFLAGS",
	"SP",
	"SS",
};

static ulong
reg2linux(char *reg)
{
	int i;

	for(i=0; i<nelem(linuxregs); i++)
		if(strcmp(linuxregs[i], reg) == 0)
			return 4*i;
	return ~(ulong)0;
}

static int
ptraceregrw(Regs *regs, char *name, ulong *val, int isr)
{
	int pid;
	ulong addr;
	u32int u;

	pid = ((PtraceRegs*)regs)->pid;
	addr = reg2linux(name);
	if(~addr == 0){
		if(isr){
			*val = ~(ulong)0;
			return 0;
		}
		werrstr("register not available");
		return -1;
	}
	if(isr){
		errno = 0;
		u = ptrace(PTRACE_PEEKUSER, pid, addr, 0);
		if(errno)
			goto ptraceerr;
		*val = u;
	}else{
		u = *val;
		if(ptrace(PTRACE_POKEUSER, pid, addr, &u) < 0)
			goto ptraceerr;
	}
	return 0;

ptraceerr:
	werrstr("ptrace: %r");
	return -1;
}

static int
isstopped(int pid)
{
	char buf[1024];
	int fd, n;
	char *p;

	snprint(buf, sizeof buf, "/proc/%d/stat", pid);
	if((fd = open(buf, OREAD)) < 0)
		return 0;
	n = read(fd, buf, sizeof buf-1);
	close(fd);
	if(n <= 0)
		return 0;
	buf[n] = 0;

	/* command name is in parens, no parens afterward */
	p = strrchr(buf, ')');
	if(p == nil || *++p != ' ')
		return 0;
	++p;

	/* next is state - T is stopped for tracing */
	return *p == 'T';
}

/* /proc/pid/stat contains 
	pid
	command in parens
	0. state
	1. ppid
	2. pgrp
	3. session
	4. tty_nr
	5. tpgid
	6. flags (math=4, traced=10)
	7. minflt
	8. cminflt
	9. majflt
	10. cmajflt
	11. utime
	12. stime
	13. cutime
	14. cstime
	15. priority
	16. nice
	17. 0
	18. itrealvalue
	19. starttime
	20. vsize
	21. rss
	22. rlim
	23. startcode
	24. endcode
	25. startstack
	26. kstkesp
	27. kstkeip
	28. pending signal bitmap
	29. blocked signal bitmap
	30. ignored signal bitmap
	31. caught signal bitmap
	32. wchan
	33. nswap
	34. cnswap
	35. exit_signal
	36. processor
*/


int
procnotes(int pid, char ***pnotes)
{
	char buf[1024], *f[40];
	int fd, i, n, nf;
	char *p, *s, **notes;
	ulong sigs;
	extern char *_p9sigstr(int, char*);

	*pnotes = nil;
	snprint(buf, sizeof buf, "/proc/%d/stat", pid);
	if((fd = open(buf, OREAD)) < 0){
		fprint(2, "open %s: %r\n", buf);
		return -1;
	}
	n = read(fd, buf, sizeof buf-1);
	close(fd);
	if(n <= 0){
		fprint(2, "read %s: %r\n", buf);
		return -1;
	}
	buf[n] = 0;

	/* command name is in parens, no parens afterward */
	p = strrchr(buf, ')');
	if(p == nil || *++p != ' '){
		fprint(2, "bad format in /proc/%d/stat\n", pid);
		return -1;
	}
	++p;

	nf = tokenize(p, f, nelem(f));
	if(0) print("code 0x%lux-0x%lux stack 0x%lux kstk 0x%lux keip 0x%lux pending 0x%lux\n",
		strtoul(f[23], 0, 0), strtoul(f[24], 0, 0), strtoul(f[25], 0, 0),
		strtoul(f[26], 0, 0), strtoul(f[27], 0, 0), strtoul(f[28], 0, 0));
	if(nf <= 28)
		return -1;

	sigs = strtoul(f[28], 0, 0) & ~(1<<SIGCONT);
	if(sigs == 0){
		*pnotes = nil;
		return 0;
	}

	notes = mallocz(32*sizeof(char*), 0);
	if(notes == nil)
		return -1;
	n = 0;
	for(i=0; i<32; i++){
		if((sigs&(1<<i)) == 0)
			continue;
		if((s = _p9sigstr(i, nil)) == nil)
			continue;
		notes[n++] = s;
	}
	*pnotes = notes;
	return n;
}

#undef waitpid

int
ctlproc(int pid, char *msg)
{
	int p, status;

	if(strcmp(msg, "hang") == 0){
		if(pid == getpid())
			return ptrace(PTRACE_TRACEME, 0, 0, 0);
		werrstr("can only hang self");
		return -1;
	}
	if(strcmp(msg, "kill") == 0)
		return ptrace(PTRACE_KILL, pid, 0, 0);
	if(strcmp(msg, "startstop") == 0){
		if(ptrace(PTRACE_CONT, pid, 0, 0) < 0)
			return -1;
		goto waitstop;
	}
	if(strcmp(msg, "sysstop") == 0){
		if(ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0)
			return -1;
		goto waitstop;
	}
	if(strcmp(msg, "stop") == 0){
		if(kill(pid, SIGSTOP) < 0)
			return -1;
		goto waitstop;
	}
	if(strcmp(msg, "waitstop") == 0){
	waitstop:
		if(isstopped(pid))
			return 0;
		for(;;){
			p = waitpid(pid, &status, WUNTRACED|__WALL);
			if(p <= 0){
				if(errno == ECHILD){
					if(isstopped(pid))
						return 0;
				}
				return -1;
			}
			if(WIFEXITED(status) || WIFSTOPPED(status))
				return 0;
		}
	}
	if(strcmp(msg, "start") == 0)
		return ptrace(PTRACE_CONT, pid, 0, 0);
	werrstr("unknown control message '%s'", msg);
	return -1;
}

char*
proctextfile(int pid)
{
	static char buf[1024], pbuf[128];

	snprint(pbuf, sizeof pbuf, "/proc/%d/exe", pid);
	if(readlink(pbuf, buf, sizeof buf) >= 0)
		return buf;
	if(access(pbuf, AEXIST) >= 0)
		return pbuf;
	return nil;
}

