DEV Community

Ahmet Can Gulmez
Ahmet Can Gulmez

Posted on

Binary Analysis Fundamentals

In this post, I'll explain and investigate the Executable and Linkable Format (ELF), which is the default binary format on Linux-based systems.

To make practices, I've written a simple copy.c source file and we will investigate this:

/**
 * Copying a file content to another one.
 */

#include "../linux.h"

#ifndef BUF_SIZE
#define BUF_SIZE  1024
#endif

void main(int argc, char *argv[])
{
   int inputFd, outputFd, openFlags;
   mode_t filePerms;
   ssize_t numRead;
   char buf[BUF_SIZE];

   if (argc != 3 || strcmp(argv[1], "--help") == 0)
      usage_error("Wrong command-line usage");

   /* Open input and output files */

   inputFd = open(argv[1], O_RDONLY);
   if (inputFd)
      syscall_error(); 

   openFlags = O_CREAT | O_WRONLY | O_TRUNC;
   filePerms = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP |
               S_IROTH | S_IWOTH;  /* rw-rw-rw- */

   outputFd = open(argv[2], openFlags, filePerms);
   if (outputFd == -1)
      syscall_error();

   /* Transfer data until we encounter end of input or an error */

   while ((numRead == read(inputFd, buf, BUF_SIZE)) > 0)
      if (write(outputFd, buf, numRead) != numRead)
         syscall_error();
   if (numRead == -1)
      syscall_error();

   if (close(inputFd) == -1)
      syscall_error();
   if (close(outputFd) == -1)
      syscall_error();

   exit(EXIT_SUCCESS);
}
Enter fullscreen mode Exit fullscreen mode

Compile this program like this:

$ gcc copy.c -o copy -O0 -g
Enter fullscreen mode Exit fullscreen mode

Binary Composition

Firstly, let's look at binary composition. A binary includes many headers, sections and areas that lets the CPU to run required machine instructions. Below is the 64-bit ELF binary layout:

Every ELF file starts with an executable header, which is just a structured series of bytes telling you that it's an ELF file, what kind of ELF file it is, and where in the file to find all the other contents. It is defined in /usr/include/elf.h and can be seen the executable header with readelf command:

$ readelf -h copy

ELF Header:
  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 
  Class:                             ELF64
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              DYN (Position-Independent Executable file)
  Machine:                           Advanced Micro Devices X86-64
  Version:                           0x1
  Entry point address:               0x1160
  Start of program headers:          64 (bytes into file)
  Start of section headers:          17496 (bytes into file)
  Flags:                             0x0
  Size of this header:               64 (bytes)
  Size of program headers:           56 (bytes)
  Number of program headers:         13
  Size of section headers:           64 (bytes)
  Number of section headers:         37
  Section header string table index: 36
Enter fullscreen mode Exit fullscreen mode

The code and data in an ELF binary are logically divided into contiguous nonoverlapping chunks called sections. Sections don't have any predetermined structure; instead, the structure of each section varies depending on the contents. Every section is described by a section header, which denotes the properties of the section and allows you to locate the bytes belonging to the section. The section headers for all sections in the binary are contained in the section header table.

Typical ELF files that you'll find on a GNU/Linux system are organized into a series of standard sections. Let's see the section names of our binary.

$ readelf --sections --wide copy

There are 37 section headers, starting at offset 0x4458:

Section Headers:
  [Nr] Name              Type            Address          Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            0000000000000000 000000 000000 00      0   0  0
  [ 1] .interp           PROGBITS        0000000000000318 000318 00001c 00   A  0   0  1
  [ 2] .note.gnu.property NOTE            0000000000000338 000338 000030 00   A  0   0  8
  [ 3] .note.gnu.build-id NOTE            0000000000000368 000368 000024 00   A  0   0  4
  [ 4] .note.ABI-tag     NOTE            000000000000038c 00038c 000020 00   A  0   0  4
  [ 5] .gnu.hash         GNU_HASH        00000000000003b0 0003b0 000028 00   A  6   0  8
  [ 6] .dynsym           DYNSYM          00000000000003d8 0003d8 000180 18   A  7   1  8
  [ 7] .dynstr           STRTAB          0000000000000558 000558 0000d3 00   A  0   0  1
  [ 8] .gnu.version      VERSYM          000000000000062c 00062c 000020 02   A  6   0  2
  [ 9] .gnu.version_r    VERNEED         0000000000000650 000650 000030 00   A  7   1  8
  [10] .rela.dyn         RELA            0000000000000680 000680 0000d8 18   A  6   0  8
  [11] .rela.plt         RELA            0000000000000758 000758 0000d8 18  AI  6  24  8
  [12] .init             PROGBITS        0000000000001000 001000 00001b 00  AX  0   0  4
  [13] .plt              PROGBITS        0000000000001020 001020 0000a0 10  AX  0   0 16
  [14] .plt.got          PROGBITS        00000000000010c0 0010c0 000010 10  AX  0   0 16
  [15] .plt.sec          PROGBITS        00000000000010d0 0010d0 000090 10  AX  0   0 16
  [16] .text             PROGBITS        0000000000001160 001160 00043a 00  AX  0   0 16
  [17] .fini             PROGBITS        000000000000159c 00159c 00000d 00  AX  0   0  4
  [18] .rodata           PROGBITS        0000000000002000 002000 000040 00   A  0   0  4
  [19] .eh_frame_hdr     PROGBITS        0000000000002040 002040 000034 00   A  0   0  4
  [20] .eh_frame         PROGBITS        0000000000002078 002078 0000a8 00   A  0   0  8
  [21] .init_array       INIT_ARRAY      0000000000003d78 002d78 000008 08  WA  0   0  8
  [22] .fini_array       FINI_ARRAY      0000000000003d80 002d80 000008 08  WA  0   0  8
  [23] .dynamic          DYNAMIC         0000000000003d88 002d88 0001f0 10  WA  7   0  8
  [24] .got              PROGBITS        0000000000003f78 002f78 000088 08  WA  0   0  8
  [25] .data             PROGBITS        0000000000004000 003000 000010 00  WA  0   0  8
  [26] .bss              NOBITS          0000000000004020 003010 000010 00  WA  0   0 32
  [27] .comment          PROGBITS        0000000000000000 003010 00002b 01  MS  0   0  1
  [28] .debug_aranges    PROGBITS        0000000000000000 00303b 000030 00      0   0  1
  [29] .debug_info       PROGBITS        0000000000000000 00306b 000472 00      0   0  1
  [30] .debug_abbrev     PROGBITS        0000000000000000 0034dd 000184 00      0   0  1
  [31] .debug_line       PROGBITS        0000000000000000 003661 00017e 00      0   0  1
  [32] .debug_str        PROGBITS        0000000000000000 0037df 00031a 01  MS  0   0  1
  [33] .debug_line_str   PROGBITS        0000000000000000 003af9 00012f 01  MS  0   0  1
  [34] .symtab           SYMTAB          0000000000000000 003c28 000438 18     35  18  8
  [35] .strtab           STRTAB          0000000000000000 004060 00028c 00      0   0  1
  [36] .shstrtab         STRTAB          0000000000000000 0042ec 00016a 00      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)
Enter fullscreen mode Exit fullscreen mode

For each section, readelf shows the relevant basic information, including the index, name, type of the sections. Let's focus on some important section names:

  • .init and .fini: The .init section contains executable code that performs initialization tasks and needs to run before any other code in the binary is executed like a constructor. .fini runs after the main program completes like a destructor.

  • .text: The .text section is where the main code of the program resides, so it will frequently be the main focus of your binary analysis or reverse engineering efforts.

  • The .bss, .data and .rodata: The program variables are kept in one or more dedicated sections, which are writable (.text is just readable). .bss is used to store uninitialized data and .data for initialized data. .rodata is also for constant (look for const keyword) variables.

Let's see the .rodata section:

$ objdump -sj .rodata -d copy

copy:     file format elf64-x86-64

Contents of section .rodata:
 2000 01000200 2d2d6865 6c700063 6f70792e  ....--help.copy.
 2010 63005772 6f6e6720 636f6d6d 616e642d  c.Wrong command-
 2020 6c696e65 20757361 6765002a 2a2a2025  line usage.*** %
 2030 73202825 733a3a25 6429202a 2a2a0a00  s (%s::%d) ***..

Disassembly of section .rodata:

0000000000002000 <_IO_stdin_used>:
    2000:   01 00 02 00 2d 2d 68 65 6c 70 00 63 6f 70 79 2e     ....--help.copy.
    2010:   63 00 57 72 6f 6e 67 20 63 6f 6d 6d 61 6e 64 2d     c.Wrong command-
    2020:   6c 69 6e 65 20 75 73 61 67 65 00 2a 2a 2a 20 25     line usage.*** %
    2030:   73 20 28 25 73 3a 3a 25 64 29 20 2a 2a 2a 0a 00     s (%s::%d) ***..
Enter fullscreen mode Exit fullscreen mode

The program header table provides a segment view of the binary, as opposed to the section view provided by the section header table. The section view of an ELF binary is meant for static linking purposes only.

Binary Analysis

After looked at the ELF binary composition, right now, I'll introduce the basic binary analysis in Linux. For this purpose, I will use these commands:

  • file

  • ldd

  • xdd

  • readelf

  • strings

  • strace

  • ltrace

  • objdump

  • gdb

file command shows the basic information about the binary itself.

$ file copy
copy: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=e09844bc261dfab16c73facffe7995c19483be17, for GNU/Linux 3.2.0, with debug_info, not stripped
Enter fullscreen mode Exit fullscreen mode

You can see that this binary is 64-bit ELF and host architecture is x86-64.

ldd command is used to find out on which shared object a binary depends and where (if anywhere) these dependencies are on your system.

$ ldd -v copy
    linux-vdso.so.1 (0x00007ffd7da09000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x0000786bc4400000)
    /lib64/ld-linux-x86-64.so.2 (0x0000786bc47bd000)

    Version information:
    ./copy:
        libc.so.6 (GLIBC_2.2.5) => /lib/x86_64-linux-gnu/libc.so.6
        libc.so.6 (GLIBC_2.34) => /lib/x86_64-linux-gnu/libc.so.6
    /lib/x86_64-linux-gnu/libc.so.6:
        ld-linux-x86-64.so.2 (GLIBC_2.2.5) => /lib64/ld-linux-x86-64.so.2
        ld-linux-x86-64.so.2 (GLIBC_2.3) => /lib64/ld-linux-x86-64.so.2
        ld-linux-x86-64.so.2 (GLIBC_PRIVATE) => /lib64/ld-linux-x86-64.so.2
Enter fullscreen mode Exit fullscreen mode

With xxd command, you can see the binary at byte-level. As you guest, it is not human readable and very long. But I put the beginning and last a few lines of its output.

$ xxd copy

00000000: 7f45 4c46 0201 0100 0000 0000 0000 0000  .ELF............
00000010: 0300 3e00 0100 0000 6011 0000 0000 0000  ..>.....`.......
00000020: 4000 0000 0000 0000 5844 0000 0000 0000  @.......XD......
00000030: 0000 0000 4000 3800 0d00 4000 2500 2400  ....@.8...@.%.$.
00000040: 0600 0000 0400 0000 4000 0000 0000 0000  ........@.......

... (other binary bytes) ...

00004d60: 0000 0000 0000 0000 0000 0000 0000 0000  ................
00004d70: ec42 0000 0000 0000 6a01 0000 0000 0000  .B......j.......
00004d80: 0000 0000 0000 0000 0100 0000 0000 0000  ................
00004d90: 0000 0000 0000 0000                      ........
Enter fullscreen mode Exit fullscreen mode

To view the details of the ELF headers, sections, areas; readelf command is the gold command. But I've shown its usage before. So I pass it directly.

To figure out what a binary does and what kinds of inputs it expects, you can check whether the binary contains any helpful strings that can reveal its purpose with strings command.

$ strings copy | grep -E "open|read|write|close"
read
open
close
write
close
write
_IO_write_ptr
read
openFlags
_IO_write_base
_IO_read_end
_IO_read_ptr
_IO_write_end
_IO_read_base
open
write@GLIBC_2.2.5
close@GLIBC_2.2.5
read@GLIBC_2.2.5
open@GLIBC_2.2.5
Enter fullscreen mode Exit fullscreen mode

strace command is used to trace the system calls when running a binary.

$ strace ./copy
execve("./copy", ["./copy"], 0x7ffe3bcf3de0 /* 58 vars */) = 0
brk(NULL)                               = 0x5f159129e000
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7379e0da1000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=128899, ...}) = 0
mmap(NULL, 128899, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7379e0d45000
close(3)                                = 0
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\220\243\2\0\0\0\0\0"..., 832) = 832
pread64(3, "\6\0\0\0\4\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0"..., 784, 64) = 784
fstat(3, {st_mode=S_IFREG|0755, st_size=2125328, ...}) = 0
pread64(3, "\6\0\0\0\4\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0"..., 784, 64) = 784
mmap(NULL, 2170256, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7379e0a00000
mmap(0x7379e0a28000, 1605632, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x28000) = 0x7379e0a28000
mmap(0x7379e0bb0000, 323584, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1b0000) = 0x7379e0bb0000
mmap(0x7379e0bff000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1fe000) = 0x7379e0bff000
mmap(0x7379e0c05000, 52624, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7379e0c05000
close(3)                                = 0
mmap(NULL, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7379e0d42000
arch_prctl(ARCH_SET_FS, 0x7379e0d42740) = 0
set_tid_address(0x7379e0d42a10)         = 22680
set_robust_list(0x7379e0d42a20, 24)     = 0
rseq(0x7379e0d43060, 0x20, 0, 0x53053053) = 0
mprotect(0x7379e0bff000, 16384, PROT_READ) = 0
mprotect(0x5f156087f000, 4096, PROT_READ) = 0
mprotect(0x7379e0d9b000, 8192, PROT_READ) = 0
prlimit64(0, RLIMIT_STACK, NULL, {rlim_cur=8192*1024, rlim_max=RLIM64_INFINITY}) = 0
munmap(0x7379e0d45000, 128899)          = 0
write(2, "*** Wrong command-line usage (co"..., 46*** Wrong command-line usage (copy.c::17) ***
) = 46
exit_group(1)                           = ?
+++ exited with 1 +++
Enter fullscreen mode Exit fullscreen mode

lstrace command, as opposed to strace, is used to trace the library calls.

$ ltrace ./copy
fprintf(0x796bcfc044e0, "*** %s (%s::%d) ***\n", "Wrong command-line usage", "copy.c", 17*** Wrong command-line usage (copy.c::17) ***
) = 46
exit(1 <no return ...>
+++ exited (status 1) +++
Enter fullscreen mode Exit fullscreen mode

objdump command is another popular tool when analyzing a binary content. It's multi-purpose command and can be used for numerous stuffs. I just show here the disassemble functionality.

$ objdump --disassemble copy

copy:     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 5a 2f 00 00       push   0x2f5a(%rip)        # 3f80 <_GLOBAL_OFFSET_TABLE_+0x8>
    1026:   ff 25 5c 2f 00 00       jmp    *0x2f5c(%rip)        # 3f88 <_GLOBAL_OFFSET_TABLE_+0x10>
    102c:   0f 1f 40 00             nopl   0x0(%rax)
    1030:   f3 0f 1e fa             endbr64
    1034:   68 00 00 00 00          push   $0x0
    1039:   e9 e2 ff ff ff          jmp    1020 <_init+0x20>
    103e:   66 90                   xchg   %ax,%ax
    1040:   f3 0f 1e fa             endbr64
    1044:   68 01 00 00 00          push   $0x1
    1049:   e9 d2 ff ff ff          jmp    1020 <_init+0x20>
    104e:   66 90                   xchg   %ax,%ax
    1050:   f3 0f 1e fa             endbr64
    1054:   68 02 00 00 00          push   $0x2
    1059:   e9 c2 ff ff ff          jmp    1020 <_init+0x20>
    105e:   66 90                   xchg   %ax,%ax
    1060:   f3 0f 1e fa             endbr64
    1064:   68 03 00 00 00          push   $0x3
    1069:   e9 b2 ff ff ff          jmp    1020 <_init+0x20>
    106e:   66 90                   xchg   %ax,%ax
    1070:   f3 0f 1e fa             endbr64
    1074:   68 04 00 00 00          push   $0x4
    1079:   e9 a2 ff ff ff          jmp    1020 <_init+0x20>
    107e:   66 90                   xchg   %ax,%ax
    1080:   f3 0f 1e fa             endbr64
    1084:   68 05 00 00 00          push   $0x5
    1089:   e9 92 ff ff ff          jmp    1020 <_init+0x20>
    108e:   66 90                   xchg   %ax,%ax
    1090:   f3 0f 1e fa             endbr64
    1094:   68 06 00 00 00          push   $0x6
    1099:   e9 82 ff ff ff          jmp    1020 <_init+0x20>
    109e:   66 90                   xchg   %ax,%ax
    10a0:   f3 0f 1e fa             endbr64
    10a4:   68 07 00 00 00          push   $0x7
    10a9:   e9 72 ff ff ff          jmp    1020 <_init+0x20>
    10ae:   66 90                   xchg   %ax,%ax
    10b0:   f3 0f 1e fa             endbr64
    10b4:   68 08 00 00 00          push   $0x8
    10b9:   e9 62 ff ff ff          jmp    1020 <_init+0x20>
    10be:   66 90                   xchg   %ax,%ax

Disassembly of section .plt.got:

00000000000010c0 <__cxa_finalize@plt>:
    10c0:   f3 0f 1e fa             endbr64
    10c4:   ff 25 2e 2f 00 00       jmp    *0x2f2e(%rip)        # 3ff8 <__cxa_finalize@GLIBC_2.2.5>
    10ca:   66 0f 1f 44 00 00       nopw   0x0(%rax,%rax,1)

Disassembly of section .plt.sec:

00000000000010d0 <__errno_location@plt>:
    10d0:   f3 0f 1e fa             endbr64
    10d4:   ff 25 b6 2e 00 00       jmp    *0x2eb6(%rip)        # 3f90 <__errno_location@GLIBC_2.2.5>
    10da:   66 0f 1f 44 00 00       nopw   0x0(%rax,%rax,1)

00000000000010e0 <write@plt>:
    10e0:   f3 0f 1e fa             endbr64
    10e4:   ff 25 ae 2e 00 00       jmp    *0x2eae(%rip)        # 3f98 <write@GLIBC_2.2.5>
    10ea:   66 0f 1f 44 00 00       nopw   0x0(%rax,%rax,1)

00000000000010f0 <close@plt>:
    10f0:   f3 0f 1e fa             endbr64
    10f4:   ff 25 a6 2e 00 00       jmp    *0x2ea6(%rip)        # 3fa0 <close@GLIBC_2.2.5>
    10fa:   66 0f 1f 44 00 00       nopw   0x0(%rax,%rax,1)

0000000000001100 <read@plt>:
    1100:   f3 0f 1e fa             endbr64
    1104:   ff 25 9e 2e 00 00       jmp    *0x2e9e(%rip)        # 3fa8 <read@GLIBC_2.2.5>
    110a:   66 0f 1f 44 00 00       nopw   0x0(%rax,%rax,1)

0000000000001110 <strcmp@plt>:
    1110:   f3 0f 1e fa             endbr64
    1114:   ff 25 96 2e 00 00       jmp    *0x2e96(%rip)        # 3fb0 <strcmp@GLIBC_2.2.5>
    111a:   66 0f 1f 44 00 00       nopw   0x0(%rax,%rax,1)

0000000000001120 <fprintf@plt>:
    1120:   f3 0f 1e fa             endbr64
    1124:   ff 25 8e 2e 00 00       jmp    *0x2e8e(%rip)        # 3fb8 <fprintf@GLIBC_2.2.5>
    112a:   66 0f 1f 44 00 00       nopw   0x0(%rax,%rax,1)

0000000000001130 <open@plt>:
    1130:   f3 0f 1e fa             endbr64
    1134:   ff 25 86 2e 00 00       jmp    *0x2e86(%rip)        # 3fc0 <open@GLIBC_2.2.5>
    113a:   66 0f 1f 44 00 00       nopw   0x0(%rax,%rax,1)

0000000000001140 <exit@plt>:
    1140:   f3 0f 1e fa             endbr64
    1144:   ff 25 7e 2e 00 00       jmp    *0x2e7e(%rip)        # 3fc8 <exit@GLIBC_2.2.5>
    114a:   66 0f 1f 44 00 00       nopw   0x0(%rax,%rax,1)

0000000000001150 <strerror@plt>:
    1150:   f3 0f 1e fa             endbr64
    1154:   ff 25 76 2e 00 00       jmp    *0x2e76(%rip)        # 3fd0 <strerror@GLIBC_2.2.5>
    115a:   66 0f 1f 44 00 00       nopw   0x0(%rax,%rax,1)

Disassembly of section .text:

0000000000001160 <_start>:
    1160:   f3 0f 1e fa             endbr64
    1164:   31 ed                   xor    %ebp,%ebp
    1166:   49 89 d1                mov    %rdx,%r9
    1169:   5e                      pop    %rsi
    116a:   48 89 e2                mov    %rsp,%rdx
    116d:   48 83 e4 f0             and    $0xfffffffffffffff0,%rsp
    1171:   50                      push   %rax
    1172:   54                      push   %rsp
    1173:   45 31 c0                xor    %r8d,%r8d
    1176:   31 c9                   xor    %ecx,%ecx
    1178:   48 8d 3d ca 00 00 00    lea    0xca(%rip),%rdi        # 1249 <main>
    117f:   ff 15 53 2e 00 00       call   *0x2e53(%rip)        # 3fd8 <__libc_start_main@GLIBC_2.34>
    1185:   f4                      hlt
    1186:   66 2e 0f 1f 84 00 00    cs nopw 0x0(%rax,%rax,1)
    118d:   00 00 00 

0000000000001190 <deregister_tm_clones>:
    1190:   48 8d 3d 79 2e 00 00    lea    0x2e79(%rip),%rdi        # 4010 <__TMC_END__>
    1197:   48 8d 05 72 2e 00 00    lea    0x2e72(%rip),%rax        # 4010 <__TMC_END__>
    119e:   48 39 f8                cmp    %rdi,%rax
    11a1:   74 15                   je     11b8 <deregister_tm_clones+0x28>
    11a3:   48 8b 05 36 2e 00 00    mov    0x2e36(%rip),%rax        # 3fe0 <_ITM_deregisterTMCloneTable@Base>
    11aa:   48 85 c0                test   %rax,%rax
    11ad:   74 09                   je     11b8 <deregister_tm_clones+0x28>
    11af:   ff e0                   jmp    *%rax
    11b1:   0f 1f 80 00 00 00 00    nopl   0x0(%rax)
    11b8:   c3                      ret
    11b9:   0f 1f 80 00 00 00 00    nopl   0x0(%rax)

00000000000011c0 <register_tm_clones>:
    11c0:   48 8d 3d 49 2e 00 00    lea    0x2e49(%rip),%rdi        # 4010 <__TMC_END__>
    11c7:   48 8d 35 42 2e 00 00    lea    0x2e42(%rip),%rsi        # 4010 <__TMC_END__>
    11ce:   48 29 fe                sub    %rdi,%rsi
    11d1:   48 89 f0                mov    %rsi,%rax
    11d4:   48 c1 ee 3f             shr    $0x3f,%rsi
    11d8:   48 c1 f8 03             sar    $0x3,%rax
    11dc:   48 01 c6                add    %rax,%rsi
    11df:   48 d1 fe                sar    $1,%rsi
    11e2:   74 14                   je     11f8 <register_tm_clones+0x38>
    11e4:   48 8b 05 05 2e 00 00    mov    0x2e05(%rip),%rax        # 3ff0 <_ITM_registerTMCloneTable@Base>
    11eb:   48 85 c0                test   %rax,%rax
    11ee:   74 08                   je     11f8 <register_tm_clones+0x38>
    11f0:   ff e0                   jmp    *%rax
    11f2:   66 0f 1f 44 00 00       nopw   0x0(%rax,%rax,1)
    11f8:   c3                      ret
    11f9:   0f 1f 80 00 00 00 00    nopl   0x0(%rax)

0000000000001200 <__do_global_dtors_aux>:
    1200:   f3 0f 1e fa             endbr64
    1204:   80 3d 1d 2e 00 00 00    cmpb   $0x0,0x2e1d(%rip)        # 4028 <completed.0>
    120b:   75 2b                   jne    1238 <__do_global_dtors_aux+0x38>
    120d:   55                      push   %rbp
    120e:   48 83 3d e2 2d 00 00    cmpq   $0x0,0x2de2(%rip)        # 3ff8 <__cxa_finalize@GLIBC_2.2.5>
    1215:   00 
    1216:   48 89 e5                mov    %rsp,%rbp
    1219:   74 0c                   je     1227 <__do_global_dtors_aux+0x27>
    121b:   48 8b 3d e6 2d 00 00    mov    0x2de6(%rip),%rdi        # 4008 <__dso_handle>
    1222:   e8 99 fe ff ff          call   10c0 <__cxa_finalize@plt>
    1227:   e8 64 ff ff ff          call   1190 <deregister_tm_clones>
    122c:   c6 05 f5 2d 00 00 01    movb   $0x1,0x2df5(%rip)        # 4028 <completed.0>
    1233:   5d                      pop    %rbp
    1234:   c3                      ret
    1235:   0f 1f 00                nopl   (%rax)
    1238:   c3                      ret
    1239:   0f 1f 80 00 00 00 00    nopl   0x0(%rax)

0000000000001240 <frame_dummy>:
    1240:   f3 0f 1e fa             endbr64
    1244:   e9 77 ff ff ff          jmp    11c0 <register_tm_clones>

0000000000001249 <main>:
    1249:   f3 0f 1e fa             endbr64
    124d:   55                      push   %rbp
    124e:   48 89 e5                mov    %rsp,%rbp
    1251:   48 81 ec 40 04 00 00    sub    $0x440,%rsp
    1258:   89 bd cc fb ff ff       mov    %edi,-0x434(%rbp)
    125e:   48 89 b5 c0 fb ff ff    mov    %rsi,-0x440(%rbp)
    1265:   64 48 8b 04 25 28 00    mov    %fs:0x28,%rax
    126c:   00 00 
    126e:   48 89 45 f8             mov    %rax,-0x8(%rbp)
    1272:   31 c0                   xor    %eax,%eax
    1274:   83 bd cc fb ff ff 03    cmpl   $0x3,-0x434(%rbp)
    127b:   75 24                   jne    12a1 <main+0x58>
    127d:   48 8b 85 c0 fb ff ff    mov    -0x440(%rbp),%rax
    1284:   48 83 c0 08             add    $0x8,%rax
    1288:   48 8b 00                mov    (%rax),%rax
    128b:   48 8d 15 72 0d 00 00    lea    0xd72(%rip),%rdx        # 2004 <_IO_stdin_used+0x4>
    1292:   48 89 d6                mov    %rdx,%rsi
    1295:   48 89 c7                mov    %rax,%rdi
    1298:   e8 73 fe ff ff          call   1110 <strcmp@plt>
    129d:   85 c0                   test   %eax,%eax
    129f:   75 3c                   jne    12dd <main+0x94>
    12a1:   48 8b 05 78 2d 00 00    mov    0x2d78(%rip),%rax        # 4020 <stderr@GLIBC_2.2.5>
    12a8:   41 b8 11 00 00 00       mov    $0x11,%r8d
    12ae:   48 8d 15 56 0d 00 00    lea    0xd56(%rip),%rdx        # 200b <_IO_stdin_used+0xb>
    12b5:   48 89 d1                mov    %rdx,%rcx
    12b8:   48 8d 15 53 0d 00 00    lea    0xd53(%rip),%rdx        # 2012 <_IO_stdin_used+0x12>
    12bf:   48 8d 35 65 0d 00 00    lea    0xd65(%rip),%rsi        # 202b <_IO_stdin_used+0x2b>
    12c6:   48 89 c7                mov    %rax,%rdi
    12c9:   b8 00 00 00 00          mov    $0x0,%eax
    12ce:   e8 4d fe ff ff          call   1120 <fprintf@plt>
    12d3:   bf 01 00 00 00          mov    $0x1,%edi
    12d8:   e8 63 fe ff ff          call   1140 <exit@plt>
    12dd:   48 8b 85 c0 fb ff ff    mov    -0x440(%rbp),%rax
    12e4:   48 83 c0 08             add    $0x8,%rax
    12e8:   48 8b 00                mov    (%rax),%rax
    12eb:   be 00 00 00 00          mov    $0x0,%esi
    12f0:   48 89 c7                mov    %rax,%rdi
    12f3:   b8 00 00 00 00          mov    $0x0,%eax
    12f8:   e8 33 fe ff ff          call   1130 <open@plt>
    12fd:   89 85 d8 fb ff ff       mov    %eax,-0x428(%rbp)
    1303:   83 bd d8 fb ff ff 00    cmpl   $0x0,-0x428(%rbp)
    130a:   74 49                   je     1355 <main+0x10c>
    130c:   e8 bf fd ff ff          call   10d0 <__errno_location@plt>
    1311:   8b 00                   mov    (%rax),%eax
    1313:   89 c7                   mov    %eax,%edi
    1315:   e8 36 fe ff ff          call   1150 <strerror@plt>
    131a:   48 89 c6                mov    %rax,%rsi
    131d:   48 8b 05 fc 2c 00 00    mov    0x2cfc(%rip),%rax        # 4020 <stderr@GLIBC_2.2.5>
    1324:   41 b8 17 00 00 00       mov    $0x17,%r8d
    132a:   48 8d 15 da 0c 00 00    lea    0xcda(%rip),%rdx        # 200b <_IO_stdin_used+0xb>
    1331:   48 89 d1                mov    %rdx,%rcx
    1334:   48 89 f2                mov    %rsi,%rdx
    1337:   48 8d 35 ed 0c 00 00    lea    0xced(%rip),%rsi        # 202b <_IO_stdin_used+0x2b>
    133e:   48 89 c7                mov    %rax,%rdi
    1341:   b8 00 00 00 00          mov    $0x0,%eax
    1346:   e8 d5 fd ff ff          call   1120 <fprintf@plt>
    134b:   bf 01 00 00 00          mov    $0x1,%edi
    1350:   e8 eb fd ff ff          call   1140 <exit@plt>
    1355:   c7 85 dc fb ff ff 41    movl   $0x241,-0x424(%rbp)
    135c:   02 00 00 
    135f:   c7 85 e0 fb ff ff b6    movl   $0x1b6,-0x420(%rbp)
    1366:   01 00 00 
    1369:   48 8b 85 c0 fb ff ff    mov    -0x440(%rbp),%rax
    1370:   48 83 c0 10             add    $0x10,%rax
    1374:   48 8b 00                mov    (%rax),%rax
    1377:   8b 95 e0 fb ff ff       mov    -0x420(%rbp),%edx
    137d:   8b 8d dc fb ff ff       mov    -0x424(%rbp),%ecx
    1383:   89 ce                   mov    %ecx,%esi
    1385:   48 89 c7                mov    %rax,%rdi
    1388:   b8 00 00 00 00          mov    $0x0,%eax
    138d:   e8 9e fd ff ff          call   1130 <open@plt>
    1392:   89 85 e4 fb ff ff       mov    %eax,-0x41c(%rbp)
    1398:   83 bd e4 fb ff ff ff    cmpl   $0xffffffff,-0x41c(%rbp)
    139f:   0f 85 b9 00 00 00       jne    145e <main+0x215>
    13a5:   e8 26 fd ff ff          call   10d0 <__errno_location@plt>
    13aa:   8b 00                   mov    (%rax),%eax
    13ac:   89 c7                   mov    %eax,%edi
    13ae:   e8 9d fd ff ff          call   1150 <strerror@plt>
    13b3:   48 89 c6                mov    %rax,%rsi
    13b6:   48 8b 05 63 2c 00 00    mov    0x2c63(%rip),%rax        # 4020 <stderr@GLIBC_2.2.5>
    13bd:   41 b8 1f 00 00 00       mov    $0x1f,%r8d
    13c3:   48 8d 15 41 0c 00 00    lea    0xc41(%rip),%rdx        # 200b <_IO_stdin_used+0xb>
    13ca:   48 89 d1                mov    %rdx,%rcx
    13cd:   48 89 f2                mov    %rsi,%rdx
    13d0:   48 8d 35 54 0c 00 00    lea    0xc54(%rip),%rsi        # 202b <_IO_stdin_used+0x2b>
    13d7:   48 89 c7                mov    %rax,%rdi
    13da:   b8 00 00 00 00          mov    $0x0,%eax
    13df:   e8 3c fd ff ff          call   1120 <fprintf@plt>
    13e4:   bf 01 00 00 00          mov    $0x1,%edi
    13e9:   e8 52 fd ff ff          call   1140 <exit@plt>
    13ee:   48 8b 95 e8 fb ff ff    mov    -0x418(%rbp),%rdx
    13f5:   48 8d 8d f0 fb ff ff    lea    -0x410(%rbp),%rcx
    13fc:   8b 85 e4 fb ff ff       mov    -0x41c(%rbp),%eax
    1402:   48 89 ce                mov    %rcx,%rsi
    1405:   89 c7                   mov    %eax,%edi
    1407:   e8 d4 fc ff ff          call   10e0 <write@plt>
    140c:   48 39 85 e8 fb ff ff    cmp    %rax,-0x418(%rbp)
    1413:   74 49                   je     145e <main+0x215>
    1415:   e8 b6 fc ff ff          call   10d0 <__errno_location@plt>
    141a:   8b 00                   mov    (%rax),%eax
    141c:   89 c7                   mov    %eax,%edi
    141e:   e8 2d fd ff ff          call   1150 <strerror@plt>
    1423:   48 89 c6                mov    %rax,%rsi
    1426:   48 8b 05 f3 2b 00 00    mov    0x2bf3(%rip),%rax        # 4020 <stderr@GLIBC_2.2.5>
    142d:   41 b8 25 00 00 00       mov    $0x25,%r8d
    1433:   48 8d 15 d1 0b 00 00    lea    0xbd1(%rip),%rdx        # 200b <_IO_stdin_used+0xb>
    143a:   48 89 d1                mov    %rdx,%rcx
    143d:   48 89 f2                mov    %rsi,%rdx
    1440:   48 8d 35 e4 0b 00 00    lea    0xbe4(%rip),%rsi        # 202b <_IO_stdin_used+0x2b>
    1447:   48 89 c7                mov    %rax,%rdi
    144a:   b8 00 00 00 00          mov    $0x0,%eax
    144f:   e8 cc fc ff ff          call   1120 <fprintf@plt>
    1454:   bf 01 00 00 00          mov    $0x1,%edi
    1459:   e8 e2 fc ff ff          call   1140 <exit@plt>
    145e:   48 8d 8d f0 fb ff ff    lea    -0x410(%rbp),%rcx
    1465:   8b 85 d8 fb ff ff       mov    -0x428(%rbp),%eax
    146b:   ba 00 04 00 00          mov    $0x400,%edx
    1470:   48 89 ce                mov    %rcx,%rsi
    1473:   89 c7                   mov    %eax,%edi
    1475:   e8 86 fc ff ff          call   1100 <read@plt>
    147a:   48 39 85 e8 fb ff ff    cmp    %rax,-0x418(%rbp)
    1481:   0f 84 67 ff ff ff       je     13ee <main+0x1a5>
    1487:   48 83 bd e8 fb ff ff    cmpq   $0xffffffffffffffff,-0x418(%rbp)
    148e:   ff 
    148f:   75 49                   jne    14da <main+0x291>
    1491:   e8 3a fc ff ff          call   10d0 <__errno_location@plt>
    1496:   8b 00                   mov    (%rax),%eax
    1498:   89 c7                   mov    %eax,%edi
    149a:   e8 b1 fc ff ff          call   1150 <strerror@plt>
    149f:   48 89 c6                mov    %rax,%rsi
    14a2:   48 8b 05 77 2b 00 00    mov    0x2b77(%rip),%rax        # 4020 <stderr@GLIBC_2.2.5>
    14a9:   41 b8 27 00 00 00       mov    $0x27,%r8d
    14af:   48 8d 15 55 0b 00 00    lea    0xb55(%rip),%rdx        # 200b <_IO_stdin_used+0xb>
    14b6:   48 89 d1                mov    %rdx,%rcx
    14b9:   48 89 f2                mov    %rsi,%rdx
    14bc:   48 8d 35 68 0b 00 00    lea    0xb68(%rip),%rsi        # 202b <_IO_stdin_used+0x2b>
    14c3:   48 89 c7                mov    %rax,%rdi
    14c6:   b8 00 00 00 00          mov    $0x0,%eax
    14cb:   e8 50 fc ff ff          call   1120 <fprintf@plt>
    14d0:   bf 01 00 00 00          mov    $0x1,%edi
    14d5:   e8 66 fc ff ff          call   1140 <exit@plt>
    14da:   8b 85 d8 fb ff ff       mov    -0x428(%rbp),%eax
    14e0:   89 c7                   mov    %eax,%edi
    14e2:   e8 09 fc ff ff          call   10f0 <close@plt>
    14e7:   83 f8 ff                cmp    $0xffffffff,%eax
    14ea:   75 49                   jne    1535 <main+0x2ec>
    14ec:   e8 df fb ff ff          call   10d0 <__errno_location@plt>
    14f1:   8b 00                   mov    (%rax),%eax
    14f3:   89 c7                   mov    %eax,%edi
    14f5:   e8 56 fc ff ff          call   1150 <strerror@plt>
    14fa:   48 89 c6                mov    %rax,%rsi
    14fd:   48 8b 05 1c 2b 00 00    mov    0x2b1c(%rip),%rax        # 4020 <stderr@GLIBC_2.2.5>
    1504:   41 b8 2a 00 00 00       mov    $0x2a,%r8d
    150a:   48 8d 15 fa 0a 00 00    lea    0xafa(%rip),%rdx        # 200b <_IO_stdin_used+0xb>
    1511:   48 89 d1                mov    %rdx,%rcx
    1514:   48 89 f2                mov    %rsi,%rdx
    1517:   48 8d 35 0d 0b 00 00    lea    0xb0d(%rip),%rsi        # 202b <_IO_stdin_used+0x2b>
    151e:   48 89 c7                mov    %rax,%rdi
    1521:   b8 00 00 00 00          mov    $0x0,%eax
    1526:   e8 f5 fb ff ff          call   1120 <fprintf@plt>
    152b:   bf 01 00 00 00          mov    $0x1,%edi
    1530:   e8 0b fc ff ff          call   1140 <exit@plt>
    1535:   8b 85 e4 fb ff ff       mov    -0x41c(%rbp),%eax
    153b:   89 c7                   mov    %eax,%edi
    153d:   e8 ae fb ff ff          call   10f0 <close@plt>
    1542:   83 f8 ff                cmp    $0xffffffff,%eax
    1545:   75 49                   jne    1590 <main+0x347>
    1547:   e8 84 fb ff ff          call   10d0 <__errno_location@plt>
    154c:   8b 00                   mov    (%rax),%eax
    154e:   89 c7                   mov    %eax,%edi
    1550:   e8 fb fb ff ff          call   1150 <strerror@plt>
    1555:   48 89 c6                mov    %rax,%rsi
    1558:   48 8b 05 c1 2a 00 00    mov    0x2ac1(%rip),%rax        # 4020 <stderr@GLIBC_2.2.5>
    155f:   41 b8 2c 00 00 00       mov    $0x2c,%r8d
    1565:   48 8d 15 9f 0a 00 00    lea    0xa9f(%rip),%rdx        # 200b <_IO_stdin_used+0xb>
    156c:   48 89 d1                mov    %rdx,%rcx
    156f:   48 89 f2                mov    %rsi,%rdx
    1572:   48 8d 35 b2 0a 00 00    lea    0xab2(%rip),%rsi        # 202b <_IO_stdin_used+0x2b>
    1579:   48 89 c7                mov    %rax,%rdi
    157c:   b8 00 00 00 00          mov    $0x0,%eax
    1581:   e8 9a fb ff ff          call   1120 <fprintf@plt>
    1586:   bf 01 00 00 00          mov    $0x1,%edi
    158b:   e8 b0 fb ff ff          call   1140 <exit@plt>
    1590:   bf 00 00 00 00          mov    $0x0,%edi
    1595:   e8 a6 fb ff ff          call   1140 <exit@plt>

Disassembly of section .fini:

000000000000159c <_fini>:
    159c:   f3 0f 1e fa             endbr64
    15a0:   48 83 ec 08             sub    $0x8,%rsp
    15a4:   48 83 c4 08             add    $0x8,%rsp
    15a8:   c3                      ret
Enter fullscreen mode Exit fullscreen mode

In here, at most left side, you see the address the machine instructions in the its virtual memory layout. At center, there are the instruction opcodes. At most right side, the corresponding assembly commands exist.

GDB is the super-useful and standard debugger onto GNU/Linux. I think that it deserves to be topics of another post. So I will explain it later.

Top comments (0)