=========== OpenSolaris virtual memory system, continued ================ Last time we started looking as the page fault handling process in OpenSolaris. Consider its illustration Fig. 9.8 (p. 475). We started looking at the "struct as", described on pp. 468--469, off of which "struct seg"s are hanging (see Chapter 9.5). This design is the same for *all* address spaces and accomodates all kinds of memory page, disk block, or device-specific memory mappings. Have a look at as_segat(), which is called by many functions to locate the segment a virtual address belongs to: http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/uts/common/vm/vm_as.c#as_segat Suggestion: explore interactions of mmap, file open/read/write, /dev/zero and /dev/null with the VM system. Pp. 467 & 470 provide some examples, see also mmap-cat.d, its output mmap-cat.trace, and the related cat.truss and pmap-cat.txt. On the algorithmic side, look at as_findseg(), as_addseg(), and as_verify() in the same file. Observe the "a_seglast" optimizaton (also used by as_segat()) in as_findseg() and the preceding comment at line 347. Suggestion: observe the uses of as_findseg(): http://src.opensolaris.org/source/search?refs=as_findseg&path=%2Futs%2F&project=%2Fonnv . Ignore for now the SPARC and the XPV (Xen Hypervisor) uses. Read Ch. 9.5 on segment drivers carefully. This "object-oriented" programming pattern of "method tables" is very common in the OS programming. It is exemplified by lines 118--145, and then 213--240: http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/uts/common/vm/seg.h More discussion: p. 479, table 9.4. Suggestion: find where in the OpenSolaris code the s_ops structures for the "segment drivers" in table 9.4 are initialized. Another (and even more fundamental) example of this pattern in the Virtual File System (VFS) design: http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/uts/common/sys/vnode.h#123 In particular, observe the "struct vnodeops", defined with the help of macros in http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/uts/common/sys/vnode.h#785 See also the comment on line 896. Suggestion: Find the initialization of the vnodeops structures for various filesystems such as /proc, and a few points where the specific operation such as "open" or "read" is dispatched to the actual driver's "worker" function from the VFS abstraction layer. ================ Object-Oriented Programming Revealed ================== Incidentally, this pattern is the essence of what they call "virtual functions" in "OO", i.e., the mechanism that makes C++ code like Base *p; p = a_list_of_classed_derived_from_base.first(); while( *p ){ p->foo(); p = p->next(); } call the class-appropriate implementation of foo() for each instance that p points at, even when p points to an instance of a derived class. This "magic" is due to the one-per-class vtable structure that every instance of a Base class or a derived from Base class points to (via a hidden pointer). Through this table pointer the right method code is chosen, via a hidden dereference like p->_vtable[offset_of_foo]() generated for every p->foo() C++ call. More info: http://www.programmers-corner.com/tutorial/36 (It's amazing how hard it has become to find actual useful information about this among all the "we'll sell you REAL C++ INTERVIEW QUESTIONS!" sites. Needless to say, most of these are useless and/or wrong). For a hacker perspective (clear, concise, to the point): http://doc.bughunter.net/buffer-overflow/cpp-vptrs.html A lot more info (this is the seldom-taught *essence* of C++): http://www.parashift.com/c++-faq-lite/virtual-functions.html ================= Direct and reverse page mapping ====================== It is kept consistent in "struct htable" with the actual page tables (on x86 pointed to by the special register %cr3, which is a part of the hardware implementation of "context"): http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/uts/i86pc/vm/htable.h#htable_t More details: "Solaris x86 internals", p. 120. Suggestion: explore a process' page tables in MDB ("mdb -k", ::htables, ::ptable, ::pte, ::vtop, ::vatopfn) "cat" is a good candidate, because it is simple and conveniently blocks on input :-) How the debugger walks these structures: http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/cmd/mdb/i86pc/modules/unix/i86mmu.c#do_va2pa (not that this is MDB code, not kernel code!) ================ Dynamic linking ======================================== A short Linux example, very much like the one we had in class: http://www.linuxforums.org/misc/understanding_elf_using_readelf_and_objdump_3.html Detailed info on ELF dynamic linking: http://www.iecc.com/linker/linker10.html (from the BEST and ONLY accessible book on the subject, http://www.iecc.com/linker/) Class example commands: To observe the .plt section of "ls": # which ls # objdump -d `which ls` | less Search for "call" instructions in the file, and you will see that they point into the PLT section. The "jmp *" instructions in the PLT start every function stub, and go through the GOT section, which is an array of code pointers, and initially points each jump right back to the next intruction, "push ". The unconditional jump to the very first stub in the PLT actually leads into the Dynamic Linker "ld.so" specified in the .interp section. This dynamic linker consumes the pushed argument and will located the address of the required library function by name (referred throught the in .dynsym and .dynstr sections). Next time, the GOT entry at will be already set to the entry point of the actual library function, bypassing the stub. To locate the .got section (recall that on x86 it is disgustingly little-endian): # objdump -s `which ls` | less +/.got Suggestion: Find and read the .dynsym and .dynstr sections. A symbol table (such as .dynsym) consists of fixed-width entries that reference the "string tables" (such as .dynstr). For the format of these entries: http://www.muppetlabs.com/~breadbox/software/ELF.txt (search for the "String Table" and "Symbol Table" sections). Reminder: An overview of the ELF file structure: # readelf -a `which ls` | less