Motiejus Jakštys c841f52fcb Elf: switch link order of libcompiler_rt and libc
Given `main.go`:

    package main
    import  _ "os/user"
    func main() {}

Compiling it to linux/arm64:

    $ CGO_CFLAGS='-O0' GOOS=linux GOARCH=arm64 CGO_ENABLED=1 CC="zig cc -target aarch64-linux-gnu.2.28" go build main.go

Results in this error:

    runtime/cgo(.text): unknown symbol memset in callarm64
    runtime/cgo(.text): unknown symbol memset in callarm64
    runtime/cgo(.text): relocation target memset not defined

In the midst of intermediate compilations files we can see this commmand:

    ld.lld -o _cgo_.o <...> /tmp/go-build206961058/b043/_x009.o <...> ~/.cache/zig/.../libcompiler_rt.a <...> ~/.cache/.../libc.so.6

`_x009.o` needs memset:

    $ readelf -Ws ./b043/_x009.o | grep memset
        22: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND memset

Both `libcompiler_rt.a` and `libc.so.6` provide it:

    $ readelf -Ws ~/.cache/zig/.../libcompiler_rt.a | grep memset
       870: 0000000000000000   318 FUNC    WEAK   DEFAULT  519 memset

    $ readelf -Ws ~/.cache/zig/.../libc.so.6 | grep -w memset
       476: 000000000001d34c     0 FUNC    GLOBAL DEFAULT    7 memset@@GLIBC_2.2.5

Since `libcompiler_rt.a` comes before libc in the linker line, the
resulting `_cgo_.o` still links to a weak, unversioned memset:

    $ readelf -Ws ./b043/_cgo_.o | grep -w memset
        40: 000000000022c07c   160 FUNC    WEAK   DEFAULT   14 memset
       719: 000000000022c07c   160 FUNC    WEAK   DEFAULT   14 memset

Since the final linking step is done by Golang's linker, it does not
know of `libcompiler_rt.a`, and fails to link with the error message
above. However, Go linker does recognize memset from glibc. If we
specify an `-lc` equivalent before the `libcompiler_rt.a`, it will link
to memset from libc:

    $ readelf -Wa ./b043/_x009.o |grep memset
        14: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND memset@GLIBC_2.17 (2)
       157: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND memset@GLIBC_2.17

... and then `main.go` will compile+link successfully.

Why doesn't Go linker take memset from glibc? An educated guess: Go
determines whether to link with glibc from what the program asks (I
presume `.dynsym`). Since `memset` is no longer attributed to glibc, Go
skips linking to glibc altogether.

Bonus question: curious why `-O0` is necessary? Because when
optimizations are enabled (the default), the C compiler replaces
`memset` function call with plain `stp` instructions (on aarch64).
2023-01-09 15:06:07 -07:00
2023-01-09 15:04:55 -07:00
2021-06-25 12:46:23 +03:00
Y++
2021-12-31 19:58:21 -05:00

ZIG

A general-purpose programming language and toolchain for maintaining robust, optimal, and reusable software.

Resources

Installation

License

The ultimate goal of the Zig project is to serve users. As a first-order effect, this means users of the compiler, helping programmers to write better software. Even more important, however, are the end-users.

Zig is intended to be used to help end-users accomplish their goals. Zig should be used to empower end-users, never to exploit them financially, or to limit their freedom to interact with hardware or software in any way.

However, such problems are best solved with social norms, not with software licenses. Any attempt to complicate the software license of Zig would risk compromising the value Zig provides.

Therefore, Zig is available under the MIT (Expat) License, and comes with a humble request: use it to make software better serve the needs of end-users.

This project redistributes code from other projects, some of which have other licenses besides MIT. Such licenses are generally similar to the MIT license for practical purposes. See the subdirectories and files inside lib/ for more details.

Description
General-purpose programming language and toolchain for maintaining robust, optimal, and reusable software.
Readme MIT 691 MiB
Languages
Zig 98.3%
C 1.1%
C++ 0.2%
Python 0.1%