diff options
author | Gabe Black <gabeblack@google.com> | 2019-12-08 01:33:23 -0800 |
---|---|---|
committer | Gabe Black <gabeblack@google.com> | 2020-01-13 22:44:49 +0000 |
commit | b8883f887e4cef97bd75ca2227e47ea3a5d6da63 (patch) | |
tree | 546fbbc9315e454bbdaf76d09353fa8c8e936d63 | |
parent | aabe7e1f697dc87e8ad0956c53a81dc1ecce2595 (diff) | |
download | gem5-b8883f887e4cef97bd75ca2227e47ea3a5d6da63.tar.xz |
sim: Add a dumpSimcall mechanism to GuestABI.
This dumps a signature for a simcall as if it was going to be invoked,
and can be used for debugging.
Change-Id: I6262b94ad4186bac8dc5a1469e9bb3b8ae9d34e1
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/23460
Reviewed-by: Jason Lowe-Power <jason@lowepower.com>
Maintainer: Jason Lowe-Power <jason@lowepower.com>
Tested-by: kokoro <noreply+kokoro@google.com>
-rw-r--r-- | src/sim/guest_abi.hh | 75 | ||||
-rw-r--r-- | src/sim/guest_abi.test.cc | 7 |
2 files changed, 82 insertions, 0 deletions
diff --git a/src/sim/guest_abi.hh b/src/sim/guest_abi.hh index b2176a6df..ff1464e8f 100644 --- a/src/sim/guest_abi.hh +++ b/src/sim/guest_abi.hh @@ -32,6 +32,7 @@ #include <functional> #include <memory> +#include <sstream> #include <type_traits> class ThreadContext; @@ -213,6 +214,14 @@ class VarArgs } }; +template <typename ...Types> +std::ostream & +operator << (std::ostream &os, const VarArgs<Types...> &va) +{ + os << "..."; + return os; +} + // The ABI independent hook which tells the GuestABI mechanism what to do with // a VarArgs argument. It constructs the underlying implementation which knows // about the ABI, and installs it in the VarArgs wrapper to give to the @@ -301,6 +310,44 @@ callFrom(ThreadContext *tc, typename ABI::Position &position, callFrom<ABI, Args...>(tc, position, partial); } + + +/* + * These functions are like the ones above, except they print the arguments + * a target function would be called with instead of actually calling it. + */ + +// With no arguments to print, add the closing parenthesis and return. +template <typename ABI, typename Ret> +static void +dumpArgsFrom(int count, std::ostream &os, ThreadContext *tc, + typename ABI::Position &position) +{ + os << ")"; +} + +// Recursively gather arguments for target from tc until we get to the base +// case above, and append those arguments to the string stream being +// constructed. +template <typename ABI, typename Ret, typename NextArg, typename ...Args> +static void +dumpArgsFrom(int count, std::ostream &os, ThreadContext *tc, + typename ABI::Position &position) +{ + // Either open the parenthesis or add a comma, depending on where we are + // in the argument list. + os << (count ? ", " : "("); + + // Extract the next argument from the thread context. + NextArg next = Argument<ABI, NextArg>::get(tc, position); + + // Add this argument to the list. + os << next; + + // Recursively handle any remaining arguments. + dumpArgsFrom<ABI, Ret, Args...>(count + 1, os, tc, position); +} + } // namespace GuestABI @@ -347,4 +394,32 @@ invokeSimcall(ThreadContext *tc, void (*target)(ThreadContext *, Args...)) tc, std::function<void(ThreadContext *, Args...)>(target)); } + +// These functions also wrap a simulator level function. Instead of running the +// function, they return a string which shows what arguments the function would +// be invoked with if it were called from the given context. + +template <typename ABI, typename Ret, typename ...Args> +std::string +dumpSimcall(std::string name, ThreadContext *tc, + std::function<Ret(ThreadContext *, Args...)> target= + std::function<Ret(ThreadContext *, Args...)>()) +{ + auto position = typename ABI::Position(); + std::ostringstream ss; + + ss << name; + GuestABI::dumpArgsFrom<ABI, Ret, Args...>(0, ss, tc, position); + return ss.str(); +} + +template <typename ABI, typename Ret, typename ...Args> +std::string +dumpSimcall(std::string name, ThreadContext *tc, + Ret (*target)(ThreadContext *, Args...)) +{ + return dumpSimcall<ABI>( + name, tc, std::function<Ret(ThreadContext *, Args...)>(target)); +} + #endif // __SIM_GUEST_ABI_HH__ diff --git a/src/sim/guest_abi.test.cc b/src/sim/guest_abi.test.cc index ee536aa13..19efb7db2 100644 --- a/src/sim/guest_abi.test.cc +++ b/src/sim/guest_abi.test.cc @@ -275,3 +275,10 @@ TEST(GuestABI, ABI_returns) EXPECT_EQ(tc.floatResult, DoubleRetValue + 2.0); } } + +TEST(GuestABI, dumpSimcall) +{ + ThreadContext tc; + std::string dump = dumpSimcall<TestABI_1D>("test", &tc, testIntVoid); + EXPECT_EQ(dump, "test(0, 11, 2, 13, ...)"); +} |