// int ioctl(int fd, unsigned long request, ...);
PRE(sys_ioctl)
{
- UInt dir = _VKI_IOC_DIR(ARG2);
- UInt size = _VKI_IOC_SIZE(ARG2);
*flags |= SfMayBlock;
// @todo PJF presumably the presence of ARG3 depends on ARG2
PRINT("sys_ioctl ( %" FMT_REGWORD "u, 0x%" FMT_REGWORD "x, %#" FMT_REGWORD "x )",ARG1,ARG2,ARG3);
PRE_REG_READ3(int, "ioctl",
int, fd, unsigned long, request, unsigned long, arg);
- /* On FreeBSD, ALL ioctl's are IOR/IOW encoded. Just use the default decoder */
- if (SimHintiS(SimHint_lax_ioctls, VG_(clo_sim_hints))) {
- /*
- * Be very lax about ioctl handling; the only
- * assumption is that the size is correct. Doesn't
- * require the full buffer to be initialized when
- * writing. Without this, using some device
- * drivers with a large number of strange ioctl
- * commands becomes very tiresome.
- */
- } else if (dir == _VKI_IOC_NONE && size > 0) {
- static UWord unknown_ioctl[10];
- static Int moans = sizeof(unknown_ioctl) / sizeof(unknown_ioctl[0]);
- if (moans > 0 && !VG_(clo_xml)) {
- /* Check if have not already moaned for this request. */
- UInt i;
- for (i = 0; i < sizeof(unknown_ioctl)/sizeof(unknown_ioctl[0]); i++) {
- if (unknown_ioctl[i] == ARG2) {
- break;
- }
- if (unknown_ioctl[i] == 0) {
- unknown_ioctl[i] = ARG2;
- moans--;
- VG_(umsg)("Warning: noted but unhandled ioctl 0x%lx"
- " with no direction hints.\n", ARG2);
- VG_(umsg)(" This could cause spurious value errors to appear.\n");
- VG_(umsg)(" See README_MISSING_SYSCALL_OR_IOCTL for "
- "guidance on writing a proper wrapper.\n" );
- return;
- }
- }
- }
- } else {
- if ((dir & _VKI_IOC_WRITE) && size > 0) {
- PRE_MEM_READ( "ioctl(generic)", ARG3, size);
- }
- if ((dir & _VKI_IOC_READ) && size > 0) {
- PRE_MEM_WRITE( "ioctl(generic)", ARG3, size);
- }
+ switch (ARG2) {
+ case VKI_FIODGNAME: {
+ struct vki_fiodgname_arg* data = (struct vki_fiodgname_arg*)(Addr)ARG3;
+ PRE_FIELD_READ("ioctl(FIODGNAME).len", data->len);
+ PRE_FIELD_READ("ioctl(FIODGNAME).buf", data->buf);
+ PRE_MEM_WRITE("ioctl(FIODGNAME).buf", (Addr)data->buf, data->len);
+ break;
+ }
+ default:
+ ML_(PRE_unknown_ioctl)(tid, ARG2, ARG3);
+ break;
}
// The block below is from Ryan Stone
POST(sys_ioctl)
{
- UInt dir = _VKI_IOC_DIR(ARG2);
- UInt size = _VKI_IOC_SIZE(ARG2);
- vg_assert(SUCCESS);
- if (size > 0 && (dir & _VKI_IOC_READ)
- && RES == 0 && ARG3 != (Addr)NULL) {
- POST_MEM_WRITE(ARG3, size);
+ switch (ARG2) {
+ case VKI_FIODGNAME: {
+ struct vki_fiodgname_arg* data = (struct vki_fiodgname_arg*)(Addr)ARG3;
+ POST_MEM_WRITE((Addr)data->buf, data->len);
+ break;
+ }
+ default:
+ ML_(POST_unknown_ioctl)(tid, RES, ARG2, ARG3);
+ break;
}
#if 0
--- /dev/null
+/* Build with cc -lutil valgrind-ptsname.c */
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+
+#include <unistd.h>
+#include <termios.h>
+
+#include <libutil.h>
+
+/*
+ * ==18203== Syscall param ioctl(generic) points to uninitialised byte(s)
+ * ==18203== at 0x49AAE7A: ioctl (in /lib/libc.so.7)
+ * ==18203== by 0x490C116: fdevname_r (in /lib/libc.so.7)
+ * ==18203== by 0x49E1567: ptsname (in /lib/libc.so.7)
+ * ==18203== by 0x486B5E2: openpty (in /lib/libutil.so.9)
+ * ==18203== by 0x2016E6: main (in /tmp/a.out)
+ * ==18203== Address 0x1ffc000a74 is on thread 1's stack
+ * ==18203== in frame #1, created by fdevname_r (???:)
+ */
+
+#if 0
+/* Relevant bit from lib/libc/gen/fdevname.c */
+char *
+fdevname_r(int fd, char *buf, int len)
+{
+ struct fiodgname_arg fgn;
+
+ /*
+ * buf here points to a `static` buffer in ptsname.c, these are the only
+ * two members of fiodgname_arg.
+ */
+ fgn.buf = buf;
+ fgn.len = len;
+
+ if (_ioctl(fd, FIODGNAME, &fgn) == -1)
+ return (NULL);
+ return (buf);
+}
+#endif
+
+int
+main()
+{
+ int master, slave;
+
+ (void)openpty(&master, &slave, NULL, NULL, NULL);
+
+ return (0);
+}
+