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>();
|
||||
}
|
||||
|
||||
// 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
|
||||
static
|
||||
string
|
||||
|
||||
@@ -97,6 +97,7 @@ struct TypeHandlerFactory {
|
||||
|
||||
extern TypeHandler *create_pointer_type_handler();
|
||||
extern TypeHandler *create_string_type_handler();
|
||||
extern TypeHandler *create_status_t_type_handler();
|
||||
|
||||
// specialization for "const char*"
|
||||
template<>
|
||||
|
||||
@@ -265,10 +265,21 @@ patch_syscalls()
|
||||
// instead of having this done here manually we should either add the
|
||||
// patching step to gensyscalls also manually or add metadata to
|
||||
// kernel/syscalls.h and have it parsed automatically
|
||||
|
||||
extern void patch_fcntl();
|
||||
extern void patch_ioctl();
|
||||
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_ioctl();
|
||||
patch_area();
|
||||
@@ -455,21 +466,12 @@ print_syscall(FILE *outputFile, Syscall* syscall, debug_post_syscall &message,
|
||||
syscall->Name().c_str() + 6);
|
||||
}
|
||||
}
|
||||
|
||||
Type *returnType = syscall->ReturnType();
|
||||
TypeHandler *handler = returnType->Handler();
|
||||
::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());
|
||||
|
||||
// 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
|
||||
|
||||
Reference in New Issue
Block a user