On Wed, Jul 01, 2015 at 02:52:45PM +0200, Patrik Jakobsson wrote: [...] > --- a/defs.h > +++ b/defs.h > @@ -266,6 +266,13 @@ struct tcb { > int u_error; /* Error code */ > long scno; /* System call number */ > long u_arg[MAX_ARGS]; /* System call arguments */ > + > + /* > + * Private data for the decoding functions of the syscall. TCB core does > + * _not_ handle allocation / deallocation of this data. > + */ > + void *priv_data; > + This will result to memory leaks if droptcb() is called before the syscall parser that allocated memory had a chance to deallocate it. As this data is no longer relevant after leaving trace_syscall_exiting(), I suggest to perform deallocation directly from trace_syscall_exiting. This API could be made more flexible by adding another pointer - the function to be called to deallocate memory, e.g. struct tcb { ... void *priv_data; void (*free_priv_data)(void *); ... }; ... void free_priv_data(struct tcb *tcp) { if (tcp->priv_data) { if (tcp->free_priv_data) { tcp->free_priv_data(tcp->priv_data); tcp->free_priv_data = NULL; } tcp->priv_data = NULL; } } ... droptcb(struct tcb *tcp) { ... free_priv_data(tcp); ... } ... trace_syscall_exiting(struct tcb *tcp) { ... ret: free_priv_data(tcp); ... } [...] On Wed, Jul 01, 2015 at 02:52:46PM +0200, Patrik Jakobsson wrote: > * Makefile.am: Add compilation of drm.c > * defs.h: Declarations of drm functions > * drm.c: Utility functions for drm driver detection > * io.c: Dispatch drm ioctls > * ioctl.c: Distpatch generic and driver specific ioctls This is not quite a GNU style changelog entry. Please have a look at http://www.gnu.org/prep/standards/html_node/Style-of-Change-Logs.html and examples in strace.git history. [...] > +#include "defs.h" > + > +#include <drm.h> > +#include <linux/limits.h> Please include <sys/param.h> instead of <linux/limits.h>. > +#define DRM_MAX_NAME_LEN 128 > + > +struct drm_ioctl_priv { > + char name[DRM_MAX_NAME_LEN]; > +}; > + > +inline int drm_is_priv(const unsigned int num) > +{ > + return (_IOC_NR(num) >= DRM_COMMAND_BASE && > + _IOC_NR(num) < DRM_COMMAND_END); > +} > + > +static int drm_get_driver_name(struct tcb *tcp, char *name, size_t bufsize) > +{ > + char path[PATH_MAX]; > + char link[PATH_MAX]; > + int ret; > + > + ret = getfdpath(tcp, tcp->u_arg[0], path, PATH_MAX - 1); > + if (ret < 0) > + return ret; > + > + snprintf(link, PATH_MAX, "/sys/class/drm/%s/device/driver", > + basename(path)); > + > + ret = readlink(link, path, PATH_MAX - 1); > + if (ret < 0) > + return ret; > + > + path[ret] = '\0'; > + strncpy(name, basename(path), bufsize); > + > + return 0; > +} I think this is getting too complicated. This function could just return strdup(basename(path)) or NULL in case of any error: static char * drm_get_driver_name(struct tcb *tcp, const char *name) { char path[PATH_MAX]; char link[PATH_MAX]; int ret; if (getfdpath(tcp, tcp->u_arg[0], path, PATH_MAX - 1) < 0) return NULL; if (snprintf(link, PATH_MAX, "/sys/class/drm/%s/device/driver", basename(path)) >= PATH_MAX) return NULL; ret = readlink(link, path, PATH_MAX - 1); if (ret < 0) return NULL; path[ret] = '\0'; return strdup(basename(path)); } > + > +int drm_is_driver(struct tcb *tcp, const char *name) > +{ > + struct drm_ioctl_priv *priv; > + int ret; > + > + /* > + * If no private data is allocated we are detecting the driver name for > + * the first time and must resolve it. > + */ > + if (tcp->priv_data == NULL) { > + tcp->priv_data = xcalloc(1, sizeof(struct drm_ioctl_priv)); xcalloc shouldn't be used if a potential memory allocation error is not fatal. In a parser that performs verbose syscall decoding no memory allocation error is fatal. > + priv = tcp->priv_data; > + > + ret = drm_get_driver_name(tcp, priv->name, DRM_MAX_NAME_LEN); > + if (ret) > + return 0; > + } > + > + priv = tcp->priv_data; > + > + return strncmp(name, priv->name, DRM_MAX_NAME_LEN) == 0; Then with priv_data+free_priv_data interface this would looks smth like ... if (!tcp->priv_data) { tcp->priv_data = drm_get_driver_name(tcp, name); if (tcp->priv_data) { tcp->free_priv_data = free; } else { tcp->priv_data = (void *) ""; tcp->free_priv_data = NULL; } } return !strcmp(name, (char *) tcp->priv_data); > +} > + > +int drm_decode_number(struct tcb *tcp, unsigned int arg) This is an ioctl request code, let's consistently call it "code" to distinguish from its argument. [...] > --- a/ioctl.c > +++ b/ioctl.c > @@ -182,7 +182,7 @@ hiddev_decode_number(unsigned int arg) > } > > int > -ioctl_decode_command_number(unsigned int arg) > +ioctl_decode_command_number(struct tcb *tcp, unsigned int arg) I've already changed ioctl_decode_command_number's signature: struct tcb * is already there and "arg" is now called "code". -- ldv
Attachment:
pgpzfHeweLdWW.pgp
Description: PGP signature
_______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/intel-gfx