記事ディレクトリ
プログラムのコンパイル プロセス
コンピュータプログラミング言語は通常、機械語、アセンブリ言語、高級言語の 3 つのカテゴリに分類されます。高級言語は機械語に翻訳して実行する必要があり、コンパイルする方法と解釈する方法の2つの翻訳方法があるため、基本的に高級言語を2つのカテゴリーに分け、一方はコンパイルするC、C++、Java などの型言語と、Python、Ruby、MATLAB、JavaScript などのインタープリター型言語です。
ここでは、高級 C/C++ 言語で記述されたプログラムを、プロセッサが実行できるバイナリ コードに変換する方法を紹介します。次の 4 つの手順が含まれます。
- 前処理 (前処理、プリプロセッサ cpp、役割: .c/s -> .i
- コンパイル、アセンブラ ccl、関数: .i -> .s
- コンパイル (アセンブリ)、コンパイラ as、関数: .s -> .o
- リンク、リンカー ld、役割: .o -> elf 実行ファイル
声明
コンテンツの一部は、侵入して削除されたインターネットから取得されます。
GCC 共通ツールチェーン
一般に GCC と呼ばれるのは、Linux システムで一般的に使用されるコンパイル ツールである GUN Compiler Collection の略語です。GCC ツール チェーン ソフトウェアには、GCC、Binutils、C ランタイム ライブラリなどが含まれます。
GCC
GCC (GNU C コンパイラ) はコンパイル ツールです。C/C++言語で書かれたプログラムをプロセッサが実行できるバイナリコードに変換する処理は、コンパイラによって完了します。
Binutils
addr2line、ar、objcopy、objdump、as、ld、ldd、readelf、size などのバイナリ プログラム処理ツールのセット。この一連のツールは、開発とデバッグに不可欠なツールであり、その簡単な紹介は次のとおりです。
- addr2line: プログラムアドレスを対応するプログラムソースファイルと対応するコード行に変換し、対応する関数を取得するために使用されます。このツールは、デバッガーがデバッグ中に対応するソース コードの場所を見つけるのに役立ちます。
- as: 主に組み立てに使用します。組み立ての詳細な紹介は以下を参照してください。
- ld: 主にリンクのために使用されます. リンクの詳細については, 以下のテキストを参照してください.
- ar: 主に静的ライブラリの作成に使用されます。初心者の理解を容易にするために、動的ライブラリと静的ライブラリの概念をここで紹介します。
- 複数の .o オブジェクト ファイルをライブラリ ファイルに生成する場合、ライブラリには静的ライブラリと動的ライブラリの 2 種類があります。
Windows では、スタティック ライブラリは拡張子が .lib のファイルで、共有ライブラリは拡張子が .dll のファイルです。Linux では、スタティック ライブラリは接尾辞 .a が付いたファイルであり、共有ライブラリは接尾辞 .so が付いたファイルです。 - 静的ライブラリと動的ライブラリの違いは、コードがロードされる瞬間が異なることです。スタティック ライブラリのコードは、コンパイル プロセス中に実行可能プログラムに読み込まれているため、サイズは比較的大きくなります。共有ライブラリのコードは、実行プログラムの実行時にメモリにロードされ、コンパイル プロセス中に参照されるだけなので、コード サイズは小さくなります。Linux システムでは、ldd コマンドを使用して、実行可能プログラムが依存する共有ライブラリーを表示できます。
システムで同時に実行する必要がある複数のプログラムがあり、これらのプログラム間に共有ライブラリがある場合、動的ライブラリを使用するとメモリをさらに節約できます。
- 複数の .o オブジェクト ファイルをライブラリ ファイルに生成する場合、ライブラリには静的ライブラリと動的ライブラリの 2 種類があります。
- ldd: 実行可能プログラムが依存する共有ライブラリを表示するために使用できます。
- objcopy: .bin を .elf に変換したり、.elf を .bin に変換したりするなど、1 つのオブジェクト ファイルを別の形式に変換します。
- objdump: 主な機能は逆アセンブルです。逆アセンブルの詳細については、次のテキストを参照してください。
- readelf: ELF ファイルに関する情報を表示します。詳細については、以下を参照してください。
- size: 実行ファイル、コードセグメント、データセグメント、合計サイズなどの各部分のサイズと合計サイズをリストします。size を使用した具体的な使用例については、以下を参照してください。
C ランタイム ライブラリ
C 言語標準は、主に 2 つの部分で構成されています。1 つは C の構文を記述し、もう 1 つは C 標準ライブラリを記述しています。C 標準ライブラリは一連の標準ヘッダー ファイルを定義し, 各ヘッダー ファイルには関連する関数, 変数, 型宣言およびマクロ定義が含まれています. たとえば, 一般的な printf 関数は C 標準ライブラリ関数であり, そのプロトタイプはstdio ヘッダー ファイル。
C 言語標準は、C 標準ライブラリ関数のプロトタイプを定義するだけで、実装は提供しません。したがって、C 言語コンパイラーは通常、C ランタイム・ライブラリー (C ランタイム・ライブラリー、CRT) のサポートを必要とします。C ランタイム ライブラリは、単に C ランタイム ライブラリと呼ばれることがよくあります。C 言語と同様に、C++ も独自の標準を定義し、C++ ランタイム ライブラリと呼ばれる関連するサポート ライブラリを提供します。
ENV
GCC ツール チェーンは主に Linux 環境で使用されるため、この記事でも Linux システムを作業環境として使用します。コンパイルの全プロセスを示すために、このセクションではまず例として C 言語で記述された単純な Hello プログラムを用意します。そのソース コードは次のとおりです。
#include<stdio.h>
int main(int argc, char *argv[])
{
printf("hello world\r\n");
return 0;
}
コンパイルプロセス
前処理
前処理プロセスには、主に次のプロセスが含まれます。
- すべての #define を削除し、すべてのマクロ定義を展開し、#if #ifdef #elif #else #endif などのすべての条件付きプリコンパイル済みディレクティブを処理します。
- #include プリコンパイル済みディレクティブを処理し、インクルード ファイルをプリコンパイル済みディレクティブの場所に挿入します。
- コメント「//」と「/* */」をすべて削除します。
- 行番号とファイル識別子を追加して、コンパイル時にデバッグ行番号とコンパイル エラー警告行番号を生成します。
- 後続のコンパイル パスに必要なすべての #pragma コンパイラ ディレクティブを保持します。
gcc で前処理するコマンドは次のとおりです。
gcc -E test.c -o test.i
GCC オプション -E により、前処理後に GCC が停止する
上記のコマンドは、ソースファイル test.c を前処理して test.i を生成するものです. test.i ファイルの内容は次のとおりです.
extern void funlockfile (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__));
# 885 "/usr/include/stdio.h" 3 4
extern int __uflow (FILE *);
extern int __overflow (FILE *, int);
# 902 "/usr/include/stdio.h" 3 4
# 2 "test.c" 2
# 3 "test.c"
int main(int argc, char *argv[])
{
printf("hello world\r\n");
return 0;
}
test.i ファイルを開いて、通常のテキスト ファイルとして表示できます。
コンパイル
コンパイル プロセスでは、前処理されたファイルに対して一連の字句解析、構文解析、意味解析、および最適化を実行して、対応するアセンブリ コードを生成します。
gccでコンパイルするコマンドは以下の通り
gcc -S test.i -o test.s
GCC のオプション -S により、コンパイル後に GCC が停止し、アセンブラーが生成される
上記のコマンドは、生成された test.i ファイルを前処理して、アセンブラー test.s をコンパイルおよび生成します。
コンパイル
アセンブリ プロシージャ コールは、アセンブリ コードを処理し、プロセッサが認識できる命令を生成して、オブジェクト ファイルにサフィックス .o を付けて保存します。各アセンブリステートメントはほぼプロセッサ命令に対応しているため、アセンブリプロセスは、アセンブリ命令とプロセッサ命令の比較表に従って、Binutils のようにアセンブラを呼び出すことで、コンパイルプロセスよりも簡単です。
プログラムが複数のソースコードファイルで構成されている場合、各ファイルはまずアセンブリ作業を完了する必要があり、次のリンク作業に入る前に .o オブジェクト ファイルが生成されます。注: オブジェクト ファイルは既に最終的なプログラムの一部ですが、リンクされるまで実行できません。
gccを使ってアセンブルするコマンドは以下の通り
gcc -c test.s -o test.o
GCC オプション -c により、アセンブリの実行後に GCC が停止し、オブジェクト ファイルが生成されます。
またはアセンブリについては直接呼び出します
as -c hello.s -o hello.o
Binutils の as を使用して、hello.s ファイルをアセンブルし、オブジェクト ファイルを生成します。
注: test.o オブジェクト ファイルは、ELF (Executable and Linkable Format) 形式のリダイレクト可能なファイルです。
リンク
リンクも静的リンクと動的リンクに分けられますが、主なポイントは次のとおりです。
- 静的リンクとは、コンパイル フェーズ中に静的ライブラリを実行可能ファイルに直接追加することを指します。そのため、実行可能ファイルは比較的大きくなります。リンカーは、関数のコードをその場所 (別のオブジェクト ファイルまたは静的にリンクされたライブラリ内) から最終的な実行可能プログラムにコピーします。実行可能ファイルを作成するためにリンカーが完了する必要がある主なタスクは、シンボルの解決 (オブジェクト ファイル内のシンボルの定義と参照を関連付ける) と再配置 (シンボル定義をメモリ アドレスに対応させ、すべての参照を変更する) です。記号に )。
- 動的リンクとは、リンク段階で一部の記述情報のみが追加され、プログラムの実行時に対応する動的ライブラリがシステムからメモリにロードされることを意味します。
- Linuxシステムでは、通常、gccがコンパイルおよびリンクする際の動的ライブラリの検索パスの順序は、最初にgccコマンドのパラメータ-Lで指定されたパスから検索し、次に環境変数LIBRARY_PATHで指定されたパスからアドレスを検索し、その後、デフォルトのパスから検索して /lib、/usr/lib、/usr/local/lib を探します。
- Linux システムでは、通常、バイナリ ファイルを実行する際の動的ライブラリの検索パスの順序は、まずオブジェクト コードのコンパイル時に指定された動的ライブラリの検索パスを検索し、次に環境変数 LD_LIBRARY_PATH で指定されたパスからアドレスを検索し、次にコンフィギュレーションからアドレス指定します。 file /etc/ ld.so.conf で指定された動的ライブラリ検索パス; 次に、デフォルト パス /lib、/usr/lib から検索します。
- Linux システムでは、ldd コマンドを使用して、実行可能プログラムが依存する共有ライブラリーを表示できます。
- 動的ライブラリと静的ライブラリをリンクするためのパスは重複する可能性があるため、libtest.a と libtest.so のように静的ライブラリ ファイルと動的ライブラリ ファイルが同じ名前でパスに存在する場合、gcc はデフォルトで動的ライブラリを優先します。リンク時に libtest.so をリンクします。gcc に libtest.a のリンクを選択させたい場合は、gcc オプション - static を指定できます。これにより、リンクに静的ライブラリの使用が強制されます。例として、Hello World を取り上げます。
- コマンド「gcc hello.c -o hello」を使用すると、動的ライブラリがリンクに使用されます. 生成された ELF 実行ファイルのサイズ (Binutils の size コマンドを使用して表示) およびリンクされた動的ライブラリ (表示する Binutils の ldd コマンド) は次のとおりです。
gcc test.c -o test size test text data bss dec hex filename 1386 600 8 1994 7ca test ldd test linux-vdso.so.1 (0x00007fffb99f4000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fc2a3600000) /lib64/ld-linux-x86-64.so.2 (0x00007fc2a39a9000)
- コマンド「gcc -static hello.c -o hello」を使用すると、スタティック ライブラリがリンクに使用され、生成された ELF 実行可能ファイルのサイズ (Binutils の size コマンドを使用して表示) およびリンクされたダイナミック ライブラリ ( Binutils の ldd コマンドを使用して、次のように表示します。
gcc -static test.c -o test size test text data bss dec hex filename 781877 23240 23016 828133 ca2e5 test ldd test not a dynamic executable
- 上記の結果から、動的にリンクされたファイルは小さく、静的にリンクされたファイルは大きいことがわかります。
- コマンド「gcc hello.c -o hello」を使用すると、動的ライブラリがリンクに使用されます. 生成された ELF 実行ファイルのサイズ (Binutils の size コマンドを使用して表示) およびリンクされた動的ライブラリ (表示する Binutils の ldd コマンド) は次のとおりです。
リンカーによって生成される最終的なファイルは、ELF 形式の実行可能ファイルです. ELF 実行可能ファイルは、通常、.text、.data、.rodata、.bss などのさまざまなセグメントにリンクされます。
ELF ファイルを分析する
ELF ファイルのセクション
ELF ファイルの形式は次のとおりです。ELF ヘッダーとセクション ヘッダー テーブルの間のセクションがセクションです。
ELF header
Program header table
.text
.rodata
...
.data
Section header table
一般的な ELF ファイルには次のセクションが含まれます
- .text: コンパイルされたプログラムの命令コード セグメント。
- .rodata: ro は読み取り専用、つまり読み取り専用データ (定数 const など) を表します。
- .data: 初期化された C プログラムのグローバル変数と静的ローカル変数。
- .bss: 初期化されていない C プログラムのグローバル変数と静的ローカル変数。
- .debug: デバッグ シンボル テーブル。デバッガーはこのセクションの情報を使用してデバッグを支援します (コンパイル時に -g オプションを追加する必要があります)。
readelf -S を使用して、各セクションの情報を表示できます
readelf -S test
上記のコマンドで表示される詳細情報は次のとおりです。
There are 31 section headers, starting at offset 0x3698:
Section Headers:
[Nr] Name Type Address Offset
Size EntSize Flags Link Info Align
[0] NULL 0000000000000000 00000000
0000000000000000 0000000000000000 0 0 0
[1] .interp PROGBITS 0000000000000318 00000318
000000000000001c 0000000000000000 A 0 0 1
[2] .note.gnu.pr[...] NOTE 0000000000000338 00000338
0000000000000030 0000000000000000 A 0 0 8
[3] .note.gnu.bu[...] NOTE 0000000000000368 00000368
0000000000000024 0000000000000000 A 0 0 4
[4] .note.ABI-tag NOTE 000000000000038c 0000038c
0000000000000020 0000000000000000 A 0 0 4
[5] .gnu.hash GNU_HASH 00000000000003b0 000003b0
0000000000000024 0000000000000000 A 6 0 8
[6] .dynsym DYNSYM 00000000000003d8 000003d8
00000000000000a8 0000000000000018 A 7 1 8
[7] .dynstr STRTAB 0000000000000480 00000480
000000000000008d 0000000000000000 A 0 0 1
[8] .gnu.version VERSYM 000000000000050e 0000050e
000000000000000e 0000000000000002 A 6 0 2
[9] .gnu.version_r VERNEED 0000000000000520 00000520
0000000000000030 0000000000000000 A 7 1 8
[10] .rela.dyn RELA 0000000000000550 00000550
00000000000000c0 0000000000000018 A 6 0 8
[11] .rela.plt RELA 0000000000000610 00000610
0000000000000018 0000000000000018 AI 6 24 8
[12] .init PROGBITS 0000000000001000 00001000
000000000000001b 0000000000000000 AX 0 0 4
[13] .plt PROGBITS 0000000000001020 00001020
0000000000000020 0000000000000010 AX 0 0 16
[14] .plt.got PROGBITS 0000000000001040 00001040
0000000000000010 0000000000000010 AX 0 0 16
[15] .plt.sec PROGBITS 0000000000001050 00001050
0000000000000010 0000000000000010 AX 0 0 16
[16] .text PROGBITS 0000000000001060 00001060
0000000000000112 0000000000000000 AX 0 0 16
[17] .fini PROGBITS 0000000000001174 00001174
000000000000000d 0000000000000000 AX 0 0 4
[18] .rodata PROGBITS 0000000000002000 00002000
0000000000000011 0000000000000000 A 0 0 4
[19] .eh_frame_hdr PROGBITS 0000000000002014 00002014
0000000000000034 0000000000000000 A 0 0 4
[20] .eh_frame PROGBITS 0000000000002048 00002048
00000000000000ac 0000000000000000 A 0 0 8
[21] .init_array INIT_ARRAY 0000000000003db8 00002db8
0000000000000008 0000000000000008 WA 0 0 8
[22] .fini_array FINI_ARRAY 0000000000003dc0 00002dc0
0000000000000008 0000000000000008 WA 0 0 8
[23] .dynamic DYNAMIC 0000000000003dc8 00002dc8
00000000000001f0 0000000000000010 WA 7 0 8
[24] .got PROGBITS 0000000000003fb8 00002fb8
0000000000000048 0000000000000008 WA 0 0 8
[25] .data PROGBITS 0000000000004000 00003000
0000000000000010 0000000000000000 WA 0 0 8
[26] .bss NOBITS 0000000000004010 00003010
0000000000000008 0000000000000000 WA 0 0 1
[27] .comment PROGBITS 0000000000000000 00003010
000000000000002b 0000000000000001 MS 0 0 1
[28] .symtab SYMTAB 0000000000000000 00003040
0000000000000360 0000000000000018 29 18 8
[29] .strtab STRTAB 0000000000000000 000033a0
00000000000001da 0000000000000000 0 0 1
[30] .shstrtab STRTAB 0000000000000000 0000357a
000000000000011a 0000000000000000 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
L (link order), O (extra OS processing required), G (group), T (TLS),
C (compressed), x (unknown), o (OS specific), E (exclude),
D (mbind), l (large), p (processor specific)
ELFを分解する
ELF ファイルは通常のテキスト ファイルとして開くことができないため、ELF ファイルに含まれる命令やデータを直接表示する場合は、逆アセンブリの方法を使用する必要があります。
objdump -D で逆アセンブルします
objdump -D test
上記のコマンドによって返される結果の一部は次のとおりです。
0000000000001149 <main>:
1149: f3 0f 1e fa endbr64
114d: 55 push %rbp
114e: 48 89 e5 mov %rsp,%rbp
1151: 48 83 ec 10 sub $0x10,%rsp
1155: 89 7d fc mov %edi,-0x4(%rbp)
1158: 48 89 75 f0 mov %rsi,-0x10(%rbp)
115c: 48 8d 05 a1 0e 00 00 lea 0xea1(%rip),%rax # 2004 <_IO_stdin_used+0x4>
1163: 48 89 c7 mov %rax,%rdi
1166: e8 e5 fe ff ff call 1050 <puts@plt>
116b: b8 00 00 00 00 mov $0x0,%eax
1170: c9 leave
1171: c3 ret
objdump -S を使用して逆アセンブルし、C 言語のソース コードを表示します (コンパイル時に -g オプションを追加する必要があります)。
objdump -S test
上記のコマンドの完全な結果は次のとおりです。
test: file format elf64-x86-64
Disassembly of section .init:
0000000000001000 <_init>:
1000: f3 0f 1e fa endbr64
1004: 48 83 ec 08 sub $0x8,%rsp
1008: 48 8b 05 d9 2f 00 00 mov 0x2fd9(%rip),%rax # 3fe8 <__gmon_start__@Base>
100f: 48 85 c0 test %rax,%rax
1012: 74 02 je 1016 <_init+0x16>
1014: ff d0 call *%rax
1016: 48 83 c4 08 add $0x8,%rsp
101a: c3 ret
Disassembly of section .plt:
0000000000001020 <.plt>:
1020: ff 35 9a 2f 00 00 push 0x2f9a(%rip) # 3fc0 <_GLOBAL_OFFSET_TABLE_+0x8>
1026: f2 ff 25 9b 2f 00 00 bnd jmp *0x2f9b(%rip) # 3fc8 <_GLOBAL_OFFSET_TABLE_+0x10>
102d: 0f 1f 00 nopl (%rax)
1030: f3 0f 1e fa endbr64
1034: 68 00 00 00 00 push $0x0
1039: f2 e9 e1 ff ff ff bnd jmp 1020 <_init+0x20>
103f: 90 nop
Disassembly of section .plt.got:
0000000000001040 <__cxa_finalize@plt>:
1040: f3 0f 1e fa endbr64
1044: f2 ff 25 ad 2f 00 00 bnd jmp *0x2fad(%rip) # 3ff8 <__cxa_finalize@GLIBC_2.2.5>
104b: 0f 1f 44 00 00 nopl 0x0(%rax,%rax,1)
Disassembly of section .plt.sec:
0000000000001050 <puts@plt>:
1050: f3 0f 1e fa endbr64
1054: f2 ff 25 75 2f 00 00 bnd jmp *0x2f75(%rip) # 3fd0 <puts@GLIBC_2.2.5>
105b: 0f 1f 44 00 00 nopl 0x0(%rax,%rax,1)
Disassembly of section .text:
0000000000001060 <_start>:
1060: f3 0f 1e fa endbr64
1064: 31 ed xor %ebp,%ebp
1066: 49 89 d1 mov %rdx,%r9
1069: 5e pop %rsi
106a: 48 89 e2 mov %rsp,%rdx
106d: 48 83 e4 f0 and $0xfffffffffffffff0,%rsp
1071: 50 push %rax
1072: 54 push %rsp
1073: 45 31 c0 xor %r8d,%r8d
1076: 31 c9 xor %ecx,%ecx
1078: 48 8d 3d ca 00 00 00 lea 0xca(%rip),%rdi # 1149 <main>
107f: ff 15 53 2f 00 00 call *0x2f53(%rip) # 3fd8 <__libc_start_main@GLIBC_2.34>
1085: f4 hlt
1086: 66 2e 0f 1f 84 00 00 cs nopw 0x0(%rax,%rax,1)
108d: 00 00 00
0000000000001090 <deregister_tm_clones>:
1090: 48 8d 3d 79 2f 00 00 lea 0x2f79(%rip),%rdi # 4010 <__TMC_END__>
1097: 48 8d 05 72 2f 00 00 lea 0x2f72(%rip),%rax # 4010 <__TMC_END__>
109e: 48 39 f8 cmp %rdi,%rax
10a1: 74 15 je 10b8 <deregister_tm_clones+0x28>
10a3: 48 8b 05 36 2f 00 00 mov 0x2f36(%rip),%rax # 3fe0 <_ITM_deregisterTMCloneTable@Base>
10aa: 48 85 c0 test %rax,%rax
10ad: 74 09 je 10b8 <deregister_tm_clones+0x28>
10af: ff e0 jmp *%rax
10b1: 0f 1f 80 00 00 00 00 nopl 0x0(%rax)
10b8: c3 ret
10b9: 0f 1f 80 00 00 00 00 nopl 0x0(%rax)
00000000000010c0 <register_tm_clones>:
10c0: 48 8d 3d 49 2f 00 00 lea 0x2f49(%rip),%rdi # 4010 <__TMC_END__>
10c7: 48 8d 35 42 2f 00 00 lea 0x2f42(%rip),%rsi # 4010 <__TMC_END__>
10ce: 48 29 fe sub %rdi,%rsi
10d1: 48 89 f0 mov %rsi,%rax
10d4: 48 c1 ee 3f shr $0x3f,%rsi
10d8: 48 c1 f8 03 sar $0x3,%rax
10dc: 48 01 c6 add %rax,%rsi
10df: 48 d1 fe sar %rsi
10e2: 74 14 je 10f8 <register_tm_clones+0x38>
10e4: 48 8b 05 05 2f 00 00 mov 0x2f05(%rip),%rax # 3ff0 <_ITM_registerTMCloneTable@Base>
10eb: 48 85 c0 test %rax,%rax
10ee: 74 08 je 10f8 <register_tm_clones+0x38>
10f0: ff e0 jmp *%rax
10f2: 66 0f 1f 44 00 00 nopw 0x0(%rax,%rax,1)
10f8: c3 ret
10f9: 0f 1f 80 00 00 00 00 nopl 0x0(%rax)
0000000000001100 <__do_global_dtors_aux>:
1100: f3 0f 1e fa endbr64
1104: 80 3d 05 2f 00 00 00 cmpb $0x0,0x2f05(%rip) # 4010 <__TMC_END__>
110b: 75 2b jne 1138 <__do_global_dtors_aux+0x38>
110d: 55 push %rbp
110e: 48 83 3d e2 2e 00 00 cmpq $0x0,0x2ee2(%rip) # 3ff8 <__cxa_finalize@GLIBC_2.2.5>
1115: 00
1116: 48 89 e5 mov %rsp,%rbp
1119: 74 0c je 1127 <__do_global_dtors_aux+0x27>
111b: 48 8b 3d e6 2e 00 00 mov 0x2ee6(%rip),%rdi # 4008 <__dso_handle>
1122: e8 19 ff ff ff call 1040 <__cxa_finalize@plt>
1127: e8 64 ff ff ff call 1090 <deregister_tm_clones>
112c: c6 05 dd 2e 00 00 01 movb $0x1,0x2edd(%rip) # 4010 <__TMC_END__>
1133: 5d pop %rbp
1134: c3 ret
1135: 0f 1f 00 nopl (%rax)
1138: c3 ret
1139: 0f 1f 80 00 00 00 00 nopl 0x0(%rax)
0000000000001140 <frame_dummy>:
1140: f3 0f 1e fa endbr64
1144: e9 77 ff ff ff jmp 10c0 <register_tm_clones>
0000000000001149 <main>:
#include<stdio.h>
int main(int argc, char *argv[])
{
1149: f3 0f 1e fa endbr64
114d: 55 push %rbp
114e: 48 89 e5 mov %rsp,%rbp
1151: 48 83 ec 10 sub $0x10,%rsp
1155: 89 7d fc mov %edi,-0x4(%rbp)
1158: 48 89 75 f0 mov %rsi,-0x10(%rbp)
printf("hello world\r\n");
115c: 48 8d 05 a1 0e 00 00 lea 0xea1(%rip),%rax # 2004 <_IO_stdin_used+0x4>
1163: 48 89 c7 mov %rax,%rdi
1166: e8 e5 fe ff ff call 1050 <puts@plt>
return 0;
116b: b8 00 00 00 00 mov $0x0,%eax
1170: c9 leave
1171: c3 ret
Disassembly of section .fini:
0000000000001174 <_fini>:
1174: f3 0f 1e fa endbr64
1178: 48 83 ec 08 sub $0x8,%rsp
117c: 48 83 c4 08 add $0x8,%rsp
1180: c3 ret