1*d89ec533Spatrick //===-- memprof_descriptions.cpp -------------------------------*- C++ -*-===//
2*d89ec533Spatrick //
3*d89ec533Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*d89ec533Spatrick // See https://llvm.org/LICENSE.txt for license information.
5*d89ec533Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*d89ec533Spatrick //
7*d89ec533Spatrick //===----------------------------------------------------------------------===//
8*d89ec533Spatrick //
9*d89ec533Spatrick // This file is a part of MemProfiler, a memory profiler.
10*d89ec533Spatrick //
11*d89ec533Spatrick // MemProf functions for getting information about an address and/or printing
12*d89ec533Spatrick // it.
13*d89ec533Spatrick //===----------------------------------------------------------------------===//
14*d89ec533Spatrick
15*d89ec533Spatrick #include "memprof_descriptions.h"
16*d89ec533Spatrick #include "memprof_mapping.h"
17*d89ec533Spatrick #include "memprof_stack.h"
18*d89ec533Spatrick #include "sanitizer_common/sanitizer_stackdepot.h"
19*d89ec533Spatrick
20*d89ec533Spatrick namespace __memprof {
21*d89ec533Spatrick
MemprofThreadIdAndName(MemprofThreadContext * t)22*d89ec533Spatrick MemprofThreadIdAndName::MemprofThreadIdAndName(MemprofThreadContext *t) {
23*d89ec533Spatrick Init(t->tid, t->name);
24*d89ec533Spatrick }
25*d89ec533Spatrick
MemprofThreadIdAndName(u32 tid)26*d89ec533Spatrick MemprofThreadIdAndName::MemprofThreadIdAndName(u32 tid) {
27*d89ec533Spatrick if (tid == kInvalidTid) {
28*d89ec533Spatrick Init(tid, "");
29*d89ec533Spatrick } else {
30*d89ec533Spatrick memprofThreadRegistry().CheckLocked();
31*d89ec533Spatrick MemprofThreadContext *t = GetThreadContextByTidLocked(tid);
32*d89ec533Spatrick Init(tid, t->name);
33*d89ec533Spatrick }
34*d89ec533Spatrick }
35*d89ec533Spatrick
Init(u32 tid,const char * tname)36*d89ec533Spatrick void MemprofThreadIdAndName::Init(u32 tid, const char *tname) {
37*d89ec533Spatrick int len = internal_snprintf(name, sizeof(name), "T%d", tid);
38*d89ec533Spatrick CHECK(((unsigned int)len) < sizeof(name));
39*d89ec533Spatrick if (tname[0] != '\0')
40*d89ec533Spatrick internal_snprintf(&name[len], sizeof(name) - len, " (%s)", tname);
41*d89ec533Spatrick }
42*d89ec533Spatrick
DescribeThread(MemprofThreadContext * context)43*d89ec533Spatrick void DescribeThread(MemprofThreadContext *context) {
44*d89ec533Spatrick CHECK(context);
45*d89ec533Spatrick memprofThreadRegistry().CheckLocked();
46*d89ec533Spatrick // No need to announce the main thread.
47*d89ec533Spatrick if (context->tid == kMainTid || context->announced) {
48*d89ec533Spatrick return;
49*d89ec533Spatrick }
50*d89ec533Spatrick context->announced = true;
51*d89ec533Spatrick InternalScopedString str;
52*d89ec533Spatrick str.append("Thread %s", MemprofThreadIdAndName(context).c_str());
53*d89ec533Spatrick if (context->parent_tid == kInvalidTid) {
54*d89ec533Spatrick str.append(" created by unknown thread\n");
55*d89ec533Spatrick Printf("%s", str.data());
56*d89ec533Spatrick return;
57*d89ec533Spatrick }
58*d89ec533Spatrick str.append(" created by %s here:\n",
59*d89ec533Spatrick MemprofThreadIdAndName(context->parent_tid).c_str());
60*d89ec533Spatrick Printf("%s", str.data());
61*d89ec533Spatrick StackDepotGet(context->stack_id).Print();
62*d89ec533Spatrick // Recursively described parent thread if needed.
63*d89ec533Spatrick if (flags()->print_full_thread_history) {
64*d89ec533Spatrick MemprofThreadContext *parent_context =
65*d89ec533Spatrick GetThreadContextByTidLocked(context->parent_tid);
66*d89ec533Spatrick DescribeThread(parent_context);
67*d89ec533Spatrick }
68*d89ec533Spatrick }
69*d89ec533Spatrick
70*d89ec533Spatrick } // namespace __memprof
71