Exploring Native Memory Inspector Direction

188 views
Skip to first unread message

dheerajkumar thota

unread,
Mar 17, 2026, 8:15:29 AM (14 days ago) Mar 17
to dart-gsoc
Hi Mentors,

 I’m Dheeraj Kumar Thota, a Computer Science student. Over the past week I’ve been exploring the native memory inspector idea to better understand the UX and architectural challenges around debugging dart:ffi allocations.  

To ground my understanding, I built a small standalone prototype that visualizes raw native memory regions (allocated via FFI) using a dynamic hex-grid with basic type interpretation. This helped me explore practical concerns like struct alignment, manual pointer inspection, and large buffer navigation.  

GitHub Repository: https://github.com/dheeraj25517-code/Inspect-native-memory-in-Dart-DevTools-project

Since I am still early in understanding Dart VM internals and DevTools architecture, I am not fully certain whether this prototype direction aligns well with the intended project scope. I would really value feedback on whether this exploration is meaningful or if I should redirect my efforts.  
  • How native allocation lifecycle signals (e.g., external memory accounting) could be surfaced for debugging
  • Feasibility of safely exposing raw memory ranges via the VM service / DDS pipeline
  • Approaches to recovering or associating type/layout metadata for FFI pointers at runtime
I would appreciate guidance on a couple of early direction questions:
  • For initial contributions, would focusing on DevTools-side UX experimentation be more helpful, or exploring VM-service-level feasibility first?
  • Are there existing efforts or preferred approaches for improving observability of native allocations that I should align with?
I plan to continue exploring and contributing in this area and would be grateful for any suggestions on how to proceed.  

Best regards,
Dheeraj Kumar Thota

Daco Harkes

unread,
Mar 18, 2026, 3:27:58 PM (12 days ago) Mar 18
to dheerajkumar thota, dart-gsoc
Hi Dheerajkumar,

Cool!

You can build the Dart SDK locally and try to figure out how to add logic to the VM for safe memory dereference with OS APIs and how to add RPCs to DDS to expo such info.

Playing around with the Dart SDK codebase will give you more information on how what the problems are and what possible solutions are.

Kind regards,

 •  Daco Harkes
 •  Software Engineer
 •  dacoh...@google.com 


--
You received this message because you are subscribed to the Google Groups "dart-gsoc" group.
To unsubscribe from this group and stop receiving emails from it, send an email to dart-gsoc+...@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/dart-gsoc/f4576022-e86a-4f17-9b06-566dfd392502n%40googlegroups.com.

dheerajkumar thota

unread,
Mar 21, 2026, 10:19:09 AM (9 days ago) Mar 21
to dart-gsoc

Hi Mentors,

Following up on my previous introductory email, I’ve been closely following recent discussions around exposing native memory to DevTools—especially the thread involving Nourhan and Ben—which has been very helpful in shaping my approach.

I’ve started exploring the VM service implementation in runtime/vm/service.cc to understand how abstractions like MethodParameter and JSONStream are used to structure RPCs. Building on insights from my initial hex-grid prototype, I’m currently exploring the VM-side infrastructure that could support this kind of inspection safely. Key aspects I’m considering include:

  • Safety and Scoping: Instead of arbitrary address reads, I’m looking into restricting access to well-defined, VM-tracked regions. This includes not just internal heap pages, but also external/native allocations where the VM has visibility.
  • Incremental Access: Modeling the RPC to operate on controlled chunks (offset + size). My prototype highlighted the need for efficient navigation of large buffers, which aligns well with existing incremental patterns in the Service API.
  • Validation Logic: I’m researching how the Dart VM represents and tracks these external memory regions internally to ensure the RPC can fail gracefully for requests outside safe boundaries.

My work with the prototype helped me understand how layout and alignment impact interpretation, and I’m eager to translate those insights into a robust VM-service-layer solution that preserves safety and stability.

I’d greatly appreciate any guidance or suggestions on whether this direction—utilizing a region-aware RPC to back a native memory inspector—aligns with the team’s vision, or if there are specific constraints or prior work I should prioritize in my exploration.

Thanks for your guidance!

Best regards,
Dheeraj Kumar Thota

Daco Harkes

unread,
Mar 23, 2026, 2:42:29 AM (8 days ago) Mar 23
to dheerajkumar thota, dart-gsoc
Hi Dheeraj,
 
Safety and Scoping: Instead of arbitrary address reads, I’m looking into restricting access to well-defined, VM-tracked regions. This includes not just internal heap pages, but also external/native allocations where the VM has visibility.

That doesn't realy work right? Because the native code might have allocated memory and passed a Pointer to Dart. How would the VM register such region?

I think the better mental model is to see the Dart + native code as a single process, and rely on the OS APIs for dealing with the process boundaries. That's why we should use the OS system calls for seeing if memory is accessible.

Kind regards,

 •  Daco Harkes
 •  Software Engineer
 •  dacoh...@google.com 

dheerajkumar thota

unread,
Mar 24, 2026, 4:16:14 PM (6 days ago) Mar 24
to dart-gsoc

Hi Daco,

Thank you for the previous guidance. Shifting my perspective made me look deeper into OS-level memory handling—specifically VirtualQuery and ReadProcessMemory on Windows, and /proc/self/maps with process_vm_readv() on Linux—which has significantly clarified my technical roadmap. For now, I am focusing exclusively on Windows.

Based on your suggestion, I’m treating the OS APIs as the source of truth for memory accessibility, using ReadProcessMemory (with partial read handling) as the authoritative mechanism.

I’m currently exploring improving the efficiency of the read engine by introducing a lightweight, page-aware cache derived from VirtualQuery, mainly to:

  • skip obviously invalid regions (e.g., MEM_RESERVE)

  • reduce unnecessary system calls during large scans

However, this cache would only serve as a heuristic for performance and not as a source of correctness—all final decisions would still rely on the actual results from OS read results, ReadProcessMemory.

Would you recommend using VirtualQuery strictly as a performance hint to skip obviously invalid regions, while relying entirely on ReadProcessMemory (with recovery logic) for correctness?

Thanks again for your guidance!

Best regards,
Dheeraj Kumar Thota


Daco Harkes

unread,
Mar 25, 2026, 4:21:09 AM (6 days ago) Mar 25
to dheerajkumar thota, dart-gsoc, Ben Konyi
Hi Dheerajkumar,

Looking at the documentation for VirtualQuery, it should work reliably by itself. 👍
The best is to just play around with it and see what happens.

Scanning larger pieces of memory is useful indeed for if we have Pointer<...> that don't point to a single element but to a long range. The Pointers don't contain such information, but in the devtools UI we probably want have an option to expand showing a single element to a range of elements.

Kind regards,

 •  Daco Harkes
 •  Software Engineer
 •  dacoh...@google.com 

dheerajkumar thota

unread,
Mar 28, 2026, 4:44:31 AM (3 days ago) Mar 28
to dart-gsoc
Hi mentors, 

I’m currently preparing a GSoC 2026 proposal for the Dart/Flutter organization and would really appreciate some early feedback on the direction.
The idea focuses on improving debugging support for Dart FFI-based applications. At the moment, DevTools provides good visibility into the Dart heap, but there is limited support for inspecting native memory (e.g., pointers, raw memory regions, or structures coming from FFI).
My proposal explores a way to extend DevTools to enable structured native memory inspection, including:
  • Inspecting memory at a given address
  • Visualizing data in both structured and raw formats
  • Exploring pointer relationships interactively
I’ve also been experimenting with a small prototype to better understand feasibility and constraints.

At this stage, I’d really value feedback on:
  • Whether this problem is relevant to the Dart/Flutter ecosystem
  • Any potential concerns around feasibility or scope
  • Suggestions on aligning this better with DevTools architecture

I’ve attached a draft proposal for reference:

An early feedback on this would really help
Thank you for the guidance.

Best regards
Dheeraj Kumar Thota

Daco Harkes

unread,
5:32 AM (17 hours ago) 5:32 AM
to dheerajkumar thota, Ben Konyi, dart-gsoc
Hi Dheerajkumar,
  • Whether this problem is relevant to the Dart/Flutter ecosystem
Yes!
  • Any potential concerns around feasibility or scope
One of the challenges is that Pointer do not have a type argument at runtime, only at compile time. So, if you want to visualize the memory on the heap you need to come up with a way to figure out what the compile time type argument of the pointer is. We could for example do this via expression evaluation.
  • Suggestions on aligning this better with DevTools architecture
@Ben Konyi Is better suited to reply to this.

Kind regards,

 •  Daco Harkes
 •  Software Engineer
 •  dacoh...@google.com 

dheerajkumar thota

unread,
10:07 AM (12 hours ago) 10:07 AM
to dart-gsoc, Daco Harkes, Ben Konyi

Hi Daco and Ben,

Following our recent discussions, I took a step back to refine the architecture and ensure it aligns more closely with how DevTools and the Dart VM are intended to work—especially around expression evaluation and type handling.

The system should use the Dart VM’s type system (via expression evaluation) to guide memory interpretation.

This directly addresses the limitation that "Pointer<T>" does not retain its type argument at runtime. By using expression evaluation ("evaluate" / "evaluateInFrame"), we can recover type information (including generics like "List<int>" or "Pointer<Int32>") and use that to drive how memory is interpreted.

From my understanding, the system is now structured as two loosely coupled layers:

1. DevTools / VM Layer (Object World – Primary Mode)

- Entry via expression evaluation:
  evaluate("expr") → InstanceRef → getObject()
- Provides:
  - Type information
  - Object structure (fields, values)
  - Safe, VM-managed references ("objectId")

This remains the source of truth, fully aligned with DevTools.


2. Memory Inspection Layer 

- Operates independently using:
  
  - Native memory reads (e.g., "ReadProcessMemory")
  - Dart VM layout knowledge ("object.h", ClassId, tags_)

- Pipeline:
  
  raw address → tag check → tags_ → ClassId → decode known layouts

- Purpose:
  
  - Low-level introspection
  - Layout validation
  - Debugging beyond VM abstractions

Relationship Between the Two

this system now treats it as an augmentation layer:

- Expression evaluation → provides type + structure
- Memory inspection → provides raw representation + deeper visibility

Modes of Operation

Mode 1 — DevTools-native (Primary, MVP)

- Expression → InstanceRef → structured object view
- Optional: enhanced visualization using type-aware decoding
  -Safe, fully aligned, no VM assumptions

Mode 2 — Address-based (Secondary)

- Direct "inspect(address)" → raw memory decoding
  -Independent of DevTools, useful for low-level debugging

Mode 3 — Object-to-address bridge (Exploratory)

- "objectId → address" (if possible)
  Not assumed, may require VM support or deeper investigation

Alignment with Expression Evaluation

This refined model uses expression evaluation to:

- Recover type information that is otherwise unavailable at runtime
- Guide how memory should be interpreted (instead of guessing)
- Stay within DevTools’ object-centric design

For example:

- "evaluate("ptr") → Pointer<Int32>"
  - interpret memory as 4-byte integers

- "evaluate("myList") → List<int>"
  -decode as array layout with integer elements


1. Does this separation between:
   
   - DevTools object inspection (primary)
   - Memory inspection (complementary)
   
   align with how you envision this fitting into DevTools?

2. Is treating address-based inspection as a separate, independent mode (rather than deriving it from "InstanceRef") the right architectural decision?

3. For the “expression evaluation → type → memory interpretation” flow:
   
   - Does this correctly address the concern about missing runtime type information for pointers?

4. Do you think exploring an optional "objectId → address" bridge is worthwhile, or should I explicitly avoid that direction?

Best regards,
Dheeraj Kumar Thota

Daco Harkes

unread,
11:04 AM (11 hours ago) 11:04 AM
to dheerajkumar thota, dart-gsoc, Ben Konyi
Hi Dheerajkumar,

The best way to answer architectural questions like this is to check out the codebase locally and try to make a prototype work.

I'm not sure what we need List<int> for. This project is focused on the FFI types, not on the other Dart types in the DevTools.

Object inspection is not very useful for Pointer, because the Pointer object only contains a 32 or 64 bit integer address pointing to native memory. The whole point of this project is to visualize that native memory.

I don't know enough about the dev tools protocol to reply to objectId, maybe @Ben Konyi can reply to that.

Kind regards,

 •  Daco Harkes
 •  Software Engineer
 •  dacoh...@google.com 

Reply all
Reply to author
Forward
0 new messages