I was looking into that, and found that cgo doesn't expect to have a
self-contained object file that doesn't link to external libraries. I
looked at the output from go build -x -work which prints the commands
used to build the files, and I found:
* gcc is used to build all the C files, this is notmal and expected
* gcc is used to aggregate all the .o objects that were built into a
master _cgo_.o object file that contains the code for all the .c files
of the module
* gcc inokes ld to generate this _cgo_.o file. Normally, ld will link
against the libc unless passed -nostdlib. In that case, the .o object
file will not contain reference to external symbols.
In my case, when gcc/ld links _cgo_.o against the libc, the only
external symbols that are unreferenced (found using nm -D) are :
w __gmon_start__
w _ITM_deregisterTMCloneTable
w _ITM_registerTMCloneTable
w _Jv_RegisterClasses
U __libc_start_main
These symbols are only necessary when we have a main function. In our
case this is not necessary. But the _init and _start functions generated
by gcc/ld make use of it.
When avoiding the link to libc (using -nostdlib) none of those symbols
appear and there is no undefined symbol.
* Later on, gco is run and open the _cgo_.o file to generate the list of
libraries to link against in the final link where the executable is
generated. In case we use the libc, it find references to libc functions
and write to a file (_cgo_import.6) that libc is necessary
If there is no external symbol required (beause we used -nostdlib),
gcc/ld will strip the .dynsym section completely because it empty.
because there is no section .dynsym, cgo will mistakenly interpret the
absence of this section as a read failure of the ELF object file.
The all stack looks like this:
https://github.com/golang/go/blob/3819907a5565c53457b826912a10b18eda708f38/src/cmd/cgo/out.go#L204
https://github.com/golang/debug/blob/512354eaded67146a256474f5f486c37fd6e5263/elf/file.go#L669
https://github.com/golang/debug/blob/512354eaded67146a256474f5f486c37fd6e5263/elf/file.go#L397
https://github.com/golang/debug/blob/512354eaded67146a256474f5f486c37fd6e5263/elf/file.go#L455
- dynimport()
- elf.Open(obj).ImportedSymbols()
- f.getSymbols(SHT_DYNSYM)
- f.getSymbols64(SHT_DYNSYM)
symtabSection := f.SectionByType(typ)
if symtabSection == nil {
return nil, nil, errors.New("no symbol section")
}
I filed an issue against the debug/elf package:
https://github.com/golang/debug/issues/1
Mildred