Mangle functions
Daniel Lohmann
daniel.lohmann@informatik.uni-erlangen.de
Mon Jan 28 17:22:00 GMT 2008
On 26.01.2008, at 23:15, Ron Kreymborg wrote:
> Is there a way the C++ pre-processor can access the mangled name of
> a class
> method? This would greatly simplify implementing interrupt handlers as
> private class methods in embedded systems where the processor uses an
> interrupt vector table. Currently one must manually build the
> mangled name
> and pass it to the gcc "alias" attribute.
>
> My idea is a macro like:
>
> #define CLASS_ISR(theclassname, themethodname) \
> ISR(theclassname) ISR_ALIASOF(gcc_mangle(theclassname,
> themethodname)); \
> void theclassname::themethodname(void)
>
> where the "gcc_mangle" function is what I am after. If this existed
> it
> would allow automating the creation of classes for embedded systems
> where
> the interrupt handler is a private class method and its "friend"
> status
> allows it access to the class data of the owning device manager
> class. The
> abbreviated example class definitions below show the timer overflow
> interrupt handler for the Timer0 peripheral of an Atmel AVR
> microprocessor:
Hi Ron,
I was looking (and asked for it on this list) for something like that
as well. Apparently, it does not exist. Even not as an extra
(external) pre-processor.
A pragmatic solution is to go the other way round. That is, to give
your C++ identifiers that ought to be interrupt handlers (or otherwise
involved in interacting with non-C++ code) explicit symbol names that
are not mangled. This is possible by an g++ extension that allows you
to explicitly specify the linker name of a symbol via an asm-directive
in its declaration:
>>>
lohmann@mocca:~/tmp$ cat test.cpp
class Foo {
static void IrqHandler() asm("MyFancyIrqHandler");
};
void Foo::IrqHandler() {
}
lohmann@mocca:~/tmp$ g++ -c test.cpp
lohmann@mocca:~/tmp$ nm test.o
00000000 T MyFancyIrqHandler
00000000 A _*MyFancyIrqHandler.eh
<<<
As you can see, the method is exported with the name
"MyFancyIrqHandler" instead of the mangled name
"__ZN3Foo10IrqHandlerEv".
BTW: In your example you used a non-static method. You probably know
that you have to make sure that the this-pointer is passed accordingly
in this case. I just mention it because it is a common cause of subtle
errors in C++/Assembly interaction.
Daniel
> //-------------------------------------------
> class CTimer0Interrupt
> {
> public:
> CTimer0Interrupt();
> ~CTimer0Interrupt();
> private:
> // Overflow interrupt handler.
> void TIMER0_OVF_vect(void) __attribute__ ((signal, __INTR_ATTRS));
> };
>
> //-------------------------------------------
> class CTimer0
> {
> friend class CTimer0Interrupt;
> public:
> CTimer0();
> ~CTimer0();
> int GetTimer0Flag(void); // true if overflow occurred
> private:
> void SetOverflowFlag(void); // called from int handler
> private:
> volatile bool mTimer0Flag;
> CTimer0Interrupt mTimer0Interrupt;
> };
>
> And in the cpp class implementation file, the method is:
>
> //---------------------------------------------------------------
> // Timer0 overflow interrupt handler.
> //
> CLASS_ISR(CTimer0Interrupt, TIMER0_OVF_vect)
> {
> TCNT0 = TIMER0_TIMEOUT; // restart the timeout
> Timer0.SetOverflowFlag(); // tell our friend
> }
>
> Inserting the mangled name by hand in the macro above produces the
> vector
> alias that allows gcc to link the external C vector name while the C+
> + code
> remains unaware of its existence outside the owning class:
>
> extern "C" void __vector_16 (void) __attribute__ ((signal,used,
> externally_visible)) ;
> void __vector_16 (void)
> __attribute__((alias("_ZN16CTimer0Interrupt11__vector_16Ev")));
> void CTimer0Interrupt::__vector_16(void)
> {
> (*(volatile uint8_t *)((0x32) + 0x20)) = 100;
> Timer0.SetOverflowFlag();
> }
>
> Ron Kreymborg
>
>
>
More information about the Gcc-help
mailing list