October 30, 2022

BSD TCP/IP for Kyu - Global variables

The C language used to let you play fast and loose with global variables. You could define them in multiple places and the compiler would pick one of those as the actual definition and generate memory there, then the rest of the definitions would serve as implicit "extern" declarations. At some point the C compiler people decided they didn't like that and required just one (and only one) definition somewhere. Everything else should reference that via an extern. It all makes sense, but makes life a hassle when porting older software, like this BSD code, that expects the old behavior.
I see a series of messages like this when I try to link:
aarch64-linux-gnu-ld.bfd: tcp_input.o:(.bss+0x0): multiple definition of `route_cb'; tcp_debug.o:(.bss+0x0): first defined here
aarch64-linux-gnu-ld.bfd: tcp_input.o:(.bss+0x10): multiple definition of `rtstat'; tcp_debug.o:(.bss+0x10): first defined here
aarch64-linux-gnu-ld.bfd: tcp_input.o:(.bss+0x20): multiple definition of `rt_tables'; tcp_debug.o:(.bss+0x20): first defined here
aarch64-linux-gnu-ld.bfd: tcp_input.o:(.bss+0xf8): multiple definition of `ipstat'; tcp_debug.o:(.bss+0xf8): first defined here
aarch64-linux-gnu-ld.bfd: tcp_input.o:(.bss+0x1b8): multiple definition of `ipq'; tcp_debug.o:(.bss+0x1b8): first defined here
aarch64-linux-gnu-ld.bfd: tcp_input.o:(.bss+0x1f0): multiple definition of `ip_id'; tcp_debug.o:(.bss+0x1f0): first defined here
aarch64-linux-gnu-ld.bfd: tcp_input.o:(.bss+0x1f4): multiple definition of `ip_defttl'; tcp_debug.o:(.bss+0x1f4): first defined here
aarch64-linux-gnu-ld.bfd: tcp_input.o:(.bss+0x1f8): multiple definition of `tcp_iss'; tcp_debug.o:(.bss+0x1f8): first defined here
aarch64-linux-gnu-ld.bfd: tcp_input.o:(.bss+0x200): multiple definition of `tcb'; tcp_debug.o:(.bss+0x200): first defined here
aarch64-linux-gnu-ld.bfd: tcp_input.o:(.bss+0x298): multiple definition of `tcpstat'; tcp_debug.o:(.bss+0x298): first defined here
aarch64-linux-gnu-ld.bfd: tcp_input.o:(.bss+0x428): multiple definition of `tcp_now'; tcp_debug.o:(.bss+0x428): first defined here
aarch64-linux-gnu-ld.bfd: tcp_input.o:(.bss+0x430): multiple definition of `tcp_debug'; tcp_debug.o:(.bss+0x430): first defined here
aarch64-linux-gnu-ld.bfd: tcp_input.o:(.bss+0x8db0): multiple definition of `tcp_debx'; tcp_debug.o:(.bss+0x8db0): first defined here

One example is "nmbclusters". This is defined in a top level kernel file sys/conf/param.c. it gets referenced in mbuf.h. This is actually done right and is worth taking note of.

Now consider "mbstat". This gets defined in mbuf.h -- but this file is included in many places and the compiler does not like this and gives the following error when compiling tcp_input.c:

multiple definition of `mbstat'; tcp_debug.o:(.bss+0x0): first defined here

Here is what I intend to do. I am going to introduce a new file. I'll call it kyu_tcp_stuff.c or something of the sort. I will put all the definitions there, including those from param.c Then I will modify header files as needed (such as mbuf.h) to add extern prefixes where they are missing.

This is exactly what I do, copying one include file after another and running make over and over to work through the above list. It is tedious, but straightforward. And soon I have my own set of files and am no longer using a -I compiler switch to search the pristine Net/3 sources.


Have any comments? Questions? Drop me a line!

Kyu / [email protected]