---
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
卻出現以下錯誤

叫我再下 `make mrproper`,就照著下一次就能正常 make 了
用 gdb 開,的確有 symbol
對於這邊 code 有興趣

可以直接對此檔案的第幾行下斷點,得知這行 C 對應的 address 在哪

### Run qemu with this kernel
將 Qemu 的 kernel 參數調為剛剛 make 好的 kernel
並且多給參數 `-s` 和 `-S` 後就 run 他
開啟 gdbserver,listen 於 port 1234
中斷著,等待 gdbclient 連進操作

### Tracing with IDA pro & gdb & radare2
IDA pro x32 開起來,選取 Debugger -> Attach -> Remote GDB debugger

設定好 IP 和 port
我的環境是 Ubuntu VM 開 QEMU,Windows VM 開 IDA pro
兩個 VM 連在同一個網段

點選 Debug options -> Set specific options
Processor 選 MIPS,endian 選 Big endian
OK

繼續點 OK

來到這個畫面

0xBFC0xxxx 開頭的 address 應該是 boot loader 的
先一直 F8 執行下去

來到開頭是 0x80xxxxxx,應該是 kernel
用 gdb 看一下這個位置的 code 是...

因為前面編譯 kernel 有把 debugging symbol build 進去
現在才看得到他的 function name 是 kernel_entry
不過 gdb 的 disassembler 只適用 x86
gdb 在這裡 disassemble 出來的組語不能參考
不過用 radare2 就沒這個困擾

想看看 init_post() 中的 call run_init_process() 位置在哪

就先 `s sym.init_post` 到 init_post() 的位置
接著 `pdf` 列出這個 function 的 assembly code

看來位置確定了,第一個 call run_init_process() 位置是 0x8011690C
回到 IDA pro 這邊下斷點

F9 按下去
此時來到斷點
先看看 qemu 畫面卡在這

IDA pro 畫面

F7 步入進去看看
同時 radare2 這邊的靜態分析也跟過去看看

看來是一個 call kernel_execve 的 wrapper
kernel_execve 呼叫了 syscall

syscall 前,所有 register 的值如圖

F7 跑下去,就 GG 了

查了一下 [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

Line 38 註解起來
### Tracing again
開 radare2 找找辣個 call run_init_process() 在哪
先下 `aa` 指令讓 r2 跑分析
我想位置應該不會差太多吧
就先跳到 0x8011690C
再下 `pdf` print function 看看
果然位置沒差太多,在 0x801168F8 就找到第一個 call run_init_process() 了

下斷點在此,然後 F9 執行到這邊暫停
接著 step into 看看,再度來到 syscall 面前
這次的 registers 狀況如下

$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 如下

不過這次 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>