From b8883f887e4cef97bd75ca2227e47ea3a5d6da63 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sun, 8 Dec 2019 01:33:23 -0800 Subject: 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 Maintainer: Jason Lowe-Power Tested-by: kokoro --- src/sim/guest_abi.hh | 75 +++++++++++++++++++++++++++++++++++++++++++++++ src/sim/guest_abi.test.cc | 7 +++++ 2 files changed, 82 insertions(+) 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 #include +#include #include class ThreadContext; @@ -213,6 +214,14 @@ class VarArgs } }; +template +std::ostream & +operator << (std::ostream &os, const VarArgs &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(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 +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 +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::get(tc, position); + + // Add this argument to the list. + os << next; + + // Recursively handle any remaining arguments. + dumpArgsFrom(count + 1, os, tc, position); +} + } // namespace GuestABI @@ -347,4 +394,32 @@ invokeSimcall(ThreadContext *tc, void (*target)(ThreadContext *, Args...)) tc, std::function(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 +std::string +dumpSimcall(std::string name, ThreadContext *tc, + std::function target= + std::function()) +{ + auto position = typename ABI::Position(); + std::ostringstream ss; + + ss << name; + GuestABI::dumpArgsFrom(0, ss, tc, position); + return ss.str(); +} + +template +std::string +dumpSimcall(std::string name, ThreadContext *tc, + Ret (*target)(ThreadContext *, Args...)) +{ + return dumpSimcall( + name, tc, std::function(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("test", &tc, testIntVoid); + EXPECT_EQ(dump, "test(0, 11, 2, 13, ...)"); +} -- cgit v1.2.3