Skip to content

Commit

Permalink
[ext] Catch missing :printf module
Browse files Browse the repository at this point in the history
Accidental use of printf will use the Newlib implementation which uses
heap, thus causing an error message about missing :platform:heap module.
  • Loading branch information
salkinium committed Jan 14, 2024
1 parent d1a6984 commit 7318c28
Show file tree
Hide file tree
Showing 5 changed files with 133 additions and 19 deletions.
1 change: 0 additions & 1 deletion ext/eyalroz/module.lb
Expand Up @@ -19,7 +19,6 @@ def prepare(module, options):

def build(env):
env.collect(":build:path.include", "modm/ext")
env.collect(":build:ccflags", "-fno-builtin-printf")
env.outbasepath = "modm/ext/printf"

env.copy("printf/src/printf/printf.h", "printf.h")
Expand Down
21 changes: 21 additions & 0 deletions ext/eyalroz/module.md
Expand Up @@ -44,3 +44,24 @@ extern "C" void putchar_(char c)
// MODM_LOG_INFO << c;
}
```


## printf is not implemented Error

This module is not included by default and any attempt to use any of the printf
methods fails with one or multiple linker error messages similiar to this:

```
`printf' referenced in section `.text.startup.main'
of main.o: defined in discarded section
`.printf_is_not_implemented!_
_Please_include_the__modm:printf__module_in_your_project!'
of libmodm.a(no_printf.o)
```
This is to prevent you from *accidentally* using the Newlib implementation of
printf, which is very expensive and also dynamically allocated memory.
You can either:
1. Include this module, which provides a fast printf implementation.
2. Provide your own implementation by strongly linking against printf functions.
85 changes: 85 additions & 0 deletions ext/eyalroz/no_printf.c.in
@@ -0,0 +1,85 @@
/*
* Copyright (c) 2024, Niklas Hauser
*
* This file is part of the modm project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
// ----------------------------------------------------------------------------

#include <stdarg.h>
#include <stddef.h>
#include <modm/architecture/utils.hpp>

// ----------------------------------------------------------------------------
modm_weak modm_section("{{ no_printf_section }}")
int vprintf(const char* format, va_list arg)
{
(void) format;
(void) arg;
return 0;
}

modm_weak modm_section("{{ no_printf_section }}")
int vsnprintf(char* s, size_t n, const char* format, va_list arg)
{
(void) s;
(void) n;
(void) format;
(void) arg;
return 0;
}

modm_weak modm_section("{{ no_printf_section }}")
int vsprintf(char* s, const char* format, va_list arg)
{
(void) s;
(void) format;
(void) arg;
return 0;
}

modm_weak modm_section("{{ no_printf_section }}")
int vfctprintf(void (*out)(char c, void* extra_arg), void* extra_arg, const char* format, va_list arg)
{
(void) out;
(void) extra_arg;
(void) format;
(void) arg;
return 0;
}

modm_weak modm_section("{{ no_printf_section }}")
int printf(const char* format, ...)
{
(void) format;
return 0;
}

modm_weak modm_section("{{ no_printf_section }}")
int sprintf(char* s, const char* format, ...)
{
(void) s;
(void) format;
return 0;
}

modm_weak modm_section("{{ no_printf_section }}")
int snprintf(char* s, size_t n, const char* format, ...)
{
(void) s;
(void) n;
(void) format;
return 0;
}

modm_weak modm_section("{{ no_printf_section }}")
int fctprintf(void (*out)(char c, void* extra_arg), void* extra_arg, const char* format, ...)
{
(void) out;
(void) extra_arg;
(void) format;
return 0;
}
33 changes: 15 additions & 18 deletions src/modm/platform/core/cortex/linker.macros
Expand Up @@ -231,14 +231,8 @@ MAIN_STACK_SIZE = {{ options[":platform:cortex-m:main_stack_size"] }};
. = ALIGN(4);
__assertion_table_end = .;
} >{{memory}}

/* We do not call static destructors ever */
/DISCARD/ :
{
*(.fini_array .fini_array.*)
}
%% if with_cpp_exceptions
%#
%% if with_cpp_exceptions
/* C++ exception unwind tables */
.exidx :
{
Expand All @@ -257,24 +251,27 @@ MAIN_STACK_SIZE = {{ options[":platform:cortex-m:main_stack_size"] }};

/* required by libc __libc_fini_array, but never called */
_fini = .;
%% else
%#
/* C++ exception unwind tables are discarded */
%% endif

/DISCARD/ :
{
/* We do not call static destructors ever */
*(.fini_array .fini_array.*)
%% if not with_cpp_exceptions
/* C++ exception unwind tables are discarded */
*(.ARM.extab* .gnu.linkonce.armextab.*)
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
*(.eh_frame*)
}
%% endif
%% if not with_heap
%#
/* Catch use of dynamic memory without `modm:platform:heap` module. */
/DISCARD/ :
{
%% endif
%% if not with_heap
/* Catch use of dynamic memory without `modm:platform:heap` module. */
*({{no_heap_section}})
%% endif
%% if not with_printf
/* Catch use of printf without `modm:printf` module. */
*({{no_printf_section}})
%% endif
}
%% endif
%% endmacro


Expand Down
12 changes: 12 additions & 0 deletions src/modm/platform/core/cortex/module.lb
Expand Up @@ -127,6 +127,11 @@ def common_memories(env):
# See :platform:heap for explanation
common_no_heap_section = (".Heap_is_not_implemented!__"
"Please_include_the__modm:platform:heap__module_in_your_project!")
# See :printf for explanation
common_no_printf_section = (".printf_is_not_implemented!__"
"Please_include_the__modm:printf__module_in_your_project!")



def common_linkerscript(env):
"""
Expand Down Expand Up @@ -170,8 +175,10 @@ def common_linkerscript(env):

"with_cpp_exceptions": env.get(":stdc++:exceptions", False),
"with_heap": env.has_module(":platform:heap"),
"with_printf": env.has_module(":printf"),
"with_crashcatcher": env.has_module(":crashcatcher"),
"no_heap_section": common_no_heap_section,
"no_printf_section": common_no_printf_section,
}
properties.update(common_memories(env))
return properties
Expand Down Expand Up @@ -336,6 +343,11 @@ def build(env):
if not env.has_module(":platform:heap"):
env.substitutions["no_heap_section"] = common_no_heap_section
env.template("../../heap/cortex/no_heap.c.in", "no_heap.c")
# Deprecate printf functions if not implemented!
env.collect(":build:ccflags", "-fno-builtin-printf")
if not env.has_module(":printf"):
env.substitutions["no_printf_section"] = common_no_printf_section
env.template(repopath("ext/eyalroz/no_printf.c.in"), "no_printf.c")

if env.has_module(":architecture:atomic"):
env.template("atomic_lock_impl.hpp.in")
Expand Down

0 comments on commit 7318c28

Please sign in to comment.