xref: /aosp_15_r20/external/pigweed/pw_toolchain/arm_gcc/newlib_os_interface_stubs.cc (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1 // Copyright 2022 The Pigweed Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
5 // the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
13 // the License.
14 
15 #include <sys/stat.h>   // POSIX header provided by Newlib; needed for stat.
16 #include <sys/times.h>  // POSIX header provided by Newlib; needed for times.
17 
18 #include <cstdio>  // fpos_t
19 
20 #include "pw_assert/check.h"
21 
22 namespace pw::toolchain {
23 namespace {
24 
AbortIfUnsupportedNewlibFunctionIsCalled()25 [[noreturn]] void AbortIfUnsupportedNewlibFunctionIsCalled() {
26   PW_CRASH(
27       "Attempted to invoke an unsupported Newlib function! The stdout and "
28       "stderr FILE objects are not supported.");
29 }
30 
31 }  // namespace
32 
33 // Wrap the stdio read, write, seek, and close Newlib functions defined in
34 // libc/stdio/stdio.c. These should never be called, so abort if they are.
35 //
36 // These functions are unconditionally linked, even if they're never called,
37 // because they are assigned as members of the stdout/stderr FILE struct. The
38 // Newlib implementations invoke some of the unsupported OS interface functions.
39 #define PW_WRAP_NEWLIB_FILE_FUNCTION(function, ...) \
40   extern "C" int __wrap_##function(__VA_ARGS__) {   \
41     AbortIfUnsupportedNewlibFunctionIsCalled();     \
42   }
43 
44 PW_WRAP_NEWLIB_FILE_FUNCTION(__sread, void*, char*, int)
45 PW_WRAP_NEWLIB_FILE_FUNCTION(__swrite, void*, char*, int)
46 PW_WRAP_NEWLIB_FILE_FUNCTION(__sseek, void*, fpos_t, int)
47 PW_WRAP_NEWLIB_FILE_FUNCTION(__sclose, void*)
48 
49 #undef PW_WRAP_NEWLIB_FILE_FUNCTION
50 
51 // Newlib defines a set of OS interface functions. Most of these should never be
52 // called, since they're used by libc functions not supported in Pigweed (e.g.
53 // fopen or printf). If they're linked into a binary, that indicates that an
54 // unsupported function was called.
55 //
56 // Newlib provides default, nop implementations of these functions. Starting
57 // with arm-none-eabi-gcc 11.3, a warning is issued when any of these defaults
58 // are used.
59 //
60 // Provide implementations for most of the Newlib OS interface functions, which
61 // are documented at https://sourceware.org/newlib/libc.html#Stubs. The default
62 // implementation calls the following function, which is never defined,
63 // resulting in a linker error.
64 [[noreturn]] void AttemptedToInvokeUnsupportedNewlibOsInterfaceFunction();
65 
66 #define PW_DISABLE_NEWLIB_FUNCTION(function, ...)            \
67   extern "C" int _##function(__VA_ARGS__) {                  \
68     AttemptedToInvokeUnsupportedNewlibOsInterfaceFunction(); \
69   }
70 
PW_DISABLE_NEWLIB_FUNCTION(_exit,void)71 PW_DISABLE_NEWLIB_FUNCTION(_exit, void)
72 PW_DISABLE_NEWLIB_FUNCTION(close, int)
73 PW_DISABLE_NEWLIB_FUNCTION(execve, char*, char**, char**)
74 PW_DISABLE_NEWLIB_FUNCTION(fork, void)
75 
76 // Provide the minimal fstat implementation recommended by the Newlib
77 // documentation since fstat is called indirectly by snprintf.
78 extern "C" int _fstat(int, struct stat* st) {
79   st->st_mode = S_IFCHR;
80   return 0;
81 }
82 
PW_DISABLE_NEWLIB_FUNCTION(getpid,void)83 PW_DISABLE_NEWLIB_FUNCTION(getpid, void)
84 
85 // Provide the minimal isatty implementation recommended by the Newlib
86 // documentation since isatty is called indirectly by snprintf.
87 extern "C" int _isatty(int) { return 1; }
88 
89 PW_DISABLE_NEWLIB_FUNCTION(gettimeofday, struct timeval*, struct timezone*)
90 PW_DISABLE_NEWLIB_FUNCTION(kill, int, int)
91 PW_DISABLE_NEWLIB_FUNCTION(link, char*, char*)
92 PW_DISABLE_NEWLIB_FUNCTION(lseek, int, int, int)
93 PW_DISABLE_NEWLIB_FUNCTION(open, const char*, int, int)
94 PW_DISABLE_NEWLIB_FUNCTION(read, int, char*, int)
95 PW_DISABLE_NEWLIB_FUNCTION(sbrk, int)
96 PW_DISABLE_NEWLIB_FUNCTION(stat, char*, struct stat*)
97 PW_DISABLE_NEWLIB_FUNCTION(times, struct tms*)
98 PW_DISABLE_NEWLIB_FUNCTION(unlink, char*)
99 PW_DISABLE_NEWLIB_FUNCTION(wait, int*)
100 PW_DISABLE_NEWLIB_FUNCTION(write, int, char*, int)
101 
102 #undef PW_DISABLE_NEWLIB_FUNCTION
103 
104 }  // namespace pw::toolchain
105