软件安全学习课程实践1:程序生成与运行实验

1 程序生成与运行实验

1.1 预处理


  • do-while-zero 宏用于在宏里压多条语句;

1.2 编译

在本单元中,你将会学习到有关C程序编译的几个重要步骤和几种C程序的中间表示形式,包括抽象语法树(AST)和LLVM中间表示(IR),最后对编译优化有个初步了解。

LLVM AST

LLVM IR

LLVM IR阅读材料:

loop in LLVM IR

int main() {
   
    
    
    int i = 0; // %2
    int sum = 0; // %3 
    for (i = 0; i < 10; i++) {
   
    
    
        sum += i;
    }

    while (sum > 0) {
   
    
    
        sum --;
    }

    return 0;
}

注意下面的IR非完整文件,只列了关键部分

define dso_local i32 @main() #0 {
   
    
    

  %2 = alloca i32, align 4
  %3 = alloca i32, align 4

  store i32 0, ptr %2, align 4
  store i32 0, ptr %3, align 4

  store i32 0, ptr %2, align 4                    ; 同名变量 i,因此复用 %2
  br label %4

4:                                                ; preds = %11, %0
  %5 = load i32, ptr %2, align 4
  %6 = icmp slt i32 %5, 10
  br i1 %6, label %7, label %14
  ; i < 10
7:                                                ; preds = %4
  %8 = load i32, ptr %2, align 4
  %9 = load i32, ptr %3, align 4
  %10 = add nsw i32 %9, %8
  store i32 %10, ptr %3, align 4
  br label %11
  ; sum += i

11:                                               ; preds = %7
  %12 = load i32, ptr %2, align 4
  %13 = add nsw i32 %12, 1
  store i32 %13, ptr %2, align 4
  br label %4, !llvm.loop !6
  ; i++
14:                                               ; preds = %4
  br label %15

15:                                               ; preds = %18, %14
  %16 = load i32, ptr %3, align 4
  %17 = icmp sgt i32 %16, 0
  br i1 %17, label %18, label %21

18:                                               ; preds = %15
  %19 = load i32, ptr %3, align 4
  %20 = add nsw i32 %19, -1
  store i32 %20, ptr %3, align 4
  br label %15, !llvm.loop !8

21:                                               ; preds = %15
  ret i32 0
}

static and global variables in LLVM IR

#include <stdio.h>
void sayHello() {
   
    
    
    printf("Hello, world!\n");
}

void incrementAndPrint() {
   
    
    
    static int count = 0;

    count ++;
    printf("Count: %d\n", count);
}

int main() {
   
    
    
    sayHello();

    incrementAndPrint();
    incrementAndPrint();
    incrementAndPrint();

    return 0;
}
@.str = private unnamed_addr constant [15 x i8] c"Hello, world!\0A\00", align 1
@incrementAndPrint.count = internal global i32 0, align 4
@.str.1 = private unnamed_addr constant [11 x i8] c"Count: %d\0A\00", align 1

; Function Attrs: noinline nounwind optnone sspstrong uwtable
define dso_local void @sayHello() #0 {
   
    
    
  %1 = call i32 (ptr, ...) @printf(ptr noundef @.str)
  ret void
}

declare i32 @printf(ptr noundef, ...) #1

; Function Attrs: noinline nounwind optnone sspstrong uwtable
define dso_local void @incrementAndPrint() #0 {
   
    
    
  %1 = load i32, ptr @incrementAndPrint.count, align 4
  %2 = add nsw i32 %1, 1
  store i32 %2, ptr @incrementAndPrint.count, align 4
  %3 = load i32, ptr @incrementAndPrint.count, align 4
  %4 = call i32 (ptr, ...) @printf(ptr noundef @.str.1, i32 noundef %3)
  ret void
}

; Function Attrs: noinline nounwind optnone sspstrong uwtable
define dso_local i32 @main() #0 {
   
    
    
  %1 = alloca i32, align 4
  store i32 0, ptr %1, align 4
  call void @sayHello()
  call void @incrementAndPrint()
  call void @incrementAndPrint()
  call void @incrementAndPrint()
  ret i32 0
}

attributes #0 = {
   
    
     noinline nounwind optnone sspstrong uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
attributes #1 = {
   
    
     "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }

!llvm.module.flags = !{
   
    
    !0, !1, !2, !3, !4}
!llvm.ident = !{
   
    
    !5}

!0 = !{
   
    
    i32 1, !"wchar_size", i32 4}
!1 = !{
   
    
    i32 7, !"PIC Level", i32 2}
!2 = !{
   
    
    i32 7, !"PIE Level", i32 2}
!3 = !{
   
    
    i32 7, !"uwtable", i32 2}
!4 = !{
   
    
    i32 7, !"frame-pointer", i32 2}
!5 = !{
   
    
    !"clang version 15.0.7"}

how to merge 2 funtions?

  • 需要注意 inline__attribute__((always_inline))的区别
#include <stdio.h>

__attribute__((always_inline)) int findMax(int a, int b) {
   
    
    
    return (a > b) ? a : b;
}

int main() {
   
    
    
    int num1 = 10; // %4
    int num2 = 20; // %5
    int max_num = findMax(num1, num2);
    printf("The maximum between %d and %d is %d\n", num1, num2, max_num);
    return 0;
}

本节IR涉及到 phi 指令

%4 = phi i32 [ 1, %1 ], [ %8, %5 ]              ; 如果是从块 %1 来的,那么值就是 1,如果是从块 %5 来的,那么值就是 %8 的值

IR如下:

@.str = private unnamed_addr constant [37 x i8] c"The maximum between %d and %d is %d\0A\00", align 1

; Function Attrs: alwaysinline nounwind sspstrong uwtable
define dso_local i32 @findMax(i32 noundef %0, i32 noundef %1) #0 {
   
    
    
  %3 = alloca i32, align 4 ; a
  %4 = alloca i32, align 4 ; b
  store i32 %0

猜你喜欢

转载自blog.csdn.net/qq_33583069/article/details/133495334