| 1 | // Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file | 
|---|
| 2 | // for details. All rights reserved. Use of this source code is governed by a | 
|---|
| 3 | // BSD-style license that can be found in the LICENSE file. | 
|---|
| 4 |  | 
|---|
| 5 | #include "vm/globals.h" | 
|---|
| 6 | #if defined(HOST_OS_FUCHSIA) | 
|---|
| 7 |  | 
|---|
| 8 | #include "platform/memory_sanitizer.h" | 
|---|
| 9 | #include "vm/native_symbol.h" | 
|---|
| 10 |  | 
|---|
| 11 | #include <dlfcn.h>   // NOLINT | 
|---|
| 12 |  | 
|---|
| 13 | namespace dart { | 
|---|
| 14 |  | 
|---|
| 15 | // On Fuchsia, in lieu of the ELF dynamic symbol table consumed through dladdr, | 
|---|
| 16 | // we consumes symbols produced by //topaz/runtime/dart/profiler_symbols and | 
|---|
| 17 | // provided to the VM by the embedder through Dart_AddSymbols. They have the | 
|---|
| 18 | // format | 
|---|
| 19 | // | 
|---|
| 20 | // struct { | 
|---|
| 21 | //    uint32_t num_entries; | 
|---|
| 22 | //    struct { | 
|---|
| 23 | //      uint32_t offset; | 
|---|
| 24 | //      uint32_t size; | 
|---|
| 25 | //      uint32_t string_table_offset; | 
|---|
| 26 | //    } entries[num_entries]; | 
|---|
| 27 | //    const char* string_table; | 
|---|
| 28 | // } | 
|---|
| 29 | // | 
|---|
| 30 | // Entries are sorted by offset. String table entries are NUL-terminated. | 
|---|
| 31 | class NativeSymbols { | 
|---|
| 32 | public: | 
|---|
| 33 | NativeSymbols(const char* dso_name, void* buffer, size_t size) | 
|---|
| 34 | : next_(NULL), dso_name_(dso_name) { | 
|---|
| 35 | num_entries_ = *reinterpret_cast<uint32_t*>(buffer); | 
|---|
| 36 | entries_ = | 
|---|
| 37 | reinterpret_cast<Entry*>(reinterpret_cast<uint32_t*>(buffer) + 1); | 
|---|
| 38 | name_table_ = reinterpret_cast<const char*>(entries_ + num_entries_); | 
|---|
| 39 | } | 
|---|
| 40 |  | 
|---|
| 41 | NativeSymbols* next() const { return next_; } | 
|---|
| 42 | void set_next(NativeSymbols* symbols) { next_ = symbols; } | 
|---|
| 43 |  | 
|---|
| 44 | bool Lookup(const char* dso_name, | 
|---|
| 45 | uword dso_offset, | 
|---|
| 46 | uword* start_offset, | 
|---|
| 47 | const char** name) { | 
|---|
| 48 | if (strcmp(dso_name, dso_name_) != 0) { | 
|---|
| 49 | return false; | 
|---|
| 50 | } | 
|---|
| 51 |  | 
|---|
| 52 | intptr_t lo = 0; | 
|---|
| 53 | intptr_t hi = num_entries_ - 1; | 
|---|
| 54 | while (lo <= hi) { | 
|---|
| 55 | intptr_t mid = (hi - lo + 1) / 2 + lo; | 
|---|
| 56 | ASSERT(mid >= lo); | 
|---|
| 57 | ASSERT(mid <= hi); | 
|---|
| 58 | const Entry& entry = entries_[mid]; | 
|---|
| 59 | if (dso_offset < entry.offset) { | 
|---|
| 60 | hi = mid - 1; | 
|---|
| 61 | } else if (dso_offset >= (entry.offset + entry.size)) { | 
|---|
| 62 | lo = mid + 1; | 
|---|
| 63 | } else { | 
|---|
| 64 | *start_offset = entry.offset; | 
|---|
| 65 | *name = &name_table_[entry.name_offset]; | 
|---|
| 66 | return true; | 
|---|
| 67 | } | 
|---|
| 68 | } | 
|---|
| 69 |  | 
|---|
| 70 | return false; | 
|---|
| 71 | } | 
|---|
| 72 |  | 
|---|
| 73 | private: | 
|---|
| 74 | struct Entry { | 
|---|
| 75 | uint32_t offset; | 
|---|
| 76 | uint32_t size; | 
|---|
| 77 | uint32_t name_offset; | 
|---|
| 78 | }; | 
|---|
| 79 |  | 
|---|
| 80 | NativeSymbols* next_; | 
|---|
| 81 | const char* const dso_name_; | 
|---|
| 82 | intptr_t num_entries_; | 
|---|
| 83 | Entry* entries_; | 
|---|
| 84 | const char* name_table_; | 
|---|
| 85 |  | 
|---|
| 86 | DISALLOW_COPY_AND_ASSIGN(NativeSymbols); | 
|---|
| 87 | }; | 
|---|
| 88 |  | 
|---|
| 89 | static NativeSymbols* symbols_ = NULL; | 
|---|
| 90 |  | 
|---|
| 91 | void NativeSymbolResolver::Init() {} | 
|---|
| 92 |  | 
|---|
| 93 | void NativeSymbolResolver::Cleanup() { | 
|---|
| 94 | NativeSymbols* symbols = symbols_; | 
|---|
| 95 | symbols_ = NULL; | 
|---|
| 96 | while (symbols != NULL) { | 
|---|
| 97 | NativeSymbols* next = symbols->next(); | 
|---|
| 98 | delete symbols; | 
|---|
| 99 | symbols = next; | 
|---|
| 100 | } | 
|---|
| 101 | } | 
|---|
| 102 |  | 
|---|
| 103 | char* NativeSymbolResolver::LookupSymbolName(uword pc, uword* start) { | 
|---|
| 104 | Dl_info info; | 
|---|
| 105 | int r = dladdr(reinterpret_cast<void*>(pc), &info); | 
|---|
| 106 | if (r == 0) { | 
|---|
| 107 | return NULL; | 
|---|
| 108 | } | 
|---|
| 109 |  | 
|---|
| 110 | auto const dso_name = info.dli_fname; | 
|---|
| 111 | const auto dso_base = reinterpret_cast<uword>(info.dli_fbase); | 
|---|
| 112 | const auto dso_offset = pc - dso_base; | 
|---|
| 113 |  | 
|---|
| 114 | for (NativeSymbols* symbols = symbols_; symbols != NULL; | 
|---|
| 115 | symbols = symbols->next()) { | 
|---|
| 116 | uword symbol_start_offset; | 
|---|
| 117 | const char* symbol_name; | 
|---|
| 118 | if (symbols->Lookup(dso_name, dso_offset, &symbol_start_offset, | 
|---|
| 119 | &symbol_name)) { | 
|---|
| 120 | if (start != NULL) { | 
|---|
| 121 | *start = symbol_start_offset + dso_base; | 
|---|
| 122 | } | 
|---|
| 123 | return strdup(symbol_name); | 
|---|
| 124 | } | 
|---|
| 125 | } | 
|---|
| 126 |  | 
|---|
| 127 | return NULL; | 
|---|
| 128 | } | 
|---|
| 129 |  | 
|---|
| 130 | void NativeSymbolResolver::FreeSymbolName(char* name) { | 
|---|
| 131 | free(name); | 
|---|
| 132 | } | 
|---|
| 133 |  | 
|---|
| 134 | bool NativeSymbolResolver::LookupSharedObject(uword pc, | 
|---|
| 135 | uword* dso_base, | 
|---|
| 136 | char** dso_name) { | 
|---|
| 137 | Dl_info info; | 
|---|
| 138 | int r = dladdr(reinterpret_cast<void*>(pc), &info); | 
|---|
| 139 | if (r == 0) { | 
|---|
| 140 | return false; | 
|---|
| 141 | } | 
|---|
| 142 | if (dso_base != nullptr) { | 
|---|
| 143 | *dso_base = reinterpret_cast<uword>(info.dli_fbase); | 
|---|
| 144 | } | 
|---|
| 145 | if (dso_name != nullptr) { | 
|---|
| 146 | *dso_name = strdup(info.dli_fname); | 
|---|
| 147 | } | 
|---|
| 148 | return true; | 
|---|
| 149 | } | 
|---|
| 150 |  | 
|---|
| 151 | void NativeSymbolResolver::AddSymbols(const char* dso_name, | 
|---|
| 152 | void* buffer, size_t size) { | 
|---|
| 153 | NativeSymbols* symbols = new NativeSymbols(dso_name, buffer, size); | 
|---|
| 154 | symbols->set_next(symbols_); | 
|---|
| 155 | symbols_ = symbols; | 
|---|
| 156 | } | 
|---|
| 157 |  | 
|---|
| 158 | }  // namespace dart | 
|---|
| 159 |  | 
|---|
| 160 | #endif  // defined(HOST_OS_FUCHSIA) | 
|---|
| 161 |  | 
|---|