Prevent GCC LTO from deleting function - c

I work with GCC-ARM-Embedded and FreeRTOS.
FreeRTOS has the function vTaskSwitchContext() which is used only in some
inline assembler code.
The problem is: When I use LTO, GCC does not consider the inline assembler code and thinks the function is not used, thus removes it. The linker then fails because the function call in the inline assembler code cannot be resolved.
I would apply __attribute__((used)) but I don't want to touch the FreeRTOS code (it's generated by STM32CubeMX).
I tried putting this in my code, but actually GCC is smart enough to not allow this to work:
if(false)
vTaskSwitchContext();
Is there some way to tell GCC in a different source file, or via parameter, that this function should not be removed?
Example
// file1.c
void vTaskSwitchContext( void )
{
...
}
// file2.c
void xPortPendSVHandler( void )
{
__asm volatile
(
...
" isb \n"
" bl vTaskSwitchContext \n"
" mov r0, #0 \n"
...
);
}

Try calling the function from a separate function which is marked used.
void dummyFunction(void) __attribute__((used));
// Never called.
void dummyFunction(void) {
vTaskSwitchContext();
}

You can add -Wl,--undefined=vTaskSwitchContext to your LDFLAGS.

For some reason, the solution that Dietrich proposed didn't work for me. I'm using Infineon's DAVE 4 (basically eclipse with a fancy code generation plugin for their line of XMC microcontrollers), which may be the reason why it didn't work. For me, I had to call vTaskSwitchContext() after vTaskStartScheduler():
int main(){
initializationCode();
vTaskStartScheduler();
//Code never reaches here
vTaskSwitchContext();
}

If your version of FreeRTOS uses already uses the macro portDONT_DISCARD for vTaskSwitchContext() you can define portDONT_DISCARD in your own portmacro.h
#define portDONT_DISCARD __attribute__((used))
Essentially backporting https://github.com/FreeRTOS/FreeRTOS-Kernel/commit/07e672c448e2a4ea56ae793f1c6dae26d908b16e

Related

How does gcc treat two functions with different optimizations, when one calls the other?

I searched for a while for an answer for this question, and if it already exists please point me to the right place.
I am investigating optimizing single functions in c compiled with gcc.
I have been able to optimize a single function outside of the general file optimization using:
void __attribute__((optimize("Os"))) Func( void )
{
...
}
But I am unsure of how gcc handles:
void __attribute__((optimize("Os"))) Func1( void )
{
...
}
void __attribute__((optimize("O3"))) Func2( void )
{
Func1();
...
}
Since Func1() is being compiled with -Os it shouldn't be inlined, and I was fairly sure that I would find that I ended up with a result where everything in Func2() optimized to -03, except for the call to Func1(). But the results I am seeing say otherwise. This leads me to believe that I am doing something wrong or don't understand the implementation of gcc correctly.
Does the -O3 optimization attribute on func2() get applied to everything inside Func2(), which would separately compile func1() with -03 for use of inlining inside the func2() call?

How to intercept a static library call in C language?

Here's my question:
There is a static library (xxx.lib) and some C files who are calling function foo() in xxx.lib. I'm hoping to get a notification message every time foo() is called. But I'm not allowed to change any source code written by others.
I've spent several days searching on the Internet and found several similar Q&As but none of these suggestions could really solve my problem. I list some of them:
use gcc -wrap: Override a function call in C
Thank god, I'm using Microsoft C compiler and linker, and I can't find an equivalent option as -wrap.
Microsoft Detours:
Detours intercepts C calls in runtime and re-direct the call to a trampoline function. But Detours is only free for IA32 version, and it's not open source.
I'm thinking about injecting a jmp instruction at the start of function foo() to redirect it to my own function. However it's not feasible when foo()is empty, like
void foo() ---> will be compiled into 0xC3 (ret)
{ but it'll need at least 8 bytes to inject a jmp
}
I found a technology named Hotpatch on MSDN. It says the linker will add serveral bytes of padding at the beginning of each function. That's great, because I can replace the padding bytes with jmp instruction to realize the interception in runtime! But when I use the /FUNCTIONPADMIN option with the linker, it gives me a warning:
LINK : warning LNK4044: unrecognized option '/FUNCTIONPADMIN'; ignored
Anybody could tell me how could I make a "hotpatchable" image correctly? Is it a workable solution for my question ?
Do I still have any hope to realize it ?
If you have the source, you can instrument the code with GCC without changing the source by adding -finstrument-functions for the build of the files containing the functions you are interested in. You'll then have to write __cyg_profile_func_enter/exit functions to print your tracing. An example from here:
#include <stdio.h>
#include <time.h>
static FILE *fp_trace;
void
__attribute__ ((constructor))
trace_begin (void)
{
fp_trace = fopen("trace.out", "w");
}
void
__attribute__ ((destructor))
trace_end (void)
{
if(fp_trace != NULL) {
fclose(fp_trace);
}
}
void
__cyg_profile_func_enter (void *func, void *caller)
{
if(fp_trace != NULL) {
fprintf(fp_trace, "e %p %p %lu\n", func, caller, time(NULL) );
}
}
void
__cyg_profile_func_exit (void *func, void *caller)
{
if(fp_trace != NULL) {
fprintf(fp_trace, "x %p %p %lu\n", func, caller, time(NULL));
}
}
Another way to go if you have source to recompile the library as a shared library. From there it is possible to do runtime insertions of your own .so/.dll using any number of debugging systems. (ltrace on unix, something or other on windows [somebody on windows -- please edit]).
If you don't have source, then I would think your option 3 should still work. Folks writing viruses have been doing it for years. You may have to do some manual inspection (because x86 instructions aren't all the same length), but the trick is to pull out a full instruction and replace it with a jump to somewhere safe. Do what you have to do, get the registers back into the same state as if the instruction you removed had run, then jump to just after the jump instruction you inserted.
The VC compiler provides 2 options /Gh & /GH for hooking functions.
The /Gh flag causes a call to the _penter function at the start of every method or function, and the /GH flag causes a call to the _pexit function at the end of every method or function.
So, if I write some code in _penter to find out the address of the caller function, then I'll be able to intercept any function selectively by comparing the function address.
I made a sample:
#include <stdio.h>
void foo()
{
}
void bar()
{
}
void main() {
bar();
foo();
printf ("I'm main()!");
}
void __declspec(naked) _cdecl _penter( void )
{
__asm {
push ebp; // standard prolog
mov ebp, esp;
sub esp, __LOCAL_SIZE
pushad; // save registers
}
unsigned int addr;
// _ReturnAddress always returns the address directly after the call, but that is not the start of the function!
// subtract 5 bytes as instruction for call _penter
// is 5 bytes long on 32-bit machines, e.g. E8 <00 00 00 00>
addr = (unsigned int)_ReturnAddress() - 5;
if (addr == foo) printf ("foo() is called.\n");
if (addr == bar) printf ("bar() is called.\n");
_asm {
popad; // restore regs
mov esp, ebp; // standard epilog
pop ebp;
ret;
}
}
Build it with cl.exe source.c /Gh and run it:
bar() is called.
foo() is called.
I'm main()!
It's perfect!
More examples about how to use _penter and _pexit can be found here A Simple Profiler and tracing with penter pexit and A Simple C++ Profiler on x64.
I've solved my problem using this method, and I hope it can help you also.
:)
I don't think there is any to do this without changing any code.
Easiest way I can think of is to do this is to write wrapper for your void foo() function and Find/Replace it with your wrapper.
void myFoo(){
return foo();
}
Instead of calling foo() call myFoo().
Hope this will help you.

Tell gcc that a function call will not return

I am using C99 under GCC.
I have a function declared static inline in a header that I cannot modify.
The function never returns but is not marked __attribute__((noreturn)).
How can I call the function in a way that tells the compiler it will not return?
I am calling it from my own noreturn function, and partly want to suppress the "noreturn function returns" warning but also want to help the optimizer etc.
I have tried including a declaration with the attribute but get a warning about the repeated declaration.
I have tried creating a function pointer and applying the attribute to that, but it says the function attribute cannot apply to a pointed function.
From the function you defined, and which calls the external function, add a call to __builtin_unreachable which is built into at least GCC and Clang compilers and is marked noreturn. In fact, this function does nothing else and should not be called. It's only here so that the compiler can infer that program execution will stop at this point.
static inline external_function() // lacks the noreturn attribute
{ /* does not return */ }
__attribute__((noreturn)) void your_function() {
external_function(); // the compiler thinks execution may continue ...
__builtin_unreachable(); // ... and now it knows it won't go beyond here
}
Edit: Just to clarify a few points raised in the comments, and generally give a bit of context:
A function has has only two ways of not returning: loop forever, or short-circuit the usual control-flow (e.g. throw an exception, jump out of the function, terminate the process, etc.)
In some cases, the compiler may be able to infer and prove through static analysis that a function will not return. Even theoretically, this is not always possible, and since we want compilers to be fast only obvious/easy cases are detected.
__attribute__((noreturn)) is an annotation (like const) which is a way for the programmer to inform the compiler that he's absolutely sure a function will not return. Following the trust but verify principle, the compiler tries to prove that the function does indeed not return. If may then issue an error if it proves the function may return, or a warning if it was not able to prove whether the function returns or not.
__builtin_unreachable has undefined behaviour because it is not meant to be called. It's only meant to help the compiler's static analysis. Indeed the compiler knows that this function does not return, so any following code is provably unreachable (except through a jump).
Once the compiler has established (either by itself, or with the programmer's help) that some code is unreachable, it may use this information to do optimizations like these:
Remove the boilerplate code used to return from a function to its caller, if the function never returns
Propagate the unreachability information, i.e. if the only execution path to a code points is through unreachable code, then this point is also unreachable. Examples:
if a function does not return, any code following its call and not reachable through jumps is also unreachable. Example: code following __builtin_unreachable() is unreachable.
in particular, it the only path to a function's return is through unreachable code, the function can be marked noreturn. That's what happens for your_function.
any memory location / variable only used in unreachable code is not needed, therefore settings/computing the content of such data is not needed.
any computations which is probably (1) unnecessary (previous bullet) and (2) has no side effects (such as pure functions) may be removed.
Illustration:
The call to external_function cannot be removed because it might have side-effects. In fact, it probably has at least the side effect of terminating the process!
The return boiler plate of your_function may be removed
Here's another example showing how code before the unreachable point may be removed
int compute(int) __attribute((pure)) { return /* expensive compute */ }
if(condition) {
int x = compute(input); // (1) no side effect => keep if x is used
// (8) x is not used => remove
printf("hello "); // (2) reachable + side effect => keep
your_function(); // (3) reachable + side effect => keep
// (4) unreachable beyond this point
printf("word!\n"); // (5) unreachable => remove
printf("%d\n", x); // (6) unreachable => remove
// (7) mark 'x' as unused
} else {
// follows unreachable code, but can jump here
// from reachable code, so this is reachable
do_stuff(); // keep
}
Several solutions:
redeclaring your function with the __attribute__
You should try to modify that function in its header by adding __attribute__((noreturn)) to it.
You can redeclare some functions with new attribute, as this stupid test demonstrates (adding an attribute to fopen) :
#include <stdio.h>
extern FILE *fopen (const char *__restrict __filename,
const char *__restrict __modes)
__attribute__ ((warning ("fopen is used")));
void
show_map_without_care (void)
{
FILE *f = fopen ("/proc/self/maps", "r");
do
{
char lin[64];
fgets (lin, sizeof (lin), f);
fputs (lin, stdout);
}
while (!feof (f));
fclose (f);
}
overriding with a macro
At last, you could define a macro like
#define func(A) {func(A); __builtin_unreachable();}
(this uses the fact that inside a macro, the macro name is not macro-expanded).
If your never-returning func is declaring as returning e.g. int you'll use a statement expression like
#define func(A) ({func(A); __builtin_unreachable(); (int)0; })
Macro-based solutions like above won't always work, e.g. if func is passed as a function pointer, or simply if some guy codes (func)(1) which is legal but ugly.
redeclaring a static inline with the noreturn attribute
And the following example:
// file ex.c
// declare exit without any standard header
void exit (int);
// define myexit as a static inline
static inline void
myexit (int c)
{
exit (c);
}
// redeclare it as notreturn
static inline void myexit (int c) __attribute__ ((noreturn));
int
foo (int *p)
{
if (!p)
myexit (1);
if (p)
return *p + 2;
return 0;
}
when compiled with GCC 4.9 (from Debian/Sid/x86-64) as gcc -S -fverbose-asm -O2 ex.c) gives an assembly file containing the expected optimization:
.type foo, #function
foo:
.LFB1:
.cfi_startproc
testq %rdi, %rdi # p
je .L5 #,
movl (%rdi), %eax # *p_2(D), *p_2(D)
addl $2, %eax #, D.1768
ret
.L5:
pushq %rax #
.cfi_def_cfa_offset 16
movb $1, %dil #,
call exit #
.cfi_endproc
.LFE1:
.size foo, .-foo
You could play with #pragma GCC diagnostic to selectively disable a warning.
Customizing GCC with MELT
Finally, you could customize your recent gcc using the MELT plugin and coding your simple extension (in the MELT domain specific language) to add the attribute noreturn when encoutering the desired function. It is probably a dozen of MELT lines, using register_finish_decl_first and a match on the function name.
Since I am the main author of MELT (free software GPLv3+) I could perhaps even code that for you if you ask, e.g. here or preferably on gcc-melt#googlegroups.com; give the concrete name of your never-returning function.
Probably the MELT code is looking like:
;;file your_melt_mode.melt
(module_is_gpl_compatible "GPLv3+")
(defun my_finish_decl (decl)
(let ( (tdecl (unbox :tree decl))
)
(match tdecl
(?(tree_function_decl_named
?(tree_identifier ?(cstring_same "your_function_name")))
;;; code to add the noreturn attribute
;;; ....
))))
(register_finish_decl_first my_finish_decl)
The real MELT code is slightly more complex. You want to define your_adding_attr_mode there. Ask me for more.
Once you coded your MELT extension your_melt_mode.melt for your needs (and compiled that MELT extension into your_melt_mode.quicklybuilt.so as documented in the MELT tutorials) you'll compile your code with
gcc -fplugin=melt \
-fplugin-arg-melt-extra=your_melt_mode.quicklybuilt \
-fplugin-arg-melt-mode=your_adding_attr_mode \
-O2 -I/your/include -c yourfile.c
In other words, you just add a few -fplugin-* flags to your CFLAGS in your Makefile !
BTW, I'm just coding in the MELT monitor (on github: https://github.com/bstarynk/melt-monitor ..., file meltmom-process.melt something quite similar.
With a MELT extension, you won't get any additional warning, since the MELT extension would alter the internal GCC AST (a GCC Tree) of the declared function on the fly!
Customizing GCC with MELT is probably the most bullet-proof solution, since it is modifying the GCC internal AST. Of course, it is probably the most costly solution (and it is GCC specific and might need -small- changes when GCC is evolving, e.g. when using the next version of GCC), but as I am trying to show it is quite easy in your case.
PS. In 2019, GCC MELT is an abandoned project. If you want to customize GCC (for any recent version of GCC, e.g. GCC 7, 8, or 9), you need to write your own GCC plugin in C++.

Undefined reference calling an assembly function in C

I just cannot find the solution to this issue..
What I'm trying to do is calling an assembly function using gcc. Just take a look:
// Somewhere in start.s
global _start_thread
_start_thread:
; ...
// Somewhere in UserThread.cpp
extern void _start_thread( pointer );
static void UserMainHack()
{
_start_thread(((UserThread*)currentThread)->getUserMain());
}
Thanks for any help..
Did you know that many C linkers automatically adds the leading underscore when looking for identifiers? So in the C source (not the assembler source), just remove the leading underscore:
extern void start_thread( pointer );
static void UserMainHack()
{
start_thread(((UserThread*)currentThread)->getUserMain());
}
Give your function [declaration] assembly linkage by using an "Asm Label":
extern void start_thread(pointer) __asm__("start_thread");
(and have the .global on the asm side match it.)
It works much like extern "C" in that it can be used for both functions and variables, and that it's one-sided (but on the C side this time).

C functions before mainCRTStartup on Mingw?

void start() {
stuff(); //code before mainCRTStartup
mainCRTStartup();
}
int main()
{
//other code
}
In Visual C++,it compiles fine and function "stuff()" gets called before main. How would call "stuff()" before "mainCRTStartup()"? on Mingw(OS:Windows NT)? it seems to ignore "void start()".
You could use the -e argument to ld (the linker) to specify start as your entry point.
I'm not sure how to feed arguments to ld using mingw; perhaps someone can edit my answer to provide that.
The real entry point is always start().
start() calls mainCRTStartup() that initializes CRT functions and call main(), so in stuff(), you can not use CRT functions.

Resources