1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "ProfilerCodeAddressService.h"
10 #include "mozilla/StackWalk.h"
12 using namespace mozilla
;
14 #if defined(XP_LINUX) || defined(XP_FREEBSD)
15 static char* SearchSymbolTable(SymbolTable
& aTable
, uint32_t aOffset
) {
18 BinarySearch(aTable
.mAddrs
, 0, aTable
.mAddrs
.Length(), aOffset
, &index
);
20 if (index
== 0 && !exact
) {
21 // Our offset is before the first symbol in the table; no result.
25 // Extract the (mangled) symbol name out of the string table.
26 auto strings
= reinterpret_cast<char*>(aTable
.mBuffer
.Elements());
28 symbol
.Append(strings
+ aTable
.mIndex
[index
- 1],
29 aTable
.mIndex
[index
] - aTable
.mIndex
[index
- 1]);
31 // First try demangling as a Rust identifier.
33 if (!profiler_demangle_rust(symbol
.get(), demangled
, std::size(demangled
))) {
34 // Then as a C++ identifier.
35 DemangleSymbol(symbol
.get(), demangled
, std::size(demangled
));
37 demangled
[std::size(demangled
) - 1] = '\0';
39 // Use the mangled name if we didn't successfully demangle.
40 return strdup(demangled
[0] != '\0' ? demangled
: symbol
.get());
44 bool ProfilerCodeAddressService::GetFunction(const void* aPc
,
45 nsACString
& aResult
) {
46 Entry
& entry
= GetEntry(aPc
);
48 #if defined(XP_LINUX) || defined(XP_FREEBSD)
49 // On Linux, most symbols will not be found by the MozDescribeCodeAddress call
50 // that GetEntry does. So we read the symbol table directly from the ELF
53 // SymbolTable currently assumes library offsets will not be larger than
55 if (entry
.mLOffset
<= 0xFFFFFFFF && !entry
.mFunction
) {
56 auto p
= mSymbolTables
.lookupForAdd(entry
.mLibrary
);
58 if (!mSymbolTables
.add(p
, entry
.mLibrary
, SymbolTable())) {
59 MOZ_CRASH("ProfilerCodeAddressService OOM");
61 profiler_get_symbol_table(entry
.mLibrary
, nullptr, &p
->value());
64 SearchSymbolTable(p
->value(), static_cast<uint32_t>(entry
.mLOffset
));
68 if (!entry
.mFunction
|| entry
.mFunction
[0] == '\0') {
72 aResult
= nsDependentCString(entry
.mFunction
);