[4/4] drm: Add decoding of DRM and KMS ioctls

Submitted by Patrik Jakobsson on June 9, 2015, 11:26 a.m.

Details

Message ID 1433849204-4125-5-git-send-email-patrik.jakobsson@linux.intel.com
State New
Headers show

Not browsing as part of any series.

Commit Message

Patrik Jakobsson June 9, 2015, 11:26 a.m.
This patch adds many of the DRM and KMS ioctls. The rest can be added as
needed.

Signed-off-by: Patrik Jakobsson <patrik.jakobsson@linux.intel.com>
---
 drm.c | 519 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 519 insertions(+)

Patch hide | download patch | download mbox

diff --git a/drm.c b/drm.c
index fa98fb7..e550c34 100644
--- a/drm.c
+++ b/drm.c
@@ -82,6 +82,468 @@  int drm_is_driver(struct tcb *tcp, const char *name)
 	return strcmp(name, drv) == 0;
 }
 
+static int drm_version(struct tcb *tcp, const unsigned int code, long arg)
+{
+	struct drm_version ver;
+	char *name, *date, *desc;
+	int ret;
+
+	if (entering(tcp) || umove(tcp, arg, &ver))
+		return 0;
+
+	name = calloc(ver.name_len + 1, 1);
+	if (!name)
+		return 0;
+	ret = umovestr(tcp, (long)ver.name, ver.name_len, name);
+	if (ret < 0)
+		goto free_name;
+
+	date = calloc(ver.date_len + 1, 1);
+	if (!date)
+		goto free_name;
+	ret = umovestr(tcp, (long)ver.date, ver.date_len, date);
+	if (ret < 0)
+		goto free_date;
+
+	desc = calloc(ver.desc_len + 1, 1);
+	if (!desc)
+		goto free_date;
+	ret = umovestr(tcp, (long)ver.desc, ver.desc_len, desc);
+	if (ret < 0)
+		goto free_desc;
+
+	tprintf(", {version_major=%d, version_minor=%d, version_patchlevel=%d, "
+		"name_len=%lu, name=%s, date_len=%lu, date=%s, "
+		"desc_len=%lu, desc=%s}",
+		ver.version_major, ver.version_minor, ver.version_patchlevel,
+		ver.name_len, name, ver.date_len, date, ver.desc_len,
+		desc);
+
+free_desc:
+	free(desc);
+free_date:
+	free(date);
+free_name:
+	free(name);
+
+	if (ret < 0)
+		return 0;
+
+	return 1;
+}
+
+static int drm_get_unique(struct tcb *tcp, const unsigned int code, long arg)
+{
+	struct drm_unique unique;
+	char *str;
+	int ret;
+
+	if (entering(tcp) || umove(tcp, arg, &unique))
+		return 0;
+
+	str = calloc(unique.unique_len + 1, 1);
+	if (!str)
+		return 0;
+	ret = umovestr(tcp, (long)unique.unique, unique.unique_len, str);
+
+	tprintf(", {unique_len=%lu, unique=%s}", unique.unique_len, str);
+
+	free(str);
+
+	if (ret < 0)
+		return 0;
+
+	return 1;
+}
+
+static int drm_get_magic(struct tcb *tcp, const unsigned int code, long arg)
+{
+	struct drm_auth auth;
+
+	if (entering(tcp) || umove(tcp, arg, &auth))
+		return 0;
+
+	tprintf(", {magic=%u}", auth.magic);
+
+	return 1;
+}
+
+static int drm_wait_vblank(struct tcb *tcp, const unsigned int code, long arg)
+{
+	union drm_wait_vblank vblank;
+
+	if (umove(tcp, arg, &vblank))
+		return 0;
+
+	if (entering(tcp)) {
+		tprintf(", {request={type=%u, sequence=%u, signal=%lu}",
+			vblank.request.type, vblank.request.sequence,
+			vblank.request.signal);
+	} else {
+		tprintf(", reply={type=%u, sequence=%u, tval_sec=%ld, tval_usec=%ld}}",
+			vblank.reply.type, vblank.reply.sequence,
+			vblank.reply.tval_sec, vblank.reply.tval_usec);
+	}
+
+	return 1;
+}
+
+static int drm_mode_get_resources(struct tcb *tcp, const unsigned int code, long arg)
+{
+	struct drm_mode_card_res res;
+
+	if (entering(tcp) || umove(tcp, arg, &res))
+		return 0;
+
+	tprintf(", {fb_id_ptr=%p, crtc_id_ptr=%p, connector_id_ptr=%p, "
+		"encoder_id_ptr=%p, count_fbs=%u, count_crtcs=%u, "
+		"count_connectors=%u, count_encoders=%u, min_width=%u, "
+		"max_width=%u, min_height=%u, max_height=%u}",
+		(void *)res.fb_id_ptr, (void *)res.crtc_id_ptr,
+		(void *)res.connector_id_ptr, (void *)res.encoder_id_ptr,
+		res.count_fbs, res.count_crtcs, res.count_connectors,
+		res.count_encoders, res.min_width, res.max_width,
+		res.min_height, res.max_height);
+
+	return 1;
+}
+
+static void drm_mode_print_modeinfo(struct drm_mode_modeinfo *info)
+{
+	tprintf("clock=%u, hdisplay=%hu, hsync_start=%hu, hsync_end=%hu, "
+		"htotal=%hu, hskew=%hu, vdisplay=%hu, vsync_start=%hu, "
+		"vsync_end=%hu, vtotal=%hu, vscan=%hu, vrefresh=%u, "
+		"flags=0x%x, type=%u, name=%s", info->clock, info->hdisplay,
+		info->hsync_start, info->hsync_end, info->htotal, info->hskew,
+		info->vdisplay, info->vsync_start, info->vsync_end,
+		info->vtotal, info->vscan, info->vrefresh, info->flags,
+		info->type, info->name);
+}
+
+static int drm_mode_get_crtc(struct tcb *tcp, const unsigned int code, long arg)
+{
+	struct drm_mode_crtc crtc;
+
+	if (entering(tcp) || umove(tcp, arg, &crtc))
+		return 0;
+
+	tprintf(", {set_connectors_ptr=%p, count_connectors=%u, crtc_id=%u, "
+		"fb_id=%u, x=%u, y=%u, gamma_size=%u, mode_valid=%u, mode={",
+		(void *)crtc.set_connectors_ptr, crtc.count_connectors,
+		crtc.crtc_id, crtc.fb_id, crtc.x, crtc.y, crtc.gamma_size,
+		crtc.mode_valid);
+
+	drm_mode_print_modeinfo(&crtc.mode);
+	tprintf("}}");
+
+	return 1;
+}
+
+static int drm_mode_set_crtc(struct tcb *tcp, const unsigned int code, long arg)
+{
+	struct drm_mode_crtc crtc;
+
+	if (entering(tcp) || umove(tcp, arg, &crtc))
+		return 0;
+
+	tprintf(", {set_connectors_ptr=%p, count_connectors=%u, crtc_id=%u, "
+		"fb_id=%u, x=%u, y=%u, gamma_size=%u, mode_valid=%u, mode={",
+		(void *)crtc.set_connectors_ptr, crtc.count_connectors,
+		crtc.crtc_id, crtc.fb_id, crtc.x, crtc.y, crtc.gamma_size,
+		crtc.mode_valid);
+
+	drm_mode_print_modeinfo(&crtc.mode);
+	tprintf("}}");
+
+	return 1;
+}
+
+static int drm_mode_cursor(struct tcb *tcp, const unsigned int code, long arg)
+{
+	struct drm_mode_cursor cursor;
+
+	if (entering(tcp) || umove(tcp, arg, &cursor))
+		return 0;
+
+	tprintf(", {flags=0x%x, crtc_id=%u, x=%d, y=%d, width=%u, height=%u, "
+		"handle=%u}", cursor.flags, cursor.crtc_id, cursor.x, cursor.y,
+		cursor.width, cursor.height, cursor.handle);
+
+	return 1;
+}
+
+static int drm_mode_cursor2(struct tcb *tcp, const unsigned int code, long arg)
+{
+	struct drm_mode_cursor2 cursor;
+
+	if (entering(tcp) || umove(tcp, arg, &cursor))
+		return 0;
+
+	tprintf(", {flags=0x%x, crtc_id=%u, x=%d, y=%d, width=%u, height=%u, "
+		"handle=%u, hot_x=%d, hot_y=%d}", cursor.flags, cursor.crtc_id,
+		cursor.x, cursor.y, cursor.width, cursor.height, cursor.handle,
+		cursor.hot_x, cursor.hot_y);
+
+	return 1;
+}
+
+static int drm_mode_get_gamma(struct tcb *tcp, const unsigned int code, long arg)
+{
+	struct drm_mode_crtc_lut lut;
+
+	if (entering(tcp) || umove(tcp, arg, &lut))
+		return 0;
+
+	/* We don't print the entire table, just the pointers */
+	tprintf(", {crtc_id=%u, gamma_size=%u, red=%p, green=%p, blue=%p}",
+		lut.crtc_id, lut.gamma_size, (void *)lut.red, (void *)lut.green,
+		(void *)lut.blue);
+
+	return 1;
+}
+
+
+static int drm_mode_set_gamma(struct tcb *tcp, const unsigned int code, long arg)
+{
+	struct drm_mode_crtc_lut lut;
+
+	if (entering(tcp) || umove(tcp, arg, &lut))
+		return 0;
+
+	/* We don't print the entire table, just the rgb pointers */
+	tprintf(", {crtc_id=%u, gamma_size=%u, red=%p, green=%p, blue=%p}",
+		lut.crtc_id, lut.gamma_size, (void *)lut.red, (void *)lut.green,
+		(void *)lut.blue);
+
+	return 1;
+}
+
+static int drm_mode_get_encoder(struct tcb *tcp, const unsigned int code, long arg)
+{
+	struct drm_mode_get_encoder enc;
+
+	if (entering(tcp) || umove(tcp, arg, &enc))
+		return 0;
+
+	/* TODO: Print name of encoder type */
+	tprintf(", {encoder_id=%u, encoder_type=%u, crtc_id=%u, "
+		"possible_crtcs=0x%x, possible_clones=0x%x}", enc.encoder_id,
+		enc.encoder_type, enc.crtc_id, enc.possible_crtcs,
+		enc.possible_clones);
+
+	return 1;
+}
+
+static int drm_mode_get_connector(struct tcb *tcp, const unsigned int code, long arg)
+{
+	struct drm_mode_get_connector con;
+
+	if (entering(tcp) || umove(tcp, arg, &con))
+		return 0;
+
+	/* We could be very verbose here but keep is simple for now */
+	tprintf(", {encoders_ptr=%p, modes_ptr=%p, props_ptr=%p, "
+		"prop_values_ptr=%p, count_modes=%u, count_props=%u, "
+		"count_encoders=%u, encoder_id=%u, connector_id=%u, "
+		"connector_type=%u, connector_type_id=%u, connection=%u, "
+		"mm_width=%u, mm_height=%u, subpixel=%u}",
+		(void *)con.encoders_ptr, (void *)con.modes_ptr,
+		(void *)con.props_ptr, (void *)con.prop_values_ptr,
+		con.count_modes, con.count_props, con.count_encoders,
+		con.encoder_id, con.connector_id, con.connector_type,
+		con.connector_type_id, con.connection, con.mm_width,
+		con.mm_height, con.subpixel);
+
+	return 1;
+}
+
+static int drm_mode_attachmode(struct tcb *tcp, const unsigned int code, long arg)
+{
+	struct drm_mode_mode_cmd cmd;
+
+	if (entering(tcp) || umove(tcp, arg, &cmd))
+		return 0;
+
+	tprintf(", {connector_id=%u, mode={", cmd.connector_id);
+	drm_mode_print_modeinfo(&cmd.mode);
+	tprintf("}");
+
+	return 1;
+}
+
+static int drm_mode_detachmode(struct tcb *tcp, const unsigned int code, long arg)
+{
+	struct drm_mode_mode_cmd cmd;
+
+	if (entering(tcp) || umove(tcp, arg, &cmd))
+		return 0;
+
+	tprintf(", {connector_id=%u, mode={", cmd.connector_id);
+	drm_mode_print_modeinfo(&cmd.mode);
+	tprintf("}");
+
+	return 1;
+}
+
+static int drm_mode_get_property(struct tcb *tcp, const unsigned int code, long arg)
+{
+	struct drm_mode_get_property prop;
+
+	if (entering(tcp) || umove(tcp, arg, &prop))
+		return 0;
+
+	tprintf(", {values_ptr=%p, enum_blob_ptr=%p, prop_id=%u, flags=0x%x, "
+		"name=%s, count_values=%u, count_enum_blobs=%u}",
+		(void *)prop.values_ptr, (void *)prop.enum_blob_ptr,
+		prop.prop_id, prop.flags, prop.name, prop.count_values,
+		prop.count_enum_blobs);
+
+	return 1;
+}
+
+static int drm_mode_set_property(struct tcb *tcp, const unsigned int code, long arg)
+{
+	struct drm_mode_connector_set_property prop;
+
+	if (entering(tcp) || umove(tcp, arg, &prop))
+		return 0;
+
+	tprintf(", {value=%Lu, prop_id=%u, connector_id=%u}", prop.value,
+		prop.prop_id, prop.connector_id);
+
+	return 1;
+}
+
+static int drm_mode_get_prop_blob(struct tcb *tcp, const unsigned int code, long arg)
+{
+	struct drm_mode_get_blob blob;
+
+	if (entering(tcp) || umove(tcp, arg, &blob))
+		return 0;
+
+	tprintf(", {blob_id=%u, length=%u, data=%p}", blob.blob_id, blob.length,
+		(void *)blob.data);
+
+	return 1;
+}
+
+static int drm_mode_add_fb(struct tcb *tcp, const unsigned int code, long arg)
+{
+	struct drm_mode_fb_cmd cmd;
+
+	if (entering(tcp) || umove(tcp, arg, &cmd))
+		return 0;
+
+	tprintf(", {fb_id=%u, width=%u, height=%u, pitch=%u, bpp=%u, depth=%u, "
+		"handle=%u}", cmd.fb_id, cmd.width, cmd.height, cmd.pitch,
+		cmd.bpp, cmd.depth, cmd.handle);
+
+	return 1;
+}
+
+static int drm_mode_get_fb(struct tcb *tcp, const unsigned int code, long arg)
+{
+	struct drm_mode_fb_cmd cmd;
+
+	if (entering(tcp) || umove(tcp, arg, &cmd))
+		return 0;
+
+	tprintf(", {fb_id=%u, width=%u, height=%u, pitch=%u, bpp=%u, depth=%u, "
+		"handle=%u}", cmd.fb_id, cmd.width, cmd.height, cmd.pitch,
+		cmd.bpp, cmd.depth, cmd.handle);
+
+	return 1;
+}
+
+static int drm_mode_rm_fb(struct tcb *tcp, const unsigned int code, long arg)
+{
+	unsigned int handle;
+
+	if (entering(tcp) || umove(tcp, arg, &handle))
+		return 0;
+
+	tprintf(", %u", handle);
+
+	return 1;
+}
+
+static int drm_mode_page_flip(struct tcb *tcp, const unsigned int code, long arg)
+{
+	struct drm_mode_crtc_page_flip flip;
+
+	if (entering(tcp) || umove(tcp, arg, &flip))
+		return 0;
+
+	tprintf(", {crtc_id=%u, fb_id=%u, flags=0x%x, user_data=0x%Lx}",
+		flip.crtc_id, flip.fb_id, flip.flags, flip.user_data);
+
+	return 1;
+}
+
+static int drm_mode_dirty_fb(struct tcb *tcp, const unsigned int code, long arg)
+{
+	struct drm_mode_fb_dirty_cmd cmd;
+
+	if (entering(tcp) || umove(tcp, arg, &cmd))
+		return 0;
+
+	tprintf(", {fb_id=%u, flags=0x%x, color=0x%x, num_clips=%u, "
+		"clips_ptr=%p}", cmd.fb_id, cmd.flags, cmd.color, cmd.num_clips,
+		(void *)cmd.clips_ptr);
+
+	return 1;
+}
+
+static int drm_mode_create_dumb(struct tcb *tcp, const unsigned int code, long arg)
+{
+	struct drm_mode_create_dumb dumb;
+
+	if (entering(tcp) || umove(tcp, arg, &dumb))
+		return 0;
+
+	tprintf(", {height=%u, width=%u, bpp=%u, flags=0x%x, handle=%u, "
+		"pitch=%u, size=%Lu}", dumb.height, dumb.width, dumb.bpp,
+		dumb.flags, dumb.handle, dumb.pitch, dumb.size);
+
+	return 1;
+}
+
+static int drm_mode_map_dumb(struct tcb *tcp, const unsigned int code, long arg)
+{
+	struct drm_mode_map_dumb dumb;
+
+	if (entering(tcp) || umove(tcp, arg, &dumb))
+		return 0;
+
+	tprintf(", {handle=%u, offset=%Lu}", dumb.handle, dumb.offset);
+
+	return 1;
+}
+
+static int drm_mode_destroy_dumb(struct tcb *tcp, const unsigned int code, long arg)
+{
+	struct drm_mode_destroy_dumb dumb;
+
+	if (entering(tcp) || umove(tcp, arg, &dumb))
+		return 0;
+
+	tprintf(", {handle=%u}", dumb.handle);
+
+	return 1;
+}
+
+static int drm_gem_close(struct tcb *tcp, const unsigned int code, long arg)
+{
+	struct drm_gem_close close;
+
+	if (entering(tcp) || umove(tcp, arg, &close))
+		return 0;
+
+	tprintf(", {handle=%u}", close.handle);
+
+	return 1;
+}
+
 int drm_ioctl(struct tcb *tcp, const unsigned int code, long arg)
 {
 	/* Check for device specific ioctls */
@@ -90,5 +552,62 @@  int drm_ioctl(struct tcb *tcp, const unsigned int code, long arg)
 			return drm_i915_ioctl(tcp, code, arg);
 	}
 
+	switch (code) {
+	case DRM_IOCTL_VERSION:
+		return drm_version(tcp, code, arg);
+	case DRM_IOCTL_GET_UNIQUE:
+		return drm_get_unique(tcp, code, arg);
+	case DRM_IOCTL_GET_MAGIC:
+		return drm_get_magic(tcp, code, arg);
+	case DRM_IOCTL_WAIT_VBLANK:
+		return drm_wait_vblank(tcp, code, arg);
+	case DRM_IOCTL_MODE_GETRESOURCES:
+		return drm_mode_get_resources(tcp, code, arg);
+	case DRM_IOCTL_MODE_GETCRTC:
+		return drm_mode_get_crtc(tcp, code, arg);
+	case DRM_IOCTL_MODE_SETCRTC:
+		return drm_mode_set_crtc(tcp, code, arg);
+	case DRM_IOCTL_MODE_CURSOR:
+		return drm_mode_cursor(tcp, code, arg);
+	case DRM_IOCTL_MODE_CURSOR2:
+		return drm_mode_cursor2(tcp, code, arg);
+	case DRM_IOCTL_MODE_GETGAMMA:
+		return drm_mode_get_gamma(tcp, code, arg);
+	case DRM_IOCTL_MODE_SETGAMMA:
+		return drm_mode_set_gamma(tcp, code, arg);
+	case DRM_IOCTL_MODE_GETENCODER:
+		return drm_mode_get_encoder(tcp, code, arg);
+	case DRM_IOCTL_MODE_GETCONNECTOR:
+		return drm_mode_get_connector(tcp, code, arg);
+	case DRM_IOCTL_MODE_ATTACHMODE:
+		return drm_mode_attachmode(tcp, code, arg);
+	case DRM_IOCTL_MODE_DETACHMODE:
+		return drm_mode_detachmode(tcp, code, arg);
+	case DRM_IOCTL_MODE_GETPROPERTY:
+		return drm_mode_get_property(tcp, code, arg);
+	case DRM_IOCTL_MODE_SETPROPERTY:
+		return drm_mode_set_property(tcp, code, arg);
+	case DRM_IOCTL_MODE_GETPROPBLOB:
+		return drm_mode_get_prop_blob(tcp, code, arg);
+	case DRM_IOCTL_MODE_GETFB:
+		return drm_mode_get_fb(tcp, code, arg);
+	case DRM_IOCTL_MODE_ADDFB:
+		return drm_mode_add_fb(tcp, code, arg);
+	case DRM_IOCTL_MODE_RMFB:
+		return drm_mode_rm_fb(tcp, code, arg);
+	case DRM_IOCTL_MODE_PAGE_FLIP:
+		return drm_mode_page_flip(tcp, code, arg);
+	case DRM_IOCTL_MODE_DIRTYFB:
+		return drm_mode_dirty_fb(tcp, code, arg);
+	case DRM_IOCTL_MODE_CREATE_DUMB:
+		return drm_mode_create_dumb(tcp, code, arg);
+	case DRM_IOCTL_MODE_MAP_DUMB:
+		return drm_mode_map_dumb(tcp, code, arg);
+	case DRM_IOCTL_MODE_DESTROY_DUMB:
+		return drm_mode_destroy_dumb(tcp, code, arg);
+	case DRM_IOCTL_GEM_CLOSE:
+		return drm_gem_close(tcp, code, arg);
+	}
+
 	return 0;
 }

Comments

On Tue,  9 Jun 2015 13:26:44 +0200
Patrik Jakobsson <patrik.jakobsson@linux.intel.com> wrote:

> This patch adds many of the DRM and KMS ioctls. The rest can be added as
> needed.
> 
> Signed-off-by: Patrik Jakobsson <patrik.jakobsson@linux.intel.com>
> ---
>  drm.c | 519 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 519 insertions(+)
> 
> diff --git a/drm.c b/drm.c
> index fa98fb7..e550c34 100644
> --- a/drm.c
> +++ b/drm.c
> @@ -82,6 +82,468 @@ int drm_is_driver(struct tcb *tcp, const char *name)
>  	return strcmp(name, drv) == 0;
>  }
>  
> +static int drm_version(struct tcb *tcp, const unsigned int code, long arg)
> +{
> +	struct drm_version ver;
> +	char *name, *date, *desc;
> +	int ret;
> +
> +	if (entering(tcp) || umove(tcp, arg, &ver))
> +		return 0;
> +
> +	name = calloc(ver.name_len + 1, 1);

We have some wrappers for that now, you can call xcalloc(), but it will
die if this does not work. Your version have the advantage of not kill
strace, and just not decode the argument.

> +	if (!name)
> +		return 0;
> +	ret = umovestr(tcp, (long)ver.name, ver.name_len, name);
> +	if (ret < 0)
> +		goto free_name;
> +
> +	date = calloc(ver.date_len + 1, 1);
> +	if (!date)
> +		goto free_name;
> +	ret = umovestr(tcp, (long)ver.date, ver.date_len, date);
> +	if (ret < 0)
> +		goto free_date;
> +
> +	desc = calloc(ver.desc_len + 1, 1);
> +	if (!desc)
> +		goto free_date;
> +	ret = umovestr(tcp, (long)ver.desc, ver.desc_len, desc);
> +	if (ret < 0)
> +		goto free_desc;
> +
> +	tprintf(", {version_major=%d, version_minor=%d, version_patchlevel=%d, "
> +		"name_len=%lu, name=%s, date_len=%lu, date=%s, "
> +		"desc_len=%lu, desc=%s}",
> +		ver.version_major, ver.version_minor, ver.version_patchlevel,
> +		ver.name_len, name, ver.date_len, date, ver.desc_len,
> +		desc);
> +
> +free_desc:
> +	free(desc);
> +free_date:
> +	free(date);
> +free_name:
> +	free(name);
> +
> +	if (ret < 0)
> +		return 0;
> +
> +	return 1;
> +}
> +
> +static int drm_get_unique(struct tcb *tcp, const unsigned int code, long arg)
> +{
> +	struct drm_unique unique;
> +	char *str;
> +	int ret;
> +
> +	if (entering(tcp) || umove(tcp, arg, &unique))
> +		return 0;
> +
> +	str = calloc(unique.unique_len + 1, 1);
> +	if (!str)
> +		return 0;
> +	ret = umovestr(tcp, (long)unique.unique, unique.unique_len, str);
> +

There is a check missing here

> +	tprintf(", {unique_len=%lu, unique=%s}", unique.unique_len, str);
> +
> +	free(str);
> +
> +	if (ret < 0)
> +		return 0;
> +
> +	return 1;
> +}
> +
> +static int drm_get_magic(struct tcb *tcp, const unsigned int code, long arg)
> +{
> +	struct drm_auth auth;
> +
> +	if (entering(tcp) || umove(tcp, arg, &auth))
> +		return 0;
> +
> +	tprintf(", {magic=%u}", auth.magic);
> +
> +	return 1;
> +}
> +
> +static int drm_wait_vblank(struct tcb *tcp, const unsigned int code, long arg)
> +{
> +	union drm_wait_vblank vblank;
> +
> +	if (umove(tcp, arg, &vblank))
> +		return 0;
> +
> +	if (entering(tcp)) {
> +		tprintf(", {request={type=%u, sequence=%u, signal=%lu}",
> +			vblank.request.type, vblank.request.sequence,
> +			vblank.request.signal);
> +	} else {
> +		tprintf(", reply={type=%u, sequence=%u, tval_sec=%ld, tval_usec=%ld}}",
> +			vblank.reply.type, vblank.reply.sequence,
> +			vblank.reply.tval_sec, vblank.reply.tval_usec);
> +	}
> +
> +	return 1;
> +}
> +
> +static int drm_mode_get_resources(struct tcb *tcp, const unsigned int code, long arg)
> +{
> +	struct drm_mode_card_res res;
> +
> +	if (entering(tcp) || umove(tcp, arg, &res))
> +		return 0;
> +
> +	tprintf(", {fb_id_ptr=%p, crtc_id_ptr=%p, connector_id_ptr=%p, "
> +		"encoder_id_ptr=%p, count_fbs=%u, count_crtcs=%u, "
> +		"count_connectors=%u, count_encoders=%u, min_width=%u, "
> +		"max_width=%u, min_height=%u, max_height=%u}",
> +		(void *)res.fb_id_ptr, (void *)res.crtc_id_ptr,
> +		(void *)res.connector_id_ptr, (void *)res.encoder_id_ptr,
> +		res.count_fbs, res.count_crtcs, res.count_connectors,
> +		res.count_encoders, res.min_width, res.max_width,
> +		res.min_height, res.max_height);
> +
> +	return 1;
> +}
> +
> +static void drm_mode_print_modeinfo(struct drm_mode_modeinfo *info)
> +{
> +	tprintf("clock=%u, hdisplay=%hu, hsync_start=%hu, hsync_end=%hu, "
> +		"htotal=%hu, hskew=%hu, vdisplay=%hu, vsync_start=%hu, "
> +		"vsync_end=%hu, vtotal=%hu, vscan=%hu, vrefresh=%u, "
> +		"flags=0x%x, type=%u, name=%s", info->clock, info->hdisplay,
> +		info->hsync_start, info->hsync_end, info->htotal, info->hskew,
> +		info->vdisplay, info->vsync_start, info->vsync_end,
> +		info->vtotal, info->vscan, info->vrefresh, info->flags,
> +		info->type, info->name);
> +}
> +
> +static int drm_mode_get_crtc(struct tcb *tcp, const unsigned int code, long arg)
> +{
> +	struct drm_mode_crtc crtc;
> +
> +	if (entering(tcp) || umove(tcp, arg, &crtc))
> +		return 0;
> +
> +	tprintf(", {set_connectors_ptr=%p, count_connectors=%u, crtc_id=%u, "
> +		"fb_id=%u, x=%u, y=%u, gamma_size=%u, mode_valid=%u, mode={",
> +		(void *)crtc.set_connectors_ptr, crtc.count_connectors,
> +		crtc.crtc_id, crtc.fb_id, crtc.x, crtc.y, crtc.gamma_size,
> +		crtc.mode_valid);
> +
> +	drm_mode_print_modeinfo(&crtc.mode);
> +	tprintf("}}");
> +
> +	return 1;
> +}
> +
> +static int drm_mode_set_crtc(struct tcb *tcp, const unsigned int code, long arg)
> +{
> +	struct drm_mode_crtc crtc;
> +
> +	if (entering(tcp) || umove(tcp, arg, &crtc))
> +		return 0;
> +
> +	tprintf(", {set_connectors_ptr=%p, count_connectors=%u, crtc_id=%u, "
> +		"fb_id=%u, x=%u, y=%u, gamma_size=%u, mode_valid=%u, mode={",
> +		(void *)crtc.set_connectors_ptr, crtc.count_connectors,
> +		crtc.crtc_id, crtc.fb_id, crtc.x, crtc.y, crtc.gamma_size,
> +		crtc.mode_valid);
> +
> +	drm_mode_print_modeinfo(&crtc.mode);
> +	tprintf("}}");
> +
> +	return 1;
> +}
> +
> +static int drm_mode_cursor(struct tcb *tcp, const unsigned int code, long arg)
> +{
> +	struct drm_mode_cursor cursor;
> +
> +	if (entering(tcp) || umove(tcp, arg, &cursor))
> +		return 0;
> +
> +	tprintf(", {flags=0x%x, crtc_id=%u, x=%d, y=%d, width=%u, height=%u, "
> +		"handle=%u}", cursor.flags, cursor.crtc_id, cursor.x, cursor.y,
> +		cursor.width, cursor.height, cursor.handle);
> +
> +	return 1;
> +}
> +
> +static int drm_mode_cursor2(struct tcb *tcp, const unsigned int code, long arg)
> +{
> +	struct drm_mode_cursor2 cursor;
> +
> +	if (entering(tcp) || umove(tcp, arg, &cursor))
> +		return 0;
> +
> +	tprintf(", {flags=0x%x, crtc_id=%u, x=%d, y=%d, width=%u, height=%u, "
> +		"handle=%u, hot_x=%d, hot_y=%d}", cursor.flags, cursor.crtc_id,
> +		cursor.x, cursor.y, cursor.width, cursor.height, cursor.handle,
> +		cursor.hot_x, cursor.hot_y);
> +
> +	return 1;
> +}
> +
> +static int drm_mode_get_gamma(struct tcb *tcp, const unsigned int code, long arg)
> +{
> +	struct drm_mode_crtc_lut lut;
> +
> +	if (entering(tcp) || umove(tcp, arg, &lut))
> +		return 0;
> +
> +	/* We don't print the entire table, just the pointers */
> +	tprintf(", {crtc_id=%u, gamma_size=%u, red=%p, green=%p, blue=%p}",
> +		lut.crtc_id, lut.gamma_size, (void *)lut.red, (void *)lut.green,
> +		(void *)lut.blue);
> +
> +	return 1;
> +}
> +
> +
> +static int drm_mode_set_gamma(struct tcb *tcp, const unsigned int code, long arg)
> +{
> +	struct drm_mode_crtc_lut lut;
> +
> +	if (entering(tcp) || umove(tcp, arg, &lut))
> +		return 0;
> +
> +	/* We don't print the entire table, just the rgb pointers */
> +	tprintf(", {crtc_id=%u, gamma_size=%u, red=%p, green=%p, blue=%p}",
> +		lut.crtc_id, lut.gamma_size, (void *)lut.red, (void *)lut.green,
> +		(void *)lut.blue);
> +
> +	return 1;
> +}
> +
> +static int drm_mode_get_encoder(struct tcb *tcp, const unsigned int code, long arg)
> +{
> +	struct drm_mode_get_encoder enc;
> +
> +	if (entering(tcp) || umove(tcp, arg, &enc))
> +		return 0;
> +
> +	/* TODO: Print name of encoder type */
> +	tprintf(", {encoder_id=%u, encoder_type=%u, crtc_id=%u, "
> +		"possible_crtcs=0x%x, possible_clones=0x%x}", enc.encoder_id,
> +		enc.encoder_type, enc.crtc_id, enc.possible_crtcs,
> +		enc.possible_clones);
> +
> +	return 1;
> +}
> +
> +static int drm_mode_get_connector(struct tcb *tcp, const unsigned int code, long arg)
> +{
> +	struct drm_mode_get_connector con;
> +
> +	if (entering(tcp) || umove(tcp, arg, &con))
> +		return 0;
> +
> +	/* We could be very verbose here but keep is simple for now */
> +	tprintf(", {encoders_ptr=%p, modes_ptr=%p, props_ptr=%p, "
> +		"prop_values_ptr=%p, count_modes=%u, count_props=%u, "
> +		"count_encoders=%u, encoder_id=%u, connector_id=%u, "
> +		"connector_type=%u, connector_type_id=%u, connection=%u, "
> +		"mm_width=%u, mm_height=%u, subpixel=%u}",
> +		(void *)con.encoders_ptr, (void *)con.modes_ptr,
> +		(void *)con.props_ptr, (void *)con.prop_values_ptr,
> +		con.count_modes, con.count_props, con.count_encoders,
> +		con.encoder_id, con.connector_id, con.connector_type,
> +		con.connector_type_id, con.connection, con.mm_width,
> +		con.mm_height, con.subpixel);
> +
> +	return 1;
> +}
> +
> +static int drm_mode_attachmode(struct tcb *tcp, const unsigned int code, long arg)
> +{
> +	struct drm_mode_mode_cmd cmd;
> +
> +	if (entering(tcp) || umove(tcp, arg, &cmd))
> +		return 0;
> +
> +	tprintf(", {connector_id=%u, mode={", cmd.connector_id);
> +	drm_mode_print_modeinfo(&cmd.mode);
> +	tprintf("}");
> +
> +	return 1;
> +}
> +
> +static int drm_mode_detachmode(struct tcb *tcp, const unsigned int code, long arg)
> +{
> +	struct drm_mode_mode_cmd cmd;
> +
> +	if (entering(tcp) || umove(tcp, arg, &cmd))
> +		return 0;
> +
> +	tprintf(", {connector_id=%u, mode={", cmd.connector_id);
> +	drm_mode_print_modeinfo(&cmd.mode);
> +	tprintf("}");
> +
> +	return 1;
> +}
> +
> +static int drm_mode_get_property(struct tcb *tcp, const unsigned int code, long arg)
> +{
> +	struct drm_mode_get_property prop;
> +
> +	if (entering(tcp) || umove(tcp, arg, &prop))
> +		return 0;
> +
> +	tprintf(", {values_ptr=%p, enum_blob_ptr=%p, prop_id=%u, flags=0x%x, "
> +		"name=%s, count_values=%u, count_enum_blobs=%u}",
> +		(void *)prop.values_ptr, (void *)prop.enum_blob_ptr,
> +		prop.prop_id, prop.flags, prop.name, prop.count_values,
> +		prop.count_enum_blobs);
> +
> +	return 1;
> +}
> +
> +static int drm_mode_set_property(struct tcb *tcp, const unsigned int code, long arg)
> +{
> +	struct drm_mode_connector_set_property prop;
> +
> +	if (entering(tcp) || umove(tcp, arg, &prop))
> +		return 0;
> +
> +	tprintf(", {value=%Lu, prop_id=%u, connector_id=%u}", prop.value,
> +		prop.prop_id, prop.connector_id);
> +
> +	return 1;
> +}
> +
> +static int drm_mode_get_prop_blob(struct tcb *tcp, const unsigned int code, long arg)
> +{
> +	struct drm_mode_get_blob blob;
> +
> +	if (entering(tcp) || umove(tcp, arg, &blob))
> +		return 0;
> +
> +	tprintf(", {blob_id=%u, length=%u, data=%p}", blob.blob_id, blob.length,
> +		(void *)blob.data);
> +
> +	return 1;
> +}
> +
> +static int drm_mode_add_fb(struct tcb *tcp, const unsigned int code, long arg)
> +{
> +	struct drm_mode_fb_cmd cmd;
> +
> +	if (entering(tcp) || umove(tcp, arg, &cmd))
> +		return 0;
> +
> +	tprintf(", {fb_id=%u, width=%u, height=%u, pitch=%u, bpp=%u, depth=%u, "
> +		"handle=%u}", cmd.fb_id, cmd.width, cmd.height, cmd.pitch,
> +		cmd.bpp, cmd.depth, cmd.handle);
> +
> +	return 1;
> +}
> +
> +static int drm_mode_get_fb(struct tcb *tcp, const unsigned int code, long arg)
> +{
> +	struct drm_mode_fb_cmd cmd;
> +
> +	if (entering(tcp) || umove(tcp, arg, &cmd))
> +		return 0;
> +
> +	tprintf(", {fb_id=%u, width=%u, height=%u, pitch=%u, bpp=%u, depth=%u, "
> +		"handle=%u}", cmd.fb_id, cmd.width, cmd.height, cmd.pitch,
> +		cmd.bpp, cmd.depth, cmd.handle);
> +
> +	return 1;
> +}
> +
> +static int drm_mode_rm_fb(struct tcb *tcp, const unsigned int code, long arg)
> +{
> +	unsigned int handle;
> +
> +	if (entering(tcp) || umove(tcp, arg, &handle))
> +		return 0;
> +
> +	tprintf(", %u", handle);
> +
> +	return 1;
> +}
> +
> +static int drm_mode_page_flip(struct tcb *tcp, const unsigned int code, long arg)
> +{
> +	struct drm_mode_crtc_page_flip flip;
> +
> +	if (entering(tcp) || umove(tcp, arg, &flip))
> +		return 0;
> +
> +	tprintf(", {crtc_id=%u, fb_id=%u, flags=0x%x, user_data=0x%Lx}",
> +		flip.crtc_id, flip.fb_id, flip.flags, flip.user_data);
> +
> +	return 1;
> +}
> +
> +static int drm_mode_dirty_fb(struct tcb *tcp, const unsigned int code, long arg)
> +{
> +	struct drm_mode_fb_dirty_cmd cmd;
> +
> +	if (entering(tcp) || umove(tcp, arg, &cmd))
> +		return 0;
> +
> +	tprintf(", {fb_id=%u, flags=0x%x, color=0x%x, num_clips=%u, "
> +		"clips_ptr=%p}", cmd.fb_id, cmd.flags, cmd.color, cmd.num_clips,
> +		(void *)cmd.clips_ptr);
> +
> +	return 1;
> +}
> +
> +static int drm_mode_create_dumb(struct tcb *tcp, const unsigned int code, long arg)
> +{
> +	struct drm_mode_create_dumb dumb;
> +
> +	if (entering(tcp) || umove(tcp, arg, &dumb))
> +		return 0;
> +
> +	tprintf(", {height=%u, width=%u, bpp=%u, flags=0x%x, handle=%u, "
> +		"pitch=%u, size=%Lu}", dumb.height, dumb.width, dumb.bpp,
> +		dumb.flags, dumb.handle, dumb.pitch, dumb.size);
> +
> +	return 1;
> +}
> +
> +static int drm_mode_map_dumb(struct tcb *tcp, const unsigned int code, long arg)
> +{
> +	struct drm_mode_map_dumb dumb;
> +
> +	if (entering(tcp) || umove(tcp, arg, &dumb))
> +		return 0;
> +
> +	tprintf(", {handle=%u, offset=%Lu}", dumb.handle, dumb.offset);
> +
> +	return 1;
> +}
> +
> +static int drm_mode_destroy_dumb(struct tcb *tcp, const unsigned int code, long arg)
> +{
> +	struct drm_mode_destroy_dumb dumb;
> +
> +	if (entering(tcp) || umove(tcp, arg, &dumb))
> +		return 0;
> +
> +	tprintf(", {handle=%u}", dumb.handle);
> +
> +	return 1;
> +}
> +
> +static int drm_gem_close(struct tcb *tcp, const unsigned int code, long arg)
> +{
> +	struct drm_gem_close close;
> +
> +	if (entering(tcp) || umove(tcp, arg, &close))
> +		return 0;
> +
> +	tprintf(", {handle=%u}", close.handle);
> +
> +	return 1;
> +}
> +
>  int drm_ioctl(struct tcb *tcp, const unsigned int code, long arg)
>  {
>  	/* Check for device specific ioctls */
> @@ -90,5 +552,62 @@ int drm_ioctl(struct tcb *tcp, const unsigned int code, long arg)
>  			return drm_i915_ioctl(tcp, code, arg);
>  	}
>  
> +	switch (code) {
> +	case DRM_IOCTL_VERSION:
> +		return drm_version(tcp, code, arg);
> +	case DRM_IOCTL_GET_UNIQUE:
> +		return drm_get_unique(tcp, code, arg);
> +	case DRM_IOCTL_GET_MAGIC:
> +		return drm_get_magic(tcp, code, arg);
> +	case DRM_IOCTL_WAIT_VBLANK:
> +		return drm_wait_vblank(tcp, code, arg);
> +	case DRM_IOCTL_MODE_GETRESOURCES:
> +		return drm_mode_get_resources(tcp, code, arg);
> +	case DRM_IOCTL_MODE_GETCRTC:
> +		return drm_mode_get_crtc(tcp, code, arg);
> +	case DRM_IOCTL_MODE_SETCRTC:
> +		return drm_mode_set_crtc(tcp, code, arg);
> +	case DRM_IOCTL_MODE_CURSOR:
> +		return drm_mode_cursor(tcp, code, arg);
> +	case DRM_IOCTL_MODE_CURSOR2:
> +		return drm_mode_cursor2(tcp, code, arg);
> +	case DRM_IOCTL_MODE_GETGAMMA:
> +		return drm_mode_get_gamma(tcp, code, arg);
> +	case DRM_IOCTL_MODE_SETGAMMA:
> +		return drm_mode_set_gamma(tcp, code, arg);
> +	case DRM_IOCTL_MODE_GETENCODER:
> +		return drm_mode_get_encoder(tcp, code, arg);
> +	case DRM_IOCTL_MODE_GETCONNECTOR:
> +		return drm_mode_get_connector(tcp, code, arg);
> +	case DRM_IOCTL_MODE_ATTACHMODE:
> +		return drm_mode_attachmode(tcp, code, arg);
> +	case DRM_IOCTL_MODE_DETACHMODE:
> +		return drm_mode_detachmode(tcp, code, arg);
> +	case DRM_IOCTL_MODE_GETPROPERTY:
> +		return drm_mode_get_property(tcp, code, arg);
> +	case DRM_IOCTL_MODE_SETPROPERTY:
> +		return drm_mode_set_property(tcp, code, arg);
> +	case DRM_IOCTL_MODE_GETPROPBLOB:
> +		return drm_mode_get_prop_blob(tcp, code, arg);
> +	case DRM_IOCTL_MODE_GETFB:
> +		return drm_mode_get_fb(tcp, code, arg);
> +	case DRM_IOCTL_MODE_ADDFB:
> +		return drm_mode_add_fb(tcp, code, arg);
> +	case DRM_IOCTL_MODE_RMFB:
> +		return drm_mode_rm_fb(tcp, code, arg);
> +	case DRM_IOCTL_MODE_PAGE_FLIP:
> +		return drm_mode_page_flip(tcp, code, arg);
> +	case DRM_IOCTL_MODE_DIRTYFB:
> +		return drm_mode_dirty_fb(tcp, code, arg);
> +	case DRM_IOCTL_MODE_CREATE_DUMB:
> +		return drm_mode_create_dumb(tcp, code, arg);
> +	case DRM_IOCTL_MODE_MAP_DUMB:
> +		return drm_mode_map_dumb(tcp, code, arg);
> +	case DRM_IOCTL_MODE_DESTROY_DUMB:
> +		return drm_mode_destroy_dumb(tcp, code, arg);
> +	case DRM_IOCTL_GEM_CLOSE:
> +		return drm_gem_close(tcp, code, arg);
> +	}
> +
>  	return 0;
>  }
On Tue, Jun 09, 2015 at 03:51:08PM +0200, Gabriel Laskar wrote:
> On Tue,  9 Jun 2015 13:26:44 +0200
> Patrik Jakobsson <patrik.jakobsson@linux.intel.com> wrote:
> 
> > This patch adds many of the DRM and KMS ioctls. The rest can be added as
> > needed.
> > 
> > Signed-off-by: Patrik Jakobsson <patrik.jakobsson@linux.intel.com>
> > ---
> >  drm.c | 519 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> >  1 file changed, 519 insertions(+)
> > 
> > diff --git a/drm.c b/drm.c
> > index fa98fb7..e550c34 100644
> > --- a/drm.c
> > +++ b/drm.c
> > @@ -82,6 +82,468 @@ int drm_is_driver(struct tcb *tcp, const char *name)
> >  	return strcmp(name, drv) == 0;
> >  }
> >  
> > +static int drm_version(struct tcb *tcp, const unsigned int code, long arg)
> > +{
> > +	struct drm_version ver;
> > +	char *name, *date, *desc;
> > +	int ret;
> > +
> > +	if (entering(tcp) || umove(tcp, arg, &ver))
> > +		return 0;
> > +
> > +	name = calloc(ver.name_len + 1, 1);
> 
> We have some wrappers for that now, you can call xcalloc(), but it will
> die if this does not work. Your version have the advantage of not kill
> strace, and just not decode the argument.
> 

If ok I'll keep it as calloc? As you say, dying here is not really neccessary.

> > +	if (!name)
> > +		return 0;
> > +	ret = umovestr(tcp, (long)ver.name, ver.name_len, name);
> > +	if (ret < 0)
> > +		goto free_name;
> > +
> > +	date = calloc(ver.date_len + 1, 1);
> > +	if (!date)
> > +		goto free_name;
> > +	ret = umovestr(tcp, (long)ver.date, ver.date_len, date);
> > +	if (ret < 0)
> > +		goto free_date;
> > +
> > +	desc = calloc(ver.desc_len + 1, 1);
> > +	if (!desc)
> > +		goto free_date;
> > +	ret = umovestr(tcp, (long)ver.desc, ver.desc_len, desc);
> > +	if (ret < 0)
> > +		goto free_desc;
> > +
> > +	tprintf(", {version_major=%d, version_minor=%d, version_patchlevel=%d, "
> > +		"name_len=%lu, name=%s, date_len=%lu, date=%s, "
> > +		"desc_len=%lu, desc=%s}",
> > +		ver.version_major, ver.version_minor, ver.version_patchlevel,
> > +		ver.name_len, name, ver.date_len, date, ver.desc_len,
> > +		desc);
> > +
> > +free_desc:
> > +	free(desc);
> > +free_date:
> > +	free(date);
> > +free_name:
> > +	free(name);
> > +
> > +	if (ret < 0)
> > +		return 0;
> > +
> > +	return 1;
> > +}
> > +
> > +static int drm_get_unique(struct tcb *tcp, const unsigned int code, long arg)
> > +{
> > +	struct drm_unique unique;
> > +	char *str;
> > +	int ret;
> > +
> > +	if (entering(tcp) || umove(tcp, arg, &unique))
> > +		return 0;
> > +
> > +	str = calloc(unique.unique_len + 1, 1);
> > +	if (!str)
> > +		return 0;
> > +	ret = umovestr(tcp, (long)unique.unique, unique.unique_len, str);
> > +
> 
> There is a check missing here

Oops, will fix.

> 
> > +	tprintf(", {unique_len=%lu, unique=%s}", unique.unique_len, str);
> > +
> > +	free(str);
> > +
> > +	if (ret < 0)
> > +		return 0;
> > +
> > +	return 1;
> > +}
> > +
> > +static int drm_get_magic(struct tcb *tcp, const unsigned int code, long arg)
> > +{
> > +	struct drm_auth auth;
> > +
> > +	if (entering(tcp) || umove(tcp, arg, &auth))
> > +		return 0;
> > +
> > +	tprintf(", {magic=%u}", auth.magic);
> > +
> > +	return 1;
> > +}
> > +
> > +static int drm_wait_vblank(struct tcb *tcp, const unsigned int code, long arg)
> > +{
> > +	union drm_wait_vblank vblank;
> > +
> > +	if (umove(tcp, arg, &vblank))
> > +		return 0;
> > +
> > +	if (entering(tcp)) {
> > +		tprintf(", {request={type=%u, sequence=%u, signal=%lu}",
> > +			vblank.request.type, vblank.request.sequence,
> > +			vblank.request.signal);
> > +	} else {
> > +		tprintf(", reply={type=%u, sequence=%u, tval_sec=%ld, tval_usec=%ld}}",
> > +			vblank.reply.type, vblank.reply.sequence,
> > +			vblank.reply.tval_sec, vblank.reply.tval_usec);
> > +	}
> > +
> > +	return 1;
> > +}
> > +
> > +static int drm_mode_get_resources(struct tcb *tcp, const unsigned int code, long arg)
> > +{
> > +	struct drm_mode_card_res res;
> > +
> > +	if (entering(tcp) || umove(tcp, arg, &res))
> > +		return 0;
> > +
> > +	tprintf(", {fb_id_ptr=%p, crtc_id_ptr=%p, connector_id_ptr=%p, "
> > +		"encoder_id_ptr=%p, count_fbs=%u, count_crtcs=%u, "
> > +		"count_connectors=%u, count_encoders=%u, min_width=%u, "
> > +		"max_width=%u, min_height=%u, max_height=%u}",
> > +		(void *)res.fb_id_ptr, (void *)res.crtc_id_ptr,
> > +		(void *)res.connector_id_ptr, (void *)res.encoder_id_ptr,
> > +		res.count_fbs, res.count_crtcs, res.count_connectors,
> > +		res.count_encoders, res.min_width, res.max_width,
> > +		res.min_height, res.max_height);
> > +
> > +	return 1;
> > +}
> > +
> > +static void drm_mode_print_modeinfo(struct drm_mode_modeinfo *info)
> > +{
> > +	tprintf("clock=%u, hdisplay=%hu, hsync_start=%hu, hsync_end=%hu, "
> > +		"htotal=%hu, hskew=%hu, vdisplay=%hu, vsync_start=%hu, "
> > +		"vsync_end=%hu, vtotal=%hu, vscan=%hu, vrefresh=%u, "
> > +		"flags=0x%x, type=%u, name=%s", info->clock, info->hdisplay,
> > +		info->hsync_start, info->hsync_end, info->htotal, info->hskew,
> > +		info->vdisplay, info->vsync_start, info->vsync_end,
> > +		info->vtotal, info->vscan, info->vrefresh, info->flags,
> > +		info->type, info->name);
> > +}
> > +
> > +static int drm_mode_get_crtc(struct tcb *tcp, const unsigned int code, long arg)
> > +{
> > +	struct drm_mode_crtc crtc;
> > +
> > +	if (entering(tcp) || umove(tcp, arg, &crtc))
> > +		return 0;
> > +
> > +	tprintf(", {set_connectors_ptr=%p, count_connectors=%u, crtc_id=%u, "
> > +		"fb_id=%u, x=%u, y=%u, gamma_size=%u, mode_valid=%u, mode={",
> > +		(void *)crtc.set_connectors_ptr, crtc.count_connectors,
> > +		crtc.crtc_id, crtc.fb_id, crtc.x, crtc.y, crtc.gamma_size,
> > +		crtc.mode_valid);
> > +
> > +	drm_mode_print_modeinfo(&crtc.mode);
> > +	tprintf("}}");
> > +
> > +	return 1;
> > +}
> > +
> > +static int drm_mode_set_crtc(struct tcb *tcp, const unsigned int code, long arg)
> > +{
> > +	struct drm_mode_crtc crtc;
> > +
> > +	if (entering(tcp) || umove(tcp, arg, &crtc))
> > +		return 0;
> > +
> > +	tprintf(", {set_connectors_ptr=%p, count_connectors=%u, crtc_id=%u, "
> > +		"fb_id=%u, x=%u, y=%u, gamma_size=%u, mode_valid=%u, mode={",
> > +		(void *)crtc.set_connectors_ptr, crtc.count_connectors,
> > +		crtc.crtc_id, crtc.fb_id, crtc.x, crtc.y, crtc.gamma_size,
> > +		crtc.mode_valid);
> > +
> > +	drm_mode_print_modeinfo(&crtc.mode);
> > +	tprintf("}}");
> > +
> > +	return 1;
> > +}
> > +
> > +static int drm_mode_cursor(struct tcb *tcp, const unsigned int code, long arg)
> > +{
> > +	struct drm_mode_cursor cursor;
> > +
> > +	if (entering(tcp) || umove(tcp, arg, &cursor))
> > +		return 0;
> > +
> > +	tprintf(", {flags=0x%x, crtc_id=%u, x=%d, y=%d, width=%u, height=%u, "
> > +		"handle=%u}", cursor.flags, cursor.crtc_id, cursor.x, cursor.y,
> > +		cursor.width, cursor.height, cursor.handle);
> > +
> > +	return 1;
> > +}
> > +
> > +static int drm_mode_cursor2(struct tcb *tcp, const unsigned int code, long arg)
> > +{
> > +	struct drm_mode_cursor2 cursor;
> > +
> > +	if (entering(tcp) || umove(tcp, arg, &cursor))
> > +		return 0;
> > +
> > +	tprintf(", {flags=0x%x, crtc_id=%u, x=%d, y=%d, width=%u, height=%u, "
> > +		"handle=%u, hot_x=%d, hot_y=%d}", cursor.flags, cursor.crtc_id,
> > +		cursor.x, cursor.y, cursor.width, cursor.height, cursor.handle,
> > +		cursor.hot_x, cursor.hot_y);
> > +
> > +	return 1;
> > +}
> > +
> > +static int drm_mode_get_gamma(struct tcb *tcp, const unsigned int code, long arg)
> > +{
> > +	struct drm_mode_crtc_lut lut;
> > +
> > +	if (entering(tcp) || umove(tcp, arg, &lut))
> > +		return 0;
> > +
> > +	/* We don't print the entire table, just the pointers */
> > +	tprintf(", {crtc_id=%u, gamma_size=%u, red=%p, green=%p, blue=%p}",
> > +		lut.crtc_id, lut.gamma_size, (void *)lut.red, (void *)lut.green,
> > +		(void *)lut.blue);
> > +
> > +	return 1;
> > +}
> > +
> > +
> > +static int drm_mode_set_gamma(struct tcb *tcp, const unsigned int code, long arg)
> > +{
> > +	struct drm_mode_crtc_lut lut;
> > +
> > +	if (entering(tcp) || umove(tcp, arg, &lut))
> > +		return 0;
> > +
> > +	/* We don't print the entire table, just the rgb pointers */
> > +	tprintf(", {crtc_id=%u, gamma_size=%u, red=%p, green=%p, blue=%p}",
> > +		lut.crtc_id, lut.gamma_size, (void *)lut.red, (void *)lut.green,
> > +		(void *)lut.blue);
> > +
> > +	return 1;
> > +}
> > +
> > +static int drm_mode_get_encoder(struct tcb *tcp, const unsigned int code, long arg)
> > +{
> > +	struct drm_mode_get_encoder enc;
> > +
> > +	if (entering(tcp) || umove(tcp, arg, &enc))
> > +		return 0;
> > +
> > +	/* TODO: Print name of encoder type */
> > +	tprintf(", {encoder_id=%u, encoder_type=%u, crtc_id=%u, "
> > +		"possible_crtcs=0x%x, possible_clones=0x%x}", enc.encoder_id,
> > +		enc.encoder_type, enc.crtc_id, enc.possible_crtcs,
> > +		enc.possible_clones);
> > +
> > +	return 1;
> > +}
> > +
> > +static int drm_mode_get_connector(struct tcb *tcp, const unsigned int code, long arg)
> > +{
> > +	struct drm_mode_get_connector con;
> > +
> > +	if (entering(tcp) || umove(tcp, arg, &con))
> > +		return 0;
> > +
> > +	/* We could be very verbose here but keep is simple for now */
> > +	tprintf(", {encoders_ptr=%p, modes_ptr=%p, props_ptr=%p, "
> > +		"prop_values_ptr=%p, count_modes=%u, count_props=%u, "
> > +		"count_encoders=%u, encoder_id=%u, connector_id=%u, "
> > +		"connector_type=%u, connector_type_id=%u, connection=%u, "
> > +		"mm_width=%u, mm_height=%u, subpixel=%u}",
> > +		(void *)con.encoders_ptr, (void *)con.modes_ptr,
> > +		(void *)con.props_ptr, (void *)con.prop_values_ptr,
> > +		con.count_modes, con.count_props, con.count_encoders,
> > +		con.encoder_id, con.connector_id, con.connector_type,
> > +		con.connector_type_id, con.connection, con.mm_width,
> > +		con.mm_height, con.subpixel);
> > +
> > +	return 1;
> > +}
> > +
> > +static int drm_mode_attachmode(struct tcb *tcp, const unsigned int code, long arg)
> > +{
> > +	struct drm_mode_mode_cmd cmd;
> > +
> > +	if (entering(tcp) || umove(tcp, arg, &cmd))
> > +		return 0;
> > +
> > +	tprintf(", {connector_id=%u, mode={", cmd.connector_id);
> > +	drm_mode_print_modeinfo(&cmd.mode);
> > +	tprintf("}");
> > +
> > +	return 1;
> > +}
> > +
> > +static int drm_mode_detachmode(struct tcb *tcp, const unsigned int code, long arg)
> > +{
> > +	struct drm_mode_mode_cmd cmd;
> > +
> > +	if (entering(tcp) || umove(tcp, arg, &cmd))
> > +		return 0;
> > +
> > +	tprintf(", {connector_id=%u, mode={", cmd.connector_id);
> > +	drm_mode_print_modeinfo(&cmd.mode);
> > +	tprintf("}");
> > +
> > +	return 1;
> > +}
> > +
> > +static int drm_mode_get_property(struct tcb *tcp, const unsigned int code, long arg)
> > +{
> > +	struct drm_mode_get_property prop;
> > +
> > +	if (entering(tcp) || umove(tcp, arg, &prop))
> > +		return 0;
> > +
> > +	tprintf(", {values_ptr=%p, enum_blob_ptr=%p, prop_id=%u, flags=0x%x, "
> > +		"name=%s, count_values=%u, count_enum_blobs=%u}",
> > +		(void *)prop.values_ptr, (void *)prop.enum_blob_ptr,
> > +		prop.prop_id, prop.flags, prop.name, prop.count_values,
> > +		prop.count_enum_blobs);
> > +
> > +	return 1;
> > +}
> > +
> > +static int drm_mode_set_property(struct tcb *tcp, const unsigned int code, long arg)
> > +{
> > +	struct drm_mode_connector_set_property prop;
> > +
> > +	if (entering(tcp) || umove(tcp, arg, &prop))
> > +		return 0;
> > +
> > +	tprintf(", {value=%Lu, prop_id=%u, connector_id=%u}", prop.value,
> > +		prop.prop_id, prop.connector_id);
> > +
> > +	return 1;
> > +}
> > +
> > +static int drm_mode_get_prop_blob(struct tcb *tcp, const unsigned int code, long arg)
> > +{
> > +	struct drm_mode_get_blob blob;
> > +
> > +	if (entering(tcp) || umove(tcp, arg, &blob))
> > +		return 0;
> > +
> > +	tprintf(", {blob_id=%u, length=%u, data=%p}", blob.blob_id, blob.length,
> > +		(void *)blob.data);
> > +
> > +	return 1;
> > +}
> > +
> > +static int drm_mode_add_fb(struct tcb *tcp, const unsigned int code, long arg)
> > +{
> > +	struct drm_mode_fb_cmd cmd;
> > +
> > +	if (entering(tcp) || umove(tcp, arg, &cmd))
> > +		return 0;
> > +
> > +	tprintf(", {fb_id=%u, width=%u, height=%u, pitch=%u, bpp=%u, depth=%u, "
> > +		"handle=%u}", cmd.fb_id, cmd.width, cmd.height, cmd.pitch,
> > +		cmd.bpp, cmd.depth, cmd.handle);
> > +
> > +	return 1;
> > +}
> > +
> > +static int drm_mode_get_fb(struct tcb *tcp, const unsigned int code, long arg)
> > +{
> > +	struct drm_mode_fb_cmd cmd;
> > +
> > +	if (entering(tcp) || umove(tcp, arg, &cmd))
> > +		return 0;
> > +
> > +	tprintf(", {fb_id=%u, width=%u, height=%u, pitch=%u, bpp=%u, depth=%u, "
> > +		"handle=%u}", cmd.fb_id, cmd.width, cmd.height, cmd.pitch,
> > +		cmd.bpp, cmd.depth, cmd.handle);
> > +
> > +	return 1;
> > +}
> > +
> > +static int drm_mode_rm_fb(struct tcb *tcp, const unsigned int code, long arg)
> > +{
> > +	unsigned int handle;
> > +
> > +	if (entering(tcp) || umove(tcp, arg, &handle))
> > +		return 0;
> > +
> > +	tprintf(", %u", handle);
> > +
> > +	return 1;
> > +}
> > +
> > +static int drm_mode_page_flip(struct tcb *tcp, const unsigned int code, long arg)
> > +{
> > +	struct drm_mode_crtc_page_flip flip;
> > +
> > +	if (entering(tcp) || umove(tcp, arg, &flip))
> > +		return 0;
> > +
> > +	tprintf(", {crtc_id=%u, fb_id=%u, flags=0x%x, user_data=0x%Lx}",
> > +		flip.crtc_id, flip.fb_id, flip.flags, flip.user_data);
> > +
> > +	return 1;
> > +}
> > +
> > +static int drm_mode_dirty_fb(struct tcb *tcp, const unsigned int code, long arg)
> > +{
> > +	struct drm_mode_fb_dirty_cmd cmd;
> > +
> > +	if (entering(tcp) || umove(tcp, arg, &cmd))
> > +		return 0;
> > +
> > +	tprintf(", {fb_id=%u, flags=0x%x, color=0x%x, num_clips=%u, "
> > +		"clips_ptr=%p}", cmd.fb_id, cmd.flags, cmd.color, cmd.num_clips,
> > +		(void *)cmd.clips_ptr);
> > +
> > +	return 1;
> > +}
> > +
> > +static int drm_mode_create_dumb(struct tcb *tcp, const unsigned int code, long arg)
> > +{
> > +	struct drm_mode_create_dumb dumb;
> > +
> > +	if (entering(tcp) || umove(tcp, arg, &dumb))
> > +		return 0;
> > +
> > +	tprintf(", {height=%u, width=%u, bpp=%u, flags=0x%x, handle=%u, "
> > +		"pitch=%u, size=%Lu}", dumb.height, dumb.width, dumb.bpp,
> > +		dumb.flags, dumb.handle, dumb.pitch, dumb.size);
> > +
> > +	return 1;
> > +}
> > +
> > +static int drm_mode_map_dumb(struct tcb *tcp, const unsigned int code, long arg)
> > +{
> > +	struct drm_mode_map_dumb dumb;
> > +
> > +	if (entering(tcp) || umove(tcp, arg, &dumb))
> > +		return 0;
> > +
> > +	tprintf(", {handle=%u, offset=%Lu}", dumb.handle, dumb.offset);
> > +
> > +	return 1;
> > +}
> > +
> > +static int drm_mode_destroy_dumb(struct tcb *tcp, const unsigned int code, long arg)
> > +{
> > +	struct drm_mode_destroy_dumb dumb;
> > +
> > +	if (entering(tcp) || umove(tcp, arg, &dumb))
> > +		return 0;
> > +
> > +	tprintf(", {handle=%u}", dumb.handle);
> > +
> > +	return 1;
> > +}
> > +
> > +static int drm_gem_close(struct tcb *tcp, const unsigned int code, long arg)
> > +{
> > +	struct drm_gem_close close;
> > +
> > +	if (entering(tcp) || umove(tcp, arg, &close))
> > +		return 0;
> > +
> > +	tprintf(", {handle=%u}", close.handle);
> > +
> > +	return 1;
> > +}
> > +
> >  int drm_ioctl(struct tcb *tcp, const unsigned int code, long arg)
> >  {
> >  	/* Check for device specific ioctls */
> > @@ -90,5 +552,62 @@ int drm_ioctl(struct tcb *tcp, const unsigned int code, long arg)
> >  			return drm_i915_ioctl(tcp, code, arg);
> >  	}
> >  
> > +	switch (code) {
> > +	case DRM_IOCTL_VERSION:
> > +		return drm_version(tcp, code, arg);
> > +	case DRM_IOCTL_GET_UNIQUE:
> > +		return drm_get_unique(tcp, code, arg);
> > +	case DRM_IOCTL_GET_MAGIC:
> > +		return drm_get_magic(tcp, code, arg);
> > +	case DRM_IOCTL_WAIT_VBLANK:
> > +		return drm_wait_vblank(tcp, code, arg);
> > +	case DRM_IOCTL_MODE_GETRESOURCES:
> > +		return drm_mode_get_resources(tcp, code, arg);
> > +	case DRM_IOCTL_MODE_GETCRTC:
> > +		return drm_mode_get_crtc(tcp, code, arg);
> > +	case DRM_IOCTL_MODE_SETCRTC:
> > +		return drm_mode_set_crtc(tcp, code, arg);
> > +	case DRM_IOCTL_MODE_CURSOR:
> > +		return drm_mode_cursor(tcp, code, arg);
> > +	case DRM_IOCTL_MODE_CURSOR2:
> > +		return drm_mode_cursor2(tcp, code, arg);
> > +	case DRM_IOCTL_MODE_GETGAMMA:
> > +		return drm_mode_get_gamma(tcp, code, arg);
> > +	case DRM_IOCTL_MODE_SETGAMMA:
> > +		return drm_mode_set_gamma(tcp, code, arg);
> > +	case DRM_IOCTL_MODE_GETENCODER:
> > +		return drm_mode_get_encoder(tcp, code, arg);
> > +	case DRM_IOCTL_MODE_GETCONNECTOR:
> > +		return drm_mode_get_connector(tcp, code, arg);
> > +	case DRM_IOCTL_MODE_ATTACHMODE:
> > +		return drm_mode_attachmode(tcp, code, arg);
> > +	case DRM_IOCTL_MODE_DETACHMODE:
> > +		return drm_mode_detachmode(tcp, code, arg);
> > +	case DRM_IOCTL_MODE_GETPROPERTY:
> > +		return drm_mode_get_property(tcp, code, arg);
> > +	case DRM_IOCTL_MODE_SETPROPERTY:
> > +		return drm_mode_set_property(tcp, code, arg);
> > +	case DRM_IOCTL_MODE_GETPROPBLOB:
> > +		return drm_mode_get_prop_blob(tcp, code, arg);
> > +	case DRM_IOCTL_MODE_GETFB:
> > +		return drm_mode_get_fb(tcp, code, arg);
> > +	case DRM_IOCTL_MODE_ADDFB:
> > +		return drm_mode_add_fb(tcp, code, arg);
> > +	case DRM_IOCTL_MODE_RMFB:
> > +		return drm_mode_rm_fb(tcp, code, arg);
> > +	case DRM_IOCTL_MODE_PAGE_FLIP:
> > +		return drm_mode_page_flip(tcp, code, arg);
> > +	case DRM_IOCTL_MODE_DIRTYFB:
> > +		return drm_mode_dirty_fb(tcp, code, arg);
> > +	case DRM_IOCTL_MODE_CREATE_DUMB:
> > +		return drm_mode_create_dumb(tcp, code, arg);
> > +	case DRM_IOCTL_MODE_MAP_DUMB:
> > +		return drm_mode_map_dumb(tcp, code, arg);
> > +	case DRM_IOCTL_MODE_DESTROY_DUMB:
> > +		return drm_mode_destroy_dumb(tcp, code, arg);
> > +	case DRM_IOCTL_GEM_CLOSE:
> > +		return drm_gem_close(tcp, code, arg);
> > +	}
> > +
> >  	return 0;
> >  }
> 
> 
> 
> -- 
> Gabriel Laskar
On Tue, 9 Jun 2015 16:29:31 +0200
Patrik Jakobsson <patrik.jakobsson@linux.intel.com> wrote:

> On Tue, Jun 09, 2015 at 03:51:08PM +0200, Gabriel Laskar wrote:
> > On Tue,  9 Jun 2015 13:26:44 +0200
> > Patrik Jakobsson <patrik.jakobsson@linux.intel.com> wrote:
> > 
> > > This patch adds many of the DRM and KMS ioctls. The rest can be added as
> > > needed.
> > > 
> > > Signed-off-by: Patrik Jakobsson <patrik.jakobsson@linux.intel.com>
> > > ---
> > >  drm.c | 519 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > >  1 file changed, 519 insertions(+)
> > > 
> > > diff --git a/drm.c b/drm.c
> > > index fa98fb7..e550c34 100644
> > > --- a/drm.c
> > > +++ b/drm.c
> > > @@ -82,6 +82,468 @@ int drm_is_driver(struct tcb *tcp, const char *name)
> > >  	return strcmp(name, drv) == 0;
> > >  }
> > >  
> > > +static int drm_version(struct tcb *tcp, const unsigned int code, long arg)
> > > +{
> > > +	struct drm_version ver;
> > > +	char *name, *date, *desc;
> > > +	int ret;
> > > +
> > > +	if (entering(tcp) || umove(tcp, arg, &ver))
> > > +		return 0;
> > > +
> > > +	name = calloc(ver.name_len + 1, 1);
> > 
> > We have some wrappers for that now, you can call xcalloc(), but it will
> > die if this does not work. Your version have the advantage of not kill
> > strace, and just not decode the argument.
> > 
> 
> If ok I'll keep it as calloc? As you say, dying here is not really neccessary.

Yeah, that was mostly me thinking out loud. Imho, I would keep the
calloc(), but I don't know what Dmitry will prefer. Maybe for
consistency, it should be better to have an xcalloc().
On Tue, Jun 09, 2015 at 01:26:44PM +0200, Patrik Jakobsson wrote:
[...]
> +static int drm_version(struct tcb *tcp, const unsigned int code, long arg)
> +{
> +	struct drm_version ver;
> +	char *name, *date, *desc;
> +	int ret;
> +
> +	if (entering(tcp) || umove(tcp, arg, &ver))
> +		return 0;
> +
> +	name = calloc(ver.name_len + 1, 1);
> +	if (!name)
> +		return 0;
> +	ret = umovestr(tcp, (long)ver.name, ver.name_len, name);
> +	if (ret < 0)
> +		goto free_name;

No need to allocate (arbitrary sized chunk of) memory just to fetch
a string that has to be printed.  There is a function called printstr()
to print such strings in a properly quoted form.
On Tue, Jun 09, 2015 at 04:38:40PM +0200, Gabriel Laskar wrote:
> On Tue, 9 Jun 2015 16:29:31 +0200
> Patrik Jakobsson <patrik.jakobsson@linux.intel.com> wrote:
> 
> > On Tue, Jun 09, 2015 at 03:51:08PM +0200, Gabriel Laskar wrote:
> > > On Tue,  9 Jun 2015 13:26:44 +0200
> > > Patrik Jakobsson <patrik.jakobsson@linux.intel.com> wrote:
> > > 
> > > > This patch adds many of the DRM and KMS ioctls. The rest can be added as
> > > > needed.
> > > > 
> > > > Signed-off-by: Patrik Jakobsson <patrik.jakobsson@linux.intel.com>
> > > > ---
> > > >  drm.c | 519 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > >  1 file changed, 519 insertions(+)
> > > > 
> > > > diff --git a/drm.c b/drm.c
> > > > index fa98fb7..e550c34 100644
> > > > --- a/drm.c
> > > > +++ b/drm.c
> > > > @@ -82,6 +82,468 @@ int drm_is_driver(struct tcb *tcp, const char *name)
> > > >  	return strcmp(name, drv) == 0;
> > > >  }
> > > >  
> > > > +static int drm_version(struct tcb *tcp, const unsigned int code, long arg)
> > > > +{
> > > > +	struct drm_version ver;
> > > > +	char *name, *date, *desc;
> > > > +	int ret;
> > > > +
> > > > +	if (entering(tcp) || umove(tcp, arg, &ver))
> > > > +		return 0;
> > > > +
> > > > +	name = calloc(ver.name_len + 1, 1);
> > > 
> > > We have some wrappers for that now, you can call xcalloc(), but it will
> > > die if this does not work. Your version have the advantage of not kill
> > > strace, and just not decode the argument.
> > > 
> > 
> > If ok I'll keep it as calloc? As you say, dying here is not really neccessary.
> 
> Yeah, that was mostly me thinking out loud. Imho, I would keep the
> calloc(), but I don't know what Dmitry will prefer. Maybe for
> consistency, it should be better to have an xcalloc().

The general rule is to call xcalloc() if die_out_of_memory() is the best
way to handle the OOM condition.  strace should neither attempt to
allocate arbitrary large chunks of memory specified by user input
nor die when such allocation requests fail.
On Wed, Jun 10, 2015 at 01:46:53AM +0300, Dmitry V. Levin wrote:
> On Tue, Jun 09, 2015 at 01:26:44PM +0200, Patrik Jakobsson wrote:
> [...]
> > +static int drm_version(struct tcb *tcp, const unsigned int code, long arg)
> > +{
> > +	struct drm_version ver;
> > +	char *name, *date, *desc;
> > +	int ret;
> > +
> > +	if (entering(tcp) || umove(tcp, arg, &ver))
> > +		return 0;
> > +
> > +	name = calloc(ver.name_len + 1, 1);
> > +	if (!name)
> > +		return 0;
> > +	ret = umovestr(tcp, (long)ver.name, ver.name_len, name);
> > +	if (ret < 0)
> > +		goto free_name;
> 
> No need to allocate (arbitrary sized chunk of) memory just to fetch
> a string that has to be printed.  There is a function called printstr()
> to print such strings in a properly quoted form.
> 

Yes, that's much nicer. Fixed in v2.

> 
> -- 
> ldv