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
13namespace 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.
31class 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
89static NativeSymbols* symbols_ = NULL;
90
91void NativeSymbolResolver::Init() {}
92
93void 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
103char* 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
130void NativeSymbolResolver::FreeSymbolName(char* name) {
131 free(name);
132}
133
134bool 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
151void 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