strace: Move poll/select syscall handling to an "event" file.
Also bring along the type handlers, and use FlagsTypeHandler.
This commit is contained in:
@@ -21,6 +21,7 @@ local straceSources =
|
||||
MemoryReader.cpp
|
||||
|
||||
area.cpp
|
||||
events.cpp
|
||||
exec.cpp
|
||||
fcntl.cpp
|
||||
ioctl.cpp
|
||||
|
||||
@@ -101,68 +101,6 @@ TypeHandlerImpl<iovec *>::GetReturnValue(Context &context, uint64 value)
|
||||
}
|
||||
|
||||
|
||||
static string
|
||||
read_fdset(Context &context, void *data)
|
||||
{
|
||||
// default FD_SETSIZE is 1024
|
||||
unsigned long tmp[1024 / (sizeof(unsigned long) * 8)];
|
||||
int32 bytesRead;
|
||||
|
||||
status_t err = context.Reader().Read(data, &tmp, sizeof(tmp), bytesRead);
|
||||
if (err != B_OK)
|
||||
return context.FormatPointer(data);
|
||||
|
||||
/* implicitly align to unsigned long lower boundary */
|
||||
int count = bytesRead / sizeof(unsigned long);
|
||||
int added = 0;
|
||||
|
||||
string r;
|
||||
r.reserve(16);
|
||||
|
||||
r = "[";
|
||||
|
||||
for (int i = 0; i < count && added < 8; i++) {
|
||||
for (int j = 0;
|
||||
j < (int)(sizeof(unsigned long) * 8) && added < 8; j++) {
|
||||
if (tmp[i] & (1UL << j)) {
|
||||
if (added > 0)
|
||||
r += " ";
|
||||
unsigned int fd = i * sizeof(unsigned long) * 8 + j;
|
||||
r += format_number(fd);
|
||||
added++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (added >= 8)
|
||||
r += " ...";
|
||||
|
||||
r += "]";
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
template<>
|
||||
string
|
||||
TypeHandlerImpl<fd_set *>::GetParameterValue(Context &context, Parameter *,
|
||||
const void *address)
|
||||
{
|
||||
void *data = *(void **)address;
|
||||
if (data != NULL && context.GetContents(Context::SIMPLE_STRUCTS))
|
||||
return read_fdset(context, data);
|
||||
return context.FormatPointer(data);
|
||||
}
|
||||
|
||||
|
||||
template<>
|
||||
string
|
||||
TypeHandlerImpl<fd_set *>::GetReturnValue(Context &context, uint64 value)
|
||||
{
|
||||
return context.FormatPointer((void *)value);
|
||||
}
|
||||
|
||||
|
||||
static string
|
||||
format_ltype(Context &context, int ltype)
|
||||
{
|
||||
@@ -219,127 +157,6 @@ format_pointer(Context &context, flock *lock)
|
||||
|
||||
|
||||
|
||||
static string
|
||||
format_signed_number(int32 value)
|
||||
{
|
||||
char tmp[32];
|
||||
snprintf(tmp, sizeof(tmp), "%d", (signed int)value);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
|
||||
static string
|
||||
read_pollfd(Context &context, void *data)
|
||||
{
|
||||
nfds_t numfds = context.ReadValue<nfds_t>(context.GetSibling(1));
|
||||
if ((int64)numfds <= 0)
|
||||
return string();
|
||||
|
||||
pollfd tmp[numfds];
|
||||
int32 bytesRead;
|
||||
|
||||
status_t err = context.Reader().Read(data, &tmp, sizeof(tmp), bytesRead);
|
||||
if (err != B_OK)
|
||||
return context.FormatPointer(data);
|
||||
|
||||
int added = 0;
|
||||
|
||||
string r;
|
||||
r.reserve(16);
|
||||
|
||||
r = "[";
|
||||
|
||||
for (nfds_t i = 0; i < numfds && added < 8; i++) {
|
||||
if ((tmp[i].fd == -1 || tmp[i].revents == 0)
|
||||
&& context.GetContents(Context::OUTPUT_VALUES)) {
|
||||
continue;
|
||||
}
|
||||
if (added > 0)
|
||||
r += ", ";
|
||||
r += "{fd=" + format_signed_number(tmp[i].fd);
|
||||
if (tmp[i].fd != -1 && context.GetContents(Context::INPUT_VALUES)) {
|
||||
r += ", events=";
|
||||
int flags = 0;
|
||||
if ((tmp[i].events & POLLIN) != 0) {
|
||||
if (flags > 0)
|
||||
r += "|";
|
||||
r += "POLLIN";
|
||||
flags++;
|
||||
}
|
||||
if ((tmp[i].events & POLLOUT) != 0) {
|
||||
if (flags > 0)
|
||||
r += "|";
|
||||
r += "POLLOUT";
|
||||
flags++;
|
||||
}
|
||||
}
|
||||
if (context.GetContents(Context::OUTPUT_VALUES)) {
|
||||
r += ", revents=";
|
||||
int flags = 0;
|
||||
if ((tmp[i].revents & POLLIN) != 0) {
|
||||
if (flags > 0)
|
||||
r += "|";
|
||||
r += "POLLIN";
|
||||
flags++;
|
||||
}
|
||||
if ((tmp[i].revents & POLLOUT) != 0) {
|
||||
if (flags > 0)
|
||||
r += "|";
|
||||
r += "POLLOUT";
|
||||
flags++;
|
||||
}
|
||||
if ((tmp[i].revents & POLLERR) != 0) {
|
||||
if (flags > 0)
|
||||
r += "|";
|
||||
r += "POLLERR";
|
||||
flags++;
|
||||
}
|
||||
if ((tmp[i].revents & POLLHUP) != 0) {
|
||||
if (flags > 0)
|
||||
r += "|";
|
||||
r += "POLLHUP";
|
||||
flags++;
|
||||
}
|
||||
if ((tmp[i].revents & POLLNVAL) != 0) {
|
||||
if (flags > 0)
|
||||
r += "|";
|
||||
r += "POLLNVAL";
|
||||
flags++;
|
||||
}
|
||||
}
|
||||
added++;
|
||||
r += "}";
|
||||
}
|
||||
|
||||
if (added >= 8)
|
||||
r += " ...";
|
||||
|
||||
r += "]";
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
template<>
|
||||
string
|
||||
TypeHandlerImpl<pollfd *>::GetParameterValue(Context &context, Parameter *,
|
||||
const void *address)
|
||||
{
|
||||
void *data = *(void **)address;
|
||||
if (data != NULL && context.GetContents(Context::SIMPLE_STRUCTS))
|
||||
return read_pollfd(context, data);
|
||||
return context.FormatPointer(data);
|
||||
}
|
||||
|
||||
|
||||
template<>
|
||||
string
|
||||
TypeHandlerImpl<pollfd *>::GetReturnValue(Context &context, uint64 value)
|
||||
{
|
||||
return context.FormatPointer((void *)value);
|
||||
}
|
||||
|
||||
|
||||
template<typename Type>
|
||||
static string
|
||||
format_pointer_value(Context &context, void *address)
|
||||
@@ -769,12 +586,6 @@ class SpecializedPointerTypeHandler : public TypeHandler {
|
||||
}
|
||||
};
|
||||
|
||||
#define DEFINE_TYPE(name, type) \
|
||||
TypeHandler *create_##name##_type_handler() \
|
||||
{ \
|
||||
return new TypeHandlerImpl<type>(); \
|
||||
}
|
||||
|
||||
#define POINTER_TYPE(name, type) \
|
||||
TypeHandler *create_##name##_type_handler() \
|
||||
{ \
|
||||
@@ -782,11 +593,9 @@ class SpecializedPointerTypeHandler : public TypeHandler {
|
||||
}
|
||||
|
||||
DEFINE_TYPE(iovec_ptr, iovec *);
|
||||
DEFINE_TYPE(fdset_ptr, fd_set *);
|
||||
POINTER_TYPE(flock_ptr, flock);
|
||||
POINTER_TYPE(ifconf_ptr, ifconf);
|
||||
POINTER_TYPE(ifreq_ptr, ifreq);
|
||||
DEFINE_TYPE(pollfd_ptr, pollfd *);
|
||||
POINTER_TYPE(siginfo_t_ptr, siginfo_t);
|
||||
POINTER_TYPE(msghdr_ptr, msghdr);
|
||||
DEFINE_TYPE(sockaddr_ptr, sockaddr *);
|
||||
@@ -796,4 +605,3 @@ POINTER_TYPE(sockaddr_args_ptr, sockaddr_args);
|
||||
POINTER_TYPE(sockopt_args_ptr, sockopt_args);
|
||||
POINTER_TYPE(socket_args_ptr, socket_args);
|
||||
#endif
|
||||
|
||||
|
||||
@@ -44,9 +44,9 @@ public:
|
||||
string GetParameterValue(Context &c, Parameter *, const void *);
|
||||
string GetReturnValue(Context &, uint64 value);
|
||||
|
||||
private:
|
||||
string RenderValue(Context &, unsigned int value) const;
|
||||
|
||||
private:
|
||||
const EnumMap &fMap;
|
||||
};
|
||||
|
||||
@@ -63,7 +63,6 @@ public:
|
||||
string GetParameterValue(Context &c, Parameter *, const void *);
|
||||
string GetReturnValue(Context &, uint64 value);
|
||||
|
||||
protected:
|
||||
string RenderValue(Context &, unsigned int value) const;
|
||||
|
||||
private:
|
||||
@@ -119,6 +118,12 @@ struct TypeHandlerFactory<const char*> {
|
||||
} \
|
||||
} \
|
||||
|
||||
#define DEFINE_TYPE(name, type) \
|
||||
TypeHandler *create_##name##_type_handler() \
|
||||
{ \
|
||||
return new TypeHandlerImpl<type>(); \
|
||||
}
|
||||
|
||||
struct fd_set;
|
||||
struct flock;
|
||||
struct ifconf;
|
||||
|
||||
@@ -0,0 +1,209 @@
|
||||
/*
|
||||
* Copyright 2023-2024, Haiku Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include <OS.h>
|
||||
#include <poll.h>
|
||||
|
||||
#include "strace.h"
|
||||
#include "Syscall.h"
|
||||
#include "Context.h"
|
||||
#include "MemoryReader.h"
|
||||
#include "TypeHandler.h"
|
||||
|
||||
|
||||
// #pragma mark - enums & flags handlers
|
||||
|
||||
|
||||
struct enum_info {
|
||||
unsigned int index;
|
||||
const char *name;
|
||||
};
|
||||
|
||||
#define ENUM_INFO_ENTRY(name) \
|
||||
{ name, #name }
|
||||
|
||||
|
||||
#define FLAG_INFO_ENTRY(name) \
|
||||
{ name, #name }
|
||||
|
||||
|
||||
static const FlagsTypeHandler::FlagInfo kPollFlagInfos[] = {
|
||||
FLAG_INFO_ENTRY(POLLIN),
|
||||
FLAG_INFO_ENTRY(POLLOUT),
|
||||
FLAG_INFO_ENTRY(POLLRDBAND),
|
||||
FLAG_INFO_ENTRY(POLLWRBAND),
|
||||
FLAG_INFO_ENTRY(POLLPRI),
|
||||
|
||||
FLAG_INFO_ENTRY(POLLERR),
|
||||
FLAG_INFO_ENTRY(POLLHUP),
|
||||
FLAG_INFO_ENTRY(POLLNVAL),
|
||||
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
|
||||
static FlagsTypeHandler::FlagsList kPollFlags;
|
||||
static FlagsTypeHandler sPollFlagsHandler(kPollFlags);
|
||||
|
||||
|
||||
// #pragma mark - specialized type handlers
|
||||
|
||||
|
||||
static string
|
||||
read_fdset(Context &context, void *data)
|
||||
{
|
||||
// default FD_SETSIZE is 1024
|
||||
unsigned long tmp[1024 / (sizeof(unsigned long) * 8)];
|
||||
int32 bytesRead;
|
||||
|
||||
status_t err = context.Reader().Read(data, &tmp, sizeof(tmp), bytesRead);
|
||||
if (err != B_OK)
|
||||
return context.FormatPointer(data);
|
||||
|
||||
/* implicitly align to unsigned long lower boundary */
|
||||
int count = bytesRead / sizeof(unsigned long);
|
||||
int added = 0;
|
||||
|
||||
string r;
|
||||
r.reserve(16);
|
||||
|
||||
r = "[";
|
||||
|
||||
for (int i = 0; i < count && added < 8; i++) {
|
||||
for (int j = 0;
|
||||
j < (int)(sizeof(unsigned long) * 8) && added < 8; j++) {
|
||||
if (tmp[i] & (1UL << j)) {
|
||||
if (added > 0)
|
||||
r += " ";
|
||||
unsigned int fd = i * sizeof(unsigned long) * 8 + j;
|
||||
r += context.FormatUnsigned(fd);
|
||||
added++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (added >= 8)
|
||||
r += " ...";
|
||||
|
||||
r += "]";
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
template<>
|
||||
string
|
||||
TypeHandlerImpl<fd_set *>::GetParameterValue(Context &context, Parameter *,
|
||||
const void *address)
|
||||
{
|
||||
void *data = *(void **)address;
|
||||
if (data != NULL && context.GetContents(Context::SIMPLE_STRUCTS))
|
||||
return read_fdset(context, data);
|
||||
return context.FormatPointer(data);
|
||||
}
|
||||
|
||||
|
||||
template<>
|
||||
string
|
||||
TypeHandlerImpl<fd_set *>::GetReturnValue(Context &context, uint64 value)
|
||||
{
|
||||
return context.FormatPointer((void *)value);
|
||||
}
|
||||
|
||||
|
||||
static string
|
||||
read_pollfd(Context &context, void *data)
|
||||
{
|
||||
nfds_t numfds = context.ReadValue<nfds_t>(context.GetSibling(1));
|
||||
if ((int64)numfds <= 0)
|
||||
return string();
|
||||
|
||||
pollfd tmp[numfds];
|
||||
int32 bytesRead;
|
||||
|
||||
status_t err = context.Reader().Read(data, &tmp, sizeof(tmp), bytesRead);
|
||||
if (err != B_OK)
|
||||
return context.FormatPointer(data);
|
||||
|
||||
string r;
|
||||
r.reserve(16);
|
||||
|
||||
r = "[";
|
||||
|
||||
int added = 0;
|
||||
for (nfds_t i = 0; i < numfds && added < 8; i++) {
|
||||
if ((tmp[i].fd == -1 || tmp[i].revents == 0)
|
||||
&& context.GetContents(Context::OUTPUT_VALUES)) {
|
||||
continue;
|
||||
}
|
||||
if (added > 0)
|
||||
r += ", ";
|
||||
r += "{fd=" + context.FormatSigned(tmp[i].fd);
|
||||
if (tmp[i].fd != -1 && context.GetContents(Context::INPUT_VALUES)) {
|
||||
r += ", events=";
|
||||
r += sPollFlagsHandler.RenderValue(context, tmp[i].events);
|
||||
}
|
||||
if (context.GetContents(Context::OUTPUT_VALUES)) {
|
||||
r += ", revents=";
|
||||
r += sPollFlagsHandler.RenderValue(context, tmp[i].revents);
|
||||
}
|
||||
added++;
|
||||
r += "}";
|
||||
}
|
||||
|
||||
if (added >= 8)
|
||||
r += " ...";
|
||||
|
||||
r += "]";
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
template<>
|
||||
string
|
||||
TypeHandlerImpl<pollfd *>::GetParameterValue(Context &context, Parameter *,
|
||||
const void *address)
|
||||
{
|
||||
void *data = *(void **)address;
|
||||
if (data != NULL && context.GetContents(Context::SIMPLE_STRUCTS))
|
||||
return read_pollfd(context, data);
|
||||
return context.FormatPointer(data);
|
||||
}
|
||||
|
||||
|
||||
template<>
|
||||
string
|
||||
TypeHandlerImpl<pollfd *>::GetReturnValue(Context &context, uint64 value)
|
||||
{
|
||||
return context.FormatPointer((void *)value);
|
||||
}
|
||||
|
||||
|
||||
DEFINE_TYPE(fdset_ptr, fd_set *)
|
||||
DEFINE_TYPE(pollfd_ptr, pollfd *)
|
||||
|
||||
|
||||
// #pragma mark - patch function
|
||||
|
||||
|
||||
void
|
||||
patch_events()
|
||||
{
|
||||
for (int i = 0; kPollFlagInfos[i].name != NULL; i++)
|
||||
kPollFlags.push_back(kPollFlagInfos[i]);
|
||||
|
||||
Syscall *poll = get_syscall("_kern_poll");
|
||||
poll->ParameterAt(0)->SetInOut(true);
|
||||
|
||||
Syscall *select = get_syscall("_kern_select");
|
||||
select->ParameterAt(1)->SetInOut(true);
|
||||
select->ParameterAt(2)->SetInOut(true);
|
||||
select->ParameterAt(3)->SetInOut(true);
|
||||
|
||||
Syscall *wait = get_syscall("_kern_wait_for_child");
|
||||
wait->ParameterAt(2)->SetOut(true);
|
||||
wait->ParameterAt(3)->SetOut(true);
|
||||
}
|
||||
@@ -124,18 +124,6 @@ patch_network()
|
||||
shutdown->GetParameter("how")->SetHandler(
|
||||
new EnumTypeHandler(kShutdownHowMap));
|
||||
|
||||
Syscall *poll = get_syscall("_kern_poll");
|
||||
poll->ParameterAt(0)->SetInOut(true);
|
||||
|
||||
Syscall *select = get_syscall("_kern_select");
|
||||
select->ParameterAt(1)->SetInOut(true);
|
||||
select->ParameterAt(2)->SetInOut(true);
|
||||
select->ParameterAt(3)->SetInOut(true);
|
||||
|
||||
Syscall *wait = get_syscall("_kern_wait_for_child");
|
||||
wait->ParameterAt(2)->SetOut(true);
|
||||
wait->ParameterAt(3)->SetOut(true);
|
||||
|
||||
Syscall *createPipe = get_syscall("_kern_create_pipe");
|
||||
createPipe->ParameterAt(0)->SetOut(true);
|
||||
createPipe->ParameterAt(0)->SetCount(2);
|
||||
@@ -147,5 +135,4 @@ patch_network()
|
||||
new EnumTypeHandler(kSocketFamilyMap));
|
||||
socketPair->GetParameter("type")->SetHandler(
|
||||
new EnumTypeHandler(kSocketTypeMap));
|
||||
|
||||
}
|
||||
|
||||
@@ -230,6 +230,7 @@ patch_syscalls()
|
||||
// kernel/syscalls.h and have it parsed automatically
|
||||
|
||||
extern void patch_area();
|
||||
extern void patch_events();
|
||||
extern void patch_exec();
|
||||
extern void patch_fcntl();
|
||||
extern void patch_ioctl();
|
||||
@@ -248,6 +249,7 @@ patch_syscalls()
|
||||
}
|
||||
|
||||
patch_area();
|
||||
patch_events();
|
||||
patch_exec();
|
||||
patch_fcntl();
|
||||
patch_ioctl();
|
||||
|
||||
Reference in New Issue
Block a user