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

Re: [rtems-users] C++ Virtual Functions



Joel Sherrill <joel@OARcorp.com> wrote, On 2/1/2005 4:07 PM:

gregory.menke@gsfc.nasa.gov wrote:

Smith, Gene writes:
> I am having some problems running code containing C++ virtual functions in
> rtems. When the code tries to branch to a virtual function address using
> "bctrl" instruction, the address (in ctr) is way out of range and results in
> a machine check exception.
> > Is there anything I need to do special in rtems for virtual functions to
> work? Is anyone using virtual functions, pure or impure, in rtems? I am
> still using rtems 4.6.1 and my ppc40x-derived bsp.
> > Tks,
> -gene


This is generally caused by problem with the linkscript where the
various tables are set up incorrectly.  The motorola_shared bsp link
script works, so you might compare them for discrepancies.  It might
also be related to your gcc- but I'd check the linkscript first.

Are you referring to the powerpc/motorola_powerpc/startup/linkcmds when you say "motorola_shared"? I appears similar to the psim version in cvs.




psim on the CVS head and post 4.6.2 on the 4.6 branch is also supposed
to work for C++.

Look at the bsp_specs as well for crt*.

If you have a simple example, you want tried on another BSP, post it.

Don't have a simple example.

Thanks for responses. The vtable addresses look ok when dumped with nm.
I see crt* in bsp_spec which is unchanged from helas and ppc40x bsp's.
However 4.6.1 psim is some different (crt in *startfile instead of
*lib). No idea what this means.

However, I think I see basically how things are going wrong. The derived
class containing the virtual function implementation is instantiated as
a global variable. I never actually see its constructor being called
(and it should occur before main I think I have read). It is showing up
in section .bss according to objdump. Therefore, it is getting zeroed
out at startup, including the _vptr value. At least I think that is
happening.

When I look at the psim head linkcmd file in CVS I see differences
regarding placement of CTOR and DTOR stuff. I probably need to tailor my
linkcmds file to be more like the head (1.18.2.4) psim version. Does
this sound reasonable? Or can someone point out to me what might be
wrong in my current linkcmds file, attached.

Thanks for the help.
-gene

P/S: The attached linkcmds actually just builds a image that runs from
ram with no rom yet involved. I load it to ram with a jtag debugger.
/*
 *  This file contains directives for the GNU linker which are specific
 *  to my ppc405 bsp (based on helas-403).
 *  This file is intended to be used together with flashentry.s
 *  it will generate a ROM that can be started directly after powerup reset
 *  See the manual "Using ld -- The GNU Linker" for syntax details.
 */

OUTPUT_FORMAT("elf32-powerpc", "elf32-powerpc",
              "elf32-powerpc")
OUTPUT_ARCH(powerpc)
 
ENTRY(flash_entry)
 
MEMORY
  {
        RAM : ORIGIN = 0, LENGTH = 64M
        FLASH : ORIGIN = 0xFFC00000, LENGTH = 4M
  }

  /* Kluge from helas: repeat addresses here, so we can work with them... */
  /* Could this be moved above MEMORY and use the symbols therein? -gds */
  flash.start = 0xFFC00000;
  flash.size  = 4M; 

  /* Address .data copied to. Must be above rtems workspace which is
   * currently set very large (4M)
   */
  DATA_DEST = 0xC00000;

SECTIONS
{
  /*
   * these are the locations where various interrupt types begin their 
   * execution.
   */
  .vectors 0x00000100 :
  {
    *(.vectors)
    . = ALIGN(0x10);
    copy.tmptop.vec = . ;
  } > RAM

  .entry :
  {
     entry.start = . ;	  
     *(.entry)
  } > RAM 

  /*
   * contains the code and constant and string data.
   */
  .text : 
  {
     text.start = . ;
     *(.entry2)
     *(.text)
     *(.gnu.linkonce.t.*)
     *(.rodata*)
     *(.gnu.linkonce.r.*)
     *(.rodata1)

     /*
      * Special FreeBSD sysctl sections.
      */
     . = ALIGN (16);
     __start_set_sysctl_set = .;
     *(set_sysctl_*);
     __stop_set_sysctl_set = ABSOLUTE(.);
     *(set_domain_*);
     *(set_pseudo_*);

     *(.eh_frame)
     *(.descriptors)
     *(rom_ver)
     etext = ALIGN(0x10);
     _etext = .;


     __CTOR_LIST__ = .;
     LONG((__CTOR_END__ - __CTOR_LIST__) / 4 - 2)
     *(.ctors)
     LONG(0)
     __CTOR_END__ = .;

     __DTOR_LIST__ = .;
     LONG((__DTOR_END__ - __DTOR_LIST__) / 4 - 2)
     *(.dtors)
     LONG(0)
     __DTOR_END__ = .;

     *(.lit)
     *(.shdata)
     _init = .; *(.init)
     _fini = .; *(.fini)
     . = ALIGN(0x10);
     _endtext = .;
     text.end = .;
     copy.tmptop.txt = .;
  } > RAM /* .text is the program code and constant strings etc. */

  text.size = text.end - text.start;

  /*
   * contains the non-constant but initialized data
   * Load right after .text but make copy at higher 
   * address at startup and use that during runtime.
   * Should allow a simple restart by running from
   * reset vector, currently 0x2010. I.e., in gdb:
   * >mon reg pc=0x2010
   * >c
   * Need to locate in RAM somewhere above rtems workspace.
   */
  copy.src = . ;
  .data DATA_DEST : AT (copy.src) 
  {
    copy.dest = . ;
    *(.data)
    *(.data1)
    *(.data.* .gnu.linkonce.d*)
    PROVIDE (__SDATA_START__ = .);
    *(.sdata)
    *(.gnu.linkonce.s.*)
    . = ALIGN(0x10);
    copy.tmptop.dat = .;
  } > RAM

  copy.size = copy.tmptop.dat - copy.dest;
  
  /*
   * Following are sections I am not real familiar with.
   * Keep them following .data load address, not above DATA_DEST.
   */
  except.start = copy.src + copy.size ;
  PROVIDE (__EXCEPT_START__ = except.start);
  .gcc_except_table except.start  : 
  { 
    *(.gcc_except_table) 
    . = ALIGN(0x10);
    copy.tmptop.exc = .;
  } >RAM
  PROVIDE (__EXCEPT_END__ = .);

  __GOT_START__ = .;
  .got :
  {
    s.got = .;
    *(.got.plt) *(.got)
    . = ALIGN(0x10);
    copy.tmptop.got = .;
  } > RAM
  __GOT_END__ = .;

  .got1 :
  { 
    *(.got1) 		
    . = ALIGN(0x10);
    copy.tmptop.gt1 = .;
  } >RAM

  PROVIDE (__GOT2_START__ = .);
  PROVIDE (_GOT2_START_ = .);
  .got2		  :
  { 
    *(.got2) 	
    . = ALIGN(0x10);
    copy.tmptop.gt2 = .;
  } >RAM
  PROVIDE (__GOT2_END__ = .);
  PROVIDE (_GOT2_END_ = .);

  PROVIDE (__FIXUP_START__ = .);
  PROVIDE (_FIXUP_START_ = .);
  .fixup	  :
  { 
    *(.fixup) 	
    . = ALIGN(0x10);
    copy.tmptop.fix = .;
  } >RAM
  PROVIDE (_FIXUP_END_ = .);
  PROVIDE (__FIXUP_END__ = .);
 
  PROVIDE (__SDATA2_START__ = .);
  .sdata2   	  :
  { 
    *(.sdata2) 	
    . = ALIGN(0x10);
    copy.tmptop.sda = .;
  } >RAM


  /*
   * bss is uninitialzed and non-constant data. It will be
   * zero'd. Not sure what .sbss2 is but I suppose it is
   * similar to bss (but not zero'd) 
   */
  .sbss2   	  : 
  { 
    *(.sbss2) 	
  } >RAM
  PROVIDE (__SBSS2_END__ = .);

  __SBSS_START__ = .;
  .bss :
  {
    bss.start = .;
    *(.bss) *(.sbss) *(COMMON)
    bss.end = ALIGN(4);
  } > RAM
  __SBSS_END__ = .;
 
  bss.size = bss.end - bss.start;
  PROVIDE(_end = bss.end);

  /* reserve 512K (4096K) for heap -- default from gen405 --- tbd gds */
  heap.end = bss.end + 4096K;
  PROVIDE(_heap_end = heap.end);
  /* reserve 64KByte for stack... -- default from gen405 -- tbd gds */
  stack.end = heap.end + 64K;
  PROVIDE(_wksp_start = stack.end);

  /* Stabs debugging sections.  */
  .stab 0 : { *(.stab) }
  .stabstr 0 : { *(.stabstr) }
  .stab.excl 0 : { *(.stab.excl) }
  .stab.exclstr 0 : { *(.stab.exclstr) }
  .stab.index 0 : { *(.stab.index) }
  .stab.indexstr 0 : { *(.stab.indexstr) }
  .comment 0 : { *(.comment) }

  /* DWARF debug sections.
     Symbols in the DWARF debugging sections are relative to the beginning
     of the section so we begin them at 0.  */
  /* DWARF 1 */
  .debug          0 : { *(.debug) }
  .line           0 : { *(.line) }
  
  /* GNU DWARF 1 extensions */
  .debug_srcinfo  0 : { *(.debug_srcinfo) }
  .debug_sfnames  0 : { *(.debug_sfnames) }
  
  /* DWARF 1.1 and DWARF 2 */
  .debug_aranges  0 : { *(.debug_aranges) }
  .debug_pubnames 0 : { *(.debug_pubnames) }
  
  /* DWARF 2 */
  .debug_info     0 : { *(.debug_info) }
  .debug_abbrev   0 : { *(.debug_abbrev) }
  .debug_line     0 : { *(.debug_line) }
  .debug_frame    0 : { *(.debug_frame) }
  .debug_str      0 : { *(.debug_str) }
  .debug_loc      0 : { *(.debug_loc) }
  .debug_macinfo  0 : { *(.debug_macinfo) }
  
  /* SGI/MIPS DWARF 2 extensions */
  .debug_weaknames 0 : { *(.debug_weaknames) }
  .debug_funcnames 0 : { *(.debug_funcnames) }
  .debug_typenames 0 : { *(.debug_typenames) }
  .debug_varnames  0 : { *(.debug_varnames) }

}