Yes, I was able to do that last week (except getting the image's name, but I'm skipping that for now, since the name is only used in debugLog), I spent a ton of time trying to implement getAddressInfoForImage, not realizing that it wasn't necessary
Yes, I'm trying to do that right now
The first problem I'm having is an "Unexpected end of file" inside the collectBytesFromPipe function, when trying to read the bytes from a RemoteReflectionInfo structure. That structure looks like this:
A RemoteReflectionInfo's size is calculated by subtracting the lowest address of its six RemoteSection fields from the highest (this is done in function makeRemoteReflectionInfo). I think this might be wrong since the RemoteSections are not necessarily contiguous, so for example, here are the logs I added of one RemoteReflectionInfo that crashes inside collectBytesFromPipe:
makeRemoteSection: Making remote section with Start = 0x7f248b195da8 Size = 0 and EndAddress = 0x7f248b195da8
makeRemoteSection: Making remote section with Start = 0x7f248b195da8 Size = 0 and EndAddress = 0x7f248b195da8
makeRemoteSection: Making remote section with Start = 0x7f248b195da8 Size = 0 and EndAddress = 0x7f248b195da8
makeRemoteSection: Making remote section with Start = 0x7f248b195da8 Size = 0 and EndAddress = 0x7f248b195da8
makeRemoteSection: Making remote section with Start = 0x7f248b1ab170 Size = 252 and EndAddress = 0x7f248b1ab26c
makeRemoteSection: Making remote section with Start = 0x7f248b195da8 Size = 0 and EndAddress = 0x7f248b195da8
makeRemoteReflectionInfo: Making RemoteReflectionInfo with size 87236 and address 0x7f248b195da8
Notice how the size of most RemoteSections is 0, but we set the size of the structure to 87236. We then try to read those bytes and that's when it crashes:
PipeMemoryReader_readBytes: Requesting read of 87236 bytes from 0x7f248b195da8
collectBytesFromPipe: Unexpected end of file
Is the way we are calculating the RemoteReflectionInfo's size correct? I'm thinking we could read each RemoteSection separately instead of trying to read a whole RemoteReflectionInfo. Would that be correct?
It sounds like you're on the right track :)! Maybe get rid of 'TotalSize', and split up the loop that reads remote sections so that you can do the non-contiguous reads?
Ok, so I got a bit further, and I have another question.
sendSymbolAddress was crashing on the swift side, with SIGSEGV, because we're passing it a handle of pointer with a bit pattern of -2 (off-topic, but Apple's doc page on the init with a bit pattern is missing). Passing a null pointer (RTLD_DEFAULT) instead works. So, should this be platform specific? Also, why do we pass the bit-pattern -2? Should that be RTLD_NEXT?
We made a bit of progress, right now we're printing:
Reflecting an object.
Instance pointer in child address space: 0x55eace0f41a0
Type reference:
(class reflect_UInt16.TestClass)
Type info:
<null type info>
Done.
So the next step is finding out why we can't find out the type info.
Apple's dlfcn.h defines RTLD_DEFAULT as ((void *) -2) /* Use default search algorithm. */: so that's why it's written in this way, although it deserves a comment.
If we can't write the macro literally in the source, then I suppose the next best thing is to conditionally define a swift let rtld_default = ... constant based on the target platform.
So the reason why we have null type info is that we rely on readObjCRODataPtr, called from readInstanceStartAndAlignmentFromClassMetadata, but this returns a null pointer since there's no Objc interop. The TypeMetadata doc describes that:
The rodata pointer is stored at offset 4; it points to an Objective-C compatible rodata record for the class. This pointer value includes a tag. The low bit is always set to 1 for Swift classes and always set to 0 for Objective-C classes.
But trying to read from the remote address + 4 returns a null pointer. What am I doing wrong?
Parts of readInstanceStartAndAlignmentFromClassMetadata assume the remote process is using an Apple runtime with ObjC interop, which won't be the case on Linux (cc'ing @Slava_Pestov to correct me if I'm wrong).
The class metadata layout is documented here. Have you tried looking up the "instance size" field if the ObjC RO data is unavailable?
I think readInstanceStartAndAlignmentFromClassMetadata is basically trying to determine the size of an instance, i.e. including contributions to the size from any superclasses.
Just to make sure I'm doing this correctly. If I want the instance size field would that be at: MetadataAddress + (8 * 5 [class flags offset] ) + 4 [class flags is 32 bits long] + 4 [instance address points is 32 bits long], assuming a 64 bit architecture right? I ask because I still a size of 0.
To close the loop: Augusto and I discovered an assumption about contiguous section layout in swift_reflection_addReflectionInfo which may not always hold, so we'll brainstorm a few ways to address that.
@augusto2112 At this point, I think it'll be hard for future readers to follow this thread. Let's start a new one if any more specific issues come up.