Skip to content

Commit

Permalink
Initial attempt to pass IBT (x86) or BTI (aarch64) to LLVM
Browse files Browse the repository at this point in the history
This requires to pass the `-Dcf-protection=branch` flag for X86 or the
`-Dbranch-protection=bti` flag for AARCH64.
  • Loading branch information
ysbaddaden committed Oct 23, 2024
1 parent d8c7592 commit c973b01
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 16 deletions.
34 changes: 26 additions & 8 deletions src/compiler/crystal/codegen/codegen.cr
Original file line number Diff line number Diff line change
Expand Up @@ -274,8 +274,7 @@ module Crystal
@llvm_context : LLVM::Context = LLVM::Context.new)
@abi = @program.target_machine.abi
# LLVM::Context.register(@llvm_context, "main")
@llvm_mod = @llvm_context.new_module("main_module")
@main_mod = @llvm_mod
@main_mod = @llvm_mod = new_module("main_module")
@main_llvm_context = @main_mod.context
@llvm_typer = LLVMTyper.new(@program, @llvm_context)
@main_llvm_typer = @llvm_typer
Expand Down Expand Up @@ -345,8 +344,6 @@ module Crystal
@unused_fun_defs = [] of FunDef
@proc_counts = Hash(String, Int32).new(0)

@llvm_mod.data_layout = self.data_layout

# We need to define __crystal_malloc and __crystal_realloc as soon as possible,
# to avoid some memory being allocated with plain malloc.
codegen_well_known_functions @node
Expand All @@ -367,6 +364,31 @@ module Crystal

getter llvm_context

def new_module(module_name)
llvm_mod = @llvm_context.new_module(module_name)
llvm_mod.data_layout = @program.target_machine.data_layout

# enable branch authentication instructions (BTI)
if @program.has_flag?("aarch64")
if @program.has_flag?("branch-protection=bti")
llvm_mod.add_flag(:override, "branch-target-enforcement", 1)
end
end

# enable control flow enforcement protection (CET): IBT and/or SHSTK
if @program.has_flag?("x86_64") || @program.has_flag?("i386")
if @program.has_flag?("cf-protection=branch") || @program.has_flag?("cf-protection=full")
llvm_mod.add_flag(:override, "cf-protection-branch", 1)
end

if @program.has_flag?("cf-protection=return") || @program.has_flag?("cf-protection=full")
llvm_mod.add_flag(:override, "cf-protection-return", 1)
end
end

llvm_mod
end

def new_builder(llvm_context)
wrap_builder(llvm_context.new_builder)
end
Expand Down Expand Up @@ -419,10 +441,6 @@ module Crystal
global.initializer = llvm_element_type.const_array(llvm_elements)
end

def data_layout
@program.target_machine.data_layout
end

class CodegenWellKnownFunctions < Visitor
@codegen : CodeGenVisitor

Expand Down
8 changes: 2 additions & 6 deletions src/compiler/crystal/codegen/debug.cr
Original file line number Diff line number Diff line change
Expand Up @@ -42,17 +42,13 @@ module Crystal

if @program.has_flag?("msvc")
# Windows uses CodeView instead of DWARF
mod.add_flag(
LibLLVM::ModuleFlagBehavior::Warning,
"CodeView",
mod.context.int32.const_int(1)
)
mod.add_flag(LibLLVM::ModuleFlagBehavior::Warning, "CodeView", 1)
end

mod.add_flag(
LibLLVM::ModuleFlagBehavior::Warning,
"Debug Info Version",
mod.context.int32.const_int(LLVM::DEBUG_METADATA_VERSION)
LLVM::DEBUG_METADATA_VERSION
)
end

Expand Down
3 changes: 1 addition & 2 deletions src/compiler/crystal/codegen/fun.cr
Original file line number Diff line number Diff line change
Expand Up @@ -626,8 +626,7 @@ class Crystal::CodeGenVisitor
# LLVM::Context.register(llvm_context, type_name)

llvm_typer = LLVMTyper.new(@program, llvm_context)
llvm_mod = llvm_context.new_module(type_name)
llvm_mod.data_layout = self.data_layout
llvm_mod = new_module(type_name)
llvm_builder = new_builder(llvm_context)

define_symbol_table llvm_mod, llvm_typer
Expand Down
5 changes: 5 additions & 0 deletions src/llvm/lib_llvm/core.cr
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,12 @@ lib LibLLVM
# counterparts (e.g. `LLVMModuleFlagBehavior` v.s. `LLVM::Module::ModFlagBehavior`)

enum ModuleFlagBehavior
Error = 0
Warning = 1
Require = 2
Override = 3
Append = 4
AppendUnique = 5
end

alias AttributeIndex = UInt
Expand Down
4 changes: 4 additions & 0 deletions src/llvm/module.cr
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ class LLVM::Module
GlobalCollection.new(self)
end

def add_flag(module_flag : LibLLVM::ModuleFlagBehavior, key : String, val : Int32)
add_flag(module_flag, key, @context.int32.const_int(val))
end

def add_flag(module_flag : LibLLVM::ModuleFlagBehavior, key : String, val : Value)
LibLLVM.add_module_flag(
self,
Expand Down

0 comments on commit c973b01

Please sign in to comment.