Skip to main content

GNU symbol visibility

Today I just learned about a quirk when building a shared library. I wanted to link against an example library that I built with meson, but I kept getting link issues, namely

undefined reference to `func_name'

I later on built it manually and inspected the resulting shared object with nm, the relevant difference was about

# built with meson
0000000000001263 t func_name

# built manually
0000000000001263 T func_name

The difference is about the lowercase/uppercase T, as NM(1) man page suggest:

“T” “t” The symbol is in the text (code) section.

However, it does not mention the difference between uppercase/lowercase.

Turns out, uppercase T means it’s global, whereas lowercase t is local. I obviously overlooked the following statement from the man page

If lowercase, the symbol is usually local; if uppercase, the symbol is global (external).

So changing the value of gnu_symbol_visibility from hidden (the default when meson auto generates the meson.build file) to default changes how symbols are handled within the generated shared object file.

More details about symbol visibility can be seen at the GNU’s wiki

And now, back to hacking!