Attacking a UDT

Post your FreeBASIC tips and tricks here. Please don’t post your code without including an explanation.
dodicat
Posts: 6557
Joined: Jan 10, 2006 20:30
Location: Scotland

Attacking a UDT

Postby dodicat » Apr 17, 2020 1:10

I don't think of this as a hack but a workaround.
Tested 32 bit gcc and gas, 64 bit and Gas64.

Code: Select all

type list
    as long s,f
end type

Type st
    private:
    Declare Property middle( As List) As String
    Declare Property middle( As List ,As String)
    Declare Operator Cast() As String
    Declare Constructor(As String="")
    #define md(s,c,d) Mid(s,c+1,d-c+1)
    as string s
End Type

'private OOP to public Procedural
declare function GetTheString alias "_ZN2ST13MIDDLE__get__ER4LIST"(as st,as list) as string 'property middle as string
declare function show alias "_ZN2STcv8FBSTRINGEv"(as st) as string  'cast
declare sub SetTheString alias "_ZN2ST13MIDDLE__set__ER4LISTR8FBSTRING"(as st,as list, as string)'property middle
declare sub construct cdecl alias "_ZN2STC1ER8FBSTRING"(as st,as string) 'constructor

'==========
Constructor st(g As String)
color 5
print __function__
color 15
s=g
End Constructor

Property st.middle(n As list) As String
color 5
print __function__
color 15
Property= md(s,n.s,n.f)
End Property

Property st.middle(n As list,g As String)
color 5
print __function__
color 15
md(s,n.s,n.f)=g
End Property

Operator st.cast() As String
color 5
print __function__
color 15
Return s
End Operator
'=========================

print "actual task:"
dim as string g="abcdefghijklmnopqrstuvwxyz"
print g
print md(g,2,7)
md(g,10,19)="STATEMENT"
print g
print
print


'use only method pointers
var GetTheStringMethod=@GetTheString
var SetTheStringMethod=@SetTheString
var ConstructorMethod=@construct
var CastMethod=@show

print "Task via method pointers:"
dim as st ptr y=allocate(sizeof(st))
ConstructorMethod(*y,"abcdefghijklmnopqrstuvwxyz")
print CastMethod(*y)
print GetTheStringMethod(*y,type(2,7))
SetTheStringMethod(*y,type(10,19),"STATEMENT")
print CastMethod(*y)


Print
sleep

deallocate y

   
Xusinboy Bekchanov
Posts: 237
Joined: Jul 26, 2018 18:28

Re: Attacking a UDT

Postby Xusinboy Bekchanov » Apr 17, 2020 6:16

In this code, when I compile in dll, I can only read a sub or function ("MySub"). Why properties look like this: _ZN7MYCLASS11NAME_get_Ev@4 and _ZN7MYCLASS11NAME_set_ER8FBSTRING@8 ?
I specifically point out: Alias "GetName" () and Alias "SetName" ()

Code: Select all

Type MyClass
Private:
   s As String
Public:
   Declare Property Name As String
   Declare Property Name(Value As String)
   Declare Constructor(Value As String = "")
End Type

Constructor MyClass Alias "New_MyClass"(Value As String = "") Export
   s = Value
End Constructor

Property MyClass.Name Alias "GetName"() As String Export
   Return s
End Property

Property MyClass.Name Alias "SetName"(Value As String) Export
   s = Value
End Property

Sub MyFunction Alias "MySub"(Value As String) Export
   Print Value
End Sub
dodicat
Posts: 6557
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Attacking a UDT

Postby dodicat » Apr 17, 2020 8:46

From the dll straight from your code. (myclass.dll)

Code: Select all


#inclib "myclass"

Type MyClass
Private:
   s As String
'Public:
   Declare Property Name As String
   Declare Property Name(Value As String)
   Declare Constructor(Value As String = "")
End Type

declare sub construct cdecl alias "_ZN7MYCLASSC1ER8FBSTRING"(as myclass,as string)
declare function fetchname  alias "_ZN7MYCLASS11NAME__get__Ev"(as myclass) as string
declare sub setnewname alias "_ZN7MYCLASS11NAME__set__ER8FBSTRING"(as MyClass,as string)
declare sub mysub alias "MySub"(as string)


dim as myclass ptr x=allocate(sizeof(MyClass))
construct( *x,"Bekchanov")
print fetchname(*x)
setnewname(*x,"Bekchanov junior")
print fetchname(*x)
mysub("Press any key to end . . .")
sleep
deallocate x

 

I use myclass pointer to keep everything private, but you can use a straight myclass if you prefer.
fxm
Posts: 9720
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Attacking a UDT

Postby fxm » Apr 17, 2020 9:00

@dodicat,
You forgot to call the destructor (implicit in this case), so that the string "st.s" is not destroyed before deallocating the memory (so its descriptor).
I think the simplest for that joke is to define an explicit empty destructor:

Code: Select all

type list
    as long s,f
end type

Type st
    private:
    Declare Property middle( As List) As String
    Declare Property middle( As List ,As String)
    Declare Operator Cast() As String
    Declare Constructor(As String="")
    Declare Destructor()
    #define md(s,c,d) Mid(s,c+1,d-c+1)
    as string s
End Type

'private OOP to public Procedural
declare function GetTheString alias "_ZN2ST13MIDDLE__get__ER4LIST"(as st,as list) as string 'property middle as string
declare function show alias "_ZN2STcv8FBSTRINGEv"(as st) as string  'cast
declare sub SetTheString alias "_ZN2ST13MIDDLE__set__ER4LISTR8FBSTRING"(as st,as list, as string)'property middle
declare sub construct cdecl alias "_ZN2STC1ER8FBSTRING"(as st,as string) 'constructor
declare sub destruct cdecl alias "_ZN2STD1Ev"(as st) 'destructor

'==========
Constructor st(g As String)
color 5
print __function__
color 15
s=g
End Constructor

Property st.middle(n As list) As String
color 5
print __function__
color 15
Property= md(s,n.s,n.f)
End Property

Property st.middle(n As list,g As String)
color 5
print __function__
color 15
md(s,n.s,n.f)=g
End Property

Operator st.cast() As String
color 5
print __function__
color 15
Return s
End Operator

Destructor st()
End Destructor

'=========================

print "actual task:"
dim as string g="abcdefghijklmnopqrstuvwxyz"
print g
print md(g,2,7)
md(g,10,19)="STATEMENT"
print g
print
print


'use only method pointers
var GetTheStringMethod=@GetTheString
var SetTheStringMethod=@SetTheString
var ConstructorMethod=@construct
var CastMethod=@show
var DestructorMethod=@destruct

print "Task via method pointers:"
dim as st ptr y=allocate(sizeof(st))
ConstructorMethod(*y,"abcdefghijklmnopqrstuvwxyz")
print CastMethod(*y)
print GetTheStringMethod(*y,type(2,7))
SetTheStringMethod(*y,type(10,19),"STATEMENT")
print CastMethod(*y)


Print
sleep

DestructorMethod(*y)
deallocate y
[edit]
Otherwise, the implicit destructor could only be called by 'cptr(st ptr,y)->destructor()' before 'deallocate y'.
Last edited by fxm on Apr 17, 2020 19:13, edited 1 time in total.
dodicat
Posts: 6557
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Attacking a UDT

Postby dodicat » Apr 17, 2020 9:19

Thank you fxm.
The next I would like to attack is a c++ library (.dll) with c++ classes.
Is it not true that all OOP operations in a procedural language are in fact only procedures, functions and subs which can be hunted down one way or another?
Xusinboy Bekchanov
Posts: 237
Joined: Jul 26, 2018 18:28

Re: Attacking a UDT

Postby Xusinboy Bekchanov » Apr 17, 2020 9:51

dodicat wrote:

Code: Select all

declare sub construct cdecl alias "_ZN7MYCLASSC1ER8FBSTRING"(as myclass,as string)
declare function fetchname  alias "_ZN7MYCLASS11NAME__get__Ev"(as myclass) as string
declare sub setnewname alias "_ZN7MYCLASS11NAME__set__ER8FBSTRING"(as MyClass,as string)
declare sub mysub alias "MySub"(as string)

I use myclass pointer to keep everything private, but you can use a straight myclass if you prefer.

My complaints were only in the name of exported functions such as: "_ZN7MYCLASSC1ER8FBSTRING", "_ZN7MYCLASS11NAME__get__Ev", "_ZN7MYCLASS11NAME__set__ER8FBSTRING"
I indicate the same with Alias: "GetName", "SetName".
dodicat
Posts: 6557
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Attacking a UDT

Postby dodicat » Apr 17, 2020 11:23

do you have gcc on path?
Mingw for example.
here is a c++ program (from the wiki) to demangle names.

Code: Select all


#include <stdio.h>
#include <stdlib.h>
#include <cxxabi.h>

int main() {
   const char *mangled_name ="_ZN2ST13MIDDLE__get__ER4LIST";
   int status = -1;
   char *demangled_name = abi::__cxa_demangle(mangled_name, NULL, NULL, &status);
   printf("Demangled: %s\n", demangled_name);
   free(demangled_name);
   system("pause");
   return 0;
}


and the result here from my fb snippet using g++ to compile the code.
declare function GetTheString alias "_ZN2ST13MIDDLE__get__ER4LIST"(as st,as list) as string 'property middle as string

Code: Select all

Demangled: ST::MIDDLE__get__(LIST&)
Press any key to continue . . .
Xusinboy Bekchanov
Posts: 237
Joined: Jul 26, 2018 18:28

Re: Attacking a UDT

Postby Xusinboy Bekchanov » Apr 17, 2020 12:50

dodicat wrote:do you have gcc on path?
Mingw for example.
here is a c++ program (from the wiki) to demangle names.

Yes, I have.
fxm
Posts: 9720
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Attacking a UDT

Postby fxm » Apr 17, 2020 16:53

dodicat wrote:Is it not true that all OOP operations in a procedural language are in fact only procedures, functions and subs which can be hunted down one way or another?

Remember that each instance of a Type gets its own copy of the member variables, unless the variables are static. But member procedures are shared across the Type.

Non-static member procedures work with a particular instance. However, inside the memory, there really is only one copy of the procedure.
A hidden parameter is passed to the member procedure: the address of the instance (corresponding to the reference This).

Since only one copy of the member procedure is in memory, we could call it through its unique address by also supplying it as the first parameter with the address of the instance.
But for now, FreeBASIC does not allow to obtain this procedure address as C ++ allows.
dodicat
Posts: 6557
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Attacking a UDT

Postby dodicat » Apr 17, 2020 17:19

Here is my first c++ dll, which demangles a mangled string name.
it uses __cxa_demangle which doesn't exist in c.
I have to use the decorated name in the c++ dll file to use with freebasic.
https://www.mediafire.com/file/whrkywt7u086zbd/demangle.zip/file
Please note that the .dll is for 64 bits.

Of course there are no structures and member functions in this .dll.
The first parameter of a type member in a decorated name is an instance of the udt (the this bit in fb).
This is seen by looking at the .asm or .c generated file from freebasic, or a .def file for a dll.
Static members are exempt from this requirement.
(fxm alluded to this).

It is only common sense really that you must supply a udt member parameter to a method made into an ordinary procedure via the decorated name.
I am not sure yet the method c++ uses to handle classes and structures.
But I'll find out in due course.
dodicat
Posts: 6557
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Attacking a UDT

Postby dodicat » Apr 17, 2020 21:56

In C++ dll's I note that the class methods passed via the decorated names do not give a slot for the freebasic THIS parameter to be sent.
Therefore you are stopped dead at this point.
However, a wrapper is easily enough made for each method (one liner each) in the C++ code.
I have tested with constructors, subs, functions and operators.
I see that templates are not passed as an entity, but the results are processed (like fb macros).
Example for class vector, all the usual type of methods (normalize, length, e.t.c), but I have added segdist (segment distance of a 3D point to a 3D line segment).

https://www.mediafire.com/file/c1zab3mp6daxhvd/vectors.zip/file
dodicat
Posts: 6557
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Attacking a UDT

Postby dodicat » Apr 20, 2020 23:53

The post above (Which I have completely re edited from a few days ago) Attacks the class methods in a a C++ .dll.
You can download and run the test from the folder.
UEZ
Posts: 586
Joined: May 05, 2017 19:59
Location: Germany

Re: Attacking a UDT

Postby UEZ » Apr 22, 2020 6:52

Sorry, but may I ask a silly question? What is "Attacking a UDT"? What can be done with it? I cannot read it out of the code... ^^
dodicat
Posts: 6557
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Attacking a UDT

Postby dodicat » Apr 22, 2020 7:35

UEZ
utd's in C++ (Classes) are not easily transferred to FreeBASIC in a C++ library (dll) if they have member functions or subs, whereas plain C interacts well with fb because structures in C do not have member functions/subs.
Most of the external libraries in fb are written in C.
The problem is the hidden THIS used by fb.
In C++ the hidden THIS is a pointer.
Classes in C++ are nearly identical to the fb TYPE if it extends object, except for the hidden THIS.
It was on the FreeBASIC todo list to introduce C++ type classes.
I note that C++ libraries induce a terrible panic in even the most seasoned fb people, so I decided to have a look into it.
UEZ
Posts: 586
Joined: May 05, 2017 19:59
Location: Germany

Re: Attacking a UDT

Postby UEZ » Apr 22, 2020 8:30

@dodicat: thanks for the clarification. I don't have any knowledge about C++ classes and some basic knowledge about classes in FB. That was the reason why this topic was and is still cryptic for me. ^^

Return to “Tips and Tricks”

Who is online

Users browsing this forum: No registered users and 2 guests