The bootobj macroThe bootobj macro is a three-line macro and, reading it, appears to show information about a file system. Here is the macro. Example 12-3 The bootobj macroHiya... cd /usr/kvm/lib/adb Hiya... cat bootobj ./"fstype"16t16C +/"name"16t128C +/"flags"16t"size"16t"vp"n3X Hiya... Unfortunately, unlike the utsname macro, execution of the bootobj macro starts at location " . ", which means the current location. This is an example of a macro that we must call by specifying a symbol name or a new current address where the macro would start its work. The question is: For which file system or file systems was this macro designed to display data? We'll see if we can figure that out shortly. First, let's discuss what this macro does step by step. The first line displays "fstype" for readability, tabs out to the display position that is a multiple of 16, then displays 16 characters . Note, unlike in the utsname macro, we are using an uppercase C modifier instead of the lowercase c . The difference is that the uppercase C says to show the contents of all 128 character positions whether or not they contain printable ASCII characters. When the value stored in memory is not printable, a "control character" representation (such as ^@ for a null byte) is printed instead. The second line advances the current address and displays 128 characters, apparently a name of some sort , judging from the fact that we print "name" before the characters. The last macro command line will generate two lines of output. The first line will have the words "flags" , "size" , and "vp" separated by tabs. The n says to print a newline. The 3X modifier says to display the contents of three full-word addresses in hexadecimal. By default, adb allows for 16 character positions for each full-word hexadecimal value displayed, with a maximum of four full words displayed per line, or 4X if we were speaking in terms of adb modifiers. Knowing this about adb, the macro's author has the "flags" , "size" , and "vp" identifiers similarly tabbed out, using the 16t modifier. So, we now know what the macro does. Next , let's see if we can figure out with which kernel variables this macro was designed to be used. The first place we might look would be the namelist , which we can examine via the UNIX nm command. In this case, we will pipe the output of nm into the UNIX grep command, searching for bootobj or something similar. We are only interested in objects, such as variables and structures, instead of kernel routines and other symbols, so we use grep a second time to print out the nm OBJT matches only. Hiya... nm /dev/ksyms grep -i bootobj grep OBJT Hiya... nm /dev/ksyms grep -i boot grep OBJT [469] 4027923924 52OBJT LOCL 0 ABS bootcode [5034] 4232978432 12OBJT LOCL 0 ABS bootparam_addr [6815] 4027926848 4OBJT GLOB 0 ABS path_to_inst_bootstrap [7229] 4028089244 256OBJT GLOB 0 ABS kern_bootargs [7402] 4028089636 4OBJT GLOB 0 ABS boothowto [7482] 4027920040 4OBJT GLOB 0 ABS bootops [7501] 4028092332 4OBJT GLOB 0 ABS kmacctboot [8707] 4028112416 4OBJT GLOB 0 ABS netboot Hiya... Well, that wasn't very helpful. Next, we will dig through the /usr/include header files. It is probably safe to assume that bootobj has something to do with the booting sequence, so we will dig through the sys subdirectory as a starting point. If that fails to find what we are looking for, we can start the search at /usr/include next time. In this example, we will use the UNIX find command to grep through all of the sys header files. If you aren't familiar with the find or grep commands, please refer to the man pages. Hiya... cd /usr/include/sys Hiya... find . -exec grep -i bootobj {} /dev/null \; ./bootconf.h:struct bootobj { ./bootconf.h:extern struct bootobj rootfs; ./bootconf.h:extern struct bootobj dumpfile; ./bootconf.h:extern struct bootobj swapfile; Hiya... Note The use of /dev/null in the grep command exec 'ed within the find command may have you wondering a bit. If only one filename is given for grep to search, we will not see the name of the file along with the matching strings. We are using /dev/null as nothing more than a second file name. Actually, any filename would have done. Try the same command with and without /dev/null specified, and you'll understand the significance of using it. So, we have found that /usr/include/sys/bootconf.h defines a bootobj structure. We need to read this header file to learn more about this structure. Here is the portion of /usr/include/sys/bootconf.h that talks about the bootobj structure. Example 12-4 Excerpts from /usr/include/sys/bootconf.h/* * Boot configuration information */ #define BO_MAXFSNAME 16 #define BO_MAXOBJNAME 128 struct bootobj { char bo_fstype[BO_MAXFSNAME]; /* vfs type name (e.g. nfs) */ char bo_name[BO_MAXOBJNAME]; /* name of object */ int bo_flags; /* flags, see below */ int bo_size; /* number of blocks */ struct vnode *bo_vp; /* vnode of object */ }; /* * flags */ #define BO_VALID 0x01 /* all information in object is valid */ #define BO_BUSY 0x02 /* object is busy */ extern struct bootobj rootfs; extern struct bootobj dumpfile; extern struct bootobj swapfile; As defined here, bootobj structures consist of 16 characters reflecting a virtual file system type, 128 characters representing an object name, a full-word integer flags value, another integer showing the size in blocks, and finally, a pointer (a full-word value) to a vnode structure declared as *bo_vp . So far, this is right in line with what the bootobj macro will be displaying. Only three structures of type bootobj are declared for use. These are dumpfile, which we have seen earlier, rootfs , and swapfile . These three variables will be in the symbol table. To confirm this, we will quickly grep through nm 's output. Hiya... nm /dev/ksyms grep rootfs [8662] 4027916920 156OBJT GLOB 0 ABS rootfs Hiya... nm /dev/ksyms grep swapfile [1285] 4028028788 4OBJT LOCL 0 ABS nswapfiles [8378] 4027917076 156OBJT GLOB 0 ABS swapfile Hiya... nm /dev/ksyms grep dumpfile [6059] 4027917232 156OBJT GLOB 0 ABS dumpfile Hiya... Note that the sizes of rootfs , swapfile, and dumpfile are each listed as 156. This decimal value represents the size in bytes. Does it fit what we found in the bootobj structure? Absolutely! 16 chars + 128 chars + 3 full words = 16 bytes + 128 bytes + 12 bytes = 156 bytes We are now fairly confident what the bootobj macro was designed to examine. Let's use adb to look at all three variables on a live system Remember, since the bootobj macro starts at the current address, we need to feed the macro a valid starting point. Figure 12-2 Using the bootobj macro against three kernel variables# adb -k /dev/ksyms /dev/mem physmem 1e15 rootfs$<bootobj rootfs: rootfs: fstype ufs^@^@^@^@^@^@^@^@^@^@^@^@^@ rootfs+0x10: name /iommu@f,e0000000/sbus@f,e0001000/espdma@f,40000 0/esp@f,800000/sd@3,0:a^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@ ^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@ ^@^@^@^@ rootfs+0x90: flags size vp 0 0 0 swapfile$<bootobj swapfile: swapfile: fstype ^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@ swapfile+0x10: name ^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@ ^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@ ^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@ ^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@ ^@^@^@^@^@^@^@^@ swapfile+0x90: flags size vp 0 0 0 dumpfile$<bootobj dumpfile: dumpfile: fstype ^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@ dumpfile+0x10: name /dev/dsk/c0t1d0s1^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@ ^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@ ^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@ ^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@ dumpfile+0x90: flags size vp 0 30200 fc2d7604 $q To find out how these structures are initialized and later used, we would have to look at the source code. We have learned a few new concepts by examining the bootobj macro, most importantly, how to attempt to establish what variables the macro was designed to be used with when its execution starts at the current location, " . ". |