2

I get these errors when I try to statically link my Go program that uses Gopacket:

/usr/bin/ld: /usr/lib/gcc/x86_64-linux-gnu/11/../../../x86_64-linux-gnu/libpcap.a(pcap-dbus.o): in function `dbus_write':
(.text+0x103): undefined reference to `dbus_message_demarshal'
/usr/bin/ld: (.text+0x119): undefined reference to `dbus_connection_send'
/usr/bin/ld: (.text+0x122): undefined reference to `dbus_connection_flush'
/usr/bin/ld: (.text+0x12a): undefined reference to `dbus_message_unref'
/usr/bin/ld: (.text+0x178): undefined reference to `dbus_error_free'
/usr/bin/ld: /usr/lib/gcc/x86_64-linux-gnu/11/../../../x86_64-linux-gnu/libpcap.a(pcap-dbus.o): in function `dbus_read':
(.text+0x1c3): undefined reference to `dbus_connection_pop_message'
/usr/bin/ld: (.text+0x1e1): undefined reference to `dbus_connection_pop_message'
/usr/bin/ld: (.text+0x1f6): undefined reference to `dbus_connection_read_write'
/usr/bin/ld: (.text+0x262): undefined reference to `dbus_message_is_signal'
/usr/bin/ld: (.text+0x27f): undefined reference to `dbus_message_marshal'
/usr/bin/ld: (.text+0x2e3): undefined reference to `dbus_free'
/usr/bin/ld: /usr/lib/gcc/x86_64-linux-gnu/11/../../../x86_64-linux-gnu/libpcap.a(pcap-dbus.o): in function `dbus_cleanup':
(.text+0x350): undefined reference to `dbus_connection_unref'
/usr/bin/ld: /usr/lib/gcc/x86_64-linux-gnu/11/../../../x86_64-linux-gnu/libpcap.a(pcap-dbus.o): in function `dbus_activate':
(.text+0x3fa): undefined reference to `dbus_connection_open'
/usr/bin/ld: (.text+0x412): undefined reference to `dbus_bus_register'
...

Indeed these symbols indeed either do not exist /usr/lib/gcc/x86_64-linux-gnu/11/../../../x86_64-linux-gnu/libpcap.a or show up as undefined. For example:

$ readelf -s /usr/lib/gcc/x86_64-linux-gnu/11/../../../x86_64-linux-gnu/libpcap.a | grep dbus_message_marshal
    42: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND dbus_message_marshal

None of these functions are called from my program, but are happening because of the dependency to Gopacket.

I have libpcap installed:

$ apt list --installed|grep pcap

WARNING: apt does not have a stable CLI interface. Use with caution in scripts.

libpcap-dev/jammy,now 1.10.1-4build1 amd64 [installed]
libpcap0.8-dev/jammy,now 1.10.1-4build1 amd64 [installed]
libpcap0.8/jammy,now 1.10.1-4build1 amd64 [installed,automatic]

Is there anything else I need? Here's how I compile:

GOOS=linux CGO_ENABLED=1 go build \
    -ldflags "-linkmode external -extldflags \"-static\"" \
    -o bin/myprog \
    -buildvcs=false

If I do not include -ldflags, the program compiles, but it is not statically linked.

I am using Go 1.18.

user2233706
  • 6,148
  • 5
  • 44
  • 86
  • Does this answer your question? [What is an undefined reference/unresolved external symbol error and how do I fix it?](https://stackoverflow.com/questions/12573816/what-is-an-undefined-reference-unresolved-external-symbol-error-and-how-do-i-fix) – Ken White Nov 24 '22 at 01:58
  • No, this is a Go program. How would I change how I compile this program with an answer to a C++ question? – user2233706 Nov 24 '22 at 02:09
  • The language is irrelevant. ldflags and libpcap are both linker related. The problem is the same, and the solution is the same. – Ken White Nov 24 '22 at 02:11
  • libpcap is getting linked. Why doesn't it have these symbols? – user2233706 Nov 24 '22 at 04:24
  • If "it" is libpcap, it doesn't have those symbols because those symbols are part of the D-Bus library, which is used by libpcap's D-Bus capture support, they're not part of libpcap itself. The libpcap *static* library isn't linked, it's built as an archive, as that's what static libraries are on UN\*Xes. The ibpcap *dynamic* library is *dynamically* linked with the D-Bus library, so the D-Bus library routines aren't linked in to libpcap. – user16139739 Nov 26 '22 at 21:36

2 Answers2

1

do not exist /usr/lib/gcc/x86_64-linux-gnu/11/../../../x86_64-linux-gnu/libpcap.a

They are not in libpcap. They are called by that version of libpcap.

You will have to link with all of the libraries reported by pkg-config --libs --static libdpdk in order to statically link that version of libpcap with any program whether it's in Go or not.

user16139739
  • 862
  • 3
  • 5
0

It's seems like it is impossible to make a statically linked binary that uses Gopacket.

I updated the build command to use libdbus-1. This got rid of the undefined dbus_* errors:

GOOS=linux CGO_ENABLED=1 CGO_LDFLAGS="-ldbus-1" go build \
    -ldflags "-linkmode external -extldflags \"-static\"" \
    -o bin/app \
    -buildvcs=false

However, I got this error:

/usr/bin/ld: /usr/lib/gcc/x86_64-linux-gnu/11/../../../x86_64-linux-gnu/libdbus-1.a(libdbus_1_la-dbus-sysdeps-unix.o): in function `_dbus_listen_systemd_sockets':
(.text+0x200e): undefined reference to `sd_listen_fds'
/usr/bin/ld: (.text+0x204f): undefined reference to `sd_is_socket'
collect2: error: ld returned 1 exit status

These functions come from libsystemd. I installed libsystemd-dev, but it seems like there is no static library for libsystemd.

user2233706
  • 6,148
  • 5
  • 44
  • 86
  • No, it's currently impossible to 100% statically link with the DPDK library, as one of the libraries on which the DPDK library currently depends,, namely libsystemd, currently offers no static library. Either 1) give up on 100% static linking (assuming Go tolerates that) or 2) give up on having a libpcap that includes DPDK support. (I'm sufficiently annoyed with that DPDK code, for this and other reasons, that I'm tempted to make it optional in libpcap, so you have to explicitly say "support DPDK" when configuring libpcap.) – user16139739 Nov 24 '22 at 23:33
  • Do you know if this change was recent? Our app used to build with an older set of dependencies. – user2233706 Nov 25 '22 at 02:47
  • (Sorry, that should have been "D-Bus", not "DPDK", above.) I don't know when libdbus started using libsystemd routines, but, on Ubuntu-22.04, `pkg-config --modversion dbus-1` reports "1.12.20" and `pkg-config --libs --static dbus-1` reports `-ldbus-1 -lsystemd`. – user16139739 Nov 26 '22 at 21:51