Skip to content

Commit bcf7dea

Browse files
committed
Read from proc to fill environment and argv if using musl/uclinux
1 parent 819d36a commit bcf7dea

File tree

2 files changed

+146
-18
lines changed

2 files changed

+146
-18
lines changed

src/runtime/os_linux.go

+3-16
Original file line numberDiff line numberDiff line change
@@ -216,8 +216,6 @@ var addrspace_vec [1]byte
216216
func mincore(addr unsafe.Pointer, n uintptr, dst *byte) int32
217217

218218
func sysargs(argc int32, argv **byte) {
219-
n := argc + 1
220-
221219
argsValid := true
222220
if islibrary || isarchive {
223221
if !sysLibArgsValid() {
@@ -226,6 +224,8 @@ func sysargs(argc int32, argv **byte) {
226224
}
227225

228226
if argsValid {
227+
n := argc + 1
228+
229229
// skip over argv, envp to get to auxv
230230
for argv_index(argv, n) != nil {
231231
n++
@@ -239,19 +239,6 @@ func sysargs(argc int32, argv **byte) {
239239
if sysauxv(auxv[:]) != 0 {
240240
return
241241
}
242-
} else {
243-
args := unsafe.Pointer(persistentalloc(goarch.PtrSize*4, 0, &memstats.other_sys))
244-
// argv pointer
245-
*(**byte)(args) = (*byte)(add(args, goarch.PtrSize*1))
246-
// argv data
247-
*(**byte)(add(args, goarch.PtrSize*1)) = (*byte)(nil) // end argv TODO: READ FROM /proc/
248-
*(**byte)(add(args, goarch.PtrSize*2)) = (*byte)(nil) // end envp TODO: READ FROM /proc/
249-
*(**byte)(add(args, goarch.PtrSize*3)) = (*byte)(nil) // end auxv TODO: READ FROM /proc/
250-
argc = 0
251-
argv = (**byte)(args)
252-
253-
// argc = 0
254-
// argv = (**byte)(&[3]*byte{nil, nil, nil})
255242
}
256243

257244
// In some situations we don't get a loader-provided
@@ -282,7 +269,7 @@ func sysargs(argc int32, argv **byte) {
282269
return
283270
}
284271
var buf [128]uintptr
285-
n = read(fd, noescape(unsafe.Pointer(&buf[0])), int32(unsafe.Sizeof(buf)))
272+
n := read(fd, noescape(unsafe.Pointer(&buf[0])), int32(unsafe.Sizeof(buf)))
286273
closefd(fd)
287274
if n < 0 {
288275
return

src/runtime/runtime1.go

+143-2
Original file line numberDiff line numberDiff line change
@@ -76,9 +76,150 @@ func argv_index(argv **byte, i int32) *byte {
7676
return *(**byte)(add(unsafe.Pointer(argv), uintptr(i)*goarch.PtrSize))
7777
}
7878

79+
// when using -buildmode=c-archive or -buildmode=c-shared on linux
80+
// we have to first make sure that glibc is being used or else
81+
// we cannot rely on argc/argv/auxv to be accurate
82+
func sysLibArgsValid() bool {
83+
if _cgo_sys_lib_args_valid != nil {
84+
ret := asmcgocall(_cgo_sys_lib_args_valid, nil)
85+
if ret != 1 {
86+
return false
87+
}
88+
}
89+
return true
90+
}
91+
92+
var procCmdline = []byte("/proc/self/cmdline\x00")
93+
var procEnviron = []byte("/proc/self/environ\x00")
94+
7995
func args(c int32, v **byte) {
80-
argc = c
81-
argv = v
96+
if sysLibArgsValid() {
97+
argc = c
98+
argv = v
99+
} else if GOOS == "linux" {
100+
argc = 0
101+
argv = nil
102+
103+
// get argc and argv size
104+
var argvSize int32 = 0
105+
fd := open(&procCmdline[0], 0 /* O_RDONLY */, 0)
106+
if fd >= 0 {
107+
for {
108+
var buf [128]byte
109+
c := read(fd, noescape(unsafe.Pointer(&buf[0])), int32(unsafe.Sizeof(buf)))
110+
if c <= 0 {
111+
break
112+
}
113+
114+
argvSize += c
115+
116+
i := c
117+
for i = 0; i < c; i++ {
118+
if buf[i] == 0 {
119+
argc++
120+
}
121+
}
122+
}
123+
124+
closefd(fd)
125+
}
126+
127+
var environSize int32 = 0
128+
var envc int32 = 0
129+
fd = open(&procEnviron[0], 0 /* O_RDONLY */, 0)
130+
if fd >= 0 {
131+
for {
132+
var buf [128]byte
133+
c := read(fd, noescape(unsafe.Pointer(&buf[0])), int32(unsafe.Sizeof(buf)))
134+
if c <= 0 {
135+
break
136+
}
137+
138+
environSize += c
139+
140+
i := c
141+
for i = 0; i < c; i++ {
142+
if buf[i] == 0 {
143+
envc++
144+
}
145+
}
146+
}
147+
148+
closefd(fd)
149+
}
150+
151+
argv = (**byte)(unsafe.Pointer(persistentalloc(goarch.PtrSize*(uintptr(argc)+uintptr(envc)+1), 0, &memstats.other_sys)))
152+
argvPtr := (**byte)(add(unsafe.Pointer(argv), goarch.PtrSize*(uintptr(argc)+uintptr(envc)+1)))
153+
*argvPtr = (*byte)(nil) //null terminate array
154+
155+
if argvSize > 0 {
156+
argvBuf := unsafe.Pointer(persistentalloc(uintptr(argvSize), 0, &memstats.other_sys))
157+
fd := open(&procCmdline[0], 0 /* O_RDONLY */, 0)
158+
if fd >= 0 {
159+
c := read(fd, noescape(argvBuf), int32(argvSize))
160+
if c < 0 {
161+
throw("failed to read arguments")
162+
return
163+
}
164+
165+
if c != int32(argvSize) {
166+
throw("short read arguments")
167+
return
168+
}
169+
170+
strStart := int32(0)
171+
strNum := 0
172+
173+
i := c
174+
var b *byte
175+
for i = 0; i < c; i++ {
176+
b = (*byte)(add(argvBuf, uintptr(i)))
177+
if *b == 0 {
178+
argvPtr := (**byte)(add(unsafe.Pointer(argv), goarch.PtrSize*uintptr(strNum)))
179+
*argvPtr = (*byte)(add(argvBuf, uintptr(strStart)))
180+
strStart = i + 1
181+
strNum++
182+
}
183+
}
184+
185+
closefd(fd)
186+
}
187+
}
188+
189+
if environSize > 0 {
190+
environBuf := unsafe.Pointer(persistentalloc(uintptr(environSize), 0, &memstats.other_sys))
191+
fd := open(&procEnviron[0], 0 /* O_RDONLY */, 0)
192+
if fd >= 0 {
193+
c := read(fd, noescape(environBuf), int32(environSize))
194+
if c < 0 {
195+
throw("failed to read environment")
196+
return
197+
}
198+
199+
if c != int32(environSize) {
200+
throw("short read environment")
201+
return
202+
}
203+
204+
strStart := int32(0)
205+
strNum := 0
206+
207+
i := c
208+
var b *byte
209+
for i = 0; i < c; i++ {
210+
b = (*byte)(add(environBuf, uintptr(i)))
211+
if *b == 0 {
212+
argvPtr := (**byte)(add(unsafe.Pointer(argv), goarch.PtrSize*(uintptr(argc)+uintptr(strNum))))
213+
*argvPtr = (*byte)(add(environBuf, uintptr(strStart)))
214+
strStart = i + 1
215+
strNum++
216+
}
217+
}
218+
219+
closefd(fd)
220+
}
221+
}
222+
}
82223
sysargs(c, v)
83224
}
84225

0 commit comments

Comments
 (0)