//===-- ArchSpec.cpp --------------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "lldb/Core/ArchSpec.h" #include #include #include "llvm/Support/ELF.h" #include "llvm/Support/MachO.h" #include "lldb/Host/Endian.h" #include "lldb/Host/Host.h" using namespace lldb; using namespace lldb_private; #define ARCH_SPEC_SEPARATOR_CHAR '-' //---------------------------------------------------------------------- // A structure that describes all of the information we want to know // about each architecture. //---------------------------------------------------------------------- struct ArchDefinition { ByteOrder byte_order; uint32_t addr_byte_size; uint32_t cpu; uint32_t sub; const char *name; }; static const char *g_arch_type_strings[] = { "invalid", "mach-o", "elf" }; #define CPU_ANY (UINT32_MAX) //---------------------------------------------------------------------- // A table that gets searched linearly for matches. This table is used // to convert cpu type and subtypes to architecture names, and to // convert architecture names to cpu types and subtypes. The ordering // is important and allows the precedence to be set when the table is // built. //---------------------------------------------------------------------- static ArchDefinition g_mach_arch_defs[] = { { eByteOrderInvalid, 0, CPU_ANY, CPU_ANY , "all" }, { eByteOrderLittle, 4, llvm::MachO::CPUTypeARM, CPU_ANY , "arm" }, { eByteOrderLittle, 4, llvm::MachO::CPUTypeARM, 0 , "arm" }, { eByteOrderLittle, 4, llvm::MachO::CPUTypeARM, 5 , "armv4" }, { eByteOrderLittle, 4, llvm::MachO::CPUTypeARM, 6 , "armv6" }, { eByteOrderLittle, 4, llvm::MachO::CPUTypeARM, 7 , "armv5" }, { eByteOrderLittle, 4, llvm::MachO::CPUTypeARM, 8 , "xscale" }, { eByteOrderLittle, 4, llvm::MachO::CPUTypeARM, 9 , "armv7" }, { eByteOrderBig, 4, llvm::MachO::CPUTypePowerPC, CPU_ANY , "ppc" }, { eByteOrderBig, 4, llvm::MachO::CPUTypePowerPC, 0 , "ppc" }, { eByteOrderBig, 4, llvm::MachO::CPUTypePowerPC, 1 , "ppc601" }, { eByteOrderBig, 4, llvm::MachO::CPUTypePowerPC, 2 , "ppc602" }, { eByteOrderBig, 4, llvm::MachO::CPUTypePowerPC, 3 , "ppc603" }, { eByteOrderBig, 4, llvm::MachO::CPUTypePowerPC, 4 , "ppc603e" }, { eByteOrderBig, 4, llvm::MachO::CPUTypePowerPC, 5 , "ppc603ev" }, { eByteOrderBig, 4, llvm::MachO::CPUTypePowerPC, 6 , "ppc604" }, { eByteOrderBig, 4, llvm::MachO::CPUTypePowerPC, 7 , "ppc604e" }, { eByteOrderBig, 4, llvm::MachO::CPUTypePowerPC, 8 , "ppc620" }, { eByteOrderBig, 4, llvm::MachO::CPUTypePowerPC, 9 , "ppc750" }, { eByteOrderBig, 4, llvm::MachO::CPUTypePowerPC, 10 , "ppc7400" }, { eByteOrderBig, 4, llvm::MachO::CPUTypePowerPC, 11 , "ppc7450" }, { eByteOrderBig, 4, llvm::MachO::CPUTypePowerPC, 100 , "ppc970" }, { eByteOrderBig, 8, llvm::MachO::CPUTypePowerPC64, 0 , "ppc64" }, { eByteOrderBig, 8, llvm::MachO::CPUTypePowerPC64, 100 , "ppc970-64" }, { eByteOrderLittle, 4, llvm::MachO::CPUTypeI386, 3 , "i386" }, { eByteOrderLittle, 4, llvm::MachO::CPUTypeI386, 4 , "i486" }, { eByteOrderLittle, 4, llvm::MachO::CPUTypeI386, 0x84 , "i486sx" }, { eByteOrderLittle, 4, llvm::MachO::CPUTypeI386, CPU_ANY , "i386" }, { eByteOrderLittle, 8, llvm::MachO::CPUTypeX86_64, 3 , "x86_64" }, { eByteOrderLittle, 8, llvm::MachO::CPUTypeX86_64, CPU_ANY , "x86_64" }, }; //---------------------------------------------------------------------- // Figure out how many architecture definitions we have //---------------------------------------------------------------------- const size_t k_num_mach_arch_defs = sizeof(g_mach_arch_defs)/sizeof(ArchDefinition); //---------------------------------------------------------------------- // A table that gets searched linearly for matches. This table is used // to convert cpu type and subtypes to architecture names, and to // convert architecture names to cpu types and subtypes. The ordering // is important and allows the precedence to be set when the table is // built. //---------------------------------------------------------------------- static ArchDefinition g_elf_arch_defs[] = { { eByteOrderInvalid, 0, llvm::ELF::EM_M32 , 0, "m32" }, // AT&T WE 32100 { eByteOrderBig, 4, llvm::ELF::EM_SPARC , 0, "sparc" }, // Sparc { eByteOrderLittle, 4, llvm::ELF::EM_386 , 0, "i386" }, // Intel 80386 { eByteOrderBig, 4, llvm::ELF::EM_68K , 0, "68k" }, // Motorola 68000 { eByteOrderBig, 4, llvm::ELF::EM_88K , 0, "88k" }, // Motorola 88000 { eByteOrderLittle, 4, llvm::ELF::EM_486 , 0, "i486" }, // Intel 486 (deprecated) { eByteOrderLittle, 4, llvm::ELF::EM_860 , 0, "860" }, // Intel 80860 { eByteOrderBig, 4, llvm::ELF::EM_MIPS , 0, "rs3000" }, // MIPS RS3000 { eByteOrderBig, 4, llvm::ELF::EM_PPC , 0, "ppc" }, // PowerPC { eByteOrderBig, 8, 21 , 0, "ppc64" }, // PowerPC64 { eByteOrderLittle, 4, llvm::ELF::EM_ARM , 0, "arm" }, // ARM { eByteOrderLittle, 4, llvm::ELF::EM_ALPHA , 0, "alpha" }, // DEC Alpha { eByteOrderLittle, 4, llvm::ELF::EM_SPARCV9, 0, "sparc9" }, // SPARC V9 { eByteOrderLittle, 8, llvm::ELF::EM_X86_64 , 0, "x86_64" }, // AMD64 }; //---------------------------------------------------------------------- // Figure out how many architecture definitions we have //---------------------------------------------------------------------- const size_t k_num_elf_arch_defs = sizeof(g_elf_arch_defs)/sizeof(ArchDefinition); //---------------------------------------------------------------------- // Default constructor //---------------------------------------------------------------------- ArchSpec::ArchSpec() : m_type (eArchTypeMachO), // Use the most complete arch definition which will always be translatable to any other ArchitectureType values m_cpu (LLDB_INVALID_CPUTYPE), m_sub (0), m_triple (), m_byte_order (lldb::endian::InlHostByteOrder()), m_addr_byte_size (0) { } //---------------------------------------------------------------------- // Constructor that initializes the object with supplied cpu and // subtypes. //---------------------------------------------------------------------- ArchSpec::ArchSpec (lldb::ArchitectureType arch_type, uint32_t cpu, uint32_t sub) : m_type (arch_type), m_cpu (cpu), m_sub (sub), m_triple (), m_byte_order (lldb::endian::InlHostByteOrder()), m_addr_byte_size (0) { if (m_type == eArchTypeMachO) MachOArchUpdated (); } //---------------------------------------------------------------------- // Constructor that initializes the object with supplied // architecture name. There are also predefined values in // Defines.h: // LLDB_ARCH_DEFAULT // The arch the current system defaults to when a program is // launched without any extra attributes or settings. // // LLDB_ARCH_DEFAULT_32BIT // The 32 bit arch the current system defaults to (if any) // // LLDB_ARCH_DEFAULT_32BIT // The 64 bit arch the current system defaults to (if any) //---------------------------------------------------------------------- ArchSpec::ArchSpec (const char *arch_name) : m_type (eArchTypeMachO), // Use the most complete arch definition which will always be translatable to any other ArchitectureType values m_cpu (LLDB_INVALID_CPUTYPE), m_sub (0), m_triple (), m_byte_order (lldb::endian::InlHostByteOrder()), m_addr_byte_size (0) { SetArch (arch_name); } //---------------------------------------------------------------------- // Destructor //---------------------------------------------------------------------- ArchSpec::~ArchSpec() { } //---------------------------------------------------------------------- // Assignment operator //---------------------------------------------------------------------- const ArchSpec& ArchSpec::operator= (const ArchSpec& rhs) { if (this != &rhs) { m_type = rhs.m_type; m_cpu = rhs.m_cpu; m_sub = rhs.m_sub; m_triple = rhs.m_triple; m_byte_order = rhs.m_byte_order; m_addr_byte_size = rhs.m_addr_byte_size; } return *this; } //---------------------------------------------------------------------- // Get a C string representation of the current architecture //---------------------------------------------------------------------- const char * ArchSpec::AsCString() const { return ArchSpec::AsCString(m_type, m_cpu, m_sub); } //---------------------------------------------------------------------- // Class function to get a C string representation given a CPU type // and subtype. //---------------------------------------------------------------------- const char * ArchSpec::AsCString (lldb::ArchitectureType arch_type, uint32_t cpu, uint32_t sub) { if (arch_type >= kNumArchTypes) return NULL; switch (arch_type) { case kNumArchTypes: case eArchTypeInvalid: break; case eArchTypeMachO: for (uint32_t i=0; i 0) return m_addr_byte_size; switch (m_type) { case kNumArchTypes: case eArchTypeInvalid: break; case eArchTypeMachO: if (GetCPUType() & llvm::MachO::CPUArchABI64) return 8; else return 4; break; case eArchTypeELF: switch (m_cpu) { case llvm::ELF::EM_M32: case llvm::ELF::EM_SPARC: case llvm::ELF::EM_386: case llvm::ELF::EM_68K: case llvm::ELF::EM_88K: case llvm::ELF::EM_486: case llvm::ELF::EM_860: case llvm::ELF::EM_MIPS: case llvm::ELF::EM_PPC: case llvm::ELF::EM_ARM: case llvm::ELF::EM_ALPHA: case llvm::ELF::EM_SPARCV9: return 4; case llvm::ELF::EM_X86_64: return 8; } break; } return 0; } //---------------------------------------------------------------------- // Returns the number of bytes that this object takes when an // instance exists in memory. //---------------------------------------------------------------------- size_t ArchSpec::MemorySize() const { return sizeof(ArchSpec); } bool ArchSpec::SetArchFromTargetTriple (const char *target_triple) { if (target_triple) { const char *hyphen = strchr(target_triple, '-'); if (hyphen) { std::string arch_only (target_triple, hyphen); return SetArch (arch_only.c_str()); } } return SetArch (target_triple); } void ArchSpec::SetMachOArch (uint32_t cpu, uint32_t sub) { m_type = lldb::eArchTypeMachO; m_cpu = cpu; m_sub = sub; MachOArchUpdated (); } void ArchSpec::MachOArchUpdated (size_t idx) { // m_type, m_cpu, and m_sub have been updated, fixup everything else if (idx >= k_num_mach_arch_defs) { for (size_t i=0; i= k_num_elf_arch_defs) { for (size_t i=0; i