Skip to content

Latest commit

 

History

History
192 lines (122 loc) · 7.02 KB

compilers.md

File metadata and controls

192 lines (122 loc) · 7.02 KB

Compilers

GCC

flag desc
-S get assembly code
-g compile with debug symbols (for GDB)
-pedantic warnings for strict ISO C
-std=c99 use C99 standard
-Wall show warnings of questionable practices
-Wextra warnings not covered by -Wall
-Wformat-y2k look for strftime code that uses double-digit year
-Wunreachable-code warn for unreachable code
-Wduplicated-cond warn about duplicated condition in if-else-if chains
-Wduplicated-branches warn about duplicate branches in if-else-if chains
-Wlogical-op warn where a bitwise operation may have been intended
-Wnull-dereference warn where compiler detects path that dereferences a null pointer
-Wjump-misses-init warn where a goto jump misses variable initialization
-Wshadow warn when a local variable shadows another variable/parameter/type/class member
-Wformat=2 aggressively check for format errors, warn about possible security bugs

LLVM

Github

List available targets

llc -version

Modules

http://clang.llvm.org/docs/Modules.html

Playing with AST, clang-query and clang-tidy

Note - when compiling from source:

-DLLVM_ENABLE_PROJECTS="clang;clang-tools-extra"

Dump AST of file

clang -Xclang -ast-dump -fsyntax-only test.cpp

clang-tidy

Adding a new check

cd llvm/clang-tools-extra/clang-tidy
python add_new_check.py misc my-first-check

clang-query

clang-query test.cpp

Dump the AST on a match:

set output dump

Reduce noise (not always reliable):

set bind-root false

Matching AST nodes:

// Match a for statement
m forStmt
// Match the 'pow' function
m functionDecl(hasName('pow'))

objdump

flag desc
-D disassemble contents of all sections (not just ones expected code)
-b binary treat target as binary blob
-i info - show available architectures and object formats
-m set architecture ('machine')
# Disassemble the executable
objdump -D ./executable

Hotpatching

MOV EDI, EDI is used because it's a safe two-byte NOP that can be used across x86-compatible manufactures - according to Raymond Chen, this was even figured out by talking to the manufacturers.

Some notes on NOP

if you want to get technical, there isn't really any difference between those two. Since the processor doesn't stop, a NOP does something, regardless of how its implemented --- at the bare minimum, it increments the instruction pointer. Selecting a "good" NOP is harder than expected because 1. it must do nothing observable to a program, 2. it must work on all processor models we want to support, 3. if it slows down the program, it should do so to the least extent possible. As the discussion here shows, doing nothing well can be surprisingly hard. Perhaps the Tao Te Ching should be consulted, in addition to any processor manuals. -Jeroen Mostert

Why not just use two NOP instructions at the entry point?

Well, because a NOP instruction consumes one clock cycle and one pipe, so two of them would consume two clock cycles and two pipes. (The instructions will likely be paired, one in each pipe, so the combined execution will take one clock cycle.) On the other hand, the MOV EDI, EDI instruction consumes one clock cycle and one pipe. (In practice, the instruction will occupy one pipe, leaving the other available to execute another instruction in parallel. You might say that the instruction executes in half a cycle.) However you calculate it, the MOV EDI, EDI instruction executes in half the time of two NOP instructions.

On the other hand, the five NOPs inserted before the start of the function are never executed, so it doesn't matter what you use to pad them. It could've been five garbage bytes for all anybody cares.

But much more important than cycle-counting is that the use of a two-byte NOP avoids the Detours problem: If the code had used two single-byte NOP instructions, then there is the risk that you will install your patch just as a thread has finished executing the first single-byte NOP and is about to begin executing the second single-byte NOP, resulting in the thread treating the second half of your JMP $-5 as the start of a new instruction. -Raymond Chen

Windows

Add /hotpatch to the compiler flags.

Links

Control Flow Integrity

https://blog.trailofbits.com/2016/10/17/lets-talk-about-cfi-clang-edition/ https://clang.llvm.org/docs/ControlFlowIntegrity.html

Compilers Explorer

https://godbolt.org/

Linkers

The GNU linker

  • /etc/ld.so.conf configures directories to search
  • /etc/ld.so.cache is the binary cache used by ld.so
# Reload ld cache
ldconfig
# See which libraries are utilized
ldconfig -v

# See what an executable links to
ldd ./executablefile

# Specify an alternate library path
export LD_LIBRARY_PATH=/path/to/dir ...

# Link object file into an executable file
ld -o example example.o
# Strip all binary symbol information
ld -s ...
# Strip debug binary symbol information
ld -S ...
# Mark stack as non executable
ld -z noexecstack

LLD