2 (* Memory info command for virtual domains.
3 (C) Copyright 2008 Richard W.M. Jones, Red Hat Inc.
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 Memory maps represent the virtual memory of a virtual machine.
25 We are mostly interested in the kernel memory and kernel data
26 structures. In Linux this stays at the same virtual memory
27 address whichever task is actually running (eg. on i386 machines,
28 the kernel is often found at virtual address 0xC0100000). Kernel
29 memory is spread out over several ranges of addresses, with gaps
30 of uninteresting or non-existant virtual addresses in between, and
31 this structure captures that.
33 A memory map is a range of 64 bit addresses from [0] to [2^64-1].
34 (Note that 64 bit addresses are used even for 32 bit virtual
35 machines - just ignore everything above 0xFFFFFFFF).
37 A memory map consists of zero or more {b mappings} of data. A
38 mapping starts at some address and has some size, and the data for
39 a mapping can come from some source such as a file or OCaml
40 string. Use {!of_file}, {!of_string}, {!add_file}, {!add_string}
41 to create a memory map from mappings.
43 {3 Overlapping mappings and holes}
45 If mappings overlap, then the mapping which was added later
46 overrides/overwrites earlier mappings at any addresses which
49 Where there is no mapping for a particular address, the memory map
50 is said to have a hole. (Typically almost all of a memory map is
51 holes). In general, the searching functions such as {!find} skip
52 over holes, while the accessor functions such as {!get_bytes}
53 raise an error if you try to read a hole, but read the individual
54 function documentation.
56 {3 Word size and endianness}
58 Memory maps may (or may not) have an associated word size and
59 endianness for the whole map. These are used when we look at
60 integers and pointers in the memory. See {!get_endian},
61 {!set_endian}, {!get_wordsize} and {!set_wordsize}, and accessor
62 functions such as {!get_int32} and {!follow_pointer}.
66 Mappings' data are stored in 1D Bigarrays. The advantages of
67 using a Bigarray are: (a) hidden from the garbage collector, (b)
68 easily accessible from C, (c) uses mmap(2) where possible.
70 Some low level functions are written in C for speed.
72 Mappings are stored in a segment tree for efficient access, but
73 the segment tree has to be rebuilt from scratch each time you add
74 a new mapping. It is not known if there is a more efficient way
75 to incrementally update a segment tree. In any case, as long as
76 you are mainly doing lookups / searches / getting bytes, this is
85 The ['ws], ['e] and ['hm] type parameters are phantom types
86 designed to ensure you don't try illegal operations before
87 initializing certain parts of the memory map. If you are not
88 familiar with phantom types, you can just ignore them.
91 {{:http://camltastic.blogspot.com/2008/05/phantom-types.html}this
92 posting about the phantom types used in virt-mem}.
94 The memory map structure is an example of a
95 {{:http://en.wikipedia.org/wiki/Purely_functional}persistent
100 (** Virtual memory addresses (even on 32 bit machines). *)
102 (** {2 Create a memory map, add mappings} *)
104 val create : unit -> ([`NoWordsize], [`NoEndian], [`NoMappings]) t
105 (** Create a new, empty memory map. *)
107 val of_file : Unix.file_descr -> addr ->
108 ([`NoWordsize], [`NoEndian], [`HasMapping]) t
109 (** Create a new memory map, mapping file [fd] at address [addr]. *)
111 val add_file : ('ws, 'e, 'hm) t -> Unix.file_descr -> addr ->
112 ('ws, 'e, [`HasMapping]) t
113 (** Add file [fd] at address [addr] to an existing memory map.
114 The new mapping can overwrite all or part of an existing mapping. *)
116 val of_string : string -> addr -> ([`NoWordsize], [`NoEndian], [`HasMapping]) t
117 (** Create a new memory map, mapping string at address [addr]. *)
119 val add_string : ('ws, 'e, 'hm) t -> string -> addr ->
120 ('ws, 'e, [`HasMapping]) t
121 (** Add string at address [addr] to an existing memory map.
122 The new mapping can overwrite all or part of an existing mapping. *)
124 val set_wordsize : ([`NoWordsize], 'e, 'hm) t -> Virt_mem_utils.wordsize ->
125 ([`Wordsize], 'e, 'hm) t
126 (** Set the natural wordsize of the memory map. This is used
127 for matching integers and pointers within the map and can be
130 val set_endian : ('ws, [`NoEndian], 'hm) t -> Bitstring.endian ->
131 ('ws, [`Endian], 'hm) t
132 (** Set the natural endianness of the memory map. This is used
133 for matching integers and pointers within the map and can be
136 val get_wordsize : ([`Wordsize], 'e, 'hm) t -> Virt_mem_utils.wordsize
137 (** Return the wordsize previously set for this memory map. *)
139 val get_endian : ('ws, [`Endian], 'hm) t -> Bitstring.endian
140 (** Return the endianness previously set for this memory map. *)
144 val find : ('ws, 'e, [`HasMapping]) t -> ?start:addr -> string -> addr option
145 (** Find string in a memory map and return its address (if found)
146 or [None] (if not found). You can pass an optional starting
147 address. If no start address is given, we begin searching at
148 the beginning of the first mapping.
150 Any holes in the memory map are skipped automatically.
152 Note that this doesn't find strings which straddle the
153 boundary of two adjacent or overlapping mappings.
155 Note that because the string being matched is an OCaml
156 string it may contain NULs (zero bytes) and those are matched
159 val find_align : ([`Wordsize], 'e, [`HasMapping]) t -> ?start:addr -> string ->
161 (** Same as {!find}, but the string must be aligned to the word size of
164 val find_all : ('ws, 'e, [`HasMapping]) t -> ?start:addr -> string -> addr list
165 (** Same as {!find}, but returns all occurrences of a string in a memory map. *)
167 val find_all_align : ([`Wordsize], 'e, [`HasMapping]) t -> ?start:addr ->
169 (** Same as {!find_all}, but the strings must be aligned to the word size. *)
171 val find_pointer : ([`Wordsize], [`Endian], [`HasMapping]) t -> ?start:addr ->
173 (** Find a pointer (address) in the memory map.
174 The pointer must be aligned to a word. *)
176 val find_pointer_all : ([`Wordsize], [`Endian], [`HasMapping]) t ->
177 ?start:addr -> addr -> addr list
178 (** Find all occurrences of a pointer in the memory map. *)
180 (** {2 Get bytes and ranges of bytes} *)
182 val get_byte : ('ws, 'e, [`HasMapping]) t -> addr -> int
183 (** Return the byte at the given address.
185 This will raise [Invalid_argument "get_byte"] if the address is
186 a hole (not mapped). *)
188 val get_bytes : ('ws, 'e, [`HasMapping]) t -> addr -> int -> string
189 (** Return the sequence of bytes starting at the given address.
191 This will raise [Invalid_argument "get_bytes"] if the address range
194 val get_int32 : ('ws, [`Endian], [`HasMapping]) t -> addr -> int32
195 (** Return the 32-bit int at [addr]. *)
197 val get_int64 : ('ws, [`Endian], [`HasMapping]) t -> addr -> int64
198 (** Return the 64-bit int at [addr]. *)
200 val get_C_int : ([`Wordsize], [`Endian], [`HasMapping]) t -> addr -> int32
201 (** Return the C 32-bit int at [addr]. *)
203 val get_C_long : ([`Wordsize], [`Endian], [`HasMapping]) t -> addr -> int64
204 (** Return the C 32 or 64-bit long at [addr]. *)
206 val get_string : ('ws, 'e, [`HasMapping]) t -> addr -> string
207 (** Return the sequence of bytes starting at [addr] up to (but not
208 including) the first ASCII NUL character. In other words, this
209 returns a C-style string.
211 This may raise [Invalid_argument "get_string"] if we reach a
212 hole (unmapped address) before finding the end of the string.
214 See also {!get_bytes}, {!is_string} and {!is_C_identifier}. *)
216 val is_string : ('ws, 'e, [`HasMapping]) t -> addr -> bool
217 (** Return true or false if the address contains an ASCII NUL-terminated
220 val is_C_identifier : ('ws, 'e, [`HasMapping]) t -> addr -> bool
221 (** Return true or false if the address contains a NUL-terminated
224 val is_mapped : ('ws, 'e, 'hm) t -> addr -> bool
225 (** Return true if the single address [addr] is mapped. *)
227 val is_mapped_range : ('ws, 'e, 'hm) t -> addr -> int -> bool
228 (** Return true if all addresses in the range [addr] to [addr+size-1]
231 val follow_pointer : ([`Wordsize], [`Endian], [`HasMapping]) t -> addr -> addr
232 (** Follow (dereference) the pointer at [addr] and return
233 the address pointed to. *)
235 val succ_long : ([`Wordsize], 'e, [`HasMapping]) t -> addr -> addr
236 (** Add wordsize bytes to [addr] and return it. *)
238 val pred_long : ([`Wordsize], 'e, [`HasMapping]) t -> addr -> addr
239 (** Subtract wordsize bytes from [addr] and return it. *)
241 val align : ([`Wordsize], 'e, [`HasMapping]) t -> addr -> addr
242 (** Align the [addr] to the next wordsize boundary. If it already
243 aligned, this just returns [addr]. *)
245 (** {2 Save and load memory maps} *)
247 (*val to_channel : ('ws, 'e, [`HasMapping]) t -> out_channel -> unit*)
248 (** Write the memory map and data to the given output channel in
249 a reasonably efficient and stable binary format. *)
251 (*val from_channel : in_channel -> ('?, '?, [`HasMapping]) t*)
252 (** Read a previously saved memory map. If the input channel does
253 not contain a memory map, this raises [Invalid_argument]. *)