The Go Programming Language

Text file src/libmach/linux.c

     1	// Derived from Plan 9 from User Space src/libmach/Linux.c
     2	// http://code.swtch.com/plan9port/src/tip/src/libmach/Linux.c
     3	//
     4	//	Copyright © 1994-1999 Lucent Technologies Inc.
     5	//	Power PC support Copyright © 1995-2004 C H Forsyth (forsyth@terzarima.net).
     6	//	Portions Copyright © 1997-1999 Vita Nuova Limited.
     7	//	Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com).
     8	//	Revisions Copyright © 2000-2004 Lucent Technologies Inc. and others.
     9	//	Portions Copyright © 2001-2007 Russ Cox.
    10	//	Portions Copyright © 2009 The Go Authors.  All rights reserved.
    11	//
    12	// Permission is hereby granted, free of charge, to any person obtaining a copy
    13	// of this software and associated documentation files (the "Software"), to deal
    14	// in the Software without restriction, including without limitation the rights
    15	// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    16	// copies of the Software, and to permit persons to whom the Software is
    17	// furnished to do so, subject to the following conditions:
    18	//
    19	// The above copyright notice and this permission notice shall be included in
    20	// all copies or substantial portions of the Software.
    21	//
    22	// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    23	// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    24	// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
    25	// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    26	// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    27	// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    28	// THE SOFTWARE.
    29	
    30	#include <u.h>
    31	#include <sys/syscall.h>	/* for tkill */
    32	#include <unistd.h>
    33	#include <dirent.h>
    34	#include <sys/ptrace.h>
    35	#include <sys/signal.h>
    36	#include <sys/wait.h>
    37	#include <errno.h>
    38	#include <libc.h>
    39	#include <bio.h>
    40	#include <mach.h>
    41	#define Ureg Ureg32
    42	#include <ureg_x86.h>
    43	#undef Ureg
    44	#define Ureg Ureg64
    45	#include <ureg_amd64.h>
    46	#undef Ureg
    47	#undef waitpid
    48	
    49	// The old glibc used with crosstool compilers on thresher
    50	// doesn't know these numbers, but the Linux kernel
    51	// had them as far back as 2.6.0.
    52	#ifndef WSTOPPED
    53	#define WSTOPPED 2
    54	#define WCONTINUED 8
    55	#define WIFCONTINUED(x) ((x) == 0xffff)
    56	#endif
    57	#ifndef PTRACE_SETOPTIONS
    58	#define PTRACE_SETOPTIONS 0x4200
    59	#define PTRACE_GETEVENTMSG 0x4201
    60	#define PTRACE_O_TRACEFORK 0x2
    61	#define PTRACE_O_TRACEVFORK 0x4
    62	#define PTRACE_O_TRACECLONE 0x8
    63	#define PTRACE_O_TRACEEXEC 0x10
    64	#define PTRACE_O_TRACEVFORKDONE 0x20
    65	#define PTRACE_O_TRACEEXIT 0x40
    66	#define PTRACE_EVENT_FORK 0x1
    67	#define PTRACE_EVENT_VFORK 0x2
    68	#define PTRACE_EVENT_CLONE 0x3
    69	#define PTRACE_EVENT_EXEC 0x4
    70	#define PTRACE_EVENT_VFORK_DONE 0x5
    71	#define PTRACE_EVENT_EXIT 0x6
    72	#endif
    73	
    74	typedef struct Ureg64 Ureg64;
    75	
    76	static Maprw ptracesegrw;
    77	static Maprw ptraceregrw;
    78	
    79	// /usr/include/asm-x86_64/user.h
    80	struct user_regs_struct {
    81		unsigned long r15,r14,r13,r12,rbp,rbx,r11,r10;
    82		unsigned long r9,r8,rax,rcx,rdx,rsi,rdi,orig_rax;
    83		unsigned long rip,cs,eflags;
    84		unsigned long rsp,ss;
    85	  	unsigned long fs_base, gs_base;
    86		unsigned long ds,es,fs,gs;
    87	};
    88	
    89	// Linux gets very upset if a debugger forgets the reported state
    90	// of a debugged process, so we keep everything we know about
    91	// a debugged process in the LinuxThread structure.
    92	//
    93	// We can poll for state changes by calling waitpid and interpreting
    94	// the integer status code that comes back.  Wait1 does this.
    95	//
    96	// If the process is already running, it is an error to PTRACE_CONT it.
    97	//
    98	// If the process is already stopped, it is an error to stop it again.
    99	//
   100	// If the process is stopped because of a signal, the debugger must
   101	// relay the signal to the PTRACE_CONT call, or else the signal is
   102	// dropped.
   103	//
   104	// If the process exits, the debugger should detach so that the real
   105	// parent can reap the zombie.
   106	//
   107	// On first attach, the debugger should set a handful of flags in order
   108	// to catch future events like fork, clone, exec, etc.
   109	
   110	// One for every attached thread.
   111	typedef struct LinuxThread LinuxThread;
   112	struct LinuxThread
   113	{
   114		int pid;
   115		int tid;
   116		int state;
   117		int signal;
   118		int child;
   119		int exitcode;
   120	};
   121	
   122	static int trace = 0;
   123	
   124	static LinuxThread **thr;
   125	static int nthr;
   126	static int mthr;
   127	
   128	static int realpid(int pid);
   129	
   130	enum
   131	{
   132		Unknown,
   133		Detached,
   134		Attached,
   135		AttachStop,
   136		Stopped,
   137		Running,
   138		Forking,
   139		Vforking,
   140		VforkDone,
   141		Cloning,
   142		Execing,
   143		Exiting,
   144		Exited,
   145		Killed,
   146	
   147		NSTATE,
   148	};
   149	
   150	static char* statestr[NSTATE] = {
   151		"Unknown",
   152		"Detached",
   153		"Attached",
   154		"AttachStop",
   155		"Stopped",
   156		"Running",
   157		"Forking",
   158		"Vforking",
   159		"VforkDone",
   160		"Cloning",
   161		"Execing",
   162		"Exiting",
   163		"Exited",
   164		"Killed"
   165	};
   166	
   167	static LinuxThread*
   168	attachthread(int pid, int tid, int *new, int newstate)
   169	{
   170		int i, n, status;
   171		LinuxThread **p, *t;
   172		uintptr flags;
   173	
   174		if(new)
   175			*new = 0;
   176	
   177		for(i=0; i<nthr; i++)
   178			if((pid == 0 || thr[i]->pid == pid) && thr[i]->tid == tid) {
   179				t = thr[i];
   180				goto fixup;
   181			}
   182	
   183		if(!new)
   184			return nil;
   185	
   186		if(nthr >= mthr) {
   187			n = mthr;
   188			if(n == 0)
   189				n = 64;
   190			else
   191				n *= 2;
   192			p = realloc(thr, n*sizeof thr[0]);
   193			if(p == nil)
   194				return nil;
   195			thr = p;
   196			mthr = n;
   197		}
   198	
   199		t = malloc(sizeof *t);
   200		if(t == nil)
   201			return nil;
   202		memset(t, 0, sizeof *t);
   203	
   204		thr[nthr++] = t;
   205		if(pid == 0 && nthr > 0)
   206			pid = thr[0]->pid;
   207		t->pid = pid;
   208		t->tid = tid;
   209		t->state = newstate;
   210		if(trace)
   211			fprint(2, "new thread %d %d\n", t->pid, t->tid);
   212		if(new)
   213			*new = 1;
   214	
   215	fixup:
   216		if(t->state == Detached) {
   217			if(ptrace(PTRACE_ATTACH, tid, 0, 0) < 0) {
   218				fprint(2, "ptrace ATTACH %d: %r\n", tid);
   219				return nil;
   220			}
   221			t->state = Attached;
   222		}
   223	
   224		if(t->state == Attached) {
   225			// wait for stop, so we can set options
   226			if(waitpid(tid, &status, __WALL|WUNTRACED|WSTOPPED) < 0)
   227				return nil;
   228			if(!WIFSTOPPED(status)) {
   229				fprint(2, "waitpid %d: status=%#x not stopped\n", tid);
   230				return nil;
   231			}
   232			t->state = AttachStop;
   233		}
   234	
   235		if(t->state == AttachStop) {
   236			// set options so we'll find out about new threads
   237			flags = PTRACE_O_TRACEFORK |
   238				PTRACE_O_TRACEVFORK |
   239				PTRACE_O_TRACECLONE |
   240				PTRACE_O_TRACEEXEC |
   241				PTRACE_O_TRACEVFORKDONE;
   242			if(ptrace(PTRACE_SETOPTIONS, tid, 0, (void*)flags) < 0)	{
   243				fprint(2, "ptrace PTRACE_SETOPTIONS %d: %r\n", tid);
   244				return nil;
   245			}
   246			t->state = Stopped;
   247		}
   248	
   249		return t;
   250	}
   251	
   252	static LinuxThread*
   253	findthread(int tid)
   254	{
   255		return attachthread(0, tid, nil, 0);
   256	}
   257	
   258	int
   259	procthreadpids(int pid, int *p, int np)
   260	{
   261		int i, n;
   262		LinuxThread *t;
   263	
   264		n = 0;
   265		for(i=0; i<nthr; i++) {
   266			t = thr[i];
   267			if(t->pid == pid) {
   268				switch(t->state) {
   269				case Exited:
   270				case Detached:
   271				case Killed:
   272					break;
   273	
   274				default:
   275					if(n < np)
   276						p[n] = t->tid;
   277					n++;
   278					break;
   279				}
   280			}
   281		}
   282		return n;
   283	}
   284	
   285	// Execute a single wait and update the corresponding thread.
   286	static int
   287	wait1(int nohang)
   288	{
   289		int tid, new, status, event;
   290		ulong data;
   291		LinuxThread *t;
   292		enum
   293		{
   294			NormalStop = 0x137f
   295		};
   296	
   297		if(nohang != 0)
   298			nohang = WNOHANG;
   299	
   300		status = 0;
   301		tid = waitpid(-1, &status, __WALL|WUNTRACED|WSTOPPED|WCONTINUED|nohang);
   302	
   303		if(tid < 0)
   304			return -1;
   305		if(tid == 0)
   306			return 0;
   307	
   308		if(trace > 0 && status != NormalStop)
   309			fprint(2, "TID %d: %#x\n", tid, status);
   310	
   311		t = findthread(tid);
   312		if(t == nil) {
   313			// Sometimes the kernel tells us about new threads
   314			// before we see the parent clone.
   315			t = attachthread(0, tid, &new, Stopped);
   316			if(t == nil) {
   317				fprint(2, "failed to attach to new thread %d\n", tid);
   318				return -1;
   319			}
   320		}
   321	
   322		if(WIFSTOPPED(status)) {
   323			t->state = Stopped;
   324			t->signal = WSTOPSIG(status);
   325			if(trace)
   326				fprint(2, "tid %d: stopped %#x%s\n", tid, status,
   327					status != NormalStop ? " ***" : "");
   328			if(t->signal == SIGTRAP && (event = status>>16) != 0) {	// ptrace event
   329				switch(event) {
   330				case PTRACE_EVENT_FORK:
   331					t->state = Forking;
   332					goto child;
   333	
   334				case PTRACE_EVENT_VFORK:
   335					t->state = Vforking;
   336					goto child;
   337	
   338				case PTRACE_EVENT_CLONE:
   339					t->state = Cloning;
   340					goto child;
   341	
   342				child:
   343					if(ptrace(PTRACE_GETEVENTMSG, t->tid, 0, &data) < 0) {
   344						fprint(2, "ptrace GETEVENTMSG tid %d: %r\n", tid);
   345						break;
   346					}
   347					t->child = data;
   348					attachthread(t->pid, t->child, &new, Running);
   349					break;
   350	
   351				case PTRACE_EVENT_EXEC:
   352					t->state = Execing;
   353					break;
   354	
   355				case PTRACE_EVENT_VFORK_DONE:
   356					t->state = VforkDone;
   357					break;
   358	
   359				case PTRACE_EVENT_EXIT:
   360					// We won't see this unless we set PTRACE_O_TRACEEXIT.
   361					// The debuggers assume that a read or write on a Map
   362					// will fail for a thread that has exited.  This event
   363					// breaks that assumption.  It's not a big deal: we
   364					// only lose the ability to see the register state at
   365					// the time of exit.
   366					if(trace)
   367						fprint(2, "tid %d: exiting %#x\n", tid, status);
   368					t->state = Exiting;
   369					if(ptrace(PTRACE_GETEVENTMSG, t->tid, 0, &data) < 0) {
   370						fprint(2, "ptrace GETEVENTMSG tid %d: %r\n", tid);
   371						break;
   372					}
   373					t->exitcode = data;
   374					break;
   375				}
   376			}
   377		}
   378		if(WIFCONTINUED(status)) {
   379			if(trace)
   380				fprint(2, "tid %d: continued %#x\n", tid, status);
   381			t->state = Running;
   382		}
   383		if(WIFEXITED(status)) {
   384			if(trace)
   385				fprint(2, "tid %d: exited %#x\n", tid, status);
   386			t->state = Exited;
   387			t->exitcode = WEXITSTATUS(status);
   388			t->signal = -1;
   389			ptrace(PTRACE_DETACH, t->tid, 0, 0);
   390			if(trace)
   391				fprint(2, "tid %d: detach exited\n", tid);
   392		}
   393		if(WIFSIGNALED(status)) {
   394			if(trace)
   395				fprint(2, "tid %d: signaled %#x\n", tid, status);
   396			t->state = Exited;
   397			t->signal = WTERMSIG(status);
   398			t->exitcode = -1;
   399			ptrace(PTRACE_DETACH, t->tid, 0, 0);
   400			if(trace)
   401				fprint(2, "tid %d: detach signaled\n", tid);
   402		}
   403		return 1;
   404	}
   405	
   406	static int
   407	waitstop(LinuxThread *t)
   408	{
   409		while(t->state == Running)
   410			if(wait1(0) < 0)
   411				return -1;
   412		return 0;
   413	}
   414	
   415	// Attach to and stop all threads in process pid.
   416	// Must stop everyone in order to make sure we set
   417	// the "tell me about new threads" option in every
   418	// task.
   419	int
   420	attachallthreads(int pid)
   421	{
   422		int tid, foundnew, new;
   423		char buf[100];
   424		DIR *d;
   425		struct dirent *de;
   426		LinuxThread *t;
   427	
   428		if(pid == 0) {
   429			fprint(2, "attachallthreads(0)\n");
   430			return -1;
   431		}
   432	
   433		pid = realpid(pid);
   434	
   435		snprint(buf, sizeof buf, "/proc/%d/task", pid);
   436		if((d = opendir(buf)) == nil) {
   437			fprint(2, "opendir %s: %r\n", buf);
   438			return -1;
   439		}
   440	
   441		// Loop in case new threads are being created right now.
   442		// We stop every thread as we find it, so eventually
   443		// this has to stop (or the system runs out of procs).
   444		do {
   445			foundnew = 0;
   446			while((de = readdir(d)) != nil) {
   447				tid = atoi(de->d_name);
   448				if(tid == 0)
   449					continue;
   450				t = attachthread(pid, tid, &new, Detached);
   451				foundnew |= new;
   452				if(t)
   453					waitstop(t);
   454			}
   455			rewinddir(d);
   456		} while(foundnew);
   457		closedir(d);
   458	
   459		return 0;
   460	}
   461	
   462	Map*
   463	attachproc(int pid, Fhdr *fp)
   464	{
   465		Map *map;
   466	
   467		if(pid == 0) {
   468			fprint(2, "attachproc(0)\n");
   469			return nil;
   470		}
   471	
   472		if(findthread(pid) == nil && attachallthreads(pid) < 0)
   473			return nil;
   474	
   475		map = newmap(0, 4);
   476		if (!map)
   477			return 0;
   478		map->pid = pid;
   479		if(mach->regsize)
   480			setmap(map, -1, 0, mach->regsize, 0, "regs", ptraceregrw);
   481	//	if(mach->fpregsize)
   482	//		setmap(map, -1, mach->regsize, mach->regsize+mach->fpregsize, 0, "fpregs", ptraceregrw);
   483		setmap(map, -1, fp->txtaddr, fp->txtaddr+fp->txtsz, fp->txtaddr, "*text", ptracesegrw);
   484		setmap(map, -1, fp->dataddr, mach->utop, fp->dataddr, "*data", ptracesegrw);
   485		return map;
   486	}
   487	
   488	void
   489	detachproc(Map *m)
   490	{
   491		LinuxThread *t;
   492	
   493		t = findthread(m->pid);
   494		if(t != nil) {
   495			ptrace(PTRACE_DETACH, t->tid, 0, 0);
   496			t->state = Detached;
   497			if(trace)
   498				fprint(2, "tid %d: detachproc\n", t->tid);
   499			// TODO(rsc): Reclaim thread structs somehow?
   500		}
   501		free(m);
   502	}
   503	
   504	/* /proc/pid/stat contains
   505		pid
   506		command in parens
   507		0. state
   508		1. ppid
   509		2. pgrp
   510		3. session
   511		4. tty_nr
   512		5. tpgid
   513		6. flags (math=4, traced=10)
   514		7. minflt
   515		8. cminflt
   516		9. majflt
   517		10. cmajflt
   518		11. utime
   519		12. stime
   520		13. cutime
   521		14. cstime
   522		15. priority
   523		16. nice
   524		17. 0
   525		18. itrealvalue
   526		19. starttime
   527		20. vsize
   528		21. rss
   529		22. rlim
   530		23. startcode
   531		24. endcode
   532		25. startstack
   533		26. kstkesp
   534		27. kstkeip
   535		28. pending signal bitmap
   536		29. blocked signal bitmap
   537		30. ignored signal bitmap
   538		31. caught signal bitmap
   539		32. wchan
   540		33. nswap
   541		34. cnswap
   542		35. exit_signal
   543		36. processor
   544	*/
   545	
   546	static int
   547	readstat(int pid, char *buf, int nbuf, char **f, int nf)
   548	{
   549		int fd, n;
   550		char *p;
   551	
   552		snprint(buf, nbuf, "/proc/%d/stat", pid);
   553		if((fd = open(buf, OREAD)) < 0){
   554			fprint(2, "open %s: %r\n", buf);
   555			return -1;
   556		}
   557		n = read(fd, buf, nbuf-1);
   558		close(fd);
   559		if(n <= 0){
   560			fprint(2, "read %s: %r\n", buf);
   561			return -1;
   562		}
   563		buf[n] = 0;
   564	
   565		/* command name is in parens, no parens afterward */
   566		p = strrchr(buf, ')');
   567		if(p == nil || *++p != ' '){
   568			fprint(2, "bad format in /proc/%d/stat\n", pid);
   569			return -1;
   570		}
   571		++p;
   572	
   573		nf = tokenize(p, f, nf);
   574		if(0) print("code 0x%lux-0x%lux stack 0x%lux kstk 0x%lux keip 0x%lux pending 0x%lux\n",
   575			strtoul(f[23], 0, 0), strtoul(f[24], 0, 0), strtoul(f[25], 0, 0),
   576			strtoul(f[26], 0, 0), strtoul(f[27], 0, 0), strtoul(f[28], 0, 0));
   577	
   578		return nf;
   579	}
   580	
   581	static char*
   582	readstatus(int pid, char *buf, int nbuf, char *key)
   583	{
   584		int fd, n;
   585		char *p;
   586	
   587		snprint(buf, nbuf, "/proc/%d/status", pid);
   588		if((fd = open(buf, OREAD)) < 0){
   589			fprint(2, "open %s: %r\n", buf);
   590			return nil;
   591		}
   592		n = read(fd, buf, nbuf-1);
   593		close(fd);
   594		if(n <= 0){
   595			fprint(2, "read %s: %r\n", buf);
   596			return nil;
   597		}
   598		buf[n] = 0;
   599		p = strstr(buf, key);
   600		if(p)
   601			return p+strlen(key);
   602		return nil;
   603	}
   604	
   605	int
   606	procnotes(int pid, char ***pnotes)
   607	{
   608		char buf[1024], *f[40];
   609		int i, n, nf;
   610		char *s, **notes;
   611		ulong sigs;
   612		extern char *_p9sigstr(int, char*);
   613	
   614		*pnotes = nil;
   615		nf = readstat(pid, buf, sizeof buf, f, nelem(f));
   616		if(nf <= 28)
   617			return -1;
   618	
   619		sigs = strtoul(f[28], 0, 0) & ~(1<<SIGCONT);
   620		if(sigs == 0){
   621			*pnotes = nil;
   622			return 0;
   623		}
   624	
   625		notes = malloc(32*sizeof(char*));
   626		if(notes == nil)
   627			return -1;
   628		memset(notes, 0, 32*sizeof(char*));
   629		n = 0;
   630		for(i=0; i<32; i++){
   631			if((sigs&(1<<i)) == 0)
   632				continue;
   633			if((s = _p9sigstr(i, nil)) == nil)
   634				continue;
   635			notes[n++] = s;
   636		}
   637		*pnotes = notes;
   638		return n;
   639	}
   640	
   641	static int
   642	realpid(int pid)
   643	{
   644		char buf[1024], *p;
   645	
   646		p = readstatus(pid, buf, sizeof buf, "\nTgid:");
   647		if(p == nil)
   648			return pid;
   649		return atoi(p);
   650	}
   651	
   652	int
   653	ctlproc(int pid, char *msg)
   654	{
   655		int new;
   656		LinuxThread *t;
   657		uintptr data;
   658	
   659		while(wait1(1) > 0)
   660			;
   661	
   662		if(strcmp(msg, "attached") == 0){
   663			t = attachthread(pid, pid, &new, Attached);
   664			if(t == nil)
   665				return -1;
   666			return 0;
   667		}
   668	
   669		if(strcmp(msg, "hang") == 0){
   670			if(pid == getpid())
   671				return ptrace(PTRACE_TRACEME, 0, 0, 0);
   672			werrstr("can only hang self");
   673			return -1;
   674		}
   675	
   676		t = findthread(pid);
   677		if(t == nil) {
   678			werrstr("not attached to pid %d", pid);
   679			return -1;
   680		}
   681		if(t->state == Exited) {
   682			werrstr("pid %d has exited", pid);
   683			return -1;
   684		}
   685		if(t->state == Killed) {
   686			werrstr("pid %d has been killed", pid);
   687			return -1;
   688		}
   689	
   690		if(strcmp(msg, "kill") == 0) {
   691			if(ptrace(PTRACE_KILL, pid, 0, 0) < 0)
   692				return -1;
   693			t->state = Killed;
   694			return 0;
   695		}
   696		if(strcmp(msg, "startstop") == 0){
   697			if(ctlproc(pid, "start") < 0)
   698				return -1;
   699			return waitstop(t);
   700		}
   701		if(strcmp(msg, "sysstop") == 0){
   702			if(ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0)
   703				return -1;
   704			t->state = Running;
   705			return waitstop(t);
   706		}
   707		if(strcmp(msg, "stop") == 0){
   708			if(trace > 1)
   709				fprint(2, "tid %d: tkill stop\n", pid);
   710			if(t->state == Stopped)
   711				return 0;
   712			if(syscall(__NR_tkill, pid, SIGSTOP) < 0)
   713				return -1;
   714			return waitstop(t);
   715		}
   716		if(strcmp(msg, "step") == 0){
   717			if(t->state == Running) {
   718				werrstr("cannot single-step unstopped %d", pid);
   719				return -1;
   720			}
   721			if(ptrace(PTRACE_SINGLESTEP, pid, 0, 0) < 0)
   722				return -1;
   723			return waitstop(t);
   724		}
   725		if(strcmp(msg, "start") == 0) {
   726			if(t->state == Running)
   727				return 0;
   728			data = 0;
   729			if(t->state == Stopped && t->signal != SIGSTOP && t->signal != SIGTRAP)
   730				data = t->signal;
   731			if(trace && data)
   732				fprint(2, "tid %d: continue %lud\n", pid, (ulong)data);
   733			if(ptrace(PTRACE_CONT, pid, 0, (void*)data) < 0)
   734				return -1;
   735			t->state = Running;
   736			return 0;
   737		}
   738		if(strcmp(msg, "waitstop") == 0) {
   739			return waitstop(t);
   740		}
   741		werrstr("unknown control message '%s'", msg);
   742		return -1;
   743	}
   744	
   745	char*
   746	proctextfile(int pid)
   747	{
   748		static char buf[1024], pbuf[128];
   749	
   750		snprint(pbuf, sizeof pbuf, "/proc/%d/exe", pid);
   751		if(readlink(pbuf, buf, sizeof buf) >= 0)
   752			return strdup(buf);
   753		if(access(pbuf, AEXIST) >= 0)
   754			return strdup(pbuf);
   755		return nil;
   756	}
   757	
   758	
   759	static int
   760	ptracerw(int type, int xtype, int isr, int pid, uvlong addr, void *v, uint n)
   761	{
   762		int i;
   763		uintptr u, a;
   764		uchar buf[sizeof(uintptr)];
   765	
   766		for(i=0; i<n; i+=sizeof(uintptr)){
   767			// Tread carefully here.  On recent versions of glibc,
   768			// ptrace is a variadic function which means the third
   769			// argument will be pushed onto the stack as a uvlong.
   770			// This is fine on amd64 but will not work for 386.
   771			// We must convert addr to a uintptr.
   772			a = addr+i;
   773			if(isr){
   774				errno = 0;
   775				u = ptrace(type, pid, a, 0);
   776				if(errno)
   777					goto ptraceerr;
   778				if(n-i >= sizeof(uintptr))
   779					memmove((char*)v+i, &u, sizeof(uintptr));
   780				else{
   781					memmove(buf, &u, sizeof u);
   782					memmove((char*)v+i, buf, n-i);
   783				}
   784			}else{
   785				if(n-i >= sizeof(uintptr))
   786					u = *(uintptr*)((char*)v+i);
   787				else{
   788					errno = 0;
   789					u = ptrace(xtype, pid, a, 0);
   790					if(errno)
   791						return -1;
   792					memmove(buf, &u, sizeof u);
   793					memmove(buf, (char*)v+i, n-i);
   794					memmove(&u, buf, sizeof u);
   795				}
   796				if(ptrace(type, pid, a, u) < 0)
   797					goto ptraceerr;
   798			}
   799		}
   800		return 0;
   801	
   802	ptraceerr:
   803		werrstr("ptrace %s addr=%#llux pid=%d: %r", isr ? "read" : "write", addr, pid);
   804		return -1;
   805	}
   806	
   807	static int
   808	ptracesegrw(Map *map, Seg *seg, uvlong addr, void *v, uint n, int isr)
   809	{
   810		return ptracerw(isr ? PTRACE_PEEKDATA : PTRACE_POKEDATA, PTRACE_PEEKDATA,
   811			isr, map->pid, addr, v, n);
   812	}
   813	
   814	// If the debugger is compiled as an x86-64 program,
   815	// then all the ptrace register read/writes are done on
   816	// a 64-bit register set.  If the target program
   817	// is a 32-bit program, the debugger is expected to
   818	// read the bottom half of the relevant registers
   819	// out of the 64-bit set.
   820	
   821	// Linux 32-bit is
   822	//	BX CX DX SI DI BP AX DS ES FS GS OrigAX IP CS EFLAGS SP SS
   823	
   824	// Linux 64-bit is
   825	//	R15 R14 R13 R12 BP BX R11 R10 R9 R8 AX CX DX SI DI OrigAX IP CS EFLAGS SP SS FSBase GSBase DS ES FS GS
   826	
   827	// Go 32-bit is
   828	//	DI SI BP NSP BX DX CX AX GS FS ES DS TRAP ECODE PC CS EFLAGS SP SS
   829	
   830	uint go32tolinux32tab[] = {
   831		4, 3, 5, 15, 0, 2, 1, 6, 10, 9, 8, 7, -1, -1, 12, 13, 14, 15, 16
   832	};
   833	static int
   834	go32tolinux32(uvlong addr)
   835	{
   836		int r;
   837	
   838		if(addr%4 || addr/4 >= nelem(go32tolinux32tab))
   839			return -1;
   840		r = go32tolinux32tab[addr/4];
   841		if(r < 0)
   842			return -1;
   843		return r*4;
   844	}
   845	
   846	uint go32tolinux64tab[] = {
   847		14, 13, 4, 19, 5, 12, 11, 10, 26, 25, 24, 23, -1, -1, 16, 17, 18, 19, 20
   848	};
   849	static int
   850	go32tolinux64(uvlong addr)
   851	{
   852		int r;
   853	
   854		if(addr%4 || addr/4 >= nelem(go32tolinux64tab))
   855			return -1;
   856		r = go32tolinux64tab[addr/4];
   857		if(r < 0)
   858			return -1;
   859		return r*8;
   860	}
   861	
   862	extern Mach mi386;
   863	extern Mach mamd64;
   864	
   865	static int
   866	go2linux(uvlong addr)
   867	{
   868		if(sizeof(void*) == 4) {
   869			if(mach == &mi386)
   870				return go32tolinux32(addr);
   871			werrstr("unsupported architecture");
   872			return -1;
   873		}
   874	
   875		if(mach == &mi386)
   876			return go32tolinux64(addr);
   877		if(mach != &mamd64) {
   878			werrstr("unsupported architecture");
   879			return -1;
   880		}
   881	
   882		switch(addr){
   883		case offsetof(Ureg64, ax):
   884			return offsetof(struct user_regs_struct, rax);
   885		case offsetof(Ureg64, bx):
   886			return offsetof(struct user_regs_struct, rbx);
   887		case offsetof(Ureg64, cx):
   888			return offsetof(struct user_regs_struct, rcx);
   889		case offsetof(Ureg64, dx):
   890			return offsetof(struct user_regs_struct, rdx);
   891		case offsetof(Ureg64, si):
   892			return offsetof(struct user_regs_struct, rsi);
   893		case offsetof(Ureg64, di):
   894			return offsetof(struct user_regs_struct, rdi);
   895		case offsetof(Ureg64, bp):
   896			return offsetof(struct user_regs_struct, rbp);
   897		case offsetof(Ureg64, r8):
   898			return offsetof(struct user_regs_struct, r8);
   899		case offsetof(Ureg64, r9):
   900			return offsetof(struct user_regs_struct, r9);
   901		case offsetof(Ureg64, r10):
   902			return offsetof(struct user_regs_struct, r10);
   903		case offsetof(Ureg64, r11):
   904			return offsetof(struct user_regs_struct, r11);
   905		case offsetof(Ureg64, r12):
   906			return offsetof(struct user_regs_struct, r12);
   907		case offsetof(Ureg64, r13):
   908			return offsetof(struct user_regs_struct, r13);
   909		case offsetof(Ureg64, r14):
   910			return offsetof(struct user_regs_struct, r14);
   911		case offsetof(Ureg64, r15):
   912			return offsetof(struct user_regs_struct, r15);
   913		case offsetof(Ureg64, ds):
   914			return offsetof(struct user_regs_struct, ds);
   915		case offsetof(Ureg64, es):
   916			return offsetof(struct user_regs_struct, es);
   917		case offsetof(Ureg64, fs):
   918			return offsetof(struct user_regs_struct, fs);
   919		case offsetof(Ureg64, gs):
   920			return offsetof(struct user_regs_struct, gs);
   921		case offsetof(Ureg64, ip):
   922			return offsetof(struct user_regs_struct, rip);
   923		case offsetof(Ureg64, cs):
   924			return offsetof(struct user_regs_struct, cs);
   925		case offsetof(Ureg64, flags):
   926			return offsetof(struct user_regs_struct, eflags);
   927		case offsetof(Ureg64, sp):
   928			return offsetof(struct user_regs_struct, rsp);
   929		case offsetof(Ureg64, ss):
   930			return offsetof(struct user_regs_struct, ss);
   931		}
   932		return -1;
   933	}
   934	
   935	static int
   936	ptraceregrw(Map *map, Seg *seg, uvlong addr, void *v, uint n, int isr)
   937	{
   938		int laddr;
   939		uvlong u;
   940	
   941		if((laddr = go2linux(addr)) < 0){
   942			if(isr){
   943				memset(v, 0, n);
   944				return 0;
   945			}
   946			werrstr("register %llud not available", addr);
   947			return -1;
   948		}
   949	
   950		if(isr){
   951			errno = 0;
   952			u = ptrace(PTRACE_PEEKUSER, map->pid, laddr, 0);
   953			if(errno)
   954				goto ptraceerr;
   955			switch(n){
   956			case 1:
   957				*(uint8*)v = u;
   958				break;
   959			case 2:
   960				*(uint16*)v = u;
   961				break;
   962			case 4:
   963				*(uint32*)v = u;
   964				break;
   965			case 8:
   966				*(uint64*)v = u;
   967				break;
   968			default:
   969				werrstr("bad register size");
   970				return -1;
   971			}
   972		}else{
   973			switch(n){
   974			case 1:
   975				u = *(uint8*)v;
   976				break;
   977			case 2:
   978				u = *(uint16*)v;
   979				break;
   980			case 4:
   981				u = *(uint32*)v;
   982				break;
   983			case 8:
   984				u = *(uint64*)v;
   985				break;
   986			default:
   987				werrstr("bad register size");
   988				return -1;
   989			}
   990			if(ptrace(PTRACE_POKEUSER, map->pid, laddr, (void*)(uintptr)u) < 0)
   991				goto ptraceerr;
   992		}
   993		return 0;
   994	
   995	ptraceerr:
   996		werrstr("ptrace %s register laddr=%d pid=%d n=%d: %r", isr ? "read" : "write", laddr, map->pid, n);
   997		return -1;
   998	}
   999	
  1000	char*
  1001	procstatus(int pid)
  1002	{
  1003		LinuxThread *t;
  1004	
  1005		t = findthread(pid);
  1006		if(t == nil)
  1007			return "???";
  1008	
  1009		return statestr[t->state];
  1010	}

release.r60.3. Except as noted, this content is licensed under a Creative Commons Attribution 3.0 License.