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