1 2 3 4 5 6 7 8 9 10 11 12 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
|
1 2 3 4 5 6 7 8 9 10 |
|
1 2 3 4 5 6 7 8 9 10 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
1 2 3 4 5 6 7 8 9 10 |
|
1 2 3 4 5 6 7 8 9 10 |
|
1 2 3 4 5 6 7 8 9 10 11 12 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
1 2 3 4 5 6 7 8 9 10 |
|
1
|
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
1
|
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
_init
sectiontext
section 開頭symbol 為_start
_start
呼叫__libc_start_main
__libc_csu_init
section__libc_csu_fini
section_fini
section1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 |
|
下面圖片是svg
檔案,需要直接按滑鼠右鍵儲存即可。
gcc hello.c -o hello
中間gcc
幫你執行了哪些指令,以及這些執行指令大概在做什麼。每個指令光要分析都要花不少時間,當作以後的作業吧。
1 2 3 4 5 6 |
|
1 2 3 4 5 |
|
這部份是在連結的時候 gcc
做的事。記得 gcc
全名是 GNU Compiler Collection
,也就是說他不是編譯器,是一個通包的程式。直接列出多連結的檔案,要注意的是在連結時似乎有個順序,所以會多次出現--push-state
-> --as-needed
-> 指定連結函式庫 -> --pop-state
的參數,以後有空再來看這部份。
cc
指令拆解1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
|
as
指令拆解1
|
|
collect2
指令拆解1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
|
ld
指令拆解要注意的是ld
是由collect2
呼叫的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
|
strace
觀察 gcc hello.c -o hello
會呼叫哪些執行檔1 2 3 4 5 6 7 8 9 10 |
|
gcc -v -o hello hello.c
輸出1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 |
|
1 2 3 4 5 6 |
|
1 2 3 |
|
本次設定主要是針對除錯最佳化,以及避免覆蓋系統原本的 glibc
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
本來想說 libc
用來提供 C 標準函式庫的 binary,那麼了不起就是 libc.so
和 libc.a
以及對應的 header files。安裝完畢後先看一下目錄,事情果然沒有像本組裝工想的那麼簡單。列出第一層目錄如下,除了預期中的lib
和include
以外,竟然還有不少預期以外的目錄。
1 2 3 4 5 6 7 8 9 10 |
|
那麼我們來看一下這些目錄下面有什麼東西吧。
先來看目錄結構,多了和多國語言相關的函式庫目錄還有 trace shared object PLT (Procedure linkage table) 工具會用到的audio目錄
1 2 3 4 |
|
接下來看/lib
的檔案
列出幾個我有興趣的檔案
*.o
/lib
裏面會發現幾個object file,它們檔名都有crt
,crt全名是 C runtime
,顯然和執行的時候有關。我有空會再找時間了解。先列出來介紹幾個如下Scrt1.o
: 這邊我們可以看到T _start
以及U main
,望文生義按圖說故事我們可以猜測執行程式的起始點其實是_start
,做了一些事情後才會去呼叫你寫的main()
,我做了一個實驗,想知道一個應用程式會連結哪些系統上的object檔案請參考這邊
1 2 3 4 5 6 7 8 9 10 |
|
crtn.o
: 用nm
去看會發現沒有symbol
,不過反組譯後會發現有兩個section
,看起來和main啟動前和使用者程式結束後會有關係。有空會再探討。1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
ld-linux-x86_64.so.2
ld.so
,這個檔案有趣的點是他是一個shared object,但是同時又是可以執行。如果我的懶病沒有發作以後會常常看到這個東西。libc.*
:
T
, U
的定義請翻前面文章,我懶得找。1 2 3 4 5 6 7 8 9 10 11 12 |
|
libm.*
: 一樣看symbol節錄1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
|
libdl
dlvsym
, dlsym
,1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
|
是除了 ldd
以外,我全部沒印象。有些甚至不在Ubuntu的預設安裝中。使用者需要另外安裝,如xtrace
等。
列出幾個我有興趣的工具
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
ldconfig
外其他的不認識1 2 3 4 5 6 7 8 9 10 11 |
|
很有趣,竟然有rpc
(remote procedure call)的檔案,紀錄rpc通訊協定的資訊。
1 2 3 |
|
跳過
跳過
跳過
1
|
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
1
|
|
1 2 3 4 5 6 7 8 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
gdb 你要的程式
gdb
設常用的 system call
如 open
info proc mappings
dump memory 檔名 開始位址 結束位址
gdb 你要的程式
1 2 3 4 5 |
|
gdb
設常用的 system call
如 open
1 2 |
|
1 2 3 4 5 6 |
|
info proc mapings
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
dump memory 檔名 開始位址 結束位址
1 2 3 4 5 6 7 |
|
1 2 3 4 5 6 7 8 9 10 11 12 |
|
懶的說明ASLR,請自行參考連結。
另外請自行比較下面兩個 cat
的記憶體區塊位址。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
|
hdr
: headerEhdr
: ELF headerEI
: ELF identET
: ELF typeEM
: ELF machinePhdr
: Program headerPT
: Program header typePF
: Prgram header flagShdr
: Section headerSHN
: Section header indexsh_
: Section headerSHT
: Section header typeSHF
: Section header flagst
: Symbol tableSTT
: Symbol table typeSTV
: Symbol table visibilityDT
: Dynamic section typeNT
: Note typeAT
: auxiliary vector typerake
在Ubuntu 無法執行,只好先處理了。
主要的問題是更新後Ruby
版本從16.04使用的2.3
升級成2.5
了。以下是我紀錄過的測試指令,必須承認這是網路上的東西剪貼,我不想知道後面的原理,後果自行負責。寫這篇文章另一個目的是確定上傳到網路上後可以正常發佈才證明真的解決問題了。
1
|
|
1 2 3 |
|
由於更新後rake
版本也從10.5.0
變成12.3.1
,所以一跑rake
就會出現版本不合的錯誤,因此我把Gemfile
rake
的版本檢查改成12
,diff 檔案如下
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
vim
下面使用稍微複雜的字串搜尋取代。故整理這篇以後可以參考。
1 2 3 4 5 6 7 8 9 |
|
Regular express 的特色是他可以match不同的pattern,所以用於搜尋和取代是非常的方便,然而當要把符合條件的字串前面或後面加上字串就會有一個問題,那就是符合的字串要怎麼表示?舉例來說,當我們想要在下面log[mem....]
之後放入test
,要怎麼做到? 這時候我們就可以使用reguler expression
的group
功能了
1 2 3 |
|
group
,一組regex可以指定零到多個group
\(match_patter\)
\0
group
\1
group
\2
group
\3
group
就用上面的訊息當範例吧
1 2 3 |
|
:%s/\(\[mem.*\]\)/\1 test/g
1 2 3 |
|
group
,都插入test
:%s/\(^\[.*\]\) \(\BIOS-e820:\) \(\[mem.*\]\)/\1 test1 \2 test2 \3 test3 /g
1 2 3 |
|
-std=c99
-Wall -Wextra -Werror -Wshadow -Wno-missing-field-initializers -Wstrict-overflow -fno-strict-aliasing
size_t
和ssize_t
差別:s
->signed,當有錯誤時會為-1
#pragma once
可用來取代Header guardvim
的心得,加上使用Vundle plugin管理工具功能配合外部程式碼分享軟體cscope
和ctags
來trace C
語言的程式碼以及編輯Python
程式碼相關設定。
致謝,感謝網友Scott介紹vim register概念,葉闆介紹的tagbar,和Kyle Lin介紹的airline。
2020/Feb/09: 由於vimrc 一直在更新,現在我自己用的.vimrc
會持續地更新在這邊,這邊的文章就當作示範教學了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
|
您需要確認
sudo apt-get install exuberant-ctags cscope
Vundle
是vim plugin 管理工具,他可以透過URL, github, 以及local FS等方式安裝甚至更新Plugin。類似的工具還有不少,我只是挑看到的第一個而已。
Vundle
常用的指令如下,還蠻容易望文生義所以我就不解釋了
:PluginList
:PluginInstall
:PluginClean
:PluginUpdate
安裝方式如下
首先你要下載Vundle
,指令如下
git clone https://github.com/VundleVim/Vundle.vim.git ~/.vim/bundle/Vundle.vim
接下來在你的.vimrc加入下面這段,我是從官方網頁改的,其實只是把他的範例Plugin幹掉並加上分隔線及分隔線內的註解而已
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
|
注意下面列出的這幾行statements,你要新增或移除Plugin就是改這個地方。這些Plugin將會在後面介紹。剛好我要安裝的Plugin都是在GitHub上開發或有mirror。而Vundle
可以用直接指定Plugin 專案在GitHub相對路徑即可安裝。這些描述也是Vundle
載入Plugin 的順序,沒寫對順序有可能有相依問題請自行注意。
例如https://github.com/Yggdroot/indentLine
就寫成Yggdroot/indentLine
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
:PluginInstall
:PluginClean
因為安裝方式已經在上面了,這邊就以介紹為主
先看圖,圖中最下方的那行就是airline,可以顯示一些有用的資訊
由左到右我們可以看到Vim 模式,Git branch 等資訊。以及一些比較特別的符號,這表示我們需要
也就是說,在安裝airline
前要做一些前置動作如下
vim-fugitive
plugin即可取得字型
1
|
|
安裝字型
1
|
|
.vimrc中指定安裝的字型
1
|
|
把下面的資料放入.vimrc
即可
1 2 |
|
當Ident為空白增加以下的Indent 對齊參考資線
注意此Plugin在Ident為tab同時又加上顯示tab字元時自動失效,目前workaround就是顯示tab字元為|
,接下來以.
延伸作為辨別。範例如下:
將trailing space顯示成明顯的紅色
簡單來說,就是把cscope指令對應到Hot key
先列出find部份的指令
1 2 3 4 5 6 7 8 9 |
|
他的使用方法也很簡單,就是先把游標移動到你要查的statement,再按ctrl
+ \
+ c|d|e|f|g|i|s|t 其中一個
。
舉例來說,我在下圖中把游標移動到core_sys_select
函數後按下ctrl
+ \
+ c
的結果如下
當啟動時,您的游標在那個敘述,Source explorer 會切割視窗,印出該敘述的定義。舉例來說,當我游標在138行的free_poll_entry
的話,顯示的畫面如下。
列出目前檔案所有symbol並且可以選擇symbol切換到該symbol在檔案中的位置
以樹狀顯示目前檔案所在目錄結構,看圖就知道
看完以上三個,你可能會覺得奇怪好像沒提到怎麼啟動。這就是Trinity
大顯身手的地方了。你安裝Trinity後,再Vundle後面加上下面的敘述就可以有
F8
: 同時打開或關閉nerdtree
, Source explorer
, 以及tag list
F9
: 打開或關閉Source explorer
F10
: 打開或關閉tag list
F11
: 打開或關閉nerdtree
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
以下是按下F8
的畫面
網友推荐的taglist改良版 plugin,為什麼不換掉taglist呢?因為我喜歡source explorer。除了安裝Plugin外,我也順便設定按下F7
可以切換,設定如下。
1 2 3 4 5 |
|
以下是按下F7
的畫面,可以注意右邊視窗會更進一步地顯示資料結構的成員名稱
單純就是讓vim
可以顯示Markdown
syntax highlight,範例如下圖:
主要是語法檢查套件相關安裝,指令如下
1
|
|
之前有介紹過,偷懶跳過。也許Python用到一陣子可以上手後可以再分享心得。
泛用形語法檢查工具,請參考Syntax checking hacks for vim說明。
目前是我靠他幫忙檢查寫的程式是否符合PEP8規範,要注意的是Ubuntu 16.04中vim
套件預設只支援Python 3
,要使用vim 編寫Python 2
的朋友請自行估狗。我之前是自行編譯vim
解決的。
語法檢查範例如下圖
讓Python 也可以使用vim
中切換配對的快捷鍵%
提供下列快捷鍵,節錄自Plugin註解:
]t
– Jump to beginning of block]e
– Jump to end of block]v
– Select (Visual Line Mode) block]<
– Shift block to left]>
– Shift block to right]#
– Comment selection]u
– Uncomment selection]c
– Select current/previous class]d
– Select current/previous function]<up>
– Jump to previous line with the same/lower indentation]<down>
– Jump to next line with the same/lower indentation確保你的程式碼符合PEP8的indent規範
以下都加在.vimrc中
,建議加到Vundle
設定結束後以確保可能會用到的Plugin已經啟動
colorscheme koehler
set guifont=Inconsolata\ for\ Powerline\ 32
set hlsearch
set cursorline
set nu
set colorcolumn=80
highlight ColorColumn guibg=#202020
set listchars=tab:»\
\
後面有一個空白set list
效果如下圖
set ts=4
set expandtab
set shiftwidth=4
vnoremap < <gv
vnoremap > >gv
set clipboard+=unnamed
"*
包含vim的unnamed register。白話講就是其他的APP如gedit中滑鼠選字後可以用"*p
貼到vim,同樣的"*y6y
的結果可以貼在其他的APP如gedit上。這部份有vim register
副本,建議到參考資料的副本區一讀。再次感謝Scott大大。1 2 3 4 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 |
|
:PluginInstall
安裝Plugin重新開啟收工cscope -bqkR
ctags -R
舉例來說,你在/tmp/linux-stable目錄下了上面兩個指令。要開啟檔案請在/tmp/linux-stable目錄中指定對應路徑。範例如下
1
|
|
本篇文章主要是解決使用gdb 設Qemu x86_64 模擬執行x86_64 buildroot kernel開機的中斷點時遇到下面的錯誤訊息
Remote 'g’ packet reply is too long:
詳細訊息如下
1 2 3 4 5 6 |
|
bfc90a5621c680000f8b19e8afea944da5c2a469
1 2 |
|
1 2 3 4 |
|
基本上是從這邊衍生出來的,挑幾個重點
-append "root=/dev/vda console=ttyS0"
/etc/inittab
才能在terminal login-S -s
-nographic
git clone https://git.buildroot.net/buildroot
make qemu_x86_64_defconfig
make menuconfig
make linux-menuconfig
make
從OSDev: QEMU and GDB in long mode可以看到可以使用下面指令頂著先(workaround)
disconnect
set arch i386:x86-64
target remote 127.0.0.1:1234
然而作為組裝工,信奉偷懶就是美德,每次要打這麼多指令實在很麻煩。因此我將這些麻煩的方式使用下面的指令自動化
1 2 3 4 5 6 |
|
執行後畫面輸出部份節錄如下
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
由於gdb command file 遇到錯誤就會停下來,所以把上面的指令放到一個檔案中,執行gdb時將會停在continue
這邊,目前懶的找解法了。有興趣的朋友可以自行研究。
1 2 3 4 5 6 |
|
1 2 3 4 |
|
1 2 3 4 5 6 7 |
|
在/etc/inittab
加入下面這行ttyS0::respawn:/sbin/getty -L ttyS0 0 vt100 # GENERIC_SERIAL
1 2 3 |
|
--remote-tab
,打久就開始厭煩想偷懶。後來整理網路上的bash_completion相關資料拼湊一個堪用的版本分享一下。因為我只是想偷懶,所以完全沒有去了解bash_completion的細節。嘛,反正可以組裝需要的功能就好。
1 2 3 4 5 6 |
|
/etc/bash_completion.d/gvim
1
|
|
tab
顯示檔案或目錄1 2 3 4 |
|
tab
就會自動填入--remote-tab
,接下來再按tab
即可選擇檔案或目錄1 2 3 4 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
閱讀版本:July 25, 2016
--ansi
, --posix
, --compatible
1 2 3 4 5 |
|
1 2 3 4 |
|
--pedantic
:產生所有ISO C和ISO C++規範的警告訊息,並將所有C的extension退貨NUL
字元以及不可列印字元,並需相容多位元編碼方式如UTF-8
perror
或strerror
等方式列印出錯誤訊息mallic
及relloc
一定要檢查回傳值是否為NULL。當使用relloc
要求分配比原本空間更小時更需要注意,因為實作關係可能最後分配的空間block可能和原本的不同free
後就不要留戀還在裏面的資料了吧malloc
出現錯誤時,非互動程式請將他視為嚴重錯誤。互動程式就儘早自殺(abort()
)吧getopt_long
處理命令列參數$TMP_DIR
環境變數而不是閉著眼睛寫到/tmp
下面prefix
,prefix為兩個字元以上(後面英文太爛看不懂)_
開頭加上prefix用來辨識這是內部函數sourcefile:lineno: message
很奇怪的,單字句子都看懂,就是不懂他要表達啥。只能猜測說不要生出一堆很功能類似的執行檔,而是用最少執行檔加上參數取代。以及執行檔儘量device independent
檔案有可能會存放在readonly FS,如果要寫東西寫到必定是可寫的目錄如/var
或是/tmp
目錄中
#endif
後加上對應的#ifdef
或#ifndef
說明,範例如下:1 2 3 4 5 6 7 8 9 |
|
int
就省略要回傳int
的函數對應宣告-Wall
,編譯器是我們的奴隸,你自己清楚要做什麼就好。不要為了避免嚴格語法檢查硬上一些奇怪的語法導致可讀性變差extern
要嘛全部放在C檔案的同一塊地方,要嘛集中到header file,不要東一撮西一撮。更嚴禁在函數內使用tmp
之類的,個別變數就給予個別有意義的變數名稱,不要偷懶。也可以在需要的最小scope宣告變數增加可讀性。-Wshadow
協助偵測這類的錯誤1 2 3 4 5 6 |
|
1 2 3 4 5 6 7 |
|
1 2 3 4 5 6 |
|
g
prefix提醒一下enum
取代巨集完全看不懂,抱歉
1 2 3 4 5 6 |
|
1 2 |
|
1 2 3 4 5 |
|
14b24726a81b719b35fee70c8ba8be2d682a7313
我目前只打開加入debug資訊的選項。接下來重編,編譯的方式請參考這邊
依照下面兩個步驟執行
基本上就是原本的指令加入兩個選項
-S
-s
-gdb tcp::1234
的縮寫,也就是說gdb可以透過port 1234和連到Qemu除錯假設你在buildroot最上層,就可以使用下面指令執行qemu 並使用gdb 除錯
1 2 3 4 5 6 |
|
這邊有點瑣碎,先講一下步驟
arm-none-eabi-gdb ./vmlinux
arm-none-eabi-gdb -ex "file ./vmlinux"
file ./vmlinux
指令arm-none-eabi-gdb -ex "target remote :1234"
target remote :1234
指令b printk
continue
1和2可以一起使用如下
1
|
|
現在看一下操作範例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
|
另外如果有興趣使用Linux kernel提供的指令,在kernel config設定打開gdb script後,可以使用下面的方式在啟動gdb時載入,只要把下面的描述加到你的~/.gdbinit
即可
1
|
|
那麼你就可以使用Linux kernel提供的gdb script,詳細的設定和指令說明在這邊。
當初犯了蠢事載入不正確的kernel image導致一堆不必要的除錯。不過多學到一個gdb Python script除錯指令,當Python script發生exception時可以用下面的指令印出Python錯誤call stack
set python print-stack full
-ex "set python print-stack full"
上一篇提到,設定實習環境的目標有:
今天就是來解決3 的項目。更細分的話,這次目標是
做組裝的最重要的原則之一就是要能夠reproduce,所以交代測試環境是一定要的
1 2 3 4 5 6 7 8 9 |
|
14b24726a81b719b35fee70c8ba8be2d682a7313
沒啥好講的,就剪貼指令吧
1
|
|
東西下載完不是就閉著眼睛開幹,因為我們在開始編譯前需要
那麼就來見招拆招吧
非常簡單,先git tag
,切過去就好。我要切到4.4.2就是
1 2 3 |
|
先講結論
1
|
|
開始沒人要看的解釋吧。基本上也亂看找出來的,簡單講一下當初的「脈絡」
find | grep vexpress
。從一堆檔案中我看到有趣的檔案./arch/arm/configs/vexpress_defconfig
。ARCH
,剩下就試看看make ARCH=arm vexpress_defconfig
,能不能動,可以動所以打完收工。然後你就知道
ARCH
可以讓make時自動參考這些檔案產生config建議不要把buildroot compile cache打開。我花了很多時間在kernel 編譯後Qemu還是沒有使用編譯後的kernel的問題,最後發現關閉buildroot compile cache問題就消失了。
如果閉著眼睛開始編譯,你會很高興地發現可以開機了,但是接下來就會很失望的發現出現mount完rootfs找不到/dev/ttyAMA0
,以至於沒辦法進入login畫面。這是因為雖然serial driver偵測到設備,但是/dev下面沒有相對的device node。解法就是確認下面kernel option有開啟。想要知道真正的原因手冊這邊有提到,請參考Dynamic using devtmpfs only
段落。
建議順便巡一下其他kernel選項,用不到的可以關一下。比如說一堆有的沒的網卡,音效支援之類的。
make menuconfig
make
指令如下
1
|
|
這其實就是make bzImage
的囉唆版,多了
ARCH=arm
CROSS_COMPILE=..
V=1
由於Kernel的演進,可以存放平台硬體相關設定讓kernel啟動時存取。此方式稱為device tree,詳細資訊可以參考這份簡介(pdf投影片)。
以論述文來說,儘量先說結論再解釋。因此懶人包如下,假設在kernel top 目錄中:
1 2 |
|
沒人要看的說明如下,懶得看推論的就剪貼上面就好
對於組裝工來說,我關心的是
要回上面的問題,最簡單的方式就是回顧buildroot中啟動qemu Vepress的命令參數,你就會發現有個東西似乎和我們關心的device tree有關聯
-dtb output/images/vexpress-v2p-ca9.dtb
這邊顯示了幾個資訊
那麼我們在Kernel中找一下檔名中有vexpress-v2p-ca9的檔案
1 2 |
|
這邊一樣透露了這是一個和dtb
很類似的檔案,那麼我們進一步做一些確認
1 2 3 4 5 6 7 8 9 |
|
剩下就是估狗大法,發現需要編譯器才能把dts轉換成dtb檔案。 所以就用上面的方式產稱dtb檔囉。
剩下就剪貼了
我在buildroot top目錄執行的,你要嘛就切到buildroot目錄下,要嘛就指定-drive file
到你自己rootfs的路徑
1
|
|
提出來兩個參數表示這是我編譯出來的kernel而不是buildroot的
-kernel /tmp/kernel/linux-stable/arch/arm/boot/zImage
-dtb /tmp/kernel/linux-stable/vexpress-v2p-ca9.dtb
開機畫面節錄如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
|
當初會去做這個主要是因為開始編譯獨立的Linux kernel前要先驗證buildroot自己編的Linux 4.4.2是否可以用qemu開機。另外的好處的就是buildroot編譯出來的kernel config (在output/build/linux-4.4.2/.config) 可以和你自己的kernel config比對。這邊只要在buildroot中make menuconfig中和kernel有關設定指定4.4.2即可,比Versatile簡單太多了故省略,如果有人遇到問題我再補上這邊說明。
]]>最近因為特別因素開始學習Linux kernel,看能不能Linux kernel和STM32兩邊都不要漏掉。不管怎樣,學習和實習絕對分不開,所以還是從環境架設開始吧。這次的實習環境架設的目標是:
今天只有辦到1, 2和4而已,剩下的請參考之後的文章。
因為我已經裝過開發相關的套件,因此如果您是新手可能要自行摸索也許有需要另外安裝的套件如git
。嘛,練習解讀錯誤訊息也是一種學習。
$ lsb_release -a No LSB modules are available. Distributor ID: Ubuntu Description: Ubuntu 14.04.5 LTS Release: 14.04 Codename: trusty
主要分成下面三個步驟
直接看例子,剪下貼上就好
1 2 3 |
|
網路上查到大部分都是從make menuconfig
開始。不過我是很明確地要用Qemu
跑ARM的系統。所以使用下面指令查詢。
1
|
|
Scott 大大指出可以使用qemu_arm_vexpress
,原因是這個平台模擬的CPU是 Cortex-A9
(ARMv7-A)的平台。之前我是用的模擬平台使用的CPU是ARM926EJ-S
(ARMv5TE),它的instruction 架構和現在差距太多,所以就轉換到這邊了。
接下來就用make menuconfig
做細項調整,因為是拿來做分析系統行為,所以調整的重點是增加系統的可觀察度、除錯工具、開發軟體套件等。
開啟或新增下面設定如下:
自行編譯 Kernel 部份下一篇會再說明。
編譯只要下make
就會幫你下載和編譯開機需要的
output/image/roofs.ext2
zImage
,放在output/image/zImage
接下來也不難,可以參考board/qemu/arm-vexpress/readme.txt
簡單來說就是執行下面指令,開機完使用root
登入不用密碼,使用poweroff
後再手動離開qemu。
1
|
|
執行畫面如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
|
還是感謝Scott大大和其他網友的幫忙。這次最重要的心得就是不要在睡眠不足的時候做實驗,浪費的時間拿去睡覺反而比較實在。
1 2 3 4 5 6 |
|
1 2 |
|
1 2 3 4 5 |
|
14b24726a81b719b35fee70c8ba8be2d682a7313
我目前只打開加入debug資訊的選項。接下來重編,編譯的方式請參考這邊
依照下面兩個步驟執行
基本上就是原本的指令加入兩個選項
-S
-s
-gdb tcp::1234
的縮寫,也就是說gdb可以透過port 1234和連到Qemu除錯假設你在buildroot最上層,就可以使用下面指令執行qemu 並使用gdb 除錯
1 2 3 4 5 |
|
這邊有點瑣碎,先講一下步驟
arm-none-eabi-gdb ./vmlinux
arm-none-eabi-gdb -ex "file ./vmlinux"
file ./vmlinux
指令arm-none-eabi-gdb -ex "target remote :1234"
target remote :1234
指令b printk
continue
1和2可以一起使用如下
1
|
|
現在看一下操作範例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
|
另外如果有興趣使用Linux kernel提供的指令,可以使用下面的方式在啟動gdb時載入
,只要把下面的描述加到你的~/.gdbinit
即可
1
|
|
那麼你就可以使用Linux kernel提供的gdb script,詳細的設定和指令說明在這邊。
當初犯了蠢事載入不正確的kernel image導致一堆不必要的除錯。不過多學到一個gdb Python script除錯指令,當Python script發生exception時可以用下面的指令印出Python錯誤call stack
set python print-stack full
-ex "set python print-stack full"