Let's take a slight detour now and verify that the instruction that caused the fault really was bad or, at least, had a bad pointer to work with. This is not necessary to the analysis, but it's a good idea (and a useful exercise) to double-check your conclusions and verify the data you're working with. If you're not clear on the details of how register windows and traps work, this might be a good time to review it before digging into this section. The instruction that faulted was: _tcp_respond+0x20: ld [%o5 + 0x1c], %o5 This is a load instruction, using the value in output register %o5 as a pointer. It will add the constant 0x1c to that address and use the result as the real location in memory which is wants to use. Grabbing a full word from that address, it will load it into output register %o5 , replacing what was there. The instruction, however, faulted: it had a bad address. This means that the register values should remain untouched while a trap takes place, so that, if necessary, the instruction could be redone. Now, where do the output registers get put on the stack? Unfortunately, they don't show up at all! But all is not lost. Recall that a trap will get a new register window and will use only the local registers to save the address of the faulting instruction. So, the input registers for the trap frame itself are actually untouched; they contain the values that they had before the trap occurred. What are these registers in the new trap frame? These input registers are, in fact, the output registers of the preceding register window! So in this case, we can locate the value in register %o5 by looking in register %i5 of the trap frame itself. We'll show you the frame again, since it's so far back there. 0xfd002d68: 48001c3 f001c770 f001c774 40 7 8 7 fd002d68 805908d9 805908d9 f018c400 63 89b 3c06915b fd002e10 f001cac0 0xfd002d68: 0x48001c3 _tcp_respond+0x20 _tcp_respond+0x24 0x40 7 8 7 0xfd002d68 0x805908d9 0x805908d9 _arptab+0x2660 0x63 0x89b 0x3c06915b 0xfd002e10 _tcp_close+0x7c The eight locals are printed first, so the value in %i5 (the 14th number printed) would be 0x3c06915b. According to the instruction, we take this value, add the constant 0x1c to it, and use it as the address of a full word in memory. Hey, this is odd ”literally! Trying to pull a full 4-byte quantity from memory starting at an odd address is illegal: it violates the alignment requirements for full-word values, which state that these must be on even 4-byte boundaries. Well, it looks like the CPU was right when it took a memory address alignment trap. This is a very bad address to use for a full-word pointer. |