2011-10-08 Paul Thomas <pault@gcc.gnu.org>
[official-gcc.git] / libgo / syscalls / syscall_linux.go
blob29c8b62403e4f36e98c36e97510230ca66038a33
1 // syscall_linux.go -- GNU/Linux specific syscall interface.
3 // Copyright 2009 The Go Authors. All rights reserved.
4 // Use of this source code is governed by a BSD-style
5 // license that can be found in the LICENSE file.
7 package syscall
9 import "unsafe"
11 func libc_ptrace(request int, pid Pid_t, addr uintptr, data *byte) _C_long __asm__ ("ptrace")
12 func libc_sendfile(int, int, *Offset_t, Size_t) Ssize_t __asm__ ("sendfile")
14 var dummy *byte
15 const sizeofPtr uintptr = uintptr(unsafe.Sizeof(dummy))
17 func ptracePeek(req int, pid int, addr uintptr, out []byte) (count int, errno int) {
18 // The peek requests are machine-size oriented, so we wrap it
19 // to retrieve arbitrary-length data.
21 var buf [sizeofPtr]byte;
23 // Leading edge. PEEKTEXT/PEEKDATA don't require aligned
24 // access (PEEKUSER warns that it might), but if we don't
25 // align our reads, we might straddle an unmapped page
26 // boundary and not get the bytes leading up to the page
27 // boundary.
28 n := 0;
29 if addr % sizeofPtr != 0 {
30 SetErrno(0);
31 val := libc_ptrace(req, Pid_t(pid), addr - addr%sizeofPtr, nil);
32 if errno := GetErrno(); errno != 0 {
33 return 0, errno;
35 *(*_C_long)(unsafe.Pointer(&buf[0])) = val;
36 n += copy(out, buf[addr%sizeofPtr:]);
37 out = out[n:];
40 // Remainder.
41 for len(out) > 0 {
42 // We use an internal buffer to gaurantee alignment.
43 // It's not documented if this is necessary, but we're paranoid.
44 SetErrno(0);
45 val := libc_ptrace(req, Pid_t(pid), addr+uintptr(n), nil);
46 if errno = GetErrno(); errno != 0 {
47 return n, errno;
49 *(*_C_long)(unsafe.Pointer(&buf[0])) = val;
50 copied := copy(out, buf[0:]);
51 n += copied;
52 out = out[copied:];
55 return n, 0;
58 func PtracePeekText(pid int, addr uintptr, out []byte) (count int, errno int) {
59 return ptracePeek(_PTRACE_PEEKTEXT, pid, addr, out);
62 func PtracePeekData(pid int, addr uintptr, out []byte) (count int, errno int) {
63 return ptracePeek(_PTRACE_PEEKDATA, pid, addr, out);
66 func ptracePoke(pokeReq int, peekReq int, pid int, addr uintptr, data []byte) (count int, errno int) {
67 // As for ptracePeek, we need to align our accesses to deal
68 // with the possibility of straddling an invalid page.
70 // Leading edge.
71 n := 0;
72 if addr % sizeofPtr != 0 {
73 var buf [sizeofPtr]byte;
74 if libc_ptrace(peekReq, Pid_t(pid), addr - addr%sizeofPtr, &buf[0]) < 0 {
75 return 0, GetErrno();
77 n += copy(buf[addr%sizeofPtr:], data);
78 word := (*byte)(unsafe.Pointer(*((*uintptr)(unsafe.Pointer(&buf[0])))));
79 if libc_ptrace(pokeReq, Pid_t(pid), addr - addr%sizeofPtr, word) < 0 {
80 return 0, GetErrno();
82 data = data[n:len(data)];
85 // Interior.
86 for uintptr(len(data)) > sizeofPtr {
87 word := (*byte)(unsafe.Pointer(*((*uintptr)(unsafe.Pointer(&data[0])))));
88 if libc_ptrace(pokeReq, Pid_t(pid), addr+uintptr(n), word) < 0 {
89 return n, GetErrno();
91 n += int(sizeofPtr);
92 data = data[sizeofPtr:len(data)];
95 // Trailing edge.
96 if len(data) > 0 {
97 var buf [sizeofPtr]byte;
98 if libc_ptrace(peekReq, Pid_t(pid), addr+uintptr(n), &buf[0]) < 0 {
99 return n, GetErrno();
101 copy(buf[0:], data);
102 word := (*byte)(unsafe.Pointer(*((*uintptr)(unsafe.Pointer(&buf[0])))));
103 if libc_ptrace(pokeReq, Pid_t(pid), addr+uintptr(n), word) < 0 {
104 return n, GetErrno();
106 n += len(data);
109 return n, 0;
112 func PtracePokeText(pid int, addr uintptr, data []byte) (count int, errno int) {
113 return ptracePoke(_PTRACE_POKETEXT, _PTRACE_PEEKTEXT, pid, addr, data);
116 func PtracePokeData(pid int, addr uintptr, data []byte) (count int, errno int) {
117 return ptracePoke(_PTRACE_POKEDATA, _PTRACE_PEEKDATA, pid, addr, data);
120 func PtraceGetRegs(pid int, regsout *PtraceRegs) (errno int) {
121 if libc_ptrace(_PTRACE_GETREGS, Pid_t(pid), 0, (*byte)(unsafe.Pointer(regsout))) < 0 {
122 return GetErrno();
123 } else {
124 return 0;
128 func PtraceSetRegs(pid int, regs *PtraceRegs) (errno int) {
129 if libc_ptrace(_PTRACE_SETREGS, Pid_t(pid), 0, (*byte)(unsafe.Pointer(regs))) < 0 {
130 return GetErrno();
131 } else {
132 return 0;
136 func PtraceSetOptions(pid int, options int) (errno int) {
137 if libc_ptrace(_PTRACE_SETOPTIONS, Pid_t(pid), 0, (*byte)(unsafe.Pointer(uintptr(options)))) < 0 {
138 return GetErrno();
139 } else {
140 return 0;
144 func PtraceGetEventMsg(pid int) (msg uint, errno int) {
145 var data _C_long;
146 if libc_ptrace(_PTRACE_GETEVENTMSG, Pid_t(pid), 0, (*byte)(unsafe.Pointer(&data))) < 0 {
147 errno = GetErrno();
149 msg = uint(data);
150 return;
153 func PtraceCont(pid int, signal int) (errno int) {
154 if libc_ptrace(_PTRACE_CONT, Pid_t(pid), 0, (*byte)(unsafe.Pointer(uintptr(signal)))) < 0 {
155 return GetErrno();
156 } else {
157 return 0;
161 func PtraceSingleStep(pid int) (errno int) {
162 if libc_ptrace(_PTRACE_SINGLESTEP, Pid_t(pid), 0, nil) < 0 {
163 return GetErrno();
164 } else {
165 return 0;
169 func PtraceAttach(pid int) (errno int) {
170 if libc_ptrace(_PTRACE_ATTACH, Pid_t(pid), 0, nil) < 0 {
171 return GetErrno();
172 } else {
173 return 0;
177 func PtraceDetach(pid int) (errno int) {
178 if libc_ptrace(_PTRACE_DETACH, Pid_t(pid), 0, nil) < 0 {
179 return GetErrno();
180 } else {
181 return 0;
185 func Tgkill(tgid int, tid int, sig int) (errno int) {
186 r1, r2, err := Syscall(SYS_TGKILL, uintptr(tgid), uintptr(tid),
187 uintptr(sig));
188 return int(err);
191 func Sendfile(outfd int, infd int, offset *int64, count int) (written int, errno int) {
192 var o Offset_t
193 var po *Offset_t
194 if offset != nil {
195 o = Offset_t(*offset)
196 po = &o
198 w := libc_sendfile(outfd, infd, po, Size_t(count))
199 if offset != nil {
200 *offset = int64(o)
202 if w < 0 {
203 return 0, GetErrno()
205 return int(w), 0