Listing memory regions in lldb

I’m working on a plugin for lldb and need to scan the memory of a crashed process. Using the API to read chunks of memory and scan (via SBProcess::Read*) for what I’m looking for is easy but I haven’t been able to find a way to find which address ranges are accessible. The SBProcess::Read* calls will return an error on an invalid address but it’s not an efficient way to scan a 64 bit address space.

This seems like it blocks simple tasks like scanning memory for blocks allocated with a header and footer to track down memory leaks, which is crude but traditional, and ought to be pretty quick to script via the Python API.

At the moment I’ve resorted to running a python script prior to launching my plugin that takes the output of “readelf --segments”, /proc//maps or “otool -l” but this isn’t ideal. On the assumption that I’m not missing something huge I’ve looked at whether it is possible to extend LLDB to provide this functionality and it seems possible, there are checks protecting calls to read memory that use the data that would need to be exposed. I’m working on a prototype implementation which I’d like to deliver back at some stage but before I go too far does this sound like a good idea?

You should be able to enumerate the memory that is occupied by loaded executables, by getting the list of loaded Modules from the target, and iterate through the all the Sections. The Sections know their loaded locations. I assume all the mapped ones will return a valid load address from GetLoadBaseAddress, so you can distinguish the loaded and unloaded ones. So you shouldn't need "readelf --segments" or "otool -l", lldb should know this.

You can scan the currently active stacks, but we don't currently know the allocated stack extents, just what is being used. It would be interesting to know the actual stack extents, so you could search in old stacks and to know if you are close to exhausting the stack of a thread.

We don't have either a generic API, or internal implementations, for getting all the mapped memory regions (or shared pages) of processes. That would be quite useful. IIRC ptr_refs does this by injecting some code into the target program that enumerates the regions. Greg would know more about this. Most systems provide some API to get at this that works cross-process, but that doesn't help debugging remotely. So we either need to teach debugserver & lldb-server to do this, or use appropriate code injection. The gdb-remote protocol has a query for the "memory map" of the process, though this is more tailored to identify things like memory mapped registers. Still it might be possible to use this as well.

It would be nice to be able to separately query heap, executable & stack memory as well. Though a properly annotated memory map would give you a way to do this, so that could be layered on top.

Jim

We have a way internally with:

    virtual Error
    lldb_private::Process::GetMemoryRegionInfo (lldb::addr_t load_addr, MemoryRegionInfo &range_info);

This isn't expose via the public API in lldb::SBProcess. If you want, you can expose this. We would need to expose a SBMemoryRegionInfo and the call could be:

namespace lldb
{
    class SBProcess
    {
        SBError GetMemoryRegionInfo (lldb::addr_t load_addr, SBMemoryRegionInfo &range_info);
    };
}

then you would call this API with address zero and it would return a SBMemoryRegionInfo with an address range and if that memory is read/write/execute. On MacOSX we always have a page zero at address 0 for 64 bit apps so it would respond with:

[0x0 - 0x100000000) read=false, write=false, execute=false

Then you call the function again with the end address of the previous range.

I would love to see this functionality exported through our public API. Let me know if you are up for making a patch. If you are, you might want to quickly read the following web page to see the rules that we apply to anything going into our public API:

http://lldb.llvm.org/SB-api-coding-rules.html

Greg

Oh, that's a cute trick, but it relies on the not (at-least-to-me) obvious fact that an address in an unmapped region will return the extents of the unmapped region. For it to be useful, that needs to be a requirement of the API's implementation.

It seems to me it would be much clearer to have an API that returns the memory regions for you.

Jim

I have experimented with the GetMemoryRegionInfo approach on the internal APIs already, it has some positives and negatives.

  • GetMemoryRegionInfo is unimplemented for Linux and Mac core dumps. That’s not necessarily a bad thing as it could be implemented the “right” way. (As Jim said GetMemoryRegionInfo would have to return the right thing for an unmapped region.) Interestingly when I’ve worked on Windows core dumps before I’ve seen that MiniDump, with the right flags, will deliberately insert a region in the middle of the memory ranges to represent the unmapped space, on 64 bit it’s quite a large section.

  • Using GetMemoryRegionInfo to iterate might be quite expensive if there are many small memory regions.

  • One reason I hadn’t looked at just exposing an SBGetMemoryRegionInfo is that it wouldn’t match a lot of the SB API’s at the moment (for example for Threads and Sections) which tend work by having GetNumXs() and GetXAtIndex() calls. Iterating with SBGetMemoryRegionInfo would be non-obvious to the user of the API since it doesn’t match the convention. It would need to be documented in the SBGetMemoryRegionInfo API.

  • I’ve found the only way to reliably filter out inaccessible memory is to do a test read and check the error return code. I’m pretty sure I’ve seen some that are readable via a memory read but marked read=false, write=false, execute=false. (I can’t remember the exact case now off the top of my head, but I think it might have been allocated but uncommitted memory or similar.)

  • Using GetMemoryRegionInfo over a remote connection on Linux and Mac worked well but seemed to coalesce some of the memory regions together. It also only allows for read/write/exec attributes to be passed. That’s a shame as a live process can often tell you more about what the region is for. The remote command memory map looks like it sends back XML so it might be possible to insert custom properties in there to give more information but I’m not sure how safe it is to do that, I don’t know the project quite well enough to understand all the use cases for the protocol.

  • Extended infomation /proc/pid/maps marking a region as [stack] would be lost. All you would get is read/write/exec info. (That said supporting everything every platform can provide might be a bit much.)

  • LLDB’s ReadMemory implementations seem to return 0’s for missing memory that should be accessible. It might be nice to include whether the memory is backed by real data or not in the API. (For example Linux core files can be missing huge pages depending on the setting of /proc/PID/coredump_filter or files can simply be truncated.)

I could implement the GetMemoryRegionInfo iteration mechanism pretty quickly and it would actually fit my purposes as far as providing all the addresses you can sensibly access.

I’m quite keen to provide a patch but don’t want to provide one that is at odds with how the rest of lldb works or provides data that’s only useful to me so I’m quite keen to get a bit of feedback on what the preferred approach would be. It could be that providing both SBGetMemoryRegionInfo and the SBGetNumMemoryRegions/SBGetMemoryRegionAtIndex pair is the right solution.

Would a patch also need to provide a command to dump this information as it can be awkward to have data that’s only accessible via the API?

Howard Hellyer
IBM Runtime Technologies, IBM Systems |


|

  • | - |

> To: Howard Hellyer/UK/IBM@IBMGB
> Cc: lldb-dev@lists.llvm.org
> Date: 12/05/2016 19:10
> Subject: Re: [lldb-dev] Listing memory regions in lldb
>
> We have a way internally with:
>
> virtual Error
> lldb_private::Process::GetMemoryRegionInfo (lldb::addr_t
> load_addr, MemoryRegionInfo &range_info);
>
> This isn't expose via the public API in lldb::SBProcess. If you
> want, you can expose this. We would need to expose a
> SBMemoryRegionInfo and the call could be:
>
> namespace lldb
> {
> class SBProcess
> {
> SBError GetMemoryRegionInfo (lldb::addr_t load_addr,
> SBMemoryRegionInfo &range_info);
> };
> }
>
> then you would call this API with address zero and it would return a
> SBMemoryRegionInfo with an address range and if that memory is read/
> write/execute. On MacOSX we always have a page zero at address 0 for
> 64 bit apps so it would respond with:
>
> [0x0 - 0x100000000) read=false, write=false, execute=false
>
> Then you call the function again with the end address of the previous range.
>
> I would love to see this functionality exported through our public
> API. Let me know if you are up for making a patch. If you are, you
> might want to quickly read the following web page to see the rules
> that we apply to anything going into our public API:
>
> http://lldb.llvm.org/SB-api-coding-rules.html
>
>
> Greg
>
> > On May 12, 2016, at 6:20 AM, Howard Hellyer via lldb-dev <lldb-
> dev@lists.llvm.org> wrote:
> >
> > I'm working on a plugin for lldb and need to scan the memory of a
> crashed process. Using the API to read chunks of memory and scan
> (via SBProcess::Read*) for what I'm looking for is easy but I
> haven't been able to find a way to find which address ranges are
> accessible. The SBProcess::Read* calls will return an error on an
> invalid address but it's not an efficient way to scan a 64 bit address space.
> >
> > This seems like it blocks simple tasks like scanning memory for
> blocks allocated with a header and footer to track down memory
> leaks, which is crude but traditional, and ought to be pretty quick
> to script via the Python API.
> >
> > At the moment I've resorted to running a python script prior to
> launching my plugin that takes the output of "readelf --segments", /
> proc/<pid>/maps or "otool -l" but this isn't ideal. On the
> assumption that I'm not missing something huge I've looked at
> whether it is possible to extend LLDB to provide this functionality
> and it seems possible, there are checks protecting calls to read
> memory that use the data that would need to be exposed. I'm working
> on a prototype implementation which I'd like to deliver back at some
> stage but before I go too far does this sound like a good idea?
> > Howard Hellyer
> > IBM Runtime Technologies, IBM Systems
> >
> >
> > _______________________________________________
> > lldb-dev mailing list
> > lldb-dev@lists.llvm.org
> > http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev
>

Interestingly when I’ve worked on Windows core dumps before I’ve seen that MiniDump, with the right flags, will deliberately insert a region in the middle of the memory ranges to represent the unmapped space, on 64 bit it’s quite a large section.

On Intel processors, the best way to do this is probably going to be to walk the page directory (see Intel processor manuals). Assuming someone implements this command in lldb, I hope it can be done in such a way as to allow different implementations when one os/architecture has a better way of doing it.

Apologies, I don’t mean either of those.

This was working on a debug tool for the IBM JVM. When we added the MiniDumpWithFullMemoryInfo to our calls to MiniDumpWriteDump we found it inserted blank ranges to keep the regions in the MINIDUMP_MEMORY_INFO_LIST structure contiguous. I checked a dump just now and it has a 8 Tb region without and access flags inserted in the middle, probably because of a gap in the addresses the libraries were loaded at, but it hasn’t added an enormous one at the end.

This is what I see:

0x00000000ffef0000 0x00000000fffeffff 0x0000000000100000 (1,048,576) RW
0x00000000ffff0000 0x00000000ffffffff 0x0000000000010000 (65,536) 0x0000000100000000 0x000007ff7713ffff 0x000007fe77140000 (8,789,500,887,040)

0x000007ff77140000 0x000007ff7714bfff 0x000000000000c000 (49,152) R

I guess I was trying to ask whether the LLDB API would report a region like that or not really but if we use the SBMemoryRegionInfo iteration model it won’t really matter - there would be an equivalent blank one there anyway so it doesn’t make any difference.


Howard Hellyer
IBM Runtime Technologies, IBM Systems
|
|

  • | - |

From: Adrian McCarthy amccarth@google.com
To: Howard Hellyer/UK/IBM@IBMGB
Cc: Greg Clayton gclayton@apple.com, LLDB lldb-dev@lists.llvm.org
Subject: Re: [lldb-dev] Listing memory regions in lldb
Date: Fri, May 13, 2016 4:57 PM

Interestingly when I’ve worked on Windows core dumps before I’ve seen that MiniDump, with the right flags, will deliberately insert a region in the middle of the memory ranges to represent the unmapped space, on 64 bit it’s quite a large section.

Are you saying that’s a bug in the minidump itself or in LLDB’s handling of it? If the latter, please send me the details (e.g., which flags trigger this behavior), and I’ll see what I can do about it.

Adrian.

Unless stated otherwise above:
IBM United Kingdom Limited - Registered in England and Wales with number 741598.
Registered office: PO Box 41, North Harbour, Portsmouth, Hampshire PO6 3AU

Apologies for the confusion, I don’t mean either of those.

This was working on a debug tool for the IBM JVM. When we added the MiniDumpWithFullMemoryInfo to our calls to MiniDumpWriteDump we found it inserted blank ranges to keep the regions in the MINIDUMP_MEMORY_INFO_LIST structure contiguous. I checked a dump just now and it has a 8 Tb region without and access flags inserted in the middle, probably because of a gap in the addresses the libraries were loaded at, but it hasn’t added an enormous one at the end.

This is what I see (from a random dump of no special importance!):

0x00000000ffef0000 0x00000000fffeffff 0x0000000000100000 (1,048,576) RW
0x00000000ffff0000 0x00000000ffffffff 0x0000000000010000 (65,536)
0x0000000100000000 0x000007ff7713ffff 0x000007fe77140000 (8,789,500,887,040)
0x000007ff77140000 0x000007ff7714bfff 0x000000000000c000 (49,152) R

I guess I was trying to ask whether the LLDB API would report a region like that or not really but if we use the SBMemoryRegionInfo iteration model it won’t really matter - there would be an equivalent blank one there anyway so it doesn’t really make a difference.

Howard Hellyer
IBM Runtime Technologies, IBM Systems |

  • |

> To: Howard Hellyer/UK/IBM@IBMGB
> Cc: Greg Clayton <gclayton@apple.com>, LLDB <lldb-dev@lists.llvm.org>
> Date: 13/05/2016 16:57
> Subject: Re: [lldb-dev] Listing memory regions in lldb
>
> Interestingly when I've worked on Windows core dumps before I've
> seen that MiniDump, with the right flags, will deliberately insert a
> region in the middle of the memory ranges to represent the unmapped
> space, on 64 bit it's quite a large section.
>
> Are you saying that's a bug in the minidump itself or in LLDB's
> handling of it? If the latter, please send me the details (e.g.,
> which flags trigger this behavior), and I'll see what I can do about it.
>
> Adrian.
>
> On Fri, May 13, 2016 at 3:35 AM, Howard Hellyer via lldb-dev <lldb-
> dev@lists.llvm.org> wrote:
> I have experimented with the GetMemoryRegionInfo approach on the
> internal APIs already, it has some positives and negatives.
>
> - GetMemoryRegionInfo is unimplemented for Linux and Mac core dumps.
> That's not necessarily a bad thing as it could be implemented the
> "right" way. (As Jim said GetMemoryRegionInfo would have to return
> the right thing for an unmapped region.) Interestingly when I've
> worked on Windows core dumps before I've seen that MiniDump, with
> the right flags, will deliberately insert a region in the middle of
> the memory ranges to represent the unmapped space, on 64 bit it's
> quite a large section.
>
> - Using GetMemoryRegionInfo to iterate might be quite expensive if
> there are many small memory regions.
>
> - One reason I hadn't looked at just exposing an
> SBGetMemoryRegionInfo is that it wouldn't match a lot of the SB
> API's at the moment (for example for Threads and Sections) which
> tend work by having GetNumXs() and GetXAtIndex() calls. Iterating
> with SBGetMemoryRegionInfo would be non-obvious to the user of the
> API since it doesn't match the convention. It would need to be
> documented in the SBGetMemoryRegionInfo API.
>
> - I've found the only way to reliably filter out inaccessible memory
> is to do a test read and check the error return code. I'm pretty
> sure I've seen some that are readable via a memory read but marked
> read=false, write=false, execute=false. (I can't remember the exact
> case now off the top of my head, but I think it might have been
> allocated but uncommitted memory or similar.)
>
> - Using GetMemoryRegionInfo over a remote connection on Linux and
> Mac worked well but seemed to coalesce some of the memory regions
> together. It also only allows for read/write/exec attributes to be
> passed. That's a shame as a live process can often tell you more
> about what the region is for. The remote command memory map looks
> like it sends back XML so it might be possible to insert custom
> properties in there to give more information but I'm not sure how
> safe it is to do that, I don't know the project quite well enough to
> understand all the use cases for the protocol.
>
> - Extended infomation /proc/pid/maps marking a region as [stack]
> would be lost. All you would get is read/write/exec info. (That said
> supporting everything every platform can provide might be a bit much.)
>
> - LLDB's ReadMemory implementations seem to return 0's for missing
> memory that should be accessible. It might be nice to include
> whether the memory is backed by real data or not in the API. (For
> example Linux core files can be missing huge pages depending on the
> setting of /proc/PID/coredump_filter or files can simply be truncated.)
>
> I could implement the GetMemoryRegionInfo iteration mechanism pretty
> quickly and it would actually fit my purposes as far as providing
> all the addresses you can sensibly access.
>
> I'm quite keen to provide a patch but don't want to provide one that
> is at odds with how the rest of lldb works or provides data that's
> only useful to me so I'm quite keen to get a bit of feedback on what
> the preferred approach would be. It could be that providing both
> SBGetMemoryRegionInfo and the SBGetNumMemoryRegions/
> SBGetMemoryRegionAtIndex pair is the right solution.
>
> Would a patch also need to provide a command to dump this
> information as it can be awkward to have data that's only accessible
> via the API?

>
> Howard Hellyer
> IBM Runtime Technologies, IBM Systems
>
>
>
>

On Intel processors, the best way to do this is probably going to be to walk the page directory (see Intel processor manuals). Assuming someone implements this command in lldb, I hope it can be done in such a way as to allow different implementations when one os/architecture has a better way of doing it.

This would fall out naturally if the gathering of the data is done in debugserver/lldb-server, which seems to me the natural place for this work to be done.

Jim

I am fine with adding new key/value pairs to each memory region so feel free to extend as needed as long as any missing keys ("memory_type == stack" for example) default to something sensible. Then each process plug-in can do what it can do and the process plug-ins will fill in as much info as possible. More comments below.

I have experimented with the GetMemoryRegionInfo approach on the internal APIs already, it has some positives and negatives.

- GetMemoryRegionInfo is unimplemented for Linux and Mac core dumps. That's not necessarily a bad thing as it could be implemented the "right" way. (As Jim said GetMemoryRegionInfo would have to return the right thing for an unmapped region.) Interestingly when I've worked on Windows core dumps before I've seen that MiniDump, with the right flags, will deliberately insert a region in the middle of the memory ranges to represent the unmapped space, on 64 bit it's quite a large section.

this is very easy to implement as the there are just sections that say "these bytes are for [0x100000000-0x100001000)". I know Mach-o core files on Mac can get the read/write/execute permissions. You can figure out the gaps very easily as well in mach-o. So this shouldn't be a problem for core files. If the core file is smart enough to say "here is the full map of what was in memory, but the sections only describe part of the actual memory", then we should be able to work with this still.

- Using GetMemoryRegionInfo to iterate might be quite expensive if there are many small memory regions.

Remember that the other use for GetMemoryRegionInfo() might be a user just asking about an address they have in a register or variable that is a pointer. So if we do add a more complex iteration scheme, feel free to do so, but please leave the call that ask about a single address intact so it can be used by clients

- One reason I hadn't looked at just exposing an SBGetMemoryRegionInfo is that it wouldn't match a lot of the SB API's at the moment (for example for Threads and Sections) which tend work by having GetNumXs() and GetXAtIndex() calls. Iterating with SBGetMemoryRegionInfo would be non-obvious to the user of the API since it doesn't match the convention. It would need to be documented in the SBGetMemoryRegionInfo API.

I don't think that the design of SBMemoryRegionInfo is affected by which approach we take. If we can ask about a single address with:

SBError
SBTarget::GetMemoryRegionInfo(lldb::addr_t load_addr, SBMemoryRegionInfo &region_info);

Or if we have:

uint32_t
SBTarget::GetNumMemoryRegions();

bool
SBTarget::GetMemoryRegionAtIndex(uint32_t idx, SBMemoryRegionInfo &region_info);

It still doesn't change SBMemoryRegionInfo's definition. I don't like the above two calls because if you do something bad like:

const uint32_t num_regions = target.GetNumMemoryRegions();
target.GetProcess().Continue();
...
SBMemoryRegionInfo region_info;
for (uint32_t i=0; i<num_regions; ++i)
{
    if (target.GetMemoryRegionAtIndex(i, region_info))
        //....
}

you don't know if num_regions is valid anymore since the process was continued. So any new API should actually do something like:

SBMemoryRegionInfoList SBTarget::GetMemoryRegions();

Then then we have:

uint32_t SBMemoryRegionInfoList::GetSize();
bool SBMemoryRegionInfoList::GetRegionAtIndex(uint32_t idx, SBMemoryRegionInfo &region_info);

The data would have been cached at the time of the SBTarget::GetMemoryRegions() call and will be contain valid data for when it was called.

- I've found the only way to reliably filter out inaccessible memory is to do a test read and check the error return code. I'm pretty sure I've seen some that are readable via a memory read but marked read=false, write=false, execute=false. (I can't remember the exact case now off the top of my head, but I think it might have been allocated but uncommitted memory or similar.)

MacOSX knows this, but each process plug-in can do what it needs to in order to determine this.

- Using GetMemoryRegionInfo over a remote connection on Linux and Mac worked well but seemed to coalesce some of the memory regions together.

You might want to add an extra parameter to not coalesce regions. Or if we start adding names to the memory regions (".text", ".data") or types (stack, heap, section from a file, guard page) then we might just start not coalescing the regions so we can see these differences. Or we can add more options to the API:

SBMemoryRegionInfoList SBTarget::GetMemoryRegions(bool coalesce);

It also only allows for read/write/exec attributes to be passed. That's a shame as a live process can often tell you more about what the region is for. The remote command memory map looks like it sends back XML so it might be possible to insert custom properties in there to give more information but I'm not sure how safe it is to do that, I don't know the project quite well enough to understand all the use cases for the protocol.

We can easily add names to regions and it would be ok for a region to not have a name. We can also add types as a enumeration (stack, heap, section from a file, guard page).

- Extended infomation /proc/pid/maps marking a region as [stack] would be lost. All you would get is read/write/exec info. (That said supporting everything every platform can provide might be a bit much.)

- LLDB's ReadMemory implementations seem to return 0's for missing memory that should be accessible. It might be nice to include whether the memory is backed by real data or not in the API. (For example Linux core files can be missing huge pages depending on the setting of /proc/PID/coredump_filter or files can simply be truncated.)

I could implement the GetMemoryRegionInfo iteration mechanism pretty quickly and it would actually fit my purposes as far as providing all the addresses you can sensibly access.

I'm quite keen to provide a patch but don't want to provide one that is at odds with how the rest of lldb works or provides data that's only useful to me so I'm quite keen to get a bit of feedback on what the preferred approach would be. It could be that providing both SBGetMemoryRegionInfo and the SBGetNumMemoryRegions/SBGetMemoryRegionAtIndex pair is the right solution.

Would a patch also need to provide a command to dump this information as it can be awkward to have data that's only accessible via the API?

Howard Hellyer
IBM Runtime Technologies, IBM Systems

Hopefully my comments have provided some insight. Let me know what you come up with.

Greg Clayton

  • Using GetMemoryRegionInfo to iterate might be quite expensive if there are many small memory regions.

Remember that the other use for GetMemoryRegionInfo() might be a user just asking about an address they have in a register or variable that is a pointer. So if we do add a more complex iteration scheme, feel free to do so, but please leave the call that ask about a single address intact so it can be used by clients

Yep, that’s sensible. It gives a user an easy way to check things like “Does this char* really point to an area of writable memory?”

  • Using GetMemoryRegionInfo over a remote connection on Linux and Mac worked well but seemed to coalesce some of the memory regions together.

You might want to add an extra parameter to not coalesce regions. Or if we start adding names to the memory regions (“.text”, “.data”) or types (stack, heap, section from a file, guard page) then we might just start not coalescing the regions so we can see these differences. Or we can add more options to the API:

This may not be an issue. After a bit more digging I think it might be safer to have individual Process plug-ins implement GetMemoryRegionInfoList directly and they can use the GetMemoryRegionInfo iteration pattern if it’s safe.

SBMemoryRegionInfoList SBTarget::GetMemoryRegions(bool coalesce);

Hopefully my comments have provided some insight. Let me know what you come up with.

I agree the SBMemoryRegionInfoList approach makes the most sense, it’s much safer.

I think in my prototyping the main difference is that I’ve put GetMemoryRegions/GetMemoryRegionInfo on SBProcess simply because that’s where the internal GetMemoryRegions/GetMemoryRegionInfo functions it calls are but I’m happy with either if you have a preference.

I’m assuming the best way forward is to submit patches is via http://reviews.llvm.org/ ?

Rather than submit a monolithic one is I was going to submit one for the SB API changes first, calling lldb_private::Process::GetMemoryRegionInfoList with that having a default unsupported impl like lldb_private::Process::GetMemoryRegionInfo.

After that I can submit patches to fill in lldb_private::Process::GetMemoryRegionInfoList (and GetMemoryRegionInfo where’s it’s missing) on a per platform basis. (The alternative was to start with a command that exploits the new Process API for listing regions and work out from there, down into the process plug-ins and up into the SB API.)

Let me know if there’s a better way to do this!

Howard Hellyer
IBM Runtime Technologies, IBM Systems

>> - Using GetMemoryRegionInfo to iterate might be quite expensive if there are many small memory regions.
>
> Remember that the other use for GetMemoryRegionInfo() might be a user just asking about an address they have in a register or variable that is a pointer. So if we do add a more complex iteration scheme, feel free to do so, but please leave the call that ask about a single address intact so it can be used by clients

Yep, that's sensible. It gives a user an easy way to check things like "Does this char* really point to an area of writable memory?"

>> - Using GetMemoryRegionInfo over a remote connection on Linux and Mac worked well but seemed to coalesce some of the memory regions together.
>
> You might want to add an extra parameter to not coalesce regions. Or if we start adding names to the memory regions (".text", ".data") or types (stack, heap, section from a file, guard page) then we might just start not coalescing the regions so we can see these differences. Or we can add more options to the API:

This may not be an issue. After a bit more digging I think it might be safer to have individual Process plug-ins implement GetMemoryRegionInfoList directly and they can use the GetMemoryRegionInfo iteration pattern if it's safe.

> SBMemoryRegionInfoList SBTarget::GetMemoryRegions(bool coalesce);

> Hopefully my comments have provided some insight. Let me know what you come up with.

I agree the SBMemoryRegionInfoList approach makes the most sense, it's much safer.

I think in my prototyping the main difference is that I've put GetMemoryRegions/GetMemoryRegionInfo on SBProcess simply because that's where the internal GetMemoryRegions/GetMemoryRegionInfo functions it calls are but I'm happy with either if you have a preference.

On SBProcess is fine.

I'm assuming the best way forward is to submit patches is via http://reviews.llvm.org/ ?

Yep!

Rather than submit a monolithic one is I was going to submit one for the SB API changes first, calling lldb_private::Process::GetMemoryRegionInfoList with that having a default unsupported impl like lldb_private::Process::GetMemoryRegionInfo.

After that I can submit patches to fill in lldb_private::Process::GetMemoryRegionInfoList (and GetMemoryRegionInfo where's it's missing) on a per platform basis. (The alternative was to start with a command that exploits the new Process API for listing regions and work out from there, down into the process plug-ins and up into the SB API.)

Let me know if there's a better way to do this!

Either way, doesn't matter to me.

I look forward to seeing your patch.

Greg Clayton