diff options
| author | Graydon Hoare <[email protected]> | 2010-06-23 21:03:09 -0700 |
|---|---|---|
| committer | Graydon Hoare <[email protected]> | 2010-06-23 21:03:09 -0700 |
| commit | d6b7c96c3eb29b9244ece0c046d3f372ff432d04 (patch) | |
| tree | b425187e232966063ffc2f0d14c04a55d8f004ef /src/boot/driver/lib.ml | |
| parent | Initial git commit. (diff) | |
| download | rust-d6b7c96c3eb29b9244ece0c046d3f372ff432d04.tar.xz rust-d6b7c96c3eb29b9244ece0c046d3f372ff432d04.zip | |
Populate tree.
Diffstat (limited to 'src/boot/driver/lib.ml')
| -rw-r--r-- | src/boot/driver/lib.ml | 232 |
1 files changed, 232 insertions, 0 deletions
diff --git a/src/boot/driver/lib.ml b/src/boot/driver/lib.ml new file mode 100644 index 00000000..e0391c65 --- /dev/null +++ b/src/boot/driver/lib.ml @@ -0,0 +1,232 @@ +open Common;; + +let log (sess:Session.sess) = + Session.log "lib" + sess.Session.sess_log_lib + sess.Session.sess_log_out +;; + +let iflog (sess:Session.sess) (thunk:(unit -> unit)) : unit = + if sess.Session.sess_log_lib + then thunk () + else () +;; + +(* FIXME: move these to sess. *) +let ar_cache = Hashtbl.create 0 ;; +let sects_cache = Hashtbl.create 0;; +let meta_cache = Hashtbl.create 0;; +let die_cache = Hashtbl.create 0;; + +let get_ar + (sess:Session.sess) + (filename:filename) + : Asm.asm_reader option = + htab_search_or_add ar_cache filename + begin + fun _ -> + let sniff = + match sess.Session.sess_targ with + Win32_x86_pe -> Pe.sniff + | MacOS_x86_macho -> Macho.sniff + | Linux_x86_elf -> Elf.sniff + in + sniff sess filename + end +;; + + +let get_sects + (sess:Session.sess) + (filename:filename) : + (Asm.asm_reader * ((string,(int*int)) Hashtbl.t)) option = + htab_search_or_add sects_cache filename + begin + fun _ -> + match get_ar sess filename with + None -> None + | Some ar -> + let get_sections = + match sess.Session.sess_targ with + Win32_x86_pe -> Pe.get_sections + | MacOS_x86_macho -> Macho.get_sections + | Linux_x86_elf -> Elf.get_sections + in + Some (ar, (get_sections sess ar)) + end +;; + +let get_meta + (sess:Session.sess) + (filename:filename) + : Ast.meta option = + htab_search_or_add meta_cache filename + begin + fun _ -> + match get_sects sess filename with + None -> None + | Some (ar, sects) -> + match htab_search sects ".note.rust" with + Some (off, _) -> + ar.Asm.asm_seek off; + Some (Asm.read_rust_note ar) + | None -> None + end +;; + +let get_dies_opt + (sess:Session.sess) + (filename:filename) + : (Dwarf.rooted_dies option) = + htab_search_or_add die_cache filename + begin + fun _ -> + match get_sects sess filename with + None -> None + | Some (ar, sects) -> + let debug_abbrev = Hashtbl.find sects ".debug_abbrev" in + let debug_info = Hashtbl.find sects ".debug_info" in + let abbrevs = Dwarf.read_abbrevs sess ar debug_abbrev in + let dies = Dwarf.read_dies sess ar debug_info abbrevs in + ar.Asm.asm_close (); + Hashtbl.remove ar_cache filename; + Some dies + end +;; + +let get_dies + (sess:Session.sess) + (filename:filename) + : Dwarf.rooted_dies = + match get_dies_opt sess filename with + None -> + Printf.fprintf stderr "Error: bad crate file: %s\n%!" filename; + exit 1 + | Some dies -> dies +;; + +let get_file_mod + (sess:Session.sess) + (abi:Abi.abi) + (filename:filename) + (nref:node_id ref) + (oref:opaque_id ref) + : Ast.mod_items = + let dies = get_dies sess filename in + let items = Hashtbl.create 0 in + Dwarf.extract_mod_items nref oref abi items dies; + items +;; + +let get_mod + (sess:Session.sess) + (abi:Abi.abi) + (meta:Ast.meta_pat) + (use_id:node_id) + (nref:node_id ref) + (oref:opaque_id ref) + : (filename * Ast.mod_items) = + let found = Queue.create () in + let suffix = + match sess.Session.sess_targ with + Win32_x86_pe -> ".dll" + | MacOS_x86_macho -> ".dylib" + | Linux_x86_elf -> ".so" + in + let rec meta_matches i f_meta = + if i >= (Array.length meta) + then true + else + match meta.(i) with + (* FIXME: bind the wildcards. *) + (_, None) -> meta_matches (i+1) f_meta + | (k, Some v) -> + match atab_search f_meta k with + None -> false + | Some v' -> + if v = v' + then meta_matches (i+1) f_meta + else false + in + let file_matches file = + log sess "searching for metadata in %s" file; + match get_meta sess file with + None -> false + | Some f_meta -> + log sess "matching metadata in %s" file; + meta_matches 0 f_meta + in + iflog sess + begin + fun _ -> + log sess "searching for library matching:"; + Array.iter + begin + fun (k,vo) -> + match vo with + None -> () + | Some v -> + log sess "%s = %S" k v + end + meta; + end; + Queue.iter + begin + fun dir -> + let dh = Unix.opendir dir in + let rec scan _ = + try + let file = Unix.readdir dh in + log sess "considering file %s" file; + if (Filename.check_suffix file suffix) && + (file_matches file) + then + begin + iflog sess + begin + fun _ -> + log sess "matched against library %s" file; + match get_meta sess file with + None -> () + | Some meta -> + Array.iter + (fun (k,v) -> log sess "%s = %S" k v) + meta; + end; + Queue.add file found; + end; + scan() + with + End_of_file -> () + in + scan () + end + sess.Session.sess_lib_dirs; + match Queue.length found with + 0 -> Common.err (Some use_id) "unsatisfied 'use' clause" + | 1 -> + let filename = Queue.pop found in + let items = get_file_mod sess abi filename nref oref in + (filename, items) + | _ -> Common.err (Some use_id) "multiple crates match 'use' clause" +;; + +let infer_lib_name + (sess:Session.sess) + (ident:filename) + : filename = + match sess.Session.sess_targ with + Win32_x86_pe -> ident ^ ".dll" + | MacOS_x86_macho -> "lib" ^ ident ^ ".dylib" + | Linux_x86_elf -> "lib" ^ ident ^ ".so" +;; + + +(* + * Local Variables: + * fill-column: 78; + * indent-tabs-mode: nil + * buffer-file-coding-system: utf-8-unix + * compile-command: "make -k -C ../.. 2>&1 | sed -e 's/\\/x\\//x:\\//g'"; + * End: + *) |