78f9b8cea9a4c41da0dc10914c08279824384b2a
[virt-mem.git] / lib / virt_mem_mmap.mli
1 (** Memory map. *)
2 (* Memory info command for virtual domains.
3    (C) Copyright 2008 Richard W.M. Jones, Red Hat Inc.
4    http://libvirt.org/
5
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.
10
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.
15
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.
19  *)
20
21 (** {2 Memory maps}
22
23     Memory maps represent the virtual memory of a virtual machine.
24
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.
32
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).
36
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.
42
43     {3 Overlapping mappings and holes}
44
45     If mappings overlap, then the mapping which was added later
46     overrides/overwrites earlier mappings at any addresses which
47     coincide.
48
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.
55
56     {3 Word size and endianness}
57
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}.
63
64     {3 Efficiency}
65
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.
69
70     Some low level functions are written in C for speed.
71
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
77     very fast.
78 *)
79
80 (** {2 Types} *)
81
82 type ('ws,'e,'hm) t
83 (** Memory map.
84
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.
89
90     See also
91     {{:http://camltastic.blogspot.com/2008/05/phantom-types.html}this
92     posting about the phantom types used in virt-mem}.
93
94     The memory map structure is an example of a
95     {{:http://en.wikipedia.org/wiki/Purely_functional}persistent
96     data structure}.
97 *)
98
99 type addr = int64
100 (** Virtual memory addresses (even on 32 bit machines). *)
101
102 type 'a typed_addr
103 (** Virtual memory addresses with an implicit type, one which we know
104     or believe is pointing at a struct of some known type. *)
105
106 external unsafe_addr_of_typed_addr : 'a typed_addr -> addr = "%identity"
107 external unsafe_typed_addr_of_addr : addr -> 'a typed_addr = "%identity"
108
109 (** {2 Create a memory map, add mappings} *)
110
111 val create : unit -> ([`NoWordsize], [`NoEndian], [`NoMappings]) t
112 (** Create a new, empty memory map. *)
113
114 val of_file : Unix.file_descr -> addr ->
115   ([`NoWordsize], [`NoEndian], [`HasMapping]) t
116 (** Create a new memory map, mapping file [fd] at address [addr]. *)
117
118 val add_file : ('ws, 'e, 'hm) t -> Unix.file_descr -> addr ->
119   ('ws, 'e, [`HasMapping]) t
120 (** Add file [fd] at address [addr] to an existing memory map.
121     The new mapping can overwrite all or part of an existing mapping. *)
122
123 val of_string : string -> addr -> ([`NoWordsize], [`NoEndian], [`HasMapping]) t
124 (** Create a new memory map, mapping string at address [addr]. *)
125
126 val add_string : ('ws, 'e, 'hm) t -> string -> addr ->
127   ('ws, 'e, [`HasMapping]) t
128 (** Add string at address [addr] to an existing memory map.
129     The new mapping can overwrite all or part of an existing mapping. *)
130
131 val set_wordsize : ([`NoWordsize], 'e, 'hm) t -> Virt_mem_utils.wordsize ->
132   ([`Wordsize], 'e, 'hm) t
133 (** Set the natural wordsize of the memory map.  This is used
134     for matching integers and pointers within the map and can be
135     set only once. *)
136
137 val set_endian : ('ws, [`NoEndian], 'hm) t -> Bitstring.endian ->
138   ('ws, [`Endian], 'hm) t
139 (** Set the natural endianness of the memory map.  This is used
140     for matching integers and pointers within the map and can be
141     set only once. *)
142
143 val get_wordsize : ([`Wordsize], 'e, 'hm) t -> Virt_mem_utils.wordsize
144 (** Return the wordsize previously set for this memory map. *)
145
146 val get_endian : ('ws, [`Endian], 'hm) t -> Bitstring.endian
147 (** Return the endianness previously set for this memory map. *)
148
149 (** {2 Searching} *)
150
151 val find : ('ws, 'e, [`HasMapping]) t -> ?start:addr -> string -> addr option
152 (** Find string in a memory map and return its address (if found)
153     or [None] (if not found).  You can pass an optional starting
154     address.  If no start address is given, we begin searching at
155     the beginning of the first mapping.
156
157     Any holes in the memory map are skipped automatically.
158
159     Note that this doesn't find strings which straddle the
160     boundary of two adjacent or overlapping mappings.
161
162     Note that because the string being matched is an OCaml
163     string it may contain NULs (zero bytes) and those are matched
164     properly. *)
165
166 val find_align : ([`Wordsize], 'e, [`HasMapping]) t -> ?start:addr -> string ->
167   addr option
168 (** Same as {!find}, but the string must be aligned to the word size of
169     the memory map. *)
170
171 val find_all : ('ws, 'e, [`HasMapping]) t -> ?start:addr -> string -> addr list
172 (** Same as {!find}, but returns all occurrences of a string in a memory map. *)
173
174 val find_all_align : ([`Wordsize], 'e, [`HasMapping]) t -> ?start:addr ->
175   string -> addr list
176 (** Same as {!find_all}, but the strings must be aligned to the word size. *)
177
178 val find_pointer : ([`Wordsize], [`Endian], [`HasMapping]) t -> ?start:addr ->
179   addr -> addr option
180 (** Find a pointer (address) in the memory map.
181     The pointer must be aligned to a word. *)
182
183 val find_pointer_all : ([`Wordsize], [`Endian], [`HasMapping]) t ->
184   ?start:addr -> addr -> addr list
185 (** Find all occurrences of a pointer in the memory map. *)
186
187 (** {2 Get bytes and ranges of bytes} *)
188
189 val get_byte : ('ws, 'e, [`HasMapping]) t -> addr -> int
190 (** Return the byte at the given address.
191
192     This will raise [Invalid_argument "get_byte"] if the address is
193     a hole (not mapped). *)
194
195 val get_bytes : ('ws, 'e, [`HasMapping]) t -> addr -> int -> string
196 (** Return the sequence of bytes starting at the given address.
197
198     This will raise [Invalid_argument "get_bytes"] if the address range
199     contains holes. *)
200
201 val get_int32 : ('ws, [`Endian], [`HasMapping]) t -> addr -> int32
202 (** Return the 32-bit int at [addr]. *)
203
204 val get_int64 : ('ws, [`Endian], [`HasMapping]) t -> addr -> int64
205 (** Return the 64-bit int at [addr]. *)
206
207 val get_C_int : ([`Wordsize], [`Endian], [`HasMapping]) t -> addr -> int32
208 (** Return the C 32-bit int at [addr]. *)
209
210 val get_C_long : ([`Wordsize], [`Endian], [`HasMapping]) t -> addr -> int64
211 (** Return the C 32 or 64-bit long at [addr]. *)
212
213 val get_string : ('ws, 'e, [`HasMapping]) t -> addr -> string
214 (** Return the sequence of bytes starting at [addr] up to (but not
215     including) the first ASCII NUL character.  In other words, this
216     returns a C-style string.
217
218     This may raise [Invalid_argument "get_string"] if we reach a
219     hole (unmapped address) before finding the end of the string.
220
221     See also {!get_bytes}, {!is_string} and {!is_C_identifier}. *)
222
223 val is_string : ('ws, 'e, [`HasMapping]) t -> addr -> bool
224 (** Return true or false if the address contains an ASCII NUL-terminated
225     string. *)
226
227 val is_C_identifier : ('ws, 'e, [`HasMapping]) t -> addr -> bool
228 (** Return true or false if the address contains a NUL-terminated
229     C identifier. *)
230
231 val is_mapped : ('ws, 'e, 'hm) t -> addr -> bool
232 (** Return true if the single address [addr] is mapped. *)
233
234 val is_mapped_range : ('ws, 'e, 'hm) t -> addr -> int -> bool
235 (** Return true if all addresses in the range [addr] to [addr+size-1]
236     are mapped. *)
237
238 val follow_pointer : ([`Wordsize], [`Endian], [`HasMapping]) t -> addr -> addr
239 (** Follow (dereference) the pointer at [addr] and return
240     the address pointed to. *)
241
242 val succ_long : ([`Wordsize], 'e, [`HasMapping]) t -> addr -> addr
243 (** Add wordsize bytes to [addr] and return it. *)
244
245 val pred_long : ([`Wordsize], 'e, [`HasMapping]) t -> addr -> addr
246 (** Subtract wordsize bytes from [addr] and return it. *)
247
248 val align : ([`Wordsize], 'e, [`HasMapping]) t -> addr -> addr
249 (** Align the [addr] to the next wordsize boundary.  If it already
250     aligned, this just returns [addr]. *)
251
252 (** {2 Save and load memory maps} *)
253
254 (*val to_channel : ('ws, 'e, [`HasMapping]) t -> out_channel -> unit*)
255 (** Write the memory map and data to the given output channel in
256     a reasonably efficient and stable binary format. *)
257
258 (*val from_channel : in_channel -> ('?, '?, [`HasMapping]) t*)
259 (** Read a previously saved memory map.  If the input channel does
260     not contain a memory map, this raises [Invalid_argument]. *)