166 lines · cpp
1//===-- CoreSpec.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 "CoreSpec.h"10#include "llvm/BinaryFormat/MachO.h"11#include "llvm/Support/YAMLTraits.h"12#include <stdio.h>13#include <string>14 15using llvm::yaml::Input;16using llvm::yaml::IO;17using llvm::yaml::MappingTraits;18 19template <> struct llvm::yaml::MappingTraits<RegisterNameAndValue> {20 static void mapping(IO &io, RegisterNameAndValue &name_value) {21 io.mapRequired("name", name_value.name);22 io.mapRequired("value", name_value.value);23 }24};25LLVM_YAML_IS_SEQUENCE_VECTOR(RegisterNameAndValue)26 27template <> struct llvm::yaml::ScalarEnumerationTraits<RegisterFlavor> {28 static void enumeration(IO &io, RegisterFlavor &flavor) {29 io.enumCase(flavor, "gpr", RegisterFlavor::GPR);30 io.enumCase(flavor, "fpr", RegisterFlavor::FPR);31 io.enumCase(flavor, "exc", RegisterFlavor::EXC);32 }33};34 35template <> struct llvm::yaml::MappingTraits<RegisterSet> {36 static void mapping(IO &io, RegisterSet ®set) {37 io.mapRequired("flavor", regset.flavor);38 io.mapRequired("registers", regset.registers);39 }40};41LLVM_YAML_IS_SEQUENCE_VECTOR(RegisterSet)42 43template <> struct llvm::yaml::MappingTraits<Thread> {44 static void mapping(IO &io, Thread &thread) {45 io.mapRequired("regsets", thread.regsets);46 }47};48LLVM_YAML_IS_SEQUENCE_VECTOR(Thread)49 50template <> struct llvm::yaml::MappingTraits<MemoryRegion> {51 static void mapping(IO &io, MemoryRegion &memory) {52 io.mapRequired("addr", memory.addr);53 io.mapOptional("UInt8", memory.bytes);54 io.mapOptional("UInt32", memory.words);55 io.mapOptional("UInt64", memory.doublewords);56 57 if (memory.bytes.size()) {58 memory.type = MemoryType::UInt8;59 memory.size = memory.bytes.size();60 } else if (memory.words.size()) {61 memory.type = MemoryType::UInt32;62 memory.size = memory.words.size() * 4;63 } else if (memory.doublewords.size()) {64 memory.type = MemoryType::UInt64;65 memory.size = memory.doublewords.size() * 8;66 }67 }68};69LLVM_YAML_IS_SEQUENCE_VECTOR(MemoryRegion)70 71template <> struct llvm::yaml::MappingTraits<Binary> {72 static void mapping(IO &io, Binary &binary) {73 io.mapOptional("name", binary.name);74 io.mapRequired("uuid", binary.uuid);75 std::optional<uint64_t> va, slide;76 io.mapOptional("virtual-address", va);77 io.mapOptional("slide", slide);78 if (va && *va != UINT64_MAX) {79 binary.value_is_slide = false;80 binary.value = *va;81 } else if (slide && *slide != UINT64_MAX) {82 binary.value_is_slide = true;83 binary.value = *slide;84 } else {85 fprintf(stderr,86 "No virtual-address or slide specified for binary %s, aborting\n",87 binary.uuid.c_str());88 exit(1);89 }90 }91};92LLVM_YAML_IS_SEQUENCE_VECTOR(Binary)93 94template <> struct llvm::yaml::MappingTraits<AddressableBits> {95 static void mapping(IO &io, AddressableBits &addr_bits) {96 std::optional<int> addressable_bits;97 io.mapOptional("num-bits", addressable_bits);98 if (addressable_bits) {99 addr_bits.lowmem_bits = *addressable_bits;100 addr_bits.highmem_bits = *addressable_bits;101 } else {102 io.mapOptional("lowmem-num-bits", addr_bits.lowmem_bits);103 io.mapOptional("highmem-num-bits", addr_bits.highmem_bits);104 }105 }106};107 108template <> struct llvm::yaml::MappingTraits<CoreSpec> {109 static void mapping(IO &io, CoreSpec &corespec) {110 std::string cpuname;111 io.mapRequired("cpu", cpuname);112 if (cpuname == "armv7m") {113 corespec.cputype = llvm::MachO::CPU_TYPE_ARM;114 corespec.cpusubtype = llvm::MachO::CPU_SUBTYPE_ARM_V7M;115 } else if (cpuname == "armv7") {116 corespec.cputype = llvm::MachO::CPU_TYPE_ARM;117 corespec.cpusubtype = llvm::MachO::CPU_SUBTYPE_ARM_ALL;118 } else if (cpuname == "riscv") {119 corespec.cputype = llvm::MachO::CPU_TYPE_RISCV;120 corespec.cpusubtype = llvm::MachO::CPU_SUBTYPE_RISCV_ALL;121 } else if (cpuname == "arm64") {122 corespec.cputype = llvm::MachO::CPU_TYPE_ARM64;123 corespec.cpusubtype = llvm::MachO::CPU_SUBTYPE_ARM64_ALL;124 } else {125 fprintf(stderr, "Unrecognized cpu name %s, exiting.\n", cpuname.c_str());126 exit(1);127 }128 io.mapOptional("threads", corespec.threads);129 io.mapOptional("memory-regions", corespec.memory_regions);130 if (corespec.cputype == llvm::MachO::CPU_TYPE_ARM ||131 corespec.cputype == llvm::MachO::CPU_TYPE_RISCV)132 corespec.wordsize = 4;133 else if (corespec.cputype == llvm::MachO::CPU_TYPE_ARM64)134 corespec.wordsize = 8;135 else {136 fprintf(stderr,137 "Unrecognized cputype, could not set wordsize, exiting.\n");138 exit(1);139 }140 io.mapOptional("addressable-bits", corespec.addressable_bits);141 io.mapOptional("binaries", corespec.binaries);142 if (corespec.addressable_bits) {143 if (!corespec.addressable_bits->lowmem_bits)144 corespec.addressable_bits->lowmem_bits = corespec.wordsize * 8;145 if (!corespec.addressable_bits->highmem_bits)146 corespec.addressable_bits->highmem_bits = corespec.wordsize * 8;147 }148 }149};150 151CoreSpec from_yaml(char *buf, size_t len) {152 llvm::StringRef file_corespec_strref(buf, len);153 154 Input yin(file_corespec_strref);155 156 CoreSpec v;157 yin >> v;158 159 if (yin.error()) {160 fprintf(stderr, "Unable to parse YAML, exiting\n");161 exit(1);162 }163 164 return v;165}166