管理されているコードの記号デバッグ

最近C++GDBマイクロソフトのCDBを使用してソースデバッグと記号デバッグを考えています。
Principally, I have been mulling over cases when symbolic debugging actually is either the only choice or the better choice over symbolic debugging. In addition, I have been exploring how closely the program flow can be followed given the somewhat limited information obtained from symbols.
Source debugging requires the presence of the source files, which may be numerous, even for a single dll. Symbolic debugging requires the presence of symbols which are output by the compiler/linker and for which there is usually only one file per module. Thus, for someone unfamiliar with the source tree, source debugging may be impractical; and, for those outside of the company, security concerns may make source viewing impossible. In addition, the interaction of the module in question with other modules (as in the case of a driver in an OS) may make the installation of source for only one module difficult (although it seems that the source file could be read in after either the debugger was broken into or the dump file loaded into the debugger).
As an aside, when debugging using the source in GDB, a method can be disassembled into its x86 assembly instructions. However, I have yet to find a similar function in CDB, although given that a method table exists for each object, I am wondering whether the assembly source can be printed. GDB seems to use the symbols for line-by-line correlation to the source, so it seems that, assuming PDB files also have such information, loading a source file given that the method to be investigated is known is a better way to debug than simply using symbols.
In .Net, a dll called sos.dll allows Common Language Runtime information (like the stack, heap, dispatch tables) to be made available to the debugger. The breakpoints are set only after a method is compiled by the Just In Time Compiler. !Name2EE allows an address of a method table to be obtained for a given .NET class. Then, using !DumpHeap -mt, the address of all objects of that class can be obtained. Then using !do on any of these objects provides field information, which can be viewed using !do. !DumpStack displays the stack trace.
Nonetheless, to understand what is going on within a given method, assembly and the register set must be understood. What I have been trying to figure out is how I/O is executed in assembly (writing to some shared memory or I/O register?).