-
Notifications
You must be signed in to change notification settings - Fork 3k
Minimal-printf: Fix wrapping of printf functions for the ARM compiler #12238
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Minimal-printf: Fix wrapping of printf functions for the ARM compiler #12238
Conversation
Based on the documentation you found, shouldn't we also modify the wrapping for vprintf? |
I have not found any documentation that says that I have nothing to suggest that |
a401a3e
to
b2483c1
Compare
vsnprintf
for ARM compilervsnprintf
and vprintf
for ARM compiler
b2483c1
to
fb075bc
Compare
@evedon |
CI started |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems wrong to me, or at least I don't understand why it improves anything - I've started discussion with Hugues offline.
@@ -66,17 +66,12 @@ int $Sub$$__2snprintf(char *buffer, size_t length, const char *format, ...) | |||
return result; | |||
} | |||
|
|||
int $Sub$$__2vprintf(char *buffer, const char *format, ...) | |||
int $Sub$$vprintf(const char *format, va_list arguments) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Basic issue: isn't this now overriding vprintf
twice? Isn't there already a definition of $Sub$$vprintf
in mbed_printf_wrapper.c? That's how it looks to me reading it, but then it apparently isn't working?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is a little tricky.
The ARM compiler does not recognise int SUB_VPRINTF(const char *format, va_list arguments){}
as a definition for vprintf
in mbed_printf_wrapper.c
. However, it recognises it when it is changed to int $Sub$$vprintf(const char *format, va_list arguments){}
.
It seems the ARM compiler requires $Sub$$
to be in the function signature when it is defined.
So all those SUB_*
definitions in mbed_printf_wrapper.c
are ignored for the ARM compiler. Only the definitions in mbed_printf_armliink_overrides.c
count.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
SUB_VPRINTF
is defined as $Sub$$vprintf
in mbed_printf_wrapper.c, isn't it? I must be missing something.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
SUB_VPRINTF
is defined as$Sub$$vprintf
in mbed_printf_wrapper.c, isn't it? I must be missing something.
You are right but I am not sure how the compiler handles $Sub$$
if a pre-processor definition is also used. What I do know is that it does use the definition in mbed_printf_wrapper.c
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wouldn't expect any oddity. Compiler documentation simply says "The dollar character $
is allowed in identifiers." Preprocessor should treat that the same as any other identifier character then.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Working with Hugues, we've established that mbed_printf_wrapper.c
is actually generating the __wrap
functions rather than the $Sub$$
functions because it tests like
#if defined(__GNUC__)
#elif defined(TOOLCHAIN_ARM) || defined(__ICCARM)
But the ARM compiler is in GCC-"compatible" mode, so is defining __GNUC__
.
Suggest reversing those blocks.
Then mbed_printf_wrapper.c
should work for the base functions, but mbed_printf_armlink_overrides
needs to provide all the corresponding __2
functions. That includes the v
functions, as we've established that the compiler will use __2vprintf
if it knows the format. (The mbed_error_printf
doesn't know the format, so uses vsnprintf
, but __2vsnprintf
is still possible in principle).
It looks like mbed_prinf_armlink_overrides
is missing __2vsprintf
, __2fprintf
and __2vfprintf
.
I wonder if possibly you should eliminate the repetition and avoid inconsistency by putting all the definitions into a header file. Then do
#if defined __ARMCC_VERSION || defined __ICCARM__
/* Intercept both printf and __2printf using $Sub$$ */
#define SUB_PRINTF $Sub$$printf
#include "printf_wrappers.h"
#undef SUB_PRINTF
#define SUB_PRINTF $Sub$$__2printf
#include "printf_wrappers.h"
#elif defined __GNUC__
/* Intercept both printf using __wrap_ */
#define SUB_PRINTF __wrap_printf
#include " printf_wrappers.h"
#endif
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, even neater, do what mbed_retarget.cpp
does to determine the prefix. You don't need one define per function, just a define to paste on the $Sub$$
, $Sub$$__2
or __wrap_
prefix. See its PREFIX(x)
macro.
So you define int PREFIX(printf)(const char *, ...)
rather than int SUB_PRINTF(const char *, ...)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
Test run: SUCCESSSummary: 11 of 11 test jobs passed |
fb075bc
to
99cd2ce
Compare
vsnprintf
and vprintf
for ARM compiler99cd2ce
to
ba01aba
Compare
As the ARM compiler is in GNU compatible mode, it defines __GNU__ which (based on pre-processor condition in mbed_printf_implentation.h) causes the printf functions to be wrapped using _wrap_* instead of $Sub$$*. This commit modifies the pre-processor conditions to check for __GNUC__last in order to correctly substitute the printf functions depending on the toolchain in use. It also gets rid of $Super$$* substitution as it is not needed. $Super$$ is used to identify the original unpatched functions. Missing substitutions for ARM compiler internal optimized "printfs" are also added.
ba01aba
to
3b59f6c
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd still rather see the two sets combined to avoid duplication and potential errors, as suggested in my previous comment. (I've not cross-checked the two files).
Maybe something for a follow-up PR (along with my __attribute__((naked))
suggestion from chat to remove space taken by _printf_c
etc).
But this seems like a valid fix now.
@kjbracey-arm let's get this in for now as it affects nightly :) |
CI started |
Test run: SUCCESSSummary: 11 of 11 test jobs passed |
Summary of changes
As the ARM compiler is in GNU compatible mode, it defines GNU which
$Sub$ $*.
(based on pre-processor condition in mbed_printf_implentation.h)
causes the printf functions to be wrapped using wrap* instead of
This commit modifies the pre-processor
conditions to check for __GNUC__last in order to correctly
substitute the printf functions depending on the toolchain in use.
It also gets rid of$Super$ $* substitution as it is not needed. $Super$ $
is used to identify the original unpatched functions.
Missing substitutions for ARM compiler internal optimized "printfs" are
also added.
Impact of changes
Migration actions required
Documentation
Pull request type
Test results
Reviewers
@kjbracey-arm @evedon