Many times I'd like to replace libc functions in embedded systems,
because of some tests or because I need a different implementation.
For example, sprintf implementation of newlib uses malloc and I can't
use it many times.
It sometimes happens that I can use malloc, with some restrictions. Just
for test or optimization, I replace libc malloc with my own implementation.
In these cases I use a very simple trick: I simply define a new sprintf()/malloc() function in one of my source code. During linking
(GNU ld), the linker prefers my implementation and ignore the
implementation in the libc. I don't know why this happens and if it is a standard way during linking, but it works for me.
Recently I found a different behaviour, with an error from the linker: multiple definitions of sprintf.
After some time, I understood it is caused by a piece of code that uses another libc function (ctime) that uses sprintf too, I suppose.
Maybe in this case, ctime needs sprintf from libc so the linker tries to
add two sprintf and gives the error.
First question: what exactly happens?
Second question: is there a better method to override a standard libc function?
I know I can use preprocessor magic, but in this case I should write MYSPRINTF(...) that is much worse than sprintf(...).
After some time, I understood it is caused by a piece of code that uses another libc function (ctime) that uses sprintf too, I suppose.
Maybe in this case, ctime needs sprintf from libc so the linker tries to
add two sprintf and gives the error.
First question: what exactly happens?
Second question: is there a better method to override a standard libc function?
I know I can use preprocessor magic, but in this case I should write MYSPRINTF(...) that is much worse than sprintf(...).
Many times I'd like to replace libc functions in embedded systems,
because of some tests or because I need a different implementation.
For example, sprintf implementation of newlib uses malloc and I can't
use it many times.
It sometimes happens that I can use malloc, with some restrictions. Just
for test or optimization, I replace libc malloc with my own implementation.
In these cases I use a very simple trick: I simply define a new sprintf()/malloc() function in one of my source code. During linking
(GNU ld), the linker prefers my implementation and ignore the
implementation in the libc. I don't know why this happens and if it is a standard way during linking, but it works for me.
Recently I found a different behaviour, with an error from the linker: multiple definitions of sprintf.
After some time, I understood it is caused by a piece of code that uses another libc function (ctime) that uses sprintf too, I suppose.
Maybe in this case, ctime needs sprintf from libc so the linker tries to
add two sprintf and gives the error.
First question: what exactly happens?
Second question: is there a better method to override a standard libc function?
I know I can use preprocessor magic, but in this case I should write MYSPRINTF(...) that is much worse than sprintf(...).
Many times I'd like to replace libc functions in embedded systems,
because of some tests or because I need a different implementation.
For example, sprintf implementation of newlib uses malloc and I can't
use it many times.
It sometimes happens that I can use malloc, with some restrictions. Just
for test or optimization, I replace libc malloc with my own implementation.
In these cases I use a very simple trick: I simply define a new sprintf()/malloc() function in one of my source code. During linking
(GNU ld), the linker prefers my implementation and ignore the
implementation in the libc. I don't know why this happens and if it is a standard way during linking, but it works for me.
Recently I found a different behaviour, with an error from the linker: multiple definitions of sprintf.
After some time, I understood it is caused by a piece of code that uses another libc function (ctime) that uses sprintf too, I suppose.
Maybe in this case, ctime needs sprintf from libc so the linker tries to
add two sprintf and gives the error.
First question: what exactly happens?
Second question: is there a better method to override a standard libc function?
I know I can use preprocessor magic, but in this case I should write MYSPRINTF(...) that is much worse than sprintf(...).
On 24/09/2022 00:43, pozz wrote:
Many times I'd like to replace libc functions in embedded systems,
because of some tests or because I need a different implementation.
For example, sprintf implementation of newlib uses malloc and I can't
use it many times.
It sometimes happens that I can use malloc, with some restrictions.
Just for test or optimization, I replace libc malloc with my own
implementation.
In these cases I use a very simple trick: I simply define a new
sprintf()/malloc() function in one of my source code. During linking
(GNU ld), the linker prefers my implementation and ignore the
implementation in the libc. I don't know why this happens and if it is
a standard way during linking, but it works for me.
Recently I found a different behaviour, with an error from the linker:
multiple definitions of sprintf.
After some time, I understood it is caused by a piece of code that
uses another libc function (ctime) that uses sprintf too, I suppose.
Maybe in this case, ctime needs sprintf from libc so the linker tries
to add two sprintf and gives the error.
First question: what exactly happens?
Second question: is there a better method to override a standard libc
function?
I know I can use preprocessor magic, but in this case I should write
MYSPRINTF(...) that is much worse than sprintf(...).
When a linker is looking for symbols used, it will first look in the
list of object files it is given, then move on to searching the static libraries. So an override of a library function should have priority.
However, when it pulls in a symbol, it will pull in the whole object
file that it is in. (Section garbage collection might let it later
remove unneeded sections, but that is /after/ this stage.) A static
library file is a collection of object files, so when the link requires pulling in a symbol from the library, it gets all the symbols from the
object file containing it. Usually, libraries are build from lots of
small files with a single function or a few highly related functions in
order to minimise this issue. (It reduces scope for inter-procedural optimisations in the library, however.)
In your case, it is not unlikely that the object library object file
that contains "sprintf" also contains "snprintf", "vsnprintf", and other related functions. So although you have overriden "sprintf", perhaps "ctime" uses "snprintf" and its object file also contains "sprintf" -
thus causing a conflict.
Il 24/09/2022 17:43, David Brown ha scritto:
On 24/09/2022 00:43, pozz wrote:
Many times I'd like to replace libc functions in embedded systems,
because of some tests or because I need a different implementation.
For example, sprintf implementation of newlib uses malloc and I can't
use it many times.
It sometimes happens that I can use malloc, with some restrictions.
Just for test or optimization, I replace libc malloc with my own
implementation.
In these cases I use a very simple trick: I simply define a new
sprintf()/malloc() function in one of my source code. During linking
(GNU ld), the linker prefers my implementation and ignore the
implementation in the libc. I don't know why this happens and if it
is a standard way during linking, but it works for me.
Recently I found a different behaviour, with an error from the
linker: multiple definitions of sprintf.
After some time, I understood it is caused by a piece of code that
uses another libc function (ctime) that uses sprintf too, I suppose.
Maybe in this case, ctime needs sprintf from libc so the linker tries
to add two sprintf and gives the error.
First question: what exactly happens?
Second question: is there a better method to override a standard libc
function?
I know I can use preprocessor magic, but in this case I should write
MYSPRINTF(...) that is much worse than sprintf(...).
When a linker is looking for symbols used, it will first look in the
list of object files it is given, then move on to searching the static
libraries. So an override of a library function should have priority.
However, when it pulls in a symbol, it will pull in the whole object
file that it is in. (Section garbage collection might let it later
remove unneeded sections, but that is /after/ this stage.) A static
library file is a collection of object files, so when the link
requires pulling in a symbol from the library, it gets all the symbols
from the object file containing it. Usually, libraries are build from
lots of small files with a single function or a few highly related
functions in order to minimise this issue. (It reduces scope for
inter-procedural optimisations in the library, however.)
In your case, it is not unlikely that the object library object file
that contains "sprintf" also contains "snprintf", "vsnprintf", and
other related functions. So although you have overriden "sprintf",
perhaps "ctime" uses "snprintf" and its object file also contains
"sprintf" - thus causing a conflict.
ctime()[1] uses actime()[2] that uses siprintf()[3].
I overrided siprintf() too and this solved the linking process.
However it's not completely clear to me. siprintf() is defined in a
single file (siprintf.c), so I thought it was contained in a single
object file (siprintf.o).
However it seems there's an object file (lib_a-sprintf.o) that contains sprintf() and siprintf(). Maybe this multiple functions object file is generated during newlib build process.
pozz wrote:
Il 24/09/2022 17:43, David Brown ha scritto:
On 24/09/2022 00:43, pozz wrote:
Many times I'd like to replace libc functions in embedded systems,
because of some tests or because I need a different implementation.
For example, sprintf implementation of newlib uses malloc and I
can't use it many times.
It sometimes happens that I can use malloc, with some restrictions.
Just for test or optimization, I replace libc malloc with my own
implementation.
In these cases I use a very simple trick: I simply define a new
sprintf()/malloc() function in one of my source code. During linking
(GNU ld), the linker prefers my implementation and ignore the
implementation in the libc. I don't know why this happens and if it
is a standard way during linking, but it works for me.
Recently I found a different behaviour, with an error from the
linker: multiple definitions of sprintf.
After some time, I understood it is caused by a piece of code that
uses another libc function (ctime) that uses sprintf too, I suppose.
Maybe in this case, ctime needs sprintf from libc so the linker
tries to add two sprintf and gives the error.
First question: what exactly happens?
Second question: is there a better method to override a standard
libc function?
I know I can use preprocessor magic, but in this case I should write
MYSPRINTF(...) that is much worse than sprintf(...).
When a linker is looking for symbols used, it will first look in the
list of object files it is given, then move on to searching the
static libraries. So an override of a library function should have
priority.
However, when it pulls in a symbol, it will pull in the whole object
file that it is in. (Section garbage collection might let it later
remove unneeded sections, but that is /after/ this stage.) A static
library file is a collection of object files, so when the link
requires pulling in a symbol from the library, it gets all the
symbols from the object file containing it. Usually, libraries are
build from lots of small files with a single function or a few highly
related functions in order to minimise this issue. (It reduces scope
for inter-procedural optimisations in the library, however.)
In your case, it is not unlikely that the object library object file
that contains "sprintf" also contains "snprintf", "vsnprintf", and
other related functions. So although you have overriden "sprintf",
perhaps "ctime" uses "snprintf" and its object file also contains
"sprintf" - thus causing a conflict.
ctime()[1] uses actime()[2] that uses siprintf()[3].
I overrided siprintf() too and this solved the linking process.
However it's not completely clear to me. siprintf() is defined in a
single file (siprintf.c), so I thought it was contained in a single
object file (siprintf.o).
However it seems there's an object file (lib_a-sprintf.o) that
contains sprintf() and siprintf(). Maybe this multiple functions
object file is generated during newlib build process.
An old-time hack to improve optimization with dumb linkers was to have a
.c file #include other .c files so that the compiler got to see more of
the code at a time.
Haven't seen that one in awhile.
Many times I'd like to replace libc functions in embedded systems,
because of some tests or because I need a different implementation.
For example, sprintf implementation of newlib uses malloc and I can't
use it many times.
Sysop: | Keyop |
---|---|
Location: | Huddersfield, West Yorkshire, UK |
Users: | 307 |
Nodes: | 16 (2 / 14) |
Uptime: | 121:22:39 |
Calls: | 6,854 |
Files: | 12,358 |
Messages: | 5,417,045 |