[cxx-abi-dev] Function descriptors in vtable

Noam Lampert noaml at mainsoft.com
Wed Jan 22 09:58:08 UTC 2003


Hi Dennis,

> >From: "Noam Lampert" <noaml at mainsoft.com>
> >However, if the vtable was created by the C++ compiler, using it in C
is
> >still very hard.
> 
> I don't think you mentioned that you created these from normal C++
> classes.

I did mention in my original email "Calling a C++ virtual method from
within C code". In addition, the sample I sent does this (takes a C++
class and sends it to a C function that calls a virtual method).

Noam


> -----Original Message-----
> From: Dennis Handly [mailto:dhandly at cup.hp.com]
> Sent: Wednesday, January 22, 2003 11:12 AM
> To: cxx-abi-dev-return-1622-cxx-abi-
> hp=adlmail.cup.hp.com at codesourcery.com; mark at codesourcery.com
> Cc: amckale at cup.hp.com; cxx-abi-dev at codesourcery.com;
gomathi at cup.hp.com;
> kerch at cup.hp.com; noaml at mainsoft.com; sassan at cup.hp.com
> Subject: Re: [cxx-abi-dev] Function descriptors in vtable
> 
> >I'll carry this a bit further, and demonstrate how this proposal
could
> >be done in the context of Noam's example:
> 
> I've already set this up and ran the example.  The part where it is
> defined in C++ aborts.
> 
> >As Mark said, every vtable entry can point to the same stub, which
can
> >be somewhere in MainWin's runtime library.
> 
> >Or dynamically in C:
> >    extern int _mainwin_com_stub;
> >    extern int bbb_f(void *b, int x);
> 
> I used this.
> 
> >(Notice we lie and declare the stub as a data symbol.
> -cary
> 
> No need to lie, just take the value out of the plabel:
>    extern void _mainwin_com_stub(void);
>    vt.f_stub = *(uint64_t*)_mainwin_com_stub;
> 
> >From: "Noam Lampert" <noaml at mainsoft.com>
> >However, if the vtable was created by the C++ compiler, using it in C
is
> >still very hard.
> 
> I don't think you mentioned that you created these from normal C++
> classes.
> 
> >Is there a more elegant way to achieve this?
> Noam
> 
> No.  Don't create these in normal C++.
> 
> >From: "Noam Lampert" <noaml at mainsoft.com>
> >It took me too long to figure out that my proposed solution here
can't
> work.
> >What could be done is
>  	   for (i = 0; i < nfuncs; i++) {
> 	         void *p = malloc(sizeof(funcdescriptor));
> 		   *p = vt[i];
> 
> It didn't take me long at all.  ;-)
> I just was too lazy to write the code to copy it.
> 
> #---------------------------------- cut here
-----------------------------
> -----
> # This is a shell archive.  Remove anything before this line,
> # then unpack it by saving it in a file and typing "sh file".
> #
> # Wrapped by Dennis Handly <dhandly at den-bear> on Wed Jan 22 01:07:30
2003
> #
> # This archive contains:
> #	cfile.c		cppfile.C	host_vtable.h	mainwin_stub.s
> #	thunkbase.h
> #
> 
> LANG=""; export LANG
> PATH=/bin:/usr/bin:/usr/sbin:/usr/ccs/bin:$PATH; export PATH
> EXIT_STATUS=0
> 
> echo x - cfile.c
> cat >cfile.c <<'@EOF'
> #include <stdio.h>
> 
> #include "host_vtable.h"
> 
> // This source files assumes that there is a definition
> // struct aaa {
> //    virtual int f(int x);
> // };
> // extern "C" void use_aaa(aaa *a);
> // We implement an instance of an inheriting class.
> // We also implement use_aaa2(aaa *a);
> 
> struct bbb;
> typedef struct {
> 	C_INTERFACE_PROLOGUE(aaa)
> 	C_STDMETHODEX_(int,f,(void* b, int x))
> } bbb_vtable;
> 
> typedef struct bbb {
> 	bbb_vtable *vt;
> } bbb;
> 
> int bbb_f(void* b, int x) {
> 	fprintf(stderr, "Inside C method - (%p) %d\n",b, x);
> 	return 0;
> }
> 
> #ifdef __ia64
> bbb_vtable vt;
> #pragma init "B_INIT"
> static void B_INIT() {
>    vt.f_stub = *(uint64_t*)_mainwin_com_stub;
>    vt.f = bbb_f;
> }
> #else
> bbb_vtable vt = {
> 	C_VTABLE_PROLOGUE
> 	C_VTABLE_ENTRY2(bbb_f)
> };
> #endif
> 
> bbb b = { &vt };
> 
> extern void use_aaa(bbb* b);
> void use_aaa2(bbb *b)
> {
> 	b->vt->f(b,3);
> }
> 
> void ctest()
> {
> 	fprintf(stderr, "Enter C test\n");
> 	use_aaa(&b);
> 	use_aaa2(&b);
> 	fprintf(stderr, "Leave C test\n");
> }
> @EOF
> 
> chmod 664 cfile.c
> 
> echo x - cppfile.C
> cat >cppfile.C <<'@EOF'
> #include <stdio.h>
> 
> struct aaa {
> 	virtual int f(int x) {
> 	    fprintf(stderr, "Inside CPP method - %d\n",x); return 1;
> 	}
> };
> struct bbb {
> 	virtual int f(int x);
> };
> 
> extern bbb b;
> 
> aaa a;
> 
> extern "C" void use_aaa(aaa *a)
> {
> 	a->f(4);
> }
> extern "C" void use_aaa2(aaa *a);
> extern "C" void cpptest()
> {
> 	fprintf(stderr, "Enter CPP test\n");
> 	use_aaa(reinterpret_cast<aaa*>(&b));
> 	use_aaa2(reinterpret_cast<aaa*>(&b));
> 	fprintf(stderr, "  defined C++\n");
> #if 0
> // can't be defined in C++
> 	use_aaa(&a);
> 	use_aaa2(&a);
> #endif
> 	fprintf(stderr, "Leave CPP test\n");
> }
> 
> 
> extern "C" void ctest();
> int main()
> {
> 	cpptest();
> 	ctest();
> }
> @EOF
> 
> chmod 664 cppfile.C
> 
> echo x - host_vtable.h
> cat >host_vtable.h <<'@EOF'
> #ifndef __HOST_VTABLE_H
> #define __HOST_VTABLE_H
> 
> #include <inttypes.h>  /* uint64_t */
> /*
> typedef _method_pointer_layout
> {
>     void (*method)(void *);
>     int vtaboff;
>     int thisoff;
> } method_pointer_layout;
> */
> 
> #ifndef __ia64
> enum vtable_layout_consts
> {
>     VTABLE_PROLOGUE_KEY = 0x12345678
> };
> #endif
> 
> // HP uses the thunkbased vtable format.
> #include "thunkbase.h"
> 
> #undef  C_STDMETHODEX_
> #ifdef __LP64
> #define C_STDMETHODEX_(type, method, arglist)   uint64_t method ##
_stub;
> \
>                                                 type (*method)
arglist;
> #else
> #define C_STDMETHODEX_(type, method, arglist)   uint64_t method ##
_stub;
> \
>                                                 int method ## _pad; \
>                                                 type (*method)
arglist;
> #endif
> 
> extern void _mainwin_com_stub(void);
> 
> #endif
> @EOF
> 
> chmod 660 host_vtable.h
> 
> echo x - mainwin_stub.s
> cat >mainwin_stub.s <<'@EOF'
>         .type   _mainwin_com_stub, at function
>         .radix  C
>         .psr    abi32
>         .psr    msb
>         .section .text = "ax", "progbits"
>         .proc   _mainwin_com_stub
> _mainwin_com_stub::
> #ifdef _ILP32
>          addp4   gp = r0, gp
>          ;;
> #endif
>          ld8     r31 = [gp], 8
>          ;;
>          ld8     gp = [gp]
>          mov     b6 = r31
>          ;;
>          br.call.dptk.few b6
>          ;;
>         .endp   bbb_f
> @EOF
> 
> chmod 664 mainwin_stub.s
> 
> echo x - thunkbase.h
> cat >thunkbase.h <<'@EOF'
> #ifndef VTABLE_THUNkBASE_H
> #define VTABLE_THUNkBASE_H
> 
> /*
>  * Thunk based vtable format.
>  * The format is an array of functions. The name thunk comes from the
fact
>  * that thunk functions are created for managing the necessary
adjustments
> of
>  * the 'this' value because of multiple inheritence semantics.
>  * Every entry is:*/
> 
> #ifndef __ia64
> typedef struct _vtable_entry_layout {
>    void (*method) ();
> } vtable_entry_layout;
> #endif
> 
> /* The vtable is:
>  * struct vtable {
>  *   vtable_entry_layout prologue [???]; // The number of reserved
entries
> varies.
>  *   vtable_entry_layout entries [];
>  * };
>  */
> 
> #define C_INTERFACE_PROLOGUE(iface)             /* Nothing */
> #define C_STDMETHOD_(type, method)              type (*method)
> #define C_STDMETHODEX_(type, method, arglist)   type (*method)
arglist;
> 
> /* structured vtable entries */
> #define C_VTABLE_PROLOGUE                       /* Nothing. */
> #define C_VTABLE_ENTRY(method)                  method
> 
> /* unstructured ((void *) array) vtable entries and sizes.
>  * For thunk based vtables this is the same as the previous. */
> #define C_VTABLE_PROLOGUE2                      C_VTABLE_PROLOGUE
> #define C_VTABLE_ENTRY2(method)
> C_VTABLE_ENTRY((void*)method)
> #define C_VTABLE_PROLOGUE_SIZE2                 0
> #define C_VTABLE_ENTRY_SIZE2                    1
> #define C_VTABLE_FUNC2(ind)                     C_VTABLE_SIZE2(ind)
> 
> /* The thunk based compilers don't need to adjust the 'this' pointer.
*/
> #define C_ADJUST_THIS_(iface, This, member)     (This)
> 
> #endif
> @EOF
> 
> chmod 660 thunkbase.h
> if [ $EXIT_STATUS -eq 1 ];then
> 	exit 1
> fi
> exit 0




More information about the cxx-abi-dev mailing list