---
# System prepended metadata

title: 底層機制遊記 MIPS 篇
tags: [底層, ' MIPS']

---

---
title: 底層機制遊記 MIPS 篇
description: 現在還太菜，看的資料還不夠多到可以系統化，所以寫遊記，意思就是隨意寫寫的
tags: 底層, MIPS
lang: zh_tw
---

# 底層機制遊記 MIPS 篇
[TOC]

## BootLoader
### Where to start?
> MIPS 的 CPU 在复位后，会从 CPU 地址的 0xbfc00000 开始执行，也就是总线地址的 0x1fc00000。
> [name=註一]

從這段話，以及實際觀察可得知，MIPS 是從 0xbfc00000 開始執行

參考註一，可以知道 MIPS 將 Memory 分了幾段，其中:
- kseg0 : 0x80000000 ~ 0x9FFFFFFF (經過緩存)
- kseg1 : 0xA0000000 ~ 0xBFFFFFFF (不經過緩存)

而這兩段又直接線性 Map 到 0x00000000 ~ 0x1FFFFFFF

0xbfc00000 對應到 0x1fc00000 是這樣來的

## Practice
我想試試看 building kernel with debugging symbols
看是否至少有 function 名稱可以讓我下斷點
試圖追到 kernel 執行到 filesystem 中的初始程式例如 /sbin/init

參考了 [linux系统/sbin/init执行过程](https://blog.csdn.net/skyflying2012/article/details/9734259)
> head.S ===> start_kernel ===> rest_init ===> cpu_idle和内核线程init ===》init_post ===> /sbin/init
> 

最終在 init/main.c 中找到 init_post(void) 有 call run_init_process("/sbin/init")

以下紀錄我實際做的事情
(建立於 [之前測試過的 DSL-2750B](https://hackmd.io/CMDTAT_vRqqw0_8XAjhs8A#D-Link-DSl-2750B) 基礎之上)

### Build Kernel with debugging symbols
基於 [之前改 kernel 的經驗](https://hackmd.io/BLdosVfXTfqL-3Afph43Wg) 是參考 [firmadyne github](https://github.com/firmadyne/kernel-v2.6.32#big-endian-mipseb)
我這次目標是 mips big-endian 架構
在 `cp config.mipseb build/mipseb/.config` 之前先修改了 `config.mipseb`
將 `CONFIG_DEBUG_INFO=y` 寫進去，目的是方便之後靜態分析，能清楚知道這 function 是啥
之後照著 README 去 make
卻出現以下錯誤
![](https://i.imgur.com/3Cuofpx.png)

叫我再下 `make mrproper`，就照著下一次就能正常 make 了

用 gdb 開，的確有 symbol

對於這邊 code 有興趣
![](https://i.imgur.com/d733F6v.png)

可以直接對此檔案的第幾行下斷點，得知這行 C 對應的 address 在哪
![](https://i.imgur.com/36iPKNl.png)


### Run qemu with this kernel
將 Qemu 的 kernel 參數調為剛剛 make 好的 kernel
並且多給參數 `-s` 和 `-S` 後就 run 他
開啟 gdbserver，listen 於 port 1234
中斷著，等待 gdbclient 連進操作
![](https://i.imgur.com/rzlQ1Qy.png)

### Tracing with IDA pro & gdb & radare2
IDA pro x32 開起來，選取 Debugger -> Attach -> Remote GDB debugger
![](https://i.imgur.com/0B7189v.png)

設定好 IP 和 port
我的環境是 Ubuntu VM 開 QEMU，Windows VM 開 IDA pro
兩個 VM 連在同一個網段
![](https://i.imgur.com/IWk2a6y.png)

點選 Debug options -> Set specific options
Processor 選 MIPS，endian 選 Big endian
OK
![](https://i.imgur.com/lGUEAVB.png)

繼續點 OK
![](https://i.imgur.com/EDQ1o1G.png)

來到這個畫面
![](https://i.imgur.com/UgWrm8R.png)

0xBFC0xxxx 開頭的 address 應該是 boot loader 的

先一直 F8 執行下去
![](https://i.imgur.com/NCBQb4V.png)

來到開頭是 0x80xxxxxx，應該是 kernel

用 gdb 看一下這個位置的 code 是...
![](https://i.imgur.com/WYLFLNW.png)
因為前面編譯 kernel 有把 debugging symbol build 進去
現在才看得到他的 function name 是 kernel_entry
不過 gdb 的 disassembler 只適用 x86 
gdb 在這裡 disassemble 出來的組語不能參考

不過用 radare2 就沒這個困擾
![](https://i.imgur.com/kuHNZpW.png)

想看看 init_post() 中的 call run_init_process() 位置在哪
![](https://i.imgur.com/JrHdg8b.png)

就先 `s sym.init_post` 到 init_post() 的位置
接著 `pdf` 列出這個 function 的 assembly code
![](https://i.imgur.com/tqD3w9Q.png)

看來位置確定了，第一個 call run_init_process() 位置是 0x8011690C

回到 IDA pro 這邊下斷點
![](https://i.imgur.com/FOcp3mA.png)

F9 按下去
此時來到斷點
先看看 qemu 畫面卡在這
![](https://i.imgur.com/Bocjul4.png)
IDA pro 畫面
![](https://i.imgur.com/KmqRT9h.png)

F7 步入進去看看
同時 radare2 這邊的靜態分析也跟過去看看
![](https://i.imgur.com/xYCWx62.png)
看來是一個 call kernel_execve 的 wrapper

kernel_execve 呼叫了 syscall
![](https://i.imgur.com/M1LVS34.png)

syscall 前，所有 register 的值如圖
![](https://i.imgur.com/KhUtcPM.png)

F7 跑下去，就 GG 了
![](https://i.imgur.com/08A0RJ7.png)

查了一下 [MIPS syscall table](https://courses.missouristate.edu/KenVollmar/MARS/Help/SyscallHelp.html)

發現根本不存在編號 0x00000FAB 的 Syscall，難怪會爆

那為何 $v0 會變成 0x00000FAB ? 有可能的變因有
- 用 IDA pro 在 debug
    可是去掉 `-s -S` 的 Qemu 參數後，一樣爆掉，所以應該不是這個緣故

那就只能是因為
- compile 時加入了 debugging symbol 

### Run qemu with original kernel
![](https://i.imgur.com/nWgDiwz.png)
Line 38 註解起來

### Tracing again
開 radare2 找找辣個 call run_init_process() 在哪
先下 `aa` 指令讓 r2 跑分析

我想位置應該不會差太多吧
就先跳到 0x8011690C
再下 `pdf` print function 看看
果然位置沒差太多，在 0x801168F8 就找到第一個 call run_init_process() 了
![](https://i.imgur.com/bx1dgQn.png)

下斷點在此，然後 F9 執行到這邊暫停
接著 step into 看看，再度來到 syscall 面前
這次的 registers 狀況如下
![](https://i.imgur.com/Z9rcn7F.png)

$v0 還是 0x00000FAB
再度報銷

why ????

還是原本這 file-system 就是爆掉的 ?

好沒關係換一個看看

### Testing other file-system
這次測試 [DAP-2360](https://hackmd.io/CMDTAT_vRqqw0_8XAjhs8A#D-Link-DAP-2360_REVA_FIRMWARE_112B073) 看看

kernel 都一樣，都是 MIPS big-endian，就直接斷點斷在 0x801168F8

一樣來到 syscall 前

registers 如下
![](https://i.imgur.com/ubOGseH.png)

不過這次 F7 執行這 syscall 沒死掉，順利地跑起來了

?????

why XDD ????

而且這時我才注意到
call syscall 之前是 `li $v0, 0xFAB` 啊
那編號 0xFAB 的 syscall 到底是?

後來發現我一開始查的 [table](https://courses.missouristate.edu/KenVollmar/MARS/Help/SyscallHelp.html) (註7.) 好像不是要查這個歐
是要查這個 [table](https://w3challs.com/syscalls/?arch=mips_o32) (註8.)

**原來編號 0xFAB 的 syscall 是 execve RRR**

那... 我想繼續 Trace 這個 `/sbin/init` 勒?

## References
1. [AR/QCA SPI 启动原理和 ART 地址定位原理](https://e-mailky.github.io/2017-11-29-mips-ar-qca)
2. [linux系统/sbin/init执行过程](https://blog.csdn.net/skyflying2012/article/details/9734259)
3. [github: firmadyne/kernel-v2.6.32](https://github.com/firmadyne/kernel-v2.6.32)
4. [Using IDA's GDB debugger with QEMU emulator](https://www.hex-rays.com/products/ida/support/tutorials/debugging_gdb_qemu.pdf)
5. [yet another radare2 cheatsheet.md](https://gist.github.com/williballenthin/6857590dab3e2a6559d7)
6. [radare2 Print Modes](https://radare.gitbooks.io/radare2book/basic_commands/print_modes.html)
7. [MIPS syscall functions available in MARS](https://courses.missouristate.edu/KenVollmar/MARS/Help/SyscallHelp.html)
8. [Linux Mips o32 syscall](https://w3challs.com/syscalls/?arch=mips_o32)

<style>
/* fix mathjax rwd scroll
 * #Research-direction > simple model
 */
ul > li > .mathjax {
    width: 100%;
    overflow-x: scroll;
    overflow-wrap: break-word;
    display: inline-block;
}

/* Dark mode */

/* <!-- todo: fix highlight.js blocks; some code blocks do not render correctly --> */

body {
    background-color: #23272a !important;
}

.ui-view-area {
    background: #23272a;
    color: #ddd;
}

.ui-toc-dropdown {
    background-color: #23272A;
    border: 1px solid rgba(255,255,255,.15);
    box-shadow: 0 6px 12px rgba(255,255,255,.175);
}

.ui-toc-dropdown .nav > li > a {
    color: #ccc;
}

.ui-toc-dropdown .nav > .active:focus > a,
.ui-toc-dropdown .nav > .active:hover > a,
.ui-toc-dropdown .nav > .active > a {
    color: #bbb;
}

.ui-toc .open .ui-toc-label {
    color: #777;
}

table * {
    background-color: #424242;
    color: #c0c0c0
}

button,
a {
    color: #64B5F6;
}

a:hover,
a:focus {
    color: #2196F3;
}

a.disable,
a.disable:hover {
    color: #EEEEEE;
}

/* Dark mode code block */
/* Imported from titangene/hackmd-dark-theme */

.markdown-body pre {
    background-color: #1e1e1e;
    border: 1px solid #555 !important;
    color: #dfdfdf;
    font-weight: 600;
}
.token.operator, .token.entity,
.token.url, .language-css .token.string,
.style .token.string {
    background: unset;
}

/* Dark mode alert boxes */

.alert-info {
    color: #f3fdff;
    background: #40788A;
    border-color: #2F7A95;
}

.alert-warning {
    color: #fffaf2;
    background: #936C36;
    border-color: #AE8443;
}

.alert-danger {
    color: #fff4f4;
    background: #834040;
    border-color: #8C2F2F
}

.alert-success {
    color: #F4FFF2;
    background-color: #436643;
    border-color: #358A28;
}

/* Stylized alert boxes */

.alert-danger>p::before {
    content: "❌ Dangerous\A";
}

.alert-warning>p::before {
    content: "⚠ Warning\A";
}

.alert-info>p::before {
    content: "ℹ  Information\A";
}

.alert-warning>p::before,
.alert-danger>p::before,
.alert-info>p::before {
    white-space: pre;
    font-weight: bold;
}

</style>

<style>
/*
 * Visual Studio 2015 dark style
 * Author: Nicolas LLOBERA <nllobera@gmail.com>
 */

.hljs {
  display: block;
  overflow-x: auto;
  padding: 0.5em;
  background: #1E1E1E;
  color: #DCDCDC;
}

.hljs-keyword,
.hljs-literal,
.hljs-symbol,
.hljs-name {
  color: #569CD6;
}
.hljs-link {
  color: #569CD6;
  text-decoration: underline;
}

.hljs-built_in,
.hljs-type {
  color: #4EC9B0;
}

.hljs-number,
.hljs-class {
  color: #B8D7A3;
}

.hljs-string,
.hljs-meta-string {
  color: #D69D85;
}

.hljs-regexp,
.hljs-template-tag {
  color: #9A5334;
}

.hljs-subst,
.hljs-function,
.hljs-title,
.hljs-params,
.hljs-formula {
  color: #DCDCDC;
}

.hljs-comment,
.hljs-quote {
  color: #57A64A;
  font-style: italic;
}

.hljs-doctag {
  color: #608B4E;
}

.hljs-meta,
.hljs-meta-keyword,
.hljs-tag {
  color: #9B9B9B;
}

.hljs-variable,
.hljs-template-variable {
  color: #BD63C5;
}

.hljs-attr,
.hljs-attribute,
.hljs-builtin-name {
  color: #9CDCFE;
}

.hljs-section {
  color: gold;
}

.hljs-emphasis {
  font-style: italic;
}

.hljs-strong {
  font-weight: bold;
}

/*.hljs-code {
  font-family:'Monospace';
}*/

.hljs-bullet,
.hljs-selector-tag,
.hljs-selector-id,
.hljs-selector-class,
.hljs-selector-attr,
.hljs-selector-pseudo {
  color: #D7BA7D;
}

.hljs-addition {
  background-color: #144212;
  display: inline-block;
  width: 100%;
}

.hljs-deletion {
  background-color: #600;
  display: inline-block;
  width: 100%;
}
</style>