brintos

brintos / llvm-project-archived public Read only

0
0
Text · 3.3 KiB · 560e4cc Raw
104 lines · c
1// REQUIRES: native-run2// UNSUPPORTED: target={{(arm|aarch64).*}}3// RUN: %clang_builtins %s %librt -o %t && %run %t4// REQUIRES: librt_has_clear_cache5 6#include <stdio.h>7#include <string.h>8#include <stdint.h>9 10#if defined(_WIN32)11#include <windows.h>12#else13#include <unistd.h>14#include <sys/mman.h>15#endif16 17extern void __clear_cache(void* start, void* end);18 19typedef int (*pfunc)(void);20 21// Make these static to avoid ILT jumps for incremental linking on Windows.22static int func1() { return 1; }23static int func2() { return 2; }24 25void __attribute__((noinline))26memcpy_f(void *dst, const void *src, size_t n) {27// ARM and MIPS naturally align functions, but use the LSB for ISA selection28// (THUMB, MIPS16/uMIPS respectively).  Ensure that the ISA bit is ignored in29// the memcpy30#if defined(__arm__) || defined(__mips__)31  memcpy(dst, (void *)((uintptr_t)src & ~1), n);32#else33  memcpy(dst, (void *)((uintptr_t)src), n);34#endif35}36 37// Realign the 'dst' pointer as if it has been returned by memcpy() above.38// We need to split it because we're using two mappings for the same area.39void *__attribute__((noinline))40realign_f(void *dst, const void *src, size_t n) {41#if defined(__arm__) || defined(__mips__)42  return (void *)((uintptr_t)dst | ((uintptr_t)src & 1));43#else44  return dst;45#endif46}47 48int main()49{50    const int kSize = 128;51#if defined(__NetBSD__)52    // we need to create separate RW and RX mappings to satisfy MPROTECT53    uint8_t *write_buffer = mmap(0, kSize,54                                 PROT_MPROTECT(PROT_READ | PROT_WRITE |55                                               PROT_EXEC),56                                 MAP_ANON | MAP_PRIVATE, -1, 0);57    if (write_buffer == MAP_FAILED)58      return 1;59    uint8_t *execution_buffer = mremap(write_buffer, kSize, NULL, kSize,60                                       MAP_REMAPDUP);61    if (execution_buffer == MAP_FAILED)62      return 1;63 64    if (mprotect(write_buffer, kSize, PROT_READ | PROT_WRITE) == -1)65      return 1;66    if (mprotect(execution_buffer, kSize, PROT_READ | PROT_EXEC) == -1)67      return 1;68#elif !defined(_WIN32)69    uint8_t *execution_buffer = mmap(0, kSize,70                                     PROT_READ | PROT_WRITE | PROT_EXEC,71                                     MAP_ANON | MAP_PRIVATE, -1, 0);72    if (execution_buffer == MAP_FAILED)73      return 1;74    uint8_t *write_buffer = execution_buffer;75#else76    HANDLE mapping = CreateFileMapping(INVALID_HANDLE_VALUE, NULL,77                                       PAGE_EXECUTE_READWRITE, 0, kSize, NULL);78    if (mapping == NULL)79        return 1;80 81    uint8_t* execution_buffer = MapViewOfFile(82        mapping, FILE_MAP_ALL_ACCESS | FILE_MAP_EXECUTE, 0, 0, 0);83    if (execution_buffer == NULL)84        return 1;85    uint8_t *write_buffer = execution_buffer;86#endif87 88    // verify you can copy and execute a function89    memcpy_f(write_buffer, func1, kSize);90    pfunc f1 = (pfunc)realign_f(execution_buffer, func1, kSize);91    __clear_cache(execution_buffer, execution_buffer + kSize);92    if ((*f1)() != 1)93        return 1;94 95    // verify you can overwrite a function with another96    memcpy_f(write_buffer, func2, kSize);97    pfunc f2 = (pfunc)realign_f(execution_buffer, func2, kSize);98    __clear_cache(execution_buffer, execution_buffer + kSize);99    if ((*f2)() != 2)100        return 1;101 102    return 0;103}104