I have been trying to use -buildmode=plugin but the .so file is too large. It's almost ~1MB for a simple file like
package main
var URI string
func Eval() bool {
return (URI == "Yes")
}
So an experiment I compiled with gccgo instead of go build -buildmode=pluginI ran the command
gccgo -o test.so -fPIC -shared test.go
The file size is really small now almost 16Kb.
The question is can I look up symbols in the above .so file using dlsym? Looks like dlsym retrieves C symbols and not Go symbols. Any way to retrieve, set go symbols?
Update:
nm output
U __gcc_personality_v0
U getenv
U getpagesize
w __gmon_start__
0000000000002eb3 T __go_init_main
U internal..z2fbytealg..types
U internal..z2fcpu..import
U internal..z2fcpu..types
w _ITM_deregisterTMCloneTable
w _ITM_registerTMCloneTable
00000000000022d9 T main.Eval
0000000000006d20 D main.Eval..f
00000000000024bd T main.struct.4runtime.gList.2.runtime.n.0int32.5..eq
0000000000006d28 D main.struct.4runtime.gList.2.runtime.n.0int32.5..eq..f
0000000000002760 T main.struct.4Size.0uint32.2Mallocs.0uint64.2Frees.0uint64.5..eq
0000000000006d30 D main.struct.4Size.0uint32.2Mallocs.0uint64.2Frees.0uint64.5..eq..f
0000000000006d40 D main..types
0000000000007150 D main.URI
U malloc
U memcmp
00000000000000b8 B __morestack_current_segment
0000000000000000 B __morestack_initial_sp
00000000000000c0 B __morestack_segments
U protect
Fn Call:
sym := s
eval, err := h.GetSymbolPointer(sym)
if err != nil {
fmt.Printf("Didn't find it ")
return -1, fmt.Errorf("Unable to find symbol")
}
x := (*func() bool)(eval)
test := (*x)() //Panics here straight away
_ = test
return 0, nil
}
Related
I made a Go fyne project, which works fine with go run ., and builds to Linux as expected with go build ..
However, when I try cross-compiling to windows using env GOOS=windows GOARCH=arm64 go build . it prints this error:
go: downloading github.com/tevino/abool v1.2.0
package playground.com/colors
imports fyne.io/fyne/v2/app
imports fyne.io/fyne/v2/internal/driver/glfw
imports fyne.io/fyne/v2/internal/driver/common
imports fyne.io/fyne/v2/internal/painter/gl
imports github.com/go-gl/gl/v3.1/gles2: build constraints exclude all Go files in /home/mohamed/code/go/pkg/mod/github.com/go-gl/gl#v0.0.0-20211210172815-726fda9656d6/v3.1/gles2
I tried a clean install of Go, tried using go clean -modcache, tried creating a separate new module.
The code for error replication:
package main
import (
"fmt"
"image/color"
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/canvas"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/widget"
)
func main() {
app := app.NewWithID("Color Mixer")
window := app.NewWindow("Color")
red := widget.NewSlider(0, 255)
green := widget.NewSlider(0, 255)
blue := widget.NewSlider(0, 255)
red_value := widget.NewLabel("0")
green_value := widget.NewLabel("0")
blue_value := widget.NewLabel("0")
red_label := widget.NewLabel("Red")
green_label := widget.NewLabel("Green")
blue_label := widget.NewLabel("Blue")
colorx := color.NRGBA{R: 0, G: 0, B: 0, A: 255}
rect := canvas.NewRectangle(colorx)
rect.SetMinSize(fyne.NewSize(300, 300))
red.OnChanged =
func(f float64) {
_, g, b, a := rect.FillColor.RGBA()
rect.FillColor = color.NRGBA{R: uint8(f),
G: uint8(g),
B: uint8(b),
A: uint8(a)}
rect.Refresh()
red_value.SetText(fmt.Sprintf("%.0f", f))
}
green.OnChanged =
func(f float64) {
r, _, b, a := rect.FillColor.RGBA()
rect.FillColor = color.NRGBA{R: uint8(r),
G: uint8(f),
B: uint8(b),
A: uint8(a)}
rect.Refresh()
green_value.SetText(fmt.Sprintf("%.0f", f))
}
blue.OnChanged =
func(f float64) {
r, g, _, a := rect.FillColor.RGBA()
rect.FillColor = color.NRGBA{R: uint8(r),
G: uint8(g),
B: uint8(f),
A: uint8(a)}
rect.Refresh()
blue_value.SetText(fmt.Sprintf("%.0f", f))
}
box := container.NewGridWithRows(
2,
container.NewGridWithRows(3, red_label, green_label, blue_label, red, green, blue, red_value, green_value, blue_value),
rect)
window.SetContent(box)
window.ShowAndRun()
}
IIRC, cross-compilation by default disables cgo, and since all the files in that github.com/go-gl/gl/v3.1/gles2 package make use of it, the building process naturally excludes them all, and produces the error you're seeing.
Hence try building while having CGO_ENABLED=1 in your environment.
A simple
CGO_ENABLED=1 GOOS=windows go build
should do the trick.
Note that in order for the build process to actually produce the expected outcome you need to have the C cross-compiler for your target GOOS/GOARCH combo installed, and probably communicated to the go tool via setting the CC environment variable—see the docs.
For instance, on Debian and its derivatives you will probably need to have the following packages installed:
gcc-mingw-w64-x86-64-win32 — for building for windows/amd64.
gcc-mingw-w64-i686-win32 — for building for windows/386.
The values to set the CC variable will be /usr/bin/i686-w64-mingw32-gcc and /usr/bin/x86_64-w64-mingw32-gcc, correspondingly.
I have no idea whether there's a MinGW cross-compiler package to target windows/arm64 which you seem to require, though, as I have zero experience with Windows on ARM devices.
Also note that in order to produce a sensible Windows executable image file while cross-compiling you will probably want to also have CGO_LDFLAGS=-static-libgcc in your environment as well—this will produce a binary not dependent on libgcc.dll, and maybe you will even want to have CGO_LDFLAGS=-static-libgcc -static to have a fully-static build.
The previous answer is correct. However you may like to use the “fyne package” command or fyne-cross - these tools aim to avoid all the manual setup.
hello i am new to static analysis and try to use golang's SSA package to analyze our code. For example i want to print all function infos in the package, the example code is:
dir := PROJECT_PATH
cfg := packages.Config{
Mode: packages.LoadAllSyntax,
Dir: dir,
}
initial, _ := packages.Load(&cfg, "./")
// Create SSA packages for well-typed packages and their dependencies.
prog, _ := ssautil.AllPackages(initial, 0)
// Build SSA code for the whole program.
prog.Build()
callGraph = cha.CallGraph(prog)
for f, node := range callGraph.Nodes{
// f is of ssa.Function
fmt.Println("func:", f, f.Name(), f.Syntax(), f.Params)
}
then i found i have no way to access the type of return values for this function (refering to the documents https://pkg.go.dev/golang.org/x/tools/go/ssa#Function)
Is there any way to analyze the type of function's return value by using ssa tools or other tools?
You can get the signature and therefore return type of a function via
f.Signature.Results()
If you don't need callgraph traversal you can directly get function info from ssa.package struct
for k, v := range pckg.Members {
c, ok := v.(*ssa.Function)
if ok{
...
}
}
package main
import (
"fmt"
)
func main() {
a := new(struct{})
b := new(struct{})
println(a, b, a==b)
c := new(struct{})
d := new(struct{})
fmt.Println(c, d, c==d)
}
output:
0xc000107f37 0xc000107f37 false
&{} &{} true
And, I will get different results after disabling compiler optimization.
0xc000087e4e 0xc000087e4e true
&{} &{} true
Why does the Go compiler do this optimization?
See [this line in the runtime source code ]
(https://github.com/golang/go/blob/6317adeed7815ad335e2e97c463a7c3c4d82fc19/src/runtime/malloc.go#L586)
if size == 0 {
return unsafe.Pointer(&zerobase)
}
I think that since all zero-size variables will be allocated with zerobase, it should print true instead of false.
Is it possibile to obtain a reference to an Interface Value without
reccurring to reflection? If not, why not?
I have attempted:
package foo
type Foo struct {
a, b int
}
func f(x interface{}) {
var foo *Foo = &x.(Foo)
foo.a = 2
}
func g(foo Foo) {
f(foo)
}
but it fails with:
./test.go:8: cannot take the address of x.(Foo)
To clear your doubts if you go by the meaning Assert
state a fact or belief confidently and forcefully
in your example x.(Foo) is just a type assertion it's not a object so you can not get its address.
so at runtime when the object will be created for example
var c interface{} = 5
d := c.(int)
fmt.Println("Hello", c, d) // Hello 5 5
it only assert that
asserts that c is not nil and that the value stored in c is of type int
So its not any physical entity in memory but at runtime d will be allocated memory based on asserted type and than the contents of c will be copied into that location.
So you can do something like
var c interface{} = 5
d := &c
fmt.Println("Hello", (*d).(int)) // hello 5
Hope i cleared your confusion.
I'm trying to use Go's flag package to dynamically generate FlagSets and collect the results in a map from flagname -> flag value.
My code looks like this:
import "flag"
fs := flag.NewFlagSet(strings.Join(commands, " "), flag.ExitOnError)
requiredFlags := []string{"flagA", "flagB"}
flags := make(map[string]string)
for _, f := range requiredFlags {
flags[f] = *fs.String(f, "", "")
}
This code compiles, but the map never gets updated after the FlagSet fs is parsed, so the values of "flagA" and "flagB" are both "". So this makes sense to me; flags is of type map[string]string after all, not map[string]*string. Unfortunately, I can't seem to fix this problem using pointers. I've tried every combination of referencing and dereferencing I can think of and I either end up with a nil pointer dereference (runtime error) or invalid indirect (compile time error).
How can I set up the map and FlagSet such that the map values are populated after the FlagSet is parsed?
What is wrong with
flags := make(map[string]*string)
for _, f := range requiredFlags {
flags[f] = fs.String(f, "", "")
}
...
println(*(flags["flagA"]))
?