diff --git a/src/arch/arm/tracers/ArmCapstone.py b/src/arch/arm/tracers/ArmCapstone.py new file mode 100644 index 0000000000..7f1b6a9e8a --- /dev/null +++ b/src/arch/arm/tracers/ArmCapstone.py @@ -0,0 +1,44 @@ +# Copyright (c) 2023 Arm Limited +# All rights reserved. +# +# The license below extends only to copyright in the software and shall +# not be construed as granting a license to any other intellectual +# property including but not limited to intellectual property relating +# to a hardware implementation of the functionality of the software +# licensed hereunder. You may use the software subject to the license +# terms below provided that you ensure that this notice is replicated +# unmodified and in its entirety in all distributions of the software, +# modified or unmodified, in source code or in binary form. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from m5.SimObject import SimObject +from m5.params import * +from m5.objects.Capstone import CapstoneDisassembler + + +class ArmCapstoneDisassembler(CapstoneDisassembler): + type = "ArmCapstoneDisassembler" + cxx_class = "gem5::trace::ArmCapstoneDisassembler" + cxx_header = "arch/arm/tracers/capstone.hh" diff --git a/src/arch/arm/tracers/SConscript b/src/arch/arm/tracers/SConscript index 15945a4ac4..ca012c5c2e 100644 --- a/src/arch/arm/tracers/SConscript +++ b/src/arch/arm/tracers/SConscript @@ -1,4 +1,4 @@ -# Copyright (c) 2018 ARM Limited +# Copyright (c) 2018, 2023 Arm Limited # All rights reserved. # # The license below extends only to copyright in the software and shall @@ -42,3 +42,8 @@ Source('tarmac_parser.cc', tags='arm isa') Source('tarmac_tracer.cc', tags='arm isa') Source('tarmac_record.cc', tags='arm isa') Source('tarmac_record_v8.cc', tags='arm isa') + +if env['CONF']['HAVE_CAPSTONE']: + SimObject('ArmCapstone.py', sim_objects=['ArmCapstoneDisassembler'], + tags=['capstone', 'arm isa']) + Source('capstone.cc', tags=['capstone', 'arm isa']) diff --git a/src/arch/arm/tracers/capstone.cc b/src/arch/arm/tracers/capstone.cc new file mode 100644 index 0000000000..469dc46568 --- /dev/null +++ b/src/arch/arm/tracers/capstone.cc @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2023 Arm Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "arch/arm/tracers/capstone.hh" + +#include "arch/arm/insts/static_inst.hh" +#include "base/output.hh" + +namespace gem5 +{ + +namespace trace +{ + +using namespace ArmISA; + +ArmCapstoneDisassembler::ArmCapstoneDisassembler(const Params &p) + : CapstoneDisassembler(p) +{ + if (cs_open(CS_ARCH_ARM64, CS_MODE_ARM, &arm64Handle) != CS_ERR_OK) + panic("Unable to open capstone for arm64 disassembly"); + + if (cs_open(CS_ARCH_ARM, CS_MODE_ARM, &armHandle) != CS_ERR_OK) + panic("Unable to open capstone for arm disassembly"); +} + +const csh* +ArmCapstoneDisassembler::currHandle(const PCStateBase &_pc) const +{ + auto pc = _pc.as(); + if (pc.aarch64()) { + return &arm64Handle; + } else { + auto mode = pc.thumb() ? CS_MODE_THUMB : CS_MODE_ARM; + cs_option(armHandle, CS_OPT_MODE, mode); + return &armHandle; + } +} + +} // namespace trace +} // namespace gem5 diff --git a/src/arch/arm/tracers/capstone.hh b/src/arch/arm/tracers/capstone.hh new file mode 100644 index 0000000000..929fbad6f5 --- /dev/null +++ b/src/arch/arm/tracers/capstone.hh @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2023 Arm Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __ARCH_ARM_TRACERS_CAPSTONE_HH__ +#define __ARCH_ARM_TRACERS_CAPSTONE_HH__ + +#include "cpu/capstone.hh" +#include "params/ArmCapstoneDisassembler.hh" + +namespace gem5 +{ + +class ThreadContext; + +namespace trace +{ + +class ArmCapstoneDisassembler : public CapstoneDisassembler +{ + public: + PARAMS(ArmCapstoneDisassembler); + ArmCapstoneDisassembler(const Params &p); + + protected: + const csh* currHandle(const PCStateBase &pc) const override; + + protected: + csh arm64Handle; + csh armHandle; +}; + +} // namespace trace +} // namespace gem5 + +#endif // __ARCH_ARM_TRACERS_CAPSTONE_HH__ diff --git a/src/arch/arm/tracers/tarmac_base.cc b/src/arch/arm/tracers/tarmac_base.cc index 25524d24b6..01add3037a 100644 --- a/src/arch/arm/tracers/tarmac_base.cc +++ b/src/arch/arm/tracers/tarmac_base.cc @@ -68,7 +68,6 @@ TarmacBaseRecord::InstEntry::InstEntry( : taken(predicate) , addr(pc.instAddr()) , opcode(staticInst->getEMI() & 0xffffffff), - disassemble(staticInst->disassemble(addr)), isetstate(pcToISetState(pc)), mode(MODE_USER) { @@ -76,11 +75,6 @@ TarmacBaseRecord::InstEntry::InstEntry( // Operating mode gained by reading the architectural register (CPSR) const CPSR cpsr = thread->readMiscRegNoEffect(MISCREG_CPSR); mode = (OperatingMode) (uint8_t)cpsr.mode; - - // In Tarmac, instruction names are printed in capital - // letters. - std::for_each(disassemble.begin(), disassemble.end(), - [](char& c) { c = toupper(c); }); } TarmacBaseRecord::RegEntry::RegEntry(const PCStateBase &pc) diff --git a/src/arch/arm/tracers/tarmac_base.hh b/src/arch/arm/tracers/tarmac_base.hh index 501eb1b008..9e80f6d1f1 100644 --- a/src/arch/arm/tracers/tarmac_base.hh +++ b/src/arch/arm/tracers/tarmac_base.hh @@ -93,7 +93,6 @@ class TarmacBaseRecord : public InstRecord bool taken; Addr addr; ArmISA::MachInst opcode; - std::string disassemble; ISetState isetstate; ArmISA::OperatingMode mode; }; diff --git a/src/arch/arm/tracers/tarmac_record.cc b/src/arch/arm/tracers/tarmac_record.cc index 59d6a18b39..5aa1f7e957 100644 --- a/src/arch/arm/tracers/tarmac_record.cc +++ b/src/arch/arm/tracers/tarmac_record.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 ARM Limited + * Copyright (c) 2017-2019, 2023 Arm Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -123,7 +123,8 @@ TarmacTracerRecord::TarmacTracerRecord(Tick _when, ThreadContext *_thread, TarmacTracerRecord::TraceInstEntry::TraceInstEntry( const TarmacContext& tarmCtx, bool predicate) - : InstEntry(tarmCtx.thread, *tarmCtx.pc, tarmCtx.staticInst, predicate) + : InstEntry(tarmCtx.thread, *tarmCtx.pc, tarmCtx.staticInst, predicate), + disassemble(tarmCtx.tracer.disassemble(tarmCtx.staticInst, *tarmCtx.pc)) { secureMode = isSecure(tarmCtx.thread); @@ -140,6 +141,11 @@ TarmacTracerRecord::TraceInstEntry::TraceInstEntry( // for 16bit (Thumb) instruction. opcode = arm_inst->encoding(); + // In Tarmac, instruction names are printed in capital + // letters. + std::for_each(disassemble.begin(), disassemble.end(), + [](char& c) { c = toupper(c); }); + // Update the instruction count: number of executed // instructions. instCount++; @@ -332,6 +338,7 @@ TarmacTracerRecord::dump() auto ®Queue = tracer.regQueue; const TarmacContext tarmCtx( + tracer, thread, staticInst->isMicroop()? macroStaticInst : staticInst, *pc diff --git a/src/arch/arm/tracers/tarmac_record.hh b/src/arch/arm/tracers/tarmac_record.hh index 009df5db29..d80121b1b9 100644 --- a/src/arch/arm/tracers/tarmac_record.hh +++ b/src/arch/arm/tracers/tarmac_record.hh @@ -115,6 +115,9 @@ class TarmacTracerRecord : public TarmacBaseRecord * 32 otherwise (ARM and BigThumb) */ uint8_t instSize; + + /** Instruction disassembly */ + std::string disassemble; }; /** Register Entry */ diff --git a/src/arch/arm/tracers/tarmac_tracer.hh b/src/arch/arm/tracers/tarmac_tracer.hh index f8c7b5ca53..71207b3860 100644 --- a/src/arch/arm/tracers/tarmac_tracer.hh +++ b/src/arch/arm/tracers/tarmac_tracer.hh @@ -58,6 +58,8 @@ class OutputStream; namespace trace { +class TarmacTracer; + /** * This object type is encapsulating the informations needed by * a Tarmac record to generate it's own entries. @@ -65,15 +67,18 @@ namespace trace { class TarmacContext { public: - TarmacContext(ThreadContext* _thread, + TarmacContext(const TarmacTracer &_tracer, + ThreadContext* _thread, const StaticInstPtr _staticInst, const PCStateBase &_pc) - : thread(_thread), staticInst(_staticInst), pc(_pc.clone()) + : tracer(_tracer), thread(_thread), staticInst(_staticInst), + pc(_pc.clone()) {} std::string tarmacCpuName() const; public: + const TarmacTracer &tracer; ThreadContext* thread; const StaticInstPtr staticInst; std::unique_ptr pc; diff --git a/src/cpu/Capstone.py b/src/cpu/Capstone.py new file mode 100644 index 0000000000..4b6b5fd84a --- /dev/null +++ b/src/cpu/Capstone.py @@ -0,0 +1,45 @@ +# Copyright (c) 2023 Arm Limited +# All rights reserved. +# +# The license below extends only to copyright in the software and shall +# not be construed as granting a license to any other intellectual +# property including but not limited to intellectual property relating +# to a hardware implementation of the functionality of the software +# licensed hereunder. You may use the software subject to the license +# terms below provided that you ensure that this notice is replicated +# unmodified and in its entirety in all distributions of the software, +# modified or unmodified, in source code or in binary form. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from m5.SimObject import SimObject +from m5.params import * +from m5.objects.InstTracer import InstDisassembler + + +class CapstoneDisassembler(InstDisassembler): + type = "CapstoneDisassembler" + cxx_class = "gem5::trace::CapstoneDisassembler" + cxx_header = "cpu/capstone.hh" + abstract = True diff --git a/src/cpu/SConscript b/src/cpu/SConscript index d6dcd2f6ea..03ba7b924d 100644 --- a/src/cpu/SConscript +++ b/src/cpu/SConscript @@ -1,6 +1,6 @@ # -*- mode:python -*- -# Copyright (c) 2020 ARM Limited +# Copyright (c) 2020, 2023 Arm Limited # All rights reserved. # # The license below extends only to copyright in the software and shall @@ -115,6 +115,9 @@ Source('simple_thread.cc') Source('thread_context.cc') Source('thread_state.cc') Source('timing_expr.cc') +SourceLib('capstone', tags='capstone') +Source('capstone.cc', tags='capstone') +SimObject('Capstone.py', sim_objects=['CapstoneDisassembler'], tags='capstone') SimObject('DummyChecker.py', sim_objects=['DummyChecker']) Source('checker/cpu.cc') diff --git a/src/cpu/SConsopts b/src/cpu/SConsopts new file mode 100644 index 0000000000..94e55ece32 --- /dev/null +++ b/src/cpu/SConsopts @@ -0,0 +1,50 @@ +# Copyright (c) 2023 Arm Limited +# All rights reserved. +# +# The license below extends only to copyright in the software and shall +# not be construed as granting a license to any other intellectual +# property including but not limited to intellectual property relating +# to a hardware implementation of the functionality of the software +# licensed hereunder. You may use the software subject to the license +# terms below provided that you ensure that this notice is replicated +# unmodified and in its entirety in all distributions of the software, +# modified or unmodified, in source code or in binary form. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Import('*') + +from gem5_scons import warning + +import gem5_scons + +with gem5_scons.Configure(main) as conf: + # Check for + conf.env['CONF']['HAVE_CAPSTONE'] = conf.CheckHeader('capstone/capstone.h', '<>') + + if conf.env['CONF']['HAVE_CAPSTONE']: + conf.env.TagImplies('capstone', 'gem5 lib') + else: + warning("Header file not found.\n" + "This host has no capstone library installed.") diff --git a/src/cpu/capstone.cc b/src/cpu/capstone.cc new file mode 100644 index 0000000000..4c2896312d --- /dev/null +++ b/src/cpu/capstone.cc @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2023 Arm Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "cpu/capstone.hh" + +#include "base/output.hh" + +namespace gem5 +{ + +namespace trace +{ + +std::string +CapstoneDisassembler::disassemble(StaticInstPtr inst, + const PCStateBase &pc, + const loader::SymbolTable *symtab) const +{ + std::string inst_dist; + if (inst->isPseudo() || inst->isMicroop()) { + // Capstone doesn't have any visibility over microops nor over + // gem5 pseudo ops. Use native disassembler instead + inst_dist = InstDisassembler::disassemble(inst, pc, symtab); + } else { + // Stripping the extended fields from the ExtMachInst + auto mach_inst = inst->getEMI() & mask(inst->size() * 8); + + cs_insn *insn; + // capstone disassembler + if (const csh *curr_handle = currHandle(pc); curr_handle != nullptr) { + size_t count = cs_disasm(*curr_handle, (uint8_t*)&mach_inst, + inst->size(), 0, 0, &insn); + + // As we are passing only one instruction, we are expecting one instruction only + // being disassembled + assert(count <= 1); + + for (int idx = 0; idx < count; idx++) { + inst_dist += csprintf(" %s %s", insn[idx].mnemonic, insn[idx].op_str); + } + } else { + // No valid handle; return an invalid string + inst_dist += " capstone failure"; + } + } + + return inst_dist; +} + +CapstoneDisassembler::CapstoneDisassembler(const Params &p) + : InstDisassembler(p) +{ +} + +} // namespace trace +} // namespace gem5 diff --git a/src/cpu/capstone.hh b/src/cpu/capstone.hh new file mode 100644 index 0000000000..1a197e5086 --- /dev/null +++ b/src/cpu/capstone.hh @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2023 Arm Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __CPU_CAPSTONE_HH__ +#define __CPU_CAPSTONE_HH__ + +#include + +#include "params/CapstoneDisassembler.hh" +#include "sim/insttracer.hh" + +namespace gem5 +{ + +class ThreadContext; + +namespace trace { + +/** + * Capstone Disassembler: + * The disassembler relies on the capstone library to convert + * the StaticInst encoding into the disassembled string. + * + * One thing to keep in mind is that the disassembled + * instruction might not coincide with the instruction being + * decoded + executed in gem5. This could be the case if + * there was a bug in either gem5 or in capstone itself. + * This scenatio is not possible with the native gem5 disassembler + * as the instruction mnemonic is tightly coupled with the + * decoded(=generated) instruction (you print what you decode) + * + * The Capstone dispatches to the native disassembler in + * two cases: + * + * a) m5 pseudo ops + * b) micro-ops + */ +class CapstoneDisassembler : public InstDisassembler +{ + public: + PARAMS(CapstoneDisassembler); + CapstoneDisassembler(const Params &p); + + std::string + disassemble(StaticInstPtr inst, + const PCStateBase &pc, + const loader::SymbolTable *symtab) const override; + + protected: + + /** + * Return a pointer to the current capstone handle (csh). + * + * Any ISA extension of the Capstone disassembler should + * initialize (with cs_open) one or more capstone handles + * at construcion time. + * (You might need more than one handle in case the ISA + * has more than one mode of operation, e.g. arm and arm64) + * The current handle in use should be returned every time + * the currHandle is called. + */ + virtual const csh* currHandle(const PCStateBase &pc) const = 0; +}; + +} // namespace trace +} // namespace gem5 + +#endif // __CPU_CAPSTONE_HH__ diff --git a/src/cpu/exetrace.cc b/src/cpu/exetrace.cc index 22d0d4be69..6cd5269fa7 100644 --- a/src/cpu/exetrace.cc +++ b/src/cpu/exetrace.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2019 ARM Limited + * Copyright (c) 2017, 2019, 2023 Arm Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -101,7 +101,7 @@ ExeTracerRecord::traceInst(const StaticInstPtr &inst, bool ran) // outs << std::setw(26) << std::left; - outs << inst->disassemble(cur_pc, &loader::debugSymbolTable); + outs << tracer.disassemble(inst, *pc, &loader::debugSymbolTable); if (ran) { outs << " : "; diff --git a/src/cpu/exetrace.hh b/src/cpu/exetrace.hh index 143cfa0eb3..3fbeb98bc3 100644 --- a/src/cpu/exetrace.hh +++ b/src/cpu/exetrace.hh @@ -1,4 +1,16 @@ /* + * Copyright (c) 2023 Arm Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * * Copyright (c) 2001-2005 The Regents of The University of Michigan * All rights reserved. * @@ -49,14 +61,19 @@ class ExeTracerRecord : public InstRecord public: ExeTracerRecord(Tick _when, ThreadContext *_thread, const StaticInstPtr _staticInst, const PCStateBase &_pc, + const ExeTracer &_tracer, const StaticInstPtr _macroStaticInst = NULL) - : InstRecord(_when, _thread, _staticInst, _pc, _macroStaticInst) + : InstRecord(_when, _thread, _staticInst, _pc, _macroStaticInst), + tracer(_tracer) { } void traceInst(const StaticInstPtr &inst, bool ran); void dump(); + + protected: + const ExeTracer &tracer; }; class ExeTracer : public InstTracer @@ -75,7 +92,7 @@ class ExeTracer : public InstTracer return NULL; return new ExeTracerRecord(when, tc, - staticInst, pc, macroStaticInst); + staticInst, pc, *this, macroStaticInst); } }; diff --git a/src/cpu/nativetrace.cc b/src/cpu/nativetrace.cc index 3070205b9f..60efc791de 100644 --- a/src/cpu/nativetrace.cc +++ b/src/cpu/nativetrace.cc @@ -1,4 +1,16 @@ /* + * Copyright (c) 2023 Arm Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * * Copyright (c) 2006-2009 The Regents of The University of Michigan * All rights reserved. * @@ -49,6 +61,17 @@ NativeTrace::NativeTrace(const Params &p) fd = native_listener->accept(); } +NativeTraceRecord::NativeTraceRecord( + NativeTrace *_parent, + Tick _when, ThreadContext *_thread, + const StaticInstPtr _staticInst, const PCStateBase &_pc, + const StaticInstPtr _macroStaticInst) + : ExeTracerRecord(_when, _thread, _staticInst, _pc, + *_parent, _macroStaticInst), + parent(_parent) +{ +} + void NativeTraceRecord::dump() { diff --git a/src/cpu/nativetrace.hh b/src/cpu/nativetrace.hh index a19acaca3f..a0866e130f 100644 --- a/src/cpu/nativetrace.hh +++ b/src/cpu/nativetrace.hh @@ -1,4 +1,16 @@ /* + * Copyright (c) 2023 Arm Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * * Copyright (c) 2006-2009 The Regents of The University of Michigan * All rights reserved. * @@ -50,20 +62,16 @@ class NativeTrace; class NativeTraceRecord : public ExeTracerRecord { - protected: - NativeTrace * parent; - public: - NativeTraceRecord(NativeTrace * _parent, + NativeTraceRecord(NativeTrace *_parent, Tick _when, ThreadContext *_thread, const StaticInstPtr _staticInst, const PCStateBase &_pc, - const StaticInstPtr _macroStaticInst=nullptr) - : ExeTracerRecord(_when, _thread, _staticInst, _pc, _macroStaticInst), - parent(_parent) - { - } + const StaticInstPtr _macroStaticInst=nullptr); void dump(); + + private: + NativeTrace *parent; }; class NativeTrace : public ExeTracer diff --git a/src/sim/InstTracer.py b/src/sim/InstTracer.py index 34c97dd43e..c8b3673d47 100644 --- a/src/sim/InstTracer.py +++ b/src/sim/InstTracer.py @@ -1,3 +1,15 @@ +# Copyright (c) 2023 Arm Limited +# All rights reserved. +# +# The license below extends only to copyright in the software and shall +# not be construed as granting a license to any other intellectual +# property including but not limited to intellectual property relating +# to a hardware implementation of the functionality of the software +# licensed hereunder. You may use the software subject to the license +# terms below provided that you ensure that this notice is replicated +# unmodified and in its entirety in all distributions of the software, +# modified or unmodified, in source code or in binary form. +# # Copyright (c) 2007 The Regents of The University of Michigan # All rights reserved. # @@ -28,8 +40,18 @@ from m5.SimObject import SimObject from m5.params import * +class InstDisassembler(SimObject): + type = "InstDisassembler" + cxx_header = "sim/insttracer.hh" + cxx_class = "gem5::trace::InstDisassembler" + + class InstTracer(SimObject): type = "InstTracer" cxx_header = "sim/insttracer.hh" cxx_class = "gem5::trace::InstTracer" abstract = True + + disassembler = Param.InstDisassembler( + InstDisassembler(), "Instruction Disassembler" + ) diff --git a/src/sim/SConscript b/src/sim/SConscript index e26676c00a..78b06c5b1d 100644 --- a/src/sim/SConscript +++ b/src/sim/SConscript @@ -105,7 +105,7 @@ GTest('proxy_ptr.test', 'proxy_ptr.test.cc') GTest('serialize.test', 'serialize.test.cc', with_tag('gem5 serialize')) GTest('serialize_handlers.test', 'serialize_handlers.test.cc') -SimObject('InstTracer.py', sim_objects=['InstTracer']) +SimObject('InstTracer.py', sim_objects=['InstTracer', 'InstDisassembler']) SimObject('Process.py', sim_objects=['Process', 'EmulatedDriver']) Source('faults.cc') Source('process.cc') diff --git a/src/sim/insttracer.hh b/src/sim/insttracer.hh index 9c9bca7692..37e29756a2 100644 --- a/src/sim/insttracer.hh +++ b/src/sim/insttracer.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2017, 2020 ARM Limited + * Copyright (c) 2014, 2017, 2020, 2023 Arm Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -48,6 +48,7 @@ #include "cpu/inst_res.hh" #include "cpu/inst_seq.hh" #include "cpu/static_inst.hh" +#include "params/InstTracer.hh" #include "sim/sim_object.hh" namespace gem5 @@ -286,10 +287,37 @@ class InstRecord bool getFaulting() const { return faulting; } }; +/** + * The base InstDisassembler class provides a one-API interface + * to disassemble the instruction passed as a first argument. + * It also provides a base implementation which is + * simply calling the StaticInst::disassemble method, which + * is the usual interface for disassembling + * a gem5 instruction. + */ +class InstDisassembler : public SimObject +{ + public: + InstDisassembler(const SimObjectParams ¶ms) + : SimObject(params) + {} + + virtual std::string + disassemble(StaticInstPtr inst, + const PCStateBase &pc, + const loader::SymbolTable *symtab) const + { + return inst->disassemble(pc.instAddr(), symtab); + } +}; + class InstTracer : public SimObject { public: - InstTracer(const Params &p) : SimObject(p) {} + PARAMS(InstTracer); + InstTracer(const Params &p) + : SimObject(p), disassembler(p.disassembler) + {} virtual ~InstTracer() {} @@ -297,6 +325,17 @@ class InstTracer : public SimObject getInstRecord(Tick when, ThreadContext *tc, const StaticInstPtr staticInst, const PCStateBase &pc, const StaticInstPtr macroStaticInst=nullptr) = 0; + + std::string + disassemble(StaticInstPtr inst, + const PCStateBase &pc, + const loader::SymbolTable *symtab=nullptr) const + { + return disassembler->disassemble(inst, pc, symtab); + } + + private: + InstDisassembler *disassembler; }; } // namespace trace