[Mono-dev] Howto Marshal IntPtr to Elf32_Phdr[] ?

Tom Spink tspink at gmail.com
Mon Mar 28 15:42:37 EDT 2011


Hi,

I only mentioned it as a point of interest - I'm afraid it doesn't
actually help you here.  You would use the MarshalAs attribute on a
parameter in a method declaration, that has a C-style array, and has a
size parameter.  Take a look at the following MSDN example:

http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.marshalasattribute.sizeparamindex(v=vs.71).aspx

Hope this helps,

-- Tom

On 28 March 2011 13:01, Quandary <quandary82 at hailmail.net> wrote:
> So what you're saying is that
>
> System.Runtime.InteropServices.UnmanagedType.LPStructArray
> is inexistant, so there can be no
> [MarshalAs(UnmanagedType.LPStructArray)]
>
> Basically, one could add a property at the end and rename the IntPtr
> variable ?
> Or would that shift the offsets ?
>
> In which case the next question would be whether there exists a
>
> [MarshalAs(UnmanagedType.Ignore)]
>
> attribute that I could prefix the property with.
>
>
> Am 28.03.2011 09:29, schrieb Tom Spink:
>>
>> Hi,
>>
>>> Still I was hoping for a less-hackish method via MarshalAs.
>>
>> Unfortunately, MarshalAs almost helps you out, by giving you a
>> SizeParamIndex property, to indicate to the marshaller which parameter
>> to get size information from when marshalling an LPArray.  But - this
>> is only for methods (that have a signature with a parameter indicating
>> the size of the array), not for structures, so it doesn't really help.
>>
>>> sounds awfully x86 specific, maybe even x86-32 specific
>>
>> Well, it's just pointer arithmetic - your not actually manipulating
>> memory here, or doing anything clever at all.  You're just reading
>> from a certain location.  It's up to the API how it presents the
>> memory - in this case, a C-style array, which is compiler specific not
>> platform specific.
>>
>>> [MarshalAs(UnmanagedType.LPStr)]
>>
>> Good point on marshalling your string, with LPStr.  I was going to
>> mention it - but forgot.
>>
>>
>> On 27 March 2011 22:20, Quandary<quandary82 at hailmail.net>  wrote:
>>>
>>> Hi Tom,
>>>
>>> Thank you, that works.
>>>
>>> Still I was hoping for a less-hackish method via MarshalAs.
>>>
>>> address + j * sizeof(mystruct_t)
>>> sounds awfully x86 specific, maybe even x86-32 specific
>>> But then again, so is struct Elf32_Phdr the way I did it.
>>>
>>>
>>> As a side-note to other potential users:
>>> If I/you apply
>>> [MarshalAs(UnmanagedType.LPStr)]
>>> to
>>> public System.IntPtr dlpi_name;
>>> and instead call it
>>> public string dlpi_name;
>>> then I needn't marshall it in the callback.
>>>
>>>
>>> Kind regards
>>>
>>> Stefan
>>>
>>>
>>> On 03/27/2011 06:23 PM, Tom Spink wrote:
>>>>
>>>> Hi Quandry,
>>>>
>>>> You've almost got it - you just need to do a bit of pointer arithmetic.
>>>>
>>>> In your for loop, you've got this:
>>>>
>>>> ///
>>>> for (j = 0; j<  info.dlpi_phnum; j++)
>>>>             Console.WriteLine("\t\t header {0}: address={1}\n", j, 22);
>>>> ///
>>>>
>>>> Not sure what that 22 is... but if you do this:
>>>>
>>>> ///
>>>> for (int j = 0; j<  info.dlpi_phnum; j++) {
>>>>     var ptr = new IntPtr(info.dlpi_phdr.ToInt64() + (j *
>>>> Marshal.SizeOf(typeof(Elf32_Phdr))));
>>>>     var hdr = (Elf32_Phdr)Marshal.PtrToStructure(ptr,
>>>> typeof(Elf32_Phdr));
>>>>
>>>>     Console.WriteLine("\t\t header {0}: address={1}: offset={2}\n", j,
>>>> info.dlpi_phdr, hdr.p_offset);
>>>> }
>>>> ///
>>>>
>>>> Inside your for loop, you've now got the 'hdr' variable, which is the
>>>> Elf32_Phdr struct of the 'current element' in the array.  This works
>>>> because info.dlpi_phdr is a pointer to the base address of the array -
>>>> where the array is just a sequential list of Elf32_Phdr structures.
>>>> So, by taking the base address, then adding on the index into the
>>>> array (multiplied by the size of the array's element type), you'll get
>>>> the base address of that particular element.  Once you've got this
>>>> base address, all you have to do is marshal that pointer, to the right
>>>> structure type.
>>>>
>>>> Also, make sure you mark your structures with the following attribute:
>>>>
>>>> [StructLayout(LayoutKind.Sequential)]
>>>>
>>>> Hope this helps!
>>>>
>>>> -- Tom
>>>>
>>>> On 27 March 2011 16:43, Quandary<quandary82 at hailmail.net>  wrote:
>>>>>
>>>>> Hi everyone,
>>>>>
>>>>> I have a problem with dl_iterate_phdr.
>>>>> (man 3 dl_iterate_phdr)
>>>>>
>>>>> You find the (till now unanswered) question on stackoverflow, I'm not
>>>>> inclined to retype everything here again, so below the link:
>>>>>
>>>>> http://stackoverflow.com/questions/5447282/c-howto-marshal-intptr-to-an-array-of-struct
>>>>>
>>>>> In a nutshell, the problem is the struct dl_phdr_info you see below.
>>>>>
>>>>> It seems I need to Marshal
>>>>> public System.IntPtr dlpi_phdr;
>>>>> to
>>>>> public Elf32_Phdr[] dlpi_phdr;
>>>>> somehow.
>>>>>
>>>>> Or maybe I did translate it to managed code the wrong way.
>>>>> Can anybody have a look at it ?
>>>>>
>>>>> All necessary code/structs to get the sample running you find on the
>>>>> stackoverflow link.
>>>>>
>>>>>
>>>>> Here's the C struct:
>>>>>
>>>>>  struct dl_phdr_info {
>>>>>            ElfW(Addr)        dlpi_addr;  /* Base address of object */
>>>>>            const char       *dlpi_name;  /* (Null-terminated) name of
>>>>>                                             object */
>>>>>            const ElfW(Phdr) *dlpi_phdr;  /* Pointer to array of
>>>>>                                             ELF program headers
>>>>>                                             for this object */
>>>>>            ElfW(Half)        dlpi_phnum; /* # of items in dlpi_phdr */
>>>>>        };
>>>>>
>>>>> Here's my C# translation of the above struct:
>>>>>
>>>>>   public struct dl_phdr_info
>>>>>     {
>>>>>         public System.UInt32 dlpi_addr; /* Base address of object */
>>>>>
>>>>>         // TODO: String, MarshalAs Pointer
>>>>>         public System.IntPtr dlpi_name;  /* (Null-terminated) name of
>>>>> object*/
>>>>>
>>>>>         /* Pointer to array of ELF program headers for this object */
>>>>>         public System.IntPtr dlpi_phdr; // Hackish, cannot read it, but
>>>>> then
>>>>> at least the rest works
>>>>>
>>>>>         // This way it throws an exception at runtime.
>>>>>
>>>>>
>>>>> //[System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPStruct)]
>>>>>         //public Elf32_Phdr[] dlpi_phdr;
>>>>>
>>>>>         public System.UInt16  dlpi_phnum; /* # of items in 'dlpi_phdr'
>>>>> */
>>>>>     }
>>>>>
>>>>>
>>>>> _______________________________________________
>>>>> Mono-devel-list mailing list
>>>>> Mono-devel-list at lists.ximian.com
>>>>> http://lists.ximian.com/mailman/listinfo/mono-devel-list
>>>>>
>>>>>
>>>>
>>>
>>
>>
>
>


More information about the Mono-devel-list mailing list