OSDN Git Service

libgo http/cgi: Pass down environment variables for irix and solaris.
[pf3gnuchains/gcc-fork.git] / libgo / syscalls / syscall_linux.go
1 // syscall_linux.go -- GNU/Linux specific syscall interface.
2
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.
6
7 package syscall
8
9 import "unsafe"
10
11 func libc_ptrace(request int, pid Pid_t, addr uintptr, data *byte) _C_long __asm__ ("ptrace")
12
13 var dummy *byte
14 const sizeofPtr uintptr = uintptr(unsafe.Sizeof(dummy))
15
16 func ptracePeek(req int, pid int, addr uintptr, out []byte) (count int, errno int) {
17         // The peek requests are machine-size oriented, so we wrap it
18         // to retrieve arbitrary-length data.
19
20         var buf [sizeofPtr]byte;
21
22         // Leading edge.  PEEKTEXT/PEEKDATA don't require aligned
23         // access (PEEKUSER warns that it might), but if we don't
24         // align our reads, we might straddle an unmapped page
25         // boundary and not get the bytes leading up to the page
26         // boundary.
27         n := 0;
28         if addr % sizeofPtr != 0 {
29                 SetErrno(0);
30                 val := libc_ptrace(req, Pid_t(pid), addr - addr%sizeofPtr, nil);
31                 if errno := GetErrno(); errno != 0 {
32                         return 0, errno;
33                 }
34                 *(*_C_long)(unsafe.Pointer(&buf[0])) = val;
35                 n += copy(out, buf[addr%sizeofPtr:]);
36                 out = out[n:];
37         }
38
39         // Remainder.
40         for len(out) > 0 {
41                 // We use an internal buffer to gaurantee alignment.
42                 // It's not documented if this is necessary, but we're paranoid.
43                 SetErrno(0);
44                 val := libc_ptrace(req, Pid_t(pid), addr+uintptr(n), nil);
45                 if errno = GetErrno(); errno != 0 {
46                         return n, errno;
47                 }
48                 *(*_C_long)(unsafe.Pointer(&buf[0])) = val;
49                 copied := copy(out, buf[0:]);
50                 n += copied;
51                 out = out[copied:];
52         }
53
54         return n, 0;
55 }
56
57 func PtracePeekText(pid int, addr uintptr, out []byte) (count int, errno int) {
58         return ptracePeek(_PTRACE_PEEKTEXT, pid, addr, out);
59 }
60
61 func PtracePeekData(pid int, addr uintptr, out []byte) (count int, errno int) {
62         return ptracePeek(_PTRACE_PEEKDATA, pid, addr, out);
63 }
64
65 func ptracePoke(pokeReq int, peekReq int, pid int, addr uintptr, data []byte) (count int, errno int) {
66         // As for ptracePeek, we need to align our accesses to deal
67         // with the possibility of straddling an invalid page.
68
69         // Leading edge.
70         n := 0;
71         if addr % sizeofPtr != 0 {
72                 var buf [sizeofPtr]byte;
73                 if libc_ptrace(peekReq, Pid_t(pid), addr - addr%sizeofPtr, &buf[0]) < 0 {
74                         return 0, GetErrno();
75                 }
76                 n += copy(buf[addr%sizeofPtr:], data);
77                 word := (*byte)(unsafe.Pointer(*((*uintptr)(unsafe.Pointer(&buf[0])))));
78                 if libc_ptrace(pokeReq, Pid_t(pid), addr - addr%sizeofPtr, word) < 0 {
79                         return 0, GetErrno();
80                 }
81                 data = data[n:len(data)];
82         }
83
84         // Interior.
85         for uintptr(len(data)) > sizeofPtr {
86                 word := (*byte)(unsafe.Pointer(*((*uintptr)(unsafe.Pointer(&data[0])))));
87                 if libc_ptrace(pokeReq, Pid_t(pid), addr+uintptr(n), word) < 0 {
88                         return n, GetErrno();
89                 }
90                 n += int(sizeofPtr);
91                 data = data[sizeofPtr:len(data)];
92         }
93
94         // Trailing edge.
95         if len(data) > 0 {
96                 var buf [sizeofPtr]byte;
97                 if libc_ptrace(peekReq, Pid_t(pid), addr+uintptr(n), &buf[0]) < 0 {
98                         return n, GetErrno();
99                 }
100                 copy(buf[0:], data);
101                 word := (*byte)(unsafe.Pointer(*((*uintptr)(unsafe.Pointer(&buf[0])))));
102                 if libc_ptrace(pokeReq, Pid_t(pid), addr+uintptr(n), word) < 0 {
103                         return n, GetErrno();
104                 }
105                 n += len(data);
106         }
107
108         return n, 0;
109 }
110
111 func PtracePokeText(pid int, addr uintptr, data []byte) (count int, errno int) {
112         return ptracePoke(_PTRACE_POKETEXT, _PTRACE_PEEKTEXT, pid, addr, data);
113 }
114
115 func PtracePokeData(pid int, addr uintptr, data []byte) (count int, errno int) {
116         return ptracePoke(_PTRACE_POKEDATA, _PTRACE_PEEKDATA, pid, addr, data);
117 }
118
119 func PtraceGetRegs(pid int, regsout *PtraceRegs) (errno int) {
120         if libc_ptrace(_PTRACE_GETREGS, Pid_t(pid), 0, (*byte)(unsafe.Pointer(regsout))) < 0 {
121                 return GetErrno();
122         } else {
123                 return 0;
124         }
125 }
126
127 func PtraceSetRegs(pid int, regs *PtraceRegs) (errno int) {
128         if libc_ptrace(_PTRACE_SETREGS, Pid_t(pid), 0, (*byte)(unsafe.Pointer(regs))) < 0 {
129                 return GetErrno();
130         } else {
131                 return 0;
132         }
133 }
134
135 func PtraceSetOptions(pid int, options int) (errno int) {
136         if libc_ptrace(_PTRACE_SETOPTIONS, Pid_t(pid), 0, (*byte)(unsafe.Pointer(uintptr(options)))) < 0 {
137                 return GetErrno();
138         } else {
139                 return 0;
140         }
141 }
142
143 func PtraceGetEventMsg(pid int) (msg uint, errno int) {
144         var data _C_long;
145         if libc_ptrace(_PTRACE_GETEVENTMSG, Pid_t(pid), 0, (*byte)(unsafe.Pointer(&data))) < 0 {
146                 errno = GetErrno();
147         }
148         msg = uint(data);
149         return;
150 }
151
152 func PtraceCont(pid int, signal int) (errno int) {
153         if libc_ptrace(_PTRACE_CONT, Pid_t(pid), 0, (*byte)(unsafe.Pointer(uintptr(signal)))) < 0 {
154                 return GetErrno();
155         } else {
156                 return 0;
157         }
158 }
159
160 func PtraceSingleStep(pid int) (errno int) {
161         if libc_ptrace(_PTRACE_SINGLESTEP, Pid_t(pid), 0, nil) < 0 {
162                 return GetErrno();
163         } else {
164                 return 0;
165         }
166 }
167
168 func PtraceAttach(pid int) (errno int) {
169         if libc_ptrace(_PTRACE_ATTACH, Pid_t(pid), 0, nil) < 0 {
170                 return GetErrno();
171         } else {
172                 return 0;
173         }
174 }
175
176 func PtraceDetach(pid int) (errno int) {
177         if libc_ptrace(_PTRACE_DETACH, Pid_t(pid), 0, nil) < 0 {
178                 return GetErrno();
179         } else {
180                 return 0;
181         }
182 }
183
184 func Tgkill(tgid int, tid int, sig int) (errno int) {
185         r1, r2, err := Syscall(SYS_TGKILL, uintptr(tgid), uintptr(tid),
186                                  uintptr(sig));
187         return int(err);
188 }