void AMXStackFramePrinter::PrintCallerName(const AMXStackFrame &frame) { if (IsMain(frame.amx(), frame.caller_address())) { stream_ << "main"; return; } if (debug_info_.IsLoaded()) { AMXDebugSymbol caller = debug_info_.GetExactFunction(frame.caller_address()); if (caller) { if (IsPublicFunction(frame.amx(), caller.GetCodeStart()) && !IsMain(frame.amx(), caller.GetCodeStart())) { stream_ << "public "; } PrintTag(caller); stream_ << caller.GetName(); return; } } const char *name = 0; if (frame.caller_address() != 0) { name = frame.amx().FindPublic(frame.caller_address()); } if (name != 0) { stream_ << "public " << name; } else { stream_ << "??"; } }
void AMXStackFramePrinter::PrintArgumentList(const AMXStackFrame &frame) { AMXStackFrame prev_frame = frame.GetPrevious(); if (prev_frame) { // Although the symbol's code start address points at the state // switch code block, function arguments actually use the real // function address for the code start because in different states // they may be not the same. cell arg_address = frame.caller_address(); if (UsesAutomata(frame)) { arg_address = GetRealFunctionAddress(frame.amx(), frame.caller_address(), frame.return_address()); } std::vector<AMXDebugSymbol> args; int num_actual_args = 0; if (HaveDebugInfo()) { std::remove_copy_if(debug_info_->GetSymbols().begin(), debug_info_->GetSymbols().end(), std::back_inserter(args), std::not1(IsArgumentOf(arg_address))); std::sort(args.begin(), args.end()); num_actual_args = static_cast<int>(args.size()); } else { static const int kMaxRawArgs = 10; num_actual_args = std::min(kMaxRawArgs, GetNumArgs(frame.amx(), prev_frame.address())); } // Print a comma-separated list of arguments and their values. // If debug info is not available argument names are omitted, // so only the values are printed. for (int i = 0; i < num_actual_args; i++) { if (i > 0) { *stream_ << ", "; } if (HaveDebugInfo()) { PrintArgument(prev_frame, args[i], i); } else { PrintArgument(prev_frame, i); } } // If the number of actual arguments passed to the function exceeds // that obtained via debug info the function may take a variable // number of arguments. In this case we don't evaluate them but just // just say that they are present as we can't say anything about // their names and types. int num_var_args = GetNumArgs(frame.amx(), prev_frame.address()) - num_actual_args; if (num_var_args > 0) { if (num_actual_args != 0) { *stream_ << ", "; } PrintVariableArguments(num_var_args); } } }
void AMXStackFramePrinter::PrintCallerName(const AMXStackFrame &frame) { if (IsMain(frame.amx(), frame.caller_address())) { *stream_ << "main"; } else { const char *name = 0; if (frame.caller_address() != 0) { name = frame.amx().FindPublic(frame.caller_address()); } if (name != 0) { *stream_ << "public " << name; } else { *stream_ << "??"; } } }
AMXDebugSymbol AMXStackFramePrinter::GetCallerSymbol( const AMXStackFrame &frame) const { AMXDebugSymbol caller; if (HaveDebugInfo()) { caller = debug_info_->GetExactFunction(frame.caller_address()); } return caller; }
void AMXStackFramePrinter::PrintState(const AMXStackFrame &frame) { AMXDebugAutomaton automaton = debug_info_->GetAutomaton( GetStateVarAddress(frame.amx(), frame.caller_address())); if (automaton) { std::vector<cell> states = GetStateIDs(frame.amx(), frame.caller_address(), frame.return_address()); if (!states.empty()) { *stream_ << "<" << automaton.GetName() << ":"; for (std::size_t i = 0; i < states.size(); i++ ) { if (i > 0) { *stream_ << ", "; } AMXDebugState state = debug_info_->GetState(automaton.GetID(), states[i]); if (state) { *stream_ << state.GetName(); } } *stream_ << ">"; } } }
bool AMXStackFramePrinter::UsesAutomata(const AMXStackFrame &frame) const { return GetStateVarAddress(frame.amx(), frame.caller_address()) > 0; }