Using Intel DCI on ISS to debug UEFI module
Tags: dci, debug, iss, tutorial
Published: 2022-07-26 11:09:51

In the previous post, I explained what is Intel DCI and how to setup Intel System Debugger (ISS). In this post, I'll explain how to use ISS to debug UEFI modules. Usage is not really different from other debugger, but it's good to see examples to get the image what it is like.


## Breaking at target UEFI module
First of all, there are lots of UEFI modules running in the bootphase. Considering this, the easiest way to break at the UEFI module you want to debug is to **put dead-loop at the top of the module**. You can just put `EB FE` at the place you want to break and the execution will stop there. Then, you can use "Move To Line" to exit dead-loop.
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ljzxffn893mudnxef3qm.png) 


## Unstable DCI Problem
In some platform or BIOS, DCI maybe unstable. For example, if you suspend the machine, put breakpoint somewhere and resume, then the ISS will say that the system is already running. Also there might be cases, DCI connection resets repeatedly. Several reasons for unstable DCI connection are stated in the Intel System Debugger manual's "Limitation of JTAG Debugging" section which can be found at `IntelSWTools/system_studio_2020/documentation_2020/en/debugger/system_studio_2020/system_debugger/system_debug/User_Guide.pdf`. But I think most of the cases is because of **WatchDog Timers (WDT)**. This timer checks platform's "heartbeat" condition, and if the "heartbeat" is stopped, platform will reset. Debugger stops execution so WDT will think something went wrong and makes platform resets, which closes the DCI connection. Therefore, you might want to **disable WDT** if your DCI connection is unstable.


## Preparing desired window in ISS
You can get your desired window here.
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vv9jengvcphg29rg4ef4.png) 


## Connect/Disconnect/Resume/Suspend/Reset/Debug
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l1bzgmx3g2jfwc5b6nap.png)
 


## Breakpoints

### Software Breakpoint
You can just double click the narrow space next to the address you want to set a software BP like below (the red square). You can see the list of BPs in the Breakpoints window.
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kbj2pxkf3m4enqrutqai.png)

### Hardware Breakpoint
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vp9kth9uqo63ka3i6z26.png)

### Memory Breakpoint (Watchpoint)
There are no such thing called *Memory Breakpoint* in ISS, but you can use ISS's special BP called Watchpoint to do similar thing. To add Watchpoint, press the below red squared button.
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mmeocnq7epimvx2sn22o.png)
If you want to break when there was a write on the address `0xcafebabe`, you can set it like below.
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cu0z6r935h7db6hhxlpo.png)
As you can see, you can also use Watchpoint to break on read, and also specify address with range.


## Modifing Registers
You can just double click to change value like this in the Registers window.
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7s24phjznkqc5rzfv5mm.png)


## Memory Browser (Hex View)
You can use Memory Browser window to check hex view around specified address.
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2q2gepg71nqbvtdzbux2.png)
You can change the cell size like below.
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bl87zvne9jl71qprnwgm.png)
I couldn't find Stack view in ISS, but you can put rsp value in this Memory Browser to see the stack instead.


## ISD Shell (Python Scripts)
You can use ISD Shell to automate operations by python scripts. However, I couldn't find any documentation explaining about the API, so I refered the source code in `C:\IntelSWTools\system_studio_2020\tools\` to find out objects or functions, and also used python functions like `dir(Object)` to check what methods are in that object. I'll leave some of the codes that I used personally, just to get the image how the code will look like.
```python
# Writing value 1 to MSR 0x1d9
threads[0].msr.write(0x1d9, 1)

# Setting 0x7764e7d7 to RIP
next(r for r in threads[0].registers.list() if r.name=="rip").set(0x7764e7d7) 

# Resume
threads[0].runcontrol.resume()
```


## Trace

### LBR Trace
**LBR (Last Branch Record)** is a feature of Intel CPU to record branch trace to MSR. This is hardware mechanism and could be easily enabled by setting MSR `IA32_DEBUGCTL (0x1d9)` to 1. [This article](https://sorami-chi.hateblo.jp/entry/2017/12/17/230000) is a good reference to look at about LBR tracing. 

To use LBR Trace in ISS, open Instruction Trace View window, and click the red squared button.
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sp0293pof4setkxzccxs.png)
Then, change the type to "LBR" and click OK.
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k5ha7y6zg00un8vdrecb.png)
After that, click below button to start capturing.
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mgbnhektgjdkmfszjdgn.png)

Now let's try it. Put some BP somewhere and press resume. After you hit the BP, you'll see the results shown like this.
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ol7hjp96y0wfornsegvo.png)
You can maximize the view by clicking above button (Press "Restore" to go back to the original view). 


### Intel Processor Trace (Intel PT)
**Intel PT** stores trace record to memory rather than MSR. Therefore, this could store far more record than LBR *at a time*. But actually, it doesn't really matter because ISS can read LBR and keep the data in the memory of analysis machine.

The **advantages** of using PT is that, PT allows you to configure the trace options more specifically. This is stated in *Intel® System Debugger - System Debug User and Reference Guide*, but in my ISS, somehow there were no place to configure these options...
The **disadvantages** of using PT is that, since PT uses memory to store trace information, it's a bit troublesome to enable it (do below two).
* set MSR `IA32_RTIT_CTL (0x570)` to 1
* enable PT in the BIOS SETUP screen and allocate enough size of memory you need

To use PT in ISS, you only have to select "PT" in this configuration window.
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zupp4smbgdo677t4wurl.png)