/* ************************************************************************** */
/*                                                                            */
/*                                                        :::      ::::::::   */
/*   utils.c                                            :+:      :+:    :+:   */
/*                                                    +:+ +:+         +:+     */
/*   By: thrieg <thrieg@student.42mulhouse.fr>      +#+  +:+       +#+        */
/*                                                +#+#+#+#+#+   +#+           */
/*   Created: 2025/12/11 04:31:15 by thrieg            #+#    #+#             */
/*   Updated: 2025/12/11 06:14:12 by thrieg           ###   ########.fr       */
/*                                                                            */
/* ************************************************************************** */

#include "../includes/ft_strace.h"
#include "../includes/syscalls_x86.h"
#include "../includes/syscalls_x64.h"
#include <elf.h>     // for EI_NIDENT, EI_CLASS, ELFCLASS32, ELFCLASS64
#include <fcntl.h>   // for open
#include <sys/uio.h>
#include <sys/user.h> // for user_regs_struct

//returns 64 for x86_64, or 32 for 32 bits, -1 for open/read error, -2 for unrecognised file type
ssize_t binary_type(char *path_to_binary)
{
    int             fd;
    unsigned char   ident[EI_NIDENT];
    ssize_t         ret;

    fd = open(path_to_binary, O_RDONLY);
    if (fd == -1)
        return (-1);
    ret = read(fd, ident, EI_NIDENT);
    close(fd);
    if (ret == -1)
        return (-1);
    if (ret != EI_NIDENT)
        return (-2);

    /* Check this is an ELF file (binary) */
    if (ident[0] != 0x7f || ident[1] != 'E'
        || ident[2] != 'L' || ident[3] != 'F')
        return (-2);

    if (ident[EI_CLASS] == ELFCLASS64)
        return (64);
    if (ident[EI_CLASS] == ELFCLASS32)
        return (32);
    return (-2); //don't know wtf this file is at this point
}

static void read_regs(pid_t pid, struct user_regs_struct *regs)
{
    struct iovec io;
    io.iov_base = regs;
    io.iov_len  = sizeof(*regs);

    if (ptrace(PTRACE_GETREGSET, pid, (void*)NT_PRSTATUS, &io) == -1)
    {
        fprintf(stderr, "PTRACE_GETREGSET failed: %s\n", strerror(errno));
        return;
    }
}

void read_regs_and_print_entry(pid_t pid, size_t binary_type)
{
    struct user_regs_struct regs;
    read_regs(pid, &regs);
    if (binary_type == 64)
    {
        if (regs.orig_rax >= g_syscalls_64_len)
        {
            printf("unknown syscall(%ld, %lld, %lld, %lld, %lld, %lld, %lld)\n",
            (long long)regs.orig_rax,
            (long long)regs.rdi,
            (long long)regs.rsi,
            (long long)regs.rdx,
            (long long)regs.r10,
            (long long)regs.r8,
            (long long)regs.r9);
        }
        else
        {
            const char *syscall_name = g_syscalls_64[regs.orig_rax]->name;
            int argc = g_syscalls_64[regs.orig_rax]->argc;
            printf("%s(%ld, %lld, %lld, %lld, %lld, %lld, %lld)\n",
            syscall,
            (long long)regs.rdi,
            (long long)regs.rsi,
            (long long)regs.rdx,
            (long long)regs.r10,
            (long long)regs.r8,
            (long long)regs.r9);
        }
    }
    else if (binary_type == 32)
    {
        if (regs.orig_eax >= g_syscalls_86_len)
        {
            printf("unknown syscall(%ld, %lld, %lld, %lld, %lld, %lld, %lld)\n",
            (long)regs.orig_eax,
            (long)regs.ebx,
            (long)regs.ecx,
            (long)regs.edx,
            (long)regs.esi,
            (long)regs.edi,
            (long)regs.ebp);
        }
        else
        {
            const char *syscall_name = g_syscalls_86[regs.orig_eax]->name;
            int argc = g_syscalls_64[regs.orig_eax]->argc;
            printf("%s(%lld, %lld, %lld, %lld, %lld, %lld)\n",
            syscall_name,
            (long)regs.ebx,
            (long)regs.ecx,
            (long)regs.edx,
            (long)regs.esi,
            (long)regs.edi,
            (long)regs.ebp);
        }
    }
}