<p>Compiled languages seem to always have to attach some name to any global object, such as a function or global variable, even after they are compiled, but not local variables. As such, languages such as C++ and Swift employ <a href="https://en.wikipedia.org/wiki/Name_mangling" rel="nofollow noreferrer">name mangling</a> to ensure that the symbols do not collide with each other. But why do there need to be symbols in the first place?</p>
<p>Although it would make sense for symbols to be preserved separately for debugging reasons, and of course library or object files need to give public symbols names so that other code can reference them, why would it be necessary to store the name of the symbols if the symbols are private anyway (<code>static</code> objects in C for instance), or after the product has already been linked? Local variables are simply identified in the assembly by specific registers or specific pointers to stack memory, so why can global objects apparently not be referenced this way, and have to be referenced by name, even after the project has been compiled and linked?</p>

<symbol-solving><linker>
Why are symbols (especially static/internal symbols) necessary?
CC BY-SA 4.0
2023-11-05T21:43:55.237Z
In what situation would such symbols appear in an executable after the linking step?
Greg Hewgill
CC BY-SA 4.0
2023-11-05T21:46:01.217Z
@GregHewgill I compile a program into an executable, and then use `objdump -d` and see the names.
CPlus
CC BY-SA 4.0
2023-11-05T21:55:27.627Z
You could use `strip` to remove the symbols, so I think they are just helpful information, and are left there only because you didn't ask it to behave in other ways.
user23013
CC BY-SA 4.0
2023-11-05T21:56:21.643Z
@user23013 For me sometimes strip does not remove the symbols. And sometimes it just replaces the symbols with other symbols.
CPlus
CC BY-SA 4.0
2023-11-05T22:09:05.413Z
@user16217248 I tried it for a simple program, and the objdump result replaced symbol names with offsets from other symbols. Are you sure the other symbols are still for the variables themselves?
user23013
CC BY-SA 4.0
2023-11-06T06:59:16.127Z
Can you show a minimal reproducible example of what you are talking about?
Nate Eldredge
CC BY-SA 4.0
2023-11-06T18:24:18.237Z
@NateEldredge It used to be the case that on my comptuter I would get 'cannot strip symbols ...' when trying to strip an executable. For some reason I can no longer reproduce that, but when I strip an object file, the `static` function names cannot be stripped, even though they are `static` and cannot be externally referenced anyway.
CPlus
CC BY-SA 4.0
2023-11-07T05:38:35.673Z
Are you stripping an **object file** or an **executable**?  Stripping an object file makes no sense.  But anyway, I can't reproduce this.  On Ubuntu 23.04 x86-64, with source file `static void blah(void) { } int main(void) { blah(); }`, doing `gcc -s s.c` results in `a.out` not containing the string `blah`, and similarly for `gcc -c s.c ; strip s.o`.  So you will have to give more details about your source file, platform, and toolchain.
Nate Eldredge
<p>Symbols are required in order to link multiple compilation units together. When a compilation unit references a procedure/function/etc. from another unit, it must somehow <strong>externalize</strong> the reference. Logically, this names the referent.</p>
<p>We use human-readable names made up of strings of characters for <strong>convenience</strong>, and our tools tend to preserve those names for later <strong>introspection</strong>.</p>

CC BY-SA 4.0
2023-11-06T16:05:20.990Z
2023-11-08T17:07:04.783Z
2023-11-08T17:07:04.783Z
Corbin
CC BY-SA 4.0
2023-11-07T22:02:24.273Z
The question explicitly acknowledges that external names need to be preserved for linking. It's about private names and preservation after linking.
Barmar
CC BY-SA 4.0
2023-11-08T00:08:19.630Z
@Barmar: Convenience and introspection are the reasons. Names don't need to be preserved by the linker; they are inputs to the linker, not outputs.
Corbin
CC BY-SA 4.0
2023-11-08T16:41:04.050Z
That should be in the answer. And the first paragraph of the answer isn't really necessary.
Barmar
CC BY-SA 4.0
2023-11-08T17:06:31.670Z
@Barmar: It's all already there. If I make the requested changes, will you accept the answer?
Corbin
CC BY-SA 4.0
2023-11-08T17:07:47.400Z
I didn't write the question, I can't accept the answer. My point is that your first paragraph is simply restating something already in the question.
Barmar
CC BY-SA 4.0
2023-11-14T04:42:03.590Z
@Barmar: linking happens at runtime when the program is dynamically linked, so there generally isn't any time "after linking"
Chris Dodd
<p>Compiled languages compile down to either a executable binary file or a dynamically linked library.</p>
<p>A dynamically linked library exposes their entry points and global variables and imported symbols through a string. This is part of how both linux and windows and wasm have structured their executable formats.</p>
<p>In the same way a dynamically linked library can look for symbols defined in the main executable using similarly exposed symbols. This can help to make sure that malloc and free for example can be used interchangeably in both. Though that's not a guarantee.</p>
<p>In most languages the default is to make global objects exposed like that because it's less hassle than to make it explicit opt-in. Especially when (like with many compiled languages) there is a linker step that combines multiple translation units each with their own set of symbols.</p>
<p>Though the opt-in can still be there to give it an explicit name for either imports or exports.</p>

CC BY-SA 4.0
2023-11-06T10:11:36.010Z
2023-11-06T10:30:29.860Z
2023-11-06T10:30:29.860Z
ratchet freak
# Why are symbols (especially static/internal symbols) necessary?
Posted by: username_0 on 2023-11-05
Compiled languages seem to always have to attach some name to any global object, such as a function or global variable, even after they are compiled, but not local variables. As such, languages such as C++ and Swift employ [name mangling](https://en.wikipedia.org/wiki/Name_mangling) to ensure that the symbols do not collide with each other. But why do there need to be symbols in the first place?

Although it would make sense for symbols to be preserved separately for debugging reasons, and of course library or object files need to give public symbols names so that other code can reference them, why would it be necessary to store the name of the symbols if the symbols are private anyway (`static` objects in C for instance), or after the product has already been linked? Local variables are simply identified in the assembly by specific registers or specific pointers to stack memory, so why can global objects apparently not be referenced this way, and have to be referenced by name, even after the project has been compiled and linked?
**Tags:** symbol-solving linker
> **Comments:**
> **username_1**: In what situation would such symbols appear in an executable after the linking step?  
> **username_0**: @GregHewgill I compile a program into an executable, and then use `objdump -d` and see the names.  
> **username_2**: You could use `strip` to remove the symbols, so I think they are just helpful information, and are left there only because you didn't ask it to behave in other ways.  
> **username_0**: @user23013 For me sometimes strip does not remove the symbols. And sometimes it just replaces the symbols with other symbols.  
> **username_2**: @user16217248 I tried it for a simple program, and the objdump result replaced symbol names with offsets from other symbols. Are you sure the other symbols are still for the variables themselves?  
> **username_3**: Can you show a minimal reproducible example of what you are talking about?  
> **username_0**: @NateEldredge It used to be the case that on my comptuter I would get 'cannot strip symbols ...' when trying to strip an executable. For some reason I can no longer reproduce that, but when I strip an object file, the `static` function names cannot be stripped, even though they are `static` and cannot be externally referenced anyway.  
> **username_3**: Are you stripping an **object file** or an **executable**?  Stripping an object file makes no sense.  But anyway, I can't reproduce this.  On Ubuntu 23.04 x86-64, with source file `static void blah(void) { } int main(void) { blah(); }`, doing `gcc -s s.c` results in `a.out` not containing the string `blah`, and similarly for `gcc -c s.c ; strip s.o`.  So you will have to give more details about your source file, platform, and toolchain.  
---
## 2 answers
### Answer by username_7 on 2023-11-06. Score: 0 | Accepted answer
Compiled languages compile down to either a executable binary file or a dynamically linked library.

A dynamically linked library exposes their entry points and global variables and imported symbols through a string. This is part of how both linux and windows and wasm have structured their executable formats.

In the same way a dynamically linked library can look for symbols defined in the main executable using similarly exposed symbols. This can help to make sure that malloc and free for example can be used interchangeably in both. Though that's not a guarantee.

In most languages the default is to make global objects exposed like that because it's less hassle than to make it explicit opt-in. Especially when (like with many compiled languages) there is a linker step that combines multiple translation units each with their own set of symbols.

Though the opt-in can still be there to give it an explicit name for either imports or exports.
---
### Answer by username_4 on 2023-11-06. Score: 2
Symbols are required in order to link multiple compilation units together. When a compilation unit references a procedure/function/etc. from another unit, it must somehow **externalize** the reference. Logically, this names the referent.

We use human-readable names made up of strings of characters for **convenience**, and our tools tend to preserve those names for later **introspection**.
> **Comments:**
> **username_5** (2023-11-07): The question explicitly acknowledges that external names need to be preserved for linking. It's about private names and preservation after linking.  
> **username_4** (2023-11-08): @Barmar: Convenience and introspection are the reasons. Names don't need to be preserved by the linker; they are inputs to the linker, not outputs.  
> **username_5** (2023-11-08): That should be in the answer. And the first paragraph of the answer isn't really necessary.  
> **username_4** (2023-11-08): @Barmar: It's all already there. If I make the requested changes, will you accept the answer?  
> **username_5** (2023-11-08): I didn't write the question, I can't accept the answer. My point is that your first paragraph is simply restating something already in the question.  
> **username_6** (2023-11-14): @Barmar: linking happens at runtime when the program is dynamically linked, so there generally isn't any time "after linking"  
---
