We can tell qemu to log all interrupts by adding the following line to the qemu command: ```bash -d int -D qemu.log ``` To grep the `qemu.log` file for lines that contain `v=`, which are the lines with interrupt information, but exclude the interrupts 0x20, 0x21, and 0x80, which are too common and fill up the whole log file, use the following command: ```bash grep -P 'v=(?!20|21|80)' qemu.log ``` Here's an example line that the command will output: ```bash 176351: v=0e e=0007 i=0 cpl=3 IP=001b:00401eba pc=00401eba SP=0023:003fefd4 CR2=00000002 ``` - `0176351`: is the count of interrupts so far - `v=0e` is the interrupt vector, `0e` is the page fault interrupt - `e` is the associated error code - `i` is set to 1 if the exception comes from the hardware or an INT instruction - `cpl` is the current privilege level, 0 = kernel mode, 3 = user mode - `IP` and `PC` are the instruction pointer and program counter, i.e. address of the current instruction - `SP` is the stack pointer In this example, the error happened in user mode, at address `00401eba`, and the stack pointer is `003fefd4`. I can then use `objdump` to disassemble the `sh` binary -which was the user-mode binary that was running at the time - and find the instruction at address `00401eba`: ```bash objdump -D -S sh | grep 401eba -A 50 -B 50 ``` - `-A 50` and `-B 50` are used to show 50 lines after and before the address `00401eba` In my case, it was in the `strcat` function, but that does not mean the problem was necessarily caused by this function, of course:

 char *strcat(char *dest, const char *src)
{
  401e90:	83 ec 10             	sub    $0x10,%esp
    char *d = dest;
  401e93:	8b 44 24 14          	mov    0x14(%esp),%eax
  401e97:	89 44 24 0c          	mov    %eax,0xc(%esp)
    while (*d != '\0') {
  401e9b:	eb 05                	jmp    401ea2 strcat+0x12
        d++;
  401e9d:	83 44 24 0c 01       	addl   $0x1,0xc(%esp)
    while (*d != '\0') {
  401ea2:	8b 44 24 0c          	mov    0xc(%esp),%eax
  401ea6:	0f b6 00             	movzbl (%eax),%eax
  401ea9:	84 c0                	test   %al,%al
  401eab:	75 f0                	jne    401e9d strcat+0xd
    }
    while (*src != '\0') {
  401ead:	eb 17                	jmp    401ec6 strcat+0x36
        *d = *src;
  401eaf:	8b 44 24 18          	mov    0x18(%esp),%eax
  401eb3:	0f b6 10             	movzbl (%eax),%edx
  401eb6:	8b 44 24 0c          	mov    0xc(%esp),%eax
  401eba:	88 10                	mov    %dl,(%eax)
        d++;
  401ebc:	83 44 24 0c 01       	addl   $0x1,0xc(%esp)
        src++;
  401ec1:	83 44 24 18 01       	addl   $0x1,0x18(%esp)
    while (*src != '\0') {
  401ec6:	8b 44 24 18          	mov    0x18(%esp),%eax
  401eca:	0f b6 00             	movzbl (%eax),%eax
  401ecd:	84 c0                	test   %al,%al
  401ecf:	75 de                	jne    401eaf strcat+0x1f
    }
    *d = '\0';
  401ed1:	8b 44 24 0c          	mov    0xc(%esp),%eax
  401ed5:	c6 00 00             	movb   $0x0,(%eax)
    return dest;
  401ed8:	8b 44 24 14          	mov    0x14(%esp),%eax
}   }