brintos

brintos / llvm-project-archived public Read only

0
0
Text · 8.0 KiB · 40c70d9 Raw
201 lines · cpp
1//===-- ThreadWriter.cpp --------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "ThreadWriter.h"10#include "CoreSpec.h"11#include "Utility.h"12#include "llvm/BinaryFormat/MachO.h"13#include <algorithm>14#include <stdio.h>15 16#define ARM_THREAD_STATE 117#define ARM_THREAD_STATE_COUNT 1718#define ARM_EXCEPTION_STATE 319#define ARM_EXCEPTION_STATE_COUNT 320 21std::vector<RegisterNameAndValue>::const_iterator22find_by_name(std::vector<RegisterNameAndValue>::const_iterator first,23             std::vector<RegisterNameAndValue>::const_iterator last,24             const char *name) {25  for (; first != last; ++first)26    if (first->name == name)27      return first;28  return last;29}30 31void add_reg_value(CoreSpec &spec, std::vector<uint8_t> &buf,32                   const std::vector<RegisterNameAndValue> &registers,33                   const char *regname, int regsize) {34  const auto it = find_by_name(registers.begin(), registers.end(), regname);35  if (it != registers.end()) {36    if (regsize == 8)37      add_uint64(buf, it->value);38    else39      add_uint32(buf, it->value);40  } else {41    if (regsize == 8)42      add_uint64(buf, 0);43    else44      add_uint32(buf, 0);45  }46}47 48void add_reg_value_32(CoreSpec &spec, std::vector<uint8_t> &buf,49                      const std::vector<RegisterNameAndValue> &registers,50                      const char *regname) {51  add_reg_value(spec, buf, registers, regname, 4);52}53 54void add_reg_value_64(CoreSpec &spec, std::vector<uint8_t> &buf,55                      const std::vector<RegisterNameAndValue> &registers,56                      const char *regname) {57  add_reg_value(spec, buf, registers, regname, 8);58}59 60void add_lc_threads_armv7(CoreSpec &spec,61                          std::vector<std::vector<uint8_t>> &load_commands) {62  for (const Thread &th : spec.threads) {63    std::vector<uint8_t> lc;64    int size_of_all_flavors = 0;65    for (const RegisterSet &rs : th.regsets) {66      if (rs.flavor == RegisterFlavor::GPR)67        size_of_all_flavors += (ARM_THREAD_STATE_COUNT * 4);68      if (rs.flavor == RegisterFlavor::EXC)69        size_of_all_flavors += (ARM_EXCEPTION_STATE_COUNT * 4);70    }71    int cmdsize = 4 * 2;                  // cmd, cmdsize72    cmdsize += 4 * 2 * th.regsets.size(); // flavor, count (per register flavor)73    cmdsize += size_of_all_flavors;       // size of all the register set data74 75    add_uint32(lc, llvm::MachO::LC_THREAD); // thread_command.cmd76    add_uint32(lc, cmdsize);                // thread_command.cmdsize77    for (const RegisterSet &rs : th.regsets) {78      if (rs.flavor == RegisterFlavor::GPR) {79        add_uint32(lc, ARM_THREAD_STATE);       // thread_command.flavor80        add_uint32(lc, ARM_THREAD_STATE_COUNT); // thread_command.count81        const char *names[] = {"r0",  "r1", "r2", "r3", "r4",   "r5",82                               "r6",  "r7", "r8", "r9", "r10",  "r11",83                               "r12", "sp", "lr", "pc", "cpsr", nullptr};84        for (int i = 0; names[i]; i++)85          add_reg_value_32(spec, lc, rs.registers, names[i]);86      }87      if (rs.flavor == RegisterFlavor::EXC) {88        add_uint32(lc, ARM_EXCEPTION_STATE);       // thread_command.flavor89        add_uint32(lc, ARM_EXCEPTION_STATE_COUNT); // thread_command.count90        const char *names[] = {"far", "esr", "exception", nullptr};91        for (int i = 0; names[i]; i++)92          add_reg_value_32(spec, lc, rs.registers, names[i]);93      }94    }95    load_commands.push_back(lc);96  }97}98 99#define ARM_THREAD_STATE64 6100#define ARM_THREAD_STATE64_COUNT 68101#define ARM_EXCEPTION_STATE64 7102#define ARM_EXCEPTION_STATE64_COUNT 4103 104void add_lc_threads_arm64(CoreSpec &spec,105                          std::vector<std::vector<uint8_t>> &load_commands) {106  for (const Thread &th : spec.threads) {107    std::vector<uint8_t> lc;108    int size_of_all_flavors = 0;109    for (const RegisterSet &rs : th.regsets) {110      if (rs.flavor == RegisterFlavor::GPR)111        size_of_all_flavors += (ARM_THREAD_STATE64_COUNT * 4);112      if (rs.flavor == RegisterFlavor::EXC)113        size_of_all_flavors += (ARM_EXCEPTION_STATE64_COUNT * 4);114    }115    int cmdsize = 4 * 2;                  // cmd, cmdsize116    cmdsize += 4 * 2 * th.regsets.size(); // flavor, count (per register flavor)117    cmdsize += size_of_all_flavors;       // size of all the register set data118 119    add_uint32(lc, llvm::MachO::LC_THREAD); // thread_command.cmd120    add_uint32(lc, cmdsize);                // thread_command.cmdsize121 122    for (const RegisterSet &rs : th.regsets) {123      if (rs.flavor == RegisterFlavor::GPR) {124        add_uint32(lc, ARM_THREAD_STATE64);       // thread_command.flavor125        add_uint32(lc, ARM_THREAD_STATE64_COUNT); // thread_command.count126        const char *names[] = {"x0",  "x1",  "x2",  "x3",  "x4",  "x5",   "x6",127                               "x7",  "x8",  "x9",  "x10", "x11", "x12",  "x13",128                               "x14", "x15", "x16", "x17", "x18", "x19",  "x20",129                               "x21", "x22", "x23", "x24", "x25", "x26",  "x27",130                               "x28", "fp",  "lr",  "sp",  "pc",  nullptr};131        for (int i = 0; names[i]; i++)132          add_reg_value_64(spec, lc, rs.registers, names[i]);133 134        // cpsr is a 4-byte reg135        add_reg_value_32(spec, lc, rs.registers, "cpsr");136        // the 4 bytes of zeroes137        add_uint32(lc, 0);138      }139      if (rs.flavor == RegisterFlavor::EXC) {140        add_uint32(lc, ARM_EXCEPTION_STATE64); // thread_command.flavor141        add_uint32(lc,142                   ARM_EXCEPTION_STATE64_COUNT); // thread_command.count143        add_reg_value_64(spec, lc, rs.registers, "far");144        add_reg_value_32(spec, lc, rs.registers, "esr");145        add_reg_value_32(spec, lc, rs.registers, "exception");146      }147    }148    load_commands.push_back(lc);149  }150}151 152#define RV32_THREAD_STATE 2153#define RV32_THREAD_STATE_COUNT 33154 155void add_lc_threads_riscv(CoreSpec &spec,156                          std::vector<std::vector<uint8_t>> &load_commands) {157  for (const Thread &th : spec.threads) {158    std::vector<uint8_t> lc;159    int size_of_all_flavors = 0;160    for (const RegisterSet &rs : th.regsets) {161      if (rs.flavor == RegisterFlavor::GPR)162        size_of_all_flavors += (RV32_THREAD_STATE_COUNT * 4);163    }164    int cmdsize = 4 * 2;                  // cmd, cmdsize165    cmdsize += 4 * 2 * th.regsets.size(); // flavor, count (per register flavor)166    cmdsize += size_of_all_flavors;       // size of all the register set data167 168    add_uint32(lc, llvm::MachO::LC_THREAD); // thread_command.cmd169    add_uint32(lc, cmdsize);                // thread_command.cmdsize170    for (const RegisterSet &rs : th.regsets) {171      if (rs.flavor == RegisterFlavor::GPR) {172        add_uint32(lc, RV32_THREAD_STATE);       // thread_command.flavor173        add_uint32(lc, RV32_THREAD_STATE_COUNT); // thread_command.count174        const char *names[] = {"zero", "ra", "sp", "gp", "tp", "t0",   "t1",175                               "t2",   "fp", "s1", "a0", "a1", "a2",   "a3",176                               "a4",   "a5", "a6", "a7", "s2", "s3",   "s4",177                               "s5",   "s6", "s7", "s8", "s9", "s10",  "s11",178                               "t3",   "t4", "t5", "t6", "pc", nullptr};179        for (int i = 0; names[i]; i++)180          add_reg_value_32(spec, lc, rs.registers, names[i]);181      }182    }183    load_commands.push_back(lc);184  }185}186 187void add_lc_threads(CoreSpec &spec,188                    std::vector<std::vector<uint8_t>> &load_commands) {189  if (spec.cputype == llvm::MachO::CPU_TYPE_ARM)190    add_lc_threads_armv7(spec, load_commands);191  else if (spec.cputype == llvm::MachO::CPU_TYPE_ARM64)192    add_lc_threads_arm64(spec, load_commands);193  else if (spec.cputype == llvm::MachO::CPU_TYPE_RISCV)194    add_lc_threads_riscv(spec, load_commands);195  else {196    fprintf(stderr,197            "Unrecognized cputype, could not write LC_THREAD.  Exiting.\n");198    exit(1);199  }200}201