Linker doesn't report multiple definitions of symbol

Horvat
Posts: 16
Joined: Thu May 02, 2024 8:40 am

Linker doesn't report multiple definitions of symbol

Postby Horvat » Tue Jun 04, 2024 12:24 pm

Hi,
after
- creating new project via idf.py create-project testproj
- copying file testproj\main\testproj.c to testproj\main\testproj2.c
- and adding "testproj2.c" to SRCS in testproj/main/CMakeLists.txt

I'd expect idf.py build to fail due to multiple definitions of symbol app_main. But it succeeds.

Do I need to add some kind of configuration/flag in order to get error/warning when there are multiple symbols with the same name?

ESP_Sprite
Posts: 9577
Joined: Thu Nov 26, 2015 4:08 am

Re: Linker doesn't report multiple definitions of symbol

Postby ESP_Sprite » Wed Jun 05, 2024 12:40 am

It normally does, I think you're running into an optimization quirk that plays up in this particular situation. Specifically, the way the linker works in ESP-IDF is that it discards as many symbols as it can, so functions that are not used won't end up using space in your final program. This also has added behaviour in that it discards entire files if the symbols defined therein are not needed. I think that it does that before checking for duplicate symbols; so in your case, testproj2.c will be entirely ignored as it doesn't contain anything needed to fully link the program.

If the linker does need to include testproj2.c, then it works. For instance, rename app_main in testproj2.c to app_main2, call app_main2 from testproj.c, then in both files declare a new function with the same name, and the linker will spit out an error.

I'm not sure how to make the linker also error out if there's a duplicate symbol in an otherwise unused file, sorry.

Elkfoot
Posts: 1
Joined: Tue Jun 25, 2024 3:55 pm

Re: Linker doesn't report multiple definitions of symbol

Postby Elkfoot » Wed Jun 26, 2024 11:19 am

I would find it very helpful if the linker could report duplicate symbols.

I had an issue in my code where I (foolishly) wrote a function called close(). I was very surprised to find that there was a runtime error where some completely unrelated code that was using sockets called what was meant to be sockets close() but instead it actually called my close() function. I think it was lucky that it caused a runtime error, otherwise it could have caused any undefined behaviour.

It would be good if this short of thing could be picked up by the linker.

RandomInternetGuy
Posts: 48
Joined: Fri Aug 11, 2023 4:56 am

Re: Linker doesn't report multiple definitions of symbol

Postby RandomInternetGuy » Tue Jul 02, 2024 11:45 pm

close() - and other symbols provided by POSIX or ISO c/c++ may be a special case.

Somewhere in the later System V days of ELF, the OS (UNIX originally, later newlib and such) would make open, malloc, write, and so on into weak symbols (multiple definitions can be presents; first one found is used) and the actual implementation, _open, _malloc, write_, _close and a few hundred of their closest friends, would be normal strong symbols just by having a file of weak symbols (foo(int a, char* b, void* c);) that immediately did (foo{return _foo(a, b, c);}) This interposing layer allowed application devs to easily replace symbols in case you needed to shim something in, add something for profiling, interject behaviour or so on. It was a really nifty feature if you knew about it, understood it, and used it for good. Inevitably, someone would write a C file that didn't include anything that got appropriate prototypes, then write "int close = 3;" or something. You can see what's coming can't you? It was totally legal by the standard, but it was not pretty. There are remnants of that explained at

https://www.embecosm.com/appnotes/ean9/ ... pace_reent or https://stackoverflow.com/questions/262 ... rnal-names

It's likely that this was convention was picked up in the code that became the ESP-IDF OS.

That wouldn't explain the linker not fussing about multiple definitions of the same global. That seems like it should get called as a foul. With -fsymbol-functions and the recent change in the language spec preferring .comm to .globl for symbols and Arduino's bizarre handling redinitions by the nature of it declaring .ino files already processed, and C++ operator overloading, it's getting increasingly difficult to tell which symbol is actually used in any given context.

None of this directly applies to OP's case. It's just saying that in many similar cases, this is actually intentionally chosen and desirable. In this case I'd share the expectation and the surprise.

Who is online

Users browsing this forum: zaik2rlm and 244 guests