Skip to content

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

Merged
merged 1 commit into from
Jan 13, 2020

Conversation

hugueskamba
Copy link
Collaborator

@hugueskamba hugueskamba commented Jan 10, 2020

Summary of changes

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.

Impact of changes

Migration actions required

Documentation


Pull request type

[X] Patch update (Bug fix / Target update / Docs update / Test update / Refactor)
[] Feature update (New feature / Functionality change / New API)
[] Major update (Breaking change E.g. Return code change / API behaviour change)

Test results

[] No Tests required for this change (E.g docs only update)
[X] Covered by existing mbed-os tests (Greentea or Unittest)
[] Tests / results supplied as part of this PR

Reviewers

@kjbracey-arm @evedon


@evedon
Copy link
Contributor

evedon commented Jan 10, 2020

Based on the documentation you found, shouldn't we also modify the wrapping for vprintf?

@hugueskamba
Copy link
Collaborator Author

Based on the documentation you found, shouldn't we also modify the wrapping for vprintf?

I have not found any documentation that says that __2vsnprintf does not exist. What I found was documentation about the printf functions that have optimised __Nprintf variants. It does not mention vprintf family of functions so I assumed vsnprintf does not have such optimised variants. I tested it because mbed_error_printf uses vnsprintf.

I have nothing to suggest that __Nvprintf does not exist, I would have to test vprintf with a sample application.

@hugueskamba hugueskamba force-pushed the hk-minimal_printf-fix-vsnprintf branch from a401a3e to b2483c1 Compare January 10, 2020 17:13
@hugueskamba hugueskamba changed the title Minimal-printf: Fix wrapping of vsnprintf for ARM compiler Minimal-printf: Fix wrapping of vsnprintf and vprintf for ARM compiler Jan 10, 2020
@hugueskamba hugueskamba force-pushed the hk-minimal_printf-fix-vsnprintf branch from b2483c1 to fb075bc Compare January 10, 2020 17:14
@hugueskamba
Copy link
Collaborator Author

Based on the documentation you found, shouldn't we also modify the wrapping for vprintf?

I have not found any documentation that says that __2vsnprintf does not exist. What I found was documentation about the printf functions that have optimised __Nprintf variants. It does not mention vprintf family of functions so I assumed vsnprintf does not have such optimised variants. I tested it because mbed_error_printf uses vnsprintf.

I have nothing to suggest that __Nvprintf does not exist, I would have to test vprintf with a sample application.

@evedon
vprintf substitution function had an incorrect signature and its content was also wrong.
This force-push adds the fix for vprintf. The PR description and title have been updated.
Thanks

@0xc0170
Copy link
Contributor

0xc0170 commented Jan 13, 2020

CI started

Copy link
Contributor

@kjbracey kjbracey left a 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)
Copy link
Contributor

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?

Copy link
Collaborator Author

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.

Copy link
Contributor

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.

Copy link
Collaborator Author

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.

Copy link
Contributor

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.

Copy link
Contributor

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

Copy link
Contributor

@kjbracey kjbracey Jan 13, 2020

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 *, ...)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@mbed-ci
Copy link

mbed-ci commented Jan 13, 2020

Test run: SUCCESS

Summary: 11 of 11 test jobs passed
Build number : 1
Build artifacts

@hugueskamba hugueskamba force-pushed the hk-minimal_printf-fix-vsnprintf branch from fb075bc to 99cd2ce Compare January 13, 2020 11:11
@hugueskamba hugueskamba changed the title Minimal-printf: Fix wrapping of vsnprintf and vprintf for ARM compiler Minimal-printf: Fix wrapping of printf functions for the ARM compiler Jan 13, 2020
@hugueskamba hugueskamba force-pushed the hk-minimal_printf-fix-vsnprintf branch from 99cd2ce to ba01aba Compare January 13, 2020 11:15
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.
@hugueskamba hugueskamba force-pushed the hk-minimal_printf-fix-vsnprintf branch from ba01aba to 3b59f6c Compare January 13, 2020 11:25
Copy link
Contributor

@kjbracey kjbracey left a 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.

@adbridge
Copy link
Contributor

@kjbracey-arm let's get this in for now as it affects nightly :)

@adbridge adbridge added needs: CI release-version: 6.0.0-alpha-1 First pre-release version of 6.0.0 and removed needs: work labels Jan 13, 2020
@adbridge
Copy link
Contributor

CI started

@mbed-ci
Copy link

mbed-ci commented Jan 13, 2020

Test run: SUCCESS

Summary: 11 of 11 test jobs passed
Build number : 2
Build artifacts

@0xc0170 0xc0170 removed the needs: CI label Jan 13, 2020
@0xc0170 0xc0170 merged commit 9243abb into ARMmbed:master Jan 13, 2020
@hugueskamba hugueskamba deleted the hk-minimal_printf-fix-vsnprintf branch January 14, 2020 08:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
release-version: 6.0.0-alpha-1 First pre-release version of 6.0.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants