Discussion:
[go-nuts] sys package changes lead to some undocumented, darker corners of Go
s***@oracle.com
2015-07-30 22:24:40 UTC
Permalink
Greetings,

I have a number of fixes I need to make to the Solaris port of the sys
package. As part of the changes for Go 1.5, the Solaris port of Go now has
full support for cgo, et al.

I noticed that the internal packages in Go, such as syscall, do something
like this to get access to the function addresses:

//go:cgo_import_dynamic libc_Getpgid getpgid "libc.so"
//go:linkname libc_Getpgid libc_Getpgid

var (
libc_Getpgid
)

...and then something like this to actually call them:

r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&libc_Getpgid)), 1,
uintptr(pid), 0, 0, 0, 0, 0)

I couldn't find any documentation on cgo_import_dynamic or the linkname
directives. Are these only intended for use within the Go "core"
packages? Is "sys" one of those packages?

Of course, searching through the source led me to the relevant lexer code:


https://github.com/golang/go/blob/75d779566b75fc1a09239bfbca40b6dba42000fd/src/cmd/compile/internal/gc/lex.go#L1729

...but that's not particularly enlightening either.

Is cgo_import_dynamic just a historical name for the documented
"-dynlinker" option cgo has?

What exactly is linkname for; just a convenient way to bind the address of
a function to a variable?

Next, when should a package use sysvicall6() or the like instead of just
calling the function?

Finally, why do those packages use that syntax instead of the documented
cgo syntax of:

//#include <someheaderfile.h>
import "C"

C.libc_Getpgid(...)

?

-Shawn
--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+***@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Ian Lance Taylor
2015-07-30 23:01:16 UTC
Permalink
This post might be inappropriate. Click to display it.
s***@oracle.com
2015-07-30 23:20:10 UTC
Permalink
Post by s***@oracle.com
Post by s***@oracle.com
I noticed that the internal packages in Go, such as syscall, do
something
Post by s***@oracle.com
//go:cgo_import_dynamic libc_Getpgid getpgid "libc.so"
//go:linkname libc_Getpgid libc_Getpgid
var (
libc_Getpgid
)
r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&libc_Getpgid)), 1,
uintptr(pid), 0, 0, 0, 0, 0)
Note that it's really only the Solaris port that does this. The other
ports make direct system calls, but the Solaris port makes dynamic
calls through libc.so. I can't recall why the Solaris port works this
way.
That part I can answer; the syscall layer on Solaris is not a stable
interface. All programs are supposed go through libc instead, which should
be fine.
Post by s***@oracle.com
Post by s***@oracle.com
I couldn't find any documentation on cgo_import_dynamic or the linkname
directives. Are these only intended for use within the Go "core"
packages?
Post by s***@oracle.com
Is "sys" one of those packages?
The go:cgo_import_dynamic comment is documented in a long
"Implementation details" comment in cmd/cgo/doc.go. I don't think
there is any godoc-visible documentation on it. There is nothing
prevent ordinary code from using it, but it's really intended for code
generated by the cgo tool.
The go:linkname comment is documented at
http://tip.golang.org/cmd/compile . As documented there, it can be
used by any file that does import "unsafe".
Thanks, I missed that.

...
Post by s***@oracle.com
Post by s***@oracle.com
Next, when should a package use sysvicall6() or the like instead of just
calling the function?
The sysvicall6 function is Solaris-specific. It's defined in
runtime/os_solaris.go. My understanding is that it exists to call a
function using the standard amd64 ABI, rather than then Go-specific
ABI which is quite different. So, you should use sysvicall6 when
directly calling a function that is written in C rather than Go. But
you should only play this kind of game in the runtime package; for
ordinary calls to C function, use the cgo tool.
So if I understand correctly, for anything within the Go "core" source code
itself (i.e. runtime), sysivcall6 is the preferred method?

However, if I were to make changes to the "sys" package or some other
package for Solaris, I should be using the "standard" syntax documented for
cgo usage?

e.g.:

import "C"

C.function()

?
Post by s***@oracle.com
Post by s***@oracle.com
Finally, why do those packages use that syntax instead of the documented
cgo
Post by s***@oracle.com
//#include <someheaderfile.h>
import "C"
C.libc_Getpgid(...)
?
The cgo package uses the runtime and syscall packages, so those
packages can not themselves use the cgo tool.
Right, silly of me.

Thanks,
-Shawn
--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+***@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Ian Lance Taylor
2015-07-30 23:24:30 UTC
Permalink
Post by s***@oracle.com
Post by Ian Lance Taylor
Post by s***@oracle.com
Next, when should a package use sysvicall6() or the like instead of just
calling the function?
The sysvicall6 function is Solaris-specific. It's defined in
runtime/os_solaris.go. My understanding is that it exists to call a
function using the standard amd64 ABI, rather than then Go-specific
ABI which is quite different. So, you should use sysvicall6 when
directly calling a function that is written in C rather than Go. But
you should only play this kind of game in the runtime package; for
ordinary calls to C function, use the cgo tool.
So if I understand correctly, for anything within the Go "core" source code
itself (i.e. runtime), sysivcall6 is the preferred method?
Not merely preferred, but the only method that will work.
Post by s***@oracle.com
However, if I were to make changes to the "sys" package or some other
package for Solaris, I should be using the "standard" syntax documented for
cgo usage?
import "C"
C.function()
?
Yes.

Ian
--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+***@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Loading...