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 | |
10 | class sosCommand : public lldb::SBCommandPluginInterface |
11 | { |
12 | const char *m_command; |
13 | void *m_sosHandle; |
14 | |
15 | public: |
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 | |
120 | bool |
121 | sosCommandInitialize(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 | |