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:
Augustin Cavalier
2023-03-28 14:23:27 -04:00
parent 8b9267565d
commit 28d588d51e
3 changed files with 47 additions and 11 deletions
+33
View File
@@ -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
+1
View File
@@ -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<>
+13 -11
View File
@@ -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