前言
可能你並不太了解msys2,但是作為一個程序員,你一定知道mingw,而msys2就集成了mingw,同時msys2還有一些其他的特性,例如包管理器等。
msys2可以在windows下搭建一個完美的類linux環境,包括bash、vim、gcc、make等工具都可以通過包管理器來添加和卸載
msys2的包管理器是使用的pacman,用過archlinux的應該都知道pacman了。
我們現在的目標是要集成make+gcc+gdb的一條編譯工具
安裝
下載地址:
msys2
如果是exe,直接雙擊安裝,如果是zip,直接解壓到安裝的地方即可。然后雙擊msys2.exe運行
[圖片上傳失敗...(image-295493-1523187370956)]
給 MSYS2 添加中科大的源
使用過archlinux的應該會知道,pacman在安裝的時候,如果源沒有設置好,下載是很慢的。
需要修改的文件是:
1. \etc\pacman.d\mirrorlist.mingw32
2. \etc\pacman.d\mirrorlist.mingw64
3. \etc\pacman.d\mirrorlist.msys
簡單的說 msys64\etc\pacman.d 目錄下有三個文件。
mirrorlist.msys
mirrorlist.mingw64
mirrorlist.mingw32
這三個文件記錄了都有哪些源。下面把我添加之后的文件內容貼上來。
首先是 mirrorlist.msys:
## ## MSYS2 repository mirrorlist ## ## Primary ## msys2.org Server = http://mirrors.ustc.edu.cn/msys2/msys/$arch/ Server = http://repo.msys2.org/msys/$arch Server = http://downloads.sourceforge.net/project/msys2/REPOS/MSYS2/$arch Server = http://www2.futureware.at/~nickoe/msys2-mirror/msys/$arch/
mirrorlist.mingw64:
## ## 64-bit Mingw-w64 repository mirrorlist ## ## Primary ## msys2.org Server = http://mirrors.ustc.edu.cn/msys2/mingw/x86_64/ Server = http://repo.msys2.org/mingw/x86_64 Server = http://downloads.sourceforge.net/project/msys2/REPOS/MINGW/x86_64 Server = http://www2.futureware.at/~nickoe/msys2-mirror/x86_64/ Server = http://mirror.bit.edu.cn/msys2/REPOS/
mirrorlist.mingw32:
## ## 32-bit Mingw-w64 repository mirrorlist ## ## Primary ## msys2.org Server = http://mirrors.ustc.edu.cn/msys2/mingw/i686/ Server = http://repo.msys2.org/mingw/i686 Server = http://downloads.sourceforge.net/project/msys2/REPOS/MINGW/i686 Server = http://www2.futureware.at/~nickoe/msys2-mirror/i686/
MSYS2 鏡像使用幫助
收錄架構
MINGW: i686, x86_64 MSYS: i686, x86_64 安裝 請訪問該鏡像目錄下的 distrib/ 目錄(x86_64 、i686),找到名為 msys2-<架構>-<日期>.exe 的文件(如 msys2-x86_64-20141113.exe),下載安裝即可。 pacman 的配置 編輯 /etc/pacman.d/mirrorlist.mingw32 ,在文件開頭添加: Server = https://mirrors.tuna.tsinghua.edu.cn/msys2/mingw/i686 編輯 /etc/pacman.d/mirrorlist.mingw64 ,在文件開頭添加: Server = https://mirrors.tuna.tsinghua.edu.cn/msys2/mingw/x86_64 編輯 /etc/pacman.d/mirrorlist.msys ,在文件開頭添加: Server = https://mirrors.tuna.tsinghua.edu.cn/msys2/msys/$arch 然后執行 pacman -Sy 刷新軟件包數據即可。
安裝可以跳過直接看pacman即可,參照這修改
中國科學技術大學方法可以參考清華的。
下載工具包
下載工具包這一部分就是純粹的pacman知識了,涉及的指令有:
pacman -Sy 更新軟件包數據
pacman -Syu 更新所有
pacman -Ss xx 查詢軟件xx的信息
pacman -S xx 安裝軟件xx
下載make
我們先通過命令pacman -Ss make查詢完整的make包名
我們可以看到,每個軟件大致分為了三大類:mingw32、mingw64、msys,如果想下載mingw那么就要對應着自己的系統下載,32位和64位要區分
我們下載msys類就行。比如我們搜到的make是這樣的:
msys/automake1.9 1.9.6-2 (base-devel) A GNU tool for automatically creating Makefiles msys/cmake 3.6.2-1 A cross-platform open-source make system msys/colormake-git r8.9c1d2e6-1 Colorized build output msys/make 4.2.1-1 (base-devel) [已安裝] GNU make utility to maintain groups of programs msys/make-git 4.1.8.g292da6f-1 GNU make utility to maintain groups of programs msys/perl 5.24.1-2 (base-devel)
即msys/make,所以我們安裝的時候只需要輸入:
pacman -S msys/make
或者直接輸入
pacman -S make
就會默認安裝msys/make
下載gcc
我們先通過命令pacman -Ss gcc查詢完整的gcc包名
mingw64/mingw-w64-x86_64-gcc-objc 6.3.0-1 (mingw-w64-x86_64-toolchain) GNU Compiler Collection (ObjC,Obj-C++) for MinGW-w64 mingw64/mingw-w64-x86_64-lcov 1.12-1 front-end for GCC's coverage testing tool gcov msys/gcc 6.3.0-1 (msys2-devel) The GNU Compiler Collection - C and C++ frontends msys/gcc-fortran 6.3.0-1 (msys2-devel) Fortran front-end for GCC
即msys/gcc,所以我們安裝的時候只需要輸入:
pacman -S msys/gcc
或者
pacman -S gcc
測試
安裝后我們測試一下:
make -v
顯示類似如下內容說明安裝成功:
GNU Make 4.2.1 為 x86_64-pc-msys 編譯 Copyright (C) 1988-2016 Free Software Foundation, Inc. 許可證:GPLv3+:GNU 通用公共許可證第 3 版或更新版本<http://gnu.org/licenses/gpl.html>。 本軟件是自由軟件:您可以自由修改和重新發布它。 在法律允許的范圍內沒有其他保證。
然后測試gcc:
使用內建 specs。
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-pc-msys/6.3.0/lto-wrapper.exe
目標:x86_64-pc-msys
配置為:/msys_scripts/gcc/src/gcc-6.3.0/configure --build=x86_64-pc-msys --prefix=/usr --libexecdir=/usr/lib --enable-bootstrap --enable-shared --enable-shared-libgcc --enable-static --enable-version-specific-runtime-libs --with-arch=x86-64 --with-tune=generic --disable-multilib --enable-__cxa_atexit --with-dwarf2 --enable-languages=c,c++,fortran,lto --enable-graphite --enable-threads=posix --enable-libatomic --enable-libcilkrts --enable-libgomp --enable-libitm --enable-libquadmath --enable-libquadmath-support --enable-libssp --disable-win32-registry --disable-symvers --with-gnu-ld --with-gnu-as --disable-isl-version-check --enable-checking=release --without-libiconv-prefix --without-libintl-prefix --with-system-zlib --enable-linker-build-id --with-default-libstdcxx-abi=gcc4-compatible 線程模型:posix gcc 版本 6.3.0 (GCC)
其他的軟件都是這么玩的,我就不介紹了。
編譯測試
我們先新建一個demo.c文件,然后編寫一段測試代碼:
#include <stdio.h> int main() { printf("abcDEF\r\n"); }
保存
然后我們通過cd 命令將msys的目錄切換到這個c文件處
后執行
$gcc demo.c -o demo
如果編譯沒有錯誤,那么會在當前目錄下生成demo.exe,然后運行:
$./demo.exe
即可看到運行結果
運行過程如下:
xml@DESKTOP-B0SS2KE MSYS /f/xml/test/DEMO1
$ gcc demo.c -o demo
xml@DESKTOP-B0SS2KE MSYS /f/xml/test/DEMO1
$ ls
demo.c demo.exe
xml@DESKTOP-B0SS2KE MSYS /f/xml/test/DEMO1
$ ./demo.exe
abcDEF
當然,如果我們需要進行細致的分析代碼,在編譯的時候就帶上-g參數,然后通過objdump來分析匯編源碼吧
xml@DESKTOP-B0SS2KE MSYS /f/xml/test/DEMO1
$ gcc demo.c -g -o demo
xml@DESKTOP-B0SS2KE MSYS /f/xml/test/DEMO1
$ objdump -f ./demo.exe
./demo.exe: 文件格式 pei-x86-64 體系結構:i386:x86-64,標志 0x0000013a: EXEC_P, HAS_DEBUG, HAS_SYMS, HAS_LOCALS, D_PAGED 起始地址 0x0000000100401000 xml@DESKTOP-B0SS2KE MSYS /f/xml/test/DEMO1 $ objdump -S ./demo.exe ./demo.exe: 文件格式 pei-x86-64 Disassembly of section .text: 00000001004010e0 <main>: #include <stdio.h> int main() { 1004010e0: 55 push %rbp 1004010e1: 48 89 e5 mov %rsp,%rbp 1004010e4: 48 83 ec 20 sub $0x20,%rsp 1004010e8: e8 33 00 00 00 callq 100401120 <__main> printf("abcDEF\r\n"); 1004010ed: 48 8d 0d 3c 1f 00 00 lea 0x1f3c(%rip),%rcx # 100403030 <.rdata> 1004010f4: e8 37 00 00 00 callq 100401130 <puts> 1004010f9: b8 00 00 00 00 mov $0x0,%eax }
當然我們也可以安裝gdb,然后通過gdb來調試代碼
作者:苦境名人
鏈接:https://www.jianshu.com/p/713f8588ba18
來源:簡書
簡書著作權歸作者所有,任何形式的轉載都請聯系作者獲得授權並注明出處。
一、簡介
objdump命令是用查看目標文件或者可執行的目標文件的構成的gcc工具。
二、選項
三、實例
1)顯示文件頭信息
objdump -f test
2)顯示Section Header信息
objdump -h test
3)顯示全部Header信息
objdump -x test
4)顯示全部Header信息,並顯示對應的十六進制文件代碼
objdump -s test
5)輸出目標文件的符號表
objdump -t obj
6)輸出目標文件的所有段概述
objdump -h obj
7)反匯編test中的需要執行指令的那些section
objdump -d test
8)反匯編test中的所有section
objdump -D test
9)反匯編出源碼(指定section)
objdump -Slj .text obj
10)對任意二進制文件進行反匯編
objdump -D -b binary -m i386 a.bin
如何使用 objdump 查看源代碼
1. 在編譯時必須使用-g選項,-g意為debug,一般可以修改源代碼的 Makefile來實現 如:
CC =$(CROSSCOM_PILE)gcc 為
CC =$(CROSSCOM_PILE)gcc -g
使成生的vmlinux中含有debug信息
2. 所有生成 .o 的 rule 中再加一條 /*其他參數除了-c外抄生成.o文件用的參數*/
CC -E -dD -C $< > /preprocessing/$(shell pwd)/$<
生成預處理文件從這個文件里面能很容易找到 c 源文件的宏定義
3. objdump -h vmlinux > vmlinux.txt
顯示 linux 內核段信息,如段的開始虛擬地址,段的長度
4. objdump -S -l -z vmlinux > vmlinux.txt
反匯編 vmlinux 到vmlinux.txt, vmlinux.txt 含有匯編和 c 源文件的混合代碼,看起來很方
便。而且能一步步看linux怎么一步步運行的。
5. objdump -S -l -z -j xxxx(section name) vmlinux > vmlinux.txt
反匯編 linux 內核段 xxxx 到文件 vmlinux.txt 中。
6. objdump -x vmlinux > x.txt
vmliux中所有段的頭信息,其中包口vmlinux的入口地址等
7. objdump --debugging vmlinux > debugging.txt
很多有用的debug信息,如函數名,結構體定義等
我覺的用根據以上信息,ultraedit看很方便。尤其在vmlinux.txt中選中文件名,
用ultraedit右鍵的open能馬上打開文件,很方便。
objdump -x obj 以某種分類信息的形式把目標文件的數據組織(被分為幾大塊)輸出 <可查到該文件的所有動態庫>
objdump -t obj 輸出目標文件的符號表()
objdump -h obj 輸出目標文件的所有段概括()
objdump -j .text/.data -S obj 輸出指定段的信息,大概就是反匯編源代碼把
objdump -S obj C語言與匯編語言同時顯示
以下為網上摘錄文章。
關於nm -s的顯示請自己man nm查看
objdump命令的man手冊
objdump - 顯示二進制文件信息
objdump
[-a] [-b bfdname |
--target=bfdname] [-C] [--debugging]
[-d] [-D]
[--disassemble-zeroes]
[-EB|-EL|--endian={big|little}] [-f]
[-h] [-i|--info]
[-j section | --section=section]
[-l] [-m machine ] [--prefix-addresses]
[-r] [-R]
[-s|--full-contents] [-S|--source]
[--[no-]show-raw-insn] [--stabs] [-t]
[-T] [-x]
[--start-address=address] [--stop-address=address]
[--adjust-vma=offset] [--version] [--help]
objfile...
--archive-headers
-a 顯示檔案庫的成員信息,與 ar tv 類似
objdump -a libpcap.a
和 ar -tv libpcap.a 顯示結果比較比較顯然這個選項沒有什么意思。
--adjust-vma=offset
When dumping information, first add offset to all
the section addresses. This is useful if the sec-
tion addresses do not correspond to the symbol
table, which can happen when putting sections at
particular addresses when using a format which can
not represent section addresses, such as a.out.
-b bfdname
--target=bfdname
指定目標碼格式。這不是必須的,objdump能自動識別許多格式,比如:objdump -b oasys -m vax -h fu.o
顯示fu.o的頭部摘要信息,明確指出該文件是Vax系統下用Oasys編譯器生成的目標文件。objdump -i將給出這里可以指定的目標碼格式列表
--demangle
-C 將底層的符號名解碼成用戶級名字,除了去掉所有開頭的下划線之外,還使得C++函數名以可理解的方式顯示出來。
--debugging
顯示調試信息。企圖解析保存在文件中的調試信息並以C語言的語法顯示出來。僅僅支持某些類型的調試信息。
--disassemble
-d 反匯編那些應該還有指令機器碼的section
--disassemble-all
-D 與 -d 類似,但反匯編所有section
--prefix-addresses
反匯編的時候,顯示每一行的完整地址。這是一種比較老的反匯編格式。
顯示效果並不理想,但可能會用到其中的某些顯示,自己可以對比。
--disassemble-zeroes
一般反匯編輸出將省略大塊的零,該選項使得這些零塊也被反匯編。
-EB
-EL
--endian={big|little}
這個選項將影響反匯編出來的指令。
little-endian就是我們當年在dos下玩匯編的時候常說的高位在高地址,x86都是這種。
--file-headers
-f 顯示objfile中每個文件的整體頭部摘要信息。
--section-headers
--headers
-h 顯示目標文件各個section的頭部摘要信息。
--help 簡短的幫助信息。
--info
-i 顯示對於 -b 或者 -m 選項可用的架構和目標格式列表。
--section=name
-j name 僅僅顯示指定section的信息
--line-numbers
-l 用文件名和行號標注相應的目標代碼,僅僅和-d、-D或者-r一起使用使用-ld和使用-d的區別不是很大,在源碼級調試的時候有用,要求編譯時使用了-g之類的調試編譯選項。
一、GCC編譯器和常用命令
gcc編譯器不僅支持c語言,還支持Ada、C++、Objective-C語言。一般編譯的過程可以分為四個階段:預處理(Preprocessing)、編譯(Compilation)、匯編(Assembly)和連接(Linking)
1、 一步到位的編譯指令
包含四個階段
gcc test.c –o test
2、 預處理
將頭文件內容插入到test.c文件,-E是預處理結束后停止,並輸出預處理結果
gcc –E test.c –o test.i
3、 編譯
對.i文件編譯,生成匯編代碼,-S表示生成匯編代碼后停止,-o輸出匯編代碼文件
gcc –S test.i –o test.s
4、 匯編
將匯編代碼文件編譯為目標文件
gcc –c test.s –o test.o
5、 連接
將其與C標准輸入輸出庫進行連接,最終生成程序test
gcc test.o –o test
6、 執行
在命令行窗口,執行./test
不同文件代表的意義:
test.c(源文件)->test.i(-E預處理后文件)->test.s(-S匯編文件)->test.o(-c目標文件)->test(-o可執行文件)
對於多個源文件進行編譯:
1、 一步到位
gcc test1.c test2.c –o test
2、 復雜一些的(執行過程和一步到位的是一樣的,都是預處理->編譯->連接)
gcc -c test1.c -o test1.o
gcc -c test2.c -o test2.o
gcc test1.o test2.o -o test
常用命令選項的意義:
1、-c 只編譯不連接
2、-O 優化編譯后的代碼,后面加數字代表優化級別
3、-o 指定輸出的文件名
4、-v 顯示編譯過程中每一步用到的命令
二、objdump命令的使用
objdump是Linux下面的反匯編目標文件或者可執行文件的命令
1、objdump –d test
反悔表test中需要執行指令的那些section
2、 objdump –h test
顯示test的Section Header信息
3、 objdump –S test.o
輸出C源代碼和反匯編出來的指令對照的格式
4、 objdump –h
顯示目標文件各個section的頭部摘要信息
5、 objdump –r
顯示文件的重定位入口
6、 objdump –t顯示文件的符號表入口
三、file命令
file命令是檢測文件類型的命令,可以讀取文件的編碼體系以及一些其他信息
---------------objdump是用查看目標文件或者可執行的目標文件的構成的GCC工具----------
以下3條命令足夠那些喜歡探索目標文件與源代碼之間的絲絲的關系的朋友。
objdump -x obj 以某種分類信息的形式把目標文件的數據組織(被分為幾大塊)輸出 <可查到該文件的所有動態庫>
objdump -t obj 輸出目標文件的符號表()
objdump -h obj 輸出目標文件的所有段概括()
objdump -j .text/.data -S obj 輸出指定段的信息,大概就是反匯編源代碼把
objdump -S obj C語言與匯編語言同時顯示
以下為網上摘錄文章。
關於nm -s的顯示請自己man nm查看
objdump命令的man手冊
objdump - 顯示二進制文件信息
objdump
[-a] [-b bfdname |
--target=bfdname] [-C] [--debugging]
[-d] [-D]
[--disassemble-zeroes]
[-EB|-EL|--endian={big|little}] [-f]
[-h] [-i|--info]
[-j section | --section=section]
[-l] [-m machine ] [--prefix-addresses]
[-r] [-R]
[-s|--full-contents] [-S|--source]
[--[no-]show-raw-insn] [--stabs] [-t]
[-T] [-x]
[--start-address=address] [--stop-address=address]
[--adjust-vma=offset] [--version] [--help]
objfile...
--archive-headers
-a 顯示檔案庫的成員信息,與 ar tv 類似
objdump -a libpcap.a
和 ar -tv libpcap.a 顯示結果比較比較
顯然這個選項沒有什么意思。
--adjust-vma=offset
When dumping information, first add offset to all
the section addresses. This is useful if the sec-
tion addresses do not correspond to the symbol
table, which can happen when putting sections at
particular addresses when using a format which can
not represent section addresses, such as a.out.
-b bfdname
--target=bfdname
指定目標碼格式。這不是必須的,objdump能自動識別許多格式,
比如:objdump -b oasys -m vax -h fu.o
顯示fu.o的頭部摘要信息,明確指出該文件是Vax系統下用Oasys
編譯器生成的目標文件。objdump -i將給出這里可以指定的
目標碼格式列表
--demangle
-C 將底層的符號名解碼成用戶級名字,除了去掉所有開頭
的下划線之外,還使得C++函數名以可理解的方式顯示出來。
--debugging
顯示調試信息。企圖解析保存在文件中的調試信息並以C語言
的語法顯示出來。僅僅支持某些類型的調試信息。
--disassemble
-d 反匯編那些應該還有指令機器碼的section
--disassemble-all
-D 與 -d 類似,但反匯編所有section
--prefix-addresses
反匯編的時候,顯示每一行的完整地址。這是一種比較老的反匯編格式。
顯示效果並不理想,但可能會用到其中的某些顯示,自己可以對比。
--disassemble-zeroes
一般反匯編輸出將省略大塊的零,該選項使得這些零塊也被反匯編。
-EB
-EL
--endian={big|little}
這個選項將影響反匯編出來的指令。
little-endian就是我們當年在dos下玩匯編的時候常說的高位在高地址,
x86都是這種。
--file-headers
-f 顯示objfile中每個文件的整體頭部摘要信息。
--section-headers
--headers
-h 顯示目標文件各個section的頭部摘要信息。
--help 簡短的幫助信息。
--info
-i 顯示對於 -b 或者 -m 選項可用的架構和目標格式列表。
--section=name
-j name 僅僅顯示指定section的信息
--line-numbers
-l 用文件名和行號標注相應的目標代碼,僅僅和-d、-D或者-r一起使用
使用-ld和使用-d的區別不是很大,在源碼級調試的時候有用,要求
編譯時使用了-g之類的調試編譯選項。
--architecture=machine
-m machine
指定反匯編目標文件時使用的架構,當待反匯編文件本身沒有描述
架構信息的時候(比如S-records),這個選項很有用。可以用-i選項
列出這里能夠指定的架構
--reloc
-r 顯示文件的重定位入口。如果和-d或者-D一起使用,重定位部分以反匯
編后的格式顯示出來。
--dynamic-reloc
-R 顯示文件的動態重定位入口,僅僅對於動態目標文件有意義,比如某些
共享庫。
--full-contents
-s 顯示指定section的完整內容。
objdump --section=.text -s inet.o | more
--source
-S 盡可能反匯編出源代碼,尤其當編譯的時候指定了-g這種調試參數時,
效果比較明顯。隱含了-d參數。
--show-raw-insn
反匯編的時候,顯示每條匯編指令對應的機器碼,除非指定了
--prefix-addresses,這將是缺省選項。
--no-show-raw-insn
反匯編時,不顯示匯編指令的機器碼,這是指定 --prefix-addresses
選項時的缺省設置。
--stabs
Display the contents of the .stab, .stab.index, and
.stab.excl sections from an ELF file. This is only
useful on systems (such as Solaris 2.0) in which
.stab debugging symbol-table entries are carried in
an ELF section. In most other file formats, debug-
ging symbol-table entries are interleaved with
linkage symbols, and are visible in the --syms output.
--start-address=address
從指定地址開始顯示數據,該選項影響-d、-r和-s選項的輸出。
--stop-address=address
顯示數據直到指定地址為止,該選項影響-d、-r和-s選項的輸出。
--syms
-t 顯示文件的符號表入口。類似於nm -s提供的信息
--dynamic-syms
-T 顯示文件的動態符號表入口,僅僅對動態目標文件有意義,比如某些
共享庫。它顯示的信息類似於 nm -D|--dynamic 顯示的信息。
--version 版本信息
objdump --version
--all-headers
-x 顯示所有可用的頭信息,包括符號表、重定位入口。-x 等價於
-a -f -h -r -t 同時指定。
objdump -x inet.o
參看 nm(1)
★ objdump應用舉例(待增加)
/*
g++ -g -Wstrict-prototypes -Wall -Wunused -o objtest objtest.c
*/
#include
#include
int main ( int argc, char * argv[] )
{
execl( "/bin/sh", "/bin/sh", "-i", 0 );
return 0;
}
g++ -g -Wstrict-prototypes -Wall -Wunused -o objtest objtest.c
objdump -j .text -Sl objtest | more
/main(查找)
08048750:
main():
/home/scz/src/objtest.c:7
*/
#include
#include
int main ( int argc, char * argv[] )
{
8048750: 55 pushl %ebp
8048751: 89 e5 movl %esp,%ebp
/home/scz/src/objtest.c:8
execl( "/bin/sh", "/bin/sh", "-i", 0 );
8048753: 6a 00 pushl $0x0
8048755: 68 d0 87 04 08 pushl $0x80487d0
804875a: 68 d3 87 04 08 pushl $0x80487d3
804875f: 68 d3 87 04 08 pushl $0x80487d3
8048764: e8 db fe ff ff call 8048644 <_init+0x40>
8048769: 83 c4 10 addl $0x10,%esp
/home/scz/src/objtest.c:9
return 0;
804876c: 31 c0 xorl %eax,%eax
804876e: eb 04 jmp 8048774
8048770: 31 c0 xorl %eax,%eax
8048772: eb 00 jmp 8048774
/home/scz/src/objtest.c:10
}
8048774: c9 leave
8048775: c3 ret
8048776: 90 nop
如果說上面還不夠清楚,可以用下面的命令輔助一下:
objdump -j .text -Sl objtest --prefix-addresses | more
objdump -j .text -Dl objtest | more
用以上不同的命令去試會得到驚喜!