Debugging Productio n SharePoin t Applicati ons Wouter van Vugt
Feb 26, 2016
Debugging Production SharePoint
ApplicationsWouter van Vugt
Agenda
• How .NET and the CLR work• Optimizing code and the effect on debuggers• Debugging third party code
HOW .NET AND THE CLR WORK
.NET Applications
• Written in any language• Executed in a runtime called CLR
– Shield code from hardware specifics• Java: One language, multi OS• .NET: Many languages, one OS (and Mono)
– Allows various types of preprocessing of codeOS
CLR
App
Common Language Runtime
Operation
• Memory management• Thread synchronization• Error handling• Type Safety
Security
• Code Access Security• Data Execution
Prevention (OS)• Address Space Layout
Randomization (OS)
Execution • Intermediate Language
Type Safety
• Type Safety– A pointer of a specific type can never point to an
object which is not of that type!
– Checked at compile AND runtime!– Knowing the actual type enables
• Reading its data Quite useful in debugging • Calling its functions
Car c = new Person()
‘Pointer type’ Pointer Object type
TRY AND CIRCUMVENT TYPE SAFETY
Demo
Creating .NET Applications
C#, C++, VB.NET, F#....
(40+)Module
PDB
Compile Link Assembly
PDB
Executing code
• Assemblies contain mostly IL code– IL is the ‘Machine code’ for .NET– Compiled to native instructions at runtime
through the JIT Compiler– Enough information remains to decompile back to
source!
C# Machine Code
Language richness compared
IL
Executing code with JIT CompilationConsole.WriteLine("Hi");Console.WriteLine("There"
);
JIT Compiler- Lookup IL for method- Compile IL to native- Modify metadata to
point to compiled code- Jump to compiled code
Console metadata
static void WriteLine(string)
JIT Compiler Address
static void WriteLine()
JIT Compiler Address
Native CPU Instructions
Native Address
Executing code with JIT CompilationConsole.WriteLine("Hi");Console.WriteLine("There"
);
Console metadata
static void WriteLine(string)
JIT Compiler- Lookup IL for method- Compile IL to native- Modify metadata to
point to compiled code- Jump to compiled code
Native Address
static void WriteLine()
JIT Compiler Address
Native CPU Instructions
Code optimization
• Compile-time– Constant value folding– Remove Branch to next
instruction and NOP instructions used to break on control flow, {, }, EndIf etc
– Overflow checking– …
• During JIT– Eliminate local variables– Range check elimination– Method inlining– Tail call optimization– Common subexpression
elimination– Dead code elimination– Loop unrolling– …
Running non optimized code
• Breakpoints • Edit and continue
C# Compiler – Variable Generation
C# Compiler – Variable Generation
Debug Release
C# Compiler – Inserting NOP
C# Compiler – Inserting NOP
Debug Release
C# Compiler – Branching
C# Compiler – Branching
Debug Release
COMPILE TIME OPTIMIZATIONSDemo
Just In Time Compilation
• Transformation of MSIL to native x86 / x64 / ARM etc
• Can optimize code– Mathematically ensured correctness
• Takes a small performance hit during startupCompiler switch C# IL Code Quality JIT Native Code Quality
/optimize- /debug- Unoptimized Optimized
/optimize- /debug+ Unoptimized Unoptimized
/optimize+ /debug+ Optimized Optimized
NGEN.exe
• JIT Compilation incurs a runtime cost• NGEN pre-compiles MSIL assemblies to
machine code• Runs as a service in the background• Also used by the “.NET Runtime Optimization
Service”
JIT - Local variable eliminationUser user = GetUser(3);PrintUser(user);
PrintUser(GetUser(3));
Before
After
JIT – Range check eliminationstatic int[] _array = new int[10]; static volatile int _i; static void Main(string[] args) {
for (int i = 0; i < _array.Length; ++i) _i += _array[i];
}
static int[] _array = new int[10]; static volatile int _i; static void Main(string[] args) {
int[] localRef = _array; for (int i = 0; i < localRef.Length; ++i)
_i += localRef[i]; }
Before
After
JIT – Method Inliningpublic class Program {
public static int And(int first, int second) { return first & second;
}static void Main(string[] args) {
int i = And(5, 4); }
}
public class Program { static void Main(string[] args) {
int i = 5 & 4; }
}
Before
After
JIT – Tail Call Optimizationstatic void Main(string[] args){ TestTailCallOptimization();}
public static void TestTailCallOptimization(){ string s = "Test"; TailCall1(s);}
static void TailCall1(string s){ Console.WriteLine(s); TailCall2(s);}
static void TailCall2(string s){ Console.WriteLine(s + s);}
Loading non-precompiled assemblies
• Native NGEN images are hard to debug– Remove the NGEN image
– Or, prevent NGEN image from loadingC:\> SET COMPLUS_ZAPDISABLE=1
C:\> NGEN uninstall MyAssembly
Preventing JIT optimization
• Creating debug builds– JIT prevented through compile time attributes
• INI file MyAssembly.ini
• In Visual Studio, on module load after attach
[.NET Framework Debugging Control]GenerateTrackingInfo=1AllowOptimize=0
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.EnableEditAndContinue | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.Default)]
DEBUGGING OPTIMIZED CODEDemo
Debugging code
• PDB files are as essential as code!
• Breakpoints can do way more than break
• Tracing is cheaper than debugging
• IntelliTrace can run in production
PDB Files
• Contain vital debugging information• No PDB? Severely limited debugging experience!• Minimal investment: Symbol server
• Managed PDB files contain– Source file names / line numbers– Local variable names– Alternate streams Used by TFS
Symbol Servers
• Central repository for storing debug symbols• File system based technology• Integrated into Team Foundation and Visual
Studio
Locating debug symbols
• PDB files are located– Same directory as module– Hardcoded path in module– Symbol server cache– Symbol server
MyAssembly.dll MyAssembly.pdb
GUID GUIDEqual
Dumpbin.exe
• Use to peek inside PE files
Prevent loading all PDBs
Visual Studio Source Server support
• Allows Visual Studio to download relevant source files automatically from a repository.
Configuring Symbol Locations
PDB alternate streams
• Used by TFS to store server path to sources
SYMBOL SERVERS, SOURCE SERVERS AND SOURCE INDEXING
Demo
Working with break points
Setting breakpoints on automatic properties
• Use ‘Break at function’ and enter get_name
Setting breakpoints on automatic properties
• Inspect callstack / locals window
Debugging third party code
• Red Gate .NET Reflector PRO– Decompile assemblies into source code– Generate PDB file from assembly + source– Enables debugging third party code
Enabling remote debugging
• Run Remote Debugging x86 or x64• Give permissions• Connect
DEBUGGING SHAREPOINTDemo