[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [avr-gcc-list] [patch, avr-libc] Fix atexit.c
From: |
Georg-Johann Lay |
Subject: |
Re: [avr-gcc-list] [patch, avr-libc] Fix atexit.c |
Date: |
Wed, 15 Oct 2014 12:49:46 +0200 |
User-agent: |
Mozilla/5.0 (X11; Linux i686; rv:24.0) Gecko/20100101 Thunderbird/24.6.0 |
Am 10/14/2014 04:07 PM, schrieb Joern Rennecke:
atexit.c has several issues which are fixed by the patch below:
i)
Issuance of calls to functions as registered by atexit() is located in
section .fini6a. As the current linker description does not handle that
section it's treated as orphan and located conflicting with other sections:
I actually wrote a binutils patch at the same time as the atexit implementation:
address@hidden:embecosm/avr-binutils-gdb.git branch avr-mainline commit
640411f2fb984e70c4ab06154089692db1734a97
I just haven't gotten around to push this to the main repo yet.
Ok, I updated the patch request (#8556) to use .fini8 instead of .fini7 to call
atexit functions.
ii)
__atexit_fini is not naked thus will crash the program as it is returning.
Good point. However, I'd prefer to add a new attribute to just say
that the function returns by falling through at the end.
Opinions on how to name this? "fallthrough" ? "return_falls_through" ?
"ctor_dtor" (although that can get confusing with the constructor /
destructor attribute) ?
Some time ago I thought about adding a new function attribute to avr-gcc that
injects code at prologue / epilogue. That way an application could instrument
particular functions with particular code. Such an attribute would cover the
feature you are proposing if the attribute is generic enough. That new
attribute would allow to:
- specify the (assembler) code to be injected as plain C-string
- specify where to inject the code:
-- before prologue
-- after prologue
-- instead of prologue
-- before epilogue
-- after epilogue
-- instead of epilogue
Cases like "after epilogue" make only sense for special functions like "naked",
but you could achieve "naked" also by replacing epilogue with the injected code
and removing prologue (by injecting "" as replacement for prologue by means of
a second such attribute).
A naked function could then be modelled as:
__attribute__((instrument ("", replace_prologue),
instrument ("", replace_epilogue)))
void fun ...
Such instrumentation could provide better control of code generation in cases
like:
- instrumenting individual functions with specific for home-made profiling /
performance measurement
- writing ISRs that need to manipulate stack, e.g. patch return address
- writing startup code as of your use case
- ...
Replacing / removing epilogue by an attribute is not enough: BBRO and all
passes running after .prologue_epilogue must not reorder blocks and a function
must not have more than one epilogue, cf. also GCC PR42240. And such a
function must not be inlined or considered for cloning and the emit insn
representing the code chunk must not be moved across any other insn.
As I had no use case by myself and I never came across a request for such a new
attribute / feature, I didn't start coding on it, ... would have been dead
code in GCC.
For a real application it might also be interesting
- how much registers are saved / would be saved on the stack
- whether the function ends with a tail call
- whether the function needs a frame pointer
- how much frame space is set up by the function
- whether the function is a leaf function
- the C name of the function
- the assembler name of the function
- maybe more
That information could be supplied by special %-codes like scheme.
Overload the meaning of the section attribute so that .init / .fini
section 'magically'causes the different return?
These section names are already in widespread use, not only for code to be run
before main. Adding magic and implicit behaviour is not a good approach, IMO,
in particular if a feature is not new and is being used in the field.
+atexit_finido (void)
{
- while (__atexit_p)
+ while (atexit_p)
{
- void (*fun) (void) = __atexit_p->fun;
- __atexit_p = __atexit_p->next;
- (*fun) ();
+ atexit_p->fun();
+ atexit_p = atexit_p->next;
This introduces a bug. If the called function calls exit (e.g.
because it throws
an error), you get an infinite recursion. The pointer must be updated before
the function is called.
Thanks for the hint, updated #8556 accordingly.
Seems my brain has not yet enough weird windings...
Johann