Re: Mangle functions

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 




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





[Index of Archives]     [Linux C Programming]     [Linux Kernel]     [eCos]     [Fedora Development]     [Fedora Announce]     [Autoconf]     [The DWARVES Debugging Tools]     [Yosemite Campsites]     [Yosemite News]     [Linux GCC]

  Powered by Linux