diff options
| author | Graydon Hoare <graydon@mozilla.com> | 2010-06-23 21:03:09 -0700 |
|---|---|---|
| committer | Graydon Hoare <graydon@mozilla.com> | 2010-06-23 21:03:09 -0700 |
| commit | d6b7c96c3eb29b9244ece0c046d3f372ff432d04 (patch) | |
| tree | b425187e232966063ffc2f0d14c04a55d8f004ef /src/rt/rust_crate_cache.cpp | |
| parent | c01efc669f09508b55eced32d3c88702578a7c3e (diff) | |
| download | rust-d6b7c96c3eb29b9244ece0c046d3f372ff432d04.tar.gz rust-d6b7c96c3eb29b9244ece0c046d3f372ff432d04.zip | |
Populate tree.
Diffstat (limited to 'src/rt/rust_crate_cache.cpp')
| -rw-r--r-- | src/rt/rust_crate_cache.cpp | 306 |
1 files changed, 306 insertions, 0 deletions
diff --git a/src/rt/rust_crate_cache.cpp b/src/rt/rust_crate_cache.cpp new file mode 100644 index 00000000000..fa10b91b97f --- /dev/null +++ b/src/rt/rust_crate_cache.cpp @@ -0,0 +1,306 @@ + +#include "rust_internal.h" + +rust_crate_cache::lib::lib(rust_dom *dom, char const *name) + : handle(0), + dom(dom) +{ +#if defined(__WIN32__) + handle = (uintptr_t)LoadLibrary(_T(name)); +#else + handle = (uintptr_t)dlopen(name, RTLD_LOCAL|RTLD_LAZY); +#endif + dom->log(rust_log::CACHE, "loaded library '%s' as 0x%" PRIxPTR, + name, handle); +} + +rust_crate_cache::lib::~lib() { + dom->log(rust_log::CACHE, "~rust_crate_cache::lib(0x%" PRIxPTR ")", + handle); + if (handle) { +#if defined(__WIN32__) + FreeLibrary((HMODULE)handle); +#else + dlclose((void*)handle); +#endif + } +} + +uintptr_t +rust_crate_cache::lib::get_handle() { + return handle; +} + + + +rust_crate_cache::c_sym::c_sym(rust_dom *dom, lib *library, char const *name) + : val(0), + library(library), + dom(dom) +{ + library->ref(); + uintptr_t handle = library->get_handle(); + if (handle) { +#if defined(__WIN32__) + val = (uintptr_t)GetProcAddress((HMODULE)handle, _T(name)); +#else + val = (uintptr_t)dlsym((void*)handle, name); +#endif + dom->log(rust_log::CACHE, "resolved symbol '%s' to 0x%" PRIxPTR, + name, val); + } else { + dom->log(rust_log::CACHE, "unresolved symbol '%s', null lib handle", + name); + } +} + +rust_crate_cache::c_sym::~c_sym() { + dom->log(rust_log::CACHE, + "~rust_crate_cache::c_sym(0x%" PRIxPTR ")", val); + library->deref(); +} + +uintptr_t +rust_crate_cache::c_sym::get_val() { + return val; +} + + + +rust_crate_cache::rust_sym::rust_sym(rust_dom *dom, + rust_crate const *curr_crate, + c_sym *crate_sym, + char const **path) + : val(0), + crate_sym(crate_sym), + dom(dom) +{ + crate_sym->ref(); + typedef rust_crate_reader::die die; + rust_crate const *crate = (rust_crate*)crate_sym->get_val(); + if (!crate) { + dom->log(rust_log::CACHE, + "failed to resolve symbol, null crate symbol"); + return; + } + rust_crate_reader rdr(dom, crate); + bool found_root = false; + bool found_leaf = false; + for (die d = rdr.dies.first_die(); + !(found_root || d.is_null()); + d = d.next_sibling()) { + + die t1 = d; + die t2 = d; + for (char const **c = crate_rel(curr_crate, path); + (*c + && !t1.is_null() + && t1.find_child_by_name(crate_rel(curr_crate, *c), t2)); + ++c, t1=t2) { + dom->log(rust_log::DWARF|rust_log::CACHE, + "matched die <0x%" PRIxPTR + ">, child '%s' = die<0x%" PRIxPTR ">", + t1.off, crate_rel(curr_crate, *c), t2.off); + found_root = found_root || true; + if (!*(c+1) && t2.find_num_attr(DW_AT_low_pc, val)) { + dom->log(rust_log::DWARF|rust_log::CACHE, + "found relative address: 0x%" PRIxPTR, val); + dom->log(rust_log::DWARF|rust_log::CACHE, + "plus image-base 0x%" PRIxPTR, + crate->get_image_base()); + val += crate->get_image_base(); + found_leaf = true; + break; + } + } + if (found_root || found_leaf) + break; + } + if (found_leaf) { + dom->log(rust_log::CACHE, "resolved symbol to 0x%" PRIxPTR, val); + } else { + dom->log(rust_log::CACHE, "failed to resolve symbol"); + } +} + +rust_crate_cache::rust_sym::~rust_sym() { + dom->log(rust_log::CACHE, + "~rust_crate_cache::rust_sym(0x%" PRIxPTR ")", val); + crate_sym->deref(); +} + +uintptr_t +rust_crate_cache::rust_sym::get_val() { + return val; +} + + + +rust_crate_cache::lib * +rust_crate_cache::get_lib(size_t n, char const *name) +{ + I(dom, n < crate->n_libs); + lib *library = libs[n]; + if (!library) { + library = new (dom) lib(dom, name); + libs[n] = library; + } + return library; +} + +rust_crate_cache::c_sym * +rust_crate_cache::get_c_sym(size_t n, lib *library, char const *name) +{ + I(dom, n < crate->n_c_syms); + c_sym *sym = c_syms[n]; + dom->log(rust_log::CACHE, "cached C symbol %s = 0x%" PRIxPTR, name, sym); + if (!sym) { + sym = new (dom) c_sym(dom, library, name); + c_syms[n] = sym; + } + return sym; +} + +rust_crate_cache::rust_sym * +rust_crate_cache::get_rust_sym(size_t n, + rust_dom *dom, + rust_crate const *curr_crate, + c_sym *crate_sym, + char const **path) +{ + I(dom, n < crate->n_rust_syms); + rust_sym *sym = rust_syms[n]; + if (!sym) { + sym = new (dom) rust_sym(dom, curr_crate, crate_sym, path); + rust_syms[n] = sym; + } + return sym; +} + +static inline void +adjust_disp(uintptr_t &disp, const void *oldp, const void *newp) +{ + if (disp) { + disp += (uintptr_t)oldp; + disp -= (uintptr_t)newp; + } +} + +type_desc * +rust_crate_cache::get_type_desc(size_t size, + size_t align, + size_t n_descs, + type_desc const **descs) +{ + I(dom, n_descs > 1); + type_desc *td = NULL; + size_t keysz = n_descs * sizeof(type_desc*); + HASH_FIND(hh, this->type_descs, descs, keysz, td); + if (td) { + dom->log(rust_log::CACHE, "rust_crate_cache::get_type_desc hit"); + return td; + } + dom->log(rust_log::CACHE, "rust_crate_cache::get_type_desc miss"); + td = (type_desc*) dom->malloc(sizeof(type_desc) + keysz); + if (!td) + return NULL; + // By convention, desc 0 is the root descriptor. + // but we ignore the size and alignment of it and use the + // passed-in, computed values. + memcpy(td, descs[0], sizeof(type_desc)); + td->first_param = &td->descs[1]; + td->size = size; + td->align = align; + for (size_t i = 0; i < n_descs; ++i) { + dom->log(rust_log::CACHE, + "rust_crate_cache::descs[%" PRIdPTR "] = 0x%" PRIxPTR, + i, descs[i]); + td->descs[i] = descs[i]; + } + adjust_disp(td->copy_glue_off, descs[0], td); + adjust_disp(td->drop_glue_off, descs[0], td); + adjust_disp(td->free_glue_off, descs[0], td); + adjust_disp(td->mark_glue_off, descs[0], td); + adjust_disp(td->obj_drop_glue_off, descs[0], td); + HASH_ADD(hh, this->type_descs, descs, keysz, td); + return td; +} + +rust_crate_cache::rust_crate_cache(rust_dom *dom, + rust_crate const *crate) + : rust_syms((rust_sym**) + dom->calloc(sizeof(rust_sym*) * crate->n_rust_syms)), + c_syms((c_sym**) dom->calloc(sizeof(c_sym*) * crate->n_c_syms)), + libs((lib**) dom->calloc(sizeof(lib*) * crate->n_libs)), + type_descs(NULL), + crate(crate), + dom(dom), + idx(0) +{ + I(dom, rust_syms); + I(dom, c_syms); + I(dom, libs); +} + +void +rust_crate_cache::flush() { + dom->log(rust_log::CACHE, "rust_crate_cache::flush()"); + for (size_t i = 0; i < crate->n_rust_syms; ++i) { + rust_sym *s = rust_syms[i]; + if (s) { + dom->log(rust_log::CACHE, + "rust_crate_cache::flush() deref rust_sym %" + PRIdPTR " (rc=%" PRIdPTR ")", i, s->refcnt); + s->deref(); + } + rust_syms[i] = NULL; + } + + for (size_t i = 0; i < crate->n_c_syms; ++i) { + c_sym *s = c_syms[i]; + if (s) { + dom->log(rust_log::CACHE, + "rust_crate_cache::flush() deref c_sym %" + PRIdPTR " (rc=%" PRIdPTR ")", i, s->refcnt); + s->deref(); + } + c_syms[i] = NULL; + } + + for (size_t i = 0; i < crate->n_libs; ++i) { + lib *l = libs[i]; + if (l) { + dom->log(rust_log::CACHE, "rust_crate_cache::flush() deref lib %" + PRIdPTR " (rc=%" PRIdPTR ")", i, l->refcnt); + l->deref(); + } + libs[i] = NULL; + } + + while (type_descs) { + type_desc *d = type_descs; + HASH_DEL(type_descs, d); + dom->log(rust_log::MEM, + "rust_crate_cache::flush() tydesc %" PRIxPTR, d); + dom->free(d); + } +} + +rust_crate_cache::~rust_crate_cache() +{ + flush(); + dom->free(rust_syms); + dom->free(c_syms); + dom->free(libs); +} + +// +// Local Variables: +// mode: C++ +// fill-column: 78; +// indent-tabs-mode: nil +// c-basic-offset: 4 +// buffer-file-coding-system: utf-8-unix +// compile-command: "make -k -C .. 2>&1 | sed -e 's/\\/x\\//x:\\//g'"; +// End: +// |
