home *** CD-ROM | disk | FTP | other *** search
- GDT.EXE -- An OS/2 Global Descriptor Table Debugger
- (may also be used to wrap fish or clean baseboards)
-
- "To tell you the honest truth, I get a little
- uneasy at the thought of device drivers by the
- masses."
- -- Noel J. Bergman
- CIS PCmagnet, 25-Oct-1988
-
- "Protected mode? What protected mode?"
- -- Ross Nelson
- BIX os.2/kernel #909
-
- GDT.EXE (version 0.30103) walks through the 286 protected-mode
- Global Descriptor Table (GDT) as used by OS/2. It relies on a small
- device driver, DEVHLP.SYS, which must be installed in your CONFIG.SYS
- file (device=devhlp.sys). DEVHLP.SYS is an OS/2 device driver that
- allows normal OS/2 Ring 3 applications (like GDT.EXE) to make DevHlp
- calls. (DEVHLP.SYS has been undergoing changes, so you should use
- the version of DEVHLP.SYS found in GDT.ARC, even if you already have
- a version of DEVHLP.SYS.)
-
- GDT.EXE comes with a state-of-the-art graphical windowed
- user-interface. Just kidding! (Perhaps) it _should_ come with such
- an interface, but actually GDT.EXE works more like EDLIN or DEBUG.
-
- To print out the entire GDT, just type W (and a carriage
- return), and the programs does a "walk" through the entire
- table. The display looks like this:
-
- GDT at 11FE80 <limit 05095> <636 entries>
- Type H for help
- $ w
- [seg 0008] 11FE80 <limit 05095> <lar 93> [Writable data]
- [seg 0010] 009BE4 <limit 00043> <lar 83> [Busy TSS gate]
- [seg 0018] 121A88 <limit 01023> <lar 92> [Writable data]
- [seg 0020] 000000 <limit 01023> <lar 93> [Writable data]
- [seg 0028] 1F5A60 <limit 02047> <lar 82> [LDT]
- [seg 0030] 1F5A60 <limit 02047> <lar 93> [Writable data]
- [seg 0038] 1F94A0 <limit 02897> <lar 93> [Writable data]
- [seg 0040] 000400 <limit 00959> <lar 93> [Writable data]
- [seg 0050] 009780 <limit 32501> <lar 93> [Writable data]
- [seg 0060] 009A00 <limit 00071> <lar F1> [Read-only data]
- [seg 0070] 009780 <limit 32501> <lar 90> [Read-only data]
- [seg 0078] 1F1980 <limit 00145> <lar 93> [Writable data]
- ....
-
- [seg] is the segment number in hex. Since the protection level
- is encoded inside the segment number, for each segment number shown
- here, there are another three aliases. The segment numbers shown by
- GDT.EXE are for Ring 0.
-
- The next entry, which looks like 123456, is the 24-bit physical
- address of the base of this segment. (Note that these are 24-bit
- physical addresses, not the 20-bit ones you're used to from DOS.)
- This number is in hex.
-
- In a 286 operating system (and OS/2 is right now very much a 286
- OS, even if you're running it on a 386 machine), a segment can be
- from 0 to 64k bytes long. The offset into the segment of the very
- last byte is indicated by the next entry in GDT.EXE's display, which
- looks like <limit 65535>. This number is in decimal.
-
- Segments can have various attributes, also known as access
- rights. The next entry displays the hex code for a segment's access
- rights, for example <lar 93>. Since this is available using the LAR
- instruction, in GDT.EXE the information itself is called the LAR,
- even though that isn't quite right.
-
- Since few people can be expected to remember that, e.g., E4 is a
- call gate, the next (and last) entry displayed when you do a walk is
- a brief textual description of the segment like "Readable code",
- "Writable data," "Pungent aroma."
-
- One type of segment is so different from the others that it's
- displayed quite differently, however. This is the call gate. (This
- documentation is not intended to teach the workings of the 286. For
- that, turn to a good book on the 286, repeat, 286, not 386 [trying to
- decipher the GDT under OS/2 using documentation for the 386 is a
- mistake; take my word for it], such as Stephen P. Morse and Douglas
- J. Albert, THE 80286 ARCHITECTURE; Ed Strauss, INSIDE THE 80286, or
- Marcel Proust, A LA RECHERCHE DU 286.)
-
- For a call gate, the display looks like this:
-
- <Call gate 0F10:0000> <code 00B0:0B4E> <phys 115AEE> DOSALLOCSHRSEG (5 wds)
- <Call gate 0F18:0000> <code 00B0:0B8A> <phys 115B2A> DOSGETSHRSEG (4 wds)
- <Call gate 0F20:0000> <code 00B0:0BC2> <phys 115B62> DOSGIVESEG (4 wds)
- <Call gate 0F28:0000> <code 00B0:0BF8> <phys 115B98> DOSGETSEG (1 wds)
-
- Rather than display the segment number as [seg 0F10], for a call
- gate the same information is displayed as <Call gate 0F10:0000>. This
- is the address you would get back from calling DosGetProcAddr on a
- DOSCALLS (OS/2 kernel) function. Actually, it's not quite what you
- would get back: 0F10:0000 represents a Ring 0 segment; its Ring 3
- equivalent is 0F13:0000.
-
- The next field, e.g., <code 00B0:0B4E>, shows the code that
- the call gate points to. Note that segment 00B0 (in this case) is
- just another entry in the GDT. (I'll jump ahead of myself and
- tell you that if you just wanted to find out about segment 00B0,
- you could type . b0 [a dot followed by a space followed by B0,
- followed of course by the carriage return].) This other entry had
- better be code, or we're in trouble.
-
- The next field, e.g., <phys 115AEE>, is the 24-bit physical
- address for the first opcode of the code pointed to by the call gate
- in the house that Jack built. (In fact, all this code seems to have
- as its first instruction yet another CALL, so there's even one more
- level of indirection.) This physical address is derived by adding
- together the physical address of the base of segment 00B0 (in this
- case) and the offset given in the call gate itself.
-
- The next field, e.g., DOSGETFRAMIS, represents the name of the
- OS/2 function for which the call gate is the entry point. If the
- name is followed by an asterisk, this indicates that this is either
- a new and/or undocumented function, e.g., DOSICANONICALIZE or
- DOSR2STACKREALLOC.
-
- The final field, e.g., (4 wds), indicates that this function
- expects 4 words (8 bytes) worth of arguments. Of course, this isn't
- such a revelation when you're talking about DOSGETFRAMIS (which,
- as we all know, does in fact take 4 words: WORD, PTR WORD, WORD),
- but it might be useful for someone to know that the undocumented (?)
- DOSQSYSINFO takes 4 words.
-
- The LAR for a call gate is E4, and if you just wanted to display
- all call gates, you could ask GDT.EXE to "search" for them:
-
- $ s e4
-
- Likewise, if you were interested in finding segments marked
- as read-only data, one thing to try would be:
-
- $ s f1
- [seg 0060] 009A00 <limit 00071> <lar F1> [Read-only data]
- [seg 03E0] 1FBE20 <limit 00481> <lar F1> [Read-only data]
-
- Now, segment 0x60 is sort of interesting: it's the global
- information segment maintained by OS/2 (so far most of the data
- structures we've been looking at are pure 286, having little or
- nothing to do with OS/2 per se, but this one is certainly an OS/2
- data structure).
-
- To actually look at the bytes in segment 0x60, we can once
- again rely on the intuitive user-friendly interface of GDT.EXE.
- In this case, use the ? command:
-
- $ ? 60
- [seg 0060] 009A00 <limit 00071> <lar F1> [Read-only data]
- 009A00 55 97 AD 23 84 2A 7B 00 17 39 09 03 FF FF 36 01 U...............
- 009A10 13 0C C4 07 01 0A 0A 00 05 10 05 01 09 00 01 03 ................
- 009A20 20 00 F8 00 01 00 00 00 00 00 00 00 00 00 00 00 ................
- 009A30 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
- 009A40 00 00 00 00 00 00 10 .......
-
- You can continually type ? x60 at the $ prompt (or, if you have
- the ALIAS command-line editor, you can just press the up-arrow key),
- and each time you display the GIS it will be a little different, since
- OS/2 updates the time kept in the GIS.
-
- One can use the ? command to display any segment. However, in
- the case of a call gate, it won't do you much good since (a) it's
- code you want, and (b) in a call gate the fields are all mixed up.
- Therefore, GDT.EXE provides the U command (for unassemble).
-
- Actually, it's not GDT.EXE that provides this -- I wouldn't know
- where to begin to write an unassembler, so CodeView (CVP.EXE) is run
- as a child process. In the case of the call gate:
-
- <Call gate 0F10:0000> <code 00B0:0B4E> <phys 115AEE> DOSALLOCSHRSEG (5 wds)
-
- you would issue the command:
-
- $ u 00b0:0b4e
-
- because you want to disassemble the code at 00B0:0B4E (remember, it's
- "just" a call gate at 0F10:0000). GDT.EXE will bring up CodeView
- (which takes quite a while!), and all sorts of trash will be spewed
- out to your screen, including a line like
-
- garbage RET ; BR0
-
- Ignore that! It's just control returning to the debugger, at which
- point it picks up our instruction to unassemble. With most of
- these DOSxxxx call gates, what you'll probably see as the first
- instruction is a line like
-
- garbage garbage garbage CALL 74A0
-
- At the CodeView prompt, you can now type
-
- > u 74a0
-
- and so on. Just q (quit) when you're done. You'll be returned to
- the GDT.EXE $ prompt.
-
- When you tire of GDT.EXE, type q to quit back to OS/2.
-
- Other GDT.EXE commands include:
-
- ! <string> -- run another OS/2 program
- $ ! cd \os2\forth && start forth
- $ ! cd \os2\xlisp && start os2xlisp
- $ ! dir
-
- H -- displays an out-of-date help message
-
- P -- displays bytes at an arbitrary physical address
- $ p b 8000 40
- $ p f e008 100
-
- R -- change radix (radix always entered in decimal)
- $ r 10
- $ r 16
-
- Not-so-blue-sky: Since in GDT.EXE we can manipulate call gates as data,
- we can probably also make them point to our own code, just an interrupt
- handler under MS-DOS. This would be useful for writing front-ends to,
- or replacements for, various DOSxxxx calls. Presumably one would name
- this facility DosSetProcAddr, since we already have DosGetProcAddr.
- Or, since there is VioRegister and KbdRegister, perhaps the facilities
- provided in DEVHLP.SYS could be used to build a DosRegister (not to
- be confused with a bridal registry, by the way). I can think of one
- DOSxxx function that could use a better front-end, for example:
- DosGetProcAddr doesn't accept ASCIIZ names for DOSCALLS; couldn't
- we just write a preprocessor for it, point the call gate at our
- code (presumably fiddling around with protection levels), have our
- code call ("chain_intr," as it were) to the code that the call gate
- originally pointed to? This would also be handy for writing home-brew
- profilers.
-
- -- Andrew Schulman
- 32 Andrew (!) Street
- Cambridge MA 02139
- 617-876-2102 (h)
- 617-577-8500 x7148 (w)
-
- 18 December 1988 // twas the week before Xmas...
- 31 December 1988 // revised: the great new year's eve debug session
-
-
-
-