aboutsummaryrefslogtreecommitdiffstats
path: root/debug
diff options
context:
space:
mode:
authorBernhard Schommer <bschommer@users.noreply.github.com>2015-09-30 12:45:40 +0200
committerBernhard Schommer <bschommer@users.noreply.github.com>2015-09-30 12:45:40 +0200
commite443d76ad1ee0182353404317ab45c26227a59ea (patch)
tree1c110864431d8f6ba06c8746233397a3e221560e /debug
parentc212ab7a8adea516db72f17d818393629dbde1b3 (diff)
parentee76d81e0e7d8a76cd31bf0d01a532d248dca45a (diff)
downloadcompcert-e443d76ad1ee0182353404317ab45c26227a59ea.tar.gz
compcert-e443d76ad1ee0182353404317ab45c26227a59ea.zip
Merge pull request #56 from AbsInt/debug_locations
Debug locations
Diffstat (limited to 'debug')
-rw-r--r--debug/CtoDwarf.ml543
-rw-r--r--debug/Debug.ml108
-rw-r--r--debug/Debug.mli78
-rw-r--r--debug/DebugInformation.ml821
-rw-r--r--debug/DebugInit.ml80
-rw-r--r--debug/DwarfPrinter.ml192
-rw-r--r--debug/DwarfPrinter.mli4
-rw-r--r--debug/DwarfTypes.mli93
-rw-r--r--debug/DwarfUtil.ml105
-rw-r--r--debug/Dwarfgen.ml444
10 files changed, 1766 insertions, 702 deletions
diff --git a/debug/CtoDwarf.ml b/debug/CtoDwarf.ml
deleted file mode 100644
index c2085eb0..00000000
--- a/debug/CtoDwarf.ml
+++ /dev/null
@@ -1,543 +0,0 @@
-(* *********************************************************************)
-(* *)
-(* The Compcert verified compiler *)
-(* *)
-(* Bernhard Schommer, AbsInt Angewandte Informatik GmbH *)
-(* *)
-(* AbsInt Angewandte Informatik GmbH. All rights reserved. This file *)
-(* is distributed under the terms of the INRIA Non-Commercial *)
-(* License Agreement. *)
-(* *)
-(* *********************************************************************)
-
-open Builtins
-open C
-open Cprint
-open Cutil
-open C2C
-open DwarfTypes
-open DwarfUtil
-open Env
-open Set
-
-(* Functions to translate a C Ast into Dwarf 2 debugging information *)
-
-
-(* Hashtable from type name to entry id *)
-let type_table: (string, int) Hashtbl.t = Hashtbl.create 7
-
-(* Hashtable for typedefname to entry id *)
-let typedef_table: (string, int) Hashtbl.t = Hashtbl.create 7
-
-(* Hashtable from composite table to entry id *)
-let composite_types_table: (int, int) Hashtbl.t = Hashtbl.create 7
-
-(* Hashtable from id of a defined composite types to minimal type info *)
-let composite_declarations: (int, (struct_or_union * string * location)) Hashtbl.t = Hashtbl.create 7
-
-module IntSet = Set.Make(struct type t = int let compare = compare end)
-
-(* Set of all declared composite_types *)
-let composite_defined: IntSet.t ref = ref IntSet.empty
-
-(* Get the type id of a composite_type *)
-let get_composite_type (name: int): int =
- try
- Hashtbl.find composite_types_table name
- with Not_found ->
- let id = next_id () in
- Hashtbl.add composite_types_table name id;
- id
-
-(* Translate a C.typ to a string needed for hashing *)
-let typ_to_string (ty: typ) =
- let buf = Buffer.create 7 in
- let chan = Format.formatter_of_buffer buf in
- typ chan ty;
- Format.pp_print_flush chan ();
- Buffer.contents buf
-
-let rec mmap f env = function
- | [] -> ([],env)
- | hd :: tl ->
- let (hd',env1) = f env hd in
- let (tl', env2) = mmap f env1 tl in
- (hd' :: tl', env2)
-
-
-(* Helper functions for the attributes *)
-
-let strip_attributes typ =
- let strip = List.filter (fun a -> a = AConst || a = AVolatile) in
- match typ with
- | TVoid at -> TVoid (strip at)
- | TInt (k,at) -> TInt (k,strip at)
- | TFloat (k,at) -> TFloat(k,strip at)
- | TPtr (t,at) -> TPtr(t,strip at)
- | TArray (t,s,at) -> TArray(t,s,strip at)
- | TFun (t,arg,v,at) -> TFun(t,arg,v,strip at)
- | TNamed (n,at) -> TNamed(n,strip at)
- | TStruct (n,at) -> TStruct(n,strip at)
- | TUnion (n,at) -> TUnion(n,strip at)
- | TEnum (n,at) -> TEnum(n,strip at)
-
-
-let strip_last_attribute typ =
- let rec hd_opt l = match l with
- [] -> None,[]
- | AConst::rest -> Some AConst,rest
- | AVolatile::rest -> Some AVolatile,rest
- | _::rest -> hd_opt rest in
- match typ with
- | TVoid at -> let l,r = hd_opt at in
- l,TVoid r
- | TInt (k,at) -> let l,r = hd_opt at in
- l,TInt (k,r)
- | TFloat (k,at) -> let l,r = hd_opt at in
- l,TFloat (k,r)
- | TPtr (t,at) -> let l,r = hd_opt at in
- l,TPtr(t,r)
- | TArray (t,s,at) -> let l,r = hd_opt at in
- l,TArray(t,s,r)
- | TFun (t,arg,v,at) -> let l,r = hd_opt at in
- l,TFun(t,arg,v,r)
- | TNamed (n,at) -> let l,r = hd_opt at in
- l,TNamed(n,r)
- | TStruct (n,at) -> let l,r = hd_opt at in
- l,TStruct(n,r)
- | TUnion (n,at) -> let l,r = hd_opt at in
- l,TUnion(n,r)
- | TEnum (n,at) -> let l,r = hd_opt at in
- l,TEnum(n,r)
-
-(* Dwarf tag for the void type*)
-let rec void_dwarf_tag =
- let void = {
- base_type_byte_size = 0;
- base_type_encoding = None;
- base_type_name = "void";
- } in
- DW_TAG_base_type void
-
-(* Generate a dwarf tag for the given integer type *)
-and int_to_dwarf_tag k =
- let encoding =
- (match k with
- | IBool -> DW_ATE_boolean
- | IChar ->
- if !Machine.config.Machine.char_signed then
- DW_ATE_signed_char
- else
- DW_ATE_unsigned_char
- | ILong | ILongLong | IShort | ISChar -> DW_ATE_signed_char
- | _ -> DW_ATE_unsigned)in
- let int = {
- base_type_byte_size = sizeof_ikind k;
- base_type_encoding = Some encoding;
- base_type_name = typ_to_string (TInt (k,[]));} in
- DW_TAG_base_type int
-
-(* Generate a dwarf tag for the given floating point type *)
-and float_to_dwarf_tag k =
- let byte_size = sizeof_fkind k in
- let float = {
- base_type_byte_size = byte_size;
- base_type_encoding = Some DW_ATE_float;
- base_type_name = typ_to_string (TFloat (k,[]));
- } in
- DW_TAG_base_type float
-
-(* Generate a dwarf tag for the given function type *)
-and fun_to_dwarf_tag rt args =
- let ret,et = (match rt with
- | TVoid _ -> None,[]
- | _ -> let ret,et = type_to_dwarf rt in
- Some ret,et) in
- let prototyped,children,others =
- (match args with
- | None ->
- let u = {
- unspecified_parameter_file_loc = None;
- unspecified_parameter_artificial = None;
- } in
- let u = new_entry (DW_TAG_unspecified_parameter u) in
- false,[u],[]
- | Some [] -> true,[],[]
- | Some l ->
- let c,e = mmap (fun acc (_,t) ->
- let t,e = type_to_dwarf t in
- let fp =
- {
- formal_parameter_file_loc = None;
- formal_parameter_artificial = None;
- formal_parameter_location = None;
- formal_parameter_name = None;
- formal_parameter_segment = None;
- formal_parameter_type = t;
- formal_parameter_variable_parameter = None;
- } in
- let entry = new_entry (DW_TAG_formal_parameter fp) in
- entry,(e@acc)) [] l in
- true,c,e) in
- let s = {
- subroutine_type = ret;
- subroutine_prototyped = prototyped;
- } in
- let s = new_entry (DW_TAG_subroutine_type s) in
- let s = add_children s children in
- s.id,((s::others)@et)
-
-(* Generate a dwarf tag for the given array type *)
-and array_to_dwarf_tag child size =
- let append_opt a b =
- match a with
- | None -> b
- | Some a -> a::b in
- let size_to_subrange s =
- match s with
- | None -> None
- | Some i ->
- let i = Int64.to_int (Int64.sub i Int64.one) in
- let s =
- {
- subrange_type = None;
- subrange_upper_bound = Some (BoundConst i);
- } in
- Some (new_entry (DW_TAG_subrange_type s)) in
- let rec aux t =
- (match t with
- | TArray (child,size,_) ->
- let sub = size_to_subrange size in
- let t,c,e = aux child in
- t,append_opt sub c,e
- | _ -> let t,e = type_to_dwarf t in
- t,[],e) in
- let t,children,e = aux child in
- let sub = size_to_subrange size in
- let children = List.rev (append_opt sub children) in
- let arr = {
- array_type_file_loc = None;
- array_type = t;
- } in
- let arr = new_entry (DW_TAG_array_type arr) in
- let arr = add_children arr children in
- arr.id,(arr::e)
-
-(* Translate a typ without attributes to a dwarf_tag *)
-and type_to_dwarf_entry typ typ_string=
- let id,entries =
- (match typ with
- | TVoid _ ->
- let e = new_entry void_dwarf_tag in
- e.id,[e]
- | TInt (k,_) ->
- let e = new_entry (int_to_dwarf_tag k) in
- e.id,[e]
- | TFloat (k,_) ->
- let e = new_entry (float_to_dwarf_tag k) in
- e.id,[e]
- | TPtr (t,_) ->
- let t,e = type_to_dwarf t in
- let pointer = {pointer_type = t;} in
- let t = new_entry (DW_TAG_pointer_type pointer) in
- t.id,t::e
- | TFun (rt,args,_,_) -> fun_to_dwarf_tag rt args
- | TStruct (i,_)
- | TUnion (i,_)
- | TEnum (i,_) ->
- let t = get_composite_type i.stamp in
- t,[]
- | TNamed (i,at) ->
- let t = Hashtbl.find typedef_table i.name in
- t,[]
- | TArray (child,size,_) -> array_to_dwarf_tag child size)
- in
- Hashtbl.add type_table typ_string id;
- id,entries
-
-(* Tranlate type with attributes to their corresponding dwarf represenation *)
-and attr_type_to_dwarf typ typ_string =
- let l,t = strip_last_attribute typ in
- match l with
- | Some AConst -> let id,t = type_to_dwarf t in
- let const_tag = DW_TAG_const_type ({const_type = id;}) in
- let const_entry = new_entry const_tag in
- let id = const_entry.id in
- Hashtbl.add type_table typ_string id;
- id,const_entry::t
- | Some AVolatile -> let id,t = type_to_dwarf t in
- let volatile_tag = DW_TAG_volatile_type ({volatile_type = id;}) in
- let volatile_entry = new_entry volatile_tag in
- let id = volatile_entry.id in
- Hashtbl.add type_table typ_string id;
- id,volatile_entry::t
- | Some (ARestrict|AAlignas _| Attr(_,_)) -> type_to_dwarf t (* This should not happen *)
- | None -> type_to_dwarf_entry typ typ_string
-
-(* Translate a given type to its dwarf representation *)
-and type_to_dwarf (typ: typ): int * dw_entry list =
- match typ with
- | TStruct (i,_)
- | TUnion (i,_)
- | TEnum (i,_) ->
- let t = get_composite_type i.stamp in
- t,[]
- | _ ->
- let typ = strip_attributes typ in
- let typ_string = typ_to_string typ in
- try
- Hashtbl.find type_table typ_string,[]
- with Not_found ->
- attr_type_to_dwarf typ typ_string
-
-(* Translate a typedef to its corresponding dwarf representation *)
-let typedef_to_dwarf gloc (name,t) =
- let i,t = type_to_dwarf t in
- let td = {
- typedef_file_loc = gloc;
- typedef_name = name;
- typedef_type = i;
- } in
- let td = new_entry (DW_TAG_typedef td) in
- Hashtbl.add typedef_table name td.id;
- td::t
-
-(* Translate a global var to its corresponding dwarf representation *)
-let glob_var_to_dwarf (s,n,t,_) gloc =
- let i,t = type_to_dwarf t in
- let ext = (match s with
- | Storage_static -> false
- | _ -> true) in
- let decl = {
- variable_file_loc = (Some gloc);
- variable_declaration = None;
- variable_external = Some ext;
- variable_location = None;
- variable_name = n.name;
- variable_segment = None;
- variable_type = i;
- } in
- let decl = new_entry (DW_TAG_variable decl) in
- t,decl
-
-(* Translate a function definition to its corresponding dwarf representation *)
-let fundef_to_dwarf f gloc =
- let ret,e = (match f.fd_ret with
- | TVoid _ -> None,[]
- | _ -> let i,t = type_to_dwarf f.fd_ret in
- Some i,t) in
- let ext = (match f.fd_storage with
- | Storage_static -> false
- | _ -> true) in
- let fdef = {
- subprogram_file_loc = (Some gloc);
- subprogram_external = Some ext;
- subprogram_frame_base = None;
- subprogram_name = f.fd_name.name;
- subprogram_prototyped = true;
- subprogram_type = ret;
- } in
- let fp,e = mmap (fun acc (p,t) ->
- let t,e = type_to_dwarf t in
- let fp =
- {
- formal_parameter_file_loc = None;
- formal_parameter_artificial = None;
- formal_parameter_location = None;
- formal_parameter_name = (Some p.name);
- formal_parameter_segment = None;
- formal_parameter_type = t;
- formal_parameter_variable_parameter = None;
- } in
- let entry = new_entry (DW_TAG_formal_parameter fp) in
- entry,(e@acc)) e f.fd_params in
- let fdef = new_entry (DW_TAG_subprogram fdef) in
- let fdef = add_children fdef fp in
- e,fdef
-
-(* Translate a enum definition to its corresponding dwarf representation *)
-let enum_to_dwarf (n,at,e) gloc =
- let enumerator_to_dwarf (i,c,_)=
- let tag =
- {
- enumerator_file_loc = None;
- enumerator_value = Int64.to_int c;
- enumerator_name = i.name;
- } in
- new_entry (DW_TAG_enumerator tag) in
- let bs = sizeof_ikind enum_ikind in
- let enum = {
- enumeration_file_loc = Some gloc;
- enumeration_byte_size = bs;
- enumeration_declaration = None;
- enumeration_name = if n.name <> "" then Some n.name else None;
- } in
- let id = get_composite_type n.stamp in
- let child = List.map enumerator_to_dwarf e in
- let enum =
- {
- tag = DW_TAG_enumeration_type enum;
- children = child;
- id = id;
- } in
- [enum]
-
-(* Translate a struct definition to its corresponding dwarf representation *)
-let struct_to_dwarf (n,at,m) env gloc =
- let info = Env.find_struct env n in
- let tag =DW_TAG_structure_type {
- structure_file_loc = Some gloc;
- structure_byte_size = info.ci_sizeof;
- structure_declaration = None;
- structure_name = if n.name <> "" then Some n.name else None;
- } in
- let id = get_composite_type n.stamp in
- let rec pack acc bcc l m =
- match m with
- | [] -> acc,bcc,[]
- | m::ms as ml ->
- (match m.fld_bitfield with
- | None -> acc,bcc,ml
- | Some n ->
- if n = 0 then
- acc,bcc,ms (* bit width 0 means end of pack *)
- else if l + n > 8 * !Machine.config.Machine.sizeof_int then
- acc,bcc,ml (* doesn't fit in current word *)
- else
- let t,e = type_to_dwarf m.fld_typ in
- let um = {
- member_file_loc = None;
- member_byte_size = Some !Machine.config.Machine.sizeof_int;
- member_bit_offset = Some l;
- member_bit_size = Some n;
- member_data_member_location = None;
- member_declaration = None;
- member_name = if m.fld_name <> "" then Some m.fld_name else None;
- member_type = t;
- } in
- pack ((new_entry (DW_TAG_member um))::acc) (e@bcc) (l + n) ms)
- and translate acc bcc m =
- match m with
- [] -> acc,bcc
- | m::ms as ml ->
- (match m.fld_bitfield with
- | None ->
- let t,e = type_to_dwarf m.fld_typ in
- let um = {
- member_file_loc = None;
- member_byte_size = None;
- member_bit_offset = None;
- member_bit_size = None;
- member_data_member_location = None;
- member_declaration = None;
- member_name = if m.fld_name <> "" then Some m.fld_name else None;
- member_type = t;
- } in
- translate ((new_entry (DW_TAG_member um))::acc) (e@bcc) ms
- | Some _ -> let acc,bcc,rest = pack acc bcc 0 ml in
- translate acc bcc rest)
- in
- let children,e = translate [] [] m in
- let children,e = List.rev children,e in
- let sou = {
- tag = tag;
- children = children;
- id = id;} in
- e@[sou]
-
-(* Translate a union definition to its corresponding dwarf representation *)
-let union_to_dwarf (n,at,m) env gloc =
- let info = Env.find_union env n in
- let tag = DW_TAG_union_type {
- union_file_loc = Some gloc;
- union_byte_size = info.ci_sizeof;
- union_declaration = None;
- union_name = if n.name <> "" then Some n.name else None;
- } in
- let id = get_composite_type n.stamp in
- let children,e = mmap
- (fun acc f ->
- let t,e = type_to_dwarf f.fld_typ in
- let um = {
- member_file_loc = None;
- member_byte_size = None;
- member_bit_offset = None;
- member_bit_size = None;
- member_data_member_location = None;
- member_declaration = None;
- member_name = if f.fld_name <> "" then Some f.fld_name else None;
- member_type = t;
- } in
- new_entry (DW_TAG_member um),e@acc)[] m in
- let sou = {
- tag = tag;
- children = children;
- id = id;} in
- e@[sou]
-
-(* Translate global declarations to there dwarf representation *)
-let globdecl_to_dwarf env (typs,decls) decl =
- PrintAsmaux.add_file (fst decl.gloc);
- match decl.gdesc with
- | Gtypedef (n,t) -> let ret = typedef_to_dwarf (Some decl.gloc) (n.name,t) in
- typs@ret,decls
- | Gdecl d -> let t,d = glob_var_to_dwarf d decl.gloc in
- typs@t,d::decls
- | Gfundef f -> let t,d = fundef_to_dwarf f decl.gloc in
- typs@t,d::decls
- | Genumdef (n,at,e) ->
- composite_defined:= IntSet.add n.stamp !composite_defined;
- let ret = enum_to_dwarf (n,at,e) decl.gloc in
- typs@ret,decls
- | Gcompositedef (Struct,n,at,m) ->
- composite_defined:= IntSet.add n.stamp !composite_defined;
- let ret = struct_to_dwarf (n,at,m) env decl.gloc in
- typs@ret,decls
- | Gcompositedef (Union,n,at,m) ->
- composite_defined:= IntSet.add n.stamp !composite_defined;
- let ret = union_to_dwarf (n,at,m) env decl.gloc in
- typs@ret,decls
- | Gcompositedecl (sou,i,_) -> Hashtbl.add composite_declarations i.stamp (sou,i.name,decl.gloc);
- typs,decls
- | Gpragma _ -> typs,decls
-
-let forward_declaration_to_dwarf sou name loc stamp =
- let id = get_composite_type stamp in
- let tag = match sou with
- | Struct ->
- DW_TAG_structure_type{
- structure_file_loc = Some loc;
- structure_byte_size = None;
- structure_declaration = Some true;
- structure_name = if name <> "" then Some name else None;
- }
- | Union ->
- DW_TAG_union_type {
- union_file_loc = Some loc;
- union_byte_size = None;
- union_declaration = Some true;
- union_name = if name <> "" then Some name else None;
- } in
- {tag = tag; children = []; id = id}
-
-
-(* Compute the dwarf representations of global declarations. The second program argument is the
- program after the bitfield and packed struct transformation *)
-let program_to_dwarf prog prog1 name =
- Hashtbl.reset type_table;
- Hashtbl.reset composite_types_table;
- Hashtbl.reset typedef_table;
- let prog = cleanupGlobals (prog) in
- let env = translEnv Env.empty prog1 in
- reset_id ();
- let typs = List.map (typedef_to_dwarf None) C2C.builtins.typedefs in
- let typs = List.concat typs in
- let typs,defs = List.fold_left (globdecl_to_dwarf env) (typs,[]) prog in
- let typs = Hashtbl.fold (fun i (sou,name,loc) typs -> if not (IntSet.mem i !composite_defined) then
- (forward_declaration_to_dwarf sou name loc i)::typs else typs) composite_declarations typs in
- let defs = typs @ defs in
- let cp = {
- compile_unit_name = name;
- } in
- let cp = new_entry (DW_TAG_compile_unit cp) in
- add_children cp defs
diff --git a/debug/Debug.ml b/debug/Debug.ml
new file mode 100644
index 00000000..1d3b260e
--- /dev/null
+++ b/debug/Debug.ml
@@ -0,0 +1,108 @@
+(* *********************************************************************)
+(* *)
+(* The Compcert verified compiler *)
+(* *)
+(* Bernhard Schommer, AbsInt Angewandte Informatik GmbH *)
+(* *)
+(* AbsInt Angewandte Informatik GmbH. All rights reserved. This file *)
+(* is distributed under the terms of the INRIA Non-Commercial *)
+(* License Agreement. *)
+(* *)
+(* *********************************************************************)
+
+open AST
+open BinNums
+open C
+open Camlcoq
+open Dwarfgen
+open DwarfTypes
+
+(* Interface for generating and printing debug information *)
+
+(* Record used for stroring references to the actual implementation functions *)
+type implem =
+ {
+ mutable init: string -> unit;
+ mutable atom_function: ident -> atom -> unit;
+ mutable atom_global_variable: ident -> atom -> unit;
+ mutable set_composite_size: ident -> struct_or_union -> int option -> unit;
+ mutable set_member_offset: ident -> string -> int -> unit;
+ mutable set_bitfield_offset: ident -> string -> int -> string -> int -> unit;
+ mutable insert_global_declaration: Env.t -> globdecl -> unit;
+ mutable add_fun_addr: atom -> (int * int) -> unit;
+ mutable generate_debug_info: (atom -> string) -> string -> debug_entries option;
+ mutable all_files_iter: (string -> unit) -> unit;
+ mutable insert_local_declaration: storage -> ident -> typ -> location -> unit;
+ mutable atom_local_variable: ident -> atom -> unit;
+ mutable enter_scope: int -> int -> int -> unit;
+ mutable enter_function_scope: int -> int -> unit;
+ mutable add_lvar_scope: int -> ident -> int -> unit;
+ mutable open_scope: atom -> int -> positive -> unit;
+ mutable close_scope: atom -> int -> positive -> unit;
+ mutable start_live_range: atom -> positive -> int * int builtin_arg -> unit;
+ mutable end_live_range: atom -> positive -> unit;
+ mutable stack_variable: atom -> int * int builtin_arg -> unit;
+ mutable function_end: atom -> positive -> unit;
+ mutable add_label: atom -> positive -> int -> unit;
+ mutable atom_parameter: ident -> ident -> atom -> unit;
+ mutable add_compilation_section_start: string ->(int * int * int * string) -> unit;
+ mutable compute_file_enum: (string -> int) -> (string-> int) -> (unit -> unit) -> unit;
+ mutable exists_section: string -> bool;
+ }
+
+let implem =
+ {
+ init = (fun _ -> ());
+ atom_function = (fun _ _ -> ());
+ atom_global_variable = (fun _ _ -> ());
+ set_composite_size = (fun _ _ _ -> ());
+ set_member_offset = (fun _ _ _ -> ());
+ set_bitfield_offset = (fun _ _ _ _ _ -> ());
+ insert_global_declaration = (fun _ _ -> ());
+ add_fun_addr = (fun _ _ -> ());
+ generate_debug_info = (fun _ _ -> None);
+ all_files_iter = (fun _ -> ());
+ insert_local_declaration = (fun _ _ _ _ -> ());
+ atom_local_variable = (fun _ _ -> ());
+ enter_scope = (fun _ _ _ -> ());
+ enter_function_scope = (fun _ _ -> ());
+ add_lvar_scope = (fun _ _ _ -> ());
+ open_scope = (fun _ _ _ -> ());
+ close_scope = (fun _ _ _ -> ());
+ start_live_range = (fun _ _ _ -> ());
+ end_live_range = (fun _ _ -> ());
+ stack_variable = (fun _ _ -> ());
+ function_end = (fun _ _ -> ());
+ add_label = (fun _ _ _ -> ());
+ atom_parameter = (fun _ _ _ -> ());
+ add_compilation_section_start = (fun _ _ -> ());
+ compute_file_enum = (fun _ _ _ -> ());
+ exists_section = (fun _ -> true);
+}
+
+let init_compile_unit name = implem.init name
+let atom_function id atom = implem.atom_function id atom
+let atom_global_variable id atom = implem.atom_global_variable id atom
+let set_composite_size id sou size = implem.set_composite_size id sou size
+let set_member_offset id field off = implem.set_member_offset id field off
+let set_bitfield_offset id field off underlying size = implem.set_bitfield_offset id field off underlying size
+let insert_global_declaration env dec = implem.insert_global_declaration env dec
+let add_fun_addr atom addr = implem.add_fun_addr atom addr
+let generate_debug_info fun_s var_s = implem.generate_debug_info fun_s var_s
+let all_files_iter f = implem.all_files_iter f
+let insert_local_declaration sto id ty loc = implem.insert_local_declaration sto id ty loc
+let atom_local_variable id atom = implem.atom_local_variable id atom
+let enter_scope p_id id = implem.enter_scope p_id id
+let enter_function_scope fun_id sc_id = implem.enter_function_scope fun_id sc_id
+let add_lvar_scope fun_id var_id s_id = implem.add_lvar_scope fun_id var_id s_id
+let open_scope atom id lbl = implem.open_scope atom id lbl
+let close_scope atom id lbl = implem.close_scope atom id lbl
+let start_live_range atom lbl loc = implem.start_live_range atom lbl loc
+let end_live_range atom lbl = implem.end_live_range atom lbl
+let stack_variable atom loc = implem.stack_variable atom loc
+let function_end atom loc = implem.function_end atom loc
+let add_label atom p lbl = implem.add_label atom p lbl
+let atom_parameter fid pid atom = implem.atom_parameter fid pid atom
+let add_compilation_section_start sec addr = implem.add_compilation_section_start sec addr
+let exists_section sec = implem.exists_section sec
+let compute_file_enum end_l entry_l line_e = implem.compute_file_enum end_l entry_l line_e
diff --git a/debug/Debug.mli b/debug/Debug.mli
new file mode 100644
index 00000000..166a6759
--- /dev/null
+++ b/debug/Debug.mli
@@ -0,0 +1,78 @@
+(* *********************************************************************)
+(* *)
+(* The Compcert verified compiler *)
+(* *)
+(* Bernhard Schommer, AbsInt Angewandte Informatik GmbH *)
+(* *)
+(* AbsInt Angewandte Informatik GmbH. All rights reserved. This file *)
+(* is distributed under the terms of the INRIA Non-Commercial *)
+(* License Agreement. *)
+(* *)
+(* *********************************************************************)
+
+open AST
+open C
+open Camlcoq
+open DwarfTypes
+open BinNums
+
+
+(* Record used for stroring references to the actual implementation functions *)
+type implem =
+ {
+ mutable init: string -> unit;
+ mutable atom_function: ident -> atom -> unit;
+ mutable atom_global_variable: ident -> atom -> unit;
+ mutable set_composite_size: ident -> struct_or_union -> int option -> unit;
+ mutable set_member_offset: ident -> string -> int -> unit;
+ mutable set_bitfield_offset: ident -> string -> int -> string -> int -> unit;
+ mutable insert_global_declaration: Env.t -> globdecl -> unit;
+ mutable add_fun_addr: atom -> (int * int) -> unit;
+ mutable generate_debug_info: (atom -> string) -> string -> debug_entries option;
+ mutable all_files_iter: (string -> unit) -> unit;
+ mutable insert_local_declaration: storage -> ident -> typ -> location -> unit;
+ mutable atom_local_variable: ident -> atom -> unit;
+ mutable enter_scope: int -> int -> int -> unit;
+ mutable enter_function_scope: int -> int -> unit;
+ mutable add_lvar_scope: int -> ident -> int -> unit;
+ mutable open_scope: atom -> int -> positive -> unit;
+ mutable close_scope: atom -> int -> positive -> unit;
+ mutable start_live_range: atom -> positive -> int * int builtin_arg -> unit;
+ mutable end_live_range: atom -> positive -> unit;
+ mutable stack_variable: atom -> int * int builtin_arg -> unit;
+ mutable function_end: atom -> positive -> unit;
+ mutable add_label: atom -> positive -> int -> unit;
+ mutable atom_parameter: ident -> ident -> atom -> unit;
+ mutable add_compilation_section_start: string -> (int * int * int * string) -> unit;
+ mutable compute_file_enum: (string -> int) -> (string-> int) -> (unit -> unit) -> unit;
+ mutable exists_section: string -> bool;
+ }
+
+val implem: implem
+
+val init_compile_unit: string -> unit
+val atom_function: ident -> atom -> unit
+val atom_global_variable: ident -> atom -> unit
+val set_composite_size: ident -> struct_or_union -> int option -> unit
+val set_member_offset: ident -> string -> int -> unit
+val set_bitfield_offset: ident -> string -> int -> string -> int -> unit
+val insert_global_declaration: Env.t -> globdecl -> unit
+val add_fun_addr: atom -> (int * int) -> unit
+val all_files_iter: (string -> unit) -> unit
+val insert_local_declaration: storage -> ident -> typ -> location -> unit
+val atom_local_variable: ident -> atom -> unit
+val enter_scope: int -> int -> int -> unit
+val enter_function_scope: int -> int -> unit
+val add_lvar_scope: int -> ident -> int -> unit
+val open_scope: atom -> int -> positive -> unit
+val close_scope: atom -> int -> positive -> unit
+val start_live_range: atom -> positive -> (int * int builtin_arg) -> unit
+val end_live_range: atom -> positive -> unit
+val stack_variable: atom -> int * int builtin_arg -> unit
+val function_end: atom -> positive -> unit
+val add_label: atom -> positive -> int -> unit
+val generate_debug_info: (atom -> string) -> string -> debug_entries option
+val atom_parameter: ident -> ident -> atom -> unit
+val add_compilation_section_start: string -> (int * int * int * string) -> unit
+val compute_file_enum: (string -> int) -> (string-> int) -> (unit -> unit) -> unit
+val exists_section: string -> bool
diff --git a/debug/DebugInformation.ml b/debug/DebugInformation.ml
new file mode 100644
index 00000000..382845a4
--- /dev/null
+++ b/debug/DebugInformation.ml
@@ -0,0 +1,821 @@
+(* *********************************************************************)
+(* *)
+(* The Compcert verified compiler *)
+(* *)
+(* Bernhard Schommer, AbsInt Angewandte Informatik GmbH *)
+(* *)
+(* AbsInt Angewandte Informatik GmbH. All rights reserved. This file *)
+(* is distributed under the terms of the INRIA Non-Commercial *)
+(* License Agreement. *)
+(* *)
+(* *********************************************************************)
+
+open AST
+open BinNums
+open C
+open Camlcoq
+open Cutil
+
+(* This implements an interface for the collection of debugging
+ information. *)
+
+(* Simple id generator *)
+let id = ref 0
+
+let next_id () =
+ let nid = !id in
+ incr id; nid
+
+let reset_id () =
+ id := 0
+
+(* Auximilary functions *)
+let list_replace c f l =
+ List.map (fun a -> if c a then f a else a) l
+
+(* The name of the current compilation unit *)
+let file_name: string ref = ref ""
+
+(** All files used in the debug entries *)
+module StringSet = Set.Make(String)
+let all_files : StringSet.t ref = ref StringSet.empty
+let add_file file =
+ all_files := StringSet.add file !all_files
+
+(* Types for the information of type info *)
+type composite_field =
+ {
+ cfd_name: string;
+ cfd_typ: int;
+ cfd_bit_size: int option;
+ cfd_bit_offset: int option;
+ cfd_byte_offset: int option;
+ cfd_byte_size: int option;
+ cfd_bitfield: string option;
+ }
+
+type composite_type =
+ {
+ ct_name: string;
+ ct_sou: struct_or_union;
+ ct_file_loc: location option;
+ ct_members: composite_field list;
+ ct_sizeof: int option;
+ ct_declaration: bool;
+ }
+
+type ptr_type = {
+ pts: int
+ }
+
+type const_type = {
+ cst_type: int
+ }
+
+type volatile_type = {
+ vol_type: int
+ }
+
+
+type array_type = {
+ arr_type: int;
+ arr_size: int64 option list;
+ }
+
+type typedef = {
+ typedef_file_loc: location option;
+ typedef_name: string;
+ typ: int option;
+ }
+
+type enumerator = {
+ enumerator_name: string;
+ enumerator_const: int64;
+ }
+
+type enum_type = {
+ enum_name: string;
+ enum_byte_size: int option;
+ enum_file_loc: location option;
+ enum_enumerators: enumerator list;
+ }
+
+type int_type = {
+ int_kind: ikind;
+ }
+
+type float_type = {
+ float_kind: fkind;
+ }
+
+type parameter_type = {
+ param_type: int;
+ param_name: string;
+ }
+
+type function_type = {
+ fun_return_type: int option;
+ fun_prototyped: bool;
+ fun_params: parameter_type list;
+ }
+
+type debug_types =
+ | IntegerType of int_type
+ | FloatType of float_type
+ | PointerType of ptr_type
+ | ArrayType of array_type
+ | CompositeType of composite_type
+ | EnumType of enum_type
+ | FunctionType of function_type
+ | Typedef of typedef
+ | ConstType of const_type
+ | VolatileType of volatile_type
+ | Void
+
+(* All types encountered *)
+let types: (int,debug_types) Hashtbl.t = Hashtbl.create 7
+
+(* Lookup table for types *)
+let lookup_types: (string, int) Hashtbl.t = Hashtbl.create 7
+
+(* Translate a C.typ to a string needed for hashing *)
+let typ_to_string (ty: typ) =
+ let buf = Buffer.create 7 in
+ let chan = Format.formatter_of_buffer buf in
+ Cprint.print_debug_idents := true;
+ Cprint.typ chan ty;
+ Cprint.print_debug_idents := false;
+ Format.pp_print_flush chan ();
+ Buffer.contents buf
+
+(* Helper functions for the attributes *)
+let strip_attributes typ =
+ let strip = List.filter (fun a -> a = AConst || a = AVolatile) in
+ match typ with
+ | TVoid at -> TVoid (strip at)
+ | TInt (k,at) -> TInt (k,strip at)
+ | TFloat (k,at) -> TFloat(k,strip at)
+ | TPtr (t,at) -> TPtr(t,strip at)
+ | TArray (t,s,at) -> TArray(t,s,strip at)
+ | TFun (t,arg,v,at) -> TFun(t,arg,v,strip at)
+ | TNamed (n,at) -> TNamed(n,strip at)
+ | TStruct (n,at) -> TStruct(n,strip at)
+ | TUnion (n,at) -> TUnion(n,strip at)
+ | TEnum (n,at) -> TEnum(n,strip at)
+
+let strip_last_attribute typ =
+ let rec hd_opt l = match l with
+ [] -> None,[]
+ | AConst::rest -> Some AConst,rest
+ | AVolatile::rest -> Some AVolatile,rest
+ | _::rest -> hd_opt rest in
+ match typ with
+ | TVoid at -> let l,r = hd_opt at in
+ l,TVoid r
+ | TInt (k,at) -> let l,r = hd_opt at in
+ l,TInt (k,r)
+ | TFloat (k,at) -> let l,r = hd_opt at in
+ l,TFloat (k,r)
+ | TPtr (t,at) -> let l,r = hd_opt at in
+ l,TPtr(t,r)
+ | TArray (t,s,at) -> let l,r = hd_opt at in
+ l,TArray(t,s,r)
+ | TFun (t,arg,v,at) -> let l,r = hd_opt at in
+ l,TFun(t,arg,v,r)
+ | TNamed (n,at) -> let l,r = hd_opt at in
+ l,TNamed(n,r)
+ | TStruct (n,at) -> let l,r = hd_opt at in
+ l,TStruct(n,r)
+ | TUnion (n,at) -> let l,r = hd_opt at in
+ l,TUnion(n,r)
+ | TEnum (n,at) -> let l,r = hd_opt at in
+ l,TEnum(n,r)
+
+(* Does the type already exist? *)
+let exist_type (ty: typ) =
+ (* We are only interrested in Const and Volatile *)
+ let ty = strip_attributes ty in
+ Hashtbl.mem lookup_types (typ_to_string ty)
+
+(* Find the type id to an type *)
+let find_type (ty: typ) =
+ (* We are only interrested in Const and Volatile *)
+ let ty = strip_attributes ty in
+ Hashtbl.find lookup_types (typ_to_string ty)
+
+(* Add type and information *)
+let insert_type (ty: typ) =
+ let insert d_ty ty =
+ let id = next_id ()
+ and name = typ_to_string ty in
+ Hashtbl.add types id d_ty;
+ Hashtbl.add lookup_types name id;
+ id in
+ (* We are only interrested in Const and Volatile *)
+ let ty = strip_attributes ty in
+ let rec typ_aux ty =
+ try find_type ty with
+ | Not_found ->
+ let d_ty =
+ match ty with
+ | TVoid _ -> Void
+ | TInt (k,_) ->
+ IntegerType ({int_kind = k })
+ | TFloat (k,_) ->
+ FloatType ({float_kind = k})
+ | TPtr (t,_) ->
+ let id = attr_aux t in
+ PointerType ({pts = id})
+ | TArray (t,s,_) ->
+ let rec size acc t = (match t with
+ | TArray (child,s,_) ->
+ size (s::acc) child
+ | _ -> t,List.rev acc) in
+ let t,s = size [s] t in
+ let id = attr_aux t in
+ let arr = {
+ arr_type = id;
+ arr_size= s;
+ } in
+ ArrayType arr
+ | TFun (t,param,va,_) ->
+ let param,prot = (match param with
+ | None -> [],false
+ | Some p -> List.map (fun (i,t) -> let t = attr_aux t in
+ {
+ param_type = t;
+ param_name = i.name;
+ }) p,true) in
+ let ret = (match t with
+ | TVoid _ -> None
+ | _ -> Some (attr_aux t)) in
+ let ftype = {
+ fun_return_type = ret;
+ fun_prototyped = prot;
+ fun_params = param;
+ } in
+ FunctionType ftype
+ | TNamed (id,_) ->
+ let typ = try
+ let _,t =
+ List.find (fun a -> fst a = id.name) CBuiltins.builtins.Builtins.typedefs in
+ Some (attr_aux t)
+ with Not_found -> None in
+ let t = {
+ typedef_file_loc = None;
+ typedef_name = id.name;
+ typ = typ;
+ } in
+ Typedef t
+ | TStruct (id,_) ->
+ let str =
+ {
+ ct_name = id.name;
+ ct_sou = Struct;
+ ct_file_loc = None;
+ ct_members = [];
+ ct_declaration = false;
+ ct_sizeof = None;
+ } in
+ CompositeType str
+ | TUnion (id,_) ->
+ let union =
+ {
+ ct_name = id.name;
+ ct_sou = Union;
+ ct_file_loc = None;
+ ct_members = [];
+ ct_declaration = false;
+ ct_sizeof = None;
+ } in
+ CompositeType union
+ | TEnum (id,_) ->
+ let enum =
+ {
+ enum_name = id.name;
+ enum_byte_size = None;
+ enum_file_loc = None;
+ enum_enumerators = [];
+ } in
+ EnumType enum in
+ insert d_ty ty
+ and attr_aux ty =
+ try
+ find_type ty
+ with
+ Not_found ->
+ match strip_last_attribute ty with
+ | Some AConst,t ->
+ let id = attr_aux t in
+ let const = { cst_type = id} in
+ insert (ConstType const) ty
+ | Some AVolatile,t ->
+ let id = attr_aux t in
+ let volatile = {vol_type = id} in
+ insert (VolatileType volatile) ty
+ | Some (ARestrict|AAlignas _| Attr(_,_)),t ->
+ attr_aux t
+ | None,t -> typ_aux t
+ in
+ attr_aux ty
+
+(* Replace the composite information *)
+let replace_composite id f =
+ let str = Hashtbl.find types id in
+ match str with
+ | CompositeType comp -> let comp' = f comp in
+ if comp <> comp' then Hashtbl.replace types id (CompositeType comp')
+ | _ -> assert false (* This should never happen *)
+
+(* Replace the enum information *)
+let replace_enum id f =
+ let str = Hashtbl.find types id in
+ match str with
+ | EnumType comp -> let comp' = f comp in
+ if comp <> comp' then Hashtbl.replace types id (EnumType comp')
+ | _ -> assert false (* This should never happen *)
+
+(* Replace the typdef information *)
+let replace_typedef id f =
+ let typdef = Hashtbl.find types id in
+ match typdef with
+ | Typedef typ -> let typ' = f typ in
+ if typ <> typ' then Hashtbl.replace types id (Typedef typ')
+ | _ -> assert false (* This should never happen *)
+
+(* Types for global definitions *)
+
+(* Information for a global variable *)
+type global_variable_information = {
+ gvar_name: string;
+ gvar_atom: atom option;
+ gvar_file_loc: location;
+ gvar_declaration: bool;
+ gvar_external: bool;
+ gvar_type: int;
+ }
+
+type parameter_information =
+ {
+ parameter_name: string;
+ parameter_ident: int;
+ parameter_atom: atom option;
+ parameter_type: int;
+}
+
+type function_information = {
+ fun_name: string;
+ fun_atom: atom option;
+ fun_file_loc: location;
+ fun_external: bool;
+ fun_return_type: int option; (* Again the special case of void functions *)
+ fun_vararg: bool;
+ fun_parameter: parameter_information list;
+ fun_low_pc: int option;
+ fun_high_pc: int option;
+ fun_scope: int option;
+ }
+
+type definition_type =
+ | GlobalVariable of global_variable_information
+ | Function of function_information
+
+
+(* All global definitions encountered *)
+let definitions: (int,definition_type) Hashtbl.t = Hashtbl.create 7
+
+(* Mapping from stamp to debug id *)
+let stamp_to_definition: (int,int) Hashtbl.t = Hashtbl.create 7
+
+(* Mapping from name to debug id *)
+let name_to_definition: (string,int) Hashtbl.t = Hashtbl.create 7
+
+(* Mapping from atom to debug id *)
+let atom_to_definition: (atom, int) Hashtbl.t = Hashtbl.create 7
+
+let find_gvar_stamp id =
+ let id = (Hashtbl.find stamp_to_definition id) in
+ let var = Hashtbl.find definitions id in
+ match var with
+ | GlobalVariable var -> id,var
+ | _ -> assert false
+
+let find_fun_stamp id =
+ let id = (Hashtbl.find stamp_to_definition id) in
+ let f = Hashtbl.find definitions id in
+ match f with
+ | Function f -> id,f
+ | _ -> assert false
+
+let find_fun_atom id =
+ let id = (Hashtbl.find atom_to_definition id) in
+ let f = Hashtbl.find definitions id in
+ match f with
+ | Function f -> id,f
+ | _ -> assert false
+
+let replace_var id var =
+ let var = GlobalVariable var in
+ Hashtbl.replace definitions id var
+
+let replace_fun id f =
+ let f = Function f in
+ Hashtbl.replace definitions id f
+
+
+(* Information for local variables *)
+type local_variable_information = {
+ lvar_name: string;
+ lvar_atom: atom option;
+ lvar_file_loc:location;
+ lvar_type: int;
+ lvar_static: bool; (* Static variable are mapped to symbols *)
+ }
+
+type scope_information =
+ {
+ scope_variables: int list; (* Variable and Scope ids *)
+ }
+
+type local_information =
+ | LocalVariable of local_variable_information
+ | Scope of scope_information
+
+(* All local variables *)
+let local_variables: (int, local_information) Hashtbl.t = Hashtbl.create 7
+
+(* Mapping from stampt to the debug id of the local variable *)
+let stamp_to_local: (int,int) Hashtbl.t = Hashtbl.create 7
+
+(* Mapping form atom to the debug id of the local variable *)
+let atom_to_local: (atom, int) Hashtbl.t = Hashtbl.create 7
+
+(* Map from scope id + function id to debug id *)
+let scope_to_local: (int * int,int) Hashtbl.t = Hashtbl.create 7
+
+(* Map from scope id + function atom to debug id *)
+let atom_to_scope: (atom * int, int) Hashtbl.t = Hashtbl.create 7
+
+let find_lvar_stamp id =
+ let id = (Hashtbl.find stamp_to_local id) in
+ let v = Hashtbl.find local_variables id in
+ match v with
+ | LocalVariable v -> id,v
+ | _ -> assert false
+
+let replace_lvar id var =
+ let var = LocalVariable var in
+ Hashtbl.replace local_variables id var
+
+let find_scope_id fid id =
+ let id = Hashtbl.find scope_to_local (fid,id) in
+ let v = Hashtbl.find local_variables id in
+ match v with
+ | Scope v -> id,v
+ | _ -> assert false
+
+let replace_scope id var =
+ let var = Scope var in
+ Hashtbl.replace local_variables id var
+
+let gen_comp_typ sou id at =
+ if sou = Struct then
+ TStruct (id,at)
+ else
+ TUnion (id,at)
+
+let insert_global_declaration env dec=
+ add_file (fst dec.gloc);
+ let insert d_dec stamp =
+ let id = next_id () in
+ Hashtbl.add definitions id d_dec;
+ Hashtbl.add stamp_to_definition stamp id
+ in
+ match dec.gdesc with
+ | Gdecl (sto,id,ty,init) ->
+ if not (is_function_type env ty) then begin
+ if not (Hashtbl.mem stamp_to_definition id.stamp) then begin
+ let at_decl,ext = (match sto with
+ | Storage_extern -> init = None,true
+ | Storage_static -> false,false
+ | _ -> false,true) in
+ let ty = insert_type ty in
+ let decl = {
+ gvar_name = id.name;
+ gvar_atom = None;
+ gvar_file_loc = dec.gloc;
+ gvar_declaration = at_decl;
+ gvar_external = ext;
+ gvar_type = ty;
+ } in
+ insert (GlobalVariable decl) id.stamp
+ end else if init <> None || sto <> Storage_extern then begin (* It is a definition *)
+ let id,var = find_gvar_stamp id.stamp in
+ replace_var id ({var with gvar_declaration = false;})
+ end
+ end else if not (Hashtbl.mem name_to_definition id.name) then begin
+ (* Implict declarations need special handling *)
+ let id' = next_id () in
+ Hashtbl.add stamp_to_definition id.stamp id';
+ Hashtbl.add name_to_definition id.name id'
+ end
+ | Gfundef f ->
+ let ret = (match f.fd_ret with
+ | TVoid _ -> None
+ | _ -> Some (insert_type f.fd_ret)) in
+ let ext = (match f.fd_storage with
+ | Storage_static -> false
+ | _ -> true) in
+ let params = List.map (fun (p,ty) ->
+ let ty = insert_type ty in
+ {
+ parameter_name = p.name;
+ parameter_ident = p.stamp;
+ parameter_atom = None;
+ parameter_type = ty;
+ }) f.fd_params in
+ let fd =
+ {
+ fun_name = f.fd_name.name;
+ fun_atom = None;
+ fun_file_loc = dec.gloc;
+ fun_external = ext;
+ fun_return_type = ret;
+ fun_vararg = f.fd_vararg;
+ fun_parameter = params;
+ fun_low_pc = None;
+ fun_high_pc = None;
+ fun_scope = None;
+ } in
+ begin try
+ let id' = Hashtbl.find name_to_definition f.fd_name.name in
+ Hashtbl.add stamp_to_definition f.fd_name.stamp id';
+ Hashtbl.add definitions id' (Function fd)
+ with Not_found ->
+ insert (Function fd) f.fd_name.stamp
+ end
+ | Gcompositedecl (sou,id,at) ->
+ ignore (insert_type (gen_comp_typ sou id at));
+ let id = find_type (gen_comp_typ sou id []) in
+ replace_composite id (fun comp -> if comp.ct_file_loc = None then
+ {comp with ct_file_loc = Some (dec.gloc);}
+ else comp)
+ | Gcompositedef (sou,id,at,fi) ->
+ ignore (insert_type (gen_comp_typ sou id at));
+ let id = find_type (gen_comp_typ sou id []) in
+ let fi = List.filter (fun f -> f.fld_name <> "") fi in (* Fields without names need no info *)
+ let fields = List.map (fun f ->
+ {
+ cfd_name = f.fld_name;
+ cfd_typ = insert_type f.fld_typ;
+ cfd_bit_size = f.fld_bitfield;
+ cfd_bit_offset = None;
+ cfd_byte_offset = None;
+ cfd_byte_size = None;
+ cfd_bitfield = None;
+ }) fi in
+ replace_composite id (fun comp ->
+ let loc = if comp.ct_file_loc = None then Some dec.gloc else comp.ct_file_loc in
+ {comp with ct_file_loc = loc; ct_members = fields; ct_declaration = true;})
+ | Gtypedef (id,t) ->
+ let id = insert_type (TNamed (id,[])) in
+ let tid = insert_type t in
+ replace_typedef id (fun typ -> {typ with typedef_file_loc = Some dec.gloc; typ = Some tid;});
+ | Genumdef (n,at,e) ->
+ ignore(insert_type (TEnum (n,at)));
+ let id = find_type (TEnum (n,[])) in
+ let enumerator = List.map (fun (i,c,_) ->
+ {
+ enumerator_name = i.name;
+ enumerator_const = c;
+ }) e in
+ replace_enum id (fun en ->
+ {en with enum_file_loc = Some dec.gloc; enum_enumerators = enumerator;})
+ | Gpragma _ -> ()
+
+let set_member_offset str field offset =
+ let id = find_type (TStruct (str,[])) in
+ replace_composite id (fun comp ->
+ let name f = f.cfd_name = field || match f.cfd_bitfield with Some n -> n = field | _ -> false in
+ let members = list_replace name (fun a -> {a with cfd_byte_offset = Some offset;}) comp.ct_members in
+ {comp with ct_members = members;})
+
+let set_composite_size comp sou size =
+ let id = find_type (gen_comp_typ sou comp []) in
+ replace_composite id (fun comp -> {comp with ct_sizeof = size;})
+
+let set_bitfield_offset str field offset underlying size =
+ let id = find_type (TStruct (str,[])) in
+ replace_composite id (fun comp ->
+ let name f = f.cfd_name = field in
+ let members = list_replace name (fun a ->
+ {a with cfd_bit_offset = Some offset; cfd_bitfield = Some underlying; cfd_byte_size = Some size})
+ comp.ct_members in
+ {comp with ct_members = members;})
+
+let atom_global_variable id atom =
+ try
+ let id,var = find_gvar_stamp id.stamp in
+ replace_var id ({var with gvar_atom = Some atom;});
+ Hashtbl.add atom_to_definition atom id
+ with Not_found -> ()
+
+let atom_function id atom =
+ try
+ let id',f = find_fun_stamp id.stamp in
+ replace_fun id' ({f with fun_atom = Some atom;});
+ Hashtbl.add atom_to_definition atom id';
+ Hashtbl.iter (fun (fid,sid) tid -> if fid = id.stamp then
+ Hashtbl.add atom_to_scope (atom,sid) tid) scope_to_local
+ with Not_found -> ()
+
+let atom_parameter fid id atom =
+ try
+ let fid',f = find_fun_stamp fid.stamp in
+ let name p = p.parameter_ident = id.stamp in
+ let params = list_replace name (fun p -> {p with parameter_atom = Some atom;}) f.fun_parameter in
+ replace_fun fid' ({f with fun_parameter = params;})
+ with Not_found -> ()
+
+let add_fun_addr atom (high,low) =
+ try
+ let id,f = find_fun_atom atom in
+ replace_fun id ({f with fun_high_pc = Some high; fun_low_pc = Some low;})
+ with Not_found -> ()
+
+let atom_local_variable id atom =
+ try
+ let id,var = find_lvar_stamp id.stamp in
+ replace_lvar id ({var with lvar_atom = Some atom;});
+ Hashtbl.add atom_to_local atom id
+ with Not_found -> ()
+
+let add_lvar_scope f_id var_id s_id =
+ try
+ let s_id',scope = find_scope_id f_id s_id in
+ let var_id,_ = find_lvar_stamp var_id.stamp in
+ replace_scope s_id' ({scope_variables = var_id::scope.scope_variables;})
+ with Not_found -> ()
+
+let insert_local_declaration sto id ty loc =
+ let ty = insert_type ty in
+ let var = {
+ lvar_name = id.name;
+ lvar_atom = None;
+ lvar_file_loc = loc;
+ lvar_type = ty;
+ lvar_static = sto = Storage_static;
+ } in
+ let id' = next_id () in
+ Hashtbl.add local_variables id' (LocalVariable var);
+ Hashtbl.add stamp_to_local id.stamp id'
+
+let new_scope f_id sc_id =
+ let scope = {scope_variables = [];} in
+ let id = next_id () in
+ Hashtbl.add local_variables id (Scope scope);
+ Hashtbl.add scope_to_local (f_id,sc_id) id;
+ id
+
+let enter_function_scope fun_id sc_id =
+ try
+ let id = new_scope fun_id sc_id in
+ let fun_id,f = find_fun_stamp fun_id in
+ replace_fun fun_id ({f with fun_scope = Some id})
+ with Not_found -> ()
+
+let enter_scope f_id p_id id =
+ try
+ let id' = new_scope f_id id in
+ let p_id',scope = find_scope_id f_id p_id in
+ replace_scope p_id' ({scope_variables = id'::scope.scope_variables;})
+ with Not_found -> ()
+
+
+type scope_range =
+ {
+ start_addr: positive option;
+ end_addr: positive option;
+ }
+
+type var_range =
+ {
+ range_start: positive option;
+ range_end: positive option;
+ var_loc: int * int builtin_arg;
+ }
+
+type var_location =
+ | RangeLoc of var_range list
+ | FunctionLoc of int * int builtin_arg (* Stack allocated variables *)
+
+let var_locations: (atom,var_location) Hashtbl.t = Hashtbl.create 7
+
+let scope_ranges: (int,scope_range list) Hashtbl.t = Hashtbl.create 7
+
+let label_translation: (atom * positive, int) Hashtbl.t = Hashtbl.create 7
+
+let add_label atom p i =
+ Hashtbl.add label_translation (atom,p) i
+
+(* Auxiliary data structures and functions *)
+module IntSet = Set.Make(struct
+ type t = int
+ let compare (x:int) (y:int) = compare x y
+end)
+
+let open_scopes: IntSet.t ref = ref IntSet.empty
+let open_vars: atom list ref = ref []
+
+let open_scope atom s_id lbl =
+ try
+ let s_id = Hashtbl.find atom_to_scope (atom,s_id) in
+ let old_r = try Hashtbl.find scope_ranges s_id with Not_found -> [] in
+ let n_scop = { start_addr = Some lbl; end_addr = None;} in
+ open_scopes := IntSet.add s_id !open_scopes;
+ Hashtbl.replace scope_ranges s_id (n_scop::old_r)
+ with Not_found -> ()
+
+let close_scope atom s_id lbl =
+ try
+ let s_id = Hashtbl.find atom_to_scope (atom,s_id) in
+ let old_r = try Hashtbl.find scope_ranges s_id with Not_found -> [] in
+ let last_r,rest =
+ begin
+ match old_r with
+ | a::rest -> a,rest
+ | _ -> assert false (* We must have an opening scope *)
+ end in
+ let new_r = ({last_r with end_addr = Some lbl;})::rest in
+ open_scopes := IntSet.remove s_id !open_scopes;
+ Hashtbl.replace scope_ranges s_id new_r
+ with Not_found -> ()
+
+let start_live_range atom lbl loc =
+ let old_r = begin try Hashtbl.find var_locations atom with Not_found -> (RangeLoc []) end in
+ match old_r with
+ | RangeLoc old_r ->
+ let n_r = { range_start = Some lbl; range_end = None; var_loc = loc } in
+ open_vars := atom::!open_vars;
+ Hashtbl.replace var_locations atom (RangeLoc (n_r::old_r))
+ | _ -> () (* Parameter that is passed as variable *)
+
+let end_live_range atom lbl =
+ try
+ let old_r = Hashtbl.find var_locations atom in
+ match old_r with
+ | RangeLoc (n_r::old_r) ->
+ if n_r.range_end = None then (* We can skip non open locations *)
+ let n_r = {n_r with range_end = Some lbl} in
+ Hashtbl.replace var_locations atom (RangeLoc (n_r::old_r))
+ | _ -> ()
+ with Not_found -> ()
+
+let stack_variable atom (sp,loc) =
+ Hashtbl.add var_locations atom (FunctionLoc (sp,loc))
+
+let function_end atom loc =
+ IntSet.iter (fun id -> close_scope atom id loc) !open_scopes;
+ open_scopes := IntSet.empty;
+ List.iter (fun atom -> end_live_range atom loc) !open_vars;
+ open_vars:= []
+
+let compilation_section_start: (string,int * int * int * string) Hashtbl.t = Hashtbl.create 7
+let compilation_section_end: (string,int) Hashtbl.t = Hashtbl.create 7
+
+let add_compilation_section_start sec addr =
+ Hashtbl.add compilation_section_start sec addr
+
+let add_compilation_section_end sec addr =
+ Hashtbl.add compilation_section_end sec addr
+
+let exists_section sec =
+ Hashtbl.mem compilation_section_start sec
+
+let filenum: (string * string,int) Hashtbl.t = Hashtbl.create 7
+
+let compute_file_enum end_label entry_label line_end =
+ Hashtbl.iter (fun sec (_,_,_,secname) ->
+ Hashtbl.add compilation_section_end sec (end_label secname);
+ StringSet.iter (fun file ->
+ let lbl = entry_label file in
+ Hashtbl.add filenum (sec,file) lbl) !all_files;
+ line_end ()) compilation_section_start
+
+let init name =
+ id := 0;
+ file_name := name;
+ Hashtbl.reset types;
+ Hashtbl.reset lookup_types;
+ Hashtbl.reset definitions;
+ Hashtbl.reset stamp_to_definition;
+ Hashtbl.reset name_to_definition;
+ Hashtbl.reset atom_to_definition;
+ Hashtbl.reset local_variables;
+ Hashtbl.reset stamp_to_local;
+ Hashtbl.reset atom_to_local;
+ Hashtbl.reset scope_to_local;
+ Hashtbl.reset compilation_section_start;
+ Hashtbl.reset compilation_section_end;
+ Hashtbl.reset filenum;
+ all_files := StringSet.empty
diff --git a/debug/DebugInit.ml b/debug/DebugInit.ml
new file mode 100644
index 00000000..6a50b020
--- /dev/null
+++ b/debug/DebugInit.ml
@@ -0,0 +1,80 @@
+(* *********************************************************************)
+(* *)
+(* The Compcert verified compiler *)
+(* *)
+(* Bernhard Schommer, AbsInt Angewandte Informatik GmbH *)
+(* *)
+(* AbsInt Angewandte Informatik GmbH. All rights reserved. This file *)
+(* is distributed under the terms of the INRIA Non-Commercial *)
+(* License Agreement. *)
+(* *)
+(* *********************************************************************)
+
+open AST
+open BinNums
+open C
+open Camlcoq
+open Dwarfgen
+open DwarfTypes
+open Debug
+
+let init_debug () =
+ implem.init <- DebugInformation.init;
+ implem.atom_function <- DebugInformation.atom_function;
+ implem.atom_global_variable <- DebugInformation.atom_global_variable;
+ implem.set_composite_size <- DebugInformation.set_composite_size;
+ implem.set_member_offset <- DebugInformation.set_member_offset;
+ implem.set_bitfield_offset <- DebugInformation.set_bitfield_offset;
+ implem.insert_global_declaration <- DebugInformation.insert_global_declaration;
+ implem.add_fun_addr <- DebugInformation.add_fun_addr;
+ implem.generate_debug_info <- (fun a b -> Some (Dwarfgen.gen_debug_info a b));
+ implem.all_files_iter <- (fun f -> DebugInformation.StringSet.iter f !DebugInformation.all_files);
+ implem.insert_local_declaration <- DebugInformation.insert_local_declaration;
+ implem.atom_local_variable <- DebugInformation.atom_local_variable;
+ implem.enter_scope <- DebugInformation.enter_scope;
+ implem.enter_function_scope <- DebugInformation.enter_function_scope;
+ implem.add_lvar_scope <- DebugInformation.add_lvar_scope;
+ implem.open_scope <- DebugInformation.open_scope;
+ implem.close_scope <- DebugInformation.close_scope;
+ implem.start_live_range <- DebugInformation.start_live_range;
+ implem.end_live_range <- DebugInformation.end_live_range;
+ implem.stack_variable <- DebugInformation.stack_variable;
+ implem.function_end <- DebugInformation.function_end;
+ implem.add_label <- DebugInformation.add_label;
+ implem.atom_parameter <- DebugInformation.atom_parameter;
+ implem.add_compilation_section_start <- DebugInformation.add_compilation_section_start;
+ implem.compute_file_enum <- DebugInformation.compute_file_enum;
+ implem.exists_section <- DebugInformation.exists_section
+
+let init_none () =
+ implem.init <- (fun _ -> ());
+ implem.atom_function <- (fun _ _ -> ());
+ implem.atom_global_variable <- (fun _ _ -> ());
+ implem.set_composite_size <- (fun _ _ _ -> ());
+ implem.set_member_offset <- (fun _ _ _ -> ());
+ implem.set_bitfield_offset <- (fun _ _ _ _ _ -> ());
+ implem.insert_global_declaration <- (fun _ _ -> ());
+ implem.add_fun_addr <- (fun _ _ -> ());
+ implem.generate_debug_info <- (fun _ _ -> None);
+ implem.all_files_iter <- (fun _ -> ());
+ implem.insert_local_declaration <- (fun _ _ _ _ -> ());
+ implem.atom_local_variable <- (fun _ _ -> ());
+ implem.enter_scope <- (fun _ _ _ -> ());
+ implem.enter_function_scope <- (fun _ _ -> ());
+ implem.add_lvar_scope <- (fun _ _ _ -> ());
+ implem.open_scope <- (fun _ _ _ -> ());
+ implem.close_scope <- (fun _ _ _ -> ());
+ implem.start_live_range <- (fun _ _ _ -> ());
+ implem.end_live_range <- (fun _ _ -> ());
+ implem.stack_variable <- (fun _ _ -> ());
+ implem.function_end <- (fun _ _ -> ());
+ implem.add_label <- (fun _ _ _ -> ());
+ implem.atom_parameter <- (fun _ _ _ -> ());
+ implem.add_compilation_section_start <- (fun _ _ -> ());
+ implem.exists_section <- (fun _ -> true)
+
+let init () =
+ if !Clflags.option_g && Configuration.advanced_debug then
+ init_debug ()
+ else
+ init_none ()
diff --git a/debug/DwarfPrinter.ml b/debug/DwarfPrinter.ml
index 15843eb9..a95c71a1 100644
--- a/debug/DwarfPrinter.ml
+++ b/debug/DwarfPrinter.ml
@@ -19,14 +19,13 @@ open PrintAsmaux
open Sections
(* The printer is parameterized over target specific functions and a set of dwarf type constants *)
-module DwarfPrinter(Target: DWARF_TARGET)(DwarfAbbrevs:DWARF_ABBREVS):
+module DwarfPrinter(Target: DWARF_TARGET):
sig
- val print_debug: out_channel -> dw_entry -> unit
+ val print_debug: out_channel -> debug_entries -> unit
end =
struct
open Target
- open DwarfAbbrevs
(* Byte value to string *)
let string_of_byte value =
@@ -36,6 +35,10 @@ module DwarfPrinter(Target: DWARF_TARGET)(DwarfAbbrevs:DWARF_ABBREVS):
let print_label oc lbl =
fprintf oc "%a:\n" label lbl
+ (* Print a positive label *)
+ let print_plabel oc lbl =
+ print_label oc (transl_label lbl)
+
(* Helper functions for abbreviation printing *)
let add_byte buf value =
Buffer.add_string buf (string_of_byte value)
@@ -64,18 +67,15 @@ module DwarfPrinter(Target: DWARF_TARGET)(DwarfAbbrevs:DWARF_ABBREVS):
let add_low_pc = add_abbr_entry (0x11,low_pc_type_abbr)
- let add_fun_pc sp buf =
- match get_fun_addr sp.subprogram_name with
- | None ->()
- | Some (a,b) -> add_high_pc buf; add_low_pc buf
-
let add_declaration = add_abbr_entry (0x3c,declaration_type_abbr)
let add_location loc buf =
match loc with
| None -> ()
- | Some (LocConst _) -> add_abbr_entry (0x2,location_const_type_abbr) buf
- | Some (LocBlock _) -> add_abbr_entry (0x2,location_block_type_abbr) buf
+ | Some (LocRef _) -> add_abbr_entry (0x2,location_ref_type_abbr) buf
+ | Some (LocList _ )
+ | Some (LocSymbol _)
+ | Some (LocSimple _) -> add_abbr_entry (0x2,location_block_type_abbr) buf
(* Dwarf entity to string function *)
let abbrev_string_of_entity entity has_sibling =
@@ -105,8 +105,8 @@ module DwarfPrinter(Target: DWARF_TARGET)(DwarfAbbrevs:DWARF_ABBREVS):
| DW_TAG_compile_unit e ->
prologue 0x11;
add_abbr_entry (0x1b,comp_dir_type_abbr) buf;
- add_high_pc buf;
add_low_pc buf;
+ add_high_pc buf;
add_abbr_entry (0x13,language_type_abbr) buf;
add_name buf;
add_abbr_entry (0x25,producer_type_abbr) buf;
@@ -129,32 +129,31 @@ module DwarfPrinter(Target: DWARF_TARGET)(DwarfAbbrevs:DWARF_ABBREVS):
prologue 0x5;
add_attr_some e.formal_parameter_file_loc add_file_loc;
add_attr_some e.formal_parameter_artificial (add_abbr_entry (0x34,artificial_type_abbr));
- add_location e.formal_parameter_location buf;
add_attr_some e.formal_parameter_name add_name;
- add_location e.formal_parameter_segment buf;
add_type buf;
- add_attr_some e.formal_parameter_variable_parameter (add_abbr_entry (0x4b,variable_parameter_type_abbr))
+ add_attr_some e.formal_parameter_variable_parameter (add_abbr_entry (0x4b,variable_parameter_type_abbr));
+ add_location e.formal_parameter_location buf
| DW_TAG_label _ ->
prologue 0xa;
add_low_pc buf;
add_name buf;
- | DW_TAG_lexical_block _ ->
+ | DW_TAG_lexical_block a ->
prologue 0xb;
- add_high_pc buf;
- add_low_pc buf
+ add_attr_some a.lexical_block_high_pc add_high_pc;
+ add_attr_some a.lexical_block_low_pc add_low_pc
| DW_TAG_member e ->
prologue 0xd;
add_attr_some e.member_file_loc add_file_loc;
- add_attr_some e.member_byte_size add_member_size;
- add_attr_some e.member_bit_offset (add_abbr_entry (0xd,bit_offset_type_abbr));
- add_attr_some e.member_bit_size (add_abbr_entry (0xc,bit_size_type_abbr));
+ add_attr_some e.member_byte_size add_byte_size;
+ add_attr_some e.member_bit_offset (add_abbr_entry (0xc,bit_offset_type_abbr));
+ add_attr_some e.member_bit_size (add_abbr_entry (0xd,bit_size_type_abbr));
+ add_attr_some e.member_declaration add_declaration;
+ add_attr_some e.member_name add_name;
+ add_type buf;
(match e.member_data_member_location with
| None -> ()
| Some (DataLocBlock __) -> add_abbr_entry (0x38,data_location_block_type_abbr) buf
- | Some (DataLocRef _) -> add_abbr_entry (0x38,data_location_ref_type_abbr) buf);
- add_attr_some e.member_declaration add_declaration;
- add_attr_some e.member_name add_name;
- add_type buf
+ | Some (DataLocRef _) -> add_abbr_entry (0x38,data_location_ref_type_abbr) buf)
| DW_TAG_pointer_type _ ->
prologue 0xf;
add_type buf
@@ -166,9 +165,10 @@ module DwarfPrinter(Target: DWARF_TARGET)(DwarfAbbrevs:DWARF_ABBREVS):
add_attr_some e.structure_name add_name
| DW_TAG_subprogram e ->
prologue 0x2e;
- add_attr_some e.subprogram_file_loc add_file_loc;
+ add_file_loc buf;
add_attr_some e.subprogram_external (add_abbr_entry (0x3f,external_type_abbr));
- add_fun_pc e buf;
+ add_attr_some e.subprogram_high_pc add_high_pc;
+ add_attr_some e.subprogram_low_pc add_low_pc;
add_name buf;
add_abbr_entry (0x27,prototyped_type_abbr) buf;
add_attr_some e.subprogram_type add_type;
@@ -200,12 +200,11 @@ module DwarfPrinter(Target: DWARF_TARGET)(DwarfAbbrevs:DWARF_ABBREVS):
add_attr_some e.unspecified_parameter_artificial (add_abbr_entry (0x34,artificial_type_abbr))
| DW_TAG_variable e ->
prologue 0x34;
- add_attr_some e.variable_file_loc add_file_loc;
+ add_file_loc buf;
add_attr_some e.variable_declaration add_declaration;
add_attr_some e.variable_external (add_abbr_entry (0x3f,external_type_abbr));
add_location e.variable_location buf;
add_name buf;
- add_location e.variable_segment buf;
add_type buf
| DW_TAG_volatile_type _ ->
prologue 0x35;
@@ -246,7 +245,7 @@ module DwarfPrinter(Target: DWARF_TARGET)(DwarfAbbrevs:DWARF_ABBREVS):
let print_abbrev oc =
let abbrevs = Hashtbl.fold (fun s i acc -> (s,i)::acc) abbrev_mapping [] in
let abbrevs = List.sort (fun (_,a) (_,b) -> Pervasives.compare a b) abbrevs in
- fprintf oc " .section %s\n" (name_of_section Section_debug_abbrev);
+ section oc Section_debug_abbrev;
let lbl = new_label () in
abbrev_start_addr := lbl;
print_label oc lbl;
@@ -276,9 +275,6 @@ module DwarfPrinter(Target: DWARF_TARGET)(DwarfAbbrevs:DWARF_ABBREVS):
| None -> ()
| Some o -> f oc o
- let print_file_loc oc f =
- print_opt_value oc f print_file_loc
-
let print_flag oc b =
output_string oc (string_of_byte b)
@@ -294,16 +290,74 @@ module DwarfPrinter(Target: DWARF_TARGET)(DwarfAbbrevs:DWARF_ABBREVS):
let print_byte oc b =
fprintf oc " .byte 0x%X\n" b
- let print_loc oc loc =
- ()
-
- let print_data_location oc dl =
- ()
+ let print_2byte oc b =
+ fprintf oc " .2byte 0x%X\n" b
let print_ref oc r =
let ref = entry_to_label r in
fprintf oc " .4byte %a\n" label ref
+ let print_file_loc oc = function
+ | Some (file,col) ->
+ fprintf oc " .4byte %a\n" label file;
+ print_uleb128 oc col
+ | None -> ()
+
+ let print_loc_expr oc = function
+ | DW_OP_bregx (a,b) ->
+ print_byte oc dw_op_bregx;
+ print_uleb128 oc a;
+ fprintf oc " .sleb128 %ld\n" b
+ | DW_OP_plus_uconst i ->
+ print_byte oc dw_op_plus_uconst;
+ print_uleb128 oc i
+ | DW_OP_piece i ->
+ print_byte oc dw_op_piece;
+ print_uleb128 oc i
+ | DW_OP_reg i ->
+ if i < 32 then
+ print_byte oc (dw_op_reg0 + i)
+ else begin
+ print_byte oc dw_op_regx;
+ print_uleb128 oc i
+ end
+
+ let print_loc oc loc =
+ match loc with
+ | LocSymbol s ->
+ print_sleb128 oc 5;
+ print_byte oc dw_op_addr;
+ fprintf oc " .4byte %a\n" symbol s
+ | LocSimple e ->
+ print_sleb128 oc (size_of_loc_expr e);
+ print_loc_expr oc e
+ | LocList e ->
+ let size = List.fold_left (fun acc a -> acc + size_of_loc_expr a) 0 e in
+ print_sleb128 oc size;
+ List.iter (print_loc_expr oc) e
+ | LocRef f -> print_ref oc f
+
+ let print_list_loc oc = function
+ | LocSymbol s ->
+ print_2byte oc 5;
+ print_byte oc dw_op_addr;
+ fprintf oc " .4byte %a\n" symbol s
+ | LocSimple e ->
+ print_2byte oc (size_of_loc_expr e);
+ print_loc_expr oc e
+ | LocList e ->
+ let size = List.fold_left (fun acc a -> acc + size_of_loc_expr a) 0 e in
+ print_2byte oc size;
+ List.iter (print_loc_expr oc) e
+ | LocRef f -> print_ref oc f
+
+ let print_data_location oc dl =
+ match dl with
+ | DataLocBlock e ->
+ print_sleb128 oc (size_of_loc_expr e);
+ print_loc_expr oc e
+ | _ -> ()
+
let print_addr oc a =
fprintf oc " .4byte %a\n" label a
@@ -336,12 +390,12 @@ module DwarfPrinter(Target: DWARF_TARGET)(DwarfAbbrevs:DWARF_ABBREVS):
let print_compilation_unit oc tag =
let prod_name = sprintf "AbsInt Angewandte Informatik GmbH:CompCert Version %s:%s" Version.version Configuration.arch in
print_string oc (Sys.getcwd ());
- print_addr oc (get_end_addr ());
- print_addr oc (get_start_addr ());
+ print_addr oc tag.compile_unit_low_pc;
+ print_addr oc tag.compile_unit_high_pc;
print_uleb128 oc 1;
print_string oc tag.compile_unit_name;
print_string oc prod_name;
- print_addr oc (get_stmt_list_addr ())
+ print_addr oc tag.compile_unit_stmt_list
let print_const_type oc ct =
print_ref oc ct.const_type
@@ -360,29 +414,30 @@ module DwarfPrinter(Target: DWARF_TARGET)(DwarfAbbrevs:DWARF_ABBREVS):
let print_formal_parameter oc fp =
print_file_loc oc fp.formal_parameter_file_loc;
print_opt_value oc fp.formal_parameter_artificial print_flag;
- print_opt_value oc fp.formal_parameter_location print_loc;
print_opt_value oc fp.formal_parameter_name print_string;
- print_opt_value oc fp.formal_parameter_segment print_loc;
print_ref oc fp.formal_parameter_type;
- print_opt_value oc fp.formal_parameter_variable_parameter print_flag
+ print_opt_value oc fp.formal_parameter_variable_parameter print_flag;
+ print_opt_value oc fp.formal_parameter_location print_loc
let print_tag_label oc tl =
print_ref oc tl.label_low_pc;
print_string oc tl.label_name
+
let print_lexical_block oc lb =
- print_ref oc lb.lexical_block_high_pc;
- print_ref oc lb.lexical_block_low_pc
+ print_opt_value oc lb.lexical_block_high_pc print_addr;
+ print_opt_value oc lb.lexical_block_low_pc print_addr
let print_member oc mb =
print_file_loc oc mb.member_file_loc;
print_opt_value oc mb.member_byte_size print_byte;
print_opt_value oc mb.member_bit_offset print_byte;
print_opt_value oc mb.member_bit_size print_byte;
- print_opt_value oc mb.member_data_member_location print_data_location;
print_opt_value oc mb.member_declaration print_flag;
print_opt_value oc mb.member_name print_string;
- print_ref oc mb.member_type
+ print_ref oc mb.member_type;
+ print_opt_value oc mb.member_data_member_location print_data_location
+
let print_pointer oc pt =
print_ref oc pt.pointer_type
@@ -398,11 +453,10 @@ module DwarfPrinter(Target: DWARF_TARGET)(DwarfAbbrevs:DWARF_ABBREVS):
fprintf oc " .4byte %a\n" label s
let print_subprogram oc sp =
- let addr = get_fun_addr sp.subprogram_name in
- print_file_loc oc sp.subprogram_file_loc;
+ print_file_loc oc (Some sp.subprogram_file_loc);
print_opt_value oc sp.subprogram_external print_flag;
- print_opt_value oc sp.subprogram_frame_base print_loc;
- print_opt_value oc addr print_subprogram_addr;
+ print_opt_value oc sp.subprogram_high_pc print_addr;
+ print_opt_value oc sp.subprogram_low_pc print_addr;
print_string oc sp.subprogram_name;
print_flag oc sp.subprogram_prototyped;
print_opt_value oc sp.subprogram_type print_ref
@@ -431,12 +485,11 @@ module DwarfPrinter(Target: DWARF_TARGET)(DwarfAbbrevs:DWARF_ABBREVS):
print_opt_value oc up.unspecified_parameter_artificial print_flag
let print_variable oc var =
- print_file_loc oc var.variable_file_loc;
+ print_file_loc oc (Some var.variable_file_loc);
print_opt_value oc var.variable_declaration print_flag;
print_opt_value oc var.variable_external print_flag;
print_opt_value oc var.variable_location print_loc;
print_string oc var.variable_name;
- print_opt_value oc var.variable_segment print_loc;
print_ref oc var.variable_type
let print_volatile_type oc vt =
@@ -482,16 +535,15 @@ module DwarfPrinter(Target: DWARF_TARGET)(DwarfAbbrevs:DWARF_ABBREVS):
print_sleb128 oc 0) entry
(* Print the debug abbrev section *)
- let print_debug_abbrev oc entry =
- compute_abbrev entry;
+ let print_debug_abbrev oc entries =
+ List.iter (fun (_,_,e,_) -> compute_abbrev e) entries;
print_abbrev oc
(* Print the debug info section *)
- let print_debug_info oc entry =
- let debug_start = new_label () in
- debug_start_addr:= debug_start;
- fprintf oc" .section %s\n" (name_of_section Section_debug_info);
- print_label oc debug_start;
+ let print_debug_info oc sec start entry =
+ debug_start_addr:= start;
+ section oc (Section_debug_info sec);
+ print_label oc start;
let debug_length_start = new_label () (* Address used for length calculation *)
and debug_end = new_label () in
fprintf oc " .4byte %a-%a\n" label debug_end label debug_length_start;
@@ -503,10 +555,24 @@ module DwarfPrinter(Target: DWARF_TARGET)(DwarfAbbrevs:DWARF_ABBREVS):
print_sleb128 oc 0;
print_label oc debug_end (* End of the debug section *)
+ let print_location_entry oc c_low l =
+ print_label oc (entry_to_label l.loc_id);
+ List.iter (fun (b,e,loc) ->
+ fprintf oc " .4byte %a-%a\n" label b label c_low;
+ fprintf oc " .4byte %a-%a\n" label e label c_low;
+ print_list_loc oc loc) l.loc;
+ fprintf oc " .4byte 0\n";
+ fprintf oc " .4byte 0\n"
+
+ let print_location_list oc (c_low,l) =
+ List.iter (print_location_entry oc c_low) l
(* Print the debug info and abbrev section *)
- let print_debug oc entry =
- print_debug_abbrev oc entry;
- print_debug_info oc entry
+ let print_debug oc entries =
+ print_debug_abbrev oc entries;
+ List.iter (fun (s,d,e,_) -> print_debug_info oc s d e) entries;
+ section oc Section_debug_loc;
+ List.iter (fun (_,_,_,l) -> print_location_list oc l) entries
+
end
diff --git a/debug/DwarfPrinter.mli b/debug/DwarfPrinter.mli
index 9e0e6693..e1e10601 100644
--- a/debug/DwarfPrinter.mli
+++ b/debug/DwarfPrinter.mli
@@ -12,7 +12,7 @@
open DwarfTypes
-module DwarfPrinter: functor (Target: DWARF_TARGET) -> functor (DwarfAbbrevs: DWARF_ABBREVS) ->
+module DwarfPrinter: functor (Target: DWARF_TARGET) ->
sig
- val print_debug: out_channel -> dw_entry -> unit
+ val print_debug: out_channel -> debug_entries -> unit
end
diff --git a/debug/DwarfTypes.mli b/debug/DwarfTypes.mli
index eaf07e1e..906b7cba 100644
--- a/debug/DwarfTypes.mli
+++ b/debug/DwarfTypes.mli
@@ -12,6 +12,8 @@
(* Types used for writing dwarf debug information *)
+open BinNums
+open Camlcoq
open Sections
(* Basic types for the value of attributes *)
@@ -36,12 +38,20 @@ type address = int
type block = string
-type location_value =
- | LocConst of constant
- | LocBlock of block
+type location_expression =
+ | DW_OP_plus_uconst of constant
+ | DW_OP_bregx of int * int32
+ | DW_OP_piece of int
+ | DW_OP_reg of int
+type location_value =
+ | LocSymbol of atom
+ | LocRef of address
+ | LocSimple of location_expression
+ | LocList of location_expression list
+
type data_location_value =
- | DataLocBlock of block
+ | DataLocBlock of location_expression
| DataLocRef of reference
type bound_value =
@@ -50,7 +60,7 @@ type bound_value =
(* Types representing the attribute information per tag value *)
-type file_loc = string * constant
+type file_loc = int * constant
type dw_tag_array_type =
{
@@ -67,7 +77,10 @@ type dw_tag_base_type =
type dw_tag_compile_unit =
{
- compile_unit_name: string;
+ compile_unit_name: string;
+ compile_unit_low_pc: int;
+ compile_unit_high_pc: int;
+ compile_unit_stmt_list: int;
}
type dw_tag_const_type =
@@ -94,11 +107,10 @@ type dw_tag_formal_parameter =
{
formal_parameter_file_loc: file_loc option;
formal_parameter_artificial: flag option;
- formal_parameter_location: location_value option;
formal_parameter_name: string option;
- formal_parameter_segment: location_value option;
formal_parameter_type: reference;
formal_parameter_variable_parameter: flag option;
+ formal_parameter_location: location_value option;
}
type dw_tag_label =
@@ -109,8 +121,8 @@ type dw_tag_label =
type dw_tag_lexical_block =
{
- lexical_block_high_pc: address;
- lexical_block_low_pc: address;
+ lexical_block_high_pc: address option;
+ lexical_block_low_pc: address option;
}
type dw_tag_member =
@@ -140,12 +152,13 @@ type dw_tag_structure_type =
type dw_tag_subprogram =
{
- subprogram_file_loc: file_loc option;
- subprogram_external: flag option;
- subprogram_frame_base: location_value option;
+ subprogram_file_loc: file_loc;
+ subprogram_external: flag option;
subprogram_name: string;
subprogram_prototyped: flag;
- subprogram_type: reference option;
+ subprogram_type: reference option;
+ subprogram_high_pc: reference option;
+ subprogram_low_pc: reference option;
}
type dw_tag_subrange_type =
@@ -183,13 +196,12 @@ type dw_tag_unspecified_parameter =
type dw_tag_variable =
{
- variable_file_loc: file_loc option;
+ variable_file_loc: file_loc;
variable_declaration: flag option;
variable_external: flag option;
- variable_location: location_value option;
variable_name: string;
- variable_segment: location_value option;
variable_type: reference;
+ variable_location: location_value option;
}
type dw_tag_volatile_type =
@@ -228,46 +240,21 @@ type dw_entry =
id: reference;
}
-(* Module type for a matching from type to dwarf encoding *)
-module type DWARF_ABBREVS =
- sig
- val sibling_type_abbr: int
- val file_loc_type_abbr: int * int
- val type_abbr: int
- val name_type_abbr: int
- val encoding_type_abbr: int
- val byte_size_type_abbr: int
- val member_size_abbr: int
- val high_pc_type_abbr: int
- val low_pc_type_abbr: int
- val stmt_list_type_abbr: int
- val declaration_type_abbr: int
- val external_type_abbr: int
- val prototyped_type_abbr: int
- val bit_offset_type_abbr: int
- val comp_dir_type_abbr: int
- val language_type_abbr: int
- val producer_type_abbr: int
- val value_type_abbr: int
- val artificial_type_abbr: int
- val variable_parameter_type_abbr: int
- val bit_size_type_abbr: int
- val location_const_type_abbr: int
- val location_block_type_abbr: int
- val data_location_block_type_abbr: int
- val data_location_ref_type_abbr: int
- val bound_const_type_abbr: int
- val bound_ref_type_abbr: int
- end
+(* The type for the location list. *)
+type location_entry =
+ {
+ loc: (int * int * location_value) list;
+ loc_id: reference;
+ }
+type dw_locations = int * location_entry list
+
+type debug_entries = (string * int * dw_entry * dw_locations) list
(* The target specific functions for printing the debug information *)
module type DWARF_TARGET=
sig
val label: out_channel -> int -> unit
val print_file_loc: out_channel -> file_loc -> unit
- val get_start_addr: unit -> int
- val get_end_addr: unit -> int
- val get_stmt_list_addr: unit -> int
- val name_of_section: section_name -> string
- val get_fun_addr: string -> (int * int) option
+ val section: out_channel -> section_name -> unit
+ val symbol: out_channel -> atom -> unit
end
diff --git a/debug/DwarfUtil.ml b/debug/DwarfUtil.ml
index f47c2b58..16e446ee 100644
--- a/debug/DwarfUtil.ml
+++ b/debug/DwarfUtil.ml
@@ -14,18 +14,8 @@
open DwarfTypes
-let id = ref 0
-
-let next_id () =
- let nid = !id in
- incr id; nid
-
-let reset_id () =
- id := 0
-
(* Generate a new entry from a given tag *)
-let new_entry tag =
- let id = next_id () in
+let new_entry id tag =
{
tag = tag;
children = [];
@@ -86,34 +76,67 @@ let dw_form_ref8 = 0x14
let dw_ref_udata = 0x15
let dw_ref_indirect = 0x16
+(* Operation encoding *)
+let dw_op_addr = 0x3
+let dw_op_plus_uconst = 0x23
+let dw_op_reg0 = 0x50
+let dw_op_regx = 0x90
+let dw_op_bregx = 0x92
+let dw_op_piece = 0x93
+
+
(* Default corresponding encoding for the different abbreviations *)
-module DefaultAbbrevs =
- struct
- let sibling_type_abbr = dw_form_ref4
- let file_loc_type_abbr = dw_form_data4,dw_form_udata
- let type_abbr = dw_form_ref_addr
- let name_type_abbr = dw_form_string
- let encoding_type_abbr = dw_form_data1
- let byte_size_type_abbr = dw_form_data1
- let member_size_abbr = dw_form_udata
- let high_pc_type_abbr = dw_form_addr
- let low_pc_type_abbr = dw_form_addr
- let stmt_list_type_abbr = dw_form_data4
- let declaration_type_abbr = dw_form_flag
- let external_type_abbr = dw_form_flag
- let prototyped_type_abbr = dw_form_flag
- let bit_offset_type_abbr = dw_form_data1
- let comp_dir_type_abbr = dw_form_string
- let language_type_abbr = dw_form_udata
- let producer_type_abbr = dw_form_string
- let value_type_abbr = dw_form_sdata
- let artificial_type_abbr = dw_form_flag
- let variable_parameter_type_abbr = dw_form_flag
- let bit_size_type_abbr = dw_form_data1
- let location_const_type_abbr = dw_form_data4
- let location_block_type_abbr = dw_form_block
- let data_location_block_type_abbr = dw_form_block
- let data_location_ref_type_abbr = dw_form_ref4
- let bound_const_type_abbr = dw_form_udata
- let bound_ref_type_abbr=dw_form_ref4
- end
+let sibling_type_abbr = dw_form_ref4
+let file_loc_type_abbr = dw_form_data4,dw_form_udata
+let type_abbr = dw_form_ref_addr
+let name_type_abbr = dw_form_string
+let encoding_type_abbr = dw_form_data1
+let byte_size_type_abbr = dw_form_data1
+let member_size_abbr = dw_form_udata
+let high_pc_type_abbr = dw_form_addr
+let low_pc_type_abbr = dw_form_addr
+let stmt_list_type_abbr = dw_form_data4
+let declaration_type_abbr = dw_form_flag
+let external_type_abbr = dw_form_flag
+let prototyped_type_abbr = dw_form_flag
+let bit_offset_type_abbr = dw_form_data1
+let comp_dir_type_abbr = dw_form_string
+let language_type_abbr = dw_form_udata
+let producer_type_abbr = dw_form_string
+let value_type_abbr = dw_form_sdata
+let artificial_type_abbr = dw_form_flag
+let variable_parameter_type_abbr = dw_form_flag
+let bit_size_type_abbr = dw_form_data1
+let location_ref_type_abbr = dw_form_data4
+let location_block_type_abbr = dw_form_block
+let data_location_block_type_abbr = dw_form_block
+let data_location_ref_type_abbr = dw_form_ref4
+let bound_const_type_abbr = dw_form_udata
+let bound_ref_type_abbr=dw_form_ref4
+
+(* Sizeof functions for the encoding of uleb128 and sleb128 *)
+let sizeof_uleb128 value =
+ let size = ref 1 in
+ let value = ref (value lsr 7) in
+ while !value <> 0 do
+ value := !value lsr 7;
+ incr size;
+ done;
+ !size
+
+let sizeof_sleb128 value =
+ let size = ref 1 in
+ let byte = ref (value land 0x7f) in
+ let value = ref (value lsr 7) in
+ while not ((!value = 0 && (!byte land 0x40) = 0) || (!value = -1 && ((!byte land 0x40) <> 0))) do
+ byte := !value land 0x7f;
+ value := !value lsr 7;
+ incr size;
+ done;
+ !size
+
+let size_of_loc_expr = function
+ | DW_OP_bregx (a,b) -> 1 + (sizeof_uleb128 a) + (sizeof_sleb128 (Int32.to_int b))
+ | DW_OP_plus_uconst a
+ | DW_OP_piece a -> 1 + (sizeof_uleb128 a)
+ | DW_OP_reg i -> if i < 32 then 1 else 2
diff --git a/debug/Dwarfgen.ml b/debug/Dwarfgen.ml
new file mode 100644
index 00000000..3239ceb6
--- /dev/null
+++ b/debug/Dwarfgen.ml
@@ -0,0 +1,444 @@
+(* *********************************************************************)
+(* *)
+(* The Compcert verified compiler *)
+(* *)
+(* Bernhard Schommer, AbsInt Angewandte Informatik GmbH *)
+(* *)
+(* AbsInt Angewandte Informatik GmbH. All rights reserved. This file *)
+(* is distributed under the terms of the INRIA Non-Commercial *)
+(* License Agreement. *)
+(* *)
+(* *********************************************************************)
+
+open AST
+open C
+open Camlcoq
+open Cutil
+open DebugInformation
+open DwarfTypes
+open DwarfUtil
+(* Generate the dwarf DIE's from the information collected in DebugInformation *)
+
+(* Helper function to get values that must be set. *)
+let get_opt_val = function
+ | Some a -> a
+ | None -> assert false
+
+(* Auxiliary data structures and functions *)
+module IntSet = Set.Make(struct
+ type t = int
+ let compare (x:int) (y:int) = compare x y
+end)
+
+let rec mmap f env = function
+ | [] -> ([],env)
+ | hd :: tl ->
+ let (hd',env1) = f env hd in
+ let (tl', env2) = mmap f env1 tl in
+ (hd' :: tl', env2)
+
+(* Functions to translate the basetypes. *)
+let int_type_to_entry id i =
+ let encoding =
+ (match i.int_kind with
+ | IBool -> DW_ATE_boolean
+ | IChar ->
+ if !Machine.config.Machine.char_signed then
+ DW_ATE_signed_char
+ else
+ DW_ATE_unsigned_char
+ | IInt | ILong | ILongLong | IShort | ISChar -> DW_ATE_signed
+ | _ -> DW_ATE_unsigned)in
+ let int = {
+ base_type_byte_size = sizeof_ikind i.int_kind;
+ base_type_encoding = Some encoding;
+ base_type_name = typ_to_string (TInt (i.int_kind,[]));} in
+ new_entry id (DW_TAG_base_type int)
+
+let float_type_to_entry id f =
+ let byte_size = sizeof_fkind f.float_kind in
+ let float = {
+ base_type_byte_size = byte_size;
+ base_type_encoding = Some DW_ATE_float;
+ base_type_name = typ_to_string (TFloat (f.float_kind,[]));
+ } in
+ new_entry id (DW_TAG_base_type float)
+
+let void_to_entry id =
+ let void = {
+ base_type_byte_size = 0;
+ base_type_encoding = None;
+ base_type_name = "void";
+ } in
+ new_entry id (DW_TAG_base_type void)
+
+let translate_file_loc sec (f,l) =
+ Hashtbl.find filenum (sec,f),l
+
+let translate_file_loc_opt sec = function
+ | None -> None
+ | Some (f,l) ->
+ try
+ Some (translate_file_loc sec (f,l))
+ with Not_found -> None
+
+let typedef_to_entry sec id t =
+ let i = get_opt_val t.typ in
+ let td = {
+ typedef_file_loc = translate_file_loc_opt sec t.typedef_file_loc;
+ typedef_name = t.typedef_name;
+ typedef_type = i;
+ } in
+ new_entry id (DW_TAG_typedef td)
+
+let pointer_to_entry id p =
+ let p = {pointer_type = p.pts} in
+ new_entry id (DW_TAG_pointer_type p)
+
+let array_to_entry id arr =
+ let arr_tag = {
+ array_type_file_loc = None;
+ array_type = arr.arr_type;
+ } in
+ let arr_entry = new_entry id (DW_TAG_array_type arr_tag) in
+ let children = List.map (fun a ->
+ let r = match a with
+ | None -> None
+ | Some i ->
+ let bound = Int64.to_int (Int64.sub i Int64.one) in
+ Some (BoundConst bound) in
+ let s = {
+ subrange_type = None;
+ subrange_upper_bound = r;
+ } in
+ new_entry (next_id ()) (DW_TAG_subrange_type s)) arr.arr_size in
+ add_children arr_entry children
+
+let const_to_entry id c =
+ new_entry id (DW_TAG_const_type ({const_type = c.cst_type}))
+
+let volatile_to_entry id v =
+ new_entry id (DW_TAG_volatile_type ({volatile_type = v.vol_type}))
+
+let enum_to_entry sec id e =
+ let enumerator_to_entry e =
+ let tag =
+ {
+ enumerator_file_loc = None;
+ enumerator_value = Int64.to_int (e.enumerator_const);
+ enumerator_name = e.enumerator_name;
+ } in
+ new_entry (next_id ()) (DW_TAG_enumerator tag) in
+ let bs = sizeof_ikind enum_ikind in
+ let enum = {
+ enumeration_file_loc = translate_file_loc_opt sec e.enum_file_loc;
+ enumeration_byte_size = bs;
+ enumeration_declaration = Some false;
+ enumeration_name = Some e.enum_name;
+ } in
+ let enum = new_entry id (DW_TAG_enumeration_type enum) in
+ let child = List.map enumerator_to_entry e.enum_enumerators in
+ add_children enum child
+
+let fun_type_to_entry id f =
+ let children = if f.fun_prototyped then
+ let u = {
+ unspecified_parameter_file_loc = None;
+ unspecified_parameter_artificial = None;
+ } in
+ [new_entry (next_id ()) (DW_TAG_unspecified_parameter u)]
+ else
+ List.map (fun p ->
+ let fp = {
+ formal_parameter_file_loc = None;
+ formal_parameter_artificial = None;
+ formal_parameter_name = if p.param_name <> "" then Some p.param_name else None;
+ formal_parameter_type = p.param_type;
+ formal_parameter_variable_parameter = None;
+ formal_parameter_location = None;
+ } in
+ new_entry (next_id ()) (DW_TAG_formal_parameter fp)) f.fun_params;
+ in
+ let s = {
+ subroutine_type = f.fun_return_type;
+ subroutine_prototyped = f.fun_prototyped
+ } in
+ let s = new_entry id (DW_TAG_subroutine_type s) in
+ add_children s children
+
+let member_to_entry mem =
+ let mem = {
+ member_file_loc = None;
+ member_byte_size = mem.cfd_byte_size;
+ member_bit_offset = mem.cfd_bit_offset;
+ member_bit_size = mem.cfd_bit_size;
+ member_data_member_location =
+ (match mem.cfd_byte_offset with
+ | None -> None
+ | Some s -> Some (DataLocBlock (DW_OP_plus_uconst s)));
+ member_declaration = None;
+ member_name = Some (mem.cfd_name);
+ member_type = mem.cfd_typ;
+ } in
+ new_entry (next_id ()) (DW_TAG_member mem)
+
+let struct_to_entry sec id s =
+ let tag = {
+ structure_file_loc = translate_file_loc_opt sec s.ct_file_loc;
+ structure_byte_size = s.ct_sizeof;
+ structure_declaration = Some s.ct_declaration;
+ structure_name = if s.ct_name <> "" then Some s.ct_name else None;
+ } in
+ let entry = new_entry id (DW_TAG_structure_type tag) in
+ let child = List.map member_to_entry s.ct_members in
+ add_children entry child
+
+let union_to_entry sec id s =
+ let tag = {
+ union_file_loc = translate_file_loc_opt sec s.ct_file_loc;
+ union_byte_size = s.ct_sizeof;
+ union_declaration = Some s.ct_declaration;
+ union_name = if s.ct_name <> "" then Some s.ct_name else None;
+ } in
+ let entry = new_entry id (DW_TAG_union_type tag) in
+ let child = List.map member_to_entry s.ct_members in
+ add_children entry child
+
+let composite_to_entry sec id s =
+ match s.ct_sou with
+ | Struct -> struct_to_entry sec id s
+ | Union -> union_to_entry sec id s
+
+let infotype_to_entry sec id = function
+ | IntegerType i -> int_type_to_entry id i
+ | FloatType f -> float_type_to_entry id f
+ | PointerType p -> pointer_to_entry id p
+ | ArrayType arr -> array_to_entry id arr
+ | CompositeType c -> composite_to_entry sec id c
+ | EnumType e -> enum_to_entry sec id e
+ | FunctionType f -> fun_type_to_entry id f
+ | Typedef t -> typedef_to_entry sec id t
+ | ConstType c -> const_to_entry id c
+ | VolatileType v -> volatile_to_entry id v
+ | Void -> void_to_entry id
+
+let needs_types id d =
+ let add_type id d =
+ if not (IntSet.mem id d) then
+ IntSet.add id d,true
+ else
+ d,false in
+ let t = Hashtbl.find types id in
+ match t with
+ | IntegerType _
+ | FloatType _
+ | Void
+ | EnumType _ -> d,false
+ | Typedef t ->
+ add_type (get_opt_val t.typ) d
+ | PointerType p ->
+ add_type p.pts d
+ | ArrayType arr ->
+ add_type arr.arr_type d
+ | ConstType c ->
+ add_type c.cst_type d
+ | VolatileType v ->
+ add_type v.vol_type d
+ | FunctionType f ->
+ let d,c = match f.fun_return_type with
+ | Some t -> add_type t d
+ | None -> d,false in
+ List.fold_left (fun (d,c) p ->
+ let d,c' = add_type p.param_type d in
+ d,c||c') (d,c) f.fun_params
+ | CompositeType c ->
+ List.fold_left (fun (d,c) f ->
+ let d,c' = add_type f.cfd_typ d in
+ d,c||c') (d,false) c.ct_members
+
+let gen_types sec needed =
+ let rec aux d =
+ let d,c = IntSet.fold (fun id (d,c) ->
+ let d,c' = needs_types id d in
+ d,c||c') d (d,false) in
+ if c then
+ aux d
+ else
+ d in
+ let typs = aux needed in
+ List.rev (Hashtbl.fold (fun id t acc ->
+ if IntSet.mem id typs then
+ (infotype_to_entry sec id t)::acc
+ else
+ acc) types [])
+
+let global_variable_to_entry sec acc id v =
+ let var = {
+ variable_file_loc = translate_file_loc sec v.gvar_file_loc;
+ variable_declaration = Some v.gvar_declaration;
+ variable_external = Some v.gvar_external;
+ variable_name = v.gvar_name;
+ variable_type = v.gvar_type;
+ variable_location = match v.gvar_atom with Some a -> Some (LocSymbol a) | None -> None;
+ } in
+ new_entry id (DW_TAG_variable var),IntSet.add v.gvar_type acc
+
+let gen_splitlong op_hi op_lo =
+ let op_piece = DW_OP_piece 4 in
+ op_piece::op_hi@(op_piece::op_lo)
+
+let translate_function_loc a = function
+ | BA_addrstack (ofs) ->
+ let ofs = camlint_of_coqint ofs in
+ Some (LocSimple (DW_OP_bregx (a,ofs))),[]
+ | BA_splitlong (BA_addrstack hi,BA_addrstack lo)->
+ let hi = camlint_of_coqint hi
+ and lo = camlint_of_coqint lo in
+ if lo = Int32.add hi 4l then
+ Some (LocSimple (DW_OP_bregx (a,hi))),[]
+ else
+ let op_hi = [DW_OP_bregx (a,hi)]
+ and op_lo = [DW_OP_bregx (a,lo)] in
+ Some (LocList (gen_splitlong op_hi op_lo)),[]
+ | _ -> None,[]
+
+let range_entry_loc (sp,l) =
+ let rec aux = function
+ | BA i -> [DW_OP_reg i]
+ | BA_addrstack ofs ->
+ let ofs = camlint_of_coqint ofs in
+ [DW_OP_bregx (sp,ofs)]
+ | BA_splitlong (hi,lo) ->
+ let hi = aux hi
+ and lo = aux lo in
+ gen_splitlong hi lo
+ | _ -> assert false in
+ match aux l with
+ | [] -> assert false
+ | [a] -> LocSimple a
+ | a::rest -> LocList (a::rest)
+
+let location_entry f_id atom =
+ try
+ begin
+ match (Hashtbl.find var_locations atom) with
+ | FunctionLoc (a,r) ->
+ translate_function_loc a r
+ | RangeLoc l ->
+ let l = List.map (fun i ->
+ let hi = get_opt_val i.range_start
+ and lo = get_opt_val i.range_end in
+ let hi = Hashtbl.find label_translation (f_id,hi)
+ and lo = Hashtbl.find label_translation (f_id,lo) in
+ hi,lo,range_entry_loc i.var_loc) l in
+ let id = next_id () in
+ Some (LocRef id),[{loc = l;loc_id = id;}]
+ end
+ with Not_found -> None,[]
+
+let function_parameter_to_entry f_id (acc,bcc) p =
+ let loc,loc_list = location_entry f_id (get_opt_val p.parameter_atom) in
+ let p = {
+ formal_parameter_file_loc = None;
+ formal_parameter_artificial = None;
+ formal_parameter_name = Some p.parameter_name;
+ formal_parameter_type = p.parameter_type;
+ formal_parameter_variable_parameter = None;
+ formal_parameter_location = loc;
+ } in
+ new_entry (next_id ()) (DW_TAG_formal_parameter p),(IntSet.add p.formal_parameter_type acc,loc_list@bcc)
+
+let rec local_variable_to_entry sec f_id (acc,bcc) v id =
+ let loc,loc_list = location_entry f_id (get_opt_val v.lvar_atom) in
+ let var = {
+ variable_file_loc = translate_file_loc sec v.lvar_file_loc;
+ variable_declaration = None;
+ variable_external = None;
+ variable_name = v.lvar_name;
+ variable_type = v.lvar_type;
+ variable_location = loc;
+ } in
+ new_entry id (DW_TAG_variable var),(IntSet.add v.lvar_type acc,loc_list@bcc)
+
+and scope_to_entry sec f_id acc sc id =
+ let l_pc,h_pc = try
+ let r = Hashtbl.find scope_ranges id in
+ let lbl l = match l with
+ | Some l -> Some (Hashtbl.find label_translation (f_id,l))
+ | None -> None in
+ begin
+ match r with
+ | [] -> None,None
+ | [a] -> lbl a.start_addr, lbl a.end_addr
+ | a::rest -> lbl (List.hd (List.rev rest)).start_addr,lbl a.end_addr
+ end
+ with Not_found -> None,None in
+ let scope = {
+ lexical_block_high_pc = h_pc;
+ lexical_block_low_pc = l_pc;
+ } in
+ let vars,acc = mmap (local_to_entry sec f_id) acc sc.scope_variables in
+ let entry = new_entry id (DW_TAG_lexical_block scope) in
+ add_children entry vars,acc
+
+and local_to_entry sec f_id acc id =
+ match Hashtbl.find local_variables id with
+ | LocalVariable v -> local_variable_to_entry sec f_id acc v id
+ | Scope v -> scope_to_entry sec f_id acc v id
+
+let fun_scope_to_entries sec f_id acc id =
+ match id with
+ | None -> [],acc
+ | Some id ->
+ let sc = Hashtbl.find local_variables id in
+ (match sc with
+ | Scope sc ->mmap (local_to_entry sec f_id) acc sc.scope_variables
+ | _ -> assert false)
+
+let function_to_entry sec (acc,bcc) id f =
+ let f_tag = {
+ subprogram_file_loc = translate_file_loc sec f.fun_file_loc;
+ subprogram_external = Some f.fun_external;
+ subprogram_name = f.fun_name;
+ subprogram_prototyped = true;
+ subprogram_type = f.fun_return_type;
+ subprogram_high_pc = f.fun_high_pc;
+ subprogram_low_pc = f.fun_low_pc;
+ } in
+ let f_id = get_opt_val f.fun_atom in
+ let acc = match f.fun_return_type with Some s -> IntSet.add s acc | None -> acc in
+ let f_entry = new_entry id (DW_TAG_subprogram f_tag) in
+ let params,(acc,bcc) = mmap (function_parameter_to_entry f_id) (acc,bcc) f.fun_parameter in
+ let vars,(acc,bcc) = fun_scope_to_entries sec f_id (acc,bcc) f.fun_scope in
+ add_children f_entry (params@vars),(acc,bcc)
+
+let definition_to_entry sec (acc,bcc) id t =
+ match t with
+ | GlobalVariable g -> let e,acc = global_variable_to_entry sec acc id g in
+ e,(acc,bcc)
+ | Function f -> function_to_entry sec (acc,bcc) id f
+
+module StringMap = Map.Make(String)
+
+let gen_debug_info sec_name var_section : debug_entries =
+ let defs = Hashtbl.fold (fun id t acc ->
+ let s = match t with
+ | GlobalVariable _ -> var_section
+ | Function f -> sec_name (get_opt_val f.fun_atom) in
+ let old = try StringMap.find s acc with Not_found -> [] in
+ StringMap.add s ((id,t)::old) acc) definitions StringMap.empty in
+ StringMap.fold (fun s defs acc ->
+ let defs,(ty,locs) = List.fold_left (fun (acc,bcc) (id,t) ->
+ let t,bcc = definition_to_entry s bcc id t in
+ t::acc,bcc) ([],(IntSet.empty,[])) defs in
+ let line_start,low_pc,debug_start,_ = Hashtbl.find compilation_section_start s
+ and high_pc = Hashtbl.find compilation_section_end s in
+ let cp = {
+ compile_unit_name = !file_name;
+ compile_unit_low_pc = low_pc;
+ compile_unit_high_pc = high_pc;
+ compile_unit_stmt_list = line_start;
+ } in
+ let cp = new_entry (next_id ()) (DW_TAG_compile_unit cp) in
+ let cp = add_children cp ((gen_types s ty) @ defs) in
+ (s,debug_start,cp,(low_pc,locs))::acc) defs []