#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]; // FIXME (issue #136): Below is a miscalculation. td->is_stateful |= descs[i]->is_stateful; } 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->sever_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->ref_count); 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->ref_count); 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->ref_count); 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: //