1// Licensed to the .NET Foundation under one or more agreements.
2// The .NET Foundation licenses this file to you under the MIT license.
3// See the LICENSE file in the project root for more information.
4
5#include "sosplugin.h"
6#include <dlfcn.h>
7#include <string.h>
8#include <string>
9
10class sosCommand : public lldb::SBCommandPluginInterface
11{
12 const char *m_command;
13 void *m_sosHandle;
14
15public:
16 sosCommand(const char *command)
17 {
18 m_command = command;
19 m_sosHandle = NULL;
20 }
21
22 virtual bool
23 DoExecute (lldb::SBDebugger debugger,
24 char** arguments,
25 lldb::SBCommandReturnObject &result)
26 {
27 LLDBServices* services = new LLDBServices(debugger, result);
28 LoadSos(services);
29
30 if (m_sosHandle)
31 {
32 const char* sosCommand = m_command;
33 if (sosCommand == NULL)
34 {
35 if (arguments == NULL || *arguments == NULL) {
36 sosCommand = "Help";
37 }
38 else
39 {
40 sosCommand = *arguments++;
41 }
42 }
43 CommandFunc commandFunc = (CommandFunc)dlsym(m_sosHandle, sosCommand);
44 if (commandFunc)
45 {
46 std::string str;
47 if (arguments != NULL)
48 {
49 for (const char* arg = *arguments; arg; arg = *(++arguments))
50 {
51 str.append(arg);
52 str.append(" ");
53 }
54 }
55 const char* sosArgs = str.c_str();
56 HRESULT hr = commandFunc(services, sosArgs);
57 if (hr != S_OK)
58 {
59 services->Output(DEBUG_OUTPUT_ERROR, "%s %s failed\n", sosCommand, sosArgs);
60 }
61 }
62 else
63 {
64 services->Output(DEBUG_OUTPUT_ERROR, "SOS command '%s' not found %s\n", sosCommand, dlerror());
65 }
66 }
67
68 services->Release();
69 return result.Succeeded();
70 }
71
72 void
73 LoadSos(LLDBServices *services)
74 {
75 if (m_sosHandle == NULL)
76 {
77 if (g_coreclrDirectory == NULL)
78 {
79 const char *coreclrModule = MAKEDLLNAME_A("coreclr");
80 const char *directory = services->GetModuleDirectory(coreclrModule);
81 if (directory != NULL)
82 {
83 std::string path(directory);
84 path.append("/");
85 g_coreclrDirectory = strdup(path.c_str());
86 }
87 else
88 {
89 services->Output(DEBUG_OUTPUT_WARNING, "The %s module is not loaded yet in the target process\n", coreclrModule);
90 }
91 }
92
93 if (g_coreclrDirectory != NULL)
94 {
95 // Load the DAC module first explicitly because SOS and DBI
96 // have implicit references to the DAC's PAL.
97 LoadModule(services, MAKEDLLNAME_A("mscordaccore"));
98
99 m_sosHandle = LoadModule(services, MAKEDLLNAME_A("sos"));
100 }
101 }
102 }
103
104 void *
105 LoadModule(LLDBServices *services, const char *moduleName)
106 {
107 std::string modulePath(g_coreclrDirectory);
108 modulePath.append(moduleName);
109
110 void *moduleHandle = dlopen(modulePath.c_str(), RTLD_NOW);
111 if (moduleHandle == NULL)
112 {
113 services->Output(DEBUG_OUTPUT_ERROR, "dlopen(%s) failed %s\n", modulePath.c_str(), dlerror());
114 }
115
116 return moduleHandle;
117 }
118};
119
120bool
121sosCommandInitialize(lldb::SBDebugger debugger)
122{
123 lldb::SBCommandInterpreter interpreter = debugger.GetCommandInterpreter();
124 interpreter.AddCommand("sos", new sosCommand(NULL), "Various coreclr debugging commands. See 'soshelp' for more details. sos <command-name> <args>");
125 interpreter.AddCommand("bpmd", new sosCommand("bpmd"), "Creates a breakpoint at the specified managed method in the specified module.");
126 interpreter.AddCommand("clrstack", new sosCommand("ClrStack"), "Provides a stack trace of managed code only.");
127 interpreter.AddCommand("clrthreads", new sosCommand("Threads"), "List the managed threads running.");
128 interpreter.AddCommand("createdump", new sosCommand("CreateDump"), "Create a xplat minidump.");
129 interpreter.AddCommand("clru", new sosCommand("u"), "Displays an annotated disassembly of a managed method.");
130 interpreter.AddCommand("dumpasync", new sosCommand("DumpAsync"), "Displays info about async state machines on the garbage-collected heap.");
131 interpreter.AddCommand("dumpclass", new sosCommand("DumpClass"), "Displays information about a EE class structure at the specified address.");
132 interpreter.AddCommand("dumpdelegate", new sosCommand("DumpDelegate"), "Displays information about a delegate.");
133 interpreter.AddCommand("dumpheap", new sosCommand("DumpHeap"), "Displays info about the garbage-collected heap and collection statistics about objects.");
134 interpreter.AddCommand("dumpil", new sosCommand("DumpIL"), "Displays the Microsoft intermediate language (MSIL) that is associated with a managed method.");
135 interpreter.AddCommand("dumplog", new sosCommand("DumpLog"), "Writes the contents of an in-memory stress log to the specified file.");
136 interpreter.AddCommand("dumpmd", new sosCommand("DumpMD"), "Displays information about a MethodDesc structure at the specified address.");
137 interpreter.AddCommand("dumpmodule", new sosCommand("DumpModule"), "Displays information about a EE module structure at the specified address.");
138 interpreter.AddCommand("dumpmt", new sosCommand("DumpMT"), "Displays information about a method table at the specified address.");
139 interpreter.AddCommand("dumpobj", new sosCommand("DumpObj"), "Displays info about an object at the specified address.");
140 interpreter.AddCommand("dumpstack", new sosCommand("DumpStack"), "Displays a native and managed stack trace.");
141 interpreter.AddCommand("dso", new sosCommand("DumpStackObjects"), "Displays all managed objects found within the bounds of the current stack.");
142 interpreter.AddCommand("eeheap", new sosCommand("EEHeap"), "Displays info about process memory consumed by internal runtime data structures.");
143 interpreter.AddCommand("eestack", new sosCommand("EEStack"), "Runs dumpstack on all threads in the process.");
144 interpreter.AddCommand("gcroot", new sosCommand("GCRoot"), "Displays info about references (or roots) to an object at the specified address.");
145 interpreter.AddCommand("ip2md", new sosCommand("IP2MD"), "Displays the MethodDesc structure at the specified address in code that has been JIT-compiled.");
146 interpreter.AddCommand("name2ee", new sosCommand("Name2EE"), "Displays the MethodTable structure and EEClass structure for the specified type or method in the specified module.");
147 interpreter.AddCommand("pe", new sosCommand("PrintException"), "Displays and formats fields of any object derived from the Exception class at the specified address.");
148 interpreter.AddCommand("syncblk", new sosCommand("SyncBlk"), "Displays the SyncBlock holder info.");
149 interpreter.AddCommand("histclear", new sosCommand("HistClear"), "Releases any resources used by the family of Hist commands.");
150 interpreter.AddCommand("histinit", new sosCommand("HistInit"), "Initializes the SOS structures from the stress log saved in the debuggee.");
151 interpreter.AddCommand("histobj", new sosCommand("HistObj"), "Examines all stress log relocation records and displays the chain of garbage collection relocations that may have led to the address passed in as an argument.");
152 interpreter.AddCommand("histobjfind", new sosCommand("HistObjFind"), "Displays all the log entries that reference an object at the specified address.");
153 interpreter.AddCommand("histroot", new sosCommand("HistRoot"), "Displays information related to both promotions and relocations of the specified root.");
154 interpreter.AddCommand("soshelp", new sosCommand("Help"), "Displays all available commands when no parameter is specified, or displays detailed help information about the specified command. soshelp <command>");
155 return true;
156}
157