| 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 | |