GoLLVM: using the result of `go build -x . ` to rebuild the program got failed

125 views
Skip to first unread message

Qingwei Li

unread,
Oct 27, 2022, 12:05:49 PM10/27/22
to golang-nuts
the GoLLVM is based on LLVM 15.0.0

Example to reproduce:
The structure of project is as follows:

```
easyPkg/
├── go.mod
├── main.go
└── Pkg
    └── utils.go
```

main.go

```
package main

import "easyPkg/Pkg"

func main() {
    Pkg.PkgFunc()
}
```

utils.go

```
package Pkg

func PkgFunc() {
    println("pkgFunc")
}
```

go.mod

```
module easyPkg

go 1.18
```

use `go build -x . 2> auto.sh` to get the building process. Then delete the generated binary file `easyPkg` and use `go clean -cache` to clean the building cache. Then I use the command `source auto.sh` to regenerate the binary, which fails.

part of the error log is as follows

```
/data/mygo/gollvm_workarea/install/bin/llvm-goc: error: unrecognized command line option '-fgo-importcfg=/dev/null'
/data/mygo/gollvm_workarea/install/bin/llvm-goc: error: unrecognized command line option '-ffile-prefix-map=a=b'
./main.go:3:19: error: /tmp/go-build3415416681/b001/_importcfgroot_/easyPkg/libPkg.a exists but does not contain any Go export data
./main.go:3:19: warning: easyPkg/Pkg: Not a directory
./main.go:3:19: error: import file 'easyPkg/Pkg' not found
./main.go:6:2: error: reference to undefined name 'Pkg'
/usr/bin/ld.gold: error: /tmp/go-build3415416681/b001/_pkg_.a: member at 72 is not an ELF object
/usr/bin/ld.gold: error: /tmp/go-build3415416681/b002/_pkg_.a: member at 72 is not an ELF object
buildid: open /tmp/go-build3415416681/b001/exe/a.out: no such file or directory
```

what can I do on the auto.sh script to regenerate the binary file? Is the process dumped completed?

On a single package with no subdirectory, the result of `go build -x .` is available for regenerating the binary file.

Moreover, my main purpose is to add -emit-llvm option wherever `llvm-goc` appears and use `llvm-link -S` to link all object files generated by llvm-goc to get a whole LLVM IR file for the whole project. If the question above is now insoluble, is there any other way to get the whole project's LLVM IR?


Than McIntosh

unread,
Oct 27, 2022, 12:11:27 PM10/27/22
to Qingwei Li, golang-nuts
>/data/mygo/gollvm_workarea/install/bin/llvm-goc: error: unrecognized command line option '-fgo-importcfg=/dev/null'

The Go command only passes this option to the compiler if it thinks that the compiler is the main go compiler ("gc") as opposed to gollvm. What output do you get when you run "go version" ?

Thanks, Than


--
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.
To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/b120de38-d603-4a8d-a029-34351abc051cn%40googlegroups.com.

Ian Lance Taylor

unread,
Oct 27, 2022, 12:55:03 PM10/27/22
to Than McIntosh, Qingwei Li, golang-nuts
On Thu, Oct 27, 2022 at 9:11 AM 'Than McIntosh' via golang-nuts
<golan...@googlegroups.com> wrote:
>
> >/data/mygo/gollvm_workarea/install/bin/llvm-goc: error: unrecognized command line option '-fgo-importcfg=/dev/null'
>
> The Go command only passes this option to the compiler if it thinks that the compiler is the main go compiler ("gc") as opposed to gollvm. What output do you get when you run "go version" ?

The code is testing whether the compiler supports that option. The
errors about -fgo-importcfg and -ffile-prefix-map can be ignored.

Not sure what is happening elsewhere, though. You showed the output
but not the commands.

Ian
> To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/CA%2BUr55ENsDS_zpp0TCeyJDfh7jO%2B%3DQOcrfNs1zxqNBYjpPPvDw%40mail.gmail.com.

Than McIntosh

unread,
Oct 27, 2022, 12:58:10 PM10/27/22
to Ian Lance Taylor, Qingwei Li, golang-nuts
Right, sorry, I stand corrected (my "gc" theory was not correct).

Thanks, Than

Qingwei Li

unread,
Oct 27, 2022, 9:46:24 PM10/27/22
to golang-nuts
go version go1.18 gollvm LLVM 15.0.0git 20220823 (experimental) linux/amd64

I might have replied to you only, because the post is not shown on the discussion.

Qingwei Li

unread,
Oct 27, 2022, 10:04:48 PM10/27/22
to golang-nuts
commands I executed are as follows. 

```bash
go build -x . 2> auto.sh  # get the building process
rm easyPkg # remove the binary file
go clean -cache # clean the cache for rebuilding
source auto.sh # rebuild
```

the llvm-project is built by following instructions in section "On Unix-like Systems > Build LLVM and Clang:" in https://clang.llvm.org/get_started.html
and replace "Unix Makefiles" with "Ninja" and "make" with "ninja"

LLVM version is 15.0.0

gollvm version is

```
go version go1.18 gollvm LLVM 15.0.0git 20220823 (experimental) linux/amd64
```

Ian Lance Taylor

unread,
Oct 28, 2022, 2:17:46 AM10/28/22
to Qingwei Li, golang-nuts
Thanks.  What I meant was that you showed us the errors from the generated shell script, but you didn't show us the commands being run by the shell script that generated those errors.  Trying running the script with the -x option.

Ian

Qingwei Li

unread,
Oct 28, 2022, 5:53:54 AM10/28/22
to golang-nuts
when I copy the project to another directory and rerun commands I mentioned above, I get correct binary. 

I think the problem is `ln -s _pkg_.a libPkg.a`. 

The process was that I made an incomplete archive libPkg.a following the shell script but I didn't use _buildid.o file as argument when using `ar rcD ...` to build the archive. After that, whenever I executed the shell script, the shell prompted `error: /tmp/go-build3415416681/b001/_importcfgroot_/easyPkg/libPkg.a exists but does not contain any Go export data`. I think it's because the `ln` tool failed to link the libPkg.a archieve file but the compiler just ignored the error and used the existing ligPkg.a, which I made by hand and didn't have some information the following tool needed. Then errors occur.

The shell script is as follows, but I think my problem has been solved.

Thanks for your help!!! 

```bash
WORK=/tmp/go-build3031634242
mkdir -p $WORK/b002/
cd $WORK
/data/mygo/gollvm_workarea/install/bin/llvm-goc -fgo-importcfg=/dev/null -c -x c - -o /dev/null || true
/data/mygo/gollvm_workarea/install/bin/llvm-goc -ffile-prefix-map=a=b -c -x c - -o /dev/null || true
cd /home/lqw/easyPkg/Pkg
/data/mygo/gollvm_workarea/install/bin/llvm-goc -c -O2 -g -m64 -fdebug-prefix-map=$WORK=/tmp/go-build -gno-record-gcc-switches -fgo-pkgpath=easyPkg/Pkg -o $WORK/b002/_go_.o -I $WORK/b002/_importcfgroot_ ./utils.go
echo '  .section .go.buildid,"e"' >> $WORK/b002/_buildid.s
echo '  .byte 0x58,0x63,0x75,0x74,0x74,0x43,0x71,0x46' >> $WORK/b002/_buildid.s
echo '  .byte 0x36,0x2d,0x77,0x48,0x67,0x50,0x64,0x36' >> $WORK/b002/_buildid.s
echo '  .byte 0x77,0x57,0x44,0x45,0x2f,0x58,0x63,0x75' >> $WORK/b002/_buildid.s
echo '  .byte 0x74,0x74,0x43,0x71,0x46,0x36,0x2d,0x77' >> $WORK/b002/_buildid.s
echo '  .byte 0x48,0x67,0x50,0x64,0x36,0x77,0x57,0x44' >> $WORK/b002/_buildid.s
echo '  .byte 0x45' >> $WORK/b002/_buildid.s
echo '  .section .note.GNU-stack,"",@progbits' >> $WORK/b002/_buildid.s
echo '  .section .note.GNU-split-stack,"",@progbits' >> $WORK/b002/_buildid.s
echo '' >> $WORK/b002/_buildid.s
/data/mygo/gollvm_workarea/install/bin/llvm-goc -xassembler-with-cpp -I $WORK/b002/ -c -o $WORK/b002/_buildid.o -D GOOS_linux -D GOARCH_amd64 -D GOPKGPATH=easyPkg_1Pkg -m64 $WORK/b002/_buildid.s
ar rcD $WORK/b002/_pkg_.a $WORK/b002/_go_.o $WORK/b002/_buildid.o
/data/mygo/gollvm_workarea/install/tools/buildid -w $WORK/b002/_pkg_.a # internal
cp $WORK/b002/_pkg_.a /home/lqw/.cache/go-build/99/99c687f035658ebacf01fe0034d140a1c9e79ce207f0efd169fcbe0d4f23634d-d # internal
mkdir -p $WORK/b001/
cat >$WORK/b001/_gomod_.go << 'EOF' # internal
package main
import _ "unsafe"
//go:linkname __set_debug_modinfo__ runtime.setmodinfo
func __set_debug_modinfo__(string)
func init() { __set_debug_modinfo__("0w\xaf\f\x92t\b\x02A\xe1\xc1\a\xe6\xd6\x18\xe6path\teasyPkg\nmod\teasyPkg\t(devel)\t\nbuild\t-compiler=gccgo\nbuild\tCGO_ENABLED=1\nbuild\tCGO_CFLAGS=\nbuild\tCGO_CPPFLAGS=\nbuild\tCGO_CXXFLAGS=\nbuild\tCGO_LDFLAGS=\nbuild\tGOARCH=amd64\nbuild\tGOEXPERIMENT=fieldtrack\nbuild\tGOOS=linux\nbuild\tGOAMD64=v1\n\xf92C1\x86\x18 r\x00\x82B\x10A\x16\xd8\xf2") }
EOF
mkdir -p $WORK/b001/_importcfgroot_/easyPkg
ln -s $WORK/b002/_pkg_.a $WORK/b001/_importcfgroot_/easyPkg/libPkg.a
cd /home/lqw/easyPkg
/data/mygo/gollvm_workarea/install/bin/llvm-goc -c -O2 -g -m64 -fdebug-prefix-map=$WORK=/tmp/go-build -gno-record-gcc-switches -o $WORK/b001/_go_.o -I $WORK/b001/_importcfgroot_ ./main.go $WORK/b001/_gomod_.go
echo '  .section .go.buildid,"e"' >> $WORK/b001/_buildid.s
echo '  .byte 0x62,0x6c,0x7a,0x44,0x45,0x34,0x43,0x38' >> $WORK/b001/_buildid.s
echo '  .byte 0x56,0x42,0x6a,0x4e,0x6a,0x74,0x4e,0x68' >> $WORK/b001/_buildid.s
echo '  .byte 0x66,0x71,0x4b,0x56,0x2f,0x62,0x6c,0x7a' >> $WORK/b001/_buildid.s
echo '  .byte 0x44,0x45,0x34,0x43,0x38,0x56,0x42,0x6a' >> $WORK/b001/_buildid.s
echo '  .byte 0x4e,0x6a,0x74,0x4e,0x68,0x66,0x71,0x4b' >> $WORK/b001/_buildid.s
echo '  .byte 0x56' >> $WORK/b001/_buildid.s
echo '  .section .note.GNU-stack,"",@progbits' >> $WORK/b001/_buildid.s
echo '  .section .note.GNU-split-stack,"",@progbits' >> $WORK/b001/_buildid.s
echo '' >> $WORK/b001/_buildid.s
/data/mygo/gollvm_workarea/install/bin/llvm-goc -xassembler-with-cpp -I $WORK/b001/ -c -o $WORK/b001/_buildid.o -D GOOS_linux -D GOARCH_amd64 -m64 $WORK/b001/_buildid.s
ar rcD $WORK/b001/_pkg_.a $WORK/b001/_go_.o $WORK/b001/_buildid.o
/data/mygo/gollvm_workarea/install/tools/buildid -w $WORK/b001/_pkg_.a # internal
cp $WORK/b001/_pkg_.a /home/lqw/.cache/go-build/db/dbe11e7450e893503846799700cb9d0005a545c180087da01751b0ba8586d06d-d # internal
cat >$WORK/b001/importcfg.link << 'EOF' # internal
packagefile easyPkg=$WORK/b001/_pkg_.a
packagefile easyPkg/Pkg=$WORK/b002/_pkg_.a
modinfo "0w\xaf\f\x92t\b\x02A\xe1\xc1\a\xe6\xd6\x18\xe6path\teasyPkg\nmod\teasyPkg\t(devel)\t\nbuild\t-compiler=gccgo\nbuild\tCGO_ENABLED=1\nbuild\tCGO_CFLAGS=\nbuild\tCGO_CPPFLAGS=\nbuild\tCGO_CXXFLAGS=\nbuild\tCGO_LDFLAGS=\nbuild\tGOARCH=amd64\nbuild\tGOEXPERIMENT=fieldtrack\nbuild\tGOOS=linux\nbuild\tGOAMD64=v1\n\xf92C1\x86\x18 r\x00\x82B\x10A\x16\xd8\xf2"
EOF
mkdir -p $WORK/b001/exe/
cd .
/data/mygo/gollvm_workarea/install/bin/llvm-goc -o $WORK/b001/exe/a.out "-Wl,-(" -m64 -Wl,--whole-archive $WORK/b001/_pkg_.a $WORK/b002/_pkg_.a -Wl,--no-whole-archive "-Wl,-)" -Wl,--build-id=0x6b376a38547962446f5337585f526e576b335a452f626c7a444534433856426a4e6a744e6866714b562f586d4a7278396231457475304f2d6e6b72326a742f6b376a38547962446f5337585f526e576b335a45
/data/mygo/gollvm_workarea/install/tools/buildid -w $WORK/b001/exe/a.out # internal
cp $WORK/b001/exe/a.out easyPkg
rm -r $WORK/b001/
```

Qingwei Li

unread,
Nov 1, 2022, 2:44:11 AM11/1/22
to golang-nuts
sorry, I get into trouble again. The shell script shown in this [post](https://groups.google.com/g/golang-nuts/c/pTX6ZtV0Uq4/m/iDz7u78_CAAJ)  is actually what the `go build -x . 2> auto.sh` generate. But what I want is adding `-emit-llvm` when using `llvm-goc -c` to build source files.

the shell script I need is 

```bash
WORK=/tmp/go-build3031634242
mkdir -p $WORK/b002/
cd $WORK
/data/mygo/gollvm_workarea/install/bin/llvm-goc -fgo-importcfg=/dev/null -c -x c - -o /dev/null || true
/data/mygo/gollvm_workarea/install/bin/llvm-goc -ffile-prefix-map=a=b -c -x c - -o /dev/null || true
cd /home/lqw/easyPkg/Pkg
/data/mygo/gollvm_workarea/install/bin/llvm-goc -c -emit-llvm -O2 -g -m64 -fdebug-prefix-map=$WORK=/tmp/go-build -gno-record-gcc-switches -fgo-pkgpath=easyPkg/Pkg -o $WORK/b002/_go_.o -I $WORK/b002/_importcfgroot_ ./utils.go
/data/mygo/gollvm_workarea/install/bin/llvm-goc -c -emit-llvm -O2 -g -m64 -fdebug-prefix-map=$WORK=/tmp/go-build -gno-record-gcc-switches -o $WORK/b001/_go_.o -I $WORK/b001/_importcfgroot_ ./main.go $WORK/b001/_gomod_.go
llvm-link -S $WORK/b002/_go_.o $WORK/b001/_go_.o -o /home/lqw/easyPkg/main.ll
```

The modified part of script is using llvm-goc `-c` option to compile `utils.go, main.go` to object files with option `-emit-llvm` added for llvm-link's final linking of all object files. 

After I get `$WORK/b001/_go_.o`, I use llvm-link to link all _go_.o to get a whole program llvm IR. But errors occur when executing `/data/mygo/gollvm_workarea/install/bin/llvm-goc -c -emit-llvm -O2 -g -m64 -fdebug-prefix-map=$WORK=/tmp/go-build -gno-record-gcc-switches -o $WORK/b001/_go_.o -I $WORK/b001/_importcfgroot_ ./main.go $WORK/b001/_gomod_.go`. The error is as follows.

```
./main.go:3:19: error: /tmp/go-build3930504361/b001/_importcfgroot_/easyPkg/libPkg.a exists but does not contain any Go export data

./main.go:3:19: warning: easyPkg/Pkg: Not a directory
./main.go:3:19: error: import file 'easyPkg/Pkg' not found
./main.go:6:2: error: reference to undefined name 'Pkg'
```

I succeeded to generate a whole program llvm IR last weekend, but I forgot what I did to get it. The key point might not be the soft link.

What can I do?
在2022年10月28日星期五 UTC+8 14:17:46<Ian Lance Taylor> 写道:
Message has been deleted

Qingwei Li

unread,
Nov 1, 2022, 3:34:47 AM11/1/22
to golang-nuts
  Ok, I solved my problem again. The solution is to add `-S -emit-llvm` to get llvm IR for each package and use `llvm-link -S a.ll b.ll -o main.ll` to link all llvm IR files to get a whole program llvm IR. 

the command is as follows:

```
WORK=/tmp/go-build438096694
mkdir -p $WORK/b002/
cd $WORK
/data/mygo/gollvm_workarea/install/bin/llvm-goc -fgo-importcfg=/dev/null -c -x c - -o /dev/null || true
/data/mygo/gollvm_workarea/install/bin/llvm-goc -ffile-prefix-map=a=b -c -x c - -o /dev/null || true
cd /home/lqw/easyPkg/Pkg
/data/mygo/gollvm_workarea/install/bin/llvm-goc -c -O2 -g -m64 -fdebug-prefix-map=$WORK=/tmp/go-build -gno-record-gcc-switches -fgo-pkgpath=easyPkg/Pkg -o $WORK/b002/_go_.o -I $WORK/b002/_importcfgroot_ ./utils.go
/data/mygo/gollvm_workarea/install/bin/llvm-goc -c -S -emit-llvm -O2 -g -m64 -fdebug-prefix-map=$WORK=/tmp/go-build -gno-record-gcc-switches -fgo-pkgpath=easyPkg/Pkg -o $WORK/b002/_go_.ll -I $WORK/b002/_importcfgroot_ ./utils.go
/data/mygo/gollvm_workarea/install/bin/llvm-goc -c -O2 -g -m64 -fdebug-prefix-map=$WORK=/tmp/go-build -gno-record-gcc-switches -o $WORK/b001/_go_.o -I $WORK/b001/_importcfgroot_ ./main.go $WORK/b001/_gomod_.go
/data/mygo/gollvm_workarea/install/bin/llvm-goc -c -S -emit-llvm -O2 -g -m64 -fdebug-prefix-map=$WORK=/tmp/go-build -gno-record-gcc-switches -o $WORK/b001/_go_.ll -I $WORK/b001/_importcfgroot_ ./main.go $WORK/b001/_gomod_.go
llvm-link -S $WORK/b002/_go_.ll $WORK/b001/_go_.ll -o main.ll
echo '  .section .go.buildid,"e"' >> $WORK/b001/_buildid.s
echo '  .byte 0x62,0x6c,0x7a,0x44,0x45,0x34,0x43,0x38' >> $WORK/b001/_buildid.s
echo '  .byte 0x56,0x42,0x6a,0x4e,0x6a,0x74,0x4e,0x68' >> $WORK/b001/_buildid.s
echo '  .byte 0x66,0x71,0x4b,0x56,0x2f,0x62,0x6c,0x7a' >> $WORK/b001/_buildid.s
echo '  .byte 0x44,0x45,0x34,0x43,0x38,0x56,0x42,0x6a' >> $WORK/b001/_buildid.s
echo '  .byte 0x4e,0x6a,0x74,0x4e,0x68,0x66,0x71,0x4b' >> $WORK/b001/_buildid.s
echo '  .byte 0x56' >> $WORK/b001/_buildid.s
echo '  .section .note.GNU-stack,"",@progbits' >> $WORK/b001/_buildid.s
echo '  .section .note.GNU-split-stack,"",@progbits' >> $WORK/b001/_buildid.s
echo '' >> $WORK/b001/_buildid.s
/data/mygo/gollvm_workarea/install/bin/llvm-goc -xassembler-with-cpp -I $WORK/b001/ -c -o $WORK/b001/_buildid.o -D GOOS_linux -D GOARCH_amd64 -m64 $WORK/b001/_buildid.s
ar rcD $WORK/b001/_pkg_.a $WORK/b001/_go_.o $WORK/b001/_buildid.o
/data/mygo/gollvm_workarea/install/tools/buildid -w $WORK/b001/_pkg_.a # internal
cp $WORK/b001/_pkg_.a /home/lqw/.cache/go-build/db/dbe11e7450e893503846799700cb9d0005a545c180087da01751b0ba8586d06d-d # internal
cat >$WORK/b001/importcfg.link << 'EOF' # internal
packagefile easyPkg=$WORK/b001/_pkg_.a
packagefile easyPkg/Pkg=$WORK/b002/_pkg_.a
modinfo "0w\xaf\f\x92t\b\x02A\xe1\xc1\a\xe6\xd6\x18\xe6path\teasyPkg\nmod\teasyPkg\t(devel)\t\nbuild\t-compiler=gccgo\nbuild\tCGO_ENABLED=1\nbuild\tCGO_CFLAGS=\nbuild\tCGO_CPPFLAGS=\nbuild\tCGO_CXXFLAGS=\nbuild\tCGO_LDFLAGS=\nbuild\tGOARCH=amd64\nbuild\tGOEXPERIMENT=fieldtrack\nbuild\tGOOS=linux\nbuild\tGOAMD64=v1\n\xf92C1\x86\x18 r\x00\x82B\x10A\x16\xd8\xf2"
EOF
mkdir -p $WORK/b001/exe/
cd .
/data/mygo/gollvm_workarea/install/bin/llvm-goc -o $WORK/b001/exe/a.out "-Wl,-(" -m64 -Wl,--whole-archive $WORK/b001/_pkg_.a $WORK/b002/_pkg_.a -Wl,--no-whole-archive "-Wl,-)" -Wl,--build-id=0x6b376a38547962446f5337585f526e576b335a452f626c7a444534433856426a4e6a744e6866714b562f586d4a7278396231457475304f2d6e6b72326a742f6b376a38547962446f5337585f526e576b335a45
/data/mygo/gollvm_workarea/install/tools/buildid -w $WORK/b001/exe/a.out # internal
cp $WORK/b001/exe/a.out easyPkg
rm $WORK/b001
```

Thanks for your time!
Reply all
Reply to author
Forward
0 new messages