golang / go

The Go programming language
https://go.dev
BSD 3-Clause "New" or "Revised" License
123.4k stars 17.59k forks source link

gollvm: error: undefined reference to 'runtime.strhash..f.1' #52899

Open tianxiaogu opened 2 years ago

tianxiaogu commented 2 years ago
# command-line-arguments
/tmp/go-build3560960528/b001/_pkg_.a(_go_.o):gomodule:type..map_6string_7int: error: undefined reference to 'runtime.strhash..f.1'

The error can be reproduced with the test case and the trunk.

package main

import "unsafe"

var E_hash func(unsafe.Pointer, uintptr) uintptr = strhash

//go:noescape
//go:linkname strhash runtime.strhash
func strhash(unsafe.Pointer, uintptr) uintptr

func pointer(s string) unsafe.Pointer {
    return unsafe.Pointer(&s)
}

func main() {
    var m map[string]int
    m = make(map[string]int)
    m["123"] = 1
    if E_hash == nil {
        panic("Oops")
    }
    if E_hash(pointer("123"), 0) != E_hash(pointer("123"), 0) {
        panic("Oops")
    }
}

Func_descriptor_expression::do_get_backend deals with function declaration and definition differently, which can request the backend twice to create global variables representing the function pointer. Unfortunately, the GOLLVM bridge uses module_->getGlobalVariable(gname) (without parameter AllowLocal) to check existing globals, which cannot find GlobalVariable with local linkage. To fix this issue, we should set is_hidden = false in Func_descriptor_expression::do_get_backend if the Function or Function_declaration has a non-empty asm_name.

Moreover, we need to set AllowLocal = true when trying to find globals via module_->getGlobalVariable and resolve linkage/type conflicts if necessary in GOLLVM bridge. Otherwise, the LLVM backend will rename the global by itself, which will lead to undefined reference errors.

ianlancetaylor commented 2 years ago

There may be a bug here, but, to be clear, using //go:linkname strhash runtime.strhash is completely unsupported. If this problem only arises with programs that use go:linkname then I don't see any real need to fix it.

Still, this program does work with gccgo so it's odd that it fails with GoLLVM.

CC @thanm