strace: Create a status_t type handler and use it for return values.
This way, we save 3 string comparisons on every non-empty return value. Actually this code was broken before, and did not print error names for return types other than status_t, because message.return_value is an unsigned integer and thus "< 0" was always false. Now we cast appropriately in the new TypeHandler, so this works properly.
This commit is contained in:
@@ -91,6 +91,39 @@ TypeHandlerFactory<bool>::Create()
|
|||||||
return new TypeHandlerImpl<bool>();
|
return new TypeHandlerImpl<bool>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// status_t
|
||||||
|
class StatusTypeHandler : public TypeHandler {
|
||||||
|
public:
|
||||||
|
StatusTypeHandler() {}
|
||||||
|
|
||||||
|
string GetParameterValue(Context &context, Parameter *, const void *address)
|
||||||
|
{
|
||||||
|
return RenderValue(context, get_value<status_t>(address));
|
||||||
|
}
|
||||||
|
|
||||||
|
string GetReturnValue(Context &context, uint64 value)
|
||||||
|
{
|
||||||
|
return RenderValue(context, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
string RenderValue(Context &context, uint64 value) const
|
||||||
|
{
|
||||||
|
string rendered = context.FormatUnsigned(value);
|
||||||
|
if (value <= UINT32_MAX && (status_t)value <= 0) {
|
||||||
|
rendered += " ";
|
||||||
|
rendered += strerror(value);
|
||||||
|
}
|
||||||
|
return rendered;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
TypeHandler *
|
||||||
|
create_status_t_type_handler()
|
||||||
|
{
|
||||||
|
return new StatusTypeHandler;
|
||||||
|
}
|
||||||
|
|
||||||
// read_string
|
// read_string
|
||||||
static
|
static
|
||||||
string
|
string
|
||||||
|
|||||||
@@ -97,6 +97,7 @@ struct TypeHandlerFactory {
|
|||||||
|
|
||||||
extern TypeHandler *create_pointer_type_handler();
|
extern TypeHandler *create_pointer_type_handler();
|
||||||
extern TypeHandler *create_string_type_handler();
|
extern TypeHandler *create_string_type_handler();
|
||||||
|
extern TypeHandler *create_status_t_type_handler();
|
||||||
|
|
||||||
// specialization for "const char*"
|
// specialization for "const char*"
|
||||||
template<>
|
template<>
|
||||||
|
|||||||
@@ -265,10 +265,21 @@ patch_syscalls()
|
|||||||
// instead of having this done here manually we should either add the
|
// instead of having this done here manually we should either add the
|
||||||
// patching step to gensyscalls also manually or add metadata to
|
// patching step to gensyscalls also manually or add metadata to
|
||||||
// kernel/syscalls.h and have it parsed automatically
|
// kernel/syscalls.h and have it parsed automatically
|
||||||
|
|
||||||
extern void patch_fcntl();
|
extern void patch_fcntl();
|
||||||
extern void patch_ioctl();
|
extern void patch_ioctl();
|
||||||
extern void patch_area();
|
extern void patch_area();
|
||||||
|
|
||||||
|
for (size_t i = 0; i < sSyscallVector.size(); i++) {
|
||||||
|
Syscall *syscall = sSyscallVector[i];
|
||||||
|
const string returnTypeName = syscall->ReturnType()->TypeName();
|
||||||
|
// patch return type handlers
|
||||||
|
if (returnTypeName == "status_t" || returnTypeName == "ssize_t"
|
||||||
|
|| returnTypeName == "int") {
|
||||||
|
syscall->ReturnType()->SetHandler(create_status_t_type_handler());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
patch_fcntl();
|
patch_fcntl();
|
||||||
patch_ioctl();
|
patch_ioctl();
|
||||||
patch_area();
|
patch_area();
|
||||||
@@ -455,21 +466,12 @@ print_syscall(FILE *outputFile, Syscall* syscall, debug_post_syscall &message,
|
|||||||
syscall->Name().c_str() + 6);
|
syscall->Name().c_str() + 6);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Type *returnType = syscall->ReturnType();
|
Type *returnType = syscall->ReturnType();
|
||||||
TypeHandler *handler = returnType->Handler();
|
TypeHandler *handler = returnType->Handler();
|
||||||
::string value = handler->GetReturnValue(ctx, message.return_value);
|
::string value = handler->GetReturnValue(ctx, message.return_value);
|
||||||
if (value.length() > 0) {
|
if (value.length() > 0)
|
||||||
print_to_string(&string, &length, " = %s", value.c_str());
|
print_to_string(&string, &length, " = %s", value.c_str());
|
||||||
|
|
||||||
// if the return type is status_t or ssize_t, print human-readable
|
|
||||||
// error codes
|
|
||||||
if (returnType->TypeName() == "status_t"
|
|
||||||
|| ((returnType->TypeName() == "ssize_t"
|
|
||||||
|| returnType->TypeName() == "int")
|
|
||||||
&& message.return_value < 0)) {
|
|
||||||
print_to_string(&string, &length, " %s", strerror(message.return_value));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// print arguments
|
// print arguments
|
||||||
|
|||||||
Reference in New Issue
Block a user