Files
xen/tools/debugger/pdb/Util.ml
T

166 lines
4.8 KiB
OCaml

(** Util.ml
*
* various utility functions
*
* @author copyright (c) 2005 alex ho
* @see <www.cl.cam.ac.uk/netos/pdb> pervasive debugger
* @version 1
*)
let int_of_hexchar h =
let i = int_of_char h in
match h with
| '0' .. '9' -> i - (int_of_char '0')
| 'a' .. 'f' -> i - (int_of_char 'a') + 10
| 'A' .. 'F' -> i - (int_of_char 'A') + 10
| _ -> raise (Invalid_argument "unknown hex character")
let hexchar_of_int i =
let hexchars = [| '0'; '1'; '2'; '3'; '4'; '5'; '6'; '7';
'8'; '9'; 'a'; 'b'; 'c'; 'd'; 'e'; 'f' |]
in
hexchars.(i)
(** flip the bytes of a four byte int
*)
let flip_int num =
let a = num mod 256
and b = (num / 256) mod 256
and c = (num / (256 * 256)) mod 256
and d = (num / (256 * 256 * 256)) in
(a * 256 * 256 * 256) + (b * 256 * 256) + (c * 256) + d
let flip_int32 num =
let a = Int32.logand num 0xffl
and b = Int32.logand (Int32.shift_right_logical num 8) 0xffl
and c = Int32.logand (Int32.shift_right_logical num 16) 0xffl
and d = (Int32.shift_right_logical num 24) in
(Int32.logor
(Int32.logor (Int32.shift_left a 24) (Int32.shift_left b 16))
(Int32.logor (Int32.shift_left c 8) d))
let int_list_of_string_list list =
List.map (fun x -> int_of_string x) list
let int_list_of_string str len =
let array_of_string s =
let int_array = Array.make len 0 in
for loop = 0 to len - 1 do
int_array.(loop) <- (Char.code s.[loop]);
done;
int_array
in
Array.to_list (array_of_string str)
(* remove leading and trailing whitespace from a string *)
let chomp str =
let head = Str.regexp "^[ \t\r\n]+" in
let tail = Str.regexp "[ \t\r\n]+$" in
let str = Str.global_replace head "" str in
Str.global_replace tail "" str
(* Stupid little parser for "<key>=<value>[,<key>=<value>]*"
It first chops the entire command at each ',', so no ',' in key or value!
Mucked to return a list of words for "value"
*)
let list_of_string str =
let delim c = Str.regexp ("[ \t]*" ^ c ^ "[ \t]*") in
let str_list = Str.split (delim " ") str in
List.map (fun x -> chomp(x)) str_list
let little_parser fn str =
let delim c = Str.regexp ("[ \t]*" ^ c ^ "[ \t]*") in
let str_list = Str.split (delim ",") str in
let pair s =
match Str.split (delim "=") s with
| [key;value] -> fn (chomp key) (list_of_string value)
| [key] -> fn (chomp key) []
| _ -> failwith (Printf.sprintf "error: (little_parser) parse error [%s]" str)
in
List.iter pair str_list
(* boolean list membership test *)
let not_list_member the_list element =
try
List.find (fun x -> x = element) the_list;
false
with
Not_found -> true
(* a very inefficient way to remove the elements of one list from another *)
let list_remove the_list remove_list =
List.filter (not_list_member remove_list) the_list
(* get a description of a file descriptor *)
let get_connection_info fd =
let get_local_info fd =
let sockname = Unix.getsockname fd in
match sockname with
| Unix.ADDR_UNIX(s) -> "unix"
| Unix.ADDR_INET(a,p) -> ((Unix.string_of_inet_addr a) ^ ":" ^
(string_of_int p))
and get_remote_info fd =
let sockname = Unix.getpeername fd in
match sockname with
| Unix.ADDR_UNIX(s) -> s
| Unix.ADDR_INET(a,p) -> ((Unix.string_of_inet_addr a) ^ ":" ^
(string_of_int p))
in
try
get_remote_info fd
with
| Unix.Unix_error (Unix.ENOTSOCK, s1, s2) ->
let s = Unix.fstat fd in
Printf.sprintf "dev: %d, inode: %d" s.Unix.st_dev s.Unix.st_ino
| Unix.Unix_error (Unix.EBADF, s1, s2) ->
let s = Unix.fstat fd in
Printf.sprintf "dev: %d, inode: %d" s.Unix.st_dev s.Unix.st_ino
| _ -> get_local_info fd
(* really write a string *)
let really_write fd str =
let strlen = String.length str in
let sent = ref 0 in
while (!sent < strlen) do
sent := !sent + (Unix.write fd str !sent (strlen - !sent))
done
let write_character fd ch =
let str = String.create 1 in
str.[0] <- ch;
really_write fd str
let send_reply fd reply =
let checksum = ref 0 in
write_character fd '$';
for loop = 0 to (String.length reply) - 1 do
write_character fd reply.[loop];
checksum := !checksum + int_of_char reply.[loop]
done;
write_character fd '#';
write_character fd (hexchar_of_int ((!checksum mod 256) / 16));
write_character fd (hexchar_of_int ((!checksum mod 256) mod 16))
(*
* BUG NEED TO LISTEN FOR REPLY +/- AND POSSIBLY RE-TRANSMIT
*)
(** A few debugger commands such as step 's' and continue 'c' do
* not immediately return a response to the debugger. In these
* cases we raise No_reply instead.
* This is also used by some contexts (such as Linux processes)
* which utilize an asynchronous request / response protocol when
* communicating with their respective backends.
*)
exception No_reply