Andreas, John, anybody,
I need to find the address of a "function" (it is in fact a global structure pointer somewhere in memory) and pass it to another function. Suppose the structure is called Type and the function allocate_one(). I call the function something like allocateOne:type size:anInt <cdecl: SomeOtherStruct* 'allocate_one' ( Type* long ) > but I am having an awful time getting the pointer to Type. Given that dlsym() will return a pointer to it, how can I represent that in Smalltalk? I have tried variations on "Indirectly call dlsym()" address := Library default getProcAddress:'name_of_global_struct'. "try to create Type* from the resulting address" type := Type fromHandle:address. type := Type fromHandle:address getHandle. type := ExternalData fromHandle:address type:Type externalType asPointerType. Something := Library default allocateOne:type size:2. and it either complains about bad arguments during the call or segment faults. Any ideas or similar examples? Bill |
On 4/3/2010 6:36 AM, Schwab,Wilhelm K wrote:
> Andreas, John, anybody, > > I need to find the address of a "function" (it is in fact a global structure pointer somewhere in memory) and pass it to another function. > > Suppose the structure is called Type and the function allocate_one(). I call the function something like > > allocateOne:type size:anInt > <cdecl: SomeOtherStruct* 'allocate_one' ( Type* long )> > > > but I am having an awful time getting the pointer to Type. Given that dlsym() will return a pointer to it, how can I represent that in Smalltalk? I have tried variations on > > "Indirectly call dlsym()" > address := Library default getProcAddress:'name_of_global_struct'. > > "try to create Type* from the resulting address" > type := Type fromHandle:address. > type := Type fromHandle:address getHandle. > type := ExternalData fromHandle:address type:Type externalType asPointerType. > > Something := Library default allocateOne:type size:2. > > and it either complains about bad arguments during the call or segment faults. Any ideas or similar examples? The return type of getProcAddress: is likely wrong. It should be declared to return void* which will cause it to return an ExternalData. With an ExternalData your second variant "Type fromHandle: data getHandle" will work. Cheers, - Andreas |
Andreas,
#getProcAddress: is a Smalltalk message, so it does not have a return type. It does return an ExternalData because it it ultimately calls <cdecl: void* 'FindSymbol' ( long char* ) > I had to create FindSymbol as a simply wrapper around dlsym() because the vm dies a quick death over (what I believe to be) linking hassles similar to recent problems in skype. Of course, I am referring the Linux vm or I would be calling GetProcAddress(). One thing that I considered is that the aspects of the ExternalData might be incorrect. The handle is an external address and type is an ExternalType that prints itself as void*. With many variations, if the call was made, the vm crashed. Bill -----Original Message----- From: [hidden email] [mailto:[hidden email]] On Behalf Of Andreas Raab Sent: Saturday, April 03, 2010 11:54 AM To: The general-purpose Squeak developers list Cc: [hidden email] Subject: Re: [Pharo-project] FFI - structure pointer On 4/3/2010 6:36 AM, Schwab,Wilhelm K wrote: > Andreas, John, anybody, > > I need to find the address of a "function" (it is in fact a global structure pointer somewhere in memory) and pass it to another function. > > Suppose the structure is called Type and the function allocate_one(). > I call the function something like > > allocateOne:type size:anInt > <cdecl: SomeOtherStruct* 'allocate_one' ( Type* long )> > > > but I am having an awful time getting the pointer to Type. Given that > dlsym() will return a pointer to it, how can I represent that in > Smalltalk? I have tried variations on > > "Indirectly call dlsym()" > address := Library default getProcAddress:'name_of_global_struct'. > > "try to create Type* from the resulting address" > type := Type fromHandle:address. > type := Type fromHandle:address getHandle. > type := ExternalData fromHandle:address type:Type externalType asPointerType. > > Something := Library default allocateOne:type size:2. > > and it either complains about bad arguments during the call or segment faults. Any ideas or similar examples? The return type of getProcAddress: is likely wrong. It should be declared to return void* which will cause it to return an ExternalData. With an ExternalData your second variant "Type fromHandle: data getHandle" will work. Cheers, - Andreas _______________________________________________ Pharo-project mailing list [hidden email] http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project |
In reply to this post by Schwab,Wilhelm K
On 2010-04-03, at 6:36 AM, Schwab,Wilhelm K wrote: > Andreas, John, anybody, > > I need to find the address of a "function" (it is in fact a global structure pointer somewhere in memory) and pass it to another function. Well some sample code from the objective C bridge. This doesn't use any "C" code or the FFI/Alien logic since it was targeted towards the iPhone and FFI and Alien aren't supported. This creates a byteArray that contains the (length) bytes from a known global structure identified by linker name. However the primitiveGetAddressFromEntryPointString returns a memory address as a large positive integer. "Pass in the name in a String, indicate the length of the data element" fetchByteArrayConstantCalled: aString withLength: length | address | address := self findAddressForString: aString. address = 0 ifTrue: [^self error: 'Address of constant not found']. ^self fetchByteArrayFrom: address length: length. findAddressForString: aNameString "ObjectiveCBridge findAddressForString: 'CGRectZero'" | externalAddress | externalAddress := self primitiveGetAddressFromEntryPointString: aNameString. ^externalAddress primitiveGetAddressFromEntryPointString: aString <primitive: 'primitiveGetAddressFromEntryPointString' module: 'ObjectiveCPlugin'> self primitiveFailed "The plugin code is below, first we need to move the name from a smalltalk string to a C String. To do this we construct a strlcpy using a fake call to str:l:cpy: then we invoke dl:sym: which is really dlSym(-2,entryPointName) This gives back the address of the data. Remember to create a 64bit positive number out of it since we could be on a 64bit system primitiveGetAddressFromEntryPointString: aEntryPointName | entryPointNameLength fn entryPointName | self primitive: 'primitiveGetAddressFromEntryPointString' parameters: #(String). self var: 'entryPointName' declareC: 'char entryPointName[256]'. self var: 'fn' declareC: 'void * fn'. entryPointNameLength := interpreterProxy slotSizeOf: aEntryPointName cPtrAsOop. entryPointNameLength > 256 ifTrue: [^interpreterProxy positive64BitIntegerFor: 0]. self str: entryPointName l: aEntryPointName cpy: entryPointNameLength+1. fn := self dl: -2 sym: entryPointName. ^interpreterProxy positive64BitIntegerFor: (self cCoerce: fn to: 'usqInt') "Given an address lets fetch N bytes from it, the ByteArray is create by the primitive " fetchByteArrayFrom: anAddress length: length ^self nsInvocationGetStructureType: anAddress length: length nsInvocationGetStructureType: bufferAddressOop length: length ^self primitiveNSInvocationGetStructureType: bufferAddressOop length: length primitiveNSInvocationGetStructureType: bufferAddressOop length: length <primitive: 'primitiveNSInvocationGetStructureType' module: 'ObjectiveCPlugin'> self primitiveFailed "64bits again for 64 bit systems, Use the fake construct of me:m:cpy: to do the memcpy" primitiveNSInvocationGetStructureType: bufferAddressOop length: length | bufferPointer newByteArray | self primitive: 'primitiveNSInvocationGetStructureType' parameters: #(Oop SmallInteger). self var: 'bufferPointer' declareC: 'char ** bufferPointer'. self var: 'buffer' declareC: 'char * buffer'. bufferPointer := self cCoerce: (interpreterProxy positive64BitValueOf: bufferAddressOop) to: 'void *'. interpreterProxy failed ifTrue: [^nil]. newByteArray := interpreterProxy instantiateClass: interpreterProxy classByteArray indexableSize: length. self me: (interpreterProxy arrayValueOf: newByteArray) m: bufferPointer cpy: length. "void * memcpy(void *restrict s1, const void *restrict s2, size_t n)" ^newByteArray -- =========================================================================== John M. McIntosh <[hidden email]> Twitter: squeaker68882 Corporate Smalltalk Consulting Ltd. http://www.smalltalkconsulting.com =========================================================================== smime.p7s (3K) Download Attachment |
In reply to this post by Schwab,Wilhelm K
On 4/3/2010 10:10 AM, Schwab,Wilhelm K wrote:
> Andreas, > > #getProcAddress: is a Smalltalk message, so it does not have a return type. It does return an ExternalData because it it ultimately calls > > <cdecl: void* 'FindSymbol' ( long char* )> > > I had to create FindSymbol as a simply wrapper around dlsym() because the vm dies a quick death over (what I believe to be) linking hassles similar to recent problems in skype. Of course, I am referring the Linux vm or I would be calling GetProcAddress(). > > One thing that I considered is that the aspects of the ExternalData might be incorrect. The handle is an external address and type is an ExternalType that prints itself as void*. With many variations, if the call was made, the vm crashed. Can you verify the correctness of both pointer as well as function signature? Depending on platform and/or entity in question you just *might* get an extra indirection. If you can't get the code to work as-is I would recommend compiling your own library that exports a symbol in the form you're using and then verify correctness of the bridge that way. Cheers, - Andreas > -----Original Message----- > From: [hidden email] [mailto:[hidden email]] On Behalf Of Andreas Raab > Sent: Saturday, April 03, 2010 11:54 AM > To: The general-purpose Squeak developers list > Cc: [hidden email] > Subject: Re: [Pharo-project] FFI - structure pointer > > On 4/3/2010 6:36 AM, Schwab,Wilhelm K wrote: >> Andreas, John, anybody, >> >> I need to find the address of a "function" (it is in fact a global structure pointer somewhere in memory) and pass it to another function. >> >> Suppose the structure is called Type and the function allocate_one(). >> I call the function something like >> >> allocateOne:type size:anInt >> <cdecl: SomeOtherStruct* 'allocate_one' ( Type* long )> >> >> >> but I am having an awful time getting the pointer to Type. Given that >> dlsym() will return a pointer to it, how can I represent that in >> Smalltalk? I have tried variations on >> >> "Indirectly call dlsym()" >> address := Library default getProcAddress:'name_of_global_struct'. >> >> "try to create Type* from the resulting address" >> type := Type fromHandle:address. >> type := Type fromHandle:address getHandle. >> type := ExternalData fromHandle:address type:Type externalType asPointerType. >> >> Something := Library default allocateOne:type size:2. >> >> and it either complains about bad arguments during the call or segment faults. Any ideas or similar examples? > > The return type of getProcAddress: is likely wrong. It should be declared to return void* which will cause it to return an ExternalData. > With an ExternalData your second variant "Type fromHandle: data getHandle" will work. > > Cheers, > - Andreas |
In reply to this post by johnmci
On 2010-04-03, at 11:01 AM, John M McIntosh wrote: > entryPointNameLength > 256 ifTrue: [^interpreterProxy positive64BitIntegerFor: 0]. Tsk, should be > 255 -- =========================================================================== John M. McIntosh <[hidden email]> Twitter: squeaker68882 Corporate Smalltalk Consulting Ltd. http://www.smalltalkconsulting.com =========================================================================== smime.p7s (3K) Download Attachment |
John,
Sorry, but you lost me. When I see interpreter proxies, I think of plugins, which I'm not doing. Are you asking me to check something? Bill -----Original Message----- From: [hidden email] [mailto:[hidden email]] On Behalf Of John M McIntosh Sent: Saturday, April 03, 2010 1:22 PM To: [hidden email] Cc: [hidden email]; The general-purpose Squeak developers list Subject: Re: [Pharo-project] [squeak-dev] FFI - structure pointer On 2010-04-03, at 11:01 AM, John M McIntosh wrote: > entryPointNameLength > 256 ifTrue: [^interpreterProxy positive64BitIntegerFor: 0]. Tsk, should be > 255 -- =========================================================================== John M. McIntosh <[hidden email]> Twitter: squeaker68882 Corporate Smalltalk Consulting Ltd. http://www.smalltalkconsulting.com =========================================================================== |
In reply to this post by Schwab,Wilhelm K
Andreas,
I *think* I already took your second option. I created functions that do nothing but return the structure pointer, call them and pass the result onward - it seems to work. Bill -----Original Message----- From: [hidden email] [mailto:[hidden email]] On Behalf Of Andreas Raab Sent: Saturday, April 03, 2010 1:16 PM To: The general-purpose Squeak developers list Cc: [hidden email] Subject: Re: [Pharo-project] FFI - structure pointer On 4/3/2010 10:10 AM, Schwab,Wilhelm K wrote: > Andreas, > > #getProcAddress: is a Smalltalk message, so it does not have a return > type. It does return an ExternalData because it it ultimately calls > > <cdecl: void* 'FindSymbol' ( long char* )> > > I had to create FindSymbol as a simply wrapper around dlsym() because the vm dies a quick death over (what I believe to be) linking hassles similar to recent problems in skype. Of course, I am referring the Linux vm or I would be calling GetProcAddress(). > > One thing that I considered is that the aspects of the ExternalData might be incorrect. The handle is an external address and type is an ExternalType that prints itself as void*. With many variations, if the call was made, the vm crashed. Can you verify the correctness of both pointer as well as function signature? Depending on platform and/or entity in question you just *might* get an extra indirection. If you can't get the code to work as-is I would recommend compiling your own library that exports a symbol in the form you're using and then verify correctness of the bridge that way. Cheers, - Andreas > -----Original Message----- > From: [hidden email] > [mailto:[hidden email]] On Behalf Of > Andreas Raab > Sent: Saturday, April 03, 2010 11:54 AM > To: The general-purpose Squeak developers list > Cc: [hidden email] > Subject: Re: [Pharo-project] FFI - structure pointer > > On 4/3/2010 6:36 AM, Schwab,Wilhelm K wrote: >> Andreas, John, anybody, >> >> I need to find the address of a "function" (it is in fact a global structure pointer somewhere in memory) and pass it to another function. >> >> Suppose the structure is called Type and the function allocate_one(). >> I call the function something like >> >> allocateOne:type size:anInt >> <cdecl: SomeOtherStruct* 'allocate_one' ( Type* long )> >> >> >> but I am having an awful time getting the pointer to Type. Given >> that >> dlsym() will return a pointer to it, how can I represent that in >> Smalltalk? I have tried variations on >> >> "Indirectly call dlsym()" >> address := Library default getProcAddress:'name_of_global_struct'. >> >> "try to create Type* from the resulting address" >> type := Type fromHandle:address. >> type := Type fromHandle:address getHandle. >> type := ExternalData fromHandle:address type:Type externalType asPointerType. >> >> Something := Library default allocateOne:type size:2. >> >> and it either complains about bad arguments during the call or segment faults. Any ideas or similar examples? > > The return type of getProcAddress: is likely wrong. It should be declared to return void* which will cause it to return an ExternalData. > With an ExternalData your second variant "Type fromHandle: data getHandle" will work. > > Cheers, > - Andreas _______________________________________________ Pharo-project mailing list [hidden email] http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project _______________________________________________ Pharo-project mailing list [hidden email] http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project |
In reply to this post by Schwab,Wilhelm K
Well you were showing "C" last time around so I assumed you where doing everything by hand so to speak.
Anyway the example shows how to get a memory address of a linker exposed global symbol without help from FFI/Alien/VM On 2010-04-03, at 11:54 AM, Schwab,Wilhelm K wrote: > John, > > Sorry, but you lost me. When I see interpreter proxies, I think of plugins, which I'm not doing. Are you asking me to check something? > > Bill -- =========================================================================== John M. McIntosh <[hidden email]> Twitter: squeaker68882 Corporate Smalltalk Consulting Ltd. http://www.smalltalkconsulting.com =========================================================================== smime.p7s (3K) Download Attachment |
Free forum by Nabble | Edit this page |